Giter Club home page Giter Club logo

docs's Introduction

CosmWasm

CircleCI

WebAssembly Smart Contracts for the Cosmos SDK.

Packages

The following packages are maintained here:

Crate Usage Download Docs Coverage
cosmwasm-crypto Internal only cosmwasm-crypto on crates.io Docs Coverage
cosmwasm-derive Internal only cosmwasm-derive on crates.io Docs Coverage
cosmwasm-schema Contract development cosmwasm-schema on crates.io Docs Coverage
cosmwasm-core Internal only cosmwasm-core on crates.io Docs Coverage
cosmwasm-std Contract development cosmwasm-std on crates.io Docs Coverage
cosmwasm-vm Host environments cosmwasm-vm on crates.io Docs Coverage
cosmwasm-check Contract development cosmwasm-check on crates.io cosmwasm-check -h N/A

cosmwasm-storage is no longer maintained and has been dropped in favor of cw-storage-plus.

Overview

To get that contract to interact with a system needs many moving parts. To get oriented, here is a list of the various components of the CosmWasm ecosystem:

Standard library:

This code is compiled into Wasm bytecode as part of the smart contract.

  • cosmwasm-std - A crate in this workspace. Provides the bindings and all imports needed to build a smart contract.
  • cw-storage-plus - A crate which provides convenience helpers for interacting with storage with powerful types supporting composite primary keys, secondary indexes, automatic snapshotting, and more. This is used in most modern contracts.

Building contracts:

  • cosmwasm-template - A starter-pack to get you quickly building your custom contract compatible with the cosmwasm system.

  • cosmwasm-plus - Some sample contracts for use and inspiration. These provide usable primitives and interfaces for many use cases, such as fungible tokens, NFTs, multisigs, governance votes, staking derivatives, and more. Look in packages for docs on the various standard interfaces, and contracts for the implementations. Please submit your contract or interface via PR.

  • rust-optimizer - A docker image and scripts to take your Rust code and produce the smallest possible Wasm output, deterministically. This is designed both for preparing contracts for deployment as well as validating that a given deployed contract is based on some given source code, allowing a similar contract verification algorithm as Etherscan.

    Building locally instead of using the docker image can leak some information about the directory structure of your system and makes the build non-reproducible.

  • serde-json-wasm - A custom json library, forked from serde-json-core. This provides an interface similar to serde-json, but without any floating-point instructions (non-deterministic) and producing builds around 40% of the code size.

Executing contracts:

  • cosmwasm-vm - A crate in this workspace. Uses the wasmer engine to execute a given smart contract. Also contains code for gas metering, storing, and caching wasm artifacts.
  • wasmvm - High-level go bindings to all the power inside cosmwasm-vm. Easily allows you to upload, instantiate and execute contracts, making use of all the optimizations and caching available inside cosmwasm-vm.
  • wasmd - A basic Cosmos SDK app to host WebAssembly smart contracts. It can be run as is, or you can import the x/wasm module from it and use it in your blockchain. It is designed to be imported and customized for other blockchains, rather than forked.
  • cosmwasm-check - A CLI tool and a crate in this workspace. Used to verify a Wasm binary is a CosmWasm smart contract suitable for uploading to a blockchain with a given set of capabilities.

Creating a Smart Contract

You can see some examples of contracts under the contracts directory, which you can look at. They are simple and self-contained, primarily meant for testing purposes, but that also makes them easier to understand.

You can also look at cw-plus for examples and inspiration on more production-like contracts and also how we call one contract from another. If you are working on DeFi or Tokens, please look at the cw20, cw721 and/or cw1155 packages that define standard interfaces as analogues to some popular ERC designs. (cw20 is also inspired by erc777).

If you want to get started building your own contract, the simplest way is to go to the cosmwasm-template repository and follow the instructions. This will give you a simple contract along with tests, and a properly configured build environment. From there you can edit the code to add your desired logic and publish it as an independent repo.

We also recommend you review our documentation site which contains a few tutorials to guide you in building your first contracts. You can find past recordings of hackathon / conference workshops and presentations on our YouTube channel, or join our Discord server to ask for help.

Minimum Supported Rust Version (MSRV)

See Minimum Supported Rust Version (MSRV).

API entry points

WebAssembly contracts are basically black boxes. They have no default entry points, and no access to the outside world by default. To make them useful, we need to add a few elements.

If you haven't worked with WebAssembly before, please read an overview on how to create imports and exports in general.

Exports

The required exports provided by the cosmwasm smart contract are:

// signal for 1.0 compatibility
extern "C" fn interface_version_8() -> () {}

// copy memory to/from host, so we can pass in/out Vec<u8>
extern "C" fn allocate(size: usize) -> u32;
extern "C" fn deallocate(pointer: u32);

// creates an initial state of a contract with a configuration send in the argument msg_ptr
extern "C" fn instantiate(env_ptr: u32, info_ptr: u32, msg_ptr: u32) -> u32;

Contracts may also implement one or more of the following to extend their functionality:

// modify the state of the contract
extern "C" fn execute(env_ptr: u32, info_ptr: u32, msg_ptr: u32) -> u32;

// query the state of the contract
extern "C" fn query(env_ptr: u32, msg_ptr: u32) -> u32;

// in-place contract migrations
extern "C" fn migrate(env_ptr: u32, msg_ptr: u32) -> u32;

// support submessage callbacks
extern "C" fn reply(env_ptr: u32, msg_ptr: u32) -> u32;

// expose privileged entry points to Cosmos SDK modules, not external accounts
extern "C" fn sudo(env_ptr: u32, msg_ptr: u32) -> u32;

// and to write an IBC application as a contract, implement these:
extern "C" fn ibc_channel_open(env_ptr: u32, msg_ptr: u32) -> u32;
extern "C" fn ibc_channel_connect(env_ptr: u32, msg_ptr: u32) -> u32;
extern "C" fn ibc_channel_close(env_ptr: u32, msg_ptr: u32) -> u32;
extern "C" fn ibc_packet_receive(env_ptr: u32, msg_ptr: u32) -> u32;
extern "C" fn ibc_packet_ack(env_ptr: u32, msg_ptr: u32) -> u32;
extern "C" fn ibc_packet_timeout(env_ptr: u32, msg_ptr: u32) -> u32;

allocate/deallocate allow the host to manage data within the Wasm VM. If you're using Rust, you can implement them by simply re-exporting them from cosmwasm::exports. instantiate, execute and query must be defined by your contract.

Imports

The imports provided to give the contract access to the environment are:

// This interface will compile into required Wasm imports.
// A complete documentation of those functions is available in the VM that provides them:
// https://github.com/CosmWasm/cosmwasm/blob/v1.0.0-beta/packages/vm/src/instance.rs#L89-L206
extern "C" {
    fn db_read(key: u32) -> u32;
    fn db_write(key: u32, value: u32);
    fn db_remove(key: u32);

    // scan creates an iterator, which can be read by consecutive next() calls
    #[cfg(feature = "iterator")]
    fn db_scan(start_ptr: u32, end_ptr: u32, order: i32) -> u32;
    #[cfg(feature = "iterator")]
    fn db_next(iterator_id: u32) -> u32;

    fn addr_validate(source_ptr: u32) -> u32;
    fn addr_canonicalize(source_ptr: u32, destination_ptr: u32) -> u32;
    fn addr_humanize(source_ptr: u32, destination_ptr: u32) -> u32;

    /// Verifies message hashes against a signature with a public key, using the
    /// secp256k1 ECDSA parametrization.
    /// Returns 0 on verification success, 1 on verification failure, and values
    /// greater than 1 in case of error.
    fn secp256k1_verify(message_hash_ptr: u32, signature_ptr: u32, public_key_ptr: u32) -> u32;

    fn secp256k1_recover_pubkey(
        message_hash_ptr: u32,
        signature_ptr: u32,
        recovery_param: u32,
    ) -> u64;

    /// Verifies message hashes against a signature with a public key, using the
    /// secp256r1 ECDSA parametrization.
    /// Returns 0 on verification success, 1 on verification failure, and values
    /// greater than 1 in case of error.
    fn secp256r1_verify(message_hash_ptr: u32, signature_ptr: u32, public_key_ptr: u32) -> u32;

    fn secp256r1_recover_pubkey(
      message_hash_ptr: u32,
      signature_ptr: u32,
      recovery_param: u32,
    ) -> u64;

    /// Verifies a message against a signature with a public key, using the
    /// ed25519 EdDSA scheme.
    /// Returns 0 on verification success, 1 on verification failure, and values
    /// greater than 1 in case of error.
    fn ed25519_verify(message_ptr: u32, signature_ptr: u32, public_key_ptr: u32) -> u32;

    /// Verifies a batch of messages against a batch of signatures and public keys, using the
    /// ed25519 EdDSA scheme.
    /// Returns 0 on verification success, 1 on verification failure, and values
    /// greater than 1 in case of error.
    fn ed25519_batch_verify(messages_ptr: u32, signatures_ptr: u32, public_keys_ptr: u32) -> u32;

    /// Writes a debug message (UFT-8 encoded) to the host for debugging purposes.
    /// The host is free to log or process this in any way it considers appropriate.
    /// In production environments it is expected that those messages are discarded.
    fn debug(source_ptr: u32);

    /// Executes a query on the chain (import). Not to be confused with the
    /// query export, which queries the state of the contract.
    fn query_chain(request: u32) -> u32;
}

(from imports.rs)

You could actually implement a WebAssembly module in any language, and as long as you implement these functions, it will be interoperable, given the JSON data passed around is in the proper format.

Note that these u32 pointers refer to Region instances, containing the offset and length of some Wasm memory, to allow for safe access between the caller and the contract:

/// Describes some data allocated in Wasm's linear memory.
/// A pointer to an instance of this can be returned over FFI boundaries.
///
/// This struct is crate internal since the cosmwasm-vm defines the same type independently.
#[repr(C)]
pub struct Region {
    /// The beginning of the region expressed as bytes from the beginning of the linear memory
    pub offset: u32,
    /// The number of bytes available in this region
    pub capacity: u32,
    /// The number of bytes used in this region
    pub length: u32,
}

(from memory.rs)

Implementing the Smart Contract

If you followed the instructions above, you should have a runable smart contract. You may notice that all of the Wasm exports are taken care of by lib.rs, which you shouldn't need to modify. What you need to do is simply look in contract.rs and implement instantiate and execute functions, defining your custom InstantiateMsg and ExecuteMsg structs for parsing your custom message types (as json):

#[entry_point]
pub fn instantiate(
  deps: DepsMut,
  env: Env,
  info: MessageInfo,
  msg: InstantiateMsg,
) -> Result<Response, ContractError> {}

#[entry_point]
pub fn execute(
  deps: DepsMut,
  env: Env,
  info: MessageInfo,
  msg: ExecuteMsg,
) -> Result<Response, ContractError> {}

#[entry_point]
pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result<Binary, ContractError> {}

#[entry_point]
pub fn migrate(deps: DepsMut, env: Env, msg: MigrateMsg) -> Result<Response, ContractError> {}

The low-level db_read and db_write imports are nicely wrapped for you by a Storage implementation (which can be swapped out between real Wasm code and test code). This gives you a simple way to read and write data to a custom sub-database that this contract can safely write to as it wants. It's up to you to determine which data you want to store here:

/// Storage provides read and write access to a persistent storage.
/// If you only want to provide read access, provide `&Storage`
pub trait Storage {
    /// Returns None when key does not exist.
    /// Returns Some(Vec<u8>) when key exists.
    ///
    /// Note: Support for differentiating between a non-existent key and a key with empty value
    /// is not great yet and might not be possible in all backends. But we're trying to get there.
    fn get(&self, key: &[u8]) -> Option<Vec<u8>>;

    #[cfg(feature = "iterator")]
    /// Allows iteration over a set of key/value pairs, either forwards or backwards.
    ///
    /// The bound `start` is inclusive and `end` is exclusive.
    ///
    /// If `start` is lexicographically greater than or equal to `end`, an empty range is described, no matter of the order.
    fn range<'a>(
        &'a self,
        start: Option<&[u8]>,
        end: Option<&[u8]>,
        order: Order,
    ) -> Box<dyn Iterator<Item = Record> + 'a>;

    fn set(&mut self, key: &[u8], value: &[u8]);

    /// Removes a database entry at `key`.
    ///
    /// The current interface does not allow to differentiate between a key that existed
    /// before and one that didn't exist. See https://github.com/CosmWasm/cosmwasm/issues/290
    fn remove(&mut self, key: &[u8]);
}

(from traits.rs)

Testing the Smart Contract (rust)

For quick unit tests and useful error messages, it is often helpful to compile the code using native build system and then test all code except for the extern "C" functions (which should just be small wrappers around the real logic).

If you have non-trivial logic in the contract, please write tests using rust's standard tooling. If you run cargo test, it will compile into native code using the debug profile, and you get the normal test environment you know and love. Notably, you can add plenty of requirements to [dev-dependencies] in Cargo.toml and they will be available for your testing joy. As long as they are only used in #[cfg(test)] blocks, they will never make it into the (release) Wasm builds and have no overhead on the production artifact.

Note that for tests, you can use the MockStorage implementation which gives a generic in-memory hashtable in order to quickly test your logic. You can see a simple example of how to write a test in our sample contract.

Testing the Smart Contract (wasm)

You may also want to ensure the compiled contract interacts with the environment properly. To do so, you will want to create a canonical release build of the <contract>.wasm file and then write tests with the same VM tooling we will use in production. This is a bit more complicated but we added some tools to help in cosmwasm-vm which can be added as a dev-dependency.

You will need to first compile the contract using cargo wasm, then load this file in the integration tests. Take a look at the sample tests to see how to do this... it is often quite easy to port a unit test to an integration test.

Production Builds

The above build process (cargo wasm) works well to produce wasm output for testing. However, it is quite large, around 1.5 MB likely, and not suitable for posting to the blockchain. Furthermore, it is very helpful if we have reproducible build step so others can prove the on-chain wasm code was generated from the published rust code.

For that, we have a separate repo, rust-optimizer that provides a docker image for building. For more info, look at rust-optimizer README, but the quickstart guide is:

docker run --rm -v "$(pwd)":/code \
  --mount type=volume,source="$(basename "$(pwd)")_cache",target=/target \
  --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \
  cosmwasm/optimizer:0.15.0

It will output a highly size-optimized build as contract.wasm in $CODE. With our example contract, the size went down to 126kB (from 1.6MB from cargo wasm). If we didn't use serde-json, this would be much smaller still...

Benchmarking

You may want to compare how long the contract takes to run inside the Wasm VM compared to in native rust code, especially for computationally intensive code, like hashing or signature verification.

TODO add instructions

Developing

The ultimate auto-updating guide to building this project is the CI configuration in .circleci/config.yml.

For manually building this repo locally during development, here are a few commands. They assume you use a stable Rust version by default and have a nightly toolchain installed as well.

Workspace

# Compile and lint
./devtools/check_workspace.sh

# Run tests
./devtools/test_workspace.sh

Contracts

Step Description Command
1 fast checks, rebuilds lock files ./devtools/check_contracts_fast.sh
2 medium fast checks ./devtools/check_contracts_medium.sh
3 slower checks ./devtools/check_contracts_full.sh

docs's People

Contributors

0xfable avatar abefernan avatar aumetra avatar chipshort avatar dariuszdepta avatar hashedone avatar jawoznia avatar pinosu avatar uint avatar webmaster128 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

docs's Issues

`cw-storage-plus`: Have examples use Sylvia?

Currently, the examples in cw-storage-plus docs create storage containers ad-hoc like this:

let mut map = Map::new("foo");

This isn't great since we want to encourage better practices for RL scenarios. Maybe we can figure out something better?

Update MultiTest links

Since the MultiTest docs are not yet ready, most of the links in the Sylvia to the MultiTest are not internal, but leads to docs.rs.

Once the MultiTest docs are done we should update links f.e. of App to lead to proper documentation section about it.

Entrypoints - Additional Info

I think the entrypoints page would be a good place to explain what DepsMut, Env and MessageInfo are for. We don't need to go into a lot of detail, but a short sentence and a docs.rs link for each would be nice.

The docs should also explain that the InstantiateMsg / ExecuteMsg / ... are defined by the user and how to do that (e.g. explain #[cw_serde]).
A similar explanation for the returned error type would be good. Right now all of the examples use StdResult, but you're totally free to use any type that implements ToString.

IBC: Enable tests for 2.1 specific features

The code examples for 2.1-specific IBC features (callbacks + async acks) are currently not tested with the docs-test-gen.
I have added TODO comments in all the places where these should be enabled once 2.1 is released.

CosmWasm core: Documentation outline

Tracking issue for a basic outline of the documentation:

  • Installation
  • Entrypoints
    • Overview
    • Instantiate (#13)
    • Execute (#13)
    • Query (#13)
    • Migrate (#13)
    • Sudo (#13)
  • Architecture
    • Actor model (#24)
    • Events and attributes
    • Data
  • Standard library
    • Overview (#26)
    • Math
      • Overview (#33)
      • Decimals
        • Overview (#33)
      • Integers
        • Overview (#33)
    • Cryptography
      • Overview (#26)
      • P256
        • Overview (#26)
        • Key recovery example
        • Verification example
      • K256 (#26)
      • Ed25519 (#26)
      • BLS12-381
        • Overview (#26)
        • Hash-to-curve example
        • Point aggregation example
        • Pairing equality example
  • Advanced
    • Overview (#35)
    • Measuring time (#35)
  • Specifications
    • Overview
    • instantiate2 algorithm (see #30)

Document Instantiate2 algorithm

For CosmWasm/cosmwasm#2155 and and other cases we need a spec for the Instantiate2 address generation algorithm. We already have 3 implementartions (Go, Rust and TypeScript) but no central definition how the addresses are calculated.

IBC: Add storage to "Channel lifecycle" examples

Currently the channel lifecycle is not guarded in any way in the examples. There is a description in the text that you should guard it and some different ways, but it would certainly be better to have it in the examples. Let's face it, people will end up just copying code out of the docs to get stuff to work.

I think it makes sense to save the channel info in storage in ibc_channel_connect and also check it in ibc_channel_open to avoid bad actors overwriting the existing channel.

Feedback for IBC docs

Reading through the IBC docs, just noting some things for consideration. Not making a PR at this stage since some of this is definitely nitpicky/subjective, maybe even wrong. Happy to discuss this and decide if/how any of it should be addressed, and then close the issue out - perhaps with no changes at all.

Landing page

  • "You can use the IBC protocol as a building block to create your own custom protocols on top of it" - I think this can be a much stronger marketing pitch. This page should emphasize the power of using contracts via IBC. Most people think of IBC as only ICS-20, and for good reason: developing anything beyond that, without CosmWasm, requires a ridiculously heavy burden of chain-level-code across multiple chains. Cosmwasm isn't just the best solution for developing IBC apps, it's arguably the only reasonable solution for IBC apps

  • "IBC is a protocol that allows different blockchains to communicate with each other. It is a standard that defines how blockchains can send and receive messages to each other." - a bit redundant, communication means sending/receiving messages here, I think one of these sentences can be deleted

Getting Started page

  • "To get started, you need to enable the stargate feature of the cosmwasm-std crate" - this is confusing... what is stargate? Why isn't this feature called "ibc"? I think explaining this a bit more is worthwhile

  • There is still a "TODO" in Notes section

Basic Concepts page

  • High-level, I think it should link to the IBC docs up front, and mention the need to run a relayer, then the rest of the doc can speak about only the relationship to CosmWasm. The rest of my notes will assume that is changed.

  • "Port: An identifier that corresponds to a single module on a chain. One module can have multiple ports. Each contract has its own unique port." - I would de-emphasize the role of cosmos modules here... suggested change: "Port: every instantiation of an ibc-enabled contract creates a unique port, similarly to how it creates a unique address"

  • "Channel: A connection between two ports on different blockchains that allows them to send packets to each other. Each port can have multiple channels." - I would de-emphasize the relationship to ports, but rather to contracts. suggested change: "Channel: to send messages between contracts on different chains, you must first create a channel over their assigned ports. Multiple channels are allowed and they can be distinguished by 'version'"

  • "Relayer": delete (mention briefly up top)

  • "Packet: A piece of binary data that is sent through a channel. It can time out if it is not delivered within a certain time frame." - small suggestion: "A piece of binary data that is sent through a channel from contract to contract" (i.e. to emphasize that it's not a client->chain thing like other messages)

Using Existing Protocols page

  • I think this should be split into ICS-20 and Custom Contract subpages, where the intro page just explains the difference between on-chain protocols and custom contract protocols, and the custom contract walks through calling the Nois (or other) example

  • I also think it should come after "Build your own protocol". Even though ICS-20 is the common case, it's easy to find, and hopefully someone will be coming to these docs because they want to build contracts that do more than ICS-20

Build Your Own Protocol page

  • As mentioned above, I think this should come before the "use existing protocols" page. Not because of which is easier to grok, but rather from the perspective of "developers writing contracts", hopefully they are more interested in writing distributed apps that require custom logic, and that's why they're on the page

  • I haven't fully groked the "advanced example"... skimmed through it, but cool stuff

Overall the docs as they are are fantastic, the above are just some small suggestions - nothing at all crucial!

Generic contracts and interfaces in sylvia

We need a very solid explanation of generic Sylvia stuff, especially in the context of chain-agnostic contracts (those should be using generic custom msg/query). The reasoning behind that should be explained, and simple way of implementing this pattern should be presented.

Make sure all code examples containing an entry point use library feature

Follow-up to #57 (comment)

We should probably enforce the convention of having a library feature in contracts by putting them explicitly into every code sample and reinforcing that this is how it should be done.

Also, as @chipshort mentioned, people will probably copy-paste from the docs a lot, so having that library feature everywhere means that they will follow best practices.


One open question is how to enforce this in CI. An idea I had was a simple CI step that greps across the extracted tests for ^#\[entry_point\] and errors out when it gets hit (something like that)

Describe actual usage of CosmWasm

The CosmWasm docs describe the creation of a product (Smart Contract) but do not explain how to use it in the real world.

I would like to see maybe a separate section like Deployment where we would create a simple but feature-full contract, set up a simple chain, and describe:

  • Install the contract on the chain
  • Initialize the contract
  • Execution, queries, sudos, ...
  • Usage of custom messages and custom queries
  • And potentially more

All of that with example setups in both contract and chain.

[tracking] Checklist before release

  • do most articles/sections have tags?
  • do examples showcase both cw-storage-plus and cw-storey? (using tabs like here)
  • is naming consistent?
  • is formatting more or less consistent? (nothing jarring)
  • #78

Storage terminology

We might want to discuss the terminology we use in docs for storage-plus and storey.

  • abstractions like Item and Map: containers, accessors, collections, structures?

are we consistent with using code tags in section/article titles

The question is - when the section/article name is a keyword/function name, should we use code tags or not? That is the minor things, and my take is that the clue is to be consistent about that. Reading some of the docs I think that doing so makes the formatting strange so I'd rather avoid any additional formatting in headers, but let's get aligned about this in the discussion and when we decide one would go through all the pages and unify that.

Possibility to highlight relevant code parts

Can we add a possibility in the code examples to highlight relevant lines? The best would probably be to dim most of the code and only make normal coloring for the relevant parts for the reader to focus on them, but any solution that moves attention to only relevant lines of the holistic example would most likely work. @abefernan ideas?

IBC: State Rewinding

I like it very much. I left couple more minor comments, apply them or not basing on your judgement, then just merge (no need for re-review).
One section I find missing here is about handling the "state rewinding". What I mean is that the IBC is non-transactional. This obviously brings the difficulty that if we get the timeout, we might want to make sure the changes we did are not happening - we need to rewind them manually.
I can see two strategies to work with that issue. One is to perform the "transaction rewinding" on the timeout/failure as mentioned. The other would be storing change state in some temporal place, and then "harden" it on ack. And probably mix of those as well.
I don't know if it is a thing to do in this PR, or if its needed, but I think some additional "advanced" chapter covering that would be nice. If you agree then please either add it or create an issue to add it later.

Originally posted by @hashedone in #19 (review)

Explain Stargate / Grpc query and Stargate / Any message from a contract POV

Basically, we want to tell people that this uses protobuf for the message / query and response type,
that they should use some protobuf crate for that (we can also reference crates like cosmos-sdk-proto and mention that many chains offer their own crates with predefined types) and show some example code on how to do it.
For messages, there is one example in the IBC docs already that can be adapted.

For Stargate query specifically, we should mention this caveat.

Rewrite `Map`

Move toward more use-case-driven docs, probably!

  • document compound keys being wonky when it comes to iteration, bounds, etc
    • link to the "wonkiness" documentation in IndexedMap docs

Feedback for “Index”

As a new cosmwasm developer, I want a graphical "anatomy of a cosmwasm program" so that I can quickly build a mental model of how it all comes together.

doing the workshop yesterday, I was able to get there, but I would have benefited from seeing some diagram of sorts.

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.