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

Implement approval query; fix helper queries #32

Merged
merged 13 commits into from
Dec 3, 2021
6 changes: 3 additions & 3 deletions Cargo.lock

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

4 changes: 2 additions & 2 deletions contracts/cw721-base/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "cw721-base"
version = "0.10.0"
version = "0.10.1"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can we release a minor version after merge @ethanfrey?

authors = ["Ethan Frey <ethanfrey@users.noreply.github.com>"]
edition = "2018"
description = "Basic implementation cw721 NFTs"
Expand All @@ -27,7 +27,7 @@ library = []
[dependencies]
cw0 = { version = "0.10.2" }
cw2 = { version = "0.10.2" }
cw721 = { path = "../../packages/cw721", version = "0.10.0" }
cw721 = { path = "../../packages/cw721", version = "0.10.1" }
cw-storage-plus = { version = "0.10.2" }
cosmwasm-std = { version = "1.0.0-beta2" }
schemars = "0.8.6"
Expand Down
5 changes: 3 additions & 2 deletions contracts/cw721-base/examples/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use std::fs::create_dir_all;
use cosmwasm_schema::{export_schema, export_schema_with_title, remove_schemas, schema_for};

use cw721::{
AllNftInfoResponse, ApprovedForAllResponse, ContractInfoResponse, NftInfoResponse,
NumTokensResponse, OwnerOfResponse, TokensResponse,
AllNftInfoResponse, ApprovedForAllResponse, ApprovedResponse, ContractInfoResponse,
NftInfoResponse, NumTokensResponse, OwnerOfResponse, TokensResponse,
};
use cw721_base::{ExecuteMsg, Extension, InstantiateMsg, MinterResponse, QueryMsg};

Expand All @@ -23,6 +23,7 @@ fn main() {
&out_dir,
"AllNftInfoResponse",
);
export_schema(&schema_for!(ApprovedResponse), &out_dir);
export_schema(&schema_for!(ApprovedForAllResponse), &out_dir);
export_schema(&schema_for!(ContractInfoResponse), &out_dir);
export_schema(&schema_for!(MinterResponse), &out_dir);
Expand Down
94 changes: 94 additions & 0 deletions contracts/cw721-base/schema/approved_response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "ApprovedResponse",
"type": "object",
"required": [
"approval"
],
"properties": {
"approval": {
"$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",
"type": "string"
}
}
},
"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)",
"oneOf": [
{
"description": "AtHeight will expire when `env.block.height` >= height",
"type": "object",
"required": [
"at_height"
],
"properties": {
"at_height": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
},
"additionalProperties": false
},
{
"description": "AtTime will expire when `env.block.time` >= time",
"type": "object",
"required": [
"at_time"
],
"properties": {
"at_time": {
"$ref": "#/definitions/Timestamp"
}
},
"additionalProperties": false
},
{
"description": "Never will never expire. Used to express the empty variant",
"type": "object",
"required": [
"never"
],
"properties": {
"never": {
"type": "object"
}
},
"additionalProperties": false
}
]
},
"Timestamp": {
"description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```",
"allOf": [
{
"$ref": "#/definitions/Uint64"
}
]
},
"Uint64": {
"description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```",
"type": "string"
}
}
}
25 changes: 25 additions & 0 deletions contracts/cw721-base/schema/query_msg.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,31 @@
},
"additionalProperties": false
},
{
"description": "Return operator that can access all of the owner's tokens. Return type: `ApprovedResponse`",
"type": "object",
"required": [
"approved"
],
"properties": {
"approved": {
"type": "object",
"required": [
"operator",
"owner"
],
"properties": {
"operator": {
"type": "string"
},
"owner": {
"type": "string"
}
}
}
},
"additionalProperties": false
},
{
"description": "List all operators that can access all of the owner's tokens Return type: `ApprovedForAllResponse`",
"type": "object",
Expand Down
25 changes: 22 additions & 3 deletions contracts/cw721-base/src/contract_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info};
use cosmwasm_std::{from_binary, to_binary, CosmosMsg, DepsMut, Empty, Response, WasmMsg};

use cw721::{
ApprovedForAllResponse, ContractInfoResponse, Cw721Query, Cw721ReceiveMsg, Expiration,
NftInfoResponse, OwnerOfResponse,
Approval, ApprovedForAllResponse, ApprovedResponse, ContractInfoResponse, Cw721Query,
Cw721ReceiveMsg, Expiration, NftInfoResponse, OwnerOfResponse,
};

use crate::{
Expand Down Expand Up @@ -470,7 +470,7 @@ fn approving_all_revoking_all() {
};
let owner = mock_info("demeter", &[]);
let res = contract
.execute(deps.as_mut(), mock_env(), owner, approve_all_msg)
.execute(deps.as_mut(), mock_env(), owner.clone(), approve_all_msg)
.unwrap();
assert_eq!(
res,
Expand All @@ -480,6 +480,25 @@ fn approving_all_revoking_all() {
.add_attribute("operator", "random")
);

// test approval query
let res = contract
.approval(
deps.as_ref(),
mock_env(),
owner.sender.into_string(),
String::from("random"),
)
.unwrap();
assert_eq!(
res,
ApprovedResponse {
approval: Approval {
spender: String::from("random"),
expires: Expiration::Never {}
}
}
);

// random can now transfer
let random = mock_info("random", &[]);
let transfer_msg = ExecuteMsg::TransferNft {
Expand Down
8 changes: 8 additions & 0 deletions contracts/cw721-base/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,14 @@ pub enum QueryMsg {
/// unset or false will filter out expired approvals, you must set to true to see them
include_expired: Option<bool>,
},

/// Return operator that can access all of the owner's tokens.
/// Return type: `ApprovedResponse`
Approved {
owner: String,
operator: String,
},

/// List all operators that can access all of the owner's tokens
/// Return type: `ApprovedForAllResponse`
ApprovedForAll {
Expand Down
30 changes: 28 additions & 2 deletions contracts/cw721-base/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use cosmwasm_std::{to_binary, Binary, BlockInfo, Deps, Env, Order, Record, StdEr

use cw0::maybe_addr;
use cw721::{
AllNftInfoResponse, ApprovedForAllResponse, ContractInfoResponse, CustomMsg, Cw721Query,
Expiration, NftInfoResponse, NumTokensResponse, OwnerOfResponse, TokensResponse,
AllNftInfoResponse, ApprovedForAllResponse, ApprovedResponse, ContractInfoResponse, CustomMsg,
Cw721Query, Expiration, NftInfoResponse, NumTokensResponse, OwnerOfResponse, TokensResponse,
};
use cw_storage_plus::Bound;

Expand Down Expand Up @@ -79,6 +79,29 @@ where
Ok(ApprovedForAllResponse { operators: res? })
}

fn approval(
&self,
deps: Deps,
_env: Env,
owner: String,
operator: String,
) -> StdResult<ApprovedResponse> {
let owner_addr = deps.api.addr_validate(&owner)?;
let operator_addr = deps.api.addr_validate(&operator)?;

let expires = self
.operators
.key((&owner_addr, &operator_addr))
.load(deps.storage)?;

Ok(ApprovedResponse {
approval: cw721::Approval {
spender: operator,
expires,
},
})
}

fn tokens(
&self,
deps: Deps,
Expand Down Expand Up @@ -197,6 +220,9 @@ where
QueryMsg::AllTokens { start_after, limit } => {
to_binary(&self.all_tokens(deps, start_after, limit)?)
}
QueryMsg::Approved { owner, operator } => {
to_binary(&self.approval(deps, env, owner, operator)?)
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion contracts/cw721-metadata-onchain/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "cw721-metadata-onchain"
version = "0.10.0"
version = "0.10.1"
authors = ["Ethan Frey <ethanfrey@users.noreply.github.com>"]
edition = "2018"
description = "Example extending CW721 NFT to store metadata on chain"
Expand Down
5 changes: 3 additions & 2 deletions contracts/cw721-metadata-onchain/examples/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use std::fs::create_dir_all;
use cosmwasm_schema::{export_schema, export_schema_with_title, remove_schemas, schema_for};

use cw721::{
AllNftInfoResponse, ApprovedForAllResponse, ContractInfoResponse, NftInfoResponse,
NumTokensResponse, OwnerOfResponse, TokensResponse,
AllNftInfoResponse, ApprovedForAllResponse, ApprovedResponse, ContractInfoResponse,
NftInfoResponse, NumTokensResponse, OwnerOfResponse, TokensResponse,
};
use cw721_metadata_onchain::{ExecuteMsg, Extension, InstantiateMsg, MinterResponse, QueryMsg};

Expand All @@ -23,6 +23,7 @@ fn main() {
&out_dir,
"AllNftInfoResponse",
);
export_schema(&schema_for!(ApprovedResponse), &out_dir);
export_schema(&schema_for!(ApprovedForAllResponse), &out_dir);
export_schema(&schema_for!(ContractInfoResponse), &out_dir);
export_schema(&schema_for!(MinterResponse), &out_dir);
Expand Down
Loading