Skip to content

Sweetmantech/myc 3556 apiimagegenerate lookup address by account#8

Merged
sweetmantech merged 5 commits into
mainfrom
sweetmantech/myc-3556-apiimagegenerate-lookup-address-by-account_id
Nov 29, 2025
Merged

Sweetmantech/myc 3556 apiimagegenerate lookup address by account#8
sweetmantech merged 5 commits into
mainfrom
sweetmantech/myc-3556-apiimagegenerate-lookup-address-by-account_id

Conversation

@sweetmantech
Copy link
Copy Markdown
Contributor

@sweetmantech sweetmantech commented Nov 28, 2025

Summary by CodeRabbit

  • New Features

    • Smart-account support with user-operation execution and paymaster-sponsored transactions
    • USDC transfer flow for on-chain payments and image-generation billing
    • Dynamic account creation fallback when an account is missing
    • Centralized configuration for account/smart-account addresses, paymaster URL and pricing
  • Breaking Changes

    • Public account retrieval now expects an accountId (string) instead of an address

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Nov 28, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Updated (UTC)
recoup-api Ready Ready Preview Nov 29, 2025 0:04am

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Nov 28, 2025

Walkthrough

Replaces address-based account lookup with an accountId/name flow (with creation fallback), adds smart-account and paymaster-backed user-op helpers, introduces USDC transfer utilities and constants, and updates payment and middleware flows to resolve and load accounts before sending user operations.

Changes

Cohort / File(s) Summary
Account resolution
lib/coinbase/getAccount.ts
Signature changed to getAccount(accountId: string); fetches by name, attempts createAccount() if not found, and adjusts error handling/logging.
Smart account helper
lib/coinbase/getSmartAccount.ts
New getSmartAccount(): Promise<EvmSmartAccount> that retrieves owner via Coinbase CDP then resolves the smart account; logs and rethrows on error.
User-op sender
lib/coinbase/sendUserOpAndWait.ts
New Call interface and sendUserOpAndWait(calls: readonly Call[]): Promise<string>: gets smart account, sends paymaster-backed user operation, waits for mining, returns transactionHash; includes logging/error propagation.
Constants
lib/const.ts
New constants exported: ACCOUNT_ADDRESS, SMART_ACCOUNT_ADDRESS, USDC_ADDRESS (typed Address), PAYMASTER_URL (uses env PAYMASTER_KEY), and IMAGE_GENERATE_PRICE.
USDC transfer utilities
lib/x402/getTransferCalls.ts, lib/x402/loadAccount.ts
New getTransferCalls(recipientAddress: Address, amount: string) builds ERC‑20 transfer calldata for USDC (6 decimals). New loadAccount(recipientAddress: Address) uses getTransferCalls() + sendUserOpAndWait() and returns tx hash.
Payment integration updates
lib/x402/fetchWithPayment.ts, middleware.ts
fetchWithPayment.ts now resolves account via getAccount(accountId) and calls loadAccount(account.address) instead of using a hard-coded account. middleware.ts now uses SMART_ACCOUNT_ADDRESS and IMAGE_GENERATE_PRICE for pricing display.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant fetchWithPayment
    participant getAccount
    participant loadAccount
    participant getTransferCalls
    participant sendUserOpAndWait
    participant getSmartAccount
    participant CDP as "Coinbase CDP (EVM)"

    Client->>fetchWithPayment: request (includes accountId)
    fetchWithPayment->>getAccount: getAccount(accountId)
    getAccount-->>fetchWithPayment: account (or created account)
    fetchWithPayment->>loadAccount: loadAccount(account.address)
    loadAccount->>getTransferCalls: getTransferCalls(recipient, price)
    getTransferCalls-->>loadAccount: Call[] (USDC transfer calldata)
    loadAccount->>sendUserOpAndWait: sendUserOpAndWait(calls)
    sendUserOpAndWait->>getSmartAccount: getSmartAccount()
    getSmartAccount->>CDP: getAccount(ACCOUNT_ADDRESS) / getSmartAccount(...)
    CDP-->>getSmartAccount: owner account / smart account
    getSmartAccount-->>sendUserOpAndWait: EvmSmartAccount
    sendUserOpAndWait->>CDP: sendUserOperation(smartAccount, network, paymasterUrl, calls)
    CDP-->>sendUserOpAndWait: userOpHash
    sendUserOpAndWait->>CDP: waitForUserOperation(userOpHash)
    CDP-->>sendUserOpAndWait: confirmed
    sendUserOpAndWait->>CDP: getUserOperation(userOpHash)
    CDP-->>sendUserOpAndWait: userOp (includes transactionHash)
    sendUserOpAndWait-->>loadAccount: transactionHash
    loadAccount-->>fetchWithPayment: transactionHash
    fetchWithPayment-->>Client: response with tx hash
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

  • Verify getAccount creation fallback for idempotency, race conditions, and error semantics.
  • Validate sendUserOpAndWait flow: types for Call, paymaster URL usage, and correct sequencing of send → wait → get.
  • Confirm USDC encoding: parseUnits(..., 6) and erc20Abi usage match token decimals.
  • Check env handling for PAYMASTER_KEY and behavior when absent.
  • Ensure updated call sites handle getAccount signature change.

Possibly related PRs

Poem

🐰
I hop where ledgers softly hum and play,
I find or make an account on the way,
Smart ops whisper through a paymaster gate,
USDC hops in — a tiny, punctual state,
A rabbit cheers: transactions bound today! 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title partially relates to the changeset—it mentions 'lookup address by account', which reflects the getAccount refactor from address to accountId, but does not clearly convey the broader scope of changes including smart account integration, user operations, and payment flow implementation. Consider a more descriptive title that captures the main objective, such as 'Add smart account and user operation support with account-based lookup' or 'Refactor account lookup and integrate smart account user operations'.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch sweetmantech/myc-3556-apiimagegenerate-lookup-address-by-account_id

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bb39ddb and 81d16ec.

📒 Files selected for processing (1)
  • lib/x402/loadAccount.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • lib/x402/loadAccount.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). (1)
  • GitHub Check: Vercel Agent Review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (3)
lib/x402/loadAccount.ts (1)

14-18: Orphaned step comments and misleading function name.

The comments reference steps "3." and "4." but there are no steps 1 or 2 in this function. Also, loadAccount is a misleading name since the function sends a USDC payment rather than loading an account.

Consider renaming to sendUsdcPayment or fundRecipient and removing the orphaned step numbers:

-  // 3. Get transfer calls
+  // Get transfer calls
   const calls = getTransferCalls(recipientAddress, IMAGE_GENERATE_PRICE);

-  // 4. Send user operation and wait for it to be mined
+  // Send user operation and wait for it to be mined
   const transactionHash = await sendUserOpAndWait(calls);
lib/coinbase/sendUserOpAndWait.ts (2)

28-31: Consider adding a timeout for waitForUserOperation.

waitForUserOperation could potentially hang indefinitely if the user operation never gets mined (e.g., due to gas price issues or network congestion). This could leave request threads blocked.

Check if the CDP SDK's waitForUserOperation accepts a timeout option, or wrap with a timeout utility:

const timeoutMs = 60_000; // 60 seconds
await Promise.race([
  cdp.evm.waitForUserOperation({
    smartAccountAddress: smartAccount.address,
    userOpHash: sendResult.userOpHash,
  }),
  new Promise((_, reject) => 
    setTimeout(() => reject(new Error('User operation timeout')), timeoutMs)
  ),
]);

6-9: Consider moving Call interface to a shared types file.

The Call interface is imported by lib/x402/getTransferCalls.ts. If this interface is reused across multiple modules, consider moving it to a dedicated types file (e.g., lib/types.ts) for better discoverability.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f3bc2ab and eba7476.

📒 Files selected for processing (8)
  • lib/coinbase/getAccount.ts (1 hunks)
  • lib/coinbase/getSmartAccount.ts (1 hunks)
  • lib/coinbase/sendUserOpAndWait.ts (1 hunks)
  • lib/const.ts (1 hunks)
  • lib/x402/fetchWithPayment.ts (2 hunks)
  • lib/x402/getTransferCalls.ts (1 hunks)
  • lib/x402/loadAccount.ts (1 hunks)
  • middleware.ts (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (7)
lib/coinbase/getSmartAccount.ts (2)
lib/coinbase/client.ts (1)
  • cdp (6-6)
lib/const.ts (2)
  • ACCOUNT_ADDRESS (3-3)
  • SMART_ACCOUNT_ADDRESS (4-4)
lib/x402/loadAccount.ts (3)
lib/x402/getTransferCalls.ts (1)
  • getTransferCalls (14-27)
lib/const.ts (1)
  • IMAGE_GENERATE_PRICE (7-7)
lib/coinbase/sendUserOpAndWait.ts (1)
  • sendUserOpAndWait (17-45)
lib/x402/fetchWithPayment.ts (3)
lib/coinbase/getAccount.ts (1)
  • getAccount (10-25)
lib/credits/deductCredits.ts (1)
  • deductCredits (23-58)
lib/x402/loadAccount.ts (1)
  • loadAccount (12-27)
lib/coinbase/sendUserOpAndWait.ts (3)
lib/coinbase/getSmartAccount.ts (1)
  • getSmartAccount (10-24)
lib/coinbase/client.ts (1)
  • cdp (6-6)
lib/const.ts (1)
  • PAYMASTER_URL (6-6)
lib/x402/getTransferCalls.ts (2)
lib/coinbase/sendUserOpAndWait.ts (1)
  • Call (6-9)
lib/const.ts (1)
  • USDC_ADDRESS (5-5)
middleware.ts (1)
lib/const.ts (2)
  • SMART_ACCOUNT_ADDRESS (4-4)
  • IMAGE_GENERATE_PRICE (7-7)
lib/coinbase/getAccount.ts (1)
lib/coinbase/client.ts (1)
  • cdp (6-6)
⏰ 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). (1)
  • GitHub Check: Vercel Agent Review
🔇 Additional comments (4)
middleware.ts (1)

3-3: LGTM!

Good refactoring to use centralized constants for the smart account address and pricing. This improves maintainability and ensures consistency across the codebase.

Also applies to: 43-47

lib/coinbase/getSmartAccount.ts (1)

10-24: LGTM!

The function is well-structured with proper error handling. The separation of owner account retrieval and smart account lookup is clean.

Consider whether this function would benefit from caching the smart account instance if called frequently, since the addresses are constant.

lib/x402/getTransferCalls.ts (1)

14-27: LGTM!

Clean utility function using viem's encoding utilities correctly. USDC decimals are correctly set to 6.

Minor: The as Call[] assertion on line 26 may be unnecessary if the object literal already satisfies the Call interface, but it's harmless.

lib/const.ts (1)

3-5: Confirm these are Base mainnet addresses and document the mainnet-only approach.

These addresses are verified as Base mainnet (USDC is officially 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913). The application is explicitly configured as "Mainnet x402 Demo" with no dev/staging environment support currently implemented. Consider whether future multi-environment support is needed; if so, these addresses should be moved to environment variables like RESOURCE_WALLET_ADDRESS to maintain consistency.

Comment thread lib/coinbase/getAccount.ts
Comment thread lib/const.ts
Comment thread lib/x402/fetchWithPayment.ts
Comment thread lib/x402/loadAccount.ts
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a 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

🧹 Nitpick comments (2)
lib/coinbase/sendUserOpAndWait.ts (2)

24-24: Consider making the network configurable.

The network is hardcoded to "base". If there's a possibility of supporting multiple networks in the future, consider making this a parameter or configuration value.


34-39: Validate the transaction hash before returning.

The code assumes userOp.transactionHash is always present. Consider adding validation to handle cases where it might be undefined or null.

     const userOp = await cdp.evm.getUserOperation({
       smartAccount,
       userOpHash: sendResult.userOpHash,
     });
 
-    return userOp.transactionHash;
+    if (!userOp.transactionHash) {
+      throw new Error('Transaction hash not found in user operation');
+    }
+    return userOp.transactionHash;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between eba7476 and bb39ddb.

📒 Files selected for processing (1)
  • lib/coinbase/sendUserOpAndWait.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
lib/coinbase/sendUserOpAndWait.ts (3)
lib/coinbase/getSmartAccount.ts (1)
  • getSmartAccount (10-24)
lib/coinbase/client.ts (1)
  • cdp (6-6)
lib/const.ts (1)
  • PAYMASTER_URL (6-6)
⏰ 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). (1)
  • GitHub Check: Vercel Agent Review
🔇 Additional comments (5)
lib/coinbase/sendUserOpAndWait.ts (5)

6-9: LGTM! Clean interface definition.

The Call interface is well-structured and uses appropriate viem types for EVM calls.


11-16: LGTM! Clear documentation.

The JSDoc comment effectively describes the function's behavior and parameters.


19-19: LGTM! Proper use of helper function.

Correctly retrieves the smart account using the helper function.


40-45: LGTM! Good error handling pattern.

The error handling appropriately logs the error and rethrows with descriptive context, which will help with debugging and monitoring.


21-27: The @ts-expect-error suppresses a real type compatibility issue, but the code is safe at runtime. Consider using an explicit type assertion instead.

The local Call interface ({ to: Address; data: Hex }) is a subset of the direct-call variant expected by CDP SDK's Calls<T> discriminated union type. However, TypeScript struggles to match readonly Call[] to the complex Calls<T> recursive/mapped type (which handles both direct and contract call shapes), causing the "excessively deep type instantiation" error.

Since the code only uses direct calls, replace the @ts-expect-error with an explicit type assertion:

const sendResult = await cdp.evm.sendUserOperation({
  smartAccount,
  network: "base",
  paymasterUrl: PAYMASTER_URL,
  calls: calls as any, // or: calls as Calls<unknown[]>
});

This preserves runtime safety while making the intent explicit. Alternatively, extend the Call interface to include the optional value field to better align with the SDK's direct-call shape and potentially eliminate the type error entirely.

Comment thread lib/coinbase/sendUserOpAndWait.ts
Comment thread lib/const.ts
@sweetmantech sweetmantech merged commit 8d04648 into main Nov 29, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant