-
Notifications
You must be signed in to change notification settings - Fork 644
add receiver address for swap and buy widget #8635
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
base: main
Are you sure you want to change the base?
Conversation
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughAdds receiver-address selection to the bridge flow: components may use either the connected wallet or a custom address for incoming tokens, with UI (dropdown + modal), outside-click handling, and plumbing from BridgeWidget → SwapWidget → SwapUI → FundWallet to include the receiver in quote/preparation requests. Changes
sequenceDiagram
participant User as User (UI)
participant Bridge as BridgeWidget
participant Swap as SwapWidget / SwapUI
participant Fund as FundWallet / TokenSection
participant Wallet as Connected Wallet
participant Quote as QuoteService / API
User->>Bridge: Open bridge widget (optional receiverAddress prop)
Bridge->>Swap: Pass props including receiverAddress
User->>Swap: Open receiver dropdown
Swap->>Fund: Render dropdown (Use connected wallet / Paste address)
User->>Fund: Select "Paste address" → open modal
Fund->>User: Show modal (input & validation)
User->>Fund: Paste & Save address
Fund->>Swap: setReceiverAddressMode("custom") / setReceiverAddress(value)
Swap->>Quote: Request quote including resolved receiverAddress
Quote-->>Swap: Return quote
Swap-->>User: Display quote
User->>Swap: Confirm swap
Swap->>Quote: Prepare transaction with receiverAddress
Quote-->>Swap: Prepared tx
Swap->>Wallet: Prompt wallet for signing
Wallet-->>Swap: Signed tx
Swap->>Quote: Submit transaction
Quote-->>User: Confirmation
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes 🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Warning Review ran into problems🔥 ProblemsErrors were encountered while retrieving linked issues. Errors (1)
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: 1
🤖 Fix all issues with AI agents
In `@packages/thirdweb/src/react/web/ui/Bridge/swap-widget/swap-ui.tsx`:
- Around line 503-541: Remove the redundant tempReceiverAddress.length check
(tempReceiverAddress truthiness is sufficient) and guard the connected-wallet
comparison against missing activeWalletInfo/activeAccount by using a safe check
for the address (e.g., ensure props.activeWalletInfo and
props.activeWalletInfo.activeAccount or use optional chaining on
activeAccount.address) before calling toLowerCase(), so replace the second
condition that compares tempReceiverAddress.toLowerCase() ===
props.activeWalletInfo?.activeAccount.address.toLowerCase() with one that first
verifies the existence of the wallet address
(props.activeWalletInfo?.activeAccount?.address) and then compares lowercase
values.
🧹 Nitpick comments (5)
packages/thirdweb/src/react/web/ui/Bridge/swap-widget/swap-ui.tsx (2)
106-136: Consider extracting the click-outside logic into a reusable hook.The click-outside handler pattern (lines 119-136) is duplicated in
FundWallet.tsx. Consider creating a shareduseClickOutsidehook to reduce duplication.♻️ Example shared hook
// In a shared hooks file function useClickOutside( ref: React.RefObject<HTMLElement | null>, isActive: boolean, onClickOutside: () => void ) { useEffect(() => { if (!isActive) return; const handleClickOutside = (event: MouseEvent) => { if (ref.current && !ref.current.contains(event.target as Node)) { onClickOutside(); } }; document.addEventListener("mousedown", handleClickOutside); return () => document.removeEventListener("mousedown", handleClickOutside); }, [isActive, onClickOutside, ref]); }
932-1026: Significant code duplication with FundWallet.tsx.The receiver address dropdown UI (lines 932-1026) is nearly identical to the implementation in
FundWallet.tsx(lines 614-706). Consider extracting this into a sharedReceiverAddressDropdowncomponent.♻️ Suggested component extraction
// In a shared component file, e.g., common/receiver-address-dropdown.tsx type ReceiverAddressDropdownProps = { activeWalletInfo: ActiveWalletInfo; receiverAddressMode: "wallet" | "custom"; receiverAddress: string; showDropdown: boolean; dropdownRef: React.RefObject<HTMLDivElement | null>; onModeChange: (mode: "wallet" | "custom") => void; onAddressChange: (address: string) => void; onShowDropdownChange: (show: boolean) => void; onOpenModal: () => void; }; export function ReceiverAddressDropdown(props: ReceiverAddressDropdownProps) { // Shared implementation }packages/thirdweb/src/react/web/ui/Bridge/FundWallet.tsx (3)
189-195: Redundant condition inisReceiverDifferentFromActiveWallet.The condition on lines 190-191 (
receiver !== activeWalletInfo?.activeAccount?.address) is redundant since line 193-194 already performs a normalized comparison usingchecksumAddress. The strict inequality check on line 190-191 would be true for case differences, but the checksummed comparison on lines 193-194 handles this correctly.♻️ Simplified condition
const isReceiverDifferentFromActiveWallet = receiver && - receiver !== activeWalletInfo?.activeAccount?.address && (activeWalletInfo?.activeAccount?.address ? checksumAddress(receiver) !== checksumAddress(activeWalletInfo?.activeAccount?.address) : true);
332-424: Significant code duplication with swap-ui.tsx.The Receiver Address Modal (lines 332-424) is nearly identical to
swap-ui.tsx(lines 481-570). Consider extracting into a sharedReceiverAddressModalcomponent to maintain consistency and reduce maintenance burden.Note: This version correctly guards against undefined
activeWalletInfo(line 375), which could be backported to theswap-ui.tsximplementation.
614-706: Code duplication - receiver dropdown UI.As noted in the
swap-ui.tsxreview, this dropdown implementation is duplicated. Extracting a sharedReceiverAddressDropdowncomponent would benefit both files.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (5)
packages/thirdweb/src/react/web/ui/Bridge/FundWallet.tsxpackages/thirdweb/src/react/web/ui/Bridge/bridge-widget/bridge-widget.tsxpackages/thirdweb/src/react/web/ui/Bridge/swap-widget/SwapWidget.tsxpackages/thirdweb/src/react/web/ui/Bridge/swap-widget/select-chain.tsxpackages/thirdweb/src/react/web/ui/Bridge/swap-widget/swap-ui.tsx
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each TypeScript file to one stateless, single-responsibility function for clarity
Re-use shared types from@/typesor localtypes.tsbarrels
Prefer type aliases over interface except for nominal shapes in TypeScript
Avoidanyandunknownin TypeScript unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial,Pick, etc.) in TypeScript
**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity and testability
Re-use shared types from@/typesor local types.ts barrel exports
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics whenever possible
Choose composition over inheritance; leverage utility types (Partial, Pick, etc.)
Comment only ambiguous logic in TypeScript files; avoid restating TypeScript types and signatures in prose
Files:
packages/thirdweb/src/react/web/ui/Bridge/bridge-widget/bridge-widget.tsxpackages/thirdweb/src/react/web/ui/Bridge/swap-widget/SwapWidget.tsxpackages/thirdweb/src/react/web/ui/Bridge/swap-widget/select-chain.tsxpackages/thirdweb/src/react/web/ui/Bridge/swap-widget/swap-ui.tsxpackages/thirdweb/src/react/web/ui/Bridge/FundWallet.tsx
packages/thirdweb/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
packages/thirdweb/src/**/*.{ts,tsx}: Comment only ambiguous logic in SDK code; avoid restating TypeScript in prose
Load heavy dependencies inside async paths to keep initial bundle lean (e.g.const { jsPDF } = await import("jspdf");)Lazy-load heavy dependencies inside async paths to keep the initial bundle lean (e.g., const { jsPDF } = await import('jspdf');)
Files:
packages/thirdweb/src/react/web/ui/Bridge/bridge-widget/bridge-widget.tsxpackages/thirdweb/src/react/web/ui/Bridge/swap-widget/SwapWidget.tsxpackages/thirdweb/src/react/web/ui/Bridge/swap-widget/select-chain.tsxpackages/thirdweb/src/react/web/ui/Bridge/swap-widget/swap-ui.tsxpackages/thirdweb/src/react/web/ui/Bridge/FundWallet.tsx
**/*.{js,jsx,ts,tsx,json}
📄 CodeRabbit inference engine (AGENTS.md)
Biome governs formatting and linting; its rules live in biome.json. Run
pnpm fix&pnpm lintbefore committing, ensure there are no linting errors
Files:
packages/thirdweb/src/react/web/ui/Bridge/bridge-widget/bridge-widget.tsxpackages/thirdweb/src/react/web/ui/Bridge/swap-widget/SwapWidget.tsxpackages/thirdweb/src/react/web/ui/Bridge/swap-widget/select-chain.tsxpackages/thirdweb/src/react/web/ui/Bridge/swap-widget/swap-ui.tsxpackages/thirdweb/src/react/web/ui/Bridge/FundWallet.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Lazy-import optional features; avoid top-level side-effects
Files:
packages/thirdweb/src/react/web/ui/Bridge/bridge-widget/bridge-widget.tsxpackages/thirdweb/src/react/web/ui/Bridge/swap-widget/SwapWidget.tsxpackages/thirdweb/src/react/web/ui/Bridge/swap-widget/select-chain.tsxpackages/thirdweb/src/react/web/ui/Bridge/swap-widget/swap-ui.tsxpackages/thirdweb/src/react/web/ui/Bridge/FundWallet.tsx
🧬 Code graph analysis (2)
packages/thirdweb/src/react/web/ui/Bridge/swap-widget/swap-ui.tsx (5)
packages/thirdweb/src/utils/web/isMobile.ts (1)
isMobile(58-82)packages/thirdweb/src/react/web/ui/components/Modal.tsx (1)
Modal(32-173)packages/thirdweb/src/react/web/ui/components/formElements.tsx (1)
Input(37-110)packages/thirdweb/src/exports/utils.ts (1)
shortenAddress(149-149)packages/thirdweb/src/react/web/ui/Bridge/common/active-wallet-details.tsx (1)
ActiveWalletDetails(21-92)
packages/thirdweb/src/react/web/ui/Bridge/FundWallet.tsx (2)
packages/thirdweb/src/react/web/ui/components/Modal.tsx (1)
Modal(32-173)packages/thirdweb/src/react/web/ui/components/formElements.tsx (1)
Input(37-110)
⏰ 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). (8)
- GitHub Check: Build Packages
- GitHub Check: E2E Tests (pnpm, webpack)
- GitHub Check: E2E Tests (pnpm, esbuild)
- GitHub Check: Unit Tests
- GitHub Check: E2E Tests (pnpm, vite)
- GitHub Check: Lint Packages
- GitHub Check: Size
- GitHub Check: Analyze (javascript)
🔇 Additional comments (9)
packages/thirdweb/src/react/web/ui/Bridge/swap-widget/select-chain.tsx (1)
137-140: LGTM!Good improvement using
Array.fromwhich is more idiomatic thanArray(n).fill(0). The biome-ignore comment appropriately documents the intentional use of index as key for static skeleton placeholders.packages/thirdweb/src/react/web/ui/Bridge/swap-widget/swap-ui.tsx (2)
89-89: LGTM!The new optional
receiverAddressprop is properly typed with theAddresstype.
758-773: LGTM!The receiver address handling correctly validates the input with
isAddressbefore usinggetAddress, and appropriately falls back to the connected wallet address when no valid custom address is provided.packages/thirdweb/src/react/web/ui/Bridge/swap-widget/SwapWidget.tsx (2)
178-182: LGTM!The new
receiverAddressprop is well-documented with JSDoc and correctly typed.
397-397: LGTM!The
receiverAddressprop is correctly passed through toSwapUI.packages/thirdweb/src/react/web/ui/Bridge/bridge-widget/bridge-widget.tsx (2)
161-165: LGTM!The
receiverAddressprop in the swap configuration is well-documented and properly typed.
423-423: LGTM!The
receiverAddressprop is correctly passed through toSwapWidget.packages/thirdweb/src/react/web/ui/Bridge/FundWallet.tsx (2)
146-158: LGTM!State initialization correctly derives initial mode from
props.receiverAddressand follows the same pattern asswap-ui.tsx.
889-914: LGTM!The
overflow: visiblechanges are necessary to allow the dropdown to render outside the container bounds. The consistent application across nested containers ensures proper rendering.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
packages/thirdweb/src/react/web/ui/Bridge/swap-widget/swap-ui.tsx
Outdated
Show resolved
Hide resolved
size-limit report 📦
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #8635 +/- ##
==========================================
- Coverage 52.97% 52.58% -0.40%
==========================================
Files 932 935 +3
Lines 62270 63111 +841
Branches 4096 4116 +20
==========================================
+ Hits 32987 33184 +197
- Misses 29184 29827 +643
- Partials 99 100 +1
🚀 New features to boost your workflow:
|
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: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/thirdweb/src/react/web/ui/Bridge/swap-widget/swap-ui.tsx (1)
148-155: Guard receiver by mode to avoid unintended recipient.
useSwapQuotealways uses a validreceiverAddress, even if the UI is in “wallet” mode. IfreceiverAddressModeandreceiverAddressget out of sync (e.g., initial props), swaps could route to a custom address while the UI shows the connected wallet.🔧 Suggested fix
- const preparedResultQuery = useSwapQuote({ + const effectiveReceiverAddress = + props.receiverAddressMode === "custom" ? props.receiverAddress : ""; + const preparedResultQuery = useSwapQuote({ amountSelection: props.amountSelection, buyTokenWithPrices: buyTokenWithPrices, sellTokenWithPrices: sellTokenWithPrices, activeWalletInfo: props.activeWalletInfo, client: props.client, - receiverAddress: props.receiverAddress, + receiverAddress: effectiveReceiverAddress, });
🧹 Nitpick comments (1)
packages/thirdweb/src/react/web/ui/Bridge/swap-widget/swap-ui.tsx (1)
488-558: Normalize/trim receiver input before validation & save.Trimming prevents false invalidation on pasted addresses; normalizing ensures a canonical value.
♻️ Suggested tweak
- {tempReceiverAddress && !isAddress(tempReceiverAddress) && ( + {tempReceiverAddress.trim() && + !isAddress(tempReceiverAddress.trim()) && ( <Container style={{ padding: spacing.sm, borderRadius: radius.md, backgroundColor: `${theme.colors.danger}15`, }} flex="row" gap="xs" center="y" > <Text size="sm" color="danger"> This isn't a valid wallet address. Please ensure that the address provided is accurate. </Text> </Container> )} @@ <Button variant="primary" fullWidth disabled={ - !tempReceiverAddress || - !isAddress(tempReceiverAddress) || - tempReceiverAddress.toLowerCase() === + !tempReceiverAddress.trim() || + !isAddress(tempReceiverAddress.trim()) || + tempReceiverAddress.trim().toLowerCase() === props.activeWalletInfo?.activeAccount.address.toLowerCase() } onClick={() => { - if ( - tempReceiverAddress && - isAddress(tempReceiverAddress) && - tempReceiverAddress.toLowerCase() !== - props.activeWalletInfo?.activeAccount.address.toLowerCase() - ) { - props.setReceiverAddress(tempReceiverAddress); + const normalized = tempReceiverAddress.trim(); + if ( + normalized && + isAddress(normalized) && + normalized.toLowerCase() !== + props.activeWalletInfo?.activeAccount.address.toLowerCase() + ) { + props.setReceiverAddress(getAddress(normalized)); props.setReceiverAddressMode("custom"); setReceiverAddressModalOpen(false); } }} > SAVE </Button>Optional: consider extracting the receiver-address modal/dropdown into a focused subcomponent to keep
SwapUIfrom growing further. As per coding guidelines, keep the file single‑responsibility.
PR-Codex overview
This PR focuses on enhancing the
receiverAddressfunctionality across multiple components in thethirdwebpackage, improving how addresses are handled and displayed during token swaps and wallet funding operations.Detailed summary
receiverAddresshandling inBridgeWidgetPropsandSwapWidgetProps.receiverAddressModestate management inSwapWidgetContent.FundWalletandSwapUI.receiverAddressandreceiverAddressMode.ReceiverWalletSectioncomponent.Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.