# Code Template

### Steps

#### 1. Implement `CommandTrait` :

1. `fn name() -> Name` : return the name of the command
2. `fn inputs() -> Vec<CmdInputDescription>` : return an array of input description, fields are:
   1. `name`: name of the input
   2. `type_bounds` : allowed types
   3. `required`&#x20;
   4. `passthrough` : if `true`, this field will be present in the output
3. `fn outputs() -> Vec<CmdOutputDescription>`:&#x20;
   1. `name`: name of the output
   2. `type`: type of the output
4. `async fn run(&self, ctx: Arc<Context>, inputs: ValueSet) -> Result<ValueSet, Error> {}`

#### 2. Submit with `inventory::submit`

#### 3. To get inputs, define a struct that implement Deserialize:

```rust
#[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,
}
```

Then get the input from a [`ValueSet`](/visual-builder/nodes/native-nodes/valueset.md) with `value::from_map` :&#x20;

```rust
 let input: Input = value::from_map(inputs)?;
```

#### 4. Output is the same, but derive Serialize on it and use `value::to_map`.

```rust
Ok(value::to_map(&Output {
  pubkey: keypair.pubkey(),
  keypair,
})?)
```

Documentation on <https://serde.rs/> is useful.

### Example

<figure><img src="/files/szCEbyrwM0XZhhEmW38R" alt=""><figcaption></figcaption></figure>

```rust
// 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
)));

```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.spaceoperator.com/visual-builder/nodes/native-nodes/code-template.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
