Skip to content

Commit

Permalink
feat: replace rpc dialogs with jsx
Browse files Browse the repository at this point in the history
  • Loading branch information
khanti42 committed Nov 19, 2024
1 parent ef8076e commit 9c78359
Show file tree
Hide file tree
Showing 12 changed files with 297 additions and 215 deletions.
23 changes: 23 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 * as snapUiUtils from '../../ui/utils';
import { getExplorerUrl, shortenAddress, toJson } from '../../utils';
import * as snapHelper from '../../utils/snap';
import * as snapUtils from '../../utils/snapUtils';
Expand Down Expand Up @@ -58,6 +59,28 @@ export function prepareConfirmDialog() {
};
}

/**
*
*/
export function prepareConfirmDialogJsx() {
const confirmDialogSpy = jest.spyOn(snapUiUtils, 'confirmDialog');
confirmDialogSpy.mockResolvedValue(true);
return {
confirmDialogSpy,
};
}

/**
*
*/
export function prepareAlertDialogJsx() {
const alertDialogSpy = jest.spyOn(snapUiUtils, 'alertDialog');
alertDialogSpy.mockResolvedValue(true);
return {
alertDialogSpy,
};
}

/**
*
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Box, Copyable, Heading, Icon, Text } from '@metamask/snaps-sdk/jsx';
import { constants } from 'starknet';

import type { SnapState } from '../types/snapState';
Expand All @@ -8,9 +9,9 @@ import {
} from '../utils/exceptions';
import {
mockAccount,
prepareAlertDialog,
prepareMockAccount,
prepareConfirmDialog,
prepareConfirmDialogJsx,
prepareAlertDialogJsx,
} from './__tests__/helper';
import { displayPrivateKey } from './display-private-key';
import type { DisplayPrivateKeyParams } from './display-private-key';
Expand Down Expand Up @@ -40,8 +41,8 @@ describe('displayPrivateKey', () => {
const chainId = constants.StarknetChainId.SN_SEPOLIA;
const account = await mockAccount(chainId);
prepareMockAccount(account, state);
prepareConfirmDialog();
const { alertDialogSpy } = prepareAlertDialog();
prepareConfirmDialogJsx();
const { alertDialogSpy } = prepareAlertDialogJsx();

const request = createRequestParam(chainId, account.address);

Expand All @@ -51,18 +52,25 @@ describe('displayPrivateKey', () => {

const calls = alertDialogSpy.mock.calls[0][0];

expect(calls).toStrictEqual([
{ type: 'text', value: 'Starknet Account Private Key' },
{ type: 'copyable', value: account.privateKey },
]);
expect(calls).toStrictEqual({
children: (
<Box>
<Heading>Starknet Account Private Key</Heading>
<Text>
Below is your Starknet Account private key. Keep it confidential.
</Text>
<Copyable value={account.privateKey} />
</Box>
),
});
});

it('renders confirmation dialog', async () => {
const chainId = constants.StarknetChainId.SN_SEPOLIA;
const account = await mockAccount(chainId);
prepareMockAccount(account, state);
const { confirmDialogSpy } = prepareConfirmDialog();
prepareAlertDialog();
const { confirmDialogSpy } = prepareConfirmDialogJsx();
prepareAlertDialogJsx();

const request = createRequestParam(chainId, account.address);

Expand All @@ -72,17 +80,28 @@ describe('displayPrivateKey', () => {

const calls = confirmDialogSpy.mock.calls[0][0];

expect(calls).toStrictEqual([
{ type: 'text', value: 'Do you want to export your private key?' },
]);
expect(calls).toStrictEqual({
children: (
<Box>
<Heading>Are you sure you want to reveal your private key?</Heading>
<Box direction="horizontal">
<Icon name="warning" size="md" />
<Text>
Confirming this action will display your private key. Ensure you
are in a secure environment.
</Text>
</Box>
</Box>
),
});
});

it('throws `UserRejectedOpError` if user denies the operation', async () => {
const chainId = constants.StarknetChainId.SN_SEPOLIA;
const account = await mockAccount(chainId);
prepareMockAccount(account, state);
const { confirmDialogSpy } = prepareConfirmDialog();
prepareAlertDialog();
const { confirmDialogSpy } = prepareConfirmDialogJsx();
prepareAlertDialogJsx();

confirmDialogSpy.mockResolvedValue(false);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { copyable, text } from '@metamask/snaps-sdk';
import { Box, Copyable, Heading, Icon, Text } from '@metamask/snaps-sdk/jsx';
import { type Infer, object, literal, assign } from 'superstruct';

import { alertDialog, confirmDialog } from '../ui/utils';
import {
AccountRpcController,
AddressStruct,
confirmDialog,
alertDialog,
BaseRequestStruct,
} from '../utils';
import { UserRejectedOpError } from '../utils/exceptions';
Expand Down Expand Up @@ -56,18 +55,36 @@ export class DisplayPrivateKeyRpc extends AccountRpcController<
// eslint-disable-next-line @typescript-eslint/no-unused-vars
params: DisplayPrivateKeyParams,
): Promise<DisplayPrivateKeyResponse> {
const confirmComponents = [text('Do you want to export your private key?')];

if (!(await confirmDialog(confirmComponents))) {
if (
!(await confirmDialog({
children: (
<Box>
<Heading>Are you sure you want to reveal your private key?</Heading>
<Box direction="horizontal">
<Icon name="warning" size="md" />
<Text>
Confirming this action will display your private key. Ensure you
are in a secure environment.
</Text>
</Box>
</Box>
),
}))
) {
throw new UserRejectedOpError() as unknown as Error;
}

const alertComponents = [
text('Starknet Account Private Key'),
copyable(this.account.privateKey),
];

await alertDialog(alertComponents);
await alertDialog({
children: (
<Box>
<Heading>Starknet Account Private Key</Heading>
<Text>
Below is your Starknet Account private key. Keep it confidential.
</Text>
<Copyable value={this.account.privateKey} />
</Box>
),
});

return null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Box, Heading, Section } from '@metamask/snaps-sdk/jsx';
import type { DeclareSignerDetails } from 'starknet';
import { constants } from 'starknet';

import type { SnapState } from '../types/snapState';
import { AddressUI, JsonDataUI, NetworkUI } from '../ui/fragments';
import { STARKNET_SEPOLIA_TESTNET_NETWORK } from '../utils/constants';
import {
UserRejectedOpError,
Expand All @@ -11,10 +13,7 @@ import * as starknetUtils from '../utils/starknetUtils';
import {
mockAccount,
prepareMockAccount,
prepareConfirmDialog,
buildSignerComponent,
buildNetworkComponent,
buildJsonDataComponent,
prepareConfirmDialogJsx as prepareConfirmDialog,
} from './__tests__/helper';
import { signDeclareTransaction } from './sign-declare-transaction';
import type { SignDeclareTransactionParams } from './sign-declare-transaction';
Expand Down Expand Up @@ -79,12 +78,21 @@ describe('signDeclareTransaction', () => {
await signDeclareTransaction.execute(request);

const calls = confirmDialogSpy.mock.calls[0][0];
expect(calls).toStrictEqual([
{ type: 'heading', value: 'Do you want to sign this transaction?' },
buildSignerComponent(address, chainId),
buildNetworkComponent(STARKNET_SEPOLIA_TESTNET_NETWORK.name),
buildJsonDataComponent('Declare Transaction Details', request.details),
]);
expect(calls).toStrictEqual({
children: (
<Box>
<Heading>Do you want to sign this transaction?</Heading>
<Section>
<AddressUI label="Signer" address={address} chainId={chainId} />
<NetworkUI networkName={STARKNET_SEPOLIA_TESTNET_NETWORK.name} />
<JsonDataUI
label={'Declare Transaction Details'}
data={request.details}
/>
</Section>
</Box>
),
});
});

it('throws `UserRejectedOpError` if user denied the operation', async () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
import type { Component } from '@metamask/snaps-sdk';
import { Box, Heading, Section } from '@metamask/snaps-sdk/jsx';
import type { DeclareSignerDetails } from 'starknet';
import type { Infer } from 'superstruct';
import { array, object, string, assign } from 'superstruct';

import { AddressUI, JsonDataUI, NetworkUI } from '../ui/fragments';
import { confirmDialog } from '../ui/utils';
import {
confirmDialog,
AddressStruct,
BaseRequestStruct,
AccountRpcController,
DeclareSignDetailsStruct,
mapDeprecatedParams,
signerUI,
networkUI,
jsonDataUI,
headerUI,
} from '../utils';
import { UserRejectedOpError } from '../utils/exceptions';
import { signDeclareTransaction as signDeclareTransactionUtil } from '../utils/starknetUtils';
Expand Down Expand Up @@ -97,30 +94,22 @@ export class SignDeclareTransactionRpc extends AccountRpcController<
protected async getSignDeclareTransactionConsensus(
details: Infer<typeof DeclareSignDetailsStruct>,
) {
const components: Component[] = [];
components.push(headerUI('Do you want to sign this transaction?'));

components.push(
signerUI({
address: details.senderAddress,
chainId: this.network.chainId,
}),
);

components.push(
networkUI({
networkName: this.network.name,
}),
);

components.push(
jsonDataUI({
label: 'Declare Transaction Details',
data: details,
}),
);

return await confirmDialog(components);
return await confirmDialog({
children: (
<Box>
<Heading>Do you want to sign this transaction?</Heading>
<Section>
<AddressUI
label="Signer"
address={details.senderAddress}
chainId={this.network.chainId}
/>
<NetworkUI networkName={this.network.name} />
<JsonDataUI label={'Declare Transaction Details'} data={details} />
</Section>
</Box>
),
});
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { Box, Heading, Section } from '@metamask/snaps-sdk/jsx';
import type { InvocationsSignerDetails } from 'starknet';
import { constants } from 'starknet';

import transactionExample from '../__tests__/fixture/transactionExample.json'; // Assuming you have a similar fixture
import type { SnapState } from '../types/snapState';
import { AddressUI, JsonDataUI, NetworkUI } from '../ui/fragments';
import { STARKNET_SEPOLIA_TESTNET_NETWORK } from '../utils/constants';
import {
UserRejectedOpError,
Expand All @@ -12,10 +14,7 @@ import * as starknetUtils from '../utils/starknetUtils';
import {
mockAccount,
prepareMockAccount,
prepareConfirmDialog,
buildNetworkComponent,
buildSignerComponent,
buildJsonDataComponent,
prepareConfirmDialogJsx as prepareConfirmDialog,
} from './__tests__/helper';
import { signTransaction } from './sign-transaction';
import type { SignTransactionParams } from './sign-transaction';
Expand Down Expand Up @@ -77,12 +76,21 @@ describe('signTransaction', () => {
await signTransaction.execute(request);

const calls = confirmDialogSpy.mock.calls[0][0];
expect(calls).toStrictEqual([
{ type: 'heading', value: 'Do you want to sign this transaction?' },
buildSignerComponent(address, chainId),
buildNetworkComponent(STARKNET_SEPOLIA_TESTNET_NETWORK.name),
buildJsonDataComponent('Transaction', transactionExample.transactions),
]);
expect(calls).toStrictEqual({
children: (
<Box>
<Heading>Do you want to sign this transaction?</Heading>
<Section>
<AddressUI label="Signer" address={address} chainId={chainId} />
<NetworkUI networkName={STARKNET_SEPOLIA_TESTNET_NETWORK.name} />
<JsonDataUI
label={'Transactions'}
data={transactionExample.transactions}
/>
</Section>
</Box>
),
});
});

it('does not render the confirmation dialog if enableAuthorize is false', async () => {
Expand Down
Loading

0 comments on commit 9c78359

Please sign in to comment.