Skip to content

feat: oneinch fusion#752

Merged
kvhnuke merged 12 commits intodevop/release-v-2-13from
feat/oneinch-fusion
Sep 25, 2025
Merged

feat: oneinch fusion#752
kvhnuke merged 12 commits intodevop/release-v-2-13from
feat/oneinch-fusion

Conversation

@kvhnuke
Copy link
Contributor

@kvhnuke kvhnuke commented Sep 11, 2025

Summary by CodeRabbit

  • New Features

    • RFQ swapping via 1inch Fusion with typed-message signing and order submission.
    • Native token wrap support in swap flows.
  • Improvements

    • "Waiting for mining" UI and background receipt polling to track transactions.
    • Graceful handling when gas data is missing (shows zero-fee tiers).
    • Providers return no-quote instead of throwing on missing price data.
    • More accurate activity transaction recording for RFQ trades.
  • Changes

    • Removed Kaia and Aurora from supported networks.

@coderabbitai
Copy link

coderabbitai bot commented Sep 11, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (3)
  • main
  • develop
  • devop/vite-migrate

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

Adds RFQ support: new OneInchFusion provider and RFQ types, RFQ UI wiring (fetch/sign/submit), wait-for-receipt helper, native-wrap helpers and ABI, provider response tagging with SwapType, config and dependency updates, and tests.

Changes

Cohort / File(s) Summary
UI: RFQ integration
packages/extension/src/ui/action/views/swap/index.vue, packages/extension/src/ui/action/views/swap/types.ts
Filter RFQ trades, fetch per-trade RFQ option objects via getRFQObject(), attach rfqOptions to trades; add rfqOptions?: RFQOptionsResponse to ProviderResponseWithStatus.
UI: Best-offer RFQ flow & initiated view
packages/extension/src/ui/action/views/swap/views/swap-best-offer/index.vue, packages/extension/src/ui/action/views/swap-initiated/index.vue
Initialize Swap for RFQ, sign EVM typed-messages (EIP‑712 V4), wait for receipts, submit RFQ orders, record RFQ orderHash in activity, expose waitingToBeMined prop and waiting state, adjust txHash/disabled logic, add debug logs.
EVM helpers
packages/extension/src/ui/action/views/swap/libs/evm-gasvals.ts, packages/extension/src/ui/action/views/swap/libs/evm-waitreceipt.ts
Return zero-fee tiers when gasVals empty; add waitForReceipt(hashes, network, timeout) to poll receipts with timeout and logging.
Core types & API surface
packages/swap/src/types/index.ts, packages/swap/src/index.ts, packages/swap/src/configs.ts
Add ProviderName.oneInchFusion, SwapType enum (regular,rfq), RFQ types (RFQOptions, RFQOptionsResponse), extend ProviderSwapResponse with type/typedMessages/getRFQObject, add ProviderWithRFQ abstract class, add submitRFQOrder on Swap, add Fusion fee configs and Wrap gas limit.
New provider: OneInch Fusion
packages/swap/src/providers/oneInchFusion/index.ts, packages/swap/src/providers/oneInchFusion/types.ts
New OneInchFusion provider (extends ProviderWithRFQ) implementing RFQ quote/swap flows, typedMessages, order creation/submission, status mapping, token maps; new OneInchSwapResponse type.
Existing providers: annotate SwapType & minor fixes
packages/swap/src/providers/.../index.ts
packages/swap/src/providers/{changelly,jupiter,okx,oneInch,paraswap,rango,zerox}/index.ts
Tag provider responses with type: SwapType.regular; minor error-handling and response-shape adjustments (ParaSwap/0x), export/supportedNetworks tweaks for OneInch.
Approvals & wrapper ABI
packages/swap/src/utils/approvals.ts, packages/swap/src/utils/abi/wrapper.ts
Add native-wrap helpers isSufficientWrappedAvailable and getNativeWrapTx, change getAllowanceTransactions fromToken shape to { address: string }, export new helpers, add wrapper contract ABI.
Dependencies
packages/swap/package.json
Add runtime deps @1inch/fusion-sdk and @1inch/limit-order-sdk.
Tests
packages/swap/tests/oneInchFusion.test.ts, packages/swap/tests/swap.test.ts
Add integration tests for OneInchFusion approval flows and include oneInchFusion in existing swap tests.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant UI as Swap UI
  participant SwapAPI as Swap
  participant Provider as OneInchFusion
  participant Wallet as EVM Signer
  participant Chain as Network/Web3
  participant Relayer as Fusion Relayer

  UI->>SwapAPI: request quotes (may include RFQ)
  SwapAPI->>Provider: getQuote(params)
  Provider-->>SwapAPI: quote { type: rfq, getRFQObject }
  SwapAPI-->>UI: quotes (RFQ includes rfqOptions via getRFQObject())

  UI->>SwapAPI: request swap for selected RFQ quote
  SwapAPI->>Provider: getSwap(quote)
  Provider-->>SwapAPI: swap { transactions[], typedMessages[], rfq metadata }
  SwapAPI-->>UI: swap payload (includes typedMessages)

  UI->>Wallet: sign typedMessages (EIP‑712 v4) -> signatures
  alt on-chain txs present
    loop for each tx
      UI->>Chain: sendTransaction(tx)
      Chain-->>UI: txHash
    end
    UI->>Chain: waitForReceipt([txHash...]) --poll-->
    Chain-->>UI: receipts ready
  end

  UI->>SwapAPI: submitRFQOrder(rfqOptions + signatures)
  SwapAPI->>Provider: submitRFQOrder(options)
  Provider->>Relayer: submit(order + signatures)
  Relayer-->>Provider: orderHash
  Provider-->>SwapAPI: orderHash
  SwapAPI-->>UI: orderHash (persist activity)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60–90 minutes

Possibly related PRs

Suggested reviewers

  • gamalielhere

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly identifies the main new capability—integrating the OneInch Fusion RFQ-based swap provider—following the feat: prefix convention and clearly reflecting the primary focus of the changeset.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.

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

❤️ Share

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

@github-actions
Copy link

github-actions bot commented Sep 11, 2025

💼 Build Files
chrome: enkrypt-chrome-4df768d3.zip
firefox: enkrypt-firefox-4df768d3.zip

💉 Virus total analysis
chrome: 4df768d3
firefox: 4df768d3

Copy link

@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: 16

Caution

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

⚠️ Outside diff range comments (12)
packages/signers/polkadot/src/index.ts (4)

49-55: Remove unsupported 5th arg to mnemonicToMiniSecret (breaks types; no effect at runtime).

mnemonicToMiniSecret accepts up to 4 params (mnemonic, password?, wordlist?, onlyJs?). Passing a 5th 2048 is invalid for current @polkadot/util-crypto typings and will fail TS checks; BIP-39’s 2048 PBKDF2 iterations are already hardcoded internally, not configurable here. Drop the extra argument. (jsdocs.io)

-    const seed = mnemonicToMiniSecret(
-      phrase,
-      password,
-      undefined,
-      options.onlyJS,
-      2048,
-    );
+    const seed = mnemonicToMiniSecret(
+      phrase,
+      password,
+      undefined, // default wordlist
+      options.onlyJS,
+    );

115-123: Async verify is not awaited; assert always passes.

assert(this.verify(...)) receives a Promise, which is truthy; signature verification is effectively skipped. Await the result.

-        assert(
-          this.verify(
+        assert(
+          await this.verify(
             bufferToHex(msgHashBuffer),
             bufferToHex(sig),
             bufferToHex(pair.publicKey),
           ),
           Errors.SigningErrors.UnableToVerify,
         );

126-134: Same here: await verify for ed25519 path.

-        assert(
-          this.verify(
+        assert(
+          await this.verify(
             bufferToHex(msgHashBuffer),
             bufferToHex(sig),
             bufferToHex(pair.publicKey),
           ),
           Errors.SigningErrors.UnableToVerify,
         );

137-145: Same here: await verify for sr25519 path.

-        assert(
-          this.verify(
+        assert(
+          await this.verify(
             bufferToHex(msgHashBuffer),
             bufferToHex(sig),
             bufferToHex(pair.publicKey),
           ),
           Errors.SigningErrors.UnableToVerify,
         );
packages/extension/package.json (1)

92-143: Action required — fix vue-echarts / ECharts peer mismatch; CRX plugin OK

  • vue-echarts@7.x targets ECharts v5 and is NOT compatible with ECharts v6. Either upgrade vue-echarts to v8 (v8 adds ECharts 6 peer support) or pin ECharts to v5. Location: packages/extension/package.json (lines 92–143).
  • @crxjs/vite-plugin@2.2.0 is compatible with Vite 7 — no change required. Location: packages/extension/package.json (lines 92–143).
packages/swap/src/providers/rango/index.ts (2)

1124-1169: Solana totalGaslimit computation can throw and/or be NaN.

  • totalGaslimit is used before initialization in the Solana branch, yielding NaN.
  • It unconditionally deserializes a VersionedTransaction even when tx.kind is "legacy", which will throw.

Fix by initializing and branching on tx.kind.

-    let totalGaslimit: number;
+    let totalGaslimit = 0;
     switch (res.networkTransactions.type) {
       case NetworkType.EVM: {
-        totalGaslimit = res.networkTransactions.transactions.reduce(
+        totalGaslimit = res.networkTransactions.transactions.reduce(
           (total: number, curVal: EVMTransaction) =>
             total + toBN(curVal.gasLimit).toNumber(),
           0,
         );
         break;
       }
       case NetworkType.Solana: {
-        for (
-          let i = 0, len = res.networkTransactions.transactions.length;
-          i < len;
-          i++
-        ) {
-          const tx = res.networkTransactions.transactions[i];
-          totalGaslimit += extractComputeBudget(
-            VersionedTransaction.deserialize(
-              Buffer.from(tx.serialized, "base64"),
-            ),
-          );
-        }
+        for (const tx of res.networkTransactions.transactions) {
+          if (tx.kind === "versioned") {
+            totalGaslimit += extractComputeBudget(
+              VersionedTransaction.deserialize(
+                Buffer.from(tx.serialized, "base64"),
+              ),
+            );
+          } else {
+            // Legacy tx: we don’t have a compute-budget extractor here; fall back to 0.
+            // Consider adding a legacy extractor or estimating via RPC if needed.
+          }
+        }
         break;
       }

1585-1596: Wrong condition for “unsigned” retry path in Solana sim helpers.

Comments say “only works for unsigned transactions” but code runs on signed ones. Flip the condition.

-    if (retryidx > 0 && signed) {
+    if (retryidx > 0 && !signed) {
@@
-    if (retryidx > 0 && signed) {
+    if (retryidx > 0 && !signed) {

Also applies to: 1640-1650

packages/swap/src/providers/jupiter/index.ts (4)

468-475: Fix optional context access in catch.

context is optional; accessing context.signal can throw and mask real errors.

-      if (!context.signal.aborted) {
+      if (!context?.signal?.aborted) {
         console.error(
           `[Jupiter.getQuote] Error calling getQuote: ${String(err)}`,
         );
       }

524-531: Same fix: optional context in getSwap catch.

-      if (!context.signal.aborted) {
+      if (!context?.signal?.aborted) {
         console.error(
           `[Jupiter.getSwap] Error calling getSwap: ${String(err)}`,
         );
       }

1005-1011: Bug: Wrong null-check after parsing swap response.

Checks quote instead of swap; will never catch a missing/empty swap and may throw erroneously.

-      if (!quote) {
+      if (!swap) {
         throw new Error(
           `Failed to get Jupiter swap at url ${url}, something went wrong and result is falsy`,
         );
       }

1054-1075: Make sleep abort-safe when no signal is provided.

Directly dereferencing abortable.signal can throw when abortable or signal is undefined.

 function sleep(
   duration: number,
   abortable?: { signal?: AbortSignal },
 ): Promise<void> {
-  if (abortable.signal.aborted) return Promise.reject(abortable.signal.reason);
+  if (abortable?.signal?.aborted) {
+    return Promise.reject(abortable.signal.reason);
+  }
   if (duration <= 0) return Promise.resolve();
   return new Promise<void>((res, rej) => {
     function onTimeout() {
       cleanupSleep();
       res();
     }
     function onAbortDuringSleep() {
       cleanupSleep();
-      rej(abortable.signal!.reason);
+      rej(abortable?.signal?.reason);
     }
     function cleanupSleep() {
-      abortable?.signal?.removeEventListener("abort", onAbortDuringSleep);
+      abortable?.signal?.removeEventListener("abort", onAbortDuringSleep);
       clearTimeout(timeout);
     }
-    abortable?.signal?.addEventListener("abort", onAbortDuringSleep);
+    abortable?.signal?.addEventListener("abort", onAbortDuringSleep);
     const timeout = setTimeout(onTimeout, duration);
   });
 }
packages/swap/src/providers/oneInch/index.ts (1)

269-279: Avoid crash when FEE_CONFIGS path is missing.

  • Issue: Accessing FEE_CONFIGS[this.name][...].fee can throw if any segment is undefined — make lookups null-safe.
  • Locations: packages/swap/src/providers/oneInch/index.ts — lines 158-161 and 268-271.
  • Apply the original suggested change (keep exactly as shown) to the occurrence at lines 268-271:
-      const feeConfig =
-        FEE_CONFIGS[this.name][quote.meta.walletIdentifier].fee || 0;
+      const feeCfg =
+        FEE_CONFIGS[this.name]?.[quote.meta.walletIdentifier];
+      const feePercent = feeCfg?.fee ?? 0;
...
-        fee: feeConfig * 100,
+        fee: feePercent * 100,
  • Also apply the same null-safe pattern to the earlier occurrence at lines 158-161 (replace direct FEE_CONFIGS[this.name][meta.walletIdentifier] access with optional chaining + nullish coalescing).
🧹 Nitpick comments (44)
Dockerfile (1)

1-1: Slim image and make Yarn deterministic via Corepack.

Apply:

 FROM node:22.18-bookworm
-RUN apt-get update
-RUN apt-get install build-essential zip -y
+RUN apt-get update && apt-get install -y --no-install-recommends build-essential zip \
+  && rm -rf /var/lib/apt/lists/*
 ENV HOME /home
 ENV NODE_OPTIONS --max-old-space-size=8192
-RUN node -v && npm -v && yarn -v
+RUN corepack enable && corepack prepare yarn@4.5.1 --activate
+RUN node -v && npm -v && yarn -v
 WORKDIR /home
.github/workflows/test-swap.yml (1)

12-12: Enable Corepack, enforce immutable installs, and cache Yarn v4 for speed.

Add after setup-node:

      - run: corepack enable

Replace install step:

      - run: yarn install --immutable

Cache Yarn 4 offline cache:

      - uses: actions/cache@v4
        with:
          path: |
            .yarn/cache
            .yarn/unplugged
            .yarn/build-state.yml
            .yarn/install-state.gz
          key: yarn4-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
          restore-keys: |
            yarn4-${{ runner.os }}-
.github/workflows/test-all.yml (1)

12-12: Same as swap workflow: Corepack + immutable + Yarn v4 cache.

Replicate the steps from the swap workflow here (corepack enable, yarn --immutable, actions/cache for .yarn/*).

packages/request/package.json (1)

34-49: Tooling bumps LGTM; consider updating engines to drop EOL Node.

This workspace targets Node 22; advertising >=14.15.0 can mislead consumers.

Outside this hunk, adjust:

-  "engines": {
-    "node": ">=14.15.0"
-  },
+  "engines": {
+    "node": ">=18.18.0"
+  },
packages/types/package.json (1)

27-31: Align @types/node across the monorepo and bump engines.node to >=18.18.0

  • Found mixed @types/node: ^24.3.1 in packages/hw-wallets and packages/signers/{bitcoin,ethereum,kadena,polkadot}; ^22.18.1 in packages/{extension,extension-bridge,keyring,name-resolution,request,storage,swap,types,utils}. Unify to a single major (recommend ^22.18.1 to match the majority).
  • All packages currently list "engines.node": ">=14.15.0" — ESLint v9 drops support for Node <18.18.0; update engines in each package.json. Suggested change:
  "engines": {
-   "node": ">=14.15.0"
+   "node": ">=18.18.0"
  },
packages/keyring/package.json (1)

37-41: Unify Node typings and engines

  • @types/node is ^22 here while some packages use ^24. Standardize across the repo (recommend 22.x to match Node 22.18 runtime).
  • Consider bumping engines.node to >=18.18.0 due to ESLint 9.

Use the monorepo audit script shared in types/package.json comment.

Also applies to: 50-51

packages/name-resolution/package.json (1)

45-46: Fix placeholder repository URL

Repo URL still has <FILL_IT>.

Outside-changes patch:

-  "url": "git+https://github.com/<FILL_IT>"
+  "url": "git+https://github.com/enkryptcom/enKrypt/tree/main/packages/name-resolution"
packages/storage/package.json (1)

30-34: Standardize @types/node and engines across packages

Same note as other packages: align @types/node major across the workspace (recommend 22.x) and consider engines.node >=18.18.0 for ESLint 9.

Use the workspace audit script posted earlier.

Also applies to: 43-45

packages/signers/bitcoin/package.json (1)

35-39: Unify Node typings to match runtime (Node 22.18)

This package uses @types/node ^24 while others use ^22. Recommend standardizing on ^22.18.x to match the repo’s Node version and avoid conflicting lib.dom/node type resolutions.

Use the audit script from types/package.json comment to list all versions in the workspace.

Also applies to: 48-49

packages/signers/ethereum/package.json (1)

35-39: Same: align @types/node major and engines

Keep @types/node consistent with the rest (recommend ^22.18.x) and consider updating engines.node >=18.18.0 for ESLint 9.

Use the workspace audit script from types/package.json.

Also applies to: 48-49

packages/signers/kadena/package.json (3)

16-20: Wire up ESLint in scripts (Prettier-only right now).

You added ESLint deps but the script runs only Prettier. Recommend adding a dedicated ESLint task and keeping format separate.

   "scripts": {
-    "build": "tsup src/index.ts --format esm,cjs --dts --clean",
-    "lint": "prettier --write .",
+    "build": "tsup src/index.ts --format esm,cjs --dts --clean",
+    "lint": "npm run lint:eslint && npm run format:check",
+    "lint:eslint": "eslint . --ext .ts",
+    "format:check": "prettier --check .",
+    "format:write": "prettier --write .",
     "test": "vitest run"
   },

21-23: Align engines with repo Node 22.x.

Everything else in the repo targets Node 22.18.0; this still advertises Node 14. Suggest bumping to avoid accidental installs on unsupported Node.

   "engines": {
-    "node": ">=14.15.0"
+    "node": ">=18.17.0"
   },

Also applies to: 31-48


34-36: Avoid duplicating TypeScript-ESLint meta and individual packages.

You have both @typescript-eslint/{eslint-plugin,parser} and the meta package typescript-eslint. Pick one approach to reduce version skew. Easiest: drop the meta package.

-    "typescript-eslint": "8.43.0",

Also applies to: 47-47

packages/extension-bridge/package.json (2)

32-36: ESLint not used in scripts.

Same as other packages—add an ESLint script and separate format check.

   "scripts": {
     "build": "tsup src/index.ts src/window/index.ts src/types.ts --clean --format esm,cjs --dts",
-    "test": "echo 'no-tests'",
-    "lint": "prettier --write ."
+    "test": "echo 'no-tests'",
+    "lint": "npm run lint:eslint && npm run format:check",
+    "lint:eslint": "eslint . --ext .ts",
+    "format:check": "prettier --check .",
+    "format:write": "prettier --write ."
   },

Also applies to: 46-65


21-23: Set engines.node ≥18 to match CI/runtime.

Prevent accidental installs on older Node when running Vitest/Vite config with import.meta.resolve.

   "engines": {
-    "node": ">=14.15.0"
+    "node": ">=18.17.0"
   },

Also applies to: 47-65

packages/swap/package.json (2)

21-23: Engines mismatch with repo Node 22.x.

Bump to avoid running tests/build on Node 14.

   "engines": {
-    "node": ">=14.15.0"
+    "node": ">=18.17.0"
   },

Also applies to: 44-60


16-20: Add ESLint to scripts (Prettier-only now).

Consistent with other packages.

   "scripts": {
-    "build": "tsup src/index.ts --format esm,cjs --dts --clean",
-    "lint": "prettier --write .",
+    "build": "tsup src/index.ts --format esm,cjs --dts --clean",
+    "lint": "npm run lint:eslint && npm run format:check",
+    "lint:eslint": "eslint . --ext .ts",
+    "format:check": "prettier --check .",
+    "format:write": "prettier --write .",
     "test": "vitest run"
   },

Also applies to: 44-60

packages/utils/package.json (2)

21-23: Raise engines.node to ≥18.

Matches CI/build toolchain and avoids subtle ESM/crypto polyfill differences on older Node.

   "engines": {
-    "node": ">=14.15.0"
+    "node": ">=18.17.0"
   },

Also applies to: 32-50


16-20: Enable ESLint in scripts.

Currently only Prettier runs.

   "scripts": {
-    "build": "tsup src/index.ts --format esm,cjs --dts --clean",
-    "lint": "prettier --write .",
+    "build": "tsup src/index.ts --format esm,cjs --dts --clean",
+    "lint": "npm run lint:eslint && npm run format:check",
+    "lint:eslint": "eslint . --ext .ts",
+    "format:check": "prettier --check .",
+    "format:write": "prettier --write .",
     "test": "vitest run"
   },

Also applies to: 32-50

packages/hw-wallets/package.json (2)

55-74: Ledger lib bumps—please smoke test on devices.

Version bumps can affect tx serialization or app compatibility. Validate ETH EIP-712, SOL derivation, and BTC segwit signing on real devices before release.


21-23: Update engines and add ESLint script.

Same rationale as other packages.

   "engines": {
-    "node": ">=14.15.0"
+    "node": ">=18.17.0"
   },
   "scripts": {
-    "build": "tsup src/index.ts --format esm,cjs --dts --clean",
-    "lint": "prettier --write .",
+    "build": "tsup src/index.ts --format esm,cjs --dts --clean",
+    "lint": "npm run lint:eslint && npm run format:check",
+    "lint:eslint": "eslint . --ext .ts",
+    "format:check": "prettier --check .",
+    "format:write": "prettier --write .",
     "test": "vitest run"
   },

Also applies to: 24-41

packages/swap/src/utils/abi/wrapper.ts (2)

1-1: Export a named ABI and freeze literal types for better tooling.

Exporting a named const and marking the array as const improves type inference (ethers/viem) and prevents accidental mutation.

-export default [
+export const WRAPPED_ABI = [
 ...
-];
+ ] as const;
+
+export default WRAPPED_ABI;

Also applies to: 153-153


114-114: Consider removing the legacy 'fallback' entry if unused.

Some tooling ignores/complains about ABI entries with type 'fallback'. If you don’t rely on it, safe to drop to reduce noise.

packages/extension/configs/vitest.config.mts (1)

20-30: Safer path conversion for customResolver (Windows-friendly).

Replacing the file:// prefix may mis-handle Windows paths. Use fileURLToPath for robust conversion.

-import { defineConfig } from 'vitest/config';
+import { defineConfig } from 'vitest/config';
+import { fileURLToPath } from 'node:url';
@@
-        customResolver(source) {
-          return import.meta.resolve(source).replace(/^file:\/\//, '');
+        customResolver(source) {
+          return fileURLToPath(new URL(import.meta.resolve(source)));
         },
packages/name-resolution/src/index.ts (3)

27-28: Avoid commented-out init; gate SID behind a feature flag and exclude from initDone.

Right now SID is still constructed but never initialized/used, adding dead weight and potential side effects. Prefer a boolean flag (e.g., enableSID) to conditionally construct/init and keep initDone strictly to active resolvers.

Example (outside this hunk):

// constructor
this.sid = options.sid && options.sid.enabled ? new SIDResolver(options.sid) : undefined;
const inits = [this.ens.init(), this.rns.init(), this.ud.init()];
this.initDone = Promise.all(inits);

35-36: Remove stale SID path from reverse resolution or guard it.

Leaving the call commented invites drift. If SID is togglable, wrap with a runtime check instead of comments.

-        // this.sid.resolveReverseName(address),
+        ...(this.sid ? [this.sid.resolveReverseName(address)] : []),

51-60: Signature rename is fine; remove commented SID branches to avoid paymentIdChain drift.
_paymentIdChain rename is OK. Remove the commented SID lines in packages/name-resolution/src/index.ts (// this.sid.init(), // this.sid.resolveReverseName(...), and the commented resolveAddress branch) — SID and types still reference paymentIdChain in packages/name-resolution/src/sid/index.ts and packages/name-resolution/src/types.ts, so the comments will drift.

packages/name-resolution/tests/resolver.test.ts (1)

23-25: Align test setup with disabled SID.

Since you expect spaceid.arb to resolve to null, also drop the SID config from the resolver options to avoid implying SID is used.

Example (outside this hunk):

const resolver = new NameResolver({ ens: { node: "https://nodes.mewapi.io/rpc/eth" } });
packages/name-resolution/tests/sid.test.ts (1)

4-4: Add a reason/comment for skipped suite and a tracking ticket.

Skipping is fine, but please annotate why and when to re-enable (e.g., link to issue).

packages/swap/src/types/index.ts (1)

239-243: RFQOptions as any makes downstream brittle.

Define a minimal shape (e.g., maker, taker, expiry, salt, chainId, permit, etc.) to prevent misuse and enable validation. Keep an escape hatch via index signature if needed.

export interface RFQOptions {
  maker: string;
  taker: string;
  expiry: string; // unix sec
  chainId: number;
  order: unknown; // provider-specific signed order blob
  signatures?: string[];
  [key: string]: unknown;
}
packages/swap/src/utils/approvals.ts (1)

108-116: Guard against native token to avoid bogus allowance calls.

If callers ever pass the native token address by mistake, this will try to call allowance on a non-ERC20. Add a short-circuit.

Apply:

- import { GAS_LIMITS } from "../configs";
+ import { GAS_LIMITS, NATIVE_TOKEN_ADDRESS } from "../configs";
@@
 const getAllowanceTransactions = async (options: {
   fromToken: { address: string };
@@
 }): Promise<EVMTransaction[]> => {
   const transactions: EVMTransaction[] = [];
+  // Native token doesn't require approvals
+  if (options.fromToken.address === NATIVE_TOKEN_ADDRESS) return transactions;
packages/signers/polkadot/package.json (1)

21-30: Move commit tooling to dev and align Node engine with toolchain.

  • @commitlint/cli should be a devDependency.
  • eslint 9/ts 5.9 generally require Node >=18.18. Align engines.node to avoid installs on unsupported Node.

Apply:

   "engines": {
-    "node": ">=14.15.0"
+    "node": ">=18.18.0"
   },
@@
   "dependencies": {
-    "@commitlint/cli": "^19.8.1",
     "@enkryptcom/utils": "workspace:^",
@@
   "devDependencies": {
+    "@commitlint/cli": "^19.8.1",
packages/extension/package.json (1)

25-90: Avoid shipping yarn as a runtime dep.

"yarn" should be a devDependency (or a root packageManager field). Keeping it in deps bloats installs.

   "dependencies": {
@@
-    "yarn": "^1.22.22",
@@
   },
   "devDependencies": {
@@
+    "yarn": "^1.22.22",
packages/swap/tests/swap.test.ts (2)

80-95: Assert existence and fix typo for 1inch Fusion quote var.

Prevent undefined access and improve naming.

-      const oneInchFusionQuote = quotes.find(
-        (q) => q.provider === ProviderName.oneInchFusion,
-      );
+      const oneInchFusionQuote = quotes.find(
+        (q) => q.provider === ProviderName.oneInchFusion,
+      );
+      expect(oneInchFusionQuote, "Missing 1inch Fusion quote").to.exist;
@@
-      const swapOneInch = await enkryptSwap.getSwap(oneInceQuote!.quote);
+      const swapOneInch = await enkryptSwap.getSwap(oneInchQuote!.quote);

117-137: Repeat existence assert and fix variable typo in second case.

-      const oneInceQuote = quotes.find(
+      const oneInchQuote = quotes.find(
         (q) => q.provider === ProviderName.oneInch,
       );
@@
-      const oneInchFusionQuote = quotes.find(
+      const oneInchFusionQuote = quotes.find(
         (q) => q.provider === ProviderName.oneInchFusion,
       );
+      expect(oneInchFusionQuote, "Missing 1inch Fusion quote").to.exist;
@@
-      expect(oneInceQuote!.provider).to.be.eq(ProviderName.oneInch);
+      expect(oneInchQuote!.provider).to.be.eq(ProviderName.oneInch);
packages/extension/src/ui/action/views/swap/index.vue (1)

841-847: Make RFQ options fetching resilient.

If one RFQ provider errors, don’t fail the whole flow—use allSettled.

-  const tradesRfqOptions = rfqTrades.map(t => t!.getRFQObject!());
+  const tradesRfqOptions = rfqTrades.map(t => t!.getRFQObject!());
   const statusObjects = await Promise.all(tradeStatusOptions);
-  const rfqOptionObjects = await Promise.all(tradesRfqOptions);
+  const rfqOptionResults = await Promise.allSettled(tradesRfqOptions);
   trades.forEach((t, idx) => (t!.status = statusObjects[idx]));
-  rfqTrades.forEach((t, idx) => (t!.rfqOptions = rfqOptionObjects[idx]));
+  rfqTrades.forEach((t, idx) => {
+    const r = rfqOptionResults[idx];
+    if (r.status === "fulfilled") t!.rfqOptions = r.value;
+  });
packages/swap/src/providers/paraswap/index.ts (1)

314-336: Add type on quote for consistency with swap responses.

Several providers tag swap responses with SwapType; mirroring that on quotes helps downstream logic stay uniform.

         const response: ProviderQuoteResponse = {
           fromTokenAmount: toBN(res.srcAmount),
           toTokenAmount: toBN(res.destAmount),
           additionalNativeFees: toBN(0),
           provider: this.name,
+          type: SwapType.regular,
           quote: {
             meta: {
               ...meta,
               priceRoute: res,
             },
             options,
             provider: this.name,
           },
packages/extension/src/providers/ethereum/networks/zksepolia.ts (1)

6-9: Rename zkgoerli -> zksepolia in zksepolia.ts

Replace zkgoerliOptions/zkgoerli/default export with zksepoliaOptions/zksepolia (file: packages/extension/src/providers/ethereum/networks/zksepolia.ts — lines ~6,21,23). index.ts import (packages/extension/src/providers/ethereum/networks/index.ts:17) already uses zkSepoliaNode and needs no change.

-const zkgoerliOptions: EvmNetworkOptions = {
+const zksepoliaOptions: EvmNetworkOptions = {
@@
-const zkgoerli = new EvmNetwork(zkgoerliOptions);
+const zksepolia = new EvmNetwork(zksepoliaOptions);
 
-export default zkgoerli;
+export default zksepolia;
packages/swap/src/providers/oneInch/index.ts (1)

39-82: Exporting supportedNetworks is fine; consider freezing to avoid accidental mutation.

Minor: prevent external mutation with Object.freeze or mark the shape readonly.

Example:

-export const supportedNetworks: {
+export const supportedNetworks: Readonly<{
   [key in SupportedNetworkName]?: { approvalAddress: string; chainId: string };
-} = {
+}> = Object.freeze({
   ...
-};
+});
packages/extension/src/ui/action/views/swap/views/swap-best-offer/index.vue (1)

267-267: Remove console logging or gate behind a debug flag.

UI logs leak into production console. Strip or guard them.

Apply:

-  console.log(trade);
...
-  console.log(`Trade ${index + 1}:`, { ... });
...
-          console.log('starting wait');
...
-          console.log('wait done');
...
-          console.log(orderHash);

Also applies to: 326-333, 449-456, 463-463

packages/swap/tests/oneInchFusion.test.ts (2)

82-85: Pad amount to 32 bytes instead of manual zero prefixing.

Manual zeros are brittle. Use 64-nybble padding.

Apply:

-        )}00000000000000000000000000000000000000000000000${numberToHex(
-          amount,
-        ).replace("0x", "")}`,
+        )}${numberToHex(amount).replace("0x", "").padStart(64, "0")}`,

49-57: Optional: Assert RFQ semantics instead of internal counts.

Strengthen tests by asserting RFQ type and approval encoding for tx[0], not the number of txs.

You can add:

expect(swap?.type).to.eq('rfq');
expect((swap?.transactions[0] as EVMTransaction).to).to.eq(fromToken.address);
expect(((swap?.transactions[0] as EVMTransaction).data as string).slice(0, 10)).to.eq('0x095ea7b3'); // approve selector

Also applies to: 76-79

packages/swap/src/providers/oneInchFusion/index.ts (2)

167-176: Strip noisy console logs from provider.

Provider-level logs will spam tests/consumers.

Remove the console.log(...) calls and keep console.error only where actionable, or gate logs behind a debug flag.

Also applies to: 234-236, 315-316


302-311: Status mapping: handle more Fusion statuses explicitly.

Consider mapping Expired, Cancelled, and Unfilled distinctly for better UX/telemetry; PartiallyFilled may be “success” depending on policy.

Example:

if (status.status === OrderStatus.Filled) return TransactionStatus.success;
if (status.status === OrderStatus.PartiallyFilled) return TransactionStatus.success; // or a dedicated status
if (status.status === OrderStatus.Pending) return TransactionStatus.pending;
if (status.status === OrderStatus.Expired || status.status === OrderStatus.Cancelled) return TransactionStatus.failed;
return TransactionStatus.failed;
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9f85baf and ba77b24.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (64)
  • .github/workflows/test-all.yml (1 hunks)
  • .github/workflows/test-swap.yml (1 hunks)
  • .nvmrc (1 hunks)
  • .vscode/settings.json (1 hunks)
  • Dockerfile (1 hunks)
  • package.json (1 hunks)
  • packages/extension-bridge/package.json (2 hunks)
  • packages/extension/configs/vitest.config.mts (1 hunks)
  • packages/extension/package.json (6 hunks)
  • packages/extension/src/providers/common/libs/new-features.ts (1 hunks)
  • packages/extension/src/providers/ethereum/libs/activity-handlers/providers/etherscan/configs.ts (1 hunks)
  • packages/extension/src/providers/ethereum/libs/assets-handlers/assetinfo-mew.ts (1 hunks)
  • packages/extension/src/providers/ethereum/networks/cagaAnkara.ts (0 hunks)
  • packages/extension/src/providers/ethereum/networks/coti-devnet.ts (0 hunks)
  • packages/extension/src/providers/ethereum/networks/coti-testnet.ts (1 hunks)
  • packages/extension/src/providers/ethereum/networks/form-testnet.ts (0 hunks)
  • packages/extension/src/providers/ethereum/networks/form.ts (0 hunks)
  • packages/extension/src/providers/ethereum/networks/index.ts (6 hunks)
  • packages/extension/src/providers/ethereum/networks/skale/chaos.ts (0 hunks)
  • packages/extension/src/providers/ethereum/networks/skale/index.ts (0 hunks)
  • packages/extension/src/providers/ethereum/networks/tac.ts (1 hunks)
  • packages/extension/src/providers/ethereum/networks/zkgoerli.ts (0 hunks)
  • packages/extension/src/providers/ethereum/networks/zksepolia.ts (1 hunks)
  • packages/extension/src/providers/polkadot/networks/index.ts (0 hunks)
  • packages/extension/src/providers/polkadot/networks/unique/opal.ts (0 hunks)
  • packages/extension/src/ui/action/views/swap/index.vue (2 hunks)
  • packages/extension/src/ui/action/views/swap/libs/evm-gasvals.ts (1 hunks)
  • packages/extension/src/ui/action/views/swap/libs/evm-waitreceipt.ts (1 hunks)
  • packages/extension/src/ui/action/views/swap/types.ts (2 hunks)
  • packages/extension/src/ui/action/views/swap/views/swap-best-offer/index.vue (8 hunks)
  • packages/hw-wallets/package.json (3 hunks)
  • packages/keyring/package.json (2 hunks)
  • packages/name-resolution/package.json (3 hunks)
  • packages/name-resolution/src/index.ts (2 hunks)
  • packages/name-resolution/tests/resolver.test.ts (1 hunks)
  • packages/name-resolution/tests/sid.test.ts (1 hunks)
  • packages/request/package.json (2 hunks)
  • packages/signers/bitcoin/package.json (2 hunks)
  • packages/signers/ethereum/package.json (2 hunks)
  • packages/signers/kadena/package.json (2 hunks)
  • packages/signers/polkadot/package.json (2 hunks)
  • packages/signers/polkadot/src/index.ts (1 hunks)
  • packages/storage/package.json (2 hunks)
  • packages/swap/package.json (2 hunks)
  • packages/swap/src/common/estimateGasList.ts (0 hunks)
  • packages/swap/src/configs.ts (2 hunks)
  • packages/swap/src/index.ts (5 hunks)
  • packages/swap/src/providers/changelly/index.ts (2 hunks)
  • packages/swap/src/providers/jupiter/index.ts (2 hunks)
  • packages/swap/src/providers/okx/index.ts (2 hunks)
  • packages/swap/src/providers/oneInch/index.ts (3 hunks)
  • packages/swap/src/providers/oneInchFusion/index.ts (1 hunks)
  • packages/swap/src/providers/oneInchFusion/types.ts (1 hunks)
  • packages/swap/src/providers/paraswap/index.ts (3 hunks)
  • packages/swap/src/providers/rango/index.ts (2 hunks)
  • packages/swap/src/providers/zerox/index.ts (3 hunks)
  • packages/swap/src/types/index.ts (6 hunks)
  • packages/swap/src/utils/abi/wrapper.ts (1 hunks)
  • packages/swap/src/utils/approvals.ts (3 hunks)
  • packages/swap/tests/oneInchFusion.test.ts (1 hunks)
  • packages/swap/tests/swap.test.ts (3 hunks)
  • packages/types/package.json (2 hunks)
  • packages/types/src/networks.ts (3 hunks)
  • packages/utils/package.json (2 hunks)
💤 Files with no reviewable changes (10)
  • packages/extension/src/providers/ethereum/networks/form-testnet.ts
  • packages/extension/src/providers/polkadot/networks/index.ts
  • packages/swap/src/common/estimateGasList.ts
  • packages/extension/src/providers/ethereum/networks/cagaAnkara.ts
  • packages/extension/src/providers/polkadot/networks/unique/opal.ts
  • packages/extension/src/providers/ethereum/networks/zkgoerli.ts
  • packages/extension/src/providers/ethereum/networks/form.ts
  • packages/extension/src/providers/ethereum/networks/skale/index.ts
  • packages/extension/src/providers/ethereum/networks/coti-devnet.ts
  • packages/extension/src/providers/ethereum/networks/skale/chaos.ts
🧰 Additional context used
🧬 Code graph analysis (10)
packages/extension/src/providers/ethereum/networks/coti-testnet.ts (1)
packages/extension/src/providers/ethereum/types/evm-network.ts (2)
  • EvmNetworkOptions (22-53)
  • EvmNetwork (55-286)
packages/swap/src/providers/oneInchFusion/types.ts (1)
packages/swap/src/types/index.ts (2)
  • EVMTransaction (163-170)
  • BN (47-47)
packages/extension/src/providers/ethereum/networks/tac.ts (2)
packages/extension/src/providers/ethereum/types/evm-network.ts (2)
  • EvmNetworkOptions (22-53)
  • EvmNetwork (55-286)
packages/extension/src/providers/ethereum/libs/activity-handlers/index.ts (1)
  • EtherscanActivity (10-10)
packages/extension/src/providers/ethereum/networks/zksepolia.ts (1)
packages/extension/src/providers/ethereum/types/evm-network.ts (2)
  • EvmNetworkOptions (22-53)
  • EvmNetwork (55-286)
packages/extension/src/ui/action/views/swap/types.ts (1)
packages/swap/src/types/index.ts (1)
  • RFQOptionsResponse (254-257)
packages/swap/tests/oneInchFusion.test.ts (4)
packages/swap/src/types/index.ts (1)
  • EVMTransaction (163-170)
packages/swap/src/providers/oneInch/index.ts (1)
  • ONEINCH_APPROVAL_ADDRESS (37-38)
packages/swap/src/utils/approvals.ts (1)
  • TOKEN_AMOUNT_INFINITY_AND_BEYOND (8-9)
packages/utils/src/index.ts (1)
  • numberToHex (46-46)
packages/swap/src/types/index.ts (1)
packages/swap/src/index.ts (1)
  • ProviderSwapResponse (270-270)
packages/swap/src/utils/approvals.ts (3)
packages/swap/src/types/index.ts (2)
  • BN (47-47)
  • EVMTransaction (163-170)
packages/swap/src/configs.ts (1)
  • GAS_LIMITS (143-143)
packages/utils/src/index.ts (1)
  • numberToHex (46-46)
packages/swap/src/index.ts (1)
packages/swap/src/types/index.ts (1)
  • RFQOptionsResponse (254-257)
packages/swap/src/providers/oneInchFusion/index.ts (6)
packages/swap/src/types/index.ts (12)
  • TokenType (49-60)
  • MinMaxResponse (205-210)
  • getQuoteOptions (143-149)
  • QuoteMetaOptions (107-114)
  • EVMTransaction (163-170)
  • ProviderQuoteResponse (218-230)
  • SwapQuote (212-216)
  • ProviderSwapResponse (259-276)
  • RFQOptionsResponse (254-257)
  • StatusOptions (244-247)
  • StatusOptionsResponse (249-252)
  • RFQOptions (239-242)
packages/swap/src/providers/oneInch/index.ts (1)
  • supportedNetworks (39-82)
packages/swap/src/utils/common.ts (1)
  • isEVMAddress (13-19)
packages/swap/src/utils/approvals.ts (4)
  • TOKEN_AMOUNT_INFINITY_AND_BEYOND (8-9)
  • getAllowanceTransactions (171-171)
  • isSufficientWrappedAvailable (174-174)
  • getNativeWrapTx (173-173)
packages/swap/src/providers/oneInchFusion/types.ts (1)
  • OneInchSwapResponse (3-12)
packages/swap/src/configs.ts (3)
  • NATIVE_TOKEN_ADDRESS (144-144)
  • FEE_CONFIGS (142-142)
  • DEFAULT_SLIPPAGE (148-148)
🪛 GitHub Check: test
packages/swap/tests/oneInchFusion.test.ts

[failure] 77-77: tests/oneInchFusion.test.ts > OneInchFusion Provider > it should return a quote non infinity approval
AssertionError: expected 1 to equal 2

  • Expected
  • Received
  • 2
  • 1

❯ tests/oneInchFusion.test.ts:77:47


[failure] 50-50: tests/oneInchFusion.test.ts > OneInchFusion Provider > it should return a quote infinity approval
AssertionError: expected 1 to equal 2

  • Expected
  • Received
  • 2
  • 1

❯ tests/oneInchFusion.test.ts:50:47

🪛 GitHub Actions: Test all swap providers
packages/swap/tests/oneInchFusion.test.ts

[error] 50-50: Step: 'cd packages/swap && yarn test' - OneInchFusion: test 'should return a quote infinity approval' failed. AssertionError: expected 1 to equal 2.


[error] 77-77: Step: 'cd packages/swap && yarn test' - OneInchFusion: test 'should return a quote non infinity approval' failed. AssertionError: expected 1 to equal 2.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: buildAll
🔇 Additional comments (39)
.nvmrc (1)

1-1: Node bump confirmed in .nvmrc — CI/Docker alignment unverified

  • .nvmrc => v22.18.0 (confirmed).
  • package.json engines in packages/* are set to >=14.15.0 (e.g., packages/hw-wallets, keyring, name-resolution, request, signers/*, storage, swap, types, utils) — not pinned to Node 22.
  • Automated search couldn't locate/verify GitHub Actions workflows or Dockerfile FROM pins (ripgrep skipped files). Ensure actions/setup-node node-version and Docker FROM node:22.18.0 are updated so CI and Docker remain in lockstep.
package.json (1)

37-38: Dev tool bumps LGTM.

No API surface impact; SWC/concurrently updates align with Node 22.

packages/extension/src/providers/ethereum/libs/assets-handlers/assetinfo-mew.ts (1)

145-149: No change required — Blockscout path already includes native token

getBlockscoutBalances builds a nativeBalance (NATIVE_TOKEN_ADDRESS) and prepends it to token results, and its catch returns a native fallback ('0x0'), so the proposed guard is redundant (see packages/extension/src/providers/ethereum/libs/assets-handlers/blockscout.ts — native mapping ~lines 47–51 and fallback ~lines 81–85).

.vscode/settings.json (1)

12-13: Editor settings LGTM.

Prettier as default formatter and disabled inline suggestions are fine for team consistency.

packages/keyring/package.json (1)

32-32: Unify @polkadot/util across packages and update lockfile

  • packages/extension/package.json, packages/hw-wallets/package.json, packages/keyring/package.json, packages/signers/polkadot/package.json all declare "@polkadot/util": "^13.5.6".
  • yarn.lock contains both 12.6.2 and 13.5.6 entries — run yarn install/upgrade (or yarn dedupe && yarn install) to ensure a single resolved version and commit the updated lockfile.
packages/name-resolution/package.json (2)

25-28: Tooling bumps look good

No issues spotted with the TS/ESLint/viem bumps for dev-time usage.

Also applies to: 38-41


50-52: Confirm runtime dependency placement for @bonfida/spl-name-service and @ensdomains/address-encoder — OK

Both packages are listed under "dependencies" in packages/name-resolution/package.json; a scan of packages/name-resolution/src found no imports/requires of "viem".

packages/swap/package.json (1)

24-42: Keep @1inch/limit-order-sdk — it's required.

packages/swap/src/providers/oneInchFusion/index.ts imports Bps from @1inch/limit-order-sdk (line 11) and uses new Bps(BigInt(...)) and Bps.fromPercent(100) when building quoteParams.integratorFee (lines 151–152).

packages/types/src/networks.ts (1)

31-31: Enum rename verified — downstream references updated; no stale names found.

New entries exist in packages/types/src/networks.ts and are referenced in:

  • packages/extension/src/providers/ethereum/networks/zksepolia.ts (NetworkNames.zkSyncSepolia)
  • packages/extension/src/providers/ethereum/networks/coti-testnet.ts (NetworkNames.CotiTestnet)
  • packages/extension/src/providers/ethereum/networks/tac.ts and packages/extension/src/providers/common/libs/new-features.ts (NetworkNames.TAC)
  • activity-handlers etherscan configs reference TAC as well.

Search returned no matches for zkSyncGoerli or CotiDevnet.

packages/extension/src/providers/common/libs/new-features.ts (1)

3-3: LGTM: feature flag updated to TAC.

packages/extension/src/providers/ethereum/networks/tac.ts (1)

7-21: Set coingeckoPlatform or harden EvmNetwork; EtherscanActivity OK.

  • explorer.tac.build is a Blockscout instance and exposes an Etherscan‑compatible /api — EtherscanActivity should work.
  • CoinGecko id "tac" exists; CoinGecko shows chain/ecosystem per asset rather than a single TAC platform id.
  • Action (pick one): A) If CoingeckoPlatform has a matching value, add coingeckoPlatform to tacOptions. B) Preferable — remove the non‑null assertion in EvmNetwork and add runtime guards/fallbacks so missing coingeckoPlatform does not throw when users add custom tokens.
  • File: packages/extension/src/providers/ethereum/networks/tac.ts (lines 7–21).
packages/swap/src/types/index.ts (4)

126-133: Add ProviderName.oneInchFusion — looks good.


321-323: Abstract ProviderWithRFQ is fine; ensure Fusion provider extends it.


158-161: SwapType set on all provider getSwap responses — resolved.

Verified provider getSwap implementations (oneInch, oneInchFusion, paraswap, zerox, okx, rango, jupiter, changelly) each return type: SwapType.regular or SwapType.rfq.


263-276: typedMessages / getRFQObject — document format and lifecycle

  • Document typedMessages: specify exact format (array of EVM typed-message payloads — e.g. JSON EIP‑712 typed-data strings), signing order/expectations and an example in packages/swap/src/types/index.ts (JSDoc or README).
  • Require/getRFQObject: guarantee idempotence and that returned RFQ options are stable/cacheable between quote and submit (UI calls it at quote time and reuses the result); update provider implementations if they return ephemeral data.

Used by: packages/extension/src/ui/action/views/swap/index.vue (getRFQObject usage) and packages/extension/src/ui/action/views/swap/views/swap-best-offer/index.vue (typedMessages → EvmTypedMessageSigner).

packages/swap/src/utils/approvals.ts (3)

70-85: Wrap balance check looks correct.

Using wrapper’s balanceOf + BN.gte is appropriate. No issues spotted.


87-102: Native wrap tx builder LGTM.

deposit() encoding + hex-encoded value and a fixed gasLimit is fine, assuming GAS_LIMITS.Wrap exists and is hex.


109-109: Signature change ripple check.

approvals.ts now expects:

  fromToken: { address: string };

Confirm every getAllowanceTransactions call passes a fromToken object with an address property. Call sites to check:

  • packages/swap/src/providers/oneInchFusion/index.ts:177
  • packages/swap/src/providers/zerox/index.ts:184
  • packages/swap/src/providers/paraswap/index.ts:208, 304
  • packages/swap/src/providers/oneInch/index.ts:194

Acceptable shapes: fromToken: options.fromToken or fromToken: { address: options.fromToken.address }.

packages/swap/src/providers/rango/index.ts (1)

1187-1192: Swap type tagging LGTM.

Explicitly marking Rango swaps as regular is correct.

packages/swap/src/providers/paraswap/index.ts (1)

286-299: Graceful error handling on missing priceRoute looks good.

Returning null instead of throwing avoids cascading failures. Thanks for the hardening.

packages/swap/src/providers/okx/index.ts (2)

37-38: LGTM: SwapType correctly wired into OKX provider.

Importing SwapType aligns the provider with the new unified swap response shape.


425-426: LGTM: Response annotated with SwapType.regular.

Consistent with other providers and the updated public types.

packages/swap/src/providers/changelly/index.ts (2)

34-35: LGTM: SwapType import added.


992-996: LGTM: SwapType.regular attached to swap response.

packages/swap/src/providers/zerox/index.ts (2)

178-179: LGTM: Stricter error guard for ZeroX response.

Returning null when transaction is missing avoids downstream NPEs.


262-263: LGTM: SwapType.regular included in response.

packages/swap/src/providers/jupiter/index.ts (1)

45-45: LGTM: SwapType wired (import + response).

Also applies to: 511-512

packages/swap/src/providers/oneInchFusion/types.ts (1)

1-12: LGTM: RFQ swap response shape looks sound.

Fields align with EVMTransaction and BN usage across the codebase.

packages/swap/src/index.ts (4)

7-7: LGTM: OneInchFusion provider import added.


39-41: LGTM: RFQ types wired into public surface.


279-280: LGTM: ToTokenType now exported from module.


133-138: Confirm provider precedence after inserting OneInchFusion.

Verified in packages/swap/src/index.ts: fromTokens are merged via [...this.providers].reverse() + Object.assign (merge at ~lines 146–147), so earlier entries in the providers array win. With OneInchFusion placed before Fusion (providers array ~lines 133–138), OneInchFusion will override Fusion on token key collisions — confirm this ordering is intended; if not, swap their order or adjust the merge logic.

packages/swap/src/providers/oneInch/index.ts (1)

18-19: LGTM: Tagging swap responses with SwapType.regular.

packages/extension/src/providers/ethereum/networks/index.ts (5)

17-17: LGTM: zkSepolia import added.


98-99: LGTM: zkGoerli → zkSepolia mapping updated.


58-59: LGTM: coti-testnet import added.


78-79: LGTM: TAC network imported.


165-166: LGTM: TAC network exported.

packages/extension/src/ui/action/views/swap/views/swap-best-offer/index.vue (1)

163-165: Avoid deep imports — import types from the package entrypoint or re-export them.

Deep import '@enkryptcom/swap/src/types' is fragile; replace with the package root and, if needed, add re-exports in @enkryptcom/swap. Occurrences to fix: packages/extension/src/ui/action/views/swap/views/swap-best-offer/index.vue (ln 163), packages/extension/src/ui/action/views/swap/index.vue (ln 171), packages/extension/src/ui/action/views/swap/types.ts (ln 13).

-import { SwapType, WalletIdentifier } from '@enkryptcom/swap/src/types';
+import { SwapType, WalletIdentifier } from '@enkryptcom/swap';

If these types aren't exported from the package entrypoint, re-export SwapType and WalletIdentifier from @enkryptcom/swap.

Comment on lines 9 to 10
include: ['crypto'],
}),
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Polyfills trimmed to ['crypto']—double-check Buffer/process use in tests.

If any tests use Buffer/process, they’ll now fail under jsdom.


🏁 Script executed:

#!/bin/bash
# Scan extension code/tests for Buffer or process usage that may need polyfills
rg -nP -C2 '\b(Buffer|process)\b' packages/extension/src packages/extension/tests || true

Length of output: 60719


Restore Buffer/process polyfills or refactor — Buffer is used widely in extension src

  • Search found many Buffer usages under packages/extension/src (representative hits):
    • packages/extension/src/ui/action/views/swap/index.vue:869 (Buffer.from(JSON.stringify(...))).
    • packages/extension/src/ui/action/views/swap/libs/send-transactions.ts:196, 288, 306, 384 (Buffer.from for txs/signatures).
    • packages/extension/src/ui/action/views/import-account/views/import-account-password.vue:85-86 (Buffer.from(privKey,'hex')).
    • packages/extension/src/providers/solana/ui/libs/signin-message.ts:50-56 (Buffer.concat / Buffer.from).
    • packages/extension/src/providers/bitcoin/libs/sign-message-utils.ts:3-11 (Buffer.alloc/Buffer.concat/Buffer.read/write).
    • packages/extension/src/providers/polkadot/libs/blockies.ts:22-23 (Buffer.from(...).toString('base64')).
  • Action: revert vitest.config.mts change (packages/extension/configs/vitest.config.mts — include Buffer/process polyfills, e.g., add 'buffer' and 'process') or update all tests/code to avoid Buffer/process; otherwise tests running under jsdom will break.
🤖 Prompt for AI Agents
In packages/extension/configs/vitest.config.mts around lines 9-10, the config
removed polyfills for Buffer/process causing many Buffer usages in
packages/extension/src to break under jsdom; restore the polyfills by reverting
the change or adding back 'buffer' and 'process' to the include/polyfill list
(or ensure the vitest setup injects Buffer and process shims before tests run),
then run the extension test suite to verify all Buffer-based usages pass.

Comment on lines 71 to 72
[NetworkNames.TAC]: 'https://explorer.tac.build/',
};
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify TAC explorer compatibility with this handler

This map mixes Etherscan- and Blockscout-style endpoints. Confirm https://explorer.tac.build/ exposes the API shape your handler expects (e.g., /api?module=account... or Blockscout equivalents), and whether a trailing /api should be used.

Optionally validate:

If the API path differs, add a per-network override or adjust the endpoint accordingly.


🏁 Script executed:

#!/bin/bash
base="https://explorer.tac.build"
# Basic reachability
curl -sI "$base" | head -n1
# Probe common API patterns (may 404 if different—adjust accordingly)
curl -s "$base/api?module=block&action=eth_block_number" | head -c 200; echo
curl -s "$base/api/v2/stats" | head -c 200; echo

Length of output: 261


Use Blockscout v2 for TAC or adapt the handler

Probed endpoints show /api returns JSON‑RPC (eth_blockNumber) and /api/v2 returns Blockscout v2 JSON (e.g., /api/v2/stats) — the explorer does not expose Etherscan "module=..." responses. Update packages/extension/src/providers/ethereum/libs/activity-handlers/providers/etherscan/configs.ts (lines 71–72) to use "https://explorer.tac.build/api/v2" or add a per-network override and change the handler to call Blockscout API shapes.

Comment on lines 144 to 145
cotiTestnetNode: cotiTestnetNode,
hoodi: hoodiNode,
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Fix key name for COTI testnet export.

Key should be cotiTestnet to match naming convention and consumers. Using cotiTestnetNode as the key is likely a breaking typo.

Apply:

-  cotiTestnetNode: cotiTestnetNode,
+  cotiTestnet: cotiTestnetNode,

🏁 Script executed:

#!/bin/bash
# Verify consumers expect `cotiTestnet`, not `cotiTestnetNode`
rg -n "cotiTestnet(Node)?" packages/extension -C2

Length of output: 1949


Fix export key: use cotiTestnet (not cotiTestnetNode)

Key should match other network keys and the exported default (packages/extension/src/providers/ethereum/networks/coti-testnet.ts). Apply:

-  cotiTestnetNode: cotiTestnetNode,
+  cotiTestnet: cotiTestnetNode,
📝 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
cotiTestnetNode: cotiTestnetNode,
hoodi: hoodiNode,
cotiTestnet: cotiTestnetNode,
hoodi: hoodiNode,
🤖 Prompt for AI Agents
packages/extension/src/providers/ethereum/networks/index.ts around lines
144-145: the exported object uses the key "cotiTestnetNode" but should use
"cotiTestnet" to match the other network keys and the default export in
packages/extension/src/providers/ethereum/networks/coti-testnet.ts; rename the
key from cotiTestnetNode to cotiTestnet while keeping the value reference
(cotiTestnetNode) unchanged so other code continues to import by the
standardized key.

Comment on lines +171 to 172
import { SwapType } from '@enkryptcom/swap/src/types';

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Avoid deep import of SwapType.

Prefer importing from '@enkryptcom/swap' once it re-exports SwapType.

-import { SwapType } from '@enkryptcom/swap/src/types';
+import { SwapType } from '@enkryptcom/swap';
📝 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
import { SwapType } from '@enkryptcom/swap/src/types';
import { SwapType } from '@enkryptcom/swap';
🤖 Prompt for AI Agents
In packages/extension/src/ui/action/views/swap/index.vue around lines 171 to
172, the file currently deep-imports SwapType from '@enkryptcom/swap/src/types';
replace that deep import with a top-level import from '@enkryptcom/swap' (i.e.
import { SwapType } from '@enkryptcom/swap') once the package re-exports it,
update any import references accordingly, and run type-check/build to ensure the
alias resolves and no other files rely on the deep path.

Copy link

@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: 3

♻️ Duplicate comments (2)
packages/swap/src/providers/oneInchFusion/index.ts (2)

256-261: Guard gasLimit when summing totalGaslimit (duplicate from prior review).

gasLimit can be undefined in quote path; toBN(undefined) throws.

-        totalGaslimit: res.transactions.reduce(
-          (total: number, curVal: EVMTransaction) =>
-            total + toBN(curVal.gasLimit).toNumber(),
-          0,
-        ),
+        totalGaslimit: res.transactions.reduce((total: number, curVal: EVMTransaction) => {
+          const gl = curVal.gasLimit ?? "0";
+          return total + toBN(gl).toNumber();
+        }, 0),

74-92: init(): return type mismatch with implementation (duplicate from prior review).

The method is declared Promise but is synchronous and never returns a Promise. Make it async (preferred) or change return type to void.

-  init(tokenList: TokenType[]): Promise<void> {
+  async init(tokenList: TokenType[]): Promise<void> {
     if (!OneInchFusion.isSupported(this.network)) return;
     this.fusionSdk = new FusionSDK({
       network: Number(supportedNetworks[this.network].chainId),
       url: "https://fusion.1inch.io",
     });
     tokenList.forEach((t) => {
       this.fromTokens[t.address] = t;
       if (!this.toTokens[this.network]) this.toTokens[this.network] = {};
       this.toTokens[this.network][t.address] = {
         ...t,
         networkInfo: {
           name: this.network,
           isAddress: (address: string) =>
             Promise.resolve(isEVMAddress(address)),
         },
       };
     });
   }
🧹 Nitpick comments (6)
packages/swap/src/providers/oneInchFusion/index.ts (6)

74-92: Persist the provided tokenList.

You have a tokenList field, but init() never assigns it.

   async init(tokenList: TokenType[]): Promise<void> {
     if (!OneInchFusion.isSupported(this.network)) return;
+    this.tokenList = tokenList;
     this.fusionSdk = new FusionSDK({
       network: Number(supportedNetworks[this.network].chainId),
       url: "https://fusion.1inch.io",
     });

117-129: Guard against uninitialized fusionSdk.

If init() wasn’t called (or early-returned for unsupported), this.fusionSdk is undefined and calls below will throw.

   private getOneInchSwap(
     options: getQuoteOptions,
     meta: QuoteMetaOptions,
     accurateEstimate: boolean,
   ): Promise<OneInchSwapResponse | null> {
+    if (!this.fusionSdk) return Promise.resolve(null);

207-218: Safer gas-limit application; handle type/length mismatches.

estimateEVMGasList.result may be shorter or contain non-strings. Current code blindly indexes and assigns.

           if (accurateGasEstimate) {
             if (accurateGasEstimate.isError) return null;
-            transactions.forEach((tx, idx) => {
-              tx.gasLimit = accurateGasEstimate.result[idx];
-            });
+            transactions.forEach((tx, idx) => {
+              const gl = accurateGasEstimate.result[idx];
+              if (!gl) return;
+              tx.gasLimit = typeof gl === "string" ? gl : String(gl);
+            });
           }

318-326: Harden submitRFQOrder parsing and error handling.

JSON.parse on orderStruct can throw; add validation and clearer errors.

-    const relayRequest = RelayerRequest.new({
-      order: JSON.parse((options as any).orderStruct),
+    let orderObj;
+    try {
+      orderObj = JSON.parse((options as any).orderStruct);
+    } catch {
+      throw new Error("OneInchFusion: Invalid orderStruct JSON");
+    }
+    const relayRequest = RelayerRequest.new({
+      order: orderObj,
       extension: (options as any).extension,
       quoteId: (options as any).quoteId,
       signature: options.signatures[0],
     });

233-237: Replace generic console.error with structured logging or remove.

"herere" is not actionable; prefer a scoped logger with error context or surface the error to caller.

-      .catch((e) => {
-        console.error(e, "herere");
-        return null;
-      });
+      .catch(() => null);

108-115: Action: Clarify/adjust min order handling — don’t treat 1 wei as a guaranteed usable minimum.

File: packages/swap/src/providers/oneInchFusion/index.ts (lines 108–115)

  • Fusion/RFQ has no protocol‑enforced per‑chain minimum (on‑chain limit = token integer unit/decimals), but resolvers/quoter/market‑makers often refuse to quote or fill very small orders.
  • Recommend: compute a practical min from token decimals or query the Quoter/resolvers to determine a user‑facing minimum; add handling for quoter failures (e.g., 400 / inability to quote) and surface a clear UX message instead of silently accepting 1 wei.
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ba77b24 and 2dd68bf.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (3)
  • packages/swap/package.json (1 hunks)
  • packages/swap/src/configs.ts (2 hunks)
  • packages/swap/src/providers/oneInchFusion/index.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/swap/src/configs.ts
  • packages/swap/package.json
🧰 Additional context used
🧬 Code graph analysis (1)
packages/swap/src/providers/oneInchFusion/index.ts (6)
packages/swap/src/types/index.ts (12)
  • TokenType (49-60)
  • MinMaxResponse (205-210)
  • getQuoteOptions (143-149)
  • QuoteMetaOptions (107-114)
  • EVMTransaction (163-170)
  • ProviderQuoteResponse (218-230)
  • SwapQuote (212-216)
  • ProviderSwapResponse (259-276)
  • RFQOptionsResponse (254-257)
  • StatusOptions (244-247)
  • StatusOptionsResponse (249-252)
  • RFQOptions (239-242)
packages/swap/src/providers/oneInch/index.ts (1)
  • supportedNetworks (39-82)
packages/swap/src/utils/common.ts (1)
  • isEVMAddress (13-19)
packages/swap/src/utils/approvals.ts (4)
  • TOKEN_AMOUNT_INFINITY_AND_BEYOND (8-9)
  • getAllowanceTransactions (171-171)
  • isSufficientWrappedAvailable (174-174)
  • getNativeWrapTx (173-173)
packages/swap/src/providers/oneInchFusion/types.ts (1)
  • OneInchSwapResponse (3-12)
packages/swap/src/configs.ts (3)
  • NATIVE_TOKEN_ADDRESS (144-144)
  • FEE_CONFIGS (142-142)
  • DEFAULT_SLIPPAGE (148-148)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: buildAll
  • GitHub Check: test
  • GitHub Check: test

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (2)
packages/extension/src/ui/action/views/swap/views/swap-best-offer/index.vue (2)

434-450: Do not JSON.parse the signature; use the hex string directly.

EvmTypedMessageSigner returns a hex string. Parsing can throw.

-        const typedMessageSigs: string[] = [];
+        const typedMessageSigs: string[] = [];
+        let rfqOrderHash: string | undefined;
 ...
-            if (sig.error) return Promise.reject(sig.error);
-            typedMessageSigs.push(JSON.parse(sig.result!));
+            if (sig.error) return Promise.reject(sig.error);
+            typedMessageSigs.push(sig.result as string);

460-466: Use the returned RFQ orderHash and guard rfqOptions access.

Avoid non‑null assertions; capture and use the actual hash returned by submitRFQOrder for activity logging. Optionally hydrate rfqOptions.

-            const orderHash = await swap.value!.submitRFQOrder({
+            rfqOrderHash = await swap.value!.submitRFQOrder({
               options: {
-                ...pickedTrade.value.rfqOptions!.options,
+                ...(pickedTrade.value.rfqOptions?.options || {}),
                 signatures: typedMessageSigs,
               },
-              provider: pickedTrade.value.rfqOptions!.provider,
+              provider: pickedTrade.value.rfqOptions?.provider || pickedTrade.value.provider,
             });
-            console.log(orderHash);
+            // Optional: hydrate for downstream consumers
+            pickedTrade.value.rfqOptions = {
+              provider: pickedTrade.value.provider,
+              options: {
+                ...(pickedTrade.value.rfqOptions?.options || {}),
+                orderHash: rfqOrderHash!,
+              },
+            } as any;
...
-          transactionHash: `${pickedTrade.value.type === SwapType.regular ? txs[0].hash : pickedTrade.value.rfqOptions!.options.orderHash}-swap`,
+          transactionHash: `${
+            pickedTrade.value.type === SwapType.regular
+              ? txs[0].hash
+              : (rfqOrderHash || pickedTrade.value.rfqOptions?.options.orderHash)
+          }-swap`,

Also applies to: 499-499

🧹 Nitpick comments (5)
packages/extension/src/ui/action/views/swap-initiated/index.vue (2)

27-33: Polish copy; add a11y live region.

Minor grammar fix and make the status update screen‑reader friendly.

-              <p v-if="waitingToBeMined">
-                Waiting for Transactions to be mined, this can take upto 30
-                seconds
+              <p v-if="waitingToBeMined" aria-live="polite">
+                Waiting for transactions to be mined. This can take up to ~30 seconds.
               </p>

98-101: Default the new prop to avoid regressions where it isn’t passed.

Make the prop optional with a sane default to prevent runtime “missing required prop” in other call sites.

 interface IProps {
   ...
-  waitingToBeMined: boolean;
+  waitingToBeMined?: boolean;
   ...
 }
 
-defineProps<IProps>();
+const props = withDefaults(defineProps<IProps>(), {
+  waitingToBeMined: false,
+});

Also applies to: 108-114

packages/extension/src/ui/action/views/swap/views/swap-best-offer/index.vue (3)

269-269: Remove leftover debug log.

Console noise in hot paths hurts UX and privacy.

-  console.log(trade);

410-411: Guard optional transactions to avoid NPE.

If transactions is undefined, .length throws.

-    (gasTier.nativeValue === '0' && pickedTrade.value.transactions.length)
+    (gasTier.nativeValue === '0' && (pickedTrade.value.transactions?.length ?? 0))

453-461: Trim noisy logs; rethrow original error.

Drop debug prints and avoid wrapping errors with new Error(e) which loses stack/context.

-            console.log('starting wait');
             await waitForReceipt(
               txs.map(tx => tx.hash),
               network.value!,
               30,
             );
-            console.log('wait done');
 ...
-          } catch (e: any) {
-            throw new Error(e);
+          } catch (e: any) {
+            throw e;
           } finally {

Also applies to: 469-471

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2dd68bf and 3170c85.

📒 Files selected for processing (2)
  • packages/extension/src/ui/action/views/swap-initiated/index.vue (2 hunks)
  • packages/extension/src/ui/action/views/swap/views/swap-best-offer/index.vue (9 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: buildAll
  • GitHub Check: test
  • GitHub Check: test
🔇 Additional comments (4)
packages/extension/src/ui/action/views/swap/views/swap-best-offer/index.vue (4)

96-99: Prop wiring LGTM.

Passing waiting‑to‑be‑mined through to SwapInitiated looks correct.


216-218: State additions LGTM.

Separate refs for waitingToBeMined and swap are clear.


319-326: Confirm Swap API initialization; avoid {} cast.

Starting Swap with api: {} as any risks runtime failures later (e.g., submitRFQOrder). Wire the real API/client or a factory.

Do we have a shared Swap API instance or factory in this repo? If yes, use it here; otherwise, expose one from @enkryptcom/swap and inject it.


454-458: Verify wait duration semantics.

UI copy says “~30 seconds”; confirm the 3rd arg to waitForReceipt is seconds (not attempts/ms) to keep UX consistent.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (7)
packages/swap/src/providers/oneInchFusion/index.ts (7)

119-124: Guard against using SDK before init().

Avoid runtime errors if a caller forgets to call init().

   private getOneInchSwap(
     options: getQuoteOptions,
     meta: QuoteMetaOptions,
     accurateEstimate: boolean,
   ): Promise<OneInchSwapResponse | null> {
+    if (!this.fusionSdk) throw new Error("OneInchFusion: init() must be called before use");

214-219: Defensive mapping of gas estimates.

Avoid out-of-bounds when result length differs; only set when present.

-          if (accurateGasEstimate) {
-            if (accurateGasEstimate.isError) return null;
-            transactions.forEach((tx, idx) => {
-              tx.gasLimit = accurateGasEstimate.result[idx];
-            });
-          }
+          if (accurateGasEstimate) {
+            if (accurateGasEstimate.isError) return null;
+            transactions.forEach((tx, idx) => {
+              const gl = accurateGasEstimate.result[idx];
+              if (gl) tx.gasLimit = gl;
+            });
+          }

237-240: Improve error logging; remove placeholder.

-      .catch((e) => {
-        console.error(e, "herere");
-        return null;
-      });
+      .catch((e) => {
+        console.error("OneInchFusion.getOneInchSwap failed", e);
+        return null;
+      });

251-258: Compute $10 minimum safely (BigNumber, zero-guard).

-      const fromToken = new SwapToken(options.fromToken);
-      const minFrom = fromToken.toRaw(
-        new BigNumber(1)
-          .div(Number(fromUSDValue) / 10)
-          .toFixed(fromToken.token.decimals),
-      ); // minimum $10 worth of tokens
-      minMax.minimumFrom = minFrom;
+      const fromToken = new SwapToken(options.fromToken);
+      const priceUsd = new BigNumber(fromUSDValue || 0);
+      if (priceUsd.lte(0)) {
+        minMax.minimumFrom = toBN("1");
+      } else {
+        const minFromHuman = new BigNumber(10).div(priceUsd); // $10 / price
+        minMax.minimumFrom = fromToken.toRaw(
+          minFromHuman.toFixed(fromToken.token.decimals),
+        );
+      }

259-259: Drop noisy debug log.

-      console.log(`min from: ${minMax}`);

316-317: Guard getStatus against uninitialized SDK.

-  getStatus(options: StatusOptions): Promise<TransactionStatus> {
-    return this.fusionSdk.getOrderStatus(options.orderHash).then((status) => {
+  getStatus(options: StatusOptions): Promise<TransactionStatus> {
+    if (!this.fusionSdk) throw new Error("OneInchFusion: init() must be called before use");
+    return this.fusionSdk.getOrderStatus(options.orderHash).then((status) => {

328-337: Guard submitRFQOrder against uninitialized SDK.

   submitRFQOrder(options: RFQOptions): Promise<string> {
+    if (!this.fusionSdk) throw new Error("OneInchFusion: init() must be called before use");
     if (!options.signatures || !options.signatures.length)
       throw new Error("OneInchFusion: No signatures found");
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3170c85 and c4adbd2.

📒 Files selected for processing (2)
  • packages/swap/src/providers/oneInchFusion/index.ts (1 hunks)
  • packages/swap/src/providers/oneInchFusion/types.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/swap/src/providers/oneInchFusion/types.ts
🧰 Additional context used
🧬 Code graph analysis (1)
packages/swap/src/providers/oneInchFusion/index.ts (5)
packages/swap/src/types/index.ts (14)
  • TokenType (49-60)
  • ProviderFromTokenResponse (278-278)
  • ProviderToTokenResponse (280-282)
  • MinMaxResponse (205-210)
  • getQuoteOptions (143-149)
  • QuoteMetaOptions (107-114)
  • EVMTransaction (163-170)
  • ProviderQuoteResponse (218-230)
  • SwapQuote (212-216)
  • ProviderSwapResponse (259-276)
  • RFQOptionsResponse (254-257)
  • StatusOptions (244-247)
  • StatusOptionsResponse (249-252)
  • RFQOptions (239-242)
packages/swap/src/providers/oneInch/index.ts (1)
  • supportedNetworks (39-82)
packages/swap/src/utils/common.ts (1)
  • isEVMAddress (13-19)
packages/swap/src/utils/approvals.ts (4)
  • TOKEN_AMOUNT_INFINITY_AND_BEYOND (8-9)
  • getAllowanceTransactions (171-171)
  • isSufficientWrappedAvailable (174-174)
  • getNativeWrapTx (173-173)
packages/swap/src/providers/oneInchFusion/types.ts (1)
  • OneInchSwapResponse (3-13)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: buildAll
🔇 Additional comments (5)
packages/swap/src/providers/oneInchFusion/index.ts (5)

270-274: Guard against undefined gasLimit when accurateEstimate=false.

-        totalGaslimit: res.transactions.reduce(
-          (total: number, curVal: EVMTransaction) =>
-            total + toBN(curVal.gasLimit).toNumber(),
-          0,
-        ),
+        totalGaslimit: res.transactions.reduce((total: number, curVal: EVMTransaction) => {
+          const gl = curVal.gasLimit ?? "0";
+          return total + toBN(gl).toNumber();
+        }, 0),

76-94: init() signature says Promise but never returns a Promise. Make it async.

-  init(tokenList: TokenType[]): Promise<void> {
+  async init(tokenList: TokenType[]): Promise<void> {
     if (!OneInchFusion.isSupported(this.network)) return;
     this.fusionSdk = new FusionSDK({
       network: Number(supportedNetworks[this.network].chainId),
       url: "https://fusion.1inch.io",
     });
     tokenList.forEach((t) => {
       this.fromTokens[t.address] = t;
       if (!this.toTokens[this.network]) this.toTokens[this.network] = {};
       this.toTokens[this.network][t.address] = {
         ...t,
         networkInfo: {
           name: this.network,
           isAddress: (address: string) =>
             Promise.resolve(isEVMAddress(address)),
         },
       };
     });
+    return;
   }

169-177: Remove PII-heavy debug log (addresses, slippage).

-        console.log({
-          ...quoteParams,
-          preset: quote.recommendedPreset,
-          walletAddress: options.fromAddress,
-          receiver: options.toAddress,
-          slippage: meta.slippage
-            ? Number(meta.slippage)
-            : Number(DEFAULT_SLIPPAGE),
-        });

284-296: Optional chain FEE_CONFIGS in swap response to avoid crashes.

-      const feeConfig =
-        FEE_CONFIGS[this.name][quote.meta.walletIdentifier].fee || 0;
+      const feeBps =
+        FEE_CONFIGS[this.name]?.[quote.meta.walletIdentifier]?.fee ?? 0;
       const response: ProviderSwapResponse = {
         fromTokenAmount: res.fromTokenAmount,
         provider: this.name,
         type: SwapType.rfq,
         toTokenAmount: res.toTokenAmount,
         transactions: res.transactions,
         typedMessages: res.typedMessages,
         additionalNativeFees: toBN(0),
         slippage: quote.meta.slippage || DEFAULT_SLIPPAGE,
-        fee: feeConfig / 100,
+        fee: feeBps / 100,

329-329: Do not log RFQ options; signatures are sensitive.

-    console.log(options);
+    // Avoid logging RFQ options (may include signatures and EIP-712 data)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (4)
packages/swap/tests/oneInchFusion.test.ts (3)

51-57: Don’t hardcode the spender; assert method selector and amount only.

For Fusion, spender should be the LOP/Fusion contract (not the Aggregation Router). Avoid brittle address assertions.

-      expect(swap?.transactions[0].to).to.be.eq(fromToken.address);
-      expect((swap?.transactions[0] as EVMTransaction).data).to.be.eq(
-        `0x095ea7b3000000000000000000000000${ONEINCH_APPROVAL_ADDRESS.replace(
-          "0x",
-          "",
-        )}${TOKEN_AMOUNT_INFINITY_AND_BEYOND.replace("0x", "")}`,
-      );
+      expect(swap?.transactions[0].to).to.be.eq(fromToken.address);
+      const data = (swap?.transactions[0] as EVMTransaction).data;
+      // approve(address,uint256)
+      expect(data.slice(0, 10)).to.be.eq("0x095ea7b3");
+      // Amount = max uint256
+      expect(data.endsWith(TOKEN_AMOUNT_INFINITY_AND_BEYOND.replace("0x", ""))).to.be.eq(true);

78-85: Avoid brittle ABI encoding in assertions; pad amount programmatically.

Use hex padding instead of hardcoding zeros.

-      expect((swap?.transactions[0] as EVMTransaction).data).to.be.eq(
-        `0x095ea7b3000000000000000000000000${ONEINCH_APPROVAL_ADDRESS.replace(
-          "0x",
-          "",
-        )}00000000000000000000000000000000000000000000000${numberToHex(
-          amount,
-        ).replace("0x", "")}`,
-      );
+      const data = (swap?.transactions[0] as EVMTransaction).data;
+      expect(data.slice(0, 10)).to.be.eq("0x095ea7b3");
+      const amountHex = numberToHex(amount).replace("0x", "");
+      expect(data.endsWith(amountHex.padStart(64, "0"))).to.be.eq(true);

22-27: Avoid async describe; it’s not awaited and can mislead.

Remove async; keep tests async inside it(...).

-describe("OneInchFusion Provider", async () => {
+describe("OneInchFusion Provider", () => {
packages/swap/src/providers/oneInchFusion/index.ts (1)

228-231: Tighten error log message (avoid stray “herere”).

Keep logs useful and non-noisy.

-      .catch((e) => {
-        console.error(e, "herere");
-        return null;
-      });
+      .catch((e) => {
+        console.error("OneInchFusion.getOneInchSwap error:", e);
+        return null;
+      });
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c4adbd2 and 4df768d.

📒 Files selected for processing (2)
  • packages/swap/src/providers/oneInchFusion/index.ts (1 hunks)
  • packages/swap/tests/oneInchFusion.test.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
packages/swap/src/providers/oneInchFusion/index.ts (6)
packages/swap/src/types/index.ts (14)
  • TokenType (49-60)
  • ProviderFromTokenResponse (278-278)
  • ProviderToTokenResponse (280-282)
  • MinMaxResponse (205-210)
  • getQuoteOptions (143-149)
  • QuoteMetaOptions (107-114)
  • EVMTransaction (163-170)
  • ProviderQuoteResponse (218-230)
  • SwapQuote (212-216)
  • ProviderSwapResponse (259-276)
  • RFQOptionsResponse (254-257)
  • StatusOptions (244-247)
  • StatusOptionsResponse (249-252)
  • RFQOptions (239-242)
packages/swap/src/providers/oneInch/index.ts (1)
  • supportedNetworks (39-82)
packages/swap/src/utils/common.ts (1)
  • isEVMAddress (13-19)
packages/swap/src/utils/approvals.ts (1)
  • TOKEN_AMOUNT_INFINITY_AND_BEYOND (8-9)
packages/swap/src/providers/oneInchFusion/types.ts (1)
  • OneInchSwapResponse (3-13)
packages/swap/src/configs.ts (3)
  • NATIVE_TOKEN_ADDRESS (144-144)
  • FEE_CONFIGS (142-142)
  • DEFAULT_SLIPPAGE (148-148)
packages/swap/tests/oneInchFusion.test.ts (3)
packages/swap/src/types/index.ts (1)
  • EVMTransaction (163-170)
packages/swap/src/providers/oneInch/index.ts (1)
  • ONEINCH_APPROVAL_ADDRESS (37-38)
packages/swap/src/utils/approvals.ts (1)
  • TOKEN_AMOUNT_INFINITY_AND_BEYOND (8-9)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: buildAll
🔇 Additional comments (8)
packages/swap/tests/oneInchFusion.test.ts (1)

50-50: Allow variable tx count (don’t assert exactly 1).

Fusion flows can require 1+ on-chain txs (approval only, or wrap+approval). Use ≥1.

-      expect(swap?.transactions.length).to.be.eq(1);
+      expect(swap?.transactions.length).to.be.gte(1);

Also applies to: 77-77

packages/swap/src/providers/oneInchFusion/index.ts (7)

138-138: Guard fee config access to prevent crashes when path is missing.

-    const feeConfig = FEE_CONFIGS[this.name][meta.walletIdentifier];
+    const feeConfig = FEE_CONFIGS[this.name]?.[meta.walletIdentifier];

139-148: Guard CHAIN_TO_WRAPPER and reuse a local var.

Avoid .toString() on possibly undefined and repeated lookups.

-    const chainId = Number(supportedNetworks[this.network].chainId);
-    const quoteParams: QuoteParams = {
+    const chainId = Number(supportedNetworks[this.network].chainId);
+    const wrapper = CHAIN_TO_WRAPPER[chainId];
+    if (isFromNative && !wrapper) return Promise.resolve(null);
+    const quoteParams: QuoteParams = {
       amount: options.amount.toString(),
-      fromTokenAddress: isFromNative
-        ? CHAIN_TO_WRAPPER[chainId].toString()
-        : options.fromToken.address,
+      fromTokenAddress: isFromNative ? wrapper.toString() : options.fromToken.address,
       toTokenAddress: options.toToken.address,
       enableEstimate: false,
       isPermit2: false,
     };

176-196: Reuse guarded wrapper in native wrap paths.

Avoid unsafe CHAIN_TO_WRAPPER[chainId].toString() calls.

-          fromToken: isFromNative
-            ? { address: CHAIN_TO_WRAPPER[chainId].toString() }
-            : options.fromToken,
+          fromToken: isFromNative ? { address: wrapper!.toString() } : options.fromToken,
-              contract: CHAIN_TO_WRAPPER[chainId].toString(),
+              contract: wrapper!.toString(),
               value: options.amount,
-                contract: CHAIN_TO_WRAPPER[chainId].toString(),
+                contract: wrapper!.toString(),
                 value: options.amount,

259-263: Guard undefined gasLimit when accurateEstimate is false.

Quotes may not have gas limits yet; summing undefined throws.

-        totalGaslimit: res.transactions.reduce(
-          (total: number, curVal: EVMTransaction) =>
-            total + toBN(curVal.gasLimit).toNumber(),
-          0,
-        ),
+        totalGaslimit: res.transactions.reduce((total: number, curVal: EVMTransaction) => {
+          const gl = curVal.gasLimit ?? "0";
+          return total + toBN(gl).toNumber();
+        }, 0),

273-285: Fee config path can be undefined; use optional chaining + default.

Prevent runtime errors and use a sane default.

-      const feeConfig =
-        FEE_CONFIGS[this.name][quote.meta.walletIdentifier].fee || 0;
+      const feeBps =
+        FEE_CONFIGS[this.name]?.[quote.meta.walletIdentifier]?.fee ?? 0;
       const response: ProviderSwapResponse = {
         fromTokenAmount: res.fromTokenAmount,
         provider: this.name,
         type: SwapType.rfq,
         toTokenAmount: res.toTokenAmount,
         transactions: res.transactions,
         typedMessages: res.typedMessages,
         additionalNativeFees: toBN(0),
         slippage: quote.meta.slippage || DEFAULT_SLIPPAGE,
-        fee: feeConfig / 100,
+        fee: feeBps / 100,

Confirm if fee expects ratio (0–1) or percent. If it’s ratio, dividing bps by 100 is off by 100x; it should be bps / 10_000.

#!/bin/bash
rg -nP --type=ts -C2 'interface\s+ProviderSwapResponse\b' packages/swap/src/types/index.ts
rg -nP --type=ts -C2 '\bfee:\s*number' packages/swap/src/types/index.ts

76-94: init() signature mismatch (declares Promise but returns synchronously).

Align the signature to avoid type errors and callers awaiting a non-promise.

-  init(tokenList: TokenType[]): Promise<void> {
+  init(tokenList: TokenType[]): void {
     if (!OneInchFusion.isSupported(this.network)) return;
     this.fusionSdk = new FusionSDK({
       network: Number(supportedNetworks[this.network].chainId),
       url: "https://fusion.1inch.io",
     });
     tokenList.forEach((t) => {
       this.fromTokens[t.address] = t;
       if (!this.toTokens[this.network]) this.toTokens[this.network] = {};
       this.toTokens[this.network][t.address] = {
         ...t,
         networkInfo: {
           name: this.network,
           isAddress: (address: string) =>
             Promise.resolve(isEVMAddress(address)),
         },
       };
     });
   }

Run to find any callers that await init():

#!/bin/bash
rg -nP --type=ts -C2 '\bawait\s+\w+\.init\s*\('

64-64: Definite assignment for fusionSdk.

Initialize or mark as definite to satisfy strictPropertyInitialization.

-  fusionSdk: FusionSDK;
+  fusionSdk!: FusionSDK;

@kvhnuke kvhnuke changed the base branch from develop to devop/release-v-2-13 September 25, 2025 18:53
@kvhnuke kvhnuke merged commit 5bb1fec into devop/release-v-2-13 Sep 25, 2025
4 checks passed
@kvhnuke kvhnuke deleted the feat/oneinch-fusion branch September 25, 2025 18:59
This was referenced Sep 25, 2025
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