Filter mint selector based on disabled payment methods

This commit is contained in:
minibits-cash
2026-09-24 14:27:49 +02:00
parent a96b22bcf9
commit ab07a29dd1
3 changed files with 65 additions and 9 deletions
+51 -2
View File
@@ -57,6 +57,8 @@ type MethodEntry = {
const mintWith = (opts: {
mintMethods?: MethodEntry[]
meltMethods?: MethodEntry[]
mintDisabled?: boolean
meltDisabled?: boolean
nut20?: boolean
}) =>
MintModel.create({
@@ -67,8 +69,8 @@ const mintWith = (opts: {
version: 'test/1',
contact: [],
nuts: {
'4': {methods: opts.mintMethods ?? [], disabled: false},
'5': {methods: opts.meltMethods ?? [], disabled: false},
'4': {methods: opts.mintMethods ?? [], disabled: opts.mintDisabled ?? false},
'5': {methods: opts.meltMethods ?? [], disabled: opts.meltDisabled ?? false},
...(opts.nut20 === undefined ? {} : {'20': {supported: opts.nut20}}),
},
time: Math.floor(Date.now() / 1000),
@@ -167,6 +169,53 @@ describe('supportsMint / supportsMelt', () => {
})
})
/**
* A mint may advertise methods AND switch the whole NUT off — nutshell does this
* when its backend is unavailable. The flag wins over the list, or the wallet
* offers a flow the mint refuses at quote time.
*/
describe('the NUT-04 / NUT-05 disabled flag', () => {
it('reports no mint method when NUT-04 is disabled, however many are listed', () => {
const mint = mintWith({
mintMethods: [BOLT11_SAT, ONCHAIN_SAT],
mintDisabled: true,
nut20: true,
})
expect(mint.mintMethodSetting('bolt11', 'sat')).toBeUndefined()
expect(mint.mintMethodSetting('onchain', 'sat')).toBeUndefined()
expect(mint.supportsMint('bolt11', 'sat')).toBe(false)
expect(mint.supportsMint('onchain', 'sat')).toBe(false)
})
it('reports no melt method when NUT-05 is disabled', () => {
const mint = mintWith({meltMethods: [BOLT11_SAT], meltDisabled: true})
expect(mint.meltMethodSetting('bolt11', 'sat')).toBeUndefined()
expect(mint.supportsMelt('bolt11', 'sat')).toBe(false)
})
it('disables only the half that is switched off', () => {
// topups closed, payouts still open
const mint = mintWith({
mintMethods: [BOLT11_SAT],
mintDisabled: true,
meltMethods: [BOLT11_SAT],
})
expect(mint.supportsMint('bolt11', 'sat')).toBe(false)
expect(mint.supportsMelt('bolt11', 'sat')).toBe(true)
})
it('is not the same as unknown capabilities — a disabled mint has cached info', () => {
// the two resolve OPPOSITELY for bolt11: unknown assumes it, disabled refuses it
const mint = mintWith({mintMethods: [BOLT11_SAT], mintDisabled: true})
expect(mint.hasUnknownCapabilities).toBe(false)
expect(mint.supportsMint('bolt11', 'sat')).toBe(false)
})
})
describe('unknown capabilities (info never cached)', () => {
it('assumes bolt11, so an upgrading user never loses their Lightning options', () => {
const mint = mintWithUnknownInfo()
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "minibits_wallet",
"version": "0.4.3-beta.23",
"version": "0.4.3-beta.25",
"private": true,
"scripts": {
"android:clean": "cd android && ./gradlew clean",
+13 -6
View File
@@ -204,16 +204,23 @@ export const MintModel = types
*
* The setting also carries `min_amount` / `max_amount` (and, for onchain,
* `options.confirmations`), which callers need for limit checks.
*
* Each NUT carries a `disabled` flag beside its method list, and a mint that
* advertises methods while disabling the NUT is telling us that direction is
* off — nutshell sets it when its backend is unavailable. Ignoring the flag
* means offering a flow the mint then refuses. Same rule as `getMethods` in
* screens/Mints/mintInfoSummary.ts, which drives MintInfoScreen: the two must
* stay in step or the mint's detail screen contradicts the topup menu.
*/
mintMethodSetting(method: PaymentMethod, unit: MintUnit): SwapMethod | undefined {
return self.mintInfo?.nuts?.['4']?.methods?.find(
m => m.method === method && m.unit === unit,
)
const nut4 = self.mintInfo?.nuts?.['4']
if (nut4?.disabled === true) return undefined
return nut4?.methods?.find(m => m.method === method && m.unit === unit)
},
meltMethodSetting(method: PaymentMethod, unit: MintUnit): SwapMethod | undefined {
return self.mintInfo?.nuts?.['5']?.methods?.find(
m => m.method === method && m.unit === unit,
)
const nut5 = self.mintInfo?.nuts?.['5']
if (nut5?.disabled === true) return undefined
return nut5?.methods?.find(m => m.method === method && m.unit === unit)
},
/** Does the mint advertise NUT-20 (signed mint quotes)? */
get supportsNut20(): boolean {