341 lines
12 KiB
Rust
341 lines
12 KiB
Rust
use std::fs::File;
|
|
use std::mem::size_of;
|
|
use std::str::FromStr;
|
|
|
|
use anyhow::Result;
|
|
use chrono::NaiveDateTime;
|
|
use clap::Clap;
|
|
use client::utils::{create_account_rent_exempt, create_and_init_mint, create_signer_key_and_nonce, create_token_account, get_account, mnemonic_to_keypair, read_keypair_file, send_instructions, Cluster};
|
|
use omega::instruction::{init_omega_contract, resolve};
|
|
use omega::state::{DETAILS_BUFFER_LEN, OmegaContract};
|
|
use serde_json::{json, Value};
|
|
use solana_client::rpc_client::RpcClient;
|
|
use solana_sdk::pubkey::Pubkey;
|
|
use solana_sdk::signature::{Keypair, Signer, write_keypair_file};
|
|
use spl_token::state::Mint;
|
|
use solana_sdk::commitment_config::CommitmentConfig;
|
|
|
|
|
|
#[derive(Clap, Debug)]
|
|
pub struct Opts {
|
|
#[clap(default_value = "devnet")]
|
|
pub cluster: Cluster,
|
|
#[clap(subcommand)]
|
|
pub command: Command,
|
|
}
|
|
|
|
#[derive(Clap, Debug)]
|
|
pub enum Command {
|
|
InitOmegaContract {
|
|
#[clap(long, short)]
|
|
payer: String,
|
|
#[clap(long)]
|
|
omega_program_id: String,
|
|
#[clap(long)]
|
|
oracle: String,
|
|
#[clap(long, short)]
|
|
quote_mint: String,
|
|
#[clap(long, short)]
|
|
num_outcomes: usize,
|
|
#[clap(long, short)]
|
|
contract_keys_path: String,
|
|
#[clap(long)]
|
|
contract_name: String,
|
|
#[clap(long)]
|
|
outcome_names: Vec<String>,
|
|
#[clap(long)]
|
|
details: String,
|
|
#[clap(long)]
|
|
exp_time: String,
|
|
#[clap(long)]
|
|
icon_urls: Option<Vec<String>>
|
|
},
|
|
IssueSet {
|
|
#[clap(long, short, default_value="~/.config/solana/id.json")]
|
|
payer: String,
|
|
#[clap(long, short)]
|
|
contract_keys_path: String,
|
|
#[clap(long, short)]
|
|
user: Option<String>
|
|
},
|
|
Resolve {
|
|
#[clap(long, short)]
|
|
payer: String,
|
|
#[clap(long, short)]
|
|
contract_keys_path: String,
|
|
#[clap(long, short)]
|
|
oracle_keypair: String,
|
|
#[clap(long, short)]
|
|
winner: String,
|
|
},
|
|
|
|
SolletToLocal {
|
|
#[clap(long, short, default_value="~/.config/solana/sollet.json")]
|
|
keypair_path: String,
|
|
#[clap(long, short)]
|
|
sollet_mnemonic: Vec<String>,
|
|
#[clap(long, short)]
|
|
passphrase: Option<String>,
|
|
},
|
|
CreateSwapPools {
|
|
#[clap(long, short)]
|
|
payer: String,
|
|
#[clap(long, short)]
|
|
contract_keys_path: String,
|
|
#[clap(long, short)]
|
|
swap_program_id: String
|
|
},
|
|
|
|
}
|
|
|
|
impl Opts {
|
|
fn client(&self) -> RpcClient {
|
|
RpcClient::new_with_commitment(self.cluster.url().to_string(), CommitmentConfig::single_gossip())
|
|
}
|
|
}
|
|
|
|
#[allow(unused_variables)]
|
|
pub fn start(opts: Opts) -> Result<()> {
|
|
let client = opts.client();
|
|
|
|
match opts.command {
|
|
Command::InitOmegaContract {
|
|
payer,
|
|
omega_program_id,
|
|
oracle,
|
|
quote_mint,
|
|
num_outcomes,
|
|
contract_keys_path,
|
|
contract_name,
|
|
outcome_names,
|
|
details,
|
|
exp_time,
|
|
icon_urls
|
|
} => {
|
|
println!("InitOmegaContract");
|
|
assert_eq!(num_outcomes, outcome_names.len());
|
|
assert!(details.len() <= DETAILS_BUFFER_LEN);
|
|
|
|
let icon_urls: Vec<String> = match icon_urls {
|
|
None => { vec![
|
|
String::from("https://ftx.com/static/media/trumphappy.055aa6c3.svg"),
|
|
String::from("https://ftx.com/static/media/trumpsad.5f8806cd.svg")
|
|
] }
|
|
Some(v) => v
|
|
};
|
|
assert_eq!(icon_urls.len(), num_outcomes);
|
|
let payer = read_keypair_file(payer.as_str())?;
|
|
let omega_program_id = Pubkey::from_str(omega_program_id.as_str())?;
|
|
let oracle_pk = Pubkey::from_str(oracle.as_str())?;
|
|
let quote_mint_pk = Pubkey::from_str(quote_mint.as_str())?;
|
|
|
|
let omega_contract_pk = create_account_rent_exempt(
|
|
&client, &payer, size_of::<OmegaContract>(), &omega_program_id
|
|
)?.pubkey();
|
|
|
|
let (signer_key, signer_nonce) = create_signer_key_and_nonce(&omega_program_id, &omega_contract_pk);
|
|
|
|
let quote_vault_pk = create_token_account(&client, "e_mint_pk, &signer_key, &payer)?.pubkey();
|
|
|
|
let quote_mint: Mint = get_account(&client, "e_mint_pk)?;
|
|
let mut outcome_infos = Vec::<Value>::new();
|
|
let mut outcome_mint_pks = vec![];
|
|
for i in 0..num_outcomes {
|
|
let outcome_mint_kp = Keypair::new();
|
|
create_and_init_mint(
|
|
&client,
|
|
&payer,
|
|
&outcome_mint_kp,
|
|
&signer_key,
|
|
quote_mint.decimals
|
|
)?;
|
|
|
|
let outcome_json = json!(
|
|
{
|
|
"mint_pk": outcome_mint_kp.pubkey().to_string(),
|
|
"name": outcome_names[i],
|
|
"icon": icon_urls[i].clone()
|
|
}
|
|
);
|
|
outcome_infos.push(outcome_json);
|
|
outcome_mint_pks.push(outcome_mint_kp.pubkey());
|
|
}
|
|
|
|
let exp_time = NaiveDateTime::parse_from_str(exp_time.as_str(), "%Y-%m-%d %H:%M:%S")?;
|
|
let exp_time = exp_time.timestamp() as u64;
|
|
|
|
let instruction = init_omega_contract(
|
|
&omega_program_id,
|
|
&omega_contract_pk,
|
|
&oracle_pk,
|
|
"e_mint_pk,
|
|
"e_vault_pk,
|
|
&signer_key,
|
|
outcome_mint_pks.as_slice(),
|
|
exp_time,
|
|
signer_nonce,
|
|
details.as_str()
|
|
)?;
|
|
|
|
let instructions = vec![instruction];
|
|
let signers = vec![&payer];
|
|
|
|
send_instructions(&client, instructions, signers, &payer.pubkey())?;
|
|
|
|
let contract_keys = json!({
|
|
"contract_name": contract_name,
|
|
"omega_program_id": omega_program_id.to_string(),
|
|
"omega_contract_pk": omega_contract_pk.to_string(),
|
|
"oracle_pk": oracle_pk.to_string(),
|
|
"quote_mint_pk": quote_mint_pk.to_string(),
|
|
"quote_vault_pk": quote_vault_pk.to_string(),
|
|
"signer_pk": signer_key.to_string(),
|
|
"signer_nonce": signer_nonce,
|
|
|
|
"outcomes": outcome_infos,
|
|
"details": details
|
|
});
|
|
|
|
let f = File::create(&contract_keys_path).unwrap();
|
|
serde_json::to_writer_pretty(&f, &contract_keys).unwrap();
|
|
println!("contract keys were written into: {}", contract_keys_path);
|
|
}
|
|
Command::IssueSet { .. } => {
|
|
println!("IssueSet");
|
|
unimplemented!()
|
|
}
|
|
Command::Resolve {
|
|
payer,
|
|
contract_keys_path,
|
|
oracle_keypair,
|
|
winner
|
|
} => {
|
|
println!("Resolve");
|
|
|
|
let payer = read_keypair_file(payer.as_str())?;
|
|
let oracle_keypair = read_keypair_file(oracle_keypair.as_str())?;
|
|
let contract_keys: Value = serde_json::from_reader(File::open(contract_keys_path)?)?;
|
|
let winner_pk = Pubkey::from_str(winner.as_str())?;
|
|
let omega_program_id = Pubkey::from_str(contract_keys["omega_program_id"].as_str().unwrap())?;
|
|
let omega_contract_pk = Pubkey::from_str(contract_keys["omega_contract_pk"].as_str().unwrap())?;
|
|
|
|
let instruction = resolve(
|
|
&omega_program_id,
|
|
&omega_contract_pk,
|
|
&oracle_keypair.pubkey(),
|
|
&winner_pk
|
|
)?;
|
|
let instructions = vec![instruction];
|
|
let mut signers = vec![&payer];
|
|
if oracle_keypair != payer {
|
|
signers.push(&oracle_keypair)
|
|
}
|
|
send_instructions(&client, instructions, signers, &payer.pubkey())?;
|
|
|
|
}
|
|
|
|
Command::SolletToLocal {
|
|
keypair_path,
|
|
sollet_mnemonic,
|
|
passphrase
|
|
} => {
|
|
let derive_path = "m/501'/0'/0/0";
|
|
let sollet_mnemonic: String = sollet_mnemonic.join(" ");
|
|
let passphrase = passphrase.unwrap_or(String::from(""));
|
|
|
|
let kp = mnemonic_to_keypair(
|
|
sollet_mnemonic.as_str(),
|
|
passphrase.as_str(),
|
|
derive_path
|
|
)?;
|
|
write_keypair_file(&kp, keypair_path.as_str()).unwrap();
|
|
}
|
|
Command::CreateSwapPools {
|
|
payer,
|
|
contract_keys_path,
|
|
swap_program_id
|
|
} => {
|
|
unimplemented!()
|
|
// Create two swap pools based on contract keys, fund them with initial liquidity
|
|
// let payer = read_keypair_file(payer.as_str())?;
|
|
// let swap_program_id = Pubkey::from_str(swap_program_id.as_str())?;
|
|
// let contract_keys: Value = serde_json::from_reader(File::open(Path::new(contract_keys_path.as_str())).unwrap())?;
|
|
//
|
|
// let swap_kp = Keypair::new();
|
|
// let swap_pk = swap_kp.pubkey();
|
|
// let create_swap_instr = create_account_instr(
|
|
// &client, &payer, &swap_kp,
|
|
// spl_token_swap::state::SwapInfo::get_packed_len(),
|
|
// &swap_program_id
|
|
// )?;
|
|
//
|
|
// let (swap_auth_pk, nonce) = u8::create_signer_key_and_nonce(&swap_program_id, &swap_pk);
|
|
//
|
|
//
|
|
// let outcome_pk = Pubkey::from_str(contract_keys["outcomes"][0]["mint_pk"].as_str().unwrap())?;
|
|
// let quote_mint_pk = Pubkey::from_str(contract_keys["quote_mint_pk"].as_str().unwrap())?;
|
|
// // let accounts: Vec<RpcKeyedAccount> = client.get_token_accounts_by_owner(&payer.pubkey(), TokenAccountsFilter::Mint(outcome_pk.clone()))?;
|
|
// // for acc in accounts {
|
|
// // println!("{}", acc.pubkey);
|
|
// // }
|
|
// // panic!();
|
|
// let outcome_wallet_kp = create_token_account(&client, &outcome_pk, &swap_auth_pk, &payer)?;
|
|
// let quote_wallet_kp = create_token_account(&client, "e_mint_pk, &swap_auth_pk, &payer)?;
|
|
// let outcome_wallet_pk = outcome_wallet_kp.pubkey();
|
|
// let quote_wallet_pk = quote_wallet_kp.pubkey();
|
|
//
|
|
// let lp_mint_kp = Keypair::new();
|
|
// let lp_mint_pk = lp_mint_kp.pubkey();
|
|
// create_and_init_mint(&client, &payer, &lp_mint_kp, &swap_auth_pk, 9)?;
|
|
//
|
|
// let fee_acc_kp = create_token_account(&client, &lp_mint_pk, &payer.pubkey(), &payer)?;
|
|
// let fee_acc_pk = fee_acc_kp.pubkey();
|
|
//
|
|
// let payer_outcome_wallet_pk = Pubkey::from_str("CqUbC9APNS5WsA26aPy1w3R5ArcUnFDPmkTuCdYBUgju")?;
|
|
// let payer_quote_wallet_pk = Pubkey::from_str("Ggh42YAn4oUcBWbLc3orbqJq1BWjqs8VaGzwAD5f8Vbb")?;
|
|
// let transfer0 = spl_token::instruction::transfer(
|
|
// &spl_token::id(),
|
|
// &payer_outcome_wallet_pk,
|
|
// &outcome_wallet_pk,
|
|
// &payer.pubkey(),
|
|
// &[],
|
|
// 1_000_000_000
|
|
// )?;
|
|
// let transfer1 = spl_token::instruction::transfer(
|
|
// &spl_token::id(),
|
|
// &payer_quote_wallet_pk,
|
|
// "e_wallet_pk,
|
|
// &payer.pubkey(),
|
|
// &[],
|
|
// 1_000_000_000
|
|
// )?;
|
|
// let swap_init_instruction = spl_token_swap::instruction::initialize(
|
|
// &swap_program_id,
|
|
// &spl_token::id(),
|
|
// &swap_pk,
|
|
// &swap_auth_pk,
|
|
// &outcome_wallet_pk,
|
|
// "e_wallet_pk,
|
|
// &lp_mint_pk,
|
|
// &fee_acc_pk,
|
|
// &fee_acc_pk,
|
|
// nonce,
|
|
// SwapCurve::default()
|
|
// )?;
|
|
//
|
|
// let instructions = vec![transfer0, transfer1, create_swap_instr, swap_init_instruction];
|
|
// let signers = vec![&payer, &swap_kp];
|
|
// send_instructions(&client, instructions, signers, &payer.pubkey())?;
|
|
// println!("finished");
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
|
|
|
|
fn main() {
|
|
let opts = Opts::parse();
|
|
start(opts).unwrap();
|
|
}
|