mirror of
https://github.com/Permissionless-Software-Foundation/psf-memo-client.git
synced 2026-09-21 16:52:02 -07:00
Fix like/tip modal spendable balance against the live wallet
The Like/Tip modal crashed with "utxos.reduce is not a function" because MemoLike.getSpendableSats assumed wallet.utxos was an array, while minimal-slp-wallet exposes it as a UtxoStore object whose spendable BCH outputs live under utxoStore.bchUtxos. Accept both shapes, and refresh the wallet UTXOs before the modal's gating balance check. By specifier.
This commit is contained in:
@@ -40,12 +40,32 @@ function LikeTipModal ({ show, post, wallet, profiles = {}, onHide, onSuccess })
|
||||
setError('')
|
||||
setSubmitting(false)
|
||||
|
||||
const memoLike = new MemoLike({ wallet })
|
||||
const page = new LikeTipPage({ memoLike })
|
||||
const result = page.open(post.txid, post.addr)
|
||||
if (!result.ok) {
|
||||
setError(formatError(result))
|
||||
let cancelled = false
|
||||
|
||||
const checkBalance = async () => {
|
||||
try {
|
||||
// Refresh the wallet's spendable UTXOs so the gating balance check is
|
||||
// accurate against the live minimal-slp-wallet (which exposes
|
||||
// wallet.utxos as a UtxoStore object, not an array).
|
||||
if (typeof wallet.getUtxos === 'function') {
|
||||
await wallet.getUtxos()
|
||||
}
|
||||
if (cancelled) return
|
||||
|
||||
const memoLike = new MemoLike({ wallet })
|
||||
const page = new LikeTipPage({ memoLike })
|
||||
const result = page.open(post.txid, post.addr)
|
||||
if (!result.ok) {
|
||||
setError(formatError(result))
|
||||
}
|
||||
} catch (err) {
|
||||
if (!cancelled) setError(err.message)
|
||||
}
|
||||
}
|
||||
|
||||
checkBalance()
|
||||
|
||||
return () => { cancelled = true }
|
||||
}, [show, post, wallet])
|
||||
|
||||
async function handleSubmit () {
|
||||
|
||||
@@ -98,7 +98,12 @@ class MemoLike extends MemoAction {
|
||||
// used by different wallet adapters.
|
||||
getSpendableSats () {
|
||||
if (!this.wallet) return 0
|
||||
const utxos = this.wallet.utxos || []
|
||||
// minimal-slp-wallet exposes wallet.utxos as a UtxoStore object whose
|
||||
// spendable BCH outputs live under utxoStore.bchUtxos, while the test and
|
||||
// acceptance wallets use a plain array. Accept both shapes.
|
||||
const utxos = Array.isArray(this.wallet.utxos)
|
||||
? this.wallet.utxos
|
||||
: (this.wallet.utxos?.utxoStore?.bchUtxos || [])
|
||||
return utxos.reduce((sum, u) => {
|
||||
const value = u.value ?? u.satoshis ?? u.amount ?? 0
|
||||
return sum + value
|
||||
|
||||
@@ -260,3 +260,27 @@ test('getSpendableSats returns 0 without a wallet or spendable values', () => {
|
||||
assert.equal(new MemoLike({ wallet: { utxos: undefined } }).getSpendableSats(), 0)
|
||||
assert.equal(new MemoLike({ wallet: { utxos: [{ txid: 'u1' }] } }).getSpendableSats(), 0)
|
||||
})
|
||||
|
||||
test('getSpendableSats reads spendable BCH outputs from the wallet UtxoStore object', () => {
|
||||
// minimal-slp-wallet exposes wallet.utxos as a UtxoStore object whose
|
||||
// spendable BCH outputs live under utxoStore.bchUtxos.
|
||||
const utxoStore = {
|
||||
utxoStore: {
|
||||
bchUtxos: [
|
||||
{ txid: 'u1', satoshis: 1500 },
|
||||
{ txid: 'u2', value: 2000 },
|
||||
{ txid: 'u3', satoshis: 2500 }
|
||||
],
|
||||
slpUtxos: { type1: { tokens: [] }, nft: [] }
|
||||
}
|
||||
}
|
||||
const wallet = fakeWallet({ utxos: utxoStore })
|
||||
|
||||
assert.equal(new MemoLike({ wallet }).getSpendableSats(), 6000)
|
||||
})
|
||||
|
||||
test('getSpendableSats returns 0 for an empty UtxoStore object', () => {
|
||||
const wallet = fakeWallet({ utxos: { utxoStore: { bchUtxos: [] } } })
|
||||
|
||||
assert.equal(new MemoLike({ wallet }).getSpendableSats(), 0)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user