parent
c34cc4918f
commit
1c86160e16
|
@ -13,20 +13,20 @@ use solana_sdk::{instruction::Instruction, pubkey::Pubkey};
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
||||||
pub struct DateConfig {
|
pub struct DateConfig {
|
||||||
#[serde(with = "ts_seconds")]
|
#[serde(with = "ts_seconds")]
|
||||||
pub dt: DateTime<Utc>,
|
pub date_time: DateTime<Utc>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for DateConfig {
|
impl Default for DateConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
dt: Utc.timestamp(0, 0),
|
date_time: Utc.timestamp(0, 0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl DateConfig {
|
impl DateConfig {
|
||||||
pub fn new(dt: Date<Utc>) -> Self {
|
pub fn new(date: Date<Utc>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
dt: dt.and_hms(0, 0, 0),
|
date_time: date.and_hms(0, 0, 0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ pub fn create_account(
|
||||||
|
|
||||||
/// Set the date in the date account. The account pubkey must be signed in the
|
/// Set the date in the date account. The account pubkey must be signed in the
|
||||||
/// transaction containing this instruction.
|
/// transaction containing this instruction.
|
||||||
pub fn store(date_pubkey: &Pubkey, dt: Date<Utc>) -> Instruction {
|
pub fn store(date_pubkey: &Pubkey, date: Date<Utc>) -> Instruction {
|
||||||
let date_config = DateConfig::new(dt);
|
let date_config = DateConfig::new(date);
|
||||||
config_instruction::store(&date_pubkey, true, vec![], &date_config)
|
config_instruction::store(&date_pubkey, true, vec![], &date_config)
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,8 +89,8 @@ fn initialize_account(
|
||||||
|
|
||||||
pub fn create_account(
|
pub fn create_account(
|
||||||
terminator_pubkey: &Pubkey,
|
terminator_pubkey: &Pubkey,
|
||||||
payee_pubkey: &Pubkey,
|
|
||||||
contract_pubkey: &Pubkey,
|
contract_pubkey: &Pubkey,
|
||||||
|
payee_pubkey: &Pubkey,
|
||||||
start_date: Date<Utc>,
|
start_date: Date<Utc>,
|
||||||
date_pubkey: &Pubkey,
|
date_pubkey: &Pubkey,
|
||||||
lamports: u64,
|
lamports: u64,
|
||||||
|
@ -115,30 +115,30 @@ pub fn create_account(
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_payee(old_payee: &Pubkey, contract: &Pubkey, new_payee: &Pubkey) -> Instruction {
|
pub fn set_payee(contract: &Pubkey, old_payee: &Pubkey, new_payee: &Pubkey) -> Instruction {
|
||||||
let account_metas = vec![
|
let account_metas = vec![
|
||||||
AccountMeta::new(*old_payee, true),
|
|
||||||
AccountMeta::new(*contract, false),
|
AccountMeta::new(*contract, false),
|
||||||
|
AccountMeta::new(*old_payee, true),
|
||||||
];
|
];
|
||||||
Instruction::new(id(), &VestInstruction::SetPayee(*new_payee), account_metas)
|
Instruction::new(id(), &VestInstruction::SetPayee(*new_payee), account_metas)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn terminate(from: &Pubkey, contract: &Pubkey, to: &Pubkey) -> Instruction {
|
pub fn redeem_tokens(contract: &Pubkey, date_pubkey: &Pubkey, to: &Pubkey) -> Instruction {
|
||||||
let mut account_metas = vec![
|
let account_metas = vec![
|
||||||
AccountMeta::new(*from, true),
|
|
||||||
AccountMeta::new(*contract, false),
|
AccountMeta::new(*contract, false),
|
||||||
|
AccountMeta::new_credit_only(*date_pubkey, false),
|
||||||
|
AccountMeta::new_credit_only(*to, false),
|
||||||
|
];
|
||||||
|
Instruction::new(id(), &VestInstruction::RedeemTokens, account_metas)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn terminate(contract: &Pubkey, from: &Pubkey, to: &Pubkey) -> Instruction {
|
||||||
|
let mut account_metas = vec![
|
||||||
|
AccountMeta::new(*contract, false),
|
||||||
|
AccountMeta::new(*from, true),
|
||||||
];
|
];
|
||||||
if from != to {
|
if from != to {
|
||||||
account_metas.push(AccountMeta::new_credit_only(*to, false));
|
account_metas.push(AccountMeta::new_credit_only(*to, false));
|
||||||
}
|
}
|
||||||
Instruction::new(id(), &VestInstruction::Terminate, account_metas)
|
Instruction::new(id(), &VestInstruction::Terminate, account_metas)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn redeem_tokens(date_pubkey: &Pubkey, contract: &Pubkey, to: &Pubkey) -> Instruction {
|
|
||||||
let account_metas = vec![
|
|
||||||
AccountMeta::new_credit_only(*date_pubkey, false),
|
|
||||||
AccountMeta::new(*contract, false),
|
|
||||||
AccountMeta::new_credit_only(*to, false),
|
|
||||||
];
|
|
||||||
Instruction::new(id(), &VestInstruction::RedeemTokens, account_metas)
|
|
||||||
}
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ fn parse_date_account(
|
||||||
let date_config =
|
let date_config =
|
||||||
deserialize::<DateConfig>(config_data).map_err(|_| InstructionError::InvalidAccountData)?;
|
deserialize::<DateConfig>(config_data).map_err(|_| InstructionError::InvalidAccountData)?;
|
||||||
|
|
||||||
Ok(date_config.dt.date())
|
Ok(date_config.date_time.date())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_account<'a>(
|
fn parse_account<'a>(
|
||||||
|
@ -80,7 +80,7 @@ pub fn process_instruction(
|
||||||
vest_state.serialize(&mut contract_account.data)
|
vest_state.serialize(&mut contract_account.data)
|
||||||
}
|
}
|
||||||
VestInstruction::SetPayee(payee_pubkey) => {
|
VestInstruction::SetPayee(payee_pubkey) => {
|
||||||
let (old_payee_keyed_account, contract_keyed_account) = match keyed_accounts {
|
let (contract_keyed_account, old_payee_keyed_account) = match keyed_accounts {
|
||||||
[ka0, ka1] => (ka0, ka1),
|
[ka0, ka1] => (ka0, ka1),
|
||||||
_ => return Err(InstructionError::InvalidArgument),
|
_ => return Err(InstructionError::InvalidArgument),
|
||||||
};
|
};
|
||||||
|
@ -91,7 +91,7 @@ pub fn process_instruction(
|
||||||
vest_state.serialize(&mut contract_account.data)
|
vest_state.serialize(&mut contract_account.data)
|
||||||
}
|
}
|
||||||
VestInstruction::RedeemTokens => {
|
VestInstruction::RedeemTokens => {
|
||||||
let (date_keyed_account, contract_keyed_account, payee_keyed_account) =
|
let (contract_keyed_account, date_keyed_account, payee_keyed_account) =
|
||||||
match keyed_accounts {
|
match keyed_accounts {
|
||||||
[ka0, ka1, ka2] => (ka0, ka1, ka2),
|
[ka0, ka1, ka2] => (ka0, ka1, ka2),
|
||||||
_ => return Err(InstructionError::InvalidArgument),
|
_ => return Err(InstructionError::InvalidArgument),
|
||||||
|
@ -101,11 +101,11 @@ pub fn process_instruction(
|
||||||
let current_date = parse_date_account(date_keyed_account, &vest_state.date_pubkey)?;
|
let current_date = parse_date_account(date_keyed_account, &vest_state.date_pubkey)?;
|
||||||
let payee_account = parse_account(payee_keyed_account, &vest_state.payee_pubkey)?;
|
let payee_account = parse_account(payee_keyed_account, &vest_state.payee_pubkey)?;
|
||||||
|
|
||||||
vest_state.redeem_tokens(current_date, contract_account, payee_account);
|
vest_state.redeem_tokens(contract_account, current_date, payee_account);
|
||||||
vest_state.serialize(&mut contract_account.data)
|
vest_state.serialize(&mut contract_account.data)
|
||||||
}
|
}
|
||||||
VestInstruction::Terminate => {
|
VestInstruction::Terminate => {
|
||||||
let (terminator_keyed_account, contract_keyed_account, payee_keyed_account) =
|
let (contract_keyed_account, terminator_keyed_account, payee_keyed_account) =
|
||||||
match keyed_accounts {
|
match keyed_accounts {
|
||||||
[ka0, ka1] => (ka0, ka1, None),
|
[ka0, ka1] => (ka0, ka1, None),
|
||||||
[ka0, ka1, ka2] => (ka0, ka1, Some(ka2)),
|
[ka0, ka1, ka2] => (ka0, ka1, Some(ka2)),
|
||||||
|
@ -161,15 +161,15 @@ mod tests {
|
||||||
/// Create a config account and use it as a date oracle.
|
/// Create a config account and use it as a date oracle.
|
||||||
fn create_date_account(
|
fn create_date_account(
|
||||||
bank_client: &BankClient,
|
bank_client: &BankClient,
|
||||||
payer_keypair: &Keypair,
|
|
||||||
date_keypair: &Keypair,
|
date_keypair: &Keypair,
|
||||||
dt: Date<Utc>,
|
payer_keypair: &Keypair,
|
||||||
|
date: Date<Utc>,
|
||||||
) -> Result<Signature, TransportError> {
|
) -> Result<Signature, TransportError> {
|
||||||
let date_pubkey = date_keypair.pubkey();
|
let date_pubkey = date_keypair.pubkey();
|
||||||
|
|
||||||
let mut instructions =
|
let mut instructions =
|
||||||
date_instruction::create_account(&payer_keypair.pubkey(), &date_pubkey, 1);
|
date_instruction::create_account(&payer_keypair.pubkey(), &date_pubkey, 1);
|
||||||
instructions.push(date_instruction::store(&date_pubkey, dt));
|
instructions.push(date_instruction::store(&date_pubkey, date));
|
||||||
|
|
||||||
let message = Message::new(instructions);
|
let message = Message::new(instructions);
|
||||||
bank_client.send_message(&[&payer_keypair, &date_keypair], message)
|
bank_client.send_message(&[&payer_keypair, &date_keypair], message)
|
||||||
|
@ -177,29 +177,29 @@ mod tests {
|
||||||
|
|
||||||
fn store_date(
|
fn store_date(
|
||||||
bank_client: &BankClient,
|
bank_client: &BankClient,
|
||||||
payer_keypair: &Keypair,
|
|
||||||
date_keypair: &Keypair,
|
date_keypair: &Keypair,
|
||||||
dt: Date<Utc>,
|
payer_keypair: &Keypair,
|
||||||
|
date: Date<Utc>,
|
||||||
) -> Result<Signature, TransportError> {
|
) -> Result<Signature, TransportError> {
|
||||||
let date_pubkey = date_keypair.pubkey();
|
let date_pubkey = date_keypair.pubkey();
|
||||||
let instruction = date_instruction::store(&date_pubkey, dt);
|
let instruction = date_instruction::store(&date_pubkey, date);
|
||||||
let message = Message::new_with_payer(vec![instruction], Some(&payer_keypair.pubkey()));
|
let message = Message::new_with_payer(vec![instruction], Some(&payer_keypair.pubkey()));
|
||||||
bank_client.send_message(&[&payer_keypair, &date_keypair], message)
|
bank_client.send_message(&[&payer_keypair, &date_keypair], message)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_vest_account(
|
fn create_vest_account(
|
||||||
bank_client: &BankClient,
|
bank_client: &BankClient,
|
||||||
|
contract_pubkey: &Pubkey,
|
||||||
payer_keypair: &Keypair,
|
payer_keypair: &Keypair,
|
||||||
payee_pubkey: &Pubkey,
|
payee_pubkey: &Pubkey,
|
||||||
contract_pubkey: &Pubkey,
|
|
||||||
start_date: Date<Utc>,
|
start_date: Date<Utc>,
|
||||||
date_pubkey: &Pubkey,
|
date_pubkey: &Pubkey,
|
||||||
lamports: u64,
|
lamports: u64,
|
||||||
) -> Result<Signature, TransportError> {
|
) -> Result<Signature, TransportError> {
|
||||||
let instructions = vest_instruction::create_account(
|
let instructions = vest_instruction::create_account(
|
||||||
&payer_keypair.pubkey(),
|
&payer_keypair.pubkey(),
|
||||||
&payee_pubkey,
|
|
||||||
&contract_pubkey,
|
&contract_pubkey,
|
||||||
|
&payee_pubkey,
|
||||||
start_date,
|
start_date,
|
||||||
&date_pubkey,
|
&date_pubkey,
|
||||||
lamports,
|
lamports,
|
||||||
|
@ -210,13 +210,13 @@ mod tests {
|
||||||
|
|
||||||
fn send_set_payee(
|
fn send_set_payee(
|
||||||
bank_client: &BankClient,
|
bank_client: &BankClient,
|
||||||
old_payee_keypair: &Keypair,
|
|
||||||
contract_pubkey: &Pubkey,
|
contract_pubkey: &Pubkey,
|
||||||
|
old_payee_keypair: &Keypair,
|
||||||
new_payee_pubkey: &Pubkey,
|
new_payee_pubkey: &Pubkey,
|
||||||
) -> Result<Signature, TransportError> {
|
) -> Result<Signature, TransportError> {
|
||||||
let instruction = vest_instruction::set_payee(
|
let instruction = vest_instruction::set_payee(
|
||||||
&old_payee_keypair.pubkey(),
|
|
||||||
&contract_pubkey,
|
&contract_pubkey,
|
||||||
|
&old_payee_keypair.pubkey(),
|
||||||
&new_payee_pubkey,
|
&new_payee_pubkey,
|
||||||
);
|
);
|
||||||
bank_client.send_instruction(&old_payee_keypair, instruction)
|
bank_client.send_instruction(&old_payee_keypair, instruction)
|
||||||
|
@ -224,13 +224,13 @@ mod tests {
|
||||||
|
|
||||||
fn send_redeem_tokens(
|
fn send_redeem_tokens(
|
||||||
bank_client: &BankClient,
|
bank_client: &BankClient,
|
||||||
|
contract_pubkey: &Pubkey,
|
||||||
payer_keypair: &Keypair,
|
payer_keypair: &Keypair,
|
||||||
payee_pubkey: &Pubkey,
|
payee_pubkey: &Pubkey,
|
||||||
contract_pubkey: &Pubkey,
|
|
||||||
date_pubkey: &Pubkey,
|
date_pubkey: &Pubkey,
|
||||||
) -> Result<Signature, TransportError> {
|
) -> Result<Signature, TransportError> {
|
||||||
let instruction =
|
let instruction =
|
||||||
vest_instruction::redeem_tokens(&date_pubkey, &contract_pubkey, &payee_pubkey);
|
vest_instruction::redeem_tokens(&contract_pubkey, &date_pubkey, &payee_pubkey);
|
||||||
let message = Message::new_with_payer(vec![instruction], Some(&payer_keypair.pubkey()));
|
let message = Message::new_with_payer(vec![instruction], Some(&payer_keypair.pubkey()));
|
||||||
bank_client.send_message(&[&payer_keypair], message)
|
bank_client.send_message(&[&payer_keypair], message)
|
||||||
}
|
}
|
||||||
|
@ -321,9 +321,9 @@ mod tests {
|
||||||
|
|
||||||
create_vest_account(
|
create_vest_account(
|
||||||
&bank_client,
|
&bank_client,
|
||||||
|
&contract_pubkey,
|
||||||
&alice_keypair,
|
&alice_keypair,
|
||||||
&bob_pubkey,
|
&bob_pubkey,
|
||||||
&contract_pubkey,
|
|
||||||
start_date,
|
start_date,
|
||||||
&date_pubkey,
|
&date_pubkey,
|
||||||
36,
|
36,
|
||||||
|
@ -340,8 +340,8 @@ mod tests {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
send_set_payee(
|
send_set_payee(
|
||||||
&bank_client,
|
&bank_client,
|
||||||
&mallory_keypair,
|
|
||||||
&contract_pubkey,
|
&contract_pubkey,
|
||||||
|
&mallory_keypair,
|
||||||
&new_bob_pubkey,
|
&new_bob_pubkey,
|
||||||
)
|
)
|
||||||
.unwrap_err();
|
.unwrap_err();
|
||||||
|
@ -352,8 +352,8 @@ mod tests {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
send_set_payee(
|
send_set_payee(
|
||||||
&bank_client,
|
&bank_client,
|
||||||
&bob_keypair,
|
|
||||||
&contract_pubkey,
|
&contract_pubkey,
|
||||||
|
&bob_keypair,
|
||||||
&new_bob_pubkey,
|
&new_bob_pubkey,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -370,7 +370,7 @@ mod tests {
|
||||||
let date_pubkey = date_keypair.pubkey();
|
let date_pubkey = date_keypair.pubkey();
|
||||||
|
|
||||||
let current_date = Utc.ymd(2019, 1, 1);
|
let current_date = Utc.ymd(2019, 1, 1);
|
||||||
create_date_account(&bank_client, &alice_keypair, &date_keypair, current_date).unwrap();
|
create_date_account(&bank_client, &date_keypair, &alice_keypair, current_date).unwrap();
|
||||||
|
|
||||||
let contract_pubkey = Pubkey::new_rand();
|
let contract_pubkey = Pubkey::new_rand();
|
||||||
let bob_pubkey = Pubkey::new_rand();
|
let bob_pubkey = Pubkey::new_rand();
|
||||||
|
@ -378,9 +378,9 @@ mod tests {
|
||||||
|
|
||||||
create_vest_account(
|
create_vest_account(
|
||||||
&bank_client,
|
&bank_client,
|
||||||
|
&contract_pubkey,
|
||||||
&alice_keypair,
|
&alice_keypair,
|
||||||
&bob_pubkey,
|
&bob_pubkey,
|
||||||
&contract_pubkey,
|
|
||||||
start_date,
|
start_date,
|
||||||
&date_pubkey,
|
&date_pubkey,
|
||||||
36,
|
36,
|
||||||
|
@ -391,9 +391,9 @@ mod tests {
|
||||||
|
|
||||||
send_redeem_tokens(
|
send_redeem_tokens(
|
||||||
&bank_client,
|
&bank_client,
|
||||||
|
&contract_pubkey,
|
||||||
&alice_keypair,
|
&alice_keypair,
|
||||||
&bob_pubkey,
|
&bob_pubkey,
|
||||||
&contract_pubkey,
|
|
||||||
&date_pubkey,
|
&date_pubkey,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -404,8 +404,8 @@ mod tests {
|
||||||
// Update the date oracle and redeem more tokens
|
// Update the date oracle and redeem more tokens
|
||||||
store_date(
|
store_date(
|
||||||
&bank_client,
|
&bank_client,
|
||||||
&alice_keypair,
|
|
||||||
&date_keypair,
|
&date_keypair,
|
||||||
|
&alice_keypair,
|
||||||
Utc.ymd(2019, 2, 1),
|
Utc.ymd(2019, 2, 1),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -417,9 +417,9 @@ mod tests {
|
||||||
|
|
||||||
send_redeem_tokens(
|
send_redeem_tokens(
|
||||||
&bank_client,
|
&bank_client,
|
||||||
|
&contract_pubkey,
|
||||||
&alice_keypair,
|
&alice_keypair,
|
||||||
&bob_pubkey,
|
&bob_pubkey,
|
||||||
&contract_pubkey,
|
|
||||||
&date_pubkey,
|
&date_pubkey,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -440,13 +440,13 @@ mod tests {
|
||||||
let date_pubkey = date_keypair.pubkey();
|
let date_pubkey = date_keypair.pubkey();
|
||||||
|
|
||||||
let current_date = Utc.ymd(2019, 1, 1);
|
let current_date = Utc.ymd(2019, 1, 1);
|
||||||
create_date_account(&bank_client, &alice_keypair, &date_keypair, current_date).unwrap();
|
create_date_account(&bank_client, &date_keypair, &alice_keypair, current_date).unwrap();
|
||||||
|
|
||||||
create_vest_account(
|
create_vest_account(
|
||||||
&bank_client,
|
&bank_client,
|
||||||
|
&contract_pubkey,
|
||||||
&alice_keypair,
|
&alice_keypair,
|
||||||
&bob_pubkey,
|
&bob_pubkey,
|
||||||
&contract_pubkey,
|
|
||||||
start_date,
|
start_date,
|
||||||
&date_pubkey,
|
&date_pubkey,
|
||||||
1,
|
1,
|
||||||
|
@ -458,7 +458,7 @@ mod tests {
|
||||||
// Now, terminate the transaction. alice gets her funds back
|
// Now, terminate the transaction. alice gets her funds back
|
||||||
// Note: that tokens up until the oracle date are *not* redeemed automatically.
|
// Note: that tokens up until the oracle date are *not* redeemed automatically.
|
||||||
let instruction =
|
let instruction =
|
||||||
vest_instruction::terminate(&alice_pubkey, &contract_pubkey, &alice_pubkey);
|
vest_instruction::terminate(&contract_pubkey, &alice_pubkey, &alice_pubkey);
|
||||||
bank_client
|
bank_client
|
||||||
.send_instruction(&alice_keypair, instruction)
|
.send_instruction(&alice_keypair, instruction)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
@ -56,8 +56,8 @@ impl VestState {
|
||||||
/// Redeem vested tokens.
|
/// Redeem vested tokens.
|
||||||
pub fn redeem_tokens(
|
pub fn redeem_tokens(
|
||||||
&mut self,
|
&mut self,
|
||||||
current_date: Date<Utc>,
|
|
||||||
contract_account: &mut Account,
|
contract_account: &mut Account,
|
||||||
|
current_date: Date<Utc>,
|
||||||
payee_account: &mut Account,
|
payee_account: &mut Account,
|
||||||
) {
|
) {
|
||||||
let schedule = create_vesting_schedule(self.start_date_time.date(), self.total_lamports);
|
let schedule = create_vesting_schedule(self.start_date_time.date(), self.total_lamports);
|
||||||
|
|
Loading…
Reference in New Issue