Sideshift: query both old and new affiliate accounts and merge completed orders#220
Sideshift: query both old and new affiliate accounts and merge completed orders#220j0ntz wants to merge 3 commits into
Conversation
b21225d to
c439b81
Compare
Live dual-account smoke test (throwaway affiliate accounts)Verified the old + new merge end to end against the live Sideshift API, using two throwaway affiliate accounts created via
Fresh affiliate accounts have no order history, so (A)/(B)/(C) confirm the live query, signature, and cursor-map plumbing, while (D) feeds one realistic settled order per account into the live query loop so the real processing + merge path produces a combined non-empty stream. Combined with the deterministic unit tests in The throwaway accounts were used only for this read-only test and carry no funds. |
…ed orders Loop the per-account completed-orders query over each configured affiliate account and merge the streams so a Sideshift affiliate-account rotation keeps reporting the old account's historical and in-flight shifts. Track latestIsoDate per account so neither account's cursor skips the other's orders, falling back to the legacy single cursor for backward compatibility. Single-account config is unchanged. Add a mocha test covering the dual-account merge and per-account cursor behavior. Claude-Session: https://claude.ai/code/session_01YNwNii1LxjqaeowP5d7dgJ
c439b81 to
ecde277
Compare
Map bsv (Bitcoin SV) to the bitcoinsv plugin id and add BSV-bsv to the delisted coins map so historical BSV orders resolve instead of throwing "Unknown network: bsv". Also skip and log a single unprocessable order rather than letting it abort the page. A throw left the per-account cursor stuck before the bad order, so the account retried then gave up every cycle forever. The dual-account change makes from-epoch backfills routine, which makes hitting such an order far more likely.
4e6e2b0 to
b308478
Compare
Code reviewFound 4 issues:
edge-reports-server/src/partners/sideshift.ts Lines 356 to 372 in 0a6ba03
edge-reports-server/src/partners/sideshift.ts Lines 365 to 372 in 0a6ba03
edge-reports-server/src/partners/sideshift.ts Lines 423 to 426 in 0a6ba03 edge-reports-server/src/queryEngine.ts Lines 276 to 285 in 0a6ba03
edge-reports-server/src/partners/sideshift.ts Lines 276 to 284 in 0a6ba03 🤖 Generated with Claude Code - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
|
Addressed the review findings above (fixup commit pushed, unit tests added):
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 9f244ba. Configure here.
9f244ba to
ee1c93b
Compare
ee1c93b to
9763ac4
Compare
peachbits
left a comment
There was a problem hiding this comment.
I don't think we should skip orders so maybe we eliminate the third commit and most of the 2nd.
| const { | ||
| sideshiftAffiliateId, | ||
| sideshiftAffiliateSecret, | ||
| sideshiftAffiliateIdNew, |
There was a problem hiding this comment.
nit: this should be numbered (sideshiftAffiliateId2) instead of adding 'new'
| let standardTx: StandardTx | ||
| try { | ||
| standardTx = await processOrder(rawTx) | ||
| } catch (e) { |
There was a problem hiding this comment.
I actually prefer the throw. We're not going to notice some stray log mentioning a skipped order but we would notice if revenue stopped getting counted.

CHANGELOG
Does this branch warrant an entry to the CHANGELOG?
Dependencies
none
Description
Asana: https://app.asana.com/0/1215088146871429/1216057011453392
The Sideshift partner plugin queried a single affiliate account, so after the
Sideshift affiliate-account rotation it would drop the previous account's
historical completed orders and miss in-flight shifts still routed under the
previous affiliateId during the App Store update lag.
This changes
src/partners/sideshift.tsto query BOTH affiliate accounts andmerge their completed-order streams, per the rotation decision (query both and
merge to preserve complete history).
What changed:
sideshiftAffiliateIdNew/sideshiftAffiliateSecretNewalongside theexisting primary pair.
apiKeysreaching a plugin is a flat string map(
asPartnerInfointypes.ts), so a nested array is not possible; theexplicit pair is the backward-compatible form.
getSideshiftAccountsreturnsthe primary account plus the optional added account, deduped by affiliateId.
sideshiftAffiliateIdis the PRE-EXISTING account: on the firstrun after deploy it inherits the legacy single
latestIsoDatewatermark, so itresumes incrementally and never re-scans its full history. The
*Newpair is aNEWLY-ADDED account with no recorded history, so it backfills from epoch.
Operational consequence at a rotation: put the current (soon-to-be-old) account
in
sideshiftAffiliateIdand the new account in*New. No progress-cache editis needed, and the account with years of history never does a multi-hour
from-epoch crawl. (Reversing the slots would send the established account
through a full from-epoch re-scan.)
querySideshiftAccountand run once per configured account; the streams aremerged into one result.
latestIsoDatecursor is tracked PER account in a newsettings.accountsmap so one account's cursor never skips the other's orders. Legacy progress
docs (single top-level
latestIsoDate, no map) fall back to that value on thefirst run after deploy, so migration is seamless. The top-level
latestIsoDateis kept as the overall max for backward compatibility.
A second commit hardens processing.
bsv(Bitcoin SV) is added to the networkand delisted-coin maps so historical BSV orders resolve instead of throwing
Unknown network: bsv. And a single unprocessable order is now skipped andlogged instead of throwing: previously a throw left the per-account cursor stuck
before the bad order, so the account retried then gave up every cycle forever.
From-epoch backfills make hitting such an order far more likely.
Backward compatible: a single-account config (no added account) behaves exactly
as before. The new account's id/secret are config values ops adds at rotation
time; the code supports two accounts now.
Testing
test/sideshift.test.ts(mocha + chai, deterministic, no live network):single-account, dual-account merge with max overall cursor, legacy progress-doc
migration, per-account cursor isolation, and skip-an-unprocessable-order. 8
passing.
across the full 5.5-year history (41 asset/network pairs) all process cleanly.
tscclean on the changed files.edge-reports-serveris a backend server with no app/sim surface, so thedual-account merge + cursor logic is covered by the unit tests above. The live
Sideshift API and CouchDB persistence paths are unchanged.
Note
Medium Risk
Changes partner ingestion cursors and can permanently skip unprocessable orders once the cursor passes them; mis-rotating primary vs *New slots could cause large backfills or missed history, though behavior is backward compatible for single-account configs.
Overview
Sideshift reporting now supports an optional second affiliate via
sideshiftAffiliateIdNew/sideshiftAffiliateSecretNew, queries each account (deduped, with errors on half-configured pairs), merges completed orders, and persists per-affiliate cursors insettings.accountswhile keeping top-levellatestIsoDateas the max across accounts. Legacy progress docs still work: the primary account inherits the old watermark; a newly added account backfills from epoch so rotation does not drop history.Processing reliability changes: coins-list failures throw
SideshiftTransientErrorand retry without advancing the cursor; unprocessable orders (e.g. unmapped coin/network) are logged by order id, skipped, and the cursor advances past them (including forward progress when a whole page is bad). BSV is added to network and delisted-coin maps.Injectable fetch/process hooks and
test/sideshift.test.tscover dual-account merge, cursor migration, skip vs transient behavior.Reviewed by Cursor Bugbot for commit 9763ac4. Bugbot is set up for automated code reviews on this repo. Configure here.