mirror of
https://github.com/Permissionless-Software-Foundation/psf-memo-client.git
synced 2026-09-21 16:52:02 -07:00
Lower tip dust limit to 600 sats and keep the like/tip modal editable after errors
Allow tips as low as 600 sats (tip output dust) while keeping the wallet balance gate at 3000 sats to cover transaction fees. Keep the tip input and Like button enabled after a validation error so the user can edit and retry. By specifier.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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}
|
||||
/>
|
||||
</Form.Group>
|
||||
</Form>
|
||||
@@ -141,7 +145,7 @@ function LikeTipModal ({ show, post, wallet, profiles = {}, onHide, onSuccess })
|
||||
<Button
|
||||
variant='primary'
|
||||
onClick={handleSubmit}
|
||||
disabled={submitting || !!error || !post || !wallet}
|
||||
disabled={submitting || !post || !wallet}
|
||||
>
|
||||
{submitting ? 'Liking...' : 'Like'}
|
||||
</Button>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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 () => {
|
||||
|
||||
Reference in New Issue
Block a user