Skip to content

feat: tc layer#155

Draft
ThomasRalee wants to merge 69 commits into
masterfrom
feat/tc-layer
Draft

feat: tc layer#155
ThomasRalee wants to merge 69 commits into
masterfrom
feat/tc-layer

Conversation

@ThomasRalee

@ThomasRalee ThomasRalee commented May 26, 2026

Copy link
Copy Markdown
Contributor

⚠️ DO NOT MERGE

Summary by CodeRabbit

  • New Features
    • Delayed Google Analytics loading (idle callback with fallback)
    • Wallet direct-sign support plus read-only address mode
    • Lean USD token price fetching (optional denom/ID inputs)
    • De-duplicate error notifications within a session
    • Pre-seeded oracle pricing for Chainlink USDC
  • Bug Fixes
    • Improved EVM wallet extension installed detection and more resilient provider selection
    • Corrected Injective EVM chain-id selection for test/devnet
  • Chores
    • Removed Bugsnag and Hotjar integrations
    • Updated Node.js (>=24) and pnpm (>=10.7.0 <11.0.0); bumped @injectivelabs deps to 1.20.17
    • Added BFF OpenAPI type generation script

@coderabbitai

coderabbitai Bot commented May 26, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The pull request performs a large-scale service layer decomposition, splitting app/service/index.ts from a monolithic construction file into a barrel that re-exports from 15+ dedicated submodules (chain, indexer, cache, bff, price, token, exchange, account, etc.). All consumers are updated to import from specific submodule paths.

The wallet system is overhauled: wallet-base/light is adopted across all wallet imports; Wallet.PrivateKeyCosmos replaces Wallet.PrivateKey; explicit validateBeforeQueue/validateMainWallet actions are added; direct-sign broadcaster variants (getAutoSignMsgBroadcasterWithDirectSign, withAutoSignPrivateKeyWithDirectSign) are introduced for fee-delegation paths; isSSOAuth replaces isGoogleAuth; and an isReadOnly guard is added to broadcast methods. A comprehensive test suite validates wallet validation and broadcaster routing across autosign and fee-delegation scenarios.

TokenPrice gains a lean fetch path via v2/denoms with field selectors. Oracle and token stores are pre-seeded with USDC price values. Bugsnag and Hotjar are fully removed; vue-gtag is now loaded dynamically after an idle-scheduled delay. A new scripts/gen-bff-types.ts CLI script replaces the prior curl-based BFF type generation.

Across the codebase, imports are consolidated to use lighter module entry points: BigNumber utilities now import from @injectivelabs/utils/big-number, SDK types from @injectivelabs/sdk-ts/types/light, encoding helpers from @injectivelabs/sdk-ts/utils/encoding, and HTTP clients from @injectivelabs/utils/http. EVM contract ABIs and public clients are now lazily initialized and cached. Module preload chunks are expanded and filtered to exclude SDK/wallet/crypto dependencies. The notification store gains WeakSet-backed error deduplication actions.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.85% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The PR title 'feat: tc layer' is vague and generic, using non-descriptive abbreviation 'tc' without clarifying what it represents or what the main change accomplishes. Expand the title to be more descriptive, e.g., 'feat: add Trading Client layer with bundle size optimization' or similar, to clarify the feature's purpose and scope.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ 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 feat/tc-layer
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch feat/tc-layer

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

@ThomasRalee ThomasRalee changed the title chore: added new wallet connected hooks feat: tc layer May 26, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 7

Caution

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

⚠️ Outside diff range comments (2)
app/store/wallet/index.ts (1)

853-906: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Read-only guard is bypassable through direct helper actions.

Line 853 and Line 911 allow direct calls to broadcast helpers without the read-only / wallet-connected checks added in Line 716 and Line 767. That allows callers to bypass the “read-only cannot sign” invariant by invoking helpers directly.

Suggested patch
 async broadcastWithoutFeeDelegation(
   broadcastOptions: MsgBroadcasterTxOptions
 ) {
   const walletStore = useSharedWalletStore()
+
+  if (walletStore.isReadOnly) {
+    throw new GeneralException(
+      new Error(
+        'Read-only connection cannot sign or submit transactions. Connect a wallet to continue.'
+      )
+    )
+  }
+
+  if (!walletStore.isUserConnected) {
+    throw new GeneralException(new Error('Wallet is not connected'))
+  }
 
   if (walletStore.isFeeDelegationEnabled) {
     throw new GeneralException(
       new Error(
         'Broadcasting is not available for fee delegation, use broadcastWithFeeDelegation instead'
@@
 async broadcastWithFeeDelegation(
   broadcastOptions: MsgBroadcasterTxOptions
 ) {
   const walletStore = useSharedWalletStore()
+
+  if (walletStore.isReadOnly) {
+    throw new GeneralException(
+      new Error(
+        'Read-only connection cannot sign or submit transactions. Connect a wallet to continue.'
+      )
+    )
+  }
+
+  if (!walletStore.isUserConnected) {
+    throw new GeneralException(new Error('Wallet is not connected'))
+  }
 
   if (!walletStore.isFeeDelegationEnabled) {
     throw new GeneralException(
       new Error(
         'Broadcasting is not available for fee delegation, use broadcastWithoutFeeDelegation instead'

Also applies to: 908-963

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/store/wallet/index.ts` around lines 853 - 906, The
broadcastWithoutFeeDelegation method (and the related broadcastWithFeeDelegation
method) are missing the read-only and wallet-connected validation checks that
exist elsewhere in the module, allowing callers to bypass the read-only
invariant by calling these methods directly. Add the same read-only guard checks
from the existing validation locations (referenced at lines 716 and 767) to the
beginning of both broadcastWithoutFeeDelegation and broadcastWithFeeDelegation
methods before any broadcast logic is executed. These checks should throw an
appropriate exception if the wallet is in read-only mode or not properly
connected, ensuring the invariant cannot be bypassed through direct helper
method invocation.
app/wallet/strategy.ts (1)

172-193: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Options parameter ignored on subsequent calls due to caching.

The options parameter is only used when creating the broadcaster on the first call. Subsequent calls return the cached promise, ignoring any new options passed:

getAutoSignMsgBroadcaster({ gasBufferCoefficient: 1.5 }) // creates instance with 1.5
getAutoSignMsgBroadcaster({ gasBufferCoefficient: 2.0 }) // returns cached instance with 1.5!

If callers are expected to always pass the same options (or none), document this constraint. If different options need to be supported, either:

  1. Remove the options parameter and hardcode the configuration
  2. Create a new instance when options differ
  3. Add a separate factory that doesn't cache
Option 1: Remove the misleading parameter
-export const getAutoSignMsgBroadcaster = (
-  options?: Partial<MsgBroadcasterOptions>
-): Promise<MsgBroadcaster> => {
+export const getAutoSignMsgBroadcaster = (): Promise<MsgBroadcaster> => {
   if (!autoSignMsgBroadcasterPromise) {
     autoSignMsgBroadcasterPromise = Promise.all([
       import('`@injectivelabs/wallet-core`'),
       getAutoSignWalletStrategy()
     ]).then(([{ MsgBroadcaster }, walletStrategy]) => {
       return new MsgBroadcaster({
         simulateTx: true,
         network: NETWORK,
         endpoints: ENDPOINTS,
         gasBufferCoefficient: 1.2,
         feePayerPubKey: FEE_PAYER_PUB_KEY,
-        walletStrategy,
-        ...options
+        walletStrategy
       })
     })
   }

   return autoSignMsgBroadcasterPromise
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/wallet/strategy.ts` around lines 172 - 193, The getAutoSignMsgBroadcaster
function accepts an options parameter that is ignored on subsequent calls due to
caching, creating a misleading API contract. Remove the options parameter from
the function signature and the spread operator that applies it in the
MsgBroadcaster instantiation, then hardcode all configuration values directly
(including gasBufferCoefficient set to 1.2) so the function's behavior matches
what callers would actually experience.
🧹 Nitpick comments (2)
app/wallet/utils/evm.ts (1)

189-207: 💤 Low value

Return value doesn't distinguish success from skip.

The function returns true in all cases: when the wallet isn't an EVM browser wallet (line 193), when strategy/provider is missing (line 201), and after successfully calling addEvmNetwork (line 206). Callers cannot distinguish between "network was added" vs "skipped because not applicable".

If this is intentional (callers don't need to differentiate), consider using void return type for clarity. If callers need to know whether the network switch actually occurred, consider returning false or a more descriptive result for the skip cases.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/wallet/utils/evm.ts` around lines 189 - 207, The
switchToInjectiveEvmNetwork function returns true in all cases: when the wallet
is not an EVM browser wallet, when the strategy or provider is missing, and
after successfully calling addEvmNetwork, making it impossible for callers to
distinguish between an actual network switch and a skipped operation. Either
change the return type to void if callers do not need to differentiate between
success and skip cases, or return false for the skip cases (the early returns
when isEvmBrowserWallet check fails and when strategy or provider is missing)
while keeping true for the successful execution path after addEvmNetwork is
called.
.coderabbit.yaml (1)

36-40: ⚡ Quick win

Include DO NOT MERGE in ignored title keywords.

Given auto-review is enabled for drafts/all branches, adding DO NOT MERGE to Line 36-40 prevents noisy reviews on intentionally blocked PRs.

Proposed fix
     ignore_title_keywords:
       - 'WIP'
       - 'DO NOT REVIEW'
+      - 'DO NOT MERGE'
       - '[skip-coderabbit]'
       - '[skip ci]'
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.coderabbit.yaml around lines 36 - 40, The ignore_title_keywords list in the
.coderabbit.yaml configuration is missing the 'DO NOT MERGE' keyword. Add 'DO
NOT MERGE' as a new entry to the ignore_title_keywords list alongside the
existing keywords 'WIP', 'DO NOT REVIEW', '[skip-coderabbit]', and '[skip ci]'
to prevent CodeRabbit from reviewing PRs that are intentionally blocked from
merging.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/plugins/tracking.client.ts`:
- Around line 36-44: The async callback passed to scheduleGtagInstall lacks
error handling for potential failures during the dynamic import of vue-gtag or
the plugin initialization. Wrap the entire async function body (including both
the import('vue-gtag') call and the nuxtApp.vueApp.use() call) in a try/catch
block to handle any promise rejections gracefully and prevent unhandled errors
from affecting application stability.

In `@app/service/app/tokenPrice.ts`:
- Around line 45-56: The buildAssetPriceDenomsLeanQuery function excludes the
denom field from its query string, but consuming code relies on falling back to
the denom value when coingecko_id is undefined. Add denom to the fields
parameter in both return statements of buildAssetPriceDenomsLeanQuery by
appending it to the existing comma-separated fields list (alongside price.price,
price.market_cap, coingecko_id, and symbol) so that the API response includes
the denom field and the fallback logic can work correctly.

In `@app/service/nameCompat.ts`:
- Around line 8-25: The lazy-import caching in getInjNameService and
getInjBonfidaNameService functions stores rejected promises permanently when the
import fails. Add error handling with a catch block to both import chains that
resets the respective cache variable (injNameServicePromise and
injBonfidaNameServicePromise) back to null/undefined when an error occurs, then
re-throws the error. This ensures that if a transient import failure happens,
the next call to these functions will attempt to re-import the module instead of
returning the cached rejected promise.

In `@app/store/token.ts`:
- Around line 22-24: The tokenUsdPriceMap is being completely replaced at lines
172, 182, and 193 when filtered denoms are fetched, which overwrites previously
cached prices including the seeded USDC denom. Instead of assigning the fetched
prices directly to tokenUsdPriceMap, merge the new prices into the existing map
by using spread syntax or Object.assign to preserve previously cached values
while adding the newly fetched prices.

In `@app/store/wallet/index.spec.ts`:
- Around line 32-37: The mock path in the vi.mock call at the beginning of the
test file is using `../../service`, but the actual code in
app/store/wallet/index.ts imports web3GatewayService from `../../service/web3`.
Update the mock path in the vi.mock function to match the actual import path by
changing `../../service` to `../../service/web3`, ensuring the mock properly
intercepts the web3GatewayService dependency and its healthCheck method.

In `@scripts/gen-bff-types.ts`:
- Around line 77-83: The fetchOpenApiSpec function makes a fetch call without
any timeout, which can cause the generation job to hang indefinitely if the
network stalls. Add an AbortController instance and set a timeout (e.g., 15
seconds) that will abort the request if it exceeds the time limit. Pass the
abort signal from the controller in the fetch options headers, and ensure the
fetch call properly handles any abort errors that may be thrown.
- Around line 36-43: The validation check on line 36 uses the `in` operator
which checks both own and inherited properties of the BFF_OPENAPI_URLS object,
allowing inherited keys like toString or constructor to incorrectly pass
validation. Replace the condition `!(target in BFF_OPENAPI_URLS)` with
`!Object.hasOwn(BFF_OPENAPI_URLS, target)` to ensure only the explicitly
declared targets are accepted.

---

Outside diff comments:
In `@app/store/wallet/index.ts`:
- Around line 853-906: The broadcastWithoutFeeDelegation method (and the related
broadcastWithFeeDelegation method) are missing the read-only and
wallet-connected validation checks that exist elsewhere in the module, allowing
callers to bypass the read-only invariant by calling these methods directly. Add
the same read-only guard checks from the existing validation locations
(referenced at lines 716 and 767) to the beginning of both
broadcastWithoutFeeDelegation and broadcastWithFeeDelegation methods before any
broadcast logic is executed. These checks should throw an appropriate exception
if the wallet is in read-only mode or not properly connected, ensuring the
invariant cannot be bypassed through direct helper method invocation.

In `@app/wallet/strategy.ts`:
- Around line 172-193: The getAutoSignMsgBroadcaster function accepts an options
parameter that is ignored on subsequent calls due to caching, creating a
misleading API contract. Remove the options parameter from the function
signature and the spread operator that applies it in the MsgBroadcaster
instantiation, then hardcode all configuration values directly (including
gasBufferCoefficient set to 1.2) so the function's behavior matches what callers
would actually experience.

---

Nitpick comments:
In @.coderabbit.yaml:
- Around line 36-40: The ignore_title_keywords list in the .coderabbit.yaml
configuration is missing the 'DO NOT MERGE' keyword. Add 'DO NOT MERGE' as a new
entry to the ignore_title_keywords list alongside the existing keywords 'WIP',
'DO NOT REVIEW', '[skip-coderabbit]', and '[skip ci]' to prevent CodeRabbit from
reviewing PRs that are intentionally blocked from merging.

In `@app/wallet/utils/evm.ts`:
- Around line 189-207: The switchToInjectiveEvmNetwork function returns true in
all cases: when the wallet is not an EVM browser wallet, when the strategy or
provider is missing, and after successfully calling addEvmNetwork, making it
impossible for callers to distinguish between an actual network switch and a
skipped operation. Either change the return type to void if callers do not need
to differentiate between success and skip cases, or return false for the skip
cases (the early returns when isEvmBrowserWallet check fails and when strategy
or provider is missing) while keeping true for the successful execution path
after addEvmNetwork is called.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3b2d7a58-4d4f-4bb3-a07e-c9aaaf1a8c13

📥 Commits

Reviewing files that changed from the base of the PR and between 2331d1a and 14072b9.

⛔ Files ignored due to path filters (4)
  • app/generated/bff-api-types.ts is excluded by !**/generated/**
  • app/generated/bff-spec.json is excluded by !**/generated/**
  • app/generated/bff.generated.ts is excluded by !**/generated/**, !**/*.generated.*
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !pnpm-lock.yaml
📒 Files selected for processing (61)
  • .coderabbit.yaml
  • app/classes/Tokens.ts
  • app/components/Amount/Usd.spec.ts
  • app/composables/hooks/onWalletConnected.ts
  • app/composables/useSharedWalletOptions.ts
  • app/data/oracle.ts
  • app/plugins/tracking.client.ts
  • app/providers/cacheApi/derivative.ts
  • app/providers/cacheApi/spot.ts
  • app/providers/cacheApi/staking.ts
  • app/providers/cacheApi/token.ts
  • app/service/account.ts
  • app/service/app/bffApi/index.ts
  • app/service/app/tokenClient.ts
  • app/service/app/tokenPrice.ts
  • app/service/bff.ts
  • app/service/cache.ts
  • app/service/chain.ts
  • app/service/derivative.ts
  • app/service/exchange.ts
  • app/service/faucet.ts
  • app/service/index.ts
  • app/service/indexer.ts
  • app/service/name.ts
  • app/service/nameCompat.ts
  • app/service/oracle.ts
  • app/service/price.ts
  • app/service/pyth.ts
  • app/service/rwa.ts
  • app/service/token.ts
  • app/service/tokenStaticFactory.ts
  • app/service/web3.ts
  • app/store/appConfig.ts
  • app/store/derivative.ts
  • app/store/json.ts
  • app/store/notification.ts
  • app/store/oracle/index.ts
  • app/store/param.ts
  • app/store/spot.ts
  • app/store/token.ts
  • app/store/wallet/extensions.ts
  • app/store/wallet/index.spec.ts
  • app/store/wallet/index.ts
  • app/store/wallet/magic.ts
  • app/store/wallet/turnkey.ts
  • app/tracking.spec.ts
  • app/types/wallet.ts
  • app/utils/constant/setup.ts
  • app/utils/helper.ts
  • app/wallet/autosign.ts
  • app/wallet/strategy.ts
  • app/wallet/utils/authz.ts
  • app/wallet/utils/cosmos.ts
  • app/wallet/utils/cosmostation.ts
  • app/wallet/utils/evm.ts
  • nuxt-config/bugsnag.ts
  • nuxt-config/vite/index.ts
  • nuxt.config.ts
  • nuxt/tsconfig.json
  • package.json
  • scripts/gen-bff-types.ts
💤 Files with no reviewable changes (5)
  • nuxt-config/bugsnag.ts
  • nuxt/tsconfig.json
  • nuxt.config.ts
  • nuxt-config/vite/index.ts
  • app/composables/hooks/onWalletConnected.ts

Comment on lines +36 to +44
scheduleGtagInstall(async () => {
const { default: VueGtag } = await import('vue-gtag')

nuxtApp.vueApp.use(VueGtag as any, {
config: {
id: GOOGLE_ANALYTICS_KEY
}
})
}

if (HOTJAR_KEY) {
nuxtApp.vueApp.use(hotjar as any, {
id: HOTJAR_KEY
})
}
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cat -n app/plugins/tracking.client.ts | head -60

Repository: InjectiveLabs/injective-ui

Length of output: 1436


🏁 Script executed:

grep -n "try\|catch\|console\." app/plugins/tracking.client.ts

Repository: InjectiveLabs/injective-ui

Length of output: 52


🏁 Script executed:

grep -r "scheduleGtagInstall" --include="*.ts" --include="*.js" -n

Repository: InjectiveLabs/injective-ui

Length of output: 227


🏁 Script executed:

find app/plugins -type f \( -name "*.ts" -o -name "*.js" \) -exec grep -l "defineNuxtPlugin\|import(" {} \; | head -5

Repository: InjectiveLabs/injective-ui

Length of output: 101


🏁 Script executed:

cat -n app/plugins/*.ts 2>/dev/null | grep -A 10 "async\|try\|catch" | head -40

Repository: InjectiveLabs/injective-ui

Length of output: 348


🏁 Script executed:

rg "import\(" app/plugins --type ts --type js -B 2 -A 2

Repository: InjectiveLabs/injective-ui

Length of output: 362


🏁 Script executed:

rg "\.use\(" app/plugins --type ts --type js -B 2 -A 2

Repository: InjectiveLabs/injective-ui

Length of output: 374


🏁 Script executed:

rg "\.catch\(|Promise\.|\.then\(" app/plugins/tracking.client.ts

Repository: InjectiveLabs/injective-ui

Length of output: 52


🏁 Script executed:

node -e "console.log('Testing promise rejection scenario:'); const cb = async () => { throw new Error('test'); }; setTimeout(cb, 0);" 2>&1 || true

Repository: InjectiveLabs/injective-ui

Length of output: 512


🏁 Script executed:

cat -n app/plugins/tracking.client.ts

Repository: InjectiveLabs/injective-ui

Length of output: 1436


Add error handling around the async vue-gtag initialization to prevent unhandled promise rejections.

The async callback passed to scheduleGtagInstall can fail at the import('vue-gtag') or plugin .use() call. Without error handling, promise rejections will be unhandled, potentially affecting application stability. Wrap the initialization in a try/catch block to isolate telemetry failures.

Proposed fix
   scheduleGtagInstall(async () => {
-    const { default: VueGtag } = await import('vue-gtag')
-
-    nuxtApp.vueApp.use(VueGtag as any, {
-      config: {
-        id: GOOGLE_ANALYTICS_KEY
-      }
-    })
+    try {
+      const { default: VueGtag } = await import('vue-gtag')
+      nuxtApp.vueApp.use(VueGtag as any, {
+        config: {
+          id: GOOGLE_ANALYTICS_KEY
+        }
+      })
+    } catch (error) {
+      console.warn('Failed to initialize vue-gtag', error)
+    }
   })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
scheduleGtagInstall(async () => {
const { default: VueGtag } = await import('vue-gtag')
nuxtApp.vueApp.use(VueGtag as any, {
config: {
id: GOOGLE_ANALYTICS_KEY
}
})
}
if (HOTJAR_KEY) {
nuxtApp.vueApp.use(hotjar as any, {
id: HOTJAR_KEY
})
}
})
scheduleGtagInstall(async () => {
try {
const { default: VueGtag } = await import('vue-gtag')
nuxtApp.vueApp.use(VueGtag as any, {
config: {
id: GOOGLE_ANALYTICS_KEY
}
})
} catch (error) {
console.warn('Failed to initialize vue-gtag', error)
}
})
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/plugins/tracking.client.ts` around lines 36 - 44, The async callback
passed to scheduleGtagInstall lacks error handling for potential failures during
the dynamic import of vue-gtag or the plugin initialization. Wrap the entire
async function body (including both the import('vue-gtag') call and the
nuxtApp.vueApp.use() call) in a try/catch block to handle any promise rejections
gracefully and prevent unhandled errors from affecting application stability.

Comment on lines +45 to +56
const buildAssetPriceDenomsLeanQuery = (denoms: string[] = []) => {
if (denoms.length === 0) {
return 'v2/denoms?withPrice=true&onlyActive=true&fields=price.price,price.market_cap,coingecko_id,symbol'
}

const denomParams = denoms.map((denom) => 'denoms=' + denom)

return [
'v2/denoms?withPrice=true&onlyActive=true&fields=price.price,price.market_cap,coingecko_id,symbol',
...denomParams
].join('&')
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

BASE="https://k8s.global.mainnet.asset.injective.network/asset-price"
QUERY="v2/denoms?withPrice=true&onlyActive=true&fields=price.price,price.market_cap,coingecko_id,symbol&denoms=inj"

curl -s "${BASE}/${QUERY}" | jq -r '
  .data.data
  | to_entries[0]
  | {
      denom_key: .key,
      value_keys: (.value | keys | sort),
      has_denom_in_value: (.value | has("denom"))
    }'

Repository: InjectiveLabs/injective-ui

Length of output: 134


🏁 Script executed:

find . -type f -name "tokenPrice.ts" | head -20

Repository: InjectiveLabs/injective-ui

Length of output: 102


🏁 Script executed:

wc -l ./app/service/app/tokenPrice.ts

Repository: InjectiveLabs/injective-ui

Length of output: 106


🏁 Script executed:

cat -n ./app/service/app/tokenPrice.ts

Repository: InjectiveLabs/injective-ui

Length of output: 8730


🏁 Script executed:

find . -type f \( -name "*.test.ts" -o -name "*.spec.ts" \) | xargs grep -l "tokenPrice\|TokenPrice" 2>/dev/null | head -10

Repository: InjectiveLabs/injective-ui

Length of output: 52


🏁 Script executed:

rg "buildAssetPriceDenomsLeanQuery|fetchUsdTokenPriceLean" --type ts

Repository: InjectiveLabs/injective-ui

Length of output: 397


🏁 Script executed:

sed -n '1,100p' app/store/token.ts | cat -n

Repository: InjectiveLabs/injective-ui

Length of output: 3694


🏁 Script executed:

rg "fetchUsdTokenPriceLean" -A 5 -B 5 app/store/token.ts

Repository: InjectiveLabs/injective-ui

Length of output: 429


Add denom field to lean price query and fix fallback logic to prevent undefined price keys.

The lean query at lines 47 and 53 excludes denom from the requested fields, but the code at line 120 falls back to tokenWithPrice.denom when coingecko_id is missing. If the API doesn't return denom and coingecko_id is undefined, id becomes undefined, causing prices to be stored under the wrong key.

Additionally, using Object.values() discards the denom key from the API response structure, eliminating a reliable fallback option.

Proposed fix
 interface TokenStaticLeanWithPrice {
-  denom: string
+  denom?: string
   symbol: string
-  coingecko_id: string
+  coingecko_id?: string
   price?: {
     price?: number
     market_cap?: number
   }
 }

 const buildAssetPriceDenomsLeanQuery = (denoms: string[] = []) => {
   if (denoms.length === 0) {
-    return 'v2/denoms?withPrice=true&onlyActive=true&fields=price.price,price.market_cap,coingecko_id,symbol'
+    return 'v2/denoms?withPrice=true&onlyActive=true&fields=denom,price.price,price.market_cap,coingecko_id,symbol'
   }

   const denomParams = denoms.map((denom) => 'denoms=' + denom)

   return [
-    'v2/denoms?withPrice=true&onlyActive=true&fields=price.price,price.market_cap,coingecko_id,symbol',
+    'v2/denoms?withPrice=true&onlyActive=true&fields=denom,price.price,price.market_cap,coingecko_id,symbol',
     ...denomParams
   ].join('&')
 }

-const tokenPriceMap = Object.values(response.data.data).reduce(
-  (tokenPriceMap: TokenPriceMap, tokenWithPrice) => {
-    const id = tokenWithPrice.coingecko_id || tokenWithPrice.denom
+const tokenPriceMap = Object.entries(response.data.data).reduce(
+  (tokenPriceMap: TokenPriceMap, [denomKey, tokenWithPrice]) => {
+    const id = tokenWithPrice.coingecko_id || tokenWithPrice.denom || denomKey
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/service/app/tokenPrice.ts` around lines 45 - 56, The
buildAssetPriceDenomsLeanQuery function excludes the denom field from its query
string, but consuming code relies on falling back to the denom value when
coingecko_id is undefined. Add denom to the fields parameter in both return
statements of buildAssetPriceDenomsLeanQuery by appending it to the existing
comma-separated fields list (alongside price.price, price.market_cap,
coingecko_id, and symbol) so that the API response includes the denom field and
the fallback logic can work correctly.

Comment thread app/service/nameCompat.ts
Comment on lines +8 to +25
const getInjNameService = () => {
if (!injNameServicePromise) {
injNameServicePromise = import('./name').then(
({ injNameService }) => injNameService
)
}

return injNameServicePromise
}

const getInjBonfidaNameService = () => {
if (!injBonfidaNameServicePromise) {
injBonfidaNameServicePromise = import('./name').then(
({ injBonfidaNameService }) => injBonfidaNameService
)
}

return injBonfidaNameServicePromise

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Reset failed lazy-import caches to avoid permanent failure state.

On Line 9 and Line 19, a failed import('./name') leaves the cached promise rejected forever. After one transient load error, all subsequent fetchInjName/fetchInjAddress calls keep failing until hard refresh.

💡 Suggested fix
 const getInjNameService = () => {
   if (!injNameServicePromise) {
-    injNameServicePromise = import('./name').then(
-      ({ injNameService }) => injNameService
-    )
+    injNameServicePromise = import('./name')
+      .then(({ injNameService }) => injNameService)
+      .catch((error) => {
+        injNameServicePromise = undefined
+        throw error
+      })
   }

   return injNameServicePromise
 }

 const getInjBonfidaNameService = () => {
   if (!injBonfidaNameServicePromise) {
-    injBonfidaNameServicePromise = import('./name').then(
-      ({ injBonfidaNameService }) => injBonfidaNameService
-    )
+    injBonfidaNameServicePromise = import('./name')
+      .then(({ injBonfidaNameService }) => injBonfidaNameService)
+      .catch((error) => {
+        injBonfidaNameServicePromise = undefined
+        throw error
+      })
   }

   return injBonfidaNameServicePromise
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const getInjNameService = () => {
if (!injNameServicePromise) {
injNameServicePromise = import('./name').then(
({ injNameService }) => injNameService
)
}
return injNameServicePromise
}
const getInjBonfidaNameService = () => {
if (!injBonfidaNameServicePromise) {
injBonfidaNameServicePromise = import('./name').then(
({ injBonfidaNameService }) => injBonfidaNameService
)
}
return injBonfidaNameServicePromise
const getInjNameService = () => {
if (!injNameServicePromise) {
injNameServicePromise = import('./name')
.then(({ injNameService }) => injNameService)
.catch((error) => {
injNameServicePromise = undefined
throw error
})
}
return injNameServicePromise
}
const getInjBonfidaNameService = () => {
if (!injBonfidaNameServicePromise) {
injBonfidaNameServicePromise = import('./name')
.then(({ injBonfidaNameService }) => injBonfidaNameService)
.catch((error) => {
injBonfidaNameServicePromise = undefined
throw error
})
}
return injBonfidaNameServicePromise
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/service/nameCompat.ts` around lines 8 - 25, The lazy-import caching in
getInjNameService and getInjBonfidaNameService functions stores rejected
promises permanently when the import fails. Add error handling with a catch
block to both import chains that resets the respective cache variable
(injNameServicePromise and injBonfidaNameServicePromise) back to null/undefined
when an error occurs, then re-throws the error. This ensures that if a transient
import failure happens, the next call to these functions will attempt to
re-import the module instead of returning the cached rejected promise.

Comment thread app/store/token.ts
Comment on lines +22 to +24
tokenUsdPriceMap: {
[usdcToken.denom]: 1
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Filtered fetches are overwriting the entire USD maps.

Line 172/Line 182/Line 193 replace whole maps even when denoms is a subset. That drops previously cached prices (and the seeded USDC denom on Line 23), so non-requested tokens can regress to 0 in tokenUsdPrice.

Proposed fix
 async fetchTokensUsdPriceMap(denoms: string[] = []) {
   const sharedTokenStore = useSharedTokenStore()

   const tokenUsdPriceMap =
     await tokenPriceService.fetchUsdTokensPrice(denoms)

-  sharedTokenStore.tokenUsdPriceMap = tokenUsdPriceMap.prices
-  sharedTokenStore.tokenUsdMarketCapMap = tokenUsdPriceMap.marketCap
+  sharedTokenStore.tokenUsdPriceMap =
+    denoms.length === 0
+      ? tokenUsdPriceMap.prices
+      : { ...sharedTokenStore.tokenUsdPriceMap, ...tokenUsdPriceMap.prices }
+  sharedTokenStore.tokenUsdMarketCapMap =
+    denoms.length === 0
+      ? tokenUsdPriceMap.marketCap
+      : {
+          ...sharedTokenStore.tokenUsdMarketCapMap,
+          ...tokenUsdPriceMap.marketCap
+        }
 },

 async fetchTokensUsdPriceMapLean(denoms: string[] = []) {
   const sharedTokenStore = useSharedTokenStore()

   const tokenUsdPriceMap =
     await tokenPriceService.fetchUsdTokenPriceLean(denoms)

-  sharedTokenStore.tokenUsdPriceMap = tokenUsdPriceMap.prices
-  sharedTokenStore.tokenUsdMarketCapMap = tokenUsdPriceMap.marketCap
+  sharedTokenStore.tokenUsdPriceMap =
+    denoms.length === 0
+      ? tokenUsdPriceMap.prices
+      : { ...sharedTokenStore.tokenUsdPriceMap, ...tokenUsdPriceMap.prices }
+  sharedTokenStore.tokenUsdMarketCapMap =
+    denoms.length === 0
+      ? tokenUsdPriceMap.marketCap
+      : {
+          ...sharedTokenStore.tokenUsdMarketCapMap,
+          ...tokenUsdPriceMap.marketCap
+        }
 },

Also applies to: 166-197

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/store/token.ts` around lines 22 - 24, The tokenUsdPriceMap is being
completely replaced at lines 172, 182, and 193 when filtered denoms are fetched,
which overwrites previously cached prices including the seeded USDC denom.
Instead of assigning the fetched prices directly to tokenUsdPriceMap, merge the
new prices into the existing map by using spread syntax or Object.assign to
preserve previously cached values while adding the newly fetched prices.

Comment on lines +32 to +37
vi.mock('../../service', () => ({
getAuthZApi: vi.fn(),
web3GatewayService: {
healthCheck: vi.fn()
}
}))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Mock path no longer matches the module imported by the store.

Line 32 mocks ../../service, but app/store/wallet/index.ts imports web3GatewayService from ../../service/web3 (Line 4). This mock won’t intercept that dependency.

Suggested patch
-vi.mock('../../service', () => ({
-  getAuthZApi: vi.fn(),
-  web3GatewayService: {
-    healthCheck: vi.fn()
-  }
-}))
+vi.mock('../../service/web3', () => ({
+  web3GatewayService: {
+    healthCheck: vi.fn()
+  }
+}))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
vi.mock('../../service', () => ({
getAuthZApi: vi.fn(),
web3GatewayService: {
healthCheck: vi.fn()
}
}))
vi.mock('../../service/web3', () => ({
web3GatewayService: {
healthCheck: vi.fn()
}
}))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/store/wallet/index.spec.ts` around lines 32 - 37, The mock path in the
vi.mock call at the beginning of the test file is using `../../service`, but the
actual code in app/store/wallet/index.ts imports web3GatewayService from
`../../service/web3`. Update the mock path in the vi.mock function to match the
actual import path by changing `../../service` to `../../service/web3`, ensuring
the mock properly intercepts the web3GatewayService dependency and its
healthCheck method.

Comment thread scripts/gen-bff-types.ts
Comment on lines +36 to +43
if (!target || !(target in BFF_OPENAPI_URLS)) {
console.error(
`Usage: tsx scripts/gen-bff-types.ts ${Object.keys(BFF_OPENAPI_URLS).join('|')}`
)
process.exit(1)
}

return target as BffTypesTarget

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

head -50 scripts/gen-bff-types.ts

Repository: InjectiveLabs/injective-ui

Length of output: 1401


Use Object.hasOwn() for strict own-property validation.

Line 36 uses the in operator, which checks both own and inherited properties. This means inherited keys like toString or constructor would incorrectly pass validation. Use Object.hasOwn() to ensure only the declared targets (dev, staging, production) are accepted.

Proposed fix
-  if (!target || !(target in BFF_OPENAPI_URLS)) {
+  if (!target || !Object.hasOwn(BFF_OPENAPI_URLS, target)) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!target || !(target in BFF_OPENAPI_URLS)) {
console.error(
`Usage: tsx scripts/gen-bff-types.ts ${Object.keys(BFF_OPENAPI_URLS).join('|')}`
)
process.exit(1)
}
return target as BffTypesTarget
if (!target || !Object.hasOwn(BFF_OPENAPI_URLS, target)) {
console.error(
`Usage: tsx scripts/gen-bff-types.ts ${Object.keys(BFF_OPENAPI_URLS).join('|')}`
)
process.exit(1)
}
return target as BffTypesTarget
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/gen-bff-types.ts` around lines 36 - 43, The validation check on line
36 uses the `in` operator which checks both own and inherited properties of the
BFF_OPENAPI_URLS object, allowing inherited keys like toString or constructor to
incorrectly pass validation. Replace the condition `!(target in
BFF_OPENAPI_URLS)` with `!Object.hasOwn(BFF_OPENAPI_URLS, target)` to ensure
only the explicitly declared targets are accepted.

Comment thread scripts/gen-bff-types.ts
Comment on lines +77 to +83
async function fetchOpenApiSpec(openApiUrl: string, apiKey: string) {
const response = await fetch(openApiUrl, {
headers: {
'x-api-key': apiKey
}
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n scripts/gen-bff-types.ts | sed -n '70,100p'

Repository: InjectiveLabs/injective-ui

Length of output: 936


🏁 Script executed:

cat -n scripts/gen-bff-types.ts | sed -n '93,150p'

Repository: InjectiveLabs/injective-ui

Length of output: 1020


🏁 Script executed:

rg "fetch\(" scripts/gen-bff-types.ts -n

Repository: InjectiveLabs/injective-ui

Length of output: 118


Add a timeout/abort to the OpenAPI fetch.

The fetch on line 78 has no timeout; a stalled network call can hang the generation job indefinitely. Use AbortController with a reasonable timeout (e.g., 15 seconds).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/gen-bff-types.ts` around lines 77 - 83, The fetchOpenApiSpec function
makes a fetch call without any timeout, which can cause the generation job to
hang indefinitely if the network stalls. Add an AbortController instance and set
a timeout (e.g., 15 seconds) that will abort the request if it exceeds the time
limit. Pass the abort signal from the controller in the fetch options headers,
and ensure the fetch call properly handles any abort errors that may be thrown.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (4)
app/wallet/pkBroadcaster.ts (1)

5-32: 🧹 Nitpick | 🔵 Trivial | 💤 Low value

Consider clearing the cached instance when the private key changes.

When a different privateKey is passed, the old msgBroadcasterWithPkInstance is overwritten without cleanup. If MsgBroadcasterWithPk holds any resources (connections, event listeners), they may leak. Additionally, concurrent calls with different private keys could race to overwrite the cache.

If MsgBroadcasterWithPk is stateless and lightweight, this is fine. Otherwise, consider explicitly nullifying the old instance or adding a cleanup method.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/wallet/pkBroadcaster.ts` around lines 5 - 32, When a different privateKey
is passed to getMsgBroadcasterWithPk, the old msgBroadcasterWithPkInstance is
overwritten without cleanup, which may cause resource leaks if
MsgBroadcasterWithPk holds connections or event listeners. Before creating and
assigning the new MsgBroadcasterWithPk instance in the import promise chain,
first nullify the old msgBroadcasterWithPkInstance to ensure any resources are
properly released. This should occur inside the .then block, after the
conditional check fails but before constructing the new instance.
app/store/oracle/index.ts (1)

76-80: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Extract the hardcoded mainnet URL to a constant.

The mainnet oracle stream URL is hardcoded on Line 78, while the testnet path uses ENDPOINTS.indexer. For consistency and maintainability, extract the mainnet URL to a constant (e.g., in app/utils/constant/setup.ts alongside ENDPOINTS).

♻️ Suggested refactor

In app/utils/constant/setup.ts, add:

export const ORACLE_STREAM_ENDPOINT = IS_MAINNET
  ? 'https://tc-derivatives.grpc-web.mainnet.asia.injective.network/'
  : ENDPOINTS.indexer

Then update this file:

-      const oracleStreamV2 = new IndexerGrpcOracleStreamV2(
-        IS_MAINNET
-          ? 'https://tc-derivatives.grpc-web.mainnet.asia.injective.network/'
-          : ENDPOINTS.indexer
-      )
+      const oracleStreamV2 = new IndexerGrpcOracleStreamV2(ORACLE_STREAM_ENDPOINT)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/store/oracle/index.ts` around lines 76 - 80, Extract the hardcoded
mainnet URL from the IndexerGrpcOracleStreamV2 instantiation in
app/store/oracle/index.ts into a constant for consistency. Create a new constant
called ORACLE_STREAM_ENDPOINT in app/utils/constant/setup.ts that returns the
appropriate URL based on the IS_MAINNET flag (mainnet URL for true,
ENDPOINTS.indexer for false). Then update the IndexerGrpcOracleStreamV2
constructor call to use this new constant instead of the inline conditional
expression with the hardcoded URL.
nuxt-config/vite/chunk/index.ts (1)

365-368: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Consider documenting the vite/preload-helper special case.

The explicit routing of vite/preload-helper to SharedVendor is a sensible optimization (as a Vite internal used across entry points), but it lacks explanation. Consider adding a brief comment to help future maintainers understand this special case.

📝 Suggested comment addition
 export function manualChunks(id: string): string | undefined {
+  // Vite's preload helper is used across entry points; bundle it in SharedVendor
+  // to avoid duplication and ensure it's available early
   if (id.includes('vite/preload-helper')) {
     return ChunkName.SharedVendor
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@nuxt-config/vite/chunk/index.ts` around lines 365 - 368, The condition
checking for vite/preload-helper lacks documentation explaining why this module
is specifically routed to SharedVendor. Add a brief comment above the if
statement that explains this is a Vite internal module used across multiple
entry points, which makes it a sensible optimization candidate for shared vendor
chunking. This will help future maintainers understand the rationale behind this
special case routing.
modules/preload-optimization.ts (1)

179-212: 🧹 Nitpick | 🔵 Trivial

Add clarifying comment explaining why both preload filtering hooks are necessary.

This PR adds a vite:extendConfig hook that filters preload dependencies at config-time via resolveDependencies (lines 179-212), while the existing build:manifest hook applies a safety check at post-build time to ensure excluded files don't have preload: true (lines 213-226). Both hooks use the same shouldExcludeFromPreload() logic but operate on different data stages.

Without a comment explaining why both mechanisms are needed, it's unclear whether this is intentional defense-in-depth or unintentional overlap. Consider adding a brief inline comment explaining the relationship between these two filtering stages.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@modules/preload-optimization.ts` around lines 179 - 212, Add a clarifying
comment above the vite:extendConfig hook in the preload-optimization module
explaining the relationship between the two filtering mechanisms. The comment
should explain that this hook filters dependencies at config-time via the
resolveDependencies callback, while the existing build:manifest hook applies a
post-build safety check to ensure excluded files don't have preload:true set.
Make it clear that both hooks use the same shouldExcludeFromPreload logic but
operate at different stages (config-time vs post-build), establishing this as an
intentional defense-in-depth approach to ensure excluded files are properly
handled throughout the entire build process.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@app/store/oracle/index.ts`:
- Around line 76-80: Extract the hardcoded mainnet URL from the
IndexerGrpcOracleStreamV2 instantiation in app/store/oracle/index.ts into a
constant for consistency. Create a new constant called ORACLE_STREAM_ENDPOINT in
app/utils/constant/setup.ts that returns the appropriate URL based on the
IS_MAINNET flag (mainnet URL for true, ENDPOINTS.indexer for false). Then update
the IndexerGrpcOracleStreamV2 constructor call to use this new constant instead
of the inline conditional expression with the hardcoded URL.

In `@app/wallet/pkBroadcaster.ts`:
- Around line 5-32: When a different privateKey is passed to
getMsgBroadcasterWithPk, the old msgBroadcasterWithPkInstance is overwritten
without cleanup, which may cause resource leaks if MsgBroadcasterWithPk holds
connections or event listeners. Before creating and assigning the new
MsgBroadcasterWithPk instance in the import promise chain, first nullify the old
msgBroadcasterWithPkInstance to ensure any resources are properly released. This
should occur inside the .then block, after the conditional check fails but
before constructing the new instance.

In `@modules/preload-optimization.ts`:
- Around line 179-212: Add a clarifying comment above the vite:extendConfig hook
in the preload-optimization module explaining the relationship between the two
filtering mechanisms. The comment should explain that this hook filters
dependencies at config-time via the resolveDependencies callback, while the
existing build:manifest hook applies a post-build safety check to ensure
excluded files don't have preload:true set. Make it clear that both hooks use
the same shouldExcludeFromPreload logic but operate at different stages
(config-time vs post-build), establishing this as an intentional
defense-in-depth approach to ensure excluded files are properly handled
throughout the entire build process.

In `@nuxt-config/vite/chunk/index.ts`:
- Around line 365-368: The condition checking for vite/preload-helper lacks
documentation explaining why this module is specifically routed to SharedVendor.
Add a brief comment above the if statement that explains this is a Vite internal
module used across multiple entry points, which makes it a sensible optimization
candidate for shared vendor chunking. This will help future maintainers
understand the rationale behind this special case routing.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 01f9028b-b983-41d6-9958-07fc569bee5f

📥 Commits

Reviewing files that changed from the base of the PR and between 42263b7 and 7df4d68.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !pnpm-lock.yaml
📒 Files selected for processing (66)
  • app/classes/TokenFactoryStatic.ts
  • app/classes/Tokens.ts
  • app/components/Amount/Base.vue
  • app/components/Amount/Index.spec.ts
  • app/components/Amount/Index.vue
  • app/components/Amount/Usd.spec.ts
  • app/components/Amount/Usd.vue
  • app/components/NumInput.vue
  • app/components/QRCode.vue
  • app/composables/useSharedBigNumberFormatted.ts
  • app/data/token.ts
  • app/data/tokenLogo.ts
  • app/providers/cacheApi/derivative.ts
  • app/providers/cacheApi/spot.ts
  • app/service/app/CoinGeckoApi.ts
  • app/service/app/Faucet.ts
  • app/service/app/SharedTokenClientStatic.ts
  • app/service/app/Web3Client.ts
  • app/service/app/Web3Gateway.ts
  • app/service/app/bonfida.ts
  • app/service/app/cacheRwaPriceFeedService.ts
  • app/service/app/ethGasPrice/estimator.ts
  • app/service/app/ethGasPrice/index.ts
  • app/service/app/nameService/utils.ts
  • app/service/app/pythClient.ts
  • app/service/app/tokenClient.ts
  • app/service/app/tokenPrice.ts
  • app/service/indexer.ts
  • app/store/evm.ts
  • app/store/geo.ts
  • app/store/json.ts
  • app/store/oracle/index.ts
  • app/store/param.ts
  • app/store/token.ts
  • app/store/wallet/extensions.ts
  • app/store/wallet/index.spec.ts
  • app/store/wallet/index.ts
  • app/store/wallet/magic.ts
  • app/store/wallet/turnkey.ts
  • app/transformer/explorer/index.ts
  • app/transformer/explorer/messageEvents.ts
  • app/transformer/explorer/messageSummary.ts
  • app/transformer/market/fundingRate.ts
  • app/transformer/market/index.ts
  • app/transformer/market/summary.ts
  • app/transformer/oracle.ts
  • app/transformer/trade/order.ts
  • app/types/market.ts
  • app/types/trade.ts
  • app/utils/constant/index.ts
  • app/utils/constant/setup.ts
  • app/utils/evm/Erc20Contract.ts
  • app/utils/evm/WETH9Contract.ts
  • app/utils/formatter.ts
  • app/utils/helper.ts
  • app/utils/ibc.ts
  • app/utils/index.ts
  • app/utils/time.ts
  • app/wallet/pkBroadcaster.ts
  • app/wallet/strategy.ts
  • app/wallet/utils/authz.ts
  • modules/preload-optimization.ts
  • nuxt-config/vite/chunk/bridge.ts
  • nuxt-config/vite/chunk/index.spec.ts
  • nuxt-config/vite/chunk/index.ts
  • nuxt.config.ts
💤 Files with no reviewable changes (1)
  • nuxt-config/vite/chunk/bridge.ts
✅ Files skipped from review due to trivial changes (11)
  • app/utils/constant/index.ts
  • app/components/Amount/Index.spec.ts
  • app/service/app/Web3Gateway.ts
  • app/transformer/market/index.ts
  • app/service/app/pythClient.ts
  • app/service/app/CoinGeckoApi.ts
  • app/utils/helper.ts
  • app/classes/TokenFactoryStatic.ts
  • app/types/market.ts
  • app/transformer/oracle.ts
  • app/transformer/market/summary.ts
🚧 Files skipped from review as they are similar to previous changes (12)
  • app/wallet/utils/authz.ts
  • app/store/wallet/turnkey.ts
  • app/store/param.ts
  • app/service/app/tokenClient.ts
  • app/classes/Tokens.ts
  • app/store/wallet/magic.ts
  • app/components/Amount/Usd.spec.ts
  • app/utils/constant/setup.ts
  • app/providers/cacheApi/derivative.ts
  • app/store/token.ts
  • app/store/wallet/index.spec.ts
  • app/service/app/tokenPrice.ts

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.

4 participants