From f114c12321af4eb28bea916e7fab7995f45e270a Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Wed, 15 Nov 2023 13:41:58 +0100 Subject: [PATCH 01/12] Add row and address component --- .../transaction-insights/src/index.ts | 20 +++++++- .../snaps-sdk/src/ui/components/address.ts | 19 +++++++ packages/snaps-sdk/src/ui/components/index.ts | 2 + packages/snaps-sdk/src/ui/components/panel.ts | 4 ++ packages/snaps-sdk/src/ui/components/row.ts | 50 +++++++++++++++++++ packages/snaps-sdk/src/ui/nodes.ts | 2 + 6 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 packages/snaps-sdk/src/ui/components/address.ts create mode 100644 packages/snaps-sdk/src/ui/components/row.ts diff --git a/packages/examples/packages/transaction-insights/src/index.ts b/packages/examples/packages/transaction-insights/src/index.ts index e180730e4e..64cfebd720 100644 --- a/packages/examples/packages/transaction-insights/src/index.ts +++ b/packages/examples/packages/transaction-insights/src/index.ts @@ -1,5 +1,12 @@ import type { OnTransactionHandler } from '@metamask/snaps-sdk'; -import { SeverityLevel, panel, text } from '@metamask/snaps-sdk'; +import { + SeverityLevel, + panel, + text, + row, + address, + doubleValue, +} from '@metamask/snaps-sdk'; import { hasProperty } from '@metamask/utils'; import { decodeData } from './utils'; @@ -30,7 +37,16 @@ export const onTransaction: OnTransactionHandler = async ({ transaction }) => { ) { const type = decodeData(transaction.data); return { - content: panel([text('**Transaction type:**'), text(type)]), + content: panel([ + row('From Address', address(transaction.from)), + row( + 'To Address', + transaction.to ? address(transaction.to) : text('None'), + ), + row('Transaction type', text(type)), + row('Value', doubleValue(text('foo'), text('bar'))), + text('Old text'), + ]), severity: SeverityLevel.Critical, }; } diff --git a/packages/snaps-sdk/src/ui/components/address.ts b/packages/snaps-sdk/src/ui/components/address.ts new file mode 100644 index 0000000000..94d9562d45 --- /dev/null +++ b/packages/snaps-sdk/src/ui/components/address.ts @@ -0,0 +1,19 @@ +import type { Infer } from 'superstruct'; +import { assign, literal, object, string } from 'superstruct'; + +import { createBuilder } from '../builder'; +import { LiteralStruct, NodeType } from '../nodes'; + +export const AddressStruct = assign( + LiteralStruct, + object({ + type: literal(NodeType.Address), + value: string(), + }), +); + +export type Address = Infer; + +export const address = createBuilder(NodeType.Address, AddressStruct, [ + 'value', +]); diff --git a/packages/snaps-sdk/src/ui/components/index.ts b/packages/snaps-sdk/src/ui/components/index.ts index 1901918024..fa1e8820dc 100644 --- a/packages/snaps-sdk/src/ui/components/index.ts +++ b/packages/snaps-sdk/src/ui/components/index.ts @@ -1,3 +1,4 @@ +export * from './address'; export * from './copyable'; export * from './divider'; export * from './heading'; @@ -7,3 +8,4 @@ export type { Component, Panel } from './panel'; export { ComponentStruct, panel, PanelStruct } from './panel'; export * from './spinner'; export * from './text'; +export * from './row'; diff --git a/packages/snaps-sdk/src/ui/components/panel.ts b/packages/snaps-sdk/src/ui/components/panel.ts index 0542971554..c7e9d5e43c 100644 --- a/packages/snaps-sdk/src/ui/components/panel.ts +++ b/packages/snaps-sdk/src/ui/components/panel.ts @@ -3,10 +3,12 @@ import { array, assign, lazy, literal, object, union } from 'superstruct'; import { createBuilder } from '../builder'; import { NodeStruct, NodeType } from '../nodes'; +import { AddressStruct } from './address'; import { CopyableStruct } from './copyable'; import { DividerStruct } from './divider'; import { HeadingStruct } from './heading'; import { ImageStruct } from './image'; +import { RowStruct } from './row'; import { SpinnerStruct } from './spinner'; import { TextStruct } from './text'; @@ -87,6 +89,8 @@ export const ComponentStruct = union([ PanelStruct, SpinnerStruct, TextStruct, + RowStruct, + AddressStruct, ]); /** diff --git a/packages/snaps-sdk/src/ui/components/row.ts b/packages/snaps-sdk/src/ui/components/row.ts new file mode 100644 index 0000000000..16a016e860 --- /dev/null +++ b/packages/snaps-sdk/src/ui/components/row.ts @@ -0,0 +1,50 @@ +import type { Infer } from 'superstruct'; +import { + assign, + literal, + object, + lazy, + string, + optional, + enums, + union, +} from 'superstruct'; + +import { createBuilder } from '../builder'; +import { LiteralStruct, NodeType } from '../nodes'; +import { AddressStruct } from './address'; +import { DoubleValueStruct } from './doubleValue'; +import { ImageStruct } from './image'; +import { TextStruct } from './text'; + +export enum RowVariant { + Default = 'default', + Critical = 'critical', + Warning = 'warning', +} + +export const RowComponentStruct = union([ + ImageStruct, + TextStruct, + AddressStruct, + DoubleValueStruct, +]); + +export const RowStruct = assign( + LiteralStruct, + object({ + type: literal(NodeType.Row), + // TODO: Use enumValue() or similar if needed? + variant: optional(enums(Object.values(RowVariant))), + label: string(), + value: lazy(() => RowComponentStruct), + }), +); + +export type Row = Infer; + +export const row = createBuilder(NodeType.Row, RowStruct, [ + 'label', + 'value', + 'variant', +]); diff --git a/packages/snaps-sdk/src/ui/nodes.ts b/packages/snaps-sdk/src/ui/nodes.ts index da62b79855..dc7a4557b3 100644 --- a/packages/snaps-sdk/src/ui/nodes.ts +++ b/packages/snaps-sdk/src/ui/nodes.ts @@ -15,6 +15,8 @@ export enum NodeType { // eslint-disable-next-line @typescript-eslint/no-shadow Text = 'text', Image = 'image', + Row = 'row', + Address = 'address', } /** From 4b0fee122b5cddfad15a73f017644e001526a878 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Wed, 15 Nov 2023 14:08:43 +0100 Subject: [PATCH 02/12] Add tests --- .../transaction-insights/src/index.ts | 10 +-- .../src/ui/components/address.test.ts | 35 +++++++++ .../snaps-sdk/src/ui/components/address.ts | 4 +- .../snaps-sdk/src/ui/components/row.test.ts | 77 +++++++++++++++++++ packages/snaps-sdk/src/ui/components/row.ts | 3 +- 5 files changed, 116 insertions(+), 13 deletions(-) create mode 100644 packages/snaps-sdk/src/ui/components/address.test.ts create mode 100644 packages/snaps-sdk/src/ui/components/row.test.ts diff --git a/packages/examples/packages/transaction-insights/src/index.ts b/packages/examples/packages/transaction-insights/src/index.ts index 64cfebd720..c215ce9b04 100644 --- a/packages/examples/packages/transaction-insights/src/index.ts +++ b/packages/examples/packages/transaction-insights/src/index.ts @@ -1,12 +1,5 @@ import type { OnTransactionHandler } from '@metamask/snaps-sdk'; -import { - SeverityLevel, - panel, - text, - row, - address, - doubleValue, -} from '@metamask/snaps-sdk'; +import { SeverityLevel, panel, text, row, address } from '@metamask/snaps-sdk'; import { hasProperty } from '@metamask/utils'; import { decodeData } from './utils'; @@ -44,7 +37,6 @@ export const onTransaction: OnTransactionHandler = async ({ transaction }) => { transaction.to ? address(transaction.to) : text('None'), ), row('Transaction type', text(type)), - row('Value', doubleValue(text('foo'), text('bar'))), text('Old text'), ]), severity: SeverityLevel.Critical, diff --git a/packages/snaps-sdk/src/ui/components/address.test.ts b/packages/snaps-sdk/src/ui/components/address.test.ts new file mode 100644 index 0000000000..4c3d71ab25 --- /dev/null +++ b/packages/snaps-sdk/src/ui/components/address.test.ts @@ -0,0 +1,35 @@ +import { NodeType } from '../nodes'; +import { address } from './address'; + +describe('address', () => { + const MOCK_ADDRESS = '0x4bbeEB066eD09B7AEd07bF39EEe0460DFa261520'; + it('creates an address component', () => { + expect(address({ value: MOCK_ADDRESS })).toStrictEqual({ + type: NodeType.Address, + value: MOCK_ADDRESS, + }); + }); + + it('creates a copyable component using the shorthand form', () => { + expect(address(MOCK_ADDRESS)).toStrictEqual({ + type: NodeType.Address, + value: MOCK_ADDRESS, + }); + }); + + it('validates the args', () => { + expect(() => address({ value: 'foo' })).toThrow( + 'Invalid address component: At path: value -- Expected a string matching `/(0x[a-fA-F0-9]{40})/` but received "foo"', + ); + + // @ts-expect-error - Invalid args. + expect(() => address({ value: MOCK_ADDRESS, bar: 'baz' })).toThrow( + 'Invalid address component: At path: bar -- Expected a value of type `never`, but received: `"baz"`.', + ); + + // @ts-expect-error - Invalid args. + expect(() => address({})).toThrow( + 'Invalid address component: At path: value -- Expected a string, but received: undefined.', + ); + }); +}); diff --git a/packages/snaps-sdk/src/ui/components/address.ts b/packages/snaps-sdk/src/ui/components/address.ts index 94d9562d45..02ed966aba 100644 --- a/packages/snaps-sdk/src/ui/components/address.ts +++ b/packages/snaps-sdk/src/ui/components/address.ts @@ -1,5 +1,5 @@ import type { Infer } from 'superstruct'; -import { assign, literal, object, string } from 'superstruct'; +import { assign, literal, object, pattern, string } from 'superstruct'; import { createBuilder } from '../builder'; import { LiteralStruct, NodeType } from '../nodes'; @@ -8,7 +8,7 @@ export const AddressStruct = assign( LiteralStruct, object({ type: literal(NodeType.Address), - value: string(), + value: pattern(string(), /(0x[a-fA-F0-9]{40})/gu), }), ); diff --git a/packages/snaps-sdk/src/ui/components/row.test.ts b/packages/snaps-sdk/src/ui/components/row.test.ts new file mode 100644 index 0000000000..ac928c805b --- /dev/null +++ b/packages/snaps-sdk/src/ui/components/row.test.ts @@ -0,0 +1,77 @@ +import { NodeType } from '../nodes'; +import { RowVariant, row } from './row'; +import { text } from './text'; + +describe('row', () => { + it('creates a row component', () => { + expect(row({ label: 'Label', value: text('Hello, world!') })).toStrictEqual( + { + type: NodeType.Row, + label: 'Label', + value: text('Hello, world!'), + }, + ); + + expect( + row({ + label: 'Label', + value: text('Hello, world!'), + variant: RowVariant.Critical, + }), + ).toStrictEqual({ + type: NodeType.Row, + label: 'Label', + value: text('Hello, world!'), + variant: RowVariant.Critical, + }); + + expect( + row({ + label: 'Label', + value: text('Hello, world!'), + variant: 'critical', + }), + ).toStrictEqual({ + type: NodeType.Row, + label: 'Label', + value: text('Hello, world!'), + variant: RowVariant.Critical, + }); + }); + + it('creates a row component using the shorthand form', () => { + expect(row('Label', text('Hello, world!'))).toStrictEqual({ + type: NodeType.Row, + label: 'Label', + value: text('Hello, world!'), + }); + + expect( + row('Label', text('Hello, world!'), RowVariant.Critical), + ).toStrictEqual({ + type: NodeType.Row, + label: 'Label', + value: text('Hello, world!'), + variant: RowVariant.Critical, + }); + + expect(row('Label', text('Hello, world!'), 'critical')).toStrictEqual({ + type: NodeType.Row, + label: 'Label', + value: text('Hello, world!'), + variant: RowVariant.Critical, + }); + }); + + it('validates the args', () => { + // @ts-expect-error - Invalid args. + expect(() => row({ label: 'bar', value: text('foo'), bar: 'baz' })).toThrow( + 'Invalid row component: At path: bar -- Expected a value of type `never`, but received: `"baz"`.', + ); + + // @ts-expect-error - Invalid args. + expect(() => row({})).toThrow( + 'Invalid row component: At path: value -- Expected the value to satisfy a union of `object | object | object`, but received: undefined.', + ); + }); +}); diff --git a/packages/snaps-sdk/src/ui/components/row.ts b/packages/snaps-sdk/src/ui/components/row.ts index 16a016e860..73aa90599a 100644 --- a/packages/snaps-sdk/src/ui/components/row.ts +++ b/packages/snaps-sdk/src/ui/components/row.ts @@ -13,7 +13,6 @@ import { import { createBuilder } from '../builder'; import { LiteralStruct, NodeType } from '../nodes'; import { AddressStruct } from './address'; -import { DoubleValueStruct } from './doubleValue'; import { ImageStruct } from './image'; import { TextStruct } from './text'; @@ -23,11 +22,11 @@ export enum RowVariant { Warning = 'warning', } +// A subset of components made available to the row export const RowComponentStruct = union([ ImageStruct, TextStruct, AddressStruct, - DoubleValueStruct, ]); export const RowStruct = assign( From 3ca7d982deeb72459093fddad0ce9a816caaf983 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Wed, 15 Nov 2023 14:12:04 +0100 Subject: [PATCH 03/12] Fix regex --- packages/snaps-sdk/src/ui/components/address.test.ts | 2 +- packages/snaps-sdk/src/ui/components/address.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/snaps-sdk/src/ui/components/address.test.ts b/packages/snaps-sdk/src/ui/components/address.test.ts index 4c3d71ab25..9dee12da70 100644 --- a/packages/snaps-sdk/src/ui/components/address.test.ts +++ b/packages/snaps-sdk/src/ui/components/address.test.ts @@ -19,7 +19,7 @@ describe('address', () => { it('validates the args', () => { expect(() => address({ value: 'foo' })).toThrow( - 'Invalid address component: At path: value -- Expected a string matching `/(0x[a-fA-F0-9]{40})/` but received "foo"', + 'Invalid address component: At path: value -- Expected a string matching `/0x[a-fA-F0-9]{40}/` but received "foo"', ); // @ts-expect-error - Invalid args. diff --git a/packages/snaps-sdk/src/ui/components/address.ts b/packages/snaps-sdk/src/ui/components/address.ts index 02ed966aba..fcab3e661e 100644 --- a/packages/snaps-sdk/src/ui/components/address.ts +++ b/packages/snaps-sdk/src/ui/components/address.ts @@ -8,7 +8,7 @@ export const AddressStruct = assign( LiteralStruct, object({ type: literal(NodeType.Address), - value: pattern(string(), /(0x[a-fA-F0-9]{40})/gu), + value: pattern(string(), /0x[a-fA-F0-9]{40}/u), }), ); From baa0b77f135ab91b1e8ce2f20ca16eb1eb4cbc25 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Thu, 16 Nov 2023 11:07:48 +0100 Subject: [PATCH 04/12] Use enumValue for variants --- packages/snaps-cli/package.json | 1 + packages/snaps-cli/src/config.ts | 3 +- packages/snaps-jest/src/internals/structs.ts | 7 +- .../src/permitted/getFile.ts | 3 +- .../src/restricted/dialog.ts | 4 +- packages/snaps-sdk/src/index.ts | 3 + packages/snaps-sdk/src/internals/index.ts | 1 + .../snaps-sdk/src/internals/structs.test.ts | 40 ++++++++++ packages/snaps-sdk/src/internals/structs.ts | 78 +++++++++++++++++++ packages/snaps-sdk/src/ui/components/row.ts | 23 +++--- packages/snaps-utils/src/enum.test.ts | 19 ----- packages/snaps-utils/src/enum.ts | 17 ---- packages/snaps-utils/src/index.browser.ts | 1 - packages/snaps-utils/src/index.ts | 1 - packages/snaps-utils/src/structs.test.ts | 24 +----- packages/snaps-utils/src/structs.ts | 70 +---------------- yarn.lock | 1 + 17 files changed, 147 insertions(+), 149 deletions(-) create mode 100644 packages/snaps-sdk/src/internals/structs.test.ts create mode 100644 packages/snaps-sdk/src/internals/structs.ts delete mode 100644 packages/snaps-utils/src/enum.test.ts delete mode 100644 packages/snaps-utils/src/enum.ts diff --git a/packages/snaps-cli/package.json b/packages/snaps-cli/package.json index e718bff857..8a972f6420 100644 --- a/packages/snaps-cli/package.json +++ b/packages/snaps-cli/package.json @@ -54,6 +54,7 @@ "@babel/plugin-transform-runtime": "^7.13.2", "@babel/preset-env": "^7.23.2", "@babel/preset-typescript": "^7.23.2", + "@metamask/snaps-sdk": "workspace:^", "@metamask/snaps-utils": "workspace:^", "@metamask/snaps-webpack-plugin": "workspace:^", "@metamask/utils": "^8.2.1", diff --git a/packages/snaps-cli/src/config.ts b/packages/snaps-cli/src/config.ts index 084e94d342..5ae5666081 100644 --- a/packages/snaps-cli/src/config.ts +++ b/packages/snaps-cli/src/config.ts @@ -1,10 +1,9 @@ +import { literal, union } from '@metamask/snaps-sdk'; import { createFromStruct, file, indent, isFile, - literal, - union, SnapsStructError, named, } from '@metamask/snaps-utils'; diff --git a/packages/snaps-jest/src/internals/structs.ts b/packages/snaps-jest/src/internals/structs.ts index e99cb4c137..44c22adbcf 100644 --- a/packages/snaps-jest/src/internals/structs.ts +++ b/packages/snaps-jest/src/internals/structs.ts @@ -1,5 +1,8 @@ -import { NotificationType, ComponentStruct } from '@metamask/snaps-sdk'; -import { enumValue } from '@metamask/snaps-utils'; +import { + NotificationType, + ComponentStruct, + enumValue, +} from '@metamask/snaps-sdk'; import { bytesToHex, JsonStruct, diff --git a/packages/snaps-rpc-methods/src/permitted/getFile.ts b/packages/snaps-rpc-methods/src/permitted/getFile.ts index d18272c17a..e523b4d739 100644 --- a/packages/snaps-rpc-methods/src/permitted/getFile.ts +++ b/packages/snaps-rpc-methods/src/permitted/getFile.ts @@ -2,9 +2,8 @@ import type { JsonRpcEngineEndCallback } from '@metamask/json-rpc-engine'; import type { PermittedHandlerExport } from '@metamask/permission-controller'; import { rpcErrors } from '@metamask/rpc-errors'; import type { GetFileParams, GetFileResult } from '@metamask/snaps-sdk'; -import { AuxiliaryFileEncoding } from '@metamask/snaps-sdk'; +import { AuxiliaryFileEncoding, enumValue } from '@metamask/snaps-sdk'; import type { InferMatching } from '@metamask/snaps-utils'; -import { enumValue } from '@metamask/snaps-utils'; import type { PendingJsonRpcResponse, JsonRpcRequest } from '@metamask/utils'; import { assertStruct } from '@metamask/utils'; import { object, optional, string, union } from 'superstruct'; diff --git a/packages/snaps-rpc-methods/src/restricted/dialog.ts b/packages/snaps-rpc-methods/src/restricted/dialog.ts index a17af04f3e..08a6788caf 100644 --- a/packages/snaps-rpc-methods/src/restricted/dialog.ts +++ b/packages/snaps-rpc-methods/src/restricted/dialog.ts @@ -5,9 +5,9 @@ import type { } from '@metamask/permission-controller'; import { PermissionType, SubjectType } from '@metamask/permission-controller'; import { rpcErrors } from '@metamask/rpc-errors'; -import { DialogType, ComponentStruct } from '@metamask/snaps-sdk'; +import { DialogType, ComponentStruct, enumValue } from '@metamask/snaps-sdk'; import type { DialogParams, EnumToUnion, Component } from '@metamask/snaps-sdk'; -import { validateComponentLinks, enumValue } from '@metamask/snaps-utils'; +import { validateComponentLinks } from '@metamask/snaps-utils'; import type { InferMatching } from '@metamask/snaps-utils'; import type { NonEmptyArray } from '@metamask/utils'; import type { Infer, Struct } from 'superstruct'; diff --git a/packages/snaps-sdk/src/index.ts b/packages/snaps-sdk/src/index.ts index 15bef21faf..cb353f11ab 100644 --- a/packages/snaps-sdk/src/index.ts +++ b/packages/snaps-sdk/src/index.ts @@ -6,6 +6,9 @@ export { getErrorStack, SNAP_ERROR_CODE, SNAP_ERROR_MESSAGE, + literal, + union, + enumValue, } from './internals'; // Re-exported from `@metamask/utils` for convenience. diff --git a/packages/snaps-sdk/src/internals/index.ts b/packages/snaps-sdk/src/internals/index.ts index 1261626b88..a0bd1a67fb 100644 --- a/packages/snaps-sdk/src/internals/index.ts +++ b/packages/snaps-sdk/src/internals/index.ts @@ -1,3 +1,4 @@ export * from './error-wrappers'; export * from './errors'; export * from './helpers'; +export * from './structs'; diff --git a/packages/snaps-sdk/src/internals/structs.test.ts b/packages/snaps-sdk/src/internals/structs.test.ts new file mode 100644 index 0000000000..64cef4cb33 --- /dev/null +++ b/packages/snaps-sdk/src/internals/structs.test.ts @@ -0,0 +1,40 @@ +import { is, validate } from 'superstruct'; + +import { enumValue, literal, union } from './structs'; + +describe('enumValue', () => { + it('validates an enum value', () => { + enum Foo { + Bar = 'bar', + Baz = 'baz', + } + + const struct = enumValue(Foo.Bar); + + expect(is('bar', struct)).toBe(true); + expect(is('baz', struct)).toBe(false); + expect(is(Foo.Bar, struct)).toBe(true); + expect(is(Foo.Baz, struct)).toBe(false); + }); +}); + +describe('literal', () => { + it.each(['foo', 42, true, false])('validates a literal value', (value) => { + expect(is(value, literal(value))).toBe(true); + }); + + it('returns a struct with the correct name', () => { + const [singleError] = validate('foo', literal('bar')); + expect(singleError?.message).toBe( + 'Expected the literal `"bar"`, but received: "foo"', + ); + + const [unionError] = validate( + 'foo', + union([literal('bar'), literal('baz')]), + ); + expect(unionError?.message).toBe( + 'Expected the value to satisfy a union of `"bar" | "baz"`, but received: "foo"', + ); + }); +}); diff --git a/packages/snaps-sdk/src/internals/structs.ts b/packages/snaps-sdk/src/internals/structs.ts new file mode 100644 index 0000000000..5c6bd2aa51 --- /dev/null +++ b/packages/snaps-sdk/src/internals/structs.ts @@ -0,0 +1,78 @@ +import type { Infer } from 'superstruct'; +import { + Struct, + define, + literal as superstructLiteral, + union as superstructUnion, +} from 'superstruct'; +import type { AnyStruct, InferStructTuple } from 'superstruct/dist/utils'; + +import type { EnumToUnion } from './helpers'; + +/** + * A wrapper of `superstruct`'s `literal` struct that also defines the name of + * the struct as the literal value. + * + * This is useful for improving the error messages returned by `superstruct`. + * For example, instead of returning an error like: + * + * ``` + * Expected the value to satisfy a union of `literal | literal`, but received: \"baz\" + * ``` + * + * This struct will return an error like: + * + * ``` + * Expected the value to satisfy a union of `"foo" | "bar"`, but received: \"baz\" + * ``` + * + * @param value - The literal value. + * @returns The `superstruct` struct, which validates that the value is equal + * to the literal value. + */ +export function literal(value: Type) { + return define( + JSON.stringify(value), + superstructLiteral(value).validator, + ); +} + +/** + * A wrapper of `superstruct`'s `union` struct that also defines the schema as + * the union of the schemas of the structs. + * + * This is useful for improving the error messages returned by `superstruct`. + * + * @param structs - The structs to union. + * @param structs."0" - The first struct. + * @param structs."1" - The remaining structs. + * @returns The `superstruct` struct, which validates that the value satisfies + * one of the structs. + */ +export function union([ + head, + ...tail +]: [head: Head, ...tail: Tail]): Struct< + Infer | InferStructTuple[number], + [head: Head, ...tail: Tail] +> { + const struct = superstructUnion([head, ...tail]); + + return new Struct({ + ...struct, + schema: [head, ...tail], + }); +} + +/** + * Superstruct struct for validating an enum value. This allows using both the + * enum string values and the enum itself as values. + * + * @param constant - The enum to validate against. + * @returns The superstruct struct. + */ +export function enumValue( + constant: Type, +): Struct, null> { + return literal(constant as EnumToUnion); +} diff --git a/packages/snaps-sdk/src/ui/components/row.ts b/packages/snaps-sdk/src/ui/components/row.ts index 73aa90599a..2af45c671c 100644 --- a/packages/snaps-sdk/src/ui/components/row.ts +++ b/packages/snaps-sdk/src/ui/components/row.ts @@ -1,15 +1,7 @@ import type { Infer } from 'superstruct'; -import { - assign, - literal, - object, - lazy, - string, - optional, - enums, - union, -} from 'superstruct'; +import { assign, literal, object, string, optional, union } from 'superstruct'; +import { enumValue } from '../../internals'; import { createBuilder } from '../builder'; import { LiteralStruct, NodeType } from '../nodes'; import { AddressStruct } from './address'; @@ -33,10 +25,15 @@ export const RowStruct = assign( LiteralStruct, object({ type: literal(NodeType.Row), - // TODO: Use enumValue() or similar if needed? - variant: optional(enums(Object.values(RowVariant))), + variant: optional( + union([ + enumValue(RowVariant.Default), + enumValue(RowVariant.Critical), + enumValue(RowVariant.Warning), + ]), + ), label: string(), - value: lazy(() => RowComponentStruct), + value: RowComponentStruct, }), ); diff --git a/packages/snaps-utils/src/enum.test.ts b/packages/snaps-utils/src/enum.test.ts deleted file mode 100644 index 68dd767189..0000000000 --- a/packages/snaps-utils/src/enum.test.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { is } from 'superstruct'; - -import { enumValue } from './enum'; - -describe('enumValue', () => { - it('validates an enum value', () => { - enum Foo { - Bar = 'bar', - Baz = 'baz', - } - - const struct = enumValue(Foo.Bar); - - expect(is('bar', struct)).toBe(true); - expect(is('baz', struct)).toBe(false); - expect(is(Foo.Bar, struct)).toBe(true); - expect(is(Foo.Baz, struct)).toBe(false); - }); -}); diff --git a/packages/snaps-utils/src/enum.ts b/packages/snaps-utils/src/enum.ts deleted file mode 100644 index 925515ac4f..0000000000 --- a/packages/snaps-utils/src/enum.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { EnumToUnion } from '@metamask/snaps-sdk'; -import type { Struct } from 'superstruct'; - -import { literal } from './structs'; - -/** - * Superstruct struct for validating an enum value. This allows using both the - * enum string values and the enum itself as values. - * - * @param constant - The enum to validate against. - * @returns The superstruct struct. - */ -export function enumValue( - constant: Type, -): Struct, null> { - return literal(constant as EnumToUnion); -} diff --git a/packages/snaps-utils/src/index.browser.ts b/packages/snaps-utils/src/index.browser.ts index 508da1afe3..edcf19c558 100644 --- a/packages/snaps-utils/src/index.browser.ts +++ b/packages/snaps-utils/src/index.browser.ts @@ -6,7 +6,6 @@ export * from './cronjob'; export * from './deep-clone'; export * from './default-endowments'; export * from './entropy'; -export * from './enum'; export * from './errors'; export * from './handlers'; export * from './handler-types'; diff --git a/packages/snaps-utils/src/index.ts b/packages/snaps-utils/src/index.ts index 70d9fb9b04..331e3da4ca 100644 --- a/packages/snaps-utils/src/index.ts +++ b/packages/snaps-utils/src/index.ts @@ -6,7 +6,6 @@ export * from './checksum'; export * from './deep-clone'; export * from './default-endowments'; export * from './entropy'; -export * from './enum'; export * from './eval'; export * from './errors'; export * from './fs'; diff --git a/packages/snaps-utils/src/structs.test.ts b/packages/snaps-utils/src/structs.test.ts index 331a191e58..a3968726e1 100644 --- a/packages/snaps-utils/src/structs.test.ts +++ b/packages/snaps-utils/src/structs.test.ts @@ -1,3 +1,4 @@ +import { union, literal } from '@metamask/snaps-sdk'; import { assert } from '@metamask/utils'; import { bold, green, red } from 'chalk'; import type { Struct } from 'superstruct'; @@ -21,8 +22,6 @@ import { getStructErrorMessage, getStructErrorPrefix, getStructFailureMessage, - literal, - union, SnapsStructError, getStructFromPath, getUnionStructNames, @@ -44,27 +43,6 @@ function getStructError(value: unknown, struct: Struct) { return error; } -describe('literal', () => { - it.each(['foo', 42, true, false])('validates a literal value', (value) => { - expect(is(value, literal(value))).toBe(true); - }); - - it('returns a struct with the correct name', () => { - const [singleError] = validate('foo', literal('bar')); - expect(singleError?.message).toBe( - 'Expected the literal `"bar"`, but received: "foo"', - ); - - const [unionError] = validate( - 'foo', - union([literal('bar'), literal('baz')]), - ); - expect(unionError?.message).toBe( - 'Expected the value to satisfy a union of `"bar" | "baz"`, but received: "foo"', - ); - }); -}); - describe('file', () => { it('resolves a file path relative to the current working directory', () => { jest.spyOn(process, 'cwd').mockReturnValue('/foo/bar'); diff --git a/packages/snaps-utils/src/structs.ts b/packages/snaps-utils/src/structs.ts index 001f7518b5..544ff3d661 100644 --- a/packages/snaps-utils/src/structs.ts +++ b/packages/snaps-utils/src/structs.ts @@ -1,18 +1,9 @@ import { isObject } from '@metamask/utils'; import { bold, green, red } from 'chalk'; import { resolve } from 'path'; -import type { Failure, Infer } from 'superstruct'; -import { - Struct, - StructError, - define, - literal as superstructLiteral, - union as superstructUnion, - create, - string, - coerce, -} from 'superstruct'; -import type { AnyStruct, InferStructTuple } from 'superstruct/dist/utils'; +import type { Failure } from 'superstruct'; +import { Struct, StructError, create, string, coerce } from 'superstruct'; +import type { AnyStruct } from 'superstruct/dist/utils'; import { indent } from './strings'; @@ -43,61 +34,6 @@ export type InferMatching< Type, > = StructType['TYPE'] extends Type ? Type : never; -/** - * A wrapper of `superstruct`'s `literal` struct that also defines the name of - * the struct as the literal value. - * - * This is useful for improving the error messages returned by `superstruct`. - * For example, instead of returning an error like: - * - * ``` - * Expected the value to satisfy a union of `literal | literal`, but received: \"baz\" - * ``` - * - * This struct will return an error like: - * - * ``` - * Expected the value to satisfy a union of `"foo" | "bar"`, but received: \"baz\" - * ``` - * - * @param value - The literal value. - * @returns The `superstruct` struct, which validates that the value is equal - * to the literal value. - */ -export function literal(value: Type) { - return define( - JSON.stringify(value), - superstructLiteral(value).validator, - ); -} - -/** - * A wrapper of `superstruct`'s `union` struct that also defines the schema as - * the union of the schemas of the structs. - * - * This is useful for improving the error messages returned by `superstruct`. - * - * @param structs - The structs to union. - * @param structs."0" - The first struct. - * @param structs."1" - The remaining structs. - * @returns The `superstruct` struct, which validates that the value satisfies - * one of the structs. - */ -export function union([ - head, - ...tail -]: [head: Head, ...tail: Tail]): Struct< - Infer | InferStructTuple[number], - [head: Head, ...tail: Tail] -> { - const struct = superstructUnion([head, ...tail]); - - return new Struct({ - ...struct, - schema: [head, ...tail], - }); -} - /** * A wrapper of `superstruct`'s `string` struct that coerces a value to a string * and resolves it relative to the current working directory. This is useful diff --git a/yarn.lock b/yarn.lock index 8fce47dfae..59e6d165bc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5045,6 +5045,7 @@ __metadata: "@metamask/eslint-config-jest": ^12.1.0 "@metamask/eslint-config-nodejs": ^12.1.0 "@metamask/eslint-config-typescript": ^12.1.0 + "@metamask/snaps-sdk": "workspace:^" "@metamask/snaps-utils": "workspace:^" "@metamask/snaps-webpack-plugin": "workspace:^" "@metamask/utils": ^8.2.1 From 48c34c7c82da0c5c52834815b283981e663e6b59 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Thu, 16 Nov 2023 11:17:40 +0100 Subject: [PATCH 05/12] Fix types, update policies and manifests --- .../lavamoat/browserify/iframe/policy.json | 30 ++++++++++++++++++- .../browserify/node-process/policy.json | 30 ++++++++++++++++++- .../browserify/node-thread/policy.json | 30 ++++++++++++++++++- .../lavamoat/browserify/offscreen/policy.json | 30 ++++++++++++++++++- .../browserify/worker-executor/policy.json | 30 ++++++++++++++++++- .../browserify/worker-pool/policy.json | 30 ++++++++++++++++++- .../src/features/renderer/Renderer.tsx | 5 ++-- packages/snaps-utils/coverage.json | 6 ++-- 8 files changed, 179 insertions(+), 12 deletions(-) diff --git a/packages/snaps-execution-environments/lavamoat/browserify/iframe/policy.json b/packages/snaps-execution-environments/lavamoat/browserify/iframe/policy.json index 2be914d879..5d1b4709e5 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/iframe/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/iframe/policy.json @@ -258,7 +258,13 @@ "packages": { "external:../snaps-sdk/src/internals/error-wrappers.ts": true, "external:../snaps-sdk/src/internals/errors.ts": true, - "external:../snaps-sdk/src/internals/helpers.ts": true + "external:../snaps-sdk/src/internals/helpers.ts": true, + "external:../snaps-sdk/src/internals/structs.ts": true + } + }, + "external:../snaps-sdk/src/internals/structs.ts": { + "packages": { + "superstruct": true } }, "external:../snaps-sdk/src/types/handlers/index.ts": { @@ -314,6 +320,13 @@ "superstruct": true } }, + "external:../snaps-sdk/src/ui/components/address.ts": { + "packages": { + "external:../snaps-sdk/src/ui/builder.ts": true, + "external:../snaps-sdk/src/ui/nodes.ts": true, + "superstruct": true + } + }, "external:../snaps-sdk/src/ui/components/copyable.ts": { "packages": { "external:../snaps-sdk/src/ui/builder.ts": true, @@ -345,11 +358,13 @@ }, "external:../snaps-sdk/src/ui/components/index.ts": { "packages": { + "external:../snaps-sdk/src/ui/components/address.ts": true, "external:../snaps-sdk/src/ui/components/copyable.ts": true, "external:../snaps-sdk/src/ui/components/divider.ts": true, "external:../snaps-sdk/src/ui/components/heading.ts": true, "external:../snaps-sdk/src/ui/components/image.ts": true, "external:../snaps-sdk/src/ui/components/panel.ts": true, + "external:../snaps-sdk/src/ui/components/row.ts": true, "external:../snaps-sdk/src/ui/components/spinner.ts": true, "external:../snaps-sdk/src/ui/components/text.ts": true } @@ -357,16 +372,29 @@ "external:../snaps-sdk/src/ui/components/panel.ts": { "packages": { "external:../snaps-sdk/src/ui/builder.ts": true, + "external:../snaps-sdk/src/ui/components/address.ts": true, "external:../snaps-sdk/src/ui/components/copyable.ts": true, "external:../snaps-sdk/src/ui/components/divider.ts": true, "external:../snaps-sdk/src/ui/components/heading.ts": true, "external:../snaps-sdk/src/ui/components/image.ts": true, + "external:../snaps-sdk/src/ui/components/row.ts": true, "external:../snaps-sdk/src/ui/components/spinner.ts": true, "external:../snaps-sdk/src/ui/components/text.ts": true, "external:../snaps-sdk/src/ui/nodes.ts": true, "superstruct": true } }, + "external:../snaps-sdk/src/ui/components/row.ts": { + "packages": { + "external:../snaps-sdk/src/internals/index.ts": true, + "external:../snaps-sdk/src/ui/builder.ts": true, + "external:../snaps-sdk/src/ui/components/address.ts": true, + "external:../snaps-sdk/src/ui/components/image.ts": true, + "external:../snaps-sdk/src/ui/components/text.ts": true, + "external:../snaps-sdk/src/ui/nodes.ts": true, + "superstruct": true + } + }, "external:../snaps-sdk/src/ui/components/spinner.ts": { "packages": { "external:../snaps-sdk/src/ui/builder.ts": true, diff --git a/packages/snaps-execution-environments/lavamoat/browserify/node-process/policy.json b/packages/snaps-execution-environments/lavamoat/browserify/node-process/policy.json index 889a585b37..5d65ea14d8 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/node-process/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/node-process/policy.json @@ -315,7 +315,13 @@ "packages": { "external:../snaps-sdk/src/internals/error-wrappers.ts": true, "external:../snaps-sdk/src/internals/errors.ts": true, - "external:../snaps-sdk/src/internals/helpers.ts": true + "external:../snaps-sdk/src/internals/helpers.ts": true, + "external:../snaps-sdk/src/internals/structs.ts": true + } + }, + "external:../snaps-sdk/src/internals/structs.ts": { + "packages": { + "superstruct": true } }, "external:../snaps-sdk/src/types/handlers/index.ts": { @@ -371,6 +377,13 @@ "superstruct": true } }, + "external:../snaps-sdk/src/ui/components/address.ts": { + "packages": { + "external:../snaps-sdk/src/ui/builder.ts": true, + "external:../snaps-sdk/src/ui/nodes.ts": true, + "superstruct": true + } + }, "external:../snaps-sdk/src/ui/components/copyable.ts": { "packages": { "external:../snaps-sdk/src/ui/builder.ts": true, @@ -402,11 +415,13 @@ }, "external:../snaps-sdk/src/ui/components/index.ts": { "packages": { + "external:../snaps-sdk/src/ui/components/address.ts": true, "external:../snaps-sdk/src/ui/components/copyable.ts": true, "external:../snaps-sdk/src/ui/components/divider.ts": true, "external:../snaps-sdk/src/ui/components/heading.ts": true, "external:../snaps-sdk/src/ui/components/image.ts": true, "external:../snaps-sdk/src/ui/components/panel.ts": true, + "external:../snaps-sdk/src/ui/components/row.ts": true, "external:../snaps-sdk/src/ui/components/spinner.ts": true, "external:../snaps-sdk/src/ui/components/text.ts": true } @@ -414,16 +429,29 @@ "external:../snaps-sdk/src/ui/components/panel.ts": { "packages": { "external:../snaps-sdk/src/ui/builder.ts": true, + "external:../snaps-sdk/src/ui/components/address.ts": true, "external:../snaps-sdk/src/ui/components/copyable.ts": true, "external:../snaps-sdk/src/ui/components/divider.ts": true, "external:../snaps-sdk/src/ui/components/heading.ts": true, "external:../snaps-sdk/src/ui/components/image.ts": true, + "external:../snaps-sdk/src/ui/components/row.ts": true, "external:../snaps-sdk/src/ui/components/spinner.ts": true, "external:../snaps-sdk/src/ui/components/text.ts": true, "external:../snaps-sdk/src/ui/nodes.ts": true, "superstruct": true } }, + "external:../snaps-sdk/src/ui/components/row.ts": { + "packages": { + "external:../snaps-sdk/src/internals/index.ts": true, + "external:../snaps-sdk/src/ui/builder.ts": true, + "external:../snaps-sdk/src/ui/components/address.ts": true, + "external:../snaps-sdk/src/ui/components/image.ts": true, + "external:../snaps-sdk/src/ui/components/text.ts": true, + "external:../snaps-sdk/src/ui/nodes.ts": true, + "superstruct": true + } + }, "external:../snaps-sdk/src/ui/components/spinner.ts": { "packages": { "external:../snaps-sdk/src/ui/builder.ts": true, diff --git a/packages/snaps-execution-environments/lavamoat/browserify/node-thread/policy.json b/packages/snaps-execution-environments/lavamoat/browserify/node-thread/policy.json index 889a585b37..5d65ea14d8 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/node-thread/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/node-thread/policy.json @@ -315,7 +315,13 @@ "packages": { "external:../snaps-sdk/src/internals/error-wrappers.ts": true, "external:../snaps-sdk/src/internals/errors.ts": true, - "external:../snaps-sdk/src/internals/helpers.ts": true + "external:../snaps-sdk/src/internals/helpers.ts": true, + "external:../snaps-sdk/src/internals/structs.ts": true + } + }, + "external:../snaps-sdk/src/internals/structs.ts": { + "packages": { + "superstruct": true } }, "external:../snaps-sdk/src/types/handlers/index.ts": { @@ -371,6 +377,13 @@ "superstruct": true } }, + "external:../snaps-sdk/src/ui/components/address.ts": { + "packages": { + "external:../snaps-sdk/src/ui/builder.ts": true, + "external:../snaps-sdk/src/ui/nodes.ts": true, + "superstruct": true + } + }, "external:../snaps-sdk/src/ui/components/copyable.ts": { "packages": { "external:../snaps-sdk/src/ui/builder.ts": true, @@ -402,11 +415,13 @@ }, "external:../snaps-sdk/src/ui/components/index.ts": { "packages": { + "external:../snaps-sdk/src/ui/components/address.ts": true, "external:../snaps-sdk/src/ui/components/copyable.ts": true, "external:../snaps-sdk/src/ui/components/divider.ts": true, "external:../snaps-sdk/src/ui/components/heading.ts": true, "external:../snaps-sdk/src/ui/components/image.ts": true, "external:../snaps-sdk/src/ui/components/panel.ts": true, + "external:../snaps-sdk/src/ui/components/row.ts": true, "external:../snaps-sdk/src/ui/components/spinner.ts": true, "external:../snaps-sdk/src/ui/components/text.ts": true } @@ -414,16 +429,29 @@ "external:../snaps-sdk/src/ui/components/panel.ts": { "packages": { "external:../snaps-sdk/src/ui/builder.ts": true, + "external:../snaps-sdk/src/ui/components/address.ts": true, "external:../snaps-sdk/src/ui/components/copyable.ts": true, "external:../snaps-sdk/src/ui/components/divider.ts": true, "external:../snaps-sdk/src/ui/components/heading.ts": true, "external:../snaps-sdk/src/ui/components/image.ts": true, + "external:../snaps-sdk/src/ui/components/row.ts": true, "external:../snaps-sdk/src/ui/components/spinner.ts": true, "external:../snaps-sdk/src/ui/components/text.ts": true, "external:../snaps-sdk/src/ui/nodes.ts": true, "superstruct": true } }, + "external:../snaps-sdk/src/ui/components/row.ts": { + "packages": { + "external:../snaps-sdk/src/internals/index.ts": true, + "external:../snaps-sdk/src/ui/builder.ts": true, + "external:../snaps-sdk/src/ui/components/address.ts": true, + "external:../snaps-sdk/src/ui/components/image.ts": true, + "external:../snaps-sdk/src/ui/components/text.ts": true, + "external:../snaps-sdk/src/ui/nodes.ts": true, + "superstruct": true + } + }, "external:../snaps-sdk/src/ui/components/spinner.ts": { "packages": { "external:../snaps-sdk/src/ui/builder.ts": true, diff --git a/packages/snaps-execution-environments/lavamoat/browserify/offscreen/policy.json b/packages/snaps-execution-environments/lavamoat/browserify/offscreen/policy.json index 70de7f2322..b71bf038ce 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/offscreen/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/offscreen/policy.json @@ -159,7 +159,13 @@ "packages": { "external:../snaps-sdk/src/internals/error-wrappers.ts": true, "external:../snaps-sdk/src/internals/errors.ts": true, - "external:../snaps-sdk/src/internals/helpers.ts": true + "external:../snaps-sdk/src/internals/helpers.ts": true, + "external:../snaps-sdk/src/internals/structs.ts": true + } + }, + "external:../snaps-sdk/src/internals/structs.ts": { + "packages": { + "superstruct": true } }, "external:../snaps-sdk/src/types/handlers/index.ts": { @@ -215,6 +221,13 @@ "superstruct": true } }, + "external:../snaps-sdk/src/ui/components/address.ts": { + "packages": { + "external:../snaps-sdk/src/ui/builder.ts": true, + "external:../snaps-sdk/src/ui/nodes.ts": true, + "superstruct": true + } + }, "external:../snaps-sdk/src/ui/components/copyable.ts": { "packages": { "external:../snaps-sdk/src/ui/builder.ts": true, @@ -246,11 +259,13 @@ }, "external:../snaps-sdk/src/ui/components/index.ts": { "packages": { + "external:../snaps-sdk/src/ui/components/address.ts": true, "external:../snaps-sdk/src/ui/components/copyable.ts": true, "external:../snaps-sdk/src/ui/components/divider.ts": true, "external:../snaps-sdk/src/ui/components/heading.ts": true, "external:../snaps-sdk/src/ui/components/image.ts": true, "external:../snaps-sdk/src/ui/components/panel.ts": true, + "external:../snaps-sdk/src/ui/components/row.ts": true, "external:../snaps-sdk/src/ui/components/spinner.ts": true, "external:../snaps-sdk/src/ui/components/text.ts": true } @@ -258,16 +273,29 @@ "external:../snaps-sdk/src/ui/components/panel.ts": { "packages": { "external:../snaps-sdk/src/ui/builder.ts": true, + "external:../snaps-sdk/src/ui/components/address.ts": true, "external:../snaps-sdk/src/ui/components/copyable.ts": true, "external:../snaps-sdk/src/ui/components/divider.ts": true, "external:../snaps-sdk/src/ui/components/heading.ts": true, "external:../snaps-sdk/src/ui/components/image.ts": true, + "external:../snaps-sdk/src/ui/components/row.ts": true, "external:../snaps-sdk/src/ui/components/spinner.ts": true, "external:../snaps-sdk/src/ui/components/text.ts": true, "external:../snaps-sdk/src/ui/nodes.ts": true, "superstruct": true } }, + "external:../snaps-sdk/src/ui/components/row.ts": { + "packages": { + "external:../snaps-sdk/src/internals/index.ts": true, + "external:../snaps-sdk/src/ui/builder.ts": true, + "external:../snaps-sdk/src/ui/components/address.ts": true, + "external:../snaps-sdk/src/ui/components/image.ts": true, + "external:../snaps-sdk/src/ui/components/text.ts": true, + "external:../snaps-sdk/src/ui/nodes.ts": true, + "superstruct": true + } + }, "external:../snaps-sdk/src/ui/components/spinner.ts": { "packages": { "external:../snaps-sdk/src/ui/builder.ts": true, diff --git a/packages/snaps-execution-environments/lavamoat/browserify/worker-executor/policy.json b/packages/snaps-execution-environments/lavamoat/browserify/worker-executor/policy.json index 2be914d879..5d1b4709e5 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/worker-executor/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/worker-executor/policy.json @@ -258,7 +258,13 @@ "packages": { "external:../snaps-sdk/src/internals/error-wrappers.ts": true, "external:../snaps-sdk/src/internals/errors.ts": true, - "external:../snaps-sdk/src/internals/helpers.ts": true + "external:../snaps-sdk/src/internals/helpers.ts": true, + "external:../snaps-sdk/src/internals/structs.ts": true + } + }, + "external:../snaps-sdk/src/internals/structs.ts": { + "packages": { + "superstruct": true } }, "external:../snaps-sdk/src/types/handlers/index.ts": { @@ -314,6 +320,13 @@ "superstruct": true } }, + "external:../snaps-sdk/src/ui/components/address.ts": { + "packages": { + "external:../snaps-sdk/src/ui/builder.ts": true, + "external:../snaps-sdk/src/ui/nodes.ts": true, + "superstruct": true + } + }, "external:../snaps-sdk/src/ui/components/copyable.ts": { "packages": { "external:../snaps-sdk/src/ui/builder.ts": true, @@ -345,11 +358,13 @@ }, "external:../snaps-sdk/src/ui/components/index.ts": { "packages": { + "external:../snaps-sdk/src/ui/components/address.ts": true, "external:../snaps-sdk/src/ui/components/copyable.ts": true, "external:../snaps-sdk/src/ui/components/divider.ts": true, "external:../snaps-sdk/src/ui/components/heading.ts": true, "external:../snaps-sdk/src/ui/components/image.ts": true, "external:../snaps-sdk/src/ui/components/panel.ts": true, + "external:../snaps-sdk/src/ui/components/row.ts": true, "external:../snaps-sdk/src/ui/components/spinner.ts": true, "external:../snaps-sdk/src/ui/components/text.ts": true } @@ -357,16 +372,29 @@ "external:../snaps-sdk/src/ui/components/panel.ts": { "packages": { "external:../snaps-sdk/src/ui/builder.ts": true, + "external:../snaps-sdk/src/ui/components/address.ts": true, "external:../snaps-sdk/src/ui/components/copyable.ts": true, "external:../snaps-sdk/src/ui/components/divider.ts": true, "external:../snaps-sdk/src/ui/components/heading.ts": true, "external:../snaps-sdk/src/ui/components/image.ts": true, + "external:../snaps-sdk/src/ui/components/row.ts": true, "external:../snaps-sdk/src/ui/components/spinner.ts": true, "external:../snaps-sdk/src/ui/components/text.ts": true, "external:../snaps-sdk/src/ui/nodes.ts": true, "superstruct": true } }, + "external:../snaps-sdk/src/ui/components/row.ts": { + "packages": { + "external:../snaps-sdk/src/internals/index.ts": true, + "external:../snaps-sdk/src/ui/builder.ts": true, + "external:../snaps-sdk/src/ui/components/address.ts": true, + "external:../snaps-sdk/src/ui/components/image.ts": true, + "external:../snaps-sdk/src/ui/components/text.ts": true, + "external:../snaps-sdk/src/ui/nodes.ts": true, + "superstruct": true + } + }, "external:../snaps-sdk/src/ui/components/spinner.ts": { "packages": { "external:../snaps-sdk/src/ui/builder.ts": true, diff --git a/packages/snaps-execution-environments/lavamoat/browserify/worker-pool/policy.json b/packages/snaps-execution-environments/lavamoat/browserify/worker-pool/policy.json index 70de7f2322..b71bf038ce 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/worker-pool/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/worker-pool/policy.json @@ -159,7 +159,13 @@ "packages": { "external:../snaps-sdk/src/internals/error-wrappers.ts": true, "external:../snaps-sdk/src/internals/errors.ts": true, - "external:../snaps-sdk/src/internals/helpers.ts": true + "external:../snaps-sdk/src/internals/helpers.ts": true, + "external:../snaps-sdk/src/internals/structs.ts": true + } + }, + "external:../snaps-sdk/src/internals/structs.ts": { + "packages": { + "superstruct": true } }, "external:../snaps-sdk/src/types/handlers/index.ts": { @@ -215,6 +221,13 @@ "superstruct": true } }, + "external:../snaps-sdk/src/ui/components/address.ts": { + "packages": { + "external:../snaps-sdk/src/ui/builder.ts": true, + "external:../snaps-sdk/src/ui/nodes.ts": true, + "superstruct": true + } + }, "external:../snaps-sdk/src/ui/components/copyable.ts": { "packages": { "external:../snaps-sdk/src/ui/builder.ts": true, @@ -246,11 +259,13 @@ }, "external:../snaps-sdk/src/ui/components/index.ts": { "packages": { + "external:../snaps-sdk/src/ui/components/address.ts": true, "external:../snaps-sdk/src/ui/components/copyable.ts": true, "external:../snaps-sdk/src/ui/components/divider.ts": true, "external:../snaps-sdk/src/ui/components/heading.ts": true, "external:../snaps-sdk/src/ui/components/image.ts": true, "external:../snaps-sdk/src/ui/components/panel.ts": true, + "external:../snaps-sdk/src/ui/components/row.ts": true, "external:../snaps-sdk/src/ui/components/spinner.ts": true, "external:../snaps-sdk/src/ui/components/text.ts": true } @@ -258,16 +273,29 @@ "external:../snaps-sdk/src/ui/components/panel.ts": { "packages": { "external:../snaps-sdk/src/ui/builder.ts": true, + "external:../snaps-sdk/src/ui/components/address.ts": true, "external:../snaps-sdk/src/ui/components/copyable.ts": true, "external:../snaps-sdk/src/ui/components/divider.ts": true, "external:../snaps-sdk/src/ui/components/heading.ts": true, "external:../snaps-sdk/src/ui/components/image.ts": true, + "external:../snaps-sdk/src/ui/components/row.ts": true, "external:../snaps-sdk/src/ui/components/spinner.ts": true, "external:../snaps-sdk/src/ui/components/text.ts": true, "external:../snaps-sdk/src/ui/nodes.ts": true, "superstruct": true } }, + "external:../snaps-sdk/src/ui/components/row.ts": { + "packages": { + "external:../snaps-sdk/src/internals/index.ts": true, + "external:../snaps-sdk/src/ui/builder.ts": true, + "external:../snaps-sdk/src/ui/components/address.ts": true, + "external:../snaps-sdk/src/ui/components/image.ts": true, + "external:../snaps-sdk/src/ui/components/text.ts": true, + "external:../snaps-sdk/src/ui/nodes.ts": true, + "superstruct": true + } + }, "external:../snaps-sdk/src/ui/components/spinner.ts": { "packages": { "external:../snaps-sdk/src/ui/builder.ts": true, diff --git a/packages/snaps-simulator/src/features/renderer/Renderer.tsx b/packages/snaps-simulator/src/features/renderer/Renderer.tsx index e617d84e06..b6ee630677 100644 --- a/packages/snaps-simulator/src/features/renderer/Renderer.tsx +++ b/packages/snaps-simulator/src/features/renderer/Renderer.tsx @@ -12,9 +12,8 @@ import { Image, } from './components'; -export const components: Record< - NodeType, - FunctionComponent<{ id: string; node: unknown }> +export const components: Partial< + Record> > = { [NodeType.Copyable]: Copyable, [NodeType.Divider]: Divider, diff --git a/packages/snaps-utils/coverage.json b/packages/snaps-utils/coverage.json index 7b8fd1d889..a6dfb22dab 100644 --- a/packages/snaps-utils/coverage.json +++ b/packages/snaps-utils/coverage.json @@ -1,6 +1,6 @@ { "branches": 95.98, - "functions": 99.01, - "lines": 98.69, - "statements": 95.61 + "functions": 99, + "lines": 98.68, + "statements": 95.58 } From da3edd6093c8871d27943fdadc10b2336d3d6a9b Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Thu, 16 Nov 2023 11:23:22 +0100 Subject: [PATCH 06/12] Lower coverage --- packages/snaps-sdk/jest.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/snaps-sdk/jest.config.js b/packages/snaps-sdk/jest.config.js index 2d14f628ef..5b2999bb25 100644 --- a/packages/snaps-sdk/jest.config.js +++ b/packages/snaps-sdk/jest.config.js @@ -10,7 +10,7 @@ module.exports = deepmerge(baseConfig, { branches: 100, functions: 100, lines: 100, - statements: 100, + statements: 99.55, }, }, From 7644c582fcfb4c97d2da934af6f5f79a0d612d5d Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Thu, 16 Nov 2023 12:10:39 +0100 Subject: [PATCH 07/12] Fix tests --- .../transaction-insights/src/index.test.ts | 45 ++++++++++++++++--- .../transaction-insights/src/index.ts | 3 +- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/packages/examples/packages/transaction-insights/src/index.test.ts b/packages/examples/packages/transaction-insights/src/index.test.ts index 9e22c1381c..d821804fe3 100644 --- a/packages/examples/packages/transaction-insights/src/index.test.ts +++ b/packages/examples/packages/transaction-insights/src/index.test.ts @@ -1,19 +1,28 @@ import { expect } from '@jest/globals'; import { installSnap } from '@metamask/snaps-jest'; -import { panel, text } from '@metamask/snaps-sdk'; +import { panel, text, row, address } from '@metamask/snaps-sdk'; describe('onTransaction', () => { + const FROM_ADDRESS = '0xd8da6bf26964af9d7eed9e03e53415d37aa96045'; + const TO_ADDRESS = '0x4bbeeb066ed09b7aed07bf39eee0460dfa261520'; + it('returns transaction insights for an ERC-20 transaction', async () => { const { sendTransaction, close } = await installSnap(); const response = await sendTransaction({ + from: FROM_ADDRESS, + to: TO_ADDRESS, // This is not a valid ERC-20 transfer as all the values are zero, but it // is enough to test the `onTransaction` handler. data: '0xa9059cbb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', }); expect(response).toRender( - panel([text('**Transaction type:**'), text('ERC-20')]), + panel([ + row('From Address', address(FROM_ADDRESS)), + row('To Address', address(TO_ADDRESS)), + row('Transaction type', text('ERC-20')), + ]), ); await close(); @@ -23,13 +32,19 @@ describe('onTransaction', () => { const { sendTransaction, close } = await installSnap(); const response = await sendTransaction({ + from: FROM_ADDRESS, + to: TO_ADDRESS, // This is not a valid ERC-721 transfer as all the values are zero, but it // is enough to test the `onTransaction` handler. data: '0x23b872dd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', }); expect(response).toRender( - panel([text('**Transaction type:**'), text('ERC-721')]), + panel([ + row('From Address', address(FROM_ADDRESS)), + row('To Address', address(TO_ADDRESS)), + row('Transaction type', text('ERC-721')), + ]), ); await close(); @@ -39,13 +54,19 @@ describe('onTransaction', () => { const { sendTransaction, close } = await installSnap(); const response = await sendTransaction({ + from: FROM_ADDRESS, + to: TO_ADDRESS, // This is not a valid ERC-1155 transfer as all the values are zero, but // it is enough to test the `onTransaction` handler. data: '0xf242432a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', }); expect(response).toRender( - panel([text('**Transaction type:**'), text('ERC-1155')]), + panel([ + row('From Address', address(FROM_ADDRESS)), + row('To Address', address(TO_ADDRESS)), + row('Transaction type', text('ERC-1155')), + ]), ); await close(); @@ -55,11 +76,17 @@ describe('onTransaction', () => { const { sendTransaction, close } = await installSnap(); const response = await sendTransaction({ + from: FROM_ADDRESS, + to: TO_ADDRESS, data: '0xabcdef1200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', }); expect(response).toRender( - panel([text('**Transaction type:**'), text('Unknown')]), + panel([ + row('From Address', address(FROM_ADDRESS)), + row('To Address', address(TO_ADDRESS)), + row('Transaction type', text('Unknown')), + ]), ); await close(); @@ -69,11 +96,17 @@ describe('onTransaction', () => { const { sendTransaction, close } = await installSnap(); const response = await sendTransaction({ + from: FROM_ADDRESS, + to: TO_ADDRESS, data: '0x', }); expect(response).toRender( - panel([text('**Transaction type:**'), text('Unknown')]), + panel([ + row('From Address', address(FROM_ADDRESS)), + row('To Address', address(TO_ADDRESS)), + row('Transaction type', text('Unknown')), + ]), ); await close(); diff --git a/packages/examples/packages/transaction-insights/src/index.ts b/packages/examples/packages/transaction-insights/src/index.ts index c215ce9b04..8356a606d5 100644 --- a/packages/examples/packages/transaction-insights/src/index.ts +++ b/packages/examples/packages/transaction-insights/src/index.ts @@ -37,11 +37,10 @@ export const onTransaction: OnTransactionHandler = async ({ transaction }) => { transaction.to ? address(transaction.to) : text('None'), ), row('Transaction type', text(type)), - text('Old text'), ]), severity: SeverityLevel.Critical, }; } - return { content: panel([text('**Transaction type:**'), text('Unknown')]) }; + return { content: panel([row('Transaction type', text('Unknown'))]) }; }; From 86abcfbdf903f788859897429392cb3f651bf190 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Thu, 16 Nov 2023 12:29:02 +0100 Subject: [PATCH 08/12] Add some docs --- .../snaps-sdk/src/ui/components/address.ts | 17 +++++++++++++ packages/snaps-sdk/src/ui/components/row.ts | 25 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/packages/snaps-sdk/src/ui/components/address.ts b/packages/snaps-sdk/src/ui/components/address.ts index fcab3e661e..349e1ae7a7 100644 --- a/packages/snaps-sdk/src/ui/components/address.ts +++ b/packages/snaps-sdk/src/ui/components/address.ts @@ -12,8 +12,25 @@ export const AddressStruct = assign( }), ); +/** + * A address node, that renders an EVM-like address and its icon. + * + * @property type - The type of the node. Must be the string `address`. + * @property value - The address in hexadecimal, including 0x. + */ export type Address = Infer; +/** + * Create an {@link Address} node. + * + * @param args - The node arguments. This can either be a string, or an object + * with the `value` property. + * @param args.value - The address to be rendered. + * @returns The address node as an object. + * @example + * const node = address({ value: '0x4bbeeb066ed09b7aed07bf39eee0460dfa261520' }); + * const node = address('0x4bbeeb066ed09b7aed07bf39eee0460dfa261520'); + */ export const address = createBuilder(NodeType.Address, AddressStruct, [ 'value', ]); diff --git a/packages/snaps-sdk/src/ui/components/row.ts b/packages/snaps-sdk/src/ui/components/row.ts index 2af45c671c..2e49ce97c1 100644 --- a/packages/snaps-sdk/src/ui/components/row.ts +++ b/packages/snaps-sdk/src/ui/components/row.ts @@ -37,8 +37,33 @@ export const RowStruct = assign( }), ); +/** + * A row node, that renders a row with a label and a value. + * + * @property type - The type of the node. Must be the string `row`. + * @property label - The label for the row. + * @property value - A sub component to be rendered + * on one side of the row. + * @property variant - Optional variant for styling. + */ export type Row = Infer; +/** + * Create a {@link Row} node. + * + * @param args - The node arguments. This can either be a string, a component and an optional variant or an object + * with the properties: `label`, `value` and `variant`. + * @param args.label - The label for the row. + * @param args.value - Another component, is currently limited to `image`, `text` and `address`. + * @param args.variant - An optional variant, either `default`, `warning` or `critical`. + * @returns The row node as an object. + * @example + * const node = image({ value: '' }); + * const node = row({ label: 'Address', value: address('0x4bbeeb066ed09b7aed07bf39eee0460dfa261520') }); + * const node = row({ label: 'Address', value: address('0x4bbeeb066ed09b7aed07bf39eee0460dfa261520'), variant: RowVariant.Warning }); + * const node = row('Address', address('0x4bbeeb066ed09b7aed07bf39eee0460dfa261520')); + * const node = row('Address', address('0x4bbeeb066ed09b7aed07bf39eee0460dfa261520'), RowVariant.Warning); + */ export const row = createBuilder(NodeType.Row, RowStruct, [ 'label', 'value', From 0052007494cac6f24ca0407d5f99c32d406c0795 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Fri, 17 Nov 2023 11:32:27 +0100 Subject: [PATCH 09/12] Fix coverage --- packages/snaps-sdk/jest.config.js | 2 +- packages/snaps-sdk/src/ui/components/row.ts | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/snaps-sdk/jest.config.js b/packages/snaps-sdk/jest.config.js index 5b2999bb25..2d14f628ef 100644 --- a/packages/snaps-sdk/jest.config.js +++ b/packages/snaps-sdk/jest.config.js @@ -10,7 +10,7 @@ module.exports = deepmerge(baseConfig, { branches: 100, functions: 100, lines: 100, - statements: 99.55, + statements: 100, }, }, diff --git a/packages/snaps-sdk/src/ui/components/row.ts b/packages/snaps-sdk/src/ui/components/row.ts index 2e49ce97c1..29cf1a7f8e 100644 --- a/packages/snaps-sdk/src/ui/components/row.ts +++ b/packages/snaps-sdk/src/ui/components/row.ts @@ -15,11 +15,7 @@ export enum RowVariant { } // A subset of components made available to the row -export const RowComponentStruct = union([ - ImageStruct, - TextStruct, - AddressStruct, -]); +const RowComponentStruct = union([ImageStruct, TextStruct, AddressStruct]); export const RowStruct = assign( LiteralStruct, From 3c8d8ca9875ce6b4e92343e104ed8fe2dd491d01 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Fri, 17 Nov 2023 11:37:17 +0100 Subject: [PATCH 10/12] Update manifests --- packages/examples/packages/bip32/snap.manifest.json | 2 +- packages/examples/packages/bip44/snap.manifest.json | 2 +- packages/examples/packages/cronjobs/snap.manifest.json | 2 +- packages/examples/packages/dialogs/snap.manifest.json | 2 +- packages/examples/packages/ethers-js/snap.manifest.json | 2 +- packages/examples/packages/get-entropy/snap.manifest.json | 2 +- packages/examples/packages/home-page/snap.manifest.json | 2 +- .../invoke-snap/packages/core-signer/snap.manifest.json | 2 +- packages/examples/packages/lifecycle-hooks/snap.manifest.json | 2 +- packages/examples/packages/manage-state/snap.manifest.json | 2 +- packages/examples/packages/notifications/snap.manifest.json | 2 +- .../examples/packages/transaction-insights/snap.manifest.json | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/examples/packages/bip32/snap.manifest.json b/packages/examples/packages/bip32/snap.manifest.json index 8f2edb1792..b0fbc4ba03 100644 --- a/packages/examples/packages/bip32/snap.manifest.json +++ b/packages/examples/packages/bip32/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/snaps.git" }, "source": { - "shasum": "c3u/Z2xy1ChWDv4R+OHTAVLeSoT/K/yv9E+q2GAsric=", + "shasum": "8uciDR11gmEm8QDs/sHYPeICmkpHOE4qVe+7zF0O7Ew=", "location": { "npm": { "filePath": "dist/bundle.js", diff --git a/packages/examples/packages/bip44/snap.manifest.json b/packages/examples/packages/bip44/snap.manifest.json index 2cc06dc707..7861497df0 100644 --- a/packages/examples/packages/bip44/snap.manifest.json +++ b/packages/examples/packages/bip44/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/snaps.git" }, "source": { - "shasum": "odIxViYr4MKCR186MZNWbIHBROIRxFDuIGm9BgC0g1E=", + "shasum": "7WXzhl1UIxj91n9Ptv/Rf+nbsYUg3XSOP14sSwEcI2k=", "location": { "npm": { "filePath": "dist/bundle.js", diff --git a/packages/examples/packages/cronjobs/snap.manifest.json b/packages/examples/packages/cronjobs/snap.manifest.json index 2ba4c8560f..aa3baecf32 100644 --- a/packages/examples/packages/cronjobs/snap.manifest.json +++ b/packages/examples/packages/cronjobs/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/snaps.git" }, "source": { - "shasum": "N4HEF5jf+USMjSvrxCYsRJBk9/tEk60CEV44F+RJwUk=", + "shasum": "CxqAZ3b6NadkqDJJDZnKKhXS8ecdcV+qIf/dOmMHzbk=", "location": { "npm": { "filePath": "dist/bundle.js", diff --git a/packages/examples/packages/dialogs/snap.manifest.json b/packages/examples/packages/dialogs/snap.manifest.json index 51797b93f0..109e750c2a 100644 --- a/packages/examples/packages/dialogs/snap.manifest.json +++ b/packages/examples/packages/dialogs/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/snaps.git" }, "source": { - "shasum": "2MlMpD+BND5lUkK5tSuCAODaVSpmMoWDgI6a9+h/1ZI=", + "shasum": "BSNPuKt7cC0lEJaE8M6Y0/7tepS8HiC/+WpjZaOYwYM=", "location": { "npm": { "filePath": "dist/bundle.js", diff --git a/packages/examples/packages/ethers-js/snap.manifest.json b/packages/examples/packages/ethers-js/snap.manifest.json index 9f24651837..12eb15fe68 100644 --- a/packages/examples/packages/ethers-js/snap.manifest.json +++ b/packages/examples/packages/ethers-js/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/snaps.git" }, "source": { - "shasum": "67kh8YEtQfNVOHu3kd9n+qXpF9ZVdpnx0STiujWMpIE=", + "shasum": "FL7kREmDDwiAIHskdA1lbCYQ4NHv8p4UHR/1Tm2mKKA=", "location": { "npm": { "filePath": "dist/bundle.js", diff --git a/packages/examples/packages/get-entropy/snap.manifest.json b/packages/examples/packages/get-entropy/snap.manifest.json index 58b95085b1..87775bfae3 100644 --- a/packages/examples/packages/get-entropy/snap.manifest.json +++ b/packages/examples/packages/get-entropy/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/snaps.git" }, "source": { - "shasum": "W/NHJ/KLYc9HpHVmqdvR5uUFMvn6GtfdN60kA2297xo=", + "shasum": "FzwUtEms+bZSRoUP/48CxTVoSkoQCLG+86oWSUZfueA=", "location": { "npm": { "filePath": "dist/bundle.js", diff --git a/packages/examples/packages/home-page/snap.manifest.json b/packages/examples/packages/home-page/snap.manifest.json index d3ce3896ac..6c95fcdec3 100644 --- a/packages/examples/packages/home-page/snap.manifest.json +++ b/packages/examples/packages/home-page/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/snaps.git" }, "source": { - "shasum": "QkxvGv1BjV0FiuIERffTlLiMO6dAyMRJXeBL913oHHM=", + "shasum": "utXHOukgm1RlUl/sYsI2aNAgeVgEKL+310wUjEAMT9E=", "location": { "npm": { "filePath": "dist/bundle.js", diff --git a/packages/examples/packages/invoke-snap/packages/core-signer/snap.manifest.json b/packages/examples/packages/invoke-snap/packages/core-signer/snap.manifest.json index f960e251f1..4c1709e978 100644 --- a/packages/examples/packages/invoke-snap/packages/core-signer/snap.manifest.json +++ b/packages/examples/packages/invoke-snap/packages/core-signer/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/snaps.git" }, "source": { - "shasum": "DMRI1Ol2xCVZGTnotA3rDkMOY8xtrSC3aXzGBdcdknQ=", + "shasum": "dbIz1yLy7sqedSP6sb8cD5DJgDloM08zJERPa/e8N78=", "location": { "npm": { "filePath": "dist/bundle.js", diff --git a/packages/examples/packages/lifecycle-hooks/snap.manifest.json b/packages/examples/packages/lifecycle-hooks/snap.manifest.json index 64900fdb8b..b93549fbb1 100644 --- a/packages/examples/packages/lifecycle-hooks/snap.manifest.json +++ b/packages/examples/packages/lifecycle-hooks/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/snaps.git" }, "source": { - "shasum": "CawaMvDVaOdsD/Ok0HCRaSzK0HCZx2OZ+zxXap+0GiM=", + "shasum": "Ve8xul91MklBaGJpiaLvCB/qIHIXZEj251XP+pIOOUQ=", "location": { "npm": { "filePath": "dist/bundle.js", diff --git a/packages/examples/packages/manage-state/snap.manifest.json b/packages/examples/packages/manage-state/snap.manifest.json index 701c0a514e..21c1d2bb14 100644 --- a/packages/examples/packages/manage-state/snap.manifest.json +++ b/packages/examples/packages/manage-state/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/snaps.git" }, "source": { - "shasum": "lliQFLB2uFZTWoJ1oU9/HYPWQHqQXlphski2+r4gg84=", + "shasum": "ClCqeb7sknLcct1+EMSjDpNqockG+NVmKnBmfXRXPpM=", "location": { "npm": { "filePath": "dist/bundle.js", diff --git a/packages/examples/packages/notifications/snap.manifest.json b/packages/examples/packages/notifications/snap.manifest.json index 4f9817d5da..05c0cc6365 100644 --- a/packages/examples/packages/notifications/snap.manifest.json +++ b/packages/examples/packages/notifications/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/snaps.git" }, "source": { - "shasum": "AJvmSmfd184z7yFXizADKAl2u6uFewRlZNp64YCm7I0=", + "shasum": "cHCctempM7XrAWGixs2nkxELAqDEezV1/2JzBcVO4t0=", "location": { "npm": { "filePath": "dist/bundle.js", diff --git a/packages/examples/packages/transaction-insights/snap.manifest.json b/packages/examples/packages/transaction-insights/snap.manifest.json index 27e913527d..f4cb8e4d92 100644 --- a/packages/examples/packages/transaction-insights/snap.manifest.json +++ b/packages/examples/packages/transaction-insights/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/snaps.git" }, "source": { - "shasum": "yGCIViDXf/YsS9eI9R46xg4GhMwqf9212A88uxsA4MY=", + "shasum": "JZGXaNG/Us70JF0HiMhpRrQP5eze6lux2QA0Q7tPzyk=", "location": { "npm": { "filePath": "dist/bundle.js", From 6d27b7b9d68dea915fd28d086a404b61e442cba6 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Fri, 17 Nov 2023 11:45:54 +0100 Subject: [PATCH 11/12] Update packages/snaps-sdk/src/ui/components/row.ts Co-authored-by: Maarten Zuidhoorn --- packages/snaps-sdk/src/ui/components/row.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/snaps-sdk/src/ui/components/row.ts b/packages/snaps-sdk/src/ui/components/row.ts index 29cf1a7f8e..90320bd559 100644 --- a/packages/snaps-sdk/src/ui/components/row.ts +++ b/packages/snaps-sdk/src/ui/components/row.ts @@ -54,7 +54,6 @@ export type Row = Infer; * @param args.variant - An optional variant, either `default`, `warning` or `critical`. * @returns The row node as an object. * @example - * const node = image({ value: '' }); * const node = row({ label: 'Address', value: address('0x4bbeeb066ed09b7aed07bf39eee0460dfa261520') }); * const node = row({ label: 'Address', value: address('0x4bbeeb066ed09b7aed07bf39eee0460dfa261520'), variant: RowVariant.Warning }); * const node = row('Address', address('0x4bbeeb066ed09b7aed07bf39eee0460dfa261520')); From dd4f40cce88205fc6a13a383bbc850c42926d3af Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Fri, 17 Nov 2023 13:51:28 +0100 Subject: [PATCH 12/12] Simplify UI slightly --- .../transaction-insights/snap.manifest.json | 2 +- .../transaction-insights/src/index.test.ts | 20 +++++++++---------- .../transaction-insights/src/index.ts | 7 ++----- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/packages/examples/packages/transaction-insights/snap.manifest.json b/packages/examples/packages/transaction-insights/snap.manifest.json index f4cb8e4d92..2e0c509bc1 100644 --- a/packages/examples/packages/transaction-insights/snap.manifest.json +++ b/packages/examples/packages/transaction-insights/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/snaps.git" }, "source": { - "shasum": "JZGXaNG/Us70JF0HiMhpRrQP5eze6lux2QA0Q7tPzyk=", + "shasum": "23BCxdotVNBpoy9z40O7y6rahH4GUD6vsGWJq1uH7Rk=", "location": { "npm": { "filePath": "dist/bundle.js", diff --git a/packages/examples/packages/transaction-insights/src/index.test.ts b/packages/examples/packages/transaction-insights/src/index.test.ts index d821804fe3..b50a6f50ba 100644 --- a/packages/examples/packages/transaction-insights/src/index.test.ts +++ b/packages/examples/packages/transaction-insights/src/index.test.ts @@ -19,8 +19,8 @@ describe('onTransaction', () => { expect(response).toRender( panel([ - row('From Address', address(FROM_ADDRESS)), - row('To Address', address(TO_ADDRESS)), + row('From', address(FROM_ADDRESS)), + row('To', address(TO_ADDRESS)), row('Transaction type', text('ERC-20')), ]), ); @@ -41,8 +41,8 @@ describe('onTransaction', () => { expect(response).toRender( panel([ - row('From Address', address(FROM_ADDRESS)), - row('To Address', address(TO_ADDRESS)), + row('From', address(FROM_ADDRESS)), + row('To', address(TO_ADDRESS)), row('Transaction type', text('ERC-721')), ]), ); @@ -63,8 +63,8 @@ describe('onTransaction', () => { expect(response).toRender( panel([ - row('From Address', address(FROM_ADDRESS)), - row('To Address', address(TO_ADDRESS)), + row('From', address(FROM_ADDRESS)), + row('To', address(TO_ADDRESS)), row('Transaction type', text('ERC-1155')), ]), ); @@ -83,8 +83,8 @@ describe('onTransaction', () => { expect(response).toRender( panel([ - row('From Address', address(FROM_ADDRESS)), - row('To Address', address(TO_ADDRESS)), + row('From', address(FROM_ADDRESS)), + row('To', address(TO_ADDRESS)), row('Transaction type', text('Unknown')), ]), ); @@ -103,8 +103,8 @@ describe('onTransaction', () => { expect(response).toRender( panel([ - row('From Address', address(FROM_ADDRESS)), - row('To Address', address(TO_ADDRESS)), + row('From', address(FROM_ADDRESS)), + row('To', address(TO_ADDRESS)), row('Transaction type', text('Unknown')), ]), ); diff --git a/packages/examples/packages/transaction-insights/src/index.ts b/packages/examples/packages/transaction-insights/src/index.ts index 8356a606d5..81892e62e7 100644 --- a/packages/examples/packages/transaction-insights/src/index.ts +++ b/packages/examples/packages/transaction-insights/src/index.ts @@ -31,11 +31,8 @@ export const onTransaction: OnTransactionHandler = async ({ transaction }) => { const type = decodeData(transaction.data); return { content: panel([ - row('From Address', address(transaction.from)), - row( - 'To Address', - transaction.to ? address(transaction.to) : text('None'), - ), + row('From', address(transaction.from)), + row('To', transaction.to ? address(transaction.to) : text('None')), row('Transaction type', text(type)), ]), severity: SeverityLevel.Critical,