Skip to content

Commit

Permalink
refactor(SNAP): apply the centralise snap ui component into the RPCs (#…
Browse files Browse the repository at this point in the history
…405)

* chore: add utils to manage snap ui

* chore: adopt centralise snap ui component into the rpcs

* chore: remove contract and casm from declare

* fix: execute txn dialog

---------

Co-authored-by: khanti42 <florin.dzeladini@consensys.net>
  • Loading branch information
stanleyyconsensys and khanti42 authored Oct 25, 2024
1 parent 90f94a5 commit a77fede
Show file tree
Hide file tree
Showing 14 changed files with 250 additions and 344 deletions.
24 changes: 24 additions & 0 deletions packages/starknet-snap/src/rpcs/__tests__/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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
Expand Down
10 changes: 5 additions & 5 deletions packages/starknet-snap/src/rpcs/declare-contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -13,7 +13,9 @@ import {
import * as starknetUtils from '../utils/starknetUtils';
import {
buildDividerComponent,
buildNetworkComponent,
buildRowComponent,
buildSignerComponent,
generateRandomFee,
mockAccount,
prepareConfirmDialog,
Expand Down Expand Up @@ -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(),
Expand Down
107 changes: 32 additions & 75 deletions packages/starknet-snap/src/rpcs/declare-contract.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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';
Expand Down Expand Up @@ -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,
}),
);
}

Expand Down
116 changes: 52 additions & 64 deletions packages/starknet-snap/src/rpcs/execute-txn.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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';
Expand Down Expand Up @@ -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[] = [];
Expand All @@ -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;
Expand All @@ -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(
Expand All @@ -332,7 +321,6 @@ export class ExecuteTxnRpc extends AccountRpcController<
);
}
}
components.push(divider());
}

return await confirmDialog(components);
Expand Down
Loading

0 comments on commit a77fede

Please sign in to comment.