Skip to content

Commit 81603e0

Browse files
committed
Split logic
Add constants. Add version validation.
1 parent 419d966 commit 81603e0

File tree

2 files changed

+125
-69
lines changed

2 files changed

+125
-69
lines changed

app/scripts/lib/transaction/eip5792.test.ts

+15
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,21 @@ describe('EIP-5792', () => {
155155
).toStrictEqual({ id: BATCH_ID_MOCK });
156156
});
157157

158+
it('throws if version not supported', async () => {
159+
await expect(
160+
processSendCalls(
161+
{
162+
addTransactionBatch: addTransactionBatchMock,
163+
getDisabledAccountUpgradeChains:
164+
getDisabledAccountUpgradeChainsMock,
165+
},
166+
messenger,
167+
{ ...SEND_CALLS_MOCK, version: '2.0' },
168+
REQUEST_MOCK,
169+
),
170+
).rejects.toThrow(`Version not supported: Got 2.0, expected 1.0`);
171+
});
172+
158173
it('throws if chain ID does not match network client', async () => {
159174
await expect(
160175
processSendCalls(

app/scripts/lib/transaction/eip5792.ts

+110-69
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
Log,
55
TransactionController,
66
TransactionControllerGetStateAction,
7+
TransactionMeta,
78
TransactionReceipt,
89
TransactionStatus,
910
} from '@metamask/transaction-controller';
@@ -22,6 +23,9 @@ type Actions =
2223

2324
export type EIP5792Messenger = Messenger<Actions, never>;
2425

26+
const VERSION_SEND_CALLS = '1.0';
27+
const VERSION_GET_CALLS_STATUS = '1.0';
28+
2529
export async function processSendCalls(
2630
hooks: {
2731
addTransactionBatch: TransactionController['addTransactionBatch'];
@@ -32,7 +36,7 @@ export async function processSendCalls(
3236
req: JsonRpcRequest & { networkClientId: string; origin?: string },
3337
): Promise<SendCallsResult> {
3438
const { addTransactionBatch, getDisabledAccountUpgradeChains } = hooks;
35-
const { calls, capabilities, chainId: requestChainId, from } = params;
39+
const { calls, from } = params;
3640
const { networkClientId, origin } = req;
3741
const transactions = calls.map((call) => ({ params: call }));
3842

@@ -41,46 +45,9 @@ export async function processSendCalls(
4145
networkClientId,
4246
).configuration.chainId;
4347

44-
if (
45-
requestChainId &&
46-
requestChainId.toLowerCase() !== dappChainId.toLowerCase()
47-
) {
48-
throw rpcErrors.invalidInput(
49-
`Chain ID must match the dApp selected network: Got ${requestChainId}, expected ${dappChainId}`,
50-
);
51-
}
52-
53-
const requiredTopLevelCapabilities = Object.keys(capabilities ?? {}).filter(
54-
(name) => capabilities?.[name].optional !== true,
55-
);
56-
57-
const requiredCallCapabilities = calls.flatMap((call) =>
58-
Object.keys(call.capabilities ?? {}).filter(
59-
(name) => call.capabilities?.[name].optional !== true,
60-
),
61-
);
62-
63-
const requiredCapabilities = [
64-
...requiredTopLevelCapabilities,
65-
...requiredCallCapabilities,
66-
];
67-
68-
if (requiredCapabilities?.length) {
69-
throw rpcErrors.invalidInput(
70-
`Unsupported non-optional capabilities: ${requiredCapabilities.join(
71-
', ',
72-
)}`,
73-
);
74-
}
75-
7648
const disabledChains = getDisabledAccountUpgradeChains();
77-
const isDisabled = disabledChains.includes(dappChainId);
7849

79-
if (isDisabled) {
80-
throw rpcErrors.methodNotSupported(
81-
`EIP-5792 is not supported for this chain and account - Chain ID: ${dappChainId}, Account: ${from}`,
82-
);
83-
}
50+
validateSendCalls(params, dappChainId, disabledChains);
8451

8552
const { batchId: id } = await addTransactionBatch({
8653
from,
@@ -104,35 +71,13 @@ export function getCallsStatus(
10471
throw rpcErrors.invalidInput(`No matching calls found`);
10572
}
10673

107-
const {
108-
chainId,
109-
hash,
110-
txReceipt: rawTxReceipt,
111-
status: transactionStatus,
112-
} = transactions[0];
113-
114-
let status = GetCallsStatusCode.PENDING;
115-
116-
if (transactionStatus === TransactionStatus.confirmed) {
117-
status = GetCallsStatusCode.CONFIRMED;
118-
} else if (transactionStatus === TransactionStatus.failed) {
119-
status = hash
120-
? GetCallsStatusCode.REVERTED
121-
: GetCallsStatusCode.FAILED_OFFCHAIN;
122-
} else if (transactionStatus === TransactionStatus.dropped) {
123-
status = GetCallsStatusCode.REVERTED;
124-
}
125-
126-
const txReceipt = rawTxReceipt as unknown as Required<TransactionReceipt> & {
127-
transactionHash: Hex;
128-
};
129-
130-
const logs =
131-
(txReceipt.logs as (Required<Log> & {
132-
data: Hex;
133-
})[]) ?? [];
74+
const transaction = transactions[0];
75+
const { chainId, txReceipt: rawTxReceipt } = transaction;
76+
const status = getStatusCode(transaction);
77+
const txReceipt = rawTxReceipt as Required<TransactionReceipt> | undefined;
78+
const logs = (txReceipt?.logs ?? []) as Required<Log>[];
13479

135-
const receipts: GetCallsStatusResult['receipts'] = [
80+
const receipts: GetCallsStatusResult['receipts'] = txReceipt && [
13681
{
13782
blockHash: txReceipt.blockHash as Hex,
13883
blockNumber: txReceipt.blockNumber as Hex,
@@ -142,13 +87,13 @@ export function getCallsStatus(
14287
data: log.data,
14388
topics: log.topics as unknown as Hex[],
14489
})),
145-
status: txReceipt.status as Hex,
90+
status: txReceipt.status as '0x0' | '0x1',
14691
transactionHash: txReceipt.transactionHash,
14792
},
14893
];
14994

15095
return {
151-
version: '1.0',
96+
version: VERSION_GET_CALLS_STATUS,
15297
id,
15398
chainId,
15499
status,
@@ -160,3 +105,99 @@ export async function getCapabilities(_address: Hex, _chainIds?: Hex[]) {
160105
// No capabilities currently supported
161106
return {};
162107
}
108+
109+
function validateSendCalls(
110+
sendCalls: SendCalls,
111+
dappChainId: Hex,
112+
disabledChains: Hex[],
113+
) {
114+
validateSendCallsVersion(sendCalls);
115+
validateSendCallsChainId(sendCalls, dappChainId);
116+
validateCapabilities(sendCalls);
117+
validateUserDisabled(sendCalls, disabledChains, dappChainId);
118+
}
119+
120+
function validateSendCallsVersion(sendCalls: SendCalls) {
121+
const { version } = sendCalls;
122+
123+
if (version !== VERSION_SEND_CALLS) {
124+
throw rpcErrors.invalidInput(
125+
`Version not supported: Got ${version}, expected ${VERSION_SEND_CALLS}`,
126+
);
127+
}
128+
}
129+
130+
function validateSendCallsChainId(sendCalls: SendCalls, dappChainId: Hex) {
131+
const { chainId: requestChainId } = sendCalls;
132+
133+
if (
134+
requestChainId &&
135+
requestChainId.toLowerCase() !== dappChainId.toLowerCase()
136+
) {
137+
throw rpcErrors.invalidInput(
138+
`Chain ID must match the dApp selected network: Got ${requestChainId}, expected ${dappChainId}`,
139+
);
140+
}
141+
}
142+
143+
function validateCapabilities(sendCalls: SendCalls) {
144+
const { calls, capabilities } = sendCalls;
145+
146+
const requiredTopLevelCapabilities = Object.keys(capabilities ?? {}).filter(
147+
(name) => capabilities?.[name].optional !== true,
148+
);
149+
150+
const requiredCallCapabilities = calls.flatMap((call) =>
151+
Object.keys(call.capabilities ?? {}).filter(
152+
(name) => call.capabilities?.[name].optional !== true,
153+
),
154+
);
155+
156+
const requiredCapabilities = [
157+
...requiredTopLevelCapabilities,
158+
...requiredCallCapabilities,
159+
];
160+
161+
if (requiredCapabilities?.length) {
162+
throw rpcErrors.invalidInput(
163+
`Unsupported non-optional capabilities: ${requiredCapabilities.join(
164+
', ',
165+
)}`,
166+
);
167+
}
168+
}
169+
170+
function validateUserDisabled(
171+
sendCalls: SendCalls,
172+
disabledChains: Hex[],
173+
dappChainId: Hex,
174+
) {
175+
const { from } = sendCalls;
176+
const isDisabled = disabledChains.includes(dappChainId);
177+
178+
if (isDisabled) {
179+
throw rpcErrors.methodNotSupported(
180+
`EIP-5792 is not supported for this chain and account - Chain ID: ${dappChainId}, Account: ${from}`,
181+
);
182+
}
183+
}
184+
185+
function getStatusCode(transactionMeta: TransactionMeta) {
186+
const { hash, status } = transactionMeta;
187+
188+
if (status === TransactionStatus.confirmed) {
189+
return GetCallsStatusCode.CONFIRMED;
190+
}
191+
192+
if (status === TransactionStatus.failed) {
193+
return hash
194+
? GetCallsStatusCode.REVERTED
195+
: GetCallsStatusCode.FAILED_OFFCHAIN;
196+
}
197+
198+
if (status === TransactionStatus.dropped) {
199+
return GetCallsStatusCode.REVERTED;
200+
}
201+
202+
return GetCallsStatusCode.PENDING;
203+
}

0 commit comments

Comments
 (0)