@@ -1596,31 +1596,47 @@ impl<S: MutinyStorage> MutinyWallet<S> {
15961596 pub async fn sweep_federation_balance (
15971597 & self ,
15981598 amount : Option < u64 > ,
1599+ from_federation_id : Option < FederationId > ,
1600+ to_federation_id : Option < FederationId > ,
15991601 ) -> Result < FedimintSweepResult , MutinyError > {
1600- // TODO support more than one federation
16011602 let federation_ids = self . list_federation_ids ( ) . await ?;
16021603 if federation_ids. is_empty ( ) {
16031604 return Err ( MutinyError :: NotFound ) ;
16041605 }
1605- let federation_id = & federation_ids[ 0 ] ;
1606+ let from_federation_id = from_federation_id . unwrap_or ( federation_ids[ 0 ] ) ;
16061607 let federation_lock = self . federations . read ( ) . await ;
1607- let fedimint_client = federation_lock
1608- . get ( federation_id )
1608+ let from_fedimint_client = federation_lock
1609+ . get ( & from_federation_id )
16091610 . ok_or ( MutinyError :: NotFound ) ?;
16101611
1612+ // decide to sweep to secondary federation or lightning node
1613+ let to_federation_client = match to_federation_id {
1614+ Some ( f) => Some ( federation_lock. get ( & f) . ok_or ( MutinyError :: NotFound ) ?) ,
1615+ None => None ,
1616+ } ;
1617+
16111618 let labels = vec ! [ SWAP_LABEL . to_string( ) ] ;
16121619
16131620 // if the user provided amount, this is easy
16141621 if let Some ( amt) = amount {
1615- let ( inv, fee) = self
1616- . node_manager
1617- . create_invoice ( amt, labels. clone ( ) )
1618- . await ?;
1622+ let ( inv, fee) = match to_federation_client {
1623+ Some ( f) => {
1624+ // swap from one federation to another
1625+ let inv = f. get_invoice ( amt, labels. clone ( ) ) . await ?;
1626+ ( inv, 0 )
1627+ }
1628+ None => {
1629+ // use the lightning node if no to federation selected
1630+ self . node_manager
1631+ . create_invoice ( amt, labels. clone ( ) )
1632+ . await ?
1633+ }
1634+ } ;
16191635
16201636 let bolt_11 = inv. bolt11 . expect ( "create inv had one job" ) ;
16211637 self . storage
16221638 . set_invoice_labels ( bolt_11. clone ( ) , labels. clone ( ) ) ?;
1623- let pay_res = fedimint_client . pay_invoice ( bolt_11, labels) . await ?;
1639+ let pay_res = from_fedimint_client . pay_invoice ( bolt_11, labels) . await ?;
16241640 let total_fees_paid = pay_res. fees_paid . unwrap_or ( 0 ) + fee;
16251641
16261642 return Ok ( FedimintSweepResult {
@@ -1630,24 +1646,33 @@ impl<S: MutinyStorage> MutinyWallet<S> {
16301646 }
16311647
16321648 // If no amount, figure out the amount to send over
1633- let current_balance = fedimint_client . get_balance ( ) . await ?;
1649+ let current_balance = from_fedimint_client . get_balance ( ) . await ?;
16341650 log_debug ! (
16351651 self . logger,
16361652 "current fedimint client balance: {}" ,
16371653 current_balance
16381654 ) ;
16391655
1640- let fees = fedimint_client . gateway_fee ( ) . await ?;
1656+ let fees = from_fedimint_client . gateway_fee ( ) . await ?;
16411657 // FIXME: this is still producing off by one. check round down
16421658 let amt = max_spendable_amount ( current_balance, & fees)
16431659 . map_or ( Err ( MutinyError :: InsufficientBalance ) , Ok ) ?;
16441660 log_debug ! ( self . logger, "max spendable: {}" , amt) ;
16451661
16461662 // try to get an invoice for this exact amount
1647- let ( inv, fee) = self
1648- . node_manager
1649- . create_invoice ( amt, labels. clone ( ) )
1650- . await ?;
1663+ let ( inv, fee) = match to_federation_client {
1664+ Some ( f) => {
1665+ // swap from one federation to another
1666+ let inv = f. get_invoice ( amt, labels. clone ( ) ) . await ?;
1667+ ( inv, 0 )
1668+ }
1669+ None => {
1670+ // use the lightning node if no to federation selected
1671+ self . node_manager
1672+ . create_invoice ( amt, labels. clone ( ) )
1673+ . await ?
1674+ }
1675+ } ;
16511676
16521677 // check if we can afford that invoice
16531678 let inv_amt = inv. amount_sats . ok_or ( MutinyError :: BadAmountError ) ?;
@@ -1660,9 +1685,19 @@ impl<S: MutinyStorage> MutinyWallet<S> {
16601685
16611686 // if invoice amount changed, create a new invoice
16621687 let ( inv_to_pay, fee) = if first_invoice_amount != inv_amt {
1663- self . node_manager
1664- . create_invoice ( first_invoice_amount, labels. clone ( ) )
1665- . await ?
1688+ match to_federation_client {
1689+ Some ( f) => {
1690+ // swap from one federation to another
1691+ let inv = f. get_invoice ( amt, labels. clone ( ) ) . await ?;
1692+ ( inv, 0 )
1693+ }
1694+ None => {
1695+ // use the lightning node if no to federation selected
1696+ self . node_manager
1697+ . create_invoice ( amt, labels. clone ( ) )
1698+ . await ?
1699+ }
1700+ }
16661701 } else {
16671702 ( inv. clone ( ) , fee)
16681703 } ;
@@ -1671,9 +1706,9 @@ impl<S: MutinyStorage> MutinyWallet<S> {
16711706 let bolt_11 = inv_to_pay. bolt11 . expect ( "create inv had one job" ) ;
16721707 self . storage
16731708 . set_invoice_labels ( bolt_11. clone ( ) , labels. clone ( ) ) ?;
1674- let first_invoice_res = fedimint_client . pay_invoice ( bolt_11, labels) . await ?;
1709+ let first_invoice_res = from_fedimint_client . pay_invoice ( bolt_11, labels) . await ?;
16751710
1676- let remaining_balance = fedimint_client . get_balance ( ) . await ?;
1711+ let remaining_balance = from_fedimint_client . get_balance ( ) . await ?;
16771712 if remaining_balance > 0 {
16781713 // there was a remainder when there shouldn't have been
16791714 // for now just log this, it is probably just a millisat/1 sat difference
@@ -1695,31 +1730,38 @@ impl<S: MutinyStorage> MutinyWallet<S> {
16951730 pub async fn estimate_sweep_federation_fee (
16961731 & self ,
16971732 amount : Option < u64 > ,
1733+ from_federation_id : Option < FederationId > ,
1734+ to_federation_id : Option < FederationId > ,
16981735 ) -> Result < Option < u64 > , MutinyError > {
16991736 if let Some ( 0 ) = amount {
17001737 return Ok ( None ) ;
17011738 }
17021739
1703- // TODO support more than one federation
17041740 let federation_ids = self . list_federation_ids ( ) . await ?;
17051741 if federation_ids. is_empty ( ) {
17061742 return Err ( MutinyError :: NotFound ) ;
17071743 }
17081744
1709- let federation_id = & federation_ids[ 0 ] ;
1745+ let from_federation_id = from_federation_id . unwrap_or ( federation_ids[ 0 ] ) ;
17101746 let federation_lock = self . federations . read ( ) . await ;
17111747 let fedimint_client = federation_lock
1712- . get ( federation_id )
1748+ . get ( & from_federation_id )
17131749 . ok_or ( MutinyError :: NotFound ) ?;
17141750 let fees = fedimint_client. gateway_fee ( ) . await ?;
17151751
17161752 let ( lsp_fee, federation_fee) = {
17171753 if let Some ( amt) = amount {
17181754 // if the user provided amount, this is easy
1719- (
1720- self . node_manager . get_lsp_fee ( amt) . await ?,
1721- ( calc_routing_fee_msat ( amt as f64 * 1_000.0 , & fees) / 1_000.0 ) . floor ( ) as u64 ,
1722- )
1755+ let incoming_fee = if to_federation_id. is_some ( ) {
1756+ 0
1757+ } else {
1758+ self . node_manager . get_lsp_fee ( amt) . await ?
1759+ } ;
1760+
1761+ let outgoing_fee =
1762+ ( calc_routing_fee_msat ( amt as f64 * 1_000.0 , & fees) / 1_000.0 ) . floor ( ) as u64 ;
1763+
1764+ ( incoming_fee, outgoing_fee)
17231765 } else {
17241766 // If no amount, figure out the amount to send over
17251767 let current_balance = fedimint_client. get_balance ( ) . await ?;
@@ -1733,11 +1775,15 @@ impl<S: MutinyStorage> MutinyWallet<S> {
17331775 . map_or ( Err ( MutinyError :: InsufficientBalance ) , Ok ) ?;
17341776 log_debug ! ( self . logger, "max spendable: {}" , amt) ;
17351777
1736- // try to get an invoice for this exact amount
1737- (
1738- self . node_manager . get_lsp_fee ( amt) . await ?,
1739- current_balance - amt,
1740- )
1778+ let incoming_fee = if to_federation_id. is_some ( ) {
1779+ 0
1780+ } else {
1781+ self . node_manager . get_lsp_fee ( amt) . await ?
1782+ } ;
1783+
1784+ let outgoing_fee = current_balance - amt;
1785+
1786+ ( incoming_fee, outgoing_fee)
17411787 }
17421788 } ;
17431789
0 commit comments