lwk_app 0.2.0

Liquid Wallet Kit - RPC server App
Documentation
use std::str::FromStr;

use lwk_rpc_model::{
    request::{self, Direction},
    response,
};
use schemars::schema_for;
use serde_json::Value;

#[derive(Debug, thiserror::Error)]
#[error("The rpc method '{name}' does not exist")]
pub struct MethodNotExist {
    name: String,
}

#[derive(Debug, PartialEq, Eq)]
#[cfg_attr(test, derive(enum_iterator::Sequence))]
pub enum Method {
    Schema,
    GenerateSigner,
    Version,
    LoadWallet,
    UnloadWallet,
    ListWallets,
    SignerLoadSoftware,
    SignerLoadJade,
    SignerLoadExternal,
    UnloadSigner,
    ListSigners,
    Address,
    Balance,
    SendMany,
    SinglesigDescriptor,
    MultisigDescriptor,
    RegisterMultisig,
    Xpub,
    Sign,
    Broadcast,
    WalletDetails,
    WalletCombine,
    WalletPsetDetails,
    WalletUtxos,
    WalletTxs,
    Issue,
    Reissue,
    Contract,
    AssetDetails,
    ListAssets,
    AssetInsert,
    AssetRemove,
    Stop,
    SignerJadeId,
}
impl Method {
    pub(crate) fn schema(&self, direction: request::Direction) -> Result<Value, serde_json::Error> {
        serde_json::to_value(match direction {
            Direction::Request => match self {
                Method::Schema => schema_for!(request::Schema),
                Method::GenerateSigner => schema_for!(request::Empty),
                Method::Version => schema_for!(request::Empty),
                Method::LoadWallet => schema_for!(request::LoadWallet),
                Method::UnloadWallet => schema_for!(request::UnloadWallet),
                Method::ListWallets => schema_for!(request::Empty),
                Method::SignerLoadSoftware => schema_for!(request::SignerLoadSoftware),
                Method::SignerLoadJade => schema_for!(request::SignerLoadJade),
                Method::SignerLoadExternal => schema_for!(request::SignerLoadExternal),
                Method::UnloadSigner => schema_for!(request::UnloadSigner),
                Method::ListSigners => schema_for!(request::Empty),
                Method::Address => schema_for!(request::Address),
                Method::Balance => schema_for!(request::Balance),
                Method::SendMany => schema_for!(request::Send),
                Method::SinglesigDescriptor => schema_for!(request::SinglesigDescriptor),
                Method::MultisigDescriptor => schema_for!(request::MultisigDescriptor),
                Method::RegisterMultisig => schema_for!(request::RegisterMultisig),
                Method::Xpub => schema_for!(request::Xpub),
                Method::Sign => schema_for!(request::Sign),
                Method::Broadcast => schema_for!(request::Broadcast),
                Method::WalletDetails => schema_for!(request::WalletDetails),
                Method::WalletCombine => schema_for!(request::WalletCombine),
                Method::WalletPsetDetails => schema_for!(request::WalletPsetDetails),
                Method::WalletUtxos => schema_for!(request::WalletUtxos),
                Method::WalletTxs => schema_for!(request::WalletTxs),
                Method::Issue => schema_for!(request::Issue),
                Method::Reissue => schema_for!(request::Reissue),
                Method::Contract => schema_for!(request::Contract),
                Method::AssetDetails => schema_for!(request::AssetDetails),
                Method::ListAssets => schema_for!(request::Empty),
                Method::AssetInsert => schema_for!(request::AssetInsert),
                Method::AssetRemove => schema_for!(request::AssetRemove),
                Method::Stop => schema_for!(request::Empty),
                Method::SignerJadeId => schema_for!(request::Empty),
            },
            Direction::Response => match self {
                Method::Schema => return serde_json::from_str(include_str!("../schema.json")),
                Method::GenerateSigner => schema_for!(response::GenerateSigner),
                Method::Version => schema_for!(response::Version),
                Method::LoadWallet => schema_for!(response::Wallet),
                Method::UnloadWallet => schema_for!(response::UnloadWallet),
                Method::ListWallets => schema_for!(response::ListWallets),
                Method::SignerLoadSoftware => schema_for!(response::Signer),
                Method::SignerLoadJade => schema_for!(response::Signer),
                Method::SignerLoadExternal => schema_for!(response::Signer),
                Method::UnloadSigner => schema_for!(response::UnloadSigner),
                Method::ListSigners => schema_for!(response::ListSigners),
                Method::Address => schema_for!(response::Address),
                Method::Balance => schema_for!(response::Balance),
                Method::SendMany => schema_for!(response::Pset),
                Method::SinglesigDescriptor => schema_for!(response::SinglesigDescriptor),
                Method::MultisigDescriptor => schema_for!(response::MultisigDescriptor),
                Method::RegisterMultisig => schema_for!(response::Empty),
                Method::Xpub => schema_for!(response::Xpub),
                Method::Sign => schema_for!(response::Pset),
                Method::Broadcast => schema_for!(response::Broadcast),
                Method::WalletDetails => schema_for!(response::WalletDetails),
                Method::WalletCombine => schema_for!(response::WalletCombine),
                Method::WalletPsetDetails => schema_for!(response::WalletPsetDetails),
                Method::WalletUtxos => schema_for!(response::WalletUtxos),
                Method::WalletTxs => schema_for!(response::WalletTxs),
                Method::Issue => schema_for!(response::Pset),
                Method::Reissue => schema_for!(response::Pset),
                Method::Contract => schema_for!(response::Contract),
                Method::AssetDetails => schema_for!(response::AssetDetails),
                Method::ListAssets => schema_for!(response::ListAssets),
                Method::AssetInsert => schema_for!(response::Empty),
                Method::AssetRemove => schema_for!(request::Empty),
                Method::Stop => schema_for!(request::Empty),
                Method::SignerJadeId => schema_for!(response::JadeId),
            },
        })
    }
}

impl FromStr for Method {
    type Err = MethodNotExist;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(match s {
            "schema" => Method::Schema,
            "generate_signer" => Method::GenerateSigner,
            "version" => Method::Version,
            "load_wallet" => Method::LoadWallet,
            "unload_wallet" => Method::UnloadWallet,
            "list_wallets" => Method::ListWallets,
            "signer_load_software" => Method::SignerLoadSoftware,
            "signer_load_jade" => Method::SignerLoadJade,
            "signer_load_external" => Method::SignerLoadExternal,
            "unload_signer" => Method::UnloadSigner,
            "list_signers" => Method::ListSigners,
            "address" => Method::Address,
            "balance" => Method::Balance,
            "send_many" => Method::SendMany,
            "singlesig_descriptor" => Method::SinglesigDescriptor,
            "multisig_descriptor" => Method::MultisigDescriptor,
            "register_multisig" => Method::RegisterMultisig,
            "xpub" => Method::Xpub,
            "sign" => Method::Sign,
            "broadcast" => Method::Broadcast,
            "wallet_details" => Method::WalletDetails,
            "wallet_combine" => Method::WalletCombine,
            "wallet_pset_details" => Method::WalletPsetDetails,
            "wallet_utxos" => Method::WalletUtxos,
            "wallet_txs" => Method::WalletTxs,
            "issue" => Method::Issue,
            "reissue" => Method::Reissue,
            "contract" => Method::Contract,
            "asset_details" => Method::AssetDetails,
            "list_assets" => Method::ListAssets,
            "asset_insert" => Method::AssetInsert,
            "asset_remove" => Method::AssetRemove,
            "signer_jade_id" => Method::SignerJadeId,
            "stop" => Method::Stop,
            _ => {
                return Err(MethodNotExist {
                    name: s.to_string(),
                })
            }
        })
    }
}

impl std::fmt::Display for Method {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let s = match self {
            Method::Schema => "schema",
            Method::GenerateSigner => "generate_signer",
            Method::Version => "version",
            Method::LoadWallet => "load_wallet",
            Method::UnloadWallet => "unload_wallet",
            Method::ListWallets => "list_wallets",
            Method::SignerLoadSoftware => "signer_load_software",
            Method::SignerLoadJade => "signer_load_jade",
            Method::SignerLoadExternal => "signer_load_external",
            Method::UnloadSigner => "unload_signer",
            Method::ListSigners => "list_signers",
            Method::Address => "address",
            Method::Balance => "balance",
            Method::SendMany => "send_many",
            Method::SinglesigDescriptor => "singlesig_descriptor",
            Method::MultisigDescriptor => "multisig_descriptor",
            Method::RegisterMultisig => "register_multisig",
            Method::Xpub => "xpub",
            Method::Sign => "sign",
            Method::Broadcast => "broadcast",
            Method::WalletDetails => "wallet_details",
            Method::WalletCombine => "wallet_combine",
            Method::WalletPsetDetails => "wallet_pset_details",
            Method::WalletUtxos => "wallet_utxos",
            Method::WalletTxs => "wallet_txs",
            Method::Issue => "issue",
            Method::Reissue => "reissue",
            Method::Contract => "contract",
            Method::AssetDetails => "asset_details",
            Method::ListAssets => "list_assets",
            Method::AssetInsert => "asset_insert",
            Method::AssetRemove => "asset_remove",
            Method::Stop => "stop",
            Method::SignerJadeId => "signer_jade_id",
        };
        write!(f, "{}", s)
    }
}

#[cfg(test)]
mod test {
    use enum_iterator::all;

    use super::Method;

    #[test]
    fn method_roundtrip() {
        let all = all::<Method>().collect::<Vec<_>>();
        for m in all {
            assert_eq!(m, m.to_string().parse().unwrap())
        }
    }
}