diff --git a/apps/swap-service/src/swaps/utils.ts b/apps/swap-service/src/swaps/utils.ts index 65acc69..241a1d7 100644 --- a/apps/swap-service/src/swaps/utils.ts +++ b/apps/swap-service/src/swaps/utils.ts @@ -3,6 +3,7 @@ import type { Swap as PrismaSwap } from '@prisma/client' import type { CreateSwapDto } from '@shapeshift/shared-types' import { baseUnitToPrecision } from '@shapeshift/shared-utils' +import { mayachainAssetId, thorchainAssetId } from '@shapeshiftoss/caip' import { bnOrZero } from '@shapeshiftoss/chain-adapters' import type { Swap as SwapperSwap, SwapperName, SwapperSpecificMetadata } from '@shapeshiftoss/swapper' import type { Asset } from '@shapeshiftoss/types' @@ -15,6 +16,11 @@ const logger = new Logger('SwapsService') const BPS_DENOMINATOR = 10000 +// Native precisions of the THORChain/Maya native fee assets — the precision the affiliate fee +// amount is stored in for these chains. +const RUNE_PRECISION = 8 +const CACAO_PRECISION = 10 + // Historical rows may persist `{}` for affiliateVerificationDetails; coerce anything // that doesn't satisfy the tightened shape (requires `hasAffiliate`) to null. const toAffiliateVerificationDetails = ( @@ -119,16 +125,29 @@ const resolveActualFeeUsd = (swap: Swap): number | null => { let priceUsd: string | null let precision: number | null - if (swap.affiliateFeeAssetId === swap.sellAsset.assetId) { - priceUsd = swap.sellAssetUsd - precision = swap.sellAsset.precision - } else if (swap.affiliateFeeAssetId === swap.buyAsset.assetId) { - priceUsd = swap.buyAssetUsd - precision = swap.buyAsset.precision - } else { - priceUsd = swap.affiliateAssetUsd - // Fee asset is neither sell nor buy — precision unknown - precision = null + switch (swap.affiliateFeeAssetId) { + case swap.sellAsset.assetId: + priceUsd = swap.sellAssetUsd + precision = swap.sellAsset.precision + break + case swap.buyAsset.assetId: + priceUsd = swap.buyAssetUsd + precision = swap.buyAsset.precision + break + case thorchainAssetId: + // Thorchain collects the affiliate fee in RUNE. + priceUsd = swap.affiliateAssetUsd + precision = RUNE_PRECISION + break + case mayachainAssetId: + // Mayachain collects the affiliate fee in CACAO. + priceUsd = swap.affiliateAssetUsd + precision = CACAO_PRECISION + break + default: + priceUsd = swap.affiliateAssetUsd + // Fee asset is neither sell nor buy nor a known native fee asset — precision unknown + precision = null } if (!priceUsd || precision === null) return null diff --git a/apps/swap-service/src/utils/affiliateFeeAsset.ts b/apps/swap-service/src/utils/affiliateFeeAsset.ts index 1a58d35..3a39ae6 100644 --- a/apps/swap-service/src/utils/affiliateFeeAsset.ts +++ b/apps/swap-service/src/utils/affiliateFeeAsset.ts @@ -1,5 +1,5 @@ import type { AssetId } from '@shapeshiftoss/caip' -import { thorchainAssetId } from '@shapeshiftoss/caip' +import { mayachainAssetId, thorchainAssetId } from '@shapeshiftoss/caip' import { SwapperName } from '@shapeshiftoss/swapper' import type { Asset } from '@shapeshiftoss/types' @@ -15,7 +15,7 @@ const SWAPPER_FEE_STRATEGY: Record = { [SwapperName.Chainflip]: 'buy_asset', [SwapperName.CowSwap]: 'sell_asset', [SwapperName.Debridge]: 'sell_asset', - [SwapperName.Mayachain]: 'sell_asset', + [SwapperName.Mayachain]: mayachainAssetId, [SwapperName.NearIntents]: 'sell_asset', [SwapperName.Portals]: 'sell_asset', [SwapperName.Relay]: null, diff --git a/apps/swap-service/src/verification/__tests__/maya.test.ts b/apps/swap-service/src/verification/__tests__/maya.test.ts index f005284..71b35e5 100644 --- a/apps/swap-service/src/verification/__tests__/maya.test.ts +++ b/apps/swap-service/src/verification/__tests__/maya.test.ts @@ -33,7 +33,8 @@ describe('verifyMaya', () => { affiliateAddress: 'ssmaya', verifiedSellAmountCryptoBaseUnit: '4000000000000000', actualBuyAmountCryptoBaseUnit: '7340228', - actualAffiliateFeeAmountCryptoBaseUnit: '4237779000', + // CACAO fee from Midgard (1e8) scaled to native precision 10: 4237779000 × 100 + actualAffiliateFeeAmountCryptoBaseUnit: '423777900000', }) }) diff --git a/apps/swap-service/src/verification/swap-verification.service.ts b/apps/swap-service/src/verification/swap-verification.service.ts index cca6057..a9c5bb8 100644 --- a/apps/swap-service/src/verification/swap-verification.service.ts +++ b/apps/swap-service/src/verification/swap-verification.service.ts @@ -329,16 +329,24 @@ export class SwapVerificationService { } private verifyThorchain(swap: Swap): Promise { - return this.verifyMidgardSwap(swap, { midgardUrl: env.VITE_THORCHAIN_MIDGARD_URL, affiliate: 'ss' }) + return this.verifyMidgardSwap(swap, { + midgardUrl: env.VITE_THORCHAIN_MIDGARD_URL, + affiliate: 'ss', + feeAssetPrecision: 8, + }) } private verifyMaya(swap: Swap): Promise { - return this.verifyMidgardSwap(swap, { midgardUrl: env.VITE_MAYACHAIN_MIDGARD_URL, affiliate: 'ssmaya' }) + return this.verifyMidgardSwap(swap, { + midgardUrl: env.VITE_MAYACHAIN_MIDGARD_URL, + affiliate: 'ssmaya', + feeAssetPrecision: 10, + }) } private async verifyMidgardSwap( swap: Swap, - config: { midgardUrl: string; affiliate: string }, + config: { midgardUrl: string; affiliate: string; feeAssetPrecision: number }, ): Promise { const txHash = swap.sellTxHash?.replace(/^0x/, '') if (!txHash) return noAffiliateResult('FAILED', 'Missing sell txHash') @@ -382,7 +390,10 @@ export class SwapVerificationService { swap.sellAsset.precision, ), actualBuyAmountCryptoBaseUnit: thorchainToNativePrecision(buyOut.coins[0].amount, swap.buyAsset.precision), - actualAffiliateFeeAmountCryptoBaseUnit: hasAffiliate ? feeOut?.coins[0].amount : undefined, + actualAffiliateFeeAmountCryptoBaseUnit: + hasAffiliate && feeOut?.coins[0]?.amount + ? thorchainToNativePrecision(feeOut.coins[0].amount, config.feeAssetPrecision) + : undefined, } }