From 52484c4ee17d7651c966d7fe939c51a7af516c14 Mon Sep 17 00:00:00 2001 From: ignaciosantise <25931366+ignaciosantise@users.noreply.github.com> Date: Thu, 6 Feb 2025 15:26:09 -0300 Subject: [PATCH 01/14] fix: show wallet info in useWalletInfo hook for ethers and ethers5 --- .changeset/light-geese-stare.md | 18 ++++++++++++++++++ packages/ethers/src/client.ts | 33 +++++++++++++++++++++++++++++++++ packages/ethers5/src/client.ts | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 .changeset/light-geese-stare.md diff --git a/.changeset/light-geese-stare.md b/.changeset/light-geese-stare.md new file mode 100644 index 00000000..18239882 --- /dev/null +++ b/.changeset/light-geese-stare.md @@ -0,0 +1,18 @@ +--- +'@reown/appkit-ethers5-react-native': patch +'@reown/appkit-ethers-react-native': patch +'@reown/appkit-auth-ethers-react-native': patch +'@reown/appkit-auth-wagmi-react-native': patch +'@reown/appkit-coinbase-ethers-react-native': patch +'@reown/appkit-coinbase-wagmi-react-native': patch +'@reown/appkit-common-react-native': patch +'@reown/appkit-core-react-native': patch +'@reown/appkit-scaffold-react-native': patch +'@reown/appkit-scaffold-utils-react-native': patch +'@reown/appkit-siwe-react-native': patch +'@reown/appkit-ui-react-native': patch +'@reown/appkit-wagmi-react-native': patch +'@reown/appkit-wallet-react-native': patch +--- + +fix: show wallet info in ethers hook diff --git a/packages/ethers/src/client.ts b/packages/ethers/src/client.ts index 846fd8a2..d2067fe9 100644 --- a/packages/ethers/src/client.ts +++ b/packages/ethers/src/client.ts @@ -450,6 +450,10 @@ export class AppKit extends AppKitScaffold { this.syncNetwork(chainImages); }); + EthersStoreUtil.subscribeKey('provider', provider => { + this.syncConnectedWalletInfo(provider); + }); + this.syncRequestedNetworks(chains, chainImages); this.syncConnectors(config); this.syncAuthConnector(config); @@ -1002,6 +1006,35 @@ export class AppKit extends AppKitScaffold { this.addAuthListeners(this.authProvider); } + private async syncConnectedWalletInfo(provider?: Provider) { + if (!provider) { + this.setConnectedWalletInfo(undefined); + + return; + } + + if ((provider as any)?.session?.peer?.metadata) { + const metadata = (provider as unknown as EthereumProvider)?.session?.peer.metadata; + if (metadata) { + this.setConnectedWalletInfo({ + ...metadata, + name: metadata.name, + icon: metadata.icons?.[0] + }); + } + } else if (provider?.id === ConstantsUtil.COINBASE_CONNECTOR_ID) { + this.setConnectedWalletInfo({ + name: 'Coinbase Wallet' + }); + } else if (provider?.id === ConstantsUtil.AUTH_CONNECTOR_ID) { + this.setConnectedWalletInfo({ + name: 'AppKit Universal Wallet' + }); + } else { + this.setConnectedWalletInfo(undefined); + } + } + private async addAuthListeners(authProvider: AppKitFrameProvider) { authProvider.onSetPreferredAccount(async ({ address, type }) => { if (address) { diff --git a/packages/ethers5/src/client.ts b/packages/ethers5/src/client.ts index 083096c2..3dd3119e 100644 --- a/packages/ethers5/src/client.ts +++ b/packages/ethers5/src/client.ts @@ -432,6 +432,10 @@ export class AppKit extends AppKitScaffold { this.syncNetwork(chainImages); }); + EthersStoreUtil.subscribeKey('provider', provider => { + this.syncConnectedWalletInfo(provider); + }); + this.syncRequestedNetworks(chains, chainImages); this.syncConnectors(config); this.syncAuthConnector(config); @@ -979,6 +983,35 @@ export class AppKit extends AppKitScaffold { this.addAuthListeners(this.authProvider); } + private async syncConnectedWalletInfo(provider?: Provider) { + if (!provider) { + this.setConnectedWalletInfo(undefined); + + return; + } + + if ((provider as any)?.session?.peer?.metadata) { + const metadata = (provider as unknown as EthereumProvider)?.session?.peer.metadata; + if (metadata) { + this.setConnectedWalletInfo({ + ...metadata, + name: metadata.name, + icon: metadata.icons?.[0] + }); + } + } else if (provider?.id === ConstantsUtil.COINBASE_CONNECTOR_ID) { + this.setConnectedWalletInfo({ + name: 'Coinbase Wallet' + }); + } else if (provider?.id === ConstantsUtil.AUTH_CONNECTOR_ID) { + this.setConnectedWalletInfo({ + name: 'AppKit Universal Wallet' + }); + } else { + this.setConnectedWalletInfo(undefined); + } + } + private async addAuthListeners(authProvider: AppKitFrameProvider) { authProvider.onSetPreferredAccount(async ({ address, type }) => { if (address) { From 9342f16103b61158cdc5d488b867455eed23ffce Mon Sep 17 00:00:00 2001 From: ignaciosantise <25931366+ignaciosantise@users.noreply.github.com> Date: Thu, 6 Feb 2025 15:48:14 -0300 Subject: [PATCH 02/14] chore: changeset --- .changeset/light-geese-stare.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/light-geese-stare.md b/.changeset/light-geese-stare.md index 18239882..a55349ef 100644 --- a/.changeset/light-geese-stare.md +++ b/.changeset/light-geese-stare.md @@ -15,4 +15,4 @@ '@reown/appkit-wallet-react-native': patch --- -fix: show wallet info in ethers hook +fix: show wallet info in useWalletInfo hook for ethers and ethers5 From aae124880470963fd512fea168806de253988a26 Mon Sep 17 00:00:00 2001 From: ignaciosantise <25931366+ignaciosantise@users.noreply.github.com> Date: Mon, 10 Feb 2025 12:17:23 -0300 Subject: [PATCH 03/14] chore: export connector id and icon if defined --- packages/auth-ethers/src/index.ts | 2 +- packages/auth-wagmi/src/index.ts | 2 +- packages/ethers/src/client.ts | 10 ++++------ packages/ethers5/src/client.ts | 10 ++++------ packages/wagmi/src/client.ts | 6 +++++- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/auth-ethers/src/index.ts b/packages/auth-ethers/src/index.ts index 01ad7822..6beb53df 100644 --- a/packages/auth-ethers/src/index.ts +++ b/packages/auth-ethers/src/index.ts @@ -7,7 +7,7 @@ interface AuthProviderProps { export class AuthProvider extends AppKitFrameProvider { readonly id = 'appKitAuth'; - readonly name = 'AppKit Auth'; + readonly name = 'AppKit Universal Wallet'; constructor(props: AuthProviderProps) { super(props.projectId, props.metadata); diff --git a/packages/auth-wagmi/src/index.ts b/packages/auth-wagmi/src/index.ts index b9859d6a..b3a2a4a0 100644 --- a/packages/auth-wagmi/src/index.ts +++ b/packages/auth-wagmi/src/index.ts @@ -35,7 +35,7 @@ export function authConnector(parameters: AuthConnectorOptions) { return createConnector(config => ({ id: authConnector.id, - name: 'AppKit Auth', + name: 'AppKit Universal Wallet', type: authConnector.type, async setup() { _provider = new AppKitFrameProvider(parameters.projectId, parameters.metadata); diff --git a/packages/ethers/src/client.ts b/packages/ethers/src/client.ts index d2067fe9..0111ff53 100644 --- a/packages/ethers/src/client.ts +++ b/packages/ethers/src/client.ts @@ -1022,13 +1022,11 @@ export class AppKit extends AppKitScaffold { icon: metadata.icons?.[0] }); } - } else if (provider?.id === ConstantsUtil.COINBASE_CONNECTOR_ID) { + } else if (provider?.id) { this.setConnectedWalletInfo({ - name: 'Coinbase Wallet' - }); - } else if (provider?.id === ConstantsUtil.AUTH_CONNECTOR_ID) { - this.setConnectedWalletInfo({ - name: 'AppKit Universal Wallet' + id: provider.id, + name: provider?.name ?? PresetsUtil.ConnectorNamesMap[provider.id], + icon: this.options?.connectorImages?.[provider.id] }); } else { this.setConnectedWalletInfo(undefined); diff --git a/packages/ethers5/src/client.ts b/packages/ethers5/src/client.ts index 3dd3119e..8e8e6b67 100644 --- a/packages/ethers5/src/client.ts +++ b/packages/ethers5/src/client.ts @@ -999,13 +999,11 @@ export class AppKit extends AppKitScaffold { icon: metadata.icons?.[0] }); } - } else if (provider?.id === ConstantsUtil.COINBASE_CONNECTOR_ID) { + } else if (provider?.id) { this.setConnectedWalletInfo({ - name: 'Coinbase Wallet' - }); - } else if (provider?.id === ConstantsUtil.AUTH_CONNECTOR_ID) { - this.setConnectedWalletInfo({ - name: 'AppKit Universal Wallet' + id: provider.id, + name: provider?.name ?? PresetsUtil.ConnectorNamesMap[provider.id], + icon: this.options?.connectorImages?.[provider.id] }); } else { this.setConnectedWalletInfo(undefined); diff --git a/packages/wagmi/src/client.ts b/packages/wagmi/src/client.ts index 15e2b5c6..81026a96 100644 --- a/packages/wagmi/src/client.ts +++ b/packages/wagmi/src/client.ts @@ -548,7 +548,11 @@ export class AppKit extends AppKitScaffold { }); } } else { - this.setConnectedWalletInfo({ name: connector.name, icon: connector.icon }); + this.setConnectedWalletInfo({ + id: connector.id, + name: connector.name, + icon: this.options?.connectorImages?.[connector.id] ?? connector.icon + }); } } From e696bf88186cf20a39096ead864ebd3746477e00 Mon Sep 17 00:00:00 2001 From: ignaciosantise <25931366+ignaciosantise@users.noreply.github.com> Date: Mon, 10 Feb 2025 14:09:40 -0300 Subject: [PATCH 04/14] chore: moved connector constants to common package --- packages/auth-ethers/package.json | 1 + packages/auth-ethers/src/index.ts | 6 +++--- packages/auth-wagmi/package.json | 1 + packages/auth-wagmi/src/index.ts | 7 ++++--- packages/coinbase-ethers/package.json | 3 +++ packages/coinbase-ethers/src/index.ts | 5 +++-- packages/coinbase-wagmi/package.json | 3 +++ packages/coinbase-wagmi/src/index.ts | 7 ++++--- packages/common/src/index.ts | 1 + packages/common/src/utils/ConstantsUtil.ts | 11 +++++++++++ .../src/utils/PresetsUtil.ts | 14 +++++++------- packages/common/src/utils/TypeUtil.ts | 2 ++ .../src/controllers/ConnectorController.ts | 3 ++- packages/core/src/utils/StorageUtil.ts | 4 ++-- packages/core/src/utils/TypeUtil.ts | 5 ++--- packages/ethers/src/client.ts | 14 ++++++++++---- packages/ethers/src/index.tsx | 8 ++------ packages/ethers/src/utils/helpers.ts | 2 +- packages/ethers5/src/client.ts | 13 +++++++++---- packages/ethers5/src/index.tsx | 8 +++----- packages/ethers5/src/utils/helpers.ts | 2 +- packages/scaffold-utils/package.json | 1 + packages/scaffold-utils/src/index.ts | 2 -- .../scaffold-utils/src/utils/ConstantsUtil.ts | 8 -------- .../src/utils/EthersHelpersUtil.ts | 4 ++-- .../scaffold-utils/src/utils/HelpersUtil.ts | 2 +- .../components/connectors-list.tsx | 5 +++-- packages/wagmi/src/client.ts | 18 +++++++++++------- packages/wagmi/src/index.tsx | 5 +++-- packages/wagmi/src/utils/helpers.ts | 2 +- scripts/bump-version.sh | 2 +- yarn.lock | 7 +++++++ 32 files changed, 105 insertions(+), 71 deletions(-) rename packages/{scaffold-utils => common}/src/utils/PresetsUtil.ts (94%) delete mode 100644 packages/scaffold-utils/src/utils/ConstantsUtil.ts diff --git a/packages/auth-ethers/package.json b/packages/auth-ethers/package.json index 4114a973..e4741edc 100644 --- a/packages/auth-ethers/package.json +++ b/packages/auth-ethers/package.json @@ -36,6 +36,7 @@ "access": "public" }, "dependencies": { + "@reown/appkit-common-react-native": "1.2.1", "@reown/appkit-wallet-react-native": "1.2.1" }, "peerDependencies": { diff --git a/packages/auth-ethers/src/index.ts b/packages/auth-ethers/src/index.ts index 6beb53df..123e2534 100644 --- a/packages/auth-ethers/src/index.ts +++ b/packages/auth-ethers/src/index.ts @@ -1,13 +1,13 @@ import { AppKitFrameProvider, type AppKitFrameTypes } from '@reown/appkit-wallet-react-native'; - +import { ConstantsUtil, PresetsUtil } from '@reown/appkit-common-react-native'; interface AuthProviderProps { projectId: string; metadata: AppKitFrameTypes.Metadata; } export class AuthProvider extends AppKitFrameProvider { - readonly id = 'appKitAuth'; - readonly name = 'AppKit Universal Wallet'; + readonly id = ConstantsUtil.AUTH_CONNECTOR_ID; + readonly name = PresetsUtil.ConnectorNamesMap[ConstantsUtil.AUTH_CONNECTOR_ID]!; constructor(props: AuthProviderProps) { super(props.projectId, props.metadata); diff --git a/packages/auth-wagmi/package.json b/packages/auth-wagmi/package.json index 7e5eefd0..7ec86311 100644 --- a/packages/auth-wagmi/package.json +++ b/packages/auth-wagmi/package.json @@ -36,6 +36,7 @@ "access": "public" }, "dependencies": { + "@reown/appkit-common-react-native": "1.2.1", "@reown/appkit-core-react-native": "1.2.1", "@reown/appkit-wallet-react-native": "1.2.1" }, diff --git a/packages/auth-wagmi/src/index.ts b/packages/auth-wagmi/src/index.ts index b3a2a4a0..fd9e3f9d 100644 --- a/packages/auth-wagmi/src/index.ts +++ b/packages/auth-wagmi/src/index.ts @@ -3,6 +3,7 @@ import { SwitchChainError, getAddress, type Address, type Hex } from 'viem'; import { AppKitFrameProvider } from '@reown/appkit-wallet-react-native'; import { StorageUtil } from '@reown/appkit-core-react-native'; +import { ConstantsUtil, PresetsUtil } from '@reown/appkit-common-react-native'; export type Metadata = { name: string; @@ -26,8 +27,8 @@ type StorageItemMap = { recentConnectorId?: string; }; -authConnector.type = 'appKitAuth' as const; -authConnector.id = 'appKitAuth' as const; +authConnector.type = PresetsUtil.ConnectorTypesMap[ConstantsUtil.AUTH_CONNECTOR_ID]!; +authConnector.id = ConstantsUtil.AUTH_CONNECTOR_ID; export function authConnector(parameters: AuthConnectorOptions) { let _provider: AppKitFrameProvider = {} as AppKitFrameProvider; let _currentAddress: Address | null = null; @@ -35,7 +36,7 @@ export function authConnector(parameters: AuthConnectorOptions) { return createConnector(config => ({ id: authConnector.id, - name: 'AppKit Universal Wallet', + name: PresetsUtil.ConnectorNamesMap[ConstantsUtil.AUTH_CONNECTOR_ID]!, type: authConnector.type, async setup() { _provider = new AppKitFrameProvider(parameters.projectId, parameters.metadata); diff --git a/packages/coinbase-ethers/package.json b/packages/coinbase-ethers/package.json index a5c11976..af13e2a2 100644 --- a/packages/coinbase-ethers/package.json +++ b/packages/coinbase-ethers/package.json @@ -36,6 +36,9 @@ "registry": "https://registry.npmjs.org/", "access": "public" }, + "dependencies": { + "@reown/appkit-common-react-native": "1.2.1" + }, "peerDependencies": { "@coinbase/wallet-mobile-sdk": ">=1.0.10", "ethers": ">=5" diff --git a/packages/coinbase-ethers/src/index.ts b/packages/coinbase-ethers/src/index.ts index 51dc3256..c8f8bfbf 100644 --- a/packages/coinbase-ethers/src/index.ts +++ b/packages/coinbase-ethers/src/index.ts @@ -1,5 +1,6 @@ import { configure, WalletMobileSDKEVMProvider } from '@coinbase/wallet-mobile-sdk'; import type { WalletMobileSDKProviderOptions } from '@coinbase/wallet-mobile-sdk/build/WalletMobileSDKEVMProvider'; +import { ConstantsUtil, PresetsUtil } from '@reown/appkit-common-react-native'; interface RequestArguments { readonly method: string; @@ -12,8 +13,8 @@ type CoinbaseProviderOptions = WalletMobileSDKProviderOptions & { }; export class CoinbaseProvider { - readonly id = 'coinbaseWallet'; - readonly name = 'Coinbase Wallet'; + readonly id = ConstantsUtil.COINBASE_CONNECTOR_ID; + readonly name = PresetsUtil.ConnectorNamesMap[ConstantsUtil.COINBASE_CONNECTOR_ID]!; private _provider?: WalletMobileSDKEVMProvider; private _initProviderPromise?: Promise; diff --git a/packages/coinbase-wagmi/package.json b/packages/coinbase-wagmi/package.json index 5a7ec05d..758311c7 100644 --- a/packages/coinbase-wagmi/package.json +++ b/packages/coinbase-wagmi/package.json @@ -36,6 +36,9 @@ "registry": "https://registry.npmjs.org/", "access": "public" }, + "dependencies": { + "@reown/appkit-common-react-native": "1.2.1" + }, "peerDependencies": { "@coinbase/wallet-mobile-sdk": ">=1.0.10", "wagmi": ">=2" diff --git a/packages/coinbase-wagmi/src/index.ts b/packages/coinbase-wagmi/src/index.ts index 8923ad01..0450673d 100644 --- a/packages/coinbase-wagmi/src/index.ts +++ b/packages/coinbase-wagmi/src/index.ts @@ -8,6 +8,7 @@ import { } from 'viem'; import { WalletMobileSDKEVMProvider, configure } from '@coinbase/wallet-mobile-sdk'; import type { WalletMobileSDKProviderOptions } from '@coinbase/wallet-mobile-sdk/build/WalletMobileSDKEVMProvider'; +import { ConstantsUtil, PresetsUtil } from '@reown/appkit-common-react-native'; type CoinbaseConnectorParameters = WalletMobileSDKProviderOptions & { redirect: string; @@ -15,13 +16,13 @@ type CoinbaseConnectorParameters = WalletMobileSDKProviderOptions & { type Provider = WalletMobileSDKEVMProvider; -coinbaseConnector.type = 'coinbaseWallet' as const; +coinbaseConnector.type = PresetsUtil.ConnectorTypesMap[ConstantsUtil.COINBASE_CONNECTOR_ID]!; export function coinbaseConnector(parameters: CoinbaseConnectorParameters) { let _provider: Provider; return createConnector(config => ({ - id: 'coinbaseWallet', - name: 'Coinbase Wallet', + id: ConstantsUtil.COINBASE_CONNECTOR_ID, + name: PresetsUtil.ConnectorNamesMap[ConstantsUtil.COINBASE_CONNECTOR_ID]!, type: coinbaseConnector.type, async connect({ chainId } = {}) { try { diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index 13f28df4..52d0a3bb 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -4,6 +4,7 @@ export { DateUtil } from './utils/DateUtil'; export { NamesUtil } from './utils/NamesUtil'; export { NetworkUtil } from './utils/NetworkUtil'; export { NumberUtil } from './utils/NumberUtil'; +export { PresetsUtil } from './utils/PresetsUtil'; export { StringUtil } from './utils/StringUtil'; export { ErrorUtil } from './utils/ErrorUtil'; export { erc20ABI } from './contracts/erc20'; diff --git a/packages/common/src/utils/ConstantsUtil.ts b/packages/common/src/utils/ConstantsUtil.ts index 4d21f178..e5a8ee51 100644 --- a/packages/common/src/utils/ConstantsUtil.ts +++ b/packages/common/src/utils/ConstantsUtil.ts @@ -1,11 +1,22 @@ export const ConstantsUtil = { + VERSION: '1.2.1', + + EIP155: 'eip155', + ADD_CHAIN_METHOD: 'wallet_addEthereumChain', + WC_NAME_SUFFIX: '.reown.id', WC_NAME_SUFFIX_LEGACY: '.wcn.id', + BLOCKCHAIN_API_RPC_URL: 'https://rpc.walletconnect.org', PULSE_API_URL: 'https://pulse.walletconnect.org', API_URL: 'https://api.web3modal.org', + + WALLET_CONNECT_CONNECTOR_ID: 'walletConnect', COINBASE_CONNECTOR_ID: 'coinbaseWallet', + AUTH_CONNECTOR_ID: 'appKitAuth', + COINBASE_EXPLORER_ID: 'fd20dc426fb37566d803205b19bbc1d4096b248ac04548e3cfb6b3a38bd033aa', + USDT_CONTRACT_ADDRESSES: [ // Mainnet '0xdac17f958d2ee523a2206206994597c13d831ec7', diff --git a/packages/scaffold-utils/src/utils/PresetsUtil.ts b/packages/common/src/utils/PresetsUtil.ts similarity index 94% rename from packages/scaffold-utils/src/utils/PresetsUtil.ts rename to packages/common/src/utils/PresetsUtil.ts index fd510290..b949dded 100644 --- a/packages/scaffold-utils/src/utils/PresetsUtil.ts +++ b/packages/common/src/utils/PresetsUtil.ts @@ -1,4 +1,4 @@ -import type { ConnectorType } from '@reown/appkit-scaffold-react-native'; +import type { ConnectorType } from './TypeUtil'; import { ConstantsUtil } from './ConstantsUtil'; export const PresetsUtil = { @@ -48,17 +48,17 @@ export const PresetsUtil = { 1313161554: '3ff73439-a619-4894-9262-4470c773a100' } as Record, + ConnectorNamesMap: { + [ConstantsUtil.WALLET_CONNECT_CONNECTOR_ID]: 'WalletConnect', + [ConstantsUtil.COINBASE_CONNECTOR_ID]: 'Coinbase Wallet', + [ConstantsUtil.AUTH_CONNECTOR_ID]: 'AppKit Universal Wallet' + } as Record, + ConnectorImageIds: { [ConstantsUtil.COINBASE_CONNECTOR_ID]: '0c2840c3-5b04-4c44-9661-fbd4b49e1800', [ConstantsUtil.WALLET_CONNECT_CONNECTOR_ID]: 'ef1a1fcf-7fe8-4d69-bd6d-fda1345b4400' } as Record, - ConnectorNamesMap: { - [ConstantsUtil.WALLET_CONNECT_CONNECTOR_ID]: 'WalletConnect', - [ConstantsUtil.COINBASE_CONNECTOR_ID]: 'Coinbase', - [ConstantsUtil.AUTH_CONNECTOR_ID]: 'Auth' - } as Record, - ConnectorTypesMap: { [ConstantsUtil.WALLET_CONNECT_CONNECTOR_ID]: 'WALLET_CONNECT', [ConstantsUtil.COINBASE_CONNECTOR_ID]: 'COINBASE', diff --git a/packages/common/src/utils/TypeUtil.ts b/packages/common/src/utils/TypeUtil.ts index a25bdcd6..13ea7ede 100644 --- a/packages/common/src/utils/TypeUtil.ts +++ b/packages/common/src/utils/TypeUtil.ts @@ -93,3 +93,5 @@ export type ThemeMode = 'dark' | 'light'; export interface ThemeVariables { accent?: string; } + +export type ConnectorType = 'WALLET_CONNECT' | 'COINBASE' | 'AUTH' | 'EXTERNAL'; diff --git a/packages/core/src/controllers/ConnectorController.ts b/packages/core/src/controllers/ConnectorController.ts index a74a4c1c..ad65496b 100644 --- a/packages/core/src/controllers/ConnectorController.ts +++ b/packages/core/src/controllers/ConnectorController.ts @@ -1,6 +1,7 @@ +import type { ConnectorType } from '@reown/appkit-common-react-native'; import { subscribeKey as subKey } from 'valtio/utils'; import { proxy, ref } from 'valtio'; -import type { Connector, ConnectorType } from '../utils/TypeUtil'; +import type { Connector } from '../utils/TypeUtil'; import { StorageUtil } from '../utils/StorageUtil'; // -- Types --------------------------------------------- // diff --git a/packages/core/src/utils/StorageUtil.ts b/packages/core/src/utils/StorageUtil.ts index e340d58b..b60e0c2a 100644 --- a/packages/core/src/utils/StorageUtil.ts +++ b/packages/core/src/utils/StorageUtil.ts @@ -1,7 +1,7 @@ /* eslint-disable no-console */ import AsyncStorage from '@react-native-async-storage/async-storage'; -import type { ConnectorType, WcWallet } from './TypeUtil'; -import type { SocialProvider } from '@reown/appkit-common-react-native'; +import type { WcWallet } from './TypeUtil'; +import type { SocialProvider, ConnectorType } from '@reown/appkit-common-react-native'; // -- Helpers ----------------------------------------------------------------- const WC_DEEPLINK = 'WALLETCONNECT_DEEPLINK_CHOICE'; diff --git a/packages/core/src/utils/TypeUtil.ts b/packages/core/src/utils/TypeUtil.ts index 498a1810..e4bddbc3 100644 --- a/packages/core/src/utils/TypeUtil.ts +++ b/packages/core/src/utils/TypeUtil.ts @@ -3,7 +3,8 @@ import type { Balance, SocialProvider, ThemeMode, - Transaction + Transaction, + ConnectorType } from '@reown/appkit-common-react-native'; export interface BaseError { @@ -38,8 +39,6 @@ export type ProjectId = string; export type Platform = 'mobile' | 'web' | 'qrcode' | 'email' | 'unsupported'; -export type ConnectorType = 'WALLET_CONNECT' | 'COINBASE' | 'AUTH' | 'EXTERNAL'; - export type Connector = { id: string; type: ConnectorType; diff --git a/packages/ethers/src/client.ts b/packages/ethers/src/client.ts index 0111ff53..ab0ef7e4 100644 --- a/packages/ethers/src/client.ts +++ b/packages/ethers/src/client.ts @@ -28,10 +28,15 @@ import { type AppKitFrameAccountType, type EstimateGasTransactionArgs } from '@reown/appkit-scaffold-react-native'; -import { erc20ABI, ErrorUtil, NamesUtil, NetworkUtil } from '@reown/appkit-common-react-native'; import { - ConstantsUtil, + erc20ABI, + ErrorUtil, + NamesUtil, + NetworkUtil, PresetsUtil, + ConstantsUtil +} from '@reown/appkit-common-react-native'; +import { HelpersUtil, StorageUtil, EthersConstantsUtil, @@ -957,14 +962,15 @@ export class AppKit extends AppKitScaffold { explorerId: PresetsUtil.ConnectorExplorerIds[ConstantsUtil.COINBASE_CONNECTOR_ID], imageId: PresetsUtil.ConnectorImageIds[ConstantsUtil.COINBASE_CONNECTOR_ID], imageUrl: this.options?.connectorImages?.[ConstantsUtil.COINBASE_CONNECTOR_ID], - name: PresetsUtil.ConnectorNamesMap[ConstantsUtil.COINBASE_CONNECTOR_ID], + name: + connector?.name ?? PresetsUtil.ConnectorNamesMap[ConstantsUtil.COINBASE_CONNECTOR_ID], type: PresetsUtil.ConnectorTypesMap[ConstantsUtil.COINBASE_CONNECTOR_ID]! }); this.checkActiveCoinbaseProvider(connector as Provider); } else { _connectors.push({ id: connector.id, - name: connector.name, + name: connector.name ?? PresetsUtil.ConnectorNamesMap[connector.id], type: 'EXTERNAL' }); } diff --git a/packages/ethers/src/index.tsx b/packages/ethers/src/index.tsx index ccdeddbf..2bd2a569 100644 --- a/packages/ethers/src/index.tsx +++ b/packages/ethers/src/index.tsx @@ -1,10 +1,6 @@ import { useEffect, useState, useSyncExternalStore } from 'react'; import { useSnapshot } from 'valtio'; -import { - ConstantsUtil, - EthersStoreUtil, - type Provider -} from '@reown/appkit-scaffold-utils-react-native'; +import { EthersStoreUtil, type Provider } from '@reown/appkit-scaffold-utils-react-native'; export { AccountButton, @@ -14,7 +10,7 @@ export { AppKit } from '@reown/appkit-scaffold-react-native'; import type { EventName, EventsControllerState } from '@reown/appkit-scaffold-react-native'; - +import { ConstantsUtil } from '@reown/appkit-common-react-native'; export { defaultConfig } from './utils/defaultConfig'; import type { AppKitOptions } from './client'; diff --git a/packages/ethers/src/utils/helpers.ts b/packages/ethers/src/utils/helpers.ts index 221b7cf1..2035ecb4 100644 --- a/packages/ethers/src/utils/helpers.ts +++ b/packages/ethers/src/utils/helpers.ts @@ -1,5 +1,5 @@ import type { CaipNetworkId } from '@reown/appkit-scaffold-react-native'; -import { PresetsUtil, ConstantsUtil } from '@reown/appkit-scaffold-utils-react-native'; +import { PresetsUtil, ConstantsUtil } from '@reown/appkit-common-react-native'; import EthereumProvider from '@walletconnect/ethereum-provider'; export async function getWalletConnectCaipNetworks(provider?: EthereumProvider) { diff --git a/packages/ethers5/src/client.ts b/packages/ethers5/src/client.ts index 8e8e6b67..a371c964 100644 --- a/packages/ethers5/src/client.ts +++ b/packages/ethers5/src/client.ts @@ -16,8 +16,6 @@ import { AppKitScaffold } from '@reown/appkit-scaffold-react-native'; import { - ConstantsUtil, - PresetsUtil, StorageUtil, HelpersUtil, EthersConstantsUtil, @@ -38,7 +36,14 @@ import { getDidAddress, type AppKitSIWEClient } from '@reown/appkit-siwe-react-native'; -import { erc20ABI, ErrorUtil, NamesUtil, NetworkUtil } from '@reown/appkit-common-react-native'; +import { + erc20ABI, + ErrorUtil, + NamesUtil, + NetworkUtil, + ConstantsUtil, + PresetsUtil +} from '@reown/appkit-common-react-native'; import EthereumProvider, { OPTIONAL_METHODS } from '@walletconnect/ethereum-provider'; import type { EthereumProviderOptions } from '@walletconnect/ethereum-provider'; import { type JsonRpcError } from '@walletconnect/jsonrpc-types'; @@ -941,7 +946,7 @@ export class AppKit extends AppKitScaffold { } else { _connectors.push({ id: connector.id, - name: connector.name, + name: connector.name ?? PresetsUtil.ConnectorNamesMap[connector.id], type: 'EXTERNAL' }); } diff --git a/packages/ethers5/src/index.tsx b/packages/ethers5/src/index.tsx index 72e55c58..868e583f 100644 --- a/packages/ethers5/src/index.tsx +++ b/packages/ethers5/src/index.tsx @@ -7,11 +7,9 @@ export { AppKit } from '@reown/appkit-scaffold-react-native'; import type { EventName, EventsControllerState } from '@reown/appkit-scaffold-react-native'; -import { - ConstantsUtil, - EthersStoreUtil, - type Provider -} from '@reown/appkit-scaffold-utils-react-native'; +import { EthersStoreUtil, type Provider } from '@reown/appkit-scaffold-utils-react-native'; +import { ConstantsUtil } from '@reown/appkit-common-react-native'; + export { defaultConfig } from './utils/defaultConfig'; import { useEffect, useState, useSyncExternalStore } from 'react'; import type { AppKitOptions } from './client'; diff --git a/packages/ethers5/src/utils/helpers.ts b/packages/ethers5/src/utils/helpers.ts index 221b7cf1..2035ecb4 100644 --- a/packages/ethers5/src/utils/helpers.ts +++ b/packages/ethers5/src/utils/helpers.ts @@ -1,5 +1,5 @@ import type { CaipNetworkId } from '@reown/appkit-scaffold-react-native'; -import { PresetsUtil, ConstantsUtil } from '@reown/appkit-scaffold-utils-react-native'; +import { PresetsUtil, ConstantsUtil } from '@reown/appkit-common-react-native'; import EthereumProvider from '@walletconnect/ethereum-provider'; export async function getWalletConnectCaipNetworks(provider?: EthereumProvider) { diff --git a/packages/scaffold-utils/package.json b/packages/scaffold-utils/package.json index 413b185f..1d436d04 100644 --- a/packages/scaffold-utils/package.json +++ b/packages/scaffold-utils/package.json @@ -35,6 +35,7 @@ "access": "public" }, "dependencies": { + "@reown/appkit-common-react-native": "1.2.1", "@reown/appkit-scaffold-react-native": "1.2.1" }, "react-native": "src/index.ts", diff --git a/packages/scaffold-utils/src/index.ts b/packages/scaffold-utils/src/index.ts index a8ecb245..c01545ca 100644 --- a/packages/scaffold-utils/src/index.ts +++ b/packages/scaffold-utils/src/index.ts @@ -1,5 +1,3 @@ -export { ConstantsUtil } from './utils/ConstantsUtil'; -export { PresetsUtil } from './utils/PresetsUtil'; export { HelpersUtil } from './utils/HelpersUtil'; export { StorageUtil } from './utils/StorageUtil'; diff --git a/packages/scaffold-utils/src/utils/ConstantsUtil.ts b/packages/scaffold-utils/src/utils/ConstantsUtil.ts deleted file mode 100644 index c2cc8e80..00000000 --- a/packages/scaffold-utils/src/utils/ConstantsUtil.ts +++ /dev/null @@ -1,8 +0,0 @@ -export const ConstantsUtil = { - VERSION: '1.2.1', - WALLET_CONNECT_CONNECTOR_ID: 'walletConnect', - COINBASE_CONNECTOR_ID: 'coinbaseWallet', - AUTH_CONNECTOR_ID: 'appKitAuth', - EIP155: 'eip155', - ADD_CHAIN_METHOD: 'wallet_addEthereumChain' -}; diff --git a/packages/scaffold-utils/src/utils/EthersHelpersUtil.ts b/packages/scaffold-utils/src/utils/EthersHelpersUtil.ts index 2ef1bc53..338fbd47 100644 --- a/packages/scaffold-utils/src/utils/EthersHelpersUtil.ts +++ b/packages/scaffold-utils/src/utils/EthersHelpersUtil.ts @@ -1,6 +1,6 @@ import type { CaipNetwork } from '@reown/appkit-scaffold-react-native'; -import { ConstantsUtil } from './ConstantsUtil'; -import { PresetsUtil } from './PresetsUtil'; +import { ConstantsUtil, PresetsUtil } from '@reown/appkit-common-react-native'; + import type { Chain, Provider } from './EthersTypesUtil'; export const EthersHelpersUtil = { diff --git a/packages/scaffold-utils/src/utils/HelpersUtil.ts b/packages/scaffold-utils/src/utils/HelpersUtil.ts index 7e443fff..354d3e99 100644 --- a/packages/scaffold-utils/src/utils/HelpersUtil.ts +++ b/packages/scaffold-utils/src/utils/HelpersUtil.ts @@ -1,5 +1,5 @@ import type { Tokens } from '@reown/appkit-scaffold-react-native'; -import { ConstantsUtil } from './ConstantsUtil'; +import { ConstantsUtil } from '@reown/appkit-common-react-native'; export const HelpersUtil = { getCaipTokens(tokens?: Tokens) { diff --git a/packages/scaffold/src/views/w3m-connect-view/components/connectors-list.tsx b/packages/scaffold/src/views/w3m-connect-view/components/connectors-list.tsx index fd655376..e1920354 100644 --- a/packages/scaffold/src/views/w3m-connect-view/components/connectors-list.tsx +++ b/packages/scaffold/src/views/w3m-connect-view/components/connectors-list.tsx @@ -1,13 +1,14 @@ import { useSnapshot } from 'valtio'; +import type { StyleProp, ViewStyle } from 'react-native'; import { ConnectorController, AssetUtil, RouterController, - type ConnectorType, ApiController } from '@reown/appkit-core-react-native'; + import { ListWallet } from '@reown/appkit-ui-react-native'; -import type { StyleProp, ViewStyle } from 'react-native'; +import type { ConnectorType } from '@reown/appkit-common-react-native'; interface Props { itemStyle: StyleProp; diff --git a/packages/wagmi/src/client.ts b/packages/wagmi/src/client.ts index 81026a96..0688b2d8 100644 --- a/packages/wagmi/src/client.ts +++ b/packages/wagmi/src/client.ts @@ -41,13 +41,15 @@ import { type AppKitFrameProvider, type EstimateGasTransactionArgs } from '@reown/appkit-scaffold-react-native'; +import { HelpersUtil, StorageUtil } from '@reown/appkit-scaffold-utils-react-native'; import { + NetworkUtil, + NamesUtil, + ErrorUtil, ConstantsUtil, - HelpersUtil, PresetsUtil, - StorageUtil -} from '@reown/appkit-scaffold-utils-react-native'; -import { NetworkUtil, NamesUtil, ErrorUtil } from '@reown/appkit-common-react-native'; + type ConnectorType +} from '@reown/appkit-common-react-native'; import { SIWEController, getDidChainId, @@ -606,8 +608,8 @@ export class AppKit extends AppKitScaffold { const provider = await authConnector.getProvider(); this.addConnector({ id: ConstantsUtil.AUTH_CONNECTOR_ID, - type: 'AUTH', - name: 'Auth', + type: PresetsUtil.ConnectorTypesMap[ConstantsUtil.AUTH_CONNECTOR_ID]!, + name: PresetsUtil.ConnectorNamesMap[ConstantsUtil.AUTH_CONNECTOR_ID], provider }); this.addAuthListeners(authConnector); @@ -615,7 +617,9 @@ export class AppKit extends AppKitScaffold { } private async addAuthListeners(connector: WagmiConnector) { - const connectedConnector = await StorageUtil.getItem('@w3m/connected_connector'); + const connectedConnector: ConnectorType | undefined = await StorageUtil.getItem( + '@w3m/connected_connector' + ); if (connectedConnector === 'AUTH') { // Set loader until it reconnects diff --git a/packages/wagmi/src/index.tsx b/packages/wagmi/src/index.tsx index 642fe8e4..51872665 100644 --- a/packages/wagmi/src/index.tsx +++ b/packages/wagmi/src/index.tsx @@ -1,4 +1,5 @@ import '@walletconnect/react-native-compat'; +import { useEffect, useState, useSyncExternalStore } from 'react'; export { AccountButton, AppKitButton, @@ -7,9 +8,9 @@ export { AppKit } from '@reown/appkit-scaffold-react-native'; import type { EventName, EventsControllerState } from '@reown/appkit-scaffold-react-native'; -import { ConstantsUtil } from '@reown/appkit-scaffold-utils-react-native'; +import { ConstantsUtil } from '@reown/appkit-common-react-native'; + export { defaultWagmiConfig } from './utils/defaultWagmiConfig'; -import { useEffect, useState, useSyncExternalStore } from 'react'; import type { AppKitOptions } from './client'; import { AppKit } from './client'; diff --git a/packages/wagmi/src/utils/helpers.ts b/packages/wagmi/src/utils/helpers.ts index 791ff854..78a325b9 100644 --- a/packages/wagmi/src/utils/helpers.ts +++ b/packages/wagmi/src/utils/helpers.ts @@ -3,7 +3,7 @@ import { type CaipNetwork, type CaipNetworkId } from '@reown/appkit-scaffold-react-native'; -import { PresetsUtil, ConstantsUtil } from '@reown/appkit-scaffold-utils-react-native'; +import { PresetsUtil, ConstantsUtil } from '@reown/appkit-common-react-native'; import type { Connector } from '@wagmi/core'; import { EthereumProvider } from '@walletconnect/ethereum-provider'; import type { AppKitClientOptions } from '../client'; diff --git a/scripts/bump-version.sh b/scripts/bump-version.sh index 43c4cb2b..371d5a5a 100755 --- a/scripts/bump-version.sh +++ b/scripts/bump-version.sh @@ -4,7 +4,7 @@ version=$(awk -F: '/"version":/ {print $2}' packages/core/package.json | tr -d ' ",') -utils="packages/scaffold-utils/src/utils/ConstantsUtil.ts" +utils="packages/common/src/utils/ConstantsUtil.ts" rootjson="package.json" # Replace version in ConstantsUtil.ts diff --git a/yarn.lock b/yarn.lock index e9521b78..05cd784f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6683,6 +6683,7 @@ __metadata: version: 0.0.0-use.local resolution: "@reown/appkit-auth-ethers-react-native@workspace:packages/auth-ethers" dependencies: + "@reown/appkit-common-react-native": "npm:1.2.1" "@reown/appkit-wallet-react-native": "npm:1.2.1" peerDependencies: ethers: ">=5" @@ -6693,6 +6694,7 @@ __metadata: version: 0.0.0-use.local resolution: "@reown/appkit-auth-wagmi-react-native@workspace:packages/auth-wagmi" dependencies: + "@reown/appkit-common-react-native": "npm:1.2.1" "@reown/appkit-core-react-native": "npm:1.2.1" "@reown/appkit-wallet-react-native": "npm:1.2.1" peerDependencies: @@ -6703,6 +6705,8 @@ __metadata: "@reown/appkit-coinbase-ethers-react-native@workspace:packages/coinbase-ethers": version: 0.0.0-use.local resolution: "@reown/appkit-coinbase-ethers-react-native@workspace:packages/coinbase-ethers" + dependencies: + "@reown/appkit-common-react-native": "npm:1.2.1" peerDependencies: "@coinbase/wallet-mobile-sdk": ">=1.0.10" ethers: ">=5" @@ -6712,6 +6716,8 @@ __metadata: "@reown/appkit-coinbase-wagmi-react-native@workspace:packages/coinbase-wagmi": version: 0.0.0-use.local resolution: "@reown/appkit-coinbase-wagmi-react-native@workspace:packages/coinbase-wagmi" + dependencies: + "@reown/appkit-common-react-native": "npm:1.2.1" peerDependencies: "@coinbase/wallet-mobile-sdk": ">=1.0.10" wagmi: ">=2" @@ -6802,6 +6808,7 @@ __metadata: version: 0.0.0-use.local resolution: "@reown/appkit-scaffold-utils-react-native@workspace:packages/scaffold-utils" dependencies: + "@reown/appkit-common-react-native": "npm:1.2.1" "@reown/appkit-scaffold-react-native": "npm:1.2.1" languageName: unknown linkType: soft From d3a9604b59fd177465fbf5b04ee3c26200e40384 Mon Sep 17 00:00:00 2001 From: ignaciosantise <25931366+ignaciosantise@users.noreply.github.com> Date: Wed, 12 Feb 2025 10:42:23 -0300 Subject: [PATCH 05/14] fix: improved state array updates in connection and router controllers --- .changeset/purple-berries-marry.md | 18 ++++++++++++++++++ .../src/controllers/ConnectorController.ts | 2 +- .../core/src/controllers/RouterController.ts | 4 ++-- 3 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 .changeset/purple-berries-marry.md diff --git a/.changeset/purple-berries-marry.md b/.changeset/purple-berries-marry.md new file mode 100644 index 00000000..5570df13 --- /dev/null +++ b/.changeset/purple-berries-marry.md @@ -0,0 +1,18 @@ +--- +'@reown/appkit-core-react-native': patch +'@reown/appkit-auth-ethers-react-native': patch +'@reown/appkit-auth-wagmi-react-native': patch +'@reown/appkit-coinbase-ethers-react-native': patch +'@reown/appkit-coinbase-wagmi-react-native': patch +'@reown/appkit-common-react-native': patch +'@reown/appkit-ethers-react-native': patch +'@reown/appkit-ethers5-react-native': patch +'@reown/appkit-scaffold-react-native': patch +'@reown/appkit-scaffold-utils-react-native': patch +'@reown/appkit-siwe-react-native': patch +'@reown/appkit-ui-react-native': patch +'@reown/appkit-wagmi-react-native': patch +'@reown/appkit-wallet-react-native': patch +--- + +fix: improved state array updates in connection and router controllers diff --git a/packages/core/src/controllers/ConnectorController.ts b/packages/core/src/controllers/ConnectorController.ts index a74a4c1c..b7860e69 100644 --- a/packages/core/src/controllers/ConnectorController.ts +++ b/packages/core/src/controllers/ConnectorController.ts @@ -30,7 +30,7 @@ export const ConnectorController = { }, addConnector(connector: Connector) { - state.connectors.push(ref(connector)); + state.connectors = [...state.connectors, ref(connector)]; }, getConnectors() { diff --git a/packages/core/src/controllers/RouterController.ts b/packages/core/src/controllers/RouterController.ts index 4865a8e7..d608e566 100644 --- a/packages/core/src/controllers/RouterController.ts +++ b/packages/core/src/controllers/RouterController.ts @@ -72,13 +72,13 @@ export const RouterController = { push(view: RouterControllerState['view'], data?: RouterControllerState['data']) { if (view !== state.view) { state.view = view; - state.history.push(view); + state.history = [...state.history, view]; state.data = data; } }, pushTransactionStack(action: TransactionAction) { - state.transactionStack.push(action); + state.transactionStack = [...state.transactionStack, action]; }, popTransactionStack(cancel?: boolean) { From 1f80e20b22e7f10d1a6d778d8da3256fe9c43eb1 Mon Sep 17 00:00:00 2001 From: ignaciosantise <25931366+ignaciosantise@users.noreply.github.com> Date: Mon, 17 Feb 2025 11:41:07 -0300 Subject: [PATCH 06/14] chore: added extra connected wallet info params --- packages/core/src/utils/TypeUtil.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/core/src/utils/TypeUtil.ts b/packages/core/src/utils/TypeUtil.ts index e4bddbc3..07d385ce 100644 --- a/packages/core/src/utils/TypeUtil.ts +++ b/packages/core/src/utils/TypeUtil.ts @@ -26,6 +26,14 @@ export type ConnectedWalletInfo = | { name?: string; icon?: string; + description?: string; + url?: string; + icons?: string[]; + redirect?: { + native?: string; + universal?: string; + linkMode?: boolean; + }; [key: string]: unknown; } | undefined; From cab165d4a0f520aecf74e7611069db833453e551 Mon Sep 17 00:00:00 2001 From: ignaciosantise <25931366+ignaciosantise@users.noreply.github.com> Date: Thu, 20 Feb 2025 14:58:36 -0300 Subject: [PATCH 07/14] chore: send origin to blockchain api, added expo check for user agent --- .../controllers/BlockchainApiController.ts | 5 +++- packages/core/src/utils/ApiUtil.ts | 26 ++++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/packages/core/src/controllers/BlockchainApiController.ts b/packages/core/src/controllers/BlockchainApiController.ts index 2b982d40..6ee7e65b 100644 --- a/packages/core/src/controllers/BlockchainApiController.ts +++ b/packages/core/src/controllers/BlockchainApiController.ts @@ -26,6 +26,7 @@ import type { } from '../utils/TypeUtil'; import { OptionsController } from './OptionsController'; import { ConstantsUtil } from '../utils/ConstantsUtil'; +import { ApiUtil } from '../utils/ApiUtil'; // -- Helpers ------------------------------------------- // const baseUrl = CoreHelperUtil.getBlockchainApiUrl(); @@ -36,7 +37,9 @@ const getHeaders = () => { return { 'Content-Type': 'application/json', 'x-sdk-type': sdkType, - 'x-sdk-version': sdkVersion + 'x-sdk-version': sdkVersion, + 'User-Agent': ApiUtil.getUserAgent(), + 'origin': ApiUtil.getOrigin() }; }; diff --git a/packages/core/src/utils/ApiUtil.ts b/packages/core/src/utils/ApiUtil.ts index bcf778f0..41319121 100644 --- a/packages/core/src/utils/ApiUtil.ts +++ b/packages/core/src/utils/ApiUtil.ts @@ -14,6 +14,26 @@ export const ApiUtil = { ].join('.'); }, + getEnvironment() { + try { + // Check if Expo is installed + const hasExpoGlobal = !!(global as any).expo; + const hasExpoConstants = hasExpoGlobal && (global as any).expo?.modules?.ExponentConstants; + const environment: string | undefined = + hasExpoConstants && (global as any).expo?.modules?.ExponentConstants?.executionEnvironment; + + if (environment === 'standalone' || environment === 'storeClient') { + return 'expo-managed'; + } else if (environment === 'bare') { + return 'expo-bare'; + } + + return 'bare'; + } catch { + return 'bare'; + } + }, + getUserAgent() { const rnVersion = Platform.select({ ios: this.getReactNativeVersion(), @@ -21,6 +41,10 @@ export const ApiUtil = { default: 'undefined' }); - return `${Platform.OS}-${Platform.Version}@rn-${rnVersion}`; + const envPrefix = this.getEnvironment(); + + const userAgent = `${Platform.OS}-${Platform.Version}@rn-${rnVersion}@${envPrefix}`; + + return userAgent; } }; From 19e17ef9b85e4d81f424438d83c3f3c89dd80c92 Mon Sep 17 00:00:00 2001 From: ignaciosantise <25931366+ignaciosantise@users.noreply.github.com> Date: Thu, 20 Feb 2025 15:39:11 -0300 Subject: [PATCH 08/14] chore: changeset --- .changeset/witty-melons-brush.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .changeset/witty-melons-brush.md diff --git a/.changeset/witty-melons-brush.md b/.changeset/witty-melons-brush.md new file mode 100644 index 00000000..343f1f66 --- /dev/null +++ b/.changeset/witty-melons-brush.md @@ -0,0 +1,18 @@ +--- +'@reown/appkit-coinbase-ethers-react-native': patch +'@reown/appkit-coinbase-wagmi-react-native': patch +'@reown/appkit-scaffold-utils-react-native': patch +'@reown/appkit-auth-ethers-react-native': patch +'@reown/appkit-auth-wagmi-react-native': patch +'@reown/appkit-scaffold-react-native': patch +'@reown/appkit-ethers5-react-native': patch +'@reown/appkit-common-react-native': patch +'@reown/appkit-ethers-react-native': patch +'@reown/appkit-wagmi-react-native': patch +'@reown/appkit-core-react-native': patch +'@reown/appkit-siwe-react-native': patch +'@reown/appkit-ui-react-native': patch +'@reown/appkit-wallet-react-native': patch +--- + +chore: send expo info in useragent From f3f4f3754673e0e85c110f41d9c77e27e30caa68 Mon Sep 17 00:00:00 2001 From: ignaciosantise <25931366+ignaciosantise@users.noreply.github.com> Date: Thu, 20 Feb 2025 15:41:41 -0300 Subject: [PATCH 09/14] fix: load transactions only when needed --- .changeset/empty-mangos-push.md | 18 ++++++++++++++++++ .../scaffold/src/modal/w3m-modal/index.tsx | 1 - .../partials/w3m-account-activity/index.tsx | 8 +++++++- 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 .changeset/empty-mangos-push.md diff --git a/.changeset/empty-mangos-push.md b/.changeset/empty-mangos-push.md new file mode 100644 index 00000000..7f70026a --- /dev/null +++ b/.changeset/empty-mangos-push.md @@ -0,0 +1,18 @@ +--- +'@reown/appkit-coinbase-ethers-react-native': patch +'@reown/appkit-coinbase-wagmi-react-native': patch +'@reown/appkit-scaffold-utils-react-native': patch +'@reown/appkit-auth-ethers-react-native': patch +'@reown/appkit-auth-wagmi-react-native': patch +'@reown/appkit-scaffold-react-native': patch +'@reown/appkit-ethers5-react-native': patch +'@reown/appkit-common-react-native': patch +'@reown/appkit-ethers-react-native': patch +'@reown/appkit-wagmi-react-native': patch +'@reown/appkit-core-react-native': patch +'@reown/appkit-siwe-react-native': patch +'@reown/appkit-ui-react-native': patch +'@reown/appkit-wallet-react-native': patch +--- + +fix: load transactions when needed diff --git a/packages/scaffold/src/modal/w3m-modal/index.tsx b/packages/scaffold/src/modal/w3m-modal/index.tsx index fe2db865..678942ec 100644 --- a/packages/scaffold/src/modal/w3m-modal/index.tsx +++ b/packages/scaffold/src/modal/w3m-modal/index.tsx @@ -71,7 +71,6 @@ export function AppKit() { const newAddress = CoreHelperUtil.getPlainAddress(address); TransactionsController.resetTransactions(); - TransactionsController.fetchTransactions(newAddress, true); if (OptionsController.state.isSiweEnabled) { const newNetworkId = CoreHelperUtil.getNetworkId(address); diff --git a/packages/scaffold/src/partials/w3m-account-activity/index.tsx b/packages/scaffold/src/partials/w3m-account-activity/index.tsx index b08ff265..5d75547a 100644 --- a/packages/scaffold/src/partials/w3m-account-activity/index.tsx +++ b/packages/scaffold/src/partials/w3m-account-activity/index.tsx @@ -1,4 +1,4 @@ -import { useCallback, useMemo, useState } from 'react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; import { useSnapshot } from 'valtio'; import { ScrollView, View, type StyleProp, type ViewStyle, RefreshControl } from 'react-native'; import { @@ -58,6 +58,12 @@ export function AccountActivity({ style }: Props) { return TransactionsController.getTransactionsByYearAndMonth(transactions as Transaction[]); }, [transactions]); + useEffect(() => { + if (!TransactionsController.state.transactions.length) { + TransactionsController.fetchTransactions(AccountController.state.address, true); + } + }, []); + if (loading && !transactions.length) { return ( From 54f37b62df7fc7954f40f21cc4a33e2a4545406f Mon Sep 17 00:00:00 2001 From: ignaciosantise <25931366+ignaciosantise@users.noreply.github.com> Date: Fri, 21 Feb 2025 13:22:17 -0300 Subject: [PATCH 10/14] chore: added tests --- .maestro/w3m-connect-flow.yaml | 4 +- apps/native/tests/shared/pages/ModalPage.ts | 91 +++---------------- apps/native/tests/shared/pages/WalletPage.ts | 22 ++++- .../tests/shared/validators/ModalValidator.ts | 17 +--- apps/native/tests/wallet.spec.ts | 49 +++++++++- .../views/w3m-account-default-view/index.tsx | 8 +- .../components/wui-loading-spinner/index.tsx | 10 +- 7 files changed, 96 insertions(+), 105 deletions(-) diff --git a/.maestro/w3m-connect-flow.yaml b/.maestro/w3m-connect-flow.yaml index 155431e5..ac7a4d80 100644 --- a/.maestro/w3m-connect-flow.yaml +++ b/.maestro/w3m-connect-flow.yaml @@ -57,7 +57,7 @@ appId: com.walletconnect.web3modal.rnclisdk id: 'account-button' - tapOn: - id: 'w3m-account-select-network' + id: 'button-network' - tapOn: text: 'Polygon' @@ -68,7 +68,7 @@ appId: com.walletconnect.web3modal.rnclisdk text: 'Polygon' - tapOn: - id: 'disconnect-button' + id: 'button-disconnect' - assertVisible: id: 'connect-button' diff --git a/apps/native/tests/shared/pages/ModalPage.ts b/apps/native/tests/shared/pages/ModalPage.ts index a8840f21..7781c80c 100644 --- a/apps/native/tests/shared/pages/ModalPage.ts +++ b/apps/native/tests/shared/pages/ModalPage.ts @@ -92,7 +92,7 @@ export class ModalPage { await expect(accountBtn, 'Account button should be visible').toBeVisible(); await expect(accountBtn, 'Account button should be enabled').toBeEnabled(); await accountBtn.click(); - const disconnectBtn = this.page.getByTestId('disconnect-button'); + const disconnectBtn = this.page.getByTestId('button-disconnect'); await expect(disconnectBtn, 'Disconnect button should be visible').toBeVisible(); await expect(disconnectBtn, 'Disconnect button should be enabled').toBeEnabled(); await disconnectBtn.click(); @@ -126,19 +126,11 @@ export class ModalPage { // } async switchNetwork(network: string) { - await this.openAccountModal(); - await this.page.getByTestId('w3m-account-select-network').click(); await this.page.getByTestId(`w3m-network-switch-${network}`).click(); // The state is chaing too fast and test runner doesn't wait the loading page. It's fastly checking the network selection button and detect that it's switched already. await this.page.waitForTimeout(300); } - // async clickWalletDeeplink() { - // await this.connectButton.click(); - // await this.page.getByTestId('wallet-selector-react-wallet-v2').click(); - // await this.page.getByTestId('tab-desktop').click(); - // } - async openAccountModal() { await this.page.getByTestId('account-button').click(); } @@ -157,14 +149,6 @@ export class ModalPage { await this.page.waitForTimeout(300); } - // async switchNetworkWithNetworkButton(networkName: string) { - // const networkButton = this.page.getByTestId('wui-network-button'); - // await networkButton.click(); - - // const networkToSwitchButton = this.page.getByTestId(`w3m-network-switch-${networkName}`); - // await networkToSwitchButton.click(); - // } - async openAllWallets() { const allWallets = this.page.getByTestId('all-wallets'); await expect(allWallets, 'All wallets should be visible').toBeVisible(); @@ -177,18 +161,6 @@ export class ModalPage { await qrCodeButton.click(); } - // async clickAllWalletsListSearchItem(id: string) { - // const allWalletsListSearchItem = this.page.getByTestId(`wallet-search-item-${id}`); - // await expect(allWalletsListSearchItem).toBeVisible(); - // await allWalletsListSearchItem.click(); - // } - - // async clickTabWebApp() { - // const tabWebApp = this.page.getByTestId('tab-webapp'); - // await expect(tabWebApp).toBeVisible(); - // await tabWebApp.click(); - // } - async clickHookDisconnectButton() { const disconnectHookButton = this.page.getByTestId('disconnect-hook-button'); await expect(disconnectHookButton).toBeVisible(); @@ -216,33 +188,6 @@ export class ModalPage { return this.page.evaluate(() => navigator.clipboard.readText()); } - // async clickOpenWebApp() { - // let url = ''; - - // const openButton = this.page.getByTestId('w3m-connecting-widget-secondary-button'); - // await expect(openButton).toBeVisible(); - // await expect(openButton).toHaveText('Open'); - - // while (!url) { - // await openButton.click(); - // await this.page.waitForTimeout(500); - - // const pages = this.page.context().pages(); - - // // Check if more than 1 tab is open - // if (pages.length > 1) { - // const lastTab = pages[pages.length - 1]; - - // if (lastTab) { - // url = lastTab.url(); - // break; - // } - // } - // } - - // return url; - // } - async search(value: string) { const searchInput = this.page.getByTestId('wui-input-text'); await expect(searchInput, 'Search input should be visible').toBeVisible(); @@ -250,30 +195,24 @@ export class ModalPage { await searchInput.fill(value); } - async openNetworks() { - await this.page.getByTestId('w3m-account-select-network').click(); + async goToNetworks() { + await this.page.getByTestId('button-network').click(); await expect(this.page.getByText('Select network')).toBeVisible(); } - // async openProfileView() { - // await this.page.getByTestId('wui-profile-button').click(); - // } - - // async getAddress(): Promise<`0x${string}`> { - // const address = await this.page.getByTestId('w3m-address').textContent(); - // expect(address, 'Address should be present').toBeTruthy(); - - // return address as `0x${string}`; - // } + async goToActivity() { + await this.page.getByTestId('button-activity').click(); + } - // async getChainId(): Promise { - // const chainId = await this.page.getByTestId('w3m-chain-id').textContent(); - // expect(chainId, 'Chain ID should be present').toBeTruthy(); + async goBack() { + await this.page.getByTestId('button-back').click(); + } - // return Number(chainId); - // } + async expectLoaderVisible() { + await expect(this.page.getByTestId('loading-spinner')).toBeVisible(); + } - // async switchNetworkWithHook() { - // await this.page.getByTestId('switch-network-hook-button').click(); - // } + async expectLoaderHidden() { + await expect(this.page.getByTestId('loading-spinner')).toBeHidden(); + } } diff --git a/apps/native/tests/shared/pages/WalletPage.ts b/apps/native/tests/shared/pages/WalletPage.ts index 49f5a203..44a48135 100644 --- a/apps/native/tests/shared/pages/WalletPage.ts +++ b/apps/native/tests/shared/pages/WalletPage.ts @@ -117,9 +117,23 @@ export class WalletPage { await this.page.waitForLoadState(); const sessionsButton = this.page.getByTestId('sessions'); await sessionsButton.click(); - const sessionCard = this.page.getByTestId(`session-card`); - await sessionCard.click(); - const disconnectButton = this.page.getByText('Delete'); - await disconnectButton.click(); + + // Try to disconnect all visible session cards + while (true) { + const sessionCards = this.page.getByTestId('session-card'); + const count = await sessionCards.count(); + + if (count === 0) { + break; + } + + // Click the first card and disconnect it + await sessionCards.first().click(); + const disconnectButton = this.page.getByText('Delete'); + await disconnectButton.click(); + + // Wait a bit for the disconnection to complete + await this.page.waitForTimeout(500); + } } } diff --git a/apps/native/tests/shared/validators/ModalValidator.ts b/apps/native/tests/shared/validators/ModalValidator.ts index d27de8fb..113c0c1f 100644 --- a/apps/native/tests/shared/validators/ModalValidator.ts +++ b/apps/native/tests/shared/validators/ModalValidator.ts @@ -82,16 +82,6 @@ export class ModalValidator { await expect(address, 'Correct address should be present').toHaveText(expectedAddress); } - // async expectNetwork(network: string) { - // const networkButton = this.page.getByTestId('w3m-account-select-network'); - // await expect(networkButton, `Network button should contain text ${network}`).toHaveText( - // network, - // { - // timeout: 5000 - // } - // ); - // } - async expectAcceptedSign() { await expect(this.page.getByText('Signature successful')).toBeVisible({ timeout: 30 * 1000 @@ -103,7 +93,7 @@ export class ModalValidator { } async expectSwitchedNetwork(network: string) { - const switchNetworkButton = this.page.getByTestId(`w3m-account-select-network-text`); + const switchNetworkButton = this.page.getByTestId(`account-select-network-text`); await expect(switchNetworkButton).toContainText(network); } @@ -132,11 +122,6 @@ export class ModalValidator { await expect(getAWalletView).toBeVisible(); } - // async expectHeaderText(text: string) { - // const headerText = this.page.getByTestId('header-text'); - // await expect(headerText).toHaveText(text); - // } - async expectNetworksDisabled(name: string) { const disabledNetworkButton = this.page.getByTestId(`w3m-network-switch-${name}`); disabledNetworkButton.click(); diff --git a/apps/native/tests/wallet.spec.ts b/apps/native/tests/wallet.spec.ts index 6f5eb68c..75fe6e4f 100644 --- a/apps/native/tests/wallet.spec.ts +++ b/apps/native/tests/wallet.spec.ts @@ -45,7 +45,7 @@ sampleWalletTest('it should be connected instantly after page refresh', async () sampleWalletTest('it should show disabled networks', async () => { const disabledNetworks = 'Gnosis'; await modalPage.openAccountModal(); - await modalPage.openNetworks(); + await modalPage.goToNetworks(); await modalValidator.expectNetworksDisabled(disabledNetworks); await modalPage.closeModal(); }); @@ -62,6 +62,8 @@ sampleWalletTest('it should switch networks and sign', async () => { // -- Switch network -------------------------------------------------------- const chainNameOnWalletPage = chainName; + await modalPage.openAccountModal(); + await modalPage.goToNetworks(); await modalPage.switchNetwork(chainName); await modalValidator.expectSwitchedNetwork(chainName); await modalPage.closeModal(); @@ -82,6 +84,8 @@ sampleWalletTest('it should switch networks and sign', async () => { sampleWalletTest('it should show last connected network after refreshing', async () => { const chainName = 'Polygon'; + await modalPage.openAccountModal(); + await modalPage.goToNetworks(); await modalPage.switchNetwork(chainName); await modalValidator.expectSwitchedNetwork(chainName); await modalPage.closeModal(); @@ -124,3 +128,46 @@ sampleWalletTest('it should disconnect as expected', async () => { await modalPage.disconnect(); await modalValidator.expectDisconnected(); }); + +sampleWalletTest('shows loader behavior on first visit to Activity screen', async () => { + // Connect to wallet + await modalPage.qrCodeFlow(modalPage, walletPage); + await modalValidator.expectConnected(); + + // First visit to Activity screen + await modalPage.openAccountModal(); + await modalPage.goToActivity(); + await modalPage.expectLoaderVisible(); + await modalPage.expectLoaderHidden(); + + // Second visit to Activity screen + await modalPage.goBack(); + await modalPage.goToActivity(); + await modalPage.expectLoaderHidden(); + + // Third visit after closing the modal + await modalPage.closeModal(); + await modalPage.openAccountModal(); + await modalPage.goToActivity(); + await modalPage.expectLoaderHidden(); + await modalPage.closeModal(); +}); + +sampleWalletTest('shows loader behavior after network change in Activity screen', async () => { + await modalPage.openAccountModal(); + + // Change network + await modalPage.goToNetworks(); + await modalPage.switchNetwork('Polygon'); + await modalValidator.expectSwitchedNetwork('Polygon'); + + // Visit Activity screen after network change + await modalPage.goToActivity(); + await modalPage.expectLoaderVisible(); + await modalPage.expectLoaderHidden(); + + // Second visit after network change + await modalPage.goBack(); + await modalPage.goToActivity(); + await modalPage.expectLoaderHidden(); +}); diff --git a/packages/scaffold/src/views/w3m-account-default-view/index.tsx b/packages/scaffold/src/views/w3m-account-default-view/index.tsx index dba1584a..f3982ed9 100644 --- a/packages/scaffold/src/views/w3m-account-default-view/index.tsx +++ b/packages/scaffold/src/views/w3m-account-default-view/index.tsx @@ -244,10 +244,10 @@ export function AccountDefaultView() { imageSrc={networkImage} imageHeaders={ApiController._getApiHeaders()} onPress={onNetworkPress} - testID="w3m-account-select-network" + testID="button-network" style={styles.actionButton} > - + {caipNetwork?.name} @@ -259,7 +259,7 @@ export function AccountDefaultView() { iconColor="accent-100" iconBackgroundColor="accent-glass-015" onPress={onSwapPress} - testID="button-activity" + testID="button-swap" style={styles.actionButton} > Swap @@ -299,7 +299,7 @@ export function AccountDefaultView() { onPress={onDisconnect} loading={disconnecting} iconBackgroundColor="gray-glass-010" - testID="disconnect-button" + testID="button-disconnect" > Disconnect diff --git a/packages/ui/src/components/wui-loading-spinner/index.tsx b/packages/ui/src/components/wui-loading-spinner/index.tsx index 4270f571..0fff6586 100644 --- a/packages/ui/src/components/wui-loading-spinner/index.tsx +++ b/packages/ui/src/components/wui-loading-spinner/index.tsx @@ -12,9 +12,15 @@ export interface LoadingSpinnerProps { size?: Exclude; color?: Exclude; style?: StyleProp; + testID?: string; } -export function LoadingSpinner({ color, style, size = 'lg' }: LoadingSpinnerProps) { +export function LoadingSpinner({ + color, + style, + size = 'lg', + testID = 'loading-spinner' +}: LoadingSpinnerProps) { const Theme = useTheme(); const spinValue = useRef(new Animated.Value(0)); const stroke = color ? Theme[color] : Theme['accent-100']; @@ -41,7 +47,7 @@ export function LoadingSpinner({ color, style, size = 'lg' }: LoadingSpinnerProp }); return ( - + Date: Fri, 21 Feb 2025 14:24:59 -0300 Subject: [PATCH 11/14] chore: test code improvements --- apps/native/tests/shared/constants/index.ts | 18 +++++- .../native/tests/shared/constants/timeouts.ts | 1 - apps/native/tests/shared/pages/ModalPage.ts | 22 ++++--- apps/native/tests/shared/types/index.ts | 4 ++ apps/native/tests/shared/utils/timeouts.ts | 6 +- apps/native/tests/wallet.spec.ts | 62 ++++++++++++++----- 6 files changed, 86 insertions(+), 27 deletions(-) delete mode 100644 apps/native/tests/shared/constants/timeouts.ts diff --git a/apps/native/tests/shared/constants/index.ts b/apps/native/tests/shared/constants/index.ts index dc2550fe..77f3b75c 100644 --- a/apps/native/tests/shared/constants/index.ts +++ b/apps/native/tests/shared/constants/index.ts @@ -8,4 +8,20 @@ export const DEFAULT_SESSION_PARAMS: SessionParams = { optAccounts: ['1', '2'], accept: true }; -export const DEFAULT_CHAIN_NAME = process.env.DEFAULT_CHAIN_NAME || 'Ethereum'; + +export const TEST_CHAINS = { + POLYGON: 'Polygon', + ETHEREUM: 'Ethereum', + GNOSIS: 'Gnosis' +} as const; + +export type SupportedChain = (typeof TEST_CHAINS)[keyof typeof TEST_CHAINS]; + +export const TIMEOUTS = { + ANIMATION: 300, + NETWORK_SWITCH: 500, + CONNECTION: 5000, + SESSION_PROPOSAL: 30000 +} as const; + +export const DEFAULT_CHAIN_NAME = process.env.DEFAULT_CHAIN_NAME || TEST_CHAINS.ETHEREUM; diff --git a/apps/native/tests/shared/constants/timeouts.ts b/apps/native/tests/shared/constants/timeouts.ts deleted file mode 100644 index 03ff123c..00000000 --- a/apps/native/tests/shared/constants/timeouts.ts +++ /dev/null @@ -1 +0,0 @@ -export const MAXIMUM_WAIT_CONNECTIONS = 30 * 1000; diff --git a/apps/native/tests/shared/pages/ModalPage.ts b/apps/native/tests/shared/pages/ModalPage.ts index 7781c80c..b7e6f1e7 100644 --- a/apps/native/tests/shared/pages/ModalPage.ts +++ b/apps/native/tests/shared/pages/ModalPage.ts @@ -1,9 +1,9 @@ import type { Locator, Page } from '@playwright/test'; import { expect } from '@playwright/test'; -import { BASE_URL, DEFAULT_SESSION_PARAMS } from '../constants'; +import { BASE_URL, DEFAULT_SESSION_PARAMS, TIMEOUTS } from '../constants'; import { WalletValidator } from '../validators/WalletValidator'; import { WalletPage } from './WalletPage'; -import { TimingRecords } from '../types'; +import { SupportedChain, TimingRecords } from '../types'; import { ModalValidator } from '../validators/ModalValidator'; export class ModalPage { @@ -125,10 +125,10 @@ export class ModalPage { // await this.page.getByTestId('w3m-connecting-siwe-cancel').click(); // } - async switchNetwork(network: string) { + async switchNetwork(network: SupportedChain) { await this.page.getByTestId(`w3m-network-switch-${network}`).click(); - // The state is chaing too fast and test runner doesn't wait the loading page. It's fastly checking the network selection button and detect that it's switched already. - await this.page.waitForTimeout(300); + // The state is changing too fast and test runner doesn't wait for the loading page + await this.page.waitForTimeout(TIMEOUTS.NETWORK_SWITCH); } async openAccountModal() { @@ -146,7 +146,7 @@ export class ModalPage { async closeModal() { await this.page.getByTestId('header-close')?.click?.(); // Wait for the modal fade out animation - await this.page.waitForTimeout(300); + await this.page.waitForTimeout(TIMEOUTS.ANIMATION); } async openAllWallets() { @@ -209,10 +209,16 @@ export class ModalPage { } async expectLoaderVisible() { - await expect(this.page.getByTestId('loading-spinner')).toBeVisible(); + await expect( + this.page.getByTestId('loading-spinner'), + 'Loading spinner should be visible' + ).toBeVisible(); } async expectLoaderHidden() { - await expect(this.page.getByTestId('loading-spinner')).toBeHidden(); + await expect( + this.page.getByTestId('loading-spinner'), + 'Loading spinner should be hidden' + ).toBeHidden(); } } diff --git a/apps/native/tests/shared/types/index.ts b/apps/native/tests/shared/types/index.ts index abf6bc54..05d6a4a0 100644 --- a/apps/native/tests/shared/types/index.ts +++ b/apps/native/tests/shared/types/index.ts @@ -1,3 +1,5 @@ +import { TEST_CHAINS } from '../constants'; + export interface SessionParams { reqAccounts: string[]; optAccounts: string[]; @@ -7,3 +9,5 @@ export interface SessionParams { export type TimingRecords = { item: string; timeMs: number }[]; export type CaipNetworkId = `${string}:${string}`; + +export type SupportedChain = (typeof TEST_CHAINS)[keyof typeof TEST_CHAINS]; diff --git a/apps/native/tests/shared/utils/timeouts.ts b/apps/native/tests/shared/utils/timeouts.ts index a74e5eee..d1d154cb 100644 --- a/apps/native/tests/shared/utils/timeouts.ts +++ b/apps/native/tests/shared/utils/timeouts.ts @@ -1,9 +1,9 @@ -import { MAXIMUM_WAIT_CONNECTIONS } from '../constants/timeouts'; +import { TIMEOUTS } from '../constants'; export function getMaximumWaitConnections(): number { if (process.env.CI) { - return MAXIMUM_WAIT_CONNECTIONS; + return TIMEOUTS.SESSION_PROPOSAL; } - return MAXIMUM_WAIT_CONNECTIONS * 2; + return TIMEOUTS.SESSION_PROPOSAL * 2; } diff --git a/apps/native/tests/wallet.spec.ts b/apps/native/tests/wallet.spec.ts index 75fe6e4f..c1bc69de 100644 --- a/apps/native/tests/wallet.spec.ts +++ b/apps/native/tests/wallet.spec.ts @@ -3,7 +3,7 @@ import { WalletPage } from './shared/pages/WalletPage'; import { WalletValidator } from './shared/validators/WalletValidator'; import { ModalPage } from './shared/pages/ModalPage'; import { ModalValidator } from './shared/validators/ModalValidator'; -import { DEFAULT_CHAIN_NAME } from './shared/constants'; +import { DEFAULT_CHAIN_NAME, TEST_CHAINS } from './shared/constants'; let modalPage: ModalPage; let modalValidator: ModalValidator; @@ -37,21 +37,36 @@ sampleWalletTest.afterAll(async () => { }); // -- Tests -------------------------------------------------------------------- +/** + * Connection Tests + * Tests the basic connection functionality including: + * - Page refresh behavior + * - Network switching + * - Disconnection flows + */ + sampleWalletTest('it should be connected instantly after page refresh', async () => { await modalPage.page.reload(); await modalValidator.expectToBeConnectedInstantly(); }); +/** + * Network Tests + * Tests network-related functionality including: + * - Disabled networks visibility + * - Network switching + * - Network persistence after refresh + */ + sampleWalletTest('it should show disabled networks', async () => { - const disabledNetworks = 'Gnosis'; await modalPage.openAccountModal(); await modalPage.goToNetworks(); - await modalValidator.expectNetworksDisabled(disabledNetworks); + await modalValidator.expectNetworksDisabled(TEST_CHAINS.GNOSIS); await modalPage.closeModal(); }); sampleWalletTest('it should switch networks and sign', async () => { - const chains = ['Polygon', 'Ethereum']; + const chains = [TEST_CHAINS.POLYGON, TEST_CHAINS.ETHEREUM]; async function processChain(index: number) { if (index >= chains.length) { @@ -77,34 +92,45 @@ sampleWalletTest('it should switch networks and sign', async () => { await processChain(index + 1); } - // Start processing from the first chain await processChain(0); }); sampleWalletTest('it should show last connected network after refreshing', async () => { - const chainName = 'Polygon'; - await modalPage.openAccountModal(); await modalPage.goToNetworks(); - await modalPage.switchNetwork(chainName); - await modalValidator.expectSwitchedNetwork(chainName); + await modalPage.switchNetwork(TEST_CHAINS.POLYGON); + await modalValidator.expectSwitchedNetwork(TEST_CHAINS.POLYGON); await modalPage.closeModal(); await modalPage.page.reload(); await modalPage.openAccountModal(); - await modalValidator.expectSwitchedNetwork(chainName); + await modalValidator.expectSwitchedNetwork(TEST_CHAINS.POLYGON); await modalPage.closeModal(); }); +/** + * Signing Tests + * Tests message signing functionality including: + * - Successful signing flow + * - Rejection flow + */ + sampleWalletTest('it should reject sign', async () => { - const chainName = 'Polygon'; await modalPage.sign(); - await walletValidator.expectReceivedSign({ chainName }); + await walletValidator.expectReceivedSign({ chainName: TEST_CHAINS.POLYGON }); await walletPage.handleRequest({ accept: false }); await modalValidator.expectRejectedSign(); }); +/** + * Disconnection Tests + * Tests various disconnection scenarios including: + * - Hook-based disconnection + * - Wallet-initiated disconnection + * - Manual disconnection + */ + sampleWalletTest('it should disconnect using hook', async () => { await modalValidator.expectConnected(); await modalPage.clickHookDisconnectButton(); @@ -129,6 +155,14 @@ sampleWalletTest('it should disconnect as expected', async () => { await modalValidator.expectDisconnected(); }); +/** + * Activity Screen Tests + * Tests the Activity screen behavior including: + * - Loader visibility on first visit + * - Loader behavior on subsequent visits + * - Loader behavior after network changes + */ + sampleWalletTest('shows loader behavior on first visit to Activity screen', async () => { // Connect to wallet await modalPage.qrCodeFlow(modalPage, walletPage); @@ -158,8 +192,8 @@ sampleWalletTest('shows loader behavior after network change in Activity screen' // Change network await modalPage.goToNetworks(); - await modalPage.switchNetwork('Polygon'); - await modalValidator.expectSwitchedNetwork('Polygon'); + await modalPage.switchNetwork(TEST_CHAINS.POLYGON); + await modalValidator.expectSwitchedNetwork(TEST_CHAINS.POLYGON); // Visit Activity screen after network change await modalPage.goToActivity(); From 2ca82f03284d56cb78354989fb866e5603cbb277 Mon Sep 17 00:00:00 2001 From: ignaciosantise <25931366+ignaciosantise@users.noreply.github.com> Date: Fri, 21 Feb 2025 16:02:27 -0300 Subject: [PATCH 12/14] fix: showing loader and placeholder correctly on activity tab --- .../partials/w3m-account-activity/index.tsx | 19 +++++++++++++------ .../partials/w3m-account-activity/styles.ts | 3 ++- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/packages/scaffold/src/partials/w3m-account-activity/index.tsx b/packages/scaffold/src/partials/w3m-account-activity/index.tsx index 5d75547a..3ec7ee05 100644 --- a/packages/scaffold/src/partials/w3m-account-activity/index.tsx +++ b/packages/scaffold/src/partials/w3m-account-activity/index.tsx @@ -1,5 +1,5 @@ -import { useCallback, useEffect, useMemo, useState } from 'react'; import { useSnapshot } from 'valtio'; +import { useCallback, useEffect, useMemo, useState } from 'react'; import { ScrollView, View, type StyleProp, type ViewStyle, RefreshControl } from 'react-native'; import { FlexView, @@ -30,6 +30,7 @@ interface Props { export function AccountActivity({ style }: Props) { const Theme = useTheme(); const [refreshing, setRefreshing] = useState(false); + const [initialLoad, setInitialLoad] = useState(true); const { loading, transactions, next } = useSnapshot(TransactionsController.state); const { caipNetwork } = useSnapshot(NetworkController.state); const networkImage = AssetUtil.getNetworkImage(caipNetwork); @@ -62,9 +63,14 @@ export function AccountActivity({ style }: Props) { if (!TransactionsController.state.transactions.length) { TransactionsController.fetchTransactions(AccountController.state.address, true); } + // Set initial load to false after first fetch + const timer = setTimeout(() => setInitialLoad(false), 100); + + return () => clearTimeout(timer); }, []); - if (loading && !transactions.length) { + // Show loading spinner during initial load or when loading with no transactions + if ((initialLoad || loading) && !transactions.length) { return ( @@ -72,13 +78,14 @@ export function AccountActivity({ style }: Props) { ); } - if (!Object.keys(transactionsByYear).length) { + // Only show placeholder when we're not in initial load or loading state + if (!Object.keys(transactionsByYear).length && !loading && !initialLoad) { return ( ); } @@ -150,14 +157,14 @@ export function AccountActivity({ style }: Props) { ))} ))} - {(next || loading) && ( + {(next || loading) && !refreshing && ( {next && !loading && ( Load more )} - {loading && !refreshing && } + {loading && } )} diff --git a/packages/scaffold/src/partials/w3m-account-activity/styles.ts b/packages/scaffold/src/partials/w3m-account-activity/styles.ts index df9874a4..64c13aab 100644 --- a/packages/scaffold/src/partials/w3m-account-activity/styles.ts +++ b/packages/scaffold/src/partials/w3m-account-activity/styles.ts @@ -18,7 +18,8 @@ export default StyleSheet.create({ height: 40 }, placeholder: { - minHeight: 200 + minHeight: 200, + flex: 0 }, loadMoreButton: { alignSelf: 'center', From 855bd0cf43abb2e2597b849a10a41de155921e9d Mon Sep 17 00:00:00 2001 From: ignaciosantise <25931366+ignaciosantise@users.noreply.github.com> Date: Fri, 21 Feb 2025 16:46:12 -0300 Subject: [PATCH 13/14] chore: add dependabot file --- .github/dependabot.yml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..af9b9608 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,8 @@ +version: 2 +updates: + - package-ecosystem: "npm" + directory: "/" + schedule: + interval: "weekly" + ignore-paths: + - "apps/**" \ No newline at end of file From fe8fd981bd7d864e452b2d4ed9ed213492b654d6 Mon Sep 17 00:00:00 2001 From: ignaciosantise <25931366+ignaciosantise@users.noreply.github.com> Date: Mon, 24 Feb 2025 10:28:02 -0300 Subject: [PATCH 14/14] chore: removed dependabot file --- .github/dependabot.yml | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index af9b9608..00000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,8 +0,0 @@ -version: 2 -updates: - - package-ecosystem: "npm" - directory: "/" - schedule: - interval: "weekly" - ignore-paths: - - "apps/**" \ No newline at end of file