Skip to content

Commit 184a914

Browse files
chore: refactor
1 parent 57f3fce commit 184a914

3 files changed

Lines changed: 49 additions & 62 deletions

File tree

packages/snap/src/core/handlers/onClientRequest/ClientRequestHandler.ts

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
import { SnapError, type Json, type JsonRpcRequest } from '@metamask/snaps-sdk';
1+
import { type Json, type JsonRpcRequest } from '@metamask/snaps-sdk';
22
import { assert, enums } from '@metamask/superstruct';
33

44
import type { ILogger } from '../../utils/logger';
55
import type { SignAndSendTransactionWithIntentUseCase } from './SignAndSendTransactionWithIntentUseCase';
66
import type { ClientRequestUseCase } from './types';
7-
import { ClientRequestMethod } from './types';
7+
import {
8+
ClientRequestMethod,
9+
SignAndSendTransactionWithIntentParamsStruct,
10+
} from './types';
811

912
export class ClientRequestHandler {
1013
readonly #methodToUseCase: Record<ClientRequestMethod, ClientRequestUseCase>;
@@ -31,18 +34,23 @@ export class ClientRequestHandler {
3134
* @returns The response to the JSON-RPC request.
3235
*/
3336
async handle(request: JsonRpcRequest): Promise<Json> {
34-
try {
35-
this.#logger.log('[onClientRequest] Handling client request...', request);
36-
37-
const { method } = request;
38-
assert(method, enums(Object.values(ClientRequestMethod)));
39-
40-
const useCase = this.#methodToUseCase[method];
41-
42-
return useCase.execute(request);
43-
} catch (error: any) {
44-
this.#logger.error(error, 'Error handling client request');
45-
throw new SnapError(error);
37+
this.#logger.log('[onClientRequest] Handling client request...', request);
38+
39+
const { method, params } = request;
40+
assert(method, enums(Object.values(ClientRequestMethod)));
41+
42+
// Parse and validate parameters based on method
43+
let parsedParams: any;
44+
switch (method) {
45+
case ClientRequestMethod.SignAndSendTransactionWithIntent:
46+
assert(params, SignAndSendTransactionWithIntentParamsStruct);
47+
parsedParams = params;
48+
break;
49+
default:
50+
throw new Error(`Unsupported method: ${method}`);
4651
}
52+
53+
const useCase = this.#methodToUseCase[method];
54+
return useCase.execute(parsedParams);
4755
}
4856
}

packages/snap/src/core/handlers/onClientRequest/SignAndSendTransactionWithIntentUseCase.ts

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
import { SolMethod } from '@metamask/keyring-api';
2-
import { assert, literal, object } from '@metamask/superstruct';
3-
import type { Json, JsonRpcRequest } from '@metamask/utils';
2+
import { assert, object } from '@metamask/superstruct';
3+
import type { Json } from '@metamask/utils';
44

55
import { Network } from '../../constants/solana';
66
import type { WalletService } from '../../services/wallet/WalletService';
77
import type { ILogger } from '../../utils/logger';
88
import type { SolanaKeyring } from '../onKeyringRequest/Keyring';
9-
import type { ClientRequestUseCase } from './types';
10-
import {
11-
ClientRequestMethod,
12-
SignAndSendTransactionWithIntentParamsStruct,
9+
import type {
10+
ClientRequestUseCase,
11+
SignAndSendTransactionWithIntentParams,
1312
} from './types';
1413

1514
export class SignAndSendTransactionWithIntentUseCase
16-
implements ClientRequestUseCase
15+
implements ClientRequestUseCase<SignAndSendTransactionWithIntentParams>
1716
{
1817
#keyring: SolanaKeyring;
1918

@@ -36,27 +35,18 @@ export class SignAndSendTransactionWithIntentUseCase
3635
* This allows swap/bridge transactions to be executed without user confirmation
3736
* when they match a verified intent from the backend.
3837
*
39-
* @param request - The JSON-RPC request containing the intent, transaction, and signature.
38+
* @param params - The validated parameters containing intent, transaction, and signature.
4039
* @returns The transaction signature if successful.
4140
*/
42-
async execute(request: JsonRpcRequest): Promise<Json> {
41+
async execute(params: SignAndSendTransactionWithIntentParams): Promise<Json> {
4342
this.#logger.log(
4443
'[SignAndSendTransactionWithIntentUseCase] execute',
45-
request,
44+
params,
4645
);
4746

48-
const { method, params } = request;
49-
50-
assert(
51-
method,
52-
literal(ClientRequestMethod.SignAndSendTransactionWithIntent),
53-
);
54-
assert(params, SignAndSendTransactionWithIntentParamsStruct);
55-
5647
const { intent, tx, signature } = params;
5748

58-
// TODO: Implement signature verification
59-
// This should verify that the backend signed the intent and transaction
49+
// Verify that the backend signed the intent (and transaction?)
6050
// to ensure the transaction came from our backend and matches the user's intent
6151
const isValidSignature = await this.#verifyBackendSignature(
6252
intent,
@@ -68,8 +58,7 @@ export class SignAndSendTransactionWithIntentUseCase
6858
throw new Error('Invalid backend signature');
6959
}
7060

71-
// TODO: Implement transaction vs intent verification
72-
// This should verify that the transaction actually performs the swap/bridge
61+
// Verify that the transaction actually performs the swap/bridge
7362
// described in the intent (correct amounts, assets, etc.)
7463
const transactionMatchesIntent = await this.#verifyTransactionMatchesIntent(
7564
intent,
@@ -81,12 +70,11 @@ export class SignAndSendTransactionWithIntentUseCase
8170
}
8271

8372
// Get the user's account
84-
// For now, we'll use the first account, but this should be determined
85-
// based on the intent's from address
86-
const account = (await this.#keyring.listAccounts())[0];
73+
// TODO: How do we know which account to use? For now, we'll use the first account
74+
const account = (await this.#keyring.listAccounts())[0]; // TODO: We should move account CRUDs to an AccountService
8775
assert(account, object());
8876

89-
// TODO: Determine the correct network from the intent
77+
// TODO: How do we know the correct network?
9078
// For now, defaulting to mainnet
9179
const scope: Network = Network.Mainnet;
9280

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import { object, string, union } from '@metamask/superstruct';
2-
import type { Json, JsonRpcRequest } from '@metamask/utils';
1+
import type { Infer } from '@metamask/superstruct';
2+
import { object, string } from '@metamask/superstruct';
3+
import type { Json } from '@metamask/utils';
34
import { CaipAssetTypeStruct } from '@metamask/utils';
45

5-
import { NetworkStruct, UuidStruct } from '../../validation/structs';
6+
import { Base64Struct, UuidStruct } from '../../validation/structs';
67

78
export enum ClientRequestMethod {
89
SignAndSendTransactionWithIntent = 'signAndSendTransactionWithIntent',
@@ -13,34 +14,24 @@ export const IntentStruct = object({
1314
timestamp: string(),
1415
from: object({
1516
asset: CaipAssetTypeStruct,
16-
amount: string(), // Keep as string to preserve precision
17+
amount: string(),
1718
}),
1819
to: object({
1920
asset: CaipAssetTypeStruct,
20-
amount: string(), // Keep as string to preserve precision
21+
amount: string(),
2122
}),
2223
});
2324

2425
export const SignAndSendTransactionWithIntentParamsStruct = object({
2526
intent: IntentStruct,
26-
tx: string(), // Base64 encoded transaction
27-
signature: string(), // Backend signature for verification
27+
tx: Base64Struct, // TODO: What type?
28+
signature: string(), // TODO: What type?
2829
});
2930

30-
export const SignAndSendTransactionWithIntentRequestStruct = object({
31-
id: UuidStruct,
32-
scope: NetworkStruct,
33-
account: UuidStruct,
34-
request: SignAndSendTransactionWithIntentParamsStruct,
35-
});
36-
37-
export const ClientRequestStruct = object({
38-
id: UuidStruct,
39-
scope: NetworkStruct,
40-
account: UuidStruct,
41-
request: union([SignAndSendTransactionWithIntentRequestStruct]),
42-
});
31+
export type SignAndSendTransactionWithIntentParams = Infer<
32+
typeof SignAndSendTransactionWithIntentParamsStruct
33+
>;
4334

44-
export type ClientRequestUseCase = {
45-
execute: (request: JsonRpcRequest) => Promise<Json>;
35+
export type ClientRequestUseCase<TParams = any> = {
36+
execute: (params: TParams) => Promise<Json>;
4637
};

0 commit comments

Comments
 (0)