cli, context: Add spl token faucet to init-mint command (#63)
This commit is contained in:
parent
7261556aba
commit
6de9192766
|
@ -3085,7 +3085,9 @@ dependencies = [
|
|||
"serum-registry-cli",
|
||||
"serum-registry-rewards-cli",
|
||||
"serum_dex",
|
||||
"solana-client",
|
||||
"solana-sdk",
|
||||
"spl-token 2.0.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
6
Makefile
6
Makefile
|
@ -12,13 +12,15 @@ TEST_PAYER_FILEPATH="$(HOME)/.config/solana/id.json"
|
|||
#
|
||||
# The solana cluster to test against. Defaults to local.
|
||||
#
|
||||
ifndef TEST_CLUSTER
|
||||
TEST_CLUSTER=l
|
||||
#TEST_CLUSTER=devnet
|
||||
endif
|
||||
#
|
||||
# The url of TEST_CLUSTER.
|
||||
#
|
||||
ifndef TEST_CLUSTER_URL
|
||||
TEST_CLUSTER_URL="http://localhost:8899"
|
||||
#TEST_CLUSTER_URL="https://devnet.solana.com"
|
||||
endif
|
||||
#
|
||||
# One can optionally set this along with the test-program command
|
||||
# to avoid redeploying everytime tests are run.
|
||||
|
|
|
@ -9,7 +9,7 @@ name = "serum"
|
|||
path = "src/main.rs"
|
||||
|
||||
[features]
|
||||
dev = ["serum-common", "serum-common-tests", "serum_dex", "solana-sdk", "serde_json", "serum-registry"]
|
||||
dev = ["serum-common", "serum-common-tests", "serum_dex", "solana-sdk", "serde_json", "serum-registry", "spl-token", "solana-client"]
|
||||
default = []
|
||||
|
||||
|
||||
|
@ -29,3 +29,5 @@ serum_dex = { path = "../dex", default-features = false, features = ["client"],
|
|||
solana-sdk = { version = "1.3.14", optional = true }
|
||||
serde_json = { version = "1.0.59", optional = true }
|
||||
serum-registry = { path = "../registry", optional = true }
|
||||
spl-token = { version = "2.0.6", optional = true }
|
||||
solana-client = { version = "1.4.4", optional = true }
|
|
@ -0,0 +1,81 @@
|
|||
use anyhow::{anyhow, Result};
|
||||
use serum_common::client::rpc;
|
||||
use serum_context::Context;
|
||||
use solana_client::rpc_config::RpcSendTransactionConfig;
|
||||
use solana_sdk::commitment_config::CommitmentConfig;
|
||||
use solana_sdk::instruction::{AccountMeta, Instruction};
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::signature::Signer;
|
||||
use solana_sdk::sysvar;
|
||||
use solana_sdk::transaction::Transaction;
|
||||
|
||||
const FAUCET_SIZE: usize = 77;
|
||||
|
||||
// `admin` must be the current mint authority.
|
||||
//
|
||||
// Faucet program here:
|
||||
//
|
||||
// https://github.com/paul-schaaf/spl-token-faucet/blob/main/src/program/src/instruction.rs.
|
||||
pub fn create(ctx: &Context, mint: Pubkey, amount: u64, admin: Pubkey) -> Result<Pubkey> {
|
||||
let faucet_pid = ctx.faucet_pid.ok_or(anyhow!("faucet not provided"))?;
|
||||
let faucet = rpc::create_account_rent_exempt(
|
||||
&ctx.rpc_client(),
|
||||
&ctx.wallet()?,
|
||||
FAUCET_SIZE,
|
||||
&faucet_pid,
|
||||
)?
|
||||
.pubkey();
|
||||
|
||||
let ixs = {
|
||||
let (faucet_pda, _nonce) =
|
||||
Pubkey::find_program_address(&["faucet".to_string().as_bytes()], &faucet_pid);
|
||||
|
||||
let set_auth_ix = spl_token::instruction::set_authority(
|
||||
&spl_token::ID,
|
||||
&mint,
|
||||
Some(&faucet_pda),
|
||||
spl_token::instruction::AuthorityType::MintTokens,
|
||||
&admin,
|
||||
&[],
|
||||
)?;
|
||||
|
||||
let create_faucet_ix = {
|
||||
let accounts = vec![
|
||||
AccountMeta::new_readonly(mint, false),
|
||||
AccountMeta::new(faucet, false),
|
||||
AccountMeta::new(sysvar::rent::ID, false),
|
||||
AccountMeta::new_readonly(admin, false),
|
||||
];
|
||||
|
||||
let mut data = vec![0];
|
||||
data.extend_from_slice(&amount.to_le_bytes());
|
||||
|
||||
Instruction {
|
||||
program_id: faucet_pid,
|
||||
data,
|
||||
accounts,
|
||||
}
|
||||
};
|
||||
|
||||
[set_auth_ix, create_faucet_ix]
|
||||
};
|
||||
|
||||
let _tx = {
|
||||
let client = ctx.rpc_client();
|
||||
let payer = ctx.wallet()?;
|
||||
let (recent_hash, _fee_calc) = client.get_recent_blockhash()?;
|
||||
let tx =
|
||||
Transaction::new_signed_with_payer(&ixs, Some(&payer.pubkey()), &[&payer], recent_hash);
|
||||
let sig = client.send_and_confirm_transaction_with_spinner_and_config(
|
||||
&tx,
|
||||
CommitmentConfig::single(),
|
||||
RpcSendTransactionConfig {
|
||||
skip_preflight: true,
|
||||
..RpcSendTransactionConfig::default()
|
||||
},
|
||||
)?;
|
||||
sig
|
||||
};
|
||||
|
||||
Ok(faucet)
|
||||
}
|
|
@ -13,11 +13,16 @@ use solana_sdk::pubkey::Pubkey;
|
|||
use solana_sdk::signature::Signer;
|
||||
use std::num::NonZeroU64;
|
||||
|
||||
mod faucet;
|
||||
|
||||
#[derive(Debug, Clap)]
|
||||
pub enum Command {
|
||||
/// Creates 1) SRM mint, 2) MSRM mint 3) SRM funded token account, and
|
||||
/// 4) MSRM funded token account, all owned by the configured wallet.
|
||||
InitMint,
|
||||
InitMint {
|
||||
#[clap(short, long)]
|
||||
faucet: bool,
|
||||
},
|
||||
AllocateAccount {
|
||||
#[clap(short, long)]
|
||||
program_id: Pubkey,
|
||||
|
@ -34,7 +39,7 @@ pub enum Command {
|
|||
|
||||
pub fn run(ctx: Context, cmd: Command) -> Result<()> {
|
||||
match cmd {
|
||||
Command::InitMint => init_mint(&ctx),
|
||||
Command::InitMint { faucet } => init_mint(&ctx, faucet),
|
||||
Command::AllocateAccount { program_id, size } => allocate_account(&ctx, program_id, size),
|
||||
Command::GenerateOrders {
|
||||
coin_wallet,
|
||||
|
@ -43,7 +48,7 @@ pub fn run(ctx: Context, cmd: Command) -> Result<()> {
|
|||
}
|
||||
}
|
||||
|
||||
fn init_mint(ctx: &Context) -> Result<()> {
|
||||
fn init_mint(ctx: &Context, faucet: bool) -> Result<()> {
|
||||
// Doesn't matter.
|
||||
let program_id = Pubkey::new_from_array([0; 32]).to_string();
|
||||
let payer_filepath = &ctx.wallet_path.to_string();
|
||||
|
@ -51,13 +56,22 @@ fn init_mint(ctx: &Context) -> Result<()> {
|
|||
std::env::set_var(serum_common_tests::TEST_PROGRAM_ID, program_id);
|
||||
std::env::set_var(serum_common_tests::TEST_PAYER_FILEPATH, payer_filepath);
|
||||
std::env::set_var(serum_common_tests::TEST_CLUSTER, cluster);
|
||||
let (_client, g) = serum_common_tests::genesis::<Client>();
|
||||
let (client, g) = serum_common_tests::genesis::<Client>();
|
||||
|
||||
let (srm_faucet, msrm_faucet) = match faucet {
|
||||
false => (None, None),
|
||||
true => {
|
||||
let srm_faucet =
|
||||
faucet::create(ctx, g.srm_mint, 1_000_000_000_000, client.payer().pubkey())?;
|
||||
let msrm_faucet =
|
||||
faucet::create(ctx, g.msrm_mint, 1_000_000_000_000, client.payer().pubkey())?;
|
||||
(Some(srm_faucet), Some(msrm_faucet))
|
||||
}
|
||||
};
|
||||
println!(
|
||||
"{}",
|
||||
serde_json::json!({
|
||||
"wallet": g.wallet.to_string(),
|
||||
"mintAuthority": g.mint_authority.to_string(),
|
||||
"srmMint": g.srm_mint.to_string(),
|
||||
"msrmMint": g.msrm_mint.to_string(),
|
||||
"god": g.god.to_string(),
|
||||
|
@ -65,6 +79,14 @@ fn init_mint(ctx: &Context) -> Result<()> {
|
|||
"godBalanceBefore": g.god_balance_before,
|
||||
"godMsrmBalanceBefore": g.god_msrm_balance_before,
|
||||
"godOwner": g.god_owner.to_string(),
|
||||
"srmFaucet": match srm_faucet {
|
||||
None => "null".to_string(),
|
||||
Some(f) => f.to_string(),
|
||||
},
|
||||
"msrmFaucet": match msrm_faucet {
|
||||
None => "null".to_string(),
|
||||
Some(f) => f.to_string(),
|
||||
}
|
||||
})
|
||||
);
|
||||
|
|
@ -32,7 +32,7 @@ impl FromStr for Cluster {
|
|||
"l" | "localnet" => Ok(Cluster::Localnet),
|
||||
"g" | "debug" => Ok(Cluster::Debug),
|
||||
_ => Err(anyhow::Error::msg(
|
||||
"Cluster must be one of [testnet, mainnet, devnet] or be an http or https url\n",
|
||||
"Cluster must be one of [localnet, testnet, mainnet, devnet] or be an http or https url\n",
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ pub struct Context {
|
|||
pub meta_entity_pid: Pubkey,
|
||||
pub lockup_pid: Pubkey,
|
||||
pub dex_pid: Pubkey,
|
||||
pub faucet_pid: Option<Pubkey>,
|
||||
}
|
||||
|
||||
impl Context {
|
||||
|
@ -85,6 +86,7 @@ struct Programs {
|
|||
pub meta_entity_pid: String,
|
||||
pub lockup_pid: String,
|
||||
pub dex_pid: String,
|
||||
pub faucet_pid: Option<String>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
|
@ -98,11 +100,20 @@ impl Config {
|
|||
impl TryFrom<Config> for Context {
|
||||
type Error = anyhow::Error;
|
||||
fn try_from(cfg: Config) -> std::result::Result<Self, anyhow::Error> {
|
||||
Ok(Self {
|
||||
cluster: cfg
|
||||
let cluster = cfg
|
||||
.network
|
||||
.cluster
|
||||
.map_or(Ok(Default::default()), |c| c.parse())?,
|
||||
.map_or(Ok(Default::default()), |c| c.parse())?;
|
||||
let faucet_pid = cfg
|
||||
.programs
|
||||
.faucet_pid
|
||||
.or_else(|| match &cluster {
|
||||
Cluster::Devnet => Some("4bXpkKSV8swHSnwqtzuboGPaPDeEgAn4Vt8GfarV5rZt".to_string()),
|
||||
_ => None,
|
||||
})
|
||||
.map(|f| f.parse().unwrap());
|
||||
Ok(Self {
|
||||
cluster,
|
||||
wallet_path: cfg
|
||||
.wallet_path
|
||||
.map_or(Default::default(), |p| WalletPath(p)),
|
||||
|
@ -114,6 +125,7 @@ impl TryFrom<Config> for Context {
|
|||
lockup_pid: cfg.programs.lockup_pid.parse()?,
|
||||
meta_entity_pid: cfg.programs.meta_entity_pid.parse()?,
|
||||
dex_pid: cfg.programs.dex_pid.parse()?,
|
||||
faucet_pid,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,10 +6,39 @@
|
|||
# Does deployment + initialization of all programs and accounts needed to run
|
||||
# the staking + lockup application.
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# ./scripts/deploy-staking.sh <localnet | devnet | mainnet>
|
||||
#
|
||||
################################################################################
|
||||
|
||||
CLUSTER=l
|
||||
#CLUSTER=devnet
|
||||
set -euox pipefail
|
||||
|
||||
CLUSTER=$1
|
||||
|
||||
if [ "$CLUSTER" = "devnet" ]; then
|
||||
echo "Deploying to Devnet..."
|
||||
FAUCET_FLAG="--faucet"
|
||||
CONFIG_FILE=~/.config/serum/cli/devnet.yaml
|
||||
CLUSTER_URL="https://devnet.solana.com"
|
||||
elif [ "$CLUSTER" = "mainnet" ]; then
|
||||
echo "Deploying to Mainnet..."
|
||||
FAUCET_FLAG=""
|
||||
CONFIG_FILE=~/.config/serum/cli/mainnet.yaml
|
||||
CLUSTER_URL="https://api.mainnet-beta.solana.com"
|
||||
elif [ "$CLUSTER" = "localnet" ]; then
|
||||
echo "Deploying to Localnet..."
|
||||
FAUCET_FLAG=""
|
||||
CONFIG_FILE=~/.config/serum/cli/localnet.yaml
|
||||
CLUSTER_URL="http://localhost:8899"
|
||||
else
|
||||
echo "Invalid cluster"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#
|
||||
# Seconds.
|
||||
#
|
||||
DEACTIVATION_TIMELOCK=60
|
||||
WITHDRAWAL_TIMELOCK=60
|
||||
#
|
||||
|
@ -24,8 +53,9 @@ STAKE_RATE=1000000
|
|||
# 1 MSRM (0 decimals) to stake.
|
||||
#
|
||||
STAKE_RATE_MEGA=1
|
||||
|
||||
CONFIG_FILE=~/.config/serum/cli/dev.yaml
|
||||
#
|
||||
# Must be built with the `dev` feature on.
|
||||
#
|
||||
serum=$(pwd)/target/debug/serum
|
||||
|
||||
main() {
|
||||
|
@ -40,6 +70,7 @@ main() {
|
|||
#
|
||||
# Build all programs.
|
||||
#
|
||||
echo "Building all programs..."
|
||||
make -s -C lockup build
|
||||
make -s -C registry build
|
||||
make -s -C registry/meta-entity build
|
||||
|
@ -49,34 +80,51 @@ main() {
|
|||
#
|
||||
# Deploy all the programs.
|
||||
#
|
||||
local pids=$(make -s -C registry deploy-all)
|
||||
local rewards_pids=$(make -s -C registry/rewards deploy-all)
|
||||
echo "Deploying all programs..."
|
||||
local pids=$(TEST_CLUSTER="$CLUSTER" TEST_CLUSTER_URL="$CLUSTER_URL" make -s -C registry deploy-all)
|
||||
local rewards_pids=$(TEST_CLUSTER="$CLUSTER" TEST_CLUSTER_URL="$CLUSTER_URL" make -s -C registry/rewards deploy-all)
|
||||
|
||||
local registry_pid=$(echo $pids | jq .registryProgramId -r)
|
||||
local lockup_pid=$(echo $pids | jq .lockupProgramId -r)
|
||||
local meta_entity_pid=$(echo $pids | jq .metaEntityProgramId -r)
|
||||
local dex_pid=$(echo $rewards_pids | jq .dexProgramId -r)
|
||||
local rewards_pid=$(echo $rewards_pids | jq .rewardsProgramId -r)
|
||||
local dex_pid=$(echo $rewards_pids | jq .dexProgramId -r)
|
||||
|
||||
#
|
||||
# Generate genesis state.
|
||||
# Generate genesis state. Use dummy accounts, if needed.
|
||||
#
|
||||
local genesis=$($serum dev init-mint)
|
||||
local srm_mint="SRMuApVNdxXokk5GT7XD5cUUgXMBCoAz2LHeuAoKWRt"
|
||||
local msrm_mint="MSRMcoVyrFxnSgo5uXwone5SKcGhT1KEJMFEkMEWf9L"
|
||||
local god="FhmUh2PEpTzUwBWPt4qgDBeqfmb2ES3T64CkT1ZiktSS" # Dummy.
|
||||
local god_msrm="FhmUh2PEpTzUwBWPt4qgDBeqfmb2ES3T64CkT1ZiktSS" # Dummy.
|
||||
local srm_faucet="None"
|
||||
local msrm_faucet="None"
|
||||
if [ "$CLUSTER" != "mainnet" ]; then
|
||||
echo "Genesis initialization..."
|
||||
genesis=$($serum --config $CONFIG_FILE dev init-mint $FAUCET_FLAG)
|
||||
|
||||
local srm_mint=$(echo $genesis | jq .srmMint -r)
|
||||
local msrm_mint=$(echo $genesis | jq .msrmMint -r)
|
||||
local god=$(echo $genesis | jq .god -r)
|
||||
local god_msrm=$(echo $genesis | jq .godMsrm -r)
|
||||
srm_mint=$(echo $genesis | jq .srmMint -r)
|
||||
msrm_mint=$(echo $genesis | jq .msrmMint -r)
|
||||
god=$(echo $genesis | jq .god -r)
|
||||
god_msrm=$(echo $genesis | jq .godMsrm -r)
|
||||
srm_faucet=$(echo $genesis | jq .srmFaucet -r)
|
||||
msrm_faucet=$(echo $genesis | jq .msrmFaucet -r)
|
||||
fi
|
||||
|
||||
#
|
||||
# Write out the CLI configuration file.
|
||||
#
|
||||
echo "Writing config $CONFIG_FILE..."
|
||||
mkdir -p $(dirname $CONFIG_FILE)
|
||||
cat << EOM > $CONFIG_FILE
|
||||
---
|
||||
network:
|
||||
cluster: $CLUSTER
|
||||
|
||||
#
|
||||
# SRM Faucet: $srm_faucet
|
||||
# MSRM Faucet: $msrm_faucet
|
||||
#
|
||||
mints:
|
||||
srm: $srm_mint
|
||||
msrm: $msrm_mint
|
||||
|
@ -87,11 +135,13 @@ programs:
|
|||
meta_entity_pid: $meta_entity_pid
|
||||
lockup_pid: $lockup_pid
|
||||
dex_pid: $dex_pid
|
||||
|
||||
EOM
|
||||
|
||||
#
|
||||
# Now intialize all the accounts.
|
||||
#
|
||||
echo "Initializing registrar..."
|
||||
local rInit=$($serum --config $CONFIG_FILE \
|
||||
registry init \
|
||||
--deactivation-timelock $DEACTIVATION_TIMELOCK \
|
||||
|
@ -104,6 +154,7 @@ EOM
|
|||
local registrar_nonce=$(echo $rInit | jq .nonce -r)
|
||||
local reward_q=$(echo $rInit | jq .rewardEventQueue -r)
|
||||
|
||||
echo "Initializing lockup..."
|
||||
local lInit=$($serum --config $CONFIG_FILE \
|
||||
lockup initialize)
|
||||
|
||||
|
@ -113,6 +164,7 @@ EOM
|
|||
# Initialize a node entity. Hack until we separate joining entities
|
||||
# from creating member accounts.
|
||||
#
|
||||
echo "Creating the default node entity..."
|
||||
local createEntity=$($serum --config $CONFIG_FILE \
|
||||
registry create-entity \
|
||||
--registrar $registrar \
|
||||
|
@ -125,6 +177,7 @@ EOM
|
|||
#
|
||||
# Add the registry to the lockup program whitelist.
|
||||
#
|
||||
echo "Adding registry to the lockup whitelist..."
|
||||
$serum --config $CONFIG_FILE \
|
||||
lockup gov \
|
||||
--safe $safe \
|
||||
|
@ -136,6 +189,7 @@ EOM
|
|||
#
|
||||
# Log the generated TypeScript.
|
||||
#
|
||||
set +e
|
||||
read -r -d '' VAR << EOM
|
||||
{
|
||||
srm: new PublicKey('${srm_mint}'),
|
||||
|
|
Loading…
Reference in New Issue