refactor: psbt error handling, closes #3804

This commit is contained in:
fbwoolf
2023-06-22 14:11:32 -05:00
committed by Fara Woolf
parent 5168e3a1aa
commit 848e0fcb46
6 changed files with 108 additions and 66 deletions

View File

@@ -0,0 +1,51 @@
import { useMemo } from 'react';
import { useSearchParams } from 'react-router-dom';
import * as btc from '@scure/btc-signer';
import { undefinedIfLengthZero } from '@shared/utils';
import { useRejectIfLedgerWallet } from '@app/common/rpc-helpers';
import { useDefaultRequestParams } from '../hooks/use-default-request-search-params';
export function usePsbtRequestSearchParams() {
const [searchParams] = useSearchParams();
const { origin, tabId } = useDefaultRequestParams();
const requestToken = searchParams.get('request');
return useMemo(
() => ({
origin,
tabId: tabId ?? 1,
requestToken,
}),
[origin, requestToken, tabId]
);
}
export function useRpcSignPsbtParams() {
useRejectIfLedgerWallet('signPsbt');
const [searchParams] = useSearchParams();
const { origin, tabId } = useDefaultRequestParams();
const requestId = searchParams.get('requestId');
const psbtHex = searchParams.get('hex');
const allowedSighash = searchParams.getAll('allowedSighash');
const signAtIndex = searchParams.getAll('signAtIndex');
if (!requestId || !psbtHex || !origin) throw new Error('Invalid params');
return useMemo(
() => ({
origin,
tabId: tabId ?? 0,
requestId,
psbtHex,
allowedSighash: undefinedIfLengthZero(
allowedSighash.map(h => Number(h)) as btc.SignatureHash[]
),
signAtIndex: undefinedIfLengthZero(signAtIndex.map(h => Number(h))),
}),
[allowedSighash, origin, psbtHex, requestId, signAtIndex, tabId]
);
}

View File

@@ -9,9 +9,12 @@ import { isString } from '@shared/utils';
import { useCurrentAccountNativeSegwitSigner } from '@app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks';
import { useCurrentAccountTaprootSigner } from '@app/store/accounts/blockchain/bitcoin/taproot-account.hooks';
import { useSignPsbtError } from './use-sign-psbt-error';
export type DecodedPsbt = ReturnType<typeof btc.RawPSBTV0.decode>;
export function usePsbtSigner() {
const signPsbtError = useSignPsbtError();
const createNativeSegwitSigner = useCurrentAccountNativeSegwitSigner();
const createTaprootSigner = useCurrentAccountTaprootSigner();
@@ -27,7 +30,7 @@ export function usePsbtSigner() {
try {
taprootSigner?.signIndex(tx, idx, allowedSighash);
} catch (e2) {
logger.error('Error signing tx at provided index', e1, e2);
signPsbtError(`Error signing PSBT at provided index, ${e1}, ${e2}`);
}
}
},
@@ -38,7 +41,7 @@ export function usePsbtSigner() {
try {
taprootSigner?.sign(tx);
} catch (e2) {
logger.error('Error signing PSBT', e1, e2);
signPsbtError(`Error signing PSBT, ${e1}, ${e2}`);
}
}
},
@@ -51,16 +54,16 @@ export function usePsbtSigner() {
try {
return btc.RawPSBTV0.decode(bytes);
} catch (e0) {
logger.info('Failed to decode as PSBT v0, trying V2', e0);
}
try {
return btc.RawPSBTV2.decode(bytes);
} catch (e2) {
logger.error('Error parsing psbt version', e2);
logger.error(`Failed to decode as PSBT v0, trying v2, ${e0}`);
try {
return btc.RawPSBTV2.decode(bytes);
} catch (e2) {
signPsbtError(`Failed to decode PSBT as v0 and v2, ${e0}, ${e2}`);
}
}
return;
},
}),
[nativeSegwitSigner, taprootSigner]
[nativeSegwitSigner, signPsbtError, taprootSigner]
);
}

View File

@@ -0,0 +1,39 @@
import { useCallback } from 'react';
import { RpcErrorCode } from '@btckit/types';
import { finalizePsbt } from '@shared/actions/finalize-psbt';
import { makeRpcErrorResponse } from '@shared/rpc/rpc-methods';
import {
usePsbtRequestSearchParams,
useRpcSignPsbtParams,
} from '@app/common/psbt/use-psbt-request-params';
export function useSignPsbtError() {
const { requestToken, tabId } = usePsbtRequestSearchParams();
const { requestId, tabId: rpcTabId } = useRpcSignPsbtParams();
return useCallback(
(errorMsg: string) => {
if (requestToken)
finalizePsbt({
requestPayload: requestToken,
tabId,
data: errorMsg,
});
chrome.tabs.sendMessage(
rpcTabId,
makeRpcErrorResponse('signPsbt', {
id: requestId,
error: {
message: errorMsg,
code: RpcErrorCode.INTERNAL_ERROR,
},
})
);
window.close();
},
[requestId, requestToken, rpcTabId, tabId]
);
}

View File

@@ -1,18 +0,0 @@
import { useMemo } from 'react';
import { useSearchParams } from 'react-router-dom';
import { useDefaultRequestParams } from '@app/common/hooks/use-default-request-search-params';
export function usePsbtRequestSearchParams() {
const [searchParams] = useSearchParams();
const { origin, tabId } = useDefaultRequestParams();
const requestToken = searchParams.get('request');
return useMemo(
() => ({
origin,
tabId: tabId ?? 1,
requestToken,
}),
[origin, requestToken, tabId]
);
}

View File

@@ -3,13 +3,12 @@ import { useMemo, useState } from 'react';
import { bytesToHex, hexToBytes } from '@noble/hashes/utils';
import { finalizePsbt } from '@shared/actions/finalize-psbt';
import { logger } from '@shared/logger';
import { ensureArray, isUndefined } from '@shared/utils';
import { useAnalytics } from '@app/common/hooks/analytics/use-analytics';
import { getPsbtPayloadFromToken } from '@app/common/psbt/requests';
import { usePsbtRequestSearchParams } from '@app/common/psbt/use-psbt-request-params';
import { usePsbtSigner } from '@app/features/psbt-signer/hooks/use-psbt-signer';
import { usePsbtRequestSearchParams } from '@app/pages/psbt-request/psbt-request.hooks';
export function usePsbtRequest() {
const { requestToken, tabId } = usePsbtRequestSearchParams();
@@ -18,6 +17,7 @@ export function usePsbtRequest() {
const analytics = useAnalytics();
return useMemo(() => {
if (!requestToken) throw new Error('Cannot decode psbt without request token');
const payload = getPsbtPayloadFromToken(requestToken);
const payloadTxBytes = hexToBytes(payload.hex);
const appName = payload?.appDetails?.name;
@@ -34,7 +34,7 @@ export function usePsbtRequest() {
payloadTxBytes,
onDenyPsbtSigning() {
void analytics.track('request_psbt_cancel');
finalizePsbt({ requestPayload: requestToken ?? '', tabId, data: 'cancel' });
finalizePsbt({ requestPayload: requestToken, tabId, data: 'PSBT request was canceled' });
},
onSignPsbt() {
setIsLoading(true);
@@ -42,8 +42,6 @@ export function usePsbtRequest() {
const tx = getPsbtAsTransaction(payload.hex);
if (!tx) return logger.error('No psbt to sign');
const indexOrIndexes = payload?.signAtIndex;
const allowedSighash = payload?.allowedSighash;

View File

@@ -1,45 +1,13 @@
import { useMemo } from 'react';
import { useSearchParams } from 'react-router-dom';
import { RpcErrorCode } from '@btckit/types';
import { bytesToHex } from '@noble/hashes/utils';
import * as btc from '@scure/btc-signer';
import { makeRpcErrorResponse, makeRpcSuccessResponse } from '@shared/rpc/rpc-methods';
import { isDefined, undefinedIfLengthZero } from '@shared/utils';
import { isDefined } from '@shared/utils';
import { useDefaultRequestParams } from '@app/common/hooks/use-default-request-search-params';
import { useRejectIfLedgerWallet } from '@app/common/rpc-helpers';
import { useRpcSignPsbtParams } from '@app/common/psbt/use-psbt-request-params';
import { usePsbtSigner } from '@app/features/psbt-signer/hooks/use-psbt-signer';
import { PsbtSigner } from '@app/features/psbt-signer/psbt-signer';
function useRpcSignPsbtParams() {
useRejectIfLedgerWallet('signPsbt');
const [searchParams] = useSearchParams();
const { origin, tabId } = useDefaultRequestParams();
const requestId = searchParams.get('requestId');
const psbtHex = searchParams.get('hex');
const allowedSighash = searchParams.getAll('allowedSighash');
const signAtIndex = searchParams.getAll('signAtIndex');
if (!requestId || !psbtHex || !origin) throw new Error('Invalid params');
return useMemo(
() => ({
origin,
tabId: tabId ?? 0,
requestId,
psbtHex,
allowedSighash: undefinedIfLengthZero(
allowedSighash.map(h => Number(h)) as btc.SignatureHash[]
),
signAtIndex: undefinedIfLengthZero(signAtIndex.map(h => Number(h))),
}),
[allowedSighash, origin, psbtHex, requestId, signAtIndex, tabId]
);
}
function useRpcSignPsbt() {
const { origin, tabId, requestId, psbtHex, allowedSighash, signAtIndex } = useRpcSignPsbtParams();
const { signPsbt, signPsbtAtIndex, getDecodedPsbt, getPsbtAsTransaction } = usePsbtSigner();
@@ -78,6 +46,7 @@ function useRpcSignPsbt() {
},
})
);
window.close();
},
};
}