-
Notifications
You must be signed in to change notification settings - Fork 619
[SDK] Feature: prepareCreateToken returns prepared transaction
#7872
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
🦋 Changeset detectedLatest commit: dceb5fa The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
How to use the Graphite Merge QueueAdd either label to this PR to merge it via the merge queue:
You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. |
WalkthroughIntroduces a new prepareCreateToken function that builds and returns a prepared ERC20 token creation transaction without sending it. Updates public exports to include prepareCreateToken. Minor syntactic reorder in predictAddress options destructuring. Adds a changeset marking a patch release for this update. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant App
participant SDK as thirdweb SDK
participant Builder as prepareCreateToken
participant Chain as Blockchain (not called)
App->>SDK: import { prepareCreateToken }
App->>Builder: prepareCreateToken(options)
Builder->>Builder: encode init/pool data, derive creator, generate salt
Builder-->>App: return prepared create transaction (not sent)
Note over App,Builder: No submission or event decoding occurs
sequenceDiagram
autonumber
participant App
participant SDK as thirdweb SDK
participant Creator as createToken
participant Chain as Blockchain
App->>SDK: import { createToken }
App->>Creator: createToken(options)
Creator->>Creator: build transaction (same inputs/utilities)
Creator->>Chain: sendAndConfirmTransaction(tx)
Chain-->>Creator: receipt
Creator->>Creator: decode AssetCreated event
Creator-->>App: return created asset details
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. Warning Review ran into problems🔥 ProblemsErrors were encountered while retrieving linked issues. Errors (1)
✨ Finishing Touches
🧪 Generate unit tests
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
size-limit report 📦
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🔭 Outside diff range comments (1)
.changeset/twenty-bees-sink.md (1)
1-6: Update .changeset to minor and include migration guideSwitching
createTokento return a prepared transaction instead of sending it is a breaking change, andTokenParams.owneris now required. Please update your changeset as follows:--- -"thirdweb": patch +"thirdweb": minor --- -feat: Update createToken to return a prepared transaction +feat(tokens): createToken returns a prepared transaction +- BREAKING: `createToken` now returns a `PreparedTransaction`; callers must send it (e.g. via `sendAndConfirmTransaction`). +- BREAKING: `TokenParams.owner` is now required. Creator derives strictly from `params.owner`. +- chore: updated `predictAddress` logic accordingly. +Migration: + +Before + const asset = await createToken({ client, chain, params }); + +After + const tx = await createToken({ client, chain, params }); + const receipt = await sendAndConfirmTransaction({ client, chain, transaction: tx }); + // (optional) parse events as neededAnd don’t forget to add a short note in the docs linking to this migration snippet.
🧹 Nitpick comments (4)
packages/thirdweb/src/tokens/predict-address.ts (1)
14-18: Add an explicit return type tied to the generated functionTo keep signatures explicit and future-proof against generator changes, annotate the return type using the generated helper’s type.
-export async function predictAddress(options: CreateTokenOptions) { +export async function predictAddress( + options: CreateTokenOptions, +): ReturnType<typeof _predictAddress> {packages/thirdweb/src/tokens/types.ts (2)
41-46: Consider typing developerAddress as Address as wellIt is passed directly to generated write/read helpers that commonly expect an Address. Aligning this improves DX and avoids unions like
string | Address.export type CreateTokenOptions = ClientAndChain & { salt?: Hex; params: TokenParams; launchConfig?: LaunchConfig; - developerAddress?: string; + developerAddress?: Address; };
48-53: Avoid duplicating Client/Chain fields in intersection
CreateTokenByImplementationConfigOptions = ClientAndChainAndAccount & CreateTokenOptionsduplicates client/chain fields via intersection. Prefer omitting overlapping keys to keep the type minimal and unambiguous.-export type CreateTokenByImplementationConfigOptions = - ClientAndChainAndAccount & - CreateTokenOptions & { - implementationAddress: string; - }; +export type CreateTokenByImplementationConfigOptions = + ClientAndChainAndAccount & + Omit<CreateTokenOptions, keyof ClientAndChain> & { + implementationAddress: string; + };packages/thirdweb/src/tokens/create-token.ts (1)
17-17: Type safety for creator: ensure TokenParams.owner is AddressThis relies on
params.ownerbeing a checksummed EVM address. See the types.ts suggestion to changeowner: stringtoowner: Address.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (4)
.changeset/twenty-bees-sink.md(1 hunks)packages/thirdweb/src/tokens/create-token.ts(2 hunks)packages/thirdweb/src/tokens/predict-address.ts(1 hunks)packages/thirdweb/src/tokens/types.ts(3 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}
📄 CodeRabbit Inference Engine (CLAUDE.md)
**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity
Re-use shared types from@/typesor localtypes.tsbarrels
Prefer type aliases over interface except for nominal shapes
Avoidanyandunknownunless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial,Pick, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose
Files:
packages/thirdweb/src/tokens/predict-address.tspackages/thirdweb/src/tokens/create-token.tspackages/thirdweb/src/tokens/types.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit Inference Engine (CLAUDE.md)
Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)
Files:
packages/thirdweb/src/tokens/predict-address.tspackages/thirdweb/src/tokens/create-token.tspackages/thirdweb/src/tokens/types.ts
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to packages/thirdweb/src/wallets/** : EIP-1193, EIP-5792, EIP-7702 standard support in wallet modules
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: E2E Tests (pnpm, webpack)
- GitHub Check: E2E Tests (pnpm, esbuild)
- GitHub Check: E2E Tests (pnpm, vite)
- GitHub Check: Lint Packages
- GitHub Check: Unit Tests
- GitHub Check: Size
- GitHub Check: Build Packages
- GitHub Check: Analyze (javascript)
🔇 Additional comments (2)
packages/thirdweb/src/tokens/predict-address.ts (1)
15-15: Owner-only creator source: verify all token call sites includeparams.owner
The removal of account fallbacks means every call to the token-package functionscreateTokenandpredictAddressmust now explicitly provideparams.owner. I ran a broad search (no obvious missing-owner usages found), but please double-check all internal and app callers, for example:• apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page-impl.tsx:114 – confirm the
createToken({ … })call suppliesownerinsideparams.
• Any other UI, CLI, or service code invokingcreateTokenfrompackages/thirdweb/src/tokens/create-token.ts.
• Any code importingpredictAddressfrompackages/thirdweb/src/tokens/predict-address.ts– ensureparams.owneris set.packages/thirdweb/src/tokens/create-token.ts (1)
35-47: LGTM: returning a prepared transaction aligns with the new flowConstructing via createById and returning the prepared transaction (without sending) matches the PR goal and simplifies the flow.
Please ensure docs and snippets are updated so integrators send the prepared tx, e.g.:
const tx = await createToken({ client, chain, params, launchConfig }); const receipt = await sendAndConfirmTransaction({ client, chain, transaction: tx });
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #7872 +/- ##
==========================================
- Coverage 56.54% 56.53% -0.01%
==========================================
Files 904 904
Lines 58592 58592
Branches 4143 4141 -2
==========================================
- Hits 33131 33126 -5
- Misses 25355 25360 +5
Partials 106 106
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/thirdweb/src/tokens/create-token.ts (1)
17-64: createToken still submits and returns an asset; PR objective says it must return a prepared transactionPer the PR objectives and changeset note, createToken should no longer send the tx nor decode events. Lines 50-64 submit the transaction and return the created asset address, which contradicts the intended API and will produce a breaking mismatch for consumers expecting a prepared transaction.
Proposed minimal fix: make createToken delegate to prepareCreateToken and return the prepared transaction. Also clean up now-unused imports.
Apply this diff to replace createToken with a delegating wrapper:
-export async function createToken(options: CreateTokenOptions) { - const { client, account, params, launchConfig } = options; - - const creator = params.owner || account.address; - const encodedInitData = await encodeInitParams({ - client, - creator, - params, - }); - - const salt: Hex = generateSalt(options.salt || bytesToHex(randomBytes(31))); - - const entrypoint = await getDeployedEntrypointERC20(options); - - let hookData: Hex = "0x"; - let contractId = padHex(toHex("ERC20Asset"), { size: 32 }); - if (launchConfig?.kind === "pool") { - hookData = encodePoolConfig(launchConfig.config); - contractId = padHex(toHex("ERC20Asset_Pool"), { size: 32 }); - } - - const transaction = createById({ - contract: entrypoint, - contractId, - params: { - data: encodedInitData, - hookData, - developer: options.developerAddress || DEFAULT_DEVELOPER_ADDRESS, - salt, - }, - creator, - }); - - const receipt = await sendAndConfirmTransaction({ account, transaction }); - const assetEvent = createdEvent(); - const decodedEvent = parseEventLogs({ - events: [assetEvent], - logs: receipt.logs, - }); - - if (decodedEvent.length === 0 || !decodedEvent[0]) { - throw new Error( - `No AssetCreated event found in transaction: ${receipt.transactionHash}`, - ); - } - - return decodedEvent[0]?.args.asset; -} +export async function createToken( + options: CreateTokenOptions, +): Promise<ReturnType<typeof createById>> { + return prepareCreateToken(options); +}Additionally remove now-unused imports at the top of the file:
-import { parseEventLogs } from "../event/actions/parse-logs.js"; -import { createdEvent } from "../extensions/tokens/__generated__/ERC20Entrypoint/events/Created.js"; -import { sendAndConfirmTransaction } from "../transaction/actions/send-and-confirm-transaction.js";
♻️ Duplicate comments (1)
packages/thirdweb/src/tokens/create-token.ts (1)
66-100: Make return type explicit and dropaccountfallback;ownershould be required
- Add an explicit return type tied to the generated write fn. This keeps the contract with consumers stable across generator updates.
- Per PR objective,
params.owneris required andaccountis removed from options. Lines 67 and 69 still destructure/useaccount. Remove it and rely onparams.ownerfor thecreator.Apply this diff:
-export async function prepareCreateToken(options: CreateTokenOptions) { - const { client, params, account, launchConfig } = options; +export async function prepareCreateToken( + options: CreateTokenOptions, +): Promise<ReturnType<typeof createById>> { + const { client, params, launchConfig } = options; - const creator = params.owner || account.address; + const creator = params.owner;Note: If
getDeployedEntrypointERC20(options)relied onaccount, its signature should be updated accordingly as part of the broader API change.
🧹 Nitpick comments (1)
packages/thirdweb/src/tokens/create-token.ts (1)
66-100: Add TSDoc with a compiling example for new public APIPublic symbols must have comprehensive TSDoc with at least one @example. Please document both prepareCreateToken and (now delegating) createToken.
Proposed doc for prepareCreateToken:
+/** + * Prepare an ERC20 token creation transaction without sending it. + * Uses the ERC20 Entrypoint factory to build a `createById` transaction with + * encoded init data, optional pool hook data, and a generated salt. + * + * @param options - Token creation options including required `params.owner`. + * @returns Prepared transaction returned by the generated `createById` write fn. + * @example + * import { createWallet, sendAndConfirmTransaction } from "thirdweb"; + * import { prepareCreateToken } from "thirdweb/tokens"; + * + * const account = createWallet("..."); // signer + * const tx = await prepareCreateToken({ + * client, + * params: { + * owner, + * name: "My Token", + * symbol: "MYT", + * supply: 1_000_000n, + * // ...other params + * }, + * launchConfig: { kind: "standard" }, + * }); + * const receipt = await sendAndConfirmTransaction({ account, transaction: tx }); + * @beta + */ export async function prepareCreateToken( options: CreateTokenOptions, ): Promise<ReturnType<typeof createById>> {And for createToken (now alias/delegation):
+/** + * Alias to {@link prepareCreateToken}. This function now returns a prepared transaction + * instead of submitting and returning the created asset. + * + * @example + * const tx = await createToken({ client, params: { owner, name: "My Token", symbol: "MYT" } }); + * const receipt = await sendAndConfirmTransaction({ account, transaction: tx }); + * @beta + */ export async function createToken( options: CreateTokenOptions, ): Promise<ReturnType<typeof createById>> { return prepareCreateToken(options); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (3)
packages/thirdweb/src/exports/tokens.ts(1 hunks)packages/thirdweb/src/tokens/create-token.ts(1 hunks)packages/thirdweb/src/tokens/predict-address.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/thirdweb/src/tokens/predict-address.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}
📄 CodeRabbit Inference Engine (CLAUDE.md)
**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity
Re-use shared types from@/typesor localtypes.tsbarrels
Prefer type aliases over interface except for nominal shapes
Avoidanyandunknownunless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial,Pick, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose
Files:
packages/thirdweb/src/exports/tokens.tspackages/thirdweb/src/tokens/create-token.ts
packages/thirdweb/src/exports/**
📄 CodeRabbit Inference Engine (CLAUDE.md)
packages/thirdweb/src/exports/**: Export everything viaexports/directory, grouped by feature in the SDK public API
Every public symbol must have comprehensive TSDoc with at least one@exampleblock that compiles and custom annotation tags (@beta,@internal,@experimental)
Files:
packages/thirdweb/src/exports/tokens.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit Inference Engine (CLAUDE.md)
Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)
Files:
packages/thirdweb/src/exports/tokens.tspackages/thirdweb/src/tokens/create-token.ts
🧠 Learnings (1)
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to packages/thirdweb/src/exports/** : Export everything via `exports/` directory, grouped by feature in the SDK public API
Applied to files:
packages/thirdweb/src/exports/tokens.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: E2E Tests (pnpm, esbuild)
- GitHub Check: Size
- GitHub Check: E2E Tests (pnpm, vite)
- GitHub Check: E2E Tests (pnpm, webpack)
- GitHub Check: Lint Packages
- GitHub Check: Build Packages
- GitHub Check: Unit Tests
- GitHub Check: Analyze (javascript)
🔇 Additional comments (1)
packages/thirdweb/src/exports/tokens.ts (1)
9-9: LGTM: New public exportprepareCreateTokenRe-export looks correct and follows the exports/ pattern used elsewhere in this file.
| export async function prepareCreateToken(options: CreateTokenOptions) { | ||
| const { client, params, account, launchConfig } = options; | ||
|
|
||
| const creator = params.owner || account.address; | ||
| const encodedInitData = await encodeInitParams({ | ||
| client, | ||
| creator, | ||
| params, | ||
| }); | ||
|
|
||
| const salt: Hex = generateSalt(options.salt || bytesToHex(randomBytes(31))); | ||
|
|
||
| const entrypoint = await getDeployedEntrypointERC20(options); | ||
|
|
||
| let hookData: Hex = "0x"; | ||
| let contractId = padHex(toHex("ERC20Asset"), { size: 32 }); | ||
| if (launchConfig?.kind === "pool") { | ||
| hookData = encodePoolConfig(launchConfig.config); | ||
| contractId = padHex(toHex("ERC20Asset_Pool"), { size: 32 }); | ||
| } | ||
|
|
||
| const transaction = createById({ | ||
| contract: entrypoint, | ||
| contractId, | ||
| params: { | ||
| data: encodedInitData, | ||
| hookData, | ||
| developer: options.developerAddress || DEFAULT_DEVELOPER_ADDRESS, | ||
| salt, | ||
| }, | ||
| creator, | ||
| }); | ||
|
|
||
| return transaction; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Verify types and upstream call sites: remove account from CreateTokenOptions and require TokenParams.owner
The code still references account and treats params.owner as optional. Ensure:
- CreateTokenOptions excludes
account - TokenParams.owner is required
- predict-address.ts and any other helpers derive
creatorfromparams.owneronly
Run this script to locate and update remaining references:
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Check destructuring of options for account in token flows"
rg -n -C3 --type=ts '(const|let)\s*\{\s*[^}]*account[^}]*\}\s*=\s*options' packages/thirdweb/src | sed -n '1,200p'
echo "Where is CreateTokenOptions defined/used?"
rg -n -C3 --type=ts '\b(CreateTokenOptions|TokenParams)\b' packages/thirdweb/src | sed -n '1,200p'
echo "Find uses of account in predict-address and token creation"
rg -n -C3 --type=ts '\baccount\b' packages/thirdweb/src/tokens/predict-address.ts packages/thirdweb/src/tokens/create-token.ts || true
echo "Find createToken call sites to assess breakage from return type change"
rg -n -C3 --type=ts '\bcreateToken\s*\(' | sed -n '1,200p'Length of output: 28489
Ensure token creation only uses params.owner and remove account from options
Please make the following mandatory updates:
• Update types
– in packages/thirdweb/src/tokens/types.ts:
• Remove the inherited account field from CreateTokenOptions (no longer extend ClientAndChainAndAccount)
• Add a required owner: string property to TokenParams
• Update token-flow implementations
– packages/thirdweb/src/tokens/create-token.ts (createToken & prepareCreateToken):
• Drop account from the options destructuring
• Replace params.owner || account.address with params.owner
– packages/thirdweb/src/tokens/predict-address.ts:
• Drop account from the options destructuring
• Derive creator = params.owner only
• Fix all upstream call sites for createToken and predictAddress (e.g. in apps/dashboard/.../create-token-page-impl.tsx):
– Remove passing account
– Ensure callers supply params.owner
These changes are breaking—please update types, implementations, and all call sites accordingly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@CodeRabbit don't tell me to make "mandatory" updates. You don't understand this code or its business context in the slightest. Know your place.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gregfromstl I apologize for being overly prescriptive in my previous comment. You're absolutely right - I don't have the full business context behind these design decisions, and I should have asked clarifying questions rather than making assumptions about what changes were needed.
Thank you for the feedback on my approach. I'll focus on asking questions and providing observations rather than directing what should be done, especially when I lack the domain knowledge you have as the author.
(\ /)
( ._. )
o_(")(")
createToken returns prepared transactionprepareCreateToken returns prepared transaction
PR-Codex overview
This PR focuses on enhancing the
createTokenfunctionality by introducing a new method,prepareCreateToken, which prepares a transaction for creating a token.Detailed summary
createTokento return a prepared transaction.prepareCreateTokenincreate-token.tsto handle token creation preparation.tokens.tsto includeprepareCreateToken.optionsinpredictAddress.Summary by CodeRabbit
New Features
Chores