Skip to content

Commit 32968fc

Browse files
authored
feat: refactor transaction sub-commands (#20)
1 parent 71f8799 commit 32968fc

File tree

4 files changed

+247
-183
lines changed

4 files changed

+247
-183
lines changed

src/transaction/mod.rs

Lines changed: 10 additions & 181 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,22 @@
1-
use std::path::PathBuf;
2-
31
use clap::{Parser, Subcommand};
4-
use jsonrpsee::core::params::ObjectParams;
5-
use miette::{bail, Context, IntoDiagnostic};
62
use tracing::instrument;
7-
use tx3_lang::Protocol;
83

4+
mod new;
95
mod resolve;
106
mod sign;
117
mod submit;
128

139
#[derive(Parser)]
1410
pub struct Args {
15-
#[arg(long, help = "Path for TX3 file describing transaction")]
16-
tx3_file: Option<PathBuf>,
17-
18-
#[arg(long, help = "Args for TX3 file describing transaction")]
19-
tx3_args_json: Option<String>,
20-
21-
#[arg(long, help = "Template for TX3 file")]
22-
tx3_template: Option<String>,
23-
24-
#[arg(long, help = "Wallet that will sign the transaction")]
25-
signer: Option<String>,
26-
27-
/// Name of the provider to use. If undefined, will use default
28-
#[arg(long, help = "Path for TX3 file describing transaction")]
29-
provider: Option<String>,
30-
3111
#[command(subcommand)]
32-
command: Option<Commands>,
12+
command: Commands,
3313
}
3414

3515
#[derive(Subcommand)]
3616
enum Commands {
17+
/// Start a new full transaction, resolve, sign and submit
18+
New(new::Args),
19+
3720
/// Resolve a transaction
3821
Resolve(resolve::Args),
3922

@@ -47,163 +30,9 @@ enum Commands {
4730
#[instrument("transaction", skip_all)]
4831
pub async fn run(args: Args, ctx: &crate::Context) -> miette::Result<()> {
4932
match args.command {
50-
Some(command) => match command {
51-
Commands::Sign(args) => sign::run(args, ctx).await?,
52-
Commands::Submit(args) => submit::run(args, ctx).await?,
53-
Commands::Resolve(args) => resolve::run(args, ctx).await?,
54-
},
55-
None => {
56-
let provider = match args.provider {
57-
Some(name) => ctx.store.find_provider(&name),
58-
None => ctx.store.default_provider(),
59-
};
60-
61-
let Some(provider) = provider else {
62-
bail!("Provider not found")
63-
};
64-
65-
let Some(tx3_file) = args.tx3_file else {
66-
bail!("Tx3 file not provided")
67-
};
68-
69-
let protocol = Protocol::from_file(tx3_file)
70-
.load()
71-
.into_diagnostic()
72-
.context("parsing tx3 file")?;
73-
74-
let txs: Vec<String> = protocol.txs().map(|x| x.name.to_string()).collect();
75-
76-
let template = match args.tx3_template {
77-
Some(template) => template,
78-
None => {
79-
let template = if txs.len() == 1 {
80-
txs.first().unwrap().clone()
81-
} else {
82-
inquire::Select::new("What transaction do you want to build?", txs)
83-
.prompt()
84-
.into_diagnostic()?
85-
};
86-
template
87-
}
88-
};
89-
90-
let prototx = protocol.new_tx(&template).unwrap();
91-
92-
let argvalues = match args.tx3_args_json {
93-
Some(args) => {
94-
let json_value = serde_json::from_str(&args)
95-
.into_diagnostic()
96-
.context("invalid tx3-args")?;
97-
98-
let serde_json::Value::Object(value) = json_value else {
99-
bail!("tx3-args must be an object");
100-
};
101-
102-
value
103-
}
104-
None => {
105-
let params = prototx.find_params();
106-
let mut argvalues = serde_json::Map::new();
107-
for (key, value) in params {
108-
match value {
109-
tx3_lang::ir::Type::Address => {
110-
let options = ctx
111-
.store
112-
.wallets()
113-
.iter()
114-
.map(|x| x.name.to_string())
115-
.collect();
116-
let wallet = inquire::Select::new(&format!("{}: ", &key), options)
117-
.prompt()
118-
.into_diagnostic()?;
119-
let address = ctx
120-
.store
121-
.wallets()
122-
.iter()
123-
.find(|x| x.name.to_string() == wallet)
124-
.unwrap()
125-
.address(provider.is_testnet());
126-
argvalues.insert(
127-
key,
128-
serde_json::Value::String(address.to_bech32().unwrap()),
129-
);
130-
}
131-
tx3_lang::ir::Type::Int => {
132-
let value = inquire::Text::new(&format!("{}: ", &key))
133-
.prompt()
134-
.into_diagnostic()?
135-
.parse::<u64>()
136-
.into_diagnostic()
137-
.context("invalid integer value")?;
138-
argvalues.insert(key, serde_json::Value::Number(value.into()));
139-
}
140-
_ => todo!(),
141-
};
142-
}
143-
argvalues
144-
}
145-
};
146-
147-
let mut builder = ObjectParams::new();
148-
builder
149-
.insert(
150-
"tir",
151-
serde_json::json!({
152-
"version": tx3_lang::ir::IR_VERSION.to_string(),
153-
"encoding": "hex",
154-
"bytecode": hex::encode(prototx.ir_bytes())
155-
}),
156-
)
157-
.unwrap();
158-
builder.insert("args", argvalues).unwrap();
159-
160-
let response = provider.trp_resolve(&builder).await?;
161-
let signer = match args.signer {
162-
Some(signer) => signer,
163-
None => {
164-
let options = ctx
165-
.store
166-
.wallets()
167-
.iter()
168-
.map(|x| x.name.to_string())
169-
.collect();
170-
inquire::Select::new(
171-
"What wallet should be used to sign the transaction?",
172-
options,
173-
)
174-
.prompt()
175-
.into_diagnostic()?
176-
}
177-
};
178-
179-
let wallet = ctx
180-
.store
181-
.wallets()
182-
.iter()
183-
.find(|x| x.name.to_string() == signer);
184-
185-
let Some(wallet) = wallet else {
186-
bail!("invalid signer wallet")
187-
};
188-
189-
let password = match wallet.is_unsafe {
190-
true => None,
191-
false => Some(
192-
inquire::Password::new("Password:")
193-
.with_help_message("The spending password of your wallet")
194-
.with_display_mode(inquire::PasswordDisplayMode::Masked)
195-
.prompt()
196-
.into_diagnostic()?,
197-
),
198-
};
199-
200-
let signed = wallet.sign(response.tx, &password)?;
201-
let txhash = provider.submit(&signed).await?;
202-
203-
println!("Submitted TX: {}", hex::encode(&signed));
204-
println!("TX Hash: {}", hex::encode(&txhash));
205-
}
206-
};
207-
208-
Ok(())
33+
Commands::New(args) => new::run(args, ctx).await,
34+
Commands::Resolve(args) => resolve::run(args, ctx).await,
35+
Commands::Sign(args) => sign::run(args, ctx).await,
36+
Commands::Submit(args) => submit::run(args, ctx).await,
37+
}
20938
}

0 commit comments

Comments
 (0)