feat: implement trading interface and smart contract integration#29
feat: implement trading interface and smart contract integration#29Rav1Chauhan wants to merge 10 commits into
Conversation
|
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds 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
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
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
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (3)
src/components/trading/BuyStableCoin.tsx (1)
18-53: Inconsistent indentation inhandleBuyfunction.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
📒 Files selected for processing (5)
src/app/page.tsxsrc/components/trading/BuyStableCoin.tsxsrc/components/trading/SellStableCoin.tsxsrc/components/trading/TokenBalances.tsxsrc/hooks/useDjedTransactions.ts
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>
There was a problem hiding this comment.
Actionable comments posted: 4
♻️ Duplicate comments (1)
src/hooks/useDjedTransactions.ts (1)
6-7:⚠️ Potential issue | 🟠 MajorAdd 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
📒 Files selected for processing (4)
src/components/trading/BuyStableCoin.tsxsrc/components/trading/SellStableCoin.tsxsrc/components/trading/TokenBalances.tsxsrc/hooks/useDjedTransactions.ts
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
src/components/trading/BuyStableCoin.tsx (1)
14-17: Fee calculation is a hardcoded client-side estimate.The
feeRateof 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
📒 Files selected for processing (4)
src/components/trading/BuyStableCoin.tsxsrc/components/trading/SellStableCoin.tsxsrc/components/trading/TokenBalances.tsxsrc/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
There was a problem hiding this comment.
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
📒 Files selected for processing (5)
next.config.mjssrc/components/trading/BuyStableCoin.tsxsrc/components/trading/TokenBalances.tsxsrc/hooks/useDjedTransactions.tssrc/utils/addresses.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- src/hooks/useDjedTransactions.ts
- src/components/trading/TokenBalances.tsx
There was a problem hiding this comment.
Actionable comments posted: 6
♻️ Duplicate comments (2)
src/components/trading/BuyStableCoin.tsx (1)
100-114:⚠️ Potential issue | 🔴 CriticalCritical: Inline ABI and contract target do not match the Djed protocol interface; approval step missing.
Same issue as
SellStableCoin.tsx: the code callsbuy(uint256)onstableCoinAddress, but persrc/hooks/useDjedTransactions.ts:48-63, the canonical buy operation isbuyStableCoins(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 | 🔴 CriticalCritical: Inline ABI and contract target do not match the Djed protocol interface.
The code calls a
sell(uint256)function onstableCoinAddress, but persrc/hooks/useDjedTransactions.ts:65-80, the canonical sell operation issellStableCoins(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
useReadContractcall doesn't capturedataorrefetch, 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 = 3is defined identically in bothSellStableCoin.tsxandBuyStableCoin.tsx. If the protocol fee changes, the UI preview will silently diverge from actual on-chain behavior. Consider extracting to a shared constant or usinguseReadContractto 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
📒 Files selected for processing (7)
src/app/dashboard/page.tsxsrc/app/trade/page.tsxsrc/components/layout/Navbar.tsxsrc/components/trading/BuyStableCoin.tsxsrc/components/trading/SellStableCoin.tsxsrc/components/trading/TokenBalances.tsxsrc/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
| 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 }, | ||
| }); |
There was a problem hiding this comment.
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.
| 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.
| 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 }, | ||
| }); |
There was a problem hiding this comment.
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.
| 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.
| /* eslint-disable */ | ||
| // @ts-nocheck |
There was a problem hiding this comment.
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.
| useEffect(() => { | ||
| if (address && !receiver) { | ||
| setReceiver(address); | ||
| } | ||
| }, [ | ||
| tradeType, | ||
| parsedAmount, | ||
| parsedAmountRC, | ||
| receiver, | ||
| address, | ||
| writeContractAsync, | ||
| contractAddress, | ||
| ]); | ||
| }, [address]); |
There was a problem hiding this comment.
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.
| 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], | ||
| }); |
There was a problem hiding this comment.
🧩 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 -uRepository: DjedAlliance/Djed-Solidity-ERC20BaseCoin-WebUI
Length of output: 165
🏁 Script executed:
sed -n '170,189p' src/app/trade/page.tsxRepository: 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 -uRepository: 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.
| 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, | ||
| }; |
There was a problem hiding this comment.
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.
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)
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
AI Usage Disclosure
Check one of the checkboxes below:
I have used the following AI models and tools: TODO
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
UI Changes
Bug Fixes