Skip to content

Commit

Permalink
Merge branch 'connect-preserve-errors' into auto-key-consent
Browse files Browse the repository at this point in the history
  • Loading branch information
sidvishnoi authored Oct 2, 2024
2 parents 10d8744 + 7057897 commit b975aa5
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 18 deletions.
22 changes: 17 additions & 5 deletions src/background/services/keyAutoAdd.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import {
ErrorWithKey,
ensureEnd,
errorWithKeyToJSON,
isErrorWithKey,
withResolvers,
type ErrorWithKeyLike,
} from '@/shared/helpers';
import type { Browser, Runtime, Tabs } from 'webextension-polyfill';
import type { WalletAddress } from '@interledger/open-payments';
Expand Down Expand Up @@ -49,7 +51,7 @@ export class KeyAutoAddService {
'publicKey',
'keyId',
]);
this.setConnectState('connecting:key');
this.updateConnectState();
await this.process(info.url, {
publicKey,
keyId,
Expand All @@ -59,7 +61,9 @@ export class KeyAutoAddService {
});
await this.validate(walletAddress.id, keyId);
} catch (error) {
this.setConnectState('error:key');
if (!error.key || !error.key.startsWith('connectWallet_error_')) {
this.updateConnectState(error);
}
throw error;
}
}
Expand Down Expand Up @@ -152,9 +156,17 @@ export class KeyAutoAddService {
}
}

private setConnectState(status: 'connecting:key' | 'error:key' | null) {
const state = status ? { status } : null;
this.storage.setPopupTransientState('connect', () => state);
private updateConnectState(err?: ErrorWithKeyLike | { message: string }) {
if (err) {
this.storage.setPopupTransientState('connect', () => ({
status: 'error:key',
error: isErrorWithKey(err) ? errorWithKeyToJSON(err) : err.message,
}));
} else {
this.storage.setPopupTransientState('connect', () => ({
status: 'connecting:key',
}));
}
}

static supports(walletAddress: WalletAddress): boolean {
Expand Down
28 changes: 23 additions & 5 deletions src/background/services/openPayments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,13 @@ import { exportJWK, generateEd25519KeyPair } from '@/shared/crypto';
import { bytesToHex } from '@noble/hashes/utils';
import {
ErrorWithKey,
errorWithKeyToJSON,
getWalletInformation,
isErrorWithKey,
withResolvers,
type ErrorWithKeyLike,
} from '@/shared/helpers';
import { AddFundsPayload, ConnectWalletPayload } from '@/shared/messages';
import type { AddFundsPayload, ConnectWalletPayload } from '@/shared/messages';
import {
DEFAULT_RATE_OF_PAY,
MAX_RATE_OF_PAY,
Expand Down Expand Up @@ -380,7 +383,8 @@ export class OpenPaymentsService {
);
} catch (error) {
if (
error.message === this.t('connectWallet_error_invalidClient') &&
isErrorWithKey(error) &&
error.key === 'connectWallet_error_invalidClient' &&
autoKeyAdd
) {
if (!KeyAutoAddService.supports(walletAddress)) {
Expand All @@ -406,11 +410,11 @@ export class OpenPaymentsService {
tabId,
);
} catch (error) {
this.setConnectState('error');
this.updateConnectStateError(error);
throw error;
}
} else {
this.setConnectState('error');
this.updateConnectStateError(error);
throw error;
}
}
Expand Down Expand Up @@ -469,6 +473,9 @@ export class OpenPaymentsService {
amount: transformedAmount,
}).catch((err) => {
if (isInvalidClientError(err)) {
if (intent === InteractionIntent.CONNECT) {
throw new ErrorWithKey('connectWallet_error_invalidClient');
}
const msg = this.t('connectWallet_error_invalidClient');
throw new Error(msg, { cause: err });
}
Expand Down Expand Up @@ -590,10 +597,21 @@ export class OpenPaymentsService {
}
}

private setConnectState(status: 'connecting' | 'error' | null) {
private setConnectState(status: 'connecting' | null) {
const state = status ? { status } : null;
this.storage.setPopupTransientState('connect', () => state);
}
private updateConnectStateError(err: ErrorWithKeyLike | { message: string }) {
this.storage.setPopupTransientState('connect', (state) => {
if (state?.status === 'error:key') {
return state;
}
return {
status: 'error',
error: isErrorWithKey(err) ? errorWithKeyToJSON(err) : err.message,
};
});
}

private async redirectToWelcomeScreen(
tabId: NonNullable<Tabs.Tab['id']>,
Expand Down
38 changes: 33 additions & 5 deletions src/popup/components/ConnectWalletForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ export const ConnectWalletForm = ({
defaultValues.recurring || false,
);

const [autoKeyShareFailed, setAutoKeyShareFailed] = React.useState(false);
const [autoKeyShareFailed, setAutoKeyShareFailed] = React.useState(
isAutoKeyAddFailed(state),
);
const [showConsent, setShowConsent] = React.useState(false);
const autoKeyAddConsent = React.useRef<boolean>(
defaultValues.autoKeyAddConsent || false,
Expand All @@ -74,8 +76,18 @@ export const ConnectWalletForm = ({
const [errors, setErrors] = React.useState({
walletAddressUrl: '',
amount: '',
keyPair: '',
connect: '',
keyPair:
state?.status === 'error:key'
? isErrorWithKey(state.error)
? t(state.error)
: state.error
: '',
connect:
state?.status === 'error'
? isErrorWithKey(state.error)
? t(state.error)
: state.error
: '',
});
const [isValidating, setIsValidating] = React.useState({
walletAddressUrl: false,
Expand Down Expand Up @@ -266,6 +278,7 @@ export const ConnectWalletForm = ({
autoComplete="on"
spellCheck={false}
enterKeyHint="go"
readOnly={isSubmitting}
onPaste={async (ev) => {
const input = ev.currentTarget;
let value = ev.clipboardData.getData('text');
Expand Down Expand Up @@ -313,7 +326,7 @@ export const ConnectWalletForm = ({
placeholder="5.00"
className="max-w-32"
defaultValue={amount}
readOnly={!walletAddressInfo?.assetCode}
readOnly={!walletAddressInfo?.assetCode || isSubmitting}
addOn={<span className="text-weak">{currencySymbol.symbol}</span>}
aria-invalid={!!errors.amount}
aria-describedby={errors.amount}
Expand Down Expand Up @@ -352,7 +365,7 @@ export const ConnectWalletForm = ({
details: errors.keyPair,
whyText: t('connectWallet_error_failedAutoKeyAddWhy'),
}}
hideError={autoKeyShareFailed}
hideError={!errors.keyPair}
text={t('connectWallet_label_publicKey')}
learnMoreText={t('connectWallet_text_publicKeyLearnMore')}
publicKey={publicKey}
Expand Down Expand Up @@ -456,6 +469,21 @@ const ManualKeyPairNeeded: React.FC<{
);
};

function isAutoKeyAddFailed(state: PopupTransientState['connect']) {
if (state?.status === 'error') {
return (
isErrorWithKey(state.error) &&
state.error.key !== 'connectWallet_error_tabClosed'
);
} else if (state?.status === 'error:key') {
return (
isErrorWithKey(state.error) &&
state.error.key.startsWith('connectWalletKeyService_error_')
);
}
return false;
}

const Footer: React.FC<{
text: string;
learnMoreText: string;
Expand Down
8 changes: 5 additions & 3 deletions src/shared/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { WalletAddress } from '@interledger/open-payments/dist/types';
import type { Tabs } from 'webextension-polyfill';
import type { ErrorWithKeyLike } from './helpers';

/** Bigint amount, before transformation with assetScale */
export type AmountValue = string;
Expand Down Expand Up @@ -109,9 +110,10 @@ export type PopupTabInfo = {
};

export type PopupTransientState = Partial<{
connect: Partial<{
status: 'connecting' | 'connecting:key' | 'error' | 'error:key' | null;
}> | null;
connect:
| null
| { status: 'connecting' | 'connecting:key' }
| { status: 'error' | 'error:key'; error: string | ErrorWithKeyLike };
}>;

export type PopupStore = Omit<
Expand Down

0 comments on commit b975aa5

Please sign in to comment.