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 1 commit 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. |
c439b81 to
ecde277
Compare
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.
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.
…ed orders Report complete shift history across an affiliate-account rotation by querying two affiliate accounts and merging their completed orders. The primary sideshiftAffiliateId/Secret pair keeps its watermark and resumes incrementally; the optional numbered sideshiftAffiliateId2/Secret2 pair is a newly-added account that backfills from epoch. A per-account cursor map tracks each account independently, and legacy single-account progress docs migrate automatically. Map bsv (Bitcoin SV) to the bitcoinsv plugin id and add BSV-bsv to the delisted coins map so historical BSV orders resolve. Unprocessable orders throw rather than being skipped, so a mapping gap stops the account loudly instead of silently dropping revenue.
9763ac4 to
efe181d
Compare

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:
sideshiftAffiliateId2/sideshiftAffiliateSecret2alongside the existingprimary pair.
apiKeysreaching a plugin is a flat string map (asPartnerInfoin
types.ts), so a nested array is not possible; the explicit numbered pairis the backward-compatible form.
getSideshiftAccountsreturns the primaryaccount plus the optional second account, deduped by affiliateId, and throws if
only one of the
*2fields is set (a half-configured pair is amisconfiguration, not a silent single-account run).
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
*2pair 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*2. 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.
bsv(Bitcoin SV) is added to the network and delisted-coin maps so historicalBSV orders resolve instead of throwing
Unknown network: bsv.skipped, per reviewer preference: a stopped account is noticed, a stray
"skipped order" log is not, so revenue never drops silently. The throw
surfaces through the block-level retry path, so the cursor holds at the bad
order until the mapping is added.
Backward compatible: a single-account config (no second account) behaves exactly
as before. The second 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, half-configured-pair throw, and
throw-on-unprocessable-order (order not recorded, cursor holds). 9 passing.
tsc --noEmitclean on the changed files.throw-on-unprocessable revert): 1199 orders across the full 5.5-year history
(41 asset/network pairs) all processed cleanly after the BSV mapping, which is
retained.
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 affiliate revenue reporting and cursor semantics; misconfiguration or cursor bugs could miss or duplicate orders, though behavior is covered by new tests and single-account configs stay backward compatible.
Overview
The Sideshift partner plugin now supports an optional second affiliate (
sideshiftAffiliateId2/sideshiftAffiliateSecret2), queries each configured account, and merges completed orders into one result so shift history survives an affiliate rotation.Sync cursors are per affiliate via
settings.accounts, while the top-levellatestIsoDateremains the max across accounts. On upgrade, the primary account keeps the legacy watermark; a newly added account backfills from epoch so old orders are not skipped. Half-configured*2credentials throw instead of silently ignoring the second account.The single-account fetch loop is extracted into
querySideshiftAccount, with injectable fetch/process hooks for unit tests. BSV is added to network and delisted-coin mappings so historical BSV orders can be normalized.New
test/sideshift.test.tscovers account list building, dual-account merge, legacy migration, per-account cursors, and behavior when order processing fails (cursor does not advance past the bad order).Reviewed by Cursor Bugbot for commit efe181d. Bugbot is set up for automated code reviews on this repo. Configure here.