Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/angry-monkeys-dress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"thirdweb": patch
---

Add customization options for the signIn modal shown from useFetchWithPayment
5 changes: 5 additions & 0 deletions .changeset/moody-camels-hear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"thirdweb": patch
---

Add monad chain definition
Comment on lines +1 to +5
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

Script executed:

#!/bin/bash

# First, let's find the changeset file and understand its structure
echo "=== Changeset file content ==="
find . -name "moody-camels-hear.md" -type f | head -5 | xargs cat

echo -e "\n=== Looking for monad chain definition in the PR ==="
# Search for monad chain definition
rg -i "monad" --type ts --type js -B2 -A2 | head -40

echo -e "\n=== Looking for chain definitions pattern ==="
# Find where chains are defined and exported
rg "chain" --type ts --type js -i "export.*chain" -B1 -A1 | head -50

Repository: thirdweb-dev/js


<shell_result>
Repository: thirdweb-dev/js
Exit code: 0

stdout:

=== Changeset file content ===
---
"thirdweb": patch
---

Add monad chain definition

=== Looking for monad chain definition in the PR ===
packages/thirdweb/src/exports/chains.ts-export { mode } from "../chains/chain-definitions/mode.js";
packages/thirdweb/src/exports/chains.ts-export { modeTestnet } from "../chains/chain-definitions/mode-testnet.js";
packages/thirdweb/src/exports/chains.ts:export { monadTestnet } from "../chains/chain-definitions/monad-testnet.js";
packages/thirdweb/src/exports/chains.ts-export { moonbeam } from "../chains/chain-definitions/moonbeam.js";
packages/thirdweb/src/exports/chains.ts-export { optimism } from "../chains/chain-definitions/optimism.js";
--
packages/thirdweb/src/chains/chain-definitions/monad-testnet.ts- * @chain
packages/thirdweb/src/chains/chain-definitions/monad-testnet.ts- */
packages/thirdweb/src/chains/chain-definitions/monad-testnet.ts:export const monadTestnet = /*@__PURE__*/ defineChain({
packages/thirdweb/src/chains/chain-definitions/monad-testnet.ts-  blockExplorers: [
packages/thirdweb/src/chains/chain-definitions/monad-testnet.ts-    {
packages/thirdweb/src/chains/chain-definitions/monad-testnet.ts:      name: "Monad Explorer",
packages/thirdweb/src/chains/chain-definitions/monad-testnet.ts:      url: "https://testnet.monadexplorer.com/",
packages/thirdweb/src/chains/chain-definitions/monad-testnet.ts-    },
packages/thirdweb/src/chains/chain-definitions/monad-testnet.ts-  ],
packages/thirdweb/src/chains/chain-definitions/monad-testnet.ts-  id: 10143,
packages/thirdweb/src/chains/chain-definitions/monad-testnet.ts:  name: "Monad Testnet",
packages/thirdweb/src/chains/chain-definitions/monad-testnet.ts-  nativeCurrency: { decimals: 18, name: "Mon", symbol: "MON" },
packages/thirdweb/src/chains/chain-definitions/monad-testnet.ts-  testnet: true,
--
packages/thirdweb/src/chains/chain-definitions/monad.ts- * @chain
packages/thirdweb/src/chains/chain-definitions/monad.ts- */
packages/thirdweb/src/chains/chain-definitions/monad.ts:export const monad = /*@__PURE__*/ defineChain({
packages/thirdweb/src/chains/chain-definitions/monad.ts-  blockExplorers: [
packages/thirdweb/src/chains/chain-definitions/monad.ts-    {
packages/thirdweb/src/chains/chain-definitions/monad.ts:      name: "Monad Vision",
packages/thirdweb/src/chains/chain-definitions/monad.ts:      url: "https://monadvision.com/",
packages/thirdweb/src/chains/chain-definitions/monad.ts-    },
packages/thirdweb/src/chains/chain-definitions/monad.ts-    {
packages/thirdweb/src/chains/chain-definitions/monad.ts:      name: "Monad Scan",
packages/thirdweb/src/chains/chain-definitions/monad.ts:      url: "https://monadscan.com/",
packages/thirdweb/src/chains/chain-definitions/monad.ts-    },
packages/thirdweb/src/chains/chain-definitions/monad.ts-  ],
packages/thirdweb/src/chains/chain-definitions/monad.ts-  id: 143,
packages/thirdweb/src/chains/chain-definitions/monad.ts:  name: "Monad",
packages/thirdweb/src/chains/chain-definitions/monad.ts-  nativeCurrency: { decimals: 18, name: "Mon", symbol: "MON" },
packages/thirdweb/src/chains/chain-definitions/monad.ts-});

=== Looking for chain definitions pattern ===

stderr:

export.*chain: No such file or directory (os error 2)

</shell_result>


Script executed:

#!/bin/bash

echo "=== Confirm monad is exported from chains.ts ==="
rg "export.*monad" packages/thirdweb/src/exports/chains.ts

echo -e "\n=== Check package.json exports or public API definition ==="
fd "package.json" -path "*/packages/thirdweb/*" --type f | head -1 | xargs head -50

echo -e "\n=== Look at recent changesets for chain additions ==="
fd "\.md" -path "*/.changeset/*" --type f | head -20 | xargs grep -l "chain" | head -5 | xargs cat

echo -e "\n=== Check if chains.ts is in the public exports ==="
cat packages/thirdweb/src/exports/chains.ts | head -20

Repository: thirdweb-dev/js


<shell_result>
Repository: thirdweb-dev/js
Exit code: 0

stdout:

=== Confirm monad is exported from chains.ts ===
export { monadTestnet } from "../chains/chain-definitions/monad-testnet.js";

=== Check package.json exports or public API definition ===

=== Look at recent changesets for chain additions ===

=== Check if chains.ts is in the public exports ===
// chain types

export { abstract } from "../chains/chain-definitions/abstract.js";
export { abstractTestnet } from "../chains/chain-definitions/abstract-testnet.js";

/**
 * PRE_DEFINED CHAINS
 */
export { anvil } from "../chains/chain-definitions/anvil.js";
export { arbitrum } from "../chains/chain-definitions/arbitrum.js";
export { arbitrumNova } from "../chains/chain-definitions/arbitrum-nova.js";
export { arbitrumSepolia } from "../chains/chain-definitions/arbitrum-sepolia.js";
export { arcTestnet } from "../chains/chain-definitions/arc-testnet.js";
export { assetChainTestnet } from "../chains/chain-definitions/assetchain-testnet.js";
export { astriaEvmDusknet } from "../chains/chain-definitions/astria-evm-dusknet.js";
export { avalanche } from "../chains/chain-definitions/avalanche.js";
export { avalancheFuji } from "../chains/chain-definitions/avalanche-fuji.js";
export { base } from "../chains/chain-definitions/base.js";
export { baseSepolia } from "../chains/chain-definitions/base-sepolia.js";
export { berachain } from "../chains/chain-definitions/berachain.js";

stderr:

error: 'h' isn't a valid value for '--type <filetype>'
  [possible values: file, directory, symlink, executable, empty, socket, pipe]

For more information try '--help'
error: 'h' isn't a valid value for '--type <filetype>'
  [possible values: file, directory, symlink, executable, empty, socket, pipe]

For more information try '--help'

</shell_result>


Script executed:

#!/bin/bash

echo "=== Search for all monad exports (not just monadTestnet) ==="
rg "export.*monad" packages/thirdweb/src/exports/chains.ts -A1 -B1

echo -e "\n=== List changesets directory ==="
ls -la .changeset/ | grep -v "^d" | head -20

echo -e "\n=== Check a few recent changesets for context ==="
find .changeset -name "*.md" -type f ! -name "README.md" ! -name "config.json" | head -10 | xargs cat

Repository: thirdweb-dev/js


<shell_result>
Repository: thirdweb-dev/js
Exit code: 0

stdout:

=== Search for all monad exports (not just monadTestnet) ===
export { modeTestnet } from "../chains/chain-definitions/mode-testnet.js";
export { monadTestnet } from "../chains/chain-definitions/monad-testnet.js";
export { moonbeam } from "../chains/chain-definitions/moonbeam.js";

=== List changesets directory ===
total 12
-rw-r--r--  1 jailuser jailuser 510 Nov 26 20:57 README.md
-rw-r--r--  1 jailuser jailuser 627 Nov 26 20:57 config.json
-rw-r--r--  1 jailuser jailuser  54 Nov 26 20:57 moody-camels-hear.md

=== Check a few recent changesets for context ===
---
"thirdweb": patch
---

Add monad chain definition

</shell_result>


Script executed:

#!/bin/bash

echo "=== Full search for monad in chains.ts ==="
rg "monad" packages/thirdweb/src/exports/chains.ts

echo -e "\n=== Count total lines in chains.ts to understand scope ==="
wc -l packages/thirdweb/src/exports/chains.ts

echo -e "\n=== Check if monad appears elsewhere in exports ==="
rg "export.*monad" packages/thirdweb/src/exports/

echo -e "\n=== Look at the actual monad.ts file to confirm it's a real chain definition ==="
head -30 packages/thirdweb/src/chains/chain-definitions/monad.ts

echo -e "\n=== Verify this is a public API entry point ==="
rg "from.*exports/chains" --type ts --type js | head -10

Repository: thirdweb-dev/js


<shell_result>
Repository: thirdweb-dev/js
Exit code: 0

stdout:

=== Full search for monad in chains.ts ===
export { monadTestnet } from "../chains/chain-definitions/monad-testnet.js";

=== Count total lines in chains.ts to understand scope ===
95 packages/thirdweb/src/exports/chains.ts

=== Check if monad appears elsewhere in exports ===
packages/thirdweb/src/exports/chains.ts:export { monadTestnet } from "../chains/chain-definitions/monad-testnet.js";

=== Look at the actual monad.ts file to confirm it's a real chain definition ===
import { defineChain } from "../utils.js";

/**
 * @chain
 */
export const monad = /*@__PURE__*/ defineChain({
  blockExplorers: [
    {
      name: "Monad Vision",
      url: "https://monadvision.com/",
    },
    {
      name: "Monad Scan",
      url: "https://monadscan.com/",
    },
  ],
  id: 143,
  name: "Monad",
  nativeCurrency: { decimals: 18, name: "Mon", symbol: "MON" },
});

=== Verify this is a public API entry point ===
packages/thirdweb/src/wallets/smart/smart-wallet-integration.test.ts:import { baseSepolia } from "../../exports/chains.js";
packages/thirdweb/src/wallets/eip5792/send-calls.test.ts:import { sepolia } from "../../exports/chains.js";
packages/thirdweb/src/transaction/actions/gasless/providers/engine.test.ts:import { polygon } from "../../../../exports/chains.js";

</shell_result>


Script executed:

#!/bin/bash

echo "=== Check if monad export was added in this PR by looking at git diff ==="
git diff HEAD -- packages/thirdweb/src/exports/chains.ts | head -40

echo -e "\n=== Verify the learning applies to this repository ==="
cat AGENTS.md 2>/dev/null | grep -A5 -B5 "changeset" | head -30

Repository: thirdweb-dev/js


<shell_result>
Repository: thirdweb-dev/js
Exit code: 0

stdout:

=== Check if monad export was added in this PR by looking at git diff ===

=== Verify the learning applies to this repository ===

⸻

8. Documentation & Developer Experience

- Each change in packages/\* should contain a changeset for the appropriate package, with the appropriate version bump

  - patch for changes that don't impact the public API
  - minor for any new/modified public API

- Surface breaking changes prominently in PR descriptions.

</shell_result>


Based on my verification:

  1. Chain definitions are public API: The file packages/thirdweb/src/exports/chains.ts is the central export point for chain definitions, and test files across the codebase import chains from this public API entry point.

  2. New chain is being added: The PR adds a new monad chain definition (file packages/thirdweb/src/chains/chain-definitions/monad.ts exists and is ready for export).

  3. Project policy confirmed: The AGENTS.md file explicitly states: "minor for any new/modified public API" and "patch for changes that don't impact the public API."

  4. This is a public API addition: Adding a new exportable chain constant is a new public API surface that consumers can import and use.


Update changeset to use minor version bump for new public chain export.

The PR adds a new chain definition (monad) to the thirdweb package's public API. Per project guidance in AGENTS.md, new/modified public APIs require a minor version bump, not patch.

---
-"thirdweb": patch
+"thirdweb": minor
---
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
---
"thirdweb": patch
---
Add monad chain definition
---
"thirdweb": minor
---
Add monad chain definition
🤖 Prompt for AI Agents
In .changeset/moody-camels-hear.md around lines 1 to 5, the changeset currently
lists "thirdweb": patch but this PR adds a new public chain export (monad) so
the version bump must be minor; update the frontmatter to "thirdweb": minor (and
keep the description), save the file so the package receives a minor version
bump per AGENTS.md guidance.

20 changes: 20 additions & 0 deletions packages/thirdweb/src/chains/chain-definitions/monad.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { defineChain } from "../utils.js";

/**
* @chain
*/
Comment on lines +3 to +5
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Add comprehensive TSDoc for the public chain export.

Per coding guidelines, every public symbol exported via exports/ must have comprehensive TSDoc including:

  • A description of the chain
  • At least one @example block showing usage
  • A custom annotation tag (@beta, @internal, or @experimental)

Currently, the TSDoc only contains @chain.

Apply this diff to add complete documentation:

 /**
+ * The Monad mainnet chain.
+ *
+ * @example
+ * ```ts
+ * import { monad } from "thirdweb/chains";
+ * import { createThirdwebClient } from "thirdweb";
+ *
+ * const client = createThirdwebClient({ clientId: "..." });
+ * const contract = getContract({ client, chain: monad, address: "0x..." });
+ * ```
+ *
  * @chain
+ * @beta
  */

Based on coding guidelines.

🤖 Prompt for AI Agents
In packages/thirdweb/src/chains/chain-definitions/monad.ts around lines 3 to 5,
the public export has only the `@chain` tag; update the TSDoc block to include a
short description of the Monad chain, an @example showing import and basic usage
(import { monad } from "thirdweb/chains"; createThirdwebClient(...);
getContract({ client, chain: monad, address: "0x..." });), and add a custom
annotation tag such as `@beta`; replace the minimal `@chain` comment with a full
JSDoc block that contains description, the example code block, `@chain`, and
`@beta`.

export const monad = /*@__PURE__*/ defineChain({
blockExplorers: [
{
name: "Monad Vision",
url: "https://monadvision.com/",
},
{
name: "Monad Scan",
url: "https://monadscan.com/",
},
],
id: 143,
name: "Monad",
nativeCurrency: { decimals: 18, name: "Mon", symbol: "MON" },
});
1 change: 1 addition & 0 deletions packages/thirdweb/src/exports/chains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export { mantaPacificTestnet } from "../chains/chain-definitions/manta-pacific-t
export { metalL2Testnet } from "../chains/chain-definitions/metal-l2-testnet.js";
export { mode } from "../chains/chain-definitions/mode.js";
export { modeTestnet } from "../chains/chain-definitions/mode-testnet.js";
export { monad } from "../chains/chain-definitions/monad.js";
export { monadTestnet } from "../chains/chain-definitions/monad-testnet.js";
export { moonbeam } from "../chains/chain-definitions/moonbeam.js";
export { optimism } from "../chains/chain-definitions/optimism.js";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { invalidateWalletBalance } from "../../providers/invalidateWalletBalance
export function useInvalidateBalances() {
const queryClient = useQueryClient();

return ({ chainId }: { chainId?: number }) => {
return ({ chainId }: { chainId?: number } = {}) => {
invalidateWalletBalance(queryClient, chainId);
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,9 @@ export function useFetchWithPaymentCore(
errorData: errorBody,
onRetry: async () => {
// Retry the entire fetch+error handling logic recursively
// Pass currentWallet to avoid re-showing connect modal with stale wallet state
try {
const result = await executeFetch();
const result = await executeFetch(currentWallet);
resolve(result);
} catch (error) {
reject(error);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,17 @@ type UseFetchWithPaymentConfig = UseFetchWithPaymentOptions & {
* These options will be merged with the client, theme, and chain from the hook.
*/
connectOptions?: Omit<UseConnectModalOptions, "client" | "theme">;
/**
* Options to customize the SignInRequiredModal that appears when the user needs to sign in.
*/
signInRequiredModal?: {
/** Custom title for the modal header */
title?: string;
/** Custom description text */
description?: string;
/** Custom label for the sign in button */
buttonLabel?: string;
};
};

/**
Expand Down Expand Up @@ -73,6 +84,7 @@ type UseFetchWithPaymentConfig = UseFetchWithPaymentOptions & {
* @param options.theme - Theme for the payment error modal (defaults to "dark")
* @param options.fundWalletOptions - Customize the BuyWidget shown when user needs to fund their wallet
* @param options.connectOptions - Customize the ConnectModal shown when user needs to sign in
* @param options.signInRequiredModal - Customize the SignInRequiredModal shown when user needs to sign in (title, description, buttonLabel)
* @returns An object containing:
* - `fetchWithPayment`: Function to make fetch requests with automatic payment handling (returns parsed data)
* - `isPending`: Boolean indicating if a request is in progress
Expand Down Expand Up @@ -146,6 +158,17 @@ type UseFetchWithPaymentConfig = UseFetchWithPaymentOptions & {
* });
* ```
*
* ### Customize the sign in required modal
* ```tsx
* const { fetchWithPayment } = useFetchWithPayment(client, {
* signInRequiredModal: {
* title: "Authentication Required",
* description: "Please sign in to access this paid content.",
* buttonLabel: "Connect Wallet",
* }
* });
* ```
*
* ### Disable the UI and handle errors yourself
* ```tsx
* const { fetchWithPayment, error } = useFetchWithPayment(client, {
Expand Down Expand Up @@ -201,6 +224,9 @@ export function useFetchWithPayment(
setRootEl(
<SignInRequiredModal
theme={theme}
title={options?.signInRequiredModal?.title}
description={options?.signInRequiredModal?.description}
buttonLabel={options?.signInRequiredModal?.buttonLabel}
onSignIn={async () => {
// Close the SignInRequiredModal
setRootEl(null);
Expand Down
20 changes: 15 additions & 5 deletions packages/thirdweb/src/react/web/ui/x402/SignInRequiredModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,23 @@ type SignInRequiredModalProps = {
theme: Theme | "light" | "dark";
onSignIn: () => void;
onCancel: () => void;
title?: string;
description?: string;
buttonLabel?: string;
};

/**
* @internal
*/
export function SignInRequiredModal(props: SignInRequiredModalProps) {
const { theme, onSignIn, onCancel } = props;
const {
theme,
onSignIn,
onCancel,
title = "Sign in required",
description = "Account required to complete payment, please sign in to continue.",
buttonLabel = "Sign in",
} = props;

return (
<CustomThemeProvider theme={theme}>
Expand All @@ -35,10 +45,10 @@ export function SignInRequiredModal(props: SignInRequiredModalProps) {
}
}}
size="compact"
title="Sign in required"
title={title}
>
<Container p="lg">
<ModalHeader title="Sign in required" />
<ModalHeader title={title} />

<Container
flex="column"
Expand All @@ -55,15 +65,15 @@ export function SignInRequiredModal(props: SignInRequiredModalProps) {
lineHeight: 1.5,
}}
>
Account required to complete payment, please sign in to continue.
{description}
</Text>
</Container>
</Container>

{/* Action Buttons */}
<ScreenBottomContainer>
<Button fullWidth gap="xs" onClick={onSignIn} variant="accent">
Sign in
{buttonLabel}
</Button>
<Button fullWidth gap="xs" onClick={onCancel} variant="secondary">
Cancel
Expand Down
Loading