Skip to content

feat: implement trading interface and smart contract integration#29

Open
Rav1Chauhan wants to merge 10 commits into
DjedAlliance:mainfrom
Rav1Chauhan:feature/trading-ui
Open

feat: implement trading interface and smart contract integration#29
Rav1Chauhan wants to merge 10 commits into
DjedAlliance:mainfrom
Rav1Chauhan:feature/trading-ui

Conversation

@Rav1Chauhan

@Rav1Chauhan Rav1Chauhan commented Mar 15, 2026

Copy link
Copy Markdown
Contributor

Addressed Issues:

Fixes #4

Screenshots/Recordings:

Trading UI with smart contract integration:
Token Balance display
Buy StableCoin interface
Sell StableCoin interface
Fee estimation
Transaction status handling
Multi-step transaction flow (Approve → Execute)

Screenshot 2026-03-16 190451 Screenshot 2026-03-16 190154 Screenshot 2026-03-16 190140 Screenshot 2026-03-16 190004 Screenshot 2026-03-16 185946

Additional Notes:

This PR implements the core trading functionality required for interacting with the Djed protocol smart contracts.

Key improvements:

• Buy StableCoin interface with amount input and transaction execution
• Sell StableCoin interface for redeeming stablecoins
• Token balance display for BaseCoin and StableCoin
• Multi-step transaction flow (approve → buy/sell)
• Transaction status updates in the UI
• Fee estimation before executing trades
• Wallet connection validation before allowing trading

Checklist

  • [ x] My PR addresses a single issue, fixes a single bug or makes a single improvement.
  • [x ] My code follows the project's code style and conventions
  • If applicable, I have made corresponding changes or additions to the documentation
  • If applicable, I have made corresponding changes or additions to tests
  • [x ] My changes generate no new warnings or errors
  • [ x] I have joined the Discord server and I will share a link to this PR with the project maintainers there
  • [x ] I have read the Contribution Guidelines
  • [ x] Once I submit my PR, CodeRabbit AI will automatically review it and I will address CodeRabbit's comments.

AI Usage Disclosure

Check one of the checkboxes below:

  • [ x] This PR does not contain AI-generated code at all.
  • This PR contains AI-generated code. I have read the AI Usage Policy and this PR complies with this policy. I have tested the code locally and I am responsible for it.

I have used the following AI models and tools: TODO

⚠️ AI Notice - Important!

We encourage contributors to use AI tools responsibly when creating Pull Requests. While AI can be a valuable aid, it is essential to ensure that your contributions meet the task requirements, build successfully, include relevant tests, and pass all linters. Submissions that do not meet these standards may be closed without warning to maintain the quality and integrity of the project. Please take the time to understand the changes you are proposing and their impact. AI slop is strongly discouraged and may lead to banning and blocking. Do not spam our repos with AI slop.

Summary by CodeRabbit

  • New Features

    • Trade section with Buy/Sell StableCoin flows, live fee/net previews, clear transaction status, and Token Balances when connected.
    • Wallet-aware UI: connect prompts and gated trading content; CTA scrolls to Trade.
  • UI Changes

    • Refreshed hero and background layout for improved visuals, spacing and scrolling.
    • Dashboard simplified to a concise metrics view with a refresh control.
  • Bug Fixes

    • Minor navbar JSX rendering issue corrected.

@coderabbitai

coderabbitai Bot commented Mar 15, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a wallet-gated on-page trading section with TokenBalances, BuyStableCoin, and SellStableCoin components; introduces a useDjedTransactions hook for contract writes; tightens address getters in utils; minor Next webpack tweak and UI/layout adjustments (hero, CTA, background wrappers).

Changes

Cohort / File(s) Summary
Homepage / Layout
src/app/page.tsx
Replaces hero with expanded layout, adds id="trade" section, wires CTA to scroll to trade, integrates LiquidEther background wrappers, and conditionally renders trading UI based on wallet connection.
Trading Components
src/components/trading/BuyStableCoin.tsx, src/components/trading/SellStableCoin.tsx, src/components/trading/TokenBalances.tsx
New client components: buy/sell forms with validation, fee/net previews, loading/error states, writeContractAsync calls for buy/sell, and TokenBalances reading ERC‑20 balanceOf.
Transactions Hook
src/hooks/useDjedTransactions.ts
New hook exposing approveBaseToken, buyStableCoin, sellStableCoin and getDjedContract() that validates NEXT_PUBLIC_DJED_CONTRACT and wraps wagmi write calls.
Addresses & Config
src/utils/addresses.ts, next.config.mjs
src/utils/addresses.ts now enforces deployed addresses via getters, adds isSupportedChain, and adjusts DJED/StableCoin address exports; next.config.mjs updates webpack fallback to disable @react-native-async-storage/async-storage.
Dashboard & Trade Pages
src/app/dashboard/page.tsx, src/app/trade/page.tsx
Dashboard simplified to fewer reads/metrics and per-contract getters; Trade page refactored to simplified approval/trade flow, early UI guards, and updated transaction loading handling.
Minor Fixes
src/components/layout/Navbar.tsx
Removed stray JSX characters and small formatting fixes.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant App as App (page.tsx)
    participant UI as Trading Components
    participant Hook as useDjedTransactions
    participant Contract as Smart Contract

    User->>App: Connect wallet
    App->>UI: Render TokenBalances & trade UI (isConnected)
    UI->>Contract: Read balances via useReadContract
    Contract-->>UI: Return balances

    User->>UI: Enter amount & click Buy
    UI->>Hook: approveBaseToken(token, spender, amount)
    Hook->>Contract: submit approve tx
    Contract-->>Hook: Approval confirmed
    UI->>Hook: buyStableCoin(amount, receiver)
    Hook->>Contract: submit buy tx
    Contract-->>Hook: Transaction confirmed
    Hook-->>UI: Success
    UI-->>User: Update status / clear input
Loading
sequenceDiagram
    participant User
    participant UI as Trading Components
    participant Hook as useDjedTransactions
    participant Contract as Smart Contract

    User->>UI: Enter amount & click Sell
    UI->>Hook: sellStableCoin(amount, receiver)
    Hook->>Contract: submit sell tx
    Contract-->>Hook: Transaction confirmed
    Hook-->>UI: Success
    UI-->>User: Update status / clear input
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • Zahnentferner

Poem

🐇 I nibble keys and watch the chain,

Approve, then buy, then sell again,
Balances glow beneath the moon,
Wallets hum — transactions soon,
Hopping happy on the trading lane 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: implement trading interface and smart contract integration' clearly and concisely summarizes the main changes: adding trading UI components and smart contract integration for buying/selling stablecoins.
Linked Issues check ✅ Passed All objectives from linked issue #4 are met: Buy/Sell StableCoin forms with transaction execution, token balance display, multi-step transaction flows, and fee calculations are all implemented and integrated.
Out of Scope Changes check ✅ Passed All changes align with the trading interface and smart contract integration objective. Modifications to address utilities, Next.js config, dashboard, and trade page support the core trading functionality without introducing unrelated changes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (3)
src/components/trading/BuyStableCoin.tsx (1)

18-53: Inconsistent indentation in handleBuy function.

The function body uses mixed indentation (no indent for function signature, then variable indentation inside). This affects readability.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/trading/BuyStableCoin.tsx` around lines 18 - 53, The handleBuy
function has inconsistent indentation; reformat the entire function body so all
internal lines use a single consistent indentation level (e.g., 2 or 4 spaces)
and align its braces and blocks (try, catch, finally) uniformly; update the body
that contains variables and calls like const parsedAmount = BigInt(amount);
setLoading(true); setStatus(" Approving BaseCoin..."); await
approveBaseToken(parsedAmount); await buyStableCoin(parsedAmount);
setAmount(""); console.error("Transaction failed:", error); and
setLoading(false); so they all follow the same indentation style for readability
and maintainability.
src/components/trading/TokenBalances.tsx (1)

6-7: Centralize contract addresses to avoid duplication and inconsistency.

These placeholder addresses are duplicated from src/hooks/useDjedTransactions.ts. Extract them to a shared constants file to ensure consistency and simplify updates.

-const BASE_TOKEN = "0xYourBaseTokenAddress";
-const STABLE_TOKEN = "0xYourStableCoinAddress";
+import { BASE_TOKEN, STABLE_TOKEN } from "@/constants/contracts";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/trading/TokenBalances.tsx` around lines 6 - 7, The duplicated
placeholder addresses BASE_TOKEN and STABLE_TOKEN should be moved into a single
shared constants module and imported where needed; create a new constants module
that exports BASE_TOKEN and STABLE_TOKEN (and any future token addresses),
replace the hardcoded declarations in TokenBalances.tsx and
useDjedTransactions.ts by importing those exports, and update any references to
use the imported symbols to ensure consistency and avoid duplication.
src/components/trading/SellStableCoin.tsx (1)

11-14: Hardcoded fee rate may not match on-chain protocol fee.

The 0.3% fee is calculated client-side. If the protocol's actual fee differs, users will see incorrect estimates. Consider fetching the fee rate from the contract or clarifying this is an estimate.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/trading/SellStableCoin.tsx` around lines 11 - 14, The fee is
hardcoded via feeRate and used to compute fee and receiveAmount in the
SellStableCoin component, which can produce incorrect client-side estimates;
change this to fetch the protocol fee rate from the on-chain contract (call the
contract's fee accessor, e.g., feeRate() or getFee) inside an async effect or
initialization path and store it in component state, then compute fee and
receiveAmount from that fetched value with a safe fallback; alternatively, if
on-chain fetching isn't possible yet, explicitly mark the UI as "estimated" and
surface the fallback default (0.003) and ensure the variable names feeRate, fee,
and receiveAmount are updated to use the fetched value.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/trading/BuyStableCoin.tsx`:
- Around line 29-37: The code uses BigInt(amount) which will throw for decimal
inputs and fires buy before approval is confirmed; replace BigInt parsing with a
proper big-number parser (e.g., ethers' parseUnits or parseEther) when computing
parsedAmount, call approveBaseToken(parsedAmount) and capture the returned
transaction, then await its on-chain confirmation (e.g.,
provider.waitForTransaction or waitForTransactionReceipt) before proceeding to
setStatus("Executing buy transaction...") and calling
buyStableCoin(parsedAmount); also ensure the buyStableCoin ABI/contract call in
useDjedTransactions.ts matches the deployed contract ABI so the buy call
succeeds.

In `@src/components/trading/SellStableCoin.tsx`:
- Around line 26-28: Validate that a wallet/signer is connected before calling
sellStableCoin and return early with user feedback if not; validate the amount
input to reject non-numeric or negative values and parse decimals by converting
to the token's smallest unit (e.g., using a parseUnits helper or multiply by
10^decimals then BigInt) instead of calling BigInt(amount) directly; replace the
current parsedAmount = BigInt(amount) with a safe conversion that handles
decimals and throws a controlled error you catch and show to the user; note that
sellStableCoin (from useDjedTransactions) will still fail until the ABI mismatch
in useDjedTransactions.ts is fixed.

In `@src/components/trading/TokenBalances.tsx`:
- Around line 47-48: The component is rendering raw bigint wei values
(baseBalance, stableBalance); replace the direct toString() output with
formatted token amounts using viem's formatUnits so balances display
human-readable decimals (e.g., formatUnits(baseBalance, 18) and
formatUnits(stableBalance, 18) or use the token's decimals if available). Import
formatUnits from 'viem', apply it where TokenBalances.tsx currently uses
baseBalance?.toString() and stableBalance?.toString(), and fallback to "0" when
balances are null/undefined.

In `@src/hooks/useDjedTransactions.ts`:
- Around line 25-32: The helper buyStableCoin is calling the wrong ABI entry and
wrong argument shape; update the function (and any callers) to call the djed ABI
functionName "buyStableCoins" (plural) on DJED_CONTRACT using djedAbi and pass
the four required parameters in the correct order: receiver, feeUI, ui, and
value (the last being the amount to send), ensuring types match the ABI (e.g.,
receiver as address, feeUI/ui as numbers/bigints as required) and that
writeContract includes these args instead of the single bigint.
- Around line 35-42: The current sellStableCoin wrapper calls the wrong ABI
function name and omits required parameters; update the function in
useDjedTransactions.ts to match the ABI by renaming it (or adding an overload)
to sellStableCoins and accept the four required parameters (amountSC, receiver,
feeUI, ui), then call writeContract with functionName: "sellStableCoins" and
args: [amountSC, receiver, feeUI, ui] so the call signature matches the Djed ABI
(see sellStableCoins in Djed.json).
- Around line 7-8: Replace the hardcoded placeholders DJED_CONTRACT and
BASE_TOKEN with configurable values sourced from environment variables (e.g.
process.env.DJED_CONTRACT and process.env.BASE_TOKEN) and add a runtime check
that throws or logs a clear error if they are missing; update any exports or
consumers in useDjedTransactions (references to DJED_CONTRACT and BASE_TOKEN) to
use the env-backed constants and optionally support network-specific overrides
or sensible fallbacks so the hook fails fast instead of using invalid addresses.

---

Nitpick comments:
In `@src/components/trading/BuyStableCoin.tsx`:
- Around line 18-53: The handleBuy function has inconsistent indentation;
reformat the entire function body so all internal lines use a single consistent
indentation level (e.g., 2 or 4 spaces) and align its braces and blocks (try,
catch, finally) uniformly; update the body that contains variables and calls
like const parsedAmount = BigInt(amount); setLoading(true); setStatus("
Approving BaseCoin..."); await approveBaseToken(parsedAmount); await
buyStableCoin(parsedAmount); setAmount(""); console.error("Transaction failed:",
error); and setLoading(false); so they all follow the same indentation style for
readability and maintainability.

In `@src/components/trading/SellStableCoin.tsx`:
- Around line 11-14: The fee is hardcoded via feeRate and used to compute fee
and receiveAmount in the SellStableCoin component, which can produce incorrect
client-side estimates; change this to fetch the protocol fee rate from the
on-chain contract (call the contract's fee accessor, e.g., feeRate() or getFee)
inside an async effect or initialization path and store it in component state,
then compute fee and receiveAmount from that fetched value with a safe fallback;
alternatively, if on-chain fetching isn't possible yet, explicitly mark the UI
as "estimated" and surface the fallback default (0.003) and ensure the variable
names feeRate, fee, and receiveAmount are updated to use the fetched value.

In `@src/components/trading/TokenBalances.tsx`:
- Around line 6-7: The duplicated placeholder addresses BASE_TOKEN and
STABLE_TOKEN should be moved into a single shared constants module and imported
where needed; create a new constants module that exports BASE_TOKEN and
STABLE_TOKEN (and any future token addresses), replace the hardcoded
declarations in TokenBalances.tsx and useDjedTransactions.ts by importing those
exports, and update any references to use the imported symbols to ensure
consistency and avoid duplication.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 31b02f6b-74f5-4857-8162-4b17c6d0b4cc

📥 Commits

Reviewing files that changed from the base of the PR and between a23b2e8 and d64a400.

📒 Files selected for processing (5)
  • src/app/page.tsx
  • src/components/trading/BuyStableCoin.tsx
  • src/components/trading/SellStableCoin.tsx
  • src/components/trading/TokenBalances.tsx
  • src/hooks/useDjedTransactions.ts

Comment thread src/components/trading/BuyStableCoin.tsx Outdated
Comment thread src/components/trading/SellStableCoin.tsx Outdated
Comment thread src/components/trading/TokenBalances.tsx Outdated
Comment thread src/hooks/useDjedTransactions.ts Outdated
Comment thread src/hooks/useDjedTransactions.ts Outdated
Comment thread src/hooks/useDjedTransactions.ts Outdated
Rav1Chauhan and others added 5 commits March 15, 2026 19:51
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

♻️ Duplicate comments (1)
src/hooks/useDjedTransactions.ts (1)

6-7: ⚠️ Potential issue | 🟠 Major

Add runtime validation for required public contract addresses.

Directly casting env vars to address types can hide missing/invalid config until transaction time.

♻️ Proposed fix
-const DJED_CONTRACT = process.env.NEXT_PUBLIC_DJED_CONTRACT as `0x${string}`;
-const BASE_TOKEN = process.env.NEXT_PUBLIC_BASE_TOKEN as `0x${string}`;
+const toAddress = (value: string | undefined, name: string): `0x${string}` => {
+  if (!value || !/^0x[a-fA-F0-9]{40}$/.test(value)) {
+    throw new Error(`Invalid or missing ${name}`);
+  }
+  return value as `0x${string}`;
+};
+
+const DJED_CONTRACT = toAddress(
+  process.env.NEXT_PUBLIC_DJED_CONTRACT,
+  "NEXT_PUBLIC_DJED_CONTRACT",
+);
+const BASE_TOKEN = toAddress(
+  process.env.NEXT_PUBLIC_BASE_TOKEN,
+  "NEXT_PUBLIC_BASE_TOKEN",
+);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/useDjedTransactions.ts` around lines 6 - 7, The code is unsafe
because DJED_CONTRACT and BASE_TOKEN are being force-cast from env vars without
runtime checks; update useDjedTransactions to validate these values at runtime
(e.g., in the hook initialization or a small helper) by ensuring they exist and
match an Ethereum address pattern (starts with "0x" and 40 hex chars), and
surface a clear error or throw with context if invalid/missing rather than
silently casting; reference the DJED_CONTRACT and BASE_TOKEN symbols and perform
the check before any transaction or contract instantiation in
useDjedTransactions so consumers fail fast with an actionable message.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/trading/BuyStableCoin.tsx`:
- Around line 51-55: The status is set to "Transaction confirmed" immediately
after calling buyStableCoin; change flow so the UI only marks confirmation after
the buy transaction is mined—either update buyStableCoin to return the
transaction/receipt and await tx.wait() (or the returned receipt) here, or have
this caller receive and await the promise returned by buyStableCoin that
resolves when mined; then call setStatus("Step 3: Transaction confirmed!") only
after the awaited receipt is obtained. Ensure you reference the buyStableCoin
invocation and setStatus call when making the change.

In `@src/components/trading/SellStableCoin.tsx`:
- Around line 18-36: The sell flow in handleSell jumps straight to
sellStableCoin without performing the token approval step; update handleSell to
mirror the buy pattern by first calling the contract approval helper (e.g.,
approveStableCoin or approveToken) with the parsedAmount and address, await its
confirmation before calling sellStableCoin(parsedAmount, address), and update
setStatus messages accordingly (e.g., "Approving tokens..." then "Executing sell
transaction..."); ensure you still wrap the whole flow in try/catch and
setLoading(false) in finally to preserve error handling.

In `@src/components/trading/TokenBalances.tsx`:
- Around line 5-6: Replace the placeholder literal addresses used in BASE_TOKEN
and STABLE_TOKEN with the actual configured token addresses (e.g., read from
your app config/environment) so balance reads work on real chains; update the
assignments for the BASE_TOKEN and STABLE_TOKEN constants in TokenBalances.tsx
to pull values from the configuration source (or a constants file) and preserve
the `0x${string}` typing to keep the address type checks intact.

In `@src/hooks/useDjedTransactions.ts`:
- Line 13: The hook fails because DJED_CONTRACT is being set from an undefined
DJED_ADDRESS; update useDjedTransactions.ts to reference the correct address
constant or import/define DJED_ADDRESS instead of the undefined symbol. Locate
the DJED_CONTRACT declaration and either (a) import DJED_ADDRESS from its module
(or use the existing exported constant name used elsewhere in the repo) and then
assign DJED_CONTRACT = DJED_ADDRESS as `0x${string}`, or (b) remove/reassign the
shadowed DJED_CONTRACT to use the already-defined contract address variable in
this module so the hook does not reference an undefined identifier.

---

Duplicate comments:
In `@src/hooks/useDjedTransactions.ts`:
- Around line 6-7: The code is unsafe because DJED_CONTRACT and BASE_TOKEN are
being force-cast from env vars without runtime checks; update
useDjedTransactions to validate these values at runtime (e.g., in the hook
initialization or a small helper) by ensuring they exist and match an Ethereum
address pattern (starts with "0x" and 40 hex chars), and surface a clear error
or throw with context if invalid/missing rather than silently casting; reference
the DJED_CONTRACT and BASE_TOKEN symbols and perform the check before any
transaction or contract instantiation in useDjedTransactions so consumers fail
fast with an actionable message.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 66ab69fd-4bc7-4218-9941-cd053d561cae

📥 Commits

Reviewing files that changed from the base of the PR and between d64a400 and 676ba26.

📒 Files selected for processing (4)
  • src/components/trading/BuyStableCoin.tsx
  • src/components/trading/SellStableCoin.tsx
  • src/components/trading/TokenBalances.tsx
  • src/hooks/useDjedTransactions.ts

Comment thread src/components/trading/BuyStableCoin.tsx Outdated
Comment thread src/components/trading/SellStableCoin.tsx Outdated
Comment thread src/components/trading/TokenBalances.tsx Outdated
Comment thread src/hooks/useDjedTransactions.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
src/components/trading/BuyStableCoin.tsx (1)

14-17: Fee calculation is a hardcoded client-side estimate.

The feeRate of 0.3% is hardcoded and may not reflect the actual protocol fee configured on-chain. Consider fetching the fee rate from the Djed contract or clearly labeling this as an "estimated" fee to avoid misleading users if the on-chain fee differs.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/trading/BuyStableCoin.tsx` around lines 14 - 17, The fee is
currently a hardcoded client-side estimate (feeRate, fee, receiveAmount in
BuyStableCoin) and may differ from the on-chain Djed protocol fee; update the
component to either (A) fetch the actual fee rate from the Djed contract (call
the contract method that returns the protocol fee, cache it, and compute fee =
Number(amount) * onChainFeeRate and receiveAmount accordingly) using your
existing web3/provider hooks, or (B) if on-chain fetching isn't available yet,
change the UI/labels to explicitly mark feeRate and receiveAmount as "Estimated
fee" and "Estimated receive amount" so users are not misled; update all
references to feeRate, fee, and receiveAmount and ensure errors/fallbacks are
handled when the on-chain call fails.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/trading/BuyStableCoin.tsx`:
- Around line 38-51: The approval is being granted to DJED_ADDRESS but the buy
uses DJED_CONTRACT (NEXT_PUBLIC_DJED_CONTRACT), causing an allowance mismatch;
update the approval call in the BuyStableCoin flow so it approves the exact
contract used by buyStableCoin: ensure approveBaseToken is called with the same
contract address symbol used by buyStableCoin (either DJED_CONTRACT or the
env-backed NEXT_PUBLIC_DJED_CONTRACT), or change addresses.ts to export the
env-backed value and replace DJED_ADDRESS with that symbol; make sure to update
references to BASE_COIN_ADDRESS and approveBaseToken to use the unified
DJED_CONTRACT symbol so both approval and buy reference the same spender
address.
- Around line 44-47: The optional chaining on publicClient when awaiting the
approval receipt can let the code continue without confirmation; update the
BuyStableCoin flow to explicitly guard that publicClient is present before
calling waitForTransactionReceipt (check publicClient and throw or return an
error if undefined), then call publicClient.waitForTransactionReceipt({ hash:
approveTx }) to actually await the approval; reference the publicClient,
waitForTransactionReceipt and approveTx symbols in your change and ensure the
buy transaction only proceeds after this awaited confirmation.

In `@src/hooks/useDjedTransactions.ts`:
- Line 6: The DJED_CONTRACT constant is being cast from
NEXT_PUBLIC_DJED_CONTRACT without runtime validation, which can produce
undefined at runtime; add a runtime check in useDjedTransactions.ts that
verifies process.env.NEXT_PUBLIC_DJED_CONTRACT is present and a valid
0x-prefixed hex string before assigning DJED_CONTRACT, and if invalid either
throw a clear error on startup or return a safe fallback/disable flows that call
writeContractAsync; reference the DJED_CONTRACT symbol and ensure callers like
writeContractAsync see a validated value (or short-circuit) so runtime failures
include a clear message about the missing/invalid NEXT_PUBLIC_DJED_CONTRACT.

---

Nitpick comments:
In `@src/components/trading/BuyStableCoin.tsx`:
- Around line 14-17: The fee is currently a hardcoded client-side estimate
(feeRate, fee, receiveAmount in BuyStableCoin) and may differ from the on-chain
Djed protocol fee; update the component to either (A) fetch the actual fee rate
from the Djed contract (call the contract method that returns the protocol fee,
cache it, and compute fee = Number(amount) * onChainFeeRate and receiveAmount
accordingly) using your existing web3/provider hooks, or (B) if on-chain
fetching isn't available yet, change the UI/labels to explicitly mark feeRate
and receiveAmount as "Estimated fee" and "Estimated receive amount" so users are
not misled; update all references to feeRate, fee, and receiveAmount and ensure
errors/fallbacks are handled when the on-chain call fails.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cdc6dc08-d173-4968-b851-8567eeb6d908

📥 Commits

Reviewing files that changed from the base of the PR and between 676ba26 and 742c554.

📒 Files selected for processing (4)
  • src/components/trading/BuyStableCoin.tsx
  • src/components/trading/SellStableCoin.tsx
  • src/components/trading/TokenBalances.tsx
  • src/hooks/useDjedTransactions.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/components/trading/TokenBalances.tsx
  • src/components/trading/SellStableCoin.tsx

Comment thread src/components/trading/BuyStableCoin.tsx Outdated
Comment thread src/components/trading/BuyStableCoin.tsx Outdated
Comment thread src/hooks/useDjedTransactions.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/trading/BuyStableCoin.tsx`:
- Around line 24-27: The check only rejects empty input but allows "0" or
negative values; update the form submit handler in the BuyStableCoin component
to validate the numeric value (parse amount to a number) and reject <= 0 before
proceeding (e.g., in the same block that currently checks if (!amount));
reference the amount variable and the submit handler (e.g., handleSubmit / onBuy
/ buyStableCoin function) and show a clear user-facing message (alert or form
error) and return early to avoid sending invalid transactions.

In `@src/utils/addresses.ts`:
- Around line 156-161: DJED_ADDRESS and the legacy exports (STABLE_COIN_ADDRESS,
RESERVE_COIN_ADDRESS, ORACLE_ADDRESS, COLLATERAL_ASSET_ADDRESS) can resolve to
invalid/placeholder addresses; validate NEXT_PUBLIC_DJED_CONTRACT at runtime
(use an isAddress/isHex checks and length 42) before casting and either throw or
set DJED_ADDRESS to undefined instead of forcing a typed string, and stop
deriving Sepolia addresses with hardcoded 11155111—use the active network/chain
id or environment-provided chain id when calling getStableCoinAddress,
getReserveCoinAddress, getOracleAddress, and getCollateralAssetAddress and
ensure those functions never return ZERO_ADDRESS (or convert ZERO_ADDRESS to
undefined/throw) so exports can’t silently point to unusable addresses (refer to
DJED_ADDRESS, getStableCoinAddress, getReserveCoinAddress, getOracleAddress,
getCollateralAssetAddress).
- Around line 144-153: There are two conflicting exports of
getCollateralAssetAddress causing a TypeScript error; remove the duplicate or
reconcile them by keeping a single export named getCollateralAssetAddress that
returns the intended type (either `0x${string}` or `0x${string} | null`) and
update any callers accordingly; locate both declarations (the one alongside
getDjedAddress/getStableCoinAddress/getReserveCoinAddress/getOracleAddress and
the later duplicate) and either delete the second definition or rename it if it
represents a different semantic (e.g., getOptionalCollateralAssetAddress) so
only one unambiguous export remains with a consistent signature.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 15248d36-be27-4b27-9c50-eae44ba8d9b8

📥 Commits

Reviewing files that changed from the base of the PR and between 742c554 and 916ccb9.

📒 Files selected for processing (5)
  • next.config.mjs
  • src/components/trading/BuyStableCoin.tsx
  • src/components/trading/TokenBalances.tsx
  • src/hooks/useDjedTransactions.ts
  • src/utils/addresses.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/hooks/useDjedTransactions.ts
  • src/components/trading/TokenBalances.tsx

Comment thread src/components/trading/BuyStableCoin.tsx Outdated
Comment thread src/utils/addresses.ts Outdated
Comment thread src/utils/addresses.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 6

♻️ Duplicate comments (2)
src/components/trading/BuyStableCoin.tsx (1)

100-114: ⚠️ Potential issue | 🔴 Critical

Critical: Inline ABI and contract target do not match the Djed protocol interface; approval step missing.

Same issue as SellStableCoin.tsx: the code calls buy(uint256) on stableCoinAddress, but per src/hooks/useDjedTransactions.ts:48-63, the canonical buy operation is buyStableCoins(receiver, feeUI, ui, amount) on the Djed contract.

The buy flow also requires approving the base coin (collateral) to the Djed contract before the buy transaction can succeed.

🐛 Proposed fix: Use the existing hook with proper approve → buy flow
+import { useDjedTransactions } from "@/hooks/useDjedTransactions";
+import { usePublicClient } from "wagmi";
+import { getDjedAddress } from "@/utils/addresses";
 ...
+  const { approveBaseToken, buyStableCoin } = useDjedTransactions();
+  const publicClient = usePublicClient();
 ...
     try {
       setLoading(true);
+      const djedAddress = getDjedAddress(chainId);
 
       const amountWei = parseUnits(amount, 18);
 
+      // Step 1: Approve base coin to Djed contract
+      setStatus?.("Approving BaseCoin...");
+      const approveTx = await approveBaseToken(collateralAddress, djedAddress, amountWei);
+      await publicClient?.waitForTransactionReceipt({ hash: approveTx });
+
+      // Step 2: Execute buy
+      setStatus?.("Executing buy...");
-      await writeContractAsync({
-        address: stableCoinAddress,
-        abi: [...],
-        functionName: "buy",
-        args: [amountWei],
-      });
+      const buyTx = await buyStableCoin(amountWei, address);
+      await publicClient?.waitForTransactionReceipt({ hash: buyTx });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/trading/BuyStableCoin.tsx` around lines 100 - 114, The current
code calls writeContractAsync with an inline ABI for buy(uint256) on
stableCoinAddress, but the Djed flow requires approving collateral and calling
the Djed contract's buyStableCoins(...) instead; replace the inline
writeContractAsync call in BuyStableCoin.tsx with the existing flow from
useDjedTransactions: first call the ERC20 approve on the base collateral token
to allow the Djed contract to spend amountWei (use the token's approve function
or the existing approve helper), then call buyStableCoins(receiver, feeUI, ui,
amount) from the Djed hook (instead of buy on stableCoinAddress), passing the
correct receiver, feeUI/ui values and amountWei; ensure you reference the Djed
contract address used by the hook and reuse the same amount/args naming as in
SellStableCoin.tsx to match the canonical flow.
src/components/trading/SellStableCoin.tsx (1)

85-98: ⚠️ Potential issue | 🔴 Critical

Critical: Inline ABI and contract target do not match the Djed protocol interface.

The code calls a sell(uint256) function on stableCoinAddress, but per src/hooks/useDjedTransactions.ts:65-80, the canonical sell operation is sellStableCoins(amount, receiver, feeUI, ui) on the Djed contract (not the stablecoin contract). This will cause transaction failures.

Additionally, selling ERC20 stablecoins back to the protocol typically requires an approval step (approve stablecoin → Djed contract) before the sell can execute.

🐛 Proposed fix: Use the existing hook or match the canonical interface
+import { useDjedTransactions } from "@/hooks/useDjedTransactions";
+import { usePublicClient } from "wagmi";
+import { getDjedAddress } from "@/utils/addresses";
 ...
+  const { approveBaseToken, sellStableCoin } = useDjedTransactions();
+  const publicClient = usePublicClient();
 ...
     try {
       setLoading(true);
+      const djedAddress = getDjedAddress(chainIdTyped);
 
       const amountWei = parseUnits(amount, 18);
 
-      await writeContractAsync({
-        address: stableCoinAddress,
-        abi: [
-          {
-            name: "sell",
-            type: "function",
-            stateMutability: "nonpayable",
-            inputs: [{ name: "amount", type: "uint256" }],
-            outputs: [],
-          },
-        ],
-        functionName: "sell",
-        args: [amountWei],
-      });
+      // Step 1: Approve stablecoin
+      setStatus?.("Approving StableCoin...");
+      const approveTx = await approveBaseToken(stableCoinAddress, djedAddress, amountWei);
+      await publicClient?.waitForTransactionReceipt({ hash: approveTx });
+
+      // Step 2: Execute sell
+      setStatus?.("Executing sell...");
+      const sellTx = await sellStableCoin(amountWei, address);
+      await publicClient?.waitForTransactionReceipt({ hash: sellTx });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/trading/SellStableCoin.tsx` around lines 85 - 98, In
SellStableCoin.tsx the code is calling sell(uint256) on stableCoinAddress which
mismatches the Djed protocol; change the flow to either use the existing hook
(from useDjedTransactions.ts) that invokes Djed.sellStableCoins(amount,
receiver, feeUI, ui) or construct a writeContractAsync against the Djed contract
ABI with functionName "sellStableCoins" and the correct args (amount, receiver,
feeUI, ui). Also add an ERC20 approval step: call approve(djedAddress,
amountWei) on the stable coin contract (stableCoinAddress) and wait for that tx
to confirm before calling sellStableCoins. Ensure you reference
stableCoinAddress, djedAddress (or the Djed contract used by
useDjedTransactions), sellStableCoins, and approve when making these changes.
🧹 Nitpick comments (2)
src/app/dashboard/page.tsx (1)

104-109: Reserve coin total supply read result is unused.

This useReadContract call doesn't capture data or refetch, making it effectively dead code. If the read is intentional, capture the result; otherwise, consider removing it.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/dashboard/page.tsx` around lines 104 - 109, The useReadContract call
invoking functionName "totalSupply" on reserveCoinAddress is unused; either
remove the call or capture its result (data, error, isLoading, refetch) so the
value is consumed. Update the useReadContract invocation inside page.tsx to
destructure the returned fields (e.g., const { data: totalSupply, refetch:
refetchTotalSupply, error, isLoading }) and then use totalSupply or
refetchTotalSupply where needed (or remove the hook entirely if the totalSupply
isn't required). Ensure the address/abi/functionName/ query options remain
unchanged when you keep the call.
src/components/trading/SellStableCoin.tsx (1)

27-27: Hardcoded fee duplicated across components; consider centralizing or reading from chain.

FEE_PERCENT = 3 is defined identically in both SellStableCoin.tsx and BuyStableCoin.tsx. If the protocol fee changes, the UI preview will silently diverge from actual on-chain behavior. Consider extracting to a shared constant or using useReadContract to fetch the actual fee from the Djed contract.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/trading/SellStableCoin.tsx` at line 27, FEE_PERCENT is
hardcoded in SellStableCoin.tsx (and duplicated in BuyStableCoin.tsx); replace
the local constant by reading the protocol fee from a single source: either
export a shared constant used by both components or fetch the on-chain fee via
useReadContract against the Djed contract and derive the percentage for UI
previews. Update SellStableCoin (and BuyStableCoin) to import the shared
constant or call the same hook (e.g., useDjedFee/useReadContract for Djed) and
remove the local FEE_PERCENT so both components always use the canonical fee
value.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/app/dashboard/page.tsx`:
- Around line 86-92: The useReadContract call that defines refetchOraclePrice is
using stableCoinAddress for the address but gating on oracleAddress, which is a
copy/paste error; update the useReadContract invocation (the refetch:
refetchOraclePrice definition) to use oracleAddress (e.g., address:
oracleAddress ?? undefined) with the same ORACLE_ABI and functionName "readData"
and keep the existing query.enabled condition (!!oracleAddress && isValidChain)
so the read targets the correct contract.
- Around line 94-102: The code uses a non-null assertion on stableCoinAddress
when calling useReadContract for totalSupply; replace the assertion with a safe
fallback (e.g., pass stableCoinAddress ?? undefined) so the hook receives
undefined instead of forcing a value, keeping query: { enabled:
!!stableCoinAddress && isValidChain } as the guard; update the useReadContract
invocation (the call that returns refetch: refetchStableSupply) to use the safe
address value and avoid the `!` operator while leaving COIN_ABI and
functionName: "totalSupply" unchanged.

In `@src/app/trade/page.tsx`:
- Around line 145-149: The useEffect that sets receiver when address connects
reads `receiver` but omits it from the dependency array; update the effect for
correct React semantics by adding `receiver` to the dependency array and keep
the guard so it only sets when `address` truthy and `receiver` falsy (i.e.,
change to useEffect(() => { if (address && !receiver) setReceiver(address); },
[address, receiver])); reference the existing useEffect, the `address` and
`receiver` variables and the `setReceiver` setter when making this change.
- Around line 1-2: Remove the top-level directives "/* eslint-disable */" and
"// `@ts-nocheck`" from src/app/trade/page.tsx and address the resulting
TypeScript/ESLint errors: add explicit types to the TradePage component props
and state, type any contract helpers (e.g., functions like fetchAllowance,
approveToken, executeTrade or useContract/getProvider/getSigner) with
appropriate ethers types (Provider, Signer, Contract), and tighten any untyped
variables (tokenAddress, amount, signer) to prevent implicit any; fix JSX/React
typing issues by typing event handlers and refs, and run the linter/TS compiler
to iterate until no errors remain.
- Around line 170-189: The functionName strings passed into writeContractAsync
are using incorrect casing for the stable-coin functions; update the conditional
that selects the function name (the ternary branch for tradeType ===
"buy-stable" and "sell-stable") to use "buyStableCoins" and "sellStableCoins"
respectively so they exactly match the ABI (DJED_ABI) entries; ensure
writeContractAsync continues to use the same tradeType branches and args mapping
when you change those two strings.

In `@src/utils/addresses.ts`:
- Around line 191-199: StableCoinFactories currently maps every chain to
ZERO_ADDRESS which causes create/page.tsx to treat all networks as unsupported
(it checks factoryAddress === ZERO_ADDRESS); replace the ZERO_ADDRESS
placeholders in the StableCoinFactories record with the real deployed factory
contract addresses for the chains you want to support (or remove unsupported
chain keys), ensuring the record keys (e.g., 1, 137, 56, 8453, 11155111, 61,
2001) map to actual hex contract addresses rather than ZERO_ADDRESS so create
flow sees a valid factoryAddress; keep the exported name StableCoinFactories and
the ZERO_ADDRESS constant references intact so other code still compiles.

---

Duplicate comments:
In `@src/components/trading/BuyStableCoin.tsx`:
- Around line 100-114: The current code calls writeContractAsync with an inline
ABI for buy(uint256) on stableCoinAddress, but the Djed flow requires approving
collateral and calling the Djed contract's buyStableCoins(...) instead; replace
the inline writeContractAsync call in BuyStableCoin.tsx with the existing flow
from useDjedTransactions: first call the ERC20 approve on the base collateral
token to allow the Djed contract to spend amountWei (use the token's approve
function or the existing approve helper), then call buyStableCoins(receiver,
feeUI, ui, amount) from the Djed hook (instead of buy on stableCoinAddress),
passing the correct receiver, feeUI/ui values and amountWei; ensure you
reference the Djed contract address used by the hook and reuse the same
amount/args naming as in SellStableCoin.tsx to match the canonical flow.

In `@src/components/trading/SellStableCoin.tsx`:
- Around line 85-98: In SellStableCoin.tsx the code is calling sell(uint256) on
stableCoinAddress which mismatches the Djed protocol; change the flow to either
use the existing hook (from useDjedTransactions.ts) that invokes
Djed.sellStableCoins(amount, receiver, feeUI, ui) or construct a
writeContractAsync against the Djed contract ABI with functionName
"sellStableCoins" and the correct args (amount, receiver, feeUI, ui). Also add
an ERC20 approval step: call approve(djedAddress, amountWei) on the stable coin
contract (stableCoinAddress) and wait for that tx to confirm before calling
sellStableCoins. Ensure you reference stableCoinAddress, djedAddress (or the
Djed contract used by useDjedTransactions), sellStableCoins, and approve when
making these changes.

---

Nitpick comments:
In `@src/app/dashboard/page.tsx`:
- Around line 104-109: The useReadContract call invoking functionName
"totalSupply" on reserveCoinAddress is unused; either remove the call or capture
its result (data, error, isLoading, refetch) so the value is consumed. Update
the useReadContract invocation inside page.tsx to destructure the returned
fields (e.g., const { data: totalSupply, refetch: refetchTotalSupply, error,
isLoading }) and then use totalSupply or refetchTotalSupply where needed (or
remove the hook entirely if the totalSupply isn't required). Ensure the
address/abi/functionName/ query options remain unchanged when you keep the call.

In `@src/components/trading/SellStableCoin.tsx`:
- Line 27: FEE_PERCENT is hardcoded in SellStableCoin.tsx (and duplicated in
BuyStableCoin.tsx); replace the local constant by reading the protocol fee from
a single source: either export a shared constant used by both components or
fetch the on-chain fee via useReadContract against the Djed contract and derive
the percentage for UI previews. Update SellStableCoin (and BuyStableCoin) to
import the shared constant or call the same hook (e.g.,
useDjedFee/useReadContract for Djed) and remove the local FEE_PERCENT so both
components always use the canonical fee value.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 15ea2bb7-b6c0-47f1-8caf-a9a25463afca

📥 Commits

Reviewing files that changed from the base of the PR and between 916ccb9 and aac0aac.

📒 Files selected for processing (7)
  • src/app/dashboard/page.tsx
  • src/app/trade/page.tsx
  • src/components/layout/Navbar.tsx
  • src/components/trading/BuyStableCoin.tsx
  • src/components/trading/SellStableCoin.tsx
  • src/components/trading/TokenBalances.tsx
  • src/utils/addresses.ts
💤 Files with no reviewable changes (1)
  • src/components/layout/Navbar.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/components/trading/TokenBalances.tsx

Comment on lines +86 to 92
const { refetch: refetchOraclePrice } =
useReadContract({
address: djed as `0x${string}` | undefined,
chainId,
query: {
enabled: isDeployedAddress(djed),
},
abi: DJED_ABI,
functionName: "rcTargetPrice",
args: [0n],
});

const { data: oraclePrice, refetch: refetchOraclePrice } = useReadContract({
address: oracle as `0x${string}` | undefined,
chainId,
abi: ORACLE_ABI,
functionName: "readData",
query: {
enabled: isDeployedAddress(oracle),
},
});

const { data: fee, refetch: refetchFee } = useReadContract({
address: djed as `0x${string}` | undefined,
chainId,
query: {
enabled: isDeployedAddress(djed),
},
abi: DJED_ABI,
functionName: "fee",
});

const { data: treasuryFee, refetch: refetchTreasuryFee } = useReadContract({
address: djed as `0x${string}` | undefined,
chainId,
query: {
enabled: isDeployedAddress(djed),
},
abi: DJED_ABI,
functionName: "treasuryFee",
});

const { data: txLimit, refetch: refetchTxLimit } = useReadContract({
address: djed as `0x${string}` | undefined,
chainId,
query: {
enabled: isDeployedAddress(djed),
},
abi: DJED_ABI,
functionName: "txLimit",
});

// Read system-wide token supplies
const { data: stablecoinTotalSupply, refetch: refetchStablecoinTotalSupply } =
useReadContract({
address: stableCoin as `0x${string}` | undefined,
chainId,
abi: COIN_ABI,
functionName: "totalSupply",
query: {
enabled: isDeployedAddress(stableCoin),
},
address: stableCoinAddress ?? undefined,
abi: ORACLE_ABI,
functionName: "readData",
query: { enabled: !!oracleAddress && isValidChain },
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Address mismatch: Oracle read uses wrong contract address.

The readData call is made to stableCoinAddress, but the enabled condition checks oracleAddress. This appears to be a copy/paste error—the read should target oracleAddress:

🐛 Proposed fix
   const { refetch: refetchOraclePrice } =
     useReadContract({
-      address: stableCoinAddress ?? undefined,
+      address: oracleAddress ?? undefined,
       abi: ORACLE_ABI,
       functionName: "readData",
       query: { enabled: !!oracleAddress && isValidChain },
     });
📝 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
const { refetch: refetchOraclePrice } =
useReadContract({
address: djed as `0x${string}` | undefined,
chainId,
query: {
enabled: isDeployedAddress(djed),
},
abi: DJED_ABI,
functionName: "rcTargetPrice",
args: [0n],
});
const { data: oraclePrice, refetch: refetchOraclePrice } = useReadContract({
address: oracle as `0x${string}` | undefined,
chainId,
abi: ORACLE_ABI,
functionName: "readData",
query: {
enabled: isDeployedAddress(oracle),
},
});
const { data: fee, refetch: refetchFee } = useReadContract({
address: djed as `0x${string}` | undefined,
chainId,
query: {
enabled: isDeployedAddress(djed),
},
abi: DJED_ABI,
functionName: "fee",
});
const { data: treasuryFee, refetch: refetchTreasuryFee } = useReadContract({
address: djed as `0x${string}` | undefined,
chainId,
query: {
enabled: isDeployedAddress(djed),
},
abi: DJED_ABI,
functionName: "treasuryFee",
});
const { data: txLimit, refetch: refetchTxLimit } = useReadContract({
address: djed as `0x${string}` | undefined,
chainId,
query: {
enabled: isDeployedAddress(djed),
},
abi: DJED_ABI,
functionName: "txLimit",
});
// Read system-wide token supplies
const { data: stablecoinTotalSupply, refetch: refetchStablecoinTotalSupply } =
useReadContract({
address: stableCoin as `0x${string}` | undefined,
chainId,
abi: COIN_ABI,
functionName: "totalSupply",
query: {
enabled: isDeployedAddress(stableCoin),
},
address: stableCoinAddress ?? undefined,
abi: ORACLE_ABI,
functionName: "readData",
query: { enabled: !!oracleAddress && isValidChain },
});
const { refetch: refetchOraclePrice } =
useReadContract({
address: oracleAddress ?? undefined,
abi: ORACLE_ABI,
functionName: "readData",
query: { enabled: !!oracleAddress && isValidChain },
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/dashboard/page.tsx` around lines 86 - 92, The useReadContract call
that defines refetchOraclePrice is using stableCoinAddress for the address but
gating on oracleAddress, which is a copy/paste error; update the useReadContract
invocation (the refetch: refetchOraclePrice definition) to use oracleAddress
(e.g., address: oracleAddress ?? undefined) with the same ORACLE_ABI and
functionName "readData" and keep the existing query.enabled condition
(!!oracleAddress && isValidChain) so the read targets the correct contract.

Comment on lines 94 to 102
const {
data: reserveCoinTotalSupply,
refetch: refetchReserveCoinTotalSupply,
} = useReadContract({
address: reserveCoin as `0x${string}` | undefined,
chainId,

refetch: refetchStableSupply,
} = useReadContract({
address: stableCoinAddress!,
abi: COIN_ABI,
functionName: "totalSupply",
query: {
enabled: isDeployedAddress(reserveCoin),
},
query: { enabled: !!stableCoinAddress && isValidChain },
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Avoid non-null assertion on potentially undefined address.

Line 98 uses stableCoinAddress! but the variable can be undefined. While query.enabled guards execution, it's safer and more consistent with other reads in this file to use stableCoinAddress ?? undefined:

🛡️ Proposed fix
   const {
     refetch: refetchStableSupply,
   } = useReadContract({
-    address: stableCoinAddress!,
+    address: stableCoinAddress ?? undefined,
     abi: COIN_ABI,
     functionName: "totalSupply",
     query: { enabled: !!stableCoinAddress && isValidChain },
   });
📝 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
const {
data: reserveCoinTotalSupply,
refetch: refetchReserveCoinTotalSupply,
} = useReadContract({
address: reserveCoin as `0x${string}` | undefined,
chainId,
refetch: refetchStableSupply,
} = useReadContract({
address: stableCoinAddress!,
abi: COIN_ABI,
functionName: "totalSupply",
query: {
enabled: isDeployedAddress(reserveCoin),
},
query: { enabled: !!stableCoinAddress && isValidChain },
});
const {
refetch: refetchStableSupply,
} = useReadContract({
address: stableCoinAddress ?? undefined,
abi: COIN_ABI,
functionName: "totalSupply",
query: { enabled: !!stableCoinAddress && isValidChain },
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/dashboard/page.tsx` around lines 94 - 102, The code uses a non-null
assertion on stableCoinAddress when calling useReadContract for totalSupply;
replace the assertion with a safe fallback (e.g., pass stableCoinAddress ??
undefined) so the hook receives undefined instead of forcing a value, keeping
query: { enabled: !!stableCoinAddress && isValidChain } as the guard; update the
useReadContract invocation (the call that returns refetch: refetchStableSupply)
to use the safe address value and avoid the `!` operator while leaving COIN_ABI
and functionName: "totalSupply" unchanged.

Comment thread src/app/trade/page.tsx
Comment on lines 1 to 2
/* eslint-disable */
// @ts-nocheck

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Disabling ESLint and TypeScript checking hides potential runtime errors.

/* eslint-disable */ and // @ts-nocheck`` suppress all static analysis, which defeats the purpose of type safety in a financial transaction component. This is particularly risky given the contract interaction code below. Remove these directives and fix the underlying type issues.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/trade/page.tsx` around lines 1 - 2, Remove the top-level directives
"/* eslint-disable */" and "// `@ts-nocheck`" from src/app/trade/page.tsx and
address the resulting TypeScript/ESLint errors: add explicit types to the
TradePage component props and state, type any contract helpers (e.g., functions
like fetchAllowance, approveToken, executeTrade or
useContract/getProvider/getSigner) with appropriate ethers types (Provider,
Signer, Contract), and tighten any untyped variables (tokenAddress, amount,
signer) to prevent implicit any; fix JSX/React typing issues by typing event
handlers and refs, and run the linter/TS compiler to iterate until no errors
remain.

Comment thread src/app/trade/page.tsx
Comment on lines +145 to +149
useEffect(() => {
if (address && !receiver) {
setReceiver(address);
}
}, [
tradeType,
parsedAmount,
parsedAmountRC,
receiver,
address,
writeContractAsync,
contractAddress,
]);
}, [address]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Missing receiver in useEffect dependency array (hidden by eslint-disable).

The effect reads receiver but doesn't include it in the dependency array. While the current logic may be intentional (only set receiver once when address connects), this pattern would normally trigger an ESLint warning that's being suppressed by the file-level disable.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/trade/page.tsx` around lines 145 - 149, The useEffect that sets
receiver when address connects reads `receiver` but omits it from the dependency
array; update the effect for correct React semantics by adding `receiver` to the
dependency array and keep the guard so it only sets when `address` truthy and
`receiver` falsy (i.e., change to useEffect(() => { if (address && !receiver)
setReceiver(address); }, [address, receiver])); reference the existing
useEffect, the `address` and `receiver` variables and the `setReceiver` setter
when making this change.

Comment thread src/app/trade/page.tsx
Comment on lines +170 to +189
await writeContractAsync({
address: contractAddress,
abi: DJED_ABI,
functionName:
tradeType === "buy-stable"
? "buyStablecoins"
: tradeType === "sell-stable"
? "sellStablecoins"
: tradeType === "buy-reserve"
? "buyReserveCoins"
: tradeType === "sell-reserve"
? "sellReserveCoins"
: "sellBothCoins",
args:
tradeType === "sell-both"
? [amountBN, parseUnits(amountRC || "0", 18), receiver, 0n, address]
: tradeType === "sell-stable"
? [amountBN, receiver, 0n, address]
: [receiver, 0n, address, amountBN],
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify the exact function names in the Djed ABI
cat src/utils/abi/Djed.json | jq -r '.[].name' | grep -i 'stablecoin' | sort -u

Repository: DjedAlliance/Djed-Solidity-ERC20BaseCoin-WebUI

Length of output: 165


🏁 Script executed:

sed -n '170,189p' src/app/trade/page.tsx

Repository: DjedAlliance/Djed-Solidity-ERC20BaseCoin-WebUI

Length of output: 764


🏁 Script executed:

cat src/utils/abi/Djed.json | jq -r '.[].name' | grep -E '(Coins|Coin)' | sort -u

Repository: DjedAlliance/Djed-Solidity-ERC20BaseCoin-WebUI

Length of output: 283


Fix function name casing for buyStableCoins and sellStableCoins.

The code uses "buyStablecoins" and "sellStablecoins" (lowercase 'c'), but the ABI defines them as buyStableCoins and sellStableCoins (capital 'C'). Function selectors in Web3 calls are case-sensitive; these mismatches will cause the buy-stable and sell-stable transactions to fail at runtime.

Change:

  • "buyStablecoins""buyStableCoins"
  • "sellStablecoins""sellStableCoins"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/trade/page.tsx` around lines 170 - 189, The functionName strings
passed into writeContractAsync are using incorrect casing for the stable-coin
functions; update the conditional that selects the function name (the ternary
branch for tradeType === "buy-stable" and "sell-stable") to use "buyStableCoins"
and "sellStableCoins" respectively so they exactly match the ABI (DJED_ABI)
entries; ensure writeContractAsync continues to use the same tradeType branches
and args mapping when you change those two strings.

Comment thread src/utils/addresses.ts
Comment on lines +191 to 199
export const StableCoinFactories: Record<number, `0x${string}`> = {
1: ZERO_ADDRESS,
137: ZERO_ADDRESS,
56: ZERO_ADDRESS,
8453: ZERO_ADDRESS,
11155111: ZERO_ADDRESS,
61: ZERO_ADDRESS,
2001: ZERO_ADDRESS,
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

StableCoinFactories all zero—create page is non-functional.

Per src/app/create/page.tsx:97-102, the create flow checks factoryAddress === ZERO_ADDRESS and displays "Unsupported network" for any chain. With all entries set to ZERO_ADDRESS, the create functionality is completely disabled.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/addresses.ts` around lines 191 - 199, StableCoinFactories currently
maps every chain to ZERO_ADDRESS which causes create/page.tsx to treat all
networks as unsupported (it checks factoryAddress === ZERO_ADDRESS); replace the
ZERO_ADDRESS placeholders in the StableCoinFactories record with the real
deployed factory contract addresses for the chains you want to support (or
remove unsupported chain keys), ensuring the record keys (e.g., 1, 137, 56,
8453, 11155111, 61, 2001) map to actual hex contract addresses rather than
ZERO_ADDRESS so create flow sees a valid factoryAddress; keep the exported name
StableCoinFactories and the ZERO_ADDRESS constant references intact so other
code still compiles.

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.

Smart Contract Integration and Transaction Handling

1 participant