Skip to content

feat: adapter architecture phase 3 — escape hatches, read-only surface, hardening#449

Draft
fernandomg wants to merge 50 commits intofeat/adapter-architecture-phases-1-2from
feat/adapter-architecture-phase-3
Draft

feat: adapter architecture phase 3 — escape hatches, read-only surface, hardening#449
fernandomg wants to merge 50 commits intofeat/adapter-architecture-phases-1-2from
feat/adapter-architecture-phase-3

Conversation

@fernandomg
Copy link
Copy Markdown
Member

@fernandomg fernandomg commented Apr 9, 2026

Description:

Phase 3 of the adapter architecture — completes the escape hatch progression across all SDK surfaces, adds the typed read-only client system, and hardens DbC enforcement and connector decoupling.

Three work tracks in 66 commits:

Escape Hatch Fixes (11 commits)

Restores the five-level escape hatch progression (styled component → hook → raw adapter → explicit adapter → core) across every SDK surface:

  • Transaction L3+L4: useTransaction() now exposes resolveAdapters(chainId) for raw adapter access and accepts explicit transactionAdapter/walletAdapter options to bypass provider resolution
  • Wallet L4: WalletGuard accepts adapter prop (matches ConnectWalletButton)
  • Provider L3: useProviderContext exported from public API for cross-cutting access
  • DbC: Runtime guards on createEvmWalletAdapter and createEvmTransactionAdapter for chains.length >= 1

Read-Only Escape Hatch (7 commits)

Completes the read-only surface from 40% to 100%:

  • Core: ReadClientFactory<TClient> generic interface, evmReadClientFactory concrete implementation, createReadClient() and resolveReadClient() utilities for CLI/agent/backend use
  • React: useReadOnly<TClient>() generic hook with factory bypass option (L4), useEvmReadOnly() typed hook returning PublicClient (L2)
  • Auto-contribute: Wallet bundles include readClientFactory, provider collects them automatically — zero config for apps with adapters

Phase 3 Hardening (6 commits)

Hardens the SDK for Phase 4:

  • DbC enforcement: Runtime guards for transport-per-chain, private key format, coreConnector.createConfig
  • @precondition vs @expects convention: 39 unenforced @precondition annotations relabeled to @expects. Rule: @precondition = enforced at runtime, always. @expects = documented assumption.
  • Connector decoupling: 3 EVM connectors converted from env-coupled singletons to factory functions accepting ConnectorAppMetadata — SDK has zero @/src/env imports
  • Bundle test coverage: createEvmWalletBundle integration tests with real wagmi

Steps:

  1. pnpm install
  2. cp .env.example .env.local and fill in required vars
  3. pnpm dev — verify app runs
  4. pnpm test — 382 SDK tests pass
  5. pnpm lint — clean
  6. pnpm tsc --noEmit — clean

Note: wagmi.config.ts now calls createConnectkitConnector(metadata) instead of using the old singleton. If you had a custom connector import, update to the factory pattern.

Type of change:

  • New feature
  • Bug fix
  • Breaking change
  • Enhancement
  • Refactoring
  • Chore

How Has This Been Tested?

  • Manual testing
  • Automated tests
  • Other (explain)

382 tests across 28 test files. TDD throughout — every feature was red-green-commit. Integration tests use real wagmi with mock connector (no wagmi mocking).

Remember to check that:

  • Your code follows the style guidelines of this project
  • You have performed a self-review of your code
  • You have commented your code in hard-to-understand areas
  • You have made corresponding changes to the documentation
  • Your changes generate no new warnings

Screenshots

N/A — SDK-only changes, no UI modifications.

Extend createNotificationLifecycle with onReplace handler, optional
ChainRegistry for explorer URLs, and shortMessage extraction for viem
errors. Add createSigningNotificationLifecycle factory for wallet signing
toasts. Wire both lifecycle instances in __root.tsx via DAppBoosterProvider
config, removing the legacy TransactionNotificationProvider wrapper.
…based TransactionButton

Migrate MintUSDC, ERC20ApproveAndTransferButton, NativeToken, and
parent TransactionButton demo to use the new adapter-based
TransactionButton with TransactionParams + lifecycle props. Replace
useWeb3StatusConnected with useWallet, WalletStatusVerifier with
WalletGuard, and getExplorerLink with getExplorerUrl.

Optimism cross-domain messenger demo gets a partial migration (keeps
LegacyTransactionButton with local TransactionNotificationProvider
wrapper) since useL1CrossDomainMessengerProxy returns Promise<Hash>
rather than TransactionParams.
Remove 39 files from the old code paths that have been superseded by the
SDK adapter architecture:

- src/hooks/ legacy hooks (useWeb3Status, useWalletStatus, useTokens)
- src/providers/ (Web3Provider, TransactionNotificationProvider)
- src/components/sharedComponents/ duplicates (TransactionButton,
  SignButton, WalletStatusVerifier, SwitchNetwork, NotificationToast,
  TokenSelect, TokenDropdown, TokenInput)
- src/wallet/connectors/*.config.tsx (connectkit, rainbowkit, reown)
- src/wallet/providers/Web3Provider.tsx (dead code after config deletion)

Files kept because they're still used by the Optimism and SignMessage
demos: wallet/hooks/*, wallet/types.ts, wallet/components/WalletStatusVerifier,
transactions/providers/*, transactions/components/LegacyTransactionButton.
…te bundle in react layer

- Core adapter (src/sdk/core/evm/wallet.ts) returns WalletAdapter directly,
  no React imports, no Provider/useConnectModal. Exposes wagmiConfig on return.
- React bundle (src/sdk/react/evm/wallet-bundle.tsx) wraps core adapter with
  WagmiProvider + QueryClientProvider + connector WalletProvider.
- EvmConnectorConfig (React-specific) moved from core/evm/types to react/evm/types.
- Connector files (connectkit, rainbowkit, reown) moved from core to react layer.
- All consumers updated: __root.tsx uses createEvmWalletBundle, wagmi.config.ts
  imports connector from react layer.
- Tests updated: unit + integration tests use EvmCoreConnectorConfig stub,
  new test verifies adapter is returned directly (not as bundle).
…er props

Remove Chakra UI imports from SDK components. WalletGuard now accepts
renderConnect and renderSwitchChain render props (fallback kept but
deprecated). ConnectWalletButton accepts a render prop receiving wallet
state and action callbacks.

Chakra-styled wrappers in src/chakra/ compose the headless components
with styled buttons. Demos and wallet/providers re-export from the
Chakra layer so consumers see no behavioral change.
…or display

Port generic error formatting: extractViemErrorMessage (walks cause chain),
sanitizeErrorMessage (strips hex, addresses, technical blocks), and
formatErrorMessage (maps common patterns like user rejection, insufficient
funds, execution reverted). Wire into lifecycle toasts and transaction
adapter prepare() reason. Replace all inline shortMessage checks.
… (Aave V3)

Aave V3 pool on Sepolia has frozen reserves. Switch all transaction
demos to Base Sepolia where the pool is active. Update USDC token
address, Pool address, and Faucet address to Base Sepolia deployments.
Add baseSepolia to the chain config.
…action

Restores escape hatch levels 3 and 4 for the transaction surface.
resolveAdapters(chainId) gives raw adapter access for one-off
customization. Explicit transactionAdapter/walletAdapter options
bypass provider resolution entirely.
useReadOnly<TClient> now accepts an optional `factory` prop that
bypasses provider-level readClientFactories resolution (Level 4
escape hatch). Default generic stays `unknown` for backward compat.
@vercel
Copy link
Copy Markdown

vercel bot commented Apr 9, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
components.dappbooster Ready Ready Preview, Comment Apr 9, 2026 8:09pm
demo.dappbooster Ready Ready Preview, Comment Apr 9, 2026 8:09pm
docs.dappbooster Ready Ready Preview, Comment Apr 9, 2026 8:09pm

Request Review

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Phase 3 of the adapter architecture: completes escape-hatch coverage, introduces a typed read-only client surface (core + React), decouples EVM connectors from app env via connector factories, and hardens runtime DbC/guards while migrating the app away from legacy wallet hooks/providers.

Changes:

  • Added typed read-only client factories/utilities (core + React hooks) and auto-contribution via wallet bundles.
  • Refactored EVM connector integration to factory pattern + introduced createEvmWalletBundle React wrapper; removed legacy wallet/provider surfaces.
  • Hardened runtime guards and error/lifecycle handling (new error formatting, notification lifecycles, prepare signer support).

Reviewed changes

Copilot reviewed 159 out of 159 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/wallet/types.ts Removed legacy re-exported wallet types.
src/wallet/providers/Web3Provider.tsx Removed legacy Web3Provider wrapper.
src/wallet/providers.ts Repointed ConnectWalletButton export to Chakra wrapper.
src/wallet/hooks/useWeb3Status.tsx Removed legacy wagmi-based status hook.
src/wallet/hooks/useWalletStatus.ts Removed legacy wallet readiness hook.
src/wallet/hooks/useWalletStatus.test.ts Removed tests for legacy hook.
src/wallet/hooks.ts Removed barrel exports for legacy hooks.
src/wallet/connectors/wagmi.config.ts Switched to connector factory call with metadata.
src/wallet/connectors/reown.config.tsx Removed legacy connector config file.
src/wallet/connectors/rainbowkit.config.tsx Removed legacy connector config file.
src/wallet/connectors/connectkit.config.tsx Removed legacy connector config file.
src/wallet/components/WalletStatusVerifier.tsx Removed legacy WalletStatusVerifier wrapper.
src/wallet/components/SwitchNetwork.tsx Migrated to SDK wallet status + wagmi walletClient.
src/wallet/components.ts Removed exports for deleted verifier.
src/utils/getExplorerLink.ts Changed invalid input behavior to return null.
src/utils/getExplorerLink.test.ts Updated tests for null-on-invalid behavior.
src/transactions/providers/TransactionNotificationProvider.test.tsx Removed legacy notification provider tests.
src/transactions/providers.ts Removed legacy provider barrel exports.
src/transactions/components/TransactionButton.test.tsx Updated mocks for new useTransaction return shape.
src/transactions/components/LegacyTransactionButton.tsx Removed wagmi-hook-based legacy transaction button.
src/transactions/components.ts Removed legacy TransactionButton export.
src/tokens/hooks/useTokens.ts Migrated from legacy wallet hooks to SDK useWallet.
src/tokens/hooks/useTokens.migration.test.ts Added “no legacy import” migration assertion.
src/tokens/components/TokenSelect/TokenSelect.migration.test.ts Added migration assertions for TokenSelect.
src/tokens/components/TokenSelect/List/AddERC20TokenButton.tsx Migrated to SDK useWallet + wagmi useWalletClient.
src/tokens/components/TokenSelect/List/AddERC20TokenButton.migration.test.ts Added migration assertions for AddERC20TokenButton.
src/tokens/components/TokenSelect/index.tsx Migrated chain/account sourcing to SDK registry + wallet.
src/sdk/react/provider/index.ts Exported useProviderContext from provider barrel.
src/sdk/react/provider/DAppBoosterProvider.tsx Auto-collected/deduped read client factories from bundles.
src/sdk/react/provider/DAppBoosterProvider.test.tsx Added tests for auto-contributed readClientFactories behavior.
src/sdk/react/provider/context.ts Tightened readClientFactories typing to unknown generic.
src/sdk/react/provider/context.test.tsx Added test coverage for provider barrel export + context behavior.
src/sdk/react/lifecycle/index.ts Exported signing notification lifecycle types + factory.
src/sdk/react/lifecycle/createNotificationLifecycle.ts Added explorer URL suffixing, replace handling, and signing lifecycle.
src/sdk/react/internal/walletLifecycle.ts Centralized lifecycle dispatch + wrapping for wallet signing.
src/sdk/react/index.ts Exported new evm surface from react package.
src/sdk/react/hooks/useWallet.ts Switched to shared wallet lifecycle wrapper; doc label updates.
src/sdk/react/hooks/useReadOnly.ts Added generic typed client + address + explorer URL support + factory bypass.
src/sdk/react/hooks/useMultiWallet.ts Expanded return to include helpers + connectedAddresses; refactored lifecycle wrapping.
src/sdk/react/hooks/index.ts Re-exported additional transaction-related types.
src/sdk/react/evm/wallet-bundle.tsx Added React wallet bundle factory (wagmi + query + connector provider stack).
src/sdk/react/evm/wallet-bundle.test.tsx Added integration-style tests for bundle composition and guards.
src/sdk/react/evm/types.ts Added app metadata and React connector config types.
src/sdk/react/evm/read-only.ts Added typed useEvmReadOnly hook using EVM read client factory.
src/sdk/react/evm/read-only.test.tsx Added tests for typed EVM read-only hook behavior.
src/sdk/react/evm/index.ts New EVM React barrel exports (connectors, hooks, bundle).
src/sdk/react/evm/connectors/reown.tsx Added Reown connector factory taking app metadata.
src/sdk/react/evm/connectors/rainbowkit.tsx Added RainbowKit connector factory taking app metadata.
src/sdk/react/evm/connectors/index.ts Added connector factory barrel.
src/sdk/react/evm/connectors/connectors.test.ts Added factory connector smoke tests.
src/sdk/react/evm/connectors/connectkit.tsx Added ConnectKit connector factory taking app metadata.
src/sdk/react/components/index.ts Exported ConnectWalletButton render-props type; expanded WalletGuard types.
src/sdk/react/components/ConnectWalletButton.tsx Converted ConnectWalletButton to headless render-prop component.
src/sdk/react/components/ConnectWalletButton.test.tsx Added tests for headless ConnectWalletButton render contract.
src/sdk/core/utils/wrap-adapter.ts Added transform hooks (beforeCall/afterCall) and updated ordering semantics.
src/sdk/core/utils/wrap-adapter.test.ts Added coverage for transform hooks and execution order.
src/sdk/core/utils/index.ts Exported WrapAdapterHooks type.
src/sdk/core/read-client.ts Added core non-React read client helpers (typed + resolver).
src/sdk/core/read-client.test.ts Added tests for new read client utilities.
src/sdk/core/index.ts Exported core read-client utilities from SDK core index.
src/sdk/core/evm/wallet.ts Removed React/provider concerns; returns adapter + wagmiConfig; added runtime guards.
src/sdk/core/evm/wallet.integration.test.ts Updated integration tests for new wallet adapter return type/config.
src/sdk/core/evm/types.ts Removed React connector config from core types (React types moved to react layer).
src/sdk/core/evm/transaction.ts Added runtime guards, signer-aware prepare, and formatted error reasons.
src/sdk/core/evm/transaction.test.ts Added tests for new guards and updated prepare behavior.
src/sdk/core/evm/server-wallet.ts Added private key runtime validation; doc label update.
src/sdk/core/evm/server-wallet.test.ts Added tests for private key validation.
src/sdk/core/evm/read-client.ts Added EVM read client factory implementation.
src/sdk/core/evm/read-client.test.ts Added tests for EVM read client factory.
src/sdk/core/evm/index.ts Exported EVM read client factory and updated wallet exports.
src/sdk/core/evm/connectors/reown.tsx Removed env-coupled singleton connector.
src/sdk/core/evm/connectors/rainbowkit.tsx Removed env-coupled singleton connector.
src/sdk/core/evm/connectors/index.ts Removed core connector barrel.
src/sdk/core/evm/connectors/connectors.test.ts Removed singleton connector tests.
src/sdk/core/evm/connectors/connectkit.tsx Removed env-coupled singleton connector.
src/sdk/core/errors/index.ts Re-exported new error formatting utilities.
src/sdk/core/errors/format.ts Added user-friendly error formatting/sanitization utilities.
src/sdk/core/errors/format.test.ts Added tests for error formatting helpers.
src/sdk/core/chain/explorer.ts Updated JSDoc annotations to @expects.
src/sdk/core/adapters/transaction.ts Updated adapter interface: prepare(params, signer?).
src/sdk/core/adapters/provider.ts Added readClientFactory to bundles; made ReadClientFactory generic.
src/sdk/core/adapters/index.test.ts Updated type-level tests for generic ReadClientFactory.
src/routes/__root.tsx Migrated app shell to wallet bundle + global lifecycles; removed legacy notification provider.
src/providers/Web3Provider.tsx Removed duplicate legacy Web3Provider.
src/main.tsx Added BigInt JSON serialization polyfill for React 19 dev tooling.
src/hooks/useWeb3Status.tsx Removed legacy app-level wallet status hook.
src/hooks/useWeb3Status.test.ts Removed tests for legacy hook.
src/hooks/useWalletStatus.ts Removed legacy app-level wallet status wrapper.
src/hooks/useWalletStatus.test.ts Removed tests for legacy wrapper.
src/core/utils/getExplorerLink.ts Changed invalid input behavior to return null (core copy).
src/core/ui/NotificationToast.tsx Removed wallet status gating; toast always mounts.
src/core/ui/ExplorerLink.tsx Added null fallback handling (currently '#').
src/core/config/networks.config.ts Added Base Sepolia chain + transport config.
src/contracts/definitions.ts Added Base Sepolia AaveFaucet address and keying via chain IDs.
src/components/sharedComponents/WalletStatusVerifier.tsx Removed legacy verifier component.
src/components/sharedComponents/WalletStatusVerifier.test.tsx Removed tests for legacy verifier component.
src/components/sharedComponents/TransactionButton.tsx Removed legacy shared TransactionButton wrapper.
src/components/sharedComponents/TokenSelect/utils.tsx Removed legacy TokenSelect utilities.
src/components/sharedComponents/TokenSelect/types.ts Removed legacy Networks type.
src/components/sharedComponents/TokenSelect/TopTokens/Item.tsx Removed legacy TopTokens item.
src/components/sharedComponents/TokenSelect/TopTokens/index.tsx Removed legacy TopTokens component.
src/components/sharedComponents/TokenSelect/styles.ts Removed legacy TokenSelect styles.
src/components/sharedComponents/TokenSelect/Search/NetworkButton.tsx Removed legacy TokenSelect search UI.
src/components/sharedComponents/TokenSelect/Search/Input.tsx Removed legacy TokenSelect search UI.
src/components/sharedComponents/TokenSelect/Search/index.tsx Removed legacy TokenSelect search UI.
src/components/sharedComponents/TokenSelect/List/VirtualizedList.tsx Removed legacy virtualized list.
src/components/sharedComponents/TokenSelect/List/TokenBalance.tsx Removed legacy balance display component.
src/components/sharedComponents/TokenSelect/List/Row.tsx Removed legacy token row component.
src/components/sharedComponents/TokenSelect/List/index.tsx Removed legacy token list component.
src/components/sharedComponents/TokenSelect/List/AddERC20TokenButton.tsx Removed legacy add-token button (sharedComponents copy).
src/components/sharedComponents/TokenInput/useTokenInput.tsx Removed legacy token input hook.
src/components/sharedComponents/TokenInput/styles.ts Removed legacy token input styles.
src/components/sharedComponents/TokenDropdown.tsx Removed legacy token dropdown component.
src/components/sharedComponents/SwitchNetwork.tsx Removed legacy SwitchNetwork component.
src/components/sharedComponents/SwitchNetwork.test.tsx Removed legacy SwitchNetwork tests.
src/components/sharedComponents/SignButton.tsx Removed legacy sign button component.
src/components/sharedComponents/NotificationToast.tsx Removed legacy NotificationToast component.
src/components/sharedComponents/ExplorerLink.tsx Added null fallback handling (currently '#').
src/components/pageComponents/home/Examples/demos/TransactionButton/NativeToken.tsx Migrated demo to adapter-based TransactionButton on Base Sepolia.
src/components/pageComponents/home/Examples/demos/TransactionButton/index.tsx Replaced legacy verifier with Chakra WalletGuard.
src/components/pageComponents/home/Examples/demos/TransactionButton/index.test.tsx Updated mocks for WalletGuard.
src/components/pageComponents/home/Examples/demos/TransactionButton/ERC20ApproveAndTransferButton/MintUSDC.tsx Migrated mint flow to adapter TransactionButton params.
src/components/pageComponents/home/Examples/demos/TransactionButton/ERC20ApproveAndTransferButton/index.tsx Migrated demo to Base Sepolia + adapter params.
src/components/pageComponents/home/Examples/demos/TransactionButton/ERC20ApproveAndTransferButton/ERC20ApproveAndTransferButton.tsx Migrated approve/transfer flow to adapter TransactionButton + SDK explorer URLs.
src/components/pageComponents/home/Examples/demos/TokenInput/index.tsx Migrated wallet connection check to SDK useWallet.
src/components/pageComponents/home/Examples/demos/TokenInput/index.test.tsx Updated wallet mocks to SDK hook.
src/components/pageComponents/home/Examples/demos/SwitchNetwork/index.tsx Migrated to SDK useWallet and updated Networks typing import.
src/components/pageComponents/home/Examples/demos/SwitchNetwork/index.test.tsx Updated mocks to SDK useWallet.
src/components/pageComponents/home/Examples/demos/SignMessage/index.tsx Replaced legacy verifier with Chakra WalletGuard.
src/components/pageComponents/home/Examples/demos/SignMessage/index.test.tsx Updated mocks to SDK hooks + WalletGuard.
src/components/pageComponents/home/Examples/demos/OptimismCrossDomainMessenger/index.tsx Refactored demo to adapter transaction execution + error formatting + SDK explorer URLs.
src/components/pageComponents/home/Examples/demos/HashHandling/index.tsx Migrated wallet state reads to SDK useWallet.
src/components/pageComponents/home/Examples/demos/HashHandling/index.test.tsx Updated mocks to SDK useWallet.
src/components/pageComponents/home/Examples/demos/HashHandling/Hash.tsx Updated explorer URL handling for nullable links.
src/components/pageComponents/home/Examples/demos/EnsName/index.tsx Adjusted ENS error rendering message.
src/chakra/WalletGuard.tsx Added Chakra-styled wrapper around headless WalletGuard.
src/chakra/index.ts Added Chakra barrel exports.
src/chakra/ConnectWalletButton.tsx Added Chakra-styled wrapper around headless ConnectWalletButton.
CLAUDE.md Documented @precondition vs @expects enforcement convention.
Comments suppressed due to low confidence (1)

src/core/utils/getExplorerLink.ts:54

  • This helper now returns null for invalid inputs, but it can still produce URLs like "undefined/address/..." when neither explorerUrl nor chain.blockExplorers?.default.url is set. That contradicts the JSDoc and will generate broken links. Consider computing a baseUrl first and either throwing (as the docs imply) or returning null when no explorer URL is available.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +8 to 10
* Transform hooks (`beforeCall`, `afterCall`) propagate errors and can modify args/results.
* Returning `void` from a transform hook passes the original value through.
*/
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docstring says transform hooks can return void for pass-through, but beforeCall/afterCall are typed to return values and the implementation uses the return value directly. If a hook accidentally returns undefined (e.g. JS consumer or any), effectiveArgs becomes undefined and .apply() will throw. Either update the docs to require returning the original value, or harden the implementation to fall back to the original args/result when the transform hook returns undefined (and consider loosening the types to unknown[] | void / unknown | void to match behavior).

Copilot uses AI. Check for mistakes.
Comment on lines +5 to +10
// BigInt is not serializable by JSON.stringify. React 19 dev mode tries to serialize
// component props for dev tools logging, which crashes when props contain BigInt values
// (e.g., TransactionParams with value: parseEther('0.1')). This polyfill prevents the crash.
;(BigInt.prototype as unknown as { toJSON: () => string }).toJSON = function () {
return this.toString()
}
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This mutates BigInt.prototype.toJSON unconditionally and creates an enumerable property, which can have unexpected side-effects (and may conflict with other polyfills). Consider guarding it (only define if missing) and using Object.defineProperty to add a non-enumerable toJSON, and/or restricting it to dev-only environments.

Copilot uses AI. Check for mistakes.
Comment on lines 36 to 40
<chakra.a
href={getExplorerLink(props)}
href={getExplorerLink(props) ?? '#'}
rel="noopener noreferrer"
target="_blank"
>
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When getExplorerLink returns null, falling back to href="#" while still using target="_blank" creates a broken link that opens a blank tab and is confusing for keyboard/screen-reader users. Prefer conditionally rendering nothing / a <span> when the URL is missing, or disable the link semantics (no href, aria-disabled, and prevent default).

Copilot uses AI. Check for mistakes.
Comment on lines 36 to 40
<chakra.a
href={getExplorerLink(props)}
href={getExplorerLink(props) ?? '#'}
rel="noopener noreferrer"
target="_blank"
>
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When getExplorerLink returns null, falling back to href="#" while still using target="_blank" creates a broken link that opens a blank tab and is confusing for keyboard/screen-reader users. Prefer conditionally rendering nothing / a <span> when the URL is missing, or disable the link semantics (no href, aria-disabled, and prevent default).

Copilot uses AI. Check for mistakes.
Comment on lines 46 to 61
export const getExplorerLink = ({ chain, explorerUrl, hashOrAddress }: GetExplorerUrlParams) => {
const baseUrl = explorerUrl ?? chain.blockExplorers?.default.url

if (!baseUrl) {
throw new Error('No block explorer URL available for this chain')
}

if (isAddress(hashOrAddress)) {
return `${baseUrl}/address/${hashOrAddress}`
}
if (isHash(hashOrAddress)) {
return `${baseUrl}/tx/${hashOrAddress}`
}

throw new Error('Invalid hash or address')
return null
}
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The JSDoc still says this function throws when the hash/address is invalid, but it now returns null in that case. Please update the documentation to match the new behavior (throws only when no explorer URL is available).

Copilot uses AI. Check for mistakes.
Comment on lines +14 to 26
interface ConnectWalletButtonProps extends UseWalletOptions {
render: (props: ConnectWalletButtonRenderProps) => ReactElement
}

/**
* Styled connect/account button that works with any connector.
* Headless connect/account button that works with any connector.
*
* Resolves the wallet adapter via `useWallet(options)` and opens the
* adapter-specific connect modal. In a multi-wallet setup, pass `chainType`
* Resolves the wallet adapter via `useWallet(options)` and delegates all
* rendering to the `render` prop. In a multi-wallet setup, pass `chainType`
* or `chainId` to target a specific adapter's modal.
*/
export const ConnectWalletButton: FC<UseWalletOptions & { label?: string }> = ({
label = 'Connect',
...walletOptions
}) => {
export const ConnectWalletButton: FC<ConnectWalletButtonProps> = ({ render, ...walletOptions }) => {
const { status, openConnectModal, openAccountModal } = useWallet(walletOptions)
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ConnectWalletButton is exported from the public @/src/sdk/react surface, but its props changed from an optional label to a required render prop. That is a breaking API change for existing consumers importing the SDK component directly. If this is intentional, it should be called out as breaking (and/or provide a backward-compatible overload/default render).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants