#[derive(Serialize, Deserialize, Debug)]
pub struct Input {
// special types like Keypair, Pubkey, Signature, Decimal
// have to be decorated with `#[serde(with = "...")]`
#[serde(with = "value::keypair")]
pub sender: Keypair,
#[serde(with = "value::pubkey")]
pub recipient: Pubkey,
// use default and ::opt for optional value
#[serde(default, with = "value::pubkey::opt")]
pub opt_pubkey: Option<Pubkey>,
#[serde(with = "value::decimal")]
pub amount: Decimal,
// optional input with a default value,
// use `#[serde(default = ...)]`
#[serde(default = "value::default::bool_true")]
pub submit: bool,
}
let input: Input = value::from_map(inputs)?;
Ok(value::to_map(&Output {
pubkey: keypair.pubkey(),
keypair,
})?)
// assuming `crate` is `cmds-solana`
use crate::prelude::*;
#[derive(Debug, Clone)]
pub struct TransferSol;
#[derive(Serialize, Deserialize, Debug)]
pub struct Input {
#[serde(with = "value::keypair")]
pub sender: Keypair,
#[serde(with = "value::pubkey")]
pub recipient: Pubkey,
#[serde(with = "value::decimal")]
pub amount: Decimal,
// optional `submit` input, `true` is not present
#[serde(default = "value::default::bool_true")]
pub submit: bool,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Output {
// optional `signature` output, needs `::opt`
#[serde(with = "value::signature::opt")]
pub signature: Option<Signature>,
pub tx: String,
}
const SOLANA_TRANSFER_SOL: &str = "transfer_sol";
// Inputs
const SENDER: &str = "sender";
const RECIPIENT: &str = "recipient";
const AMOUNT: &str = "amount";
const SUBMIT: &str = "submit";
// Outputs
const TX: &str = "tx";
const SIGNATURE: &str = "signature";
#[async_trait]
impl CommandTrait for TransferSol {
fn name(&self) -> Name {
SOLANA_TRANSFER_SOL.into()
}
fn inputs(&self) -> Vec<CmdInput> {
[
CmdInput {
name: SENDER.into(),
type_bounds: [ValueType::Keypair, ValueType::String].to_vec(),
required: true,
passthrough: false,
},
CmdInput {
name: RECIPIENT.into(),
type_bounds: [ValueType::Pubkey, ValueType::Keypair, ValueType::String].to_vec(),
required: true,
passthrough: false,
},
CmdInput {
name: AMOUNT.into(),
type_bounds: [ValueType::F64].to_vec(),
required: true,
passthrough: false,
},
CmdInput {
name: SUBMIT.into(),
type_bounds: [ValueType::Bool].to_vec(),
required: false,
passthrough: false,
},
]
.to_vec()
}
fn outputs(&self) -> Vec<CmdOutput> {
[
CmdOutput {
name: SIGNATURE.into(),
r#type: ValueType::String,
},
CmdOutput {
name: TX.into(),
r#type: ValueType::String,
},
]
.to_vec()
}
async fn run(&self, ctx: Arc<Context>, inputs: ValueSet) -> flow::Result<ValueSet> {
let input: Input = value::from_map(inputs)?;
// ...
Ok(value::to_map(&Output {
signature,
tx: tx_str,
})?)
}
}
inventory::submit!(CommandDescription::new(SOLANA_TRANSFER_SOL, |_| Box::new(
TransferSol
)));