mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 09:57:02 +01:00
[FLASK] Implement Snaps UI Renderer (#16605)
* Start implementation of Snaps UI Renderer * Add snap name and fix some design issues * Fix lint * Add some types * More fixes * Actually install snaps-ui * Use JS instead of TS * Remove unused deps * Remove dep * Update LavaMoat policies * Fix style lint * Add story * Small tweaks after rebase * Remove spacer and add test * Fix lint * Remove console.log * Add error message * Remove edge-case that doesnt exist anymore * Update yarn.lock * Update policy
This commit is contained in:
parent
7e7be2769d
commit
c75d2dce55
3
app/_locales/en/messages.json
generated
3
app/_locales/en/messages.json
generated
@ -3409,6 +3409,9 @@
|
||||
"snapsToggle": {
|
||||
"message": "A snap will only run if it is enabled"
|
||||
},
|
||||
"snapsUIError": {
|
||||
"message": "The UI specified by the snap is invalid."
|
||||
},
|
||||
"someNetworksMayPoseSecurity": {
|
||||
"message": "Some networks may pose security and/or privacy risks. Understand the risks before adding & using a network."
|
||||
},
|
||||
|
@ -2435,7 +2435,7 @@
|
||||
"TextEncoder": true
|
||||
},
|
||||
"packages": {
|
||||
"@metamask/snaps-utils>superstruct": true,
|
||||
"@metamask/snaps-ui>superstruct": true,
|
||||
"browserify>buffer": true,
|
||||
"nock>debug": true
|
||||
}
|
||||
|
@ -1275,9 +1275,9 @@
|
||||
"@metamask/permission-controller": true,
|
||||
"@metamask/rpc-methods>@metamask/key-tree": true,
|
||||
"@metamask/rpc-methods>nanoid": true,
|
||||
"@metamask/snaps-ui>superstruct": true,
|
||||
"@metamask/snaps-utils": true,
|
||||
"@metamask/snaps-utils>@noble/hashes": true,
|
||||
"@metamask/snaps-utils>superstruct": true,
|
||||
"eth-block-tracker>@metamask/utils": true,
|
||||
"eth-rpc-errors": true
|
||||
}
|
||||
@ -1766,11 +1766,11 @@
|
||||
"URL": true
|
||||
},
|
||||
"packages": {
|
||||
"@metamask/snaps-ui>superstruct": true,
|
||||
"@metamask/snaps-utils>@noble/hashes": true,
|
||||
"@metamask/snaps-utils>@scure/base": true,
|
||||
"@metamask/snaps-utils>cron-parser": true,
|
||||
"@metamask/snaps-utils>rfdc": true,
|
||||
"@metamask/snaps-utils>superstruct": true,
|
||||
"@metamask/snaps-utils>validate-npm-package-name": true,
|
||||
"eth-block-tracker>@metamask/utils": true,
|
||||
"semver": true
|
||||
@ -2804,7 +2804,7 @@
|
||||
"TextEncoder": true
|
||||
},
|
||||
"packages": {
|
||||
"@metamask/snaps-utils>superstruct": true,
|
||||
"@metamask/snaps-ui>superstruct": true,
|
||||
"browserify>buffer": true,
|
||||
"nock>debug": true
|
||||
}
|
||||
|
@ -2435,7 +2435,7 @@
|
||||
"TextEncoder": true
|
||||
},
|
||||
"packages": {
|
||||
"@metamask/snaps-utils>superstruct": true,
|
||||
"@metamask/snaps-ui>superstruct": true,
|
||||
"browserify>buffer": true,
|
||||
"nock>debug": true
|
||||
}
|
||||
|
@ -226,6 +226,7 @@
|
||||
"@metamask/slip44": "^2.1.0",
|
||||
"@metamask/smart-transactions-controller": "^3.0.0",
|
||||
"@metamask/snaps-controllers": "^0.26.1",
|
||||
"@metamask/snaps-ui": "^0.26.1",
|
||||
"@metamask/snaps-utils": "^0.26.1",
|
||||
"@metamask/subject-metadata-controller": "^1.0.0",
|
||||
"@ngraveio/bc-ur": "^1.1.6",
|
||||
|
@ -38,6 +38,7 @@
|
||||
@import 'flask/snap-content-footer/index';
|
||||
@import 'flask/snap-install-warning/index';
|
||||
@import 'flask/snap-remove-warning/index';
|
||||
@import 'flask/snap-ui-renderer/index';
|
||||
@import 'flask/snap-delineator/index';
|
||||
@import 'flask/snap-settings-card/index';
|
||||
@import 'flask/update-snap-permission-list/index';
|
||||
|
1
ui/components/app/flask/snap-ui-renderer/index.js
Normal file
1
ui/components/app/flask/snap-ui-renderer/index.js
Normal file
@ -0,0 +1 @@
|
||||
export { SnapUIRenderer } from './snap-ui-renderer';
|
17
ui/components/app/flask/snap-ui-renderer/index.scss
Normal file
17
ui/components/app/flask/snap-ui-renderer/index.scss
Normal file
@ -0,0 +1,17 @@
|
||||
.snap-ui-renderer {
|
||||
&__error {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
&__spinner {
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
&__divider {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&__panel {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
104
ui/components/app/flask/snap-ui-renderer/snap-ui-renderer.js
Normal file
104
ui/components/app/flask/snap-ui-renderer/snap-ui-renderer.js
Normal file
@ -0,0 +1,104 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useSelector } from 'react-redux';
|
||||
import nanoid from 'nanoid';
|
||||
import { isComponent } from '@metamask/snaps-ui';
|
||||
import MetaMaskTemplateRenderer from '../../metamask-template-renderer/metamask-template-renderer';
|
||||
import {
|
||||
TYPOGRAPHY,
|
||||
FONT_WEIGHT,
|
||||
DISPLAY,
|
||||
FLEX_DIRECTION,
|
||||
} from '../../../../helpers/constants/design-system';
|
||||
import { SnapDelineator } from '../snap-delineator';
|
||||
import { useI18nContext } from '../../../../hooks/useI18nContext';
|
||||
import ActionableMessage from '../../../ui/actionable-message/actionable-message';
|
||||
import { getSnap } from '../../../../selectors';
|
||||
|
||||
export const UI_MAPPING = {
|
||||
panel: (props) => ({
|
||||
element: 'Box',
|
||||
// eslint-disable-next-line no-use-before-define
|
||||
children: props.children.map(mapToTemplate),
|
||||
props: {
|
||||
display: DISPLAY.FLEX,
|
||||
flexDirection: FLEX_DIRECTION.COLUMN,
|
||||
className: 'snap-ui-renderer__panel',
|
||||
},
|
||||
}),
|
||||
heading: (props) => ({
|
||||
element: 'Typography',
|
||||
children: props.value,
|
||||
props: {
|
||||
variant: TYPOGRAPHY.H3,
|
||||
fontWeight: FONT_WEIGHT.BOLD,
|
||||
},
|
||||
}),
|
||||
text: (props) => ({
|
||||
element: 'Typography',
|
||||
children: props.value,
|
||||
props: {
|
||||
variant: TYPOGRAPHY.H6,
|
||||
},
|
||||
}),
|
||||
spinner: () => ({
|
||||
element: 'Spinner',
|
||||
props: {
|
||||
className: 'snap-ui-renderer__spinner',
|
||||
},
|
||||
}),
|
||||
divider: () => ({
|
||||
element: 'hr',
|
||||
props: {
|
||||
className: 'snap-ui-renderer__divider',
|
||||
},
|
||||
}),
|
||||
copyable: (props) => ({
|
||||
element: 'Copyable',
|
||||
props: {
|
||||
text: props.value,
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
const mapToTemplate = (data) => {
|
||||
const { type } = data;
|
||||
const mapped = UI_MAPPING[type](data);
|
||||
// TODO: We may want to have deterministic keys at some point
|
||||
return { ...mapped, key: nanoid() };
|
||||
};
|
||||
|
||||
// Component that maps Snaps UI JSON format to MetaMask Template Renderer format
|
||||
export const SnapUIRenderer = ({ snapId, data }) => {
|
||||
const t = useI18nContext();
|
||||
const snap = useSelector((state) => getSnap(state, snapId));
|
||||
|
||||
const snapName = snap.manifest.proposedName;
|
||||
|
||||
if (!isComponent(data)) {
|
||||
return (
|
||||
<SnapDelineator snapName={snapName}>
|
||||
<ActionableMessage
|
||||
className="snap-ui-renderer__error"
|
||||
message={t('snapsUIError')}
|
||||
type="danger"
|
||||
useIcon
|
||||
iconFillColor="var(--color-error-default)"
|
||||
/>
|
||||
</SnapDelineator>
|
||||
);
|
||||
}
|
||||
|
||||
const sections = mapToTemplate(data);
|
||||
|
||||
return (
|
||||
<SnapDelineator snapName={snapName}>
|
||||
<MetaMaskTemplateRenderer sections={sections} />
|
||||
</SnapDelineator>
|
||||
);
|
||||
};
|
||||
|
||||
SnapUIRenderer.propTypes = {
|
||||
snapId: PropTypes.string,
|
||||
data: PropTypes.object,
|
||||
};
|
@ -0,0 +1,34 @@
|
||||
import React from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
import { object } from '@storybook/addon-knobs';
|
||||
import { panel, text, heading, divider, copyable } from '@metamask/snaps-ui';
|
||||
import configureStore from '../../../../store/store';
|
||||
import testData from '../../../../../.storybook/test-data';
|
||||
import { SnapUIRenderer } from '.';
|
||||
|
||||
const store = configureStore(testData);
|
||||
|
||||
export default {
|
||||
title: 'Components/App/SnapUIRenderer',
|
||||
id: __filename,
|
||||
decorators: [(story) => <Provider store={store}>{story()}</Provider>],
|
||||
};
|
||||
|
||||
const DATA = panel([
|
||||
heading('Foo bar'),
|
||||
text('Description'),
|
||||
divider(),
|
||||
text('More text'),
|
||||
copyable('Text you can copy'),
|
||||
]);
|
||||
|
||||
export const DefaultStory = () => (
|
||||
<SnapUIRenderer
|
||||
snapId="local:http://localhost:8080/"
|
||||
data={object('data', DATA)}
|
||||
/>
|
||||
);
|
||||
|
||||
export const ErrorStory = () => (
|
||||
<SnapUIRenderer snapId="local:http://localhost:8080/" data="foo" />
|
||||
);
|
@ -0,0 +1,9 @@
|
||||
import { NodeType } from '@metamask/snaps-ui';
|
||||
import { UI_MAPPING } from './snap-ui-renderer';
|
||||
|
||||
describe('Snap UI mapping', () => {
|
||||
it('supports all exposed components', () => {
|
||||
const nodes = Object.values(NodeType);
|
||||
expect(Object.keys(UI_MAPPING).sort()).toStrictEqual(nodes.sort());
|
||||
});
|
||||
});
|
@ -15,6 +15,7 @@ import Tooltip from '../../ui/tooltip/tooltip';
|
||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||
import { SnapDelineator } from '../flask/snap-delineator';
|
||||
import { Copyable } from '../flask/copyable';
|
||||
import Spinner from '../../ui/spinner';
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
export const safeComponentList = {
|
||||
@ -41,5 +42,7 @@ export const safeComponentList = {
|
||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||
SnapDelineator,
|
||||
Copyable,
|
||||
Spinner,
|
||||
hr: 'hr',
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
};
|
||||
|
11
yarn.lock
11
yarn.lock
@ -4371,6 +4371,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@metamask/snaps-ui@npm:^0.26.1":
|
||||
version: 0.26.1
|
||||
resolution: "@metamask/snaps-ui@npm:0.26.1"
|
||||
dependencies:
|
||||
"@metamask/utils": ^3.3.1
|
||||
superstruct: ^0.16.7
|
||||
checksum: 73dc68f02670ae075abf54740c4b3265741699b10cf2f9dc16a56393651d6595361feaa3f80cec4900884bd351e9177b0f1eb27e4511cdc7dc6b05be2e107210
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@metamask/snaps-utils@npm:^0.26.1":
|
||||
version: 0.26.1
|
||||
resolution: "@metamask/snaps-utils@npm:0.26.1"
|
||||
@ -23354,6 +23364,7 @@ __metadata:
|
||||
"@metamask/slip44": ^2.1.0
|
||||
"@metamask/smart-transactions-controller": ^3.0.0
|
||||
"@metamask/snaps-controllers": ^0.26.1
|
||||
"@metamask/snaps-ui": ^0.26.1
|
||||
"@metamask/snaps-utils": ^0.26.1
|
||||
"@metamask/subject-metadata-controller": ^1.0.0
|
||||
"@metamask/test-dapp": ^5.2.1
|
||||
|
Loading…
Reference in New Issue
Block a user