From 9682831cbc493ccf50ee2827d3db3119e8420af7 Mon Sep 17 00:00:00 2001 From: Julien Fontanel Date: Fri, 28 Aug 2026 12:00:19 +0200 Subject: [PATCH 1/5] feat(solana-wallet-snap): use shareable serialization in Solana snap --- eslint-suppressions.json | 25 ----- .../src/core/caching/InMemoryCache.ts | 4 +- .../src/core/caching/StateCache.ts | 4 +- .../src/core/caching/types.ts | 2 +- .../src/core/caching/useCache.test.ts | 2 +- .../src/core/caching/useCache.ts | 3 +- .../core/clients/nft-api/NftApiClient.test.ts | 3 +- .../src/core/clients/nft-api/NftApiClient.ts | 2 +- .../clients/price-api/PriceApiClient.test.ts | 2 +- .../core/clients/price-api/PriceApiClient.ts | 3 +- .../refreshConfirmationEstimation.test.tsx | 5 +- .../refreshConfirmationEstimation.tsx | 2 +- .../core/serialization/deserialize.test.ts | 95 ---------------- .../src/core/serialization/deserialize.ts | 37 ------ .../src/core/serialization/serialize.test.ts | 105 ------------------ .../src/core/serialization/serialize.ts | 47 -------- .../src/core/serialization/types.ts | 17 --- .../services/assets/AssetsService.test.ts | 2 +- .../assets/adapters/SnapAssetsAdapter.test.ts | 2 +- .../assets/adapters/SnapAssetsAdapter.ts | 3 +- .../connection/SolanaConnection.test.ts | 2 +- .../services/connection/SolanaConnection.ts | 2 +- .../core/services/send/SendService.test.ts | 2 +- .../src/core/services/send/SendService.ts | 3 +- .../src/core/services/state/IStateManager.ts | 2 +- .../src/core/services/state/InMemoryState.ts | 3 +- .../src/core/services/state/State.ts | 10 +- .../src/core/utils/interface.ts | 11 +- .../src/entities/subscriptions.ts | 2 +- .../components/Instruction/Instruction.tsx | 2 +- .../solana-wallet-snap/src/snapContext.ts | 2 +- 31 files changed, 38 insertions(+), 368 deletions(-) delete mode 100644 packages/solana-wallet-snap/src/core/serialization/deserialize.test.ts delete mode 100644 packages/solana-wallet-snap/src/core/serialization/deserialize.ts delete mode 100644 packages/solana-wallet-snap/src/core/serialization/serialize.test.ts delete mode 100644 packages/solana-wallet-snap/src/core/serialization/serialize.ts delete mode 100644 packages/solana-wallet-snap/src/core/serialization/types.ts diff --git a/eslint-suppressions.json b/eslint-suppressions.json index f605383ed..802cb4be7 100644 --- a/eslint-suppressions.json +++ b/eslint-suppressions.json @@ -277,31 +277,6 @@ "count": 1 } }, - "packages/solana-wallet-snap/src/core/serialization/deserialize.test.ts": { - "import-x/no-named-as-default": { - "count": 1 - } - }, - "packages/solana-wallet-snap/src/core/serialization/deserialize.ts": { - "import-x/no-named-as-default": { - "count": 1 - } - }, - "packages/solana-wallet-snap/src/core/serialization/serialize.test.ts": { - "import-x/no-named-as-default": { - "count": 1 - } - }, - "packages/solana-wallet-snap/src/core/serialization/serialize.ts": { - "import-x/no-named-as-default": { - "count": 1 - } - }, - "packages/solana-wallet-snap/src/core/serialization/types.ts": { - "import-x/no-named-as-default": { - "count": 1 - } - }, "packages/solana-wallet-snap/src/core/services/__mocks__/mockConnection.ts": { "@typescript-eslint/explicit-function-return-type": { "count": 9 diff --git a/packages/solana-wallet-snap/src/core/caching/InMemoryCache.ts b/packages/solana-wallet-snap/src/core/caching/InMemoryCache.ts index aa3cdd221..fd38a2251 100644 --- a/packages/solana-wallet-snap/src/core/caching/InMemoryCache.ts +++ b/packages/solana-wallet-snap/src/core/caching/InMemoryCache.ts @@ -1,7 +1,5 @@ -import type { Logger } from '@metamask/snap-networks-utils'; +import type { Logger, Serializable } from '@metamask/snap-networks-utils'; import { assert } from '@metamask/utils'; - -import type { Serializable } from '../serialization/types'; import type { ICache } from './ICache'; import type { CacheEntry } from './types'; diff --git a/packages/solana-wallet-snap/src/core/caching/StateCache.ts b/packages/solana-wallet-snap/src/core/caching/StateCache.ts index c3f113459..21082a881 100644 --- a/packages/solana-wallet-snap/src/core/caching/StateCache.ts +++ b/packages/solana-wallet-snap/src/core/caching/StateCache.ts @@ -1,7 +1,5 @@ -import type { Logger } from '@metamask/snap-networks-utils'; +import type { Logger, Serializable } from '@metamask/snap-networks-utils'; import { assert } from '@metamask/utils'; - -import type { Serializable } from '../serialization/types'; import type { IStateManager } from '../services/state/IStateManager'; import defaultLogger from '../utils/logger'; import type { ICache } from './ICache'; diff --git a/packages/solana-wallet-snap/src/core/caching/types.ts b/packages/solana-wallet-snap/src/core/caching/types.ts index a06842d0b..e18316b31 100644 --- a/packages/solana-wallet-snap/src/core/caching/types.ts +++ b/packages/solana-wallet-snap/src/core/caching/types.ts @@ -1,4 +1,4 @@ -import type { Serializable } from '../serialization/types'; +import type { Serializable } from '@metamask/snap-networks-utils'; export type TimestampMilliseconds = number; diff --git a/packages/solana-wallet-snap/src/core/caching/useCache.test.ts b/packages/solana-wallet-snap/src/core/caching/useCache.test.ts index a5bc70236..5d9eb3dc3 100644 --- a/packages/solana-wallet-snap/src/core/caching/useCache.test.ts +++ b/packages/solana-wallet-snap/src/core/caching/useCache.test.ts @@ -1,4 +1,4 @@ -import type { Serializable } from '../serialization/types'; +import type { Serializable } from '@metamask/snap-networks-utils'; import type { ICache } from './ICache'; import { useCache } from './useCache'; import type { CacheOptions } from './useCache'; diff --git a/packages/solana-wallet-snap/src/core/caching/useCache.ts b/packages/solana-wallet-snap/src/core/caching/useCache.ts index aae865597..028f2584c 100644 --- a/packages/solana-wallet-snap/src/core/caching/useCache.ts +++ b/packages/solana-wallet-snap/src/core/caching/useCache.ts @@ -1,6 +1,7 @@ /* eslint-disable no-void */ -import type { Serializable } from '../serialization/types'; +import type { Serializable } from '@metamask/snap-networks-utils'; + import logger from '../utils/logger'; import type { ICache } from './ICache'; diff --git a/packages/solana-wallet-snap/src/core/clients/nft-api/NftApiClient.test.ts b/packages/solana-wallet-snap/src/core/clients/nft-api/NftApiClient.test.ts index 5d64bdecf..77e27281a 100644 --- a/packages/solana-wallet-snap/src/core/clients/nft-api/NftApiClient.test.ts +++ b/packages/solana-wallet-snap/src/core/clients/nft-api/NftApiClient.test.ts @@ -1,6 +1,7 @@ +import type { Serializable } from '@metamask/snap-networks-utils'; + import type { ICache } from '../../caching/ICache'; import { InMemoryCache } from '../../caching/InMemoryCache'; -import type { Serializable } from '../../serialization/types'; import { mockLogger } from '../../services/__mocks__/logger'; import type { ConfigProvider } from '../../services/config'; import { trackError } from '../../utils/errors'; diff --git a/packages/solana-wallet-snap/src/core/clients/nft-api/NftApiClient.ts b/packages/solana-wallet-snap/src/core/clients/nft-api/NftApiClient.ts index 8ecd907d6..72d248eab 100644 --- a/packages/solana-wallet-snap/src/core/clients/nft-api/NftApiClient.ts +++ b/packages/solana-wallet-snap/src/core/clients/nft-api/NftApiClient.ts @@ -1,11 +1,11 @@ /* eslint-disable @typescript-eslint/naming-convention */ import { UrlStruct, buildUrl } from '@metamask/snap-networks-utils'; +import type { Serializable } from '@metamask/snap-networks-utils'; import { assert } from '@metamask/superstruct'; import type { ICache } from '../../caching/ICache'; import { useCache } from '../../caching/useCache'; -import type { Serializable } from '../../serialization/types'; import type { ConfigProvider } from '../../services/config'; import { trackError } from '../../utils/errors'; import type { diff --git a/packages/solana-wallet-snap/src/core/clients/price-api/PriceApiClient.test.ts b/packages/solana-wallet-snap/src/core/clients/price-api/PriceApiClient.test.ts index 95dc00600..cba741ba4 100644 --- a/packages/solana-wallet-snap/src/core/clients/price-api/PriceApiClient.test.ts +++ b/packages/solana-wallet-snap/src/core/clients/price-api/PriceApiClient.test.ts @@ -1,11 +1,11 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ import type { CaipAssetType } from '@metamask/keyring-api'; +import type { Serializable } from '@metamask/snap-networks-utils'; import { cloneDeep } from 'lodash'; import type { ICache } from '../../caching/ICache'; import { InMemoryCache } from '../../caching/InMemoryCache'; import { KnownCaip19Id } from '../../constants/solana'; -import type { Serializable } from '../../serialization/types'; import { mockLogger } from '../../services/__mocks__/logger'; import type { ConfigProvider } from '../../services/config'; import { MOCK_EXCHANGE_RATES } from '../../test/mocks/price-api/exchange-rates'; diff --git a/packages/solana-wallet-snap/src/core/clients/price-api/PriceApiClient.ts b/packages/solana-wallet-snap/src/core/clients/price-api/PriceApiClient.ts index 3baa2ca72..a1b506eaf 100644 --- a/packages/solana-wallet-snap/src/core/clients/price-api/PriceApiClient.ts +++ b/packages/solana-wallet-snap/src/core/clients/price-api/PriceApiClient.ts @@ -2,14 +2,13 @@ import type { CaipAssetType } from '@metamask/keyring-api'; import { UrlStruct, buildUrl } from '@metamask/snap-networks-utils'; -import type { Logger } from '@metamask/snap-networks-utils'; +import type { Logger, Serializable } from '@metamask/snap-networks-utils'; import { array, assert } from '@metamask/superstruct'; import { CaipAssetTypeStruct } from '@metamask/utils'; import { mapKeys } from 'lodash'; import type { ICache } from '../../caching/ICache'; import { useCache } from '../../caching/useCache'; -import type { Serializable } from '../../serialization/types'; import type { ConfigProvider } from '../../services/config'; import logger from '../../utils/logger'; import type { diff --git a/packages/solana-wallet-snap/src/core/handlers/onCronjob/backgroundEvents/refreshConfirmationEstimation.test.tsx b/packages/solana-wallet-snap/src/core/handlers/onCronjob/backgroundEvents/refreshConfirmationEstimation.test.tsx index bf02d1cf9..248a85582 100644 --- a/packages/solana-wallet-snap/src/core/handlers/onCronjob/backgroundEvents/refreshConfirmationEstimation.test.tsx +++ b/packages/solana-wallet-snap/src/core/handlers/onCronjob/backgroundEvents/refreshConfirmationEstimation.test.tsx @@ -1,9 +1,9 @@ import { SolMethod } from '@metamask/keyring-api'; +import { serialize } from '@metamask/snap-networks-utils'; import type { JsonRpcParams, JsonRpcRequest } from '@metamask/utils'; import { transactionScanService, state } from '../../../../snapContext'; import { METAMASK_ORIGIN, Network } from '../../../constants/solana'; -import { serialize } from '../../../serialization/serialize'; import { EXPIRED_TRANSACTION_SCAN } from '../../../services/transaction-scan/buildExpiredScanResult'; import { isTransactionBlockhashExpired } from '../../../services/transaction-scan/isTransactionBlockhashExpired'; import { trackError } from '../../../utils/errors'; @@ -21,7 +21,8 @@ jest.mock('../../../utils/errors', () => ({ trackError: jest.fn().mockResolvedValue('tracked-error-id'), })); -jest.mock('../../../serialization/serialize', () => ({ +jest.mock('@metamask/snap-networks-utils', () => ({ + ...jest.requireActual('@metamask/snap-networks-utils'), serialize: jest.fn((value) => value), })); diff --git a/packages/solana-wallet-snap/src/core/handlers/onCronjob/backgroundEvents/refreshConfirmationEstimation.tsx b/packages/solana-wallet-snap/src/core/handlers/onCronjob/backgroundEvents/refreshConfirmationEstimation.tsx index 3af29b15d..474f941f8 100644 --- a/packages/solana-wallet-snap/src/core/handlers/onCronjob/backgroundEvents/refreshConfirmationEstimation.tsx +++ b/packages/solana-wallet-snap/src/core/handlers/onCronjob/backgroundEvents/refreshConfirmationEstimation.tsx @@ -1,3 +1,4 @@ +import { serialize } from '@metamask/snap-networks-utils'; import type { OnCronjobHandler } from '@metamask/snaps-sdk'; import { ConfirmTransactionRequest } from '../../../../features/confirmation/views/ConfirmTransactionRequest/ConfirmTransactionRequest'; @@ -8,7 +9,6 @@ import { transactionScanService, } from '../../../../snapContext'; import { METAMASK_ORIGIN } from '../../../constants/solana'; -import { serialize } from '../../../serialization/serialize'; import type { UnencryptedStateValue } from '../../../services/state/State'; import { EXPIRED_TRANSACTION_SCAN } from '../../../services/transaction-scan/buildExpiredScanResult'; import { isTransactionBlockhashExpired } from '../../../services/transaction-scan/isTransactionBlockhashExpired'; diff --git a/packages/solana-wallet-snap/src/core/serialization/deserialize.test.ts b/packages/solana-wallet-snap/src/core/serialization/deserialize.test.ts deleted file mode 100644 index 34362a2de..000000000 --- a/packages/solana-wallet-snap/src/core/serialization/deserialize.test.ts +++ /dev/null @@ -1,95 +0,0 @@ -/* eslint-disable jest/prefer-strict-equal */ - -import BigNumber from 'bignumber.js'; - -import { deserialize } from './deserialize'; - -describe('deserialize', () => { - it('deserializes primitive values', () => { - expect(deserialize('test')).toBe('test'); - expect(deserialize(42)).toBe(42); - expect(deserialize(true)).toBe(true); - expect(deserialize(null)).toBeNull(); - }); - - it('deserializes special serialized types', () => { - expect(deserialize({ __type: 'undefined' })).toBeUndefined(); - expect( - deserialize({ __type: 'bigint', value: '9007199254740991' }), - ).toStrictEqual(BigInt(9007199254740991)); - expect( - deserialize({ __type: 'BigNumber', value: '123456789.123456789' }), - ).toStrictEqual(new BigNumber('123456789.123456789')); - }); - - it('deserializes arrays with mixed types', () => { - expect( - deserialize([ - 1, - 'hello', - true, - null, - { __type: 'undefined' }, - { __type: 'bigint', value: '9007199254740991' }, - { __type: 'BigNumber', value: '123456789.123456789' }, - ]), - ).toEqual([ - 1, - 'hello', - true, - null, - undefined, - BigInt(9007199254740991), - new BigNumber('123456789.123456789'), - ]); - }); - - it('deserializes objects with nested structures', () => { - const input = { - nested: { - bigNumber: { __type: 'BigNumber', value: '123.456' }, - bigint: { __type: 'bigint', value: '9007199254740991' }, - undefined: { __type: 'undefined' }, - }, - array: [ - { __type: 'BigNumber', value: '789.012' }, - { __type: 'bigint', value: '9007199254740992' }, - ], - }; - - const result = deserialize(input); - - expect(result).toEqual({ - nested: { - bigNumber: new BigNumber('123.456'), - bigint: BigInt('9007199254740991'), - undefined, - }, - array: [new BigNumber('789.012'), BigInt('9007199254740992')], - }); - }); - - it('handles non-undefined falsy values correctly', () => { - const input = { - zero: 0, - emptyString: '', - falseValue: false, - nullValue: null, - }; - - const result = deserialize(input); - - expect(result).toStrictEqual({ - zero: 0, - emptyString: '', - falseValue: false, - nullValue: null, - }); - }); - - it('deserializes Uint8Array', () => { - const input = { __type: 'Uint8Array', value: 'AQID' }; - const result = deserialize(input); - expect(result).toStrictEqual(new Uint8Array([1, 2, 3])); - }); -}); diff --git a/packages/solana-wallet-snap/src/core/serialization/deserialize.ts b/packages/solana-wallet-snap/src/core/serialization/deserialize.ts deleted file mode 100644 index 4e352e443..000000000 --- a/packages/solana-wallet-snap/src/core/serialization/deserialize.ts +++ /dev/null @@ -1,37 +0,0 @@ -import type { Json } from '@metamask/snaps-sdk'; -import { getBase64Codec } from '@solana/kit'; -import BigNumber from 'bignumber.js'; - -import type { Serializable } from './types'; - -/** - * Deserializes the passed value from a JSON object to an object with its the original values. - * It transforms the JSON-serializable representation of non-JSON-serializable values back into their original values. - * - * @param serializedValue - The value to deserialize. - * @returns The deserialized value. - */ -export const deserialize = (serializedValue: Json): Serializable => - JSON.parse(JSON.stringify(serializedValue), (_key, value) => { - if (!value) { - return value; - } - - if (value.__type === 'undefined') { - return undefined; - } - - if (value.__type === 'BigNumber') { - return new BigNumber(value.value); - } - - if (value.__type === 'bigint') { - return BigInt(value.value); - } - - if (value.__type === 'Uint8Array') { - return getBase64Codec().encode(value.value); - } - - return value; - }); diff --git a/packages/solana-wallet-snap/src/core/serialization/serialize.test.ts b/packages/solana-wallet-snap/src/core/serialization/serialize.test.ts deleted file mode 100644 index 85dbda83c..000000000 --- a/packages/solana-wallet-snap/src/core/serialization/serialize.test.ts +++ /dev/null @@ -1,105 +0,0 @@ -import BigNumber from 'bignumber.js'; - -import { serialize } from './serialize'; - -describe('serialize', () => { - it('serializes primitive values', () => { - expect(serialize('test')).toBe('test'); - expect(serialize(42)).toBe(42); - expect(serialize(true)).toBe(true); - expect(serialize(null)).toBeNull(); - expect(serialize(undefined)).toStrictEqual({ __type: 'undefined' }); - }); - - it('serializes special types', () => { - expect(serialize(BigInt(9007199254740991))).toStrictEqual({ - __type: 'bigint', - value: '9007199254740991', - }); - expect(serialize(new BigNumber('123456789.123456789'))).toStrictEqual({ - __type: 'BigNumber', - value: '123456789.123456789', - }); - }); - - it('serializes arrays with mixed types', () => { - const input = [undefined, new BigNumber('123'), BigInt('456')]; - const result = serialize(input); - expect(result).toStrictEqual([ - { __type: 'undefined' }, - { __type: 'BigNumber', value: '123' }, - { __type: 'bigint', value: '456' }, - ]); - }); - - it('serializes objects with nested structures', () => { - const input = { - nested: { - bigNumber: new BigNumber('123.456'), - bigint: BigInt('9007199254740991'), - undefined, - }, - array: [new BigNumber('789.012'), BigInt('9007199254740992')], - }; - - const result = serialize(input); - - expect(result).toStrictEqual({ - nested: { - bigNumber: { __type: 'BigNumber', value: '123.456' }, - bigint: { __type: 'bigint', value: '9007199254740991' }, - undefined: { __type: 'undefined' }, - }, - array: [ - { __type: 'BigNumber', value: '789.012' }, - { __type: 'bigint', value: '9007199254740992' }, - ], - }); - }); - - it('serializes empty objects and arrays', () => { - const input = { - emptyObject: {}, - emptyArray: [], - }; - - const result = serialize(input); - - expect(result).toStrictEqual(input); - }); - - it('serializes deeply nested structures', () => { - const input = { - level1: { - level2: { - level3: { - bigint: BigInt('123'), - undefined, - }, - }, - }, - }; - - const result = serialize(input); - - expect(result).toStrictEqual({ - level1: { - level2: { - level3: { - bigint: { __type: 'bigint', value: '123' }, - undefined: { __type: 'undefined' }, - }, - }, - }, - }); - }); - - it('serializes Uint8Array', () => { - const input = new Uint8Array([1, 2, 3]); - const result = serialize(input); - expect(result).toStrictEqual({ - __type: 'Uint8Array', - value: 'AQID', - }); - }); -}); diff --git a/packages/solana-wallet-snap/src/core/serialization/serialize.ts b/packages/solana-wallet-snap/src/core/serialization/serialize.ts deleted file mode 100644 index 824003cf1..000000000 --- a/packages/solana-wallet-snap/src/core/serialization/serialize.ts +++ /dev/null @@ -1,47 +0,0 @@ -import type { Json } from '@metamask/snaps-sdk'; -import { getBase64Codec } from '@solana/kit'; -import BigNumber from 'bignumber.js'; -import { cloneDeepWith } from 'lodash'; - -import type { Serializable } from './types'; - -/** - * Serializes the passed value to a JSON object so it can be stored in JSON-serializable storage like the snap state and interface context. - * It transforms non-JSON-serializable values into a specific JSON-serializable representation that can be deserialized later. - * - * @param value - The value to serialize. - * @returns The serialized value. - * @throws If an unsupported case is encountered. This indicates a missing implementation. - */ -export const serialize = (value: Serializable): Record => - cloneDeepWith(value, (val) => { - if (val === undefined) { - return { - __type: 'undefined', - }; - } - - if (val instanceof BigNumber) { - return { - __type: 'BigNumber', - value: val.toString(), - }; - } - - if (typeof val === 'bigint') { - return { - __type: 'bigint', - value: val.toString(), - }; - } - - if (val instanceof Uint8Array) { - return { - __type: 'Uint8Array', - value: getBase64Codec().decode(val), - }; - } - - // Return undefined to let lodash handle the cloning of other values - return undefined; - }); diff --git a/packages/solana-wallet-snap/src/core/serialization/types.ts b/packages/solana-wallet-snap/src/core/serialization/types.ts deleted file mode 100644 index ad86620e7..000000000 --- a/packages/solana-wallet-snap/src/core/serialization/types.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { Json } from '@metamask/snaps-sdk'; -import type BigNumber from 'bignumber.js'; - -/** - * A primitive value that can be serialized to JSON using the `serialize` function. - */ -export type Serializable = - | Json - | undefined - | null - | bigint - | BigNumber - | Uint8Array - | Serializable[] - | { - [prop: string]: Serializable; - }; diff --git a/packages/solana-wallet-snap/src/core/services/assets/AssetsService.test.ts b/packages/solana-wallet-snap/src/core/services/assets/AssetsService.test.ts index 7ddfc10c0..5cf6ccf95 100644 --- a/packages/solana-wallet-snap/src/core/services/assets/AssetsService.test.ts +++ b/packages/solana-wallet-snap/src/core/services/assets/AssetsService.test.ts @@ -1,5 +1,6 @@ import { KeyringEvent } from '@metamask/keyring-api'; import { emitSnapKeyringEvent } from '@metamask/keyring-snap-sdk'; +import type { Serializable } from '@metamask/snap-networks-utils'; import { cloneDeep } from 'lodash'; import type { ICache } from '../../caching/ICache'; @@ -8,7 +9,6 @@ import { MOCK_NFTS_LIST_RESPONSE_MAPPED } from '../../clients/nft-api/mocks/mock import type { NftApiClient } from '../../clients/nft-api/NftApiClient'; import type { TokenApiClient } from '../../clients/token-api-client/TokenApiClient'; import { Network } from '../../constants/solana'; -import type { Serializable } from '../../serialization/types'; import { MOCK_ASSET_ENTITIES, MOCK_ASSET_ENTITY_0, diff --git a/packages/solana-wallet-snap/src/core/services/assets/adapters/SnapAssetsAdapter.test.ts b/packages/solana-wallet-snap/src/core/services/assets/adapters/SnapAssetsAdapter.test.ts index 3d46e21c1..1f9be1274 100644 --- a/packages/solana-wallet-snap/src/core/services/assets/adapters/SnapAssetsAdapter.test.ts +++ b/packages/solana-wallet-snap/src/core/services/assets/adapters/SnapAssetsAdapter.test.ts @@ -1,3 +1,4 @@ +import type { Serializable } from '@metamask/snap-networks-utils'; import { cloneDeep } from 'lodash'; import type { ICache } from '../../../caching/ICache'; @@ -5,7 +6,6 @@ import { InMemoryCache } from '../../../caching/InMemoryCache'; import { MOCK_NFTS_LIST_RESPONSE_MAPPED } from '../../../clients/nft-api/mocks/mockNftsListResponseMapped'; import type { NftApiClient } from '../../../clients/nft-api/NftApiClient'; import type { TokenApiClient } from '../../../clients/token-api-client/TokenApiClient'; -import type { Serializable } from '../../../serialization/types'; import { MOCK_ASSET_ENTITY_0, MOCK_ASSET_ENTITY_1, diff --git a/packages/solana-wallet-snap/src/core/services/assets/adapters/SnapAssetsAdapter.ts b/packages/solana-wallet-snap/src/core/services/assets/adapters/SnapAssetsAdapter.ts index 5bc27c123..c84d13e3e 100644 --- a/packages/solana-wallet-snap/src/core/services/assets/adapters/SnapAssetsAdapter.ts +++ b/packages/solana-wallet-snap/src/core/services/assets/adapters/SnapAssetsAdapter.ts @@ -6,7 +6,7 @@ import type { Balance, } from '@metamask/keyring-api'; import { emitSnapKeyringEvent } from '@metamask/keyring-snap-sdk'; -import type { Logger } from '@metamask/snap-networks-utils'; +import type { Logger, Serializable } from '@metamask/snap-networks-utils'; import type { FungibleAssetMarketData, FungibleAssetMetadata, @@ -40,7 +40,6 @@ import type { TokenCaipAssetType, } from '../../../constants/solana'; import type { TokenAccountInfoWithJsonData } from '../../../sdk-extensions/rpc-api'; -import type { Serializable } from '../../../serialization/types'; import { fromTokenUnits } from '../../../utils/fromTokenUnit'; import { getNetworkFromToken } from '../../../utils/getNetworkFromToken'; import { tokenAddressToCaip19 } from '../../../utils/tokenAddressToCaip19'; diff --git a/packages/solana-wallet-snap/src/core/services/connection/SolanaConnection.test.ts b/packages/solana-wallet-snap/src/core/services/connection/SolanaConnection.test.ts index 257b539c7..721867c6a 100644 --- a/packages/solana-wallet-snap/src/core/services/connection/SolanaConnection.test.ts +++ b/packages/solana-wallet-snap/src/core/services/connection/SolanaConnection.test.ts @@ -1,11 +1,11 @@ /* eslint-disable @typescript-eslint/no-require-imports */ +import type { Serializable } from '@metamask/snap-networks-utils'; import { fetchJsonParsedAccount } from '@solana/kit'; import type { ICache } from '../../caching/ICache'; import { InMemoryCache } from '../../caching/InMemoryCache'; import { KnownCaip19Id, Network } from '../../constants/solana'; -import type { Serializable } from '../../serialization/types'; import { mockLogger } from '../__mocks__/logger'; import { MOCK_JSON_PARSED_ACCOUNT, diff --git a/packages/solana-wallet-snap/src/core/services/connection/SolanaConnection.ts b/packages/solana-wallet-snap/src/core/services/connection/SolanaConnection.ts index 333f0a4a2..4f889e719 100644 --- a/packages/solana-wallet-snap/src/core/services/connection/SolanaConnection.ts +++ b/packages/solana-wallet-snap/src/core/services/connection/SolanaConnection.ts @@ -1,3 +1,4 @@ +import type { Serializable } from '@metamask/snap-networks-utils'; import { assert } from '@metamask/superstruct'; import { Duration } from '@metamask/utils'; import { fetchMint } from '@solana-program/token-2022'; @@ -20,7 +21,6 @@ import type { Rpc, SolanaRpcApi } from '@solana/kit'; import type { ICache } from '../../caching/ICache'; import { useCache } from '../../caching/useCache'; import type { Network } from '../../constants/solana'; -import type { Serializable } from '../../serialization/types'; import { NetworkStruct } from '../../validation/structs'; import type { ConfigProvider } from '../config/ConfigProvider'; import { createMainTransport } from './transport'; diff --git a/packages/solana-wallet-snap/src/core/services/send/SendService.test.ts b/packages/solana-wallet-snap/src/core/services/send/SendService.test.ts index 52e2a49f9..511982d7e 100644 --- a/packages/solana-wallet-snap/src/core/services/send/SendService.test.ts +++ b/packages/solana-wallet-snap/src/core/services/send/SendService.test.ts @@ -1,4 +1,5 @@ import { SolMethod } from '@metamask/keyring-api'; +import type { Serializable } from '@metamask/snap-networks-utils'; import { lamports } from '@solana/kit'; import type { AssetEntity, SolanaKeyringAccount } from '../../../entities'; @@ -13,7 +14,6 @@ import { import { ClientRequestMethod } from '../../handlers/onClientRequest/types'; import type { SolanaKeyring } from '../../handlers/onKeyringRequest/Keyring'; import { fromTransactionToBase64String } from '../../sdk-extensions/codecs'; -import type { Serializable } from '../../serialization/types'; import { MOCK_SOLANA_KEYRING_ACCOUNT_0, MOCK_SOLANA_KEYRING_ACCOUNT_1, diff --git a/packages/solana-wallet-snap/src/core/services/send/SendService.ts b/packages/solana-wallet-snap/src/core/services/send/SendService.ts index 225ed45dc..92cd1787f 100644 --- a/packages/solana-wallet-snap/src/core/services/send/SendService.ts +++ b/packages/solana-wallet-snap/src/core/services/send/SendService.ts @@ -1,6 +1,6 @@ import type { KeyringRequest } from '@metamask/keyring-api'; import { SolMethod } from '@metamask/keyring-api'; -import type { Logger } from '@metamask/snap-networks-utils'; +import type { Logger, Serializable } from '@metamask/snap-networks-utils'; import type { Json } from '@metamask/snaps-sdk'; import { Duration, parseCaipAssetType } from '@metamask/utils'; import { address as asAddress, compileTransaction } from '@solana/kit'; @@ -12,7 +12,6 @@ import type { Network } from '../../constants/solana'; import { METAMASK_ORIGIN, Networks } from '../../constants/solana'; import type { SolanaKeyring } from '../../handlers/onKeyringRequest/Keyring'; import { fromTransactionToBase64String } from '../../sdk-extensions/codecs'; -import type { Serializable } from '../../serialization/types'; import { solToLamports } from '../../utils/conversion'; import type { AssetsService } from '../assets'; import type { SolanaConnection } from '../connection'; diff --git a/packages/solana-wallet-snap/src/core/services/state/IStateManager.ts b/packages/solana-wallet-snap/src/core/services/state/IStateManager.ts index 685121cfb..22367d8c8 100644 --- a/packages/solana-wallet-snap/src/core/services/state/IStateManager.ts +++ b/packages/solana-wallet-snap/src/core/services/state/IStateManager.ts @@ -1,4 +1,4 @@ -import type { Serializable } from '../../serialization/types'; +import type { Serializable } from '@metamask/snap-networks-utils'; export type IStateManager> = { /** diff --git a/packages/solana-wallet-snap/src/core/services/state/InMemoryState.ts b/packages/solana-wallet-snap/src/core/services/state/InMemoryState.ts index a3ea16450..0b0aaf9ea 100644 --- a/packages/solana-wallet-snap/src/core/services/state/InMemoryState.ts +++ b/packages/solana-wallet-snap/src/core/services/state/InMemoryState.ts @@ -1,6 +1,5 @@ +import type { Serializable } from '@metamask/snap-networks-utils'; import { get, set, unset } from 'lodash'; - -import type { Serializable } from '../../serialization/types'; import type { IStateManager } from './IStateManager'; /** diff --git a/packages/solana-wallet-snap/src/core/services/state/State.ts b/packages/solana-wallet-snap/src/core/services/state/State.ts index 465224fa9..d03e9c156 100644 --- a/packages/solana-wallet-snap/src/core/services/state/State.ts +++ b/packages/solana-wallet-snap/src/core/services/state/State.ts @@ -1,7 +1,9 @@ /* eslint-disable @typescript-eslint/naming-convention */ import type { Transaction } from '@metamask/keyring-api'; -import { safeMerge } from '@metamask/snap-networks-utils'; +import { deserialize, safeMerge, serialize } from '@metamask/snap-networks-utils'; +import type { Serializable } from '@metamask/snap-networks-utils'; +import type { Json } from '@metamask/snaps-sdk'; import type { Address, Signature } from '@solana/kit'; import type { MutexInterface } from 'async-mutex'; import { Mutex } from 'async-mutex'; @@ -14,9 +16,6 @@ import type { } from '../../../entities'; import type { EventEmitter } from '../../../infrastructure'; import type { SpotPrices } from '../../clients/price-api/types'; -import { deserialize } from '../../serialization/deserialize'; -import { serialize } from '../../serialization/serialize'; -import type { Serializable } from '../../serialization/types'; import type { IStateManager } from './IStateManager'; export type AccountId = string; @@ -248,7 +247,8 @@ export class State< method: 'snap_manageState', params: { operation: 'update', - newState: serialize(newState), + // State values are always objects, so the serialized result is too. + newState: serialize(newState) as Record, encrypted: this.#config.encrypted, }, }); diff --git a/packages/solana-wallet-snap/src/core/utils/interface.ts b/packages/solana-wallet-snap/src/core/utils/interface.ts index bec868648..14fcc88cf 100644 --- a/packages/solana-wallet-snap/src/core/utils/interface.ts +++ b/packages/solana-wallet-snap/src/core/utils/interface.ts @@ -1,3 +1,5 @@ +import { deserialize, serialize } from '@metamask/snap-networks-utils'; +import type { Serializable } from '@metamask/snap-networks-utils'; import type { ComponentOrElement, DialogResult, @@ -10,9 +12,6 @@ import type { } from '@metamask/snaps-sdk'; import type { ScheduleBackgroundEventMethod } from '../handlers/onCronjob/backgroundEvents/ScheduleBackgroundEventMethod'; -import { deserialize } from '../serialization/deserialize'; -import { serialize } from '../serialization/serialize'; -import type { Serializable } from '../serialization/types'; import type { Preferences } from '../types/snap'; export const CONFIRM_SIGN_AND_SEND_TRANSACTION_INTERFACE_NAME = @@ -31,7 +30,8 @@ export async function createInterface( ui: ComponentOrElement, context: TContext, ): Promise { - const serializedContext = serialize(context); + // Contexts are always objects, so the serialized result is too. + const serializedContext = serialize(context) as Record; return snap.request({ method: 'snap_createInterface', params: { @@ -54,7 +54,8 @@ export async function updateInterface( ui: ComponentOrElement, context: TContext, ): Promise { - const serializedContext = serialize(context); + // Contexts are always objects, so the serialized result is too. + const serializedContext = serialize(context) as Record; return snap.request({ method: 'snap_updateInterface', params: { diff --git a/packages/solana-wallet-snap/src/entities/subscriptions.ts b/packages/solana-wallet-snap/src/entities/subscriptions.ts index 64748a7d8..c08001061 100644 --- a/packages/solana-wallet-snap/src/entities/subscriptions.ts +++ b/packages/solana-wallet-snap/src/entities/subscriptions.ts @@ -1,9 +1,9 @@ +import type { Serializable } from '@metamask/snap-networks-utils'; import type { GetWebSocketsResult } from '@metamask/snaps-sdk'; import type { JsonRpcParams } from '@metamask/utils'; import type { SolanaRpcResponse } from '@solana/kit'; import type { Network } from '../core/constants/solana'; -import type { Serializable } from '../core/serialization/types'; export type WebSocketConnection = GetWebSocketsResult[number] & { readonly network: Network; diff --git a/packages/solana-wallet-snap/src/features/confirmation/components/Instruction/Instruction.tsx b/packages/solana-wallet-snap/src/features/confirmation/components/Instruction/Instruction.tsx index 854d639f5..d46435a10 100644 --- a/packages/solana-wallet-snap/src/features/confirmation/components/Instruction/Instruction.tsx +++ b/packages/solana-wallet-snap/src/features/confirmation/components/Instruction/Instruction.tsx @@ -1,8 +1,8 @@ +import { deserialize } from '@metamask/snap-networks-utils'; import { Address, Box, Link, Section, Text } from '@metamask/snaps-sdk/jsx'; import { isAddress } from '@solana/kit'; import type { Network } from '../../../../core/constants/solana'; -import { deserialize } from '../../../../core/serialization/deserialize'; import { addressToCaip10 } from '../../../../core/utils/addressToCaip10'; import { getSolanaExplorerUrl } from '../../../../core/utils/getSolanaExplorerUrl'; import type { Locale } from '../../../../core/utils/i18n'; diff --git a/packages/solana-wallet-snap/src/snapContext.ts b/packages/solana-wallet-snap/src/snapContext.ts index 15f7b5cf0..5366f152b 100644 --- a/packages/solana-wallet-snap/src/snapContext.ts +++ b/packages/solana-wallet-snap/src/snapContext.ts @@ -1,3 +1,4 @@ +import type { Serializable } from '@metamask/snap-networks-utils'; import type { ICache } from './core/caching/ICache'; import { InMemoryCache } from './core/caching/InMemoryCache'; import { StateCache } from './core/caching/StateCache'; @@ -7,7 +8,6 @@ import { SecurityAlertsApiClient } from './core/clients/security-alerts-api/Secu import { TokenApiClient } from './core/clients/token-api-client/TokenApiClient'; import { ClientRequestHandler } from './core/handlers'; import { SolanaKeyring } from './core/handlers/onKeyringRequest/Keyring'; -import type { Serializable } from './core/serialization/types'; import { AccountsRepository, AccountsService, From 52839dda1063b8a7d758e0205a7012fb5ef7304f Mon Sep 17 00:00:00 2001 From: Julien Fontanel Date: Fri, 28 Aug 2026 12:06:08 +0200 Subject: [PATCH 2/5] chore: fix lint --- .../solana-wallet-snap/src/core/caching/InMemoryCache.ts | 1 + packages/solana-wallet-snap/src/core/caching/StateCache.ts | 1 + .../solana-wallet-snap/src/core/caching/useCache.test.ts | 1 + .../src/core/services/state/InMemoryState.ts | 1 + .../solana-wallet-snap/src/core/services/state/State.ts | 6 +++++- packages/solana-wallet-snap/src/snapContext.ts | 1 + 6 files changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/solana-wallet-snap/src/core/caching/InMemoryCache.ts b/packages/solana-wallet-snap/src/core/caching/InMemoryCache.ts index fd38a2251..90750af2a 100644 --- a/packages/solana-wallet-snap/src/core/caching/InMemoryCache.ts +++ b/packages/solana-wallet-snap/src/core/caching/InMemoryCache.ts @@ -1,5 +1,6 @@ import type { Logger, Serializable } from '@metamask/snap-networks-utils'; import { assert } from '@metamask/utils'; + import type { ICache } from './ICache'; import type { CacheEntry } from './types'; diff --git a/packages/solana-wallet-snap/src/core/caching/StateCache.ts b/packages/solana-wallet-snap/src/core/caching/StateCache.ts index 21082a881..598af6d8c 100644 --- a/packages/solana-wallet-snap/src/core/caching/StateCache.ts +++ b/packages/solana-wallet-snap/src/core/caching/StateCache.ts @@ -1,5 +1,6 @@ import type { Logger, Serializable } from '@metamask/snap-networks-utils'; import { assert } from '@metamask/utils'; + import type { IStateManager } from '../services/state/IStateManager'; import defaultLogger from '../utils/logger'; import type { ICache } from './ICache'; diff --git a/packages/solana-wallet-snap/src/core/caching/useCache.test.ts b/packages/solana-wallet-snap/src/core/caching/useCache.test.ts index 5d9eb3dc3..0dd469654 100644 --- a/packages/solana-wallet-snap/src/core/caching/useCache.test.ts +++ b/packages/solana-wallet-snap/src/core/caching/useCache.test.ts @@ -1,4 +1,5 @@ import type { Serializable } from '@metamask/snap-networks-utils'; + import type { ICache } from './ICache'; import { useCache } from './useCache'; import type { CacheOptions } from './useCache'; diff --git a/packages/solana-wallet-snap/src/core/services/state/InMemoryState.ts b/packages/solana-wallet-snap/src/core/services/state/InMemoryState.ts index 0b0aaf9ea..597997809 100644 --- a/packages/solana-wallet-snap/src/core/services/state/InMemoryState.ts +++ b/packages/solana-wallet-snap/src/core/services/state/InMemoryState.ts @@ -1,5 +1,6 @@ import type { Serializable } from '@metamask/snap-networks-utils'; import { get, set, unset } from 'lodash'; + import type { IStateManager } from './IStateManager'; /** diff --git a/packages/solana-wallet-snap/src/core/services/state/State.ts b/packages/solana-wallet-snap/src/core/services/state/State.ts index d03e9c156..ff42e9867 100644 --- a/packages/solana-wallet-snap/src/core/services/state/State.ts +++ b/packages/solana-wallet-snap/src/core/services/state/State.ts @@ -1,7 +1,11 @@ /* eslint-disable @typescript-eslint/naming-convention */ import type { Transaction } from '@metamask/keyring-api'; -import { deserialize, safeMerge, serialize } from '@metamask/snap-networks-utils'; +import { + deserialize, + safeMerge, + serialize, +} from '@metamask/snap-networks-utils'; import type { Serializable } from '@metamask/snap-networks-utils'; import type { Json } from '@metamask/snaps-sdk'; import type { Address, Signature } from '@solana/kit'; diff --git a/packages/solana-wallet-snap/src/snapContext.ts b/packages/solana-wallet-snap/src/snapContext.ts index 5366f152b..28e86afd6 100644 --- a/packages/solana-wallet-snap/src/snapContext.ts +++ b/packages/solana-wallet-snap/src/snapContext.ts @@ -1,4 +1,5 @@ import type { Serializable } from '@metamask/snap-networks-utils'; + import type { ICache } from './core/caching/ICache'; import { InMemoryCache } from './core/caching/InMemoryCache'; import { StateCache } from './core/caching/StateCache'; From 4d2bd121130a01f8fc3c4247d3e2ad31720ec4e1 Mon Sep 17 00:00:00 2001 From: Julien Fontanel Date: Fri, 28 Aug 2026 14:41:04 +0200 Subject: [PATCH 3/5] chore: update shasum --- packages/solana-wallet-snap/snap.manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/solana-wallet-snap/snap.manifest.json b/packages/solana-wallet-snap/snap.manifest.json index 87607ea91..95bb11f0b 100644 --- a/packages/solana-wallet-snap/snap.manifest.json +++ b/packages/solana-wallet-snap/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/internal-snaps.git" }, "source": { - "shasum": "5FfpznC3zSm/PzcS3bNGu1a/heN2o1uLIfoc/y3xpMc=", + "shasum": "lRWlHwebOtD1xRQYIaqY34zZOL+726QvMmznnBpd22g=", "location": { "npm": { "filePath": "dist/bundle.js", From def079aa5079874c272025305b1f65fc8307b45e Mon Sep 17 00:00:00 2001 From: Julien Fontanel Date: Fri, 28 Aug 2026 14:43:39 +0200 Subject: [PATCH 4/5] chore: update shasum --- packages/solana-wallet-snap/snap.manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/solana-wallet-snap/snap.manifest.json b/packages/solana-wallet-snap/snap.manifest.json index 6d9added4..7a3a59d1c 100644 --- a/packages/solana-wallet-snap/snap.manifest.json +++ b/packages/solana-wallet-snap/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/internal-snaps.git" }, "source": { - "shasum": "Q2MJMblB+y+GZbCWcaoI0QUB2pNN1JfiWP/y05hBg7g=", + "shasum": "TUy54es6ZHiRpYSPotsZy46/teh9MOo3mO/YJ+sQ7kI=", "location": { "npm": { "filePath": "dist/bundle.js", From ddcf023f36d51fba7ff94e89c7d50ba41abacbf5 Mon Sep 17 00:00:00 2001 From: Julien Fontanel Date: Fri, 28 Aug 2026 14:57:13 +0200 Subject: [PATCH 5/5] chore: update shasum --- packages/solana-wallet-snap/snap.manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/solana-wallet-snap/snap.manifest.json b/packages/solana-wallet-snap/snap.manifest.json index 7a3a59d1c..8a5f96c45 100644 --- a/packages/solana-wallet-snap/snap.manifest.json +++ b/packages/solana-wallet-snap/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/internal-snaps.git" }, "source": { - "shasum": "TUy54es6ZHiRpYSPotsZy46/teh9MOo3mO/YJ+sQ7kI=", + "shasum": "V3iOdFzSye/NKphktjgWLlyZ6npSWHr+dgR0tkVtJvU=", "location": { "npm": { "filePath": "dist/bundle.js",