diff --git a/app/assets/gift-cards/kissofmatcha.agi.cash.webp b/app/assets/gift-cards/kissofmatcha.agi.cash.webp new file mode 100644 index 000000000..88f663f8a Binary files /dev/null and b/app/assets/gift-cards/kissofmatcha.agi.cash.webp differ diff --git a/app/features/accounts/account-repository.ts b/app/features/accounts/account-repository.ts index 07c1d6961..b19c41e72 100644 --- a/app/features/accounts/account-repository.ts +++ b/app/features/accounts/account-repository.ts @@ -1,6 +1,7 @@ import { type QueryClient, useQueryClient } from '@tanstack/react-query'; import type { DistributedOmit } from 'type-fest'; import { z } from 'zod'; +import { normalizeMintUrl } from '~/lib/cashu'; import { ProofSchema } from '~/lib/cashu/types'; import type { Currency } from '~/lib/money'; import { @@ -122,7 +123,7 @@ export class AccountRepository { let details = {}; if (accountInput.type === 'cashu') { details = CashuAccountDetailsDbDataSchema.parse({ - mint_url: accountInput.mintUrl, + mint_url: normalizeMintUrl(accountInput.mintUrl), is_test_mint: accountInput.isTestMint, keyset_counters: accountInput.keysetCounters, } satisfies z.input); diff --git a/app/features/gift-cards/use-discover-cards.ts b/app/features/gift-cards/use-discover-cards.ts index 11ccb6d39..b9d2cb8ab 100644 --- a/app/features/gift-cards/use-discover-cards.ts +++ b/app/features/gift-cards/use-discover-cards.ts @@ -1,6 +1,7 @@ import { useMemo } from 'react'; import blockAndBeanCard from '~/assets/gift-cards/blockandbean.agi.cash.webp'; import compassCoffeeCard from '~/assets/gift-cards/compass.agi.cash.webp'; +import kissOfMatchaCard from '~/assets/gift-cards/kissofmatcha.agi.cash.webp'; import mapleCard from '~/assets/gift-cards/maple.agi.cash.webp'; import mariposaCard from '~/assets/gift-cards/mariposa.agi.cash.webp'; import pinkOwlCoffeeCard from '~/assets/gift-cards/pinkowl.agi.cash.webp'; @@ -23,6 +24,7 @@ const GIFT_CARD_IMAGES: Record = { 'https://maple.agi.cash': mapleCard, 'https://mariposa.agi.cash': mariposaCard, 'https://compass.agi.cash': compassCoffeeCard, + 'https://kissofmatcha.agi.cash': kissOfMatchaCard, 'https://pinkowl.agi.cash': pinkOwlCoffeeCard, 'https://shack.agi.cash': theShackCard, 'https://theepicureantrader.agi.cash': theEpicurianTraderCard, diff --git a/app/features/receive/receive-cashu-token.tsx b/app/features/receive/receive-cashu-token.tsx index 00c67755d..8d9b4fabf 100644 --- a/app/features/receive/receive-cashu-token.tsx +++ b/app/features/receive/receive-cashu-token.tsx @@ -334,7 +334,10 @@ export default function ReceiveToken({ className="w-[200px]" loading={isClaimLoading} > - {isReceiveAccountKnown ? 'Claim' : 'Add Mint and Claim'} + {!isReceiveAccountKnown && + receiveAccount.purpose === 'transactional' + ? 'Add Mint and Claim' + : 'Claim'} )} diff --git a/app/features/user/user-repository.ts b/app/features/user/user-repository.ts index 4d5b4f2ea..fa18f6849 100644 --- a/app/features/user/user-repository.ts +++ b/app/features/user/user-repository.ts @@ -1,6 +1,7 @@ import type { QueryClient } from '@tanstack/react-query'; import type { DistributedOmit } from 'type-fest'; import type { z } from 'zod'; +import { normalizeMintUrl } from '~/lib/cashu'; import type { Currency } from '~/lib/money'; import type { Account, RedactedAccount } from '../accounts/account'; import { @@ -187,7 +188,7 @@ export class WriteUserRepository { details: (() => { if (account.type === 'cashu') { return CashuAccountDetailsDbDataSchema.parse({ - mint_url: account.mintUrl, + mint_url: normalizeMintUrl(account.mintUrl), is_test_mint: account.isTestMint, keyset_counters: {}, } satisfies z.input); diff --git a/app/lib/cashu/utils.ts b/app/lib/cashu/utils.ts index c178cdc62..ca09b4801 100644 --- a/app/lib/cashu/utils.ts +++ b/app/lib/cashu/utils.ts @@ -264,6 +264,14 @@ export const getCashuWallet = ( }); }; +/** + * Normalize a mint URL by trimming whitespace, lowercasing, and stripping + * trailing slashes. Use this whenever a mint URL is stored or compared so + * variants like `https://Mint.io/` and `https://mint.io` match. + */ +export const normalizeMintUrl = (mintUrl: string): string => + mintUrl.trim().toLowerCase().replace(/\/+$/, ''); + /** * Check if a mint is a test mint by checking if the mint is in the list of * known test mints. @@ -276,9 +284,7 @@ export const getCashuWallet = ( * @returns True if the mint is a known test mint */ export const checkIsTestMint = (mintUrl: string): boolean => { - // Normalize URL by removing trailing slash and converting to lowercase - const normalizedUrl = mintUrl.toLowerCase().replace(/\/+$/, ''); - return knownTestMints.includes(normalizedUrl); + return knownTestMints.includes(normalizeMintUrl(mintUrl)); }; /** @@ -288,8 +294,5 @@ export const checkIsTestMint = (mintUrl: string): boolean => { * @returns True if the mint URLs are equal */ export const areMintUrlsEqual = (a: string, b: string) => { - return ( - a.toLowerCase().replace(/\/+$/, '').trim() === - b.toLowerCase().replace(/\/+$/, '').trim() - ); + return normalizeMintUrl(a) === normalizeMintUrl(b); };