use cosmwasm_std::{coin, to_binary, Addr, Binary, Coin, CosmosMsg, StdError, StdResult};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use crate::common::{validate_address, validate_string};
use crate::types::{AttributeValueType, MarkerAccess, MarkerType, NameBinding, ProvenanceRoute};
static MSG_DATAFMT_VERSION: &str = "2.0.0";
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub struct ProvenanceMsg {
pub route: ProvenanceRoute, pub params: ProvenanceMsgParams, pub version: String, }
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub enum ProvenanceMsgParams {
Name(NameMsgParams),
Attribute(AttributeMsgParams),
Marker(MarkerMsgParams),
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum NameMsgParams {
BindName {
name: String,
address: Addr,
restrict: bool,
},
DeleteName {
name: String,
},
}
fn create_name_msg(params: NameMsgParams) -> CosmosMsg<ProvenanceMsg> {
CosmosMsg::Custom(ProvenanceMsg {
route: ProvenanceRoute::Name,
params: ProvenanceMsgParams::Name(params),
version: String::from(MSG_DATAFMT_VERSION),
})
}
pub fn bind_name<S: Into<String>, H: Into<Addr>>(
name: S,
address: H,
binding: NameBinding,
) -> StdResult<CosmosMsg<ProvenanceMsg>> {
Ok(create_name_msg(NameMsgParams::BindName {
name: validate_string(name, "name")?,
address: validate_address(address)?,
restrict: matches!(binding, NameBinding::Restricted),
}))
}
pub fn unbind_name<S: Into<String>>(name: S) -> StdResult<CosmosMsg<ProvenanceMsg>> {
Ok(create_name_msg(NameMsgParams::DeleteName {
name: validate_string(name, "name")?,
}))
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum AttributeMsgParams {
AddAttribute {
address: Addr,
name: String,
value: Binary,
value_type: AttributeValueType,
},
DeleteAttribute {
address: Addr,
name: String,
},
}
fn create_attribute_msg(params: AttributeMsgParams) -> CosmosMsg<ProvenanceMsg> {
CosmosMsg::Custom(ProvenanceMsg {
route: ProvenanceRoute::Attribute,
params: ProvenanceMsgParams::Attribute(params),
version: String::from(MSG_DATAFMT_VERSION),
})
}
pub fn add_attribute<H: Into<Addr>, S: Into<String>, B: Into<Binary>>(
address: H,
name: S,
value: B,
value_type: AttributeValueType,
) -> StdResult<CosmosMsg<ProvenanceMsg>> {
Ok(create_attribute_msg(AttributeMsgParams::AddAttribute {
address: validate_address(address)?,
name: validate_string(name, "name")?,
value: value.into(),
value_type,
}))
}
pub fn add_json_attribute<H: Into<Addr>, S: Into<String>, T: Serialize + ?Sized>(
address: H,
name: S,
data: &T,
) -> StdResult<CosmosMsg<ProvenanceMsg>> {
let value = to_binary(data)?;
add_attribute(address, name, value, AttributeValueType::Json)
}
pub fn delete_attributes<H: Into<Addr>, S: Into<String>>(
address: H,
name: S,
) -> StdResult<CosmosMsg<ProvenanceMsg>> {
Ok(create_attribute_msg(AttributeMsgParams::DeleteAttribute {
address: validate_address(address)?,
name: validate_string(name, "name")?,
}))
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum MarkerMsgParams {
CreateMarker {
coin: Coin,
marker_type: MarkerType,
},
GrantMarkerAccess {
denom: String,
address: Addr,
permissions: Vec<MarkerAccess>,
},
RevokeMarkerAccess {
denom: String,
address: Addr,
},
FinalizeMarker {
denom: String,
},
ActivateMarker {
denom: String,
},
CancelMarker {
denom: String,
},
DestroyMarker {
denom: String,
},
MintMarkerSupply {
coin: Coin,
},
BurnMarkerSupply {
coin: Coin,
},
WithdrawCoins {
marker_denom: String,
coin: Coin,
recipient: Addr,
},
TransferMarkerCoins {
coin: Coin,
to: Addr,
from: Addr,
},
}
fn create_marker_msg(params: MarkerMsgParams) -> CosmosMsg<ProvenanceMsg> {
CosmosMsg::Custom(ProvenanceMsg {
route: ProvenanceRoute::Marker,
params: ProvenanceMsgParams::Marker(params),
version: String::from(MSG_DATAFMT_VERSION),
})
}
pub fn create_marker<S: Into<String>>(
amount: u128,
denom: S,
marker_type: MarkerType,
) -> StdResult<CosmosMsg<ProvenanceMsg>> {
if amount == 0 {
return Err(StdError::generic_err("marker supply must be > 0"));
}
let coin = coin(amount, validate_string(denom, "denom")?);
Ok(create_marker_msg(MarkerMsgParams::CreateMarker {
coin,
marker_type,
}))
}
pub fn grant_marker_access<S: Into<String>, H: Into<Addr>>(
denom: S,
address: H,
permissions: Vec<MarkerAccess>,
) -> StdResult<CosmosMsg<ProvenanceMsg>> {
Ok(create_marker_msg(MarkerMsgParams::GrantMarkerAccess {
denom: validate_string(denom, "denom")?,
address: validate_address(address)?,
permissions,
}))
}
pub fn revoke_marker_access<S: Into<String>, H: Into<Addr>>(
denom: S,
address: H,
) -> StdResult<CosmosMsg<ProvenanceMsg>> {
Ok(create_marker_msg(MarkerMsgParams::RevokeMarkerAccess {
denom: validate_string(denom, "denom")?,
address: validate_address(address)?,
}))
}
pub fn finalize_marker<S: Into<String>>(denom: S) -> StdResult<CosmosMsg<ProvenanceMsg>> {
Ok(create_marker_msg(MarkerMsgParams::FinalizeMarker {
denom: validate_string(denom, "denom")?,
}))
}
pub fn activate_marker<S: Into<String>>(denom: S) -> StdResult<CosmosMsg<ProvenanceMsg>> {
Ok(create_marker_msg(MarkerMsgParams::ActivateMarker {
denom: validate_string(denom, "denom")?,
}))
}
pub fn cancel_marker<S: Into<String>>(denom: S) -> StdResult<CosmosMsg<ProvenanceMsg>> {
Ok(create_marker_msg(MarkerMsgParams::CancelMarker {
denom: validate_string(denom, "denom")?,
}))
}
pub fn destroy_marker<S: Into<String>>(denom: S) -> StdResult<CosmosMsg<ProvenanceMsg>> {
Ok(create_marker_msg(MarkerMsgParams::DestroyMarker {
denom: validate_string(denom, "denom")?,
}))
}
pub fn mint_marker_supply<S: Into<String>>(
amount: u128,
denom: S,
) -> StdResult<CosmosMsg<ProvenanceMsg>> {
if amount == 0 {
return Err(StdError::generic_err("mint amount must be > 0"));
}
let coin = coin(amount, validate_string(denom, "denom")?);
Ok(create_marker_msg(MarkerMsgParams::MintMarkerSupply {
coin,
}))
}
pub fn burn_marker_supply<S: Into<String>>(
amount: u128,
denom: S,
) -> StdResult<CosmosMsg<ProvenanceMsg>> {
if amount == 0 {
return Err(StdError::generic_err("burn amount must be > 0"));
}
let coin = coin(amount, validate_string(denom, "denom")?);
Ok(create_marker_msg(MarkerMsgParams::BurnMarkerSupply {
coin,
}))
}
pub fn withdraw_coins<S: Into<String>, H: Into<Addr>>(
marker_denom: S,
amount: u128,
denom: S,
recipient: H,
) -> StdResult<CosmosMsg<ProvenanceMsg>> {
if amount == 0 {
return Err(StdError::generic_err("withdraw amount must be > 0"));
}
let coin = coin(amount, validate_string(denom, "denom")?);
Ok(create_marker_msg(MarkerMsgParams::WithdrawCoins {
marker_denom: validate_string(marker_denom, "marker_denom")?,
coin,
recipient: validate_address(recipient)?,
}))
}
pub fn transfer_marker_coins<S: Into<String>, H: Into<Addr>>(
amount: u128,
denom: S,
to: H,
from: H,
) -> StdResult<CosmosMsg<ProvenanceMsg>> {
if amount == 0 {
return Err(StdError::generic_err("transfer amount must be > 0"));
}
let coin = coin(amount, validate_string(denom, "denom")?);
let msg = create_marker_msg(MarkerMsgParams::TransferMarkerCoins {
coin,
to: validate_address(to)?,
from: validate_address(from)?,
});
Ok(msg)
}