From 5df3bcf52086be13e80af54b98965f10c47946d5 Mon Sep 17 00:00:00 2001 From: kaladinlight <35275952+kaladinlight@users.noreply.github.com> Date: Mon, 18 May 2026 11:14:50 -0600 Subject: [PATCH] feat(swap-service): Mayachain swap verification Co-Authored-By: Claude Opus 4.7 (1M context) --- .../__tests__/fixtures/maya/response.json | 94 ++++++++ .../__tests__/fixtures/maya/swap.ts | 82 +++++++ .../src/verification/__tests__/maya.test.ts | 200 ++++++++++++++++++ .../src/verification/__tests__/relay.test.ts | 2 +- .../src/verification/__tests__/setup.ts | 4 +- .../verification/__tests__/thorchain.test.ts | 4 +- .../verification/swap-verification.service.ts | 79 ++----- apps/swap-service/src/verification/types.ts | 9 - 8 files changed, 401 insertions(+), 73 deletions(-) create mode 100644 apps/swap-service/src/verification/__tests__/fixtures/maya/response.json create mode 100644 apps/swap-service/src/verification/__tests__/fixtures/maya/swap.ts create mode 100644 apps/swap-service/src/verification/__tests__/maya.test.ts diff --git a/apps/swap-service/src/verification/__tests__/fixtures/maya/response.json b/apps/swap-service/src/verification/__tests__/fixtures/maya/response.json new file mode 100644 index 0000000..d3a9482 --- /dev/null +++ b/apps/swap-service/src/verification/__tests__/fixtures/maya/response.json @@ -0,0 +1,94 @@ +{ + "actions": [ + { + "date": "1778781664239595999", + "height": "16562704", + "in": [ + { + "address": "0xa44c286ba83bb771cd0107b2c1df678435bd1535", + "coins": [ + { + "amount": "400000", + "asset": "ETH.ETH" + } + ], + "txID": "E4DAC04D7194ABA8F3A9FA154CD7BE3055A03D35797F1916D8721F6273FA16EB" + } + ], + "metadata": { + "swap": { + "affiliateAddress": "ssmaya", + "affiliateFee": "60", + "inPriceUSD": "2292.5229642298773", + "isStreamingSwap": true, + "liquidityFee": "126740373", + "memo": "=:ETH.USDC:0xA44C286BA83Bb771cd0107B2c1Df678435Bd1535:724374326:ssmaya:60", + "networkFees": [ + { + "amount": "170650000", + "asset": "ETH.USDC-0XA0B86991C6218B36C1D19D4A2E9EB0CE3606EB48" + } + ], + "outPriceUSD": "1.0158642784979675", + "streamingSwapMeta": { + "count": "1", + "depositedCoin": { + "amount": "0", + "asset": "" + }, + "inCoin": { + "amount": "0", + "asset": "" + }, + "interval": "0", + "lastHeight": "0", + "outCoin": { + "amount": "0", + "asset": "" + }, + "outEstimation": "4237779000", + "quantity": "1" + }, + "swapSlip": "2", + "swapTarget": "724374326" + } + }, + "out": [ + { + "address": "0xa44c286ba83bb771cd0107b2c1df678435bd1535", + "coins": [ + { + "amount": "734022800", + "asset": "ETH.USDC-0XA0B86991C6218B36C1D19D4A2E9EB0CE3606EB48" + } + ], + "height": "16562711", + "txID": "389BD007E29E081811C735F773D360A05DFC3E0C8608781A85602A7C7AE2AD4B" + }, + { + "address": "maya122h9hlrugzdny9ct95z6g7afvpzu34s73tgnyv", + "affiliate": true, + "coins": [ + { + "amount": "4237779000", + "asset": "MAYA.CACAO" + } + ], + "height": "16562705", + "txID": "" + } + ], + "pools": [ + "ETH.ETH", + "ETH.USDC-0XA0B86991C6218B36C1D19D4A2E9EB0CE3606EB48" + ], + "status": "success", + "type": "swap" + } + ], + "count": "1", + "meta": { + "nextPageToken": "165627049000000001", + "prevPageToken": "165627049000000001" + } +} \ No newline at end of file diff --git a/apps/swap-service/src/verification/__tests__/fixtures/maya/swap.ts b/apps/swap-service/src/verification/__tests__/fixtures/maya/swap.ts new file mode 100644 index 0000000..71e56f2 --- /dev/null +++ b/apps/swap-service/src/verification/__tests__/fixtures/maya/swap.ts @@ -0,0 +1,82 @@ +import { SwapperName } from '@shapeshiftoss/swapper' + +import type { Swap } from '../../../../swaps/types' + +export default { + swapId: '562f173c-1515-4a4e-bf6b-cd1b35a9db1f', + sellAsset: { + icon: 'https://rawcdn.githack.com/trustwallet/assets/32e51d582a890b3dd3135fe3ee7c20c2fd699a6d/blockchains/ethereum/info/logo.png', + name: 'Ethereum', + color: '#5C6BC0', + symbol: 'ETH', + assetId: 'eip155:1/slip44:60', + chainId: 'eip155:1', + explorer: 'https://etherscan.io', + precision: 18, + networkIcon: + 'https://rawcdn.githack.com/trustwallet/assets/32e51d582a890b3dd3135fe3ee7c20c2fd699a6d/blockchains/ethereum/info/logo.png', + networkName: 'Ethereum', + networkColor: '#5C6BC0', + explorerTxLink: 'https://etherscan.io/tx/', + relatedAssetKey: 'eip155:1/slip44:60', + explorerAddressLink: 'https://etherscan.io/address/', + }, + buyAsset: { + icon: 'https://assets.coingecko.com/coins/images/6319/large/USDC.png?1769615602', + name: 'USDC', + color: '#2373CB', + symbol: 'USDC', + assetId: 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', + chainId: 'eip155:1', + explorer: 'https://etherscan.io', + precision: 6, + networkIcon: + 'https://rawcdn.githack.com/trustwallet/assets/32e51d582a890b3dd3135fe3ee7c20c2fd699a6d/blockchains/ethereum/info/logo.png', + networkName: 'Ethereum', + networkColor: '#5C6BC0', + explorerTxLink: 'https://etherscan.io/tx/', + relatedAssetKey: 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', + explorerAddressLink: 'https://etherscan.io/address/', + }, + sellAmountCryptoBaseUnit: '4000000000000000', + expectedBuyAmountCryptoBaseUnit: '7280143.98', + actualBuyAmountCryptoBaseUnit: '7340228', + status: 'SUCCESS', + source: 'MAYAChain', + swapperName: SwapperName.Mayachain, + sellAccountId: '3c70e97c6f86a5b5cfdf82dfd3380ac4ed3d8b89dabf86f631bdf739372926be', + buyAccountId: null, + receiveAddress: '0xA44C286BA83Bb771cd0107B2c1Df678435Bd1535', + sellTxHash: '0xe4dac04d7194aba8f3a9fa154cd7be3055a03d35797f1916d8721f6273fa16eb', + buyTxHash: '0x389BD007E29E081811C735F773D360A05DFC3E0C8608781A85602A7C7AE2AD4B', + txLink: null, + statusMessage: '', + isStreaming: false, + createdAt: new Date('2026-05-14T18:00:35.263Z'), + updatedAt: new Date('2026-05-18T16:27:43.217Z'), + metadata: { + quoteId: '562f173c-1515-4a4e-bf6b-cd1b35a9db1f', + stepIndex: 0, + acrossTransactionMetadata: undefined, + chainflipSwapId: undefined, + debridgeTransactionMetadata: undefined, + relayerExplorerTxLink: undefined, + relayerTxHash: undefined, + relayTransactionMetadata: undefined, + streamingSwapMetadata: undefined, + }, + userId: 'api', + referralCode: null, + sellAssetUsd: '2309.11', + buyAssetUsd: '0.99977', + affiliateAssetUsd: '2309.11', + isAffiliateVerified: null, + affiliateVerificationDetails: null, + affiliateAddress: '0xA44C286BA83Bb771cd0107B2c1Df678435Bd1535', + affiliateBps: 60, + origin: 'api', + affiliateFeeAssetId: 'eip155:1/slip44:60', + actualAffiliateFeeAmountCryptoBaseUnit: null, + shapeshiftBps: 10, + verificationStatus: 'PENDING', +} satisfies Swap diff --git a/apps/swap-service/src/verification/__tests__/maya.test.ts b/apps/swap-service/src/verification/__tests__/maya.test.ts new file mode 100644 index 0000000..f005284 --- /dev/null +++ b/apps/swap-service/src/verification/__tests__/maya.test.ts @@ -0,0 +1,200 @@ +import type { HttpService } from '@nestjs/axios' +import { of, throwError } from 'rxjs' + +import type { Swap } from '../../swaps/types' +import { SwapVerificationService } from '../swap-verification.service' + +import mayaResponse from './fixtures/maya/response.json' +import mayaSwap from './fixtures/maya/swap' + +const swap = mayaSwap as unknown as Swap + +const makeHttpMock = (response: unknown): HttpService => { + const get = jest.fn().mockReturnValue(of({ data: response })) + return { get } as unknown as HttpService +} + +describe('verifyMaya', () => { + let service: SwapVerificationService + + beforeEach(() => { + jest.restoreAllMocks() + }) + + it('verifies a successful swap with shapeshift affiliate', async () => { + service = new SwapVerificationService(makeHttpMock(mayaResponse)) + + const result = await service.verifySwap(swap) + + expect(result).toMatchObject({ + verificationStatus: 'SUCCESS', + hasAffiliate: true, + affiliateBps: 60, + affiliateAddress: 'ssmaya', + verifiedSellAmountCryptoBaseUnit: '4000000000000000', + actualBuyAmountCryptoBaseUnit: '7340228', + actualAffiliateFeeAmountCryptoBaseUnit: '4237779000', + }) + }) + + it('strips 0x prefix from sellTxHash before calling Midgard', async () => { + const get = jest.fn().mockReturnValue(of({ data: mayaResponse })) + service = new SwapVerificationService({ get } as unknown as HttpService) + + await service.verifySwap(swap) + + const url = get.mock.calls[0][0] + expect(url).toMatch(/\/actions\?txid=[0-9a-f]+$/i) + expect(url).not.toMatch(/=0x/i) + }) + + it('does not attribute affiliate fields when the action affiliate is not ssmaya', async () => { + const response = structuredClone(mayaResponse) + response.actions[0].metadata.swap.affiliateAddress = 'other' + + service = new SwapVerificationService(makeHttpMock(response)) + + const result = await service.verifySwap(swap) + + expect(result.verificationStatus).toBe('SUCCESS') + expect(result.hasAffiliate).toBe(false) + expect(result.affiliateAddress).toBeUndefined() + expect(result.affiliateBps).toBeUndefined() + expect(result.actualAffiliateFeeAmountCryptoBaseUnit).toBeUndefined() + }) + + it('returns hasAffiliate=false when affiliateAddress is ssmaya but no fee was paid out', async () => { + const response = structuredClone(mayaResponse) + response.actions[0].out = response.actions[0].out.filter((out) => !('affiliate' in out && out.affiliate)) + + service = new SwapVerificationService(makeHttpMock(response)) + + const result = await service.verifySwap(swap) + + expect(result.hasAffiliate).toBe(false) + expect(result.affiliateAddress).toBeUndefined() + expect(result.affiliateBps).toBeUndefined() + expect(result.actualAffiliateFeeAmountCryptoBaseUnit).toBeUndefined() + }) + + it('returns FAILED when sellTxHash is missing', async () => { + service = new SwapVerificationService(makeHttpMock(mayaResponse)) + + const result = await service.verifySwap({ ...swap, sellTxHash: null } as Swap) + + expect(result).toMatchObject({ + verificationStatus: 'FAILED', + hasAffiliate: false, + noAffiliateReason: 'Missing sell txHash', + }) + }) + + it('returns PENDING when Midgard returns no actions', async () => { + service = new SwapVerificationService(makeHttpMock({ actions: [] })) + + const result = await service.verifySwap(swap) + + expect(result.verificationStatus).toBe('PENDING') + expect(result.noAffiliateReason).toBe('No action found in Midgard') + }) + + it('returns PENDING when the action is still pending', async () => { + const response = structuredClone(mayaResponse) + response.actions[0].status = 'pending' + + service = new SwapVerificationService(makeHttpMock(response)) + + const result = await service.verifySwap(swap) + + expect(result.verificationStatus).toBe('PENDING') + expect(result.noAffiliateReason).toBe('Swap action still pending') + }) + + it('returns FAILED when the action type is not swap', async () => { + const response = structuredClone(mayaResponse) + response.actions[0].type = 'addLiquidity' + + service = new SwapVerificationService(makeHttpMock(response)) + + const result = await service.verifySwap(swap) + + expect(result.verificationStatus).toBe('FAILED') + expect(result.noAffiliateReason).toBe('Invalid swap action type') + }) + + it('returns FAILED when swap metadata is missing', async () => { + const response = structuredClone(mayaResponse) as { + actions: Array<{ metadata: { swap?: unknown } }> + } + delete response.actions[0].metadata.swap + + service = new SwapVerificationService(makeHttpMock(response)) + + const result = await service.verifySwap(swap) + + expect(result.verificationStatus).toBe('FAILED') + expect(result.noAffiliateReason).toBe('No swap metadata found') + }) + + it('selects the buy out by memo destination rather than array position', async () => { + const response = structuredClone(mayaResponse) + response.actions[0].out.reverse() + + service = new SwapVerificationService(makeHttpMock(response)) + + const result = await service.verifySwap(swap) + + expect(result.actualBuyAmountCryptoBaseUnit).toBe('7340228') + }) + + it('returns FAILED when no out matches the memo destination', async () => { + const response = structuredClone(mayaResponse) + response.actions[0].out = response.actions[0].out.map((out) => + 'affiliate' in out && out.affiliate ? out : { ...out, address: '0xdeadbeef' }, + ) + + service = new SwapVerificationService(makeHttpMock(response)) + + const result = await service.verifySwap(swap) + + expect(result.verificationStatus).toBe('FAILED') + expect(result.noAffiliateReason).toBe('No outbound matching memo destination') + }) + + it('returns FAILED when the action status is failed (refund)', async () => { + const response = structuredClone(mayaResponse) + response.actions[0].status = 'failed' + + service = new SwapVerificationService(makeHttpMock(response)) + + const result = await service.verifySwap(swap) + + expect(result.verificationStatus).toBe('FAILED') + expect(result.noAffiliateReason).toBe('Swap action failed') + }) + + it('returns FAILED when the memo has no destination address', async () => { + const response = structuredClone(mayaResponse) + response.actions[0].metadata.swap.memo = '' + + service = new SwapVerificationService(makeHttpMock(response)) + + const result = await service.verifySwap(swap) + + expect(result.verificationStatus).toBe('FAILED') + expect(result.noAffiliateReason).toBe('Could not parse destination address from memo') + }) + + it('returns PENDING when the HTTP call fails (transient — retry next tick)', async () => { + const httpMock = { + get: jest.fn().mockReturnValue(throwError(() => new Error('upstream 500'))), + } as unknown as HttpService + + service = new SwapVerificationService(httpMock) + + const result = await service.verifySwap(swap) + + expect(result.verificationStatus).toBe('PENDING') + expect(result.noAffiliateReason).toBe('upstream 500') + }) +}) diff --git a/apps/swap-service/src/verification/__tests__/relay.test.ts b/apps/swap-service/src/verification/__tests__/relay.test.ts index b4e3dc0..97e5f60 100644 --- a/apps/swap-service/src/verification/__tests__/relay.test.ts +++ b/apps/swap-service/src/verification/__tests__/relay.test.ts @@ -203,7 +203,7 @@ describe('verifyRelay', () => { const result = await service.verifySwap(swap) expect(result.verificationStatus).toBe('PENDING') - expect(result.noAffiliateReason).toBe('No request data found from Relay API') + expect(result.noAffiliateReason).toBe('No request data returned from Relay API') }) it('returns PENDING when the HTTP call fails (transient — retry next tick)', async () => { diff --git a/apps/swap-service/src/verification/__tests__/setup.ts b/apps/swap-service/src/verification/__tests__/setup.ts index e083d37..15f955b 100644 --- a/apps/swap-service/src/verification/__tests__/setup.ts +++ b/apps/swap-service/src/verification/__tests__/setup.ts @@ -9,8 +9,8 @@ jest.mock('../../env', () => ({ VITE_CHAINFLIP_API_KEY: 'x', VITE_NEAR_INTENTS_API_KEY: 'x', VITE_THORCHAIN_NODE_URL: 'https://thornode.test', - VITE_THORCHAIN_MIDGARD_URL: 'https://midgard.test', - VITE_MAYACHAIN_NODE_URL: 'https://mayanode.test', + VITE_THORCHAIN_MIDGARD_URL: 'https://thorchain-midgard.test', + VITE_MAYACHAIN_MIDGARD_URL: 'https://mayachain-midgard.test', VITE_ACROSS_API_URL: 'https://across.test', VITE_BEBOP_API_URL: 'https://bebop.test', VITE_CHAINFLIP_API_URL: 'https://chainflip.test', diff --git a/apps/swap-service/src/verification/__tests__/thorchain.test.ts b/apps/swap-service/src/verification/__tests__/thorchain.test.ts index 8a64d85..f40abda 100644 --- a/apps/swap-service/src/verification/__tests__/thorchain.test.ts +++ b/apps/swap-service/src/verification/__tests__/thorchain.test.ts @@ -85,7 +85,7 @@ describe('verifyThorchain', () => { expect(result).toMatchObject({ verificationStatus: 'FAILED', hasAffiliate: false, - noAffiliateReason: 'Missing txHash for Thorchain verification', + noAffiliateReason: 'Missing sell txHash', }) }) @@ -171,7 +171,7 @@ describe('verifyThorchain', () => { const result = await service.verifySwap(swap) expect(result.verificationStatus).toBe('FAILED') - expect(result.noAffiliateReason).toBe('Swap action failed on Thorchain') + expect(result.noAffiliateReason).toBe('Swap action failed') }) it('returns FAILED when the memo has no destination address', async () => { diff --git a/apps/swap-service/src/verification/swap-verification.service.ts b/apps/swap-service/src/verification/swap-verification.service.ts index 0554b2d..b72a86d 100644 --- a/apps/swap-service/src/verification/swap-verification.service.ts +++ b/apps/swap-service/src/verification/swap-verification.service.ts @@ -23,11 +23,10 @@ import { PortalsOrderResponse, RelayRequestsResponse, StonfiQuoteMetadata, - ThorchainMayaTxResponse, ZrxApiResponse, ZrxTrade, } from './types' -import { applyBps, noAffiliateResult, THORCHAIN_PRECISION, thorchainToNativePrecision } from './utils' +import { applyBps, noAffiliateResult, thorchainToNativePrecision } from './utils' @Injectable() export class SwapVerificationService { @@ -38,13 +37,10 @@ export class SwapVerificationService { private readonly shapeshiftButterswapEntrance = 'shapeshift' private readonly shapeshiftChainflipAffiliate = 'shapeshift' private readonly shapeshiftCowswapAppCode = 'shapeshift' - private readonly shapeshiftMayaAffiliate = 'ssmaya' private readonly bebopApiKey = env.VITE_BEBOP_API_KEY private readonly chainflipApiKey = env.VITE_CHAINFLIP_API_KEY - private readonly mayachainNodeUrl = env.VITE_MAYACHAIN_NODE_URL - private readonly acrossApiUrl = env.VITE_ACROSS_API_URL private readonly bebopApiUrl = env.VITE_BEBOP_API_URL private readonly chainflipApiUrl = env.VITE_CHAINFLIP_API_URL @@ -95,7 +91,7 @@ export class SwapVerificationService { return await this.verifyAcross(swap) case SwapperName.Debridge: case SwapperName.Test: - return noAffiliateResult('SUCCESS', `Verification not implemented`) + return noAffiliateResult('SUCCESS', 'Verification not implemented') default: { const _exhaustive: never = swap.swapperName void _exhaustive @@ -166,7 +162,7 @@ export class SwapVerificationService { ) const request = data?.requests?.[0] - if (!request?.data) return noAffiliateResult('PENDING', 'No request data found from Relay API') + if (!request?.data) return noAffiliateResult('PENDING', 'No request data returned from Relay API') const appFees = request.data.appFees?.length ? request.data.appFees : (request.data.paidAppFees ?? []) @@ -328,12 +324,23 @@ export class SwapVerificationService { } } - private async verifyThorchain(swap: Swap): Promise { + private verifyThorchain(swap: Swap): Promise { + return this.verifyMidgardSwap(swap, { midgardUrl: env.VITE_THORCHAIN_MIDGARD_URL, affiliate: 'ss' }) + } + + private verifyMaya(swap: Swap): Promise { + return this.verifyMidgardSwap(swap, { midgardUrl: env.VITE_MAYACHAIN_MIDGARD_URL, affiliate: 'ssmaya' }) + } + + private async verifyMidgardSwap( + swap: Swap, + config: { midgardUrl: string; affiliate: string }, + ): Promise { const txHash = swap.sellTxHash?.replace(/^0x/, '') - if (!txHash) return noAffiliateResult('FAILED', 'Missing txHash for Thorchain verification') + if (!txHash) return noAffiliateResult('FAILED', 'Missing sell txHash') const { data } = await firstValueFrom( - this.httpService.get(`${env.VITE_THORCHAIN_MIDGARD_URL}/actions?txid=${txHash}`), + this.httpService.get(`${config.midgardUrl}/actions?txid=${txHash}`), ) const action = data.actions[0] @@ -341,7 +348,7 @@ export class SwapVerificationService { if (action.type !== 'swap') return noAffiliateResult('FAILED', 'Invalid swap action type') if (action.status === 'pending') return noAffiliateResult('PENDING', 'Swap action still pending') - if (action.status === 'failed') return noAffiliateResult('FAILED', 'Swap action failed on Thorchain') + if (action.status === 'failed') return noAffiliateResult('FAILED', 'Swap action failed') const swapMetadata = action.metadata.swap if (!swapMetadata) return noAffiliateResult('FAILED', 'No swap metadata found') @@ -349,7 +356,7 @@ export class SwapVerificationService { const affiliateAddress = swapMetadata.affiliateAddress // Memo format: =:ASSET:DESTADDR:LIM/INTERVAL/QUANTITY:AFFILIATE:FEE - // The destination is what THORChain observed on-chain, so it's the trusted source for matching the buy out. + // The destination is what Midgard observed on-chain, so it's the trusted source for matching the buy out. const destinationAddress = swapMetadata.memo.split(':')[2] if (!destinationAddress) return noAffiliateResult('FAILED', 'Could not parse destination address from memo') @@ -359,7 +366,7 @@ export class SwapVerificationService { if (!buyOut) return noAffiliateResult('FAILED', 'No outbound matching memo destination') const feeOut = action.out.find((out) => out.affiliate) - const hasAffiliate = affiliateAddress === 'ss' && !!feeOut + const hasAffiliate = affiliateAddress === config.affiliate && !!feeOut return { verificationStatus: 'SUCCESS', @@ -375,52 +382,6 @@ export class SwapVerificationService { } } - private async verifyMaya(swap: Swap): Promise { - const txHash = swap.sellTxHash || undefined - - if (!txHash) return noAffiliateResult('FAILED', 'Missing txHash for Maya verification') - - // SECURITY: Query Maya node API to verify memo contains affiliate info - const txUrl = `${this.mayachainNodeUrl}/mayachain/tx/${txHash}` - - this.logger.log(`Maya - Fetching tx from node API: ${txUrl}`) - - const response = await firstValueFrom(this.httpService.get(txUrl)) - - const observedTx = response.data?.observed_tx - - if (!observedTx || !observedTx.tx) return noAffiliateResult('PENDING', 'No observed transaction found') - - const memo: string | undefined = observedTx.tx.memo - // Observed tx's memo is immutable on chain — absence is definitive, not transient. - if (!memo) return noAffiliateResult('SUCCESS', 'No memo found in transaction') - - // Parse memo format: =:r:maya1dz68dtlzrxnjflha9vvs7yt7p77mqdnf5yugww:131082237:ss:0 - // The affiliate code is after the 4th colon, followed by fee in bps - const memoPattern = new RegExp(`:${this.shapeshiftMayaAffiliate}:(\\d+)`, 'i') - const memoMatch = memo.match(memoPattern) - - const hasShapeshiftAffiliate = !!memoMatch - const affiliateBps = memoMatch ? parseInt(memoMatch[1]) : undefined - - const coins = observedTx.tx.coins - const sellAssetPrecision = swap.sellAsset.precision ?? THORCHAIN_PRECISION - const firstCoinAmount = coins?.[0]?.amount - const verifiedSellAmountCryptoBaseUnit = firstCoinAmount - ? thorchainToNativePrecision(firstCoinAmount, sellAssetPrecision) - : undefined - - return { - verificationStatus: 'SUCCESS', - hasAffiliate: hasShapeshiftAffiliate, - affiliateBps: hasShapeshiftAffiliate && affiliateBps ? affiliateBps : undefined, - affiliateAddress: hasShapeshiftAffiliate ? this.shapeshiftMayaAffiliate : undefined, - verifiedSellAmountCryptoBaseUnit, - actualBuyAmountCryptoBaseUnit: undefined, - actualAffiliateFeeAmountCryptoBaseUnit: undefined, - } - } - private async verifyChainflip(swap: Swap): Promise { const metadata = swap.metadata as Record const chainflipSwapId = metadata?.chainflipSwapId as string | undefined diff --git a/apps/swap-service/src/verification/types.ts b/apps/swap-service/src/verification/types.ts index fb6c58a..69b5054 100644 --- a/apps/swap-service/src/verification/types.ts +++ b/apps/swap-service/src/verification/types.ts @@ -1,12 +1,3 @@ -export interface ThorchainMayaTxResponse { - observed_tx?: { - tx?: { - memo?: string - coins?: Array<{ amount?: string }> - } - } -} - export type MidgardCoin = { amount: string asset: string