Skip to content
Draft
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@
"@metamask/eth-trezor-keyring": "^9.0.0",
"@metamask/etherscan-link": "^3.0.0",
"@metamask/gas-fee-controller": "^25.0.0",
"@metamask/gator-permissions-controller": "^0.4.0",
"@metamask/gator-permissions-controller": "^0.5.0",
"@metamask/gator-permissions-snap": "^0.7.0",
"@metamask/institutional-wallet-snap": "1.3.4",
"@metamask/jazzicon": "patch:@metamask/jazzicon@npm%3A2.0.0#~/.yarn/patches/@metamask-jazzicon-npm-2.0.0-36957be38d.patch",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
const mockStartTime = 1736271776; // January 7, 2025;

describe('NATIVE token permissions', () => {
const mockExpiryTimestamp = 1767225600; // January 1, 2026

const mockNativeTokenStreamPermission: StoredGatorPermissionSanitized<
Signer,
NativeTokenStreamPermission
Expand All @@ -71,6 +73,15 @@
signerMeta: {
delegationManager: '0xdb9B1e94B5b69Df7e401DDbedE43491141047dB3',
},
rules: [

Check failure on line 76 in ui/components/multichain/pages/gator-permissions/components/review-gator-permission-item.test.tsx

View workflow job for this annotation

GitHub Actions / test-lint / Test lint

Object literal may only specify known properties, and 'rules' does not exist in type 'PermissionResponseSanitized<Signer, NativeTokenStreamPermission>'.
{
type: 'expiry',
isAdjustmentAllowed: false,
data: {
timestamp: mockExpiryTimestamp,
},
},
],
},
siteOrigin: 'http://localhost:8000',
};
Expand All @@ -97,6 +108,15 @@
signerMeta: {
delegationManager: '0xdb9B1e94B5b69Df7e401DDbedE43491141047dB3',
},
rules: [

Check failure on line 111 in ui/components/multichain/pages/gator-permissions/components/review-gator-permission-item.test.tsx

View workflow job for this annotation

GitHub Actions / test-lint / Test lint

Object literal may only specify known properties, and 'rules' does not exist in type 'PermissionResponseSanitized<Signer, NativeTokenPeriodicPermission>'.
{
type: 'expiry',
isAdjustmentAllowed: false,
data: {
timestamp: mockExpiryTimestamp,
},
},
],
},
siteOrigin: 'http://localhost:8000',
};
Expand Down Expand Up @@ -153,11 +173,12 @@
expect(startDate).toBeInTheDocument();
expect(startDate).toHaveTextContent('01/07/2025');

// Verify expiration date is rendered
// Verify expiration date is rendered with correct date (January 1, 2026)
const expirationDate = getByTestId(
'review-gator-permission-expiration-date',
);
expect(expirationDate).toBeInTheDocument();
expect(expirationDate).toHaveTextContent('01/01/2026');

// Verify network name is rendered
const networkName = getByTestId('review-gator-permission-network-name');
Expand Down Expand Up @@ -200,11 +221,12 @@
expect(startDate).toBeInTheDocument();
expect(startDate).toHaveTextContent('01/07/2025');

// Verify expiration date is rendered
// Verify expiration date is rendered with correct date (January 1, 2026)
const expirationDate = getByTestId(
'review-gator-permission-expiration-date',
);
expect(expirationDate).toBeInTheDocument();
expect(expirationDate).toHaveTextContent('01/01/2026');

// Verify network name is rendered
const networkName = getByTestId('review-gator-permission-network-name');
Expand All @@ -219,6 +241,8 @@
const mockTokenAddress: Hex =
'0x2260fac5e5542a773aa44fbcfedf7c193bc2c599';

const mockExpiryTimestamp = 1767225600; // January 1, 2026

const mockErc20TokenPeriodicPermission: StoredGatorPermissionSanitized<
Signer,
Erc20TokenPeriodicPermission
Expand All @@ -242,6 +266,15 @@
signerMeta: {
delegationManager: '0xdb9B1e94B5b69Df7e401DDbedE43491141047dB3',
},
rules: [

Check failure on line 269 in ui/components/multichain/pages/gator-permissions/components/review-gator-permission-item.test.tsx

View workflow job for this annotation

GitHub Actions / test-lint / Test lint

Object literal may only specify known properties, and 'rules' does not exist in type 'PermissionResponseSanitized<Signer, Erc20TokenPeriodicPermission>'.
{
type: 'expiry',
isAdjustmentAllowed: false,
data: {
timestamp: mockExpiryTimestamp,
},
},
],
},
siteOrigin: 'http://localhost:8000',
};
Expand Down Expand Up @@ -270,6 +303,15 @@
signerMeta: {
delegationManager: '0xdb9B1e94B5b69Df7e401DDbedE43491141047dB3',
},
rules: [

Check failure on line 306 in ui/components/multichain/pages/gator-permissions/components/review-gator-permission-item.test.tsx

View workflow job for this annotation

GitHub Actions / test-lint / Test lint

Object literal may only specify known properties, and 'rules' does not exist in type 'PermissionResponseSanitized<Signer, Erc20TokenStreamPermission>'.
{
type: 'expiry',
isAdjustmentAllowed: false,
data: {
timestamp: mockExpiryTimestamp,
},
},
],
},
siteOrigin: 'http://localhost:8000',
};
Expand Down Expand Up @@ -326,11 +368,12 @@
expect(startDate).toBeInTheDocument();
expect(startDate).toHaveTextContent('01/07/2025');

// Verify expiration date is rendered
// Verify expiration date is rendered with correct date (January 1, 2026)
const expirationDate = getByTestId(
'review-gator-permission-expiration-date',
);
expect(expirationDate).toBeInTheDocument();
expect(expirationDate).toHaveTextContent('01/01/2026');

// Verify network name is rendered
const networkName = getByTestId('review-gator-permission-network-name');
Expand Down Expand Up @@ -373,6 +416,13 @@
expect(startDate).toBeInTheDocument();
expect(startDate).toHaveTextContent('01/07/2025');

// Verify expiration date is rendered with correct date (January 1, 2026)
const expirationDate = getByTestId(
'review-gator-permission-expiration-date',
);
expect(expirationDate).toBeInTheDocument();
expect(expirationDate).toHaveTextContent('01/01/2026');

// Verify network name is rendered
const networkName = getByTestId('review-gator-permission-network-name');
expect(networkName).toHaveTextContent(mockNetworkName);
Expand Down Expand Up @@ -450,6 +500,116 @@
const streamRate = getByTestId('review-gator-permission-stream-rate');
expect(streamRate.textContent).toContain('Unknown amount');
});

it('renders "No expiration" when permission has no expiry', () => {
const mockPermissionWithoutExpiry: StoredGatorPermissionSanitized<
Signer,
NativeTokenPeriodicPermission
> = {
permissionResponse: {
chainId: '0x1',
address: mockSelectedAccountAddress,
permission: {
type: 'native-token-periodic',
isAdjustmentAllowed: false,
data: {
periodAmount: '0x6f05b59d3b20000',
periodDuration: 604800,
startTime: mockStartTime,
justification: 'Test permission without expiry',
},
},
context: '0x00000000',
signerMeta: {
delegationManager: '0xdb9B1e94B5b69Df7e401DDbedE43491141047dB3',
},
// No rules array = no expiry
},
siteOrigin: 'http://localhost:8000',
};

const { container, getByTestId } = renderWithProvider(
<ReviewGatorPermissionItem
networkName={mockNetworkName}
gatorPermission={mockPermissionWithoutExpiry}
onRevokeClick={() => mockOnClick()}
/>,
store,
);

// Expand to see expiration date
const expandButton = container.querySelector('[aria-label="expand"]');
if (expandButton) {
fireEvent.click(expandButton);
}

// Verify expiration date shows "No expiration"
const expirationDate = getByTestId(
'review-gator-permission-expiration-date',
);
expect(expirationDate).toBeInTheDocument();
expect(expirationDate).toHaveTextContent('No expiration');
});

it('renders correct expiration date when permission has expiry', () => {
const customExpiryTimestamp = 1744588800; // April 14, 2025

const mockPermissionWithExpiry: StoredGatorPermissionSanitized<
Signer,
NativeTokenPeriodicPermission
> = {
permissionResponse: {
chainId: '0x1',
address: mockSelectedAccountAddress,
permission: {
type: 'native-token-periodic',
isAdjustmentAllowed: false,
data: {
periodAmount: '0x6f05b59d3b20000',
periodDuration: 604800,
startTime: mockStartTime,
justification: 'Test permission with expiry',
},
},
context: '0x00000000',
signerMeta: {
delegationManager: '0xdb9B1e94B5b69Df7e401DDbedE43491141047dB3',
},
rules: [

Check failure on line 578 in ui/components/multichain/pages/gator-permissions/components/review-gator-permission-item.test.tsx

View workflow job for this annotation

GitHub Actions / test-lint / Test lint

Object literal may only specify known properties, and 'rules' does not exist in type 'PermissionResponseSanitized<Signer, NativeTokenPeriodicPermission>'.
{
type: 'expiry',
isAdjustmentAllowed: false,
data: {
timestamp: customExpiryTimestamp,
},
},
],
},
siteOrigin: 'http://localhost:8000',
};

const { container, getByTestId } = renderWithProvider(
<ReviewGatorPermissionItem
networkName={mockNetworkName}
gatorPermission={mockPermissionWithExpiry}
onRevokeClick={() => mockOnClick()}
/>,
store,
);

// Expand to see expiration date
const expandButton = container.querySelector('[aria-label="expand"]');
if (expandButton) {
fireEvent.click(expandButton);
}

// Verify expiration date shows the correct date
const expirationDate = getByTestId(
'review-gator-permission-expiration-date',
);
expect(expirationDate).toBeInTheDocument();
expect(expirationDate).toHaveTextContent('04/14/2025');
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ import { useI18nContext } from '../../../../../hooks/useI18nContext';
import {
convertTimestampToReadableDate,
getPeriodFrequencyValueTranslationKey,
extractExpiryToReadableDate,
GatorPermissionRule,
convertAmountPerSecondToAmountPerPeriod,
getDecimalizedHexValue,
extractExpiryToReadableDate,
GatorPermissionRule,
} from '../../../../../../shared/lib/gator-permissions';
import { PreferredAvatar } from '../../../../app/preferred-avatar';
import { BackgroundColor } from '../../../../../helpers/constants/design-system';
Expand Down Expand Up @@ -104,6 +104,7 @@ export const ReviewGatorPermissionItem = ({
onRevokeClick,
}: ReviewGatorPermissionItemProps) => {
const t = useI18nContext();

const { permissionResponse, siteOrigin } = gatorPermission;
const { chainId } = permissionResponse;
const permissionType = permissionResponse.permission.type;
Expand Down Expand Up @@ -134,9 +135,6 @@ export const ReviewGatorPermissionItem = ({
name: foundTokenMetadata.name || 'Unknown Token',
};
}
console.warn(
`Token metadata not found for address: ${tokenAddress} for chain: ${chainId}`,
);
return {
symbol: 'Unknown Token',
decimals: null,
Expand Down Expand Up @@ -164,23 +162,21 @@ export const ReviewGatorPermissionItem = ({
};

/**
* Returns the expiration date from the rules
* Returns the expiration date from the permission rules
*
* @param rules - The rules to extract the expiration from
* @returns The expiration date
*/
const getExpirationDate = useCallback(
(rules: GatorPermissionRule[]): string => {
if (!rules) {
return t('gatorPermissionNoExpiration');
}
if (rules.length === 0) {
return t('gatorPermissionNoExpiration');
const getExpirationDate = useCallback((): string => {
if ('rules' in permissionResponse && permissionResponse.rules) {
const expiryDate = extractExpiryToReadableDate(
permissionResponse.rules as GatorPermissionRule[],
);
if (expiryDate) {
return expiryDate;
}
return extractExpiryToReadableDate(rules);
},
[t],
);
}
return t('gatorPermissionNoExpiration');
}, [permissionResponse, t]);

/**
* Returns the token stream permission details
Expand Down Expand Up @@ -242,12 +238,9 @@ export const ReviewGatorPermissionItem = ({
testId: 'review-gator-permission-start-date',
},

// TODO: Need to expose rules on StoredGatorPermissionSanitized in the gator-permissions-controller so we can have stronger typing
expirationDate: {
translationKey: 'gatorPermissionsExpirationDate',
value: getExpirationDate(
(permission as unknown as { rules: GatorPermissionRule[] }).rules,
),
value: getExpirationDate(),
testId: 'review-gator-permission-expiration-date',
},
streamRate: {
Expand Down Expand Up @@ -306,12 +299,9 @@ export const ReviewGatorPermissionItem = ({
testId: 'review-gator-permission-start-date',
},

// TODO: Need to expose rules on StoredGatorPermissionSanitized in the gator-permissions-controller so we can have stronger typing
expirationDate: {
translationKey: 'gatorPermissionsExpirationDate',
value: getExpirationDate(
(permission as unknown as { rules: GatorPermissionRule[] }).rules,
),
value: getExpirationDate(),
testId: 'review-gator-permission-expiration-date',
},
},
Expand Down
10 changes: 5 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6581,9 +6581,9 @@ __metadata:
languageName: node
linkType: hard

"@metamask/gator-permissions-controller@npm:^0.4.0":
version: 0.4.0
resolution: "@metamask/gator-permissions-controller@npm:0.4.0"
"@metamask/gator-permissions-controller@npm:^0.5.0":
version: 0.5.0
resolution: "@metamask/gator-permissions-controller@npm:0.5.0"
dependencies:
"@metamask/7715-permission-types": "npm:^0.3.0"
"@metamask/base-controller": "npm:^9.0.0"
Expand All @@ -6596,7 +6596,7 @@ __metadata:
peerDependencies:
"@metamask/snaps-controllers": ^14.0.1
"@metamask/transaction-controller": ^61.1.0
checksum: 10/7042081a938c20d0534e009c22e7db1bc476622008dee8658278f7b9888625be3bab9745bdff1d835fd0f7566a395e156c34703cb5809f57039e5d6a4df9213b
checksum: 10/0d3ae0688499923639dcf4aeb0a0165e37375b8df818bb2a311ba2262ae87e1f3751f34861675c293bf4ba6b9071c82401296cf891af0f5a1448b4a2086d555d
languageName: node
linkType: hard

Expand Down Expand Up @@ -32550,7 +32550,7 @@ __metadata:
"@metamask/forwarder": "npm:^1.1.0"
"@metamask/foundryup": "npm:^1.0.1"
"@metamask/gas-fee-controller": "npm:^25.0.0"
"@metamask/gator-permissions-controller": "npm:^0.4.0"
"@metamask/gator-permissions-controller": "npm:^0.5.0"
"@metamask/gator-permissions-snap": "npm:^0.7.0"
"@metamask/institutional-wallet-snap": "npm:1.3.4"
"@metamask/jazzicon": "patch:@metamask/jazzicon@npm%3A2.0.0#~/.yarn/patches/@metamask-jazzicon-npm-2.0.0-36957be38d.patch"
Expand Down
Loading