Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 50 additions & 6 deletions app/features/settings/accounts/add-mint-form.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { MintKeyset } from '@cashu/cashu-ts';
import { type QueryClient, useQueryClient } from '@tanstack/react-query';
import { Controller, useForm } from 'react-hook-form';
import { useLocation, useNavigate } from 'react-router';
Expand All @@ -19,7 +20,11 @@ import {
} from '~/features/shared/cashu';
import { useUser } from '~/features/user/user-hooks';
import { useToast } from '~/hooks/use-toast';
import { getCashuProtocolUnit, getMintPurpose } from '~/lib/cashu';
import {
type MintInfo,
getCashuProtocolUnit,
getMintPurpose,
} from '~/lib/cashu';
import type { Currency } from '~/lib/money';
import { LinkWithViewTransition } from '~/lib/transitions';

Expand All @@ -34,17 +39,56 @@ const currencies = [
{ value: 'USD', label: 'USD' },
];

type GetMintInfoAndKeysetsResult =
| {
success: true;
data: {
mintInfo: MintInfo;
keysets: MintKeyset[];
};
}
| {
success: false;
error: string;
};

const getMintInfoAndKeysets = async (
mintUrl: string,
queryClient: QueryClient,
): Promise<GetMintInfoAndKeysetsResult> => {
try {
const [mintInfo, allKeysets] = await Promise.all([
queryClient.fetchQuery(mintInfoQueryOptions(mintUrl)),
queryClient.fetchQuery(allMintKeysetsQueryOptions(mintUrl)),
]);
return { success: true, data: { mintInfo, keysets: allKeysets.keysets } };
} catch (error) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gudnuf cashu-ts returns NetworkError instance for these errors but unfortunately the error is useless because it just gives us the generic message. Ideally we should be able to distinct error codes so we can know if the mint is not found or maybe in case of 500 error that it's just temporarily down. Because of this I used generic message that covers both cases.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's HttpResponseError too. This is from request.ts. It should throw HttpResponse error if it got a response and NetworkError if fetch failed

Image

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when I enter non existing mint url, I get NetworkError which doesn't have a status or anything. if I enter giberish url and also if I enter valid url that fails with 404:

Image

should we just treat all NetworkErrors as mint doesn't exist?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you enter a real mint url, but its offline it will be network error with no status? We don't know whether this means its a real mint or not, so I'd say your current error message is good for network errors.

Can you catch HttpResponseErrors for the case where you input valid url that returns a 404? Then we know its not a valid mint

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure if that will even work. E.g. this dalmatinskiportal.hr that I tried is a local news site and it did return 404 but cashu-ts still threw NetworkError.

console.debug('Failed to validate mint', { cause: error });
return {
success: false,
error:
'Mint not found or temporarily unavailable. Make sure the URL is correct or try again later.',
};
}
};

const validateMint = async (
value: string,
formValues: FormValues,
queryClient: QueryClient,
): Promise<string | true> => {
const unit = getCashuProtocolUnit(formValues.currency);
const [mintInfo, keysets] = await Promise.all([
queryClient.fetchQuery(mintInfoQueryOptions(value)),
queryClient.fetchQuery(allMintKeysetsQueryOptions(value)),
]);
return cashuMintValidator(value, unit, mintInfo, keysets.keysets);
const result = await getMintInfoAndKeysets(value, queryClient);
if (!result.success) {
return result.error;
}

return cashuMintValidator(
value,
unit,
result.data.mintInfo,
result.data.keysets,
);
};

export function AddMintForm() {
Expand Down
1 change: 1 addition & 0 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.