Add Symbiosis Swaps#518
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.OpenSSF Scorecard
Scanned Files |
There was a problem hiding this comment.
🤖 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 Guidedocs/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 Indexdocs/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 | ❌ 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/
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 address0xaf88d065e77c8cC2239327C5EDb3A432268e5831... 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: ReplacetoChainId: 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 totx.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 lineif 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 lineconst 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 linedeadline: 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: ThesetInterval(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 bycontract.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 value1.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 functionpickBestSourceForRbtc 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 toclearInterval(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 URLhttps://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: Thethrow 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: ThebridgeUsdtToRbtc 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 nameslippage, 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 usesuserBtcAddress 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 conditionallowance > 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
- PR: #518
- Changed files:
docs/06-use-cases/index.md,docs/06-use-cases/interoperability/integrate-symbiosis.md
Generated by Devportal Review Agent · v0.0.7+b4935ef+2026-06-24
| @@ -0,0 +1,946 @@ | |||
| --- | |||
There was a problem hiding this comment.
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/quotesis inconsistent with the documented/v2/quoteendpoint 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 ofquote.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;statusis 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, notintervalRef. (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_IDis used but not defined in this file. (line 356 ·⚠️ Medium · 📝 Doc Correctness) - ✅ Python field name is misspelled as
slipageinstead ofslippage. (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
userBtcAddressanduserRskAddressare used but never defined in the snippet. (line 209 ·⚠️ Medium · 📝 Doc Correctness) - ⬜ The
writeContractcall is not awaited, leavingapproveHashas 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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
🟠 High | 🐛 Logic Bug | Auto Fixed ✅
Removes the trailing ellipsis so the address is a valid 42-character Ethereum address.
| address: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831...", // native USDC | |
| address: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", // native USDC |
| signer, | ||
| ); | ||
| const allowance = await usdc.allowance(userAddress, quote.approveTo); | ||
| if (allowance < BigInt(quote.tokenAmountIn.amount)) { |
There was a problem hiding this comment.
🟠 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.
| if (allowance < BigInt(quote.tokenAmountIn.amount)) { | |
| if (allowance.lt(quote.tokenAmountIn.amount)) { |
| 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)); | ||
| } | ||
| } |
There was a problem hiding this comment.
🟠 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.
| 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)); | |
| } | |
| } |
| const res = await fetch( | ||
| `https://api.symbiosis.finance/crosschain/v2/tx/${sourceChainId}/${txHash}`, | ||
| ); | ||
| const status = res.json(); |
There was a problem hiding this comment.
🟠 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.
| 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(); |
| slippage: 250, | ||
| deadline: Date.now() + 1800, |
There was a problem hiding this comment.
🟠 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.
| slippage: 250, | |
| deadline: Date.now() + 1800, | |
| slippage: 250, | |
| deadline: Math.floor(Date.now() / 1000) + 1800, |
| fetchOnce(); | ||
| if (!paused) { | ||
| intervalRef.current = setInterval(fetchOnce, 30); | ||
| } |
There was a problem hiding this comment.
🟠 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.
| 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); |
There was a problem hiding this comment.
🟠 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.
| 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. |
There was a problem hiding this comment.
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.
| [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
left a comment
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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.
| `/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"; |
There was a problem hiding this comment.
Removes the extra slash so the URL resolves correctly to the Symbiosis API endpoint.
| const SYMBIOSIS_API = "https://api.symbiosis.finance//crosschain"; | |
| const SYMBIOSIS_API = "https://api.symbiosis.finance/crosschain"; |
| //throw new Error(`Swap ${status.status}: ${status.error ?? "see explorer"}`); | ||
| } |
There was a problem hiding this comment.
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.
| //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 |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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.
| 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). |
There was a problem hiding this comment.
🔵 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.
| - **(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`). |
There was a problem hiding this comment.
🔵 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.
| - **(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. |
There was a problem hiding this comment.
🔵 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.
| - **(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. |
There was a problem hiding this comment.
🔵 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.
| 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: |
There was a problem hiding this comment.
🔵 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.
| 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
left a comment
There was a problem hiding this comment.
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: | ||
|
|
||
| ``` |
There was a problem hiding this comment.
🔵 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 |
There was a problem hiding this comment.
🔵 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 |
There was a problem hiding this comment.
🔵 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. |
There was a problem hiding this comment.
🔵 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 |
There was a problem hiding this comment.
🔵 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 |
There was a problem hiding this comment.
🔵 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 |
There was a problem hiding this comment.
🔵 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 |
There was a problem hiding this comment.
🔵 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 |
There was a problem hiding this comment.
🔵 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 |
There was a problem hiding this comment.
🔵 Nitpick | 🎨 Rootstock.016-No-inline-comments | Auto Fix not Applied
Avoid inline comments in code blocks.
ahsan-javaiid
left a comment
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
🔵 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 |
There was a problem hiding this comment.
🔵 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 |
There was a problem hiding this comment.
🔵 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 |
There was a problem hiding this comment.
🔵 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 |
There was a problem hiding this comment.
🔵 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. |
There was a problem hiding this comment.
🔵 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.
| **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) | |
There was a problem hiding this comment.
🔵 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.
| | 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` | |
There was a problem hiding this comment.
🔵 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.
| | 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) | |
There was a problem hiding this comment.
🔵 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.
| | 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. |
There was a problem hiding this comment.
🔵 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.
| - 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.
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:
symbiosis-js-sdk— direct protocol access from a TypeScript/Node app