1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use cosmwasm_std::{
HumanAddr, Env, Uint128,
};
use fsnft_utils::{
FtokenInstance, ContractInfo, UndrNftInfo, FtokenInfo, FtokenConf,
AucConf, PropConf,
};
use secret_toolkit::{
// serialization::{Json, Serde},
utils::{HandleCallback, Query},
snip721::{ViewerInfo, AccessLevel, Metadata, Expiration, NftDossier,
},
};
use crate::{
contract::{RESPONSE_BLOCK_SIZE},
msg::InitMsg,
};
use super::{
state::{StakedTokens, ResvVote, PropInfoTally, VoteRegister, BidInfo},
};
/////////////////////////////////////////////////////////////////////////////////
// Instantiation
/////////////////////////////////////////////////////////////////////////////////
/// Init Callback response to send upon instantiation of ftoken contract
#[derive(Serialize, Deserialize, JsonSchema, Clone, Debug)]
#[serde(rename_all = "snake_case")]
pub enum InitRes {
/// Callback to fractionalizer contract upon instantiation of ftoken contract
ReceiveFtokenCallback {
ftkn_instance: FtokenInstance,
},
/// set viewing key sent to nft contract
SetViewingKey {
/// desired viewing key
key: String,
/// optional message length padding
padding: Option<String>,
},
}
impl HandleCallback for InitRes {
const BLOCK_SIZE: usize = RESPONSE_BLOCK_SIZE;
}
/// Implements register_receieve of ftoken contract on fractionalizer
impl InitRes {
pub fn register_receive(msg: InitMsg, env: Env) -> Self {
InitRes::ReceiveFtokenCallback {
ftkn_instance: FtokenInstance {
ftkn_idx: msg.init_info.ftkn_idx,
depositor: msg.init_info.depositor,
ftoken_contr: ContractInfo {
code_hash: env.contract_code_hash,
address: env.contract.address,
},
init_nft_info: UndrNftInfo {
token_id: msg.init_info.nft_info.token_id,
nft_contr: ContractInfo {
code_hash: msg.init_info.nft_info.nft_contr.code_hash,
address: msg.init_info.nft_info.nft_contr.address,
},
},
name: msg.name,
symbol: msg.symbol,
decimals: msg.decimals,
}
}
}
}
/////////////////////////////////////////////////////////////////////////////////
// ftoken query messages
/////////////////////////////////////////////////////////////////////////////////
/// Public (ie: non authenticated) query messages that are specific to ftoken
/// functionality (as opposed to standard SNIP20 queries)
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum FtokenQuery {
/// Information on the ftoken determined at the point of fractionalization
FtokenInfo { },
/// ftoken configuration, including auction and DAO parameters. These configurations
/// can be changed through a DAO
FtokenConfig { },
AuctionConfig { },
ProposalConfig { },
/// The minimum amount that a bidder needs to bid (to buy out the underlying NFT) in
/// order for the bid to be valid.
ReservationPrice { },
/// List of DAO proposals
ProposalList { },
// Enabling this reduces the privacy of bidders. Blockchain analysis or side chain attacks
// can easily reveal address of bidders
BidList {
page: u32,
page_size: u32
},
}
/// Authenticated queries (ie: required viewing key or query permit) that are specific
/// to ftoken functionality (as opposed to standard SNIP20 queries)
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum FtokenAuthQuery {
NftPrivateMetadata { },
NftDossier { },
StakedTokens { },
ReservationPriceVote { },
ProposalVotes { prop_id: u32 },
Bid { },
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum FtokenQueryAnswer {
FtokenInfo {
ftkn_info: FtokenInfo,
},
FtokenConfig {
ftkn_conf: FtokenConf,
},
AuctionConfig {
auc_conf: AucConf,
},
ProposalConfig {
prop_conf: PropConf,
},
ReservationPrice {
ftokens_voted: Uint128,
reservation_price: Uint128,
},
ProposalList(Vec<PropInfoTally>),
BidList {
bid_amounts: Vec<Uint128>,
total_bids: u64,
},
NftPrivateMetadata(PrivateMetadataResponse),
NftDossier(NftDossierResponse),
StakedTokens(StakedTokens),
ReservationPriceVote(ResvVote),
ProposalVotes(VoteRegister),
Bid(BidInfo),
}
/////////////////////////////////////////////////////////////////////////////////
// Messages between ftoken contract and underlying NFT
/////////////////////////////////////////////////////////////////////////////////
/// List of messages that is allowed to be sent to underlying NFT. ftoken holders
/// can propose to send these messages to the underlying NFT, where other ftoken
/// holders vote on whether to accept the proposal. Once a proposal passes, a
/// transaction can be triggered to send the proposed message to the underlying NFT
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum AllowedNftMsg {
SetMetadata {
public_metadata: Option<Metadata>,
private_metadata: Option<Metadata>,
},
Reveal { },
MakeOwnershipPrivate { },
SetGlobalApproval {
view_owner: Option<AccessLevel>,
view_private_metadata: Option<AccessLevel>,
expires: Option<Expiration>,
},
SetWhitelistedApproval {
address: HumanAddr,
view_owner: Option<AccessLevel>,
view_private_metadata: Option<AccessLevel>,
expires: Option<Expiration>,
},
}
/// List of messages that is allowed to be sent to underlying NFT
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum S721HandleMsg {
/// set the public and/or private metadata. This can be called by either the token owner or
/// a valid minter if they have been given this power by the appropriate config values
SetMetadata {
/// id of the token whose metadata should be updated
token_id: String,
/// the optional new public metadata
public_metadata: Option<Metadata>,
/// the optional new private metadata
private_metadata: Option<Metadata>,
/// optional message length padding
padding: Option<String>,
},
/// Reveal the private metadata of a sealed token and mark the token as having been unwrapped
Reveal {
/// id of the token to unwrap
token_id: String,
/// optional message length padding
padding: Option<String>,
},
/// if a contract was instantiated to make ownership public by default, this will allow
/// an address to make the ownership of their tokens private. The address can still use
/// SetGlobalApproval to make ownership public either inventory-wide or for a specific token
MakeOwnershipPrivate {
/// optional message length padding
padding: Option<String>,
},
/// add/remove approval(s) that whitelist everyone (makes public)
SetGlobalApproval {
/// optional token id to apply approval/revocation to
token_id: Option<String>,
/// optional permission level for viewing the owner
view_owner: Option<AccessLevel>,
/// optional permission level for viewing private metadata
view_private_metadata: Option<AccessLevel>,
/// optional expiration
expires: Option<Expiration>,
/// optional message length padding
padding: Option<String>,
},
/// add/remove approval(s) for a specific address on the token(s) you own. Any permissions
/// that are omitted will keep the current permission setting for that whitelist address
SetWhitelistedApproval {
/// address being granted/revoked permission
address: HumanAddr,
/// optional token id to apply approval/revocation to
token_id: Option<String>,
/// optional permission level for viewing the owner
view_owner: Option<AccessLevel>,
/// optional permission level for viewing private metadata
view_private_metadata: Option<AccessLevel>,
/// optional permission level for transferring
transfer: Option<AccessLevel>,
/// optional expiration
expires: Option<Expiration>,
/// optional message length padding
padding: Option<String>,
},
}
/// Query messages to be sent to SNIP721 contract. Uses viewing key for cross
/// contract query, rather than permits
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum S721QueryMsg {
/// from snip721 contract
/// display the owner of the specified token if authorized to view it. If the requester
/// is also the token's owner, the response will also include a list of any addresses
/// that can transfer this token. The transfer approval list is for CW721 compliance,
/// but the NftDossier query will be more complete by showing viewing approvals as well
OwnerOf {
token_id: String,
/// optional address and key requesting to view the token owner
viewer: Option<ViewerInfo>,
/// optionally include expired Approvals in the response list. If ommitted or
/// false, expired Approvals will be filtered out of the response
include_expired: Option<bool>,
},
/// displays the private metadata if permitted to view it
PrivateMetadata {
token_id: String,
/// optional address and key requesting to view the private metadata
viewer: Option<ViewerInfo>,
},
/// displays all the information about a token that the viewer has permission to
/// see. This may include the owner, the public metadata, the private metadata, royalty
/// information, mint run information, whether the token is unwrapped, whether the token is
/// transferable, and the token and inventory approvals
NftDossier {
token_id: String,
/// optional address and key requesting to view the token information
viewer: Option<ViewerInfo>,
/// optionally include expired Approvals in the response list. If ommitted or
/// false, expired Approvals will be filtered out of the response
include_expired: Option<bool>,
},
}
impl Query for S721QueryMsg {
const BLOCK_SIZE: usize = RESPONSE_BLOCK_SIZE;
}
/// wrapper to deserialize `PrivateMetadata` responses, with additional implementations
/// /// above the standard implementation in `secret_toolkit`
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct PrivateMetadataResponse {
pub private_metadata: Metadata,
}
/// wrapper to deserialize `NftDossier` responses, with additional implementations
/// above the standard implementation in `secret_toolkit`
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct NftDossierResponse {
pub nft_dossier: NftDossier,
}
/// DAO proposals that an ftoken holder can make. A minimum amount of tokens
/// need to be staked along with proposals
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum Proposal {
/// Proposal to send a message to the underlying NFT
MsgToNft {
msg: AllowedNftMsg,
},
/// Proposals to change the ftoken configuration, which includes auction
/// configurations and DAO configurations
ChangeConfig {
config: FtokenConf,
},
}