mirror of
https://github.com/d0zingcat/ore.git
synced 2026-05-13 23:16:52 +00:00
sdk, miner
This commit is contained in:
@@ -68,6 +68,7 @@ pub struct Swap {
|
||||
pub amount: [u8; 8],
|
||||
pub direction: u8,
|
||||
pub precision: u8,
|
||||
pub seed: [u8; 32],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
|
||||
118
api/src/sdk.rs
118
api/src/sdk.rs
@@ -21,26 +21,41 @@ pub fn program_log(accounts: &[AccountInfo], msg: &[u8]) -> Result<(), ProgramEr
|
||||
invoke_signed(&log(*accounts[0].key, msg), accounts, &crate::ID, &[MARKET])
|
||||
}
|
||||
|
||||
pub fn initialize(signer: Pubkey) -> Instruction {
|
||||
let config_address = config_pda().0;
|
||||
let market_address = market_pda().0;
|
||||
let mint_address = MINT_ADDRESS;
|
||||
let treasury_address = TREASURY_ADDRESS;
|
||||
let treasury_tokens_address = treasury_tokens_address();
|
||||
let vault_address = vault_pda().0;
|
||||
Instruction {
|
||||
program_id: crate::ID,
|
||||
accounts: vec![
|
||||
AccountMeta::new(signer, true),
|
||||
AccountMeta::new(config_address, false),
|
||||
AccountMeta::new(market_address, false),
|
||||
AccountMeta::new(mint_address, false),
|
||||
AccountMeta::new(treasury_address, false),
|
||||
AccountMeta::new(treasury_tokens_address, false),
|
||||
AccountMeta::new(vault_address, false),
|
||||
AccountMeta::new_readonly(system_program::ID, false),
|
||||
AccountMeta::new_readonly(spl_token::ID, false),
|
||||
AccountMeta::new_readonly(spl_associated_token_account::ID, false),
|
||||
],
|
||||
data: Initialize {}.to_bytes(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mine(signer: Pubkey, authority: Pubkey, id: u64, nonce: u64) -> Instruction {
|
||||
let block_adddress = block_pda(id).0;
|
||||
let market_address = market_pda().0;
|
||||
let miner_address = miner_pda(authority).0;
|
||||
let recipient = get_associated_token_address(&authority, &MINT_ADDRESS);
|
||||
Instruction {
|
||||
program_id: crate::ID,
|
||||
accounts: vec![
|
||||
AccountMeta::new(signer, true),
|
||||
AccountMeta::new(authority, false),
|
||||
AccountMeta::new(block_adddress, false),
|
||||
AccountMeta::new(market_address, false),
|
||||
AccountMeta::new(miner_address, false),
|
||||
AccountMeta::new(MINT_ADDRESS, false),
|
||||
AccountMeta::new(recipient, false),
|
||||
AccountMeta::new(TREASURY_ADDRESS, false),
|
||||
AccountMeta::new_readonly(system_program::ID, false),
|
||||
AccountMeta::new_readonly(spl_token::ID, false),
|
||||
AccountMeta::new_readonly(crate::ID, false),
|
||||
AccountMeta::new_readonly(sysvar::slot_hashes::ID, false),
|
||||
],
|
||||
data: Mine {
|
||||
nonce: nonce.to_le_bytes(),
|
||||
@@ -49,15 +64,94 @@ pub fn mine(signer: Pubkey, authority: Pubkey, id: u64, nonce: u64) -> Instructi
|
||||
}
|
||||
}
|
||||
|
||||
pub fn open(signer: Pubkey, id: u64) -> Instruction {
|
||||
let block_adddress = block_pda(id).0;
|
||||
let market_address = market_pda().0;
|
||||
Instruction {
|
||||
program_id: crate::ID,
|
||||
accounts: vec![
|
||||
AccountMeta::new(signer, true),
|
||||
AccountMeta::new(block_adddress, false),
|
||||
AccountMeta::new(market_address, false),
|
||||
AccountMeta::new_readonly(system_program::ID, false),
|
||||
],
|
||||
data: Open {
|
||||
id: id.to_le_bytes(),
|
||||
}
|
||||
.to_bytes(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn close(signer: Pubkey, opener: Pubkey, winner: Pubkey, id: u64) -> Instruction {
|
||||
let block_adddress = block_pda(id).0;
|
||||
let miner_tokens_address = get_associated_token_address(&winner, &MINT_ADDRESS);
|
||||
let mint_address = MINT_ADDRESS;
|
||||
let treasury_address = TREASURY_ADDRESS;
|
||||
let treasury_tokens_address = treasury_tokens_address();
|
||||
Instruction {
|
||||
program_id: crate::ID,
|
||||
accounts: vec![
|
||||
AccountMeta::new(signer, true),
|
||||
AccountMeta::new(block_adddress, false),
|
||||
AccountMeta::new(winner, false),
|
||||
AccountMeta::new(miner_tokens_address, false),
|
||||
AccountMeta::new(mint_address, false),
|
||||
AccountMeta::new(opener, false),
|
||||
AccountMeta::new(treasury_address, false),
|
||||
AccountMeta::new(treasury_tokens_address, false),
|
||||
AccountMeta::new_readonly(system_program::ID, false),
|
||||
AccountMeta::new_readonly(spl_token::ID, false),
|
||||
AccountMeta::new_readonly(spl_associated_token_account::ID, false),
|
||||
],
|
||||
data: Close {}.to_bytes(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset(signer: Pubkey, fee_collector: Pubkey, id: u64) -> Instruction {
|
||||
let block_prev_adddress = block_pda(id).0;
|
||||
let block_next_adddress = block_pda(id + 1).0;
|
||||
let config_address = config_pda().0;
|
||||
let market_address = market_pda().0;
|
||||
let mint_address = MINT_ADDRESS;
|
||||
let treasury_address = TREASURY_ADDRESS;
|
||||
let treasury_tokens_address = treasury_tokens_address();
|
||||
let vault_address = vault_pda().0;
|
||||
Instruction {
|
||||
program_id: crate::ID,
|
||||
accounts: vec![
|
||||
AccountMeta::new(signer, true),
|
||||
AccountMeta::new(block_prev_adddress, false),
|
||||
AccountMeta::new(block_next_adddress, false),
|
||||
AccountMeta::new_readonly(config_address, false),
|
||||
AccountMeta::new(fee_collector, false),
|
||||
AccountMeta::new(market_address, false),
|
||||
AccountMeta::new(mint_address, false),
|
||||
AccountMeta::new(treasury_address, false),
|
||||
AccountMeta::new(treasury_tokens_address, false),
|
||||
AccountMeta::new(vault_address, false),
|
||||
AccountMeta::new_readonly(system_program::ID, false),
|
||||
AccountMeta::new_readonly(spl_token::ID, false),
|
||||
AccountMeta::new_readonly(crate::ID, false),
|
||||
AccountMeta::new_readonly(sysvar::slot_hashes::ID, false),
|
||||
],
|
||||
data: Reset {}.to_bytes(),
|
||||
}
|
||||
}
|
||||
// let [signer_info, block_info, config_info, fee_collector_info, market_info, miner_info, mint_info, tokens_info, vault_info, system_program, token_program, associated_token_program, ore_program] =
|
||||
|
||||
pub fn swap(
|
||||
signer: Pubkey,
|
||||
id: u64,
|
||||
fee_collector: Pubkey,
|
||||
amount: u64,
|
||||
direction: SwapDirection,
|
||||
precision: SwapPrecision,
|
||||
seed: [u8; 32],
|
||||
) -> Instruction {
|
||||
let block_adddress = block_pda(id).0;
|
||||
let config_address = config_pda().0;
|
||||
let market_address = market_pda().0;
|
||||
let miner_address = miner_pda(signer).0;
|
||||
let tokens_quote_address = get_associated_token_address(&signer, &MINT_ADDRESS);
|
||||
let vault_address = vault_pda().0;
|
||||
Instruction {
|
||||
@@ -65,7 +159,10 @@ pub fn swap(
|
||||
accounts: vec![
|
||||
AccountMeta::new(signer, true),
|
||||
AccountMeta::new(block_adddress, false),
|
||||
AccountMeta::new(config_address, false),
|
||||
AccountMeta::new(fee_collector, false),
|
||||
AccountMeta::new(market_address, false),
|
||||
AccountMeta::new(miner_address, false),
|
||||
AccountMeta::new(MINT_ADDRESS, false),
|
||||
AccountMeta::new(tokens_quote_address, false),
|
||||
AccountMeta::new(vault_address, false),
|
||||
@@ -78,6 +175,7 @@ pub fn swap(
|
||||
amount: amount.to_le_bytes(),
|
||||
direction: direction as u8,
|
||||
precision: precision as u8,
|
||||
seed: seed,
|
||||
}
|
||||
.to_bytes(),
|
||||
}
|
||||
|
||||
@@ -13,9 +13,6 @@ pub struct Miner {
|
||||
/// The ID of the last block this miner mined in.
|
||||
pub block_id: u64,
|
||||
|
||||
/// The hash of the last block this miner mined in.
|
||||
pub hash: [u8; 32],
|
||||
|
||||
/// The amount of hashpower this miner has committed to the current block.
|
||||
pub hashpower: u64,
|
||||
|
||||
|
||||
@@ -55,3 +55,7 @@ pub fn vault_pda() -> (Pubkey, u8) {
|
||||
pub fn treasury_pda() -> (Pubkey, u8) {
|
||||
Pubkey::find_program_address(&[TREASURY], &crate::ID)
|
||||
}
|
||||
|
||||
pub fn treasury_tokens_address() -> Pubkey {
|
||||
spl_associated_token_account::get_associated_token_address(&TREASURY_ADDRESS, &MINT_ADDRESS)
|
||||
}
|
||||
|
||||
@@ -35,9 +35,18 @@ async fn main() {
|
||||
"blocks" => {
|
||||
log_blocks(&rpc).await.unwrap();
|
||||
}
|
||||
"initialize" => {
|
||||
initialize(&rpc, &payer).await.unwrap();
|
||||
}
|
||||
"open" => {
|
||||
open(&rpc, &payer).await.unwrap();
|
||||
}
|
||||
"swap" => {
|
||||
swap(&rpc, &payer).await.unwrap();
|
||||
}
|
||||
"miner" => {
|
||||
log_miner(&rpc, payer.pubkey()).await.unwrap();
|
||||
}
|
||||
"set_admin" => {
|
||||
set_admin(&rpc, &payer).await.unwrap();
|
||||
}
|
||||
@@ -48,18 +57,42 @@ async fn main() {
|
||||
};
|
||||
}
|
||||
|
||||
async fn initialize(
|
||||
rpc: &RpcClient,
|
||||
payer: &solana_sdk::signer::keypair::Keypair,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
let ix = ore_api::sdk::initialize(payer.pubkey());
|
||||
submit_transaction(rpc, payer, &[ix]).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn open(
|
||||
rpc: &RpcClient,
|
||||
payer: &solana_sdk::signer::keypair::Keypair,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
let id_str = std::env::var("ID").expect("Missing ID env var");
|
||||
let id = id_str.parse::<u64>()?;
|
||||
let ix = ore_api::sdk::open(payer.pubkey(), id);
|
||||
submit_transaction(rpc, payer, &[ix]).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn swap(
|
||||
rpc: &RpcClient,
|
||||
payer: &solana_sdk::signer::keypair::Keypair,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
let id_str = std::env::var("ID").expect("Missing ID env var");
|
||||
let id = id_str.parse::<u64>()?;
|
||||
let config = get_config(rpc).await?;
|
||||
let fee_collector = config.fee_collector;
|
||||
let ix = ore_api::sdk::swap(
|
||||
payer.pubkey(),
|
||||
id,
|
||||
10000000,
|
||||
fee_collector,
|
||||
100_000_000,
|
||||
SwapDirection::Buy,
|
||||
SwapPrecision::ExactIn,
|
||||
[0; 32],
|
||||
);
|
||||
submit_transaction(rpc, payer, &[ix]).await?;
|
||||
Ok(())
|
||||
@@ -74,6 +107,17 @@ async fn set_admin(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn log_miner(rpc: &RpcClient, authority: Pubkey) -> Result<(), anyhow::Error> {
|
||||
let miner = get_miner(&rpc, authority).await?;
|
||||
println!("Miner");
|
||||
println!(" authority: {}", authority);
|
||||
println!(" block_id: {}", miner.block_id);
|
||||
println!(" hashpower: {}", miner.hashpower);
|
||||
println!(" total_hashpower: {}", miner.total_hashpower);
|
||||
println!(" total_rewards: {}", miner.total_rewards);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn log_clock(rpc: &RpcClient) -> Result<(), anyhow::Error> {
|
||||
let clock = get_clock(&rpc).await?;
|
||||
println!("Clock");
|
||||
@@ -126,6 +170,13 @@ async fn get_config(rpc: &RpcClient) -> Result<Config, anyhow::Error> {
|
||||
Ok(*config)
|
||||
}
|
||||
|
||||
async fn get_miner(rpc: &RpcClient, authority: Pubkey) -> Result<Miner, anyhow::Error> {
|
||||
let miner_pda = ore_api::state::miner_pda(authority);
|
||||
let account = rpc.get_account(&miner_pda.0).await?;
|
||||
let miner = Miner::try_from_bytes(&account.data)?;
|
||||
Ok(*miner)
|
||||
}
|
||||
|
||||
async fn get_clock(rpc: &RpcClient) -> Result<Clock, anyhow::Error> {
|
||||
let data = rpc.get_account_data(&solana_sdk::sysvar::clock::ID).await?;
|
||||
let clock = bincode::deserialize::<Clock>(&data)?;
|
||||
|
||||
@@ -5,7 +5,7 @@ use steel::*;
|
||||
pub fn process_close(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResult {
|
||||
// Load accounts.
|
||||
let clock = Clock::get()?;
|
||||
let [signer_info, block_info, miner_info, miner_tokens_info, mint_info, opener_info, recipient_info, treasury_info, treasury_tokens_info, system_program, token_program, associated_token_program] =
|
||||
let [signer_info, block_info, miner_info, miner_tokens_info, mint_info, opener_info, treasury_info, treasury_tokens_info, system_program, token_program, associated_token_program] =
|
||||
accounts
|
||||
else {
|
||||
return Err(ProgramError::NotEnoughAccountKeys);
|
||||
@@ -41,11 +41,10 @@ pub fn process_close(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResul
|
||||
|
||||
// Payout block reward to winning miner.
|
||||
if block.best_hash_miner != Pubkey::default() {
|
||||
// Load recipient.
|
||||
recipient_info.as_associated_token_account(&block.best_hash_miner, &mint_info.key)?;
|
||||
// Load winning miner.
|
||||
let miner = miner_info
|
||||
.as_account_mut::<Miner>(&ore_api::ID)?
|
||||
.assert_mut(|m| m.authority == block.best_hash_miner)?;
|
||||
.has_address(&block.best_hash_miner)?
|
||||
.as_account_mut::<Miner>(&ore_api::ID)?;
|
||||
|
||||
// Update stats.
|
||||
miner.total_rewards += block.reward;
|
||||
|
||||
@@ -38,7 +38,7 @@ pub fn process_mine(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult
|
||||
// If hash is best hash, update best hash.
|
||||
if h < block.best_hash {
|
||||
block.best_hash = h;
|
||||
block.best_hash_miner = miner.authority;
|
||||
block.best_hash_miner = *miner_info.key;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -8,7 +8,7 @@ pub fn process_open(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult
|
||||
let id = u64::from_le_bytes(args.id);
|
||||
|
||||
// Load accounts.
|
||||
let [signer_info, block_info, market_info, system_program, ore_program] = accounts else {
|
||||
let [signer_info, block_info, market_info, system_program] = accounts else {
|
||||
return Err(ProgramError::NotEnoughAccountKeys);
|
||||
};
|
||||
signer_info.is_signer()?;
|
||||
@@ -16,7 +16,6 @@ pub fn process_open(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult
|
||||
.as_account::<Market>(&ore_api::ID)?
|
||||
.assert(|m| m.block_id < id)?; // Only allow opening blocks in forward bias
|
||||
system_program.is_program(&system_program::ID)?;
|
||||
ore_program.is_program(&ore_api::ID)?;
|
||||
|
||||
// Create block, if it doesn't exist.
|
||||
if block_info.data_is_empty() {
|
||||
|
||||
@@ -30,9 +30,6 @@ pub fn process_swap(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult
|
||||
.assert_mut(|m| m.block_id == block.id)?
|
||||
.assert_mut(|m| m.base.liquidity() > 0)?
|
||||
.assert_mut(|m| m.quote.liquidity() > 0)?;
|
||||
let miner = miner_info
|
||||
.as_account_mut::<Miner>(&ore_api::ID)?
|
||||
.assert_mut(|m| m.authority == *signer_info.key)?;
|
||||
mint_info
|
||||
.has_address(&market.quote.mint)?
|
||||
.has_address(&MINT_ADDRESS)?
|
||||
@@ -46,10 +43,35 @@ pub fn process_swap(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult
|
||||
associated_token_program.is_program(&spl_associated_token_account::ID)?;
|
||||
ore_program.is_program(&ore_api::ID)?;
|
||||
|
||||
// Load miner.
|
||||
let miner = if miner_info.data_is_empty() {
|
||||
create_program_account::<Miner>(
|
||||
miner_info,
|
||||
system_program,
|
||||
signer_info,
|
||||
&ore_api::ID,
|
||||
&[MINER, &signer_info.key.to_bytes()],
|
||||
)?;
|
||||
let miner = miner_info.as_account_mut::<Miner>(&ore_api::ID)?;
|
||||
miner.authority = *signer_info.key;
|
||||
miner.block_id = block.id;
|
||||
miner.hashpower = 0;
|
||||
miner.seed = [0; 32];
|
||||
miner.total_hashpower = 0;
|
||||
miner.total_rewards = 0;
|
||||
miner
|
||||
} else {
|
||||
miner_info
|
||||
.as_account_mut::<Miner>(&ore_api::ID)?
|
||||
.assert_mut(|m| m.authority == *signer_info.key)?
|
||||
.assert_mut(|m| m.block_id <= block.id)?
|
||||
};
|
||||
|
||||
// Reset miner.
|
||||
if miner.block_id != block.id {
|
||||
miner.block_id = block.id;
|
||||
miner.hashpower = 0;
|
||||
miner.seed = args.seed;
|
||||
}
|
||||
|
||||
// Pay swap fee.
|
||||
|
||||
Reference in New Issue
Block a user