-
Notifications
You must be signed in to change notification settings - Fork 1
feat: migrate from reown to dynamic #146
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Rate limit exceeded@premiumjibles has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 8 minutes and 26 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (31)
📝 WalkthroughWalkthroughReplaces AppKit wallet stack with Dynamic Labs providers/connectors, centralizes EVM/Solana chain config, renames VITE_PROJECT_ID → VITE_DYNAMIC_ENVIRONMENT_ID, migrates Solana signing to signer-based APIs, and rewires wallet UI/hooks, network switching, and transaction/send/swap flows. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant App as App (DynamicContextProvider)
participant Hook as useWalletConnection
participant Wallet as Wallets (evmWallet / solanaWallet)
participant Connector as Connector (evm.connector / solanaSigner)
participant RPC as Chain RPC / PublicClient
User->>App: trigger send/swap or network switch
App->>Hook: resolve primaryWallet, evmWallet, solanaWallet, primaryAddress
Hook-->>App: return primaryAddress + wallet objects
App->>Wallet: ensure correct primary (maybe changePrimary)
alt EVM path
Wallet->>Connector: connector.switchNetwork(chainId)
Connector->>RPC: perform chain switch
RPC-->>Connector: result
else Solana path
Wallet->>Connector: getSigner()
Connector-->>App: signer
end
App->>Connector: sign and submit transaction
Connector->>RPC: submit transaction
RPC-->>App: tx hash / error
App-->>User: success / error
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (13)
apps/agentic-chat/src/utils/chains/solana/transaction.ts (1)
40-42: Consider extracting the window.solana type declaration.The inline type declaration for
window.solanacould be extracted to a shared type definition file for better maintainability and reusability.Consider adding to
apps/agentic-chat/src/utils/chains/types.ts:declare global { interface Window { solana?: { signTransaction: (tx: VersionedTransaction) => Promise<VersionedTransaction> } } }Then simplify this line to:
- const signer = - params.solanaSigner ?? - (window as { solana?: { signTransaction: (tx: VersionedTransaction) => Promise<VersionedTransaction> } }).solana + const signer = params.solanaSigner ?? window.solanaapps/agentic-chat/src/components/Portfolio/NetworkWalletRow.tsx (1)
45-49: Redundant stopPropagation wrapper around CopyButton.The
CopyButtoncomponent already callse.stopPropagation()internally in its click handler (seeCopyButton.tsxlines 17-18). The wrapper div withonClickandonKeyDownstopPropagation is unnecessary.{address && ( - <div onClick={e => e.stopPropagation()} onKeyDown={e => e.stopPropagation()} role="button" tabIndex={0}> - <CopyButton value={address} className="text-muted-foreground hover:text-foreground" /> - </div> + <CopyButton value={address} className="text-muted-foreground hover:text-foreground" /> )}apps/agentic-chat/src/app/app.tsx (1)
43-52: Consider validatingVITE_DYNAMIC_ENVIRONMENT_IDat startup.If
VITE_DYNAMIC_ENVIRONMENT_IDis undefined or empty, the Dynamic SDK may fail silently or with a cryptic error. Consider adding validation or a fallback with a clear error message during development.const dynamicEnvironmentId = import.meta.env.VITE_DYNAMIC_ENVIRONMENT_ID if (!dynamicEnvironmentId) { throw new Error('VITE_DYNAMIC_ENVIRONMENT_ID environment variable is required') }apps/agentic-chat/src/hooks/usePortfolioQuery.ts (1)
15-16: Redundant context access:primaryWalletis available fromuseWalletConnection.
useWalletConnectionalready accessesprimaryWalletfromuseDynamicContext()internally and exposesprimaryAddress. Consider exposingprimaryWalletfromuseWalletConnectionto avoid duplicate context consumption, or use the existingevmWallet/solanaWalletfromuseWalletConnectionto determine the primary wallet type.apps/agentic-chat/src/hooks/useNetworkSwitch.ts (1)
112-132: Consider using a constant or case-insensitive comparison for Solana network check.The string comparison
data.network === 'solana'is case-sensitive and relies on the exact string format. Consider using a constant or normalizing the comparison to prevent issues if the network name format varies:- if (data.network === 'solana') { + if (data.network.toLowerCase() === 'solana') {apps/agentic-chat/src/hooks/useSendExecution.ts (1)
187-194: Consider adding error handling for wallet switch.The
changePrimaryWalletcall is awaited but not wrapped in try/catch. If the wallet switch fails, the error will propagate to the outer catch block, which may be acceptable, but consider whether a more specific error message would help users understand what failed.if ( chainNamespace === CHAIN_NAMESPACE.Solana && solanaWallet && primaryWallet && !isSolanaWallet(primaryWallet) ) { - await changePrimaryWallet(solanaWallet.id) + try { + await changePrimaryWallet(solanaWallet.id) + } catch (e) { + throw new Error('Failed to switch to Solana wallet') + } }apps/agentic-chat/src/lib/wagmi-config.ts (1)
10-13: Consider using custom RPC URLs from chain config.The
http()transport is created without arguments, using wagmi's default RPC URLs. However,SUPPORTED_EVM_CHAINSdefines customrpcUrlfor each chain. Consider using those for consistency:-const transports = Object.fromEntries(SUPPORTED_CHAIN_IDS.map(id => [id, http()])) as Record< +const transports = Object.fromEntries( + SUPPORTED_EVM_CHAINS.map(c => [c.chain.id, http(c.rpcUrl)]) +) as Record< (typeof SUPPORTED_CHAIN_IDS)[number], ReturnType<typeof http> >apps/agentic-chat/src/hooks/useSwapExecution.tsx (1)
217-243: Consider extracting shared wallet switching logic.The wallet switching logic (lines 217-243) is nearly identical to
useSendExecution. Consider extracting this to a shared utility to reduce duplication and ensure consistent behavior.Example shared utility:
// utils/walletSwitch.ts export async function ensureCorrectPrimaryWallet( chainNamespace: string, primaryWallet: Wallet | null, evmWallet: EthereumWallet | undefined, solanaWallet: SolanaWallet | undefined, changePrimaryWallet: (id: string) => Promise<void> ): Promise<void> { if (chainNamespace === CHAIN_NAMESPACE.Solana) { if (solanaWallet && primaryWallet && !isSolanaWallet(primaryWallet)) { await changePrimaryWallet(solanaWallet.id) } } else if (chainNamespace === CHAIN_NAMESPACE.Evm) { if (!evmWallet) throw new Error('EVM wallet not connected') if (primaryWallet && !isEthereumWallet(primaryWallet)) { await changePrimaryWallet(evmWallet.id) } } }apps/agentic-chat/src/components/Portfolio/PortfolioDrawer.tsx (3)
57-62: Add error handling for removeWallet.The
removeWalletcall is fire-and-forget withvoid. If it fails, the user won't know. Consider adding error handling:const handleWalletDisconnect = useCallback(() => { if (walletToDisconnect) { - void removeWallet(walletToDisconnect) + removeWallet(walletToDisconnect).catch(error => { + console.error('Failed to disconnect wallet:', error) + }) setWalletToDisconnect(null) } }, [walletToDisconnect, removeWallet])
85-92: Inefficient wallet filtering inwalletGroupscomputation.The
otherWalletsfilter callsfilterEvmWalletsandfilterSolanaWalletsfor each wallet individually, which is O(n²). Consider restructuring:const walletGroups = useMemo( () => ({ evmWallets: filterEvmWallets(userWallets), solanaWallets: filterSolanaWallets(userWallets), - otherWallets: userWallets.filter(w => !filterEvmWallets([w]).length && !filterSolanaWallets([w]).length), + otherWallets: userWallets.filter( + w => !isEthereumWallet(w) && !isSolanaWallet(w) + ), }), [userWallets] )This requires importing
isEthereumWalletandisSolanaWalletfrom the Dynamic Labs packages, which are already used elsewhere in the codebase.
112-185: Consider extracting repeated wallet group rendering to a component.The three wallet group blocks (EVM, Solana, Other) have identical structure. Consider extracting to reduce duplication:
const WalletGroup = ({ label, wallets }: { label: string; wallets: Wallet[] }) => { if (wallets.length === 0) return null return ( <div className="mb-2"> <div className="px-2 py-1 text-xs font-medium text-muted-foreground/70 uppercase tracking-wider"> {label} </div> {wallets.map(wallet => ( <div key={wallet.id} className="relative"> <NetworkWalletRow label={wallet.connector.name} address={wallet.address} icon={getWalletIcon(wallet)} isConnected={true} isActive={wallet.id === primaryWallet?.id} onConnect={() => { if (wallet.id !== primaryWallet?.id) { void changePrimaryWallet(wallet.id) } }} onDisconnect={() => setWalletToDisconnect(wallet.id)} /> </div> ))} </div> ) }apps/agentic-chat/src/lib/chains.ts (1)
15-88: Consider externalizing or validating icon URLs.The icon URLs are hardcoded to Dynamic's CDN (
app.dynamic.xyz/assets/networks/). If Dynamic changes their asset paths or the app needs to work offline/in a custom environment, these could break silently.Consider either:
- Using environment variables or a config file for the base URL
- Adding a fallback mechanism for missing icons
- Documenting that these URLs depend on Dynamic's CDN availability
const DYNAMIC_ICON_BASE = 'https://app.dynamic.xyz/assets/networks' // Then use: iconUrl: `${DYNAMIC_ICON_BASE}/eth.svg`,apps/agentic-chat/src/hooks/useWalletConnection.ts (1)
28-30: Consider adding a fallback icon.The
getWalletIconfunction safely handles null/undefined wallet via optional chaining, but callers may need to handle theundefinedreturn value. Consider whether a default fallback icon would be useful.
📜 Review details
Configuration used: CodeRabbit 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.
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (30)
.env.example(1 hunks).env.production(1 hunks)apps/agentic-chat/package.json(1 hunks)apps/agentic-chat/src/app/app.tsx(2 hunks)apps/agentic-chat/src/components/CustomConnectButton.tsx(3 hunks)apps/agentic-chat/src/components/Portfolio/NetworkWalletRow.tsx(2 hunks)apps/agentic-chat/src/components/Portfolio/PortfolioDrawer.tsx(4 hunks)apps/agentic-chat/src/components/tools/InitiateSwapUI.tsx(1 hunks)apps/agentic-chat/src/components/tools/SendUI.tsx(1 hunks)apps/agentic-chat/src/hooks/useApprovedChains.ts(1 hunks)apps/agentic-chat/src/hooks/useAutoNetworkSwitch.ts(1 hunks)apps/agentic-chat/src/hooks/useNetworkSwitch.ts(3 hunks)apps/agentic-chat/src/hooks/usePortfolioQuery.ts(2 hunks)apps/agentic-chat/src/hooks/useSendExecution.ts(5 hunks)apps/agentic-chat/src/hooks/useSwapExecution.tsx(8 hunks)apps/agentic-chat/src/hooks/useWalletConnection.ts(1 hunks)apps/agentic-chat/src/lib/appkit.ts(0 hunks)apps/agentic-chat/src/lib/chains.ts(1 hunks)apps/agentic-chat/src/lib/networks.ts(1 hunks)apps/agentic-chat/src/lib/solana-config.ts(0 hunks)apps/agentic-chat/src/lib/wagmi-config.ts(1 hunks)apps/agentic-chat/src/types/appkit.d.ts(0 hunks)apps/agentic-chat/src/utils/chains/evm/transaction.ts(2 hunks)apps/agentic-chat/src/utils/chains/solana/transaction.ts(2 hunks)apps/agentic-chat/src/utils/chains/types.ts(1 hunks)apps/agentic-chat/src/utils/sendExecutor.ts(2 hunks)apps/agentic-chat/src/utils/sendTransaction.ts(2 hunks)apps/agentic-chat/src/utils/swapExecutor.ts(2 hunks)apps/agentic-chat/vite.config.mjs(1 hunks)package.json(1 hunks)
💤 Files with no reviewable changes (3)
- apps/agentic-chat/src/lib/appkit.ts
- apps/agentic-chat/src/lib/solana-config.ts
- apps/agentic-chat/src/types/appkit.d.ts
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-22T20:32:10.539Z
Learnt from: kaladinlight
Repo: shapeshift/agentic-chat PR: 76
File: apps/agentic-server/src/mastra/tools/asset/coingecko/constants.ts:1-10
Timestamp: 2025-09-22T20:32:10.539Z
Learning: When cross-app dependencies are identified (like server code importing from chat packages), the user prefers to extract shared constants into dedicated packages in the packages/ directory following the existing pattern of shapeshiftoss/types and shapeshiftoss/utils.
Applied to files:
apps/agentic-chat/src/lib/networks.tsapps/agentic-chat/src/hooks/useSendExecution.ts
🧬 Code graph analysis (14)
apps/agentic-chat/src/utils/sendExecutor.ts (5)
apps/agentic-server/src/lib/schemas/swapSchemas.ts (1)
TransactionData(75-75)apps/agentic-server/src/tools/send.ts (1)
SendOutput(137-137)apps/agentic-server/src/index.ts (1)
SendOutput(64-64)apps/agentic-server/src/lib/schemas/sendSchemas.ts (1)
SendOutput(49-49)apps/agentic-chat/src/utils/chains/types.ts (1)
SolanaWalletSigner(8-10)
apps/agentic-chat/src/utils/chains/evm/transaction.ts (1)
apps/agentic-chat/src/lib/chains.ts (1)
chainIdToChain(99-101)
apps/agentic-chat/src/components/Portfolio/NetworkWalletRow.tsx (3)
apps/agentic-chat/src/lib/utils.ts (1)
truncateAddress(9-12)apps/agentic-chat/src/components/ui/CopyButton.tsx (1)
CopyButton(15-41)apps/agentic-chat/src/components/ui/IconButton.tsx (1)
IconButton(22-29)
apps/agentic-chat/src/utils/sendTransaction.ts (1)
apps/agentic-chat/src/utils/chains/types.ts (1)
SolanaWalletSigner(8-10)
apps/agentic-chat/src/hooks/useApprovedChains.ts (2)
apps/agentic-chat/src/hooks/useWalletConnection.ts (2)
filterEvmWallets(20-22)filterSolanaWallets(24-26)apps/agentic-chat/src/lib/chains.ts (2)
EVM_CAIP_IDS(108-108)SOLANA_CAIP_ID(90-90)
apps/agentic-chat/src/hooks/useSwapExecution.tsx (2)
apps/agentic-chat/src/hooks/useWalletConnection.ts (1)
useWalletConnection(42-67)apps/agentic-chat/src/utils/chains/types.ts (1)
SolanaWalletSigner(8-10)
apps/agentic-chat/src/hooks/usePortfolioQuery.ts (2)
apps/agentic-chat/src/hooks/useWalletConnection.ts (1)
useWalletConnection(42-67)apps/agentic-chat/src/services/portfolioService.ts (1)
fetchFullPortfolio(31-102)
apps/agentic-chat/src/utils/chains/types.ts (2)
apps/agentic-chat/src/types/transaction.ts (1)
Transaction(1-10)packages/caip/src/constants.ts (1)
ChainId(175-175)
apps/agentic-chat/src/lib/wagmi-config.ts (1)
apps/agentic-chat/src/lib/chains.ts (2)
SUPPORTED_EVM_CHAINS(15-88)SUPPORTED_CHAIN_IDS(94-97)
apps/agentic-chat/src/hooks/useWalletConnection.ts (2)
apps/agentic-chat/src/types/wallet.ts (1)
Wallet(1-6)apps/agentic-chat/src/hooks/useApprovedChains.ts (1)
useApprovedChains(8-24)
apps/agentic-chat/src/components/CustomConnectButton.tsx (4)
apps/agentic-chat/src/hooks/useWalletConnection.ts (2)
useWalletConnection(42-67)getWalletIcon(28-30)apps/agentic-chat/src/lib/utils.ts (1)
truncateAddress(9-12)apps/agentic-chat/src/lib/chains.ts (1)
SOLANA_CAIP_ID(90-90)packages/utils/src/networkIcons.ts (1)
NETWORK_ICONS(14-31)
apps/agentic-chat/src/app/app.tsx (2)
apps/agentic-chat/src/lib/chains.ts (1)
DYNAMIC_EVM_NETWORKS(110-120)apps/agentic-chat/src/lib/wagmi-config.ts (1)
wagmiConfig(15-19)
apps/agentic-chat/src/hooks/useSendExecution.ts (5)
apps/agentic-chat/src/hooks/useWalletConnection.ts (1)
useWalletConnection(42-67)packages/caip/src/constants.ts (1)
CHAIN_NAMESPACE(46-54)apps/agentic-chat/src/utils/chains/types.ts (1)
SolanaWalletSigner(8-10)apps/agentic-chat/src/utils/sendExecutor.ts (1)
executeSend(34-40)apps/agentic-server/src/tools/send.ts (1)
executeSend(24-71)
apps/agentic-chat/src/utils/swapExecutor.ts (3)
apps/agentic-server/src/lib/schemas/swapSchemas.ts (2)
SwapData(77-77)TransactionData(75-75)apps/agentic-server/src/tools/initiateSwap.ts (1)
InitiateSwapOutput(277-277)apps/agentic-chat/src/utils/chains/types.ts (1)
SolanaWalletSigner(8-10)
⏰ 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). (1)
- GitHub Check: main
🔇 Additional comments (37)
apps/agentic-chat/src/components/tools/InitiateSwapUI.tsx (1)
19-19: LGTM - More accurate address source.Deriving the address from
swapOutput?.swapData.sellAccountis semantically correct as it shows the actual sender of the swap transaction rather than the currently connected wallet. This is especially important for historical transactions where the connected wallet may differ from the transaction initiator.apps/agentic-chat/src/components/tools/SendUI.tsx (1)
17-17: LGTM - Consistent address source.Using
sendOutput?.summary.fromto derive the address is consistent with the approach inInitiateSwapUI.tsxand correctly represents the actual transaction sender rather than the currently connected wallet.apps/agentic-chat/src/hooks/useAutoNetworkSwitch.ts (1)
1-5: Verify that callers don't rely on the previous hook behavior.The hook has been converted to a no-op with network switching delegated to the Dynamic SDK. While this maintains API compatibility, ensure that any code calling
useAutoNetworkSwitchdoesn't rely on side effects from the previous implementation.package.json (1)
62-64: @solana/web3.js version 1.98.1 is valid and secure.The override pins
@solana/web3.jsto version 1.98.1, which is a stable, non-deprecated release on NPM with no known security vulnerabilities. The version is stricter than the semver range^1.95.8specified in the app's package.json, though newer patch versions (1.98.2, 1.98.3, 1.98.4) are available.apps/agentic-chat/package.json (1)
16-21: The Dynamic Labs SDK packages at version 4.49.0 are compatible with React 19.1.1. The @dynamic-labs/sdk-react-core package explicitly declares React peerDependencies as>=18.0.0 <20.0.0, which includes React 19. No compatibility concerns.apps/agentic-chat/src/components/Portfolio/NetworkWalletRow.tsx (1)
31-34: Verify the intent of row click triggeringonConnect.When connected, clicking the row calls
onConnect. Confirm this is intentional for switching/selecting the active wallet rather than an oversight where it should be a no-op or different action for an already-connected wallet..env.example (1)
26-27: LGTM!The environment variable rename from
VITE_PROJECT_IDtoVITE_DYNAMIC_ENVIRONMENT_IDis clear and aligns with the Dynamic Labs SDK migration.apps/agentic-chat/src/utils/sendExecutor.ts (1)
4-4: LGTM!The refactoring from
SolanaWalletProvidertoSolanaWalletSigneris consistent and aligns with the signer-based wallet interaction pattern introduced in this PR.Also applies to: 11-11, 28-28
apps/agentic-chat/src/utils/sendTransaction.ts (1)
4-4: LGTM!Consistent type rename aligning
SendTransactionParamswith the newSolanaWalletSignerinterface.Also applies to: 13-13
apps/agentic-chat/src/utils/chains/evm/transaction.ts (1)
25-28: LGTM!Good improvement replacing the
extractChainiteration with a direct O(1) map lookup viachainIdToChain. The explicit validation guard with a clear error message is a good defensive addition.apps/agentic-chat/src/utils/swapExecutor.ts (1)
4-4: LGTM!Consistent with the
sendExecutor.tsrefactoring, maintaining symmetry between swap and send transaction flows.Also applies to: 12-12, 28-28
apps/agentic-chat/src/app/app.tsx (1)
1-13: LGTM on the Dynamic Labs SDK integration.The provider hierarchy (
DynamicContextProvider→WagmiProvider→QueryClientProvider→DynamicWagmiConnector) follows the recommended nesting for Dynamic Labs with Wagmi. Theconnect-onlyauthentication mode and network merging strategy are appropriate for this use case.apps/agentic-chat/src/components/CustomConnectButton.tsx (3)
17-19: Potential stalechainIdwhen Solana is the primary wallet.When the primary wallet is Solana,
useChainId()from wagmi may return a stale EVM chain ID (from the last connected EVM wallet) or undefined. This could cause thecaipChainIdon line 47 to fall through to an EVM chain even when Solana is primary, though theisPrimarySolanacheck should handle this correctly.Consider verifying that
chainIdbehavior is expected when no EVM wallet is active.
39-48: LGTM!The address fallback chain and the conditional CAIP ID derivation based on wallet type are well-structured. The Solana-specific handling using
isSolanaWalletensures the correct network icon is displayed.
50-64: LGTM!The conditional rendering for wallet and network icons handles missing values gracefully, and the address truncation provides a clean user experience.
apps/agentic-chat/src/hooks/useApprovedChains.ts (1)
14-20: Behavioral change: All EVM chains are now approved if any EVM wallet is connected.The previous implementation likely extracted specific approved chains from WalletConnect sessions. This new logic includes all
EVM_CAIP_IDSwhen any EVM wallet is present, which may grant broader access than the wallet actually supports.If chain-specific approvals are needed (e.g., for WalletConnect v2 session namespaces), this simplification may cause issues. Please confirm this is the intended behavior with Dynamic's wallet model.
apps/agentic-chat/src/hooks/usePortfolioQuery.ts (2)
22-31: Behavioral change: Portfolio only fetches for the primary wallet type.Previously, the portfolio may have fetched for both EVM and Solana addresses. Now it only fetches for the primary wallet's chain type. Users with both EVM and Solana wallets connected will only see the portfolio for whichever wallet is currently primary.
If this is intentional, consider adding a comment explaining this behavior. If users should see their combined portfolio, both addresses should be passed to
fetchFullPortfolio.
38-48: LGTM!The asset filtering logic and return shape are well-structured, maintaining backward compatibility with consumers of this hook.
apps/agentic-chat/src/hooks/useNetworkSwitch.ts (3)
73-99: LGTM!The hydration logic for persisted state follows a clean pattern, ensuring that tool state is properly restored when the component re-mounts.
167-183: LGTM!The error handling is comprehensive, properly capturing the error message, updating the state, and persisting the failure for recovery purposes.
139-153: The code pattern here is intentional and appears throughout the codebase (useSwapExecution.tsx, useSendExecution.ts). AfterchangePrimaryWallet(evmWallet.id)switches the primary wallet context, theevmWallet.connectorreference remains valid because the connector is tied to the wallet instance itself, not to its primary designation. The pattern is consistent with Dynamic SDK's design where changing primary wallet status doesn't invalidate other wallet instances. No special handling or re-fetching is needed.apps/agentic-chat/src/lib/networks.ts (1)
1-1: No action needed. The re-export ofchainIdToChainandnetworkNameToChainIdfrom./chainsis correct, and there are no consumers in the codebase using outdated export names.apps/agentic-chat/src/utils/chains/types.ts (2)
6-13: LGTM! Clean interface design with backward compatibility.The
SolanaWalletSignerinterface is appropriately minimal, focusing only on the signing capability needed. The legacy alias preserves backward compatibility during migration.
22-22: LGTM! Parameter rename aligns with signer-based pattern.The rename from
solanaProvidertosolanaSignerbetter reflects the actual usage and aligns with the new Dynamic Labs integration.apps/agentic-chat/src/hooks/useSendExecution.ts (1)
205-214: LGTM! EVM wallet validation and network switching.Good defensive check for
evmWalletpresence before proceeding. The primary wallet switch and network switch sequence is correct.apps/agentic-chat/src/lib/wagmi-config.ts (1)
15-19: LGTM! Config structure is correct.Setting
multiInjectedProviderDiscovery: falseis appropriate since Dynamic Labs handles wallet discovery. The config is properly typed and exported.apps/agentic-chat/src/hooks/useSwapExecution.tsx (2)
201-205: LGTM! Early signer retrieval is a good pattern.Obtaining the Solana signer early in the flow, before network switching and transaction execution, ensures it's available when needed and fails fast if there's an issue.
278-286: LGTM! Approval confirmation handles missing public client gracefully.The
if (publicClient)check prevents crashes if the chain isn't properly configured in wagmi.apps/agentic-chat/src/components/Portfolio/PortfolioDrawer.tsx (2)
43-55: LGTM! Proper cleanup on disconnect.Good pattern: invalidating relevant queries before logout ensures stale data isn't displayed if the user reconnects.
257-268: LGTM! Per-wallet disconnect confirmation.Good UX to require confirmation before disconnecting individual wallets. The dialog state management using
walletToDisconnectis clean.apps/agentic-chat/src/lib/chains.ts (3)
5-13: Well-structured chain configuration interface.The
ChainConfiginterface provides a clean, type-safe structure for chain metadata. This centralizes chain configuration and avoids scattered magic values.
103-106: Clarify thesolana: 0mapping.Using
0as the chain ID for Solana is unconventional since Solana doesn't use numeric chain IDs like EVM chains. This could cause issues if code assumes all values in this map are valid EVM chain IDs.Consider:
- Adding a comment explaining why
0is used (e.g., sentinel value for non-EVM)- Using a separate mapping for non-EVM networks
- Using
nullor a distinct constant likeSOLANA_CHAIN_ID_PLACEHOLDER = 0+// Solana uses 0 as a placeholder since it doesn't have a numeric chain ID like EVM chains export const networkNameToChainId: Record<string, number> = { ...Object.fromEntries(SUPPORTED_EVM_CHAINS.map(c => [c.networkName, c.chain.id])), solana: 0, }
110-120: LGTM - Clean transformation to Dynamic's EvmNetwork type.The mapping from
ChainConfigtoEvmNetworkis well-structured and correctly maps all required fields includingnativeCurrencyfrom viem's chain definition.apps/agentic-chat/src/hooks/useWalletConnection.ts (4)
20-26: LGTM - Filter functions follow the same pattern as find functions.These utility functions provide a clean API for filtering wallets by type and are properly typed with type guards.
32-40: Well-defined return type interface.The
WalletConnectionResultinterface clearly documents the hook's contract and provides good type safety for consumers.
42-66: Clean wallet resolution logic with sensible priority.The hook correctly:
- Prioritizes
primaryWalletwhen it matches the expected type- Falls back to searching
userWalletsfor each wallet type- Derives addresses from resolved wallets
- Computes
isConnectedfrom address presenceThis approach ensures users with multiple wallets get their primary wallet used preferentially.
10-18: Type cast is appropriate given SDK design, no changes needed.
DynamicWallet(derived fromuseUserWallets) andWalletare distinct types from the same SDK package, as evidenced bygetWalletIconaccepting both. Thew as Walletcast is intentional type narrowing required becauseuseUserWalletsreturns a broader union type than the type guards expect. This pattern is consistent across all helper functions and poses no runtime risk—the types are mutually compatible. If the SDK's type definitions change in future updates, this code would require explicit updates regardless, which is normal for external dependency changes.
59024ea to
bea0509
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/agentic-chat/src/hooks/useSendExecution.ts (1)
169-175: Address comparison may fail for Solana addresses.The lowercase comparison at line 173 works for EVM addresses but Solana addresses are case-sensitive (base58 encoded). This could cause false negatives for Solana transactions.
- if (currentAddress.toLowerCase() !== tx.from.toLowerCase()) { + const addressesMatch = chainNamespace === CHAIN_NAMESPACE.Evm + ? currentAddress.toLowerCase() === tx.from.toLowerCase() + : currentAddress === tx.from + if (!addressesMatch) { throw new Error('Wallet address changed. Please re-initiate the transaction.') }
♻️ Duplicate comments (2)
apps/agentic-chat/src/hooks/useApprovedChains.ts (1)
9-23: Memoization is ineffective due to unstableuserWalletsreference.As flagged in the previous review,
useUserWallets()returns a new array reference on each render, causing theuseMemoto recalculate every time. Use a stable derived key:export function useApprovedChains(): string[] { const userWallets = useUserWallets() + const walletIds = useMemo(() => userWallets.map(w => w.id).join(','), [userWallets]) return useMemo(() => { const chainIds: string[] = [] if (filterEvmWallets(userWallets).length > 0) { chainIds.push(...EVM_CAIP_IDS) } if (filterSolanaWallets(userWallets).length > 0) { chainIds.push(SOLANA_CAIP_ID) } return chainIds - }, [userWallets]) + }, [walletIds, userWallets]) }apps/agentic-chat/src/hooks/useSendExecution.ts (1)
224-230: Consider usingISolanaSignertype from Dynamic Labs SDK.The code assigns
solanaWallet.getSigner()toSolanaWalletSigner, but Dynamic Labs SDK returnsISolanaSigner. While structurally compatible, using the SDK's type directly would improve type safety and clarity.Dynamic Labs SDK 4.49.0 ISolanaSigner type definition
🧹 Nitpick comments (7)
apps/agentic-chat/src/utils/chains/solana/transaction.ts (1)
40-42: Extract the inline type annotation for better maintainability.The inline type annotation for
window.solanais verbose and couples the type definition with its usage. Consider extracting it to a type alias or ensuring it aligns with theSolanaWalletSignerinterface mentioned in previous reviews.// At the top of the file or in types.ts type SolanaWindowProvider = { signTransaction: (tx: VersionedTransaction) => Promise<VersionedTransaction> } // Then use: const signer = params.solanaSigner ?? (window as { solana?: SolanaWindowProvider }).solanaapps/agentic-chat/src/components/CustomConnectButton.tsx (1)
39-53: LGTM! Clean integration with Dynamic context.The address resolution chain and CAIP chain ID construction are well-structured. Minor observation: if
walletIconis falsy (e.g., wallet doesn't provide an icon), the parent div still renders but appears empty. This shouldn't cause visual issues given the network icon overlay, but consider a fallback icon or hiding the container:- {walletIcon && <img src={walletIcon} alt={walletName || 'Wallet'} className="w-6 h-6 rounded-full" />} + <img src={walletIcon || '/fallback-wallet-icon.svg'} alt={walletName || 'Wallet'} className="w-6 h-6 rounded-full" />apps/agentic-chat/src/app/app.tsx (1)
43-70: Provider hierarchy looks correct.The nesting order (DynamicContextProvider → WagmiProvider → QueryClientProvider → DynamicWagmiConnector) aligns with Dynamic Labs integration patterns.
However,
VITE_DYNAMIC_ENVIRONMENT_IDat line 46 has no fallback or validation. If this env variable is missing or empty, the app will silently fail to initialize properly. Consider adding a runtime check:const environmentId = import.meta.env.VITE_DYNAMIC_ENVIRONMENT_ID if (!environmentId) { throw new Error('VITE_DYNAMIC_ENVIRONMENT_ID is required') }apps/agentic-chat/src/components/Portfolio/PortfolioDrawer.tsx (4)
43-55: Consider awaitinginvalidateQueriesbefore logout.The query invalidations are fire-and-forget while
handleLogOutis awaited. If logout completes before invalidation finishes, there could be a brief window where stale data persists.- const handleDisconnect = useCallback(() => { - void queryClient.invalidateQueries({ queryKey: ['portfolio'] }) - void queryClient.invalidateQueries({ queryKey: ['approvedChains'] }) - - handleLogOut() + const handleDisconnect = useCallback(async () => { + await Promise.all([ + queryClient.invalidateQueries({ queryKey: ['portfolio'] }), + queryClient.invalidateQueries({ queryKey: ['approvedChains'] }), + ]) + + await handleLogOut() .catch(error => { console.error('Failed to disconnect wallet:', error) }) .finally(() => { setShowDisconnectAlert(false) onClose() }) }, [queryClient, handleLogOut, onClose])
57-62: Missing error handling forremoveWallet.
removeWalletis called withvoidbut failures are silently ignored. Consider adding error handling to inform users if wallet removal fails.const handleWalletDisconnect = useCallback(() => { if (walletToDisconnect) { - void removeWallet(walletToDisconnect) + removeWallet(walletToDisconnect).catch(error => { + console.error('Failed to remove wallet:', error) + }) setWalletToDisconnect(null) } }, [walletToDisconnect, removeWallet])
86-93: Inefficient wallet filtering creates unnecessary intermediate arrays.
filterEvmWallets([w])andfilterSolanaWallets([w])are called for each wallet inotherWalletscomputation, creating single-element arrays repeatedly. Use the type guards directly instead.+import { isEthereumWallet } from '@dynamic-labs/ethereum' +import { isSolanaWallet } from '@dynamic-labs/solana' +import type { Wallet } from '@dynamic-labs/sdk-react-core' const walletGroups = useMemo( () => ({ evmWallets: filterEvmWallets(userWallets), solanaWallets: filterSolanaWallets(userWallets), - otherWallets: userWallets.filter(w => !filterEvmWallets([w]).length && !filterSolanaWallets([w]).length), + otherWallets: userWallets.filter(w => !isEthereumWallet(w as Wallet) && !isSolanaWallet(w as Wallet)), }), [userWallets] )
113-136: Repetitive wallet row rendering across EVM, Solana, and Other groups.The three wallet group sections (lines 113-136, 138-161, 163-186) contain nearly identical rendering logic. Consider extracting a reusable component or helper to reduce duplication.
const WalletGroupSection = ({ label, wallets }: { label: string; wallets: typeof walletGroups.evmWallets }) => ( wallets.length > 0 ? ( <div className="mb-2"> <div className="px-2 py-1 text-xs font-medium text-muted-foreground/70 uppercase tracking-wider"> {label} </div> {wallets.map(wallet => ( <div key={wallet.id} className="relative"> <NetworkWalletRow label={wallet.connector.name} address={wallet.address} icon={getWalletIcon(wallet)} isConnected={true} isActive={wallet.id === primaryWallet?.id} onConnect={() => wallet.id !== primaryWallet?.id && void changePrimaryWallet(wallet.id)} onDisconnect={() => setWalletToDisconnect(wallet.id)} /> </div> ))} </div> ) : null )
📜 Review details
Configuration used: CodeRabbit 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.
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (30)
.env.example(1 hunks).env.production(1 hunks)apps/agentic-chat/package.json(1 hunks)apps/agentic-chat/src/app/app.tsx(2 hunks)apps/agentic-chat/src/components/CustomConnectButton.tsx(3 hunks)apps/agentic-chat/src/components/Portfolio/NetworkWalletRow.tsx(2 hunks)apps/agentic-chat/src/components/Portfolio/PortfolioDrawer.tsx(4 hunks)apps/agentic-chat/src/components/tools/InitiateSwapUI.tsx(1 hunks)apps/agentic-chat/src/components/tools/SendUI.tsx(1 hunks)apps/agentic-chat/src/hooks/useApprovedChains.ts(1 hunks)apps/agentic-chat/src/hooks/useAutoNetworkSwitch.ts(1 hunks)apps/agentic-chat/src/hooks/useNetworkSwitch.ts(3 hunks)apps/agentic-chat/src/hooks/usePortfolioQuery.ts(2 hunks)apps/agentic-chat/src/hooks/useSendExecution.ts(5 hunks)apps/agentic-chat/src/hooks/useSwapExecution.tsx(8 hunks)apps/agentic-chat/src/hooks/useWalletConnection.ts(1 hunks)apps/agentic-chat/src/lib/appkit.ts(0 hunks)apps/agentic-chat/src/lib/chains.ts(1 hunks)apps/agentic-chat/src/lib/networks.ts(1 hunks)apps/agentic-chat/src/lib/solana-config.ts(0 hunks)apps/agentic-chat/src/lib/wagmi-config.ts(1 hunks)apps/agentic-chat/src/types/appkit.d.ts(0 hunks)apps/agentic-chat/src/utils/chains/evm/transaction.ts(2 hunks)apps/agentic-chat/src/utils/chains/solana/transaction.ts(2 hunks)apps/agentic-chat/src/utils/chains/types.ts(1 hunks)apps/agentic-chat/src/utils/sendExecutor.ts(2 hunks)apps/agentic-chat/src/utils/sendTransaction.ts(2 hunks)apps/agentic-chat/src/utils/swapExecutor.ts(2 hunks)apps/agentic-chat/vite.config.mjs(1 hunks)package.json(1 hunks)
💤 Files with no reviewable changes (3)
- apps/agentic-chat/src/lib/appkit.ts
- apps/agentic-chat/src/types/appkit.d.ts
- apps/agentic-chat/src/lib/solana-config.ts
🚧 Files skipped from review as they are similar to previous changes (12)
- apps/agentic-chat/src/components/tools/InitiateSwapUI.tsx
- apps/agentic-chat/src/utils/chains/types.ts
- .env.production
- apps/agentic-chat/vite.config.mjs
- apps/agentic-chat/src/utils/swapExecutor.ts
- package.json
- apps/agentic-chat/src/components/tools/SendUI.tsx
- apps/agentic-chat/src/lib/chains.ts
- apps/agentic-chat/src/hooks/useWalletConnection.ts
- apps/agentic-chat/package.json
- .env.example
- apps/agentic-chat/src/utils/sendExecutor.ts
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-09-16T20:28:23.547Z
Learnt from: premiumjibles
Repo: shapeshift/agentic-chat PR: 68
File: apps/agentic-server/package.json:26-26
Timestamp: 2025-09-16T20:28:23.547Z
Learning: In the ShapeShift agentic-chat codebase, mathjs optimization (lazy-loading or using modular sub-packages) has been noted for future implementation rather than immediate action.
Applied to files:
apps/agentic-chat/src/hooks/useApprovedChains.ts
📚 Learning: 2025-09-22T20:32:10.539Z
Learnt from: kaladinlight
Repo: shapeshift/agentic-chat PR: 76
File: apps/agentic-server/src/mastra/tools/asset/coingecko/constants.ts:1-10
Timestamp: 2025-09-22T20:32:10.539Z
Learning: When cross-app dependencies are identified (like server code importing from chat packages), the user prefers to extract shared constants into dedicated packages in the packages/ directory following the existing pattern of shapeshiftoss/types and shapeshiftoss/utils.
Applied to files:
apps/agentic-chat/src/lib/networks.tsapps/agentic-chat/src/hooks/useSendExecution.ts
🧬 Code graph analysis (10)
apps/agentic-chat/src/utils/sendTransaction.ts (1)
apps/agentic-chat/src/utils/chains/types.ts (1)
SolanaWalletSigner(8-10)
apps/agentic-chat/src/hooks/useApprovedChains.ts (2)
apps/agentic-chat/src/hooks/useWalletConnection.ts (2)
filterEvmWallets(20-22)filterSolanaWallets(24-26)apps/agentic-chat/src/lib/chains.ts (2)
EVM_CAIP_IDS(108-108)SOLANA_CAIP_ID(90-90)
apps/agentic-chat/src/components/Portfolio/PortfolioDrawer.tsx (4)
apps/agentic-chat/src/hooks/useWalletConnection.ts (4)
useWalletConnection(42-67)getWalletIcon(28-30)filterEvmWallets(20-22)filterSolanaWallets(24-26)apps/agentic-chat/src/hooks/usePortfolioQuery.ts (1)
usePortfolioQuery(14-49)apps/agentic-chat/src/lib/utils.ts (1)
truncateAddress(9-12)apps/agentic-chat/src/components/Portfolio/NetworkWalletRow.tsx (1)
NetworkWalletRow(19-72)
apps/agentic-chat/src/hooks/useNetworkSwitch.ts (3)
apps/agentic-chat/src/hooks/useWalletConnection.ts (1)
useWalletConnection(42-67)apps/agentic-chat/src/hooks/useToolExecutionEffect.ts (1)
useToolExecutionEffect(10-57)apps/agentic-chat/src/lib/chains.ts (1)
networkNameToChainId(103-106)
apps/agentic-chat/src/hooks/usePortfolioQuery.ts (2)
apps/agentic-chat/src/hooks/useWalletConnection.ts (1)
useWalletConnection(42-67)apps/agentic-chat/src/services/portfolioService.ts (1)
fetchFullPortfolio(31-102)
apps/agentic-chat/src/components/Portfolio/NetworkWalletRow.tsx (3)
apps/agentic-chat/src/lib/utils.ts (1)
truncateAddress(9-12)apps/agentic-chat/src/components/ui/CopyButton.tsx (1)
CopyButton(15-41)apps/agentic-chat/src/components/ui/IconButton.tsx (1)
IconButton(22-29)
apps/agentic-chat/src/hooks/useSwapExecution.tsx (3)
apps/agentic-chat/src/hooks/useWalletConnection.ts (1)
useWalletConnection(42-67)apps/agentic-chat/src/utils/chains/types.ts (1)
SolanaWalletSigner(8-10)packages/caip/src/constants.ts (1)
CHAIN_NAMESPACE(46-54)
apps/agentic-chat/src/lib/wagmi-config.ts (1)
apps/agentic-chat/src/lib/chains.ts (2)
SUPPORTED_EVM_CHAINS(15-88)SUPPORTED_CHAIN_IDS(94-97)
apps/agentic-chat/src/app/app.tsx (2)
apps/agentic-chat/src/lib/chains.ts (1)
DYNAMIC_EVM_NETWORKS(110-120)apps/agentic-chat/src/lib/wagmi-config.ts (1)
wagmiConfig(15-19)
apps/agentic-chat/src/utils/chains/evm/transaction.ts (1)
apps/agentic-chat/src/lib/chains.ts (1)
chainIdToChain(99-101)
⏰ 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). (1)
- GitHub Check: main
🔇 Additional comments (18)
apps/agentic-chat/src/utils/chains/evm/transaction.ts (2)
25-28: Good defensive check for unsupported chains.The explicit guard and error message for unsupported chain IDs improves debuggability compared to a silent undefined chain.
18-28: [rewritten comment]
[classification tag]apps/agentic-chat/src/components/Portfolio/NetworkWalletRow.tsx (2)
31-34: The clickable row pattern improves wallet selection UX.Making the connected wallet row clickable to set it as active is intuitive. The propagation handling on child elements correctly prevents unintended activations.
39-41: Active badge styling is clear and non-intrusive.The badge provides good visual feedback for the currently selected wallet without being overly prominent.
apps/agentic-chat/src/hooks/useAutoNetworkSwitch.ts (1)
1-5: Approve the hook as-is; it is actively used in the codebase.The hook is imported and called in
apps/agentic-chat/src/app/app.tsxwithin theAppContentfunction, so it cannot be removed. The no-op implementation with explanatory comments is appropriate during this migration—Dynamic SDK handles network coordination automatically, and the hook is retained as a call site for potential future network-awareness logic. The current approach maintains API stability without introducing dead code.apps/agentic-chat/src/lib/networks.ts (1)
1-1: Clean re-export centralizes chain configuration.The re-export of
chainIdToChainandnetworkNameToChainIdfrom./chainssimplifies the module structure and is appropriate for internal use within the agentic-chat application.apps/agentic-chat/src/lib/wagmi-config.ts (1)
15-19: The currentcreateConfigimplementation is correct and does not need SSR or storage options.The previous WagmiAdapter setup (from Reown) only configured
projectIdandnetworks— it did not include SSR or storage settings. The app is a Vite+React client-side SPA with no SSR framework, so SSR configuration is not applicable. Wallet state persistence is now handled by the Dynamic Labs SDK (@dynamic-labs/wagmi-connector), while app-level state uses Zustand with localStorage (inchatStore.ts). ThewagmiConfigitself does not need additional storage or SSR options.apps/agentic-chat/src/utils/sendTransaction.ts (1)
4-13: LGTM! Clean type migration from provider to signer model.The parameter rename from
solanaProvidertosolanaSigneraligns well with the newSolanaWalletSignerinterface that exposes onlysignTransaction, reflecting the narrower API surface from Dynamic Labs.apps/agentic-chat/src/hooks/usePortfolioQuery.ts (1)
18-31: Behavioral change: portfolio now scoped to primary wallet only.The previous implementation likely fetched portfolios for both connected wallet types. Now only the primary wallet's portfolio is fetched. This appears intentional but worth confirming.
Additionally,
evmAddressToFetchandsolanaAddressToFetchare captured in thequeryFnclosure but aren't included in the query key. If these values change mid-query, the query could use stale addresses while React Query thinks the result is still valid forprimaryAddress.Consider including the derived addresses in the query key for consistency:
- const queryKey = useMemo(() => ['portfolio', primaryAddress] as const, [primaryAddress]) + const queryKey = useMemo( + () => ['portfolio', primaryAddress, evmAddressToFetch, solanaAddressToFetch] as const, + [primaryAddress, evmAddressToFetch, solanaAddressToFetch] + )apps/agentic-chat/src/hooks/useSwapExecution.tsx (3)
201-205: Solana signer retrieval looks correct.The
await solanaWallet.getSigner()properly handles the async nature of signer retrieval from Dynamic Labs SDK.
278-280: Good fix: explicit chainId for public client.Passing
chainId: Number(chainReference)ensures the correct chain's public client is used for waiting on transaction receipt, avoiding potential cross-chain issues.
217-243: Wallet switching logic is well-structured and safe.The pattern of checking wallet type and conditionally switching primary wallet before network operations is correct. The early bail for missing EVM wallet (line 234-236) prevents runtime errors. Wallet references remain stable after
changePrimaryWallet— Dynamic Labs SDK updates which wallet is considered primary in its context, but does not mutate or recreate the underlying wallet objects. TheevmWalletreference captured at the start of the function continues to be valid for the subsequentswitchNetworkcall.apps/agentic-chat/src/hooks/useNetworkSwitch.ts (1)
139-183: EVM network switching logic is well-structured.The try-catch pattern with proper state persistence for both success and error cases is solid. The console logging aids debugging.
apps/agentic-chat/src/components/Portfolio/PortfolioDrawer.tsx (2)
1-7: Imports look correct for Dynamic Labs migration.The imports are well-organized, bringing in the necessary Dynamic Labs hooks and utility functions from the local
useWalletConnectionhook.
258-269: Second disconnect dialog implementation looks good.The per-wallet disconnect confirmation dialog properly manages state via
walletToDisconnectand clears it on cancel/close.apps/agentic-chat/src/hooks/useSendExecution.ts (3)
1-18: Imports correctly updated for Dynamic Labs SDK.The imports properly bring in the type guards (
isEthereumWallet,isSolanaWallet), context hooks, and the localSolanaWalletSignertype.
186-200: Solana wallet switching logic is correct.The code properly checks if the primary wallet is not a Solana wallet before switching, avoiding unnecessary wallet switches when already on Solana.
205-214: EVM wallet validation and network switch logic looks good.The code correctly validates EVM wallet presence and switches primary wallet when needed before performing network switch.
apps/agentic-chat/src/components/Portfolio/NetworkWalletRow.tsx
Outdated
Show resolved
Hide resolved
bea0509 to
034f99a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (6)
apps/agentic-chat/src/lib/wagmi-config.ts (1)
10-13: Custom RPC URLs from chain config are not being used.This issue was flagged in a previous review.
SUPPORTED_EVM_CHAINSdefines customrpcUrlvalues (e.g.,https://eth.llamarpc.com), but the transports use barehttp()which falls back to viem's default public RPCs.-const transports = Object.fromEntries(SUPPORTED_CHAIN_IDS.map(id => [id, http()])) as Record< +const transports = Object.fromEntries( + SUPPORTED_EVM_CHAINS.map(c => [c.chain.id, http(c.rpcUrl)]) +) as Record< (typeof SUPPORTED_CHAIN_IDS)[number], ReturnType<typeof http> >apps/agentic-chat/src/hooks/useNetworkSwitch.ts (1)
101-132: Bug: Solana network switching always fails due to falsy chainId check.This issue was flagged in a previous review. The
networkNameToChainIdmap assignssolana: 0(fromchains.ts). Since0is falsy in JavaScript, the check at line 104 (if (!targetChainId)) triggers for Solana before reaching the Solana-specific handling at line 113.Reorder the checks to handle Solana before the chainId validation, or change the check to
targetChainId === undefined:const { state } = useToolExecutionEffect(toolCallId, networkData, initialNetworkState, async (data, setState) => { + // Handle Solana first (chainId 0 is falsy) + if (data.network === 'solana') { + if (solanaWallet && primaryWallet && !isSolanaWallet(primaryWallet)) { + await changePrimaryWallet(solanaWallet.id) + } + setState(draft => { + draft.phase = 'success' + }) + if (activeConversationId) { + const persisted = networkStateToPersistedState( + toolCallId, + { phase: 'success' }, + activeConversationId, + data.network, + data + ) + store.persistTransaction(persisted) + } + return + } + const targetChainId = networkNameToChainId[data.network] - if (!targetChainId) { + if (targetChainId === undefined) { setState(draft => { draft.phase = 'error' draft.error = `Network "${data.network}" not found` }) return } - - // Solana doesn't need network switching in the same way, but we might need to switch primary wallet - if (data.network === 'solana') { - // ... move this block before the chainId check - }apps/agentic-chat/src/utils/chains/solana/transaction.ts (1)
81-83: Type assertion can be removed.This was flagged in a previous review. The
SolanaWalletSignerinterface definessignTransactionas a generic method that correctly infersVersionedTransactionas the return type, making this assertion redundant.- const signedTx = await (signer.signTransaction as (tx: VersionedTransaction) => Promise<VersionedTransaction>)( - transaction - ) + const signedTx = await signer.signTransaction(transaction)apps/agentic-chat/src/hooks/useApprovedChains.ts (1)
9-23:useMemodependency onuserWalletsis likely ineffective.
useApprovedChainsmemoizes onuserWallets, butuseUserWallets()does not guarantee referential stability and may return a new array each render, causing the memo to recompute every time and negating its benefit. The logic is correct; this is mainly about efficiency and intent clarity.Consider using a stable derived key as the dependency, for example:
- Derive a wallet IDs key once:
const walletKey = useMemo( () => userWallets.map(w => w.id).join(','), [userWallets], )- Then memoize chain IDs off that:
return useMemo(() => { const chainIds: string[] = [] if (filterEvmWallets(userWallets).length > 0) chainIds.push(...EVM_CAIP_IDS) if (filterSolanaWallets(userWallets).length > 0) chainIds.push(SOLANA_CAIP_ID) return chainIds }, [walletKey])This keeps behavior identical while making
useMemoactually effective. Based on learnings and prior review notes.apps/agentic-chat/src/components/Portfolio/NetworkWalletRow.tsx (1)
14-16: Remove or fix the extrarole="button"wrapper aroundCopyButton.The new
isActivebadge and click/propagation logic look fine, but theCopyButtonwrapper here:{address && ( <div onClick={e => e.stopPropagation()} onKeyDown={e => e.stopPropagation()} role="button" tabIndex={0}> <CopyButton value={address} className="text-muted-foreground hover:text-foreground" /> </div> )}still has the same accessibility issue previously flagged:
- It declares
role="button"andtabIndex={0}but never triggers any action on Enter/Space; it only callsstopPropagation.CopyButtonitself already handlese.stopPropagation()on click and is a proper button viaIconButton, so this wrapper is redundant and introduces an extra, non-functional focus target.Suggested fix:
- Simplest: remove the wrapper and render
CopyButtondirectly, relying on its internalstopPropagation().- If a wrapper is required for layout, drop
role="button"andtabIndexfrom the wrapper, or implement proper keyboard activation that forwards to the inner button while still stopping propagation.Also applies to: 31-49, 55-58
apps/agentic-chat/src/hooks/useSendExecution.ts (1)
1-3: Solana signer typing still diverges from Dynamic Labs’getSigner()return type.You’re importing a local
SolanaWalletSignerand assigning the result ofawait solanaWallet.getSigner()to it:import type { SolanaWalletSigner } from '@/utils/chains/types' // ... let solanaSigner: SolanaWalletSigner | undefined if (chainNamespace === CHAIN_NAMESPACE.Solana && solanaWallet) { solanaSigner = await solanaWallet.getSigner() }Per earlier review and Dynamic’s v4.49.0 docs,
getSigner()returns Dynamic’s own Solana signer type (e.g.ISolanaSignerfrom@dynamic-labs/solana-core), which exposes additional methods beyondsignTransaction. Relying on a narrower, homegrownSolanaWalletSignerinterface is structurally valid in TypeScript, but it can drift from the actual SDK type over time and obscure breaking changes.To keep things aligned while preserving your abstraction, consider either:
- Importing and using the SDK type directly here (
ISolanaSigner), or- Making
SolanaWalletSignerin@/utils/chains/typesa type alias (orextends) of the Dynamic SDK’s signer type, so all call sites stay in sync with the upstream signature.This is the same concern raised in the previous review; addressing it once will make future Dynamic upgrades safer.
Also applies to: 14-15, 224-231
🧹 Nitpick comments (4)
apps/agentic-chat/src/components/Portfolio/PortfolioDrawer.tsx (2)
1-8: Dynamic wallet wiring and derived state look solid; small optimization for wallet grouping.The integration with Dynamic (
useDynamicContext,useSwitchWallet,useDynamicModals,useUserWallets,useWalletConnection) plusdisplayAddress/truncatedAddressand primary/chain‑specific wallet icons is cohesive and matches the rest of the PR. The connect flow (closing the drawer, then either linking a new wallet or starting auth) is also clean.For
walletGroups, you currently recompute EVM/Solana classification inside theotherWalletsfilter by callingfilterEvmWallets([w])/filterSolanaWallets([w])per wallet. You could avoid repeated work and keep the classification logic in one place by computing the filtered lists once and deriving “other” from them, e.g.:const walletGroups = useMemo(() => { const evmWallets = filterEvmWallets(userWallets) const solanaWallets = filterSolanaWallets(userWallets) const evmIds = new Set(evmWallets.map(w => w.id)) const solanaIds = new Set(solanaWallets.map(w => w.id)) const otherWallets = userWallets.filter(w => !evmIds.has(w.id) && !solanaIds.has(w.id)) return { evmWallets, solanaWallets, otherWallets } }, [userWallets])This is purely an optimization/readability tweak; current behavior is correct.
Also applies to: 33-55, 64-77, 79-93
57-63: Per‑wallet disconnect UX works; consider handling async errors and avoiding dual‑dialog overlap.The per‑wallet rows and dialogs are wired correctly: selecting a wallet updates the primary via
changePrimaryWallet, andwalletToDisconnect+ the secondaryAlertDialogprovide a clear, scoped disconnect flow.Two small refinements to consider:
handleWalletDisconnectcallsvoid removeWallet(walletToDisconnect)and ignores the result. IfremoveWalletis async and can fail, you may want toawaitit inside atry/catch(and potentially show a toast) to avoid unhandled rejections and give users feedback when a disconnect fails.- Because you now have both a “global logout” dialog (
showDisconnectAlert) and a per‑wallet dialog (walletToDisconnect), it’s possible for both to be triggered in quick succession. If that’s not desired, you could, for example, clearwalletToDisconnectinsidehandleDisconnector disable the global power button whilewalletToDisconnectis set.These are UX/resilience polish items; the current logic is otherwise sound.
Also applies to: 110-137, 138-161, 163-186, 189-192, 254-265
apps/agentic-chat/src/hooks/useWalletConnection.ts (2)
10-31: Helper filters/finders are correct; you may be able to drop the extraWalletcast.
findEvmWallet/findSolanaWallet/filterEvmWallets/filterSolanaWalletsare nicely factored and give you strong typing for Ethereum vs Solana wallets.If
useUserWallets()indeed returnsWallet[]from@dynamic-labs/sdk-react-core, yourDynamicWalletalias is already compatible withWallet, and you may be able to invoke the type guards directly:return wallets.find((w): w is EthereumWallet => isEthereumWallet(w))instead of casting
w as Walletfirst. Dropping the cast tightens types slightly and avoids a possible future mismatch ifDynamicWallet’s shape diverges fromWallet.
1-6: Avoid the circular dependency betweenuseWalletConnectionanduseApprovedChainsby extracting wallet helpers.
useWalletConnectionimportsuseApprovedChains, anduseApprovedChains(per the provided snippet) importsfilterEvmWallets/filterSolanaWalletsfrom this same module. This circular dependency is safe today because neither hook is invoked at module top level, but it does couple the modules and can become brittle as more logic is added.A cleaner structure would be:
- Move
DynamicWallet,findEvmWallet,findSolanaWallet,filterEvmWallets,filterSolanaWallets, and maybegetWalletIconinto a small shared utility module (e.g.walletUtils.ts) or a dedicated shared package, and- Have both
useWalletConnectionanduseApprovedChainsimport from that utility.That breaks the cycle and keeps wallet‑classification logic in one place, which should scale better as you add more chain types and consumers. Based on learnings, this also aligns with your preference to centralize shared cross‑app logic into dedicated packages/utilities.
Also applies to: 8-9, 32-40, 42-66
📜 Review details
Configuration used: CodeRabbit 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.
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (30)
.env.example(1 hunks).env.production(1 hunks)apps/agentic-chat/package.json(1 hunks)apps/agentic-chat/src/app/app.tsx(2 hunks)apps/agentic-chat/src/components/CustomConnectButton.tsx(3 hunks)apps/agentic-chat/src/components/Portfolio/NetworkWalletRow.tsx(2 hunks)apps/agentic-chat/src/components/Portfolio/PortfolioDrawer.tsx(4 hunks)apps/agentic-chat/src/components/tools/InitiateSwapUI.tsx(1 hunks)apps/agentic-chat/src/components/tools/SendUI.tsx(1 hunks)apps/agentic-chat/src/hooks/useApprovedChains.ts(1 hunks)apps/agentic-chat/src/hooks/useAutoNetworkSwitch.ts(0 hunks)apps/agentic-chat/src/hooks/useNetworkSwitch.ts(3 hunks)apps/agentic-chat/src/hooks/usePortfolioQuery.ts(2 hunks)apps/agentic-chat/src/hooks/useSendExecution.ts(5 hunks)apps/agentic-chat/src/hooks/useSwapExecution.tsx(8 hunks)apps/agentic-chat/src/hooks/useWalletConnection.ts(1 hunks)apps/agentic-chat/src/lib/appkit.ts(0 hunks)apps/agentic-chat/src/lib/chains.ts(1 hunks)apps/agentic-chat/src/lib/networks.ts(0 hunks)apps/agentic-chat/src/lib/solana-config.ts(0 hunks)apps/agentic-chat/src/lib/wagmi-config.ts(1 hunks)apps/agentic-chat/src/types/appkit.d.ts(0 hunks)apps/agentic-chat/src/utils/chains/evm/transaction.ts(2 hunks)apps/agentic-chat/src/utils/chains/solana/transaction.ts(2 hunks)apps/agentic-chat/src/utils/chains/types.ts(1 hunks)apps/agentic-chat/src/utils/sendExecutor.ts(2 hunks)apps/agentic-chat/src/utils/sendTransaction.ts(2 hunks)apps/agentic-chat/src/utils/swapExecutor.ts(2 hunks)apps/agentic-chat/vite.config.mjs(1 hunks)package.json(1 hunks)
💤 Files with no reviewable changes (5)
- apps/agentic-chat/src/lib/appkit.ts
- apps/agentic-chat/src/lib/solana-config.ts
- apps/agentic-chat/src/lib/networks.ts
- apps/agentic-chat/src/types/appkit.d.ts
- apps/agentic-chat/src/hooks/useAutoNetworkSwitch.ts
🚧 Files skipped from review as they are similar to previous changes (9)
- apps/agentic-chat/src/components/tools/InitiateSwapUI.tsx
- .env.production
- apps/agentic-chat/src/app/app.tsx
- apps/agentic-chat/vite.config.mjs
- apps/agentic-chat/src/lib/chains.ts
- apps/agentic-chat/src/utils/sendTransaction.ts
- apps/agentic-chat/src/utils/chains/evm/transaction.ts
- apps/agentic-chat/src/components/tools/SendUI.tsx
- .env.example
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-09-16T20:28:23.547Z
Learnt from: premiumjibles
Repo: shapeshift/agentic-chat PR: 68
File: apps/agentic-server/package.json:26-26
Timestamp: 2025-09-16T20:28:23.547Z
Learning: In the ShapeShift agentic-chat codebase, mathjs optimization (lazy-loading or using modular sub-packages) has been noted for future implementation rather than immediate action.
Applied to files:
apps/agentic-chat/src/hooks/useApprovedChains.ts
📚 Learning: 2025-09-22T20:32:10.539Z
Learnt from: kaladinlight
Repo: shapeshift/agentic-chat PR: 76
File: apps/agentic-server/src/mastra/tools/asset/coingecko/constants.ts:1-10
Timestamp: 2025-09-22T20:32:10.539Z
Learning: When cross-app dependencies are identified (like server code importing from chat packages), the user prefers to extract shared constants into dedicated packages in the packages/ directory following the existing pattern of shapeshiftoss/types and shapeshiftoss/utils.
Applied to files:
apps/agentic-chat/src/hooks/useSendExecution.ts
🧬 Code graph analysis (12)
apps/agentic-chat/src/lib/wagmi-config.ts (1)
apps/agentic-chat/src/lib/chains.ts (2)
SUPPORTED_EVM_CHAINS(15-88)SUPPORTED_CHAIN_IDS(94-97)
apps/agentic-chat/src/hooks/useNetworkSwitch.ts (3)
apps/agentic-chat/src/hooks/useWalletConnection.ts (1)
useWalletConnection(42-67)apps/agentic-chat/src/hooks/useToolExecutionEffect.ts (1)
useToolExecutionEffect(10-57)apps/agentic-chat/src/lib/chains.ts (1)
networkNameToChainId(103-106)
apps/agentic-chat/src/utils/sendExecutor.ts (1)
apps/agentic-chat/src/utils/chains/types.ts (1)
SolanaWalletSigner(8-10)
apps/agentic-chat/src/components/CustomConnectButton.tsx (4)
apps/agentic-chat/src/hooks/useWalletConnection.ts (2)
useWalletConnection(42-67)getWalletIcon(28-30)apps/agentic-chat/src/lib/utils.ts (1)
truncateAddress(9-12)apps/agentic-chat/src/lib/chains.ts (1)
SOLANA_CAIP_ID(90-90)packages/utils/src/networkIcons.ts (1)
NETWORK_ICONS(14-31)
apps/agentic-chat/src/hooks/useWalletConnection.ts (2)
apps/agentic-chat/src/types/wallet.ts (1)
Wallet(1-6)apps/agentic-chat/src/hooks/useApprovedChains.ts (1)
useApprovedChains(8-24)
apps/agentic-chat/src/hooks/useApprovedChains.ts (2)
apps/agentic-chat/src/hooks/useWalletConnection.ts (2)
filterEvmWallets(20-22)filterSolanaWallets(24-26)apps/agentic-chat/src/lib/chains.ts (2)
EVM_CAIP_IDS(108-108)SOLANA_CAIP_ID(90-90)
apps/agentic-chat/src/components/Portfolio/NetworkWalletRow.tsx (3)
apps/agentic-chat/src/lib/utils.ts (1)
truncateAddress(9-12)apps/agentic-chat/src/components/ui/CopyButton.tsx (1)
CopyButton(15-41)apps/agentic-chat/src/components/ui/IconButton.tsx (1)
IconButton(22-29)
apps/agentic-chat/src/components/Portfolio/PortfolioDrawer.tsx (6)
apps/agentic-chat/src/hooks/useWalletConnection.ts (4)
useWalletConnection(42-67)getWalletIcon(28-30)filterEvmWallets(20-22)filterSolanaWallets(24-26)apps/agentic-chat/src/hooks/usePortfolioQuery.ts (1)
usePortfolioQuery(14-49)apps/agentic-chat/src/lib/utils.ts (1)
truncateAddress(9-12)apps/agentic-chat/src/components/ui/DropdownMenu.tsx (3)
DropdownMenuTrigger(206-206)DropdownMenuContent(207-207)DropdownMenuSeparator(214-214)apps/agentic-chat/src/components/Portfolio/NetworkWalletRow.tsx (1)
NetworkWalletRow(19-72)apps/agentic-chat/src/components/ui/AlertDialog.tsx (8)
AlertDialog(93-93)AlertDialogContent(97-97)AlertDialogHeader(98-98)AlertDialogTitle(100-100)AlertDialogDescription(101-101)AlertDialogFooter(99-99)AlertDialogCancel(103-103)AlertDialogAction(102-102)
apps/agentic-chat/src/utils/swapExecutor.ts (1)
apps/agentic-chat/src/utils/chains/types.ts (1)
SolanaWalletSigner(8-10)
apps/agentic-chat/src/hooks/useSwapExecution.tsx (4)
apps/agentic-chat/src/hooks/useWalletConnection.ts (1)
useWalletConnection(42-67)apps/agentic-chat/src/utils/chains/types.ts (1)
SolanaWalletSigner(8-10)packages/caip/src/constants.ts (1)
CHAIN_NAMESPACE(46-54)apps/agentic-chat/src/lib/wagmi-config.ts (1)
wagmiConfig(15-19)
apps/agentic-chat/src/hooks/useSendExecution.ts (5)
apps/agentic-chat/src/hooks/useWalletConnection.ts (1)
useWalletConnection(42-67)apps/agentic-chat/src/stores/chatStore.ts (1)
useChatStore(69-188)packages/caip/src/constants.ts (1)
CHAIN_NAMESPACE(46-54)apps/agentic-chat/src/utils/chains/types.ts (1)
SolanaWalletSigner(8-10)apps/agentic-server/src/tools/send.ts (1)
executeSend(24-71)
apps/agentic-chat/src/utils/chains/types.ts (2)
apps/agentic-chat/src/types/transaction.ts (1)
Transaction(1-10)packages/caip/src/constants.ts (1)
ChainId(175-175)
⏰ 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). (1)
- GitHub Check: main
🔇 Additional comments (12)
apps/agentic-chat/package.json (1)
16-21: LGTM!The Dynamic Labs dependencies are consistently versioned at
^4.49.0, which is appropriate for a coordinated SDK migration. The caret range allows compatible updates while maintaining version alignment across the Dynamic Labs packages.apps/agentic-chat/src/lib/wagmi-config.ts (1)
15-19: LGTM!The
createConfigsetup withmultiInjectedProviderDiscovery: falseis appropriate when using Dynamic Labs, as Dynamic handles wallet discovery through its own mechanisms.apps/agentic-chat/src/hooks/useNetworkSwitch.ts (1)
139-166: LGTM!The EVM network switching logic correctly handles primary wallet switching when the current wallet is Solana, validates EVM wallet availability, and uses Dynamic's connector for network switching with proper error handling and state persistence.
apps/agentic-chat/src/utils/chains/solana/transaction.ts (1)
40-46: LGTM!The signer acquisition with fallback to
window.solanaprovides backwards compatibility while supporting the new Dynamic Labs signer pattern. The inline type annotation forwindow.solanacorrectly constrains the expected interface.package.json (1)
62-64: The Solana web3.js version override is intentional and necessary.The override to
1.98.1is required because Dynamic Labs packages (v4.49.0) have fixed dependencies on this version. Multiple Dynamic Labs packages (@dynamic-labs/solana,@dynamic-labs/solana-core,@dynamic-labs/embedded-wallet-solana, and@dynamic-labs/waas-svm) explicitly require@solana/[email protected], while the direct dependencies specify^1.95.8and^1.95.2. The override correctly resolves this conflict, as confirmed by the migration commit ("feat: migrate from reown to dynamic"). All API usage (Connection, PublicKey, TransactionMessage, etc.) is compatible across the minor version range.apps/agentic-chat/src/utils/swapExecutor.ts (1)
4-13: Solana signer wiring in swap executor looks consistent.
ExecuteTransactionOptionsandfinalTxnow correctly carrysolanaSigner?: SolanaWalletSigner, matching the updatedTransactionParamsshape and keeping EVM behavior unchanged when no signer is passed.Also applies to: 28-32
apps/agentic-chat/src/utils/sendExecutor.ts (1)
4-12: Send executor’s Solana signer integration is consistent.The
solanaSigner?: SolanaWalletSigneroption is cleanly threaded intofinalTxand only attached when present, preserving existing EVM behavior while enabling Solana signing via the shared transaction adapter.Also applies to: 21-32
apps/agentic-chat/src/utils/chains/types.ts (1)
6-23: Solana signer abstraction andTransactionParamsupdate look sound.Defining
SolanaWalletSignerwithsignTransactionand threading it intoTransactionParams.solanaSigner?(plus theSolanaWalletProvideralias for back-compat) provides a clear, minimal surface for Solana signing while keeping adapters generic over chain. Internal call sites that passsolanaSigner(send/swap executors) align with this shape.apps/agentic-chat/src/components/CustomConnectButton.tsx (1)
16-20: Dynamic wallet wiring and CAIP-based network icon look correct.
- Address selection (
primaryWallet?.address ?? evmAddress ?? solanaAddress) gracefully prefers the dynamic primary wallet while still falling back to chain-specific addresses.isPrimarySolana+SOLANA_CAIP_IDvseip155:${chainId}matches theNETWORK_ICONSCAIP key scheme, so EVM vs Solana network icons should render as expected.setShowAuthFlow(true)is an appropriate replacement for the prior connect flow, andonConnectedClickremains isolated from the connect button viahandleOpenAccount.No functional issues stand out here.
Also applies to: 39-49, 53-58
apps/agentic-chat/src/hooks/useSwapExecution.tsx (2)
18-19: Wallet context and primary-wallet switching integration is coherent.
useSwapExecutionnow:
- Pulls
evmAddress,solanaAddress,evmWallet, andsolanaWalletfromuseWalletConnection.- Reads
primaryWalletpluschangePrimaryWalletfrom Dynamic context.The resulting logic cleanly distinguishes EVM vs Solana flows and ensures a concrete wallet is available before progressing, with primary wallet switching handled explicitly where needed. This keeps the swap-step state machine intact while aligning it with the new Dynamic-based wallet model.
Also applies to: 159-165
201-205: Solana signer acquisition and EVM/Solana execution paths look robust.Key points in the execution effect:
For Solana:
- Lazily obtains
solanaSignerviasolanaWallet.getSigner()only whenchainNamespace === CHAIN_NAMESPACE.Solanaand a Solana wallet exists.- Ensures the active address matches
swapTx.frombefore proceeding.- Skips the EVM-specific approval confirmation step while still passing
solanaSignerto bothexecuteApprovalandexecuteSwap.For EVM:
- Guards against missing
evmWalletbefore switching networks.- If the primary wallet isn’t EVM, switches the primary to
evmWallet.idbefore callingevmWallet.connector.switchNetwork({ networkChainId: sellChainIdNumber }).- Uses
getPublicClient(wagmiConfig, { chainId: Number(chainReference) })andwaitForTransactionReceiptonly for EVM approvals.Shared:
- Both approval and swap execution now receive
{ solanaSigner }, which is defined only for Solana, so EVM paths ignore it without behavioral change.Overall, the signer handling and chain-conditional branching are consistent with the updated
SolanaWalletSignerabstraction and avoid obvious race or mismatch conditions.Also applies to: 217-225, 234-240, 243-244, 254-256, 278-280, 301-303
apps/agentic-chat/src/hooks/useSendExecution.ts (1)
136-141: Network switching and primary‑wallet alignment logic look correct for EVM vs Solana.Using
useWalletConnection()to deriveevmAddress/solanaAddressandevmWallet/solanaWallet, then:
- Verifying
currentAddressagainsttx.from,- Switching the primary wallet to Solana when
chainNamespace === CHAIN_NAMESPACE.Solanabut the currentprimaryWalletisn’t Solana, and- On EVM, ensuring
evmWalletexists, promoting it toprimaryWalletwhen necessary, and then callingevmWallet.connector.switchNetwork({ networkChainId }),gives a coherent story that should prevent mismatches between the active wallet/network and the transaction being executed.
No functional issues stand out here; just ensure the non‑EVM branches you support (currently Solana) remain in sync with how
executeSendexpects its wallet context.Also applies to: 184-221
034f99a to
1ca0b23
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (5)
apps/agentic-chat/src/utils/chains/solana/transaction.ts (1)
81-83: Remove unnecessary type assertion.The
SolanaWalletSignerinterface definessignTransactionas a generic method that infers the return type from the input type. When called withVersionedTransaction, TypeScript automatically infers the return type asPromise<VersionedTransaction>, making the type assertion redundant.- const signedTx = await (signer.signTransaction as (tx: VersionedTransaction) => Promise<VersionedTransaction>)( - transaction - ) + const signedTx = await signer.signTransaction(transaction)apps/agentic-chat/src/components/Portfolio/NetworkWalletRow.tsx (1)
34-36: Accessibility issue: Remove wrapper with incomplete button semantics.The wrapper div has
role="button"andtabIndex={0}but only stops propagation on keydown without handling Enter/Space activation. SinceCopyButtonalready handlesstopPropagationinternally (seeCopyButton.tsxline 18), this wrapper is unnecessary and creates an inaccessible button for keyboard users.{address && ( - <div onClick={e => e.stopPropagation()} onKeyDown={e => e.stopPropagation()} role="button" tabIndex={0}> - <CopyButton value={address} className="text-muted-foreground hover:text-foreground" /> - </div> + <div onClick={e => e.stopPropagation()}> + <CopyButton value={address} className="text-muted-foreground hover:text-foreground" /> + </div> )}apps/agentic-chat/src/hooks/useNetworkSwitch.ts (1)
102-132: Critical: Solana network switching still fails due to falsy chainId check.The past review marked this as addressed, but the code still shows the problematic pattern. At line 104,
if (!targetChainId)treats chainId0(Solana fromnetworkNameToChainId.solana = 0) as falsy, causing the error at lines 105-109 to execute before the Solana-specific handling at lines 113-132.Reorder to check Solana first, before validating chainId:
const { state } = useToolExecutionEffect(toolCallId, networkData, initialNetworkState, async (data, setState) => { + // Solana doesn't need network switching in the same way, but we might need to switch primary wallet + if (data.network === 'solana') { + const targetChainId = networkNameToChainId[data.network] + if (targetChainId === undefined) { + setState(draft => { + draft.phase = 'error' + draft.error = `Network "${data.network}" not found` + }) + return + } + + if (solanaWallet && primaryWallet && !isSolanaWallet(primaryWallet)) { + await changePrimaryWallet(solanaWallet.id) + } + + setState(draft => { + draft.phase = 'success' + }) + if (activeConversationId) { + const persisted = networkStateToPersistedState( + toolCallId, + { phase: 'success' }, + activeConversationId, + data.network, + data + ) + store.persistTransaction(persisted) + } + return + } + const targetChainId = networkNameToChainId[data.network] - if (!targetChainId) { + if (targetChainId === undefined) { setState(draft => { draft.phase = 'error' draft.error = `Network "${data.network}" not found` }) return } - // Solana doesn't need network switching in the same way... - if (data.network === 'solana') { - ... - }apps/agentic-chat/src/lib/wagmi-config.ts (1)
10-13: Custom RPC URLs from chain config are still not being used.
SUPPORTED_EVM_CHAINSdefines customrpcUrlvalues (e.g.,https://eth.llamarpc.com), but the transports still use barehttp()which falls back to viem's default public RPCs. This may cause rate limiting or reliability issues.Apply this diff to use the custom RPC URLs:
-const transports = Object.fromEntries(SUPPORTED_CHAIN_IDS.map(id => [id, http()])) as Record< +const transports = Object.fromEntries( + SUPPORTED_EVM_CHAINS.map(c => [c.chain.id, http(c.rpcUrl)]) +) as Record< (typeof SUPPORTED_CHAIN_IDS)[number], ReturnType<typeof http> >apps/agentic-chat/src/hooks/useSendExecution.ts (1)
224-230: Type annotation uses localSolanaWalletSignerrather than SDK type.As noted in a previous review, the Dynamic Labs SDK returns
ISolanaSignerfromgetSigner(). While structurally compatible, using the SDK's type would provide stronger type guarantees.This is the same pattern flagged in
useSwapExecution.tsx. Consider importingISolanaSignerfrom@dynamic-labs/solana-corefor both files.
🧹 Nitpick comments (7)
apps/agentic-chat/src/app/app.tsx (1)
41-51: Consider validating the environment variable.The
VITE_DYNAMIC_ENVIRONMENT_IDis passed directly toDynamicContextProviderwithout validation. If this environment variable is missing or invalid, the application will fail at runtime with potentially unclear errors.Add validation before the return statement:
function App() { const dynamicEnvironmentId = import.meta.env.VITE_DYNAMIC_ENVIRONMENT_ID if (!dynamicEnvironmentId) { console.error('VITE_DYNAMIC_ENVIRONMENT_ID is not configured') return <div>Configuration error: Missing Dynamic environment ID</div> } return ( <DynamicContextProvider // ... settings={{ environmentId: dynamicEnvironmentId, // ...apps/agentic-chat/src/components/Portfolio/PortfolioDrawer.tsx (2)
43-55: Consider awaiting query invalidation before logout.The
handleDisconnectfunction callsinvalidateQuerieswith.catch(console.error)but doesn't await them before callinghandleLogOut(). This could lead to a race condition where the logout completes before cache invalidation.const handleDisconnect = useCallback(() => { - queryClient.invalidateQueries({ queryKey: ['portfolio'] }).catch(console.error) - queryClient.invalidateQueries({ queryKey: ['approvedChains'] }).catch(console.error) - - handleLogOut() + Promise.all([ + queryClient.invalidateQueries({ queryKey: ['portfolio'] }), + queryClient.invalidateQueries({ queryKey: ['approvedChains'] }), + ]) + .catch(console.error) + .then(() => handleLogOut()) .catch(error => { console.error('Failed to disconnect wallet:', error) }) .finally(() => { setShowDisconnectAlert(false) onClose() }) }, [queryClient, handleLogOut, onClose])
116-186: Consider extracting repeated wallet list rendering into a reusable component.The rendering logic for EVM, Solana, and Other wallet groups is nearly identical. This could be refactored into a single
WalletGroupcomponent to reduce duplication.// Example extracted component const WalletGroup = ({ label, wallets, primaryWallet, changePrimaryWallet, setWalletToDisconnect }) => ( wallets.length > 0 && ( <div className="mb-2"> <div className="px-2 py-1 text-xs font-medium text-muted-foreground/70 uppercase tracking-wider"> {label} </div> {wallets.map(wallet => ( <div key={wallet.id} className="relative"> <NetworkWalletRow label={wallet.connector.name} address={wallet.address} icon={getWalletIcon(wallet)} isActive={wallet.id === primaryWallet?.id} onConnect={() => { if (wallet.id !== primaryWallet?.id) { changePrimaryWallet(wallet.id).catch(console.error) } }} onDisconnect={() => setWalletToDisconnect(wallet.id)} /> </div> ))} </div> ) );apps/agentic-chat/src/lib/chains.ts (2)
15-88: Consider using environment variables or a config service for RPC URLs.The hardcoded public RPC endpoints (e.g.,
https://eth.llamarpc.com,https://polygon-rpc.com) may have rate limits in production. Consider making these configurable via environment variables or using a dedicated RPC provider.{ chain: mainnet, networkName: 'ethereum', caipId: 'eip155:1', iconUrl: 'https://app.dynamic.xyz/assets/networks/eth.svg', blockExplorerUrl: 'https://etherscan.io/', - rpcUrl: 'https://eth.llamarpc.com', + rpcUrl: import.meta.env.VITE_ETH_RPC_URL ?? 'https://eth.llamarpc.com', vanityName: 'Ethereum', }, // ... similar for other chains
103-106: Using0for Solana chain ID is unconventional but acceptable.The
solana: 0entry innetworkNameToChainIduses 0 as a sentinel value since Solana doesn't have an EVM-style numeric chain ID. Document this convention or consider usingnull/undefinedif consumers can handle it.export const networkNameToChainId: Record<string, number> = { ...Object.fromEntries(SUPPORTED_EVM_CHAINS.map(c => [c.networkName, c.chain.id])), - solana: 0, + solana: 0, // Sentinel value: Solana is not an EVM chain }apps/agentic-chat/src/hooks/useWalletConnection.ts (1)
32-40: Consider exportingWalletConnectionResultinterface.The interface is well-defined but not exported. If other components need to type their props or state based on this return type, exporting it would improve reusability.
-interface WalletConnectionResult { +export interface WalletConnectionResult { isConnected: boolean evmAddress: string | undefined solanaAddress: string | undefined primaryAddress: string | undefined approvedChainIds: string[] evmWallet: EthereumWallet | undefined solanaWallet: SolanaWallet | undefined }apps/agentic-chat/src/hooks/useSwapExecution.tsx (1)
201-205: Consider aligning type imports with SDK definitions for consistency.The code uses the local
SolanaWalletSignerinterface (which only definessignTransaction) rather than the SDK'sISolanaSignertype from@dynamic-labs/solana-core. While the current approach works sinceSolanaWalletSigneris a compatible subset, importingISolanaSignerwould align with SDK conventions and provide access to additional signer methods if needed in the future. This same pattern appears inuseSendExecution.ts.
📜 Review details
Configuration used: CodeRabbit 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.
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (30)
.env.example(1 hunks).env.production(1 hunks)apps/agentic-chat/package.json(1 hunks)apps/agentic-chat/src/app/app.tsx(2 hunks)apps/agentic-chat/src/components/CustomConnectButton.tsx(3 hunks)apps/agentic-chat/src/components/Portfolio/NetworkWalletRow.tsx(1 hunks)apps/agentic-chat/src/components/Portfolio/PortfolioDrawer.tsx(4 hunks)apps/agentic-chat/src/components/tools/InitiateSwapUI.tsx(1 hunks)apps/agentic-chat/src/components/tools/SendUI.tsx(1 hunks)apps/agentic-chat/src/hooks/useApprovedChains.ts(1 hunks)apps/agentic-chat/src/hooks/useAutoNetworkSwitch.ts(0 hunks)apps/agentic-chat/src/hooks/useNetworkSwitch.ts(3 hunks)apps/agentic-chat/src/hooks/usePortfolioQuery.ts(2 hunks)apps/agentic-chat/src/hooks/useSendExecution.ts(5 hunks)apps/agentic-chat/src/hooks/useSwapExecution.tsx(8 hunks)apps/agentic-chat/src/hooks/useWalletConnection.ts(1 hunks)apps/agentic-chat/src/lib/appkit.ts(0 hunks)apps/agentic-chat/src/lib/chains.ts(1 hunks)apps/agentic-chat/src/lib/networks.ts(0 hunks)apps/agentic-chat/src/lib/solana-config.ts(0 hunks)apps/agentic-chat/src/lib/wagmi-config.ts(1 hunks)apps/agentic-chat/src/types/appkit.d.ts(0 hunks)apps/agentic-chat/src/utils/chains/evm/transaction.ts(2 hunks)apps/agentic-chat/src/utils/chains/solana/transaction.ts(2 hunks)apps/agentic-chat/src/utils/chains/types.ts(1 hunks)apps/agentic-chat/src/utils/sendExecutor.ts(2 hunks)apps/agentic-chat/src/utils/sendTransaction.ts(2 hunks)apps/agentic-chat/src/utils/swapExecutor.ts(2 hunks)apps/agentic-chat/vite.config.mjs(1 hunks)package.json(1 hunks)
💤 Files with no reviewable changes (5)
- apps/agentic-chat/src/hooks/useAutoNetworkSwitch.ts
- apps/agentic-chat/src/lib/networks.ts
- apps/agentic-chat/src/lib/appkit.ts
- apps/agentic-chat/src/lib/solana-config.ts
- apps/agentic-chat/src/types/appkit.d.ts
🚧 Files skipped from review as they are similar to previous changes (4)
- apps/agentic-chat/src/components/tools/SendUI.tsx
- .env.example
- apps/agentic-chat/package.json
- apps/agentic-chat/src/utils/chains/evm/transaction.ts
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-09-16T20:28:23.547Z
Learnt from: premiumjibles
Repo: shapeshift/agentic-chat PR: 68
File: apps/agentic-server/package.json:26-26
Timestamp: 2025-09-16T20:28:23.547Z
Learning: In the ShapeShift agentic-chat codebase, mathjs optimization (lazy-loading or using modular sub-packages) has been noted for future implementation rather than immediate action.
Applied to files:
apps/agentic-chat/src/hooks/useApprovedChains.ts
📚 Learning: 2025-09-22T20:32:10.539Z
Learnt from: kaladinlight
Repo: shapeshift/agentic-chat PR: 76
File: apps/agentic-server/src/mastra/tools/asset/coingecko/constants.ts:1-10
Timestamp: 2025-09-22T20:32:10.539Z
Learning: When cross-app dependencies are identified (like server code importing from chat packages), the user prefers to extract shared constants into dedicated packages in the packages/ directory following the existing pattern of shapeshiftoss/types and shapeshiftoss/utils.
Applied to files:
apps/agentic-chat/src/hooks/useSendExecution.ts
🧬 Code graph analysis (15)
apps/agentic-chat/src/utils/chains/types.ts (1)
packages/caip/src/constants.ts (1)
ChainId(175-175)
apps/agentic-chat/src/hooks/useApprovedChains.ts (2)
apps/agentic-chat/src/lib/chains.ts (2)
EVM_CAIP_IDS(108-108)SOLANA_CAIP_ID(90-90)apps/agentic-chat/src/types/wallet.ts (1)
Wallet(1-6)
apps/agentic-chat/src/utils/sendExecutor.ts (1)
apps/agentic-chat/src/utils/chains/types.ts (1)
SolanaWalletSigner(8-10)
apps/agentic-chat/src/utils/sendTransaction.ts (1)
apps/agentic-chat/src/utils/chains/types.ts (1)
SolanaWalletSigner(8-10)
apps/agentic-chat/src/utils/swapExecutor.ts (1)
apps/agentic-chat/src/utils/chains/types.ts (1)
SolanaWalletSigner(8-10)
apps/agentic-chat/src/hooks/useSwapExecution.tsx (3)
apps/agentic-chat/src/hooks/useWalletConnection.ts (1)
useWalletConnection(42-67)apps/agentic-chat/src/utils/chains/types.ts (1)
SolanaWalletSigner(8-10)packages/caip/src/constants.ts (1)
CHAIN_NAMESPACE(46-54)
apps/agentic-chat/src/components/Portfolio/PortfolioDrawer.tsx (4)
apps/agentic-chat/src/hooks/useWalletConnection.ts (4)
useWalletConnection(42-67)getWalletIcon(28-30)filterEvmWallets(20-22)filterSolanaWallets(24-26)apps/agentic-chat/src/hooks/usePortfolioQuery.ts (1)
usePortfolioQuery(14-49)apps/agentic-chat/src/lib/utils.ts (1)
truncateAddress(9-12)apps/agentic-chat/src/components/Portfolio/NetworkWalletRow.tsx (1)
NetworkWalletRow(17-52)
apps/agentic-chat/src/components/Portfolio/NetworkWalletRow.tsx (3)
apps/agentic-chat/src/lib/utils.ts (1)
truncateAddress(9-12)apps/agentic-chat/src/components/ui/CopyButton.tsx (1)
CopyButton(15-41)apps/agentic-chat/src/components/ui/IconButton.tsx (1)
IconButton(22-29)
apps/agentic-chat/src/hooks/useSendExecution.ts (4)
apps/agentic-chat/src/hooks/useWalletConnection.ts (1)
useWalletConnection(42-67)packages/caip/src/constants.ts (1)
CHAIN_NAMESPACE(46-54)apps/agentic-chat/src/utils/chains/types.ts (1)
SolanaWalletSigner(8-10)apps/agentic-chat/src/utils/sendExecutor.ts (1)
executeSend(34-40)
apps/agentic-chat/src/lib/wagmi-config.ts (1)
apps/agentic-chat/src/lib/chains.ts (2)
SUPPORTED_EVM_CHAINS(15-88)SUPPORTED_CHAIN_IDS(94-97)
apps/agentic-chat/src/app/app.tsx (2)
apps/agentic-chat/src/lib/chains.ts (1)
DYNAMIC_EVM_NETWORKS(110-120)apps/agentic-chat/src/lib/wagmi-config.ts (1)
wagmiConfig(15-19)
apps/agentic-chat/src/hooks/useWalletConnection.ts (2)
apps/agentic-chat/src/types/wallet.ts (1)
Wallet(1-6)apps/agentic-chat/src/hooks/useApprovedChains.ts (1)
useApprovedChains(54-68)
apps/agentic-chat/src/hooks/useNetworkSwitch.ts (3)
apps/agentic-chat/src/hooks/useWalletConnection.ts (1)
useWalletConnection(42-67)apps/agentic-chat/src/hooks/useToolExecutionEffect.ts (1)
useToolExecutionEffect(10-57)apps/agentic-chat/src/lib/chains.ts (1)
networkNameToChainId(103-106)
apps/agentic-chat/src/components/CustomConnectButton.tsx (4)
apps/agentic-chat/src/hooks/useWalletConnection.ts (2)
useWalletConnection(42-67)getWalletIcon(28-30)apps/agentic-chat/src/lib/utils.ts (1)
truncateAddress(9-12)apps/agentic-chat/src/lib/chains.ts (1)
SOLANA_CAIP_ID(90-90)packages/utils/src/networkIcons.ts (1)
NETWORK_ICONS(14-31)
apps/agentic-chat/src/hooks/usePortfolioQuery.ts (2)
apps/agentic-chat/src/hooks/useWalletConnection.ts (1)
useWalletConnection(42-67)apps/agentic-chat/src/services/portfolioService.ts (1)
fetchFullPortfolio(31-102)
⏰ 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). (1)
- GitHub Check: main
🔇 Additional comments (31)
.env.production (1)
25-26: LGTM!The environment variable rename from
VITE_PROJECT_IDtoVITE_DYNAMIC_ENVIRONMENT_IDaligns with the migration to Dynamic Labs and is properly documented.apps/agentic-chat/src/components/Portfolio/NetworkWalletRow.tsx (1)
17-51: LGTM with one accessibility concern.The component refactor simplifies the UI by making the entire row clickable for connection. The Active badge provides clear visual feedback, and the disconnect button properly stops propagation. The structure is clean and the logic is sound, pending resolution of the accessibility issue flagged above.
apps/agentic-chat/src/utils/chains/types.ts (2)
6-13: LGTM!The
SolanaWalletSignerinterface provides a clean abstraction for Solana wallet signing, with proper typing for both transaction types. The backward compatibility alias and inline documentation are helpful.
22-22: LGTM!The parameter rename from
solanaProvidertosolanaSigneraccurately reflects the new interface and improves clarity.apps/agentic-chat/src/hooks/useNetworkSwitch.ts (1)
139-183: LGTM!The EVM network switching logic with Dynamic connector is well-structured. The try-catch block properly handles errors, persists state, and switches wallets when needed. The console logs aid debugging.
apps/agentic-chat/src/components/tools/InitiateSwapUI.tsx (1)
19-19: LGTM!Deriving the address from
swapOutput?.swapData.sellAccountis more direct and aligns with the migration away from AppKit. The swap data is the authoritative source for the account performing the swap.apps/agentic-chat/src/utils/chains/solana/transaction.ts (1)
40-46: LGTM!The signer source now correctly uses
params.solanaSignerwith a fallback towindow.solana, properly typed with theSolanaWalletSignerinterface. The validation logic is sound.apps/agentic-chat/vite.config.mjs (1)
9-12: Theprocess.envstubbing is safe and appropriate for this browser-based application.The codebase already uses
import.meta.envfor all environment variable access (e.g.,VITE_AGENTIC_SERVER_BASE_URL,VITE_ENABLE_ANALYTICS,VITE_SOLANA_RPC_URL,VITE_DYNAMIC_ENVIRONMENT_ID), which is Vite's standard runtime approach for browser builds. No client-side code or dependencies rely onprocess.envdirectly, making the empty object stub safe and correct.apps/agentic-chat/src/utils/sendTransaction.ts (1)
4-4: LGTM! Type migration is consistent.The migration from
SolanaWalletProvidertoSolanaWalletSigneraligns with the broader shift to signer-based APIs. The type interface provides the necessarysignTransactionmethod.Also applies to: 13-13
apps/agentic-chat/src/utils/swapExecutor.ts (1)
4-4: LGTM! Consistent signer migration.The type and property changes are consistent with the signer-based approach across transaction utilities.
Also applies to: 12-12, 28-28
apps/agentic-chat/src/utils/sendExecutor.ts (1)
4-4: LGTM! Consistent with other executors.The migration follows the same signer-based pattern as swapExecutor.ts.
Also applies to: 11-11, 28-28
apps/agentic-chat/src/app/app.tsx (1)
52-68: LGTM! Provider structure is correct.The provider nesting follows the correct order: DynamicContextProvider → WagmiProvider → QueryClientProvider → DynamicWagmiConnector → App content. This ensures proper initialization and context availability.
apps/agentic-chat/src/components/CustomConnectButton.tsx (1)
18-50: LGTM! Dynamic wallet integration is well-structured.The component correctly:
- Uses
primaryWalletfor primary wallet state- Falls back through
primaryWallet.address→evmAddress→solanaAddressfor address display- Determines wallet type for proper CAIP chain ID computation
- Handles both EVM and Solana wallet icons and network badges
apps/agentic-chat/src/hooks/useApprovedChains.ts (1)
59-65: LGTM! Query key properly addresses referential stability.Using
userWallets.map(w => w.id).join(',')in the query key ensures the query only refetches when wallet identities actually change, which addresses the referential stability concern from earlier reviews.apps/agentic-chat/src/hooks/usePortfolioQuery.ts (1)
18-24: Clarify intent: Is portfolio fetching limited to primary wallet by design?The current logic only fetches portfolio data for the primary wallet: if the primary wallet is EVM-based,
solanaAddressToFetchis undefined, and vice versa. This means users with both EVM and Solana wallets connected will only see the portfolio of their primary wallet.
useWalletConnectionexposes bothevmAddressandsolanaAddress, and thefetchFullPortfolioAPI endpoint is designed to accept and aggregate data from both chains. If the intent is to display a unified portfolio across all connected wallets, the hook should pass both addresses:- // Determine which address type the primary wallet is - const isEvmPrimary = primaryWallet && isEthereumWallet(primaryWallet) - const isSolanaPrimary = primaryWallet && isSolanaWallet(primaryWallet) - - // Only pass the address that matches the primary wallet type - const evmAddressToFetch = isEvmPrimary ? primaryAddress : undefined - const solanaAddressToFetch = isSolanaPrimary ? primaryAddress : undefined + const { evmAddress, solanaAddress } = useWalletConnection()Then update the query call to use
evmAddressandsolanaAddressdirectly, and adjust the query key accordingly.Confirm whether primary-wallet-only is the intended behavior or if multi-chain portfolio support is required.
apps/agentic-chat/src/hooks/useSwapExecution.tsx (5)
1-22: Imports look correct for the Dynamic Labs migration.The imports properly bring in
isEthereumWallet,isSolanaWallet,useDynamicContext,useSwitchWallet, and the localSolanaWalletSignertype. The migration from the previous wallet provider to Dynamic Labs SDK is consistent.
159-163: Wallet context destructuring is well-structured.The hook now correctly retrieves
evmAddress,solanaAddress,solanaWallet, andevmWalletfromuseWalletConnection(), andprimaryWallet/changePrimaryWalletfrom Dynamic context hooks.
217-224: Primary wallet switch for Solana path is well-handled.The logic correctly detects when Solana is the active chain but the primary wallet is not a Solana wallet, then switches accordingly. This ensures proper wallet alignment before transaction execution.
234-243: EVM network switch logic is correct.The code properly validates EVM wallet presence, switches primary wallet if needed, and uses the Dynamic Labs connector's
switchNetworkmethod. Error handling for missing EVM wallet is appropriate.
278-280: Public client creation properly includes chainId.The
getPublicClientcall now correctly passes thechainIdin the configuration object, which is necessary for wagmi to return the correct chain-specific client.apps/agentic-chat/src/components/Portfolio/PortfolioDrawer.tsx (3)
1-7: Imports are appropriate for the Dynamic Labs migration.All necessary hooks (
useDynamicContext,useDynamicModals,useSwitchWallet,useUserWallets) and utilities (filterEvmWallets,filterSolanaWallets,getWalletIcon) are imported correctly.
86-96: Wallet grouping logic is well-structured.The memoized
walletGroupscorrectly categorizes wallets into EVM, Solana, and Other groups, using a Set for efficient exclusion of already-categorized wallets.
254-265: Per-wallet disconnect confirmation dialog is a good UX addition.The two-step disconnect flow with a confirmation dialog prevents accidental wallet disconnections. The
onOpenChangehandler correctly resets state when the dialog is closed.apps/agentic-chat/src/lib/chains.ts (2)
1-13: Clean interface definition for chain configuration.The
ChainConfiginterface provides a well-structured schema for chain metadata including the viem Chain object, network identifiers, URLs, and display names.
110-120: DYNAMIC_EVM_NETWORKS transformation is correct.The mapping from
ChainConfigtoEvmNetworkproperly populates all required fields for Dynamic Labs network configuration.apps/agentic-chat/src/hooks/useSendExecution.ts (3)
1-18: Imports align with the Dynamic Labs migration pattern.The imports mirror
useSwapExecution.tsx, maintaining consistency across the codebase for the wallet migration.
136-140: Wallet context destructuring is consistent with swap execution.The hook correctly retrieves wallet data from
useWalletConnection()and Dynamic context hooks.
187-214: Network switch logic correctly handles both Solana and EVM paths.The Solana path properly switches primary wallet when needed, and the EVM path validates wallet presence before switching networks. Error handling is appropriate.
apps/agentic-chat/src/hooks/useWalletConnection.ts (3)
1-10: Imports and type alias are well-structured.The Dynamic Labs SDK imports are appropriate, and the
DynamicWallettype alias provides a clean abstraction over theuseUserWalletsreturn type.
12-30: Helper functions provide clean wallet filtering utilities.The
find*andfilter*functions properly use type guards withisEthereumWallet/isSolanaWallet. ThegetWalletIconfunction safely accesses the nested connector metadata.
42-66: Hook implementation correctly prioritizes primary wallet.The logic properly checks if
primaryWalletis an EVM or Solana wallet first, then falls back to finding any available wallet of that type. This ensures the primary wallet is always used when compatible.
1ca0b23 to
a4768e0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
♻️ Duplicate comments (5)
apps/agentic-chat/src/components/Portfolio/NetworkWalletRow.tsx (1)
34-36: Accessibility:role="button"without keyboard activation.This wrapper has
role="button"andtabIndex={0}but doesn't handle Enter/Space key activation. SinceCopyButtonalready callsstopPropagationinternally, this wrapper can be simplified.{address && ( - <div onClick={e => e.stopPropagation()} onKeyDown={e => e.stopPropagation()} role="button" tabIndex={0}> + <div onClick={e => e.stopPropagation()}> <CopyButton value={address} className="text-muted-foreground hover:text-foreground" /> </div> )}apps/agentic-chat/src/hooks/usePortfolioQuery.ts (1)
15-16: Consider adding explicit Dynamic SDK state checks for robustness.Per Dynamic Labs SDK documentation,
primaryWalletcan be null during auth resolution or wallet switching even whenisConnectedis true. The currentenabled: isConnected && !!primaryAddressguard works becauseprimaryAddressderives fromprimaryWallet?.address, but this is implicit.For clarity and to align with Dynamic's patterns, consider explicit checks:
const { primaryWallet, sdkHasLoaded } = useDynamicContext() // ... enabled: isConnected && !!primaryAddress && sdkHasLoadedAlso applies to: 31-31
apps/agentic-chat/src/hooks/useApprovedChains.ts (1)
40-45: Only the first EVM wallet's approved chains are queried.The comment states "they should all have same session," but this assumption doesn't hold for mixed wallet scenarios. WalletConnect wallets query
getSupportedNetworks(), while injected wallets return allEVM_CAIP_IDS. If users connect both types, the first wallet's chain set may not represent complete coverage.Consider querying all EVM wallets and merging unique chains:
- const firstEvmWallet = evmWallets[0] - if (firstEvmWallet) { - // Get approved chains from the first EVM wallet (they should all have same session) - const evmChains = await getApprovedChainsForWallet(firstEvmWallet) - chainIds.push(...evmChains) - } + if (evmWallets.length > 0) { + const evmChainResults = await Promise.all( + evmWallets.map(wallet => getApprovedChainsForWallet(wallet)) + ) + const uniqueEvmChains = [...new Set(evmChainResults.flat())] + chainIds.push(...uniqueEvmChains) + }apps/agentic-chat/src/hooks/useNetworkSwitch.ts (1)
101-132: Bug: Solana network switching fails due to falsy chainId check.The
networkNameToChainIdmap assignssolana: 0(fromchains.tsline 105). Since0is falsy in JavaScript, the check at line 104 (if (!targetChainId)) will trigger an error for Solana before reaching the Solana-specific handling at line 113.Reorder the checks to handle Solana before the chainId validation, or use strict equality:
const { state } = useToolExecutionEffect(toolCallId, networkData, initialNetworkState, async (data, setState) => { + // Handle Solana first since chainId 0 is falsy + if (data.network === 'solana') { + if (solanaWallet && primaryWallet && !isSolanaWallet(primaryWallet)) { + await changePrimaryWallet(solanaWallet.id) + } + + setState(draft => { + draft.phase = 'success' + }) + if (activeConversationId) { + const persisted = networkStateToPersistedState( + toolCallId, + { phase: 'success' }, + activeConversationId, + data.network, + data + ) + store.persistTransaction(persisted) + } + return + } + const targetChainId = networkNameToChainId[data.network] - if (!targetChainId) { + if (targetChainId === undefined) { setState(draft => { draft.phase = 'error' draft.error = `Network "${data.network}" not found` }) return } - - // Solana doesn't need network switching in the same way, but we might need to switch primary wallet - if (data.network === 'solana') { - ... - }apps/agentic-chat/src/hooks/useSendExecution.ts (1)
224-230: Add proper type annotations for Dynamic Labs SDK'sSolanaWallet.getSigner()return type.The code assigns
solanaWallet.getSigner()toSolanaWalletSigner, but Dynamic Labs SDK v4.49.0 returnsISolanaSigner(which includespublicKeyand methods likesignTransaction,signAllTransactions,signAndSendTransaction,signMessage). The type annotation should match the actual SDK return type for clarity and type safety.Import and use
ISolanaSignerfrom@dynamic-labs/solana-coreinstead of the localSolanaWalletSignertype:+import type { ISolanaSigner } from '@dynamic-labs/solana-core' import { isSolanaWallet } from '@dynamic-labs/solana'Then update the type annotation:
- let solanaSigner: SolanaWalletSigner | undefined + let solanaSigner: ISolanaSigner | undefined if (chainNamespace === CHAIN_NAMESPACE.Solana && solanaWallet) { solanaSigner = await solanaWallet.getSigner() }
🧹 Nitpick comments (6)
apps/agentic-chat/src/utils/sendExecutor.ts (1)
10-12: Consider extracting sharedExecuteTransactionOptionstype.This interface is identical to the one in
swapExecutor.ts. If the pattern is stable, extracting it to a shared location (e.g.,@/utils/chains/types) would reduce duplication.apps/agentic-chat/src/app/app.tsx (1)
41-70: Provider setup follows Dynamic Labs conventions correctly.The provider hierarchy (DynamicContextProvider → WagmiProvider → QueryClientProvider → DynamicWagmiConnector) aligns with Dynamic's recommended integration pattern. The
initialAuthenticationMode: 'connect-only'is appropriate for wallet connection without embedded authentication.Consider adding runtime validation for the environment ID to provide a clearer error message during development:
+const dynamicEnvironmentId = import.meta.env.VITE_DYNAMIC_ENVIRONMENT_ID +if (!dynamicEnvironmentId) { + throw new Error('VITE_DYNAMIC_ENVIRONMENT_ID is required') +} + <DynamicContextProvider theme="dark" settings={{ - environmentId: import.meta.env.VITE_DYNAMIC_ENVIRONMENT_ID, + environmentId: dynamicEnvironmentId,apps/agentic-chat/src/components/CustomConnectButton.tsx (1)
39-40: Inconsistent memoization betweenwalletIconandwalletName.
walletNameis wrapped inuseMemobutwalletIconis not, despite both being derived fromprimaryWallet?.connector. Either memoize both or neither for consistency. Since both are simple property accesses returning primitives/strings, memoization provides negligible benefit here.- const walletIcon = primaryWallet?.connector?.metadata?.icon - const walletName = useMemo(() => primaryWallet?.connector?.name, [primaryWallet?.connector?.name]) + const walletIcon = primaryWallet?.connector?.metadata?.icon + const walletName = primaryWallet?.connector?.nameapps/agentic-chat/src/hooks/useSwapExecution.tsx (1)
201-205: Consider error handling forgetSigner()call.The
solanaWallet.getSigner()call is awaited but not wrapped in try/catch. If this throws (e.g., wallet disconnected mid-operation), it could cause an unhandled rejection before the main try block catches it.// Get Solana signer if needed - SolanaWallet has getSigner() directly on the class let solanaSigner: SolanaWalletSigner | undefined if (chainNamespace === CHAIN_NAMESPACE.Solana && solanaWallet) { - solanaSigner = await solanaWallet.getSigner() + try { + solanaSigner = await solanaWallet.getSigner() + } catch (e) { + throw new Error('Failed to get Solana signer. Please reconnect your wallet.') + } }apps/agentic-chat/src/hooks/useNetworkSwitch.ts (1)
142-152: Remove debug console.log statements before production.Debug logging statements should be removed or replaced with proper logging infrastructure for production code.
if (evmWallet && primaryWallet && !isEthereumWallet(primaryWallet)) { - console.log('[useNetworkSwitch] Switching primary wallet from Solana to EVM:', evmWallet.id) await changePrimaryWallet(evmWallet.id) } ... - console.log('[useNetworkSwitch] Switching chain via Dynamic connector to:', targetChainId) await evmWallet.connector.switchNetwork({ networkChainId: targetChainId })apps/agentic-chat/src/components/Portfolio/PortfolioDrawer.tsx (1)
57-62: Consider handling the case when the disconnected wallet is the primary wallet.When removing a wallet via
removeWallet, if that wallet is the current primary wallet, the user may be left in an inconsistent state. Consider checking ifwalletToDisconnect === primaryWallet?.idand handling that case (e.g., switching to another wallet first or showing additional confirmation).const handleWalletDisconnect = useCallback(() => { if (walletToDisconnect) { + // If disconnecting the primary wallet and other wallets exist, switch first + const otherWallets = userWallets.filter(w => w.id !== walletToDisconnect) + if (walletToDisconnect === primaryWallet?.id && otherWallets.length > 0) { + changePrimaryWallet(otherWallets[0].id).catch(console.error) + } removeWallet(walletToDisconnect).catch(console.error) setWalletToDisconnect(null) } - }, [walletToDisconnect, removeWallet]) + }, [walletToDisconnect, removeWallet, primaryWallet?.id, userWallets, changePrimaryWallet])
📜 Review details
Configuration used: CodeRabbit 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.
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (31)
.env.example(1 hunks).env.production(1 hunks)apps/agentic-chat/package.json(1 hunks)apps/agentic-chat/src/app/app.tsx(2 hunks)apps/agentic-chat/src/components/CustomConnectButton.tsx(3 hunks)apps/agentic-chat/src/components/Portfolio/NetworkWalletRow.tsx(1 hunks)apps/agentic-chat/src/components/Portfolio/PortfolioDrawer.tsx(5 hunks)apps/agentic-chat/src/components/tools/InitiateSwapUI.tsx(1 hunks)apps/agentic-chat/src/components/tools/SendUI.tsx(1 hunks)apps/agentic-chat/src/hooks/useApprovedChains.ts(1 hunks)apps/agentic-chat/src/hooks/useAutoNetworkSwitch.ts(0 hunks)apps/agentic-chat/src/hooks/useNetworkSwitch.ts(3 hunks)apps/agentic-chat/src/hooks/usePortfolioQuery.ts(2 hunks)apps/agentic-chat/src/hooks/useSendExecution.ts(5 hunks)apps/agentic-chat/src/hooks/useSwapExecution.tsx(8 hunks)apps/agentic-chat/src/hooks/useWalletConnection.ts(1 hunks)apps/agentic-chat/src/lib/appkit.ts(0 hunks)apps/agentic-chat/src/lib/chains.ts(1 hunks)apps/agentic-chat/src/lib/networks.ts(0 hunks)apps/agentic-chat/src/lib/solana-config.ts(0 hunks)apps/agentic-chat/src/lib/wagmi-config.ts(1 hunks)apps/agentic-chat/src/lib/walletUtils.ts(1 hunks)apps/agentic-chat/src/types/appkit.d.ts(0 hunks)apps/agentic-chat/src/utils/chains/evm/transaction.ts(2 hunks)apps/agentic-chat/src/utils/chains/solana/transaction.ts(2 hunks)apps/agentic-chat/src/utils/chains/types.ts(1 hunks)apps/agentic-chat/src/utils/sendExecutor.ts(2 hunks)apps/agentic-chat/src/utils/sendTransaction.ts(2 hunks)apps/agentic-chat/src/utils/swapExecutor.ts(2 hunks)apps/agentic-chat/vite.config.mjs(1 hunks)package.json(1 hunks)
💤 Files with no reviewable changes (5)
- apps/agentic-chat/src/hooks/useAutoNetworkSwitch.ts
- apps/agentic-chat/src/lib/appkit.ts
- apps/agentic-chat/src/types/appkit.d.ts
- apps/agentic-chat/src/lib/networks.ts
- apps/agentic-chat/src/lib/solana-config.ts
🚧 Files skipped from review as they are similar to previous changes (10)
- apps/agentic-chat/package.json
- apps/agentic-chat/src/utils/chains/solana/transaction.ts
- .env.example
- .env.production
- apps/agentic-chat/src/lib/wagmi-config.ts
- apps/agentic-chat/src/utils/chains/evm/transaction.ts
- apps/agentic-chat/src/components/tools/InitiateSwapUI.tsx
- apps/agentic-chat/src/components/tools/SendUI.tsx
- package.json
- apps/agentic-chat/src/utils/sendTransaction.ts
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-09-16T20:28:23.547Z
Learnt from: premiumjibles
Repo: shapeshift/agentic-chat PR: 68
File: apps/agentic-server/package.json:26-26
Timestamp: 2025-09-16T20:28:23.547Z
Learning: In the ShapeShift agentic-chat codebase, mathjs optimization (lazy-loading or using modular sub-packages) has been noted for future implementation rather than immediate action.
Applied to files:
apps/agentic-chat/src/hooks/useApprovedChains.ts
📚 Learning: 2025-09-22T20:32:10.539Z
Learnt from: kaladinlight
Repo: shapeshift/agentic-chat PR: 76
File: apps/agentic-server/src/mastra/tools/asset/coingecko/constants.ts:1-10
Timestamp: 2025-09-22T20:32:10.539Z
Learning: When cross-app dependencies are identified (like server code importing from chat packages), the user prefers to extract shared constants into dedicated packages in the packages/ directory following the existing pattern of shapeshiftoss/types and shapeshiftoss/utils.
Applied to files:
apps/agentic-chat/src/hooks/useSendExecution.ts
🧬 Code graph analysis (10)
apps/agentic-chat/src/utils/chains/types.ts (2)
apps/agentic-chat/src/types/transaction.ts (1)
Transaction(1-10)packages/caip/src/constants.ts (1)
ChainId(175-175)
apps/agentic-chat/src/components/Portfolio/NetworkWalletRow.tsx (3)
apps/agentic-chat/src/lib/utils.ts (1)
truncateAddress(9-12)apps/agentic-chat/src/components/ui/CopyButton.tsx (1)
CopyButton(15-41)apps/agentic-chat/src/components/ui/IconButton.tsx (1)
IconButton(22-29)
apps/agentic-chat/src/utils/swapExecutor.ts (1)
apps/agentic-chat/src/utils/chains/types.ts (1)
SolanaWalletSigner(8-10)
apps/agentic-chat/src/components/Portfolio/PortfolioDrawer.tsx (5)
apps/agentic-chat/src/hooks/useWalletConnection.ts (3)
useWalletConnection(23-48)filterEvmWallets(11-11)filterSolanaWallets(11-11)apps/agentic-chat/src/hooks/usePortfolioQuery.ts (1)
usePortfolioQuery(14-49)apps/agentic-chat/src/lib/utils.ts (1)
truncateAddress(9-12)apps/agentic-chat/src/lib/walletUtils.ts (2)
filterEvmWallets(21-24)filterSolanaWallets(26-29)apps/agentic-chat/src/components/Portfolio/NetworkWalletRow.tsx (1)
NetworkWalletRow(17-52)
apps/agentic-chat/src/hooks/useNetworkSwitch.ts (3)
apps/agentic-chat/src/hooks/useWalletConnection.ts (1)
useWalletConnection(23-48)apps/agentic-chat/src/hooks/useToolExecutionEffect.ts (1)
useToolExecutionEffect(10-57)apps/agentic-chat/src/lib/chains.ts (1)
networkNameToChainId(103-106)
apps/agentic-chat/src/hooks/useWalletConnection.ts (2)
apps/agentic-chat/src/hooks/useApprovedChains.ts (1)
useApprovedChains(54-68)apps/agentic-chat/src/lib/walletUtils.ts (2)
findEvmWallet(11-14)findSolanaWallet(16-19)
apps/agentic-chat/src/app/app.tsx (2)
apps/agentic-chat/src/lib/chains.ts (1)
DYNAMIC_EVM_NETWORKS(110-120)apps/agentic-chat/src/lib/wagmi-config.ts (1)
wagmiConfig(15-19)
apps/agentic-chat/src/components/CustomConnectButton.tsx (4)
apps/agentic-chat/src/hooks/useWalletConnection.ts (1)
useWalletConnection(23-48)apps/agentic-chat/src/lib/utils.ts (1)
truncateAddress(9-12)apps/agentic-chat/src/lib/chains.ts (1)
SOLANA_CAIP_ID(90-90)packages/utils/src/networkIcons.ts (1)
NETWORK_ICONS(14-31)
apps/agentic-chat/src/hooks/useSwapExecution.tsx (3)
apps/agentic-chat/src/hooks/useWalletConnection.ts (1)
useWalletConnection(23-48)apps/agentic-chat/src/utils/chains/types.ts (1)
SolanaWalletSigner(8-10)packages/caip/src/constants.ts (1)
CHAIN_NAMESPACE(46-54)
apps/agentic-chat/src/hooks/useSendExecution.ts (5)
apps/agentic-chat/src/hooks/useWalletConnection.ts (1)
useWalletConnection(23-48)packages/caip/src/constants.ts (1)
CHAIN_NAMESPACE(46-54)apps/agentic-chat/src/utils/chains/types.ts (1)
SolanaWalletSigner(8-10)apps/agentic-chat/src/utils/sendExecutor.ts (1)
executeSend(34-40)apps/agentic-server/src/index.ts (1)
executeSend(64-64)
⏰ 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). (1)
- GitHub Check: main
🔇 Additional comments (27)
apps/agentic-chat/vite.config.mjs (1)
9-12: LGTM — standard browser polyfill forprocess.env.This is a common Vite pattern to prevent runtime errors from libraries that reference
process.env. Since Vite usesimport.meta.envfor environment variables, this empty object shim is appropriate.apps/agentic-chat/src/utils/swapExecutor.ts (1)
4-4: LGTM — clean migration to signer-based API.The rename from
solanaProvidertosolanaSignerand the corresponding type change align with the Dynamic Labs signer pattern. TheSolanaWalletSignerinterface correctly exposes only thesignTransactionmethod needed for this use case.Also applies to: 10-13, 28-28
apps/agentic-chat/src/utils/sendExecutor.ts (1)
4-4: LGTM — consistent with the signer migration inswapExecutor.ts.The changes mirror the swap executor updates. Both files now use the same
SolanaWalletSignertype andsolanaSignernaming convention.Also applies to: 10-12, 28-28
apps/agentic-chat/src/components/Portfolio/NetworkWalletRow.tsx (1)
17-50: LGTM — cleaner unified row design.The simplified clickable row approach with proper
stopPropagationon child actions is a good pattern. TheisActivebadge provides clear visual feedback.apps/agentic-chat/src/hooks/usePortfolioQuery.ts (1)
18-24: Behavior change: portfolio now fetches only the primary wallet's chain.With this logic, if a user has both EVM and Solana wallets connected but the primary is EVM, only the EVM portfolio is fetched. Previously, both addresses may have been passed. Verify this is the intended UX.
apps/agentic-chat/src/components/CustomConnectButton.tsx (2)
44-49: Network icon lookup may returnundefinedfor unrecognized chains.If
caipChainIddoesn't exist inNETWORK_ICONS,networkIconwill beundefined. The UI handles this gracefully (conditional render on line 63), but users on unsupported chains won't see a network indicator. This is acceptable behavior, but worth noting for awareness.
17-35: Wallet connection flow and address derivation look correct.The migration to
setShowAuthFlow(true)for triggering the connection modal and the address fallback chain (primaryWallet?.address → evmAddress → solanaAddress) properly handles both EVM and Solana wallet scenarios.apps/agentic-chat/src/utils/chains/types.ts (2)
6-13: Type definitions are well-structured.The
SolanaWalletSignerinterface correctly uses a generic constraint to preserve the input transaction type through signing. The backward compatibility aliasSolanaWalletProvideris a thoughtful addition for gradual migration.
22-22: All usages ofsolanaProviderhave been successfully updated tosolanaSignerthroughout the codebase—no remaining references detected.apps/agentic-chat/src/hooks/useApprovedChains.ts (2)
59-61: Query key now uses stable wallet IDs - addresses previous memoization concern.Using
userWallets.map(w => w.id).join(',')in the query key ensures the query only re-runs when wallet identities actually change, not on every render. This properly addresses the referential stability concern from the prior review.
17-32: Error handling ingetApprovedChainsForWalletis appropriate.The try-catch gracefully falls back to
EVM_CAIP_IDSifgetSupportedNetworks()fails, ensuring the app remains functional even if WalletConnect session queries fail.apps/agentic-chat/src/lib/walletUtils.ts (1)
11-29: Utility functions are correctly implemented with proper type predicates.The eslint-disable comments are justified—the Dynamic SDK's type variance between
Wallet<any>[]and specific wallet types (explained in the file header) necessitates suppressing the unsafe-argument warning. The type predicate syntax(w): w is EthereumWallet =>correctly narrows types for consumers. BothfilterEvmWalletsandfilterSolanaWalletsare actively used in PortfolioDrawer.tsx with memoization.apps/agentic-chat/src/hooks/useSwapExecution.tsx (3)
217-224: LGTM on Solana primary wallet switching.The logic correctly switches to the Solana wallet when a Solana transaction is needed but the primary wallet is not Solana. The guard conditions are appropriate.
234-243: LGTM on EVM wallet and network switching.The implementation correctly validates the EVM wallet presence, switches the primary wallet if needed, and uses Dynamic's connector API for network switching.
278-280: LGTM on public client configuration.The
getPublicClientcall correctly passes the chainId configuration to get the appropriate chain-specific client.apps/agentic-chat/src/lib/chains.ts (2)
15-88: LGTM on centralized chain configuration.The
SUPPORTED_EVM_CHAINSarray provides a clean, single source of truth for chain configurations. Using viem's chain definitions ensures consistency with the ecosystem.
110-120: LGTM on Dynamic EVM networks transformation.The
DYNAMIC_EVM_NETWORKSarray correctly transforms the chain configurations into theEvmNetworkformat expected by Dynamic Labs SDK.apps/agentic-chat/src/hooks/useWalletConnection.ts (2)
23-47: LGTM on wallet connection hook.The hook provides a clean abstraction over Dynamic Labs wallet state, correctly prioritizing the primary wallet and falling back to any connected wallet of the appropriate type. The return type is well-defined with all necessary fields for downstream consumers.
11-11: Good pattern: Re-exporting wallet utilities.Re-exporting
filterEvmWallets,filterSolanaWallets,findEvmWallet, andfindSolanaWalletfrom this hook module provides a convenient single import point for wallet-related functionality.apps/agentic-chat/src/components/Portfolio/PortfolioDrawer.tsx (3)
43-55: LGTM on disconnect handler with proper cleanup.The
handleDisconnectfunction correctly invalidates relevant query caches before logging out, ensuring stale data isn't displayed after reconnection.
99-154: LGTM on wallet dropdown with grouped wallets.The implementation correctly groups EVM and Solana wallets, displays appropriate labels, and handles primary wallet switching with proper guards. The UI provides clear visual feedback for the active wallet.
216-227: LGTM on per-wallet disconnect confirmation dialog.The implementation follows the same AlertDialog pattern as the main disconnect dialog, providing consistent UX. The
onOpenChangehandler correctly clears thewalletToDisconnectstate when the dialog is dismissed.apps/agentic-chat/src/hooks/useSendExecution.ts (5)
1-3: LGTM! Imports correctly updated for Dynamic Labs migration.The Dynamic Labs SDK imports (
isEthereumWallet,isSolanaWallet,useDynamicContext,useSwitchWallet) are appropriate for the new wallet management approach.
136-140: LGTM! Hook usage correctly migrated to Dynamic Labs context.The destructuring of
solanaWalletandevmWalletfromuseWalletConnection, along withprimaryWalletandchangePrimaryWalletfrom Dynamic Labs hooks, properly supports the new multi-wallet management approach.
205-207: Good error handling for missing EVM wallet.The explicit check for
evmWalletexistence with a clear error message prevents runtime failures and provides actionable feedback to users.
209-214: Primary wallet alignment logic mirrors Solana approach.The code aligns the primary wallet to
evmWalletbefore switching networks, similar to the Solana path. The same verification concerns apply here—ensurechangePrimaryWallet()completes successfully beforeswitchNetwork()is called.
187-194: The code is sound. ThechangePrimaryWallet()call at line 193 is properly awaited, ensuring it completes before the subsequentsetStatecall marks the step complete. Any errors fromchangePrimaryWalletwill be caught by the outer try-catch block (lines 161-242), which persists the error state and tracks the failed step. No race conditions or timing issues exist with this implementation.
apps/agentic-chat/src/lib/chains.ts
Outdated
| rpcUrl: 'https://eth.llamarpc.com', | ||
| vanityName: 'Ethereum', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
llamarpc rate limits and reliability for production
💡 Result:
Short answer: llama.cpp's RPC (rpc-server / llama-server) has no built‑in API rate‑limiting and is still effectively “experimental” for heavy production use — it can work in production if you design around its limits, but you must expect throughput/latency penalties, memory/transfer failure modes, and operational fragility unless you thoroughly test and harden the setup. [1][2][3][4]
Key points (concise):
- Rate limits: none provided by the RPC layer — you must enforce request throttling, queues, or concurrency limits at your own API/gateway layer. [1][2]
- Reliability: documented as proof‑of‑concept/fragile; maintainers and users report crashes when RPC servers are overloaded or when model offload exceeds available RAM, and there are known performance/throughput regressions vs single‑node runs. Test for token throughput, memory pressure, and edge cases. [1][3][4]
- Network & performance: RPC transfers can be heavy (substantial bytes/token) and introduce significant latency and lower GPU utilization in multi‑node splits — network bandwidth and latency strongly affect token/sec. Monitor per‑token traffic and colocate when possible. [5][4]
- Security: RPC was explicitly warned as insecure if exposed to open networks; always run behind private networks, firewalls, or VPNs. [1]
Practical recommendations for production:
- Put a fronting API/gateway (NGINX, Envoy, FastAPI, Kong) to enforce rate limits, concurrency, auth, and circuit breakers. (No built‑in RPC rate limiting.) [1]
- Capacity test with your exact model, tensor‑split, batch sizes, and network topology; measure tokens/sec, p95 latency, and bytes/token. Use these results to size nodes and set autoscaling thresholds. [3][4][5]
- Avoid overcommitting RPC server RAM; leave headroom and enable caching where supported. Watch for model‑load crashes when >~75% of server RAM is used (reported). [3]
- Co‑locate high‑traffic offload servers on the same high‑bandwidth network or use 10Gb+ links; prefer local GPU where feasible to reduce RPC overhead. [4][5]
- Add health checks, rolling restarts, request timeouts and retries, exponential backoff, and throttling to protect RPC backends from bursts. [1][3]
- Consider alternatives for critical production: single‑node large‑GPU instances, commercial hosted inference (with SLA/rate limits), or proven multi‑node orchestration layers (that include rate limiting, autoscaling, and monitoring).
Sources:
- llama.cpp RPC example / README (notes that RPC is experimental, insecure, and intended as proof‑of‑concept). [1]
- llama.cpp docs / server build & RPC usage references. [2]
- GitHub issues reporting crashes when offloading large models / memory overcommit. [3]
- GitHub issue and community reports about GPU utilization and RPC throughput penalties. [4]
- Community performance reports (per‑token network traffic, Reddit threads) highlighting high bytes/token and practical latency/throughput impacts. [5]
If you want, I can: run a short checklist tailored to your model (size, batch, token rate target, network) and produce concrete capacity numbers and a recommended fronting‑gateway config.
🏁 Script executed:
# Check the full context of the file to understand usage
head -50 apps/agentic-chat/src/lib/chains.tsRepository: shapeshift/agentic-chat
Length of output: 1564
🏁 Script executed:
# Search for all RPC URL references in the file
rg -n "rpcUrl|https://" apps/agentic-chat/src/lib/chains.ts -A 2 -B 2Repository: shapeshift/agentic-chat
Length of output: 2480
🏁 Script executed:
# Check if there's any environment variable configuration for RPC URLs
rg -r "process.env|import.*env|\.env" apps/agentic-chat/src/lib/chains.tsRepository: shapeshift/agentic-chat
Length of output: 49
🌐 Web query:
Ethereum public RPC endpoints rate limits reliability llamarpc
💡 Result:
Short answer
- eth.llamarpc.com is a widely-used free public Ethereum RPC used by many projects and tools and generally measures fast in independent latency tests, but LlamaRPC does not publish a formal public SLA or clear global per-IP public rate-limit page like some paid providers. [1][2][3]
- Public RPC endpoints (Cloudflare, PublicNode, Ankr, GetBlock, etc.) each impose different limits (RPS, daily caps, per-method weights) and throttling behaviors; free endpoints are shared resources and can return 429s or intermittent errors under load. Expect modest free-tier limits (tens to a few hundred RPS or method-weighted "credits") or per-IP/day caps depending on provider. Examples: Cloudflare/publicnode entries in public lists and docs. [4][5]
- Practical guidance: do not rely on a single public endpoint for production—use multiple endpoints + client-side rate limiting, batching, caching, exponential backoff, and (for high-volume/critical apps) a paid RPC provider or self-hosted node for guaranteed throughput. [6][2]
Notes and sources
- eth.llamarpc.com listed among public RPCs and measured fast in independent comparisons. [2][3]
- Public RPC catalogs and provider docs summarizing many endpoints and typical rate‑limit patterns (per-second / daily caps / method weights). See aggregated lists and examples. [4][5]
- Best-practices (multiple endpoints, rate-limiting, backoff, paid plans or own node) referenced in tooling/docs that use eth.llamarpc.com as an endpoint and in RPC-provider docs. [6][2]
Sources
- urlscan record / domain metadata for llamarpc.com. [turn2search6]
- Chain‑List / public RPC index showing eth.llamarpc.com as an Ethereum mainnet endpoint. [turn0search8]
- Independent node-performance comparison showing LlamaRPC latency vs competitors. [turn1search6]
- Aggregated public RPC lists (CompareNodes / Chain‑List) and catalogs of public endpoints and notes about availability. [turn0search7][turn0search8]
- Examples of provider rate‑limit docs and policies (sample provider pages showing RPS/day or credit systems). [turn0search0][turn0search4]
- Tooling/docs recommending multiple endpoints and rate‑limit handling (Ponder, projects that include eth.llamarpc.com as an example). [turn1search0][turn1search2]
If you want, I can:
- check LlamaRPC for any updated public rate‑limit or status pages right now, or
- produce a short code snippet showing how to implement multi‑endpoint failover + exponential backoff for ethers/viem.
🌐 Web query:
public RPC endpoints production ethereum rate limiting best practices
💡 Result:
Short checklist — production public Ethereum RPC endpoints rate-limiting best practices:
- Define limits & quotas per identity: enforce per-API-key and per-IP quotas (short window + burst allowance). [2][3]
- Use a token‑bucket or sliding‑window algorithm server-side; expose X-RateLimit-Limit / -Remaining / -Reset headers and return 429 on exceed. [1][3]
- Limit JSON-RPC batch size and expensive methods (set max batch length and per-method cost). [1][3]
- Client-side throttling: implement a local rate limiter that respects estimated cost units (CU) to avoid 429s. [4]
- Backoff & retry: require exponential backoff + jitter on 429/5xx; respect any server backoff_seconds field. [3][2]
- Caching & aggregation: cache frequently-read data, use block-tag caching, and combine requests (batch, multicall) when possible. [5][2]
- Circuit breaker & health checks: stop routing to failing providers, do health probes, and rotate/blacklist degraded nodes. [5][8]
- Multi-provider & load‑balance: spread traffic across providers/regions to smooth spikes and reduce single‑point overload. [5][8]
- Monitoring, alerts & metrics: track RPS, 429 rate, latency, error rates, per-key usage and queue depth; alert before limits hit. [2][5]
- Security controls: require authentication for higher quotas, IP/referrer whitelists for client keys, and rotate keys. [4][3]
- Provide developer guidance: publish per-method costs, recommended client limits, and escalation path for quota increases. [2][1]
If you want, I can produce a recommended server-side config (token-bucket params, header formats, sample 429 body) or sample client limiter code (Node/Go).
🏁 Script executed:
# Check for environment configuration or dotenv files
fd -e ".env*" -e "config" apps/agentic-chat/ | head -20Repository: shapeshift/agentic-chat
Length of output: 444
🏁 Script executed:
# Check if rpcUrl is configurable or used elsewhere in the codebase
rg -r "CHAIN|RPC_URL|process.env" apps/agentic-chat/ --type ts --type js | head -30Repository: shapeshift/agentic-chat
Length of output: 222
Use environment-configurable RPC URLs and implement fallback/rate-limit handling for production.
Public RPC endpoints (llamarpc, polygon-rpc.com, etc.) enforce rate limits and lack formal SLAs—eth.llamarpc.com specifically does not publish clear per-IP limits. Hardcoding a single RPC per chain risks outages and 429 errors under load. For production, make RPC URLs environment-configurable, implement multi-endpoint failover, add client-side rate limiting and exponential backoff, and consider paid RPC providers for critical operations.
🤖 Prompt for AI Agents
In apps/agentic-chat/src/lib/chains.ts around lines 22-23, the RPC URL is
hardcoded to a public endpoint which risks rate limits and outages; change the
chain RPC configuration to read a prioritized list of RPC endpoints from
environment variables (with sensible defaults to the current URL), implement
client-side multi-endpoint failover (try next endpoint on network error/429),
add a simple rate limiter and exponential backoff/retry strategy for transient
429/5xx responses, and make provider selection/configurable (env var for
provider priority or paid provider URL) so production can override defaults and
avoid single-endpoint failures.
a4768e0 to
977b1de
Compare
977b1de to
d4dc7e6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (8)
apps/agentic-chat/src/lib/chains.ts (2)
15-88: Consider env‑configurable RPC URLs and optional multi‑endpoint strategy for productionHardcoding single public RPC URLs (e.g.,
https://eth.llamarpc.com,https://polygon-rpc.com) is convenient for dev but brittle in production due to rate limits and lack of SLAs. Consider:
- Reading RPC URLs from environment variables with these as defaults, and
- (Optionally) supporting multiple RPC URLs per chain plus simple client‑side failover/backoff in your networking layer.
This keeps
ChainConfigas the central source of truth while making production setups more resilient.
103-106:solana: 0sentinel innetworkNameToChainIdis easy to misuseMapping
solanato0makes anyif (!targetChainId)checks treat Solana as “missing”, which is already causing issues inuseNetworkSwitch. Either avoid giving Solana a numericchainIdhere (and handle it by name elsewhere), or ensure all consumers use an explicit undefined check (targetChainId === undefined) rather than falsy checks.apps/agentic-chat/src/hooks/useNetworkSwitch.ts (1)
101-121: Bug: Solana network switch path is unreachable due to falsychainIdcheck
networkNameToChainId['solana']is0, so fordata.network === 'solana'theif (!targetChainId)block runs first and returns an error before the Solana‑specific branch. As a result, Solana “switches” always fail.Reorder the Solana handling and make the missing‑network check explicit:
- const targetChainId = networkNameToChainId[data.network] - - if (!targetChainId) { + // Solana doesn't require an EVM network switch, only primary wallet alignment. + if (data.network === 'solana') { + if (solanaWallet && primaryWallet && !isSolanaWallet(primaryWallet)) { + await changePrimaryWallet(solanaWallet.id) + } + + setState(draft => { + draft.phase = 'success' + }) + persistState({ phase: 'success' }) + return + } + + const targetChainId = networkNameToChainId[data.network] + + if (targetChainId === undefined) { const errorState: NetworkSwitchState = { phase: 'error', error: `Network "${data.network}" not found` } setState(draft => { draft.phase = errorState.phase draft.error = errorState.error }) persistState(errorState) return } - - // Solana doesn't need network switching in the same way, but we might need to switch primary wallet - if (data.network === 'solana') { - if (solanaWallet && primaryWallet && !isSolanaWallet(primaryWallet)) { - await changePrimaryWallet(solanaWallet.id) - } - - setState(draft => { - draft.phase = 'success' - }) - persistState({ phase: 'success' }) - return - }This ensures Solana uses the dedicated path and only true “unknown” networks are rejected.
apps/agentic-chat/src/hooks/usePortfolioQuery.ts (2)
19-24: Stale closure in queryFn still present.As noted in the previous review,
evmAddressandsolanaAddressare captured in thequeryFnclosure but aren't included inqueryKey. While this is unlikely to cause issues in practice (wallet type changes typically change the address too), it's technically incorrect and could cause stale fetches in multi-wallet scenarios.The previous review's suggestion to add these to the queryKey or recompute them inline remains valid.
24-24: Consider adding explicit Dynamic SDK state checks.As noted in the previous review, the query relies on the implicit
!!addressguard, but doesn't check Dynamic SDK-specific state flags likeisLoggedInorloadingNetwork. While the current implementation works, adding explicit SDK state checks would make the intent clearer and align better with Dynamic Labs' documented patterns.apps/agentic-chat/src/components/Portfolio/NetworkWalletRow.tsx (1)
34-36: Accessibility issue persists:role="button"requires keyboard activation handlers.As noted in the previous review, the wrapper has
role="button"andtabIndex={0}but only stops propagation on keydown without handling Enter/Space to trigger the action. SinceCopyButtonalready handlesstopPropagationinternally, this wrapper may be unnecessary.The previous review's suggestion to remove the wrapper or add proper keyboard activation handlers remains valid.
apps/agentic-chat/src/lib/wagmi-config.ts (1)
10-13: Custom RPC URLs from chain config are still not being used.As noted in the previous review,
SUPPORTED_EVM_CHAINSdefines customrpcUrlvalues (e.g.,https://eth.llamarpc.com), but the transports use barehttp()which falls back to viem's default public RPCs. This may cause rate limiting or reliability issues.The previous review's suggestion to pass the custom RPC URLs to
http()remains valid.apps/agentic-chat/src/hooks/useSendExecution.ts (1)
224-228: Use Dynamic Labs SDK'sISolanaSignertype instead of localSolanaWalletSigner.As noted in the previous review, the code uses the local
SolanaWalletSignertype, but Dynamic Labs SDK'sgetSigner()method returnsISolanaSigner. The previous review's suggestion to import and useISolanaSignerfrom@dynamic-labs/solana-coreremains valid.
🧹 Nitpick comments (2)
apps/agentic-chat/package.json (1)
16-21: Confirm Dynamic package versions and peer-dependency compatibilityAll
@dynamic-labs/*packages are aligned on^4.49.0, which is good. Please double‑check against Dynamic’s docs that this version range is compatible with your currentwagmi,viem, and React versions and that any required peer deps are satisfied, especially in production builds.If anything is off, I can help suggest a compatible version matrix.
apps/agentic-chat/src/hooks/useSwapExecution.tsx (1)
213-217: Use Dynamic Labs SDK'sISolanaSignertype instead of localSolanaWalletSigner.Similar to the issue in
useSendExecution.ts, this code uses the localSolanaWalletSignertype, but Dynamic Labs SDK'sgetSigner()method returnsISolanaSigner. While structurally compatible, using the actual SDK type provides better type safety and documentation.+import type { ISolanaSigner } from '@dynamic-labs/solana-core' -import type { SolanaWalletSigner } from '@/utils/chains/types' +import type { SolanaWalletSigner as LocalSolanaWalletSigner } from '@/utils/chains/types' - let solanaSigner: SolanaWalletSigner | undefined + let solanaSigner: ISolanaSigner | undefined if (chainNamespace === CHAIN_NAMESPACE.Solana && solanaWallet) { solanaSigner = await solanaWallet.getSigner() }
📜 Review details
Configuration used: CodeRabbit 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.
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (31)
.env.example(1 hunks).env.production(1 hunks)apps/agentic-chat/package.json(1 hunks)apps/agentic-chat/src/app/app.tsx(2 hunks)apps/agentic-chat/src/components/CustomConnectButton.tsx(2 hunks)apps/agentic-chat/src/components/Portfolio/NetworkWalletRow.tsx(1 hunks)apps/agentic-chat/src/components/Portfolio/PortfolioDrawer.tsx(5 hunks)apps/agentic-chat/src/components/tools/InitiateSwapUI.tsx(1 hunks)apps/agentic-chat/src/components/tools/SendUI.tsx(1 hunks)apps/agentic-chat/src/hooks/useApprovedChains.ts(1 hunks)apps/agentic-chat/src/hooks/useAutoNetworkSwitch.ts(0 hunks)apps/agentic-chat/src/hooks/useNetworkSwitch.ts(4 hunks)apps/agentic-chat/src/hooks/usePortfolioQuery.ts(1 hunks)apps/agentic-chat/src/hooks/useSendExecution.ts(5 hunks)apps/agentic-chat/src/hooks/useSwapExecution.tsx(12 hunks)apps/agentic-chat/src/hooks/useWalletConnection.ts(1 hunks)apps/agentic-chat/src/lib/appkit.ts(0 hunks)apps/agentic-chat/src/lib/chains.ts(1 hunks)apps/agentic-chat/src/lib/networks.ts(0 hunks)apps/agentic-chat/src/lib/solana-config.ts(0 hunks)apps/agentic-chat/src/lib/wagmi-config.ts(1 hunks)apps/agentic-chat/src/lib/walletUtils.ts(1 hunks)apps/agentic-chat/src/types/appkit.d.ts(0 hunks)apps/agentic-chat/src/utils/chains/evm/transaction.ts(2 hunks)apps/agentic-chat/src/utils/chains/solana/transaction.ts(2 hunks)apps/agentic-chat/src/utils/chains/types.ts(1 hunks)apps/agentic-chat/src/utils/sendExecutor.ts(2 hunks)apps/agentic-chat/src/utils/sendTransaction.ts(2 hunks)apps/agentic-chat/src/utils/swapExecutor.ts(2 hunks)apps/agentic-chat/vite.config.mjs(1 hunks)package.json(1 hunks)
💤 Files with no reviewable changes (5)
- apps/agentic-chat/src/types/appkit.d.ts
- apps/agentic-chat/src/lib/networks.ts
- apps/agentic-chat/src/hooks/useAutoNetworkSwitch.ts
- apps/agentic-chat/src/lib/appkit.ts
- apps/agentic-chat/src/lib/solana-config.ts
🚧 Files skipped from review as they are similar to previous changes (9)
- apps/agentic-chat/src/components/tools/SendUI.tsx
- .env.production
- apps/agentic-chat/src/utils/sendTransaction.ts
- apps/agentic-chat/src/lib/walletUtils.ts
- package.json
- apps/agentic-chat/src/utils/chains/solana/transaction.ts
- .env.example
- apps/agentic-chat/src/components/Portfolio/PortfolioDrawer.tsx
- apps/agentic-chat/src/hooks/useApprovedChains.ts
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-22T20:32:10.539Z
Learnt from: kaladinlight
Repo: shapeshift/agentic-chat PR: 76
File: apps/agentic-server/src/mastra/tools/asset/coingecko/constants.ts:1-10
Timestamp: 2025-09-22T20:32:10.539Z
Learning: When cross-app dependencies are identified (like server code importing from chat packages), the user prefers to extract shared constants into dedicated packages in the packages/ directory following the existing pattern of shapeshiftoss/types and shapeshiftoss/utils.
Applied to files:
apps/agentic-chat/src/hooks/useSendExecution.ts
🧬 Code graph analysis (10)
apps/agentic-chat/src/utils/swapExecutor.ts (3)
apps/agentic-server/src/lib/schemas/swapSchemas.ts (2)
SwapData(77-77)TransactionData(75-75)apps/agentic-server/src/tools/initiateSwap.ts (1)
InitiateSwapOutput(277-277)apps/agentic-chat/src/utils/chains/types.ts (1)
SolanaWalletSigner(8-10)
apps/agentic-chat/src/utils/sendExecutor.ts (1)
apps/agentic-chat/src/utils/chains/types.ts (1)
SolanaWalletSigner(8-10)
apps/agentic-chat/src/components/CustomConnectButton.tsx (4)
apps/agentic-chat/src/lib/utils.ts (1)
truncateAddress(9-12)apps/agentic-chat/src/lib/chains.ts (1)
SOLANA_CAIP_ID(90-90)packages/utils/src/networkIcons.ts (1)
NETWORK_ICONS(14-31)apps/agentic-chat/src/components/ui/Button.tsx (1)
Button(55-55)
apps/agentic-chat/src/utils/chains/types.ts (1)
packages/caip/src/constants.ts (1)
ChainId(175-175)
apps/agentic-chat/src/hooks/useWalletConnection.ts (2)
apps/agentic-chat/src/hooks/useApprovedChains.ts (1)
useApprovedChains(31-57)apps/agentic-chat/src/lib/walletUtils.ts (2)
findEvmWallet(11-14)findSolanaWallet(16-19)
apps/agentic-chat/src/lib/wagmi-config.ts (1)
apps/agentic-chat/src/lib/chains.ts (2)
SUPPORTED_EVM_CHAINS(15-88)SUPPORTED_CHAIN_IDS(94-97)
apps/agentic-chat/src/hooks/useSwapExecution.tsx (3)
apps/agentic-chat/src/hooks/useWalletConnection.ts (1)
useWalletConnection(23-48)apps/agentic-chat/src/utils/chains/types.ts (1)
SolanaWalletSigner(8-10)packages/caip/src/constants.ts (1)
CHAIN_NAMESPACE(46-54)
apps/agentic-chat/src/app/app.tsx (2)
apps/agentic-chat/src/lib/chains.ts (1)
DYNAMIC_EVM_NETWORKS(110-120)apps/agentic-chat/src/lib/wagmi-config.ts (1)
wagmiConfig(15-19)
apps/agentic-chat/src/hooks/useNetworkSwitch.ts (3)
apps/agentic-chat/src/hooks/useWalletConnection.ts (1)
useWalletConnection(23-48)apps/agentic-chat/src/hooks/useToolExecutionEffect.ts (1)
useToolExecutionEffect(10-57)apps/agentic-chat/src/lib/chains.ts (1)
networkNameToChainId(103-106)
apps/agentic-chat/src/components/Portfolio/NetworkWalletRow.tsx (3)
apps/agentic-chat/src/lib/utils.ts (1)
truncateAddress(9-12)apps/agentic-chat/src/components/ui/CopyButton.tsx (1)
CopyButton(15-41)apps/agentic-chat/src/components/ui/IconButton.tsx (1)
IconButton(22-29)
⏰ 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). (1)
- GitHub Check: main
🔇 Additional comments (6)
apps/agentic-chat/vite.config.mjs (1)
11-11: No action needed. Setting'process.env': {}in the Vitedefineconfig is a standard practice to prevent undefined reference errors in the browser bundle. A search of the codebase found no remainingprocess.envusages, confirming the migration toimport.meta.envis complete or was never applicable for the browser code.apps/agentic-chat/src/components/tools/InitiateSwapUI.tsx (1)
19-19: UsingswapData.sellAccountfor “Received from” looks correctDeriving
addressfromswapOutput.swapData.sellAccountkeeps the header tied to the actual swap source account (including for historical runs) instead of the current wallet hook. This is consistent with the rest of the component’s use ofswapOutputand is a safe change.apps/agentic-chat/src/utils/chains/types.ts (1)
6-23: Signer-based Solana typing and legacy alias look soundThe
SolanaWalletSignerinterface withsignTransaction<T extends Transaction | VersionedTransaction>matches common wallet signer contracts, and theSolanaWalletProvideralias preserves backward compatibility. UpdatingTransactionParamstosolanaSigner?: SolanaWalletSignerkeeps the call sites structurally aligned with the new signer model.apps/agentic-chat/src/utils/swapExecutor.ts (1)
4-13: Swap executor wiring toSolanaWalletSigneris consistentThreading
solanaSigner?: SolanaWalletSignerthroughExecuteTransactionOptionsand intofinalTxaligns with the updatedTransactionParamstype and keeps the EVM path unchanged. Approval and swap both correctly reuse the sharedexecuteTransaction.Also applies to: 28-29
apps/agentic-chat/src/utils/sendExecutor.ts (1)
4-12: Send executor’s Solana signer integration matches the shared transaction shapeUsing
solanaSigner?: SolanaWalletSignerinExecuteTransactionOptionsand conditionally spreading it intofinalTxis consistent with the new sharedTransactionParamscontract and mirrors the swap executor path, so both EVM and Solana sends route through the same abstraction cleanly.Also applies to: 28-29
apps/agentic-chat/src/utils/chains/evm/transaction.ts (1)
23-28: Chain resolution viachainIdToChainand explicit unsupported‑chain error look goodLooking up the chain with
chainIdToChain[chainId]and throwing on missing entries makes unsupported chains fail fast, while keeping the rest of the transaction construction (getAddress,Hexcast, optionalgas) intact. This centralizes chain metadata behind your newlib/chainsmodule without changing the externalsendEvmTransactionAPI.Also applies to: 33-46
d4dc7e6 to
1bbd371
Compare
Summary by CodeRabbit
New Features
Refactor
Chores
✏️ Tip: You can customize this high-level summary in your review settings.