Skip to content

Add Symbiosis Swaps#518

Open
ahsan-javaiid wants to merge 10 commits into
mainfrom
feat/symbiosis
Open

Add Symbiosis Swaps#518
ahsan-javaiid wants to merge 10 commits into
mainfrom
feat/symbiosis

Conversation

@ahsan-javaiid

Copy link
Copy Markdown
Collaborator

docs: Add Symbiosis Finance integration guide

Summary

Adds a new integration guide for Symbiosis Finance under docs/06-use-cases/interoperability/. Symbiosis natively supports Rootstock (Chain ID 30) for cross-chain swaps across 30+ EVM and non-EVM networks, including native BTC ↔ Rootstock routes via the BTC Fee Collector deployed on Rootstock.

The guide covers two integration paths:

  1. REST API — language-agnostic, recommended for production
  2. symbiosis-js-sdk — direct protocol access from a TypeScript/Node app

@vercel

vercel Bot commented Jun 29, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
devportal-rootstock Ready Ready Preview, Comment Jun 29, 2026 11:49am

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

OpenSSF Scorecard

PackageVersionScoreDetails

Scanned Files

@ahsan-javaiid ahsan-javaiid left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🤖 PR Review · #518 — Add Symbiosis Swaps

Chunk: 1/1
PR URL: #518
Author: ahsan-javaiid (Ahsan Javaid)
State: OPEN
Reviewed: 2026-06-29
Confidence: High — 70 high · 0 medium · 0 low
Mode: Full pipeline (validator + AI reviewer + implementer).
Knowledge base: not attached — findings reflect this PR's diff and validator output only.
Suggestion resolution: 35 applied — 33 resolved ✅, 2 re-flagged in a later pass ⚠️
Contributor Description: docs: Add Symbiosis Finance integration guide

Caution

Verdict: Changes requested — 16 critical/high bug(s) in code snippets.


📝 What's in this PR

This PR adds a comprehensive integration guide for Symbiosis Finance, a cross-chain AMM DEX natively supporting Rootstock. The guide enables developers to build dApps that swap tokens between Rootstock and 30+ EVM/non-EVM networks, plus native Bitcoin, using either the REST API (recommended for production) or the JS SDK (for programmatic access). The guide includes step-by-step examples, production checklists, and additional patterns (React hooks, viem, Python, destination calldata, polling utilities) covering real-world integration scenarios.


📋 Changes

Cohort / File(s) Summary
Symbiosis Integration Guide
docs/06-use-cases/interoperability/integrate-symbiosis.md
New comprehensive guide covering REST API and JS SDK integration paths for cross-chain swaps via Symbiosis Finance. Includes prerequisites, 60-second concepts, step-by-step instructions (quote, approve, sign, track), Bitcoin route details, 10+ code patterns in TypeScript/JavaScript/Python/React, production checklists, troubleshooting, and reference links. Demonstrates both language-agnostic API approach and SDK-based protocol access.
Use Cases Index
docs/06-use-cases/index.md
Added Symbiosis Finance filter item to the interoperability section of the Use Cases index, enabling users to discover the new integration guide alongside existing bridge and interoperability options (LayerZero, LI.FI).

✨ What works well

  • The guide clearly separates two integration paths (REST API vs. SDK) with explicit use-case guidance for each, making it easy for developers to choose the right approach for their stack.
  • Comprehensive production checklist highlighting security-critical steps (correct approval targets, calldata freshness, contract address verification) shows strong attention to developer safety and fund protection.
  • Excellent breadth of code samples across five languages (TypeScript, JavaScript, Python, React, bash) and realistic patterns (batch quoting, exponential backoff, quote refresh loops, viem/ethers interop) demonstrates the breadth of integration scenarios.

📊 Documentation Impact

High — HIGH severity findings detected affecting developer-facing documentation.

Comment counts

🔴 Critical 🟠 High 🟡 Medium 🔵 Nitpick ℹ️ Informational
0 16 12 42 0

🎯 Agent Score

Overall score: 90 / 100 — Grade A · preview deployment ↗

Page Score ✅ Pass ⚠️ Warn ❌ Fail Top issue
/use-cases/ 16/20 16 3 1 ✗ markdown-content-parity: 1 of 1 pages have substantive content differences bet…
/use-cases/interoperability/integrate-symbiosis 18/20 18 2 0
Full per-page raw scorer output (2 page(s))

Page 1: https://devportal-rootstock-git-feat-symbiosis-iov-labs-mkt.vercel.app/use-cases/

  Source file: docs/06-use-cases/index.md

Running checks on devportal-rootstock-git-feat-symbiosis-iov-labs-mkt.vercel.app/use-cases/...

Agent-Friendly Docs Check: https://devportal-rootstock-git-feat-symbiosis-iov-labs-mkt.vercel.app/use-cases/
Timestamp: 6/29/2026, 4:31:17 PM

content-discoverability
  ✓ llms-txt-exists: llms.txt found at https://devportal-rootstock-git-feat-symbiosis-iov-labs-mkt.vercel.app/llms.txt
  ✓ llms-txt-valid: llms.txt follows the proposed structure (H1, blockquote, heading-delimited link sections)
  ⚠ llms-txt-size: llms.txt is 62,185 characters (between 50,000 and 100,000; consider splitting)
      Learn more: https://agentdocsspec.com/spec/#llms-txt-size
  ⚠ llms-txt-links-resolve: All links are external; 26/27 resolve (1 failed; may be bot-detection or rate-limiting)
      Learn more: https://agentdocsspec.com/spec/#llms-txt-links-resolve
  ○ llms-txt-links-markdown: All 27 links are external; cannot assess markdown support
  ✓ llms-txt-directive-html: llms.txt directive found in HTML of all 1 pages, near the top of content
  ✓ llms-txt-directive-md: llms.txt directive found in markdown of all 1 pages, near the top of content

markdown-availability
  ✓ markdown-url-support: 1/1 pages support .md URLs (100%)
  ✓ content-negotiation: 1/1 pages support content negotiation (100%)

page-size
  ✓ rendering-strategy: All 1 pages contain server-rendered content
  ✓ page-size-markdown: All 1 pages under 50K chars (median 690, max 690)
  ✓ page-size-html: All 1 pages under 50K chars (median 65K HTML → 7K markdown (89% boilerplate))
  ⚠ content-start-position: 1 of 1 pages have content starting at 10–50% (worst 14%)
      Learn more: https://agentdocsspec.com/spec/#content-start-position

content-structure
  ✓ tabbed-content-serialization: No tabbed content detected across 1 pages
  ✓ section-header-quality: No tabbed content found; header quality check not applicable
  ✓ markdown-code-fence-validity: All 0 code fences properly closed across 2 pages

url-stability
  ✓ http-status-codes: All 1 pages return proper error codes for bad URLs
  ✓ redirect-behavior: All 1 redirect(s) across 1 pages are same-host HTTP redirects

observability
  ○ llms-txt-coverage: No sitemap found; cannot assess llms.txt coverage without a sitemap as ground truth
  ✗ markdown-content-parity: 1 of 1 pages have substantive content differences between markdown and HTML (avg 85% missing)
      Learn more: https://agentdocsspec.com/spec/#markdown-content-parity
  ✓ cache-header-hygiene: All 2 endpoints have appropriate cache headers

authentication
  ✓ auth-gate-detection: All 1 pages are publicly accessible
  ○ auth-alternative-access: All docs pages are publicly accessible; no alternative access paths needed

Summary
  16 passed, 3 warnings, 1 failed, 3 skipped (23 total)

Full spec: https://agentdocsspec.com/spec/


Page 2: https://devportal-rootstock-git-feat-symbiosis-iov-labs-mkt.vercel.app/use-cases/interoperability/integrate-symbiosis

  Source file: docs/06-use-cases/interoperability/integrate-symbiosis.md

Running checks on devportal-rootstock-git-feat-symbiosis-iov-labs-mkt.vercel.app/use-cases/interoperability/integrate-symbiosis...

Agent-Friendly Docs Check: https://devportal-rootstock-git-feat-symbiosis-iov-labs-mkt.vercel.app/use-cases/interoperability/integrate-symbiosis
Timestamp: 6/29/2026, 4:31:23 PM

content-discoverability
  ✓ llms-txt-exists: llms.txt found at https://devportal-rootstock-git-feat-symbiosis-iov-labs-mkt.vercel.app/llms.txt
  ✓ llms-txt-valid: llms.txt follows the proposed structure (H1, blockquote, heading-delimited link sections)
  ⚠ llms-txt-size: llms.txt is 62,185 characters (between 50,000 and 100,000; consider splitting)
      Learn more: https://agentdocsspec.com/spec/#llms-txt-size
  ⚠ llms-txt-links-resolve: All links are external; 0/1 resolve (1 failed; may be bot-detection or rate-limiting)
      Learn more: https://agentdocsspec.com/spec/#llms-txt-links-resolve
  ○ llms-txt-links-markdown: All 1 links are external; cannot assess markdown support
  ✓ llms-txt-directive-html: llms.txt directive found in HTML of all 1 pages, near the top of content
  ✓ llms-txt-directive-md: llms.txt directive found in markdown of all 1 pages, near the top of content

markdown-availability
  ✓ markdown-url-support: 1/1 pages support .md URLs (100%)
  ✓ content-negotiation: 1/1 pages support content negotiation (100%)

page-size
  ✓ rendering-strategy: All 1 pages contain server-rendered content
  ✓ page-size-markdown: All 1 pages under 50K chars (median 34K, max 34K)
  ✓ page-size-html: All 1 pages under 50K chars (median 472K HTML → 43K markdown (91% boilerplate))
  ✓ content-start-position: Content starts within first 10% on all 1 pages (median 0%)

content-structure
  ✓ tabbed-content-serialization: No tabbed content detected across 1 pages
  ✓ section-header-quality: No tabbed content found; header quality check not applicable
  ✓ markdown-code-fence-validity: All 23 code fences properly closed across 2 pages

url-stability
  ✓ http-status-codes: All 1 pages return proper error codes for bad URLs
  ✓ redirect-behavior: All 1 redirect(s) across 1 pages are same-host HTTP redirects

observability
  ○ llms-txt-coverage: No sitemap found; cannot assess llms.txt coverage without a sitemap as ground truth
  ✓ markdown-content-parity: All 1 pages have equivalent markdown and HTML content (avg 3% missing)
  ✓ cache-header-hygiene: All 2 endpoints have appropriate cache headers

authentication
  ✓ auth-gate-detection: All 1 pages are publicly accessible
  ○ auth-alternative-access: All docs pages are publicly accessible; no alternative access paths needed

Summary
  18 passed, 2 warnings, 3 skipped (23 total)

Full spec: https://agentdocsspec.com/spec/


🔍 Findings

70 finding(s) — 16 escalated · 54 suggested · click to expand
# Category Severity Difficulty File Description Confidence
48 code_snippet HIGH EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:83
showWhy it matters: The address 0xaf88d065e77c8cC2239327C5EDb3A432268e5831... is 45 characters instead of 42 (0x + 40 hex digits), making it invalid. Any code copying this example will fail when attempting to interact with the contract. Recommendation: Remove the trailing ... to restore the complete address: 0xaf88d065e77c8cC2239327C5EDb3A432268e5831.
High
51 code_snippet HIGH EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:469
showWhy it matters: The chain .then((r) => r.json()).then((r) => r.json()) calls .json() on a Response object, then calls .json() again on the already-parsed JSON object. The second call will fail with a TypeError because parsed JSON objects do not have a .json() method. This breaks the quote-fetching hook. Recommendation: Remove the duplicate .then((r) => r.json()) call, keeping only one.
High
52 code_snippet HIGH EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:491
showWhy it matters: The guide consistently identifies Rootstock as Chain ID 30 throughout every other example. Using 31 here will send the swap to the wrong network, causing the transaction to fail or be routed to an incorrect destination. Recommendation: Replace toChainId: 31 with toChainId: 30 to match the documented Rootstock mainnet identifier.
High
54 code_snippet HIGH EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:534
showWhy it matters: The REST API section explicitly states: "Approve the user's ERC-20 to this address, not to tx.to." This viem example contradicts that guidance by approving to quote.tx.to. Approving to the wrong contract may result in the token transfer failing or funds being stuck. Recommendation: Change the approval target to quote.approveTo: args: [quote.approveTo, parseUnits(quote.tokenAmountIn.amount, 6)]. Also update the comment to say "metaRouterGateway" instead of "metaRouter".
High
56 code_snippet HIGH EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:607
showWhy it matters: The line if status["status"] = "success": uses a single = (assignment) instead of == (comparison). This is a syntax error that will prevent the Python script from running at all. The Python interpreter will raise a SyntaxError on this line. Recommendation: Replace = with == to perform a comparison.
High
58 code_snippet HIGH EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:748
showWhy it matters: The line const status = res.json(); does not await the async call. status becomes a Promise, and the subsequent line if (status.status === "success") tries to access the .status property on a Promise object, which will be undefined. The condition will never be true and the polling logic breaks. Recommendation: Add await: const status = await res.json();.
High
59 code_snippet HIGH EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:794
showWhy it matters: The line deadline: Date.now() + 1800 adds 1800 milliseconds (1.8 seconds) to the current time in milliseconds. However, Symbiosis deadline fields expect Unix time in seconds. This deadline will expire almost immediately (within 2 seconds), causing the swap to fail with a "deadline exceeded" error. Earlier examples in the guide correctly use Math.floor(Date.now() / 1000) + 1800 for a 30-minute deadline. Recommendation: Divide Date.now() by 1000 and convert to seconds: deadline: Math.floor(Date.now() / 1000) + 1800.
High
60 code_snippet HIGH EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:863
showWhy it matters: The setInterval(fetchOnce, 30) call sets the interval to 30 milliseconds, not 30 seconds. This means the quote-refresh function fires 1000 times per second, overwhelming the network and the Symbiosis API with unnecessary requests. The guide mentions (~30 seconds) as the intended refresh rate. Recommendation: Change the interval to 30000 milliseconds (30 seconds): setInterval(fetchOnce, 30000); or define a constant for clarity.
High
61 code_snippet HIGH EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:163
showWhy it matters: The code attempts to compare an ethers.BigNumber (returned by contract.allowance()) with a JavaScript BigInt using the < operator. BigNumber overloads comparison operators, but comparison with a BigInt primitive will not work correctly and may throw a TypeError or produce unexpected results. Recommendation: Use BigNumber's .lt() method to compare values correctly: allowance.lt(quote.tokenAmountIn.amount).
High
62 code_snippet HIGH EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:176
showWhy it matters: The while(true) loop continues polling /v2/tx/{chainId}/{txHash} without a maximum time limit. If the API fails to return a definitive status (success, stucked, or reverted), the function hangs indefinitely, blocking the user's flow. Recommendation: Add a timeout guard similar to the pollUntilSettled function elsewhere in the guide (lines 747–757). Track elapsed time and throw an error after ~20 minutes if the swap hasn't settled.
High
64 code_snippet HIGH EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:476
showWhy it matters: Throughout the guide, the REST API endpoint is consistently /v2/quote (singular) for fetching quotes. This React hook calls /v2/quotes (plural), which does not appear in the API reference or any other example. The inconsistency will cause the fetch to hit an undefined endpoint and likely fail. Recommendation: Change the endpoint from /v2/quotes to /v2/quote (singular) to match the documented API.
High
65 code_snippet HIGH EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:476
showWhy it matters: The Slippage Reference section (line 865) explicitly states that slippage is expressed in basis points with a valid range of 20–1000 (0.2%–10.0%). The value 1.5 is below the minimum and will likely be rejected by the API or produce unexpected behavior. Recommendation: Set slippage to at least 20 (0.2% tolerance); for typical cross-chain swaps, 100–200 is common. For this stable-coin swap (USDC to RBTC), 100 (1.0% tolerance) is conservative and reasonable.
High
66 code_snippet HIGH EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:601
showWhy it matters: USDC has 6 decimals, not 8. The code multiplies the user's amount by 108, resulting in values 100 times larger than intended. For a 25 USDC swap, this would send 2500 USDC worth of request data. The API may reject the oversized amount or cause transaction failures. Recommendation: Change the exponent from 108 to 10**6 to match USDC's actual decimal places.
High
67 code_snippet HIGH EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:612
showWhy it matters: time.sleep(5000) pauses the polling loop for 5000 seconds (~83 minutes). Users waiting for swap confirmation would stall for over an hour between status checks. The documented polling interval should be a few seconds. Recommendation: Change the argument to time.sleep(5) for a 5-second delay between polling attempts.
High
68 code_snippet HIGH EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:704
showWhy it matters: The function pickBestSourceForRbtc is intended to return the best (highest amountOut) source tokens. Currently, it sorts quotes by amountOut in ascending order and slices the first 3 items, which are the worst options. Users would see the least favorable exchange rates. Recommendation: Reverse the sort order to descending so the highest amountOut values are ranked first.
High
70 code_snippet HIGH EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:871
showWhy it matters: The cleanup function in the React hook's useEffect attempts to clearInterval(intervalRef), but intervalRef is a React Ref object, not the interval ID. The interval ID is stored in intervalRef.current. This bug leaves the interval running after the component unmounts, causing memory leaks and continued API calls. Recommendation: Fix the cleanup to clear the stored interval ID: clearInterval(intervalRef.current).
High
47 code_snippet MEDIUM EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:75
showWhy it matters: The URL https://api.symbiosis.finance//crosschain has two consecutive slashes, which will cause HTTP requests to fail or route to an unexpected endpoint. Recommendation: Replace with https://api.symbiosis.finance/crosschain (single slash before crosschain).
High
49 code_snippet MEDIUM EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:187
showWhy it matters: The throw statement on the commented line is meant to terminate the polling loop when a swap gets stuck or reverted. Without it, the while (true) loop continues indefinitely on error states, blocking the application. Developers copying this code will have broken error handling. Recommendation: Uncomment the throw new Error(...) line so the polling function exits and propagates the error when a swap fails.
High
50 code_snippet MEDIUM EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:356
showWhy it matters: The bridgeUsdtToRbtc function in symbiosis-execute-sdk.ts calls .findTransitTokenSent(ROOTSTOCK_CHAIN_ID, ...) but the constant is only defined in the previous example file (symbiosis-sdk.ts). A developer copying this file in isolation will get a reference error at runtime. Recommendation: Add an import statement import { ROOTSTOCK_CHAIN_ID } from "./symbiosis-sdk"; at the top of the file, or redeclare the constant locally: const ROOTSTOCK_CHAIN_ID = 30;.
High
53 code_snippet MEDIUM EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:528
showWhy it matters: In the viem example, const approveHash = walletClient.writeContract({...}); does not await the async call. The variable becomes a Promise instead of a transaction hash string. When the function returns { approveHash, swapHash }, the caller receives a Promise in the approveHash field, not a usable hash. Recommendation: Add await to resolve the Promise: const approveHash = await walletClient.writeContract({...});.
High
55 code_snippet MEDIUM EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:580
showWhy it matters: The Symbiosis API expects the field name slippage, not slipage. The API will either reject the request with a validation error or silently ignore the misspelled field. This breaks slippage control in the quote request. Recommendation: Fix the spelling: "slippage": 200,.
High
63 code_snippet MEDIUM EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:209
showWhy it matters: The snippet uses userBtcAddress and userRskAddress in the request body without defining or explaining them in the code. A developer copying this snippet will encounter a ReferenceError at runtime. Recommendation: Define these variables before the fetch call, e.g., const userBtcAddress = "user's Bitcoin address"; const userRskAddress = "user's Rootstock address"; OR add prose above the snippet explaining that these should be replaced with the user's actual wallet addresses.
High
69 code_snippet MEDIUM EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:835
showWhy it matters: The condition allowance > amount returns false if the user's allowance exactly matches the required amount. In reality, an exact match is sufficient and the function should return true. This edge case causes unnecessary re-approvals when the allowance is precisely calibrated. Recommendation: Use >= to accept allowance values equal to or greater than the required amount.
High
1 Rootstock.607-Robotics, Rootstock.602-Rootstock-product-names, Rootstock.600-Rootstock-names-versions MEDIUM EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:9
showAI-style pattern detected. Consider using 'specific list' instead of 'L2s, EVM, and non'. | Use 'rBTC' instead of 'RBTC' | Use 'rBTC' instead of 'RBTC'
High
12 Rootstock.600-Rootstock-names-versions, Rootstock.602-Rootstock-product-names MEDIUM EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:71
showUse 'rBTC' instead of 'RBTC' | Use 'rBTC' instead of 'RBTC'
High
21 Rootstock.600-Rootstock-names-versions, Rootstock.602-Rootstock-product-names MEDIUM EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:254
showUse 'rBTC' instead of 'RBTC' | Use 'rBTC' instead of 'RBTC'
High
34 Rootstock.602-Rootstock-product-names, Rootstock.600-Rootstock-names-versions MEDIUM EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:758
showUse 'rBTC' instead of 'RBTC' | Use 'rBTC' instead of 'RBTC'
High
35 Rootstock.602-Rootstock-product-names, Rootstock.600-Rootstock-names-versions MEDIUM EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:760
showUse 'rBTC' instead of 'RBTC' | Use 'rBTC' instead of 'RBTC'
High
71 consistency LOW EASY docs/06-use-cases/index.md:110
showWhy it matters: Rootstock style and the guide's title use 'Symbiosis Finance' (capitalized). The filter item description uses the lowercase 'symbiosis', creating an inconsistency. Brand consistency matters for professionalism and clarity. Recommendation: Capitalize the product name to match the official branding: 'Integrate Symbiosis into your Rootstock dApp…'
High
2 Rootstock.005-Industry-product-names LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:26
showUse 'Mainnet' instead of 'mainnet'
High
3 Rootstock.607-Robotics, Rootstock.005-Industry-product-names LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:35
showAI-style pattern detected. Consider using ', ' instead of ' — '. | Use 'Mainnet' instead of 'mainnet'
High
4 Rootstock.006-Contractions-forbidden LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:36
showConsider using 'don't' instead of 'Do not'
High
5 Rootstock.607-Robotics, Rootstock.006-Contractions-forbidden LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:45
showAI-style pattern detected. Consider using ', ' instead of ' — '. | Consider using 'isn't' instead of 'is not'
High
6 Rootstock.607-Robotics LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:46
showAI-style pattern detected. Consider using ', ' instead of ' — '.
High
7 Rootstock.607-Robotics, Rootstock.006-Contractions-forbidden LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:47
showAI-style pattern detected. Consider using ', ' instead of ' — '. | Consider using 'isn't' instead of 'is not'
High
8 Rootstock.607-Robotics LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:49
showAI-style pattern detected. Consider using ', ' instead of ' — '.
High
9 Rootstock.005-Industry-product-names LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:53
showUse 'Mainnet' instead of 'mainnet'
High
10 Rootstock.016-No-inline-comments LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:55
showAvoid inline comments in code blocks.
High
11 Rootstock.016-No-inline-comments LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:65
showAvoid inline comments in code blocks.
High
13 Rootstock.016-No-inline-comments LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:73
showAvoid inline comments in code blocks.
High
14 Rootstock.006-Contractions-forbidden LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:132
showConsider using 'don't' instead of 'Do not'
High
15 Rootstock.607-Robotics LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:134
showAI-style pattern detected. Consider using 'specific list' instead of 'Approve, Sign, and Send'.
High
16 Rootstock.016-No-inline-comments LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:136
showAvoid inline comments in code blocks.
High
17 Rootstock.016-No-inline-comments LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:175
showAvoid inline comments in code blocks.
High
18 Rootstock.006-Contractions-forbidden LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:194
showConsider using 'doesn't' instead of 'does not'
High
19 Rootstock.016-No-inline-comments LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:200
showAvoid inline comments in code blocks.
High
20 Rootstock.006-Contractions-forbidden LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:240
showConsider using 'doesn't' instead of 'does not'
High
22 Rootstock.607-Robotics LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:312
showAI-style pattern detected. Consider using 'specific list' instead of 'Approve, Send, and Wait'.
High
23 Rootstock.016-No-inline-comments LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:314
showAvoid inline comments in code blocks.
High
24 Rootstock.006-Contractions-forbidden LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:363
showConsider using 'can't' instead of 'cannot'
High
25 Rootstock.016-No-inline-comments LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:370
showAvoid inline comments in code blocks.
High
26 Rootstock.016-No-inline-comments LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:398
showAvoid inline comments in code blocks.
High
27 Rootstock.011-Headings-not-followed-by-heading LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:421
showAvoid stacked headings. There should be content for each heading.
High
28 Rootstock.016-No-inline-comments LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:427
showAvoid inline comments in code blocks.
High
29 Rootstock.016-No-inline-comments LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:504
showAvoid inline comments in code blocks.
High
30 Rootstock.016-No-inline-comments LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:554
showAvoid inline comments in code blocks.
High
31 Rootstock.016-No-inline-comments LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:622
showAvoid inline comments in code blocks.
High
32 Rootstock.016-No-inline-comments LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:681
showAvoid inline comments in code blocks.
High
33 Rootstock.016-No-inline-comments LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:731
showAvoid inline comments in code blocks.
High
36 Rootstock.016-No-inline-comments LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:762
showAvoid inline comments in code blocks.
High
37 Rootstock.016-No-inline-comments LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:848
showAvoid inline comments in code blocks.
High
38 Rootstock.016-No-inline-comments LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:881
showAvoid inline comments in code blocks.
High
39 Rootstock.607-Robotics LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:919
showAI-style pattern detected. Consider using ', ' instead of ' — '.
High
40 Rootstock.607-Robotics LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:921
showAI-style pattern detected. Consider using ', ' instead of ' — '.
High
41 Rootstock.607-Robotics LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:923
showAI-style pattern detected. Consider using ', ' instead of ' — '.
High
42 Rootstock.607-Robotics LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:925
showAI-style pattern detected. Consider using ', ' instead of ' — '.
High
43 Rootstock.605-Word-list LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:932
showUse 'Rootstock Explorer' instead of 'explorer'.
High
44 Rootstock.005-Industry-product-names LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:933
showUse 'Mainnet' instead of 'mainnet'
High
45 Rootstock.605-Word-list LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:938
showUse 'Rootstock Explorer' instead of 'explorer'.
High
46 Rootstock.605-Word-list LOW EASY docs/06-use-cases/interoperability/integrate-symbiosis.md:943
showUse 'Rootstock Explorer' instead of 'explorer'.
High

Click show in the Description column to expand the full message for any row.


⚙️ Review Iterations

Round Findings Escalated Suggested Document-only Improved
1 60 9 51 0 Yes
2 11 8 3 0 Yes

📌 Sources

Generated by Devportal Review Agent · v0.0.7+b4935ef+2026-06-24

@@ -0,0 +1,946 @@
---

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Review: integrate-symbiosis.md

Page: docs/06-use-cases/interoperability/integrate-symbiosis.md

Summary

This PR adds a comprehensive integration guide for Symbiosis Finance, a cross-chain AMM DEX natively supporting Rootstock. The guide enables developers to build dApps that swap tokens between Rootstock and 30+ EVM/non-EVM networks, plus native Bitcoin, using either the REST API (recommended for production) or the JS SDK (for programmatic access). The guide includes step-by-step examples, production checklists, and additional patterns (React hooks, viem, Python, destination calldata, polling utilities) covering real-world integration scenarios.

Before merge, correct 16 HIGH-severity code/structural issue(s) and address 12 MEDIUM-severity finding(s) in integrate-symbiosis.md — see the inline comments on this file for the specific fixes. Developers copying the HIGH-severity examples would otherwise hit runtime errors, wrong network routing, or broken navigation; the MEDIUM-severity items are style/naming corrections.

The remaining 41 LOW-severity finding(s) are editorial (style guide, contractions, product naming, AI-style patterns). Those improvements are valuable but not merge blockers and can be addressed in a follow-up pass.

What works well

  • The guide clearly separates two integration paths (REST API vs. SDK) with explicit use-case guidance for each, making it easy for developers to choose the right approach for their stack.
  • Comprehensive production checklist highlighting security-critical steps (correct approval targets, calldata freshness, contract address verification) shows strong attention to developer safety and fund protection.
  • Excellent breadth of code samples across five languages (TypeScript, JavaScript, Python, React, bash) and realistic patterns (batch quoting, exponential backoff, quote refresh loops, viem/ethers interop) demonstrates the breadth of integration scenarios.

Fixed by agentic — checklist

The agent applied these fixes automatically and pushed them to the PR branch:

  • ✅ USDC token address is truncated with ellipsis. (line 83 · 🟠 High · 🐛 Logic Bug)
  • ✅ BigNumber cannot be directly compared with BigInt; comparison will fail at runtime. (line 163 · 🟠 High · 🐛 Logic Bug)
  • ✅ Polling function has no timeout guard and will loop indefinitely if API returns unexpected status. (line 176 · 🟠 High · 🐛 Logic Bug)
  • ✅ The .json() method is called twice on the same fetch response. (line 469 · 🟠 High · 🐛 Logic Bug)
  • ✅ Endpoint /v2/quotes is inconsistent with the documented /v2/quote endpoint used elsewhere. (line 476 · 🟠 High · 📝 Doc Correctness)
  • ✅ Slippage value of 1.5 is below the documented minimum of 20 basis points. (line 476 · 🟠 High · 🐛 Logic Bug)
  • ✅ The example uses chain ID 31 instead of Rootstock's chain ID 30. (line 491 · 🟠 High · 📝 Doc Correctness)
  • ✅ The viem example approves to quote.tx.to (metaRouter) instead of quote.approveTo (metaRouterGateway). (line 534 · 🟠 High · 📝 Doc Correctness)
  • ✅ USDC decimal conversion uses 108 instead of 106; amounts will be 100× too large. (line 601 · 🟠 High · 🐛 Logic Bug)
  • ✅ Python syntax error: assignment operator = used in conditional instead of comparison ==. (line 607 · 🟠 High · 🐛 Logic Bug)
  • ✅ Sleep duration is 5000 seconds (83 minutes) instead of 5 seconds. (line 612 · 🟠 High · 🐛 Logic Bug)
  • ✅ Sort order selects worst quotes instead of best; sorting ascending then slicing [0, 3] returns lowest amountOut values. (line 704 · 🟠 High · 🐛 Logic Bug)
  • ✅ The .json() call is not awaited; status is assigned a Promise instead of the parsed JSON. (line 748 · 🟠 High · 🐛 Logic Bug)
  • ✅ Deadline calculation uses milliseconds instead of seconds. (line 794 · 🟠 High · 🐛 Logic Bug)
  • ✅ The poll interval is set to 30 milliseconds instead of 30 seconds. (line 863 · 🟠 High · 🐛 Logic Bug)
  • ✅ Cleanup function clears wrong variable; should clear intervalRef.current, not intervalRef. (line 871 · 🟠 High · 🐛 Logic Bug)
  • ✅ Use 'rBTC' instead of 'RBTC' (lines 71, 254, 758, 760 · ⚠️ Medium · 🎨 Rootstock.600-Rootstock-names-versions)
  • ✅ API URL contains a double slash. (line 75 · ⚠️ Medium · 🐛 Logic Bug)
  • ✅ Error handling for stuck/reverted swaps is commented out. (line 187 · ⚠️ Medium · 🐛 Logic Bug)
  • ✅ Constant ROOTSTOCK_CHAIN_ID is used but not defined in this file. (line 356 · ⚠️ Medium · 📝 Doc Correctness)
  • ✅ Python field name is misspelled as slipage instead of slippage. (line 580 · ⚠️ Medium · 🐛 Logic Bug)
  • ✅ Allowance comparison uses > instead of >=, rejecting exactly-sufficient approvals. (line 835 · ⚠️ Medium · 🐛 Logic Bug)
  • ✅ Use 'Mainnet' instead of 'mainnet' (lines 26, 53, 933 · 🔵 Nitpick · 🎨 Rootstock.005-Industry-product-names)
  • ✅ Use 'Rootstock Explorer' instead of 'explorer' (lines 932, 938, 943 · 🔵 Nitpick · 🎨 Rootstock.605-Word-list)

Required before merge — checklist

Contributor action order — these items still need a manual fix:

  • ⬜ AI-style pattern detected (lines 9, 35, 45, 46, 47, 49, 134, 312, 919, 921, 923, 925 · ⚠️ Medium · 🎨 Rootstock.607-Robotics)
  • ⬜ Variables userBtcAddress and userRskAddress are used but never defined in the snippet. (line 209 · ⚠️ Medium · 📝 Doc Correctness)
  • ⬜ The writeContract call is not awaited, leaving approveHash as an unresolved Promise. (line 528 · ⚠️ Medium · 🐛 Logic Bug)
  • ⬜ Consider using 'don't' instead of 'Do not' (lines 36, 132 · 🔵 Nitpick · 🎨 Rootstock.006-Contractions-forbidden)
  • ⬜ Avoid inline comments in code blocks (lines 55, 65, 73, 136, 175, 200, 314, 370, 398, 427, 504, 554, 622, 681, 731, 762, 848, 881 · 🔵 Nitpick · 🎨 Rootstock.016-No-inline-comments)
  • ⬜ Consider using 'doesn't' instead of 'does not' (lines 194, 240 · 🔵 Nitpick · 🎨 Rootstock.006-Contractions-forbidden)
  • ⬜ Consider using 'can't' instead of 'cannot' (line 363 · 🔵 Nitpick · 🎨 Rootstock.006-Contractions-forbidden)
  • ⬜ Avoid stacked headings (line 421 · 🔵 Nitpick · 🎨 Rootstock.011-Headings-not-followed-by-heading)

description="Cross-chain token transfers between Rootstock and Ethereum Sepolia using LayerZero OFT."
/>

<FilterItem

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Review: index.md

Page: docs/06-use-cases/index.md

Summary

This PR adds a comprehensive integration guide for Symbiosis Finance, a cross-chain AMM DEX natively supporting Rootstock. The guide enables developers to build dApps that swap tokens between Rootstock and 30+ EVM/non-EVM networks, plus native Bitcoin, using either the REST API (recommended for production) or the JS SDK (for programmatic access). The guide includes step-by-step examples, production checklists, and additional patterns (React hooks, viem, Python, destination calldata, polling utilities) covering real-world integration scenarios.

No merge-blocking issues were identified in index.md.

The remaining 1 LOW-severity finding(s) are editorial (style guide, contractions, product naming, AI-style patterns). Those improvements are valuable but not merge blockers and can be addressed in a follow-up pass.

What works well

  • The guide clearly separates two integration paths (REST API vs. SDK) with explicit use-case guidance for each, making it easy for developers to choose the right approach for their stack.
  • Comprehensive production checklist highlighting security-critical steps (correct approval targets, calldata freshness, contract address verification) shows strong attention to developer safety and fund protection.
  • Excellent breadth of code samples across five languages (TypeScript, JavaScript, Python, React, bash) and realistic patterns (batch quoting, exponential backoff, quote refresh loops, viem/ethers interop) demonstrates the breadth of integration scenarios.

Fixed by agentic — checklist

The agent applied these fixes automatically and pushed them to the PR branch:

  • ✅ Product name 'symbiosis' should be capitalized as 'Symbiosis' throughout. (line 110 · 🔵 Nitpick · ↔️ Consistency)

const body = {
tokenAmountIn: {
chainId: 42161, // Arbitrum One
address: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831...", // native USDC

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🟠 High | 🐛 Logic Bug | Auto Fixed ✅
Removes the trailing ellipsis so the address is a valid 42-character Ethereum address.

Suggested change
address: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831...", // native USDC
address: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", // native USDC

signer,
);
const allowance = await usdc.allowance(userAddress, quote.approveTo);
if (allowance < BigInt(quote.tokenAmountIn.amount)) {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🟠 High | 🐛 Logic Bug | Auto Fixed ✅
BigNumber.lt() handles string, number, and BigNumber arguments safely
Removes the BigInt() wrapper and uses the method designed for BigNumber comparisons.

Suggested change
if (allowance < BigInt(quote.tokenAmountIn.amount)) {
if (allowance.lt(quote.tokenAmountIn.amount)) {

Comment on lines +176 to +189
export async function waitForSymbiosisSwap(sourceChainId: number, txHash: string) {
while (true) {
const res = await fetch(
`${SYMBIOSIS_API}/v2/tx/${sourceChainId}/${txHash}`,
);
const status = await res.json();
// status.status is one of: "pending", "success", "stucked", "reverted"
if (status.status === "success") return status;
if (status.status === "stucked" || status.status === "reverted") {
//throw new Error(`Swap ${status.status}: ${status.error ?? "see explorer"}`);
}
await new Promise((r) => setTimeout(r, 5000));
}
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🟠 High | 🐛 Logic Bug | Auto Fixed ✅
Adds a timeout guard using Date.now() to track elapsed time
After 20 minutes (1200000 milliseconds) without a definitive status, the function throws an error instead of polling indefinitely.

Suggested change
export async function waitForSymbiosisSwap(sourceChainId: number, txHash: string) {
while (true) {
const res = await fetch(
`${SYMBIOSIS_API}/v2/tx/${sourceChainId}/${txHash}`,
);
const status = await res.json();
// status.status is one of: "pending", "success", "stucked", "reverted"
if (status.status === "success") return status;
if (status.status === "stucked" || status.status === "reverted") {
//throw new Error(`Swap ${status.status}: ${status.error ?? "see explorer"}`);
}
await new Promise((r) => setTimeout(r, 5000));
}
}
export async function waitForSymbiosisSwap(sourceChainId: number, txHash: string) {
const start = Date.now();
while (true) {
const res = await fetch(
`${SYMBIOSIS_API}/v2/tx/${sourceChainId}/${txHash}`,
);
const status = await res.json();
// status.status is one of: "pending", "success", "stucked", "reverted"
if (status.status === "success") return status;
if (status.status === "stucked" || status.status === "reverted") {
throw new Error(`Swap ${status.status}: ${status.error ?? "see explorer"}`);
}
if (Date.now() - start > 1200000) {
throw new Error("Polling timed out after 20 minutes");
}
await new Promise((r) => setTimeout(r, 5000));
}
}

Comment on lines +740 to +743
const res = await fetch(
`https://api.symbiosis.finance/crosschain/v2/tx/${sourceChainId}/${txHash}`,
);
const status = res.json();

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🟠 High | 🐛 Logic Bug | Auto Fixed ✅
Awaits the .json() Promise so status holds the parsed response object, allowing the conditional checks on status.status to work correctly.

Suggested change
const res = await fetch(
`https://api.symbiosis.finance/crosschain/v2/tx/${sourceChainId}/${txHash}`,
);
const status = res.json();
const res = await fetch(
`https://api.symbiosis.finance/crosschain/v2/tx/${sourceChainId}/${txHash}`,
);
const status = await res.json();

Comment on lines +793 to +794
slippage: 250,
deadline: Date.now() + 1800,

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🟠 High | 🐛 Logic Bug | Auto Fixed ✅
Converts Date.now() (milliseconds) to Unix seconds before adding the offset, matching the deadline format expected by the Symbiosis SDK.

Suggested change
slippage: 250,
deadline: Date.now() + 1800,
slippage: 250,
deadline: Math.floor(Date.now() / 1000) + 1800,

Comment on lines +866 to +869
fetchOnce();
if (!paused) {
intervalRef.current = setInterval(fetchOnce, 30);
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🟠 High | 🐛 Logic Bug | Auto Fixed ✅
Changes the interval from 30ms to 30000ms (30 seconds) so quotes refresh at the documented rate without overwhelming the API.

Suggested change
fetchOnce();
if (!paused) {
intervalRef.current = setInterval(fetchOnce, 30);
}
fetchOnce();
if (!paused) {
intervalRef.current = setInterval(fetchOnce, 30000);
}

if (!paused) {
intervalRef.current = setInterval(fetchOnce, 30);
}
return () => clearInterval(intervalRef);

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🟠 High | 🐛 Logic Bug | Auto Fixed ✅
Accesses the actual interval ID stored in the Ref object's .current property before clearing it
Prevents memory leaks and orphaned intervals.

Suggested change
return () => clearInterval(intervalRef);
return () => clearInterval(intervalRef.current);

description: "Integrate Symbiosis Finance into your Rootstock dApp to enable cross-chain swaps between Rootstock and 30+ EVM and non-EVM networks (including native Bitcoin) using the Symbiosis JS SDK or REST API."
---

[Symbiosis Finance](https://symbiosis.finance/) is a cross-chain AMM DEX that aggregates liquidity from L1s, L2s, EVM, and non-EVM networks. Rootstock is natively integrated, which means any token tradable on a DEX in any supported network can be swapped into RBTC, rUSDT, or any Rootstock token, and vice versa, in a single user action. Symbiosis also supports BTC ↔ Rootstock routes through its BTC Fee Collector deployed on Rootstock.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

⚠️ Medium | 🎨 Rootstock.607-Robotics, Rootstock.602-Rootstock-product-names, Rootstock.600-Rootstock-names-versions | Auto Fixed ✅
Deterministic autofix: replaced 'RBTC' with 'rBTC' on line 9 per the finding's 'use X instead of Y' directive
This skeleton was generated by the orchestrator's deterministic fallback and should be verified by the human reviewer.

Suggested change
[Symbiosis Finance](https://symbiosis.finance/) is a cross-chain AMM DEX that aggregates liquidity from L1s, L2s, EVM, and non-EVM networks. Rootstock is natively integrated, which means any token tradable on a DEX in any supported network can be swapped into RBTC, rUSDT, or any Rootstock token, and vice versa, in a single user action. Symbiosis also supports BTC ↔ Rootstock routes through its BTC Fee Collector deployed on Rootstock.
[Symbiosis Finance](https://symbiosis.finance/) is a cross-chain AMM DEX that aggregates liquidity from L1s, L2s, EVM, and non-EVM networks. Rootstock is natively integrated, which means any token tradable on a DEX in any supported network can be swapped into rBTC, rUSDT, or any Rootstock token, and vice versa, in a single user action. Symbiosis also supports BTC ↔ Rootstock routes through its BTC Fee Collector deployed on Rootstock.

@ahsan-javaiid ahsan-javaiid left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

PR Review Report (continued — inline comments part 2/4)

Comments split across multiple reviews to stay under GitHub's per-request limits.


### Step 2: Fetch a Quote (`/v2/quote`)

`/v2/quote` returns the best route and calldata for any-to-any swaps except `BTC → Any`. The example below quotes 25 USDC on Arbitrum to native RBTC on Rootstock.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

⚠️ Medium | 🎨 Rootstock.600-Rootstock-names-versions, Rootstock.602-Rootstock-product-names | Auto Fixed ✅
Deterministic autofix: replaced 'RBTC' with 'rBTC' on line 71 per the finding's 'use X instead of Y' directive
This skeleton was generated by the orchestrator's deterministic fallback and should be verified by the human reviewer.

Suggested change
`/v2/quote` returns the best route and calldata for any-to-any swaps except `BTC → Any`. The example below quotes 25 USDC on Arbitrum to native RBTC on Rootstock.
`/v2/quote` returns the best route and calldata for any-to-any swaps except `BTC → Any`. The example below quotes 25 USDC on Arbitrum to native rBTC on Rootstock.


```ts
// lib/symbiosis-quote.ts
const SYMBIOSIS_API = "https://api.symbiosis.finance//crosschain";

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

⚠️ Medium | 🐛 Logic Bug | Auto Fixed ✅
Removes the extra slash so the URL resolves correctly to the Symbiosis API endpoint.

Suggested change
const SYMBIOSIS_API = "https://api.symbiosis.finance//crosschain";
const SYMBIOSIS_API = "https://api.symbiosis.finance/crosschain";

Comment on lines +185 to +186
//throw new Error(`Swap ${status.status}: ${status.error ?? "see explorer"}`);
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

⚠️ Medium | 🐛 Logic Bug | Auto Fixed ✅
Uncommenting the throw allows the function to exit the infinite loop and signal a failure when the swap is stuck or reverted, rather than polling forever.

Suggested change
//throw new Error(`Swap ${status.status}: ${status.error ?? "see explorer"}`);
}
throw new Error(`Swap ${status.status}: ${status.error ?? "see explorer"}`);
}

tokenAmountIn: {
chainId: 3652501241, // Symbiosis BTC chain identifier
address: "0x0000000000000000000000000000000000000000",
amount: "100000", // 0.001 BTC, 8 decimals

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

⚠️ Medium | 📝 Doc Correctness | Auto Fix not Applied
Variables userBtcAddress and userRskAddress are used but never defined in the snippet.
Why it matters: The snippet uses userBtcAddress and userRskAddress in the request body without defining or explaining them in the code. A developer copying this snippet will encounter a ReferenceError at runtime. Recommendation: Define these variables before the fetch call, e.g., const userBtcAddress = "user's Bitcoin address"; const userRskAddress = "user's Rootstock address"; OR add prose above the snippet explaining that these should be replaced with the user's actual wallet addresses.


### Initialize and Quote a Cross-Chain Swap

The example below quotes **USDT on BNB Chain → RBTC on Rootstock** and signs the returned `transactionRequest` with ethers.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

⚠️ Medium | 🎨 Rootstock.600-Rootstock-names-versions, Rootstock.602-Rootstock-product-names | Auto Fixed ✅
Deterministic autofix: replaced 'RBTC' with 'rBTC' on line 254 per the finding's 'use X instead of Y' directive
This skeleton was generated by the orchestrator's deterministic fallback and should be verified by the human reviewer.

Suggested change
The example below quotes **USDT on BNB Chain → RBTC on Rootstock** and signs the returned `transactionRequest` with ethers.
The example below quotes **USDT on BNB Chain → rBTC on Rootstock** and signs the returned `transactionRequest` with ethers.


A Symbiosis cross-chain swap is made of up to three legs:

- **(A) Source-chain on-chain swap** — optional, when the source token is not the transit token used to leave the chain (typically USDC, USDT, WETH, or WBTC).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🔵 Nitpick | 🎨 Rootstock.607-Robotics, Rootstock.006-Contractions-forbidden | Auto Fixed ✅
Deterministic autofix: replaced ' — ' with ', ' on line 45 per the finding's 'use X instead of Y' directive
This skeleton was generated by the orchestrator's deterministic fallback and should be verified by the human reviewer.

Suggested change
- **(A) Source-chain on-chain swap** optional, when the source token is not the transit token used to leave the chain (typically USDC, USDT, WETH, or WBTC).
- **(A) Source-chain on-chain swap**, optional, when the source token is not the transit token used to leave the chain (typically USDC, USDT, WETH, or WBTC).

A Symbiosis cross-chain swap is made of up to three legs:

- **(A) Source-chain on-chain swap** — optional, when the source token is not the transit token used to leave the chain (typically USDC, USDT, WETH, or WBTC).
- **(B) Host-chain swap** — always performed on the Symbiosis host chain between synthetic sTokens (e.g. `sUSDC` → `sUSDC`).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🔵 Nitpick | 🎨 Rootstock.607-Robotics | Auto Fixed ✅
Deterministic autofix: replaced ' — ' with ', ' on line 46 per the finding's 'use X instead of Y' directive
This skeleton was generated by the orchestrator's deterministic fallback and should be verified by the human reviewer.

Suggested change
- **(B) Host-chain swap** always performed on the Symbiosis host chain between synthetic sTokens (e.g. `sUSDC``sUSDC`).
- **(B) Host-chain swap**, always performed on the Symbiosis host chain between synthetic sTokens (e.g. `sUSDC``sUSDC`).


- **(A) Source-chain on-chain swap** — optional, when the source token is not the transit token used to leave the chain (typically USDC, USDT, WETH, or WBTC).
- **(B) Host-chain swap** — always performed on the Symbiosis host chain between synthetic sTokens (e.g. `sUSDC` → `sUSDC`).
- **(C) Destination-chain on-chain swap** — optional, when the destination token is not the transit token.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🔵 Nitpick | 🎨 Rootstock.607-Robotics, Rootstock.006-Contractions-forbidden | Auto Fixed ✅
Deterministic autofix: replaced ' — ' with ', ' on line 47 per the finding's 'use X instead of Y' directive
This skeleton was generated by the orchestrator's deterministic fallback and should be verified by the human reviewer.

Suggested change
- **(C) Destination-chain on-chain swap** optional, when the destination token is not the transit token.
- **(C) Destination-chain on-chain swap**, optional, when the destination token is not the transit token.

- **(B) Host-chain swap** — always performed on the Symbiosis host chain between synthetic sTokens (e.g. `sUSDC` → `sUSDC`).
- **(C) Destination-chain on-chain swap** — optional, when the destination token is not the transit token.

The user signs one transaction on the source chain. Symbiosis Relayers and (where deployed) the Solver service finalize legs (B) and (C) automatically. The slippage tolerance the user picks is distributed across these legs — the host leg always reserves at most 0.2%. Refer to [Slippage Tolerance Distribution](https://docs.symbiosis.finance/developer-tools/symbiosis-api/slippage-tolerance-distribution-in-cross-chain-swaps) for the exact formula.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🔵 Nitpick | 🎨 Rootstock.607-Robotics | Auto Fixed ✅
Deterministic autofix: replaced ' — ' with ', ' on line 49 per the finding's 'use X instead of Y' directive
This skeleton was generated by the orchestrator's deterministic fallback and should be verified by the human reviewer.

Suggested change
The user signs one transaction on the source chain. Symbiosis Relayers and (where deployed) the Solver service finalize legs (B) and (C) automatically. The slippage tolerance the user picks is distributed across these legs the host leg always reserves at most 0.2%. Refer to [Slippage Tolerance Distribution](https://docs.symbiosis.finance/developer-tools/symbiosis-api/slippage-tolerance-distribution-in-cross-chain-swaps) for the exact formula.
The user signs one transaction on the source chain. Symbiosis Relayers and (where deployed) the Solver service finalize legs (B) and (C) automatically. The slippage tolerance the user picks is distributed across these legs, the host leg always reserves at most 0.2%. Refer to [Slippage Tolerance Distribution](https://docs.symbiosis.finance/developer-tools/symbiosis-api/slippage-tolerance-distribution-in-cross-chain-swaps) for the exact formula.


## Integration 1: The Symbiosis REST API

The REST API wraps the SDK and is backward-compatible across SDK upgrades. This is the recommended path for production. The base URL for mainnet is:

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🔵 Nitpick | 🎨 Rootstock.005-Industry-product-names | Auto Fixed ✅
Deterministic autofix: replaced 'mainnet' with 'Mainnet' on line 53 per the finding's 'use X instead of Y' directive
This skeleton was generated by the orchestrator's deterministic fallback and should be verified by the human reviewer.

Suggested change
The REST API wraps the SDK and is backward-compatible across SDK upgrades. This is the recommended path for production. The base URL for mainnet is:
The REST API wraps the SDK and is backward-compatible across SDK upgrades. This is the recommended path for production. The base URL for Mainnet is:

@ahsan-javaiid ahsan-javaiid left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

PR Review Report (continued — inline comments part 3/4)

Comments split across multiple reviews to stay under GitHub's per-request limits.


The REST API wraps the SDK and is backward-compatible across SDK upgrades. This is the recommended path for production. The base URL for mainnet is:

```

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🔵 Nitpick | 🎨 Rootstock.016-No-inline-comments | Auto Fix not Applied
Avoid inline comments in code blocks.


Use `/v1/chains` to confirm Rootstock (Chain ID `30`) is in the supported set and to discover any new networks Symbiosis adds.

```bash

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🔵 Nitpick | 🎨 Rootstock.016-No-inline-comments | Auto Fix not Applied
Avoid inline comments in code blocks.


`/v2/quote` returns the best route and calldata for any-to-any swaps except `BTC → Any`. The example below quotes 25 USDC on Arbitrum to native RBTC on Rootstock.

```ts

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🔵 Nitpick | 🎨 Rootstock.016-No-inline-comments | Auto Fix not Applied
Avoid inline comments in code blocks.

The two fields you must use:

- `approveTo` — the **`metaRouterGateway`** address. Approve the user's ERC-20 to **this** address, not to `tx.to`.
- `tx` — sign and broadcast exactly as returned. Do not mutate the `data` field.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🔵 Nitpick | 🎨 Rootstock.006-Contractions-forbidden | Auto Fix not Applied
Consider using 'don't' instead of 'Do not'

- `approveTo` — the **`metaRouterGateway`** address. Approve the user's ERC-20 to **this** address, not to `tx.to`.
- `tx` — sign and broadcast exactly as returned. Do not mutate the `data` field.

### Step 3: Approve, Sign, and Send

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🔵 Nitpick | 🎨 Rootstock.607-Robotics | Auto Fix not Applied
AI-style pattern detected
Consider using 'specific list' instead of 'Approve, Sign, and Send'.


Outgoing-BTC routes settle through Symbiosis' BTC fee collector on Rootstock and bridge to native BTC via ThorChain or Chainflip (whichever produces a better route at execution time). See [Symbiosis as Interchain Communication Protocol](https://docs.symbiosis.finance/main-concepts/symbiosis-as-interchain-communication-protocol) for the routing diagram.

## Additional Patterns

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🔵 Nitpick | 🎨 Rootstock.011-Headings-not-followed-by-heading | Auto Fix not Applied
Avoid stacked headings
There should be content for each heading.


A reusable React hook for fetching Symbiosis quotes from a Wagmi-based dApp. Pulls the connected account from `useAccount`, debounces the input, and exposes loading and error state to the component.

```tsx

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🔵 Nitpick | 🎨 Rootstock.016-No-inline-comments | Auto Fix not Applied
Avoid inline comments in code blocks.


If your stack uses viem instead of ethers, use `walletClient.sendTransaction` with the raw calldata returned by the API. The example below executes the quote returned from `useSymbiosisQuote`.

```ts

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🔵 Nitpick | 🎨 Rootstock.016-No-inline-comments | Auto Fix not Applied
Avoid inline comments in code blocks.


A minimal Python client for quoting and submitting a swap with `requests` + `web3.py`. Convenient for cron jobs or settlement scripts.

```python

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🔵 Nitpick | 🎨 Rootstock.016-No-inline-comments | Auto Fix not Applied
Avoid inline comments in code blocks.


Symbiosis can forward arbitrary calldata to a contract on Rootstock after the bridge settles, similar to LI.FI's Composer. Use this to deposit bridged USDC straight into a yield vault without a second user signature.

```ts

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🔵 Nitpick | 🎨 Rootstock.016-No-inline-comments | Auto Fix not Applied
Avoid inline comments in code blocks.

@ahsan-javaiid ahsan-javaiid left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

PR Review Report (continued — inline comments part 4/4)

Comments split across multiple reviews to stay under GitHub's per-request limits.


Useful when you want to display the best entry point for each of a user's holdings on Arbitrum, side-by-side. Quote each token in parallel, sort by `amountOut`, and surface the top three.

```ts

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🔵 Nitpick | 🎨 Rootstock.016-No-inline-comments | Auto Fix not Applied
Avoid inline comments in code blocks.


`/v2/tx/{chainId}/{txHash}` is cheap to call but you should still cap your poll frequency. The helper below backs off exponentially up to 60 seconds and gives up after 20 minutes.

```ts

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🔵 Nitpick | 🎨 Rootstock.016-No-inline-comments | Auto Fix not Applied
Avoid inline comments in code blocks.


A common Rootstock-outbound flow: convert RBTC held on Rootstock into USDT on BNB Chain to pay off-ramp invoices. Uses the SDK with an explicit deadline guard.

```ts

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🔵 Nitpick | 🎨 Rootstock.016-No-inline-comments | Auto Fix not Applied
Avoid inline comments in code blocks.


If a user lingers on the review screen, the calldata you fetched from `/v2/quote` will go stale. Refresh the quote on a 30-second interval and stop when the user clicks Swap.

```ts

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🔵 Nitpick | 🎨 Rootstock.016-No-inline-comments | Auto Fix not Applied
Avoid inline comments in code blocks.


If you want to monetize swaps through your integration, contact the Symbiosis team to configure a partner-fee model (percentage, fixed, or hybrid). Once registered, include your `partnerAddress` in the API/SDK request:

```ts

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🔵 Nitpick | 🎨 Rootstock.016-No-inline-comments | Auto Fix not Applied
Avoid inline comments in code blocks.


**`waitForComplete` never resolves** — Most often a host-leg failure. Call `symbiosis.getPendingRequests(address)` and use `newRevertPending(request).revert()` to refund the user.

**Rootstock RPC rate limits during status polling** — Use a dedicated endpoint. The public Rootstock RPC is sufficient for low-volume tests; production traffic should use [a Rootstock RPC provider](/dev-tools/node-rpc/) such as Alchemy, dRPC, GetBlock, or NowNodes.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🔵 Nitpick | 🎨 Rootstock.607-Robotics | Auto Fixed ✅
Deterministic autofix: replaced ' — ' with ', ' on line 925 per the finding's 'use X instead of Y' directive
This skeleton was generated by the orchestrator's deterministic fallback and should be verified by the human reviewer.

Suggested change
**Rootstock RPC rate limits during status polling** Use a dedicated endpoint. The public Rootstock RPC is sufficient for low-volume tests; production traffic should use [a Rootstock RPC provider](/dev-tools/node-rpc/) such as Alchemy, dRPC, GetBlock, or NowNodes.
**Rootstock RPC rate limits during status polling**, Use a dedicated endpoint. The public Rootstock RPC is sufficient for low-volume tests; production traffic should use [a Rootstock RPC provider](/dev-tools/node-rpc/) such as Alchemy, dRPC, GetBlock, or NowNodes.

| Resource | URL |
|---|---|
| Symbiosis web app | [app.symbiosis.finance/swap](https://app.symbiosis.finance/swap) |
| Symbiosis Explorer | [explorer.symbiosis.finance](https://explorer.symbiosis.finance/transactions) |

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🔵 Nitpick | 🎨 Rootstock.605-Word-list | Auto Fixed ✅
Deterministic autofix: replaced 'explorer' with 'Rootstock Explorer' on line 932 per the finding's 'use X instead of Y' directive
This skeleton was generated by the orchestrator's deterministic fallback and should be verified by the human reviewer.

Suggested change
| Symbiosis Explorer | [explorer.symbiosis.finance](https://explorer.symbiosis.finance/transactions) |
| Symbiosis Explorer | [Rootstock Explorer.symbiosis.finance](https://explorer.symbiosis.finance/transactions) |

|---|---|
| Symbiosis web app | [app.symbiosis.finance/swap](https://app.symbiosis.finance/swap) |
| Symbiosis Explorer | [explorer.symbiosis.finance](https://explorer.symbiosis.finance/transactions) |
| API base URL (mainnet) | `https://api.symbiosis.finance/crosschain` |

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🔵 Nitpick | 🎨 Rootstock.005-Industry-product-names | Auto Fixed ✅
Deterministic autofix: replaced 'mainnet' with 'Mainnet' on line 933 per the finding's 'use X instead of Y' directive
This skeleton was generated by the orchestrator's deterministic fallback and should be verified by the human reviewer.

Suggested change
| API base URL (mainnet) | `https://api.symbiosis.finance/crosschain` |
| API base URL (Mainnet) | `https://api.symbiosis.finance/crosschain` |

| JS SDK package | [`symbiosis-js-sdk`](https://www.npmjs.com/package/symbiosis-js-sdk) |
| JS SDK source | [github.com/symbiosis-finance/js-sdk](https://github.com/symbiosis-finance/js-sdk) |
| Mainnet contract config | [`src/crosschain/config/mainnet.ts`](https://github.com/symbiosis-finance/js-sdk/blob/main/src/crosschain/config/mainnet.ts) |
| Partner dashboard | [explorer.symbiosis.finance/partners](https://explorer.symbiosis.finance/partners) |

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🔵 Nitpick | 🎨 Rootstock.605-Word-list | Auto Fixed ✅
Deterministic autofix: replaced 'explorer' with 'Rootstock Explorer' on line 938 per the finding's 'use X instead of Y' directive
This skeleton was generated by the orchestrator's deterministic fallback and should be verified by the human reviewer.

Suggested change
| Partner dashboard | [explorer.symbiosis.finance/partners](https://explorer.symbiosis.finance/partners) |
| Partner dashboard | [Rootstock Explorer.symbiosis.finance/partners](https://explorer.symbiosis.finance/partners) |


## Next Steps

- Quote a sample route from your target source chain to Rootstock via the [Swagger API explorer](https://api.symbiosis.finance/crosschain/docs/) before writing any code.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🔵 Nitpick | 🎨 Rootstock.605-Word-list | Auto Fixed ✅
Deterministic autofix: replaced 'explorer' with 'Rootstock Explorer' on line 943 per the finding's 'use X instead of Y' directive
This skeleton was generated by the orchestrator's deterministic fallback and should be verified by the human reviewer.

Suggested change
- Quote a sample route from your target source chain to Rootstock via the [Swagger API explorer](https://api.symbiosis.finance/crosschain/docs/) before writing any code.
- Quote a sample route from your target source chain to Rootstock via the [Swagger API Rootstock Explorer](https://api.symbiosis.finance/crosschain/docs/) before writing any code.

Applied autofix suggestions emitted by the Rootstock DevPortal Review Agent.
@ahsan-javaiid ahsan-javaiid changed the title [Only Test] Add Symbiosis Swaps Add Symbiosis Swaps Jul 2, 2026
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