Skip to content

Commit 7ad91e6

Browse files
committed
runtime, cli: payment workflow
1 parent e03adc6 commit 7ad91e6

File tree

10 files changed

+223
-112
lines changed

10 files changed

+223
-112
lines changed

Cargo.lock

Lines changed: 27 additions & 37 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ bp-esplora = "0.11.0-beta.1"
3838
descriptors = "0.11.0-beta.1"
3939
psbt = { version = "0.11.0-beta.1", features = ["client-side-validation"] }
4040
rgb-std = { version = "0.11.0-beta.2", features = ["fs"] }
41+
rgb-psbt = { version = "0.11.0-alpha.2", path = "psbt" }
4142
indexmap = "2.0.2"
4243
chrono = "0.4.31"
4344
serde_crate = { package = "serde", version = "1", features = ["derive"] }
@@ -70,8 +71,8 @@ bp-std = { workspace = true }
7071
bp-wallet = { workspace = true, features = ["fs"] }
7172
bp-esplora = { workspace = true, optional = true }
7273
descriptors = { workspace = true }
73-
psbt = { workspace = true }
7474
rgb-std = { workspace = true }
75+
rgb-psbt = { workspace = true }
7576
rgb-persist-fs = { version = "0.11.0-alpha", path = "fs" }
7677
indexmap = { workspace = true }
7778
chrono = { workspace = true }

cli/src/command.rs

Lines changed: 43 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,22 @@
2020
// limitations under the License.
2121

2222
use std::fs;
23+
use std::fs::File;
2324
use std::path::PathBuf;
2425
use std::str::FromStr;
2526

2627
use amplify::confinement::U16;
2728
use bp_util::{Config, Exec};
2829
use bpstd::{Sats, Txid};
29-
use bpwallet::{Invoice, TxParams};
30-
use rgb_rt::{DescriptorRgb, RgbDescr, RgbKeychain, RuntimeError};
30+
use psbt::PsbtVer;
31+
use rgb_rt::{DescriptorRgb, RgbDescr, RgbKeychain, RuntimeError, TransferParams};
3132
use rgbstd::containers::{Bindle, Transfer, UniversalBindle};
3233
use rgbstd::contract::{ContractId, GenesisSeal, GraphSeal, StateType};
3334
use rgbstd::interface::{ContractBuilder, FilterExclude, IfaceId, SchemaIfaces};
3435
use rgbstd::invoice::{Beneficiary, InvoiceState, RgbInvoice, RgbTransport};
3536
use rgbstd::persistence::{Inventory, Stash};
3637
use rgbstd::schema::SchemaId;
37-
use rgbstd::SealDefinition;
38+
use rgbstd::XSeal;
3839
use seals::txout::{CloseMethod, ExplicitSeal};
3940
use strict_types::encoding::{FieldName, TypeName};
4041
use strict_types::StrictVal;
@@ -139,10 +140,19 @@ pub enum Command {
139140
/// Transfer RGB assets
140141
#[display("transfer")]
141142
Transfer {
143+
/// Encode PSBT as V2
144+
#[clap(short = '2')]
145+
v2: bool,
146+
142147
/// Method for single-use-seals
143148
#[clap(long, default_value = "tapret1st")]
144149
method: CloseMethod,
145150

151+
/// Amount of satoshis which should be paid to the address-based
152+
/// beneficiary
153+
#[clap(long, default_value = "2000")]
154+
sats: Sats,
155+
146156
/// Invoice data
147157
invoice: RgbInvoice,
148158

@@ -295,7 +305,7 @@ impl Exec for RgbArgs {
295305
contract,
296306
file,
297307
} => {
298-
let mut runtime = self.rgb_runtime(&config)?;
308+
let runtime = self.rgb_runtime(&config)?;
299309
let bindle = runtime
300310
.export_contract(*contract)
301311
.map_err(|err| err.to_string())?;
@@ -471,7 +481,7 @@ impl Exec for RgbArgs {
471481
.expect("seal must be a string");
472482
let seal =
473483
ExplicitSeal::<Txid>::from_str(seal).expect("invalid seal definition");
474-
let seal = GenesisSeal::from(seal);
484+
let seal = XSeal::Bitcoin(GenesisSeal::from(seal));
475485

476486
// Workaround for borrow checker:
477487
let field_name =
@@ -537,15 +547,15 @@ impl Exec for RgbArgs {
537547
.next()
538548
.expect("no addresses left")
539549
.addr;
540-
Beneficiary::WitnessUtxo(addr)
550+
Beneficiary::WitnessVoutBitcoin(addr)
541551
}
542552
(_, Some(outpoint)) => {
543553
let seal = GraphSeal::new(
544554
runtime.wallet().seal_close_method(),
545555
outpoint.txid,
546556
outpoint.vout,
547557
);
548-
runtime.store_seal_secret(SealDefinition::Bitcoin(seal))?;
558+
runtime.store_seal_secret(XSeal::Bitcoin(seal))?;
549559
Beneficiary::BlindedSeal(seal.to_concealed_seal())
550560
}
551561
};
@@ -565,40 +575,36 @@ impl Exec for RgbArgs {
565575
}
566576
#[allow(unused_variables)]
567577
Command::Transfer {
578+
v2,
568579
method,
569580
invoice,
570581
fee,
571-
psbt: psbt_filename,
582+
sats,
583+
psbt: psbt_file,
572584
consignment: out_file,
573585
} => {
574-
// 1. BP Wallet: Do coin selection (using Layer2 components)
575-
// 2. BP Wallet: Construct PSBT prototype (no state transitions)
576-
// ... complete PSBT structure updates in multi-party protocols
577-
// 3. RGB Std: Prepare stencil - main state transition and blank state
578-
// transitions
579-
// 4. RGB PSBT: Embed stencil into PSBT
580-
// ... complete PSBT client-side updates in multi-party protocols
581-
// 5. RGB PSBT: Anchorize PSBT, extract disclosure
582-
// 6. RGB Std: Merge disclosure into the stash, cache and index
583-
// 7. RGB Std: Prepare consignment
584-
585586
let mut runtime = self.rgb_runtime(&config)?;
586-
587587
// TODO: Support lock time and RBFs
588-
let params = TxParams::with(*fee);
588+
let params = TransferParams::with(*fee, *sats);
589589

590-
eprint!("Constructing PSBT ... ");
591-
let mut psbt = runtime
592-
.wallet_mut()
593-
.construct_psbt(coins, Invoice, params)?;
594-
eprintln!("success");
595-
596-
eprint!("Constructing transfer consignment ... ");
597-
let transfer = runtime
598-
.pay(invoice, &mut psbt, method)
590+
let (psbt, meta, transfer) = runtime
591+
.pay(invoice, *method, params)
599592
.map_err(|err| err.to_string())?;
593+
600594
transfer.save(&out_file)?;
601-
eprintln!("success");
595+
596+
let ver = if *v2 { PsbtVer::V2 } else { PsbtVer::V0 };
597+
eprintln!("{}", serde_yaml::to_string(&psbt).unwrap());
598+
match psbt_file {
599+
Some(file_name) => {
600+
let mut psbt_file = File::create(file_name)?;
601+
psbt.encode(ver, &mut psbt_file)?;
602+
}
603+
None => match ver {
604+
PsbtVer::V0 => println!("{psbt}"),
605+
PsbtVer::V2 => println!("{psbt:#}"),
606+
},
607+
}
602608
}
603609
Command::Inspect { file, format } => {
604610
let bindle = UniversalBindle::load_file(file)?;
@@ -651,7 +657,11 @@ impl Exec for RgbArgs {
651657
format!("{root_dir}/stash/geneses/{id}.yaml"),
652658
serde_yaml::to_string(runtime.genesis(id)?)?,
653659
)?;
654-
for (no, suppl) in runtime.contract_suppl(id).into_iter().flatten().enumerate()
660+
for (no, suppl) in runtime
661+
.contract_suppl_all(id)
662+
.into_iter()
663+
.flatten()
664+
.enumerate()
655665
{
656666
fs::write(
657667
format!("{root_dir}/stash/geneses/{id}.suppl.{no:03}.yaml"),
@@ -665,7 +675,7 @@ impl Exec for RgbArgs {
665675
serde_yaml::to_string(runtime.bundle(id)?)?,
666676
)?;
667677
}
668-
for id in runtime.anchor_ids()? {
678+
for id in runtime.witness_ids()? {
669679
fs::write(
670680
format!("{root_dir}/stash/anchors/{id}.yaml"),
671681
serde_yaml::to_string(runtime.anchor(id)?)?,

cli/src/resolver.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,20 @@ use std::convert::Infallible;
2424
use bpstd::{Tx, Txid};
2525
use rgbstd::resolvers::ResolveHeight;
2626
use rgbstd::validation::{ResolveTx, TxResolverError};
27-
use rgbstd::{Anchor, Layer1, WitnessAnchor};
27+
use rgbstd::{Layer1, WitnessAnchor, XAnchor};
2828

2929
use crate::RgbArgs;
3030

3131
// TODO: Embed in contract issuance builder
3232
pub struct PanickingResolver;
3333
impl ResolveHeight for PanickingResolver {
3434
type Error = Infallible;
35-
fn resolve_anchor(&mut self, _: &Anchor) -> Result<WitnessAnchor, Self::Error> {
35+
fn resolve_anchor(&mut self, _: &XAnchor) -> Result<WitnessAnchor, Self::Error> {
3636
unreachable!("PanickingResolver must be used only for newly issued contract validation")
3737
}
3838
}
3939
impl ResolveTx for PanickingResolver {
40-
fn resolve_tx(&self, _: Layer1, _: Txid) -> Result<Tx, TxResolverError> {
40+
fn resolve_bp_tx(&self, _: Layer1, _: Txid) -> Result<Tx, TxResolverError> {
4141
unreachable!("PanickingResolver must be used only for newly issued contract validation")
4242
}
4343
}
@@ -48,12 +48,12 @@ impl RgbArgs {
4848
struct DumbResolver();
4949
impl ResolveHeight for DumbResolver {
5050
type Error = Infallible;
51-
fn resolve_anchor(&mut self, _: &Anchor) -> Result<WitnessAnchor, Self::Error> {
51+
fn resolve_anchor(&mut self, _: &XAnchor) -> Result<WitnessAnchor, Self::Error> {
5252
todo!()
5353
}
5454
}
5555
impl ResolveTx for DumbResolver {
56-
fn resolve_tx(&self, _: Layer1, _: Txid) -> Result<Tx, TxResolverError> { todo!() }
56+
fn resolve_bp_tx(&self, _: Layer1, _: Txid) -> Result<Tx, TxResolverError> { todo!() }
5757
}
5858
DumbResolver::default()
5959
}

psbt/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[package]
2-
name = "psbt-rgb"
2+
name = "rgb-psbt"
33
version = { workspace = true }
44
description = "Partially signed bitcoin transaction RGB extensions"
55
keywords = ["bitcoin", "invoices", "rgb", "smart-contracts", "psbt"]

psbt/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ mod rgb;
2626

2727
use bp::dbc::opret::OpretProof;
2828
use bp::dbc::tapret::TapretProof;
29-
use psbt::{DbcPsbtError, Psbt};
29+
pub use psbt::*;
3030
use rgbstd::containers::{Batch, Fascia, XchainOutpoint};
3131
use rgbstd::{AnchorSet, XAnchor};
3232

0 commit comments

Comments
 (0)