refactor to make kebab-case (almost) entirely an Icepick thing rather than a thing per-interface
This commit is contained in:
parent
d7e61b4ae1
commit
a18282d107
|
@ -106,29 +106,24 @@ impl std::fmt::Display for Cluster {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
|
||||||
pub struct GetBlockhash {
|
pub struct GetBlockhash {
|
||||||
cluster: Option<Cluster>,
|
cluster: Option<Cluster>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
|
||||||
pub struct GenerateWallet {
|
pub struct GenerateWallet {
|
||||||
account: Option<String>,
|
account: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
|
||||||
pub struct GetWalletAddress {}
|
pub struct GetWalletAddress {}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
|
||||||
pub struct GetTokenInfo {
|
pub struct GetTokenInfo {
|
||||||
token: String,
|
token: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
|
||||||
pub struct Transfer {
|
pub struct Transfer {
|
||||||
amount: String,
|
amount: String,
|
||||||
to_address: String,
|
to_address: String,
|
||||||
|
@ -140,7 +135,6 @@ pub struct Transfer {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
|
||||||
pub struct CreateTokenAccount {
|
pub struct CreateTokenAccount {
|
||||||
funder_address: Option<String>,
|
funder_address: Option<String>,
|
||||||
wallet_address: String,
|
wallet_address: String,
|
||||||
|
@ -148,7 +142,6 @@ pub struct CreateTokenAccount {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
|
||||||
pub struct TransferToken {
|
pub struct TransferToken {
|
||||||
amount: String,
|
amount: String,
|
||||||
token_address: String,
|
token_address: String,
|
||||||
|
@ -162,19 +155,16 @@ pub struct TransferToken {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
|
||||||
pub struct Sign {
|
pub struct Sign {
|
||||||
blockhash: String,
|
blockhash: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
|
||||||
pub struct Broadcast {
|
pub struct Broadcast {
|
||||||
cluster: Option<Cluster>,
|
cluster: Option<Cluster>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
|
||||||
pub struct Request {
|
pub struct Request {
|
||||||
// NOTE: Can't use the proper XPrv type from Keyfork because Solana's a big stinky
|
// NOTE: Can't use the proper XPrv type from Keyfork because Solana's a big stinky
|
||||||
// and adds in its own derivation constructs that cause type conflicts.
|
// and adds in its own derivation constructs that cause type conflicts.
|
||||||
|
@ -188,7 +178,7 @@ pub struct Request {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
#[serde(tag = "operation", content = "values", rename_all = "kebab-case")]
|
#[serde(tag = "operation", content = "values")]
|
||||||
pub enum Operation {
|
pub enum Operation {
|
||||||
GetBlockhash(GetBlockhash),
|
GetBlockhash(GetBlockhash),
|
||||||
GenerateWallet(GenerateWallet),
|
GenerateWallet(GenerateWallet),
|
||||||
|
@ -406,14 +396,16 @@ impl Module for Solana {
|
||||||
let client = solana_rpc_client::rpc_client::RpcClient::new(cluster_url);
|
let client = solana_rpc_client::rpc_client::RpcClient::new(cluster_url);
|
||||||
let response = client.get_latest_blockhash().unwrap();
|
let response = client.get_latest_blockhash().unwrap();
|
||||||
Ok(serde_json::json!({
|
Ok(serde_json::json!({
|
||||||
"blob": response.to_string(),
|
"blob": {
|
||||||
|
"blockhash": response.to_string(),
|
||||||
|
},
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
Operation::GenerateWallet(GenerateWallet { account }) => {
|
Operation::GenerateWallet(GenerateWallet { account }) => {
|
||||||
let account = u32::from_str(account.as_deref().unwrap_or("0")).unwrap();
|
let account = u32::from_str(account.as_deref().unwrap_or("0")).unwrap();
|
||||||
Ok(serde_json::json!({
|
Ok(serde_json::json!({
|
||||||
"blob": null,
|
"blob": {},
|
||||||
"derivation-accounts": [(account | 1 << 31)],
|
"derivation_accounts": [(account | 1 << 31)],
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
Operation::GetWalletAddress(_) => {
|
Operation::GetWalletAddress(_) => {
|
||||||
|
@ -422,7 +414,9 @@ impl Module for Solana {
|
||||||
let keypair = Self::keypair_from_bytes(key);
|
let keypair = Self::keypair_from_bytes(key);
|
||||||
let pubkey = keypair.pubkey();
|
let pubkey = keypair.pubkey();
|
||||||
Ok(serde_json::json!({
|
Ok(serde_json::json!({
|
||||||
"blob": pubkey.to_string(),
|
"blob": {
|
||||||
|
"pubkey": pubkey.to_string(),
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
Operation::GetTokenInfo(GetTokenInfo { token }) => {
|
Operation::GetTokenInfo(GetTokenInfo { token }) => {
|
||||||
|
@ -442,7 +436,8 @@ impl Module for Solana {
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
None => serde_json::json!({
|
None => serde_json::json!({
|
||||||
"blob": null,
|
"blob": {},
|
||||||
|
"error": "key was not found!",
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -499,8 +494,10 @@ impl Module for Solana {
|
||||||
requested_accounts.push(*account | 1 << 31);
|
requested_accounts.push(*account | 1 << 31);
|
||||||
}
|
}
|
||||||
Ok(serde_json::json!({
|
Ok(serde_json::json!({
|
||||||
"blob": transaction,
|
"blob": {
|
||||||
"derivation-accounts": requested_accounts,
|
"transaction": transaction,
|
||||||
|
},
|
||||||
|
"derivation_accounts": requested_accounts,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
Operation::CreateTokenAccount(CreateTokenAccount {
|
Operation::CreateTokenAccount(CreateTokenAccount {
|
||||||
|
@ -528,8 +525,10 @@ impl Module for Solana {
|
||||||
let transaction = solana_sdk::transaction::Transaction::new_unsigned(message);
|
let transaction = solana_sdk::transaction::Transaction::new_unsigned(message);
|
||||||
#[allow(clippy::identity_op)]
|
#[allow(clippy::identity_op)]
|
||||||
Ok(serde_json::json!({
|
Ok(serde_json::json!({
|
||||||
"blob": transaction,
|
"blob": {
|
||||||
"derivation-accounts": [0u32 | 1 << 31],
|
"transaction": transaction,
|
||||||
|
},
|
||||||
|
"derivation_accounts": [0u32 | 1 << 31],
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
Operation::TransferToken(TransferToken {
|
Operation::TransferToken(TransferToken {
|
||||||
|
@ -619,14 +618,19 @@ impl Module for Solana {
|
||||||
|
|
||||||
#[allow(clippy::identity_op)]
|
#[allow(clippy::identity_op)]
|
||||||
Ok(serde_json::json!({
|
Ok(serde_json::json!({
|
||||||
"blob": transaction,
|
"blob": {
|
||||||
"derivation-accounts": [0u32 | 1 << 31],
|
"transaction": transaction,
|
||||||
|
},
|
||||||
|
"derivation_accounts": [0u32 | 1 << 31],
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
Operation::Sign(Sign { blockhash }) => {
|
Operation::Sign(Sign { blockhash }) => {
|
||||||
let blob = request.blob.expect("passed in instruction blob");
|
let transaction = request
|
||||||
|
.blob
|
||||||
|
.and_then(|b| b.get("transaction").cloned())
|
||||||
|
.expect("was given transaction");
|
||||||
let mut transaction: solana_sdk::transaction::Transaction =
|
let mut transaction: solana_sdk::transaction::Transaction =
|
||||||
serde_json::from_value(blob).expect("valid message blob");
|
serde_json::from_value(transaction).expect("valid message blob");
|
||||||
let keys = request
|
let keys = request
|
||||||
.derived_keys
|
.derived_keys
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
|
@ -639,16 +643,21 @@ impl Module for Solana {
|
||||||
.try_sign(&keys, hash)
|
.try_sign(&keys, hash)
|
||||||
.expect("not enough keys provided");
|
.expect("not enough keys provided");
|
||||||
Ok(serde_json::json!({
|
Ok(serde_json::json!({
|
||||||
"blob": transaction,
|
"blob": {
|
||||||
|
"transaction": transaction,
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
Operation::Broadcast(Broadcast { cluster }) => {
|
Operation::Broadcast(Broadcast { cluster }) => {
|
||||||
let cluster = cluster.unwrap_or(Cluster::MainnetBeta);
|
let cluster = cluster.unwrap_or(Cluster::MainnetBeta);
|
||||||
let cluster_url = format!("https://api.{cluster}.solana.com");
|
let cluster_url = format!("https://api.{cluster}.solana.com");
|
||||||
|
|
||||||
let blob = request.blob.expect("passed in instruction blob");
|
let transaction = request
|
||||||
|
.blob
|
||||||
|
.and_then(|b| b.get("transaction").cloned())
|
||||||
|
.expect("was given transaction");
|
||||||
let transaction: solana_sdk::transaction::Transaction =
|
let transaction: solana_sdk::transaction::Transaction =
|
||||||
serde_json::from_value(blob).expect("valid message blob");
|
serde_json::from_value(transaction).expect("valid message blob");
|
||||||
transaction.verify().expect("invalid signatures");
|
transaction.verify().expect("invalid signatures");
|
||||||
let client = solana_rpc_client::rpc_client::RpcClient::new(cluster_url);
|
let client = solana_rpc_client::rpc_client::RpcClient::new(cluster_url);
|
||||||
let _simulated_response = client.simulate_transaction(&transaction).unwrap();
|
let _simulated_response = client.simulate_transaction(&transaction).unwrap();
|
||||||
|
|
|
@ -124,7 +124,7 @@ pub fn do_cli_thing() {
|
||||||
|
|
||||||
let derivation_accounts = cli_input
|
let derivation_accounts = cli_input
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|json| json.get("derivation-accounts"));
|
.and_then(|json| json.get("derivation_accounts"));
|
||||||
|
|
||||||
let matches = icepick_command.get_matches();
|
let matches = icepick_command.get_matches();
|
||||||
if let Some((module, matches)) = matches.subcommand() {
|
if let Some((module, matches)) = matches.subcommand() {
|
||||||
|
@ -134,44 +134,77 @@ pub fn do_cli_thing() {
|
||||||
.find(|(name, ..)| *name == module)
|
.find(|(name, ..)| *name == module)
|
||||||
.and_then(|(.., operations)| operations.iter().find(|o| o.name == subcommand))
|
.and_then(|(.., operations)| operations.iter().find(|o| o.name == subcommand))
|
||||||
{
|
{
|
||||||
let mut args = std::collections::HashMap::<&String, Option<&String>>::with_capacity(
|
let mut args = std::collections::HashMap::<String, Option<&String>>::with_capacity(
|
||||||
operation.arguments.len(),
|
operation.arguments.len(),
|
||||||
);
|
);
|
||||||
for arg in &operation.arguments {
|
for arg in &operation.arguments {
|
||||||
args.insert(&arg.name, matches.get_one::<String>(&arg.name));
|
args.insert(
|
||||||
|
arg.name.replace('-', "_"),
|
||||||
|
matches.get_one::<String>(&arg.name),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (algo, path) = config.modules.iter().find_map(|fmodule| {
|
let (algo, path) = config
|
||||||
|
.modules
|
||||||
|
.iter()
|
||||||
|
.find_map(|fmodule| {
|
||||||
if fmodule.name == module {
|
if fmodule.name == module {
|
||||||
return Some((fmodule.algorithm.clone(), fmodule.derivation_prefix.clone()))
|
return Some((
|
||||||
|
fmodule.algorithm.clone(),
|
||||||
|
fmodule.derivation_prefix.clone(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}).unwrap();
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let mut derived_keys: Vec<Vec<u8>> = vec![];
|
let mut derived_keys: Vec<Vec<u8>> = vec![];
|
||||||
if let Some(accounts) = derivation_accounts {
|
if let Some(accounts) = derivation_accounts {
|
||||||
let accounts: Vec<keyfork_derive_util::DerivationIndex> =
|
let accounts: Vec<keyfork_derive_util::DerivationIndex> =
|
||||||
serde_json::from_value(accounts.clone())
|
serde_json::from_value(accounts.clone())
|
||||||
.expect("valid derivation-accounts");
|
.expect("valid derivation_accounts");
|
||||||
let mut client =
|
let mut client =
|
||||||
keyforkd_client::Client::discover_socket().expect("keyforkd started");
|
keyforkd_client::Client::discover_socket().expect("keyforkd started");
|
||||||
for account in accounts {
|
for account in accounts {
|
||||||
let request = keyfork_derive_util::request::DerivationRequest::new(algo.clone(), &path.clone().chain_push(account));
|
let request = keyfork_derive_util::request::DerivationRequest::new(
|
||||||
|
algo.clone(),
|
||||||
|
&path.clone().chain_push(account),
|
||||||
|
);
|
||||||
let request = keyforkd_models::Request::Derivation(request);
|
let request = keyforkd_models::Request::Derivation(request);
|
||||||
let response = client.request(&request).expect("valid derivation");
|
let response = client.request(&request).expect("valid derivation");
|
||||||
match response {
|
match response {
|
||||||
keyforkd_models::Response::Derivation(keyfork_derive_util::request::DerivationResponse { data, .. }) => {
|
keyforkd_models::Response::Derivation(
|
||||||
|
keyfork_derive_util::request::DerivationResponse { data, .. },
|
||||||
|
) => {
|
||||||
derived_keys.push(data.to_vec());
|
derived_keys.push(data.to_vec());
|
||||||
},
|
}
|
||||||
_ => panic!("Unexpected response"),
|
_ => panic!("Unexpected response"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// in the event this is not PascalCase, this would be false.
|
||||||
|
// we set this to true to capitalize the first character.
|
||||||
|
let mut last_char_was_dash = true;
|
||||||
|
let subcommand = subcommand
|
||||||
|
.chars()
|
||||||
|
.filter_map(|c| {
|
||||||
|
if last_char_was_dash {
|
||||||
|
last_char_was_dash = false;
|
||||||
|
return Some(c.to_ascii_uppercase());
|
||||||
|
}
|
||||||
|
if c == '-' {
|
||||||
|
last_char_was_dash = true;
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(c)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<String>();
|
||||||
let json = serde_json::json!({
|
let json = serde_json::json!({
|
||||||
"operation": subcommand,
|
"operation": subcommand,
|
||||||
"values": args,
|
"values": args,
|
||||||
"derived-keys": derived_keys,
|
"derived_keys": derived_keys,
|
||||||
"blob": blob,
|
"blob": blob,
|
||||||
});
|
});
|
||||||
let bin = commands
|
let bin = commands
|
||||||
|
|
|
@ -11,7 +11,7 @@ printf "%s" "Amount of token to transfer: "
|
||||||
read token_amount
|
read token_amount
|
||||||
|
|
||||||
echo "Acquiring blockhash..."
|
echo "Acquiring blockhash..."
|
||||||
blockhash="$(icepick sol get-blockhash --cluster devnet | jq -r .blob)"
|
blockhash="$(icepick sol get-blockhash --cluster devnet | jq -r .blob.blockhash)"
|
||||||
|
|
||||||
echo "Saving information to file"
|
echo "Saving information to file"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue