diff --git a/web/cashtab/src/hooks/useWallet.js b/web/cashtab/src/hooks/useWallet.js --- a/web/cashtab/src/hooks/useWallet.js +++ b/web/cashtab/src/hooks/useWallet.js @@ -10,6 +10,11 @@ loadStoredWallet, isValidStoredWallet, isLegacyMigrationRequired, + whichUtxosWereAdded, + whichUtxosWereConsumed, + addNewHydratedUtxos, + removeConsumedUtxos, + areAllUtxosIncludedInIncrementallyHydratedUtxos, } from '@utils/cashMethods'; import { isValidCashtabSettings } from '@utils/validation'; import localforage from 'localforage'; @@ -210,6 +215,7 @@ ]; const utxos = await getUtxos(BCH, cashAddresses); + console.log(`utxos`, utxos); // If an error is returned or utxos from only 1 address are returned if (!utxos || isEmpty(utxos) || utxos.error || utxos.length < 2) { @@ -224,6 +230,7 @@ utxos, previousUtxos, ); + console.log(`utxosHaveChanged`, utxosHaveChanged); // If the utxo set has not changed, if (!utxosHaveChanged) { @@ -235,14 +242,102 @@ return; } - const hydratedUtxoDetails = await getHydratedUtxoDetails( - BCH, - utxos, - ); + // Hm you can only do this if utxos and wallet.state.utxos are not undefined + // they may be undefined if you boot up a new wallet + + // Nest a try...catch; if you have an error in incremental utxo approach, fall back to hydrating them all + let incrementalHydratedUtxosValid; + let incrementallyAdjustedHydratedUtxoDetails; + try { + const utxosAdded = whichUtxosWereAdded( + wallet.state.utxos, + utxos, + ); + console.log(`utxosAdded`, utxosAdded); + const utxosConsumed = whichUtxosWereConsumed( + wallet.state.utxos, + utxos, + ); + console.log(`utxosConsumed`, utxosConsumed); + console.log( + `wallet.state.hydratedUtxoDetails`, + wallet.state.hydratedUtxoDetails, + ); + + let incrementallyAdjustedHydratedUtxoDetails = + wallet.state.hydratedUtxoDetails; + + // Hydrate only added utxos + // Note this needs to be in the right format! + + if (utxosConsumed) { + incrementallyAdjustedHydratedUtxoDetails = + removeConsumedUtxos( + utxosConsumed, + incrementallyAdjustedHydratedUtxoDetails, + ); + + const afterRemoveConsumedUtxos = + incrementallyAdjustedHydratedUtxoDetails; + + console.log( + `incrementallyAdjustedHydratedUtxoDetails afterRemoveConsumedUtxos`, + afterRemoveConsumedUtxos, + ); + } + + if (utxosAdded) { + const addedHydratedUtxos = await getHydratedUtxoDetails( + BCH, + utxosAdded, + ); + console.log(`addedHydratedUtxos`, addedHydratedUtxos); + + incrementallyAdjustedHydratedUtxoDetails = + addNewHydratedUtxos( + addedHydratedUtxos, + incrementallyAdjustedHydratedUtxoDetails, + ); + const afterAddHydratedUtxoDetails = + incrementallyAdjustedHydratedUtxoDetails; + console.log( + `incrementallyAdjustedHydratedUtxoDetails afterAddHydratedUtxoDetails`, + afterAddHydratedUtxoDetails, + ); + } + // If all the above is good, find some checks, then set wallet state with that + // Else use the old way + // If (incrementallyAdjustedHydratedUtxoDetails contains all utxos as utxos) then set wallet state + // else hydrate all of'em + + const incrementalHydratedUtxosValid = + areAllUtxosIncludedInIncrementallyHydratedUtxos( + utxos, + incrementallyAdjustedHydratedUtxoDetails, + ); + console.log( + `areAllUtxosIncludedInIncrementallyHydratedUtxos`, + incrementalHydratedUtxosValid, + ); + } catch (err) { + console.log( + `Error in incremental determination of hydratedUtxoDetails`, + ); + console.log(err); + incrementalHydratedUtxosValid = false; + } + + if (!incrementalHydratedUtxosValid) { + console.log( + `Incremental approach invalid, hydrating all utxos`, + ); + incrementallyAdjustedHydratedUtxoDetails = + await getHydratedUtxoDetails(BCH, utxos); + } const slpBalancesAndUtxos = await getSlpBalancesAndUtxos( BCH, - hydratedUtxoDetails, + incrementallyAdjustedHydratedUtxoDetails, ); const txHistory = await getTxHistory(BCH, cashAddresses); @@ -276,13 +371,19 @@ newState.balances = normalizeBalance(slpBalancesAndUtxos); + // TODO -- sometimes seeing a discrepancy here + // Looks like occasionally a change utxo is seen as added, but the sent utxo is not seen as consumed + // e.g. this tx got notification for +287 https://explorer.be.cash/tx/670bd1f85413d5a093c321f32494a7df560844e04d15a10c484fef45f0527627 + console.log(`balances`, newState.balances); + newState.tokens = tokens; newState.parsedTxHistory = parsedWithTokens; newState.utxos = utxos; - newState.hydratedUtxoDetails = hydratedUtxoDetails; + newState.hydratedUtxoDetails = + incrementallyAdjustedHydratedUtxoDetails; // Set wallet with new state field wallet.state = newState; @@ -1053,7 +1154,7 @@ }).finally(() => { setLoading(false); }); - }, 10000); + }, 3000); const fetchBchPrice = async ( fiatCode = cashtabSettings ? cashtabSettings.fiatCurrency : 'usd', diff --git a/web/cashtab/src/utils/__mocks__/incrementalUtxoMocks.js b/web/cashtab/src/utils/__mocks__/incrementalUtxoMocks.js new file mode 100644 --- /dev/null +++ b/web/cashtab/src/utils/__mocks__/incrementalUtxoMocks.js @@ -0,0 +1,3652 @@ +// @generated + +// Templated mocks +// Showcase how whichUtxosWereAdded and whichUtxosWereConsumed work on easier to review mocks + +export const previousUtxosTemplate = [ + { + utxos: [], + address: 'Cashtab 145 address probably with no utxos', + }, + { + utxos: [], + address: 'Cashtab 245 address probably with no utxos', + }, + { + utxos: [ + { + tx_hash: 'some random xec utxo', + tx_pos: 1, + value: 1000, + }, + { + tx_hash: 'some random eToken utxo', + tx_pos: 1, + value: 546, + }, + { + tx_hash: 'alpha', + tx_pos: 1, + value: 25000, + }, + { + tx_hash: 'Consumed utxo from a tx sending 100,000 XEC', + tx_pos: 0, + value: 7500000, + }, + { + tx_hash: + 'Consumed utxo from a tx sending 100,000 XEC, not necessarily the same txid', + tx_pos: 1, + value: 5000000, + }, + { + tx_hash: 'Consumed utxo from sending an eToken tx (XEC utxo)', + tx_pos: 0, + value: 10546, + }, + { + tx_hash: + 'Consumed utxo from sending an eToken tx (eToken utxo)', + tx_pos: 1, + value: 546, + }, + ], + address: 'Cashtab 1899 address probably with all the utxos', + }, +]; +export const currentUtxosAfterSingleXecReceiveTxTemplate = [ + { + utxos: [], + address: 'Cashtab 145 address probably with no utxos', + }, + { + utxos: [], + address: 'Cashtab 245 address probably with no utxos', + }, + { + utxos: [ + { + tx_hash: 'some random xec utxo', + tx_pos: 1, + value: 1000, + }, + { + tx_hash: 'some random new xec utxo', + tx_pos: 1, + value: 1000, + }, + { + tx_hash: 'some random eToken utxo', + tx_pos: 1, + value: 546, + }, + { + tx_hash: 'alpha', + tx_pos: 1, + value: 25000, + }, + { + tx_hash: 'Consumed utxo from a tx sending 100,000 XEC', + tx_pos: 0, + value: 7500000, + }, + { + tx_hash: + 'Consumed utxo from a tx sending 100,000 XEC, not necessarily the same txid', + tx_pos: 1, + value: 5000000, + }, + { + tx_hash: 'Consumed utxo from sending an eToken tx (XEC utxo)', + tx_pos: 0, + value: 10546, + }, + { + tx_hash: + 'Consumed utxo from sending an eToken tx (eToken utxo)', + tx_pos: 1, + value: 546, + }, + ], + address: 'Cashtab 1899 address probably with all the utxos', + }, +]; + +export const utxosAddedBySingleXecReceiveTxTemplate = [ + { + utxos: [], + address: 'Cashtab 145 address probably with no utxos', + }, + { + utxos: [], + address: 'Cashtab 245 address probably with no utxos', + }, + { + utxos: [ + { + tx_hash: 'some random new xec utxo', + tx_pos: 1, + value: 1000, + }, + ], + address: 'Cashtab 1899 address probably with all the utxos', + }, +]; +export const utxosAddedByMultiXecReceiveTxTemplate = [ + { + utxos: [], + address: 'Cashtab 145 address probably with no utxos', + }, + { + utxos: [], + address: 'Cashtab 245 address probably with no utxos', + }, + { + utxos: [ + { + tx_hash: 'some random new xec utxo from a multi-send tx', + tx_pos: 0, + value: 1000, + }, + { + tx_hash: 'some random new xec utxo from a multi-send tx', + tx_pos: 1, + value: 1000, + }, + { + tx_hash: 'some random new xec utxo from a multi-send tx', + tx_pos: 2, + value: 1000, + }, + ], + address: 'Cashtab 1899 address probably with all the utxos', + }, +]; +export const currentUtxosAfterMultiXecReceiveTxTemplate = [ + { + utxos: [], + address: 'Cashtab 145 address probably with no utxos', + }, + { + utxos: [], + address: 'Cashtab 245 address probably with no utxos', + }, + { + utxos: [ + { + tx_hash: 'some random xec utxo', + tx_pos: 1, + value: 1000, + }, + { + tx_hash: 'some random eToken utxo', + tx_pos: 1, + value: 546, + }, + { + tx_hash: 'alpha', + tx_pos: 1, + value: 25000, + }, + { + tx_hash: 'some random new xec utxo from a multi-send tx', + tx_pos: 0, + value: 1000, + }, + { + tx_hash: 'some random new xec utxo from a multi-send tx', + tx_pos: 1, + value: 1000, + }, + { + tx_hash: 'some random new xec utxo from a multi-send tx', + tx_pos: 2, + value: 1000, + }, + { + tx_hash: 'Consumed utxo from a tx sending 100,000 XEC', + tx_pos: 0, + value: 7500000, + }, + { + tx_hash: + 'Consumed utxo from a tx sending 100,000 XEC, not necessarily the same txid', + tx_pos: 1, + value: 5000000, + }, + { + tx_hash: 'Consumed utxo from sending an eToken tx (XEC utxo)', + tx_pos: 0, + value: 10546, + }, + { + tx_hash: + 'Consumed utxo from sending an eToken tx (eToken utxo)', + tx_pos: 1, + value: 546, + }, + ], + address: 'Cashtab 1899 address probably with all the utxos', + }, +]; + +export const utxosAddedByEtokenReceiveTxTemplate = [ + { + utxos: [], + address: 'Cashtab 145 address probably with no utxos', + }, + { + utxos: [], + address: 'Cashtab 245 address probably with no utxos', + }, + { + utxos: [ + { + tx_hash: 'Newly Received eToken Utxo', + tx_pos: 0, + value: 546, + }, + ], + address: 'Cashtab 1899 address probably with all the utxos', + }, +]; +export const currentUtxosAfterEtokenReceiveTxTemplate = [ + { + utxos: [], + address: 'Cashtab 145 address probably with no utxos', + }, + { + utxos: [], + address: 'Cashtab 245 address probably with no utxos', + }, + { + utxos: [ + { + tx_hash: 'some random xec utxo', + tx_pos: 1, + value: 1000, + }, + { + tx_hash: 'some random eToken utxo', + tx_pos: 1, + value: 546, + }, + { + tx_hash: 'alpha', + tx_pos: 1, + value: 25000, + }, + { + tx_hash: 'Newly Received eToken Utxo', + tx_pos: 0, + value: 546, + }, + ], + address: 'Cashtab 1899 address probably with all the utxos', + }, +]; +export const utxosAddedBySingleXecSendTxTemplate = [ + { + utxos: [], + address: 'Cashtab 145 address probably with no utxos', + }, + { + utxos: [], + address: 'Cashtab 245 address probably with no utxos', + }, + { + utxos: [ + { + tx_hash: 'Change utxo from a tx sending 100,000 XEC', + tx_pos: 0, + value: 2500000, + }, + ], + address: 'Cashtab 1899 address probably with all the utxos', + }, +]; +export const utxosConsumedBySingleXecSendTxTemplate = [ + { + utxos: [], + address: 'Cashtab 145 address probably with no utxos', + }, + { + utxos: [], + address: 'Cashtab 245 address probably with no utxos', + }, + { + utxos: [ + { + tx_hash: 'Consumed utxo from a tx sending 100,000 XEC', + tx_pos: 0, + value: 7500000, + }, + { + tx_hash: + 'Consumed utxo from a tx sending 100,000 XEC, not necessarily the same txid', + tx_pos: 1, + value: 5000000, + }, + ], + address: 'Cashtab 1899 address probably with all the utxos', + }, +]; +export const currentUtxosAfterSingleXecSendTxTemplate = [ + { + utxos: [], + address: 'Cashtab 145 address probably with no utxos', + }, + { + utxos: [], + address: 'Cashtab 245 address probably with no utxos', + }, + { + utxos: [ + { + tx_hash: 'some random xec utxo', + tx_pos: 1, + value: 1000, + }, + { + tx_hash: 'some random eToken utxo', + tx_pos: 1, + value: 546, + }, + { + tx_hash: 'alpha', + tx_pos: 1, + value: 25000, + }, + { + tx_hash: 'Change utxo from a tx sending 100,000 XEC', + tx_pos: 0, + value: 2500000, + }, + { + tx_hash: 'Consumed utxo from sending an eToken tx (XEC utxo)', + tx_pos: 0, + value: 10546, + }, + { + tx_hash: + 'Consumed utxo from sending an eToken tx (eToken utxo)', + tx_pos: 1, + value: 546, + }, + ], + address: 'Cashtab 1899 address probably with all the utxos', + }, +]; + +export const utxosAddedByEtokenSendTxTemplate = [ + { + utxos: [], + address: 'Cashtab 145 address probably with no utxos', + }, + { + utxos: [], + address: 'Cashtab 245 address probably with no utxos', + }, + { + utxos: [ + { + tx_hash: 'Change utxo from an eToken tx (XEC change)', + tx_pos: 0, + value: 9454, + }, + { + tx_hash: 'Change utxo from an eToken tx (eToken change)', + tx_pos: 0, + value: 546, + }, + ], + address: 'Cashtab 1899 address probably with all the utxos', + }, +]; +export const utxosConsumedByEtokenSendTxTemplate = [ + { + utxos: [], + address: 'Cashtab 145 address probably with no utxos', + }, + { + utxos: [], + address: 'Cashtab 245 address probably with no utxos', + }, + { + utxos: [ + { + tx_hash: 'Consumed utxo from sending an eToken tx (XEC utxo)', + tx_pos: 0, + value: 10546, + }, + { + tx_hash: + 'Consumed utxo from sending an eToken tx (eToken utxo)', + tx_pos: 1, + value: 546, + }, + ], + address: 'Cashtab 1899 address probably with all the utxos', + }, +]; +export const currentUtxosAfterEtokenSendTxTemplate = [ + { + utxos: [], + address: 'Cashtab 145 address probably with no utxos', + }, + { + utxos: [], + address: 'Cashtab 245 address probably with no utxos', + }, + { + utxos: [ + { + tx_hash: 'some random xec utxo', + tx_pos: 1, + value: 1000, + }, + { + tx_hash: 'some random eToken utxo', + tx_pos: 1, + value: 546, + }, + { + tx_hash: 'alpha', + tx_pos: 1, + value: 25000, + }, + { + tx_hash: 'Consumed utxo from a tx sending 100,000 XEC', + tx_pos: 0, + value: 7500000, + }, + { + tx_hash: + 'Consumed utxo from a tx sending 100,000 XEC, not necessarily the same txid', + tx_pos: 1, + value: 5000000, + }, + { + tx_hash: 'Change utxo from an eToken tx (XEC change)', + tx_pos: 0, + value: 9454, + }, + { + tx_hash: 'Change utxo from an eToken tx (eToken change)', + tx_pos: 0, + value: 546, + }, + ], + address: 'Cashtab 1899 address probably with all the utxos', + }, +]; + +export const previousUtxosBeforeSendAllTxTemplate = [ + { + utxos: [], + address: 'Cashtab 145 address probably with no utxos', + }, + { + utxos: [], + address: 'Cashtab 245 address probably with no utxos', + }, + { + utxos: [ + { + tx_hash: 'alpha', + tx_pos: 1, + value: 25550, + }, + ], + address: 'Cashtab 1899 address probably with all the utxos', + }, +]; + +export const currentUtxosAfterSendAllTxTemplate = [ + { + utxos: [], + address: 'Cashtab 145 address probably with no utxos', + }, + { + utxos: [], + address: 'Cashtab 245 address probably with no utxos', + }, + { + utxos: [], + address: 'Cashtab 1899 address probably with all the utxos', + }, +]; +export const utxosConsumedBySendAllTxTemplate = + previousUtxosBeforeSendAllTxTemplate; + +export const excludedUtxoAlpha = { + // Note this is includedUtxoAlpha with tx_pos of 0 instead of 1 + height: 680784, + tx_hash: '28f061fee068d3b9cb578141bac3d4d9ec4eccebec680464bf0aafaac414811f', + tx_pos: 0, + value: 546, +}; +export const excludedUtxoBeta = { + // Note this is includedUtxoBeta with value 95212725 instead of 95212726 + height: 0, + tx_hash: '3c89d42ff868c74546ba819aaf4e5c5d5e5c63437d91c9c1cf5406ccbec3d952', + tx_pos: 3, + value: 95212725, +}; + +// Real mocks +// These mocks come from an actual Cashtab wallet +// They are kind of enormous and tricky for a reviewer to understand, +// but they come from the scenarios described in the variable names and unit tests + +export const includedUtxoAlpha = { + height: 680784, + tx_hash: '28f061fee068d3b9cb578141bac3d4d9ec4eccebec680464bf0aafaac414811f', + tx_pos: 1, + value: 546, +}; +export const includedUtxoBeta = { + height: 0, + tx_hash: '3c89d42ff868c74546ba819aaf4e5c5d5e5c63437d91c9c1cf5406ccbec3d952', + tx_pos: 3, + value: 95212726, +}; + +export const previousUtxosObjUtxoArray = [ + { + height: 680782, + tx_hash: + '525457276f1b6984170c9b35a8312d4988fce495723eabadd2afcdb3b872b2f1', + tx_pos: 1, + value: 546, + }, + { + height: 680784, + tx_hash: + '28f061fee068d3b9cb578141bac3d4d9ec4eccebec680464bf0aafaac414811f', + tx_pos: 1, + value: 546, + }, + { + height: 680784, + tx_hash: + '5fa3ffccea55c968beb7d214c563c92336ce2bbccbb714ba819848a7f7060bdb', + tx_pos: 1, + value: 546, + }, + { + height: 680784, + tx_hash: + 'daa98a872b7d88fefd2257b006db001ef82a601f3943b92e0c753076598a7b75', + tx_pos: 1, + value: 546, + }, + { + height: 681190, + tx_hash: + 'e9dca9aa954131a0004325fff11dfddcd6e5843c468116cf4d38cb264032cdc0', + tx_pos: 2, + value: 546, + }, + { + height: 681191, + tx_hash: + 'b35c502f388cdfbdd6841b7a73e973149b3c8deca76295a3e4665939e0562796', + tx_pos: 2, + value: 546, + }, + { + height: 685181, + tx_hash: + '7987f68aa70d29ac0e0ac31d74354a8b1cd515c9893f6a5cdc7a3bf505e08b05', + tx_pos: 1, + value: 546, + }, + { + height: 686546, + tx_hash: + 'bd84598096c113cd2110bc1748dd0613a933e2ddc440654c12ca4db4659933ed', + tx_pos: 1, + value: 546, + }, + { + height: 687240, + tx_hash: + 'cd9e5bc5fc041e46e8ce01ddb232c54fe48f1fb4a7288f10fdd03a6c2af875e1', + tx_pos: 2, + value: 546, + }, + { + height: 688194, + tx_hash: + '3de671a7107d3803d78f7f4a4e5c794d0903a8d28d16076445c084943c1e2db8', + tx_pos: 1, + value: 546, + }, + { + height: 688449, + tx_hash: + 'ab5079e9d24c33b31893cb98d409d24acdc396b5ab751e4c428d2463e991030c', + tx_pos: 2, + value: 546, + }, + { + height: 692599, + tx_hash: + '0158981b89b75bd923d511aaaaccd94b8d1d86babeeb69c29e3caf71e33bcc11', + tx_pos: 1, + value: 546, + }, + { + height: 692599, + tx_hash: + '1ef9ad7d3e01fd9d83983eac92eefb4900b343225a80c29bff025deff9aab57c', + tx_pos: 1, + value: 546, + }, + { + height: 693606, + tx_hash: + '9989f6f4941d7cf3206b327d957b022b41bf7e449a11fd5dd5cf1e9bc93f1ecf', + tx_pos: 2, + value: 546, + }, + { + height: 699216, + tx_hash: + '6f4e602620f5df257df8655f5834d5cfbbb73f62601c69afa96198f8ab4c2680', + tx_pos: 2, + value: 546, + }, + { + height: 699359, + tx_hash: + 'b99cb29050779d4f185c3c31c22e664436966314c8b260075b38bbb453180603', + tx_pos: 2, + value: 546, + }, + { + height: 700185, + tx_hash: + '71e458d9fd68a72fd5b13e2c758c6ba246495fa2933764876221450c096938b8', + tx_pos: 2, + value: 546, + }, + { + height: 700469, + tx_hash: + '41b9da9a5719b7bf61a02a598a37ee918a4da01e6ff5b1fb5366221ee93fd498', + tx_pos: 2, + value: 546, + }, + { + height: 700469, + tx_hash: + '6e24e89b6d5284138c69777527760500b99614631bca7f2a5c38f4648dae9524', + tx_pos: 1, + value: 546, + }, + { + height: 700469, + tx_hash: + 'bab327965a4fd423a383859b021ea2971987ceaa6fa3bc3994c3a3266a237db5', + tx_pos: 2, + value: 546, + }, + { + height: 700572, + tx_hash: + '431f527f657b399d8753fb63aee6c806ca0f8907d93606c46b36a33dcb5cb5b9', + tx_pos: 2, + value: 546, + }, + { + height: 700677, + tx_hash: + 'da9460ce4b1c92b4f6ef4e4a6bc2d05539f49d02b17681389d9ce22b8dca50f0', + tx_pos: 1, + value: 546, + }, + { + height: 700915, + tx_hash: + 'ef80e1ceeada69a9639c320c1fba47ea4417cd3aad1be1635c3472ce28aaef33', + tx_pos: 2, + value: 546, + }, + { + height: 701079, + tx_hash: + '0d5408adeefc0d9468d957a0a2bca1b63c371e68e61b3fd9c30de60058471935', + tx_pos: 1, + value: 546, + }, + { + height: 701079, + tx_hash: + '6397497c053e5c641ae624d4af80e8aa931a0e7b018f17a9543afed9b705cf29', + tx_pos: 1, + value: 546, + }, + { + height: 701079, + tx_hash: + 'c665bfd2353940648b018a3126ddbc7ac309729c7ca4598ebd7941930fd80b60', + tx_pos: 1, + value: 546, + }, + { + height: 701079, + tx_hash: + 'ebf864950d862ebb53e121350d15c8b34b2374eb22afffb98fcb655b38441d59', + tx_pos: 1, + value: 546, + }, + { + height: 701079, + tx_hash: + 'fe10460f822163c33515f3a853c1470d68223c9c0e8f8cbc6c954ca537129f30', + tx_pos: 1, + value: 546, + }, + { + height: 701189, + tx_hash: + '3656afe8682997be4cab4275e4bbec3f81c8aa264cec206a7215d449ee6b9af4', + tx_pos: 1, + value: 546, + }, + { + height: 701189, + tx_hash: + '87656bf2c2f2d46d16ba6b41b4ff488a3eff1e852c64bc921322f580e375f3cb', + tx_pos: 1, + value: 546, + }, + { + height: 701191, + tx_hash: + 'c212e45f21418fa7fd5bbf2941892353c1d6ddb9d6d16ff12fba3f7919c37b43', + tx_pos: 1, + value: 546, + }, + { + height: 701194, + tx_hash: + 'ff61be814b18f60a640169c5d70b42ce29bd9caf2f5e5592655e924760634c1e', + tx_pos: 1, + value: 546, + }, + { + height: 701208, + tx_hash: + '0e9179929b71d8a94ce9de75434d9e0901eacf3b2b882fa02a56eab450d0bd0b', + tx_pos: 1, + value: 546, + }, + { + height: 701211, + tx_hash: + '4ad31e5ab9cfcead7d8b48b81a542044e44e63124eb96d6463fe4bbe5b77e9ad', + tx_pos: 1, + value: 546, + }, + { + height: 701211, + tx_hash: + '72d4827a9a0b9adac9430ba799cb049af14fd79df11569b4e1a4741ac114b84d', + tx_pos: 1, + value: 546, + }, + { + height: 701221, + tx_hash: + '42d3e2d97604f09c002df701f964adacacd28bc328acc0066a2563d63f522681', + tx_pos: 1, + value: 546, + }, + { + height: 701223, + tx_hash: + '890bd4d72e75c4123b73dc81b9f4f89716fabe456a9047f9a5a5ef4a5162d218', + tx_pos: 2, + value: 546, + }, + { + height: 709251, + tx_hash: + '9e8483407944d9b75c331ebd6178b0cabc3e8c3b5bb0492b7b2256c8740f655a', + tx_pos: 1, + value: 546, + }, + { + height: 709259, + tx_hash: + '4f4fc78f7a008fc109789722d89fe95fe75ca1f15af625f24ae4ec74d420552e', + tx_pos: 1, + value: 546, + }, + { + height: 709668, + tx_hash: + 'da371839612b153543d0cffb09e0220dca7c7acfebda660785807b269bd0341c', + tx_pos: 1, + value: 546, + }, + { + height: 710065, + tx_hash: + '117939de3822734df69fb5cc27a6429860ee2f7a78917603da8b8aebba2a9150', + tx_pos: 1, + value: 546, + }, + { + height: 711088, + tx_hash: + '982ca55c84510e4184ff5a6e7fc310a1de7833e8c617b46014f962ed89bf0f57', + tx_pos: 2, + value: 546, + }, + { + height: 711227, + tx_hash: + 'e26db37d5c64b265514cd5cbb9d5194a7f2967b5974d167236d46be4954e435c', + tx_pos: 2, + value: 546, + }, + { + height: 715111, + tx_hash: + 'b39fdb53e21d67fa5fd3a11122f1452f15884047f2b80e8efe633c3b520b7a39', + tx_pos: 1, + value: 546, + }, + { + height: 715815, + tx_hash: + '3515f4a9851ad44124e0ddf6149344deb27a97720fc7e5254a9d2c86da7415a9', + tx_pos: 1, + value: 546, + }, + { + height: 715815, + tx_hash: + '6fb6122742cac8fd1df2d68997fdfa4c077bc22d9ef4a336bfb63d24225f9060', + tx_pos: 1, + value: 546, + }, + { + height: 715816, + tx_hash: + '2936188a41f22a3e0a47d13296147fb3f9ddd2f939fe6382904d21a610e8e49c', + tx_pos: 1, + value: 546, + }, + { + height: 717055, + tx_hash: + '18c0360f0db5399223cbed48f55c4cee9d9914c8a4a7dedcf9172a36201e9896', + tx_pos: 1, + value: 546, + }, + { + height: 717653, + tx_hash: + '3adbf501e21c711d20118e003711168eb39f560c01f4c6d6736fa3f3fceaa577', + tx_pos: 1, + value: 546, + }, + { + height: 717824, + tx_hash: + 'c0fe05d7bf71cd0f476ea18cdd4ecb26e1b9a33c911f4aaf143b2b18bc3b5f4f', + tx_pos: 1, + value: 546, + }, + { + height: 718091, + tx_hash: + '905cc5662cad77df56c3770863634ce498dde9d4772dc494d33b7ce3f36fa66c', + tx_pos: 2, + value: 546, + }, + { + height: 718280, + tx_hash: + 'f31f4ad7bf035cfb587a07a12ec60937cb8cbeafa7e4d7ed4f3276fea26fcfec', + tx_pos: 1, + value: 546, + }, + { + height: 718790, + tx_hash: + '67faa4753da2940d053f32edcda2c052a16c683aeb73f10cfde5c18266c14fe2', + tx_pos: 2, + value: 546, + }, + { + height: 720056, + tx_hash: + '9c6363fb537d529f512a12d292ea9682fe7159e6bf5ebfec5b7067b401d2dba4', + tx_pos: 1, + value: 546, + }, + { + height: 720070, + tx_hash: + '4eed87ba70864d9daa46d201c47db4513f77e5d4cc01256ab4dcc6dae9dfa055', + tx_pos: 1, + value: 546, + }, + { + height: 720070, + tx_hash: + '7975514a3185cbb70900e9767e5fcc91c86913cb1d2ad9a28474253875271e33', + tx_pos: 1, + value: 546, + }, + { + height: 720070, + tx_hash: + 'e10ae7a1bc78561ed367d59f150aebc13ef2054ba62f1a0db08fc7612d5ed58b', + tx_pos: 1, + value: 546, + }, + { + height: 720070, + tx_hash: + 'fb71c88bd5369cb8278f49ac672a9721833c36fc69143848b46ae15860339ea6', + tx_pos: 1, + value: 546, + }, + { + height: 720078, + tx_hash: + 'c3c6c6fb1619d001c29f17a701d042bc6b983e71113822aeeb66ca434fd9fa6c', + tx_pos: 1, + value: 546, + }, + { + height: 720951, + tx_hash: + 'fb50eac73a4fd5e2a701e0dbf4e575cea9c083e061b1db722e057164c7317e5b', + tx_pos: 2, + value: 546, + }, + { + height: 721083, + tx_hash: + 'dfb3dbf90fd87f6d66465ff05a61ddf1e1ca30900fadfe9cd4b73468649935ed', + tx_pos: 2, + value: 546, + }, + { + height: 724822, + tx_hash: + 'ed0dab39d5e976e433a705785726901dc83daa7d579412c18ee997341de010d3', + tx_pos: 1, + value: 546, + }, + { + height: 725143, + tx_hash: + 'e99296764134d6ea9ba7521490563762cfaf1541854ba9babc26c0df8665ac32', + tx_pos: 1, + value: 546, + }, + { + height: 725871, + tx_hash: + '82a3fe0b03ab07a564351443634da1b1ed3960e4771c59b6f8abbf7ef4b3258d', + tx_pos: 1, + value: 546, + }, + { + height: 725882, + tx_hash: + '1db1bef70013d178d7912731435029f9c8588f1d0089944c53eccffd255b5efc', + tx_pos: 2, + value: 546, + }, + { + height: 0, + tx_hash: + '6c70ada5dfda75788b48ad6da211a3ea56b4b2bad8fa807954b553742e62c73d', + tx_pos: 0, + value: 60000, + }, + { + height: 0, + tx_hash: + '94b34b291f3c77d008f3521462563ea1656542f9f8908d18a489edf5eda27fdb', + tx_pos: 0, + value: 900, + }, + { + height: 0, + tx_hash: + '9e6d5d346effd3b57bd68d95a9bfc9de1e5787f110589aa3b88d7852eebb425f', + tx_pos: 1, + value: 673, + }, + { + height: 0, + tx_hash: + '3c89d42ff868c74546ba819aaf4e5c5d5e5c63437d91c9c1cf5406ccbec3d952', + tx_pos: 2, + value: 546, + }, + { + height: 0, + tx_hash: + '3c89d42ff868c74546ba819aaf4e5c5d5e5c63437d91c9c1cf5406ccbec3d952', + tx_pos: 3, + value: 95212726, + }, +]; + +export const previousUtxosBeforeSingleXecReceiveTx = [ + { + utxos: [ + { + height: 660149, + tx_hash: + '976753770d4fd3baa0a36e0792ba6b0f906efc771b25690b5300f5437ba0f0db', + tx_pos: 2, + value: 546, + }, + { + height: 660971, + tx_hash: + 'aefc3f3c65760d0f0fa716a84d12c4dc76ca7552953d6c7a4358abb6e24c5d7c', + tx_pos: 2, + value: 546, + }, + { + height: 661700, + tx_hash: + '854d49d29819cdb5c4d9248146ffc82771cd3a7727f25a22993456f68050503e', + tx_pos: 1, + value: 546, + }, + { + height: 662159, + tx_hash: + '05e90e9f35bc041a2939e0e28cf9c436c9adb0f247a7fb0d1f4abb26d418f096', + tx_pos: 2, + value: 546, + }, + { + height: 662935, + tx_hash: + 'ec423d0089f5cd85973ff6d875e9507f6b396b3b82bf6e9f5cfb24b7c70273bd', + tx_pos: 2, + value: 546, + }, + { + height: 666954, + tx_hash: + '1b19314963be975c57eb37df12b6a8e0598bcb743226cdc684895520f51c4dfe', + tx_pos: 1, + value: 546, + }, + ], + address: 'bitcoincash:qpv9fx6mjdpgltygudnpw3tvmxdyzx7savhphtzswu', + }, + { + utxos: [], + address: 'bitcoincash:qppc593r2hhksvrz5l77n5yd6usrj74waqnqemgjgf', + }, + { + utxos: [ + { + height: 669673, + tx_hash: + 'bd8b527df1d5d3bd611a8f0ee8f14af83cb7d107fb2e140dbd2d9f4b3a86786a', + tx_pos: 1, + value: 546, + }, + { + height: 669673, + tx_hash: + 'd2ad75a6974e4dc021483f381f314d260e958cbcc444230b485436b6264eaf3d', + tx_pos: 1, + value: 546, + }, + { + height: 669942, + tx_hash: + 'ff5fe4c631a5dd3e3b1cc74cb12b9eebf04d177c206eaadb8d949cc4fbb6a092', + tx_pos: 0, + value: 546, + }, + { + height: 669958, + tx_hash: + '0da32e1f64a12ed2a4afd406368cc76ab3f8c462b26fbdd9817675ffa0fa7668', + tx_pos: 0, + value: 546, + }, + { + height: 669959, + tx_hash: + '182f50952631c4bcdd46f4d42ac68376674727fa40dbcbf1101e40fbfd58b55a', + tx_pos: 0, + value: 546, + }, + { + height: 670076, + tx_hash: + '4064e02fe523cb107fecaf3f5abaabb89f7e2bb6662751ba4f86f8d18ebeb1fa', + tx_pos: 1, + value: 546, + }, + { + height: 670482, + tx_hash: + 'b78a3f8d17fc69cd1314517c36abad85f09fbca4d43ac108bced2ac78428f2c8', + tx_pos: 0, + value: 546, + }, + { + height: 670670, + tx_hash: + '55eec1cb63d2b3aa604ba2f505735de07cb224fcdbd8e554aa1180f59cdd0541', + tx_pos: 0, + value: 546, + }, + { + height: 671724, + tx_hash: + '37f63a9b1bcdc4733425dcfc3a7f3564d5095467ad7f64707fe52dbe5c1e1897', + tx_pos: 2, + value: 546, + }, + { + height: 672701, + tx_hash: + 'f90631b48521a4147dd9dd7091ce936eddc0c3e6221ec87fa4fabacc453a0b95', + tx_pos: 1, + value: 546, + }, + { + height: 691329, + tx_hash: + '8d38f2f805ed3f4089cd28cd89ca279628a9fa933b04fd4820d14e66fc4d4ed5', + tx_pos: 1, + value: 546, + }, + { + height: 692599, + tx_hash: + '0158981b89b75bd923d511aaaaccd94b8d1d86babeeb69c29e3caf71e33bcc11', + tx_pos: 2, + value: 546, + }, + { + height: 692599, + tx_hash: + '1ef9ad7d3e01fd9d83983eac92eefb4900b343225a80c29bff025deff9aab57c', + tx_pos: 2, + value: 546, + }, + { + height: 714696, + tx_hash: + 'a3add503bba986398b39fa2200ce658423a597b4f7fe9de04a2da4501f8b05a3', + tx_pos: 1, + value: 546, + }, + { + height: 714696, + tx_hash: + 'f29939b961d8f3b27d7826e3f22451fcf9273ac84421312a20148b1e083a5bb0', + tx_pos: 1, + value: 546, + }, + { + height: 714701, + tx_hash: + '2502bdc75d3afdce0742505d53e6d50cefb1268d7c2a835c06b701702b79e1b8', + tx_pos: 1, + value: 546, + }, + { + height: 714705, + tx_hash: + '742a8e656fe7a6cff86e688ec191be780974fc54b900f58cd15049be89e9e1c5', + tx_pos: 1, + value: 546, + }, + { + height: 714823, + tx_hash: + 'c70d5f036368e184d2a52389b2f4c2471855aebaccbd418db24d4515ce062dbe', + tx_pos: 1, + value: 546, + }, + { + height: 714823, + tx_hash: + 'edb693529851379bcbd75008f78940df8232510e6a1c64d8dc81693ae2a53f66', + tx_pos: 1, + value: 546, + }, + { + height: 722860, + tx_hash: + 'afe4bc6ff9a3e26b6fb8803b754223b9f368402f479b21c39b2ff8f54bfb7f5e', + tx_pos: 2, + value: 546, + }, + { + height: 723247, + tx_hash: + 'cc03f4b178f54327d5c337650531abf2a2464e2a9a486c38c6194f8ac96e9842', + tx_pos: 2, + value: 546, + }, + { + height: 724544, + tx_hash: + '83b9bab68c36364035976c7590df0b19d2f7b16c98d51d124891289bf3a122a5', + tx_pos: 2, + value: 546, + }, + { + height: 724545, + tx_hash: + '9ea438223212fc98af2ada411ecf75e83a10ad091bebfb0adc3925f32f311c71', + tx_pos: 2, + value: 546, + }, + { + height: 725144, + tx_hash: + '69fdd3dc4914c33f980aee4dcc04e65706e43498acf92f48bf70c159cb708111', + tx_pos: 1, + value: 1254435, + }, + { + height: 725144, + tx_hash: + 'ef67e7785c2a991c4f5fc20f88b2649dd2fb2c637b6861a9586d4449ea1b06b3', + tx_pos: 1, + value: 463186023, + }, + ], + address: 'bitcoincash:qpmytrdsakt0axrrlswvaj069nat3p9s7ct4lsf8k9', + }, +]; + +export const currentUtxosAfterSingleXecReceiveTx = [ + { + utxos: [ + { + height: 660149, + tx_hash: + '976753770d4fd3baa0a36e0792ba6b0f906efc771b25690b5300f5437ba0f0db', + tx_pos: 2, + value: 546, + }, + { + height: 660971, + tx_hash: + 'aefc3f3c65760d0f0fa716a84d12c4dc76ca7552953d6c7a4358abb6e24c5d7c', + tx_pos: 2, + value: 546, + }, + { + height: 661700, + tx_hash: + '854d49d29819cdb5c4d9248146ffc82771cd3a7727f25a22993456f68050503e', + tx_pos: 1, + value: 546, + }, + { + height: 662159, + tx_hash: + '05e90e9f35bc041a2939e0e28cf9c436c9adb0f247a7fb0d1f4abb26d418f096', + tx_pos: 2, + value: 546, + }, + { + height: 662935, + tx_hash: + 'ec423d0089f5cd85973ff6d875e9507f6b396b3b82bf6e9f5cfb24b7c70273bd', + tx_pos: 2, + value: 546, + }, + { + height: 666954, + tx_hash: + '1b19314963be975c57eb37df12b6a8e0598bcb743226cdc684895520f51c4dfe', + tx_pos: 1, + value: 546, + }, + ], + address: 'bitcoincash:qpv9fx6mjdpgltygudnpw3tvmxdyzx7savhphtzswu', + }, + { + utxos: [], + address: 'bitcoincash:qppc593r2hhksvrz5l77n5yd6usrj74waqnqemgjgf', + }, + { + utxos: [ + { + height: 669673, + tx_hash: + 'bd8b527df1d5d3bd611a8f0ee8f14af83cb7d107fb2e140dbd2d9f4b3a86786a', + tx_pos: 1, + value: 546, + }, + { + height: 669673, + tx_hash: + 'd2ad75a6974e4dc021483f381f314d260e958cbcc444230b485436b6264eaf3d', + tx_pos: 1, + value: 546, + }, + { + height: 669942, + tx_hash: + 'ff5fe4c631a5dd3e3b1cc74cb12b9eebf04d177c206eaadb8d949cc4fbb6a092', + tx_pos: 0, + value: 546, + }, + { + height: 669958, + tx_hash: + '0da32e1f64a12ed2a4afd406368cc76ab3f8c462b26fbdd9817675ffa0fa7668', + tx_pos: 0, + value: 546, + }, + { + height: 669959, + tx_hash: + '182f50952631c4bcdd46f4d42ac68376674727fa40dbcbf1101e40fbfd58b55a', + tx_pos: 0, + value: 546, + }, + { + height: 670076, + tx_hash: + '4064e02fe523cb107fecaf3f5abaabb89f7e2bb6662751ba4f86f8d18ebeb1fa', + tx_pos: 1, + value: 546, + }, + { + height: 670482, + tx_hash: + 'b78a3f8d17fc69cd1314517c36abad85f09fbca4d43ac108bced2ac78428f2c8', + tx_pos: 0, + value: 546, + }, + { + height: 670670, + tx_hash: + '55eec1cb63d2b3aa604ba2f505735de07cb224fcdbd8e554aa1180f59cdd0541', + tx_pos: 0, + value: 546, + }, + { + height: 671724, + tx_hash: + '37f63a9b1bcdc4733425dcfc3a7f3564d5095467ad7f64707fe52dbe5c1e1897', + tx_pos: 2, + value: 546, + }, + { + height: 672701, + tx_hash: + 'f90631b48521a4147dd9dd7091ce936eddc0c3e6221ec87fa4fabacc453a0b95', + tx_pos: 1, + value: 546, + }, + { + height: 691329, + tx_hash: + '8d38f2f805ed3f4089cd28cd89ca279628a9fa933b04fd4820d14e66fc4d4ed5', + tx_pos: 1, + value: 546, + }, + { + height: 692599, + tx_hash: + '0158981b89b75bd923d511aaaaccd94b8d1d86babeeb69c29e3caf71e33bcc11', + tx_pos: 2, + value: 546, + }, + { + height: 692599, + tx_hash: + '1ef9ad7d3e01fd9d83983eac92eefb4900b343225a80c29bff025deff9aab57c', + tx_pos: 2, + value: 546, + }, + { + height: 714696, + tx_hash: + 'a3add503bba986398b39fa2200ce658423a597b4f7fe9de04a2da4501f8b05a3', + tx_pos: 1, + value: 546, + }, + { + height: 714696, + tx_hash: + 'f29939b961d8f3b27d7826e3f22451fcf9273ac84421312a20148b1e083a5bb0', + tx_pos: 1, + value: 546, + }, + { + height: 714701, + tx_hash: + '2502bdc75d3afdce0742505d53e6d50cefb1268d7c2a835c06b701702b79e1b8', + tx_pos: 1, + value: 546, + }, + { + height: 714705, + tx_hash: + '742a8e656fe7a6cff86e688ec191be780974fc54b900f58cd15049be89e9e1c5', + tx_pos: 1, + value: 546, + }, + { + height: 714823, + tx_hash: + 'c70d5f036368e184d2a52389b2f4c2471855aebaccbd418db24d4515ce062dbe', + tx_pos: 1, + value: 546, + }, + { + height: 714823, + tx_hash: + 'edb693529851379bcbd75008f78940df8232510e6a1c64d8dc81693ae2a53f66', + tx_pos: 1, + value: 546, + }, + { + height: 722860, + tx_hash: + 'afe4bc6ff9a3e26b6fb8803b754223b9f368402f479b21c39b2ff8f54bfb7f5e', + tx_pos: 2, + value: 546, + }, + { + height: 723247, + tx_hash: + 'cc03f4b178f54327d5c337650531abf2a2464e2a9a486c38c6194f8ac96e9842', + tx_pos: 2, + value: 546, + }, + { + height: 724544, + tx_hash: + '83b9bab68c36364035976c7590df0b19d2f7b16c98d51d124891289bf3a122a5', + tx_pos: 2, + value: 546, + }, + { + height: 724545, + tx_hash: + '9ea438223212fc98af2ada411ecf75e83a10ad091bebfb0adc3925f32f311c71', + tx_pos: 2, + value: 546, + }, + { + height: 725144, + tx_hash: + '69fdd3dc4914c33f980aee4dcc04e65706e43498acf92f48bf70c159cb708111', + tx_pos: 1, + value: 1254435, + }, + { + height: 725144, + tx_hash: + 'ef67e7785c2a991c4f5fc20f88b2649dd2fb2c637b6861a9586d4449ea1b06b3', + tx_pos: 1, + value: 463186023, + }, + { + height: 0, + tx_hash: + 'c1d76ac732b84b9cbd6d94c1463c1739e1a701c5e6bd966f904226ae43c13e0c', + tx_pos: 0, + value: 42069, + }, + ], + address: 'bitcoincash:qpmytrdsakt0axrrlswvaj069nat3p9s7ct4lsf8k9', + }, +]; +export const utxosAddedBySingleXecReceiveTx = [ + { + address: 'bitcoincash:qpv9fx6mjdpgltygudnpw3tvmxdyzx7savhphtzswu', + utxos: [], + }, + { + address: 'bitcoincash:qppc593r2hhksvrz5l77n5yd6usrj74waqnqemgjgf', + utxos: [], + }, + { + address: 'bitcoincash:qpmytrdsakt0axrrlswvaj069nat3p9s7ct4lsf8k9', + utxos: [ + { + height: 0, + tx_hash: + 'c1d76ac732b84b9cbd6d94c1463c1739e1a701c5e6bd966f904226ae43c13e0c', + tx_pos: 0, + value: 42069, + }, + ], + }, +]; + +export const previousUtxosBeforeMultiXecReceiveTx = + currentUtxosAfterSingleXecReceiveTx; +export const currentUtxosAfterMultiXecReceiveTx = [ + { + utxos: [ + { + height: 660149, + tx_hash: + '976753770d4fd3baa0a36e0792ba6b0f906efc771b25690b5300f5437ba0f0db', + tx_pos: 2, + value: 546, + }, + { + height: 660971, + tx_hash: + 'aefc3f3c65760d0f0fa716a84d12c4dc76ca7552953d6c7a4358abb6e24c5d7c', + tx_pos: 2, + value: 546, + }, + { + height: 661700, + tx_hash: + '854d49d29819cdb5c4d9248146ffc82771cd3a7727f25a22993456f68050503e', + tx_pos: 1, + value: 546, + }, + { + height: 662159, + tx_hash: + '05e90e9f35bc041a2939e0e28cf9c436c9adb0f247a7fb0d1f4abb26d418f096', + tx_pos: 2, + value: 546, + }, + { + height: 662935, + tx_hash: + 'ec423d0089f5cd85973ff6d875e9507f6b396b3b82bf6e9f5cfb24b7c70273bd', + tx_pos: 2, + value: 546, + }, + { + height: 666954, + tx_hash: + '1b19314963be975c57eb37df12b6a8e0598bcb743226cdc684895520f51c4dfe', + tx_pos: 1, + value: 546, + }, + ], + address: 'bitcoincash:qpv9fx6mjdpgltygudnpw3tvmxdyzx7savhphtzswu', + }, + { + utxos: [], + address: 'bitcoincash:qppc593r2hhksvrz5l77n5yd6usrj74waqnqemgjgf', + }, + { + utxos: [ + { + height: 669673, + tx_hash: + 'bd8b527df1d5d3bd611a8f0ee8f14af83cb7d107fb2e140dbd2d9f4b3a86786a', + tx_pos: 1, + value: 546, + }, + { + height: 669673, + tx_hash: + 'd2ad75a6974e4dc021483f381f314d260e958cbcc444230b485436b6264eaf3d', + tx_pos: 1, + value: 546, + }, + { + height: 669942, + tx_hash: + 'ff5fe4c631a5dd3e3b1cc74cb12b9eebf04d177c206eaadb8d949cc4fbb6a092', + tx_pos: 0, + value: 546, + }, + { + height: 669958, + tx_hash: + '0da32e1f64a12ed2a4afd406368cc76ab3f8c462b26fbdd9817675ffa0fa7668', + tx_pos: 0, + value: 546, + }, + { + height: 669959, + tx_hash: + '182f50952631c4bcdd46f4d42ac68376674727fa40dbcbf1101e40fbfd58b55a', + tx_pos: 0, + value: 546, + }, + { + height: 670076, + tx_hash: + '4064e02fe523cb107fecaf3f5abaabb89f7e2bb6662751ba4f86f8d18ebeb1fa', + tx_pos: 1, + value: 546, + }, + { + height: 670482, + tx_hash: + 'b78a3f8d17fc69cd1314517c36abad85f09fbca4d43ac108bced2ac78428f2c8', + tx_pos: 0, + value: 546, + }, + { + height: 670670, + tx_hash: + '55eec1cb63d2b3aa604ba2f505735de07cb224fcdbd8e554aa1180f59cdd0541', + tx_pos: 0, + value: 546, + }, + { + height: 671724, + tx_hash: + '37f63a9b1bcdc4733425dcfc3a7f3564d5095467ad7f64707fe52dbe5c1e1897', + tx_pos: 2, + value: 546, + }, + { + height: 672701, + tx_hash: + 'f90631b48521a4147dd9dd7091ce936eddc0c3e6221ec87fa4fabacc453a0b95', + tx_pos: 1, + value: 546, + }, + { + height: 691329, + tx_hash: + '8d38f2f805ed3f4089cd28cd89ca279628a9fa933b04fd4820d14e66fc4d4ed5', + tx_pos: 1, + value: 546, + }, + { + height: 692599, + tx_hash: + '0158981b89b75bd923d511aaaaccd94b8d1d86babeeb69c29e3caf71e33bcc11', + tx_pos: 2, + value: 546, + }, + { + height: 692599, + tx_hash: + '1ef9ad7d3e01fd9d83983eac92eefb4900b343225a80c29bff025deff9aab57c', + tx_pos: 2, + value: 546, + }, + { + height: 714696, + tx_hash: + 'a3add503bba986398b39fa2200ce658423a597b4f7fe9de04a2da4501f8b05a3', + tx_pos: 1, + value: 546, + }, + { + height: 714696, + tx_hash: + 'f29939b961d8f3b27d7826e3f22451fcf9273ac84421312a20148b1e083a5bb0', + tx_pos: 1, + value: 546, + }, + { + height: 714701, + tx_hash: + '2502bdc75d3afdce0742505d53e6d50cefb1268d7c2a835c06b701702b79e1b8', + tx_pos: 1, + value: 546, + }, + { + height: 714705, + tx_hash: + '742a8e656fe7a6cff86e688ec191be780974fc54b900f58cd15049be89e9e1c5', + tx_pos: 1, + value: 546, + }, + { + height: 714823, + tx_hash: + 'c70d5f036368e184d2a52389b2f4c2471855aebaccbd418db24d4515ce062dbe', + tx_pos: 1, + value: 546, + }, + { + height: 714823, + tx_hash: + 'edb693529851379bcbd75008f78940df8232510e6a1c64d8dc81693ae2a53f66', + tx_pos: 1, + value: 546, + }, + { + height: 722860, + tx_hash: + 'afe4bc6ff9a3e26b6fb8803b754223b9f368402f479b21c39b2ff8f54bfb7f5e', + tx_pos: 2, + value: 546, + }, + { + height: 723247, + tx_hash: + 'cc03f4b178f54327d5c337650531abf2a2464e2a9a486c38c6194f8ac96e9842', + tx_pos: 2, + value: 546, + }, + { + height: 724544, + tx_hash: + '83b9bab68c36364035976c7590df0b19d2f7b16c98d51d124891289bf3a122a5', + tx_pos: 2, + value: 546, + }, + { + height: 724545, + tx_hash: + '9ea438223212fc98af2ada411ecf75e83a10ad091bebfb0adc3925f32f311c71', + tx_pos: 2, + value: 546, + }, + { + height: 725144, + tx_hash: + '69fdd3dc4914c33f980aee4dcc04e65706e43498acf92f48bf70c159cb708111', + tx_pos: 1, + value: 1254435, + }, + { + height: 725144, + tx_hash: + 'ef67e7785c2a991c4f5fc20f88b2649dd2fb2c637b6861a9586d4449ea1b06b3', + tx_pos: 1, + value: 463186023, + }, + { + height: 0, + tx_hash: + '19130781afa8476b82797b0abb8ee5206f6f84ab4b1c296b900020f2a885d29a', + tx_pos: 0, + value: 42000, + }, + { + height: 0, + tx_hash: + 'c1d76ac732b84b9cbd6d94c1463c1739e1a701c5e6bd966f904226ae43c13e0c', + tx_pos: 0, + value: 42069, + }, + { + height: 0, + tx_hash: + '19130781afa8476b82797b0abb8ee5206f6f84ab4b1c296b900020f2a885d29a', + tx_pos: 1, + value: 6900, + }, + { + height: 0, + tx_hash: + '19130781afa8476b82797b0abb8ee5206f6f84ab4b1c296b900020f2a885d29a', + tx_pos: 2, + value: 3300, + }, + ], + address: 'bitcoincash:qpmytrdsakt0axrrlswvaj069nat3p9s7ct4lsf8k9', + }, +]; +export const utxosAddedByMultiXecReceiveTx = [ + { + address: 'bitcoincash:qpv9fx6mjdpgltygudnpw3tvmxdyzx7savhphtzswu', + utxos: [], + }, + { + address: 'bitcoincash:qppc593r2hhksvrz5l77n5yd6usrj74waqnqemgjgf', + utxos: [], + }, + { + address: 'bitcoincash:qpmytrdsakt0axrrlswvaj069nat3p9s7ct4lsf8k9', + utxos: [ + { + height: 0, + tx_hash: + '19130781afa8476b82797b0abb8ee5206f6f84ab4b1c296b900020f2a885d29a', + tx_pos: 0, + value: 42000, + }, + { + height: 0, + tx_hash: + '19130781afa8476b82797b0abb8ee5206f6f84ab4b1c296b900020f2a885d29a', + tx_pos: 1, + value: 6900, + }, + { + height: 0, + tx_hash: + '19130781afa8476b82797b0abb8ee5206f6f84ab4b1c296b900020f2a885d29a', + tx_pos: 2, + value: 3300, + }, + ], + }, +]; + +export const previousUtxosBeforeEtokenReceiveTx = + currentUtxosAfterMultiXecReceiveTx; +export const currentUtxosAfterEtokenReceiveTx = [ + { + utxos: [ + { + height: 660149, + tx_hash: + '976753770d4fd3baa0a36e0792ba6b0f906efc771b25690b5300f5437ba0f0db', + tx_pos: 2, + value: 546, + }, + { + height: 660971, + tx_hash: + 'aefc3f3c65760d0f0fa716a84d12c4dc76ca7552953d6c7a4358abb6e24c5d7c', + tx_pos: 2, + value: 546, + }, + { + height: 661700, + tx_hash: + '854d49d29819cdb5c4d9248146ffc82771cd3a7727f25a22993456f68050503e', + tx_pos: 1, + value: 546, + }, + { + height: 662159, + tx_hash: + '05e90e9f35bc041a2939e0e28cf9c436c9adb0f247a7fb0d1f4abb26d418f096', + tx_pos: 2, + value: 546, + }, + { + height: 662935, + tx_hash: + 'ec423d0089f5cd85973ff6d875e9507f6b396b3b82bf6e9f5cfb24b7c70273bd', + tx_pos: 2, + value: 546, + }, + { + height: 666954, + tx_hash: + '1b19314963be975c57eb37df12b6a8e0598bcb743226cdc684895520f51c4dfe', + tx_pos: 1, + value: 546, + }, + ], + address: 'bitcoincash:qpv9fx6mjdpgltygudnpw3tvmxdyzx7savhphtzswu', + }, + { + utxos: [], + address: 'bitcoincash:qppc593r2hhksvrz5l77n5yd6usrj74waqnqemgjgf', + }, + { + utxos: [ + { + height: 669673, + tx_hash: + 'bd8b527df1d5d3bd611a8f0ee8f14af83cb7d107fb2e140dbd2d9f4b3a86786a', + tx_pos: 1, + value: 546, + }, + { + height: 669673, + tx_hash: + 'd2ad75a6974e4dc021483f381f314d260e958cbcc444230b485436b6264eaf3d', + tx_pos: 1, + value: 546, + }, + { + height: 669942, + tx_hash: + 'ff5fe4c631a5dd3e3b1cc74cb12b9eebf04d177c206eaadb8d949cc4fbb6a092', + tx_pos: 0, + value: 546, + }, + { + height: 669958, + tx_hash: + '0da32e1f64a12ed2a4afd406368cc76ab3f8c462b26fbdd9817675ffa0fa7668', + tx_pos: 0, + value: 546, + }, + { + height: 669959, + tx_hash: + '182f50952631c4bcdd46f4d42ac68376674727fa40dbcbf1101e40fbfd58b55a', + tx_pos: 0, + value: 546, + }, + { + height: 670076, + tx_hash: + '4064e02fe523cb107fecaf3f5abaabb89f7e2bb6662751ba4f86f8d18ebeb1fa', + tx_pos: 1, + value: 546, + }, + { + height: 670482, + tx_hash: + 'b78a3f8d17fc69cd1314517c36abad85f09fbca4d43ac108bced2ac78428f2c8', + tx_pos: 0, + value: 546, + }, + { + height: 670670, + tx_hash: + '55eec1cb63d2b3aa604ba2f505735de07cb224fcdbd8e554aa1180f59cdd0541', + tx_pos: 0, + value: 546, + }, + { + height: 671724, + tx_hash: + '37f63a9b1bcdc4733425dcfc3a7f3564d5095467ad7f64707fe52dbe5c1e1897', + tx_pos: 2, + value: 546, + }, + { + height: 672701, + tx_hash: + 'f90631b48521a4147dd9dd7091ce936eddc0c3e6221ec87fa4fabacc453a0b95', + tx_pos: 1, + value: 546, + }, + { + height: 691329, + tx_hash: + '8d38f2f805ed3f4089cd28cd89ca279628a9fa933b04fd4820d14e66fc4d4ed5', + tx_pos: 1, + value: 546, + }, + { + height: 692599, + tx_hash: + '0158981b89b75bd923d511aaaaccd94b8d1d86babeeb69c29e3caf71e33bcc11', + tx_pos: 2, + value: 546, + }, + { + height: 692599, + tx_hash: + '1ef9ad7d3e01fd9d83983eac92eefb4900b343225a80c29bff025deff9aab57c', + tx_pos: 2, + value: 546, + }, + { + height: 714696, + tx_hash: + 'a3add503bba986398b39fa2200ce658423a597b4f7fe9de04a2da4501f8b05a3', + tx_pos: 1, + value: 546, + }, + { + height: 714696, + tx_hash: + 'f29939b961d8f3b27d7826e3f22451fcf9273ac84421312a20148b1e083a5bb0', + tx_pos: 1, + value: 546, + }, + { + height: 714701, + tx_hash: + '2502bdc75d3afdce0742505d53e6d50cefb1268d7c2a835c06b701702b79e1b8', + tx_pos: 1, + value: 546, + }, + { + height: 714705, + tx_hash: + '742a8e656fe7a6cff86e688ec191be780974fc54b900f58cd15049be89e9e1c5', + tx_pos: 1, + value: 546, + }, + { + height: 714823, + tx_hash: + 'c70d5f036368e184d2a52389b2f4c2471855aebaccbd418db24d4515ce062dbe', + tx_pos: 1, + value: 546, + }, + { + height: 714823, + tx_hash: + 'edb693529851379bcbd75008f78940df8232510e6a1c64d8dc81693ae2a53f66', + tx_pos: 1, + value: 546, + }, + { + height: 722860, + tx_hash: + 'afe4bc6ff9a3e26b6fb8803b754223b9f368402f479b21c39b2ff8f54bfb7f5e', + tx_pos: 2, + value: 546, + }, + { + height: 723247, + tx_hash: + 'cc03f4b178f54327d5c337650531abf2a2464e2a9a486c38c6194f8ac96e9842', + tx_pos: 2, + value: 546, + }, + { + height: 724544, + tx_hash: + '83b9bab68c36364035976c7590df0b19d2f7b16c98d51d124891289bf3a122a5', + tx_pos: 2, + value: 546, + }, + { + height: 724545, + tx_hash: + '9ea438223212fc98af2ada411ecf75e83a10ad091bebfb0adc3925f32f311c71', + tx_pos: 2, + value: 546, + }, + { + height: 725144, + tx_hash: + '69fdd3dc4914c33f980aee4dcc04e65706e43498acf92f48bf70c159cb708111', + tx_pos: 1, + value: 1254435, + }, + { + height: 725144, + tx_hash: + 'ef67e7785c2a991c4f5fc20f88b2649dd2fb2c637b6861a9586d4449ea1b06b3', + tx_pos: 1, + value: 463186023, + }, + { + height: 726142, + tx_hash: + '19130781afa8476b82797b0abb8ee5206f6f84ab4b1c296b900020f2a885d29a', + tx_pos: 0, + value: 42000, + }, + { + height: 726142, + tx_hash: + '19130781afa8476b82797b0abb8ee5206f6f84ab4b1c296b900020f2a885d29a', + tx_pos: 1, + value: 6900, + }, + { + height: 726142, + tx_hash: + '19130781afa8476b82797b0abb8ee5206f6f84ab4b1c296b900020f2a885d29a', + tx_pos: 2, + value: 3300, + }, + { + height: 726142, + tx_hash: + 'c1d76ac732b84b9cbd6d94c1463c1739e1a701c5e6bd966f904226ae43c13e0c', + tx_pos: 0, + value: 42069, + }, + { + height: 0, + tx_hash: + '66f0663e79f6a7fa3bf0834a16b48cb86fa42076c0df25ae89b402d5ee97c311', + tx_pos: 1, + value: 546, + }, + ], + address: 'bitcoincash:qpmytrdsakt0axrrlswvaj069nat3p9s7ct4lsf8k9', + }, +]; +export const utxosAddedByEtokenReceiveTx = [ + { + address: 'bitcoincash:qpv9fx6mjdpgltygudnpw3tvmxdyzx7savhphtzswu', + utxos: [], + }, + { + address: 'bitcoincash:qppc593r2hhksvrz5l77n5yd6usrj74waqnqemgjgf', + utxos: [], + }, + { + address: 'bitcoincash:qpmytrdsakt0axrrlswvaj069nat3p9s7ct4lsf8k9', + utxos: [ + { + height: 0, + tx_hash: + '66f0663e79f6a7fa3bf0834a16b48cb86fa42076c0df25ae89b402d5ee97c311', + tx_pos: 1, + value: 546, + }, + ], + }, +]; + +export const previousUtxosBeforeSingleXecSendTx = + currentUtxosAfterEtokenReceiveTx; +export const currentUtxosAfterSingleXecSendTx = [ + { + utxos: [ + { + height: 660149, + tx_hash: + '976753770d4fd3baa0a36e0792ba6b0f906efc771b25690b5300f5437ba0f0db', + tx_pos: 2, + value: 546, + }, + { + height: 660971, + tx_hash: + 'aefc3f3c65760d0f0fa716a84d12c4dc76ca7552953d6c7a4358abb6e24c5d7c', + tx_pos: 2, + value: 546, + }, + { + height: 661700, + tx_hash: + '854d49d29819cdb5c4d9248146ffc82771cd3a7727f25a22993456f68050503e', + tx_pos: 1, + value: 546, + }, + { + height: 662159, + tx_hash: + '05e90e9f35bc041a2939e0e28cf9c436c9adb0f247a7fb0d1f4abb26d418f096', + tx_pos: 2, + value: 546, + }, + { + height: 662935, + tx_hash: + 'ec423d0089f5cd85973ff6d875e9507f6b396b3b82bf6e9f5cfb24b7c70273bd', + tx_pos: 2, + value: 546, + }, + { + height: 666954, + tx_hash: + '1b19314963be975c57eb37df12b6a8e0598bcb743226cdc684895520f51c4dfe', + tx_pos: 1, + value: 546, + }, + ], + address: 'bitcoincash:qpv9fx6mjdpgltygudnpw3tvmxdyzx7savhphtzswu', + }, + { + utxos: [], + address: 'bitcoincash:qppc593r2hhksvrz5l77n5yd6usrj74waqnqemgjgf', + }, + { + utxos: [ + { + height: 669673, + tx_hash: + 'bd8b527df1d5d3bd611a8f0ee8f14af83cb7d107fb2e140dbd2d9f4b3a86786a', + tx_pos: 1, + value: 546, + }, + { + height: 669673, + tx_hash: + 'd2ad75a6974e4dc021483f381f314d260e958cbcc444230b485436b6264eaf3d', + tx_pos: 1, + value: 546, + }, + { + height: 669942, + tx_hash: + 'ff5fe4c631a5dd3e3b1cc74cb12b9eebf04d177c206eaadb8d949cc4fbb6a092', + tx_pos: 0, + value: 546, + }, + { + height: 669958, + tx_hash: + '0da32e1f64a12ed2a4afd406368cc76ab3f8c462b26fbdd9817675ffa0fa7668', + tx_pos: 0, + value: 546, + }, + { + height: 669959, + tx_hash: + '182f50952631c4bcdd46f4d42ac68376674727fa40dbcbf1101e40fbfd58b55a', + tx_pos: 0, + value: 546, + }, + { + height: 670076, + tx_hash: + '4064e02fe523cb107fecaf3f5abaabb89f7e2bb6662751ba4f86f8d18ebeb1fa', + tx_pos: 1, + value: 546, + }, + { + height: 670482, + tx_hash: + 'b78a3f8d17fc69cd1314517c36abad85f09fbca4d43ac108bced2ac78428f2c8', + tx_pos: 0, + value: 546, + }, + { + height: 670670, + tx_hash: + '55eec1cb63d2b3aa604ba2f505735de07cb224fcdbd8e554aa1180f59cdd0541', + tx_pos: 0, + value: 546, + }, + { + height: 671724, + tx_hash: + '37f63a9b1bcdc4733425dcfc3a7f3564d5095467ad7f64707fe52dbe5c1e1897', + tx_pos: 2, + value: 546, + }, + { + height: 672701, + tx_hash: + 'f90631b48521a4147dd9dd7091ce936eddc0c3e6221ec87fa4fabacc453a0b95', + tx_pos: 1, + value: 546, + }, + { + height: 691329, + tx_hash: + '8d38f2f805ed3f4089cd28cd89ca279628a9fa933b04fd4820d14e66fc4d4ed5', + tx_pos: 1, + value: 546, + }, + { + height: 692599, + tx_hash: + '0158981b89b75bd923d511aaaaccd94b8d1d86babeeb69c29e3caf71e33bcc11', + tx_pos: 2, + value: 546, + }, + { + height: 692599, + tx_hash: + '1ef9ad7d3e01fd9d83983eac92eefb4900b343225a80c29bff025deff9aab57c', + tx_pos: 2, + value: 546, + }, + { + height: 714696, + tx_hash: + 'a3add503bba986398b39fa2200ce658423a597b4f7fe9de04a2da4501f8b05a3', + tx_pos: 1, + value: 546, + }, + { + height: 714696, + tx_hash: + 'f29939b961d8f3b27d7826e3f22451fcf9273ac84421312a20148b1e083a5bb0', + tx_pos: 1, + value: 546, + }, + { + height: 714701, + tx_hash: + '2502bdc75d3afdce0742505d53e6d50cefb1268d7c2a835c06b701702b79e1b8', + tx_pos: 1, + value: 546, + }, + { + height: 714705, + tx_hash: + '742a8e656fe7a6cff86e688ec191be780974fc54b900f58cd15049be89e9e1c5', + tx_pos: 1, + value: 546, + }, + { + height: 714823, + tx_hash: + 'c70d5f036368e184d2a52389b2f4c2471855aebaccbd418db24d4515ce062dbe', + tx_pos: 1, + value: 546, + }, + { + height: 714823, + tx_hash: + 'edb693529851379bcbd75008f78940df8232510e6a1c64d8dc81693ae2a53f66', + tx_pos: 1, + value: 546, + }, + { + height: 722860, + tx_hash: + 'afe4bc6ff9a3e26b6fb8803b754223b9f368402f479b21c39b2ff8f54bfb7f5e', + tx_pos: 2, + value: 546, + }, + { + height: 723247, + tx_hash: + 'cc03f4b178f54327d5c337650531abf2a2464e2a9a486c38c6194f8ac96e9842', + tx_pos: 2, + value: 546, + }, + { + height: 724544, + tx_hash: + '83b9bab68c36364035976c7590df0b19d2f7b16c98d51d124891289bf3a122a5', + tx_pos: 2, + value: 546, + }, + { + height: 724545, + tx_hash: + '9ea438223212fc98af2ada411ecf75e83a10ad091bebfb0adc3925f32f311c71', + tx_pos: 2, + value: 546, + }, + { + height: 726142, + tx_hash: + '19130781afa8476b82797b0abb8ee5206f6f84ab4b1c296b900020f2a885d29a', + tx_pos: 0, + value: 42000, + }, + { + height: 726142, + tx_hash: + '19130781afa8476b82797b0abb8ee5206f6f84ab4b1c296b900020f2a885d29a', + tx_pos: 1, + value: 6900, + }, + { + height: 726142, + tx_hash: + '19130781afa8476b82797b0abb8ee5206f6f84ab4b1c296b900020f2a885d29a', + tx_pos: 2, + value: 3300, + }, + { + height: 726142, + tx_hash: + 'c1d76ac732b84b9cbd6d94c1463c1739e1a701c5e6bd966f904226ae43c13e0c', + tx_pos: 0, + value: 42069, + }, + { + height: 726143, + tx_hash: + '66f0663e79f6a7fa3bf0834a16b48cb86fa42076c0df25ae89b402d5ee97c311', + tx_pos: 1, + value: 546, + }, + { + height: 0, + tx_hash: + '082fb2d1289f1c6576c34c714c3a7b3e8fef89e16802d0ea47777fcf339c99ee', + tx_pos: 1, + value: 460232806, + }, + ], + address: 'bitcoincash:qpmytrdsakt0axrrlswvaj069nat3p9s7ct4lsf8k9', + }, +]; +// i.e. change +export const utxosAddedBySingleXecSendTx = [ + { + address: 'bitcoincash:qpv9fx6mjdpgltygudnpw3tvmxdyzx7savhphtzswu', + utxos: [], + }, + { + address: 'bitcoincash:qppc593r2hhksvrz5l77n5yd6usrj74waqnqemgjgf', + utxos: [], + }, + { + address: 'bitcoincash:qpmytrdsakt0axrrlswvaj069nat3p9s7ct4lsf8k9', + utxos: [ + { + height: 0, + tx_hash: + '082fb2d1289f1c6576c34c714c3a7b3e8fef89e16802d0ea47777fcf339c99ee', + tx_pos: 1, + value: 460232806, + }, + ], + }, +]; +export const utxosConsumedBySingleXecSendTx = [ + { + address: 'bitcoincash:qpv9fx6mjdpgltygudnpw3tvmxdyzx7savhphtzswu', + utxos: [], + }, + { + address: 'bitcoincash:qppc593r2hhksvrz5l77n5yd6usrj74waqnqemgjgf', + utxos: [], + }, + { + address: 'bitcoincash:qpmytrdsakt0axrrlswvaj069nat3p9s7ct4lsf8k9', + utxos: [ + { + height: 725144, + tx_hash: + '69fdd3dc4914c33f980aee4dcc04e65706e43498acf92f48bf70c159cb708111', + tx_pos: 1, + value: 1254435, + }, + { + height: 725144, + tx_hash: + 'ef67e7785c2a991c4f5fc20f88b2649dd2fb2c637b6861a9586d4449ea1b06b3', + tx_pos: 1, + value: 463186023, + }, + ], + }, +]; + +export const utxosAddedByEtokenSendTx = [ + { + address: 'bitcoincash:qq0mw6nah9huwaxt45qw3fegjpszkjlrqsvttwy36p', + utxos: [], + }, + { + address: 'bitcoincash:qz5lf9pxde9neq3hzte8mmwts03sktl9nuz6m3dynu', + utxos: [], + }, + { + address: 'bitcoincash:qz2708636snqhsxu8wnlka78h6fdp77ar5ulhz04hr', + utxos: [ + { + height: 0, + tx_hash: + 'b8982cf5531afcba125a9e17550d42a01045c3aa5ee70a485f8fbcde3dae191d', + tx_pos: 2, + value: 546, + }, + { + height: 0, + tx_hash: + 'b8982cf5531afcba125a9e17550d42a01045c3aa5ee70a485f8fbcde3dae191d', + tx_pos: 3, + value: 95200829, + }, + ], + }, +]; +export const utxosConsumedByEtokenSendTx = [ + { + address: 'bitcoincash:qq0mw6nah9huwaxt45qw3fegjpszkjlrqsvttwy36p', + utxos: [], + }, + { + address: 'bitcoincash:qz5lf9pxde9neq3hzte8mmwts03sktl9nuz6m3dynu', + utxos: [], + }, + { + address: 'bitcoincash:qz2708636snqhsxu8wnlka78h6fdp77ar5ulhz04hr', + utxos: [ + { + height: 711088, + tx_hash: + '982ca55c84510e4184ff5a6e7fc310a1de7833e8c617b46014f962ed89bf0f57', + tx_pos: 2, + value: 546, + }, + { + height: 726009, + tx_hash: + '9a0ba92af0aaaf16ec6a8bf0fc12d919078cd4c3f556a27dc792689803337ef9', + tx_pos: 1, + value: 95202647, + }, + ], + }, +]; + +export const previousUtxosBeforeEtokenSendTx = [ + { + utxos: [], + address: 'bitcoincash:qq0mw6nah9huwaxt45qw3fegjpszkjlrqsvttwy36p', + }, + { + utxos: [], + address: 'bitcoincash:qz5lf9pxde9neq3hzte8mmwts03sktl9nuz6m3dynu', + }, + { + utxos: [ + { + height: 680782, + tx_hash: + '525457276f1b6984170c9b35a8312d4988fce495723eabadd2afcdb3b872b2f1', + tx_pos: 1, + value: 546, + }, + { + height: 680784, + tx_hash: + '28f061fee068d3b9cb578141bac3d4d9ec4eccebec680464bf0aafaac414811f', + tx_pos: 1, + value: 546, + }, + { + height: 680784, + tx_hash: + '5fa3ffccea55c968beb7d214c563c92336ce2bbccbb714ba819848a7f7060bdb', + tx_pos: 1, + value: 546, + }, + { + height: 680784, + tx_hash: + 'daa98a872b7d88fefd2257b006db001ef82a601f3943b92e0c753076598a7b75', + tx_pos: 1, + value: 546, + }, + { + height: 681190, + tx_hash: + 'e9dca9aa954131a0004325fff11dfddcd6e5843c468116cf4d38cb264032cdc0', + tx_pos: 2, + value: 546, + }, + { + height: 681191, + tx_hash: + 'b35c502f388cdfbdd6841b7a73e973149b3c8deca76295a3e4665939e0562796', + tx_pos: 2, + value: 546, + }, + { + height: 685181, + tx_hash: + '7987f68aa70d29ac0e0ac31d74354a8b1cd515c9893f6a5cdc7a3bf505e08b05', + tx_pos: 1, + value: 546, + }, + { + height: 686546, + tx_hash: + 'bd84598096c113cd2110bc1748dd0613a933e2ddc440654c12ca4db4659933ed', + tx_pos: 1, + value: 546, + }, + { + height: 687240, + tx_hash: + 'cd9e5bc5fc041e46e8ce01ddb232c54fe48f1fb4a7288f10fdd03a6c2af875e1', + tx_pos: 2, + value: 546, + }, + { + height: 688194, + tx_hash: + '3de671a7107d3803d78f7f4a4e5c794d0903a8d28d16076445c084943c1e2db8', + tx_pos: 1, + value: 546, + }, + { + height: 688449, + tx_hash: + 'ab5079e9d24c33b31893cb98d409d24acdc396b5ab751e4c428d2463e991030c', + tx_pos: 2, + value: 546, + }, + { + height: 692599, + tx_hash: + '0158981b89b75bd923d511aaaaccd94b8d1d86babeeb69c29e3caf71e33bcc11', + tx_pos: 1, + value: 546, + }, + { + height: 692599, + tx_hash: + '1ef9ad7d3e01fd9d83983eac92eefb4900b343225a80c29bff025deff9aab57c', + tx_pos: 1, + value: 546, + }, + { + height: 693606, + tx_hash: + '9989f6f4941d7cf3206b327d957b022b41bf7e449a11fd5dd5cf1e9bc93f1ecf', + tx_pos: 2, + value: 546, + }, + { + height: 699216, + tx_hash: + '6f4e602620f5df257df8655f5834d5cfbbb73f62601c69afa96198f8ab4c2680', + tx_pos: 2, + value: 546, + }, + { + height: 699359, + tx_hash: + 'b99cb29050779d4f185c3c31c22e664436966314c8b260075b38bbb453180603', + tx_pos: 2, + value: 546, + }, + { + height: 700185, + tx_hash: + '71e458d9fd68a72fd5b13e2c758c6ba246495fa2933764876221450c096938b8', + tx_pos: 2, + value: 546, + }, + { + height: 700469, + tx_hash: + '41b9da9a5719b7bf61a02a598a37ee918a4da01e6ff5b1fb5366221ee93fd498', + tx_pos: 2, + value: 546, + }, + { + height: 700469, + tx_hash: + '6e24e89b6d5284138c69777527760500b99614631bca7f2a5c38f4648dae9524', + tx_pos: 1, + value: 546, + }, + { + height: 700469, + tx_hash: + 'bab327965a4fd423a383859b021ea2971987ceaa6fa3bc3994c3a3266a237db5', + tx_pos: 2, + value: 546, + }, + { + height: 700572, + tx_hash: + '431f527f657b399d8753fb63aee6c806ca0f8907d93606c46b36a33dcb5cb5b9', + tx_pos: 2, + value: 546, + }, + { + height: 700677, + tx_hash: + 'da9460ce4b1c92b4f6ef4e4a6bc2d05539f49d02b17681389d9ce22b8dca50f0', + tx_pos: 1, + value: 546, + }, + { + height: 700915, + tx_hash: + 'ef80e1ceeada69a9639c320c1fba47ea4417cd3aad1be1635c3472ce28aaef33', + tx_pos: 2, + value: 546, + }, + { + height: 701079, + tx_hash: + '0d5408adeefc0d9468d957a0a2bca1b63c371e68e61b3fd9c30de60058471935', + tx_pos: 1, + value: 546, + }, + { + height: 701079, + tx_hash: + '6397497c053e5c641ae624d4af80e8aa931a0e7b018f17a9543afed9b705cf29', + tx_pos: 1, + value: 546, + }, + { + height: 701079, + tx_hash: + 'c665bfd2353940648b018a3126ddbc7ac309729c7ca4598ebd7941930fd80b60', + tx_pos: 1, + value: 546, + }, + { + height: 701079, + tx_hash: + 'ebf864950d862ebb53e121350d15c8b34b2374eb22afffb98fcb655b38441d59', + tx_pos: 1, + value: 546, + }, + { + height: 701079, + tx_hash: + 'fe10460f822163c33515f3a853c1470d68223c9c0e8f8cbc6c954ca537129f30', + tx_pos: 1, + value: 546, + }, + { + height: 701189, + tx_hash: + '3656afe8682997be4cab4275e4bbec3f81c8aa264cec206a7215d449ee6b9af4', + tx_pos: 1, + value: 546, + }, + { + height: 701189, + tx_hash: + '87656bf2c2f2d46d16ba6b41b4ff488a3eff1e852c64bc921322f580e375f3cb', + tx_pos: 1, + value: 546, + }, + { + height: 701191, + tx_hash: + 'c212e45f21418fa7fd5bbf2941892353c1d6ddb9d6d16ff12fba3f7919c37b43', + tx_pos: 1, + value: 546, + }, + { + height: 701194, + tx_hash: + 'ff61be814b18f60a640169c5d70b42ce29bd9caf2f5e5592655e924760634c1e', + tx_pos: 1, + value: 546, + }, + { + height: 701208, + tx_hash: + '0e9179929b71d8a94ce9de75434d9e0901eacf3b2b882fa02a56eab450d0bd0b', + tx_pos: 1, + value: 546, + }, + { + height: 701211, + tx_hash: + '4ad31e5ab9cfcead7d8b48b81a542044e44e63124eb96d6463fe4bbe5b77e9ad', + tx_pos: 1, + value: 546, + }, + { + height: 701211, + tx_hash: + '72d4827a9a0b9adac9430ba799cb049af14fd79df11569b4e1a4741ac114b84d', + tx_pos: 1, + value: 546, + }, + { + height: 701221, + tx_hash: + '42d3e2d97604f09c002df701f964adacacd28bc328acc0066a2563d63f522681', + tx_pos: 1, + value: 546, + }, + { + height: 701223, + tx_hash: + '890bd4d72e75c4123b73dc81b9f4f89716fabe456a9047f9a5a5ef4a5162d218', + tx_pos: 2, + value: 546, + }, + { + height: 709251, + tx_hash: + '9e8483407944d9b75c331ebd6178b0cabc3e8c3b5bb0492b7b2256c8740f655a', + tx_pos: 1, + value: 546, + }, + { + height: 709259, + tx_hash: + '4f4fc78f7a008fc109789722d89fe95fe75ca1f15af625f24ae4ec74d420552e', + tx_pos: 1, + value: 546, + }, + { + height: 709668, + tx_hash: + 'da371839612b153543d0cffb09e0220dca7c7acfebda660785807b269bd0341c', + tx_pos: 1, + value: 546, + }, + { + height: 710065, + tx_hash: + '117939de3822734df69fb5cc27a6429860ee2f7a78917603da8b8aebba2a9150', + tx_pos: 1, + value: 546, + }, + { + height: 711088, + tx_hash: + '982ca55c84510e4184ff5a6e7fc310a1de7833e8c617b46014f962ed89bf0f57', + tx_pos: 2, + value: 546, + }, + { + height: 711227, + tx_hash: + 'e26db37d5c64b265514cd5cbb9d5194a7f2967b5974d167236d46be4954e435c', + tx_pos: 2, + value: 546, + }, + { + height: 715111, + tx_hash: + 'b39fdb53e21d67fa5fd3a11122f1452f15884047f2b80e8efe633c3b520b7a39', + tx_pos: 1, + value: 546, + }, + { + height: 715815, + tx_hash: + '3515f4a9851ad44124e0ddf6149344deb27a97720fc7e5254a9d2c86da7415a9', + tx_pos: 1, + value: 546, + }, + { + height: 715815, + tx_hash: + '6fb6122742cac8fd1df2d68997fdfa4c077bc22d9ef4a336bfb63d24225f9060', + tx_pos: 1, + value: 546, + }, + { + height: 715816, + tx_hash: + '2936188a41f22a3e0a47d13296147fb3f9ddd2f939fe6382904d21a610e8e49c', + tx_pos: 1, + value: 546, + }, + { + height: 717055, + tx_hash: + '18c0360f0db5399223cbed48f55c4cee9d9914c8a4a7dedcf9172a36201e9896', + tx_pos: 1, + value: 546, + }, + { + height: 717653, + tx_hash: + '3adbf501e21c711d20118e003711168eb39f560c01f4c6d6736fa3f3fceaa577', + tx_pos: 1, + value: 546, + }, + { + height: 717824, + tx_hash: + 'c0fe05d7bf71cd0f476ea18cdd4ecb26e1b9a33c911f4aaf143b2b18bc3b5f4f', + tx_pos: 1, + value: 546, + }, + { + height: 718091, + tx_hash: + '905cc5662cad77df56c3770863634ce498dde9d4772dc494d33b7ce3f36fa66c', + tx_pos: 2, + value: 546, + }, + { + height: 718280, + tx_hash: + 'f31f4ad7bf035cfb587a07a12ec60937cb8cbeafa7e4d7ed4f3276fea26fcfec', + tx_pos: 1, + value: 546, + }, + { + height: 718790, + tx_hash: + '67faa4753da2940d053f32edcda2c052a16c683aeb73f10cfde5c18266c14fe2', + tx_pos: 2, + value: 546, + }, + { + height: 720056, + tx_hash: + '9c6363fb537d529f512a12d292ea9682fe7159e6bf5ebfec5b7067b401d2dba4', + tx_pos: 1, + value: 546, + }, + { + height: 720070, + tx_hash: + '4eed87ba70864d9daa46d201c47db4513f77e5d4cc01256ab4dcc6dae9dfa055', + tx_pos: 1, + value: 546, + }, + { + height: 720070, + tx_hash: + '7975514a3185cbb70900e9767e5fcc91c86913cb1d2ad9a28474253875271e33', + tx_pos: 1, + value: 546, + }, + { + height: 720070, + tx_hash: + 'e10ae7a1bc78561ed367d59f150aebc13ef2054ba62f1a0db08fc7612d5ed58b', + tx_pos: 1, + value: 546, + }, + { + height: 720070, + tx_hash: + 'fb71c88bd5369cb8278f49ac672a9721833c36fc69143848b46ae15860339ea6', + tx_pos: 1, + value: 546, + }, + { + height: 720078, + tx_hash: + 'c3c6c6fb1619d001c29f17a701d042bc6b983e71113822aeeb66ca434fd9fa6c', + tx_pos: 1, + value: 546, + }, + { + height: 720951, + tx_hash: + 'fb50eac73a4fd5e2a701e0dbf4e575cea9c083e061b1db722e057164c7317e5b', + tx_pos: 2, + value: 546, + }, + { + height: 721083, + tx_hash: + 'dfb3dbf90fd87f6d66465ff05a61ddf1e1ca30900fadfe9cd4b73468649935ed', + tx_pos: 2, + value: 546, + }, + { + height: 724822, + tx_hash: + 'ed0dab39d5e976e433a705785726901dc83daa7d579412c18ee997341de010d3', + tx_pos: 1, + value: 546, + }, + { + height: 725143, + tx_hash: + 'e99296764134d6ea9ba7521490563762cfaf1541854ba9babc26c0df8665ac32', + tx_pos: 1, + value: 546, + }, + { + height: 725871, + tx_hash: + '82a3fe0b03ab07a564351443634da1b1ed3960e4771c59b6f8abbf7ef4b3258d', + tx_pos: 1, + value: 546, + }, + { + height: 725882, + tx_hash: + '1db1bef70013d178d7912731435029f9c8588f1d0089944c53eccffd255b5efc', + tx_pos: 2, + value: 546, + }, + { + height: 726001, + tx_hash: + '3c89d42ff868c74546ba819aaf4e5c5d5e5c63437d91c9c1cf5406ccbec3d952', + tx_pos: 2, + value: 546, + }, + { + height: 726008, + tx_hash: + '85e9379d5b9b371aa7f9464376290fbc6a40083ec14883460b649898f6d7c60b', + tx_pos: 0, + value: 10000, + }, + { + height: 726008, + tx_hash: + '85e9379d5b9b371aa7f9464376290fbc6a40083ec14883460b649898f6d7c60b', + tx_pos: 1, + value: 20000, + }, + { + height: 726008, + tx_hash: + '85e9379d5b9b371aa7f9464376290fbc6a40083ec14883460b649898f6d7c60b', + tx_pos: 2, + value: 30000, + }, + { + height: 726008, + tx_hash: + '85e9379d5b9b371aa7f9464376290fbc6a40083ec14883460b649898f6d7c60b', + tx_pos: 3, + value: 40000, + }, + { + height: 726008, + tx_hash: + '85e9379d5b9b371aa7f9464376290fbc6a40083ec14883460b649898f6d7c60b', + tx_pos: 4, + value: 50000, + }, + { + height: 726009, + tx_hash: + '52d2fd9d10debecbed6f8c3554517dada688c83197c4e57ad74556f0317c84b4', + tx_pos: 1, + value: 546, + }, + { + height: 726009, + tx_hash: + '9a0ba92af0aaaf16ec6a8bf0fc12d919078cd4c3f556a27dc792689803337ef9', + tx_pos: 1, + value: 95202647, + }, + { + height: 726009, + tx_hash: + 'b7bc037936eaac55cb2f377bbf564a06e86c419875f4ab2879f452e598aa999b', + tx_pos: 1, + value: 50148, + }, + { + height: 726009, + tx_hash: + 'd2e7d88785948ea46d1162401abf6e26b42b886df5c7fe5a64fe14ed292ebcdd', + tx_pos: 1, + value: 5146, + }, + ], + address: 'bitcoincash:qz2708636snqhsxu8wnlka78h6fdp77ar5ulhz04hr', + }, +]; +export const currentUtxosAfterEtokenSendTx = [ + { + utxos: [], + address: 'bitcoincash:qq0mw6nah9huwaxt45qw3fegjpszkjlrqsvttwy36p', + }, + { + utxos: [], + address: 'bitcoincash:qz5lf9pxde9neq3hzte8mmwts03sktl9nuz6m3dynu', + }, + { + utxos: [ + { + height: 680782, + tx_hash: + '525457276f1b6984170c9b35a8312d4988fce495723eabadd2afcdb3b872b2f1', + tx_pos: 1, + value: 546, + }, + { + height: 680784, + tx_hash: + '28f061fee068d3b9cb578141bac3d4d9ec4eccebec680464bf0aafaac414811f', + tx_pos: 1, + value: 546, + }, + { + height: 680784, + tx_hash: + '5fa3ffccea55c968beb7d214c563c92336ce2bbccbb714ba819848a7f7060bdb', + tx_pos: 1, + value: 546, + }, + { + height: 680784, + tx_hash: + 'daa98a872b7d88fefd2257b006db001ef82a601f3943b92e0c753076598a7b75', + tx_pos: 1, + value: 546, + }, + { + height: 681190, + tx_hash: + 'e9dca9aa954131a0004325fff11dfddcd6e5843c468116cf4d38cb264032cdc0', + tx_pos: 2, + value: 546, + }, + { + height: 681191, + tx_hash: + 'b35c502f388cdfbdd6841b7a73e973149b3c8deca76295a3e4665939e0562796', + tx_pos: 2, + value: 546, + }, + { + height: 685181, + tx_hash: + '7987f68aa70d29ac0e0ac31d74354a8b1cd515c9893f6a5cdc7a3bf505e08b05', + tx_pos: 1, + value: 546, + }, + { + height: 686546, + tx_hash: + 'bd84598096c113cd2110bc1748dd0613a933e2ddc440654c12ca4db4659933ed', + tx_pos: 1, + value: 546, + }, + { + height: 687240, + tx_hash: + 'cd9e5bc5fc041e46e8ce01ddb232c54fe48f1fb4a7288f10fdd03a6c2af875e1', + tx_pos: 2, + value: 546, + }, + { + height: 688194, + tx_hash: + '3de671a7107d3803d78f7f4a4e5c794d0903a8d28d16076445c084943c1e2db8', + tx_pos: 1, + value: 546, + }, + { + height: 688449, + tx_hash: + 'ab5079e9d24c33b31893cb98d409d24acdc396b5ab751e4c428d2463e991030c', + tx_pos: 2, + value: 546, + }, + { + height: 692599, + tx_hash: + '0158981b89b75bd923d511aaaaccd94b8d1d86babeeb69c29e3caf71e33bcc11', + tx_pos: 1, + value: 546, + }, + { + height: 692599, + tx_hash: + '1ef9ad7d3e01fd9d83983eac92eefb4900b343225a80c29bff025deff9aab57c', + tx_pos: 1, + value: 546, + }, + { + height: 693606, + tx_hash: + '9989f6f4941d7cf3206b327d957b022b41bf7e449a11fd5dd5cf1e9bc93f1ecf', + tx_pos: 2, + value: 546, + }, + { + height: 699216, + tx_hash: + '6f4e602620f5df257df8655f5834d5cfbbb73f62601c69afa96198f8ab4c2680', + tx_pos: 2, + value: 546, + }, + { + height: 699359, + tx_hash: + 'b99cb29050779d4f185c3c31c22e664436966314c8b260075b38bbb453180603', + tx_pos: 2, + value: 546, + }, + { + height: 700185, + tx_hash: + '71e458d9fd68a72fd5b13e2c758c6ba246495fa2933764876221450c096938b8', + tx_pos: 2, + value: 546, + }, + { + height: 700469, + tx_hash: + '41b9da9a5719b7bf61a02a598a37ee918a4da01e6ff5b1fb5366221ee93fd498', + tx_pos: 2, + value: 546, + }, + { + height: 700469, + tx_hash: + '6e24e89b6d5284138c69777527760500b99614631bca7f2a5c38f4648dae9524', + tx_pos: 1, + value: 546, + }, + { + height: 700469, + tx_hash: + 'bab327965a4fd423a383859b021ea2971987ceaa6fa3bc3994c3a3266a237db5', + tx_pos: 2, + value: 546, + }, + { + height: 700572, + tx_hash: + '431f527f657b399d8753fb63aee6c806ca0f8907d93606c46b36a33dcb5cb5b9', + tx_pos: 2, + value: 546, + }, + { + height: 700677, + tx_hash: + 'da9460ce4b1c92b4f6ef4e4a6bc2d05539f49d02b17681389d9ce22b8dca50f0', + tx_pos: 1, + value: 546, + }, + { + height: 700915, + tx_hash: + 'ef80e1ceeada69a9639c320c1fba47ea4417cd3aad1be1635c3472ce28aaef33', + tx_pos: 2, + value: 546, + }, + { + height: 701079, + tx_hash: + '0d5408adeefc0d9468d957a0a2bca1b63c371e68e61b3fd9c30de60058471935', + tx_pos: 1, + value: 546, + }, + { + height: 701079, + tx_hash: + '6397497c053e5c641ae624d4af80e8aa931a0e7b018f17a9543afed9b705cf29', + tx_pos: 1, + value: 546, + }, + { + height: 701079, + tx_hash: + 'c665bfd2353940648b018a3126ddbc7ac309729c7ca4598ebd7941930fd80b60', + tx_pos: 1, + value: 546, + }, + { + height: 701079, + tx_hash: + 'ebf864950d862ebb53e121350d15c8b34b2374eb22afffb98fcb655b38441d59', + tx_pos: 1, + value: 546, + }, + { + height: 701079, + tx_hash: + 'fe10460f822163c33515f3a853c1470d68223c9c0e8f8cbc6c954ca537129f30', + tx_pos: 1, + value: 546, + }, + { + height: 701189, + tx_hash: + '3656afe8682997be4cab4275e4bbec3f81c8aa264cec206a7215d449ee6b9af4', + tx_pos: 1, + value: 546, + }, + { + height: 701189, + tx_hash: + '87656bf2c2f2d46d16ba6b41b4ff488a3eff1e852c64bc921322f580e375f3cb', + tx_pos: 1, + value: 546, + }, + { + height: 701191, + tx_hash: + 'c212e45f21418fa7fd5bbf2941892353c1d6ddb9d6d16ff12fba3f7919c37b43', + tx_pos: 1, + value: 546, + }, + { + height: 701194, + tx_hash: + 'ff61be814b18f60a640169c5d70b42ce29bd9caf2f5e5592655e924760634c1e', + tx_pos: 1, + value: 546, + }, + { + height: 701208, + tx_hash: + '0e9179929b71d8a94ce9de75434d9e0901eacf3b2b882fa02a56eab450d0bd0b', + tx_pos: 1, + value: 546, + }, + { + height: 701211, + tx_hash: + '4ad31e5ab9cfcead7d8b48b81a542044e44e63124eb96d6463fe4bbe5b77e9ad', + tx_pos: 1, + value: 546, + }, + { + height: 701211, + tx_hash: + '72d4827a9a0b9adac9430ba799cb049af14fd79df11569b4e1a4741ac114b84d', + tx_pos: 1, + value: 546, + }, + { + height: 701221, + tx_hash: + '42d3e2d97604f09c002df701f964adacacd28bc328acc0066a2563d63f522681', + tx_pos: 1, + value: 546, + }, + { + height: 701223, + tx_hash: + '890bd4d72e75c4123b73dc81b9f4f89716fabe456a9047f9a5a5ef4a5162d218', + tx_pos: 2, + value: 546, + }, + { + height: 709251, + tx_hash: + '9e8483407944d9b75c331ebd6178b0cabc3e8c3b5bb0492b7b2256c8740f655a', + tx_pos: 1, + value: 546, + }, + { + height: 709259, + tx_hash: + '4f4fc78f7a008fc109789722d89fe95fe75ca1f15af625f24ae4ec74d420552e', + tx_pos: 1, + value: 546, + }, + { + height: 709668, + tx_hash: + 'da371839612b153543d0cffb09e0220dca7c7acfebda660785807b269bd0341c', + tx_pos: 1, + value: 546, + }, + { + height: 710065, + tx_hash: + '117939de3822734df69fb5cc27a6429860ee2f7a78917603da8b8aebba2a9150', + tx_pos: 1, + value: 546, + }, + { + height: 711227, + tx_hash: + 'e26db37d5c64b265514cd5cbb9d5194a7f2967b5974d167236d46be4954e435c', + tx_pos: 2, + value: 546, + }, + { + height: 715111, + tx_hash: + 'b39fdb53e21d67fa5fd3a11122f1452f15884047f2b80e8efe633c3b520b7a39', + tx_pos: 1, + value: 546, + }, + { + height: 715815, + tx_hash: + '3515f4a9851ad44124e0ddf6149344deb27a97720fc7e5254a9d2c86da7415a9', + tx_pos: 1, + value: 546, + }, + { + height: 715815, + tx_hash: + '6fb6122742cac8fd1df2d68997fdfa4c077bc22d9ef4a336bfb63d24225f9060', + tx_pos: 1, + value: 546, + }, + { + height: 715816, + tx_hash: + '2936188a41f22a3e0a47d13296147fb3f9ddd2f939fe6382904d21a610e8e49c', + tx_pos: 1, + value: 546, + }, + { + height: 717055, + tx_hash: + '18c0360f0db5399223cbed48f55c4cee9d9914c8a4a7dedcf9172a36201e9896', + tx_pos: 1, + value: 546, + }, + { + height: 717653, + tx_hash: + '3adbf501e21c711d20118e003711168eb39f560c01f4c6d6736fa3f3fceaa577', + tx_pos: 1, + value: 546, + }, + { + height: 717824, + tx_hash: + 'c0fe05d7bf71cd0f476ea18cdd4ecb26e1b9a33c911f4aaf143b2b18bc3b5f4f', + tx_pos: 1, + value: 546, + }, + { + height: 718091, + tx_hash: + '905cc5662cad77df56c3770863634ce498dde9d4772dc494d33b7ce3f36fa66c', + tx_pos: 2, + value: 546, + }, + { + height: 718280, + tx_hash: + 'f31f4ad7bf035cfb587a07a12ec60937cb8cbeafa7e4d7ed4f3276fea26fcfec', + tx_pos: 1, + value: 546, + }, + { + height: 718790, + tx_hash: + '67faa4753da2940d053f32edcda2c052a16c683aeb73f10cfde5c18266c14fe2', + tx_pos: 2, + value: 546, + }, + { + height: 720056, + tx_hash: + '9c6363fb537d529f512a12d292ea9682fe7159e6bf5ebfec5b7067b401d2dba4', + tx_pos: 1, + value: 546, + }, + { + height: 720070, + tx_hash: + '4eed87ba70864d9daa46d201c47db4513f77e5d4cc01256ab4dcc6dae9dfa055', + tx_pos: 1, + value: 546, + }, + { + height: 720070, + tx_hash: + '7975514a3185cbb70900e9767e5fcc91c86913cb1d2ad9a28474253875271e33', + tx_pos: 1, + value: 546, + }, + { + height: 720070, + tx_hash: + 'e10ae7a1bc78561ed367d59f150aebc13ef2054ba62f1a0db08fc7612d5ed58b', + tx_pos: 1, + value: 546, + }, + { + height: 720070, + tx_hash: + 'fb71c88bd5369cb8278f49ac672a9721833c36fc69143848b46ae15860339ea6', + tx_pos: 1, + value: 546, + }, + { + height: 720078, + tx_hash: + 'c3c6c6fb1619d001c29f17a701d042bc6b983e71113822aeeb66ca434fd9fa6c', + tx_pos: 1, + value: 546, + }, + { + height: 720951, + tx_hash: + 'fb50eac73a4fd5e2a701e0dbf4e575cea9c083e061b1db722e057164c7317e5b', + tx_pos: 2, + value: 546, + }, + { + height: 721083, + tx_hash: + 'dfb3dbf90fd87f6d66465ff05a61ddf1e1ca30900fadfe9cd4b73468649935ed', + tx_pos: 2, + value: 546, + }, + { + height: 724822, + tx_hash: + 'ed0dab39d5e976e433a705785726901dc83daa7d579412c18ee997341de010d3', + tx_pos: 1, + value: 546, + }, + { + height: 725143, + tx_hash: + 'e99296764134d6ea9ba7521490563762cfaf1541854ba9babc26c0df8665ac32', + tx_pos: 1, + value: 546, + }, + { + height: 725871, + tx_hash: + '82a3fe0b03ab07a564351443634da1b1ed3960e4771c59b6f8abbf7ef4b3258d', + tx_pos: 1, + value: 546, + }, + { + height: 725882, + tx_hash: + '1db1bef70013d178d7912731435029f9c8588f1d0089944c53eccffd255b5efc', + tx_pos: 2, + value: 546, + }, + { + height: 726001, + tx_hash: + '3c89d42ff868c74546ba819aaf4e5c5d5e5c63437d91c9c1cf5406ccbec3d952', + tx_pos: 2, + value: 546, + }, + { + height: 726008, + tx_hash: + '85e9379d5b9b371aa7f9464376290fbc6a40083ec14883460b649898f6d7c60b', + tx_pos: 0, + value: 10000, + }, + { + height: 726008, + tx_hash: + '85e9379d5b9b371aa7f9464376290fbc6a40083ec14883460b649898f6d7c60b', + tx_pos: 1, + value: 20000, + }, + { + height: 726008, + tx_hash: + '85e9379d5b9b371aa7f9464376290fbc6a40083ec14883460b649898f6d7c60b', + tx_pos: 2, + value: 30000, + }, + { + height: 726008, + tx_hash: + '85e9379d5b9b371aa7f9464376290fbc6a40083ec14883460b649898f6d7c60b', + tx_pos: 3, + value: 40000, + }, + { + height: 726008, + tx_hash: + '85e9379d5b9b371aa7f9464376290fbc6a40083ec14883460b649898f6d7c60b', + tx_pos: 4, + value: 50000, + }, + { + height: 726009, + tx_hash: + '52d2fd9d10debecbed6f8c3554517dada688c83197c4e57ad74556f0317c84b4', + tx_pos: 1, + value: 546, + }, + { + height: 726009, + tx_hash: + 'b7bc037936eaac55cb2f377bbf564a06e86c419875f4ab2879f452e598aa999b', + tx_pos: 1, + value: 50148, + }, + { + height: 726009, + tx_hash: + 'd2e7d88785948ea46d1162401abf6e26b42b886df5c7fe5a64fe14ed292ebcdd', + tx_pos: 1, + value: 5146, + }, + { + height: 0, + tx_hash: + 'b8982cf5531afcba125a9e17550d42a01045c3aa5ee70a485f8fbcde3dae191d', + tx_pos: 2, + value: 546, + }, + { + height: 0, + tx_hash: + 'b8982cf5531afcba125a9e17550d42a01045c3aa5ee70a485f8fbcde3dae191d', + tx_pos: 3, + value: 95200829, + }, + ], + address: 'bitcoincash:qz2708636snqhsxu8wnlka78h6fdp77ar5ulhz04hr', + }, +]; + +export const previousUtxosBeforeSendAllTx = [ + { + utxos: [], + address: 'bitcoincash:qq3q2vr3qkawa3m2lhg5wurzgpxjqvek6crvxgpsrf', + }, + { + utxos: [], + address: 'bitcoincash:qzv8arsknrmda2n4xg02rvtp2yzh072c6s5ms7jhfq', + }, + { + utxos: [ + { + height: 726153, + tx_hash: + 'a40216751b8c9c5ade1dd2962afcdc657e4e2c92416fb0b2dd956bce75425afb', + tx_pos: 0, + value: 4206900, + }, + ], + address: 'bitcoincash:qq3af2r4n5ndek40cq3lq8y5qjq8v0aq4sc0faj07q', + }, +]; +export const currentUtxosAfterSendAllTx = [ + { + utxos: [], + address: 'bitcoincash:qq3q2vr3qkawa3m2lhg5wurzgpxjqvek6crvxgpsrf', + }, + { + utxos: [], + address: 'bitcoincash:qzv8arsknrmda2n4xg02rvtp2yzh072c6s5ms7jhfq', + }, + { + utxos: [], + address: 'bitcoincash:qq3af2r4n5ndek40cq3lq8y5qjq8v0aq4sc0faj07q', + }, +]; +export const utxosConsumedBySendAllTx = [ + { + address: 'bitcoincash:qq3q2vr3qkawa3m2lhg5wurzgpxjqvek6crvxgpsrf', + utxos: [], + }, + { + address: 'bitcoincash:qzv8arsknrmda2n4xg02rvtp2yzh072c6s5ms7jhfq', + utxos: [], + }, + { + address: 'bitcoincash:qq3af2r4n5ndek40cq3lq8y5qjq8v0aq4sc0faj07q', + utxos: [ + { + height: 726153, + tx_hash: + 'a40216751b8c9c5ade1dd2962afcdc657e4e2c92416fb0b2dd956bce75425afb', + tx_pos: 0, + value: 4206900, + }, + ], + }, +]; diff --git a/web/cashtab/src/utils/__tests__/cashMethods.test.js b/web/cashtab/src/utils/__tests__/cashMethods.test.js --- a/web/cashtab/src/utils/__tests__/cashMethods.test.js +++ b/web/cashtab/src/utils/__tests__/cashMethods.test.js @@ -14,6 +14,11 @@ toLegacyToken, toLegacyCashArray, parseOpReturn, + isExcludedUtxo, + whichUtxosWereAdded, + whichUtxosWereConsumed, + removeConsumedUtxos, + addNewHydratedUtxos, } from '@utils/cashMethods'; import { @@ -77,6 +82,50 @@ mockParsedETokenOutputArray, } from '../__mocks__/mockOpReturnParsedArray'; +import { + excludedUtxoAlpha, + excludedUtxoBeta, + includedUtxoAlpha, + includedUtxoBeta, + previousUtxosTemplate, + currentUtxosAfterSingleXecReceiveTxTemplate, + utxosAddedBySingleXecReceiveTxTemplate, + utxosAddedByMultiXecReceiveTxTemplate, + currentUtxosAfterMultiXecReceiveTxTemplate, + utxosAddedByEtokenReceiveTxTemplate, + currentUtxosAfterEtokenReceiveTxTemplate, + utxosAddedBySingleXecSendTxTemplate, + utxosConsumedBySingleXecSendTxTemplate, + currentUtxosAfterSingleXecSendTxTemplate, + utxosAddedByEtokenSendTxTemplate, + utxosConsumedByEtokenSendTxTemplate, + currentUtxosAfterEtokenSendTxTemplate, + previousUtxosBeforeSendAllTxTemplate, + currentUtxosAfterSendAllTxTemplate, + utxosConsumedBySendAllTxTemplate, + previousUtxosBeforeSendAllTx, + currentUtxosAfterSendAllTx, + utxosConsumedBySendAllTx, + previousUtxosObjUtxoArray, + utxosAddedBySingleXecReceiveTx, + previousUtxosBeforeSingleXecReceiveTx, + currentUtxosAfterSingleXecReceiveTx, + utxosAddedByMultiXecReceiveTx, + previousUtxosBeforeMultiXecReceiveTx, + currentUtxosAfterMultiXecReceiveTx, + utxosAddedByEtokenReceiveTx, + previousUtxosBeforeEtokenReceiveTx, + currentUtxosAfterEtokenReceiveTx, + utxosAddedBySingleXecSendTx, + utxosConsumedBySingleXecSendTx, + previousUtxosBeforeSingleXecSendTx, + currentUtxosAfterSingleXecSendTx, + utxosAddedByEtokenSendTx, + utxosConsumedByEtokenSendTx, + previousUtxosBeforeEtokenSendTx, + currentUtxosAfterEtokenSendTx, +} from '../__mocks__/incrementalUtxoMocks'; + describe('Correctly executes cash utility functions', () => { it(`Correctly converts smallest base unit to smallest decimal for cashDecimals = 2`, () => { expect(fromSmallestDenomination(1, 2)).toBe(0.01); @@ -345,4 +394,269 @@ const result = parseOpReturn(eTokenInputHex); expect(result).toStrictEqual(mockParsedETokenOutputArray); }); + test('isExcludedUtxo returns true for a utxo with different tx_pos and same txid as an existing utxo in the set', async () => { + expect( + isExcludedUtxo(excludedUtxoAlpha, previousUtxosObjUtxoArray), + ).toBe(true); + }); + test('isExcludedUtxo returns true for a utxo with different value and same txid as an existing utxo in the set', async () => { + expect( + isExcludedUtxo(excludedUtxoBeta, previousUtxosObjUtxoArray), + ).toBe(true); + }); + test('isExcludedUtxo returns false for a utxo with different tx_pos and same txid', async () => { + expect( + isExcludedUtxo(includedUtxoAlpha, previousUtxosObjUtxoArray), + ).toBe(false); + }); + test('isExcludedUtxo returns false for a utxo with different value and same txid', async () => { + expect( + isExcludedUtxo(includedUtxoBeta, previousUtxosObjUtxoArray), + ).toBe(false); + }); + test('whichUtxosWereAdded correctly identifies a single added utxo after a received XEC tx [template]', async () => { + expect( + whichUtxosWereAdded( + previousUtxosTemplate, + currentUtxosAfterSingleXecReceiveTxTemplate, + ), + ).toStrictEqual(utxosAddedBySingleXecReceiveTxTemplate); + }); + test('whichUtxosWereConsumed correctly identifies no utxos consumed after a received XEC tx [template]', async () => { + expect( + whichUtxosWereConsumed( + previousUtxosTemplate, + currentUtxosAfterSingleXecReceiveTxTemplate, + ), + ).toStrictEqual(false); + }); + test('whichUtxosWereAdded correctly identifies a single added utxo after a received XEC tx', async () => { + expect( + whichUtxosWereAdded( + previousUtxosBeforeSingleXecReceiveTx, + currentUtxosAfterSingleXecReceiveTx, + ), + ).toStrictEqual(utxosAddedBySingleXecReceiveTx); + }); + test('whichUtxosWereConsumed correctly identifies no utxos consumed a received XEC tx', async () => { + expect( + whichUtxosWereConsumed( + previousUtxosBeforeSingleXecReceiveTx, + currentUtxosAfterSingleXecReceiveTx, + ), + ).toStrictEqual(false); + }); + test('whichUtxosWereAdded correctly identifies multiple added utxos with the same txid [template]', async () => { + expect( + whichUtxosWereAdded( + previousUtxosTemplate, + currentUtxosAfterMultiXecReceiveTxTemplate, + ), + ).toStrictEqual(utxosAddedByMultiXecReceiveTxTemplate); + }); + test('whichUtxosWereConsumed correctly identifies no consumed utxos after receiving an XEC multi-send tx [template]', async () => { + expect( + whichUtxosWereConsumed( + previousUtxosTemplate, + currentUtxosAfterMultiXecReceiveTxTemplate, + ), + ).toStrictEqual(false); + }); + test('whichUtxosWereAdded correctly identifies multiple added utxos with the same txid', async () => { + expect( + whichUtxosWereAdded( + previousUtxosBeforeMultiXecReceiveTx, + currentUtxosAfterMultiXecReceiveTx, + ), + ).toStrictEqual(utxosAddedByMultiXecReceiveTx); + }); + test('whichUtxosWereConsumed correctly identifies no consumed utxos after receiving an XEC multi-send tx', async () => { + expect( + whichUtxosWereConsumed( + previousUtxosBeforeMultiXecReceiveTx, + currentUtxosAfterMultiXecReceiveTx, + ), + ).toStrictEqual(false); + }); + test('whichUtxosWereAdded correctly identifies an added utxos from received eToken tx [template]', async () => { + expect( + whichUtxosWereAdded( + previousUtxosTemplate, + currentUtxosAfterEtokenReceiveTxTemplate, + ), + ).toStrictEqual(utxosAddedByEtokenReceiveTxTemplate); + }); + test('whichUtxosWereAdded correctly identifies an added utxos from received eToken tx', async () => { + expect( + whichUtxosWereAdded( + previousUtxosBeforeEtokenReceiveTx, + currentUtxosAfterEtokenReceiveTx, + ), + ).toStrictEqual(utxosAddedByEtokenReceiveTx); + }); + test('whichUtxosWereConsumed correctly identifies consumed utxos from a single send XEC tx', async () => { + expect( + whichUtxosWereConsumed( + previousUtxosBeforeSingleXecSendTx, + currentUtxosAfterSingleXecSendTx, + ), + ).toStrictEqual(utxosConsumedBySingleXecSendTx); + }); + test('whichUtxosWereAdded correctly identifies no utxos were added in a send all XEC tx (no change) [template]', async () => { + expect( + whichUtxosWereAdded( + previousUtxosBeforeSendAllTxTemplate, + currentUtxosAfterSendAllTxTemplate, + ), + ).toStrictEqual(false); + }); + test('whichUtxosWereConsumed correctly identifies consumed utxos from a send all XEC tx [template]', async () => { + expect( + whichUtxosWereConsumed( + previousUtxosBeforeSendAllTxTemplate, + currentUtxosAfterSendAllTxTemplate, + ), + ).toStrictEqual(utxosConsumedBySendAllTxTemplate); + }); + test('whichUtxosWereAdded correctly identifies no utxos were added in a send all XEC tx (no change)', async () => { + expect( + whichUtxosWereAdded( + previousUtxosBeforeSendAllTx, + currentUtxosAfterSendAllTx, + ), + ).toStrictEqual(false); + }); + test('whichUtxosWereConsumed correctly identifies consumed utxos from a send all XEC tx', async () => { + expect( + whichUtxosWereConsumed( + previousUtxosBeforeSendAllTx, + currentUtxosAfterSendAllTx, + ), + ).toStrictEqual(utxosConsumedBySendAllTx); + }); + test('whichUtxosWereAdded correctly identifies an added utxo from a single send XEC tx', async () => { + expect( + whichUtxosWereAdded( + previousUtxosBeforeSingleXecSendTx, + currentUtxosAfterSingleXecSendTx, + ), + ).toStrictEqual(utxosAddedBySingleXecSendTx); + }); + test('whichUtxosWereConsumed correctly identifies consumed utxos from a single send XEC tx [template]', async () => { + expect( + whichUtxosWereConsumed( + previousUtxosTemplate, + currentUtxosAfterSingleXecSendTxTemplate, + ), + ).toStrictEqual(utxosConsumedBySingleXecSendTxTemplate); + }); + test('whichUtxosWereAdded correctly identifies an added utxo from a single send XEC tx [template]', async () => { + expect( + whichUtxosWereAdded( + previousUtxosTemplate, + currentUtxosAfterSingleXecSendTxTemplate, + ), + ).toStrictEqual(utxosAddedBySingleXecSendTxTemplate); + }); + test('whichUtxosWereAdded correctly identifies added change utxos from a send eToken tx [template]', async () => { + expect( + whichUtxosWereAdded( + previousUtxosTemplate, + currentUtxosAfterEtokenSendTxTemplate, + ), + ).toStrictEqual(utxosAddedByEtokenSendTxTemplate); + }); + test('whichUtxosWereConsumed correctly identifies consumed utxos from a send eToken tx [template]', async () => { + expect( + whichUtxosWereConsumed( + previousUtxosTemplate, + currentUtxosAfterEtokenSendTxTemplate, + ), + ).toStrictEqual(utxosConsumedByEtokenSendTxTemplate); + }); + test('whichUtxosWereAdded correctly identifies added change utxos from a send eToken tx', async () => { + expect( + whichUtxosWereAdded( + previousUtxosBeforeEtokenSendTx, + currentUtxosAfterEtokenSendTx, + ), + ).toStrictEqual(utxosAddedByEtokenSendTx); + }); + test('whichUtxosWereConsumed correctly identifies consumed utxos from a send eToken tx', async () => { + expect( + whichUtxosWereConsumed( + previousUtxosBeforeEtokenSendTx, + currentUtxosAfterEtokenSendTx, + ), + ).toStrictEqual(utxosConsumedByEtokenSendTx); + }); + + // TODO return false if no utxos added but one utxo is consumed + // TODO other unit tests + // TODO fix your "is this shit fucked up? function" , see notes below + + /* + test('isExcludedUtxo returns true for a utxo that does not exist in a set of other utxos', () => { + expect(isExcludedUtxo(excludedUtxoAlpha, previousUtxos)).toBe(true); + }); + isExcludedUtxo + + Required mocks + excludedUtxo + includedUtxo + previousUtxos + + 1) isExcludedUtxo returns true for a utxo that does not exist in a set of other utxos + 2) isExcludedUtxo returns false for a utxo that does exist in a set of utxos + 3) isExcludedUtxo returns true for a utxo that does not exist in a set of other utxos, even where other utxos with the same tx_hash do exist + + whichUtxosWereAdded + + test('whichUtxosWereAdded correctly identifies a single added utxo', async () => { + expect( + whichUtxosWereAdded(previousUtxos, currentUtxosAfterSingleXecReceiveTx), + ).toBe(utxosAddedBySingleXecReceiveTx); + }); + + Required mocks: + previousUtxos (exists) + currentUtxosAdded + currentUtxosEtokenSend + currentUtxosXecSend + currentUtxosXecMultiReceive + currentUtxosXecMultiSend + + 1) whichUtxosWereAdded correctly identifies a single added utxo + 2) whichUtxosWereAdded correctly identifies multiple added utxos + 3) whichUtxosWereAdded correctly identifies no utxos where added if one utxo is fully consumed + 4) whichUtxosWereAdded correctly identifies a change utxo as added + + whichUtxosWereConsumed + + Required mocks are the different results + Same tests as whichUtxosWereAdded but different results + + removeConsumedUtxos + + 1) Removes 1 utxo from hydratedUtxoDetails + 2) Removes multiple utxos from hydratedUtxoDetails + 3) Same as 1 but with reorganized hydratedUtxoDetails + 4) Same as 2 but with reorganized hydratedUtxoDetails + + addNewHydratedUtxos + + 1) Adds single new hydrated utxo to hydratedUtxoDetails + 2) Adds multiple new hydrated utxos to hydratedUtxoDetails + + areAllUtxosIncludedInIncrementallyHydratedUtxos + + 1) Verifies that hydratedUtxoDetails contains all utxos in the utxo set + NOTE TODO -- it also needs to verify that hydratedUtxoDetails contains NO OTHER UTXOS + You can cheat this bc if you meet the above condition and the total utxo count is the same, you are good + otherwise you are bad + + + + + */ }); diff --git a/web/cashtab/src/utils/cashMethods.js b/web/cashtab/src/utils/cashMethods.js --- a/web/cashtab/src/utils/cashMethods.js +++ b/web/cashtab/src/utils/cashMethods.js @@ -487,3 +487,390 @@ return false; }; +export const isExcludedUtxo = (utxo, utxoArray) => { + /* + utxo is a single utxo of model + { + height: 724992 + tx_hash: "8d4bdedb7c4443412e0c2f316a330863aef54d9ba73560ca60cca6408527b247" + tx_pos: 0 + value: 10200 + } + + utxoArray is an array of utxos + */ + let isExcludedUtxo = true; + const { tx_hash, tx_pos, value } = utxo; + for (let i = 0; i < utxoArray.length; i += 1) { + const thisUtxo = utxoArray[i]; + // NOTE + // You can't match height, as this changes from 0 to blockheight after confirmation + //const thisUtxoHeight = thisUtxo.height; + const thisUtxoTxid = thisUtxo.tx_hash; + const thisUtxoTxPos = thisUtxo.tx_pos; + const thisUtxoValue = thisUtxo.value; + // If you find a utxo such that each object key is identical + if ( + tx_hash === thisUtxoTxid && + tx_pos === thisUtxoTxPos && + value === thisUtxoValue + ) { + // Then this utxo is not excluded from the array + isExcludedUtxo = false; + } + } + + return isExcludedUtxo; +}; +export const whichUtxosWereAdded = (previousUtxos, currentUtxos) => { + let utxosAddedFlag = false; + const utxosAdded = []; + // Iterate over currentUtxos + // For each currentUtxo -- does it exist in previousUtxos? + // If no, it's added + + // Note that the inputs are arrays of arrays, model + /* + previousUtxos = [{address: 'string', utxos: []}, ...] + */ + + // Iterate over the currentUtxos array of {address: 'string', utxos: []} objects + for (let i = 0; i < currentUtxos.length; i += 1) { + // Take the first object + const thisCurrentUtxoObject = currentUtxos[i]; + const thisCurrentUtxoObjectAddress = thisCurrentUtxoObject.address; + const thisCurrentUtxoObjectUtxos = thisCurrentUtxoObject.utxos; + // Iterate over the previousUtxos array of {address: 'string', utxos: []} objects + for (let j = 0; j < previousUtxos.length; j += 1) { + const thisPreviousUtxoObject = previousUtxos[j]; + const thisPreviousUtxoObjectAddress = + thisPreviousUtxoObject.address; + // When you find the utxos object at the same address + if ( + thisCurrentUtxoObjectAddress === thisPreviousUtxoObjectAddress + ) { + // Create a utxosAddedObject with the address + const utxosAddedObject = { + address: thisCurrentUtxoObjectAddress, + utxos: [], + }; + utxosAdded.push(utxosAddedObject); + + // Grab the previousUtxoObject utxos array. thisCurrentUtxoObjectUtxos has changed compared to thisPreviousUtxoObjectUtxos + const thisPreviousUtxoObjectUtxos = + thisPreviousUtxoObject.utxos; + // To see if any utxos exist in thisCurrentUtxoObjectUtxos that do not exist in thisPreviousUtxoObjectUtxos + // iterate over thisPreviousUtxoObjectUtxos for each utxo in thisCurrentUtxoObjectUtxos + for (let k = 0; k < thisCurrentUtxoObjectUtxos.length; k += 1) { + const thisCurrentUtxo = thisCurrentUtxoObjectUtxos[k]; + + if ( + isExcludedUtxo( + thisCurrentUtxo, + thisPreviousUtxoObjectUtxos, + ) + ) { + // If thisCurrentUtxo was not in the corresponding previous utxos + // Then it was added + + //utxosAdded.push(utxosAddedObject); + utxosAdded[j].utxos.push(thisCurrentUtxo); + utxosAddedFlag = true; + } + } + } + } + } + // If utxos were added, return them + if (utxosAddedFlag) { + return utxosAdded; + } + // Else return false + return utxosAddedFlag; +}; + +export const whichUtxosWereConsumed = (previousUtxos, currentUtxos) => { + let utxosConsumedFlag = false; + const utxosConsumed = []; + // Iterate over previousUtxos + // For each previousUtxo -- does it exist in currentUtxos? + // If no, it's consumed + + // Note that the inputs are arrays of arrays, model + /* + previousUtxos = [{address: 'string', utxos: []}, ...] + */ + + // Iterate over the previousUtxos array of {address: 'string', utxos: []} objects + for (let i = 0; i < previousUtxos.length; i += 1) { + // Take the first object + const thisPreviousUtxoObject = previousUtxos[i]; + const thisPreviousUtxoObjectAddress = thisPreviousUtxoObject.address; + const thisPreviousUtxoObjectUtxos = thisPreviousUtxoObject.utxos; + // Iterate over the currentUtxos array of {address: 'string', utxos: []} objects + for (let j = 0; j < currentUtxos.length; j += 1) { + const thisCurrentUtxoObject = currentUtxos[j]; + const thisCurrentUtxoObjectAddress = thisCurrentUtxoObject.address; + // When you find the utxos object at the same address + if ( + thisCurrentUtxoObjectAddress === thisPreviousUtxoObjectAddress + ) { + // Create a utxosConsumedObject with the address + const utxosConsumedObject = { + address: thisCurrentUtxoObjectAddress, + utxos: [], + }; + utxosConsumed.push(utxosConsumedObject); + // Grab the currentUtxoObject utxos array. thisCurrentUtxoObjectUtxos has changed compared to thisPreviousUtxoObjectUtxos + const thisCurrentUtxoObjectUtxos = thisCurrentUtxoObject.utxos; + // To see if any utxos exist in thisPreviousUtxoObjectUtxos that do not exist in thisCurrentUtxoObjectUtxos + // iterate over thisCurrentUtxoObjectUtxos for each utxo in thisPreviousUtxoObjectUtxos + for ( + let k = 0; + k < thisPreviousUtxoObjectUtxos.length; + k += 1 + ) { + const thisPreviousUtxo = thisPreviousUtxoObjectUtxos[k]; + // If thisPreviousUtxo was not in the corresponding current utxos + + if ( + isExcludedUtxo( + thisPreviousUtxo, + thisCurrentUtxoObjectUtxos, + ) + ) { + // Then it was consumed + utxosConsumed[j].utxos.push(thisPreviousUtxo); + utxosConsumedFlag = true; + } + } + } + } + } + // If utxos were consumed, return them + if (utxosConsumedFlag) { + return utxosConsumed; + } + // Else return false + return utxosConsumedFlag; +}; +export const removeConsumedUtxos = (consumedUtxos, hydratedUtxoDetails) => { + let hydratedUtxoDetailsWithConsumedUtxosRemoved = hydratedUtxoDetails; + const slpUtxosArray = hydratedUtxoDetails.slpUtxos; + // Iterate over consumedUtxos + // Every utxo in consumedUtxos must be removed from hydratedUtxoDetails + for (let i = 0; i < consumedUtxos.length; i += 1) { + const thisConsumedUtxoObject = consumedUtxos[i]; // {address: 'string', utxos: [{},{},...{}]} + const thisConsumedUtxoObjectAddr = thisConsumedUtxoObject.address; + const thisConsumedUtxoObjectUtxoArray = thisConsumedUtxoObject.utxos; + for (let j = 0; j < thisConsumedUtxoObjectUtxoArray.length; j += 1) { + const thisConsumedUtxo = thisConsumedUtxoObjectUtxoArray[j]; + // Iterate through slpUtxosArray to find thisConsumedUtxo + slpUtxosArrayLoop: for ( + let k = 0; + k < slpUtxosArray.length; + k += 1 + ) { + const thisSlpUtxosArrayUtxoObject = slpUtxosArray[k]; // {address: 'string', utxos: [{},{},...{}]} + const thisSlpUtxosArrayUtxoObjectAddr = + thisSlpUtxosArrayUtxoObject.address; + // If this address matches the address of the consumed utxo, check for a consumedUtxo match + // Note, slpUtxos may have many utxo objects with the same address, need to check them all until you find and remove this consumed utxo + if ( + thisConsumedUtxoObjectAddr === + thisSlpUtxosArrayUtxoObjectAddr + ) { + const thisSlpUtxosArrayUtxoObjectUtxoArray = + thisSlpUtxosArrayUtxoObject.utxos; + + // Iterate to find it and remove it + for ( + let m = 0; + m < thisSlpUtxosArrayUtxoObjectUtxoArray.length; + m += 1 + ) { + const thisHydratedUtxo = + thisSlpUtxosArrayUtxoObjectUtxoArray[m]; + if ( + thisConsumedUtxo.tx_hash === + thisHydratedUtxo.tx_hash && + thisConsumedUtxo.tx_pos === + thisHydratedUtxo.tx_pos && + thisConsumedUtxo.value === thisHydratedUtxo.value + ) { + // remove it + hydratedUtxoDetailsWithConsumedUtxosRemoved.slpUtxos[ + k + ].utxos.splice(m, 1); + // go to the next consumedUtxo + break slpUtxosArrayLoop; + } + } + } + } + } + } + return hydratedUtxoDetailsWithConsumedUtxosRemoved; +}; + +export const addNewHydratedUtxos = ( + addedHydratedUtxos, + hydratedUtxoDetails, +) => { + const theseAdditionalHydratedUtxos = addedHydratedUtxos.slpUtxos; + for (let i = 0; i < theseAdditionalHydratedUtxos.length; i += 1) { + const thisHydratedUtxoObj = theseAdditionalHydratedUtxos[i]; + hydratedUtxoDetails.slpUtxos.push(thisHydratedUtxoObj); + } + return hydratedUtxoDetails; + // Add hydrateUtxos(addedUtxos) to hydratedUtxoDetails + /* + e.g. add this + { + "slpUtxos": + [ + { + "utxos": [ + { + "height": 725886, + "tx_hash": "29985c01444bf80ade764e5d40d7ec2c12317e03301243170139c75f20c51f78", + "tx_pos": 0, + "value": 3300, + "txid": "29985c01444bf80ade764e5d40d7ec2c12317e03301243170139c75f20c51f78", + "vout": 0, + "isValid": false + } + ], + "address": "bitcoincash:qz2708636snqhsxu8wnlka78h6fdp77ar5ulhz04hr" + } + ] + } + +to this + +{ + "slpUtxos": + [ + { + "utxos": [ + { + "height": 725886, + "tx_hash": "29985c01444bf80ade764e5d40d7ec2c12317e03301243170139c75f20c51f78", + "tx_pos": 0, + "value": 3300, + "txid": "29985c01444bf80ade764e5d40d7ec2c12317e03301243170139c75f20c51f78", + "vout": 0, + "isValid": false + } + ... up to 20 + ], + "address": "bitcoincash:qz2708636snqhsxu8wnlka78h6fdp77ar5ulhz04hr" + }, + { + "utxos": [ + { + "height": 725886, + "tx_hash": "29985c01444bf80ade764e5d40d7ec2c12317e03301243170139c75f20c51f78", + "tx_pos": 0, + "value": 3300, + "txid": "29985c01444bf80ade764e5d40d7ec2c12317e03301243170139c75f20c51f78", + "vout": 0, + "isValid": false + } + ... up to 20 + ], + "address": "bitcoincash:qz2708636snqhsxu8wnlka78h6fdp77ar5ulhz04hr" + } + , + ... a bunch of these in batches of 20 + ] + } + */ +}; + +export const getUtxoCount = utxos => { + // return how many utxos + /* + Both utxos and hydratedUtxoDetails.slpUtxos are build like so + [ + { + address: 'string', + utxos: [{}, {}, {}...{}] + }, + { + address: 'string', + utxos: [{}, {}, {}...{}] + }, + { + address: 'string', + utxos: [{}, {}, {}...{}] + }, + ] + + We want a function that quickly determines how many utxos are here + */ + let utxoCount = 0; + for (let i = 0; i < utxos.length; i += 1) { + const thisUtxoArrLength = utxos[i].utxos.length; + utxoCount += thisUtxoArrLength; + } + return utxoCount; +}; + +export const areAllUtxosIncludedInIncrementallyHydratedUtxos = ( + utxos, + incrementallyHydratedUtxos, +) => { + let incrementallyHydratedUtxosIncludesAllUtxosInLatestUtxoApiFetch = false; + // check + const { slpUtxos } = incrementallyHydratedUtxos; + + // Iterate over utxos array + for (let i = 0; i < utxos.length; i += 1) { + const thisUtxoObject = utxos[i]; + const thisUtxoObjectAddr = thisUtxoObject.address; + const thisUtxoObjectUtxos = thisUtxoObject.utxos; + let utxoFound; + for (let j = 0; j < thisUtxoObjectUtxos.length; j += 1) { + const thisUtxo = thisUtxoObjectUtxos[j]; + utxoFound = false; + // Now iterate over slpUtxos to find it + slpUtxosLoop: for (let k = 0; k < slpUtxos.length; k += 1) { + const thisSlpUtxosObject = slpUtxos[k]; + const thisSlpUtxosObjectAddr = thisSlpUtxosObject.address; + if (thisUtxoObjectAddr === thisSlpUtxosObjectAddr) { + const thisSlpUtxosObjectUtxos = thisSlpUtxosObject.utxos; + for ( + let m = 0; + m < thisSlpUtxosObjectUtxos.length; + m += 1 + ) { + const thisSlpUtxo = thisSlpUtxosObjectUtxos[m]; + if ( + thisUtxo.tx_hash === thisSlpUtxo.tx_hash && + thisUtxo.tx_pos === thisSlpUtxo.tx_pos && + thisUtxo.value === thisSlpUtxo.value + ) { + utxoFound = true; + // goto next utxo + break slpUtxosLoop; + } + } + } + if (k === slpUtxos.length - 1 && !utxoFound) { + // return false + return incrementallyHydratedUtxosIncludesAllUtxosInLatestUtxoApiFetch; + } + } + } + } + // It's possible that hydratedUtxoDetails includes every utxo from the utxos array, but for some reason also includes additional utxos + const utxosInUtxos = getUtxoCount(utxos); + const utxosInIncrementallyHydratedUtxos = getUtxoCount(slpUtxos); + if (utxosInUtxos !== utxosInIncrementallyHydratedUtxos) { + return incrementallyHydratedUtxosIncludesAllUtxosInLatestUtxoApiFetch; + } + // If you make it here, good to go + incrementallyHydratedUtxosIncludesAllUtxosInLatestUtxoApiFetch = true; + return incrementallyHydratedUtxosIncludesAllUtxosInLatestUtxoApiFetch; +};