Compare commits

..
Author SHA1 Message Date
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
221f95b4f8 Version Packages (#5093)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-21 23:17:57 +13:00
Joaquim VergesandGitHub 223c497f49 fix: ensure smart accounts are deployed before validating signatures (#5092) 2024-10-21 23:08:43 +13:00
Joaquim VergesandGitHub 541bee5b34 fix: update useProfiles when connecting to different account (#5089) 2024-10-21 22:40:31 +13:00
MananTank df128bfc17 Open Share Modal after applying freewallets coupon (#5085)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces a new modal component, `ShareFreeWalletsModal`, to facilitate sharing free wallet offers via social media or email. It also updates the `CouponCard` to handle coupon applications and trigger the modal.

### Detailed summary
- Added `ShareFreeWalletsModal` component for sharing options.
- Created Storybook stories for `ShareFreeWalletsModal` in `share-free-wallets-modal.stories.tsx`.
- Updated `ApplyCouponCard` to include an additional parameter for coupon application callback.
- Integrated lazy loading for `ShareFreeWalletsModal` in `CouponCard`.
- Implemented state management for modal visibility in `CouponSection`.

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

<!-- end pr-codex -->
2024-10-19 18:31:07 +00:00
kien-ngo f2d10853f1 [Dashboard] Remove AddressCopyButton (#5077)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on removing the `AddressCopyButton` component from various files and replacing it with `CopyTextButton` and `CopyAddressButton` components to optimize bundle size and improve code consistency.

### Detailed summary
- Deleted `AddressCopyButton.tsx` file.
- Removed all imports of `AddressCopyButton` from multiple files.
- Replaced instances of `AddressCopyButton` with `CopyTextButton` in `webhooks-table.tsx` and `token-id.tsx`.
- Replaced `AddressCopyButton` with `CopyAddressButton` in `transaction-timeline.tsx` and `contract-subscriptions-table.tsx`.

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

<!-- end pr-codex -->
2024-10-19 08:52:15 +00:00
kien-ngo a68830ca67 [Dashboard] Edition's Mint tab to have custom recipient (#4981)
<img width="1211" alt="image" src="https://github.com/user-attachments/assets/35a4a06f-6170-4757-a901-73eb43e0af89">

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the `mint-supply-tab` component by integrating a new form validation schema using `zod`, improving the user experience with better form handling, and updating the imports for consistency.

### Detailed summary
- Added `zod` for form validation.
- Created `mintAdditionalSupplyFormSchema` to validate recipient address and mint amount.
- Refactored form handling to use the new validation schema.
- Updated the form structure with `Form`, `FormField`, and related components.
- Replaced old form submission logic with a new `onSubmit` function.
- Improved user feedback with toast notifications for transaction status.

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

<!-- end pr-codex -->
2024-10-19 08:40:16 +00:00
MananTank 5da500edca Add noUncheckedIndexedAccess: true in dashboard tsconfig and fix all issues (#5084)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces various enhancements and bug fixes across multiple files, focusing on improving type safety, handling undefined values, and refining conditions to prevent errors. It also updates the handling of cookies, contract metadata, and native token definitions.

### Detailed summary
- Added `"noUncheckedIndexedAccess": true` in `tsconfig.json`.
- Updated cookie retrieval to check for `_val` in `SyncStoreToCookies.tsx`.
- Modified ecosystem redirection condition in `EcosystemLandingPage.tsx`.
- Added checks for undefined chains in `allChains.ts`.
- Improved handling of optional values in various components.
- Enhanced error handling for uploaded files in `IconUpload.tsx`.
- Refactored native token definitions for better clarity and maintainability.
- Checked for existence of items before accessing properties in several components.
- Ensured consistent handling of optional chaining to avoid runtime errors.
- Updated metadata handling in various contract-related components.

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

<!-- end pr-codex -->
2024-10-19 02:46:44 +00:00
kien-ngo 4542a48933 [Dashboard] Add tokenURI section to the NFT page (#5035)
<img width="1172" alt="image" src="https://github.com/user-attachments/assets/bef8ec5b-b453-43e1-bc90-f7156b3dd578">

<!-- start pr-codex -->

---

## PR-Codex overview
This PR enhances the `TokenIdPage` component by adding functionality for displaying and copying the token URI of an NFT. It introduces a `CopyTextButton` and a link that opens the token URI in a new tab, improving user interaction and accessibility.

### Detailed summary
- Added import for `CopyTextButton`.
- Added import for `ExternalLinkIcon`.
- Introduced `Link` from `next/link`.
- Added `token URI` section in the UI.
- Implemented `CopyTextButton` to copy the `nft.tokenURI`.
- Added a button with a link that opens the `nft.tokenURI` in a new tab.

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

<!-- end pr-codex -->
2024-10-18 23:58:59 +00:00
Vasiliy GualotoandGitHub 17127d7763 Docs(update): Correcting the Modular contract getting started tutoria… (#5074) 2024-10-18 16:14:38 -07:00
MananTank 0dbb174e50 Mention missing Unreal Engine in various copy (#5082)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR updates the descriptions in two files to include `Unreal Engine` as a supported platform alongside `Unity` and `React Native` for social logins and smart contract integrations.

### Detailed summary
- Updated the text in `apps/dashboard/src/components/embedded-wallets/Configure/index.tsx` to include `Unreal Engine` in the supported platforms for social logins.
- Modified the `description` in `apps/dashboard/src/pages/interact.tsx` to add `Unreal Engine` as a supported platform for smart contract integrations.

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

<!-- end pr-codex -->
2024-10-18 17:18:50 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
0a1d59d789 Version Packages (#5069)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-18 10:18:08 -07:00
MananTank a04cda1e5a Improve chain page Open graph metadata + image (#5081)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the Open Graph metadata and improving the layout of the `chainPage` component in the dashboard application.

### Detailed summary
- In `layout.tsx`, added an `openGraph` object containing `title` and `description`.
- In `opengraph-image.tsx`, added the `objectFit` property with the value `"contain"` for image styling.

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

<!-- end pr-codex -->
2024-10-18 17:00:19 +00:00
gregfromstl 67a363f624 [SDK] Fix: ConnectEmbed SIWE Revalidation (#5080)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on fixing revalidation issues related to `siwe` authentication in the `ConnectEmbed` component by updating mutation keys to include the `activeAccount` address.

### Detailed summary
- Updated `mutationKey` for the `login` mutation to include `activeAccount?.address`.
- Updated `mutationKey` for the `logout` mutation to include `activeAccount?.address`.
- Added `gcTime`, `placeholderData`, and `refetchOnWindowFocus` options in the hook configuration.

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

<!-- end pr-codex -->
2024-10-18 16:23:33 +00:00
kien-ngo 1cd11a86f7 [Dashboard] Remove unnecessary chakra-ui Tabs in Listing sheet (#5076)
Remove unnecessary Tabs, just put the button at the bottom, since there's ever been only 1 tab anyway

![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/VtULqGKSp33n0VHOzNJK/53a75b30-20b2-471c-9566-4b022a96b616.png)

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on refactoring the marketplace components by removing unused files and consolidating the listing cancellation functionality into a single component, `CancelTab`. It also enhances the `ListingDrawer` component with improved UI elements for displaying asset information.

### Detailed summary
- Deleted `CancelDirectListing.tsx` and `CancelEnglishAuction.tsx`.
- Introduced `CancelTab` for handling cancellation of listings and auctions.
- Updated `ListingDrawer` to use `CancelTab`.
- Replaced `useTxNotifications` with `toast` for transaction feedback.
- Added `CopyAddressButton` and `CopyTextButton` for better user interaction.
- Refactored asset details display in `ListingDrawer` for improved readability.

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

<!-- end pr-codex -->
2024-10-18 07:46:39 +00:00
iuwqyir 9da5cd7d49 Add insight service and expose cacheOptions for node auth (#5072)
## Problem solved

This update adds the "insight" scope to API keys and exposes cacheOptions for node authentication. It also includes the "insight" service in the SERVICE_DEFINITIONS object and adds it to the HIDDEN_SERVICES array. The authorizeNode function now accepts an optional cacheOptions parameter, allowing for more flexible caching strategies in node authentication.

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the `@thirdweb-dev/service-utils` by adding an `insight` service, modifying the `CacheOptions` type, and updating the `authorizeNode` function to accept `cacheOptions`. It also includes changes to the `HIDDEN_SERVICES` constant.

### Detailed summary
- Added `insight` service with properties `name`, `title`, and `description`.
- Updated `HIDDEN_SERVICES` to include `insight`.
- Changed `CacheOptions` from a local type to an exported type.
- Modified `authorizeNode` to accept `cacheOptions` as an argument.
- Updated the call to `authorize` to include `cacheOptions`.

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

<!-- end pr-codex -->
2024-10-18 07:12:12 +00:00
kien-ngo 0dd1438012 [Dashboard] Add Cloudflare Turnstile to Faucet page (#5067)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces support for Cloudflare Turnstile captcha validation in the faucet functionality of the dashboard application, enhancing security during fund claims. It also updates dependencies and configuration for the new feature.

### Detailed summary
- Added `TURNSTILE_SITE_KEY` constant to `env.ts`.
- Updated `package.json` to include `@marsidev/react-turnstile`.
- Modified `.env.example` to add `NEXT_PUBLIC_TURNSTILE_SITE_KEY` and `TURNSTILE_SECRET_KEY`.
- Updated `next.config.js` to allow scripts from Cloudflare.
- Enhanced `POST` handler in `route.ts` to validate `turnstileToken`.
- Updated `FaucetButton.tsx` to integrate Turnstile captcha and form handling.
- Introduced `claimFaucetSchema` for form validation using `zod`.

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

<!-- end pr-codex -->
2024-10-18 05:42:42 +00:00
joaquim-verges 0f4e6622e0 feat: add custom auth options to ecosystem settings (#5075)
## Problem solved

![CleanShot 2024-10-18 at 14.59.26.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/GGPGC1k4LEcpDtkOsVBe/73287a0a-c367-4a6e-9897-5df7c2935df6.png)

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the `Ecosystem` type and its related components by adding support for custom authentication options, including headers and endpoints, and updating the mutation logic to accommodate these changes.

### Detailed summary
- Added `customAuthOptions` to the `Ecosystem` type.
- Updated `useUpdateEcosystem` to accept `Ecosystem` directly.
- Modified mutation logic to handle the new `Ecosystem` structure.
- Introduced `CustomAuthOptionsForm` for managing custom authentication endpoints and headers.
- Enhanced UI components to reflect new functionality.

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

<!-- end pr-codex -->
2024-10-18 04:47:34 +00:00
kien-ngo e67a300410 [Dashboard] Update support email to include wallet address (DASH-75) (#5055)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR refactors the `prepareEmailBody` function to accept a single `props` object instead of multiple parameters. It also updates the function to include `name` and `walletAddress`, while modifying the email body to reflect these changes.

### Detailed summary
- Changed `prepareEmailBody` to accept a single `props` object.
- Added `name` and `walletAddress` to the `props` object.
- Updated the email body to include `# Name: ${name}` and `# Wallet address: ${walletAddress}`.
- Modified the call to `prepareEmailBody` to pass a structured object instead of separate arguments.

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

<!-- end pr-codex -->
2024-10-17 21:23:34 +00:00
MananTank 00a6a56158 Move Contract page components to app router folder #2 (no code change) (#5073)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR refactors the structure of the dashboard application, changing the import paths for several components and pages to a more localized format. It also moves certain components related to contract management and permissions to new locations.

### Detailed summary
- Updated import paths for various pages and components to local paths.
- Moved `ContractSplitPage` to `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/split/ContractSplitPage.tsx`.
- Moved `DistributeButton` to `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/split/components/distribute-button.tsx`.
- Moved `ContractProposalsPage` to `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/proposals/ContractProposalsPage.tsx`.
- Moved `ContractEditModulesPage` to `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/ContractEditModulesPage.tsx`.
- Moved `ContractPermissionsPage` to `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/permissions/ContractPermissionsPage.tsx`.
- Moved `ContractExplorerPage` to `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/explorer/ContractExplorerPage.tsx`.
- Moved `ContractSettingsPage` to `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/settings/ContractSettingsPage.tsx`.
- Updated import statements in `events-feed.tsx` and `permissions/index.tsx` to reflect new paths.
- Adjusted type imports in various components to align with the new structure.

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

<!-- end pr-codex -->
2024-10-17 21:03:42 +00:00
MananTank 7855c3ea8a Move Contract page components to app router folder (no code change) (#5071)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on restructuring the file organization and imports within the `dashboard` application. It moves components to a more cohesive structure, enhancing maintainability and clarity.

### Detailed summary
- Updated imports to use relative paths instead of absolute paths.
- Renamed several component files for consistency.
- Moved `CancelDirectListing` and `CancelEnglishAuction` to a new structure under `components`.
- Adjusted imports in various `page.tsx` files to reflect new component paths.
- Consolidated marketplace-related components under a unified structure.

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

<!-- end pr-codex -->
2024-10-17 20:22:08 +00:00
GWSzeto 6597cb6525 fix: small typo (#5070)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on correcting the links in the `page.mdx` file related to modular contracts in the portal documentation.

### Detailed summary
- Fixed the link for `Create Core Contract` from `create-core-contact` to `create-core-contract`.
- Fixed the link for `Create Module Contract` from `create-module-contact` to `create-module-contract`.
- Removed the link for `Deploy Modular Contract`.

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

<!-- end pr-codex -->
2024-10-17 19:19:16 +00:00
MananTank fbd9853697 Add extra info on page crashing errors to identify them in Sentry dashboard (#5068)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR enhances error handling in the application by integrating `Sentry` with additional context for captured exceptions, specifically tagging the errors and providing extra information about the crashed page and router.

### Detailed summary
- In `global-error.tsx`, modified `Sentry.captureException` to use `Sentry.withScope` for better error context.
- Added tags and extra data (e.g., `crashedPage`, `boundary`, `router`) to the captured exceptions.
- In `_error.tsx`, implemented similar changes for handling errors with `contextData`.

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

<!-- end pr-codex -->
2024-10-17 19:02:15 +00:00
MananTank b01faacd99 Catch failed to post tracking errors (#5065)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on improving error handling in the `track.ts` file by catching errors during tracking operations to prevent them from being reported to error services.

### Detailed summary
- Modified the promise chain in `track.ts` to catch errors by adding a `.catch(() => {});` statement.
- Updated the changelog in `changeset/rotten-weeks-raise.md` to reflect the change in error handling for tracking operations.

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

<!-- end pr-codex -->
2024-10-17 18:48:28 +00:00
MananTank ef6b4f48ef Add reason string on abort() method in fetch util (#5063)
Fixes: DASH-323

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on improving error handling in the `abort` method of the `AbortController` by adding a reason string. This change aims to prevent the `AbortError: signal is aborted without reason` errors and updates tests to reflect the new error message.

### Detailed summary
- Updated the `abort` method in `fetch.ts` to include a reason string: `controller?.abort("timeout")`.
- Changed the expected error message in `download.test.ts` from "This operation was aborted" to "timeout" for two test cases.

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

<!-- end pr-codex -->
2024-10-17 18:35:23 +00:00
MananTank c5a2cdb3b6 Fix Cannot read properties of undefined (reading 'message') in errorParser.tsx (#5066)
Fixes: DASH-326
2024-10-17 18:24:12 +00:00
MananTank 5dd0c91d3e catch and handle error in TokenClaimButton (#5064)
Fixes: DASH-324
2024-10-17 18:12:22 +00:00
kien-ngo f8f90fd3ab [Dashboard] Fix prepareEvent code snippet (#5052)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on removing redundant lines of code related to the `preparedEvent` declaration in the `code-overview.tsx` file.

### Detailed summary
- Removed duplicate declarations of `preparedEvent` that included `contract` and `signature: "{{function}}"`.
- Streamlined the `getContractEvents` function call by eliminating unnecessary lines.

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

<!-- end pr-codex -->
2024-10-17 11:22:13 +00:00
joaquim-verges 63037f1bf1 fix: ensure valid block explorer URL for address links (#5061)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on updating the `href` attribute in the `metadata-header.tsx` file to ensure that the URL for the block explorer correctly appends the address, handling cases where the URL may or may not end with a trailing slash.

### Detailed summary
- Modified the `href` attribute to check if `validBlockExplorer.url` ends with a `/`.
- If it does not, a `/` is added before appending `address/${address}`.

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

<!-- end pr-codex -->
2024-10-17 05:45:07 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
b205f1d298 Version Packages (#5050)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-17 16:58:17 +13:00
Joaquim VergesandGitHub cb6a0537d8 chore: update chains (#5059) 2024-10-17 16:41:49 +13:00
gregfromstl 772604eee2 Fix: Pass iframe data on every call (#5053)
## Problem solved

This removes any assumptions of the iframe's local storage persistence.

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on fixing the flaky authentication state in Progressive Web Apps (PWAs) by enhancing the `InAppWalletIframeCommunicator` and `IframeCommunicator` classes to properly manage local storage and client information.

### Detailed summary
- Added `localStorage`, `clientId`, and `ecosystem` as parameters to `IFrameCommunicatorProps`.
- Modified the constructor of `IframeCommunicator` to accept and assign `localStorage`, `clientId`, and `ecosystem`.
- Updated `onIframeLoadedInitVariables` to retrieve authentication data from `localStorage`.
- Enhanced message posting to include initialization data with every request to handle storage resets.

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

<!-- end pr-codex -->
2024-10-17 03:05:07 +00:00
gregfromstl 6e4cd214a3 [Dashboard] Feature: AA Analytics (#5060)
![Screenshot 2024-10-16 at 6 26 17 PM](https://github.com/user-attachments/assets/0aa9b2f3-2891-4078-9251-7ba60a45f8df)

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the analytics dashboard by adding user operation statistics, improving chart components, and correcting minor naming inconsistencies.

### Detailed summary
- Fixed spelling of `DailyConnections` in `DailyConnectionsChartCard`.
- Updated the title of `DailyConnections` in its story file.
- Introduced `userOpStats` functions and types in `useApi.ts` and `storyUtils.ts`.
- Integrated `userOpUsage` and `aggregateUserOpUsage` in `ConnectAnalyticsDashboard`.
- Added `TotalSponsoredChartCard` and `SponsoredTransactionsChartCard` components with user operation stats.
- Modified `ConnectAnalyticsDashboardUI` to include new user operation metrics.
- Enhanced chart data handling for user operations in `TotalSponsoredChartCard` and `SponsoredTransactionsChartCard`.

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

<!-- end pr-codex -->
2024-10-17 01:59:46 +00:00
MananTank 77380200bb Fix Account Factories table stuck in loading state (#5058)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on updating the `enabled` property in the `AccountFactories` component's logic to check for the presence of data in `contractListQuery` more accurately.

### Detailed summary
- Changed the condition for the `enabled` property from checking `!!contractListQuery.data?.length` to `!!contractListQuery.data`.

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

<!-- end pr-codex -->
2024-10-16 21:48:35 +00:00
MananTank 85e7d15f22 Sentry config fixes for dashboard (#5056)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR updates the configuration for `Sentry` in the `next.config.js` file and modifies the `turbo.json` to include an environment variable for `SENTRY_AUTH_TOKEN`. It also refines the `Sentry` setup options for better functionality and logging.

### Detailed summary
- Added `"env": ["SENTRY_AUTH_TOKEN"]` to `turbo.json`.
- Updated `Sentry` configuration in `apps/dashboard/next.config.js`:
  - Changed `silent` from `true` to `false`.
  - Added `authToken: process.env.SENTRY_AUTH_TOKEN`.
- Retained other `Sentry` options with no changes.

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

<!-- end pr-codex -->
2024-10-16 21:23:44 +00:00
gregfromstl 3a141e742c [SDK] Feature: Twitch Login (#5047)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces a `Twitch` authentication strategy across various components in the `thirdweb` package, enhancing social login options for users.

### Detailed summary
- Added `Twitch` as a new authentication option in multiple files.
- Updated `socialAuthOptions` to include `Twitch`.
- Integrated `Twitch` icon in UI components.
- Modified authentication logic to handle `Twitch` sign-in.
- Updated relevant types and constants for `Twitch`.

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

<!-- end pr-codex -->
2024-10-15 23:34:57 +00:00
MananTank 5f09091a23 Move claim condition components in app router folder (no code change) (#5049)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on restructuring the file organization of the `claim-conditions` components, moving them from a nested path to a more streamlined directory. It also updates import paths accordingly.

### Detailed summary
- Moved `claim-conditions` components to `_components` directory.
- Updated import paths in several files to reflect the new structure.
- Adjusted the layout of the `ClaimConditions` component to use `w-full`.
- Removed the import of `SnapshotUpload` from its old path and imported it from the new location.

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

<!-- end pr-codex -->
2024-10-15 23:04:18 +00:00
MananTank d08b9be3c5 Move /nfts and /nfts/<tokenId> page components in app router folder (No code change) (#5048)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on restructuring the file paths and imports within the NFT dashboard components to improve organization and maintainability.

### Detailed summary
- Updated import paths for `TokenIdPage` and `ContractNFTPage` in the `page.tsx` files.
- Moved components from `contract-ui/tabs/nfts` to `app/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/components`.
- Added `useChainSlug` import in `table.tsx`.
- Refactored `airdrop-tab.tsx` to import `AirdropAddressInput` and `AirdropUpload` from local path.
- Adjusted import paths for `NftProperty` and `useNFTDrawerTabs` in `token-id.tsx`.
- Updated dynamic imports for several components in `useNftDrawerTabs.tsx`.

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

<!-- end pr-codex -->
2024-10-15 22:50:41 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
cb64067f47 Version Packages (#5030)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-16 11:49:41 +13:00
MananTank 2ed3be210c Move /analytics contract page in app router folder (no code change) (#5046)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on updating the import path for the `ContractAnalyticsPage` component in the `page.tsx` file located in the analytics tab of the dashboard. It simplifies the import by using a relative path.

### Detailed summary
- Changed the import path for `ContractAnalyticsPage` from a long relative path to a simplified relative import (`"./ContractAnalyticsPage"`).
- No other significant changes are noted in the diff.

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

<!-- end pr-codex -->
2024-10-15 22:27:27 +00:00
MananTank 0159983a99 Move /accounts contract page in app router folder (no code change) (#5044)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on refactoring the structure of account-related components in the dashboard, improving import paths for better clarity and maintainability.

### Detailed summary
- Updated the import path for `AccountsPage` in `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/page.tsx`.
- Removed an unnecessary import of `useChainSlug` in `accounts-table.tsx` and replaced it with a direct import.
- Added `useChainSlug` import in `accounts-table.tsx` from a new path.

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

<!-- end pr-codex -->
2024-10-15 22:27:25 +00:00
joaquim-verges ec10e81624 fix: improve wallet linking for ecosystems (#5045)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing wallet connection functionality by integrating ecosystem wallet support across various components in the `thirdweb` package.

### Detailed summary
- Updated `ConnectWalletSocialOptions.tsx` to include `ecosystem` in wallet connection.
- Modified `PassKeyLogin.tsx` to add `ecosystem` handling during signup.
- Enhanced `WalletAuth.tsx` to support ecosystem wallets.
- Improved `SocialLogin.tsx` by incorporating `ecosystem` in login methods.
- Adjusted `OTPLoginUI.tsx` to manage `ecosystem` data during authentication processes.

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

<!-- end pr-codex -->
2024-10-15 22:17:24 +00:00
MananTank eaf303bc45 Move account-permissions page components in app router folder (No code change) (#5043)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on refactoring import statements for better path clarity and consistency in the `account-signers.tsx` and `account-signer.tsx` files.

### Detailed summary
- Updated import path for `AccountSigners` in `page.tsx` from a relative path to a more concise one.
- Adjusted the import path for `useAllChainsData` in `account-signer.tsx` to reflect a simpler structure.

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

<!-- end pr-codex -->
2024-10-15 22:13:21 +00:00
MananTank 0b671fe8fc Move Account Page components in app router folder (No Code Change) (#5042)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on refactoring the code structure for better organization and maintainability, particularly in the `account` section of the dashboard. It modifies import paths and updates component references.

### Detailed summary
- Changed import path for `AccountPage` in `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/account/page.tsx`.
- Updated import path for `NFTCards` in `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/account/components/nfts-owned.tsx`.
- Modified import paths for `useV5DashboardChain` and `StoredChain` in `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/account/components/deposit-native.tsx`.

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

<!-- end pr-codex -->
2024-10-15 22:02:47 +00:00
MananTank e701fbf0d3 Migrate Marketplace listing cards on overview page to shadcn/tailwind (#5041)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR primarily focuses on updating the styling and structure of components in the `MarketplaceDetails` and `ListingCards` sections, replacing certain components with new ones and enhancing the layout.

### Detailed summary
- Changed `rounded-xl` to `rounded-lg` in `nft-media.tsx`.
- Replaced `TrackedLink` with `TrackedLinkTW` in `MarketplaceDetails.tsx`.
- Removed unused imports from `MarketplaceDetails.tsx`.
- Updated layout in `ListingCards` with a new grid structure.
- Enhanced `Skeleton` components with `SkeletonContainer` for better loading states.
- Improved styling and structure of listing items.

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

<!-- end pr-codex -->
2024-10-15 21:44:53 +00:00
MananTank ccff347d96 Migrate Marketplace Listing Stats on Contract Overview page to shadcn+tailwind (#5040)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR primarily focuses on refactoring components in the `MarketplaceDetails.tsx` and `listing-stats.tsx` files to replace instances of the `Flex` component with standard `div` elements, while also introducing a new `StatCard` component for displaying statistics.

### Detailed summary
- Replaced `Flex` components with `div` elements in `DirectListingCards`, `EnglishAuctionCards`, and `MarketplaceDetails`.
- Introduced a new `StatCard` component in `listing-stats.tsx` for displaying statistics.
- Updated the rendering of total listings, direct listings, and English auctions to use `StatCard`.

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

<!-- end pr-codex -->
2024-10-15 21:02:38 +00:00
MananTank 0cf478e33f Migrate ContractCheckList Card to shadcn + StepsCard UI adjustment (#5039)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on improving the styling and structure of the `StepsCard` component in the dashboard by modifying the layout and updating the child elements to use `<p>` tags instead of `<Text>`, along with adjusting some class names for better styling consistency.

### Detailed summary
- Increased the gap in the `flex` container from `gap-5` to `gap-7`.
- Changed the margin-bottom of a `div` from `mb-3` to `mb-1`.
- Replaced `<Text>` components with `<p>` elements for children content in multiple steps.
- Updated `Link` components with new class names for consistent styling.

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

<!-- end pr-codex -->
2024-10-15 21:02:36 +00:00
MananTank 52d89ceb6d Move contract overview page components to app router folder (No code changes) (#5038)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on refactoring the structure of the dashboard components by relocating several components to a new directory structure under `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components`.

### Detailed summary
- Moved `NFTCards` import in `nfts-owned.tsx` to a new path.
- Updated `NFTCards` import in `NFTDetails.tsx` to the new path.
- Added `getAllRoleMembers` import in `PermissionsTable.tsx` from a new path.
- Moved `getAllRoleMembers` import to a new path in `PermissionsTable.tsx`.
- Added `useContractFunctionSelectors` import in `ContractChecklist.tsx` from a new path.
- Moved `useContractFunctionSelectors` import to a new path in `ContractChecklist.tsx`.

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

<!-- end pr-codex -->
2024-10-15 21:02:35 +00:00
jnsdls 60a80ef304 remove all leftover react-icons refrerences (#5031)
<!-- start pr-codex -->

## PR-Codex overview
This PR focuses on replacing instances of `react-icons` with `lucide-react` icons across various components in the application, enhancing the icon usage consistency and potentially improving performance.

### Detailed summary
- Removed `react-icons` in favor of `lucide-react` icons in multiple components.
- Updated imports and icon usage in `EditPage`, `SponsorshipPolicies`, `GuideShowcase`, `InstalledModulesTable`, and others.
- Added a new `GithubIcon` component in `GithubButtonLink`.
- Modified the `StatusCheck` component to use `lucide-react` icons for status representation.
- Adjusted icon properties and classes for better styling and consistency.

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

<!-- end pr-codex -->
2024-10-15 17:25:48 +00:00
arcoraven 82474486eb feat: Engine delete modal now prompts to permanently delete, calls new route (#4998)
<!-- start pr-codex -->

## PR-Codex overview
This PR focuses on renaming and modifying the functionality related to deleting cloud-hosted engines in the `useEngine` hook and its usage in the `EngineInstancesTable`. The changes include updates to input types, function names, and UI elements for clarity and consistency.

### Detailed summary
- Renamed `RemoveCloudHostedInput` to `DeleteCloudHostedInput`.
- Changed `instanceId` to `deploymentId` in the input type.
- Renamed `useEngineRemoveCloudHosted` to `useEngineDeleteCloudHosted`.
- Updated API endpoint in the mutation function.
- Changed UI labels from "Remove" to "Delete" and "Cancel Engine Subscription" to "Permanently Delete Engine".
- Added feedback textarea in the delete confirmation modal.
- Enhanced alert messages for irreversible actions.
- Updated handling of deletion confirmation acknowledgment.

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

<!-- end pr-codex -->
2024-10-15 16:46:07 +00:00
kien-ngo 958bedd724 [Dashboard] Remove react-icons (1) (#5034)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on updating the icon components throughout the application, replacing icons from `react-icons` with `lucide-react` icons for a more consistent design and possibly improved performance.

### Detailed summary
- Replaced `FiArrowRight` with `MoveRightIcon` in `guide-showcase.tsx`.
- Replaced `BiChevronDown` with `ChevronDownIcon` in `NetworkSelectorButton.tsx`.
- Replaced `FiCalendar` and `FiClock` with `CalendarIcon` and `ClockIcon` in `DevRelEvent.tsx`.
- Replaced `IoCheckmarkCircle` and `AiOutlineDollarCircle` with `CircleCheckIcon` and `CircleDollarSignIcon` in `FeatureItem.tsx`.
- Replaced `AiOutlineCode` and `CgFileDocument` with `FileTextIcon` and `SquareTerminalIcon` in `CodeSelector.tsx`.
- Replaced various `react-icons` in `IpfsUploadDropzone.tsx` with `lucide-react` icons.

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

<!-- end pr-codex -->
2024-10-15 14:03:40 +00:00
kien-ngo 3fe33a6ca0 [SDK] ERC1155 extension: mintToBatch (#5032)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR adds the `mintToBatch` function to the `ERC1155` extension, allowing multiple tokens to be minted in a single transaction. It includes new tests to ensure the functionality works as expected.

### Detailed summary
- Introduced `mintToBatch` function in `mintToBatch.ts`.
- Added `MintToBatchParams` type definition.
- Updated `erc1155.ts` to export `mintToBatch` and `MintToBatchParams`.
- Created tests for `mintToBatch` in `mintToBatch.test.ts` to validate minting multiple tokens.

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

<!-- end pr-codex -->
2024-10-15 08:14:41 +00:00
joaquim-verges 1994d9e52d feat: support for enclave migration in React Native (#4992)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the `thirdweb` package by introducing support for enclave wallet migration in React Native and updating relevant dependencies, including `@thirdweb-dev/react-native-adapter`.

### Detailed summary
- Added support for enclave wallet migration in React Native.
- Updated dependency versions for `@thirdweb-dev/react-native-adapter` and `thirdweb`.
- Changed how `ecosystemId` is handled in multiple files to use an object structure.
- Enhanced error handling in wallet recovery functions.
- Updated `ConnectedButton`, `ConnectedModal`, and other UI components to accept `client` prop.
- Introduced migration functionality in `migrateToEnclaveWallet`.
- Refactored wallet-related actions to improve code consistency and structure.

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

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

<!-- end pr-codex -->
2024-10-15 08:10:05 +00:00
kien-ngo 44b2634d4c [Dashboard] Marketplace Listing drawer -> Sheet (#5008)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR refactors the `ListingDrawer` component by replacing the `Drawer` component with the `Sheet` component, streamlining the layout and improving the structure of the user interface.

### Detailed summary
- Removed `Drawer` component and replaced it with `Sheet` and `SheetContent`.
- Adjusted properties for `Sheet` to manage open state and layout.
- Updated class names for `SheetContent` to maintain styling consistency.

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

<!-- end pr-codex -->
2024-10-15 02:49:27 +00:00
kien-ngo 2e6361cc48 [Dashboard] Remove react-icons (3) (#5007)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on updating several components in the application to replace icons from `react-icons` with those from `lucide-react` and `@chakra-ui/react`, enhancing the visual consistency and modernizing the UI.

### Detailed summary
- Replaced `BsFillLightningChargeFill` with `ZapIcon` in `cta-buttons.tsx`.
- Updated `BsLightningCharge` to `ZapIcon` in `AnyEVM.tsx`.
- Added `InfoIcon` alongside `Trash2Icon` in `contract-subscriptions-table.tsx`.
- Replaced `FiInfo` with `InfoIcon` in `transaction-timeline.tsx`.
- Swapped `MdMarkEmailRead` with `MailCheckIcon` in `NewsletterSection.tsx`.
- Changed `IoIosInformationCircleOutline` to `InfoIcon` in `system-metrics/index.tsx`.
- Replaced `FaChartArea` with `ChartAreaIcon` in `system-metrics/index.tsx`.
- Updated `FiInfo` to `InfoIcon` in `transactions-table.tsx`.
- Changed `FiArrowLeft` to `MoveLeftIcon` and `FiArrowRight` to `MoveRightIcon` in `transactions-table.tsx`.
- Replaced multiple instances of `FiInfo` with `InfoIcon` in `TransactionDetailsDrawer`.

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

<!-- end pr-codex -->
2024-10-15 02:42:14 +00:00
kien-ngo d6f2acb7ac [Dashboard] Remove react-icons (2) (#5006)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on updating various components to replace icon imports from `react-icons` with icons from `lucide-react`. Additionally, it modifies the icon usage in several tables to enhance the UI consistency.

### Detailed summary
- Replaced `BsArrowRight` with `MoveRightIcon` in `RelevantDataSection`.
- Updated trash icons from `FiTrash` to `Trash2Icon` in:
  - `KeypairsTable`
  - `WebhooksTable`
  - `ContractSubscriptionTable`
  - `AdminsTable`
  - `EngineInstancesTable`
  - `RelayersTable`
  - `AccessTokensTable`
  - `BackendWalletsTable`
- Added `PencilIcon` in `AdminsTable`, `EngineInstancesTable`, `RelayersTable`, and `AccessTokensTable` for edit actions.
- Adjusted icon rendering to JSX syntax (`<IconName />`) for consistency across tables.

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

<!-- end pr-codex -->
2024-10-15 02:42:13 +00:00
kien-ngo f6cf5b5c86 [Dashboard] Remove react-icons (1) (#5005)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on replacing several instances of icon imports from `react-icons` with new icons from `lucide-react` across various components in the project, enhancing the consistency and modern look of the UI.

### Detailed summary
- Replaced `AiOutlineInfoCircle` with `CirclePlusIcon` in `FormItem.tsx`.
- Replaced `AiOutlinePlusCircle` with `CirclePlusIcon` in multiple buttons: `AddAdminButton`, `AddAccessTokenButton`, `AddKeypairButton`, `AddWebhookButton`, `AddRelayerButton`, `AddContractSubscriptionButton`.
- Updated icons in `SettingDetectedState` from `VscExtensions` to `Grid2x2XIcon` and `FiExternalLink` to `ExternalLinkIcon`.
- Replaced `BsShieldFillCheck` with `ShieldCheckIcon` and `FiArrowRight` with `MoveRightIcon` in `PublishedContractTable`.
- Updated `ModalSizeButton` to use `ListIcon` and `Rows3Icon` instead of `FaRectangleList` and `RiFileListFill`.
- In `PublishedContract`, replaced icons: `BiPencil` with `PencilIcon`, `VscCalendar` with `CalendarDaysIcon`, `VscBook` with `BookOpenTextIcon`, and `VscServer` with `ServerIcon`.

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

<!-- end pr-codex -->
2024-10-15 02:42:11 +00:00
kien-ngo 7bfad6ee74 [Dashboard] Mobile menu drawer -> Sheet (#4999)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on updating the `MobileMenu` component in the `apps/dashboard/src/components/product-pages/common/nav/MobileMenu.tsx` file by replacing the `Drawer` component with a new `Sheet` component for improved UI handling.

### Detailed summary
- Removed `display` prop from `MobileMenu` in `Topnav.tsx`.
- Changed `MobileMenu` from using `useDisclosure` to `useState` for open state management.
- Replaced `Drawer` with `Sheet` for menu display.
- Updated `IconButton` size in `MobileMenu`.
- Adjusted `onItemClick` handlers to close the menu using `setOpen(false)`.

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

<!-- end pr-codex -->
2024-10-15 02:42:10 +00:00
kien-ngo 6faf63ff95 [SDK] Fix upload reveal batch (#5009)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on fixing the upload logic for creating delayed reveal batches in the `thirdweb` package. It improves the handling of file uploads and the calculation of starting file numbers for batches, ensuring proper functionality during NFT batch creation and reveal.

### Detailed summary
- Updated `createDelayedRevealBatch` to use `Promise.all` for concurrent uploads and token ID retrieval.
- Added logic to calculate the starting file number for batch uploads.
- Removed mock implementations for certain functions in the test file.
- Enhanced test cases to verify proper creation and revealing of NFT batches.

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

<!-- end pr-codex -->
2024-10-15 01:54:28 +00:00
jnsdls da9f1964e4 update dependencies (#5029)
<!-- start pr-codex -->

## PR-Codex overview
This PR focuses on updating dependencies across multiple packages, including `@aws-sdk/client-lambda`, `@radix-ui/react-*` components, and various development tools. It also includes a code change to handle `htmlStyle` in the `RenderCode` component.

### Detailed summary
- Updated `@aws-sdk/client-lambda` to `3.670.0`.
- Updated various `@radix-ui/react-*` components to the latest versions.
- Increased the `limit` in `.size-limit.json` for `thirdweb` from `105 kB` to `110 kB`.
- Updated `typescript` and `vitest` versions across multiple packages.
- Code change in `RenderCode` to handle cases where `token.htmlStyle` is undefined.

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

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

<!-- end pr-codex -->
2024-10-14 22:52:59 +00:00
MananTank 96d4ad1849 Move Dashboard landing page to App router + Migrate to shadncn/tailwind (#4996)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on refactoring components in the `dashboard` section of the application, updating imports, and improving the layout and functionality of the `Changelog`, `HomeProductCard`, and `OnboardingSteps` components.

### Detailed summary
- Removed obsolete `Dashboard` constants.
- Updated `Link` import in `Changelog` from `tw-components` to `next/link`.
- Adjusted `Changelog` component to include a wider `Skeleton`.
- Modified `HomeProductCard` to use `next/image` and `next/link`.
- Enhanced `OnboardingSteps` to use a new structure for steps and modified the rendering logic.
- Changed step keys to a constant object format.
- Improved layout and styling for various components.

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

<!-- end pr-codex -->
2024-10-14 20:53:27 +00:00
MananTank 92fbb18ae9 Move Deployed Contracts Page to App Router (#4995)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the contract deployment and management features in the dashboard application. It introduces new components, improves layouts, and refines data handling for better user experience.

### Detailed summary
- Updated layout in `deploy.tsx` and `layout.tsx` to use flexbox for better responsiveness.
- Added `getAuthTokenWalletAddress` function in `getAuthToken.ts` for wallet address retrieval.
- Introduced `DeployedContractsPage` and `DeployedContractsTable` components for contract management.
- Refactored `DeployedContracts` component to accept contract list directly and handle loading state.
- Added `GetStartedWithContractsDeploy` component for user onboarding.
- Enhanced `DeployedContractsPageHeader` with import and deploy contract buttons.
- Improved sorting logic in `getSortedDeployedContracts.tsx`.
- Removed unused imports and cleaned up code for better readability.

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

<!-- end pr-codex -->
2024-10-14 20:53:26 +00:00
MananTank 6ceb24b0d6 Show Payment Modal when applying a coupon if account has no validPayment method setup (#5011)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR enhances the `ApplyCouponCard` and `CouponSection` components by introducing new props for handling payment setup. It allows the UI to conditionally display messages and trigger payment modals based on the payment status.

### Detailed summary
- Added `isPaymentSetup` and `onAddPayment` props to `ApplyCouponCardUI`.
- Updated `ApplyCouponCard` to handle new props.
- Modified the `onSubmit` method to check payment setup status.
- Enhanced `CouponSection` to receive and use new props.
- Replaced modal handling with state management in `Billing`.
- Updated `CouponSection` to trigger payment modal when needed.

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

<!-- end pr-codex -->
2024-10-14 20:41:47 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
e06b40ee67 chore(deps): bump react-dropzone from 14.2.3 to 14.2.9 (#5022)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-14 13:40:26 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
f0d6212ef8 chore(deps): bump @radix-ui/react-accordion from 1.2.0 to 1.2.1 (#5024)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-14 13:39:05 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
52254865d3 chore(deps): bump @radix-ui/react-switch from 1.1.0 to 1.1.1 (#5020)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-14 13:31:41 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
068a83d9bd chore(deps): bump use-debounce from 10.0.3 to 10.0.4 (#5018)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-14 13:31:25 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
744c839cfa chore(deps): bump @radix-ui/react-popover from 1.1.1 to 1.1.2 (#5017)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-14 13:31:07 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
7470677509 chore(deps-dev): bump vite from 5.4.8 to 5.4.9 (#5016)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-14 13:30:01 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
c70777e4a7 chore(deps): bump @aws-sdk/credential-providers from 3.658.1 to 3.670.0 (#5014)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-14 13:29:42 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
06219c92cb chore(deps-dev): bump typedoc from 0.26.7 to 0.26.9 (#5015)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-14 13:29:22 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
d845d3e58d chore(deps-dev): bump eslint-plugin-tailwindcss from 3.17.4 to 3.17.5 (#5013)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-14 13:29:03 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
6fb8141e24 chore(deps): bump @radix-ui/react-select from 2.1.1 to 2.1.2 (#5012)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-14 13:28:49 -07:00
arcoraven 4672475ced feat: Support multiple wallets in Engine dashboard (#4956)
- Adds support for configuring creds for AWS + GCP independently
- Moves all touched UI to tailwind
- Import / Create wallet buttons allow selecting the wallet type
- Unrelated: Moved version upgrade button to the new enpdoint. Will deprecate the old one.

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on refactoring the engine configuration components to improve how instances and wallet configurations are handled, enhancing the overall clarity and functionality of the engine's wallet management features.

### Detailed summary
- Removed `instanceUrl` prop in favor of `instance` for components.
- Introduced `LocalConfig` component for local wallet configuration.
- Added support for multiple wallet types with `EngineBackendWalletOptions`.
- Updated wallet configuration forms to use a unified `Form` component.
- Improved error handling and user feedback for wallet operations.
- Enhanced dialog components for creating and importing backend wallets.

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

<!-- end pr-codex -->
2024-10-14 19:42:57 +00:00
MananTank 926d823129 Fix ColorInput label click not triggering correct input in playground (#5010)
Fixes: DASH-315
2024-10-14 16:28:25 +00:00
kien-ngo 50e359d58b [SDK] Improve ERC1155 test coverage (#4985)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing test coverage for the ERC20 and ERC1155 extensions in the `thirdweb` package. It introduces conditional test execution based on the presence of a secret key and adds new tests to verify specific functionalities.

### Detailed summary
- Updated `describe` blocks to conditionally run tests based on `process.env.TW_SECRET_KEY` for multiple test files.
- Added tests for `isLazyMintSupported` in `erc1155: lazyMint`.
- Added tests for `isMintAdditionalSupplyToSupported` in `erc1155: mintAdditionalSupplyTo`.
- Added tests for `mintTo` functionality in `erc1155: mintTo`.
- Added tests for `isGetNFTsSupported` in `ERC1155 getNFTs`.

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

<!-- end pr-codex -->
2024-10-13 23:30:34 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
a1a6574c22 Version Packages (#5003)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-14 10:22:26 +13:00
gregandGitHub 98f358d63a fix: throw if no token is found in local storage (#4961) 2024-10-14 09:17:58 +13:00
db5457fa87 [SDK / Wallet UI] URI Connection (#4997)
Co-authored-by: Joaquim Verges <[email protected]>
2024-10-14 09:17:00 +13:00
Joaquim VergesandGitHub df0388d83b feat: expose auth options on useConnectModal (#5004) 2024-10-14 09:12:56 +13:00
kien-ngo 9685a85274 [SDK] Expose stuff for UD extensions, improve test (#4962)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the `thirdweb` SDK by exposing new functionalities related to `UnstoppableDomains`, specifically the `namehash`, `reverseNameOf`, and `exists` methods, along with related error handling and utility functions.

### Detailed summary
- Added `namehash` and `reverseNameOf` functions to `UnstoppableDomains`.
- Introduced `exists` function to check the existence of a tokenId.
- Updated `resolveAddress` to utilize `exists` for validation.
- Added error handling for non-existent domain names in tests.
- Exported new types and functions from `unstoppable-domains`.

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

<!-- end pr-codex -->
2024-10-13 08:18:44 +00:00
joaquim-verges cd2c0f3868 feat: handle zksync direct deploys in deployContract (#5002)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the `thirdweb` library with new features and bug fixes, particularly for zkSync deployments and improvements to various ERC1155 and ERC721 modules.

### Detailed summary
- Added support for zkSync direct deploys in `deployContract`.
- Updated `SequentialTokenIdERC1155` to include `startTokenId` in its module.
- Modified event signatures for `BatchMetadataUpdate` in both ERC721 and ERC1155.
- Increased test retry count and max concurrency in `vitest.config.ts`.
- Introduced new methods for batch metadata handling, including `getBatchIndex` and `getMetadataBatch`.
- Added `setBaseURI` functionality for both `BatchMetadataERC721` and `BatchMetadataERC1155`.
- Created parameter encoding functions for `updateTokenIdERC1155`.
- Enhanced error handling and configuration retrieval methods in modules.

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

<!-- end pr-codex -->
2024-10-13 06:30:11 +00:00
Joaquim VergesandGitHub 4f346e69e3 docs: update read-contract usage examples and explanations (#5001) 2024-10-12 22:13:53 +13:00
MananTank f9f536568e Remove scrollIntoView for activeTab (#5000)
Its creating issues with scrolling on iOS
2024-10-12 05:55:59 +00:00
MananTank 79f029cdae Only Show Top wallets in Connect Analytics, merge rest to Others + Remove dynamically generated colors (#4994)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the wallet analytics dashboard by improving the display of wallet statistics, adding new wallet types, and refining the chart configurations for better visualization of wallet usage data.

### Detailed summary
- Updated `globals.css` to remove redundant CSS variables.
- Added new wallet types in `storyUtils.ts`.
- Adjusted container widths in several story components to a maximum width of `1150px`.
- Enhanced `WalletConnectorsChartCard` to show top wallets and aggregate others.
- Updated chart configuration to handle "Others" category in both `WalletConnectorsChartCard` and `WalletDistributionChartCard`.
- Changed `ChartToShow` type to include `totalConnections` and `uniqueWalletsConnected`.
- Modified data handling in `WalletDistributionChartCard` to aggregate wallet stats correctly.
- Updated rendering logic to reflect changes in chart data and labels.

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

<!-- end pr-codex -->
2024-10-12 00:00:18 +05:30
gregfromstl 2914a50b84 Chore: deprecate iframe (#4991)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on deprecating two authentication strategies in the `types.ts` file related to in-app wallets. The strategies for `iframe_email_verification` and `iframe` are marked as deprecated, which indicates they should not be used in future implementations.

### Detailed summary
- Added `@deprecated` comment to the `iframe_email_verification` strategy.
- Added `@deprecated` comment to the `iframe` strategy.

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

<!-- end pr-codex -->
2024-10-11 16:46:44 +00:00
MananTank 1b559bf224 Add bottom padding to Sidebar (#4993)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on modifying the padding class in the `Sidebar.tsx` component to enhance the layout.

### Detailed summary
- Changed the class from `pt-7` to `py-7` in the `div` element, which adjusts the vertical padding (top and bottom) instead of just the top padding.

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

<!-- end pr-codex -->
2024-10-11 15:12:09 +00:00
Joaquim VergesandGitHub 982219a939 feat: add troubleshooting guide for React Native (#4990) 2024-10-11 13:36:03 +13:00
MananTank bed3561070 Update Banner copy (#4989)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR updates the text of the `label` prop in the `AnnouncementBanner` component to provide a clearer and more concise message about the promotional offer for in-app wallets.

### Detailed summary
- Updated `label` prop in the `AnnouncementBanner` from:
  - 'Get 12 months of unlimited in-app wallets by applying the "FREEWALLETS" coupon in the billing dashboard'
  - To: 'Claim 12 months of free in-app wallets. Use code "FREEWALLETS". Redeem offer by October 31st!'

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

<!-- end pr-codex -->
2024-10-10 19:39:01 +00:00
MananTank 99adbe24ca Add Unlimited wallets Banner, Add Team & Legacy dashboard links in headers (#4971)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR primarily focuses on removing the `DashboardTypeBanner` component and replacing it with the `UnlimitedWalletsBanner` in various files. It also introduces a new tooltip in the `SecondaryNav` and makes minor adjustments to the `BillingHeader` and `AnnouncementBanner`.

### Detailed summary
- Deleted `DashboardTypeBanner` component.
- Replaced instances of `TryTeamsUIBanner` and `TeamsUIBanner` with `UnlimitedWalletsBanner`.
- Added a tooltip in `SecondaryNav` for switching to the legacy dashboard.
- Simplified `BillingHeader` by changing the heading style.
- Updated `AnnouncementBanner` to include a new `UnlimitedWalletsBanner` function.

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

<!-- end pr-codex -->
2024-10-10 18:45:43 +00:00
MananTank d7e34f23e6 Add Date Range and Interval Selector on Connect Analytics page (#4988)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the date range selection functionality in the `PayAnalytics` and `ConnectAnalyticsDashboard` components by incorporating the `subDays` function and restructuring the date range handling.

### Detailed summary
- Added `subDays` import from `date-fns` for date calculations.
- Refactored `getLastNDaysRange` to use `subDays` for calculating past dates.
- Moved and restructured the `presets` rendering logic in `Filters` for clarity.
- Introduced `DateRangeSelector` and `IntervalSelector` components in `ConnectAnalyticsDashboard`.
- Replaced `useMemo` with `useState` for managing date ranges in `ConnectAnalyticsDashboard`.
- Simplified date range handling and interval type selection.

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

<!-- end pr-codex -->
2024-10-10 18:37:23 +00:00
arcoraven e06cc9b920 chore: New Engine Docs link, add some AA issues to troubleshooting guide (#4982)
<!-- start pr-codex -->

## PR-Codex overview
This PR updates the API documentation links throughout the application to point to the new `thirdweb-engine.apidocumentation.com` URLs, ensuring that users access the correct and up-to-date API references.

### Detailed summary
- Updated `API Reference` link in `sidebar.tsx`.
- Changed API reference links in `page.mdx` files for:
  - `See API reference` section.
  - `Update Chain Configuration` instructions.
  - `Cancel Transaction` references.
  - `Contract Subscriptions` references.
  - `Retry Transaction` and `Cancel` instructions.
  - `Reset Nonce` instructions.
- Added new content regarding `UserOps` and error handling.

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

<!-- end pr-codex -->
2024-10-10 17:39:01 +00:00
MananTank ec5336695b Fix unhandled server error on certain deprecated chain slugs (#4986)
Fixes: DASH-311
2024-10-10 16:25:03 +00:00
MananTank e7dd1864f9 Fix View all analytics link in contract overview page (#4987)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR updates the URL structure in the `Analytics.tsx` component to ensure the correct routing format for the analytics link.

### Detailed summary
- Changed the `href` attribute of the `Link` component from `${chainSlug}/${contractAddress}/analytics` to `/${chainSlug}/${contractAddress}/analytics` to include a leading slash.

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

<!-- end pr-codex -->
2024-10-10 16:19:02 +00:00
kien-ngo ba9a7d4148 [Dashboard] Remove react-icons (2) (#4983)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on updating icon imports from `react-icons` to `lucide-react` across several components, enhancing consistency and potentially reducing bundle size.

### Detailed summary
- Replaced `FiMenu` with `MenuIcon` in `MobileMenu.tsx`.
- Replaced `FiSearch` with `SearchIcon` in `HackathonFooter.tsx`.
- Replaced `FiArrowRight` with `MoveRightIcon` in `TWQueryTable.tsx`.
- Replaced `BsFillLightningChargeFill` with `ZapIcon` in `HomePageCard.tsx` and `HeroSection.tsx`.
- Replaced `BsShieldCheck` with `ShieldCheckIcon` in `PublishedContract`.
- Replaced `FiArrowRight` and `FaEllipsisVertical` with `MoveRightIcon` and `EllipsisVerticalIcon` in `TWTable.tsx`.

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

<!-- end pr-codex -->
2024-10-10 14:50:37 +00:00
kien-ngo c776943d4e [Dashboard] Remove react-icons (1) (#4980)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on updating icon imports in various components, replacing some icons from `react-icons` with corresponding icons from `lucide-react`, and modifying the icon usage in the `HomePageCodeBlock`, `CustomContractForm`, `PublisherSocials`, `EventsFeedItem`, and `FileInput` components.

### Detailed summary
- Replaced `BsLightning` with `ZapIcon` in `HomePageCodeBlock`.
- Replaced `FiHelpCircle` with `InfoIcon` in `CustomContractForm`.
- Replaced `FiGlobe` with `GlobeIcon` in `PublisherSocials`.
- Replaced `FiCopy` with `CopyIcon` and `FiChevronDown` with `ChevronDownIcon` in `EventsFeedItem`.
- Replaced `FiUpload` with `UploadIcon` and `FiImage` with `ImageIcon` in `FileInput`.

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

<!-- end pr-codex -->
2024-10-10 14:50:33 +00:00
kien-ngo abcbcd0b64 [Dashboard] Fix HStack (#4984)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the layout of various components in the dashboard by adding `items-center` and `gap-2` classes to `div` elements with the `flex` class. This improves vertical alignment and spacing between elements.

### Detailed summary
- Added `items-center` and `gap-2` classes to multiple `div` elements in:
  - `airdrop-upload.tsx`
  - `AccountForm.tsx`
  - `snapshot-upload.tsx`
  - `index.tsx`
  - `Steps.tsx`
  - `DowngradeDialog.tsx`
  - `PlanCard.tsx`
  - `batch-table.tsx`
  - `UsagePage.tsx`
  - `Header.tsx`
  - `Plan.tsx`

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

<!-- end pr-codex -->
2024-10-10 14:39:51 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
3d201fc603 Version Packages (#4975)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-10 21:40:11 +13:00
kien-ngo f3fee565f9 [SDK] Improve test coverage for ERC20 extensions (#4963)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on adding unit tests for various functionalities related to ERC20 contracts, including metadata retrieval, contract validation, and batch token transfers.

### Detailed summary
- Added tests for `getCurrencyMetadata` to validate ERC20 contracts and return correct metadata.
- Implemented tests for `isERC20` to check contract validity against USDT, USDC, and an NFT contract.
- Created tests for `transferBatch` to verify token transfers to multiple recipients.

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

<!-- end pr-codex -->
2024-10-10 02:32:36 +00:00
gregandGitHub ec0f8d20bb [React Native SDK] Fix: Remove device share if recovering private key fails (#4976) 2024-10-10 15:27:59 +13:00
Joaquim VergesandGitHub ccd4cd6f59 fix: overestimate zksync gas limit for paymaster extra gas (#4979) 2024-10-10 12:35:47 +13:00
MananTank bd0dbb7033 Team Member Settings Page updates (#4978)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the `TeamMembersSettingsPage` by adding an alert for unavailable features, updating the logic for invite permissions, and refining member management with improved filtering and sorting functionalities.

### Detailed summary
- Added an `Alert` component in `TeamMembersSettingsPage` to notify users about feature availability.
- Changed the condition for `inviteEnabled` in `InviteSection` to check for non-free plans.
- Updated member management logic to filter and sort members based on roles.
- Modified the `ManageMembersSection` to use filtered member lists for display and actions.
- Adjusted the `createMemberStub` function to accept a `createdHours` parameter.
- Updated storybook examples to reflect changes in team plans and permissions.

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

<!-- end pr-codex -->
2024-10-09 22:46:10 +00:00
kien-ngo f5b82308ee [Dashboard] Fix minor layer issues (#4928)
Before:
![image](https://github.com/user-attachments/assets/5429077d-24ee-4641-8025-137a67ab187d)

After:
![image](https://github.com/user-attachments/assets/72784965-1708-48a9-b614-970697ad40b9)

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on updating the layout and styling of components in the `supply-cards.tsx` and `page.tsx` files to enhance the visual structure and responsiveness of the dashboard interface.

### Detailed summary
- In `supply-cards.tsx`, changed the layout from a row (`flex-row`) to a column (`flex-col`) for better alignment.
- In `page.tsx`, modified the layout to use `flex-col` with additional styling adjustments, including:
  - Updated heading class from `font-bold text-xl` to `font-semibold text-2xl tracking-tight`.
  - Adjusted the container to use a grid layout for better responsiveness.

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

<!-- end pr-codex -->
2024-10-09 22:27:50 +00:00
joaquim-verges 7c103431c4 feat: add Soneium Minato chain definition (#4977)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on adding a new blockchain definition for `soneiumMinato` and updating the in-app wallet component to link with `Metamask` and `Passkey`.

### Detailed summary
- Added `soneiumMinato` chain definition in `packages/thirdweb/src/chains/chain-definitions/soneium-minato.ts`.
- Updated `packages/thirdweb/src/exports/chains.ts` to export `soneiumMinato`.
- Modified `apps/playground-web/src/components/in-app-wallet/profile-sections.tsx` to include buttons for linking `Metamask` and `Passkey`, replacing the `Coinbase Wallet` button.

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

<!-- end pr-codex -->
2024-10-09 21:54:57 +00:00
ElasticBottle 6a4b776ecc chore: don't override auth token / client id when hitting in app wall… (#4974)
…et url

## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the `thirdweb` dashboard by allowing account linking and improving the authorization logic in the `fetch.ts` file.

### Detailed summary
- Updated the authorization check in `fetch.ts` to exclude URLs from in-app wallets when sending the `authToken`.
- Introduced a new function `isInAppWalletUrl(url: string): boolean` to determine if a URL is from an in-app or embedded wallet.

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

<!-- end pr-codex -->
2024-10-09 18:30:50 +00:00
MananTank e29d80a9ec Spacing adjustments on account-abstraction policies form (#4973)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the layout and readability of the `SponsorshipPolicies` component in the `AccountAbstractionSettingsPage` by adjusting the spacing in flex containers and modifying text formatting for better clarity.

### Detailed summary
- Updated `div` elements to include `gap-6 lg:gap-12` for improved spacing.
- Changed text formatting to use `<br />` for line breaks instead of plain text.
- Made similar adjustments across multiple sections, including global spend limits and restrict to specific chains.

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

<!-- end pr-codex -->
2024-10-09 18:06:20 +00:00
MananTank 0c5b0bf007 Add /unlimited-wallets framer path in rewrites, format js files with biome (#4972)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on updating configuration settings, version numbers, and making minor adjustments in the codebase, including enhancing the `FRAMER_PATHS` and refining error messages in the UI.

### Detailed summary
- Added `editor.defaultFormatter` for `[javascript]` in `.vscode/settings.json`.
- Updated `version` from `5.61.3` to `5.61.4` in `packages/thirdweb/package.json`.
- Expanded `FRAMER_PATHS` in `apps/dashboard/next.config.js`.
- Added a new entry in `packages/thirdweb/CHANGELOG.md` for version `5.61.4`.
- Modified error message handling in `packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.tsx`.
- Changed fetch URL string formatting in `apps/dashboard/next-sitemap.config.js`.
- Renamed `_path` to `path` in the `transform` function of `apps/dashboard/next-sitemap.config.js`.

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

<!-- end pr-codex -->
2024-10-09 17:25:28 +00:00
MananTank 9adf6e6b25 Prefill Promo code on coupon card from search param + scroll into view (#4968)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces functionality for pre-filling a coupon code in the `ApplyCouponCard` component based on URL search parameters and enhances the user experience by scrolling into view when a coupon code is present.

### Detailed summary
- Added `BadgeContainer` for pre-filled coupon code display in `ApplyCouponCard.stories.tsx`.
- Utilized `useSearchParams` to retrieve the coupon code from the URL in `CouponCard.tsx`.
- Enhanced `ApplyCouponCardUI` to accept `prefillPromoCode` and `scrollIntoView` props.
- Implemented scrolling behavior to focus on the form when a coupon code is present.
- Wrapped `ApplyCouponCard` in a `Suspense` component to manage loading states effectively.

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

<!-- end pr-codex -->
2024-10-09 17:10:31 +00:00
MananTank 9330401645 Include search params when redirecting to login page (#4967)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the login flow by preserving search parameters in the URL when redirecting to the login page and updating the `useLoggedInUser` hook to handle login state more effectively.

### Detailed summary
- Added `searchParamsString` to include query parameters in the login redirect.
- Updated `useLoggedInUser` to redirect based on `isLoggedIn` status instead of `redirectTo`.
- Introduced `buildLoginPath` function to construct login URLs.
- Removed unused `pathname` from `EnsureLoginPayload`.

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

<!-- end pr-codex -->
2024-10-09 17:10:30 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
6527123e99 Version Packages (#4970)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-09 09:37:48 -07:00
MananTank 3446b4cabf Remove accidentally added file path in Pay UI (#4969)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on improving the user interface by removing unnecessary text from the error message displayed in the Pay UI of the `BuyScreen` component.

### Detailed summary
- Updated the error message in the `BuyScreen` component to remove extra text.
- The error message now simply states "Minimum amount is {errorMsg.minAmount}" without additional, redundant details.

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

<!-- end pr-codex -->
2024-10-09 16:07:07 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
f83d2667be Version Packages (#4966)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-09 23:33:57 +13:00
Joaquim VergesandGitHub 24981a7f60 fix: respect raw accountSalt passed as hex (#4965) 2024-10-09 23:15:58 +13:00
kien-ngo f2c40bdadc [SDK] Improve test coverage for ERC721 extensions (#4964)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the `erc721` extension by adding error handling, improving test coverage, and refining contract interactions, particularly regarding token URIs and contract support checks.

### Detailed summary
- Updated `getNFT.ts` to check for trimmed `uri`.
- Added new imports in test files for contracts and wallets.
- Implemented tests for unsupported contract methods in `getOwnedTokenIds.test.ts`.
- Added support check tests in `getNFTs.test.ts`.
- Created a test for default URI handling in `getNFT.test.ts`.

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

<!-- end pr-codex -->
2024-10-09 04:12:48 +00:00
MananTank 26e3c57e8f Complete various TODOs in team layout (#4959)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR primarily focuses on enhancing the handling of team images across various components in the dashboard. It updates the `src` attributes for `GradientAvatar` and `ProjectAvatar` components to use the appropriate team images, while also improving the `InviteSection` button functionality.

### Detailed summary
- Updated `src` for `GradientAvatar` in `TeamSelectionUI.tsx` to use `team.image`.
- Modified `className` for `Img` in `ProjectAvatar.tsx` to include an additional `border-border` class.
- Changed `src` for `titleAvatarIcon` in `TeamSettingsSidebar.tsx` to use `props.team.image`.
- Updated the `Upgrade` button in `InviteSection.tsx` to be a link to billing settings.
- Set `src` for `GradientAvatar` in `TeamHeaderUI.tsx` and `TeamHeaderMobileUI.tsx` to use `currentTeam.image`.

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

<!-- end pr-codex -->
2024-10-08 23:59:42 +00:00
gregfromstl 89bcb92619 [SDK] Test: Replace deprecated checkContractWalletSignature use (#4949)
<!-- start pr-codex -->

## PR-Codex overview
This PR focuses on updating the function used to verify wallet signatures in the `smart-wallet-integration.test.ts` file. The change improves clarity by renaming `checkContractWalletSignature` to `verifySignature` and modifies the way the contract is obtained.

### Detailed summary
- Renamed the function from `checkContractWalletSignature` to `verifySignature`.
- Changed the way the contract is constructed by removing the `getContract` call and directly using the parameters `address`, `chain`, and `client`.

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

<!-- end pr-codex -->
2024-10-08 22:22:20 +00:00
MananTank 74cd019f8a Add SelectWithSearch + Improved Single Network Selector component (#4957)
![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/yNOf1svJ8o3zjO7zQouZ/4586e4df-ba4e-4d02-b594-61c61c81f446.png)

<!-- start pr-codex -->

---

## PR-Codex overview
This PR refactors the network selection components by replacing `NetworkDropdown` with `SingleNetworkSelector` across multiple files, enhancing the network selection UI and functionality.

### Detailed summary
- Removed `NetworkDropdown` from various components.
- Introduced `SingleNetworkSelector` to replace `NetworkDropdown`.
- Updated props for `SingleNetworkSelector` to improve chain selection.
- Refactored related imports to point to the new component location.

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

<!-- end pr-codex -->
2024-10-08 22:11:19 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
f5d2d35aaa Version Packages (#4960)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-09 10:55:47 +13:00
Joaquim VergesandGitHub 4170c60ca6 fix: export fetchKeyMetadataFromApi from service-utils (#4958) 2024-10-09 10:49:19 +13:00
MananTank c723aa9d5b Improved Multi Network Selector component (#4953)
Fixes: DASH-298

Its _blazingly fast_

![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/yNOf1svJ8o3zjO7zQouZ/bf448bb9-716e-4c47-8930-0e75e5d32905.png)

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on refactoring the `NetworkDropdown` component into a new `MultiNetworkSelector` component, enhancing the multi-selection capabilities for network options while improving the overall code structure and functionality.

### Detailed summary
- Renamed `NetworkDropdown` to `MultiNetworkSelector` for multi-selection functionality.
- Updated `NetworksFieldset` and `AccountAbstractionSettingsPage` to utilize `MultiNetworkSelector`.
- Enhanced `MultiSelect` component with a `searchPlaceholder` prop and improved search functionality.
- Added `overrideSearchFn` and `renderOption` props to `MultiSelect` for customizable option rendering.
- Introduced `data-scrollable` attribute in `ScrollShadow` for better scrolling behavior.
- Improved styling and layout adjustments in various components.

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

<!-- end pr-codex -->
2024-10-08 21:33:20 +00:00
521 changed files with 15254 additions and 8015 deletions
+3
View File
@@ -21,5 +21,8 @@
},
"[markdown]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascript]": {
"editor.defaultFormatter": "biomejs.biome"
}
}
+5 -1
View File
@@ -96,4 +96,8 @@ UNTHREAD_PRO_TIER_ID=""
NEXT_PUBLIC_DEMO_ENGINE_URL=""
# API server secret (required for thirdweb.com SIWE login). Copy from Vercel.
API_SERVER_SECRET=""
API_SERVER_SECRET=""
# Used for the Faucet page (/<chain_id>)
NEXT_PUBLIC_TURNSTILE_SITE_KEY=""
TURNSTILE_SECRET_KEY=""
+4 -2
View File
@@ -3,7 +3,7 @@
*
*/
async function fetchChainsFromApi() {
const res = await fetch(`https://api.thirdweb.com/v1/chains`, {
const res = await fetch("https://api.thirdweb.com/v1/chains", {
headers: {
"Content-Type": "application/json",
},
@@ -55,7 +55,9 @@ module.exports = {
],
},
exclude: ["/chain/validate"],
transform: async (config, path) => {
transform: async (config, _path) => {
let path = _path;
// ignore og image paths
if (path.includes("_og")) {
return null;
+38 -38
View File
@@ -8,7 +8,7 @@ const ContentSecurityPolicy = `
style-src 'self' 'unsafe-inline' vercel.live;
font-src 'self' vercel.live assets.vercel.com framerusercontent.com;
frame-src * data:;
script-src 'self' 'unsafe-eval' 'unsafe-inline' 'wasm-unsafe-eval' 'inline-speculation-rules' *.thirdweb.com *.thirdweb-dev.com vercel.live js.stripe.com framerusercontent.com events.framer.com;
script-src 'self' 'unsafe-eval' 'unsafe-inline' 'wasm-unsafe-eval' 'inline-speculation-rules' *.thirdweb.com *.thirdweb-dev.com vercel.live js.stripe.com framerusercontent.com events.framer.com challenges.cloudflare.com;
connect-src * data: blob:;
worker-src 'self' blob:;
block-all-mixed-content;
@@ -40,7 +40,11 @@ const securityHeaders = [
const redirects = require("./redirects");
// add framer paths here
const FRAMER_PATHS = ["/connect/sign-in", "/contracts/modular-contracts"];
const FRAMER_PATHS = [
"/connect/sign-in",
"/contracts/modular-contracts",
"/unlimited-wallets",
];
/**
* @returns {import('next').RemotePattern[]}
@@ -163,7 +167,6 @@ const moduleExports = {
};
const { withSentryConfig } = require("@sentry/nextjs");
const { withPlausibleProxy } = require("next-plausible");
// we only want sentry on production environments
@@ -179,48 +182,45 @@ module.exports = withBundleAnalyzer(
customDomain: "https://pl.thirdweb.com",
scriptName: "pl",
})(
wSentry(
moduleExports,
{
// For all available options, see:
// https://github.com/getsentry/sentry-webpack-plugin#options
wSentry(moduleExports, {
// For all available options, see:
// https://github.com/getsentry/sentry-webpack-plugin#options
// Suppresses source map uploading logs during build
silent: true,
org: "thirdweb-dev",
project: "dashboard",
},
{
// For all available options, see:
// https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/
org: "thirdweb-dev",
project: "dashboard",
// An auth token is required for uploading source maps.
authToken: process.env.SENTRY_AUTH_TOKEN,
// Suppresses source map uploading logs during build
silent: false,
// For all available options, see:
// https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/
// Upload a larger set of source maps for prettier stack traces (increases build time)
widenClientFileUpload: true,
// Upload a larger set of source maps for prettier stack traces (increases build time)
widenClientFileUpload: true,
// Transpiles SDK to be compatible with IE11 (increases bundle size)
transpileClientSDK: false,
// Transpiles SDK to be compatible with IE11 (increases bundle size)
transpileClientSDK: false,
// Routes browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers (increases server load)
tunnelRoute: "/err",
// Routes browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers (increases server load)
tunnelRoute: "/err",
// Hides source maps from generated client bundles
hideSourceMaps: true,
// Hides source maps from generated client bundles
hideSourceMaps: true,
// Automatically tree-shake Sentry logger statements to reduce bundle size
disableLogger: true,
// Automatically tree-shake Sentry logger statements to reduce bundle size
disableLogger: true,
// Enables automatic instrumentation of Vercel Cron Monitors.
// See the following for more information:
// https://docs.sentry.io/product/crons/
// https://vercel.com/docs/cron-jobs
automaticVercelMonitors: false,
// Enables automatic instrumentation of Vercel Cron Monitors.
// See the following for more information:
// https://docs.sentry.io/product/crons/
// https://vercel.com/docs/cron-jobs
automaticVercelMonitors: false,
/**
* Disables the Sentry Webpack plugin on the server.
* See: https://github.com/getsentry/sentry-javascript/issues/10468#issuecomment-2004710692
*/
disableServerWebpackPlugin: true,
},
),
/**
* Disables the Sentry Webpack plugin on the server.
* See: https://github.com/getsentry/sentry-javascript/issues/10468#issuecomment-2004710692
*/
disableServerWebpackPlugin: true,
}),
),
);
+41 -41
View File
@@ -29,46 +29,47 @@
"@emotion/react": "11.13.3",
"@emotion/styled": "11.13.0",
"@hookform/resolvers": "^3.9.0",
"@marsidev/react-turnstile": "^1.0.2",
"@n8tb1t/use-scroll-position": "^2.0.3",
"@radix-ui/react-alert-dialog": "^1.1.1",
"@radix-ui/react-avatar": "^1.1.0",
"@radix-ui/react-checkbox": "^1.1.1",
"@radix-ui/react-dialog": "1.1.1",
"@radix-ui/react-dropdown-menu": "^2.1.1",
"@radix-ui/react-hover-card": "^1.1.1",
"@radix-ui/react-alert-dialog": "^1.1.2",
"@radix-ui/react-avatar": "^1.1.1",
"@radix-ui/react-checkbox": "^1.1.2",
"@radix-ui/react-dialog": "1.1.2",
"@radix-ui/react-dropdown-menu": "^2.1.2",
"@radix-ui/react-hover-card": "^1.1.2",
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-popover": "^1.1.1",
"@radix-ui/react-popover": "^1.1.2",
"@radix-ui/react-progress": "^1.1.0",
"@radix-ui/react-radio-group": "^1.2.0",
"@radix-ui/react-select": "^2.1.1",
"@radix-ui/react-radio-group": "^1.2.1",
"@radix-ui/react-select": "^2.1.2",
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-switch": "^1.1.0",
"@radix-ui/react-tooltip": "1.1.2",
"@sentry/nextjs": "8.32.0",
"@shazow/whatsabi": "^0.15.2",
"@stripe/react-stripe-js": "^2.7.3",
"@radix-ui/react-switch": "^1.1.1",
"@radix-ui/react-tooltip": "1.1.3",
"@sentry/nextjs": "8.34.0",
"@shazow/whatsabi": "^0.15.3",
"@stripe/react-stripe-js": "^2.8.1",
"@stripe/stripe-js": "^3.5.0",
"@tanstack/react-query": "5.56.2",
"@tanstack/react-query": "5.59.13",
"@tanstack/react-table": "^8.17.3",
"@thirdweb-dev/service-utils": "workspace:*",
"@vercel/og": "^0.6.2",
"abitype": "1.0.5",
"abitype": "1.0.6",
"chakra-react-select": "^4.7.6",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"color": "^4.2.3",
"compare-versions": "^6.1.0",
"date-fns": "^3.6.0",
"date-fns": "4.1.0",
"flat": "^6.0.1",
"framer-motion": "11.9.0",
"framer-motion": "11.11.8",
"fuse.js": "7.0.0",
"input-otp": "^1.2.4",
"ioredis": "^5.4.1",
"ipaddr.js": "^2.2.0",
"lottie-react": "^2.4.0",
"lucide-react": "0.441.0",
"next": "14.2.13",
"lucide-react": "0.452.0",
"next": "14.2.15",
"next-plausible": "^3.12.0",
"next-seo": "^6.5.0",
"next-themes": "^0.3.0",
@@ -83,48 +84,47 @@
"react-children-utilities": "^2.10.0",
"react-day-picker": "^8.10.1",
"react-dom": "18.3.1",
"react-dropzone": "^14.2.3",
"react-dropzone": "^14.2.9",
"react-hook-form": "7.52.0",
"react-icons": "^5.2.1",
"react-intersection-observer": "^9.10.3",
"react-markdown": "^9.0.1",
"react-responsive-carousel": "^3.2.23",
"react-table": "^7.8.0",
"recharts": "^2.12.7",
"recharts": "^2.13.0",
"remark-gfm": "^4.0.0",
"server-only": "^0.0.1",
"sonner": "^1.5.0",
"spdx-correct": "^3.2.0",
"swagger-ui-react": "^5.17.14",
"tailwind-merge": "^2.5.2",
"tailwind-merge": "^2.5.4",
"tailwindcss-animate": "^1.0.7",
"thirdweb": "workspace:*",
"tiny-invariant": "^1.3.3",
"use-debounce": "^10.0.1",
"use-debounce": "^10.0.4",
"zod": "3.23.8"
},
"devDependencies": {
"@chakra-ui/cli": "^2.4.1",
"@chromatic-com/storybook": "2.0.2",
"@next/bundle-analyzer": "14.2.13",
"@next/eslint-plugin-next": "14.2.13",
"@next/bundle-analyzer": "14.2.15",
"@next/eslint-plugin-next": "14.2.15",
"@playwright/test": "1.47.2",
"@storybook/addon-essentials": "8.3.4",
"@storybook/addon-essentials": "8.3.5",
"@storybook/addon-interactions": "8.3.5",
"@storybook/addon-links": "8.3.4",
"@storybook/addon-onboarding": "8.3.4",
"@storybook/addon-viewport": "8.3.4",
"@storybook/blocks": "8.3.4",
"@storybook/nextjs": "8.3.4",
"@storybook/react": "8.3.4",
"@storybook/addon-links": "8.3.5",
"@storybook/addon-onboarding": "8.3.5",
"@storybook/addon-viewport": "8.3.5",
"@storybook/blocks": "8.3.5",
"@storybook/nextjs": "8.3.5",
"@storybook/react": "8.3.5",
"@storybook/test": "8.3.5",
"@types/color": "^3.0.6",
"@types/node": "20.14.9",
"@types/papaparse": "^5.3.14",
"@types/pluralize": "^0.0.33",
"@types/qrcode": "^1.5.5",
"@types/react": "^18.3.10",
"@types/react-dom": "^18",
"@types/react": "^18.3.11",
"@types/react-dom": "^18.3.1",
"@types/react-table": "^7.7.20",
"@types/spdx-correct": "^3.1.3",
"@types/swagger-ui-react": "^4.18.3",
@@ -133,14 +133,14 @@
"autoprefixer": "^10.4.19",
"checkly": "^4.8.1",
"eslint": "8.57.0",
"eslint-config-biome": "1.8.4",
"eslint-plugin-react-compiler": "0.0.0-experimental-ca16900-20240916",
"eslint-config-biome": "1.9.3",
"eslint-plugin-react-compiler": "0.0.0-experimental-fa06e2c-20241014",
"eslint-plugin-storybook": "^0.9.0",
"knip": "^5.30.6",
"knip": "^5.33.3",
"next-sitemap": "^4.2.3",
"postcss": "8.4.47",
"storybook": "8.3.4",
"storybook": "8.3.5",
"tailwindcss": "3.4.13",
"typescript": "5.6.2"
"typescript": "5.6.3"
}
}
+6 -9
View File
@@ -1,7 +1,6 @@
import "server-only";
import { COOKIE_ACTIVE_ACCOUNT, COOKIE_PREFIX_TOKEN } from "@/constants/cookie";
import { API_SERVER_URL } from "@/constants/env";
import { cookies } from "next/headers";
import { getAuthToken } from "../../app/api/lib/getAuthToken";
const TeamAccountRole = {
OWNER: "OWNER",
@@ -26,14 +25,10 @@ export type TeamMember = {
};
export async function getMembers(teamSlug: string) {
const cookiesManager = cookies();
const activeAccount = cookiesManager.get(COOKIE_ACTIVE_ACCOUNT)?.value;
const token = activeAccount
? cookiesManager.get(COOKIE_PREFIX_TOKEN + activeAccount)?.value
: null;
const token = getAuthToken();
if (!token) {
return [];
return undefined;
}
const teamsRes = await fetch(
@@ -44,8 +39,10 @@ export async function getMembers(teamSlug: string) {
},
},
);
if (teamsRes.ok) {
return (await teamsRes.json())?.result as TeamMember[];
}
return [];
return undefined;
}
@@ -9,7 +9,7 @@ export function ProjectAvatar(props: {
return (
<Img
src={props.src}
className={cn("rounded-lg border", props.className)}
className={cn("rounded-lg border border-border", props.className)}
alt={""}
fallback={
<div className="flex items-center justify-center bg-muted/50">
@@ -0,0 +1,145 @@
"use client";
import { MultiSelect } from "@/components/blocks/multi-select";
import { SelectWithSearch } from "@/components/blocks/select-with-search";
import { Badge } from "@/components/ui/badge";
import { useCallback, useMemo } from "react";
import { useAllChainsData } from "../../../hooks/chains/allChains";
function cleanChainName(chainName: string) {
return chainName.replace("Mainnet", "");
}
type Option = { label: string; value: string };
export function MultiNetworkSelector(props: {
selectedChainIds: number[];
onChange: (chainIds: number[]) => void;
}) {
const { allChains, idToChain } = useAllChainsData();
const options = useMemo(() => {
return allChains.map((chain) => {
return {
label: cleanChainName(chain.name),
value: String(chain.chainId),
};
});
}, [allChains]);
const searchFn = useCallback(
(option: Option, searchValue: string) => {
const chain = idToChain.get(Number(option.value));
if (!chain) {
return false;
}
if (Number.isInteger(Number.parseInt(searchValue))) {
return String(chain.chainId).startsWith(searchValue);
}
return chain.name.toLowerCase().includes(searchValue.toLowerCase());
},
[idToChain],
);
const renderOption = useCallback(
(option: Option) => {
const chain = idToChain.get(Number(option.value));
if (!chain) {
return option.label;
}
return (
<div className="flex justify-between gap-4">
<span className="grow truncate text-left">
{cleanChainName(chain.name)}
</span>
<Badge variant="outline" className="gap-2">
<span className="text-muted-foreground">Chain ID</span>
{chain.chainId}
</Badge>
</div>
);
},
[idToChain],
);
return (
<MultiSelect
searchPlaceholder="Search by Name or Chain Id"
selectedValues={props.selectedChainIds.map(String)}
options={options}
onSelectedValuesChange={(chainIds) => {
props.onChange(chainIds.map(Number));
}}
placeholder="Select Chains"
overrideSearchFn={searchFn}
renderOption={renderOption}
/>
);
}
export function SingleNetworkSelector(props: {
chainId: number | undefined;
onChange: (chainId: number) => void;
}) {
const { allChains, idToChain } = useAllChainsData();
const options = useMemo(() => {
return allChains.map((chain) => {
return {
label: chain.name,
value: String(chain.chainId),
};
});
}, [allChains]);
const searchFn = useCallback(
(option: Option, searchValue: string) => {
const chain = idToChain.get(Number(option.value));
if (!chain) {
return false;
}
if (Number.isInteger(Number.parseInt(searchValue))) {
return String(chain.chainId).startsWith(searchValue);
}
return chain.name.toLowerCase().includes(searchValue.toLowerCase());
},
[idToChain],
);
const renderOption = useCallback(
(option: Option) => {
const chain = idToChain.get(Number(option.value));
if (!chain) {
return option.label;
}
return (
<div className="flex justify-between gap-4">
<span className="grow truncate text-left">{chain.name}</span>
<Badge variant="outline" className="gap-2">
<span className="text-muted-foreground">Chain ID</span>
{chain.chainId}
</Badge>
</div>
);
},
[idToChain],
);
return (
<SelectWithSearch
searchPlaceholder="Search by Name or Chain Id"
value={String(props.chainId)}
options={options}
onValueChange={(chainId) => {
props.onChange(Number(chainId));
}}
placeholder="Select Chain"
overrideSearchFn={searchFn}
renderOption={renderOption}
/>
);
}
@@ -35,7 +35,7 @@ export function Sidebar(props: SidebarContentProps) {
props.className,
)}
>
<div className="pt-7">
<div className="py-7">
{props.header}
<div className="flex flex-col gap-1">
<RenderSidebarLinks links={props.links} />
@@ -1,3 +1,4 @@
/* eslint-disable no-restricted-syntax */
"use client";
import { Button } from "@/components/ui/button";
@@ -9,7 +10,14 @@ import {
import { Separator } from "@/components/ui/separator";
import { cn } from "@/lib/utils";
import { CheckIcon, ChevronDown, SearchIcon, XIcon } from "lucide-react";
import * as React from "react";
import {
forwardRef,
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from "react";
import { useShowMore } from "../../lib/useShowMore";
import { ScrollShadow } from "../ui/ScrollShadow/ScrollShadow";
import { Input } from "../ui/input";
@@ -24,6 +32,7 @@ interface MultiSelectProps
selectedValues: string[];
onSelectedValuesChange: (value: string[]) => void;
placeholder: string;
searchPlaceholder?: string;
/**
* Maximum number of items to display. Extra selected items will be summarized.
@@ -32,12 +41,16 @@ interface MultiSelectProps
maxCount?: number;
className?: string;
overrideSearchFn?: (
option: { value: string; label: string },
searchTerm: string,
) => boolean;
renderOption?: (option: { value: string; label: string }) => React.ReactNode;
}
export const MultiSelect = React.forwardRef<
HTMLButtonElement,
MultiSelectProps
>(
export const MultiSelect = forwardRef<HTMLButtonElement, MultiSelectProps>(
(
{
options,
@@ -50,10 +63,10 @@ export const MultiSelect = React.forwardRef<
},
ref,
) => {
const [isPopoverOpen, setIsPopoverOpen] = React.useState(false);
const [searchValue, setSearchValue] = React.useState("");
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
const [searchValue, setSearchValue] = useState("");
const handleInputKeyDown = React.useCallback(
const handleInputKeyDown = useCallback(
(event: React.KeyboardEvent<HTMLInputElement>) => {
if (event.key === "Enter") {
setIsPopoverOpen(true);
@@ -66,7 +79,7 @@ export const MultiSelect = React.forwardRef<
[selectedValues, onSelectedValuesChange],
);
const toggleOption = React.useCallback(
const toggleOption = useCallback(
(option: string) => {
const newSelectedValues = selectedValues.includes(option)
? selectedValues.filter((value) => value !== option)
@@ -76,7 +89,7 @@ export const MultiSelect = React.forwardRef<
[selectedValues, onSelectedValuesChange],
);
const handleClear = React.useCallback(() => {
const handleClear = useCallback(() => {
onSelectedValuesChange([]);
}, [onSelectedValuesChange]);
@@ -84,7 +97,7 @@ export const MultiSelect = React.forwardRef<
setIsPopoverOpen((prev) => !prev);
};
const clearExtraOptions = React.useCallback(() => {
const clearExtraOptions = useCallback(() => {
const newSelectedValues = selectedValues.slice(0, maxCount);
onSelectedValuesChange(newSelectedValues);
}, [selectedValues, onSelectedValuesChange, maxCount]);
@@ -92,14 +105,51 @@ export const MultiSelect = React.forwardRef<
// show 50 initially and then 20 more when reaching the end
const { itemsToShow, lastItemRef } = useShowMore<HTMLButtonElement>(50, 20);
const optionsToShow = React.useMemo(() => {
const searchValLowercase = searchValue.toLowerCase();
const filteredOptions = options.filter((option) => {
return option.label.toLowerCase().includes(searchValLowercase);
});
const { overrideSearchFn } = props;
return filteredOptions.slice(0, itemsToShow);
}, [options, searchValue, itemsToShow]);
const optionsToShow = useMemo(() => {
const filteredOptions: {
label: string;
value: string;
}[] = [];
const searchValLowercase = searchValue.toLowerCase();
for (let i = 0; i <= options.length - 1; i++) {
if (filteredOptions.length >= itemsToShow) {
break;
}
const option = options[i];
if (!option) {
continue;
}
if (overrideSearchFn) {
if (overrideSearchFn(option, searchValLowercase)) {
filteredOptions.push(option);
}
} else {
if (option.label.toLowerCase().includes(searchValLowercase)) {
filteredOptions.push(option);
}
}
}
return filteredOptions;
}, [options, searchValue, itemsToShow, overrideSearchFn]);
// scroll to top when options change
const popoverElRef = useRef<HTMLDivElement>(null);
// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
useEffect(() => {
const scrollContainer =
popoverElRef.current?.querySelector("[data-scrollable]");
if (scrollContainer) {
scrollContainer.scrollTo({
top: 0,
});
}
}, [searchValue]);
return (
<Popover open={isPopoverOpen} onOpenChange={setIsPopoverOpen}>
@@ -109,7 +159,7 @@ export const MultiSelect = React.forwardRef<
{...props}
onClick={handleTogglePopover}
className={cn(
"flex h-auto min-h-10 w-full items-center justify-between rounded-md border bg-inherit p-3 hover:bg-inherit",
"flex h-auto min-h-10 w-full items-center justify-between rounded-md border border-border bg-inherit p-3 hover:bg-inherit",
className,
)}
>
@@ -119,10 +169,14 @@ export const MultiSelect = React.forwardRef<
<div className="flex flex-wrap items-center gap-1.5">
{selectedValues.slice(0, maxCount).map((value) => {
const option = options.find((o) => o.value === value);
if (!option) {
return null;
}
return (
<ClosableBadge
key={value}
label={option?.label || ""}
label={option.label}
onClose={() => toggleOption(value)}
/>
);
@@ -170,7 +224,7 @@ export const MultiSelect = React.forwardRef<
</Button>
</PopoverTrigger>
<PopoverContent
className="p-0"
className="z-[10001] p-0"
align="center"
sideOffset={10}
onEscapeKeyDown={() => setIsPopoverOpen(false)}
@@ -178,12 +232,13 @@ export const MultiSelect = React.forwardRef<
width: "var(--radix-popover-trigger-width)",
maxHeight: "var(--radix-popover-content-available-height)",
}}
ref={popoverElRef}
>
<div>
{/* Search */}
<div className="relative">
<Input
placeholder="Search"
placeholder={props.searchPlaceholder || "Search"}
value={searchValue}
onChange={(e) => setSearchValue(e.target.value)}
className="!h-auto rounded-b-none border-0 border-border border-b py-4 pl-10 focus-visible:ring-0 focus-visible:ring-offset-0"
@@ -193,7 +248,7 @@ export const MultiSelect = React.forwardRef<
</div>
<ScrollShadow
scrollableClassName="max-h-[350px] p-1"
scrollableClassName="max-h-[min(calc(var(--radix-popover-content-available-height)-60px),350px)] p-1"
className="rounded"
>
{/* List */}
@@ -213,7 +268,7 @@ export const MultiSelect = React.forwardRef<
aria-selected={isSelected}
onClick={() => toggleOption(option.value)}
variant="ghost"
className="flex w-full cursor-pointer justify-start gap-3 rounded-sm px-3 py-2"
className="flex w-full cursor-pointer justify-start gap-3 rounded-sm px-3 py-2 text-left"
ref={
i === optionsToShow.length - 1 ? lastItemRef : undefined
}
@@ -229,7 +284,11 @@ export const MultiSelect = React.forwardRef<
<CheckIcon className="size-4" />
</div>
<span>{option.label}</span>
<div className="min-w-0 grow">
{props.renderOption
? props.renderOption(option)
: option.label}
</div>
</Button>
);
})}
@@ -0,0 +1,69 @@
import type { Meta, StoryObj } from "@storybook/react";
import { useMemo, useState } from "react";
import { BadgeContainer, mobileViewport } from "../../../stories/utils";
import { SelectWithSearch } from "./select-with-search";
const meta = {
title: "blocks/SelectWithSearch",
component: Story,
parameters: {
nextjs: {
appDirectory: true,
},
},
} satisfies Meta<typeof Story>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Desktop: Story = {
args: {},
};
export const Mobile: Story = {
args: {},
parameters: {
viewport: mobileViewport("iphone14"),
},
};
function createList(len: number) {
return Array.from({ length: len }, (_, i) => ({
value: `${i}`,
label: `Item ${i}`,
}));
}
function Story() {
return (
<div className="mx-auto flex w-full max-w-[600px] flex-col gap-6 px-4 py-6">
<VariantTest storyLabel="5 items" listLen={5} />
<VariantTest storyLabel="5000 items" listLen={5000} />
<VariantTest
defaultValue={"3"}
storyLabel="20 items, 3 selected by default"
listLen={20}
/>
</div>
);
}
function VariantTest(props: {
defaultValue?: string;
storyLabel: string;
listLen: number;
}) {
const list = useMemo(() => createList(props.listLen), [props.listLen]);
const [value, setValue] = useState<string | undefined>(props.defaultValue);
return (
<BadgeContainer label={props.storyLabel}>
<SelectWithSearch
value={value}
options={list}
onValueChange={setValue}
placeholder="Select items"
/>
</BadgeContainer>
);
}
@@ -0,0 +1,194 @@
/* eslint-disable no-restricted-syntax */
"use client";
import { Button } from "@/components/ui/button";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { cn } from "@/lib/utils";
import { CheckIcon, ChevronDown, SearchIcon } from "lucide-react";
import React, { useRef, useMemo, useEffect } from "react";
import { useShowMore } from "../../lib/useShowMore";
import { ScrollShadow } from "../ui/ScrollShadow/ScrollShadow";
import { Input } from "../ui/input";
interface SelectWithSearchProps
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
options: {
label: string;
value: string;
}[];
value: string | undefined;
onValueChange: (value: string) => void;
placeholder: string;
searchPlaceholder?: string;
className?: string;
overrideSearchFn?: (
option: { value: string; label: string },
searchTerm: string,
) => boolean;
renderOption?: (option: { value: string; label: string }) => React.ReactNode;
}
export const SelectWithSearch = React.forwardRef<
HTMLButtonElement,
SelectWithSearchProps
>(
(
{ options, onValueChange, placeholder, className, value, ...props },
ref,
) => {
const [isPopoverOpen, setIsPopoverOpen] = React.useState(false);
const [searchValue, setSearchValue] = React.useState("");
const selectedOption = useMemo(
() => options.find((option) => option.value === value),
[options, value],
);
// show 50 initially and then 20 more when reaching the end
const { itemsToShow, lastItemRef } = useShowMore<HTMLButtonElement>(50, 20);
const { overrideSearchFn } = props;
const optionsToShow = useMemo(() => {
const filteredOptions: {
label: string;
value: string;
}[] = [];
const searchValLowercase = searchValue.toLowerCase();
for (let i = 0; i <= options.length - 1; i++) {
if (filteredOptions.length >= itemsToShow) {
break;
}
const option = options[i];
if (!option) {
continue;
}
if (overrideSearchFn) {
if (overrideSearchFn(option, searchValLowercase)) {
filteredOptions.push(option);
}
} else {
if (option.label.toLowerCase().includes(searchValLowercase)) {
filteredOptions.push(option);
}
}
}
return filteredOptions;
}, [options, searchValue, itemsToShow, overrideSearchFn]);
// scroll to top when options change
const popoverElRef = useRef<HTMLDivElement>(null);
// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
useEffect(() => {
const scrollContainer =
popoverElRef.current?.querySelector("[data-scrollable]");
if (scrollContainer) {
scrollContainer.scrollTo({
top: 0,
});
}
}, [searchValue]);
return (
<Popover open={isPopoverOpen} onOpenChange={setIsPopoverOpen}>
<PopoverTrigger asChild>
<Button
ref={ref}
{...props}
onClick={() => setIsPopoverOpen(true)}
className={cn(
"flex w-full items-center justify-between rounded-md border border-border bg-inherit p-3 hover:bg-inherit",
className,
)}
>
<div className="flex w-full items-center justify-between">
<span
className={cn(
"text-muted-foreground text-sm",
selectedOption && "text-foreground",
)}
>
{selectedOption?.label || placeholder}
</span>
<ChevronDown className="h-4 cursor-pointer text-muted-foreground" />
</div>
</Button>
</PopoverTrigger>
<PopoverContent
className="z-[10001] p-0"
align="center"
sideOffset={10}
onEscapeKeyDown={() => setIsPopoverOpen(false)}
style={{
width: "var(--radix-popover-trigger-width)",
maxHeight: "var(--radix-popover-content-available-height)",
}}
ref={popoverElRef}
>
<div>
{/* Search */}
<div className="relative">
<Input
placeholder={props.searchPlaceholder || "Search"}
value={searchValue}
onChange={(e) => setSearchValue(e.target.value)}
className="!h-auto rounded-b-none border-0 border-border border-b py-3 pl-10 focus-visible:ring-0 focus-visible:ring-offset-0"
/>
<SearchIcon className="-translate-y-1/2 absolute top-1/2 left-4 size-4 text-muted-foreground" />
</div>
<ScrollShadow
scrollableClassName="max-h-[min(calc(var(--radix-popover-content-available-height)-60px),350px)] p-1"
className="rounded"
>
{/* List */}
<div>
{optionsToShow.length === 0 && (
<div className="flex justify-center py-10">
No results found
</div>
)}
{optionsToShow.map((option, i) => {
const isSelected = value === option.value;
return (
<Button
key={option.value}
role="option"
aria-selected={isSelected}
onClick={() => onValueChange(option.value)}
variant="ghost"
className="flex w-full cursor-pointer justify-start gap-3 rounded-sm px-3 py-2 text-left"
ref={
i === optionsToShow.length - 1 ? lastItemRef : undefined
}
>
<div className="flex size-4 items-center justify-center">
{isSelected && <CheckIcon className="size-4" />}
</div>
<div className="min-w-0 grow">
{props.renderOption
? props.renderOption(option)
: option.label}
</div>
</Button>
);
})}
</div>
</ScrollShadow>
</div>
</PopoverContent>
</Popover>
);
},
);
SelectWithSearch.displayName = "SelectWithSearch";
@@ -125,6 +125,7 @@ export function ScrollShadow(props: {
<div
className={cn("no-scrollbar overflow-auto", props.scrollableClassName)}
ref={scrollableEl}
data-scrollable
>
{props.children}
</div>
+1 -1
View File
@@ -143,7 +143,7 @@ const ChartTooltipContent = React.forwardRef<
}
const [item] = payload;
const key = `${labelKey || item.dataKey || item.name || "value"}`;
const key = `${labelKey || item?.dataKey || item?.name || "value"}`;
const itemConfig = getPayloadConfigFromPayload(config, item, key);
const value =
!labelKey && typeof label === "string"
@@ -16,7 +16,9 @@ const ImageUpload = React.forwardRef<HTMLInputElement, ImageUploadProps>(
const [activeFile, setActiveFile] = React.useState<File | null>(null);
const onDrop = React.useCallback(
(acceptedFiles: File[]) => {
setActiveFile(acceptedFiles[0]);
if (acceptedFiles[0]) {
setActiveFile(acceptedFiles[0]);
}
onUpload?.(acceptedFiles);
},
[onUpload],
@@ -35,7 +35,8 @@ const InputOTPSlot = React.forwardRef<
React.ComponentPropsWithoutRef<"div"> & { index: number }
>(({ index, className, ...props }, ref) => {
const inputOTPContext = React.useContext(OTPInputContext);
const { char, hasFakeCaret, isActive } = inputOTPContext.slots[index];
// biome-ignore lint/style/noNonNullAssertion: pure shadcn component - it works
const { char, hasFakeCaret, isActive } = inputOTPContext.slots[index]!;
return (
<div
@@ -62,7 +63,7 @@ const InputOTPSeparator = React.forwardRef<
React.ElementRef<"div">,
React.ComponentPropsWithoutRef<"div">
>(({ ...props }, ref) => (
// biome-ignore lint/a11y/useFocusableInteractive: <explanation>
// biome-ignore lint/a11y/useFocusableInteractive: pure shadcn component - it works
<div ref={ref} role="separator" {...props}>
<Dot />
</div>
@@ -159,12 +159,6 @@ function useUnderline<El extends HTMLElement>() {
setTimeout(() => {
lineEl.style.transition = "transform 0.3s, width 0.3s";
}, 0);
activeTabEl.scrollIntoView({
behavior: "smooth",
block: "nearest",
inline: "center",
});
} else if (lineRef.current) {
lineRef.current.style.width = "0px";
}
+3
View File
@@ -23,3 +23,6 @@ export const DASHBOARD_STORAGE_URL =
export const API_SERVER_URL =
process.env.NEXT_PUBLIC_THIRDWEB_API_HOST || "https://api.thirdweb.com";
export const TURNSTILE_SITE_KEY =
process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY || "";
-5
View File
@@ -40,8 +40,6 @@
/* Others */
--radius: 0.5rem;
--chart-lightness: 50%;
--chart-saturation: 50%;
}
.dark,
@@ -78,9 +76,6 @@
--border: 0 0% 15%;
--ring: 0 0% 30%;
--input: 0 0% 15%;
--chart-lightness: 50%;
--chart-saturation: 50%;
}
}
@@ -21,6 +21,21 @@ export const accountKeys = {
to,
period,
] as const,
userOpStats: (
walletAddress: string,
clientId: string,
from: string,
to: string,
period: string,
) =>
[
...accountKeys.wallet(walletAddress),
"userOps",
clientId,
from,
to,
period,
] as const,
credits: (walletAddress: string) =>
[...accountKeys.wallet(walletAddress), "credits"] as const,
billingSession: (walletAddress: string) =>
@@ -44,13 +44,12 @@ export function useActivity(contract: ThirdwebContract, autoUpdate?: boolean) {
}
const obj = eventsQuery.data.slice(0, 100).reduce(
(acc, curr) => {
if (acc[curr.transactionHash]) {
acc[curr.transactionHash].events.push(curr);
acc[curr.transactionHash].events.sort(
(a, b) => b.logIndex - a.logIndex,
);
if (acc[curr.transactionHash].blockNumber > curr.blockNumber) {
acc[curr.transactionHash].blockNumber = curr.blockNumber;
const internalTx = acc[curr.transactionHash];
if (internalTx) {
internalTx.events.push(curr);
internalTx.events.sort((a, b) => b.logIndex - a.logIndex);
if (internalTx.blockNumber > curr.blockNumber) {
internalTx.blockNumber = curr.blockNumber;
}
} else {
acc[curr.transactionHash] = {
@@ -234,6 +234,13 @@ export interface WalletStats {
walletType: string;
}
export interface UserOpStats {
date: string;
successful: number;
failed: number;
sponsoredUsd: number;
}
interface BillingProduct {
name: string;
id: string;
@@ -383,6 +390,100 @@ async function getWalletUsage(args: {
return json.data;
}
async function getUserOpUsage(args: {
clientId: string;
from?: Date;
to?: Date;
period?: "day" | "week" | "month" | "year" | "all";
}) {
const { clientId, from, to, period } = args;
const searchParams = new URLSearchParams();
searchParams.append("clientId", clientId);
if (from) {
searchParams.append("from", from.toISOString());
}
if (to) {
searchParams.append("to", to.toISOString());
}
if (period) {
searchParams.append("period", period);
}
const res = await fetch(
`${THIRDWEB_ANALYTICS_API_HOST}/v1/user-ops?${searchParams.toString()}`,
{
method: "GET",
headers: {
"Content-Type": "application/json",
},
},
);
const json = await res.json();
if (res.status !== 200) {
throw new Error(json.message);
}
return json.data;
}
export function useUserOpUsageAggregate(args: {
clientId: string;
from?: Date;
to?: Date;
}) {
const { clientId, from, to } = args;
const { user, isLoggedIn } = useLoggedInUser();
return useQuery({
queryKey: accountKeys.userOpStats(
user?.address as string,
clientId as string,
from?.toISOString() || "",
to?.toISOString() || "",
"all",
),
queryFn: async () => {
return getUserOpUsage({
clientId,
from,
to,
period: "all",
});
},
enabled: !!clientId && !!user?.address && isLoggedIn,
});
}
export function useUserOpUsagePeriod(args: {
clientId: string;
from?: Date;
to?: Date;
period: "day" | "week" | "month" | "year";
}) {
const { clientId, from, to, period } = args;
const { user, isLoggedIn } = useLoggedInUser();
return useQuery({
queryKey: accountKeys.userOpStats(
user?.address as string,
clientId as string,
from?.toISOString() || "",
to?.toISOString() || "",
period,
),
queryFn: async () => {
return getUserOpUsage({
clientId,
from,
to,
period,
});
},
enabled: !!clientId && !!user?.address && isLoggedIn,
});
}
export function useWalletUsageAggregate(args: {
clientId: string;
from?: Date;
@@ -48,7 +48,7 @@ export async function fetchDashboardContractMetadata(
if (compilerMetadata?.name.includes(":")) {
const _name = compilerMetadata.name.split(":")[1];
if (_name) {
compilerMetadata.name = compilerMetadata.name.split(":")[1];
compilerMetadata.name = _name;
}
}
@@ -3,6 +3,7 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import type { ResultItem } from "components/engine/system-metrics/components/StatusCodes";
import { THIRDWEB_API_HOST } from "constants/urls";
import type { EngineBackendWalletType } from "lib/engine";
import { useState } from "react";
import { useActiveAccount, useActiveWalletChain } from "thirdweb/react";
import invariant from "tiny-invariant";
@@ -111,10 +112,16 @@ export function useEngineBackendWallets(instance: string) {
});
}
type EngineFeature =
| "KEYPAIR_AUTH"
| "CONTRACT_SUBSCRIPTIONS"
| "IP_ALLOWLIST"
| "HETEROGENEOUS_WALLET_TYPES";
interface EngineSystemHealth {
status: string;
engineVersion?: string;
features?: string[];
features?: EngineFeature[];
}
export function useEngineSystemHealth(
@@ -138,6 +145,18 @@ export function useEngineSystemHealth(
});
}
// Helper function to check if a feature is supported.
export function useHasEngineFeature(
instanceUrl: string,
feature: EngineFeature,
) {
const query = useEngineSystemHealth(instanceUrl);
return {
query,
isSupported: !!query.data?.features?.includes(feature),
};
}
interface EngineSystemQueueMetrics {
result: {
queued: number;
@@ -188,17 +207,15 @@ export function useEngineLatestVersion() {
}
interface UpdateVersionInput {
engineId: string;
deploymentId: string;
serverVersion: string;
}
export function useEngineUpdateServerVersion() {
return useMutation({
mutationFn: async (input: UpdateVersionInput) => {
invariant(input.engineId, "engineId is required");
const res = await fetch(
`${THIRDWEB_API_HOST}/v2/engine/${input.engineId}/infrastructure`,
`${THIRDWEB_API_HOST}/v2/engine/deployments/${input.deploymentId}/infrastructure`,
{
method: "PUT",
headers: {
@@ -244,27 +261,26 @@ export function useEngineRemoveFromDashboard() {
});
}
export interface RemoveCloudHostedInput {
instanceId: string;
export interface DeleteCloudHostedInput {
deploymentId: string;
reason: "USING_SELF_HOSTED" | "TOO_EXPENSIVE" | "MISSING_FEATURES" | "OTHER";
feedback: string;
}
export function useEngineRemoveCloudHosted() {
export function useEngineDeleteCloudHosted() {
const { user } = useLoggedInUser();
const queryClient = useQueryClient();
return useMutation({
mutationFn: async ({
instanceId,
deploymentId,
reason,
feedback,
}: RemoveCloudHostedInput) => {
}: DeleteCloudHostedInput) => {
const res = await fetch(
`${THIRDWEB_API_HOST}/v1/engine/${instanceId}/remove-cloud-hosted`,
`${THIRDWEB_API_HOST}/v2/engine/deployments/${deploymentId}/infrastructure/delete`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
@@ -401,29 +417,22 @@ export function useEngineTransactions(instance: string, autoUpdate: boolean) {
});
}
type WalletConfig =
| {
type: "local";
}
| {
type: "aws-kms";
awsAccessKeyId: string;
awsSecretAccessKey: string;
awsRegion: string;
}
| {
type: "gcp-kms";
gcpApplicationProjectId: string;
gcpKmsLocationId: string;
gcpKmsKeyRingId: string;
gcpApplicationCredentialEmail: string;
gcpApplicationCredentialPrivateKey: string;
};
export interface WalletConfigResponse {
type: EngineBackendWalletType;
awsAccessKeyId?: string | null;
awsRegion?: string | null;
gcpApplicationProjectId?: string | null;
gcpKmsLocationId?: string | null;
gcpKmsKeyRingId?: string | null;
gcpApplicationCredentialEmail?: string | null;
}
export function useEngineWalletConfig(instance: string) {
const token = useLoggedInUser().user?.jwt ?? null;
return useQuery({
return useQuery<WalletConfigResponse>({
queryKey: engineKeys.walletConfig(instance),
queryFn: async () => {
const res = await fetch(`${instance}configuration/wallets`, {
@@ -432,8 +441,7 @@ export function useEngineWalletConfig(instance: string) {
});
const json = await res.json();
return (json.result as WalletConfig) || {};
return json.result;
},
enabled: !!instance && !!token,
});
@@ -799,9 +807,6 @@ export function useEngineWebhooks(instance: string) {
// POST REQUESTS
export type SetWalletConfigInput =
| {
type: "local";
}
| {
type: "aws-kms";
awsAccessKeyId: string;
@@ -821,8 +826,8 @@ export function useEngineSetWalletConfig(instance: string) {
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (input: SetWalletConfigInput) => {
return useMutation<WalletConfigResponse, void, SetWalletConfigInput>({
mutationFn: async (input) => {
invariant(instance, "instance is required");
const res = await fetch(`${instance}configuration/wallets`, {
@@ -847,6 +852,7 @@ export function useEngineSetWalletConfig(instance: string) {
}
export type CreateBackendWalletInput = {
type: EngineBackendWalletType;
label?: string;
};
@@ -913,25 +919,20 @@ export function useEngineUpdateBackendWallet(instance: string) {
});
}
export type ImportBackendWalletInput =
| {
awsKmsKeyId: string;
awsKmsArn: string;
}
| {
gcpKmsKeyId: string;
gcpKmsKeyVersionId: string;
}
| {
privateKey?: string;
}
| {
mnemonic?: string;
}
| {
encryptedJson?: string;
password?: string;
};
// The backend determines the wallet imported based on the provided fields.
export type ImportBackendWalletInput = {
label?: string;
awsKmsArn?: string;
gcpKmsKeyId?: string;
gcpKmsKeyVersionId?: string;
privateKey?: string;
mnemonic?: string;
encryptedJson?: string;
password?: string;
};
export function useEngineImportBackendWallet(instance: string) {
const token = useLoggedInUser().user?.jwt ?? null;
@@ -1639,6 +1640,9 @@ export function useEngineCreateNotificationChannel(engineId: string) {
`${THIRDWEB_API_HOST}/v1/engine/${engineId}/notification-channels`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(input),
},
);
@@ -1667,7 +1671,9 @@ export function useEngineDeleteNotificationChannel(engineId: string) {
const res = await fetch(
`${THIRDWEB_API_HOST}/v1/engine/${engineId}/notification-channels/${notificationChannelId}`,
{ method: "DELETE" },
{
method: "DELETE",
},
);
if (!res.ok) {
throw new Error(`Unexpected status ${res.status}: ${await res.text()}`);
@@ -56,9 +56,7 @@ export function useLoggedInUser(): {
retry: false,
queryFn: async () => {
const searchParams = new URLSearchParams();
if (pathname) {
searchParams.set("pathname", pathname);
}
if (connectedAddress) {
searchParams.set("address", connectedAddress);
}
@@ -76,10 +74,18 @@ export function useLoggedInUser(): {
// legit use-case for now
// eslint-disable-next-line no-restricted-syntax
useEffect(() => {
if (query.data?.redirectTo) {
router.replace(query.data.redirectTo);
if (query.data?.isLoggedIn === false) {
// not using useSearchParams hook here to avoid adding Suspense boundaries everywhere this hook is being used
const currentHref = new URL(window.location.href);
const currentPathname = currentHref.pathname;
const currentSearchParams = currentHref.searchParams.toString();
router.replace(
buildLoginPath(
`${currentPathname}${currentSearchParams ? `?${currentSearchParams}` : ""}`,
),
);
}
}, [query.data?.redirectTo, router]);
}, [query.data?.isLoggedIn, router]);
// if we are "disconnected" we are not logged in
if (connectionStatus === "disconnected") {
@@ -135,3 +141,7 @@ export function useLoggedInUser(): {
: null,
};
}
function buildLoginPath(pathname: string | undefined): string {
return `/login${pathname ? `?next=${encodeURIComponent(pathname)}` : ""}`;
}
@@ -2,17 +2,24 @@
import { Spinner } from "@/components/ui/Spinner/Spinner";
import { Button } from "@/components/ui/button";
import { THIRDWEB_ENGINE_FAUCET_WALLET } from "@/constants/env";
import { Form, FormControl, FormField, FormItem } from "@/components/ui/form";
import {
THIRDWEB_ENGINE_FAUCET_WALLET,
TURNSTILE_SITE_KEY,
} from "@/constants/env";
import { useThirdwebClient } from "@/constants/thirdweb.client";
import { CustomConnectWallet } from "@3rdweb-sdk/react/components/connect-wallet";
import { Turnstile } from "@marsidev/react-turnstile";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import type { CanClaimResponseType } from "app/api/testnet-faucet/can-claim/CanClaimResponseType";
import { mapV4ChainToV5Chain } from "contexts/map-chains";
import { useTrack } from "hooks/analytics/useTrack";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { toUnits } from "thirdweb";
import type { ChainMetadata } from "thirdweb/chains";
import { useActiveAccount, useWalletBalance } from "thirdweb/react";
import { z } from "zod";
function formatTime(seconds: number) {
const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" });
@@ -29,6 +36,12 @@ function formatTime(seconds: number) {
return rtf.format(+seconds, "second");
}
const claimFaucetSchema = z.object({
turnstileToken: z.string().min(1, {
message: "Captcha validation is required.",
}),
});
export function FaucetButton({
chain,
amount,
@@ -52,7 +65,7 @@ export function FaucetButton({
const queryClient = useQueryClient();
const claimMutation = useMutation({
mutationFn: async () => {
mutationFn: async (turnstileToken: string) => {
trackEvent({
category: "faucet",
action: "claim",
@@ -67,6 +80,7 @@ export function FaucetButton({
body: JSON.stringify({
chainId: chainId,
toAddress: address,
turnstileToken,
}),
});
@@ -117,6 +131,8 @@ export function FaucetButton({
faucetWalletBalanceQuery.data !== undefined &&
faucetWalletBalanceQuery.data.value < toUnits("1", 17);
const form = useForm<z.infer<typeof claimFaucetSchema>>();
// loading state
if (faucetWalletBalanceQuery.isPending || canClaimFaucetQuery.isPending) {
return (
@@ -161,28 +177,46 @@ export function FaucetButton({
);
}
const claimFunds = (values: z.infer<typeof claimFaucetSchema>) => {
// Instead of having a dedicated endpoint (/api/verify-token),
// we can just attach the token in the payload and send it to the claim-faucet endpoint, to avoid a round-trip request
const claimPromise = claimMutation.mutateAsync(values.turnstileToken);
toast.promise(claimPromise, {
success: `${amount} ${chain.nativeCurrency.symbol} sent successfully`,
error: `Failed to claim ${amount} ${chain.nativeCurrency.symbol}`,
});
};
// eligible to claim and faucet has balance
return (
<div className="flex w-full flex-col text-center">
<Button
variant="primary"
className="w-full gap-2"
onClick={() => {
const claimPromise = claimMutation.mutateAsync();
toast.promise(claimPromise, {
success: `${amount} ${chain.nativeCurrency.symbol} sent successfully`,
error: `Failed to claim ${amount} ${chain.nativeCurrency.symbol}`,
});
}}
>
{claimMutation.isPending ? (
<>
Claiming <Spinner className="size-3" />
</>
) : (
`Get ${amount} ${chain.nativeCurrency.symbol}`
)}
</Button>
<Form {...form}>
<form onSubmit={form.handleSubmit(claimFunds)}>
<Button variant="primary" className="w-full gap-2" type="submit">
{claimMutation.isPending ? (
<>
Claiming <Spinner className="size-3" />
</>
) : (
`Get ${amount} ${chain.nativeCurrency.symbol}`
)}
</Button>
<FormField
control={form.control}
name="turnstileToken"
render={({ field }) => (
<FormItem>
<FormControl>
<Turnstile
siteKey={TURNSTILE_SITE_KEY}
onSuccess={(token) => field.onChange(token)}
/>
</FormControl>
</FormItem>
)}
/>
</form>
</Form>
{faucetWalletBalanceQuery.data && (
<p className="mt-3 text-muted-foreground text-xs">
@@ -46,6 +46,10 @@ export async function generateMetadata({
return {
title,
description,
openGraph: {
title,
description,
},
};
}
@@ -122,6 +122,7 @@ export default async function Image({
right: -2,
height: 150,
width: 150,
objectFit: "contain",
}}
/>
)}
@@ -2,11 +2,11 @@
import { TransactionButton } from "components/buttons/TransactionButton";
import { useTrack } from "hooks/analytics/useTrack";
import { useTxNotifications } from "hooks/useTxNotifications";
import { useAllChainsData } from "hooks/chains/allChains";
import { toast } from "sonner";
import type { ThirdwebContract } from "thirdweb";
import { cancelAuction, cancelListing } from "thirdweb/extensions/marketplace";
import { useSendAndConfirmTransaction } from "thirdweb/react";
import { useAllChainsData } from "../../../hooks/chains/allChains";
interface CancelTabProps {
id: string;
@@ -25,14 +25,9 @@ export const CancelTab: React.FC<CancelTabProps> = ({
const transaction = isAuction
? cancelAuction({ contract, auctionId: BigInt(id) })
: cancelListing({ contract, listingId: BigInt(id) });
const { onSuccess, onError } = useTxNotifications(
"Listing cancelled",
"Error cancelling listing",
);
const cancelQuery = useSendAndConfirmTransaction();
return (
<div className="flex flex-col gap-3 pt-3">
{/* maybe some text? */}
<TransactionButton
txChainID={contract.chain.id}
transactionCount={1}
@@ -43,7 +38,7 @@ export const CancelTab: React.FC<CancelTabProps> = ({
action: "cancel-listing",
label: "attempt",
});
cancelQuery.mutate(transaction, {
const promise = cancelQuery.mutateAsync(transaction, {
onSuccess: () => {
trackEvent({
category: "marketplace",
@@ -51,7 +46,6 @@ export const CancelTab: React.FC<CancelTabProps> = ({
label: "success",
network,
});
onSuccess();
},
onError: (error) => {
trackEvent({
@@ -61,14 +55,19 @@ export const CancelTab: React.FC<CancelTabProps> = ({
network,
error,
});
onError(error);
console.error(error);
},
});
toast.promise(promise, {
loading: `Cancelling ${isAuction ? "auction" : "listing"}`,
success: "Item cancelled successfully",
error: "Failed to cancel",
});
}}
colorScheme="primary"
alignSelf="flex-end"
>
Cancel Listing
Cancel {isAuction ? "Auction" : "Listing"}
</TransactionButton>
</div>
);
@@ -8,7 +8,7 @@ import { useState } from "react";
import type { ThirdwebContract } from "thirdweb";
import { useActiveAccount } from "thirdweb/react";
import { Button, Drawer } from "tw-components";
import { CreateListingsForm } from "../listings/components/list-form";
import { CreateListingsForm } from "./list-form";
const LIST_FORM_ID = "marketplace-list-form";
@@ -15,6 +15,7 @@ import {
import { CurrencySelector } from "components/shared/CurrencySelector";
import { SolidityInput } from "contract-ui/components/solidity-inputs";
import { useTrack } from "hooks/analytics/useTrack";
import { useAllChainsData } from "hooks/chains/allChains";
import { useTxNotifications } from "hooks/useTxNotifications";
import { isAlchemySupported } from "lib/wallet/nfts/alchemy";
import { isMoralisSupported } from "lib/wallet/nfts/moralis";
@@ -57,8 +58,6 @@ import {
import { NFTMediaWithEmptyState } from "tw-components/nft-media";
import { shortenIfAddress } from "utils/usedapp-external";
import { useAllChainsData } from "../../../../hooks/chains/allChains";
type ListForm =
| (Omit<CreateListingParams, "quantity" | "currencyContractAddress"> & {
currencyContractAddress: string;
@@ -0,0 +1,180 @@
import { WalletAddress } from "@/components/blocks/wallet-address";
import { CopyAddressButton } from "@/components/ui/CopyAddressButton";
import { CopyTextButton } from "@/components/ui/CopyTextButton";
import { Sheet, SheetContent } from "@/components/ui/sheet";
import { Flex, GridItem, SimpleGrid, usePrevious } from "@chakra-ui/react";
import type { ThirdwebContract } from "thirdweb";
import type {
DirectListing,
EnglishAuction,
} from "thirdweb/extensions/marketplace";
import { useActiveAccount } from "thirdweb/react";
import { Badge, Card, CodeBlock, Heading, Text } from "tw-components";
import { NFTMediaWithEmptyState } from "tw-components/nft-media";
import { CancelTab } from "./cancel-tab";
import { LISTING_STATUS } from "./types";
interface NFTDrawerProps {
contract: ThirdwebContract;
isOpen: boolean;
onClose: () => void;
data: DirectListing | EnglishAuction | null;
}
export const ListingDrawer: React.FC<NFTDrawerProps> = ({
contract,
isOpen,
onClose,
data,
}) => {
const address = useActiveAccount()?.address;
const prevData = usePrevious(data);
const renderData = data || prevData;
const isOwner =
address?.toLowerCase() === renderData?.creatorAddress.toLowerCase();
const tokenId = renderData?.asset.id.toString() || "";
if (!renderData) {
return null;
}
return (
<Sheet open={isOpen} onOpenChange={onClose}>
<SheetContent className="flex w-full flex-col gap-6 py-6 md:min-w-[600px]">
<div className="flex flex-row gap-6">
<NFTMediaWithEmptyState
metadata={renderData.asset.metadata}
requireInteraction
width="150px"
height="150px"
/>
<Flex flexDir="column" gap={2} w="70%">
<Heading size="title.lg">{renderData.asset.metadata.name}</Heading>
<Text size="label.md" noOfLines={6}>
{renderData.asset.metadata.name}
</Text>
</Flex>
</div>
<Flex flexDir="column" gap={4}>
<Card as={Flex} flexDir="column" gap={3}>
<SimpleGrid rowGap={3} columns={12} placeItems="center left">
<GridItem colSpan={3}>
<Heading size="label.md">Asset contract address</Heading>
</GridItem>
<GridItem colSpan={9}>
<CopyAddressButton
address={renderData.assetContractAddress}
copyIconPosition="right"
/>
</GridItem>
<GridItem colSpan={3}>
<Heading size="label.md">Token ID</Heading>
</GridItem>
<GridItem colSpan={9}>
<CopyTextButton
textToCopy={tokenId}
textToShow={tokenId}
copyIconPosition="right"
tooltip="Token ID"
/>
</GridItem>
<GridItem colSpan={3}>
<Heading size="label.md">Seller</Heading>
</GridItem>
<GridItem colSpan={9}>
<WalletAddress address={renderData.creatorAddress} />
</GridItem>
<GridItem colSpan={3}>
<Heading size="label.md">Listing ID</Heading>
</GridItem>
<GridItem colSpan={9}>
<CopyTextButton
textToCopy={renderData.id.toString()}
textToShow={renderData.id.toString()}
copyIconPosition="right"
tooltip="Listing ID"
/>
</GridItem>
<GridItem colSpan={3}>
<Heading size="label.md">Type</Heading>
</GridItem>
<GridItem colSpan={9}>
<Text fontFamily="mono" size="body.md">
{renderData.asset.type}
</Text>
</GridItem>
<GridItem colSpan={3}>
<Heading size="label.md">Status</Heading>
</GridItem>
<GridItem colSpan={9}>
<Badge
size="label.sm"
variant="subtle"
textTransform="capitalize"
>
{LISTING_STATUS[renderData.status]}
</Badge>
</GridItem>
<GridItem colSpan={3}>
<Heading size="label.md">Quantity</Heading>
</GridItem>
<GridItem colSpan={9}>
<Text fontFamily="mono" size="body.md">
{(renderData.quantity || 0n).toString()}{" "}
{/* For listings that are completed, the `quantity` would be `0`
So we show this text to make it clear */}
{LISTING_STATUS[renderData.status] === "Completed"
? "(Sold out)"
: ""}
</Text>
</GridItem>
{renderData.type === "direct-listing" && (
<>
<GridItem colSpan={3}>
<Heading size="label.md">Price</Heading>
</GridItem>
<GridItem colSpan={9}>
<Text fontFamily="mono" size="body.md">
{renderData.currencyValuePerToken.displayValue}{" "}
{renderData.currencyValuePerToken.symbol}
</Text>
</GridItem>
</>
)}
{/*
Todo: Add a Buy button somewhere in this section once the Dashboard is fully migrated to v5 (?)
Kien already shipped a prebuilt component for the Marketplace Buy Button in SDK v5
*/}
</SimpleGrid>
</Card>
{data?.asset.metadata.properties ? (
<Card as={Flex} flexDir="column" gap={4}>
<Heading size="label.md">Attributes</Heading>
<CodeBlock
code={
JSON.stringify(data.asset.metadata.properties, null, 2) || ""
}
language="json"
canCopy={false}
wrap={false}
overflow="auto"
/>
</Card>
) : null}
</Flex>
{isOwner && (
<CancelTab
contract={contract}
id={renderData.id.toString()}
isAuction={renderData.type === "english-auction"}
/>
)}
</SheetContent>
</Sheet>
);
};
@@ -17,7 +17,6 @@ import {
} from "@chakra-ui/react";
import type { UseQueryResult } from "@tanstack/react-query";
import { MediaCell } from "components/contract-pages/table/table-columns/cells/media-cell";
import { ListingDrawer } from "contract-ui/tabs/shared-components/listing-drawer";
import {
ChevronFirstIcon,
ChevronLastIcon,
@@ -40,6 +39,7 @@ import type {
} from "thirdweb/extensions/marketplace";
import { min } from "thirdweb/utils";
import { Button, Text } from "tw-components";
import { ListingDrawer } from "./listing-drawer";
import { LISTING_STATUS } from "./types";
const tableColumns: Column<DirectListing | EnglishAuction>[] = [
@@ -100,7 +100,6 @@ interface MarketplaceTableProps {
start: number;
}>
>;
type: "direct-listings" | "english-auctions";
}
const DEFAULT_QUERY_STATE = { count: 50, start: 0 };
@@ -112,7 +111,6 @@ export const MarketplaceTable: React.FC<MarketplaceTableProps> = ({
totalCountQuery,
queryParams,
setQueryParams,
type,
}) => {
const [listingsToShow, setListingsToShow_] = useState<"all" | "valid">("all");
@@ -215,7 +213,6 @@ export const MarketplaceTable: React.FC<MarketplaceTableProps> = ({
data={tokenRow}
isOpen={!!tokenRow}
onClose={() => setTokenRow(null)}
type={type}
/>
<Table {...getTableProps()}>
<Thead>
@@ -2,7 +2,7 @@
import type { ThirdwebContract } from "thirdweb";
import { Heading } from "tw-components";
import { CreateListingButton } from "../shared-components/list-button";
import { CreateListingButton } from "../components/list-button";
import { DirectListingsTable } from "./components/table";
interface ContractDirectListingsPageProps {
@@ -1,6 +1,5 @@
"use client";
import { MarketplaceTable } from "contract-ui/tabs/shared-components/marketplace-table";
import { useState } from "react";
import type { ThirdwebContract } from "thirdweb";
import {
@@ -9,6 +8,7 @@ import {
totalListings,
} from "thirdweb/extensions/marketplace";
import { useReadContract } from "thirdweb/react";
import { MarketplaceTable } from "../../components/marketplace-table";
interface DirectListingsTableProps {
contract: ThirdwebContract;
@@ -40,7 +40,6 @@ export const DirectListingsTable: React.FC<DirectListingsTableProps> = ({
totalCountQuery={totalCountQuery}
queryParams={queryParams}
setQueryParams={setQueryParams}
type="direct-listings"
/>
);
};
@@ -1,7 +1,7 @@
import { notFound, redirect } from "next/navigation";
import { ContractDirectListingsPage } from "../../../../../../contract-ui/tabs/direct-listings/page";
import { getContractPageParamsInfo } from "../_utils/getContractFromParams";
import { getContractPageMetadata } from "../_utils/getContractPageMetadata";
import { getContractPageParamsInfo } from "../../_utils/getContractFromParams";
import { getContractPageMetadata } from "../../_utils/getContractPageMetadata";
import { ContractDirectListingsPage } from "./ContractDirectListingsPage";
export default async function Page(props: {
params: {
@@ -2,7 +2,7 @@
import type { ThirdwebContract } from "thirdweb";
import { Heading } from "tw-components";
import { CreateListingButton } from "../shared-components/list-button";
import { CreateListingButton } from "../components/list-button";
import { EnglishAuctionsTable } from "./components/table";
interface ContractEnglishAuctionsProps {
@@ -1,6 +1,5 @@
"use client";
import { MarketplaceTable } from "contract-ui/tabs/shared-components/marketplace-table";
import { useState } from "react";
import type { ThirdwebContract } from "thirdweb";
import {
@@ -9,6 +8,7 @@ import {
totalAuctions,
} from "thirdweb/extensions/marketplace";
import { useReadContract } from "thirdweb/react";
import { MarketplaceTable } from "../../components/marketplace-table";
interface EnglishAuctionsTableProps {
contract: ThirdwebContract;
@@ -40,7 +40,6 @@ export const EnglishAuctionsTable: React.FC<EnglishAuctionsTableProps> = ({
totalCountQuery={totalCountQuery}
queryParams={queryParams}
setQueryParams={setQueryParams}
type="english-auctions"
/>
);
};
@@ -1,7 +1,7 @@
import { notFound, redirect } from "next/navigation";
import { ContractEnglishAuctionsPage } from "../../../../../../contract-ui/tabs/english-auctions/page";
import { getContractPageParamsInfo } from "../_utils/getContractFromParams";
import { getContractPageMetadata } from "../_utils/getContractPageMetadata";
import { getContractPageParamsInfo } from "../../_utils/getContractFromParams";
import { getContractPageMetadata } from "../../_utils/getContractPageMetadata";
import { ContractEnglishAuctionsPage } from "./ContractEnglishAuctionsPage";
export default async function Page(props: {
params: {
@@ -15,7 +15,7 @@ import type { z } from "zod";
import type {
ClaimCondition as LegacyClaimCondition,
ClaimConditionInputSchema as LegacyClaimConditionInputSchema,
} from "../../legacy-zod-schema";
} from "../legacy-zod-schema";
type SnapshotEntry = {
address: string;
@@ -16,7 +16,6 @@ import {
Spinner,
} from "@chakra-ui/react";
import { TransactionButton } from "components/buttons/TransactionButton";
import { SnapshotUpload } from "contract-ui/tabs/claim-conditions/components/snapshot-upload";
import { useTrack } from "hooks/analytics/useTrack";
import { useTxNotifications } from "hooks/useTxNotifications";
import { CircleHelpIcon, PlusIcon } from "lucide-react";
@@ -46,8 +45,9 @@ import {
type ClaimConditionInput,
ClaimConditionInputSchema,
type SnapshotEntry,
} from "../../legacy-zod-schema";
} from "../legacy-zod-schema";
import { ResetClaimEligibility } from "../reset-claim-eligibility";
import { SnapshotUpload } from "../snapshot-upload";
import { getClaimPhasesInLegacyFormat, setClaimPhasesTx } from "./hooks";
import { ClaimConditionsPhase } from "./phase";
@@ -17,7 +17,7 @@ export const ClaimConditions: React.FC<ClaimConditionsProps> = ({
isERC20,
}) => {
return (
<div className="flex flex-col gap-8">
<div className="flex w-full flex-col gap-8">
<Flex p={0} position="relative">
<Flex
pt={{ base: isColumn ? 0 : 6, md: 6 }}
@@ -1,8 +1,8 @@
import { CURRENCIES } from "constants/currencies";
import { useAllChainsData } from "hooks/chains/allChains";
import { Text } from "tw-components";
import { shortenIfAddress } from "utils/usedapp-external";
import { isAddressZero } from "utils/zeroAddress";
import { useAllChainsData } from "../../../../hooks/chains/allChains";
interface PricePreviewProps {
price: string | number | undefined;
@@ -427,7 +427,7 @@ const SnapshotTableColumns = [
return address;
}
return (
<div className="flex flex-row">
<div className="flex flex-row items-center gap-2">
<Tooltip
label={
address.startsWith("0x")
@@ -1,9 +1,9 @@
import { WalletAddress } from "@/components/blocks/wallet-address";
import { Flex, SimpleGrid, useBreakpointValue } from "@chakra-ui/react";
import { formatDistance } from "date-fns/formatDistance";
import { useAllChainsData } from "hooks/chains/allChains";
import { useActiveAccount } from "thirdweb/react";
import { Badge, Card, Heading, Text } from "tw-components";
import { useAllChainsData } from "../../../../hooks/chains/allChains";
export type AccountSignerType = {
signer: string;
@@ -1,7 +1,7 @@
import { notFound, redirect } from "next/navigation";
import { AccountSigners } from "../../../../../../contract-ui/tabs/account-permissions/components/account-signers";
import { getContractPageParamsInfo } from "../_utils/getContractFromParams";
import { getContractPageMetadata } from "../_utils/getContractPageMetadata";
import { AccountSigners } from "./components/account-signers";
export default async function Page(props: {
params: {
@@ -3,12 +3,12 @@
import { useThirdwebClient } from "@/constants/thirdweb.client";
import { Input } from "@chakra-ui/react";
import { TransactionButton } from "components/buttons/TransactionButton";
import { useV5DashboardChain } from "lib/v5-adapter";
import { type ChangeEvent, useState } from "react";
import type { StoredChain } from "stores/chainStores";
import { prepareTransaction, toWei } from "thirdweb";
import { useSendAndConfirmTransaction } from "thirdweb/react";
import { Card } from "tw-components";
import { useV5DashboardChain } from "../../../../lib/v5-adapter";
import type { StoredChain } from "../../../../stores/chainStores";
interface DepositNativeProps {
address: string;
@@ -1,9 +1,9 @@
"use client";
import { useWalletNFTs } from "@3rdweb-sdk/react";
import { NFTCards } from "contract-ui/tabs/overview/components/NFTCards";
import type { ThirdwebContract } from "thirdweb";
import { Text } from "tw-components";
import { NFTCards } from "../../_components/NFTCards";
interface NftsOwnedProps {
contract: ThirdwebContract;
@@ -1,7 +1,7 @@
import { notFound, redirect } from "next/navigation";
import { AccountPage } from "../../../../../../contract-ui/tabs/account/page";
import { getContractPageParamsInfo } from "../_utils/getContractFromParams";
import { getContractPageMetadata } from "../_utils/getContractPageMetadata";
import { AccountPage } from "./AccountPage";
export default async function Page(props: {
params: {
@@ -4,6 +4,7 @@ import { useDashboardRouter } from "@/lib/DashboardRouter";
import { Flex, IconButton, Select, Skeleton } from "@chakra-ui/react";
import { createColumnHelper } from "@tanstack/react-table";
import { TWTable } from "components/shared/TWTable";
import { useChainSlug } from "hooks/chains/chainSlug";
import {
ChevronFirstIcon,
ChevronLastIcon,
@@ -15,7 +16,6 @@ import type { ThirdwebContract } from "thirdweb";
import { getAccounts, totalAccounts } from "thirdweb/extensions/erc4337";
import { useReadContract } from "thirdweb/react";
import { Text, TrackedCopyButton } from "tw-components";
import { useChainSlug } from "../../../../hooks/chains/chainSlug";
const columnHelper = createColumnHelper<{ account: string }>();
@@ -1,7 +1,7 @@
import { notFound, redirect } from "next/navigation";
import { AccountsPage } from "../../../../../../contract-ui/tabs/accounts/page";
import { getContractPageParamsInfo } from "../_utils/getContractFromParams";
import { getContractPageMetadata } from "../_utils/getContractPageMetadata";
import { AccountsPage } from "./AccountsPage";
export default async function Page(props: {
params: {
@@ -1,7 +1,7 @@
import { notFound, redirect } from "next/navigation";
import { ContractAnalyticsPage } from "../../../../../../contract-ui/tabs/analytics/page";
import { getContractPageParamsInfo } from "../_utils/getContractFromParams";
import { getContractPageMetadata } from "../_utils/getContractPageMetadata";
import { ContractAnalyticsPage } from "./ContractAnalyticsPage";
export default async function Page(props: {
params: {
@@ -1,5 +1,5 @@
import { notFound, redirect } from "next/navigation";
import { ClaimConditions } from "../../../../../../contract-ui/tabs/claim-conditions/components/claim-conditions";
import { ClaimConditions } from "../_components/claim-conditions/claim-conditions";
import { getContractPageParamsInfo } from "../_utils/getContractFromParams";
import { getContractPageMetadata } from "../_utils/getContractPageMetadata";
@@ -3,11 +3,13 @@
import { useApiKeys, useCreateApiKey } from "@3rdweb-sdk/react/hooks/useApi";
import { Flex, FormControl, Input, Link, Select } from "@chakra-ui/react";
import { useTrack } from "hooks/analytics/useTrack";
import { useAllChainsData } from "hooks/chains/allChains";
import { useClipboard } from "hooks/useClipboard";
import { useTxNotifications } from "hooks/useTxNotifications";
import { CheckIcon, CopyIcon } from "lucide-react";
import { useMemo } from "react";
import { useForm } from "react-hook-form";
import type { StoredChain } from "stores/chainStores";
import type { ThirdwebContract } from "thirdweb";
import type { ChainMetadata } from "thirdweb/chains";
import {
@@ -19,8 +21,6 @@ import {
Heading,
Text,
} from "tw-components";
import { useAllChainsData } from "../../../../hooks/chains/allChains";
import type { StoredChain } from "../../../../stores/chainStores";
interface EmbedSetupProps {
contract: ThirdwebContract;
@@ -171,7 +171,7 @@ function minimizeChain(
return {
name: chain.name,
chain: chain.chain,
rpc: [firstRpc],
rpc: [firstRpc || ""],
nativeCurrency: chain.nativeCurrency,
shortName: chain.shortName,
chainId: chain.chainId,
@@ -509,7 +509,7 @@ export const EmbedSetup: React.FC<EmbedSetupProps> = ({
)}
{colorOptions.map((color) => (
<option key={color} value={color}>
{color[0].toUpperCase() + color.substring(1)}
{color[0]?.toUpperCase() + color.substring(1)}
</option>
))}
</Select>
@@ -524,7 +524,7 @@ export const EmbedSetup: React.FC<EmbedSetupProps> = ({
<Select {...register("secondaryColor")}>
{colorOptions.map((color) => (
<option key={color} value={color}>
{color[0].toUpperCase() + color.substring(1)}
{color[0]?.toUpperCase() + color.substring(1)}
</option>
))}
</Select>
@@ -1,7 +1,7 @@
import { notFound, redirect } from "next/navigation";
import { EmbedSetup } from "../../../../../../contract-ui/tabs/embed/components/embed-setup";
import { getContractPageParamsInfo } from "../_utils/getContractFromParams";
import { getContractPageMetadata } from "../_utils/getContractPageMetadata";
import { EmbedSetup } from "./embed-setup";
export default async function Page(props: {
params: {
@@ -15,7 +15,6 @@ import {
Divider,
Flex,
FormControl,
Icon,
LightMode,
List,
Select,
@@ -25,11 +24,11 @@ import {
Tooltip,
} from "@chakra-ui/react";
import { AnimatePresence, motion } from "framer-motion";
import { useChainSlug } from "hooks/chains/chainSlug";
import { useClipboard } from "hooks/useClipboard";
import { CircleHelpIcon } from "lucide-react";
import { ChevronDownIcon, CircleHelpIcon, CopyIcon } from "lucide-react";
import { useSearchParams } from "next/navigation";
import { Fragment, useMemo, useState } from "react";
import { FiChevronDown, FiCopy } from "react-icons/fi";
import { toast } from "sonner";
import type { ThirdwebContract } from "thirdweb";
import { stringify } from "thirdweb/utils";
@@ -41,7 +40,6 @@ import {
Heading,
Text,
} from "tw-components";
import { useChainSlug } from "../../../../hooks/chains/chainSlug";
interface EventsFeedProps {
contract: ThirdwebContract;
@@ -258,7 +256,7 @@ const EventsFeedItem: React.FC<EventsFeedItemProps> = ({
toast.info("Transaction hash copied.");
}}
>
<Icon as={FiCopy} boxSize={3} />
<CopyIcon className="size-4" />
</Button>
</Tooltip>
<Text fontFamily="mono" noOfLines={1}>
@@ -306,7 +304,7 @@ const EventsFeedItem: React.FC<EventsFeedItemProps> = ({
{transaction.blockNumber}
</Text>
<div>
<Icon as={FiChevronDown} />
<ChevronDownIcon className="size-4" />
</div>
</div>
</Box>
@@ -1,6 +1,6 @@
import { notFound } from "next/navigation";
import { EventsFeed } from "../../../../../../contract-ui/tabs/events/components/events-feed";
import { getContractPageParamsInfo } from "../_utils/getContractFromParams";
import { EventsFeed } from "./events-feed";
export default async function Page(props: {
params: {
@@ -2,8 +2,8 @@ import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import { CircleAlertIcon } from "lucide-react";
import { notFound } from "next/navigation";
import { resolveContractAbi } from "thirdweb/contract";
import { ContractExplorerPage } from "../../../../../../contract-ui/tabs/explorer/page";
import { getContractPageParamsInfo } from "../_utils/getContractFromParams";
import { ContractExplorerPage } from "./ContractExplorerPage";
export default async function Page(props: {
params: {
@@ -2,12 +2,12 @@ import { ChakraProviderSetup } from "@/components/ChakraProviderSetup";
import { SidebarLayout } from "@/components/blocks/SidebarLayout";
import { ContractMetadata } from "components/custom-contract/contract-header/contract-metadata";
import { DeprecatedAlert } from "components/shared/DeprecatedAlert";
import { PrimaryDashboardButton } from "contract-ui/components/primary-dashboard-button";
import type { Metadata } from "next";
import { getContractMetadata } from "thirdweb/extensions/common";
import { resolveFunctionSelectors } from "../../../../../lib/selectors";
import { shortenIfAddress } from "../../../../../utils/usedapp-external";
import { ConfigureCustomChain } from "./ConfigureCustomChain";
import { PrimaryDashboardButton } from "./_components/primary-dashboard-button";
import { supportedERCs } from "./_utils/detectedFeatures/supportedERCs";
import { getContractPageParamsInfo } from "./_utils/getContractFromParams";
import { getContractPageMetadata } from "./_utils/getContractPageMetadata";
@@ -18,9 +18,8 @@ import { Skeleton } from "@/components/ui/skeleton";
import { ToolTipLabel } from "@/components/ui/tooltip";
import { useMutation } from "@tanstack/react-query";
import { TransactionButton } from "components/buttons/TransactionButton";
import { CircleSlash } from "lucide-react";
import { CircleSlash, TrashIcon } from "lucide-react";
import { useState } from "react";
import { FaRegTrashAlt } from "react-icons/fa";
import { toast } from "sonner";
import {
type ContractOptions,
@@ -233,7 +232,7 @@ function ModuleRow(props: {
{uninstallMutation.isPending ? (
<Spinner className="size-4" />
) : (
<FaRegTrashAlt className="size-4" />
<TrashIcon className="size-4" />
)}
</Button>
</ToolTipLabel>
@@ -1,8 +1,8 @@
import { FormControl } from "@chakra-ui/react";
import { useQuery } from "@tanstack/react-query";
import { SolidityInput } from "contract-ui/components/solidity-inputs";
import invariant from "tiny-invariant";
import { FormErrorMessage, FormLabel } from "tw-components";
import { SolidityInput } from "../../../components/solidity-inputs";
import type { InstallModuleForm } from "./ModuleForm";
import { getModuleInstalledParams } from "./getModuleInstalledParams";
@@ -1,7 +1,7 @@
import { notFound, redirect } from "next/navigation";
import { ContractEditModulesPage } from "../../../../../../contract-ui/tabs/manage/page";
import { getContractPageParamsInfo } from "../_utils/getContractFromParams";
import { getContractPageMetadata } from "../_utils/getContractPageMetadata";
import { ContractEditModulesPage } from "./ContractEditModulesPage";
export default async function Page(props: {
params: {
@@ -53,9 +53,9 @@ export const ContractNFTPage: React.FC<NftOverviewPageProps> = ({
return (
<div className="flex flex-col gap-6">
<div className="flex flex-row items-center justify-between">
<h2 className="font-bold text-xl">Contract NFTs</h2>
<div className="flex flex-col gap-2 md:flex-row">
<div className="flex flex-col gap-3 xl:flex-row xl:items-center xl:justify-between">
<h2 className="font-semibold text-2xl tracking-tight">Contract NFTs</h2>
<div className="grid grid-cols-2 gap-2 md:flex">
{isRevealable && <NFTRevealButton contract={contract} />}
{isERC721ClaimToSupported && (
/**
@@ -2,10 +2,6 @@
import { Flex, useDisclosure } from "@chakra-ui/react";
import { TransactionButton } from "components/buttons/TransactionButton";
import {
type AirdropAddressInput,
AirdropUpload,
} from "contract-ui/tabs/nfts/components/airdrop-upload";
import { useTrack } from "hooks/analytics/useTrack";
import { useTxNotifications } from "hooks/useTxNotifications";
import { UploadIcon } from "lucide-react";
@@ -15,6 +11,7 @@ import { multicall } from "thirdweb/extensions/common";
import { balanceOf, encodeSafeTransferFrom } from "thirdweb/extensions/erc1155";
import { useActiveAccount, useSendAndConfirmTransaction } from "thirdweb/react";
import { Button, Text } from "tw-components";
import { type AirdropAddressInput, AirdropUpload } from "./airdrop-upload";
interface AirdropTabProps {
contract: ThirdwebContract;
@@ -335,7 +335,7 @@ const AirdropTable: React.FC<AirdropTableProps> = ({ data, portalRef }) => {
return address;
}
return (
<div className="flex flex-row">
<div className="flex flex-row items-center gap-2">
<Tooltip
label={
address.startsWith("0x")
@@ -0,0 +1,138 @@
"use client";
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { zodResolver } from "@hookform/resolvers/zod";
import { TransactionButton } from "components/buttons/TransactionButton";
import { useTrack } from "hooks/analytics/useTrack";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { type ThirdwebContract, isAddress } from "thirdweb";
import { mintAdditionalSupplyTo } from "thirdweb/extensions/erc1155";
import { useActiveAccount, useSendAndConfirmTransaction } from "thirdweb/react";
import { z } from "zod";
interface MintSupplyTabProps {
contract: ThirdwebContract;
tokenId: string;
}
const mintAdditionalSupplyFormSchema = z.object({
to: z.string().refine((value) => isAddress(value), {
message: "Invalid Ethereum address",
}),
amount: z.number().int().min(1, "Amount must be at least 1"),
});
const MintSupplyTab: React.FC<MintSupplyTabProps> = ({ contract, tokenId }) => {
const trackEvent = useTrack();
const address = useActiveAccount()?.address;
const form = useForm<z.input<typeof mintAdditionalSupplyFormSchema>>({
resolver: zodResolver(mintAdditionalSupplyFormSchema),
defaultValues: {
amount: 1,
to: address || "",
},
});
const sendAndConfirmTx = useSendAndConfirmTransaction();
function onSubmit(values: z.input<typeof mintAdditionalSupplyFormSchema>) {
trackEvent({
category: "nft",
action: "mint-supply",
label: "attempt",
});
const transaction = mintAdditionalSupplyTo({
contract,
to: values.to,
tokenId: BigInt(tokenId),
supply: BigInt(values.amount),
});
const promise = sendAndConfirmTx.mutateAsync(transaction, {
onSuccess: () => {
trackEvent({
category: "nft",
action: "mint-supply",
label: "success",
});
form.reset();
},
onError: (error) => {
trackEvent({
category: "nft",
action: "mint-supply",
label: "error",
error,
});
},
});
toast.promise(promise, {
loading: "Minting NFT",
success: "Minted successfully",
error: "Failed to mint",
});
}
return (
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="flex w-full flex-col gap-2"
>
<FormField
control={form.control}
name="amount"
render={({ field }) => (
<FormItem>
<FormLabel>Amount</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormDescription>
How many would you like to mint?
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="to"
render={({ field }) => (
<FormItem>
<FormLabel>Recipient</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<TransactionButton
txChainID={contract.chain.id}
transactionCount={1}
isLoading={sendAndConfirmTx.isPending}
type="submit"
colorScheme="primary"
alignSelf="flex-end"
>
Mint
</TransactionButton>
</form>
</Form>
);
};
export default MintSupplyTab;
@@ -1,7 +1,7 @@
import { notFound, redirect } from "next/navigation";
import { TokenIdPage } from "../../../../../../../contract-ui/tabs/nfts/components/token-id";
import { getContractPageParamsInfo } from "../../_utils/getContractFromParams";
import { getContractPageMetadata } from "../../_utils/getContractPageMetadata";
import { TokenIdPage } from "./token-id";
export default async function Page(props: {
params: {

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