feat: reusable mint fee math with cached quotes, fee-aware Max in move funds

This commit is contained in:
2026-08-20 10:13:36 +02:00
parent 39261212cf
commit f4b9377d17
4 changed files with 148 additions and 4 deletions
+4 -1
View File
@@ -52,6 +52,9 @@ interface MockTargetMintOptions {
preimage: string;
// value of the note a claim mints, in msat
noteAmountMsat: number;
// optional payRequest metadata advertising a receive fee, e.g.
// '[["text/plain","Mint fees: 2000,0"]]' (flat 2000 msat, 0 ppm)
mintFeeMetadata?: string;
}
export class MintMocker {
@@ -127,7 +130,7 @@ export class MintMocker {
maxSendable: 100_000_000_000,
withdrawLink: `${origin}${NOTE_PATH}`,
mintPubkey: options.mintPubkey,
metadata: '[]',
metadata: options.mintFeeMetadata ?? '[]',
});
},
);
+25
View File
@@ -73,6 +73,31 @@ test.describe('Move funds', () => {
await expect(page.getByRole('button', { name: 'Move now' })).toBeVisible();
});
test('the Max helper discounts the target mint fee', async ({ page, mint }) => {
await fundSourceMint(page, mint);
// the target mint advertises a flat 2-sat receive fee (2000 msat, 0 ppm)
await mint.mockTargetMint(
{
mintPubkey: TARGET_PUBKEY,
invoice: INVOICE,
preimage: PREIMAGE,
noteAmountMsat: AMOUNT_MSAT,
mintFeeMetadata: '[["text/plain","Mint fees: 2000,0"]]',
},
MINT2_ORIGIN,
);
await page.goto('/#/settings/move');
await pickOption(page, 'From mint', 'mint.test - 50 sats available');
await pickOption(page, 'To mint', 'Another mint…');
await page.getByLabel('Target mint address').fill('@mint2.test');
// the fee quote lands (caption shown), then Max fills 50 - 2 = 48
await expect(page.getByText(/receive fee/)).toBeVisible();
await page.getByRole('button', { name: 'Max' }).click();
await expect(page.getByLabel('Amount')).toHaveValue('48');
});
test('a two-mint transfer moves the balance', async ({ page, mint }) => {
await fundSourceMint(page, mint);
// the target mint: hands out the invoice, reports it settled with the