Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Escrow 721 setup #5

Merged
merged 34 commits into from
Jun 23, 2022
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
a745030
escrow 721 basic setup
humanalgorithm Apr 28, 2022
ed9bb6d
fix formatting
humanalgorithm Apr 28, 2022
74ce4e3
working query owner of
humanalgorithm Apr 29, 2022
9699446
compiling build with two key tuple key
humanalgorithm May 27, 2022
ed8e7cc
ics 721 tests pass
humanalgorithm May 27, 2022
294f83a
working mint test in e2etest
humanalgorithm May 27, 2022
0326a7c
fix lint:
humanalgorithm May 28, 2022
65f2db5
refactor e2etest
humanalgorithm May 31, 2022
837d0f4
stashing to share code
humanalgorithm Jun 2, 2022
a1d0e40
working get owner query
humanalgorithm Jun 2, 2022
f6e8f15
uncomment test
humanalgorithm Jun 2, 2022
1979b7d
lint
humanalgorithm Jun 2, 2022
16cd95d
working get nft info
humanalgorithm Jun 2, 2022
e22d94c
fix lint
humanalgorithm Jun 2, 2022
57ae1b1
working transfer NFT
humanalgorithm Jun 2, 2022
c3568f0
remove unnecesary code
humanalgorithm Jun 2, 2022
69458d8
no error save class
humanalgorithm Jun 3, 2022
ceac211
working has class
humanalgorithm Jun 3, 2022
f2c06f2
fix lint
humanalgorithm Jun 3, 2022
766fd88
working GetClass implementation
humanalgorithm Jun 3, 2022
50b8d11
regen schema, refactor test
humanalgorithm Jun 3, 2022
a694720
fix class storage map
humanalgorithm Jun 23, 2022
b3cdbed
adding response attributes
humanalgorithm Jun 23, 2022
dac2db1
fix format
humanalgorithm Jun 23, 2022
edce0d0
updating cargo versions
humanalgorithm Jun 23, 2022
086c137
updating cargo cw721-ibc versions
humanalgorithm Jun 23, 2022
b546368
change to get nft
humanalgorithm Jun 23, 2022
4fe8d48
change to getnft
humanalgorithm Jun 23, 2022
337d228
fix lint
humanalgorithm Jun 23, 2022
f0d7981
refactory query logic
humanalgorithm Jun 23, 2022
36c93d5
remove non needed comment
humanalgorithm Jun 23, 2022
1a6eacb
Merge pull request #6 from public-awesome/humanalgorithm/refactor-que…
humanalgorithm Jun 23, 2022
4ffd6f2
changing query functions to public
humanalgorithm Jun 23, 2022
accb69e
fix lint
humanalgorithm Jun 23, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
421 changes: 337 additions & 84 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions contracts/escrow721/.cargo/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[alias]
wasm = "build --release --target wasm32-unknown-unknown"
unit-test = "test --lib"
schema = "run --example schema"
47 changes: 47 additions & 0 deletions contracts/escrow721/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
[package]
authors = ["Michael Scotto"]
edition = "2021"
name = "escrow721"
version = "0.12.0"


exclude = [
# Those files are rust-optimizer artifacts. You might want to commit them for convenience but they should not be part of the source code publication.
"contract.wasm",
"hash.txt",
]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lib]
crate-type = ["cdylib", "rlib"]

[features]
# for more explicit tests, cargo test --features=backtraces
backtraces = ["cosmwasm-std/backtraces"]
# use library feature to disable all instantiate/execute/query exports
library = []

[package.metadata.scripts]
optimize = """docker run --rm -v "$(pwd)":/code \
--mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/target \
--mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \
cosmwasm/rust-optimizer:0.12.3
"""

[dependencies]
cosmwasm-std = { version = "1.0.0-beta8", features = ["stargate"] }
cosmwasm-storage = { version = "1.0.0-beta8" }
cw-storage-plus = "0.13.2"
cw-utils = "0.13.2"
cw2 = "0.13.2"
cw20-ics20 = { version = "0.13.2", features = ["library"] }
sg721 = { version = "0.12.0", features = ["library"] }
cw721-base-ibc = { git = "https://github.com/public-awesome/cw721-ibc.git", version = "0.13.2", branch="main", features = ["library"]}
cw721-ibc = { git = "https://github.com/public-awesome/cw721-ibc.git", branch="main", version = "0.13.2"}
schemars = "0.8.8"
serde = { version = "1.0.133", default-features = false, features = ["derive"] }
thiserror = { version = "1.0.30" }

[dev-dependencies]
cosmwasm-schema = { version = "1.0.0-beta8" }
138 changes: 138 additions & 0 deletions contracts/escrow721/src/contract.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
use cosmwasm_std::entry_point;
use cosmwasm_std::Response;
use cosmwasm_std::StdError;
#[cfg(not(feature = "library"))]
use cosmwasm_std::{to_binary, Binary, Deps, DepsMut, Empty, Env, MessageInfo, StdResult};
use cw721_base_ibc::msg::{ExecuteMsg, InstantiateMsg, MintMsg, QueryMsg};
use cw721_base_ibc::{ContractError, Cw721Contract};
use cw721_ibc::{Cw721Execute, Cw721Query, NftInfoResponse, OwnerOfResponse};

pub type CW721ContractWrapper<'a> = Cw721Contract<'a, Empty, Empty>;
use crate::state::CLASS_STORAGE;

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn instantiate(
deps: DepsMut,
_env: Env,
_info: MessageInfo,
msg: InstantiateMsg,
) -> StdResult<cosmwasm_std::Response> {
CW721ContractWrapper::default().instantiate(deps, _env, _info, msg)
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn execute(
deps: DepsMut,
env: Env,
info: MessageInfo,
msg: ExecuteMsg<Empty>,
) -> Result<Response<Empty>, ContractError> {
match msg {
ExecuteMsg::SaveClass {
class_id,
class_uri,
} => save_class(deps, class_id, class_uri),
_ => CW721ContractWrapper::default().execute(deps, env, info, msg),
}
}

pub fn save_class(
deps: DepsMut,
class_id: String,
class_uri: String,
) -> Result<Response<Empty>, ContractError> {
CLASS_STORAGE.save(deps.storage, class_id, &class_uri)?;
Ok(Response::default())

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add response attributes for indexers "action", "save_class", "class_id", class_id

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added these attributes

}

pub fn transfer(
deps: DepsMut,
env: Env,
info: MessageInfo,
recipient: String,
class_id: String,
token_id: String,
) -> Result<cosmwasm_std::Response, ContractError> {
CW721ContractWrapper::default().transfer_nft(deps, env, info, recipient, class_id, token_id)
}

pub fn mint(
deps: DepsMut,
_env: Env,
info: MessageInfo,
class_id: String,
token_id: String,
token_uri: String,
receiver: String,
) -> Result<cosmwasm_std::Response, ContractError> {
let mint_msg = MintMsg {
class_id,
token_id,
owner: receiver,
token_uri: Some(token_uri),
extension: Empty {},
};

CW721ContractWrapper::default().mint(deps, _env, info, mint_msg)
}

pub fn burn(
deps: DepsMut,
_env: Env,
info: MessageInfo,
class_id: String,
token_id: String,
) -> Result<cosmwasm_std::Response, ContractError> {
CW721ContractWrapper::default().burn(deps, _env, info, class_id, token_id)
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
match msg {
QueryMsg::OwnerOf {
class_id,
token_id,
include_expired,
} => to_binary(&get_owner(
deps,
_env,
class_id,
token_id,
include_expired.unwrap_or(false),
)?),
QueryMsg::NftInfo { class_id, token_id } => to_binary(&nft_info(deps, class_id, token_id)?),
QueryMsg::HasClass { class_id } => to_binary(&has_class(deps, class_id)),
QueryMsg::GetClass { class_id } => to_binary(&get_class(deps, class_id)?),
_ => Err(StdError::GenericErr {
msg: "Unsupported message type".to_string(),
}),
}
}

pub fn get_owner(
deps: Deps,
env: Env,
class_id: String,
token_id: String,
include_expired: bool,
) -> StdResult<OwnerOfResponse> {
CW721ContractWrapper::default().owner_of(deps, env, class_id, token_id, include_expired)
}

fn nft_info(deps: Deps, class_id: String, token_id: String) -> StdResult<NftInfoResponse<Empty>> {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CW Standard: add query_ prefixes to differentiate query implementation functions.

  • fn query_nft_info
  • fn query_has_class
  • fn query_get_class

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mccallofthewild per the IBC spec this should actually be called "GetNFT"
https://github.com/cosmos/ibc/pull/615/files#diff-254e967536211862be86cdfb12569fbcaa03eaf39672f9fae5ab7b226b57cc8fR152

I would like to stay with the spec names wherever possible
But on the other hand I think anytime a query is performed it would be through the query function so possibly it doesn't need to stay with the spec name

Let me know what you think (I changed it to GetNFT for now which is what I originally intended)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@humanalgorithm GetNFT sounds right.

It may be wise to make the functions public as well. The main purpose for the query naming convention is to make it easy to wrap/extend the contract without losing compatibility with the canonical codebase.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mccallofthewild I'll make the query functions public

CW721ContractWrapper::default().nft_info(deps, class_id, token_id)
}

fn has_class(deps: Deps, class_id: String) -> bool {
CLASS_STORAGE.has(deps.storage, class_id)
}

fn get_class(deps: Deps, class_id: String) -> StdResult<(String, String)> {
match CLASS_STORAGE.load(deps.storage, class_id.clone()) {
Ok(class_uri) => Ok((class_id, class_uri)),
Err(_) => Err(StdError::generic_err(format!(
"Class {} not found",
class_id
))),
}
}
2 changes: 2 additions & 0 deletions contracts/escrow721/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod contract;
pub mod state;
3 changes: 3 additions & 0 deletions contracts/escrow721/src/state.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
use cw_storage_plus::Map;

pub const CLASS_STORAGE: Map<String, String> = Map::new("class_storage");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's preferable to use &str here than owned strings. Did you run into issues using &str?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a comment about what these strings represent?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to <&str, String> with a comment

3 changes: 2 additions & 1 deletion contracts/ics721/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ cw-storage-plus = "0.13.2"
cw-utils = "0.13.2"
cw2 = "0.13.2"
cw20-ics20 = { version = "0.13.2", features = ["library"] }
cw721 = "0.13.2"
cw721-base-ibc = { git = "https://github.com/public-awesome/cw721-ibc.git", version="0.13.2"}
cw721-ibc = { git = "https://github.com/public-awesome/cw721-ibc.git", version="0.13.2"}
schemars = "0.8.8"
serde = { version = "1.0.133", default-features = false, features = ["derive"] }
thiserror = { version = "1.0.30" }
Expand Down
4 changes: 2 additions & 2 deletions contracts/ics721/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use cosmwasm_std::{
};
use cw2::set_contract_version;
use cw20_ics20::msg::{ListChannelsResponse, PortResponse};
use cw721::Cw721ReceiveMsg;
use cw721_ibc::Cw721ReceiveMsg;
use cw_utils::nonpayable;

use crate::error::ContractError;
Expand Down Expand Up @@ -84,7 +84,7 @@ pub fn execute_transfer(

// build ics721 packet
let packet = Ics721Packet::new(
env.contract.address.as_ref(),
&msg.class_id,
None,
msg.token_ids
.iter()
Expand Down
18 changes: 11 additions & 7 deletions contracts/ics721/src/contract_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ mod contact_testing {
use cosmwasm_std::{CosmosMsg, IbcEndpoint};
use cw2::{get_contract_version, ContractVersion};
use cw20_ics20::state::ChannelInfo;
use cw721_ibc::Cw721ReceiveMsg;

use cosmwasm_std::testing::mock_dependencies;

Expand Down Expand Up @@ -342,15 +343,15 @@ mod contact_testing {
},
Attribute {
key: "class_id".into(),
value: "cosmos2contract".into(),
value: "abc/123/collection-addr".into(),
},
Attribute {
key: "token_ids".into(),
value: "1,2,3".into(),
},
];
let expected_ics721_packet = Ics721Packet::new(
mock_env().contract.address.as_ref(),
"abc/123/collection-addr",
None,
transfer_msg
.token_ids
Expand Down Expand Up @@ -399,6 +400,7 @@ mod contact_testing {

let cw721_receive_msg = Cw721ReceiveMsg {
sender: sender_address_str.to_string(),
class_id: "abc/123/collection-addr".to_string(),
token_id: "1".to_string(),
msg: to_binary(&transfer_msg).unwrap(),
};
Expand All @@ -425,15 +427,15 @@ mod contact_testing {
},
Attribute {
key: "class_id".into(),
value: "cosmos2contract".into(),
value: "abc/123/collection-addr".into(),
},
Attribute {
key: "token_ids".into(),
value: "1,2,3".into(),
},
];
let expected_ics721_packet = Ics721Packet::new(
mock_env().contract.address.as_ref(),
"abc/123/collection-addr",
None,
transfer_msg
.token_ids
Expand Down Expand Up @@ -484,6 +486,7 @@ mod contact_testing {

let cw721_receive_msg = Cw721ReceiveMsg {
sender: sender_address_str.to_string(),
class_id: "class_id_1".to_string(),
token_id: "1".to_string(),
msg: to_binary(&transfer_msg).unwrap(),
};
Expand Down Expand Up @@ -525,6 +528,7 @@ mod contact_testing {
let cw_721_receive_sender = "sender_address_receive_path";
let cw721_receive_msg = ExecuteMsg::Receive(Cw721ReceiveMsg {
sender: cw_721_receive_sender.to_string(),
class_id: "abc/123/collection-addr".to_string(),
token_id: "1".to_string(),
msg: to_binary(&transfer_msg).unwrap(),
});
Expand All @@ -551,7 +555,7 @@ mod contact_testing {
},
Attribute {
key: "class_id".into(),
value: "cosmos2contract".into(),
value: "abc/123/collection-addr".into(),
},
Attribute {
key: "token_ids".into(),
Expand All @@ -560,7 +564,7 @@ mod contact_testing {
];

let expected_ics721_packet = Ics721Packet::new(
mock_env().contract.address.as_ref(),
"abc/123/collection-addr",
None,
transfer_msg
.token_ids
Expand Down Expand Up @@ -628,7 +632,7 @@ mod contact_testing {
},
Attribute {
key: "class_id".into(),
value: "cosmos2contract".into(),
value: "abc/123/collection-addr".into(),
},
Attribute {
key: "token_ids".into(),
Expand Down
2 changes: 1 addition & 1 deletion contracts/ics721/src/ibc.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use cw20_ics20::ibc::Ics20Ack;
use cw20_ics20::state::ChannelInfo;
use cw721::Cw721ExecuteMsg;
use cw721_ibc::Cw721ExecuteMsg;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

Expand Down
2 changes: 1 addition & 1 deletion contracts/ics721/src/msg.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use cw20_ics20::state::ChannelInfo;
use cw721::Cw721ReceiveMsg;
use cw721_ibc::Cw721ReceiveMsg;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

Expand Down
13 changes: 13 additions & 0 deletions e2e/account.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package e2e_test

import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/secp256k1"
)

type Account struct {
PrivKey secp256k1.PrivKey
PubKey crypto.PubKey
Address sdk.AccAddress
}
Loading