aboutsummaryrefslogtreecommitdiffstats
path: root/src/wallet.js
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-06-24 14:12:46 -0700
committerAdam Soltys <[email protected]>2026-06-24 14:12:46 -0700
commit3463af1d81c2712d657bbf30ecba98ffe5873729 (patch)
tree897aa78d3aa3f9227b6a3de00132ded16607033a /src/wallet.js
parent1a92d81b792f9e6d2ecb284aab979985a36d34c7 (diff)
downloadcoinosv3-3463af1d81c2712d657bbf30ecba98ffe5873729.tar.gz
coinosv3-3463af1d81c2712d657bbf30ecba98ffe5873729.zip
Fee-aware gift minimum; move gift entrypoint to Send page
Minimum: the flat 546-sat floor is replaced by a fee-aware minimum (dust + one claim fee of headroom, floored at 546) via giftMinimum(), so the recipient clears dust comfortably even if fees rise before they claim — e.g. ~1000 sats at 5 sat/vB, ~7300 at 50. The create form shows the live minimum and rejects below it; buildClaimTx keeps the hard 294-sat dust guard as a final backstop (claim fails rather than handing over dust). UI: the gift entrypoint moves from Settings to a "Gift some Bitcoin" link on the Send page, opening the gift view as a send sub-view with a back button. New strings translated across all 19 locales. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Diffstat (limited to 'src/wallet.js')
-rw-r--r--src/wallet.js12
1 files changed, 11 insertions, 1 deletions
diff --git a/src/wallet.js b/src/wallet.js
index ad890d3..39848e8 100644
--- a/src/wallet.js
+++ b/src/wallet.js
@@ -838,10 +838,12 @@ export class Wallet {
// direct to their own fresh address. Reserves the coin. Returns { code, ... }.
createGift(amountSats, feeRate) {
const gift = BigInt(Math.round(amountSats));
- if (gift < 546n) throw new Error('Gift amount is too small.');
const rate = Math.max(1, Math.round(feeRate));
const claimFee = BigInt(Math.ceil((11 + 68 + 31 * 2) * rate)); // claimer's 1-in 2-out tx
const DUST = 294n;
+ // Require dust + one claim fee of headroom so the recipient stays well above
+ // dust even if fees rise before they claim.
+ if (gift < BigInt(giftMinimum(rate))) throw new Error('Gift amount is too small.');
const need = gift + claimFee + DUST;
const coin = this.utxos
.filter((u) => u.confirmed && !this.isReserved(utxoId(u)))
@@ -1293,6 +1295,14 @@ export function utxoId(u) {
// base64url PSBT: one SIGHASH_SINGLE-signed input + the sender's change output.
// previewGift reports the room available to the claimer (before their fee);
// buildClaimTx adds the claimer's output and finalizes a broadcastable tx.
+// Smallest sensible gift at a given fee rate: dust + one claim fee of headroom
+// (floored at 546 sats), so the recipient clears dust even if fees climb.
+export function giftMinimum(feeRate) {
+ const rate = Math.max(1, Math.round(feeRate));
+ const claimFee = Math.ceil((11 + 68 + 31 * 2) * rate);
+ return Math.max(546, 294 + claimFee);
+}
+
export function previewGift(code) {
try {
const tx = btc.Transaction.fromPSBT(base64urlnopad.decode(code));