Skip to content

Commit

Permalink
feat: replace rpc dialogs with jsx (#422)
Browse files Browse the repository at this point in the history
* chore: add jsx support in snap (#415)

* chore: add jsx support in snap

* chore: fix comment

* chore: update yarn.lock

* feat: add common jsx component (#417)

* chore: add jsx support in snap

* chore: add jsx support in snap

* feat: jsx support management

* feat: common jsx components and fragments

* chore: fix test and lint

* chore: rollback jsx support detection not here

* chore: fix comment

* chore: fix comments

* chore: fix comments

* chore: update yarn.lock

* chore: update yarn.lock

* chore: add react-dom types

* chore: fix comments

* chore: rebase wallet-ui changes happening elsewhere

* feat: add fee token selection interactive UI (#418)

* chore: add jsx support in snap

* chore: add jsx support in snap

* feat: jsx support management

* feat: common jsx components and fragments

* chore: fix test and lint

* feat: add interactive-ui for execute txn

* fix: add mutex in jsx support detection mechanism

* chore: fixture request addapted

* chore: ensure test pass

* chore: lint

* chore: remove console.log

* chore: rollback jsx support detection not here

* chore: rollback index.tsx

* chore: fix comment

* chore: fix comments

* chore: fix comments

* chore: update yarn.lock

* chore: update yarn.lock

* chore: update yarn.lock

* chore: rebase wallet-ui changes happening elsewhere

* chore: fix comments

* chore: fix comments

* chore: fix comments

* chore: fix comments

* chore: fix comments

* chore: fix comments

* chore: removed utils

* fix: implement comments

* fix: implement comments

* chore: fix comments

* Update packages/starknet-snap/src/ui/components/ExecuteTxnUI.tsx

Co-authored-by: Stanley Yuen <[email protected]>

* Update packages/starknet-snap/src/ui/components/ExecuteTxnUI.tsx

Co-authored-by: Stanley Yuen <[email protected]>

* Update packages/starknet-snap/src/ui/utils.test.tsx

Co-authored-by: Stanley Yuen <[email protected]>

* Update packages/starknet-snap/src/types/snapState.ts

Co-authored-by: Stanley Yuen <[email protected]>

* Update packages/starknet-snap/src/ui/components/ExecuteTxnUI.tsx

Co-authored-by: Stanley Yuen <[email protected]>

* Update packages/starknet-snap/src/ui/components/ExecuteTxnUI.tsx

Co-authored-by: Stanley Yuen <[email protected]>

* Update packages/starknet-snap/src/ui/utils.test.tsx

Co-authored-by: Stanley Yuen <[email protected]>

* Update packages/starknet-snap/src/ui/utils.test.tsx

Co-authored-by: Stanley Yuen <[email protected]>

* chore: fix comments

* chore: fix comments

* chore: fix comments

* chore: lint

---------

Co-authored-by: Stanley Yuen <[email protected]>

* feat: adopt fee token selection dialog in RPC `starkNet_executeTxn` (#419)

* chore: add jsx support in snap

* chore: add jsx support in snap

* feat: jsx support management

* feat: common jsx components and fragments

* chore: fix test and lint

* feat: add interactive-ui for execute txn

* fix: add mutex in jsx support detection mechanism

* chore: fixture request addapted

* chore: ensure test pass

* chore: lint

* feat: add interactive-ui in execute txn

* chore: remove console.log

* chore: missing helper in tests

* chore: lint

* chore: rollback jsx support detection not here

* chore: rollback index.tsx

* chore: fix comment

* chore: fix comments

* chore: fix comments

* chore: update yarn.lock

* chore: update yarn.lock

* feat: update wallet-ui message

* chore: update yarn.lock

* chore: rebase wallet-ui changes happening elsewhere

* chore: rebase wallet-ui changes happening elsewhere

* chore: fix comments

* chore: fix comments

* fix: formatter-utils

* chore: fix comments

* chore: fix comments

* chore: lint

* chore: lint

* chore: fix comments

* chore: fix comments

* chore: fix comments

* chore: fix comments

* chore: removed utils

* fix: implement comments

* fix: implement comments

* chore: fix comments

* chore: fix comments

* Update packages/starknet-snap/src/ui/components/ExecuteTxnUI.tsx

Co-authored-by: Stanley Yuen <[email protected]>

* Update packages/starknet-snap/src/ui/components/ExecuteTxnUI.tsx

Co-authored-by: Stanley Yuen <[email protected]>

* Update packages/starknet-snap/src/ui/utils.test.tsx

Co-authored-by: Stanley Yuen <[email protected]>

* Update packages/starknet-snap/src/types/snapState.ts

Co-authored-by: Stanley Yuen <[email protected]>

* Update packages/starknet-snap/src/ui/components/ExecuteTxnUI.tsx

Co-authored-by: Stanley Yuen <[email protected]>

* Update packages/starknet-snap/src/ui/components/ExecuteTxnUI.tsx

Co-authored-by: Stanley Yuen <[email protected]>

* Update packages/starknet-snap/src/ui/utils.test.tsx

Co-authored-by: Stanley Yuen <[email protected]>

* Update packages/starknet-snap/src/ui/utils.test.tsx

Co-authored-by: Stanley Yuen <[email protected]>

* chore: fix comments

* chore: fix comments

* chore: fix comments

* chore: fix comments

* chore: fix comments

* chore: lint

* chore: lint

* chore: fix comments

* chore: fix comments

---------

Co-authored-by: Stanley Yuen <[email protected]>

* chore: fix tests

* feat: replace rpc dialogs with jsx

* feat: add sign-message in jsx

* feat: add jsx support detection (#416)

* chore: add jsx support in snap

* chore: add jsx support in snap

* feat: jsx support management

* chore: fix test and lint

* fix: add mutex in jsx support detection mechanism

* chore: ensure test pass

* feat: new init state manager class to manage state init and support check

* fix: wait for hooks in request handler

* chore: lint

* fix: set jsx support to true before showing dialog

* chore: fix comment

* fix: moved ping pong

* chore: lint

* chore: rollback state

* chore: lint

* chore: fix comments

* fix: test suits

* fix: use functional component

* feat: add event listener for fee token selection (#420)

* chore: add jsx support in snap

* chore: add jsx support in snap

* feat: jsx support management

* feat: common jsx components and fragments

* chore: fix test and lint

* feat: add interactive-ui for execute txn

* fix: add mutex in jsx support detection mechanism

* chore: fixture request addapted

* chore: ensure test pass

* chore: lint

* feat: add interactive-ui in execute txn

* chore: remove console.log

* chore: missing helper in tests

* chore: lint

* feat: event-handler in index.tsx

* feat: event controller

* feat: error handling and tests suits for event controller

* fix: test suits

* fix: signer in fee-token-selector

* chore: rollback jsx support detection not here

* chore: rollback index.tsx

* chore: lint

* chore: fix comment

* chore: fix comments

* chore: fix comments

* chore: update yarn.lock

* chore: update yarn.lock

* feat: update wallet-ui message

* chore: update yarn.lock

* chore: rebase wallet-ui changes happening elsewhere

* chore: rebase wallet-ui changes happening elsewhere

* chore: fix comments

* chore: fix comments

* fix: formatter-utils

* chore: fix comments

* chore: fix comments

* chore: lint

* chore: lint

* chore: fix comments

* chore: fix comments

* chore: fix comments

* chore: fix comments

* chore: lint

* chore: lint

* chore: removed utils

* feat: add comments in user-input classes

* fix: implement comments

* fix: implement comments

* chore: fix comments

* chore: fix comments

* Update packages/starknet-snap/src/ui/components/ExecuteTxnUI.tsx

Co-authored-by: Stanley Yuen <[email protected]>

* Update packages/starknet-snap/src/ui/components/ExecuteTxnUI.tsx

Co-authored-by: Stanley Yuen <[email protected]>

* Update packages/starknet-snap/src/ui/utils.test.tsx

Co-authored-by: Stanley Yuen <[email protected]>

* Update packages/starknet-snap/src/types/snapState.ts

Co-authored-by: Stanley Yuen <[email protected]>

* Update packages/starknet-snap/src/ui/components/ExecuteTxnUI.tsx

Co-authored-by: Stanley Yuen <[email protected]>

* Update packages/starknet-snap/src/ui/components/ExecuteTxnUI.tsx

Co-authored-by: Stanley Yuen <[email protected]>

* Update packages/starknet-snap/src/ui/utils.test.tsx

Co-authored-by: Stanley Yuen <[email protected]>

* Update packages/starknet-snap/src/ui/utils.test.tsx

Co-authored-by: Stanley Yuen <[email protected]>

* chore: fix comments

* chore: fix comments

* chore: fix comments

* chore: fix comments

* chore: fix comments

* chore: lint

* chore: lint

* chore: fix rebase

* chore: fix comments

* chore: fix comments

* chore: fix comments

* chore: rebase

* fix: removed user-input controller abstract class and derived ones

* chore: rollback execute-txn

* chore: update

* chore: fix comments

* chore: fix comments

* chore: refine the code

* fix: add execution test

* fix: update execute txn test

---------

Co-authored-by: Stanley Yuen <[email protected]>

* chore: lint

* chore: docstring

* chore: lint

* chore: docstring

* chore: lint

* chore: lint

* chore: lint

---------

Co-authored-by: Stanley Yuen <[email protected]>
  • Loading branch information
khanti42 and stanleyyconsensys authored Nov 21, 2024
1 parent abfc0e5 commit 3debd47
Show file tree
Hide file tree
Showing 20 changed files with 588 additions and 319 deletions.
86 changes: 86 additions & 0 deletions packages/starknet-snap/src/rpcs/__tests__/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type { StarknetAccount } from '../../__tests__/helper';
import { generateAccounts, generateRandomValue } from '../../__tests__/helper';
import { TransactionRequestStateManager } from '../../state/request-state-manager';
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 @@ -80,6 +81,91 @@ export function prepareConfirmDialog() {
};
}

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

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

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

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

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

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

/**
*
*/
export function prepareRenderDisplayPrivateKeyAlertUI() {
const alertDialogSpy = jest.spyOn(
snapUiUtils,
'renderDisplayPrivateKeyAlertUI',
);
return {
alertDialogSpy,
};
}

/**
*
*/
Expand Down
31 changes: 9 additions & 22 deletions packages/starknet-snap/src/rpcs/display-private-key.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import {
} from '../utils/exceptions';
import {
mockAccount,
prepareAlertDialog,
prepareMockAccount,
prepareConfirmDialog,
prepareRenderDisplayPrivateKeyAlertUI,
prepareRenderDisplayPrivateKeyConfirmUI,
} from './__tests__/helper';
import { displayPrivateKey } from './display-private-key';
import type { DisplayPrivateKeyParams } from './display-private-key';
Expand Down Expand Up @@ -40,49 +40,36 @@ describe('displayPrivateKey', () => {
const chainId = constants.StarknetChainId.SN_SEPOLIA;
const account = await mockAccount(chainId);
prepareMockAccount(account, state);
prepareConfirmDialog();
const { alertDialogSpy } = prepareAlertDialog();
prepareRenderDisplayPrivateKeyConfirmUI();
const { alertDialogSpy } = prepareRenderDisplayPrivateKeyAlertUI();

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

await displayPrivateKey.execute(request);

expect(alertDialogSpy).toHaveBeenCalledTimes(1);

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

expect(calls).toStrictEqual([
{ type: 'text', value: 'Starknet Account Private Key' },
{ type: 'copyable', value: account.privateKey },
]);
expect(alertDialogSpy).toHaveBeenCalledWith(account.privateKey);
});

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 } = prepareRenderDisplayPrivateKeyConfirmUI();
prepareRenderDisplayPrivateKeyAlertUI();

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

await displayPrivateKey.execute(request);

expect(confirmDialogSpy).toHaveBeenCalledTimes(1);

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

expect(calls).toStrictEqual([
{ type: 'text', value: 'Do you want to export your private key?' },
]);
});

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 } = prepareRenderDisplayPrivateKeyConfirmUI();
prepareRenderDisplayPrivateKeyAlertUI();

confirmDialogSpy.mockResolvedValue(false);

Expand Down
19 changes: 6 additions & 13 deletions packages/starknet-snap/src/rpcs/display-private-key.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { copyable, text } from '@metamask/snaps-sdk';
import { type Infer, object, literal, assign } from 'superstruct';

import {
renderDisplayPrivateKeyAlertUI,
renderDisplayPrivateKeyConfirmUI,
} from '../ui/utils';
import {
AccountRpcController,
AddressStruct,
confirmDialog,
alertDialog,
BaseRequestStruct,
} from '../utils';
import { UserRejectedOpError } from '../utils/exceptions';
Expand Down Expand Up @@ -56,19 +57,11 @@ 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 renderDisplayPrivateKeyConfirmUI())) {
throw new UserRejectedOpError() as unknown as Error;
}

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

await alertDialog(alertComponents);

await renderDisplayPrivateKeyAlertUI(this.account.privateKey);
return null;
}
}
Expand Down
24 changes: 10 additions & 14 deletions packages/starknet-snap/src/rpcs/sign-declare-transaction.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@ import * as starknetUtils from '../utils/starknetUtils';
import {
mockAccount,
prepareMockAccount,
prepareConfirmDialog,
buildSignerComponent,
buildNetworkComponent,
buildJsonDataComponent,
prepareRenderSignDeclareTransactionUI,
} from './__tests__/helper';
import { signDeclareTransaction } from './sign-declare-transaction';
import type { SignDeclareTransactionParams } from './sign-declare-transaction';
Expand Down Expand Up @@ -52,7 +49,7 @@ describe('signDeclareTransaction', () => {
const account = await mockAccount(chainId);

prepareMockAccount(account, state);
prepareConfirmDialog();
prepareRenderSignDeclareTransactionUI();

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

Expand All @@ -72,27 +69,26 @@ describe('signDeclareTransaction', () => {
const { address } = account;

prepareMockAccount(account, state);
const { confirmDialogSpy } = prepareConfirmDialog();
const { confirmDialogSpy } = prepareRenderSignDeclareTransactionUI();

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?' },
buildSignerComponent(address, chainId),
buildNetworkComponent(STARKNET_SEPOLIA_TESTNET_NETWORK.name),
buildJsonDataComponent('Declare Transaction Details', request.details),
]);
expect(confirmDialogSpy).toHaveBeenCalledWith({
senderAddress: address,
chainId,
networkName: STARKNET_SEPOLIA_TESTNET_NETWORK.name,
declareTransactions: request.details,
});
});

it('throws `UserRejectedOpError` if user denied the operation', async () => {
const chainId = constants.StarknetChainId.SN_SEPOLIA;
const account = await mockAccount(chainId);

prepareMockAccount(account, state);
const { confirmDialogSpy } = prepareConfirmDialog();
const { confirmDialogSpy } = prepareRenderSignDeclareTransactionUI();

confirmDialogSpy.mockResolvedValue(false);

Expand Down
45 changes: 9 additions & 36 deletions packages/starknet-snap/src/rpcs/sign-declare-transaction.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
import type { Component } from '@metamask/snaps-sdk';
import type { DeclareSignerDetails } from 'starknet';
import type { Infer } from 'superstruct';
import { array, object, string, assign } from 'superstruct';

import { renderSignDeclareTransactionUI } 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 @@ -84,7 +79,14 @@ export class SignDeclareTransactionRpc extends AccountRpcController<
params: SignDeclareTransactionParams,
): Promise<SignDeclareTransactionResponse> {
const { details } = params;
if (!(await this.getSignDeclareTransactionConsensus(details))) {
if (
!(await renderSignDeclareTransactionUI({
senderAddress: details.senderAddress,
networkName: this.network.name,
chainId: this.network.chainId,
declareTransactions: details,
}))
) {
throw new UserRejectedOpError() as unknown as Error;
}

Expand All @@ -93,35 +95,6 @@ export class SignDeclareTransactionRpc extends AccountRpcController<
details as unknown as DeclareSignerDetails,
)) as unknown as SignDeclareTransactionResponse;
}

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);
}
}

export const signDeclareTransaction = new SignDeclareTransactionRpc();
24 changes: 10 additions & 14 deletions packages/starknet-snap/src/rpcs/sign-message.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ import * as starknetUtils from '../utils/starknetUtils';
import {
mockAccount,
prepareMockAccount,
prepareConfirmDialog,
buildSignerComponent,
buildJsonDataComponent,
prepareRenderSignMessageUI,
} from './__tests__/helper';
import { signMessage } from './sign-message';
import type { SignMessageParams } from './sign-message';
Expand All @@ -33,7 +31,7 @@ describe('signMessage', () => {
const account = await mockAccount(constants.StarknetChainId.SN_SEPOLIA);

prepareMockAccount(account, state);
prepareConfirmDialog();
prepareRenderSignMessageUI();

const expectedResult = await starknetUtils.signMessage(
account.privateKey,
Expand All @@ -56,30 +54,28 @@ describe('signMessage', () => {
const { address, chainId } = account;

prepareMockAccount(account, state);
const { confirmDialogSpy } = prepareConfirmDialog();
const { confirmDialogSpy } = prepareRenderSignMessageUI();

const request = {
chainId: constants.StarknetChainId.SN_SEPOLIA,
chainId: chainId as constants.StarknetChainId,
address,
typedDataMessage: typedDataExample,
enableAuthorize: true,
};

await signMessage.execute(request);

const calls = confirmDialogSpy.mock.calls[0][0];
expect(calls).toStrictEqual([
{ type: 'heading', value: 'Do you want to sign this message?' },
buildSignerComponent(address, chainId),
buildJsonDataComponent('Message', typedDataExample),
]);
expect(confirmDialogSpy).toHaveBeenCalledWith({
address,
chainId,
typedDataMessage: typedDataExample,
});
});

it('throws `UserRejectedOpError` if user denied the operation', async () => {
const account = await mockAccount(constants.StarknetChainId.SN_SEPOLIA);

prepareMockAccount(account, state);
const { confirmDialogSpy } = prepareConfirmDialog();
const { confirmDialogSpy } = prepareRenderSignMessageUI();

confirmDialogSpy.mockResolvedValue(false);

Expand Down
Loading

0 comments on commit 3debd47

Please sign in to comment.