diff --git a/packages/solana-wallet-snap/CHANGELOG.md b/packages/solana-wallet-snap/CHANGELOG.md index 4fd4a80dd..4ea9b5995 100644 --- a/packages/solana-wallet-snap/CHANGELOG.md +++ b/packages/solana-wallet-snap/CHANGELOG.md @@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Accept non-URL request origins instead of throwing while rendering confirmations, so requests relayed over WalletConnect (whose origin is a per-session channel id) can be confirmed +- Show the dapp URL reported in `originMetadata` in the "Request from" row of the transaction, sign-message, and sign-in confirmations, marked "Not verified", and hide the row entirely when there is nothing verifiable or self-reported to show (previously an unverifiable origin was displayed as if verified, or threw) +- Stop sending unverifiable origins to the security alerts API: a WalletConnect channel id or a self-reported dapp URL can flip a Blockaid verdict, so such requests are now reported as wallet-initiated +- Only run the sign-in (SIWS) domain check against a verifiable origin, instead of comparing the requested domain to a self-reported one - Migrate `trackError` and `withCatchAndThrowSnapError` to `@metamask/snap-networks-utils` `createSnapErrorHandling`, and add `getSnapProvider` for Snap RPC access - Extract Snap-owned assets domain logic into `SnapAssetsAdapter`; `AssetsService` is a thin facade that delegates metadata, market data, fetch, persist, and account asset reads through the adapter (no Core routing yet). ([#121](https://github.com/MetaMask/internal-snaps/pull/121)) - Align `AssetsService` read API with `snap-networks-utils` / AssetsController shapes by adding `getAccountAssetByID`, `getAccountAssetsByIDs`, `getAccountAssetsByScope`, and `getAccountAssets`, and routing Keyring and Send through them (still Snap-owned storage). ([#120](https://github.com/MetaMask/internal-snaps/pull/120)) diff --git a/packages/solana-wallet-snap/locales/en.json b/packages/solana-wallet-snap/locales/en.json index c9febc192..7bf90ad8f 100644 --- a/packages/solana-wallet-snap/locales/en.json +++ b/packages/solana-wallet-snap/locales/en.json @@ -196,6 +196,12 @@ "confirmation.origin.tooltip": { "message": "This is the site asking for your confirmation." }, + "confirmation.origin.unverified": { + "message": "Not verified" + }, + "confirmation.origin.unverified.tooltip": { + "message": "This site is reported by the app that sent the request. MetaMask can't verify it." + }, "confirmation.simulationErrorTitle": { "message": "This transaction was reverted during simulation." }, diff --git a/packages/solana-wallet-snap/messages.json b/packages/solana-wallet-snap/messages.json index dacda376d..32840dc6c 100644 --- a/packages/solana-wallet-snap/messages.json +++ b/packages/solana-wallet-snap/messages.json @@ -64,6 +64,8 @@ "confirmation.feeError": "Unable to estimate fee", "confirmation.origin": "Request from", "confirmation.origin.tooltip": "This is the site asking for your confirmation.", + "confirmation.origin.unverified": "Not verified", + "confirmation.origin.unverified.tooltip": "This site is reported by the app that sent the request. MetaMask can't verify it.", "confirmation.simulationErrorTitle": "This transaction was reverted during simulation.", "confirmation.simulationErrorSubtitle": "{reason}", "confirmation.validationErrorTitle": "This is a deceptive request", diff --git a/packages/solana-wallet-snap/src/core/services/confirmation/ConfirmationHandler.ts b/packages/solana-wallet-snap/src/core/services/confirmation/ConfirmationHandler.ts index dcc1842e4..d76ba83f2 100644 --- a/packages/solana-wallet-snap/src/core/services/confirmation/ConfirmationHandler.ts +++ b/packages/solana-wallet-snap/src/core/services/confirmation/ConfirmationHandler.ts @@ -105,6 +105,7 @@ export class ConfirmationHandler { scope, method, origin: request.origin, + originMetadata: request.originMetadata ?? null, transaction: base64EncodedTransaction, account, }); diff --git a/packages/solana-wallet-snap/src/core/services/transaction-scan/TransactionScan.test.ts b/packages/solana-wallet-snap/src/core/services/transaction-scan/TransactionScan.test.ts index 0af9628f7..c6eeceaed 100644 --- a/packages/solana-wallet-snap/src/core/services/transaction-scan/TransactionScan.test.ts +++ b/packages/solana-wallet-snap/src/core/services/transaction-scan/TransactionScan.test.ts @@ -62,6 +62,49 @@ describe('TransactionScan', () => { }); }); + it.each([ + ['a WalletConnect channel id', '4f3a1b2c-0000-4000-8000-000000000000'], + ['the MetaMask origin', 'metamask'], + ])('does not forward %s to the scan', async (_, origin) => { + const scanTransactions = jest + .spyOn(mockSecurityAlertsApiClient, 'scanTransactions') + .mockResolvedValue({ + status: 'SUCCESS', + } as SecurityAlertSimulationValidationResponse); + + await transactionScanService.scanTransaction({ + method: 'method', + accountAddress: 'accountAddress', + transaction: 'transaction', + scope: Network.Mainnet, + origin, + }); + + expect(scanTransactions).toHaveBeenCalledWith( + expect.objectContaining({ origin: 'https://metamask.io' }), + ); + }); + + it('forwards a verifiable origin to the scan', async () => { + const scanTransactions = jest + .spyOn(mockSecurityAlertsApiClient, 'scanTransactions') + .mockResolvedValue({ + status: 'SUCCESS', + } as SecurityAlertSimulationValidationResponse); + + await transactionScanService.scanTransaction({ + method: 'method', + accountAddress: 'accountAddress', + transaction: 'transaction', + scope: Network.Mainnet, + origin: 'https://portfolio.metamask.io', + }); + + expect(scanTransactions).toHaveBeenCalledWith( + expect.objectContaining({ origin: 'https://portfolio.metamask.io' }), + ); + }); + it('returns null if the scan fails', async () => { const error = new Error('Scan failed'); jest diff --git a/packages/solana-wallet-snap/src/core/services/transaction-scan/TransactionScan.ts b/packages/solana-wallet-snap/src/core/services/transaction-scan/TransactionScan.ts index 8f82a5319..d63b4daee 100644 --- a/packages/solana-wallet-snap/src/core/services/transaction-scan/TransactionScan.ts +++ b/packages/solana-wallet-snap/src/core/services/transaction-scan/TransactionScan.ts @@ -1,9 +1,10 @@ import type { Logger } from '@metamask/snap-networks-utils'; +import { resolveOrigin } from '@metamask/snap-networks-utils'; import type { SolanaKeyringAccount } from '../../../entities'; import type { SecurityAlertsApiClient } from '../../clients/security-alerts-api/SecurityAlertsApiClient'; import type { SecurityAlertSimulationValidationResponse } from '../../clients/security-alerts-api/types'; -import { METAMASK_ORIGIN, METAMASK_ORIGIN_URL } from '../../constants/solana'; +import { METAMASK_ORIGIN_URL } from '../../constants/solana'; import type { Network } from '../../constants/solana'; import { trackError } from '../../utils/errors'; import type { AnalyticsService } from '../analytics/AnalyticsService'; @@ -63,7 +64,12 @@ export class TransactionScanService { accountAddress, transactions: [transaction], scope, - origin: origin === METAMASK_ORIGIN ? METAMASK_ORIGIN_URL : origin, + // Only a verifiable origin may reach the scan: the URL is a core + // heuristic and can flip a verdict, so an unverifiable one (a + // WalletConnect channel id, or a URL self-reported by the requester) + // would let a dapp influence the check meant to catch it. Those are + // reported as wallet-initiated instead. + origin: resolveOrigin(origin).verifiedOrigin ?? METAMASK_ORIGIN_URL, options, }); diff --git a/packages/solana-wallet-snap/src/core/utils/parseOrigin.test.ts b/packages/solana-wallet-snap/src/core/utils/parseOrigin.test.ts deleted file mode 100644 index b209ed65c..000000000 --- a/packages/solana-wallet-snap/src/core/utils/parseOrigin.test.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { METAMASK_ORIGIN } from '../constants/solana'; -import { parseOrigin } from './parseOrigin'; - -describe('parseOrigin', () => { - describe('when origin is MetaMask', () => { - it('returns "MetaMask" for metamask origin', () => { - expect(parseOrigin(METAMASK_ORIGIN)).toBe('MetaMask'); - }); - - it('returns "MetaMask" for exact string match', () => { - expect(parseOrigin('metamask')).toBe('MetaMask'); - }); - }); - - describe('when origin is a valid URL', () => { - it('returns hostname for HTTP URLs', () => { - expect(parseOrigin('http://example.com')).toBe('example.com'); - expect(parseOrigin('http://www.example.com')).toBe('www.example.com'); - expect(parseOrigin('http://sub.example.com')).toBe('sub.example.com'); - }); - - it('returns hostname for HTTPS URLs', () => { - expect(parseOrigin('https://example.com')).toBe('example.com'); - expect(parseOrigin('https://www.example.com')).toBe('www.example.com'); - expect(parseOrigin('https://sub.example.com')).toBe('sub.example.com'); - }); - - it('returns hostname for URLs with paths', () => { - expect(parseOrigin('https://example.com/path')).toBe('example.com'); - expect(parseOrigin('https://example.com/path/to/resource')).toBe( - 'example.com', - ); - expect(parseOrigin('https://example.com/path?query=value')).toBe( - 'example.com', - ); - }); - - it('returns hostname for URLs with query parameters', () => { - expect(parseOrigin('https://example.com?param=value')).toBe( - 'example.com', - ); - expect( - parseOrigin('https://example.com/path?param1=value1¶m2=value2'), - ).toBe('example.com'); - }); - - it('returns hostname for URLs with fragments', () => { - expect(parseOrigin('https://example.com#section')).toBe('example.com'); - expect(parseOrigin('https://example.com/path#section')).toBe( - 'example.com', - ); - }); - - it('returns hostname for URLs with ports', () => { - expect(parseOrigin('https://example.com:8080')).toBe('example.com'); - expect(parseOrigin('http://localhost:3000')).toBe('localhost'); - }); - - it('returns hostname for localhost URLs', () => { - expect(parseOrigin('http://localhost')).toBe('localhost'); - expect(parseOrigin('http://localhost:3000')).toBe('localhost'); - expect(parseOrigin('https://localhost')).toBe('localhost'); - }); - - it('returns hostname for IP addresses', () => { - expect(parseOrigin('http://192.168.1.1')).toBe('192.168.1.1'); - expect(parseOrigin('https://127.0.0.1')).toBe('127.0.0.1'); - expect(parseOrigin('http://192.168.1.1:8080')).toBe('192.168.1.1'); - }); - }); - - describe('edge cases', () => { - it('throws an error for URLs without protocol', () => { - expect(() => parseOrigin('//example.com')).toThrow('Invalid URL'); - expect(() => parseOrigin('//www.example.com')).toThrow('Invalid URL'); - }); - - it('handles URLs with custom protocols', () => { - expect(parseOrigin('ftp://example.com')).toBe('example.com'); - expect(parseOrigin('ws://example.com')).toBe('example.com'); - expect(parseOrigin('wss://example.com')).toBe('example.com'); - }); - - it('handles complex subdomains', () => { - expect(parseOrigin('https://api.v1.example.com')).toBe( - 'api.v1.example.com', - ); - expect(parseOrigin('https://dev.staging.example.com')).toBe( - 'dev.staging.example.com', - ); - }); - }); - - describe('error handling', () => { - it('throws error for invalid URLs', () => { - expect(() => parseOrigin('not-a-url')).toThrow('Invalid URL'); - expect(() => parseOrigin('http://')).toThrow('Invalid URL'); - expect(() => parseOrigin('https://')).toThrow('Invalid URL'); - expect(() => parseOrigin('')).toThrow('Invalid URL'); - }); - - it('throws error for malformed URLs', () => { - expect(() => parseOrigin('http://:8080')).toThrow('Invalid URL'); - }); - }); -}); diff --git a/packages/solana-wallet-snap/src/core/utils/parseOrigin.ts b/packages/solana-wallet-snap/src/core/utils/parseOrigin.ts deleted file mode 100644 index ad99e043b..000000000 --- a/packages/solana-wallet-snap/src/core/utils/parseOrigin.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { METAMASK_ORIGIN } from '../constants/solana'; - -/** - * Parses the origin from a string. - * - * @param origin - The origin to parse. - * @returns The parsed origin. - */ -export function parseOrigin(origin: string) { - if (origin === METAMASK_ORIGIN) { - return 'MetaMask'; - } - - try { - return new URL(origin).hostname; - } catch (error) { - throw new Error('Invalid URL'); - } -} diff --git a/packages/solana-wallet-snap/src/features/confirmation/components/OriginRow/OriginRow.tsx b/packages/solana-wallet-snap/src/features/confirmation/components/OriginRow/OriginRow.tsx new file mode 100644 index 000000000..3872fe696 --- /dev/null +++ b/packages/solana-wallet-snap/src/features/confirmation/components/OriginRow/OriginRow.tsx @@ -0,0 +1,65 @@ +import type { SnapComponent } from '@metamask/snaps-sdk/jsx'; +import { Box, Icon, Text as SnapText, Tooltip } from '@metamask/snaps-sdk/jsx'; + +import type { Locale } from '../../../../core/utils/i18n'; +import { i18n } from '../../../../core/utils/i18n'; + +type OriginRowProps = { + /** Hostname to display. The row is not rendered when `null`. */ + displayOrigin: string | null; + /** Whether the hostname was reported by the requester and can't be verified. */ + isSelfReported: boolean; + locale: Locale; +}; + +/** + * The "Request from" row of a confirmation. + * + * A self-reported origin is displayed with an explicit "not verified" marker: + * it comes from the requesting app over a transport that cannot prove it, so + * showing it bare would imply a verification we never made. + * + * @param props - The component props. + * @param props.displayOrigin - Hostname to display, or `null` to render nothing. + * @param props.isSelfReported - Whether the hostname is unverifiable. + * @param props.locale - The locale used for the labels. + * @returns The origin row, or `null` when there is nothing to display. + */ +export const OriginRow: SnapComponent = ({ + displayOrigin, + isSelfReported, + locale, +}) => { + if (!displayOrigin) { + return null; + } + + const translate = i18n(locale); + + return ( + + + + {translate('confirmation.origin')} + + + + + + + {displayOrigin} + {isSelfReported ? ( + + {translate('confirmation.origin.unverified')} + + ) : null} + + + ); +}; diff --git a/packages/solana-wallet-snap/src/features/confirmation/components/TransactionDetails/TransactionDetails.tsx b/packages/solana-wallet-snap/src/features/confirmation/components/TransactionDetails/TransactionDetails.tsx index a444619ad..41c681ca6 100644 --- a/packages/solana-wallet-snap/src/features/confirmation/components/TransactionDetails/TransactionDetails.tsx +++ b/packages/solana-wallet-snap/src/features/confirmation/components/TransactionDetails/TransactionDetails.tsx @@ -1,3 +1,5 @@ +import type { SelfReportedOriginMetadata } from '@metamask/snap-networks-utils'; +import { resolveOrigin } from '@metamask/snap-networks-utils'; import type { SnapComponent } from '@metamask/snaps-sdk/jsx'; import { Address, @@ -18,8 +20,8 @@ import { addressToCaip10 } from '../../../../core/utils/addressToCaip10'; import { formatCrypto } from '../../../../core/utils/formatCrypto'; import { formatFiat } from '../../../../core/utils/formatFiat'; import { i18n } from '../../../../core/utils/i18n'; -import { parseOrigin } from '../../../../core/utils/parseOrigin'; import { tokenToFiat } from '../../../../core/utils/tokenToFiat'; +import { OriginRow } from '../OriginRow/OriginRow'; type TransactionDetailsProps = { accountAddress: string | null; @@ -33,10 +35,12 @@ type TransactionDetailsProps = { preferences: Preferences; networkImage: string | null; origin: string; + originMetadata: SelfReportedOriginMetadata | null; }; export const TransactionDetails: SnapComponent = ({ origin, + originMetadata, accountAddress, accountDomain, destinationAddress, @@ -50,9 +54,12 @@ export const TransactionDetails: SnapComponent = ({ }) => { const { currency, locale } = preferences; const translate = i18n(locale); - const isMetaMaskOrigin = origin === METAMASK_ORIGIN; - const originHostname = - origin && !isMetaMaskOrigin ? parseOrigin(origin) : null; + const { displayOrigin, isSelfReported } = resolveOrigin( + origin, + originMetadata, + ); + // Wallet-initiated transactions have no origin row to show. + const originToDisplay = origin === METAMASK_ORIGIN ? null : displayOrigin; const pricesFetching = fetchingPricesStatus === 'fetching'; const pricesError = fetchingPricesStatus === 'error'; @@ -64,19 +71,13 @@ export const TransactionDetails: SnapComponent = ({ return (
- {originHostname ? ( + {originToDisplay ? ( - - - - {translate('confirmation.origin')} - - - - - - {originHostname} - + {null} ) : null} diff --git a/packages/solana-wallet-snap/src/features/confirmation/views/ConfirmSignIn/ConfirmSignIn.tsx b/packages/solana-wallet-snap/src/features/confirmation/views/ConfirmSignIn/ConfirmSignIn.tsx index c43834026..247fadc18 100644 --- a/packages/solana-wallet-snap/src/features/confirmation/views/ConfirmSignIn/ConfirmSignIn.tsx +++ b/packages/solana-wallet-snap/src/features/confirmation/views/ConfirmSignIn/ConfirmSignIn.tsx @@ -1,3 +1,5 @@ +import type { SelfReportedOriginMetadata } from '@metamask/snap-networks-utils'; +import { resolveOrigin } from '@metamask/snap-networks-utils'; import { Address, Box, @@ -19,10 +21,10 @@ import { SOL_IMAGE_SVG } from '../../../../core/test/mocks/solana-image-svg'; import type { Preferences } from '../../../../core/types/snap'; import { addressToCaip10 } from '../../../../core/utils/addressToCaip10'; import { i18n } from '../../../../core/utils/i18n'; -import { parseOrigin } from '../../../../core/utils/parseOrigin'; import type { SolanaKeyringAccount } from '../../../../entities'; import { BasicNullableField } from '../../components/BasicNullableField/BasicNullableField'; import { EstimatedChanges } from '../../components/EstimatedChanges/EstimatedChanges'; +import { OriginRow } from '../../components/OriginRow/OriginRow'; import { ConfirmSignInFormNames } from './events'; export type ConfirmSignInProps = { @@ -41,6 +43,7 @@ export type ConfirmSignInProps = { resources: string[]; }>; origin: string; + originMetadata: SelfReportedOriginMetadata | null; account: SolanaKeyringAccount; accountDomain: string | null; scope: Network; @@ -51,6 +54,7 @@ export type ConfirmSignInProps = { export const ConfirmSignIn: SnapComponent = ({ params, origin, + originMetadata, account, accountDomain, scope, @@ -58,7 +62,10 @@ export const ConfirmSignIn: SnapComponent = ({ networkImage, }) => { const translate = i18n(preferences.locale); - const originHostname = origin ? parseOrigin(origin) : null; + const { displayOrigin, isSelfReported, verifiedOrigin } = resolveOrigin( + origin, + originMetadata, + ); const { domain, @@ -81,7 +88,10 @@ export const ConfirmSignIn: SnapComponent = ({ const signInAddressCaip10 = address ? addressToCaip10(scope, address) : null; const isBadAccount = signInAddressCaip10 !== accountAddressCaip10; - const isBadDomain = domain !== originHostname; + // Only a verifiable origin may drive the SIWS domain check. A self-reported + // origin is supplied by the requester, so comparing against it would let the + // requester decide whether its own domain looks legitimate. + const isBadDomain = verifiedOrigin !== null && domain !== displayOrigin; return ( @@ -104,14 +114,11 @@ export const ConfirmSignIn: SnapComponent = ({ ) : null}
- {originHostname ? ( - - {originHostname} - - ) : null} + { preferences={mockPreferences} networkImage={SOL_IMAGE_SVG} origin={TEST_ORIGIN} + originMetadata={null} />, ); }); diff --git a/packages/solana-wallet-snap/src/features/confirmation/views/ConfirmSignIn/render.tsx b/packages/solana-wallet-snap/src/features/confirmation/views/ConfirmSignIn/render.tsx index 5dd19f6f9..8584a71f5 100644 --- a/packages/solana-wallet-snap/src/features/confirmation/views/ConfirmSignIn/render.tsx +++ b/packages/solana-wallet-snap/src/features/confirmation/views/ConfirmSignIn/render.tsx @@ -30,6 +30,7 @@ export async function render( request: { params }, scope, origin, + originMetadata, } = request; const [preferences, accountDomain] = await Promise.all([ @@ -46,6 +47,7 @@ export async function render( preferences={preferences} networkImage={SOL_IMAGE_SVG} origin={origin} + originMetadata={originMetadata ?? null} />, {}, ); diff --git a/packages/solana-wallet-snap/src/features/confirmation/views/ConfirmSignMessage/ConfirmSignMessage.tsx b/packages/solana-wallet-snap/src/features/confirmation/views/ConfirmSignMessage/ConfirmSignMessage.tsx index bf445ca8b..dd79f92a2 100644 --- a/packages/solana-wallet-snap/src/features/confirmation/views/ConfirmSignMessage/ConfirmSignMessage.tsx +++ b/packages/solana-wallet-snap/src/features/confirmation/views/ConfirmSignMessage/ConfirmSignMessage.tsx @@ -1,3 +1,5 @@ +import type { SelfReportedOriginMetadata } from '@metamask/snap-networks-utils'; +import { resolveOrigin } from '@metamask/snap-networks-utils'; import { Address, Box, @@ -5,11 +7,9 @@ import { Container, Footer, Heading, - Icon, Image, Section, Text, - Tooltip, } from '@metamask/snaps-sdk/jsx'; import type { SnapComponent } from '@metamask/snaps-sdk/jsx'; @@ -20,8 +20,8 @@ import { SOL_IMAGE_SVG } from '../../../../core/test/mocks/solana-image-svg'; import { addressToCaip10 } from '../../../../core/utils/addressToCaip10'; import type { Locale } from '../../../../core/utils/i18n'; import { i18n } from '../../../../core/utils/i18n'; -import { parseOrigin } from '../../../../core/utils/parseOrigin'; import type { SolanaKeyringAccount } from '../../../../entities'; +import { OriginRow } from '../../components/OriginRow/OriginRow'; import { ConfirmSignMessageFormNames } from './events'; export type ConfirmSignMessageProps = { @@ -32,6 +32,7 @@ export type ConfirmSignMessageProps = { locale: Locale; networkImage: string | null; origin: string; + originMetadata: SelfReportedOriginMetadata | null; }; export const ConfirmSignMessage: SnapComponent = ({ @@ -42,10 +43,14 @@ export const ConfirmSignMessage: SnapComponent = ({ locale, networkImage, origin, + originMetadata, }) => { const translate = i18n(locale); const { address } = account; - const originHostname = origin ? parseOrigin(origin) : null; + const { displayOrigin, isSelfReported } = resolveOrigin( + origin, + originMetadata, + ); const addressCaip10 = addressToCaip10(scope, address); return ( @@ -70,19 +75,11 @@ export const ConfirmSignMessage: SnapComponent = ({
- {originHostname ? ( - - - - {translate('confirmation.origin')} - - - - - - {originHostname} - - ) : null} + {translate('confirmation.account')} diff --git a/packages/solana-wallet-snap/src/features/confirmation/views/ConfirmSignMessage/render.test.tsx b/packages/solana-wallet-snap/src/features/confirmation/views/ConfirmSignMessage/render.test.tsx index c691f2f8f..7fc139950 100644 --- a/packages/solana-wallet-snap/src/features/confirmation/views/ConfirmSignMessage/render.test.tsx +++ b/packages/solana-wallet-snap/src/features/confirmation/views/ConfirmSignMessage/render.test.tsx @@ -76,6 +76,7 @@ describe('render', () => { locale={'en'} networkImage={SOL_IMAGE_SVG} origin={TEST_ORIGIN} + originMetadata={null} />, ); }); diff --git a/packages/solana-wallet-snap/src/features/confirmation/views/ConfirmSignMessage/render.tsx b/packages/solana-wallet-snap/src/features/confirmation/views/ConfirmSignMessage/render.tsx index 285fedfd9..04351d90f 100644 --- a/packages/solana-wallet-snap/src/features/confirmation/views/ConfirmSignMessage/render.tsx +++ b/packages/solana-wallet-snap/src/features/confirmation/views/ConfirmSignMessage/render.tsx @@ -33,6 +33,7 @@ export async function render( }, scope, origin, + originMetadata, } = request; const messageBytes = getBase64Codec().encode(messageBase64); @@ -54,6 +55,7 @@ export async function render( locale={locale} networkImage={SOL_IMAGE_SVG} origin={origin} + originMetadata={originMetadata ?? null} />, {}, ); diff --git a/packages/solana-wallet-snap/src/features/confirmation/views/ConfirmTransactionRequest/ConfirmTransactionRequest.tsx b/packages/solana-wallet-snap/src/features/confirmation/views/ConfirmTransactionRequest/ConfirmTransactionRequest.tsx index 04d9ac2b5..3f597a597 100644 --- a/packages/solana-wallet-snap/src/features/confirmation/views/ConfirmTransactionRequest/ConfirmTransactionRequest.tsx +++ b/packages/solana-wallet-snap/src/features/confirmation/views/ConfirmTransactionRequest/ConfirmTransactionRequest.tsx @@ -71,6 +71,7 @@ export const ConfirmTransactionRequest = ({ preferences={context.preferences} networkImage={context.networkImage} origin={context.origin} + originMetadata={context.originMetadata} />