Skip to content

feat: add Orchestra USDT deposit addresses and recovery - #165

Merged
ben-kaufman merged 2 commits into
masterfrom
feat/usdt-orchestra-deposits-20261005
Oct 7, 2026
Merged

ben-kaufman merged 2 commits into
masterfrom
feat/usdt-orchestra-deposits-20261005

Conversation

@ben-kaufman

@ben-kaufman ben-kaufman commented Oct 5, 2026 •

Copy link
Copy Markdown
Collaborator

Description

Add UsdtDepositClient for receiving USDT from Ethereum, Tron, Solana, Polygon, Base and BNB Smart Chain into the wallet's Arbitrum One USDT0 account through reusable Orchestra deposit addresses. The sender transfers USDT normally; the Bitkit recipient receives USDT0 after provider costs. Arbitrum remains a direct receive path.

  • Discover enabled sources, obtain an indicative estimate and reusable address, inspect paginated deposit history and linked orders, and request an eligible refund to a user-approved source-chain address.
  • Authenticate private operations with a short-lived, domain-separated signature from the wallet's owner key. Provider credentials stay in the companion service. Reuse existing key derivation, signing and bounded HTTP transport.
  • Validate source addresses and pin EVM QR payloads to the correct chain and token. Keep the public amount contract in millionths of USDT, including BSC's 18-decimal source token.
  • Expose the client, records and actionable errors through UniFFI, with refreshed Swift interfaces and consumer documentation. Provider progress never credits the wallet balance; verified Arbitrum history does.

The companion backend update is published in bitkit-usdt-service@7b2fc2b. This PR is based on master and is independent of the Paykit proof PR. It does not change outgoing USDT0 bridging or add a database/migration.

Supported routes and rollout

These six sources are the intersection of live USDT routes and standing addresses returned by the approved account. The broader Orchestra swap catalog also includes sources for which that account does not return standing addresses, including Optimism, TON, Plasma and HyperEVM; they are not advertised by this integration. An EVM address must never be reused on an unlisted chain.

Sources are disabled by default in the service. Enable each through ORCHESTRA_DEPOSIT_NETWORKS after funded delivery and recovery acceptance. Unconverted Tron refunds require provider assistance. Quotes are indicative, and linked order amounts can represent a batch of deposits.

QA Notes

  • cargo test --locked --lib modules::usdt: 68 passed, 1 existing ignored test. Final deposit contract suite: 7 passed.
  • cargo fmt --check, host library build, and cargo clippy --locked --lib --tests passed. Complete Clippy diagnostics checked against the base: no new handwritten-code warnings; existing repository warnings remain.
  • Regenerated Swift and Kotlin from the exact host library. Swift compile/link and record smoke passed; Kotlin record compilation and ktlint passed. Full device/ABI packaging remains covered by PR CI.
  • Companion service: typecheck, Biome, 47 tests, build and production Docker build passed. Credential scan of all changed files passed.
  • Live read-only estimates succeeded for all six sources, including BSC unit scaling. Funded Polygon-to-Arbitrum receive, restart and address reuse were previously exercised in both apps. Other sources, live refunds and fresh-seed recovery still require funded acceptance; fixture tests are not claimed as mainnet tests.

Consumer builds need matching generated bindings and network selectors for the six exposed deposit variants. No mobile package release is included here.

@ovi-reviewer ovi-reviewer 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.

Verdict: ✅ Approve

Review: diff 8 files.

Findings:
1 inline (1 LOW)

QA:
The PR description reports automated checks and author verification; it requests no reviewer tests.


Reviewed by gpt-6.1-sol-high via gh-pr-review-loop skill
Commands: @ovi-reviewer review · test · retest

Comment thread src/modules/usdt/deposits.rs Outdated
@coreyphillips

Copy link
Copy Markdown
Collaborator

Two independent reviews, nothing blocking a merge.

worth doing, does not block

  • Refund address is validated against a caller-chosen network, not the deposit's (src/modules/usdt/deposits.rs:236). request_refund validates refund_address against the network argument, but that network is not part of the signed payload and is never checked against the deposit's own network. The payload at src/modules/usdt/deposits.rs:239 carries only depositId, offset and refundAddress. UsdtDeposit.network is a plain String, so the app has to map it to UsdtDepositNetwork by hand. If the app picks the wrong variant (for example Ethereum for a Tron deposit), the local check passes a 0x address and only the companion service stands between the user and a refund to an address on the wrong chain. One fix is to look up the deposit's network with detail first. Another is to include network in the signed payload so the service can reject a mismatch. I did not inspect the service, so it may already reject this.
  • HTTP 408 is reported as an invalid response (src/modules/usdt/deposits.rs:322). A 408 response from the deposit endpoint falls through the generic client-error branch and becomes InvalidResponse. Proxy timeouts are retryable transport failures, and other send or body timeouts already become NetworkUnavailable, so callers receive the wrong recovery guidance for this case.

@ben-kaufman
ben-kaufman merged commit 7fe3f67 into master Oct 7, 2026
5 checks passed
@ben-kaufman
ben-kaufman deleted the feat/usdt-orchestra-deposits-20261005 branch October 7, 2026 01:33
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