Skip to content

Commit

Permalink
Merge pull request #247 from yihuang/cw1155-spec
Browse files Browse the repository at this point in the history
Add cw1155 specification
  • Loading branch information
ethanfrey authored Mar 19, 2021
2 parents 0c3f3f5 + 8581364 commit 34504b0
Show file tree
Hide file tree
Showing 21 changed files with 1,350 additions and 0 deletions.
13 changes: 13 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions packages/cw0/src/event.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use cosmwasm_std::Response;

/// This defines a set of attributes which should be added to `Response`.
pub trait Event {
/// Append attributes to response
fn add_attributes(&self, response: &mut Response);
}
2 changes: 2 additions & 0 deletions packages/cw0/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod balance;
mod event;
mod expiration;
mod pagination;
mod payment;
Expand All @@ -9,4 +10,5 @@ pub use pagination::{
pub use payment::{may_pay, must_pay, nonpayable, one_coin, PaymentError};

pub use crate::balance::NativeBalance;
pub use crate::event::Event;
pub use crate::expiration::{Duration, Expiration, DAY, HOUR, WEEK};
19 changes: 19 additions & 0 deletions packages/cw1155/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "cw1155"
version = "0.6.0-alpha1"
authors = ["Huang Yi <huang@crypto.com>"]
edition = "2018"
description = "Definition and types for the CosmWasm-1155 interface"
license = "Apache-2.0"
repository = "https://github.com/CosmWasm/cosmwasm-plus"
homepage = "https://cosmwasm.com"
documentation = "https://docs.cosmwasm.com"

[dependencies]
cw0 = { path = "../../packages/cw0", version = "0.6.0-alpha1" }
cosmwasm-std = { version = "0.14.0-beta1" }
schemars = "0.7"
serde = { version = "1.0.103", default-features = false, features = ["derive"] }

[dev-dependencies]
cosmwasm-schema = { version = "0.14.0-beta1" }
112 changes: 112 additions & 0 deletions packages/cw1155/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# CW1155 Spec: Multiple Tokens

CW1155 is a specification for managing multiple tokens based on CosmWasm.
The name and design is based on Ethereum's ERC1155 standard.

The specification is split into multiple sections, a contract may only
implement some of this functionality, but must implement the base.

Design decisions:

- Fungible tokens and non-fungible tokens are treated equally, non-fungible tokens just have one max supply.

- Approval is set or unset to some operator over entire set of tokens. (More nuanced control is defined in
[ERC1761](https://eips.ethereum.org/EIPS/eip-1761), do we want to merge them together?)

- Mint and burn are mixed with transfer/send messages, otherwise, we'll have much more message types, e.g.
`Mint`/`MintToContract`/`BatchMint`/`BatchMintToContract`, etc.

In transfer/send messges, `from`/`to` are optional, a `None` `from` means minting, a `None` `to` means burning, they
must not both be `None` at the same time.

## Base

### Messages

`SendFrom{from, to, token_id, value, msg}` - This transfers some amount of tokens between two accounts. If `to` is an
address controlled by a smart contract, it must implement the `CW1155Receiver` interface, `msg` will be passed to it
along with other fields, otherwise, `msg` should be `None`. The operator should either be the `from` account or have
approval from it.

`BatchSendFrom{from, to, batch: Vec<(token_id, value)>, msg}` - Batched version of `SendFrom` which can handle multiple
types of tokens at once.

`Mint {to, token_id, value, msg}` - This mints some tokens to `to` account, If `to` is controlled by a smart contract,
it should implement `CW1155Receiver` interface, `msg` will be passed to it along with other fields, otherwise, `msg`
should be `None`.

`BatchMint {to, batch: Vec<(token_id, value)>, msg}` - Batched version of `Mint`.

`Burn {from, token_id, value}` - This burns some tokens from `from` account.

`BatchBurn {from, batch: Vec<(token_id, value)>}` - Batched version of `Burn`.

`ApproveAll{ operator, expires }` - Allows operator to transfer / send any token from the owner's account. If expiration
is set, then this allowance has a time/height limit.

`RevokeAll { operator }` - Remove previously granted ApproveAll permission

### Queries

`Balance { owner, token_id }` - Query the balance of `owner` on perticular type of token, default to `0` when record not
exist.

`BatchBalance { owner, token_ids }` - Query the balance of `owner` on multiple types of tokens, batched version of
`Balance`.

`ApprovedForAll{owner, include_expired, start_after, limit}` - List all operators that can access all of the owner's
tokens. Return type is `ApprovedForAllResponse`. If `include_expired` is set, show expired owners in the results,
otherwise, ignore them.

`ApprovedForAllItem{owner, operator}` - Query approved status `owner` granted to `operator`. Return type is
`ApprovedForAllItemResponse`.

### Receiver

Any contract wish to receive CW1155 tokens must implement `Cw1155ReceiveMsg` and `Cw1155BatchReceiveMsg`.

`Cw1155ReceiveMsg { operator, from, token_id, amount, msg}` -

`Cw1155BatchReceiveMsg { operator, from, batch, msg}` -

### Events

- `transfer(from, to, token_id, value)`

`from`/`to` are optional, no `from` attribute means minting, no `to` attribute means burning, but they mustn't be
neglected at the same time.


## Metadata

### Queries

`TokenInfo{ token_id }` - Query metadata url of `token_id`.

### Events

`token_info(url, token_id)`

Metadata url of `token_id` is changed, `url` should point to a json file.

## Enumerable

### Queries

Pagination is acheived via `start_after` and `limit`. Limit is a request
set by the client, if unset, the contract will automatically set it to
`DefaultLimit` (suggested 10). If set, it will be used up to a `MaxLimit`
value (suggested 30). Contracts can define other `DefaultLimit` and `MaxLimit`
values without violating the CW1155 spec, and clients should not rely on
any particular values.

If `start_after` is unset, the query returns the first results, ordered by
lexogaphically by `token_id`. If `start_after` is set, then it returns the
first `limit` tokens *after* the given one. This allows straight-forward
pagination by taking the last result returned (a `token_id`) and using it
as the `start_after` value in a future query.

`Tokens{owner, start_after, limit}` - List all token_ids that belong to a given owner.
Return type is `TokensResponse{tokens: Vec<token_id>}`.

`AllTokens{start_after, limit}` - Requires pagination. Lists all token_ids controlled by the contract.
24 changes: 24 additions & 0 deletions packages/cw1155/examples/schema.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use std::env::current_dir;
use std::fs::create_dir_all;

use cosmwasm_schema::{export_schema, remove_schemas, schema_for};

use cw1155;

fn main() {
let mut out_dir = current_dir().unwrap();
out_dir.push("schema");
create_dir_all(&out_dir).unwrap();
remove_schemas(&out_dir).unwrap();

export_schema(&schema_for!(cw1155::Cw1155HandleMsg), &out_dir);
export_schema(&schema_for!(cw1155::Cw1155QueryMsg), &out_dir);
export_schema(&schema_for!(cw1155::Cw1155ReceiveMsg), &out_dir);
export_schema(&schema_for!(cw1155::Cw1155BatchReceiveMsg), &out_dir);
export_schema(&schema_for!(cw1155::BalanceResponse), &out_dir);
export_schema(&schema_for!(cw1155::BatchBalanceResponse), &out_dir);
export_schema(&schema_for!(cw1155::ApprovedForAllResponse), &out_dir);
export_schema(&schema_for!(cw1155::IsApprovedForAllResponse), &out_dir);
export_schema(&schema_for!(cw1155::TokenInfoResponse), &out_dir);
export_schema(&schema_for!(cw1155::TokensResponse), &out_dir);
}
91 changes: 91 additions & 0 deletions packages/cw1155/schema/approved_for_all_response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "ApprovedForAllResponse",
"type": "object",
"required": [
"operators"
],
"properties": {
"operators": {
"type": "array",
"items": {
"$ref": "#/definitions/Approval"
}
}
},
"definitions": {
"Approval": {
"type": "object",
"required": [
"expires",
"spender"
],
"properties": {
"expires": {
"description": "When the Approval expires (maybe Expiration::never)",
"allOf": [
{
"$ref": "#/definitions/Expiration"
}
]
},
"spender": {
"description": "Account that can transfer/send the token",
"allOf": [
{
"$ref": "#/definitions/HumanAddr"
}
]
}
}
},
"Expiration": {
"description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)",
"anyOf": [
{
"description": "AtHeight will expire when `env.block.height` >= height",
"type": "object",
"required": [
"at_height"
],
"properties": {
"at_height": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
}
},
{
"description": "AtTime will expire when `env.block.time` >= time",
"type": "object",
"required": [
"at_time"
],
"properties": {
"at_time": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
}
},
{
"description": "Never will never expire. Used to express the empty variant",
"type": "object",
"required": [
"never"
],
"properties": {
"never": {
"type": "object"
}
}
}
]
},
"HumanAddr": {
"type": "string"
}
}
}
18 changes: 18 additions & 0 deletions packages/cw1155/schema/balance_response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "BalanceResponse",
"type": "object",
"required": [
"balance"
],
"properties": {
"balance": {
"$ref": "#/definitions/Uint128"
}
},
"definitions": {
"Uint128": {
"type": "string"
}
}
}
21 changes: 21 additions & 0 deletions packages/cw1155/schema/batch_balance_response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "BatchBalanceResponse",
"type": "object",
"required": [
"balances"
],
"properties": {
"balances": {
"type": "array",
"items": {
"$ref": "#/definitions/Uint128"
}
}
},
"definitions": {
"Uint128": {
"type": "string"
}
}
}
57 changes: 57 additions & 0 deletions packages/cw1155/schema/cw1155_batch_receive_msg.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Cw1155BatchReceiveMsg",
"description": "Cw1155BatchReceiveMsg should be de/serialized under `BatchReceive()` variant in a HandleMsg",
"type": "object",
"required": [
"batch",
"msg",
"operator"
],
"properties": {
"batch": {
"type": "array",
"items": {
"type": "array",
"items": [
{
"type": "string"
},
{
"$ref": "#/definitions/Uint128"
}
],
"maxItems": 2,
"minItems": 2
}
},
"from": {
"anyOf": [
{
"$ref": "#/definitions/HumanAddr"
},
{
"type": "null"
}
]
},
"msg": {
"$ref": "#/definitions/Binary"
},
"operator": {
"$ref": "#/definitions/HumanAddr"
}
},
"definitions": {
"Binary": {
"description": "Binary is a wrapper around Vec<u8> to add base64 de/serialization with serde. It also adds some helper methods to help encode inline.\n\nThis is only needed as serde-json-{core,wasm} has a horrible encoding for Vec<u8>",
"type": "string"
},
"HumanAddr": {
"type": "string"
},
"Uint128": {
"type": "string"
}
}
}
Loading

0 comments on commit 34504b0

Please sign in to comment.