Compare commits

...
Author SHA1 Message Date
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
120f965941 Version Packages (#5117)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-25 09:03:57 +13:00
kien-ngo cf36a33c3f [Dashboard] Update erc1155 airdrop form (#5127)
- [x] Remove tw-component's Drawer
- [x] Consolidate some shared code
- [x] Remove an useEffect

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on refactoring the airdrop functionality in a dashboard application, improving the handling of token and NFT airdrops by consolidating interfaces and components.

### Detailed summary
- Renamed `ERC20AirdropAddressInput` to `AirdropAddressInput`.
- Updated `AirdropUploadERC20` to `AirdropUpload`.
- Adjusted state management for airdrop data.
- Simplified CSV data processing.
- Enhanced error handling during transaction processes.
- Replaced modal with `Sheet` component for airdrop interface.

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

<!-- end pr-codex -->
2024-10-24 19:39:52 +00:00
joaquim-verges 2fdb69dd44 optimize: improve mintAdditionalSupplyTo efficiency (#5148)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on optimizing the `mintAdditionalSupplyTo` function in the `erc1155` extension by modifying how the token URI is handled during the minting process.

### Detailed summary
- Removed the retrieval of the existing token URI from the contract.
- Set the `uri` field to an empty string, indicating the contract will maintain the existing token URI.
- Kept the `to`, `tokenId`, and `amount` fields unchanged.

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

<!-- end pr-codex -->
2024-10-24 08:41:20 +00:00
Joaquim VergesandGitHub 06c0cf3898 chore: update @mobile-wallet-protocol/client to 0.1.1 (#5151) 2024-10-24 21:07:55 +13:00
Joaquim VergesandGitHub 47b1bbbd7c feat: enable sign in with wallet for ecosystems (#5153) 2024-10-24 21:06:47 +13:00
kien-ngo 53e9d8bc1d [SDK] Consolidate ERC1155 Drop tests (#5137)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR primarily focuses on refactoring tests for the `erc1155` extension, updating account references, and adding new test cases for metadata updates and claim conditions.

### Detailed summary
- Deleted `claimTo.test.ts` and `updateMetadata.test.ts`.
- Updated account references from `TEST_ACCOUNT_A` to `TEST_ACCOUNT_C`.
- Added a test case for updating metadata.
- Added a test case to verify claiming without payment for the primary fee recipient.
- Ensured `getActiveClaimCondition` works correctly with new test cases.

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

<!-- end pr-codex -->
2024-10-24 06:01:54 +00:00
jnsdls 9fadbcc17a update dependencies (#5150)
<!-- start pr-codex -->

## PR-Codex overview
This PR focuses on updating dependencies across multiple packages, including `@thirdweb-dev/react-native-adapter`, `@thirdweb-dev/service-utils`, and `thirdweb`, along with making type exports consistent in various modules.

### Detailed summary
- Updated `@cloudflare/workers-types` from `4.20241011.0` to `4.20241022.0`.
- Updated `@biomejs/biome` from `1.9.3` to `1.9.4`.
- Updated `turbo` from `2.1.3` to `2.2.3`.
- Updated `@tanstack/react-query` from `5.59.13` to `5.59.16` across multiple packages.
- Updated `lucide-react` from `0.452.0` to `0.453.0` across multiple packages.
- Updated `tailwindcss` from `3.4.13` to `3.4.14` across multiple packages.
- Updated `react-native` from `0.75.3` to `0.76.0`.
- Changed exports from `export { type ... }` to `export type { ... }` in several files for consistency.
- Updated multiple AWS SDK dependencies to `3.678.0`.
- Updated `viem` from `2.21.25` to `2.21.34`.

> 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-24 01:15:46 +00:00
gregfromstl c04b93e705 [Dashboard] Feature: AA analytics tab (#5149)
<!-- start pr-codex -->

## PR-Codex overview
This PR focuses on enhancing the analytics dashboard for account abstraction by updating components, improving data handling, and adding new features for user operation statistics and wallet usage.

### Detailed summary
- Updated `clientId` handling in `ConnectAnalyticsDashboard` and `AccountAbstractionPage`.
- Introduced `connectLayoutSlug` prop in `ConnectAnalyticsDashboard`.
- Added `IntervalSelector` and `DateRangeSelector` components for better date management.
- Refactored `ConnectAnalyticsDashboardUI` to include `AccountAbstractionSummary`.
- Enhanced `TotalSponsoredChartCard` and `SponsoredTransactionsChartCard` with new chart states.
- Moved `createUserOpStatsStub` to a new location and cleaned up unused code.
- Improved data aggregation for user operation statistics in `useUserOpUsageAggregate`.

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

<!-- end pr-codex -->
2024-10-24 00:25:00 +00:00
Jonas DanielsandGitHub e6e994479f move landing page to framer (#5146) 2024-10-23 17:00:11 -07:00
arcoraven cf61115064 chore: add knowledge base link (#5147)
<!-- start pr-codex -->

## PR-Codex overview
This PR updates the `supportLinks` array in the `Header.tsx` file to improve the naming of existing links and to add a new link for the Knowledge Base.

### Detailed summary
- Changed the name of the first link from `"Support Site"` to `"Get thirdweb support"`.
- Added a new link for the Knowledge Base with the name `"Knowledge Base"` and the URL `https://support.thirdweb.com`.

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

<!-- end pr-codex -->
2024-10-23 23:31:43 +00:00
Joaquim VergesandGitHub 60d2190e95 feat: smart account options for ecosystems (#5136) 2024-10-24 12:16:52 +13:00
MananTank 3cf0039c58 Move support ticket creation to /support/create-ticket page (#5144)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on restructuring the support ticket creation process in the dashboard application. It removes the old `CreateTicket` component and replaces it with a new implementation, enhancing user navigation and support form functionality.

### Detailed summary
- Deleted `create-ticket.client.tsx`.
- Updated `SupportPage` to replace `<CreateTicket />` with a button linking to `/support/create-ticket`.
- Created a new `Page` component for the support ticket creation, including authentication check and breadcrumb navigation.
- Introduced a new `CreateTicket` component with dynamic support form imports and form handling.
- Added form reset and submission handling in `CreateTicket`.

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

<!-- end pr-codex -->
2024-10-23 20:01:35 +00:00
kien-ngo 4841ff382a [Dashboard] Add some informative badges to the Explorer (#5138)
![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/VtULqGKSp33n0VHOzNJK/1670002e-3123-4770-b29c-fdc84dce88dd.png)
2024-10-23 18:51:06 +00:00
MananTank d580fe05e3 Customize faucet claim amount for various chains (#5143)
<!-- start pr-codex -->

## PR-Codex overview
This PR focuses on updating the `FaucetButton` and related components to use dynamic claim amounts based on the `chainId`, replacing hardcoded values with a function that retrieves the appropriate amount.

### Detailed summary
- Changed `amount` type from `string` to `number` in `FaucetButton.tsx`.
- Introduced `customClaimAmounts` and `defaultClaimAmount` in `claim-amount.ts`.
- Updated `FaucetSection` and `GetFundsFromFaucet` to use `getFaucetClaimAmount`.
- Modified API response in `route.ts` to return dynamic claim amounts.

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

<!-- end pr-codex -->
2024-10-23 17:33:34 +00:00
MananTank 7a1099b601 Make rows in contract table actual links to allow opening in new tab with cmd click (#5142)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the `DeployedContractsPageHeader` and related components by improving the link handling for contract names and refining the UI elements in the contract table.

### Detailed summary
- Updated `DeployedContractsPageHeader` to use a new `Button` import.
- Added `linkOverlay` prop to `AsyncContractNameCell`.
- Enhanced link styling in `AsyncContractNameCell` with conditional classes.
- Passed `linkOverlay` prop when rendering `AsyncContractNameCell` in the contract table.
- Simplified event handling in `ContractTableRow`.

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

<!-- end pr-codex -->
2024-10-23 17:09:16 +00:00
MananTank 4e5fdcf415 Fix claim condition loading state + UI tweaks (#5141)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on refactoring the `ClaimConditionsForm` component in the `claim-conditions` files to improve layout and loading state handling.

### Detailed summary
- Updated `Flex` component properties in `claim-conditions.tsx` for layout consistency.
- Added a loading spinner in `claim-conditions-form/index.tsx` to handle fetching state.
- Removed the previous spinner implementation for a cleaner loading experience.
- Adjusted `flexDir` property for better responsiveness.

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

<!-- end pr-codex -->
2024-10-23 16:57:37 +00:00
MananTank eaeb53218c Show 404 on invalid contract address in contract page (#5140)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR enhances the `Layout` component by adding a validation check to ensure that the `contractAddress` parameter is a valid address using `isAddress`. If the address is invalid, it returns a "not found" response.

### Detailed summary
- Imported `isAddress` from `thirdweb/utils`.
- Added a check to validate `props.params.contractAddress` using `isAddress`.
- If the address is invalid, the function returns `notFound()`.

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

<!-- end pr-codex -->
2024-10-23 16:52:11 +00:00
MananTank 09b7404985 Show 404 on deprecated chain contract page (#5139)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on improving the handling of contract metadata and checking for deprecated chains in the `layout.tsx` file. It ensures that the correct contract information is used and adds a condition to handle deprecated chain statuses.

### Detailed summary
- Added a check for `chainMetadata.status` to call `notFound()` if the status is "deprecated".
- Updated the `isValidContract` check to use `contract` from `info` instead of the previous variable.
- Rearranged the destructuring of `contract` and `chainMetadata` for clarity.

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

<!-- end pr-codex -->
2024-10-23 16:52:10 +00:00
Joaquim VergesandGitHub 3c77c6b2c8 fix: correct indentation in useSendTransaction example (#5133) 2024-10-23 19:46:54 +13:00
kien-ngo 71aa2578c3 [SDK] Consolidate tests to avoid excessive deployERC1155Contract (#5135)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR primarily focuses on refactoring and enhancing the test coverage for the `erc1155` extension of the `thirdweb` package. It removes outdated tests, introduces new tests, and updates existing ones to improve functionality verification.

### Detailed summary
- Removed multiple test files related to `erc1155` functions.
- Updated `lazyMint.test.ts` to use `DROP1155_CONTRACT`.
- Added a test for `isGetNFTsSupported` in `drop1155.test.ts`.
- Simplified and enhanced tests in `mintAdditionalSupplyToBatch.test.ts`.
- Introduced new tests for `updateTokenURI`, minting, and `getOwnedTokenIds` in `token1155.test.ts`.

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

<!-- end pr-codex -->
2024-10-23 06:37:09 +00:00
kien-ngo c32576fb47 [SDK] ERC721 claimToBatch extension (#5124)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces the `claimToBatch` functionality for the `ERC721` extension, allowing multiple claims in a single transaction. It includes tests to ensure the optimization of claim content and the correct processing of batch claims.

### Detailed summary
- Added `claimToBatch` function in `claimToBatch.ts` for batch claiming NFTs.
- Introduced `ClaimToBatchParams` type to define batch claim structure.
- Implemented `optimizeClaimContent` function to consolidate identical recipient claims.
- Created tests for `claimToBatch` and `optimizeClaimContent` in `claimToBatch.test.ts`.
- Verified the functionality of `isClaimToSupported` in the test suite.

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

<!-- end pr-codex -->
2024-10-23 03:39:12 +00:00
kien-ngo d522343e04 [SDK] Optimize mintAdditionalSupplyToBatch (#5125)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on optimizing the `mintAdditionalSupplyToBatch` extension by introducing a new function to batch minting requests that share the same recipient and token ID, reducing the number of transactions required.

### Detailed summary
- Added `WithOverrides` to `MintAdditionalSupplyToBatchParams`.
- Implemented `optimizeMintBatchContent` function to consolidate minting requests.
- Updated `mintAdditionalSupplyToBatch` to use optimized NFT data.
- Added a test for `optimizeMintBatchContent` to verify its functionality.

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

<!-- end pr-codex -->
2024-10-23 03:15:05 +00:00
gregfromstl 4f22e2b190 [SDK] Feature: Track transactions and SIWE (#5086)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on improving the analytics tracking for wallet connections and transactions within the `thirdweb` library. It refines the tracking methods by introducing specific tracking functions for connections and payments, enhancing the data sent for analytics.

### Detailed summary
- Deleted `track.ts` file.
- Updated import paths for `trackConnect` and `trackPayEvent` in several files.
- Introduced `trackConnect` and `trackPayEvent` functions with detailed parameters.
- Added tracking functionality to wallet connection methods in `in-app` and `coinbase` wallets.
- Enhanced error handling and data structure in tracking functions.
- Added tests for `trackConnect`, `trackPayEvent`, and `trackLogin` functionalities.

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

<!-- end pr-codex -->
2024-10-23 00:37:33 +00:00
gregfromstl 319a203a4e [SDK] Fix: Prevent Duplicated RDNS Values from WalletConnect (#5129)
Fixes #5116

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on updating wallet metadata and image assets for various wallets in the `thirdweb` project. It includes changes to wallet IDs, homepages, image IDs, and mobile app links, ensuring accurate information for wallet integration.

### Detailed summary
- Removed the file `lovely-items-live.md`.
- Updated `native` and `universal` links for `finance.plena` and `finance.openwallet`.
- Changed `image_id` for `Crypto.com`, `Status`, `Coin98`, and others.
- Added new wallet entries for `com.daffione`, `com.beexo`, `id.plumaa`, `io.owallet`, and `com.ipmb`.
- Updated `getWalletInfo` method to include new wallets and remove `org.nitrogen` and `com.brave.wallet`.
- Added new images for several wallets as base64 encoded data.
- Updated the count of supported wallets in `wallet-ids.ts` and `wallet-infos.ts`.

> The following files were skipped due to too many changes: `packages/thirdweb/src/wallets/__generated__/wallet/com.coin98/image.ts`, `packages/thirdweb/src/wallets/__generated__/wallet/app.status/image.ts`

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

<!-- end pr-codex -->
2024-10-23 00:25:29 +00:00
MananTank cdb907f175 Remove Gas estimator link in footer (#5134)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on modifying the `app-footer.tsx` component by removing the `Gas Estimator` link from the footer.

### Detailed summary
- Removed the `Link` component for `Gas Estimator`.
- The remaining `Link` component for `chainlist` retains its class names and attributes.

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

<!-- end pr-codex -->
2024-10-22 23:50:57 +00:00
joaquim-verges 364d97e97e feat: auto-resolve entrypoint address from factory (#5123)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on updating the `smartWallet` integration to automatically resolve the entrypoint address from the account factory when available, enhancing usability and simplifying the configuration for users.

### Detailed summary
- Replaced `ENTRYPOINT_ADDRESS_v0_7` with `DEFAULT_ACCOUNT_FACTORY_V0_7` in the `smartWallet` configuration.
- Updated documentation to reflect changes in how to use the `smartWallet` with the factory.
- Added logic to resolve the entrypoint address from the factory if not provided.
- Introduced a new function `getEntrypointFromFactory` to fetch the entrypoint address from the account factory contract.

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

<!-- end pr-codex -->
2024-10-22 21:54:20 +00:00
gregfromstl 795e9c13a4 [Service Utils] Feature: add ecosystem headers to extractAuthorizationData (#5083)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces new ecosystem headers to the `extractAuthorizationData` function in the `service-utils` package, enhancing the authorization process by including `ecosystemId` and `ecosystemPartnerId`.

### Detailed summary
- Added `ecosystemId` and `ecosystemPartnerId` to the type definitions in `index.ts`.
- Updated `extractAuthorizationData` to retrieve `ecosystemId` and `ecosystemPartnerId` from headers and URL search parameters in `cf-worker/index.ts` and `node/index.ts`.

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

<!-- end pr-codex -->
2024-10-22 21:24:33 +00:00
MananTank 0b510f881b Handle contract page crash if contract is not deployed (#5132)
## 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 `ContractOverviewPage` and validating contract existence in the `layout.tsx`. It introduces an `ErrorBoundary` around the `PublishedBy` component and checks if a contract is deployed before rendering the layout.

### Detailed summary
- Wrapped the `PublishedBy` component in an `ErrorBoundary` in `ContractOverviewPage.tsx`.
- Added a check for contract deployment using `isContractDeployed` in `layout.tsx`.
- Implemented a `notFound()` call if the contract is not deployed, with a TODO for future improvements.

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

<!-- end pr-codex -->
2024-10-22 21:09:06 +00:00
kien-ngo 5351d4e407 [SDK] minor fix for test (#5122)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR refactors the test for the `mintToBatch` function, changing its execution context and updating the minting logic to utilize `mintAdditionalSupplyToBatch`. It also modifies the structure of the NFT data being tested.

### Detailed summary
- Changed `describe` to use `describe.runIf(process.env.TW_SECRET_KEY)`.
- Updated minting function from `mintToBatch` to `mintAdditionalSupplyToBatch`.
- Adjusted parameters for minting NFTs.
- Modified the expected NFT details in the final assertion.

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

<!-- end pr-codex -->
2024-10-22 20:26:10 +00:00
gregfromstl 0cafa33a18 [SDK] Feature: GitHub Auth (#5062)
<!-- start pr-codex -->

## PR-Codex overview
This PR introduces GitHub authentication support across various components of the application, enhancing the social login options for users.

### Detailed summary
- Added `GitHub` to authentication options in `types.ts`.
- Included `GitHub` in the social login forms and icons.
- Updated the `InAppWebConnector` to handle `GitHub` authentication.
- Defined `GITHUB_ICON` SVG for branding.
- Integrated `githubIconUri` for wallet icons.

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

<!-- end pr-codex -->
2024-10-22 19:44:00 +00:00
gregfromstl dd77c7f57c Analytics UI Empty States (#5121)
<img width="968" alt="Screenshot 2024-10-21 at 6 23 23 PM" src="https://github.com/user-attachments/assets/86000f33-2041-4d3a-b084-b6367e61f032">

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the `DocLink` component for better link handling and integrating it into various chart components for improved user guidance on wallet connections and transactions.

### Detailed summary
- Added `DocLink` component in `DocLink.tsx`.
- Refactored `ConnectSDKCard` to use `DocLink` instead of its previous implementation.
- Modified `EmptyChartState` to accept `children` for customizable content.
- Integrated `DocLink` into multiple chart components, providing links for wallet integration guidance.

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

<!-- end pr-codex -->
2024-10-22 19:21:27 +00:00
MananTank 9c3ff94f29 Move ContractCard and PublishedBy components to RSC (#5097) 2024-10-22 18:44:47 +00:00
Joaquim VergesandGitHub 45fcfb1dae feat: support smart account options for ecosystem wallets (#5091) 2024-10-22 22:25:00 +13:00
Joaquim VergesandGitHub 788eefd1d5 refactor: simplify API fetch error handling in aa-chains route (#5119) 2024-10-22 22:24:06 +13:00
kien-ngo f8c981c0ca [SDK] ERC1155 extension: mintAdditionalSupplyToBatch (#5036)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces a new ERC1155 extension called `mintAdditionalSupplyToBatch`, allowing users to mint additional supplies of NFTs in a single transaction. It also modifies existing minting logic for better handling of asynchronous operations.

### Detailed summary
- Added new extension `mintAdditionalSupplyToBatch` in `mintAdditionalSupplyToBatch.ts`.
- Updated `mintToBatch.ts` for improved async handling and data processing.
- Created tests for `mintAdditionalSupplyToBatch` in `mintAdditionalSupplyToBatch.test.ts`.
- Updated export statements in `erc1155.ts` to include the new function.

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

<!-- end pr-codex -->
2024-10-22 06:30:29 +00:00
kien-ngo 1628fa2a79 [SDK] Improve general test cases (#5054)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces new tests for resolving Unstoppable Domains and updates the `mintToBatch` test for `ERC1155` contracts, including the handling of NFT retrieval and ensuring proper error handling.

### Detailed summary
- Added a test case in `resolveName.test.ts` to check error handling for addresses without a domain.
- Updated the `mintToBatch.test.ts` to use `describe.runIf` for conditional execution.
- Refactored the `mintToBatch` test to include NFT retrieval and validation after minting.

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

<!-- end pr-codex -->
2024-10-22 06:18:22 +00:00
joaquim-verges 0e26a88e7f fix: resolve ecosystem image URL using thirdweb storage (#5120)
## Problem solved

Fixes CNCT-2087

<!-- start pr-codex -->

---

## PR-Codex overview
This PR enhances the `Layout` component in the `layout.tsx` file by improving the way the ecosystem image URL is resolved using `resolveScheme`, ensuring proper handling of the image source.

### Detailed summary
- Added import for `resolveScheme` from `thirdweb/storage`.
- Added import for `client` from `../../../lib/client`.
- Updated the `src` attribute of the `<img>` tag to use `resolveScheme({ uri: ecosystem.imageUrl, client })` instead of directly using `ecosystem.imageUrl`.

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

<!-- end pr-codex -->
2024-10-22 00:52:15 +00:00
joaquim-verges 50f98d7486 portal: show all supported chains in AA docs (#5090)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the `Document` component by adding the `AAChainList` feature, which fetches and displays account abstraction chains. It also improves the API route for fetching chain data.

### Detailed summary
- Added `AAChainList` component in `apps/portal/src/components/Document/AAChainList.tsx`.
- Implemented `getChains` function to fetch account abstraction chains.
- Updated API route in `apps/portal/src/app/api/aa-chains/route.ts` to fetch services and chains.
- Integrated `AAChainList` in the `page.mdx` for displaying available chains.

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

<!-- end pr-codex -->
2024-10-21 23:14:11 +00:00
joaquim-verges 40aeb529ac test: add environment check for ERC1155 mintToBatch tests (#5115)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR modifies the test for the `mintToBatch` function in the `ERC1155 Edition` to include conditional execution based on the presence of a `TW_SECRET_KEY`. It also refactors the test structure, improving readability and organization.

### Detailed summary
- Changed `describe` to conditionally run based on `process.env.TW_SECRET_KEY`.
- Refactored the test structure for `mintToBatch`.
- Moved the `sendAndConfirmTransaction` call inside the test.
- Added detailed NFT validation after minting.
- Removed redundant code and improved clarity.

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

<!-- end pr-codex -->
2024-10-21 23:00:13 +00:00
kumaryash90 e7bbc321c2 Fix auto verification of contracts (#5099)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces the export of the `verifyContract` function from `ContractSourcesPage.tsx` and integrates it into the `CustomContractForm` component to send a verification request after deploying a contract.

### Detailed summary
- Changed `verifyContract` from a local function to an exported function in `ContractSourcesPage.tsx`.
- Imported `verifyContract` into `custom-contract.tsx`.
- Added a call to `verifyContract` in the `CustomContractForm` after contract deployment.

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

<!-- end pr-codex -->
2024-10-21 22:09:39 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
8f157aa43f chore(deps-dev): bump @vitejs/plugin-react from 4.3.2 to 4.3.3 (#5114)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-21 14:54:09 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
a437baa57a chore(deps): bump @shazow/whatsabi from 0.15.3 to 0.15.4 (#5113)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-21 14:27:29 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
4331ed1f04 chore(deps): bump framer-motion from 11.11.8 to 11.11.9 (#5112)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-21 14:12:37 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
5c896b0fd5 chore(deps-dev): bump msw from 2.4.11 to 2.4.12 (#5107)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-21 14:06:36 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
16aa7b7918 chore(deps-dev): bump typedoc from 0.26.9 to 0.26.10 (#5106)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-21 14:01:41 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
341d312679 chore(deps-dev): bump @storybook/test from 8.3.5 to 8.3.6 (#5100)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-21 14:00:25 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
3aff548a10 chore(deps-dev): bump @types/papaparse from 5.3.14 to 5.3.15 (#5103)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-21 14:00:13 -07:00
MananTank 002c545d0e Handle published contract page server side errors (#5098)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on improving error handling and null checks in the `published-contract` related components of the dashboard application. It ensures that appropriate actions are taken when data is missing, enhancing the application's robustness.

### Detailed summary
- Added null checks for `publishedContracts` in multiple files.
- Implemented `notFound()` calls when `publishedContractVersions` or `publishedContracts` are missing.
- Enhanced error handling in `getPublishedContractsWithPublisherMapping.ts` with try-catch.
- Updated `publisherAddress` resolution logic for better clarity.

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

<!-- end pr-codex -->
2024-10-21 20:29:44 +00:00
MananTank bc5b543269 Fix all resolveScheme unhandled errors (#5096)
Fixes: DASH-333
2024-10-21 19:36:51 +00:00
MananTank 1a45f21abb Handle page crash when rendering NFTs with unexpected title, description values (#5095)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces error handling components to display messages for unexpected values in the NFT-related pages, enhancing user experience by providing feedback when data does not meet expectations.

### Detailed summary
- Added `react-error-boundary` to handle errors.
- Created `UnexpectedValueErrorMessage` component for displaying error messages.
- Integrated error handling in `TokenIdPage`, `NFTName`, and `NFTDescription` components.
- Updated `NFTGetAllTable` to use `UnexpectedValueErrorMessage` for invalid data.
- Wrapped NFT cell rendering in `ErrorBoundary` to catch errors.

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

<!-- end pr-codex -->
2024-10-21 16:42:20 +00:00
kien-ngo d59ab13ce8 [Dashboard] Add Media URI to token page (#5088)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR enhances the `TokenIdPage` component by adding a section to display the media URI of an NFT, including a button to copy the URI and a link to view it externally.

### Detailed summary
- Added a conditional rendering block to display the media URI if `nft.metadata.image` exists.
- Included a `GridItem` for the "Media URI" heading.
- Added a `CopyTextButton` to copy the media URI.
- Added a button with a link to the media URI, featuring an `ExternalLinkIcon`.

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

<!-- end pr-codex -->
2024-10-21 13:44:06 +00:00
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
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
33c2f56d3d Version Packages (#4950)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-09 10:08:26 +13:00
Joaquim VergesandGitHub eff129ab9a feat: export fetchKeyMetadataFromApi and remove checkPolicy options (#4955) 2024-10-09 09:13:24 +13:00
joaquim-verges 8efe536482 feat: add account factory 0.7 to explore (#4951)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces support for new account factories and updates documentation regarding custom account factories and Entrypoint v0.7. It enhances the `smartWallet` function and provides clearer information on available account factory options.

### Detailed summary
- Added support for `thirdweb.eth/AccountFactory_0_7` and `thirdweb.eth/ManagedAccountFactory_0_7`.
- Updated documentation to include usage of custom account factories with the `smartWallet` function.
- Included examples for using v0.7 Entrypoint with `smartWallet`.
- Revised default account factory information in the documentation to specify v0.6 and v0.7 options.

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

<!-- end pr-codex -->
2024-10-08 19:43:51 +00:00
GWSzeto 5c4c570176 fix: small typo in the getting started docs (#4954)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on modifying the initialization of `callbackFunctions` and `fallbackFunctions` in the `create-module-contract` function to use dynamic arrays instead of single instances.

### Detailed summary
- Changed `config.callbackFunctions` from a single `CallbackFunction` to a dynamic array of `CallbackFunction` with size 1.
- Changed `config.fallbackFunctions` from a single `FallbackFunction` to a dynamic array of `FallbackFunction` with size 2.

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

<!-- end pr-codex -->
2024-10-08 19:38:47 +00:00
Joaquim VergesandGitHub ea36c54118 feat: allow overriding callGasLimit for userops (#4948) 2024-10-09 07:25:47 +13:00
cf37bb5e54 Bump @storybook/test from 8.3.4 to 8.3.5 (#4943)
Co-authored-by: dependabot <[email protected]>
2024-10-08 10:32:20 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Manan Tank
fbab9f75d0 Bump @changesets/cli from 2.27.8 to 2.27.9 (#4941)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Manan Tank <[email protected]>
2024-10-08 10:32:08 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Manan Tank
96943e69f1 Bump @storybook/addon-interactions from 8.3.4 to 8.3.5 (#4940)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Manan Tank <[email protected]>
2024-10-08 10:31:57 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Manan Tank
6d84a5d81a Bump @shazow/whatsabi from 0.14.1 to 0.15.2 (#4942)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Manan Tank <[email protected]>
2024-10-08 10:31:32 -07:00
kien-ngo 4f6c364da2 [Dashboard] Add searchbar for Explorer (#4916)
Part of DASH-246

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces a search functionality to filter displayed functions in the `ContractFunctionsPanel`. It enhances user experience by allowing users to search for specific functions using a search input.

### Detailed summary
- Added `SearchIcon` and `Input` components for search functionality.
- Implemented state management for keyword search using `useState` and `useDebounce`.
- Filtered functions based on the search input before rendering.
- Updated the layout to include the search input at the top of the functions list.

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

<!-- end pr-codex -->
2024-10-08 17:13:42 +00:00
kien-ngo 0e900fe319 [Dashboard] Replace erc721 claim Drawer with Sheet (#4932)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on refactoring the `NFTClaimButton` component to replace the `Drawer` with a `Sheet` component for a better user interface. It enhances the form handling by integrating validation and error messaging for claiming NFTs.

### Detailed summary
- Removed the `Drawer` component and replaced it with a `Sheet`.
- Integrated `react-hook-form` for form handling.
- Added validation for the "To Address" and "Amount" fields.
- Implemented error messages for form validation.
- Added transaction handling logic for NFT claims.
- Used `TransactionButton` for submitting the claim.

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

<!-- end pr-codex -->
2024-10-08 16:47:31 +00:00
MananTank 1adbc62477 Migrate Engine Overview page to shadcn/tailwind - Part1 (#4926)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on refactoring the `CreateBackendWalletButton` and `ImportBackendWalletButton` components to use a new dialog system, enhancing the user interface and improving code structure. It also introduces tooltips and updates form handling for better user experience.

### Detailed summary
- Replaced `Modal` with `Dialog` for `CreateBackendWalletButton` and `ImportBackendWalletButton`.
- Added `tooltip` prop in `FormFieldSetup`.
- Updated form handling for better state management and error display.
- Enhanced UI elements with improved styling and layout.
- Refactored wallet import and creation logic for clarity and maintainability.

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

<!-- end pr-codex -->
2024-10-08 16:36:28 +00:00
kien-ngo 87c88546ec [Dashboard] Small update to allow open link with Explorer (#4930)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR enhances the `InteractiveAbiFunction` component by adding support for displaying links for both IPFS URIs and traditional URLs. It introduces an `ExternalLinkIcon` and a new `Link` component for external links, improving user accessibility to resources.

### Detailed summary
- Added import for `ExternalLinkIcon` and `Link` from `next/link`.
- Modified the `language` prop in `CodeBlock` based on the response data type.
- Introduced a link for IPFS URIs that opens in a new tab.
- Added a link for traditional URLs with an icon, enhancing user interaction.

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

<!-- end pr-codex -->
2024-10-08 16:26:08 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
d5039f4aa0 Version Packages (#4945)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-08 15:05:08 +13:00
Joaquim VergesandGitHub 7b7226f9c6 feat: export additional types from service-utils (#4946) 2024-10-08 14:33:58 +13:00
Joaquim VergesandGitHub 506764dabd feat: support showAllWallets prop in React Native Connect UI (#4933) 2024-10-08 11:19:54 +13:00
Joaquim VergesandGitHub a6449125b2 feat: add 'from' parameter to estimateGas example (#4938) 2024-10-08 11:19:27 +13:00
Joaquim VergesandGitHub 822ece45ec feat: add option to disable storing last passkey credentials (#4944) 2024-10-08 11:18:52 +13:00
MananTank fa826b5f1f Add Teams UI Banners (#4936)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces a new `DashboardTypeCookieSetter` component to manage dashboard type cookies and updates various parts of the application to utilize this functionality. It also adds new banner components for improved user notifications.

### Detailed summary
- Added `DashboardTypeCookieSetter` component to set dashboard type cookies.
- Integrated `DashboardTypeCookieSetter` in `AppShell`, `RootTeamLayout`, and `AccountLayout`.
- Created `TeamsUIBanner` and `TryTeamsUIBanner` components for user announcements.
- Updated routing logic in `login/page.tsx` based on cookie value.
- Modified `AnnouncementBanner` for better usability and appearance.
- Added a new button in `HeroSection` to redirect based on cookie value.

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

<!-- end pr-codex -->
2024-10-07 20:39:59 +00:00
MananTank dce2ca0e3d Fix MaskedAvatar component stuck in loading state (#4937)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR primarily focuses on making minor adjustments to the text content in the `ambassadors.tsx` file and refining the handling of props in the `MaskedAvatar` component within `masked-avatar/index.tsx`.

### Detailed summary
- In `ambassadors.tsx`, added a space after "Meet the".
- In `masked-avatar/index.tsx`:
  - Changed `skeletonData` from `false` to `undefined`.
  - Changed `loadedData` from `isPending` to `src`.
  - Updated the render prop to use `v` instead of `src`.

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

<!-- end pr-codex -->
2024-10-07 19:28:23 +00:00
gregfromstl c6fbd60816 [SDK] Fix: pass gasPrice to injected provider (#4935)
<!-- start pr-codex -->

## PR-Codex overview
This PR introduces the handling of `gasPrice` in the transaction object within the `injected` wallet module.

### Detailed summary
- Added a new line to handle `gasPrice` in the transaction object.
- The `gasPrice` is conditionally converted to hexadecimal format using `numberToHex` if it exists.

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

<!-- end pr-codex -->
2024-10-07 19:11:21 +00:00
kien-ngo 8e8011370b [Dashboard] Replace Reveal-NFT Drawer with Sheet (#4931)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on replacing the `Drawer` component with a `Sheet` component in the `NFTRevealButton`. It enhances the user interface for revealing NFTs by implementing a form within the `Sheet` for batch selection and password input.

### Detailed summary
- Removed `Drawer` and `NFTRevealForm` components.
- Added `Sheet`, `SheetContent`, `SheetHeader`, `SheetTitle`, and `SheetTrigger` components.
- Integrated a form for batch selection and password input using `react-hook-form`.
- Implemented analytics tracking for the reveal action.
- Added error handling and toast notifications for transaction status.

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

<!-- end pr-codex -->
2024-10-07 13:57:32 +00:00
0xFirekeeper 11de1f3ce2 [Portal] MAUI Template & Link Updates (#4929)
<!-- start pr-codex -->

## PR-Codex overview
This PR focuses on enhancing the `.NET SDK Portal` and its documentation, updating package versions, and adding new features related to MAUI integration, while also improving the sidebar navigation.

### Detailed summary
- Added `.NET SDK Portal` link to the sidebar in `sidebar.tsx`.
- Updated `Thirdweb` package version from `1.0.0` to `2.4.0` in `page.mdx`.
- Added `MAUI Integration` link to the sidebar in `sidebar.tsx`.
- Updated reference link for `Full Reference` in `sidebar.tsx`.
- Introduced new content for MAUI integration in `page.mdx`.
- Enhanced documentation with new constants and functions in `utils/page.mdx`.

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

<!-- end pr-codex -->
2024-10-05 07:11:37 +00:00
kien-ngo 5c6f288d2a chore: Fix readContract docs (#4920)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on updating the `useReadContract` function calls in two files by adding a comma to the method definition for better syntax clarity.

### Detailed summary
- In `packages/thirdweb/src/transaction/read-contract.ts`:
  - Added a comma after the method definition for `tokenURI`.

- In `packages/thirdweb/src/react/core/hooks/contract/useReadContract.ts`:
  - Added a comma after the method definition for `tokenURI`.

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

<!-- end pr-codex -->
2024-10-05 02:08:10 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
4660e0ceb8 Version Packages (#4907)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-05 12:06:15 +13:00
YashandGitHub 5211446f20 Cache create2 factory addresses (#4922) 2024-10-05 10:27:46 +13:00
joaquim-verges d4c423cd97 fix: handle 0n as from/to blocks in getContractEvents (#4919)
Fixes CNCT-1987

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on improving the validation of `fromBlock` and `toBlock` parameters in the `getContractEvents` function to ensure they are explicitly defined before performing any calculations.

### Detailed summary
- Updated condition to check if `fromBlock` and `toBlock` are not `undefined` instead of truthy.
- Adjusted logic for setting `restParams.toBlock` and `restParams.fromBlock` based on the new checks.

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

<!-- end pr-codex -->
2024-10-04 20:48:05 +00:00
dirtycajunrice b6bf3b923d Updated docs and replaced outdated speed-racer (#4903)
## Problem solved

* Updated Unreal Engine docs
* Replaced speed-racer references with tappyfowl
* Fixed all references of `unreal`  to `unreal-engine`

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on renaming the `unreal` module to `unreal-engine`, updating related paths, icons, and metadata throughout the codebase. It also introduces new wallet functionalities and modifies some documentation for clarity.

### Detailed summary
- Renamed `unreal` to `unreal-engine` across various files.
- Updated paths and references in `Header.tsx`, `layout.tsx`, and `sidebar.tsx`.
- Changed icon references from `UnrealIcon` to `UnrealEngineIcon`.
- Modified metadata functions to use `createUnrealEngineMetadata`.
- Added new wallet functionalities in `in-app-wallet` and `wallet-handles`.
- Updated documentation in multiple `.mdx` files to reflect changes.
- Deleted obsolete assets and files related to the old `unreal` structure.

> The following files were skipped due to too many changes: `pnpm-lock.yaml`, `apps/portal/src/app/unreal-engine/blueprints/utilities/nodes.ts`, `apps/portal/src/app/unreal-engine/blueprints/in-app-wallet/nodes.ts`, `apps/portal/src/app/unreal/blueprints/smart-wallet/nodes.ts`

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

<!-- end pr-codex -->
2024-10-04 20:37:17 +00:00
ElasticBottle 0f6b881bca docs: update fetching user details endpoint for ecosystems (#4918)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the `getUser` functionality in the `thirdweb` SDK by adding support for querying user details via an external wallet address and ecosystem identifiers.

### Detailed summary
- Added support for querying user details using `externalWalletAddress` in `getUser`.
- Updated documentation for `getUser` to include `externalWalletAddress` as a query parameter.
- Modified examples in the documentation to demonstrate querying with `externalWalletAddress`.
- Updated user detail query parameters in documentation to reflect new options.

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

<!-- end pr-codex -->
2024-10-04 19:54:38 +00:00
4dee169c3b Add ecosystem wallet security documentation (#4911)
Signed-off-by: Ian Mukherjee <[email protected]>
Signed-off-by: Joaquim Verges <[email protected]>
Co-authored-by: Joaquim Verges <[email protected]>
2024-10-05 08:53:52 +13:00
5dfde0f4ec Add guest mode documentation (#4910)
Signed-off-by: Ian Mukherjee <[email protected]>
Co-authored-by: Joaquim Verges <[email protected]>
2024-10-05 08:16:55 +13:00
MananTank b148fa0d65 Plug in Team settings page UI to API (#4888)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR primarily focuses on enhancing the `Team` functionality by adding billing features, updating team settings, and refining the UI components to support new properties such as `billingEmail` and `image`. It also improves the update mechanisms for team attributes.

### Detailed summary
- Added `billingEmail` and `image` fields to the `Team` model.
- Updated the `TeamGeneralSettingsPage` to accept `authToken` instead of `client`.
- Implemented `updateTeam` function to handle team updates.
- Modified UI components to support new fields and update methods.
- Enhanced `FileInput` to handle fallback URLs.
- Refactored `TeamNameFormControl` and `TeamSlugFormControl` to utilize `updateTeamField` for updates.
- Integrated `resolveScheme` for avatar URL handling in `TeamAvatarFormControl`.

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

<!-- end pr-codex -->
2024-10-04 17:36:40 +00:00
MananTank 5c8766b5b6 Remove calls to 0.rpc on deploy page (#4925)
Fixes: DASH-268

![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/yNOf1svJ8o3zjO7zQouZ/4d64b356-b831-40e3-96a6-ed686b59a3e9.png)
2024-10-04 17:19:51 +00:00
MananTank 04f826923e Fix Get started with deploying contracts card buttons layout (#4923)
Current:

![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/yNOf1svJ8o3zjO7zQouZ/41286158-0065-465b-80a5-f61dd62af7b7.png)

Fixed:

![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/yNOf1svJ8o3zjO7zQouZ/be5b23ed-8159-421d-beb0-ca4dfc2f8c12.png)
2024-10-04 15:36:11 +00:00
kien-ngo c935fbf72d [Portal] Fix useChain in migrate docs (#4921)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR updates the TypeScript SDK v5 cheatsheet to reflect changes in the wallet connection methods, specifically updating the references for the `Get Connected Chain` functionality.

### Detailed summary
- Updated the reference for `Get Connected Chain` from [`useSwitchActiveWalletChain()`] to [`useActiveWalletChain()`] in both `page.mdx` files.

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

<!-- end pr-codex -->
2024-10-04 12:57:18 +00:00
Joaquim VergesandGitHub 63d0777e6f feat: add useLinkProfile hook and update profile linking docs + playground (#4906) 2024-10-04 21:18:32 +13:00
MananTank a94f98195b Show active coupon on billing page (#4917)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on refactoring and enhancing coupon-related components in the `Billing` section of the dashboard. It involves renaming components, improving props handling, and adding new functionalities for coupon application and management.

### Detailed summary
- Renamed `CouponCard` to `CouponSection` in `Billing/index.tsx`.
- Updated `SettingsCard` to use dynamic class names for buttons.
- Added new stories for `CouponDetailsCardUI` and `ApplyCouponCardUI`.
- Implemented optimistic updates for coupon application and deletion.
- Enhanced `CouponCard` to `ApplyCouponCard` with new props for coupon application.
- Introduced `CouponDetailsCardUI` for displaying active coupon details.
- Improved error handling and loading states in coupon-related components.

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

<!-- end pr-codex -->
2024-10-04 00:24:25 +00:00
kien-ngo 27375af91b [Dashboard] Remove react-icons (6) (#4915)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on refactoring components to improve code quality and consistency. It replaces some icon imports with new icons from `lucide-react`, adjusts class names for better styling, and introduces new components like `DotNetIcon` and `UnrealIcon`.

### Detailed summary
- Updated `className` in `airdrop-upload-erc20.tsx`.
- Replaced `FiChevronRight` with `ChevronRightIcon` in `MiniPlayground.tsx`.
- Added `DotNetIcon` and `UnrealIcon` components.
- Updated icon usage in `ConnectSDKCard.tsx` and `SnapshotUpload.tsx`.
- Refactored icons in `claim-conditions-form` and `snapshot-upload.tsx`.
- Adjusted layout and styling in various components for consistency.

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

<!-- end pr-codex -->
2024-10-03 23:43:05 +00:00
arcoraven b2276e9b9f chore: move gas and timeout details to Engine FAQ (#4914)
<!-- start pr-codex -->

## PR-Codex overview
This PR focuses on updating the documentation for transaction settings in the `Engine` feature. It clarifies the structure and usage of `txOverrides` for sending native currency and overriding gas settings, including examples and warnings about transaction timeouts.

### Detailed summary
- Changed keys in `txOverrides` from unquoted to quoted strings in the JSON structure.
- Added a section on sending native currency with examples.
- Introduced a section on overriding gas settings with examples.
- Included a warning about setting a timeout for transactions.
- Added a section on specifying transaction timeouts with examples.

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

<!-- end pr-codex -->
2024-10-03 21:56:26 +00:00
MananTank b31ab5a371 Move /connect/account-abstraction to app router (#4896)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on implementing Account Abstraction features in the dashboard, enhancing the user interface, and integrating API key management for smart wallets.

### Detailed summary
- Removed `account-abstraction.tsx`.
- Added `getAASupportedAPIKeys` function to filter API keys for bundler services.
- Created `AccountAbstractionAPIKeysMenu` to manage API key selection.
- Implemented `PageHeader` for account abstraction context.
- Developed `OpChainAlert` to notify users about gas credits.
- Updated `Layout` with SEO metadata.
- Enhanced `SmartWallets` component to utilize a default tab.
- Created `Page` component to handle authentication and API key redirection.
- Added client ID specific page with account and API key validation.

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

<!-- end pr-codex -->
2024-10-03 20:49:27 +00:00
MananTank b82011e764 Move /connect/in-app-wallets to app router (#4894)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the `in-app-wallets` feature by adding new components and functionalities, including API key management and layout improvements.

### Detailed summary
- Added `getInAppWalletSupportedAPIKeys` function to fetch and filter API keys.
- Created `Layout` component with footer sections.
- Implemented `InAppWalletsAPIKeysMenu` for API key selection.
- Added `PageHeader` with description and link.
- Enhanced `Page` component to handle redirects and display API keys.
- Updated `EmbeddedWallets` component to use `defaultTab` prop instead of search params.

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

<!-- end pr-codex -->
2024-10-03 20:49:26 +00:00
kien-ngo a7e285a90d [Dashboard] Remove react-icons (5) (#4904)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

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

### Detailed summary
- Replaced `FiEye` with `EyeIcon` in `reveal-button.tsx`.
- Replaced `FiCopy` with `CopyIcon` in `LatestEvents.tsx`.
- Replaced `BsLightningCharge` with `ZapIcon` in `GeneralCta.tsx`.
- Replaced `FiCheck` with `CheckIcon` in `address-input.tsx`.
- Replaced `FaXTwitter` with `XIcon` and `SiOpensea` with `OpenseaIcon` in `OpCreditsGrantedModal.tsx`.
- Replaced `FiX` with `XIcon` and caret icons with `ChevronDownIcon`, `ChevronUpIcon` in `phase.tsx`.
- Replaced `FiPlay` with `PlayIcon` and `FaCircleInfo` with `InfoIcon` in `interactive-abi-function.tsx`.
- Replaced `FiInfo` with `InfoIcon` in `list-form.tsx`.
- Replaced navigation icons in `accounts-table.tsx` with `Chevron` icons from `lucide-react`.
- Added `OpenseaIcon` component in `OpenseaIcon.tsx`.

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

<!-- end pr-codex -->
2024-10-03 20:29:57 +00:00
MananTank 615dd1e6a6 Move /connect/analytics to app router (#4893)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the `Analytics` section of the dashboard by introducing a new `AnalyticsPageAPIKeysMenu`, updating the `ApiKeysMenu` component to use a more generic type, and improving the handling of API keys for better user experience.

### Detailed summary
- Removed `DashboardConnectAnalytics` from constants.
- Added `AnalyticsPageAPIKeysMenu` to manage API keys.
- Updated `ApiKeysMenu` to use a generic type for `apiKeys`.
- Modified selection logic in `ApiKeysMenu` to use `key` instead of `id`.
- Enhanced page redirection logic based on API keys availability.

> The following files were skipped due to too many changes: `apps/dashboard/tsconfig.tsbuildinfo`

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

<!-- end pr-codex -->
2024-10-03 20:22:47 +00:00
kien-ngo 7cd39f07b4 [Dashboard] Remove react-icons (4) (#4900)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on updating various components in the dashboard to replace certain icon imports with `lucide-react` icons, enhancing the UI consistency and modernizing the iconography used throughout the application.

### Detailed summary
- Replaced `BiTransferAlt` with `ArrowLeftRightIcon` in `TransactionButton`.
- Replaced `IoChevronBack` with `ChevronLeftIcon` in `TokenIdPage`.
- Replaced `RiCheckboxMultipleBlankLine` with `FileStackIcon` in `BatchLazyMintButton`.
- Replaced `VscDebugDisconnect` with `UnplugIcon` in `MismatchButton`.
- Replaced `FiCopy` with `CopyIcon` in `PermissionsTable`.
- Replaced `FiCheckCircle` and `FiXCircle` with `CircleCheckIcon` and `CircleXIcon` in `VerifyContractModal`.
- Replaced `FiUpload` with `UploadIcon` in `AirdropTab`.
- Updated various components to use `lucide-react` icons instead of `react-icons`.
- Improved layout and styling in `AirdropUpload` and `AirdropTable` components.

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

<!-- end pr-codex -->
2024-10-03 17:18:37 +00:00
kien-ngo 4b80b250b4 [Dashboard] Vote contract proposal drawer (#4899)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on refactoring the proposal creation UI components, replacing a `Drawer` with a `Sheet` for better user experience, and enhancing the proposal submission process with improved form handling and error management.

### Detailed summary
- Deleted `proposal-form.tsx`.
- Modified `metadata-header.tsx` className for better styling.
- Replaced `Flex` components with `div` for layout in `page.tsx`.
- Refactored `ProposalButton` to use `Sheet` instead of `Drawer`.
- Added form handling with `react-hook-form` in `ProposalButton`.
- Implemented error handling and user feedback with `toast` in the proposal submission process.

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

<!-- end pr-codex -->
2024-10-03 17:11:43 +00:00
MananTank 47f53879f8 Fix APIKey fetch in project layout (#4912)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces a new function, `getAPIKeyForProjectId`, to streamline the retrieval of API keys for projects. It replaces the previous usage of `getAPIKey` across multiple components, ensuring consistent handling of project IDs.

### Detailed summary
- Added `getAPIKeyForProjectId` function in `getAPIKeys.ts`.
- Replaced calls to `getAPIKey` with `getAPIKeyForProjectId` in:
  - `apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/page.tsx`
  - `apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/pay/page.tsx`
  - `apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/account-abstraction/page.tsx`
  - `apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/in-app-wallets/page.tsx`
  - `apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/account-abstraction/page.tsx`

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

<!-- end pr-codex -->
2024-10-03 16:42:08 +00:00
kien-ngo 6ff85d32c5 [Dashboard] Remove react-icons (3) (#4898)
## 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 multiple components, enhancing consistency and potentially improving performance.

### Detailed summary
- Replaced `FiX` with `XIcon` in `SmartWalletsBillingAlert`.
- Replaced `CircleAlert` with `CircleAlertIcon` in `AirdropTable`.
- Replaced `FiUpload` with `UploadIcon` in `IconUpload`.
- Updated `HackathonEarnFooter` to use `SearchIcon`.
- Replaced `BsLightningCharge` with `ZapIcon` in `Community`.
- Replaced `IoAlertCircleOutline` with `CircleAlertIcon` in `AirdropTable`.
- Updated pagination icons in `AirdropTable` to use `Chevron` icons from `lucide-react`.

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

<!-- end pr-codex -->
2024-10-03 16:07:58 +00:00
MananTank 37d62e2b06 Fix Engine /configuration page textarea populated with data (#4908)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on updating the `useForm` hook in two components, changing the prop from `defaultValues` to `values`. This change ensures that the form initializes with the provided values directly.

### Detailed summary
- In `cors.tsx`, changed `defaultValues` to `values` in the `useForm` hook.
- In `ip-allowlist.tsx`, changed `defaultValues` to `values` in the `useForm` hook.

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

<!-- end pr-codex -->
2024-10-03 15:55:30 +00:00
kien-ngo 422a725092 [Dashboard] Fix airdrop erc20 scroll issue (#4909)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on modifying the `className` of the `SheetContent` component in the `airdrop-button.tsx` file to improve its styling by adding an `overflow-y-auto` class, allowing for vertical scrolling if the content exceeds the available space.

### Detailed summary
- Updated the `className` of the `SheetContent` component:
  - Added `overflow-y-auto` to enable vertical scrolling.

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

<!-- end pr-codex -->
2024-10-03 14:39:36 +00:00
kien-ngo d1d3fdc732 [Dashboard] Remove react-icons (2) (#4885)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR primarily focuses on replacing icon imports from `react-icons` with corresponding icons from `lucide-react` across multiple components, enhancing consistency and potentially reducing bundle size.

### Detailed summary
- Replaced `FiCopy` with `CopyIcon` in `AddressCopyButton`.
- Replaced `MdOutlineAccountBalanceWallet` with `WalletIcon` in `TransactionSimulator`.
- Replaced `FiMoon` and `FiSun` with `MoonIcon` and `SunIcon` in `ColorModeToggle`.
- Replaced `FiTrash` with `Trash2Icon` in `SettingsMetadata`.
- Added `PlusIcon` and `Trash2Icon` in `metadata.tsx`.
- Replaced `FiPlus` with `PlusIcon` in `permissions-editor.tsx`.
- Replaced `BsFillLightningChargeFill` with `ZapIcon` in `contact-us.tsx`.
- Replaced `BsFillLightningChargeFill` with `ZapIcon` in `contracts.tsx`.
- Replaced `IoChevronBack` with `ChevronFirstIcon` in `ContractPublishForm`.
- Replaced `IoChevronBack` with `ChevronLeftIcon` in `BatchLazyMint`.
- Replaced various `Md` icons with `Chevron` icons in `BatchTable`.
- Replaced `Chevron` icons in `airdrop-upload-erc20.tsx`.
- Replaced `FiExternalLink` with `MoveUpRightIcon` in `pricing.tsx`.
- Replaced `IoIosInformationCircleOutline` with `InfoIcon` in `pricing.tsx`.
- Replaced `IoCheckmarkCircle` with `CircleCheckIcon` in `pricing.tsx`.
- Replaced `AiOutlineDollarCircle` with `CircleDollarSignIcon` in `pricing.tsx`.
- Replaced `FiArrowRight` with `MoveRightIcon` in `marketplace-table.tsx`.

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

<!-- end pr-codex -->
2024-10-03 12:29:57 +00:00
kien-ngo a453d96aed [SDK] Unstoppable Domains resolvers (#4905)
<!-- start pr-codex -->

## PR-Codex overview
This PR focuses on adding support for Unstoppable Domains within the `thirdweb` SDK, including new resolvers for names and addresses, and enhancing functionality through tests and constants.

### Detailed summary
- Added `UD_POLYGON_MAINNET` constant.
- Introduced functions: `resolveName`, `resolveAddress`, `reverseNameOf`, `getMany`, and `namehash`.
- Implemented tests for `resolveName` and `resolveAddress`.
- Added exports for new types and functions in `unstoppable-domains.ts`.

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

<!-- end pr-codex -->
2024-10-03 09:57:36 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
bfe9753be6 Version Packages (#4881)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-03 14:33:47 +13:00
Joaquim VergesandGitHub eeb993df75 feat: optimize zksync contract deployment and bytecode handling (#4902) 2024-10-03 14:09:00 +13:00
ElasticBottle 367a270bba fix: update timeline for GDPR compliance (#4897)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR updates the compliance information regarding GDPR and CCPA in the `page.mdx` file, providing more detailed and accurate descriptions of the data handling practices.

### Detailed summary
- Updated the compliance statement for GDPR and CCPA.
- Changed the text from a general statement about in-app wallets to specify that `thirdweb` complies with GDPR and CCPA frameworks.
- Clarified the timeframe for data deletion requests (30 days for GDPR and 45 for CCPA).

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

<!-- end pr-codex -->
2024-10-03 01:02:51 +00:00
kumaryash90 e91581aec6 Update chain stack type check (#4901)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces a new property `stackType` across various components and utilities, enhancing the handling of blockchain network configurations and metadata.

### Detailed summary
- Added `stackType` property in `types.ts` for chains.
- Updated `utils.ts` to include `stackType` from data.
- Included `stackType` in `embed-setup.tsx` and `ConfigureNetworkForm.tsx`.
- Modified the `isZkSyncChain` function to use `getChainMetadata` for `stackType` validation.
- Removed the obsolete `getChainStack` function.

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

<!-- end pr-codex -->
2024-10-03 00:17:49 +00:00
ElasticBottle 985c4b0804 fix: add missing partner id for ecosystem wallet (#4886)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on fixing the issue of missing `partnerId` when creating an ecosystem wallet in the `thirdweb` package.

### Detailed summary
- Updated `partnerId` in `packages/thirdweb/src/wallets/in-app/web/ecosystem.ts` to use `ecosystem.partnerId`.
- Updated `partnerId` in `packages/thirdweb/src/wallets/in-app/native/ecosystem.ts` to use `createOptions?.partnerId`.

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

<!-- end pr-codex -->
2024-10-02 22:38:54 +00:00
MananTank 9fb5401a93 Add Coupon Card in Billing Page (#4895)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the `SettingsBillingPage` component by adding a `teamId` prop to manage billing settings for different teams. It also introduces a new `CouponCard` component that allows users to apply coupon codes with relevant feedback.

### Detailed summary
- Updated `Page` component to pass `teamId` to `SettingsBillingPage`.
- Modified `SettingsBillingPage` to accept `teamId` as a prop.
- Adjusted `Billing` component to use `teamId` in its rendering.
- Introduced `CouponCard` component for applying coupon codes.
- Implemented logic in `CouponCard` to handle coupon submissions and display feedback based on response status.
- Updated `Billing` component to include `CouponCard`.

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

<!-- end pr-codex -->
2024-10-02 21:48:14 +00:00
Joaquim VergesandGitHub e54867550e feat: switch to v2 bundler for all user operations (#4884) 2024-10-03 10:12:43 +13:00
MananTank 514647cb53 Add Billing alerts on /connect layout in app router (#4892)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the `BillingAlerts` component by allowing it to accept a `className` prop for better styling flexibility. It also updates the usage of `BillingAlerts` in various components to apply specific padding classes.

### Detailed summary
- Modified `BillingAlerts` to accept an optional `className` prop.
- Updated the `BillingAlerts` usage in `apps/dashboard/src/components/layout/app-shell/index.tsx` to include `className="py-6"`.
- Updated `BillingAlerts` usage in `apps/dashboard/src/app/(dashboard)/dashboard/connect/layout.tsx` to include `className="pb-6"`.
- Adjusted the rendering of `BillingAlertsUI` to apply the `className` prop.

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

<!-- end pr-codex -->
2024-10-02 19:56:29 +00:00
MananTank eb8638e0c2 Spacing fixes on OnboardingGeneral component (#4891)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on refactoring the layout of the `OnboardingGeneral` and `AccountForm` components by replacing `FocusLock` and `Flex` components with `div` elements, enhancing the structure and styling of the components.

### Detailed summary
- Replaced `<FocusLock>` with `<div>` in `OnboardingGeneral`.
- Changed `<Flex>` to `<div className="flex flex-col gap-4">` in `OnboardingGeneral`.
- Updated `<Flex>` to `<div className={cn("flex w-full", ...)}> ` in `AccountForm`.
- Modified closing tags from `</Flex>` to `</div>` in both components.

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

<!-- end pr-codex -->
2024-10-02 18:45:33 +00:00
MananTank a6f85ac949 Replace react-otp-input with shadcn input-otp (#4889)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces a new OTP input component using the `input-otp` library, along with related animations and configuration updates. It replaces the existing `react-otp-input` dependency and enhances the onboarding email confirmation process.

### Detailed summary
- Added `input-otp` dependency to `package.json`.
- Removed `react-otp-input` from `package.json`.
- Updated `tailwind.config.js` to include `caret-blink` animation.
- Created new components: `InputOTP`, `InputOTPGroup`, `InputOTPSlot`, `InputOTPSeparator`.
- Refactored `ConfirmEmail.tsx` to utilize the new OTP input components.
- Improved styling and functionality for OTP input slots.

> 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-02 17:57:34 +00:00
MananTank 726bbde9ca Add privacyPolicyUrl and termsOfServiceUrl on ConnectEmbed in login page (#4890)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the `login` component by adding links for the privacy policy and terms of service.

### Detailed summary
- Added `privacyPolicyUrl` prop with the value `"/privacy"` to the component.
- Added `termsOfServiceUrl` prop with the value `"/tos"` to the component.

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

<!-- end pr-codex -->
2024-10-02 17:46:44 +00:00
MananTank 025c581be6 api server url env cleanup (#4887)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces a new constant, `API_SERVER_URL`, to centralize the API server URL configuration. It replaces instances of `process.env.NEXT_PUBLIC_THIRDWEB_API_HOST` throughout the codebase, enhancing maintainability and readability.

### Detailed summary
- Added `API_SERVER_URL` in `env.ts`.
- Replaced `process.env.NEXT_PUBLIC_THIRDWEB_API_HOST` with `API_SERVER_URL` in multiple files:
  - `getAccount.ts`
  - `fetchEcosystemList.ts`
  - `fetchEcosystem.ts`
  - `team-members.ts`
  - `get-auth-token/route.ts`
  - `getAPIKeys.ts`
  - `ensure-login/route.ts`
  - `server-proxy/api/[...paths].tsx`
  - `team.ts`
  - `projects.ts`
  - `create-ticket.action.ts`
  - `auth-actions.ts`
  - `utils.ts`
- Updated fetch requests to use `API_SERVER_URL` for consistent API endpoint access.

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

<!-- end pr-codex -->
2024-10-02 17:39:21 +00:00
arcoraven 522968a505 chore: Update version flow updates deployment (#4852)
## Problem solved

Changes the "update Engine version" flow to query the infra backend to perform the version upgrade.

Previously this would ping Slack for a thirdweb staff to update.

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on improving the code quality and user interface across various components in the dashboard. It includes updates to placeholders, text content, and the handling of engine updates.

### Detailed summary
- Updated `placeholder` in `ip-allowlist.tsx` to use curly braces.
- Added periods to sentences in `EngineImportPage.tsx` and `CreateEnginePage.tsx`.
- Simplified conditional rendering in `engine-instances-table.tsx`.
- Changed `cloudDeployedAt` to `deploymentId` in `useEngine.ts`.
- Renamed `useEngineUpdateVersion` to `useEngineUpdateServerVersion`.
- Updated fetch method to `PUT` for engine updates.
- Changed variable names for clarity in `EngineVersionBadge.tsx`.
- Updated props in `UpdateVersionModal` to use `latestVersion`.
- Adjusted toast messages for better user feedback during engine updates.

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

<!-- end pr-codex -->
2024-10-02 07:09:16 +00:00
joaquim-verges 454f063f98 refactor: optimize zksync chain detection and add Creator Testnet test (#4883)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on refactoring code related to the handling of contract metadata, specifically around bytecode fetching and the integration of `zksync` support. It enhances the clarity and functionality of contract deployment processes.

### Detailed summary
- Removed checks for `compilerType` in multiple files.
- Simplified bytecode fetching by introducing `fetchBytecodeFromCompilerMetadata`.
- Updated contract metadata handling in `fetchDeployMetadata`.
- Adjusted UI components to reflect new metadata structure.
- Added a test for sending transactions on the Creator Testnet.

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

<!-- end pr-codex -->
2024-10-02 03:40:38 +00:00
MananTank 78cbc412ce Migrate Billing related components to tailwind/shadcn - Part 1 (#4879)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR primarily refactors the onboarding and billing components, improving the UI structure and enhancing the modal functionalities. It replaces the `OnboardingTitle` with `TitleAndDescription`, streamlining the code and updating various components for better usability and consistency.

### Detailed summary
- Replaced `<OnboardingTitle>` with `<TitleAndDescription>` in several components.
- Updated `OnboardingModal` to remove redundant `onClose` props.
- Refactored billing alert components to use new UI elements.
- Enhanced the layout of forms and alerts for better UX.
- Improved state management for modal visibility.
- Added new utility functions for account and billing data stubs.
- Updated import statements for consistency and clarity.

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

<!-- end pr-codex -->
2024-10-02 00:07:14 +00:00
kien-ngo 79c50cb311 [Dashboard] Remove react-icons (1) (#4882)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR primarily focuses on replacing various icon components with `PlusIcon` and `UploadIcon` from the `lucide-react` library, enhancing the UI consistency across the application.

### Detailed summary
- Replaced `Upload` component with `UploadIcon` in `airdrop-upload-erc20.tsx` and `upload-step.tsx`.
- Updated `FiPlus` icons to `PlusIcon` in multiple components, including `external-links-fieldset.tsx`, `NFTMintButton.tsx`, and more.
- Removed unused `Icon` imports from several files.
- Adjusted icon classes for consistent styling.

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

<!-- end pr-codex -->
2024-10-01 23:46:56 +00:00
kien-ngo 764ee8ca47 [Dashboard] Remove some chakra icons, adjust IpfsUploadButton (#4880)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR primarily focuses on UI enhancements and component updates across various files in the dashboard application, including adjustments to icons, button properties, and tooltip components.

### Detailed summary
- Updated `InputRightElement` width from `145px` to `160px`.
- Changed `Tooltip` to `ToolTipLabel` in `OpenSeaPropertyBadge`.
- Modified `leftIcon` rendering in `ConnectPlaygroundButton` and `CodeOptionButton` to use class-based icons.
- Replaced `FiUpload` with `UploadIcon` in `IpfsUploadButton`.
- Swapped `BsFillLightningChargeFill` with `ZapIcon` in `ProductButton`.

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

<!-- end pr-codex -->
2024-10-01 23:46:54 +00:00
jnsdls 783d84467d update dependencies (#4874)
<!-- start pr-codex -->

## PR-Codex overview
This PR focuses on updating various dependencies across multiple packages, ensuring compatibility and incorporating improvements.

### Detailed summary
- Updated `turbo` from `2.1.2` to `2.1.3`.
- Updated `@types/react` from `^18.3.8` to `^18.3.10`.
- Updated `tailwindcss` from `3.4.12` to `3.4.13`.
- Updated `@walletconnect/react-native-compat` from `2.13.2` to `2.16.3`.
- Updated `@coinbase/wallet-sdk` from `4.0.4` to `4.1.0`.
- Updated `viem` from `2.21.12` to `2.21.16`.
- Various other dependency updates across multiple packages.

> 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-01 22:10:01 +00:00
jnsdls 687a733d4a Add deprecation warnings to dashboard folders (#4878)
### TL;DR

Added warning messages to deprecated folders in the dashboard to prevent further additions.

### What changed?

Added `DO_NOT_ADD_THINGS_HERE.md` files to several deprecated folders within the dashboard's `src` directory. These folders include:

- @3rdweb-sdk
- classes
- contract-ui
- core-ui
- og-lib
- pages
- tw-components

Each file contains a warning message stating that the folder is deprecated and advising developers not to add new content to these locations.

### How to test?

1. Navigate to each of the mentioned folders in the dashboard's `src` directory.
2. Verify that the `DO_NOT_ADD_THINGS_HERE.md` file exists in each folder.
3. Open the files and confirm they contain the correct warning message.

### Why make this change?

This change aims to prevent developers from adding new content to deprecated parts of the dashboard. By placing clear warning messages in these folders, we reduce the risk of introducing new code or features in areas that are scheduled for removal. This helps maintain code quality, reduces technical debt, and supports the ongoing efforts to modernize and streamline the dashboard's structure.
2024-10-01 21:32:00 +00:00
kien-ngo 96daa2654c [SDK] Update docs for claimTo extensions (#4849)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR enhances the documentation for the `claimTo` function across the `ERC1155`, `ERC20`, and `ERC721` extensions by adding usage examples for drops with allowlists, emphasizing the need to specify the claimer address.

### Detailed summary
- Added a "### Basic usage" section to the documentation for `claimTo` in all three extensions.
- Introduced a "### For Drops with allowlists" section explaining the need for the `from` parameter.
- Provided code examples for using `claimTo` with allowlists in `ERC1155`, `ERC20`, and `ERC721`.

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

<!-- end pr-codex -->
2024-10-01 21:08:24 +00:00
kien-ngo a2ce5f56ab [Dashboard] Remove <Code /> component (ez mode) (#4787)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing code readability by replacing instances of the `Code` component from Chakra UI with a new `InlineCode` component, which provides a consistent styling for inline code snippets across various files.

### Detailed summary
- Added `InlineCode` component in `inline-code.tsx`.
- Replaced `Code` with `InlineCode` in multiple components for improved consistency:
  - `ChainValidation`
  - `EngineCorsConfig`
  - `EngineIpAllowlistConfig`
  - `InteractiveAbiFunction`
  - `EngineAccessTokens`
  - `SnapshotUpload`
  - `UploadStep`

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

<!-- end pr-codex -->
2024-10-01 21:03:53 +00:00
kumaryash90 6beec7a35e Check zksync stack (#4869)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on updating the `isZkSyncChain` function to be asynchronous and modifying various parts of the codebase to await its result. This change enhances the handling of chain identification, particularly for zkSync-related operations.

### Detailed summary
- Changed `isZkSyncChain` to an async function.
- Updated calls to `isZkSyncChain` to use `await` in several files.
- Modified the logic in `isZkSyncChain` to include additional checks for specific chain IDs.
- Introduced a new async function `getChainStack` for fetching chain stack information.

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

<!-- end pr-codex -->
2024-10-01 20:12:35 +00:00
31f371d065 Superposition Mainnnet Custom Chain Page (#4875)
Co-authored-by: Jonas Daniels <[email protected]>
2024-10-01 12:45:00 -07:00
MananTank fd8674a8a4 Single Header component for App and Pages router (#4877)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on refactoring the dashboard components, enhancing the UI elements, and improving the overall structure of the codebase. It includes updates to navigation, styling, and the introduction of new components for better functionality.

### Detailed summary
- Deleted unused files: `nav-link.client.tsx`, `headerLinks.ts`, `MobileBurgerMenu.tsx`.
- Updated `cmd-k-search` button styling and icon size.
- Changed import paths in `layout.tsx`.
- Added `DashboardHeaderTabs` component to manage navigation.
- Refactored `DashboardHeader` to streamline layout and include new links.
- Updated `ColorModeToggle` and `CreditsButton` for better UI interaction.
- Enhanced `CreditsItem` component layout and functionality.
- Replaced `TrackedLinkButton` with `NavLink` in `UpgradeButton`.

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

<!-- end pr-codex -->
2024-10-01 19:33:06 +00:00
0xFirekeeper d3b0dc6646 [Portal] Fix Unity link (#4876)
<!-- start pr-codex -->

## PR-Codex overview
This PR updates the links in the `page.mdx` file for the Unity SDK to reflect the correct versioning in the URLs.

### Detailed summary
- Updated the link in the text from `/unity/getting-started` to `/unity/v5/getting-started`.
- Changed the `href` attribute of the `ArticleIconCard` component from `/unity/getting-started` to `/unity/v5/getting-started`.

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

<!-- end pr-codex -->
2024-10-01 19:29:36 +00:00
kien-ngo 98c5fd0b79 [SDK} Skip pack test (#4873)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on updating the `createNewPack` test in the `createNewPack.test.ts` file. It enhances the test by ensuring the correct creation and opening of a Pack while managing ERC20 and ERC721 tokens, including minting, approval, and balance checks.

### Detailed summary
- Added a `describe.skip` for `createNewPack` to temporarily skip the test.
- Reformatted the test to ensure proper execution flow.
- Included minting and approval for ERC20 and ERC721 tokens.
- Added assertions to verify balances and pack content after creation.
- Ensured correct metadata checks for the created Pack.

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

<!-- end pr-codex -->
2024-10-01 00:57:50 +00:00
0xFirekeeper 2f11259ccd [Portal] Link new Telegram Unity Template (#4872)
<!-- start pr-codex -->

## PR-Codex overview
This PR updates the `page.mdx` file to modify existing `ArticleCard` entries and add new ones. It enhances the descriptions and removes a duplicate `ArticleCard` for `Pioneer`.

### Detailed summary
- Updated the `description` for the `Take Flight!` and `Blockventure` `ArticleCard` entries.
- Added two new `ArticleCard` entries for `Telegram Mini-App` and `Pioneer`.
- Removed the duplicate `ArticleCard` for `Pioneer`.

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

<!-- end pr-codex -->
2024-10-01 00:47:16 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
97c09003dc Version Packages (#4842)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-01 13:37:54 +13:00
Edward SunandGitHub 5d0505c43c Add purchaseData to transfer transactions (#4871) 2024-10-01 09:14:38 +09:00
Jonas DanielsandGitHub e552fda9e5 fix auth token (#4870) 2024-09-30 16:58:35 -07:00
kien-ngo cddeda4280 [Dashboard] Remove <Stack/> (5) (#4844)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on refactoring the usage of the `Stack` component from `@chakra-ui/react` to standard HTML elements with Flexbox classes for layout consistency and performance improvements across various components in the dashboard.

### Detailed summary
- Removed `Stack` component and replaced it with `div` elements using Flexbox classes in multiple files.
- Updated `as` prop for `FormControl` elements to use `className` for styling.
- Adjusted various components to improve layout and spacing using Tailwind CSS classes.
- Added `StackProps` to `SelectOptionProps` interface, making it more flexible.
- Ensured consistency in component structure and styling throughout the dashboard.

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

<!-- end pr-codex -->
2024-09-30 23:27:38 +00:00
MananTank cb72f67c92 Fix Contract Type shown in Contracts Table, Fix PublishedBy not showing latest version (#4854)
Fixes DASH-274

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on improving the handling of published contracts in the dashboard by reversing and sorting the list of contracts based on the publisher, prioritizing those from `THIRDWEB_DEPLOYER_ADDRESS`.

### Detailed summary
- In `published-by.tsx`, the list of published contracts is reversed.
- In `cells.tsx`, a new sorted array `publishedContractsFromDeploySorted` is created from the original contracts.
- The sorting prioritizes contracts published by `THIRDWEB_DEPLOYER_ADDRESS`.
- The display name retrieval uses the sorted list instead of the original query.

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

<!-- end pr-codex -->
2024-09-30 23:15:51 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
222964dcbb Bump eslint-plugin-storybook from 0.8.0 to 0.9.0 (#4866)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-30 16:14:49 -07:00
MananTank ec37c74199 Fix InteractiveAbiFunction component not rendered in published contract page explorer (#4868)
FIXES: DASH-273

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on improving type safety and handling of published contracts in the dashboard application. It modifies type definitions and enhances the rendering logic for contract functions.

### Detailed summary
- Changed `snippet` type from `Record<CodeEnvironment, any>` to `Partial<Record<CodeEnvironment, any>>` in `formatSnippet`.
- Added a check for `publishedContract` in `layout.tsx` to ensure it exists before proceeding.
- Updated the `ContractFunction` component to enforce required `fn` and optional `contract` props.
- Enhanced rendering logic in `ContractFunctionInner` to display function usage and code snippets based on contract availability.

> The following files were skipped due to too many changes: `apps/dashboard/tsconfig.tsbuildinfo`

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

<!-- end pr-codex -->
2024-09-30 22:57:39 +00:00
kien-ngo 2ac1e86b8f [Dashboard] Remove FTUX (#4851)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on removing the `FTUX` component and related files from the project, simplifying the `Dashboard` component by eliminating conditional rendering based on wallet connection status.

### Detailed summary
- Deleted `FTUX.tsx` and associated files: `shared.ts`, `slides.tsx`, `animations.ts`, `Graphics.tsx`, `ContentContainer.tsx`, and `GraphicContainer.tsx`.
- Removed logic for `connectionStatus` and `showFTUX` from `Dashboard`.
- Streamlined rendering in `Dashboard` by directly displaying `OnboardingSteps`.

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

<!-- end pr-codex -->
2024-09-30 22:49:45 +00:00
kien-ngo bdc5964054 [Dashboard] Remove ListItem (2) (#4850)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR primarily focuses on the removal of several files related to the `contract-ui` and `core-ui` components, alongside updates to various components and hooks to include `txChainID` for improved transaction handling.

### Detailed summary
- Deleted multiple files in `contract-ui` and `core-ui`.
- Added `txChainID` prop to `TransactionButton` across various components for transaction context.
- Updated `useWalletNFTs` to accept an object parameter for better clarity.
- Enhanced error handling in API functions.
- Refactored several components to improve code readability and maintainability.

> The following files were skipped due to too many changes: `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/claim-conditions/page.tsx`, `apps/dashboard/src/contract-ui/tabs/claim-conditions/components/claim-conditions.tsx`, `apps/dashboard/src/contract-ui/tabs/permissions/page.tsx`, `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/page.tsx`, `apps/dashboard/src/components/app-layouts/app.tsx`, `apps/dashboard/src/contract-ui/tabs/overview/components/NFTCards.tsx`, `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/detectedFeatures/erc4337.ts`, `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/explorer/page.tsx`, `apps/dashboard/src/contract-ui/tabs/tokens/page.tsx`, `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/code/page.tsx`, `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/page.tsx`, `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/page.tsx`, `apps/dashboard/src/contract-ui/tabs/shared-components/cancel-tab.tsx`, `apps/dashboard/src/pages/hackathon/readyplayer3.tsx`, `apps/dashboard/src/contract-ui/tabs/overview/components/PermissionsTable.tsx`, `apps/dashboard/src/contract-ui/tabs/overview/components/BuildYourApp.tsx`, `apps/dashboard/src/stores/chainStores.tsx`, `apps/dashboard/src/contract-ui/tabs/account/page.tsx`, `apps/dashboard/src/contract-ui/tabs/overview/components/NFTDetails.tsx`, `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/settings/page.tsx`, `apps/dashboard/src/contract-ui/tabs/accounts/components/accounts-table.tsx`, `apps/dashboard/src/contract-ui/tabs/code/components/code-overview.tsx`, `apps/dashboard/src/stores/SyncStoreToStorage.tsx`, `apps/dashboard/src/contract-ui/tabs/overview/components/ContractChecklist.tsx`, `apps/dashboard/src/contract-ui/tabs/nfts/components/table.tsx`, `apps/dashboard/src/pages/contact-us.tsx`, `apps/dashboard/src/contract-ui/tabs/embed/components/embed-setup.tsx`, `apps/dashboard/src/components/contract-functions/contract-function.tsx`, `apps/dashboard/src/contract-ui/tabs/events/components/events-feed.tsx`, `apps/dashboard/src/contract-ui/tabs/nfts/components/airdrop-upload.tsx`, `apps/dashboard/src/@/components/blocks/Sidebar.tsx`, `apps/dashboard/src/components/shared/DeprecatedAlert.tsx`, `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractFromParams.ts`, `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/ConfigureCustomChain.tsx`, `apps/dashboard/src/contract-ui/tabs/overview/components/Analytics.tsx`, `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/detectedFeatures/claimConditions.ts`, `apps/dashboard/src/contract-ui/tabs/tokens/components/airdrop-upload-erc20.tsx`, `apps/dashboard/src/contract-ui/tabs/settings/page.tsx`, `apps/dashboard/src/contract-ui/tabs/nfts/components/token-id.tsx`, `apps/dashboard/src/pages/hackathon/consumer-crypto.tsx`, `apps/dashboard/src/@/components/blocks/MobileSidebar.tsx`, `apps/dashboard/src/components/custom-contract/contract-header/contract-metadata.tsx`, `apps/dashboard/src/contract-ui/tabs/explorer/page.tsx`, `apps/dashboard/src/contract-ui/tabs/overview/components/LatestEvents.tsx`, `apps/dashboard/src/contract-ui/tabs/overview/page.tsx`, `apps/dashboard/src/contract-ui/tabs/listings/components/list-form.tsx`, `apps/dashboard/src/components/layout/app-shell/index.tsx`, `apps/dashboard/src/@3rdweb-sdk/react/hooks/useDashboardContractMetadata.tsx`, `apps/dashboard/src/og-lib/url-utils.ts`, `apps/dashboard/src/@3rdweb-sdk/react/hooks/useActiveChainId.tsx`, `apps/dashboard/src/@/components/blocks/charts/area-chart.tsx`, `apps/dashboard/src/contract-ui/components/primary-dashboard-button.tsx`, `apps/dashboard/src/pages/hackathon/earn.tsx`, `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractPageSidebarLinks.ts`, `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractPageMetadata.ts`, `apps/dashboard/src/contract-ui/tabs/nfts/page.tsx`, `apps/dashboard/src/core-ui/batch-upload/upload-step.tsx`, `apps/dashboard/src/contract-ui/tabs/overview/components/MarketplaceDetails.tsx`, `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/layout.tsx`, `apps/dashboard/src/components/contract-components/hooks.ts`, `apps/dashboard/src/pages/api/og/contract.tsx`, `apps/dashboard/src/components/configure-networks/ConfigureNetworkForm.tsx`, `apps/dashboard/src/components/custom-contract/contract-header/metadata-header.tsx`, `apps/dashboard/src/@3rdweb-sdk/react/hooks/useApi.ts`, `apps/dashboard/src/components/buttons/MismatchButton.tsx`, `apps/dashboard/src/@3rdweb-sdk/react/hooks/useEngine.ts`

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

<!-- end pr-codex -->
2024-09-30 22:49:44 +00:00
kien-ngoandManan Tank 5fc07f7111 [Dashboard] Remove ListItem (1) and fix some UI issues from the aspect-ratio PR (#4846)
Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

This PR focuses on replacing `List` and `ListItem` components with HTML `<ul>` and `<li>` elements across multiple files to improve semantic HTML structure and potentially enhance accessibility.

- Removed `List` and `ListItem` components in favor of `<ul>` and `<li>` elements in various components.
- Updated `label` in `CreateListingsForm` to use a `Card` with structured `<ul>` content.
- Adjusted lists in `Hackathon`, `HackathonEarn`, and `ContactUs` pages to use `<ul>` and `<li>`.
- Minor styling adjustments for improved layout and alignment.

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

<!-- end pr-codex -->
2024-10-01 03:59:35 +05:30
MananTank 80729e9748 Move contract pages to app router (#4820)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on code cleanup and refactoring, including the removal of deprecated files and the addition of `txChainID` props in various components for better transaction handling.

### Detailed summary
- Deleted multiple unused files in `apps/dashboard/src/contract-ui` and `apps/dashboard/src/core-ui`.
- Added `txChainID` prop to `TransactionButton` in various components for transaction context.
- Updated components to use direct imports and improved overall code structure.
- Enhanced error handling and metadata fetching for contracts.

> The following files were skipped due to too many changes: `apps/dashboard/src/contract-ui/tabs/permissions/page.tsx`, `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/page.tsx`, `apps/dashboard/src/components/app-layouts/app.tsx`, `apps/dashboard/src/contract-ui/tabs/overview/components/NFTCards.tsx`, `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/detectedFeatures/erc4337.ts`, `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/explorer/page.tsx`, `apps/dashboard/src/contract-ui/tabs/tokens/page.tsx`, `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/code/page.tsx`, `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/page.tsx`, `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/page.tsx`, `apps/dashboard/src/contract-ui/tabs/shared-components/cancel-tab.tsx`, `apps/dashboard/src/contract-ui/tabs/overview/components/PermissionsTable.tsx`, `apps/dashboard/src/contract-ui/tabs/overview/components/BuildYourApp.tsx`, `apps/dashboard/src/stores/chainStores.tsx`, `apps/dashboard/src/contract-ui/tabs/account/page.tsx`, `apps/dashboard/src/contract-ui/tabs/overview/components/NFTDetails.tsx`, `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/settings/page.tsx`, `apps/dashboard/src/contract-ui/tabs/accounts/components/accounts-table.tsx`, `apps/dashboard/src/components/contract-functions/contract-function.tsx`, `apps/dashboard/src/contract-ui/tabs/code/components/code-overview.tsx`, `apps/dashboard/src/stores/SyncStoreToStorage.tsx`, `apps/dashboard/src/contract-ui/tabs/overview/components/ContractChecklist.tsx`, `apps/dashboard/src/contract-ui/tabs/nfts/components/table.tsx`, `apps/dashboard/src/contract-ui/tabs/embed/components/embed-setup.tsx`, `apps/dashboard/src/contract-ui/tabs/listings/components/list-form.tsx`, `apps/dashboard/src/contract-ui/tabs/events/components/events-feed.tsx`, `apps/dashboard/src/@/components/blocks/Sidebar.tsx`, `apps/dashboard/src/components/shared/DeprecatedAlert.tsx`, `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractFromParams.ts`, `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/ConfigureCustomChain.tsx`, `apps/dashboard/src/contract-ui/tabs/overview/components/Analytics.tsx`, `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/detectedFeatures/claimConditions.ts`, `apps/dashboard/src/contract-ui/tabs/settings/page.tsx`, `apps/dashboard/src/contract-ui/tabs/nfts/components/token-id.tsx`, `apps/dashboard/src/@/components/blocks/MobileSidebar.tsx`, `apps/dashboard/src/components/custom-contract/contract-header/contract-metadata.tsx`, `apps/dashboard/src/contract-ui/tabs/explorer/page.tsx`, `apps/dashboard/src/contract-ui/tabs/overview/components/LatestEvents.tsx`, `apps/dashboard/src/contract-ui/tabs/overview/page.tsx`, `apps/dashboard/src/components/layout/app-shell/index.tsx`, `apps/dashboard/src/@3rdweb-sdk/react/hooks/useDashboardContractMetadata.tsx`, `apps/dashboard/src/og-lib/url-utils.ts`, `apps/dashboard/src/@3rdweb-sdk/react/hooks/useActiveChainId.tsx`, `apps/dashboard/src/@/components/blocks/charts/area-chart.tsx`, `apps/dashboard/src/contract-ui/components/primary-dashboard-button.tsx`, `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractPageSidebarLinks.ts`, `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractPageMetadata.ts`, `apps/dashboard/src/contract-ui/tabs/nfts/page.tsx`, `apps/dashboard/src/contract-ui/tabs/overview/components/MarketplaceDetails.tsx`, `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/layout.tsx`, `apps/dashboard/src/components/contract-components/hooks.ts`, `apps/dashboard/src/pages/api/og/contract.tsx`, `apps/dashboard/src/components/configure-networks/ConfigureNetworkForm.tsx`, `apps/dashboard/src/components/custom-contract/contract-header/metadata-header.tsx`, `apps/dashboard/src/@3rdweb-sdk/react/hooks/useApi.ts`, `apps/dashboard/src/components/buttons/MismatchButton.tsx`, `apps/dashboard/src/@3rdweb-sdk/react/hooks/useEngine.ts`

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

<!-- end pr-codex -->
2024-09-30 21:43:43 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
8832f87f4a Bump @storybook/addon-interactions from 8.3.2 to 8.3.4 (#4867)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-30 14:35:43 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
39a43903ad Bump @aws-sdk/client-lambda from 3.656.0 to 3.659.0 (#4861)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-30 14:33:46 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
6396729839 Bump @cloudflare/workers-types from 4.20240919.0 to 4.20240925.0 (#4862)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-30 14:32:17 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
30fd225538 Bump @walletconnect/sign-client from 2.16.2 to 2.16.3 (#4864)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-30 14:31:13 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
931bbd4952 Bump @storybook/react-vite from 8.3.2 to 8.3.4 (#4863)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-30 14:23:30 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
3202ce105c Bump @storybook/blocks from 8.3.2 to 8.3.4 (#4860)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-30 14:19:56 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
36aa3f0937 Bump @storybook/react from 8.3.2 to 8.3.4 (#4855)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-30 14:05:14 -07:00
MananTank ab43d9426a Fix Code tab not working in playground - revert shiki to 1.16 (#4853)
Fixes CNCT-1958
2024-09-30 18:52:16 +00:00
AmirandGitHub 29938abfe3 Update page.mdx (#4848)
Signed-off-by: Amir <[email protected]>
2024-09-29 21:40:27 -07:00
AmirandGitHub 5bb5a437cd Update page.mdx (#4847)
Signed-off-by: Amir <[email protected]>
2024-09-29 21:14:07 -07:00
kien-ngo 8b681729a1 [Dashboard] Remove <Stack /> (4) (#4843)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on refactoring the layout components in various files from using `Stack` to `div` elements with Flexbox classes for better styling and layout control.

### Detailed summary
- Replaced `<Stack>` components with `<div>` using Flexbox classes in multiple files.
- Updated form structures to use `<form>` tags directly instead of wrapping them in `<Stack>`.
- Adjusted spacing and alignment using Flexbox properties.

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

<!-- end pr-codex -->
2024-09-29 18:29:22 +00:00
kien-ngo 6c26012a71 [SDK] Update smart wallet test (#4845)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces a new `sleep` function in `sleep.ts` for delaying asynchronous operations and replaces existing inline sleep implementations across various files with this unified function.

### Detailed summary
- Added `sleep` function in `packages/thirdweb/src/utils/sleep.ts` for delaying async operations.
- Removed duplicate `sleep` functions from `packages/thirdweb/src/rpc/watchBlockNumber.ts` and `packages/thirdweb/src/wallets/in-app/web/utils/iFrameCommunication/IframeCommunicator.ts`.
- Updated calls to `sleep` in `packages/thirdweb/src/wallets/smart/smart-wallet-integration-v07.test.ts` and `packages/thirdweb/src/wallets/in-app/web/utils/iFrameCommunication/IframeCommunicator.ts` to use the new function.

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

<!-- end pr-codex -->
2024-09-28 23:11:39 +00:00
kien-ngo 90b5495efb [SDK] Add Pack extensions (#4579)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces new functionalities and enhancements for the `Pack` contract in the `thirdweb` project, including event definitions, deployment options, and methods for managing packs and rewards.

### Detailed summary
- Added `initialize` function to `Pack.json`.
- Exported new types and functions in `deploy-pack.ts`.
- Defined new events and functions in `IPackVRFDirect.json`.
- Created tests for deploying `Pack` contracts.
- Updated changelog with Pack extensions.
- Implemented various methods for managing packs, including `openPack`, `addPackContents`, and `claimRewards`.

> The following files were skipped due to too many changes: `packages/thirdweb/src/extensions/pack/createNewPack.test.ts`, `packages/thirdweb/src/extensions/prebuilts/__generated__/Pack/write/initialize.ts`, `packages/thirdweb/src/extensions/pack/__generated__/IPack/write/createPack.ts`, `packages/thirdweb/src/extensions/pack/createNewPack.ts`

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

<!-- end pr-codex -->
2024-09-28 12:46:54 +00:00
Kien NgoandGitHub 71575afef3 [SDK] Avoid out-of-fund in tests (#4840) 2024-09-28 20:59:40 +12:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
70adb57293 Version Packages (#4841)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-09-28 20:48:14 +12:00
Kien NgoandGitHub 96fa4102ba [SDK] Avoid IPFS uploads in tests whenever possible (#4824) 2024-09-28 20:26:44 +12:00
Joaquim VergesandGitHub fc56142880 fix: createAndSignUserOp with multiple transactions (#4839) 2024-09-28 20:26:06 +12:00
gregfromstl 842baa0513 [SDK] Fix: ensure optional chains are passed to wc (#4838)
<!-- start pr-codex -->

## PR-Codex overview
This PR focuses on enhancing the `wallet-connect` functionality by ensuring that optional chains are correctly handled in the wallet connection request process.

### Detailed summary
- Updated the destructuring of the return value from `getChainsToRequest` to include `requiredChain`.
- Changed how `optionalChains` and `chains` are assigned in `connectWC` and `initProvider` functions.
- Modified the return structure of `getChainsToRequest` to include `requiredChain` and `optionalChains`.

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

<!-- end pr-codex -->
2024-09-28 07:51:20 +00:00
jnsdls 601958d5b7 [Add] Framer rewrite for /framer-test route (#4577)
<!-- start pr-codex -->

## PR-Codex overview
This PR updates the `next.config.js` file to enhance security policies and add new redirect paths for Framer.

### Detailed summary
- Updated `style-src` and `font-src` directives to include `vercel.live`, `assets.vercel.com`, and `framerusercontent.com`.
- Added `framerusercontent.com` and `events.framer.com` to the `script-src` directive.
- Introduced `FRAMER_PATHS` for specific redirect paths.
- Added new redirect mappings for Framer paths to `https://landing.thirdweb.com`.

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

<!-- end pr-codex -->
2024-09-27 22:30:41 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
bec828de86 Version Packages (#4822)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-09-27 15:30:03 -07:00
gregfromstl a576a5b858 [SDK] Test: Adds storage mocks and basic tests (#4833)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces new features and improvements related to file uploads and downloads using IPFS and Arweave, along with enhancements to testing with `msw`. It also updates dependencies and modifies some configurations.

### Detailed summary
- Updated `.gitignore` to include `.aider*`.
- Modified `web-node.ts` to streamline header handling.
- Added `msw` as a dependency in `package.json`.
- Enhanced `download.ts` to better handle request timeouts.
- Implemented `msw` handlers in `storage.ts` for IPFS and Arweave.
- Expanded tests in `download.test.ts` for various download scenarios.
- Added tests in `web-node.test.ts` for file uploads and error handling.

> 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-09-27 22:04:39 +00:00
MananTank 5e3be734a3 Fix line break in engine Allowlisted Domains textarea placeholder (#4835)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR updates the `placeholder` prop of the `Textarea` component in the `cors.tsx` file to use a JavaScript expression instead of a string literal.

### Detailed summary
- Changed the `placeholder` prop from a string literal (`"https://example.com\nhttp://localhost:3000"`) to a JavaScript expression (`{"https://example.com\nhttp://localhost:3000"}`) for potentially better handling of the string.

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

<!-- end pr-codex -->
2024-09-27 22:00:05 +00:00
MananTank ce6d873ccc Fix Page crash on Module selection (#4834)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the handling of `selectedModule` in the `ModuleForm.tsx` component by including additional properties for better data management.

### Detailed summary
- Added `selectedModule?.contractId` to the data array.
- Added `selectedModule?.bytecodeHash` to the data array.

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

<!-- end pr-codex -->
2024-09-27 21:39:17 +00:00
gregfromstl bbe75b0bc8 [SDK] Fix: Only request specified wallet connect chains (#4832)
Falls in line with the WC spec and appeases some picky wallets

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on fixing wallet connection issues in the `thirdweb` package, particularly for wallets with limited chain support. It improves handling of optional chains and modifies how chains are requested.

### Detailed summary
- Updated handling of `optionalChains` to default to `[1]` if empty.
- Changed `chains` to be `undefined` if `chainToRequest` is not provided.
- Modified `setRequestedChainsIds` function to accept `chains` as `undefined`.
- Simplified logic for `chainsToRequest` to use `undefined` when no chains are available.

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

<!-- end pr-codex -->
2024-09-27 19:47:31 +00:00
gregfromstl cefa4eb097 [SDK] Docs: fix social profiles docs (#4821)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR updates the method used to retrieve social profiles in the `profiles.ts` file, changing the function name from `getProfiles` to `getSocialProfiles`.

### Detailed summary
- Changed the import statement from `getProfiles` to `getSocialProfiles` from the `thirdweb/social` module.
- Updated the usage of the function in the example to reflect the new function name.

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

<!-- end pr-codex -->
2024-09-27 16:34:01 +00:00
kien-ngo 63ceb2874c [Dashboard] Remove <Stack/> (3) (#4831)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on replacing instances of the `Stack` component from Chakra UI with `div` elements styled using Tailwind CSS classes. This change aims to improve layout consistency across various components in the application.

### Detailed summary
- Replaced `<Stack>` with `<div className="flex ...">` in multiple components for layout consistency.
- Adjusted spacing and alignment properties to match previous `Stack` behavior.
- Updated components in `airdrop-tab.tsx`, `select-option.tsx`, `airdrop-upload.tsx`, and others.

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

<!-- end pr-codex -->
2024-09-27 16:08:38 +00:00
kien-ngo 509c7981ee [Dashboard] Remove <Stack /> (2) (#4830)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR primarily focuses on replacing instances of the `Stack` component with `div` elements styled using Tailwind CSS classes, enhancing the layout while maintaining functionality across various components in the dashboard application.

### Detailed summary
- Replaced `<Stack>` with `<div className="flex flex-col gap-X">` in multiple components for consistent styling.
- Updated `spacing` properties to `gap` for better alignment with Tailwind CSS practices.
- Maintained functionality across components such as `PermissionEditor`, `EventsFeedItem`, and various modal dialogs.

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

<!-- end pr-codex -->
2024-09-27 15:54:39 +00:00
kien-ngo 8ea9420cc4 [Dashboard] Remove <Stack /> (1) (#4829)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on replacing instances of the `Stack` component with `div` elements styled with Flexbox classes for layout consistency across various components in the application.

### Detailed summary
- Replaced `Stack` components with `div` elements using Flexbox for layout in multiple files.
- Updated spacing and alignment properties to maintain visual consistency.
- Adjusted modal body structures to use Flexbox for better responsiveness.

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

<!-- end pr-codex -->
2024-09-27 15:48:40 +00:00
kien-ngo 8dda1139dc [Dashboard] Remove default <Stack /> (#4828)
@MananTank here's the source code: https://github.com/chakra-ui/chakra-ui/blob/main/packages/react/src/components/stack/stack.tsx

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on replacing `Stack` components with `div` elements styled with `flex` and `gap` classes across various files for a more consistent layout approach in the UI.

### Detailed summary
- Replaced `Stack` with `div className="flex flex-col gap-2"` in multiple components.
- Updated layout in `airdrop-tab.tsx`, `mint-form.tsx`, `lazy-mint-form.tsx`, `split/page.tsx`, `shared-metadata-form.tsx`, `update-metadata-form.tsx`, `transaction-timeline.tsx`, `NewsletterSection.tsx`, and more.
- Enhanced UI consistency and responsiveness.

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

<!-- end pr-codex -->
2024-09-27 11:21:45 +00:00
kien-ngo a637cab051 [Dashboard] Remove @react-icons/all-files (#4819)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on updating icon components in the `dashboard` application by replacing `react-icons` with custom SVG icons for improved performance and maintainability.

### Detailed summary
- Removed `@react-icons/all-files` dependency.
- Added new SVG components: `MediumIcon`, `YoutubeIcon`, `TiktokIcon`, `TelegramIcon`, `RedditIcon`, `MetaIcon`, `InstagramIcon`.
- Updated `SupportPage`, `PublisherSocials`, `AppFooter`, and other components to use new icons.

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

<!-- end pr-codex -->
2024-09-27 03:07:36 +00:00
kien-ngo c31f919cd4 [Dashboard] Replace Linkedin icon (#4818)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces a new `LinkedInIcon` component and replaces instances of the `SiLinkedin` icon with the new `LinkedInIcon` in two files, enhancing the consistency of icon usage across the application.

### Detailed summary
- Created a new `LinkedInIcon` component in `LinkedinIcon.tsx`.
- Replaced `SiLinkedin` with `LinkedInIcon` in `socialLinks.tsx`.
- Replaced `SiLinkedin` with `LinkedInIcon` in `PublisherSocials.tsx`.

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

<!-- end pr-codex -->
2024-09-27 02:41:46 +00:00
kien-ngo ffcd199381 [Dashboard] Replace twitter icon (#4817)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces a new `XIcon` component and replaces existing Twitter icons in various components with this new icon, enhancing consistency and potentially improving the visual design.

### Detailed summary
- Added a new `XIcon` component in `XIcon.tsx`.
- Replaced `SiTwitter` icon with `XIcon` in:
  - `edit-profile.tsx`
  - `socialLinks.tsx`
  - `PublisherSocials.tsx`

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

<!-- end pr-codex -->
2024-09-27 02:41:43 +00:00
kien-ngo b1d78b1f42 [Dashboard] Replace Discord icon (#4816)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on replacing the usage of the `SiDiscord` icon from `@react-icons/all-files` with a custom `DiscordIcon` component in multiple files, enhancing the icon's integration and potentially improving styling consistency.

### Detailed summary
- Replaced `SiDiscord` icon with `DiscordIcon` in:
  - `edit-profile.tsx`
  - `socialLinks.tsx`
  - `PublisherSocials.tsx`
- Introduced `DiscordIcon` component in `DiscordIcon.tsx` with an SVG representation.

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

<!-- end pr-codex -->
2024-09-27 01:52:10 +00:00
kien-ngo bc348ea953 [Dashboard] Replace Unity icon (#4814)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on replacing instances of the `SiUnity` icon from the `react-icons` library with a new custom `UnityIcon` component across multiple files in the dashboard application.

### Detailed summary
- Added a new `UnityIcon` component in `UnityIcon.tsx`.
- Replaced `SiUnity` with `UnityIcon` in:
  - `ConnectSDKCard.tsx`
  - `ConnectPlaygroundButton.tsx`
  - `CodeOptionButton.tsx`
  - `SupportedPlatformLink.tsx`
  - `CodeSegment.tsx`

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

<!-- end pr-codex -->
2024-09-27 01:24:04 +00:00
kien-ngo 43a24e2ed4 [Dashboard] Replace React icon (#4813)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on replacing the usage of `SiReact` icon with a new custom `ReactIcon` component across several files in the dashboard application.

### Detailed summary
- Added `ReactIcon` component in `apps/dashboard/src/components/icons/brand-icons/ReactIcon.tsx`.
- Replaced `SiReact` with `ReactIcon` in:
  - `ConnectSDKCard.tsx`
  - `ConnectPlaygroundButton.tsx`
  - `CodeOptionButton.tsx`
  - `SupportedPlatformLink.tsx`
  - `CodeSegment.tsx`

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

<!-- end pr-codex -->
2024-09-27 01:24:02 +00:00
kien-ngo 7b40f2e8e4 [Dashboard] Replace JS and TS icons (#4812)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on replacing existing icon imports for `JavaScript` and `TypeScript` with custom icon components, enhancing the visual representation in the application.

### Detailed summary
- Replaced `SiJavascript` with `JavaScriptIcon` in `ConnectPlaygroundButton.tsx`, `CodeOptionButton.tsx`, `CodeSegment.tsx`.
- Replaced `SiTypescript` with `TypeScriptIcon` in `SupportedPlatformLink.tsx`, `ConnectSDKCard.tsx`, `CodeSegment.tsx`.
- Added new components: `JavaScriptIcon.tsx` and `TypeScriptIcon.tsx` for custom icons.

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

<!-- end pr-codex -->
2024-09-27 01:24:00 +00:00
kien-ngo c1d94aec4f [Dashboard] Replace SiGithub (#4811)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on replacing the usage of the `SiGithub` icon from `@react-icons` with a custom `GithubIcon` component across several files in the dashboard application.

### Detailed summary
- Replaced `SiGithub` with `GithubIcon` in:
  - `GameCard.tsx`
  - `app-footer.tsx`
  - `edit-profile.tsx`
  - `socialLinks.tsx`
  - `PublisherSocials.tsx`
- Added `GithubIcon` component in `GithubIcon.tsx` with SVG implementation.

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

<!-- end pr-codex -->
2024-09-27 01:23:58 +00:00
kien-ngo ebd5908d4a [Dashboard] Remove non-branding icons (#4810)
<!-- start pr-codex -->

## PR-Codex overview
This PR focuses on replacing various `react-icons` with `lucide-react` icons across multiple components, along with some minor adjustments to properties and imports. It aims to standardize icon usage within the codebase.

### Detailed summary
- Removed `IconType` from multiple interfaces in `types.ts` and `AnimatedCLICommand.tsx`.
- Replaced `react-icons` with `lucide-react` icons in `HackathonFooter`, `NFTClaimButton`, and other components.
- Updated icon rendering logic in multiple components for consistency.
- Adjusted imports and usage of icons in `FileInput`, `BatchLazyMint`, and `MismatchButton`.

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

<!-- end pr-codex -->
2024-09-27 01:11:42 +00:00
Edward SunandGitHub 21b032d1b8 Remove text in UI (#4823) 2024-09-26 16:56:46 -07:00
kumaryash90 d0616c4486 Fix Cronos zkevm deployments (#4815)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR adds support for the `cronos zkevm` by updating the `isZkSyncChain` check to include additional chain IDs for both the testnet and mainnet.

### Detailed summary
- Updated the `isZkSyncChain` function in the file `packages/thirdweb/src/utils/any-evm/zksync/isZkSyncChain.ts`.
- Added chain ID `282` for `cronos zkevm testnet`.
- Added chain ID `388` for `cronos zkevm mainnet`.

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

<!-- end pr-codex -->
2024-09-26 22:13:03 +00:00
MananTank 88db5eaeab Add upload to IPFS on teams & account avatar form fields (#4807)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the account and team settings pages by adding image upload functionality for accounts and teams, updating component imports, and improving layout responsiveness.

### Detailed summary
- Added `updateAccountImage` method to `AccountSettingsPage` and `AccountSettingsPageUI`.
- Introduced `updateTeamImage` method in `TeamGeneralSettingsPage` and `TeamGeneralSettingsPageUI`.
- Changed layout from `min-h-full` to `min-h-screen`.
- Updated import statements to reflect new component names.
- Implemented async image upload functionality with IPFS integration.
- Added error handling for image update methods.

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

<!-- end pr-codex -->
2024-09-26 20:43:18 +00:00
MananTank 09b1c28c09 Replace Avatar placeholders with Avatar components in teams and account layout (#4803)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR primarily focuses on updating the account handling in various components to use an `account` object instead of separate email fields, and introduces new avatar components for enhanced visual representation of users and projects.

### Detailed summary
- Replaced `email` with `account` in multiple components.
- Introduced `GradientAvatar` and `ProjectAvatar` components for displaying user and project images.
- Updated story files to showcase new avatar components.
- Added placeholder comments for future image integration.
- Adjusted layout and styling for better alignment with new account structure.

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

<!-- end pr-codex -->
2024-09-26 20:43:14 +00:00
1189 changed files with 36836 additions and 27262 deletions
+4 -1
View File
@@ -27,4 +27,7 @@ sitemap*.xml
packages/*/typedoc/*
*storybook.log
storybook-static
storybook-static
.aider*
tsconfig.tsbuildinfo
+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=""
+9
View File
@@ -34,6 +34,11 @@ module.exports = {
message:
"Use useV5DashboardChain instead if you are using it inside a component",
},
{
selector: "CallExpression[callee.name='resolveScheme']",
message:
"resolveScheme can throw error if resolution fails. Either catch the error and ignore the lint warning or Use `resolveSchemeWithErrorHandler` / `replaceIpfsUrl` utility in dashboard instead",
},
],
"no-restricted-imports": [
"error",
@@ -60,6 +65,8 @@ module.exports = {
"AspectRatio",
"useToast",
"useClipboard",
"Badge",
"Stack",
// also the types
"ButtonProps",
"BadgeProps",
@@ -71,6 +78,8 @@ module.exports = {
"MenuGroupProps",
"MenuItemProps",
"AspectRatioProps",
"BadgeProps",
"StackProps",
],
message:
'Use the equivalent component from "tw-components" instead.',
+7
View File
@@ -0,0 +1,7 @@
// add framer paths here
module.exports = [
"/",
"/connect/sign-in",
"/contracts/modular-contracts",
"/unlimited-wallets",
];
+13 -2
View File
@@ -1,9 +1,10 @@
// @ts-check
/**
*
*/
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 +56,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;
@@ -75,8 +78,16 @@ module.exports = {
};
},
additionalPaths: async (config) => {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const FRAMER_PATHS = require("./framer-rewrites");
const allChains = await fetchChainsFromApi();
return [
...FRAMER_PATHS.map((path) => ({
loc: path,
changefreq: config.changefreq,
priority: config.priority,
lastmod: config.autoLastmod ? new Date().toISOString() : undefined,
})),
...allChains.map((chain) => {
return {
loc: `/${chain.slug}`,
+45 -39
View File
@@ -5,10 +5,10 @@ const ContentSecurityPolicy = `
img-src * data: blob:;
media-src * data: blob:;
object-src 'none';
style-src 'self' 'unsafe-inline' https://vercel.live;
font-src 'self' https://vercel.live https://assets.vercel.com;
style-src 'self' 'unsafe-inline' vercel.live;
font-src 'self' vercel.live assets.vercel.com framerusercontent.com fonts.gstatic.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;
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;
@@ -38,6 +38,7 @@ const securityHeaders = [
];
const redirects = require("./redirects");
const FRAMER_PATHS = require("./framer-rewrites");
/**
* @returns {import('next').RemotePattern[]}
@@ -128,6 +129,15 @@ const moduleExports = {
source: "/thirdweb.eth/:path*",
destination: "/deployer.thirdweb.eth/:path*",
},
// re-write /home to / (this is so that logged in users will be able to go to /home and NOT be redirected to the logged in app)
{
source: "/home",
destination: "/",
},
...FRAMER_PATHS.map((path) => ({
source: path,
destination: `https://landing.thirdweb.com${path}`,
})),
];
},
images: {
@@ -156,7 +166,6 @@ const moduleExports = {
};
const { withSentryConfig } = require("@sentry/nextjs");
const { withPlausibleProxy } = require("next-plausible");
// we only want sentry on production environments
@@ -172,48 +181,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: true,
// 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,
}),
),
);
+48 -49
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",
"@react-icons/all-files": "^4.1.0",
"@sentry/nextjs": "8.30.0",
"@shazow/whatsabi": "^0.14.1",
"@stripe/react-stripe-js": "^2.7.3",
"@radix-ui/react-switch": "^1.1.1",
"@radix-ui/react-tooltip": "1.1.3",
"@sentry/nextjs": "8.35.0",
"@shazow/whatsabi": "^0.15.4",
"@stripe/react-stripe-js": "^2.8.1",
"@stripe/stripe-js": "^3.5.0",
"@tanstack/react-query": "5.56.2",
"@tanstack/react-query": "5.59.16",
"@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.5.6",
"framer-motion": "11.11.9",
"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.453.0",
"next": "14.2.15",
"next-plausible": "^3.12.0",
"next-seo": "^6.5.0",
"next-themes": "^0.3.0",
@@ -83,49 +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-error-boundary": "^4.1.2",
"react-hook-form": "7.52.0",
"react-icons": "^5.2.1",
"react-intersection-observer": "^9.10.3",
"react-markdown": "^9.0.1",
"react-otp-input": "^3.1.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.2",
"@storybook/addon-interactions": "8.3.2",
"@storybook/addon-links": "8.3.2",
"@storybook/addon-onboarding": "8.3.2",
"@storybook/addon-viewport": "8.3.2",
"@storybook/blocks": "8.3.2",
"@storybook/nextjs": "8.3.2",
"@storybook/react": "8.3.2",
"@storybook/test": "8.3.2",
"@storybook/addon-essentials": "8.3.6",
"@storybook/addon-interactions": "8.3.6",
"@storybook/addon-links": "8.3.6",
"@storybook/addon-onboarding": "8.3.6",
"@storybook/addon-viewport": "8.3.6",
"@storybook/blocks": "8.3.6",
"@storybook/nextjs": "8.3.6",
"@storybook/react": "8.3.6",
"@storybook/test": "8.3.6",
"@types/color": "^3.0.6",
"@types/node": "20.14.9",
"@types/papaparse": "^5.3.14",
"@types/papaparse": "^5.3.15",
"@types/pluralize": "^0.0.33",
"@types/qrcode": "^1.5.5",
"@types/react": "^18.3.8",
"@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",
@@ -134,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-plugin-storybook": "^0.8.0",
"knip": "^5.30.5",
"eslint-config-biome": "1.9.3",
"eslint-plugin-react-compiler": "0.0.0-experimental-fa06e2c-20241014",
"eslint-plugin-storybook": "^0.9.0",
"knip": "^5.33.3",
"next-sitemap": "^4.2.3",
"postcss": "8.4.47",
"storybook": "8.3.2",
"tailwindcss": "3.4.12",
"typescript": "5.6.2"
"storybook": "8.3.6",
"tailwindcss": "3.4.14",
"typescript": "5.6.3"
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 318 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 294 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

+3 -5
View File
@@ -1,10 +1,8 @@
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";
const THIRDWEB_API_HOST =
process.env.NEXT_PUBLIC_THIRDWEB_API_HOST || "https://api.thirdweb.com";
export type Project = {
id: string;
name: string;
@@ -34,7 +32,7 @@ export async function getProjects(teamSlug: string) {
}
const teamsRes = await fetch(
`${THIRDWEB_API_HOST}/v1/teams/${teamSlug}/projects`,
`${API_SERVER_URL}/v1/teams/${teamSlug}/projects`,
{
headers: {
Authorization: `Bearer ${token}`,
@@ -59,7 +57,7 @@ export async function getProject(teamSlug: string, projectSlug: string) {
}
const teamsRes = await fetch(
`${THIRDWEB_API_HOST}/v1/teams/${teamSlug}/projects/${projectSlug}`,
`${API_SERVER_URL}/v1/teams/${teamSlug}/projects/${projectSlug}`,
{
headers: {
Authorization: `Bearer ${token}`,
+8 -13
View File
@@ -1,9 +1,6 @@
import "server-only";
import { COOKIE_ACTIVE_ACCOUNT, COOKIE_PREFIX_TOKEN } from "@/constants/cookie";
import { cookies } from "next/headers";
const THIRDWEB_API_HOST =
process.env.NEXT_PUBLIC_THIRDWEB_API_HOST || "https://api.thirdweb.com";
import { API_SERVER_URL } from "@/constants/env";
import { getAuthToken } from "../../app/api/lib/getAuthToken";
const TeamAccountRole = {
OWNER: "OWNER",
@@ -28,26 +25,24 @@ 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(
`${THIRDWEB_API_HOST}/v1/teams/${teamSlug}/members`,
`${API_SERVER_URL}/v1/teams/${teamSlug}/members`,
{
headers: {
Authorization: `Bearer ${token}`,
},
},
);
if (teamsRes.ok) {
return (await teamsRes.json())?.result as TeamMember[];
}
return [];
return undefined;
}
+7 -9
View File
@@ -1,22 +1,20 @@
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";
const THIRDWEB_API_HOST =
process.env.NEXT_PUBLIC_THIRDWEB_API_HOST || "https://api.thirdweb.com";
export type Team = {
id: string;
name: string;
slug: string;
createdAt: string;
updatedAt: string;
deletedAt: string | null;
bannedAt: string | null;
// image: string; // -> TODO
deletedAt?: string;
bannedAt?: string;
image?: string;
billingPlan: "pro" | "growth" | "free";
billingStatus: "validPayment" | (string & {}); // what's the other value?
// billingEmail: string;
billingEmail: string;
// billingExternalId: string;
// billingType: "STRIPE" | ??
// billingCustomerPayload: ?? | null
@@ -35,7 +33,7 @@ export async function getTeamBySlug(slug: string) {
return null;
}
const teamRes = await fetch(`${THIRDWEB_API_HOST}/v1/teams/${slug}`, {
const teamRes = await fetch(`${API_SERVER_URL}/v1/teams/${slug}`, {
headers: {
Authorization: `Bearer ${token}`,
},
@@ -57,7 +55,7 @@ export async function getTeams() {
return [];
}
const teamsRes = await fetch(`${THIRDWEB_API_HOST}/v1/teams`, {
const teamsRes = await fetch(`${API_SERVER_URL}/v1/teams`, {
headers: {
Authorization: `Bearer ${token}`,
},
@@ -0,0 +1,15 @@
"use client";
import { useEffect } from "react";
import { setCookie } from "../../stores/SyncStoreToCookies";
export function DashboardTypeCookieSetter(props: {
type: "team" | "old";
}) {
// eslint-disable-next-line no-restricted-syntax
useEffect(() => {
setCookie("x-dashboard-type", props.type);
}, [props.type]);
return null;
}
@@ -0,0 +1,89 @@
import type { Meta, StoryObj } from "@storybook/react";
import { useState } from "react";
import { BadgeContainer } from "../../../../stories/utils";
import { Button } from "../../ui/button";
import { GradientAvatar } from "./GradientAvatar";
const meta = {
title: "blocks/Avatars/GradientAvatar",
component: Story,
parameters: {},
} satisfies Meta<typeof Story>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Desktop: Story = {
args: {},
};
function Story() {
return (
<div className="flex flex-col gap-10 p-10">
<p> All images below are set with size-6 className </p>
<BadgeContainer label="No Src, No id - Skeleton">
<GradientAvatar id={undefined} src={undefined} className="size-6" />
</BadgeContainer>
<BadgeContainer label="No Src, id=foo - Skeleton">
<GradientAvatar id={"foo"} src={undefined} className="size-6" />
</BadgeContainer>
<BadgeContainer label="Invalid/Empty Src, id=foo - Gradient">
<GradientAvatar id={"foo"} src={""} className="size-6" />
</BadgeContainer>
<BadgeContainer label="Invalid/Empty Src, id=bar - Gradient">
<GradientAvatar id={"bar"} src={""} className="size-6" />
</BadgeContainer>
<BadgeContainer label="Empty/Invalid Src, No id - default fallback">
<GradientAvatar src="invalid-src" id={undefined} className="size-6" />
</BadgeContainer>
<ToggleTest />
</div>
);
}
function ToggleTest() {
const [data, setData] = useState<undefined | { src: string; id: string }>(
undefined,
);
return (
<div className="relative flex flex-col gap-10 border p-6">
<Button
variant="outline"
onClick={() => {
if (data) {
setData(undefined);
} else {
setData({
id: "foo",
src: "https://picsum.photos/400",
});
}
}}
className="absolute top-6 right-6 inline-flex"
>
Toggle Src
</Button>
<p> Src+ID is: {data ? "set" : "not set"} </p>
<BadgeContainer label="Valid Src">
<GradientAvatar src={data?.src} id={data?.id} className="size-6" />
</BadgeContainer>
<BadgeContainer label="invalid Src">
<GradientAvatar
className="size-6"
src={data ? "invalid-src" : undefined}
id={undefined}
/>
</BadgeContainer>
</div>
);
}
@@ -0,0 +1,58 @@
import { Img } from "@/components/blocks/Img";
import { useMemo } from "react";
import { cn } from "../../../lib/utils";
const gradients = [
["#fca5a5", "#b91c1c"],
["#fdba74", "#c2410c"],
["#fcd34d", "#b45309"],
["#fde047", "#a16207"],
["#a3e635", "#4d7c0f"],
["#86efac", "#15803d"],
["#67e8f9", "#0e7490"],
["#7dd3fc", "#0369a1"],
["#93c5fd", "#1d4ed8"],
["#a5b4fc", "#4338ca"],
["#c4b5fd", "#6d28d9"],
["#d8b4fe", "#7e22ce"],
["#f0abfc", "#a21caf"],
["#f9a8d4", "#be185d"],
["#fda4af", "#be123c"],
];
function getGradientForString(str: string) {
const number = Math.abs(
str.split("").reduce((acc, b, i) => acc + b.charCodeAt(0) * (i + 1), 0),
);
const index = number % gradients.length;
return gradients[index];
}
export function GradientAvatar(props: {
src: string | undefined;
id: string | undefined;
className: string;
}) {
const gradient = useMemo(() => {
if (!props.id) {
return undefined;
}
return getGradientForString(props.id);
}, [props.id]);
return (
<Img
src={props.src}
className={cn("rounded-full", props.className)}
fallback={
gradient ? (
<div
style={{
background: `linear-gradient(45deg, ${gradient[0]} 0%, ${gradient[1]} 100%)`,
}}
/>
) : undefined
}
/>
);
}
@@ -0,0 +1,76 @@
import type { Meta, StoryObj } from "@storybook/react";
import { useState } from "react";
import { BadgeContainer } from "../../../../stories/utils";
import { Button } from "../../ui/button";
import { ProjectAvatar } from "./ProjectAvatar";
const meta = {
title: "blocks/Avatars/ProjectAvatar",
component: Story,
parameters: {},
} satisfies Meta<typeof Story>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Desktop: Story = {
args: {},
};
function Story() {
return (
<div className="flex flex-col gap-10 p-10">
<p> All images below are set with size-6 className </p>
<BadgeContainer label="No Src - Skeleton">
<ProjectAvatar src={undefined} className="size-6" />
</BadgeContainer>
<BadgeContainer label="Invalid/Empty Src - BoxIcon Fallback">
<ProjectAvatar src={""} className="size-6" />
</BadgeContainer>
<ToggleTest />
</div>
);
}
function ToggleTest() {
const [data, setData] = useState<undefined | { src: string; name: string }>(
undefined,
);
return (
<div className="relative flex flex-col gap-10 border p-6">
<Button
variant="outline"
onClick={() => {
if (data) {
setData(undefined);
} else {
setData({
name: "foo",
src: "https://picsum.photos/400",
});
}
}}
className="absolute top-6 right-6 inline-flex"
>
Toggle Src
</Button>
<p> Src+Name is: {data ? "set" : "not set"} </p>
<BadgeContainer label="Valid Src">
<ProjectAvatar src={data?.src} className="size-6" />
</BadgeContainer>
<BadgeContainer label="invalid Src">
<ProjectAvatar
src={data ? "invalid-src" : undefined}
className="size-6"
/>
</BadgeContainer>
</div>
);
}
@@ -0,0 +1,21 @@
import { Img } from "@/components/blocks/Img";
import { BoxIcon } from "lucide-react";
import { cn } from "../../../lib/utils";
export function ProjectAvatar(props: {
src: string | undefined;
className: string | undefined;
}) {
return (
<Img
src={props.src}
className={cn("rounded-lg border border-border", props.className)}
alt={""}
fallback={
<div className="flex items-center justify-center bg-muted/50">
<BoxIcon className="size-[50%] text-muted-foreground" />
</div>
}
/>
);
}
@@ -11,9 +11,12 @@ import {
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import { cn } from "../../lib/utils";
export function DangerSettingCard(props: {
title: string;
className?: string;
footerClassName?: string;
description: string;
buttonLabel: string;
buttonOnClick: () => void;
@@ -22,18 +25,31 @@ export function DangerSettingCard(props: {
title: string;
description: string;
};
children?: React.ReactNode;
}) {
return (
<div className="overflow-hidden rounded-lg border border-red-500/70">
<div className="bg-muted/50 px-4 py-6 lg:px-6">
<div
className={cn(
"overflow-hidden rounded-lg border border-red-500/70",
props.className,
)}
>
<div className="px-4 py-6 lg:px-6">
<h3 className="font-semibold text-xl tracking-tight">{props.title}</h3>
<p className="mt-1.5 mb-4 text-foreground text-sm">
{props.description}
</p>
{props.children}
</div>
<div className="flex justify-end border-red-500/70 border-t bg-red-100 px-4 py-4 lg:px-6 dark:bg-red-500/20">
<div
className={cn(
"flex justify-end border-red-500/70 border-t bg-red-100 px-4 py-4 lg:px-6 dark:bg-red-500/20",
props.footerClassName,
)}
>
<Dialog>
<DialogTrigger asChild>
<Button
@@ -46,7 +62,10 @@ export function DangerSettingCard(props: {
</Button>
</DialogTrigger>
<DialogContent>
<DialogContent
className="z-[10001]"
dialogOverlayClassName="z-[10000]"
>
<DialogHeader className="pr-10">
<DialogTitle className="leading-snug">
{props.confirmationDialog.title}
@@ -7,7 +7,7 @@ export function FormFieldSetup(props: {
label: string;
errorMessage: React.ReactNode | undefined;
children: React.ReactNode;
tooltip: React.ReactNode | undefined;
tooltip?: React.ReactNode;
isRequired: boolean;
}) {
return (
@@ -4,25 +4,45 @@ import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
import { ChevronDownIcon } from "lucide-react";
import { usePathname } from "next/navigation";
import { useState } from "react";
import { useMemo, useState } from "react";
import { cn } from "../../lib/utils";
import { NavLink } from "../ui/NavLink";
import type { SidebarLink } from "./Sidebar";
import {
RenderSidebarLinks,
type SidebarBaseLink,
type SidebarLink,
} from "./Sidebar";
export function MobileSidebar(props: {
links?: SidebarLink[];
links: SidebarLink[];
footer?: React.ReactNode;
trigger?: React.ReactNode;
triggerClassName?: string;
}) {
const [isOpen, setIsOpen] = useState(false);
const pathname = usePathname();
const activeLink = props.links?.find((link) => {
if (link.exactMatch) {
return link.href === pathname;
const activeLink = useMemo(() => {
function isActive(link: SidebarBaseLink) {
if (link.exactMatch) {
return link.href === pathname;
}
return pathname?.startsWith(link.href);
}
return pathname?.startsWith(link.href);
});
for (const link of props.links) {
if ("group" in link) {
for (const subLink of link.links) {
if (isActive(subLink)) {
return subLink;
}
}
} else {
if (isActive(link)) {
return link;
}
}
}
}, [props.links, pathname]);
const defaultTrigger = (
<Button
@@ -41,7 +61,7 @@ export function MobileSidebar(props: {
<Dialog open={isOpen} onOpenChange={setIsOpen}>
<DialogTrigger asChild>{props.trigger || defaultTrigger}</DialogTrigger>
<DialogContent
className="rounded-t-xl rounded-b-none p-4"
className="no-scrollbar max-h-[80vh] overflow-auto rounded-t-xl rounded-b-none p-4"
dialogCloseClassName="hidden"
onClick={(e) => {
if (e.target instanceof HTMLAnchorElement) {
@@ -49,23 +69,7 @@ export function MobileSidebar(props: {
}
}}
>
<div className="flex flex-col gap-2">
{props.links?.map((link) => {
return (
<Button size="sm" variant="ghost" asChild key={link.href}>
<NavLink
href={link.href}
className="!text-left flex h-auto justify-start gap-2 py-3"
activeClassName="bg-accent"
exactMatch={link.exactMatch}
tracking={link.tracking}
>
{link.label}
</NavLink>
</Button>
);
})}
</div>
<RenderSidebarLinks links={props.links} />
{props.footer}
</DialogContent>
</Dialog>
@@ -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}
/>
);
}
@@ -17,6 +17,15 @@ export function SettingsCard(
disabled: boolean;
isPending: boolean;
type?: "submit";
variant?:
| "ghost"
| "default"
| "primary"
| "destructive"
| "outline"
| "secondary";
className?: string;
label?: string;
};
}>,
) {
@@ -58,14 +67,15 @@ export function SettingsCard(
{props.saveButton && !props.noPermissionText && (
<Button
size="sm"
className="gap-2"
className={cn("gap-2", props.saveButton.className)}
onClick={props.saveButton.onClick}
disabled={props.saveButton.disabled || props.saveButton.isPending}
variant="outline"
variant={props.saveButton.variant || "outline"}
type={props.saveButton.type}
>
{props.saveButton.isPending && <Spinner className="size-3" />}
{props.saveButton.isPending ? "Saving" : "Save"}
{props.saveButton.label ||
(props.saveButton.isPending ? "Saving" : "Save")}
</Button>
)}
</div>
@@ -3,7 +3,7 @@ import type React from "react";
import { cn } from "../../lib/utils";
import { NavLink } from "../ui/NavLink";
export type SidebarLink = {
export type SidebarBaseLink = {
href: string;
label: React.ReactNode;
exactMatch?: boolean;
@@ -14,6 +14,13 @@ export type SidebarLink = {
};
};
export type SidebarLink =
| SidebarBaseLink
| {
group: string;
links: SidebarBaseLink[];
};
type SidebarContentProps = {
header?: React.ReactNode;
links: SidebarLink[];
@@ -28,26 +35,45 @@ export function Sidebar(props: SidebarContentProps) {
props.className,
)}
>
<div className="pt-7">
<div className="py-7">
{props.header}
<div className="flex flex-col gap-1">
{props.links?.map((link) => {
const isExternal = link.href.startsWith("http");
return (
<NavLink
key={link.href}
href={link.href}
className="flex items-center gap-2 rounded-md px-3 py-2 text-muted-foreground text-sm hover:bg-muted"
activeClassName="text-foreground"
exactMatch={link.exactMatch}
>
{link.label}
{isExternal && <ExternalLinkIcon className="size-3" />}
</NavLink>
);
})}
<RenderSidebarLinks links={props.links} />
</div>
</div>
</aside>
);
}
export function RenderSidebarLinks(props: { links: SidebarLink[] }) {
return (
<div className="flex flex-col gap-1">
{props.links.map((link, i) => {
if ("group" in link) {
return (
<div className={cn({ "mt-6": i !== 0 })}>
<p className={cn("px-3 py-2 font-medium text-foreground")}>
{link.group}
</p>
<RenderSidebarLinks links={link.links} />
</div>
);
}
const isExternal = link.href.startsWith("http");
return (
<NavLink
key={link.href}
href={link.href}
className="flex items-center gap-2 rounded-md px-3 py-2 text-muted-foreground text-sm hover:bg-muted"
activeClassName="text-foreground"
exactMatch={link.exactMatch}
>
{link.label}
{isExternal && <ExternalLinkIcon className="size-3" />}
</NavLink>
);
})}
</div>
);
}
@@ -1,17 +1,15 @@
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import { ThirdwebMiniLogo } from "app/components/ThirdwebMiniLogo";
import { DiscordIcon } from "components/icons/brand-icons/DiscordIcon";
import { GithubIcon } from "components/icons/brand-icons/GithubIcon";
import { InstagramIcon } from "components/icons/brand-icons/InstagramIcon";
import { LinkedInIcon } from "components/icons/brand-icons/LinkedinIcon";
import { RedditIcon } from "components/icons/brand-icons/RedditIcon";
import { TiktokIcon } from "components/icons/brand-icons/TiktokIcon";
import { XIcon } from "components/icons/brand-icons/XIcon";
import { YoutubeIcon } from "components/icons/brand-icons/YoutubeIcon";
import Link from "next/link";
import {
SiDiscord,
SiGithub,
SiInstagram,
SiLinkedin,
SiReddit,
SiTiktok,
SiX,
SiYoutube,
} from "react-icons/si";
type AppFooterProps = {
className?: string;
@@ -35,17 +33,17 @@ export function AppFooter(props: AppFooterProps) {
<div className="flex flex-row gap-3">
<Button size="icon" variant="ghost" asChild className="size-9">
<Link href="https://github.com/thirdweb-dev" target="_blank">
<SiGithub className="size-5 text-muted-foreground" />
<GithubIcon className="size-5 text-muted-foreground" />
</Link>
</Button>
<Button size="icon" variant="ghost" asChild className="size-9">
<Link href="https://www.tiktok.com/@thirdweb" target="_blank">
<SiTiktok className="size-5 text-muted-foreground" />
<TiktokIcon className="size-5 text-muted-foreground" />
</Link>
</Button>
<Button size="icon" variant="ghost" asChild className="size-9">
<Link href="https://www.instagram.com/thirdweb/" target="_blank">
<SiInstagram className="size-5 text-muted-foreground" />
<InstagramIcon className="size-5 text-muted-foreground" />
</Link>
</Button>
<Button size="icon" variant="ghost" asChild className="size-9">
@@ -53,27 +51,27 @@ export function AppFooter(props: AppFooterProps) {
href="hhttps://www.linkedin.com/company/third-web/"
target="_blank"
>
<SiLinkedin className="size-5 text-muted-foreground" />
<LinkedInIcon className="size-5 text-muted-foreground" />
</Link>
</Button>
<Button size="icon" variant="ghost" asChild className="size-9">
<Link href="https://www.youtube.com/@thirdweb_" target="_blank">
<SiYoutube className="size-5 text-muted-foreground" />
<YoutubeIcon className="size-5 text-muted-foreground" />
</Link>
</Button>
<Button size="icon" variant="ghost" asChild className="size-9">
<Link href="https://discord.gg/thirdweb" target="_blank">
<SiDiscord className="size-5 text-muted-foreground" />
<DiscordIcon className="size-5 text-muted-foreground" />
</Link>
</Button>
<Button size="icon" variant="ghost" asChild className="size-9">
<Link href="https://www.reddit.com/r/thirdweb/" target="_blank">
<SiReddit className="size-5 text-muted-foreground" />
<RedditIcon className="size-5 text-muted-foreground" />
</Link>
</Button>
<Button size="icon" variant="ghost" asChild className="size-9">
<Link href="https://x.com/thirdweb" target="_blank">
<SiX className="size-5 text-muted-foreground" />
<XIcon className="size-5 text-muted-foreground" />
</Link>
</Button>
</div>
@@ -121,13 +119,7 @@ export function AppFooter(props: AppFooterProps) {
>
Terms of Service
</Link>
<Link
className="px-[10px] py-[6px] text-muted-foreground text-sm hover:underline"
href="https://thirdweb.com/gas"
target="_blank"
>
Gas Estimator
</Link>
<Link
className="px-[10px] py-[6px] text-muted-foreground text-sm hover:underline"
href="https://thirdweb.com/chainlist"
@@ -1,14 +1,5 @@
"use client";
import { Area, AreaChart, CartesianGrid, XAxis } from "recharts";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import {
type ChartConfig,
ChartContainer,
@@ -18,11 +9,9 @@ import {
ChartTooltipContent,
} from "@/components/ui/chart";
import { useMemo } from "react";
import { Area, AreaChart, CartesianGrid, XAxis } from "recharts";
type ThirdwebAreaChartProps<TConfig extends ChartConfig> = {
// metadata
title: string;
description?: string;
// chart config
config: TConfig;
data: Array<Record<keyof TConfig, number> & { time: number | string | Date }>;
@@ -37,73 +26,65 @@ export function ThirdwebAreaChart<TConfig extends ChartConfig>(
) {
const configKeys = useMemo(() => Object.keys(props.config), [props.config]);
return (
<Card>
<CardHeader>
<CardTitle>{props.title}</CardTitle>
{props.description && (
<CardDescription>{props.description}</CardDescription>
)}
</CardHeader>
<CardContent>
<ChartContainer config={props.config} className={props.chartClassName}>
<AreaChart
accessibilityLayer
data={props.data}
margin={{
left: 12,
right: 12,
}}
>
<CartesianGrid vertical={false} />
<XAxis
dataKey="time"
tickLine={false}
axisLine={false}
tickMargin={8}
tickFormatter={(value) => new Date(value).toLocaleDateString()}
/>
<ChartTooltip cursor={false} content={<ChartTooltipContent />} />
<defs>
{configKeys.map((key) => (
<linearGradient
key={key}
id={`fill_${key}`}
x1="0"
y1="0"
x2="0"
y2="1"
>
<stop
offset="5%"
stopColor={`var(--color-${key})`}
stopOpacity={0.8}
/>
<stop
offset="95%"
stopColor={`var(--color-${key})`}
stopOpacity={0.1}
/>
</linearGradient>
))}
</defs>
<div className="rounded-lg border border-border bg-muted/50 px-4 pt-10 pb-4">
<ChartContainer config={props.config} className={props.chartClassName}>
<AreaChart
accessibilityLayer
data={props.data}
margin={{
left: 12,
right: 12,
}}
>
<CartesianGrid vertical={false} />
<XAxis
dataKey="time"
tickLine={false}
axisLine={false}
tickMargin={20}
tickFormatter={(value) => new Date(value).toLocaleDateString()}
/>
<ChartTooltip cursor={false} content={<ChartTooltipContent />} />
<defs>
{configKeys.map((key) => (
<Area
<linearGradient
key={key}
dataKey={key}
type="natural"
fill={`url(#fill_${key})`}
fillOpacity={0.4}
stroke={`var(--color-${key})`}
stackId="a"
/>
id={`fill_${key}`}
x1="0"
y1="0"
x2="0"
y2="1"
>
<stop
offset="5%"
stopColor={`var(--color-${key})`}
stopOpacity={0.8}
/>
<stop
offset="95%"
stopColor={`var(--color-${key})`}
stopOpacity={0.1}
/>
</linearGradient>
))}
</defs>
{configKeys.map((key) => (
<Area
key={key}
dataKey={key}
type="natural"
fill={`url(#fill_${key})`}
fillOpacity={0.4}
stroke={`var(--color-${key})`}
stackId="a"
/>
))}
{props.showLegend && (
<ChartLegend content={<ChartLegendContent />} />
)}
</AreaChart>
</ChartContainer>
</CardContent>
</Card>
{props.showLegend && (
<ChartLegend content={<ChartLegendContent />} className="pt-8" />
)}
</AreaChart>
</ChartContainer>
</div>
);
}
@@ -0,0 +1,44 @@
import { CopyTextButton } from "@/components/ui/CopyTextButton";
import { ScrollShadow } from "@/components/ui/ScrollShadow/ScrollShadow";
import { useMemo } from "react";
export function UnexpectedValueErrorMessage(props: {
value: unknown;
title: string;
description: string;
className?: string;
}) {
const stringifiedValue = useMemo(() => {
try {
return JSON.stringify(props.value, null, 2);
} catch {
return undefined;
}
}, [props.value]);
return (
<div className={props.className}>
<p className="text-base text-destructive-text"> {props.title} </p>
<p className="text-foreground text-sm">{props.description}</p>
{stringifiedValue && (
<div className="mt-3">
<p className="mb-0.5 text-muted-foreground text-sm">Value Received</p>
<ScrollShadow className="rounded-lg bg-muted/50">
<code className="block whitespace-pre p-4 font-mono text-xs">
{stringifiedValue}
</code>
</ScrollShadow>
<CopyTextButton
copyIconPosition="left"
textToShow="Copy value"
textToCopy={stringifiedValue}
tooltip="Copy value"
className="-translate-x-2 mt-1 text-muted-foreground"
variant="ghost"
/>
</div>
)}
</div>
);
}
@@ -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";
@@ -1,5 +1,4 @@
"use client";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import {
HoverCard,
@@ -7,6 +6,7 @@ import {
HoverCardTrigger,
} from "@/components/ui/hover-card";
import { useThirdwebClient } from "@/constants/thirdweb.client";
import { resolveSchemeWithErrorHandler } from "@/lib/resolveSchemeWithErrorHandler";
import { useClipboard } from "hooks/useClipboard";
import { Check, Copy, ExternalLinkIcon } from "lucide-react";
import { useMemo } from "react";
@@ -18,7 +18,6 @@ import {
type SocialProfile,
useSocialProfiles,
} from "thirdweb/react";
import { resolveScheme } from "thirdweb/storage";
import { cn } from "../../lib/utils";
import { Badge } from "../ui/badge";
import { Button } from "../ui/button";
@@ -113,22 +112,20 @@ export function WalletAddress(props: {
) : !profiles.data?.length ? (
<p className="text-muted-foreground text-sm">No profiles found</p>
) : (
profiles.data?.map((profile) => (
<div
className="flex flex-row items-center gap-2"
key={profile.type + profile.name}
>
{profile.avatar &&
(profile.avatar.startsWith("http") ||
profile.avatar?.startsWith("ipfs")) && (
profiles.data?.map((profile) => {
const walletAvatarLink = resolveSchemeWithErrorHandler({
client: thirdwebClient,
uri: profile.avatar,
});
return (
<div
className="flex flex-row items-center gap-2"
key={profile.type + profile.name}
>
{walletAvatarLink && (
<Avatar>
<AvatarImage
src={resolveScheme({
client: thirdwebClient,
uri: profile.avatar,
})}
alt={profile.name}
/>
<AvatarImage src={walletAvatarLink} alt={profile.name} />
{profile.name && (
<AvatarFallback>
{profile.name.slice(0, 2)}
@@ -136,19 +133,20 @@ export function WalletAddress(props: {
)}
</Avatar>
)}
<div className="flex w-full flex-col gap-1">
<div className="flex w-full flex-row items-center justify-between gap-4">
<h4 className="font-semibold text-md">{profile.name}</h4>
<Badge variant="outline">{profile.type}</Badge>
<div className="flex w-full flex-col gap-1">
<div className="flex w-full flex-row items-center justify-between gap-4">
<h4 className="font-semibold text-md">{profile.name}</h4>
<Badge variant="outline">{profile.type}</Badge>
</div>
{profile.bio && (
<p className="line-clamp-1 whitespace-normal text-muted-foreground text-sm">
{profile.bio}
</p>
)}
</div>
{profile.bio && (
<p className="line-clamp-1 whitespace-normal text-muted-foreground text-sm">
{profile.bio}
</p>
)}
</div>
</div>
))
);
})
)}
<Button
asChild
@@ -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"
@@ -0,0 +1,36 @@
"use client";
import { useClipboard } from "hooks/useClipboard";
import { CheckIcon, CopyIcon } from "lucide-react";
import { cn } from "../../lib/utils";
import { Button } from "./button";
export function PlainTextCodeBlock(props: {
code: string;
copyButtonClassName?: string;
}) {
const { hasCopied, onCopy } = useClipboard(props.code);
return (
<div className="relative">
<code className="block whitespace-pre rounded-lg border border-border bg-muted/50 p-4">
{props.code}
</code>
<Button
size="sm"
variant="outline"
onClick={onCopy}
className={cn(
"absolute top-3.5 right-3.5 h-auto p-2",
props.copyButtonClassName,
)}
>
{hasCopied ? (
<CheckIcon className="size-3 text-green-500" />
) : (
<CopyIcon className="size-3 text-muted-foreground" />
)}
</Button>
</div>
);
}
@@ -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],
@@ -0,0 +1,17 @@
import { cn } from "@/lib/utils";
export function InlineCode({
code,
className,
}: { code: string; className?: string }) {
return (
<code
className={cn(
"inline-block rounded bg-muted px-2 font-mono text-sm",
className,
)}
>
{code}
</code>
);
}
@@ -0,0 +1,73 @@
"use client";
import { OTPInput, OTPInputContext } from "input-otp";
import { Dot } from "lucide-react";
import * as React from "react";
import { cn } from "@/lib/utils";
const InputOTP = React.forwardRef<
React.ElementRef<typeof OTPInput>,
React.ComponentPropsWithoutRef<typeof OTPInput>
>(({ className, containerClassName, ...props }, ref) => (
<OTPInput
ref={ref}
containerClassName={cn(
"flex items-center gap-2 has-[:disabled]:opacity-50",
containerClassName,
)}
className={cn("disabled:cursor-not-allowed", className)}
{...props}
/>
));
InputOTP.displayName = "InputOTP";
const InputOTPGroup = React.forwardRef<
React.ElementRef<"div">,
React.ComponentPropsWithoutRef<"div">
>(({ className, ...props }, ref) => (
<div ref={ref} className={cn("flex items-center", className)} {...props} />
));
InputOTPGroup.displayName = "InputOTPGroup";
const InputOTPSlot = React.forwardRef<
React.ElementRef<"div">,
React.ComponentPropsWithoutRef<"div"> & { index: number }
>(({ index, className, ...props }, ref) => {
const inputOTPContext = React.useContext(OTPInputContext);
// biome-ignore lint/style/noNonNullAssertion: pure shadcn component - it works
const { char, hasFakeCaret, isActive } = inputOTPContext.slots[index]!;
return (
<div
ref={ref}
className={cn(
"relative flex h-10 w-10 items-center justify-center border-input border-y border-r text-sm transition-all first:rounded-l-md first:border-l last:rounded-r-md",
isActive && "z-10 ring-2 ring-ring ring-offset-background",
className,
)}
{...props}
>
{char}
{hasFakeCaret && (
<div className="pointer-events-none absolute inset-0 flex items-center justify-center">
<div className="h-4 w-px animate-caret-blink bg-foreground duration-1000" />
</div>
)}
</div>
);
});
InputOTPSlot.displayName = "InputOTPSlot";
const InputOTPSeparator = React.forwardRef<
React.ElementRef<"div">,
React.ComponentPropsWithoutRef<"div">
>(({ ...props }, ref) => (
// biome-ignore lint/a11y/useFocusableInteractive: pure shadcn component - it works
<div ref={ref} role="separator" {...props}>
<Dot />
</div>
));
InputOTPSeparator.displayName = "InputOTPSeparator";
export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator };
+1 -1
View File
@@ -11,7 +11,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
<input
type={type}
className={cn(
"flex h-10 w-full rounded-md border border-input bg-card px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:font-medium file:text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
"flex h-10 w-full rounded-md border border-input bg-card px-3 py-2 text-sm ring-offset-background selection:bg-foreground selection:text-background file:border-0 file:bg-transparent file:font-medium file:text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
className,
)}
ref={ref}
@@ -51,12 +51,12 @@ const RadioGroupItemButton = React.forwardRef<
<RadioGroupPrimitive.Item
ref={ref}
className={cn(
"group flex min-w-32 cursor-pointer items-center space-x-3 space-y-0 rounded-md border-2 px-3 py-4 font-medium transition-all hover:border-foreground/25 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 peer-hover:border-nonce data-[state=checked]:border-inverted",
"group flex min-w-32 cursor-pointer items-center space-x-3 space-y-0 rounded-lg border px-4 py-3 font-medium transition-all hover:border-foreground/25 hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 peer-hover:border-nonce data-[state=checked]:border-muted-foreground",
className,
)}
{...props}
>
<div className="flex aspect-square h-4 w-4 items-center justify-center rounded-full border-2 text-inverted ring-offset-background transition-all focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 group-hover:border-foreground/25 group-data-[state=checked]:border-inverted">
<div className="flex aspect-square h-4 w-4 items-center justify-center rounded-full border text-inverted ring-offset-background transition-all focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 group-hover:border-foreground/25 group-data-[state=checked]:border-inverted">
{/* Show on checked */}
<RadioGroupPrimitive.Indicator className="flex items-center justify-center rounded-full transition-all">
<Circle className="h-2 w-2 fill-current text-current" />
+2 -6
View File
@@ -159,12 +159,8 @@ 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";
}
}
-1
View File
@@ -5,7 +5,6 @@ const LOGGED_IN_ONLY_PATHS = [
"/team",
// anything that _starts_ with /cli is logged in only
"/cli",
"/support",
// publish page
"/contracts/publish",
];
+6
View File
@@ -20,3 +20,9 @@ export const PROD_OR_DEV_URL = isProd ? "thirdweb.com" : "thirdweb-dev.com";
export const DASHBOARD_STORAGE_URL =
process.env.NEXT_PUBLIC_DASHBOARD_UPLOAD_SERVER ||
"https://storage.thirdweb.com";
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 || "";
+2
View File
@@ -1,3 +1,5 @@
"use client";
import { useSyncExternalStore } from "react";
export type Store<T> = {
@@ -0,0 +1,21 @@
import type { ThirdwebClient } from "thirdweb";
import { resolveScheme } from "thirdweb/storage";
export function resolveSchemeWithErrorHandler(options: {
uri: string | undefined;
client: ThirdwebClient;
}) {
if (!options.uri) {
return undefined;
}
try {
// eslint-disable-next-line no-restricted-syntax
return resolveScheme({
uri: options.uri,
client: options.client,
});
} catch (err) {
console.error("error resolving ipfs url", options.uri, err);
return undefined;
}
}
-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%;
}
}
@@ -0,0 +1,3 @@
# DO NOT ADD NEW THINGS INSIDE THIS FOLDER OR SUB_FOLDERS
This part of the dashboard is deprecated, and we are actively working on removing it. Please do not add new things here. If you need to add new things, please add them to the appropriate folder in the src folder.
@@ -1,9 +1,3 @@
export const networkKeys = {
all: ["network"] as const,
chain: (chainId?: number) => [...networkKeys.all, chainId] as const,
multiChainRegistry: ["multi-chain-registry"] as const,
};
export const accountKeys = {
all: ["account"] as const,
wallet: (walletAddress: string) =>
@@ -27,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) =>
@@ -1,98 +0,0 @@
import { networkKeys, useDashboardEVMChainId } from "@3rdweb-sdk/react";
import {
type MutationFunction,
type QueryFunction,
type QueryKey,
type UseMutationOptions,
type UseQueryOptions,
type UseQueryResult,
useMutation,
useQuery,
useQueryClient,
} from "@tanstack/react-query";
import { useCallback } from "react";
export function useQueryWithNetwork<
TQueryFnData = unknown,
TError = unknown,
TData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey,
>(
queryKey: TQueryKey,
queryFn: QueryFunction<TQueryFnData, TQueryKey>,
options?: Omit<
UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>,
"queryKey" | "queryFn"
>,
): UseQueryResult<TData, TError> {
const activeChainId = useDashboardEVMChainId();
const mergedOptions: Omit<
UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>,
"queryKey" | "queryFn"
> = {
...options,
enabled: !!(activeChainId && options?.enabled),
};
const combinedQueryKey = (
networkKeys.chain(activeChainId) as readonly unknown[]
).concat(queryKey) as unknown as TQueryKey;
return useQuery({
...mergedOptions,
queryKey: combinedQueryKey,
queryFn,
});
}
export function useMutationWithInvalidate<
TData = unknown,
TError = unknown,
TVariables = void,
TContext = unknown,
TQueryKey extends QueryKey = QueryKey,
>(
mutationFn: MutationFunction<TData, TVariables>,
options?: Omit<
UseMutationOptions<TData, TError, TVariables, TContext>,
"mutationFn" | "onSuccess"
> & {
onSuccess?: (
data: TData,
variables: TVariables,
context: TContext | undefined,
wrapCacheKeys: (
cacheKeysToInvalidate: TQueryKey[],
// biome-ignore lint/suspicious/noConfusingVoidType: FIX ME
) => Promise<void[]>,
) => Promise<unknown> | undefined;
},
) {
const activeChainId = useDashboardEVMChainId();
const queryClient = useQueryClient();
const invalidate = useCallback(
(cacheKeysToInvalidate: TQueryKey[]) => {
return Promise.all(
cacheKeysToInvalidate.map((cacheKey) => {
return queryClient.invalidateQueries({
queryKey: (
networkKeys.chain(activeChainId) as readonly unknown[]
).concat(cacheKey) as unknown[],
});
}),
);
},
[queryClient, activeChainId],
);
return useMutation({
...options,
mutationFn,
onSuccess: (...args) => {
if (options?.onSuccess) {
options.onSuccess(...args, invalidate);
}
},
});
}
@@ -1,12 +1,4 @@
import {
createContext,
useCallback,
useContext,
useEffect,
useState,
} from "react";
import type { ChainMetadata } from "thirdweb/chains";
import invariant from "tiny-invariant";
export type EVMContractInfo = {
// using null instead of undefined here so that this type can be JSON stringified
@@ -14,78 +6,3 @@ export type EVMContractInfo = {
chainSlug: string;
contractAddress: string;
};
type SetEVMContractInfo = (info: EVMContractInfo) => void;
// Legacy: will be removed with contract page -> app router refactor
// eslint-disable-next-line no-restricted-syntax
const EVMContractInfoContext = createContext<EVMContractInfo | undefined>(
undefined,
);
// Legacy: will be removed with contract page -> app router refactor
// eslint-disable-next-line no-restricted-syntax
const SetEVMContractInfoContext = createContext<SetEVMContractInfo | undefined>(
undefined,
);
// TODO let's move this out of here eventually
export function EVMContractInfoProvider(props: {
children: React.ReactNode;
value?: EVMContractInfo;
}) {
const [value, setValue] = useState<EVMContractInfo | undefined>(props.value);
// keep the state in sync with the props.value
// this is required when route changes and page goes from fallback to actual page
const _setValue = useCallback((info?: EVMContractInfo) => {
setValue((prevValue) => {
if (
prevValue?.chainSlug === info?.chainSlug &&
prevValue?.contractAddress === info?.contractAddress &&
info?.chain === null
) {
return prevValue;
}
return info;
});
}, []);
// no better way right now - this whole file is going away with RSC migration
// eslint-disable-next-line no-restricted-syntax
useEffect(() => {
_setValue(props.value);
}, [_setValue, props.value]);
// when we move from rendering the fallback page to the actual page, props.value is correct value but state lags behind with undefined value
// in that case we use the props.value instead of providing undefined and update the state with effect afterwards
// this only happens ONCE, when the page is not yet created on server. once it is created and cached. value will always be defined
const providedValue = value || props.value;
return (
<EVMContractInfoContext.Provider value={providedValue}>
<SetEVMContractInfoContext.Provider value={_setValue}>
{props.children}
</SetEVMContractInfoContext.Provider>
</EVMContractInfoContext.Provider>
);
}
export function useEVMContractInfo() {
return useContext(EVMContractInfoContext);
}
export function useSetEVMContractInfo() {
const setter = useContext(SetEVMContractInfoContext);
invariant(
setter,
"useSetEVMContractInfo must be used inside EVMContractInfoProvider",
);
return setter;
}
// for EVM - get network info from context
export function useDashboardEVMChainId() {
const contractInfo = useEVMContractInfo();
return contractInfo?.chain?.chainId;
}
@@ -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] = {
@@ -7,7 +7,6 @@ import {
import { THIRDWEB_ANALYTICS_API_HOST, THIRDWEB_API_HOST } from "constants/urls";
import invariant from "tiny-invariant";
import { accountKeys, apiKeys, authorizedWallets } from "../cache-keys";
import { useMutationWithInvalidate } from "./query/useQueryWithNetwork";
import { useLoggedInUser } from "./useLoggedInUser";
// FIXME: We keep repeating types, API server should provide them
@@ -67,6 +66,7 @@ export type Account = {
paymentFailureCode: string;
serviceCutoffDate: string;
}[];
// TODO - add image URL
};
interface UpdateAccountInput {
@@ -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,116 @@ 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<UserOpStats>({
queryKey: accountKeys.userOpStats(
user?.address as string,
clientId as string,
from?.toISOString() || "",
to?.toISOString() || "",
"all",
),
queryFn: async () => {
const userOpStats: UserOpStats[] = await getUserOpUsage({
clientId,
from,
to,
period: "all",
});
// Aggregate stats across wallet types
return userOpStats.reduce(
(acc, curr) => {
acc.successful += curr.successful;
acc.failed += curr.failed;
acc.sponsoredUsd += curr.sponsoredUsd;
return acc;
},
{
date: (from || new Date()).toISOString(),
successful: 0,
failed: 0,
sponsoredUsd: 0,
},
);
},
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;
@@ -478,8 +595,8 @@ export function useUpdateAccountPlan(waitForWebhook?: boolean) {
const { user } = useLoggedInUser();
const queryClient = useQueryClient();
return useMutationWithInvalidate(
async (input: { plan: string; feedback?: string }) => {
return useMutation({
mutationFn: async (input: { plan: string; feedback?: string }) => {
invariant(user?.address, "walletAddress is required");
const res = await fetch(`${THIRDWEB_API_HOST}/v1/account/plan`, {
@@ -505,27 +622,26 @@ export function useUpdateAccountPlan(waitForWebhook?: boolean) {
return json.data;
},
{
onSuccess: async () => {
onSuccess: async () => {
return Promise.all([
// invalidate usage data as limits are different
await queryClient.invalidateQueries({
queryClient.invalidateQueries({
queryKey: accountKeys.me(user?.address as string),
});
return queryClient.invalidateQueries({
}),
queryClient.invalidateQueries({
queryKey: accountKeys.usage(user?.address as string),
});
},
}),
]);
},
);
});
}
export function useUpdateNotifications() {
const { user } = useLoggedInUser();
const queryClient = useQueryClient();
return useMutationWithInvalidate(
async (input: UpdateAccountNotificationsInput) => {
return useMutation({
mutationFn: async (input: UpdateAccountNotificationsInput) => {
invariant(user?.address, "walletAddress is required");
const res = await fetch(`${THIRDWEB_API_HOST}/v1/account/notifications`, {
@@ -544,14 +660,12 @@ export function useUpdateNotifications() {
return json.data;
},
{
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: accountKeys.me(user?.address as string),
});
},
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: accountKeys.me(user?.address as string),
});
},
);
});
}
export function useCreateBillingSession(enabled = false) {
@@ -588,8 +702,8 @@ export function useConfirmEmail() {
const { user } = useLoggedInUser();
const queryClient = useQueryClient();
return useMutationWithInvalidate(
async (input: ConfirmEmailInput) => {
return useMutation({
mutationFn: async (input: ConfirmEmailInput) => {
invariant(user?.address, "walletAddress is required");
const res = await fetch(`${THIRDWEB_API_HOST}/v1/account/confirmEmail`, {
@@ -608,31 +722,29 @@ export function useConfirmEmail() {
return json.data;
},
{
onSuccess: async () => {
// invalidate related cache, since could be relinking account
return Promise.all([
queryClient.invalidateQueries({
queryKey: apiKeys.keys(user?.address as string),
}),
queryClient.invalidateQueries({
queryKey: accountKeys.usage(user?.address as string),
}),
queryClient.invalidateQueries({
queryKey: accountKeys.me(user?.address as string),
}),
]);
},
onSuccess: async () => {
// invalidate related cache, since could be relinking account
return Promise.all([
queryClient.invalidateQueries({
queryKey: apiKeys.keys(user?.address as string),
}),
queryClient.invalidateQueries({
queryKey: accountKeys.usage(user?.address as string),
}),
queryClient.invalidateQueries({
queryKey: accountKeys.me(user?.address as string),
}),
]);
},
);
});
}
export function useResendEmailConfirmation() {
const { user } = useLoggedInUser();
const queryClient = useQueryClient();
return useMutationWithInvalidate(
async () => {
return useMutation({
mutationFn: async () => {
invariant(user?.address, "walletAddress is required");
const res = await fetch(
@@ -654,22 +766,20 @@ export function useResendEmailConfirmation() {
return json.data;
},
{
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: accountKeys.me(user?.address as string),
});
},
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: accountKeys.me(user?.address as string),
});
},
);
});
}
export function useCreatePaymentMethod() {
const { user } = useLoggedInUser();
const queryClient = useQueryClient();
return useMutationWithInvalidate(
async (paymentMethodId: string) => {
return useMutation({
mutationFn: async (paymentMethodId: string) => {
invariant(user?.address, "walletAddress is required");
const res = await fetch(`${THIRDWEB_API_HOST}/v1/account/paymentMethod`, {
@@ -690,14 +800,12 @@ export function useCreatePaymentMethod() {
return json.data;
},
{
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: accountKeys.me(user?.address as string),
});
},
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: accountKeys.me(user?.address as string),
});
},
);
});
}
export function useApiKeys() {
@@ -760,8 +868,8 @@ export function useUpdateApiKey() {
const { user } = useLoggedInUser();
const queryClient = useQueryClient();
return useMutationWithInvalidate(
async (input: UpdateKeyInput) => {
return useMutation({
mutationFn: async (input: UpdateKeyInput) => {
invariant(user?.address, "walletAddress is required");
const res = await fetch(`${THIRDWEB_API_HOST}/v1/keys/${input.id}`, {
@@ -781,22 +889,20 @@ export function useUpdateApiKey() {
return json.data;
},
{
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: apiKeys.keys(user?.address as string),
});
},
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: apiKeys.keys(user?.address as string),
});
},
);
});
}
export function useRevokeApiKey() {
const { user } = useLoggedInUser();
const queryClient = useQueryClient();
return useMutationWithInvalidate(
async (id: string) => {
return useMutation({
mutationFn: async (id: string) => {
invariant(user?.address, "walletAddress is required");
const res = await fetch(`${THIRDWEB_API_HOST}/v1/keys/${id}/revoke`, {
@@ -815,14 +921,12 @@ export function useRevokeApiKey() {
return json.data;
},
{
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: apiKeys.keys(user?.address as string),
});
},
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: apiKeys.keys(user?.address as string),
});
},
);
});
}
export const usePolicies = (serviceId?: string) => {
@@ -851,8 +955,11 @@ export const usePolicies = (serviceId?: string) => {
export const useUpdatePolicies = () => {
const queryClient = useQueryClient();
return useMutationWithInvalidate(
async (input: { serviceId: string; data: ApiKeyServicePolicy }) => {
return useMutation({
mutationFn: async (input: {
serviceId: string;
data: ApiKeyServicePolicy;
}) => {
const res = await fetch(`${THIRDWEB_API_HOST}/v1/policies`, {
method: "POST",
@@ -870,22 +977,20 @@ export const useUpdatePolicies = () => {
}
return json.data as ApiKeyServicePolicy;
},
{
onSuccess: (_, variables) => {
return queryClient.invalidateQueries({
queryKey: ["policies", variables.serviceId],
});
},
onSuccess: (_, variables) => {
return queryClient.invalidateQueries({
queryKey: ["policies", variables.serviceId],
});
},
);
});
};
export function useRevokeAuthorizedWallet() {
const { user } = useLoggedInUser();
const queryClient = useQueryClient();
return useMutationWithInvalidate(
async (variables: { authorizedWalletId: string }) => {
return useMutation({
mutationFn: async (variables: { authorizedWalletId: string }) => {
invariant(user?.address, "walletAddress is required");
const { authorizedWalletId } = variables;
@@ -909,16 +1014,12 @@ export function useRevokeAuthorizedWallet() {
return json.data;
},
{
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: authorizedWallets.authorizedWallets(
user?.address as string,
),
});
},
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: authorizedWallets.authorizedWallets(user?.address as string),
});
},
);
});
}
export function useAuthorizedWallets() {
@@ -14,41 +14,52 @@ import { getContractMetadata, name, symbol } from "thirdweb/extensions/common";
export function useDashboardContractMetadata(contract: ThirdwebContract) {
return useQuery({
queryKey: ["contract-metadata-header", contract.chain.id, contract.address],
queryFn: async () => {
const [contractMetadata, _name, _symbol, compilerMetadata] =
await Promise.all([
getContractMetadata({ contract }).catch(() => ({
image: "",
name: "",
symbol: "",
})),
name({ contract }).catch(() => ""),
symbol({ contract }).catch(() => ""),
getCompilerMetadata(contract).catch(() => undefined),
]);
/**
* Handle the case where the contract.thirdweb.com endpoint returns a very long name
* example url: https://contract.thirdweb.com/metadata/324/0x66E298335c5992d599132582De8eaAF75348e6e6
* In that case, we split the solidity name on ":" and take the second part
*/
if (compilerMetadata?.name.includes(":")) {
const _name = compilerMetadata.name.split(":")[1];
if (_name) {
compilerMetadata.name = compilerMetadata.name.split(":")[1];
}
}
const contractName =
contractMetadata?.name || _name || compilerMetadata?.name || "";
const contractSymbol = contractMetadata?.symbol || _symbol || "";
return {
name: contractName,
symbol: contractSymbol,
image: contractMetadata.image || "",
contractType: compilerMetadata?.name || "",
};
},
queryFn: () => fetchDashboardContractMetadata(contract),
});
}
type DashboardContractMetadata = {
name: string;
symbol: string;
image: string;
contractType: string;
};
export async function fetchDashboardContractMetadata(
contract: ThirdwebContract,
): Promise<DashboardContractMetadata> {
const [contractMetadata, _name, _symbol, compilerMetadata] =
await Promise.all([
getContractMetadata({ contract }).catch(() => ({
image: "",
name: "",
symbol: "",
})),
name({ contract }).catch(() => ""),
symbol({ contract }).catch(() => ""),
getCompilerMetadata(contract).catch(() => undefined),
]);
/**
* Handle the case where the contract.thirdweb.com endpoint returns a very long name
* example url: https://contract.thirdweb.com/metadata/324/0x66E298335c5992d599132582De8eaAF75348e6e6
* In that case, we split the solidity name on ":" and take the second part
*/
if (compilerMetadata?.name.includes(":")) {
const _name = compilerMetadata.name.split(":")[1];
if (_name) {
compilerMetadata.name = _name;
}
}
const contractName =
contractMetadata?.name || _name || compilerMetadata?.name || "";
const contractSymbol = contractMetadata?.symbol || _symbol || "";
return {
name: contractName,
symbol: contractSymbol,
image: contractMetadata.image || "",
contractType: compilerMetadata?.name || "",
};
}
@@ -1,11 +1,13 @@
"use client";
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";
import { engineKeys } from "../cache-keys";
import { useMutationWithInvalidate } from "./query/useQueryWithNetwork";
import { useLoggedInUser } from "./useLoggedInUser";
export type EngineTier = "STARTER" | "PREMIUM" | "ENTERPRISE";
@@ -17,7 +19,6 @@ export type EngineInstance = {
name: string;
url: string;
lastAccessedAt: string;
cloudDeployedAt?: string;
status:
| "active"
| "pending"
@@ -25,6 +26,7 @@ export type EngineInstance = {
| "deploying"
| "paymentFailed"
| "deploymentFailed";
deploymentId?: string;
};
// Not checking for null token because the token is required the tanstack useQuery hook
@@ -110,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(
@@ -137,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;
@@ -187,24 +207,25 @@ export function useEngineLatestVersion() {
}
interface UpdateVersionInput {
engineId: string;
deploymentId: string;
serverVersion: string;
}
export function useEngineUpdateVersion() {
export function useEngineUpdateServerVersion() {
return useMutation({
mutationFn: async (input: UpdateVersionInput) => {
invariant(input.engineId, "engineId is required");
const res = await fetch(`${THIRDWEB_API_HOST}/v1/engine/update-version`, {
method: "POST",
headers: {
"Content-Type": "application/json",
const res = await fetch(
`${THIRDWEB_API_HOST}/v2/engine/deployments/${input.deploymentId}/infrastructure`,
{
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
serverVersion: input.serverVersion,
}),
},
body: JSON.stringify({
engineId: input.engineId,
}),
});
);
// we never use the response body
res.body?.cancel();
if (!res.ok) {
@@ -240,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",
},
@@ -397,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`, {
@@ -428,8 +441,7 @@ export function useEngineWalletConfig(instance: string) {
});
const json = await res.json();
return (json.result as WalletConfig) || {};
return json.result;
},
enabled: !!instance && !!token,
});
@@ -570,8 +582,8 @@ export function useEngineAddKeypair(instance: string) {
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
async (input: AddKeypairInput) => {
return useMutation({
mutationFn: async (input: AddKeypairInput) => {
invariant(instance, "instance is required");
const res = await fetch(`${instance}auth/keypair/add`, {
@@ -587,14 +599,12 @@ export function useEngineAddKeypair(instance: string) {
return json.result;
},
{
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.keypairs(instance),
});
},
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.keypairs(instance),
});
},
);
});
}
type RemoveKeypairInput = {
@@ -605,8 +615,8 @@ export function useEngineRemoveKeypair(instance: string) {
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
async (input: RemoveKeypairInput) => {
return useMutation({
mutationFn: async (input: RemoveKeypairInput) => {
invariant(instance, "instance is required");
const res = await fetch(`${instance}auth/keypair/remove`, {
@@ -622,14 +632,12 @@ export function useEngineRemoveKeypair(instance: string) {
return json.result;
},
{
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.keypairs(instance),
});
},
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.keypairs(instance),
});
},
);
});
}
export type EngineRelayer = {
@@ -672,8 +680,8 @@ export function useEngineCreateRelayer(instance: string) {
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
async (input: CreateRelayerInput) => {
return useMutation({
mutationFn: async (input: CreateRelayerInput) => {
invariant(instance, "instance is required");
const res = await fetch(`${instance}relayer/create`, {
@@ -689,14 +697,12 @@ export function useEngineCreateRelayer(instance: string) {
return json.result;
},
{
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.relayers(instance),
});
},
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.relayers(instance),
});
},
);
});
}
type RevokeRelayerInput = {
@@ -707,8 +713,8 @@ export function useEngineRevokeRelayer(instance: string) {
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
async (input: RevokeRelayerInput) => {
return useMutation({
mutationFn: async (input: RevokeRelayerInput) => {
invariant(instance, "instance is required");
const res = await fetch(`${instance}relayer/revoke`, {
@@ -724,14 +730,12 @@ export function useEngineRevokeRelayer(instance: string) {
return json.result;
},
{
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.relayers(instance),
});
},
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.relayers(instance),
});
},
);
});
}
export type UpdateRelayerInput = {
@@ -747,8 +751,8 @@ export function useEngineUpdateRelayer(instance: string) {
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
async (input: UpdateRelayerInput) => {
return useMutation({
mutationFn: async (input: UpdateRelayerInput) => {
invariant(instance, "instance is required");
const res = await fetch(`${instance}relayer/update`, {
@@ -764,14 +768,12 @@ export function useEngineUpdateRelayer(instance: string) {
return json.result;
},
{
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.relayers(instance),
});
},
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.relayers(instance),
});
},
);
});
}
export interface EngineWebhook {
@@ -805,9 +807,6 @@ export function useEngineWebhooks(instance: string) {
// POST REQUESTS
export type SetWalletConfigInput =
| {
type: "local";
}
| {
type: "aws-kms";
awsAccessKeyId: string;
@@ -827,8 +826,8 @@ export function useEngineSetWalletConfig(instance: string) {
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
async (input: SetWalletConfigInput) => {
return useMutation<WalletConfigResponse, void, SetWalletConfigInput>({
mutationFn: async (input) => {
invariant(instance, "instance is required");
const res = await fetch(`${instance}configuration/wallets`, {
@@ -844,17 +843,16 @@ export function useEngineSetWalletConfig(instance: string) {
return json.result;
},
{
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.walletConfig(instance),
});
},
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.walletConfig(instance),
});
},
);
});
}
export type CreateBackendWalletInput = {
type: EngineBackendWalletType;
label?: string;
};
@@ -862,8 +860,8 @@ export function useEngineCreateBackendWallet(instance: string) {
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
async (input: CreateBackendWalletInput) => {
return useMutation({
mutationFn: async (input: CreateBackendWalletInput) => {
invariant(instance, "instance is required");
const res = await fetch(`${instance}backend-wallet/create`, {
@@ -879,14 +877,12 @@ export function useEngineCreateBackendWallet(instance: string) {
return json.result;
},
{
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.backendWallets(instance),
});
},
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.backendWallets(instance),
});
},
);
});
}
interface UpdateBackendWalletInput {
@@ -898,8 +894,8 @@ export function useEngineUpdateBackendWallet(instance: string) {
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
async (input: UpdateBackendWalletInput) => {
return useMutation({
mutationFn: async (input: UpdateBackendWalletInput) => {
invariant(instance, "instance is required");
const res = await fetch(`${instance}backend-wallet/update`, {
@@ -915,42 +911,35 @@ export function useEngineUpdateBackendWallet(instance: string) {
return json.result;
},
{
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.backendWallets(instance),
});
},
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.backendWallets(instance),
});
},
);
});
}
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;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
async (input: ImportBackendWalletInput) => {
return useMutation({
mutationFn: async (input: ImportBackendWalletInput) => {
invariant(instance, "instance is required");
const res = await fetch(`${instance}backend-wallet/import`, {
@@ -966,22 +955,20 @@ export function useEngineImportBackendWallet(instance: string) {
return json.result;
},
{
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.backendWallets(instance),
});
},
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.backendWallets(instance),
});
},
);
});
}
export function useEngineGrantPermissions(instance: string) {
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
async (input: EngineAdmin) => {
return useMutation({
mutationFn: async (input: EngineAdmin) => {
invariant(instance, "instance is required");
const res = await fetch(`${instance}auth/permissions/grant`, {
@@ -997,14 +984,12 @@ export function useEngineGrantPermissions(instance: string) {
return json.result;
},
{
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.permissions(instance),
});
},
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.permissions(instance),
});
},
);
});
}
type RevokePermissionsInput = {
@@ -1015,8 +1000,8 @@ export function useEngineRevokePermissions(instance: string) {
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
async (input: RevokePermissionsInput) => {
return useMutation({
mutationFn: async (input: RevokePermissionsInput) => {
invariant(instance, "instance is required");
const res = await fetch(`${instance}auth/permissions/revoke`, {
@@ -1032,14 +1017,12 @@ export function useEngineRevokePermissions(instance: string) {
return json.result;
},
{
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.permissions(instance),
});
},
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.permissions(instance),
});
},
);
});
}
type CreateAccessTokenResponse = AccessToken & {
@@ -1050,8 +1033,8 @@ export function useEngineCreateAccessToken(instance: string) {
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
async () => {
return useMutation({
mutationFn: async () => {
invariant(instance, "instance is required");
const res = await fetch(`${instance}auth/access-tokens/create`, {
@@ -1067,14 +1050,12 @@ export function useEngineCreateAccessToken(instance: string) {
return json.result as CreateAccessTokenResponse;
},
{
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.accessTokens(instance),
});
},
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.accessTokens(instance),
});
},
);
});
}
type RevokeAccessTokenInput = {
@@ -1085,8 +1066,8 @@ export function useEngineRevokeAccessToken(instance: string) {
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
async (input: RevokeAccessTokenInput) => {
return useMutation({
mutationFn: async (input: RevokeAccessTokenInput) => {
invariant(instance, "instance is required");
const res = await fetch(`${instance}auth/access-tokens/revoke`, {
@@ -1102,14 +1083,12 @@ export function useEngineRevokeAccessToken(instance: string) {
return json.result;
},
{
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.accessTokens(instance),
});
},
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.accessTokens(instance),
});
},
);
});
}
type UpdateAccessTokenInput = {
@@ -1121,8 +1100,8 @@ export function useEngineUpdateAccessToken(instance: string) {
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
async (input: UpdateAccessTokenInput) => {
return useMutation({
mutationFn: async (input: UpdateAccessTokenInput) => {
invariant(instance, "instance is required");
const res = await fetch(`${instance}auth/access-tokens/update`, {
@@ -1138,14 +1117,12 @@ export function useEngineUpdateAccessToken(instance: string) {
return json.result;
},
{
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.accessTokens(instance),
});
},
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.accessTokens(instance),
});
},
);
});
}
export type CreateWebhookInput = {
@@ -1158,8 +1135,8 @@ export function useEngineCreateWebhook(instance: string) {
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
async (input: CreateWebhookInput) => {
return useMutation({
mutationFn: async (input: CreateWebhookInput) => {
invariant(instance, "instance is required");
const res = await fetch(`${instance}webhooks/create`, {
@@ -1175,14 +1152,12 @@ export function useEngineCreateWebhook(instance: string) {
return json.result;
},
{
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.webhooks(instance),
});
},
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.webhooks(instance),
});
},
);
});
}
type RevokeWebhookInput = {
@@ -1193,8 +1168,8 @@ export function useEngineRevokeWebhook(instance: string) {
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
async (input: RevokeWebhookInput) => {
return useMutation({
mutationFn: async (input: RevokeWebhookInput) => {
invariant(instance, "instance is required");
const res = await fetch(`${instance}webhooks/revoke`, {
@@ -1210,14 +1185,12 @@ export function useEngineRevokeWebhook(instance: string) {
return json.result;
},
{
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.webhooks(instance),
});
},
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.webhooks(instance),
});
},
);
});
}
type SendTokensInput = {
@@ -1659,14 +1632,17 @@ export function useEngineCreateNotificationChannel(engineId: string) {
const { isLoggedIn } = useLoggedInUser();
const queryClient = useQueryClient();
return useMutationWithInvalidate(
async (input: CreateNotificationChannelInput) => {
return useMutation({
mutationFn: async (input: CreateNotificationChannelInput) => {
invariant(isLoggedIn, "Must be logged in.");
const res = await fetch(
`${THIRDWEB_API_HOST}/v1/engine/${engineId}/notification-channels`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(input),
},
);
@@ -1677,39 +1653,37 @@ export function useEngineCreateNotificationChannel(engineId: string) {
const json = await res.json();
return json.data as EngineNotificationChannel;
},
{
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.notificationChannels(engineId),
});
},
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.notificationChannels(engineId),
});
},
);
});
}
export function useEngineDeleteNotificationChannel(engineId: string) {
const { isLoggedIn } = useLoggedInUser();
const queryClient = useQueryClient();
return useMutationWithInvalidate(
async (notificationChannelId: string) => {
return useMutation({
mutationFn: async (notificationChannelId: string) => {
invariant(isLoggedIn, "Must be logged in.");
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()}`);
}
res.body?.cancel();
},
{
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.notificationChannels(engineId),
});
},
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.notificationChannels(engineId),
});
},
);
});
}
@@ -1,3 +1,5 @@
"use client";
import { isLoginRequired } from "@/constants/auth";
import { useDashboardRouter } from "@/lib/DashboardRouter";
import { useQuery } from "@tanstack/react-query";
@@ -54,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);
}
@@ -74,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") {
@@ -133,3 +141,7 @@ export function useLoggedInUser(): {
: null,
};
}
function buildLoginPath(pathname: string | undefined): string {
return `/login${pathname ? `?next=${encodeURIComponent(pathname)}` : ""}`;
}
@@ -1,17 +1,18 @@
import { useQuery } from "@tanstack/react-query";
import type { WalletNFTApiReturn } from "pages/api/wallet/nfts/[chainId]";
import { useQueryWithNetwork } from "./query/useQueryWithNetwork";
export function useWalletNFTs(walletAddress?: string, chainId?: number) {
return useQueryWithNetwork(
["walletNfts", walletAddress],
async () => {
export function useWalletNFTs(params: {
chainId: number;
walletAddress?: string;
}) {
return useQuery({
queryKey: ["walletNfts", params.chainId, params.walletAddress],
queryFn: async () => {
const response = await fetch(
`/api/wallet/nfts/${chainId}?owner=${walletAddress}`,
`/api/wallet/nfts/${params.chainId}?owner=${params.walletAddress}`,
);
return (await response.json()) as WalletNFTApiReturn;
},
{
enabled: !!walletAddress && !!chainId,
},
);
enabled: !!params.walletAddress,
});
}
@@ -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,12 +36,18 @@ 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,
}: {
chain: ChainMetadata;
amount: string;
amount: number;
}) {
const client = useThirdwebClient();
const address = useActiveAccount()?.address;
@@ -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">
@@ -1,16 +1,16 @@
import type { ChainMetadata } from "thirdweb/chains";
import { getFaucetClaimAmount } from "../../../../../../api/testnet-faucet/claim/claim-amount";
import { ChainIcon } from "../../../../components/server/chain-icon";
import { FaucetButton } from "../client/FaucetButton";
import { GiftIcon } from "../icons/GiftIcon";
import { SectionTitle } from "./SectionTitle";
const amountToGive = "0.01";
export async function FaucetSection(props: { chain: ChainMetadata }) {
const { chain } = props;
// Check eligibilty.
const sanitizedChainName = chain.name.replace("Mainnet", "").trim();
const amountToGive = getFaucetClaimAmount(props.chain.chainId);
return (
<section>
@@ -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",
}}
/>
)}
@@ -1,8 +1,9 @@
import { useEVMContractInfo } from "@3rdweb-sdk/react";
import { Stack } from "@chakra-ui/react";
"use client";
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";
@@ -19,19 +20,16 @@ export const CancelTab: React.FC<CancelTabProps> = ({
isAuction,
}) => {
const trackEvent = useTrack();
const network = useEVMContractInfo()?.chain;
const { idToChain } = useAllChainsData();
const network = idToChain.get(contract.chain.id);
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 (
<Stack pt={3} gap={3}>
{/* maybe some text? */}
<div className="flex flex-col gap-3 pt-3">
<TransactionButton
txChainID={contract.chain.id}
transactionCount={1}
isLoading={cancelQuery.isPending}
onClick={() => {
@@ -40,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",
@@ -48,7 +46,6 @@ export const CancelTab: React.FC<CancelTabProps> = ({
label: "success",
network,
});
onSuccess();
},
onError: (error) => {
trackEvent({
@@ -58,15 +55,20 @@ 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>
</Stack>
</div>
);
};
@@ -1,12 +1,14 @@
"use client";
import { ListerOnly } from "@3rdweb-sdk/react/components/roles/lister-only";
import { Icon, useDisclosure } from "@chakra-ui/react";
import { useDisclosure } from "@chakra-ui/react";
import { TransactionButton } from "components/buttons/TransactionButton";
import { PlusIcon } from "lucide-react";
import { useState } from "react";
import { FiPlus } from "react-icons/fi";
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";
@@ -47,6 +49,7 @@ export const CreateListingButton: React.FC<CreateListingButtonProps> = ({
Cancel
</Button>
<TransactionButton
txChainID={contract.chain.id}
isLoading={isFormLoading}
transactionCount={2}
form={LIST_FORM_ID}
@@ -68,7 +71,7 @@ export const CreateListingButton: React.FC<CreateListingButtonProps> = ({
</Drawer>
<Button
colorScheme="primary"
leftIcon={<Icon as={FiPlus} />}
leftIcon={<PlusIcon className="size-5" />}
{...restButtonProps}
onClick={onOpen}
isDisabled={!address}
@@ -1,31 +1,29 @@
import { Alert, AlertTitle } from "@/components/ui/alert";
import { useDashboardEVMChainId, useEVMContractInfo } from "@3rdweb-sdk/react";
import { Card } from "@/components/ui/card";
import { useDashboardOwnedNFTs } from "@3rdweb-sdk/react/hooks/useDashboardOwnedNFTs";
import { useWalletNFTs } from "@3rdweb-sdk/react/hooks/useWalletNFTs";
import {
Box,
Flex,
FormControl,
Icon,
Input,
Select,
Spinner,
Stack,
Tooltip,
useModalContext,
} from "@chakra-ui/react";
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";
import { isSimpleHashSupported } from "lib/wallet/nfts/simpleHash";
import type { WalletNFT } from "lib/wallet/nfts/types";
import { CircleAlertIcon } from "lucide-react";
import { CircleAlertIcon, InfoIcon } from "lucide-react";
import { useMemo } from "react";
import { useForm } from "react-hook-form";
import { FiInfo } from "react-icons/fi";
import { toast } from "sonner";
import {
NATIVE_TOKEN_ADDRESS,
@@ -58,7 +56,7 @@ import {
Text,
} from "tw-components";
import { NFTMediaWithEmptyState } from "tw-components/nft-media";
import { ListLabel } from "./list-label";
import { shortenIfAddress } from "utils/usedapp-external";
type ListForm =
| (Omit<CreateListingParams, "quantity" | "currencyContractAddress"> & {
@@ -103,8 +101,10 @@ export const CreateListingsForm: React.FC<CreateListingsFormProps> = ({
setIsFormLoading,
}) => {
const trackEvent = useTrack();
const network = useEVMContractInfo()?.chain;
const chainId = useDashboardEVMChainId();
const chainId = contract.chain.id;
const { idToChain } = useAllChainsData();
const network = idToChain.get(chainId);
const isSupportedChain =
chainId &&
(isSimpleHashSupported(chainId) ||
@@ -113,10 +113,10 @@ export const CreateListingsForm: React.FC<CreateListingsFormProps> = ({
const account = useActiveAccount();
const { data: walletNFTs, isPending: isWalletNFTsLoading } = useWalletNFTs(
account?.address,
const { data: walletNFTs, isPending: isWalletNFTsLoading } = useWalletNFTs({
chainId,
);
walletAddress: account?.address,
});
const sendAndConfirmTx = useSendAndConfirmTransaction();
const form = useForm<ListForm>({
@@ -211,9 +211,8 @@ export const CreateListingsForm: React.FC<CreateListingsFormProps> = ({
);
return (
<Stack
spacing={6}
as="form"
<form
className="flex flex-col gap-6"
id={formId}
onSubmit={form.handleSubmit(async (formData) => {
if (!formData.selected || !selectedContract) {
@@ -363,31 +362,13 @@ export const CreateListingsForm: React.FC<CreateListingsFormProps> = ({
</FormHelperText>
{!isSupportedChain ? (
<Flex flexDir="column" gap={4} mb={4}>
<Stack
direction="row"
bg="orange.50"
borderRadius="md"
borderWidth="1px"
borderColor="orange.100"
align="center"
padding="10px"
spacing={3}
_dark={{
bg: "orange.300",
borderColor: "orange.300",
}}
>
<Icon
as={FiInfo}
color="orange.400"
_dark={{ color: "orange.900" }}
boxSize={6}
/>
<div className="flex flex-row items-center gap-3 rounded-md border border-border border-orange-100 bg-orange-50 p-[10px] dark:border-orange-300 dark:bg-orange-300">
<InfoIcon className="size-6 text-orange-400 dark:text-orange-900" />
<Text color="orange.800" _dark={{ color: "orange.900" }}>
This chain is not supported by our NFT API yet, please enter the
contract address of the NFT you want to list.
</Text>
</Stack>
</div>
<FormControl
isInvalid={!!form.formState.errors.selected?.contractAddress}
>
@@ -428,7 +409,25 @@ export const CreateListingsForm: React.FC<CreateListingsFormProps> = ({
shouldWrapChildren
placement="left-end"
key={nft.contractAddress + nft.id}
label={<ListLabel nft={nft} />}
label={
<Card className="p-4">
<ul>
<li>
<strong>Name:</strong> {nft.metadata?.name || "N/A"}
</li>
<li>
<strong>Contract Address:</strong>{" "}
{shortenIfAddress(nft.contractAddress)}
</li>
<li>
<strong>Token ID: </strong> {nft.id.toString()}
</li>
<li>
<strong>Token Standard: </strong> {nft.type}
</li>
</ul>
</Card>
}
>
<Box
borderRadius="lg"
@@ -454,26 +453,8 @@ export const CreateListingsForm: React.FC<CreateListingsFormProps> = ({
})}
</Flex>
) : nfts && nfts.length === 0 ? (
<Stack
direction="row"
bg="orange.50"
borderRadius="md"
borderWidth="1px"
borderColor="orange.100"
align="center"
padding="10px"
spacing={3}
_dark={{
bg: "orange.300",
borderColor: "orange.300",
}}
>
<Icon
as={FiInfo}
color="orange.400"
_dark={{ color: "orange.900" }}
boxSize={6}
/>
<div className="flex flex-row items-center gap-3 rounded-md border border-border border-orange-100 bg-orange-50 p-[10px] dark:border-orange-300 dark:bg-orange-300">
<InfoIcon className="size-6 text-orange-400 dark:text-orange-900" />
<Text color="orange.800" _dark={{ color: "orange.900" }}>
There are no NFTs owned by this wallet. You need NFTs to create a
listing. You can create NFTs with thirdweb.{" "}
@@ -482,7 +463,7 @@ export const CreateListingsForm: React.FC<CreateListingsFormProps> = ({
</Link>
.
</Text>
</Stack>
</div>
) : null}
</FormControl>
<FormControl isRequired isDisabled={noNfts}>
@@ -490,6 +471,7 @@ export const CreateListingsForm: React.FC<CreateListingsFormProps> = ({
Listing Currency
</Heading>
<CurrencySelector
contractChainId={chainId}
value={form.watch("currencyContractAddress")}
onChange={(e) =>
form.setValue("currencyContractAddress", e.target.value)
@@ -514,11 +496,11 @@ export const CreateListingsForm: React.FC<CreateListingsFormProps> = ({
</FormControl>
{form.watch("selected")?.type?.toLowerCase() !== "erc721" && (
<FormControl isRequired isDisabled={noNfts}>
<Stack justify="space-between" direction="row">
<div className="flex flex-row justify-between gap-2">
<Heading as={FormLabel} size="label.lg">
Quantity
</Heading>
</Stack>
</div>
<Input {...form.register("quantity")} />
<FormHelperText>
The number of tokens to list for sale.
@@ -558,6 +540,6 @@ export const CreateListingsForm: React.FC<CreateListingsFormProps> = ({
<AlertTitle>No NFT selected</AlertTitle>
</Alert>
)}
</Stack>
</form>
);
};
@@ -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>
);
};
@@ -2,7 +2,6 @@ import { WalletAddress } from "@/components/blocks/wallet-address";
import {
ButtonGroup,
Flex,
Icon,
IconButton,
Select,
Skeleton,
@@ -18,7 +17,13 @@ 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,
ChevronLeftIcon,
ChevronRightIcon,
MoveRightIcon,
} from "lucide-react";
import {
type Dispatch,
type SetStateAction,
@@ -26,13 +31,6 @@ import {
useMemo,
useState,
} from "react";
import { FiArrowRight } from "react-icons/fi";
import {
MdFirstPage,
MdLastPage,
MdNavigateBefore,
MdNavigateNext,
} from "react-icons/md";
import { type Cell, type Column, usePagination, useTable } from "react-table";
import type { ThirdwebContract } from "thirdweb";
import type {
@@ -41,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>[] = [
@@ -101,7 +100,6 @@ interface MarketplaceTableProps {
start: number;
}>
>;
type: "direct-listings" | "english-auctions";
}
const DEFAULT_QUERY_STATE = { count: 50, start: 0 };
@@ -113,7 +111,6 @@ export const MarketplaceTable: React.FC<MarketplaceTableProps> = ({
totalCountQuery,
queryParams,
setQueryParams,
type,
}) => {
const [listingsToShow, setListingsToShow_] = useState<"all" | "valid">("all");
@@ -216,7 +213,6 @@ export const MarketplaceTable: React.FC<MarketplaceTableProps> = ({
data={tokenRow}
isOpen={!!tokenRow}
onClose={() => setTokenRow(null)}
type={type}
/>
<Table {...getTableProps()}>
<Thead>
@@ -268,7 +264,7 @@ export const MarketplaceTable: React.FC<MarketplaceTableProps> = ({
</Td>
))}
<Td borderBottomWidth="inherit" borderColor="borderColor">
<Icon as={FiArrowRight} />
<MoveRightIcon className="size-3" />
</Td>
</Tr>
);
@@ -281,13 +277,13 @@ export const MarketplaceTable: React.FC<MarketplaceTableProps> = ({
<IconButton
isDisabled={!canPreviousPage || totalCountQuery.isPending}
aria-label="first page"
icon={<Icon as={MdFirstPage} />}
icon={<ChevronFirstIcon className="size-4" />}
onClick={() => gotoPage(0)}
/>
<IconButton
isDisabled={!canPreviousPage || totalCountQuery.isPending}
aria-label="previous page"
icon={<Icon as={MdNavigateBefore} />}
icon={<ChevronLeftIcon className="size-4" />}
onClick={() => previousPage()}
/>
<Text whiteSpace="nowrap">
@@ -303,13 +299,13 @@ export const MarketplaceTable: React.FC<MarketplaceTableProps> = ({
<IconButton
isDisabled={!canNextPage || totalCountQuery.isPending}
aria-label="next page"
icon={<Icon as={MdNavigateNext} />}
icon={<ChevronRightIcon className="size-4" />}
onClick={() => nextPage()}
/>
<IconButton
isDisabled={!canNextPage || totalCountQuery.isPending}
aria-label="last page"
icon={<Icon as={MdLastPage} />}
icon={<ChevronLastIcon className="size-4" />}
onClick={() => gotoPage(pageCount - 1)}
/>
@@ -1,6 +1,8 @@
"use client";
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,4 +1,5 @@
import { MarketplaceTable } from "contract-ui/tabs/shared-components/marketplace-table";
"use client";
import { useState } from "react";
import type { ThirdwebContract } from "thirdweb";
import {
@@ -7,6 +8,7 @@ import {
totalListings,
} from "thirdweb/extensions/marketplace";
import { useReadContract } from "thirdweb/react";
import { MarketplaceTable } from "../../components/marketplace-table";
interface DirectListingsTableProps {
contract: ThirdwebContract;
@@ -38,7 +40,6 @@ export const DirectListingsTable: React.FC<DirectListingsTableProps> = ({
totalCountQuery={totalCountQuery}
queryParams={queryParams}
setQueryParams={setQueryParams}
type="direct-listings"
/>
);
};
@@ -0,0 +1,27 @@
import { notFound, redirect } from "next/navigation";
import { getContractPageParamsInfo } from "../../_utils/getContractFromParams";
import { getContractPageMetadata } from "../../_utils/getContractPageMetadata";
import { ContractDirectListingsPage } from "./ContractDirectListingsPage";
export default async function Page(props: {
params: {
contractAddress: string;
chain_id: string;
};
}) {
const info = await getContractPageParamsInfo(props.params);
if (!info) {
notFound();
}
const { isDirectListingSupported } = await getContractPageMetadata(
info.contract,
);
if (!isDirectListingSupported) {
redirect(`/${props.params.chain_id}/${props.params.contractAddress}`);
}
return <ContractDirectListingsPage contract={info.contract} />;
}
@@ -1,6 +1,8 @@
"use client";
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,4 +1,5 @@
import { MarketplaceTable } from "contract-ui/tabs/shared-components/marketplace-table";
"use client";
import { useState } from "react";
import type { ThirdwebContract } from "thirdweb";
import {
@@ -7,6 +8,7 @@ import {
totalAuctions,
} from "thirdweb/extensions/marketplace";
import { useReadContract } from "thirdweb/react";
import { MarketplaceTable } from "../../components/marketplace-table";
interface EnglishAuctionsTableProps {
contract: ThirdwebContract;
@@ -38,7 +40,6 @@ export const EnglishAuctionsTable: React.FC<EnglishAuctionsTableProps> = ({
totalCountQuery={totalCountQuery}
queryParams={queryParams}
setQueryParams={setQueryParams}
type="english-auctions"
/>
);
};
@@ -0,0 +1,27 @@
import { notFound, redirect } from "next/navigation";
import { getContractPageParamsInfo } from "../../_utils/getContractFromParams";
import { getContractPageMetadata } from "../../_utils/getContractPageMetadata";
import { ContractEnglishAuctionsPage } from "./ContractEnglishAuctionsPage";
export default async function Page(props: {
params: {
contractAddress: string;
chain_id: string;
};
}) {
const info = await getContractPageParamsInfo(props.params);
if (!info) {
notFound();
}
const { isEnglishAuctionSupported } = await getContractPageMetadata(
info.contract,
);
if (!isEnglishAuctionSupported) {
redirect(`/${props.params.chain_id}/${props.params.contractAddress}`);
}
return <ContractEnglishAuctionsPage contract={info.contract} />;
}
@@ -0,0 +1,68 @@
"use client";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import { Button } from "@/components/ui/button";
import { CheckIcon, CircleAlertIcon, RotateCcwIcon } from "lucide-react";
import { useState } from "react";
import { ConfigureNetworks } from "../../../../../components/configure-networks/ConfigureNetworks";
import { addChainOverrides } from "../../../../../stores/chainStores";
export function ConfigureCustomChain(props: {
chainSlug: string;
}) {
const { chainSlug } = props;
const isSlugNumber = Number.isInteger(Number.parseInt(chainSlug));
const [isConfigured, setIsConfigured] = useState(false);
if (isConfigured) {
return (
<div className="mx-auto max-w-[600px] py-10">
<Alert variant="info">
<CheckIcon className="size-5" />
<AlertTitle>Network Configured Successfully</AlertTitle>
</Alert>
<div className="h-6" />
<Button
onClick={() => window.location.reload()}
className="w-full gap-2"
>
<RotateCcwIcon className="size-4" />
Reload Page to Continue
</Button>
</div>
);
}
return (
<div className="mx-auto max-w-[600px] py-10">
<Alert variant="warning">
<CircleAlertIcon className="size-5" />
<AlertTitle>
No Chain found with {isSlugNumber ? "chain ID" : "slug"}{" "}
{`"${chainSlug}"`}
</AlertTitle>
<AlertDescription>
Configure a chain with {isSlugNumber ? "chain ID" : "slug"}{" "}
{`"${chainSlug}"`} to continue
</AlertDescription>
</Alert>
<div className="h-6" />
<div className="rounded-lg border border-border">
<ConfigureNetworks
prefillSlug={isSlugNumber ? undefined : chainSlug}
prefillChainId={isSlugNumber ? chainSlug : undefined}
onNetworkAdded={(network) => {
if (
chainSlug === network.slug ||
chainSlug === `${network.chainId}`
) {
addChainOverrides(network);
setIsConfigured(true);
}
}}
editChain={undefined}
/>
</div>
</div>
);
}
@@ -8,13 +8,7 @@ import {
} from "@chakra-ui/react";
import { useMemo } from "react";
import { type NFT, ZERO_ADDRESS } from "thirdweb";
import {
Card,
Heading,
Text,
TrackedLink,
type TrackedLinkProps,
} from "tw-components";
import { Card, TrackedLink, type TrackedLinkProps } from "tw-components";
import { NFTMediaWithEmptyState } from "tw-components/nft-media";
type NFTWithContract = NFT & { contractAddress: string; chainId: number };
@@ -83,18 +77,20 @@ export const NFTCards: React.FC<NFTCardsProps> = ({
/>
</Skeleton>
</div>
<Flex p={4} pb={3} gap={3} direction="column">
<Flex p={4} pb={3} gap={1} direction="column">
<Skeleton w={!isPending ? "100%" : "50%"} isLoaded={!isPending}>
<Heading size="label.md">{token.metadata.name}</Heading>
<h2 className="font-semibold tracking-tight">
{token.metadata.name}
</h2>
</Skeleton>
<SkeletonText isLoaded={!isPending}>
<Text noOfLines={3}>
<p className="line-clamp-3 text-muted-foreground text-sm">
{token.metadata.description ? (
token.metadata.description
) : (
<i>No description</i>
)}
</Text>
</p>
</SkeletonText>
</Flex>
</Card>
@@ -8,7 +8,9 @@ import { CustomFormControl } from "../common";
/**
* Allows the user to select how much they want to charge to claim each NFT
*/
export const ClaimPriceInput = () => {
export const ClaimPriceInput = (props: {
contractChainId: number;
}) => {
const {
formDisabled,
isErc20,
@@ -43,6 +45,7 @@ export const ClaimPriceInput = () => {
</Box>
<Box w={{ base: "100%", md: isColumn ? "50%" : "100%" }}>
<CurrencySelector
contractChainId={props.contractChainId}
isDisabled={formDisabled}
value={field?.currencyAddress || NATIVE_TOKEN_ADDRESS}
onChange={(e) =>
@@ -1,6 +1,5 @@
import { Box, Flex, Icon, Select } from "@chakra-ui/react";
import { BsCircleFill } from "react-icons/bs";
import { FiUpload } from "react-icons/fi";
import { Box, Flex, Select } from "@chakra-ui/react";
import { UploadIcon } from "lucide-react";
import { Button, Text } from "tw-components";
import { useClaimConditionsFormContext } from "..";
import { CustomFormControl } from "../common";
@@ -120,7 +119,7 @@ export const ClaimerSelection = () => {
isDisabled={disabledSnapshotButton}
borderRadius="md"
onClick={() => setOpenIndex(phaseIndex)}
rightIcon={<Icon as={FiUpload} />}
rightIcon={<UploadIcon className="size-4" />}
>
{isAdmin ? "Edit" : "See"} Claimer Snapshot
</Button>
@@ -137,8 +136,8 @@ export const ClaimerSelection = () => {
}}
ml={2}
>
<Icon as={BsCircleFill} boxSize={2} />
<Text size="body.sm" color="inherit">
●{" "}
<strong>
{field.snapshot?.length} address
{field.snapshot?.length === 1 ? "" : "es"}
@@ -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;
@@ -1,3 +1,6 @@
"use client";
import { Spinner } from "@/components/ui/Spinner/Spinner";
import { ToolTipLabel } from "@/components/ui/tooltip";
import { AdminOnly } from "@3rdweb-sdk/react/components/roles/admin-only";
import { useIsAdmin } from "@3rdweb-sdk/react/hooks/useContractRoles";
@@ -8,17 +11,14 @@ import {
AlertTitle,
Box,
Flex,
Icon,
Menu,
MenuButton,
MenuList,
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 } from "lucide-react";
import { CircleHelpIcon, PlusIcon } from "lucide-react";
import { Fragment, createContext, useContext, useMemo, useState } from "react";
import {
type UseFieldArrayReturn,
@@ -26,7 +26,6 @@ import {
useFieldArray,
useForm,
} from "react-hook-form";
import { FiPlus } from "react-icons/fi";
import {
NATIVE_TOKEN_ADDRESS,
type ThirdwebContract,
@@ -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";
@@ -445,19 +445,16 @@ export const ClaimConditionsForm: React.FC<ClaimConditionsFormProps> = ({
};
}, [claimConditionsQuery.data, controlledFields, isMultiPhase]);
if (isFetchingData) {
return (
<div className="flex h-[400px] w-full items-center justify-center rounded-lg border border-border">
<Spinner className="size-10" />
</div>
);
}
return (
<>
{/* spinner */}
{isFetchingData && (
<Spinner
color="primary"
size="xs"
position="absolute"
top={2}
right={4}
/>
)}
<Flex onSubmit={handleFormSubmit} direction="column" as="form" gap={10}>
<Flex direction="column" gap={6}>
{/* Show the reason why the form is disabled */}
@@ -553,7 +550,7 @@ export const ClaimConditionsForm: React.FC<ClaimConditionsFormProps> = ({
<Flex
justifyContent="space-between"
flexDir={{ base: "column", md: isColumn ? "column" : "row" }}
flexDir={{ base: "column", md: "row" }}
gap={2}
>
<div className="flex flex-row gap-2">
@@ -565,7 +562,7 @@ export const ClaimConditionsForm: React.FC<ClaimConditionsFormProps> = ({
colorScheme="primary"
variant={phases?.length > 0 ? "outline" : "solid"}
borderRadius="md"
leftIcon={<Icon as={FiPlus} />}
leftIcon={<PlusIcon className="size-5" />}
isDisabled={
sendTx.isPending || (!isMultiPhase && phases?.length > 0)
}
@@ -631,6 +628,7 @@ export const ClaimConditionsForm: React.FC<ClaimConditionsFormProps> = ({
!isMultiPhase ? (
<TransactionButton
colorScheme="primary"
txChainID={contract.chain.id}
transactionCount={1}
isDisabled={claimConditionsQuery.isPending}
type="submit"
@@ -1,7 +1,6 @@
import { AdminOnly } from "@3rdweb-sdk/react/components/roles/admin-only";
import { Flex, Icon, SimpleGrid } from "@chakra-ui/react";
import { FiX } from "react-icons/fi";
import { RxCaretDown, RxCaretUp } from "react-icons/rx";
import { Flex, SimpleGrid } from "@chakra-ui/react";
import { ChevronDownIcon, ChevronUpIcon, XIcon } from "lucide-react";
import type { ThirdwebContract } from "thirdweb";
import { Badge, Button, Card, Heading, Text } from "tw-components";
import { ClaimConditionTypeData, useClaimConditionsFormContext } from ".";
@@ -57,10 +56,11 @@ export const ClaimConditionsPhase: React.FC<ClaimConditionsPhaseProps> = ({
onClick={toggleEditing}
size="sm"
rightIcon={
<Icon
as={field.isEditing ? RxCaretUp : RxCaretDown}
boxSize={5}
/>
field.isEditing ? (
<ChevronUpIcon className="size-4" />
) : (
<ChevronDownIcon className="size-4" />
)
}
>
{field.isEditing ? "Collapse" : isAdmin ? "Edit" : "See Phase"}
@@ -72,7 +72,7 @@ export const ClaimConditionsPhase: React.FC<ClaimConditionsPhaseProps> = ({
isDisabled={isPending}
colorScheme="red"
size="sm"
rightIcon={<Icon as={FiX} />}
rightIcon={<XIcon className="size-4" />}
>
Remove
</Button>
@@ -107,6 +107,7 @@ export const ClaimConditionsPhase: React.FC<ClaimConditionsPhaseProps> = ({
<PricePreview
price={field.price}
currencyAddress={field.currencyAddress}
contractChainId={contract.chain.id}
/>
<div className="flex flex-col">
<Text fontWeight="bold">Limit per wallet</Text>
@@ -137,7 +138,7 @@ export const ClaimConditionsPhase: React.FC<ClaimConditionsPhaseProps> = ({
<CustomFormGroup>
<MaxClaimableSupplyInput />
<ClaimPriceInput />
<ClaimPriceInput contractChainId={contract.chain.id} />
</CustomFormGroup>
{claimConditionType === "specific" ||
@@ -1,6 +1,7 @@
import { Flex, Stack } from "@chakra-ui/react";
"use client";
import { Flex } from "@chakra-ui/react";
import type { ThirdwebContract } from "thirdweb";
import { Heading, Text } from "tw-components";
import { ClaimConditionsForm } from "./claim-conditions-form/index";
interface ClaimConditionsProps {
@@ -16,24 +17,19 @@ export const ClaimConditions: React.FC<ClaimConditionsProps> = ({
isERC20,
}) => {
return (
<Stack spacing={8}>
<div className="flex w-full flex-col gap-8">
<Flex p={0} position="relative">
<Flex
pt={{ base: isColumn ? 0 : 6, md: 6 }}
direction="column"
gap={8}
w="full"
>
<Flex direction="column" gap={6} w="full">
{/* Info */}
<Flex as="section" direction="column" gap={4}>
<div className="flex flex-col">
<Heading size="title.md">Set Claim Conditions</Heading>
<Text size="body.md" fontStyle="italic" mt={2}>
Control when the {isERC20 ? "tokens" : "NFTs"} get dropped, how
much they cost, and more.
</Text>
</div>
</Flex>
<section>
<h2 className="mb-1 font-semibold text-xl tracking-tight">
Set Claim Conditions
</h2>
<p className="text-muted-foreground text-sm">
Control when the {isERC20 ? "tokens" : "NFTs"} get dropped, how
much they cost, and more.
</p>
</section>
{/* Set Claim Conditions */}
<ClaimConditionsForm
@@ -46,6 +42,6 @@ export const ClaimConditions: React.FC<ClaimConditionsProps> = ({
/>
</Flex>
</Flex>
</Stack>
</div>
);
};
@@ -1,24 +1,23 @@
import { useDashboardEVMChainId } from "@3rdweb-sdk/react";
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;
currencyAddress: string | undefined;
contractChainId: number;
}
export const PricePreview: React.FC<PricePreviewProps> = ({
price,
currencyAddress,
contractChainId,
}) => {
const chainId = useDashboardEVMChainId();
const { idToChain } = useAllChainsData();
const chain = chainId ? idToChain.get(chainId) : undefined;
const helperCurrencies = chainId ? CURRENCIES[chainId] || [] : [];
const chain = idToChain.get(contractChainId);
const helperCurrencies = CURRENCIES[contractChainId] || [];
const foundCurrency = helperCurrencies.find(
(currency) =>
@@ -1,3 +1,5 @@
"use client";
import { ToolTipLabel } from "@/components/ui/tooltip";
import { AdminOnly } from "@3rdweb-sdk/react/components/roles/admin-only";
import { TransactionButton } from "components/buttons/TransactionButton";
@@ -93,6 +95,7 @@ export const ResetClaimEligibility: React.FC<ResetClaimEligibilityProps> = ({
onClick={handleResetClaimEligibility}
loadingText="Resetting..."
size="sm"
txChainID={contract.chain.id}
>
Reset Eligibility
<ToolTipLabel
@@ -1,17 +1,15 @@
import { InlineCode } from "@/components/ui/inline-code";
import { useThirdwebClient } from "@/constants/thirdweb.client";
import { cn } from "@/lib/utils";
import {
Box,
Code,
Container,
Flex,
Icon,
IconButton,
Link,
ListItem,
Portal,
Select,
Stack,
Table,
TableContainer,
Tbody,
@@ -23,18 +21,18 @@ import {
UnorderedList,
} from "@chakra-ui/react";
import { Logo } from "components/logo";
import {
ChevronFirstIcon,
ChevronLastIcon,
ChevronLeftIcon,
ChevronRightIcon,
CircleAlertIcon,
DownloadIcon,
UploadIcon,
} from "lucide-react";
import Papa from "papaparse";
import { useCallback, useEffect, useRef, useState } from "react";
import { type DropzoneOptions, useDropzone } from "react-dropzone";
import { BsFillCloudUploadFill } from "react-icons/bs";
import { FiDownload } from "react-icons/fi";
import { IoAlertCircleOutline } from "react-icons/io5";
import {
MdFirstPage,
MdLastPage,
MdNavigateBefore,
MdNavigateNext,
} from "react-icons/md";
import { type Column, usePagination, useTable } from "react-table";
import { isAddress } from "thirdweb";
import { resolveAddress } from "thirdweb/extensions/ens";
@@ -235,12 +233,11 @@ export const SnapshotUpload: React.FC<SnapshotUploadProps> = ({
>
<input {...getInputProps()} />
<div className="!m-auto flex flex-col">
<Icon
as={BsFillCloudUploadFill}
boxSize={8}
mb={2}
color={noCsv ? "red.500" : "gray.600"}
mx="auto"
<UploadIcon
className={cn(
"mx-auto mb-2 size-8",
noCsv ? "text-red-500" : "text-gray-600",
)}
/>
{isDragActive ? (
<Heading as={Text} size="label.md">
@@ -260,37 +257,38 @@ export const SnapshotUpload: React.FC<SnapshotUploadProps> = ({
</div>
</div>
</div>
<div className="flex flex-row gap-2">
<div className="flex flex-col gap-2">
<Heading size="label.md">Requirements</Heading>
<UnorderedList spacing={1}>
{dropType === "specific" ? (
<>
<Text as={ListItem}>
Files <em>must</em> contain one .csv file with a list
of addresses and their <Code>maxClaimable</Code>.
(amount each wallet is allowed to claim)
of addresses and their{" "}
<InlineCode code="maxClaimable" />. (amount each
wallet is allowed to claim)
<br />
<Link
download
color="blue.500"
href="/snapshot-with-maxclaimable.csv"
>
<Icon boxSize="1em" as={FiDownload} /> Example
<DownloadIcon className="inline size-3" /> Example
snapshot
</Link>
</Text>
<Text as={ListItem}>
You may optionally add <Code>price</Code> and{" "}
<Code>currencyAddress</Code> overrides as well. This
lets you override the currency and price you would
like to charge per wallet you specified
You may optionally add <InlineCode code="price" /> and
<InlineCode code="currencyAddress" /> overrides as
well. This lets you override the currency and price
you would like to charge per wallet you specified
<br />
<Link
download
color="blue.500"
href="/snapshot-with-overrides.csv"
>
<Icon boxSize="1em" as={FiDownload} /> Example
<DownloadIcon className="inline size-3" /> Example
snapshot
</Link>
</Text>
@@ -302,12 +300,13 @@ export const SnapshotUpload: React.FC<SnapshotUploadProps> = ({
of addresses.
<br />
<Link download color="blue.500" href="/snapshot.csv">
<Icon boxSize="1em" as={FiDownload} /> Example
<DownloadIcon className="inline size-3" /> Example
snapshot
</Link>
</Text>
<Text as={ListItem}>
You may optionally add a <Code>maxClaimable</Code>{" "}
You may optionally add a{" "}
<InlineCode code="maxClaimable" />
column override. (amount each wallet is allowed to
claim) If not specified, the default value is the one
you have set on your claim phase.
@@ -317,15 +316,15 @@ export const SnapshotUpload: React.FC<SnapshotUploadProps> = ({
color="blue.500"
href="/snapshot-with-maxclaimable.csv"
>
<Icon boxSize="1em" as={FiDownload} /> Example
<DownloadIcon className="inline size-3" /> Example
snapshot
</Link>
</Text>
<Text as={ListItem}>
You may optionally add <Code>price</Code> and{" "}
<Code>currencyAddress</Code> overrides. This lets you
override the currency and price you would like to
charge per wallet you specified.{" "}
You may optionally add <InlineCode code="price" /> and
<InlineCode code="currencyAddress" /> overrides. This
lets you override the currency and price you would
like to charge per wallet you specified.{" "}
<strong>
When defining a custom currency address, you must
also define a price override.
@@ -336,7 +335,7 @@ export const SnapshotUpload: React.FC<SnapshotUploadProps> = ({
color="blue.500"
href="/snapshot-with-overrides.csv"
>
<Icon boxSize="1em" as={FiDownload} /> Example
<DownloadIcon className="inline size-3" /> Example
snapshot
</Link>
</Text>
@@ -428,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")
@@ -436,12 +435,12 @@ const SnapshotTableColumns = [
: "Address couldn't be resolved"
}
>
<Stack direction="row" align="center">
<Icon as={IoAlertCircleOutline} color="red.500" boxSize={5} />
<div className="flex flex-row items-center gap-2">
<CircleAlertIcon className="size-4 text-red-500" />
<Text fontWeight="bold" color="red.500" cursor="default">
{address}
</Text>
</Stack>
</div>
</Tooltip>
</div>
);
@@ -558,33 +557,33 @@ const SnapshotTable: React.FC<SnapshotTableProps> = ({ data, portalRef }) => {
</TableContainer>
<Portal containerRef={portalRef}>
<div className="flex w-full items-center justify-center">
<div className="flex flex-row">
<div className="flex flex-row gap-1">
<IconButton
isDisabled={!canPreviousPage}
aria-label="first page"
icon={<Icon as={MdFirstPage} />}
icon={<ChevronFirstIcon className="size-4" />}
onClick={() => gotoPage(0)}
/>
<IconButton
isDisabled={!canPreviousPage}
aria-label="previous page"
icon={<Icon as={MdNavigateBefore} />}
icon={<ChevronLeftIcon className="size-4" />}
onClick={() => previousPage()}
/>
<Text whiteSpace="nowrap">
<p className="my-auto whitespace-nowrap">
Page <strong>{pageIndex + 1}</strong> of{" "}
<strong>{pageOptions.length}</strong>
</Text>
</p>
<IconButton
isDisabled={!canNextPage}
aria-label="next page"
icon={<Icon as={MdNavigateNext} />}
icon={<ChevronRightIcon className="size-4" />}
onClick={() => nextPage()}
/>
<IconButton
isDisabled={!canNextPage}
aria-label="last page"
icon={<Icon as={MdLastPage} />}
icon={<ChevronLastIcon className="size-4" />}
onClick={() => gotoPage(pageCount - 1)}
/>
@@ -1,32 +1,39 @@
import { useEVMContractInfo } from "@3rdweb-sdk/react/hooks/useActiveChainId";
"use client";
import { Spinner } from "@/components/ui/Spinner/Spinner";
import { Button } from "@/components/ui/button";
import type { EVMContractInfo } from "@3rdweb-sdk/react";
import {
useAddContractMutation,
useAllContractList,
} from "@3rdweb-sdk/react/hooks/useRegistry";
import { Icon } from "@chakra-ui/react";
import { useTrack } from "hooks/analytics/useTrack";
import { useTxNotifications } from "hooks/useTxNotifications";
import { useRouter } from "next/router";
import { FiPlus } from "react-icons/fi";
import { CodeIcon, PlusIcon } from "lucide-react";
import Link from "next/link";
import { usePathname } from "next/navigation";
import type { Chain } from "thirdweb";
import { useActiveAccount } from "thirdweb/react";
import { Button } from "tw-components";
import { BuildAppsButton } from "./build-apps-button";
const TRACKING_CATEGORY = "add_to_dashboard_upsell";
type AddToDashboardCardProps = {
contractAddress?: string;
contractAddress: string;
chain: Chain;
contractInfo: EVMContractInfo;
hideCodePageLink?: boolean;
};
export const PrimaryDashboardButton: React.FC<AddToDashboardCardProps> = ({
contractAddress,
chain,
contractInfo,
hideCodePageLink,
}) => {
const chain = useEVMContractInfo()?.chain;
const addContract = useAddContractMutation();
const trackEvent = useTrack();
const walletAddress = useActiveAccount()?.address;
const router = useRouter();
const pathname = usePathname();
const registry = useAllContractList(walletAddress);
const { onSuccess: onAddSuccess, onError: onAddError } = useTxNotifications(
@@ -42,7 +49,7 @@ export const PrimaryDashboardButton: React.FC<AddToDashboardCardProps> = ({
// compare address...
c.address.toLowerCase() === contractAddress.toLowerCase() &&
// ... and chainId
c.chainId === chain?.chainId,
c.chainId === chain.id,
) &&
registry.isSuccess;
@@ -50,28 +57,36 @@ export const PrimaryDashboardButton: React.FC<AddToDashboardCardProps> = ({
!walletAddress ||
!contractAddress ||
!chain ||
router.asPath.includes("payments")
pathname?.includes("payments")
) {
return null;
}
return isInRegistry ? (
<BuildAppsButton>Code Snippets</BuildAppsButton>
) : (
if (isInRegistry) {
if (hideCodePageLink) {
return null;
}
if (!pathname?.endsWith("/code")) {
return (
<Button variant="outline" asChild className="gap-2">
<Link
href={`/${contractInfo.chainSlug}/${contractInfo.contractAddress}/code`}
>
<CodeIcon className="size-4" />
Code Snippets
</Link>
</Button>
);
}
return null;
}
return (
<Button
minW="inherit"
variant="solid"
bg="bgBlack"
color="bgWhite"
_hover={{
opacity: 0.85,
}}
_active={{
opacity: 0.75,
}}
leftIcon={<Icon as={FiPlus} />}
isLoading={addContract.isPending}
isDisabled={!chain?.chainId}
className="gap-2"
variant="outline"
onClick={() => {
if (!chain) {
return;
@@ -85,7 +100,7 @@ export const PrimaryDashboardButton: React.FC<AddToDashboardCardProps> = ({
addContract.mutate(
{
contractAddress,
chainId: chain.chainId,
chainId: chain.id,
},
{
onSuccess: () => {
@@ -111,6 +126,11 @@ export const PrimaryDashboardButton: React.FC<AddToDashboardCardProps> = ({
);
}}
>
{addContract.isPending ? (
<Spinner className="size-4" />
) : (
<PlusIcon className="size-4" />
)}
Import contract
</Button>
);
@@ -0,0 +1,49 @@
import * as ERC20Ext from "thirdweb/extensions/erc20";
import * as ERC721Ext from "thirdweb/extensions/erc721";
import * as ERC1155Ext from "thirdweb/extensions/erc1155";
export function isERC721ClaimConditionsSupported(functionSelectors: string[]) {
return [
// reads
ERC721Ext.isGetClaimConditionByIdSupported(functionSelectors),
ERC721Ext.isGetActiveClaimConditionIdSupported(functionSelectors),
ERC721Ext.isGetClaimConditionsSupported(functionSelectors),
ERC721Ext.isGetActiveClaimConditionSupported(functionSelectors),
// writes
ERC721Ext.isSetClaimConditionsSupported(functionSelectors),
ERC721Ext.isResetClaimEligibilitySupported(functionSelectors),
].every(Boolean);
}
export function isERC20ClaimConditionsSupported(functionSelectors: string[]) {
return [
// reads
ERC20Ext.isGetClaimConditionByIdSupported(functionSelectors),
ERC20Ext.isGetActiveClaimConditionIdSupported(functionSelectors),
ERC20Ext.isGetClaimConditionsSupported(functionSelectors),
ERC20Ext.isGetActiveClaimConditionSupported(functionSelectors),
// writes
ERC20Ext.isSetClaimConditionsSupported(functionSelectors),
ERC20Ext.isResetClaimEligibilitySupported(functionSelectors),
].every(Boolean);
}
function isERC1155ClaimConditionsSupported(functionSelectors: string[]) {
return [
// reads
ERC1155Ext.isGetClaimConditionByIdSupported(functionSelectors),
ERC1155Ext.isGetClaimConditionsSupported(functionSelectors),
ERC1155Ext.isGetActiveClaimConditionSupported(functionSelectors),
// writes
ERC1155Ext.isSetClaimConditionsSupported(functionSelectors),
ERC1155Ext.isResetClaimEligibilitySupported(functionSelectors),
].every(Boolean);
}
export function isClaimConditionsSupported(functionSelectors: string[]) {
return (
isERC721ClaimConditionsSupported(functionSelectors) ||
isERC20ClaimConditionsSupported(functionSelectors) ||
isERC1155ClaimConditionsSupported(functionSelectors)
);
}
@@ -0,0 +1,26 @@
import * as ERC4337Ext from "thirdweb/extensions/erc4337";
export function isAccountFactoryContract(functionSelectors: string[]) {
return [
ERC4337Ext.isGetAllAccountsSupported(functionSelectors),
ERC4337Ext.isGetAccountsSupported(functionSelectors),
ERC4337Ext.isTotalAccountsSupported(functionSelectors),
ERC4337Ext.isGetAccountsOfSignerSupported(functionSelectors),
ERC4337Ext.isPredictAccountAddressSupported(functionSelectors),
].every(Boolean);
}
export function isAccountContract(functionSelectors: string[]) {
return ERC4337Ext.isValidateUserOpSupported(functionSelectors);
}
export function isAccountPermissionsSupported(functionSelectors: string[]) {
return [
ERC4337Ext.isGetAllActiveSignersSupported(functionSelectors),
ERC4337Ext.isGetAllAdminsSupported(functionSelectors),
ERC4337Ext.isGetAllSignersSupported(functionSelectors),
ERC4337Ext.isIsActiveSignerSupported(functionSelectors),
ERC4337Ext.isIsAdminSupported(functionSelectors),
ERC4337Ext.isAddAdminSupported(functionSelectors),
].every(Boolean);
}
@@ -0,0 +1,17 @@
import * as MarketplaceExt from "thirdweb/extensions/marketplace";
export function isDirectListingSupported(functionSelectors: string[]) {
return [
MarketplaceExt.isCreateListingSupported(functionSelectors),
MarketplaceExt.isCancelListingSupported(functionSelectors),
MarketplaceExt.isBuyFromListingSupported(functionSelectors),
].every(Boolean);
}
export function isEnglishAuctionSupported(functionSelectors: string[]) {
return [
MarketplaceExt.isCreateAuctionSupported(functionSelectors),
MarketplaceExt.isCancelAuctionSupported(functionSelectors),
MarketplaceExt.isBidInAuctionSupported(functionSelectors),
].every(Boolean);
}
@@ -0,0 +1,11 @@
import {
isGetInstalledModulesSupported,
isInstallModuleSupported,
} from "thirdweb/modules";
export function isModularCoreContract(functionSelectors: string[]) {
return [
isGetInstalledModulesSupported(functionSelectors),
isInstallModuleSupported(functionSelectors),
].every(Boolean);
}
@@ -0,0 +1,21 @@
import * as PermissionsExt from "thirdweb/extensions/permissions";
export function isPermissionsSupported(functionSelectors: string[]) {
return [
PermissionsExt.isGetRoleAdminSupported(functionSelectors),
PermissionsExt.isGrantRoleSupported(functionSelectors),
PermissionsExt.isHasRoleSupported(functionSelectors),
PermissionsExt.isRenounceRoleSupported(functionSelectors),
PermissionsExt.isRevokeRoleSupported(functionSelectors),
].every(Boolean);
}
export function isPermissionsEnumerableSupported(functionSelectors: string[]) {
return (
isPermissionsSupported(functionSelectors) &&
[
PermissionsExt.isGetRoleMemberSupported(functionSelectors),
PermissionsExt.isGetRoleMemberCountSupported(functionSelectors),
].every(Boolean)
);
}
@@ -0,0 +1,14 @@
import { isERC20 as isERC20_ERC20 } from "thirdweb/extensions/erc20";
import { isGetNFTSupported as isGetNFTSupported_ERC721 } from "thirdweb/extensions/erc721";
import { isGetNFTSupported as isGetNFTSupported_ERC1155 } from "thirdweb/extensions/erc1155";
export function supportedERCs(functionSelectors: string[]) {
const isERC721 = isGetNFTSupported_ERC721(functionSelectors);
const isERC1155 = isGetNFTSupported_ERC1155(functionSelectors);
const isERC20 = isERC20_ERC20(functionSelectors);
return {
isERC721,
isERC1155,
isERC20,
};
}

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