Skip to content

Sideshift: query both old and new affiliate accounts and merge completed orders#220

Open
j0ntz wants to merge 1 commit into
masterfrom
jon/sideshift-dual-account
Open

Sideshift: query both old and new affiliate accounts and merge completed orders#220
j0ntz wants to merge 1 commit into
masterfrom
jon/sideshift-dual-account

Conversation

@j0ntz

@j0ntz j0ntz commented Jun 25, 2026

Copy link
Copy Markdown

CHANGELOG

Does this branch warrant an entry to the CHANGELOG?

  • Yes
  • No

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 OLD account's historical
completed orders and miss in-flight shifts still routed under the OLD affiliateId
during the App Store update lag.

This changes src/partners/sideshift.ts to query BOTH the old and new affiliate
accounts and merge their completed-order streams, per the rotation decision
(query both and merge to preserve complete history).

What changed:

  • Config carries an optional second account via flat string fields
    sideshiftAffiliateIdOld / sideshiftAffiliateSecretOld alongside the
    existing primary pair. apiKeys reaching a plugin is a flat string map
    (asPartnerInfo in types.ts), so a nested array is not possible; the old
    pair is the explicit, backward-compatible form. getSideshiftAccounts returns
    the primary account plus the optional old account, deduped by affiliateId.
  • The existing per-account query/signature/retry/time-block loop is factored into
    querySideshiftAccount and run once per configured account; the transaction
    streams are merged into one result.
  • The latestIsoDate cursor is tracked PER account in a new
    settings.accounts map 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 the first run after deploy, so migration is seamless. The
    top-level latestIsoDate is kept as the overall max for backward compatibility.

Backward compatible: a single-account config (no old account) behaves exactly as
before. The new account's id/secret are config values ops adds later; the code
supports two accounts now.

Testing

  • New test/sideshift.test.ts (mocha + chai, deterministic, no live network):
    single-account, dual-account merge with max overall cursor, legacy progress-doc
    migration, and per-account cursor isolation. 7 passing.
  • tsc and eslint clean on the changed files.

edge-reports-server is a backend server with no app/sim surface, so there is no
in-app drive; the dual-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 reporting sync cursors and can emit duplicate or overlapping orders if both accounts return the same orderId; logic is well-tested but affects financial reporting completeness.

Overview
Sideshift affiliate reporting no longer relies on a single account during an affiliate ID rotation. Optional flat config fields sideshiftAffiliateIdOld / sideshiftAffiliateSecretOld add a legacy account alongside the primary pair; getSideshiftAccounts builds a deduped list (single-account configs behave as before).

The completed-order fetch loop is extracted into querySideshiftAccount and run once per account, with injectable fetch/process hooks for tests. Results are merged into one transaction list. Sync state adds settings.accounts (per-affiliateId latestIsoDate); the top-level latestIsoDate remains the max across accounts. On first run after upgrade, the primary account inherits the legacy watermark while a newly added old account backfills from epoch so its history is not skipped.

Adds test/sideshift.test.ts covering account list building, dual-account merge, legacy progress docs, and per-account cursor isolation.

Reviewed by Cursor Bugbot for commit c439b81. Bugbot is set up for automated code reviews on this repo. Configure here.

@cursor cursor 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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit b21225d. Configure here.

Comment thread src/partners/sideshift.ts Outdated
…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
@j0ntz j0ntz force-pushed the jon/sideshift-dual-account branch from b21225d to c439b81 Compare June 25, 2026 23:52
@j0ntz

j0ntz commented Jun 26, 2026

Copy link
Copy Markdown
Author

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 POST https://sideshift.ai/api/v2/create-account (no auth, no funds). affiliateIds Eg5PxMqMLh (new/primary) and QCZLA49Hkr (old/kept).

Check Result
(A) Live completedOrders accepts each account's HMAC-SHA1 signature PASS, HTTP 200 for both (0 orders, as expected for fresh accounts)
(B) querySideshift with the default live fetch queries both accounts PASS, per-account cursor map keyed by both affiliateIds, 0 fetch errors
(C) Both NEW and OLD affiliateIds hit the live endpoint in one run PASS
(D) Merge of non-empty streams through the real processSideshiftTx (live coins API) PASS, merged stream holds orders from both accounts; per-account cursors isolated (NEW 2026-06-20T10:00:00Z, OLD 2026-06-18T09:00:00Z, no cross-skip)

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 test/sideshift.test.ts, the dual-account merge is verified against the live API.

The throwaway accounts were used only for this read-only test and carry no funds.

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.

1 participant