Compare commits

..
Author SHA1 Message Date
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>GitHub Action
34e6f69568 Version Packages (#3953)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub Action <[email protected]>
2024-08-05 17:04:41 -07:00
Jonas Daniels c9e14e366c Revert "Version Packages (#3950)"
This reverts commit 65eb299eb0.
2024-08-05 16:24:13 -07:00
Jonas DanielsandGitHub 4308c4a1cf [Chore] Update thirdweb dependency to use workspace protocol (#3952) 2024-08-05 16:20:44 -07:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
65eb299eb0 Version Packages (#3950)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-08-05 16:18:53 -07:00
gregfromstl 1309602889 docs: adds telegram changeset (#3951)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR adds a new feature to the `thirdweb` module, enabling users to log in to in-app wallets using Telegram.

### Detailed summary
- Added support for Telegram login option in in-app wallets using `thirdweb`
- Updated `inAppWallet` function to include Telegram login strategy
- Added example code snippet for connecting to wallet using Telegram strategy

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

<!-- end pr-codex -->
2024-08-05 22:54:17 +00:00
GWSzeto 09ebee8e41 added build back into the docs (#3949)
Modified .gitignore so that it accepts the build folder

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to add detailed documentation for various ERC standards in smart contracts.

### Detailed summary
- Added documentation for ERC721, ERC1155, and ERC20 smart contract standards
- Included usage examples and base contracts for each extension
- Updated metadata and images for clarity and consistency

> The following files were skipped due to too many changes: `apps/portal/src/app/contracts/build/extensions/erc-1155/ERC1155Mintable/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-721/ERC721Mintable/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-1155/ERC1155Enumerable/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-721/ERC721Revealable/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-1155/ERC1155Revealable/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-721/ERC721Enumerable/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-1155/ERC1155Burnable/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-721/ERC721BatchMintable/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-20/ERC20BatchMintable/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-721/ERC721Supply/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-1155/ERC1155Supply/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-1155/ERC1155Claimable/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-1155/ERC1155BatchMintable/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-721/ERC721Claimable/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-20/ERC20ClaimConditions/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-20/ERC20/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-721/ERC721ClaimConditions/page.mdx`, `apps/portal/src/app/contracts/build/base-contracts/erc-20/base/page.mdx`, `apps/portal/src/app/contracts/build/extensions/general/Multicall/page.mdx`, `apps/portal/src/app/contracts/build/modular-contracts/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-721/ERC721ClaimCustom/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-1155/ERC1155ClaimCustom/page.mdx`, `apps/portal/src/app/contracts/build/base-contracts/erc-4337/account-factory/page.mdx`, `apps/portal/src/app/contracts/build/base-contracts/erc-20/vote/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-1155/ERC1155ClaimConditions/page.mdx`, `apps/portal/src/app/contracts/build/extensions/general/PermissionsEnumerable/page.mdx`, `apps/portal/src/app/contracts/build/base-contracts/erc-4337/managed-account-factory/page.mdx`, `apps/portal/src/app/contracts/build/base-contracts/erc-20/drop/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-1155/ERC1155ClaimPhases/page.mdx`, `apps/portal/src/app/contracts/build/extensions/general/Ownable/page.mdx`, `apps/portal/src/app/contracts/build/base-contracts/erc-20/drop-vote/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-721/ERC721ClaimPhases/page.mdx`, `apps/portal/src/app/contracts/build/extensions/general/BatchMintMetadata/page.mdx`, `apps/portal/src/app/contracts/build/extensions/general/Permissions/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-721/ERC721Staking/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-20/ERC20Permit/page.mdx`, `apps/portal/src/app/contracts/build/base-contracts/erc-20/signature-mint/page.mdx`, `apps/portal/src/app/contracts/build/base-contracts/erc-4337/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-20/ERC20Staking/page.mdx`, `apps/portal/src/app/contracts/build/extensions/general/ContractMetadata/page.mdx`, `apps/portal/src/app/contracts/build/extensions/general/PlatformFee/page.mdx`, `apps/portal/src/app/contracts/build/base-contracts/erc-721/delayed-reveal/page.mdx`, `apps/portal/src/app/contracts/build/base-contracts/erc-20/signature-mint-vote/page.mdx`, `apps/portal/src/app/contracts/build/base-contracts/erc-1155/delayed-reveal/page.mdx`, `apps/portal/src/app/contracts/build/extensions/general/LazyMint/page.mdx`, `apps/portal/src/app/contracts/build/base-contracts/erc-721/signature-mint/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-4337/AccountExtension/page.mdx`, `apps/portal/src/app/contracts/build/extensions/general/PrimarySale/page.mdx`, `apps/portal/src/app/contracts/build/base-contracts/erc-1155/signature-mint/page.mdx`, `apps/portal/src/app/contracts/build/base-contracts/erc-4337/managed-account/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-1155/ERC1155Staking/page.mdx`, `apps/portal/src/app/contracts/build/base-contracts/erc-721/base/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-4337/SmartWallet/page.mdx`, `apps/portal/src/app/contracts/build/base-contracts/erc-4337/account/page.mdx`, `apps/portal/src/app/contracts/build/base-contracts/erc-721/lazy-mint/page.mdx`, `apps/portal/src/app/contracts/build/extensions/general/DelayedReveal/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-4337/SmartWalletFactory/page.mdx`, `apps/portal/src/app/contracts/build/get-started/page.mdx`, `apps/portal/src/app/contracts/build/extensions/general/Royalty/page.mdx`, `apps/portal/src/app/contracts/build/base-contracts/erc-721/drop/page.mdx`, `apps/portal/src/app/contracts/build/base-contracts/erc-1155/lazy-mint/page.mdx`, `apps/portal/src/app/contracts/build/base-contracts/erc-1155/base/page.mdx`, `apps/portal/src/app/contracts/build/base-contracts/erc-1155/drop/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-20/ERC20SignatureMint/page.mdx`, `apps/portal/src/app/contracts/build/base-contracts/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-721/ERC721SignatureMint/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-1155/ERC1155SignatureMint/page.mdx`, `apps/portal/src/app/contracts/build/extensions/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-1155/ERC1155DropSinglePhase/page.mdx`, `apps/portal/src/app/contracts/build/extensions/general/DropSinglePhase/page.mdx`, `apps/portal/src/app/contracts/build/extensions/general/Drop/page.mdx`, `apps/portal/src/app/contracts/build/extensions/erc-1155/ERC1155Drop/page.mdx`, `apps/portal/src/app/contracts/build/overview/assets/extension-model.svg`

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

<!-- end pr-codex -->
2024-08-05 22:42:20 +00:00
ea2247c40c Added Celo Alfajores Testnet within the chain-definitions (#3941)
Signed-off-by: Jonas Daniels <[email protected]>
Co-authored-by: Jonas Daniels <[email protected]>
2024-08-05 15:30:42 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
a8061277fb chore(deps-dev): bump typescript from 5.5.2 to 5.5.4 (#3945)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-05 15:23:19 -07:00
Jonas DanielsandGitHub eb94d2ad18 [Feature] Add Content Security Policy and security headers configuration (#3943) 2024-08-05 15:20:13 -07:00
kien-ngo b3aabee23b Dashboard v5: Remove more v4 code (#3927)
This PR is the first step to eventually remove all the v4 code inside `src/contract-ui/tabs/nfts/page.tsx`

2 main components that is now v4-free:
- [x] useIsMinter
- [x] MinterOnly

In fear of putting up a huge PR, I submit this PR as the first in this series

<!-- start pr-codex -->

---

## PR-Codex overview
This PR updates contract handling and minter role detection across multiple components.

### Detailed summary
- Updated contract handling to use `ThirdwebContract`
- Improved minter role detection logic
- Refactored minting components to use updated contract handling

> The following files were skipped due to too many changes: `apps/dashboard/src/contract-ui/tabs/nfts/components/shared-metadata-button.tsx`, `apps/dashboard/src/contract-ui/tabs/nfts/components/batch-lazy-mint-button.tsx`, `apps/dashboard/src/contract-ui/tabs/nfts/page.tsx`

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

<!-- end pr-codex -->
2024-08-05 20:43:02 +00:00
kien-ngo 72fad8f22d Dashboard v5: Remove useStorageUpload (#3929)
- Add new React hook that uses v5's `upload` under the hood
- Sacrifice has been made - we remove the progress % from the loading bar

<!-- start pr-codex -->

---

## PR-Codex overview
The PR focuses on replacing `useStorageUpload` with `useDashboardStorageUpload` in multiple components for IPFS file uploads.

### Detailed summary
- Replaced `useStorageUpload` with `useDashboardStorageUpload` in `button.tsx`, `string-input.tsx`, `IconUpload.tsx`, and `dropzone.tsx`.
- Updated file upload logic in `FileUpload` component in `dropzone.tsx`.
- Added `useDashboardStorageUpload` in `useDashboardStorageUpload.tsx` for IPFS file uploads.

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

<!-- end pr-codex -->
2024-08-05 20:26:18 +00:00
MananTank e2db196790 Fix Forced dark theme on certain pages (#3940)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to add a new `useForceDarkTheme` hook to enforce dark theme across multiple pages.

### Detailed summary
- Added `useForceDarkTheme` hook to enforce dark theme.
- Updated multiple pages to use the new hook.
- Removed `DarkMode` component from affected pages.

> The following files were skipped due to too many changes: `apps/dashboard/src/pages/404.tsx`, `apps/dashboard/src/pages/index.tsx`, `apps/dashboard/src/pages/template/[id].tsx`, `apps/dashboard/src/pages/open-source.tsx`, `apps/dashboard/src/pages/contact-us.tsx`, `apps/dashboard/src/pages/community/ambassadors.tsx`

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

<!-- end pr-codex -->
2024-08-05 20:06:59 +00:00
gregfromstl ae28e27a8c feat: telegram login (#3830)
## TL;DR

This PR introduces support for Telegram OAuth across various components of the thirdweb packages.

## What changed?

- Added 'Telegram' as an OAuth option in `WALLETS` array within the `constants.ts` file.
- Introduced `telegramIconUri` constant and its usage across the application.
- Updated `socialIcons` object and methods to handle new Telegram icon.
- Enhanced `WalletImage` components to recognize and display the Telegram icon.
- Included Telegram in OAuth login path determination within `oauthSignIn.ts`.
- Updated enumerations and type definitions to include Telegram.
- Modified `InAppNativeConnector` and `InAppWebConnector` to handle Telegram OAuth redirection.

## How to test?

1. Navigate to the authentication section in the application.
2. Check for the new 'Sign in with Telegram' option.
3. Attempt to sign in using a Telegram account and verify the successful login flow.

## Why make this change?

To expand the authentication options available to users, providing more flexibility and convenience. Telegram is a popular messaging app, and integrating it as an OAuth option can enhance user experience.

---

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to add `Telegram` as a supported authentication option across various parts of the application.

### Detailed summary
- Added `Telegram` as an authentication option in various files
- Included `TELEGRAM_ICON` in multiple components
- Updated social icons with `telegramIconUri`

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

<!-- end pr-codex -->
2024-08-05 19:49:16 +00:00
kien-ngo 9640b184ad Dashboard: Fix [Open IPFS folder] link (#3935)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to refactor the logic for getting the folder path from an IPFS hash URL in the `dropzone.tsx` component.

### Detailed summary
- Refactored logic to extract folder path from IPFS hash URL
- Updated return statement to use the extracted folder path for the IPFS URL

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

<!-- end pr-codex -->
2024-08-05 16:59:18 +00:00
kien-ngo a2e13820f2 Dashboard v5: Update dashboard [...paths].tsx to v5 (#3925)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to refactor contract detection logic and improve metadata handling.

### Detailed summary
- Removed `detectContractFeature` from `@thirdweb-dev/sdk`
- Added functions for detecting ERC20, ERC721, and ERC1155 extensions
- Improved contract metadata handling with `getContractMetadata` function

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

<!-- end pr-codex -->
2024-08-05 16:46:09 +00:00
jnsdls d0ea16e887 [Fix] Add 'Chainlist' link to header and update navigation structure (#3939)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to add a new `Chainlist` link in the header and a corresponding button in the app shell.

### Detailed summary
- Added `Chainlist` link in the header navigation.
- Included a `Chainlist` button in the app shell for quick access.
- Removed previous `Chainlist` link implementation.

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

<!-- end pr-codex -->
2024-08-05 16:41:37 +00:00
kien-ngo 1f3448e1ea Portal: Improve ts docs (#3937)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR enhances error handling and callback functionality in various components like `TransactionButton` and `CreateDirectListingButton`.

### Detailed summary
- Added guidance for error handling and callbacks in `TransactionButton`
- Updated comments in `CreateDirectListingButton`
- Improved error handling info in `ClaimButton`
- Added examples and instructions for handling errors and callbacks in components

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

<!-- end pr-codex -->
2024-08-05 06:27:14 +00:00
MananTank ad619a779c Use shadcn checkbox in deploy form (#3928)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to refactor and improve the UI components in the custom contract form.

### Detailed summary
- Added `CheckboxWithLabel` component with enhanced functionality.
- Refactored `Tooltip` to `ToolTipLabel` for better usability.
- Updated usage of components like `TrackedLinkTW` and `Spinner`.
- Improved layout and styling for better user experience.

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

<!-- end pr-codex -->
2024-08-04 18:55:17 +00:00
MananTank 09e89e5e6b Move FileInput from chakra to tailwind (#3926)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR updates various components to replace Chakra UI props with className for styling consistency.

### Detailed summary
- Replaced Chakra UI props with className for consistent styling in multiple components.
- Updated styling in `FileInput` component for better consistency and maintainability.
- Added new imports and removed unnecessary imports in `FileInput` component.

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

<!-- end pr-codex -->
2024-08-04 18:46:46 +00:00
jnsdls baefa5e9c7 [Chore] Uniform formatting in package.json and update fs imports (#3933) 2024-08-03 23:53:16 +00:00
kien-ngo 57e87528c8 chore: add a small test for numberToHex() (#3932)
Happened to write this quick test when debugging an issue

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to add a test for the `numberToHex` function in `hex.ts`.

### Detailed summary
- Added a test suite for `numberToHex` function in `hex.ts`
- Tested conversion of a number to a hexadecimal string with specified size and sign
- Asserted the correctness of the conversion result

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

<!-- end pr-codex -->
2024-08-03 23:39:39 +00:00
Jonas DanielsandGitHub 0b5dc2a137 [Fix] Validate and decode nextPath to ensure it is a relative path before redirecting (#3930) 2024-08-03 15:56:32 -07:00
jnsdls 0d23d5d6d5 [Fix] Exclude auth token from pay URLs when setting request headers (#3931)
This PR updates the fetch utility in the Thirdweb package to exclude the authorization token from being sent when the endpoint is related to the pay service. This ensures that requests to 'pay.' prefixed URLs are always made on behalf of the 'developer' rather than the 'end user.' It introduces a new function, isPayUrl, to determine if the URL belongs to the pay service.

---
2024-08-03 22:38:12 +00:00
kien-ngo 16376e56d7 Fix typo in docs (#3924)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces information about using Ethers.js in version 5 of the thirdweb SDK.

### Detailed summary
- Added a section titled "Ethers.js in v5" in `page.mdx`
- Clarified that SDK v5 is compatible with Ethers.js v5 and v6

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

<!-- end pr-codex -->
2024-08-03 05:19:07 +00:00
kien-ngo 3f923e4469 Update to React migration docs (#3923)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on migrating React SDK v4 to v5. It includes changes in installation steps, interacting with contracts, and introducing an ethers.js adapter.

### Detailed summary
- Updated installation steps for React SDK v5
- Added new components for interacting with contracts
- Introduced an ethers.js adapter for compatibility with v5
- Updated sidebar links for migration guidance

> The following files were skipped due to too many changes: `apps/portal/src/app/react/v5/sidebar.tsx`

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

<!-- end pr-codex -->
2024-08-03 05:09:30 +00:00
kien-ngo c7a417e285 <Crusade> Claim NFT drop to v5 (#3910)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to optimize NFT claiming functionality in the dashboard.

### Detailed summary
- Refactored NFTClaimButton to use `contractAddress` and `chainId`
- Updated NFTClaimForm to use `contractAddress` and `chainId` instead of `contract`
- Improved error handling in NFTClaimForm
- Added transaction handling in NFTClaimForm

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

<!-- end pr-codex -->
2024-08-03 01:58:31 +00:00
gregfromstl a97d7636ba docs: add callouts for generating client ID across multiple guides (#3921)
### TL;DR

Added information callouts across various SDK documentation pages, prompting users to generate a client ID to access blockchain APIs, storage, and more.

### What changed?

1. Integrated `Link` and `Button` components from `next/link` and `@/components/ui/button` respectively.
2. Added `<Callout>` components with instructional text and links for generating client IDs.
3. Changed existing callout in TypeScript client page from 'Api Key' to 'Client ID'.

### How to test?

Check the following pages for the new callout additions:
- `/connect`
- `/react-native/v5`
- `/react/v5`
- `/typescript/v5`
- `/typescript/v5/client`

### Why make this change?

To guide users in generating a client ID, which is necessary to access various features offered by the SDK.

---

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to update references from "Api Key" to "Client ID" and add a `Link` and `Button` component for generating client IDs in various pages.

### Detailed summary
- Updated "Api Key" to "Client ID" in callouts
- Added `Link` and `Button` components for generating client IDs in multiple pages

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

<!-- end pr-codex -->
2024-08-03 01:55:02 +00:00
Jonas DanielsandGitHub 80e0957857 [Feature] Add portal build configuration to turbo.json and update changeset (#3922) 2024-08-02 18:11:35 -07:00
gregfromstl 14d3d18ad2 fix: portal dependencies (#3920)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on updating dependencies and adding webpack configuration.

### Detailed summary
- Skipped a test for executing zkcandy tx via SDK
- Updated `remark-gfm` version
- Added webpack configuration for external libraries
- Updated dependencies for linting and fixed scripts
- Updated various `mdast-util` packages
- Updated `micromark-extension` packages
- Updated `remark-gfm` version in multiple places

> 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-08-03 00:38:06 +00:00
MananTank 079dc921d4 [dashboard] Enhance UI consistency across chain page components (#3919)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to update various UI components in the dashboard app for better styling consistency and functionality.

### Detailed summary
- Updated styling of `CopyTextButton`, `ExplorerSection`, `LiveStats`, and `ChainOverviewSection`.
- Replaced `CopyButton` import with `CopyTextButton`.
- Improved button and link styling for better user experience.

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

<!-- end pr-codex -->
2024-08-03 00:10:36 +00:00
kien-ngo c2e86c6828 <Crusade> Type-only migration! (#3909)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to update types and imports related to NFT metadata handling in various files.

### Detailed summary
- Updated types to use `NFTInput` instead of `NFTMetadataInput` for NFT metadata handling.
- Updated imports to use `NFTInput` from "thirdweb/utils" in multiple files.
- Adjusted function signatures and parameters accordingly for consistency and compatibility.

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

<!-- end pr-codex -->
2024-08-02 23:32:06 +00:00
gregfromstl 9d519c6590 chore: move the docs to the monorepo (#3915)
Adds the docs to the monorepo
2024-08-02 22:41:36 +00:00
kien-ngo d04b03226a <Crusade> Dashboard to v5: Marketplace v3 (#3907)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to add a `type` field to `DirectListing` and `EnglishAuction` types in the marketplace extensions.

### Detailed summary
- Added `type` field to `DirectListing` and `EnglishAuction` types
- Updated components to handle `type` field for pricing display
- Refactored contract role checks for Marketplace v3 compatibility

> The following files were skipped due to too many changes: `apps/dashboard/src/contract-ui/tabs/listings/components/list-form.tsx`

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

<!-- end pr-codex -->
2024-08-02 22:17:03 +00:00
MananTank c24dadaa60 Chain page tweaks (#3916)
<!-- start pr-codex -->

## PR-Codex overview
This PR updates various components and functions related to chain metadata and wallet connection logic.

### Detailed summary
- Improved conditional rendering for `ChainCTA` component
- Updated styles and behavior in `SidebarContent` and `MobileMenu`
- Added `useCustomConnectModal` hook for custom wallet connection modal
- Enhanced `AddChainToWallet` component with custom connect modal functionality

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

<!-- end pr-codex -->
2024-08-02 22:09:42 +00:00
gregfromstl 2c751b4fce test: adds msw (#3913)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to add `msw` for network call mocking, update dependencies, and enhance wallet integration tests.

### Detailed summary
- Added `msw` for network call mocking in tests
- Updated dependencies
- Improved wallet integration tests with new functions

> 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-08-02 20:16:31 +00:00
Joe-Thirdweb e7f7ae8452 Chainlist default banner for PAID CHAINS (#3911)
## Problem solved

Short description of the bug fixed or feature added
Added a default banner and CTA image for every paying chain except lens.
Added an about section to every paying chain
Added a link to their website for every paying chain

##How to test
Visit the chain's chainlist page and view the images.
Click on their "learn More" butttons to be taken to their website.
Chains Added
- Lumia Mainnet
- Superposition Testnet
- Aleph 0 Mainnet
- b3 Mainnet
- Campnetwork v2 testnet
- Donatuz mainnet
- Fuse
- Gemuchain
- 0g labs testnet
- zkCandy
- zkSync

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to add metadata for different blockchains in the dashboard.

### Detailed summary
- Added metadata for Lumia Mainnet, Superposition Testnet, Aleph 0 Mainnet, B3 Mainnet, CampNetwork Testnet v2, Donatuz, Fuse, Gemuchain, 0G-Newton-Testnet, Plume, zkCandy, and zkSync
- Updated `utils.ts` with imports for new assets
- Updated chain metadata record with details for each blockchain

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

<!-- end pr-codex -->
2024-08-02 19:14:22 +00:00
9c292a4903 [dashboard] Chain page redesign (#3826)
Co-authored-by: Manan Tank <[email protected]>
2024-08-02 19:01:12 +00:00
jnsdls b06272c35d [Feature] Add Chainlist link and update header styles (#3899)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to add a new link "Chainlist" to the dashboard header and update styles for better user experience.

### Detailed summary
- Added "Chainlist" link to the dashboard header
- Updated styles for the "Chainlist" link to match the design
- Adjusted styles for active links in the header for better visibility and consistency

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

<!-- end pr-codex -->
2024-08-02 17:44:14 +00:00
joaquim-verges 366646e354 chore(jsdocs): enhance JSDoc examples across multiple hooks and functions (#3908)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces enhancements related to wallet interactions, contract calls, and event monitoring in the application.

### Detailed summary
- Added functionality to pre-authenticate users via email or phone number
- Enhanced wallet connection components with account abstraction and gas sponsorship options
- Updated wallet connection buttons to support account abstraction and gas sponsorship
- Improved wallet information retrieval with examples
- Expanded capabilities for fetching wallet balances for native and specific tokens
- Enhanced contract call preparation with examples of different method signatures and value options
- Improved contract event monitoring with event extensions and custom event watching
- Updated contract read hooks to automatically update on contract changes

> The following files were skipped due to too many changes: `packages/thirdweb/src/react/core/hooks/contract/useReadContract.ts`, `packages/thirdweb/src/transaction/actions/send-transaction.ts`, `packages/thirdweb/src/react/web/hooks/transaction/useSendTransaction.tsx`

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

<!-- end pr-codex -->
2024-08-02 03:17:02 +00:00
joaquim-verges 8eeec64388 fix(tests): update PayEmbed tests to use waitFor for render assertions (#3906)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to update test files in `PayEmbed-disconnected.test.tsx` and `PayEmbed.test.tsx` to use `waitFor` for asynchronous operations.

### Detailed summary
- Added `waitFor` for asynchronous operations in test files
- Updated test cases to handle asynchronous rendering and interactions

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

<!-- end pr-codex -->
2024-08-01 20:03:45 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>GitHub Action
4dea4ba3c0 Version Packages (#3900)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub Action <[email protected]>
2024-08-02 08:02:39 +12:00
Jonas DanielsandGitHub a66071b2c2 [Fix] Correct integer check logic in middleware function (#3905) 2024-08-01 12:20:15 -07:00
gregfromstl 306f3da606 fix(thirdweb): resolve occasional iframe error during OAuth login (#3903)
### TL;DR
Fix occasional iframe error when logging in with oauth

### What changed?
Removed error throwing for invalid event type in OAuth login flow.

### How to test?
Attempt OAuth login and ensure no errors occur related to iframes.

### Why make this change?
To prevent unnecessary exceptions which impede the OAuth login user experience.

---
2024-08-01 18:56:12 +00:00
Manan TankandGitHub e6495c1541 Remove ja_JP locale set in playground for ConnectButton (#3904) 2024-08-02 06:23:16 +12:00
Joaquim VergesandGitHub 825ef239a0 fix(gas): handle gas free chains where baseFeePerGas is 0 (#3901) 2024-08-01 21:30:09 +12:00
joaquim-verges 13d9741f77 feat(localization): Add Korean and French locale support (#3895)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR adds Korean and French locales, updates wallet connection screens, and adds smart wallet content.

### Detailed summary
- Added Korean and French locales
- Updated wallet connection screens with new locales
- Added smart wallet content for Korean locale

> The following files were skipped due to too many changes: `packages/thirdweb/src/react/web/wallets/local/locale/kr.ts`, `packages/thirdweb/src/react/web/wallets/shared/locale/kr.ts`, `packages/thirdweb/src/react/web/wallets/local/locale/fr.ts`, `packages/thirdweb/src/react/web/wallets/local/locale/ja.ts`, `packages/thirdweb/src/react/web/wallets/shared/locale/ja.ts`, `packages/thirdweb/src/react/web/wallets/shared/locale/fr.ts`, `packages/thirdweb/src/react/web/ui/ConnectWallet/locale/kr.ts`, `packages/thirdweb/src/react/web/ui/ConnectWallet/locale/fr.ts`

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

<!-- end pr-codex -->
2024-08-01 08:07:23 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
94f5ed601d Version Packages (#3898)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-07-31 23:24:25 -07:00
Jonas DanielsandGitHub 4463848671 [Fix] Remove 'create' command from key-requiring CLI commands (#3897) 2024-07-31 23:10:54 -07:00
gregandGitHub 3b49b18f4d fix(react): OTP validation in React Native Connect UI (#3896) 2024-07-31 23:10:43 -07:00
Joaquim VergesandGitHub 2e0ca0ecee feat(webGL): Update CB wallet v4 for webGL (#3893) 2024-08-01 13:25:05 +12:00
MananTank ff6a319caf Map generic inputs to prebuilt components for Modular Contract install params fiedsets (#3887)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to update contract form components with improved form handling and modular extension support.

### Detailed summary
- Added `isBeta` prop to `ContractCard` and `publishedContractToShow` check
- Updated `PrimarySaleFieldset` and `RoyaltyFieldset` with improved form handling
- Enhanced modular extension support in `ModularContractDefaultExtensionsFieldset`

> The following files were skipped due to too many changes: `apps/dashboard/src/components/contract-components/contract-deploy-form/modular-contract-default-extensions-fieldset.tsx`

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

<!-- end pr-codex -->
2024-07-31 23:23:41 +00:00
MananTank 744c570ed1 [dashboard] Use dark default Theme for first time users (#3890)
<!-- start pr-codex -->

## PR-Codex overview
This PR introduces a new `defaultTheme` prop set to "dark" in the `_app.tsx` file.

### Detailed summary
- Added `defaultTheme` prop with value "dark" in the `_app.tsx` file.

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

<!-- end pr-codex -->
2024-07-31 22:08:51 +00:00
MananTank fff9550c8f [dashboard] Fix Spinner size in Add to wallet button in chain page (#3888)
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to update the styling of the "Add to wallet" button in the `add-chain-to-wallet.tsx` component.

### Detailed summary
- Updated the `className` of the button to include `gap-2` for spacing
- Adjusted the Spinner size with the class `size-3`

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

<!-- end pr-codex -->
2024-07-31 19:16:32 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>GitHub Action
f925451c15 Version Packages (#3874)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub Action <[email protected]>
2024-08-01 06:45:44 +12:00
gregfromstl fd30702ffd fix(thirdweb): mobile auth (#3886)
### TL;DR

Improved social authentication flexibility by adding support for an optional `redirectUrl` parameter and a new `mobile` mode.

### What changed?

- `getLoginPath.ts`: Added handling for `redirectUrl` and a new mode `mobile`.
- `native-auth.ts`: Updated social login to use `mobile` mode and include `redirectUrl`.
- `auth/middleware.ts`: Enhanced error handling for recovery codes by attempting fallback recovery code method.
- `native-connector.ts`: Fixed typo in console error message and ensured `redirectUrl` defaults correctly for native social logins.

### How to test?

1. Initiate a social login with the added `mobile` mode and verify if the `redirectUrl` functions correctly.
2. Trigger an error scenario in recovery code fetching and check that the fallback method is attempted and appropriate error is thrown if both fail.
3. Check the console for corrected error messages.

### Why make this change?

To increase the robustness and flexibility of social authentication by supporting mobile specific workflows and enhanced error resilience.

---

## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to enhance mobile authentication in the thirdweb application by updating redirect URLs and recovery code handling.

### Detailed summary
- Updated authentication mode to "mobile" instead of "popup"
- Added `redirectUrl` parameter for mobile authentication
- Improved error handling for recovery code retrieval
- Modified login path generation to support mobile authentication

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

<!-- end pr-codex -->
2024-07-31 16:44:08 +00:00
Joaquim VergesandGitHub 6cd279bc49 fix(ethers5adapter): correct transaction result nonces handling (#3885) 2024-07-31 22:19:28 +12:00
jnsdls 75cc5a6434 [Fix] Improve contract deploy logging and optimize Redis initialization (#3883)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to refactor the Redis caching implementation by encapsulating the Redis instance creation and usage inside a function to avoid unnecessary calls during build.

### Detailed summary
- Encapsulated Redis instance creation and usage inside a function `getRedis()`
- Refactored cache functions to use `getRedis()` function for Redis instance access

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

<!-- end pr-codex -->
2024-07-30 22:07:21 +00:00
kien-ngo e7d6161819 Add prebuilt component: CreateDirectListingButton (#3881)
<!-- start pr-codex -->

## PR-Codex overview
This PR adds a `CreateDirectListingButton` component for the Marketplace v3, allowing users to create direct listings for NFTs.

### Detailed summary
- Added `CreateDirectListingButton` component
- Updated `getPayMetadata` function
- Added test file for `CreateDirectListingButton`
- Updated `CreateDirectListingButton` component implementation

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

<!-- end pr-codex -->
2024-07-30 21:51:19 +00:00
MananTank 4171f1536d Improved error messages when connection management hooks used outside ThirdwebProvider (#3882)
<!-- start pr-codex -->

## PR-Codex overview
This PR improves error messages for connection management hooks used outside `ThirdwebProvider`.

### Detailed summary
- Added `useConnectionManagerCtx` to provide specific error messages
- Updated hooks to use `useConnectionManagerCtx` instead of `useConnectionManager`

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

<!-- end pr-codex -->
2024-07-30 20:59:57 +00:00
MananTank 5eb495581d Fix autoconnect of wallets connected from "All wallets" screen (#3880)
FIXES: DASH-104

<!-- start pr-codex -->

## PR-Codex overview
This PR focuses on fixing the `useAutoConnectCore` function in `useAutoConnect.ts` to handle auto-connect for wallets from the "All wallets" screen.

### Detailed summary
- Fixed autoConnect for wallets from "All wallets" screen
- Added `createWallet` import
- Updated logic to handle lastActiveWalletId not found in availableWallets

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

<!-- end pr-codex -->
2024-07-30 17:37:45 +00:00
MananTank 36172a0476 [dash] Use the correct chain in Smart Account deposit native funds transaction (#3879)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to update the DepositNative component to include the chain information for better functionality.

### Detailed summary
- Updated `DepositNative` component in `account/page.tsx` to include `chain` information
- Added `mapStoredChainTov5Chain` function to map chain data in `map-chains.tsx`
- Imported `mapStoredChainTov5Chain` in `NetworkSelectorButton.tsx` and `deposit-native.tsx`

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

<!-- end pr-codex -->
2024-07-30 16:56:06 +00:00
kien-ngo cee989d41d (crusade) Dashboard v5 (#3876)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to refactor components in the contract UI tabs to use `contractAddress` and `chainId` instead of passing the entire `contract` object.

### Detailed summary
- Refactored `DirectListingsTable` and `EnglishAuctionsTable` components to accept `contractAddress` and `chainId`
- Updated `CancelDirectListing` and `CancelEnglishAuction` components to use `contractAddress` and `chainId`
- Modified `MarketplaceTable` components to receive `contractAddress` and `chainId` instead of `contract` object

> The following files were skipped due to too many changes: `apps/dashboard/src/contract-ui/tabs/claim-conditions/components/snapshot-upload.tsx`, `apps/dashboard/src/utils/tx-frame.ts`, `apps/dashboard/src/contract-ui/tabs/shared-components/listing-drawer.tsx`, `apps/dashboard/src/contract-ui/tabs/shared-components/cancel-tab.tsx`, `apps/dashboard/src/constants/currencies.ts`

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

<!-- end pr-codex -->
2024-07-30 16:42:41 +00:00
MananTank c55652f310 [dash] Fix wrong balance shown in Split contract (#3878)
<!-- start pr-codex -->

## PR-Codex overview
This PR updates the `nativeBalanceQuery` function in `page.tsx` to use the `contractAddress` instead of `address`.

### Detailed summary
- Updated `nativeBalanceQuery` to use `contractAddress` instead of `address`

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

<!-- end pr-codex -->
2024-07-30 16:29:19 +00:00
MananTank 9246ecb1e6 [dashboard] Add missing chakra color in theme (#3877)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to update the `backgroundCardHighlight` theme property in `apps/dashboard/src/theme/index.ts`.

### Detailed summary
- Updated `backgroundCardHighlight` property values
- Removed unused theme properties like `backgroundBody`, `wordmark`, `heading`, etc.

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

<!-- end pr-codex -->
2024-07-30 16:22:39 +00:00
jnsdls 337c8c953e [Feature] Add German localization for ConnectWallet and related components (#3875)
<!-- start pr-codex -->

## PR-Codex overview
This PR adds German localization to the `thirdweb` package, including translations and locale updates for various wallet-related components.

### Detailed summary
- Added German localization to the `thirdweb` package
- Updated `LocaleId` type to include `"de_DE"`
- Added German translations for wallet connection screens and instructions
- Updated locale files for smart wallets, injected wallets, and shared wallets to include German translations

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

<!-- end pr-codex -->
2024-07-30 08:08:47 +00:00
IDubuque 7e21d93a77 add refund to substatus (#3856)
## Problem solved

- add refund status

## Changes made

- [ ] Public API changes: list the public API changes made if any
- [ ] Internal API changes: explain the internal logic changes

## How to test

- [ ] Automated tests: link to unit test file
- [ ] Manual tests: step by step instructions on how to test

## Contributor NFT

Paste in your wallet address below and we will airdrop you a special NFT when your pull request is merged.

```Address: ```

<!-- start pr-codex -->

---

## PR-Codex overview
This PR adds a new status "REFUNDED" to the `getStatus.ts` file and defines a new `SwapType` type with values "SAME_CHAIN" and "CROSS_CHAIN".

### Detailed summary
- Added status "REFUNDED" to possible statuses in `getStatus.ts`
- Defined new `SwapType` type with values "SAME_CHAIN" and "CROSS_CHAIN"

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

<!-- end pr-codex -->
2024-07-30 07:41:48 +00:00
jnsdls 97f7ad4d29 [Fix] Redirect CLI login to support page and remove CLI login route (#3872)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to temporarily redirect the CLI login page to a support page to troubleshoot device linking issues.

### Detailed summary
- Added a temporary redirect for `/cli/login` to a support page for troubleshooting device linking issues.

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

<!-- end pr-codex -->
2024-07-30 06:54:39 +00:00
jnsdls f702cf7216 [Fix] Ensure -k flag is included for key-requiring thirdweb CLI commands (#3871)
FIXES: DASH-50

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to temporarily disable CLI login and provide guidance on using secret keys for specific commands.

### Detailed summary
- Temporarily disable CLI login functionality
- Provide guidance on passing secret keys for specific commands
- Check for missing -k flag in certain commands

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

<!-- end pr-codex -->
2024-07-30 06:42:40 +00:00
Jonas DanielsandGitHub 0797a56ba6 Update CODEOWNERS (#3873)
Signed-off-by: Jonas Daniels <[email protected]>
2024-07-29 23:41:51 -07:00
AmineAfia 76d35bd428 Add a status page to engine dashboard (#3848)
## Problem solved

Short description of the bug fixed or feature added

## Changes made

- [ ] Added status page to engine
![CleanShot 2024-07-29 at 00 34 13@2x](https://github.com/user-attachments/assets/68b79b2b-7256-4015-89c9-0cc84a361ee8)

- [ ] Internal API changes: explain the internal logic changes

## How to test

- [ ] Automated tests: link to unit test file
- [ ] Manual tests: step by step instructions on how to test: navigate to engine page and click on the statu snavigation in the left menu

## Contributor NFT

Paste in your wallet address below and we will airdrop you a special NFT when your pull request is merged.

```Address: ```

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to add system metrics functionality to the dashboard, including error rates and status codes.

### Detailed summary
- Added system metrics styling for charts
- Implemented system metrics components like `Healthcheck`, `ErrorRate`, and `StatusCodes`
- Updated `useEngineSystemHealth` hook with a polling interval parameter
- Updated UI components for better visualization of metrics

> The following files were skipped due to too many changes: `apps/dashboard/src/components/engine/system-metrics/components/StatusCodes.tsx`, `apps/dashboard/src/@/components/ui/chart.tsx`

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

<!-- end pr-codex -->
2024-07-30 06:19:09 +00:00
kien-ngo 24459b259b Update OG image for thirdweb.com/support (#3868)
## Problem solved

Short description of the bug fixed or feature added

## Changes made

- [ ] Public API changes: list the public API changes made if any
- [ ] Internal API changes: explain the internal logic changes

## How to test

- [ ] Automated tests: link to unit test file
- [ ] Manual tests: step by step instructions on how to test

## Contributor NFT

Paste in your wallet address below and we will airdrop you a special NFT when your pull request is merged.

```Address: ```

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to add metadata for Open Graph support in the dashboard page.

### Detailed summary
- Added `metadata` object with title and openGraph properties
- Imported `Metadata` type from "next"
- Updated the title for Open Graph support on the dashboard page

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

<!-- end pr-codex -->
2024-07-30 05:01:26 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>GitHub Action
195064adf7 Version Packages (#3852)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub Action <[email protected]>
2024-07-30 14:24:25 +12:00
Joaquim VergesandGitHub bd44ce935e chore(thirdweb): better TSdocs + more exports (#3869) 2024-07-30 13:39:58 +12:00
gregfromstl 109575eba5 fix(react): update social button styling and behavior logic (#3867)
![Screenshot 2024-07-29 at 5.35.57 PM.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/G5kV6fAq4H1wu10SVop6/b85da5cc-045e-47b9-bde4-e85321c2d802.png)

![Screenshot 2024-07-29 at 4.33.04 PM.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/G5kV6fAq4H1wu10SVop6/36aa163a-2d6a-450f-879f-35a81078360a.png)

![Screenshot 2024-07-29 at 4.30.51 PM.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/G5kV6fAq4H1wu10SVop6/587c10c8-ccd3-4578-a609-83842a037894.png)

<!-- start pr-codex -->

---

## PR-Codex overview
This PR increases the minimum number of social logins displayed before switching to a different layout. It also adjusts the styling of the social login buttons.

### Detailed summary
- Increased minimum social logins displayed to 3
- Adjusted social login buttons layout based on the number of logins
- Updated styling for social login buttons to improve alignment and spacing

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

<!-- end pr-codex -->
2024-07-29 23:21:36 +00:00
kien-ngo e27ebef85b Prebuilt UI: BuyDirectListingButton for Marketplace v3 (#3847)
<!-- start pr-codex -->

## PR-Codex overview
This PR adds a new prebuilt component `BuyDirectListingButton` for Marketplace v3 in Thirdweb.

### Detailed summary
- Added `BuyDirectListingButton` component for buying NFTs from a listing
- Includes necessary logic for preparing and executing transactions
- Provides detailed documentation and testing for the component

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

<!-- end pr-codex -->
2024-07-29 22:39:16 +00:00
Manan TankandGitHub f31e21196a [dashboard] Fix faucet filter in chainlist page (#3859) 2024-07-29 22:37:50 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
5f8c7976dc chore(deps): bump CodSpeedHQ/action from 2 to 3 (#3858)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-29 15:01:42 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
07cc040391 chore(deps): bump tailwind-merge from 2.3.0 to 2.4.0 (#3862)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-29 15:00:52 -07:00
kien-ngo 91edae58a7 <Crusade> Dashboard to v5 (#3843)
<!-- start pr-codex -->

## PR-Codex overview
This PR exposes `multicall` and `encodeSafeTransferFrom` extensions, adds `RequiredParam` type, and updates NFT UI components.

### Detailed summary
- Exposed `multicall` and `encodeSafeTransferFrom` extensions
- Added `RequiredParam` type
- Updated NFT UI components with new features and improvements

> The following files were skipped due to too many changes: `apps/dashboard/src/contract-ui/tabs/nfts/components/transfer-tab.tsx`, `apps/dashboard/src/contract-ui/tabs/nfts/components/burn-tab.tsx`, `apps/dashboard/src/contract-ui/tabs/nfts/components/airdrop-tab.tsx`

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

<!-- end pr-codex -->
2024-07-29 21:38:25 +00:00
kien-ngo 7ec421f0e7 Add util function: convertParamValues (#3854)
## Problem solved

Short description of the bug fixed or feature added

## Changes made

- [ ] Public API changes: list the public API changes made if any
- [ ] Internal API changes: explain the internal logic changes

## How to test

- [ ] Automated tests: link to unit test file
- [ ] Manual tests: step by step instructions on how to test

## Contributor NFT

Paste in your wallet address below and we will airdrop you a special NFT when your pull request is merged.

```Address: ```

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to add a utility function `parseAbiParams` to convert parameter values based on type for Solidity smart contracts.

### Detailed summary
- Added `parseAbiParams` function to convert parameter values
- Added tests for `parseAbiParams` function
- Utility for ensuring correct parameter formatting

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

<!-- end pr-codex -->
2024-07-29 21:21:46 +00:00
gregfromstl d5e546726a feat(thirdweb): adds useChainMetadata hook to retrieve metadata for a chain (#3857)
### TL;DR

This PR adds a new hook, `useChainMetadata`, to the thirdweb library. The hook allows developers to retrieve metadata for a specific blockchain, such as name, icon, available faucets, and block explorers.

### What changed?

- Added `useChainMetadata` hook in `thirdweb/react`.
- Deprecated `useChainQuery` hook.
- Updated documentation to reflect the new hook.

### How to test?

1. Import the `useChainMetadata` from `thirdweb/react`.
2. Call the hook with a chain defined using `defineChain`.
3. Check the returned metadata for correctness.

### Why make this change?

This change provides a more intuitive and documented way to retrieve chain metadata, replacing the deprecated `useChainQuery` hook. It enhances developer experience by offering a straightforward API to access chain-related information.

---

<!-- start pr-codex -->

---

## PR-Codex overview
This PR adds a new hook `useChainMetadata` to retrieve chain metadata in Thirdweb React. It also updates the `useChainQuery` hook to `useChainMetadata`.

### Detailed summary
- Added `useChainMetadata` hook to retrieve chain metadata
- Updated `useChainQuery` to `useChainMetadata`
- Improved documentation for `useChainMetadata`

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

<!-- end pr-codex -->
2024-07-29 21:02:05 +00:00
gregfromstl e26d0705f7 fix: passkey, email, phone auth (#3860)
### TL;DR
Updated the in-app wallet authentication logic to correctly handle redirect strategies. The previous logic incorrectly threw an error when the strategy was within the list of supported social authentication options.

### What changed?
Modified the condition to check if the strategy is included in the socialAuthOptions and call `connector.authenticateWithRedirect` accordingly.

### How to test?
1. Set up an in-app wallet with a supported social authentication strategy.
2. Initiate the authentication process and verify that the redirection occurs without errors.

### Why make this change?
Ensures that supported social authentication methods that require redirection are handled correctly without causing errors.

---
2024-07-29 20:44:32 +00:00
Manan TankandGitHub 77b852af16 Fix contract card height in dashboard (#3853) 2024-07-29 15:58:22 +00:00
Manan TankandGitHub 9b043315bf Disable system option in next-theme provider (#3855) 2024-07-29 21:17:13 +05:30
kien-ngo cdb2970806 ClaimButton to handle approval for ERC20 (#3846)
## Problem solved

Short description of the bug fixed or feature added

## Changes made

- [ ] Public API changes: list the public API changes made if any
- [ ] Internal API changes: explain the internal logic changes

## How to test

- [ ] Automated tests: link to unit test file
- [ ] Manual tests: step by step instructions on how to test

## Contributor NFT

Paste in your wallet address below and we will airdrop you a special NFT when your pull request is merged.

```Address: ```

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to handle ERC20 approval for the ClaimButton component in the Thirdweb package.

### Detailed summary
- Added `getPayMetadata` function to handle custom Pay metadata
- Updated `ClaimButton` component to handle ERC20 approval
- Utilized hooks for contract interaction and transaction handling

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

<!-- end pr-codex -->
2024-07-29 11:50:27 +00:00
gregfromstl dcfc9363fa docs: jsdoc content improvements (#3851)
### TL;DR

This PR enhances the `createThirdwebClient` and `download` functions by adding detailed descriptions, examples, and additional parameters.

### What changed?

1. `createThirdwebClient` function now includes options for `clientId` and `secretKey`.
2. `download` function now supports multiple URI schemes (IPFS, Arweave, HTTP) and includes examples for each.
3. Added `requestTimeoutMs` parameter to `download` function.
4. Improved JSDoc comments and examples for both functions.

### How to test?

- Create a Thirdweb client using both client ID and secret key, and test its functionality.
- Test downloading files using IPFS, Arweave, and HTTP URIs with different timeout settings.

### Why make this change?

These changes enhance the flexibility and usability of the Thirdweb client and download functions by providing more detailed documentation and additional configurable parameters. This aims to improve developer experience and clarity.

---

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to enhance the Thirdweb SDK by adding the ability to create a client using a client ID or secret key and improving the file download functionality.

### Detailed summary
- Updated `createThirdwebClient` function to accept `clientId` and `secretKey`
- Added support for downloading files from IPFS, Arweave, or HTTP URIs in the `download` function
- Improved error handling and request timeout handling in the `download` function

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

<!-- end pr-codex -->
2024-07-29 05:00:49 +00:00
Jonas DanielsandGitHub 78651115d2 Update CODEOWNERS (#3850)
Signed-off-by: Jonas Daniels <[email protected]>
2024-07-28 18:52:18 -07:00
kien-ngo 7abe1b528f Update templates demo links (#3849)
## Problem solved

Short description of the bug fixed or feature added

## Changes made

- [ ] Public API changes: list the public API changes made if any
- [ ] Internal API changes: explain the internal logic changes

## How to test

- [ ] Automated tests: link to unit test file
- [ ] Manual tests: step by step instructions on how to test

## Contributor NFT

Paste in your wallet address below and we will airdrop you a special NFT when your pull request is merged.

```Address: ```

<!-- start pr-codex -->

---

## PR-Codex overview
This PR updates homepage URLs for the `Vite Starter` and `Next Starter` templates to include `https://`.

### Detailed summary
- Updated homepage URL for `Vite Starter` template
- Updated homepage URL for `Next Starter` template

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

<!-- end pr-codex -->
2024-07-29 00:34:52 +00:00
2e549837f7 Add @component toshow component on components section in docs (#3832)
Co-authored-by: Joaquim Verges <[email protected]>
2024-07-28 16:51:01 -07:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>GitHub Action
4f539ad8d4 Version Packages (#3837)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub Action <[email protected]>
2024-07-28 09:04:01 +12:00
gregfromstl b551b69291 feat(react): add tabs to view assets screen (#3845)
1. Renamed `ViewFunds` to `ViewAssets` throughout the codebase for better clarity.
2. Updated file names and corresponding imports to reflect this change.
3. Modified the styling of the tabs on the `TransactionsScreen`.
4. Updated the grid layout and spacing in the `ViewNFTs` component.
5. Streamlined token viewing logic by creating reusable content components for tokens and NFTs in `ViewAssets`, `ViewNFTs`, and `ViewTokens`.

---

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to restyle the View Assets Connect UI page and rename `ViewFunds` to `ViewAssets`.

### Detailed summary
- Restyled the View Assets Connect UI page
- Renamed `ViewFunds` component to `ViewAssets`
- Updated references and function names accordingly
- Added new components `ViewTokensContent` and `ViewNFTsContent`
- Updated UI layout and styling for better user experience

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

<!-- end pr-codex -->
2024-07-27 19:53:41 +00:00
gregfromstl 6901a41839 feat(react): adds tab icons to connect ui transactions page (#3844)
![Screenshot 2024-07-27 at 2.07.20 PM.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/G5kV6fAq4H1wu10SVop6/006213aa-0e02-4b06-a3ec-335bcbb91069.png)
![Screenshot 2024-07-27 at 2.07.25 PM.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/G5kV6fAq4H1wu10SVop6/acc841ae-cd8d-4e02-942c-4872aa2b4c2c.png)

### TL;DR
Improved the TransactionsScreen UI in the thirdweb package by adding new icons for better visualization and adjusted some layout styles for uniformity.

### What changed?
- Added CoinsIcon and FundsIcon for better tab representation in TransactionsScreen.tsx.
- Updated Tabs component to support labels with React nodes.
- Implemented padding and minHeight adjustments in BuyTxHistory and WalletTransactionHistory components.
- Conditionally rendered transaction history buttons only when transactions are available.

### How to test?
1. Navigate to the TransactionsScreen in the thirdweb package.
2. Verify that the tabs now display icons alongside text labels.
3. Check the layout adjustments in the transaction history components for proper spacing and padding.

### Why make this change?
To enhance the user experience by improving the visual representation of tabs and ensuring consistency in the layout of transaction history components.

---
2024-07-27 19:24:47 +00:00
kien-ngo d775333b40 Expose ERC20 extension: getApprovalForTransaction (#3831)
## Problem solved

Short description of the bug fixed or feature added

## Changes made

- [ ] Public API changes: list the public API changes made if any
- [ ] Internal API changes: explain the internal logic changes

## How to test

- [ ] Automated tests: link to unit test file
- [ ] Manual tests: step by step instructions on how to test

## Contributor NFT

Paste in your wallet address below and we will airdrop you a special NFT when your pull request is merged.

```Address: ```

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to expose a new ERC20 extension function `getApprovalForTransaction` for handling ERC20 token approvals.

### Detailed summary
- Exposed `getApprovalForTransaction` in `erc20.ts`
- Added `getApprovalForTransaction` function in `getApprovalForTransaction.ts`
- Defined `GetApprovalForTransactionParams` interface in `getApprovalForTransaction.ts`
- Provided detailed documentation and example usage for `getApprovalForTransaction`

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

<!-- end pr-codex -->
2024-07-27 18:44:11 +00:00
gregfromstl b0a303d5ef feat: farcaster login (#3827)
### TL;DR

Added Farcaster icon and login support to the thirdweb package.

### What changed?

- Added Farcaster icon to `socialIcons.ts` and `svgs.ts`
- Updated `WalletImage.tsx` to include Farcaster icon.
- Added Farcaster as a supported social login option throughout the codebase.

### How to test?

1. Ensure the Farcaster icon is rendered correctly by using the Farcaster login option.
2. Verify the Farcaster login flow works as expected on both web and native applications.

### Why make this change?

This update adds support for Farcaster as a social login option, enhancing the flexibility and options available to users for authentication.

---

<!-- start pr-codex -->

---

## PR-Codex overview
This PR adds support for the "Farcaster" authentication option in various parts of the application.

### Detailed summary
- Added "Farcaster" as an authentication option
- Updated login and connection flows to include "Farcaster"
- Introduced Farcaster icons for web and native UI components
- Enhanced social auth login paths to support Farcaster

> The following files were skipped due to too many changes: `packages/thirdweb/src/react/core/utils/socialIcons.ts`

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

<!-- end pr-codex -->
2024-07-27 06:24:10 +00:00
MananTank 95d90ea344 Explore page UI tweaks (#3840)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to update UI components and improve code readability in the dashboard explore feature.

### Detailed summary
- Updated UI components in `ContractCard` and `PublishUpsellCard`
- Simplified `showSkeleton` logic in `ContractCard`
- Replaced `ChakraNextImage` with `Image` and `Button` components
- Reorganized JSX structure for better readability

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

<!-- end pr-codex -->
2024-07-27 03:48:11 +00:00
jnsdls 0da9703284 [Refactor] Remove unused TimeRangeSwitcher component (#3839) 2024-07-27 01:17:30 +00:00
MananTank 22f7a5ddb3 Update Explorer page layout to tailwind, add Modular contracts (#3836)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to enhance the UI/UX of the dashboard explore section and components.

### Detailed summary
- Updated styling and layout for Explore page components
- Added `TrackedLinkTW` component for analytics tracking
- Introduced `isBeta` flag for contracts
- Improved UI consistency and accessibility across components

> The following files were skipped due to too many changes: `apps/dashboard/src/components/explore/upsells/deploy-your-own.tsx`, `apps/dashboard/src/components/explore/contract-card/index.tsx`

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

<!-- end pr-codex -->
2024-07-27 01:11:56 +00:00
Manan TankandGitHub 7cb39cdd2a Fix flash of dark theme when loading dashboard in light mode + replace useColorMode with useTheme (#3838) 2024-07-27 00:32:47 +00:00
Manan TankandGitHub b128530355 Move connection manager creation to context instead of global singleton (#3817) 2024-07-26 23:13:22 +00:00
kumaryash90 dd3ae00279 Refresh button for contract metadata (#3834)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to add a feature for refreshing contract metadata in the Contract Sources page.

### Detailed summary
- Added `RefreshContractMetadataButton` component for refreshing contract metadata
- Imported `useMutation` and `useQueryClient` from `@tanstack/react-query`
- Imported `toast` from `sonner`
- Updated `VerifyContractParams` type to `ContractParams`
- Modified function parameters in `verifyContract`
- Updated conditional check in `ContractSourcesPage`
- Added logic to handle refreshing contract metadata and invalidating queries

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

<!-- end pr-codex -->
2024-07-26 21:20:28 +00:00
jnsdls 676411898b [Feature] Add support for Webhooks in Pay UI component (#3810)
CLOSES: DASH-88, DASH-87, DASH-85, DASH-86

<!-- start pr-codex -->

---

## PR-Codex overview
This PR enhances the Pay UI in the dashboard by adding a new "Webhooks" tab with functionality to create, view, and delete webhooks.

### Detailed summary
- Added a new `WebhooksPage` component
- Integrated webhooks functionality with API calls
- Implemented create and delete webhook features with dialogs
- Updated UI components for webhooks management

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

<!-- end pr-codex -->
2024-07-26 21:06:34 +00:00
jnsdls 169b02020d [Fix] Update AppFooter layout: streamline class names and enhance social media links (#3833)
Refactored the AppFooter component in the dashboard app to simplify the DOM structure, clean up redundant class names and properties, and group social media icons more effectively. Adjusted the layout to use container and grid classes for better organization.

---
2024-07-26 19:42:02 +00:00
kien-ngo 794282533c Add Vanar CTA text (#3828)
## Problem solved

Short description of the bug fixed or feature added

## Changes made

- [ ] Public API changes: list the public API changes made if any
- [ ] Internal API changes: explain the internal logic changes

## How to test

- [ ] Automated tests: link to unit test file
- [ ] Manual tests: step by step instructions on how to test

## Contributor NFT

Paste in your wallet address below and we will airdrop you a special NFT when your pull request is merged.

```Address: ```

<!-- start pr-codex -->

---

## PR-Codex overview
This PR updates the `title` property in the `ChainMetadata` object in `utils.ts`.

### Detailed summary
- Updated the `title` property value in the `ChainMetadata` object to "Fully EVM compatible L1 for Entertainment".

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

<!-- end pr-codex -->
2024-07-26 16:05:31 +00:00
MananTank ebfcbd7051 Fix various UI issues/improvements in dashboard (#3829)
* Improved Dialog styles on mobile
* Use the correct color in form error message
* Fix z-index issue with footer
* Fix z-index issue with tab underline
* Fix padding for various other elements

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to update styles and components in the dashboard layout.

### Detailed summary
- Added padding to a container in `layout.tsx`
- Updated form layout in `create-ticket.client.tsx`
- Adjusted styling in `sidebar.client.tsx`
- Enhanced uninstall dialog in `InstalledExtensionsTable.tsx`
- Modified classnames in `form.tsx`
- Revised dialog styles in `dialog.tsx`
- Refactored layout structure in `index.tsx`

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

<!-- end pr-codex -->
2024-07-26 15:12:22 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>GitHub Action
9eea6e17ab Version Packages (#3819)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub Action <[email protected]>
2024-07-26 21:20:50 +12:00
jnsdls 74714ccf31 [Feature] Add AppFooter component and integrate it across the app (#3825)
- New `AppFooter` component added in `app-footer.tsx` under `components/blocks`.
- Replaced `DashboardFooter` with `AppFooter` in `dashboard/layout.tsx`.
- Deleted old `DashboardFooter` implementation.
- Updated social icons and layout in the footer.
- Adjusted `DashboardHeader` styles for consistency.

---

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to update the footer component and layout in the dashboard app.

### Detailed summary
- Changed `DashboardFooter` to `AppFooter` in `DashboardLayout`
- Updated styles and content in `AppFooter`
- Removed `MobileBurgerMenu` import
- Updated button variant in `MobileBurgerMenu`
- Updated header layout in `DashboardHeader`

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

<!-- end pr-codex -->
2024-07-26 08:03:19 +00:00
4a4a0612ed feat(pay): Add metadata support for purchase flows (#3750)
Co-authored-by: Manan Tank <[email protected]>
2024-07-26 20:00:51 +12:00
MananTank c7f8bea4bc Move faucet inside chain page layout + UI tweaks (#3824)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to refactor the `faucet` page in the dashboard for a specific chain.

### Detailed summary
- Moved `getChain` import to a different path
- Reorganized `InfoCard` and added new headings with styling
- Updated `SpinWheel` component with `Skeleton` import and conditional rendering

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

<!-- end pr-codex -->
2024-07-26 00:09:33 +00:00
gregfromstl 3848327373 feat(thirdweb): adds redirect oauth (#3822)
### TL;DR

Added support for OAuth redirects in the In-App wallet authentication flow.

### What changed?

1. Introduced `auth.mode` with options `

---

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces the ability to open OAuth windows as a redirect, beneficial for embedded applications like Telegram web apps.

### Detailed summary
- Added `mode: "redirect"` option for OAuth windows
- Implemented functions for OAuth redirection
- Updated authentication options for in-app wallets

> The following files were skipped due to too many changes: `packages/thirdweb/src/react/core/hooks/wallets/useAutoConnect.ts`, `packages/thirdweb/src/wallets/in-app/web/lib/web-connector.ts`

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

<!-- end pr-codex -->
2024-07-25 23:33:31 +00:00
FirekeeperandGitHub bff7a0af6f Unity 4.17.0 (#3812) 2024-07-25 14:49:19 -07:00
Manan TankandGitHub d25a169d47 Fix Modular contracts encodeAbi error when deploying (#3823) 2024-07-26 02:53:05 +05:30
YashandGitHub 9e0dd0194b Fix transaction count for modular deployments (#3820) 2024-07-26 01:29:37 +05:30
Manan TankandGitHub 3ffd555e15 Move /trending page inside dashboard layout (#3816) 2024-07-25 18:47:56 +00:00
Manan TankandGitHub 87dc9a5f90 Allow selecting non-connected wallet on sign-in screen in ConnectEmbed (#3815) 2024-07-25 18:26:53 +00:00
kien-ngo 6081ac7b18 chore: Remove more v4 code from Dashboard (#3813)
## Problem solved

Short description of the bug fixed or feature added

## Changes made

- [ ] Public API changes: list the public API changes made if any
- [ ] Internal API changes: explain the internal logic changes

## How to test

- [ ] Automated tests: link to unit test file
- [ ] Manual tests: step by step instructions on how to test

## Contributor NFT

Paste in your wallet address below and we will airdrop you a special NFT when your pull request is merged.

```Address: ```

<!-- start pr-codex -->

---

## PR-Codex overview
This PR exposes new types `NFTInput` and `NFTMetadata`, updates type imports, and adds `SUPPORTED_CHAIN_ID` type.

### Detailed summary
- Exposed types: `NFTInput` and `NFTMetadata`
- Updated type imports in various files
- Added `SUPPORTED_CHAIN_ID` type definition

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

<!-- end pr-codex -->
2024-07-25 17:31:36 +00:00
kien-ngo 80379a22e3 Give Dashboard > Marketplace section some luv (#3811)
Use this preview link to test:
https://thirdweb.com/avalanche-fuji/0x8C1D464B385A2B7EAa80dcAAD66DD8BC0256e717/direct-listings

<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to enhance the listing details display in the dashboard UI.

### Detailed summary
- Added `Listing ID` and `Type` display sections
- Improved `Status` section with additional text for clarity
- Included `Price` section with currency value and symbol
- Commented out a TODO for adding a Buy button in the future

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

<!-- end pr-codex -->
2024-07-25 16:42:10 +00:00
kien-ngo 97a8405d4e Update Vanar page (thirdweb.com/vanar) (#3814)
Note: We are still waiting for the CTA text from them

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to add support for the VANAR blockchain in the dashboard.

### Detailed summary
- Added support for VANAR blockchain in `utils.ts`
- Imported `vanarBanner` and `vanarCTABG` images
- Defined metadata for VANAR blockchain in `chainMetaRecord`

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

<!-- end pr-codex -->
2024-07-25 16:37:02 +00:00
jnsdls 26c7cf17d1 [Refactor] Remove radix toast dependencies and related components (#3808)
### TL;DR

This PR refactors the dashboard application by removing the custom toast component and its dependencies, and migrating to the 'sonner' library for toasts. Key changes include the deletion of toast-related components and utilities, adjustments to the `ExportToCSVButton` component to use 'sonner' for toast notifications, and the streamlining of `package.json` and `pnpm-lock.yaml` files.

### What changed?

- Removed custom toast components (`toast.tsx`, `toaster.tsx`, `use-toast.ts`).
- Updated `ExportToCSVButton.tsx` to use 'sonner' for toast notifications.
- Removed `@radix-ui/react-toast` dependency from `package.json` and `pnpm-lock.yaml`.
- Cleaned up `package.json` and `pnpm-lock.yaml` by removing the old toast dependencies.

### How to test?

1. Export a CSV in the dashboard and confirm that toast notifications appear correctly.
2. Check the application for any missing toast notifications that might indicate issues with the migration.

### Why make this change?

The custom toast implementation was redundant with the introduction of the 'sonner' library, which provides a more efficient and streamlined approach to toast notifications. This migration simplifies the codebase and reduces dependencies.

---
2024-07-25 05:34:06 +00:00
jnsdls df4e58b754 [Fix] Remove redundant z-index values in dialog and toast components (#3807) 2024-07-25 05:02:12 +00:00
GWSzeto d6bbca576b Explorer page to show transaction information (#3674)
- ETH RPC calls to block, transaction and receipt
- TODO: tooltips (copy from blockscout), replace in ENS names where appropriate, decode input data, detect whether it's a transfer or contract interaction, event logs page

### What it looks like
<img width="1055" alt="Screenshot 2024-07-12 at 11 00 23 AM" src="https://github.com/user-attachments/assets/182f392a-1f2a-4323-ab55-706374060b4a">

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on restructuring file paths and importing components for better organization in the dashboard chain pages.

### Detailed summary
- Moved components to `(chainPage)` directory for clarity
- Updated import paths for components in various files
- Refactored file paths for consistency and organization

> The following files were skipped due to too many changes: `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/tx/[txHash]/page.tsx`

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

<!-- end pr-codex -->
2024-07-25 04:49:46 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
79e34e1f81 Version Packages (#3794)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-07-24 21:46:52 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
284cfdf95c chore(deps): bump typedoc from 0.25.13 to 0.26.5 (#3780)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-24 21:26:56 -07:00
83517fbe08 chore(deps-dev): bump @testing-library/jest-dom from 6.4.6 to 6.4.7 (#3778)
Co-authored-by: dependabot <[email protected]>
2024-07-24 21:26:28 -07:00
9cc9f05f68 fix: bun detect (#3791)
Co-authored-by: Joaquim Verges <[email protected]>
Co-authored-by: Jonas Daniels <[email protected]>
2024-07-24 21:26:08 -07:00
dependabot 25b07c4ee7 chore(deps): bump next from 14.2.4 to 14.2.5 (#3776)
Bumps [next](https://github.com/vercel/next.js) from 14.2.4 to 14.2.5.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/vercel/next.js/releases">next's releases</a>.</em></p>
<blockquote>
<h2>v14.2.5</h2>
<blockquote>
<p>[!NOTE]<br />
This release is backporting bug fixes. It does <strong>not</strong> include all pending features/changes on canary.</p>
</blockquote>
<h3>Core Changes</h3>
<ul>
<li>avoid merging global css in a way that leaks into other chunk groups (<a href="https://redirect.github.com/vercel/next.js/issues/67373">#67373</a>)</li>
<li>Fix server action edge redirect with middleware rewrite (<a href="https://redirect.github.com/vercel/next.js/issues/67148">#67148</a>)</li>
<li>fix(next): reject protocol-relative URLs in image optimization (<a href="https://redirect.github.com/vercel/next.js/issues/65752">#65752</a>)</li>
<li>fix(next-swc): correct path interop to filepath for wasm (<a href="https://redirect.github.com/vercel/next.js/issues/65633">#65633</a>)</li>
<li>Use addDependency to track metadata route file changes (<a href="https://redirect.github.com/vercel/next.js/issues/66714">#66714</a>)</li>
<li>Fix noindex is missing on static not-found page (<a href="https://redirect.github.com/vercel/next.js/issues/67135">#67135</a>)</li>
<li>perf: improve retrieving versionInfo on Turbo HMR (<a href="https://redirect.github.com/vercel/next.js/issues/67309">#67309</a>)</li>
<li>fix(next/image): handle invalid url (<a href="https://redirect.github.com/vercel/next.js/issues/67465">#67465</a>)</li>
<li>fix(next): initial prefetch cache not set properly with different search params (<a href="https://redirect.github.com/vercel/next.js/issues/65977">#65977</a>)</li>
<li>fix: Backport class properties fix (<a href="https://redirect.github.com/vercel/next.js/issues/67377">#67377</a>)</li>
<li>Upgrade acorn (<a href="https://redirect.github.com/vercel/next.js/issues/67592">#67592</a>)</li>
</ul>
<h3>Misc</h3>
<ul>
<li>Log stdio for pull-turbo-cache script (<a href="https://redirect.github.com/vercel/next.js/issues/66759">#66759</a>)</li>
<li>Ensure turbo is setup when building in docker (<a href="https://redirect.github.com/vercel/next.js/issues/66804">#66804</a>)</li>
</ul>
<h3>Credits</h3>
<p>Huge thanks to <a href="https://github.com/devjiwonchoi"><code>@​devjiwonchoi</code></a>, <a href="https://github.com/ijjk"><code>@​ijjk</code></a>, <a href="https://github.com/emmerich"><code>@​emmerich</code></a>, <a href="https://github.com/huozhi"><code>@​huozhi</code></a>,  <a href="https://github.com/kdy1"><code>@​kdy1</code></a>, <a href="https://github.com/kwonoj"><code>@​kwonoj</code></a>, <a href="https://github.com/styfle"><code>@​styfle</code></a>, and <a href="https://github.com/sokra"><code>@​sokra</code></a> for helping!</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/vercel/next.js/commit/0bf7f52db8b2c1e0b13d332de105fab645240e1e"><code>0bf7f52</code></a> v14.2.5</li>
<li><a href="https://github.com/vercel/next.js/commit/30d6dfc8bb97dfa674033c27e5c6a09d6d8e11f0"><code>30d6dfc</code></a> fix: metadata route merging conflicts</li>
<li><a href="https://github.com/vercel/next.js/commit/186ec6b58b0e6cd74a00f72c3bf2d7e1fe1941aa"><code>186ec6b</code></a> Log stdio for pull-turbo-cache script (<a href="https://redirect.github.com/vercel/next.js/issues/66759">#66759</a>)</li>
<li><a href="https://github.com/vercel/next.js/commit/45656d3323d164cf3917a8d6ea21b1a4f34a9844"><code>45656d3</code></a> Ensure turbo is setup when building in docker (<a href="https://redirect.github.com/vercel/next.js/issues/66804">#66804</a>)</li>
<li><a href="https://github.com/vercel/next.js/commit/08e7fd1f010077b13e29a59ce0a5edc50e4886ec"><code>08e7fd1</code></a> Upgrade acorn (<a href="https://redirect.github.com/vercel/next.js/issues/67592">#67592</a>)</li>
<li><a href="https://github.com/vercel/next.js/commit/1d08dab887a349ebd010e99201fd64000d030066"><code>1d08dab</code></a> avoid merging global css in a way that leaks into other chunk groups (<a href="https://redirect.github.com/vercel/next.js/issues/67373">#67373</a>)</li>
<li><a href="https://github.com/vercel/next.js/commit/21a9d591412e2dd0473808216c8edce854d27d88"><code>21a9d59</code></a> Fix server action edge redirect with middleware rewrite (<a href="https://redirect.github.com/vercel/next.js/issues/67148">#67148</a>)</li>
<li><a href="https://github.com/vercel/next.js/commit/1b10b13a7486d223df87d82e93b75eac2e8ed65a"><code>1b10b13</code></a> fix(next): reject protocol-relative URLs in image optimization (<a href="https://redirect.github.com/vercel/next.js/issues/65752">#65752</a>)</li>
<li><a href="https://github.com/vercel/next.js/commit/c64c61d8a8c06d4c6f8d8c773a662c12ac20635e"><code>c64c61d</code></a> fix(next-swc): correct path interop to filepath for wasm (<a href="https://redirect.github.com/vercel/next.js/issues/65633">#65633</a>)</li>
<li><a href="https://github.com/vercel/next.js/commit/6c661d2ce5126de18abb8f6326e79725dbd5493c"><code>6c661d2</code></a> Use addDependency to track metadata route file changes (<a href="https://redirect.github.com/vercel/next.js/issues/66714">#66714</a>)</li>
<li>Additional commits viewable in <a href="https://github.com/vercel/next.js/compare/v14.2.4...v14.2.5">compare view</a></li>
</ul>
</details>
<br />

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=next&package-manager=npm_and_yarn&previous-version=14.2.4&new-version=14.2.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)

</details>

<!-- start pr-codex -->

---

## PR-Codex overview
This PR updates the Next.js version to 14.2.5 in multiple packages and dependencies.

### Detailed summary
- Updated Next.js version to 14.2.5 in `wallet-ui`, `playground-web`, `dashboard`
- Updated `next-auth` to version 4.24.7
- Updated `typescript` to version 5.5.2

> 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-07-25 03:34:07 +00:00
Joaquim VergesandGitHub b27c842f26 chore(claim-button): add ClaimButton component changeset (#3806) 2024-07-25 15:14:47 +12:00
dependabot 10c292d7bd chore(deps): bump viem from 2.16.5 to 2.17.10 (#3783)
Bumps [viem](https://github.com/wevm/viem) from 2.16.5 to 2.17.10.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/wevm/viem/releases">viem's releases</a>.</em></p>
<blockquote>
<h2>[email protected]</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p><a href="https://redirect.github.com/wevm/viem/pull/2513">#2513</a> <a href="https://github.com/wevm/viem/commit/3af06fe23dda1f44d43b3d3cec5d985894c2840a"><code>3af06fe</code></a> Thanks <a href="https://github.com/hoangtan282"><code>@​hoangtan282</code></a>! - Added Funki Mainnet.</p>
</li>
<li>
<p><a href="https://redirect.github.com/wevm/viem/pull/2519">#2519</a> <a href="https://github.com/wevm/viem/commit/01cdac14d508fbae50a31492e244b7adbe858bab"><code>01cdac1</code></a> Thanks <a href="https://github.com/cbfyi"><code>@​cbfyi</code></a>! - Added dispute game factory address for Base Sepolia.</p>
</li>
<li>
<p><a href="https://redirect.github.com/wevm/viem/pull/2515">#2515</a> <a href="https://github.com/wevm/viem/commit/b7e4fa518b1798741cf029f34ed3154695ab3a16"><code>b7e4fa5</code></a> Thanks <a href="https://github.com/JoeyKhd"><code>@​JoeyKhd</code></a>! - Added Root Network chain.</p>
</li>
</ul>
<h2>[email protected].9</h2>
<h3>Patch Changes</h3>
<ul>
<li><a href="https://github.com/wevm/viem/commit/b71e656e08dadc44e2c1eccb5f505f70ce4d3aaf"><code>b71e656e</code></a> Thanks <a href="https://github.com/jxom"><code>@​jxom</code></a>! - Exported types required for inference.</li>
</ul>
<h2>[email protected].8</h2>
<h3>Patch Changes</h3>
<ul>
<li><a href="https://github.com/wevm/viem/commit/690cb9a78a801edf7ea3ab1d8cf1a0cd794fc32a"><code>690cb9a7</code></a> Thanks <a href="https://github.com/jxom"><code>@​jxom</code></a>! - Exported types required for inference.</li>
</ul>
<h2>[email protected].7</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p><a href="https://github.com/wevm/viem/commit/7d3d505221d4bb2ccc002be1cddc9e2011e33c01"><code>7d3d505</code></a> Thanks <a href="https://github.com/jxom"><code>@​jxom</code></a>! - Allow override of <code>Content-Type</code> header on <code>http</code> transport.</p>
</li>
<li>
<p><a href="https://github.com/wevm/viem/commit/aa42f47fe8b5ce19858e5855ecdceae7000dbb92"><code>aa42f47</code></a> Thanks <a href="https://github.com/jxom"><code>@​jxom</code></a>! - Updated Darwinia chain explorer URL.</p>
</li>
<li>
<p><a href="https://github.com/wevm/viem/commit/759e34dde23ca50275d9e4df38805e8f0b285753"><code>759e34d</code></a> Thanks <a href="https://github.com/jxom"><code>@​jxom</code></a>! - Enforced <code>r</code> and <code>s</code> hex values on <code>Signature</code> to be always padded to 32 bytes.</p>
</li>
</ul>
<h2>[email protected].5</h2>
<h3>Patch Changes</h3>
<ul>
<li><a href="https://redirect.github.com/wevm/viem/pull/2500">#2500</a> <a href="https://github.com/wevm/viem/commit/f6d60054bdcf8ada44c8af46b66eda50b05dd08b"><code>f6d60054</code></a> Thanks <a href="https://github.com/lucadonnoh"><code>@​lucadonnoh</code></a>! - Added OP Stack contract addresses for Mode Testnet chain.</li>
</ul>
<h2>[email protected].4</h2>
<h3>Patch Changes</h3>
<ul>
<li><a href="https://redirect.github.com/wevm/viem/pull/2493">#2493</a> <a href="https://github.com/wevm/viem/commit/ef3601d1db04e41c993943c0cfc72d3a64bbb6db"><code>ef3601d</code></a> Thanks <a href="https://github.com/billalxcode"><code>@​billalxcode</code></a>! - Added DreyerX Testnet chain</li>
</ul>
<h2>[email protected].3</h2>
<h3>Patch Changes</h3>
<ul>
<li><a href="https://github.com/wevm/viem/commit/ec3b0e08f0a379249224e65092277191f1a8502b"><code>ec3b0e0</code></a> Thanks <a href="https://github.com/jxom"><code>@​jxom</code></a>! - Added fallback verification in <code>verifyHash</code>.</li>
</ul>
<h2>[email protected].2</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p><a href="https://redirect.github.com/wevm/viem/pull/2479">#2479</a> <a href="https://github.com/wevm/viem/commit/5028b3fb723100e49ca9b301405360b23c2a1003"><code>5028b3f</code></a> Thanks <a href="https://github.com/keyding"><code>@​keyding</code></a>! - Added Artela Testnet chain.</p>
</li>
<li>
<p><a href="https://redirect.github.com/wevm/viem/pull/2478">#2478</a> <a href="https://github.com/wevm/viem/commit/795ca46cf93bc496abb23a5b868ea48bd80860ae"><code>795ca46</code></a> Thanks <a href="https://github.com/sj719045032"><code>@​sj719045032</code></a>! - Added zkLink Nova Sepolia Testnet chain.</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/wevm/viem/commit/8e3c9ec058885ac94f5b3a3d8f38eee201130ab5"><code>8e3c9ec</code></a> chore: bump size</li>
<li><a href="https://github.com/wevm/viem/commit/892d62fd17d14e60cfcb36caa671516caee990c4"><code>892d62f</code></a> chore: version package (<a href="https://redirect.github.com/wevm/viem/issues/2520">#2520</a>)</li>
<li><a href="https://github.com/wevm/viem/commit/01cdac14d508fbae50a31492e244b7adbe858bab"><code>01cdac1</code></a> feat: add dispute game factory address for Base Sepolia (<a href="https://redirect.github.com/wevm/viem/issues/2519">#2519</a>)</li>
<li><a href="https://github.com/wevm/viem/commit/7e17bb1b7413cb9d9f406c6d274511a6c8b7eef4"><code>7e17bb1</code></a> chore: up solady test</li>
<li><a href="https://github.com/wevm/viem/commit/b7e4fa518b1798741cf029f34ed3154695ab3a16"><code>b7e4fa5</code></a> feat: add root and root poricini (<a href="https://redirect.github.com/wevm/viem/issues/2515">#2515</a>)</li>
<li><a href="https://github.com/wevm/viem/commit/c3fac1be047cac22b3e0e1bd154038754b2b583e"><code>c3fac1b</code></a> chore: tweak funkiMainnet</li>
<li><a href="https://github.com/wevm/viem/commit/42c197776b300c5c44f09e86157fa344ddc2659f"><code>42c1977</code></a> chore: format</li>
<li><a href="https://github.com/wevm/viem/commit/3af06fe23dda1f44d43b3d3cec5d985894c2840a"><code>3af06fe</code></a> feat: add Funki Mainnet (<a href="https://redirect.github.com/wevm/viem/issues/2513">#2513</a>)</li>
<li><a href="https://github.com/wevm/viem/commit/3354c46174cdb7e86036bf28b696a0ce6cf982d5"><code>3354c46</code></a> docs: add missing <code>http</code> import in the config file example (<a href="https://redirect.github.com/wevm/viem/issues/2517">#2517</a>)</li>
<li><a href="https://github.com/wevm/viem/commit/752680e14df5ef6b4afcff5c2b9a2ecd1491f1a7"><code>752680e</code></a> chore: update nonceManager tests</li>
<li>Additional commits viewable in <a href="https://github.com/wevm/viem/compare/[email protected]@2.17.10">compare view</a></li>
</ul>
</details>
<br />

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=viem&package-manager=npm_and_yarn&previous-version=2.16.5&new-version=2.17.10)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)

</details>

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is updating the `viem` package version from `2.16.5` to `2.17.10` across multiple locations.

### Detailed summary
- Updated `viem` package version from `2.16.5` to `2.17.10` in multiple files
- Peer dependencies and dev dependencies updated to `[email protected]`

> 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-07-25 02:45:39 +00:00
kumaryash90 8599fbf4e0 Deploy modular core with default extensions (#3524)
## Problem solved

Short description of the bug fixed or feature added

## Changes made

- [ ] Public API changes: list the public API changes made if any
- [ ] Internal API changes: explain the internal logic changes

## How to test

- [ ] Automated tests: link to unit test file
- [ ] Manual tests: step by step instructions on how to test

## Contributor NFT

Paste in your wallet address below and we will airdrop you a special NFT when your pull request is merged.

```Address: ```

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces support for modular extensions in contract publishing forms.

### Detailed summary
- Added support for modular extensions in contract publishing forms
- Updated extension input fields to handle modular extensions
- Implemented extension installation parameters for modular extensions

> The following files were skipped due to too many changes: `apps/dashboard/src/components/contract-components/contract-publish-form/index.tsx`, `legacy_packages/sdk/src/evm/common/any-evm-utils/getModularDeploymentInfo.ts`, `legacy_packages/sdk/src/evm/core/sdk.ts`

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

<!-- end pr-codex -->
2024-07-25 02:18:44 +00:00
jnsdls 5c9af853fa [Refactor] Simplify RPC client map key usage in getRpcClient function (#3805)
### TL;DR
Fixes an issue with RPC client reuse to improve performance.

### What changed?
The change replaces the use of `chainId` with `rpcUrl` as the key in the `rpcClientMap` to ensure the correct RPC client is reused.

### How to test?
Test by running existing unit tests and functional tests for RPC client related functionality. Ensure that performance metrics show improvement in RPC client reuse scenarios.

### Why make this change?
This change is motivated by the need to improve performance by ensuring the RPC client is correctly reused.

---
2024-07-25 01:35:50 +00:00
joaquim-verges cb616f75ed fix(gas): correct gas estimation logic on Arbitrum Sepolia (#3804)
<!-- start pr-codex -->

## PR-Codex overview
This PR fixes gas estimation issues on Arbitrum Sepolia and ensures proper handling of zero `maxPriorityFeePerGas`.

### Detailed summary
- Fixed gas estimation for Arbitrum Sepolia
- Added test case for 0 `maxPriorityFeePerGas`
- Updated conditions for handling `maxPriorityFeePerGas` as `null`

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

<!-- end pr-codex -->
2024-07-25 00:36:07 +00:00
joaquim-verges c82c524e13 feat(smart): allow overriding nonce for smart accounts (#3782)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to allow overriding the nonce for smart accounts in the `thirdweb` package.

### Detailed summary
- Added the ability to override nonce for smart accounts
- Exported `generateRandomUint192` function
- Updated imports and added new functions in `userop.ts` file
- Modified `createUnsignedUserOp` function to use custom nonce logic

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

<!-- end pr-codex -->
2024-07-24 22:37:45 +00:00
joaquim-verges e7581fc5bd fix(tests): conditionally run ClaimButton tests based on TW_SECRET_KEY environment variable (#3803) 2024-07-24 22:32:07 +00:00
Manan TankandGitHub 8fa7eef5bc Add missing JSdoc tags for docs organization (#3802) 2024-07-24 20:40:38 +00:00
joaquim-verges 39b31d9d0c fix(tests): conditionally run tests based on TW_SECRET_KEY environment variable (#3790)
<!-- start pr-codex -->

## PR-Codex overview
This PR updates test descriptions to conditionally run based on a secret key presence.

### Detailed summary
- Updated test descriptions to run conditionally with `runIf` based on `TW_SECRET_KEY`
- Added conditional execution for specific test cases
- Ensured tests run only if the secret key is present

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

<!-- end pr-codex -->
2024-07-24 19:57:35 +00:00
gregfromstl a51f53f531 fix: standardize RPC URL construction across the codebase (#3801)
<!-- start pr-codex -->

## PR-Codex overview
This PR focuses on fixing the RPC URL construction for chains in the `thirdweb` package.

### Detailed summary
- Updated RPC URL construction in `IFrameWallet` for signing transactions and typed data
- Updated RPC URL construction in chain utilities for defining, caching, and converting chains

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

<!-- end pr-codex -->
2024-07-24 19:40:26 +00:00
gregfromstl b15118a34f fix(thirdweb): clean-up send funds styles (#3800)
### TL;DR

This pull request centers the text and aligns the spinner in the SendFunds button within the ConnectWallet screen.

### What changed?

- Added `textAlign: "center"` to the button style to center the text
- Moved the spinner alignment condition to ensure it appears correctly when the button is in a pending state

### How to test?

1. Navigate to the `ConnectWallet` screen
2. Trigger the `SendFunds` action
3. Verify that the button text is centered and the spinner is correctly aligned during pending state

### Why make this change?

This change improves the UI by ensuring the button text is consistently centered and the spinner is appropriately aligned during the fund sending process.

---

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on making minor style fixes on the Connect UI Send Funds page.

### Detailed summary
- Updated the text element to be centered and multiline with a red color for error messages
- Adjusted the conditional rendering of the spinner to display only when sending funds is pending

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

<!-- end pr-codex -->
2024-07-24 19:17:08 +00:00
kien-ngo f4d44428b4 Dashboard cleanup (#3789)
- [x] Remove ethers.utils.isAddress
- [x] Remove useBalanceForAddress
- [x] Remove useTransferNativeToken

<!-- start pr-codex -->

---

## PR-Codex overview
This PR updates wallet balance functions and address validation in various components.

### Detailed summary
- Updated `getWalletBalance` function parameter from `account` to `address`
- Replaced `utils.isAddress` with `isAddress` for address validation
- Updated balance retrieval and address validation in multiple components
- Added new wallet balance hooks for fetching balances
- Refactored deposit functionality to use new wallet balance hooks

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

<!-- end pr-codex -->
2024-07-24 17:50:46 +00:00
jnsdls 634923ae29 [Fix] Handle non-SVG chain icons correctly in opengraph-image component (#3799) 2024-07-24 17:22:02 +00:00
Kien NgoandGitHub 15df5f7cbf Update middleware.ts (#3798) 2024-07-24 15:18:34 +00:00
kien-ngo 105e523ce4 Prebuilt UI: ClaimButton for all thirdweb Drop contracts (#3785)
## Problem solved

Short description of the bug fixed or feature added

## Changes made

- [ ] Public API changes: list the public API changes made if any
- [ ] Internal API changes: explain the internal logic changes

## How to test

- [ ] Automated tests: link to unit test file
- [ ] Manual tests: step by step instructions on how to test

## Contributor NFT

Paste in your wallet address below and we will airdrop you a special NFT when your pull request is merged.

```Address: ```

<!-- start pr-codex -->

---

## PR-Codex overview
This PR adds a `ClaimButton` component for claiming tokens from thirdweb Drop contracts.

### Detailed summary
- Added `ClaimButton` component for thirdweb Drop contracts
- Defined types for different token claim parameters
- Implemented claim logic for ERC721, ERC1155, and ERC20 tokens
- Added tests for ERC721 and ERC1155 claim scenarios

> The following files were skipped due to too many changes: `packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/ClaimButton/ClaimButton.test.tsx`

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

<!-- end pr-codex -->
2024-07-24 10:19:35 +00:00
MananTank fc23b90c34 Dashboard color fixes (#3781)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to update text colors across the application for better consistency and clarity.

### Detailed summary
- Updated text color classes to `text-success-text` and `text-destructive-text` for better clarity and consistency.
- Renamed background color class from `bg-destructive` to `bg-warning` for better semantics.
- Adjusted CSS variables for text colors to enhance readability and maintain consistency.

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

<!-- end pr-codex -->
2024-07-24 07:55:31 +00:00
gregfromstl a560af22a1 fix(dashboard): audited contract icon alignment (#3793)
### TL;DR

Improve the UI layout of the contract-card component by adjusting spacing and removing unnecessary Skeleton wrappers.

### What changed?

The `gap` property for the `Flex` component was increased from 0 to 1 to provide better spacing. The `Skeleton` wrappers around the `Icon` and `Text` components were removed for a cleaner design.

### How to test?

1. Go to the dashboard and navigate to the explore section.
2. Check the contract-card components and observe the new spacing and the absence of loading skeletons around the `Icon` and `Text`.

### Why make this change?

The change is aimed at improving the user interface by making the contract-card component cleaner and visually more appealing.

---
2024-07-24 07:43:09 +00:00
Joaquim VergesandGitHub c51f7857e2 fix(gas): handle Polygon Amoy Gas Station fee data (#3796) 2024-07-24 13:29:09 +12:00
Manan TankandGitHub 5fabe66613 Fix XDC network sendTransaction issue (#3792) 2024-07-24 01:54:34 +05:30
kien-ngo 891bc988d6 update middleware to handle chainId: 404 (#3786)
<!-- start pr-codex -->

## PR-Codex overview
This PR ensures that the `possibleChainId` is not rewritten to the slug if it equals 404.

### Detailed summary
- Updated condition to exclude rewriting `possibleChainId` if it equals 404.

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

<!-- end pr-codex -->
2024-07-23 04:19:44 +00:00
MananTank 934ab63f6a Fix import contract not working in dashboard (#3784)
<!-- start pr-codex -->

## PR-Codex overview
This PR updates the `useRegistry.ts` and `hooks.ts` files to include a new `account` value of `300000n`.

### Detailed summary
- Updated `useRegistry.ts` and `hooks.ts` with `account: 300000n` value
- Called `deployContext.nextStep()` after the changes

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

<!-- end pr-codex -->
2024-07-22 23:42:27 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>GitHub Action
e0e4ce016c Version Packages (#3768)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub Action <[email protected]>
2024-07-23 10:22:02 +12:00
gregfromstl d3c83023f8 Auth Refactor (#3779)
### TL;DR
Improved the in-app wallet sign-in speed by refactoring OAuth path handling to make it more generic and efficient.

### What changed?
- Standardized the OAuth path handling to make it more generic and reusable across multiple providers.
- Updated `getLoginPath` to `getSocialAuthLoginPath` for OAuth providers like Google, Facebook, Apple, and Discord.
- Improved login speed and reduced redundancy by streamlining the OAuth path logic.
- Removed outdated and redundant code related to individual OAuth provider handling.

### How to test?
1. Test the sign-in process using various OAuth providers such as Google, Facebook, Apple, and Discord.
2. Ensure the redirection and sign-in speed are improved.
3. Verify that the in-app wallet sign-in works seamlessly without any errors.

### Why make this change?
The changes were necessary to optimize and standardize the OAuth sign-in process, improving the overall user experience. The previous implementation had redundant code for individual providers, which was refactored to be more efficient and easier to maintain.

---

<!-- start pr-codex -->

---

## PR-Codex overview
This PR improves in-app wallet sign-in speed by updating authentication strategies and paths.

### Detailed summary
- Updated OAuth authentication strategy to `SocialAuthOption`
- Improved login path retrieval for social authentication providers
- Refactored Discord-specific authentication to generic OAuth approach

> The following files were skipped due to too many changes: `packages/thirdweb/src/wallets/in-app/native/auth/native-auth.ts`

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

<!-- end pr-codex -->
2024-07-22 20:58:26 +00:00
gregfromstl a9a3f0f423 fix(deploy): add missing version argument in computeDeploymentInfoFromContractId function (#3769)
Fix deterministic deploys with specified versions by adding the 'version' argument to the 'computeDeploymentInfoFromContractId' function.

---

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on fixing deterministic deploys with specified versions in the `compute-published-contract-deploy-info.ts` file under `thirdweb` package.

### Detailed summary
- Added `version` field to `computePublishedContractDeployInfo` function parameters.
- Utilizes the specified version for deterministic deployments.

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

<!-- end pr-codex -->
2024-07-22 17:34:29 +00:00
jnsdls 3de2dce384 [Feature] Add placeholder chain to provider setup and custom SDK context, make middleware method async (#3773)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to enhance the app setup process by adding placeholder chains and improving dynamic routing.

### Detailed summary
- Added `PLACEHOLDER_CHAIN` object in `Billing.tsx` and `provider-setup.tsx`
- Updated context with placeholder chain if configured chains are empty
- Added dynamic routing logic in `middleware.ts` for chain IDs

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

<!-- end pr-codex -->
2024-07-22 15:28:44 +00:00
kien-ngo 4d392efc0c Hotfix: avoid page crash on loading :chainId/contractAddress (#3772)
<!-- start pr-codex -->

## PR-Codex overview
This PR updates a conditional check in the file `apps/dashboard/src/pages/[chain_id]/[...paths].tsx`.

### Detailed summary
- Updated conditional check for `configuredChain` to compare `getDashboardChainRpc` values for different chain IDs.

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

<!-- end pr-codex -->
2024-07-22 15:07:34 +00:00
kumaryash90 f082af0403 Proxy resolution with storage slot (#3687)
<!-- start pr-codex -->

## PR-Codex overview
This PR focuses on fixing proxy resolution in the `thirdweb` package. It includes updates to contract deployment and implementation extraction logic.

### Detailed summary
- Fixed proxy resolution in `resolveImplementation.ts`
- Added tests for extracting implementation address
- Updated proxy bytecode and constructor ABI for ERC1967 proxy
- Added `DUMMY_BYTECODE` for contract deployment

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

<!-- end pr-codex -->
2024-07-22 14:24:10 +00:00
jnsdls b07f9207a4 [Feature] Add Ecosystem Wallet Pricing Card component and integrate it across pages (#3770) 2024-07-22 10:52:50 +00:00
kien-ngo 9f555cab0d Dashboard: removal of @thirdweb-dev/chains (#3766)
## Problem solved

Short description of the bug fixed or feature added

## Changes made

- [ ] Public API changes: list the public API changes made if any
- [ ] Internal API changes: explain the internal logic changes

## How to test

- [ ] Automated tests: link to unit test file
- [ ] Manual tests: step by step instructions on how to test

## Contributor NFT

Paste in your wallet address below and we will airdrop you a special NFT when your pull request is merged.

```Address: ```

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to update chain definitions and RPC URLs, improve network configuration, and enhance contract component utilities.

### Detailed summary
- Updated chain definitions for various networks
- Adjusted RPC URLs in network configuration
- Enhanced contract component utilities with new features

> The following files were skipped due to too many changes: `packages/thirdweb/src/chains/chain-definitions/polygon-zkevm-testnet.ts`, `packages/thirdweb/src/chains/chain-definitions/scroll-sepolia-testnet.ts`, `packages/thirdweb/src/chains/chain-definitions/manta-pacific-testnet.ts`, `packages/thirdweb/src/chains/chain-definitions/scroll-alpha-testnet.ts`, `apps/dashboard/src/@3rdweb-sdk/react/hooks/useActiveChainId.tsx`, `apps/dashboard/src/lib/ens.ts`, `apps/dashboard/src/components/custom-contract/contract-header/contract-metadata.tsx`, `apps/dashboard/src/@3rdweb-sdk/react/hooks/useApi.ts`, `apps/dashboard/package.json`, `apps/dashboard/src/components/custom-contract/contract-header/metadata-header.tsx`, `apps/dashboard/src/constants/chains.ts`, `apps/dashboard/src/hooks/chains/configureChains.ts`, `apps/dashboard/src/lib/rpc.ts`, `apps/dashboard/src/pages/[chain_id]/[...paths].tsx`, `apps/dashboard/src/utils/tx-frame.ts`, `.changeset/beige-seas-design.md`, `apps/dashboard/src/utils/fetchChain.ts`, `apps/dashboard/src/components/settings/Account/Billing/CreditsItem.tsx`, `apps/dashboard/src/pages/publish/[...paths].tsx`, `apps/dashboard/src/@3rdweb-sdk/react/hooks/useFavoriteChains.ts`, `apps/dashboard/src/components/wallets/ConnectWalletPlayground/PreviewThirdwebProvider.tsx`, `apps/dashboard/src/lib/v5-adapter.ts`, `apps/dashboard/src/pages/profile/[profileAddress].tsx`, `apps/dashboard/src/@3rdweb-sdk/react/components/popularChains.ts`, `apps/dashboard/src/components/engine/overview/transactions-table.tsx`, `apps/dashboard/src/components/explore/contract-card/index.tsx`, `apps/dashboard/src/pages/api/revalidate/publish.ts`, `apps/dashboard/src/components/smart-wallets/AccountFactories/factory-contracts.tsx`, `apps/dashboard/src/components/smart-wallets/AccountFactories/index.tsx`, `apps/dashboard/src/components/contract-components/contract-publish-form/index.tsx`, `apps/dashboard/src/contexts/all-chains.tsx`, `apps/dashboard/src/components/app-layouts/provider-setup.tsx`, `apps/dashboard/src/components/shared/DeprecatedAlert.tsx`, `apps/dashboard/src/contract-ui/tabs/embed/components/embed-setup.tsx`, `apps/dashboard/src/constants/currencies.ts`, `packages/thirdweb/src/exports/chains.ts`, `apps/dashboard/src/contexts/configured-chains.tsx`, `apps/dashboard/src/components/contract-components/hooks.ts`, `pnpm-lock.yaml`, `apps/dashboard/src/lib/wallet/nfts/types.ts`

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

<!-- end pr-codex -->
2024-07-22 10:22:37 +00:00
kien-ngo 26d825bc4f Lens extensions (no Playground) (#3764)
<!-- start pr-codex -->

## PR-Codex overview
This PR adds extension support for the Lens Protocol, updates text in a component, and includes various changes related to Lens metadata handling.

### Detailed summary
- Added extension support for Lens Protocol
- Updated text in SponsorshipPolicies component
- Added functions in various Lens-related JSON files
- Modified test files to use `MAX_UINT256`
- Updated Lens profile schema and metadata attributes
- Added tests for Lens protocol functions and metadata retrieval

> The following files were skipped due to too many changes: `packages/thirdweb/src/extensions/lens/read/getHandleFromProfileId.test.ts`, `packages/thirdweb/src/extensions/lens/consts.ts`, `packages/thirdweb/src/extensions/lens/read/getHandleFromProfileId.ts`, `packages/thirdweb/src/extensions/lens/read/getProfileMetadata.ts`, `packages/thirdweb/src/extensions/lens/__generated__/FollowNFT/read/getFollowerCount.ts`, `packages/thirdweb/src/extensions/lens/__generated__/LensHandle/read/getHandleTokenURIContract.ts`, `packages/thirdweb/src/extensions/lens/read/getFullProfile.ts`, `packages/thirdweb/src/extensions/lens/__generated__/LensHub/read/nonces.ts`, `packages/thirdweb/src/extensions/lens/__generated__/LensHub/read/exists.ts`, `packages/thirdweb/src/extensions/lens/__generated__/TokenHandleRegistry/read/nonces.ts`, `packages/thirdweb/src/extensions/lens/__generated__/TokenHandleRegistry/read/resolve.ts`, `packages/thirdweb/src/extensions/lens/__generated__/LensHandle/read/getHandle.ts`, `packages/thirdweb/src/extensions/lens/__generated__/LensHandle/read/getTokenId.ts`, `packages/thirdweb/src/extensions/lens/__generated__/LensHandle/read/getLocalName.ts`, `packages/thirdweb/src/extensions/lens/__generated__/FollowNFT/read/isFollowing.ts`, `packages/thirdweb/src/extensions/lens/__generated__/LensHub/read/tokenDataOf.ts`, `packages/thirdweb/src/extensions/lens/__generated__/LensHub/read/mintTimestampOf.ts`, `packages/thirdweb/src/extensions/lens/__generated__/FollowNFT/read/mintTimestampOf.ts`, `packages/thirdweb/src/extensions/lens/__generated__/ModuleRegistry/read/getModuleTypes.ts`, `packages/thirdweb/src/extensions/lens/__generated__/TokenHandleRegistry/read/getDefaultHandle.ts`, `packages/thirdweb/src/extensions/lens/__generated__/FollowNFT/read/getFollowTokenId.ts`, `packages/thirdweb/src/extensions/lens/__generated__/LensHub/read/getContentURI.ts`, `packages/thirdweb/src/extensions/lens/__generated__/FollowNFT/read/getFollowTimestamp.ts`, `packages/thirdweb/src/extensions/lens/__generated__/ModuleRegistry/read/isModuleRegistered.ts`, `packages/thirdweb/src/extensions/lens/__generated__/FollowNFT/read/getFollowerProfileId.ts`, `packages/thirdweb/src/extensions/lens/__generated__/FollowNFT/read/getFollowData.ts`, `packages/thirdweb/src/extensions/lens/__generated__/LensHub/read/getProfile.ts`, `packages/thirdweb/src/extensions/lens/__generated__/LensHub/read/getProfileIdByHandleHash.ts`, `packages/thirdweb/src/extensions/lens/__generated__/ModuleRegistry/read/isErc20CurrencyRegistered.ts`, `packages/thirdweb/src/extensions/lens/__generated__/FollowNFT/read/getOriginalFollowTimestamp.ts`, `packages/thirdweb/src/extensions/lens/__generated__/ModuleRegistry/read/isModuleRegisteredAs.ts`, `packages/thirdweb/src/extensions/lens/__generated__/FollowNFT/read/getProfileIdAllowedToRecover.ts`, `packages/thirdweb/src/extensions/lens/__generated__/LensHub/read/getPublication.ts`, `packages/thirdweb/src/exports/extensions/lens.ts`

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

<!-- end pr-codex -->
2024-07-21 08:29:50 +00:00
kien-ngo 11b2ad05ad Remove @thirdweb-dev/sdk from dashboard (partially) (#3767)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to expose `roleMap` and `getRoleHash` functions.

### Detailed summary
- Exposed `roleMap` and `getRoleHash` functions in `permissions.ts`
- Updated imports to use `thirdweb` instead of `@thirdweb-dev/sdk`
- Added `roleMap` import in `permissions` component
- Updated address resolution and validation in `airdrop-upload.tsx`

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

<!-- end pr-codex -->
2024-07-20 19:43:03 +00:00
kien-ngo a580e6a71e [Dashboard to v5] Remove ethers.constants, some ethers.utils, some other things (#3765)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to refactor address-related functions and constants, consolidating them under `thirdweb` library.

### Detailed summary
- Refactored address-related functions and constants to use `thirdweb` library
- Updated imports and usage of `isAddress`, `ZERO_ADDRESS`, and `NATIVE_TOKEN_ADDRESS`
- Replaced `constants.AddressZero` with `ZERO_ADDRESS` where applicable

> The following files were skipped due to too many changes: `apps/dashboard/src/contract-ui/tabs/nfts/components/claim-tab.tsx`, `apps/dashboard/src/contract-ui/tabs/claim-conditions/components/claim-conditions-form/index.tsx`, `apps/dashboard/src/contract-ui/tabs/nfts/components/airdrop-upload.tsx`, `apps/dashboard/src/contract-ui/tabs/claim-conditions/components/snapshot-upload.tsx`, `apps/dashboard/src/contract-ui/tabs/split/page.tsx`, `apps/dashboard/src/contract-ui/tabs/permissions/components/permissions-editor.tsx`, `apps/dashboard/src/components/shared/CurrencySelector.tsx`, `apps/dashboard/src/contract-ui/tabs/permissions/components/contract-permission.tsx`, `apps/dashboard/src/@3rdweb-sdk/react/cache-keys.ts`

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

<!-- end pr-codex -->
2024-07-20 18:51:54 +00:00
kien-ngo 0148864ebc Playground Auth without Supabase example (#3757)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to enhance authentication and authorization features using Thirdweb for the `playground-web` app.

### Detailed summary
- Updated `client.ts` to handle secret key for Thirdweb client
- Modified authentication logic in `auth-button.tsx` and `basic-auth.tsx`
- Added gated content feature in `gated-content.tsx`
- Updated page layout and content for authentication in `page.tsx`

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

<!-- end pr-codex -->
2024-07-20 01:40:38 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>GitHub Action
9a29beb460 Version Packages (#3749)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub Action <[email protected]>
2024-07-20 13:32:24 +12:00
MananTank 6a94696c7e Fix Wallet switcher icon position in wallet details modal (#3762)
<!-- start pr-codex -->

## PR-Codex overview
This PR fixes the wallet switcher icon position in the wallet details modal.

### Detailed summary
- Adjusted the wallet switcher icon position in `Modal.tsx`
- Updated the `borderRadius` in `buttons.tsx`
- Added a new `ShuffleIconLucide` component in `ShuffleIconLucide.tsx`
- Replaced `ShuffleIcon` with `ShuffleIconLucide` in `Details.tsx`

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

<!-- end pr-codex -->
2024-07-19 22:52:06 +00:00
kumaryash90 d6b2c259d9 Register zksync contract on multichain registry after deployment (#3717)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to enhance the deployment process of contracts by adding a gas override option and improving the registration process on the multichain registry for ZkSync contracts.

### Detailed summary
- Added `gasOverride` option for contract deployment
- Improved ZkSync contract registration process
- Removed unnecessary contract registration function
- Updated contract deployment handling for ZkSync
- Refactored contract deployment logic and metadata handling

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

<!-- end pr-codex -->
2024-07-19 22:35:39 +00:00
Manan TankandGitHub 742207c8fe Fix Get started Billing form edit button not working (#3759) 2024-07-19 21:53:07 +00:00
gregfromstl ec3405b307 feat(react-native): add discord login (#3716)
<!-- start pr-codex -->

## PR-Codex overview
This PR adds Discord login functionality to the React Native SDK, including new paths, UI changes, and authentication methods.

### Detailed summary
- Added Discord login feature to React Native SDK
- Updated UI components for Discord login
- Implemented Discord authentication methods
- Created new paths for Discord login
- Updated authentication middleware for Discord integration

> The following files were skipped due to too many changes: `packages/thirdweb/src/wallets/in-app/native/helpers/wallet/recoveryCode.ts`

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

<!-- end pr-codex -->
2024-07-19 21:19:31 +00:00
ElasticBottle 31ee4e53e2 feat(thirdweb): Add support for discord auth in in app wallet (#3678)
## Problem solved

Short description of the bug fixed or feature added

## Changes made

- [ ] Public API changes: list the public API changes made if any
- [ ] Internal API changes: explain the internal logic changes

## How to test

- [ ] Automated tests: link to unit test file
- [ ] Manual tests: step by step instructions on how to test

## Contributor NFT

Paste in your wallet address below and we will airdrop you a special NFT when your pull request is merged.

```Address: ```

<!-- start pr-codex -->

---

## PR-Codex overview
This PR adds Discord login option to thirdweb in-app and ecosystem wallets.

### Detailed summary
- Added Discord login option to in-app and ecosystem wallets
- Updated authentication constants and locales
- Implemented Discord login functionality
- Updated wallet images and social login components

> The following files were skipped due to too many changes: `packages/thirdweb/src/react/web/wallets/shared/ConnectWalletSocialOptions.tsx`, `packages/thirdweb/src/react/native/ui/icons/svgs.ts`, `packages/thirdweb/src/wallets/in-app/web/lib/auth/discord.ts`

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

<!-- end pr-codex -->
2024-07-19 21:19:27 +00:00
gregfromstl ec5ef50085 fix: correct typo in addSessionKey.ts file and update jsdocs with contract parameter (#3758) 2024-07-19 21:03:37 +00:00
gregfromstl 83cd9e5a8f fix(transaction): handle undefined predefinedGas value in estimate-gas and add test for 0 gas value (#3761)
### TL;DR

This pull request addresses a bug in the `estimateGas` function where a gas value of `0` is now respected instead of being overridden.

### What changed?

- Updated `estimateGas` function to properly handle and respect a gas value of `0`.
- Added a test case to ensure that a gas value of `0` does not throw an error and is correctly serialized.

### How to test?

- Run unit tests to ensure the new test case passes.

### Why make this change?

This change ensures that transactions explicitly set with a gas value of `0` are respected and not overridden, providing more accurate and expected behavior.

---
2024-07-19 20:41:08 +00:00
gregfromstl d8ea41dd4e fix(dashboard): replace Wrench icon with Pencil icon in partners table (#3760)
## Problem solved

Short description of the bug fixed or feature added

## Changes made

- [ ] Public API changes: list the public API changes made if any
- [ ] Internal API changes: explain the internal logic changes

## How to test

- [ ] Automated tests: link to unit test file
- [ ] Manual tests: step by step instructions on how to test

## Contributor NFT

Paste in your wallet address below and we will airdrop you a special NFT when your pull request is merged.

```Address: ```

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to update the icon used for editing partners in the partners table component.

### Detailed summary
- Updated icon for editing partners from `Wrench` to `Pencil` in `partners-table.tsx`

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

<!-- end pr-codex -->
2024-07-19 19:29:03 +00:00
870be083f7 fix(connect-ui): update Connect UI tabs styling with new design enhancements (#3746)
Co-authored-by: gregfromstl <[email protected]>
Co-authored-by: Manan Tank <[email protected]>
2024-07-19 19:18:28 +00:00
kien-ngo 56b34ce197 Allow to add extra call data to prepareContractCall (#3676)
<!-- start pr-codex -->

## PR-Codex overview
This PR enhances the `prepareContractCall` function in the `thirdweb` package to allow adding extra call data to transactions.

### Detailed summary
- Added support for extra call data in `prepareContractCall`
- Introduced internal functions to handle extra call data in transactions
- Updated tests to cover extra call data scenarios

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

<!-- end pr-codex -->
2024-07-19 17:38:36 +00:00
iuwqyir b7295f93c5 use workspace version for service-utils (#3756)
## Problem solved

Reverts back to workspace version for `service-utils` package

## Changes made

- [ ] Public API changes: list the public API changes made if any
- [ ] Internal API changes: explain the internal logic changes

## How to test

- [ ] Automated tests: link to unit test file
- [ ] Manual tests: step by step instructions on how to test

## Contributor NFT

Paste in your wallet address below and we will airdrop you a special NFT when your pull request is merged.

```Address: ```

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to update the dependency resolution for `@thirdweb-dev/service-utils` and `@thirdweb-dev/dynamic-contracts`.

### Detailed summary
- Updated `@thirdweb-dev/service-utils` dependency resolution to `workspace:*`
- Removed specific dependencies for `@thirdweb-dev/[email protected]`
- Updated snapshot for `@thirdweb-dev/[email protected]`

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

<!-- end pr-codex -->
2024-07-19 17:25:24 +00:00
jnsdls 38ce393078 [Feature] Add Rootstock banner and CTA images and update chain metadata (#3755) 2024-07-19 17:09:30 +00:00
gregfromstl fde7ad5e93 fix(dashboard): add update partner form and refactor domain validation (#3747)
### TL;DR

This PR introduces new functionalities and updates aimed at improving partner management within the ecosystem section of the dashboard.

### What changed?

1. **Partner Update Feature**: Added a new form and modal to enable the updating of partner details, including name, domains, bundle IDs, and permissions.
2. **Refactored Domain Validation**: Moved domain validation regex to a constants file for improved code maintainability.
3. **UI Enhancements**: Updated UI components to include an edit button for partner details in the partners' table.
4. **Code Cleanup**: Removed redundant code and improved component structure for better readability.

### How to test?

1. Navigate to the ecosystem section in the dashboard.
2. Select a partner and click the edit button to open the update modal.
3. Update the partner details and save changes. Ensure that the details are updated correctly in the database and UI.

### Why make this change?

This change aims to enhance the user experience by allowing easier management of ecosystem partners directly from the dashboard. It also improves code maintainability and readability by refactoring existing components and validation logic.

---

<!-- start pr-codex -->

---

## PR-Codex overview
This PR updates partner permission handling and refactors form validation in the ecosystem dashboard.

### Detailed summary
- Added `PartnerPermission` type and `isValidPermission` function
- Updated partner object permissions to use `PartnerPermission`
- Refactored form validation using `partnerFormSchema`
- Added `useUpdatePartner` hook for updating partners
- Updated UI components and modals for partner management

> The following files were skipped due to too many changes: `apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/components/server/partners-table.tsx`, `apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/components/client/update-partner-form.client.tsx`

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

<!-- end pr-codex -->
2024-07-19 16:38:07 +00:00
gregfromstl 713ff296fd fix(tests): update wait function test precision (#3754)
### TL;DR
Improve the precision of the wait function tests by changing the expectation from a simple greater-than-or-equal check to an absolute difference check within a margin of error of 10 milliseconds.

### What changed?
In `wait.test.ts` files located in the `thirdweb/src/react/core/utils/` and `thirdweb/src/utils/promise/` paths, the expectation `expect(elapsedTime).toBeGreaterThanOrEqual(waitTime)` was updated to `expect(Math.abs(elapsedTime - waitTime)).toBeLessThan(10)` to improve test accuracy by accounting for slight timing variations.

### How to test?
Run the test suites located in `thirdweb/src/react/core/utils/wait.test.ts` and `thirdweb/src/utils/promise/wait.test.ts` to ensure that they pass successfully with the updated precision checks.

### Why make this change?
The motivation behind this change is to enhance the reliability and precision of the wait function tests by accommodating minor variations in elapsed time, which can occur due to factors like system load and execution context.

---
2024-07-19 16:23:58 +00:00
iuwqyir af4acc4319 add chainsaw service description (#3745)
## Problem solved

Added chainsaw service description so it can be used for auth

## Contributor NFT

Paste in your wallet address below and we will airdrop you a special NFT when your pull request is merged.

```Address: ```

<!-- start pr-codex -->

---

## PR-Codex overview
This PR adds a new service called `chainsaw` to the service-utils package and updates dependencies and configurations related to it.

### Detailed summary
- Added `chainsaw` service definition in `service-utils`
- Updated dependencies and configurations for the `chainsaw` service
- Updated `service-utils` version to `0.4.36` in various files and lock files

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

<!-- end pr-codex -->
2024-07-19 15:56:20 +00:00
kien-ngo 091b6099e7 Update ancient8 banner (#3753)
## Problem solved

Short description of the bug fixed or feature added

## Changes made

- [ ] Public API changes: list the public API changes made if any
- [ ] Internal API changes: explain the internal logic changes

## How to test

- [ ] Automated tests: link to unit test file
- [ ] Manual tests: step by step instructions on how to test

## Contributor NFT

Paste in your wallet address below and we will airdrop you a special NFT when your pull request is merged.

```Address: ```

<!-- start pr-codex -->

---

## PR-Codex overview
This PR updates banner images and gradient styling in the dashboard for a better visual experience.

### Detailed summary
- Deleted `ancient8-banner.jpg` and updated to `ancient8-banner.png` for better quality.
- Changed gradient styling in the header for improved visual appeal.
- Updated imports of banner images in `utils.ts` to match file extensions.

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

<!-- end pr-codex -->
2024-07-19 15:04:09 +00:00
joaquim-verges aba1266431 fix(thirdweb): Handle minimum purchase amount errors in buy with crypto flow (#3751)
<!-- start pr-codex -->

## PR-Codex overview
This PR focuses on handling the minimum amount in the buy-to-crypto flow.

### Detailed summary
- Updated error handling messages for buy with fiat and crypto flows
- Added functions to set token amount and track editing status
- Improved error messages display for minimum purchase amount
- Implemented functionality to set the minimum amount in the UI

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

<!-- end pr-codex -->
2024-07-19 05:23:39 +00:00
Joaquim VergesandGitHub 24bcee24ea fix(RN): correct disconnect button color in light mode and other minor UI adjustments (#3748) 2024-07-19 14:52:02 +12:00
joaquim-verges c6741b42cd feat(pay): add async ERC20 value property to transaction options (#3661)
### TL;DR

This PR introduces support for ERC20 tokens in the transaction flow, allowing users to seamlessly interact with contracts that require ERC20 token payments.

### What changed?

1. Added ERC20 token handling in the `useSendTransaction` hook to check balance and prompt users to buy ERC20 if needed.
2. Integrated ERC20 token fields, such as `erc20Value`, into the transaction preparation and cost estimation processes.
3. Updated various contract-writing scripts to include `erc20Value` overrides where necessary.
4. Enhanced the UI in `TxModal` and `BuyScreen` to display and process ERC20 token transactions.
5. Added tests for ERC20 token transactions in the `drop721.test.ts` file.
6. Extended documentation and examples to include ERC20 token use cases in transaction flows.

### How to test?

1. Run the unit tests in the `drop721.test.ts` file to ensure ERC20 transactions are correctly processed.
2. Use the `useSendTransaction` hook in a sample component and attempt transactions with both native and ERC20 tokens.
3. Verify that the ERC20 token purchase prompt appears when balance is insufficient.

### Why make this change?

Adding ERC20 support enhances the flexibility and functionality of the transaction flow, making it easier for users to interact with a wider range of smart contracts that require different types of token payments.

---

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on handling ERC20 transaction values in Pay components.

### Detailed summary
- Added `tokenDecimals` in `types.ts`
- Modified `title` in `PayEmbed.tsx` and `transferBatch.ts`
- Added `overrides` in `transfer.ts`, `transferFrom.ts`, `approve.ts`
- Added `erc20Value` in various transaction files
- Updated `prepare-transaction.ts` with `erc20Value`
- Added `erc20Value` in generated files for different ERC20 transactions

> The following files were skipped due to too many changes: `packages/thirdweb/src/extensions/common/__generated__/IMulticall/write/multicall.ts`, `packages/thirdweb/src/extensions/erc20/__generated__/IMintableERC20/write/mintTo.ts`, `packages/thirdweb/src/extensions/erc721/__generated__/IBurnableERC721/write/burn.ts`, `packages/thirdweb/src/extensions/erc721/__generated__/IStaking721/write/withdraw.ts`, `packages/thirdweb/src/extensions/farcaster/__generated__/IBundler/write/register.ts`, `packages/thirdweb/src/extensions/airdrop/__generated__/Airdrop/write/airdropERC20.ts`, `packages/thirdweb/src/extensions/airdrop/__generated__/Airdrop/write/claimERC1155.ts`, `packages/thirdweb/src/extensions/erc4337/__generated__/IEntryPoint/write/addStake.ts`, `packages/thirdweb/src/extensions/erc721/__generated__/IDelayedReveal/write/reveal.ts`, `packages/thirdweb/src/extensions/erc721/__generated__/IERC721A/write/transferFrom.ts`, `packages/thirdweb/src/extensions/farcaster/__generated__/IKeyGateway/write/addFor.ts`, `packages/thirdweb/src/extensions/marketplace/__generated__/IMarketplace/write/buy.ts`, `packages/thirdweb/src/extensions/airdrop/__generated__/Airdrop/write/airdropERC721.ts`, `packages/thirdweb/src/extensions/airdrop/__generated__/Airdrop/write/setMerkleRoot.ts`, `packages/thirdweb/src/extensions/erc1155/__generated__/IBurnableERC1155/write/burn.ts`, `packages/thirdweb/src/extensions/erc1155/__generated__/IStaking1155/write/withdraw.ts`, `packages/thirdweb/src/extensions/erc20/__generated__/IBurnableERC20/write/burnFrom.ts`, `packages/thirdweb/src/extensions/erc4337/__generated__/IEntryPoint/write/depositTo.ts`, `packages/thirdweb/src/extensions/erc4337/__generated__/IEntryPoint/write/handleOps.ts`, `packages/thirdweb/src/extensions/erc721/__generated__/IClaimableERC721/write/claim.ts`, `packages/thirdweb/src/extensions/erc721/__generated__/IMintableERC721/write/mintTo.ts`, `packages/thirdweb/src/extensions/farcaster/__generated__/IIdGateway/write/register.ts`, `packages/thirdweb/src/extensions/farcaster/__generated__/IIdRegistry/write/recover.ts`, `packages/thirdweb/src/extensions/farcaster/__generated__/IKeyRegistry/write/remove.ts`, `packages/thirdweb/src/extensions/marketplace/__generated__/IOffers/write/makeOffer.ts`, `packages/thirdweb/src/extensions/airdrop/__generated__/Airdrop/write/airdropERC1155.ts`, `packages/thirdweb/src/extensions/erc4337/__generated__/IEntryPoint/write/withdrawTo.ts`, `packages/thirdweb/src/extensions/farcaster/__generated__/IIdRegistry/write/transfer.ts`, `packages/thirdweb/src/extensions/marketplace/__generated__/IMarketplace/write/offer.ts`, `packages/thirdweb/src/extensions/modular/__generated__/ModularCore/write/grantRoles.ts`, `packages/thirdweb/src/extensions/prebuilts/__generated__/DropERC20/write/initialize.ts`, `packages/thirdweb/src/extensions/uniswap/__generated__/ISwapRouter/write/exactInput.ts`, `packages/thirdweb/src/extensions/erc1155/__generated__/IClaimableERC1155/write/claim.ts`, `packages/thirdweb/src/extensions/erc1155/__generated__/IMintableERC1155/write/mintTo.ts`, `packages/thirdweb/src/extensions/erc4337/__generated__/IAccount/write/validateUserOp.ts`, `packages/thirdweb/src/extensions/erc721/__generated__/IDrop/write/setClaimConditions.ts`, `packages/thirdweb/src/extensions/erc721/__generated__/INFTMetadata/write/setTokenURI.ts`, `packages/thirdweb/src/extensions/farcaster/__generated__/IStorageRegistry/write/rent.ts`, `packages/thirdweb/src/extensions/marketplace/__generated__/IOffers/write/acceptOffer.ts`, `packages/thirdweb/src/extensions/marketplace/__generated__/IOffers/write/cancelOffer.ts`, `packages/thirdweb/src/extensions/modular/__generated__/ModularCore/write/revokeRoles.ts`, `packages/thirdweb/src/extensions/prebuilts/__generated__/DropERC721/write/initialize.ts`, `packages/thirdweb/src/extensions/prebuilts/__generated__/TokenERC20/write/initialize.ts`, `packages/thirdweb/src/extensions/uniswap/__generated__/IQuoter/write/quoteExactInput.ts`, `packages/thirdweb/src/extensions/uniswap/__generated__/ISwapRouter/write/exactOutput.ts`, `packages/thirdweb/src/extensions/erc1155/__generated__/INFTMetadata/write/setTokenURI.ts`, `packages/thirdweb/src/extensions/erc20/__generated__/IAirdropERC20/write/airdropERC20.ts`, `packages/thirdweb/src/extensions/erc721/__generated__/IERC721A/write/safeTransferFrom.ts`, `packages/thirdweb/src/extensions/farcaster/__generated__/IIdGateway/write/registerFor.ts`, `packages/thirdweb/src/extensions/farcaster/__generated__/IIdRegistry/write/recoverFor.ts`, `packages/thirdweb/src/extensions/farcaster/__generated__/IKeyRegistry/write/removeFor.ts`, `packages/thirdweb/src/extensions/multicall3/__generated__/IMulticall3/write/aggregate.ts`, `packages/thirdweb/src/extensions/prebuilts/__generated__/DropERC1155/write/initialize.ts`, `packages/thirdweb/src/extensions/prebuilts/__generated__/Marketplace/write/initialize.ts`, `packages/thirdweb/src/extensions/prebuilts/__generated__/TokenERC721/write/initialize.ts`, `packages/thirdweb/src/extensions/thirdweb/__generated__/IRulesEngine/write/deleteRule.ts`, `packages/thirdweb/src/extensions/uniswap/__generated__/IQuoter/write/quoteExactOutput.ts`, `packages/thirdweb/src/extensions/erc1155/__generated__/IERC1155/write/safeTransferFrom.ts`, `packages/thirdweb/src/extensions/erc1155/__generated__/IStaking1155/write/claimRewards.ts`, `packages/thirdweb/src/extensions/erc4337/__generated__/IEntryPoint/write/withdrawStake.ts`, `packages/thirdweb/src/extensions/erc721/__generated__/IERC721A/write/setApprovalForAll.ts`, `packages/thirdweb/src/extensions/farcaster/__generated__/IIdRegistry/write/transferFor.ts`, `packages/thirdweb/src/extensions/modular/__generated__/ModularCore/write/renounceRoles.ts`, `packages/thirdweb/src/extensions/multicall3/__generated__/IMulticall3/write/aggregate3.ts`, `packages/thirdweb/src/extensions/prebuilts/__generated__/TokenERC1155/write/initialize.ts`, `packages/thirdweb/src/extensions/airdrop/__generated__/Airdrop/write/airdropNativeToken.ts`, `packages/thirdweb/src/extensions/common/__generated__/IRoyaltyPayments/write/getRoyalty.ts`, `packages/thirdweb/src/extensions/erc1155/__generated__/IBurnableERC1155/write/burnBatch.ts`, `packages/thirdweb/src/extensions/erc1155/__generated__/IERC1155/write/setApprovalForAll.ts`, `packages/thirdweb/src/extensions/erc20/__generated__/IAirdropERC20Claimable/write/claim.ts`, `packages/thirdweb/src/extensions/erc4337/__generated__/IEntryPoint/write/incrementNonce.ts`, `packages/thirdweb/src/extensions/permissions/__generated__/IPermissions/write/grantRole.ts`, `packages/thirdweb/src/extensions/thirdweb/__generated__/ITWMultichainRegistry/write/add.ts`, `packages/thirdweb/src/extensions/uniswap/__generated__/IUniswapV3Factory/write/setOwner.ts`, `packages/thirdweb/src/extensions/erc20/__generated__/IDropERC20/write/setClaimConditions.ts`, `packages/thirdweb/src/extensions/erc721/__generated__/DropERC721/write/setMaxTotalSupply.ts`, `packages/thirdweb/src/extensions/erc721/__generated__/IAirdropERC721/write/airdropERC721.ts`, `packages/thirdweb/src/extensions/multicall3/__generated__/IMulticall3/write/tryAggregate.ts`, `packages/thirdweb/src/extensions/permissions/__generated__/IPermissions/write/revokeRole.ts`, `packages/thirdweb/src/extensions/erc1155/__generated__/IDrop1155/write/setClaimConditions.ts`, `packages/thirdweb/src/extensions/erc4337/__generated__/IEntryPoint/write/getSenderAddress.ts`, `packages/thirdweb/src/extensions/erc4337/__generated__/IEntryPoint/write/simulateHandleOp.ts`, `packages/thirdweb/src/extensions/erc721/__generated__/DropERC721/write/freezeBatchBaseURI.ts`, `packages/thirdweb/src/extensions/erc721/__generated__/DropERC721/write/updateBatchBaseURI.ts`, `packages/thirdweb/src/extensions/erc721/__generated__/IAirdropERC721Claimable/write/claim.ts`, `packages/thirdweb/src/extensions/erc721/__generated__/INFTStake/write/depositRewardTokens.ts`, `packages/thirdweb/src/extensions/farcaster/__generated__/IStorageRegistry/write/batchRent.ts`, `packages/thirdweb/src/extensions/marketplace/__generated__/IMarketplace/write/acceptOffer.ts`, `packages/thirdweb/src/extensions/modular/__generated__/ModularCore/write/installExtension.ts`, `packages/thirdweb/src/extensions/uniswap/__generated__/ISwapRouter/write/exactInputSingle.ts`, `packages/thirdweb/src/extensions/uniswap/__generated__/IUniswapV3Factory/write/createPool.ts`, `packages/thirdweb/src/extensions/common/__generated__/IRoyalty/write/setDefaultRoyaltyInfo.ts`, `packages/thirdweb/src/extensions/erc1155/__generated__/DropERC1155/write/setMaxTotalSupply.ts`, `packages/thirdweb/src/extensions/erc20/__generated__/ITokenStake/write/depositRewardTokens.ts`, `packages/thirdweb/src/extensions/erc4337/__generated__/IAccountFactory/write/createAccount.ts`, `packages/thirdweb/src/extensions/erc4337/__generated__/IAccountFactory/write/onSignerAdded.ts`, `packages/thirdweb/src/extensions/erc721/__generated__/INFTStake/write/withdrawRewardTokens.ts`, `packages/thirdweb/src/extensions/marketplace/__generated__/IMarketplace/write/closeAuction.ts`, `packages/thirdweb/src/extensions/modular/__generated__/IModularCore/write/installExtension.ts`, `packages/thirdweb/src/extensions/modular/__generated__/ModularCore/write/transferOwnership.ts`, `packages/thirdweb/src/extensions/permissions/__generated__/IPermissions/write/renounceRole.ts`, `packages/thirdweb/src/extensions/thirdweb/__generated__/ITWMultichainRegistry/write/remove.ts`, `packages/thirdweb/src/extensions/uniswap/__generated__/IQuoter/write/quoteExactInputSingle.ts`, `packages/thirdweb/src/extensions/uniswap/__generated__/ISwapRouter/write/exactOutputSingle.ts`, `packages/thirdweb/src/extensions/common/__generated__/IPlatformFee/write/setPlatformFeeInfo.ts`, `packages/thirdweb/src/extensions/common/__generated__/IRoyalty/write/setRoyaltyInfoForToken.ts`, `packages/thirdweb/src/extensions/erc1155/__generated__/DropERC1155/write/freezeBatchBaseURI.ts`, `packages/thirdweb/src/extensions/erc1155/__generated__/DropERC1155/write/updateBatchBaseURI.ts`, `packages/thirdweb/src/extensions/erc1155/__generated__/IAirdropERC1155/write/airdropERC1155.ts`, `packages/thirdweb/src/extensions/erc1155/__generated__/IAirdropERC1155Claimable/write/claim.ts`, `packages/thirdweb/src/extensions/erc1155/__generated__/IERC1155/write/safeBatchTransferFrom.ts`, `packages/thirdweb/src/extensions/erc20/__generated__/ITokenStake/write/withdrawRewardTokens.ts`, `packages/thirdweb/src/extensions/erc4337/__generated__/IEntryPoint/write/simulateValidation.ts`, `packages/thirdweb/src/extensions/marketplace/__generated__/IMarketplace/write/createListing.ts`, `packages/thirdweb/src/extensions/marketplace/__generated__/IMarketplace/write/updateListing.ts`, `packages/thirdweb/src/extensions/modular/__generated__/ModularCore/write/uninstallExtension.ts`, `packages/thirdweb/src/extensions/multicall3/__generated__/IMulticall3/write/aggregate3Value.ts`, `packages/thirdweb/src/extensions/prebuilts/__generated__/OpenEditionERC721/write/initialize.ts`, `packages/thirdweb/src/extensions/uniswap/__generated__/IQuoter/write/quoteExactOutputSingle.ts`, `packages/thirdweb/src/extensions/common/__generated__/IContractMetadata/write/setContractURI.ts`, `packages/thirdweb/src/extensions/erc4337/__generated__/IAccountFactory/write/onSignerRemoved.ts`, `packages/thirdweb/src/extensions/erc4337/__generated__/IEntryPoint/write/handleAggregatedOps.ts`, `packages/thirdweb/src/extensions/erc721/__generated__/IERC721Receiver/write/onERC721Received.ts`, `packages/thirdweb/src/extensions/marketplace/__generated__/IMarketplace/write/setContractURI.ts`, `packages/thirdweb/src/extensions/modular/__generated__/IModularCore/write/uninstallExtension.ts`, `packages/thirdweb/src/extensions/common/__generated__/IRoyaltyPayments/write/setRoyaltyEngine.ts`, `packages/thirdweb/src/extensions/erc721/__generated__/ISharedMetadata/write/setSharedMetadata.ts`, `packages/thirdweb/src/extensions/multicall3/__generated__/IMulticall3/write/blockAndAggregate.ts`, `packages/thirdweb/src/extensions/airdrop/__generated__/Airdrop/write/airdropERC20WithSignature.ts`, `packages/thirdweb/src/extensions/erc1155/__generated__/IEditionStake/write/depositRewardTokens.ts`, `packages/thirdweb/src/extensions/marketplace/__generated__/IDirectListings/write/cancelListing.ts`, `packages/thirdweb/src/extensions/marketplace/__generated__/IDirectListings/write/createListing.ts`, `packages/thirdweb/src/extensions/marketplace/__generated__/IDirectListings/write/updateListing.ts`, `packages/thirdweb/src/extensions/marketplace/__generated__/IEnglishAuctions/write/bidInAuction.ts`, `packages/thirdweb/src/extensions/thirdweb/__generated__/IRulesEngine/write/createRuleThreshold.ts`, `packages/thirdweb/src/extensions/thirdweb/__generated__/IThirdwebContract/write/setContractURI.ts`, `packages/thirdweb/src/extensions/uniswap/__generated__/IUniswapV3Factory/write/enableFeeAmount.ts`, `packages/thirdweb/src/extensions/airdrop/__generated__/Airdrop/write/airdropERC721WithSignature.ts`, `packages/thirdweb/src/extensions/erc1155/__generated__/IERC1155Receiver/write/onERC1155Received.ts`, `packages/thirdweb/src/extensions/erc1155/__generated__/IEditionStake/write/withdrawRewardTokens.ts`, `packages/thirdweb/src/extensions/erc4337/__generated__/IPaymaster/write/validatePaymasterUserOp.ts`, `packages/thirdweb/src/extensions/marketplace/__generated__/IDirectListings/write/buyFromListing.ts`, `packages/thirdweb/src/extensions/marketplace/__generated__/IEnglishAuctions/write/cancelAuction.ts`, `packages/thirdweb/src/extensions/marketplace/__generated__/IEnglishAuctions/write/createAuction.ts`, `packages/thirdweb/src/extensions/airdrop/__generated__/Airdrop/write/airdropERC1155WithSignature.ts`, `packages/thirdweb/src/extensions/common/__generated__/IPrimarySale/write/setPrimarySaleRecipient.ts`, `packages/thirdweb/src/extensions/erc20/__generated__/ISignatureMintERC20/write/mintWithSignature.ts`, `packages/thirdweb/src/extensions/farcaster/__generated__/IIdRegistry/write/changeRecoveryAddress.ts`, `packages/thirdweb/src/extensions/marketplace/__generated__/IMarketplace/write/setPlatformFeeInfo.ts`, `packages/thirdweb/src/extensions/multicall3/__generated__/IMulticall3/write/tryBlockAndAggregate.ts`, `packages/thirdweb/src/extensions/thirdweb/__generated__/IContractPublisher/write/publishContract.ts`, `packages/thirdweb/src/extensions/erc1155/__generated__/DropERC1155/write/setSaleRecipientForToken.ts`, `packages/thirdweb/src/extensions/marketplace/__generated__/IMarketplace/write/cancelDirectListing.ts`, `packages/thirdweb/src/extensions/permissions/__generated__/IPermissionsEnumerable/write/grantRole.ts`, `packages/thirdweb/src/extensions/thirdweb/__generated__/IRulesEngine/write/setRulesEngineOverride.ts`, `packages/thirdweb/src/extensions/erc721/__generated__/ISharedMetadataBatch/write/setSharedMetadata.ts`, `packages/thirdweb/src/extensions/erc721/__generated__/ISignatureMintERC721/write/mintWithSignature.ts`, `packages/thirdweb/src/extensions/modular/__generated__/ModularCore/write/completeOwnershipHandover.ts`, `packages/thirdweb/src/extensions/permissions/__generated__/IPermissionsEnumerable/write/revokeRole.ts`, `packages/thirdweb/src/extensions/thirdweb/__generated__/IContractPublisher/write/unpublishContract.ts`, `packages/thirdweb/src/extensions/erc1155/__generated__/IPackVRFDirect/write/openPackAndClaimRewards.ts`, `packages/thirdweb/src/extensions/farcaster/__generated__/IIdRegistry/write/changeRecoveryAddressFor.ts`, `packages/thirdweb/src/extensions/thirdweb/__generated__/IRulesEngine/write/createRuleMultiplicative.ts`, `packages/thirdweb/src/extensions/erc1155/__generated__/IERC1155Receiver/write/onERC1155BatchReceived.ts`, `packages/thirdweb/src/extensions/erc1155/__generated__/ISignatureMintERC1155/write/mintWithSignature.ts`, `packages/thirdweb/src/extensions/farcaster/__generated__/IIdRegistry/write/transferAndChangeRecovery.ts`, `packages/thirdweb/src/extensions/permissions/__generated__/IPermissionsEnumerable/write/renounceRole.ts`, `packages/thirdweb/src/extensions/erc721/__generated__/ISharedMetadataBatch/write/deleteSharedMetadata.ts`, `packages/thirdweb/src/extensions/marketplace/__generated__/IEnglishAuctions/write/collectAuctionPayout.ts`, `packages/thirdweb/src/extensions/marketplace/__generated__/IEnglishAuctions/write/collectAuctionTokens.ts`, `packages/thirdweb/src/extensions/farcaster/__generated__/IIdRegistry/write/transferAndChangeRecoveryFor.ts`, `packages/thirdweb/src/extensions/marketplace/__generated__/IDirectListings/write/approveBuyerForListing.ts`, `packages/thirdweb/src/extensions/thirdweb/__generated__/IContractPublisher/write/setPublisherProfileUri.ts`, `packages/thirdweb/src/extensions/erc4337/__generated__/IAccountPermissions/write/setPermissionsForSigner.ts`, `packages/thirdweb/src/extensions/common/__generated__/IClaimConditionsSinglePhase/write/setClaimConditions.ts`, `packages/thirdweb/src/extensions/marketplace/__generated__/IDirectListings/write/approveCurrencyForListing.ts`, `packages/thirdweb/src/extensions/thirdweb/__generated__/IContractFactory/write/deployProxyByImplementation.ts`, `packages/thirdweb/src/extensions/erc20/write/sigMint.ts`, `packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/main/useBuyTxStates.ts`, `packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/pay-transactions/BuyTxHistory.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/pay-transactions/TxDetailsScreen.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/TransactionsScreen.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/pay-transactions/FiatDetailsScreen.tsx`, `packages/thirdweb/src/extensions/erc20/write/deposit.ts`, `packages/thirdweb/src/utils/extensions/drops/get-claim-params.ts`, `packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/PayTokenIcon.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.tsx`, `packages/thirdweb/src/extensions/erc20/write/getApprovalForTransaction.ts`, `apps/playground-web/src/components/pay/transaction-button.tsx`, `packages/thirdweb/src/extensions/erc721/drop721.test.ts`, `packages/thirdweb/src/react/core/hooks/transaction/useSendTransaction.ts`, `packages/thirdweb/src/react/web/hooks/transaction/useSendTransaction.tsx`

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

<!-- end pr-codex -->
2024-07-19 01:57:06 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>GitHub Action
26ca958b55 Version Packages (#3722)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub Action <[email protected]>
2024-07-19 07:16:46 +12:00
AmineAfia 7098c8435b changed comeback tomorrow to give funds (#3744)
## Problem solved

Short description of the bug fixed or feature added

## Changes made

- [ ] come back tomorrow gives funds now

## How to test

- [ ] Automated tests: link to unit test file
- [ ] Manual tests: step by step instructions on how to test

## Contributor NFT

Paste in your wallet address below and we will airdrop you a special NFT when your pull request is merged.

```Address: ```

<!-- start pr-codex -->

---

## PR-Codex overview
This PR updates the SpinWheel component in the dashboard app to adjust the amount displayed based on the result and improve the success message.

### Detailed summary
- Updated the amount displayed based on the result in `SpinWheel.tsx`
- Improved success message with a more informative and positive message

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

<!-- end pr-codex -->
2024-07-18 18:29:44 +00:00
YashandGitHub c073ce59d1 Update XAI logo on homepage (#3743) 2024-07-18 20:28:46 +02:00
gregfromstl 4ae0bf72f5 chore: remove random logs (#3742) 2024-07-18 16:34:46 +00:00
AmineAfia 9b7f7938f2 added cache removal when faucet transfer fails (#3726)
## Problem solved

Users rate limited when faucet fails to transfer funds e.g. faucet empty

## Changes made

- [ ] Added the mechanism to remove users from the cache when the funding transfer fails (e.g. when the faucet is empty)

## How to test

- [ ] empty the faucet or make the transfer request fail

## Contributor NFT

Paste in your wallet address below and we will airdrop you a special NFT when your pull request is merged.

```Address: ```

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to add a new function `cacheDeleteKey` to delete a cache key and update its usage in the testnet faucet route.

### Detailed summary
- Added `cacheDeleteKey` function to delete a cache key in `lib/redis`
- Updated the testnet faucet route to use `cacheDeleteKey` for cache management

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

<!-- end pr-codex -->
2024-07-18 11:57:56 +00:00
Joaquim VergesandGitHub 8aa69f4129 fix(docs): tsdoc linting (#3739) 2024-07-18 20:29:17 +12:00
joaquim-verges 6cc3038298 fix(thirdweb): add optional 'from' in readContract method (#3735)
Fixes #3683

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to add an optional 'from' parameter in the `readContract()` function and update default max block wait times to 100 in various files.

### Detailed summary
- Added optional 'from' parameter in `readContract()`
- Updated default max block wait times to 10 in specific files
- Increased default max block wait times to 100 in other files

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

<!-- end pr-codex -->
2024-07-18 07:55:17 +00:00
Manan TankandGitHub db2cadfc4b Increased Transaction cost buffer for Pay Modal (#3730) 2024-07-18 07:54:10 +00:00
Joaquim VergesandGitHub 85f6cca8fc docs(thirdweb): Add examples and documentation tags for modular and utility functions (#3738) 2024-07-18 15:42:10 +12:00
80e6855a19 docs: fix fetchProofs jsdocs (#3736)
Co-authored-by: gregfromstl <[email protected]>
2024-07-18 14:54:00 +12:00
Farhan KhwajaandGitHub e02a18a4d8 Updates: Engine (#3737) 2024-07-18 07:15:46 +05:30
farhanW3 029a0ad9e8 Update: Engine Deletion Logic (#3734)
<!-- start pr-codex -->

## PR-Codex overview
This PR updates the condition for rendering a form in the `engine-instances-table.tsx` component based on the `instance` status.

### Detailed summary
- Changed the condition for rendering a form based on `instance.status`
- Form now appears for instances with status "paymentFailed" or "active" without `cloudDeployedAt`

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

<!-- end pr-codex -->
2024-07-18 01:09:18 +00:00
Joaquim VergesandGitHub f351054d34 fix(dashboard): Fix zksync deployments with inapp wallet (#3721) 2024-07-18 13:08:13 +12:00
gregfromstl 6bda057306 feat(connect-wallet): add transaction history page to connect modal UI (#3718)
This pull request introduces new features and modifications to the transaction history feature within the connect modal UI. Key changes include:

- Addition of a transaction history page accessible from the connect modal's main menu, allowing users to view and manage their transaction history more effectively.
- Refactoring of transaction-related components to enhance code maintainability and readability. Specifically, renaming components related to 'BuyTxHistory' to 'PayTxHistory' to better reflect their functionality.
- Updates to locale files to include new translations for added labels such as 'payTransactions' and 'walletTransactions'.
- Integration of new navigation options within the connect modal, enabling seamless switching between different transaction views, including 'Fiat Transactions' and 'Wallet Transactions'.
- Ensuring that the transaction history page supports multiple languages, with updated English, Spanish, Japanese, and Vietnamese locale files.
- Improvements to UI components to ensure consistent styling and user experience across the transaction history pages.

These enhancements aim to provide users with an improved interface for managing their transaction histories, thereby enhancing overall user experience.

---

<!-- start pr-codex -->

---

## PR-Codex overview
This PR adds a transaction history page to the connect modal UI.

### Detailed summary
- Added transaction history page to connect modal UI
- Renamed "pending-tx" to "transactions"
- Updated text and components related to transactions and fiat transactions
- Reorganized file structure for transaction-related screens and components

> The following files were skipped due to too many changes: `packages/thirdweb/src/react/web/ui/ConnectWallet/TransactionsScreen.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/screens/WalletTransactionHistory.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/tx-history/BuyTxHistory.tsx`

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

<!-- end pr-codex -->
2024-07-18 00:25:12 +00:00
MananTank faaa426bbb Fix chain page crash when adding ref query param on dashboard (#3732)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to refactor the handling of search parameters in the trending section of the dashboard.

### Detailed summary
- Updated the handling of search parameters in the trending section of the dashboard.
- Reorganized the code to use `searchParams` object for time range, page, and sort by.
- Refactored the `TrendingContractSection` and `TrendingTable` components to utilize `searchParams` object efficiently.

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

<!-- end pr-codex -->
2024-07-17 21:56:15 +00:00
0a5af48f70 Fix custom chain RPC not used if passed via chains prop (#3728)
Co-authored-by: MananTank <[email protected]>
2024-07-17 18:44:19 +00:00
joaquim-verges 0f9170caf1 feat(dashboard): add trending link in contracts section (#3720)
<!-- start pr-codex -->

## PR-Codex overview
This PR adds a new "Trending" section to the sidebar, updates the pagination component, and modifies search filters for gas usage. Additionally, it refactors the package.json file for thirdweb.

### Detailed summary
- Added "Trending" section to sidebar
- Updated pagination component
- Modified search filters for gas usage
- Refactored package.json for thirdweb

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

<!-- end pr-codex -->
2024-07-17 08:42:42 +00:00
joaquim-verges 05df89cb61 feat(smart): ERC20 paymaster support (#3719)
### TL;DR

Adds support for using an ERC20 paymaster in smart accounts. This includes functionality to check and approve ERC20 allowances as needed.

### What changed?

- Introduced support for ERC20 paymasters in smart accounts.
- Added logic to check and approve ERC20 allowances.
- Updated the `defaultTokens` list to include a new token for testing purposes.

### How to test?

1. Ensure that the smart account can interact with ERC20 paymasters.
2. Verify that the account approval for ERC20 paymasters works as expected.
3. Check that the default tokens list reflects the new token and can be utilized appropriately.

### Why make this change?

To enable smart accounts to use ERC20 tokens for paymaster functionalities, enhancing versatility and use-case scenarios for smart accounts.

---

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to add support for ERC20 paymaster for smart accounts.

### Detailed summary
- Added ERC20 paymaster support for smart accounts
- Implemented functions for approving ERC20 transactions
- Modified smart account creation to handle ERC20 paymasters

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

<!-- end pr-codex -->
2024-07-17 08:25:38 +00:00
joaquim-verges 8bc814aaf9 feat(pay): add metadata title support for pay screens (#3664)
<!-- start pr-codex -->

## PR-Codex overview
This PR updates various components across different files to allow for dynamic customization of titles in the UI screens.

### Detailed summary
- Added `title` prop to multiple components for dynamic title customization.
- Updated titles in UI screens to use the dynamic `title` prop.
- Enhanced flexibility for customizing display titles in the UI.

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

<!-- end pr-codex -->
2024-07-17 08:07:47 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>GitHub Action
080903e3a9 Version Packages (#3675)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub Action <[email protected]>
2024-07-17 19:23:27 +12:00
Farhan KhwajaandGitHub c5b97407b0 updates: UserOp example + receipt retrieval function (#3712) 2024-07-16 22:32:35 -07:00
AmineAfia 39b329a56e Add Faucet to every Testnet chain page (#3660)
## Problem solved

Faucet for EVM every chain. When the faucet is empty we crowdfund faucet sponsors

## Changes made

- [ ] Added faucet UI
- [ ] Added faucet endpoint
- [ ] Added faucet eligibility endpoint

## How to test

- [ ] See video

https://github.com/user-attachments/assets/b4414d63-c4cf-44f9-8824-c7307ad34013

## Contributor NFT

Paste in your wallet address below and we will airdrop you a special NFT when your pull request is merged.

```Address: ```

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to implement a faucet feature for testnet chains, allowing users to claim testnet funds.

### Detailed summary
- Added "faucet" service type and functionality.
- Implemented faucet-related components and pages.
- Utilized Redis for caching faucet requests.
- Added necessary dependencies for faucet functionality.
- Updated chain metadata generation for faucet feature.

> The following files were skipped due to too many changes: `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/faucet/components/SpinWheel.tsx`, `pnpm-lock.yaml`

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

<!-- end pr-codex -->
2024-07-16 22:29:18 +00:00
d4mr 910b115030 Engine Configuration: IP Allowlist (#3700)
Corresponding Engine PR: https://github.com/thirdweb-dev/engine/pull/564
<img width="773" alt="image" src="https://github.com/user-attachments/assets/a27098a6-4d6f-4cbb-a2aa-795f50d531ac">

<!-- start pr-codex -->

---

## PR-Codex overview
This PR introduces IP allowlisting feature to the engine configuration.

### Detailed summary
- Added `ipaddr.js` library for IP address validation
- Implemented IP allowlist configuration in the engine settings
- Created hooks for fetching and setting IP allowlist
- Added UI components for managing IP allowlist in the dashboard

> 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-07-16 20:00:30 +00:00
jnsdls b85eabd991 [Fix] Update AddYourChainButton URL in ChainList page to new support form link (#3714) 2024-07-16 18:01:31 +00:00
jnsdls 7b96f417a1 [Fix] Use encodeURIComponent for URL paths in redirect and Link components (#3713) 2024-07-16 17:47:51 +00:00
Manan TankandGitHub a5573046f1 Fix adding a chain as favorite not working in dashboard (#3711) 2024-07-16 17:33:18 +00:00
0xFirekeeper cae0e280fa Unity 4.16.7 (#3710)
Sync chains too

<!-- start pr-codex -->

---

## PR-Codex overview
This PR updates various chain configurations with corrected URLs, symbols, and RPC endpoints. It also adds icons and red flags for better identification.

### Detailed summary
- Corrected URLs, symbols, and RPC endpoints for multiple chains
- Added icons for chain identification
- Updated red flags for specific chains

> The following files were skipped due to too many changes: `legacy_packages/chains/chains/1116.ts`, `legacy_packages/chains/chains/48900.ts`, `legacy_packages/chains/chains/65536.ts`, `legacy_packages/chains/chains/28122024.ts`, `legacy_packages/chains/chains/1115.ts`, `legacy_packages/chains/chains/44787.ts`, `legacy_packages/chains/chains/31.ts`, `legacy_packages/chains/chains/16350.ts`, `legacy_packages/chains/chains/179.ts`, `legacy_packages/chains/chains/852.ts`, `legacy_packages/chains/chains/123321.ts`, `legacy_packages/chains/chains/2702128.ts`, `legacy_packages/chains/chains/46.ts`, `legacy_packages/chains/chains/1648.ts`, `legacy_packages/chains/chains/10096.ts`, `legacy_packages/chains/chains/190.ts`, `legacy_packages/chains/chains/16481.ts`, `legacy_packages/chains/chains/1578.ts`, `legacy_packages/chains/chains/178.ts`, `legacy_packages/chains/chains/77677.ts`, `legacy_packages/chains/chains/1223.ts`, `legacy_packages/chains/chains/245022929.ts`, `legacy_packages/chains/chains/1570.ts`, `legacy_packages/chains/chains/7774.ts`, `legacy_packages/chains/chains/1398243.ts`, `legacy_packages/chains/chains/187.ts`, `legacy_packages/chains/chains/1313.ts`, `legacy_packages/chains/chains/9496.ts`, `legacy_packages/chains/chains/328527.ts`, `legacy_packages/chains/chains/327126.ts`, `legacy_packages/chains/chains/8869.ts`, `legacy_packages/chains/chains/12227331.ts`, `legacy_packages/chains/chains/29732.ts`, `legacy_packages/chains/chains/184.ts`, `legacy_packages/chains/chains/19191.ts`, `legacy_packages/chains/chains/20240603.ts`, `legacy_packages/chains/chains/10241024.ts`, `legacy_packages/chains/chains/199991.ts`, `legacy_packages/chains/chains/1811.ts`, `legacy_packages/chains/chains/486487.ts`, `legacy_packages/chains/chains/59902.ts`, `legacy_packages/chains/chains/42026.ts`, `legacy_packages/chains/chains/55614.ts`, `legacy_packages/chains/chains/6550.ts`, `legacy_packages/chains/chains/261.ts`, `legacy_packages/chains/chains/15430.ts`, `legacy_packages/chains/chains/65100003.ts`, `legacy_packages/chains/chains/8022.ts`, `legacy_packages/chains/chains/55239.ts`, `legacy_packages/chains/chains/5566.ts`, `legacy_packages/chains/chains/292003.ts`, `legacy_packages/chains/chains/65357.ts`, `legacy_packages/chains/chains/56667.ts`, `legacy_packages/chains/chains/87566.ts`, `legacy_packages/chains/chains/65010003.ts`, `legacy_packages/chains/chains/16680.ts`, `legacy_packages/chains/chains/22562.ts`, `legacy_packages/chains/chains/57056.ts`, `legacy_packages/chains/chains/62454.ts`, `legacy_packages/chains/chains/62587.ts`, `legacy_packages/chains/chains/75991.ts`, `legacy_packages/chains/chains/22721.ts`, `legacy_packages/chains/chains/26945.ts`, `legacy_packages/chains/chains/85677.ts`, `legacy_packages/chains/chains/9302.ts`, `legacy_packages/chains/chains/40875.ts`, `legacy_packages/chains/chains/420000.ts`, `legacy_packages/chains/chains/19077.ts`, `legacy_packages/chains/chains/3338.ts`, `legacy_packages/chains/chains/86602.ts`, `legacy_packages/chains/chains/86225.ts`, `legacy_packages/chains/chains/99083.ts`, `legacy_packages/chains/chains/24076.ts`, `legacy_packages/chains/chains/17071.ts`, `legacy_packages/chains/chains/8886.ts`, `legacy_packages/chains/chains/16180.ts`, `legacy_packages/chains/chains/4444444.ts`, `legacy_packages/chains/chains/9372.ts`, `legacy_packages/chains/chains/2311.ts`, `legacy_packages/chains/chains/1456.ts`, `legacy_packages/chains/chains/6806.ts`, `legacy_packages/chains/chains/1903648807.ts`, `legacy_packages/chains/chains/646.ts`, `legacy_packages/chains/chains/4457845.ts`, `legacy_packages/chains/chains/325000.ts`, `legacy_packages/chains/chains/175177.ts`, `legacy_packages/chains/chains/7001.ts`, `legacy_packages/chains/src/index.ts`

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

<!-- end pr-codex -->
2024-07-16 17:00:19 +00:00
joaquim-verges 8e1a24a60e feat(pay): add recipient address support to PayEmbed (#3662)
<!-- start pr-codex -->

## PR-Codex overview
This PR adds the recipient address feature to PayEmbed and refactors recipient address handling in various components.

### Detailed summary
- Added recipient address to PayEmbed for sending purchased tokens
- Refactored handling of recipient address in different screens and hooks
- Updated logic for onramp and swap processes based on recipient address

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

<!-- end pr-codex -->
2024-07-16 15:24:08 +00:00
Joaquim VergesandGitHub aadbd33e9d fix(thirdweb): make client and chain mandatory in useWalletBalance (#3706) 2024-07-16 20:19:18 +12:00
joaquim-verges 1a09f46f24 feat(RN): support auth in React Native (#3708) 2024-07-16 05:55:45 +00:00
gregfromstl f8f6790da7 fix(auth): resolve typed data signatures issue in in-app wallet (#3707)
### TL;DR

- Added domain data for typed data signatures.
- Updated hooks and utilities to use `account` instead of `signer`.

### What changed?

- Modified `useRegistry.ts`, `hooks.ts`, and `utils.ts` to replace `signer` with `account` for signing transactions.
- Updated `in-app-account.ts` to correctly handle domain data for typed data signatures.

### How to test?

1. Deploy a contract using the dashboard and ensure that `account` is used correctly instead of `signer`.
2. Validate that typed data signatures are correctly generated in the in-app wallet.

### Why make this change?

To improve the accuracy and reliability of in-app wallet typed data signatures by ensuring the correct handling of domain data and consistent use of `account` across the application.

---

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to fix in-app wallet typed data signatures and optimize contract-related functions.

### Detailed summary
- Fixed in-app wallet typed data signatures
- Updated contract-related functions for better optimization and clarity

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

<!-- end pr-codex -->
2024-07-16 05:38:11 +00:00
gregfromstl 73c74f11d4 feat(airdrop): add fetchProofsERC methods for ERC20, ERC721, and ERC1155 (#3709)
This update introduces new methods for fetching proofs for ERCXX tokens (specifically ERC20, ERC721, and ERC1155). The methods `fetchProofsERC20`, `fetchProofsERC721`, and `fetchProofsERC1155` have been added to the airdrop extension. These methods allow users to retrieve claim Merkle proofs for the specified address and tokens, ensuring that users in the allowlist can claim their airdrop. Additionally, example usage and detailed docstrings have been included to guide developers on how to implement these methods in their projects.

---

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to add `fetchProofsERCXX` methods for ERC721, ERC20, and ERC1155 airdrop contracts.

### Detailed summary
- Added `fetchProofsERC721`, `fetchProofsERC20`, and `fetchProofsERC1155` methods
- Updated `claimERC20` to use `fetchProofsERC20`
- Added detailed documentation for each method
- Renamed `fetchProofsrERC20` to `fetchProofsERC20`

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

<!-- end pr-codex -->
2024-07-16 05:27:46 +00:00
kien-ngo 3479117b28 Add Vietnamese locale (#3681)
<!-- start pr-codex -->

## PR-Codex overview
This PR adds Vietnamese locale support for the ConnectButton components and updates various language files for the ConnectWallet feature.

### Detailed summary
- Added Vietnamese locale for ConnectButton components
- Updated language files for ConnectWallet screens and wallets with Vietnamese translations

> The following files were skipped due to too many changes: `packages/thirdweb/src/react/web/wallets/local/locale/vi.ts`, `packages/thirdweb/src/react/web/wallets/shared/locale/vi.ts`, `packages/thirdweb/src/react/web/ui/ConnectWallet/locale/vi.ts`

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

<!-- end pr-codex -->
2024-07-16 03:38:43 +00:00
kien-ngo 34f6fd5fdd Add chainlist link to the contract page (#3705)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to add a link to the `MetadataHeader` component that redirects to a specific chain page.

### Detailed summary
- Added `Link` import from "next/link"
- Applied `as={Link}` and `href={`/${chain.chainId}`}` to make the header clickable
- Set `cursor="pointer"` for better user interaction

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

<!-- end pr-codex -->
2024-07-16 00:57:30 +00:00
joaquim-verges baec85f6b4 fix(thirdweb): update TransactionError constructor to correctly set message property (#3704) 2024-07-16 00:44:17 +00:00
gregfromstl 88fa60d4ad fix(dashboard): domain validation for ecosystem partner domains (#3701)
### TL;DR
Updated the domain validation regex in the AddPartnerForm component to handle new wildcard subdomain cases and made minor formatting fixes.

### What changed?
- Updated the domain validation regex to handle new wildcard subdomain cases.
- Fixed minor formatting issues with array and string declarations.

### How to test?
1. Navigate to the Add Partner form in the dashboard.
2. Test the domain input field with the following cases to ensure proper validation:
   - general domains (e.g., example.com)
   - wildcard subdomains (e.g., *.example.com)
   - nested wildcard subdomains (e.g., *.*.example.com)

### Why make this change?
The changes were necessary to improve the domain validation mechanism by accommodating new wildcard subdomain cases, and to maintain code quality through consistent formatting.

---

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to update the `isDomainRegex` pattern in the `add-partner-form.client.tsx` file for improved domain validation.

### Detailed summary
- Updated the `isDomainRegex` pattern for domain validation with additional flexibility and accuracy.

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

<!-- end pr-codex -->
2024-07-15 22:40:41 +00:00
iuwqyir d780bff72f new fields for usage event schema (#3692)
## Problem solved

Adds 2 new optional fields to usage event schema:
* evmRequestParams
* providerIp

Allows a new possible source for the event - `rpcV2`

## Changes made

- [x] service-utils: Update usage tracker schema

## How to test

## Contributor NFT

Paste in your wallet address below and we will airdrop you a special NFT when your pull request is merged.

```Address: ```

<!-- start pr-codex -->

---

## PR-Codex overview
This PR updates the schema for the usage tracker event in the `service-utils` package to include new fields `evmRequestParams` and `providerIp`.

### Detailed summary
- Added `evmRequestParams` field to the usage event schema
- Added `providerIp` field to the usage event schema

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

<!-- end pr-codex -->
2024-07-15 22:17:53 +00:00
gregfromstl 062bcc79f9 fix(dashboard): update ecosystem wallet copy to include wallet count (#3702)
### TL;DR

Updated UI elements and feature list in the create page of the ecosystem section.

### What changed?

- Adjusted padding and positioning of elements for better alignment and appearance.
- Added a new feature item to the list: '30,000 active wallets included*'.
- Included a note regarding additional wallet costs ('$0.02 per additional wallet').

### How to test?

Navigate to the 'Create Ecosystem' page in the dashboard. Verify that the layout changes are correctly applied and the new feature/item is visible with the note on wallet costs.

### Why make this change?

These updates improve the clarity of information provided to users and enhance the overall user experience on the create page of the ecosystem section.

---

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to update the ecosystem creation page in the dashboard with additional wallet information.

### Detailed summary
- Added display of 30,000 active wallets included
- Added pricing information for additional wallets

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

<!-- end pr-codex -->
2024-07-15 22:12:27 +00:00
Manan TankandGitHub 817a778a17 Fix Network Selector only showing 1 search result (#3694) 2024-07-16 01:48:17 +05:30
jnsdls 5eddf27a48 [Feature] Update title in PRICING_SECTIONS for Monthly Active In-App Wallets (#3693) 2024-07-15 18:46:14 +00:00
81751d3e08 Fix "add custom network" button not closing details modal (#3690)
Signed-off-by: Jonas Daniels <[email protected]>
Co-authored-by: Jonas Daniels <[email protected]>
2024-07-15 18:25:59 +00:00
7e416c0f6b Add queryOptions for useWalletBalance hook (#3688)
Co-authored-by: MananTank <[email protected]>
2024-07-15 18:07:46 +00:00
MananTank 6ad65e234c Add type prop for TransactionButton (#3689)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to add a `type` prop for the `TransactionButton` component in the `thirdweb` package.

### Detailed summary
- Added `type` prop for `TransactionButton`
- Updated `TransactionButton` component to include `type` attribute for button element

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

<!-- end pr-codex -->
2024-07-15 17:38:47 +00:00
Manan TankandGitHub d27f9ffdd1 Fix wrong isBrave check in dashboard (#3691) 2024-07-15 22:58:10 +05:30
Joaquim VergesandGitHub a3fb673e50 fix(thirdweb): handle universal links on ios for coinbase wallet connection (#3677) 2024-07-15 14:30:47 +12:00
kien-ngo aee7aef76f Export getClaimParams for thirdweb Drop contracts (#3685)
Initially this is for interacting with other frameworks like frog.fm
Might be useful elsewhere idk

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on exporting a new utils method `getClaimParams` for thirdweb Drop contracts.

### Detailed summary
- Added export for `getClaimParams` method in `utils/extensions/drops/get-claim-params.js`
- Exported type `GetClaimParamsOptions` for thirdweb Drop contracts

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

<!-- end pr-codex -->
2024-07-15 02:10:44 +00:00
kien-ngo b67519aecb Allow uploading .obj file (#3684)
<!-- start pr-codex -->

## PR-Codex overview
This PR enhances file input handling in components by adding support for `.obj` files alongside `.usdz` and `.glb` files.

### Detailed summary
- Updated `FileInput.tsx` to support `.obj` files for 3D models
- Updated `mint-form.tsx` to recognize `.gltf` files and `.obj` files for 3D models

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

<!-- end pr-codex -->
2024-07-14 21:30:21 +00:00
kien-ngo eabb2150a9 Add support for Zora1155 in ERC1155 > getOwned (#3659)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to add support for Zora1155 in ERC1155 > getOwned.

### Detailed summary
- Added support for Zora1155 contract in ERC1155 > getOwned function
- Updated functions to handle Zora1155 contract methods
- Introduced new functions for Zora1155 contract interaction

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

<!-- end pr-codex -->
2024-07-12 21:09:23 +00:00
Joaquim VergesandGitHub 9f3fb7d1ee feat(smart): respect accountAddress override (#3673) 2024-07-13 05:59:47 +12:00
arcoraven 0d4852787f feat: Tools pages (#3665)
Adds new tools pages:
- Wei converter
- Hex converter
- Unix time converter
- Keccak256 converter

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to add new tools to the dashboard for converting between different formats like hex, decimal, Unix time, and Keccak-256 hashes.

### Detailed summary
- Added Hex Converter, Wei Converter, Unix Time Converter, and Keccak256 Converter tools
- Created components for each converter tool
- Implemented share functionality for each tool
- Added metadata for each tool
- Included tab navigation for easy access to tools

> The following files were skipped due to too many changes: `apps/dashboard/src/app/(dashboard)/tools/unixtime-converter/components/UnixTimeConverter.tsx`, `apps/dashboard/src/app/(dashboard)/tools/wei-converter/components/WeiConverter.tsx`

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

<!-- end pr-codex -->
2024-07-12 16:56:13 +00:00
Joaquim VergesandGitHub 4a1d1494ec feat(dashboard): add import for SortBy type to chain page (#3670) 2024-07-12 21:29:04 +12:00
Joaquim VergesandGitHub 0e555529d4 feat(dashboard): handle trending contracts in chain page (#3669) 2024-07-12 21:25:18 +12:00
Joaquim VergesandGitHub 21b72baf5b fix(dashboard): ensure scrolling sticks for pagination (#3668) 2024-07-12 20:35:20 +12:00
farhanW3 00fd82b08e Updates: Engine Demo (#3666)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to enhance the dashboard engine functionality by adding a demo engine feature and improving user interactions.

### Detailed summary
- Added a demo engine URL environment variable
- Updated import engine instance button style
- Implemented try demo button functionality with analytics tracking
- Improved error handling for missing environment variables

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

<!-- end pr-codex -->
2024-07-12 07:54:16 +00:00
Joaquim VergesandGitHub 95397cd0f7 feat(dashboard): implement sorting feature in trending table (#3667) 2024-07-12 19:31:12 +12:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>GitHub Action
a629ae53f1 Version Packages (#3658)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub Action <[email protected]>
2024-07-12 08:23:22 +12:00
joaquim-verges 3d14162a69 fix(core): correct extension detection (#3657)
<!-- start pr-codex -->

## PR-Codex overview
This PR focuses on fixing extension contract detection and enhancing ownership function detection for ERC721 contracts.

### Detailed summary
- Fixed extension contract detection in `detectExtension.ts`
- Added ownership function detection in `getOwnedNFTs.test.ts`
- Updated imports for test clients and contract utils

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

<!-- end pr-codex -->
2024-07-11 19:32:30 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
12f829f4f1 Version Packages (#3643)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-07-12 06:44:19 +12:00
77d7dd135f fix(thirdweb): resolve autoconnect issue for phone number sign-in on React Native (#3656)
Co-authored-by: joaquim-verges <[email protected]>
2024-07-12 06:27:34 +12:00
Manan TankandGitHub 9dd7b4de79 Ensure account address is checksum encoded (#3655) 2024-07-11 23:25:26 +05:30
jnsdls 44eb1bdd51 [Refactor] Clean up create-ticket.action.ts to streamline form data handling (#3654)
### TL;DR
Updated the createTicketAction function to ensure that only specific fields (attachments and json) are retained in formData during ticket creation.

### What changed?
- Introduced a constant KEEP_FIELDS to specify fields that should be retained in formData.
- Added the content field to formData before deleting non-essential fields.
- Removed specific deletion of extraInfo_Problem_Area key.

### How to test?
1. Trigger the createTicketAction function in support component.
2. Verify if only attachments and json fields are present in the formData when a ticket is created.

### Why make this change?
To ensure that only necessary data is sent when creating a ticket, optimizing the data payload and avoiding potential issues with extraneous fields.

---
2024-07-11 15:41:28 +00:00
jnsdls 727467b41a [Feature] Add Mantle banner and update ChainPageLayout for visual consistency (#3653)
This PR enhances the ChainPageLayout by adding support for background images for different chains and integrating Mantle chain-specific assets. Key updates include:
- Addition of the `mantle-banner.jpeg` and `mantle-cta.jpeg` images.
- Updates to `add-chain-to-wallet.tsx` and `layout.tsx` to support dynamic background and text color adjustments based on the presence of a background image.
- Modification of the `chainMetaRecord` to include metadata for the Mantle chain (chain ID 5000).

 ### TL;DR
Enhanced the ChainPageLayout component by adding support for chain-specific background images and integrating Mantle assets.

 ### What changed?
- New chain-specific background image support
- Integration with Mantle assets
- Updates to relevant components to handle background and text adjustments dynamically.

 ### How to test?
1. Go to the ChainPageLayout for any chain that has a background image (e.g., Mantle).
2. Verify that the background image is displayed correctly.
3. Check that text color and other UI elements adjust appropriately based on the background image.
4. Ensure that Mantle-specific content is displayed correctly.

 ### Why make this change?
This enhancement provides a more visually engaging and chain-specific user experience. The integration with Mantle also helps in showcasing specific chains more effectively.

---
2024-07-11 15:20:26 +00:00
joaquim-verges 9bbbba44f2 refactor(search): use trending contract data in search (#3652)
<!-- start pr-codex -->

## PR-Codex overview
This PR updates time range handling and contract fetching in the trending feature.

### Detailed summary
- Updated time range handling in `TimeRangeSwitcher`
- Moved `TimeRange` type to `lib/search`
- Refactored contract fetching logic to `fetchTopContracts`
- Added new types and functions related to trending contracts
- Updated imports and removed redundant code in `trending-table`

> The following files were skipped due to too many changes: `apps/dashboard/src/app/trending/components/trending-table.tsx`, `apps/dashboard/src/components/cmd-k-search/index.tsx`

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

<!-- end pr-codex -->
2024-07-11 08:44:56 +00:00
jnsdls 17f5b5ab52 [Feature] Add background image and update login page UI (#3651) 2024-07-11 07:11:25 +00:00
jnsdls 0bbf157a31 [Refactor] Update ChainPageLayout and ChainCTA components for visual consistency and add ancient8 banner asset (#3650) 2024-07-11 07:01:24 +00:00
joaquim-verges f402f6d1c2 trending contracts (#3641)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to enhance the dashboard UI and functionality.

### Detailed summary
- Updated UI components like `Spinner` and `Toggle`
- Improved styling and color schemes
- Added new pages and components for trending contracts
- Refactored search functionality
- Integrated thirdweb client for chain icons

> The following files were skipped due to too many changes: `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/page.tsx`, `apps/dashboard/src/@/components/ui/table.tsx`, `apps/dashboard/src/app/trending/components/icons.tsx`, `apps/dashboard/src/app/trending/components/trending-table.tsx`, `pnpm-lock.yaml`

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

<!-- end pr-codex -->
2024-07-11 04:19:17 +00:00
jnsdls 4661731561 [Feature] Add /support path to the list of logged in only paths (#3649) 2024-07-11 03:08:05 +00:00
jnsdls 509c584e7a [Refactor] Update environment variable usage and integrate Radix Dialog component (#3648)
This refactor replaces the usage of individual Unthread environment variables with a single `UNTHREAD_API_KEY`. Additionally, components and forms related to support tickets have been updated to streamline the support request flow. The Chakra UI components have been replaced with Radix UI components for consistency. Unused components have been removed and some components were slightly enhanced for development simplicity.

---

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to refactor code in the dashboard app, update dependencies, and improve UI components.

### Detailed summary
- Removed support-related components and pages
- Updated layout and styling in various dashboard components
- Added new products and product-related functions
- Updated dependencies in `package.json` and `pnpm-lock.yaml`
- Refactored form inputs and layouts in support forms

> The following files were skipped due to too many changes: `apps/dashboard/src/components/help/contact-forms/engine/index.tsx`, `apps/dashboard/src/components/help/contact-forms/connect/AffectedAreaInput.tsx`, `apps/dashboard/src/components/help/contact-forms/shared/SupportForm_SelectInput.tsx`, `apps/dashboard/src/components/help/contact-forms/contracts/index.tsx`, `apps/dashboard/src/components/help/contact-forms/connect/index.tsx`, `apps/dashboard/src/@/components/ui/dialog.tsx`, `apps/dashboard/src/app/(dashboard)/support/components/create-ticket.client.tsx`, `apps/dashboard/src/app/(dashboard)/support/components/create-ticket.action.ts`, `apps/dashboard/src/components/help/contact-forms/shared/SupportForm_AttachmentUploader.tsx`, `apps/dashboard/src/app/(dashboard)/support/page.tsx`

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

<!-- end pr-codex -->
2024-07-10 16:00:39 -07:00
Manan TankandGitHub 979a2b8147 Fix zero token amount formatting (#3646) 2024-07-10 21:29:41 +05:30
kien-ngo f239d09eae MediaRenderer: only render video poster if it's an image (#3642)
<!-- start pr-codex -->

## PR-Codex overview
This PR focuses on updating the `MediaRenderer` component to only render the video poster if it's an image.

### Detailed summary
- Updated `MediaRenderer` to conditionally render video poster based on MIME type
- Improved handling of poster rendering for better compatibility

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

<!-- end pr-codex -->
2024-07-10 03:44:29 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>GitHub Action
133eae1384 Version Packages (#3635)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub Action <[email protected]>
2024-07-10 09:01:31 +12:00
jnsdls 6370b7cc90 [Refactor] Remove NeedSomeHelp component and its references (#3640)
### TL;DR
This PR removes the `ContextAIBotButton` and `NeedSomeHelp` components from the dashboard source code.

### What changed?
- Deleted `context-ai-button.tsx` and `need-some-help.tsx` files from the help folder.
- Updated `support.tsx` to remove the `NeedSomeHelp` component.

### How to test?
1. Navigate to the support page in the dashboard.
2. Ensure that the `NeedSomeHelp` section is no longer displayed.
3. Check that there are no console errors related to the missing components.

### Why make this change?
These components are no longer needed as part of the dashboard's help system and are being removed to simplify the codebase and reduce unnecessary dependencies.

---

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to remove unused help components and restructure the Support page layout.

### Detailed summary
- Deleted `NeedSomeHelp` and `ContextAiButton` components
- Removed unnecessary import statements
- Updated the layout of the Support page to exclude `NeedSomeHelp` component

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

<!-- end pr-codex -->
2024-07-09 18:34:41 +00:00
jnsdls f91a024cc5 [Refactor] Update THIRDWEB_API_HOST integration in ensure-login flow (#3638)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to update authentication endpoints and improve error handling in the codebase.

### Detailed summary
- Updated logout endpoint in `General.tsx`
- Changed user authentication endpoint to `/v1/account/me`
- Removed `decodeJWT` function import
- Added `THIRDWEB_API_HOST` environment variable
- Improved error handling in `GET` function in `route.ts`

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

<!-- end pr-codex -->
2024-07-09 18:34:36 +00:00
joaquim-verges cebf6d4e89 fix(sdk): enforce legacy transactions on Vanar mainnet (#3639) 2024-07-09 18:15:43 +00:00
jnsdls 17701b69f0 [Feature] Add conditional page refresh on specific routes and integrate PayUI component (#3607)
<!-- start pr-codex -->

## PR-Codex overview
This PR updates components related to Pay analytics and configuration.

### Detailed summary
- Updated `usePayPurchases`, `usePayVolume`, `usePayNewCustomers`, and `usePayCustomers` hooks
- Refactored `PayUI` component in `dashboard/connect/pay/components/pay-ui.client.tsx`
- Added `getApiKeys` function in `dashboard/connect/pay/page.tsx`

> The following files were skipped due to too many changes: `apps/dashboard/src/app/(dashboard)/dashboard/connect/pay/page.tsx`

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

<!-- end pr-codex -->
2024-07-09 17:56:10 +00:00
gregfromstl e4d9963f2d chore(dashboard): remove nft checkout from api page (#3636)
<!-- start pr-codex -->

## PR-Codex overview
This PR removes the `checkout` service from `services.ts` and adjusts the `pay` service properties.

### Detailed summary
- Removed `checkout` service
- Adjusted properties of `pay` service

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

<!-- end pr-codex -->
2024-07-09 17:43:28 +00:00
joaquim-verges 02fff7d9e8 fix(thirdweb): loosen react native peer dep version restriction (#3637) 2024-07-09 17:36:29 +00:00
Manan TankandGitHub 4d24208099 Fix smart wallet connection not updating connection manager properly (#3634) 2024-07-09 21:34:52 +05:30
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
f8016071e2 Version Packages (#3612)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-07-09 19:34:41 +12:00
Joaquim VergesandGitHub 636fe40779 fix(storage): correct directory handling for mobile file uploads (#3633) 2024-07-09 19:21:00 +12:00
jnsdls a02d1111e0 [Refactor] Remove unused useConfirmEmbeddedWallet hook and clean up onboarding flow (#3632)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to refactor authentication and onboarding flows, removing unused code and optimizing user creation and confirmation processes.

### Detailed summary
- Added user creation logic if user does not exist
- Removed `useConfirmEmbeddedWallet` hook
- Refactored onboarding flow and removed unused code
- Optimized handling of account confirmation and email verification

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

<!-- end pr-codex -->
2024-07-09 05:08:24 +00:00
jnsdls 9b2591cc21 [Feature] Add CustomPayEmbed component to pay page for chain integration (#3629)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to add a custom payment embed component for a specific chain in the dashboard.

### Detailed summary
- Added `CustomPayEmbed` component in `pay-embed.client.tsx`
- Utilized `thirdwebClient` and `defineChain` for payment functionality
- Integrated theme handling and payment options for a specific chain

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

<!-- end pr-codex -->
2024-07-09 00:02:48 +00:00
jnsdls 3f0291def5 [Feature] Enhance login flow with loading spinner and redirect button (#3631) 2024-07-08 23:55:59 +00:00
MananTank 41b9a53e35 Fix search in Network selector (#3630)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to fix the search functionality in the Network Selector screen by optimizing chain queries and improving user experience.

### Detailed summary
- Added `useChainsQuery` and `useChainQuery` functions for chain data retrieval
- Improved search functionality by optimizing chain queries and handling loading states
- Updated dependencies and imports for better code organization

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

<!-- end pr-codex -->
2024-07-08 22:35:37 +00:00
jnsdls 73105cc4ff [Feature] Extend useEcosystem hook and update Layout and Ecosystem components (#3604)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to refactor ecosystem creation and management components in the dashboard.

### Detailed summary
- Refactored ecosystem creation components
- Updated ecosystem status handling
- Improved ecosystem selection functionality
- Reorganized ecosystem layout components

> The following files were skipped due to too many changes: `apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/components/client/ecosystem-header.client.tsx`

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

<!-- end pr-codex -->
2024-07-08 22:05:45 +00:00
Joaquim VergesandGitHub 95c9d3d924 chore(sdk): export smart wallet and bundler utilities (#3622) 2024-07-09 08:34:53 +12:00
gregfromstl 325416ea19 feat(chain): add Blast chain definition and export (#3619)
### TL;DR

Added a new chain definition for the 'Blast' chain.

### What changed?

- Added a new file `blast.ts` in `chain-definitions`
- Defined the Blast chain with ID 81457, name 'Blast', and native currency 'Ether'.
- Added Blastscan as the block explorer with corresponding URL and API URL.
- Updated `chains.ts` to export the `blast` chain.

### How to test?

1. Verify that the `blast.ts` file exists in the `chain-definitions` directory.
2. Check that the chain ID, name, and native currency are correctly defined.
3. Ensure the block explorer details are accurate.
4. Confirm that `chains.ts` exports the `blast` chain.

### Why make this change?

This change adds support for the Blast chain, which may be required for upcoming features or integrations. Including it ensures that the system can recognize and interact with the Blast blockchain.

---

<!-- start pr-codex -->

---

## PR-Codex overview
This PR adds the `blast` chain preset to `thirdweb` package.

### Detailed summary
- Added `blast` chain definition in `blast.ts`
- Exported `blast` in `chains.ts` for use in `thirdweb` package

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

<!-- end pr-codex -->
2024-07-08 19:41:36 +00:00
gregfromstl 444ac06b10 fix(dashboard): update partner ID description in ecosystem partners section (#3620)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to enhance the user guidance in the ecosystem-partners-section by adding a reminder to generate at least one partner ID for use in the app.

### Detailed summary
- Added a reminder to generate at least one partner ID for app usage.

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

<!-- end pr-codex -->
2024-07-08 19:27:42 +00:00
Manan TankandGitHub 5470dd9cf8 Pay UI improvements - Token amount rounding (#3621) 2024-07-09 00:38:42 +05:30
Jonas DanielsandGitHub 9b67df7d11 [Fix] Enhance error logging in login flow (#3617) 2024-07-08 15:32:23 +00:00
jnsdls 21aaec802f [Refactor] Improve MediaRenderer component and update token components (#3602)
<!-- start pr-codex -->

## PR-Codex overview
This PR enhances ERC20 functionality and token details display.

### Detailed summary
- Added `transferBatch()` extension to `erc20.ts`
- Updated `TokenDetails` component to include `chainId`
- Improved ERC20 contract handling in `useTxNotifications`
- Updated `TokenBurnButton` and `TokenAirdropButton` components to use V5 contract handling

> The following files were skipped due to too many changes: `apps/dashboard/src/contract-ui/tabs/tokens/components/airdrop-button.tsx`, `apps/dashboard/src/contract-ui/tabs/tokens/components/transfer-button.tsx`, `apps/dashboard/src/contract-ui/tabs/tokens/components/supply.tsx`, `apps/dashboard/src/contract-ui/tabs/tokens/components/airdrop-form.tsx`, `apps/dashboard/src/contract-ui/tabs/tokens/components/transfer-form.tsx`, `apps/dashboard/src/contract-ui/tabs/tokens/components/burn-form.tsx`

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

<!-- end pr-codex -->
2024-07-08 08:26:40 +00:00
Jonas DanielsandGitHub 230a49be7b [Fix] Add support for legacy TW_AUTH_TOKEN in useLoggedInUser hook (#3616) 2024-07-08 01:25:11 -07:00
Jonas DanielsandGitHub 36b6ef3e68 [Refactor] Update environment variable usage for THIRDWEB_API_HOST in login flow (#3615) 2024-07-08 00:47:41 -07:00
jnsdls 342d74efff api proxy (#3603)
<!-- start pr-codex -->

## PR-Codex overview
This PR focuses on enhancing JWT utils, updating API host paths, and optimizing user authentication handling.

### Detailed summary
- Export JWT utils, fix naming of `decodeJWT`
- Update API host paths to use relative paths
- Optimize user authentication handling in various components

> The following files were skipped due to too many changes: `apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/hooks/use-delete-partner.ts`, `apps/dashboard/src/components/app-layouts/app.tsx`, `apps/dashboard/src/components/buttons/TransactionButton.tsx`, `apps/dashboard/src/pages/dashboard/settings/notifications.tsx`, `apps/dashboard/src/components/engine/overview/transaction-timeline.tsx`, `apps/dashboard/src/pages/dashboard/settings/devices.tsx`, `apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/hooks/use-add-partner.ts`, `apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/hooks/use-update-ecosystem.ts`, `apps/dashboard/src/app/(dashboard)/dashboard/connect/pay/page.tsx`, `apps/dashboard/src/pages/dashboard/engine/index.tsx`, `apps/dashboard/src/pages/dashboard/settings/billing.tsx`, `apps/dashboard/src/components/engine/engine-instances-table.tsx`, `apps/dashboard/src/pages/dashboard/settings/usage.tsx`, `apps/dashboard/src/pages/dashboard/settings/gas-credits.tsx`, `apps/dashboard/src/pages/dashboard/settings/api-keys/index.tsx`, `apps/dashboard/src/pages/api/server-proxy/api/[...paths].tsx`, `apps/dashboard/src/pages/dashboard/connect/analytics.tsx`, `apps/dashboard/src/components/storage/your-files.tsx`, `apps/dashboard/src/pages/api/server-proxy/pay/[...paths].tsx`, `apps/dashboard/src/components/engine/engine-list.tsx`, `apps/dashboard/src/components/pay/PayAnalytics/hooks/usePayVolume.ts`, `apps/dashboard/src/components/pay/PayAnalytics/hooks/usePayNewCustomers.ts`, `apps/dashboard/src/components/pay/PayAnalytics/hooks/usePayPurchases.ts`, `apps/dashboard/src/pages/dashboard/connect/in-app-wallets.tsx`, `apps/dashboard/src/middleware.ts`, `apps/dashboard/src/components/pay/PayAnalytics/hooks/usePayCustomers.ts`, `apps/dashboard/src/pages/dashboard/connect/account-abstraction.tsx`, `apps/dashboard/src/app/login/page.tsx`, `apps/dashboard/src/app/components/ThirdwebMiniLogo.tsx`, `apps/dashboard/src/app/api/auth/ensure-login/route.ts`, `apps/dashboard/src/app/login/auth-actions.ts`, `apps/dashboard/src/components/buttons/MismatchButton.tsx`, `apps/dashboard/src/@3rdweb-sdk/react/hooks/useLoggedInUser.ts`, `apps/dashboard/src/@3rdweb-sdk/react/components/connect-wallet/index.tsx`, `apps/dashboard/src/@3rdweb-sdk/react/hooks/useApi.ts`, `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-07-08 06:17:38 +00:00
gregfromstl d253bad72f feature(ts): adds verifyTypedData and verifyHash (#3613) 2024-07-08 04:18:01 +00:00
gregfromstl f6ff5a78fc feat(connect-modal): Integrate NFT support into connect modal (#3585)
This PR introduces the ability to add NFTs to the connect modal in the thirdweb package. By using the `supportedNFTs` configuration, users can customize which NFTs are shown in the 'View Funds' section within the details modal. This update includes modifications to several TypeScript files to support the new functionality, adjustments in the UI components to handle NFT displays, and updates to hooks and utility functions to fetch and display owned NFTs.

---

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to add support for NFTs in the connect modal and customize the NFTs shown in the "View Funds" screen.

### Detailed summary
- Added support for NFTs in the connect modal with `supportedNFTs`
- Customized NFTs shown in the "View Funds" screen with `supportedNFTs`
- Updated components and types to handle NFTs
- Added NFT customization examples in documentation

> The following files were skipped due to too many changes: `packages/thirdweb/src/react/web/ui/ConnectWallet/screens/ViewFunds.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/Details.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/screens/ViewNFTs.tsx`

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

<!-- end pr-codex -->
2024-07-05 06:06:20 +00:00
MananTank f103a902f3 Fix TransactionButton callbacks not called when sending tx from pay modal (#3611)
<!-- start pr-codex -->

## PR-Codex overview
This PR focuses on fixing Transaction Button callbacks not being called when a transaction is executed in the Pay Modal.

### Detailed summary
- Added `rejectTx` parameter with reason in `useSendTransaction.ts`
- Added `resolveTx` parameter in `useSendTransaction.ts`
- Updated `useSendTransaction` in `useSendTransaction.tsx` to handle `rejectTx` and `resolveTx`
- Added `onTxSent` callback in `TxModal` and `ExecutingTxScreen` to handle transaction data

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

<!-- end pr-codex -->
2024-07-05 05:19:20 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>GitHub Action
0191e8dbad Version Packages (#3610)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub Action <[email protected]>
2024-07-05 16:48:57 +12:00
Manan TankandGitHub 2ab8b3ca78 reset selection data on wallet button click (no custom selection UI) (#3608) 2024-07-05 03:24:00 +00:00
gregfromstl 9faa8fc112 feat(auth): add ERC-6492 utilities and verification compatibility (#3609) 2024-07-05 01:46:21 +00:00
gregfromstl 34b9bbe77f fix(wallet): ensure disconnect events are emitted (#3597)
Introducing a patch in the `thirdweb` library to address wallet disconnect events. The main changes involve making the `onDisconnect` function asynchronous and ensuring that it correctly emits disconnect events. Affected files include `coinbaseWebSDK.ts` and `index.ts` in the `thirdweb/src/wallets` directory.

---

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on fixing wallet disconnect events not being emitted in the `thirdweb` package.

### Detailed summary
- Added `async` keyword to `onDisconnect` function in `injected/index.ts` and `coinbaseWebSDK.ts`
- Replaced `disconnect` with `onDisconnect` in `onConnect` functions in both files

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

<!-- end pr-codex -->
2024-07-05 01:30:32 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
4b72c1174c Version Packages (#3606)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-07-04 21:39:31 +12:00
Joaquim VergesandGitHub c261921e55 fix(ui): resolve inapp wallet layout reset issue (#3605) 2024-07-04 21:27:00 +12:00
jnsdls 84e4d60752 [Fix] Remove outdated @ts-expect-error comments and update class usage (#3601) 2024-07-04 04:58:52 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>GitHub Action
b34ac5f524 Version Packages (#3586)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub Action <[email protected]>
2024-07-04 16:10:22 +12:00
gregfromstl 059063f95f fix(dashboard): update and add tooltips in ecosystem form component (#3596) 2024-07-04 03:53:15 +00:00
Manan TankandGitHub e22b308fa7 Add Pay/Receive wallet Selector in Pay UI, Wallet switcher in Details Modal (#3591) 2024-07-04 03:28:04 +00:00
joaquim-verges e598f46422 fix(sdk): enforce legacy transactions on Vanguard chain (#3600) 2024-07-04 03:00:19 +00:00
jnsdls d2de83da66 [Refactor] Replace useApiAuthToken with useAccessToken (#3592)
<!-- start pr-codex -->

## PR-Codex overview
This PR enhances the `siwe_auth` functionality for better user authentication and access control.

### Detailed summary
- Renamed `ConnectWallet` component to `ConnectButton`
- Updated `useExtensionContractInfo` to use `useActiveAccount`
- Replaced `useApiAuthToken` with `useAccessToken` in multiple files
- Improved `useSiweAuth` with additional features and mutations
- Updated components to use `useAccessToken` for authentication
- Refactored `useLoggedInUser` to fetch user data efficiently

> The following files were skipped due to too many changes: `apps/dashboard/src/@3rdweb-sdk/react/hooks/useApi.ts`, `apps/dashboard/src/@3rdweb-sdk/react/components/connect-wallet/index.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-07-04 02:16:03 +00:00
joaquim-verges eac126bb14 fix(react-native): respect modal title and theme colors (#3599) 2024-07-04 01:45:44 +00:00
Joaquim VergesandGitHub e0f4e5a233 fix(ui): correct error handling in SendFundsForm component (#3593) 2024-07-04 12:52:39 +12:00
Manan TankandGitHub e5cccb9d70 Fix Send TX UI (#3598) 2024-07-04 12:51:24 +12:00
gregfromstl a6ed6e66da fix(dashboard): ecosystem images (#3594)
<!-- start pr-codex -->

## PR-Codex overview
This PR adds the `sizes`, `alt`, `fill`, and `unoptimized` attributes to the image in `ecosystem-header.client.tsx`.

### Detailed summary
- Added `sizes="100px"` attribute to the image
- Added `alt={ecosystem.name}` attribute
- Added `fill` attribute
- Added `unoptimized` attribute

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

<!-- end pr-codex -->
2024-07-03 22:25:23 +00:00
jnsdls 106c01356c [Fix] Update awaitTransaction and alignedTx nonce handling (#3590)
FIXES: DASH-58

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on fixing the `ethers5` adapter's `populateTransaction` method for `sendTransaction`.

### Detailed summary
- Updated `populateTransaction` method in `ethers5.ts` to fix `sendTransaction` functionality
- Adjusted `nonce` default value from -1 to 0 for better handling

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

<!-- end pr-codex -->
2024-07-03 19:37:09 +00:00
kumaryash90 687328aae9 Blockscout v2 contract verification (#3576)
## Problem solved

Short description of the bug fixed or feature added

## Changes made

- [ ] Public API changes: list the public API changes made if any
- [ ] Internal API changes: explain the internal logic changes

## How to test

- [ ] Automated tests: link to unit test file
- [ ] Manual tests: step by step instructions on how to test

## Contributor NFT

Paste in your wallet address below and we will airdrop you a special NFT when your pull request is merged.

```Address: ```

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on adding support for Blockscout v2 contract verification.

### Detailed summary
- Added `ExplorerType` enum for different explorer types
- Modified contract verifier to handle Blockscout v2 verification
- Updated verification functions to support different explorer types

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

<!-- end pr-codex -->
2024-07-03 18:18:53 +00:00
gregfromstl 073359698e fix(hooks): update useLoggedInUser to include address validation (#3589) 2024-07-03 17:36:38 +00:00
gregfromstl ca54aa71c2 fix(dashboard): update to use new THIRDWEB_API_HOST in dashboard ecosystem components (#3588)
### TL;DR

Replaced `process.env.NEXT_PUBLIC_THIRDWEB_API_HOST` with `THIRDWEB_API_HOST` constant for ecosystem wallet-related fetch calls.

### What changed?

1. Updated import statements to bring in the `THIRDWEB_API_HOST` constant.
2. Replaced instances of `${process.env.NEXT_PUBLIC_THIRDWEB_API_HOST}` with `${THIRDWEB_API_HOST}` in ecosystem wallet-related fetch calls.
3. Updated links in the main ecosystem page for better navigation.

### How to test?

1. Ensure all ecosystem wallet functionality (fetching list, creating, etc.) still works without errors.
2. Verify that the navigation links on the main ecosystem page point to the correct URLs.

### Why make this change?

To replace the use of environment variables with constants for better code maintainability and readability.

---
2024-07-03 16:44:25 +00:00
Kien NgoandGitHub ff6d15491e Hotfix: Update support form to use Connect v5 (#3587) 2024-07-03 15:18:59 +00:00
Joaquim VergesandGitHub 229561e1a7 feat(react-native): animated connect loading states (#3583) 2024-07-03 20:51:54 +12:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>GitHub Action
e739d550e9 Version Packages (#3578)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub Action <[email protected]>
2024-07-03 17:45:37 +12:00
gregfromstl 4353229a55 docs(ts): fix ecosystem wallet jsdocs (#3580)
## Problem solved

Short description of the bug fixed or feature added

## Changes made

- [ ] Public API changes: list the public API changes made if any
- [ ] Internal API changes: explain the internal logic changes

## How to test

- [ ] Automated tests: link to unit test file
- [ ] Manual tests: step by step instructions on how to test

## Contributor NFT

Paste in your wallet address below and we will airdrop you a special NFT when your pull request is merged.

```Address: ```

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to update the ecosystem wallet integration by replacing the `integratorId` parameter with `partnerId`.

### Detailed summary
- Replaced `integratorId` parameter with `partnerId` for connecting to a restricted ecosystem wallet with designated partner ID.
- Updated the code comments to reflect the change in parameter name.

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

<!-- end pr-codex -->
2024-07-03 02:14:50 +00:00
joaquim-verges 9651b96b96 feat: expose waitForUserOpReceipt helper function (#3582) 2024-07-03 02:09:23 +00:00
joaquim-verges 3c1734f639 fix: unit price conversion for ERC20 claimTo (#3581) 2024-07-03 00:43:53 +00:00
jnsdls 49ae575211 refactor: ConnectWallet v5 in dashboard (#3397)
### TL;DR

Rewrite `useAddress` function with `useActiveAccount` function across various components to streamline account state handling. Replace `useChainId` with `useActiveWalletChain` to manage chain IDs more accurately. Update various other functions to align with the `thirdweb/react` package changes.

### What changed?

1. Replaced `useAddress` with `useActiveAccount` in multiple components.
2. Replaced `useChainId` with `useActiveWalletChain` in multiple components.
3. Updated hook imports and usages to align with the `thirdweb/react` package updates.
4. Revisited and updated certain functionalities, including wallet connections, contract interactions, and UI updates for better efficiency.

### How to test?

1. Check if the `useActiveAccount` function accurately reflects the current active account state across different components.
2. Verify the `useActiveWalletChain` function is managing and reflecting the chain ID appropriately.
3. Test various functionalities including wallet connections and contract interactions to ensure they are working as expected after the hook changes.

### Why make this change?

To streamline account and chain state handling, leveraging the latest hooks from the `thirdweb/react` package for better modernity and efficiency in code maintenance and functionality.

---

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on improving loading performance for chains and updating to useActiveAccount instead of useAddress.

### Detailed summary
- Improved loading performance for chains
- Replaced `useAddress` with `useActiveAccount` in multiple components
- Updated `fetchAuthToken` function to remove promises from the map when done

> The following files were skipped due to too many changes: `apps/dashboard/src/pages/dashboard/settings/billing.tsx`, `apps/dashboard/src/contract-ui/tabs/tokens/components/burn-button.tsx`, `apps/dashboard/src/contract-ui/tabs/proposals/page.tsx`, `apps/dashboard/src/core-ui/nft-drawer/useNftDrawerTabs.tsx`, `apps/dashboard/src/contract-ui/tabs/tokens/components/transfer-button.tsx`, `apps/dashboard/src/contract-ui/tabs/tokens/components/burn-form.tsx`, `apps/dashboard/src/contract-ui/tabs/claim-conditions/components/claim-conditions-form/index.tsx`, `apps/dashboard/src/contract-ui/tabs/settings/components/royalties.tsx`, `packages/thirdweb/src/react/web/ui/components/ChainName.tsx`, `apps/dashboard/src/contract-ui/components/solidity-inputs/address-input.tsx`, `apps/dashboard/src/components/engine/contract-subscription/contract-subscriptions-table.tsx`, `apps/dashboard/src/contract-ui/tabs/listings/components/listing-drawer.tsx`, `apps/dashboard/src/contract-ui/tabs/tokens/components/airdrop-button.tsx`, `apps/dashboard/src/pages/api/moralis/balances.ts`, `apps/dashboard/src/contract-ui/tabs/tokens/components/mint-form.tsx`, `apps/dashboard/src/contract-ui/tabs/tokens/components/airdrop-form.tsx`, `apps/dashboard/src/components/contract-components/contract-deploy-form/index.tsx`, `apps/dashboard/src/contract-ui/tabs/shared-components/listing-drawer.tsx`, `apps/dashboard/src/contract-ui/tabs/settings/components/primary-sale.tsx`, `apps/dashboard/src/contract-ui/tabs/account-permissions/components/account-signer.tsx`, `apps/dashboard/src/pages/profile/[profileAddress].tsx`, `apps/dashboard/src/contract-ui/tabs/nfts/components/claim-form.tsx`, `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/layout.tsx`, `apps/dashboard/src/components/onboarding/Steps.tsx`, `apps/dashboard/src/contract-ui/tabs/shared-components/list-button.tsx`, `apps/dashboard/src/contract-ui/components/primary-dashboard-button.tsx`, `packages/thirdweb/src/react/native/ui/components/ChainIcon.tsx`, `apps/dashboard/src/@3rdweb-sdk/react/hooks/useEngine.ts`, `apps/dashboard/src/contract-ui/tabs/nfts/components/mint-supply-tab.tsx`, `apps/dashboard/src/contract-ui/tabs/split/page.tsx`, `apps/dashboard/src/contract-ui/tabs/nfts/components/airdrop-tab.tsx`, `packages/thirdweb/src/react/web/ui/components/TokenIcon.tsx`, `apps/dashboard/src/contract-ui/tabs/nfts/components/claim-tab.tsx`, `packages/thirdweb/src/react/web/ui/components/token/TokenSymbol.tsx`, `apps/dashboard/src/pages/dashboard/contracts/deploy.tsx`, `apps/dashboard/src/components/contract-components/published-contract/index.tsx`, `apps/dashboard/src/contract-ui/tabs/english-auctions/components/table.tsx`, `apps/dashboard/src/pages/dashboard/contracts/publish.tsx`, `apps/dashboard/src/components/contract-components/contract-publish-form/index.tsx`, `apps/dashboard/src/app/(dashboard)/providers.tsx`, `apps/dashboard/src/components/engine/engine-instances-table.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/BuyTokenInput.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/tx-history/TokenInfoRow.tsx`, `apps/dashboard/src/contract-ui/tabs/direct-listings/components/table.tsx`, `apps/dashboard/src/components/contract-tabs/code/ContractCode.tsx`, `apps/dashboard/src/components/cmd-k-search/index.tsx`, `apps/dashboard/src/contract-ui/tabs/nfts/components/mint-form.tsx`, `packages/thirdweb/src/react/native/ui/connect/SendScreen.tsx`, `apps/dashboard/src/contract-ui/tabs/settings/components/metadata.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.tsx`, `apps/dashboard/src/contract-ui/tabs/code/components/code-overview.tsx`, `apps/dashboard/src/@3rdweb-sdk/react/hooks/useRegistry.ts`, `apps/dashboard/src/contract-ui/tabs/settings/components/platform-fees.tsx`, `packages/thirdweb/src/chains/utils.ts`, `packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/tx-history/BuyTxHistory.tsx`, `packages/thirdweb/src/react/native/ui/connect/ConnectedModal.tsx`, `apps/dashboard/src/pages/dashboard/index.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/PayWithCrypto.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatTxDetailsTable.tsx`, `apps/dashboard/src/contract-ui/tabs/overview/components/MarketplaceDetails.tsx`, `apps/dashboard/src/components/engine/overview/backend-wallets-table.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/screens/TokenSelector.tsx`, `apps/dashboard/src/@3rdweb-sdk/react/hooks/useVote.ts`, `packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.tsx`, `apps/dashboard/src/components/ipfs-upload/dropzone.tsx`, `apps/dashboard/src/components/app-layouts/app.tsx`, `apps/dashboard/src/components/contract-components/import-contract/modal.tsx`, `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/components/client/add-chain-to-wallet.tsx`, `apps/dashboard/src/components/wallets/PosthogIdentifier.tsx`, `apps/dashboard/src/@3rdweb-sdk/react/hooks/useContractRoles.ts`, `apps/dashboard/src/components/onboarding/index.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/Details.tsx`, `apps/dashboard/src/@3rdweb-sdk/react/hooks/useLoggedInUser.ts`, `apps/dashboard/src/components/selects/CustomChainRenderer.tsx`, `apps/dashboard/src/pages/cli/login.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/tx-history/SwapDetailsScreen.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatSteps.tsx`, `apps/dashboard/src/components/app-layouts/providers.tsx`, `apps/dashboard/src/components/buttons/TransactionButton.tsx`, `apps/dashboard/src/components/contract-components/hooks.ts`, `packages/thirdweb/src/react/core/hooks/others/useChainQuery.ts`, `apps/dashboard/src/components/buttons/MismatchButton.tsx`, `apps/dashboard/src/components/selects/NetworkSelectorButton.tsx`, `apps/dashboard/src/components/app-layouts/provider-setup.tsx`, `apps/dashboard/src/@3rdweb-sdk/react/components/connect-wallet/index.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/NetworkSelector.tsx`

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

<!-- end pr-codex -->
2024-07-02 21:57:22 +00:00
jnsdls f5b8afef5c [Fix] Remove IPFS replacement hack in ChainIcon component (#3579)
no longer needed
2024-07-02 21:44:10 +00:00
gregfromstl 4786c2da72 feature(dashboard): ecosystem wallets (#3537)
<!-- start pr-codex -->

## PR-Codex overview
This PR introduces new error classes, updates routing, adds UI components, and refactors styles in the dashboard app.

### Detailed summary
- Added `FetchError` class for errors in API fetch requests
- Updated routing for ecosystem permissions
- Added new UI components for alerts, dropdown menus, and tabs
- Refactored global CSS styles for colors and backgrounds
- Updated ecosystem and partner types
- Refactored layout and input components
- Added hooks for fetching partners and ecosystem status
- Added pages for payment failure and ecosystem creation status
- Updated user authentication hook for better handling of connection status

> The following files were skipped due to too many changes: `apps/dashboard/src/@3rdweb-sdk/react/hooks/useLoggedInUser.ts`, `apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/hooks/use-ecosystem.ts`, `apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/hooks/use-ecosystem-list.ts`, `apps/dashboard/src/app/components/Header/DashboardHeader.tsx`, `apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/layout.tsx`, `apps/dashboard/src/app/(dashboard)/dashboard/components/sidebar/sidebar.client.tsx`, `apps/dashboard/src/@/components/ui/form.tsx`, `apps/dashboard/src/@/components/ui/ConfirmationDialog.tsx`, `apps/dashboard/src/app/components/DashboardFooter.tsx`, `apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/hooks/use-delete-partner.ts`, `apps/dashboard/src/@/components/ui/image-upload.tsx`, `apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/hooks/use-update-ecosystem.ts`, `apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/create/page.tsx`, `apps/dashboard/src/app/(dashboard)/(chain)/chainlist/components/server/chainlist-card.tsx`, `apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/create/hooks/use-create-ecosystem.ts`, `apps/dashboard/src/@/components/ui/radio-group.tsx`, `apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/hooks/use-add-partner.ts`, `apps/dashboard/src/app/(dashboard)/(chain)/chainlist/components/client/filters.tsx`, `apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/components/client/integration-permissions-toggle.client.tsx`, `apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/components/client/ecosystem-header.client.tsx`, `apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/page.tsx`, `apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/components/server/partners-table.tsx`, `apps/dashboard/src/@/components/ui/alert-dialog.tsx`, `apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/create/components/client/create-ecosystem-form.client.tsx`, `apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/components/client/add-partner-form.client.tsx`, `apps/dashboard/src/@/components/ui/dropdown-menu.tsx`, `pnpm-lock.yaml`

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

<!-- end pr-codex -->
2024-07-02 21:17:53 +00:00
gregfromstl 6b919e1385 feature(react): show ecosystem wallet branding regardless of modal size (#3577)
<!-- start pr-codex -->

## PR-Codex overview
This PR focuses on displaying ecosystem wallet branding in a wide modal layout.

### Detailed summary
- Display ecosystem wallet branding in wide modal layout
- Updated `EcosystemWalletFormUI.tsx` to show wallet header in all layouts

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

<!-- end pr-codex -->
2024-07-02 20:58:52 +00:00
Jonas DanielsandGitHub 2b5ee62b2b Version Packages (#3571) 2024-07-02 11:37:11 -07:00
Manan TankandGitHub 59531310d9 Reset selection data on wallet selection (#3575) 2024-07-02 15:58:00 +00:00
joaquim-verges 9516259245 fix(react-native): ensure onClose is called on successful wallet connection in ConnectModal (#3573) 2024-07-02 15:13:22 +00:00
MananTank f526d733d0 Fix inApp wallet connection screen on compact modal (#3574)
<!-- start pr-codex -->

## PR-Codex overview
This PR focuses on fixing issues related to the inApp wallet connection flow in the Compact size Connect UI.

### Detailed summary
- Fixed broken inApp wallet connection flow
- Added missing back button in inApp wallet connection flow
- Updated handling of going back to main screen in wallet UI components

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

<!-- end pr-codex -->
2024-07-02 15:07:24 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
931cca3a7e build(deps): bump viem from 2.16.4 to 2.16.5 (#3567)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-01 22:49:57 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
20d4c90b54 build(deps-dev): bump @swc/core from 1.6.5 to 1.6.6 (#3566)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-01 22:49:47 -07:00
edwardysun e5f772dd5c Support localhost in Pay domains (#3569)
## Problem solved

Use "http://" if localhost domain used for thirdweb Pay

<!-- start pr-codex -->

---

## PR-Codex overview
This PR adds support for using localhost as a domain override option for the Pay service.

### Detailed summary
- Added support for localhost as a domain override option for the Pay service in `definitions.ts`
- Updated all endpoint URLs to use the `getPayBaseUrl()` function instead of directly fetching the domain from `getThirdwebDomains().pay`

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

<!-- end pr-codex -->
2024-07-02 05:13:20 +00:00
jnsdls 373ce19286 fix lockfile (#3572) 2024-07-02 04:49:24 +00:00
joaquim-verges 1a2e056329 feat(react native): add Skeleton loading state across components (#3570) 2024-07-02 03:58:23 +00:00
joaquim-verges 0077d38c65 feat: Connect components in React Native [part 1] (#3246)
<!-- start pr-codex -->

## PR-Codex overview
This PR focuses on refactoring, updating dependencies, and improving code organization.

### Detailed summary
- Updated dependencies and file paths
- Refactored wallet-related functions
- Added default wallets for various chains
- Updated UI components and design system configurations

> The following files were skipped due to too many changes: `packages/thirdweb/src/react/web/wallets/shared/OTPLoginUI.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/WalletSelector.tsx`, `packages/thirdweb/src/react/web/wallets/shared/SocialLogin.tsx`, `packages/thirdweb/src/react/native/ui/components/TokenIcon.tsx`, `packages/thirdweb/src/react/web/wallets/shared/PassKeyLogin.tsx`, `packages/thirdweb/src/react/web/ui/PayEmbed.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatSteps.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/Modal/SmartWalletConnectUI.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/screens/TokenSelector.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/screens/ViewFunds.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/screens/SignatureScreen.tsx`, `packages/thirdweb/src/react/web/ui/components/WalletImage.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/Modal/AnyWalletConnectUI.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/PayWithCrypto.tsx`, `packages/thirdweb/src/react/native/ui/connect/ErrorView.tsx`, `packages/thirdweb/src/react/web/hooks/transaction/useSendTransaction.tsx`, `packages/thirdweb/src/react/native/ui/connect/SuccessView.tsx`, `packages/react-native-adapter/README.md`, `packages/thirdweb/src/react/native/ui/components/text.tsx`, `packages/thirdweb/src/react/native/ui/components/ChainIcon.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/ConnectButton.tsx`, `packages/thirdweb/src/wallets/manager/index.ts`, `packages/thirdweb/src/react/web/wallets/shared/ConnectWalletSocialOptions.tsx`, `packages/thirdweb/src/react/native/ui/components/Address.tsx`, `packages/thirdweb/src/react/web/hooks/wallets/useAutoConnect.ts`, `packages/thirdweb/src/react/native/ui/components/RNImage.tsx`, `packages/thirdweb/src/exports/react.native.ts`, `packages/thirdweb/src/react/web/ui/ConnectWallet/ConnectButtonProps.ts`, `packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.tsx`, `packages/thirdweb/src/react/native/ui/components/Header.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/defaultTokens.ts`, `packages/thirdweb/src/react/native/ui/connect/ReceiveScreen.tsx`, `packages/thirdweb/src/react/native/ui/components/button.tsx`, `packages/thirdweb/src/exports/react.ts`, `packages/thirdweb/src/react/native/ui/components/WalletImage.tsx`, `packages/thirdweb/src/react/native/ui/connect/ConnectedButton.tsx`, `packages/thirdweb/src/react/core/hooks/wallets/useSendToken.ts`, `packages/thirdweb/src/react/web/ui/ConnectWallet/screens/SendFunds.tsx`, `packages/thirdweb/src/react/native/ui/components/input.tsx`, `packages/thirdweb/src/react/core/utils/wallet.ts`, `packages/thirdweb/src/react/web/ui/components/ChainIcon.tsx`, `packages/thirdweb/src/react/native/ui/connect/ExternalWalletsList.tsx`, `packages/thirdweb/package.json`, `packages/thirdweb/src/react/native/ui/connect/TokenListScreen.tsx`, `packages/thirdweb/src/react/native/ui/connect/ConnectButton.tsx`, `packages/thirdweb/src/react/native/ui/connect/SendScreen.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/Details.tsx`, `packages/thirdweb/src/react/native/ui/connect/ConnectModal.tsx`, `packages/thirdweb/src/react/native/ui/connect/InAppWalletUI.tsx`, `packages/thirdweb/src/react/core/hooks/connection/ConnectEmbedProps.ts`, `packages/thirdweb/src/react/native/ui/connect/ConnectedModal.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/Modal/ConnectEmbed.tsx`, `packages/thirdweb/src/react/web/ui/ConnectWallet/icons/dataUris.ts`, `packages/thirdweb/src/react/native/ui/icons/svgs.ts`, `pnpm-lock.yaml`

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

<!-- end pr-codex -->
2024-07-02 02:01:48 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>GitHub Action
53aa8674b4 Version Packages (#3555)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub Action <[email protected]>
2024-07-02 13:59:25 +12:00
gregfromstl 98a9e226fa fix(ts): import of coinbase sdk in vite (#3562)
### TL;DR

Corrected the import handling for CoinbaseWalletSDK in the coinbaseWebSDK.ts file.

### What changed?

The import statement for CoinbaseWalletSDK was modified to handle cases where the import does not return a default function directly.

### How to test?

- Verify the Coinbase wallet integration in the application.
- Ensure that different environments (e.g., development, production) can import and utilize the CoinbaseWalletSDK without errors.

### Why make this change?

This change ensures that the CoinbaseWalletSDK import is handled correctly, thereby preventing potential import errors that could occur in various environments.

---

<!-- start pr-codex -->

---

## PR-Codex overview
This PR fixes coinbase wallet connections on Vite by addressing import errors related to `CoinbaseWalletSDK`.

### Detailed summary
- Fixed import error for `CoinbaseWalletSDK` on Vite
- Added workaround for Vite dev import issues
- Ensured proper initialization of `CoinbaseWalletSDK` to connect coinbase wallet

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

<!-- end pr-codex -->
2024-07-01 22:05:33 +00:00
kien-ngo a1d6a3c93e Add announcement for Onchain Olympics (#3568)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to update the AnnouncementBanner component with a new link and label for the Onchain Olympics event, along with revised text content.

### Detailed summary
- Updated link `href` to "https://onchainolympics.com"
- Updated `label` to "onchain-olympics"
- Revised text content to promote the Onchain Olympics event and NFT minting.

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

<!-- end pr-codex -->
2024-07-01 21:42:49 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
6c0edcd673 build(deps): bump @radix-ui/react-focus-scope from 1.0.4 to 1.1.0 (#3564)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-01 14:41:54 -07:00
kien-ngo 3bee20d545 Fix playground docs link (#3561)
<!-- start pr-codex -->

## PR-Codex overview
This PR updates the link in the sign-in page to direct users to the new "overview" section instead of the main sign-in page.

### Detailed summary
- Updated the link `href` in the sign-in page to navigate to the "overview" section instead of the main sign-in page.

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

<!-- end pr-codex -->
2024-07-01 15:30:00 +00:00
Joaquim VergesandGitHub 6e24b3f0f5 fix: add missing sendTransaction import in multiple files to ensure proper transaction handling (#3559) 2024-07-01 20:35:52 +12:00
gregfromstl 54c1789330 fix(utils): correct filter condition for recommended wallets (#3558)
## Problem solved

Recommended wallets were being compared for object equality when sorting, which caused confusion when using inline `createWallet` to set the recommended wallets. This PR updates sorting to compare the recommended wallets by ID (installed providers already work this way)
2024-07-01 01:33:08 +00:00
jnsdls cbb0bc2835 [Fix] Update package dependencies and improve import paths (#3554)
This pull request updates package.json dependencies to specific versions across multiple packages, moving from using caret (^) to specific version numbers for consistency and to prevent unwanted updates. Additionally, it includes changes to various TypeScript files, primarily adding the ESLint directive `@typescript-eslint/no-unused-vars` to suppress warnings for unused variables.

---

<!-- start pr-codex -->

---

## PR-Codex overview
This PR updates dependencies, adds styled components, and disables eslint for unused vars in various React components.

### Detailed summary
- Updated dependencies in multiple package.json files
- Added styled components for DialogContent, Overlay, DropContainer, QRPlaceholder, and more
- Disabled eslint for unused vars in React components
- Updated next.config.mjs in playground-web
- Updated pnpm-workspace.yaml
- Added eslint and styled components in wallets package.json
- Updated dependencies in wallet-ui package.json

> The following files were skipped due to too many changes: `apps/playground-web/src/components/blockchain-api/write-contract-extension.tsx`, `legacy_packages/react/src/wallet/ConnectWallet/NetworkSelector.tsx`, `apps/playground-web/package.json`, `legacy_packages/react/package.json`, `apps/playground-web/src/components/blockchain-api/write-contract-raw.tsx`, `package.json`, `apps/dashboard/package.json`, `pnpm-lock.yaml`

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

<!-- end pr-codex -->
2024-06-30 00:06:16 +00:00
gregfromstlandgregfromstl 80b9cd967c chore(tests): update tests to use sendAndConfirmTransaction method (#3548)
This pull request updates the function names and constants used in the deploy-modular-core.test.ts file. Specific changes include:

- Replacing `ADDRESS_ZERO` with `ZERO_ADDRESS` to align with existing codebase conventions.
- Changing `sendTransaction` to `sendAndConfirmTransaction` to include transaction confirmation within the test cases.

### TL;DR

Updated function names and constants in the deploy-modular-core.test.ts for better alignment with the codebase.

### What changed?

- Replaced `ADDRESS_ZERO` with `ZERO_ADDRESS`.
- Replaced `sendTransaction` with `sendAndConfirmTransaction`.

### How to test?

Run the updated tests in deploy-modular-core.test.ts to ensure all changes work as expected.

### Why make this change?

These changes improve the code readability and follow naming conventions already established in the codebase. By including transaction confirmation, the tests are more robust and reliable.

---
2024-06-28 20:49:55 -07:00
Jonas DanielsandGitHub cddd0ca302 Version Packages (#3530) 2024-06-28 19:57:12 -07:00
Jonas Daniels 8bfba81d2e Create poor-dragons-eat.md
Signed-off-by: Jonas Daniels <[email protected]>
2024-06-28 19:28:46 -07:00
Jonas Daniels 9250ac5b44 Update packages/thirdweb/src/chains/chain-definitions/linea-sepolia.ts
Signed-off-by: Jonas Daniels <[email protected]>
2024-06-28 19:28:46 -07:00
maciekzygmuntandJonas Daniels 5f7e9545ce add exports 2024-06-28 19:28:46 -07:00
Maciej ZygmuntandJonas Daniels 439976b7a6 add linea chain configs 2024-06-28 19:28:46 -07:00
jnsdls b6ab038802 Update Dependencies (#3551)
<!-- start pr-codex -->

## PR-Codex overview
This PR updates various dependencies across different packages to their latest versions.

### Detailed summary
- Updated `webpack` to `5.92.1`
- Updated `@types/node` to `20.14.9`
- Updated `@microsoft/api-documenter` to `^7.25.4`
- Updated `abitype` to `1.0.5`
- Updated `@babel/preset-react` to `^7.24.7`
- Updated `eslint-config-turbo` to `2.0.6`
- Updated `@typescript-eslint/eslint-plugin` to `7.14.1`
- Updated `viem` to `2.16.4`
- Updated various other dependencies across packages

> The following files were skipped due to too many changes: `apps/dashboard/package.json`, `packages/thirdweb/package.json`, `pnpm-lock.yaml`

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

<!-- end pr-codex -->
2024-06-29 02:14:34 +00:00
gregfromstl 31775dc1dc feature(ts): unpin files from ipfs (#3552)
<!-- start pr-codex -->

## PR-Codex overview
This PR adds a new `unpin` function to `thirdweb` package for unpinning files from IPFS.

### Detailed summary
- Added `unpin` function to unpin files from IPFS in `thirdweb` package
- Defined `UnpinOptions` type for specifying client and CID
- Implemented unpin logic with error handling and authorization check

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

<!-- end pr-codex -->
2024-06-29 01:34:02 +00:00
jnsdls 32d1838d6a [Chore] Update Foundry version to nightly-c4a984fbf2c48b793c8cd53af84f56009dd1070c in CI workflow (#3553) 2024-06-29 01:13:24 +00:00
jnsdls 049a91a52a [Chore] Bump turbo from 2.0.5 to 2.0.6 (#3550) 2024-06-29 00:01:38 +00:00
gregfromstl 31d8b830f2 chore(wallet-ui): initialize project (#3477)
<!-- start pr-codex -->

## PR-Codex overview
This PR focuses on adding Thirdweb Wallet UI to the project, configuring Next.js, Tailwind CSS, and PostCSS, setting up Biome, and defining TypeScript settings.

### Detailed summary
- Added Thirdweb Wallet UI
- Configured Next.js, Tailwind CSS, and PostCSS
- Set up Biome configuration
- Defined TypeScript settings for Wallet UI
- Added global CSS styles for the app
- Updated dependencies and scripts in package.json

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

<!-- end pr-codex -->
2024-06-28 23:42:02 +00:00
MananTank be9118a04f [dashboard] Add copy button for chain id (#3538)
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to add a `CopyTextButton` component with copy functionality and icon positioning to enable copying text in various components.

### Detailed summary
- Added `CopyTextButton` component for copying text with icon positioning
- Implemented `CopyTextButton` in multiple files for copying chain IDs and addresses
- Updated components to include the new `CopyTextButton` for better user experience

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

<!-- end pr-codex -->
2024-06-28 23:24:24 +00:00
jnsdls 3ffad1a5a6 [Fix] Update import paths in engine-explorer and _app.tsx for better modularity (#3547)
### TL;DR

Corrected stylesheet imports for `swagger-ui.css` in the Engine Explorer component and added the Toaster component import in the _app.tsx.

### What changed?

- Added missing `swagger-ui.css` import in `engine-explorer.tsx`
- Removed duplicate `swagger-ui.css` import from `_app.tsx`
- Ensured Toaster component import in `_app.tsx`

### How to test?

- Verify UI for the Engine Explorer relies on the correct styles
- Ensure the Toaster component renders correctly without issues

### Why make this change?

To ensure the correct CSS styles are applied and to improve the maintainability of the import statements.

---

<!-- start pr-codex -->

---

## PR-Codex overview
This PR adds `swagger-ui.css` to `engine-explorer.tsx` and removes it from `_app.tsx`.

### Detailed summary
- Added `swagger-ui.css` import to `engine-explorer.tsx`
- Removed `swagger-ui.css` import from `_app.tsx`

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

<!-- end pr-codex -->
2024-06-28 23:06:04 +00:00
jnsdls 37d9373cf2 [Feature] Update dependencies and add new form and toaster components (#3546)
### TL;DR

This PR introduces new form components and integrates Sonner for toast notifications, along with various enhancements and fixes.

### What changed?

- Added new form components (`Form`, `FormField`, `FormLabel`, etc.) to the `ui` directory.
- Integrated `sonner` for toast notifications, adding a `Toaster` component.
- Migrated `pay.tsx` to the App Router and refactored its structure.
- Updated `DashboardHeader` and `DashboardLayout` for consistent spacing and padding.
- Refactored existing API key components and updated styles for better alignment and responsiveness.
- Fixed layout issues in `PayConfig` and other related components.

### How to test?

1. Navigate to the Dashboard and ensure the form components are rendering correctly.
2. Interact with forms and verify validation and error messages display as expected.
3. Trigger actions that would show toast notifications and ensure they are styled and positioned correctly.
4. Check the `PayConfig` and API key management sections for any UI regressions or inconsistencies.

### Why make this change?

- To enhance the user experience with improved form components and toast notifications.
- To maintain consistency in layout and design across the Dashboard.
- To address layout and spacing issues reported in the Pay section and other related components.

---

<!-- start pr-codex -->

---

## PR-Codex overview
This PR updates the layout, components, and dependencies in the dashboard app.

### Detailed summary
- Updated layout styles in `layout.tsx` and `DashboardHeader.tsx`
- Added `Toaster` component in `layout.tsx`
- Updated `sonner` package to version `1.5.0`
- Refactored components in `ConnectWalletPrompt.tsx` and `NoApiKeys.tsx`
- Implemented a new `Toaster` component in `sonner.tsx`
- Added new components and refactored UI in `Menu.tsx` and `ApiKeys/NoApiKeys.tsx`
- Updated page structure in `connect/pay.tsx`

> The following files were skipped due to too many changes: `apps/dashboard/src/@/components/ui/form.tsx`, `apps/dashboard/src/components/pay/PayConfig.tsx`

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

<!-- end pr-codex -->
2024-06-28 23:06:02 +00:00
gregfromstl 27daf22010 fix(ts): prepare incoming walletconnect transactions (#3541)
Adding thirdwebClient to createWalletConnectClient and fulfillRequest functions to ensure proper transaction execution through WalletConnect. This update includes a refactor of handleSendTransactionRequest to utilize the new client and various other related changes for consistency.

---

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on fixing in-app wallet transaction execution via WalletConnect by introducing `thirdwebClient` and updating related functions.

### Detailed summary
- Introduced `thirdwebClient` to handle WalletConnect transactions
- Updated functions to include `thirdwebClient` parameter
- Added tests using `TEST_CLIENT` for `thirdwebClient` integration

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

<!-- end pr-codex -->
2024-06-28 22:46:53 +00:00
gregfromstl 7e242602e9 fix(wallet): handle errors when connecting with open access ecosystem (#3545)
<!-- start pr-codex -->

## PR-Codex overview
This PR focuses on fixing errors related to connecting with an open access ecosystem by updating permissions logic in the `in-app-account.ts` file.

### Detailed summary
- Updated permissions logic to include partnerId check for ecosystem connectivity.

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

<!-- end pr-codex -->
2024-06-28 22:18:35 +00:00
gregfromstl 85f2f6d2bd fix(ts): properly disconnect wallet connect (#3539)
<!-- start pr-codex -->

## PR-Codex overview
This PR focuses on fixing WalletConnect client disconnections and improving error handling.

### Detailed summary
- Added a delay in testing for WalletConnect client disconnections
- Updated the `onDisconnect` function in `WalletConnectReceiverScreen.tsx` to handle loading state and query invalidation
- Improved error handling in `wallet-connect/receiver/index.ts` by catching errors during disconnect
- Added a function to remove sessions in `disconnectWalletConnectSession`
- Updated `disconnectWalletConnectSession` to handle errors gracefully

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

<!-- end pr-codex -->
2024-06-28 21:50:37 +00:00
gregfromstl 6704fa8870 fix(mint): add ability to override transaction properties in mintTo functions (#3543)
This pull request introduces a minor update to the thirdweb library, specifically adding the feature to override transaction properties in the `mintTo` functions for ERC1155, ERC20, and ERC721 tokens. Additionally, it refines the ENS avatar resolution tests by removing an offchain record test that relies on a secret key, improving overall test reliability.

---
2024-06-28 21:02:33 +00:00
jnsdls d2c1038845 [Feature] Add new Dashboard sidebar components and ecosystem wallets link (#3531)
<!-- start pr-codex -->

## PR-Codex overview
This PR updates the dashboard layout and styling, adds Ecosystem Wallet features, and refactors navigation components.

### Detailed summary
- Added "Ecosystem Wallets" section to dashboard sidebar
- Updated button styles in UI components
- Implemented Ecosystem Wallet page with alerts and buttons
- Refactored navigation components for better usability

> The following files were skipped due to too many changes: `apps/dashboard/src/app/(dashboard)/dashboard/components/sidebar/sidebar.client.tsx`

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

<!-- end pr-codex -->
2024-06-28 20:20:14 +00:00
gregfromstl 517ecff0b2 fix(sepolia): rename Sepolia native currency symbol to ETH (#3542) 2024-06-28 20:15:10 +00:00
gregfromstl cf2d1b8df3 feat(utils): add shortenHex function to utils for shortening hexadecimal strings (#3534) 2024-06-28 00:35:21 +00:00
gregfromstl e4b6391cb3 fix(transaction): export StoredTransaction type from transaction-store.js (#3533)
### TL;DR

This pull request modifies the `transaction-store.ts` module by exporting the type `StoredTransaction`, making it available for external use.

### What changed?

- The type `StoredTransaction` was exported from `transaction-store.ts`
- Updated the export statement for `StoredTransaction` in `transaction.ts`

### How to test?

1. Ensure that the module `transaction-store.ts` exports the type `StoredTransaction`.
2. Verify that importing `StoredTransaction` from the module works correctly in another file.

### Why make this change?

This change was made to facilitate the external utilization of the `StoredTransaction` type.

---

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to add a `StoredTransaction` type to the `thirdweb` package.

### Detailed summary
- Added `StoredTransaction` type to `transaction-store.ts`
- Exported `StoredTransaction` type in `transaction.ts`

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

<!-- end pr-codex -->
2024-06-28 00:29:52 +00:00
arcoraven 07ec487320 fix: bigint crash on tooltip (#3532)
## Problem solved

Fix error: "Do not know how to serialize bigint" by casting bigint to number when used as a string.

<!-- start pr-codex -->

---

## PR-Codex overview
This PR updates the README file to provide instructions for starting a local dev server and modifies a query key in a TypeScript file for improved functionality.

### Detailed summary
- Updated README.md to include instructions for starting a local dev server
- Modified query key in contract-subscriptions-table.tsx for better functionality

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

<!-- end pr-codex -->
2024-06-27 22:29:12 +00:00
gregfromstl 18c3d3be9f fix(react): remove problematic console errors (#3529)
These console.error logs don't represent an actual error state, and trigger error monitoring services for users
2024-06-27 19:06:27 +00:00
3053 changed files with 173382 additions and 17674 deletions
+2
View File
@@ -19,6 +19,8 @@
"runtimes-node-module",
"playground-web",
"thirdweb-dashboard",
"wallet-ui",
"portal",
"@thirdweb-dev/auth",
"@thirdweb-dev/chains",
"@thirdweb-dev/cli",
+37 -34
View File
@@ -1,53 +1,56 @@
# Order is important; the last matching pattern takes the most precedence.
# Platform team owns everything by default
# default ownership group
- @jnsdls @joaquim-verges @MananTank @gregfromstl
# legacy packages
legacy_packages/auth/ @jnsdls
legacy_packages/chains/ @jnsdls
legacy_packages/cli/ @jnsdls
legacy_packages/contracts-js/ @jnsdls
legacy_packages/crypto/ @jnsdls
legacy_packages/generated-abis/ @jnsdls
legacy_packages/merkletree/ @jnsdls
legacy_packages/pay/ @jnsdls
legacy_packages/payments/ @jnsdls
legacy_packages/react/ @MananTank @jnsdls
legacy_packages/react-core/ @MananTank @jnsdls
legacy_packages/react-native/ @jnsdls
legacy_packages/react-native-compat/ @jnsdls
legacy_packages/auth/ @jnsdls @joaquim-verges
legacy_packages/chains/ @jnsdls @joaquim-verges
legacy_packages/cli/ @jnsdls @joaquim-verges
legacy_packages/contracts-js/ @jnsdls @joaquim-verges
legacy_packages/crypto/ @jnsdls @joaquim-verges
legacy_packages/generated-abis/ @jnsdls @joaquim-verges
legacy_packages/merkletree/ @jnsdls @joaquim-verges
legacy_packages/pay/ @jnsdls @joaquim-verges
legacy_packages/payments/ @jnsdls @joaquim-verges
legacy_packages/react/ @MananTank @jnsdls @joaquim-verges
legacy_packages/react-core/ @MananTank @jnsdls @joaquim-verges
legacy_packages/react-native/ @jnsdls @joaquim-verges
legacy_packages/react-native-compat/ @jnsdls @joaquim-verges
legacy_packages/sdk/ @joaquim-verges @jnsdls
legacy_packages/storage/ @jnsdls
legacy_packages/wallets/ @MananTank @jnsdls
legacy_packages/storage/ @jnsdls @joaquim-verges
legacy_packages/wallets/ @MananTank @jnsdls @joaquim-verges
# legacy e2e
legacy_e2e/ @jnsdls
# packages
packages/thirdweb/ @joaquim-verges @gregfromstl @jnsdls
## specific thirdweb pieces
packages/thirdweb/src/react/ @joaquim-verges @gregfromstl @MananTank @jnsdls
packages/thirdweb/src/reactive/ @joaquim-verges @gregfromstl @MananTank @jnsdls
packages/thirdweb/src/gas/ @joaquim-verges @jnsdls
packages/thirdweb/src/pay/ @joaquim-verges @gregfromstl @MananTank @jnsdls
packages/typedoc-gen/ @MananTank @jnsdls @joaquim-verges
packages/service-utils/ @arcoraven @jnsdls @joaquim-verges
packages/eslint-config-thirdweb/ @jnsdls @joaquim-verges
packages/tw-tsconfig/ @jnsdls @joaquim-verges
packages/unity-js-bridge/ @joaquim-verges @0xFirekeeper @jnsdls
packages/thirdweb/src/react/ @MananTank
packages/thirdweb/src/reactive/ @MananTank
packages/thirdweb/src/gas/ @joaquim-verges
packages/thirdweb/src/pay/ @MananTank @IDubuque
packages/typedoc-gen/ @MananTank
# owned by phil for now
packages/service-utils/ @arcoraven
packages/eslint-config-thirdweb/ @jnsdls
packages/tw-tsconfig/ @jnsdls
packages/unity-js-bridge/ @joaquim-verges @0xFirekeeper
# apps
apps/ @jnsdls @joaquim-verges
apps/dashboard/ @jnsdls @MananTank @joaquim-verges
apps/playground-web/ @joaquim-verges @gregfromstl @jnsdls @joaquim-verges
apps/wallet-ui/ @gregfromstl @jnsdls @joaquim-verges @MananTank
apps/portal/ @gregfromstl @jnsdls @joaquim-verges @MananTank
# .github folder + .changeset + turbo config is owned by jonas for now
scripts/ @jnsdls @joaquim-verges
.github/ @jnsdls @joaquim-verges
.changeset/config.json @jnsdls @joaquim-verges
turbo.json @jnsdls @joaquim-verges
.vscode/ @jnsdls @joaquim-verges
scripts/ @jnsdls
.github/ @jnsdls
.changeset/config.json @jnsdls
turbo.json @jnsdls
+15
View File
@@ -77,6 +77,21 @@ Many of the tests use forked versions of live chains like mainnet. We fork these
If you need to use accounts in your tests, use the predefined accounts in `test/src/test-wallets.ts`. These are the default anvil accounts that are pre-funded on the local test forks.
##### Mocking Network Calls
If your test depends on a downstream network call, you must mock the call using `msw`. You can use one of the existing mocks in `test/src/mocks` or create your own. Once you've created a mock request, setup the server and add all your mocks like so:
```ts
import { setupServer } from "msw/node";
import { downloadMock, uploadMock } from "../../../test/src/mocks/storage.js";
const server = setupServer(uploadMock("HASH"), downloadMock({ name: "Test NFT" }));
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
```
#### Linting
We use a linter to maintain best practices across projects. Once your changes are complete (or periodically while making changes), run the linter with the following command from the repo root:
+3
View File
@@ -11,3 +11,6 @@ legacy_packages:
packages:
- changed-files:
- any-glob-to-any-file: "packages/**/*"
portal:
- changed-files:
- any-glob-to-any-file: "apps/portal/**/*"
-15
View File
@@ -2,18 +2,3 @@
Short description of the bug fixed or feature added
## Changes made
- [ ] Public API changes: list the public API changes made if any
- [ ] Internal API changes: explain the internal logic changes
## How to test
- [ ] Automated tests: link to unit test file
- [ ] Manual tests: step by step instructions on how to test
## Contributor NFT
Paste in your wallet address below and we will airdrop you a special NFT when your pull request is merged.
```Address: ```
+2 -1
View File
@@ -65,6 +65,7 @@ jobs:
uses: foundry-rs/foundry-toolchain@v1
with:
cache: false
version: nightly-c4a984fbf2c48b793c8cd53af84f56009dd1070c
- run: pnpm test
@@ -162,7 +163,7 @@ jobs:
cache: false
- name: Run benchmarks
uses: CodSpeedHQ/action@v2
uses: CodSpeedHQ/action@v3
with:
token: ${{ secrets.CODSPEED_TOKEN }}
run: "pnpm bench"
+2 -2
View File
@@ -14,7 +14,7 @@ public/dist
.idea/
.yalc/
yalc.lock
build/
./build/
playwright-report/
.env/
@@ -25,4 +25,4 @@ legacy_packages/cli/artifacts/
codecov
# Remove sitemap files (generated at build time)
sitemap*.xml
sitemap*.xml
+9 -5
View File
@@ -82,8 +82,12 @@ NEXT_TELEMETRY_DISABLED=1
NEXT_PUBLIC_TRENCH_2_API_ENDPOINT=""
# Unthread variables - only required for submitting the support form in /support
NEXT_PUBLIC_UNTHREAD_TRIAGE_CHANNEL_ID=""
NEXT_PUBLIC_UNTHREAD_EMAIL_INBOX_ID=""
NEXT_PUBLIC_UNTHREAD_FREE_TIER_ID=""
NEXT_PUBLIC_UNTHREAD_GROWTH_TIER_ID=""
NEXT_PUBLIC_UNTHREAD_PRO_TIER_ID=""
UNTHREAD_API_KEY=""
UNTHREAD_TRIAGE_CHANNEL_ID=""
UNTHREAD_EMAIL_INBOX_ID=""
UNTHREAD_FREE_TIER_ID=""
UNTHREAD_GROWTH_TIER_ID=""
UNTHREAD_PRO_TIER_ID=""
# Demo Engine
NEXT_PUBLIC_DEMO_ENGINE_URL=""
+4 -11
View File
@@ -2,20 +2,13 @@
This repo contains the full source for all of thirdweb.com and the thirdweb dashboard.
## Building
## Starting a local dev server
### Install dependencies
We use `pnpm`.
Run from the root folder (thirdweb-dev/js):
```sh
pnpm install
```
### Starting local dev server.
```sh
pnpm dev
cd <path/to/thirdweb-dev/js>
pnpm dashboard
```
### Building for production
+32 -24
View File
@@ -25,29 +25,32 @@
"@chakra-ui/styled-system": "^2.9.2",
"@chakra-ui/theme-tools": "^2.1.2",
"@coinbase/onchainkit": "^0.14.2",
"@emotion/react": "^11.11.4",
"@emotion/react": "11.11.4",
"@emotion/styled": "11.11.5",
"@hookform/resolvers": "^3.6.0",
"@n8tb1t/use-scroll-position": "^2.0.3",
"@radix-ui/react-alert-dialog": "^1.1.1",
"@radix-ui/react-aspect-ratio": "^1.0.3",
"@radix-ui/react-checkbox": "^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-label": "^2.1.0",
"@radix-ui/react-popover": "^1.1.0",
"@radix-ui/react-popover": "^1.1.1",
"@radix-ui/react-radio-group": "^1.2.0",
"@radix-ui/react-select": "^2.0.0",
"@radix-ui/react-select": "^2.1.1",
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-toast": "^1.2.1",
"@radix-ui/react-tooltip": "^1.1.0",
"@radix-ui/react-toggle": "^1.1.0",
"@radix-ui/react-toggle-group": "^1.1.0",
"@radix-ui/react-tooltip": "1.1.2",
"@react-icons/all-files": "^4.1.0",
"@sentry/nextjs": "^8.8.0",
"@stripe/react-stripe-js": "^2.7.1",
"@stripe/react-stripe-js": "^2.7.2",
"@stripe/stripe-js": "^3.5.0",
"@tanstack/query-async-storage-persister": "^4.36.1",
"@tanstack/react-query": "^4.36.1",
"@tanstack/react-query-persist-client": "^4.36.1",
"@tanstack/react-table": "^8.17.3",
"@thirdweb-dev/chains": "workspace:*",
"@thirdweb-dev/react": "workspace:*",
"@thirdweb-dev/react-core": "workspace:*",
"@thirdweb-dev/sdk": "workspace:*",
@@ -55,7 +58,7 @@
"@thirdweb-dev/storage": "workspace:*",
"@thirdweb-dev/wallets": "workspace:*",
"@vercel/og": "^0.6.2",
"abitype": "1.0.4",
"abitype": "1.0.5",
"chakra-react-select": "^4.7.6",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
@@ -64,12 +67,14 @@
"date-fns": "^3.6.0",
"ethers": "^5.7.2",
"flat": "^6.0.1",
"framer-motion": "^11.2.11",
"fuse.js": "^7.0.0",
"framer-motion": "^11.2.12",
"fuse.js": "7.0.0",
"idb-keyval": "^6.2.1",
"ioredis": "^5.4.1",
"ipaddr.js": "^2.2.0",
"lottie-react": "^2.4.0",
"lucide-react": "^0.395.0",
"next": "14.2.4",
"lucide-react": "^0.399.0",
"next": "14.2.5",
"next-plausible": "^3.12.0",
"next-seo": "^6.5.0",
"next-themes": "^0.3.0",
@@ -84,6 +89,7 @@
"qrcode": "^1.5.3",
"react": "18.3.1",
"react-children-utilities": "^2.10.0",
"react-confetti": "^6.1.0",
"react-day-picker": "^8.10.1",
"react-dom": "18.3.1",
"react-dropzone": "^14.2.3",
@@ -98,15 +104,17 @@
"recharts": "^2.12.7",
"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.3.0",
"tailwind-merge": "^2.4.0",
"tailwindcss-animate": "^1.0.7",
"thirdweb": "workspace:*",
"tiny-invariant": "^1.3.3",
"use-debounce": "^10.0.1",
"vaul": "^0.9.1",
"zksync-ethers": "5.9.0",
"zod": "^3.23.8"
"zod": "3.23.8"
},
"devDependencies": {
"@chakra-ui/cli": "^2.4.1",
@@ -114,7 +122,7 @@
"@next/eslint-plugin-next": "^14.2.4",
"@playwright/test": "^1.44.1",
"@types/color": "^3.0.6",
"@types/node": "^20.14.6",
"@types/node": "20.14.9",
"@types/papaparse": "^5.3.14",
"@types/pluralize": "^0.0.33",
"@types/qrcode": "^1.5.5",
@@ -123,26 +131,26 @@
"@types/react-table": "^7.7.20",
"@types/spdx-correct": "^3.1.3",
"@types/swagger-ui-react": "^4.18.3",
"@typescript-eslint/eslint-plugin": "^7.13.1",
"@typescript-eslint/parser": "^7.14.1",
"@typescript-eslint/eslint-plugin": "7.14.1",
"@typescript-eslint/parser": "7.14.1",
"autoprefixer": "^10.4.19",
"checkly": "^4.6.3",
"checkly": "^4.7.0",
"dotenv": "^16.4.5",
"eslint": "^8.57.0",
"eslint": "8.57.0",
"eslint-config-biome": "^1.7.3",
"eslint-config-prettier": "^9.1.0",
"eslint-config-prettier": "9.1.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-inclusive-language": "^2.2.1",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-promise": "^6.2.0",
"eslint-plugin-react": "^7.34.3",
"eslint-plugin-react": "7.34.3",
"eslint-plugin-react-compiler": "0.0.0-experimental-51a85ea-20240601",
"eslint-plugin-react-hooks": "^4.6.2",
"knip": "^5.22.0",
"knip": "^5.23.1",
"next-sitemap": "^4.2.3",
"next-unused": "^0.0.6",
"tailwindcss": "^3.4.4",
"typescript": "5.5.2"
"typescript": "5.5.4"
},
"next-unused": {
"alias": {},
@@ -0,0 +1,17 @@
<svg width="1073" height="504" viewBox="0 0 1073 504" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0_48_35063" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="0" width="1351" height="840">
<path d="M1350.46 0H0V840H1350.46V0Z" fill="white"/>
</mask>
<g mask="url(#mask0_48_35063)">
<path d="M4.77995 70.7069L4.77697 70.6996C-9.16164 36.4867 16.1683 1 51.6663 1H279.112C300.663 1 318.394 13.6646 325.999 32.6791L506.922 484.987L506.929 485.004L506.937 485.022C511.986 496.381 512.002 510.315 506.922 523.013L393.199 807.321L393.197 807.328L393.194 807.335C376.734 850.383 315.901 850.456 298.132 807.318C298.131 807.316 298.13 807.314 298.129 807.312L4.77995 70.7069ZM842.195 70.7069L842.192 70.6996C828.253 36.4867 853.583 1 889.081 1H1116.53C1138.08 1 1155.81 13.6646 1163.41 32.6791L1344.34 484.987L1344.34 485.004L1344.35 485.022C1349.4 496.381 1349.42 510.315 1344.34 523.013L1230.61 807.321L1230.61 807.328L1230.61 807.335C1214.15 850.382 1153.32 850.456 1135.55 807.32C1135.55 807.317 1135.55 807.314 1135.54 807.312L842.195 70.7069ZM444.192 69.4575C444.191 69.4542 444.19 69.451 444.189 69.4477C432.783 36.4753 456.887 1 492.355 1H691.37C712.903 1 731.93 14.9382 739.544 33.9578C739.546 33.9623 739.548 33.9669 739.549 33.9714L904.945 486.224C904.946 486.228 904.948 486.233 904.949 486.238C908.751 497.653 908.752 509.053 904.95 520.469C904.948 520.474 904.946 520.479 904.945 520.484L805.448 791.836C788.971 836.198 725.585 836.198 709.108 791.836L444.192 69.4575Z" stroke="url(#paint0_linear_48_35063)" stroke-width="2"/>
</g>
<defs>
<linearGradient id="paint0_linear_48_35063" x1="-91.767" y1="269.743" x2="811.065" y2="1296.62" gradientUnits="userSpaceOnUse">
<stop stop-color="#F213A4"/>
<stop offset="0.1517" stop-color="#E011A7"/>
<stop offset="0.4554" stop-color="#B20DAF"/>
<stop offset="0.8789" stop-color="#6806BB"/>
<stop offset="1" stop-color="#5204BF"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

+12
View File
@@ -270,6 +270,18 @@ function redirects() {
destination: "/in-app-wallets",
permanent: false,
},
{
source: "/dashboard/connect/ecosystem/:slug((?!create$)[^/]+)",
destination: "/dashboard/connect/ecosystem/:slug/permissions",
permanent: false,
},
// temporarily redirect cli login to support page
{
source: "/cli/login",
destination:
"https://support.thirdweb.com/troubleshooting-errors/7Y1BqKNvtLdBv5fZkRZZB3/issue-linking-device-on-the-authorization-page-via-thirdweb-cli/cn9LRA3ax7XCP6uxwRYdvx",
permanent: false,
},
];
}
@@ -0,0 +1,142 @@
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import Link from "next/link";
import {
SiDiscord,
SiGithub,
SiInstagram,
SiLinkedin,
SiReddit,
SiTiktok,
SiX,
SiYoutube,
} from "react-icons/si";
import { ThirdwebMiniLogo } from "../../../app/components/ThirdwebMiniLogo";
type AppFooterProps = {
className?: string;
};
export function AppFooter(props: AppFooterProps) {
return (
<footer
className={cn(
"bg-background border-t border-border py-6 md:py-8 w-full",
props.className,
)}
>
<div className="container flex flex-col gap-4 md:gap-6">
{/* top row */}
<div className="flex flex-col md:flex-row gap-4 md:justify-between md:items-center">
<div className="flex flex-row gap-3 items-center">
<ThirdwebMiniLogo className="h-7" />
<p className="text-sm text-secondary-foreground">© 2024 thirdweb</p>
</div>
<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="text-secondary-foreground size-5" />
</Link>
</Button>
<Button size="icon" variant="ghost" asChild className="size-9">
<Link href="https://www.tiktok.com/@thirdweb" target="_blank">
<SiTiktok className="text-secondary-foreground size-5" />
</Link>
</Button>
<Button size="icon" variant="ghost" asChild className="size-9">
<Link href="https://www.instagram.com/thirdweb/" target="_blank">
<SiInstagram className="text-secondary-foreground size-5" />
</Link>
</Button>
<Button size="icon" variant="ghost" asChild className="size-9">
<Link
href="hhttps://www.linkedin.com/company/third-web/"
target="_blank"
>
<SiLinkedin className="text-secondary-foreground size-5" />
</Link>
</Button>
<Button size="icon" variant="ghost" asChild className="size-9">
<Link href="https://www.youtube.com/@thirdweb_" target="_blank">
<SiYoutube className="text-secondary-foreground size-5" />
</Link>
</Button>
<Button size="icon" variant="ghost" asChild className="size-9">
<Link href="https://discord.gg/thirdweb" target="_blank">
<SiDiscord className="text-secondary-foreground size-5" />
</Link>
</Button>
<Button size="icon" variant="ghost" asChild className="size-9">
<Link href="https://www.reddit.com/r/thirdweb/" target="_blank">
<SiReddit className="text-secondary-foreground size-5" />
</Link>
</Button>
<Button size="icon" variant="ghost" asChild className="size-9">
<Link href="https://x.com/thirdweb" target="_blank">
<SiX className="text-secondary-foreground size-5" />
</Link>
</Button>
</div>
</div>
{/* bottom row */}
<div className="grid grid-rows-5 grid-cols-2 grid-flow-col gap-2 md:flex md:flex-row md:justify-between">
<Link
className="py-[6px] px-[10px] text-secondary-foreground text-sm hover:underline"
href="/"
>
Home
</Link>
<Link
className="py-[6px] px-[10px] text-secondary-foreground text-sm hover:underline"
href="https://blog.thirdweb.com"
target="_blank"
>
Blog
</Link>
<Link
className="py-[6px] px-[10px] text-secondary-foreground text-sm hover:underline"
href="https://portal.thirdweb.com/changelog"
target="_blank"
>
Changelog
</Link>
<Link
className="py-[6px] px-[10px] text-secondary-foreground text-sm hover:underline"
href="https://feedback.thirdweb.com/"
target="_blank"
>
Feedback
</Link>
<Link
className="py-[6px] px-[10px] text-secondary-foreground text-sm hover:underline"
href="https://thirdweb.com/privacy"
target="_blank"
>
Privacy Policy
</Link>
<Link
className="py-[6px] px-[10px] text-secondary-foreground text-sm hover:underline"
href="https://thirdweb.com/tos"
target="_blank"
>
Terms of Service
</Link>
<Link
className="py-[6px] px-[10px] text-secondary-foreground text-sm hover:underline"
href="https://thirdweb.com/gas"
target="_blank"
>
Gas Estimator
</Link>
<Link
className="py-[6px] px-[10px] text-secondary-foreground text-sm hover:underline"
href="https://thirdweb.com/chainlist"
target="_blank"
>
Chain List
</Link>
</div>
</div>
</footer>
);
}
@@ -11,21 +11,21 @@ export function ColorModeToggle() {
const { setTheme, theme } = useTheme();
return (
<Button
variant="ghost"
size="icon"
onClick={() => {
setTheme(theme === "dark" ? "light" : "dark");
}}
aria-label="Toggle theme"
>
<ClientOnly ssr={<Skeleton className="size-6 bg-accent border" />}>
<ClientOnly ssr={<Skeleton className="size-10 bg-accent border" />}>
<Button
variant="ghost"
size="icon"
onClick={() => {
setTheme(theme === "dark" ? "light" : "dark");
}}
aria-label="Toggle theme"
>
{theme === "light" ? (
<Sun strokeWidth={1} className="size-6" />
) : (
<Moon strokeWidth={1} className="size-6" />
)}
</ClientOnly>
</Button>
</Button>
</ClientOnly>
);
}
@@ -1,9 +1,18 @@
"use client";
import { ThemeProvider as NextThemesProvider } from "next-themes";
import { ThemeProvider as NextThemesProvider, useTheme } from "next-themes";
import type { ThemeProviderProps } from "next-themes/dist/types";
import * as React from "react";
import { useEffect } from "react";
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
return <NextThemesProvider {...props}>{children}</NextThemesProvider>;
}
export function useForceDarkTheme() {
const { setTheme } = useTheme();
// eslint-disable-next-line no-restricted-syntax
useEffect(() => {
setTheme("dark");
}, [setTheme]);
}
@@ -0,0 +1,64 @@
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog";
import type { buttonVariants } from "@/components/ui/button";
import type { VariantProps } from "class-variance-authority";
import type React from "react";
import { cn } from "../../lib/utils";
export interface ConfirmationDialogProps
extends VariantProps<typeof buttonVariants> {
title?: React.ReactNode;
description?: React.ReactNode;
onSubmit?: () => void;
open?: boolean;
onOpenChange?: (open: boolean) => void;
children?: React.ReactNode;
className?: string;
}
export function ConfirmationDialog({
title,
description,
onSubmit,
open,
onOpenChange,
children,
variant = "primary",
className,
}: ConfirmationDialogProps) {
return (
<AlertDialog open={open} onOpenChange={onOpenChange}>
<AlertDialogTrigger asChild>{children}</AlertDialogTrigger>
<AlertDialogContent className={cn("w-[90vw] sm:w-auto", className)}>
<AlertDialogHeader className="w-full sm:w-auto">
<AlertDialogTitle>{title}</AlertDialogTitle>
<AlertDialogDescription>{description}</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter className="w-full sm:w-auto">
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction
variant={variant}
type="submit"
onClick={() => {
onSubmit?.();
onOpenChange?.(false);
}}
>
Continue
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
}
@@ -1,10 +1,7 @@
"use client";
import { CheckIcon, CopyIcon } from "lucide-react";
import { useState } from "react";
import { cn } from "../../lib/utils";
import { Button } from "./button";
import { ToolTipLabel } from "./tooltip";
import { CopyTextButton } from "./CopyTextButton";
export function CopyAddressButton(props: {
address: string;
@@ -17,36 +14,18 @@ export function CopyAddressButton(props: {
| "outline"
| "secondary"
| "ghost";
copyIconPosition: "left" | "right";
}) {
const [isCopied, setIsCopied] = useState(false);
const shortenedAddress = `${props.address.slice(0, 6)}...${props.address.slice(0, 4)}`;
return (
<ToolTipLabel label="Copy address">
<Button
variant={props.variant || "outline"}
aria-label="Copy"
className={cn(
"h-auto w-auto px-2.5 py-1.5 flex gap-2 text-xs rounded-lg font-mono text-foreground",
props.className,
)}
onClick={() => {
navigator.clipboard.writeText(props.address);
setIsCopied(true);
setTimeout(() => setIsCopied(false), 1000);
}}
>
{isCopied ? (
<CheckIcon
className={cn("size-3 text-green-500", props.iconClassName)}
/>
) : (
<CopyIcon
className={cn("size-3 text-muted-foreground", props.iconClassName)}
/>
)}
{shortenedAddress}
</Button>
</ToolTipLabel>
<CopyTextButton
textToCopy={props.address}
textToShow={shortenedAddress}
tooltip="Copy Address"
className={cn("font-mono text-sm", props.className)}
variant={props.variant}
copyIconPosition={props.copyIconPosition}
/>
);
}
@@ -0,0 +1,62 @@
"use client";
import { CheckIcon, CopyIcon } from "lucide-react";
import { useState } from "react";
import { cn } from "../../lib/utils";
import { Button } from "./button";
import { ToolTipLabel } from "./tooltip";
export function CopyTextButton(props: {
textToShow: string;
textToCopy: string;
tooltip: string;
className?: string;
iconClassName?: string;
variant?:
| "primary"
| "default"
| "destructive"
| "outline"
| "secondary"
| "ghost";
copyIconPosition: "left" | "right";
}) {
const [isCopied, setIsCopied] = useState(false);
const copyButton = isCopied ? (
<CheckIcon className={cn("size-3 text-green-500", props.iconClassName)} />
) : (
<CopyIcon
className={cn("size-3 text-muted-foreground", props.iconClassName)}
/>
);
return (
<ToolTipLabel label={props.tooltip}>
<Button
variant={props.variant || "outline"}
aria-label={props.tooltip}
className={cn(
"h-auto w-auto px-2.5 py-1.5 flex gap-2 rounded-lg text-foreground font-normal",
props.className,
)}
onClick={() => {
navigator.clipboard.writeText(props.textToCopy);
setIsCopied(true);
setTimeout(() => setIsCopied(false), 1000);
}}
>
{props.copyIconPosition === "right" ? (
<>
{props.textToShow}
{copyButton}
</>
) : (
<>
{copyButton}
{props.textToShow}
</>
)}
</Button>
</ToolTipLabel>
);
}
@@ -69,7 +69,7 @@ export function DatePickerWithRange(props: {
<DynamicHeight>
<div>
{!isValid && (
<p className="text-sm pt-2 justify-center text-destructive-foreground text-center flex items-center gap-2">
<p className="text-sm pt-2 justify-center text-destructive-text text-center flex items-center gap-2">
<CalendarX2Icon className="h-4 w-4" />
Invalid date range
</p>
@@ -113,9 +113,9 @@ export function DatePickerWithRange(props: {
}
}}
classNames={{
day_range_start: "!bg-inverted",
day_range_start: "!bg-inverted !text-inverted-foreground",
day_range_end:
"!bg-inverted/20 !text-inverted pointer-events-none",
"!bg-inverted/50 !text-inverted-foreground pointer-events-none",
}}
/>
)}
@@ -135,9 +135,9 @@ export function DatePickerWithRange(props: {
}
}}
classNames={{
day_range_end: "!bg-inverted",
day_range_end: "!bg-inverted !text-inverted-foreground",
day_range_start:
"!bg-inverted/20 !text-inverted pointer-events-none",
"!bg-inverted/50 !text-inverted-foreground pointer-events-none",
}}
/>
)}
@@ -0,0 +1,146 @@
"use client";
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
import * as React from "react";
import { buttonVariants } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import type { VariantProps } from "class-variance-authority";
const AlertDialog = AlertDialogPrimitive.Root;
const AlertDialogTrigger = AlertDialogPrimitive.Trigger;
const AlertDialogPortal = AlertDialogPrimitive.Portal;
const AlertDialogOverlay = React.forwardRef<
React.ElementRef<typeof AlertDialogPrimitive.Overlay>,
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>
>(({ className, ...props }, ref) => (
<AlertDialogPrimitive.Overlay
className={cn(
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
className,
)}
{...props}
ref={ref}
/>
));
AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;
const AlertDialogContent = React.forwardRef<
React.ElementRef<typeof AlertDialogPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>
>(({ className, ...props }, ref) => (
<AlertDialogPortal>
<AlertDialogOverlay />
<AlertDialogPrimitive.Content
ref={ref}
className={cn(
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] rounded-lg",
className,
)}
{...props}
/>
</AlertDialogPortal>
));
AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;
const AlertDialogHeader = ({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col space-y-2 text-center sm:text-left",
className,
)}
{...props}
/>
);
AlertDialogHeader.displayName = "AlertDialogHeader";
const AlertDialogFooter = ({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
className,
)}
{...props}
/>
);
AlertDialogFooter.displayName = "AlertDialogFooter";
const AlertDialogTitle = React.forwardRef<
React.ElementRef<typeof AlertDialogPrimitive.Title>,
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>
>(({ className, ...props }, ref) => (
<AlertDialogPrimitive.Title
ref={ref}
className={cn("text-lg hyphens-auto font-semibold", className)}
{...props}
/>
));
AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;
const AlertDialogDescription = React.forwardRef<
React.ElementRef<typeof AlertDialogPrimitive.Description>,
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>
>(({ className, ...props }, ref) => (
<AlertDialogPrimitive.Description
ref={ref}
className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
));
AlertDialogDescription.displayName =
AlertDialogPrimitive.Description.displayName;
interface AlertDialogActionProps
extends React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>,
VariantProps<typeof buttonVariants> {}
const AlertDialogAction = React.forwardRef<
React.ElementRef<typeof AlertDialogPrimitive.Action>,
AlertDialogActionProps
>((props: AlertDialogActionProps, ref) => (
<AlertDialogPrimitive.Action
ref={ref}
className={cn(buttonVariants({ variant: props.variant }), props.className)}
{...props}
/>
));
AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;
const AlertDialogCancel = React.forwardRef<
React.ElementRef<typeof AlertDialogPrimitive.Cancel>,
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>
>(({ className, ...props }, ref) => (
<AlertDialogPrimitive.Cancel
ref={ref}
className={cn(
buttonVariants({ variant: "outline" }),
"mt-2 sm:mt-0",
className,
)}
{...props}
/>
));
AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;
export {
AlertDialog,
AlertDialogPortal,
AlertDialogOverlay,
AlertDialogTrigger,
AlertDialogContent,
AlertDialogHeader,
AlertDialogFooter,
AlertDialogTitle,
AlertDialogDescription,
AlertDialogAction,
AlertDialogCancel,
};
@@ -0,0 +1,65 @@
import { type VariantProps, cva } from "class-variance-authority";
import * as React from "react";
import { cn } from "@/lib/utils";
const alertVariants = cva(
"relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground",
{
variants: {
variant: {
default: "bg-background text-foreground",
destructive:
"bg-destructive/10 border-destructive/50 dark:border-destructive [&>svg]:text-destructive",
info: "bg-primary/10 border-primary/50 dark:border-primary [&>svg]:text-primary",
warning:
"bg-warning/10 border-warning/50 dark:border-warning [&>svg]:text-warning",
},
},
defaultVariants: {
variant: "default",
},
},
);
const Alert = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>
>(({ className, variant, ...props }, ref) => (
<div
ref={ref}
role="alert"
className={cn(alertVariants({ variant }), className)}
{...props}
/>
));
Alert.displayName = "Alert";
const AlertTitle = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLHeadingElement>
>(({ className, ...props }, ref) => (
<h5
ref={ref}
className={cn("mb-1.5 font-medium leading-none tracking-tight", className)}
{...props}
/>
));
AlertTitle.displayName = "AlertTitle";
const AlertDescription = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLParagraphElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn(
"text-sm [&_p]:leading-relaxed text-secondary-foreground",
className,
)}
{...props}
/>
));
AlertDescription.displayName = "AlertDescription";
export { Alert, AlertTitle, AlertDescription };
+2 -2
View File
@@ -4,14 +4,14 @@ import type * as React from "react";
import { cn } from "@/lib/utils";
const badgeVariants = cva(
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 leading-4",
"inline-flex items-center rounded-full border border-border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 leading-4",
{
variants: {
variant: {
default:
"border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
secondary:
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
"border-transparent bg-accent text-accent-foreground hover:bg-accent/80",
destructive:
"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
warning: "border-transparent bg-warning text-warning-foreground",
@@ -10,15 +10,15 @@ const buttonVariants = cva(
variants: {
variant: {
primary:
"bg-primary text-primary-foreground hover:bg-primary/90 text-semibold",
"bg-primary hover:bg-primary/90 text-semibold text-primary-foreground ",
default: "bg-foreground text-background hover:bg-foreground/90",
destructive:
"bg-destructive text-destructive-foreground hover:bg-destructive/90 text-semibold",
"bg-destructive hover:bg-destructive/90 text-semibold text-destructive-foreground ",
outline:
"border border-input bg-transaprent hover:bg-accent hover:text-accent-foreground text-semibold",
secondary:
"bg-secondary text-secondary-foreground hover:bg-secondary/80 text-semibold",
ghost: "hover:bg-accent hover:text-accent-foreground text-semibold",
"bg-secondary hover:bg-secondary/80 text-semibold text-secondary-foreground ",
ghost: "hover:bg-accent text-semibold hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline text-semibold",
},
size: {
@@ -0,0 +1,368 @@
"use client";
import * as React from "react";
import * as RechartsPrimitive from "recharts";
import { cn } from "@/lib/utils";
// Format: { THEME_NAME: CSS_SELECTOR }
const THEMES = { light: "", dark: ".dark" } as const;
export type ChartConfig = {
[k in string]: {
label?: React.ReactNode;
icon?: React.ComponentType;
} & (
| { color?: string; theme?: never }
| { color?: never; theme: Record<keyof typeof THEMES, string> }
);
};
type ChartContextProps = {
config: ChartConfig;
};
const ChartContext = React.createContext<ChartContextProps | null>(null);
function useChart() {
const context = React.useContext(ChartContext);
if (!context) {
throw new Error("useChart must be used within a <ChartContainer />");
}
return context;
}
const ChartContainer = React.forwardRef<
HTMLDivElement,
React.ComponentProps<"div"> & {
config: ChartConfig;
children: React.ComponentProps<
typeof RechartsPrimitive.ResponsiveContainer
>["children"];
}
>(({ id, className, children, config, ...props }, ref) => {
const uniqueId = React.useId();
const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`;
return (
<ChartContext.Provider value={{ config }}>
<div
data-chart={chartId}
ref={ref}
className={cn(
"flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-none [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none",
className,
)}
{...props}
>
<ChartStyle id={chartId} config={config} />
<RechartsPrimitive.ResponsiveContainer>
{children}
</RechartsPrimitive.ResponsiveContainer>
</div>
</ChartContext.Provider>
);
});
ChartContainer.displayName = "Chart";
const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
const colorConfig = Object.entries(config).filter(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
([_, config]) => config.theme || config.color,
);
if (!colorConfig.length) {
return null;
}
return (
<style
// biome-ignore lint/security/noDangerouslySetInnerHtml: <explanation>
dangerouslySetInnerHTML={{
__html: Object.entries(THEMES)
.map(
([theme, prefix]) => `
${prefix} [data-chart=${id}] {
${colorConfig
.map(([key, itemConfig]) => {
const color =
itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||
itemConfig.color;
return color ? ` --color-${key}: ${color};` : null;
})
.join("\n")}
}
`,
)
.join("\n"),
}}
/>
);
};
const ChartTooltip = RechartsPrimitive.Tooltip;
const ChartTooltipContent = React.forwardRef<
HTMLDivElement,
React.ComponentProps<typeof RechartsPrimitive.Tooltip> &
React.ComponentProps<"div"> & {
hideLabel?: boolean;
hideIndicator?: boolean;
indicator?: "line" | "dot" | "dashed";
nameKey?: string;
labelKey?: string;
}
>(
(
{
active,
payload,
className,
indicator = "dot",
hideLabel = false,
hideIndicator = false,
label,
labelFormatter,
labelClassName,
formatter,
color,
nameKey,
labelKey,
},
ref,
) => {
const { config } = useChart();
const tooltipLabel = React.useMemo(() => {
if (hideLabel || !payload?.length) {
return null;
}
const [item] = payload;
const key = `${labelKey || item.dataKey || item.name || "value"}`;
const itemConfig = getPayloadConfigFromPayload(config, item, key);
const value =
!labelKey && typeof label === "string"
? config[label as keyof typeof config]?.label || label
: itemConfig?.label;
if (labelFormatter) {
return (
<div className={cn("font-medium", labelClassName)}>
{labelFormatter(value, payload)}
</div>
);
}
if (!value) {
return null;
}
return <div className={cn("font-medium", labelClassName)}>{value}</div>;
}, [
label,
labelFormatter,
payload,
hideLabel,
labelClassName,
config,
labelKey,
]);
if (!active || !payload?.length) {
return null;
}
const nestLabel = payload.length === 1 && indicator !== "dot";
return (
<div
ref={ref}
className={cn(
"grid min-w-[8rem] items-start gap-1.5 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl",
className,
)}
>
{!nestLabel ? tooltipLabel : null}
<div className="grid gap-1.5">
{payload.map((item, index) => {
const key = `${nameKey || item.name || item.dataKey || "value"}`;
const itemConfig = getPayloadConfigFromPayload(config, item, key);
const indicatorColor = color || item.payload.fill || item.color;
return (
<div
key={item.dataKey}
className={cn(
"flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground",
indicator === "dot" && "items-center",
)}
>
{formatter && item?.value !== undefined && item.name ? (
formatter(item.value, item.name, item, index, item.payload)
) : (
<>
{/* Icon */}
{itemConfig?.icon ? (
<itemConfig.icon />
) : (
!hideIndicator && (
<div
className={cn(
"shrink-0 rounded-[2px] border-[--color-border] bg-[--color-bg]",
{
"h-2.5 w-2.5": indicator === "dot",
"w-1": indicator === "line",
"w-0 border-[1.5px] border-dashed bg-transparent":
indicator === "dashed",
"my-0.5": nestLabel && indicator === "dashed",
},
)}
style={
{
"--color-bg": indicatorColor,
"--color-border": indicatorColor,
} as React.CSSProperties
}
/>
)
)}
<div
className={cn(
"flex flex-1 gap-2 justify-between leading-none",
nestLabel ? "items-end" : "items-center",
)}
>
<div className="grid gap-1.5">
{nestLabel ? tooltipLabel : null}
<span className="text-muted-foreground">
{itemConfig?.label || item.name}
</span>
</div>
{item.value && (
<span className="font-mono font-medium tabular-nums text-foreground">
{item.value}
</span>
)}
</div>
</>
)}
</div>
);
})}
</div>
</div>
);
},
);
ChartTooltipContent.displayName = "ChartTooltip";
const ChartLegend = RechartsPrimitive.Legend;
const ChartLegendContent = React.forwardRef<
HTMLDivElement,
React.ComponentProps<"div"> &
Pick<RechartsPrimitive.LegendProps, "payload" | "verticalAlign"> & {
hideIcon?: boolean;
nameKey?: string;
}
>(
(
{ className, hideIcon = false, payload, verticalAlign = "bottom", nameKey },
ref,
) => {
const { config } = useChart();
if (!payload?.length) {
return null;
}
return (
<div
ref={ref}
className={cn(
"flex items-center justify-center gap-4",
verticalAlign === "top" ? "pb-3" : "pt-3",
className,
)}
>
{payload.map((item) => {
const key = `${nameKey || item.dataKey || "value"}`;
const itemConfig = getPayloadConfigFromPayload(config, item, key);
return (
<div
key={item.value}
className={cn(
"flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground",
)}
>
{itemConfig?.icon && !hideIcon ? (
<itemConfig.icon />
) : (
<div
className="h-2 w-2 shrink-0 rounded-[2px]"
style={{
backgroundColor: item.color,
}}
/>
)}
{itemConfig?.label}
</div>
);
})}
</div>
);
},
);
ChartLegendContent.displayName = "ChartLegend";
// Helper to extract item config from a payload.
function getPayloadConfigFromPayload(
config: ChartConfig,
payload: unknown,
key: string,
) {
if (typeof payload !== "object" || payload === null) {
return undefined;
}
const payloadPayload =
"payload" in payload &&
typeof payload.payload === "object" &&
payload.payload !== null
? payload.payload
: undefined;
let configLabelKey: string = key;
if (
key in payload &&
typeof payload[key as keyof typeof payload] === "string"
) {
configLabelKey = payload[key as keyof typeof payload] as string;
} else if (
payloadPayload &&
key in payloadPayload &&
typeof payloadPayload[key as keyof typeof payloadPayload] === "string"
) {
configLabelKey = payloadPayload[
key as keyof typeof payloadPayload
] as string;
}
return configLabelKey in config
? config[configLabelKey]
: config[key as keyof typeof config];
}
export {
ChartContainer,
ChartTooltip,
ChartTooltipContent,
ChartLegend,
ChartLegendContent,
ChartStyle,
};
@@ -28,3 +28,19 @@ const Checkbox = React.forwardRef<
Checkbox.displayName = CheckboxPrimitive.Root.displayName;
export { Checkbox };
export function CheckboxWithLabel(props: {
children: React.ReactNode;
className?: string;
}) {
return (
<label
className={cn(
"flex gap-2 items-center text-secondary-foreground text-sm cursor-pointer select-none",
props.className,
)}
>
{props.children}
</label>
);
}
@@ -0,0 +1,137 @@
"use client";
import * as DialogPrimitive from "@radix-ui/react-dialog";
import { X } from "lucide-react";
import * as React from "react";
import { cn } from "@/lib/utils";
const Dialog = DialogPrimitive.Root;
const DialogTrigger = DialogPrimitive.Trigger;
const DialogPortal = DialogPrimitive.Portal;
const DialogClose = DialogPrimitive.Close;
const DialogOverlay = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Overlay>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
>(({ className, ...props }, ref) => (
<DialogPrimitive.Overlay
ref={ref}
className={cn(
"fixed inset-0 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
className,
)}
{...props}
/>
));
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
const DialogContent = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> & {
dialogOverlayClassName?: string;
dialogCloseClassName?: string;
}
>(({ className, children, ...props }, ref) => (
<DialogPortal>
<DialogOverlay className={props.dialogOverlayClassName} />
<DialogPrimitive.Content
ref={ref}
className={cn(
"fixed grid w-full max-w-lg gap-4 border bg-background p-6 shadow-lg duration-300 rounded-lg border-border",
// on mobile - put the dialog at the bottom of the screen, animate - slide up and fade in
"bottom-0 left-0 right-0",
"data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
// on desktop - vertically and horizontally center the dialog, animate - zoom and fade in
"md:bottom-auto md:left-[50%] md:top-[50%] md:translate-x-[-50%] md:translate-y-[-50%] ",
"md:data-[state=closed]:zoom-out-95 md:data-[state=open]:zoom-in-95 ",
"md:data-[state=closed]:slide-out-to-left-1/2 md:data-[state=closed]:slide-out-to-top-[48%] ",
"md:data-[state=open]:slide-in-from-left-1/2 md:data-[state=open]:slide-in-from-top-[48%] ",
"data-[state=open]:animate-in data-[state=closed]:animate-out",
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
className,
)}
{...props}
>
{children}
<DialogPrimitive.Close
className={cn(
"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground",
props.dialogCloseClassName,
)}
>
<X className="h-4 w-4" />
<span className="sr-only">Close</span>
</DialogPrimitive.Close>
</DialogPrimitive.Content>
</DialogPortal>
));
DialogContent.displayName = DialogPrimitive.Content.displayName;
const DialogHeader = ({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn("flex flex-col space-y-1.5 text-left", className)}
{...props}
/>
);
DialogHeader.displayName = "DialogHeader";
const DialogFooter = ({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
className,
)}
{...props}
/>
);
DialogFooter.displayName = "DialogFooter";
const DialogTitle = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Title>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
>(({ className, ...props }, ref) => (
<DialogPrimitive.Title
ref={ref}
className={cn(
"text-lg font-semibold leading-none tracking-tight",
className,
)}
{...props}
/>
));
DialogTitle.displayName = DialogPrimitive.Title.displayName;
const DialogDescription = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Description>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
>(({ className, ...props }, ref) => (
<DialogPrimitive.Description
ref={ref}
className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
));
DialogDescription.displayName = DialogPrimitive.Description.displayName;
export {
Dialog,
DialogPortal,
DialogOverlay,
DialogClose,
DialogTrigger,
DialogContent,
DialogHeader,
DialogFooter,
DialogTitle,
DialogDescription,
};
@@ -0,0 +1,118 @@
"use client";
import * as React from "react";
import { Drawer as DrawerPrimitive } from "vaul";
import { cn } from "@/lib/utils";
const Drawer = ({
shouldScaleBackground = true,
...props
}: React.ComponentProps<typeof DrawerPrimitive.Root>) => (
<DrawerPrimitive.Root
shouldScaleBackground={shouldScaleBackground}
{...props}
/>
);
Drawer.displayName = "Drawer";
const DrawerTrigger = DrawerPrimitive.Trigger;
const DrawerPortal = DrawerPrimitive.Portal;
const DrawerClose = DrawerPrimitive.Close;
const DrawerOverlay = React.forwardRef<
React.ElementRef<typeof DrawerPrimitive.Overlay>,
React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Overlay>
>(({ className, ...props }, ref) => (
<DrawerPrimitive.Overlay
ref={ref}
className={cn("fixed inset-0 z-50 bg-black/80", className)}
{...props}
/>
));
DrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName;
const DrawerContent = React.forwardRef<
React.ElementRef<typeof DrawerPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Content>
>(({ className, children, ...props }, ref) => (
<DrawerPortal>
<DrawerOverlay />
<DrawerPrimitive.Content
ref={ref}
className={cn(
"fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border bg-background",
className,
)}
{...props}
>
<div className="mx-auto mt-4 h-2 w-[100px] rounded-full bg-muted" />
{children}
</DrawerPrimitive.Content>
</DrawerPortal>
));
DrawerContent.displayName = "DrawerContent";
const DrawerHeader = ({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn("grid gap-1.5 p-4 text-center sm:text-left", className)}
{...props}
/>
);
DrawerHeader.displayName = "DrawerHeader";
const DrawerFooter = ({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn("mt-auto flex flex-col gap-2 p-4", className)}
{...props}
/>
);
DrawerFooter.displayName = "DrawerFooter";
const DrawerTitle = React.forwardRef<
React.ElementRef<typeof DrawerPrimitive.Title>,
React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Title>
>(({ className, ...props }, ref) => (
<DrawerPrimitive.Title
ref={ref}
className={cn(
"text-lg font-semibold leading-none tracking-tight",
className,
)}
{...props}
/>
));
DrawerTitle.displayName = DrawerPrimitive.Title.displayName;
const DrawerDescription = React.forwardRef<
React.ElementRef<typeof DrawerPrimitive.Description>,
React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Description>
>(({ className, ...props }, ref) => (
<DrawerPrimitive.Description
ref={ref}
className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
));
DrawerDescription.displayName = DrawerPrimitive.Description.displayName;
export {
Drawer,
DrawerPortal,
DrawerOverlay,
DrawerTrigger,
DrawerClose,
DrawerContent,
DrawerHeader,
DrawerFooter,
DrawerTitle,
DrawerDescription,
};
@@ -0,0 +1,200 @@
"use client";
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
import { Check, ChevronRight, Circle } from "lucide-react";
import * as React from "react";
import { cn } from "@/lib/utils";
const DropdownMenu = DropdownMenuPrimitive.Root;
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
const DropdownMenuGroup = DropdownMenuPrimitive.Group;
const DropdownMenuPortal = DropdownMenuPrimitive.Portal;
const DropdownMenuSub = DropdownMenuPrimitive.Sub;
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
const DropdownMenuSubTrigger = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
inset?: boolean;
}
>(({ className, inset, children, ...props }, ref) => (
<DropdownMenuPrimitive.SubTrigger
ref={ref}
className={cn(
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent",
inset && "pl-8",
className,
)}
{...props}
>
{children}
<ChevronRight className="ml-auto h-4 w-4" />
</DropdownMenuPrimitive.SubTrigger>
));
DropdownMenuSubTrigger.displayName =
DropdownMenuPrimitive.SubTrigger.displayName;
const DropdownMenuSubContent = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
>(({ className, ...props }, ref) => (
<DropdownMenuPrimitive.SubContent
ref={ref}
className={cn(
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className,
)}
{...props}
/>
));
DropdownMenuSubContent.displayName =
DropdownMenuPrimitive.SubContent.displayName;
const DropdownMenuContent = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
>(({ className, sideOffset = 4, ...props }, ref) => (
<DropdownMenuPrimitive.Portal>
<DropdownMenuPrimitive.Content
ref={ref}
sideOffset={sideOffset}
className={cn(
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className,
)}
{...props}
/>
</DropdownMenuPrimitive.Portal>
));
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
const DropdownMenuItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
inset?: boolean;
}
>(({ className, inset, ...props }, ref) => (
<DropdownMenuPrimitive.Item
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
inset && "pl-8",
className,
)}
{...props}
/>
));
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
const DropdownMenuCheckboxItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
>(({ className, children, checked, ...props }, ref) => (
<DropdownMenuPrimitive.CheckboxItem
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className,
)}
checked={checked}
{...props}
>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<DropdownMenuPrimitive.ItemIndicator>
<Check className="h-4 w-4" />
</DropdownMenuPrimitive.ItemIndicator>
</span>
{children}
</DropdownMenuPrimitive.CheckboxItem>
));
DropdownMenuCheckboxItem.displayName =
DropdownMenuPrimitive.CheckboxItem.displayName;
const DropdownMenuRadioItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
>(({ className, children, ...props }, ref) => (
<DropdownMenuPrimitive.RadioItem
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className,
)}
{...props}
>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<DropdownMenuPrimitive.ItemIndicator>
<Circle className="h-2 w-2 fill-current" />
</DropdownMenuPrimitive.ItemIndicator>
</span>
{children}
</DropdownMenuPrimitive.RadioItem>
));
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
const DropdownMenuLabel = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Label>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
inset?: boolean;
}
>(({ className, inset, ...props }, ref) => (
<DropdownMenuPrimitive.Label
ref={ref}
className={cn(
"px-2 py-1.5 text-sm font-semibold",
inset && "pl-8",
className,
)}
{...props}
/>
));
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
const DropdownMenuSeparator = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
>(({ className, ...props }, ref) => (
<DropdownMenuPrimitive.Separator
ref={ref}
className={cn("-mx-1 my-1 h-px bg-muted", className)}
{...props}
/>
));
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
const DropdownMenuShortcut = ({
className,
...props
}: React.HTMLAttributes<HTMLSpanElement>) => {
return (
<span
className={cn("ml-auto text-xs tracking-widest opacity-60", className)}
{...props}
/>
);
};
DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
export {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuCheckboxItem,
DropdownMenuRadioItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuGroup,
DropdownMenuPortal,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuRadioGroup,
};
+203
View File
@@ -0,0 +1,203 @@
import type * as LabelPrimitive from "@radix-ui/react-label";
import { Slot } from "@radix-ui/react-slot";
import * as React from "react";
import {
Controller,
type ControllerProps,
type FieldPath,
type FieldValues,
FormProvider,
useFormContext,
} from "react-hook-form";
import { Label } from "@/components/ui/label";
import { cn } from "@/lib/utils";
import { ToolTipLabel } from "./tooltip";
const Form = FormProvider;
type FormFieldContextValue<
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
> = {
name: TName;
};
const FormFieldContext = React.createContext<FormFieldContextValue>(
{} as FormFieldContextValue,
);
const FormField = <
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
>({
...props
}: ControllerProps<TFieldValues, TName>) => {
return (
<FormFieldContext.Provider value={{ name: props.name }}>
<Controller {...props} />
</FormFieldContext.Provider>
);
};
const useFormField = () => {
const fieldContext = React.useContext(FormFieldContext);
const itemContext = React.useContext(FormItemContext);
const { getFieldState, formState } = useFormContext();
const fieldState = getFieldState(fieldContext.name, formState);
if (!fieldContext) {
throw new Error("useFormField should be used within <FormField>");
}
const { id } = itemContext;
return {
id,
name: fieldContext.name,
formItemId: `${id}-form-item`,
formDescriptionId: `${id}-form-item-description`,
formMessageId: `${id}-form-item-message`,
...fieldState,
};
};
type FormItemContextValue = {
id: string;
};
const FormItemContext = React.createContext<FormItemContextValue>(
{} as FormItemContextValue,
);
const FormItem = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => {
const id = React.useId();
return (
<FormItemContext.Provider value={{ id }}>
<div ref={ref} className={cn("space-y-2", className)} {...props} />
</FormItemContext.Provider>
);
});
FormItem.displayName = "FormItem";
const FormLabel = React.forwardRef<
React.ElementRef<typeof LabelPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>
>(({ className, ...props }, ref) => {
const { error, formItemId } = useFormField();
return (
<Label
ref={ref}
className={cn(error && "text-destructive-text", className)}
htmlFor={formItemId}
{...props}
/>
);
});
FormLabel.displayName = "FormLabel";
const RequiredFormLabel = React.forwardRef<
React.ElementRef<typeof LabelPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>
>(({ className, ...props }, ref) => {
const { error, formItemId } = useFormField();
return (
<ToolTipLabel label="Required">
<Label
ref={ref}
className={cn(error && "text-destructive-text", "relative", className)}
htmlFor={formItemId}
{...props}
>
{props.children}
<span className="absolute -top-1.5 -right-2 text-destructive-text">
•
</span>
</Label>
</ToolTipLabel>
);
});
FormLabel.displayName = "FormLabel";
const FormControl = React.forwardRef<
React.ElementRef<typeof Slot>,
React.ComponentPropsWithoutRef<typeof Slot>
>(({ ...props }, ref) => {
const { error, formItemId, formDescriptionId, formMessageId } =
useFormField();
return (
<Slot
ref={ref}
id={formItemId}
aria-describedby={
!error
? `${formDescriptionId}`
: `${formDescriptionId} ${formMessageId}`
}
aria-invalid={!!error}
{...props}
/>
);
});
FormControl.displayName = "FormControl";
const FormDescription = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLParagraphElement>
>(({ className, ...props }, ref) => {
const { formDescriptionId } = useFormField();
return (
<p
ref={ref}
id={formDescriptionId}
className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
);
});
FormDescription.displayName = "FormDescription";
const FormMessage = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLParagraphElement>
>(({ className, children, ...props }, ref) => {
const { error, formMessageId } = useFormField();
const body = error ? String(error?.message) : children;
if (!body) {
return null;
}
return (
<p
ref={ref}
id={formMessageId}
className={cn("text-sm font-medium text-destructive-text", className)}
{...props}
>
{body}
</p>
);
});
FormMessage.displayName = "FormMessage";
export {
useFormField,
Form,
FormItem,
FormLabel,
RequiredFormLabel,
FormControl,
FormDescription,
FormMessage,
FormField,
};
@@ -0,0 +1,63 @@
"use client";
import * as React from "react";
import { cn } from "@/lib/utils";
import { UploadIcon } from "lucide-react";
import Image from "next/image";
import { useDropzone } from "react-dropzone";
export interface ImageUploadProps
extends React.InputHTMLAttributes<HTMLInputElement> {
onUpload?: (files: File[]) => void;
}
const ImageUpload = React.forwardRef<HTMLInputElement, ImageUploadProps>(
({ className, onUpload, ...props }, ref) => {
const [activeFile, setActiveFile] = React.useState<File | null>(null);
const onDrop = React.useCallback(
(acceptedFiles: File[]) => {
setActiveFile(acceptedFiles[0]);
onUpload?.(acceptedFiles);
},
[onUpload],
);
const { getRootProps, getInputProps, isDragActive } = useDropzone({
onDrop,
});
return (
<div className="flex items-start">
<div
{...getRootProps()}
className={cn(
"border bg-card relative group cursor-pointer hover:border-primary flex-col gap-1.5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 overflow-hidden transition-all rounded-md flex items-center justify-center p-4 py-6 text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
isDragActive ? "border-primary" : "border-input",
!activeFile ? "w-full" : "min-h-32 min-w-32",
className,
)}
>
<input ref={ref} {...getInputProps()} {...props} />
{activeFile ? (
<Image
className="object-contain object-center "
src={URL.createObjectURL(activeFile)}
fill
alt=""
/>
) : (
<>
<UploadIcon className="w-5 h-5 transition-all group-hover:scale-110" />
<p className="text-xs text-center">
Drag and drop a file or click to upload
</p>
</>
)}
</div>
</div>
);
},
);
ImageUpload.displayName = "Input";
export { ImageUpload };
+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-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium 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 file:border-0 file:bg-transparent file:text-sm file:font-medium 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}
@@ -5,6 +5,7 @@ import { Circle } from "lucide-react";
import * as React from "react";
import { cn } from "@/lib/utils";
import { Label } from "./label";
const RadioGroup = React.forwardRef<
React.ElementRef<typeof RadioGroupPrimitive.Root>,
@@ -41,4 +42,34 @@ const RadioGroupItem = React.forwardRef<
});
RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName;
export { RadioGroup, RadioGroupItem };
// Displays the radio item as a button-like element
const RadioGroupItemButton = React.forwardRef<
React.ElementRef<typeof RadioGroupPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>
>(({ className, ...props }, ref) => {
return (
<RadioGroupPrimitive.Item
ref={ref}
className={cn(
"cursor-pointer group flex items-center px-3 peer-hover:border-nonce py-4 space-x-3 space-y-0 border-2 rounded-md min-w-32 font-medium hover:border-foreground/25 transition-all data-[state=checked]:border-primary 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,
)}
{...props}
>
<div className="flex items-center justify-center w-4 h-4 border-2 rounded-full transition-all group-data-[state=checked]:border-primary text-primary group-hover:border-foreground/25 aspect-square ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50">
{/* Show on checked */}
<RadioGroupPrimitive.Indicator className="flex items-center justify-center transition-all rounded-full">
<Circle className="w-2 h-2 text-current fill-current" />
</RadioGroupPrimitive.Indicator>
{/* Show on hover */}
<div className="items-center justify-center hidden transition-all rounded-full text-foreground/25 group-hover:flex group-data-[state=checked]:hidden">
<Circle className="w-2 h-2 text-current fill-current" />
</div>
</div>
<Label className="cursor-pointer">{props.children}</Label>
</RadioGroupPrimitive.Item>
);
});
RadioGroupItemButton.displayName = RadioGroupPrimitive.Item.displayName;
export { RadioGroup, RadioGroupItem, RadioGroupItemButton };
@@ -19,7 +19,7 @@ const SelectTrigger = React.forwardRef<
<SelectPrimitive.Trigger
ref={ref}
className={cn(
"flex gap-2 h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
"flex gap-2 h-10 w-full items-center justify-between rounded-md border border-input bg-card px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
className,
)}
{...props}
@@ -25,14 +25,14 @@ function SkeletonContainer<T>(props: {
style={props.style}
aria-hidden={isLoading ? "true" : "false"}
className={cn(
isLoading && "animate-pulse rounded-lg bg-muted",
isLoading && "animate-pulse rounded-lg bg-muted inline-block",
props.className,
)}
>
<div className={cn(isLoading && "invisible")}>
<div
className={cn(
"transitino-opacity duration-300",
"transition-opacity duration-300",
isLoading ? "opacity-0" : "opacity-100",
)}
>
@@ -0,0 +1,31 @@
"use client";
import { useTheme } from "next-themes";
import { Toaster as Sonner } from "sonner";
type ToasterProps = React.ComponentProps<typeof Sonner>;
const Toaster = ({ ...props }: ToasterProps) => {
const { theme = "system" } = useTheme();
return (
<Sonner
theme={theme as ToasterProps["theme"]}
className="toaster group"
toastOptions={{
classNames: {
toast:
"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg group-[.toaster]:border",
description: "group-[.toast]:text-muted-foreground",
actionButton:
"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
cancelButton:
"group-[.toast]:bg-muted group-[.toast]:text-muted-foreground",
},
}}
{...props}
/>
);
};
export { Toaster };
@@ -0,0 +1,117 @@
import * as React from "react";
import { cn } from "@/lib/utils";
const Table = React.forwardRef<
HTMLTableElement,
React.HTMLAttributes<HTMLTableElement>
>(({ className, ...props }, ref) => (
<div className="relative w-full overflow-auto">
<table
ref={ref}
className={cn("w-full caption-bottom text-sm", className)}
{...props}
/>
</div>
));
Table.displayName = "Table";
const TableHeader = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} />
));
TableHeader.displayName = "TableHeader";
const TableBody = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<tbody
ref={ref}
className={cn("[&_tr:last-child]:border-0", className)}
{...props}
/>
));
TableBody.displayName = "TableBody";
const TableFooter = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<tfoot
ref={ref}
className={cn(
"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
className,
)}
{...props}
/>
));
TableFooter.displayName = "TableFooter";
const TableRow = React.forwardRef<
HTMLTableRowElement,
React.HTMLAttributes<HTMLTableRowElement>
>(({ className, ...props }, ref) => (
<tr
ref={ref}
className={cn(
"border-b transition-colors data-[state=selected]:bg-muted",
className,
)}
{...props}
/>
));
TableRow.displayName = "TableRow";
const TableHead = React.forwardRef<
HTMLTableCellElement,
React.ThHTMLAttributes<HTMLTableCellElement>
>(({ className, ...props }, ref) => (
<th
ref={ref}
className={cn(
"h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",
className,
)}
{...props}
/>
));
TableHead.displayName = "TableHead";
const TableCell = React.forwardRef<
HTMLTableCellElement,
React.TdHTMLAttributes<HTMLTableCellElement>
>(({ className, ...props }, ref) => (
<td
ref={ref}
className={cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className)}
{...props}
/>
));
TableCell.displayName = "TableCell";
const TableCaption = React.forwardRef<
HTMLTableCaptionElement,
React.HTMLAttributes<HTMLTableCaptionElement>
>(({ className, ...props }, ref) => (
<caption
ref={ref}
className={cn("mt-4 text-sm text-muted-foreground", className)}
{...props}
/>
));
TableCaption.displayName = "TableCaption";
export {
Table,
TableHeader,
TableBody,
TableFooter,
TableHead,
TableRow,
TableCell,
TableCaption,
};
+21 -6
View File
@@ -5,7 +5,12 @@ import { ScrollShadow } from "./ScrollShadow/ScrollShadow";
import { Button } from "./button";
export function TabLinks(props: {
links: { name: string; href: string; isActive: boolean }[];
links: {
name: string;
href: string;
isActive: boolean;
isEnabled?: boolean;
}[];
}) {
const { containerRef, lineRef, activeTabRef } =
useUnderline<HTMLAnchorElement>();
@@ -16,14 +21,23 @@ export function TabLinks(props: {
<div className="flex" ref={containerRef}>
{props.links.map((tab) => {
return (
<Button asChild key={tab.name} variant="ghost">
<Button
asChild
key={tab.name}
disabled={!tab.isEnabled}
variant="ghost"
>
<Link
data-active={tab.isActive}
ref={tab.isActive ? activeTabRef : undefined}
href={tab.href}
aria-disabled={!tab.isEnabled}
className={cn(
"rounded-lg hover:bg-muted px-3 font-medium text-sm lg:text-base relative h-auto",
!tab.isActive && "opacity-50 hover:opacity-100",
!tab.isActive &&
tab.isEnabled &&
"opacity-50 hover:opacity-100",
!tab.isEnabled && "opacity-50 pointer-events-none",
)}
>
{tab.name}
@@ -36,7 +50,7 @@ export function TabLinks(props: {
{/* Active line */}
<div
ref={lineRef}
className="absolute left-0 bottom-0 z-10 h-[2px] bg-foreground rounded-lg fade-in-0 animate-in"
className="absolute left-0 bottom-0 h-[2px] bg-foreground rounded-lg fade-in-0 animate-in"
/>
</ScrollShadow>
{/* Bottom line */}
@@ -56,12 +70,13 @@ export function TabButtons(props: {
tabClassName?: string;
activeTabClassName?: string;
tabContainerClassName?: string;
containerClassName?: string;
}) {
const { containerRef, lineRef, activeTabRef } =
useUnderline<HTMLButtonElement>();
return (
<div className="relative">
<div className={cn("relative", props.containerClassName)}>
<ScrollShadow scrollableClassName="pb-[8px] relative">
<div
className={cn("flex", props.tabContainerClassName)}
@@ -93,7 +108,7 @@ export function TabButtons(props: {
{/* Active line */}
<div
ref={lineRef}
className="absolute left-0 bottom-0 z-10 h-[2px] bg-foreground rounded-lg fade-in-0 animate-in"
className="absolute left-0 bottom-0 h-[2px] bg-foreground rounded-lg fade-in-0 animate-in"
/>
</ScrollShadow>
{/* Bottom line */}
@@ -0,0 +1,24 @@
import * as React from "react";
import { cn } from "@/lib/utils";
export interface TextareaProps
extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}
const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
({ className, ...props }, ref) => {
return (
<textarea
className={cn(
"flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background 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}
{...props}
/>
);
},
);
Textarea.displayName = "Textarea";
export { Textarea };
@@ -1,129 +0,0 @@
"use client";
import * as ToastPrimitives from "@radix-ui/react-toast";
import { type VariantProps, cva } from "class-variance-authority";
import { X } from "lucide-react";
import * as React from "react";
import { cn } from "@/lib/utils";
const ToastProvider = ToastPrimitives.Provider;
const ToastViewport = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Viewport>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Viewport>
>(({ className, ...props }, ref) => (
<ToastPrimitives.Viewport
ref={ref}
className={cn(
"fixed top-0 z-[10000000] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px] gap-4",
className,
)}
{...props}
/>
));
ToastViewport.displayName = ToastPrimitives.Viewport.displayName;
const toastVariants = cva(
"group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full",
{
variants: {
variant: {
default: "border bg-background text-foreground",
destructive:
"destructive group border-destructive bg-destructive text-destructive-foreground",
},
},
defaultVariants: {
variant: "default",
},
},
);
const Toast = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Root>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> &
VariantProps<typeof toastVariants>
>(({ className, variant, ...props }, ref) => {
return (
<ToastPrimitives.Root
ref={ref}
className={cn(toastVariants({ variant }), className)}
{...props}
/>
);
});
Toast.displayName = ToastPrimitives.Root.displayName;
const ToastAction = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Action>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Action>
>(({ className, ...props }, ref) => (
<ToastPrimitives.Action
ref={ref}
className={cn(
"inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium ring-offset-background transition-colors hover:bg-secondary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive",
className,
)}
{...props}
/>
));
ToastAction.displayName = ToastPrimitives.Action.displayName;
const ToastClose = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Close>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Close>
>(({ className, ...props }, ref) => (
<ToastPrimitives.Close
ref={ref}
className={cn(
"absolute right-2 top-2 rounded-md p-1 text-foreground/50 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600",
className,
)}
toast-close=""
{...props}
>
<X className="h-4 w-4" />
</ToastPrimitives.Close>
));
ToastClose.displayName = ToastPrimitives.Close.displayName;
const ToastTitle = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Title>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title>
>(({ className, ...props }, ref) => (
<ToastPrimitives.Title
ref={ref}
className={cn("text-sm font-semibold", className)}
{...props}
/>
));
ToastTitle.displayName = ToastPrimitives.Title.displayName;
const ToastDescription = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Description>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Description>
>(({ className, ...props }, ref) => (
<ToastPrimitives.Description
ref={ref}
className={cn("text-sm opacity-90", className)}
{...props}
/>
));
ToastDescription.displayName = ToastPrimitives.Description.displayName;
type ToastProps = React.ComponentPropsWithoutRef<typeof Toast>;
type ToastActionElement = React.ReactElement<typeof ToastAction>;
export {
type ToastProps,
type ToastActionElement,
ToastProvider,
ToastViewport,
Toast,
ToastTitle,
ToastDescription,
ToastClose,
ToastAction,
};
@@ -1,31 +0,0 @@
"use client";
import {
Toast,
ToastClose,
ToastDescription,
ToastProvider,
ToastTitle,
ToastViewport,
} from "@/components/ui/toast";
import { useToast } from "@/components/ui/use-toast";
export function Toaster() {
const { toasts } = useToast();
return (
<ToastProvider>
{toasts.map(({ id, title, description, action, ...props }) => (
<Toast key={id} {...props}>
<div className="grid gap-1 z-50">
{title && <ToastTitle>{title}</ToastTitle>}
{description && <ToastDescription>{description}</ToastDescription>}
</div>
{action}
<ToastClose />
</Toast>
))}
<ToastViewport />
</ToastProvider>
);
}
@@ -0,0 +1,61 @@
"use client";
import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group";
import type { VariantProps } from "class-variance-authority";
import * as React from "react";
import { toggleVariants } from "@/components/ui/toggle";
import { cn } from "@/lib/utils";
const ToggleGroupContext = React.createContext<
VariantProps<typeof toggleVariants>
>({
size: "default",
variant: "default",
});
const ToggleGroup = React.forwardRef<
React.ElementRef<typeof ToggleGroupPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Root> &
VariantProps<typeof toggleVariants>
>(({ className, variant, size, children, ...props }, ref) => (
<ToggleGroupPrimitive.Root
ref={ref}
className={cn("flex items-center justify-center gap-1", className)}
{...props}
>
<ToggleGroupContext.Provider value={{ variant, size }}>
{children}
</ToggleGroupContext.Provider>
</ToggleGroupPrimitive.Root>
));
ToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName;
const ToggleGroupItem = React.forwardRef<
React.ElementRef<typeof ToggleGroupPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Item> &
VariantProps<typeof toggleVariants>
>(({ className, children, variant, size, ...props }, ref) => {
const context = React.useContext(ToggleGroupContext);
return (
<ToggleGroupPrimitive.Item
ref={ref}
className={cn(
toggleVariants({
variant: context.variant || variant,
size: context.size || size,
}),
className,
)}
{...props}
>
{children}
</ToggleGroupPrimitive.Item>
);
});
ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName;
export { ToggleGroup, ToggleGroupItem };
@@ -0,0 +1,45 @@
"use client";
import * as TogglePrimitive from "@radix-ui/react-toggle";
import { type VariantProps, cva } from "class-variance-authority";
import * as React from "react";
import { cn } from "@/lib/utils";
const toggleVariants = cva(
"inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground",
{
variants: {
variant: {
default: "bg-transparent",
outline:
"border border-input bg-transparent hover:bg-accent hover:text-accent-foreground",
},
size: {
default: "h-10 px-3",
sm: "h-9 px-2.5",
lg: "h-11 px-5",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
},
);
const Toggle = React.forwardRef<
React.ElementRef<typeof TogglePrimitive.Root>,
React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> &
VariantProps<typeof toggleVariants>
>(({ className, variant, size, ...props }, ref) => (
<TogglePrimitive.Root
ref={ref}
className={cn(toggleVariants({ variant, size, className }))}
{...props}
/>
));
Toggle.displayName = TogglePrimitive.Root.displayName;
export { Toggle, toggleVariants };
+13 -4
View File
@@ -19,7 +19,7 @@ const TooltipContent = React.forwardRef<
ref={ref}
sideOffset={sideOffset}
className={cn(
"z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
"z-50 overflow-hidden rounded-md border border-border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className,
)}
{...props}
@@ -31,15 +31,24 @@ export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
export function ToolTipLabel(props: {
children: React.ReactNode;
label: string;
label: string | undefined;
rightIcon?: React.ReactNode;
leftIcon?: React.ReactNode;
}) {
if (!props.label) {
return props.children;
}
return (
<TooltipProvider>
<Tooltip delayDuration={100} disableHoverableContent={true}>
<TooltipTrigger asChild>{props.children}</TooltipTrigger>
<TooltipContent sideOffset={10}>
<TooltipTrigger asChild className="!pointer-events-auto">
{props.children}
</TooltipTrigger>
<TooltipContent
sideOffset={10}
className="max-w-[300px] leading-relaxed"
>
<div className="p-2 text-sm flex items-center gap-1.5">
{props.leftIcon}
{props.label}
@@ -0,0 +1,24 @@
import { useTrack } from "hooks/analytics/useTrack";
import Link from "next/link";
import type React from "react";
export type TrackedLinkProps = React.ComponentProps<typeof Link> & {
category: string;
label?: string;
trackingProps?: Record<string, string>;
};
export function TrackedLinkTW(props: TrackedLinkProps) {
const trackEvent = useTrack();
const { category, label, trackingProps, ...restProps } = props;
return (
<Link
onClick={(e) => {
trackEvent({ category, action: "click", label, ...trackingProps });
props.onClick?.(e);
}}
{...restProps}
/>
);
}
@@ -1,192 +0,0 @@
/* eslint-disable no-restricted-syntax */
"use client";
import { useEffect, useState } from "react";
import type { ToastActionElement, ToastProps } from "@/components/ui/toast";
const TOAST_LIMIT = 5;
const TOAST_REMOVE_DELAY = 5000; // 5 seconds
type ToasterToast = ToastProps & {
id: string;
title?: React.ReactNode;
description?: React.ReactNode;
action?: ToastActionElement;
};
const actionTypes = {
ADD_TOAST: "ADD_TOAST",
UPDATE_TOAST: "UPDATE_TOAST",
DISMISS_TOAST: "DISMISS_TOAST",
REMOVE_TOAST: "REMOVE_TOAST",
} as const;
let count = 0;
function genId() {
count = (count + 1) % Number.MAX_SAFE_INTEGER;
return count.toString();
}
type ActionType = typeof actionTypes;
type Action =
| {
type: ActionType["ADD_TOAST"];
toast: ToasterToast;
}
| {
type: ActionType["UPDATE_TOAST"];
toast: Partial<ToasterToast>;
}
| {
type: ActionType["DISMISS_TOAST"];
toastId?: ToasterToast["id"];
}
| {
type: ActionType["REMOVE_TOAST"];
toastId?: ToasterToast["id"];
};
interface State {
toasts: ToasterToast[];
}
const toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>();
const addToRemoveQueue = (toastId: string) => {
if (toastTimeouts.has(toastId)) {
return;
}
const timeout = setTimeout(() => {
toastTimeouts.delete(toastId);
dispatch({
type: "REMOVE_TOAST",
toastId: toastId,
});
}, TOAST_REMOVE_DELAY);
toastTimeouts.set(toastId, timeout);
};
export const reducer = (state: State, action: Action): State => {
switch (action.type) {
case "ADD_TOAST":
return {
...state,
toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
};
case "UPDATE_TOAST":
return {
...state,
toasts: state.toasts.map((t) =>
t.id === action.toast.id ? { ...t, ...action.toast } : t,
),
};
case "DISMISS_TOAST": {
const { toastId } = action;
// ! Side effects ! - This could be extracted into a dismissToast() action,
// but I'll keep it here for simplicity
if (toastId) {
addToRemoveQueue(toastId);
} else {
for (const toast of state.toasts) {
addToRemoveQueue(toast.id);
}
}
return {
...state,
toasts: state.toasts.map((t) =>
t.id === toastId || toastId === undefined
? {
...t,
open: false,
}
: t,
),
};
}
case "REMOVE_TOAST":
if (action.toastId === undefined) {
return {
...state,
toasts: [],
};
}
return {
...state,
toasts: state.toasts.filter((t) => t.id !== action.toastId),
};
}
};
const listeners: Array<(state: State) => void> = [];
let memoryState: State = { toasts: [] };
function dispatch(action: Action) {
memoryState = reducer(memoryState, action);
for (const listener of listeners) {
listener(memoryState);
}
}
type Toast = Omit<ToasterToast, "id">;
function toast({ ...props }: Toast) {
const id = genId();
const update = (props: ToasterToast) =>
dispatch({
type: "UPDATE_TOAST",
toast: { ...props, id },
});
const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id });
dispatch({
type: "ADD_TOAST",
toast: {
...props,
id,
open: true,
onOpenChange: (open: boolean) => {
if (!open) dismiss();
},
},
});
return {
id: id,
dismiss,
update,
};
}
function useToast() {
const [state, setState] = useState<State>(memoryState);
// listeners is global, that's fine, I guess?
// we add a listener on mount and remove it on unmount
useEffect(() => {
listeners.push(setState);
return () => {
const index = listeners.indexOf(setState);
if (index > -1) {
listeners.splice(index, 1);
}
};
}, []);
return {
...state,
toast,
dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }),
};
}
export { useToast, toast };
+8
View File
@@ -0,0 +1,8 @@
export const LOGGED_IN_ONLY_PATHS = [
// anything that _starts_ with /dashboard is logged in only
"/dashboard",
// anything that _starts_ with /cli is logged in only
"/cli",
"/support",
// TODO: add any other logged in only paths here
];
+2
View File
@@ -0,0 +1,2 @@
export const COOKIE_ACTIVE_ACCOUNT = "tw_active_account";
export const COOKIE_PREFIX_TOKEN = "tw_token_";
+3
View File
@@ -7,3 +7,6 @@ export const DASHBOARD_THIRDWEB_SECRET_KEY =
export const IPFS_GATEWAY_URL =
(process.env.NEXT_PUBLIC_IPFS_GATEWAY_URL as string) ||
"https://{clientId}.ipfscdn.io/ipfs/{cid}/{path}";
export const THIRDWEB_ENGINE_FAUCET_WALLET =
process.env.NEXT_PUBLIC_THIRDWEB_ENGINE_FAUCET_WALLET || "";
+33 -10
View File
@@ -4,7 +4,7 @@
@layer base {
:root {
/* bg - nuetral */
/* bg - neutral */
--background: 0 0% 100%;
--secondary: 0 0% 97%;
--muted: 0 0% 95%;
@@ -15,9 +15,9 @@
/* bg - colorful */
--primary: 221.21deg 83.19% 53.33%;
--destructive: 0 84.2% 90%;
--success: 142.09 60.56% 80%;
--warning: 40.61deg 96.12% 88%;
--destructive: 0 84.2% 94%;
--success: 142.09 60.56% 90%;
--warning: 40.61deg 96.12% 92%;
/* Text */
--foreground: 0 0% 3.9%;
@@ -32,6 +32,8 @@
--inverted-foreground: var(--background);
--warning-foreground: 40.61deg 96.12% 40.4%;
--link-foreground: 221.21deg 83.19% 53.33%;
--destructive-text: 0 84.24% 60.2%;
--success-text: 142.09 70.56% 35.29%;
/* Borders */
--border: 0 0% 80%;
@@ -43,9 +45,9 @@
}
.dark {
/* bg - nuetral */
/* bg - neutral */
--background: 0 0% 4.5%;
--secondary: 0 0% 5.5%;
--secondary: 0 0% 6.5%;
--muted: 0 0% 9%;
--accent: 0 0% 12%;
--card: var(--secondary);
@@ -53,8 +55,8 @@
--inverted: var(--foreground);
/* bg - colorful */
--primary: 215.88 100% 60%;
--destructive: 0 62.8% 10%;
--primary: 221 83% 54%;
--destructive: 0 62.8% 15%;
--success: 156.2 71.6% 10%;
--warning: 40.61deg 96.12% 8%;
@@ -62,14 +64,16 @@
--foreground: 0 0% 98%;
--card-foreground: 0 0% 98%;
--popover-foreground: 0 0% 98%;
--primary-foreground: 0 0% 4.5%;
--primary-foreground: 0 0% 100%;
--secondary-foreground: 0 0% 75%;
--muted-foreground: 0 0% 63.9%;
--accent-foreground: 0 0% 98%;
--destructive-foreground: 0 84.24% 60.2%;
--destructive-foreground: 0deg 90.6% 80%;
--success-foreground: 156.2 71.6% 66.86%;
--warning-foreground: 45.4deg 93.39% 47.45%;
--link-foreground: 215.88 100% 65%;
--destructive-text: 0 84.24% 65%;
--success-text: 156.2 71.6% 66.86%;
/* Borders */
--border: 0 0% 14.9%;
@@ -87,6 +91,25 @@
}
}
/* shadcn charts */
@layer base {
:root {
--chart-1: 12 76% 61%;
--chart-2: 173 58% 39%;
--chart-3: 197 37% 24%;
--chart-4: 43 74% 66%;
--chart-5: 27 87% 67%;
}
.dark {
--chart-1: 220 70% 50%;
--chart-2: 160 60% 45%;
--chart-3: 30 80% 55%;
--chart-4: 280 65% 60%;
--chart-5: 340 75% 55%;
}
}
@keyframes skeleton {
0%,
100% {
@@ -1,5 +1,5 @@
import type { ContractType } from "@thirdweb-dev/sdk";
import { constants } from "ethers";
import type { ContractType } from "constants/contracts";
import { ZERO_ADDRESS } from "thirdweb";
export const networkKeys = {
all: ["network"] as const,
@@ -76,6 +76,8 @@ export const engineKeys = {
[...engineKeys.backendWallet(address, chainId), "balance"] as const,
corsUrls: (instance: string) =>
[...engineKeys.all, instance, "corsUrls"] as const,
ipAllowlist: (instance: string) =>
[...engineKeys.all, instance, "ipAllowlist"] as const,
contractSubscriptions: (instance: string) =>
[...engineKeys.all, instance, "contractSubscriptions"] as const,
contractSubscriptionsLastBlock: (instance: string, chainId: number) =>
@@ -95,14 +97,11 @@ export const engineKeys = {
export const contractKeys = {
all: ["contract"] as const,
lists: () => [...contractKeys.all, "list"] as const,
list: (address = constants.AddressZero) =>
[...contractKeys.lists(), address] as const,
listWithFilters: (
address = constants.AddressZero,
filters?: ContractType[],
) => [...contractKeys.list(address), { filters }] as const,
list: (address = ZERO_ADDRESS) => [...contractKeys.lists(), address] as const,
listWithFilters: (address = ZERO_ADDRESS, filters?: ContractType[]) =>
[...contractKeys.list(address), { filters }] as const,
details: () => [...contractKeys.all, "detail"] as const,
detail: (address: string = constants.AddressZero) =>
detail: (address: string = ZERO_ADDRESS) =>
[...contractKeys.details(), address] as const,
};
@@ -115,42 +114,37 @@ export const walletKeys = {
export const splitsKeys = {
all: ["splits"] as const,
lists: () => [...splitsKeys.all, "list"] as const,
list: (address = constants.AddressZero) =>
[...splitsKeys.lists(), address] as const,
detail: (address = constants.AddressZero) =>
[...splitsKeys.all, address] as const,
currencies: (address = constants.AddressZero) =>
list: (address = ZERO_ADDRESS) => [...splitsKeys.lists(), address] as const,
detail: (address = ZERO_ADDRESS) => [...splitsKeys.all, address] as const,
currencies: (address = ZERO_ADDRESS) =>
[...splitsKeys.detail(address), "currencies"] as const,
balances: (address = constants.AddressZero) =>
balances: (address = ZERO_ADDRESS) =>
[...splitsKeys.detail(address), "balances"] as const,
};
export const voteKeys = {
all: ["vote"] as const,
detail: (address = constants.AddressZero) =>
[...voteKeys.all, address] as const,
proposals: (address = constants.AddressZero) =>
detail: (address = ZERO_ADDRESS) => [...voteKeys.all, address] as const,
proposals: (address = ZERO_ADDRESS) =>
[...voteKeys.detail(address), "proposals"] as const,
proposal: (proposalId = "-1", address = constants.AddressZero) =>
proposal: (proposalId = "-1", address = ZERO_ADDRESS) =>
[...voteKeys.proposals(address), proposalId] as const,
balances: (address = constants.AddressZero, addresses = [] as string[]) =>
balances: (address = ZERO_ADDRESS, addresses = [] as string[]) =>
[...voteKeys.detail(address), "balances", { addresses }] as const,
delegations: (address = constants.AddressZero) =>
delegations: (address = ZERO_ADDRESS) =>
[...voteKeys.detail(address), "delegations"] as const,
delegation: (
address = constants.AddressZero,
userAddress = constants.AddressZero,
) => [...voteKeys.delegations(address), userAddress] as const,
delegation: (address = ZERO_ADDRESS, userAddress = ZERO_ADDRESS) =>
[...voteKeys.delegations(address), userAddress] as const,
userHasVotedOnProposal: (
proposalId = "-1",
address = constants.AddressZero,
userAddress = constants.AddressZero,
address = ZERO_ADDRESS,
userAddress = ZERO_ADDRESS,
) =>
[
...voteKeys.proposal(proposalId, address),
"hasVotedOnProposal",
userAddress,
] as const,
canExecuteProposal: (proposalId = "-1", address = constants.AddressZero) =>
canExecuteProposal: (proposalId = "-1", address = ZERO_ADDRESS) =>
[...voteKeys.proposal(proposalId, address), "canExecute"] as const,
};
@@ -1,85 +1,132 @@
"use client";
import { ConnectWallet } from "@thirdweb-dev/react";
import { Spinner } from "@/components/ui/Spinner/Spinner";
import { Button } from "@/components/ui/button";
import { thirdwebClient } from "@/constants/client";
import { useSupportedChains } from "@thirdweb-dev/react";
import { useTrack } from "hooks/analytics/useTrack";
import {
useAddRecentlyUsedChainId,
useRecentlyUsedChains,
} from "hooks/chains/recentlyUsedChains";
import { useSetIsNetworkConfigModalOpen } from "hooks/networkConfigModal";
import { useTheme } from "next-themes";
import Image from "next/image";
import Link from "next/link";
import { type ComponentProps, useCallback } from "react";
import { CustomChainRenderer } from "../../../../components/selects/CustomChainRenderer";
import { useTrack } from "../../../../hooks/analytics/useTrack";
import { usePathname } from "next/navigation";
import { useCallback, useMemo } from "react";
import { type Chain, defineChain } from "thirdweb";
import { AutoConnect, ConnectButton, useConnectModal } from "thirdweb/react";
import { getSDKTheme } from "../../../../app/components/sdk-component-theme";
import { useFavoriteChains } from "../../hooks/useFavoriteChains";
import { useLoggedInUser } from "../../hooks/useLoggedInUser";
import { popularChains } from "../popularChains";
export interface ConnectWalletProps {
shrinkMobile?: boolean;
upsellTestnet?: boolean;
onChainSelect?: (chainId: number) => void;
auth?: ComponentProps<typeof ConnectWallet>["auth"];
disableChainConfig?: boolean;
disableAddCustomNetwork?: boolean;
}
export const CustomConnectWallet: React.FC<ConnectWalletProps> = ({
auth,
disableChainConfig,
disableAddCustomNetwork,
export const CustomConnectWallet = (props: {
loginRequired?: boolean;
connectButtonClassName?: string;
}) => {
const loginRequired =
props.loginRequired === undefined ? true : props.loginRequired;
const { theme } = useTheme();
const recentChains = useRecentlyUsedChains();
const recentChainsv4 = useRecentlyUsedChains();
const addRecentlyUsedChainId = useAddRecentlyUsedChainId();
const setIsNetworkConfigModalOpen = useSetIsNetworkConfigModalOpen();
// const setIsNetworkConfigModalOpen = useSetIsNetworkConfigModalOpen();
const t = theme === "light" ? "light" : "dark";
const allv4Chains = useSupportedChains();
const favChainsQuery = useFavoriteChains();
return (
<ConnectWallet
auth={auth}
theme={t}
welcomeScreen={() => {
return <ConnectWalletWelcomeScreen theme={t} />;
}}
termsOfServiceUrl="/tos"
privacyPolicyUrl="/privacy"
hideTestnetFaucet={false}
networkSelector={{
sections: [
{
label: "Recently used",
chains: recentChains,
},
{
label: "Favorites",
chains: favChainsQuery.data ?? [],
},
{
label: "Popular",
chains: popularChains,
},
],
onSwitch(chain) {
addRecentlyUsedChainId(chain.chainId);
},
onCustomClick: disableAddCustomNetwork
? undefined
: () => {
setIsNetworkConfigModalOpen(true);
},
const allChains = useMemo(() => {
return allv4Chains.map((c) => defineChain(c));
}, [allv4Chains]);
renderChain(props) {
return (
<CustomChainRenderer
{...props}
disableChainConfig={disableChainConfig}
/>
);
const chainSections = useMemo(() => {
return [
{
label: "Favorites",
chains: favChainsQuery.data.map(defineChain),
},
{
label: "Popular",
chains: popularChains,
},
{
label: "Recent",
chains: recentChainsv4.map(defineChain),
},
];
}, [recentChainsv4, favChainsQuery.data]);
// ensures login status on pages that need it
const { isLoading, isLoggedIn } = useLoggedInUser();
const pathname = usePathname();
if (isLoading) {
return (
<>
<div className="w-[144px] h-[48px] bg-muted border rounded-lg flex items-center justify-center">
<Spinner className="size-4" />
</div>
{/* need autoconnect here so that we actually connect */}
<AutoConnect client={thirdwebClient} />
</>
);
}
if (!isLoggedIn && loginRequired) {
return (
<>
<Button asChild variant="default" className="gap-2" size="lg">
<Link
href={`/login${pathname ? `?next=${encodeURIComponent(pathname)}` : ""}`}
>
Sign In
</Link>
</Button>
{/* need autoconnect here so that we actually connect */}
<AutoConnect client={thirdwebClient} />
</>
);
}
return (
<ConnectButton
theme={getSDKTheme(t)}
client={thirdwebClient}
connectModal={{
privacyPolicyUrl: "/privacy",
termsOfServiceUrl: "/tos",
showThirdwebBranding: false,
welcomeScreen: () => <ConnectWalletWelcomeScreen theme={t} />,
}}
appMetadata={{
name: "thirdweb",
logoUrl: "https://thirdweb.com/favicon.ico",
url: "https://thirdweb.com",
}}
onDisconnect={async () => {
try {
// log out the user
await fetch("/api/auth/logout", {
method: "POST",
});
} catch (err) {
console.error("Failed to log out", err);
}
}}
connectButton={{
className: props.connectButtonClassName,
}}
chains={allChains}
detailsModal={{
networkSelector: {
sections: chainSections,
onSwitch(chain) {
addRecentlyUsedChainId(chain.id);
},
// TODO: bring this back when it works reliably
// renderChain: CustomChainRenderer,
},
}}
showThirdwebBranding={false}
/>
);
};
@@ -155,6 +202,35 @@ export function ConnectWalletWelcomeScreen(props: {
);
}
export function useCustomConnectModal() {
const { connect } = useConnectModal();
const { theme } = useTheme();
return useCallback(
(options?: { chain?: Chain }) => {
return connect({
client: thirdwebClient,
appMetadata: {
name: "thirdweb",
logoUrl: "https://thirdweb.com/favicon.ico",
url: "https://thirdweb.com",
},
chain: options?.chain,
privacyPolicyUrl: "/privacy",
termsOfServiceUrl: "/tos",
showThirdwebBranding: false,
welcomeScreen: () => (
<ConnectWalletWelcomeScreen
theme={theme === "light" ? "light" : "dark"}
/>
),
theme: getSDKTheme(theme === "light" ? "light" : "dark"),
});
},
[connect, theme],
);
}
/**
* A link component extends the `Link` component and adds tracking.
*/
@@ -1,35 +1,35 @@
import {
Arbitrum,
ArbitrumSepolia,
Avalanche,
AvalancheFuji,
Base,
BaseSepoliaTestnet,
Binance,
BinanceTestnet,
Ethereum,
Localhost,
OpSepoliaTestnet,
Optimism,
Polygon,
PolygonAmoyTestnet,
Sepolia,
} from "@thirdweb-dev/chains";
arbitrum,
arbitrumSepolia,
avalanche,
avalancheFuji,
base,
baseSepolia,
bsc,
bscTestnet,
ethereum,
localhost,
optimism,
optimismSepolia,
polygon,
polygonAmoy,
sepolia,
} from "thirdweb/chains";
export const popularChains = [
Ethereum,
Sepolia,
Polygon,
PolygonAmoyTestnet,
Base,
BaseSepoliaTestnet,
Arbitrum,
ArbitrumSepolia,
Optimism,
OpSepoliaTestnet,
Binance,
BinanceTestnet,
Avalanche,
AvalancheFuji,
Localhost,
ethereum,
sepolia,
polygon,
polygonAmoy,
base,
baseSepolia,
arbitrum,
arbitrumSepolia,
optimism,
optimismSepolia,
bsc,
bscTestnet,
avalanche,
avalancheFuji,
localhost,
];
@@ -1,9 +1,9 @@
import { useIsLister } from "@3rdweb-sdk/react/hooks/useContractRoles";
import type { ValidContractInstance } from "@thirdweb-dev/sdk";
import type { ThirdwebContract } from "thirdweb";
import type { ComponentWithChildren } from "types/component-with-children";
interface IListerOnlyProps {
contract?: ValidContractInstance;
contract: ThirdwebContract;
}
export const ListerOnly: ComponentWithChildren<IListerOnlyProps> = ({
@@ -1,9 +1,9 @@
import { useIsMinter } from "@3rdweb-sdk/react/hooks/useContractRoles";
import type { ValidContractInstance } from "@thirdweb-dev/sdk";
import type { ThirdwebContract } from "thirdweb";
import type { ComponentWithChildren } from "types/component-with-children";
interface IMinterOnlyProps {
contract?: ValidContractInstance;
contract: ThirdwebContract;
}
export const MinterOnly: ComponentWithChildren<IMinterOnlyProps> = ({
@@ -1,4 +1,3 @@
import type { Chain } from "@thirdweb-dev/chains";
import {
createContext,
useCallback,
@@ -6,11 +5,12 @@ import {
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
chain: Chain | null;
chain: ChainMetadata | null;
chainSlug: string;
contractAddress: string;
};
@@ -4,8 +4,7 @@ import {
useQuery,
useQueryClient,
} from "@tanstack/react-query";
import type { Chain } from "@thirdweb-dev/chains";
import { useEffect, useState } from "react";
import type { ChainMetadata } from "thirdweb/chains";
import invariant from "tiny-invariant";
import { THIRDWEB_API_HOST } from "../../../constants/urls";
import { accountKeys, apiKeys, authorizedWallets } from "../cache-keys";
@@ -277,7 +276,6 @@ export function useAccount({ refetchInterval }: UseAccountInput = {}) {
async () => {
const res = await fetch(`${THIRDWEB_API_HOST}/v1/account/me`, {
method: "GET",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
@@ -305,7 +303,6 @@ export function useAccountUsage() {
async () => {
const res = await fetch(`${THIRDWEB_API_HOST}/v1/account/usage`, {
method: "GET",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
@@ -330,7 +327,7 @@ export function useAccountCredits() {
async () => {
const res = await fetch(`${THIRDWEB_API_HOST}/v1/account/credits`, {
method: "GET",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
@@ -364,7 +361,7 @@ export function useWalletStats(clientId: string | undefined) {
`${THIRDWEB_API_HOST}/v1/account/wallets?clientId=${clientId}`,
{
method: "GET",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
@@ -392,7 +389,7 @@ export function useUpdateAccount() {
const res = await fetch(`${THIRDWEB_API_HOST}/v1/account`, {
method: "PUT",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
@@ -427,7 +424,7 @@ export function useUpdateAccountPlan(waitForWebhook?: boolean) {
const res = await fetch(`${THIRDWEB_API_HOST}/v1/account/plan`, {
method: "PUT",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
@@ -471,7 +468,7 @@ export function useUpdateNotifications() {
const res = await fetch(`${THIRDWEB_API_HOST}/v1/account/notifications`, {
method: "PUT",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
@@ -507,7 +504,7 @@ export function useCreateBillingSession(enabled = false) {
`${THIRDWEB_API_HOST}/v1/account/billingSession`,
{
method: "GET",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
@@ -535,7 +532,7 @@ export function useConfirmEmail() {
const res = await fetch(`${THIRDWEB_API_HOST}/v1/account/confirmEmail`, {
method: "PUT",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
@@ -565,49 +562,6 @@ export function useConfirmEmail() {
);
}
export function useConfirmEmbeddedWallet() {
const { user } = useLoggedInUser();
const queryClient = useQueryClient();
return useMutationWithInvalidate(
async ({ ewsJwt }: { ewsJwt: string }) => {
invariant(user?.address, "walletAddress is required");
const res = await fetch(
`${THIRDWEB_API_HOST}/v1/account/confirmEmbeddedWallet`,
{
method: "PUT",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ paperJwt: ewsJwt }),
},
);
const json = await res.json();
if (json.error) {
throw new Error(json.error.message);
}
return json.data;
},
{
onSuccess: () => {
// invalidate related cache, since could be relinking account
queryClient.invalidateQueries(apiKeys.keys(user?.address as string));
queryClient.invalidateQueries(
accountKeys.usage(user?.address as string),
);
return queryClient.invalidateQueries(
accountKeys.me(user?.address as string),
);
},
},
);
}
export function useResendEmailConfirmation() {
const { user } = useLoggedInUser();
const queryClient = useQueryClient();
@@ -620,7 +574,7 @@ export function useResendEmailConfirmation() {
`${THIRDWEB_API_HOST}/v1/account/resendEmailConfirmation`,
{
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
@@ -655,7 +609,7 @@ export function useCreatePaymentMethod() {
const res = await fetch(`${THIRDWEB_API_HOST}/v1/account/paymentMethod`, {
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
@@ -688,7 +642,7 @@ export function useApiKeys() {
async () => {
const res = await fetch(`${THIRDWEB_API_HOST}/v1/keys`, {
method: "GET",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
@@ -714,7 +668,7 @@ export function useCreateApiKey() {
const res = await fetch(`${THIRDWEB_API_HOST}/v1/keys`, {
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
@@ -748,7 +702,7 @@ export function useUpdateApiKey() {
const res = await fetch(`${THIRDWEB_API_HOST}/v1/keys/${input.id}`, {
method: "PUT",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
@@ -783,7 +737,7 @@ export function useRevokeApiKey() {
const res = await fetch(`${THIRDWEB_API_HOST}/v1/keys/${id}/revoke`, {
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
@@ -815,7 +769,7 @@ export const usePolicies = (serviceId?: string) => {
`${THIRDWEB_API_HOST}/v1/policies?serviceId=${serviceId}`,
{
method: "GET",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
@@ -837,7 +791,7 @@ export const useUpdatePolicies = () => {
async (input: { serviceId: string; data: ApiKeyServicePolicy }) => {
const res = await fetch(`${THIRDWEB_API_HOST}/v1/policies`, {
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
@@ -869,7 +823,7 @@ export function useAuthorizeWalletWithAccount() {
const res = await fetch(`${THIRDWEB_API_HOST}/v1/jwt/authorize-wallet`, {
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/json",
authorization: `Bearer ${variables.token}`,
@@ -903,7 +857,7 @@ export function useRevokeAuthorizedWallet() {
`${THIRDWEB_API_HOST}/v1/authorized-wallets/${authorizedWalletId}/revoke`,
{
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
@@ -936,7 +890,7 @@ export function useAuthorizedWallets() {
async () => {
const res = await fetch(`${THIRDWEB_API_HOST}/v1/authorized-wallets`, {
method: "GET",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
@@ -953,110 +907,6 @@ export function useAuthorizedWallets() {
);
}
type FetchAuthTokenResponse = {
jwt: string;
paymentsSellerId?: string;
};
const TOKEN_PROMISE_MAP = new Map<string, Promise<FetchAuthTokenResponse>>();
async function fetchAuthToken(
address: string,
abortController?: AbortController,
): Promise<FetchAuthTokenResponse> {
if (!address) {
throw new Error("address is required");
}
if (TOKEN_PROMISE_MAP.has(address)) {
return TOKEN_PROMISE_MAP.get(address) as Promise<FetchAuthTokenResponse>;
}
const promise = new Promise<FetchAuthTokenResponse>((resolve, reject) => {
return fetch(`${THIRDWEB_API_HOST}/v1/auth/token`, {
method: "GET",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
signal: abortController?.signal,
})
.then((res) => res.json())
.then((json) => {
if (json.error) {
throw new Error(json.error.message);
}
return {
jwt: json.data.jwt as string,
paymentsSellerId: json.data.paymentsSellerId,
};
})
.then(resolve)
.catch(reject);
});
TOKEN_PROMISE_MAP.set(address, promise);
return promise;
}
// keep the promise around so we don't fetch it multiple times even if the hook gets called from different places
let inflightPromise: Promise<FetchAuthTokenResponse> | null = null;
export function useApiAuthToken() {
const { user } = useLoggedInUser();
const [token, setToken] = useState<string | null>(null);
const [paymentsSellerId, setPaymentsSellerId] = useState<string | null>(null);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<Error | null>(null);
// not using a query because we don't want to store this in any cache
// eslint-disable-next-line no-restricted-syntax
useEffect(() => {
let mounted = true;
setError(null);
setIsLoading(false);
if (!user?.address) {
return;
}
setIsLoading(true);
const abortController = new AbortController();
if (!inflightPromise) {
inflightPromise = fetchAuthToken(user.address, abortController);
}
// eslint-disable-next-line promise/catch-or-return
inflightPromise
.then((t) => {
// eslint-disable-next-line promise/always-return
if (mounted) {
setToken(t.jwt);
if (t.paymentsSellerId) {
setPaymentsSellerId(t.paymentsSellerId);
}
}
})
.catch((err) => {
if (mounted) {
setError(err);
}
})
.finally(() => {
if (mounted) {
inflightPromise = null;
setIsLoading(false);
}
});
return () => {
mounted = false;
// cancel the fetch if it's still in flight
abortController.abort();
inflightPromise = null;
setToken(null);
};
}, [user?.address]);
return { error, isLoading, token, paymentsSellerId };
}
/**
*
*/
@@ -1065,8 +915,6 @@ export async function fetchChainsFromApi() {
// TODO: re-visit this
const res = await fetch("https://api.thirdweb.com/v1/chains", {
method: "GET",
// do not inclue credentials for chains endpoint
// credentials: "include",
headers: {
"Content-Type": "application/json",
},
@@ -1077,7 +925,7 @@ export async function fetchChainsFromApi() {
throw new Error(json.error.message);
}
return json.data as Chain[];
return json.data as ChainMetadata[];
}
export function useApiChains() {
@@ -1,13 +0,0 @@
import { useQuery } from "@tanstack/react-query";
import { useSDK } from "@thirdweb-dev/react";
import invariant from "tiny-invariant";
import { walletKeys } from "../cache-keys";
export function useBalanceForAddress(address: string | undefined) {
const sdk = useSDK();
invariant(address, "Address is not provided");
return useQuery(walletKeys.balances(address), async () => {
invariant(sdk, "SDK is not initialized");
return await sdk.getBalance(address);
});
}
@@ -1,13 +1,14 @@
import {
type ContractWithRoles,
type RequiredParam,
type RolesForContract,
useAddress,
useContractType,
useRoleMembers,
} from "@thirdweb-dev/react";
import type { ValidContractInstance } from "@thirdweb-dev/sdk";
import { constants } from "ethers";
import { type ThirdwebContract, ZERO_ADDRESS } from "thirdweb";
import { hasRole } from "thirdweb/extensions/permissions";
import { useActiveAccount, useReadContract } from "thirdweb/react";
import type { RequiredParam } from "utils/types";
function isContractWithRoles(
contract: RequiredParam<ValidContractInstance>,
@@ -30,7 +31,7 @@ function useIsAccountRole<TContract extends ContractWithRoles>(
return false;
}
if (data?.includes(constants.AddressZero)) {
if (data?.includes(ZERO_ADDRESS)) {
return true;
}
@@ -40,7 +41,7 @@ function useIsAccountRole<TContract extends ContractWithRoles>(
export function useIsAdmin<TContract extends ValidContractInstance>(
contract: RequiredParam<TContract>,
) {
const address = useAddress();
const address = useActiveAccount()?.address;
const { data: contractType } = useContractType(contract?.getAddress());
const contractHasRoles = isContractWithRoles(contract);
@@ -60,7 +61,7 @@ export function useIsAdminOrSelf<TContract extends ValidContractInstance>(
contract: RequiredParam<TContract>,
self: RequiredParam<string>,
) {
const address = useAddress();
const address = useActiveAccount()?.address;
const { data: contractType } = useContractType(contract?.getAddress());
const isAdmin = useIsAdmin(contract);
@@ -73,38 +74,45 @@ export function useIsAdminOrSelf<TContract extends ValidContractInstance>(
return isAdmin;
}
export function useIsMinter<TContract extends ValidContractInstance>(
contract: RequiredParam<TContract>,
) {
const address = useAddress();
const { data: contractType } = useContractType(contract?.getAddress());
const contractHasRoles = isContractWithRoles(contract);
const isAccountRole = useIsAccountRole(
"minter",
contractHasRoles ? contract : undefined,
address,
);
export function useIsMinter(contract: ThirdwebContract) {
const address = useActiveAccount()?.address;
const userCanMintQuery = useReadContract(hasRole, {
contract,
targetAccountAddress: address ?? "",
role: "minter",
queryOptions: { enabled: !!address },
});
if (contractType === "custom") {
return true;
}
return isAccountRole;
const anyoneCanMintQuery = useReadContract(hasRole, {
contract,
targetAccountAddress: ZERO_ADDRESS,
role: "minter",
});
// If both requests "error out", we can safely assume that
// this is a custom (aka. non-thirdweb) contract
// so we just return `true` in that case
const isCustomContract =
userCanMintQuery.isError && anyoneCanMintQuery.isError;
return anyoneCanMintQuery.data || userCanMintQuery.data || isCustomContract;
}
export function useIsLister<TContract extends ValidContractInstance>(
contract: RequiredParam<TContract>,
) {
const address = useAddress();
const { data: contractType } = useContractType(contract?.getAddress());
const contractHasRoles = isContractWithRoles(contract);
const isAccountRole = useIsAccountRole(
"lister",
contractHasRoles ? contract : undefined,
address,
);
// Applicable to Marketplace v3 only
export function useIsLister(contract: ThirdwebContract) {
const address = useActiveAccount()?.address;
const { data: userCanList } = useReadContract(hasRole, {
contract,
targetAccountAddress: address ?? "",
role: "lister",
queryOptions: { enabled: !!address },
});
if (contractType === "custom") {
return true;
}
return isAccountRole;
const { data: anyoneCanList } = useReadContract(hasRole, {
contract,
targetAccountAddress: ZERO_ADDRESS,
role: "lister",
});
return anyoneCanList || userCanList;
}
@@ -1,202 +0,0 @@
import { useToast } from "@chakra-ui/react";
import { useState } from "react";
import invariant from "tiny-invariant";
import { THIRDWEB_API_HOST } from "../../../constants/urls";
import { useMutationWithInvalidate } from "./query/useQueryWithNetwork";
import { useAccount } from "./useApi";
import { useLoggedInUser } from "./useLoggedInUser";
const SUPPORT_EMAIL = "[email protected]";
export type CreateTicketInput = {
markdown: string;
product: string;
files?: File[];
} & Record<string, string>;
function prepareEmailTitle(
input: CreateTicketInput,
email: string,
name: string,
) {
const title =
input.product && input.extraInfo_Problem_Area
? `${input.product}: ${input.extraInfo_Problem_Area} (${email})`
: `New ticket from ${name} (${email})`;
return title;
}
function prepareEmailBody(
input: CreateTicketInput,
email: string,
address: string,
) {
// Update `markdown` to include the infos from the form
const extraInfo = Object.keys(input)
.filter((key) => key.startsWith("extraInfo_"))
.map((key) => {
const prettifiedKey = `# ${key
.replace("extraInfo_", "")
.replaceAll("_", " ")}`;
return `${prettifiedKey}: ${input[key] ?? "N/A"}\n`;
})
.join("");
const markdown = `# Email: ${email}
# Address: ${address}
# Product: ${input.product}
${extraInfo}
# Message:
${input.markdown}
`;
return markdown;
}
export function useCreateTicket() {
const { user } = useLoggedInUser();
const account = useAccount();
const toast = useToast();
const [data, setData] = useState<CreateTicketInput>();
return useMutationWithInvalidate(
async (input: CreateTicketInput) => {
setData(input);
invariant(user?.address, "walletAddress is required");
invariant(account?.data, "Account not found");
const { name, email, plan } = account.data;
const formData = new FormData();
const planToCustomerId: Record<string, string> = {
free: process.env.NEXT_PUBLIC_UNTHREAD_FREE_TIER_ID as string,
growth: process.env.NEXT_PUBLIC_UNTHREAD_GROWTH_TIER_ID as string,
pro: process.env.NEXT_PUBLIC_UNTHREAD_PRO_TIER_ID as string,
};
const customerId = planToCustomerId[plan] || undefined;
if (input.files?.length) {
for (const file of input.files) {
formData.append("attachments", file);
}
}
const title = prepareEmailTitle(input, email ?? "", name ?? "");
const markdown = prepareEmailBody(input, email ?? "", user.address);
const content = {
type: "email",
title,
markdown,
status: "open",
onBehalfOf: {
email,
name,
},
customerId,
emailInboxId: process.env.NEXT_PUBLIC_UNTHREAD_EMAIL_INBOX_ID,
triageChannelId: process.env.NEXT_PUBLIC_UNTHREAD_TRIAGE_CHANNEL_ID,
};
formData.append("json", JSON.stringify(content));
// Show toast for "loading"
toast({
id: "_submitting_ticket_toast_",
position: "bottom",
variant: "solid",
title: "Submitting ticket",
status: "loading",
duration: 5000,
isClosable: true,
});
const res = await fetch(
`${THIRDWEB_API_HOST}/v1/account/create-unthread-ticket`,
{
method: "POST",
credentials: "include",
body: formData,
},
);
const json = await res.json();
if (json.error) {
throw new Error(json.error.message);
}
return json.data;
},
{
onError: () => {
/**
* In case an unexpected incident happens, we fallback to use `mailto:`
* as an alternative solution
*/
if (!data) {
return toast({
position: "bottom",
variant: "solid",
title: "Oops, something went wrong",
description: (
<>
If the problem persists, please reach out to us directly via{" "}
{
<a
href={`mailto:${SUPPORT_EMAIL}`}
target="_blank"
rel="noreferrer"
>
{SUPPORT_EMAIL}
</a>
}
</>
),
status: "error",
duration: 15000,
isClosable: true,
});
}
const emailSubject = prepareEmailTitle(
data,
account.data?.email ?? "",
account.data?.name ?? "",
);
const emailBody = encodeURIComponent(
prepareEmailBody(
data,
account.data?.email ?? "",
user?.address ?? "",
),
).replace(/%0A/g, "%0D%0A");
toast({
position: "bottom",
variant: "solid",
title: "Oops, something went wrong",
description: (
<>
If the problem persists, please reach out to us directly via{" "}
{
<a
href={`mailto:${SUPPORT_EMAIL}?subject=${emailSubject}&body=${emailBody}`}
target="_blank"
rel="noreferrer"
>
{SUPPORT_EMAIL}
</a>
}
</>
),
status: "error",
duration: 15000,
isClosable: true,
});
},
onSuccess: async () => {
toast.close("_submitting_ticket_toast_");
toast({
position: "bottom",
variant: "solid",
title: "Success",
description:
"Successfully sent support ticket. Our team will be in touch using your account email shortly.",
status: "success",
duration: 5000,
isClosable: true,
});
},
},
);
}
@@ -0,0 +1,26 @@
import { thirdwebClient } from "@/constants/client";
import { useMutation } from "@tanstack/react-query";
import { upload } from "thirdweb/storage";
type DashboardUploadOptions = {
uploadWithoutDirectory?: boolean;
metadata?: Record<string, string>;
};
export function useDashboardStorageUpload(options?: DashboardUploadOptions) {
return useMutation({
mutationFn: async (files: Array<File | string>): Promise<string[]> => {
const uris = await upload({
client: thirdwebClient,
files,
...options,
});
// the upload method in SDK v5 has this logic
// that will make it return only a string if you upload only 1 file
if (typeof uris === "string") {
return [uris];
}
return uris;
},
});
}
@@ -35,9 +35,9 @@ export function useEmbeddedWallets(clientId: string) {
`${THIRDWEB_EWS_API_HOST}/api/thirdweb/embedded-wallet?clientId=${clientId}&lastAccessedAt=0`,
{
method: "GET",
credentials: "include",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${user?.jwt}`,
},
},
);
@@ -1,11 +1,11 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useAddress, useChainId } from "@thirdweb-dev/react";
import { THIRDWEB_API_HOST } from "constants/urls";
import { useState } from "react";
import { useActiveAccount, useActiveWalletChain } from "thirdweb/react";
import invariant from "tiny-invariant";
import type { ResultItem } from "../../../components/engine/system-metrics/components/StatusCodes";
import { engineKeys } from "../cache-keys";
import { useMutationWithInvalidate } from "./query/useQueryWithNetwork";
import { useApiAuthToken } from "./useApi";
import { useLoggedInUser } from "./useLoggedInUser";
export function useEngineConnectedInstance() {
@@ -23,7 +23,7 @@ export type EngineInstance = {
name: string;
url: string;
lastAccessedAt: string;
cloudDeployedAt: string;
cloudDeployedAt?: string;
status:
| "active"
| "pending"
@@ -60,7 +60,6 @@ export function useEngineInstances() {
async (): Promise<EngineInstance[]> => {
const res = await fetch(`${THIRDWEB_API_HOST}/v1/engine`, {
method: "GET",
credentials: "include",
});
if (!res.ok) {
throw new Error(`Unexpected status ${res.status}: ${await res.text()}`);
@@ -99,7 +98,7 @@ export type BackendWallet = {
};
export function useEngineBackendWallets(instance: string) {
const { token } = useApiAuthToken();
const token = useLoggedInUser().user?.jwt ?? null;
return useQuery(
[engineKeys.backendWallets(instance)],
@@ -123,7 +122,10 @@ export interface EngineSystemHealth {
features?: string[];
}
export function useEngineSystemHealth(instanceUrl: string) {
export function useEngineSystemHealth(
instanceUrl: string,
pollInterval: number | false = false,
) {
return useQuery(
engineKeys.health(instanceUrl),
async () => {
@@ -136,7 +138,10 @@ export function useEngineSystemHealth(instanceUrl: string) {
const json = (await res.json()) as EngineSystemHealth;
return json;
},
{ enabled: !!instanceUrl },
{
enabled: !!instanceUrl,
refetchInterval: pollInterval,
},
);
}
@@ -144,7 +149,6 @@ export function useEngineLatestVersion() {
return useQuery(engineKeys.latestVersion(), async () => {
const res = await fetch(`${THIRDWEB_API_HOST}/v1/engine/latest-version`, {
method: "GET",
credentials: "include",
});
if (!res.ok) {
throw new Error(`Unexpected status ${res.status}: ${await res.text()}`);
@@ -164,7 +168,7 @@ export function useEngineUpdateVersion() {
const res = await fetch(`${THIRDWEB_API_HOST}/v1/engine/update-version`, {
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
@@ -190,7 +194,6 @@ export function useEngineRemoveFromDashboard() {
const res = await fetch(`${THIRDWEB_API_HOST}/v1/engine/${instanceId}`, {
method: "DELETE",
credentials: "include",
});
// we never use the response body
res.body?.cancel();
@@ -224,7 +227,7 @@ export function useEngineRemoveCloudHosted() {
`${THIRDWEB_API_HOST}/v1/engine/${instanceId}/remove-cloud-hosted`,
{
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
@@ -261,7 +264,7 @@ export function useEngineEditInstance() {
async ({ instanceId, name, url }: EditEngineInstanceInput) => {
const res = await fetch(`${THIRDWEB_API_HOST}/v1/engine/${instanceId}`, {
method: "PUT",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
@@ -342,7 +345,7 @@ type TransactionResponse = {
* @returns
*/
export function useEngineTransactions(instance: string, autoUpdate: boolean) {
const { token } = useApiAuthToken();
const token = useLoggedInUser().user?.jwt ?? null;
return useQuery(
engineKeys.transactions(instance),
@@ -383,7 +386,7 @@ type WalletConfig =
};
export function useEngineWalletConfig(instance: string) {
const { token } = useApiAuthToken();
const token = useLoggedInUser().user?.jwt ?? null;
return useQuery(
engineKeys.walletConfig(instance),
@@ -413,8 +416,8 @@ export function useEngineBackendWalletBalance(
instance: string,
address: string,
) {
const { token } = useApiAuthToken();
const chainId = useChainId();
const token = useLoggedInUser().user?.jwt ?? null;
const chainId = useActiveWalletChain()?.id;
invariant(chainId, "chainId is required");
@@ -444,8 +447,8 @@ export type EngineAdmin = {
};
export function useEnginePermissions(instance: string) {
const { token } = useApiAuthToken();
const address = useAddress();
const token = useLoggedInUser().user?.jwt ?? null;
const address = useActiveAccount()?.address;
return useQuery(
engineKeys.permissions(instance),
@@ -479,7 +482,7 @@ export type AccessToken = {
};
export function useEngineAccessTokens(instance: string) {
const { token } = useApiAuthToken();
const token = useLoggedInUser().user?.jwt ?? null;
return useQuery(
engineKeys.accessTokens(instance),
@@ -509,7 +512,7 @@ export type Keypair = {
};
export function useEngineKeypairs(instance: string) {
const { token } = useApiAuthToken();
const token = useLoggedInUser().user?.jwt ?? null;
return useQuery(
engineKeys.keypairs(instance),
@@ -534,7 +537,7 @@ type AddKeypairInput = {
};
export function useEngineAddKeypair(instance: string) {
const { token } = useApiAuthToken();
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
@@ -567,7 +570,7 @@ type RemoveKeypairInput = {
};
export function useEngineRemoveKeypair(instance: string) {
const { token } = useApiAuthToken();
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
@@ -605,7 +608,7 @@ export type EngineRelayer = {
};
export function useEngineRelayer(instance: string) {
const { token } = useApiAuthToken();
const token = useLoggedInUser().user?.jwt ?? null;
return useQuery(
engineKeys.relayers(instance),
@@ -632,7 +635,7 @@ export type CreateRelayerInput = {
};
export function useEngineCreateRelayer(instance: string) {
const { token } = useApiAuthToken();
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
@@ -665,7 +668,7 @@ type RevokeRelayerInput = {
};
export function useEngineRevokeRelayer(instance: string) {
const { token } = useApiAuthToken();
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
@@ -703,7 +706,7 @@ export type UpdateRelayerInput = {
};
export function useEngineUpdateRelayer(instance: string) {
const { token } = useApiAuthToken();
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
@@ -742,7 +745,7 @@ export interface EngineWebhook {
}
export function useEngineWebhooks(instance: string) {
const { token } = useApiAuthToken();
const token = useLoggedInUser().user?.jwt ?? null;
return useQuery(
engineKeys.webhooks(instance),
@@ -781,7 +784,7 @@ export type SetWalletConfigInput =
};
export function useEngineSetWalletConfig(instance: string) {
const { token } = useApiAuthToken();
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
@@ -814,7 +817,7 @@ export type CreateBackendWalletInput = {
};
export function useEngineCreateBackendWallet(instance: string) {
const { token } = useApiAuthToken();
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
@@ -850,7 +853,7 @@ interface UpdateBackendWalletInput {
}
export function useEngineUpdateBackendWallet(instance: string) {
const { token } = useApiAuthToken();
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
@@ -901,7 +904,7 @@ export type ImportBackendWalletInput =
};
export function useEngineImportBackendWallet(instance: string) {
const { token } = useApiAuthToken();
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
@@ -932,7 +935,7 @@ export function useEngineImportBackendWallet(instance: string) {
}
export function useEngineGrantPermissions(instance: string) {
const { token } = useApiAuthToken();
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
@@ -965,7 +968,7 @@ type RevokePermissionsInput = {
};
export function useEngineRevokePermissions(instance: string) {
const { token } = useApiAuthToken();
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
@@ -998,7 +1001,7 @@ type CreateAccessTokenResponse = AccessToken & {
};
export function useEngineCreateAccessToken(instance: string) {
const { token } = useApiAuthToken();
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
@@ -1031,7 +1034,7 @@ type RevokeAccessTokenInput = {
};
export function useEngineRevokeAccessToken(instance: string) {
const { token } = useApiAuthToken();
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
@@ -1065,7 +1068,7 @@ type UpdateAccessTokenInput = {
};
export function useEngineUpdateAccessToken(instance: string) {
const { token } = useApiAuthToken();
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
@@ -1100,7 +1103,7 @@ export type CreateWebhookInput = {
};
export function useEngineCreateWebhook(instance: string) {
const { token } = useApiAuthToken();
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
@@ -1133,7 +1136,7 @@ type RevokeWebhookInput = {
};
export function useEngineRevokeWebhook(instance: string) {
const { token } = useApiAuthToken();
const token = useLoggedInUser().user?.jwt ?? null;
const queryClient = useQueryClient();
return useMutationWithInvalidate(
@@ -1170,7 +1173,7 @@ type SendTokensInput = {
};
export function useEngineSendTokens(instance: string) {
const { token } = useApiAuthToken();
const token = useLoggedInUser().user?.jwt ?? null;
return useMutation(async (input: SendTokensInput) => {
invariant(instance, "instance is required");
@@ -1201,7 +1204,7 @@ export function useEngineSendTokens(instance: string) {
}
export function useEngineCorsConfiguration(instance: string) {
const { token } = useApiAuthToken();
const token = useLoggedInUser().user?.jwt ?? null;
return useQuery(
engineKeys.corsUrls(instance),
@@ -1225,7 +1228,7 @@ interface SetCorsUrlInput {
export function useEngineSetCorsConfiguration(instance: string) {
const queryClient = useQueryClient();
const { token } = useApiAuthToken();
const token = useLoggedInUser().user?.jwt ?? null;
return useMutation(
async (input: SetCorsUrlInput) => {
@@ -1252,6 +1255,64 @@ export function useEngineSetCorsConfiguration(instance: string) {
);
}
export function useEngineIpAllowlistConfiguration(instance: string) {
const token = useLoggedInUser().user?.jwt ?? null;
// don't bother sending requests that bounce
// if engine instance is not updated to have IP_ALLOWLIST
const { data: health } = useEngineSystemHealth(instance);
return useQuery(
engineKeys.ipAllowlist(instance),
async () => {
const res = await fetch(`${instance}configuration/ip-allowlist`, {
method: "GET",
headers: getEngineRequestHeaders(token),
});
const json = await res.json();
return (json.result as string[]) || [];
},
{
enabled:
!!instance && !!token && health?.features?.includes("IP_ALLOWLIST"),
},
);
}
interface SetIpAllowlistInput {
ips: string[];
}
export function useEngineSetIpAllowlistConfiguration(instance: string) {
const queryClient = useQueryClient();
const token = useLoggedInUser().user?.jwt ?? null;
return useMutation(
async (input: SetIpAllowlistInput) => {
invariant(instance, "instance is required");
const res = await fetch(`${instance}configuration/ip-allowlist`, {
method: "PUT",
headers: getEngineRequestHeaders(token),
body: JSON.stringify(input),
});
const json = await res.json();
if (json.error) {
throw new Error(json.error.message);
}
return json.result;
},
{
onSuccess: () => {
return queryClient.invalidateQueries(engineKeys.ipAllowlist(instance));
},
},
);
}
export interface EngineContractSubscription {
id: string;
chainId: number;
@@ -1268,7 +1329,7 @@ export interface EngineContractSubscription {
}
export function useEngineContractSubscription(instance: string) {
const { token } = useApiAuthToken();
const token = useLoggedInUser().user?.jwt ?? null;
return useQuery(
engineKeys.contractSubscriptions(instance),
async () => {
@@ -1298,7 +1359,7 @@ export interface AddContractSubscriptionInput {
export function useEngineAddContractSubscription(instance: string) {
const queryClient = useQueryClient();
const { token } = useApiAuthToken();
const token = useLoggedInUser().user?.jwt ?? null;
return useMutation(
async (input: AddContractSubscriptionInput) => {
@@ -1333,7 +1394,7 @@ export interface RemoveContractSubscriptionInput {
export function useEngineRemoveContractSubscription(instance: string) {
const queryClient = useQueryClient();
const { token } = useApiAuthToken();
const token = useLoggedInUser().user?.jwt ?? null;
return useMutation(
async (input: RemoveContractSubscriptionInput) => {
@@ -1367,7 +1428,7 @@ export function useEngineSubscriptionsLastBlock(
chainId: number,
autoUpdate: boolean,
) {
const { token } = useApiAuthToken();
const token = useLoggedInUser().user?.jwt ?? null;
return useQuery(
engineKeys.contractSubscriptionsLastBlock(instanceUrl, chainId),
@@ -1395,6 +1456,9 @@ export interface EngineResourceMetrics {
data: {
cpu: number;
memory: number;
errorRate: ResultItem[];
statusCodes: ResultItem[];
requestVolume: ResultItem[];
};
}
@@ -1406,10 +1470,6 @@ export function useEngineResourceMetrics(engineId: string) {
async () => {
const res = await fetch(
`${THIRDWEB_API_HOST}/v1/engine/${engineId}/metrics`,
{
method: "GET",
credentials: "include",
},
);
if (!res.ok) {
setEnabled(false);
@@ -1,6 +1,6 @@
import type { Chain } from "@thirdweb-dev/chains";
import { useSupportedChains } from "@thirdweb-dev/react";
import { useMemo } from "react";
import type { ChainMetadata } from "thirdweb/chains";
import { useFavouriteChainIds } from "../../../app/(dashboard)/(chain)/components/client/star-button";
export function useFavoriteChains() {
@@ -9,7 +9,7 @@ export function useFavoriteChains() {
const data = useMemo(() => {
if (favChainsQuery.data) {
const _chains: Chain[] = [];
const _chains: ChainMetadata[] = [];
// biome-ignore lint/complexity/noForEach: FIXME
favChainsQuery.data.forEach((chainId) => {
const chain = allChains.find((c) => String(c.chainId) === chainId);
@@ -21,7 +21,7 @@ export function useFavoriteChains() {
return _chains;
}
return [] as Chain[];
return [] as ChainMetadata[];
}, [favChainsQuery.data, allChains]);
return {
@@ -1,21 +1,132 @@
import { useAddress, useUser } from "@thirdweb-dev/react";
import { LOGGED_IN_ONLY_PATHS } from "@/constants/auth";
import { useQuery } from "@tanstack/react-query";
import { usePathname, useRouter } from "next/navigation";
import { useRef } from "react";
import {
useActiveAccount,
useActiveWalletConnectionStatus,
} from "thirdweb/react";
import type { EnsureLoginResponse } from "../../../app/api/auth/ensure-login/route";
export function useLoggedInUser(): ReturnType<typeof useUser> {
const connectedAddress = useAddress();
const userQuery = useUser();
// define "TW_AUTH_TOKEN" to exist on the window object
declare global {
interface Window {
TW_AUTH_TOKEN?: string;
}
}
// user is not considered logged in if the connected address does not match the user's address
if (
!userQuery.isLoggedIn ||
!connectedAddress ||
userQuery.user?.address !== connectedAddress
) {
export function useLoggedInUser(): {
isLoading: boolean;
isLoggedIn: boolean;
user: { address: string; jwt?: string } | null;
} {
const router = useRouter();
const pathname = usePathname();
const connectedAddress = useActiveAccount()?.address;
const connectionStatus = useActiveWalletConnectionStatus();
// this is to work around the fact that `connectionStatus` ends up as "disconnected"
// which we *do* care about, but only after we have been "connecting" at least once
const statusWasEverConnecting = useRef(false);
if (connectionStatus === "connecting" || connectionStatus === "connected") {
statusWasEverConnecting.current = true;
}
const query = useQuery({
// enabled if:
// - there is a pathname
// - we are not already currently connecting
// - the pathname is one of the LOGGED_IN_ONLY_PATHS
enabled:
!!pathname &&
connectionStatus !== "connecting" &&
statusWasEverConnecting.current &&
LOGGED_IN_ONLY_PATHS.some((path) => pathname.startsWith(path)),
// the last "persist", part of the queryKey, is to make sure that we do not cache this query in indexDB
// convention in v4 of the SDK that we are (ab)using here
queryKey: ["logged_in_user", connectedAddress, { persist: false }],
retry: false,
queryFn: async () => {
const searchParams = new URLSearchParams();
if (pathname) {
searchParams.set("pathname", pathname);
}
if (connectedAddress) {
searchParams.set("address", connectedAddress);
}
const res = await fetch(
`/api/auth/ensure-login?${searchParams.toString()}`,
{
method: "GET",
},
);
return (await res.json()) as EnsureLoginResponse;
},
onSuccess: (data) => {
if (data.redirectTo) {
router.replace(data.redirectTo);
}
if (data.jwt) {
// necessary for legacy things for now (SDK picks it up from there)
// eslint-disable-next-line react-compiler/react-compiler
window.TW_AUTH_TOKEN = data.jwt;
} else {
window.TW_AUTH_TOKEN = undefined;
}
},
});
// if we are "disconnected" we are not logged in
if (connectionStatus === "disconnected") {
return {
user: undefined,
isLoading: userQuery.isLoading,
isLoading: false,
isLoggedIn: false,
user: null,
};
}
return userQuery;
// if we are still connecting, we are "loading"
if (connectionStatus === "connecting") {
return {
isLoading: true,
isLoggedIn: false,
user: null,
};
}
// same if we do not yet have a path
if (!pathname) {
return {
isLoading: true,
isLoggedIn: false,
user: null,
};
}
// if we do not have an address we are not logged in
if (!connectedAddress) {
return {
isLoading: false,
isLoggedIn: false,
user: null,
};
}
// if we are not on a logged in path, we can simply return the connected address
if (!LOGGED_IN_ONLY_PATHS.some((path) => pathname.startsWith(path))) {
return {
isLoading: false,
isLoggedIn: true,
user: { address: connectedAddress },
};
}
// otherwise we return the query data
return {
isLoading: query.isLoading,
isLoggedIn: query.data ? query.data.isLoggedIn : false,
user: query.data?.isLoggedIn
? { address: connectedAddress, jwt: query.data.jwt }
: null,
};
}
@@ -1,5 +1,5 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useAddress, useSDK, useSigner } from "@thirdweb-dev/react";
import { useSigner } from "@thirdweb-dev/react";
import {
addContractToMultiChainRegistry,
getGaslessPolygonSDK,
@@ -13,6 +13,7 @@ import { defineDashboardChain } from "lib/v5-adapter";
import { useMemo } from "react";
import { getContract } from "thirdweb";
import { polygon } from "thirdweb/chains";
import { useActiveAccount } from "thirdweb/react";
import invariant from "tiny-invariant";
const MULTICHAIN_REGISTRY_ADDRESS =
@@ -95,7 +96,7 @@ type RemoveContractParams = {
};
export function useRemoveContractMutation() {
const walletAddress = useAddress();
const walletAddress = useActiveAccount()?.address;
const signer = useSigner();
const { chainIdToChainRecord } = useAllChainsData();
@@ -133,23 +134,21 @@ type AddContractParams = {
};
export function useAddContractMutation() {
const sdk = useSDK();
const walletAddress = useAddress();
const signer = useSigner();
const account = useActiveAccount();
const queryClient = useQueryClient();
return useMutation(
async (data: AddContractParams) => {
invariant(walletAddress, "cannot add a contract without an address");
invariant(sdk, "sdk not provided");
invariant(account, "cannot add a contract without an address");
return await addContractToMultiChainRegistry(
{
address: data.contractAddress,
chainId: data.chainId,
},
signer,
account,
300000n,
);
},
{
@@ -1,23 +0,0 @@
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { useSDK } from "@thirdweb-dev/react";
import invariant from "tiny-invariant";
import { walletKeys } from "../cache-keys";
type TransferInput = {
address: string;
amount: string;
};
export function useTransferNativeToken() {
const sdk = useSDK();
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (input: TransferInput) => {
invariant(sdk, "SDK is not initialized");
await sdk.wallet.transfer(input.address, input.amount);
},
onSuccess: (_, variables) => {
queryClient.invalidateQueries(walletKeys.balances(variables.address));
},
});
}
@@ -1,12 +1,8 @@
import {
type RequiredParam,
useAddress,
useContract,
useContractMetadata,
useSDK,
} from "@thirdweb-dev/react";
import { useContract, useContractMetadata, useSDK } from "@thirdweb-dev/react";
import type { Vote, VoteType } from "@thirdweb-dev/sdk";
import { useActiveAccount } from "thirdweb/react";
import invariant from "tiny-invariant";
import type { RequiredParam } from "utils/types";
import { voteKeys } from "../cache-keys";
import {
useMutationWithInvalidate,
@@ -27,7 +23,7 @@ export function useHasVotedOnProposal(
contract: RequiredParam<Vote>,
proposalId: string,
) {
const address = useAddress();
const address = useActiveAccount()?.address;
return useQueryWithNetwork(
voteKeys.userHasVotedOnProposal(
proposalId,
@@ -56,7 +52,7 @@ export function useCanExecuteProposal(
export function useTokensDelegated(contract?: Vote) {
const sdk = useSDK();
const address = useAddress();
const address = useActiveAccount()?.address;
return useQueryWithNetwork(
voteKeys.delegation(contract?.getAddress(), address),
@@ -127,7 +123,7 @@ export function useProposalCreateMutation(contractAddress?: string) {
export function useDelegateMutation(contract?: Vote) {
const sdk = useSDK();
const address = useAddress();
const address = useActiveAccount()?.address;
const contractAddress = contract?.getAddress();
@@ -159,7 +155,7 @@ export function useCastVoteMutation(
contract: RequiredParam<Vote>,
proposalId: string,
) {
const address = useAddress();
const address = useActiveAccount()?.address;
const contractAddress = contract?.getAddress();
return useMutationWithInvalidate(
@@ -1,11 +1,11 @@
import { useAddress } from "@thirdweb-dev/react";
import type { WalletNFTApiReturn } from "pages/api/wallet/nfts/[chainId]";
import { useActiveAccount } from "thirdweb/react";
import { useQueryWithNetwork } from "./query/useQueryWithNetwork";
import { useDashboardEVMChainId } from "./useActiveChainId";
export function useWalletNFTs(walletAddress?: string) {
const activeChainId = useDashboardEVMChainId();
const connectedAddress = useAddress();
const connectedAddress = useActiveAccount()?.address;
const address = walletAddress || connectedAddress;
@@ -0,0 +1,143 @@
"use client";
import { Spinner } from "@/components/ui/Spinner/Spinner";
import { Button } from "@/components/ui/button";
import { THIRDWEB_ENGINE_FAUCET_WALLET } from "@/constants/env";
import { CustomConnectWallet } from "@3rdweb-sdk/react/components/connect-wallet";
import { useMutation } from "@tanstack/react-query";
import { thirdwebClient } from "lib/thirdweb-client";
import { useRouter } from "next/navigation";
import { toast } from "sonner";
import { defineChain, toUnits } from "thirdweb";
import type { ChainMetadata } from "thirdweb/chains";
import { useActiveAccount, useWalletBalance } from "thirdweb/react";
function formatTime(seconds: number) {
const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" });
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
if (hours > 0) {
return rtf.format(+hours, "hour");
}
if (minutes > 0) {
return rtf.format(+minutes, "minute");
}
return rtf.format(+seconds, "second");
}
export function FaucetButton({
chain,
ttlSeconds,
amount,
}: {
chain: ChainMetadata;
ttlSeconds: number;
amount: string;
}) {
const address = useActiveAccount()?.address;
const chainId = chain.chainId;
const definedChain = defineChain(chainId);
const faucetWalletBalanceQuery = useWalletBalance({
address: THIRDWEB_ENGINE_FAUCET_WALLET,
chain: definedChain,
client: thirdwebClient,
});
const claimMutation = useMutation({
mutationFn: async () => {
const response = await fetch("/api/testnet-faucet/claim", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
chainId: chainId,
toAddress: address,
amount,
}),
});
if (!response.ok) {
const data = await response.json();
throw data.error;
}
},
onSuccess: () => {
router.refresh();
},
});
const router = useRouter();
const isFaucetEmpty =
faucetWalletBalanceQuery.data !== undefined &&
faucetWalletBalanceQuery.data.value < toUnits("1", 17);
// checking faucet balance
if (faucetWalletBalanceQuery.isLoading) {
return (
<Button variant="secondary" className="w-full gap-2">
Checking Faucet Balance <Spinner className="size-3" />
</Button>
);
}
// faucet is empty
if (isFaucetEmpty) {
return (
<Button variant="outline" disabled className="w-full">
Faucet is empty right now, come back later
</Button>
);
}
// not eligible to claim right now
if (ttlSeconds > 0) {
return (
<Button variant="outline" className="w-full" disabled>
Your next claim is available {formatTime(ttlSeconds)}
</Button>
);
}
if (!address) {
return (
<CustomConnectWallet
loginRequired={false}
connectButtonClassName="!w-full !rounded !bg-primary !text-primary-foreground !px-4 !py-2 !text-sm"
/>
);
}
// eligible to claim and faucet has balance
return (
<div className="flex flex-col w-full 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.isLoading ? (
<>
Claiming <Spinner className="size-3" />
</>
) : (
`Get ${amount} ${chain.nativeCurrency.symbol}`
)}
</Button>
{faucetWalletBalanceQuery.data && (
<p className="mt-3 text-xs text-secondary-foreground">
{Number(faucetWalletBalanceQuery.data.displayValue).toFixed(3)}{" "}
{faucetWalletBalanceQuery.data.symbol} left in the faucet
</p>
)}
</div>
);
}
@@ -0,0 +1,34 @@
"use client";
import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
import { MenuIcon } from "lucide-react";
import { useState } from "react";
import type { ChainMetadata } from "thirdweb/chains";
import { SidebarContent } from "../server/sidebar-content";
export function MobileMenu(props: {
chain: ChainMetadata;
}) {
const [isOpen, setIsOpen] = useState(false);
return (
<Dialog open={isOpen} onOpenChange={setIsOpen}>
<DialogTrigger asChild>
<Button size="icon" variant="outline" className="lg:hidden">
<MenuIcon strokeWidth={1} />
</Button>
</DialogTrigger>
<DialogContent
className="p-0"
dialogCloseClassName="hidden"
onClick={(e) => {
if (e.target instanceof HTMLAnchorElement) {
setIsOpen(false);
}
}}
>
<SidebarContent chain={props.chain} />
</DialogContent>
</Dialog>
);
}
@@ -0,0 +1,42 @@
"use client";
import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
import { thirdwebClient } from "@/constants/client";
import { useTheme } from "next-themes";
import { defineChain } from "thirdweb";
import { PayEmbed } from "thirdweb/react";
import { getSDKTheme } from "../../../../../../components/sdk-component-theme";
export function PayModalButton(props: { chainId: number; label: string }) {
const { theme } = useTheme();
return (
<Dialog>
<DialogTrigger asChild>
<Button variant="primary" className="w-full">
{props.label}
</Button>
</DialogTrigger>
<DialogContent
className="md:max-w-[360px] p-0 border-none bg-transparent"
dialogOverlayClassName="backdrop-blur-lg"
dialogCloseClassName="focus:ring-0"
>
<PayEmbed
client={thirdwebClient}
theme={getSDKTheme(theme === "dark" ? "dark" : "light")}
className="!w-auto"
payOptions={{
prefillBuy: {
chain: defineChain(props.chainId),
allowEdits: {
chain: false,
amount: true,
token: true,
},
},
}}
/>
</DialogContent>
</Dialog>
);
}
@@ -0,0 +1,68 @@
"use client";
import { Spinner } from "@/components/ui/Spinner/Spinner";
import { Button } from "@/components/ui/button";
import { ToolTipLabel } from "@/components/ui/tooltip";
import { useCustomConnectModal } from "@3rdweb-sdk/react/components/connect-wallet";
import { useMutation } from "@tanstack/react-query";
import { toast } from "sonner";
import type { Chain } from "thirdweb";
import {
useActiveAccount,
useActiveWalletChain,
useSwitchActiveWalletChain,
} from "thirdweb/react";
import { useDebounce } from "use-debounce";
type AddChainToWalletProps = {
chain: Chain;
};
export const AddChainToWallet: React.FC<AddChainToWalletProps> = (props) => {
const account = useActiveAccount();
const switchChain = useSwitchActiveWalletChain();
const activeWalletChainId = useActiveWalletChain()?.id;
const customConnectModal = useCustomConnectModal();
const switchChainMutation = useMutation({
mutationFn: async () => {
await switchChain(props.chain);
},
});
const [debouncedLoading] = useDebounce(switchChainMutation.isLoading, 50);
const disabled = debouncedLoading || activeWalletChainId === props.chain?.id;
return (
<ToolTipLabel
label={
activeWalletChainId === props.chain.id
? "Wallet is already connected to this chain"
: undefined
}
>
<Button
disabled={disabled}
className="gap-2 w-full"
variant="outline"
onClick={() => {
// Connct directly to this chain
if (!account) {
return customConnectModal({ chain: props.chain });
}
// switch to this chain
const switchPromise = switchChainMutation.mutateAsync();
toast.promise(switchPromise, {
success: `${props.chain.name} added to wallet`,
error: `Failed to add ${props.chain.name} to wallet`,
});
}}
>
<span>Add to wallet</span>
{debouncedLoading && <Spinner className="size-3" />}
</Button>
</ToolTipLabel>
);
};
@@ -1,6 +1,6 @@
"use client";
import { CopyButton } from "@/components/ui/CopyButton";
import { CopyTextButton } from "@/components/ui/CopyTextButton";
import { Skeleton } from "@/components/ui/skeleton";
import { ToolTipLabel } from "@/components/ui/tooltip";
import { useQuery } from "@tanstack/react-query";
@@ -9,7 +9,7 @@ import { thirdwebClient } from "lib/thirdweb-client";
import { CircleCheck, XIcon } from "lucide-react";
import { useState } from "react";
import { hostnameEndsWith } from "utils/url";
import { PrimaryInfoItem } from "../../../components/server/primary-info-item";
import { PrimaryInfoItem } from "../server/primary-info-item";
function useChainStatswithRPC(_rpcUrl: string) {
const [shouldRefetch, setShouldRefetch] = useState(true);
@@ -69,29 +69,34 @@ export function ChainLiveStats(props: { rpc: string }) {
titleIcon={
stats.isSuccess ? (
<ToolTipLabel label="Working">
<CircleCheck className="size-4 text-success-foreground" />
<CircleCheck className="size-4 text-success-text" />
</ToolTipLabel>
) : stats.isError ? (
<ToolTipLabel label="Not Working">
<XIcon className="size-4 text-destructive-foreground" />
<XIcon className="size-4 text-destructive-text" />
</ToolTipLabel>
) : null
}
>
<div className="flex items-center gap-1">
<div className="text-lg">{new URL(props.rpc).origin}</div>
<CopyButton text={new URL(props.rpc).origin} />
<CopyTextButton
tooltip="Copy RPC URL"
textToShow={new URL(props.rpc).origin}
textToCopy={props.rpc}
copyIconPosition="right"
variant="ghost"
className="px-2 py-1 -translate-x-2 text-base"
iconClassName="size-4"
/>
</div>
</PrimaryInfoItem>
{/* Latency */}
<PrimaryInfoItem title="RPC Latency" titleIcon={<PulseDot />}>
{stats.isError ? (
<p className="text-lg fade-in-0 animate-in text-destructive-foreground">
N/A
</p>
<p className="fade-in-0 animate-in text-destructive-text">N/A</p>
) : stats.data ? (
<p className="text-lg fade-in-0 animate-in">{stats.data.latency}ms</p>
<p className="fade-in-0 animate-in">{stats.data.latency}ms</p>
) : (
<div className="flex py-1 h-[28px] w-[70px]">
<Skeleton className="h-full w-full" />
@@ -102,13 +107,9 @@ export function ChainLiveStats(props: { rpc: string }) {
{/* Block Height */}
<PrimaryInfoItem title="Block Height" titleIcon={<PulseDot />}>
{stats.isError ? (
<p className="text-lg fade-in-0 animate-in text-destructive-foreground">
N/A
</p>
<p className="fade-in-0 animate-in text-destructive-text">N/A</p>
) : stats.data ? (
<p className="text-lg fade-in-0 animate-in">
{stats.data.blockNumber}
</p>
<p className="fade-in-0 animate-in">{stats.data.blockNumber}</p>
) : (
<div className="flex py-1 h-[28px] w-[140px]">
<Skeleton className="h-full w-full" />
@@ -122,9 +123,9 @@ export function ChainLiveStats(props: { rpc: string }) {
function PulseDot() {
return (
<ToolTipLabel label={"Live Data"}>
<span className="relative flex size-3">
<span className="relative flex size-2">
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-sky-400 opacity-75" />
<span className="relative inline-flex rounded-full size-3 bg-primary" />
<span className="relative inline-flex rounded-full size-2 bg-primary" />
</span>
</ToolTipLabel>
);
@@ -0,0 +1,24 @@
"use client";
import { cn } from "@/lib/utils";
import Link from "next/link";
import { usePathname } from "next/navigation";
export type NavButtonProps = {
className?: string;
activeClassName?: string;
href: string;
};
export function NavLink(props: React.PropsWithChildren<NavButtonProps>) {
const pathname = usePathname();
const isActive = pathname === props.href;
return (
<Link
href={props.href}
className={cn(props.className, isActive && props.activeClassName)}
>
{props.children}
</Link>
);
}
@@ -0,0 +1,89 @@
export function CreditCardIcon(props: {
bg: string;
className?: string;
}) {
return (
<svg
width={48}
height={48}
viewBox="0 0 48 48"
fill="none"
xmlns="http://www.w3.org/2000/svg"
aria-hidden="true"
className={props.className}
>
<rect width={48} height={48} rx={16} fill={props.bg} />
<rect
x={1}
y={1}
width={46}
height={46}
rx={15}
stroke="url(#paint0_linear_1315_3638)"
strokeOpacity="0.2"
strokeWidth={2}
/>
<rect x={5} y={5} width={38} height={38} rx={11} fill={props.bg} />
<rect
x={5}
y={5}
width={38}
height={38}
rx={11}
stroke="url(#paint1_linear_1315_3638)"
strokeWidth={2}
/>
<path
d="M32.3337 22.3333H15.667M23.167 25.6666H19.0003M15.667 20.8333L15.667 27.1666C15.667 28.1 15.667 28.5668 15.8486 28.9233C16.0084 29.2369 16.2634 29.4918 16.577 29.6516C16.9335 29.8333 17.4002 29.8333 18.3337 29.8333L29.667 29.8333C30.6004 29.8333 31.0671 29.8333 31.4236 29.6516C31.7372 29.4918 31.9922 29.2369 32.152 28.9233C32.3337 28.5668 32.3337 28.1 32.3337 27.1666V20.8333C32.3337 19.8999 32.3337 19.4332 32.152 19.0766C31.9922 18.763 31.7372 18.5081 31.4236 18.3483C31.0671 18.1666 30.6004 18.1666 29.667 18.1666L18.3337 18.1666C17.4002 18.1666 16.9335 18.1666 16.577 18.3483C16.2634 18.5081 16.0084 18.763 15.8486 19.0766C15.667 19.4332 15.667 19.8999 15.667 20.8333Z"
stroke="url(#paint2_linear_1315_3638)"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
<defs>
<linearGradient
id="paint0_linear_1315_3638"
x1="-3.26045"
y1="15.4021"
x2="45.7807"
y2="50.1547"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#F213A4" />
<stop offset="0.1517" stopColor="#E011A7" />
<stop offset="0.4554" stopColor="#B20DAF" />
<stop offset="0.8789" stopColor="#6806BB" />
<stop offset={1} stopColor="#5204BF" />
</linearGradient>
<linearGradient
id="paint1_linear_1315_3638"
x1="1.28296"
y1="16.835"
x2="42.1506"
y2="45.7956"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#F213A4" />
<stop offset="0.1517" stopColor="#E011A7" />
<stop offset="0.4554" stopColor="#B20DAF" />
<stop offset="0.8789" stopColor="#6806BB" />
<stop offset={1} stopColor="#5204BF" />
</linearGradient>
<linearGradient
id="paint2_linear_1315_3638"
x1="14.5349"
y1="21.9102"
x2="27.1676"
y2="34.6989"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#F213A4" />
<stop offset="0.1517" stopColor="#E011A7" />
<stop offset="0.4554" stopColor="#B20DAF" />
<stop offset="0.8789" stopColor="#6806BB" />
<stop offset={1} stopColor="#5204BF" />
</linearGradient>
</defs>
</svg>
);
}
@@ -0,0 +1,98 @@
export function GiftIcon(props: {
bg: string;
className?: string;
}) {
return (
<svg
width={48}
height={48}
viewBox="0 0 48 48"
fill="none"
xmlns="http://www.w3.org/2000/svg"
aria-hidden="true"
>
<rect width={48} height={48} rx={16} fill={props.bg} />
<rect
x={1}
y={1}
width={46}
height={46}
rx={15}
stroke="url(#paint0_linear_1214_43510)"
strokeOpacity="0.2"
strokeWidth={2}
/>
<rect x={5} y={5} width={38} height={38} rx={11} fill={props.bg} />
<rect
x={5}
y={5}
width={38}
height={38}
rx={11}
stroke="url(#paint1_linear_1214_43510)"
strokeWidth={2}
/>
<g clipPath="url(#clip0_1214_43510)">
<path
d="M23.9993 19.0001V32.3334M23.9993 19.0001H21.0529C20.6188 19.0001 20.2024 18.8245 19.8955 18.5119C19.5885 18.1994 19.416 17.7754 19.416 17.3334C19.416 16.8914 19.5885 16.4675 19.8955 16.1549C20.2024 15.8423 20.6188 15.6667 21.0529 15.6667C23.3446 15.6667 23.9993 19.0001 23.9993 19.0001ZM23.9993 19.0001H26.9458C27.3799 19.0001 27.7963 18.8245 28.1032 18.5119C28.4102 18.1994 28.5827 17.7754 28.5827 17.3334C28.5827 16.8914 28.4102 16.4675 28.1032 16.1549C27.7963 15.8423 27.3799 15.6667 26.9458 15.6667C24.6541 15.6667 23.9993 19.0001 23.9993 19.0001ZM30.666 23.1667V29.6667C30.666 30.6002 30.666 31.0669 30.4844 31.4234C30.3246 31.737 30.0696 31.992 29.756 32.1518C29.3995 32.3334 28.9328 32.3334 27.9993 32.3334L19.9993 32.3334C19.0659 32.3334 18.5992 32.3334 18.2427 32.1518C17.9291 31.992 17.6741 31.737 17.5143 31.4234C17.3327 31.0669 17.3327 30.6002 17.3327 29.6667V23.1667M15.666 20.3334L15.666 21.8334C15.666 22.3001 15.666 22.5335 15.7568 22.7117C15.8367 22.8685 15.9642 22.996 16.121 23.0759C16.2993 23.1667 16.5326 23.1667 16.9993 23.1667L30.9994 23.1667C31.4661 23.1667 31.6994 23.1667 31.8777 23.0759C32.0345 22.996 32.162 22.8685 32.2419 22.7117C32.3327 22.5335 32.3327 22.3001 32.3327 21.8334V20.3334C32.3327 19.8667 32.3327 19.6333 32.2419 19.4551C32.162 19.2983 32.0345 19.1708 31.8777 19.0909C31.6994 19.0001 31.4661 19.0001 30.9993 19.0001L16.9993 19.0001C16.5326 19.0001 16.2993 19.0001 16.121 19.0909C15.9642 19.1708 15.8367 19.2983 15.7568 19.4551C15.666 19.6333 15.666 19.8667 15.666 20.3334Z"
stroke="url(#paint2_linear_1214_43510)"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</g>
<defs>
<linearGradient
id="paint0_linear_1214_43510"
x1="-3.26045"
y1="15.4021"
x2="45.7807"
y2="50.1547"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#F213A4" />
<stop offset="0.1517" stopColor="#E011A7" />
<stop offset="0.4554" stopColor="#B20DAF" />
<stop offset="0.8789" stopColor="#6806BB" />
<stop offset={1} stopColor="#5204BF" />
</linearGradient>
<linearGradient
id="paint1_linear_1214_43510"
x1="1.28296"
y1="16.835"
x2="42.1506"
y2="45.7956"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#F213A4" />
<stop offset="0.1517" stopColor="#E011A7" />
<stop offset="0.4554" stopColor="#B20DAF" />
<stop offset="0.8789" stopColor="#6806BB" />
<stop offset={1} stopColor="#5204BF" />
</linearGradient>
<linearGradient
id="paint2_linear_1214_43510"
x1="14.5339"
y1="21.0147"
x2="31.5621"
y2="33.0816"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#F213A4" />
<stop offset="0.1517" stopColor="#E011A7" />
<stop offset="0.4554" stopColor="#B20DAF" />
<stop offset="0.8789" stopColor="#6806BB" />
<stop offset={1} stopColor="#5204BF" />
</linearGradient>
<clipPath id="clip0_1214_43510">
<rect
width={20}
height={20}
fill="white"
transform="translate(14 14)"
/>
</clipPath>
</defs>
</svg>
);
}
@@ -0,0 +1,61 @@
import { ExternalLinkIcon } from "lucide-react";
import Link from "next/link";
import type { ChainMetadata } from "thirdweb/chains";
import { ChainIcon } from "../../../../components/server/chain-icon";
import { PayModalButton } from "../client/PayModal";
import { CreditCardIcon } from "../icons/CreditCardIcon";
import { SectionTitle } from "./SectionTitle";
export function BuyFundsSection(props: { chain: ChainMetadata }) {
const sanitizedChainName = props.chain.name.replace("Mainnet", "").trim();
return (
<section>
<SectionTitle title="Buy Funds" />
<div className="border border-border px-4 py-10 rounded-lg flex justify-center">
<div className="max-w-[520px] flex flex-col items-center ">
<div className="flex items-center">
<ChainIcon
className="size-12 -mr-2 rounded-full border p-1"
iconUrl={props.chain.icon?.url}
/>
<CreditCardIcon
bg="hsl(var(--background))"
className="size-12 -ml-2"
/>
</div>
<div className="h-6" />
<h2 className="text-lg tracking-tight font-semibold text-center px-4">
Buy Funds on {sanitizedChainName} using thirdweb Pay
</h2>
<div className="h-2" />
<p className="text-secondary-foreground text-sm max-w-[520px] text-center px-4">
Instantly onramp, bridge & swap into {sanitizedChainName} with any
token.
</p>
<div className="h-8" />
<PayModalButton
chainId={props.chain.chainId}
label={`Buy Funds on ${sanitizedChainName}`}
/>
<div className="h-4" />
<Link
href="https://portal.thirdweb.com/connect/pay/overview"
className="inline-flex gap-1.5 items-center text-sm text-secondary-foreground hover:text-foreground"
>
Learn more about thirdweb Pay{" "}
<ExternalLinkIcon className="size-3" />
</Link>
</div>
</div>
</section>
);
}
@@ -0,0 +1,52 @@
import { CopyTextButton } from "@/components/ui/CopyTextButton";
import { ExternalLinkIcon } from "lucide-react";
import Link from "next/link";
import React from "react";
import type { ChainMetadata } from "thirdweb/chains";
import { ChainLiveStats } from "../client/live-stats";
import { SectionTitle } from "./SectionTitle";
import { PrimaryInfoItem } from "./primary-info-item";
export function ChainOverviewSection(props: { chain: ChainMetadata }) {
const { chain } = props;
return (
<section>
<SectionTitle title="Chain Overview" />
<div className="grid grid-cols-1 gap-6 lg:gap-8 md:grid-cols-2 lg:grid-cols-3 border rounded-lg p-4 md:p-6">
{/* Info */}
{chain.infoURL && (
<PrimaryInfoItem title="Info">
<Link
href={chain.infoURL}
target="_blank"
className="inline-flex items-center gap-1.5 hover:text-link-foreground"
>
{new URL(chain.infoURL).hostname}
<ExternalLinkIcon className="size-4" />
</Link>
</PrimaryInfoItem>
)}
{/* Chain Id */}
<PrimaryInfoItem title="Chain ID">
<CopyTextButton
textToCopy={chain.chainId.toString()}
textToShow={chain.chainId.toString()}
tooltip="Copy Chain ID"
variant="ghost"
className="-translate-x-2 py-1 px-2 text-base"
iconClassName="size-4"
copyIconPosition="right"
/>
</PrimaryInfoItem>
{/* Native token */}
<PrimaryInfoItem title="Native Token">
{chain.nativeCurrency.name} ({chain.nativeCurrency.symbol})
</PrimaryInfoItem>
{chain.rpc[0] && <ChainLiveStats rpc={chain.rpc[0]} />}
</div>
</section>
);
}
@@ -0,0 +1,30 @@
import { Button } from "@/components/ui/button";
import { ExternalLinkIcon } from "lucide-react";
import Link from "next/link";
import { SectionTitle } from "./SectionTitle";
export function ClaimChainSection() {
return (
<section>
<SectionTitle title="Claim Chain" />
<div className="border p-4 rounded-lg">
<p className="mb-1"> This chain page is unclaimed </p>
<p className="text-secondary-foreground text-sm mb-5">
Are you the owner of this ecosystem? Claim this page to add additional
information on this page to help your developers get started!
</p>
<Button variant="outline" asChild>
<Link
className="gap-2"
href="https://share.hsforms.com/1o01TyfsZRAao2eCrzuXSVgea58c"
target="_blank"
>
<span>Claim Chain</span>
<ExternalLinkIcon className="size-4 -mt-[3px]" />
</Link>
</Button>
</div>
</section>
);
}
@@ -0,0 +1,57 @@
import { getIpAddress } from "lib/ip";
import { cacheTtl } from "lib/redis";
import type { ChainMetadata } from "thirdweb/chains";
import { ChainIcon } from "../../../../components/server/chain-icon";
import { FaucetButton } from "../client/FaucetButton";
import { GiftIcon } from "../icons/GiftIcon";
import { SectionTitle } from "./SectionTitle";
const amountToGive = "0.1";
export async function FaucetSection(props: { chain: ChainMetadata }) {
const { chain } = props;
// Check eligibilty.
const ipAddress = getIpAddress();
const cacheKey = `testnet-faucet:${chain.chainId}:${ipAddress}`;
const ttlSeconds = await cacheTtl(cacheKey);
const sanitizedChainName = chain.name.replace("Mainnet", "").trim();
return (
<section>
<SectionTitle title="Faucet" />
<div className="border border-border px-4 py-10 rounded-lg flex justify-center">
<div className="max-w-[520px] w-full flex flex-col items-center ">
<div className="flex items-center">
<ChainIcon
className="size-12 -mr-2 rounded-full border p-1"
iconUrl={props.chain.icon?.url}
/>
<GiftIcon bg="hsl(var(--background))" className="size-12 -ml-2" />
</div>
<div className="h-6" />
<h2 className="text-lg tracking-tight font-semibold text-center px-4">
{sanitizedChainName} Faucet
</h2>
<div className="h-2" />
<p className="text-secondary-foreground text-sm max-w-[520px] text-center px-4">
Get free {chain.nativeCurrency.symbol} fast and reliably.{" "}
{amountToGive} {chain.nativeCurrency.symbol}/day.
</p>
<div className="h-8" />
<FaucetButton
chain={chain}
ttlSeconds={ttlSeconds}
amount={amountToGive}
/>
</div>
</div>
</section>
);
}
@@ -0,0 +1,5 @@
export function SectionTitle(props: { title: string }) {
return (
<h2 className="text-xl tracking-tight mb-2 font-semibold">{props.title}</h2>
);
}
@@ -0,0 +1,53 @@
import { CircleCheckIcon } from "lucide-react";
import Link from "next/link";
import { products } from "../../../../components/server/products";
import type { ChainMetadataWithServices } from "../../../../types/chain";
import { SectionTitle } from "./SectionTitle";
export function SupportedProductsSection(props: {
services: ChainMetadataWithServices["services"];
}) {
const enabledProducts = products.filter((product) => {
return props.services.find(
(service) => service.service === product.id && service.enabled,
);
});
if (enabledProducts.length === 0) {
return null;
}
return (
<section>
<SectionTitle title="thirdweb Products" />
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4">
{enabledProducts.map((product) => {
return (
<div
key={product.id}
className="border rounded-lg p-4 flex gap-3 relative hover:bg-secondary transition-colors duration-300 pr-8"
>
<CircleCheckIcon className="size-5 text-success-text absolute top-4 right-4" />
<product.icon className="size-5 shrink-0 mt-0.5" />
<div>
<h3 className="font-medium mb-1.5">
<Link
href={product.link}
className="before:absolute before:inset-0"
target="_blank"
>
{" "}
{product.name}{" "}
</Link>
</h3>
<p className="text-sm text-secondary-foreground">
{product.description}
</p>
</div>
</div>
);
})}
</div>
</section>
);
}
@@ -0,0 +1,65 @@
import { AspectRatio } from "@/components/ui/aspect-ratio";
import { Button } from "@/components/ui/button";
import Link from "next/link";
import { defineChain } from "thirdweb";
import type { ChainMetadata } from "thirdweb/chains";
import { ChainIcon } from "../../../../components/server/chain-icon";
import { MobileMenu } from "../client/MobileMenu";
import { AddChainToWallet } from "../client/add-chain-to-wallet";
type ChainHeaderProps = {
headerImageUrl?: string;
logoUrl?: string;
chain: ChainMetadata;
};
// TODO: improve the behavior when clicking "Get started with thirdweb", currently just redirects to the dashboard
export function ChainHeader(props: ChainHeaderProps) {
return (
// force the banner image to be 4:1 aspect ratio and full-width on mobile devices
<div className="flex flex-col">
{!props.headerImageUrl && <div className="h-8 md:hidden" />}
<AspectRatio
ratio={props.headerImageUrl ? 4 : 8}
className="border-b border-border -mx-4 lg:-mx-6"
>
{props.headerImageUrl && (
// eslint-disable-next-line @next/next/no-img-element
<img
src={props.headerImageUrl}
alt=""
className="object-cover object-center h-full w-full"
/>
)}
</AspectRatio>
{/* below header */}
<div className="relative flex flex-row justify-end items-end">
{/* chain logo */}
<ChainIcon
iconUrl={props.logoUrl}
className="p-2 lg:p-4 absolute top-0 left-0 size-20 lg:size-36 rounded-full bg-background -translate-y-[50%] overflow-hidden border border-border"
/>
{/* action group */}
<div className="pt-3 lg:pt-6">
{/* Desktop only */}
<div className="hidden lg:flex flex-row gap-2">
<AddChainToWallet chain={defineChain(props.chain)} />
<Button variant="primary" asChild>
<Link href="https://thirdweb.com/dashboard" target="_blank">
Get started with thirdweb
</Link>
</Button>
</div>
{/* Mobile Menu */}
<MobileMenu chain={props.chain} />
</div>
</div>
</div>
);
}
@@ -0,0 +1,44 @@
import { Button } from "@/components/ui/button";
import Link from "next/link";
export type ChainCTAProps = {
backgroundImageUrl: string;
title: string;
description?: string;
buttonText: string;
buttonLink: string;
};
export function ChainCTA(props: ChainCTAProps) {
return (
<div
className="bg-cover bg-center bg-no-repeat rounded-xl border border-border overflow-hidden"
style={{
backgroundImage: `url(${props.backgroundImageUrl})`,
}}
>
<div className="grid items-center justify-center gap-6 p-8 md:grid-cols-[1fr_auto] md:gap-12 bg-gradient-to-r from-background to-background/90">
<div className="space-y-4 text-center md:text-left">
<h2 className="text-2xl md:text-3xl font-bold tracking-tighter text-foreground md:max-w-[85%]">
{props.title}
</h2>
{props.description && (
<p className="max-w-[600px] text-secondary-foreground leading-relaxed text-sm md:text-base">
{props.description}
</p>
)}
</div>
<Button asChild>
<Link
href={props.buttonLink}
prefetch={false}
target={props.buttonLink.startsWith("http") ? "_blank" : undefined}
className="font-semibold"
>
{props.buttonText}
</Link>
</Button>
</div>
</div>
);
}
@@ -1,22 +1,22 @@
import { ExternalLinkIcon } from "lucide-react";
import Link from "next/link";
import type { ChainMetadataWithServices } from "../../../types/chain";
import type { ChainMetadataWithServices } from "../../../../types/chain";
import { SectionTitle } from "./SectionTitle";
export function ExplorersSection(props: {
explorers: NonNullable<ChainMetadataWithServices["explorers"]>;
}) {
return (
<div>
<h2 className="text-base text-muted-foreground mb-2 font-medium">
Explorers
</h2>
<section>
<SectionTitle title="Explorers" />
<div className="grid grid-cols-1 gap-3 md:gap-4 md:grid-cols-2 lg:grid-cols-3">
{props.explorers.map((explorer) => {
return (
<div
key={explorer.url}
className="p-4 border rounded-xl relative bg-secondary hover:bg-muted"
className="p-4 border rounded-xl relative hover:bg-secondary"
>
<ExternalLinkIcon className="size-4 absolute top-4 right-4 text-muted-foreground" />
<h3 className="mb-1 text-base font-semibold capitalize">
{explorer.name}
</h3>
@@ -29,11 +29,10 @@ export function ExplorersSection(props: {
? explorer.url.slice(0, -1)
: explorer.url}
</Link>
<ExternalLinkIcon className="size-4 absolute top-4 right-4 text-muted-foreground" />
</div>
);
})}
</div>
</div>
</section>
);
}
@@ -4,14 +4,14 @@ export function PrimaryInfoItem(props: {
children: React.ReactNode;
}) {
return (
<section className="border-b pb-4 lg:pb-6">
<div>
<div className="flex items-center gap-2">
<h2 className="text-base text-muted-foreground font-medium">
<h3 className="text-base text-muted-foreground font-medium">
{props.title}
</h2>
</h3>
{props.titleIcon}
</div>
{props.children}
</section>
</div>
);
}
@@ -0,0 +1,70 @@
import { ArrowLeftIcon } from "lucide-react";
import Link from "next/link";
import type React from "react";
import type { ChainMetadata } from "thirdweb/chains";
import { Button } from "../../../../../../../@/components/ui/button";
import { Separator } from "../../../../../../../@/components/ui/separator";
import { NavLink } from "../client/nav-link.client";
export type SidebarContentProps = {
chain: ChainMetadata;
};
export function SidebarContent(props: SidebarContentProps) {
return (
<div className="p-4 md:pt-8 sticky top-0">
{/* Desktop only */}
<div className="lg:flex items-center gap-1.5 mb-5 hidden flex-wrap">
<Link
href="/chainlist"
className="text-secondary-foreground hover:text-foreground text-sm"
>
Chainlist
</Link>
<span className="text-secondary-foreground text-sm"> / </span>
<Link href={`/${props.chain.slug}`} className="text-foreground text-sm">
{props.chain.name.replace("Mainnet", "")}
</Link>
</div>
<div className="flex flex-col gap-2 lg:gap-4 lg:border-l-2 lg:pl-1">
<SidebarNavLink href={`/${props.chain.slug}`} label="Overview" />
<SidebarNavLink
href={`/${props.chain.slug}/popular`}
label="Popular Contracts"
/>
</div>
{/* mobile obly */}
<div className="lg:hidden">
<Separator className="mt-10 mb-4" />
<SidebarNavLink
href="/chainlist"
label={
<>
<ArrowLeftIcon className="size-4" />
<span className="text-secondary-foreground">View all chains</span>
</>
}
/>
</div>
</div>
);
}
function SidebarNavLink(props: {
href: string;
label: React.ReactNode;
}) {
return (
<Button size="sm" variant="ghost" asChild>
<NavLink
href={props.href}
className="!text-left justify-start flex gap-2 h-auto py-3.5 lg:text-secondary-foreground before:absolute before:h-full relative before:w-[2px] before:-left-1.5 lg:py-0 lg:h-auto lg:hover:bg-transparent"
activeClassName="bg-accent lg:text-foreground lg:bg-transparent lg:before:bg-link-foreground "
>
{props.label}
</NavLink>
</Button>
);
}
@@ -0,0 +1,126 @@
import { Button } from "@/components/ui/button";
import { TicketCheckIcon } from "lucide-react";
import type { Metadata } from "next";
import Link from "next/link";
import { redirect } from "next/navigation";
import { defineChain } from "thirdweb";
import { StarButton } from "../../components/client/star-button";
import { getChain, getChainMetadata } from "../../utils";
import { AddChainToWallet } from "./components/client/add-chain-to-wallet";
import { ChainHeader } from "./components/server/chain-header";
import { SidebarContent } from "./components/server/sidebar-content";
// TODO: improve the behavior when clicking "Get started with thirdweb", currently just redirects to the dashboard
export async function generateMetadata({
params,
}: { params: { chain_id: string } }): Promise<Metadata> {
const chain = await getChain(params.chain_id);
const sanitizedChainName = chain.name.replace("Mainnet", "").trim();
const title = `${sanitizedChainName}: RPC and Chain Settings`;
const description = `Use the best ${sanitizedChainName} RPC and add to your wallet. Discover the chain ID, native token, explorers, and ${
chain.testnet && chain.faucets?.length ? "faucet options" : "more"
}.`;
return {
title,
description,
};
}
// this is the dashboard layout file
export default async function ChainPageLayout({
children,
params,
}: {
children: React.ReactNode;
params: { chain_id: string };
}) {
const chain = await getChain(params.chain_id);
if (params.chain_id !== chain.slug) {
redirect(chain.slug);
}
const chainMetadata = await getChainMetadata(chain.chainId);
return (
<div className="container flex flex-row h-full">
<aside className="w-[280px] flex-shrink-0 hidden lg:block">
<SidebarContent chain={chain} />
</aside>
<div className="flex flex-col w-full lg:px-6 lg:border-x pb-10">
{/* Icon + Background */}
<ChainHeader
headerImageUrl={chainMetadata?.headerImgUrl}
logoUrl={chain.icon?.url}
chain={chain}
/>
<div className="h-4 md:h-8" />
<div className="flex flex-col gap-3 md:gap-2">
{/* Gas Sponsored badge - Mobile */}
{chainMetadata?.gasSponsored && (
<div className="md:hidden flex">
<GasSponseredBadge />
</div>
)}
{/* Chain name */}
<div className="flex flex-row gap-1.5 items-center">
<h1 className="text-2xl font-semibold lg:text-3xl lg:font-semibold tracking-tight">
{chain.name}
</h1>
{/* Favorite */}
<StarButton
chainId={chain.chainId}
iconClassName="size-5"
className="p-1"
/>
{/* Gas Sponsored badge - Desktop */}
{chainMetadata?.gasSponsored && (
<div className="hidden md:block">
<GasSponseredBadge />
</div>
)}
</div>
{/* description */}
{chainMetadata?.about && (
<p className="text-secondary-foreground text-sm lg:text-base mb-2">
{chainMetadata.about}
</p>
)}
{/* mobile action row */}
<div className="sm:hidden w-full">
<div className="grid grid-cols-2 gap-2">
<AddChainToWallet chain={defineChain(chain)} />
<Button variant="primary">
<Link href="https://thirdweb.com/dashboard" target="_blank">
Get started
</Link>
</Button>
</div>
</div>
</div>
<div className="h-8" />
{children}
</div>
</div>
);
}
function GasSponseredBadge() {
return (
<div className="flex items-center gap-2 rounded-full text-[hsl(334,81.12%,69.65%)] bg-[hsla(335,57%,51%,0.2)] px-2.5 py-1">
<TicketCheckIcon className="size-4" />
<span className="font-medium text-xs">Gas Sponsored</span>
</div>
);
}
@@ -80,20 +80,23 @@ export default async function Image({
return new Response("Chain not found", { status: 400 });
}
// TODO: handle svg - doesn't work right now
const hasWorkingChainIcon = chain.icon?.url && chain.icon?.format !== "svg";
const [interBold, chainIcon, imageData] = await Promise.all([
// fetch the font we use
fetch(new URL("og-lib/fonts/inter/700.ttf", import.meta.url)).then((res) =>
res.arrayBuffer(),
),
// download the chain icon if there is one
chain.icon?.url
chain.icon?.url && hasWorkingChainIcon
? download({ uri: chain.icon.url, client: thirdwebClient }).then((res) =>
res.arrayBuffer(),
)
: undefined,
// download the background image (based on chain)
fetch(
chain.icon?.url
chain.icon?.url && hasWorkingChainIcon
? new URL(
"og-lib/assets/chain/bg-with-icon.png",
@@ -121,7 +124,7 @@ export default async function Image({
/>
{/* the actual component starts here */}
{chainIcon && (
{hasWorkingChainIcon && (
<img
alt=""
// @ts-expect-error - TS doesn't know about the ImageResponse component
@@ -0,0 +1,100 @@
import { Button } from "@/components/ui/button";
import { ArrowRightIcon, CircleAlertIcon } from "lucide-react";
import Link from "next/link";
import { type SortBy, fetchTopContracts } from "../../../../../lib/search";
import { TrendingContractSection } from "../../../trending/components/trending-table";
import { getChain, getChainMetadata } from "../../utils";
import { BuyFundsSection } from "./components/server/BuyFundsSection";
import { ChainOverviewSection } from "./components/server/ChainOverviewSection";
import { ClaimChainSection } from "./components/server/ClaimChainSection";
import { FaucetSection } from "./components/server/FaucetSection";
import { SupportedProductsSection } from "./components/server/SupportedProductsSection";
import { ChainCTA } from "./components/server/cta-card";
import { ExplorersSection } from "./components/server/explorer-section";
export default async function Page(props: {
params: { chain_id: string };
searchParams: { page?: number; sortBy?: SortBy };
}) {
const chain = await getChain(props.params.chain_id);
const chainMetadata = await getChainMetadata(chain.chainId);
const isDeprecated = chain.status === "deprecated";
const topContracts = await fetchTopContracts({
chainId: chain.chainId,
page: props.searchParams.page,
sortBy: props.searchParams.sortBy,
perPage: 3,
timeRange: "month",
});
return (
<div className="flex flex-col gap-10">
{/* Custom CTA */}
{(chainMetadata?.cta?.title || chainMetadata?.cta?.description) && (
<ChainCTA {...chainMetadata.cta} />
)}
{/* Deprecated Alert */}
{isDeprecated && (
<section className="bg-destructive rounded-lg text-destructive-foreground border border-destructive-foreground/20">
<div className="container py-4 flex flex-row items-center gap-4">
<CircleAlertIcon className="size-6 flex-shrink-0" />
<h3 className="font-medium">
This chain has been marked as deprecated. Some or all services may
no longer function.
</h3>
</div>
</section>
)}
{/* Buy Funds */}
{chain.services.find((c) => c.service === "pay" && c.enabled) && (
<BuyFundsSection chain={chain} />
)}
{/* Faucet */}
{chain.testnet && <FaucetSection chain={chain} />}
{/* Chain Overview */}
<ChainOverviewSection chain={chain} />
{/* Explorers */}
{chain.explorers && chain.explorers.length > 0 && (
<ExplorersSection explorers={chain.explorers} />
)}
{topContracts.length > 0 && (
<section>
<div className="mb-3 flex items-center justify-between">
<h2 className="text-xl tracking-tight font-semibold">
Popular Contracts
</h2>
<Button asChild variant="outline">
<Link
href={`/${chain.slug}/popular`}
className="flex gap-2 items-center"
>
See All
<ArrowRightIcon className="size-4" />
</Link>
</Button>
</div>
<TrendingContractSection
topContracts={topContracts}
chainId={chain.chainId}
searchParams={props.searchParams}
showPagination={false}
/>
</section>
)}
{chain.services.filter((s) => s.enabled).length > 0 && (
<SupportedProductsSection services={chain.services} />
)}
{/* Claim Chain */}
{!chainMetadata && <ClaimChainSection />}
</div>
);
}
@@ -0,0 +1,51 @@
import { CircleAlertIcon } from "lucide-react";
import React from "react";
import { type SortBy, fetchTopContracts } from "../../../../../../lib/search";
import { TrendingContractSection } from "../../../../trending/components/trending-table";
import { getChain } from "../../../utils";
export default async function Page(props: {
params: { chain_id: string };
searchParams: { page?: number; sortBy?: SortBy };
}) {
const chain = await getChain(props.params.chain_id);
const topContracts = await fetchTopContracts({
chainId: chain.chainId,
page: props.searchParams.page,
sortBy: props.searchParams.sortBy,
perPage: 15,
timeRange: "month",
});
return (
<section className="mt-2">
<h2 className="text-2xl tracking-tighter font-semibold mb-2">
Popular Contracts
</h2>
<p className="text-sm text-secondary-foreground">
Explore contracts on Ethereum and sort them by your preferred metrics
</p>
<div className="h-8" />
{topContracts.length > 0 && (
<TrendingContractSection
topContracts={topContracts}
chainId={chain.chainId}
searchParams={props.searchParams}
showPagination={true}
/>
)}
{topContracts.length === 0 && (
<div className="text-secondary-foreground text-lg flex border rounded-lg h-[200px] border-border items-center justify-center">
<div className="flex items-center gap-2">
<CircleAlertIcon className="size-5 text-destructive-text" />
No contracts found
</div>
</div>
)}
</section>
);
}

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

@@ -1,59 +0,0 @@
import { redirect } from "next/navigation";
import { getChain } from "../../utils";
import { InfoCard } from "../components/server/info-card";
export default async function Page(props: { params: { chain_id: string } }) {
const chain = await getChain(props.params.chain_id);
const enabled = chain.services.find(
(s) => s.service === "account-abstraction",
)?.enabled;
if (!enabled) {
redirect(`/${props.params.chain_id}`);
}
return (
<div>
<InfoCard
title="Account Abstraction"
links={[
{
label: "Get Started",
href: "/dashboard/connect/account-abstraction",
},
{
label: "Learn More",
href: "https://portal.thirdweb.com/connect/account-abstraction/how-it-works",
},
]}
>
<p>
Everything you need to leverage account abstraction technology to
enable seamless user experiences for your users.
</p>
<p>
You get all the tools to integrate account abstraction into your app.
This includes:
</p>
<div className="h-3" />
<ul className="text-secondary-foreground pl-4 [&_li]:list-disc [&_li]:mb-3 [&_li]:pl-1">
<li>
Account factory contracts that let you spin up smart accounts for
your users
</li>
<li>
Bundler, which is the infrastructure needed to process account
abstraction transactions (known as User Ops)
</li>
<li>
Paymaster, which lets you sponsor transaction fees for your users
</li>
</ul>
</InfoCard>
</div>
);
}
@@ -1,56 +0,0 @@
"use client";
import { Spinner } from "@/components/ui/Spinner/Spinner";
import { Button } from "@/components/ui/button";
import { ToolTipLabel } from "@/components/ui/tooltip";
import { useMutation } from "@tanstack/react-query";
import { useAddress, useChainId, useSwitchChain } from "@thirdweb-dev/react";
import { useDebounce } from "use-debounce";
type AddChainToWalletProps = {
chainId: number;
};
export const AddChainToWallet: React.FC<AddChainToWalletProps> = (props) => {
const address = useAddress();
const switchChain = useSwitchChain();
const activeWalletChainId = useChainId();
const switchChainMutation = useMutation({
mutationFn: async () => {
await switchChain(props.chainId);
},
});
// debounce the loading state to prevent flickering
const [debouncedLoading] = useDebounce(switchChainMutation.isLoading, 50);
const buttonContent = (
<Button
disabled={
!address || debouncedLoading || activeWalletChainId === props.chainId
}
className="w-full md:min-w-40"
onClick={() => switchChainMutation.mutate()}
>
{debouncedLoading && <Spinner />}
<span>Add to wallet</span>
</Button>
);
if (address && activeWalletChainId !== props.chainId) {
return buttonContent;
}
return (
<ToolTipLabel
label={
activeWalletChainId === props.chainId
? "You are already connected to this chain"
: "Connect your wallet first"
}
>
<div className="cursor-not-allowed">{buttonContent}</div>
</ToolTipLabel>
);
};
@@ -1,51 +0,0 @@
"use client";
import { TabLinks } from "@/components/ui/tabs";
import { useSelectedLayoutSegment } from "next/navigation";
import type { ChainSupportedService } from "../../../types/chain";
import { useMemo } from "react";
import { products } from "../../../components/server/products";
export function getEnabledTabs(enabledServices: ChainSupportedService[]) {
return products
.map((p) => ({
name: p.name,
segment: p.id === "contracts" ? "" : p.id,
serviceId: p.id,
icon: p.icon,
isEnabled: enabledServices.includes(p.id) ?? false,
}))
.sort((a, b) => {
if (a.isEnabled && !b.isEnabled) {
return -1;
}
if (!a.isEnabled && b.isEnabled) {
return 1;
}
return 0;
});
}
export function ChainPageTabs(props: {
chainSlug: string;
enabledServices: ChainSupportedService[];
}) {
const layoutSegment = useSelectedLayoutSegment() || "";
const links = useMemo(() => {
return getEnabledTabs(props.enabledServices);
}, [props.enabledServices]);
return (
<TabLinks
links={links.map((tab) => ({
name: tab.name,
href: `/${props.chainSlug}/${tab.segment}`,
isActive: layoutSegment === tab.segment,
isEnabled: tab.isEnabled,
icon: tab.icon,
}))}
/>
);
}
@@ -1,45 +0,0 @@
import { Button } from "@/components/ui/button";
import Link from "next/link";
export type ChainCTAProps = {
backgroundImageUrl: string;
title: string;
description?: string;
buttonText: string;
buttonLink: string;
};
export function ChainCTA(props: ChainCTAProps) {
return (
<div className="container px-4">
<div
className="w-full overflow-hidden rounded-xl shadow-lg bg-cover bg-center bg-no-repeat"
style={{
backgroundImage: `url(${props.backgroundImageUrl})`,
}}
>
<div className="grid items-center justify-center gap-6 bg-gradient-to-r from-accent/30 to-accent/0 p-8 sm:p-12 md:grid-cols-[1fr_auto] md:gap-12 lg:p-16">
<div className="space-y-4 text-center md:text-left">
<h2 className="text-3xl font-bold tracking-tighter text-accent-foreground sm:text-4xl md:text-5xl">
{props.title}
</h2>
{props.description && (
<p className="max-w-[600px] md:text-lg">{props.description}</p>
)}
</div>
<Button asChild size="lg">
<Link
href={props.buttonLink}
prefetch={false}
target={
props.buttonLink.startsWith("http") ? "_blank" : undefined
}
>
{props.buttonText}
</Link>
</Button>
</div>
</div>
</div>
);
}
@@ -1,44 +0,0 @@
import { ExternalLinkIcon } from "lucide-react";
import Link from "next/link";
export function FaucetsSection(props: { faucets: readonly string[] }) {
return (
<div>
<h2 className="text-base text-muted-foreground mb-2 font-medium">
Faucets
</h2>
<div className="grid grid-cols-1 gap-3 md:gap-4 md:grid-cols-2 lg:grid-cols-3">
{props.faucets.map((faucet) => {
const url = new URL(faucet);
const hostnameSplit = url.hostname.split(".");
const tld = hostnameSplit.pop();
const domain = hostnameSplit.pop();
const displayTitle = `${domain}.${tld}`;
let displayUrl = url.port + url.hostname + url.pathname;
displayUrl = displayUrl.endsWith("/")
? displayUrl.slice(0, -1)
: displayUrl;
return (
<div
key={faucet}
className="p-4 border rounded-xl relative bg-secondary hover:bg-muted"
>
<h3 className="mb-1 text-base font-semibold capitalize">
{displayTitle}
</h3>
<Link
href={faucet}
target="_blank"
className="text-sm flex gap-1.5 items-center before:absolute before:inset-0 before:z-0 text-muted-foreground"
>
{displayUrl}
</Link>
<ExternalLinkIcon className="size-4 absolute top-4 right-4 text-muted-foreground" />
</div>
);
})}
</div>
</div>
);
}
@@ -1,41 +0,0 @@
import { Button } from "@/components/ui/button";
import { ExternalLinkIcon } from "lucide-react";
import Link from "next/link";
import type React from "react";
export function InfoCard(props: {
title: string;
links?: { label: string; href: string }[];
children: React.ReactNode;
}) {
return (
<div className="border rounded-xl px-4 py-4 bg-secondary relative">
<h2 className="text-xl font-semibold tracking-tight mb-4">
{props.title}
</h2>
<div className="[&_p]:mb-3 [&_p]:text-secondary-foreground max-w-[1000px]">
{props.children}
</div>
{props.links && (
<div className="flex flex-col lg:flex-row mt-7 gap-3">
{props.links.map((link) => {
return (
<Button asChild variant="outline" key={link.label}>
<Link
href={link.href}
className="items-center gap-2"
target="_blank"
>
{link.label}{" "}
<ExternalLinkIcon className="size-3 text-muted-foreground" />
</Link>
</Button>
);
})}
</div>
)}
</div>
);
}
@@ -1,104 +0,0 @@
import Link from "next/link";
import { redirect } from "next/navigation";
import { FaReact } from "react-icons/fa";
import { FaUnity } from "react-icons/fa6";
import { SiDotnet, SiSolidity, SiTypescript } from "react-icons/si";
import { getChain } from "../../utils";
import { InfoCard } from "../components/server/info-card";
type SDKInfo = {
name: string;
href: string;
icon: React.FC<{ className?: string }>;
};
const sdks: SDKInfo[] = [
{
name: "TypeScript",
href: "https://portal.thirdweb.com/typescript/v5",
icon: SiTypescript,
},
{
name: "React",
href: "https://portal.thirdweb.com/typescript/v5/react",
icon: FaReact,
},
{
name: "React Native",
href: "https://portal.thirdweb.com/typescript/v5/react-native",
icon: FaReact,
},
{
name: "Unity",
href: "https://portal.thirdweb.com/unity",
icon: FaUnity,
},
{
name: "Solidity",
href: "https://portal.thirdweb.com/contracts/build/overview",
icon: SiSolidity,
},
{
name: ".NET SDK",
href: "https://portal.thirdweb.com/dotnet",
icon: SiDotnet,
},
];
export default async function Page(props: { params: { chain_id: string } }) {
const chain = await getChain(props.params.chain_id);
const enabled = chain.services.find(
(s) => s.service === "connect-sdk",
)?.enabled;
if (!enabled) {
redirect(`/${props.params.chain_id}`);
}
return (
<div>
<InfoCard
title="Connect SDK"
links={[
{
label: "Learn More",
href: "https://portal.thirdweb.com/connect",
},
]}
>
<p>
Connect is the complete toolkit for connecting every user to your
application.
</p>
<p>
It features customizable onboarding flows, self-custodial in-app
wallets, account abstraction, onramps, and more.
</p>
</InfoCard>
<div className="h-10" />
<h3 className="text-foreground text-3xl tracking-tighter font-semibold">
Get Started
</h3>
<div className="h-3" />
<div className="grid gap-3 md:gap-4 grid-cols-1 md:grid-cols-3 lg:grid-cols-4">
{sdks.map((sdk) => {
return (
<Link
key={sdk.name}
href={sdk.href}
target="_blank"
className="border p-4 bg-secondary rounded-lg hover:bg-muted font-medium flex items-center gap-3"
>
<sdk.icon className="size-5 text-muted-foreground" />
{sdk.name}
</Link>
);
})}
</div>
</div>
);
}
@@ -1,35 +0,0 @@
import { redirect } from "next/navigation";
import { getChain } from "../../utils";
import { InfoCard } from "../components/server/info-card";
export default async function Page(props: { params: { chain_id: string } }) {
const chain = await getChain(props.params.chain_id);
const enabled = chain.services.find((s) => s.service === "engine")?.enabled;
if (!enabled) {
redirect(`/${props.params.chain_id}`);
}
return (
<div>
<InfoCard
title="thirdweb Engine"
links={[
{
label: "Setup Engine Instance",
href: "/dashboard/engine",
},
{
label: "Learn More",
href: "https://portal.thirdweb.com/engine",
},
]}
>
<p>
thirdweb Engine is a backend HTTP server that reads, writes, and
deploys contracts at production scale.
</p>
</InfoCard>
</div>
);
}

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