From fbef4c3e36484162fc4b619a1d6a04432237b8f5 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Wed, 9 Apr 2025 14:19:52 -0400 Subject: [PATCH 01/17] fix(send-flow-snap): pass correct displayAvatar param in all UI update instances --- packages/examples/packages/send-flow/src/index.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/examples/packages/send-flow/src/index.tsx b/packages/examples/packages/send-flow/src/index.tsx index 103036dd8f..6e06fd8385 100644 --- a/packages/examples/packages/send-flow/src/index.tsx +++ b/packages/examples/packages/send-flow/src/index.tsx @@ -113,7 +113,9 @@ export const onUserInput: OnUserInputHandler = async ({ errors={formErrors} // For testing purposes, we display the avatar if the address is // a valid hex checksum address. - displayAvatar={isCaipHexAddress(event.value)} + displayAvatar={isCaipHexAddress( + event.name === 'to' ? event.value : sendForm.to, + )} /> ), }, @@ -134,6 +136,7 @@ export const onUserInput: OnUserInputHandler = async ({ total={total} fees={fees} errors={formErrors} + displayAvatar={isCaipHexAddress(sendForm.to)} /> ), }, From 0ae891417ca23a27f3efab47568e47abea35c96c Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Wed, 9 Apr 2025 14:22:07 -0400 Subject: [PATCH 02/17] chore: update snap shasum --- packages/examples/packages/send-flow/snap.manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/examples/packages/send-flow/snap.manifest.json b/packages/examples/packages/send-flow/snap.manifest.json index 9dc13faa72..5c08fc651d 100644 --- a/packages/examples/packages/send-flow/snap.manifest.json +++ b/packages/examples/packages/send-flow/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/snaps.git" }, "source": { - "shasum": "u6ivnu9fXa7saZ10sruh8I3ZKZjeAur4W+9+LVp9BoU=", + "shasum": "A6EWaBqDoKUJIzRolke7nkQXKK/Ob5/q9NhaFs5qRk0=", "location": { "npm": { "filePath": "dist/bundle.js", From 78f694dc198b1f428c328699aff9a2978c3d67b3 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Fri, 11 Apr 2025 20:25:32 -0400 Subject: [PATCH 03/17] test: add tests for various send flow interactions --- .../packages/send-flow/src/index.test.tsx | 221 +++++++++++++++++- 1 file changed, 220 insertions(+), 1 deletion(-) diff --git a/packages/examples/packages/send-flow/src/index.test.tsx b/packages/examples/packages/send-flow/src/index.test.tsx index 568c7b5a2d..05246036cf 100644 --- a/packages/examples/packages/send-flow/src/index.test.tsx +++ b/packages/examples/packages/send-flow/src/index.test.tsx @@ -1,6 +1,9 @@ import { expect } from '@jest/globals'; import { installSnap } from '@metamask/snaps-jest'; +import { SendFlow } from './components'; +import { accountsArray } from './data'; + describe('onRpcRequest', () => { it('throws an error if the requested method does not exist', async () => { const { request } = await installSnap(); @@ -21,6 +24,222 @@ describe('onRpcRequest', () => { }); describe('display', () => { - it.todo('shows a custom dialog with the SendFlow interface'); + it('shows a custom dialog with the SendFlow interface', async () => { + const { request } = await installSnap(); + + const response = request({ + method: 'display', + }); + + const sendFlowInterface = await response.getInterface(); + + expect(sendFlowInterface).toRender( + , + ); + }); + }); +}); + +describe('onHomePage', () => { + it('returns a custom UI', async () => { + const { onHomePage } = await installSnap(); + + const response = await onHomePage(); + + const sendFlowInterface = response.getInterface(); + + expect(sendFlowInterface).toRender( + , + ); + }); +}); + +describe('onUserInput', () => { + it('handles account selection', async () => { + const { request } = await installSnap(); + + const response = request({ + method: 'display', + }); + + const sendFlowInterface = await response.getInterface(); + + await sendFlowInterface.selectFromSelector( + 'accountSelector', + accountsArray[1].address, + ); + + const updatedInterface = await response.getInterface(); + + expect(updatedInterface).toRender( + , + ); + }); + + it('handles amount input', async () => { + const { request } = await installSnap(); + + const response = request({ + method: 'display', + }); + + const sendFlowInterface = await response.getInterface(); + + await sendFlowInterface.typeInField('amount', '0.5'); + + const updatedInterface = await response.getInterface(); + + expect(updatedInterface).toRender( + , + ); + }); + + it('handles to input', async () => { + const { request } = await installSnap(); + + const response = request({ + method: 'display', + }); + + const sendFlowInterface = await response.getInterface(); + + await sendFlowInterface.typeInField( + 'to', + '0x1234567890123456789012345678901234567890', + ); + + const updatedInterface = await response.getInterface(); + + expect(updatedInterface).toRender( + , + ); + }); + + it('handles invalid input', async () => { + const { request } = await installSnap(); + + const response = request({ + method: 'display', + }); + + const sendFlowInterface = await response.getInterface(); + + await sendFlowInterface.typeInField('amount', '2'); + + const updatedInterface = await response.getInterface(); + + expect(updatedInterface).toRender( + , + ); + }); + + it('maintains state across multiple interactions', async () => { + const { request } = await installSnap(); + + const response = request({ + method: 'display', + }); + + const sendFlowInterface = await response.getInterface(); + + await sendFlowInterface.selectFromSelector( + 'accountSelector', + accountsArray[1].address, + ); + + await sendFlowInterface.typeInField('amount', '0.5'); + + const updatedInterface = await response.getInterface(); + + expect(updatedInterface).toRender( + , + ); + + await sendFlowInterface.typeInField( + 'to', + '0x1234567890123456789012345678901234567890', + ); + + const updatedInterface2 = await response.getInterface(); + + expect(updatedInterface2).toRender( + , + ); + + await sendFlowInterface.typeInField('amount', '0'); + + const updatedInterface3 = await response.getInterface(); + + expect(updatedInterface3).toRender( + , + ); }); }); From 32213eb9270aa0941be59c4e78869805fd3084eb Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Fri, 11 Apr 2025 20:43:59 -0400 Subject: [PATCH 04/17] test: update jest config to add svg transformer --- .../packages/send-flow/jest.config.js | 6 +++++ .../test/transformers/svgTransformer.js | 24 +++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 packages/examples/packages/send-flow/test/transformers/svgTransformer.js diff --git a/packages/examples/packages/send-flow/jest.config.js b/packages/examples/packages/send-flow/jest.config.js index d73c99b9a2..2df2e54842 100644 --- a/packages/examples/packages/send-flow/jest.config.js +++ b/packages/examples/packages/send-flow/jest.config.js @@ -33,4 +33,10 @@ module.exports = deepmerge(baseConfig, { '/node_modules/@metamask/$1', ], }, + + // Transform SVG files using our custom transformer + transform: { + ...baseConfig.transform, + '\\.svg$': '/test/transformers/svgTransformer.js', + }, }); diff --git a/packages/examples/packages/send-flow/test/transformers/svgTransformer.js b/packages/examples/packages/send-flow/test/transformers/svgTransformer.js new file mode 100644 index 0000000000..f400163430 --- /dev/null +++ b/packages/examples/packages/send-flow/test/transformers/svgTransformer.js @@ -0,0 +1,24 @@ +/** + * A custom transformer for SVG files in Jest tests. + */ +module.exports = { + /** + * Process an SVG file for Jest tests. + * + * @param {string} sourceText - The content of the SVG file. + * @returns {string} The transformed code. + */ + process(sourceText) { + return `module.exports = ${sourceText}`; + }, + + /** + * Generate a cache key for the transformation. + * + * @param {string} sourceText - The content of the SVG file. + * @returns {string} A cache key for Jest to use for caching purposes. + */ + getCacheKey(sourceText) { + return sourceText; + }, +}; From 13954faa12faaf04efe42e763e161d81552291dc Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Sat, 12 Apr 2025 09:30:14 -0400 Subject: [PATCH 05/17] test: update svg formatting to match tests --- .../examples/packages/send-flow/src/images/btc.svg | 13 +------------ .../packages/send-flow/src/images/jazzicon1.svg | 12 +----------- .../packages/send-flow/src/images/jazzicon2.svg | 12 +----------- 3 files changed, 3 insertions(+), 34 deletions(-) diff --git a/packages/examples/packages/send-flow/src/images/btc.svg b/packages/examples/packages/send-flow/src/images/btc.svg index f5889766e2..80fa533b3f 100644 --- a/packages/examples/packages/send-flow/src/images/btc.svg +++ b/packages/examples/packages/send-flow/src/images/btc.svg @@ -1,12 +1 @@ - - - - - - - - - + diff --git a/packages/examples/packages/send-flow/src/images/jazzicon1.svg b/packages/examples/packages/send-flow/src/images/jazzicon1.svg index c7cc308bb7..a4a473b17c 100644 --- a/packages/examples/packages/send-flow/src/images/jazzicon1.svg +++ b/packages/examples/packages/send-flow/src/images/jazzicon1.svg @@ -1,11 +1 @@ - - - - - - - - - - - + diff --git a/packages/examples/packages/send-flow/src/images/jazzicon2.svg b/packages/examples/packages/send-flow/src/images/jazzicon2.svg index b00299acb0..a4bf570e01 100644 --- a/packages/examples/packages/send-flow/src/images/jazzicon2.svg +++ b/packages/examples/packages/send-flow/src/images/jazzicon2.svg @@ -1,11 +1 @@ - - - - - - - - - - - + From 5eff5d8ca4dc69f11aaa3d8166f86ae77483d69b Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Sat, 12 Apr 2025 09:30:45 -0400 Subject: [PATCH 06/17] test: fix svg transformer --- .../packages/send-flow/test/transformers/svgTransformer.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/examples/packages/send-flow/test/transformers/svgTransformer.js b/packages/examples/packages/send-flow/test/transformers/svgTransformer.js index f400163430..3b78c3ecbb 100644 --- a/packages/examples/packages/send-flow/test/transformers/svgTransformer.js +++ b/packages/examples/packages/send-flow/test/transformers/svgTransformer.js @@ -6,10 +6,12 @@ module.exports = { * Process an SVG file for Jest tests. * * @param {string} sourceText - The content of the SVG file. - * @returns {string} The transformed code. + * @returns {object} The transformed code. */ process(sourceText) { - return `module.exports = ${sourceText}`; + return { + code: `module.exports = ${JSON.stringify(sourceText)};`, + }; }, /** From d227c8b49b612298f3bad5d8e8684fe229f7a4c7 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Sat, 12 Apr 2025 09:31:49 -0400 Subject: [PATCH 07/17] chore: update snap shasum --- packages/examples/packages/send-flow/snap.manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/examples/packages/send-flow/snap.manifest.json b/packages/examples/packages/send-flow/snap.manifest.json index 5c08fc651d..b8b4d8f57d 100644 --- a/packages/examples/packages/send-flow/snap.manifest.json +++ b/packages/examples/packages/send-flow/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/snaps.git" }, "source": { - "shasum": "A6EWaBqDoKUJIzRolke7nkQXKK/Ob5/q9NhaFs5qRk0=", + "shasum": "FOyn/lPGc/Fu6cW6EgX8OwklVJ/+HBydyqz+IDE8M+U=", "location": { "npm": { "filePath": "dist/bundle.js", From 75015d371ae124df6245b2ba4dc97062aa261c64 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Sat, 12 Apr 2025 09:32:47 -0400 Subject: [PATCH 08/17] test: update expected props --- .../examples/packages/send-flow/src/index.test.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/examples/packages/send-flow/src/index.test.tsx b/packages/examples/packages/send-flow/src/index.test.tsx index 05246036cf..faaa360993 100644 --- a/packages/examples/packages/send-flow/src/index.test.tsx +++ b/packages/examples/packages/send-flow/src/index.test.tsx @@ -88,10 +88,10 @@ describe('onUserInput', () => { accounts={accountsArray} selectedAccount={accountsArray[1].address} selectedCurrency="BTC" - total={{ amount: 0, fiat: 0 }} + total={{ amount: 1.0001, fiat: 251.23 }} fees={{ amount: 1.0001, fiat: 1.23 }} errors={{}} - displayAvatar={true} + displayAvatar={false} />, ); }); @@ -133,7 +133,7 @@ describe('onUserInput', () => { await sendFlowInterface.typeInField( 'to', - '0x1234567890123456789012345678901234567890', + '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', ); const updatedInterface = await response.getInterface(); @@ -143,7 +143,7 @@ describe('onUserInput', () => { accounts={accountsArray} selectedAccount={accountsArray[0].address} selectedCurrency="BTC" - total={{ amount: 0, fiat: 251.23 }} + total={{ amount: 1.0001, fiat: 251.23 }} fees={{ amount: 1.0001, fiat: 1.23 }} errors={{}} displayAvatar={true} @@ -169,7 +169,7 @@ describe('onUserInput', () => { accounts={accountsArray} selectedAccount={accountsArray[0].address} selectedCurrency="BTC" - total={{ amount: 3.0001, fiat: 251.23 }} + total={{ amount: 3.0000999999999998, fiat: 251.23 }} fees={{ amount: 1.0001, fiat: 1.23 }} errors={{ amount: 'Insufficient funds' }} displayAvatar={false} @@ -209,7 +209,7 @@ describe('onUserInput', () => { await sendFlowInterface.typeInField( 'to', - '0x1234567890123456789012345678901234567890', + '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', ); const updatedInterface2 = await response.getInterface(); From eee4f6d7d4239626ab94aac9ebe4aed97bbc237f Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Sat, 12 Apr 2025 09:33:21 -0400 Subject: [PATCH 09/17] feat: add logic to format address input values in snap simulation --- packages/snaps-simulation/src/interface.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/packages/snaps-simulation/src/interface.ts b/packages/snaps-simulation/src/interface.ts index cccebd5aa2..3104b2a892 100644 --- a/packages/snaps-simulation/src/interface.ts +++ b/packages/snaps-simulation/src/interface.ts @@ -520,17 +520,24 @@ export async function typeInField( ); assert( - result.element.type === 'Input', - `Expected an element of type "Input", but found "${result.element.type}".`, + result.element.type === 'Input' || result.element.type === 'AddressInput', + `Expected an element of type "Input" or "AddressInput", but found "${result.element.type}".`, ); + let newValue = value; + + if (result.element.type === 'AddressInput') { + const { chainId } = result.element.props; + newValue = `${chainId}:${newValue}`; + } + const { state, context } = controllerMessenger.call( 'SnapInterfaceController:getInterface', snapId, id, ); - const newState = mergeValue(state, name, value, result.form); + const newState = mergeValue(state, name, newValue, result.form); controllerMessenger.call( 'SnapInterfaceController:updateInterfaceState', @@ -548,7 +555,7 @@ export async function typeInField( event: { type: UserInputEventType.InputChangeEvent, name: result.element.props.name, - value, + value: newValue, }, id, context, From 4d8d84ff052bf17751e3fcecfdaeddcf469e2a0b Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Sat, 12 Apr 2025 11:10:52 -0400 Subject: [PATCH 10/17] test: fix typeInField test --- packages/snaps-simulation/src/interface.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/snaps-simulation/src/interface.test.tsx b/packages/snaps-simulation/src/interface.test.tsx index d887bb2f2c..09d2b8741b 100644 --- a/packages/snaps-simulation/src/interface.test.tsx +++ b/packages/snaps-simulation/src/interface.test.tsx @@ -964,7 +964,7 @@ describe('typeInField', () => { 'baz', ), ).rejects.toThrow( - 'Expected an element of type "Input", but found "Button".', + 'Expected an element of type "Input" or "AddressInput", but found "Button".', ); }); }); From 7fc149d244ccd3195d95f9e22d2b82d1b59e7de4 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Sat, 12 Apr 2025 11:55:42 -0400 Subject: [PATCH 11/17] test: add address input test for typeInField --- .../snaps-simulation/src/interface.test.tsx | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/packages/snaps-simulation/src/interface.test.tsx b/packages/snaps-simulation/src/interface.test.tsx index 09d2b8741b..1b81d4fa59 100644 --- a/packages/snaps-simulation/src/interface.test.tsx +++ b/packages/snaps-simulation/src/interface.test.tsx @@ -18,6 +18,7 @@ import { RadioGroup, Radio, Box, + AddressInput, Input, FileInput, Checkbox, @@ -924,6 +925,55 @@ describe('typeInField', () => { }); }); + it('updates the interface state and sends an InputChangeEvent for an AddressInput', async () => { + jest.spyOn(rootControllerMessenger, 'call'); + const content = ( + + ); + + const interfaceId = await interfaceController.createInterface( + MOCK_SNAP_ID, + content, + ); + + await typeInField( + rootControllerMessenger, + interfaceId, + content, + MOCK_SNAP_ID, + 'addressInput', + '0x1234567890123456789012345678901234567890', + ); + + expect(rootControllerMessenger.call).toHaveBeenCalledWith( + 'SnapInterfaceController:updateInterfaceState', + interfaceId, + { addressInput: 'eip155:0:0x1234567890123456789012345678901234567890' }, + ); + + expect(handleRpcRequestMock).toHaveBeenCalledWith(MOCK_SNAP_ID, { + origin: 'metamask', + handler: HandlerType.OnUserInput, + request: { + jsonrpc: '2.0', + method: ' ', + params: { + event: { + type: UserInputEventType.InputChangeEvent, + name: 'addressInput', + value: 'eip155:0:0x1234567890123456789012345678901234567890', + }, + id: interfaceId, + context: null, + }, + }, + }); + }); + it('throws if there is no inputs in the interface', async () => { const content = text('bar'); From 4836a5456d0d92c228774e9e6b2951fa0e282da2 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Mon, 14 Apr 2025 09:31:03 -0400 Subject: [PATCH 12/17] update shasum --- packages/examples/packages/wasm/snap.manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/examples/packages/wasm/snap.manifest.json b/packages/examples/packages/wasm/snap.manifest.json index 1828ca557a..33c30330bb 100644 --- a/packages/examples/packages/wasm/snap.manifest.json +++ b/packages/examples/packages/wasm/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/snaps.git" }, "source": { - "shasum": "6MsBR6Q/fNzDp5dGRWhBZLIBYu4o31cZRTI9iIUdIn0=", + "shasum": "HehP6oFGpT5GZKlzNTVsHCTeTOlBF1044VvfhQGOCEk=", "location": { "npm": { "filePath": "dist/bundle.js", From 840b77804a88eb2f66e7853c35195a0a03a863e3 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Mon, 14 Apr 2025 11:52:11 -0400 Subject: [PATCH 13/17] refactor: add function to process input values, add utility function and tests for printing error messages, add const for tracking typeable inputs --- packages/snaps-simulation/src/interface.ts | 30 +++++++++++++------ .../src/test-utils/constants.ts | 1 + .../src/test-utils/errors.test.ts | 21 +++++++++++++ .../snaps-simulation/src/test-utils/errors.ts | 23 ++++++++++++++ 4 files changed, 66 insertions(+), 9 deletions(-) create mode 100644 packages/snaps-simulation/src/test-utils/constants.ts create mode 100644 packages/snaps-simulation/src/test-utils/errors.test.ts create mode 100644 packages/snaps-simulation/src/test-utils/errors.ts diff --git a/packages/snaps-simulation/src/interface.ts b/packages/snaps-simulation/src/interface.ts index 3104b2a892..ebeea88b8c 100644 --- a/packages/snaps-simulation/src/interface.ts +++ b/packages/snaps-simulation/src/interface.ts @@ -31,13 +31,14 @@ import type { RootControllerMessenger } from './controllers'; import { getFileSize, getFileToUpload } from './files'; import type { Interface, RunSagaFunction } from './store'; import { getCurrentInterface, resolveInterface, setInterface } from './store'; +import { TypeableInputs } from './test-utils/constants'; +import { formatTypeErrorMessage } from './test-utils/errors'; import type { FileOptions, SnapHandlerInterface, SnapInterface, SnapInterfaceActions, } from './types'; - /** * The maximum file size that can be uploaded. */ @@ -494,6 +495,22 @@ export function mergeValue( return { ...state, [name]: value }; } +/** + * Process the input value for an input element based on the element type. + * + * @param value - The original input value. + * @param element - The interface element. + * @returns The processed value. + */ +function processInputValue(value: string, element: NamedJSXElement): string { + if (element.type === 'AddressInput') { + const { chainId } = element.props; + return `${chainId}:${value}`; + } + + return value; +} + /** * Type a value in an interface element. * @@ -520,16 +537,11 @@ export async function typeInField( ); assert( - result.element.type === 'Input' || result.element.type === 'AddressInput', - `Expected an element of type "Input" or "AddressInput", but found "${result.element.type}".`, + TypeableInputs.includes(result.element.type), + `Expected an element of type ${formatTypeErrorMessage(TypeableInputs)}, but found "${result.element.type}".`, ); - let newValue = value; - - if (result.element.type === 'AddressInput') { - const { chainId } = result.element.props; - newValue = `${chainId}:${newValue}`; - } + const newValue = processInputValue(value, result.element); const { state, context } = controllerMessenger.call( 'SnapInterfaceController:getInterface', diff --git a/packages/snaps-simulation/src/test-utils/constants.ts b/packages/snaps-simulation/src/test-utils/constants.ts new file mode 100644 index 0000000000..2b6cdd740a --- /dev/null +++ b/packages/snaps-simulation/src/test-utils/constants.ts @@ -0,0 +1 @@ +export const TypeableInputs = ['Input', 'AddressInput']; diff --git a/packages/snaps-simulation/src/test-utils/errors.test.ts b/packages/snaps-simulation/src/test-utils/errors.test.ts new file mode 100644 index 0000000000..9f5c70b32a --- /dev/null +++ b/packages/snaps-simulation/src/test-utils/errors.test.ts @@ -0,0 +1,21 @@ +import { formatTypeErrorMessage } from './errors'; + +describe('formatTypeErrorMessage', () => { + it('should format error message for one type', () => { + const types = ['Input']; + const result = formatTypeErrorMessage(types); + expect(result).toBe('"Input"'); + }); + + it('should format error message for two types', () => { + const types = ['Input', 'AddressInput']; + const result = formatTypeErrorMessage(types); + expect(result).toBe('"Input" or "AddressInput"'); + }); + + it('should format error message for multiple types', () => { + const types = ['Input', 'AddressInput', 'NewInput']; + const result = formatTypeErrorMessage(types); + expect(result).toBe('"Input", "AddressInput" or "NewInput"'); + }); +}); diff --git a/packages/snaps-simulation/src/test-utils/errors.ts b/packages/snaps-simulation/src/test-utils/errors.ts new file mode 100644 index 0000000000..bb004ccdce --- /dev/null +++ b/packages/snaps-simulation/src/test-utils/errors.ts @@ -0,0 +1,23 @@ +/** + * Format types for error messages based on the number of types. + * + * @param types - Array of type names. + * @returns Formatted string for error message. + */ +export function formatTypeErrorMessage(types: string[]): string { + if (types.length === 1) { + return `"${types[0]}"`; + } + + if (types.length === 2) { + return `"${types[0]}" or "${types[1]}"`; + } + + const lastType = types[types.length - 1]; + const otherTypes = types + .slice(0, -1) + .map((type) => `"${type}"`) + .join(', '); + + return `${otherTypes} or "${lastType}"`; +} From ff79d56643012c7763fc4aa474615d5c0365a306 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Mon, 14 Apr 2025 11:54:33 -0400 Subject: [PATCH 14/17] chore: update exports --- packages/snaps-simulation/src/test-utils/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/snaps-simulation/src/test-utils/index.ts b/packages/snaps-simulation/src/test-utils/index.ts index 9567e012a3..fb7059e997 100644 --- a/packages/snaps-simulation/src/test-utils/index.ts +++ b/packages/snaps-simulation/src/test-utils/index.ts @@ -1,3 +1,5 @@ export * from './controller'; +export * from './errors'; export * from './options'; export * from './server'; +export * from './constants'; From 2a85475b11007020229eec0a11cea2c2b7da71c6 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Mon, 14 Apr 2025 12:05:07 -0400 Subject: [PATCH 15/17] chore: move constant and util to correct locations --- packages/snaps-simulation/src/constants.ts | 5 +++++ packages/snaps-simulation/src/interface.ts | 4 ++-- packages/snaps-simulation/src/test-utils/constants.ts | 1 - packages/snaps-simulation/src/test-utils/index.ts | 3 +-- .../src/{test-utils => utils}/errors.test.ts | 0 .../snaps-simulation/src/{test-utils => utils}/errors.ts | 0 6 files changed, 8 insertions(+), 5 deletions(-) delete mode 100644 packages/snaps-simulation/src/test-utils/constants.ts rename packages/snaps-simulation/src/{test-utils => utils}/errors.test.ts (100%) rename packages/snaps-simulation/src/{test-utils => utils}/errors.ts (100%) diff --git a/packages/snaps-simulation/src/constants.ts b/packages/snaps-simulation/src/constants.ts index b69d4c817a..f066eea0eb 100644 --- a/packages/snaps-simulation/src/constants.ts +++ b/packages/snaps-simulation/src/constants.ts @@ -26,3 +26,8 @@ export const DEFAULT_CURRENCY = 'usd'; * The default JSON-RPC endpoint for Ethereum requests. */ export const DEFAULT_JSON_RPC_ENDPOINT = 'https://cloudflare-eth.com/'; + +/** + * The types of inputs that can be used in the `typeInField` interface action. + */ +export const TypeableInputs = ['Input', 'AddressInput']; diff --git a/packages/snaps-simulation/src/interface.ts b/packages/snaps-simulation/src/interface.ts index ebeea88b8c..8048ea023e 100644 --- a/packages/snaps-simulation/src/interface.ts +++ b/packages/snaps-simulation/src/interface.ts @@ -27,18 +27,18 @@ import deepEqual from 'fast-deep-equal'; import { type SagaIterator } from 'redux-saga'; import { call, put, select, take } from 'redux-saga/effects'; +import { TypeableInputs } from './constants'; import type { RootControllerMessenger } from './controllers'; import { getFileSize, getFileToUpload } from './files'; import type { Interface, RunSagaFunction } from './store'; import { getCurrentInterface, resolveInterface, setInterface } from './store'; -import { TypeableInputs } from './test-utils/constants'; -import { formatTypeErrorMessage } from './test-utils/errors'; import type { FileOptions, SnapHandlerInterface, SnapInterface, SnapInterfaceActions, } from './types'; +import { formatTypeErrorMessage } from './utils/errors'; /** * The maximum file size that can be uploaded. */ diff --git a/packages/snaps-simulation/src/test-utils/constants.ts b/packages/snaps-simulation/src/test-utils/constants.ts deleted file mode 100644 index 2b6cdd740a..0000000000 --- a/packages/snaps-simulation/src/test-utils/constants.ts +++ /dev/null @@ -1 +0,0 @@ -export const TypeableInputs = ['Input', 'AddressInput']; diff --git a/packages/snaps-simulation/src/test-utils/index.ts b/packages/snaps-simulation/src/test-utils/index.ts index fb7059e997..ed9b94b8c1 100644 --- a/packages/snaps-simulation/src/test-utils/index.ts +++ b/packages/snaps-simulation/src/test-utils/index.ts @@ -1,5 +1,4 @@ export * from './controller'; -export * from './errors'; +export * from '../utils/errors'; export * from './options'; export * from './server'; -export * from './constants'; diff --git a/packages/snaps-simulation/src/test-utils/errors.test.ts b/packages/snaps-simulation/src/utils/errors.test.ts similarity index 100% rename from packages/snaps-simulation/src/test-utils/errors.test.ts rename to packages/snaps-simulation/src/utils/errors.test.ts diff --git a/packages/snaps-simulation/src/test-utils/errors.ts b/packages/snaps-simulation/src/utils/errors.ts similarity index 100% rename from packages/snaps-simulation/src/test-utils/errors.ts rename to packages/snaps-simulation/src/utils/errors.ts From 27d71b4e7f112fd7abdf3164e5742bba83f8d3fc Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Mon, 14 Apr 2025 12:35:16 -0400 Subject: [PATCH 16/17] refactor: rename const, remove export --- packages/snaps-simulation/src/constants.ts | 2 +- packages/snaps-simulation/src/interface.ts | 6 +++--- packages/snaps-simulation/src/test-utils/index.ts | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/snaps-simulation/src/constants.ts b/packages/snaps-simulation/src/constants.ts index f066eea0eb..fe700b68cb 100644 --- a/packages/snaps-simulation/src/constants.ts +++ b/packages/snaps-simulation/src/constants.ts @@ -30,4 +30,4 @@ export const DEFAULT_JSON_RPC_ENDPOINT = 'https://cloudflare-eth.com/'; /** * The types of inputs that can be used in the `typeInField` interface action. */ -export const TypeableInputs = ['Input', 'AddressInput']; +export const TYPEABLE_INPUTS = ['Input', 'AddressInput']; diff --git a/packages/snaps-simulation/src/interface.ts b/packages/snaps-simulation/src/interface.ts index 8048ea023e..e0f2f22444 100644 --- a/packages/snaps-simulation/src/interface.ts +++ b/packages/snaps-simulation/src/interface.ts @@ -27,7 +27,7 @@ import deepEqual from 'fast-deep-equal'; import { type SagaIterator } from 'redux-saga'; import { call, put, select, take } from 'redux-saga/effects'; -import { TypeableInputs } from './constants'; +import { TYPEABLE_INPUTS } from './constants'; import type { RootControllerMessenger } from './controllers'; import { getFileSize, getFileToUpload } from './files'; import type { Interface, RunSagaFunction } from './store'; @@ -537,8 +537,8 @@ export async function typeInField( ); assert( - TypeableInputs.includes(result.element.type), - `Expected an element of type ${formatTypeErrorMessage(TypeableInputs)}, but found "${result.element.type}".`, + TYPEABLE_INPUTS.includes(result.element.type), + `Expected an element of type ${formatTypeErrorMessage(TYPEABLE_INPUTS)}, but found "${result.element.type}".`, ); const newValue = processInputValue(value, result.element); diff --git a/packages/snaps-simulation/src/test-utils/index.ts b/packages/snaps-simulation/src/test-utils/index.ts index ed9b94b8c1..9567e012a3 100644 --- a/packages/snaps-simulation/src/test-utils/index.ts +++ b/packages/snaps-simulation/src/test-utils/index.ts @@ -1,4 +1,3 @@ export * from './controller'; -export * from '../utils/errors'; export * from './options'; export * from './server'; From 5a6a3ce24af1d0d72aa39eac25f1e69fa32e4e0c Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Mon, 14 Apr 2025 15:49:49 -0400 Subject: [PATCH 17/17] fix: snap shasum --- packages/examples/packages/wasm/snap.manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/examples/packages/wasm/snap.manifest.json b/packages/examples/packages/wasm/snap.manifest.json index 33c30330bb..1828ca557a 100644 --- a/packages/examples/packages/wasm/snap.manifest.json +++ b/packages/examples/packages/wasm/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/snaps.git" }, "source": { - "shasum": "HehP6oFGpT5GZKlzNTVsHCTeTOlBF1044VvfhQGOCEk=", + "shasum": "6MsBR6Q/fNzDp5dGRWhBZLIBYu4o31cZRTI9iIUdIn0=", "location": { "npm": { "filePath": "dist/bundle.js",