Skip to content

Impl Stellar UI integrations#115

Merged
JoE11-y merged 6 commits intomainfrom
stellar-integrations
Apr 14, 2026
Merged

Impl Stellar UI integrations#115
JoE11-y merged 6 commits intomainfrom
stellar-integrations

Conversation

@JoE11-y
Copy link
Copy Markdown
Contributor

@JoE11-y JoE11-y commented Apr 13, 2026

Stellar integrations

Adds end-to-end Stellar support to ProofBridge alongside the existing EVM flow: Soroban contracts, chain-kind-aware backend relayer, SEP-43 signing in the frontend, and full EVM↔Stellar cross-chain e2e tooling.

Scope

Backend relayer

  • API hygiene: ValidationPipe({ whitelist, forbidNonWhitelisted }) globally; list endpoints standardized on { data, nextCursor } (was rows); IFundAdResponse.amount / IAd.minAmount|maxAmount / IUpdateAdResponse DTO types aligned with runtime shape.
  • Ad adToken / orderToken embeds now include assetIssuer for client-side trustline checks.

Frontend

  • Stellar wallet provider (StellarWalletProvider) built on @creit.tech/stellar-wallets-kit with Freighter/Albedo/Lobstr/xBull/Rabet/Hana modules and a signMessage API for SEP-43 off-chain signatures.
  • Stellar-aware flows for create-ad, fund-ad, withdraw, close-ad, create-trade, unlock — each branches on chainKind and picks the appropriate wallet (0x EVM vs G… strkey) for recipient addresses.
  • SEP-43 unlock signing for Stellar trades: verifyOrderSignature does off-chain Ed25519 verification against "Stellar Signed Message:\n" + orderHash; no on-chain impact.
  • isAdCreator via shape discrimination on orderParams (adManager field ⇒ OrderPortal side, srcOrderPortal ⇒ AdManager side) — fixes a prior bug where address comparison broke under bytes32 padding on EVM.
  • SAC trustline UX: assertRecipientTrustline preflights withdraw/close to Stellar SAC recipients and surfaces a clear error when the destination has no trustline, instead of letting the Soroban call revert.
  • Horizon balance reads in TradeAd for NATIVE/SAC tokens when the order chain is Stellar; wagmi useBalance is gated off on that branch.
  • Unified connectionAction in TradeAd — replaces nested ternaries and a dead "Connect Stellar wallet" button with a priority ladder: pay-side wallet → chain switch → destination-wallet → bridge. Cross-chain EVM↔Stellar trades now require (and surface) both wallets instead of throwing at runtime.
  • Removed unused SellAdd.tsx stub; TradeAd already covers both directions.

Test plan

  • pnpm --filter @proofbridge/backend-relayer test (unit + e2e)
  • bash scripts/relayer-e2e/e2e.sh against a local relayer
  • pnpm --filter scripts/cross-chain-e2e start — EVM↔Stellar round trip
  • Frontend: create ad on Stellar (SAC + NATIVE), fund, partial withdraw, close; create trade EVM→Stellar and Stellar→EVM; confirm unlock signature flow on both sides.
  • Frontend wallet-connect ladder: disconnect each wallet individually and confirm TradeAd surfaces the correct next step (connect pay / switch chain / connect destination / bridge).
  • SAC trustline: withdraw to a recipient with no trustline — confirm preflight error fires before the Soroban call.

Summary by CodeRabbit

  • New Features

    • Added Stellar support, wallet connectivity, and Soroban flows; bridge now works across Ethereum & Stellar
    • Introduced SAC and SEP41 token types and Stellar token issuer handling
  • UI Updates

    • Updated landing/bridge copy to reflect Ethereum & Stellar
    • Improved wallet connection UI and chain-aware address formatting
  • API Changes

    • Chain/list pagination renamed to data and token responses include assetIssuer and chainKind

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 13, 2026

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

Adds Stellar (Soroban) support across frontend and backend: database schema (Token.assetIssuer), token/chain kind fields, signature handling for EVM and Stellar, Stellar wallet/provider and SEP-10 auth, Soroban invocation/trustline utilities, ABI and types updates, and multiple frontend/ backend DTO/service adaptations.

Changes

Cohort / File(s) Summary
Database & Prisma
apps/backend-relayer/prisma/migrations/..._add_token_asset_issuer/migration.sql, apps/backend-relayer/prisma/schema.prisma
Add assetIssuer TEXT column and nullable assetIssuer String? on Token.
Backend: Chain adapters & Stellar provider
apps/backend-relayer/src/chain-adapters/.../chain-adapter.abstract.ts, .../evm-chain-adapter.ts, .../stellar-chain-adapter.ts, apps/backend-relayer/src/providers/stellar/stellar.service.ts
Widened verifyOrderSignature signature param to string; EVM adapter adds runtime hex validation; Stellar provider accepts hex/base64 and verifies against a SEP-43-like signed message preimage.
Backend: Token, Ads, Routes, Trades, Types
apps/backend-relayer/src/modules/token/*, src/modules/ads/*, src/modules/routes/route.service.ts, src/modules/trades/*, src/types/index.d.ts
Add assetIssuer handling, include chain.kind in selects, add chainKind to responses/DTOs, validate SAC rules in token service, extend trade flows to surface chainKind and orderHash.
Backend: Validation, tests, main
apps/backend-relayer/src/main.ts, src/modules/admin/admin.controller.spec.ts, src/modules/chains/*, test/e2e/*.ts
Enable ValidationPipe whitelist/forbidNonWhitelisted; update unit/e2e test fixtures and response shape (rowsdata).
Frontend: Stellar wallet & auth
apps/frontend/components/providers/StellarWallet.tsx, apps/frontend/hooks/useStellarAuth.ts, apps/frontend/services/auth.service.ts, apps/frontend/components/providers/RainbowKit.tsx, apps/frontend/components/connect-wallet/ConnectWalletButton.tsx
Add StellarWalletProvider and hooks, implement SEP-10 login flow and shared auth service; adapt RainbowKit auth plumbing and Connect button to include Stellar flows.
Frontend: Soroban / Stellar utilities
apps/frontend/utils/stellar/*, apps/frontend/lib/stellar-adapter.ts, apps/frontend/utils/stellar/*
New Soroban invoke, scval, actions, trustline, address conversions, balance fetchers, and adapter/hooks for signing and RPC interaction.
Frontend: EVM utilities & typed-data
apps/frontend/utils/evm/typedData.ts, apps/frontend/utils/evm/address.ts, apps/frontend/utils/evm/index.ts
Add EIP-712 typed-data helpers, hex32↔address utilities, and barrel exports for reuse.
Frontend: Address formatting & amounts
apps/frontend/utils/format-address.ts, apps/frontend/utils/amount.ts
Add chain-aware formatting (EVM vs Stellar) and toBaseUnits with chain-specific default decimals.
Frontend: Hooks & components (bridge/trades/ads)
apps/frontend/hooks/useAds.ts, apps/frontend/hooks/useTrades.ts, apps/frontend/components/bridge-ui/*, apps/frontend/components/ad-management-ui/*, apps/frontend/components/orders/OrdersTable.tsx
Branch create/lock/unlock/ad flows for STELLAR vs EVM, add trustline checks/establishment, integrate Stellar signer/address selection, update balance logic and address formatting, remove SellAd component.
Frontend: ABIs & contract surface
apps/frontend/abis/AdManager.abi.ts, apps/frontend/abis/orderPortal.abi.ts, apps/frontend/abis/ERC20.abi.ts
Rewrote/retyped ABIs (many params changed, address→bytes32 in places), converted to as const, adjusted events/errors to match cross-chain bytes32 usage.
Frontend: Types
apps/frontend/types/chains.ts, apps/frontend/types/tokens.ts, apps/frontend/types/trades.ts, apps/frontend/types/ads.ts, apps/frontend/types/*
Introduce ChainKind and TokenKind; split chain/token shapes into discriminated unions (EVM vs STELLAR); add assetIssuer and chainKind fields to responses and request DTOs; adjust many request/response types to string/bigint shapes.
Frontend: Services, env, packaging
apps/frontend/services/*, apps/frontend/.env.example, apps/frontend/package.json
Switch to shared api client, update chain list response handling, add Stellar SDK and wallets-kit deps, add env example variables.
E2E & deployment scripts
scripts/cross-chain-e2e/*, scripts/relayer-e2e/*
Deploy/link Stellar order portal, add adManager on EVM, seed assetIssuer and tokenKind, adjust e2e flows to use Stellar preimage signing and query param name changes.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Frontend
  participant Relayer
  participant StellarRPC
  participant Database
  rect rgba(100,149,237,0.5)
  User->>Frontend: open login (Stellar)
  Frontend->>StellarRPC: request connect / sign XDR (StellarWalletProvider)
  StellarRPC-->>Frontend: signed XDR
  Frontend->>Relayer: POST /v1/auth/login (signed XDR, chainKind=STELLAR)
  Relayer->>Relayer: verify SEP-10 sig (stellar.service)
  Relayer->>Database: lookup/create user, issue tokens
  Relayer-->>Frontend: return tokens (auth_token, refresh_token)
  Frontend->>User: store cookies, reload
  end
Loading
sequenceDiagram
  participant User
  participant Frontend
  participant Relayer
  participant SorobanRPC
  participant EVM
  rect rgba(34,139,34,0.5)
  User->>Frontend: create/ad (SAC token)
  Frontend->>Frontend: ensure trustline (trustline.ts) -> if missing sign+submit
  Frontend->>SorobanRPC: invoke create_ad (invokeSoroban via StellarAdapter)
  SorobanRPC-->>Frontend: txHash
  Frontend->>Relayer: POST createAd (chainKind=STELLAR, reqContractDetails)
  Relayer->>Database: persist ad with assetIssuer
  Relayer-->>Frontend: ad created response
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

Suggested reviewers

  • Ugo-X

"🐰
I hopped through code in moonlit night,
Added Stellar wallets, signed messages bright,
Trustlines set and Soroban calls play,
EVM and Stellar now bridge the way,
A little carrot for every merged byte."

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 32.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Impl Stellar UI integrations' refers to a real and significant part of the changeset (frontend Stellar wallet provider, Stellar-aware component flows, SEP-43 signing), but it does not capture the broader scope of the changes. The PR also includes substantial backend schema changes, validation improvements, standardized API responses, and cross-chain infrastructure. The title is too narrow to summarize the main architectural changes.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch stellar-integrations

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 11

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
apps/frontend/package.json (1)

32-33: ⚠️ Potential issue | 🟡 Minor

React and ReactDOM version mismatch.

react is pinned to 19.1.0 while react-dom is at 19.2.5. These packages should typically use matching versions to avoid potential subtle runtime inconsistencies or compatibility issues.

Proposed fix
-    "react": "19.1.0",
-    "react-dom": "19.2.5",
+    "react": "19.2.5",
+    "react-dom": "19.2.5",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/frontend/package.json` around lines 32 - 33, The package.json has
mismatched React versions: "react" is 19.1.0 while "react-dom" is 19.2.5; update
the dependencies so both "react" and "react-dom" use the same version (pick a
single canonical version, e.g., set "react" to "19.2.5" to match "react-dom" or
align both to a chosen release), then reinstall to update the lockfile
(npm/yarn/pnpm install) and run the app/tests/build to verify compatibility;
modify the "react" and/or "react-dom" entries in package.json accordingly.
apps/backend-relayer/src/modules/trades/trade.service.ts (1)

1291-1291: ⚠️ Potential issue | 🟡 Minor

Remove debug console.log statement.

This appears to be a debug artifact that should be removed before merging:

-      console.log(dto);
-
       return {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/backend-relayer/src/modules/trades/trade.service.ts` at line 1291,
Remove the debug console.log(dto) statement found in trade.service.ts (inside
the relevant TradeService method handling the DTO) — delete the console.log call
or replace it with the module's proper logger (e.g., this.logger.debug or
processLogger.debug) if the DTO needs to be recorded, ensuring no raw console
logs remain in production code.
🧹 Nitpick comments (12)
apps/backend-relayer/src/modules/ads/dto/ad.dto.ts (1)

248-259: LGTM — consider tightening the TypeScript type for consistency.

The addition of chainKind and the expanded kind enum correctly support Stellar token types. Note that TokenDto.chainKind is typed as string while the response DTOs (e.g., CreateAdResponseDto.chainKind) use the stricter 'EVM' | 'STELLAR' union. For consistency, consider:

-  chainKind!: string;
+  chainKind!: 'EVM' | 'STELLAR';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/backend-relayer/src/modules/ads/dto/ad.dto.ts` around lines 248 - 259,
TokenDto has loose string types for chainKind and kind; tighten them to match
the response DTO unions by changing the property types on the TokenDto class:
set chainKind to the literal union 'EVM' | 'STELLAR' and set kind to the literal
union 'ERC20' | 'NATIVE' | 'SAC' | 'SEP41' (keeping the existing `@ApiProperty`
enum metadata as-is) so consumers and CreateAdResponseDto remain consistent with
these exact values.
apps/backend-relayer/src/modules/routes/route.service.ts (1)

93-107: Extract duplicated token select into a shared constant.

The same nested adToken/orderToken select shape is repeated across list/get/create, which makes schema evolution error-prone.

Refactor sketch
+const tokenSelect = {
+  id: true,
+  symbol: true,
+  name: true,
+  address: true,
+  decimals: true,
+  kind: true,
+  assetIssuer: true,
+  chain: { select: { id: true, name: true, chainId: true, kind: true } },
+} as const;

 // then reuse:
 adToken: {
-  select: { ...full object... }
+  select: tokenSelect
 },
 orderToken: {
-  select: { ...full object... }
+  select: tokenSelect
 },

Also applies to: 155-168, 239-253

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

In `@apps/backend-relayer/src/modules/routes/route.service.ts` around lines 93 -
107, Extract the repeated nested select shape for adToken/orderToken into a
shared constant (e.g., TOKEN_SELECT or TOKEN_WITH_CHAIN) in route.service.ts and
replace the duplicated select objects used in the list/get/create query calls;
specifically locate the repeated select blocks referenced for adToken and
orderToken in the functions that perform list/get/create operations and
substitute them with the single shared constant (export it if other modules need
it), ensuring the constant includes the chain: { select: { id, name, chainId,
kind } } structure and the token fields id, symbol, name, address, decimals,
kind, assetIssuer so all queries reference the same shape.
apps/backend-relayer/prisma/schema.prisma (1)

86-88: Enforce assetIssuer/Token.kind invariant at the database layer.

Right now this rule exists only in comments. Add a DB check constraint so data can’t drift from the intended SAC-only semantics.

Proposed migration snippet
+-- In a new SQL migration:
+ALTER TABLE "Token"
+ADD CONSTRAINT "token_assetIssuer_kind_check"
+CHECK (
+  ("kind" = 'SAC' AND "assetIssuer" IS NOT NULL)
+  OR
+  ("kind" <> 'SAC' AND "assetIssuer" IS NULL)
+);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/backend-relayer/prisma/schema.prisma` around lines 86 - 88, Add a
DB-level CHECK constraint so Token.kind and assetIssuer cannot drift from the
SAC-only rule: ensure that when Token.kind = 'SAC' then assetIssuer IS NOT NULL,
and when Token.kind != 'SAC' then assetIssuer IS NULL. Implement this by adding
a SQL migration that runs ALTER TABLE "Token" ADD CONSTRAINT
token_assetissuer_kind_check CHECK ((kind = 'SAC' AND assetIssuer IS NOT NULL)
OR (kind <> 'SAC' AND assetIssuer IS NULL)); and update any Prisma migration
metadata so the constraint is tracked (keep the Prisma schema Token model
unchanged except for mapping if needed).
apps/frontend/lib/chains.ts (1)

9-17: Consider externalizing the Stellar chain ID instead of hard-coding it.

If backend seed/config changes, this can silently hide valid chains in selectors. Prefer env/config-driven wiring.

Possible refactor
-export const STELLAR_TESTNET_CHAIN_ID = "1000001"
+export const STELLAR_TESTNET_CHAIN_ID =
+  process.env.NEXT_PUBLIC_STELLAR_TESTNET_CHAIN_ID ?? "1000001"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/frontend/lib/chains.ts` around lines 9 - 17, Replace the hard-coded
STELLAR_TESTNET_CHAIN_ID with a config-driven value so UI selectors reflect
backend changes: read the chain id from a runtime config or env (e.g.
NEXT_PUBLIC_STELLAR_TESTNET_CHAIN_ID) and fall back to the existing "1000001"
constant; update the STELLAR_TESTNET_CHAIN_ID declaration and ensure
VISIBLE_CHAIN_IDS uses that config value (referencing STELLAR_TESTNET_CHAIN_ID
and VISIBLE_CHAIN_IDS) so changes to backend seed/config automatically surface
in the front-end selectors.
apps/frontend/components/ad-management-ui/AddLiquidity.tsx (1)

109-109: Silent error swallowing in handleCreateAd.

The empty catch block discards all errors, making debugging difficult. Consider at least logging the error or showing a toast notification.

♻️ Proposed fix
-    } catch (error) { }
+    } catch (error) {
+      console.error("Failed to create ad:", error)
+      // Consider adding a toast notification here
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/frontend/components/ad-management-ui/AddLiquidity.tsx` at line 109, The
catch block in handleCreateAd silently swallows errors; modify the catch in
AddLiquidity's handleCreateAd to log the error (e.g., console.error or process
logger) and/or surface a user-facing notification (toast) with a helpful
message; ensure you reference the caught error variable and include context like
"Failed to create ad" when logging or notifying so debugging and UX are
improved.
apps/frontend/components/bridge-ui/BridgeTab.tsx (1)

48-52: Inconsistent API shape in commented code.

The commented code checks chains?.data.length but accesses chains.rows[0]. If this code is uncommented, it will fail. Consider either fixing or removing this dead code.

♻️ Fix or remove
-  // useEffect(() => {
-  //   if (chains?.data.length) {
-  //     setSelectedBaseChainId(chains.rows[0].chainId)
-  //   }
-  // }, [chains])
+  // Removed stale commented code that referenced old API shape
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/frontend/components/bridge-ui/BridgeTab.tsx` around lines 48 - 52, The
commented useEffect contains an inconsistent API check: it checks
chains?.data.length but then accesses chains.rows[0].chainId; update the code so
the shape is consistent (either check chains?.rows?.length before using
chains.rows[0].chainId, or use chains?.data[0].chainId and
setSelectedBaseChainId accordingly), or if this block is dead, remove the
commented code entirely; locate the useEffect block and fix the condition and
access to match the actual API shape used elsewhere in the component (symbols:
useEffect, chains, rows, data, setSelectedBaseChainId).
apps/frontend/lib/stellar-adapter.ts (1)

6-7: Consider warning when falling back to testnet defaults in production.

The silent fallback to testnet URLs when NEXT_PUBLIC_STELLAR_* env vars are unset could cause production issues. Consider logging a warning or validating env vars at startup.

♻️ Optional: Add development-time warning
+const warnMissingEnv = (name: string, fallback: string) => {
+  if (process.env.NODE_ENV === "production" && !process.env[name]) {
+    console.warn(`Missing ${name}, falling back to ${fallback}`)
+  }
+}
+
 export function useStellarAdapter(): {
   ...
   const buildCtx = (): StellarAdapterCtx => {
     ...
     const rpcUrl =
       process.env.NEXT_PUBLIC_STELLAR_RPC_URL || DEFAULT_TESTNET_RPC
+    warnMissingEnv("NEXT_PUBLIC_STELLAR_RPC_URL", DEFAULT_TESTNET_RPC)

Also applies to: 20-21, 34-35

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

In `@apps/frontend/lib/stellar-adapter.ts` around lines 6 - 7, When building the
Stellar adapter, detect when NEXT_PUBLIC_STELLAR_RPC and
NEXT_PUBLIC_STELLAR_HORIZON are unset and you're using the fallback constants
DEFAULT_TESTNET_RPC or DEFAULT_TESTNET_HORIZON; in that case emit a clear
warning (or throw/configure a startup validation failure) so production
deployments don’t silently use testnet endpoints. Update the initialization
logic in apps/frontend/lib/stellar-adapter.ts to check
process.env.NEXT_PUBLIC_STELLAR_RPC and process.env.NEXT_PUBLIC_STELLAR_HORIZON,
and if running in production (NODE_ENV === "production") log a warning/error
that the code is falling back to DEFAULT_TESTNET_RPC/DEFAULT_TESTNET_HORIZON and
suggest setting the env vars.
apps/frontend/hooks/useStellarAuth.ts (1)

41-44: Consider adding cookie security attributes.

The auth tokens are stored without Secure or SameSite attributes. While HttpOnly cannot be set client-side, adding Secure and SameSite improves security posture:

-      Cookies.set("auth_token", data.tokens.access)
-      Cookies.set("refresh_token", data.tokens.refresh)
+      Cookies.set("auth_token", data.tokens.access, {
+        secure: true,
+        sameSite: "strict",
+      })
+      Cookies.set("refresh_token", data.tokens.refresh, {
+        secure: true,
+        sameSite: "strict",
+      })

Also note that return data on line 44 is unreachable after window.location.reload().

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

In `@apps/frontend/hooks/useStellarAuth.ts` around lines 41 - 44, The code in
useStellarAuth.ts sets auth cookies via Cookies.set("auth_token", ...) and
Cookies.set("refresh_token", ...) without security attributes and then calls
window.location.reload(), making the subsequent return data unreachable; update
the Cookies.set calls to include Secure: true and SameSite: 'Lax' or 'Strict'
(and consider a sensible expires if needed) so tokens are set with those
attributes, and either remove the unreachable return data or move the return
before window.location.reload() (or replace reload with navigation that
preserves the return flow) to ensure reachable control flow.
apps/frontend/hooks/useAds.ts (1)

378-402: Consider passing ad token info to avoid redundant fetch.

Both useWithdrawFunds and useCloseAd call getSingleAd(data.adId) solely to retrieve adToken for the trustline check. If the caller already has this information (e.g., from the ad detail page context), consider extending IWithdrawFromAdRequest / ICloseAdRequest to optionally include adToken, avoiding the extra network round-trip:

// In the request type
adToken?: IAdToken; // Optional: pass if available to skip fetch

// In the mutation
const adToken = data.adToken ?? (await getSingleAd(data.adId)).adToken;
await assertRecipientTrustline(adToken, data.to);

This is a minor optimization and not blocking.

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

In `@apps/frontend/hooks/useAds.ts` around lines 378 - 402, Add an optional
adToken field to the request types (IWithdrawFromAdRequest and ICloseAdRequest)
and update the withdrawal/close flows to use it when present: in the code path
that currently calls getSingleAd(data.adId) (see getSingleAd and
assertRecipientTrustline usage in useWithdrawFunds/useCloseAd handlers), resolve
adToken as const adToken = data.adToken ?? (await
getSingleAd(data.adId)).adToken and pass that to
assertRecipientTrustline(adToken, data.to) to avoid the redundant fetch when the
caller already supplies the token.
apps/frontend/utils/stellar/invoke.ts (1)

40-40: Default to TESTNET could be risky in production.

The fallback to Networks.TESTNET when networkPassphrase is undefined could cause issues if a caller forgets to pass the passphrase in a production environment. Consider making networkPassphrase required or logging a warning when using the default:

-  const passphrase = networkPassphrase ?? Networks.TESTNET
+  if (!networkPassphrase) {
+    console.warn("invokeSoroban: networkPassphrase not provided, defaulting to TESTNET")
+  }
+  const passphrase = networkPassphrase ?? Networks.TESTNET

This helps catch configuration mistakes during development.

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

In `@apps/frontend/utils/stellar/invoke.ts` at line 40, The code currently falls
back to Networks.TESTNET via the variable passphrase (const passphrase =
networkPassphrase ?? Networks.TESTNET), which is risky; update invoke.ts so
networkPassphrase is required or, if keeping optional, emit a clear
warning/error when undefined and before defaulting to Networks.TESTNET; locate
the related symbol networkPassphrase and the passphrase assignment in invoke.ts
(or the containing function) and either change the parameter to be non-optional
or add a runtime check that logs/processLogger.warn (or throws) when
networkPassphrase is missing, then only use Networks.TESTNET as an explicit,
clearly logged fallback.
apps/frontend/hooks/useTrades.ts (1)

456-492: Consider extracting the orderParams transformation to reduce inline IIFE complexity.

The inline IIFEs work correctly but add cognitive overhead. A helper function could improve readability.

♻️ Optional: Extract transformation helper
function toBigIntOrderParams<T extends { amount: string; salt: string }>(
  p: T,
  chainIdKey: 'adChainId' | 'orderChainId'
): Omit<T, 'amount' | 'salt' | typeof chainIdKey> & { amount: bigint; salt: bigint } & Record<typeof chainIdKey, bigint> {
  return {
    ...p,
    amount: BigInt(p.amount),
    [chainIdKey]: BigInt((p as any)[chainIdKey]),
    salt: BigInt(p.salt),
  } as any;
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/frontend/hooks/useTrades.ts` around lines 456 - 492, The inline IIFEs
converting orderParams to BigInt values create cognitive overhead; extract that
logic into a helper (e.g., toBigIntOrderParams) and use it where the IIFEs are
called inside the writeContractAsync args. Implement a generic helper that
accepts the param object and the chainId key name (adChainId or orderChainId),
converts amount, salt and the appropriate chain id to BigInt while preserving
other fields (handle types IOrderPortalOrderParams and IAdManagerOrderParams),
then replace the two IIFE usages in useTrades.ts with calls to this helper for
clearer, reusable code.
apps/frontend/components/providers/StellarWallet.tsx (1)

158-178: Consider guarding signing methods when wallet is not connected.

The signing methods pass address ?? undefined to the SDK. If these are called before connection, the SDK behavior may be unpredictable. The UI likely guards against this, but a defensive check could improve robustness.

💡 Optional defensive check
   const signTransaction = useCallback(
     async (xdr: string, networkPassphrase?: string) => {
+      if (!address) throw new Error("Stellar wallet not connected")
       const { signedTxXdr } = await StellarWalletsKit.signTransaction(xdr, {
         networkPassphrase: networkPassphrase ?? Networks.TESTNET,
-        address: address ?? undefined,
+        address,
       })
       return signedTxXdr
     },
     [address],
   )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/frontend/components/providers/StellarWallet.tsx` around lines 158 - 178,
signTransaction and signMessage call StellarWalletsKit even when address may be
undefined, which can lead to unpredictable SDK behavior; add a defensive guard
in both functions (signTransaction and signMessage) to check that address (or a
wallet-connected flag) is present and throw or return a clear error if not,
instead of calling StellarWalletsKit.signTransaction/signMessage with address ??
undefined; keep networkPassphrase logic as-is (Networks.TESTNET fallback) but
ensure the functions early-exit when no connected address is available.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/backend-relayer/src/chain-adapters/adapters/evm-chain-adapter.ts`:
- Around line 186-193: The code casts signature to `0x${string}` without runtime
checking before calling `this.viem.verifyOrderSignature`; add a validation step
(similar to `assertLocalAddress`) to verify the signature is a hex string of the
expected length (e.g. matches /^0x[0-9a-fA-F]{130}$/) before casting. Implement
or reuse a helper like `assertHexSignature(signature, 'signature')` and call it
in the same function (the one that calls `this.viem.verifyOrderSignature`) so
the unsafe cast to `signature as \`0x\${string}\`` is only done after the check.
Ensure the validation throws the same style of error as `assertLocalAddress` on
failure.

In `@apps/backend-relayer/src/modules/token/dto/token.dto.ts`:
- Around line 131-138: The assetIssuer field is only being string-validated but
needs format and conditional requirement when token kind is SAC; update the DTO
to replace the loose `@IsString`()/@IsOptional() with a conditional validator like
`@ValidateIf`(o => o.kind === 'SAC') plus `@IsNotEmpty`() and a strict Stellar
public-key pattern check (e.g. Matches(/^G[A-Z2-7]{55}$/) or an equivalent
StrKey validator) to ensure correct G-strkey format; also apply the same change
to the other occurrence of assetIssuer in the file (the block around lines
~201-208) so both DTOs enforce format and require the issuer when kind ===
'SAC'.

In `@apps/backend-relayer/src/modules/token/token.service.ts`:
- Around line 218-226: The current check throws whenever dto.kind !== 'SAC'
regardless of the previous value; update the condition to only enforce clearing
assetIssuer when the existing record is SAC and the new kind moves away from SAC
(i.e., change the if to verify exists.kind === 'SAC' && dto.kind !== 'SAC'). In
the block referencing dto.kind and exists.kind (in token.service.ts around the
kind-change logic), keep the same error message and behavior but only trigger it
for transitions originating from 'SAC'.

In `@apps/frontend/components/bridge-ui/TradeAd.tsx`:
- Around line 92-104: The conditional block uses optional chaining with non-null
assertions like balance?.data?.value! and nativeBalance?.data?.decimals! which
is contradictory and unsafe; since you already check balance.data and
nativeBalance.data in the if/else guards, replace the optional-chained
expressions with direct property access (e.g., balance.data.value and
balance.data.decimals, nativeBalance.data.value and nativeBalance.data.decimals)
when calling formatUnits and keep setBalance_value as-is; update the references
in the effect that depends on balance.data, nativeBalance.data,
stellarBalance.data, isStellarOrder to remove the unnecessary ?. and !.

In `@apps/frontend/hooks/useTrades.ts`:
- Around line 347-386: The EIP-712 struct types for cross-chain address fields
in the signTypedDataAsync call are incorrect (currently "address") and must be
changed to "bytes32" to match the contract; update the Order type declaration in
signTypedDataAsync to use bytes32 for orderChainToken, adChainToken, bridger,
orderPortal, orderRecipient, adManager, adCreator, and adRecipient, and
transform the corresponding values pulled from params into 32-byte padded
representations (e.g., pad EVM addresses as bytes32(uint256(uint160(address)))
or an equivalent JS utility that left-pads/truncates to 32 bytes) while keeping
numeric fields (amount, orderChainId, adChainId, salt) as uint256/BigInt and
leaving other fields (adId) as their correct types so the produced EIP-712
message matches the contract ORDER_TYPEHASH.

In `@apps/frontend/package.json`:
- Around line 13-17: Update the dependency entry for `@rainbow-me/rainbowkit` in
package.json from "^2.2.8" to "^2.2.10"; locate the "@rainbow-me/rainbowkit"
entry and bump the version string to "^2.2.10", then run your package manager
(npm/yarn/pnpm install) to update lockfiles and verify the app builds/tests
pass.

In `@apps/frontend/services/chains.service.ts`:
- Line 14: The returned response type currently forces nextCursor to be a
non-null string; update the cast at the return in chains.service.ts so the
response is typed as { data: IChain[]; nextCursor: string | null } (i.e., make
nextCursor nullable) to avoid propagating unsafe non-null assumptions in
pagination logic where nextCursor may be absent. Ensure any callers of the
function handle nextCursor possibly being null.

In `@apps/frontend/types/ads.ts`:
- Around line 28-29: The chainId type is inconsistent across response
interfaces—ICreateAdResponse.chainId is number while IFundAdResponse.chainId,
IWithdrawFromAdResponse.chainId, and ICloseAdResponse.chainId are string; change
ICreateAdResponse.chainId to string so all four response interfaces use the same
type (chainId: string), and then update any local usages/call sites that assume
a number to use string or parse as needed; target the interfaces named
ICreateAdResponse, IFundAdResponse, IWithdrawFromAdResponse, and
ICloseAdResponse and the chainId property when making the change.

In `@apps/frontend/types/chains.ts`:
- Around line 3-10: The IChain interface should be converted to a discriminated
union keyed by ChainKind so EVM chains keep adManagerAddress/orderPortalAddress
typed as viem's Address while STELLAR chains use a plain string (hex/strkey)
type; update the type definition for ChainKind/IChain to two variants (e.g., {
kind: "EVM"; adManagerAddress: Address; orderPortalAddress: Address } | { kind:
"STELLAR"; adManagerAddress: string; orderPortalAddress: string }) and then
update callers (notably functions in trade.service.ts that currently cast
stellar values with `as \`0x${string}\``) to narrow by chain.kind before using
the address so the casts are unnecessary and Stellar addresses can be decoded to
strkey at the RPC boundary (follow
apps/backend-relayer/src/providers/stellar/utils/address.ts decoding logic).

In `@apps/frontend/types/tokens.ts`:
- Around line 1-4: The Token address type currently uses viem's Address for all
TokenKind values; change this to a discriminated union so EVM kinds use Address
and Stellar kinds use a hex/string type: introduce a TokenAddress union (or
inline union on IToken) discriminated by kind (e.g., { kind: "NATIVE" | "ERC20";
address: Address } | { kind: "SAC" | "SEP41"; address: string /* or
`0x${string}` */ }), update IToken to reference that union instead of Address,
and update any other usages mentioned (routes.ts and ads.ts) to use the new
discriminated shape and corresponding conversion helpers.

In `@apps/frontend/utils/stellar/address.ts`:
- Around line 6-15: hex32ToBuffer currently accepts both 32-byte and 20-byte hex
(padding the latter), which can produce an invalid Ed25519 public key when
passed to hex32ToAccountId/StrKey.encodeEd25519PublicKey; update
hex32ToAccountId to validate that the input is a true 32-byte hex (reject
20-byte EVM-style addresses) or introduce a separate hex32OnlyToBuffer that only
accepts 32-byte hex and use that inside hex32ToAccountId; ensure the function(s)
throw a clear error for 20-byte inputs and reference hex32ToBuffer,
hex32ToAccountId (and StrKey.encodeEd25519PublicKey) so callers know to use the
32-byte-only path for StrKey operations.

---

Outside diff comments:
In `@apps/backend-relayer/src/modules/trades/trade.service.ts`:
- Line 1291: Remove the debug console.log(dto) statement found in
trade.service.ts (inside the relevant TradeService method handling the DTO) —
delete the console.log call or replace it with the module's proper logger (e.g.,
this.logger.debug or processLogger.debug) if the DTO needs to be recorded,
ensuring no raw console logs remain in production code.

In `@apps/frontend/package.json`:
- Around line 32-33: The package.json has mismatched React versions: "react" is
19.1.0 while "react-dom" is 19.2.5; update the dependencies so both "react" and
"react-dom" use the same version (pick a single canonical version, e.g., set
"react" to "19.2.5" to match "react-dom" or align both to a chosen release),
then reinstall to update the lockfile (npm/yarn/pnpm install) and run the
app/tests/build to verify compatibility; modify the "react" and/or "react-dom"
entries in package.json accordingly.

---

Nitpick comments:
In `@apps/backend-relayer/prisma/schema.prisma`:
- Around line 86-88: Add a DB-level CHECK constraint so Token.kind and
assetIssuer cannot drift from the SAC-only rule: ensure that when Token.kind =
'SAC' then assetIssuer IS NOT NULL, and when Token.kind != 'SAC' then
assetIssuer IS NULL. Implement this by adding a SQL migration that runs ALTER
TABLE "Token" ADD CONSTRAINT token_assetissuer_kind_check CHECK ((kind = 'SAC'
AND assetIssuer IS NOT NULL) OR (kind <> 'SAC' AND assetIssuer IS NULL)); and
update any Prisma migration metadata so the constraint is tracked (keep the
Prisma schema Token model unchanged except for mapping if needed).

In `@apps/backend-relayer/src/modules/ads/dto/ad.dto.ts`:
- Around line 248-259: TokenDto has loose string types for chainKind and kind;
tighten them to match the response DTO unions by changing the property types on
the TokenDto class: set chainKind to the literal union 'EVM' | 'STELLAR' and set
kind to the literal union 'ERC20' | 'NATIVE' | 'SAC' | 'SEP41' (keeping the
existing `@ApiProperty` enum metadata as-is) so consumers and CreateAdResponseDto
remain consistent with these exact values.

In `@apps/backend-relayer/src/modules/routes/route.service.ts`:
- Around line 93-107: Extract the repeated nested select shape for
adToken/orderToken into a shared constant (e.g., TOKEN_SELECT or
TOKEN_WITH_CHAIN) in route.service.ts and replace the duplicated select objects
used in the list/get/create query calls; specifically locate the repeated select
blocks referenced for adToken and orderToken in the functions that perform
list/get/create operations and substitute them with the single shared constant
(export it if other modules need it), ensuring the constant includes the chain:
{ select: { id, name, chainId, kind } } structure and the token fields id,
symbol, name, address, decimals, kind, assetIssuer so all queries reference the
same shape.

In `@apps/frontend/components/ad-management-ui/AddLiquidity.tsx`:
- Line 109: The catch block in handleCreateAd silently swallows errors; modify
the catch in AddLiquidity's handleCreateAd to log the error (e.g., console.error
or process logger) and/or surface a user-facing notification (toast) with a
helpful message; ensure you reference the caught error variable and include
context like "Failed to create ad" when logging or notifying so debugging and UX
are improved.

In `@apps/frontend/components/bridge-ui/BridgeTab.tsx`:
- Around line 48-52: The commented useEffect contains an inconsistent API check:
it checks chains?.data.length but then accesses chains.rows[0].chainId; update
the code so the shape is consistent (either check chains?.rows?.length before
using chains.rows[0].chainId, or use chains?.data[0].chainId and
setSelectedBaseChainId accordingly), or if this block is dead, remove the
commented code entirely; locate the useEffect block and fix the condition and
access to match the actual API shape used elsewhere in the component (symbols:
useEffect, chains, rows, data, setSelectedBaseChainId).

In `@apps/frontend/components/providers/StellarWallet.tsx`:
- Around line 158-178: signTransaction and signMessage call StellarWalletsKit
even when address may be undefined, which can lead to unpredictable SDK
behavior; add a defensive guard in both functions (signTransaction and
signMessage) to check that address (or a wallet-connected flag) is present and
throw or return a clear error if not, instead of calling
StellarWalletsKit.signTransaction/signMessage with address ?? undefined; keep
networkPassphrase logic as-is (Networks.TESTNET fallback) but ensure the
functions early-exit when no connected address is available.

In `@apps/frontend/hooks/useAds.ts`:
- Around line 378-402: Add an optional adToken field to the request types
(IWithdrawFromAdRequest and ICloseAdRequest) and update the withdrawal/close
flows to use it when present: in the code path that currently calls
getSingleAd(data.adId) (see getSingleAd and assertRecipientTrustline usage in
useWithdrawFunds/useCloseAd handlers), resolve adToken as const adToken =
data.adToken ?? (await getSingleAd(data.adId)).adToken and pass that to
assertRecipientTrustline(adToken, data.to) to avoid the redundant fetch when the
caller already supplies the token.

In `@apps/frontend/hooks/useStellarAuth.ts`:
- Around line 41-44: The code in useStellarAuth.ts sets auth cookies via
Cookies.set("auth_token", ...) and Cookies.set("refresh_token", ...) without
security attributes and then calls window.location.reload(), making the
subsequent return data unreachable; update the Cookies.set calls to include
Secure: true and SameSite: 'Lax' or 'Strict' (and consider a sensible expires if
needed) so tokens are set with those attributes, and either remove the
unreachable return data or move the return before window.location.reload() (or
replace reload with navigation that preserves the return flow) to ensure
reachable control flow.

In `@apps/frontend/hooks/useTrades.ts`:
- Around line 456-492: The inline IIFEs converting orderParams to BigInt values
create cognitive overhead; extract that logic into a helper (e.g.,
toBigIntOrderParams) and use it where the IIFEs are called inside the
writeContractAsync args. Implement a generic helper that accepts the param
object and the chainId key name (adChainId or orderChainId), converts amount,
salt and the appropriate chain id to BigInt while preserving other fields
(handle types IOrderPortalOrderParams and IAdManagerOrderParams), then replace
the two IIFE usages in useTrades.ts with calls to this helper for clearer,
reusable code.

In `@apps/frontend/lib/chains.ts`:
- Around line 9-17: Replace the hard-coded STELLAR_TESTNET_CHAIN_ID with a
config-driven value so UI selectors reflect backend changes: read the chain id
from a runtime config or env (e.g. NEXT_PUBLIC_STELLAR_TESTNET_CHAIN_ID) and
fall back to the existing "1000001" constant; update the
STELLAR_TESTNET_CHAIN_ID declaration and ensure VISIBLE_CHAIN_IDS uses that
config value (referencing STELLAR_TESTNET_CHAIN_ID and VISIBLE_CHAIN_IDS) so
changes to backend seed/config automatically surface in the front-end selectors.

In `@apps/frontend/lib/stellar-adapter.ts`:
- Around line 6-7: When building the Stellar adapter, detect when
NEXT_PUBLIC_STELLAR_RPC and NEXT_PUBLIC_STELLAR_HORIZON are unset and you're
using the fallback constants DEFAULT_TESTNET_RPC or DEFAULT_TESTNET_HORIZON; in
that case emit a clear warning (or throw/configure a startup validation failure)
so production deployments don’t silently use testnet endpoints. Update the
initialization logic in apps/frontend/lib/stellar-adapter.ts to check
process.env.NEXT_PUBLIC_STELLAR_RPC and process.env.NEXT_PUBLIC_STELLAR_HORIZON,
and if running in production (NODE_ENV === "production") log a warning/error
that the code is falling back to DEFAULT_TESTNET_RPC/DEFAULT_TESTNET_HORIZON and
suggest setting the env vars.

In `@apps/frontend/utils/stellar/invoke.ts`:
- Line 40: The code currently falls back to Networks.TESTNET via the variable
passphrase (const passphrase = networkPassphrase ?? Networks.TESTNET), which is
risky; update invoke.ts so networkPassphrase is required or, if keeping
optional, emit a clear warning/error when undefined and before defaulting to
Networks.TESTNET; locate the related symbol networkPassphrase and the passphrase
assignment in invoke.ts (or the containing function) and either change the
parameter to be non-optional or add a runtime check that logs/processLogger.warn
(or throws) when networkPassphrase is missing, then only use Networks.TESTNET as
an explicit, clearly logged fallback.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1a6d7531-7c8c-4e4a-8769-135331154f74

📥 Commits

Reviewing files that changed from the base of the PR and between f578385 and d63e432.

⛔ Files ignored due to path filters (3)
  • apps/frontend/public/assets/logos/stellar-logo.svg is excluded by !**/*.svg
  • apps/frontend/public/assets/logos/stellar-xlm-logo.png is excluded by !**/*.png
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (66)
  • apps/backend-relayer/prisma/migrations/20260413000000_add_token_asset_issuer/migration.sql
  • apps/backend-relayer/prisma/schema.prisma
  • apps/backend-relayer/src/chain-adapters/adapters/chain-adapter.abstract.ts
  • apps/backend-relayer/src/chain-adapters/adapters/evm-chain-adapter.ts
  • apps/backend-relayer/src/chain-adapters/adapters/stellar-chain-adapter.ts
  • apps/backend-relayer/src/main.ts
  • apps/backend-relayer/src/modules/admin/admin.controller.spec.ts
  • apps/backend-relayer/src/modules/ads/ad.service.ts
  • apps/backend-relayer/src/modules/ads/dto/ad.dto.ts
  • apps/backend-relayer/src/modules/chains/chain.controller.spec.ts
  • apps/backend-relayer/src/modules/chains/chain.service.ts
  • apps/backend-relayer/src/modules/chains/dto/chain.dto.ts
  • apps/backend-relayer/src/modules/routes/route.service.ts
  • apps/backend-relayer/src/modules/token/dto/token.dto.ts
  • apps/backend-relayer/src/modules/token/token.service.ts
  • apps/backend-relayer/src/modules/trades/dto/trade.dto.ts
  • apps/backend-relayer/src/modules/trades/trade.service.ts
  • apps/backend-relayer/src/providers/stellar/stellar.service.ts
  • apps/backend-relayer/src/types/index.d.ts
  • apps/backend-relayer/test/e2e/chain.e2e-spec.ts
  • apps/backend-relayer/test/e2e/token.e2e-spec.ts
  • apps/frontend/abis/AdManager.abi.ts
  • apps/frontend/abis/ERC20.abi.ts
  • apps/frontend/abis/orderPortal.abi.ts
  • apps/frontend/app/(app)/(auth-protected)/faucet/page.tsx
  • apps/frontend/app/(app)/bridge/page.tsx
  • apps/frontend/app/layout.tsx
  • apps/frontend/components/ad-management-ui/AddLiquidity.tsx
  • apps/frontend/components/bridge-ui/BridgeTab.tsx
  • apps/frontend/components/bridge-ui/SellAdd.tsx
  • apps/frontend/components/bridge-ui/TradeAd.tsx
  • apps/frontend/components/connect-wallet/ConnectWalletButton.tsx
  • apps/frontend/components/landing/Approach.tsx
  • apps/frontend/components/landing/Features.tsx
  • apps/frontend/components/landing/Hero-Alt.tsx
  • apps/frontend/components/landing/Hero.tsx
  • apps/frontend/components/landing/ReImagining.tsx
  • apps/frontend/components/orders/OrdersTable.tsx
  • apps/frontend/components/providers/RainbowKit.tsx
  • apps/frontend/components/providers/StellarWallet.tsx
  • apps/frontend/hooks/useAds.ts
  • apps/frontend/hooks/useStellarAuth.ts
  • apps/frontend/hooks/useTrades.ts
  • apps/frontend/lib/chain-icons.ts
  • apps/frontend/lib/chains.ts
  • apps/frontend/lib/stellar-adapter.ts
  • apps/frontend/package.json
  • apps/frontend/services/ads.service.ts
  • apps/frontend/services/auth.service.ts
  • apps/frontend/services/chains.service.ts
  • apps/frontend/types/ads.ts
  • apps/frontend/types/chains.ts
  • apps/frontend/types/tokens.ts
  • apps/frontend/types/trades.ts
  • apps/frontend/utils/amount.ts
  • apps/frontend/utils/evm/address.ts
  • apps/frontend/utils/evm/index.ts
  • apps/frontend/utils/evm/typedData.ts
  • apps/frontend/utils/format-address.ts
  • apps/frontend/utils/stellar/actions.ts
  • apps/frontend/utils/stellar/address.ts
  • apps/frontend/utils/stellar/balance.ts
  • apps/frontend/utils/stellar/index.ts
  • apps/frontend/utils/stellar/invoke.ts
  • apps/frontend/utils/stellar/scval.ts
  • apps/frontend/utils/stellar/trustline.ts
💤 Files with no reviewable changes (1)
  • apps/frontend/components/bridge-ui/SellAdd.tsx

Comment thread apps/backend-relayer/src/modules/token/dto/token.dto.ts
Comment thread apps/backend-relayer/src/modules/token/token.service.ts
Comment thread apps/frontend/components/bridge-ui/TradeAd.tsx
Comment thread apps/frontend/hooks/useTrades.ts
Comment thread apps/frontend/services/chains.service.ts Outdated
Comment thread apps/frontend/types/ads.ts Outdated
Comment thread apps/frontend/types/chains.ts Outdated
Comment thread apps/frontend/types/tokens.ts
Comment thread apps/frontend/utils/stellar/address.ts
JoE11-y added 3 commits April 14, 2026 00:37
  Critical:
  - useTrades: EIP-712 Order struct signs bytes32 for cross-chain address
    fields to match on-chain ORDER_TYPEHASH; previously signed as `address`,
    which produced a non-matching typeHash and broke signature verification.
  - token.service: SAC-transition guard now checks `exists.kind === 'SAC'`
    so NATIVE → SEP41 (neither SAC) no longer demands clearing assetIssuer.

  Major:
  - evm-chain-adapter: add assertLocalSignature hex-regex guard before
    casting to `0x${string}` in verifyOrderSignature.
  - token.dto: validate assetIssuer format (`/^G[A-Z2-7]{55}$/`) on create;
    update accepts empty string as explicit clear sentinel.
  - types/chains: IChain becomes a discriminated union (IEvmChain |
    IStellarChain) so Stellar addresses aren't forced through viem Address.

  Minor:
  - TradeAd: drop redundant optional-chain+non-null-assert after the
    balance.data guard.
  - types/ads: ICreateAdResponse.chainId number → string to match siblings.
  - chains.service: nextCursor typed as string | null.
  - types/tokens: IToken split into IEvmToken | IStellarToken union.
  - utils/stellar/address: hex32ToAccountId / hex32ToContractId now reject
    20-byte EVM input via new hex32OnlyToBuffer helper to prevent bogus
    StrKey output from zero-padded EVM addresses.
  - package.json: bump @rainbow-me/rainbowkit ^2.2.8 → ^2.2.10.\
@JoE11-y JoE11-y merged commit 9fb3748 into main Apr 14, 2026
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant