Skip to content

Commit

Permalink
Merge pull request #32 from CosmWasm/implement-approval-query
Browse files Browse the repository at this point in the history
Implement approval query; fix helper queries
  • Loading branch information
the-frey committed Dec 3, 2021
2 parents fab5ba5 + 70d820b commit cbdca5f
Show file tree
Hide file tree
Showing 20 changed files with 490 additions and 45 deletions.
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"
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

0 comments on commit cbdca5f

Please sign in to comment.