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
1 change: 1 addition & 0 deletions src/methods/wallet-get-calls-status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export type GetCallsStatusResult = {
id: Hex;
chainId: Hex;
status: number;
atomic: boolean;
receipts?: {
logs: {
address: Hex;
Expand Down
18 changes: 17 additions & 1 deletion src/methods/wallet-get-capabilities.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import type {
GetCapabilitiesResult,
} from './wallet-get-capabilities';
import { walletGetCapabilities } from './wallet-get-capabilities';
import type { WalletMiddlewareOptions } from '../wallet';

type GetAccounts = WalletMiddlewareOptions['getAccounts'];

const ADDRESS_MOCK = '0x123abc123abc123abc123abc123abc123abc123a';
const CHAIN_ID_MOCK = '0x1';
Expand All @@ -26,10 +29,12 @@ describe('wallet_getCapabilities', () => {
let request: JsonRpcRequest;
let params: GetCapabilitiesParams;
let response: PendingJsonRpcResponse<GetCapabilitiesResult>;
let getAccountsMock: jest.MockedFn<GetAccounts>;
let getCapabilitiesMock: jest.MockedFunction<GetCapabilitiesHook>;

async function callMethod() {
return walletGetCapabilities(request, response, {
getAccounts: getAccountsMock,
getCapabilities: getCapabilitiesMock,
});
}
Expand All @@ -41,6 +46,7 @@ describe('wallet_getCapabilities', () => {
params = request.params as GetCapabilitiesParams;
response = {} as PendingJsonRpcResponse<GetCapabilitiesResult>;

getAccountsMock = jest.fn().mockResolvedValue([ADDRESS_MOCK]);
getCapabilitiesMock = jest.fn().mockResolvedValue(RESULT_MOCK);
});

Expand Down Expand Up @@ -72,7 +78,9 @@ describe('wallet_getCapabilities', () => {

it('throws if no hook', async () => {
await expect(
walletGetCapabilities(request, response, {}),
walletGetCapabilities(request, response, {
getAccounts: getAccountsMock,
}),
).rejects.toMatchInlineSnapshot(`[Error: Method not supported.]`);
});

Expand Down Expand Up @@ -115,4 +123,12 @@ describe('wallet_getCapabilities', () => {
0 - Expected a string matching \`/^0x[0-9a-fA-F]{40}$/\` but received "0x123"]
`);
});

it('throws if from is not in accounts', async () => {
getAccountsMock.mockResolvedValueOnce([]);

await expect(callMethod()).rejects.toMatchInlineSnapshot(
`[Error: The requested account and/or method has not been authorized by the user.]`,
);
});
});
12 changes: 11 additions & 1 deletion src/methods/wallet-get-capabilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import type {
} from '@metamask/utils';
import { StrictHexStruct, HexChecksumAddressStruct } from '@metamask/utils';

import { validateParams } from '../utils/validation';
import {
validateAndNormalizeKeyholder,
validateParams,
} from '../utils/validation';

const GetCapabilitiesStruct = tuple([
HexChecksumAddressStruct,
Expand All @@ -29,8 +32,10 @@ export async function walletGetCapabilities(
req: JsonRpcRequest,
res: PendingJsonRpcResponse<Json>,
{
getAccounts,
getCapabilities,
}: {
getAccounts: (req: JsonRpcRequest) => Promise<string[]>;
getCapabilities?: GetCapabilitiesHook;
},
): Promise<void> {
Expand All @@ -42,6 +47,11 @@ export async function walletGetCapabilities(

const address = req.params[0];
const chainIds = req.params[1];

await validateAndNormalizeKeyholder(address, req, {
getAccounts,
});

const capabilities = await getCapabilities(address, chainIds, req);

res.result = capabilities;
Expand Down
6 changes: 5 additions & 1 deletion src/methods/wallet-send-calls.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const REQUEST_MOCK = {
version: '1.0',
from: ADDRESS_MOCK,
chainId: HEX_MOCK,
atomicRequired: true,
calls: [
{
to: ADDRESS_MOCK,
Expand Down Expand Up @@ -123,12 +124,13 @@ describe('wallet_sendCalls', () => {
params[0].from = undefined as never;
params[0].chainId = undefined as never;
params[0].calls = undefined as never;
params[0].atomicRequired = undefined as never;

await expect(callMethod()).rejects.toMatchInlineSnapshot(`
[Error: Invalid params

0 > from - Expected a string, but received: undefined
0 > chainId - Expected a string, but received: undefined
0 > atomicRequired - Expected a value of type \`boolean\`, but received: \`undefined\`
0 > calls - Expected an array value, but received: undefined]
`);
});
Expand All @@ -139,13 +141,15 @@ describe('wallet_sendCalls', () => {
params[0].chainId = 123 as never;
params[0].calls = '123' as never;
params[0].capabilities = '123' as never;
params[0].atomicRequired = 123 as never;

await expect(callMethod()).rejects.toMatchInlineSnapshot(`
[Error: Invalid params

0 > id - Expected a string, but received: 123
0 > from - Expected a string matching \`/^0x[0-9a-fA-F]{40}$/\` but received "123"
0 > chainId - Expected a string, but received: 123
0 > atomicRequired - Expected a value of type \`boolean\`, but received: \`123\`
0 > calls - Expected an array value, but received: "123"
0 > capabilities - Expected an object, but received: "123"]
`);
Expand Down
11 changes: 7 additions & 4 deletions src/methods/wallet-send-calls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ const SendCallsStruct = tuple([
object({
version: nonempty(string()),
id: optional(StrictHexStruct),
from: HexChecksumAddressStruct,
from: optional(HexChecksumAddressStruct),
chainId: StrictHexStruct,
atomicRequired: boolean(),
calls: array(
object({
to: optional(HexChecksumAddressStruct),
Expand Down Expand Up @@ -81,9 +82,11 @@ export async function walletSendCalls(

const params = req.params[0];

const from = await validateAndNormalizeKeyholder(params.from, req, {
getAccounts,
});
const from = params.from
? await validateAndNormalizeKeyholder(params.from, req, {
getAccounts,
})
: undefined;

const sendCalls: SendCalls = {
...params,
Expand Down
2 changes: 1 addition & 1 deletion src/utils/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export function validateParams<ParamsType>(
const [error] = validate(value, struct);

if (error) {
throw rpcErrors.invalidInput(
throw rpcErrors.invalidParams(
formatValidationError(error, `Invalid params`),
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@

// EIP-5792
wallet_getCapabilities: createAsyncMiddleware(async (params, req) =>
walletGetCapabilities(params, req, { getCapabilities }),
walletGetCapabilities(params, req, { getAccounts, getCapabilities }),
),
wallet_sendCalls: createAsyncMiddleware(async (params, req) =>
walletSendCalls(params, req, { getAccounts, processSendCalls }),
Expand Down Expand Up @@ -461,7 +461,7 @@
*
* @param address - The address to validate and normalize.
* @param req - The request object.
* @returns {string} - The normalized address, if valid. Otherwise, throws

Check warning on line 464 in src/wallet.ts

View workflow job for this annotation

GitHub Actions / Build, lint, and test / Lint (18.x)

There must be no hyphen before @returns description

Check warning on line 464 in src/wallet.ts

View workflow job for this annotation

GitHub Actions / Build, lint, and test / Lint (18.x)

JSDoc description does not satisfy the regex pattern

Check warning on line 464 in src/wallet.ts

View workflow job for this annotation

GitHub Actions / Build, lint, and test / Lint (20.x)

There must be no hyphen before @returns description

Check warning on line 464 in src/wallet.ts

View workflow job for this annotation

GitHub Actions / Build, lint, and test / Lint (20.x)

JSDoc description does not satisfy the regex pattern

Check warning on line 464 in src/wallet.ts

View workflow job for this annotation

GitHub Actions / Build, lint, and test / Lint (22.x)

There must be no hyphen before @returns description

Check warning on line 464 in src/wallet.ts

View workflow job for this annotation

GitHub Actions / Build, lint, and test / Lint (22.x)

JSDoc description does not satisfy the regex pattern
* an error
*/
async function validateAndNormalizeKeyholder(
Expand Down
Loading