Skip to content

Conversation

@montycheese
Copy link

@montycheese montycheese commented Jan 14, 2026

  • Add @base-org/account 2.5.0 dependency
    • Implement Base Account SDK wallet connector
    • Add base-account-web.ts with EIP-1193 provider implementation
    • Add base-account-wallet.ts with core wallet logic
    • Export types and helper functions
    • Maintain backwards compatibility with coinbase/wallet-sdk

PR-Codex overview

This PR introduces support for the Base Account SDK within the thirdweb wallet integration, enhancing wallet creation and connection functionalities.

Detailed summary

  • Added BASE_ACCOUNT constant in constants.ts.
  • Integrated BaseAccountSDKWalletConnectionOptions and BaseAccountWalletCreationOptions types.
  • Implemented baseAccountWalletSDK function for wallet connection.
  • Updated wallet creation documentation to include Base Account SDK.
  • Added tests for Base Account SDK functionalities.

The following files were skipped due to too many changes: pnpm-lock.yaml

✨ Ask PR-Codex anything about this PR by commenting with /codex {your question}

Summary by CodeRabbit

  • New Features
    • Added Base Account SDK wallet support to the SDK, enabling users to create and connect Base Account wallets.
    • Support for transaction signing, message signing, and typed data signing.
    • Added chain switching and EIP-5792 multi-call operations for Base Account wallets.
    • New wallet type available through the standard wallet creation interface.

✏️ Tip: You can customize this high-level summary in your review settings.

@changeset-bot
Copy link

changeset-bot bot commented Jan 14, 2026

⚠️ No Changeset found

Latest commit: 47438c6

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel
Copy link

vercel bot commented Jan 14, 2026

@montycheese is attempting to deploy a commit to the thirdweb Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 14, 2026

Walkthrough

This pull request integrates Base Account SDK wallet support into the Thirdweb SDK. Changes include adding the @base-org/account dependency, introducing a new BASE_ACCOUNT wallet type constant, implementing complete provider management with signing and transaction functionality, defining connection and creation options types, and integrating the new wallet into the wallet creation factory with corresponding public API exports and comprehensive test coverage.

Changes

Cohort / File(s) Summary
Dependency Management
packages/thirdweb/package.json
Added @base-org/account v2.5.0 as a direct dependency
Wallet Type Constants
packages/thirdweb/src/wallets/constants.ts
Introduced BASE_ACCOUNT constant with value "org.base.account"
Type System Extensions
packages/thirdweb/src/wallets/wallet-types.ts
Updated WalletId union and added conditional type branches for BASE_ACCOUNT in WalletConnectionOption, WalletAutoConnectionOption, and WalletCreationOptions; added imports for BaseAccountSDKWalletConnectionOptions and BaseAccountWalletCreationOptions
Core Base Account Implementation
packages/thirdweb/src/wallets/base-account/base-account-web.ts
Implemented provider management, type guards, account/wallet construction with transaction and signing support (personal_sign, eth_signTypedData_v4, EIP-5792), connection lifecycle management (connect, autoConnect, switchChain), and event subscriptions
Base Account Wallet Factory
packages/thirdweb/src/wallets/base-account/base-account-wallet.ts
Created baseAccountWalletSDK factory function that initializes Wallet instance with lifecycle methods (autoConnect, connect, disconnect, switchChain) and event subscriptions
Wallet Creation Integration
packages/thirdweb/src/wallets/create-wallet.ts
Added BASE_ACCOUNT case to createWallet switch statement using baseAccountWalletSDK with providerFactory; updated JSDoc with Base Account SDK usage example
Public API Exports
packages/thirdweb/src/exports/wallets.ts
Re-exported BaseAccountSDKWalletConnectionOptions, BaseAccountWalletCreationOptions types and isBaseAccountSDKWallet function from base-account-web module
Test Coverage
packages/thirdweb/src/wallets/base-account/base-account-web.test.ts
Added comprehensive test suite covering provider initialization, wallet type checking, connection flows (standard and auto-connect), message signing (personal_sign), typed data signing (eth_signTypedData_v4), and event handling

Sequence Diagrams

sequenceDiagram
    participant App as Application
    participant Wallet as Base Account Wallet
    participant Provider as Base Account SDK Provider
    participant Chain as Chain Service

    App->>Wallet: createWallet(BASE_ACCOUNT)
    Wallet->>Wallet: baseAccountWalletSDK(providerFactory)
    
    App->>Wallet: connect(options)
    Wallet->>Provider: getBaseAccountWebProvider()
    Provider-->>Wallet: ProviderInterface (cached)
    Wallet->>Provider: eth_requestAccounts()
    Provider-->>Wallet: [account_address]
    Wallet->>Provider: eth_chainId()
    Provider-->>Wallet: chain_id
    Wallet->>Chain: getCachedChainIfExists()
    Chain-->>Wallet: Chain metadata
    Wallet->>Wallet: emit accountsChanged
    Wallet->>Wallet: emit chainChanged
    Wallet-->>App: {account, chain, switchChain}
Loading
sequenceDiagram
    participant App as Application
    participant Wallet as Base Account Wallet
    participant Provider as Base Account SDK Provider
    participant Signer as Signing Service

    App->>Wallet: signMessage("hello")
    Wallet->>Signer: Hex.fromString("hello")
    Signer-->>Wallet: formatted_message
    Wallet->>Provider: personal_sign(formatted_message, account)
    Provider-->>Wallet: signature_hex
    Wallet->>Signer: Hex.validate(signature_hex)
    Signer-->>Wallet: is_valid
    Wallet-->>App: signature

    App->>Wallet: sendTransaction({to, data, value})
    Wallet->>Provider: eth_sendTransaction()
    Provider-->>Wallet: tx_hash
    Wallet-->>App: tx_hash
Loading
sequenceDiagram
    participant App as Application
    participant Wallet as Base Account Wallet
    participant Provider as Base Account SDK Provider
    participant Chain as Chain Service

    App->>Wallet: switchChain(chain)
    Wallet->>Provider: wallet_switchEthereumChain({chainId})
    alt Chain already exists
        Provider-->>Wallet: success
    else Chain not found (4902)
        Provider-->>Wallet: 4902 error
        Wallet->>Provider: wallet_addEthereumChain(chainConfig)
        Provider-->>Wallet: success
    end
    Wallet->>Wallet: emit chainChanged
    Wallet-->>App: switched
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description provides a bullet-point summary of changes and implementation details but deviates from the template structure (missing formatted title, issue tag, notes, and test instructions). Follow the repository template: format the title as '[SDK] Feature: ...', include issue tag (TEAM-0000 format), add explicit 'Notes for the reviewer' section, and document testing approach (unit tests location, etc.).
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add base account sdk' is concise and directly related to the main change—adding Base Account SDK support to the wallet integration.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (2)
  • EIP-1193: Entity not found: Issue - Could not find referenced Issue.
  • TEAM-0000: Entity not found: Issue - Could not find referenced Issue.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added packages SDK Involves changes to the thirdweb SDK labels Jan 14, 2026
@socket-security
Copy link

socket-security bot commented Jan 14, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​base-org/​account@​2.5.09910010098100

View full report

      - Add @base-org/account 2.5.0 dependency
      - Implement Base Account SDK wallet connector
      - Add base-account-web.ts with EIP-1193 provider implementation
      - Add base-account-wallet.ts with core wallet logic
      - Export types and helper functions
      - Maintain backwards compatibility with coinbase/wallet-sdk
@joaquim-verges joaquim-verges marked this pull request as ready for review January 16, 2026 01:23
@joaquim-verges joaquim-verges requested review from a team as code owners January 16, 2026 01:23
@joaquim-verges
Copy link
Member

joaquim-verges commented Jan 16, 2026

ty @montycheese ! can you add a changeset ?

pnpm changeset from the root of the repo, select thirdweb, enter to skip and make it a minor

also you can run pnpm fix / lint for linting issues

@vercel
Copy link

vercel bot commented Jan 16, 2026

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

Project Deployment Review Updated (UTC)
thirdweb_playground Ready Ready Preview, Comment Jan 16, 2026 1:31am

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Fix all issues with AI agents
In `@packages/thirdweb/package.json`:
- Line 14: Update package.json to include a size-limit configuration array and
add an entry tracking the new `@base-org/account` dependency (identify the package
by its name "@base-org/account" and include a descriptive label in the
size-limit entry), and change the dependency version to the latest patch (2.5.1)
instead of 2.5.0; ensure the size-limit array follows the existing project
format and includes the package path or import target used by the build so
bundle budgets are enforced for `@base-org/account`.

In `@packages/thirdweb/src/wallets/base-account/base-account-wallet.ts`:
- Around line 44-52: The accountChanged subscription is never cleaned up which
can leak on repeated connects; capture its unsubscribe function (e.g., const
unsubscribeAccountChanged = emitter.subscribe("accountChanged", ...)) and call
unsubscribeAccountChanged() inside the disconnect handler alongside
unsubscribeChainChanged() and unsubscribeDisconnect() (and any other teardown
paths) so all three subscriptions are properly unsubscribed when the wallet
disconnects; update references in base-account-wallet.ts to use
unsubscribeAccountChanged where accountChanged is subscribed.

In `@packages/thirdweb/src/wallets/base-account/base-account-web.ts`:
- Around line 442-462: The catch block around the wallet_switchEthereumChain
flow swallows all errors except when error.code === 4902; update the catch in
base-account-web.ts to re-throw any error that is not the "chain not added" case
so callers get notified of failures (e.g., user rejection 4001). Specifically,
inside the catch handling for wallet_switchEthereumChain, keep the existing
handling that calls getChainMetadata and provider.request for the 4902 case but
after that if the caught error's code !== 4902 throw the original error
(preserve the error object) so failures from provider.request or
wallet_switchEthereumChain propagate to callers.
- Around line 150-178: The sendTransaction method builds the eth_sendTransaction
params but omits EIP-1559 gas fields; inside sendTransaction (the
provider.request call that constructs the tx object) include tx.gasPrice,
tx.maxFeePerGas, and tx.maxPriorityFeePerGas when present (convert numeric
values to hex with numberToHex like gas is handled) so the provider receives
explicit gas pricing; keep getAddress(address), accessList, data, to, value
handling unchanged and continue passing gasPrice through to trackTransaction as
before.

In `@packages/thirdweb/src/wallets/create-wallet.ts`:
- Around line 128-141: The example in createWallet's usage shows a non-existent
option `testnet: false`; update the example to remove `testnet` and demonstrate
using the supported `chains` option from BaseAccountWalletCreationOptions (see
base-account-web.ts) instead — e.g., replace `testnet` with an appropriate
`chains` array or comment explaining how to select testnet chains when calling
createWallet("org.base.account", { appMetadata, chains }) so the example matches
the actual createWallet/BaseAccountWalletCreationOptions API.
🧹 Nitpick comments (4)
packages/thirdweb/src/wallets/base-account/base-account-web.test.ts (1)

124-177: Sign tests validate mocked patterns rather than actual implementation.

These tests define local account objects with signMessage and signTypedData implementations that mimic the expected behavior, then verify those local implementations. This approach validates that ox/Hex and ox/TypedData usage patterns work correctly, but doesn't exercise the actual createAccount function from base-account-web.ts.

Consider refactoring to test the real implementation by:

  1. Exposing createAccount for testing, or
  2. Testing through connectBaseAccountSDK which returns the real account object
Example approach using connectBaseAccountSDK
test("signMessage works through connected account", async () => {
  provider.request = vi
    .fn()
    .mockResolvedValueOnce(["0x123"]) // eth_requestAccounts
    .mockResolvedValueOnce("0x1")     // eth_chainId
    .mockResolvedValue("0xsignature"); // personal_sign
  
  const emitter = { emit: vi.fn() };
  const options = { client: {} };

  const [account] = await connectBaseAccountSDK(
    options as any,
    emitter as any,
    provider,
  );

  const signature = await account.signMessage({ message: "hello" });
  expect(signature).toBe("0xsignature");
});
packages/thirdweb/src/wallets/base-account/base-account-web.ts (2)

179-202: Redundant address check in signMessage.

The check at lines 180-182 verifies account.address, but this property is set on line 149 during account creation and cannot be undefined. This check is defensive but unnecessary. The same applies to signTypedData (lines 204-206).


100-125: The singleton pattern is intentional and acceptable by design.

The module-level _provider singleton is not a bug. Each createWallet() call creates a new wallet instance with its own providerFactory closure that captures the specific options. The options are established at wallet instantiation time, not provided on subsequent calls. The singleton is reused only within the same wallet instance to maintain connection state.

This design is intentional and consistent with other wallet implementations (Coinbase). Consider adding a more explicit explanatory comment to match what coinbase-web.ts provides: "this should be ok since all the creation options are provided at build time."

packages/thirdweb/src/wallets/wallet-types.ts (1)

96-111: LGTM!

The type branching for WalletConnectionOption correctly routes BASE_ACCOUNT to BaseAccountSDKWalletConnectionOptions.

Nit: Line 99 has a typo "inhected" → "injected".

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 621f187 and 47438c6.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (8)
  • packages/thirdweb/package.json
  • packages/thirdweb/src/exports/wallets.ts
  • packages/thirdweb/src/wallets/base-account/base-account-wallet.ts
  • packages/thirdweb/src/wallets/base-account/base-account-web.test.ts
  • packages/thirdweb/src/wallets/base-account/base-account-web.ts
  • packages/thirdweb/src/wallets/constants.ts
  • packages/thirdweb/src/wallets/create-wallet.ts
  • packages/thirdweb/src/wallets/wallet-types.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each TypeScript file to one stateless, single-responsibility function for clarity
Re-use shared types from @/types or local types.ts barrels
Prefer type aliases over interface except for nominal shapes in TypeScript
Avoid any and unknown in TypeScript unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial, Pick, etc.) in TypeScript

**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity and testability
Re-use shared types from @/types or local types.ts barrel exports
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics whenever possible
Choose composition over inheritance; leverage utility types (Partial, Pick, etc.)
Comment only ambiguous logic in TypeScript files; avoid restating TypeScript types and signatures in prose

Files:

  • packages/thirdweb/src/exports/wallets.ts
  • packages/thirdweb/src/wallets/base-account/base-account-wallet.ts
  • packages/thirdweb/src/wallets/wallet-types.ts
  • packages/thirdweb/src/wallets/base-account/base-account-web.ts
  • packages/thirdweb/src/wallets/constants.ts
  • packages/thirdweb/src/wallets/base-account/base-account-web.test.ts
  • packages/thirdweb/src/wallets/create-wallet.ts
packages/thirdweb/src/exports/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

packages/thirdweb/src/exports/**/*.{ts,tsx}: Export everything via exports/ directory, grouped by feature in SDK development
Every public symbol must have comprehensive TSDoc with at least one @example block that compiles and custom annotation tags (@beta, @internal, @experimental)

Export everything in packages/thirdweb via the exports/ directory, grouped by feature. Every public symbol must have comprehensive TSDoc including at least one @example block that compiles and one custom annotation (@beta, @internal, @experimental, etc.)

Files:

  • packages/thirdweb/src/exports/wallets.ts
packages/thirdweb/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

packages/thirdweb/src/**/*.{ts,tsx}: Comment only ambiguous logic in SDK code; avoid restating TypeScript in prose
Load heavy dependencies inside async paths to keep initial bundle lean (e.g. const { jsPDF } = await import("jspdf");)

Lazy-load heavy dependencies inside async paths to keep the initial bundle lean (e.g., const { jsPDF } = await import('jspdf');)

Files:

  • packages/thirdweb/src/exports/wallets.ts
  • packages/thirdweb/src/wallets/base-account/base-account-wallet.ts
  • packages/thirdweb/src/wallets/wallet-types.ts
  • packages/thirdweb/src/wallets/base-account/base-account-web.ts
  • packages/thirdweb/src/wallets/constants.ts
  • packages/thirdweb/src/wallets/base-account/base-account-web.test.ts
  • packages/thirdweb/src/wallets/create-wallet.ts
**/*.{js,jsx,ts,tsx,json}

📄 CodeRabbit inference engine (AGENTS.md)

Biome governs formatting and linting; its rules live in biome.json. Run pnpm fix & pnpm lint before committing, ensure there are no linting errors

Files:

  • packages/thirdweb/src/exports/wallets.ts
  • packages/thirdweb/src/wallets/base-account/base-account-wallet.ts
  • packages/thirdweb/src/wallets/wallet-types.ts
  • packages/thirdweb/src/wallets/base-account/base-account-web.ts
  • packages/thirdweb/package.json
  • packages/thirdweb/src/wallets/constants.ts
  • packages/thirdweb/src/wallets/base-account/base-account-web.test.ts
  • packages/thirdweb/src/wallets/create-wallet.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Lazy-import optional features; avoid top-level side-effects

Files:

  • packages/thirdweb/src/exports/wallets.ts
  • packages/thirdweb/src/wallets/base-account/base-account-wallet.ts
  • packages/thirdweb/src/wallets/wallet-types.ts
  • packages/thirdweb/src/wallets/base-account/base-account-web.ts
  • packages/thirdweb/src/wallets/constants.ts
  • packages/thirdweb/src/wallets/base-account/base-account-web.test.ts
  • packages/thirdweb/src/wallets/create-wallet.ts
packages/thirdweb/package.json

📄 CodeRabbit inference engine (CLAUDE.md)

Track bundle budgets via package.json#size-limit

Files:

  • packages/thirdweb/package.json
**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.test.{ts,tsx}: Place tests alongside code: foo.tsfoo.test.ts in the same directory
Use real function invocations with stub data in tests; avoid brittle mocks
Use Mock Service Worker (MSW) for fetch/HTTP call interception in tests
Keep tests deterministic and side-effect free
Use predefined test accounts from test/src/test-wallets.ts in tests
Use FORKED_ETHEREUM_CHAIN for mainnet interactions and ANVIL_CHAIN for isolated tests

**/*.test.{ts,tsx}: Co-locate tests with source files using the pattern foo.ts ↔ foo.test.ts
Use real function invocations with stub data in tests; avoid brittle mocks
For network interactions in tests, use Mock Service Worker (MSW) to intercept fetch/HTTP calls, mocking only scenarios that are hard to reproduce
Keep tests deterministic and side-effect free; Vitest is pre-configured

Files:

  • packages/thirdweb/src/wallets/base-account/base-account-web.test.ts
🧬 Code graph analysis (2)
packages/thirdweb/src/wallets/wallet-types.ts (2)
packages/thirdweb/src/wallets/constants.ts (1)
  • BASE_ACCOUNT (5-5)
packages/thirdweb/src/wallets/base-account/base-account-web.ts (2)
  • BaseAccountSDKWalletConnectionOptions (78-98)
  • BaseAccountWalletCreationOptions (41-73)
packages/thirdweb/src/wallets/create-wallet.ts (3)
packages/thirdweb/src/wallets/constants.ts (1)
  • BASE_ACCOUNT (5-5)
packages/thirdweb/src/wallets/base-account/base-account-wallet.ts (1)
  • baseAccountWalletSDK (17-116)
packages/thirdweb/src/wallets/base-account/base-account-web.ts (1)
  • getBaseAccountWebProvider (106-125)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: E2E Tests (pnpm, vite)
  • GitHub Check: E2E Tests (pnpm, webpack)
  • GitHub Check: E2E Tests (pnpm, esbuild)
  • GitHub Check: Unit Tests
  • GitHub Check: Size
  • GitHub Check: Build Packages
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (13)
packages/thirdweb/src/exports/wallets.ts (1)

14-18: Base Account SDK exports follow established patterns.

The new exports align with the existing pattern used for Coinbase SDK (lines 19-22). The type exports and runtime type guard (isBaseAccountSDKWallet) provide a complete public API surface for the new wallet integration.

packages/thirdweb/src/wallets/base-account/base-account-web.test.ts (1)

84-122: Connection tests validate the core flow.

The connectBaseAccountSDK and autoConnectBaseAccountSDK tests properly mock the provider and verify account address/chain extraction from the SDK responses. The test setup correctly resets modules between runs to avoid cached state issues.

packages/thirdweb/src/wallets/base-account/base-account-wallet.ts (2)

55-95: Connection methods follow lazy-loading best practices.

Both autoConnect and connect correctly use dynamic imports to lazy-load the web module, keeping the initial bundle lean per coding guidelines. The implementations properly track connections for analytics and maintain consistent state updates.

The similar structure between autoConnect (lines 55-75) and connect (lines 76-95) could potentially be refactored to share common logic, but the current approach maintains clarity and matches patterns used in other wallet implementations.


96-114: Wallet lifecycle methods are properly implemented.

The disconnect correctly resets local state before invoking the provider disconnect handler. The switchChain method properly delegates to the handler established during connection. The getChain method uses getCachedChainIfExists for performance optimization.

packages/thirdweb/src/wallets/base-account/base-account-web.ts (2)

300-352: Event handling is well-structured.

The onConnect function properly manages provider event subscriptions with corresponding cleanup in disconnect. The onAccountsChanged handler correctly handles the edge case of an empty accounts array by triggering disconnect. The returned tuple provides all necessary lifecycle functions.


84-98: JSDoc comment is incomplete - missing closing tag.

The JSDoc comment for the chain property (starting at line 84) is missing the closing */ before line 97. This may cause documentation generation issues.

Proposed fix
   * const address = await wallet.connect({ chain: myChain })
+   */
   chain?: Chain;
 };

Likely an incorrect or invalid review comment.

packages/thirdweb/src/wallets/constants.ts (1)

5-5: LGTM!

The new BASE_ACCOUNT constant follows the established reverse domain notation pattern consistent with other wallet constants.

packages/thirdweb/src/wallets/create-wallet.ts (2)

13-17: LGTM!

Imports follow the established pattern, mirroring the Coinbase wallet import structure.


212-224: LGTM!

The Base Account SDK wallet case follows the established pattern. The lazy provider loading via providerFactory aligns with the coding guidelines for keeping the initial bundle lean.

packages/thirdweb/src/wallets/wallet-types.ts (4)

9-17: LGTM!

Imports are correctly structured, following the established pattern for wallet-specific types and constants.


43-43: LGTM!

Adding typeof BASE_ACCOUNT to the WalletId union follows the pattern established by other wallet constants, enabling type-safe wallet creation.


127-142: LGTM!

The WalletAutoConnectionOption type branch correctly mirrors the connection option pattern for BASE_ACCOUNT.


154-164: LGTM!

The WalletCreationOptions type branch correctly returns BaseAccountWalletCreationOptions for BASE_ACCOUNT, enabling type-safe wallet creation with the appropriate options.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

"url": "https://github.com/thirdweb-dev/js/issues"
},
"dependencies": {
"@base-org/account": "2.5.0",
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Query npm registry for `@base-org/account` version 2.5.0
curl -s https://registry.npmjs.org/@base-org/account | jq '.versions["2.5.0"] | {version, dist: .dist | {tarball, shasum}}'

Repository: thirdweb-dev/js

Length of output: 240


🏁 Script executed:

# Also check the latest version available
curl -s https://registry.npmjs.org/@base-org/account | jq '.["dist-tags"]'

Repository: thirdweb-dev/js

Length of output: 204


🏁 Script executed:

# Check the current package.json to understand size-limit configuration
head -50 packages/thirdweb/package.json

Repository: thirdweb-dev/js

Length of output: 1487


🏁 Script executed:

# Search for size-limit configuration in package.json
grep -A 20 "size-limit" packages/thirdweb/package.json

Repository: thirdweb-dev/js

Length of output: 2457


🏁 Script executed:

# Also check if the change included updates to size-limit
git diff HEAD -- packages/thirdweb/package.json | head -100

Repository: thirdweb-dev/js

Length of output: 41


🏁 Script executed:

# Search for size-limit configuration array in the entire package.json
cat packages/thirdweb/package.json | jq '.["size-limit"]' 2>/dev/null || echo "No size-limit array found in package.json"

Repository: thirdweb-dev/js

Length of output: 63


🏁 Script executed:

# Also check the end of the file to see if size-limit config is there
tail -100 packages/thirdweb/package.json

Repository: thirdweb-dev/js

Length of output: 3731


Add size-limit configuration for the new @base-org/account dependency.

The @base-org/account package at version 2.5.0 is valid and follows the existing exact-version pinning pattern. However, per the coding guidelines, bundle budgets must be tracked via package.json#size-limit. The current package.json lacks a size-limit configuration array—add an entry for this dependency to track its bundle size impact. Additionally, consider updating to version 2.5.1 (the latest patch), as it's more recent than 2.5.0.

🤖 Prompt for AI Agents
In `@packages/thirdweb/package.json` at line 14, Update package.json to include a
size-limit configuration array and add an entry tracking the new
`@base-org/account` dependency (identify the package by its name
"@base-org/account" and include a descriptive label in the size-limit entry),
and change the dependency version to the latest patch (2.5.1) instead of 2.5.0;
ensure the size-limit array follows the existing project format and includes the
package path or import target used by the build so bundle budgets are enforced
for `@base-org/account`.

Comment on lines +44 to +52
const unsubscribeDisconnect = emitter.subscribe("disconnect", () => {
reset();
unsubscribeChainChanged();
unsubscribeDisconnect();
});

emitter.subscribe("accountChanged", (_account) => {
account = _account;
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Potential subscription leak for accountChanged event.

The chainChanged and disconnect subscriptions are properly cleaned up on disconnect (lines 46-47), but the accountChanged subscription (lines 50-52) is never unsubscribed. This could lead to memory leaks if the wallet is repeatedly connected and disconnected.

Proposed fix
+  const unsubscribeAccountChanged = emitter.subscribe("accountChanged", (_account) => {
+    account = _account;
+  });
+
   const unsubscribeDisconnect = emitter.subscribe("disconnect", () => {
     reset();
     unsubscribeChainChanged();
     unsubscribeDisconnect();
+    unsubscribeAccountChanged();
   });

-  emitter.subscribe("accountChanged", (_account) => {
-    account = _account;
-  });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const unsubscribeDisconnect = emitter.subscribe("disconnect", () => {
reset();
unsubscribeChainChanged();
unsubscribeDisconnect();
});
emitter.subscribe("accountChanged", (_account) => {
account = _account;
});
const unsubscribeAccountChanged = emitter.subscribe("accountChanged", (_account) => {
account = _account;
});
const unsubscribeDisconnect = emitter.subscribe("disconnect", () => {
reset();
unsubscribeChainChanged();
unsubscribeDisconnect();
unsubscribeAccountChanged();
});
🤖 Prompt for AI Agents
In `@packages/thirdweb/src/wallets/base-account/base-account-wallet.ts` around
lines 44 - 52, The accountChanged subscription is never cleaned up which can
leak on repeated connects; capture its unsubscribe function (e.g., const
unsubscribeAccountChanged = emitter.subscribe("accountChanged", ...)) and call
unsubscribeAccountChanged() inside the disconnect handler alongside
unsubscribeChainChanged() and unsubscribeDisconnect() (and any other teardown
paths) so all three subscriptions are properly unsubscribed when the wallet
disconnects; update references in base-account-wallet.ts to use
unsubscribeAccountChanged where accountChanged is subscribed.

Comment on lines +150 to +178
async sendTransaction(tx: SendTransactionOption) {
const transactionHash = (await provider.request({
method: "eth_sendTransaction",
params: [
{
accessList: tx.accessList,
data: tx.data,
from: getAddress(address),
gas: tx.gas ? numberToHex(tx.gas) : undefined,
to: tx.to as Address,
value: tx.value ? numberToHex(tx.value) : undefined,
},
],
})) as Hex;

trackTransaction({
chainId: tx.chainId,
client: client,
contractAddress: tx.to ?? undefined,
gasPrice: tx.gasPrice,
transactionHash,
walletAddress: getAddress(address),
walletType: BASE_ACCOUNT,
});

return {
transactionHash,
};
},
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

sendTransaction omits EIP-1559 gas parameters.

The transaction request (lines 153-162) includes gas, value, data, accessList, but omits gasPrice, maxFeePerGas, and maxPriorityFeePerGas. While some providers may estimate these, explicitly passing them when provided ensures the transaction uses the caller's intended gas settings.

Proposed fix to include gas pricing parameters
         params: [
           {
             accessList: tx.accessList,
             data: tx.data,
             from: getAddress(address),
             gas: tx.gas ? numberToHex(tx.gas) : undefined,
+            gasPrice: tx.gasPrice ? numberToHex(tx.gasPrice) : undefined,
+            maxFeePerGas: tx.maxFeePerGas ? numberToHex(tx.maxFeePerGas) : undefined,
+            maxPriorityFeePerGas: tx.maxPriorityFeePerGas ? numberToHex(tx.maxPriorityFeePerGas) : undefined,
             to: tx.to as Address,
             value: tx.value ? numberToHex(tx.value) : undefined,
           },
         ],
🤖 Prompt for AI Agents
In `@packages/thirdweb/src/wallets/base-account/base-account-web.ts` around lines
150 - 178, The sendTransaction method builds the eth_sendTransaction params but
omits EIP-1559 gas fields; inside sendTransaction (the provider.request call
that constructs the tx object) include tx.gasPrice, tx.maxFeePerGas, and
tx.maxPriorityFeePerGas when present (convert numeric values to hex with
numberToHex like gas is handled) so the provider receives explicit gas pricing;
keep getAddress(address), accessList, data, to, value handling unchanged and
continue passing gasPrice through to trackTransaction as before.

Comment on lines +442 to +462
} catch (error) {
const apiChain = await getChainMetadata(chain);

// Indicates chain is not added to provider
// biome-ignore lint/suspicious/noExplicitAny: TODO: fix later
if ((error as any)?.code === 4902) {
// try to add the chain
await provider.request({
method: "wallet_addEthereumChain",
params: [
{
blockExplorerUrls: apiChain.explorers?.map((x) => x.url) || [],
chainId: chainIdHex,
chainName: apiChain.name,
nativeCurrency: apiChain.nativeCurrency, // no client id on purpose here
rpcUrls: getValidPublicRPCUrl(apiChain),
},
],
});
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Errors other than code 4902 are silently swallowed.

When wallet_switchEthereumChain fails with an error that is not code 4902, the error is caught but not re-thrown after the if block (line 447-461). This means chain switch failures due to user rejection (code 4001) or other errors will silently fail without notifying the caller.

Proposed fix to re-throw non-4902 errors
   } catch (error) {
     const apiChain = await getChainMetadata(chain);
 
     // Indicates chain is not added to provider
     // biome-ignore lint/suspicious/noExplicitAny: TODO: fix later
     if ((error as any)?.code === 4902) {
       // try to add the chain
       await provider.request({
         method: "wallet_addEthereumChain",
         params: [
           {
             blockExplorerUrls: apiChain.explorers?.map((x) => x.url) || [],
             chainId: chainIdHex,
             chainName: apiChain.name,
             nativeCurrency: apiChain.nativeCurrency, // no client id on purpose here
             rpcUrls: getValidPublicRPCUrl(apiChain),
           },
         ],
       });
+    } else {
+      throw error;
     }
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} catch (error) {
const apiChain = await getChainMetadata(chain);
// Indicates chain is not added to provider
// biome-ignore lint/suspicious/noExplicitAny: TODO: fix later
if ((error as any)?.code === 4902) {
// try to add the chain
await provider.request({
method: "wallet_addEthereumChain",
params: [
{
blockExplorerUrls: apiChain.explorers?.map((x) => x.url) || [],
chainId: chainIdHex,
chainName: apiChain.name,
nativeCurrency: apiChain.nativeCurrency, // no client id on purpose here
rpcUrls: getValidPublicRPCUrl(apiChain),
},
],
});
}
}
} catch (error) {
const apiChain = await getChainMetadata(chain);
// Indicates chain is not added to provider
// biome-ignore lint/suspicious/noExplicitAny: TODO: fix later
if ((error as any)?.code === 4902) {
// try to add the chain
await provider.request({
method: "wallet_addEthereumChain",
params: [
{
blockExplorerUrls: apiChain.explorers?.map((x) => x.url) || [],
chainId: chainIdHex,
chainName: apiChain.name,
nativeCurrency: apiChain.nativeCurrency, // no client id on purpose here
rpcUrls: getValidPublicRPCUrl(apiChain),
},
],
});
} else {
throw error;
}
}
🤖 Prompt for AI Agents
In `@packages/thirdweb/src/wallets/base-account/base-account-web.ts` around lines
442 - 462, The catch block around the wallet_switchEthereumChain flow swallows
all errors except when error.code === 4902; update the catch in
base-account-web.ts to re-throw any error that is not the "chain not added" case
so callers get notified of failures (e.g., user rejection 4001). Specifically,
inside the catch handling for wallet_switchEthereumChain, keep the existing
handling that calls getChainMetadata and provider.request for the 4902 case but
after that if the caught error's code !== 4902 throw the original error
(preserve the error object) so failures from provider.request or
wallet_switchEthereumChain propagate to callers.

Comment on lines +128 to +141
* const baseWallet = createWallet("org.base.account", {
* appMetadata: {
* name: "My App",
* url: "https://my-app.com",
* description: "my app description",
* logoUrl: "https://path/to/my-app/logo.svg",
* },
* testnet: false, // set to true for testnet
* });
*
* const account = await baseWallet.connect({
* client,
* });
* ```
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Documentation example contains a non-existent property.

The testnet: false option on line 135 doesn't exist in BaseAccountWalletCreationOptions. Per the type definition in base-account-web.ts, only appMetadata and chains are supported properties.

To specify testnet usage, the chains option should be used instead:

📝 Suggested documentation fix
 * const baseWallet = createWallet("org.base.account", {
 *   appMetadata: {
 *     name: "My App",
-*     url: "https://my-app.com",
-*     description: "my app description",
 *     logoUrl: "https://path/to/my-app/logo.svg",
 *   },
-*   testnet: false, // set to true for testnet
+*   chains: [base], // specify supported chains
 * });
🤖 Prompt for AI Agents
In `@packages/thirdweb/src/wallets/create-wallet.ts` around lines 128 - 141, The
example in createWallet's usage shows a non-existent option `testnet: false`;
update the example to remove `testnet` and demonstrate using the supported
`chains` option from BaseAccountWalletCreationOptions (see base-account-web.ts)
instead — e.g., replace `testnet` with an appropriate `chains` array or comment
explaining how to select testnet chains when calling
createWallet("org.base.account", { appMetadata, chains }) so the example matches
the actual createWallet/BaseAccountWalletCreationOptions API.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

packages SDK Involves changes to the thirdweb SDK

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants