I’ve added schema-embed but still can’t pass parameter on init func, following is my code.
// /// The human-readable description of a voting option.
// pub type VotingOption = String;
/// The voting options are stored in a vector. The vector index is used to refer
/// to a specific voting option.
/// Number of holder.
pub type TotalHolders = u32;
/// single holder amount
pub type TotalHolderAmount = u64;
/// The parameter type for the contract function `init`.
/// Takes a description, the voting options, and the `end_time` to start the
/// election.
#[derive(Serialize, SchemaType)]
pub struct InitParameter {
pub end_time: Timestamp,
}
/// The contract state
#[derive(Serialize, Clone)]
struct State {
/// The map connects a voter to the index of the voted-for voting option.
pub holders: BTreeMap<AccountAddress, Amount>,
/// The last timestamp that an account can vote.
/// The election is open from the point in time that this smart contract is
/// initialized until the `end_time`.
end_time: Timestamp,
total_holders: TotalHolders,
}
#[derive(Serialize, SchemaType)]
pub struct VestingView {
/// The last timestamp that an account can vote.
/// The election is open from the point in time that this smart contract is
/// initialized until the `end_time`.
pub end_time: Timestamp,
/// The map connects the index of a voting option to the number of votes
/// it received so far.
pub holders: BTreeMap<AccountAddress, Amount>,
pub total_holders: TotalHolders,
pub current_balance: Amount
}
/// The different errors that the `vote` function can produce.
#[derive(Reject, Serialize, PartialEq, Eq, Debug, SchemaType)]
pub enum VotingError {
/// Raised when parsing the parameter failed.
#[from(ParseError)]
ParsingFailed,
/// Raised when the vote is placed after the election has ended.
VestingFinished,
/// Raised when voting for a voting option that does not exist.
InvalidVotingOption,
/// Raised when a smart contract tries to participate in the election. Only
/// accounts are allowed to vote.
ContractVoter,
}
pub type VestingResult<T> = Result<T, VotingError>;
// Contract functions
/// Initialize the contract instance and start the vesting.
/// end_time
#[init(contract = "vesting", parameter = "InitParameter")]
fn init<S: HasStateApi>(
ctx: &impl HasInitContext,
_state_builder: &mut StateBuilder<S>,
) -> InitResult<State> {
// Parse the parameter.
let param: InitParameter = ctx.parameter_cursor().get()?;
// Set the state.
Ok(State {
holders: BTreeMap::new(),
end_time: param.end_time,
total_holders: 0,
})
}
/// Enables accounts to vote for a specific voting option. Each account can
/// change its selected voting option with this function as often as it desires
/// until the `end_time` is reached.
///
/// It rejects if:
/// - It fails to parse the parameter.
/// - A contract tries to vote.
/// - It is past the `end_time`.
#[receive(
contract = "vesting",
name = "vest",
mutable,
payable,
error = "VotingError"
)]
fn vest<S: HasStateApi>(
ctx: &impl HasReceiveContext,
host: &mut impl HasHost<State, StateApiType = S>,
_amount: Amount,
) -> VestingResult<()> {
// Check that the election hasn't finished yet.
if ctx.metadata().slot_time() > host.state().end_time {
return Err(VotingError::VestingFinished);
}
// Ensure that the sender is an account.
let acc = match ctx.sender() {
Address::Account(acc) => acc,
Address::Contract(_) => return Err(VotingError::ContractVoter),
};
host.state_mut().total_holders += 1;
// Insert or replace the vote for the account.
host.state_mut()
.holders
.entry(acc)
.and_modify(|current_balance| *current_balance += _amount)
.or_insert(_amount);
Ok(())
}
#[receive(contract = "vesting", name = "view")]
fn vesting_info<S: HasStateApi>(
_ctx: &impl HasReceiveContext,
host: &impl HasHost<State, StateApiType = S>,
) -> ReceiveResult<VestingView> {
let holders = host.state().holders.clone();
let total_holders = host.state().total_holders.clone();
let end_time = host.state().end_time;
let current_balance = host.self_balance(); // read current balance
Ok(VestingView {
holders,
total_holders,
end_time,
current_balance,
})
}```