Struct clockwork_network_program::state::Delegation
source · pub struct Delegation {
pub authority: Pubkey,
pub id: u64,
pub stake_amount: u64,
pub worker: Pubkey,
pub yield_balance: u64,
}
Expand description
An account to manage a token holder’s stake delegation with a particiular a worker.
Fields§
The authority of this delegation account.
id: u64
The id of this delegation (auto-incrementing integer relative to worker)
stake_amount: u64
The number of delegated tokens currently locked with the worker.
worker: Pubkey
The worker to delegate stake to.
yield_balance: u64
The number of lamports claimable as yield by the authority.
Implementations§
source§impl Delegation
impl Delegation
sourcepub fn pubkey(worker: Pubkey, id: u64) -> Pubkey
pub fn pubkey(worker: Pubkey, id: u64) -> Pubkey
Examples found in repository?
More examples
src/instructions/worker_delegations_stake.rs (line 36)
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
pub fn handler(ctx: Context<WorkerStakeDelegations>) -> Result<ThreadResponse> {
// Get accounts.
let config = &ctx.accounts.config;
let registry = &ctx.accounts.registry;
let thread = &ctx.accounts.thread;
let worker = &ctx.accounts.worker;
// Build the next instruction for the thread.
let next_instruction = if worker.total_delegations.gt(&0) {
// This worker has delegations. Stake their deposits.
let delegation_pubkey = Delegation::pubkey(worker.key(), 0);
Some(InstructionData {
program_id: crate::ID,
accounts: vec![
AccountMetaData::new_readonly(config.key(), false),
AccountMetaData::new(delegation_pubkey, false),
AccountMetaData::new(
get_associated_token_address(&delegation_pubkey, &config.mint),
false,
),
AccountMetaData::new_readonly(registry.key(), false),
AccountMetaData::new_readonly(thread.key(), true),
AccountMetaData::new_readonly(anchor_spl::token::ID, false),
AccountMetaData::new_readonly(worker.key(), false),
AccountMetaData::new(
get_associated_token_address(&worker.key(), &config.mint),
false,
),
],
data: anchor_sighash("delegation_stake").to_vec(),
})
} else if worker
.id
.checked_add(1)
.unwrap()
.lt(®istry.total_workers)
{
// This worker has no delegations. Move on to the next worker.
Some(InstructionData {
program_id: crate::ID,
accounts: vec![
AccountMetaData::new_readonly(config.key(), false),
AccountMetaData::new_readonly(registry.key(), false),
AccountMetaData::new_readonly(thread.key(), true),
AccountMetaData::new_readonly(
Worker::pubkey(worker.id.checked_add(1).unwrap()),
false,
),
],
data: anchor_sighash("worker_delegations_stake").to_vec(),
})
} else {
// This worker has no delegations and it is the last worker. Move on to the snapshot job!
Some(InstructionData {
program_id: crate::ID,
accounts: vec![
AccountMetaData::new_readonly(config.key(), false),
AccountMetaData::new(clockwork_utils::PAYER_PUBKEY, true),
AccountMetaData::new_readonly(registry.key(), false),
AccountMetaData::new(
Snapshot::pubkey(registry.current_epoch.checked_add(1).unwrap()),
false,
),
AccountMetaData::new_readonly(system_program::ID, false),
AccountMetaData::new_readonly(thread.key(), true),
],
data: anchor_sighash("snapshot_create").to_vec(),
})
};
Ok(ThreadResponse {
next_instruction,
..ThreadResponse::default()
})
}
src/instructions/snapshot_frame_create.rs (line 97)
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
pub fn handler(ctx: Context<SnapshotFrameCreate>) -> Result<ThreadResponse> {
// Get accounts.
let config = &ctx.accounts.config;
let registry = &ctx.accounts.registry;
let snapshot = &mut ctx.accounts.snapshot;
let snapshot_frame = &mut ctx.accounts.snapshot_frame;
let system_program = &ctx.accounts.system_program;
let thread = &ctx.accounts.thread;
let worker = &ctx.accounts.worker;
let worker_stake = &ctx.accounts.worker_stake;
// Initialize snapshot frame account.
snapshot_frame.init(
snapshot.total_frames,
snapshot.key(),
worker_stake.amount,
snapshot.total_stake,
worker.key(),
)?;
// Update snapshot total workers.
snapshot.total_stake = snapshot
.total_stake
.checked_add(worker_stake.amount)
.unwrap();
snapshot.total_frames = snapshot.total_frames.checked_add(1).unwrap();
// Build the next instruction for the thread.
let next_instruction = if worker.total_delegations.gt(&0) {
// This worker has delegations. Create a snapshot entry for each delegation associated with this worker.
let zeroth_delegation_pubkey = Delegation::pubkey(worker.pubkey(), 0);
let zeroth_snapshot_entry_pubkey = SnapshotEntry::pubkey(snapshot_frame.key(), 0);
Some(InstructionData {
program_id: crate::ID,
accounts: vec![
AccountMetaData::new_readonly(config.key(), false),
AccountMetaData::new_readonly(zeroth_delegation_pubkey, false),
AccountMetaData::new(clockwork_utils::PAYER_PUBKEY, true),
AccountMetaData::new_readonly(registry.key(), false),
AccountMetaData::new_readonly(snapshot.key(), false),
AccountMetaData::new(zeroth_snapshot_entry_pubkey, false),
AccountMetaData::new(snapshot_frame.key(), false),
AccountMetaData::new_readonly(system_program.key(), false),
AccountMetaData::new_readonly(thread.key(), true),
AccountMetaData::new_readonly(worker.key(), false),
],
data: anchor_sighash("snapshot_entry_create").to_vec(),
})
} else if snapshot.total_frames.lt(®istry.total_workers) {
// This worker has no delegations. Create a snapshot frame for the next worker.
let next_snapshot_frame_pubkey =
SnapshotFrame::pubkey(snapshot.key(), snapshot_frame.id.checked_add(1).unwrap());
let next_worker_pubkey = Worker::pubkey(worker.id.checked_add(1).unwrap());
Some(InstructionData {
program_id: crate::ID,
accounts: vec![
AccountMetaData::new_readonly(config.key(), false),
AccountMetaData::new(clockwork_utils::PAYER_PUBKEY, true),
AccountMetaData::new_readonly(registry.key(), false),
AccountMetaData::new(snapshot.key(), false),
AccountMetaData::new(next_snapshot_frame_pubkey, false),
AccountMetaData::new_readonly(system_program.key(), false),
AccountMetaData::new_readonly(thread.key(), true),
AccountMetaData::new_readonly(next_worker_pubkey, false),
AccountMetaData::new_readonly(
get_associated_token_address(&next_worker_pubkey, &config.mint),
false,
),
],
data: anchor_sighash("snapshot_frame_create").to_vec(),
})
} else {
// This worker has no delegations and this is the last frame, so the snapshot is done. Cutover to the next epoch!
Some(InstructionData {
program_id: crate::ID,
accounts: vec![
AccountMetaData::new_readonly(config.key(), false),
AccountMetaData::new(registry.key(), false),
AccountMetaData::new_readonly(thread.key(), true),
],
data: anchor_sighash("registry_epoch_cutover").to_vec(),
})
};
Ok(ThreadResponse {
next_instruction,
..ThreadResponse::default()
})
}
src/instructions/snapshot_entry_create.rs (line 102)
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
pub fn handler(ctx: Context<SnapshotEntryCreate>) -> Result<ThreadResponse> {
// Get accounts.
let config = &ctx.accounts.config;
let delegation = &ctx.accounts.delegation;
let registry = &ctx.accounts.registry;
let snapshot = &mut ctx.accounts.snapshot;
let snapshot_entry = &mut ctx.accounts.snapshot_entry;
let snapshot_frame = &mut ctx.accounts.snapshot_frame;
let system_program = &ctx.accounts.system_program;
let thread = &ctx.accounts.thread;
let worker = &ctx.accounts.worker;
// Initialize snapshot entry account.
snapshot_entry.init(
delegation.key(),
snapshot_frame.total_entries,
snapshot_frame.key(),
delegation.stake_amount,
)?;
// Update the snapshot frame.
snapshot_frame.total_entries = snapshot_frame.total_entries.checked_add(1).unwrap();
// Build the next instruction for the thread.
let next_instruction = if snapshot_frame.total_entries.lt(&worker.total_delegations) {
// Create a snapshot entry for the next delegation.
let next_delegation_pubkey =
Delegation::pubkey(worker.pubkey(), delegation.id.checked_add(1).unwrap());
let next_snapshot_entry_pubkey = SnapshotEntry::pubkey(
snapshot_frame.key(),
snapshot_entry.id.checked_add(1).unwrap(),
);
Some(InstructionData {
program_id: crate::ID,
accounts: vec![
AccountMetaData::new_readonly(config.key(), false),
AccountMetaData::new_readonly(next_delegation_pubkey, false),
AccountMetaData::new(clockwork_utils::PAYER_PUBKEY, true),
AccountMetaData::new_readonly(thread.key(), true),
AccountMetaData::new_readonly(registry.key(), false),
AccountMetaData::new_readonly(snapshot.key(), false),
AccountMetaData::new(next_snapshot_entry_pubkey, false),
AccountMetaData::new(snapshot_frame.key(), false),
AccountMetaData::new_readonly(system_program.key(), false),
AccountMetaData::new_readonly(worker.key(), false),
],
data: anchor_sighash("snapshot_entry_create").to_vec(),
})
} else if snapshot.total_frames.lt(®istry.total_workers) {
// This frame has captured all its entries. Create a frame for the next worker.
let next_snapshot_frame_pubkey =
SnapshotFrame::pubkey(snapshot.key(), snapshot_frame.id.checked_add(1).unwrap());
let next_worker_pubkey = Worker::pubkey(worker.id.checked_add(1).unwrap());
Some(InstructionData {
program_id: crate::ID,
accounts: vec![
AccountMetaData::new_readonly(config.key(), false),
AccountMetaData::new(clockwork_utils::PAYER_PUBKEY, true),
AccountMetaData::new_readonly(registry.key(), false),
AccountMetaData::new(snapshot.key(), false),
AccountMetaData::new(next_snapshot_frame_pubkey, false),
AccountMetaData::new_readonly(system_program.key(), false),
AccountMetaData::new_readonly(thread.key(), true),
AccountMetaData::new_readonly(next_worker_pubkey, false),
AccountMetaData::new_readonly(
get_associated_token_address(&next_worker_pubkey, &config.mint),
false,
),
],
data: anchor_sighash("snapshot_frame_create").to_vec(),
})
} else {
// All entries in this frame have been captured, and it is the last frame. The snapshot is done!
Some(InstructionData {
program_id: crate::ID,
accounts: vec![
AccountMetaData::new_readonly(config.key(), false),
AccountMetaData::new(registry.key(), false),
AccountMetaData::new_readonly(thread.key(), true),
],
data: anchor_sighash("registry_epoch_cutover").to_vec(),
})
};
Ok(ThreadResponse {
next_instruction,
..ThreadResponse::default()
})
}
src/instructions/delegation_stake.rs (line 100)
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
pub fn handler(ctx: Context<DelegationStake>) -> Result<ThreadResponse> {
// Get accounts.
let config = &ctx.accounts.config;
let delegation = &mut ctx.accounts.delegation;
let delegation_stake = &mut ctx.accounts.delegation_stake;
let registry = &ctx.accounts.registry;
let thread = &ctx.accounts.thread;
let token_program = &ctx.accounts.token_program;
let worker = &ctx.accounts.worker;
let worker_stake = &ctx.accounts.worker_stake;
// Transfer tokens from delegation to worker account.
let amount = delegation_stake.amount;
let bump = *ctx.bumps.get("delegation").unwrap();
transfer(
CpiContext::new_with_signer(
token_program.to_account_info(),
Transfer {
from: delegation_stake.to_account_info(),
to: worker_stake.to_account_info(),
authority: delegation.to_account_info(),
},
&[&[
SEED_DELEGATION,
delegation.worker.as_ref(),
delegation.id.to_be_bytes().as_ref(),
&[bump],
]],
),
amount,
)?;
// Update the delegation's stake amount.
delegation.stake_amount = delegation.stake_amount.checked_add(amount).unwrap();
// Build next instruction for the thread.
let next_instruction = if delegation
.id
.checked_add(1)
.unwrap()
.lt(&worker.total_delegations)
{
// This worker has more delegations, continue locking their stake.
let next_delegation_pubkey =
Delegation::pubkey(worker.key(), delegation.id.checked_add(1).unwrap());
Some(InstructionData {
program_id: crate::ID,
accounts: vec![
AccountMetaData::new_readonly(config.key(), false),
AccountMetaData::new(next_delegation_pubkey, false),
AccountMetaData::new(
get_associated_token_address(&next_delegation_pubkey, &config.mint),
false,
),
AccountMetaData::new_readonly(registry.key(), false),
AccountMetaData::new_readonly(thread.key(), true),
AccountMetaData::new_readonly(token_program.key(), false),
AccountMetaData::new_readonly(worker.key(), false),
AccountMetaData::new(worker_stake.key(), false),
],
data: anchor_sighash("delegation_stake").to_vec(),
})
} else if worker
.id
.checked_add(1)
.unwrap()
.lt(®istry.total_workers)
{
// This worker has no more delegations, move on to the next worker.
Some(InstructionData {
program_id: crate::ID,
accounts: vec![
AccountMetaData::new_readonly(config.key(), false),
AccountMetaData::new_readonly(registry.key(), false),
AccountMetaData::new_readonly(thread.key(), true),
AccountMetaData::new_readonly(
Worker::pubkey(worker.id.checked_add(1).unwrap()),
false,
),
],
data: anchor_sighash("worker_delegations_stake").to_vec(),
})
} else {
// This worker has no more delegations and it is the last worker. Start the snapshot!
Some(InstructionData {
program_id: crate::ID,
accounts: vec![
AccountMetaData::new_readonly(config.key(), false),
AccountMetaData::new(clockwork_utils::PAYER_PUBKEY, true),
AccountMetaData::new_readonly(registry.key(), false),
AccountMetaData::new(
Snapshot::pubkey(registry.current_epoch.checked_add(1).unwrap()),
false,
),
AccountMetaData::new_readonly(system_program::ID, false),
AccountMetaData::new_readonly(thread.key(), true),
],
data: anchor_sighash("snapshot_create").to_vec(),
})
};
Ok(ThreadResponse {
next_instruction,
..ThreadResponse::default()
})
}
src/instructions/fee_distribute.rs (line 115)
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
pub fn handler(ctx: Context<FeeDistribute>) -> Result<ThreadResponse> {
// Get accounts
let config = &ctx.accounts.config;
let delegation = &mut ctx.accounts.delegation;
let fee = &mut ctx.accounts.fee;
let registry = &ctx.accounts.registry;
let snapshot = &ctx.accounts.snapshot;
let snapshot_entry = &ctx.accounts.snapshot_entry;
let snapshot_frame = &ctx.accounts.snapshot_frame;
let thread = &ctx.accounts.thread;
let worker = &ctx.accounts.worker;
// Calculate the balance of this particular delegation, based on the weight of its stake with this worker.
let distribution_balance = if snapshot_frame.stake_amount.gt(&0) {
fee.distributable_balance
.checked_mul(snapshot_entry.stake_amount)
.unwrap()
.checked_div(snapshot_frame.stake_amount)
.unwrap()
} else {
0
};
// Transfer yield to the worker.
**fee.to_account_info().try_borrow_mut_lamports()? = fee
.to_account_info()
.lamports()
.checked_sub(distribution_balance)
.unwrap();
**delegation.to_account_info().try_borrow_mut_lamports()? = delegation
.to_account_info()
.lamports()
.checked_add(distribution_balance)
.unwrap();
// Increment the delegation's yield balance.
delegation.yield_balance = delegation
.yield_balance
.checked_add(distribution_balance)
.unwrap();
// Build the next instruction for the thread.
let next_instruction = if snapshot_entry
.id
.checked_add(1)
.unwrap()
.lt(&snapshot_frame.total_entries)
{
// This frame has more entries. Move on to the next one.
let next_delegation_pubkey =
Delegation::pubkey(worker.key(), delegation.id.checked_add(1).unwrap());
let next_snapshot_entry_pubkey = SnapshotEntry::pubkey(
snapshot_frame.key(),
snapshot_entry.id.checked_add(1).unwrap(),
);
Some(InstructionData {
program_id: crate::ID,
accounts: vec![
AccountMetaData::new_readonly(config.key(), false),
AccountMetaData::new(next_delegation_pubkey, false),
AccountMetaData::new(fee.key(), false),
AccountMetaData::new_readonly(registry.key(), false),
AccountMetaData::new_readonly(snapshot.key(), false),
AccountMetaData::new_readonly(snapshot_frame.key(), false),
AccountMetaData::new_readonly(next_snapshot_entry_pubkey, false),
AccountMetaData::new_readonly(thread.key(), true),
AccountMetaData::new_readonly(worker.key(), false),
],
data: anchor_sighash("fee_distribute").to_vec(),
})
} else if snapshot_frame
.id
.checked_add(1)
.unwrap()
.lt(&snapshot.total_frames)
{
// This frame has no more entries. Move on to the next worker.
let next_worker_pubkey = Worker::pubkey(worker.id.checked_add(1).unwrap());
let next_snapshot_frame_pubkey =
SnapshotFrame::pubkey(snapshot.key(), snapshot_frame.id.checked_add(1).unwrap());
Some(InstructionData {
program_id: crate::ID,
accounts: vec![
AccountMetaData::new_readonly(config.key(), false),
AccountMetaData::new(Fee::pubkey(next_worker_pubkey), false),
AccountMetaData::new_readonly(registry.key(), false),
AccountMetaData::new_readonly(snapshot.key(), false),
AccountMetaData::new_readonly(next_snapshot_frame_pubkey, false),
AccountMetaData::new_readonly(thread.key(), true),
AccountMetaData::new(next_worker_pubkey, false),
],
data: anchor_sighash("worker_fees_distribute").to_vec(),
})
} else {
// This frame has no more entires and it is the last frame. Move on to staking delegations.
Some(InstructionData {
program_id: crate::ID,
accounts: vec![
AccountMetaData::new_readonly(config.key(), false),
AccountMetaData::new_readonly(registry.key(), false),
AccountMetaData::new_readonly(thread.key(), true),
AccountMetaData::new_readonly(Worker::pubkey(0), false),
],
data: anchor_sighash("worker_delegations_stake").to_vec(),
})
};
Ok(ThreadResponse {
next_instruction,
..ThreadResponse::default()
})
}
Additional examples can be found in:
Trait Implementations§
source§impl AccountDeserialize for Delegation
impl AccountDeserialize for Delegation
source§fn try_deserialize(buf: &mut &[u8]) -> Result<Self>
fn try_deserialize(buf: &mut &[u8]) -> Result<Self>
Deserializes previously initialized account data. Should fail for all
uninitialized accounts, where the bytes are zeroed. Implementations
should be unique to a particular account type so that one can never
successfully deserialize the data of one account type into another.
For example, if the SPL token program were to implement this trait,
it should be impossible to deserialize a
Mint
account into a token
Account
. Read moresource§impl AccountSerialize for Delegation
impl AccountSerialize for Delegation
source§impl BorshDeserialize for Delegationwhere
Pubkey: BorshDeserialize,
u64: BorshDeserialize,
impl BorshDeserialize for Delegationwhere
Pubkey: BorshDeserialize,
u64: BorshDeserialize,
source§impl BorshSerialize for Delegationwhere
Pubkey: BorshSerialize,
u64: BorshSerialize,
impl BorshSerialize for Delegationwhere
Pubkey: BorshSerialize,
u64: BorshSerialize,
source§impl Clone for Delegation
impl Clone for Delegation
source§fn clone(&self) -> Delegation
fn clone(&self) -> Delegation
Returns a copy of the value. Read more
1.0.0 · source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source
. Read more