diff --git a/specs/like-tip-memo.feature b/specs/like-tip-memo.feature index 466ef65..40031f9 100644 --- a/specs/like-tip-memo.feature +++ b/specs/like-tip-memo.feature @@ -39,6 +39,7 @@ Feature: Like / Tip a Memo Examples: | tip | + | 600 | | 3000 | | 25000 | @@ -64,7 +65,7 @@ Feature: Like / Tip a Memo Examples: | tip | | 1 | - | 2999 | + | 599 | Scenario: Like / Tip a Memo - 6 a tip above the maximum is rejected Given the wallet has a spendable balance of 150000000 sats diff --git a/src/components/post-feed/like-tip-modal.js b/src/components/post-feed/like-tip-modal.js index d6e4c5f..073463d 100644 --- a/src/components/post-feed/like-tip-modal.js +++ b/src/components/post-feed/like-tip-modal.js @@ -123,8 +123,12 @@ function LikeTipModal ({ show, post, wallet, profiles = {}, onHide, onSuccess }) step='1' placeholder='0' value={tip} - onChange={(e) => setTip(e.target.value)} - disabled={submitting || !!error} + onChange={(e) => { + setTip(e.target.value) + // Clear a previous validation error so the user can retry. + setError('') + }} + disabled={submitting} /> @@ -141,7 +145,7 @@ function LikeTipModal ({ show, post, wallet, profiles = {}, onHide, onSuccess }) diff --git a/src/services/memo-like.js b/src/services/memo-like.js index 038ccf2..cff2127 100644 --- a/src/services/memo-like.js +++ b/src/services/memo-like.js @@ -16,7 +16,8 @@ Constants MEMO_LIKE_PREFIX : hex prefix for the Memo "like" action (0x6d04) - DUST_LIMIT_SATS : smallest non-dust BCH output (3000 sats) + DUST_LIMIT_SATS : minimum wallet balance required to broadcast a like (3000 sats) + DUST_TIP_SATS : smallest non-dust tip output (600 sats) MAX_TIP_SATS : sanity maximum for a single tip (100000000 sats = 1 BCH) PARENT_TXID_BYTES : liked post txid size in bytes (32) */ @@ -26,6 +27,7 @@ const { hexToBytes } = require('./hex') const MEMO_LIKE_PREFIX = '6d04' const DUST_LIMIT_SATS = 3000 +const DUST_TIP_SATS = 600 const MAX_TIP_SATS = 100000000 const PARENT_TXID_BYTES = 32 @@ -43,6 +45,7 @@ class MemoLike extends MemoAction { super(deps) this.feed = deps.feed this.dustLimit = deps.dustLimit || DUST_LIMIT_SATS + this.dustTipSats = deps.dustTipSats || DUST_TIP_SATS this.maxTip = deps.maxTip || MAX_TIP_SATS } @@ -81,8 +84,8 @@ class MemoLike extends MemoAction { throw err } - if (tipSats > 0 && tipSats < this.dustLimit) { - const err = new Error(`Tip is below the dust limit of ${this.dustLimit} sats.`) + if (tipSats > 0 && tipSats < this.dustTipSats) { + const err = new Error(`Tip is below the dust limit of ${this.dustTipSats} sats.`) err.code = 'like_dust' throw err } @@ -189,6 +192,7 @@ class MemoLike extends MemoAction { MemoLike.MEMO_LIKE_PREFIX = MEMO_LIKE_PREFIX MemoLike.DUST_LIMIT_SATS = DUST_LIMIT_SATS +MemoLike.DUST_TIP_SATS = DUST_TIP_SATS MemoLike.MAX_TIP_SATS = MAX_TIP_SATS module.exports = MemoLike diff --git a/test/unit/like-tip-page.test.js b/test/unit/like-tip-page.test.js index 39a033a..865ea7c 100644 --- a/test/unit/like-tip-page.test.js +++ b/test/unit/like-tip-page.test.js @@ -154,7 +154,7 @@ test('submitting with a non-numeric tip string is rejected', async () => { test('submitting with a dust tip is rejected', async () => { const { wallet, page } = build() page.open(POST_TXID, AUTHOR_ADDRESS) - page.setTip('2999') + page.setTip('599') const result = await page.submit() diff --git a/test/unit/memo-like.test.js b/test/unit/memo-like.test.js index 8030a0f..4667318 100644 --- a/test/unit/memo-like.test.js +++ b/test/unit/memo-like.test.js @@ -59,6 +59,10 @@ test('DUST_LIMIT_SATS is 3000', () => { assert.equal(MemoLike.DUST_LIMIT_SATS, 3000) }) +test('DUST_TIP_SATS is 600', () => { + assert.equal(MemoLike.DUST_TIP_SATS, 600) +}) + test('MAX_TIP_SATS is 100000000', () => { assert.equal(MemoLike.MAX_TIP_SATS, 100000000) }) @@ -135,20 +139,23 @@ test('a negative tip is rejected with a validation error', async () => { await assertLikeRejected(fakeWallet(), -1, 'like_validation') }) -test('a tip below the dust limit is rejected with a dust error', async () => { +test('a tip below the tip dust limit is rejected with a dust error', async () => { const wallet = fakeWallet({ utxos: [{ txid: 'u1', value: 100000 }] }) await assertLikeRejected(wallet, 1, 'like_dust') - await assertLikeRejected(wallet, 2999, 'like_dust') + await assertLikeRejected(wallet, 599, 'like_dust') }) -test('a tip at the dust limit is accepted', async () => { +test('a tip at the tip dust limit is accepted', async () => { const wallet = fakeWallet({ utxos: [{ txid: 'u1', value: 100000 }] }) const memoLike = new MemoLike({ wallet }) - const txid = await memoLike.like(POST_TXID, 3000, AUTHOR_ADDRESS) + const txid = await memoLike.like(POST_TXID, 600, AUTHOR_ADDRESS) assert.equal(txid, 'fake-txid') assert.equal(wallet.broadcasts.length, 1) + assert.deepEqual(wallet.broadcasts[0].bchOutput, [ + { address: AUTHOR_ADDRESS, amountSat: 600 } + ]) }) test('a tip above the hard maximum is rejected with a maximum error', async () => {