mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 01:47:00 +01:00
[FLASK] Expose transaction origin to transaction insight snaps (#16671)
* Expose transaction origin to transaction insight snaps * Support multiple icons for each label for a permission * Add transaction insight origin permission * Fix fencing * Fix import and permission crash * Use function properly for connected accounts
This commit is contained in:
parent
6416936eec
commit
025ee2cb48
4
app/_locales/en/messages.json
generated
4
app/_locales/en/messages.json
generated
@ -2763,6 +2763,10 @@
|
||||
"message": "Fetch and display transaction insights.",
|
||||
"description": "The description for the `endowment:transaction-insight` permission"
|
||||
},
|
||||
"permission_transactionInsightOrigin": {
|
||||
"message": "See the origins of websites that suggest transactions",
|
||||
"description": "The description for the `transactionOrigin` caveat, to be used with the `endowment:transaction-insight` permission"
|
||||
},
|
||||
"permission_unknown": {
|
||||
"message": "Unknown permission: $1",
|
||||
"description": "$1 is the name of a requested permission that is not recognized."
|
||||
|
@ -17,7 +17,7 @@ import SnapContentFooter from '../../flask/snap-content-footer/snap-content-foot
|
||||
import Box from '../../../ui/box/box';
|
||||
import ActionableMessage from '../../../ui/actionable-message/actionable-message';
|
||||
|
||||
export const SnapInsight = ({ transaction, chainId, selectedSnap }) => {
|
||||
export const SnapInsight = ({ transaction, origin, chainId, selectedSnap }) => {
|
||||
const t = useI18nContext();
|
||||
const {
|
||||
data: response,
|
||||
@ -26,6 +26,7 @@ export const SnapInsight = ({ transaction, chainId, selectedSnap }) => {
|
||||
} = useTransactionInsightSnap({
|
||||
transaction,
|
||||
chainId,
|
||||
origin,
|
||||
snapId: selectedSnap.id,
|
||||
});
|
||||
|
||||
@ -146,6 +147,10 @@ SnapInsight.propTypes = {
|
||||
* CAIP2 Chain ID
|
||||
*/
|
||||
chainId: PropTypes.string,
|
||||
/*
|
||||
* The origin of the transaction
|
||||
*/
|
||||
origin: PropTypes.string,
|
||||
/*
|
||||
* The insight snap selected
|
||||
*/
|
||||
|
@ -1,6 +1,7 @@
|
||||
import classnames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { useState } from 'react';
|
||||
import { flatten } from 'lodash';
|
||||
import CheckBox from '../../ui/check-box';
|
||||
import { useI18nContext } from '../../../hooks/useI18nContext';
|
||||
import { getPermissionDescription } from '../../../helpers/utils/permission';
|
||||
@ -17,6 +18,12 @@ const ConnectedAccountsPermissions = ({ permissions }) => {
|
||||
return null;
|
||||
}
|
||||
|
||||
const permissionLabels = flatten(
|
||||
permissions.map(({ key, value }) =>
|
||||
getPermissionDescription(t, key, value),
|
||||
),
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="connected-accounts-permissions">
|
||||
<p
|
||||
@ -43,20 +50,18 @@ const ConnectedAccountsPermissions = ({ permissions }) => {
|
||||
>
|
||||
<p>{t('authorizedPermissions')}:</p>
|
||||
<ul className="connected-accounts-permissions__list">
|
||||
{permissions.map(({ key: permissionName }) => (
|
||||
{permissionLabels.map(({ label }, idx) => (
|
||||
<li
|
||||
key={permissionName}
|
||||
key={`connected-permission-${idx}`}
|
||||
className="connected-accounts-permissions__list-item"
|
||||
>
|
||||
<CheckBox
|
||||
checked
|
||||
disabled
|
||||
id={permissionName}
|
||||
id={`connected-permission-${idx}`}
|
||||
className="connected-accounts-permissions__checkbox"
|
||||
/>
|
||||
<label htmlFor={permissionName}>
|
||||
{getPermissionDescription(t, permissionName).label}
|
||||
</label>
|
||||
<label htmlFor={`connected-permission-${idx}`}>{label}</label>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
@ -16,14 +16,14 @@ export default function UpdateSnapPermissionList({
|
||||
const ApprovedPermissions = () => {
|
||||
return Object.entries(approvedPermissions).map(
|
||||
([permissionName, permissionValue]) => {
|
||||
const { label, rightIcon } = getPermissionDescription(
|
||||
const permissions = getPermissionDescription(
|
||||
t,
|
||||
permissionName,
|
||||
permissionValue,
|
||||
);
|
||||
const { date } = permissionValue;
|
||||
const formattedDate = formatDate(date, 'yyyy-MM-dd');
|
||||
return (
|
||||
return permissions.map(({ label, rightIcon }) => (
|
||||
<div className="approved-permission" key={permissionName}>
|
||||
<i className="fas fa-check" />
|
||||
<div className="permission-description">
|
||||
@ -38,7 +38,7 @@ export default function UpdateSnapPermissionList({
|
||||
</div>
|
||||
{rightIcon && <i className={rightIcon} />}
|
||||
</div>
|
||||
);
|
||||
));
|
||||
},
|
||||
);
|
||||
};
|
||||
@ -46,12 +46,12 @@ export default function UpdateSnapPermissionList({
|
||||
const RevokedPermissions = () => {
|
||||
return Object.entries(revokedPermissions).map(
|
||||
([permissionName, permissionValue]) => {
|
||||
const { label, rightIcon } = getPermissionDescription(
|
||||
const permissions = getPermissionDescription(
|
||||
t,
|
||||
permissionName,
|
||||
permissionValue,
|
||||
);
|
||||
return (
|
||||
return permissions.map(({ label, rightIcon }) => (
|
||||
<div className="revoked-permission" key={permissionName}>
|
||||
<i className="fas fa-x" />
|
||||
<div className="permission-description">
|
||||
@ -66,7 +66,7 @@ export default function UpdateSnapPermissionList({
|
||||
</div>
|
||||
{rightIcon && <i className={rightIcon} />}
|
||||
</div>
|
||||
);
|
||||
));
|
||||
},
|
||||
);
|
||||
};
|
||||
@ -74,12 +74,12 @@ export default function UpdateSnapPermissionList({
|
||||
const NewPermissions = () => {
|
||||
return Object.entries(newPermissions).map(
|
||||
([permissionName, permissionValue]) => {
|
||||
const { label, rightIcon } = getPermissionDescription(
|
||||
const permissions = getPermissionDescription(
|
||||
t,
|
||||
permissionName,
|
||||
permissionValue,
|
||||
);
|
||||
return (
|
||||
return permissions.map(({ label, rightIcon }) => (
|
||||
<div className="new-permission" key={permissionName}>
|
||||
<i className="fas fa-arrow-right" />
|
||||
<div className="permission-description">
|
||||
@ -94,7 +94,7 @@ export default function UpdateSnapPermissionList({
|
||||
</div>
|
||||
{rightIcon && <i className={rightIcon} />}
|
||||
</div>
|
||||
);
|
||||
));
|
||||
},
|
||||
);
|
||||
};
|
||||
|
@ -12,29 +12,19 @@ import { useI18nContext } from '../../../hooks/useI18nContext';
|
||||
* @returns {JSX.Element[]} An array of permission description nodes.
|
||||
*/
|
||||
function getDescriptionNodes(t, permissionName, permissionValue) {
|
||||
const { label, leftIcon, rightIcon } = getPermissionDescription(
|
||||
const permissions = getPermissionDescription(
|
||||
t,
|
||||
permissionName,
|
||||
permissionValue,
|
||||
);
|
||||
|
||||
if (Array.isArray(label)) {
|
||||
return label.map((labelValue, index) => (
|
||||
<div className="permission" key={`${permissionName}-${index}`}>
|
||||
<i className={leftIcon} />
|
||||
{labelValue}
|
||||
{rightIcon && <i className={rightIcon} />}
|
||||
</div>
|
||||
));
|
||||
}
|
||||
|
||||
return [
|
||||
<div className="permission" key={permissionName}>
|
||||
return permissions.map(({ label, leftIcon, rightIcon }, index) => (
|
||||
<div className="permission" key={`${permissionName}-${index}`}>
|
||||
<i className={leftIcon} />
|
||||
{label}
|
||||
{rightIcon && <i className={rightIcon} />}
|
||||
</div>,
|
||||
];
|
||||
</div>
|
||||
));
|
||||
}
|
||||
|
||||
export default function PermissionsConnectPermissionList({ permissions }) {
|
||||
|
@ -2,6 +2,8 @@ import deepFreeze from 'deep-freeze-strict';
|
||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||
import React from 'react';
|
||||
import { getRpcCaveatOrigins } from '@metamask/snaps-controllers/dist/snaps/endowments/rpc';
|
||||
import { SnapCaveatType } from '@metamask/snaps-utils';
|
||||
import { isNonEmptyArray } from '@metamask/controller-utils';
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
import {
|
||||
RestrictedMethods,
|
||||
@ -17,132 +19,140 @@ import { coinTypeToProtocolName } from './util';
|
||||
const UNKNOWN_PERMISSION = Symbol('unknown');
|
||||
|
||||
const PERMISSION_DESCRIPTIONS = deepFreeze({
|
||||
[RestrictedMethods.eth_accounts]: {
|
||||
label: (t) => t('permission_ethereumAccounts'),
|
||||
[RestrictedMethods.eth_accounts]: (t) => ({
|
||||
label: t('permission_ethereumAccounts'),
|
||||
leftIcon: 'fas fa-eye',
|
||||
rightIcon: null,
|
||||
},
|
||||
}),
|
||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||
[RestrictedMethods.snap_confirm]: {
|
||||
label: (t) => t('permission_customConfirmation'),
|
||||
[RestrictedMethods.snap_confirm]: (t) => ({
|
||||
label: t('permission_customConfirmation'),
|
||||
leftIcon: 'fas fa-user-check',
|
||||
rightIcon: null,
|
||||
},
|
||||
[RestrictedMethods.snap_notify]: {
|
||||
}),
|
||||
[RestrictedMethods.snap_notify]: (t) => ({
|
||||
leftIcon: 'fas fa-bell',
|
||||
label: (t) => t('permission_notifications'),
|
||||
label: t('permission_notifications'),
|
||||
rightIcon: null,
|
||||
},
|
||||
[RestrictedMethods.snap_getBip32PublicKey]: {
|
||||
label: (t, _, permissionValue) => {
|
||||
return permissionValue.caveats[0].value.map(({ path, curve }) =>
|
||||
t('permission_viewBip32PublicKeys', [
|
||||
<span className="permission-label-item" key={path.join('/')}>
|
||||
{path.join('/')}
|
||||
</span>,
|
||||
curve,
|
||||
]),
|
||||
);
|
||||
},
|
||||
leftIcon: 'fas fa-eye',
|
||||
rightIcon: null,
|
||||
},
|
||||
[RestrictedMethods.snap_getBip32Entropy]: {
|
||||
label: (t, _, permissionValue) => {
|
||||
return permissionValue.caveats[0].value.map(({ path, curve }) =>
|
||||
t('permission_manageBip32Keys', [
|
||||
<span className="permission-label-item" key={path.join('/')}>
|
||||
{path.join('/')}
|
||||
</span>,
|
||||
curve,
|
||||
]),
|
||||
);
|
||||
},
|
||||
leftIcon: 'fas fa-door-open',
|
||||
rightIcon: null,
|
||||
},
|
||||
[RestrictedMethods.snap_getBip44Entropy]: {
|
||||
label: (t, _, permissionValue) => {
|
||||
return permissionValue.caveats[0].value.map(({ coinType }) =>
|
||||
t('permission_manageBip44Keys', [
|
||||
<span className="permission-label-item" key={`coin-type-${coinType}`}>
|
||||
{coinTypeToProtocolName(coinType) ||
|
||||
`${coinType} (Unrecognized protocol)`}
|
||||
</span>,
|
||||
]),
|
||||
);
|
||||
},
|
||||
leftIcon: 'fas fa-door-open',
|
||||
rightIcon: null,
|
||||
},
|
||||
[RestrictedMethods.snap_getEntropy]: {
|
||||
label: (t) => t('permission_getEntropy'),
|
||||
}),
|
||||
[RestrictedMethods.snap_getBip32PublicKey]: (t, _, permissionValue) =>
|
||||
permissionValue.caveats[0].value.map(({ path, curve }) => ({
|
||||
label: t('permission_viewBip32PublicKeys', [
|
||||
<span className="permission-label-item" key={path.join('/')}>
|
||||
{path.join('/')}
|
||||
</span>,
|
||||
curve,
|
||||
]),
|
||||
leftIcon: 'fas fa-eye',
|
||||
rightIcon: null,
|
||||
})),
|
||||
[RestrictedMethods.snap_getBip32Entropy]: (t, _, permissionValue) =>
|
||||
permissionValue.caveats[0].value.map(({ path, curve }) => ({
|
||||
label: t('permission_manageBip32Keys', [
|
||||
<span className="permission-label-item" key={path.join('/')}>
|
||||
{path.join('/')}
|
||||
</span>,
|
||||
curve,
|
||||
]),
|
||||
leftIcon: 'fas fa-door-open',
|
||||
rightIcon: null,
|
||||
})),
|
||||
[RestrictedMethods.snap_getBip44Entropy]: (t, _, permissionValue) =>
|
||||
permissionValue.caveats[0].value.map(({ coinType }) => ({
|
||||
label: t('permission_manageBip44Keys', [
|
||||
<span className="permission-label-item" key={`coin-type-${coinType}`}>
|
||||
{coinTypeToProtocolName(coinType) ||
|
||||
`${coinType} (Unrecognized protocol)`}
|
||||
</span>,
|
||||
]),
|
||||
leftIcon: 'fas fa-door-open',
|
||||
rightIcon: null,
|
||||
})),
|
||||
[RestrictedMethods.snap_getEntropy]: (t) => ({
|
||||
label: t('permission_getEntropy'),
|
||||
leftIcon: 'fas fa-key',
|
||||
rightIcon: null,
|
||||
},
|
||||
[RestrictedMethods.snap_manageState]: {
|
||||
label: (t) => t('permission_manageState'),
|
||||
}),
|
||||
[RestrictedMethods.snap_manageState]: (t) => ({
|
||||
label: t('permission_manageState'),
|
||||
leftIcon: 'fas fa-download',
|
||||
rightIcon: null,
|
||||
},
|
||||
[RestrictedMethods['wallet_snap_*']]: {
|
||||
label: (t, permissionName) => {
|
||||
const snapId = permissionName.split('_').slice(-1);
|
||||
return t('permission_accessSnap', [snapId]);
|
||||
},
|
||||
}),
|
||||
[RestrictedMethods['wallet_snap_*']]: (t, permissionName) => ({
|
||||
label: t('permission_accessSnap', [permissionName.split('_').slice(-1)]),
|
||||
leftIcon: 'fas fa-bolt',
|
||||
rightIcon: null,
|
||||
},
|
||||
[EndowmentPermissions['endowment:network-access']]: {
|
||||
label: (t) => t('permission_accessNetwork'),
|
||||
}),
|
||||
[EndowmentPermissions['endowment:network-access']]: (t) => ({
|
||||
label: t('permission_accessNetwork'),
|
||||
leftIcon: 'fas fa-wifi',
|
||||
rightIcon: null,
|
||||
},
|
||||
[EndowmentPermissions['endowment:long-running']]: {
|
||||
label: (t) => t('permission_longRunning'),
|
||||
}),
|
||||
[EndowmentPermissions['endowment:long-running']]: (t) => ({
|
||||
label: t('permission_longRunning'),
|
||||
leftIcon: 'fas fa-infinity',
|
||||
rightIcon: null,
|
||||
}),
|
||||
[EndowmentPermissions['endowment:transaction-insight']]: (
|
||||
t,
|
||||
_,
|
||||
permissionValue,
|
||||
) => {
|
||||
const result = [
|
||||
{
|
||||
label: t('permission_transactionInsight'),
|
||||
leftIcon: 'fas fa-info',
|
||||
rightIcon: null,
|
||||
},
|
||||
];
|
||||
|
||||
if (
|
||||
isNonEmptyArray(permissionValue.caveats) &&
|
||||
permissionValue.caveats[0].type === SnapCaveatType.TransactionOrigin &&
|
||||
permissionValue.caveats[0].value
|
||||
) {
|
||||
result.push({
|
||||
label: t('permission_transactionInsightOrigin'),
|
||||
leftIcon: 'fas fa-compass',
|
||||
rightIcon: null,
|
||||
});
|
||||
}
|
||||
return result;
|
||||
},
|
||||
[EndowmentPermissions['endowment:transaction-insight']]: {
|
||||
label: (t) => t('permission_transactionInsight'),
|
||||
leftIcon: 'fas fa-info',
|
||||
rightIcon: null,
|
||||
},
|
||||
[EndowmentPermissions['endowment:cronjob']]: {
|
||||
label: (t) => t('permission_cronjob'),
|
||||
[EndowmentPermissions['endowment:cronjob']]: (t) => ({
|
||||
label: t('permission_cronjob'),
|
||||
leftIcon: 'fas fa-clock',
|
||||
rightIcon: null,
|
||||
},
|
||||
[EndowmentPermissions['endowment:ethereum-provider']]: {
|
||||
label: (t) => t('permission_ethereumProvider'),
|
||||
}),
|
||||
[EndowmentPermissions['endowment:ethereum-provider']]: (t) => ({
|
||||
label: t('permission_ethereumProvider'),
|
||||
leftIcon: 'fab fa-ethereum',
|
||||
rightIcon: null,
|
||||
},
|
||||
[EndowmentPermissions['endowment:rpc']]: {
|
||||
label: (t, _, permissionValue) => {
|
||||
const { snaps, dapps } = getRpcCaveatOrigins(permissionValue);
|
||||
}),
|
||||
[EndowmentPermissions['endowment:rpc']]: (t, _, permissionValue) => {
|
||||
const { snaps, dapps } = getRpcCaveatOrigins(permissionValue);
|
||||
|
||||
const messages = [];
|
||||
if (snaps) {
|
||||
messages.push(t('permission_rpc', [t('otherSnaps')]));
|
||||
}
|
||||
const labels = [];
|
||||
if (snaps) {
|
||||
labels.push(t('permission_rpc', [t('otherSnaps')]));
|
||||
}
|
||||
|
||||
if (dapps) {
|
||||
messages.push(t('permission_rpc', [t('websites')]));
|
||||
}
|
||||
if (dapps) {
|
||||
labels.push(t('permission_rpc', [t('websites')]));
|
||||
}
|
||||
|
||||
return messages;
|
||||
},
|
||||
leftIcon: 'fas fa-plug',
|
||||
rightIcon: null,
|
||||
return labels.map((label) => ({
|
||||
label,
|
||||
leftIcon: 'fas fa-plug',
|
||||
rightIcon: null,
|
||||
}));
|
||||
},
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
[UNKNOWN_PERMISSION]: {
|
||||
label: (t, permissionName) =>
|
||||
t('permission_unknown', [permissionName ?? 'undefined']),
|
||||
[UNKNOWN_PERMISSION]: (t, permissionName) => ({
|
||||
label: t('permission_unknown', [permissionName ?? 'undefined']),
|
||||
leftIcon: 'fas fa-times-circle',
|
||||
rightIcon: null,
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
/**
|
||||
@ -156,7 +166,7 @@ const PERMISSION_DESCRIPTIONS = deepFreeze({
|
||||
* @param {Function} t - The translation function
|
||||
* @param {string} permissionName - The name of the permission to request
|
||||
* @param {object} permissionValue - The value of the permission to request
|
||||
* @returns {(permissionName:string) => PermissionLabelObject}
|
||||
* @returns {PermissionLabelObject[]}
|
||||
*/
|
||||
export const getPermissionDescription = (
|
||||
t,
|
||||
@ -176,5 +186,9 @@ export const getPermissionDescription = (
|
||||
}
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
return { ...value, label: value.label(t, permissionName, permissionValue) };
|
||||
const result = value(t, permissionName, permissionValue);
|
||||
if (!Array.isArray(result)) {
|
||||
return [result];
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
@ -1,18 +1,28 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { getTransactionOriginCaveat } from '@metamask/snaps-controllers';
|
||||
import { handleSnapRequest } from '../../store/actions';
|
||||
import { getPermissionSubjects } from '../../selectors';
|
||||
|
||||
const INSIGHT_PERMISSION = 'endowment:transaction-insight';
|
||||
|
||||
export function useTransactionInsightSnap({ transaction, chainId, snapId }) {
|
||||
export function useTransactionInsightSnap({
|
||||
transaction,
|
||||
chainId,
|
||||
origin,
|
||||
snapId,
|
||||
}) {
|
||||
const subjects = useSelector(getPermissionSubjects);
|
||||
if (!subjects[snapId]?.permissions[INSIGHT_PERMISSION]) {
|
||||
const permission = subjects[snapId]?.permissions[INSIGHT_PERMISSION];
|
||||
if (!permission) {
|
||||
throw new Error(
|
||||
'This snap does not have the transaction insight endowment.',
|
||||
);
|
||||
}
|
||||
|
||||
const hasTransactionOriginCaveat = getTransactionOriginCaveat(permission);
|
||||
const transactionOrigin = hasTransactionOriginCaveat ? origin : null;
|
||||
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [data, setData] = useState(undefined);
|
||||
const [error, setError] = useState(undefined);
|
||||
@ -30,7 +40,7 @@ export function useTransactionInsightSnap({ transaction, chainId, snapId }) {
|
||||
request: {
|
||||
jsonrpc: '2.0',
|
||||
method: ' ',
|
||||
params: { transaction, chainId },
|
||||
params: { transaction, chainId, transactionOrigin },
|
||||
},
|
||||
});
|
||||
setData(d);
|
||||
@ -43,7 +53,7 @@ export function useTransactionInsightSnap({ transaction, chainId, snapId }) {
|
||||
if (transaction) {
|
||||
fetchInsight();
|
||||
}
|
||||
}, [snapId, transaction, chainId]);
|
||||
}, [snapId, transaction, chainId, transactionOrigin]);
|
||||
|
||||
return { data, error, loading };
|
||||
}
|
||||
|
@ -755,7 +755,7 @@ export default class ConfirmTransactionBase extends Component {
|
||||
renderInsight() {
|
||||
const { txData, insightSnaps } = this.props;
|
||||
const { selectedInsightSnapId } = this.state;
|
||||
const { txParams, chainId } = txData;
|
||||
const { txParams, chainId, origin } = txData;
|
||||
|
||||
const selectedSnap = insightSnaps.find(
|
||||
({ id }) => id === selectedInsightSnapId,
|
||||
@ -791,6 +791,7 @@ export default class ConfirmTransactionBase extends Component {
|
||||
>
|
||||
<SnapInsight
|
||||
transaction={txParams}
|
||||
origin={origin}
|
||||
chainId={caip2ChainId}
|
||||
selectedSnap={selectedSnap}
|
||||
/>
|
||||
@ -802,6 +803,7 @@ export default class ConfirmTransactionBase extends Component {
|
||||
>
|
||||
<SnapInsight
|
||||
transaction={txParams}
|
||||
origin={origin}
|
||||
chainId={caip2ChainId}
|
||||
selectedSnap={selectedSnap}
|
||||
/>
|
||||
|
@ -242,13 +242,13 @@ export function getPermissionsForActiveTab(state) {
|
||||
const { activeTab, metamask } = state;
|
||||
const { subjects = {} } = metamask;
|
||||
|
||||
return Object.keys(subjects[activeTab.origin]?.permissions || {}).map(
|
||||
(parentCapability) => {
|
||||
return {
|
||||
key: parentCapability,
|
||||
};
|
||||
},
|
||||
);
|
||||
const permissions = subjects[activeTab.origin]?.permissions ?? {};
|
||||
return Object.keys(permissions).map((parentCapability) => {
|
||||
return {
|
||||
key: parentCapability,
|
||||
value: permissions[parentCapability],
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export function activeTabHasPermissions(state) {
|
||||
|
@ -425,10 +425,25 @@ describe('selectors', () => {
|
||||
},
|
||||
};
|
||||
|
||||
it('should return a list of permissions strings', () => {
|
||||
it('should return a list of permissions keys and values', () => {
|
||||
expect(getPermissionsForActiveTab(mockState)).toStrictEqual([
|
||||
{
|
||||
key: 'eth_accounts',
|
||||
value: {
|
||||
caveats: [
|
||||
{
|
||||
type: 'restrictReturnedAccounts',
|
||||
value: [
|
||||
'0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5',
|
||||
'0x7250739de134d33ec7ab1ee592711e15098c9d2d',
|
||||
],
|
||||
},
|
||||
],
|
||||
date: 1586359844177,
|
||||
id: '3aa65a8b-3bcb-4944-941b-1baa5fe0ed8b',
|
||||
invoker: 'https://remix.ethereum.org',
|
||||
parentCapability: 'eth_accounts',
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user