Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .changelog/unreleased/features/4790-frontend-sus-fees.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Added support for MASP frontend providers sustainability fees.
([\#4790](https://github.com/anoma/namada/pull/4790))
1 change: 1 addition & 0 deletions .github/workflows/scripts/e2e.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"e2e::eth_bridge_tests::everything": 4,
"e2e::ibc_tests::frontend_sus_fee": 350,
"e2e::ibc_tests::ibc_transfers": 414,
"e2e::ibc_tests::ibc_nft_transfers": 224,
"e2e::ibc_tests::pgf_over_ibc": 415,
Expand Down
145 changes: 125 additions & 20 deletions crates/apps_lib/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,9 @@ pub mod cmds {
Self::parse_with_ctx(matches, TxShieldingTransfer);
let tx_unshielding_transfer =
Self::parse_with_ctx(matches, TxUnshieldingTransfer);
let tx_ibc_transfer = Self::parse_with_ctx(matches, TxIbcTransfer);
let tx_ibc_transfer = Self::parse_with_ctx(matches, |cmd| {
TxIbcTransfer(Box::new(cmd))
});
let tx_osmosis_swap = Self::parse_with_ctx(matches, |cmd| {
TxOsmosisSwap(Box::new(cmd))
});
Expand Down Expand Up @@ -507,7 +509,7 @@ pub mod cmds {
TxShieldedTransfer(TxShieldedTransfer),
TxShieldingTransfer(TxShieldingTransfer),
TxUnshieldingTransfer(TxUnshieldingTransfer),
TxIbcTransfer(TxIbcTransfer),
TxIbcTransfer(Box<TxIbcTransfer>),
TxOsmosisSwap(Box<TxOsmosisSwap>),
QueryResult(QueryResult),
TxUpdateAccount(TxUpdateAccount),
Expand Down Expand Up @@ -3691,6 +3693,14 @@ pub mod args {
pub const TARGET: Arg<WalletAddress> = arg("target");
pub const TARGET_OPT: ArgOpt<WalletAddress> = arg_opt("target");
pub const TEMPLATES_PATH: Arg<PathBuf> = arg("templates-path");
// WARNING: use only for testing purposes, MASP frontend fees don't make
// sense when operating from the CLI
pub const __TEST_FRONTEND_SUS_FEE: ArgOpt<WalletTransferTarget> =
arg_opt("test-frontend-sus-fee");
// WARNING: use only for testing purposes, MASP frontend fees don't make
// sense when operating from the CLI
pub const __TEST_FRONTEND_SUS_FEE_IBC: ArgOpt<WalletPaymentAddr> =
arg_opt("test-frontend-sus-fee-ibc");
pub const TIMEOUT_HEIGHT: ArgOpt<u64> = arg_opt("timeout-height");
pub const TIMEOUT_SEC_OFFSET: ArgOpt<u64> = arg_opt("timeout-sec-offset");
pub const TM_ADDRESS_OPT: ArgOpt<String> = arg_opt("tm-address");
Expand Down Expand Up @@ -4928,11 +4938,11 @@ pub mod args {
ctx: &mut Context,
) -> Result<TxShieldingTransfer<SdkTypes>, Self::Error> {
let tx = self.tx.to_sdk(ctx)?;
let mut data = vec![];
let mut sources = vec![];
let chain_ctx = ctx.borrow_mut_chain_or_exit();

for transfer_data in self.sources {
data.push(TxTransparentSource {
sources.push(TxTransparentSource {
source: chain_ctx.get(&transfer_data.source),
token: chain_ctx.get(&transfer_data.token),
amount: transfer_data.amount,
Expand All @@ -4947,12 +4957,17 @@ pub mod args {
amount: transfer_data.amount,
});
}
let frontend_sus_fee =
self.frontend_sus_fee.map(|(target, percentage)| {
(chain_ctx.get(&target), percentage)
});

Ok(TxShieldingTransfer::<SdkTypes> {
tx,
sources: data,
sources,
targets,
tx_code_path: self.tx_code_path.to_path_buf(),
frontend_sus_fee,
})
}
}
Expand All @@ -4963,24 +4978,31 @@ pub mod args {
let source = SOURCE.parse(matches);
let target = PAYMENT_ADDRESS_TARGET.parse(matches);
let token = TOKEN.parse(matches);
let amount = InputAmount::Unvalidated(AMOUNT.parse(matches));
let raw_amount = AMOUNT.parse(matches);
let amount = InputAmount::Unvalidated(raw_amount);
let tx_code_path = PathBuf::from(TX_TRANSFER_WASM);
let data = vec![TxTransparentSource {
source,
let sources = vec![TxTransparentSource {
source: source.clone(),
token: token.clone(),
amount,
}];
let targets = vec![TxShieldedTarget {
target,
token,
token: token.clone(),
amount,
}];
let frontend_sus_fee =
__TEST_FRONTEND_SUS_FEE.parse(matches).map(|target| {
// Take a constant fee of 10% on top of the input amount
(target, Dec::new(1, 1).unwrap())
});

Self {
tx,
sources: data,
sources,
targets,
tx_code_path,
frontend_sus_fee,
}
}

Expand All @@ -5001,6 +5023,15 @@ pub mod args {
.def()
.help(wrap!("The amount to transfer in decimal.")),
)
.arg(
__TEST_FRONTEND_SUS_FEE
.def()
.help(wrap!(
"The optional address of the frontend provider \
that will take the masp sustainability fee."
))
.hide(true),
)
}
}

Expand Down Expand Up @@ -5033,6 +5064,12 @@ pub mod args {
amount: transfer_data.amount,
});
}

let frontend_sus_fee =
self.frontend_sus_fee.map(|(target, percentage)| {
(chain_ctx.get(&target), percentage)
});

let gas_spending_key =
self.gas_spending_key.map(|key| chain_ctx.get_cached(&key));

Expand All @@ -5042,6 +5079,7 @@ pub mod args {
gas_spending_key,
sources,
tx_code_path: self.tx_code_path.to_path_buf(),
frontend_sus_fee,
})
}
}
Expand All @@ -5052,26 +5090,34 @@ pub mod args {
let source = SPENDING_KEY_SOURCE.parse(matches);
let target = TARGET.parse(matches);
let token = TOKEN.parse(matches);
let amount = InputAmount::Unvalidated(AMOUNT.parse(matches));
let raw_amount = AMOUNT.parse(matches);
let amount = InputAmount::Unvalidated(raw_amount);
let tx_code_path = PathBuf::from(TX_TRANSFER_WASM);
let data = vec![TxTransparentTarget {
target,
let targets = vec![TxTransparentTarget {
target: target.clone(),
token: token.clone(),
amount,
}];
let sources = vec![TxShieldedSource {
source,
token,
source: source.clone(),
token: token.clone(),
amount,
}];
let gas_spending_key = GAS_SPENDING_KEY.parse(matches);

let frontend_sus_fee =
__TEST_FRONTEND_SUS_FEE.parse(matches).map(|target| {
// Take a constant fee of 10% on top of the input amount
(target, Dec::new(1, 1).unwrap())
});

Self {
tx,
sources,
targets: data,
targets,
gas_spending_key,
tx_code_path,
frontend_sus_fee,
}
}

Expand All @@ -5098,6 +5144,15 @@ pub mod args {
payment. When not provided the source spending key will \
be used."
)))
.arg(
__TEST_FRONTEND_SUS_FEE
.def()
.help(wrap!(
"The optional address of the frontend provider \
that will take the masp sustainability fee."
))
.hide(true),
)
}
}

Expand All @@ -5112,6 +5167,10 @@ pub mod args {
let chain_ctx = ctx.borrow_mut_chain_or_exit();
let gas_spending_key =
self.gas_spending_key.map(|key| chain_ctx.get_cached(&key));
let frontend_sus_fee =
self.frontend_sus_fee.map(|(target, percentage)| {
(chain_ctx.get(&target), percentage)
});

Ok(TxIbcTransfer::<SdkTypes> {
tx,
Expand All @@ -5128,6 +5187,7 @@ pub mod args {
ibc_memo: self.ibc_memo,
gas_spending_key,
tx_code_path: self.tx_code_path.to_path_buf(),
frontend_sus_fee,
})
}
}
Expand All @@ -5138,7 +5198,9 @@ pub mod args {
let source = TRANSFER_SOURCE.parse(matches);
let receiver = RECEIVER.parse(matches);
let token = TOKEN.parse(matches);
let amount = InputAmount::Unvalidated(AMOUNT.parse(matches));

let raw_amount = AMOUNT.parse(matches);
let amount = InputAmount::Unvalidated(raw_amount);
let port_id = PORT_ID.parse(matches);
let channel_id = CHANNEL_ID.parse(matches);
let timeout_height = TIMEOUT_HEIGHT.parse(matches);
Expand All @@ -5154,6 +5216,12 @@ pub mod args {
let ibc_memo = IBC_MEMO.parse(matches);
let gas_spending_key = GAS_SPENDING_KEY.parse(matches);
let tx_code_path = PathBuf::from(TX_IBC_WASM);
let frontend_sus_fee =
__TEST_FRONTEND_SUS_FEE.parse(matches).map(|target| {
// Take a constant fee of 10% on top of the input amount
(target, Dec::new(1, 1).unwrap())
});

Self {
tx,
source,
Expand All @@ -5169,6 +5237,7 @@ pub mod args {
ibc_memo,
gas_spending_key,
tx_code_path,
frontend_sus_fee,
}
}

Expand Down Expand Up @@ -5218,6 +5287,15 @@ pub mod args {
payment (if this is a shielded action). When not \
provided the source spending key will be used."
)))
.arg(
__TEST_FRONTEND_SUS_FEE
.def()
.help(wrap!(
"The optional address of the frontend provider \
that will take the masp sustainability fee."
))
.hide(true),
)
}
}

Expand All @@ -5244,6 +5322,7 @@ pub mod args {
route: self.route,
osmosis_lcd_rpc: self.osmosis_lcd_rpc,
osmosis_sqs_rpc: self.osmosis_sqs_rpc,
frontend_sus_fee: None,
})
}
}
Expand Down Expand Up @@ -5296,6 +5375,7 @@ pub mod args {
route,
osmosis_lcd_rpc,
osmosis_sqs_rpc,
frontend_sus_fee: None,
}
}

Expand Down Expand Up @@ -7210,6 +7290,9 @@ pub mod args {
) -> Result<GenIbcShieldingTransfer<SdkTypes>, Self::Error> {
let query = self.query.to_sdk(ctx)?;
let chain_ctx = ctx.borrow_chain_or_exit();
let frontend_sus_fee = self
.frontend_sus_fee
.map(|(target, amount)| (chain_ctx.get(&target), amount));

Ok(GenIbcShieldingTransfer::<SdkTypes> {
query,
Expand All @@ -7231,6 +7314,7 @@ pub mod args {
IbcShieldingTransferAsset::Address(chain_ctx.get(&addr))
}
},
frontend_sus_fee,
})
}
}
Expand All @@ -7239,9 +7323,10 @@ pub mod args {
fn parse(matches: &ArgMatches) -> Self {
let query = Query::parse(matches);
let output_folder = OUTPUT_FOLDER_PATH.parse(matches);
let target = TRANSFER_TARGET.parse(matches);
let target = PAYMENT_ADDRESS_TARGET.parse(matches);
let token = TOKEN_STR.parse(matches);
let amount = InputAmount::Unvalidated(AMOUNT.parse(matches));
let raw_amount = AMOUNT.parse(matches);
let amount = InputAmount::Unvalidated(raw_amount);
let expiration = EXPIRATION_OPT.parse(matches);
let port_id = PORT_ID.parse(matches);
let channel_id = CHANNEL_ID.parse(matches);
Expand All @@ -7254,6 +7339,12 @@ pub mod args {
None => TxExpiration::Default,
}
};
let frontend_sus_fee = __TEST_FRONTEND_SUS_FEE_IBC
.parse(matches)
.map(|payment_address| {
// Take a constant fee of 10% on top of the input amount
(payment_address, Dec::new(1, 1).unwrap())
});

Self {
query,
Expand All @@ -7266,6 +7357,7 @@ pub mod args {
channel_id,
token,
},
frontend_sus_fee,
}
}

Expand All @@ -7274,7 +7366,11 @@ pub mod args {
.arg(OUTPUT_FOLDER_PATH.def().help(wrap!(
"The output folder path where the artifact will be stored."
)))
.arg(TRANSFER_TARGET.def().help(wrap!("The target address.")))
.arg(
PAYMENT_ADDRESS_TARGET
.def()
.help(wrap!("The shielded target account address.")),
)
.arg(TOKEN.def().help(wrap!("The transfer token.")))
.arg(
AMOUNT
Expand Down Expand Up @@ -7307,6 +7403,15 @@ pub mod args {
.arg(CHANNEL_ID.def().help(wrap!(
"The channel ID via which the token is received."
)))
.arg(
__TEST_FRONTEND_SUS_FEE_IBC
.def()
.help(wrap!(
"The optional address of the frontend provider \
that will take the masp sustainability fee."
))
.hide(true),
)
}
}

Expand Down
3 changes: 2 additions & 1 deletion crates/apps_lib/src/cli/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ impl CliApi {
let namada = ctx.to_sdk(client, io);
tx::submit_unshielding_transfer(&namada, args).await?;
}
Sub::TxIbcTransfer(TxIbcTransfer(args)) => {
Sub::TxIbcTransfer(args) => {
let TxIbcTransfer(args) = *args;
let chain_ctx = ctx.borrow_mut_chain_or_exit();
let ledger_address =
chain_ctx.get(&args.tx.ledger_address);
Expand Down
Loading
Loading