feat(swap-service): Thorchain swap verification#38
Conversation
WIP commit moved to its own branch so the swap verification status refactor (verificationStatus column + decoupled polling) can land independently on develop. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
# Conflicts: # apps/swap-service/src/verification/swap-verification.service.ts # apps/swap-service/src/verification/utils.ts
@shapeshiftoss/chain-adapters transitively imports p-queue (ESM-only), which Jest's CJS loader can't parse. The verification tests only need bnOrZero, so stub the package via bignumber.js. Also add the missing VITE_THORCHAIN_MIDGARD_URL env stub used by the Thorchain verifier. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace the two synthetic Thornode fixtures (status/tx responses) with a single Midgard /actions response captured from a real ETH→USDC swap with ShapeShift affiliate, and update the matching Swap row fixture so verifier assertions reflect on-chain values rather than hand-rolled shapes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Treat action.status === 'failed' as FAILED (was falling through to the success path and producing a bogus SUCCESS verification). - Select the buy out by matching the memo destination address (the on-chain trusted value) instead of relying on array position. - Require both affiliateAddress === 'ss' AND a real affiliate out for hasAffiliate=true; gate affiliateBps, affiliateAddress, and actualAffiliateFeeAmountCryptoBaseUnit on that flag so foreign affiliate data never lands in our settlement record. - Treat "no out matching memo destination" as FAILED rather than PENDING — by Midgard invariants, post-pending actions have fully populated outs, so a mismatch is definitive. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Thorchain settles affiliate fees in RUNE regardless of the swap legs, so the previous 'sell_asset' strategy was wrong. Generalize the fee strategy to allow a fixed AssetId (RUNE here) and use null in place of the sentinel string for swappers with no affiliate fee asset. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (8)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Use jest.requireActual with a top-level type-only import for the BigNumber type, replacing bare require() and inline import() type annotations that tripped @typescript-eslint/no-require-imports and consistent-type-imports. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Description
Implements ShapeShift affiliate verification for THORChain swaps via Midgard's
/actionsendpoint, then hardens the result against malformed/foreign data so we don't pollute settlement records.swap-verification.service.tsverifyThorchain): fetch the action by inbound txid, validatetype === 'swap', treatstatus === 'failed'asFAILED(was silently producing aSUCCESS), and returnPENDINGwhile still in flight.=:ASSET:DEST:LIM/...:AFFILIATE:FEE) and match by!affiliate && address === dest, instead of relying onout[length-1]array position.hasAffiliaterequires bothaffiliateAddress === 'ss'AND a real affiliate out — neither alone is sufficient. WhenhasAffiliateis false,affiliateBps,affiliateAddress, andactualAffiliateFeeAmountCryptoBaseUnitare allundefinedso foreign-affiliate or no-fee swaps don't write attribution data.affiliateFeeAsset.tsnow supports a fixedAssetIdstrategy and usesthorchainAssetIdfor THORChain (was incorrectlysell_asset).@shapeshiftoss/chain-adaptersin jest setup (it transitively imports the ESM-onlyp-queuewhich Jest can't parse) and add the missingVITE_THORCHAIN_MIDGARD_URLenv. Replace the two old synthetic fixtures with a real captured Midgard/actionsresponse.Testing
yarn test(inapps/swap-service) — all suites green, including new Thorchain cases:0xprefix is stripped fromsellTxHashbefore the Midgard callssaffiliate ⇒hasAffiliate=falseand all affiliate fields undefinedssmemo but no affiliate out ⇒hasAffiliate=falseFAILEDFAILEDstatus === 'failed'⇒FAILEDsellTxHash⇒FAILED; HTTP error ⇒PENDINGswap_verificationrow records RUNE as the affiliate fee asset and the destination-matched buy amount.🤖 Generated with Claude Code