From cac0a64f0061c312f38ea04252aca19675655c65 Mon Sep 17 00:00:00 2001 From: Florin Dzeladini Date: Tue, 21 Jan 2025 12:34:34 +0100 Subject: [PATCH 1/9] fix: account contract isRequiredDeploy Upgrade order mismatch --- packages/starknet-snap/src/wallet/account/account.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/starknet-snap/src/wallet/account/account.ts b/packages/starknet-snap/src/wallet/account/account.ts index bfb5197f..bddea5a4 100644 --- a/packages/starknet-snap/src/wallet/account/account.ts +++ b/packages/starknet-snap/src/wallet/account/account.ts @@ -61,8 +61,8 @@ export class Account { // When a Account object discovery by the account service, // it should already cached the status of requireDeploy and requireUpgrade. const [upgradeRequired, deployRequired] = await Promise.all([ - this.accountContract.isRequireDeploy(), this.accountContract.isRequireUpgrade(), + this.accountContract.isRequireDeploy(), ]); return { addressSalt: this.publicKey, From 58e7ddfc1592e0befbe6ee97a5c6a0cfe179a3da Mon Sep 17 00:00:00 2001 From: Florin Dzeladini Date: Tue, 21 Jan 2025 17:20:22 +0100 Subject: [PATCH 2/9] feat: multi strategy for account discovery --- .../rpcs/abstract/account-rpc-controller.ts | 10 +++++--- .../starknet-snap/src/rpcs/add-account.ts | 23 +++++++++++++++---- .../src/rpcs/get-current-account.ts | 11 ++++++--- .../starknet-snap/src/rpcs/switch-account.ts | 17 ++++++++++---- packages/starknet-snap/src/utils/factory.ts | 9 ++++++++ .../src/wallet/account/discovery.ts | 18 ++++++++++++++- .../src/wallet/account/service.ts | 4 ++++ packages/wallet-ui/src/services/useSnap.ts | 19 ++++++++++++--- .../wallet-ui/src/services/useStarkNetSnap.ts | 6 +++++ 9 files changed, 98 insertions(+), 19 deletions(-) diff --git a/packages/starknet-snap/src/rpcs/abstract/account-rpc-controller.ts b/packages/starknet-snap/src/rpcs/abstract/account-rpc-controller.ts index 3370c33e..b314519b 100644 --- a/packages/starknet-snap/src/rpcs/abstract/account-rpc-controller.ts +++ b/packages/starknet-snap/src/rpcs/abstract/account-rpc-controller.ts @@ -4,7 +4,7 @@ import { DeployRequiredError, UpgradeRequiredError, } from '../../utils/exceptions'; -import { createAccountService } from '../../utils/factory'; +import { AccountDiscoveryType, createAccountService } from '../../utils/factory'; import { showDeployRequestModal, showUpgradeRequestModal, @@ -15,6 +15,7 @@ import { ChainRpcController } from './chain-rpc-controller'; export type AccountRpcParams = { chainId: string; address: string; + accountDiscoveryType?: AccountDiscoveryType; }; export type AccountRpcControllerOptions = { @@ -55,8 +56,11 @@ export abstract class AccountRpcController< protected async preExecute(params: Request): Promise { await super.preExecute(params); const { address } = params; - - const accountService = createAccountService(this.network); + const accountService = createAccountService( + this.network, + undefined, + params.accountDiscoveryType, + ); this.account = await accountService.deriveAccountByAddress(address); try { diff --git a/packages/starknet-snap/src/rpcs/add-account.ts b/packages/starknet-snap/src/rpcs/add-account.ts index 6645d77d..0b9671a7 100644 --- a/packages/starknet-snap/src/rpcs/add-account.ts +++ b/packages/starknet-snap/src/rpcs/add-account.ts @@ -1,10 +1,19 @@ -import { type Infer } from 'superstruct'; +import { assign, enums, object, optional, type Infer } from 'superstruct'; -import { BaseRequestStruct, AccountStruct, logger } from '../utils'; -import { createAccountService } from '../utils/factory'; +import { + BaseRequestStruct, + AccountStruct, + logger, +} from '../utils'; +import { AccountDiscoveryType, createAccountService } from '../utils/factory'; import { ChainRpcController } from './abstract/chain-rpc-controller'; -export const AddAccountRequestStruct = BaseRequestStruct; +export const AddAccountRequestStruct = assign( + object({ + accountDiscoveryType: optional(enums(Object.values(AccountDiscoveryType))), + }), + BaseRequestStruct, +); export const AddAccountResponseStruct = AccountStruct; @@ -34,7 +43,11 @@ export class AddAccountRpc extends ChainRpcController< // eslint-disable-next-line @typescript-eslint/no-unused-vars params: AddAccountParams, ): Promise { - const accountService = createAccountService(this.network); + const accountService = createAccountService( + this.network, + undefined, + params.accountDiscoveryType, + ); const account = await accountService.deriveAccountByIndex(); diff --git a/packages/starknet-snap/src/rpcs/get-current-account.ts b/packages/starknet-snap/src/rpcs/get-current-account.ts index 23b7a6af..a87417ce 100644 --- a/packages/starknet-snap/src/rpcs/get-current-account.ts +++ b/packages/starknet-snap/src/rpcs/get-current-account.ts @@ -1,14 +1,15 @@ -import { boolean, object, optional, assign, type Infer } from 'superstruct'; +import { boolean, object, optional, assign, type Infer, enums } from 'superstruct'; import { AccountStateManager } from '../state/account-state-manager'; import { BaseRequestStruct, AccountStruct } from '../utils'; -import { createAccountService } from '../utils/factory'; +import { AccountDiscoveryType, createAccountService } from '../utils/factory'; import { ChainRpcController } from './abstract/chain-rpc-controller'; export const GetCurrentAccountRequestStruct = assign( BaseRequestStruct, object({ fromState: optional(boolean()), + accountDiscoveryType: optional(enums(Object.values(AccountDiscoveryType))), }), ); @@ -44,7 +45,11 @@ export class GetCurrentAccountRpc extends ChainRpcController< protected async handleRequest( params: GetCurrentAccountParams, ): Promise { - const accountService = createAccountService(this.network); + const accountService = createAccountService( + this.network, + undefined, + params.accountDiscoveryType, + ); if (params.fromState) { // Get the current account from the state if the flag is set. diff --git a/packages/starknet-snap/src/rpcs/switch-account.ts b/packages/starknet-snap/src/rpcs/switch-account.ts index 0f31b160..558ca08a 100644 --- a/packages/starknet-snap/src/rpcs/switch-account.ts +++ b/packages/starknet-snap/src/rpcs/switch-account.ts @@ -1,13 +1,18 @@ -import { assign, object, type Infer } from 'superstruct'; +import { assign, enums, object, optional, type Infer } from 'superstruct'; -import { BaseRequestStruct, AccountStruct, AddressStruct } from '../utils'; -import { createAccountService } from '../utils/factory'; +import { + BaseRequestStruct, + AccountStruct, + AddressStruct, +} from '../utils'; +import { AccountDiscoveryType, createAccountService } from '../utils/factory'; import { AccountRpcController } from './abstract/account-rpc-controller'; export const SwitchAccountRequestStruct = assign( BaseRequestStruct, object({ address: AddressStruct, + accountDiscoveryType: optional(enums(Object.values(AccountDiscoveryType))), }), ); @@ -39,7 +44,11 @@ export class SwitchAccountRpc extends AccountRpcController< protected async handleRequest( params: SwitchAccountParams, ): Promise { - const accountService = createAccountService(this.network); + const accountService = createAccountService( + this.network, + undefined, + params.accountDiscoveryType, + ); await accountService.switchAccount(params.chainId, this.account); diff --git a/packages/starknet-snap/src/utils/factory.ts b/packages/starknet-snap/src/utils/factory.ts index d4f12d60..70e2e16c 100644 --- a/packages/starknet-snap/src/utils/factory.ts +++ b/packages/starknet-snap/src/utils/factory.ts @@ -47,19 +47,28 @@ export function createTransactionService( }); } +export enum AccountDiscoveryType { + DEFAULT = 'DEFAULT', + ForceCairo0 = 'FORCE_CAIRO_0', + ForceCairo1 = 'FORCE_CAIRO_1', +} + /** * Create a AccountService object. * * @param network - The network. * @param [accountStateMgr] - The `AccountStateManager`. + * @param accountDiscoveryType * @returns A AccountService object. */ export function createAccountService( network: Network, accountStateMgr?: AccountStateManager, + accountDiscoveryType?: AccountDiscoveryType, ): AccountService { return new AccountService({ network, accountStateMgr, + accountDiscoveryType, }); } diff --git a/packages/starknet-snap/src/wallet/account/discovery.ts b/packages/starknet-snap/src/wallet/account/discovery.ts index c5da0725..e43773ec 100644 --- a/packages/starknet-snap/src/wallet/account/discovery.ts +++ b/packages/starknet-snap/src/wallet/account/discovery.ts @@ -1,4 +1,5 @@ import type { Network } from '../../types/snapState'; +import { AccountDiscoveryType } from '../../utils/factory'; import { Cairo0Contract } from './cairo0'; import { Cairo1Contract } from './cairo1'; import type { CairoAccountContract } from './contract'; @@ -16,8 +17,23 @@ export class AccountContractDiscovery { protected network: Network; - constructor(network: Network) { + constructor(network: Network, discoveryType?: AccountDiscoveryType) { this.network = network; + if (discoveryType !== undefined) { + switch (discoveryType) { + case AccountDiscoveryType.ForceCairo0: + this.contractCtors = [Cairo0Contract]; + this.defaultContractCtor = Cairo0Contract; + break; + case AccountDiscoveryType.ForceCairo1: + this.contractCtors = [Cairo1Contract]; + this.defaultContractCtor = Cairo1Contract; + break; + default: + this.contractCtors = [Cairo1Contract, Cairo0Contract]; + this.defaultContractCtor = Cairo1Contract; + } + } } /** diff --git a/packages/starknet-snap/src/wallet/account/service.ts b/packages/starknet-snap/src/wallet/account/service.ts index c2b6afb4..e541a0cc 100644 --- a/packages/starknet-snap/src/wallet/account/service.ts +++ b/packages/starknet-snap/src/wallet/account/service.ts @@ -5,6 +5,7 @@ import { AccountNotFoundError, MaxAccountLimitExceededError, } from '../../utils/exceptions'; +import { AccountDiscoveryType } from '../../utils/factory'; import { Account } from './account'; import { AccountContractDiscovery } from './discovery'; import { AccountKeyPair } from './keypair'; @@ -19,14 +20,17 @@ export class AccountService { constructor({ network, accountStateMgr = new AccountStateManager(), + accountDiscoveryType = AccountDiscoveryType.DEFAULT, }: { network: Network; accountStateMgr?: AccountStateManager; + accountDiscoveryType?: AccountDiscoveryType; }) { this.network = network; this.accountStateMgr = accountStateMgr; this.accountContractDiscoveryService = new AccountContractDiscovery( network, + accountDiscoveryType, ); } diff --git a/packages/wallet-ui/src/services/useSnap.ts b/packages/wallet-ui/src/services/useSnap.ts index 3c3f8d7e..78e88851 100644 --- a/packages/wallet-ui/src/services/useSnap.ts +++ b/packages/wallet-ui/src/services/useSnap.ts @@ -65,9 +65,22 @@ export const useSnap = () => { }; const ping = async (): Promise => { - await invokeSnap({ - method: 'ping', - }); + // Extract the `accountDiscovery` parameter from the GET field (e.g., URL search params) + const urlParams = new URLSearchParams(window.location.search); + const accountDiscovery = urlParams.get('accountDiscovery'); + + if (accountDiscovery !== null) { + await invokeSnap({ + method: 'ping', + params: { + accountDiscoveryType: accountDiscovery, + }, + }); + } else { + await invokeSnap({ + method: 'ping', + }); + } }; return { diff --git a/packages/wallet-ui/src/services/useStarkNetSnap.ts b/packages/wallet-ui/src/services/useStarkNetSnap.ts index 5cfa4782..c5f1af95 100644 --- a/packages/wallet-ui/src/services/useStarkNetSnap.ts +++ b/packages/wallet-ui/src/services/useStarkNetSnap.ts @@ -767,10 +767,12 @@ export const useStarkNetSnap = () => { const addNewAccount = async (chainId: string) => { dispatch(enableLoadingWithMessage('Adding new account...')); try { + const urlParams = new URLSearchParams(window.location.search); const account = await invokeSnap({ method: 'starkNet_addAccount', params: { chainId, + accountDiscoveryType: urlParams.get('accountDiscovery'), }, }); @@ -792,10 +794,12 @@ export const useStarkNetSnap = () => { }; const getCurrentAccount = async (chainId: string) => { + const urlParams = new URLSearchParams(window.location.search); return await invokeSnap({ method: 'starkNet_getCurrentAccount', params: { chainId, + accountDiscoveryType: urlParams.get('accountDiscovery') ?? "DEFAULT", }, }); }; @@ -807,11 +811,13 @@ export const useStarkNetSnap = () => { ), ); try { + const urlParams = new URLSearchParams(window.location.search); const account = await invokeSnap({ method: 'starkNet_swtichAccount', params: { chainId, address, + accountDiscoveryType: urlParams.get('accountDiscovery'), }, }); From 87af60d870acf361a839c4deb66e7a90f38d2566 Mon Sep 17 00:00:00 2001 From: Florin Dzeladini Date: Wed, 22 Jan 2025 09:15:16 +0100 Subject: [PATCH 3/9] chore: fix lint --- .../src/rpcs/abstract/account-rpc-controller.ts | 3 ++- packages/starknet-snap/src/rpcs/add-account.ts | 6 +----- packages/starknet-snap/src/rpcs/get-current-account.ts | 9 ++++++++- packages/starknet-snap/src/rpcs/switch-account.ts | 6 +----- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/starknet-snap/src/rpcs/abstract/account-rpc-controller.ts b/packages/starknet-snap/src/rpcs/abstract/account-rpc-controller.ts index b314519b..c14cc392 100644 --- a/packages/starknet-snap/src/rpcs/abstract/account-rpc-controller.ts +++ b/packages/starknet-snap/src/rpcs/abstract/account-rpc-controller.ts @@ -4,7 +4,8 @@ import { DeployRequiredError, UpgradeRequiredError, } from '../../utils/exceptions'; -import { AccountDiscoveryType, createAccountService } from '../../utils/factory'; +import type { AccountDiscoveryType } from '../../utils/factory'; +import { createAccountService } from '../../utils/factory'; import { showDeployRequestModal, showUpgradeRequestModal, diff --git a/packages/starknet-snap/src/rpcs/add-account.ts b/packages/starknet-snap/src/rpcs/add-account.ts index 0b9671a7..f465badc 100644 --- a/packages/starknet-snap/src/rpcs/add-account.ts +++ b/packages/starknet-snap/src/rpcs/add-account.ts @@ -1,10 +1,6 @@ import { assign, enums, object, optional, type Infer } from 'superstruct'; -import { - BaseRequestStruct, - AccountStruct, - logger, -} from '../utils'; +import { BaseRequestStruct, AccountStruct, logger } from '../utils'; import { AccountDiscoveryType, createAccountService } from '../utils/factory'; import { ChainRpcController } from './abstract/chain-rpc-controller'; diff --git a/packages/starknet-snap/src/rpcs/get-current-account.ts b/packages/starknet-snap/src/rpcs/get-current-account.ts index a87417ce..9b0c2d5e 100644 --- a/packages/starknet-snap/src/rpcs/get-current-account.ts +++ b/packages/starknet-snap/src/rpcs/get-current-account.ts @@ -1,4 +1,11 @@ -import { boolean, object, optional, assign, type Infer, enums } from 'superstruct'; +import { + boolean, + object, + optional, + assign, + type Infer, + enums, +} from 'superstruct'; import { AccountStateManager } from '../state/account-state-manager'; import { BaseRequestStruct, AccountStruct } from '../utils'; diff --git a/packages/starknet-snap/src/rpcs/switch-account.ts b/packages/starknet-snap/src/rpcs/switch-account.ts index 558ca08a..72762a9b 100644 --- a/packages/starknet-snap/src/rpcs/switch-account.ts +++ b/packages/starknet-snap/src/rpcs/switch-account.ts @@ -1,10 +1,6 @@ import { assign, enums, object, optional, type Infer } from 'superstruct'; -import { - BaseRequestStruct, - AccountStruct, - AddressStruct, -} from '../utils'; +import { BaseRequestStruct, AccountStruct, AddressStruct } from '../utils'; import { AccountDiscoveryType, createAccountService } from '../utils/factory'; import { AccountRpcController } from './abstract/account-rpc-controller'; From b1c400aeffa0b184a48fd4bb976ee0cb1936b6ca Mon Sep 17 00:00:00 2001 From: Florin Dzeladini Date: Wed, 22 Jan 2025 10:56:18 +0100 Subject: [PATCH 4/9] chore: fix lint --- packages/wallet-ui/src/services/useStarkNetSnap.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/wallet-ui/src/services/useStarkNetSnap.ts b/packages/wallet-ui/src/services/useStarkNetSnap.ts index c5f1af95..2fc2d13a 100644 --- a/packages/wallet-ui/src/services/useStarkNetSnap.ts +++ b/packages/wallet-ui/src/services/useStarkNetSnap.ts @@ -799,7 +799,7 @@ export const useStarkNetSnap = () => { method: 'starkNet_getCurrentAccount', params: { chainId, - accountDiscoveryType: urlParams.get('accountDiscovery') ?? "DEFAULT", + accountDiscoveryType: urlParams.get('accountDiscovery') ?? 'DEFAULT', }, }); }; From 6f52df3c5589cb2b40531b3d924b998a01f76abb Mon Sep 17 00:00:00 2001 From: Florin Dzeladini Date: Wed, 22 Jan 2025 21:43:05 +0100 Subject: [PATCH 5/9] feat: banner to choose force cairo version option --- packages/starknet-snap/src/config.ts | 2 +- .../ui/Framework/Framework.style.ts | 12 ++-- .../ui/Framework/Framework.view.tsx | 64 ++++++++++++++++--- .../AccountSwitchModal.view.tsx | 4 +- 4 files changed, 65 insertions(+), 17 deletions(-) diff --git a/packages/starknet-snap/src/config.ts b/packages/starknet-snap/src/config.ts index ba34fe15..47d726d9 100644 --- a/packages/starknet-snap/src/config.ts +++ b/packages/starknet-snap/src/config.ts @@ -65,7 +65,7 @@ export const Config: SnapConfig = { }, account: { - maxAccountToCreate: 2, + maxAccountToCreate: 1, }, // eslint-disable-next-line no-restricted-globals diff --git a/packages/wallet-ui/src/components/ui/Framework/Framework.style.ts b/packages/wallet-ui/src/components/ui/Framework/Framework.style.ts index d6233c41..418aa1ec 100644 --- a/packages/wallet-ui/src/components/ui/Framework/Framework.style.ts +++ b/packages/wallet-ui/src/components/ui/Framework/Framework.style.ts @@ -14,7 +14,7 @@ export const Wrapper = styled.div` export const ColMiddle = styled.div` width: 1040px; margin: auto; - + margin-top: 40px; @media (max-width: 1024px) { width: 896px; } @@ -34,14 +34,16 @@ export const Content = styled.div` export const Banner = styled.div` position: fixed; left: 0px; - bottom: 0px; + top: 0px; width: 100%; - background-color: ${(props) => props.theme.palette.primary.main}; + background-color: red; + margin-bottom: 24px; color: ${(props) => props.theme.palette.grey.grey3}; display: flex; align-items: center; - padding: 13px 24px; - justify-content: space-between; + padding: 10px 24px; + justify-content: space-around; + z-index: 2; `; export const CloseIcon = styled(FontAwesomeIcon)` diff --git a/packages/wallet-ui/src/components/ui/Framework/Framework.view.tsx b/packages/wallet-ui/src/components/ui/Framework/Framework.view.tsx index c463df87..695cb278 100644 --- a/packages/wallet-ui/src/components/ui/Framework/Framework.view.tsx +++ b/packages/wallet-ui/src/components/ui/Framework/Framework.view.tsx @@ -1,8 +1,8 @@ -import { ReactNode, useState } from 'react'; +import { ReactNode } from 'react'; import { Footer } from 'components/ui/organism/Footer'; +import { Button, Stack, Typography } from '@mui/material'; // Importing MUI components import { Banner, - CloseIcon, ColMiddle, Content, MenuStyled, @@ -15,7 +15,29 @@ interface Props { } export const FrameworkView = ({ connected, children }: Props) => { - const [bannerOpen, setBannerOpen] = useState(true); + // Get the current `accountDiscovery` value from the URL + const urlParams = new URLSearchParams(window.location.search); + const accountDiscovery = urlParams.get('accountDiscovery'); + + const bannerMessage = + accountDiscovery === 'FORCE_CAIRO_1' + ? 'This is a special version for recovering funds on a Cairo 1 account.' + : accountDiscovery === 'FORCE_CAIRO_0' + ? 'This is a special version for recovering funds on a Cairo 0 account.' + : 'This is a special version of the dapp for account recovery purposes.'; + + const handleAccountChange = (version: string) => { + // Update the URL without reloading the page + const newParams = new URLSearchParams(window.location.search); + newParams.set('accountDiscovery', version); + window.history.replaceState( + {}, + '', + `${window.location.pathname}?${newParams.toString()}`, + ); + window.location.reload(); // Reload to apply the updated query parameter + }; + return ( @@ -23,12 +45,36 @@ export const FrameworkView = ({ connected, children }: Props) => { {children}