diff --git a/packages/starknet-snap/src/rpcs/__tests__/helper.ts b/packages/starknet-snap/src/rpcs/__tests__/helper.ts index 70c08cd8..40b9b6ee 100644 --- a/packages/starknet-snap/src/rpcs/__tests__/helper.ts +++ b/packages/starknet-snap/src/rpcs/__tests__/helper.ts @@ -4,6 +4,7 @@ import type { constants } from 'starknet'; import type { StarknetAccount } from '../../__tests__/helper'; import { generateAccounts, generateRandomValue } from '../../__tests__/helper'; import type { SnapState } from '../../types/snapState'; +import { getExplorerUrl, shortenAddress, toJson } from '../../utils'; import * as snapHelper from '../../utils/snap'; import * as snapUtils from '../../utils/snapUtils'; import * as starknetUtils from '../../utils/starknetUtils'; @@ -84,6 +85,29 @@ export const buildDividerComponent = () => { }; }; +export const buildAddressComponent = ( + label: string, + address: string, + chainId: string, +) => { + return buildRowComponent( + label, + `[${shortenAddress(address)}](${getExplorerUrl(address, chainId)})`, + ); +}; + +export const buildSignerComponent = (value: string, chainId: string) => { + return buildAddressComponent('Signer Address', value, chainId); +}; + +export const buildNetworkComponent = (chainName: string) => { + return buildRowComponent('Network', chainName); +}; + +export const buildJsonDataComponent = (label: string, data: any) => { + return buildRowComponent(label, toJson(data)); +}; + /** * * @param min diff --git a/packages/starknet-snap/src/rpcs/declare-contract.test.ts b/packages/starknet-snap/src/rpcs/declare-contract.test.ts index 4f916a9b..d745397c 100644 --- a/packages/starknet-snap/src/rpcs/declare-contract.test.ts +++ b/packages/starknet-snap/src/rpcs/declare-contract.test.ts @@ -3,7 +3,7 @@ import type { Abi, UniversalDetails } from 'starknet'; import { constants } from 'starknet'; import type { Infer } from 'superstruct'; -import { toJson, type DeclareContractPayloadStruct } from '../utils'; +import { type DeclareContractPayloadStruct } from '../utils'; import { STARKNET_SEPOLIA_TESTNET_NETWORK } from '../utils/constants'; import { UserRejectedOpError, @@ -13,7 +13,9 @@ import { import * as starknetUtils from '../utils/starknetUtils'; import { buildDividerComponent, + buildNetworkComponent, buildRowComponent, + buildSignerComponent, generateRandomFee, mockAccount, prepareConfirmDialog, @@ -213,11 +215,9 @@ describe('DeclareContractRpc', () => { type: 'heading', value: 'Do you want to sign this transaction?', }, - buildRowComponent('Signer Address', account.address), + buildSignerComponent(account.address, network.chainId), buildDividerComponent(), - buildRowComponent('Network', network.name), - buildDividerComponent(), - buildRowComponent('Contract', toJson(payload.contract)), + buildNetworkComponent(network.name), buildDividerComponent(), buildRowComponent('Compiled Class Hash', payload.compiledClassHash ?? ''), buildDividerComponent(), diff --git a/packages/starknet-snap/src/rpcs/declare-contract.ts b/packages/starknet-snap/src/rpcs/declare-contract.ts index 533549cb..03d06bba 100644 --- a/packages/starknet-snap/src/rpcs/declare-contract.ts +++ b/packages/starknet-snap/src/rpcs/declare-contract.ts @@ -1,5 +1,4 @@ import type { Component } from '@metamask/snaps-sdk'; -import { heading, divider, row, text } from '@metamask/snaps-sdk'; import convert from 'ethereum-unit-converter'; import type { Infer } from 'superstruct'; import { assign, object, optional, string } from 'superstruct'; @@ -12,7 +11,11 @@ import { UniversalDetailsStruct, confirmDialog, AccountRpcController, - toJson, + signerUI, + networkUI, + rowUI, + dividerUI, + headerUI, } from '../utils'; import { UserRejectedOpError } from '../utils/exceptions'; import { declareContract as declareContractUtil } from '../utils/starknetUtils'; @@ -103,98 +106,52 @@ export class DeclareContractRpc extends AccountRpcController< protected async getDeclareContractConsensus(params: DeclareContractParams) { const { payload, details, address } = params; const components: Component[] = []; - components.push(heading('Do you want to sign this transaction?')); + components.push(headerUI('Do you want to sign this transaction?')); components.push( - row( - 'Signer Address', - text({ - value: address, - markdown: false, - }), - ), + signerUI({ + address, + chainId: this.network.chainId, + }), ); - components.push(divider()); - + components.push(dividerUI()); components.push( - row( - 'Network', - text({ - value: this.network.name, - markdown: false, - }), - ), + networkUI({ + networkName: this.network.name, + }), ); - if (payload.contract) { - components.push(divider()); - const contractDetails = - typeof payload.contract === 'string' - ? payload.contract - : toJson(payload.contract); - components.push( - row( - 'Contract', - text({ - value: contractDetails, - markdown: false, - }), - ), - ); - } + const { compiledClassHash, classHash } = payload; - if (payload.compiledClassHash) { - components.push(divider()); + if (compiledClassHash) { + components.push(dividerUI()); components.push( - row( - 'Compiled Class Hash', - text({ - value: payload.compiledClassHash, - markdown: false, - }), - ), - ); - } - - if (payload.classHash) { - components.push(divider()); - components.push( - row( - 'Class Hash', - text({ - value: payload.classHash, - markdown: false, - }), - ), + rowUI({ + label: 'Compiled Class Hash', + value: compiledClassHash, + }), ); } - if (payload.casm) { - const casmDetails = toJson(payload.casm); - components.push(divider()); + if (classHash) { + components.push(dividerUI()); components.push( - row( - 'Casm', - text({ - value: casmDetails, - markdown: false, - }), - ), + rowUI({ + label: 'Class Hash', + value: classHash, + }), ); } if (details?.maxFee) { const maxFeeInEth = convert(details.maxFee, 'wei', 'ether'); - components.push(divider()); + components.push(dividerUI()); components.push( - row( - 'Max Fee (ETH)', - text({ - value: maxFeeInEth, - markdown: false, - }), - ), + rowUI({ + label: 'Max Fee (ETH)', + value: maxFeeInEth, + }), ); } diff --git a/packages/starknet-snap/src/rpcs/execute-txn.ts b/packages/starknet-snap/src/rpcs/execute-txn.ts index 25dbc2ee..9e6d6108 100644 --- a/packages/starknet-snap/src/rpcs/execute-txn.ts +++ b/packages/starknet-snap/src/rpcs/execute-txn.ts @@ -1,5 +1,4 @@ import type { Component, Json } from '@metamask/snaps-sdk'; -import { heading, row, text, divider } from '@metamask/snaps-sdk'; import convert from 'ethereum-unit-converter'; import type { Call, Calldata } from 'starknet'; import { constants, TransactionStatus, TransactionType } from 'starknet'; @@ -20,6 +19,13 @@ import { UniversalDetailsStruct, CallsStruct, mapDeprecatedParams, + addressUI, + signerUI, + networkUI, + jsonDataUI, + dividerUI, + headerUI, + rowUI, } from '../utils'; import { UserRejectedOpError } from '../utils/exceptions'; import { logger } from '../utils/logger'; @@ -214,6 +220,7 @@ export class ExecuteTxnRpc extends AccountRpcController< maxFee: string, version?: constants.TRANSACTION_VERSION, ) { + const { name: chainName, chainId } = this.network; const callsArray = Array.isArray(calls) ? calls : [calls]; const components: Component[] = []; @@ -222,72 +229,59 @@ export class ExecuteTxnRpc extends AccountRpcController< ? FeeToken.STRK : FeeToken.ETH; + components.push(headerUI('Do you want to sign this transaction?')); components.push( - row( - 'Signer Address', - text({ - value: address, - markdown: false, - }), - ), + signerUI({ + address, + chainId, + }), ); // Display a message to indicate the signed transaction will include an account deployment if (!accountDeployed) { - components.push(heading(`The account will be deployed`)); - components.push(divider()); + components.push(headerUI(`The account will be deployed`)); } + components.push(dividerUI()); components.push( - row( - `Estimated Gas Fee (${feeToken})`, - text({ - value: convert(maxFee, 'wei', 'ether'), - markdown: false, - }), - ), + rowUI({ + label: `Estimated Gas Fee (${feeToken})`, + value: convert(maxFee, 'wei', 'ether'), + }), ); + components.push(dividerUI()); components.push( - row( - 'Network', - text({ - value: this.network.name, - markdown: false, - }), - ), + networkUI({ + networkName: chainName, + }), ); - components.push(divider()); // Iterate over each call in the calls array for (const call of callsArray) { const { contractAddress, calldata, entrypoint } = call; - + components.push(dividerUI()); components.push( - row( - 'Contract', - text({ - value: contractAddress, - markdown: false, - }), - ), + addressUI({ + label: 'Contract', + address: contractAddress, + chainId, + }), ); components.push( - row( - 'Call Data', - text({ - value: JSON.stringify(calldata, null, 2), - markdown: false, - }), - ), + jsonDataUI({ + label: 'Call Data', + data: calldata, + }), ); // If the contract is an ERC20 token and the function is 'transfer', display sender, recipient, and amount const token = await this.tokenStateManager.getToken({ address: contractAddress, - chainId: this.network.chainId, + chainId, }); + if (token && entrypoint === 'transfer' && calldata) { try { const senderAddress = address; @@ -301,29 +295,24 @@ export class ExecuteTxnRpc extends AccountRpcController< Number(calldata[1]) * Math.pow(10, -1 * token.decimals) ).toFixed(token.decimals); } - + components.push(dividerUI()); components.push( - row( - 'Sender Address', - text({ - value: senderAddress, - markdown: false, - }), - ), - row( - 'Recipient Address', - text({ - value: recipientAddress, - markdown: false, - }), - ), - row( - `Amount (${token.symbol})`, - text({ - value: amount, - markdown: false, - }), - ), + addressUI({ + label: 'Sender Address', + address: senderAddress, + chainId, + }), + dividerUI(), + addressUI({ + label: 'Recipient Address', + address: recipientAddress, + chainId, + }), + dividerUI(), + rowUI({ + label: `Amount (${token.symbol})`, + value: amount, + }), ); } catch (error) { logger.warn( @@ -332,7 +321,6 @@ export class ExecuteTxnRpc extends AccountRpcController< ); } } - components.push(divider()); } return await confirmDialog(components); diff --git a/packages/starknet-snap/src/rpcs/sign-declare-transaction.test.ts b/packages/starknet-snap/src/rpcs/sign-declare-transaction.test.ts index 73defc9b..a36f639c 100644 --- a/packages/starknet-snap/src/rpcs/sign-declare-transaction.test.ts +++ b/packages/starknet-snap/src/rpcs/sign-declare-transaction.test.ts @@ -2,7 +2,6 @@ import type { DeclareSignerDetails } from 'starknet'; import { constants } from 'starknet'; import type { SnapState } from '../types/snapState'; -import { toJson } from '../utils'; import { STARKNET_SEPOLIA_TESTNET_NETWORK } from '../utils/constants'; import { UserRejectedOpError, @@ -13,6 +12,9 @@ import { mockAccount, prepareMockAccount, prepareConfirmDialog, + buildSignerComponent, + buildNetworkComponent, + buildJsonDataComponent, } from './__tests__/helper'; import { signDeclareTransaction } from './sign-declare-transaction'; import type { SignDeclareTransactionParams } from './sign-declare-transaction'; @@ -67,44 +69,21 @@ describe('signDeclareTransaction', () => { it('renders confirmation dialog', async () => { const chainId = constants.StarknetChainId.SN_SEPOLIA; const account = await mockAccount(chainId); + const { address } = account; prepareMockAccount(account, state); const { confirmDialogSpy } = prepareConfirmDialog(); - const request = createRequest(chainId, account.address); + const request = createRequest(chainId, address); await signDeclareTransaction.execute(request); const calls = confirmDialogSpy.mock.calls[0][0]; expect(calls).toStrictEqual([ { type: 'heading', value: 'Do you want to sign this transaction?' }, - { - type: 'row', - label: 'Network', - value: { - value: STARKNET_SEPOLIA_TESTNET_NETWORK.name, - markdown: false, - type: 'text', - }, - }, - { - type: 'row', - label: 'Signer Address', - value: { - value: account.address, - markdown: false, - type: 'text', - }, - }, - { - type: 'row', - label: 'Declare Transaction Details', - value: { - value: toJson(request.details), - markdown: false, - type: 'text', - }, - }, + buildSignerComponent(address, chainId), + buildNetworkComponent(STARKNET_SEPOLIA_TESTNET_NETWORK.name), + buildJsonDataComponent('Declare Transaction Details', request.details), ]); }); diff --git a/packages/starknet-snap/src/rpcs/sign-declare-transaction.ts b/packages/starknet-snap/src/rpcs/sign-declare-transaction.ts index 9a9d92e1..775dcd09 100644 --- a/packages/starknet-snap/src/rpcs/sign-declare-transaction.ts +++ b/packages/starknet-snap/src/rpcs/sign-declare-transaction.ts @@ -1,5 +1,4 @@ import type { Component } from '@metamask/snaps-sdk'; -import { heading, row, text } from '@metamask/snaps-sdk'; import type { DeclareSignerDetails } from 'starknet'; import type { Infer } from 'superstruct'; import { array, object, string, assign } from 'superstruct'; @@ -7,11 +6,14 @@ import { array, object, string, assign } from 'superstruct'; import { confirmDialog, AddressStruct, - toJson, BaseRequestStruct, AccountRpcController, DeclareSignDetailsStruct, mapDeprecatedParams, + signerUI, + networkUI, + jsonDataUI, + headerUI, } from '../utils'; import { UserRejectedOpError } from '../utils/exceptions'; import { signDeclareTransaction as signDeclareTransactionUtil } from '../utils/starknetUtils'; @@ -96,34 +98,26 @@ export class SignDeclareTransactionRpc extends AccountRpcController< details: Infer, ) { const components: Component[] = []; - components.push(heading('Do you want to sign this transaction?')); + components.push(headerUI('Do you want to sign this transaction?')); + components.push( - row( - 'Network', - text({ - value: this.network.name, - markdown: false, - }), - ), + signerUI({ + address: details.senderAddress, + chainId: this.network.chainId, + }), ); + components.push( - row( - 'Signer Address', - text({ - value: details.senderAddress, - markdown: false, - }), - ), + networkUI({ + networkName: this.network.name, + }), ); components.push( - row( - 'Declare Transaction Details', - text({ - value: toJson(details), - markdown: false, - }), - ), + jsonDataUI({ + label: 'Declare Transaction Details', + data: details, + }), ); return await confirmDialog(components); diff --git a/packages/starknet-snap/src/rpcs/sign-message.test.ts b/packages/starknet-snap/src/rpcs/sign-message.test.ts index 1e219ffe..9b34d629 100644 --- a/packages/starknet-snap/src/rpcs/sign-message.test.ts +++ b/packages/starknet-snap/src/rpcs/sign-message.test.ts @@ -2,7 +2,6 @@ import { constants } from 'starknet'; import typedDataExample from '../__tests__/fixture/typedDataExample.json'; import type { SnapState } from '../types/snapState'; -import { toJson } from '../utils'; import { STARKNET_SEPOLIA_TESTNET_NETWORK } from '../utils/constants'; import { UserRejectedOpError, @@ -13,6 +12,8 @@ import { mockAccount, prepareMockAccount, prepareConfirmDialog, + buildSignerComponent, + buildJsonDataComponent, } from './__tests__/helper'; import { signMessage } from './sign-message'; import type { SignMessageParams } from './sign-message'; @@ -52,13 +53,14 @@ describe('signMessage', () => { it('renders confirmation dialog', async () => { const account = await mockAccount(constants.StarknetChainId.SN_SEPOLIA); + const { address, chainId } = account; prepareMockAccount(account, state); const { confirmDialogSpy } = prepareConfirmDialog(); const request = { chainId: constants.StarknetChainId.SN_SEPOLIA, - address: account.address, + address, typedDataMessage: typedDataExample, enableAuthorize: true, }; @@ -68,24 +70,8 @@ describe('signMessage', () => { const calls = confirmDialogSpy.mock.calls[0][0]; expect(calls).toStrictEqual([ { type: 'heading', value: 'Do you want to sign this message?' }, - { - type: 'row', - label: 'Message', - value: { - value: toJson(typedDataExample), - markdown: false, - type: 'text', - }, - }, - { - type: 'row', - label: 'Signer Address', - value: { - value: account.address, - markdown: false, - type: 'text', - }, - }, + buildSignerComponent(address, chainId), + buildJsonDataComponent('Message', typedDataExample), ]); }); diff --git a/packages/starknet-snap/src/rpcs/sign-message.ts b/packages/starknet-snap/src/rpcs/sign-message.ts index 79d8d692..80112ca3 100644 --- a/packages/starknet-snap/src/rpcs/sign-message.ts +++ b/packages/starknet-snap/src/rpcs/sign-message.ts @@ -1,17 +1,18 @@ import type { Component } from '@metamask/snaps-sdk'; -import { heading, row, text } from '@metamask/snaps-sdk'; import type { Infer } from 'superstruct'; import { array, object, string, assign } from 'superstruct'; import { confirmDialog, AddressStruct, - toJson, TypeDataStruct, AuthorizableStruct, BaseRequestStruct, AccountRpcController, mapDeprecatedParams, + signerUI, + jsonDataUI, + headerUI, } from '../utils'; import { UserRejectedOpError } from '../utils/exceptions'; import { signMessage as signMessageUtil } from '../utils/starknetUtils'; @@ -95,24 +96,18 @@ export class SignMessageRpc extends AccountRpcController< address: string, ) { const components: Component[] = []; - components.push(heading('Do you want to sign this message?')); + components.push(headerUI('Do you want to sign this message?')); components.push( - row( - 'Message', - text({ - value: toJson(typedDataMessage), - markdown: false, - }), - ), + signerUI({ + address, + chainId: this.network.chainId, + }), ); components.push( - row( - 'Signer Address', - text({ - value: address, - markdown: false, - }), - ), + jsonDataUI({ + label: 'Message', + data: typedDataMessage, + }), ); return await confirmDialog(components); diff --git a/packages/starknet-snap/src/rpcs/sign-transaction.test.ts b/packages/starknet-snap/src/rpcs/sign-transaction.test.ts index 0d4026a2..5200545a 100644 --- a/packages/starknet-snap/src/rpcs/sign-transaction.test.ts +++ b/packages/starknet-snap/src/rpcs/sign-transaction.test.ts @@ -3,7 +3,6 @@ import { constants } from 'starknet'; import transactionExample from '../__tests__/fixture/transactionExample.json'; // Assuming you have a similar fixture import type { SnapState } from '../types/snapState'; -import { toJson } from '../utils'; import { STARKNET_SEPOLIA_TESTNET_NETWORK } from '../utils/constants'; import { UserRejectedOpError, @@ -14,6 +13,9 @@ import { mockAccount, prepareMockAccount, prepareConfirmDialog, + buildNetworkComponent, + buildSignerComponent, + buildJsonDataComponent, } from './__tests__/helper'; import { signTransaction } from './sign-transaction'; import type { SignTransactionParams } from './sign-transaction'; @@ -67,6 +69,7 @@ describe('signTransaction', () => { it('renders confirmation dialog', async () => { const chainId = constants.StarknetChainId.SN_SEPOLIA; const account = await mockAccount(chainId); + const { address } = account; prepareMockAccount(account, state); const { confirmDialogSpy } = prepareConfirmDialog(); const request = createRequestParam(chainId, account.address, true); @@ -76,33 +79,9 @@ describe('signTransaction', () => { const calls = confirmDialogSpy.mock.calls[0][0]; expect(calls).toStrictEqual([ { type: 'heading', value: 'Do you want to sign this transaction?' }, - { - type: 'row', - label: 'Network', - value: { - value: STARKNET_SEPOLIA_TESTNET_NETWORK.name, - markdown: false, - type: 'text', - }, - }, - { - type: 'row', - label: 'Signer Address', - value: { - value: account.address, - markdown: false, - type: 'text', - }, - }, - { - type: 'row', - label: 'Transactions', - value: { - value: toJson(transactionExample.transactions), - markdown: false, - type: 'text', - }, - }, + buildSignerComponent(address, chainId), + buildNetworkComponent(STARKNET_SEPOLIA_TESTNET_NETWORK.name), + buildJsonDataComponent('Transaction', transactionExample.transactions), ]); }); diff --git a/packages/starknet-snap/src/rpcs/sign-transaction.ts b/packages/starknet-snap/src/rpcs/sign-transaction.ts index 592ec8e9..ccb61009 100644 --- a/packages/starknet-snap/src/rpcs/sign-transaction.ts +++ b/packages/starknet-snap/src/rpcs/sign-transaction.ts @@ -1,5 +1,4 @@ import type { DialogResult } from '@metamask/snaps-sdk'; -import { heading, row, text } from '@metamask/snaps-sdk'; import type { Call, InvocationsSignerDetails } from 'starknet'; import type { Infer } from 'superstruct'; import { array, object, string, assign, any } from 'superstruct'; @@ -11,8 +10,11 @@ import { BaseRequestStruct, AccountRpcController, CallDataStruct, - toJson, mapDeprecatedParams, + jsonDataUI, + signerUI, + networkUI, + headerUI, } from '../utils'; import { UserRejectedOpError } from '../utils/exceptions'; import { signTransactions } from '../utils/starknetUtils'; @@ -104,28 +106,18 @@ export class SignTransactionRpc extends AccountRpcController< transactions: Call[], ): Promise { return await confirmDialog([ - heading('Do you want to sign this transaction?'), - row( - 'Network', - text({ - value: this.network.name, - markdown: false, - }), - ), - row( - 'Signer Address', - text({ - value: address, - markdown: false, - }), - ), - row( - 'Transactions', - text({ - value: toJson(transactions), - markdown: false, - }), - ), + headerUI('Do you want to sign this transaction?'), + signerUI({ + address, + chainId: this.network.chainId, + }), + networkUI({ + networkName: this.network.name, + }), + jsonDataUI({ + label: 'Transaction', + data: transactions, + }), ]); } } diff --git a/packages/starknet-snap/src/rpcs/switch-network.test.ts b/packages/starknet-snap/src/rpcs/switch-network.test.ts index 5058a6c0..d01d6d36 100644 --- a/packages/starknet-snap/src/rpcs/switch-network.test.ts +++ b/packages/starknet-snap/src/rpcs/switch-network.test.ts @@ -12,7 +12,12 @@ import { InvalidRequestParamsError, UserRejectedOpError, } from '../utils/exceptions'; -import { prepareConfirmDialog } from './__tests__/helper'; +import { + buildDividerComponent, + buildNetworkComponent, + buildRowComponent, + prepareConfirmDialog, +} from './__tests__/helper'; import { switchNetwork } from './switch-network'; import type { SwitchNetworkParams } from './switch-network'; @@ -123,27 +128,9 @@ describe('switchNetwork', () => { expect(confirmDialogSpy).toHaveBeenCalledWith([ { type: 'heading', value: 'Do you want to switch to this network?' }, - { - type: 'row', - label: 'Chain Name', - value: { - value: requestNetwork.name, - markdown: false, - type: 'text', - }, - }, - { - type: 'divider', - }, - { - type: 'row', - label: 'Chain ID', - value: { - value: requestNetwork.chainId, - markdown: false, - type: 'text', - }, - }, + buildNetworkComponent(requestNetwork.name), + buildDividerComponent(), + buildRowComponent('Chain ID', requestNetwork.chainId), ]); }); diff --git a/packages/starknet-snap/src/rpcs/switch-network.ts b/packages/starknet-snap/src/rpcs/switch-network.ts index 61bc0fbf..12ac65b8 100644 --- a/packages/starknet-snap/src/rpcs/switch-network.ts +++ b/packages/starknet-snap/src/rpcs/switch-network.ts @@ -1,5 +1,4 @@ import type { Component } from '@metamask/snaps-sdk'; -import { divider, heading, row, text } from '@metamask/snaps-sdk'; import type { Infer } from 'superstruct'; import { assign, boolean } from 'superstruct'; @@ -9,6 +8,10 @@ import { AuthorizableStruct, BaseRequestStruct, RpcController, + networkUI, + rowUI, + dividerUI, + headerUI, } from '../utils'; import { InvalidNetworkError, UserRejectedOpError } from '../utils/exceptions'; @@ -98,25 +101,18 @@ export class SwitchNetworkRpc extends RpcController< networkChainId: string, ) { const components: Component[] = []; - components.push(heading('Do you want to switch to this network?')); + components.push(headerUI('Do you want to switch to this network?')); components.push( - row( - 'Chain Name', - text({ - value: networkName, - markdown: false, - }), - ), + networkUI({ + networkName, + }), ); - components.push(divider()); + components.push(dividerUI()); components.push( - row( - 'Chain ID', - text({ - value: networkChainId, - markdown: false, - }), - ), + rowUI({ + label: 'Chain ID', + value: networkChainId, + }), ); return await confirmDialog(components); diff --git a/packages/starknet-snap/src/rpcs/watch-asset.test.ts b/packages/starknet-snap/src/rpcs/watch-asset.test.ts index 2569ca7e..c38bce01 100644 --- a/packages/starknet-snap/src/rpcs/watch-asset.test.ts +++ b/packages/starknet-snap/src/rpcs/watch-asset.test.ts @@ -12,7 +12,9 @@ import { UserRejectedOpError, } from '../utils/exceptions'; import { + buildAddressComponent, buildDividerComponent, + buildNetworkComponent, buildRowComponent, prepareConfirmDialog, } from './__tests__/helper'; @@ -109,9 +111,13 @@ describe('WatchAssetRpc', () => { expect(confirmDialogSpy).toHaveBeenCalledWith([ { type: 'heading', value: 'Do you want to add this token?' }, - buildRowComponent('Network', network.name), + buildNetworkComponent(network.name), buildDividerComponent(), - buildRowComponent('Token Address', request.tokenAddress), + buildAddressComponent( + 'Token Address', + request.tokenAddress, + network.chainId, + ), buildDividerComponent(), buildRowComponent('Token Name', request.tokenName), buildDividerComponent(), diff --git a/packages/starknet-snap/src/rpcs/watch-asset.ts b/packages/starknet-snap/src/rpcs/watch-asset.ts index f011efcb..39b364fc 100644 --- a/packages/starknet-snap/src/rpcs/watch-asset.ts +++ b/packages/starknet-snap/src/rpcs/watch-asset.ts @@ -1,5 +1,4 @@ import type { Component } from '@metamask/snaps-sdk'; -import { divider, heading, row, text } from '@metamask/snaps-sdk'; import type { Infer } from 'superstruct'; import { assign, boolean, min, number, object, optional } from 'superstruct'; @@ -14,6 +13,11 @@ import { TokenNameStruct, TokenSymbolStruct, isPreloadedToken, + addressUI, + networkUI, + rowUI, + dividerUI, + headerUI, } from '../utils'; import { DEFAULT_DECIMAL_PLACES } from '../utils/constants'; import { @@ -131,7 +135,13 @@ export class WatchAssetRpc extends RpcController< const erc20Token: Erc20Token = this.buildErc20Token(params); const network = await this.getNetworkFromChainId(chainId); - if (!(await this.getWatchAssetConsensus(network.name, erc20Token))) { + if ( + !(await this.getWatchAssetConsensus( + network.name, + network.chainId, + erc20Token, + )) + ) { throw new UserRejectedOpError() as unknown as Error; } @@ -142,18 +152,27 @@ export class WatchAssetRpc extends RpcController< protected async getWatchAssetConsensus( networkName: string, + chainId: string, erc20Token: Erc20Token, ) { const { address, name, symbol, decimals } = erc20Token; - const componentPairs = [ + const componentPairs: { + label?: string; + value?: string; + component?: Component; + }[] = [ { - label: 'Network', - value: networkName, + component: networkUI({ + networkName, + }), }, { - label: 'Token Address', - value: address, + component: addressUI({ + label: 'Token Address', + address, + chainId, + }), }, { label: 'Token Name', @@ -168,20 +187,24 @@ export class WatchAssetRpc extends RpcController< value: decimals.toString(), }, ]; + const components: Component[] = []; - components.push(heading('Do you want to add this token?')); - componentPairs.forEach(({ label, value }, idx) => { - components.push( - row( - label, - text({ + components.push(headerUI('Do you want to add this token?')); + + componentPairs.forEach(({ label, value, component }, idx) => { + if (component) { + components.push(component); + } else if (label && value) { + components.push( + rowUI({ + label, value, - markdown: false, }), - ), - ); + ); + } + if (idx < componentPairs.length - 1) { - components.push(divider()); + components.push(dividerUI()); } }); return await confirmDialog(components);