mirror of
https://github.com/zhigang1992/wallet.git
synced 2026-01-12 22:53:27 +08:00
fix(psbt): parse param schema, return error, closes #3804
This commit is contained in:
@@ -3,7 +3,11 @@ import * as btc from '@scure/btc-signer';
|
||||
import { hexToBytes } from '@stacks/common';
|
||||
|
||||
import { RouteUrls } from '@shared/route-urls';
|
||||
import { SignPsbtRequest } from '@shared/rpc/methods/sign-psbt';
|
||||
import {
|
||||
SignPsbtRequest,
|
||||
getRpcSignPsbtParamErrors,
|
||||
validateRpcSignPsbtParams,
|
||||
} from '@shared/rpc/methods/sign-psbt';
|
||||
import { makeRpcErrorResponse } from '@shared/rpc/rpc-methods';
|
||||
import { ensureArray, isDefined } from '@shared/utils';
|
||||
|
||||
@@ -25,24 +29,23 @@ function validatePsbt(hex: string) {
|
||||
}
|
||||
|
||||
export async function rpcSignPsbt(message: SignPsbtRequest, port: chrome.runtime.Port) {
|
||||
if (!message.params || !message.params.hex) {
|
||||
if (!validateRpcSignPsbtParams(message.params)) {
|
||||
const errors = getRpcSignPsbtParamErrors(message.params);
|
||||
chrome.tabs.sendMessage(
|
||||
getTabIdFromPort(port),
|
||||
makeRpcErrorResponse('signPsbt', {
|
||||
id: message.id,
|
||||
error: { code: RpcErrorCode.INVALID_PARAMS, message: 'Invalid parameters' },
|
||||
error: {
|
||||
code: RpcErrorCode.INVALID_PARAMS,
|
||||
message:
|
||||
'Invalid parameters: ' +
|
||||
errors.map(e => `Error in path ${e.path}, ${e.message}.`).join(' '),
|
||||
},
|
||||
})
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const params: RequestParams = [
|
||||
['requestId', message.id],
|
||||
['hex', message.params.hex],
|
||||
['publicKey', message.params.publicKey],
|
||||
['network', message.params.network ?? 'mainnet'],
|
||||
];
|
||||
|
||||
if (!validatePsbt(message.params.hex)) {
|
||||
chrome.tabs.sendMessage(
|
||||
getTabIdFromPort(port),
|
||||
@@ -54,21 +57,28 @@ export async function rpcSignPsbt(message: SignPsbtRequest, port: chrome.runtime
|
||||
return;
|
||||
}
|
||||
|
||||
const requestParams: RequestParams = [
|
||||
['requestId', message.id],
|
||||
['hex', message.params.hex],
|
||||
['publicKey', message.params.publicKey],
|
||||
['network', message.params.network ?? 'mainnet'],
|
||||
];
|
||||
|
||||
if (isDefined(message.params.account)) {
|
||||
params.push(['accountIndex', message.params.account.toString()]);
|
||||
requestParams.push(['accountIndex', message.params.account.toString()]);
|
||||
}
|
||||
|
||||
if (isDefined(message.params.allowedSighash))
|
||||
ensureArray(message.params.allowedSighash).forEach(hash =>
|
||||
params.push(['allowedSighash', hash.toString()])
|
||||
requestParams.push(['allowedSighash', hash.toString()])
|
||||
);
|
||||
|
||||
if (isDefined(message.params.signAtIndex))
|
||||
ensureArray(message.params.signAtIndex).forEach(index =>
|
||||
params.push(['signAtIndex', index.toString()])
|
||||
requestParams.push(['signAtIndex', index.toString()])
|
||||
);
|
||||
|
||||
const { urlParams, tabId } = makeSearchParamsWithDefaults(port, params);
|
||||
const { urlParams, tabId } = makeSearchParamsWithDefaults(port, requestParams);
|
||||
|
||||
const { id } = await triggerRequestWindowOpen(RouteUrls.RpcSignPsbt, urlParams);
|
||||
listenForPopupClose({
|
||||
|
||||
@@ -38,7 +38,9 @@ export enum WalletDefaultNetworkConfigurationIds {
|
||||
|
||||
export type DefaultNetworkConfigurations = keyof typeof WalletDefaultNetworkConfigurationIds;
|
||||
|
||||
export type NetworkModes = 'mainnet' | 'testnet';
|
||||
export const networkModes = ['mainnet', 'testnet'] as const;
|
||||
|
||||
export type NetworkModes = (typeof networkModes)[number];
|
||||
|
||||
type BitcoinTestnetModes = 'testnet' | 'regtest' | 'signet';
|
||||
|
||||
|
||||
@@ -1,15 +1,36 @@
|
||||
import { DefineRpcMethod, RpcRequest, RpcResponse } from '@btckit/types';
|
||||
import { SignatureHash } from '@scure/btc-signer';
|
||||
import * as yup from 'yup';
|
||||
|
||||
import { NetworkModes } from '@shared/constants';
|
||||
import { networkModes } from '@shared/constants';
|
||||
|
||||
interface SignPsbtRequestParams {
|
||||
publicKey: string;
|
||||
allowedSighash?: SignatureHash[];
|
||||
hex: string;
|
||||
signAtIndex?: number | number[];
|
||||
network?: NetworkModes;
|
||||
account?: number;
|
||||
const rpcSignPsbtValidator = yup.object().shape({
|
||||
publicKey: yup.string().required(),
|
||||
allowedSighash: yup.array().of(yup.number().required()),
|
||||
hex: yup.string().required(),
|
||||
signAtIndex: yup.number().integer().positive(),
|
||||
network: yup.string().oneOf(networkModes),
|
||||
account: yup.number().integer().positive(),
|
||||
});
|
||||
|
||||
type SignPsbtRequestParams = yup.InferType<typeof rpcSignPsbtValidator>;
|
||||
|
||||
export function validateRpcSignPsbtParams(obj: unknown): obj is SignPsbtRequestParams {
|
||||
try {
|
||||
rpcSignPsbtValidator.validateSync(obj, { abortEarly: false });
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function getRpcSignPsbtParamErrors(obj: unknown) {
|
||||
try {
|
||||
rpcSignPsbtValidator.validateSync(obj, { abortEarly: false });
|
||||
return [];
|
||||
} catch (e) {
|
||||
if (e instanceof yup.ValidationError) return e.inner;
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export type SignPsbtRequest = RpcRequest<'signPsbt', SignPsbtRequestParams>;
|
||||
|
||||
Reference in New Issue
Block a user