Skip to content

Commit 8514374

Browse files
committed
refactor: extract convertTransactionToRedeemDelegations as central entry point
Mirror the extension by introducing a single convertTransactionToRedeemDelegations function in app/util/transactions/delegation.ts that handles caveats, executions, optional EIP-7702 authorization, and unconditional flattening of nested redeemDelegations. - getDelegationTransaction is now a thin wrapper that defaults value to 0x0 - Delegation7702PublishHook uses the central function, removing ~100 lines of duplicated delegation/execution/caveat assembly - Flattening of nested redeemDelegations is automatic for every caller
1 parent 2d197c9 commit 8514374

3 files changed

Lines changed: 271 additions & 269 deletions

File tree

app/util/transactions/delegation.test.ts

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ import {
44
TransactionController,
55
TransactionMeta,
66
} from '@metamask/transaction-controller';
7-
import { SignMessenger, getDelegationTransaction } from './delegation';
7+
import {
8+
SignMessenger,
9+
convertTransactionToRedeemDelegations,
10+
getDelegationTransaction,
11+
} from './delegation';
812
import { MOCK_ANY_NAMESPACE, Messenger } from '@metamask/messenger';
913
import { Hex, bytesToHex, remove0x } from '@metamask/utils';
1014
import {
@@ -365,4 +369,82 @@ describe('Transaction Delegation Utils', () => {
365369
});
366370
});
367371
});
372+
373+
describe('convertTransactionToRedeemDelegations', () => {
374+
it('returns data and delegation manager address', async () => {
375+
const result = await convertTransactionToRedeemDelegations({
376+
transaction: TRANSACTION_META_MOCK,
377+
messenger: messengerMock,
378+
});
379+
380+
expect(result.data).toBeDefined();
381+
expect(result.to).toBeDefined();
382+
expect(result.authorizationList).toHaveLength(1);
383+
});
384+
385+
it('skips authorization when skipAuthorization is true', async () => {
386+
const result = await convertTransactionToRedeemDelegations({
387+
transaction: TRANSACTION_META_MOCK,
388+
messenger: messengerMock,
389+
skipAuthorization: true,
390+
});
391+
392+
expect(result.authorizationList).toBeUndefined();
393+
});
394+
395+
it('uses provided caveats instead of deriving them', async () => {
396+
const customCaveat = {
397+
enforcer: '0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef' as Hex,
398+
terms: '0x' as Hex,
399+
args: '0x' as Hex,
400+
};
401+
402+
await convertTransactionToRedeemDelegations({
403+
transaction: TRANSACTION_META_MOCK,
404+
messenger: messengerMock,
405+
caveats: [customCaveat],
406+
skipAuthorization: true,
407+
});
408+
409+
expect(signDelegationMock).toHaveBeenCalledWith({
410+
chainId: TRANSACTION_META_MOCK.chainId,
411+
delegation: expect.objectContaining({
412+
caveats: [customCaveat],
413+
}),
414+
});
415+
});
416+
417+
it('appends additionalExecutions to the execution batch without changing caveat count', async () => {
418+
const extraAddress = '0x1111111111111111111111111111111111111111' as Hex;
419+
const extra = {
420+
target: extraAddress,
421+
value: BigInt(0),
422+
callData: '0x' as Hex,
423+
};
424+
425+
await convertTransactionToRedeemDelegations({
426+
transaction: TRANSACTION_META_MOCK,
427+
messenger: messengerMock,
428+
additionalExecutions: [extra],
429+
skipAuthorization: true,
430+
});
431+
432+
const [signCall] = signDelegationMock.mock.calls;
433+
const signedDelegation = signCall[0].delegation;
434+
expect(signedDelegation.caveats.length).toBeGreaterThan(0);
435+
});
436+
437+
it('uses provided delegationSignature instead of calling messenger', async () => {
438+
const precomputedSig = '0xdeadbeef' as Hex;
439+
440+
await convertTransactionToRedeemDelegations({
441+
transaction: TRANSACTION_META_MOCK,
442+
messenger: messengerMock,
443+
delegationSignature: precomputedSig,
444+
skipAuthorization: true,
445+
});
446+
447+
expect(signDelegationMock).not.toHaveBeenCalled();
448+
});
449+
});
368450
});

0 commit comments

Comments
 (0)