Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(HomePage): revamp snap onHomePage handler #345

Merged
merged 19 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
0f7c0d6
refactor: dappUrl function
stanleyyconsensys Sep 4, 2024
f061146
chore: update config
stanleyyconsensys Sep 4, 2024
e6a6663
chore: fix lint
stanleyyconsensys Sep 4, 2024
aea4234
refactor: revamp on home page handler
stanleyyconsensys Sep 4, 2024
6cc1181
fix: lint
stanleyyconsensys Sep 4, 2024
475e3e2
chore: update home page controller location
stanleyyconsensys Sep 4, 2024
6ce7f1a
Merge branch 'main' into chore/refactor-dapp-url-utils
stanleyyconsensys Sep 4, 2024
1dff3e9
Merge branch 'chore/refactor-dapp-url-utils' into chore/refactor-snap…
stanleyyconsensys Sep 4, 2024
7871389
fix: lint
stanleyyconsensys Sep 4, 2024
499bc05
Merge branch 'main' into chore/refactor-snap-on-homepage-handle
stanleyyconsensys Sep 4, 2024
83e4c68
Merge branch 'main' into chore/refactor-snap-on-homepage-handle
khanti42 Sep 4, 2024
ca865fc
Merge branch 'main' into chore/refactor-snap-on-homepage-handle
stanleyyconsensys Oct 8, 2024
410166b
chore: update home page test
stanleyyconsensys Oct 8, 2024
204f233
chore: update network state mgr with default network config
stanleyyconsensys Oct 8, 2024
51cedf5
chore: lint fix
stanleyyconsensys Oct 8, 2024
09fc37d
Merge branch 'chore/add-default-network-config' into chore/refactor-s…
stanleyyconsensys Oct 8, 2024
4f9fadd
chore: lint
stanleyyconsensys Oct 8, 2024
2befaa1
Merge branch 'main' into chore/refactor-snap-on-homepage-handle
stanleyyconsensys Oct 8, 2024
dd074cd
chore: get balance with pending block only in HP
stanleyyconsensys Oct 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 9 additions & 154 deletions packages/starknet-snap/src/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,9 @@
import { MethodNotFoundError, SnapError } from '@metamask/snaps-sdk';
import { constants } from 'starknet';
import { text, MethodNotFoundError, SnapError } from '@metamask/snaps-sdk';

import { onRpcRequest, onHomePage } from '.';
import { manageStateSpy } from '../test/snap-provider.mock';
import { generateAccounts, type StarknetAccount } from './__tests__/helper';
import { onHomePage, onRpcRequest } from '.';
import * as createAccountApi from './createAccount';
import type { SnapState } from './types/snapState';
import {
ETHER_MAINNET,
ETHER_SEPOLIA_TESTNET,
STARKNET_MAINNET_NETWORK,
STARKNET_SEPOLIA_TESTNET_NETWORK,
} from './utils/constants';
import { HomePageController } from './on-home-page';
import * as keyPairUtils from './utils/keyPair';
import * as starknetUtils from './utils/starknetUtils';

jest.mock('./utils/logger');

Expand Down Expand Up @@ -79,153 +69,18 @@ describe('onRpcRequest', () => {
});

describe('onHomePage', () => {
const state: SnapState = {
accContracts: [],
erc20Tokens: [ETHER_MAINNET, ETHER_SEPOLIA_TESTNET],
networks: [STARKNET_MAINNET_NETWORK, STARKNET_SEPOLIA_TESTNET_NETWORK],
transactions: [],
currentNetwork: undefined,
};

const mockState = (snapState: SnapState) => {
manageStateSpy.mockResolvedValue(snapState);
};

const mockAccount = async (chainId: constants.StarknetChainId) => {
const accounts = await generateAccounts(chainId);
return accounts[0];
};

const mockAccountDiscovery = (account: StarknetAccount) => {
const getKeysFromAddressIndexSpy = jest.spyOn(
starknetUtils,
'getKeysFromAddressIndex',
);
const getCorrectContractAddressSpy = jest.spyOn(
starknetUtils,
'getCorrectContractAddress',
);

getKeysFromAddressIndexSpy.mockResolvedValue({
privateKey: account.privateKey,
publicKey: account.publicKey,
addressIndex: account.addressIndex,
derivationPath: account.derivationPath as unknown as any,
});

getCorrectContractAddressSpy.mockResolvedValue({
address: account.address,
signerPubKey: account.publicKey,
upgradeRequired: false,
deployRequired: false,
});

return {
getKeysFromAddressIndexSpy,
getCorrectContractAddressSpy,
};
};

const mockGetBalance = (balance: string) => {
const getBalanceSpy = jest.spyOn(starknetUtils, 'getBalance');
getBalanceSpy.mockResolvedValue(balance);
};

it('renders user address, user balance and network', async () => {
const account = await mockAccount(constants.StarknetChainId.SN_SEPOLIA);
mockState(state);
mockAccountDiscovery(account);
mockGetBalance('1000');

const result = await onHomePage();

expect(result).toStrictEqual({
content: {
type: 'panel',
children: [
{ type: 'text', value: 'Address' },
{
type: 'copyable',
value: account.address,
},
{
type: 'row',
label: 'Network',
value: {
type: 'text',
value: STARKNET_MAINNET_NETWORK.name,
},
},
{
type: 'row',
label: 'Balance',
value: {
type: 'text',
value: '0.000000000000001 ETH',
},
},
{ type: 'divider' },
{
type: 'text',
value:
'Visit the [companion dapp for Starknet](https://snaps.consensys.io/starknet) to manage your account.',
},
],
},
});
});

it('renders with network from state if `currentNetwork` is not undefined', async () => {
const network = STARKNET_MAINNET_NETWORK;
const account = await mockAccount(constants.StarknetChainId.SN_MAIN);
mockState({
...state,
currentNetwork: network,
});
mockAccountDiscovery(account);
mockGetBalance('1000');
it('executes homePageController', async () => {
const executeSpy = jest.spyOn(HomePageController.prototype, 'execute');
executeSpy.mockResolvedValue({ content: text('test') });

const result = await onHomePage();

expect(executeSpy).toHaveBeenCalledTimes(1);
expect(result).toStrictEqual({
content: {
type: 'panel',
children: [
{ type: 'text', value: 'Address' },
{
type: 'copyable',
value: account.address,
},
{
type: 'row',
label: 'Network',
value: {
type: 'text',
value: network.name,
},
},
{
type: 'row',
label: 'Balance',
value: {
type: 'text',
value: '0.000000000000001 ETH',
},
},
{ type: 'divider' },
{
type: 'text',
value:
'Visit the [companion dapp for Starknet](https://snaps.consensys.io/starknet) to manage your account.',
},
],
type: 'text',
value: 'test',
},
});
});

it('throws `Unable to initialize Snap HomePage` error when state not found', async () => {
await expect(onHomePage()).rejects.toThrow(
'Unable to initialize Snap HomePage',
);
});
});
79 changes: 2 additions & 77 deletions packages/starknet-snap/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,13 @@ import type {
OnHomePageHandler,
OnInstallHandler,
OnUpdateHandler,
Component,
} from '@metamask/snaps-sdk';
import {
panel,
row,
divider,
text,
copyable,
SnapError,
MethodNotFoundError,
} from '@metamask/snaps-sdk';
import { ethers } from 'ethers';

import { addErc20Token } from './addErc20Token';
import { addNetwork } from './addNetwork';
Expand All @@ -34,6 +29,7 @@ import { getStoredUserAccounts } from './getStoredUserAccounts';
import { getTransactions } from './getTransactions';
import { getTransactionStatus } from './getTransactionStatus';
import { getValue } from './getValue';
import { homePageController } from './on-home-page';
import { recoverAccounts } from './recoverAccounts';
import type {
DisplayPrivateKeyParams,
Expand Down Expand Up @@ -66,8 +62,6 @@ import { upgradeAccContract } from './upgradeAccContract';
import { getDappUrl, isSnapRpcError } from './utils';
import {
CAIRO_VERSION_LEGACY,
ETHER_MAINNET,
ETHER_SEPOLIA_TESTNET,
PRELOADED_TOKENS,
STARKNET_MAINNET_NETWORK,
STARKNET_SEPOLIA_TESTNET_NETWORK,
Expand All @@ -82,11 +76,6 @@ import {
upsertNetwork,
removeNetwork,
} from './utils/snapUtils';
import {
getBalance,
getCorrectContractAddress,
getKeysFromAddressIndex,
} from './utils/starknetUtils';

declare const snap;
logger.logLevel = parseInt(Config.logLevel, 10);
Expand Down Expand Up @@ -344,69 +333,5 @@ export const onUpdate: OnUpdateHandler = async () => {
};

export const onHomePage: OnHomePageHandler = async () => {
try {
const state: SnapState = await snap.request({
method: 'snap_manageState',
params: {
operation: 'get',
},
});

if (!state) {
throw new Error('State not found.');
}

// default network is mainnet
let network = STARKNET_MAINNET_NETWORK;
if (
state.currentNetwork &&
state.currentNetwork.chainId !== STARKNET_TESTNET_NETWORK.chainId
) {
network = state.currentNetwork;
}

// we only support 1 address at this moment
const idx = 0;
const keyDeriver = await getAddressKeyDeriver(snap);
const { publicKey } = await getKeysFromAddressIndex(
keyDeriver,
network.chainId,
state,
idx,
);
const { address } = await getCorrectContractAddress(network, publicKey);

const ethToken =
network.chainId === ETHER_SEPOLIA_TESTNET.chainId
? ETHER_SEPOLIA_TESTNET
: ETHER_MAINNET;
const balance =
(await getBalance(address, ethToken.address, network)) ?? BigInt(0);
const displayBalance = ethers.utils.formatUnits(
ethers.BigNumber.from(balance),
ethToken.decimals,
);

const panelItems: Component[] = [];
panelItems.push(text('Address'));
panelItems.push(copyable(`${address}`));
panelItems.push(row('Network', text(`${network.name}`)));
panelItems.push(row('Balance', text(`${displayBalance} ETH`)));
panelItems.push(divider());
panelItems.push(
text(
`Visit the [companion dapp for Starknet](${getDappUrl()}) to manage your account.`,
),
);

return {
content: panel(panelItems),
};
} catch (error) {
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
logger.error(`Error: ${error}`);
throw new SnapError(
'Unable to initialize Snap HomePage',
) as unknown as Error;
}
return await homePageController.execute();
};
Loading
Loading