Compare commits

...
Author SHA1 Message Date
Joaquim VergesGitHubgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
d0c2ac63a9 Version Packages (#7042)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-05-16 05:06:17 -07:00
Joaquim VergesandGitHub 170f14fb54 [Dashboard] Add pagination to server wallets page (#7070) 2025-05-16 05:04:26 -07:00
Joaquim VergesandGitHub da2a2a0e86 [SDK] Fix buyWithCrypto false not respected when returning from quote (#7069) 2025-05-16 04:57:48 -07:00
saminaandGitHub e62fd3fe40 [Docs] Engine Update (#7052)
Signed-off-by: samina <[email protected]>
2025-05-16 04:09:33 -07:00
Joaquim VergesandGitHub 99a7cce624 [Engine] Add all testnets to test transaction options (#7066) 2025-05-16 04:08:17 -07:00
Joaquim VergesandGitHub 61152dd098 [Engine] Add FAILED status to execution result and update error handling (#7065) 2025-05-16 03:34:27 -07:00
Maximilian HubertandGitHub 05519fcdde [DOCS] fix link in contributing.md (#7063)
Signed-off-by: Maximilian Hubert <[email protected]>
2025-05-16 00:11:57 -07:00
saminaandGitHub 7257747520 [Docs] Engine (#7057)
Signed-off-by: samina <[email protected]>
2025-05-16 00:10:35 -07:00
Prithvish BaidyaandGitHub e71e7d70a6 [Vault] default to engine-cloud vault proxy (#7058) 2025-05-15 16:44:03 -07:00
Joaquim VergesandGitHub 8d47864967 [SDK] Export prepareUserOp and add support for new wallets (#7061) 2025-05-15 16:43:11 -07:00
kumaryash90 4a8adc143f [Docs] Stylus dev workflow (#7060)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces documentation and assets for integrating thirdweb tools into the Stylus contract development workflow, specifically for Rust. It includes setup instructions, publishing and deployment commands, and images to enhance the documentation.

### Detailed summary
- Added new sections in `page.mdx` for Arbitrum Stylus.
- Included prerequisites for Rust and Solidity installations.
- Provided setup commands for creating a Stylus project.
- Added commands for publishing and deploying Stylus contracts.
- Included images (`stylus-publish-page.png`, `stylus-deploy-page.png`) to illustrate the process.

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

<!-- end pr-codex -->
2025-05-15 21:30:32 +00:00
MananTank db538473cf [NEB-248] Show native token balances in assets, show popular tokens on top (#7056)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR enhances the `AssetsSection` component by integrating wallet balance retrieval, modifying how assets are displayed, and implementing new logic for sorting tokens. It also introduces a new constant for native tokens and adjusts rendering based on whether an asset is native.

### Detailed summary
- Added `NATIVE_TOKEN_ADDRESS` and `getWalletBalance` import from `thirdweb`.
- Updated `key` for `AssetItem` to include `chain_id`.
- Introduced `isNativeToken` to conditionally render the `ChainIconClient`.
- Modified the `href` for `Link` based on whether the asset is a native token.
- Added a new set `tokensToShowOnTop` for sorting specific tokens.
- Implemented `nativeBalances` query to fetch wallet balances for various chains.
- Combined `nativeBalances` and `assetsQuery` data for rendering in `AssetsSectionUI`.

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

<!-- end pr-codex -->
2025-05-15 20:52:49 +00:00
Manan TankandGitHub 2057546934 Nebula: Recent Activity improvements in sidebar (#7055) 2025-05-15 13:52:15 -07:00
gregandGitHub ba52e68eab [Dashboard] Fix: Trend markers and UB volume type dropdown (#7059) 2025-05-15 12:05:40 -07:00
0eff64824b [Dashboard] Feature: Add Universal Bridge to analytics dashboard (#7051)
Co-authored-by: Claude <[email protected]>
2025-05-14 18:07:07 -07:00
saminacodes ae7407dca4 [Docs] engine and ub changes (#7049)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the documentation and user guidance for the `thirdweb` platform, specifically around the Engine v3 features, onramp providers, and pricing details. It introduces new FAQs, clarifies migration steps, and adds visual content.

### Detailed summary
- Added new section for "Onramp Providers" in `sidebar.tsx`.
- Updated Engine FAQs in `page.mdx` with pricing and transaction details.
- Revised migration guide in `page.mdx` with clearer instructions and a callout for wallet migration.
- Enhanced `faqs/page.mdx` with additional questions about Universal Bridge and supported payment methods.
- Updated "Buy With Fiat" availability to 160+ countries.
- Included images for creating a vault and sending transactions in the `get-started/page.mdx`.
- Revised onramp providers section to clarify provider preferences and fees in `onramp-providers/page.mdx`.

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

<!-- end pr-codex -->
2025-05-14 22:53:11 +00:00
Joe-Thirdweb a443b309dc Adding NeoX custom chain info. (#7045)
Adding Custom chain info to

- NeoX Mainnet 47763
- NeoX Testnt 12227332

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces new assets and metadata for the `Neo X` blockchain, enhancing the dashboard with images and information about its features and offerings.

### Detailed summary
- Added imports for `NeoXBanner` and `NeoXCTA` images.
- Introduced metadata for `Neo X` (ID: 47763) including:
  - `headerImgUrl`
  - `about` description
  - `cta` object with `backgroundImageUrl`, `title`, `buttonLink`, and `buttonText`.
- Duplicated metadata for `Neo X Testnet` (ID: 12227332) with similar structure.

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

<!-- end pr-codex -->
2025-05-14 22:44:28 +00:00
Joaquim VergesGitHubgraphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
ae2ff743c0 [Engine] Update OpenAPI spec and configuration (#7050)
Signed-off-by: Joaquim Verges <[email protected]>
Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
2025-05-14 15:43:30 -07:00
MananTank dfa8603593 [NEB-213] Nebula: Show wallet Assets and Activity in sidebar (#7046)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR primarily focuses on enhancing the `AssetsSection` and `TransactionsSection` components by adding new features and improving the UI. It also modifies several existing components for better functionality and user experience.

### Detailed summary
- Changed `mergedSessions.push(session)` to `mergedSessions.unshift(session)` in `useSessionsWithLocalOverrides.ts`.
- Updated the width of the sidebar in `ChatPageLayout.tsx` from `280px` to `300px`.
- Added `customDetailsButton` prop to `NebulaConnectWallet` in `NebulaConnectButton.tsx`.
- Implemented conditional rendering for `customDetailsButton` in `NebulaConnectWallet`.
- Created storybook stories for `AssetsSection` and `TransactionsSection` with stubs for tokens and transactions.
- Enhanced `AssetsSection` and `TransactionsSection` components to handle loading states and display messages when there are no assets or transactions.
- Introduced `WalletDetails` component in `ChatSidebar` to manage assets and transactions tabs.
- Refactored `WalletSelector` to integrate `useActiveWallet` for better wallet management and user feedback.
- Improved button components with tooltips for better accessibility and UX.

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

<!-- end pr-codex -->
2025-05-14 21:47:42 +00:00
saminacodes 9f1ca54c26 Update page.mdx (#7048)
CORE-0000

<!-- start pr-codex -->

---

## PR-Codex overview
This PR updates the `preferredProvider` options in the `detailsModal` configuration for the `connectbutton` component, enhancing payment provider flexibility.

### Detailed summary
- Modified `preferredProvider` options in `detailsModal`:
  - Removed `"KADO"`
  - Added `"COINBASE"`

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

<!-- end pr-codex -->
2025-05-14 17:44:23 +00:00
MananTank 7df81b7323 [TOOL-4493] Dashboard: Add starter legacy discontinuation banner (#7047)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces a `StarterLegacyDiscontinuedBanner` component to the `RootTeamLayout` in `layout.tsx`. It displays a notification for users on the "starter_legacy" billing plan, informing them of the discontinuation and providing a link to select a new plan.

### Detailed summary
- Added a conditional rendering for `StarterLegacyDiscontinuedBanner` based on the team's billing plan.
- Created the `StarterLegacyDiscontinuedBanner` component to inform users about the discontinuation of starter legacy plans.
- Included a button with a link to the billing settings for selecting a new plan, featuring an `ArrowRightIcon`.

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

<!-- end pr-codex -->
2025-05-14 16:25:35 +00:00
GiselleNessi ab74fcdaf8 add new apis tab to nav (#7044)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR adds a new section to the `Header` component in the `Header.tsx` file, introducing `apisLinks` for API documentation links and integrating a `DropdownLinks` component for displaying these links.

### Detailed summary
- Added a new constant `apisLinks` containing links to API documentation.
- Introduced a `DropdownLinks` component to display `apisLinks` in the header.
- Adjusted padding in the header's layout from `xl:px-2` to `xl:px-1` for the new dropdown.

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

<!-- end pr-codex -->
2025-05-14 15:09:12 +00:00
Joaquim VergesandGitHub 1191d5dad9 [Engine] Add EOA read/create permissions for server wallets (#7043) 2025-05-14 22:32:35 +12:00
Joaquim VergesandGitHub 20b5ba943a [SDK] Propagate 401 errors when connecting in-app wallet (#7040) 2025-05-14 02:03:41 -07:00
Joaquim VergesGitHubgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
f0f8da8fab Version Packages (#7032)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-05-13 19:50:56 -07:00
Joaquim VergesandGitHub da3fc99c0b [SDK] Default to in-memory storage for inAppWallet outside browser (#7038) 2025-05-13 18:32:37 -07:00
fb4c190eb3 [Dashboard] Feature: Default analytics range to 30 days and save preference (#7039)
Co-authored-by: Claude <[email protected]>
2025-05-13 15:25:09 -07:00
FirekeeperandGitHub 1c31a1e4df [Portal] .NET ThirdwebBridge Onramping & InAppWallet 7702 Account Abstraction (#7017) 2025-05-13 14:14:45 -07:00
MananTank 04c10f82fd [TOOL-4471] GatedSwitch updates, Make In-app wallet branding gated by starter+ (#7021)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the billing and plan management features in the dashboard. It introduces new props for handling plan highlights and open plan sheets, modifies tooltip styles, and adjusts billing card components to improve user experience.

### Detailed summary
- Updated `tooltip.tsx` to change padding in tooltip content.
- Changed `requiredPlan` from `authRequiredPlan` to `brandingRequiredPlan` in `Configure/index.tsx`.
- Added `openPlanSheetButtonByDefault` and `highlightPlan` props in various components.
- Modified `PlanInfoCardClient` and `Billing` components to utilize new props.
- Updated `TeamPlanBadge` to include an optional postfix.
- Enhanced `BillingPricing` logic to handle plan highlights.
- Adjusted `GatedSwitch` tooltip content for better user guidance.

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

<!-- end pr-codex -->
2025-05-13 20:22:10 +00:00
MananTank ab173886ac [TOOL-4483] Move changelog to team landing page from notifications (#7037)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on refactoring notification handling in the application, removing unused functions, and enhancing the UI components related to notifications and alerts.

### Detailed summary
- Removed `getChangelogNotifications` and related props from several components.
- Introduced `DismissibleAlert` component for better alert management.
- Updated `NotificationButtonUI` to streamline notification handling.
- Adjusted UI elements for consistency and clarity.

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

<!-- end pr-codex -->
2025-05-13 19:19:55 +00:00
Joe-Thirdweb df06bec699 [Dashboard]Adding zkCandy + Onyx chain updates (#7035)
Adding custom chain info to

- Onyx Mainnet
- zkCandy Mainnet

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces new assets and updates the `chainMetaRecord` object to include information for the `Onyx` and `zkCandy` blockchains, enhancing the dashboard with additional details and visuals.

### Detailed summary
- Added imports for `onyxBanner`, `onyxCTA`, and `zkCandyBanner` images.
- Introduced `Onyx` blockchain entry in `chainMetaRecord` with header image, description, and CTA.
- Added `zkCandy` blockchain entry in `chainMetaRecord` with header image, description, and CTA.
- Updated comment for `zkCandy` entry to specify it as "zkCandy Testnet".

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

<!-- end pr-codex -->
2025-05-13 15:42:08 +00:00
Joaquim VergesandGitHub 6000dacfbb [Docs] Add Engine v2 to v3 migration guide (#7036) 2025-05-13 04:12:27 -07:00
Joaquim VergesandGitHub fc6535069b [SDK] Preload wallet balances on pay embed (#7034) 2025-05-13 17:08:26 +12:00
Joaquim VergesandGitHub b15c3c0747 Add contract availability documentation to ERC methods (#7033) 2025-05-12 17:47:28 -07:00
Joaquim VergesandGitHub 1985de89aa [SDK] Expose inMemoryStorage for inAppWallet backend usage (#7016) 2025-05-12 16:04:22 -07:00
MananTank 2b87b7bb75 [NEB-246] Nebula: handle aborted session with no messages (#7025)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the `ChatSidebar`, `useSessionsWithLocalOverrides`, and `ChatPageContent` components. It improves session handling, updates the chat sidebar title, and adds a user-friendly message for sessions without messages.

### Detailed summary
- Updated `title` prop in `<ChatSidebarLink>` to default to "Untitled Chat".
- Merged new sessions with existing ones in `useSessionsWithLocalOverrides`.
- Introduced a message and icon for sessions with no messages in `ChatPageContent`.
- Conditional rendering of `<Chats>` based on message availability.

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

<!-- end pr-codex -->
2025-05-12 20:54:35 +00:00
MananTank d99a985ab4 [NEB-238] Show ENS name in selected account badge (#7024)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on updating the rendering of the `AccountName` component in the `ChatBar.tsx` file to improve the styling and structure of the address display.

### Detailed summary
- Replaced `span` with `AccountName` component for displaying the selected address.
- Added `className="text-xs"` to the `AccountName` component.
- Updated `loadingComponent` and `fallbackComponent` to use a consistent `span` with `className="text-xs"`.
- Changed `className` of `span` in `WalletSelector` from `font-mono text-sm` to `text-sm` for a consistent style.

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

<!-- end pr-codex -->
2025-05-12 20:54:35 +00:00
MananTank e74574ccf5 [NEB-239] Fix chain search not working properly for chain name starting with number (#7023)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on improving the code by replacing `Number.parseInt` with `Number` for checking if a value is an integer across multiple files, enhancing readability and consistency.

### Detailed summary
- In `TokenSelector.tsx`, changed `Number.parseInt(searchValue)` to `Number(searchValue)`.
- In `single-network-selector.tsx`, modified the same integer check.
- In `ConfigureCustomChain.tsx`, updated integer check for `chainSlug`.
- In `NetworkSelectors.tsx`, replaced the integer check similarly.

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

<!-- end pr-codex -->
2025-05-12 20:54:35 +00:00
MananTank 98d05d6fb6 [NEB-247] Show error event in chat UI (#7022)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces error handling for chat responses in the `ChatPageContent` and `chat.ts` files. It adds functionality to display error messages when an error event is received.

### Detailed summary
- Added handling for `"error"` case in `ChatPageContent.tsx` to update messages with error details.
- Implemented parsing of error data in `chat.ts` to extract error code and message.
- Updated `ChatStreamedEvent` type to include an `"error"` event with relevant data structure.

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

<!-- end pr-codex -->
2025-05-13 02:09:03 +05:30
MananTank f4ac3c2a3a [NEB-245] Limit image format types for upload (#7019)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the `ImageUploadButton` component by allowing it to accept specific image file types and updating the `ChatBar` component to utilize this feature.

### Detailed summary
- In `ChatBar.tsx`, added `accept` attribute with value `"image/jpeg,image/png,image/webp"` to the file input.
- In `image-upload-button.tsx`, changed `accept` property from a static value `"image/*"` to a dynamic value using `props.accept`.
- Updated `ImageUploadButton` to include `accept` in its props definition.

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

<!-- end pr-codex -->
2025-05-12 20:26:53 +00:00
MananTank a3a4bf4361 Nebula: Fix User Image message type (#7018)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on updating the image handling in the `types.ts` and related components by modifying the structure of image objects, allowing for optional `image_url` and `b64` properties.

### Detailed summary
- In `types.ts`, changed the `image` type to include `image_url: string | null` and `b64: string | null`.
- In `ChatBar.tsx`, added `image_url: null` when pushing the image object to `userMessage.content`.
- In `Chats.tsx`, updated the condition to check if `msg.b64` is a string and used `msg.image_url ?? ""` for the URL.
- In `NebulaImage.tsx`, adjusted the skeleton div to have a minimum height of 300px.

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

<!-- end pr-codex -->
2025-05-12 17:15:52 +00:00
Joaquim VergesGitHubgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
e8ec54e6e2 Version Packages (#7014)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-05-12 01:43:18 -07:00
Joaquim VergesandGitHub 58e343c10c [SDK] Improve EIP-5792 wallet capabilities support (#7003) 2025-05-12 01:25:30 -07:00
Prithvish BaidyaandGitHub bad9db9760 postfix slash to engine url (#7013) 2025-05-12 00:41:45 -07:00
Joaquim VergesGitHubgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
6a1e54ec69 Version Packages (#7010)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-05-11 16:16:33 -07:00
7ddedfbed1 Fix: Catch siwe doLogin errors (#7012)
Co-authored-by: Claude <[email protected]>
2025-05-12 10:45:32 +12:00
98eda9dd3d Fix: Auto-signin to autoconnect for all cases (#7011)
Co-authored-by: Claude <[email protected]>
2025-05-11 14:41:47 -07:00
5a13ad4521 [SDK] Fix: Automatically trigger login for connected wallets whe… (#7009)
Co-authored-by: Claude <[email protected]>
2025-05-11 14:02:23 -07:00
gregGitHubgraphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
557a29a960 [Dashboard] Fix: Copying payment link on iOS (#7008)
Signed-off-by: greg <[email protected]>
Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
2025-05-11 08:03:07 -07:00
gregandGitHub ff565cb0f8 Fix: Trend badge formatting (#7007) 2025-05-10 10:40:23 -07:00
gregfromstl 816aa6137b [Dashboard] Fix: Display latest value in PayNewCustomers component (#7002)
🤖 Generated with [Claude Code](https://claude.ai/code)

<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on improving the logic used to display the total value in the `SkeletonContainer` of the `PayNewCustomers` component. It ensures that when `graphData` is empty, it returns "NA", and otherwise, it retrieves the last value or defaults to 0.

### Detailed summary
- Updated the logic in `SkeletonContainer`:
  - Changed the expression to return `graphData[graphData.length - 1]?.value || 0` when `graphData` is not empty.
  - Maintained the output of "NA" when `isEmpty` is true.

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

<!-- end pr-codex -->
2025-05-10 17:10:32 +00:00
MananTank 7de273c59d Dashboard: Reset last-used-* cookies on login page (#7005)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on adding a `deleteCookie` function to manage cookies and incorporates a new component, `ResetLastUsedCookies`, in the `LoginPage` to clear specific cookies upon rendering.

### Detailed summary
- Added `deleteCookie` function in `cookie.ts` to delete cookies by name.
- Imported constants `LAST_USED_PROJECT_ID`, `LAST_USED_TEAM_ID`, and `LAST_VISITED_TEAM_PAGE_PATH` in `LoginPage.tsx`.
- Implemented `ResetLastUsedCookies` component to delete specific cookies on mount.

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

<!-- end pr-codex -->
2025-05-10 13:18:36 +00:00
Joaquim VergesGitHubgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
95cc441edd Version Packages (#7006)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-05-10 06:18:04 -07:00
Joaquim VergesandGitHub 6f1d4b1fcf [SDK] Handle tx with value on engineAccount (#7004) 2025-05-10 06:13:54 -07:00
7ede361870 Fix testnet filtering in NetworkSelectors (#7001)
Co-authored-by: Claude <[email protected]>
2025-05-09 23:05:51 -07:00
8b50779229 [Dashboard] Feature: Disable testnets in Payment Link form (#7000)
Co-authored-by: Claude <[email protected]>
2025-05-09 22:51:41 -07:00
gregGitHubClaudegraphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
282d9f2c39 [Dashboard] Fix: Use x-client-id + x-team-id for all UB requests (#6999)
Signed-off-by: greg <[email protected]>
Co-authored-by: Claude <[email protected]>
Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
2025-05-09 22:17:01 -07:00
jnsdls e739de158d Only set secret key or client ID when not using auth token (#6994)
This PR modifies the header setting logic in `getClientFetch` to ensure that secret keys and client IDs are only set when not using an auth token. This prevents potential conflicts between different authentication methods by making the header setting logic mutually exclusive.

<!-- start pr-codex -->

---

## PR-Codex overview
This PR modifies the logic in the `fetch.ts` file to ensure that the `x-secret-key` and `x-client-id` headers are only set when not using the authentication token, enhancing security and clarity in header management.

### Detailed summary
- Added an `else` clause to only set `x-secret-key` if not using the auth token.
- Rearranged the condition for setting `x-client-id` to follow the new logic.

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

<!-- end pr-codex -->
2025-05-10 02:54:20 +00:00
gregandGitHub 451594c80c Feature: Migrate Universal Bridge Analytics (#6988) 2025-05-09 18:16:43 -07:00
gregfromstl 9634e49113 Feature: Add client id to checkout form url (#6997)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the `CheckoutLinkForm` component by passing a `client` prop to it and improving its functionality. It also refines the styling and class management using the `cn` utility for better readability and maintainability.

### Detailed summary
- Modified `page.tsx` to create a `client` using `getClientThirdwebClient` and pass it to `CheckoutLinkForm`.
- Changed the `CheckoutLinkForm` function signature to accept a `client` prop.
- Updated multiple instances in `CheckoutLinkForm` to utilize `client.clientId`.
- Replaced static class names with the `cn` utility for dynamic class management in the button and div elements.
- Adjusted the conditional rendering of classes for better readability and performance in the component.

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

<!-- end pr-codex -->
2025-05-10 01:05:38 +00:00
gregandGitHub a4e12c5516 Fix: Auth method for checkout page api requests to ub service (#6996) 2025-05-09 17:29:49 -07:00
MananTank 2297915633 [NEB-210] Nebula: Add image upload (#6995)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces image upload functionality within the chat application, enhancing user interaction by allowing users to send images along with text messages. It also includes updates to various components to support this feature.

### Detailed summary
- Added `allowImageUpload` prop to multiple components.
- Introduced `ImageUploadButton` for image selection.
- Modified `ChatBar` to handle image uploads and message composition.
- Updated `FloatingChatContentLoggedIn`, `ChatPageContent`, and `EmptyStateChatPageContent` to accommodate new props.
- Enhanced `NebulaImage` for displaying uploaded images.
- Implemented image preview and removal functionality in `ChatBar`.

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

<!-- end pr-codex -->
2025-05-09 23:19:08 +00:00
gregandGitHub 585ba2f575 Feature: Checkout link creation page (#6989) 2025-05-09 13:51:26 -07:00
MananTank a68ec74d25 Dashboard: Use React taint API for envs, envs cleanup (#6992)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR primarily focuses on refactoring the environment variables used throughout the application, shifting from a centralized `env` file to a more modular `public-envs` and `server-envs` structure. This enhances organization and clarity regarding environment variable usage.

### Detailed summary
- Deleted `env.ts` and introduced `public-envs.ts` and `server-envs.ts`.
- Updated imports across various files to use new environment variable structure.
- Replaced direct `process.env` calls with imported constants.
- Added `taint` feature for sensitive server environment variables.
- Adjusted fetch URLs to use `NEXT_PUBLIC_THIRDWEB_API_HOST` instead of `API_SERVER_URL`.

> The following files were skipped due to too many changes: `apps/dashboard/src/@/constants/server-envs.ts`, `apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractPageMetadata.ts`, `apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractPageMetadataSetup.ts`, `apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/engine/cloud/server-wallets/components/try-it-out.tsx`

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

<!-- end pr-codex -->
2025-05-09 17:12:44 +00:00
MananTank 7ae3a81a11 [NEB-241] Nebula: /chat endpoint schema update related changes (#6982)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on refactoring the message structure in the chat components to utilize a new `NebulaUserMessage` type, enhancing the way messages are handled and displayed throughout the application.

### Detailed summary
- Updated message structure in `Chats` and `ChatBar` to use `NebulaUserMessage`.
- Changed message content handling in `FloatingChatContent` and `ChatPageContent`.
- Modified `NebulaImage` component to accept new props.
- Adjusted `EmptyStateChatPageContent` and `Chats` to support new message format.
- Enhanced message rendering logic in `RenderMessage` and `RenderResponse` components.

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

<!-- end pr-codex -->
2025-05-09 17:03:50 +00:00
MananTank ccb9cd5d0a Dashboard: Fix team links in header on pages outside /team layout (#6981)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR modifies the `href` attribute of the `Link` component in the `TeamSelectionUI.tsx` file to ensure that the URL path is correctly constructed when navigating between team pages.

### Detailed summary
- Updated the `href` logic to check if `pathname` starts with `/team`.
- Changed the `replace` method to use the full path for `currentTeam.slug` and `team.slug`.
- Ensured that the fallback URL for the `Link` defaults to `/team/${team.slug}` when conditions are not met.

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

<!-- end pr-codex -->
2025-05-09 11:33:34 +00:00
MananTank 3dc11c087a Dashboard: Contract pages cleanup (#6991)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR primarily focuses on refactoring the contract-related code to consistently use `clientContract` and `serverContract` variables instead of `contract`. This improves clarity and ensures that the correct contract instance is used in various components.

### Detailed summary
- Replaced instances of `info.contract` with `info.clientContract` or `info.serverContract` across multiple files.
- Updated conditions checking for localhost to use `info.isLocalhostChain`.
- Modified return statements in several components to use the appropriate contract variable.
- Adjusted metadata fetching and handling to align with the new contract structure.
- Removed `ContractAnalyticsPageClient` usage in favor of direct `ContractAnalyticsPage` with `clientContract`.

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

<!-- end pr-codex -->
2025-05-09 11:18:35 +00:00
Joaquim VergesandGitHub 49479d40b0 [Dashboard] Replace serverThirdwebClient with getUserThirdwebClient (#6990) 2025-05-09 00:23:29 -07:00
Joaquim VergesGitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
3d7c2d4f67 [Auth] Replace mainnet with ANVIL_CHAIN in verifyTypedData tests (#6985)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-08 22:01:46 -07:00
Manan TankandGitHub 5b40f76b4d Dashboard: thirdweb client refactor (#6987) 2025-05-09 03:15:41 +02:00
Joaquim VergesGitHubgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
ef1550cff5 Version Packages (#6986)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-05-09 02:34:56 +02:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
b1719fd4ff chore(deps): bump github/codeql-action from 3.28.16 to 3.28.17 (#6940)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-09 02:27:42 +02:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
598d4006d9 chore(deps): bump changesets/action from 1.4.10 to 1.5.0 (#6939)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-09 02:27:23 +02:00
Jonas DanielsandGitHub bc75ae6826 Handle JWT auth method explicitly in service-utils (#6984) 2025-05-09 02:25:42 +02:00
Joe-ThirdwebGitHubsaminagraphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
8fb8a7530c [Portal] Block native to thridweb guide (#6977)
Signed-off-by: samina <[email protected]>
Co-authored-by: samina <[email protected]>
Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
2025-05-08 14:37:28 -07:00
Joaquim VergesandGitHub 106ca3cd01 [Dashboard] more robust engine cloud FTUX (#6980) 2025-05-08 14:29:14 -07:00
Jonas DanielsandGitHub 76a718c8f5 Force auth token usage for storage uploads (#6973) 2025-05-08 22:44:04 +02:00
GiselleNessi 1e924e037f updated alert description in team overview dashboard page (#6979)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on updating the content in the `page.tsx` file related to the `TeamProjectsPage` component and modifying the alert message to provide clearer information about managing engines within projects.

### Detailed summary
- Reordered the placement of the `<TeamProjectsPage>` component.
- Updated the alert message to clarify that engines, contracts, project settings, and more are managed within projects.

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

<!-- end pr-codex -->
2025-05-08 16:06:27 +00:00
Joaquim VergesandGitHub 99d2497b51 [Dashboard] Add Indonesia to SMS country select options (#6978) 2025-05-08 01:43:23 -07:00
Joaquim VergesandGitHub a5a1d17f3b [Dashboard] Add info alert about Engines moving to projects (#6976) 2025-05-07 20:47:18 -07:00
Joaquim VergesGitHubgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
62c179d775 Version Packages (#6975)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-05-07 18:44:36 -07:00
Joaquim VergesandGitHub e96ebba2cb [SDK] Add 7702 support + minimal account implementation (#6874) 2025-05-07 18:09:14 -07:00
Joaquim VergesGitHubgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
4e6daac6dd Version Packages (#6972)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-05-07 16:03:49 -07:00
Joaquim VergesandGitHub 5f6403bb8d [SDK] Fix hex value handling for smart wallet execution (#6974) 2025-05-07 15:56:47 -07:00
saminaGitHubgraphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>Joaquim Verges
4c5fc839d6 New engine docs (#6951)
Signed-off-by: samina <[email protected]>
Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
Co-authored-by: Joaquim Verges <[email protected]>
2025-05-07 14:25:21 -07:00
Joe-ThirdwebandGitHub f6eff13492 [Dashboard]: Adding new assets forPlume chains (#6971) 2025-05-07 23:03:59 +02:00
omahsandGitHub ebbda37d5a Fix typos (#6970) 2025-05-07 23:03:11 +02:00
c81fed3617 [TOOL-3337] Dashboard: Engine cloud - DO NOT MERGE (#6639)
Co-authored-by: Prithvish Baidya <[email protected]>
Co-authored-by: Joaquim Verges <[email protected]>
2025-05-08 06:53:10 +12:00
MananTank ec50f8cc3c [NEB-231] Show Image response in Nebula, minor refactor (#6964)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the chat functionality in the `nebula-app` by introducing support for image messages and refactoring the message history structure. It also adds new components for image handling and feedback actions.

### Detailed summary
- Added `request_id` to action messages in `Chats.stories.tsx`.
- Introduced `NebulaSessionHistoryMessage` type in `types.ts`.
- Updated `history` in `SessionInfo` to use `NebulaSessionHistoryMessage`.
- Implemented image message handling in `chat.ts`.
- Refactored `promptNebula` to include `request_id`.
- Created `NebulaImage` component for rendering images.
- Added `MessageActions` component for user feedback.
- Refactored `ChatPageContent` to utilize new message parsing logic.
- Updated message rendering in `Chats` to support image types.
- Removed redundant code for message handling in `ChatPageContent`.

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

<!-- end pr-codex -->
2025-05-07 14:17:51 +00:00
Joaquim VergesGitHubgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
3315a53653 Version Packages (#6968)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-05-07 01:57:16 -07:00
Joaquim VergesandGitHub 4e42158c7b [SDK] Handle Hedera native currency decimals for smart wallet calls (#6969) 2025-05-07 01:54:43 -07:00
Joaquim VergesandGitHub 5a069fe657 [PayEmbed] Always connect to destination chain if available (#6967) 2025-05-06 19:05:12 -07:00
Joaquim VergesandGitHub 490497c68b [Checkout] Enhance redirect handling for different payment types (#6959) 2025-05-06 19:04:41 -07:00
Joaquim VergesGitHubgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
bdb4c31a6a Version Packages (#6966)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-05-06 18:34:04 -07:00
MananTank 171594d66a [NEB-237] Fix Nebula OG Image (#6965)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR removes a block of code that redirects requests for the `nebula-app` path to a new URL format. This change likely simplifies the routing logic in the application.

### Detailed summary
- Removed the conditional block that checked if the first path was `nebula-app`.
- Deleted the logic to construct a new URL and redirect to `nebula.thirdweb.com`.

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

<!-- end pr-codex -->
2025-05-06 23:48:37 +00:00
Joaquim VergesandGitHub 760b250bc3 [SDK] Fix MetaMask deeplink parsing (#6963) 2025-05-06 16:48:19 -07:00
MananTank 669a95f983 Nebula: Context selection updates (#6961)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on updating the wallet management system in the `Nebula` application. It enhances context handling, modifies wallet address management, and improves the integration of active accounts.

### Detailed summary
- Replaced `activeAccountAddress` with `selectedAddress` in multiple components.
- Updated context handling to use `setContext`.
- Enhanced `WalletSelector` to use the new `selectedAddress`.
- Refactored state management for context filters in `ChatPageContent`.
- Added memoization for context filters to optimize performance.

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

<!-- end pr-codex -->
2025-05-06 23:37:15 +00:00
Phillip HoandGitHub 928113bb0b chore: Support Engine Core and Webhook usage events (#6960) 2025-05-07 06:02:11 +07:00
gregandGitHub c8b8b2faad Fix: Adds checkout error boundary (#6962) 2025-05-06 14:41:26 -07:00
MananTank 9d40b13299 DX: Improved auto imports (#6950)
Taken from:

https://x.com/dillionverma/status/1917639091228926311
2025-05-06 10:51:30 +00:00
Joaquim VergesandGitHub bda0f3edb8 [Checkout] Add theme support and improve client configuration (#6958) 2025-05-06 03:31:56 -07:00
Joaquim VergesGitHubgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
dfa3ee0231 Version Packages (#6949)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-05-06 00:00:14 -07:00
gregandGitHub 3a100c98ef fix: hide common extension name (#6957) 2025-05-05 23:56:31 -07:00
gregandGitHub 08cff4b6c2 Feature: Adds chains function (#6956) 2025-05-05 23:46:56 -07:00
gregfromstl f2b4fe6727 Feature: Checkout page (#6954)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the checkout experience in the `dashboard` app by integrating analytics and improving the layout and structure of the checkout components.

### Detailed summary
- Removed a redirect from `"/checkout"` to `"/connect"` in `apps/dashboard/redirects.js`.
- Added `THIRDWEB_ANALYTICS_DOMAIN` to `urls.ts`.
- Created `Providers` component to wrap children with `ThirdwebProvider`.
- Enhanced `CheckoutLayout` with `ThemeProvider` and layout structure.
- Updated `CheckoutEmbed` to utilize new analytics domain and handle payment success.
- Implemented a new `RoutesPage` for handling checkout logic and parameters.

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

<!-- end pr-codex -->
2025-05-06 06:36:40 +00:00
gregandGitHub 6dd2b09450 [SDK] Feature: Adds sortBy to Bridge.routes (#6955) 2025-05-05 22:15:12 -07:00
gregandGitHub 736c3f8558 [SDK] Feature: Add maxSteps to bridge quote functions (#6953) 2025-05-05 20:25:54 -07:00
gregGitHubgraphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
055e451fd0 [Portal] Clean up UB docs (#6952)
Signed-off-by: greg <[email protected]>
Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
2025-05-05 19:46:38 -07:00
MananTank 2c6bd620b5 Dashboard: Remove unused assets (#6948)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on the deletion of numerous asset files from the `apps/dashboard/public` directory and an update to the `logUnusedAssets.ts` script to adjust how asset file names are checked within the content.

### Detailed summary
- Deleted multiple asset files from `apps/dashboard/public/logos`, `apps/dashboard/public/assets`, and `apps/dashboard/public/assets/community/gallery`.
- Modified the `logUnusedAssets.ts` script:
  - Changed the condition to check for asset file names to include a leading slash: `if (content.includes(`/${assetFileName.name}`))`.

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

<!-- end pr-codex -->
2025-05-05 22:46:39 +00:00
MananTank 98e0cbdc71 [TOOL-4373] Dashboard: replace /team/~/~ with /team/<team-slug>/~ wherever possible (#6946)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the billing components in the dashboard by adding `teamSlug` as a prop to various components, allowing for better integration of team-specific billing information.

### Detailed summary
- Added `teamSlug` prop to `<CreditsInfoCard />` in `Billing/index.tsx`.
- Updated `<SmartWalletsBillingAlert />` to receive `teamSlug` in `AccountAbstractionPage.tsx`.
- Modified `CreditsInfoCard` to use `teamSlug` prop.
- Enhanced `SmartWalletsBillingAlert` to accept `teamSlug` as a prop.
- Passed `teamSlug` to the `href` in `SmartWalletsBillingAlert`.
- Included `teamSlug` in `CreditsItem` component.

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

<!-- end pr-codex -->
2025-05-05 22:46:39 +00:00
MananTank 1bc036ce6f Dashboard: Remove OPCreditsGrantedModal (#6945)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on removing several components related to onboarding and image handling from the project, as well as updating the `layout.tsx` file to eliminate the use of the `OpCreditsGrantedModalWrapperServer` component.

### Detailed summary
- Deleted the following files:
  - `apps/dashboard/src/components/Image/index.tsx`
  - `apps/dashboard/public/assets/dashboard/confetti.gif`
  - `apps/dashboard/src/components/icons/brand-icons/OpenseaIcon.tsx`
  - `apps/dashboard/src/components/onboarding/OpCreditsGrantedModal.tsx`
  - `apps/dashboard/src/components/onboarding/OpCreditsGrantedModalWrapper.tsx`
  - `apps/dashboard/src/components/onboarding/OpCreditsGrantedModalWrapperServer.tsx`
- Removed the `<OpCreditsGrantedModalWrapperServer />` component from the `layout.tsx` file.

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

<!-- end pr-codex -->
2025-05-05 22:46:39 +00:00
MananTank 9f90b87c31 [TOOL-4366] Redirect /team to last visited team (#6938)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR updates the team management functionality in the `TeamRootPage` component by replacing the method for retrieving the team with a new function that checks for the last visited team or defaults to a standard team. This improves user experience by remembering the last team visited.

### Detailed summary
- Replaced `getDefaultTeam` with `getLastVisitedTeamOrDefaultTeam` in `TeamRootPage`.
- Updated the condition to check if a team is available.
- Changed the redirect URL to use the slug of the newly retrieved `team`.
- Added `getLastVisitedTeamOrDefaultTeam` function in `team.ts` to handle team retrieval logic using cookies.

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

<!-- end pr-codex -->
2025-05-05 22:38:17 +00:00
MananTank e9d0b6e3d2 SDK: do not attempt autoconnect again if already successfull (#6900)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces a new `force` option for the auto-connect functionality in the `thirdweb` wallet, allowing users to force an auto-connect attempt even if a previous attempt was successful.

### Detailed summary
- Added `force` option to `AutoConnectProps` in `autoConnect.ts`.
- Updated `autoConnectCore` to respect the `force` option, allowing multiple connect attempts.
- Modified tests in `autoConnectCore.test.ts` to include the `force` option in various scenarios.

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

<!-- end pr-codex -->
2025-05-05 22:20:15 +00:00
GiselleNessi ee065b8d10 removed wrong link for connectButton theme (#6937)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR updates the link for the `ConnectButton` component's theme documentation from Notion to the official Thirdweb portal, ensuring users have access to the most accurate and current information.

### Detailed summary
- Changed the link for the `ConnectButton` component's theme documentation from Notion to the official Thirdweb portal.

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

<!-- end pr-codex -->
2025-05-05 19:18:07 +00:00
GiselleNessi b17078b025 [Portal] removed nebula waitlist CTA (#6936)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR updates the `page.mdx` file for the Nebula project, transitioning its status from Alpha to Beta and adding a new feature to encourage users to try the live version.

### Detailed summary
- Added `ArticleIconCard` component import from `@doc`.
- Changed status from Alpha to Beta.
- Introduced a new section with a `Stack` containing an `ArticleIconCard` to promote trying Nebula live.
- Updated the link in the `ArticleIconCard` to point to the live Nebula page.

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

<!-- end pr-codex -->
2025-05-05 19:13:45 +00:00
MananTank a4c9b28149 [TOOL-4374] Dashboard: Update Team name and slug validation (#6935)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces validation schemas for team slugs and names using `zod`, refactors the `TeamInfoForm` and `TeamGeneralSettingsPageUI` components to utilize these schemas, and enhances form handling and error messaging.

### Detailed summary
- Added `teamSlugSchema` and `teamNameSchema` for validation.
- Refactored `TeamInfoForm` to use `teamNameSchema` and `teamSlugSchema`.
- Updated form submission handling in `TeamInfoForm` and `TeamSlugFormControl`.
- Improved error handling and messaging for team name and slug inputs.
- Removed redundant validations and constants from `TeamInfoForm`.

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

<!-- end pr-codex -->
2025-05-05 18:23:28 +00:00
1290 changed files with 27397 additions and 6911 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ We use [Turborepo](https://turbo.build/repo/docs) to manage the repository, and
We use [pnpm](https://pnpm.io) for package management across the repo. `pnpm` is similar to `npm` or `yarn` but with more efficient disk space usage.
**With the v5 SDK, we've consolidated everything into a single project at [/packages/thirdweb](./packages/thirdweb). You can still find the legacy packages at [/legacy_packages](./legacy_packages).**
**With the v5 SDK, we've consolidated everything into a single project at [/packages/thirdweb](../packages/thirdweb). You can still find the legacy packages at [/legacy_packages](../legacy_packages).**
This single package provides a performant & lightweight SDK to interact with any EVM chain across Node, React, and React Native. Learn more about how to use the thirdweb SDK in our [documentation](https://portal.thirdweb.com/typescript/v5).
+3 -3
View File
@@ -46,7 +46,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@28deaeda66b76a05916b6923827895f2b14ab387 # v3.28.16
uses: github/codeql-action/init@60168efe1c415ce0f5521ea06d5c2062adbeed1b # v3.28.17
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -59,7 +59,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@28deaeda66b76a05916b6923827895f2b14ab387 # v3.28.16
uses: github/codeql-action/autobuild@60168efe1c415ce0f5521ea06d5c2062adbeed1b # v3.28.17
# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
@@ -72,4 +72,4 @@ jobs:
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@28deaeda66b76a05916b6923827895f2b14ab387 # v3.28.16
uses: github/codeql-action/analyze@60168efe1c415ce0f5521ea06d5c2062adbeed1b # v3.28.17
+1 -1
View File
@@ -36,7 +36,7 @@ jobs:
- name: Create release Pull Request or publish to NPM
id: changesets
uses: changesets/action@06245a4e0a36c064a573d4150030f5ec548e4fcc #v1.4.0
uses: changesets/action@746c25e23caa47dceb6a48ee85b4cbc5a9f5f293 #v1.4.0
with:
publish: pnpm release
version: pnpm version-packages
+2 -1
View File
@@ -30,4 +30,5 @@ packages/*/typedoc/*
storybook-static
.aider*
tsconfig.tsbuildinfo
tsconfig.tsbuildinfo
.cursor
+6
View File
@@ -9,6 +9,12 @@
"typescript.preferences.autoImportFileExcludePatterns": [
"./packages/thirdweb/src/exports"
],
"typescript.preferences.autoImportSpecifierExcludeRegexes": [
"@radix-ui",
"next/router",
"next/dist",
"^lucide-react/dist/lucide-react.suffixed$"
],
"typescript.tsdk": "node_modules/typescript/lib",
"[typescriptreact]": {
"editor.defaultFormatter": "biomejs.biome"
+5 -1
View File
@@ -104,4 +104,8 @@ ANALYTICS_SERVICE_URL=""
NEXT_PUBLIC_NEBULA_URL=""
# required for billing parts of the dashboard (team -> settings -> billing / invoices)
STRIPE_SECRET_KEY=""
STRIPE_SECRET_KEY=""
# required for server wallet management
NEXT_PUBLIC_THIRDWEB_VAULT_URL=""
NEXT_PUBLIC_ENGINE_CLOUD_URL=""
+1
View File
@@ -12,6 +12,7 @@
"ignoreDependencies": [
"@storybook/blocks",
"@thirdweb-dev/service-utils",
"@thirdweb-dev/vault-sdk",
"@types/color",
"fast-xml-parser"
]
+3
View File
@@ -0,0 +1,3 @@
declare module "lucide-react" {
export * from "lucide-react/dist/lucide-react.suffixed";
}
+1
View File
@@ -123,6 +123,7 @@ const baseNextConfig: NextConfig = {
webpackBuildWorker: true,
webpackMemoryOptimizations: true,
serverSourceMaps: false,
taint: true,
},
serverExternalPackages: ["pino-pretty"],
async headers() {
+2
View File
@@ -45,11 +45,13 @@
"@radix-ui/react-slot": "^1.2.0",
"@radix-ui/react-switch": "^1.2.2",
"@radix-ui/react-tooltip": "1.2.3",
"@scalar/api-reference-react": "^0.6.19",
"@sentry/nextjs": "9.13.0",
"@shazow/whatsabi": "0.21.0",
"@tanstack/react-query": "5.74.4",
"@tanstack/react-table": "^8.21.3",
"@thirdweb-dev/service-utils": "workspace:*",
"@thirdweb-dev/vault-sdk": "workspace:*",
"@vercel/functions": "2.0.0",
"@vercel/og": "^0.6.8",
"abitype": "1.0.8",
Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 228 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 251 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

@@ -1,6 +0,0 @@
<svg width="17" height="17" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Check Circle Icon">
<path id="Vector" d="M8.5 16.5C12.9184 16.5 16.5 12.9184 16.5 8.5C16.5 4.0816 12.9184 0.5 8.5 0.5C4.0816 0.5 0.5 4.0816 0.5 8.5C0.5 12.9184 4.0816 16.5 8.5 16.5Z" fill="white"/>
<path id="Check" d="M4.87939 9.01716L6.9482 11.086L12.1202 5.91394" stroke="#000001" stroke-width="1.23077" stroke-linecap="round" stroke-linejoin="round"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 470 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 395 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 244 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 213 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 208 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 314 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 676 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 779 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 269 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

-5
View File
@@ -100,11 +100,6 @@ async function redirects() {
destination: "/auth",
permanent: false,
},
{
source: "/checkout",
destination: "/connect",
permanent: false,
},
{
source: "/extensions",
destination: "/build",
+1 -1
View File
@@ -88,7 +88,7 @@ function main(params: { assetsFolder: string; srcFolder: string }) {
// remove the files for which its name can be found in the content of the file
folderVisitor(params.srcFolder, (content) => {
for (const assetFileName of assetFileNames) {
if (content.includes(assetFileName.name)) {
if (content.includes(`/${assetFileName.name}`)) {
unusedFileNames.delete(assetFileName);
}
}
+2 -2
View File
@@ -1,7 +1,7 @@
"use server";
import { getAuthToken } from "../../app/(app)/api/lib/getAuthToken";
import { API_SERVER_URL } from "../constants/env";
import { NEXT_PUBLIC_THIRDWEB_API_HOST } from "../constants/public-envs";
export async function acceptInvite(options: {
teamId: string;
@@ -17,7 +17,7 @@ export async function acceptInvite(options: {
}
const res = await fetch(
`${API_SERVER_URL}/v1/teams/${options.teamId}/invites/${options.inviteId}/accept`,
`${NEXT_PUBLIC_THIRDWEB_API_HOST}/v1/teams/${options.teamId}/invites/${options.inviteId}/accept`,
{
method: "POST",
headers: {
+2 -2
View File
@@ -1,7 +1,7 @@
"use server";
import { getAuthToken } from "../../app/(app)/api/lib/getAuthToken";
import { API_SERVER_URL } from "../constants/env";
import { NEXT_PUBLIC_THIRDWEB_API_HOST } from "../constants/public-envs";
export async function reSubscribePlan(options: {
teamId: string;
@@ -14,7 +14,7 @@ export async function reSubscribePlan(options: {
}
const res = await fetch(
`${API_SERVER_URL}/v1/teams/${options.teamId}/checkout/resubscribe-plan`,
`${NEXT_PUBLIC_THIRDWEB_API_HOST}/v1/teams/${options.teamId}/checkout/resubscribe-plan`,
{
method: "PUT",
headers: {
+13 -10
View File
@@ -1,7 +1,7 @@
"use server";
import { getAuthToken } from "../../app/(app)/api/lib/getAuthToken";
import { API_SERVER_URL } from "../constants/env";
import { NEXT_PUBLIC_THIRDWEB_API_HOST } from "../constants/public-envs";
export async function confirmEmailWithOTP(otp: string) {
const token = await getAuthToken();
@@ -12,16 +12,19 @@ export async function confirmEmailWithOTP(otp: string) {
};
}
const res = await fetch(`${API_SERVER_URL}/v1/account/confirmEmail`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
const res = await fetch(
`${NEXT_PUBLIC_THIRDWEB_API_HOST}/v1/account/confirmEmail`,
{
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({
confirmationToken: otp,
}),
},
body: JSON.stringify({
confirmationToken: otp,
}),
});
);
if (!res.ok) {
const json = await res.json();
@@ -2,7 +2,8 @@
import { defineDashboardChain } from "lib/defineDashboardChain";
import { ZERO_ADDRESS, isAddress, toTokens } from "thirdweb";
import { getWalletBalance } from "thirdweb/wallets";
import { getUserThirdwebClient } from "../../app/(app)/api/lib/getAuthToken";
import { MORALIS_API_KEY } from "../constants/server-envs";
import { serverThirdwebClient } from "../constants/thirdweb-client.server";
type BalanceQueryResponse = Array<{
balance: string;
@@ -23,7 +24,6 @@ export async function getTokenBalancesFromMoralis(params: {
error: string;
}
> {
const client = await getUserThirdwebClient();
const { contractAddress, chainId } = params;
if (!isAddress(contractAddress)) {
@@ -39,7 +39,7 @@ export async function getTokenBalancesFromMoralis(params: {
const balance = await getWalletBalance({
address: contractAddress,
chain,
client,
client: serverThirdwebClient,
});
return [
{
@@ -61,7 +61,7 @@ export async function getTokenBalancesFromMoralis(params: {
const resp = await fetch(tokenBalanceEndpoint, {
method: "GET",
headers: {
"x-api-key": process.env.MORALIS_API_KEY || "",
"x-api-key": MORALIS_API_KEY,
},
});
@@ -12,7 +12,8 @@ import type { WalletNFT } from "lib/wallet/nfts/types";
import { getVercelEnv } from "../../lib/vercel-utils";
import { isAlchemySupported } from "../../lib/wallet/nfts/isAlchemySupported";
import { isMoralisSupported } from "../../lib/wallet/nfts/isMoralisSupported";
import { DASHBOARD_THIRDWEB_CLIENT_ID } from "../constants/env";
import { NET_PUBLIC_DASHBOARD_THIRDWEB_CLIENT_ID } from "../constants/public-envs";
import { MORALIS_API_KEY } from "../constants/server-envs";
type WalletNFTApiReturn =
| { result: WalletNFT[]; error?: undefined }
@@ -59,13 +60,13 @@ export async function getWalletNFTs(params: {
}
}
if (isMoralisSupported(chainId) && process.env.MORALIS_API_KEY) {
if (isMoralisSupported(chainId) && MORALIS_API_KEY) {
const url = generateMoralisUrl({ chainId, owner });
const response = await fetch(url, {
method: "GET",
headers: {
"X-API-Key": process.env.MORALIS_API_KEY,
"X-API-Key": MORALIS_API_KEY,
},
next: {
revalidate: 10, // cache for 10 seconds
@@ -148,7 +149,7 @@ async function getWalletNFTsFromInsight(params: {
const response = await fetch(url, {
headers: {
"x-client-id": DASHBOARD_THIRDWEB_CLIENT_ID,
"x-client-id": NET_PUBLIC_DASHBOARD_THIRDWEB_CLIENT_ID,
},
});
+9 -10
View File
@@ -1,7 +1,11 @@
"use server";
import { getAuthToken } from "../../app/(app)/api/lib/getAuthToken";
import { API_SERVER_URL } from "../constants/env";
import {
NEXT_PUBLIC_ENGINE_CLOUD_URL,
NEXT_PUBLIC_THIRDWEB_API_HOST,
} from "../constants/public-envs";
import { ANALYTICS_SERVICE_URL } from "../constants/server-envs";
type ProxyActionParams = {
pathname: string;
@@ -76,18 +80,13 @@ async function proxy<T>(
}
export async function apiServerProxy<T>(params: ProxyActionParams) {
return proxy<T>(API_SERVER_URL, params);
return proxy<T>(NEXT_PUBLIC_THIRDWEB_API_HOST, params);
}
export async function payServerProxy<T>(params: ProxyActionParams) {
return proxy<T>(
process.env.NEXT_PUBLIC_PAY_URL
? `https://${process.env.NEXT_PUBLIC_PAY_URL}`
: "https://pay.thirdweb-dev.com",
params,
);
export async function engineCloudProxy<T>(params: ProxyActionParams) {
return proxy<T>(NEXT_PUBLIC_ENGINE_CLOUD_URL, params);
}
export async function analyticsServerProxy<T>(params: ProxyActionParams) {
return proxy<T>(process.env.ANALYTICS_SERVICE_URL || "", params);
return proxy<T>(ANALYTICS_SERVICE_URL, params);
}
+14 -11
View File
@@ -1,7 +1,7 @@
"use server";
import { getAuthToken } from "../../app/(app)/api/lib/getAuthToken";
import { API_SERVER_URL } from "../constants/env";
import { NEXT_PUBLIC_THIRDWEB_API_HOST } from "../constants/public-envs";
export async function sendTeamInvites(options: {
teamId: string;
@@ -40,17 +40,20 @@ async function sendInvite(
invite: { email: string; role: "OWNER" | "MEMBER" },
token: string,
) {
const res = await fetch(`${API_SERVER_URL}/v1/teams/${teamId}/invites`, {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
const res = await fetch(
`${NEXT_PUBLIC_THIRDWEB_API_HOST}/v1/teams/${teamId}/invites`,
{
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
inviteEmail: invite.email,
inviteRole: invite.role,
}),
},
body: JSON.stringify({
inviteEmail: invite.email,
inviteRole: invite.role,
}),
});
);
if (!res.ok) {
const errorMessage = await res.text();
@@ -2,13 +2,12 @@ import "server-only";
import Stripe from "stripe";
import type { Team } from "../api/team";
import { STRIPE_SECRET_KEY } from "../constants/server-envs";
let existingStripe: Stripe | undefined;
function getStripe() {
if (!existingStripe) {
const STRIPE_SECRET_KEY = process.env.STRIPE_SECRET_KEY;
if (!STRIPE_SECRET_KEY) {
throw new Error("STRIPE_SECRET_KEY is not set");
}
@@ -1,6 +1,6 @@
"use server";
import { getAuthToken } from "../../app/(app)/api/lib/getAuthToken";
import { API_SERVER_URL } from "../constants/env";
import { NEXT_PUBLIC_THIRDWEB_API_HOST } from "../constants/public-envs";
export async function updateAccount(values: {
name?: string;
@@ -13,7 +13,7 @@ export async function updateAccount(values: {
throw new Error("No Auth token");
}
const res = await fetch(`${API_SERVER_URL}/v1/account`, {
const res = await fetch(`${NEXT_PUBLIC_THIRDWEB_API_HOST}/v1/account`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
+75 -11
View File
@@ -6,11 +6,14 @@ import type {
InAppWalletStats,
RpcMethodStats,
TransactionStats,
UniversalBridgeStats,
UniversalBridgeWalletStats,
UserOpStats,
WalletStats,
WalletUserStats,
} from "types/analytics";
import { getAuthToken } from "../../app/(app)/api/lib/getAuthToken";
import { ANALYTICS_SERVICE_URL } from "../constants/server-envs";
import { getChains } from "./chain";
async function fetchAnalytics(
@@ -29,34 +32,38 @@ async function fetchAnalytics(
}
// create a new URL object for the analytics server
const ANALYTICS_SERVICE_URL = new URL(
process.env.ANALYTICS_SERVICE_URL || "https://analytics.thirdweb.com",
const analyticsServiceUrl = new URL(
ANALYTICS_SERVICE_URL || "https://analytics.thirdweb.com",
);
ANALYTICS_SERVICE_URL.pathname = pathname;
analyticsServiceUrl.pathname = pathname;
for (const param of searchParams?.split("&") || []) {
const [key, value] = param.split("=");
if (!key || !value) {
throw new Error("Invalid input, no key or value provided");
}
ANALYTICS_SERVICE_URL.searchParams.append(
analyticsServiceUrl.searchParams.append(
decodeURIComponent(key),
decodeURIComponent(value),
);
}
// client id DEBUG OVERRIDE
// ANALYTICS_SERVICE_URL.searchParams.delete("clientId");
// ANALYTICS_SERVICE_URL.searchParams.delete("accountId");
// ANALYTICS_SERVICE_URL.searchParams.append(
// "clientId",
// "...",
// analyticsServiceUrl.searchParams.delete("projectId");
// analyticsServiceUrl.searchParams.delete("teamId");
// analyticsServiceUrl.searchParams.append(
// "teamId",
// "team_cm0lde33r02344w129k5hm2xz",
// );
// analyticsServiceUrl.searchParams.append(
// "projectId",
// "prj_cm4rqwx9b002qrnsnr37wqpo6",
// );
return fetch(ANALYTICS_SERVICE_URL, {
return fetch(analyticsServiceUrl, {
...init,
headers: {
"content-type": "application/json",
...init?.headers,
authorization: `Bearer ${token}`,
},
});
}
@@ -367,3 +374,60 @@ export async function getEcosystemWalletUsage(args: {
return json.data as EcosystemWalletStats[];
}
export async function getUniversalBridgeUsage(args: {
teamId: string;
projectId?: string;
from?: Date;
to?: Date;
period?: "day" | "week" | "month" | "year" | "all";
}) {
const searchParams = buildSearchParams(args);
const res = await fetchAnalytics(`v2/universal?${searchParams.toString()}`, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
});
if (res?.status !== 200) {
const reason = await res?.text();
console.error(
`Failed to fetch universal bridge stats: ${res?.status} - ${res.statusText} - ${reason}`,
);
return [];
}
const json = await res.json();
return json.data as UniversalBridgeStats[];
}
export async function getUniversalBridgeWalletUsage(args: {
teamId: string;
projectId: string;
from?: Date;
to?: Date;
period?: "day" | "week" | "month" | "year" | "all";
}) {
const searchParams = buildSearchParams(args);
const res = await fetchAnalytics(
`v2/universal/wallets?${searchParams.toString()}`,
{
method: "GET",
headers: {
"Content-Type": "application/json",
},
},
);
if (res?.status !== 200) {
const reason = await res?.text();
console.error(
`Failed to fetch universal bridge wallet stats: ${res?.status} - ${res.statusText} - ${reason}`,
);
return null;
}
const json = await res.json();
return json.data as UniversalBridgeWalletStats[];
}
+16 -12
View File
@@ -1,21 +1,25 @@
import "server-only";
import type { ChainMetadata } from "thirdweb/chains";
import type { ChainService } from "../../app/(app)/(dashboard)/(chain)/types/chain";
import { API_SERVER_URL, THIRDWEB_API_SECRET } from "../constants/env";
import { NEXT_PUBLIC_THIRDWEB_API_HOST } from "../constants/public-envs";
import { API_SERVER_SECRET } from "../constants/server-envs";
export async function getGasSponsoredChains() {
if (!THIRDWEB_API_SECRET) {
if (!API_SERVER_SECRET) {
throw new Error("API_SERVER_SECRET is not set");
}
const res = await fetch(`${API_SERVER_URL}/v1/chains/gas-sponsored`, {
headers: {
"Content-Type": "application/json",
"x-service-api-key": THIRDWEB_API_SECRET,
const res = await fetch(
`${NEXT_PUBLIC_THIRDWEB_API_HOST}/v1/chains/gas-sponsored`,
{
headers: {
"Content-Type": "application/json",
"x-service-api-key": API_SERVER_SECRET,
},
next: {
revalidate: 15 * 60, //15 minutes
},
},
next: {
revalidate: 15 * 60, //15 minutes
},
});
);
if (!res.ok) {
console.error(
@@ -37,7 +41,7 @@ export async function getGasSponsoredChains() {
export function getChains() {
return fetch(
`${API_SERVER_URL}/v1/chains`,
`${NEXT_PUBLIC_THIRDWEB_API_HOST}/v1/chains`,
// revalidate every 60 minutes
{ next: { revalidate: 60 * 60 } },
).then((res) => res.json()) as Promise<{ data: ChainMetadata[] }>;
@@ -45,7 +49,7 @@ export function getChains() {
export function getChainServices() {
return fetch(
`${API_SERVER_URL}/v1/chains/services`,
`${NEXT_PUBLIC_THIRDWEB_API_HOST}/v1/chains/services`,
// revalidate every 60 minutes
{ next: { revalidate: 60 * 60 } },
).then((res) => res.json()) as Promise<{
+8 -5
View File
@@ -1,5 +1,5 @@
import { getAuthToken } from "../../app/(app)/api/lib/getAuthToken";
import { API_SERVER_URL } from "../constants/env";
import { NEXT_PUBLIC_THIRDWEB_API_HOST } from "../constants/public-envs";
export type LinkedWallet = {
createdAt: string;
@@ -14,11 +14,14 @@ export async function getLinkedWallets() {
return null;
}
const res = await fetch(`${API_SERVER_URL}/v1/account/wallets`, {
headers: {
Authorization: `Bearer ${token}`,
const res = await fetch(
`${NEXT_PUBLIC_THIRDWEB_API_HOST}/v1/account/wallets`,
{
headers: {
Authorization: `Bearer ${token}`,
},
},
});
);
if (res.ok) {
const json = (await res.json()) as {
+3 -3
View File
@@ -1,5 +1,5 @@
import "server-only";
import { API_SERVER_URL } from "@/constants/env";
import { NEXT_PUBLIC_THIRDWEB_API_HOST } from "@/constants/public-envs";
import type { ProjectResponse } from "@thirdweb-dev/service-utils";
import { getAuthToken } from "../../app/(app)/api/lib/getAuthToken";
@@ -13,7 +13,7 @@ export async function getProjects(teamSlug: string) {
}
const teamsRes = await fetch(
`${API_SERVER_URL}/v1/teams/${teamSlug}/projects`,
`${NEXT_PUBLIC_THIRDWEB_API_HOST}/v1/teams/${teamSlug}/projects`,
{
headers: {
Authorization: `Bearer ${token}`,
@@ -34,7 +34,7 @@ export async function getProject(teamSlug: string, projectSlug: string) {
}
const teamsRes = await fetch(
`${API_SERVER_URL}/v1/teams/${teamSlug}/projects/${projectSlug}`,
`${NEXT_PUBLIC_THIRDWEB_API_HOST}/v1/teams/${teamSlug}/projects/${projectSlug}`,
{
headers: {
Authorization: `Bearer ${token}`,
+15 -10
View File
@@ -1,4 +1,6 @@
import { API_SERVER_URL, THIRDWEB_API_SECRET } from "../constants/env";
import "server-only";
import { NEXT_PUBLIC_THIRDWEB_API_HOST } from "../constants/public-envs";
import { API_SERVER_SECRET } from "../constants/server-envs";
export type SMSCountryTiers = {
tier1: string[];
@@ -9,18 +11,21 @@ export type SMSCountryTiers = {
};
export async function getSMSCountryTiers() {
if (!THIRDWEB_API_SECRET) {
if (!API_SERVER_SECRET) {
throw new Error("API_SERVER_SECRET is not set");
}
const res = await fetch(`${API_SERVER_URL}/v1/sms/list-country-tiers`, {
headers: {
"Content-Type": "application/json",
"x-service-api-key": THIRDWEB_API_SECRET,
const res = await fetch(
`${NEXT_PUBLIC_THIRDWEB_API_HOST}/v1/sms/list-country-tiers`,
{
headers: {
"Content-Type": "application/json",
"x-service-api-key": API_SERVER_SECRET,
},
next: {
revalidate: 15 * 60, //15 minutes
},
},
next: {
revalidate: 15 * 60, //15 minutes
},
});
);
if (!res.ok) {
console.error(
+2 -2
View File
@@ -1,5 +1,5 @@
import { getAuthToken } from "../../app/(app)/api/lib/getAuthToken";
import { API_SERVER_URL } from "../constants/env";
import { NEXT_PUBLIC_THIRDWEB_API_HOST } from "../constants/public-envs";
export type TeamInvite = {
id: string;
@@ -25,7 +25,7 @@ export async function getTeamInvites(
}
const res = await fetch(
`${API_SERVER_URL}/v1/teams/${teamId}/invites?skip=${options.start}&take=${options.count}`,
`${NEXT_PUBLIC_THIRDWEB_API_HOST}/v1/teams/${teamId}/invites?skip=${options.start}&take=${options.count}`,
{
headers: {
Authorization: `Bearer ${authToken}`,
+3 -3
View File
@@ -1,5 +1,5 @@
import "server-only";
import { API_SERVER_URL } from "@/constants/env";
import { NEXT_PUBLIC_THIRDWEB_API_HOST } from "@/constants/public-envs";
import { getAuthToken } from "../../app/(app)/api/lib/getAuthToken";
const TeamAccountRole = {
@@ -33,7 +33,7 @@ export async function getMembers(teamSlug: string) {
}
const teamsRes = await fetch(
`${API_SERVER_URL}/v1/teams/${teamSlug}/members`,
`${NEXT_PUBLIC_THIRDWEB_API_HOST}/v1/teams/${teamSlug}/members`,
{
headers: {
Authorization: `Bearer ${token}`,
@@ -56,7 +56,7 @@ export async function getMemberById(teamSlug: string, memberId: string) {
}
const res = await fetch(
`${API_SERVER_URL}/v1/teams/${teamSlug}/members/${memberId}`,
`${NEXT_PUBLIC_THIRDWEB_API_HOST}/v1/teams/${teamSlug}/members/${memberId}`,
{
headers: {
Authorization: `Bearer ${token}`,
@@ -1,5 +1,5 @@
import { getAuthToken } from "../../app/(app)/api/lib/getAuthToken";
import { API_SERVER_URL } from "../constants/env";
import { NEXT_PUBLIC_THIRDWEB_API_HOST } from "../constants/public-envs";
import type { ProductSKU } from "../lib/billing";
type InvoiceLine = {
@@ -47,7 +47,7 @@ export async function getTeamSubscriptions(slug: string) {
}
const teamRes = await fetch(
`${API_SERVER_URL}/v1/teams/${slug}/subscriptions`,
`${NEXT_PUBLIC_THIRDWEB_API_HOST}/v1/teams/${slug}/subscriptions`,
{
headers: {
Authorization: `Bearer ${token}`,
+39 -11
View File
@@ -1,7 +1,10 @@
import "server-only";
import { API_SERVER_URL, THIRDWEB_API_SECRET } from "@/constants/env";
import { NEXT_PUBLIC_THIRDWEB_API_HOST } from "@/constants/public-envs";
import { API_SERVER_SECRET } from "@/constants/server-envs";
import type { TeamResponse } from "@thirdweb-dev/service-utils";
import { cookies } from "next/headers";
import { getAuthToken } from "../../app/(app)/api/lib/getAuthToken";
import { LAST_USED_TEAM_ID } from "../../constants/cookies";
export type Team = TeamResponse & { stripeCustomerId: string | null };
@@ -12,11 +15,14 @@ export async function getTeamBySlug(slug: string) {
return null;
}
const teamRes = await fetch(`${API_SERVER_URL}/v1/teams/${slug}`, {
headers: {
Authorization: `Bearer ${token}`,
const teamRes = await fetch(
`${NEXT_PUBLIC_THIRDWEB_API_HOST}/v1/teams/${slug}`,
{
headers: {
Authorization: `Bearer ${token}`,
},
},
});
);
if (teamRes.ok) {
return (await teamRes.json())?.result as Team;
}
@@ -24,11 +30,14 @@ export async function getTeamBySlug(slug: string) {
}
export async function service_getTeamBySlug(slug: string) {
const teamRes = await fetch(`${API_SERVER_URL}/v1/teams/${slug}`, {
headers: {
"x-service-api-key": THIRDWEB_API_SECRET,
const teamRes = await fetch(
`${NEXT_PUBLIC_THIRDWEB_API_HOST}/v1/teams/${slug}`,
{
headers: {
"x-service-api-key": API_SERVER_SECRET,
},
},
});
);
if (teamRes.ok) {
return (await teamRes.json())?.result as Team;
@@ -47,7 +56,7 @@ export async function getTeams() {
return null;
}
const teamsRes = await fetch(`${API_SERVER_URL}/v1/teams`, {
const teamsRes = await fetch(`${NEXT_PUBLIC_THIRDWEB_API_HOST}/v1/teams`, {
headers: {
Authorization: `Bearer ${token}`,
},
@@ -64,7 +73,7 @@ export async function getDefaultTeam() {
return null;
}
const res = await fetch(`${API_SERVER_URL}/v1/teams/~`, {
const res = await fetch(`${NEXT_PUBLIC_THIRDWEB_API_HOST}/v1/teams/~`, {
headers: {
Authorization: `Bearer ${token}`,
},
@@ -74,3 +83,22 @@ export async function getDefaultTeam() {
}
return null;
}
export async function getLastVisitedTeamOrDefaultTeam() {
const token = await getAuthToken();
if (!token) {
return null;
}
const cookiesStore = await cookies();
const lastVisitedTeamId = cookiesStore.get(LAST_USED_TEAM_ID)?.value;
if (lastVisitedTeamId) {
const team = await getTeamById(lastVisitedTeamId);
if (team) {
return team;
}
}
return getDefaultTeam();
}
@@ -0,0 +1 @@
export const UB_BASE_URL = process.env.NEXT_PUBLIC_THIRDWEB_BRIDGE_HOST;
@@ -1,7 +1,8 @@
"use server";
import { getAuthToken } from "app/(app)/api/lib/getAuthToken";
import { NEXT_PUBLIC_THIRDWEB_BRIDGE_HOST } from "../../constants/public-envs";
const UB_BASE_URL = process.env.NEXT_PUBLIC_THIRDWEB_BRIDGE_HOST;
const UB_BASE_URL = NEXT_PUBLIC_THIRDWEB_BRIDGE_HOST;
type Webhook = {
url: string;
@@ -15,13 +16,15 @@ type Webhook = {
export async function getWebhooks(props: {
clientId: string;
teamId: string;
}) {
const authToken = await getAuthToken();
const res = await fetch(`${UB_BASE_URL}/v1/developer/webhooks`, {
method: "GET",
headers: {
"Content-Type": "application/json",
"x-client-id-override": props.clientId,
"x-client-id": props.clientId,
"x-team-id": props.teamId,
Authorization: `Bearer ${authToken}`,
},
});
@@ -37,12 +40,20 @@ export async function getWebhooks(props: {
export async function createWebhook(props: {
clientId: string;
teamId: string;
version?: number;
url: string;
label: string;
secret?: string;
}) {
const authToken = await getAuthToken();
console.log(
"UB_BASE_URL",
UB_BASE_URL,
props.clientId,
props.teamId,
authToken,
);
const res = await fetch(`${UB_BASE_URL}/v1/developer/webhooks`, {
method: "POST",
body: JSON.stringify({
@@ -53,7 +64,8 @@ export async function createWebhook(props: {
}),
headers: {
"Content-Type": "application/json",
"x-client-id-override": props.clientId,
"x-client-id": props.clientId,
"x-team-id": props.teamId,
Authorization: `Bearer ${authToken}`,
},
});
@@ -68,6 +80,7 @@ export async function createWebhook(props: {
export async function deleteWebhook(props: {
clientId: string;
teamId: string;
webhookId: string;
}) {
const authToken = await getAuthToken();
@@ -77,7 +90,8 @@ export async function deleteWebhook(props: {
method: "DELETE",
headers: {
"Content-Type": "application/json",
"x-client-id-override": props.clientId,
"x-client-id": props.clientId,
"x-team-id": props.teamId,
Authorization: `Bearer ${authToken}`,
},
},
@@ -108,7 +122,7 @@ export async function getFees(props: {
headers: {
"Content-Type": "application/json",
"x-team-id": props.teamId,
"x-client-id-override": props.clientId,
"x-client-id": props.clientId,
Authorization: `Bearer ${authToken}`,
},
});
@@ -133,8 +147,8 @@ export async function updateFee(props: {
method: "PUT",
headers: {
"Content-Type": "application/json",
"x-client-id-override": props.clientId,
"x-team-id": props.teamId,
"x-client-id": props.clientId,
Authorization: `Bearer ${authToken}`,
},
body: JSON.stringify({
@@ -150,3 +164,87 @@ export async function updateFee(props: {
return;
}
export type PaymentsResponse = {
data: Payment[];
meta: {
totalCount: number;
};
};
export type Payment = {
id: string;
blockNumber?: bigint;
transactionId: string;
clientId: string;
sender: string;
receiver: string;
developerFeeRecipient: string;
developerFeeBps: number;
transactions: Array<{
chainId: number;
transactionHash: string;
}>;
status: "PENDING" | "COMPLETED" | "FAILED" | "NOT_FOUND";
type: "buy" | "sell" | "transfer";
originAmount: bigint;
destinationAmount: bigint;
purchaseData: unknown;
originToken: {
address: string;
symbol: string;
decimals: number;
chainId: number;
};
destinationToken: {
address: string;
symbol: string;
decimals: number;
chainId: number;
};
createdAt: string;
};
export async function getPayments(props: {
clientId: string;
teamId: string;
limit?: number;
offset?: number;
}) {
const authToken = await getAuthToken();
// Build URL with query parameters if provided
let url = `${UB_BASE_URL}/v1/developer/payments`;
const queryParams = new URLSearchParams();
if (props.limit) {
queryParams.append("limit", props.limit.toString());
}
if (props.offset) {
queryParams.append("offset", props.offset.toString());
}
// Append query params to URL if any exist
const queryString = queryParams.toString();
if (queryString) {
url = `${url}?${queryString}`;
}
const res = await fetch(url, {
method: "GET",
headers: {
"Content-Type": "application/json",
"x-client-id": props.clientId,
"x-team-id": props.teamId,
Authorization: `Bearer ${authToken}`,
},
});
if (!res.ok) {
const text = await res.text();
throw new Error(text);
}
const json = await res.json();
return json as PaymentsResponse;
}
@@ -0,0 +1,39 @@
"use server";
import { DASHBOARD_THIRDWEB_SECRET_KEY } from "@/constants/server-envs";
import { UB_BASE_URL } from "./constants";
export type TokenMetadata = {
name: string;
symbol: string;
address: string;
decimals: number;
chainId: number;
iconUri?: string;
};
export async function getUniversalBridgeTokens(props: {
chainId?: number;
}) {
const url = new URL(`${UB_BASE_URL}/v1/tokens`);
if (props.chainId) {
url.searchParams.append("chainId", String(props.chainId));
}
url.searchParams.append("limit", "1000");
const res = await fetch(url.toString(), {
method: "GET",
headers: {
"Content-Type": "application/json",
"x-secret-key": DASHBOARD_THIRDWEB_SECRET_KEY,
} as Record<string, string>,
});
if (!res.ok) {
const text = await res.text();
throw new Error(text);
}
const json = await res.json();
return json.data as Array<TokenMetadata>;
}
+3 -2
View File
@@ -1,5 +1,6 @@
import "server-only";
import { unstable_cache } from "next/cache";
import { ANALYTICS_SERVICE_URL } from "../../constants/server-envs";
export type RPCUsageDataItem = {
date: string;
@@ -16,7 +17,7 @@ export const fetchRPCUsage = unstable_cache(
to: string;
period: "day" | "week" | "month" | "year" | "all";
}) => {
const analyticsEndpoint = process.env.ANALYTICS_SERVICE_URL as string;
const analyticsEndpoint = ANALYTICS_SERVICE_URL;
const url = new URL(`${analyticsEndpoint}/v2/rpc/usage-types`);
url.searchParams.set("teamId", params.teamId);
if (params.projectId) {
@@ -79,7 +80,7 @@ export const getLast24HoursRPCUsage = unstable_cache(
projectId?: string;
authToken: string;
}) => {
const analyticsEndpoint = process.env.ANALYTICS_SERVICE_URL as string;
const analyticsEndpoint = ANALYTICS_SERVICE_URL;
const url = new URL(`${analyticsEndpoint}/v2/rpc/24-hours`);
url.searchParams.set("teamId", params.teamId);
if (params.projectId) {
+3 -3
View File
@@ -2,7 +2,7 @@
import "server-only";
import { getAuthToken } from "../../app/(app)/api/lib/getAuthToken";
import { API_SERVER_URL } from "../constants/env";
import { NEXT_PUBLIC_THIRDWEB_API_HOST } from "../constants/public-envs";
export type VerifiedDomainResponse =
| {
@@ -27,7 +27,7 @@ export async function checkDomainVerification(
}
const res = await fetch(
`${API_SERVER_URL}/v1/teams/${teamIdOrSlug}/verified-domain`,
`${NEXT_PUBLIC_THIRDWEB_API_HOST}/v1/teams/${teamIdOrSlug}/verified-domain`,
{
headers: {
Authorization: `Bearer ${token}`,
@@ -54,7 +54,7 @@ export async function createDomainVerification(
}
const res = await fetch(
`${API_SERVER_URL}/v1/teams/${teamIdOrSlug}/verified-domain`,
`${NEXT_PUBLIC_THIRDWEB_API_HOST}/v1/teams/${teamIdOrSlug}/verified-domain`,
{
method: "POST",
body: JSON.stringify({ domain }),
@@ -71,7 +71,7 @@ export function MultiNetworkSelector(props: {
return false;
}
if (Number.isInteger(Number.parseInt(searchValue))) {
if (Number.isInteger(Number(searchValue))) {
return String(chain.chainId).startsWith(searchValue);
}
return chain.name.toLowerCase().includes(searchValue.toLowerCase());
@@ -144,18 +144,26 @@ export function SingleNetworkSelector(props: {
side?: "left" | "right" | "top" | "bottom";
disableChainId?: boolean;
align?: "center" | "start" | "end";
disableTestnets?: boolean;
placeholder?: string;
client: ThirdwebClient;
}) {
const { allChains, idToChain } = useAllChainsData();
const chainsToShow = useMemo(() => {
if (!props.chainIds) {
return allChains;
let chains = allChains;
if (props.disableTestnets) {
chains = chains.filter((chain) => !chain.testnet);
}
const chainIdSet = new Set(props.chainIds);
return allChains.filter((chain) => chainIdSet.has(chain.chainId));
}, [allChains, props.chainIds]);
if (props.chainIds) {
const chainIdSet = new Set(props.chainIds);
chains = chains.filter((chain) => chainIdSet.has(chain.chainId));
}
return chains;
}, [allChains, props.chainIds, props.disableTestnets]);
const options = useMemo(() => {
return chainsToShow.map((chain) => {
@@ -173,7 +181,7 @@ export function SingleNetworkSelector(props: {
return false;
}
if (Number.isInteger(Number.parseInt(searchValue))) {
if (Number.isInteger(Number(searchValue))) {
return String(chain.chainId).startsWith(searchValue);
}
return chain.name.toLowerCase().includes(searchValue.toLowerCase());
@@ -218,6 +226,7 @@ export function SingleNetworkSelector(props: {
<SelectWithSearch
searchPlaceholder="Search by Name or Chain ID"
value={String(props.chainId)}
showCheck={false}
options={options}
onValueChange={(chainId) => {
props.onChange(Number(chainId));
@@ -95,7 +95,7 @@ export function FullWidthSidebarLayout(props: {
links={[...contentSidebarLinks, ...(footerSidebarLinks || [])]}
/>
<main className="z-0 flex min-w-0 grow flex-col max-sm:w-full">
<main className="flex min-w-0 grow flex-col max-sm:w-full">
{children}
</main>
<AppFooter containerClassName="max-w-7xl" />
@@ -137,7 +137,7 @@ function RenderSidebarGroup(props: {
}
if ("separator" in link) {
return <SidebarSeparator className="my-1" />;
return <SidebarSeparator key={Math.random()} className="my-1" />;
}
return (
@@ -0,0 +1,49 @@
import type { Meta, StoryObj } from "@storybook/react";
import { useState } from "react";
import {
BadgeContainer,
storybookThirdwebClient,
} from "../../../stories/utils";
import { TokenSelector } from "./TokenSelector";
const meta = {
title: "blocks/Cards/TokenSelector",
component: Story,
parameters: {
nextjs: {
appDirectory: true,
},
},
} satisfies Meta<typeof Story>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Variants: Story = {
args: {},
};
function Story() {
return (
<div className="container flex max-w-6xl flex-col gap-8 py-10">
<Variant label="No Chains selected by default" />
</div>
);
}
function Variant(props: {
label: string;
selectedChainId?: number;
}) {
const [tokenAddress, setTokenAddress] = useState<string>("");
return (
<BadgeContainer label={props.label}>
<TokenSelector
tokenAddress={tokenAddress}
chainId={props.selectedChainId}
client={storybookThirdwebClient}
onChange={setTokenAddress}
/>
</BadgeContainer>
);
}
@@ -0,0 +1,124 @@
import { useCallback, useMemo } from "react";
import type { ThirdwebClient } from "thirdweb";
import { shortenAddress } from "thirdweb/utils";
import { useTokensData } from "../../../hooks/tokens/tokens";
import { replaceIpfsUrl } from "../../../lib/sdk";
import { fallbackChainIcon } from "../../../utils/chain-icons";
import { cn } from "../../lib/utils";
import { Badge } from "../ui/badge";
import { Img } from "./Img";
import { SelectWithSearch } from "./select-with-search";
type Option = { label: string; value: string };
export function TokenSelector(props: {
tokenAddress: string | undefined;
onChange: (tokenAddress: string) => void;
className?: string;
popoverContentClassName?: string;
chainId?: number;
side?: "left" | "right" | "top" | "bottom";
disableChainId?: boolean;
align?: "center" | "start" | "end";
placeholder?: string;
client: ThirdwebClient;
disabled?: boolean;
enabled?: boolean;
}) {
const { tokens, isFetching } = useTokensData({
chainId: props.chainId,
enabled: props.enabled,
});
const options = useMemo(() => {
return tokens.allTokens.map((token) => {
return {
label: token.symbol,
value: `${token.chainId}:${token.address}`,
};
});
}, [tokens.allTokens]);
const searchFn = useCallback(
(option: Option, searchValue: string) => {
const token = tokens.addressChainToToken.get(option.value);
if (!token) {
return false;
}
if (Number.isInteger(Number(searchValue))) {
return String(token.chainId).startsWith(searchValue);
}
return (
token.name.toLowerCase().includes(searchValue.toLowerCase()) ||
token.symbol.toLowerCase().includes(searchValue.toLowerCase()) ||
token.address.toLowerCase().includes(searchValue.toLowerCase())
);
},
[tokens],
);
const renderOption = useCallback(
(option: Option) => {
const token = tokens.addressChainToToken.get(option.value);
if (!token) {
return option.label;
}
const resolvedSrc = token.iconUri
? replaceIpfsUrl(token.iconUri, props.client)
: fallbackChainIcon;
return (
<div className="flex items-center justify-between gap-4">
<span className="flex grow gap-2 truncate text-left">
<Img
// render different image element if src changes to avoid showing old image while loading new one
key={resolvedSrc}
className={cn("size-5 rounded-full object-contain")}
src={resolvedSrc}
loading={"lazy"}
alt=""
// eslint-disable-next-line @next/next/no-img-element
fallback={<img src={fallbackChainIcon} alt="" />}
skeleton={
<div className="animate-pulse rounded-full bg-border" />
}
/>
{token.symbol}
</span>
{!props.disableChainId && (
<Badge variant="outline" className="gap-2 max-sm:hidden">
<span className="text-muted-foreground">Address</span>
{shortenAddress(token.address, 4)}
</Badge>
)}
</div>
);
},
[tokens, props.disableChainId, props.client],
);
return (
<SelectWithSearch
searchPlaceholder="Search by name or symbol"
value={props.tokenAddress}
options={options}
onValueChange={(tokenAddress) => {
props.onChange(tokenAddress);
}}
closeOnSelect={true}
showCheck={false}
placeholder={
isFetching ? "Loading Tokens..." : props.placeholder || "Select Token"
}
overrideSearchFn={searchFn}
renderOption={renderOption}
className={props.className}
popoverContentClassName={props.popoverContentClassName}
disabled={isFetching || props.disabled}
side={props.side}
align={props.align}
/>
);
}
@@ -0,0 +1,36 @@
"use client";
import { XIcon } from "lucide-react";
import { useLocalStorage } from "../../../hooks/useLocalStorage";
import { Button } from "../ui/button";
export function DismissibleAlert(props: {
title: React.ReactNode;
description: React.ReactNode;
localStorageId: string;
}) {
const [isVisible, setIsVisible] = useLocalStorage(
props.localStorageId,
true,
false,
);
if (!isVisible) return null;
return (
<div className="relative rounded-lg border border-border bg-card p-4">
<Button
onClick={() => setIsVisible(false)}
className="absolute top-4 right-4 h-auto w-auto p-1 text-muted-foreground"
aria-label="Close alert"
variant="ghost"
>
<XIcon className="size-5" />
</Button>
<div>
<h2 className="mb-0.5 font-semibold">{props.title} </h2>
<div className="text-muted-foreground text-sm">{props.description}</div>
</div>
</div>
);
}
@@ -9,7 +9,7 @@ import {
} from "@/components/ui/popover";
import { Separator } from "@/components/ui/separator";
import { cn } from "@/lib/utils";
import { CheckIcon, ChevronDown, SearchIcon, XIcon } from "lucide-react";
import { CheckIcon, ChevronDownIcon, SearchIcon, XIcon } from "lucide-react";
import {
forwardRef,
useCallback,
@@ -201,7 +201,7 @@ export const MultiSelect = forwardRef<HTMLButtonElement, MultiSelectProps>(
orientation="vertical"
className="flex h-full min-h-6"
/>
<ChevronDown className="h-4 cursor-pointer text-muted-foreground" />
<ChevronDownIcon className="h-4 cursor-pointer text-muted-foreground" />
</div>
</div>
) : (
@@ -209,7 +209,7 @@ export const MultiSelect = forwardRef<HTMLButtonElement, MultiSelectProps>(
<span className="text-muted-foreground text-sm">
{placeholder}
</span>
<ChevronDown className="h-4 cursor-pointer text-muted-foreground" />
<ChevronDownIcon className="h-4 cursor-pointer text-muted-foreground" />
</div>
)}
</Button>
@@ -8,7 +8,7 @@ import {
PopoverTrigger,
} from "@/components/ui/popover";
import { cn } from "@/lib/utils";
import { CheckIcon, ChevronDown, SearchIcon } from "lucide-react";
import { CheckIcon, ChevronDownIcon, SearchIcon } from "lucide-react";
import React, { useRef, useMemo, useEffect } from "react";
import { useShowMore } from "../../lib/useShowMore";
import { ScrollShadow } from "../ui/ScrollShadow/ScrollShadow";
@@ -34,6 +34,7 @@ interface SelectWithSearchProps
side?: "left" | "right" | "top" | "bottom";
align?: "center" | "start" | "end";
closeOnSelect?: boolean;
showCheck?: boolean;
}
export const SelectWithSearch = React.forwardRef<
@@ -52,6 +53,7 @@ export const SelectWithSearch = React.forwardRef<
popoverContentClassName,
searchPlaceholder,
closeOnSelect,
showCheck = true,
...props
},
ref,
@@ -126,12 +128,14 @@ export const SelectWithSearch = React.forwardRef<
<span
className={cn(
"truncate text-muted-foreground text-sm",
selectedOption && "text-foreground",
selectedOption && "w-full text-foreground",
)}
>
{selectedOption?.label || placeholder}
{renderOption && selectedOption
? renderOption(selectedOption)
: selectedOption?.label || placeholder}
</span>
<ChevronDown className="size-4 cursor-pointer text-muted-foreground" />
<ChevronDownIcon className="size-4 cursor-pointer text-muted-foreground" />
</div>
</Button>
</PopoverTrigger>
@@ -191,9 +195,11 @@ export const SelectWithSearch = React.forwardRef<
i === optionsToShow.length - 1 ? lastItemRef : undefined
}
>
<div className="flex size-4 items-center justify-center">
{isSelected && <CheckIcon className="size-4" />}
</div>
{showCheck && (
<div className="flex size-4 items-center justify-center">
{isSelected && <CheckIcon className="size-4" />}
</div>
)}
<div className="min-w-0 grow">
{renderOption ? renderOption(option) : option.label}
@@ -8,7 +8,7 @@ import {
import { useThirdwebClient } from "@/constants/thirdweb.client";
import { resolveSchemeWithErrorHandler } from "@/lib/resolveSchemeWithErrorHandler";
import { useClipboard } from "hooks/useClipboard";
import { Check, Copy, XIcon } from "lucide-react";
import { CheckIcon, CopyIcon, XIcon } from "lucide-react";
import { useMemo } from "react";
import { type ThirdwebClient, isAddress } from "thirdweb";
import { ZERO_ADDRESS } from "thirdweb";
@@ -104,9 +104,9 @@ export function WalletAddress(props: {
className="flex items-center gap-2"
>
{hasCopied ? (
<Check className="h-4 w-4" />
<CheckIcon className="h-4 w-4" />
) : (
<Copy className="h-4 w-4" />
<CopyIcon className="h-4 w-4" />
)}
{hasCopied ? "Copied!" : "Copy"}
</Button>
@@ -9,11 +9,7 @@ import {
} from "@/components/ui/popover";
import { cn } from "@/lib/utils";
import { format, isBefore } from "date-fns";
import {
Calendar as CalendarIcon,
CalendarX2Icon,
ChevronDownIcon,
} from "lucide-react";
import { CalendarIcon, CalendarX2Icon, ChevronDownIcon } from "lucide-react";
import React from "react";
import { DynamicHeight } from "./DynamicHeight";
import { TabButtons } from "./tabs";
@@ -1,7 +1,7 @@
"use client";
import * as AccordionPrimitive from "@radix-ui/react-accordion";
import { ChevronDown } from "lucide-react";
import { ChevronDownIcon } from "lucide-react";
import * as React from "react";
import { cn } from "@/lib/utils";
@@ -34,7 +34,7 @@ const AccordionTrigger = React.forwardRef<
{...props}
>
{children}
<ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" />
<ChevronDownIcon className="h-4 w-4 shrink-0 transition-transform duration-200" />
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
));
@@ -1,5 +1,5 @@
import { Slot } from "@radix-ui/react-slot";
import { ChevronRight, MoreHorizontal } from "lucide-react";
import { ChevronRightIcon, MoreHorizontalIcon } from "lucide-react";
import * as React from "react";
import { cn } from "@/lib/utils";
@@ -84,7 +84,7 @@ const BreadcrumbSeparator = ({
className={cn("[&>svg]:size-3.5", className)}
{...props}
>
{children ?? <ChevronRight />}
{children ?? <ChevronRightIcon />}
</li>
);
BreadcrumbSeparator.displayName = "BreadcrumbSeparator";
@@ -102,7 +102,7 @@ const BreadcrumbEllipsis = ({
)}
{...props}
>
<MoreHorizontal className="h-4 w-4" />
<MoreHorizontalIcon className="h-4 w-4" />
<span className="sr-only">More</span>
</span>
);
@@ -22,7 +22,7 @@ const buttonVariants = cva(
link: "text-primary underline-offset-4 hover:underline text-semibold",
pink: "border border-nebula-pink-foreground !text-nebula-pink-foreground bg-[hsl(var(--nebula-pink-foreground)/5%)] hover:bg-nebula-pink-foreground/10 dark:!text-foreground dark:bg-nebula-pink-foreground/10 dark:hover:bg-nebula-pink-foreground/20",
upsell:
"bg-gradient-to-r from-purple-500 to-pink-500 text-white hover:from-purple-600 hover:to-pink-600 shadow-lg hover:shadow-xl transform hover:-translate-y-0.5 transition-all duration-200",
"bg-green-600 text-white hover:bg-green-700 shadow-lg hover:shadow-xl transform hover:-translate-y-0.5 transition-all duration-200",
},
size: {
default: "h-10 px-4 py-2",
@@ -1,6 +1,6 @@
"use client";
import { ChevronLeft, ChevronRight } from "lucide-react";
import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
import type * as React from "react";
import { DayPicker } from "react-day-picker";
@@ -54,8 +54,8 @@ function Calendar({
...classNames,
}}
components={{
IconLeft: () => <ChevronLeft className="h-4 w-4" />,
IconRight: () => <ChevronRight className="h-4 w-4" />,
IconLeft: () => <ChevronLeftIcon className="size-4" />,
IconRight: () => <ChevronRightIcon className="size-4" />,
}}
{...props}
/>
@@ -12,6 +12,7 @@ export type ChartConfig = {
[k in string]: {
label?: React.ReactNode;
icon?: React.ComponentType;
isCurrency?: boolean;
} & (
| { color?: string; theme?: never }
| { color?: never; theme: Record<keyof typeof THEMES, string> }
@@ -1,7 +1,7 @@
"use client";
import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
import { Check } from "lucide-react";
import { CheckIcon } from "lucide-react";
import * as React from "react";
import { cn } from "@/lib/utils";
@@ -21,7 +21,7 @@ const Checkbox = React.forwardRef<
<CheckboxPrimitive.Indicator
className={cn("flex items-center justify-center text-current")}
>
<Check className="h-4 w-4" />
<CheckIcon className="size-4" />
</CheckboxPrimitive.Indicator>
</CheckboxPrimitive.Root>
));
@@ -1,7 +1,7 @@
"use client";
import * as DialogPrimitive from "@radix-ui/react-dialog";
import { X } from "lucide-react";
import { XIcon } from "lucide-react";
import * as React from "react";
import { cn } from "@/lib/utils";
@@ -65,7 +65,7 @@ const DialogContent = React.forwardRef<
dialogCloseClassName,
)}
>
<X className="h-4 w-4" />
<XIcon className="size-4" />
<span className="sr-only">Close</span>
</DialogPrimitive.Close>
</DialogPrimitive.Content>
@@ -1,7 +1,7 @@
"use client";
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
import { Check, ChevronRight, Circle } from "lucide-react";
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react";
import * as React from "react";
import { cn } from "@/lib/utils";
@@ -34,7 +34,7 @@ const DropdownMenuSubTrigger = React.forwardRef<
{...props}
>
{children}
<ChevronRight className="ml-auto h-4 w-4" />
<ChevronRightIcon className="ml-auto size-4" />
</DropdownMenuPrimitive.SubTrigger>
));
DropdownMenuSubTrigger.displayName =
@@ -107,7 +107,7 @@ const DropdownMenuCheckboxItem = React.forwardRef<
>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<DropdownMenuPrimitive.ItemIndicator>
<Check className="h-4 w-4" />
<CheckIcon className="size-4" />
</DropdownMenuPrimitive.ItemIndicator>
</span>
{children}
@@ -130,7 +130,7 @@ const DropdownMenuRadioItem = React.forwardRef<
>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<DropdownMenuPrimitive.ItemIndicator>
<Circle className="h-2 w-2 fill-current" />
<CircleIcon className="size-2 fill-current" />
</DropdownMenuPrimitive.ItemIndicator>
</span>
{children}
@@ -0,0 +1,45 @@
"use client";
import { Button } from "@/components/ui/button";
import type React from "react";
import { useRef } from "react";
interface ImageUploadProps {
value: File | undefined;
onChange?: (files: File[]) => void;
children?: React.ReactNode;
variant?: React.ComponentProps<typeof Button>["variant"];
className?: string;
multiple?: boolean;
accept: string;
}
export function ImageUploadButton(props: ImageUploadProps) {
const fileInputRef = useRef<HTMLInputElement>(null);
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const files = Array.from(e.target.files || []);
props.onChange?.(files);
};
return (
<div>
<Button
variant={props.variant}
onClick={() => fileInputRef.current?.click()}
className={props.className}
>
{props.children}
</Button>
<input
ref={fileInputRef}
type="file"
multiple={props.multiple}
accept={props.accept}
onChange={handleFileChange}
className="hidden"
aria-label="Upload image"
/>
</div>
);
}
@@ -1,7 +1,7 @@
"use client";
import { OTPInput, OTPInputContext } from "input-otp";
import { Dot } from "lucide-react";
import { DotIcon } from "lucide-react";
import * as React from "react";
import { cn } from "@/lib/utils";
@@ -65,7 +65,7 @@ const InputOTPSeparator = React.forwardRef<
>(({ ...props }, ref) => (
// biome-ignore lint/a11y/useFocusableInteractive: pure shadcn component - it works
<div ref={ref} role="separator" {...props}>
<Dot />
<DotIcon />
</div>
));
InputOTPSeparator.displayName = "InputOTPSeparator";
@@ -1,4 +1,8 @@
import { ChevronLeft, ChevronRight, MoreHorizontal } from "lucide-react";
import {
ChevronLeftIcon,
ChevronRightIcon,
MoreHorizontalIcon,
} from "lucide-react";
import * as React from "react";
import { Button, type ButtonProps } from "@/components/ui/button";
@@ -66,7 +70,7 @@ const PaginationPrevious = ({
className={cn("h-10 gap-1 pl-2.5", className)}
{...props}
>
<ChevronLeft className="h-4 w-4" />
<ChevronLeftIcon className="size-4" />
<span className="max-sm:hidden">Previous</span>
</PaginationLink>
);
@@ -83,7 +87,7 @@ const PaginationNext = ({
{...props}
>
<span className="max-sm:hidden">Next</span>
<ChevronRight className="h-4 w-4" />
<ChevronRightIcon className="size-4" />
</PaginationLink>
);
PaginationNext.displayName = "PaginationNext";
@@ -100,7 +104,7 @@ const PaginationEllipsis = ({
)}
{...props}
>
<MoreHorizontal className="h-4 w-4" />
<MoreHorizontalIcon className="size-4" />
<span className="sr-only">More pages</span>
</span>
);
@@ -1,7 +1,7 @@
"use client";
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
import { Circle } from "lucide-react";
import { CircleIcon } from "lucide-react";
import * as React from "react";
import { cn } from "@/lib/utils";
@@ -35,7 +35,7 @@ const RadioGroupItem = React.forwardRef<
{...props}
>
<RadioGroupPrimitive.Indicator className="flex items-center justify-center">
<Circle className="h-2.5 w-2.5 fill-current text-current" />
<CircleIcon className="size-2.5 fill-current text-current" />
</RadioGroupPrimitive.Indicator>
</RadioGroupPrimitive.Item>
);
@@ -59,11 +59,11 @@ const RadioGroupItemButton = React.forwardRef<
<div className="flex aspect-square h-4 w-4 items-center justify-center rounded-full border text-inverted ring-offset-background transition-all focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 group-hover:border-foreground/25 group-data-[state=checked]:border-inverted">
{/* Show on checked */}
<RadioGroupPrimitive.Indicator className="flex items-center justify-center rounded-full transition-all">
<Circle className="h-2 w-2 fill-current text-current" />
<CircleIcon className="size-2 fill-current text-current" />
</RadioGroupPrimitive.Indicator>
{/* Show on hover */}
<div className="hidden items-center justify-center rounded-full text-foreground/25 transition-all group-hover:flex group-data-[state=checked]:hidden">
<Circle className="h-2 w-2 fill-current text-current" />
<CircleIcon className="size-2 fill-current text-current" />
</div>
</div>
<Label className="cursor-pointer">{props.children}</Label>

Some files were not shown because too many files have changed in this diff Show More