From d47cd1a10690bb146c05bc0108b5046fbdc893ee Mon Sep 17 00:00:00 2001 From: Guillaume Roux Date: Mon, 31 Mar 2025 18:46:52 +0200 Subject: [PATCH 01/10] Add `onAssetHistoricalPrice` handler --- .../src/snaps/SnapController.ts | 4 + .../coverage.json | 8 +- .../common/BaseSnapExecutor.test.browser.ts | 54 ++++++ .../src/common/commands.test.ts | 11 ++ .../src/common/commands.ts | 8 + .../src/common/validation.test.ts | 46 +++++ .../src/common/validation.ts | 91 +++++----- packages/snaps-rpc-methods/package.json | 4 +- .../snaps-rpc-methods/src/endowments/index.ts | 1 + .../src/permitted/scheduleBackgroundEvent.ts | 23 +-- .../types/handlers/asset-historical-price.ts | 52 ++++++ .../snaps-sdk/src/types/handlers/index.ts | 1 + .../src/asset-historical-price.test.ts | 167 ++++++++++++++++++ .../snaps-utils/src/asset-historical-price.ts | 38 ++++ packages/snaps-utils/src/handlers/exports.ts | 10 ++ packages/snaps-utils/src/handlers/types.ts | 1 + packages/snaps-utils/src/index.ts | 1 + packages/snaps-utils/src/structs.test.ts | 19 ++ packages/snaps-utils/src/structs.ts | 21 +++ yarn.lock | 2 - 20 files changed, 493 insertions(+), 69 deletions(-) create mode 100644 packages/snaps-sdk/src/types/handlers/asset-historical-price.ts create mode 100644 packages/snaps-utils/src/asset-historical-price.test.ts create mode 100644 packages/snaps-utils/src/asset-historical-price.ts diff --git a/packages/snaps-controllers/src/snaps/SnapController.ts b/packages/snaps-controllers/src/snaps/SnapController.ts index ddd85137d5..49c7cdf5e1 100644 --- a/packages/snaps-controllers/src/snaps/SnapController.ts +++ b/packages/snaps-controllers/src/snaps/SnapController.ts @@ -104,6 +104,7 @@ import { MAX_FILE_SIZE, OnSettingsPageResponseStruct, isValidUrl, + OnAssetHistoricalPriceResponseStruct, } from '@metamask/snaps-utils'; import type { Json, @@ -3820,6 +3821,9 @@ export class SnapController extends BaseController< case HandlerType.OnAssetsConversion: assertStruct(result, OnAssetsConversionResponseStruct); break; + case HandlerType.OnAssetHistoricalPrice: + assertStruct(result, OnAssetHistoricalPriceResponseStruct); + break; default: break; } diff --git a/packages/snaps-execution-environments/coverage.json b/packages/snaps-execution-environments/coverage.json index 7907537cbd..322df8e3e1 100644 --- a/packages/snaps-execution-environments/coverage.json +++ b/packages/snaps-execution-environments/coverage.json @@ -1,6 +1,6 @@ { - "branches": 80.53, - "functions": 88.96, - "lines": 90.69, - "statements": 89.74 + "branches": 80, + "functions": 89.1, + "lines": 90.64, + "statements": 89.59 } diff --git a/packages/snaps-execution-environments/src/common/BaseSnapExecutor.test.browser.ts b/packages/snaps-execution-environments/src/common/BaseSnapExecutor.test.browser.ts index efd0935491..c2891b12e9 100644 --- a/packages/snaps-execution-environments/src/common/BaseSnapExecutor.test.browser.ts +++ b/packages/snaps-execution-environments/src/common/BaseSnapExecutor.test.browser.ts @@ -1473,6 +1473,60 @@ describe('BaseSnapExecutor', () => { }); }); + it('supports `onAssetHistoricalPrice` export', async () => { + const CODE = ` + module.exports.onAssetHistoricalPrice = () => ({ historicalPrice: { + intervals: { + 'P1D': [ + [1635724800000, "1"], + ] + }, + updateTime: 1635724800000, + } }); + `; + + const executor = new TestSnapExecutor(); + await executor.executeSnap(1, MOCK_SNAP_ID, CODE, []); + + expect(await executor.readCommand()).toStrictEqual({ + jsonrpc: '2.0', + id: 1, + result: 'OK', + }); + + await executor.writeCommand({ + jsonrpc: '2.0', + id: 2, + method: 'snapRpc', + params: [ + MOCK_SNAP_ID, + HandlerType.OnAssetHistoricalPrice, + MOCK_ORIGIN, + { + jsonrpc: '2.0', + method: '', + params: { + from: 'bip122:000000000019d6689c085ae165831e93/slip44:0', + to: 'swift:0/iso4217:USD', + }, + }, + ], + }); + + expect(await executor.readCommand()).toStrictEqual({ + id: 2, + jsonrpc: '2.0', + result: { + historicalPrice: { + intervals: { + P1D: [[1635724800000, '1']], + }, + updateTime: 1635724800000, + }, + }, + }); + }); + it('supports `onAssetsLookup` export', async () => { const CODE = ` module.exports.onAssetsLookup = () => ({ assets: {} }); diff --git a/packages/snaps-execution-environments/src/common/commands.test.ts b/packages/snaps-execution-environments/src/common/commands.test.ts index 2f10b780ef..068914e495 100644 --- a/packages/snaps-execution-environments/src/common/commands.test.ts +++ b/packages/snaps-execution-environments/src/common/commands.test.ts @@ -41,6 +41,17 @@ describe('getHandlerArguments', () => { ).toThrow('Invalid request params'); }); + it('validates the request params for the OnAssetHistoricalPrice handler', () => { + expect(() => + getHandlerArguments(MOCK_ORIGIN, HandlerType.OnAssetHistoricalPrice, { + id: 1, + jsonrpc: '2.0', + method: 'foo', + params: {}, + }), + ).toThrow('Invalid request params'); + }); + it('throws for invalid handler types', () => { expect(() => // @ts-expect-error Invalid handler type. diff --git a/packages/snaps-execution-environments/src/common/commands.ts b/packages/snaps-execution-environments/src/common/commands.ts index db7b2f34d0..588c7fe8f4 100644 --- a/packages/snaps-execution-environments/src/common/commands.ts +++ b/packages/snaps-execution-environments/src/common/commands.ts @@ -18,6 +18,7 @@ import { assertIsOnAssetsLookupRequestArguments, assertIsOnAssetsConversionRequestArguments, assertIsOnProtocolRequestArguments, + assertIsOnAssetHistoricalPriceRequestArguments, } from './validation'; export type CommandMethodsMapping = { @@ -59,6 +60,13 @@ export function getHandlerArguments( const { signature, signatureOrigin } = request.params; return { signature, signatureOrigin }; } + + case HandlerType.OnAssetHistoricalPrice: { + assertIsOnAssetHistoricalPriceRequestArguments(request.params); + const { from, to } = request.params; + return { from, to }; + } + case HandlerType.OnAssetsLookup: { assertIsOnAssetsLookupRequestArguments(request.params); const { assets } = request.params; diff --git a/packages/snaps-execution-environments/src/common/validation.test.ts b/packages/snaps-execution-environments/src/common/validation.test.ts index c3cec65b34..f1ef61c9cb 100644 --- a/packages/snaps-execution-environments/src/common/validation.test.ts +++ b/packages/snaps-execution-environments/src/common/validation.test.ts @@ -1,6 +1,7 @@ import { UserInputEventType } from '@metamask/snaps-sdk'; import { + assertIsOnAssetHistoricalPriceRequestArguments, assertIsOnAssetsConversionRequestArguments, assertIsOnAssetsLookupRequestArguments, assertIsOnNameLookupRequestArguments, @@ -378,3 +379,48 @@ describe('assertIsOnProtocolRequestArguments', () => { }, ); }); + +describe('assertIsOnAssetHistoricalPriceRequestArguments', () => { + it.each([ + { + from: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501', + to: 'swift:0/iso4217:USD', + }, + ])( + 'does not throw for a valid asset historical price request object', + (args) => { + expect(() => + assertIsOnAssetHistoricalPriceRequestArguments(args), + ).not.toThrow(); + }, + ); + + it.each([ + true, + false, + null, + undefined, + 0, + 1, + '', + 'foo', + [], + {}, + { from: [], to: 'swift:0/iso4217:USD' }, + { to: 'swift:0/iso4217:USD', from: 'foo' }, + { from: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501' }, + { to: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501' }, + { + from: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501', + to: 'swift:0/iso4217:USD', + foo: 'bar', + }, + ])( + 'throws if the value is not a valid asset historical price request object', + (value) => { + expect(() => + assertIsOnAssetHistoricalPriceRequestArguments(value as any), + ).toThrow('Invalid request params:'); + }, + ); +}); diff --git a/packages/snaps-execution-environments/src/common/validation.ts b/packages/snaps-execution-environments/src/common/validation.ts index 1e772c558f..83e91e55cd 100644 --- a/packages/snaps-execution-environments/src/common/validation.ts +++ b/packages/snaps-execution-environments/src/common/validation.ts @@ -124,6 +124,25 @@ export type RequestArguments = | ExecuteSnapRequestArguments | SnapRpcRequestArguments; +/** + * Asserts that the given value is a valid request arguments object. + * + * @param value - The value to validate. + * @param requestArgumentsStruct - The struct to validate the value against. + * @throws If the value is not a valid request arguments object. + */ +function assertRequestArguments( + value: unknown, + requestArgumentsStruct: Struct, +): asserts value is Struct { + assertStruct( + value, + requestArgumentsStruct, + 'Invalid request params', + rpcErrors.invalidParams, + ); +} + export const OnTransactionRequestArgumentsStruct = object({ // TODO: Improve `transaction` type. transaction: record(string(), JsonStruct), @@ -146,12 +165,7 @@ export type OnTransactionRequestArguments = Infer< export function assertIsOnTransactionRequestArguments( value: unknown, ): asserts value is OnTransactionRequestArguments { - assertStruct( - value, - OnTransactionRequestArgumentsStruct, - 'Invalid request params', - rpcErrors.invalidParams, - ); + assertRequestArguments(value, OnTransactionRequestArgumentsStruct); } export const OnSignatureRequestArgumentsStruct = object({ @@ -174,12 +188,7 @@ export type OnSignatureRequestArguments = Infer< export function assertIsOnSignatureRequestArguments( value: unknown, ): asserts value is OnSignatureRequestArguments { - assertStruct( - value, - OnSignatureRequestArgumentsStruct, - 'Invalid request params', - rpcErrors.invalidParams, - ); + assertRequestArguments(value, OnSignatureRequestArgumentsStruct); } const baseNameLookupArgs = { chainId: CaipChainIdStruct }; @@ -217,12 +226,30 @@ export type PossibleLookupRequestArgs = typeof baseNameLookupArgs & { export function assertIsOnNameLookupRequestArguments( value: unknown, ): asserts value is OnNameLookupRequestArguments { - assertStruct( - value, - OnNameLookupRequestArgumentsStruct, - 'Invalid request params', - rpcErrors.invalidParams, - ); + assertRequestArguments(value, OnNameLookupRequestArgumentsStruct); +} + +export const OnAssetHistoricalPriceRequestArgumentsStruct = object({ + from: CaipAssetTypeStruct, + to: CaipAssetTypeStruct, +}); + +export type OnAssetHistoricalPriceRequestArguments = Infer< + typeof OnAssetHistoricalPriceRequestArgumentsStruct +>; + +/** + * Asserts that the given value is a valid {@link OnAssetHistoricalPriceRequestArguments} + * object. + * + * @param value - The value to validate. + * @throws If the value is not a valid {@link OnAssetHistoricalPriceRequestArguments} + * object. + */ +export function assertIsOnAssetHistoricalPriceRequestArguments( + value: unknown, +): asserts value is OnAssetHistoricalPriceRequestArguments { + assertRequestArguments(value, OnAssetHistoricalPriceRequestArgumentsStruct); } export const OnAssetsLookupRequestArgumentsStruct = object({ @@ -244,12 +271,7 @@ export type OnAssetsLookupRequestArguments = Infer< export function assertIsOnAssetsLookupRequestArguments( value: unknown, ): asserts value is OnAssetsLookupRequestArguments { - assertStruct( - value, - OnAssetsLookupRequestArgumentsStruct, - 'Invalid request params', - rpcErrors.invalidParams, - ); + assertRequestArguments(value, OnAssetsLookupRequestArgumentsStruct); } export const OnAssetsConversionRequestArgumentsStruct = object({ @@ -280,12 +302,7 @@ export type OnAssetsConversionRequestArguments = Infer< export function assertIsOnAssetsConversionRequestArguments( value: unknown, ): asserts value is OnAssetsConversionRequestArguments { - assertStruct( - value, - OnAssetsConversionRequestArgumentsStruct, - 'Invalid request params', - rpcErrors.invalidParams, - ); + assertRequestArguments(value, OnAssetsConversionRequestArgumentsStruct); } export const OnUserInputArgumentsStruct = object({ @@ -307,12 +324,7 @@ export type OnUserInputArguments = Infer; export function assertIsOnUserInputRequestArguments( value: unknown, ): asserts value is OnUserInputArguments { - assertStruct( - value, - OnUserInputArgumentsStruct, - 'Invalid request params', - rpcErrors.invalidParams, - ); + assertRequestArguments(value, OnUserInputArgumentsStruct); } export const OnProtocolRequestArgumentsStruct = object({ @@ -335,12 +347,7 @@ export type OnProtocolRequestArguments = Infer< export function assertIsOnProtocolRequestArguments( value: unknown, ): asserts value is OnProtocolRequestArguments { - assertStruct( - value, - OnProtocolRequestArgumentsStruct, - 'Invalid request params', - rpcErrors.invalidParams, - ); + assertRequestArguments(value, OnProtocolRequestArgumentsStruct); } // TODO: Either fix this lint violation or explain why it's necessary to ignore. diff --git a/packages/snaps-rpc-methods/package.json b/packages/snaps-rpc-methods/package.json index 1cda7715d1..869a456ee9 100644 --- a/packages/snaps-rpc-methods/package.json +++ b/packages/snaps-rpc-methods/package.json @@ -62,8 +62,7 @@ "@metamask/snaps-utils": "workspace:^", "@metamask/superstruct": "^3.1.0", "@metamask/utils": "^11.2.0", - "@noble/hashes": "^1.7.1", - "luxon": "^3.5.0" + "@noble/hashes": "^1.7.1" }, "devDependencies": { "@lavamoat/allow-scripts": "^3.0.4", @@ -72,7 +71,6 @@ "@swc/core": "1.3.78", "@swc/jest": "^0.2.26", "@ts-bridge/cli": "^0.6.1", - "@types/luxon": "^3", "@types/node": "18.14.2", "deepmerge": "^4.2.2", "depcheck": "^1.4.7", diff --git a/packages/snaps-rpc-methods/src/endowments/index.ts b/packages/snaps-rpc-methods/src/endowments/index.ts index c4d435d31e..60c68b1c01 100644 --- a/packages/snaps-rpc-methods/src/endowments/index.ts +++ b/packages/snaps-rpc-methods/src/endowments/index.ts @@ -126,6 +126,7 @@ export const handlerEndowments: Record = { [HandlerType.OnSettingsPage]: settingsPageEndowmentBuilder.targetName, [HandlerType.OnSignature]: signatureInsightEndowmentBuilder.targetName, [HandlerType.OnUserInput]: null, + [HandlerType.OnAssetHistoricalPrice]: assetsEndowmentBuilder.targetName, [HandlerType.OnAssetsLookup]: assetsEndowmentBuilder.targetName, [HandlerType.OnAssetsConversion]: assetsEndowmentBuilder.targetName, [HandlerType.OnProtocolRequest]: protocolEndowmentBuilder.targetName, diff --git a/packages/snaps-rpc-methods/src/permitted/scheduleBackgroundEvent.ts b/packages/snaps-rpc-methods/src/permitted/scheduleBackgroundEvent.ts index 7073708c46..d5c81c8843 100644 --- a/packages/snaps-rpc-methods/src/permitted/scheduleBackgroundEvent.ts +++ b/packages/snaps-rpc-methods/src/permitted/scheduleBackgroundEvent.ts @@ -19,7 +19,6 @@ import { hasProperty, type PendingJsonRpcResponse, } from '@metamask/utils'; -import { DateTime, Duration } from 'luxon'; import { SnapEndowments } from '../endowments'; import type { MethodHooksObject } from '../utils'; @@ -76,22 +75,6 @@ export type ScheduleBackgroundEventParameters = InferMatching< ScheduleBackgroundEventParams >; -/** - * Generates a `DateTime` object based on if a duration or date is provided. - * - * @param params - The validated params from the `snap_scheduleBackgroundEvent` call. - * @returns A `DateTime` object. - */ -function getStartDate(params: ScheduleBackgroundEventParams) { - if ('duration' in params) { - return DateTime.fromJSDate(new Date()) - .toUTC() - .plus(Duration.fromISO(params.duration)); - } - - return DateTime.fromISO(params.date, { setZone: true }); -} - /** * The `snap_scheduleBackgroundEvent` method implementation. * @@ -126,7 +109,11 @@ async function getScheduleBackgroundEventImplementation( const { request } = validatedParams; - const date = getStartDate(validatedParams); + const time = hasProperty(validatedParams, 'date') + ? (validatedParams.date as string) + : validatedParams.duration; + + const date = getStartDate(time); // Make sure any millisecond precision is removed. const truncatedDate = date.startOf('second').toISO({ diff --git a/packages/snaps-sdk/src/types/handlers/asset-historical-price.ts b/packages/snaps-sdk/src/types/handlers/asset-historical-price.ts new file mode 100644 index 0000000000..226b4d5a40 --- /dev/null +++ b/packages/snaps-sdk/src/types/handlers/asset-historical-price.ts @@ -0,0 +1,52 @@ +import type { CaipAssetType } from '@metamask/utils'; + +/** + * The historical price value. + * The first element in the array is the timestamp, the second is the price. + */ +export type HistoricalPriceValue = [number, string]; + +/** + * The historical price object. + * The key is the time period as an ISO 8601 duration, the value is an array of historical price values. + */ +export type HistoricalPriceIntervals = { + [key: string]: HistoricalPriceValue[]; +}; + +/** + * The response from the historical price query, containing the historical price about the requested asset pair. + * + * @property historicalPrice - The historical price object + * @property historicalPrice.intervals - The historical price of the asset pair. + * @property historicalPrice.conversionTime - The time at which the conversion rate was calculated. + * @property historicalPrice.expirationTime - The time at which the conversion rate expires. + */ +export type OnAssetHistoricalPriceResponse = { + historicalPrice: { + intervals: HistoricalPriceIntervals; + conversionTime: number; + expirationTime?: number; + }; +} | null; + +/** + * The `onAssetHistoricalPrice` handler arguments. + * + * @property from - The CAIP-19 asset type of the asset requested. + * @property to - The CAIP-19 asset type of the asset converted to. + */ +export type OnAssetHistoricalPriceArguments = { + from: CaipAssetType; + to: CaipAssetType; +}; + +/** + * The `onAssetHistoricalPrice` handler. This is called by MetaMask when querying about historical price of an asset pair on specific chains. + * + * @returns The historical price of the asset pair. See + * {@link OnAssetHistoricalPriceResponse}. + */ +export type OnAssetHistoricalPriceHandler = ( + args: OnAssetHistoricalPriceArguments, +) => Promise; diff --git a/packages/snaps-sdk/src/types/handlers/index.ts b/packages/snaps-sdk/src/types/handlers/index.ts index d9b44d6913..b2b857fb89 100644 --- a/packages/snaps-sdk/src/types/handlers/index.ts +++ b/packages/snaps-sdk/src/types/handlers/index.ts @@ -1,3 +1,4 @@ +export type * from './asset-historical-price'; export * from './assets-conversion'; export * from './assets-lookup'; export type * from './cronjob'; diff --git a/packages/snaps-utils/src/asset-historical-price.test.ts b/packages/snaps-utils/src/asset-historical-price.test.ts new file mode 100644 index 0000000000..e02a95374a --- /dev/null +++ b/packages/snaps-utils/src/asset-historical-price.test.ts @@ -0,0 +1,167 @@ +import { is } from '@metamask/superstruct'; + +import { + AssetHistoricalPriceStruct, + HistoricalPriceStruct, + OnAssetHistoricalPriceResponseStruct, +} from './asset-historical-price'; + +describe('HistoricalPriceStruct', () => { + it('validates an object', () => { + const value = { + P1D: [ + [1737542312, '1'], + [1737542312, '2'], + ], + P1W: [ + [1737542312, '1'], + [1737542312, '2'], + ], + }; + + expect(is(value, HistoricalPriceStruct)).toBe(true); + }); + + it.each([ + 'foo', + 42, + null, + undefined, + {}, + [], + { + foo: [ + [1737542312, '1'], + [1737542312, '2'], + ], + }, + ])('does not validate "%p"', (value) => { + expect(is(value, HistoricalPriceStruct)).toBe(false); + }); +}); + +describe('AssetHistoricalPriceStruct', () => { + it.each([ + { + intervals: { + P1D: [ + [1737542312, '1'], + [1737542312, '2'], + ], + P1W: [ + [1737542312, '1'], + [1737542312, '2'], + ], + }, + updateTime: 1737542312, + expirationTime: 1737542312, + }, + { + intervals: { + P1D: [ + [1737542312, '1'], + [1737542312, '2'], + ], + P1W: [ + [1737542312, '1'], + [1737542312, '2'], + ], + }, + updateTime: 1737542312, + }, + null, + ])('validates an object', (value) => { + expect(is(value, AssetHistoricalPriceStruct)).toBe(true); + }); + + it.each([ + 'foo', + 42, + undefined, + {}, + [], + { + intervals: { + foo: [ + [1737542312, '1'], + [1737542312, '2'], + ], + }, + updateTime: 1737542312, + }, + ])('does not validate "%p"', (value) => { + expect(is(value, AssetHistoricalPriceStruct)).toBe(false); + }); +}); + +describe('OnAssetHistoricalPriceResponseStruct', () => { + it.each([ + { + historicalPrice: { + intervals: { + P1D: [ + [1737542312, '1'], + [1737542312, '2'], + ], + P1W: [ + [1737542312, '1'], + [1737542312, '2'], + ], + }, + updateTime: 1737542312, + expirationTime: 1737542312, + }, + }, + { + historicalPrice: { + intervals: { + P1D: [ + [1737542312, '1'], + [1737542312, '2'], + ], + P1W: [ + [1737542312, '1'], + [1737542312, '2'], + ], + }, + updateTime: 1737542312, + }, + }, + { + historicalPrice: null, + }, + ])('validates "%p"', (value) => { + expect(is(value, OnAssetHistoricalPriceResponseStruct)).toBe(true); + }); + + it.each([ + 'foo', + 42, + undefined, + {}, + [], + { + historicalPrice: { + historicalPrice: { + foo: [ + [1737542312, '1'], + [1737542312, '2'], + ], + }, + }, + }, + { + historicalPrice: { + historicalPrice: { + foo: [ + [1737542312, '1'], + [1737542312, '2'], + ], + }, + expirationTime: 1737542312, + }, + }, + ])('does not validate "%p"', (value) => { + expect(is(value, OnAssetHistoricalPriceResponseStruct)).toBe(false); + }); +}); diff --git a/packages/snaps-utils/src/asset-historical-price.ts b/packages/snaps-utils/src/asset-historical-price.ts new file mode 100644 index 0000000000..4273875be8 --- /dev/null +++ b/packages/snaps-utils/src/asset-historical-price.ts @@ -0,0 +1,38 @@ +import { + array, + nullable, + number, + object, + optional, + string, + tuple, +} from '@metamask/superstruct'; + +import { nonEmptyRecord } from './structs'; +import { Iso8601DurationStruct } from './time'; + +/** + * A struct representing a historical price. + */ +export const HistoricalPriceStruct = nonEmptyRecord( + Iso8601DurationStruct, + array(tuple([number(), string()])), +); + +/** + * A struct representing an asset's historical price. + */ +export const AssetHistoricalPriceStruct = nullable( + object({ + intervals: HistoricalPriceStruct, + updateTime: number(), + expirationTime: optional(number()), + }), +); + +/** + * A struct representing the response of the `onAssetHistoricalPrice` method. + */ +export const OnAssetHistoricalPriceResponseStruct = object({ + historicalPrice: AssetHistoricalPriceStruct, +}); diff --git a/packages/snaps-utils/src/handlers/exports.ts b/packages/snaps-utils/src/handlers/exports.ts index bcf4cefe3f..e9e491b68d 100644 --- a/packages/snaps-utils/src/handlers/exports.ts +++ b/packages/snaps-utils/src/handlers/exports.ts @@ -1,4 +1,5 @@ import type { + OnAssetHistoricalPriceHandler, OnAssetsConversionHandler, OnAssetsLookupHandler, OnCronjobHandler, @@ -95,6 +96,15 @@ export const SNAP_EXPORTS = { return typeof snapExport === 'function'; }, }, + [HandlerType.OnAssetHistoricalPrice]: { + type: HandlerType.OnAssetHistoricalPrice, + required: true, + validator: ( + snapExport: unknown, + ): snapExport is OnAssetHistoricalPriceHandler => { + return typeof snapExport === 'function'; + }, + }, [HandlerType.OnAssetsLookup]: { type: HandlerType.OnAssetsLookup, required: true, diff --git a/packages/snaps-utils/src/handlers/types.ts b/packages/snaps-utils/src/handlers/types.ts index bd68948828..882893e303 100644 --- a/packages/snaps-utils/src/handlers/types.ts +++ b/packages/snaps-utils/src/handlers/types.ts @@ -42,6 +42,7 @@ export enum HandlerType { OnUserInput = 'onUserInput', OnAssetsLookup = 'onAssetsLookup', OnAssetsConversion = 'onAssetsConversion', + OnAssetHistoricalPrice = 'onAssetHistoricalPrice', OnProtocolRequest = 'onProtocolRequest', } diff --git a/packages/snaps-utils/src/index.ts b/packages/snaps-utils/src/index.ts index b51634f29b..3570558063 100644 --- a/packages/snaps-utils/src/index.ts +++ b/packages/snaps-utils/src/index.ts @@ -1,4 +1,5 @@ export type * from './account'; +export * from './asset-historical-price'; export * from './array'; export * from './auxiliary-files'; export * from './base64'; diff --git a/packages/snaps-utils/src/structs.test.ts b/packages/snaps-utils/src/structs.test.ts index f67b6d9cef..9e4d16bca1 100644 --- a/packages/snaps-utils/src/structs.test.ts +++ b/packages/snaps-utils/src/structs.test.ts @@ -11,6 +11,7 @@ import { union as superstructUnion, array, is, + any, } from '@metamask/superstruct'; import { assert } from '@metamask/utils'; import { bold, green, red } from 'chalk'; @@ -31,6 +32,7 @@ import { validateUnion, createUnion, mergeStructs, + nonEmptyRecord, } from './structs'; jest.mock('@metamask/superstruct', () => { @@ -511,3 +513,20 @@ describe('mergeStructs', () => { expect(is({ dapps: true }, struct)).toBe(true); }); }); + +describe('nonEmptyRecord', () => { + it.each([[1, 2, 3], { foo: 'bar' }])('validates "%p"', (value) => { + const struct = nonEmptyRecord(string(), any()); + + expect(is(value, struct)).toBe(true); + }); + + it.each(['foo', 42, null, undefined, [], {}])( + 'does not validate "%p"', + (value) => { + const struct = nonEmptyRecord(string(), any()); + + expect(is(value, struct)).toBe(false); + }, + ); +}); diff --git a/packages/snaps-utils/src/structs.ts b/packages/snaps-utils/src/structs.ts index 1881c19b57..7614a5118d 100644 --- a/packages/snaps-utils/src/structs.ts +++ b/packages/snaps-utils/src/structs.ts @@ -14,6 +14,8 @@ import { Struct, StructError, create, + refine, + record, } from '@metamask/superstruct'; import type { NonEmptyArray } from '@metamask/utils'; import { assert, isObject } from '@metamask/utils'; @@ -547,3 +549,22 @@ export function mergeStructs(...structs: Struct[]): Struct { }, }); } + +/** + * Refine a struct to be a non-empty record. + * + * @param Key - The struct for the record key. + * @param Value - The struct for the record value. + * @returns The refined struct. + */ +export function nonEmptyRecord( + Key: Struct, + Value: Struct, +) { + return refine(record(Key, Value), 'Non-empty record', (value) => { + return ( + (Array.isArray(value) && value.length > 0) || + Object.keys(value).length > 0 + ); + }); +} diff --git a/yarn.lock b/yarn.lock index 8c50205655..737fc237fb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5845,7 +5845,6 @@ __metadata: "@swc/core": "npm:1.3.78" "@swc/jest": "npm:^0.2.26" "@ts-bridge/cli": "npm:^0.6.1" - "@types/luxon": "npm:^3" "@types/node": "npm:18.14.2" deepmerge: "npm:^4.2.2" depcheck: "npm:^1.4.7" @@ -5853,7 +5852,6 @@ __metadata: jest: "npm:^29.0.2" jest-it-up: "npm:^2.0.0" jest-silent-reporter: "npm:^0.6.0" - luxon: "npm:^3.5.0" prettier: "npm:^3.3.3" typescript: "npm:~5.3.3" languageName: unknown From 381d01baa80753627f2c8528dd1c466b3fa0826c Mon Sep 17 00:00:00 2001 From: Guillaume Roux Date: Tue, 1 Apr 2025 11:55:45 +0200 Subject: [PATCH 02/10] Add tests and fix type issue --- .../src/snaps/SnapController.test.tsx | 139 ++++++++++++++++++ .../coverage.json | 6 +- .../types/handlers/asset-historical-price.ts | 6 +- 3 files changed, 145 insertions(+), 6 deletions(-) diff --git a/packages/snaps-controllers/src/snaps/SnapController.test.tsx b/packages/snaps-controllers/src/snaps/SnapController.test.tsx index 0dfd201646..0668fd4ea5 100644 --- a/packages/snaps-controllers/src/snaps/SnapController.test.tsx +++ b/packages/snaps-controllers/src/snaps/SnapController.test.tsx @@ -4354,6 +4354,145 @@ describe('SnapController', () => { }); }); + describe('onAssetHistoricalPrice', () => { + it('throws if `onAssetHistoricalPrice` handler returns an invalid response', async () => { + const rootMessenger = getControllerMessenger(); + const messenger = getSnapControllerMessenger(rootMessenger); + const snapController = getSnapController( + getSnapControllerOptions({ + messenger, + state: { + snaps: getPersistedSnapsState(), + }, + }), + ); + + rootMessenger.registerActionHandler( + 'PermissionController:getPermissions', + () => ({ + [SnapEndowments.Assets]: { + caveats: [ + { + type: SnapCaveatType.ChainIds, + value: ['bip122:000000000019d6689c085ae165831e93'], + }, + ], + date: 1664187844588, + id: 'izn0WGUO8cvq_jqvLQuQP', + invoker: MOCK_SNAP_ID, + parentCapability: SnapEndowments.Assets, + }, + }), + ); + + rootMessenger.registerActionHandler( + 'SubjectMetadataController:getSubjectMetadata', + () => MOCK_SNAP_SUBJECT_METADATA, + ); + + rootMessenger.registerActionHandler( + 'ExecutionService:handleRpcRequest', + async () => + Promise.resolve({ + historicalPrice: { foo: {} }, + }), + ); + + await expect( + snapController.handleRequest({ + snapId: MOCK_SNAP_ID, + origin: 'foo.com', + handler: HandlerType.OnAssetHistoricalPrice, + request: { + jsonrpc: '2.0', + method: ' ', + params: {}, + id: 1, + }, + }), + ).rejects.toThrow( + `Assertion failed: At path: historicalPrice.intervals -- Expected an object, but received: undefined.`, + ); + + snapController.destroy(); + }); + + it('returns the value when `onAssetHistoricalPrice` returns a valid response', async () => { + const rootMessenger = getControllerMessenger(); + const messenger = getSnapControllerMessenger(rootMessenger); + const snapController = getSnapController( + getSnapControllerOptions({ + messenger, + state: { + snaps: getPersistedSnapsState(), + }, + }), + ); + + rootMessenger.registerActionHandler( + 'PermissionController:getPermissions', + () => ({ + [SnapEndowments.Assets]: { + caveats: [ + { + type: SnapCaveatType.ChainIds, + value: ['bip122:000000000019d6689c085ae165831e93'], + }, + ], + date: 1664187844588, + id: 'izn0WGUO8cvq_jqvLQuQP', + invoker: MOCK_SNAP_ID, + parentCapability: SnapEndowments.Assets, + }, + }), + ); + + rootMessenger.registerActionHandler( + 'SubjectMetadataController:getSubjectMetadata', + () => MOCK_SNAP_SUBJECT_METADATA, + ); + + rootMessenger.registerActionHandler( + 'ExecutionService:handleRpcRequest', + async () => + Promise.resolve({ + historicalPrice: { + intervals: { + P1D: [[1737548790, '400']], + }, + updateTime: 1737548790, + }, + }), + ); + + expect( + await snapController.handleRequest({ + snapId: MOCK_SNAP_ID, + origin: 'foo.com', + handler: HandlerType.OnAssetHistoricalPrice, + request: { + jsonrpc: '2.0', + method: ' ', + params: { + from: 'bip122:000000000019d6689c085ae165831e93/slip44:0', + to: 'swift:0/iso4217:USD', + }, + id: 1, + }, + }), + ).toStrictEqual({ + historicalPrice: { + intervals: { + P1D: [[1737548790, '400']], + }, + updateTime: 1737548790, + }, + }); + + snapController.destroy(); + }); + }); + describe('getRpcRequestHandler', () => { it('handlers populate the "jsonrpc" property if missing', async () => { const rootMessenger = getControllerMessenger(); diff --git a/packages/snaps-execution-environments/coverage.json b/packages/snaps-execution-environments/coverage.json index 322df8e3e1..4dbe385a1f 100644 --- a/packages/snaps-execution-environments/coverage.json +++ b/packages/snaps-execution-environments/coverage.json @@ -1,6 +1,6 @@ { - "branches": 80, + "branches": 80.66, "functions": 89.1, - "lines": 90.64, - "statements": 89.59 + "lines": 90.78, + "statements": 89.72 } diff --git a/packages/snaps-sdk/src/types/handlers/asset-historical-price.ts b/packages/snaps-sdk/src/types/handlers/asset-historical-price.ts index 226b4d5a40..5f063579d0 100644 --- a/packages/snaps-sdk/src/types/handlers/asset-historical-price.ts +++ b/packages/snaps-sdk/src/types/handlers/asset-historical-price.ts @@ -19,13 +19,13 @@ export type HistoricalPriceIntervals = { * * @property historicalPrice - The historical price object * @property historicalPrice.intervals - The historical price of the asset pair. - * @property historicalPrice.conversionTime - The time at which the conversion rate was calculated. - * @property historicalPrice.expirationTime - The time at which the conversion rate expires. + * @property historicalPrice.updateTime - The time at which the historical price has been calculated. + * @property historicalPrice.expirationTime - The time at which the historical price expires. */ export type OnAssetHistoricalPriceResponse = { historicalPrice: { intervals: HistoricalPriceIntervals; - conversionTime: number; + updateTime: number; expirationTime?: number; }; } | null; From ed1ee3ddbc9bd873e29c986d49b70aca602f335b Mon Sep 17 00:00:00 2001 From: Guillaume Roux Date: Wed, 2 Apr 2025 14:48:11 +0200 Subject: [PATCH 03/10] fix after rebase --- packages/snaps-rpc-methods/package.json | 4 +++- .../snaps-rpc-methods/src/endowments/index.ts | 1 - .../src/permitted/scheduleBackgroundEvent.ts | 23 +++++++++++++++---- .../asset-historical-price.test.ts | 0 .../{ => handlers}/asset-historical-price.ts | 6 ++--- packages/snaps-utils/src/handlers/index.ts | 1 + packages/snaps-utils/src/index.ts | 1 - packages/snaps-utils/src/structs.test.ts | 19 --------------- packages/snaps-utils/src/structs.ts | 21 ----------------- yarn.lock | 2 ++ 10 files changed, 27 insertions(+), 51 deletions(-) rename packages/snaps-utils/src/{ => handlers}/asset-historical-price.test.ts (100%) rename packages/snaps-utils/src/{ => handlers}/asset-historical-price.ts (84%) diff --git a/packages/snaps-rpc-methods/package.json b/packages/snaps-rpc-methods/package.json index 869a456ee9..1cda7715d1 100644 --- a/packages/snaps-rpc-methods/package.json +++ b/packages/snaps-rpc-methods/package.json @@ -62,7 +62,8 @@ "@metamask/snaps-utils": "workspace:^", "@metamask/superstruct": "^3.1.0", "@metamask/utils": "^11.2.0", - "@noble/hashes": "^1.7.1" + "@noble/hashes": "^1.7.1", + "luxon": "^3.5.0" }, "devDependencies": { "@lavamoat/allow-scripts": "^3.0.4", @@ -71,6 +72,7 @@ "@swc/core": "1.3.78", "@swc/jest": "^0.2.26", "@ts-bridge/cli": "^0.6.1", + "@types/luxon": "^3", "@types/node": "18.14.2", "deepmerge": "^4.2.2", "depcheck": "^1.4.7", diff --git a/packages/snaps-rpc-methods/src/endowments/index.ts b/packages/snaps-rpc-methods/src/endowments/index.ts index 60c68b1c01..c4d435d31e 100644 --- a/packages/snaps-rpc-methods/src/endowments/index.ts +++ b/packages/snaps-rpc-methods/src/endowments/index.ts @@ -126,7 +126,6 @@ export const handlerEndowments: Record = { [HandlerType.OnSettingsPage]: settingsPageEndowmentBuilder.targetName, [HandlerType.OnSignature]: signatureInsightEndowmentBuilder.targetName, [HandlerType.OnUserInput]: null, - [HandlerType.OnAssetHistoricalPrice]: assetsEndowmentBuilder.targetName, [HandlerType.OnAssetsLookup]: assetsEndowmentBuilder.targetName, [HandlerType.OnAssetsConversion]: assetsEndowmentBuilder.targetName, [HandlerType.OnProtocolRequest]: protocolEndowmentBuilder.targetName, diff --git a/packages/snaps-rpc-methods/src/permitted/scheduleBackgroundEvent.ts b/packages/snaps-rpc-methods/src/permitted/scheduleBackgroundEvent.ts index d5c81c8843..7073708c46 100644 --- a/packages/snaps-rpc-methods/src/permitted/scheduleBackgroundEvent.ts +++ b/packages/snaps-rpc-methods/src/permitted/scheduleBackgroundEvent.ts @@ -19,6 +19,7 @@ import { hasProperty, type PendingJsonRpcResponse, } from '@metamask/utils'; +import { DateTime, Duration } from 'luxon'; import { SnapEndowments } from '../endowments'; import type { MethodHooksObject } from '../utils'; @@ -75,6 +76,22 @@ export type ScheduleBackgroundEventParameters = InferMatching< ScheduleBackgroundEventParams >; +/** + * Generates a `DateTime` object based on if a duration or date is provided. + * + * @param params - The validated params from the `snap_scheduleBackgroundEvent` call. + * @returns A `DateTime` object. + */ +function getStartDate(params: ScheduleBackgroundEventParams) { + if ('duration' in params) { + return DateTime.fromJSDate(new Date()) + .toUTC() + .plus(Duration.fromISO(params.duration)); + } + + return DateTime.fromISO(params.date, { setZone: true }); +} + /** * The `snap_scheduleBackgroundEvent` method implementation. * @@ -109,11 +126,7 @@ async function getScheduleBackgroundEventImplementation( const { request } = validatedParams; - const time = hasProperty(validatedParams, 'date') - ? (validatedParams.date as string) - : validatedParams.duration; - - const date = getStartDate(time); + const date = getStartDate(validatedParams); // Make sure any millisecond precision is removed. const truncatedDate = date.startOf('second').toISO({ diff --git a/packages/snaps-utils/src/asset-historical-price.test.ts b/packages/snaps-utils/src/handlers/asset-historical-price.test.ts similarity index 100% rename from packages/snaps-utils/src/asset-historical-price.test.ts rename to packages/snaps-utils/src/handlers/asset-historical-price.test.ts diff --git a/packages/snaps-utils/src/asset-historical-price.ts b/packages/snaps-utils/src/handlers/asset-historical-price.ts similarity index 84% rename from packages/snaps-utils/src/asset-historical-price.ts rename to packages/snaps-utils/src/handlers/asset-historical-price.ts index 4273875be8..8ed2a9a438 100644 --- a/packages/snaps-utils/src/asset-historical-price.ts +++ b/packages/snaps-utils/src/handlers/asset-historical-price.ts @@ -1,3 +1,4 @@ +import { nonEmptyRecord } from '@metamask/snaps-sdk'; import { array, nullable, @@ -8,14 +9,13 @@ import { tuple, } from '@metamask/superstruct'; -import { nonEmptyRecord } from './structs'; -import { Iso8601DurationStruct } from './time'; +import { ISO8601DurationStruct } from '../time'; /** * A struct representing a historical price. */ export const HistoricalPriceStruct = nonEmptyRecord( - Iso8601DurationStruct, + ISO8601DurationStruct, array(tuple([number(), string()])), ); diff --git a/packages/snaps-utils/src/handlers/index.ts b/packages/snaps-utils/src/handlers/index.ts index 0c164de707..d6df9efa3b 100644 --- a/packages/snaps-utils/src/handlers/index.ts +++ b/packages/snaps-utils/src/handlers/index.ts @@ -1,3 +1,4 @@ +export * from './asset-historical-price'; export * from './exports'; export * from './home-page'; export * from './name-lookup'; diff --git a/packages/snaps-utils/src/index.ts b/packages/snaps-utils/src/index.ts index 3570558063..b51634f29b 100644 --- a/packages/snaps-utils/src/index.ts +++ b/packages/snaps-utils/src/index.ts @@ -1,5 +1,4 @@ export type * from './account'; -export * from './asset-historical-price'; export * from './array'; export * from './auxiliary-files'; export * from './base64'; diff --git a/packages/snaps-utils/src/structs.test.ts b/packages/snaps-utils/src/structs.test.ts index 9e4d16bca1..f67b6d9cef 100644 --- a/packages/snaps-utils/src/structs.test.ts +++ b/packages/snaps-utils/src/structs.test.ts @@ -11,7 +11,6 @@ import { union as superstructUnion, array, is, - any, } from '@metamask/superstruct'; import { assert } from '@metamask/utils'; import { bold, green, red } from 'chalk'; @@ -32,7 +31,6 @@ import { validateUnion, createUnion, mergeStructs, - nonEmptyRecord, } from './structs'; jest.mock('@metamask/superstruct', () => { @@ -513,20 +511,3 @@ describe('mergeStructs', () => { expect(is({ dapps: true }, struct)).toBe(true); }); }); - -describe('nonEmptyRecord', () => { - it.each([[1, 2, 3], { foo: 'bar' }])('validates "%p"', (value) => { - const struct = nonEmptyRecord(string(), any()); - - expect(is(value, struct)).toBe(true); - }); - - it.each(['foo', 42, null, undefined, [], {}])( - 'does not validate "%p"', - (value) => { - const struct = nonEmptyRecord(string(), any()); - - expect(is(value, struct)).toBe(false); - }, - ); -}); diff --git a/packages/snaps-utils/src/structs.ts b/packages/snaps-utils/src/structs.ts index 7614a5118d..1881c19b57 100644 --- a/packages/snaps-utils/src/structs.ts +++ b/packages/snaps-utils/src/structs.ts @@ -14,8 +14,6 @@ import { Struct, StructError, create, - refine, - record, } from '@metamask/superstruct'; import type { NonEmptyArray } from '@metamask/utils'; import { assert, isObject } from '@metamask/utils'; @@ -549,22 +547,3 @@ export function mergeStructs(...structs: Struct[]): Struct { }, }); } - -/** - * Refine a struct to be a non-empty record. - * - * @param Key - The struct for the record key. - * @param Value - The struct for the record value. - * @returns The refined struct. - */ -export function nonEmptyRecord( - Key: Struct, - Value: Struct, -) { - return refine(record(Key, Value), 'Non-empty record', (value) => { - return ( - (Array.isArray(value) && value.length > 0) || - Object.keys(value).length > 0 - ); - }); -} diff --git a/yarn.lock b/yarn.lock index 737fc237fb..8c50205655 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5845,6 +5845,7 @@ __metadata: "@swc/core": "npm:1.3.78" "@swc/jest": "npm:^0.2.26" "@ts-bridge/cli": "npm:^0.6.1" + "@types/luxon": "npm:^3" "@types/node": "npm:18.14.2" deepmerge: "npm:^4.2.2" depcheck: "npm:^1.4.7" @@ -5852,6 +5853,7 @@ __metadata: jest: "npm:^29.0.2" jest-it-up: "npm:^2.0.0" jest-silent-reporter: "npm:^0.6.0" + luxon: "npm:^3.5.0" prettier: "npm:^3.3.3" typescript: "npm:~5.3.3" languageName: unknown From 16b0e92c7fc45a375894257059964d74e29b17a4 Mon Sep 17 00:00:00 2001 From: Guillaume Roux Date: Wed, 2 Apr 2025 15:40:31 +0200 Subject: [PATCH 04/10] fix lavamoat policy and handle requested changes --- .../lavamoat/browserify/iframe/policy.json | 6 ++ .../browserify/node-process/policy.json | 6 ++ .../browserify/node-thread/policy.json | 6 ++ .../lavamoat/browserify/webview/policy.json | 6 ++ .../browserify/worker-executor/policy.json | 6 ++ .../browserify/worker-pool/policy.json | 6 ++ .../src/common/validation.ts | 6 +- .../snaps-rpc-methods/src/endowments/index.ts | 1 + .../types/handlers/asset-historical-price.ts | 4 +- packages/snaps-utils/coverage.json | 6 +- .../handlers/asset-historical-price.test.ts | 74 ++++++++++++++++++- .../src/handlers/asset-historical-price.ts | 4 +- .../snaps-utils/src/handlers/exports.test.ts | 1 + 13 files changed, 119 insertions(+), 13 deletions(-) diff --git a/packages/snaps-execution-environments/lavamoat/browserify/iframe/policy.json b/packages/snaps-execution-environments/lavamoat/browserify/iframe/policy.json index 520b71350d..0db0d8199b 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/iframe/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/iframe/policy.json @@ -99,10 +99,16 @@ "packages": { "@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, + "@metamask/snaps-utils>luxon": true, "@metamask/superstruct": true, "@metamask/utils": true } }, + "@metamask/snaps-utils>luxon": { + "globals": { + "Intl": true + } + }, "@metamask/utils": { "globals": { "TextDecoder": 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 803b8ed933..3dc0877639 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/node-process/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/node-process/policy.json @@ -109,10 +109,16 @@ "packages": { "@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, + "@metamask/snaps-utils>luxon": true, "@metamask/superstruct": true, "@metamask/utils": true } }, + "@metamask/snaps-utils>luxon": { + "globals": { + "Intl": true + } + }, "@metamask/utils": { "builtin": { "buffer.Buffer": 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 803b8ed933..3dc0877639 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/node-thread/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/node-thread/policy.json @@ -109,10 +109,16 @@ "packages": { "@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, + "@metamask/snaps-utils>luxon": true, "@metamask/superstruct": true, "@metamask/utils": true } }, + "@metamask/snaps-utils>luxon": { + "globals": { + "Intl": true + } + }, "@metamask/utils": { "builtin": { "buffer.Buffer": true diff --git a/packages/snaps-execution-environments/lavamoat/browserify/webview/policy.json b/packages/snaps-execution-environments/lavamoat/browserify/webview/policy.json index 520b71350d..0db0d8199b 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/webview/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/webview/policy.json @@ -99,10 +99,16 @@ "packages": { "@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, + "@metamask/snaps-utils>luxon": true, "@metamask/superstruct": true, "@metamask/utils": true } }, + "@metamask/snaps-utils>luxon": { + "globals": { + "Intl": true + } + }, "@metamask/utils": { "globals": { "TextDecoder": 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 520b71350d..0db0d8199b 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/worker-executor/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/worker-executor/policy.json @@ -99,10 +99,16 @@ "packages": { "@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, + "@metamask/snaps-utils>luxon": true, "@metamask/superstruct": true, "@metamask/utils": true } }, + "@metamask/snaps-utils>luxon": { + "globals": { + "Intl": true + } + }, "@metamask/utils": { "globals": { "TextDecoder": 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 df5877fd7f..3ffd577da1 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/worker-pool/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/worker-pool/policy.json @@ -45,10 +45,16 @@ "packages": { "@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, + "@metamask/snaps-utils>luxon": true, "@metamask/superstruct": true, "@metamask/utils": true } }, + "@metamask/snaps-utils>luxon": { + "globals": { + "Intl": true + } + }, "@metamask/utils": { "globals": { "TextDecoder": true, diff --git a/packages/snaps-execution-environments/src/common/validation.ts b/packages/snaps-execution-environments/src/common/validation.ts index 83e91e55cd..9f37ab9665 100644 --- a/packages/snaps-execution-environments/src/common/validation.ts +++ b/packages/snaps-execution-environments/src/common/validation.ts @@ -128,16 +128,16 @@ export type RequestArguments = * Asserts that the given value is a valid request arguments object. * * @param value - The value to validate. - * @param requestArgumentsStruct - The struct to validate the value against. + * @param struct - The struct to validate the value against. * @throws If the value is not a valid request arguments object. */ function assertRequestArguments( value: unknown, - requestArgumentsStruct: Struct, + struct: Struct, ): asserts value is Struct { assertStruct( value, - requestArgumentsStruct, + struct, 'Invalid request params', rpcErrors.invalidParams, ); diff --git a/packages/snaps-rpc-methods/src/endowments/index.ts b/packages/snaps-rpc-methods/src/endowments/index.ts index c4d435d31e..60c68b1c01 100644 --- a/packages/snaps-rpc-methods/src/endowments/index.ts +++ b/packages/snaps-rpc-methods/src/endowments/index.ts @@ -126,6 +126,7 @@ export const handlerEndowments: Record = { [HandlerType.OnSettingsPage]: settingsPageEndowmentBuilder.targetName, [HandlerType.OnSignature]: signatureInsightEndowmentBuilder.targetName, [HandlerType.OnUserInput]: null, + [HandlerType.OnAssetHistoricalPrice]: assetsEndowmentBuilder.targetName, [HandlerType.OnAssetsLookup]: assetsEndowmentBuilder.targetName, [HandlerType.OnAssetsConversion]: assetsEndowmentBuilder.targetName, [HandlerType.OnProtocolRequest]: protocolEndowmentBuilder.targetName, diff --git a/packages/snaps-sdk/src/types/handlers/asset-historical-price.ts b/packages/snaps-sdk/src/types/handlers/asset-historical-price.ts index 5f063579d0..f14ab58216 100644 --- a/packages/snaps-sdk/src/types/handlers/asset-historical-price.ts +++ b/packages/snaps-sdk/src/types/handlers/asset-historical-price.ts @@ -8,7 +8,7 @@ export type HistoricalPriceValue = [number, string]; /** * The historical price object. - * The key is the time period as an ISO 8601 duration, the value is an array of historical price values. + * The key is the time period as an ISO 8601 duration or the "all" string, the value is an array of historical price values. */ export type HistoricalPriceIntervals = { [key: string]: HistoricalPriceValue[]; @@ -42,7 +42,7 @@ export type OnAssetHistoricalPriceArguments = { }; /** - * The `onAssetHistoricalPrice` handler. This is called by MetaMask when querying about historical price of an asset pair on specific chains. + * The `onAssetHistoricalPrice` handler. This is called by MetaMask when querying about the historical price of an asset pair on a specific chain. * * @returns The historical price of the asset pair. See * {@link OnAssetHistoricalPriceResponse}. diff --git a/packages/snaps-utils/coverage.json b/packages/snaps-utils/coverage.json index fe235fd33d..16472380bd 100644 --- a/packages/snaps-utils/coverage.json +++ b/packages/snaps-utils/coverage.json @@ -1,6 +1,6 @@ { "branches": 99.75, - "functions": 98.94, - "lines": 98.55, - "statements": 97.03 + "functions": 98.95, + "lines": 98.56, + "statements": 97.05 } diff --git a/packages/snaps-utils/src/handlers/asset-historical-price.test.ts b/packages/snaps-utils/src/handlers/asset-historical-price.test.ts index e02a95374a..821494caeb 100644 --- a/packages/snaps-utils/src/handlers/asset-historical-price.test.ts +++ b/packages/snaps-utils/src/handlers/asset-historical-price.test.ts @@ -7,8 +7,8 @@ import { } from './asset-historical-price'; describe('HistoricalPriceStruct', () => { - it('validates an object', () => { - const value = { + it.each([ + { P1D: [ [1737542312, '1'], [1737542312, '2'], @@ -17,8 +17,24 @@ describe('HistoricalPriceStruct', () => { [1737542312, '1'], [1737542312, '2'], ], - }; - + }, + { + all: [ + [1737542312, '1'], + [1737542312, '2'], + ], + }, + { + all: [ + [1737542312, '1'], + [1737542312, '2'], + ], + P1D: [ + [1737542312, '1'], + [1737542312, '2'], + ], + }, + ])('validates "%p"', (value) => { expect(is(value, HistoricalPriceStruct)).toBe(true); }); @@ -69,6 +85,28 @@ describe('AssetHistoricalPriceStruct', () => { }, updateTime: 1737542312, }, + { + intervals: { + all: [ + [1737542312, '1'], + [1737542312, '2'], + ], + }, + updateTime: 1737542312, + }, + { + intervals: { + all: [ + [1737542312, '1'], + [1737542312, '2'], + ], + P1W: [ + [1737542312, '1'], + [1737542312, '2'], + ], + }, + updateTime: 1737542312, + }, null, ])('validates an object', (value) => { expect(is(value, AssetHistoricalPriceStruct)).toBe(true); @@ -127,6 +165,34 @@ describe('OnAssetHistoricalPriceResponseStruct', () => { updateTime: 1737542312, }, }, + { + historicalPrice: { + intervals: { + all: [ + [1737542312, '1'], + [1737542312, '2'], + ], + }, + updateTime: 1737542312, + expirationTime: 1737542312, + }, + }, + { + historicalPrice: { + intervals: { + all: [ + [1737542312, '1'], + [1737542312, '2'], + ], + P1W: [ + [1737542312, '1'], + [1737542312, '2'], + ], + }, + updateTime: 1737542312, + expirationTime: 1737542312, + }, + }, { historicalPrice: null, }, diff --git a/packages/snaps-utils/src/handlers/asset-historical-price.ts b/packages/snaps-utils/src/handlers/asset-historical-price.ts index 8ed2a9a438..ae96ed268e 100644 --- a/packages/snaps-utils/src/handlers/asset-historical-price.ts +++ b/packages/snaps-utils/src/handlers/asset-historical-price.ts @@ -1,12 +1,14 @@ import { nonEmptyRecord } from '@metamask/snaps-sdk'; import { array, + literal, nullable, number, object, optional, string, tuple, + union, } from '@metamask/superstruct'; import { ISO8601DurationStruct } from '../time'; @@ -15,7 +17,7 @@ import { ISO8601DurationStruct } from '../time'; * A struct representing a historical price. */ export const HistoricalPriceStruct = nonEmptyRecord( - ISO8601DurationStruct, + union([literal('all'), ISO8601DurationStruct]), array(tuple([number(), string()])), ); diff --git a/packages/snaps-utils/src/handlers/exports.test.ts b/packages/snaps-utils/src/handlers/exports.test.ts index cb0a5b617d..3f1d445147 100644 --- a/packages/snaps-utils/src/handlers/exports.test.ts +++ b/packages/snaps-utils/src/handlers/exports.test.ts @@ -28,6 +28,7 @@ describe('SNAP_EXPORT_NAMES', () => { 'onUserInput', 'onAssetsLookup', 'onAssetsConversion', + 'onAssetHistoricalPrice', 'onProtocolRequest', ]); }); From 3c4e5b575f8aa408a10e151e15ab9ca0e070bd5e Mon Sep 17 00:00:00 2001 From: Guillaume Roux Date: Wed, 2 Apr 2025 15:51:45 +0200 Subject: [PATCH 05/10] fix after rebase --- packages/snaps-controllers/src/snaps/SnapController.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/snaps-controllers/src/snaps/SnapController.test.tsx b/packages/snaps-controllers/src/snaps/SnapController.test.tsx index 0668fd4ea5..6cf674e691 100644 --- a/packages/snaps-controllers/src/snaps/SnapController.test.tsx +++ b/packages/snaps-controllers/src/snaps/SnapController.test.tsx @@ -4401,7 +4401,7 @@ describe('SnapController', () => { await expect( snapController.handleRequest({ snapId: MOCK_SNAP_ID, - origin: 'foo.com', + origin: MOCK_ORIGIN, handler: HandlerType.OnAssetHistoricalPrice, request: { jsonrpc: '2.0', @@ -4468,7 +4468,7 @@ describe('SnapController', () => { expect( await snapController.handleRequest({ snapId: MOCK_SNAP_ID, - origin: 'foo.com', + origin: MOCK_ORIGIN, handler: HandlerType.OnAssetHistoricalPrice, request: { jsonrpc: '2.0', From 5a76eee4d54f66d965718cbccc88400bf7a08f35 Mon Sep 17 00:00:00 2001 From: Guillaume Roux Date: Wed, 2 Apr 2025 16:14:58 +0200 Subject: [PATCH 06/10] remove unnecessary exports to execution environments in `snaps-utils` --- .../lavamoat/browserify/iframe/policy.json | 6 ------ .../lavamoat/browserify/node-process/policy.json | 6 ------ .../lavamoat/browserify/node-thread/policy.json | 6 ------ .../lavamoat/browserify/webview/policy.json | 6 ------ .../lavamoat/browserify/worker-executor/policy.json | 6 ------ .../lavamoat/browserify/worker-pool/policy.json | 6 ------ packages/snaps-utils/src/index.executionenv.ts | 3 ++- 7 files changed, 2 insertions(+), 37 deletions(-) diff --git a/packages/snaps-execution-environments/lavamoat/browserify/iframe/policy.json b/packages/snaps-execution-environments/lavamoat/browserify/iframe/policy.json index 0db0d8199b..520b71350d 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/iframe/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/iframe/policy.json @@ -99,16 +99,10 @@ "packages": { "@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, - "@metamask/snaps-utils>luxon": true, "@metamask/superstruct": true, "@metamask/utils": true } }, - "@metamask/snaps-utils>luxon": { - "globals": { - "Intl": true - } - }, "@metamask/utils": { "globals": { "TextDecoder": 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 3dc0877639..803b8ed933 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/node-process/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/node-process/policy.json @@ -109,16 +109,10 @@ "packages": { "@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, - "@metamask/snaps-utils>luxon": true, "@metamask/superstruct": true, "@metamask/utils": true } }, - "@metamask/snaps-utils>luxon": { - "globals": { - "Intl": true - } - }, "@metamask/utils": { "builtin": { "buffer.Buffer": 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 3dc0877639..803b8ed933 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/node-thread/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/node-thread/policy.json @@ -109,16 +109,10 @@ "packages": { "@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, - "@metamask/snaps-utils>luxon": true, "@metamask/superstruct": true, "@metamask/utils": true } }, - "@metamask/snaps-utils>luxon": { - "globals": { - "Intl": true - } - }, "@metamask/utils": { "builtin": { "buffer.Buffer": true diff --git a/packages/snaps-execution-environments/lavamoat/browserify/webview/policy.json b/packages/snaps-execution-environments/lavamoat/browserify/webview/policy.json index 0db0d8199b..520b71350d 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/webview/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/webview/policy.json @@ -99,16 +99,10 @@ "packages": { "@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, - "@metamask/snaps-utils>luxon": true, "@metamask/superstruct": true, "@metamask/utils": true } }, - "@metamask/snaps-utils>luxon": { - "globals": { - "Intl": true - } - }, "@metamask/utils": { "globals": { "TextDecoder": 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 0db0d8199b..520b71350d 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/worker-executor/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/worker-executor/policy.json @@ -99,16 +99,10 @@ "packages": { "@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, - "@metamask/snaps-utils>luxon": true, "@metamask/superstruct": true, "@metamask/utils": true } }, - "@metamask/snaps-utils>luxon": { - "globals": { - "Intl": true - } - }, "@metamask/utils": { "globals": { "TextDecoder": 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 3ffd577da1..df5877fd7f 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/worker-pool/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/worker-pool/policy.json @@ -45,16 +45,10 @@ "packages": { "@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, - "@metamask/snaps-utils>luxon": true, "@metamask/superstruct": true, "@metamask/utils": true } }, - "@metamask/snaps-utils>luxon": { - "globals": { - "Intl": true - } - }, "@metamask/utils": { "globals": { "TextDecoder": true, diff --git a/packages/snaps-utils/src/index.executionenv.ts b/packages/snaps-utils/src/index.executionenv.ts index 231173cb3f..1fec2b333e 100644 --- a/packages/snaps-utils/src/index.executionenv.ts +++ b/packages/snaps-utils/src/index.executionenv.ts @@ -1,6 +1,7 @@ // Special entrypoint for execution environments for bundle sizing reasons export * from './errors'; -export * from './handlers'; +export type { SnapExports } from './handlers'; +export { HandlerType, SNAP_EXPORTS, SNAP_EXPORT_NAMES } from './handlers'; export * from './iframe'; export * from './logging'; export * from './types'; From 937e56a87598444f826a7ea38dae46c49cd412e1 Mon Sep 17 00:00:00 2001 From: Guillaume Roux Date: Wed, 2 Apr 2025 17:14:22 +0200 Subject: [PATCH 07/10] rebuild --- .../lavamoat/browserify/iframe/policy.json | 6 ++++++ .../lavamoat/browserify/node-process/policy.json | 6 ++++++ .../lavamoat/browserify/node-thread/policy.json | 6 ++++++ .../lavamoat/browserify/webview/policy.json | 6 ++++++ .../lavamoat/browserify/worker-executor/policy.json | 6 ++++++ .../lavamoat/browserify/worker-pool/policy.json | 6 ++++++ 6 files changed, 36 insertions(+) diff --git a/packages/snaps-execution-environments/lavamoat/browserify/iframe/policy.json b/packages/snaps-execution-environments/lavamoat/browserify/iframe/policy.json index 520b71350d..0db0d8199b 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/iframe/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/iframe/policy.json @@ -99,10 +99,16 @@ "packages": { "@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, + "@metamask/snaps-utils>luxon": true, "@metamask/superstruct": true, "@metamask/utils": true } }, + "@metamask/snaps-utils>luxon": { + "globals": { + "Intl": true + } + }, "@metamask/utils": { "globals": { "TextDecoder": 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 803b8ed933..3dc0877639 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/node-process/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/node-process/policy.json @@ -109,10 +109,16 @@ "packages": { "@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, + "@metamask/snaps-utils>luxon": true, "@metamask/superstruct": true, "@metamask/utils": true } }, + "@metamask/snaps-utils>luxon": { + "globals": { + "Intl": true + } + }, "@metamask/utils": { "builtin": { "buffer.Buffer": 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 803b8ed933..3dc0877639 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/node-thread/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/node-thread/policy.json @@ -109,10 +109,16 @@ "packages": { "@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, + "@metamask/snaps-utils>luxon": true, "@metamask/superstruct": true, "@metamask/utils": true } }, + "@metamask/snaps-utils>luxon": { + "globals": { + "Intl": true + } + }, "@metamask/utils": { "builtin": { "buffer.Buffer": true diff --git a/packages/snaps-execution-environments/lavamoat/browserify/webview/policy.json b/packages/snaps-execution-environments/lavamoat/browserify/webview/policy.json index 520b71350d..0db0d8199b 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/webview/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/webview/policy.json @@ -99,10 +99,16 @@ "packages": { "@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, + "@metamask/snaps-utils>luxon": true, "@metamask/superstruct": true, "@metamask/utils": true } }, + "@metamask/snaps-utils>luxon": { + "globals": { + "Intl": true + } + }, "@metamask/utils": { "globals": { "TextDecoder": 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 520b71350d..0db0d8199b 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/worker-executor/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/worker-executor/policy.json @@ -99,10 +99,16 @@ "packages": { "@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, + "@metamask/snaps-utils>luxon": true, "@metamask/superstruct": true, "@metamask/utils": true } }, + "@metamask/snaps-utils>luxon": { + "globals": { + "Intl": true + } + }, "@metamask/utils": { "globals": { "TextDecoder": 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 df5877fd7f..3ffd577da1 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/worker-pool/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/worker-pool/policy.json @@ -45,10 +45,16 @@ "packages": { "@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, + "@metamask/snaps-utils>luxon": true, "@metamask/superstruct": true, "@metamask/utils": true } }, + "@metamask/snaps-utils>luxon": { + "globals": { + "Intl": true + } + }, "@metamask/utils": { "globals": { "TextDecoder": true, From 6d04c7521c203bc0332866730d08c048bb45b21c Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Thu, 3 Apr 2025 10:28:16 +0200 Subject: [PATCH 08/10] Tweak exports to reduce bundle size --- packages/snaps-utils/src/index.executionenv.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/snaps-utils/src/index.executionenv.ts b/packages/snaps-utils/src/index.executionenv.ts index 1fec2b333e..65b7b13096 100644 --- a/packages/snaps-utils/src/index.executionenv.ts +++ b/packages/snaps-utils/src/index.executionenv.ts @@ -1,7 +1,7 @@ // Special entrypoint for execution environments for bundle sizing reasons export * from './errors'; -export type { SnapExports } from './handlers'; -export { HandlerType, SNAP_EXPORTS, SNAP_EXPORT_NAMES } from './handlers'; +export * from './handlers/exports'; +export * from './handlers/types'; export * from './iframe'; export * from './logging'; export * from './types'; From 40c42d8397a52b72dc3fd0df6e58983401d6ca8d Mon Sep 17 00:00:00 2001 From: Guillaume Roux Date: Thu, 3 Apr 2025 11:37:03 +0200 Subject: [PATCH 09/10] update coverage after rebase --- packages/snaps-controllers/coverage.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/snaps-controllers/coverage.json b/packages/snaps-controllers/coverage.json index dfab807b4a..14f89698f5 100644 --- a/packages/snaps-controllers/coverage.json +++ b/packages/snaps-controllers/coverage.json @@ -1,6 +1,6 @@ { - "branches": 93.41, + "branches": 93.42, "functions": 97.38, "lines": 98.34, - "statements": 98.07 + "statements": 98.08 } From 322f804dae36913ed97396b7e2b0e1a4b078af83 Mon Sep 17 00:00:00 2001 From: Guillaume Roux Date: Thu, 3 Apr 2025 11:40:04 +0200 Subject: [PATCH 10/10] update policies after not importing luxon --- .../lavamoat/browserify/iframe/policy.json | 6 ------ .../lavamoat/browserify/node-process/policy.json | 6 ------ .../lavamoat/browserify/node-thread/policy.json | 6 ------ .../lavamoat/browserify/webview/policy.json | 6 ------ .../lavamoat/browserify/worker-executor/policy.json | 6 ------ .../lavamoat/browserify/worker-pool/policy.json | 6 ------ 6 files changed, 36 deletions(-) diff --git a/packages/snaps-execution-environments/lavamoat/browserify/iframe/policy.json b/packages/snaps-execution-environments/lavamoat/browserify/iframe/policy.json index 0db0d8199b..520b71350d 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/iframe/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/iframe/policy.json @@ -99,16 +99,10 @@ "packages": { "@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, - "@metamask/snaps-utils>luxon": true, "@metamask/superstruct": true, "@metamask/utils": true } }, - "@metamask/snaps-utils>luxon": { - "globals": { - "Intl": true - } - }, "@metamask/utils": { "globals": { "TextDecoder": 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 3dc0877639..803b8ed933 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/node-process/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/node-process/policy.json @@ -109,16 +109,10 @@ "packages": { "@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, - "@metamask/snaps-utils>luxon": true, "@metamask/superstruct": true, "@metamask/utils": true } }, - "@metamask/snaps-utils>luxon": { - "globals": { - "Intl": true - } - }, "@metamask/utils": { "builtin": { "buffer.Buffer": 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 3dc0877639..803b8ed933 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/node-thread/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/node-thread/policy.json @@ -109,16 +109,10 @@ "packages": { "@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, - "@metamask/snaps-utils>luxon": true, "@metamask/superstruct": true, "@metamask/utils": true } }, - "@metamask/snaps-utils>luxon": { - "globals": { - "Intl": true - } - }, "@metamask/utils": { "builtin": { "buffer.Buffer": true diff --git a/packages/snaps-execution-environments/lavamoat/browserify/webview/policy.json b/packages/snaps-execution-environments/lavamoat/browserify/webview/policy.json index 0db0d8199b..520b71350d 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/webview/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/webview/policy.json @@ -99,16 +99,10 @@ "packages": { "@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, - "@metamask/snaps-utils>luxon": true, "@metamask/superstruct": true, "@metamask/utils": true } }, - "@metamask/snaps-utils>luxon": { - "globals": { - "Intl": true - } - }, "@metamask/utils": { "globals": { "TextDecoder": 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 0db0d8199b..520b71350d 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/worker-executor/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/worker-executor/policy.json @@ -99,16 +99,10 @@ "packages": { "@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, - "@metamask/snaps-utils>luxon": true, "@metamask/superstruct": true, "@metamask/utils": true } }, - "@metamask/snaps-utils>luxon": { - "globals": { - "Intl": true - } - }, "@metamask/utils": { "globals": { "TextDecoder": 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 3ffd577da1..df5877fd7f 100644 --- a/packages/snaps-execution-environments/lavamoat/browserify/worker-pool/policy.json +++ b/packages/snaps-execution-environments/lavamoat/browserify/worker-pool/policy.json @@ -45,16 +45,10 @@ "packages": { "@metamask/rpc-errors": true, "@metamask/snaps-sdk": true, - "@metamask/snaps-utils>luxon": true, "@metamask/superstruct": true, "@metamask/utils": true } }, - "@metamask/snaps-utils>luxon": { - "globals": { - "Intl": true - } - }, "@metamask/utils": { "globals": { "TextDecoder": true,