Skip to content

Add tectonic adapter - #106

Open
DeveloperAmrit wants to merge 5 commits into
DjedAlliance:mainfrom
DeveloperAmrit:add-tectonic-adapter
Open

Add tectonic adapter#106
DeveloperAmrit wants to merge 5 commits into
DjedAlliance:mainfrom
DeveloperAmrit:add-tectonic-adapter

Conversation

@DeveloperAmrit

@DeveloperAmrit DeveloperAmrit commented Jul 27, 2026

Copy link
Copy Markdown
Member

Addressed Issues:

Screenshots/Recordings:

tectonic_adapter_1.mp4

Additional Notes:

StablePay is moving from Djed to Tectonic. Tectonic isn't deployed anywhere yet, so this adds the integration layer plus a local harness to develop against, without touching the existing Djed paths.

Changes

  • tectonic-sdk/ — new package. Pure pricing math (pricing.js) plus a viem client (tectonic.js). Ships source, no build step.

  • stablepay-sdk/src/core/adapters/ — ProtocolAdapter interface with TectonicAdapter and DjedAdapter. Transaction.js now delegates to whichever the network config names, keeping its existing method names so the widget barely changed.

  • utils/config.js — networks gain a protocol field. It defaults to "djed", so every existing entry behaves exactly as before.

  • tectonic-local/ — Foundry project with a patched copy of the upstream contract, a mock oracle, a deploy script and 21 tests. The upstream draft can't currently be deployed and used (its first mint() reverts), so this exists purely to unblock development. It gets deleted once there's a real deployment.

Checklist

  • My PR addresses a single issue, fixes a single bug or makes a single improvement.
  • My code follows the project's code style and conventions
  • If applicable, I have made corresponding changes or additions to the documentation
  • If applicable, I have made corresponding changes or additions to tests
  • My changes generate no new warnings or errors
  • I have joined the Discord server and I will share a link to this PR with the project maintainers there
  • I have read the Contribution Guidelines
  • Once I submit my PR, CodeRabbit AI will automatically review it and I will address CodeRabbit's comments.

AI Usage Disclosure

Check one of the checkboxes below:

  • This PR does not contain AI-generated code at all.
  • This PR contains AI-generated code. I have read the AI Usage Policy and this PR complies with this policy. I have tested the code locally and I am responsible for it.

I have used the following AI models and tools: Claude

⚠️ AI Notice - Important!

We encourage contributors to use AI tools responsibly when creating Pull Requests. While AI can be a valuable aid, it is essential to ensure that your contributions meet the task requirements, build successfully, include relevant tests, and pass all linters. Submissions that do not meet these standards may be closed without warning to maintain the quality and integrity of the project. Please take the time to understand the changes you are proposing and their impact. AI slop is strongly discouraged and may lead to banning and blocking. Do not spam our repos with AI slop.

Summary by CodeRabbit

  • New Features

    • Added support for Tectonic stablecoin payments alongside existing networks.
    • Added protocol-aware quotes, transfers, balance details, reserve-health warnings, and clearer payment receipts.
    • Added local Tectonic development support, including network configuration and deployment tooling.
    • Introduced a standalone Tectonic SDK with pricing, quoting, transaction-building, and balance utilities.
  • Bug Fixes

    • Improved payment calculations and rounding safeguards to help prevent underpayment.
    • Improved stability-fee handling and reserve-ratio behavior in local protocol deployments.
  • Documentation

    • Added configuration guidance and explanatory comments for local development and package usage.

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@DeveloperAmrit, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 54 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0a999c67-f191-433a-a02f-491e8c48f739

📥 Commits

Reviewing files that changed from the base of the PR and between 8d20e75 and 288a1a1.

⛔ Files ignored due to path filters (3)
  • stablepay-sdk/dist/esm/index.js is excluded by !**/dist/**
  • stablepay-sdk/dist/umd/index.js is excluded by !**/dist/**
  • stablepay-sdk/dist/umd/index.js.map is excluded by !**/dist/**, !**/*.map
📒 Files selected for processing (9)
  • stablepay-sdk/src/core/adapters/TectonicAdapter.js
  • stablepay-sdk/src/utils/config.js
  • stablepay-sdk/src/widget/TransactionReview.jsx
  • tectonic-local/script/DeployLocal.s.sol
  • tectonic-local/src/Coin.sol
  • tectonic-local/src/Tectonic.sol
  • tectonic-local/test/Tectonic.t.sol
  • tectonic-sdk/src/pricing.js
  • tectonic-sdk/test/pricing.test.js
📝 Walkthrough

Walkthrough

The PR adds a local Tectonic contract environment and SDK, introduces protocol adapters into StablePay, updates widget transaction flows for protocol-specific quoting and transfers, and adds local-network example support, package exports, tests, deployment tooling, and repository ignore rules.

Changes

Tectonic protocol integration

Layer / File(s) Summary
Local Tectonic contracts and deployment
tectonic-local/src/*, tectonic-local/script/*, tectonic-local/test/*, tectonic-local/foundry.toml
Adds Tectonic, Coin, MockOracle, deployment automation, reserve and fee mechanics, forced redemptions, and Forge regression tests.
Tectonic SDK client and pricing
tectonic-sdk/src/*, tectonic-sdk/test/*, tectonic-sdk/scripts/*, tectonic-sdk/package.json
Adds ABI definitions, fixed-point pricing helpers, TectonicClient, transaction builders, reserve diagnostics, conversion utilities, unit tests, and a local smoke test.
Protocol adapters and StablePay wiring
stablepay-sdk/src/core/*, stablepay-sdk/src/utils/config.js, stablepay-sdk/src/contexts/chains.js, stablepay-sdk/src/index.js
Adds the adapter interface and Djed/Tectonic implementations, selects adapters from network configuration, supports tectonic-local, and delegates Transaction behavior through adapters.
Widget and local example flow
stablepay-sdk/src/widget/*, stablepay-sdk/example/src/App.jsx, stablepay-sdk/example/vite.config.js
Uses adapter-backed quotes and transfer builders, displays protocol warnings and paid/received amounts, and adds local Tectonic example configuration.
Repository ignore rules
.gitignore, stablepay-sdk/.gitignore
Adds monorepo and SDK ignore patterns for dependencies, secrets, generated output, coverage, and editor or OS files.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

Suggested reviewers: zahnentferner

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main change: adding Tectonic adapter support, though the PR also includes SDK and local-dev updates.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (14)
stablepay-sdk/src/contexts/chains.js (2)

142-155: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Reuse localChain.rpcUrls.default.http instead of re-literalizing the URL.

The sepolia branch above derives rpcUrls from the chain object; hardcoding http://127.0.0.1:8545 a second time means a port change must be made in two places.

♻️ Proposed refactor
-        rpcUrls: ['http://127.0.0.1:8545'],
+        rpcUrls: localChain.rpcUrls.default.http,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@stablepay-sdk/src/contexts/chains.js` around lines 142 - 155, Update the
`tectonic-local` branch in the chain configuration to populate `rpcUrls` from
`localChain.rpcUrls.default.http`, matching the existing `sepolia` branch
pattern, and remove the duplicated hardcoded localhost URL.

72-87: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Drop the unused network field from localChain.

Viem 2.21.53 doesn’t use this field for chain operations or type validation, so network: 'localhost' is only custom noise on this defineChain result.

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

In `@stablepay-sdk/src/contexts/chains.js` around lines 72 - 87, Remove the unused
network property from the localChain definition passed to defineChain, leaving
the remaining chain metadata unchanged.
tectonic-local/test/Tectonic.t.sol (2)

345-355: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Consider a regression test for multi-holder forced redemption.

Every forced-redemption test exercises a single holder, so the index-advance behaviour after swap-removal (see tectonic-local/src/Tectonic.sol lines 258-269) is untested. A two- or three-holder case would pin the intended coverage semantics.

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

In `@tectonic-local/test/Tectonic.t.sol` around lines 345 - 355, Add a regression
test alongside test_ForcedRedemptionPaysTheHolderInBasecoin that creates at
least two holders, triggers forceRedemptions, and verifies each expected holder
is redeemed and paid. Exercise the swap-removal path in forceRedemptions so
index advancement is validated across multiple holders, preserving the intended
coverage semantics.

146-161: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Prefer bound() over stacked vm.assume in fuzz tests.

Three vm.assume filters on a uint96 domain (only ~1e12..1e24 of 0..7.9e28 is accepted, then further filtered by required < 500 ether) discard the large majority of inputs and can exhaust max_test_rejects. bound(rawAmount, 1e12, 1e24) keeps every run useful and makes the tested range explicit.

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

In `@tectonic-local/test/Tectonic.t.sol` around lines 146 - 161, Replace the
stacked vm.assume filters in testFuzz_SDK_CostFormulaNeverUnderpaysTheMerchant
with bound() calls for rawAmount and rawPrice, using the intended inclusive
ranges. Preserve the required < 500 ether solvency constraint without excessive
rejection, adjusting the input bounds or setup as needed so fuzz runs remain
valid while covering the explicit tested domain.
stablepay-sdk/src/core/adapters/DjedAdapter.js (2)

31-56: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

getWeb3/getDjedContract sit outside the try/catch.

An unreachable RPC URL throws a raw provider error rather than the friendly, cause-listing message this block was written to produce. Widening the try to cover lines 32-33 makes the diagnostics apply to the most common failure (bad uri).

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

In `@stablepay-sdk/src/core/adapters/DjedAdapter.js` around lines 31 - 56, Widen
the try/catch in init() to include the getWeb3(this.config.uri) and
getDjedContract(this.web3, this.address) calls, so RPC connection and contract
initialization failures use the existing friendly diagnostic message. Keep the
current error details and cause list unchanged.

85-90: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Hardcoded UI fee beneficiary as a silent fallback.

0x0232...9839 is a magic address embedded in adapter logic; if uiFeeAddress is missing from a network config, fees silently go to it. Move it to a named exported constant (or require it explicitly per network) so the default is auditable.

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

In `@stablepay-sdk/src/core/adapters/DjedAdapter.js` around lines 85 - 90, Replace
the inline UI fee address fallback in DjedAdapter.buildMintTx with a named
exported constant, and reference that constant when uiFeeAddress is absent. Keep
the existing configured-address override and transaction construction unchanged,
making the default beneficiary easy to audit.
stablepay-sdk/src/utils/config.js (1)

118-125: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

useLocalTectonic mutates shared module state.

Fine for a dev-only escape hatch, but it makes the registry order-dependent for anything that captured a config reference earlier. Consider returning a derived config object instead of mutating the singleton, or at least documenting that it must be called before widget mount.

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

In `@stablepay-sdk/src/utils/config.js` around lines 118 - 125, Update
useLocalTectonic to return a derived tectonic-local configuration with the
supplied address applied to both tectonicAddress and tokens.stablecoin.address,
without mutating networksConfig or any nested shared objects. Preserve the
existing address validation and returned configuration shape.
stablepay-sdk/src/core/adapters/ProtocolAdapter.js (1)

9-23: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Interface doc omits getWarnings/getEffectiveBalance.

getWarnings() is defined below but not listed in the contract summary, and TectonicAdapter.getEffectiveBalance() has no base declaration at all — callers can't rely on it existing across adapters. Adding a default (e.g. returning the raw balance) would keep the widget protocol-agnostic. Also line 22's sentence is truncated ("an invoice must be.").

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

In `@stablepay-sdk/src/core/adapters/ProtocolAdapter.js` around lines 9 - 23,
Update the ProtocolAdapter contract summary to include getWarnings() and
getEffectiveBalance(), and complete the truncated bigint amount documentation
sentence. Add a base getEffectiveBalance() declaration or default implementation
that returns the raw balance, so all adapters expose the same callable interface
while allowing TectonicAdapter to retain its override.
tectonic-local/script/DeployLocal.s.sol (1)

63-74: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Prefer vm.serializeX / vm.writeJson over hand-rolled JSON concatenation.

Foundry's JSON cheatcodes handle escaping and formatting, and keep the manifest schema in one place. Purely optional for a local dev script.

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

In `@tectonic-local/script/DeployLocal.s.sol` around lines 63 - 74, Replace the
hand-built JSON string in the deployment manifest flow with Foundry’s
vm.serializeX and vm.writeJson cheatcodes, using the existing manifest fields
from the json construction and preserving their names and values. Keep the
output schema and local deployment behavior unchanged while relying on
cheatcodes for formatting and escaping.
tectonic-sdk/test/client.test.js (1)

168-175: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Missing test coverage for buildRedeemTx.

buildTransferTx and buildMintTx are both tested, but buildRedeemTx — a fund-moving path — has no direct test here.

✅ Suggested test
test("buildRedeemTx targets the protocol contract and encodes the receiver", async () => {
  const { client } = makeClient();
  await client.init();
  const tx = client.buildRedeemTx({ from: PAYER, receiver: MERCHANT, amountSC: 5n * D });

  assert.equal(tx.to, ADDRESS);
  assert.equal(tx.value, 0n);
  assert.ok(tx.data.toLowerCase().includes(MERCHANT.slice(2).toLowerCase()), "receiver encoded");
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tectonic-sdk/test/client.test.js` around lines 168 - 175, Add direct test
coverage for client.buildRedeemTx alongside the existing transaction-builder
tests. Initialize the client, build a redemption using PAYER, MERCHANT, and an
amount, then assert it targets ADDRESS, has zero value, and encodes the receiver
address in the transaction data.
tectonic-sdk/src/tectonic.js (3)

199-241: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Hardcoded 18 instead of the BC_DECIMALS constant.

constants.js exports BC_DECIMALS specifically for basecoin decimals, but quoteMint, quotePayment, and quoteRedeem hardcode the literal 18 three times (lines 210, 219, 238) instead of importing and using it. Currently harmless since all supported chains use 18-decimal native tokens, but it defeats the purpose of the constant and is an easy drift point if that assumption ever changes.

♻️ Proposed fix
 import {
   D,
   SC_DECIMALS,
+  BC_DECIMALS,
   GAS_LIMIT_MULTIPLIER_PERCENT,
   RESERVE_HEALTH,
 } from "./constants.js";
@@
-      requiredBCFormatted: fromBaseUnits(requiredBC, 18, 8),
+      requiredBCFormatted: fromBaseUnits(requiredBC, BC_DECIMALS, 8),
@@
-    const value = typeof amountBC === "bigint" ? amountBC : toBaseUnits(amountBC, 18);
+    const value = typeof amountBC === "bigint" ? amountBC : toBaseUnits(amountBC, BC_DECIMALS);
@@
-      payoutBCFormatted: fromBaseUnits(payoutBC, 18, 8),
+      payoutBCFormatted: fromBaseUnits(payoutBC, BC_DECIMALS, 8),
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tectonic-sdk/src/tectonic.js` around lines 199 - 241, Replace the hardcoded
basecoin decimal value in quoteMint, quotePayment, and quoteRedeem with the
imported BC_DECIMALS constant, including both conversion and formatting calls,
while leaving stablecoin decimal handling unchanged.

302-319: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Inconsistent input validation vs. buildMintTx.

buildMintTx validates payer, receiver, and value before building the transaction (lines 263-267), but buildTransferTx and buildRedeemTx encode calldata without checking that from/to/receiver are provided or that amount/amountSC is a positive value. A caller passing undefined/0 here produces a plausible-looking tx object that will fail unpredictably (or send junk calldata) rather than failing fast with a clear error.

♻️ Suggested guard
 buildTransferTx({ from, to, amount }) {
+  if (!from) throw new Error("buildTransferTx: from is required");
+  if (!to) throw new Error("buildTransferTx: to is required");
+  if (typeof amount !== "bigint" || amount <= 0n) {
+    throw new Error("buildTransferTx: amount must be a positive bigint");
+  }
   const data = encodeFunctionData({
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tectonic-sdk/src/tectonic.js` around lines 302 - 319, Align buildTransferTx
and buildRedeemTx with buildMintTx by validating their required addresses and
amounts before calling encodeFunctionData. Ensure from and to are provided for
transfers, from and the effective receiver are provided for redeems, and
amount/amountSC is a positive value; fail fast with the same validation style
and clear errors already used by buildMintTx.

277-293: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Distinguish revert-caused estimateGas failures from transient estimation failures.

With Viem 2.x, revert errors are structured/re-exportable via viem error classes; use that instead of falling back to wallet estimation for all failures. A pre-simulation error for mint() usually means the signed transaction will revert as-is, so surface that to the caller before requesting a signature.

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

In `@tectonic-sdk/src/tectonic.js` around lines 277 - 293, Update the
gas-estimation catch block in the payment transaction flow around
publicClient.estimateGas to identify Viem 2.x revert errors using the
appropriate re-exported Viem error class and propagate those failures to the
caller before requesting a signature. Keep the existing warning and
wallet-estimation fallback only for non-revert estimation failures.
stablepay-sdk/example/src/App.jsx (1)

18-23: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Avoid calling useLocalTectonic from the React hooks lint scope.

This example enables eslint-plugin-react-hooks, and the use* function name is treated as a hook, so StablePay.useLocalTectonic(…) can’t call it safely at module scope. Either rename the exported helper/alias it to a non-hook name in the example, or keep the Tectonic setup behind an explicitly ESLint-disabled setup path.

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

In `@stablepay-sdk/example/src/App.jsx` around lines 18 - 23, Update the Tectonic
initialization around StablePay.useLocalTectonic so it is not treated as a React
hook call at module scope. Prefer using a non-hook exported helper or alias in
the example; otherwise place the call behind an explicitly ESLint-disabled setup
path while preserving the existing conditional TECTONIC_ADDRESS behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@stablepay-sdk/src/utils/config.js`:
- Around line 86-98: Update the tectonic-local configuration’s tectonicAddress
and matching stablecoin address from the zero-address placeholder to null, so
TectonicAdapter’s existing missing-address guard handles uninitialized local
deployments. Preserve useLocalTectonic() as the path that supplies real
addresses.

In `@stablepay-sdk/src/widget/TransactionReview.jsx`:
- Around line 258-269: Use the configured stablecoin symbol as the single source
of truth for the merchant-received value: update receivedSymbol in the
onTransactionComplete payload to use
networkSelector.getSelectedNetworkConfig()?.tokens?.stablecoin?.symbol, matching
the “Merchant Receives” UI row, and retain the existing fallback if needed.

In `@tectonic-local/script/DeployLocal.s.sol`:
- Around line 59-86: Move vm.createDir("deployments", true) into the guarded
manifest-writing flow alongside vm.writeFile, so failures from either operation
are caught and produce the existing warning while deployment continues. Keep the
JSON construction and success/error messages unchanged.

In `@tectonic-local/src/Coin.sol`:
- Line 4: Update the import in Coin.sol to use the configured
`@openzeppelin/contracts` prefix, matching Tectonic.sol. No direct change is
needed in tectonic-local/foundry.toml lines 16-19 because the corrected import
aligns with its existing remapping.

In `@tectonic-local/src/Tectonic.sol`:
- Around line 145-161: Validate constructor inputs before initializing state:
require a non-zero oracleAddress and enforce the documented invariant D <
criticalReserveRatio < safeReserveRatio < 2D using the contract’s existing D
symbol or equivalent denomination. Update the Tectonic constructor so invalid
reserve ratios and oracle addresses revert, preventing deployment of unusable
contracts.
- Around line 258-269: Update the forced-redemption loop so it does not
increment i after _redeem removes a holder and refills that slot via
updateHolder; retain the same index for b > 0, while continuing to advance for
empty holders. Preserve the existing wraparound, iteration limit, gas check, and
holderCount termination behavior.

---

Nitpick comments:
In `@stablepay-sdk/example/src/App.jsx`:
- Around line 18-23: Update the Tectonic initialization around
StablePay.useLocalTectonic so it is not treated as a React hook call at module
scope. Prefer using a non-hook exported helper or alias in the example;
otherwise place the call behind an explicitly ESLint-disabled setup path while
preserving the existing conditional TECTONIC_ADDRESS behavior.

In `@stablepay-sdk/src/contexts/chains.js`:
- Around line 142-155: Update the `tectonic-local` branch in the chain
configuration to populate `rpcUrls` from `localChain.rpcUrls.default.http`,
matching the existing `sepolia` branch pattern, and remove the duplicated
hardcoded localhost URL.
- Around line 72-87: Remove the unused network property from the localChain
definition passed to defineChain, leaving the remaining chain metadata
unchanged.

In `@stablepay-sdk/src/core/adapters/DjedAdapter.js`:
- Around line 31-56: Widen the try/catch in init() to include the
getWeb3(this.config.uri) and getDjedContract(this.web3, this.address) calls, so
RPC connection and contract initialization failures use the existing friendly
diagnostic message. Keep the current error details and cause list unchanged.
- Around line 85-90: Replace the inline UI fee address fallback in
DjedAdapter.buildMintTx with a named exported constant, and reference that
constant when uiFeeAddress is absent. Keep the existing configured-address
override and transaction construction unchanged, making the default beneficiary
easy to audit.

In `@stablepay-sdk/src/core/adapters/ProtocolAdapter.js`:
- Around line 9-23: Update the ProtocolAdapter contract summary to include
getWarnings() and getEffectiveBalance(), and complete the truncated bigint
amount documentation sentence. Add a base getEffectiveBalance() declaration or
default implementation that returns the raw balance, so all adapters expose the
same callable interface while allowing TectonicAdapter to retain its override.

In `@stablepay-sdk/src/utils/config.js`:
- Around line 118-125: Update useLocalTectonic to return a derived
tectonic-local configuration with the supplied address applied to both
tectonicAddress and tokens.stablecoin.address, without mutating networksConfig
or any nested shared objects. Preserve the existing address validation and
returned configuration shape.

In `@tectonic-local/script/DeployLocal.s.sol`:
- Around line 63-74: Replace the hand-built JSON string in the deployment
manifest flow with Foundry’s vm.serializeX and vm.writeJson cheatcodes, using
the existing manifest fields from the json construction and preserving their
names and values. Keep the output schema and local deployment behavior unchanged
while relying on cheatcodes for formatting and escaping.

In `@tectonic-local/test/Tectonic.t.sol`:
- Around line 345-355: Add a regression test alongside
test_ForcedRedemptionPaysTheHolderInBasecoin that creates at least two holders,
triggers forceRedemptions, and verifies each expected holder is redeemed and
paid. Exercise the swap-removal path in forceRedemptions so index advancement is
validated across multiple holders, preserving the intended coverage semantics.
- Around line 146-161: Replace the stacked vm.assume filters in
testFuzz_SDK_CostFormulaNeverUnderpaysTheMerchant with bound() calls for
rawAmount and rawPrice, using the intended inclusive ranges. Preserve the
required < 500 ether solvency constraint without excessive rejection, adjusting
the input bounds or setup as needed so fuzz runs remain valid while covering the
explicit tested domain.

In `@tectonic-sdk/src/tectonic.js`:
- Around line 199-241: Replace the hardcoded basecoin decimal value in
quoteMint, quotePayment, and quoteRedeem with the imported BC_DECIMALS constant,
including both conversion and formatting calls, while leaving stablecoin decimal
handling unchanged.
- Around line 302-319: Align buildTransferTx and buildRedeemTx with buildMintTx
by validating their required addresses and amounts before calling
encodeFunctionData. Ensure from and to are provided for transfers, from and the
effective receiver are provided for redeems, and amount/amountSC is a positive
value; fail fast with the same validation style and clear errors already used by
buildMintTx.
- Around line 277-293: Update the gas-estimation catch block in the payment
transaction flow around publicClient.estimateGas to identify Viem 2.x revert
errors using the appropriate re-exported Viem error class and propagate those
failures to the caller before requesting a signature. Keep the existing warning
and wallet-estimation fallback only for non-revert estimation failures.

In `@tectonic-sdk/test/client.test.js`:
- Around line 168-175: Add direct test coverage for client.buildRedeemTx
alongside the existing transaction-builder tests. Initialize the client, build a
redemption using PAYER, MERCHANT, and an amount, then assert it targets ADDRESS,
has zero value, and encodes the receiver address in the transaction data.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8af36d0d-56ff-4753-82a2-4fb5acd13fc3

📥 Commits

Reviewing files that changed from the base of the PR and between c903ed3 and 8d20e75.

⛔ Files ignored due to path filters (7)
  • .DS_Store is excluded by !**/.DS_Store
  • stablepay-sdk/dist/esm/index.js is excluded by !**/dist/**
  • stablepay-sdk/dist/umd/index.js is excluded by !**/dist/**
  • stablepay-sdk/dist/umd/index.js.map is excluded by !**/dist/**, !**/*.map
  • stablepay-sdk/example/package-lock.json is excluded by !**/package-lock.json
  • stablepay-sdk/package-lock.json is excluded by !**/package-lock.json
  • tectonic-sdk/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (36)
  • .gitignore
  • stablepay-sdk/.gitignore
  • stablepay-sdk/example/src/App.jsx
  • stablepay-sdk/example/vite.config.js
  • stablepay-sdk/package.json
  • stablepay-sdk/rollup.config.mjs
  • stablepay-sdk/src/contexts/chains.js
  • stablepay-sdk/src/core/Transaction.js
  • stablepay-sdk/src/core/adapters/DjedAdapter.js
  • stablepay-sdk/src/core/adapters/ProtocolAdapter.js
  • stablepay-sdk/src/core/adapters/TectonicAdapter.js
  • stablepay-sdk/src/core/adapters/index.js
  • stablepay-sdk/src/index.js
  • stablepay-sdk/src/utils/config.js
  • stablepay-sdk/src/widget/TokenDropdown.jsx
  • stablepay-sdk/src/widget/TransactionReview.jsx
  • tectonic-local/.gitignore
  • tectonic-local/deployments/.gitkeep
  • tectonic-local/foundry.toml
  • tectonic-local/script/DeployLocal.s.sol
  • tectonic-local/src/Coin.sol
  • tectonic-local/src/IOracle.sol
  • tectonic-local/src/Math.sol
  • tectonic-local/src/MockOracle.sol
  • tectonic-local/src/Tectonic.sol
  • tectonic-local/test/Tectonic.t.sol
  • tectonic-sdk/.gitignore
  • tectonic-sdk/package.json
  • tectonic-sdk/scripts/smoke-local.mjs
  • tectonic-sdk/src/artifacts/TectonicABI.js
  • tectonic-sdk/src/constants.js
  • tectonic-sdk/src/index.js
  • tectonic-sdk/src/pricing.js
  • tectonic-sdk/src/tectonic.js
  • tectonic-sdk/test/client.test.js
  • tectonic-sdk/test/pricing.test.js

Comment thread stablepay-sdk/src/utils/config.js
Comment thread stablepay-sdk/src/widget/TransactionReview.jsx
Comment thread tectonic-local/script/DeployLocal.s.sol Outdated
Comment thread tectonic-local/src/Coin.sol Outdated
Comment thread tectonic-local/src/Tectonic.sol
Comment thread tectonic-local/src/Tectonic.sol

@Atharva0506 Atharva0506 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Is the tectonic-local Solidity fork intended as a long-term part of this repo? The commit header says "delete this fork when upstream is complete." It would be helpful to track this in an issue or a TODO so it doesn't become permanent.

and

example/package-lock.json is 2836 lines. Is this intentional? Most monorepos either gitignore package-lock.json in sub-packages or commit it deliberately. This one looks intentional since the example is a standalone Vite app, but worth confirming.


// Protocol-specific merchant warnings (Tectonic stability fees and
// triggered redemptions have no Djed equivalent).
newTransaction.getWarnings().then(setProtocolWarnings);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Minor: L75 fires getWarnings() without a .catch(). The Transaction.getWarnings() method swallows adapter errors internally, but if setProtocolWarnings throws (e.g. component unmounts before the promise resolves), you'll get an unhandled rejection. A simple .catch(() => {}) would cover it, or you could await it inside the existing try/catch.

Comment on lines +134 to +136
if (!/^\d*\.?\d*$/.test(str) || str === "" || str === ".") {
throw new Error(`Tectonic: "${value}" is not a valid decimal amount`);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

toBaseUnits(-1, 18) as a number silently produces -1e18n because the string path is only reached for strings, and the number path goes straight to BigInt(value). It doesn't cause an actual bug since requiredPaymentForStablecoins rejects non-positive amounts, but an early error in toBaseUnits would be clearer for callers. Consider adding a sign check in the toBigInt helper, or in toBaseUnits for the numeric branch.

@DeveloperAmrit

Copy link
Copy Markdown
Member Author

@Atharva0506

  1. Tectonic-local is temporary; it will be removed once Tectonic is deployed for real
  2. example/package-lock.json is intentional

This was referenced Aug 10, 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.

2 participants