Skip to content

Commit

Permalink
Require users manually specify a --fee-rate for wallet send (#1755)
Browse files Browse the repository at this point in the history
NB `wallet send <AMOUNT>` still uses fee-rate estimation from `bitcoind`.

See #1432 for more details.
  • Loading branch information
veryordinally authored Feb 15, 2023
1 parent b0ca486 commit 3b49ab2
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 25 deletions.
2 changes: 1 addition & 1 deletion docs/src/guides/inscriptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ ord wallet receive
Send the inscription by running:

```
ord wallet send ADDRESS INSCRIPTION_ID
ord wallet send --fee-rate <FEE_RATE> <ADDRESS> <INSCRIPTION_ID>
```

See the pending transaction with:
Expand Down
3 changes: 2 additions & 1 deletion src/subcommand/wallet/inscribe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@ impl Inscribe {
.iter()
.map(|txin| utxos.get(&txin.previous_output).unwrap().to_sat())
.sum::<u64>()
- tx.output.iter().map(|txout| txout.value).sum::<u64>()
.checked_sub(tx.output.iter().map(|txout| txout.value).sum::<u64>())
.unwrap()
}

fn create_inscription_transactions(
Expand Down
6 changes: 1 addition & 5 deletions src/subcommand/wallet/send.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@ use {super::*, crate::wallet::Wallet};
pub(crate) struct Send {
address: Address,
outgoing: Outgoing,
#[clap(
long,
default_value = "1.0",
help = "Use fee rate of <FEE_RATE> sats/vB"
)]
#[clap(long, help = "Use fee rate of <FEE_RATE> sats/vB")]
fee_rate: FeeRate,
}

Expand Down
2 changes: 1 addition & 1 deletion tests/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ fn inscription_page_after_send() {
);

let txid = CommandBuilder::new(format!(
"wallet send bc1qcqgs2pps4u4yedfyl5pysdjjncs8et5utseepv {inscription}"
"wallet send --fee-rate 1 bc1qcqgs2pps4u4yedfyl5pysdjjncs8et5utseepv {inscription}"
))
.rpc_server(&rpc_server)
.stdout_regex(".*")
Expand Down
2 changes: 1 addition & 1 deletion tests/wallet/inscriptions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ fn inscriptions() {
.output::<receive::Output>()
.address;

let stdout = CommandBuilder::new(format!("wallet send {address} {inscription}"))
let stdout = CommandBuilder::new(format!("wallet send --fee-rate 1 {address} {inscription}"))
.rpc_server(&rpc_server)
.expected_exit_code(0)
.stdout_regex(".*")
Expand Down
54 changes: 38 additions & 16 deletions tests/wallet/send.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fn inscriptions_can_be_sent() {
rpc_server.mine_blocks(1);

let stdout = CommandBuilder::new(format!(
"wallet send bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4 {inscription}",
"wallet send --fee-rate 1 bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4 {inscription}",
))
.rpc_server(&rpc_server)
.stdout_regex(r".*")
Expand Down Expand Up @@ -51,7 +51,7 @@ fn send_unknown_inscription() {
let txid = rpc_server.mine_blocks(1)[0].txdata[0].txid();

CommandBuilder::new(format!(
"wallet send bc1qcqgs2pps4u4yedfyl5pysdjjncs8et5utseepv {txid}i0"
"wallet send --fee-rate 1 bc1qcqgs2pps4u4yedfyl5pysdjjncs8et5utseepv {txid}i0"
))
.rpc_server(&rpc_server)
.expected_stderr(format!("error: Inscription {txid}i0 not found\n"))
Expand All @@ -70,7 +70,7 @@ fn send_inscribed_sat() {
rpc_server.mine_blocks(1);

let stdout = CommandBuilder::new(format!(
"wallet send bc1qcqgs2pps4u4yedfyl5pysdjjncs8et5utseepv {inscription}",
"wallet send --fee-rate 1 bc1qcqgs2pps4u4yedfyl5pysdjjncs8et5utseepv {inscription}",
))
.rpc_server(&rpc_server)
.stdout_regex("[[:xdigit:]]{64}\n")
Expand Down Expand Up @@ -99,7 +99,7 @@ fn send_on_mainnnet_works_with_wallet_named_foo() {
.output::<Create>();

CommandBuilder::new(format!(
"--wallet foo wallet send bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4 {txid}:0:0"
"--wallet foo wallet send --fee-rate 1 bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4 {txid}:0:0"
))
.rpc_server(&rpc_server)
.stdout_regex(r"[[:xdigit:]]{64}\n")
Expand All @@ -113,7 +113,7 @@ fn send_addresses_must_be_valid_for_network() {
create_wallet(&rpc_server);

CommandBuilder::new(format!(
"wallet send tb1q6en7qjxgw4ev8xwx94pzdry6a6ky7wlfeqzunz {txid}:0:0"
"wallet send --fee-rate 1 tb1q6en7qjxgw4ev8xwx94pzdry6a6ky7wlfeqzunz {txid}:0:0"
))
.rpc_server(&rpc_server)
.expected_stderr(
Expand All @@ -130,7 +130,7 @@ fn send_on_mainnnet_works_with_wallet_named_ord() {
create_wallet(&rpc_server);

let stdout = CommandBuilder::new(format!(
"wallet send bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4 {txid}:0:0"
"wallet send --fee-rate 1 bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4 {txid}:0:0"
))
.rpc_server(&rpc_server)
.stdout_regex(r".*")
Expand All @@ -155,7 +155,7 @@ fn send_does_not_use_inscribed_sats_as_cardinal_utxos() {

let txid = rpc_server.mine_blocks_with_subsidy(1, 100)[0].txdata[0].txid();
CommandBuilder::new(format!(
"wallet send bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4 {txid}:0:0"
"wallet send --fee-rate 1 bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4 {txid}:0:0"
))
.rpc_server(&rpc_server)
.expected_exit_code(1)
Expand All @@ -182,7 +182,7 @@ fn do_not_accidentally_send_an_inscription() {
};

CommandBuilder::new(format!(
"wallet send bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4 {output}:55"
"wallet send --fee-rate 1 bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4 {output}:55"
))
.rpc_server(&rpc_server)
.expected_exit_code(1)
Expand All @@ -202,7 +202,7 @@ fn inscriptions_cannot_be_sent_by_satpoint() {
rpc_server.mine_blocks(1);

CommandBuilder::new(format!(
"wallet send bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4 {reveal}:0:0"
"wallet send --fee-rate 1 bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4 {reveal}:0:0"
))
.rpc_server(&rpc_server)
.expected_stderr("error: inscriptions must be sent by inscription ID\n")
Expand All @@ -217,9 +217,10 @@ fn send_btc() {

rpc_server.mine_blocks(1);

let output = CommandBuilder::new("wallet send bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4 1btc")
.rpc_server(&rpc_server)
.output::<Output>();
let output =
CommandBuilder::new("wallet send --fee-rate 1 bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4 1btc")
.rpc_server(&rpc_server)
.output::<Output>();

assert_eq!(
output.transaction,
Expand Down Expand Up @@ -249,9 +250,10 @@ fn send_btc_locks_inscriptions() {

let Inscribe { reveal, .. } = inscribe(&rpc_server);

let output = CommandBuilder::new("wallet send bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4 1btc")
.rpc_server(&rpc_server)
.output::<Output>();
let output =
CommandBuilder::new("wallet send --fee-rate 1 bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4 1btc")
.rpc_server(&rpc_server)
.output::<Output>();

assert_eq!(
output.transaction,
Expand Down Expand Up @@ -284,7 +286,7 @@ fn send_btc_fails_if_lock_unspent_fails() {

rpc_server.mine_blocks(1);

CommandBuilder::new("wallet send bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4 1btc")
CommandBuilder::new("wallet send --fee-rate 1 bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4 1btc")
.rpc_server(&rpc_server)
.expected_stderr("error: failed to lock ordinal UTXOs\n")
.expected_exit_code(1)
Expand Down Expand Up @@ -322,3 +324,23 @@ fn wallet_send_with_fee_rate() {

pretty_assert_eq!(fee_rate, 2.0);
}

#[test]
fn user_must_provide_fee_rate_to_send() {
let rpc_server = test_bitcoincore_rpc::spawn();
create_wallet(&rpc_server);
rpc_server.mine_blocks(1);

let Inscribe { inscription, .. } = inscribe(&rpc_server);

CommandBuilder::new(format!(
"wallet send bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4 {inscription}"
))
.rpc_server(&rpc_server)
.expected_exit_code(2)
.stderr_regex(
".*error: The following required arguments were not provided:
.*--fee-rate <FEE_RATE>.*",
)
.run();
}

0 comments on commit 3b49ab2

Please sign in to comment.