Giter Club home page Giter Club logo

alonzo-testnet's Introduction

Alonzo-testnet

This is the repository for the Cardano Alonzo testnet rollout program.

Here you will find a set of exercises and support material to use on the Alonzo testnet. We will gradually add materials to this repository through the testnet phases to help you understand the testnet and make use of its features.

The planned syllabus is outlined below. Exercises will be deployed here and linked from this page as they are finalised.

Target Audience

The exercises are designed to help those who are unfamiliar with the Cardano node to write and submit Plutus scripts on the Alonzo testnets using the node CLI, so that they can develop their own simple DApps. Those who are already familiar with the node may choose to skip some of the earlier exercises, of course. Note that there will be no Cardano wallet or Plutus application backend support prior to Alonzo Purple, so functionality will be limited compared with the full Plutus experience.

Useful Resources

Documentation

Instructions for installing the Cardano node (pre-compiled, cabal, nix & Docker)

Plutus Scripts and other useful Resources

Plutus Explainer (Technical Terminology)

Plutus Tutorials

Cardano Documentation

Executable Nodes

Alonzo-1.30.1 node Linux binary

Alonzo-1.30.1 node MacOSX binary

Alonzo-1.30.1 node Windows binary

Alonzo-1.30.1 node Docker image

Network Configurations

Alonzo Purple and Cardano Testnet configuration files

Exercise 1: Getting Started

  1. Introduction to the Alonzo Testnet.
  2. Setting up a node to connect to the testnet.
  3. Obtaining test Ada.

Exercise 1 (Model Solutions)

Exercise 2: Hard Fork (Optional)

See an update proposal submitted to the chain and follow along as we go through the hard fork to the Alonzo era.

(Note that this may be a one-off event for each Testnet since we will need to start the network from scratch - the timing will be notified on the relevant Discord channel).

Exercise 2

Exercise 3: Addresses and Transactions

  1. Managing payment addresses.
  2. Building, signing and submitting transactions on chain.
  3. Submitting a transaction containing a pre-built Plutus script.

Exercise 3 (Model Solution)

Exercise 4: Compiling and Submitting Simple Plutus Scripts

  1. Compiling simple Plutus transactions.
  2. Submitting simple Plutus transactions.
  3. Calculating fees for Plutus transactions.
  4. Determining what effect your Plutus transactions have had on the blockchain.

Exercise 4 (Model Solution)

Exercise 5: Managing Native Tokens

  1. Minting native tokens using both Mary-era forging scripts
  2. Minting native tokens using Plutus forging scripts
  3. Redeeming/burning native tokens
  4. Minting non-fungible tokens
  5. Time-based scripts

Exercise 5

Exercise 6: DApps

  1. Building more substantial DApps
  2. Interacting with external events

Exercise 6

Exercise 7: Interacting with the Wallet (Coming Soon)

  1. The Cardano Wallet CLI
  2. Submitting transactions with Plutus Scripts from the wallet CLI
  3. Some simple DApps using the wallet CLI

Exercise 7

Feedback

We welcome feedback on any issues you have encountered:

Can I join in if I don't yet have an invite to the IOG-run Testnet?

Yes, if you have sufficient technical expertise, you are more than welcome to set up your own private cluster and to try the exercises! We have provided sample solutions to help if you encounter problems and our tutorials and other documentation are all available for you to use. As we open up the Alonzo testnets, we will then be able to integrate you with other community users, including providing access to the Testnet Discord channels. We recommend that you follow the Alonzo Purple exercises. You may find the following setup guides useful.

How to launch a testnet

Scripts for setting up a testnet

How to Make a Shelley blockchain from scratch

alonzo-testnet's People

Contributors

ahaxu avatar ak3n avatar bwbush avatar carloslopezdelara avatar catch-21 avatar chris-moreton avatar dino- avatar elviejo79 avatar igodlab avatar kevinhammond avatar luisantonioig avatar marcfontaine avatar nahern avatar nstankov-bg avatar olgahryniuk avatar savaki avatar stakelovelace avatar sviksha avatar tdiesler avatar teodanciu avatar wrlannen avatar zagita21 avatar zarej 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

alonzo-testnet's Issues

Add examples of automated test coverage to the solutions

In the pioneer program we were able to run our scripts in the playground and later learned about automated test coverage. It be nice to have something similar for the current exercises too. Especially now, where there is so little feedback (i.e. not even logging) from on-chain validation.

Alonzo-testnet current capabilities

Please excuse my ignorance, but I've searched and can't find the answers.
Why are Plutus example scripts provided on the "Plutus Playground"
(Starter, Vesting, Game, CrowdFunding) so different than
the examples found on the "Alonzo-testnet" (HellowWorld, AlwaysSuceeed, AlwaysFail)?
These "Alonzo-testnet" scripts are very basic and seem to only provide a script
address to accomodate cardano-cli commands.

I've tried compiling components of "CrowdFunding.hs"
on the "Alonzo-testnet" with no success.
The compiler fails on the statements like:
"import Plutus.Contract"

Is there a way to get a scripts like "CrowdFunding.hs"
on the "Alonzo-testnet"? If so, How?

Are we waiting for the complete implementation of the the
Plutus Application Backend(PAB) to have this capablity?

Will I be able to implment scripts like "CrowdFunding.hs"
after PAB is in?

Exercice 3. Lock funds forever in the plutus script

The order in which you specify the --tx-out flags when building the transaction matters a lot.

cardano-cli transaction build-raw --alonzo-era \
--tx-in aa1d18824746b58ce4ed242211f4e785d3b97f9fe6b255de27d5c3bb1056a55b#0 \
--tx-out $changeAddress+value \
--tx-out $plutusScriptAddress+value \
--tx-out-datum-hash $hash \
--invalid-hereafter $slotHeight \
--fee value \
--out-file tx.raw

will succeed. However, the same transaction as written below will end up locked forever without datum associated with the newly created script utxo.

cardano-cli transaction build-raw --alonzo-era \
--tx-out-datum-hash $hash \
--tx-in aa1d18824746b58ce4ed242211f4e785d3b97f9fe6b255de27d5c3bb1056a55b#0 \
--tx-out $changeAddress+value \
--tx-out $plutusScriptAddress+value \
--invalid-hereafter $slotHeight \
--fee value \
--out-file tx.raw

My understanding from this is that the datum will go to the closest --tx-out when building the transaction. Is this correct ?

mistake in Exercise3 Solution + some improvement.

In part one of the solution. When creating a --mary-era transaction, it uses the option --protocol-params-file which is not available for mary.

Also, is isn't clear where the pparams.json comes from. It'd be nice to have a line at the begining like:

cardano-cli query protocol-parameters --testnet-magic 5 > pparams.json

Plutus scripts are not stable under exports of Haskell file

Maybe this belongs to the plutus repo, yet I want to ask this question.

With the newest stand of things. Using this repo on tag "purple-2", on a nix-shell of the corresponding plutus repo on commit 8c83c4abe211b4bbcaca3cdf1b2c0e38d0eb683f. I compile the the "plutus-helloworld" script, I get the exact same script file as is on the resources/plutus-scripts/HelloWorldInt.plutus. No surprises here, but keep the reference.

cabal run plutus-helloworld && sha256sum result.plutus
Writing output to: result.plutus
"Log output"
[]
"Ex Budget"
ExBudget {exBudgetCPU = ExCPU 1191020, exBudgetMemory = ExMemory 4100}
4ccaa8c855dab22626b164f9ba7f6392b55618353d93c0578c12278636938054  result.plutus

A minimal change on HelloWorld.hs

@@ -10,6 +10,7 @@
 module Cardano.PlutusExample.HelloWorld
   ( helloWorldSerialised
   , helloWorldSBS
+  , helloWorld
   ) where

Notice it is only, exporting the valuidator script from the module. I have not change it. And only the serialized script is actually used later by the executable that writes it to file. This alone produces noticeable change under compilation.

cabal run plutus-helloworld && sha256sum result.plutus
Up to date
Writing output to: result.plutus
"Log output"
[]
"Ex Budget"
ExBudget {exBudgetCPU = ExCPU 1101701, exBudgetMemory = ExMemory 3800}
1aea5fec8b597c7bcb59e471b550bf10b309e7c57c110da6ecfd08da729b6ad3  result.plutus

Notice how now the execution budget is lower on both CPU and Memory. On top of that the file size itself has dropped from 271 bytes to 243.

What is going on here?
How can we trust contracts if this non-related change to the script or it dependencies completely alter it. Here I'm exporting from the Module.

Alonzo white sync error

I have started node
cardano-node run
--topology alonzo-white-topology.json
--database-path db
--socket-path node.socket
--port 3001
--config alonzo-white-config.json

it syncs successfully until
{
"epoch": 97,
"hash": "73162004bd3dbb779a7eaa74925fcd2b049c0c7327eaec0ce70ef3116cc9fd8c",
"slot": 691960,
"block": 34012,
"era": "Alonzo",
"syncProgress": "26.49"
}

Error:
[WS:cardano.node.ChainDB:Error:21] [2021-08-06 07:09:53.33 UTC] Invalid block ddd1200a49f0a24d1ba00ce7244eacfbd9422cfdbe6a16b461cdc5a081b3c130 at slot 691987: ExtValidationErrorLedger (HardForkLedgerErrorFromEra S (S (S (S (Z (WrapLedgerErr {unwrapLedgerErr = BBodyError (BlockTransitionError [TooManyExUnits (ExUnits {exUnitsMem = 15800, exUnitsSteps = 81620000}) (ExUnits {exUnitsMem = 1, exUnitsSteps = 1}),ShelleyInAlonzoPredFail (LedgersFailure (LedgerFailure (UtxowFailure (WrappedShelleyEraFailure (UtxoFailure (ExUnitsTooBigUTxO (ExUnits {exUnitsMem = 1, exUnitsSteps = 1}) (ExUnits {exUnitsMem = 15800, exUnitsSteps = 81620000}))))))),ShelleyInAlonzoPredFail (LedgersFailure (LedgerFailure (UtxowFailure (WrappedShelleyEraFailure (UtxoFailure (InsufficientCollateral (Coin 4000000) (Coin 102635800)))))))])}))))))

File Name too long

error: unable to create file byron/ledger/executable-spec/src/goblin_genomes/UPIVOTES_ApplyVotesFailure_UpivoteFailure_UPVOTEFailure_ADDVOTEFailure_AVSigDoesNotVerify.genome: Filename too long
error: unable to create file byron/ledger/executable-spec/src/goblin_genomes/UPIVOTES_ApplyVotesFailure_UpivoteFailure_UPVOTEFailure_ADDVOTEFailure_NoUpdateProposal.genome: Filename too long
HEAD is now at f827a4321 At PV6, translate time for Plutus correctly.

  • I resolved "file name too long" , but this error is coming.
  • Cardano Plutus Program, Testnet and its library are no so good as Ethereum and Solana.

Command failed: transaction build Error: The following scripts have execution failures: the script for transaction input 0 (in the order of the TxIds)

I follow this exercise resources/plutus-sources/plutus-helloworld/app/plutus-sum.hs

But, I got this error when trying to build unlock tnx to unlock fund from this script address

cardano-cli transaction build \
--alonzo-era \
--testnet-magic ${TESTNETMAGIC} \
--tx-in ${plutusutxotxin} \
--tx-in-script-file $script_path \
--tx-in-datum-value 6 \
--tx-in-redeemer-value 6 \
--tx-in-collateral ${txCollateral} \
--protocol-params-file pparams.json \
--change-address $(cat payment.addr) \
--out-file $unlock_tx

# output
Command failed: transaction build  Error: The following scripts have execution failures:
the script for transaction input 0 (in the order of the TxIds) failed with The Plutus script evaluation failed: An error has occurred:  User error:
The provided Plutus code called 'error'.

Built script file step

$ cabal run plutus-sum -- 6 ahaxu.sum.script

# output 
Up to date
sumDataSerialised: writing script name ahaxu.sum.script with datum 6
"Log output"
[]
"Ex Budget"
ExBudget {exBudgetCPU = ExCPU 23836562, exBudgetMemory = ExMemory 67604}
sumWrappedSerialised: writing script name ahaxu.sum.script with datum 6
"Log output"
[]
"Ex Budget"
ExBudget {exBudgetCPU = ExCPU 123673719, exBudgetMemory = ExMemory 313942}

Datum hash

export script_datum_hash=`cardano-cli transaction hash-script-data --script-data-value 6`

Here is the unlock cli

export txCollateral="bd13868bb8c7b2ab058d8055f492217d9a9e8e27e6d542d695b7b88fbbab524a#0"

# tx in which contains hash datum (6 as datum)
>>>
7a5baf3d4aa3c2a88e876c404cea4a930c3f2ba17c1fa59a0ccb2bdcd480b019     1        6000000 lovelace + TxOutDatumHash ScriptDataInAlonzoEra "bfa726c3c149165b108e6ff550cb1a1c4f0fdc2e9f26a9a16f48babe73b600ce"


export plutusutxotxin=7a5baf3d4aa3c2a88e876c404cea4a930c3f2ba17c1fa59a0ccb2bdcd480b019#1
export unlock_tx="ahaxu.sum.script.unlock.build"

cardano-cli transaction build \
--alonzo-era \
--testnet-magic ${TESTNETMAGIC} \
--tx-in ${plutusutxotxin} \
--tx-in-script-file $script_path \
--tx-in-datum-value 6 \
--tx-in-redeemer-value 6 \
--tx-in-collateral ${txCollateral} \
--protocol-params-file pparams.json \
--change-address $(cat payment.addr) \
--out-file $unlock_tx

Solution described in e3SampleSolution.md does not appear to work

Using cardano-node 1.27.0 and a private testnet, I tried to reproduce the Sample solutions for exercise 3. When attempting to follow the spend step described here,

cardano-cli transaction build-raw \
--alonzo-era \
--fee 801000000 \
--tx-in fb169b24bbf66e9a1f779ab87fef63321a616d64e69e5e0206a6b8e8af4c7802#0 \
--tx-in-script-file untyped-always-succeeds-txin.plutus \
--tx-in-datum-value $(cat random_datum.txt) \
--tx-in-redeemer-value $(cat random_datum.txt) \
--tx-in-execution-units "(200000000,200000000)" \
--tx-in-collateral 3064e641ab188863eb3ec7755d1c06ba4c95b3db5575a87998c95c7c8053430a#1 \
--tx-out addr_test1qzsdrv4juj5hmc3dqeq9wc7kpjwmu69zwjz9j29m3l88m26hdfyr7r54f67e7c9de70ld7gzfwmhqpudvkyyvkse2gmq0cvrdj+9199000000 \
--protocol-params-file pparams.json\
--out-file tx.raw

the transaction always fails resulting in the loss of collateral contained in3064e641ab188863eb3ec7755d1c06ba4c95b3db5575a87998c95c7c8053430a#1.

I've built a number of different private alonzo testnets using cardano-node/scripts/byron-to-alonzo/mkfiles.sh with a parameter of alonzo to generate the configuration. I've tried both with tx fees set to 0 and with tx fees set to what they are on mainnet and every attempt has failed in the same way. The uxto with the contract attached appears un-spendable.

ubuntu@ip-10-0-104-12:~/scripts$ cardano-cli query utxo --cardano-mode --testnet-magic 42 --whole-utxo
                           TxHash                                 TxIx        Amount
--------------------------------------------------------------------------------------
65ab3fd095876def5b9c772aec4821d6a183e7b685d1f6f0b993dba95405b801     0        5010000000 lovelace + TxOutDatumHashNone
b1db7cf043d1277fe891ffb74c2ae68bbc104e695f0cc9139d1688a70c1bd3e5     3        10000000000 lovelace + TxOutDatumHashNone
b1db7cf043d1277fe891ffb74c2ae68bbc104e695f0cc9139d1688a70c1bd3e5     4        10000000000 lovelace + TxOutDatumHashNone
b1db7cf043d1277fe891ffb74c2ae68bbc104e695f0cc9139d1688a70c1bd3e5     5        10000000000 lovelace + TxOutDatumHashNone
b1db7cf043d1277fe891ffb74c2ae68bbc104e695f0cc9139d1688a70c1bd3e5     6        10000000000 lovelace + TxOutDatumHashNone
b1db7cf043d1277fe891ffb74c2ae68bbc104e695f0cc9139d1688a70c1bd3e5     7        10000000000 lovelace + TxOutDatumHashNone
b1db7cf043d1277fe891ffb74c2ae68bbc104e695f0cc9139d1688a70c1bd3e5     8        10000000000 lovelace + TxOutDatumHashNone
b1db7cf043d1277fe891ffb74c2ae68bbc104e695f0cc9139d1688a70c1bd3e5     9        10000000000 lovelace + TxOutDatumHashNone
b1db7cf043d1277fe891ffb74c2ae68bbc104e695f0cc9139d1688a70c1bd3e5    10        900000000000 lovelace + TxOutDatumHashNone
b6a6f3a8adb85f237230441fdcf472f557e384a468e525e900c83ae3cc3109b1     0        5000000000 lovelace + TxOutDatumHash ScriptDataInAlonzoEra "417069468791fe6c810d1a1ebe4ca78cf6c6983de997f86ec2470dc15bbe9d0f"
f640231da6ed61c2867f802c85584974967f2490da6b8e15c7614a819f239016     0        5010000000 lovelace + TxOutDatumHashNone

Any suggestions would be greatly appreciated.

Show working code for emulator trace and playground usage

I tried to port some trivial emulator trace usage like Free.hs from the plutus-pioneer-program to this project, which currently fails (for me) with a plutus compile error related to plutus-contract.

Currently, I can neither get the emulator nor the playground working and there isn't sufficient debug logging during script validation either. Recent versions of the pioneer program don't seem to align with the 1.29.0 testnet, so I can't reliably copy from there.

Could we please have some document usage and examples for the emulator and perhaps even the playground in this project? Perhaps start simple with Free.hs - I guess that would already unblock further progress for me.

Ideally, this would find its way into plutus-example as well.

Depends: PR #65
Related to: IntersectMBO/plutus#3910

Alonzo blue sync error

I have started node
cardano-node run
--topology alonzo-blue-topology.json
--database-path db
--socket-path node.socket
--port 3001
--config alonzo-blue-config.json \

it syncs successfully until
{
"epoch": 234,
"hash": "7a1490c9b70bee0a81274393f579114b9e32ffc2358df82762a972af6c075be5",
"slot": 1678283,
"block": 81983,
"era": "Alonzo",
"syncProgress": "27.68"
}

Error:
[WS:cardano.node.DnsSubscription:Error:318] [2021-08-06 07:17:15.12 UTC] Domain: "relays.alonzo-blue.dev.cardano.org" Application Exception: 50.18.74.57:3001 DecoderFailure (BlockFetchHardForkBlock (': * ByronBlock (': * (ShelleyBlock (ShelleyEra StandardCrypto)) (': * (ShelleyBlock (ShelleyMAEra 'Allegra StandardCrypto)) (': * (ShelleyBlock (ShelleyMAEra 'Mary StandardCrypto)) (': * (ShelleyBlock (AlonzoEra StandardCrypto)) ('[] *))))))) ServerAgency TokStreaming) (DeserialiseFailure 1404 "expected tag")

Error: Caused by: [ (builtin unBData) (con data #06) ] when trying to convert Integer to `PlutusTx.Builtins.BuiltinString`

From this line https://github.com/input-output-hk/Alonzo-testnet/blob/main/resources/plutus-sources/plutus-helloworld/src/Cardano/PlutusExample/Sum.hs#L45
I try to add trace log when isGoodSum failed

isGoodSum :: Integer -> Integer -> Bool
isGoodSum n s =
    traceIfFalse log checker
    where
        checker = smartSum n == s
        log = "not a good sum "

It works well with the code above, how ever I want the log message more detail like not a good sum: s=6 with n=6

I tried to convert Integer to BuiltinString and append together

-- ...
import qualified PlutusTx.Builtins as BI

toBS :: Integer -> BI.BuiltinString
toBS = BI.decodeUtf8 . BI.unsafeDataAsB . BI.mkI

{-# INLINABLE isGoodSum #-}
isGoodSum :: Integer -> Integer -> Bool
isGoodSum n s =
    traceIfFalse log checker
    where
        checker = smartSum n == s
        log =
            "not a good sum: s="
            `BI.appendString`
            toBS s
            `BI.appendString`
            " with n="
            `BI.appendString` 
            toBS n

The plutus script can be built as cabal run plutus-sum -- 6 ahaxu.sum.script, and I also can lock some ADA at the script address corresponded to this ahaxu.sum.script script.
But, There is error when I try to unlock the fund

cardano-cli transaction build \
--alonzo-era \
--testnet-magic ${TESTNETMAGIC} \
--tx-in ${plutusutxotxin} \
--tx-in-script-file $script_path \
--tx-in-datum-value 6 \
--tx-in-redeemer-value 6 \
--tx-in-collateral ${txCollateral} \
--protocol-params-file pparams.json \
--change-address $(cat payment.addr) \
--out-file $unlock_tx

Command failed: transaction build  Error: The following scripts have execution failures:
the script for transaction input 0 (in the order of the TxIds) failed with: 
The Plutus script evaluation failed: An error has occurred:  User error:
The provided Plutus code called 'error'.
Caused by: [ (builtin unBData) (con data #06) ]
Script debugging logs: 

I think there is error with the toBS function when converting data. Any idea, how to fix this? Thanks in advance!

[edited]
I tried BI.decodeUtf8 $ BI.unsafeDataAsB $ BI.mkI 10 with ghci

> BI.decodeUtf8 $ BI.unsafeDataAsB $ BI.mkI 10
"*** Exception: not a B
CallStack (from HasCallStack):
  error, called at src/PlutusTx/Builtins/Internal.hs:377:41 in plutus-tx-0.1.0.0-ff99f38a14c6d70a1f775c2ecd6d9d27491a3e2396f0c6b90d2a740967fd7468:PlutusTx.Builtins.Internal

so, the error related to this https://github.com/input-output-hk/plutus/blob/master/plutus-tx/src/PlutusTx/Builtins/Internal.hs#L382-L384

Exercise 3 feedback/questions

I completed exercise 3 but some things weren't clear to me that I think could be made clearer:

  • Why must the random number be passed as both --tx-in-datum-value and --tx-in-redeemer-value?
  • How do execution units relate to the fee passed with --fee? Should they match? Should --fee be execution units + some additional fee for the transaction?
  • Why are there two values in --execution-units?
  • Why is the script called "always succeed" and described as always succeeding if the random number must be known to withdraw funds?
  • Where is the source code for the script?

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.