diff --git a/packages/chain-adapters/src/types.ts b/packages/chain-adapters/src/types.ts index 05ddb7bc564..f4351eb28be 100644 --- a/packages/chain-adapters/src/types.ts +++ b/packages/chain-adapters/src/types.ts @@ -106,7 +106,10 @@ export type GetBIP44ParamsInput = { export type TransferType = unchained.TransferType export type TradeType = unchained.TradeType -export type TxMetadata = unchained.evm.TxMetadata | unchained.cosmossdk.TxMetadata +export type TxMetadata = + | unchained.evm.TxMetadata + | unchained.cosmossdk.TxMetadata + | unchained.utxo.TxMetadata export type Transaction = Omit & { transfers: TxTransfer[] diff --git a/packages/chain-adapters/src/utxo/UtxoBaseAdapter.ts b/packages/chain-adapters/src/utxo/UtxoBaseAdapter.ts index 4683f9e726c..c7f68f38eec 100644 --- a/packages/chain-adapters/src/utxo/UtxoBaseAdapter.ts +++ b/packages/chain-adapters/src/utxo/UtxoBaseAdapter.ts @@ -77,6 +77,7 @@ export interface ChainAdapterArgs { | unchained.litecoin.V1Api ws: unchained.ws.Client } + midgardUrl: string } export interface UtxoBaseAdapterArgs extends ChainAdapterArgs { @@ -491,10 +492,10 @@ export abstract class UtxoBaseAdapter implements IChainAd blockHash: parsedTx.blockHash, blockHeight: parsedTx.blockHeight, blockTime: parsedTx.blockTime, - chainId: parsedTx.chainId, chain: this.getType(), + chainId: parsedTx.chainId, confirmations: parsedTx.confirmations, - txid: parsedTx.txid, + data: parsedTx.data, fee: parsedTx.fee, status: parsedTx.status, trade: parsedTx.trade, @@ -505,6 +506,7 @@ export abstract class UtxoBaseAdapter implements IChainAd type: transfer.type, value: transfer.totalValue, })), + txid: parsedTx.txid, } }), ) @@ -558,6 +560,7 @@ export abstract class UtxoBaseAdapter implements IChainAd blockTime: tx.blockTime, chainId: tx.chainId, confirmations: tx.confirmations, + data: tx.data, fee: tx.fee, status: tx.status, trade: tx.trade, diff --git a/packages/chain-adapters/src/utxo/bitcoin/BitcoinChainAdapter.test.ts b/packages/chain-adapters/src/utxo/bitcoin/BitcoinChainAdapter.test.ts index e4e5f1ba7ad..6b9923e3a6f 100644 --- a/packages/chain-adapters/src/utxo/bitcoin/BitcoinChainAdapter.test.ts +++ b/packages/chain-adapters/src/utxo/bitcoin/BitcoinChainAdapter.test.ts @@ -136,6 +136,7 @@ describe('BitcoinChainAdapter', () => { }, coinName: 'Bitcoin', chainId: KnownChainIds.BitcoinMainnet, + midgardUrl: '', } }) diff --git a/packages/chain-adapters/src/utxo/bitcoin/BitcoinChainAdapter.ts b/packages/chain-adapters/src/utxo/bitcoin/BitcoinChainAdapter.ts index 78949dd4a6a..c30551054ab 100644 --- a/packages/chain-adapters/src/utxo/bitcoin/BitcoinChainAdapter.ts +++ b/packages/chain-adapters/src/utxo/bitcoin/BitcoinChainAdapter.ts @@ -33,6 +33,7 @@ export class ChainAdapter extends UtxoBaseAdapter parser: new unchained.bitcoin.TransactionParser({ assetId: btcAssetId, chainId: args.chainId ?? DEFAULT_CHAIN_ID, + midgardUrl: args.midgardUrl, }), supportedAccountTypes: SUPPORTED_ACCOUNT_TYPES, supportedChainIds: SUPPORTED_CHAIN_IDS, diff --git a/packages/chain-adapters/src/utxo/bitcoincash/BitcoinCashChainAdapter.test.ts b/packages/chain-adapters/src/utxo/bitcoincash/BitcoinCashChainAdapter.test.ts index 2e6b0e32b59..ce9a574b99d 100644 --- a/packages/chain-adapters/src/utxo/bitcoincash/BitcoinCashChainAdapter.test.ts +++ b/packages/chain-adapters/src/utxo/bitcoincash/BitcoinCashChainAdapter.test.ts @@ -141,6 +141,7 @@ describe('BitcoinCashChainAdapter', () => { }, coinName: 'BitcoinCash', chainId: KnownChainIds.BitcoinCashMainnet, + midgardUrl: '', } }) diff --git a/packages/chain-adapters/src/utxo/bitcoincash/BitcoinCashChainAdapter.ts b/packages/chain-adapters/src/utxo/bitcoincash/BitcoinCashChainAdapter.ts index 5b6d830be94..5dab5ad54b7 100644 --- a/packages/chain-adapters/src/utxo/bitcoincash/BitcoinCashChainAdapter.ts +++ b/packages/chain-adapters/src/utxo/bitcoincash/BitcoinCashChainAdapter.ts @@ -29,6 +29,7 @@ export class ChainAdapter extends UtxoBaseAdapter { }, coinName: 'Dogecoin', chainId: KnownChainIds.DogecoinMainnet, + midgardUrl: '', } }) diff --git a/packages/chain-adapters/src/utxo/dogecoin/DogecoinChainAdapter.ts b/packages/chain-adapters/src/utxo/dogecoin/DogecoinChainAdapter.ts index 47b3c4bf149..f779a5d0bfa 100644 --- a/packages/chain-adapters/src/utxo/dogecoin/DogecoinChainAdapter.ts +++ b/packages/chain-adapters/src/utxo/dogecoin/DogecoinChainAdapter.ts @@ -31,6 +31,7 @@ export class ChainAdapter extends UtxoBaseAdapter parser: new unchained.dogecoin.TransactionParser({ assetId: dogeAssetId, chainId: args.chainId ?? DEFAULT_CHAIN_ID, + midgardUrl: args.midgardUrl, }), supportedAccountTypes: SUPPORTED_ACCOUNT_TYPES, supportedChainIds: SUPPORTED_CHAIN_IDS, diff --git a/packages/chain-adapters/src/utxo/litecoin/LitecoinChainAdapter.test.ts b/packages/chain-adapters/src/utxo/litecoin/LitecoinChainAdapter.test.ts index f496d8b4f08..ed8abd3455e 100644 --- a/packages/chain-adapters/src/utxo/litecoin/LitecoinChainAdapter.test.ts +++ b/packages/chain-adapters/src/utxo/litecoin/LitecoinChainAdapter.test.ts @@ -130,6 +130,7 @@ describe('LitecoinChainAdapter', () => { }, coinName: 'Litecoin', chainId: KnownChainIds.LitecoinMainnet, + midgardUrl: '', } }) diff --git a/packages/chain-adapters/src/utxo/litecoin/LitecoinChainAdapter.ts b/packages/chain-adapters/src/utxo/litecoin/LitecoinChainAdapter.ts index 114d0c3c807..bbe1cb40c52 100644 --- a/packages/chain-adapters/src/utxo/litecoin/LitecoinChainAdapter.ts +++ b/packages/chain-adapters/src/utxo/litecoin/LitecoinChainAdapter.ts @@ -33,6 +33,7 @@ export class ChainAdapter extends UtxoBaseAdapter parser: new unchained.litecoin.TransactionParser({ assetId: ltcAssetId, chainId: args.chainId ?? DEFAULT_CHAIN_ID, + midgardUrl: args.midgardUrl, }), supportedAccountTypes: SUPPORTED_ACCOUNT_TYPES, supportedChainIds: SUPPORTED_CHAIN_IDS, diff --git a/packages/unchained-client/src/types.ts b/packages/unchained-client/src/types.ts index d6e322f8234..c5fcd10c7d5 100644 --- a/packages/unchained-client/src/types.ts +++ b/packages/unchained-client/src/types.ts @@ -34,6 +34,7 @@ export interface Trade { // these are user facing values, and should be rendered as such export enum TradeType { Trade = 'Trade', + Swap = 'Swap', Refund = 'Refund', } diff --git a/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/bitcoin.test.ts b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/bitcoin.test.ts index 0975a3e0eb7..f4ac15d1059 100644 --- a/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/bitcoin.test.ts +++ b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/bitcoin.test.ts @@ -1,13 +1,49 @@ import { btcAssetId, btcChainId } from '@shapeshiftoss/caip' -import { describe, expect, it } from 'vitest' +import { describe, expect, it, vi } from 'vitest' -import type { ParsedTx } from '../../../../types' -import { TransferType, TxStatus } from '../../../../types' +import type { Trade } from '../../../../types' +import { Dex, TradeType, TransferType, TxStatus } from '../../../../types' +import type { ParsedTx } from '../../../parser' import { TransactionParser } from '../index' import standardNoChange from './mockData/standardNoChange' import standardWithChange from './mockData/standardWithChange' +import thorchainLoanOpen from './mockData/thorchainLoanOpen' +import thorchainLoanOpenRefund from './mockData/thorchainLoanOpenRefund' +import thorchainLoanOutbound from './mockData/thorchainLoanOutbound' +import thorchainLoanRepayment from './mockData/thorchainLoanRepayment' +import thorchainLoanRepaymentRefund from './mockData/thorchainLoanRepaymentRefund' +import thorchainLpDeposit from './mockData/thorchainLpDeposit' +import thorchainLpOutbound from './mockData/thorchainLpOutbound' +import thorchainLpRefund from './mockData/thorchainLpRefund' +import thorchainLpWithdraw from './mockData/thorchainLpWithdraw' +import thorchainSaversDeposit from './mockData/thorchainSaversDeposit' +import thorchainSaversOutbound from './mockData/thorchainSaversOutbound' +import thorchainSaversRefund from './mockData/thorchainSaversRefund' +import thorchainSaversWithdraw from './mockData/thorchainSaversWithdraw' +import thorchainStreamingSwap from './mockData/thorchainStreamingSwap' +import thorchainStreamingSwapOutbound from './mockData/thorchainStreamingSwapOutbound' +import thorchainStreamingSwapRefund from './mockData/thorchainStreamingSwapRefund' +import thorchainSwap from './mockData/thorchainSwap' +import thorchainSwapOutbound from './mockData/thorchainSwapOutbound' +import thorchainSwapRefund from './mockData/thorchainSwapRefund' -const txParser = new TransactionParser({ chainId: btcChainId, assetId: btcAssetId }) +const mocks = vi.hoisted(() => ({ + get: vi.fn(), +})) + +vi.mock('axios', () => { + const mockAxios = { + create: vi.fn(() => ({ + get: mocks.get, + })), + } + + return { + default: mockAxios, + } +}) + +const txParser = new TransactionParser({ chainId: btcChainId, assetId: btcAssetId, midgardUrl: '' }) describe('parseTx', () => { describe('standard', () => { @@ -220,4 +256,738 @@ describe('parseTx', () => { expect(expected).toEqual(actual) }) }) + + describe('thorchain', () => { + it('should be able to parse swap', async () => { + const { tx } = thorchainSwap + const address = 'bc1qhj86s3evc2y9wawecemntq8sp0c3mqmaagmqjd' + const memo = '=:GAIA.ATOM:cosmos1aywmluxanawepu2g2vpe3a449ashlxy04l2mcc:37207e5:rg:25' + + const trade: Trade = { + dexName: Dex.Thor, + memo, + type: TradeType.Swap, + } + + const expected: ParsedTx = { + txid: tx.txid, + blockHash: tx.blockHash, + blockHeight: tx.blockHeight, + blockTime: tx.timestamp, + confirmations: tx.confirmations, + status: TxStatus.Confirmed, + address, + chainId: btcChainId, + fee: { + assetId: btcAssetId, + value: '40128', + }, + transfers: [ + { + type: TransferType.Send, + from: address, + to: 'bc1qgpa0uz3ph4076j4f3kjxgzzd6t5298sdtjvwc9', + assetId: btcAssetId, + totalValue: '881809', + components: [{ value: '161139' }, { value: '720670' }], + }, + { + type: TransferType.Receive, + from: address, + to: address, + assetId: btcAssetId, + totalValue: '59872', + components: [{ value: '59872' }], + }, + ], + data: { parser: 'thorchain', memo, swap: { type: 'Standard' } }, + trade, + } + + const actual = await txParser.parse(tx, address) + + expect(actual).toEqual(expected) + }) + + it('should be able to parse swap outbound', async () => { + const { tx, actionsResponse } = thorchainSwapOutbound + const address = 'bc1qtgsttdcy3z67hegc36l99egdm36va0m5r0gece' + const memo = 'OUT:B5FE4F2D310D32ADD3D70C1E806E224943A08E73AC89287AB374B6566C4605D8' + + mocks.get.mockImplementationOnce(() => ({ data: actionsResponse })) + + const expected: ParsedTx = { + txid: tx.txid, + blockHash: tx.blockHash, + blockHeight: tx.blockHeight, + blockTime: tx.timestamp, + confirmations: tx.confirmations, + status: TxStatus.Confirmed, + address, + chainId: btcChainId, + transfers: [ + { + type: TransferType.Receive, + from: 'bc1qh7cjvuc3gtt3r4afm0zqvhvrpkfw0ahxrfwfgu', + to: address, + assetId: btcAssetId, + totalValue: '24574773', + components: [{ value: '24574773' }], + }, + ], + data: { parser: 'thorchain', memo, method: 'swapOut', swap: { type: 'Standard' } }, + } + + const actual = await txParser.parse(tx, address) + + expect(actual).toEqual(expected) + }) + + it('should be able to parse swap refund', async () => { + const { tx, actionsResponse } = thorchainSwapRefund + const address = 'bc1qss42t2tk76cst7267xj4jsuddqea69zgdkql89' + const memo = 'REFUND:1A15D2C488FCA6FE4B50A930BDFCF320DAD6FCFF629B8D91310648E35FCEE967' + + mocks.get.mockImplementationOnce(() => ({ data: actionsResponse })) + + const expected: ParsedTx = { + txid: tx.txid, + blockHash: tx.blockHash, + blockHeight: tx.blockHeight, + blockTime: tx.timestamp, + confirmations: tx.confirmations, + status: TxStatus.Confirmed, + address, + chainId: btcChainId, + transfers: [ + { + type: TransferType.Receive, + from: 'bc1qgpa0uz3ph4076j4f3kjxgzzd6t5298sdtjvwc9', + to: address, + assetId: btcAssetId, + totalValue: '2943300', + components: [{ value: '2943300' }], + }, + ], + data: { parser: 'thorchain', memo, method: 'swapRefund', swap: { type: 'Standard' } }, + } + + const actual = await txParser.parse(tx, address) + + expect(actual).toEqual(expected) + }) + + it('should be able to parse streaming swap', async () => { + const { tx } = thorchainStreamingSwap + const address = 'bc1q0aajfmjr9a007zadm60lusdl2lqtexars8aul3' + const memo = '=:ETH.USDT-EC7:0x6057d2D9f07e06FA0836a17a4e4F0044d8F02912:0/1/0:ti:70' + + const trade: Trade = { + dexName: Dex.Thor, + memo, + type: TradeType.Swap, + } + + const expected: ParsedTx = { + txid: tx.txid, + blockHash: tx.blockHash, + blockHeight: tx.blockHeight, + blockTime: tx.timestamp, + confirmations: tx.confirmations, + status: TxStatus.Confirmed, + address, + chainId: btcChainId, + fee: { + assetId: btcAssetId, + value: '11484', + }, + transfers: [ + { + type: TransferType.Send, + from: address, + to: 'bc1qgpa0uz3ph4076j4f3kjxgzzd6t5298sdtjvwc9', + assetId: btcAssetId, + totalValue: '689420', + components: [{ value: '689420' }], + }, + { + type: TransferType.Receive, + from: address, + to: address, + assetId: btcAssetId, + totalValue: '469636', + components: [{ value: '469636' }], + }, + ], + data: { parser: 'thorchain', memo, swap: { type: 'Streaming' } }, + trade, + } + + const actual = await txParser.parse(tx, address) + + expect(actual).toEqual(expected) + }) + + it('should be able to parse streaming swap outbound', async () => { + const { tx, actionsResponse } = thorchainStreamingSwapOutbound + const address = 'bc1qk8mhj9j5rsz7j7ymv92t2mv5fcqfgt7scn9p72' + const memo = 'OUT:08A863D310AECF008B4A9742A596603EA008C682B4E48FF8FF80C408FBE72EB3' + + mocks.get.mockImplementationOnce(() => ({ data: actionsResponse })) + + const expected: ParsedTx = { + txid: tx.txid, + blockHash: tx.blockHash, + blockHeight: tx.blockHeight, + blockTime: tx.timestamp, + confirmations: tx.confirmations, + status: TxStatus.Confirmed, + address, + chainId: btcChainId, + transfers: [ + { + type: TransferType.Receive, + from: 'bc1qsqwywyfq3dhrmu3kh8emh2l6u5hde7szxpg99j', + to: address, + assetId: btcAssetId, + totalValue: '116388', + components: [{ value: '116388' }], + }, + ], + data: { parser: 'thorchain', memo, method: 'swapOut', swap: { type: 'Streaming' } }, + } + + const actual = await txParser.parse(tx, address) + + expect(actual).toEqual(expected) + }) + + it('should be able to parse streaming swap refund', async () => { + const { tx, actionsResponse } = thorchainStreamingSwapRefund + const address = 'bc1qafsug8uvhxga5ua9q99k46nhd680e97n26egzc' + const memo = 'REFUND:08933D25AD065A6C96E60BA2A0E5DED23810E8A303D3E06192BD9393149D5002' + + mocks.get.mockImplementationOnce(() => ({ data: actionsResponse })) + + const expected: ParsedTx = { + txid: tx.txid, + blockHash: tx.blockHash, + blockHeight: tx.blockHeight, + blockTime: tx.timestamp, + confirmations: tx.confirmations, + status: TxStatus.Confirmed, + address, + chainId: btcChainId, + transfers: [ + { + type: TransferType.Receive, + from: 'bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q', + to: address, + assetId: btcAssetId, + totalValue: '117553237', + components: [{ value: '117553237' }], + }, + ], + data: { parser: 'thorchain', memo, method: 'swapRefund', swap: { type: 'Streaming' } }, + } + + const actual = await txParser.parse(tx, address) + + expect(actual).toEqual(expected) + }) + + it('should be able to parse savers deposit', async () => { + const { tx } = thorchainSaversDeposit + const address = 'bc1qqfcte3j9jgaa7p3uxr6fntqpad269vv2wvmzss' + const memo = '+:BTC/BTC::t:0' + + const expected: ParsedTx = { + txid: tx.txid, + blockHash: tx.blockHash, + blockHeight: tx.blockHeight, + blockTime: tx.timestamp, + confirmations: tx.confirmations, + status: TxStatus.Confirmed, + address, + chainId: btcChainId, + fee: { + assetId: btcAssetId, + value: '26058', + }, + transfers: [ + { + type: TransferType.Send, + from: address, + to: 'bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q', + assetId: btcAssetId, + totalValue: '17494111', + components: [{ value: '17494111' }], + }, + ], + data: { parser: 'thorchain', method: 'deposit', memo, liquidity: { type: 'Savers' } }, + } + + const actual = await txParser.parse(tx, address) + + expect(actual).toEqual(expected) + }) + + it('should be able to parse savers withdraw', async () => { + const { tx } = thorchainSaversWithdraw + const address = 'bc1quneer6jgruq5ltatkjcl3rq75u0pzzlnrfkj5j' + const memo = '-:BTC/BTC:10000' + + const expected: ParsedTx = { + txid: tx.txid, + blockHash: tx.blockHash, + blockHeight: tx.blockHeight, + blockTime: tx.timestamp, + confirmations: tx.confirmations, + status: TxStatus.Confirmed, + address, + chainId: btcChainId, + fee: { + assetId: btcAssetId, + value: '17640', + }, + transfers: [ + { + type: TransferType.Send, + from: address, + to: 'bc1qgpa0uz3ph4076j4f3kjxgzzd6t5298sdtjvwc9', + assetId: btcAssetId, + totalValue: '371369', + components: [{ value: '371369' }], + }, + { + type: TransferType.Receive, + from: address, + to: address, + assetId: btcAssetId, + totalValue: '343728', + components: [{ value: '343728' }], + }, + ], + data: { parser: 'thorchain', method: 'withdraw', memo, liquidity: { type: 'Savers' } }, + } + + const actual = await txParser.parse(tx, address) + + expect(actual).toEqual(expected) + }) + + it('should be able to parse savers outbound', async () => { + const { tx, actionsResponse } = thorchainSaversOutbound + const address = 'bc1qgc62l320e29qg3cadhxn65kldp308n6epn07ej' + const memo = 'OUT:67F019E338BE8682A7D2C988277B8F32FC197F429CC43AA9B195C14F9597741E' + + mocks.get.mockImplementationOnce(() => ({ data: actionsResponse })) + + const expected: ParsedTx = { + txid: tx.txid, + blockHash: tx.blockHash, + blockHeight: tx.blockHeight, + blockTime: tx.timestamp, + confirmations: tx.confirmations, + status: TxStatus.Confirmed, + address, + chainId: btcChainId, + transfers: [ + { + type: TransferType.Receive, + from: 'bc1qsqwywyfq3dhrmu3kh8emh2l6u5hde7szxpg99j', + to: address, + assetId: btcAssetId, + totalValue: '1166419', + components: [{ value: '1166419' }], + }, + ], + data: { parser: 'thorchain', memo, method: 'withdrawOut', liquidity: { type: 'Savers' } }, + } + + const actual = await txParser.parse(tx, address) + + expect(actual).toEqual(expected) + }) + + it('should be able to parse savers refund', async () => { + const { tx, actionsResponse } = thorchainSaversRefund + const address = 'bc1qw400vxxng36x052q8gthtvm3ujnl5xz957p2ma' + const memo = 'REFUND:B25446E18F1B3A8D03708EAB1636C4B35E218AF05BE3FD8A811D39953CBF909A' + + mocks.get.mockImplementationOnce(() => ({ data: actionsResponse })) + + const expected: ParsedTx = { + txid: tx.txid, + blockHash: tx.blockHash, + blockHeight: tx.blockHeight, + blockTime: tx.timestamp, + confirmations: tx.confirmations, + status: TxStatus.Confirmed, + address, + chainId: btcChainId, + transfers: [ + { + type: TransferType.Receive, + from: 'bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q', + to: address, + assetId: btcAssetId, + totalValue: '1132183', + components: [{ value: '1132183' }], + }, + ], + data: { parser: 'thorchain', memo, method: 'depositRefund', liquidity: { type: 'Savers' } }, + } + + const actual = await txParser.parse(tx, address) + + expect(actual).toEqual(expected) + }) + + it('should be able to parse lp deposit', async () => { + const { tx } = thorchainLpDeposit + const address = 'bc1qn72fnd27rfk33jx6pmglnl6x2e07c8cxnahrgj' + const memo = '+:BTC.BTC::t:0' + + const expected: ParsedTx = { + txid: tx.txid, + blockHash: tx.blockHash, + blockHeight: tx.blockHeight, + blockTime: tx.timestamp, + confirmations: tx.confirmations, + status: TxStatus.Confirmed, + address, + chainId: btcChainId, + fee: { + assetId: btcAssetId, + value: '35250', + }, + transfers: [ + { + type: TransferType.Send, + from: address, + to: 'bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q', + assetId: btcAssetId, + totalValue: '90800000', + components: [{ value: '80800000' }, { value: '10000000' }], + }, + { + type: TransferType.Receive, + from: address, + to: address, + assetId: btcAssetId, + totalValue: '764750', + components: [{ value: '764750' }], + }, + ], + data: { parser: 'thorchain', method: 'deposit', memo, liquidity: { type: 'LP' } }, + } + + const actual = await txParser.parse(tx, address) + + expect(actual).toEqual(expected) + }) + + it('should be able to parse lp withdraw', async () => { + const { tx } = thorchainLpWithdraw + const address = 'bc1q9sqrn9gyjqjuds7gf66nwm6vr54eyfqdj86qxd' + const memo = '-:BTC.BTC:10000' + + const expected: ParsedTx = { + txid: tx.txid, + blockHash: tx.blockHash, + blockHeight: tx.blockHeight, + blockTime: tx.timestamp, + confirmations: tx.confirmations, + status: TxStatus.Confirmed, + address, + chainId: btcChainId, + fee: { + assetId: btcAssetId, + value: '17640', + }, + transfers: [ + { + type: TransferType.Send, + from: address, + to: 'bc1qgpa0uz3ph4076j4f3kjxgzzd6t5298sdtjvwc9', + assetId: btcAssetId, + totalValue: '2000000', + components: [{ value: '2000000' }], + }, + { + type: TransferType.Receive, + from: address, + to: address, + assetId: btcAssetId, + totalValue: '1972359', + components: [{ value: '1972359' }], + }, + ], + data: { parser: 'thorchain', method: 'withdraw', memo, liquidity: { type: 'LP' } }, + } + + const actual = await txParser.parse(tx, address) + + expect(actual).toEqual(expected) + }) + + it('should be able to parse lp outbound', async () => { + const { tx, actionsResponse } = thorchainLpOutbound + const address = 'bc1qpaue8hq4zcyzsys02pr0yxr60s6hsz6yt6h493' + const memo = 'OUT:85CEF3183958A805643C6BD93169AC2ED30051C21F19CBF5B26161CC5AF89659' + + mocks.get.mockImplementationOnce(() => ({ data: actionsResponse })) + + const expected: ParsedTx = { + txid: tx.txid, + blockHash: tx.blockHash, + blockHeight: tx.blockHeight, + blockTime: tx.timestamp, + confirmations: tx.confirmations, + status: TxStatus.Confirmed, + address, + chainId: btcChainId, + transfers: [ + { + type: TransferType.Receive, + from: 'bc1qsqwywyfq3dhrmu3kh8emh2l6u5hde7szxpg99j', + to: address, + assetId: btcAssetId, + totalValue: '914306', + components: [{ value: '914306' }], + }, + ], + data: { parser: 'thorchain', memo, method: 'withdrawOut', liquidity: { type: 'LP' } }, + } + + const actual = await txParser.parse(tx, address) + + expect(actual).toEqual(expected) + }) + + it('should be able to parse lp refund', async () => { + const { tx, actionsResponse } = thorchainLpRefund + const address = 'bc1qw400vxxng36x052q8gthtvm3ujnl5xz957p2ma' + const memo = 'REFUND:B25446E18F1B3A8D03708EAB1636C4B35E218AF05BE3FD8A811D39953CBF909A' + + mocks.get.mockImplementationOnce(() => ({ data: actionsResponse })) + + const expected: ParsedTx = { + txid: tx.txid, + blockHash: tx.blockHash, + blockHeight: tx.blockHeight, + blockTime: tx.timestamp, + confirmations: tx.confirmations, + status: TxStatus.Confirmed, + address, + chainId: btcChainId, + transfers: [ + { + type: TransferType.Receive, + from: 'bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q', + to: address, + assetId: btcAssetId, + totalValue: '1132183', + components: [{ value: '1132183' }], + }, + ], + data: { parser: 'thorchain', memo, method: 'depositRefund', liquidity: { type: 'LP' } }, + } + + const actual = await txParser.parse(tx, address) + + expect(actual).toEqual(expected) + }) + + it('should be able to parse loan open', async () => { + const { tx } = thorchainLoanOpen + const address = 'bc1qdvzzsscn056p6k0xe0y05ray32g8a5pzs74qra' + const memo = '$+:THOR.RUNE:thor1h7jfggcpqvc4dz546wm9etlgsas0x6su3q490w' + + const expected: ParsedTx = { + txid: tx.txid, + blockHash: tx.blockHash, + blockHeight: tx.blockHeight, + blockTime: tx.timestamp, + confirmations: tx.confirmations, + status: TxStatus.Confirmed, + address, + chainId: btcChainId, + fee: { + assetId: btcAssetId, + value: '15822', + }, + transfers: [ + { + type: TransferType.Send, + from: address, + to: 'bc1qh7cjvuc3gtt3r4afm0zqvhvrpkfw0ahxrfwfgu', + assetId: btcAssetId, + totalValue: '5300894', + components: [{ value: '5300894' }], + }, + { + type: TransferType.Receive, + from: address, + to: address, + assetId: btcAssetId, + totalValue: '65072', + components: [{ value: '65072' }], + }, + ], + data: { parser: 'thorchain', method: 'loanOpen', memo }, + } + + const actual = await txParser.parse(tx, address) + + expect(actual).toEqual(expected) + }) + + it('should be able to parse loan repayment', async () => { + const { tx } = thorchainLoanRepayment + const address = 'bc1q3a2me0crkm0ap27ythdavfa20l2tgw3cs4tf4k' + const memo = '$-:BTC.BTC:bc1q3a2me0crkm0ap27ythdavfa20l2tgw3cs4tf4k' + + const expected: ParsedTx = { + txid: tx.txid, + blockHash: tx.blockHash, + blockHeight: tx.blockHeight, + blockTime: tx.timestamp, + confirmations: tx.confirmations, + status: TxStatus.Confirmed, + address, + chainId: btcChainId, + fee: { + assetId: btcAssetId, + value: '19140', + }, + transfers: [ + { + type: TransferType.Send, + from: address, + to: 'bc1qh7cjvuc3gtt3r4afm0zqvhvrpkfw0ahxrfwfgu', + assetId: btcAssetId, + totalValue: '20222437', + components: [{ value: '20222437' }], + }, + { + type: TransferType.Receive, + from: address, + to: address, + assetId: btcAssetId, + totalValue: '2530623', + components: [{ value: '2530623' }], + }, + ], + data: { parser: 'thorchain', method: 'loanRepayment', memo }, + } + + const actual = await txParser.parse(tx, address) + + expect(actual).toEqual(expected) + }) + + it('should be able to parse loan outbound', async () => { + const { tx, actionsResponse } = thorchainLoanOutbound + const address = 'bc1q269j5rs4rm5tjpvm6adcchhvgmghc4p46250ra' + const memo = 'OUT:5378E62D1426BA399753583F01E8655C508DE22903352D1CAFA10942222CF7A1' + + mocks.get.mockImplementationOnce(() => ({ data: actionsResponse })) + + const expected: ParsedTx = { + txid: tx.txid, + blockHash: tx.blockHash, + blockHeight: tx.blockHeight, + blockTime: tx.timestamp, + confirmations: tx.confirmations, + status: TxStatus.Confirmed, + address, + chainId: btcChainId, + transfers: [ + { + type: TransferType.Receive, + from: 'bc1qh7cjvuc3gtt3r4afm0zqvhvrpkfw0ahxrfwfgu', + to: address, + assetId: btcAssetId, + totalValue: '14954979', + components: [{ value: '14954979' }], + }, + ], + data: { parser: 'thorchain', memo, method: 'loanOut' }, + } + + const actual = await txParser.parse(tx, address) + + expect(actual).toEqual(expected) + }) + + it('should be able to parse loan open refund', async () => { + const { tx, actionsResponse } = thorchainLoanOpenRefund + const address = 'bc1q269j5rs4rm5tjpvm6adcchhvgmghc4p46250ra' + const memo = 'REFUND:5378E62D1426BA399753583F01E8655C508DE22903352D1CAFA10942222CF7A1' + + mocks.get.mockImplementationOnce(() => ({ data: actionsResponse })) + + const expected: ParsedTx = { + txid: tx.txid, + blockHash: tx.blockHash, + blockHeight: tx.blockHeight, + blockTime: tx.timestamp, + confirmations: tx.confirmations, + status: TxStatus.Confirmed, + address, + chainId: btcChainId, + transfers: [ + { + type: TransferType.Receive, + from: 'bc1qh7cjvuc3gtt3r4afm0zqvhvrpkfw0ahxrfwfgu', + to: address, + assetId: btcAssetId, + totalValue: '14954979', + components: [{ value: '14954979' }], + }, + ], + data: { parser: 'thorchain', method: 'loanOpenRefund', memo }, + } + + const actual = await txParser.parse(tx, address) + + expect(actual).toEqual(expected) + }) + + it('should be able to parse loan repayment refund', async () => { + const { tx, actionsResponse } = thorchainLoanRepaymentRefund + const address = 'bc1q269j5rs4rm5tjpvm6adcchhvgmghc4p46250ra' + const memo = 'REFUND:5378E62D1426BA399753583F01E8655C508DE22903352D1CAFA10942222CF7A1' + + mocks.get.mockImplementationOnce(() => ({ data: actionsResponse })) + + const expected: ParsedTx = { + txid: tx.txid, + blockHash: tx.blockHash, + blockHeight: tx.blockHeight, + blockTime: tx.timestamp, + confirmations: tx.confirmations, + status: TxStatus.Confirmed, + address, + chainId: btcChainId, + transfers: [ + { + type: TransferType.Receive, + from: 'bc1qh7cjvuc3gtt3r4afm0zqvhvrpkfw0ahxrfwfgu', + to: address, + assetId: btcAssetId, + totalValue: '14954979', + components: [{ value: '14954979' }], + }, + ], + data: { parser: 'thorchain', method: 'loanRepaymentRefund', memo }, + } + + const actual = await txParser.parse(tx, address) + + expect(actual).toEqual(expected) + }) + }) }) diff --git a/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainLoanOpen.ts b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainLoanOpen.ts new file mode 100644 index 00000000000..5e5e97253ad --- /dev/null +++ b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainLoanOpen.ts @@ -0,0 +1,48 @@ +import type { Tx } from '../../../index' + +const tx: Tx = { + txid: 'b4e88401bb9b2b3b17c376bf5a62efd968ddfdf796c55fd4e35d80695225c4dc', + blockHash: '00000000000000000003aafb9d8e1935a96f13272e34aa31b6c5e3d36860d190', + blockHeight: 824488, + timestamp: 1704466294, + confirmations: 576, + value: '5285072', + fee: '15822', + hex: '020000000001010fb364e4def910db9e7eb94f8d7329142f50e2ceb4445c231bc65884d8cc31530000000000ffffffff03a0a64f0000000000160014bfb126731142d711d7a9dbc4065d830d92e7f6e600000000000000003a6a38242b3a54484f522e52554e453a74686f723168376a666767637071766334647a353436776d3965746c67736173307836737533713439307730fe0000000000001600146b042843137d341d59e6cbc8fa0fa48a907ed0220247304402205219c65b3136500a0a3fc51680c3a56ae655c466c8e0a761242e88382dba129402207ec4edc56aa15378caa4dad7c1ad4f2154aa42fb77c365753d05b6425fca4bb101210229ddfcc67bb4e612c3d2ac6b140f725c2d53ce3afcfac2f7f7d8e59b1a4811cb00000000', + vin: [ + { + txid: '5331ccd88458c61b235c44b4cee2502f1429738d4fb97e9edb10f9dee464b30f', + sequence: 4294967295, + addresses: ['bc1qdvzzsscn056p6k0xe0y05ray32g8a5pzs74qra'], + value: '5300894', + }, + ], + vout: [ + { + value: '5220000', + n: 0, + scriptPubKey: { + hex: '0014bfb126731142d711d7a9dbc4065d830d92e7f6e6', + }, + addresses: ['bc1qh7cjvuc3gtt3r4afm0zqvhvrpkfw0ahxrfwfgu'], + }, + { + value: '0', + n: 1, + opReturn: 'OP_RETURN ($+:THOR.RUNE:thor1h7jfggcpqvc4dz546wm9etlgsas0x6su3q490w)', + scriptPubKey: { + hex: '6a38242b3a54484f522e52554e453a74686f723168376a666767637071766334647a353436776d3965746c677361733078367375337134393077', + }, + }, + { + value: '65072', + n: 2, + scriptPubKey: { + hex: '00146b042843137d341d59e6cbc8fa0fa48a907ed022', + }, + addresses: ['bc1qdvzzsscn056p6k0xe0y05ray32g8a5pzs74qra'], + }, + ], +} + +export default { tx } diff --git a/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainLoanOpenRefund.ts b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainLoanOpenRefund.ts new file mode 100644 index 00000000000..b42bfa6e394 --- /dev/null +++ b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainLoanOpenRefund.ts @@ -0,0 +1,109 @@ +import type { ActionsResponse } from '../../../../parser/thorchain' +import type { Tx } from '../../../index' + +// NOTE: this is not a real transaction as I was unable to find an actual bitcoin savers refund on chain + +const tx: Tx = { + txid: 'db19b42a99d5117f8e3b94d4f23e5f02157937f3c4d8371afd0a56b9dbfa084d', + blockHash: '000000000000000000039632dab0444fc966b3effd455154150cb4de84104bff', + blockHeight: 825076, + timestamp: 1704851622, + confirmations: 269, + value: '36691043911', + fee: '18236', + hex: '0100000000010151d7def92332fc9fc89b215da63638ac060c10db7ea831fdf2d0eb5cda36a5230100000000ffffffff03e331e40000000000160014568b2a0e151ee8b9059bd75b8c5eec46d17c543564b4108a08000000160014bfb126731142d711d7a9dbc4065d830d92e7f6e60000000000000000466a444f55543a3533373845363244313432364241333939373533353833463031453836353543353038444532323930333335324431434146413130393432323232434637413102473044022075a2ce69074b2f4bb48e9a75e0fa965a06cf3bfe84cac2e964b242ca29595df50220548018eef12f81f5e49d8216a1938f85c64684f700703d87e13a317c9b0808d7012102e04413afe986a11b20749ed3962058e1c9d8df9816ef399a22f57ab36801055f00000000', + vin: [ + { + txid: '23a536da5cebd0f2fd31a87edb100c06ac3836a65d219bc89ffc3223f9ded751', + vout: '1', + sequence: 4294967295, + addresses: ['bc1qh7cjvuc3gtt3r4afm0zqvhvrpkfw0ahxrfwfgu'], + value: '36691062147', + }, + ], + vout: [ + { + value: '14954979', + n: 0, + scriptPubKey: { + hex: '0014568b2a0e151ee8b9059bd75b8c5eec46d17c5435', + }, + addresses: ['bc1q269j5rs4rm5tjpvm6adcchhvgmghc4p46250ra'], + }, + { + value: '36676088932', + n: 1, + scriptPubKey: { + hex: '0014bfb126731142d711d7a9dbc4065d830d92e7f6e6', + }, + addresses: ['bc1qh7cjvuc3gtt3r4afm0zqvhvrpkfw0ahxrfwfgu'], + }, + { + value: '0', + n: 2, + opReturn: + 'OP_RETURN (REFUND:5378E62D1426BA399753583F01E8655C508DE22903352D1CAFA10942222CF7A1)', + scriptPubKey: { + hex: '6a444f55543a35333738453632443134323642413339393735333538334630314538363535433530384445323239303333353244314341464131303934323232324346374131', + }, + }, + ], +} + +const actionsResponse: ActionsResponse = { + actions: [ + { + date: '1702138875088627651', + height: '13782524', + in: [ + { + address: 'bc1qdvzzsscn056p6k0xe0y05ray32g8a5pzs74qra', + coins: [ + { + amount: '15954979', + asset: 'BTC.BTC', + }, + ], + txID: 'DB19B42A99D5117F8E3B94D4F23E5F02157937F3C4D8371AFD0A56B9DBFA084D', + }, + ], + metadata: { + refund: { + affiliateAddress: '', + affiliateFee: '0', + memo: '$+:ETH.ETH:0x8a7eAE0fbd128D33022e9d64D912f9903e0f5fcc:0', + networkFees: [ + { + amount: '64500', + asset: 'BTC.BTC', + }, + ], + reason: 'some refund reason', + }, + }, + out: [ + { + address: 'bc1q269j5rs4rm5tjpvm6adcchhvgmghc4p46250ra', + coins: [ + { + amount: '14954979', + asset: 'BTC.BTC', + }, + ], + height: '13783250', + txID: 'DB19B42A99D5117F8E3B94D4F23E5F02157937F3C4D8371AFD0A56B9DBFA084D', + }, + ], + pools: [], + status: 'success', + type: 'refund', + }, + ], + count: '1', + meta: { + nextPageToken: '137825241002020011', + prevPageToken: '137825241002020011', + }, +} + +export default { tx, actionsResponse } diff --git a/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainLoanOutbound.ts b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainLoanOutbound.ts new file mode 100644 index 00000000000..88d0f00da48 --- /dev/null +++ b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainLoanOutbound.ts @@ -0,0 +1,109 @@ +import type { ActionsResponse } from '../../../../parser/thorchain' +import type { Tx } from '../../../index' + +const tx: Tx = { + txid: 'db19b42a99d5117f8e3b94d4f23e5f02157937f3c4d8371afd0a56b9dbfa084d', + blockHash: '000000000000000000039632dab0444fc966b3effd455154150cb4de84104bff', + blockHeight: 825076, + timestamp: 1704851622, + confirmations: 269, + value: '36691043911', + fee: '18236', + hex: '0100000000010151d7def92332fc9fc89b215da63638ac060c10db7ea831fdf2d0eb5cda36a5230100000000ffffffff03e331e40000000000160014568b2a0e151ee8b9059bd75b8c5eec46d17c543564b4108a08000000160014bfb126731142d711d7a9dbc4065d830d92e7f6e60000000000000000466a444f55543a3533373845363244313432364241333939373533353833463031453836353543353038444532323930333335324431434146413130393432323232434637413102473044022075a2ce69074b2f4bb48e9a75e0fa965a06cf3bfe84cac2e964b242ca29595df50220548018eef12f81f5e49d8216a1938f85c64684f700703d87e13a317c9b0808d7012102e04413afe986a11b20749ed3962058e1c9d8df9816ef399a22f57ab36801055f00000000', + vin: [ + { + txid: '23a536da5cebd0f2fd31a87edb100c06ac3836a65d219bc89ffc3223f9ded751', + vout: '1', + sequence: 4294967295, + addresses: ['bc1qh7cjvuc3gtt3r4afm0zqvhvrpkfw0ahxrfwfgu'], + value: '36691062147', + }, + ], + vout: [ + { + value: '14954979', + n: 0, + scriptPubKey: { + hex: '0014568b2a0e151ee8b9059bd75b8c5eec46d17c5435', + }, + addresses: ['bc1q269j5rs4rm5tjpvm6adcchhvgmghc4p46250ra'], + }, + { + value: '36676088932', + n: 1, + scriptPubKey: { + hex: '0014bfb126731142d711d7a9dbc4065d830d92e7f6e6', + }, + addresses: ['bc1qh7cjvuc3gtt3r4afm0zqvhvrpkfw0ahxrfwfgu'], + }, + { + value: '0', + n: 2, + opReturn: 'OP_RETURN (OUT:5378E62D1426BA399753583F01E8655C508DE22903352D1CAFA10942222CF7A1)', + scriptPubKey: { + hex: '6a444f55543a35333738453632443134323642413339393735333538334630314538363535433530384445323239303333353244314341464131303934323232324346374131', + }, + }, + ], +} + +const actionsResponse: ActionsResponse = { + actions: [ + { + date: '1704845816294227234', + height: '14207666', + in: [ + { + address: '0x3c896c5163bfaa022b0df3f00613560df247adb4', + coins: [ + { + amount: '173556206700', + asset: 'ETH.USDT-0XDAC17F958D2EE523A2206206994597C13D831EC7', + }, + ], + txID: '5378E62D1426BA399753583F01E8655C508DE22903352D1CAFA10942222CF7A1', + }, + ], + metadata: { + swap: { + affiliateAddress: '', + affiliateFee: '0', + isStreamingSwap: false, + liquidityFee: '39241624', + memo: 'loan-:BTC.BTC:bc1q269j5rs4rm5tjpvm6adcchhvgmghc4p46250ra:0', + networkFees: [ + { + amount: '64500', + asset: 'BTC.BTC', + }, + ], + swapSlip: '11', + swapTarget: '0', + }, + }, + out: [ + { + address: 'bc1q269j5rs4rm5tjpvm6adcchhvgmghc4p46250ra', + coins: [ + { + amount: '14954979', + asset: 'BTC.BTC', + }, + ], + height: '14208401', + txID: 'DB19B42A99D5117F8E3B94D4F23E5F02157937F3C4D8371AFD0A56B9DBFA084D', + }, + ], + pools: ['ETH.USDT-0XDAC17F958D2EE523A2206206994597C13D831EC7', 'THOR.TOR'], + status: 'success', + type: 'swap', + }, + ], + count: '1', + meta: { + nextPageToken: '142076669000000016', + prevPageToken: '142076669000000016', + }, +} + +export default { tx, actionsResponse } diff --git a/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainLoanRepayment.ts b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainLoanRepayment.ts new file mode 100644 index 00000000000..199b9f253eb --- /dev/null +++ b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainLoanRepayment.ts @@ -0,0 +1,49 @@ +import type { Tx } from '../../../index' + +const tx: Tx = { + txid: '28858da8fd927ebef6c8eb5c4dc56e9fbb5007fbd9c4ddbff41af103b1faafe5', + blockHash: '000000000000000000008fa0238f5e117dbf3443dbdd3129446880413d605168', + blockHeight: 824798, + timestamp: 1704673512, + confirmations: 547, + value: '20203297', + fee: '19140', + hex: '020000000001013df989be242aecaa1af9b643f0c5a0a8d01f853283d0b045e6e2f1e37a2c7bbf0200000000ffffffff03e2a90d0100000000160014bfb126731142d711d7a9dbc4065d830d92e7f6e60000000000000000376a35242d3a4254432e4254433a626331713361326d653063726b6d3061703237797468646176666132306c32746777336373347466346b3f9d2600000000001600148f55bcbf03b6dfd0abc45ddbd627aa7fd4b43a380247304402204fa1392da4b56843df96a14e686f1a240de471670062fdc5ff67ffa293003842022014bc41e4bb390cd0c1ac0213697eae3841b1d229dae9432f9c67d1b181d57867012102132adbcafd051b36d6e1ad8ec720128d49a76033ce2a36c25ad9498637a21d8600000000', + vin: [ + { + txid: 'bf7b2c7ae3f1e2e645b0d08332851fd0a8a0c5f043b6f91aaaec2a24be89f93d', + vout: '2', + sequence: 4294967295, + addresses: ['bc1q3a2me0crkm0ap27ythdavfa20l2tgw3cs4tf4k'], + value: '20222437', + }, + ], + vout: [ + { + value: '17672674', + n: 0, + scriptPubKey: { + hex: '0014bfb126731142d711d7a9dbc4065d830d92e7f6e6', + }, + addresses: ['bc1qh7cjvuc3gtt3r4afm0zqvhvrpkfw0ahxrfwfgu'], + }, + { + value: '0', + n: 1, + opReturn: 'OP_RETURN ($-:BTC.BTC:bc1q3a2me0crkm0ap27ythdavfa20l2tgw3cs4tf4k)', + scriptPubKey: { + hex: '6a35242d3a4254432e4254433a626331713361326d653063726b6d3061703237797468646176666132306c32746777336373347466346b', + }, + }, + { + value: '2530623', + n: 2, + scriptPubKey: { + hex: '00148f55bcbf03b6dfd0abc45ddbd627aa7fd4b43a38', + }, + addresses: ['bc1q3a2me0crkm0ap27ythdavfa20l2tgw3cs4tf4k'], + }, + ], +} + +export default { tx } diff --git a/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainLoanRepaymentRefund.ts b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainLoanRepaymentRefund.ts new file mode 100644 index 00000000000..14c7d54847e --- /dev/null +++ b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainLoanRepaymentRefund.ts @@ -0,0 +1,109 @@ +import type { ActionsResponse } from '../../../../parser/thorchain' +import type { Tx } from '../../../index' + +// NOTE: this is not a real transaction as I was unable to find an actual bitcoin savers refund on chain + +const tx: Tx = { + txid: 'db19b42a99d5117f8e3b94d4f23e5f02157937f3c4d8371afd0a56b9dbfa084d', + blockHash: '000000000000000000039632dab0444fc966b3effd455154150cb4de84104bff', + blockHeight: 825076, + timestamp: 1704851622, + confirmations: 269, + value: '36691043911', + fee: '18236', + hex: '0100000000010151d7def92332fc9fc89b215da63638ac060c10db7ea831fdf2d0eb5cda36a5230100000000ffffffff03e331e40000000000160014568b2a0e151ee8b9059bd75b8c5eec46d17c543564b4108a08000000160014bfb126731142d711d7a9dbc4065d830d92e7f6e60000000000000000466a444f55543a3533373845363244313432364241333939373533353833463031453836353543353038444532323930333335324431434146413130393432323232434637413102473044022075a2ce69074b2f4bb48e9a75e0fa965a06cf3bfe84cac2e964b242ca29595df50220548018eef12f81f5e49d8216a1938f85c64684f700703d87e13a317c9b0808d7012102e04413afe986a11b20749ed3962058e1c9d8df9816ef399a22f57ab36801055f00000000', + vin: [ + { + txid: '23a536da5cebd0f2fd31a87edb100c06ac3836a65d219bc89ffc3223f9ded751', + vout: '1', + sequence: 4294967295, + addresses: ['bc1qh7cjvuc3gtt3r4afm0zqvhvrpkfw0ahxrfwfgu'], + value: '36691062147', + }, + ], + vout: [ + { + value: '14954979', + n: 0, + scriptPubKey: { + hex: '0014568b2a0e151ee8b9059bd75b8c5eec46d17c5435', + }, + addresses: ['bc1q269j5rs4rm5tjpvm6adcchhvgmghc4p46250ra'], + }, + { + value: '36676088932', + n: 1, + scriptPubKey: { + hex: '0014bfb126731142d711d7a9dbc4065d830d92e7f6e6', + }, + addresses: ['bc1qh7cjvuc3gtt3r4afm0zqvhvrpkfw0ahxrfwfgu'], + }, + { + value: '0', + n: 2, + opReturn: + 'OP_RETURN (REFUND:5378E62D1426BA399753583F01E8655C508DE22903352D1CAFA10942222CF7A1)', + scriptPubKey: { + hex: '6a444f55543a35333738453632443134323642413339393735333538334630314538363535433530384445323239303333353244314341464131303934323232324346374131', + }, + }, + ], +} + +const actionsResponse: ActionsResponse = { + actions: [ + { + date: '1702138875088627651', + height: '13782524', + in: [ + { + address: 'bc1qdvzzsscn056p6k0xe0y05ray32g8a5pzs74qra', + coins: [ + { + amount: '15954979', + asset: 'BTC.BTC', + }, + ], + txID: 'DB19B42A99D5117F8E3B94D4F23E5F02157937F3C4D8371AFD0A56B9DBFA084D', + }, + ], + metadata: { + refund: { + affiliateAddress: '', + affiliateFee: '0', + memo: '$-:ETH.ETH:0x8a7eAE0fbd128D33022e9d64D912f9903e0f5fcc:0', + networkFees: [ + { + amount: '64500', + asset: 'BTC.BTC', + }, + ], + reason: 'some refund reason', + }, + }, + out: [ + { + address: 'bc1q269j5rs4rm5tjpvm6adcchhvgmghc4p46250ra', + coins: [ + { + amount: '14954979', + asset: 'BTC.BTC', + }, + ], + height: '13783250', + txID: 'DB19B42A99D5117F8E3B94D4F23E5F02157937F3C4D8371AFD0A56B9DBFA084D', + }, + ], + pools: [], + status: 'success', + type: 'refund', + }, + ], + count: '1', + meta: { + nextPageToken: '137825241002020011', + prevPageToken: '137825241002020011', + }, +} + +export default { tx, actionsResponse } diff --git a/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainLpDeposit.ts b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainLpDeposit.ts new file mode 100644 index 00000000000..dcc5b672427 --- /dev/null +++ b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainLpDeposit.ts @@ -0,0 +1,54 @@ +import type { Tx } from '../../../index' + +const tx: Tx = { + txid: '63718db6a7dbb2ddf0ccfc3351fba1a7ba8172bb49c463cb7c94c05dd7cf28d2', + blockHash: '00000000000000000003a3927282def3cb9333d27a3e57fb796b7b98f1051cb1', + blockHeight: 825042, + timestamp: 1704828477, + confirmations: 21, + value: '90764750', + fee: '35250', + hex: '020000000001029d2037a2f19e36b986d066bc594e1596a8c9b4617584895c030c8ae1ebb8b8660000000000ffffffff907cedbbfa25c650da7bc5f2a41acfe59caa6fba85f0c39e678d4dd7ff30980c0000000000ffffffff03804a5d050000000016001427fce96d5f6a72244e56563c7eb41fb79ac5ecf00000000000000000106a0e2b3a4254432e4254433a3a743a304eab0b00000000001600149f9499b55e1a6d18c8da0ed1f9ff46565fec1f0602483045022100819c94dc2ad05ab229697c159eb4e9652c8cd9af60d6a0d1fbda4226429c6ff90220025bc0d996ba76e8ac687f2ccdf50cc2eb588ef4fe07d269fe06ff90478cde1a0121028aa8d2b3800844316100cb564d3e477a18e4aa42a6b17b3d5e97625842fe229602473044022007e40b32390201ca59f00f52bb08128b585006d73d32f6fec2cc47f7431d94d5022025bf00e1a2e05904e8c51b65f0361aa926a64392271dc5d5a6f3f739ef8b926d0121028aa8d2b3800844316100cb564d3e477a18e4aa42a6b17b3d5e97625842fe229600000000', + vin: [ + { + txid: '66b8b8ebe18a0c035c89847561b4c9a896154e59bc66d086b9369ef1a237209d', + sequence: 4294967295, + addresses: ['bc1qn72fnd27rfk33jx6pmglnl6x2e07c8cxnahrgj'], + value: '80800000', + }, + { + txid: '0c9830ffd74d8d679ec3f085ba6faa9ce5cf1aa4f2c57bda50c625fabbed7c90', + sequence: 4294967295, + addresses: ['bc1qn72fnd27rfk33jx6pmglnl6x2e07c8cxnahrgj'], + value: '10000000', + }, + ], + vout: [ + { + value: '90000000', + n: 0, + scriptPubKey: { + hex: '001427fce96d5f6a72244e56563c7eb41fb79ac5ecf0', + }, + addresses: ['bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q'], + }, + { + value: '0', + n: 1, + opReturn: 'OP_RETURN (+:BTC.BTC::t:0)', + scriptPubKey: { + hex: '6a0e2b3a4254432e4254433a3a743a30', + }, + }, + { + value: '764750', + n: 2, + scriptPubKey: { + hex: '00149f9499b55e1a6d18c8da0ed1f9ff46565fec1f06', + }, + addresses: ['bc1qn72fnd27rfk33jx6pmglnl6x2e07c8cxnahrgj'], + }, + ], +} + +export default { tx } diff --git a/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainLpOutbound.ts b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainLpOutbound.ts new file mode 100644 index 00000000000..9ec9f186833 --- /dev/null +++ b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainLpOutbound.ts @@ -0,0 +1,107 @@ +import type { ActionsResponse } from '../../../../parser/thorchain' +import type { Tx } from '../../../index' + +const tx: Tx = { + txid: '9fc8843b239a50c1f00c38788c5dea2060c97bb17a5786291751210b78513a8a', + blockHash: '00000000000000000003d61a48a55bcc1d7aaa2ccb5eb9268f1458bbecc6c9d7', + blockHeight: 825310, + timestamp: 1704980055, + confirmations: 35, + value: '9744025454', + fee: '28388', + hex: '010000000001018658894f728e35b9ebdd568bc3c1772f9d0f98dfca47d8323bd89d225dd1ca300100000000ffffffff0382f30d00000000001600140f7993dc15160828120f5046f2187a7c35780b44ec13bc4402000000160014801c4711208b6e3df236b9f3bbabfae52edcfa020000000000000000466a444f55543a3835434546333138333935384138303536343343364244393331363941433245443330303531433231463139434246354232363136314343354146383936353902483045022100a6044b28ebc262009f64a7cfdf5c750f7afb81d0f2dddd5c582e78b5847802c902206a2659394c823a93dfe1bf33211960507216ce7c5c7fbf9f7f0f60a592d14c35012102ea13b3619f73a04474af18459522b16fa8388f17d4a78393a8302b202c87548300000000', + vin: [ + { + txid: '30cad15d229dd83b32d847cadf980f9d2f77c1c38b56ddebb9358e724f895886', + vout: '1', + sequence: 4294967295, + addresses: ['bc1qsqwywyfq3dhrmu3kh8emh2l6u5hde7szxpg99j'], + value: '9744053842', + }, + ], + vout: [ + { + value: '914306', + n: 0, + scriptPubKey: { + hex: '00140f7993dc15160828120f5046f2187a7c35780b44', + }, + addresses: ['bc1qpaue8hq4zcyzsys02pr0yxr60s6hsz6yt6h493'], + }, + { + value: '9743111148', + n: 1, + scriptPubKey: { + hex: '0014801c4711208b6e3df236b9f3bbabfae52edcfa02', + }, + addresses: ['bc1qsqwywyfq3dhrmu3kh8emh2l6u5hde7szxpg99j'], + }, + { + value: '0', + n: 2, + opReturn: 'OP_RETURN (OUT:85CEF3183958A805643C6BD93169AC2ED30051C21F19CBF5B26161CC5AF89659)', + scriptPubKey: { + hex: '6a444f55543a38354345463331383339353841383035363433433642443933313639414332454433303035314332314631394342463542323631363143433541463839363539', + }, + }, + ], +} + +const actionsResponse: ActionsResponse = { + actions: [ + { + date: '1704979997021299499', + height: '14228633', + in: [ + { + address: 'bc1qpaue8hq4zcyzsys02pr0yxr60s6hsz6yt6h493', + coins: [ + { + amount: '10001', + asset: 'BTC.BTC', + }, + ], + txID: '85CEF3183958A805643C6BD93169AC2ED30051C21F19CBF5B26161CC5AF89659', + }, + ], + metadata: { + withdraw: { + asymmetry: '0', + basisPoints: '3300', + impermanentLossProtection: '0', + liquidityUnits: '-2453933026', + memo: '-:BTC.BTC:3300', + networkFees: [ + { + amount: '151500', + asset: 'BTC.BTC', + }, + ], + }, + }, + out: [ + { + address: 'bc1qpaue8hq4zcyzsys02pr0yxr60s6hsz6yt6h493', + coins: [ + { + amount: '914306', + asset: 'BTC.BTC', + }, + ], + height: '14228641', + txID: '9FC8843B239A50C1F00C38788C5DEA2060C97BB17A5786291751210B78513A8A', + }, + ], + pools: ['BTC.BTC'], + status: 'success', + type: 'withdraw', + }, + ], + count: '1', + meta: { + nextPageToken: '142286331000280005', + prevPageToken: '142286331000280005', + }, +} + +export default { tx, actionsResponse } diff --git a/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainLpRefund.ts b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainLpRefund.ts new file mode 100644 index 00000000000..d0c3cb9da76 --- /dev/null +++ b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainLpRefund.ts @@ -0,0 +1,161 @@ +import type { ActionsResponse } from '../../../../parser/thorchain' +import type { Tx } from '../../../index' + +const tx: Tx = { + txid: '8877bc0b81bd8cdd4dc5fbf2d654c873669f88de622a8bf545c8ade491d1828c', + blockHash: '000000000000000000005882bda71b3a43073227d5637b24ecc9c9e013e6cbf6', + blockHeight: 823072, + timestamp: 1703632402, + confirmations: 2279, + value: '36088685264', + fee: '158400', + hex: '0100000000010a8952dbf883e77719ae92ce3cf275f4d4bb2664ae287d634f53f18eb992320a510000000000ffffffff894334d10f363cfcbb8b173d8bd1436a6fb7d72710bbafcb429d13b9da5155800000000000ffffffff687bc3bd0e72a82509793f0808343d64d5e043d79abd166e412927b741d382b40000000000ffffffff9ab19c9dc8789b6a81541d3a6edd7ef54c009335ecca6b5dafbf571add59e6010000000000ffffffff5f6e6ba996b50cbf1d0e88fb2f12af897213c02b6e73655fd3c92e26e2cbf4c30000000000ffffffff3d26fc70a35432f3a292975e4125cadf70b36227b0c8a3e101f423dfdd15bbc80000000000ffffffffa24913e1c4b74210965257ccd6fe10b18821f903bb609f8981f82530d2f5b61d0000000000ffffffff3a10bd1f9f3e85f34ee570ef33ea38797cf1ecae473be3e01b55408f580d64420000000000ffffffff6afcc217cc6391bc6d75f9c5a3fb787cc28f6f5aed736eb892a373273e1b7a8b0000000000ffffffffe0697a3fe7629e43c675902ed8a09186f8db498c4e96f40d56e812224a3d92b10000000000ffffffff039746110000000000160014755ef618d3447467d1403a1775b371e4a7fa1845395cfc660800000016001427fce96d5f6a72244e56563c7eb41fb79ac5ecf00000000000000000496a47524546554e443a4232353434364531384631423341384430333730384541423136333643344233354532313841463035424533464438413831314433393935334342463930394102483045022100e68c11313a4b894b1dbaecb32826634a95ea7bbc02310080a28ecf0593c1189f02204214c84fc7236eaddb230abeb1a70cc83e4ea6fed22256b1cef69db9112e30d60121027b7c1a30b26b2a107934ba542bec15e28efa52a05541515966828181c55f0c1f02483045022100dfcdc639989602999677b3553404f560f2c14ffd79854bce214c29bbd6b2e29f02201778af61ace62985aae2f6d0d71ef25955bed51116b9833bf2745366ebd02f6d0121027b7c1a30b26b2a107934ba542bec15e28efa52a05541515966828181c55f0c1f02483045022100cfcb55f5829b2b18be165909d789fdc7d1b74bc6a2ca54aa5110aac5d94a037c022070bb7a5aff3060569bca51906eeca5e3075d41c8c4d38d7623eb2e7dee18be910121027b7c1a30b26b2a107934ba542bec15e28efa52a05541515966828181c55f0c1f02473044022070a2a6d4169154c7feb82308824fc4c3dbb24fe0150ddea4d063f3d54ef9a4ff02206ffa1603eb45038095a3e121c8be9b09d587a304bc93a2b9804b86d574f405b70121027b7c1a30b26b2a107934ba542bec15e28efa52a05541515966828181c55f0c1f02483045022100f6bdb448aeab6f13c51e9a43da4ea079e834dc043c25c1f111cce43c4d58369d022075cb3a28e3668d5956d5e97477e0b90c6acf4dcd8019222983c836ed478b97df0121027b7c1a30b26b2a107934ba542bec15e28efa52a05541515966828181c55f0c1f024730440220575315951dab4bdc1b9559c5c364c33fe0442cd03699813524c6bba6072d255002202c41b65ff39a879afa147598e713adaaca25895e13734073e9654230df02e8ab0121027b7c1a30b26b2a107934ba542bec15e28efa52a05541515966828181c55f0c1f02483045022100b4740550d271a69c726e3a7102fcfa2f89fda4030f1e0aa0003e4e4cf642af78022058af5d6fab770e6df923ca9566e67b39c27891239fcb4b5c746dd15f732ac88f0121027b7c1a30b26b2a107934ba542bec15e28efa52a05541515966828181c55f0c1f02483045022100fc37665650767fb4e6011330ce14cb504f00376c3f982798f28992daf57dc4e50220731b5cc85cec5fc9a9b7cc47668f13921343ddfba67fa1bb046d658f07e228f40121027b7c1a30b26b2a107934ba542bec15e28efa52a05541515966828181c55f0c1f0247304402201dc094581fdec3401f7b1fa46b2b1e87e23c42333bb8f46205e830c74fc7128a022078cdfd8fa6b9c9e98febbbb82ebcbda45a123503652f1a0132a1b1f75712037a0121027b7c1a30b26b2a107934ba542bec15e28efa52a05541515966828181c55f0c1f0247304402206acab88779e4dcc919e0a42ca08be0d4eff90e09f6d1b58873927d759903033502205bbc978d353031d50303dca013788f7a76c5c346caf7afffb27acec80617e1390121027b7c1a30b26b2a107934ba542bec15e28efa52a05541515966828181c55f0c1f00000000', + vin: [ + { + txid: '510a3292b98ef1534f637d28ae6426bbd4f475f23cce92ae1977e783f8db5289', + sequence: 4294967295, + addresses: ['bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q'], + value: '29915400', + }, + { + txid: '805551dab9139d42cbafbb1027d7b76f6a43d18b3d178bbbfc3c360fd1344389', + sequence: 4294967295, + addresses: ['bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q'], + value: '3529501', + }, + { + txid: 'b482d341b72729416e16bd9ad743e0d5643d3408083f790925a8720ebdc37b68', + sequence: 4294967295, + addresses: ['bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q'], + value: '36021545481', + }, + { + txid: '01e659dd1a57bfaf5d6bcaec3593004cf57edd6e3a1d54816a9b78c89d9cb19a', + sequence: 4294967295, + addresses: ['bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q'], + value: '184371', + }, + { + txid: 'c3f4cbe2262ec9d35f65736e2bc0137289af122ffb880e1dbf0cb596a96b6e5f', + sequence: 4294967295, + addresses: ['bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q'], + value: '1100507', + }, + { + txid: 'c8bb15dddf23f401e1a3c8b02762b370dfca25415e9792a2f33254a370fc263d', + sequence: 4294967295, + addresses: ['bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q'], + value: '650000', + }, + { + txid: '1db6f5d23025f881899f60bb03f92188b110fed6cc5752961042b7c4e11349a2', + sequence: 4294967295, + addresses: ['bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q'], + value: '640000', + }, + { + txid: '42640d588f40551be0e33b47aeecf17c7938ea33ef70e54ef3853e9f1fbd103a', + sequence: 4294967295, + addresses: ['bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q'], + value: '300000', + }, + { + txid: '8b7a1b3e2773a392b86e73ed5a6f8fc27c78fba3c5f9756dbc9163cc17c2fc6a', + sequence: 4294967295, + addresses: ['bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q'], + value: '29915400', + }, + { + txid: 'b1923d4a2212e8560df4964e8c49dbf88691a0d82e9075c6439e62e73f7a69e0', + sequence: 4294967295, + addresses: ['bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q'], + value: '1063004', + }, + ], + vout: [ + { + value: '1132183', + n: 0, + scriptPubKey: { + hex: '0014755ef618d3447467d1403a1775b371e4a7fa1845', + }, + addresses: ['bc1qw400vxxng36x052q8gthtvm3ujnl5xz957p2ma'], + }, + { + value: '36087553081', + n: 1, + scriptPubKey: { + hex: '001427fce96d5f6a72244e56563c7eb41fb79ac5ecf0', + }, + addresses: ['bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q'], + }, + { + value: '0', + n: 2, + opReturn: + 'OP_RETURN (REFUND:B25446E18F1B3A8D03708EAB1636C4B35E218AF05BE3FD8A811D39953CBF909A)', + scriptPubKey: { + hex: '6a47524546554e443a42323534343645313846314233413844303337303845414231363336433442333545323138414630354245334644384138313144333939353343424639303941', + }, + }, + ], +} + +const actionsResponse: ActionsResponse = { + actions: [ + { + date: '1703631569986450183', + height: '14016397', + in: [ + { + address: 'bc1qw400vxxng36x052q8gthtvm3ujnl5xz957p2ma', + coins: [ + { + amount: '1290583', + asset: 'BTC.BTC', + }, + ], + txID: 'B25446E18F1B3A8D03708EAB1636C4B35E218AF05BE3FD8A811D39953CBF909A', + }, + ], + metadata: { + refund: { + affiliateAddress: 't', + affiliateFee: '0', + memo: '+:BTC.BTC:thor1qt3zazyedurs4qjsrju69kdzhnvy9qqs2z64dn:t:0', + networkFees: [ + { + amount: '198000', + asset: 'BTC.BTC', + }, + ], + reason: + 'memo paired address must be non-empty and together with origin address match the liquidity provider record', + }, + }, + out: [ + { + address: 'bc1qw400vxxng36x052q8gthtvm3ujnl5xz957p2ma', + coins: [ + { + amount: '1132183', + asset: 'BTC.BTC', + }, + ], + height: '14016419', + txID: '8877BC0B81BD8CDD4DC5FBF2D654C873669F88DE622A8BF545C8ADE491D1828C', + }, + ], + pools: [], + status: 'success', + type: 'refund', + }, + ], + count: '1', + meta: { + nextPageToken: '140163971000100011', + prevPageToken: '140163971000100011', + }, +} + +export default { tx, actionsResponse } diff --git a/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainLpWithdraw.ts b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainLpWithdraw.ts new file mode 100644 index 00000000000..b9724b2b7d0 --- /dev/null +++ b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainLpWithdraw.ts @@ -0,0 +1,48 @@ +import type { Tx } from '../../../index' + +const tx: Tx = { + txid: 'f59341d17abd6bf27754a78ab7adb2d4b266ce3e67fb67bab9520601c1feab4d', + blockHash: '00000000000000000001c179a607f1ea9bec0ddc91da473e3656d2372f0f3037', + blockHeight: 824921, + timestamp: 1704760752, + confirmations: 143, + value: '1982360', + fee: '17640', + hex: '02000000000101552ce08d292a0d02aa972c046212442e31e20c50bfe85a1a53936551ed7df94e0000000000ffffffff031127000000000000160014407afe0a21bd5fed4aa98da464084dd2e8a29e0d0000000000000000116a0f2d3a4254432e4254433a313030303087181e00000000001600142c003995049025c6c3c84eb5376f4c1d2b92240d024730440220634a315b2df1538eee1f0e5e2230f7c80fdec9d184702212111830f0d34e855b02200b5b12261c10813f69403c0b1bd9ec0f24445bd63578b8ae58c60f2e1ccd204c0121031954c5405a3df5ff7eab0bb5f3f314daa9e97340bb19aa51fce80fbb9beb516400000000', + vin: [ + { + txid: '4ef97ded516593531a5ae8bf500ce2312e441262042c97aa020d2a298de02c55', + sequence: 4294967295, + addresses: ['bc1q9sqrn9gyjqjuds7gf66nwm6vr54eyfqdj86qxd'], + value: '2000000', + }, + ], + vout: [ + { + value: '10001', + n: 0, + scriptPubKey: { + hex: '0014407afe0a21bd5fed4aa98da464084dd2e8a29e0d', + }, + addresses: ['bc1qgpa0uz3ph4076j4f3kjxgzzd6t5298sdtjvwc9'], + }, + { + value: '0', + n: 1, + opReturn: 'OP_RETURN (-:BTC.BTC:10000)', + scriptPubKey: { + hex: '6a0f2d3a4254432e4254433a3130303030', + }, + }, + { + value: '1972359', + n: 2, + scriptPubKey: { + hex: '00142c003995049025c6c3c84eb5376f4c1d2b92240d', + }, + addresses: ['bc1q9sqrn9gyjqjuds7gf66nwm6vr54eyfqdj86qxd'], + }, + ], +} + +export default { tx } diff --git a/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainSaversDeposit.ts b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainSaversDeposit.ts new file mode 100644 index 00000000000..dc4cfd374ad --- /dev/null +++ b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainSaversDeposit.ts @@ -0,0 +1,40 @@ +import type { Tx } from '../../../index' + +const tx: Tx = { + txid: '9cddfc4cda88eca0f48ad36cd6501cf72812a81d1eeab1d036d1902d2548d8d1', + blockHash: '00000000000000000003a3927282def3cb9333d27a3e57fb796b7b98f1051cb1', + blockHeight: 825042, + timestamp: 1704828477, + confirmations: 13, + value: '17468053', + fee: '26058', + hex: '02000000000101264cf01b97ce5cd0ed4ea30f1b8830d2be9acb07f065c7ddcef3556c2c2f89160000000000ffffffff02958a0a010000000016001427fce96d5f6a72244e56563c7eb41fb79ac5ecf00000000000000000106a0e2b3a4254432f4254433a3a743a3002483045022100d0266a22bdbdbf7ddcbadc422c463b60be63ea3a36ddb0ab165c6de1426f233b022049c5cb9d2689ab48b7d178c26f00c17ff218bd79b79e1f8e176177ba554f456701210375623ef548ac5d93c2f6fea1da4ec28e39d06f0c65b21c9acf389f54d650699400000000', + vin: [ + { + txid: '16892f2c6c55f3ceddc765f007cb9abed230881b0fa34eedd05cce971bf04c26', + sequence: 4294967295, + addresses: ['bc1qqfcte3j9jgaa7p3uxr6fntqpad269vv2wvmzss'], + value: '17494111', + }, + ], + vout: [ + { + value: '17468053', + n: 0, + scriptPubKey: { + hex: '001427fce96d5f6a72244e56563c7eb41fb79ac5ecf0', + }, + addresses: ['bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q'], + }, + { + value: '0', + n: 1, + opReturn: 'OP_RETURN (+:BTC/BTC::t:0)', + scriptPubKey: { + hex: '6a0e2b3a4254432f4254433a3a743a30', + }, + }, + ], +} + +export default { tx } diff --git a/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainSaversOutbound.ts b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainSaversOutbound.ts new file mode 100644 index 00000000000..6e64b053741 --- /dev/null +++ b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainSaversOutbound.ts @@ -0,0 +1,156 @@ +import type { ActionsResponse } from '../../../../parser/thorchain' +import type { Tx } from '../../../index' + +const tx: Tx = { + txid: '740ec4f695f8b13a5cdfcedecd5935eebcd4c291823c4f9f7ce439f6ea6e260f', + blockHash: '0000000000000000000068db0c3196f7af78fa1cf7f7d51c05f9546ed667a0f7', + blockHeight: 825282, + timestamp: 1704969446, + confirmations: 63, + value: '9724530237', + fee: '17484', + hex: '01000000000101d5504539eb1c629ed853b8ea51592a2f7ad06fcc8f03e4882195787e8f9e3c740100000000ffffffff0353cc1100000000001600144634afc54fca8a04471d6dcd3d52df6862f3cf59eac18e4302000000160014801c4711208b6e3df236b9f3bbabfae52edcfa020000000000000000466a444f55543a363746303139453333384245383638324137443243393838323737423846333246433139374634323943433433414139423139354331344639353937373431450248304502210090fb40520ccebc45773f588b6b1e05c6f6fa12f74210cf49150253d41aa8026902201dd42c60453432853b9615ae1c2e02e454c412bb3e064a9ba09334ee12d24c30012102ea13b3619f73a04474af18459522b16fa8388f17d4a78393a8302b202c87548300000000', + vin: [ + { + txid: '743c9e8f7e78952188e4038fcc6fd07a2f2a5951eab853d89e621ceb394550d5', + vout: '1', + sequence: 4294967295, + addresses: ['bc1qsqwywyfq3dhrmu3kh8emh2l6u5hde7szxpg99j'], + value: '9724547721', + }, + ], + vout: [ + { + value: '1166419', + n: 0, + scriptPubKey: { + hex: '00144634afc54fca8a04471d6dcd3d52df6862f3cf59', + }, + addresses: ['bc1qgc62l320e29qg3cadhxn65kldp308n6epn07ej'], + }, + { + value: '9723363818', + n: 1, + scriptPubKey: { + hex: '0014801c4711208b6e3df236b9f3bbabfae52edcfa02', + }, + addresses: ['bc1qsqwywyfq3dhrmu3kh8emh2l6u5hde7szxpg99j'], + }, + { + value: '0', + n: 2, + opReturn: 'OP_RETURN (OUT:67F019E338BE8682A7D2C988277B8F32FC197F429CC43AA9B195C14F9597741E)', + scriptPubKey: { + hex: '6a444f55543a36374630313945333338424538363832413744324339383832373742384633324643313937463432394343343341413942313935433134463935393737343145', + }, + }, + ], +} + +const actionsResponse: ActionsResponse = { + actions: [ + { + date: '1704969152069324223', + height: '14226934', + in: [ + { + address: 'bc1qgc62l320e29qg3cadhxn65kldp308n6epn07ej', + coins: [ + { + amount: '1183936', + asset: 'BTC/BTC', + }, + ], + txID: '67F019E338BE8682A7D2C988277B8F32FC197F429CC43AA9B195C14F9597741E', + }, + ], + metadata: { + swap: { + affiliateAddress: '', + affiliateFee: '0', + isStreamingSwap: false, + liquidityFee: '188258', + memo: '=:BTC.BTC:bc1qgc62l320e29qg3cadhxn65kldp308n6epn07ej', + networkFees: [ + { + amount: '93000', + asset: 'BTC.BTC', + }, + ], + swapSlip: '0', + swapTarget: '0', + }, + }, + out: [ + { + address: 'bc1qgc62l320e29qg3cadhxn65kldp308n6epn07ej', + coins: [ + { + amount: '1166419', + asset: 'BTC.BTC', + }, + ], + height: '14226967', + txID: '740EC4F695F8B13A5CDFCEDECD5935EEBCD4C291823C4F9F7CE439F6EA6E260F', + }, + ], + pools: ['BTC.BTC'], + status: 'success', + type: 'swap', + }, + { + date: '1704969122087130650', + height: '14226930', + in: [ + { + address: 'bc1qgc62l320e29qg3cadhxn65kldp308n6epn07ej', + coins: [ + { + amount: '10001', + asset: 'BTC.BTC', + }, + ], + txID: '67F019E338BE8682A7D2C988277B8F32FC197F429CC43AA9B195C14F9597741E', + }, + ], + metadata: { + withdraw: { + asymmetry: '0', + basisPoints: '10000', + impermanentLossProtection: '0', + liquidityUnits: '-1142776', + memo: '-:BTC/BTC:10000', + networkFees: [ + { + amount: '93000', + asset: 'BTC.BTC', + }, + ], + }, + }, + out: [ + { + address: 'bc1qgc62l320e29qg3cadhxn65kldp308n6epn07ej', + coins: [ + { + amount: '1166419', + asset: 'BTC.BTC', + }, + ], + height: '14226967', + txID: '740EC4F695F8B13A5CDFCEDECD5935EEBCD4C291823C4F9F7CE439F6EA6E260F', + }, + ], + pools: ['BTC/BTC'], + status: 'success', + type: 'withdraw', + }, + ], + count: '2', + meta: { + nextPageToken: '142269301001360005', + prevPageToken: '142269349000000060', + }, +} + +export default { tx, actionsResponse } diff --git a/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainSaversRefund.ts b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainSaversRefund.ts new file mode 100644 index 00000000000..baa1ed7bd67 --- /dev/null +++ b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainSaversRefund.ts @@ -0,0 +1,163 @@ +import type { ActionsResponse } from '../../../../parser/thorchain' +import type { Tx } from '../../../index' + +// NOTE: this is not a real transaction as I was unable to find an actual bitcoin savers refund on chain + +const tx: Tx = { + txid: '8877bc0b81bd8cdd4dc5fbf2d654c873669f88de622a8bf545c8ade491d1828c', + blockHash: '000000000000000000005882bda71b3a43073227d5637b24ecc9c9e013e6cbf6', + blockHeight: 823072, + timestamp: 1703632402, + confirmations: 2279, + value: '36088685264', + fee: '158400', + hex: '0100000000010a8952dbf883e77719ae92ce3cf275f4d4bb2664ae287d634f53f18eb992320a510000000000ffffffff894334d10f363cfcbb8b173d8bd1436a6fb7d72710bbafcb429d13b9da5155800000000000ffffffff687bc3bd0e72a82509793f0808343d64d5e043d79abd166e412927b741d382b40000000000ffffffff9ab19c9dc8789b6a81541d3a6edd7ef54c009335ecca6b5dafbf571add59e6010000000000ffffffff5f6e6ba996b50cbf1d0e88fb2f12af897213c02b6e73655fd3c92e26e2cbf4c30000000000ffffffff3d26fc70a35432f3a292975e4125cadf70b36227b0c8a3e101f423dfdd15bbc80000000000ffffffffa24913e1c4b74210965257ccd6fe10b18821f903bb609f8981f82530d2f5b61d0000000000ffffffff3a10bd1f9f3e85f34ee570ef33ea38797cf1ecae473be3e01b55408f580d64420000000000ffffffff6afcc217cc6391bc6d75f9c5a3fb787cc28f6f5aed736eb892a373273e1b7a8b0000000000ffffffffe0697a3fe7629e43c675902ed8a09186f8db498c4e96f40d56e812224a3d92b10000000000ffffffff039746110000000000160014755ef618d3447467d1403a1775b371e4a7fa1845395cfc660800000016001427fce96d5f6a72244e56563c7eb41fb79ac5ecf00000000000000000496a47524546554e443a4232353434364531384631423341384430333730384541423136333643344233354532313841463035424533464438413831314433393935334342463930394102483045022100e68c11313a4b894b1dbaecb32826634a95ea7bbc02310080a28ecf0593c1189f02204214c84fc7236eaddb230abeb1a70cc83e4ea6fed22256b1cef69db9112e30d60121027b7c1a30b26b2a107934ba542bec15e28efa52a05541515966828181c55f0c1f02483045022100dfcdc639989602999677b3553404f560f2c14ffd79854bce214c29bbd6b2e29f02201778af61ace62985aae2f6d0d71ef25955bed51116b9833bf2745366ebd02f6d0121027b7c1a30b26b2a107934ba542bec15e28efa52a05541515966828181c55f0c1f02483045022100cfcb55f5829b2b18be165909d789fdc7d1b74bc6a2ca54aa5110aac5d94a037c022070bb7a5aff3060569bca51906eeca5e3075d41c8c4d38d7623eb2e7dee18be910121027b7c1a30b26b2a107934ba542bec15e28efa52a05541515966828181c55f0c1f02473044022070a2a6d4169154c7feb82308824fc4c3dbb24fe0150ddea4d063f3d54ef9a4ff02206ffa1603eb45038095a3e121c8be9b09d587a304bc93a2b9804b86d574f405b70121027b7c1a30b26b2a107934ba542bec15e28efa52a05541515966828181c55f0c1f02483045022100f6bdb448aeab6f13c51e9a43da4ea079e834dc043c25c1f111cce43c4d58369d022075cb3a28e3668d5956d5e97477e0b90c6acf4dcd8019222983c836ed478b97df0121027b7c1a30b26b2a107934ba542bec15e28efa52a05541515966828181c55f0c1f024730440220575315951dab4bdc1b9559c5c364c33fe0442cd03699813524c6bba6072d255002202c41b65ff39a879afa147598e713adaaca25895e13734073e9654230df02e8ab0121027b7c1a30b26b2a107934ba542bec15e28efa52a05541515966828181c55f0c1f02483045022100b4740550d271a69c726e3a7102fcfa2f89fda4030f1e0aa0003e4e4cf642af78022058af5d6fab770e6df923ca9566e67b39c27891239fcb4b5c746dd15f732ac88f0121027b7c1a30b26b2a107934ba542bec15e28efa52a05541515966828181c55f0c1f02483045022100fc37665650767fb4e6011330ce14cb504f00376c3f982798f28992daf57dc4e50220731b5cc85cec5fc9a9b7cc47668f13921343ddfba67fa1bb046d658f07e228f40121027b7c1a30b26b2a107934ba542bec15e28efa52a05541515966828181c55f0c1f0247304402201dc094581fdec3401f7b1fa46b2b1e87e23c42333bb8f46205e830c74fc7128a022078cdfd8fa6b9c9e98febbbb82ebcbda45a123503652f1a0132a1b1f75712037a0121027b7c1a30b26b2a107934ba542bec15e28efa52a05541515966828181c55f0c1f0247304402206acab88779e4dcc919e0a42ca08be0d4eff90e09f6d1b58873927d759903033502205bbc978d353031d50303dca013788f7a76c5c346caf7afffb27acec80617e1390121027b7c1a30b26b2a107934ba542bec15e28efa52a05541515966828181c55f0c1f00000000', + vin: [ + { + txid: '510a3292b98ef1534f637d28ae6426bbd4f475f23cce92ae1977e783f8db5289', + sequence: 4294967295, + addresses: ['bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q'], + value: '29915400', + }, + { + txid: '805551dab9139d42cbafbb1027d7b76f6a43d18b3d178bbbfc3c360fd1344389', + sequence: 4294967295, + addresses: ['bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q'], + value: '3529501', + }, + { + txid: 'b482d341b72729416e16bd9ad743e0d5643d3408083f790925a8720ebdc37b68', + sequence: 4294967295, + addresses: ['bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q'], + value: '36021545481', + }, + { + txid: '01e659dd1a57bfaf5d6bcaec3593004cf57edd6e3a1d54816a9b78c89d9cb19a', + sequence: 4294967295, + addresses: ['bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q'], + value: '184371', + }, + { + txid: 'c3f4cbe2262ec9d35f65736e2bc0137289af122ffb880e1dbf0cb596a96b6e5f', + sequence: 4294967295, + addresses: ['bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q'], + value: '1100507', + }, + { + txid: 'c8bb15dddf23f401e1a3c8b02762b370dfca25415e9792a2f33254a370fc263d', + sequence: 4294967295, + addresses: ['bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q'], + value: '650000', + }, + { + txid: '1db6f5d23025f881899f60bb03f92188b110fed6cc5752961042b7c4e11349a2', + sequence: 4294967295, + addresses: ['bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q'], + value: '640000', + }, + { + txid: '42640d588f40551be0e33b47aeecf17c7938ea33ef70e54ef3853e9f1fbd103a', + sequence: 4294967295, + addresses: ['bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q'], + value: '300000', + }, + { + txid: '8b7a1b3e2773a392b86e73ed5a6f8fc27c78fba3c5f9756dbc9163cc17c2fc6a', + sequence: 4294967295, + addresses: ['bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q'], + value: '29915400', + }, + { + txid: 'b1923d4a2212e8560df4964e8c49dbf88691a0d82e9075c6439e62e73f7a69e0', + sequence: 4294967295, + addresses: ['bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q'], + value: '1063004', + }, + ], + vout: [ + { + value: '1132183', + n: 0, + scriptPubKey: { + hex: '0014755ef618d3447467d1403a1775b371e4a7fa1845', + }, + addresses: ['bc1qw400vxxng36x052q8gthtvm3ujnl5xz957p2ma'], + }, + { + value: '36087553081', + n: 1, + scriptPubKey: { + hex: '001427fce96d5f6a72244e56563c7eb41fb79ac5ecf0', + }, + addresses: ['bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q'], + }, + { + value: '0', + n: 2, + opReturn: + 'OP_RETURN (REFUND:B25446E18F1B3A8D03708EAB1636C4B35E218AF05BE3FD8A811D39953CBF909A)', + scriptPubKey: { + hex: '6a47524546554e443a42323534343645313846314233413844303337303845414231363336433442333545323138414630354245334644384138313144333939353343424639303941', + }, + }, + ], +} + +const actionsResponse: ActionsResponse = { + actions: [ + { + date: '1703631569986450183', + height: '14016397', + in: [ + { + address: 'bc1qw400vxxng36x052q8gthtvm3ujnl5xz957p2ma', + coins: [ + { + amount: '1290583', + asset: 'BTC.BTC', + }, + ], + txID: 'B25446E18F1B3A8D03708EAB1636C4B35E218AF05BE3FD8A811D39953CBF909A', + }, + ], + metadata: { + refund: { + affiliateAddress: 't', + affiliateFee: '0', + memo: '+:BTC/BTC:thor1qt3zazyedurs4qjsrju69kdzhnvy9qqs2z64dn:t:0', + networkFees: [ + { + amount: '198000', + asset: 'BTC.BTC', + }, + ], + reason: + 'memo paired address must be non-empty and together with origin address match the liquidity provider record', + }, + }, + out: [ + { + address: 'bc1qw400vxxng36x052q8gthtvm3ujnl5xz957p2ma', + coins: [ + { + amount: '1132183', + asset: 'BTC.BTC', + }, + ], + height: '14016419', + txID: '8877BC0B81BD8CDD4DC5FBF2D654C873669F88DE622A8BF545C8ADE491D1828C', + }, + ], + pools: [], + status: 'success', + type: 'refund', + }, + ], + count: '1', + meta: { + nextPageToken: '140163971000100011', + prevPageToken: '140163971000100011', + }, +} + +export default { tx, actionsResponse } diff --git a/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainSaversWithdraw.ts b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainSaversWithdraw.ts new file mode 100644 index 00000000000..c0258738d15 --- /dev/null +++ b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainSaversWithdraw.ts @@ -0,0 +1,48 @@ +import type { Tx } from '../../../index' + +const tx: Tx = { + txid: 'f082c1509bef398e52a84a32991237ffbcc8a230c8d43cf63b6d71ffda07bc17', + blockHash: '00000000000000000001bf0e33e237b8f517fa9dbaac41bc3fc7707cfb8cfe8e', + blockHeight: 825043, + timestamp: 1704828720, + confirmations: 15, + value: '353729', + fee: '17640', + hex: '02000000000101e7d3ef2181b0f90c1a18e0dd00d823993e0e2976eb52ebea9f322468bd732b290000000000ffffffff031127000000000000160014407afe0a21bd5fed4aa98da464084dd2e8a29e0d0000000000000000116a0f2d3a4254432f4254433a3130303030b03e050000000000160014e4f391ea481f014fafabb4b1f88c1ea71e110bf30247304402203649075c913ccf0d5dbb5811ffa1cc24882f0feaac337f32de05585af3b36746022002e372d4946afee6fae6437f977d6b34a9208678df9665fcbea8309ae99a81000121022f8183f4998ef0e04a09bd86a64e4e46e8ab49105dcbec6e9eb8951cc53f85b900000000', + vin: [ + { + txid: '292b73bd6824329feaeb52eb76290e3e9923d800dde0181a0cf9b08121efd3e7', + sequence: 4294967295, + addresses: ['bc1quneer6jgruq5ltatkjcl3rq75u0pzzlnrfkj5j'], + value: '371369', + }, + ], + vout: [ + { + value: '10001', + n: 0, + scriptPubKey: { + hex: '0014407afe0a21bd5fed4aa98da464084dd2e8a29e0d', + }, + addresses: ['bc1qgpa0uz3ph4076j4f3kjxgzzd6t5298sdtjvwc9'], + }, + { + value: '0', + n: 1, + opReturn: 'OP_RETURN (-:BTC/BTC:10000)', + scriptPubKey: { + hex: '6a0f2d3a4254432f4254433a3130303030', + }, + }, + { + value: '343728', + n: 2, + scriptPubKey: { + hex: '0014e4f391ea481f014fafabb4b1f88c1ea71e110bf3', + }, + addresses: ['bc1quneer6jgruq5ltatkjcl3rq75u0pzzlnrfkj5j'], + }, + ], +} + +export default { tx } diff --git a/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainStreamingSwap.ts b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainStreamingSwap.ts new file mode 100644 index 00000000000..f4581d28014 --- /dev/null +++ b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainStreamingSwap.ts @@ -0,0 +1,49 @@ +import type { Tx } from '../../../index' + +const tx: Tx = { + txid: 'a1174a690a6e9cc570e4e4a76f8be49d82fa2353cfd686c1b6b210d58d0e3cc7', + blockHash: '00000000000000000002e0780dc578b85b9d8aa76db00ccdfca8629b353dfb43', + blockHeight: 825055, + timestamp: 1704834951, + confirmations: 2, + value: '677936', + fee: '11484', + hex: '01000000000101b02c9e0f5c77e0ee1817c1fa8f840a6f7a89aa828d2fa1287fd2469aaaa9aa260100000000ffffffff03ac2d030000000000160014407afe0a21bd5fed4aa98da464084dd2e8a29e0d842a0700000000001600147f7b24ee432f5eff0badde9ffe41bf57c0bc9ba30000000000000000476a453d3a4554482e555344542d4543373a3078363035376432443966303765303646413038333661313761346534463030343464384630323931323a302f312f303a74693a37300247304402202ea6a37f58f32329933144aa8af636e7893845aba6923f7346b11e18eb08dd460220273b2571f1e7df8bee2b158ef063c9a4db53767a3093842c7ccc3dc44a13d51d012103e9154423011550766d1e1bf868c045613e166020556dabdb9319b149b407cc9800000000', + vin: [ + { + txid: '26aaa9aa9a46d27f28a12f8d82aa897a6f0a848ffac11718eee0775c0f9e2cb0', + vout: '1', + sequence: 4294967295, + addresses: ['bc1q0aajfmjr9a007zadm60lusdl2lqtexars8aul3'], + value: '689420', + }, + ], + vout: [ + { + value: '208300', + n: 0, + scriptPubKey: { + hex: '0014407afe0a21bd5fed4aa98da464084dd2e8a29e0d', + }, + addresses: ['bc1qgpa0uz3ph4076j4f3kjxgzzd6t5298sdtjvwc9'], + }, + { + value: '469636', + n: 1, + scriptPubKey: { + hex: '00147f7b24ee432f5eff0badde9ffe41bf57c0bc9ba3', + }, + addresses: ['bc1q0aajfmjr9a007zadm60lusdl2lqtexars8aul3'], + }, + { + value: '0', + n: 2, + opReturn: 'OP_RETURN (=:ETH.USDT-EC7:0x6057d2D9f07e06FA0836a17a4e4F0044d8F02912:0/1/0:ti:70)', + scriptPubKey: { + hex: '6a453d3a4554482e555344542d4543373a3078363035376432443966303765303646413038333661313761346534463030343464384630323931323a302f312f303a74693a3730', + }, + }, + ], +} + +export default { tx } diff --git a/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainStreamingSwapOutbound.ts b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainStreamingSwapOutbound.ts new file mode 100644 index 00000000000..6ee39b767d9 --- /dev/null +++ b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainStreamingSwapOutbound.ts @@ -0,0 +1,124 @@ +import type { ActionsResponse } from '../../../../parser/thorchain' +import type { Tx } from '../../../index' + +const tx: Tx = { + txid: '39f1a4d0f9a7dba5365eb40c73590ca81c702676de18f0438556da8f6b179068', + blockHash: '0000000000000000000056407ba45b95b4697e0b78bc96be0d9439f8c9ff76d6', + blockHeight: 825199, + timestamp: 1704927505, + confirmations: 146, + value: '10127250588', + fee: '9212', + hex: '010000000001015c218924b60667f02e922561d6a5cdb5d4756a0a1a3682ad9d494ac87a48bb810100000000ffffffff03a4c6010000000000160014b1f77916541c05e9789b6154b56d944e00942fd0f8cd9f5b02000000160014801c4711208b6e3df236b9f3bbabfae52edcfa020000000000000000466a444f55543a3038413836334433313041454346303038423441393734324135393636303345413030384336383242344534384646384646383043343038464245373245423302483045022100e8d2bac8222482d0d8290e3bb9259c025e603eb2d2f606ef0ce641ca441a5ece02204de27096b64613fd768bf3e53c6293056f46484ee590f616f7b11539537fa681012102ea13b3619f73a04474af18459522b16fa8388f17d4a78393a8302b202c87548300000000', + vin: [ + { + txid: '81bb487ac84a499dad82361a0a6a75d4b5cda5d66125922ef06706b62489215c', + vout: '1', + sequence: 4294967295, + addresses: ['bc1qsqwywyfq3dhrmu3kh8emh2l6u5hde7szxpg99j'], + value: '10127259800', + }, + ], + vout: [ + { + value: '116388', + n: 0, + scriptPubKey: { + hex: '0014b1f77916541c05e9789b6154b56d944e00942fd0', + }, + addresses: ['bc1qk8mhj9j5rsz7j7ymv92t2mv5fcqfgt7scn9p72'], + }, + { + value: '10127134200', + n: 1, + scriptPubKey: { + hex: '0014801c4711208b6e3df236b9f3bbabfae52edcfa02', + }, + addresses: ['bc1qsqwywyfq3dhrmu3kh8emh2l6u5hde7szxpg99j'], + }, + { + value: '0', + n: 2, + opReturn: 'OP_RETURN (OUT:08A863D310AECF008B4A9742A596603EA008C682B4E48FF8FF80C408FBE72EB3)', + scriptPubKey: { + hex: '6a444f55543a30384138363344333130414543463030384234413937343241353936363033454130303843363832423445343846463846463830433430384642453732454233', + }, + }, + ], +} + +const actionsResponse: ActionsResponse = { + actions: [ + { + date: '1704926256872734003', + height: '14220195', + in: [ + { + address: '0x5b7e725729790240ccf2da19d92cad339153ce02', + coins: [ + { + amount: '19125435', + asset: 'BSC.BNB', + }, + ], + txID: '08A863D310AECF008B4A9742A596603EA008C682B4E48FF8FF80C408FBE72EB3', + }, + ], + metadata: { + swap: { + affiliateAddress: 'ti', + affiliateFee: '70', + isStreamingSwap: true, + liquidityFee: '35155', + memo: '=:BTC.BTC:bc1qk8mhj9j5rsz7j7ymv92t2mv5fcqfgt7scn9p72:0/1/0:ti:70', + networkFees: [ + { + amount: '49500', + asset: 'BTC.BTC', + }, + { + amount: '2000000', + asset: 'THOR.RUNE', + }, + ], + swapSlip: '0', + swapTarget: '0', + }, + }, + out: [ + { + address: 'thor1dl7un46w7l7f3ewrnrm6nq58nerjtp0dradjtd', + coins: [ + { + amount: '6121855', + asset: 'THOR.RUNE', + }, + ], + height: '14220195', + txID: '', + }, + { + address: 'bc1qk8mhj9j5rsz7j7ymv92t2mv5fcqfgt7scn9p72', + coins: [ + { + amount: '116388', + asset: 'BTC.BTC', + }, + ], + height: '14220243', + txID: '39F1A4D0F9A7DBA5365EB40C73590CA81C702676DE18F0438556DA8F6B179068', + }, + ], + pools: ['BSC.BNB', 'BTC.BTC'], + status: 'success', + type: 'swap', + }, + ], + count: '1', + meta: { + nextPageToken: '142201959000000014', + prevPageToken: '142201959000000014', + }, +} + +export default { tx, actionsResponse } diff --git a/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainStreamingSwapRefund.ts b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainStreamingSwapRefund.ts new file mode 100644 index 00000000000..36203365ec1 --- /dev/null +++ b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainStreamingSwapRefund.ts @@ -0,0 +1,122 @@ +import type { ActionsResponse } from '../../../../parser/thorchain' +import type { Tx } from '../../../index' + +const tx: Tx = { + txid: '772ead20ed7d60fbfba15eea0dc2cf71dfe945605a4caed79db8a852d005e212', + blockHash: '0000000000000000000388f199739861321ef85985502c0e48dd0bc9614574b1', + blockHeight: 825081, + timestamp: 1704853769, + confirmations: 269, + value: '36827315371', + fee: '17763', + hex: '010000000001012df0ece4d36ae85959f89652bd46e41ded5f7ed6d773fbee46b9e58f839784020100000000ffffffff0355b8010700000000160014ea61c41f8cb991da73a5014b6aea776e8efc97d35684128c0800000016001427fce96d5f6a72244e56563c7eb41fb79ac5ecf00000000000000000496a47524546554e443a3038393333443235414430363541364339364536304241324130453544454432333831304538413330334433453036313932424439333933313439443530303202473044022001d365c35ce3eb806e3c0d4e8e91335c052d59dfdd5618b11d97e7b13734daa20220437f9130cdf444ff360f2dbce80a46bc25579b59179087d36b7d602c601d40eb0121027b7c1a30b26b2a107934ba542bec15e28efa52a05541515966828181c55f0c1f00000000', + vin: [ + { + txid: '028497838fe5b946eefb73d7d67e5fed1de446bd5296f85959e86ad3e4ecf02d', + vout: '1', + sequence: 4294967295, + addresses: ['bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q'], + value: '36827333134', + }, + ], + vout: [ + { + value: '117553237', + n: 0, + scriptPubKey: { + hex: '0014ea61c41f8cb991da73a5014b6aea776e8efc97d3', + }, + addresses: ['bc1qafsug8uvhxga5ua9q99k46nhd680e97n26egzc'], + }, + { + value: '36709762134', + n: 1, + scriptPubKey: { + hex: '001427fce96d5f6a72244e56563c7eb41fb79ac5ecf0', + }, + addresses: ['bc1qyl7wjm2ldfezgnjk2c78adqlk7dvtm8sd7gn0q'], + }, + { + value: '0', + n: 2, + opReturn: + 'OP_RETURN (REFUND:08933D25AD065A6C96E60BA2A0E5DED23810E8A303D3E06192BD9393149D5002)', + scriptPubKey: { + hex: '6a47524546554e443a30383933334432354144303635413643393645363042413241304535444544323338313045384133303344334530363139324244393339333134394435303032', + }, + }, + ], +} + +const actionsResponse: ActionsResponse = { + actions: [ + { + date: '1704846972505457968', + height: '14207846', + in: [ + { + address: 'bc1qafsug8uvhxga5ua9q99k46nhd680e97n26egzc', + coins: [ + { + amount: '117646000', + asset: 'BTC.BTC', + }, + ], + txID: '08933D25AD065A6C96E60BA2A0E5DED23810E8A303D3E06192BD9393149D5002', + }, + ], + metadata: { + refund: { + affiliateAddress: 't', + affiliateFee: '30', + memo: '=:e:0xc6ebf3bd612844a533f63a702149bb09f356f5d8:2272314978/3/5:t:30', + networkFees: [ + { + amount: '168000', + asset: 'BTC.BTC', + }, + { + amount: '2000000', + asset: 'THOR.RUNE', + }, + ], + reason: 'emit asset 564938548 less than price limit 568078744', + }, + }, + out: [ + { + address: 'thor160yye65pf9rzwrgqmtgav69n6zlsyfpgm9a7xk', + coins: [ + { + amount: '3401542016', + asset: 'THOR.RUNE', + }, + ], + height: '14207851', + txID: '', + }, + { + address: 'bc1qafsug8uvhxga5ua9q99k46nhd680e97n26egzc', + coins: [ + { + amount: '117553237', + asset: 'BTC.BTC', + }, + ], + height: '14208872', + txID: '772EAD20ED7D60FBFBA15EEA0DC2CF71DFE945605A4CAED79DB8A852D005E212', + }, + ], + pools: [], + status: 'success', + type: 'refund', + }, + ], + count: '1', + meta: { + nextPageToken: '142078469000000009', + prevPageToken: '142078469000000009', + }, +} + +export default { tx, actionsResponse } diff --git a/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainSwap.ts b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainSwap.ts new file mode 100644 index 00000000000..45196856627 --- /dev/null +++ b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainSwap.ts @@ -0,0 +1,55 @@ +import type { Tx } from '../../../index' + +const tx: Tx = { + txid: '54a990298b6b0c3e3ec9425e3c472ccee85e06552508c2e7622027e7cd838a4c', + blockHash: '0000000000000000000091c5a281798916835808be23053b1e947459e54f8489', + blockHeight: 825037, + timestamp: 1704826002, + confirmations: 2, + value: '841681', + fee: '40128', + hex: '02000000000102f04d5ade98060a34e86a9dc42025919482b40e764e28b2683f3c1f2d1f553f870000000000ffffffff7e83be97ca70feb50ecd0a3bbb58b2240abf592ca66129b4fc50851728974ddf0000000000ffffffff03f1ed0b0000000000160014407afe0a21bd5fed4aa98da464084dd2e8a29e0d0000000000000000496a473d3a474149412e41544f4d3a636f736d6f73316179776d6c7578616e617765707532673276706533613434396173686c787930346c326d63633a333732303765353a72673a3235e0e9000000000000160014bc8fa8472cc2885775d9c6773580f00bf11d837d02483045022100db52d55d0d536b02b3a6608e3302340c708f2aca314b66a0fa65ae3fecd0542e02205a102be29c87cb29e10be25539c6dc01273b877143e4f6de131c995197d5c4a5012103618338071e5feb2c83a34578dfd36186d3123af9ccca0f4f1073c549046750f402473044022065c0952e8c2ddb5d1cc20f6021f78073c26421017d3945e25df33103e3b8652e02205582013765775d63e8d03c4259f1c10aef5b847a914e0fdf474468212ac094a2012103618338071e5feb2c83a34578dfd36186d3123af9ccca0f4f1073c549046750f400000000', + vin: [ + { + txid: '873f551f2d1f3c3f68b2284e760eb48294912520c49d6ae8340a0698de5a4df0', + sequence: 4294967295, + addresses: ['bc1qhj86s3evc2y9wawecemntq8sp0c3mqmaagmqjd'], + value: '161139', + }, + { + txid: 'df4d9728178550fcb42961a62c59bf0a24b258bb3b0acd0eb5fe70ca97be837e', + sequence: 4294967295, + addresses: ['bc1qhj86s3evc2y9wawecemntq8sp0c3mqmaagmqjd'], + value: '720670', + }, + ], + vout: [ + { + value: '781809', + n: 0, + scriptPubKey: { + hex: '0014407afe0a21bd5fed4aa98da464084dd2e8a29e0d', + }, + addresses: ['bc1qgpa0uz3ph4076j4f3kjxgzzd6t5298sdtjvwc9'], + }, + { + value: '0', + n: 1, + opReturn: + 'OP_RETURN (=:GAIA.ATOM:cosmos1aywmluxanawepu2g2vpe3a449ashlxy04l2mcc:37207e5:rg:25)', + scriptPubKey: { + hex: '6a473d3a474149412e41544f4d3a636f736d6f73316179776d6c7578616e617765707532673276706533613434396173686c787930346c326d63633a333732303765353a72673a3235', + }, + }, + { + value: '59872', + n: 2, + scriptPubKey: { + hex: '0014bc8fa8472cc2885775d9c6773580f00bf11d837d', + }, + addresses: ['bc1qhj86s3evc2y9wawecemntq8sp0c3mqmaagmqjd'], + }, + ], +} + +export default { tx } diff --git a/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainSwapOutbound.ts b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainSwapOutbound.ts new file mode 100644 index 00000000000..181d8bad554 --- /dev/null +++ b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainSwapOutbound.ts @@ -0,0 +1,109 @@ +import type { ActionsResponse } from '../../../../parser/thorchain' +import type { Tx } from '../../../index' + +const tx: Tx = { + txid: 'bf0c67414d6842ce3f24af1114ad2afb4afdc8f7fab9ec2dc2feec52a1b8e65d', + blockHash: '00000000000000000003a3927282def3cb9333d27a3e57fb796b7b98f1051cb1', + blockHeight: 825042, + timestamp: 1704828477, + confirmations: 6, + value: '37146338589', + fee: '18800', + hex: '010000000001011ec3cc7f06f7854a6c0bf705a91ac3a4da602c1ae5c13f006d6d684599899c860100000000ffffffff0335fb7601000000001600145a20b5b70488b5ebe5188ebe52e50ddc74cebf74e829a1a408000000160014bfb126731142d711d7a9dbc4065d830d92e7f6e60000000000000000466a444f55543a423546453446324433313044333241444433443730433145383036453232343934334130384537334143383932383741423337344236353636433436303544380247304402201e4f9b61098ff861b3fa9f17ee23e9ee0740b93ef537b97bdd59c21f11fa542b02202bbef13d05c652a5c0e43c155752126dc8733553cd648a9bc270fe60975dd37c012102e04413afe986a11b20749ed3962058e1c9d8df9816ef399a22f57ab36801055f00000000', + vin: [ + { + txid: '869c899945686d6d003fc1e51a2c60daa4c31aa905f70b6c4a85f7067fccc31e', + vout: '1', + sequence: 4294967295, + addresses: ['bc1qh7cjvuc3gtt3r4afm0zqvhvrpkfw0ahxrfwfgu'], + value: '37146357389', + }, + ], + vout: [ + { + value: '24574773', + n: 0, + scriptPubKey: { + hex: '00145a20b5b70488b5ebe5188ebe52e50ddc74cebf74', + }, + addresses: ['bc1qtgsttdcy3z67hegc36l99egdm36va0m5r0gece'], + }, + { + value: '37121763816', + n: 1, + scriptPubKey: { + hex: '0014bfb126731142d711d7a9dbc4065d830d92e7f6e6', + }, + addresses: ['bc1qh7cjvuc3gtt3r4afm0zqvhvrpkfw0ahxrfwfgu'], + }, + { + value: '0', + n: 2, + opReturn: 'OP_RETURN (OUT:B5FE4F2D310D32ADD3D70C1E806E224943A08E73AC89287AB374B6566C4605D8)', + scriptPubKey: { + hex: '6a444f55543a42354645344632443331304433324144443344373043314538303645323234393433413038453733414338393238374142333734423635363643343630354438', + }, + }, + ], +} + +const actionsResponse: ActionsResponse = { + actions: [ + { + date: '1704828114457766702', + height: '14204933', + in: [ + { + address: 'thor1x0uv04mglg439a8vw8q4mn83jm5s3uuj0mzsy9', + coins: [ + { + amount: '238200000000', + asset: 'THOR.RUNE', + }, + ], + txID: 'B5FE4F2D310D32ADD3D70C1E806E224943A08E73AC89287AB374B6566C4605D8', + }, + ], + metadata: { + swap: { + affiliateAddress: '', + affiliateFee: '0', + isStreamingSwap: false, + liquidityFee: '42877209', + memo: 'SWAP:BTC.BTC:bc1qtgsttdcy3z67hegc36l99egdm36va0m5r0gece:24000000', + networkFees: [ + { + amount: '58500', + asset: 'BTC.BTC', + }, + ], + swapSlip: '2', + swapTarget: '24000000', + }, + }, + out: [ + { + address: 'bc1qtgsttdcy3z67hegc36l99egdm36va0m5r0gece', + coins: [ + { + amount: '24574773', + asset: 'BTC.BTC', + }, + ], + height: '14204982', + txID: 'BF0C67414D6842CE3F24AF1114AD2AFB4AFDC8F7FAB9EC2DC2FEEC52A1B8E65D', + }, + ], + pools: ['BTC.BTC'], + status: 'success', + type: 'swap', + }, + ], + count: '1', + meta: { + nextPageToken: '142049339000000035', + prevPageToken: '142049339000000035', + }, +} + +export default { tx, actionsResponse } diff --git a/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainSwapRefund.ts b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainSwapRefund.ts new file mode 100644 index 00000000000..4927ab30ead --- /dev/null +++ b/packages/unchained-client/src/utxo/bitcoin/parser/__tests__/mockData/thorchainSwapRefund.ts @@ -0,0 +1,236 @@ +import type { ActionsResponse } from '../../../../parser/thorchain' +import type { Tx } from '../../../index' + +const tx: Tx = { + txid: '89d3c6fb860248a517bcff7b7e0846d76a6b67186da705f798cd3a2943e6d0b2', + blockHash: '00000000000000000000121bb2cfa215a1ab0ebdd5678d842d366c9a724994b5', + blockHeight: 825327, + timestamp: 1704988619, + confirmations: 21, + value: '18460707810', + fee: '84000', + hex: '0100000000010a3f2df43a2781279dad4d7a64481a2807b79a3d337492d730c5dbe88f593c70fb0000000000ffffffff8e7cca97d39ba2b9672d5e0767fd4ef585b550d81a704391bc4f54e8151114410000000000ffffffff0bda57722360af6e0851ad16046092d69f812dd3b5d968a294248d28729c2bae0000000000ffffffffc8b27e5e2e8bdebf517214cafbaaa4a9729385b180e398f5a9168bdfcbee5e180000000000ffffffff3bf99bfc1c3a88006a562dae8297943301c94376ddde3c8ac7bb20301096a81d0000000000ffffffff5b5f8a88d131fb9f31925c946f0e726442cffd19b69bae325f13e1668820f25c0000000000ffffffffe8ed66136600f6e4eb36b34235e9adf0eb0a32d637b85e69ef98fba5ceda3f760000000000ffffffffb61e29afe2f4472ccbcf11604e95a2bd2e84f0dd43a3d21a4f022128971cd27c0000000000ffffffff32899a90939db6d58ad1cb8d8c5c5f80846bb375727cd72234e28c0e58b0f59e0000000000ffffffff655549e32bb2333d12948b32616b229b0ebf528d51c5f4daed78bac40e1756b40000000000ffffffff0344e92c0000000000160014842aa5a976f6b105f95af1a559438d6833dd14489e222b4c04000000160014407afe0a21bd5fed4aa98da464084dd2e8a29e0d0000000000000000496a47524546554e443a3141313544324334383846434136464534423530413933304244464346333230444144364643464636323942384439313331303634384533354643454539363702473044022049bcb0e5b47af2966cdaa0a0b8761e440c3e1d8aa51dacd617f7ddb121f2bb5102200f31957b4853f952da2d0341b11da79938f3f26d309a8179ba1c1289ec36eda201210306e6d1084d266a835aa01a36960bf69d225bad189172b28b48229d7a4371a82b02483045022100f3fb68819012cf4a291916eb7a5d45215bfd132d99e6ff673587ad0788d6c009022042767a073a0bd5227bb2fb9e584effe1d6bf7acba4afa96c0700da6da6fab4fb01210306e6d1084d266a835aa01a36960bf69d225bad189172b28b48229d7a4371a82b02473044022074865e4108cf0008fbc714d10b86620d964e0fb7bff0d26d6f7aef91fc18be48022013d00097d8c130354b6065a26857112bdf2c353cc888134399c9cee5b636106d01210306e6d1084d266a835aa01a36960bf69d225bad189172b28b48229d7a4371a82b024830450221008dfeb14c75fb044b7100b754373ab58fec8e7230ec7ad7c956c2a1b6199fea5d022069660918d0b3179034cb250889fcd7fbec50afe2ebb9afb82f2832e183deafba01210306e6d1084d266a835aa01a36960bf69d225bad189172b28b48229d7a4371a82b0247304402207d28b401712cac28ef7276c150a78c9fe50651e670a56460369e55c095fdb1da02200d8238234bc7ecb1d86033e15cd6a4a30eedbf6cdba76bc78ac99619258f4a1a01210306e6d1084d266a835aa01a36960bf69d225bad189172b28b48229d7a4371a82b02483045022100a9a8dbf1d87d69491cd52734ff4cd827e3b5f23f5303faadd884be61d887dfc20220163239b67d480d5183ce6dc6b7b0be9115041db06ea0ca113bccdf2745d71df701210306e6d1084d266a835aa01a36960bf69d225bad189172b28b48229d7a4371a82b02483045022100aa7b5ef2c58dea14febe32d39c01e9f0d1a15ec58c3351f5cb90b03c50dfbd3f022048b192e878010fcec6fd94dfa623f127be5a730454fea6d1b7650843f4b4af8901210306e6d1084d266a835aa01a36960bf69d225bad189172b28b48229d7a4371a82b02483045022100b3cd4ce3a1b586abd505a0f79b678a22fdf63635648880bd6784577caa1211710220494c89e72e041b435c3b4b5ad0c59891c8f041ad153aa4ae72abae559d45ea7101210306e6d1084d266a835aa01a36960bf69d225bad189172b28b48229d7a4371a82b02483045022100d203ee3d11068effa97a898f08170517d6d78612d1901e696932aec846d230a202207bef69105e5c60e9f987a3c2ee877303a0a2fb44ecab12cec99caba8dc643ded01210306e6d1084d266a835aa01a36960bf69d225bad189172b28b48229d7a4371a82b02483045022100cc66dcddb58c0c7a568e9c31834bf1030c427050864cb7582b347c367c9b477802207da615f7f66cc412f125ab8aa045a719e3a3e9772d9f14dfd975b08b73013f3a01210306e6d1084d266a835aa01a36960bf69d225bad189172b28b48229d7a4371a82b00000000', + vin: [ + { + txid: 'fb703c598fe8dbc530d79274333d9ab707281a48647a4dad9d2781273af42d3f', + sequence: 4294967295, + addresses: ['bc1qgpa0uz3ph4076j4f3kjxgzzd6t5298sdtjvwc9'], + value: '89000000', + }, + { + txid: '41141115e8544fbc9143701ad850b585f54efd67075e2d67b9a29bd397ca7c8e', + sequence: 4294967295, + addresses: ['bc1qgpa0uz3ph4076j4f3kjxgzzd6t5298sdtjvwc9'], + value: '163523', + }, + { + txid: 'ae2b9c72288d2494a268d9b5d32d819fd692600416ad51086eaf60237257da0b', + sequence: 4294967295, + addresses: ['bc1qgpa0uz3ph4076j4f3kjxgzzd6t5298sdtjvwc9'], + value: '165727000', + }, + { + txid: '185eeecbdf8b16a9f598e380b1859372a9a4aafbca147251bfde8b2e5e7eb2c8', + sequence: 4294967295, + addresses: ['bc1qgpa0uz3ph4076j4f3kjxgzzd6t5298sdtjvwc9'], + value: '1500000', + }, + { + txid: '1da896103020bbc78a3cdedd7643c90133949782ae2d566a00883a1cfc9bf93b', + sequence: 4294967295, + addresses: ['bc1qgpa0uz3ph4076j4f3kjxgzzd6t5298sdtjvwc9'], + value: '31949738', + }, + { + txid: '5cf2208866e1135f32ae9bb619fdcf4264720e6f945c92319ffb31d1888a5f5b', + sequence: 4294967295, + addresses: ['bc1qgpa0uz3ph4076j4f3kjxgzzd6t5298sdtjvwc9'], + value: '1140000', + }, + { + txid: '763fdacea5fb98ef695eb837d6320aebf0ade93542b336ebe4f600661366ede8', + sequence: 4294967295, + addresses: ['bc1qgpa0uz3ph4076j4f3kjxgzzd6t5298sdtjvwc9'], + value: '18160651549', + }, + { + txid: '7cd21c972821024f1ad2a343ddf0842ebda2954e6011cfcb2c47f4e2af291eb6', + sequence: 4294967295, + addresses: ['bc1qgpa0uz3ph4076j4f3kjxgzzd6t5298sdtjvwc9'], + value: '10000000', + }, + { + txid: '9ef5b0580e8ce23422d77c7275b36b84805f5c8c8dcbd18ad5b69d93909a8932', + sequence: 4294967295, + addresses: ['bc1qgpa0uz3ph4076j4f3kjxgzzd6t5298sdtjvwc9'], + value: '160000', + }, + { + txid: 'b456170ec4ba78eddaf4c5518d52bf0e9b226b61328b94123d33b22be3495565', + sequence: 4294967295, + addresses: ['bc1qgpa0uz3ph4076j4f3kjxgzzd6t5298sdtjvwc9'], + value: '500000', + }, + ], + vout: [ + { + value: '2943300', + n: 0, + scriptPubKey: { + hex: '0014842aa5a976f6b105f95af1a559438d6833dd1448', + }, + addresses: ['bc1qss42t2tk76cst7267xj4jsuddqea69zgdkql89'], + }, + { + value: '18457764510', + n: 1, + scriptPubKey: { + hex: '0014407afe0a21bd5fed4aa98da464084dd2e8a29e0d', + }, + addresses: ['bc1qgpa0uz3ph4076j4f3kjxgzzd6t5298sdtjvwc9'], + }, + { + value: '0', + n: 2, + opReturn: + 'OP_RETURN (REFUND:1A15D2C488FCA6FE4B50A930BDFCF320DAD6FCFF629B8D91310648E35FCEE967)', + scriptPubKey: { + hex: '6a47524546554e443a31413135443243343838464341364645344235304139333042444643463332304441443646434646363239423844393133313036343845333546434545393637', + }, + }, + ], +} + +const actionsResponse: ActionsResponse = { + actions: [ + { + date: '1704985751404757954', + height: '14229520', + in: [ + { + address: 'bc1qss42t2tk76cst7267xj4jsuddqea69zgdkql89', + coins: [ + { + amount: '8700', + asset: 'BTC.BTC', + }, + ], + txID: '1A15D2C488FCA6FE4B50A930BDFCF320DAD6FCFF629B8D91310648E35FCEE967', + }, + ], + metadata: { + swap: { + affiliateAddress: 'ss', + affiliateFee: '29', + isStreamingSwap: false, + liquidityFee: '5', + memo: '=:ETH.ETH:0x7fFA927b18576304bFF35d5C1bFe20CDa66C1BF1:52656381:ss:29', + networkFees: [ + { + amount: '2000000', + asset: 'THOR.RUNE', + }, + ], + swapSlip: '0', + swapTarget: '0', + }, + }, + out: [ + { + address: 'thor1xmaggkcln5m5fnha2780xrdrulmplvfrz6wj3l', + coins: [ + { + amount: '76104597', + asset: 'THOR.RUNE', + }, + ], + height: '14229520', + txID: '', + }, + { + address: 'bc1qss42t2tk76cst7267xj4jsuddqea69zgdkql89', + coins: [ + { + amount: '2943300', + asset: 'BTC.BTC', + }, + ], + height: '14229955', + txID: '89D3C6FB860248A517BCFF7B7E0846D76A6B67186DA705F798CD3A2943E6D0B2', + }, + ], + pools: ['BTC.BTC'], + status: 'success', + type: 'swap', + }, + { + date: '1704985728185659748', + height: '14229517', + in: [ + { + address: 'bc1qss42t2tk76cst7267xj4jsuddqea69zgdkql89', + coins: [ + { + amount: '2991300', + asset: 'BTC.BTC', + }, + ], + txID: '1A15D2C488FCA6FE4B50A930BDFCF320DAD6FCFF629B8D91310648E35FCEE967', + }, + ], + metadata: { + refund: { + affiliateAddress: 'ss', + affiliateFee: '29', + memo: '=:ETH.ETH:0x7fFA927b18576304bFF35d5C1bFe20CDa66C1BF1:52656381:ss:29', + networkFees: [ + { + amount: '69000', + asset: 'BTC.BTC', + }, + { + amount: '2000000', + asset: 'THOR.RUNE', + }, + ], + reason: + 'fail to add outbound tx: 2 errors occurred:\n\t* internal error\n\t* outbound amount does not meet requirements (52540689/52656381)\n\n', + }, + }, + out: [ + { + address: 'thor1xmaggkcln5m5fnha2780xrdrulmplvfrz6wj3l', + coins: [ + { + amount: '76104597', + asset: 'THOR.RUNE', + }, + ], + height: '14229520', + txID: '', + }, + { + address: 'bc1qss42t2tk76cst7267xj4jsuddqea69zgdkql89', + coins: [ + { + amount: '2943300', + asset: 'BTC.BTC', + }, + ], + height: '14229955', + txID: '89D3C6FB860248A517BCFF7B7E0846D76A6B67186DA705F798CD3A2943E6D0B2', + }, + ], + pools: [], + status: 'success', + type: 'refund', + }, + ], + count: '2', + meta: { + nextPageToken: '142295179000000377', + prevPageToken: '142295209000000112', + }, +} + +export default { tx, actionsResponse } diff --git a/packages/unchained-client/src/utxo/bitcoin/parser/index.ts b/packages/unchained-client/src/utxo/bitcoin/parser/index.ts index a31b5d95b3e..63c38f692b9 100644 --- a/packages/unchained-client/src/utxo/bitcoin/parser/index.ts +++ b/packages/unchained-client/src/utxo/bitcoin/parser/index.ts @@ -1,4 +1,16 @@ import type { Tx } from '../../../generated/bitcoin' +import type { BaseTransactionParserArgs } from '../../parser' import { BaseTransactionParser } from '../../parser' +import * as thorchain from '../../parser/thorchain' -export class TransactionParser extends BaseTransactionParser {} +export interface TransactionParserArgs extends BaseTransactionParserArgs { + midgardUrl: string +} + +export class TransactionParser extends BaseTransactionParser { + constructor(args: TransactionParserArgs) { + super(args) + + this.registerParsers([new thorchain.Parser({ midgardUrl: args.midgardUrl })]) + } +} diff --git a/packages/unchained-client/src/utxo/bitcoincash/parser/__tests__/bitcoincash.test.ts b/packages/unchained-client/src/utxo/bitcoincash/parser/__tests__/bitcoincash.test.ts index a27db3ff2f1..f5deccfeaac 100644 --- a/packages/unchained-client/src/utxo/bitcoincash/parser/__tests__/bitcoincash.test.ts +++ b/packages/unchained-client/src/utxo/bitcoincash/parser/__tests__/bitcoincash.test.ts @@ -1,5 +1,5 @@ import { bchAssetId, bchChainId } from '@shapeshiftoss/caip' -import { describe, expect, it } from 'vitest' +import { describe, expect, it, vi } from 'vitest' import type { ParsedTx } from '../../../../types' import { TransferType, TxStatus } from '../../../../types' @@ -7,7 +7,23 @@ import { TransactionParser } from '../index' import standardNoChange from './mockData/standardNoChange' import standardWithChange from './mockData/standardWithChange' -const txParser = new TransactionParser({ chainId: bchChainId, assetId: bchAssetId }) +const mocks = vi.hoisted(() => ({ + get: vi.fn(), +})) + +vi.mock('axios', () => { + const mockAxios = { + create: vi.fn(() => ({ + get: mocks.get, + })), + } + + return { + default: mockAxios, + } +}) + +const txParser = new TransactionParser({ chainId: bchChainId, assetId: bchAssetId, midgardUrl: '' }) describe('parseTx', () => { describe('standard', () => { diff --git a/packages/unchained-client/src/utxo/bitcoincash/parser/index.ts b/packages/unchained-client/src/utxo/bitcoincash/parser/index.ts index b51606879b0..d48c4b35eb5 100644 --- a/packages/unchained-client/src/utxo/bitcoincash/parser/index.ts +++ b/packages/unchained-client/src/utxo/bitcoincash/parser/index.ts @@ -1,4 +1,16 @@ import type { Tx } from '../../../generated/bitcoincash' +import type { BaseTransactionParserArgs } from '../../parser' import { BaseTransactionParser } from '../../parser' +import * as thorchain from '../../parser/thorchain' -export class TransactionParser extends BaseTransactionParser {} +export interface TransactionParserArgs extends BaseTransactionParserArgs { + midgardUrl: string +} + +export class TransactionParser extends BaseTransactionParser { + constructor(args: TransactionParserArgs) { + super(args) + + this.registerParsers([new thorchain.Parser({ midgardUrl: args.midgardUrl })]) + } +} diff --git a/packages/unchained-client/src/utxo/dogecoin/parser/__tests__/dogecoin.test.ts b/packages/unchained-client/src/utxo/dogecoin/parser/__tests__/dogecoin.test.ts index 14b0301daa1..cb0b2a39bae 100644 --- a/packages/unchained-client/src/utxo/dogecoin/parser/__tests__/dogecoin.test.ts +++ b/packages/unchained-client/src/utxo/dogecoin/parser/__tests__/dogecoin.test.ts @@ -1,5 +1,5 @@ import { dogeAssetId, dogeChainId } from '@shapeshiftoss/caip' -import { describe, expect, it } from 'vitest' +import { describe, expect, it, vi } from 'vitest' import type { ParsedTx } from '../../../../types' import { TransferType, TxStatus } from '../../../../types' @@ -7,7 +7,27 @@ import { TransactionParser } from '../index' import standardNoChange from './mockData/standardNoChange' import standardWithChange from './mockData/standardWithChange' -const txParser = new TransactionParser({ chainId: dogeChainId, assetId: dogeAssetId }) +const mocks = vi.hoisted(() => ({ + get: vi.fn(), +})) + +vi.mock('axios', () => { + const mockAxios = { + create: vi.fn(() => ({ + get: mocks.get, + })), + } + + return { + default: mockAxios, + } +}) + +const txParser = new TransactionParser({ + chainId: dogeChainId, + assetId: dogeAssetId, + midgardUrl: '', +}) describe('parseTx', () => { describe('standard', () => { diff --git a/packages/unchained-client/src/utxo/dogecoin/parser/index.ts b/packages/unchained-client/src/utxo/dogecoin/parser/index.ts index 61f103844f5..21a96a66e96 100644 --- a/packages/unchained-client/src/utxo/dogecoin/parser/index.ts +++ b/packages/unchained-client/src/utxo/dogecoin/parser/index.ts @@ -1,4 +1,16 @@ import type { Tx } from '../../../generated/dogecoin' +import type { BaseTransactionParserArgs } from '../../parser' import { BaseTransactionParser } from '../../parser' +import * as thorchain from '../../parser/thorchain' -export class TransactionParser extends BaseTransactionParser {} +export interface TransactionParserArgs extends BaseTransactionParserArgs { + midgardUrl: string +} + +export class TransactionParser extends BaseTransactionParser { + constructor(args: TransactionParserArgs) { + super(args) + + this.registerParsers([new thorchain.Parser({ midgardUrl: args.midgardUrl })]) + } +} diff --git a/packages/unchained-client/src/utxo/index.ts b/packages/unchained-client/src/utxo/index.ts index 968b4b2299a..0ea94209bd7 100644 --- a/packages/unchained-client/src/utxo/index.ts +++ b/packages/unchained-client/src/utxo/index.ts @@ -1,6 +1,6 @@ export type { utxo as types } from '@shapeshiftoss/common-api' -export { BaseTransactionParser } from './parser' +export * from './parser' export * as bitcoin from './bitcoin' export * as bitcoincash from './bitcoincash' export * as dogecoin from './dogecoin' diff --git a/packages/unchained-client/src/utxo/litecoin/parser/__tests__/litecoin.test.ts b/packages/unchained-client/src/utxo/litecoin/parser/__tests__/litecoin.test.ts index 951a5ad61a4..45597c99115 100644 --- a/packages/unchained-client/src/utxo/litecoin/parser/__tests__/litecoin.test.ts +++ b/packages/unchained-client/src/utxo/litecoin/parser/__tests__/litecoin.test.ts @@ -1,5 +1,5 @@ import { ltcAssetId, ltcChainId } from '@shapeshiftoss/caip' -import { describe, expect, it } from 'vitest' +import { describe, expect, it, vi } from 'vitest' import type { ParsedTx } from '../../../../types' import { TransferType, TxStatus } from '../../../../types' @@ -7,7 +7,23 @@ import { TransactionParser } from '../index' import standardNoChange from './mockData/standardNoChange' import standardWithChange from './mockData/standardWithChange' -const txParser = new TransactionParser({ chainId: ltcChainId, assetId: ltcAssetId }) +const mocks = vi.hoisted(() => ({ + get: vi.fn(), +})) + +vi.mock('axios', () => { + const mockAxios = { + create: vi.fn(() => ({ + get: mocks.get, + })), + } + + return { + default: mockAxios, + } +}) + +const txParser = new TransactionParser({ chainId: ltcChainId, assetId: ltcAssetId, midgardUrl: '' }) describe('parseTx', () => { describe('standard', () => { diff --git a/packages/unchained-client/src/utxo/litecoin/parser/index.ts b/packages/unchained-client/src/utxo/litecoin/parser/index.ts index 98d3c1d9382..6d90ede83a2 100644 --- a/packages/unchained-client/src/utxo/litecoin/parser/index.ts +++ b/packages/unchained-client/src/utxo/litecoin/parser/index.ts @@ -1,4 +1,16 @@ import type { Tx } from '../../../generated/litecoin' +import type { BaseTransactionParserArgs } from '../../parser' import { BaseTransactionParser } from '../../parser' +import * as thorchain from '../../parser/thorchain' -export class TransactionParser extends BaseTransactionParser {} +export interface TransactionParserArgs extends BaseTransactionParserArgs { + midgardUrl: string +} + +export class TransactionParser extends BaseTransactionParser { + constructor(args: TransactionParserArgs) { + super(args) + + this.registerParsers([new thorchain.Parser({ midgardUrl: args.midgardUrl })]) + } +} diff --git a/packages/unchained-client/src/utxo/parser/index.ts b/packages/unchained-client/src/utxo/parser/index.ts index 9ee8bc205c7..11c0fdaa61d 100644 --- a/packages/unchained-client/src/utxo/parser/index.ts +++ b/packages/unchained-client/src/utxo/parser/index.ts @@ -2,9 +2,12 @@ import type { AssetId, ChainId } from '@shapeshiftoss/caip' import type { utxo } from '@shapeshiftoss/common-api' import { BigNumber } from 'bignumber.js' -import type { ParsedTx } from '../../types' import { TransferType, TxStatus } from '../../types' import { aggregateTransfer } from '../../utils' +import type { ParsedTx } from '../parser' +import type { SubParser } from './types' + +export * from './types' export interface BaseTransactionParserArgs { chainId: ChainId @@ -15,12 +18,34 @@ export class BaseTransactionParser { chainId: ChainId assetId: AssetId + private parsers: SubParser[] = [] + constructor(args: BaseTransactionParserArgs) { this.chainId = args.chainId this.assetId = args.assetId } - parse(tx: T, address: string): Promise { + /** + * Register custom transaction sub parser to parse custom op return data + * + * _parsers should be registered from most generic first to most specific last_ + */ + registerParser(parser: SubParser): void { + this.parsers.unshift(parser) + } + + protected registerParsers(parsers: SubParser[]): void { + parsers.forEach(parser => this.registerParser(parser)) + } + + async parse(tx: T, address: string): Promise { + const parserResults = await (async () => { + for (const parser of this.parsers) { + const result = await parser.parse(tx, address) + if (result) return result + } + })() + const parsedTx: ParsedTx = { address, blockHash: tx.blockHash, @@ -29,8 +54,10 @@ export class BaseTransactionParser { chainId: this.chainId, confirmations: tx.confirmations, status: tx.confirmations > 0 ? TxStatus.Confirmed : TxStatus.Pending, - transfers: [], + transfers: parserResults?.transfers ?? [], txid: tx.txid, + trade: parserResults?.trade, + data: parserResults?.data, } tx.vin.forEach(vin => { diff --git a/packages/unchained-client/src/utxo/parser/thorchain.ts b/packages/unchained-client/src/utxo/parser/thorchain.ts new file mode 100644 index 00000000000..47b43250c26 --- /dev/null +++ b/packages/unchained-client/src/utxo/parser/thorchain.ts @@ -0,0 +1,248 @@ +import type { Axios } from 'axios' +import axios from 'axios' + +import { type BaseTxMetadata, Dex, TradeType } from '../../types' +import type { SubParser, Tx, TxSpecific } from '../parser' + +export type LiquidityType = 'Savers' | 'LP' +export type SwapType = 'Standard' | 'Streaming' + +interface Liquidity { + type: LiquidityType +} + +interface Swap { + type: SwapType +} + +export interface TxMetadata extends BaseTxMetadata { + parser: 'thorchain' + memo: string + liquidity?: Liquidity + swap?: Swap +} + +interface Coin { + amount: string + asset: string +} + +interface InOut { + txID: string + address: string + coins: Coin[] + height?: string +} + +interface Metadata { + addLiquidity?: { + liquidityUnits: string + } + refund?: { + affiliateAddress: string + affiliateFee: string + memo: string + networkFees: Coin[] + reason: string + } + swap?: { + affiliateAddress: string + affiliateFee: string + isStreamingSwap: boolean + liquidityFee: string + networkFees: Coin[] + swapSlip: string + swapTarget: string + memo: string + } + withdraw?: { + asymmetry: string + basisPoints: string + impermanentLossProtection: string + liquidityUnits: string + memo: string + networkFees: Coin[] + } +} + +interface Actions { + date: string + height: string + in: InOut[] + out: InOut[] + metadata?: Metadata + pools: string[] + status: 'success' | 'pending' + type: 'swap' | 'addLiquidity' | 'withdraw' | 'donate' | 'refund' | 'switch' +} + +export interface ActionsResponse { + actions: Actions[] + count: string + meta: { + nextPageToken: string + prevPageToken: string + } +} + +interface ExtraMetadata { + method: string + liquidity?: Liquidity + swap?: Swap +} + +const streamingSwapRegex = /:\d+\/\d+\/\d+:/ +const opReturnRegex = /OP_RETURN \((?[^)]+)\)/ + +const getLiquidityType = (pool: string): LiquidityType => (pool.includes('/') ? 'Savers' : 'LP') + +const getSwapType = (memo: string): SwapType => + streamingSwapRegex.test(memo) ? 'Streaming' : 'Standard' + +export interface ParserArgs { + midgardUrl: string +} + +export class Parser implements SubParser { + private readonly axiosMidgard: Axios + + constructor(args: ParserArgs) { + this.axiosMidgard = axios.create({ baseURL: args.midgardUrl }) + } + + async parse(tx: Tx): Promise { + const opReturn = tx.vout.find(vout => vout.opReturn)?.opReturn + if (!opReturn) return + + const memo = opReturn.match(opReturnRegex)?.groups?.memo + + if (!memo) return + + const [type] = memo.split(':') + + switch (type.toLowerCase()) { + case 'swap': + case '=': + case 's': { + return await Promise.resolve({ + data: { parser: 'thorchain', memo, swap: { type: getSwapType(memo) } }, + trade: { dexName: Dex.Thor, type: TradeType.Swap, memo }, + }) + } + case 'add': + case '+': { + const [, pool] = memo.split(':') + const type = getLiquidityType(pool) + return await Promise.resolve({ + data: { parser: 'thorchain', method: 'deposit', memo, liquidity: { type } }, + }) + } + case 'withdraw': + case '-': + case 'wd': { + const [, pool] = memo.split(':') + const type = getLiquidityType(pool) + return await Promise.resolve({ + data: { parser: 'thorchain', method: 'withdraw', memo, liquidity: { type } }, + }) + } + case '$+': + case 'loan+': + return await Promise.resolve({ + data: { parser: 'thorchain', memo, method: 'loanOpen' }, + }) + case '$-': + case 'loan-': + return await Promise.resolve({ + data: { parser: 'thorchain', memo, method: 'loanRepayment' }, + }) + case 'out': { + const extraMetadata = await this.getExtraMetadata(memo) + return await Promise.resolve({ + data: { parser: 'thorchain', memo, ...extraMetadata }, + }) + } + case 'refund': + const extraMetadata = await this.getExtraMetadata(memo) + return await Promise.resolve({ + data: { parser: 'thorchain', memo, ...extraMetadata }, + }) + default: + return + } + } + + private getExtraMetadata = async (memo: string): Promise => { + const [type, txid] = memo.split(':') + const { data } = await this.axiosMidgard.get(`/actions?txid=${txid}`) + + const action = data.actions[data.actions.length - 1] + + const swapMemo = action.metadata?.swap?.memo ?? '' + const [swapType] = swapMemo.split(':') + + const refundMemo = action.metadata?.refund?.memo ?? '' + const [refundType] = refundMemo.split(':') + + const txType = (() => { + if (swapType) { + switch (swapType) { + case '$-': + case 'loan-': + return 'loan' + default: + return action.type + } + } + + if (refundType) { + switch (refundType) { + case 'swap': + case '=': + case 's': + return 'swap' + case '$+': + case 'loan+': + return 'loanOpen' + case '$-': + case 'loan-': + return 'loanRepayment' + case 'add': + case '+': + return 'deposit' + case 'withdraw': + case '-': + case 'wd': + return 'withdraw' + default: + return action.type + } + } + + return action.type + })() + + const method = (() => { + switch (type.toLowerCase()) { + case 'out': { + return txType ? `${txType}Out` : 'out' + } + case 'refund': { + return txType ? `${txType}Refund` : 'refund' + } + default: + return 'unknown' + } + })() + + const liquidity = (() => { + if (txType === 'withdraw') return { type: getLiquidityType(action.pools[0]) } + if (type.toLowerCase() === 'refund' && txType === 'deposit') + return { type: getLiquidityType(refundMemo.split(':')[1]) } + })() + + const swap = txType === 'swap' ? { type: getSwapType(swapMemo || refundMemo) } : undefined + + return { method, liquidity, swap } + } +} diff --git a/packages/unchained-client/src/utxo/parser/types.ts b/packages/unchained-client/src/utxo/parser/types.ts new file mode 100644 index 00000000000..df046471234 --- /dev/null +++ b/packages/unchained-client/src/utxo/parser/types.ts @@ -0,0 +1,18 @@ +import type { utxo } from '@shapeshiftoss/common-api' + +import type { StandardTx } from '../../types' +import type * as thorchain from './thorchain' + +export type Tx = utxo.Tx + +export type TxMetadata = thorchain.TxMetadata + +export interface ParsedTx extends StandardTx { + data?: TxMetadata +} + +export type TxSpecific = Partial> + +export interface SubParser { + parse(tx: T, address: string): Promise +} diff --git a/src/assets/translations/en/main.json b/src/assets/translations/en/main.json index 31ae1caf215..4d593b7f6fc 100644 --- a/src/assets/translations/en/main.json +++ b/src/assets/translations/en/main.json @@ -569,6 +569,7 @@ "to": "To", "from": "From", "trade": "Trade", + "swap": "Swap", "amount": "Amount", "for": "for", "emptyMessage": "Your %{status} transactions will appear here.", @@ -603,6 +604,28 @@ "thor": { "transferOut": "Transfer out" }, + "thorchain": { + "deposit": "Deposit", + "depositRefund": "Deposit Refund", + "loanOpen": "Loan Open", + "loanOpenRefund": "Loan Open Refund", + "loanOut": "Loan Collateral Received", + "loanRepayment": "Loan Repayment", + "loanRepaymentRefund": "Loan Repayment Refund", + "out": "Outbound Received", + "swapOut": "Swap Received", + "swapRefund": "Swap Refund", + "transferOut": "Transfer Out", + "withdraw": "Withdraw Requested", + "withdrawOut": "Withdraw Received" + }, + "swap": { + "deposit": "Swap", + "streamingSwap": "Streaming Swap", + "out": "Swap", + "refund": "Refund", + "outbound": "Outbound" + }, "foxy": { "stake": "Stake", "unstake": "Unstake", @@ -631,13 +654,6 @@ "begin_redelegate": "Redelegate", "withdraw_delegator_reward": "Claim Reward" }, - "swap": { - "deposit": "Swap", - "streamingSwap": "Streaming Swap", - "out": "Swap", - "refund": "Refund", - "outbound": "Outbound" - }, "ibc": { "transfer": "Sent", "recv_packet": "Received" @@ -1731,6 +1747,7 @@ "Send": "Send", "Receive": "Receive", "Trade": "Trade", + "Swap": "Swap", "Refund": "Refund" }, "assets": "Assets", @@ -2187,4 +2204,3 @@ } } } - diff --git a/src/components/TransactionHistoryRows/TransactionGenericRow.tsx b/src/components/TransactionHistoryRows/TransactionGenericRow.tsx index f8f3ddad9e8..3f4f78ee8f9 100644 --- a/src/components/TransactionHistoryRows/TransactionGenericRow.tsx +++ b/src/components/TransactionHistoryRows/TransactionGenericRow.tsx @@ -2,6 +2,7 @@ import { ArrowDownIcon, ArrowUpIcon, WarningTwoIcon } from '@chakra-ui/icons' import type { StackDirection } from '@chakra-ui/react' import { Box, Button, Flex, SimpleGrid, Stack, Tag, useColorModeValue } from '@chakra-ui/react' import type { AssetId } from '@shapeshiftoss/caip' +import type { TxMetadata } from '@shapeshiftoss/chain-adapters' import { TradeType, TransferType, TxStatus } from '@shapeshiftoss/unchained-client' import React, { useMemo } from 'react' import { FaArrowRight, FaExchangeAlt, FaStickyNote, FaThumbsUp } from 'react-icons/fa' @@ -21,7 +22,7 @@ import { breakpoints } from 'theme/theme' import { ApproveIcon } from './components/ApproveIcon' import { AssetsTransfers } from './components/AssetsTransfers' import { AssetTransfer } from './components/AssetTransfer' -import type { getTxMetadataWithAssetId } from './utils' +import { getTxMetadataWithAssetId } from './utils' const buttonPadding = { base: 2, md: 4 } const stackDivider = ( @@ -72,6 +73,7 @@ const TransactionIcon = ({ case TransferType.Receive: return case TradeType.Trade: + case TradeType.Swap: return case Method.Approve: { return assetId && value ? ( @@ -94,7 +96,7 @@ type TransactionGenericRowProps = { transfersByType: Record fee?: Fee txid: TxId - txData?: ReturnType + txData?: TxMetadata blockTime: number explorerTxLink: string toggleOpen: () => void @@ -121,6 +123,8 @@ export const TransactionGenericRow = ({ breakPoints: [isLargerThanLg], } = GetTxLayoutFormats({ parentWidth }) + const txMetadataWithAssetId = useMemo(() => getTxMetadataWithAssetId(txData), [txData]) + const transfers = useMemo(() => { return Object.values(transfersByType).map((transfersOfType, index) => { const hasManyTypeTransfers = transfersOfType.length > 1 @@ -214,8 +218,8 @@ export const TransactionGenericRow = ({ {status === TxStatus.Pending && } @@ -254,6 +258,28 @@ export const TransactionGenericRow = ({ NFT )} + {txData && txData.parser === 'thorchain' && txData.liquidity && ( + + {txData.liquidity.type} + + )} + {txData && txData.parser === 'thorchain' && txData.swap?.type === 'Streaming' && ( + + {txData.swap.type} + + )} diff --git a/src/components/TransactionHistoryRows/TransactionMethod.tsx b/src/components/TransactionHistoryRows/TransactionMethod.tsx index 2d49c87e165..b7e82a1e371 100644 --- a/src/components/TransactionHistoryRows/TransactionMethod.tsx +++ b/src/components/TransactionHistoryRows/TransactionMethod.tsx @@ -18,13 +18,6 @@ import { TransactionGenericRow } from './TransactionGenericRow' import type { TransactionRowProps } from './TransactionRow' import { getTransfersByType, getTxMetadataWithAssetId } from './utils' -const isStreamingSwapMemo = (memo: string | undefined): boolean => { - if (!memo) return false - - const regex = /:\d+\/\d+\/\d+:/ - return regex.test(memo) -} - export const TransactionMethod = ({ txDetails, showDateAndGuide, @@ -35,8 +28,6 @@ export const TransactionMethod = ({ }: TransactionRowProps) => { const translate = useTranslate() const txMetadata = useMemo(() => txDetails.tx.data!, [txDetails.tx.data]) // we are guaranteed to have had metadata to render this component - const memo = 'memo' in txMetadata ? txMetadata.memo : undefined - const isStreamingSwap = useMemo(() => isStreamingSwapMemo(memo), [memo]) const { method, parser } = txMetadata const txMetadataWithAssetId = useMemo(() => getTxMetadataWithAssetId(txMetadata), [txMetadata]) @@ -53,8 +44,6 @@ export const TransactionMethod = ({ const symbol = asset?.symbol const titlePrefix = (() => { switch (true) { - case isStreamingSwap: - return 'transactionRow.parser.swap.streamingSwap' case method !== undefined && parser !== undefined: return `transactionRow.parser.${parser}.${method}` default: @@ -70,7 +59,7 @@ export const TransactionMethod = ({ default: return translate(titlePrefix) } - }, [asset?.symbol, method, isStreamingSwap, parser, translate]) + }, [asset?.symbol, method, parser, translate]) const type = useMemo(() => { switch (method) { @@ -79,23 +68,32 @@ export const TransactionMethod = ({ case Method.Delegate: case Method.Deposit: case Method.JoinPool: + case Method.LoanOpen: + case Method.LoanRepayment: case Method.Stake: case Method.Transfer: case Method.TransferOut: return TransferType.Send case Method.BeginUnbonding: case Method.ClaimWithdraw: + case Method.DepositRefund: case Method.Exit: case Method.ExitPool: case Method.InstantUnstake: + case Method.LoanOpenRefund: + case Method.LoanOut: + case Method.LoanRepaymentRefund: case Method.Out: case Method.Outbound: case Method.RecvPacket: case Method.Refund: case Method.RemoveLiquidityEth: + case Method.SwapOut: + case Method.SwapRefund: case Method.Unstake: case Method.Withdraw: case Method.WithdrawDelegatorReward: + case Method.WithdrawOut: return TransferType.Receive case Method.Approve: case Method.Revoke: @@ -121,7 +119,7 @@ export const TransactionMethod = ({ fee={txDetails.fee} explorerTxLink={txDetails.explorerTxLink} txid={txDetails.tx.txid} - txData={txMetadataWithAssetId} + txData={txMetadata} showDateAndGuide={showDateAndGuide} parentWidth={parentWidth} /> diff --git a/src/components/TransactionHistoryRows/TransactionRow.tsx b/src/components/TransactionHistoryRows/TransactionRow.tsx index 8552ed4eeb5..ebf23ae9a81 100644 --- a/src/components/TransactionHistoryRows/TransactionRow.tsx +++ b/src/components/TransactionHistoryRows/TransactionRow.tsx @@ -67,6 +67,7 @@ const TransactionType = ({ case TransferType.Receive: return case TradeType.Trade: + case TradeType.Swap: case TradeType.Refund: return case 'method': diff --git a/src/components/TransactionHistoryRows/TransactionTrade.tsx b/src/components/TransactionHistoryRows/TransactionTrade.tsx index 192aa48cff9..a3388589a19 100644 --- a/src/components/TransactionHistoryRows/TransactionTrade.tsx +++ b/src/components/TransactionHistoryRows/TransactionTrade.tsx @@ -42,6 +42,7 @@ export const TransactionTrade = ({ fee={txDetails.fee} explorerTxLink={txDetails.explorerTxLink} txid={txDetails.tx.txid} + txData={txDetails.tx.data} showDateAndGuide={showDateAndGuide} parentWidth={parentWidth} /> diff --git a/src/hooks/useTxDetails/useTxDetails.ts b/src/hooks/useTxDetails/useTxDetails.ts index cec8475a083..3e4a8595671 100644 --- a/src/hooks/useTxDetails/useTxDetails.ts +++ b/src/hooks/useTxDetails/useTxDetails.ts @@ -31,10 +31,16 @@ export enum Method { ClaimWithdraw = 'claimWithdraw', Delegate = 'delegate', Deposit = 'deposit', + DepositRefund = 'depositRefund', Exit = 'exit', ExitPool = 'exit_pool', InstantUnstake = 'instantUnstake', JoinPool = 'join_pool', + LoanOpen = 'loanOpen', + LoanOpenRefund = 'loanOpenRefund', + LoanOut = 'loanOut', + LoanRepayment = 'loanRepayment', + LoanRepaymentRefund = 'loanRepaymentRefund', Out = 'out', Outbound = 'outbound', RecvPacket = 'recv_packet', @@ -42,11 +48,14 @@ export enum Method { RemoveLiquidityEth = 'removeLiquidityETH', Revoke = 'revoke', Stake = 'stake', + SwapOut = 'swapOut', + SwapRefund = 'swapRefund', Transfer = 'transfer', TransferOut = 'transferOut', Unstake = 'unstake', Withdraw = 'withdraw', WithdrawDelegatorReward = 'withdraw_delegator_reward', + WithdrawOut = 'withdrawOut', } export interface TxDetails { diff --git a/src/plugins/bitcoin/index.tsx b/src/plugins/bitcoin/index.tsx index 95349eb7f33..d19ac647c8f 100644 --- a/src/plugins/bitcoin/index.tsx +++ b/src/plugins/bitcoin/index.tsx @@ -29,6 +29,7 @@ export default function register(): Plugins { return new bitcoin.ChainAdapter({ providers: { http, ws }, coinName: 'Bitcoin', + midgardUrl: getConfig().REACT_APP_MIDGARD_URL, }) }, ], diff --git a/src/plugins/bitcoincash/index.tsx b/src/plugins/bitcoincash/index.tsx index cee6ad35f24..eed364573aa 100644 --- a/src/plugins/bitcoincash/index.tsx +++ b/src/plugins/bitcoincash/index.tsx @@ -29,6 +29,7 @@ export default function register(): Plugins { return new bitcoincash.ChainAdapter({ providers: { http, ws }, coinName: 'BitcoinCash', + midgardUrl: getConfig().REACT_APP_MIDGARD_URL, }) }, ], diff --git a/src/plugins/dogecoin/index.tsx b/src/plugins/dogecoin/index.tsx index 2a193011d9c..ddce997d3da 100644 --- a/src/plugins/dogecoin/index.tsx +++ b/src/plugins/dogecoin/index.tsx @@ -29,6 +29,7 @@ export default function register(): Plugins { return new dogecoin.ChainAdapter({ providers: { http, ws }, coinName: 'Dogecoin', + midgardUrl: getConfig().REACT_APP_MIDGARD_URL, }) }, ], diff --git a/src/plugins/litecoin/index.tsx b/src/plugins/litecoin/index.tsx index 5ebc8213788..1852998813e 100644 --- a/src/plugins/litecoin/index.tsx +++ b/src/plugins/litecoin/index.tsx @@ -29,6 +29,7 @@ export default function register(): Plugins { return new litecoin.ChainAdapter({ providers: { http, ws }, coinName: 'Litecoin', + midgardUrl: getConfig().REACT_APP_MIDGARD_URL, }) }, ], diff --git a/src/state/migrations/index.ts b/src/state/migrations/index.ts index ba014a23b8a..beba3f31af6 100644 --- a/src/state/migrations/index.ts +++ b/src/state/migrations/index.ts @@ -23,4 +23,5 @@ export const migrations = { 15: clearAssets, 16: clearOpportunities, 17: clearTxHistory, + 18: clearTxHistory, }