Page MenuHomePhabricator

D15784.id46587.diff
No OneTemporary

D15784.id46587.diff

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/cashtab/extension/public/manifest.json b/cashtab/extension/public/manifest.json
--- a/cashtab/extension/public/manifest.json
+++ b/cashtab/extension/public/manifest.json
@@ -3,7 +3,7 @@
"name": "Cashtab",
"description": "A browser-integrated eCash wallet from Bitcoin ABC",
- "version": "3.8.0",
+ "version": "3.9.0",
"content_scripts": [
{
"matches": ["file://*/*", "http://*/*", "https://*/*"],
diff --git a/cashtab/package-lock.json b/cashtab/package-lock.json
--- a/cashtab/package-lock.json
+++ b/cashtab/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "cashtab",
- "version": "2.8.0",
+ "version": "2.9.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "cashtab",
- "version": "2.8.0",
+ "version": "2.9.0",
"dependencies": {
"@ant-design/icons": "^5.3.0",
"@bitgo/utxo-lib": "^9.33.0",
diff --git a/cashtab/package.json b/cashtab/package.json
--- a/cashtab/package.json
+++ b/cashtab/package.json
@@ -1,6 +1,6 @@
{
"name": "cashtab",
- "version": "2.8.0",
+ "version": "2.9.0",
"private": true,
"scripts": {
"start": "node scripts/start.js",
diff --git a/cashtab/src/chronik/__tests__/index.test.js b/cashtab/src/chronik/__tests__/index.test.js
--- a/cashtab/src/chronik/__tests__/index.test.js
+++ b/cashtab/src/chronik/__tests__/index.test.js
@@ -4,30 +4,30 @@
import {
organizeUtxosByType,
- getPreliminaryTokensArray,
- finalizeTokensArray,
- getTokenStats,
flattenChronikTxHistory,
sortAndTrimChronikTxHistory,
- parseChronikTx,
+ parseTx,
getMintAddress,
+ getTokenGenesisInfo,
+ getTokenBalances,
+ getHistory,
+ getUtxos,
} from 'chronik';
import vectors from '../fixtures/vectors';
-import {
- mockOrganizedUtxosByType,
- mockPreliminaryTokensArray,
- mockPreliminaryTokensArrayClone,
- mockPreliminaryTokensArrayCloneClone,
- mockChronikTxDetailsResponses,
- mockFinalTokenArray,
- mockFinalCachedTokenInfo,
- mockPartialCachedTokenInfo,
- mockPartialChronikTxDetailsResponses,
-} from '../fixtures/chronikUtxos';
-import { mockChronikTokenResponse } from '../fixtures/mockChronikTokenStats';
import {
mockTxHistoryOfAllAddresses,
mockFlatTxHistoryNoUnconfirmed,
+ chronikTokenMocks,
+ mockLargeTokenCache,
+ chronikSlpUtxos,
+ keyValueBalanceArray,
+ mockTxHistoryWalletJson,
+ mockPath1899History,
+ mockPath145History,
+ mockTxHistoryTokenCache,
+ tokensInHistory,
+ expectedParsedTxHistory,
+ noCachedInfoParsedTxHistory,
} from '../fixtures/mocks';
import {
mintingTxTabCash,
@@ -39,285 +39,14 @@
mintingAddressBuxSelfMint,
mintingTxBuxSelfMint,
} from '../fixtures/chronikMintTxs';
+import { cashtabWalletFromJSON } from 'helpers';
import { ChronikClient } from 'chronik-client';
import { when } from 'jest-when';
+import { MockChronikClient } from '../../../../modules/mock-chronik-client';
+import CashtabCache from 'config/CashtabCache';
describe('Cashtab chronik.js functions', () => {
- it(`getTokenStats successfully returns a token stats object`, async () => {
- // Initialize chronik
- const chronik = new ChronikClient(
- 'https://FakeChronikUrlToEnsureMocksOnly.com',
- );
- const tokenId =
- 'bb8e9f685a06a2071d82f757ce19201b4c8e5e96fbe186960a3d65aec83eab20';
- /*
- Mock the API response from chronik.token('tokenId') called
- in getTokenStats()
- */
- chronik.token = jest.fn();
- when(chronik.token)
- .calledWith(tokenId)
- .mockResolvedValue(mockChronikTokenResponse);
- expect(await getTokenStats(chronik, tokenId)).toStrictEqual(
- mockChronikTokenResponse,
- );
- });
- it(`getPreliminaryTokensArray successfully returns an array of all tokenIds and token balances (not yet adjusted for token decimals)`, () => {
- expect(
- getPreliminaryTokensArray(mockOrganizedUtxosByType.slpUtxos),
- ).toStrictEqual(mockPreliminaryTokensArray);
- });
- it(`We will automatically cache the unknown tokenId 0000000000000000000000000000000000000000000000000000000000000000 without attempting to get its info from chronik`, async () => {
- // Initialize chronik
- const chronik = new ChronikClient(
- 'https://FakeChronikUrlToEnsureMocksOnly.com',
- );
-
- const MOCK_SLP_UTXOS_WITH_UNKNOWN = [
- {
- outpoint: {
- txid: '250c93fd6bc2f1853a41d2fd1f5754a92f79f952f10ab038401be1600d5cbb88',
- outIdx: 1,
- },
- blockHeight: 836452,
- isCoinbase: false,
- value: 546,
- isFinal: true,
- token: {
- tokenId:
- '7cd7cd7c54167d306e770f972b564584c44cb412ee45839b4b97bb6e724c8849',
- tokenType: {
- protocol: 'ALP',
- type: 'ALP_TOKEN_TYPE_STANDARD',
- number: 0,
- },
- amount: '1000000',
- isMintBaton: false,
- },
- address: 'ecash:qqq9f9z3uhpzkxrgdjkd7dxuuey7tmpmugpmnw0kue',
- },
- {
- outpoint: {
- txid: '74a8598eed00672e211553a69e22334128199883fe79eb4ad64f9c0b7909735c',
- outIdx: 1,
- },
- blockHeight: 836457,
- isCoinbase: false,
- value: 1000,
- isFinal: true,
- token: {
- tokenId:
- '0000000000000000000000000000000000000000000000000000000000000000',
- tokenType: {
- protocol: 'ALP',
- type: 'ALP_TOKEN_TYPE_UNKNOWN',
- number: 255,
- },
- amount: '0',
- isMintBaton: false,
- },
- address: 'ecash:qqq9f9z3uhpzkxrgdjkd7dxuuey7tmpmugpmnw0kue',
- },
- ];
-
- // Get preliminary token utxos
- const preliminaryTokensArray = getPreliminaryTokensArray(
- MOCK_SLP_UTXOS_WITH_UNKNOWN,
- );
-
- // Expected mock token cache after calling finalizeTokensArray
- const UNKNOWN_TOKEN_ID =
- '0000000000000000000000000000000000000000000000000000000000000000';
- const KNOWN_TOKEN_ID =
- '7cd7cd7c54167d306e770f972b564584c44cb412ee45839b4b97bb6e724c8849';
- const mockTokens = new Map();
- mockTokens.set(KNOWN_TOKEN_ID, {
- tokenTicker: 'tCRD',
- tokenName: 'Test CRD',
- url: 'https://crd.network/tcrd',
- decimals: 4,
- data: {
- 0: 0,
- 1: 0,
- 2: 0,
- 3: 0,
- 4: 0,
- 5: 0,
- 6: 0,
- 7: 0,
- 8: 0,
- },
- authPubkey:
- '03d2dc0cea5c81593f1bfcd42763a21f5c85e7e8d053cdf990f8b383b892b72420',
- });
- mockTokens.set(UNKNOWN_TOKEN_ID, {
- decimals: 0,
- tokenName: 'Unknown Token',
- tokenTicker: 'UNKNOWN',
- url: 'N/A',
- });
-
- // Get finalized tokens array
-
- // Only mock the known tokenId api call
- chronik.token = jest.fn();
-
- when(chronik.token)
- .calledWith(KNOWN_TOKEN_ID)
- .mockResolvedValue({
- tokenId:
- '7cd7cd7c54167d306e770f972b564584c44cb412ee45839b4b97bb6e724c8849',
- tokenType: {
- protocol: 'ALP',
- type: 'ALP_TOKEN_TYPE_STANDARD',
- number: 0,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'tCRD',
- tokenName: 'Test CRD',
- url: 'https://crd.network/tcrd',
- decimals: 4,
- data: {
- 0: 0,
- 1: 0,
- 2: 0,
- 3: 0,
- 4: 0,
- 5: 0,
- 6: 0,
- 7: 0,
- 8: 0,
- },
- authPubkey:
- '03d2dc0cea5c81593f1bfcd42763a21f5c85e7e8d053cdf990f8b383b892b72420',
- },
- block: {
- height: 821187,
- hash: '00000000000000002998aedef7c4fc2c52281e318461d66c3c9fe10151449448',
- timestamp: 1701716369,
- },
- });
-
- expect(
- await finalizeTokensArray(chronik, preliminaryTokensArray),
- ).toStrictEqual({
- tokens: [
- {
- tokenId:
- '7cd7cd7c54167d306e770f972b564584c44cb412ee45839b4b97bb6e724c8849',
- balance: '100',
- info: {
- tokenTicker: 'tCRD',
- tokenName: 'Test CRD',
- url: 'https://crd.network/tcrd',
- decimals: 4,
- data: {
- 0: 0,
- 1: 0,
- 2: 0,
- 3: 0,
- 4: 0,
- 5: 0,
- 6: 0,
- 7: 0,
- 8: 0,
- },
- authPubkey:
- '03d2dc0cea5c81593f1bfcd42763a21f5c85e7e8d053cdf990f8b383b892b72420',
- },
- },
- {
- tokenId:
- '0000000000000000000000000000000000000000000000000000000000000000',
- balance: '0',
- info: {
- decimals: 0,
- tokenTicker: 'UNKNOWN',
- tokenName: 'Unknown Token',
- url: 'N/A',
- },
- },
- ],
- cachedTokens: mockTokens,
- newTokensToCache: true,
- });
- });
- it(`finalizeTokensArray successfully returns finalTokenArray and cachedTokenInfoById even if no cachedTokenInfoById is provided`, async () => {
- // Initialize chronik
- const chronik = new ChronikClient(
- 'https://FakeChronikUrlToEnsureMocksOnly.com',
- );
- /*
- Mock the API response from chronik.token('tokenId') called
- in returnGetTokenInfoChronikPromise -- for each tokenId used
- */
- chronik.token = jest.fn();
- for (let i = 0; i < mockChronikTxDetailsResponses.length; i += 1) {
- when(chronik.token)
- .calledWith(mockChronikTxDetailsResponses[i].tokenId)
- .mockResolvedValue(mockChronikTxDetailsResponses[i]);
- }
-
- expect(
- await finalizeTokensArray(chronik, mockPreliminaryTokensArray),
- ).toStrictEqual({
- tokens: mockFinalTokenArray,
- cachedTokens: mockFinalCachedTokenInfo,
- newTokensToCache: true,
- });
- });
- it(`finalizeTokensArray successfully returns finalTokenArray and cachedTokenInfoById when called with all token info in cache`, async () => {
- // Initialize chronik
- const chronik = new ChronikClient(
- 'https://FakeChronikUrlToEnsureMocksOnly.com',
- );
-
- expect(
- await finalizeTokensArray(
- chronik,
- mockPreliminaryTokensArrayClone,
- mockFinalCachedTokenInfo,
- ),
- ).toStrictEqual({
- tokens: mockFinalTokenArray,
- cachedTokens: mockFinalCachedTokenInfo,
- newTokensToCache: false,
- });
- });
- it(`updateCachedTokenInfoAndFinalizeTokensArray successfully returns finalTokenArray and cachedTokenInfoById when called with some token info in cache`, async () => {
- // Initialize chronik
- const chronik = new ChronikClient(
- 'https://FakeChronikUrlToEnsureMocksOnly.com',
- );
- /*
- Mock the API response from chronik.token('tokenId') called
- in returnGetTokenInfoChronikPromise -- for each tokenId used
- */
- chronik.token = jest.fn();
- for (
- let i = 0;
- i < mockPartialChronikTxDetailsResponses.length;
- i += 1
- ) {
- when(chronik.token)
- .calledWith(mockPartialChronikTxDetailsResponses[i].tokenId)
- .mockResolvedValue(mockPartialChronikTxDetailsResponses[i]);
- }
-
- expect(
- await finalizeTokensArray(
- chronik,
- mockPreliminaryTokensArrayCloneClone,
- mockPartialCachedTokenInfo,
- ),
- ).toStrictEqual({
- tokens: mockFinalTokenArray,
- cachedTokens: mockFinalCachedTokenInfo,
- newTokensToCache: true,
- });
- });
- it(`flattenChronikTxHistory successfully combines the result of getTxHistoryChronik into a single array`, async () => {
+ it(`flattenChronikTxHistory successfully combines the result of getHistory into a single array`, async () => {
expect(
await flattenChronikTxHistory(mockTxHistoryOfAllAddresses),
).toStrictEqual(mockFlatTxHistoryNoUnconfirmed);
@@ -327,10 +56,7 @@
const chronik = new ChronikClient(
'https://FakeChronikUrlToEnsureMocksOnly.com',
);
- /*
- Mock the API response from chronik.tx('tokenId') called
- in returnGetTokenInfoChronikPromise -- for each tokenId used
- */
+
chronik.tx = jest.fn();
when(chronik.tx)
@@ -346,10 +72,7 @@
const chronik = new ChronikClient(
'https://FakeChronikUrlToEnsureMocksOnly.com',
);
- /*
- Mock the API response from chronik.tx('tokenId') called
- in returnGetTokenInfoChronikPromise -- for each tokenId used
- */
+
chronik.tx = jest.fn();
when(chronik.tx)
@@ -366,10 +89,6 @@
'https://FakeChronikUrlToEnsureMocksOnly.com',
);
- /*
- Mock the API response from chronik.tx('tokenId') called
- in returnGetTokenInfoChronikPromise -- for each tokenId used
- */
chronik.tx = jest.fn();
when(chronik.tx)
@@ -386,10 +105,6 @@
'https://FakeChronikUrlToEnsureMocksOnly.com',
);
- /*
- Mock the API response from chronik.tx('tokenId') called
- in returnGetTokenInfoChronikPromise -- for each tokenId used
- */
chronik.tx = jest.fn();
when(chronik.tx)
@@ -401,23 +116,12 @@
);
});
describe('Parses supported tx types', () => {
- const { expectedReturns, expectedErrors } = vectors.parseChronikTx;
+ const { expectedReturns } = vectors.parseTx;
expectedReturns.forEach(expectedReturn => {
- const { description, tx, wallet, tokenInfoById, parsed } =
+ const { description, tx, wallet, cachedTokens, parsed } =
expectedReturn;
- it(`parseChronikTx: ${description}`, () => {
- expect(parseChronikTx(tx, wallet, tokenInfoById)).toStrictEqual(
- parsed,
- );
- });
- });
- expectedErrors.forEach(expectedError => {
- const { description, tx, wallet, tokenInfoById, errorMsg } =
- expectedError;
- it(`parseChronikTx throws error for: ${description}`, () => {
- expect(() => parseChronikTx(tx, wallet, tokenInfoById)).toThrow(
- errorMsg,
- );
+ it(`parseTx: ${description}`, () => {
+ expect(parseTx(tx, wallet, cachedTokens)).toStrictEqual(parsed);
});
});
});
@@ -451,4 +155,292 @@
});
});
});
+ describe('We get info we want to cache about a token from its genesis tx and chronik token info endpoint', () => {
+ const { expectedReturns, expectedErrors } = vectors.getTokenGenesisInfo;
+
+ expectedReturns.forEach(expectedReturn => {
+ const { description, tokenId, tokenInfo, genesisTx, returned } =
+ expectedReturn;
+ const mockedChronik = new MockChronikClient();
+
+ // Set mock for chronik.token(tokenId)
+ mockedChronik.setMock('token', {
+ input: tokenId,
+ output: tokenInfo,
+ });
+
+ // Set mock for chronik.tx(tokenId)
+ mockedChronik.setMock('tx', {
+ input: tokenId,
+ output: genesisTx,
+ });
+
+ it(`getTokenGenesisInfo: ${description}`, async () => {
+ expect(
+ await getTokenGenesisInfo(mockedChronik, tokenId),
+ ).toStrictEqual(returned);
+ });
+ });
+
+ expectedErrors.forEach(expectedReturn => {
+ const { description, tokenId, tokenInfo, genesisTx, msg } =
+ expectedReturn;
+ const mockedChronik = new MockChronikClient();
+
+ // Set mock for chronik.token(tokenId)
+ mockedChronik.setMock('token', {
+ input: tokenId,
+ output: tokenInfo,
+ });
+
+ // Set mock for chronik.tx(tokenId)
+ mockedChronik.setMock('tx', {
+ input: tokenId,
+ output: genesisTx,
+ });
+
+ it(`getTokenGenesisInfo: ${description}`, async () => {
+ await expect(
+ getTokenGenesisInfo(mockedChronik, tokenId),
+ ).rejects.toEqual(msg);
+ });
+ });
+ });
+ it('We can get token balance from a large token utxo set and update the cache', async () => {
+ // Mock the endpoints that will be called in updating the cache during getTokenBalances
+ const tokenIds = Object.keys(chronikTokenMocks);
+ const mockedChronik = new MockChronikClient();
+ for (const tokenId of tokenIds) {
+ const { token, tx } = chronikTokenMocks[tokenId];
+ // Set mock for chronik.token(tokenId)
+ mockedChronik.setMock('token', {
+ input: tokenId,
+ output: token,
+ });
+
+ // Set mock for chronik.tx(tokenId)
+ mockedChronik.setMock('tx', {
+ input: tokenId,
+ output: tx,
+ });
+ }
+
+ // Initialize an empty token cache
+ const tokenCache = new CashtabCache().tokens;
+
+ // Get token balances
+ const tokenBalances = await getTokenBalances(
+ mockedChronik,
+ chronikSlpUtxos,
+ tokenCache,
+ );
+
+ // Expect cache is updated
+ expect(tokenCache).toStrictEqual(mockLargeTokenCache);
+
+ // Expect correct balances
+ expect(tokenBalances).toStrictEqual(new Map(keyValueBalanceArray));
+ });
+ it('We can get token balance form a large token utxo set that includes a utxo of unknown tokenId and update the cache', async () => {
+ // Mock the endpoints that will be called in updating the cache during getTokenBalances
+ const tokenIds = Object.keys(chronikTokenMocks);
+ const mockedChronik = new MockChronikClient();
+ for (const tokenId of tokenIds) {
+ const { token, tx } = chronikTokenMocks[tokenId];
+ // Set mock for chronik.token(tokenId)
+ mockedChronik.setMock('token', {
+ input: tokenId,
+ output: token,
+ });
+
+ // Set mock for chronik.tx(tokenId)
+ mockedChronik.setMock('tx', {
+ input: tokenId,
+ output: tx,
+ });
+ }
+
+ // Initialize an empty token cache
+ const tokenCache = new CashtabCache().tokens;
+
+ // Get token balances
+ const tokenBalances = await getTokenBalances(
+ mockedChronik,
+ [
+ ...chronikSlpUtxos,
+ {
+ outpoint: {
+ txid: '74a8598eed00672e211553a69e22334128199883fe79eb4ad64f9c0b7909735c',
+ outIdx: 1,
+ },
+ blockHeight: 836457,
+ isCoinbase: false,
+ value: 1000,
+ isFinal: true,
+ token: {
+ tokenId:
+ '0000000000000000000000000000000000000000000000000000000000000000',
+ tokenType: {
+ protocol: 'ALP',
+ type: 'ALP_TOKEN_TYPE_UNKNOWN',
+ number: 255,
+ },
+ amount: '0',
+ isMintBaton: false,
+ },
+ path: 1899,
+ },
+ ],
+ tokenCache,
+ );
+
+ // Expect cache is updated
+ expect(tokenCache).toStrictEqual(mockLargeTokenCache);
+
+ // Expect correct balances, including a 0 balance for the unknown token id
+ expect(tokenBalances).toStrictEqual(
+ new Map([
+ ...keyValueBalanceArray,
+ [
+ '0000000000000000000000000000000000000000000000000000000000000000',
+ '0',
+ ],
+ ]),
+ );
+ });
+ it('We can get utxos from multiple paths and tag each one with its path', async () => {
+ // Make all of your chronik mocks
+
+ // Revive JSON wallet
+ const mockTxHistoryWallet = cashtabWalletFromJSON(
+ mockTxHistoryWalletJson,
+ );
+
+ const defaultAddress = mockTxHistoryWallet.paths.get(1899).address;
+ const secondaryAddress = mockTxHistoryWallet.paths.get(145).address;
+
+ // Set tx history for all paths
+ const mockedChronik = new MockChronikClient();
+ mockedChronik.setAddress(defaultAddress);
+ mockedChronik.setUtxosByAddress(defaultAddress, {
+ outputScript: 'string',
+ utxos: [{ value: 546 }],
+ });
+ mockedChronik.setAddress(secondaryAddress);
+ mockedChronik.setUtxosByAddress(secondaryAddress, {
+ outputScript: 'string',
+ utxos: [{ value: 546 }],
+ });
+ expect(
+ await getUtxos(mockedChronik, mockTxHistoryWallet),
+ ).toStrictEqual([
+ { value: 546, path: 1899 },
+ { value: 546, path: 145 },
+ ]);
+ });
+ it('We can get and parse tx history from a multi-path wallet, and update the token cache at the same time', async () => {
+ // Make all of your chronik mocks
+ const tokenIds = Object.keys(tokensInHistory);
+ const mockedChronik = new MockChronikClient();
+ for (const tokenId of tokenIds) {
+ const { token, tx } = tokensInHistory[tokenId];
+ // Set mock for chronik.token(tokenId)
+ mockedChronik.setMock('token', {
+ input: tokenId,
+ output: token,
+ });
+
+ // Set mock for chronik.tx(tokenId)
+ mockedChronik.setMock('tx', {
+ input: tokenId,
+ output: tx,
+ });
+ }
+
+ // Revive JSON wallet
+ const mockTxHistoryWallet = cashtabWalletFromJSON(
+ mockTxHistoryWalletJson,
+ );
+
+ const defaultAddress = mockTxHistoryWallet.paths.get(1899).address;
+ const secondaryAddress = mockTxHistoryWallet.paths.get(145).address;
+
+ // Set tx history for all paths
+ mockedChronik.setAddress(defaultAddress);
+ mockedChronik.setTxHistoryByAddress(
+ defaultAddress,
+ mockPath1899History,
+ );
+ mockedChronik.setAddress(secondaryAddress);
+ mockedChronik.setTxHistoryByAddress(
+ secondaryAddress,
+ mockPath145History,
+ );
+
+ // Initialize an empty token cache
+ const tokenCache = new CashtabCache().tokens;
+
+ // Get token balances
+ const parsedTxHistory = await getHistory(
+ mockedChronik,
+ mockTxHistoryWallet,
+ tokenCache,
+ );
+
+ // Expect cache is updated
+ expect(tokenCache).toStrictEqual(mockTxHistoryTokenCache);
+
+ // Expect correct tx history
+ expect(parsedTxHistory).toStrictEqual(expectedParsedTxHistory);
+ });
+ describe('We can get and parse tx history from a multi-path wallet. If there is an error in getting cached token data, we still parse tx history.', () => {
+ // Make all of your chronik mocks
+ const tokenIds = Object.keys(tokensInHistory);
+ const mockedChronik = new MockChronikClient();
+ for (const tokenId of tokenIds) {
+ // Mock an error in getting cached token info
+ mockedChronik.setMock('token', {
+ input: tokenId,
+ output: new Error('Some chronik error'),
+ });
+ }
+
+ // Revive JSON wallet
+ const mockTxHistoryWallet = cashtabWalletFromJSON(
+ mockTxHistoryWalletJson,
+ );
+
+ const defaultAddress = mockTxHistoryWallet.paths.get(1899).address;
+ const secondaryAddress = mockTxHistoryWallet.paths.get(145).address;
+
+ // Set tx history for all paths
+ mockedChronik.setAddress(defaultAddress);
+ mockedChronik.setTxHistoryByAddress(
+ defaultAddress,
+ mockPath1899History,
+ );
+ mockedChronik.setAddress(secondaryAddress);
+ mockedChronik.setTxHistoryByAddress(
+ secondaryAddress,
+ mockPath145History,
+ );
+
+ it(`We add to token cache and get parsed tx history`, async () => {
+ // Initialize an empty token cache
+ const tokenCache = new CashtabCache().tokens;
+
+ // Get token balances
+ const parsedTxHistory = await getHistory(
+ mockedChronik,
+ mockTxHistoryWallet,
+ tokenCache,
+ );
+
+ // Expect cache is unchanged
+ expect(tokenCache).toStrictEqual(new CashtabCache().tokens);
+
+ // Expect correct tx history
+ expect(parsedTxHistory).toStrictEqual(noCachedInfoParsedTxHistory);
+ });
+ });
});
diff --git a/cashtab/src/chronik/fixtures/chronikUtxos.js b/cashtab/src/chronik/fixtures/chronikUtxos.js
--- a/cashtab/src/chronik/fixtures/chronikUtxos.js
+++ b/cashtab/src/chronik/fixtures/chronikUtxos.js
@@ -2,8 +2,6 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-import { BN } from 'slp-mdm';
-
export const mockChronikUtxos = [
{
outpoint: {
@@ -6240,3044 +6238,6 @@
],
};
-export const mockPreliminaryTokensArray = [
- {
- tokenId:
- 'bf24d955f59351e738ecd905966606a6837e478e1982943d724eab10caad82fd',
- balance: new BN('1'),
- },
- {
- tokenId:
- 'bef614aac85c0c866f4d39e4d12a96851267d38d1bca5bdd6488bbd42e28b6b1',
- balance: new BN('240000001'),
- },
- {
- tokenId:
- '1f6a65e7a4bde92c0a012de2bcf4007034504a765377cdf08a3ee01d1eaa6901',
- balance: new BN('1'),
- },
- {
- tokenId:
- 'dd84ca78db4d617221b58eabc6667af8fe2f7eadbfcc213d35be9f1b419beb8d',
- balance: new BN('1'),
- },
- {
- tokenId:
- '50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e',
- balance: new BN('1'),
- },
- {
- tokenId:
- 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb',
- balance: new BN('99999999'),
- },
- {
- tokenId:
- '22f4ba40312ea3e90e1bfa88d2aa694c271d2e07361907b6eb5568873ffa62bf',
- balance: new BN('5500000'),
- },
- {
- tokenId:
- 'aa7202397a06097e8ff36855aa72c0ee032659747e5bd7cbcd3099fc3a62b6b6',
- balance: new BN('992'),
- },
- {
- tokenId:
- 'da9460ce4b1c92b4f6ef4e4a6bc2d05539f49d02b17681389d9ce22b8dca50f0',
- balance: new BN('333'),
- },
- {
- tokenId:
- '4db25a4b2f0b57415ce25fab6d9cb3ac2bbb444ff493dc16d0615a11ad06c875',
- balance: new BN('999988'),
- },
- {
- tokenId:
- '16b12bbacdbb8c8a799adbfd782bfff9843c1f9b0be148eaae02a1a7f74f95c4',
- balance: new BN('999900000000000'),
- },
- {
- tokenId:
- 'bd1acc4c986de57af8d6d2a64aecad8c30ee80f37ae9d066d758923732ddc9ba',
- balance: new BN('108999698951'),
- },
- {
- tokenId:
- '9e9738e9ac3ff202736bf7775f875ebae6f812650df577a947c20c52475e43da',
- balance: new BN('9100'),
- },
- {
- tokenId:
- 'f36e1b3d9a2aaf74f132fef3834e9743b945a667a4204e761b85f2e7b65fd41a',
- balance: new BN('1000'),
- },
- {
- tokenId:
- '7f8889682d57369ed0e32336f8b7e0ffec625a35cca183f4e81fde4e71a538a1',
- balance: new BN('2'),
- },
- {
- tokenId:
- '98183238638ecb4ddc365056e22de0e8a05448c1e6084bae247fae5a74ad4f48',
- balance: new BN('999990106'),
- },
- {
- tokenId:
- '3515f4a9851ad44124e0ddf6149344deb27a97720fc7e5254a9d2c86da7415a9',
- balance: new BN('100'),
- },
- {
- tokenId:
- '6fb6122742cac8fd1df2d68997fdfa4c077bc22d9ef4a336bfb63d24225f9060',
- balance: new BN('102'),
- },
- {
- tokenId:
- '2936188a41f22a3e0a47d13296147fb3f9ddd2f939fe6382904d21a610e8e49c',
- balance: new BN('102'),
- },
- {
- tokenId:
- 'e859eeb52e7afca6217fb36784b3b6d3c7386a52f391dd0d00f2ec03a5e8e77b',
- balance: new BN('10'),
- },
- {
- tokenId:
- 'bdb3b4215ca0622e0c4c07655522c376eaa891838a82f0217fa453bb0595a37c',
- balance: new BN('20000'),
- },
- {
- tokenId:
- '7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d',
- balance: new BN('5235120760000000'),
- },
- {
- tokenId:
- '7bbf452698a24b138b0357f689587fc6ea58410c34503b1179b91e40e10bba8b',
- balance: new BN('9999999900'),
- },
- {
- tokenId:
- '6376cae692cf0302ecdd63234c14cbb2b21cec75ab538335f90254cfb3ed44cc',
- balance: new BN('165'),
- },
- {
- tokenId:
- '666c4318d1f7fef5f2c698262492c519018d4e9130f95d05f6be9f0fb7149e96',
- balance: new BN('99'),
- },
- {
- tokenId:
- '157e0cdef5d5c51bdea00eac9ab821d809bb9d03cf98da85833614bedb129be6',
- balance: new BN('82'),
- },
- {
- tokenId:
- 'acba1d7f354c6d4d001eb99d31de174e5cea8a31d692afd6e7eb8474ad541f55',
- balance: new BN('123456844'),
- },
- {
- tokenId:
- 'ccf5fe5a387559c8ab9efdeb0c0ef1b444e677298cfddf07671245ce3cb3c79f',
- balance: new BN('47800000000'),
- },
- {
- tokenId:
- '4bd147fc5d5ff26249a9299c46b80920c0b81f59a60e05428262160ebee0b0c3',
- balance: new BN('996100'),
- },
- {
- tokenId:
- 'b8f2a9e767a0be7b80c7e414ef2534586d4da72efddb39a4e70e501ab73375cc',
- balance: new BN('9000'),
- },
- {
- tokenId:
- '1101bd5d7b6bbc3176fb2b93d08e76ab532b04ff731d71502249e3cb9b6fcb1a',
- balance: new BN('999888000000000'),
- },
- {
- tokenId:
- '3de671a7107d3803d78f7f4a4e5c794d0903a8d28d16076445c084943c1e2db8',
- balance: new BN('2200'),
- },
- {
- tokenId:
- '44929ff3b1fc634f982fede112cf12b21199a2ebbcf718412a38de9177d77168',
- balance: new BN('2'),
- },
- {
- tokenId:
- '639a8dba34788ff3ebd3977d4ac045825394285ee648bb1d159e1c12b787ff25',
- balance: new BN('9955000000000'),
- },
- {
- tokenId:
- 'd376ebcd518067c8e10c0505865cf7336160b47807e6f1a95739ba90ae838840',
- balance: new BN('100'),
- },
- {
- tokenId:
- 'b40d1f6acdb6ee68d7eca0167fe2753c076bc309b2e3b1af8bff70ca34b945b0',
- balance: new BN('5000'),
- },
- {
- tokenId:
- 'b39fdb53e21d67fa5fd3a11122f1452f15884047f2b80e8efe633c3b520b7a39',
- balance: new BN('6968'),
- },
- {
- tokenId:
- '3adbf501e21c711d20118e003711168eb39f560c01f4c6d6736fa3f3fceaa577',
- balance: new BN('999999000'),
- },
- {
- tokenId:
- '0916e71779c9de7ee125741d3f5ab01f556356dbc86fd327a24f1e9e22ebc917',
- balance: new BN('1700'),
- },
- {
- tokenId:
- '6e24e89b6d5284138c69777527760500b99614631bca7f2a5c38f4648dae9524',
- balance: new BN('999999900'),
- },
- {
- tokenId:
- '8ead21ce4b3b9e7b57607b97b65b5013496dc6e3dfdea162c08ce7265a66ebc8',
- balance: new BN('100000000'),
- },
- {
- tokenId:
- 'e4e1a2fb071fa71ca727e08ed1d8ea52a9531c79d1e5f1ebf483c66b71a8621c',
- balance: new BN('7900000000'),
- },
- {
- tokenId:
- '45f0ff5cae7e89da6b96c26c8c48a959214c5f0e983e78d0925f8956ca8848c6',
- balance: new BN('5400000'),
- },
- {
- tokenId:
- '77ec4036ef8546ac46df6d3a5374e961216f92624627eaeef5d2e1a253df9fc6',
- balance: new BN('117'),
- },
-];
-
-export const mockPreliminaryTokensArrayClone = [
- {
- tokenId:
- 'bf24d955f59351e738ecd905966606a6837e478e1982943d724eab10caad82fd',
- balance: new BN('1'),
- },
- {
- tokenId:
- 'bef614aac85c0c866f4d39e4d12a96851267d38d1bca5bdd6488bbd42e28b6b1',
- balance: new BN('240000001'),
- },
- {
- tokenId:
- '1f6a65e7a4bde92c0a012de2bcf4007034504a765377cdf08a3ee01d1eaa6901',
- balance: new BN('1'),
- },
- {
- tokenId:
- 'dd84ca78db4d617221b58eabc6667af8fe2f7eadbfcc213d35be9f1b419beb8d',
- balance: new BN('1'),
- },
- {
- tokenId:
- '50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e',
- balance: new BN('1'),
- },
- {
- tokenId:
- 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb',
- balance: new BN('99999999'),
- },
- {
- tokenId:
- '22f4ba40312ea3e90e1bfa88d2aa694c271d2e07361907b6eb5568873ffa62bf',
- balance: new BN('5500000'),
- },
- {
- tokenId:
- 'aa7202397a06097e8ff36855aa72c0ee032659747e5bd7cbcd3099fc3a62b6b6',
- balance: new BN('992'),
- },
- {
- tokenId:
- 'da9460ce4b1c92b4f6ef4e4a6bc2d05539f49d02b17681389d9ce22b8dca50f0',
- balance: new BN('333'),
- },
- {
- tokenId:
- '4db25a4b2f0b57415ce25fab6d9cb3ac2bbb444ff493dc16d0615a11ad06c875',
- balance: new BN('999988'),
- },
- {
- tokenId:
- '16b12bbacdbb8c8a799adbfd782bfff9843c1f9b0be148eaae02a1a7f74f95c4',
- balance: new BN('999900000000000'),
- },
- {
- tokenId:
- 'bd1acc4c986de57af8d6d2a64aecad8c30ee80f37ae9d066d758923732ddc9ba',
- balance: new BN('108999698951'),
- },
- {
- tokenId:
- '9e9738e9ac3ff202736bf7775f875ebae6f812650df577a947c20c52475e43da',
- balance: new BN('9100'),
- },
- {
- tokenId:
- 'f36e1b3d9a2aaf74f132fef3834e9743b945a667a4204e761b85f2e7b65fd41a',
- balance: new BN('1000'),
- },
- {
- tokenId:
- '7f8889682d57369ed0e32336f8b7e0ffec625a35cca183f4e81fde4e71a538a1',
- balance: new BN('2'),
- },
- {
- tokenId:
- '98183238638ecb4ddc365056e22de0e8a05448c1e6084bae247fae5a74ad4f48',
- balance: new BN('999990106'),
- },
- {
- tokenId:
- '3515f4a9851ad44124e0ddf6149344deb27a97720fc7e5254a9d2c86da7415a9',
- balance: new BN('100'),
- },
- {
- tokenId:
- '6fb6122742cac8fd1df2d68997fdfa4c077bc22d9ef4a336bfb63d24225f9060',
- balance: new BN('102'),
- },
- {
- tokenId:
- '2936188a41f22a3e0a47d13296147fb3f9ddd2f939fe6382904d21a610e8e49c',
- balance: new BN('102'),
- },
- {
- tokenId:
- 'e859eeb52e7afca6217fb36784b3b6d3c7386a52f391dd0d00f2ec03a5e8e77b',
- balance: new BN('10'),
- },
- {
- tokenId:
- 'bdb3b4215ca0622e0c4c07655522c376eaa891838a82f0217fa453bb0595a37c',
- balance: new BN('20000'),
- },
- {
- tokenId:
- '7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d',
- balance: new BN('5235120760000000'),
- },
- {
- tokenId:
- '7bbf452698a24b138b0357f689587fc6ea58410c34503b1179b91e40e10bba8b',
- balance: new BN('9999999900'),
- },
- {
- tokenId:
- '6376cae692cf0302ecdd63234c14cbb2b21cec75ab538335f90254cfb3ed44cc',
- balance: new BN('165'),
- },
- {
- tokenId:
- '666c4318d1f7fef5f2c698262492c519018d4e9130f95d05f6be9f0fb7149e96',
- balance: new BN('99'),
- },
- {
- tokenId:
- '157e0cdef5d5c51bdea00eac9ab821d809bb9d03cf98da85833614bedb129be6',
- balance: new BN('82'),
- },
- {
- tokenId:
- 'acba1d7f354c6d4d001eb99d31de174e5cea8a31d692afd6e7eb8474ad541f55',
- balance: new BN('123456844'),
- },
- {
- tokenId:
- 'ccf5fe5a387559c8ab9efdeb0c0ef1b444e677298cfddf07671245ce3cb3c79f',
- balance: new BN('47800000000'),
- },
- {
- tokenId:
- '4bd147fc5d5ff26249a9299c46b80920c0b81f59a60e05428262160ebee0b0c3',
- balance: new BN('996100'),
- },
- {
- tokenId:
- 'b8f2a9e767a0be7b80c7e414ef2534586d4da72efddb39a4e70e501ab73375cc',
- balance: new BN('9000'),
- },
- {
- tokenId:
- '1101bd5d7b6bbc3176fb2b93d08e76ab532b04ff731d71502249e3cb9b6fcb1a',
- balance: new BN('999888000000000'),
- },
- {
- tokenId:
- '3de671a7107d3803d78f7f4a4e5c794d0903a8d28d16076445c084943c1e2db8',
- balance: new BN('2200'),
- },
- {
- tokenId:
- '44929ff3b1fc634f982fede112cf12b21199a2ebbcf718412a38de9177d77168',
- balance: new BN('2'),
- },
- {
- tokenId:
- '639a8dba34788ff3ebd3977d4ac045825394285ee648bb1d159e1c12b787ff25',
- balance: new BN('9955000000000'),
- },
- {
- tokenId:
- 'd376ebcd518067c8e10c0505865cf7336160b47807e6f1a95739ba90ae838840',
- balance: new BN('100'),
- },
- {
- tokenId:
- 'b40d1f6acdb6ee68d7eca0167fe2753c076bc309b2e3b1af8bff70ca34b945b0',
- balance: new BN('5000'),
- },
- {
- tokenId:
- 'b39fdb53e21d67fa5fd3a11122f1452f15884047f2b80e8efe633c3b520b7a39',
- balance: new BN('6968'),
- },
- {
- tokenId:
- '3adbf501e21c711d20118e003711168eb39f560c01f4c6d6736fa3f3fceaa577',
- balance: new BN('999999000'),
- },
- {
- tokenId:
- '0916e71779c9de7ee125741d3f5ab01f556356dbc86fd327a24f1e9e22ebc917',
- balance: new BN('1700'),
- },
- {
- tokenId:
- '6e24e89b6d5284138c69777527760500b99614631bca7f2a5c38f4648dae9524',
- balance: new BN('999999900'),
- },
- {
- tokenId:
- '8ead21ce4b3b9e7b57607b97b65b5013496dc6e3dfdea162c08ce7265a66ebc8',
- balance: new BN('100000000'),
- },
- {
- tokenId:
- 'e4e1a2fb071fa71ca727e08ed1d8ea52a9531c79d1e5f1ebf483c66b71a8621c',
- balance: new BN('7900000000'),
- },
- {
- tokenId:
- '45f0ff5cae7e89da6b96c26c8c48a959214c5f0e983e78d0925f8956ca8848c6',
- balance: new BN('5400000'),
- },
- {
- tokenId:
- '77ec4036ef8546ac46df6d3a5374e961216f92624627eaeef5d2e1a253df9fc6',
- balance: new BN('117'),
- },
-];
-export const mockPreliminaryTokensArrayCloneClone = [
- {
- tokenId:
- 'bf24d955f59351e738ecd905966606a6837e478e1982943d724eab10caad82fd',
- balance: new BN('1'),
- },
- {
- tokenId:
- 'bef614aac85c0c866f4d39e4d12a96851267d38d1bca5bdd6488bbd42e28b6b1',
- balance: new BN('240000001'),
- },
- {
- tokenId:
- '1f6a65e7a4bde92c0a012de2bcf4007034504a765377cdf08a3ee01d1eaa6901',
- balance: new BN('1'),
- },
- {
- tokenId:
- 'dd84ca78db4d617221b58eabc6667af8fe2f7eadbfcc213d35be9f1b419beb8d',
- balance: new BN('1'),
- },
- {
- tokenId:
- '50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e',
- balance: new BN('1'),
- },
- {
- tokenId:
- 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb',
- balance: new BN('99999999'),
- },
- {
- tokenId:
- '22f4ba40312ea3e90e1bfa88d2aa694c271d2e07361907b6eb5568873ffa62bf',
- balance: new BN('5500000'),
- },
- {
- tokenId:
- 'aa7202397a06097e8ff36855aa72c0ee032659747e5bd7cbcd3099fc3a62b6b6',
- balance: new BN('992'),
- },
- {
- tokenId:
- 'da9460ce4b1c92b4f6ef4e4a6bc2d05539f49d02b17681389d9ce22b8dca50f0',
- balance: new BN('333'),
- },
- {
- tokenId:
- '4db25a4b2f0b57415ce25fab6d9cb3ac2bbb444ff493dc16d0615a11ad06c875',
- balance: new BN('999988'),
- },
- {
- tokenId:
- '16b12bbacdbb8c8a799adbfd782bfff9843c1f9b0be148eaae02a1a7f74f95c4',
- balance: new BN('999900000000000'),
- },
- {
- tokenId:
- 'bd1acc4c986de57af8d6d2a64aecad8c30ee80f37ae9d066d758923732ddc9ba',
- balance: new BN('108999698951'),
- },
- {
- tokenId:
- '9e9738e9ac3ff202736bf7775f875ebae6f812650df577a947c20c52475e43da',
- balance: new BN('9100'),
- },
- {
- tokenId:
- 'f36e1b3d9a2aaf74f132fef3834e9743b945a667a4204e761b85f2e7b65fd41a',
- balance: new BN('1000'),
- },
- {
- tokenId:
- '7f8889682d57369ed0e32336f8b7e0ffec625a35cca183f4e81fde4e71a538a1',
- balance: new BN('2'),
- },
- {
- tokenId:
- '98183238638ecb4ddc365056e22de0e8a05448c1e6084bae247fae5a74ad4f48',
- balance: new BN('999990106'),
- },
- {
- tokenId:
- '3515f4a9851ad44124e0ddf6149344deb27a97720fc7e5254a9d2c86da7415a9',
- balance: new BN('100'),
- },
- {
- tokenId:
- '6fb6122742cac8fd1df2d68997fdfa4c077bc22d9ef4a336bfb63d24225f9060',
- balance: new BN('102'),
- },
- {
- tokenId:
- '2936188a41f22a3e0a47d13296147fb3f9ddd2f939fe6382904d21a610e8e49c',
- balance: new BN('102'),
- },
- {
- tokenId:
- 'e859eeb52e7afca6217fb36784b3b6d3c7386a52f391dd0d00f2ec03a5e8e77b',
- balance: new BN('10'),
- },
- {
- tokenId:
- 'bdb3b4215ca0622e0c4c07655522c376eaa891838a82f0217fa453bb0595a37c',
- balance: new BN('20000'),
- },
- {
- tokenId:
- '7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d',
- balance: new BN('5235120760000000'),
- },
- {
- tokenId:
- '7bbf452698a24b138b0357f689587fc6ea58410c34503b1179b91e40e10bba8b',
- balance: new BN('9999999900'),
- },
- {
- tokenId:
- '6376cae692cf0302ecdd63234c14cbb2b21cec75ab538335f90254cfb3ed44cc',
- balance: new BN('165'),
- },
- {
- tokenId:
- '666c4318d1f7fef5f2c698262492c519018d4e9130f95d05f6be9f0fb7149e96',
- balance: new BN('99'),
- },
- {
- tokenId:
- '157e0cdef5d5c51bdea00eac9ab821d809bb9d03cf98da85833614bedb129be6',
- balance: new BN('82'),
- },
- {
- tokenId:
- 'acba1d7f354c6d4d001eb99d31de174e5cea8a31d692afd6e7eb8474ad541f55',
- balance: new BN('123456844'),
- },
- {
- tokenId:
- 'ccf5fe5a387559c8ab9efdeb0c0ef1b444e677298cfddf07671245ce3cb3c79f',
- balance: new BN('47800000000'),
- },
- {
- tokenId:
- '4bd147fc5d5ff26249a9299c46b80920c0b81f59a60e05428262160ebee0b0c3',
- balance: new BN('996100'),
- },
- {
- tokenId:
- 'b8f2a9e767a0be7b80c7e414ef2534586d4da72efddb39a4e70e501ab73375cc',
- balance: new BN('9000'),
- },
- {
- tokenId:
- '1101bd5d7b6bbc3176fb2b93d08e76ab532b04ff731d71502249e3cb9b6fcb1a',
- balance: new BN('999888000000000'),
- },
- {
- tokenId:
- '3de671a7107d3803d78f7f4a4e5c794d0903a8d28d16076445c084943c1e2db8',
- balance: new BN('2200'),
- },
- {
- tokenId:
- '44929ff3b1fc634f982fede112cf12b21199a2ebbcf718412a38de9177d77168',
- balance: new BN('2'),
- },
- {
- tokenId:
- '639a8dba34788ff3ebd3977d4ac045825394285ee648bb1d159e1c12b787ff25',
- balance: new BN('9955000000000'),
- },
- {
- tokenId:
- 'd376ebcd518067c8e10c0505865cf7336160b47807e6f1a95739ba90ae838840',
- balance: new BN('100'),
- },
- {
- tokenId:
- 'b40d1f6acdb6ee68d7eca0167fe2753c076bc309b2e3b1af8bff70ca34b945b0',
- balance: new BN('5000'),
- },
- {
- tokenId:
- 'b39fdb53e21d67fa5fd3a11122f1452f15884047f2b80e8efe633c3b520b7a39',
- balance: new BN('6968'),
- },
- {
- tokenId:
- '3adbf501e21c711d20118e003711168eb39f560c01f4c6d6736fa3f3fceaa577',
- balance: new BN('999999000'),
- },
- {
- tokenId:
- '0916e71779c9de7ee125741d3f5ab01f556356dbc86fd327a24f1e9e22ebc917',
- balance: new BN('1700'),
- },
- {
- tokenId:
- '6e24e89b6d5284138c69777527760500b99614631bca7f2a5c38f4648dae9524',
- balance: new BN('999999900'),
- },
- {
- tokenId:
- '8ead21ce4b3b9e7b57607b97b65b5013496dc6e3dfdea162c08ce7265a66ebc8',
- balance: new BN('100000000'),
- },
- {
- tokenId:
- 'e4e1a2fb071fa71ca727e08ed1d8ea52a9531c79d1e5f1ebf483c66b71a8621c',
- balance: new BN('7900000000'),
- },
- {
- tokenId:
- '45f0ff5cae7e89da6b96c26c8c48a959214c5f0e983e78d0925f8956ca8848c6',
- balance: new BN('5400000'),
- },
- {
- tokenId:
- '77ec4036ef8546ac46df6d3a5374e961216f92624627eaeef5d2e1a253df9fc6',
- balance: new BN('117'),
- },
-];
-
-export const mockChronikTxDetailsResponses = [
- {
- tokenId:
- 'bf24d955f59351e738ecd905966606a6837e478e1982943d724eab10caad82fd',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'ST',
- tokenName: 'ST',
- url: 'developer.bitcoin.com',
- decimals: 0,
- hash: '',
- },
- block: {
- height: 625949,
- hash: '00000000000000000071fae486bb8a703faacb1fdcc613bd024ac1c0870e16d8',
- timestamp: 1583919726,
- },
- },
- {
- tokenId:
- 'bef614aac85c0c866f4d39e4d12a96851267d38d1bca5bdd6488bbd42e28b6b1',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'CTP',
- tokenName: 'Cash Tab Points',
- url: 'https://cashtabapp.com/',
- decimals: 9,
- hash: '',
- },
- block: {
- height: 660971,
- hash: '00000000000000000334795ce566d1202a804e71422d05c93beb6afc4eb99cf3',
- timestamp: 1605037203,
- },
- },
- {
- tokenId:
- '1f6a65e7a4bde92c0a012de2bcf4007034504a765377cdf08a3ee01d1eaa6901',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: '🍔',
- tokenName: 'Burger',
- url: 'https://c4.wallpaperflare.com/wallpaper/58/564/863/giant-hamburger-wallpaper-preview.jpg',
- decimals: 0,
- hash: '',
- },
- block: {
- height: 619053,
- hash: '0000000000000000005b1e5a9a6db0570e8836cd8515e9c390ceb6ae174a2bae',
- timestamp: 1579759858,
- },
- },
- {
- tokenId:
- 'dd84ca78db4d617221b58eabc6667af8fe2f7eadbfcc213d35be9f1b419beb8d',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'TAP',
- tokenName: 'Thoughts and Prayers',
- url: '',
- decimals: 0,
- hash: '',
- },
- block: {
- height: 580703,
- hash: '000000000000000000d4d1d3ecb1a6134e3e4bb2ffd457f267e5e44139f2505f',
- timestamp: 1556742931,
- },
- },
- {
- tokenId:
- '50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'TBC',
- tokenName: 'tabcash',
- url: 'https://cashtabapp.com/',
- decimals: 0,
- hash: '',
- },
- block: {
- height: 674143,
- hash: '000000000000000034c77993a35c74fe2dddace27198681ca1e89e928d0c2fff',
- timestamp: 1613859311,
- },
- },
- {
- tokenId:
- 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'NAKAMOTO',
- tokenName: 'NAKAMOTO',
- url: '',
- decimals: 8,
- hash: '',
- },
- block: {
- height: 555671,
- hash: '000000000000000000aeb2168da809c07ede4de5ec2109df43bf49ef13805ddc',
- timestamp: 1541634138,
- },
- },
- {
- tokenId:
- '22f4ba40312ea3e90e1bfa88d2aa694c271d2e07361907b6eb5568873ffa62bf',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'CLA',
- tokenName: 'Cashtab Local Alpha',
- url: 'boomertakes.com',
- decimals: 5,
- hash: '',
- },
- block: {
- height: 688194,
- hash: '00000000000000003d718f77c7b914230be2357a1863542d9ce99994836e5eac',
- timestamp: 1622049539,
- },
- },
- {
- tokenId:
- 'aa7202397a06097e8ff36855aa72c0ee032659747e5bd7cbcd3099fc3a62b6b6',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'CTL',
- tokenName: 'Cashtab Token Launch Launch Token',
- url: 'https://cashtabapp.com/',
- decimals: 0,
- hash: '',
- },
- block: {
- height: 684993,
- hash: '00000000000000004c2f629c06444ec73fd059e1ee55e99d5e4b7bbff24f176a',
- timestamp: 1620160437,
- },
- },
- {
- tokenId:
- 'da9460ce4b1c92b4f6ef4e4a6bc2d05539f49d02b17681389d9ce22b8dca50f0',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'SA',
- tokenName: 'Spinner Alpha',
- url: 'https://cashtabapp.com/',
- decimals: 0,
- hash: '',
- },
- block: {
- height: 700677,
- hash: '000000000000000000b31f812d4eacbe21ac1b6b55542cdc92de2634b263c8b7',
- timestamp: 1629467912,
- },
- },
- {
- tokenId:
- '4db25a4b2f0b57415ce25fab6d9cb3ac2bbb444ff493dc16d0615a11ad06c875',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'LVV',
- tokenName: 'Lambda Variant Variants',
- url: 'https://cashtabapp.com/',
- decimals: 0,
- hash: '',
- },
- block: {
- height: 700722,
- hash: '0000000000000000260ee4c3b4f4ddde127bc0105d685c0ef31775b612627222',
- timestamp: 1629500864,
- },
- },
- {
- tokenId:
- '16b12bbacdbb8c8a799adbfd782bfff9843c1f9b0be148eaae02a1a7f74f95c4',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'CGEN',
- tokenName: 'Cashtab Genesis',
- url: 'https://boomertakes.com/',
- decimals: 9,
- hash: '',
- },
- block: {
- height: 684837,
- hash: '00000000000000001d065fdd22416c4e8e99803964f4fb9c91af6feb5ead5ff3',
- timestamp: 1620082584,
- },
- },
- {
- tokenId:
- 'bd1acc4c986de57af8d6d2a64aecad8c30ee80f37ae9d066d758923732ddc9ba',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'TBS',
- tokenName: 'TestBits',
- url: 'https://thecryptoguy.com/',
- decimals: 9,
- hash: '',
- },
- block: {
- height: 662989,
- hash: '000000000000000022f3b95ea9544c77938f232601b87a82b5c375b81e0123ae',
- timestamp: 1607034208,
- },
- },
- {
- tokenId:
- '9e9738e9ac3ff202736bf7775f875ebae6f812650df577a947c20c52475e43da',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'CUTT',
- tokenName: 'Cashtab Unit Test Token',
- url: 'https://cashtabapp.com/',
- decimals: 2,
- hash: '',
- },
- block: {
- height: 685003,
- hash: '000000000000000025276037dd4c38f5dc913e176bc37d4fdd1ca1b4de80e0d5',
- timestamp: 1620163728,
- },
- },
- {
- tokenId:
- 'f36e1b3d9a2aaf74f132fef3834e9743b945a667a4204e761b85f2e7b65fd41a',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'POW',
- tokenName: 'ProofofWriting.com Token',
- url: 'https://www.proofofwriting.com/26',
- decimals: 0,
- hash: '',
- },
- block: {
- height: 685949,
- hash: '0000000000000000436e71d5291d2fb067decc838dcb85a99ff6da1d28b89fad',
- timestamp: 1620712051,
- },
- },
- {
- tokenId:
- '7f8889682d57369ed0e32336f8b7e0ffec625a35cca183f4e81fde4e71a538a1',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'HONK',
- tokenName: 'HONK HONK',
- url: 'THE REAL HONK SLP TOKEN',
- decimals: 0,
- hash: '',
- },
- block: {
- height: 576633,
- hash: '000000000000000001400c74bf6ea59af97680bb6ee5b8918f0296795191dc56',
- timestamp: 1554290938,
- },
- },
- {
- tokenId:
- '98183238638ecb4ddc365056e22de0e8a05448c1e6084bae247fae5a74ad4f48',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'DVV',
- tokenName: 'Delta Variant Variants',
- url: 'https://cashtabapp.com/',
- decimals: 0,
- hash: '',
- },
- block: {
- height: 700469,
- hash: '00000000000000000bb5f9bb8e292c0017c34e05708f74eae3ae09ff18f6bc89',
- timestamp: 1629339994,
- },
- },
- {
- tokenId:
- '3515f4a9851ad44124e0ddf6149344deb27a97720fc7e5254a9d2c86da7415a9',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: '001',
- tokenName: '01',
- url: 'https://cashtab.com/',
- decimals: 0,
- hash: '',
- },
- block: {
- height: 715815,
- hash: '0000000000000000051e62c2d7365b642cade7245eff991b5074e612491d7188',
- timestamp: 1638316051,
- },
- },
- {
- tokenId:
- '6fb6122742cac8fd1df2d68997fdfa4c077bc22d9ef4a336bfb63d24225f9060',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: '002',
- tokenName: '2',
- url: 'https://cashtab.com/',
- decimals: 0,
- hash: '',
- },
- block: {
- height: 715815,
- hash: '0000000000000000051e62c2d7365b642cade7245eff991b5074e612491d7188',
- timestamp: 1638316051,
- },
- },
- {
- tokenId:
- '2936188a41f22a3e0a47d13296147fb3f9ddd2f939fe6382904d21a610e8e49c',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: '002',
- tokenName: '2',
- url: 'https://cashtab.com/',
- decimals: 0,
- hash: '',
- },
- block: {
- height: 715816,
- hash: '000000000000000007ccb2b916fb456b9c035a38e961bc4908a14096766d5a59',
- timestamp: 1638316507,
- },
- },
- {
- tokenId:
- 'e859eeb52e7afca6217fb36784b3b6d3c7386a52f391dd0d00f2ec03a5e8e77b',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'test',
- tokenName: 'test',
- url: 'https://cashtab.com/',
- decimals: 1,
- hash: '',
- },
- block: {
- height: 717055,
- hash: '0000000000000000113b17f038ac607eb5ef3c5636bf47088f692695b229d1cf',
- timestamp: 1639066280,
- },
- },
- {
- tokenId:
- 'bdb3b4215ca0622e0c4c07655522c376eaa891838a82f0217fa453bb0595a37c',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'Service',
- tokenName: 'Evc token',
- url: 'https://cashtab.com',
- decimals: 0,
- hash: '',
- },
- block: {
- height: 715115,
- hash: '000000000000000008685ec611c9ab59dd1062431e3b40a7e27c0320c4993f68',
- timestamp: 1637890451,
- },
- },
- {
- tokenId:
- '7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'WDT',
- tokenName:
- 'Test Token With Exceptionally Long Name For CSS And Style Revisions',
- url: 'https://www.ImpossiblyLongWebsiteDidYouThinkWebDevWouldBeFun.org',
- decimals: 7,
- hash: '85b591c15c9f49531e39fcfeb2a5a26b2bd0f7c018fb9cd71b5d92dfb732d5cc',
- },
- block: {
- height: 659948,
- hash: '000000000000000002e096ec3fda458dab941cd2ab40a7be10d54e88c9b06f37',
- timestamp: 1604423892,
- },
- },
- {
- tokenId:
- '7bbf452698a24b138b0357f689587fc6ea58410c34503b1179b91e40e10bba8b',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'COVID',
- tokenName: 'COVID-19',
- url: 'https://en.wikipedia.org/wiki/COVID-19',
- decimals: 0,
- hash: '',
- },
- block: {
- height: 716909,
- hash: '00000000000000000fc11b1bc4bb87ac76efbde32abdeb1c6aa1102c5d0a9718',
- timestamp: 1638980176,
- },
- },
- {
- tokenId:
- '6376cae692cf0302ecdd63234c14cbb2b21cec75ab538335f90254cfb3ed44cc',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'CLT',
- tokenName: 'Cashtab Local Tests',
- url: 'https://cashtab.com/',
- decimals: 0,
- hash: '',
- },
- block: {
- height: 720056,
- hash: '00000000000000001539b8b8d9e7d9459eb16ad84d387fc13326a34d7e09633d',
- timestamp: 1640867749,
- },
- },
- {
- tokenId:
- '666c4318d1f7fef5f2c698262492c519018d4e9130f95d05f6be9f0fb7149e96',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'CPG',
- tokenName: 'Cashtab Prod Gamma',
- url: 'thecryptoguy.com',
- decimals: 0,
- hash: '',
- },
- block: {
- height: 688495,
- hash: '000000000000000028aa42a7c622846b742465dfaaf41d29f955c1b8ee890c9e',
- timestamp: 1622237370,
- },
- },
- {
- tokenId:
- '157e0cdef5d5c51bdea00eac9ab821d809bb9d03cf98da85833614bedb129be6',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'CLNSP',
- tokenName: 'ComponentLongNameSpeedLoad',
- url: 'https://cashtabapp.com/',
- decimals: 0,
- hash: '',
- },
- block: {
- height: 685168,
- hash: '00000000000000001cd7cfe38ef8173732989f73bd4818e13db2b909c4cea007',
- timestamp: 1620249731,
- },
- },
- {
- tokenId:
- 'acba1d7f354c6d4d001eb99d31de174e5cea8a31d692afd6e7eb8474ad541f55',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'CTB',
- tokenName: 'CashTabBits',
- url: 'https://cashtabapp.com/',
- decimals: 9,
- hash: '',
- },
- block: {
- height: 662874,
- hash: '000000000000000055df35f930c6e9ef6f4c51f1df6650d53eb3390cb92503fa',
- timestamp: 1606935101,
- },
- },
- {
- tokenId:
- 'ccf5fe5a387559c8ab9efdeb0c0ef1b444e677298cfddf07671245ce3cb3c79f',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'XGB',
- tokenName: 'Garmonbozia',
- url: 'https://twinpeaks.fandom.com/wiki/Garmonbozia',
- decimals: 8,
- hash: '',
- },
- block: {
- height: 685147,
- hash: '00000000000000000955aad3a91d39a54197e5eb567660a41cb25c08430a991a',
- timestamp: 1620241359,
- },
- },
- {
- tokenId:
- '4bd147fc5d5ff26249a9299c46b80920c0b81f59a60e05428262160ebee0b0c3',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'NOCOVID',
- tokenName: 'Covid19 Lifetime Immunity',
- url: 'https://www.who.int/emergencies/diseases/novel-coronavirus-2019/covid-19-vaccines',
- decimals: 0,
- hash: '',
- },
- block: {
- height: 680063,
- hash: '000000000000000012ad3d6dfb3505616ab9c3cb3772abac0448ddfc25043df4',
- timestamp: 1617304616,
- },
- },
- {
- tokenId:
- 'b8f2a9e767a0be7b80c7e414ef2534586d4da72efddb39a4e70e501ab73375cc',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'CTD',
- tokenName: 'Cashtab Dark',
- url: 'https://cashtab.com/',
- decimals: 0,
- hash: '',
- },
- block: {
- height: 726043,
- hash: '00000000000000000182db32e000171006b7b7820181676b5fd8f29cc90d2b9c',
- timestamp: 1644455332,
- },
- },
- {
- tokenId:
- '1101bd5d7b6bbc3176fb2b93d08e76ab532b04ff731d71502249e3cb9b6fcb1a',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'XBIT',
- tokenName: 'eBits',
- url: 'https://boomertakes.com/',
- decimals: 9,
- hash: '',
- },
- block: {
- height: 680776,
- hash: '00000000000000003667d7cd150a1a29c78f5fab9360ab3c0e32eba99f9e2c08',
- timestamp: 1617733350,
- },
- },
- {
- tokenId:
- '3de671a7107d3803d78f7f4a4e5c794d0903a8d28d16076445c084943c1e2db8',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'CLB',
- tokenName: 'Cashtab Local Beta',
- url: 'boomertakes.com',
- decimals: 2,
- hash: '',
- },
- block: {
- height: 688194,
- hash: '00000000000000003d718f77c7b914230be2357a1863542d9ce99994836e5eac',
- timestamp: 1622049539,
- },
- },
- {
- tokenId:
- '44929ff3b1fc634f982fede112cf12b21199a2ebbcf718412a38de9177d77168',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'coin',
- tokenName: 'johncoin',
- url: 'https://cashtab.com/',
- decimals: 0,
- hash: '',
- },
- block: {
- height: 723121,
- hash: '00000000000000000ef48c91305f1054ae11c13e07eea788faa1f955aa4620fe',
- timestamp: 1642724690,
- },
- },
- {
- tokenId:
- '639a8dba34788ff3ebd3977d4ac045825394285ee648bb1d159e1c12b787ff25',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'CFL',
- tokenName: 'Cashtab Facelift',
- url: 'https://cashtab.com/',
- decimals: 9,
- hash: '',
- },
- block: {
- height: 726826,
- hash: '000000000000000007ba9fcd82bc10d70a55d4d74cb041cf234699c746d1c635',
- timestamp: 1644953895,
- },
- },
- {
- tokenId:
- 'd376ebcd518067c8e10c0505865cf7336160b47807e6f1a95739ba90ae838840',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'CFL',
- tokenName: 'Cashtab Facelift',
- url: 'https://cashtab.com/',
- decimals: 0,
- hash: '',
- },
- block: {
- height: 726826,
- hash: '000000000000000007ba9fcd82bc10d70a55d4d74cb041cf234699c746d1c635',
- timestamp: 1644953895,
- },
- },
- {
- tokenId:
- 'b40d1f6acdb6ee68d7eca0167fe2753c076bc309b2e3b1af8bff70ca34b945b0',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'KAT',
- tokenName: 'KA_Test',
- url: 'https://cashtab.com/',
- decimals: 0,
- hash: '',
- },
- block: {
- height: 727176,
- hash: '00000000000000000a37233b9ed0520368c58437fc4ce5edbda386a4619440f5',
- timestamp: 1645146139,
- },
- },
- {
- tokenId:
- 'b39fdb53e21d67fa5fd3a11122f1452f15884047f2b80e8efe633c3b520b7a39',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'SCΩΩG',
- tokenName: 'Scoogi Omega',
- url: 'https://cashtab.com/',
- decimals: 0,
- hash: '',
- },
- block: {
- height: 715111,
- hash: '0000000000000000029e7e0884d9f8b94437d146476ba12aa52815320d497be2',
- timestamp: 1637879760,
- },
- },
- {
- tokenId:
- '3adbf501e21c711d20118e003711168eb39f560c01f4c6d6736fa3f3fceaa577',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'OMI',
- tokenName: 'Omicron',
- url: 'cdc.gov',
- decimals: 0,
- hash: '',
- },
- block: {
- height: 717653,
- hash: '000000000000000004cc2d26068bcd8dcab87841b0ce6b5150f4f8b6ccff6d10',
- timestamp: 1639430827,
- },
- },
- {
- tokenId:
- '0916e71779c9de7ee125741d3f5ab01f556356dbc86fd327a24f1e9e22ebc917',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'CTL2',
- tokenName: 'Cashtab Token Launch Launch Token v2',
- url: 'thecryptoguy.com',
- decimals: 0,
- hash: '',
- },
- block: {
- height: 684993,
- hash: '00000000000000004c2f629c06444ec73fd059e1ee55e99d5e4b7bbff24f176a',
- timestamp: 1620160437,
- },
- },
- {
- tokenId:
- '6e24e89b6d5284138c69777527760500b99614631bca7f2a5c38f4648dae9524',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'CBB',
- tokenName: 'Cashtab Beta Bits',
- url: 'https://cashtabapp.com/',
- decimals: 0,
- hash: '',
- },
- block: {
- height: 700469,
- hash: '00000000000000000bb5f9bb8e292c0017c34e05708f74eae3ae09ff18f6bc89',
- timestamp: 1629339994,
- },
- },
- {
- tokenId:
- '8ead21ce4b3b9e7b57607b97b65b5013496dc6e3dfdea162c08ce7265a66ebc8',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'IFP',
- tokenName: 'Infrastructure Funding Proposal Token',
- url: 'ifp.cash',
- decimals: 8,
- hash: 'b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553',
- },
- block: {
- height: 650236,
- hash: '0000000000000000029d56ae91f48538121ce5e64c656053a1ddfda72249338d',
- timestamp: 1598560882,
- },
- },
- {
- tokenId:
- 'e4e1a2fb071fa71ca727e08ed1d8ea52a9531c79d1e5f1ebf483c66b71a8621c',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'CPA',
- tokenName: 'Cashtab Prod Alpha',
- url: 'thecryptoguy.com',
- decimals: 8,
- hash: '',
- },
- block: {
- height: 688355,
- hash: '0000000000000000369a9ebe2b6308da3ee9b0c864d79c26cad753f76f0f6e0d',
- timestamp: 1622132169,
- },
- },
- {
- tokenId:
- '45f0ff5cae7e89da6b96c26c8c48a959214c5f0e983e78d0925f8956ca8848c6',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'CMA',
- tokenName: 'CashtabMintAlpha',
- url: 'https://cashtabapp.com/',
- decimals: 5,
- hash: '',
- },
- block: {
- height: 685170,
- hash: '000000000000000025782a5b5b44efb49f9c3f86ef7355dc36010afc6624e3fd',
- timestamp: 1620250206,
- },
- },
- {
- tokenId:
- '77ec4036ef8546ac46df6d3a5374e961216f92624627eaeef5d2e1a253df9fc6',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'CTLv3',
- tokenName: 'Cashtab Token Launch Launch Token v3',
- url: 'coinex.com',
- decimals: 0,
- hash: '',
- },
- block: {
- height: 684994,
- hash: '0000000000000000384706dfb07ac54ff08d0b143bebc51b130dac5caa7c4eae',
- timestamp: 1620160484,
- },
- },
-];
-
-export const mockFinalTokenArray = [
- {
- tokenId:
- '1f6a65e7a4bde92c0a012de2bcf4007034504a765377cdf08a3ee01d1eaa6901',
- balance: '1',
- info: {
- tokenTicker: '🍔',
- tokenName: 'Burger',
- url: 'https://c4.wallpaperflare.com/wallpaper/58/564/863/giant-hamburger-wallpaper-preview.jpg',
- hash: '',
- decimals: 0,
- },
- },
- {
- tokenId:
- '3515f4a9851ad44124e0ddf6149344deb27a97720fc7e5254a9d2c86da7415a9',
- balance: '100',
- info: {
- tokenTicker: '001',
- tokenName: '01',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 0,
- },
- },
- {
- tokenId:
- '6fb6122742cac8fd1df2d68997fdfa4c077bc22d9ef4a336bfb63d24225f9060',
- balance: '102',
- info: {
- tokenTicker: '002',
- tokenName: '2',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 0,
- },
- },
- {
- tokenId:
- '2936188a41f22a3e0a47d13296147fb3f9ddd2f939fe6382904d21a610e8e49c',
- balance: '102',
- info: {
- tokenTicker: '002',
- tokenName: '2',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 0,
- },
- },
- {
- tokenId:
- '6e24e89b6d5284138c69777527760500b99614631bca7f2a5c38f4648dae9524',
- balance: '999999900',
- info: {
- tokenTicker: 'CBB',
- tokenName: 'Cashtab Beta Bits',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 0,
- },
- },
- {
- tokenId:
- '639a8dba34788ff3ebd3977d4ac045825394285ee648bb1d159e1c12b787ff25',
- balance: '9955',
- info: {
- tokenTicker: 'CFL',
- tokenName: 'Cashtab Facelift',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 9,
- },
- },
- {
- tokenId:
- 'd376ebcd518067c8e10c0505865cf7336160b47807e6f1a95739ba90ae838840',
- balance: '100',
- info: {
- tokenTicker: 'CFL',
- tokenName: 'Cashtab Facelift',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 0,
- },
- },
- {
- tokenId:
- '16b12bbacdbb8c8a799adbfd782bfff9843c1f9b0be148eaae02a1a7f74f95c4',
- balance: '999900',
- info: {
- tokenTicker: 'CGEN',
- tokenName: 'Cashtab Genesis',
- url: 'https://boomertakes.com/',
- hash: '',
- decimals: 9,
- },
- },
- {
- tokenId:
- '22f4ba40312ea3e90e1bfa88d2aa694c271d2e07361907b6eb5568873ffa62bf',
- balance: '55',
- info: {
- tokenTicker: 'CLA',
- tokenName: 'Cashtab Local Alpha',
- url: 'boomertakes.com',
- hash: '',
- decimals: 5,
- },
- },
- {
- tokenId:
- '3de671a7107d3803d78f7f4a4e5c794d0903a8d28d16076445c084943c1e2db8',
- balance: '22',
- info: {
- tokenTicker: 'CLB',
- tokenName: 'Cashtab Local Beta',
- url: 'boomertakes.com',
- hash: '',
- decimals: 2,
- },
- },
- {
- tokenId:
- '157e0cdef5d5c51bdea00eac9ab821d809bb9d03cf98da85833614bedb129be6',
- balance: '82',
- info: {
- tokenTicker: 'CLNSP',
- tokenName: 'ComponentLongNameSpeedLoad',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 0,
- },
- },
- {
- tokenId:
- '6376cae692cf0302ecdd63234c14cbb2b21cec75ab538335f90254cfb3ed44cc',
- balance: '165',
- info: {
- tokenTicker: 'CLT',
- tokenName: 'Cashtab Local Tests',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 0,
- },
- },
- {
- tokenId:
- '45f0ff5cae7e89da6b96c26c8c48a959214c5f0e983e78d0925f8956ca8848c6',
- balance: '54',
- info: {
- tokenTicker: 'CMA',
- tokenName: 'CashtabMintAlpha',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 5,
- },
- },
- {
- tokenId:
- '44929ff3b1fc634f982fede112cf12b21199a2ebbcf718412a38de9177d77168',
- balance: '2',
- info: {
- tokenTicker: 'coin',
- tokenName: 'johncoin',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 0,
- },
- },
- {
- tokenId:
- '7bbf452698a24b138b0357f689587fc6ea58410c34503b1179b91e40e10bba8b',
- balance: '9999999900',
- info: {
- tokenTicker: 'COVID',
- tokenName: 'COVID-19',
- url: 'https://en.wikipedia.org/wiki/COVID-19',
- hash: '',
- decimals: 0,
- },
- },
- {
- tokenId:
- 'e4e1a2fb071fa71ca727e08ed1d8ea52a9531c79d1e5f1ebf483c66b71a8621c',
- balance: '79',
- info: {
- tokenTicker: 'CPA',
- tokenName: 'Cashtab Prod Alpha',
- url: 'thecryptoguy.com',
- hash: '',
- decimals: 8,
- },
- },
- {
- tokenId:
- '666c4318d1f7fef5f2c698262492c519018d4e9130f95d05f6be9f0fb7149e96',
- balance: '99',
- info: {
- tokenTicker: 'CPG',
- tokenName: 'Cashtab Prod Gamma',
- url: 'thecryptoguy.com',
- hash: '',
- decimals: 0,
- },
- },
- {
- tokenId:
- 'acba1d7f354c6d4d001eb99d31de174e5cea8a31d692afd6e7eb8474ad541f55',
- balance: '0.123456844',
- info: {
- tokenTicker: 'CTB',
- tokenName: 'CashTabBits',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 9,
- },
- },
- {
- tokenId:
- 'b8f2a9e767a0be7b80c7e414ef2534586d4da72efddb39a4e70e501ab73375cc',
- balance: '9000',
- info: {
- tokenTicker: 'CTD',
- tokenName: 'Cashtab Dark',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 0,
- },
- },
- {
- tokenId:
- 'aa7202397a06097e8ff36855aa72c0ee032659747e5bd7cbcd3099fc3a62b6b6',
- balance: '992',
- info: {
- tokenTicker: 'CTL',
- tokenName: 'Cashtab Token Launch Launch Token',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 0,
- },
- },
- {
- tokenId:
- '0916e71779c9de7ee125741d3f5ab01f556356dbc86fd327a24f1e9e22ebc917',
- balance: '1700',
- info: {
- tokenTicker: 'CTL2',
- tokenName: 'Cashtab Token Launch Launch Token v2',
- url: 'thecryptoguy.com',
- hash: '',
- decimals: 0,
- },
- },
- {
- tokenId:
- '77ec4036ef8546ac46df6d3a5374e961216f92624627eaeef5d2e1a253df9fc6',
- balance: '117',
- info: {
- tokenTicker: 'CTLv3',
- tokenName: 'Cashtab Token Launch Launch Token v3',
- url: 'coinex.com',
- hash: '',
- decimals: 0,
- },
- },
- {
- tokenId:
- 'bef614aac85c0c866f4d39e4d12a96851267d38d1bca5bdd6488bbd42e28b6b1',
- balance: '0.240000001',
- info: {
- tokenTicker: 'CTP',
- tokenName: 'Cash Tab Points',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 9,
- },
- },
- {
- tokenId:
- '9e9738e9ac3ff202736bf7775f875ebae6f812650df577a947c20c52475e43da',
- balance: '91',
- info: {
- tokenTicker: 'CUTT',
- tokenName: 'Cashtab Unit Test Token',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 2,
- },
- },
- {
- tokenId:
- '98183238638ecb4ddc365056e22de0e8a05448c1e6084bae247fae5a74ad4f48',
- balance: '999990106',
- info: {
- tokenTicker: 'DVV',
- tokenName: 'Delta Variant Variants',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 0,
- },
- },
- {
- tokenId:
- '7f8889682d57369ed0e32336f8b7e0ffec625a35cca183f4e81fde4e71a538a1',
- balance: '2',
- info: {
- tokenTicker: 'HONK',
- tokenName: 'HONK HONK',
- url: 'THE REAL HONK SLP TOKEN',
- hash: '',
- decimals: 0,
- },
- },
- {
- tokenId:
- '8ead21ce4b3b9e7b57607b97b65b5013496dc6e3dfdea162c08ce7265a66ebc8',
- balance: '1',
- info: {
- tokenTicker: 'IFP',
- tokenName: 'Infrastructure Funding Proposal Token',
- url: 'ifp.cash',
- hash: 'b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553',
- decimals: 8,
- },
- },
- {
- tokenId:
- 'b40d1f6acdb6ee68d7eca0167fe2753c076bc309b2e3b1af8bff70ca34b945b0',
- balance: '5000',
- info: {
- tokenTicker: 'KAT',
- tokenName: 'KA_Test',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 0,
- },
- },
- {
- tokenId:
- '4db25a4b2f0b57415ce25fab6d9cb3ac2bbb444ff493dc16d0615a11ad06c875',
- balance: '999988',
- info: {
- tokenTicker: 'LVV',
- tokenName: 'Lambda Variant Variants',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 0,
- },
- },
- {
- tokenId:
- 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb',
- balance: '0.99999999',
- info: {
- tokenTicker: 'NAKAMOTO',
- tokenName: 'NAKAMOTO',
- url: '',
- hash: '',
- decimals: 8,
- },
- },
- {
- tokenId:
- '4bd147fc5d5ff26249a9299c46b80920c0b81f59a60e05428262160ebee0b0c3',
- balance: '996100',
- info: {
- tokenTicker: 'NOCOVID',
- tokenName: 'Covid19 Lifetime Immunity',
- url: 'https://www.who.int/emergencies/diseases/novel-coronavirus-2019/covid-19-vaccines',
- hash: '',
- decimals: 0,
- },
- },
- {
- tokenId:
- '3adbf501e21c711d20118e003711168eb39f560c01f4c6d6736fa3f3fceaa577',
- balance: '999999000',
- info: {
- tokenTicker: 'OMI',
- tokenName: 'Omicron',
- url: 'cdc.gov',
- hash: '',
- decimals: 0,
- },
- },
- {
- tokenId:
- 'f36e1b3d9a2aaf74f132fef3834e9743b945a667a4204e761b85f2e7b65fd41a',
- balance: '1000',
- info: {
- tokenTicker: 'POW',
- tokenName: 'ProofofWriting.com Token',
- url: 'https://www.proofofwriting.com/26',
- hash: '',
- decimals: 0,
- },
- },
- {
- tokenId:
- 'da9460ce4b1c92b4f6ef4e4a6bc2d05539f49d02b17681389d9ce22b8dca50f0',
- balance: '333',
- info: {
- tokenTicker: 'SA',
- tokenName: 'Spinner Alpha',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 0,
- },
- },
- {
- tokenId:
- 'b39fdb53e21d67fa5fd3a11122f1452f15884047f2b80e8efe633c3b520b7a39',
- balance: '6968',
- info: {
- tokenTicker: 'SCΩΩG',
- tokenName: 'Scoogi Omega',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 0,
- },
- },
- {
- tokenId:
- 'bdb3b4215ca0622e0c4c07655522c376eaa891838a82f0217fa453bb0595a37c',
- balance: '20000',
- info: {
- tokenTicker: 'Service',
- tokenName: 'Evc token',
- url: 'https://cashtab.com',
- hash: '',
- decimals: 0,
- },
- },
- {
- tokenId:
- 'bf24d955f59351e738ecd905966606a6837e478e1982943d724eab10caad82fd',
- balance: '1',
- info: {
- tokenTicker: 'ST',
- tokenName: 'ST',
- url: 'developer.bitcoin.com',
- hash: '',
- decimals: 0,
- },
- },
- {
- tokenId:
- 'dd84ca78db4d617221b58eabc6667af8fe2f7eadbfcc213d35be9f1b419beb8d',
- balance: '1',
- info: {
- tokenTicker: 'TAP',
- tokenName: 'Thoughts and Prayers',
- url: '',
- hash: '',
- decimals: 0,
- },
- },
- {
- tokenId:
- '50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e',
- balance: '1',
- info: {
- tokenTicker: 'TBC',
- tokenName: 'tabcash',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 0,
- },
- },
- {
- tokenId:
- 'bd1acc4c986de57af8d6d2a64aecad8c30ee80f37ae9d066d758923732ddc9ba',
- balance: '108.999698951',
- info: {
- tokenTicker: 'TBS',
- tokenName: 'TestBits',
- url: 'https://thecryptoguy.com/',
- hash: '',
- decimals: 9,
- },
- },
- {
- tokenId:
- 'e859eeb52e7afca6217fb36784b3b6d3c7386a52f391dd0d00f2ec03a5e8e77b',
- balance: '1',
- info: {
- tokenTicker: 'test',
- tokenName: 'test',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 1,
- },
- },
- {
- tokenId:
- '7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d',
- balance: '523512076',
- info: {
- tokenTicker: 'WDT',
- tokenName:
- 'Test Token With Exceptionally Long Name For CSS And Style Revisions',
- url: 'https://www.ImpossiblyLongWebsiteDidYouThinkWebDevWouldBeFun.org',
- hash: '85b591c15c9f49531e39fcfeb2a5a26b2bd0f7c018fb9cd71b5d92dfb732d5cc',
- decimals: 7,
- },
- },
- {
- tokenId:
- '1101bd5d7b6bbc3176fb2b93d08e76ab532b04ff731d71502249e3cb9b6fcb1a',
- balance: '999888',
- info: {
- tokenTicker: 'XBIT',
- tokenName: 'eBits',
- url: 'https://boomertakes.com/',
- hash: '',
- decimals: 9,
- },
- },
- {
- tokenId:
- 'ccf5fe5a387559c8ab9efdeb0c0ef1b444e677298cfddf07671245ce3cb3c79f',
- balance: '478',
- info: {
- tokenTicker: 'XGB',
- tokenName: 'Garmonbozia',
- url: 'https://twinpeaks.fandom.com/wiki/Garmonbozia',
- hash: '',
- decimals: 8,
- },
- },
-];
-
-export const legacyMockFinalCachedTokenInfo = {
- 'bf24d955f59351e738ecd905966606a6837e478e1982943d724eab10caad82fd': {
- tokenTicker: 'ST',
- tokenName: 'ST',
- url: 'developer.bitcoin.com',
- hash: '',
- decimals: 0,
- tokenId:
- 'bf24d955f59351e738ecd905966606a6837e478e1982943d724eab10caad82fd',
- },
- 'bef614aac85c0c866f4d39e4d12a96851267d38d1bca5bdd6488bbd42e28b6b1': {
- tokenTicker: 'CTP',
- tokenName: 'Cash Tab Points',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 9,
- tokenId:
- 'bef614aac85c0c866f4d39e4d12a96851267d38d1bca5bdd6488bbd42e28b6b1',
- },
- '1f6a65e7a4bde92c0a012de2bcf4007034504a765377cdf08a3ee01d1eaa6901': {
- tokenTicker: '🍔',
- tokenName: 'Burger',
- url: 'https://c4.wallpaperflare.com/wallpaper/58/564/863/giant-hamburger-wallpaper-preview.jpg',
- hash: '',
- decimals: 0,
- tokenId:
- '1f6a65e7a4bde92c0a012de2bcf4007034504a765377cdf08a3ee01d1eaa6901',
- },
- 'dd84ca78db4d617221b58eabc6667af8fe2f7eadbfcc213d35be9f1b419beb8d': {
- tokenTicker: 'TAP',
- tokenName: 'Thoughts and Prayers',
- url: '',
- hash: '',
- decimals: 0,
- tokenId:
- 'dd84ca78db4d617221b58eabc6667af8fe2f7eadbfcc213d35be9f1b419beb8d',
- },
- '50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e': {
- tokenTicker: 'TBC',
- tokenName: 'tabcash',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 0,
- tokenId:
- '50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e',
- },
- 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb': {
- tokenTicker: 'NAKAMOTO',
- tokenName: 'NAKAMOTO',
- url: '',
- hash: '',
- decimals: 8,
- tokenId:
- 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb',
- },
- '22f4ba40312ea3e90e1bfa88d2aa694c271d2e07361907b6eb5568873ffa62bf': {
- tokenTicker: 'CLA',
- tokenName: 'Cashtab Local Alpha',
- url: 'boomertakes.com',
- hash: '',
- decimals: 5,
- tokenId:
- '22f4ba40312ea3e90e1bfa88d2aa694c271d2e07361907b6eb5568873ffa62bf',
- },
- 'aa7202397a06097e8ff36855aa72c0ee032659747e5bd7cbcd3099fc3a62b6b6': {
- tokenTicker: 'CTL',
- tokenName: 'Cashtab Token Launch Launch Token',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 0,
- tokenId:
- 'aa7202397a06097e8ff36855aa72c0ee032659747e5bd7cbcd3099fc3a62b6b6',
- },
- 'da9460ce4b1c92b4f6ef4e4a6bc2d05539f49d02b17681389d9ce22b8dca50f0': {
- tokenTicker: 'SA',
- tokenName: 'Spinner Alpha',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 0,
- tokenId:
- 'da9460ce4b1c92b4f6ef4e4a6bc2d05539f49d02b17681389d9ce22b8dca50f0',
- },
- '4db25a4b2f0b57415ce25fab6d9cb3ac2bbb444ff493dc16d0615a11ad06c875': {
- tokenTicker: 'LVV',
- tokenName: 'Lambda Variant Variants',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 0,
- tokenId:
- '4db25a4b2f0b57415ce25fab6d9cb3ac2bbb444ff493dc16d0615a11ad06c875',
- },
- '16b12bbacdbb8c8a799adbfd782bfff9843c1f9b0be148eaae02a1a7f74f95c4': {
- tokenTicker: 'CGEN',
- tokenName: 'Cashtab Genesis',
- url: 'https://boomertakes.com/',
- hash: '',
- decimals: 9,
- tokenId:
- '16b12bbacdbb8c8a799adbfd782bfff9843c1f9b0be148eaae02a1a7f74f95c4',
- },
- 'bd1acc4c986de57af8d6d2a64aecad8c30ee80f37ae9d066d758923732ddc9ba': {
- tokenTicker: 'TBS',
- tokenName: 'TestBits',
- url: 'https://thecryptoguy.com/',
- hash: '',
- decimals: 9,
- tokenId:
- 'bd1acc4c986de57af8d6d2a64aecad8c30ee80f37ae9d066d758923732ddc9ba',
- },
- '9e9738e9ac3ff202736bf7775f875ebae6f812650df577a947c20c52475e43da': {
- tokenTicker: 'CUTT',
- tokenName: 'Cashtab Unit Test Token',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 2,
- tokenId:
- '9e9738e9ac3ff202736bf7775f875ebae6f812650df577a947c20c52475e43da',
- },
- 'f36e1b3d9a2aaf74f132fef3834e9743b945a667a4204e761b85f2e7b65fd41a': {
- tokenTicker: 'POW',
- tokenName: 'ProofofWriting.com Token',
- url: 'https://www.proofofwriting.com/26',
- hash: '',
- decimals: 0,
- tokenId:
- 'f36e1b3d9a2aaf74f132fef3834e9743b945a667a4204e761b85f2e7b65fd41a',
- },
- '7f8889682d57369ed0e32336f8b7e0ffec625a35cca183f4e81fde4e71a538a1': {
- tokenTicker: 'HONK',
- tokenName: 'HONK HONK',
- url: 'THE REAL HONK SLP TOKEN',
- hash: '',
- decimals: 0,
- tokenId:
- '7f8889682d57369ed0e32336f8b7e0ffec625a35cca183f4e81fde4e71a538a1',
- },
- '98183238638ecb4ddc365056e22de0e8a05448c1e6084bae247fae5a74ad4f48': {
- tokenTicker: 'DVV',
- tokenName: 'Delta Variant Variants',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 0,
- tokenId:
- '98183238638ecb4ddc365056e22de0e8a05448c1e6084bae247fae5a74ad4f48',
- },
- '3515f4a9851ad44124e0ddf6149344deb27a97720fc7e5254a9d2c86da7415a9': {
- tokenTicker: '001',
- tokenName: '01',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 0,
- tokenId:
- '3515f4a9851ad44124e0ddf6149344deb27a97720fc7e5254a9d2c86da7415a9',
- },
- '6fb6122742cac8fd1df2d68997fdfa4c077bc22d9ef4a336bfb63d24225f9060': {
- tokenTicker: '002',
- tokenName: '2',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 0,
- tokenId:
- '6fb6122742cac8fd1df2d68997fdfa4c077bc22d9ef4a336bfb63d24225f9060',
- },
- '2936188a41f22a3e0a47d13296147fb3f9ddd2f939fe6382904d21a610e8e49c': {
- tokenTicker: '002',
- tokenName: '2',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 0,
- tokenId:
- '2936188a41f22a3e0a47d13296147fb3f9ddd2f939fe6382904d21a610e8e49c',
- },
- 'e859eeb52e7afca6217fb36784b3b6d3c7386a52f391dd0d00f2ec03a5e8e77b': {
- tokenTicker: 'test',
- tokenName: 'test',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 1,
- tokenId:
- 'e859eeb52e7afca6217fb36784b3b6d3c7386a52f391dd0d00f2ec03a5e8e77b',
- },
- 'bdb3b4215ca0622e0c4c07655522c376eaa891838a82f0217fa453bb0595a37c': {
- tokenTicker: 'Service',
- tokenName: 'Evc token',
- url: 'https://cashtab.com',
- hash: '',
- decimals: 0,
- tokenId:
- 'bdb3b4215ca0622e0c4c07655522c376eaa891838a82f0217fa453bb0595a37c',
- },
- '7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d': {
- tokenTicker: 'WDT',
- tokenName:
- 'Test Token With Exceptionally Long Name For CSS And Style Revisions',
- url: 'https://www.ImpossiblyLongWebsiteDidYouThinkWebDevWouldBeFun.org',
- hash: '85b591c15c9f49531e39fcfeb2a5a26b2bd0f7c018fb9cd71b5d92dfb732d5cc',
- decimals: 7,
- tokenId:
- '7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d',
- },
- '7bbf452698a24b138b0357f689587fc6ea58410c34503b1179b91e40e10bba8b': {
- tokenTicker: 'COVID',
- tokenName: 'COVID-19',
- url: 'https://en.wikipedia.org/wiki/COVID-19',
- hash: '',
- decimals: 0,
- tokenId:
- '7bbf452698a24b138b0357f689587fc6ea58410c34503b1179b91e40e10bba8b',
- },
- '6376cae692cf0302ecdd63234c14cbb2b21cec75ab538335f90254cfb3ed44cc': {
- tokenTicker: 'CLT',
- tokenName: 'Cashtab Local Tests',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 0,
- tokenId:
- '6376cae692cf0302ecdd63234c14cbb2b21cec75ab538335f90254cfb3ed44cc',
- },
- '666c4318d1f7fef5f2c698262492c519018d4e9130f95d05f6be9f0fb7149e96': {
- tokenTicker: 'CPG',
- tokenName: 'Cashtab Prod Gamma',
- url: 'thecryptoguy.com',
- hash: '',
- decimals: 0,
- tokenId:
- '666c4318d1f7fef5f2c698262492c519018d4e9130f95d05f6be9f0fb7149e96',
- },
- '157e0cdef5d5c51bdea00eac9ab821d809bb9d03cf98da85833614bedb129be6': {
- tokenTicker: 'CLNSP',
- tokenName: 'ComponentLongNameSpeedLoad',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 0,
- tokenId:
- '157e0cdef5d5c51bdea00eac9ab821d809bb9d03cf98da85833614bedb129be6',
- },
- 'acba1d7f354c6d4d001eb99d31de174e5cea8a31d692afd6e7eb8474ad541f55': {
- tokenTicker: 'CTB',
- tokenName: 'CashTabBits',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 9,
- tokenId:
- 'acba1d7f354c6d4d001eb99d31de174e5cea8a31d692afd6e7eb8474ad541f55',
- },
- 'ccf5fe5a387559c8ab9efdeb0c0ef1b444e677298cfddf07671245ce3cb3c79f': {
- tokenTicker: 'XGB',
- tokenName: 'Garmonbozia',
- url: 'https://twinpeaks.fandom.com/wiki/Garmonbozia',
- hash: '',
- decimals: 8,
- tokenId:
- 'ccf5fe5a387559c8ab9efdeb0c0ef1b444e677298cfddf07671245ce3cb3c79f',
- },
- '4bd147fc5d5ff26249a9299c46b80920c0b81f59a60e05428262160ebee0b0c3': {
- tokenTicker: 'NOCOVID',
- tokenName: 'Covid19 Lifetime Immunity',
- url: 'https://www.who.int/emergencies/diseases/novel-coronavirus-2019/covid-19-vaccines',
- hash: '',
- decimals: 0,
- tokenId:
- '4bd147fc5d5ff26249a9299c46b80920c0b81f59a60e05428262160ebee0b0c3',
- },
- 'b8f2a9e767a0be7b80c7e414ef2534586d4da72efddb39a4e70e501ab73375cc': {
- tokenTicker: 'CTD',
- tokenName: 'Cashtab Dark',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 0,
- tokenId:
- 'b8f2a9e767a0be7b80c7e414ef2534586d4da72efddb39a4e70e501ab73375cc',
- },
- '1101bd5d7b6bbc3176fb2b93d08e76ab532b04ff731d71502249e3cb9b6fcb1a': {
- tokenTicker: 'XBIT',
- tokenName: 'eBits',
- url: 'https://boomertakes.com/',
- hash: '',
- decimals: 9,
- tokenId:
- '1101bd5d7b6bbc3176fb2b93d08e76ab532b04ff731d71502249e3cb9b6fcb1a',
- },
- '3de671a7107d3803d78f7f4a4e5c794d0903a8d28d16076445c084943c1e2db8': {
- tokenTicker: 'CLB',
- tokenName: 'Cashtab Local Beta',
- url: 'boomertakes.com',
- hash: '',
- decimals: 2,
- tokenId:
- '3de671a7107d3803d78f7f4a4e5c794d0903a8d28d16076445c084943c1e2db8',
- },
- '44929ff3b1fc634f982fede112cf12b21199a2ebbcf718412a38de9177d77168': {
- tokenTicker: 'coin',
- tokenName: 'johncoin',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 0,
- tokenId:
- '44929ff3b1fc634f982fede112cf12b21199a2ebbcf718412a38de9177d77168',
- },
- '639a8dba34788ff3ebd3977d4ac045825394285ee648bb1d159e1c12b787ff25': {
- tokenTicker: 'CFL',
- tokenName: 'Cashtab Facelift',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 9,
- tokenId:
- '639a8dba34788ff3ebd3977d4ac045825394285ee648bb1d159e1c12b787ff25',
- },
- 'd376ebcd518067c8e10c0505865cf7336160b47807e6f1a95739ba90ae838840': {
- tokenTicker: 'CFL',
- tokenName: 'Cashtab Facelift',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 0,
- tokenId:
- 'd376ebcd518067c8e10c0505865cf7336160b47807e6f1a95739ba90ae838840',
- },
- 'b40d1f6acdb6ee68d7eca0167fe2753c076bc309b2e3b1af8bff70ca34b945b0': {
- tokenTicker: 'KAT',
- tokenName: 'KA_Test',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 0,
- tokenId:
- 'b40d1f6acdb6ee68d7eca0167fe2753c076bc309b2e3b1af8bff70ca34b945b0',
- },
- 'b39fdb53e21d67fa5fd3a11122f1452f15884047f2b80e8efe633c3b520b7a39': {
- tokenTicker: 'SCΩΩG',
- tokenName: 'Scoogi Omega',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 0,
- tokenId:
- 'b39fdb53e21d67fa5fd3a11122f1452f15884047f2b80e8efe633c3b520b7a39',
- },
- '3adbf501e21c711d20118e003711168eb39f560c01f4c6d6736fa3f3fceaa577': {
- tokenTicker: 'OMI',
- tokenName: 'Omicron',
- url: 'cdc.gov',
- hash: '',
- decimals: 0,
- tokenId:
- '3adbf501e21c711d20118e003711168eb39f560c01f4c6d6736fa3f3fceaa577',
- },
- '0916e71779c9de7ee125741d3f5ab01f556356dbc86fd327a24f1e9e22ebc917': {
- tokenTicker: 'CTL2',
- tokenName: 'Cashtab Token Launch Launch Token v2',
- url: 'thecryptoguy.com',
- hash: '',
- decimals: 0,
- tokenId:
- '0916e71779c9de7ee125741d3f5ab01f556356dbc86fd327a24f1e9e22ebc917',
- },
- '6e24e89b6d5284138c69777527760500b99614631bca7f2a5c38f4648dae9524': {
- tokenTicker: 'CBB',
- tokenName: 'Cashtab Beta Bits',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 0,
- tokenId:
- '6e24e89b6d5284138c69777527760500b99614631bca7f2a5c38f4648dae9524',
- },
- '8ead21ce4b3b9e7b57607b97b65b5013496dc6e3dfdea162c08ce7265a66ebc8': {
- tokenTicker: 'IFP',
- tokenName: 'Infrastructure Funding Proposal Token',
- url: 'ifp.cash',
- hash: 'b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553',
- decimals: 8,
- tokenId:
- '8ead21ce4b3b9e7b57607b97b65b5013496dc6e3dfdea162c08ce7265a66ebc8',
- },
- 'e4e1a2fb071fa71ca727e08ed1d8ea52a9531c79d1e5f1ebf483c66b71a8621c': {
- tokenTicker: 'CPA',
- tokenName: 'Cashtab Prod Alpha',
- url: 'thecryptoguy.com',
- hash: '',
- decimals: 8,
- tokenId:
- 'e4e1a2fb071fa71ca727e08ed1d8ea52a9531c79d1e5f1ebf483c66b71a8621c',
- },
- '45f0ff5cae7e89da6b96c26c8c48a959214c5f0e983e78d0925f8956ca8848c6': {
- tokenTicker: 'CMA',
- tokenName: 'CashtabMintAlpha',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 5,
- tokenId:
- '45f0ff5cae7e89da6b96c26c8c48a959214c5f0e983e78d0925f8956ca8848c6',
- },
- '77ec4036ef8546ac46df6d3a5374e961216f92624627eaeef5d2e1a253df9fc6': {
- tokenTicker: 'CTLv3',
- tokenName: 'Cashtab Token Launch Launch Token v3',
- url: 'coinex.com',
- hash: '',
- decimals: 0,
- tokenId:
- '77ec4036ef8546ac46df6d3a5374e961216f92624627eaeef5d2e1a253df9fc6',
- },
-};
-const calculatedMockFinalCachedTokenInfo = new Map();
-const legacyCachedTokenIds = Object.keys(legacyMockFinalCachedTokenInfo);
-for (const tokenId of legacyCachedTokenIds) {
- const legacyGenesisInfo = JSON.parse(
- JSON.stringify(legacyMockFinalCachedTokenInfo[tokenId]),
- );
- // Remove the tokenId key which we do not need stored at the value
- delete legacyGenesisInfo.tokenId;
- calculatedMockFinalCachedTokenInfo.set(tokenId, legacyGenesisInfo);
-}
-export const mockFinalCachedTokenInfo = calculatedMockFinalCachedTokenInfo;
-
-export const legacyMockPartialCachedTokenInfo = {
- '1f6a65e7a4bde92c0a012de2bcf4007034504a765377cdf08a3ee01d1eaa6901': {
- tokenTicker: '🍔',
- tokenName: 'Burger',
- url: 'https://c4.wallpaperflare.com/wallpaper/58/564/863/giant-hamburger-wallpaper-preview.jpg',
- hash: '',
- decimals: 0,
- tokenId:
- '1f6a65e7a4bde92c0a012de2bcf4007034504a765377cdf08a3ee01d1eaa6901',
- },
- 'dd84ca78db4d617221b58eabc6667af8fe2f7eadbfcc213d35be9f1b419beb8d': {
- tokenTicker: 'TAP',
- tokenName: 'Thoughts and Prayers',
- url: '',
- hash: '',
- decimals: 0,
- tokenId:
- 'dd84ca78db4d617221b58eabc6667af8fe2f7eadbfcc213d35be9f1b419beb8d',
- },
- '50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e': {
- tokenTicker: 'TBC',
- tokenName: 'tabcash',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 0,
- tokenId:
- '50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e',
- },
- 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb': {
- tokenTicker: 'NAKAMOTO',
- tokenName: 'NAKAMOTO',
- url: '',
- hash: '',
- decimals: 8,
- tokenId:
- 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb',
- },
- '22f4ba40312ea3e90e1bfa88d2aa694c271d2e07361907b6eb5568873ffa62bf': {
- tokenTicker: 'CLA',
- tokenName: 'Cashtab Local Alpha',
- url: 'boomertakes.com',
- hash: '',
- decimals: 5,
- tokenId:
- '22f4ba40312ea3e90e1bfa88d2aa694c271d2e07361907b6eb5568873ffa62bf',
- },
- 'aa7202397a06097e8ff36855aa72c0ee032659747e5bd7cbcd3099fc3a62b6b6': {
- tokenTicker: 'CTL',
- tokenName: 'Cashtab Token Launch Launch Token',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 0,
- tokenId:
- 'aa7202397a06097e8ff36855aa72c0ee032659747e5bd7cbcd3099fc3a62b6b6',
- },
- 'da9460ce4b1c92b4f6ef4e4a6bc2d05539f49d02b17681389d9ce22b8dca50f0': {
- tokenTicker: 'SA',
- tokenName: 'Spinner Alpha',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 0,
- tokenId:
- 'da9460ce4b1c92b4f6ef4e4a6bc2d05539f49d02b17681389d9ce22b8dca50f0',
- },
- '4db25a4b2f0b57415ce25fab6d9cb3ac2bbb444ff493dc16d0615a11ad06c875': {
- tokenTicker: 'LVV',
- tokenName: 'Lambda Variant Variants',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 0,
- tokenId:
- '4db25a4b2f0b57415ce25fab6d9cb3ac2bbb444ff493dc16d0615a11ad06c875',
- },
- '16b12bbacdbb8c8a799adbfd782bfff9843c1f9b0be148eaae02a1a7f74f95c4': {
- tokenTicker: 'CGEN',
- tokenName: 'Cashtab Genesis',
- url: 'https://boomertakes.com/',
- hash: '',
- decimals: 9,
- tokenId:
- '16b12bbacdbb8c8a799adbfd782bfff9843c1f9b0be148eaae02a1a7f74f95c4',
- },
- 'bd1acc4c986de57af8d6d2a64aecad8c30ee80f37ae9d066d758923732ddc9ba': {
- tokenTicker: 'TBS',
- tokenName: 'TestBits',
- url: 'https://thecryptoguy.com/',
- hash: '',
- decimals: 9,
- tokenId:
- 'bd1acc4c986de57af8d6d2a64aecad8c30ee80f37ae9d066d758923732ddc9ba',
- },
- '9e9738e9ac3ff202736bf7775f875ebae6f812650df577a947c20c52475e43da': {
- tokenTicker: 'CUTT',
- tokenName: 'Cashtab Unit Test Token',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 2,
- tokenId:
- '9e9738e9ac3ff202736bf7775f875ebae6f812650df577a947c20c52475e43da',
- },
-
- '7f8889682d57369ed0e32336f8b7e0ffec625a35cca183f4e81fde4e71a538a1': {
- tokenTicker: 'HONK',
- tokenName: 'HONK HONK',
- url: 'THE REAL HONK SLP TOKEN',
- hash: '',
- decimals: 0,
- tokenId:
- '7f8889682d57369ed0e32336f8b7e0ffec625a35cca183f4e81fde4e71a538a1',
- },
- '98183238638ecb4ddc365056e22de0e8a05448c1e6084bae247fae5a74ad4f48': {
- tokenTicker: 'DVV',
- tokenName: 'Delta Variant Variants',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 0,
- tokenId:
- '98183238638ecb4ddc365056e22de0e8a05448c1e6084bae247fae5a74ad4f48',
- },
- '3515f4a9851ad44124e0ddf6149344deb27a97720fc7e5254a9d2c86da7415a9': {
- tokenTicker: '001',
- tokenName: '01',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 0,
- tokenId:
- '3515f4a9851ad44124e0ddf6149344deb27a97720fc7e5254a9d2c86da7415a9',
- },
- '6fb6122742cac8fd1df2d68997fdfa4c077bc22d9ef4a336bfb63d24225f9060': {
- tokenTicker: '002',
- tokenName: '2',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 0,
- tokenId:
- '6fb6122742cac8fd1df2d68997fdfa4c077bc22d9ef4a336bfb63d24225f9060',
- },
- '2936188a41f22a3e0a47d13296147fb3f9ddd2f939fe6382904d21a610e8e49c': {
- tokenTicker: '002',
- tokenName: '2',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 0,
- tokenId:
- '2936188a41f22a3e0a47d13296147fb3f9ddd2f939fe6382904d21a610e8e49c',
- },
- 'e859eeb52e7afca6217fb36784b3b6d3c7386a52f391dd0d00f2ec03a5e8e77b': {
- tokenTicker: 'test',
- tokenName: 'test',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 1,
- tokenId:
- 'e859eeb52e7afca6217fb36784b3b6d3c7386a52f391dd0d00f2ec03a5e8e77b',
- },
- 'bdb3b4215ca0622e0c4c07655522c376eaa891838a82f0217fa453bb0595a37c': {
- tokenTicker: 'Service',
- tokenName: 'Evc token',
- url: 'https://cashtab.com',
- hash: '',
- decimals: 0,
- tokenId:
- 'bdb3b4215ca0622e0c4c07655522c376eaa891838a82f0217fa453bb0595a37c',
- },
- '7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d': {
- tokenTicker: 'WDT',
- tokenName:
- 'Test Token With Exceptionally Long Name For CSS And Style Revisions',
- url: 'https://www.ImpossiblyLongWebsiteDidYouThinkWebDevWouldBeFun.org',
- hash: '85b591c15c9f49531e39fcfeb2a5a26b2bd0f7c018fb9cd71b5d92dfb732d5cc',
- decimals: 7,
- tokenId:
- '7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d',
- },
- '7bbf452698a24b138b0357f689587fc6ea58410c34503b1179b91e40e10bba8b': {
- tokenTicker: 'COVID',
- tokenName: 'COVID-19',
- url: 'https://en.wikipedia.org/wiki/COVID-19',
- hash: '',
- decimals: 0,
- tokenId:
- '7bbf452698a24b138b0357f689587fc6ea58410c34503b1179b91e40e10bba8b',
- },
- '6376cae692cf0302ecdd63234c14cbb2b21cec75ab538335f90254cfb3ed44cc': {
- tokenTicker: 'CLT',
- tokenName: 'Cashtab Local Tests',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 0,
- tokenId:
- '6376cae692cf0302ecdd63234c14cbb2b21cec75ab538335f90254cfb3ed44cc',
- },
- '666c4318d1f7fef5f2c698262492c519018d4e9130f95d05f6be9f0fb7149e96': {
- tokenTicker: 'CPG',
- tokenName: 'Cashtab Prod Gamma',
- url: 'thecryptoguy.com',
- hash: '',
- decimals: 0,
- tokenId:
- '666c4318d1f7fef5f2c698262492c519018d4e9130f95d05f6be9f0fb7149e96',
- },
- '157e0cdef5d5c51bdea00eac9ab821d809bb9d03cf98da85833614bedb129be6': {
- tokenTicker: 'CLNSP',
- tokenName: 'ComponentLongNameSpeedLoad',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 0,
- tokenId:
- '157e0cdef5d5c51bdea00eac9ab821d809bb9d03cf98da85833614bedb129be6',
- },
- 'acba1d7f354c6d4d001eb99d31de174e5cea8a31d692afd6e7eb8474ad541f55': {
- tokenTicker: 'CTB',
- tokenName: 'CashTabBits',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 9,
- tokenId:
- 'acba1d7f354c6d4d001eb99d31de174e5cea8a31d692afd6e7eb8474ad541f55',
- },
- 'ccf5fe5a387559c8ab9efdeb0c0ef1b444e677298cfddf07671245ce3cb3c79f': {
- tokenTicker: 'XGB',
- tokenName: 'Garmonbozia',
- url: 'https://twinpeaks.fandom.com/wiki/Garmonbozia',
- hash: '',
- decimals: 8,
- tokenId:
- 'ccf5fe5a387559c8ab9efdeb0c0ef1b444e677298cfddf07671245ce3cb3c79f',
- },
- '4bd147fc5d5ff26249a9299c46b80920c0b81f59a60e05428262160ebee0b0c3': {
- tokenTicker: 'NOCOVID',
- tokenName: 'Covid19 Lifetime Immunity',
- url: 'https://www.who.int/emergencies/diseases/novel-coronavirus-2019/covid-19-vaccines',
- hash: '',
- decimals: 0,
- tokenId:
- '4bd147fc5d5ff26249a9299c46b80920c0b81f59a60e05428262160ebee0b0c3',
- },
- 'b8f2a9e767a0be7b80c7e414ef2534586d4da72efddb39a4e70e501ab73375cc': {
- tokenTicker: 'CTD',
- tokenName: 'Cashtab Dark',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 0,
- tokenId:
- 'b8f2a9e767a0be7b80c7e414ef2534586d4da72efddb39a4e70e501ab73375cc',
- },
- '1101bd5d7b6bbc3176fb2b93d08e76ab532b04ff731d71502249e3cb9b6fcb1a': {
- tokenTicker: 'XBIT',
- tokenName: 'eBits',
- url: 'https://boomertakes.com/',
- hash: '',
- decimals: 9,
- tokenId:
- '1101bd5d7b6bbc3176fb2b93d08e76ab532b04ff731d71502249e3cb9b6fcb1a',
- },
- '3de671a7107d3803d78f7f4a4e5c794d0903a8d28d16076445c084943c1e2db8': {
- tokenTicker: 'CLB',
- tokenName: 'Cashtab Local Beta',
- url: 'boomertakes.com',
- hash: '',
- decimals: 2,
- tokenId:
- '3de671a7107d3803d78f7f4a4e5c794d0903a8d28d16076445c084943c1e2db8',
- },
- '44929ff3b1fc634f982fede112cf12b21199a2ebbcf718412a38de9177d77168': {
- tokenTicker: 'coin',
- tokenName: 'johncoin',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 0,
- tokenId:
- '44929ff3b1fc634f982fede112cf12b21199a2ebbcf718412a38de9177d77168',
- },
- '639a8dba34788ff3ebd3977d4ac045825394285ee648bb1d159e1c12b787ff25': {
- tokenTicker: 'CFL',
- tokenName: 'Cashtab Facelift',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 9,
- tokenId:
- '639a8dba34788ff3ebd3977d4ac045825394285ee648bb1d159e1c12b787ff25',
- },
- 'd376ebcd518067c8e10c0505865cf7336160b47807e6f1a95739ba90ae838840': {
- tokenTicker: 'CFL',
- tokenName: 'Cashtab Facelift',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 0,
- tokenId:
- 'd376ebcd518067c8e10c0505865cf7336160b47807e6f1a95739ba90ae838840',
- },
- 'b40d1f6acdb6ee68d7eca0167fe2753c076bc309b2e3b1af8bff70ca34b945b0': {
- tokenTicker: 'KAT',
- tokenName: 'KA_Test',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 0,
- tokenId:
- 'b40d1f6acdb6ee68d7eca0167fe2753c076bc309b2e3b1af8bff70ca34b945b0',
- },
- 'b39fdb53e21d67fa5fd3a11122f1452f15884047f2b80e8efe633c3b520b7a39': {
- tokenTicker: 'SCΩΩG',
- tokenName: 'Scoogi Omega',
- url: 'https://cashtab.com/',
- hash: '',
- decimals: 0,
- tokenId:
- 'b39fdb53e21d67fa5fd3a11122f1452f15884047f2b80e8efe633c3b520b7a39',
- },
- '3adbf501e21c711d20118e003711168eb39f560c01f4c6d6736fa3f3fceaa577': {
- tokenTicker: 'OMI',
- tokenName: 'Omicron',
- url: 'cdc.gov',
- hash: '',
- decimals: 0,
- tokenId:
- '3adbf501e21c711d20118e003711168eb39f560c01f4c6d6736fa3f3fceaa577',
- },
- '0916e71779c9de7ee125741d3f5ab01f556356dbc86fd327a24f1e9e22ebc917': {
- tokenTicker: 'CTL2',
- tokenName: 'Cashtab Token Launch Launch Token v2',
- url: 'thecryptoguy.com',
- hash: '',
- decimals: 0,
- tokenId:
- '0916e71779c9de7ee125741d3f5ab01f556356dbc86fd327a24f1e9e22ebc917',
- },
- '6e24e89b6d5284138c69777527760500b99614631bca7f2a5c38f4648dae9524': {
- tokenTicker: 'CBB',
- tokenName: 'Cashtab Beta Bits',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 0,
- tokenId:
- '6e24e89b6d5284138c69777527760500b99614631bca7f2a5c38f4648dae9524',
- },
- '8ead21ce4b3b9e7b57607b97b65b5013496dc6e3dfdea162c08ce7265a66ebc8': {
- tokenTicker: 'IFP',
- tokenName: 'Infrastructure Funding Proposal Token',
- url: 'ifp.cash',
- hash: 'b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553',
- decimals: 8,
- tokenId:
- '8ead21ce4b3b9e7b57607b97b65b5013496dc6e3dfdea162c08ce7265a66ebc8',
- },
- 'e4e1a2fb071fa71ca727e08ed1d8ea52a9531c79d1e5f1ebf483c66b71a8621c': {
- tokenTicker: 'CPA',
- tokenName: 'Cashtab Prod Alpha',
- url: 'thecryptoguy.com',
- hash: '',
- decimals: 8,
- tokenId:
- 'e4e1a2fb071fa71ca727e08ed1d8ea52a9531c79d1e5f1ebf483c66b71a8621c',
- },
- '45f0ff5cae7e89da6b96c26c8c48a959214c5f0e983e78d0925f8956ca8848c6': {
- tokenTicker: 'CMA',
- tokenName: 'CashtabMintAlpha',
- url: 'https://cashtabapp.com/',
- hash: '',
- decimals: 5,
- tokenId:
- '45f0ff5cae7e89da6b96c26c8c48a959214c5f0e983e78d0925f8956ca8848c6',
- },
- '77ec4036ef8546ac46df6d3a5374e961216f92624627eaeef5d2e1a253df9fc6': {
- tokenTicker: 'CTLv3',
- tokenName: 'Cashtab Token Launch Launch Token v3',
- url: 'coinex.com',
- hash: '',
- decimals: 0,
- tokenId:
- '77ec4036ef8546ac46df6d3a5374e961216f92624627eaeef5d2e1a253df9fc6',
- },
-};
-const calculatedMockPartialCachedTokenInfo = new Map();
-const legacyMockPartialCachedTokenIds = Object.keys(
- legacyMockPartialCachedTokenInfo,
-);
-for (const tokenId of legacyMockPartialCachedTokenIds) {
- const legacyGenesisInfo = JSON.parse(
- JSON.stringify(legacyMockPartialCachedTokenInfo[tokenId]),
- );
- // Remove the tokenId key which we do not need stored at the value
- delete legacyGenesisInfo.tokenId;
- calculatedMockPartialCachedTokenInfo.set(tokenId, legacyGenesisInfo);
-}
-export const mockPartialCachedTokenInfo = calculatedMockPartialCachedTokenInfo;
-
-export const mockPartialChronikTxDetailsResponses = [
- {
- tokenId:
- 'bf24d955f59351e738ecd905966606a6837e478e1982943d724eab10caad82fd',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'ST',
- tokenName: 'ST',
- url: 'developer.bitcoin.com',
- decimals: 0,
- hash: '',
- },
- block: {
- height: 625949,
- hash: '00000000000000000071fae486bb8a703faacb1fdcc613bd024ac1c0870e16d8',
- timestamp: 1583919726,
- },
- },
- {
- tokenId:
- 'bef614aac85c0c866f4d39e4d12a96851267d38d1bca5bdd6488bbd42e28b6b1',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'CTP',
- tokenName: 'Cash Tab Points',
- url: 'https://cashtabapp.com/',
- decimals: 9,
- hash: '',
- },
- block: {
- height: 660971,
- hash: '00000000000000000334795ce566d1202a804e71422d05c93beb6afc4eb99cf3',
- timestamp: 1605037203,
- },
- },
- {
- tokenId:
- 'f36e1b3d9a2aaf74f132fef3834e9743b945a667a4204e761b85f2e7b65fd41a',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'POW',
- tokenName: 'ProofofWriting.com Token',
- url: 'https://www.proofofwriting.com/26',
- decimals: 0,
- hash: '',
- },
- block: {
- height: 685949,
- hash: '0000000000000000436e71d5291d2fb067decc838dcb85a99ff6da1d28b89fad',
- timestamp: 1620712051,
- },
- },
-];
export const legacyMockTokenInfoById = {
'bf24d955f59351e738ecd905966606a6837e478e1982943d724eab10caad82fd': {
tokenTicker: 'ST',
diff --git a/cashtab/src/chronik/fixtures/mockChronikTokenStats.js b/cashtab/src/chronik/fixtures/mockChronikTokenStats.js
deleted file mode 100644
--- a/cashtab/src/chronik/fixtures/mockChronikTokenStats.js
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2024 The Bitcoin developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-// Result of chronik.token(`3c14fcdc3fce9738d213c1ab9d9ff18234fecab9d1ad5a77d3f7b95964269f4a`) for in-node cc
-export const mockChronikTokenResponse = {
- tokenId: '3c14fcdc3fce9738d213c1ab9d9ff18234fecab9d1ad5a77d3f7b95964269f4a',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'VVS',
- tokenName: 'ethantest',
- url: 'https://cashtab.com/',
- decimals: 3,
- hash: '',
- },
- block: {
- height: 758409,
- hash: '00000000000000000f305eafc05bffd14de4acf52787596b5927199c9cab37da',
- timestamp: 1663859004,
- },
-};
diff --git a/cashtab/src/chronik/fixtures/mocks.js b/cashtab/src/chronik/fixtures/mocks.js
--- a/cashtab/src/chronik/fixtures/mocks.js
+++ b/cashtab/src/chronik/fixtures/mocks.js
@@ -2,6 +2,9 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+import { validWalletJson } from 'validation/fixtures/mocks';
+import CashtabCache from 'config/CashtabCache';
+
export const mockTxHistoryOfAllAddresses = [
{
txs: [
@@ -7210,559 +7213,6 @@
},
};
-export const legacyTxHistoryTokenInfoById = {
- 'bf24d955f59351e738ecd905966606a6837e478e1982943d724eab10caad82fd': {
- tokenTicker: 'ST',
- tokenName: 'ST',
- tokenDocumentUrl: 'developer.bitcoin.com',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- 'bf24d955f59351e738ecd905966606a6837e478e1982943d724eab10caad82fd',
- },
- 'bef614aac85c0c866f4d39e4d12a96851267d38d1bca5bdd6488bbd42e28b6b1': {
- tokenTicker: 'CTP',
- tokenName: 'Cash Tab Points',
- tokenDocumentUrl: 'https://cashtabapp.com/',
- tokenDocumentHash: '',
- decimals: 9,
- tokenId:
- 'bef614aac85c0c866f4d39e4d12a96851267d38d1bca5bdd6488bbd42e28b6b1',
- },
- '1f6a65e7a4bde92c0a012de2bcf4007034504a765377cdf08a3ee01d1eaa6901': {
- tokenTicker: '🍔',
- tokenName: 'Burger',
- tokenDocumentUrl:
- 'https://c4.wallpaperflare.com/wallpaper/58/564/863/giant-hamburger-wallpaper-preview.jpg',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- '1f6a65e7a4bde92c0a012de2bcf4007034504a765377cdf08a3ee01d1eaa6901',
- },
- 'dd84ca78db4d617221b58eabc6667af8fe2f7eadbfcc213d35be9f1b419beb8d': {
- tokenTicker: 'TAP',
- tokenName: 'Thoughts and Prayers',
- tokenDocumentUrl: '',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- 'dd84ca78db4d617221b58eabc6667af8fe2f7eadbfcc213d35be9f1b419beb8d',
- },
- '50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e': {
- tokenTicker: 'TBC',
- tokenName: 'tabcash',
- tokenDocumentUrl: 'https://cashtabapp.com/',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- '50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e',
- },
- 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb': {
- tokenTicker: 'NAKAMOTO',
- tokenName: 'NAKAMOTO',
- tokenDocumentUrl: '',
- tokenDocumentHash: '',
- decimals: 8,
- tokenId:
- 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb',
- },
- '22f4ba40312ea3e90e1bfa88d2aa694c271d2e07361907b6eb5568873ffa62bf': {
- tokenTicker: 'CLA',
- tokenName: 'Cashtab Local Alpha',
- tokenDocumentUrl: 'boomertakes.com',
- tokenDocumentHash: '',
- decimals: 5,
- tokenId:
- '22f4ba40312ea3e90e1bfa88d2aa694c271d2e07361907b6eb5568873ffa62bf',
- },
- 'da9460ce4b1c92b4f6ef4e4a6bc2d05539f49d02b17681389d9ce22b8dca50f0': {
- tokenTicker: 'SA',
- tokenName: 'Spinner Alpha',
- tokenDocumentUrl: 'https://cashtabapp.com/',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- 'da9460ce4b1c92b4f6ef4e4a6bc2d05539f49d02b17681389d9ce22b8dca50f0',
- },
- '4db25a4b2f0b57415ce25fab6d9cb3ac2bbb444ff493dc16d0615a11ad06c875': {
- tokenTicker: 'LVV',
- tokenName: 'Lambda Variant Variants',
- tokenDocumentUrl: 'https://cashtabapp.com/',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- '4db25a4b2f0b57415ce25fab6d9cb3ac2bbb444ff493dc16d0615a11ad06c875',
- },
- '16b12bbacdbb8c8a799adbfd782bfff9843c1f9b0be148eaae02a1a7f74f95c4': {
- tokenTicker: 'CGEN',
- tokenName: 'Cashtab Genesis',
- tokenDocumentUrl: 'https://boomertakes.com/',
- tokenDocumentHash: '',
- decimals: 9,
- tokenId:
- '16b12bbacdbb8c8a799adbfd782bfff9843c1f9b0be148eaae02a1a7f74f95c4',
- },
- 'bd1acc4c986de57af8d6d2a64aecad8c30ee80f37ae9d066d758923732ddc9ba': {
- tokenTicker: 'TBS',
- tokenName: 'TestBits',
- tokenDocumentUrl: 'https://thecryptoguy.com/',
- tokenDocumentHash: '',
- decimals: 9,
- tokenId:
- 'bd1acc4c986de57af8d6d2a64aecad8c30ee80f37ae9d066d758923732ddc9ba',
- },
- 'aa7202397a06097e8ff36855aa72c0ee032659747e5bd7cbcd3099fc3a62b6b6': {
- tokenTicker: 'CTL',
- tokenName: 'Cashtab Token Launch Launch Token',
- tokenDocumentUrl: 'https://cashtabapp.com/',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- 'aa7202397a06097e8ff36855aa72c0ee032659747e5bd7cbcd3099fc3a62b6b6',
- },
- '9e9738e9ac3ff202736bf7775f875ebae6f812650df577a947c20c52475e43da': {
- tokenTicker: 'CUTT',
- tokenName: 'Cashtab Unit Test Token',
- tokenDocumentUrl: 'https://cashtabapp.com/',
- tokenDocumentHash: '',
- decimals: 2,
- tokenId:
- '9e9738e9ac3ff202736bf7775f875ebae6f812650df577a947c20c52475e43da',
- },
- 'f36e1b3d9a2aaf74f132fef3834e9743b945a667a4204e761b85f2e7b65fd41a': {
- tokenTicker: 'POW',
- tokenName: 'ProofofWriting.com Token',
- tokenDocumentUrl: 'https://www.proofofwriting.com/26',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- 'f36e1b3d9a2aaf74f132fef3834e9743b945a667a4204e761b85f2e7b65fd41a',
- },
- '7f8889682d57369ed0e32336f8b7e0ffec625a35cca183f4e81fde4e71a538a1': {
- tokenTicker: 'HONK',
- tokenName: 'HONK HONK',
- tokenDocumentUrl: 'THE REAL HONK SLP TOKEN',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- '7f8889682d57369ed0e32336f8b7e0ffec625a35cca183f4e81fde4e71a538a1',
- },
- '3515f4a9851ad44124e0ddf6149344deb27a97720fc7e5254a9d2c86da7415a9': {
- tokenTicker: '001',
- tokenName: '01',
- tokenDocumentUrl: 'https://cashtab.com/',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- '3515f4a9851ad44124e0ddf6149344deb27a97720fc7e5254a9d2c86da7415a9',
- },
- '6fb6122742cac8fd1df2d68997fdfa4c077bc22d9ef4a336bfb63d24225f9060': {
- tokenTicker: '002',
- tokenName: '2',
- tokenDocumentUrl: 'https://cashtab.com/',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- '6fb6122742cac8fd1df2d68997fdfa4c077bc22d9ef4a336bfb63d24225f9060',
- },
- '2936188a41f22a3e0a47d13296147fb3f9ddd2f939fe6382904d21a610e8e49c': {
- tokenTicker: '002',
- tokenName: '2',
- tokenDocumentUrl: 'https://cashtab.com/',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- '2936188a41f22a3e0a47d13296147fb3f9ddd2f939fe6382904d21a610e8e49c',
- },
- 'e859eeb52e7afca6217fb36784b3b6d3c7386a52f391dd0d00f2ec03a5e8e77b': {
- tokenTicker: 'test',
- tokenName: 'test',
- tokenDocumentUrl: 'https://cashtab.com/',
- tokenDocumentHash: '',
- decimals: 1,
- tokenId:
- 'e859eeb52e7afca6217fb36784b3b6d3c7386a52f391dd0d00f2ec03a5e8e77b',
- },
- 'bdb3b4215ca0622e0c4c07655522c376eaa891838a82f0217fa453bb0595a37c': {
- tokenTicker: 'Service',
- tokenName: 'Evc token',
- tokenDocumentUrl: 'https://cashtab.com',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- 'bdb3b4215ca0622e0c4c07655522c376eaa891838a82f0217fa453bb0595a37c',
- },
- '7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d': {
- tokenTicker: 'WDT',
- tokenName:
- 'Test Token With Exceptionally Long Name For CSS And Style Revisions',
- tokenDocumentUrl:
- 'https://www.ImpossiblyLongWebsiteDidYouThinkWebDevWouldBeFun.org',
- tokenDocumentHash:
- '85b591c15c9f49531e39fcfeb2a5a26b2bd0f7c018fb9cd71b5d92dfb732d5cc',
- decimals: 7,
- tokenId:
- '7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d',
- },
- '7bbf452698a24b138b0357f689587fc6ea58410c34503b1179b91e40e10bba8b': {
- tokenTicker: 'COVID',
- tokenName: 'COVID-19',
- tokenDocumentUrl: 'https://en.wikipedia.org/wiki/COVID-19',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- '7bbf452698a24b138b0357f689587fc6ea58410c34503b1179b91e40e10bba8b',
- },
- '6376cae692cf0302ecdd63234c14cbb2b21cec75ab538335f90254cfb3ed44cc': {
- tokenTicker: 'CLT',
- tokenName: 'Cashtab Local Tests',
- tokenDocumentUrl: 'https://cashtab.com/',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- '6376cae692cf0302ecdd63234c14cbb2b21cec75ab538335f90254cfb3ed44cc',
- },
- '666c4318d1f7fef5f2c698262492c519018d4e9130f95d05f6be9f0fb7149e96': {
- tokenTicker: 'CPG',
- tokenName: 'Cashtab Prod Gamma',
- tokenDocumentUrl: 'thecryptoguy.com',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- '666c4318d1f7fef5f2c698262492c519018d4e9130f95d05f6be9f0fb7149e96',
- },
- '157e0cdef5d5c51bdea00eac9ab821d809bb9d03cf98da85833614bedb129be6': {
- tokenTicker: 'CLNSP',
- tokenName: 'ComponentLongNameSpeedLoad',
- tokenDocumentUrl: 'https://cashtabapp.com/',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- '157e0cdef5d5c51bdea00eac9ab821d809bb9d03cf98da85833614bedb129be6',
- },
- 'acba1d7f354c6d4d001eb99d31de174e5cea8a31d692afd6e7eb8474ad541f55': {
- tokenTicker: 'CTB',
- tokenName: 'CashTabBits',
- tokenDocumentUrl: 'https://cashtabapp.com/',
- tokenDocumentHash: '',
- decimals: 9,
- tokenId:
- 'acba1d7f354c6d4d001eb99d31de174e5cea8a31d692afd6e7eb8474ad541f55',
- },
- 'ccf5fe5a387559c8ab9efdeb0c0ef1b444e677298cfddf07671245ce3cb3c79f': {
- tokenTicker: 'XGB',
- tokenName: 'Garmonbozia',
- tokenDocumentUrl: 'https://twinpeaks.fandom.com/wiki/Garmonbozia',
- tokenDocumentHash: '',
- decimals: 8,
- tokenId:
- 'ccf5fe5a387559c8ab9efdeb0c0ef1b444e677298cfddf07671245ce3cb3c79f',
- },
- '4bd147fc5d5ff26249a9299c46b80920c0b81f59a60e05428262160ebee0b0c3': {
- tokenTicker: 'NOCOVID',
- tokenName: 'Covid19 Lifetime Immunity',
- tokenDocumentUrl:
- 'https://www.who.int/emergencies/diseases/novel-coronavirus-2019/covid-19-vaccines',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- '4bd147fc5d5ff26249a9299c46b80920c0b81f59a60e05428262160ebee0b0c3',
- },
- 'b8f2a9e767a0be7b80c7e414ef2534586d4da72efddb39a4e70e501ab73375cc': {
- tokenTicker: 'CTD',
- tokenName: 'Cashtab Dark',
- tokenDocumentUrl: 'https://cashtab.com/',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- 'b8f2a9e767a0be7b80c7e414ef2534586d4da72efddb39a4e70e501ab73375cc',
- },
- '1101bd5d7b6bbc3176fb2b93d08e76ab532b04ff731d71502249e3cb9b6fcb1a': {
- tokenTicker: 'XBIT',
- tokenName: 'eBits',
- tokenDocumentUrl: 'https://boomertakes.com/',
- tokenDocumentHash: '',
- decimals: 9,
- tokenId:
- '1101bd5d7b6bbc3176fb2b93d08e76ab532b04ff731d71502249e3cb9b6fcb1a',
- },
- '3de671a7107d3803d78f7f4a4e5c794d0903a8d28d16076445c084943c1e2db8': {
- tokenTicker: 'CLB',
- tokenName: 'Cashtab Local Beta',
- tokenDocumentUrl: 'boomertakes.com',
- tokenDocumentHash: '',
- decimals: 2,
- tokenId:
- '3de671a7107d3803d78f7f4a4e5c794d0903a8d28d16076445c084943c1e2db8',
- },
- '44929ff3b1fc634f982fede112cf12b21199a2ebbcf718412a38de9177d77168': {
- tokenTicker: 'coin',
- tokenName: 'johncoin',
- tokenDocumentUrl: 'https://cashtab.com/',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- '44929ff3b1fc634f982fede112cf12b21199a2ebbcf718412a38de9177d77168',
- },
- '639a8dba34788ff3ebd3977d4ac045825394285ee648bb1d159e1c12b787ff25': {
- tokenTicker: 'CFL',
- tokenName: 'Cashtab Facelift',
- tokenDocumentUrl: 'https://cashtab.com/',
- tokenDocumentHash: '',
- decimals: 9,
- tokenId:
- '639a8dba34788ff3ebd3977d4ac045825394285ee648bb1d159e1c12b787ff25',
- },
- 'd376ebcd518067c8e10c0505865cf7336160b47807e6f1a95739ba90ae838840': {
- tokenTicker: 'CFL',
- tokenName: 'Cashtab Facelift',
- tokenDocumentUrl: 'https://cashtab.com/',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- 'd376ebcd518067c8e10c0505865cf7336160b47807e6f1a95739ba90ae838840',
- },
- 'b40d1f6acdb6ee68d7eca0167fe2753c076bc309b2e3b1af8bff70ca34b945b0': {
- tokenTicker: 'KAT',
- tokenName: 'KA_Test',
- tokenDocumentUrl: 'https://cashtab.com/',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- 'b40d1f6acdb6ee68d7eca0167fe2753c076bc309b2e3b1af8bff70ca34b945b0',
- },
- 'b39fdb53e21d67fa5fd3a11122f1452f15884047f2b80e8efe633c3b520b7a39': {
- tokenTicker: 'SCΩΩG',
- tokenName: 'Scoogi Omega',
- tokenDocumentUrl: 'https://cashtab.com/',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- 'b39fdb53e21d67fa5fd3a11122f1452f15884047f2b80e8efe633c3b520b7a39',
- },
- '3adbf501e21c711d20118e003711168eb39f560c01f4c6d6736fa3f3fceaa577': {
- tokenTicker: 'OMI',
- tokenName: 'Omicron',
- tokenDocumentUrl: 'cdc.gov',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- '3adbf501e21c711d20118e003711168eb39f560c01f4c6d6736fa3f3fceaa577',
- },
- '0916e71779c9de7ee125741d3f5ab01f556356dbc86fd327a24f1e9e22ebc917': {
- tokenTicker: 'CTL2',
- tokenName: 'Cashtab Token Launch Launch Token v2',
- tokenDocumentUrl: 'thecryptoguy.com',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- '0916e71779c9de7ee125741d3f5ab01f556356dbc86fd327a24f1e9e22ebc917',
- },
- '6e24e89b6d5284138c69777527760500b99614631bca7f2a5c38f4648dae9524': {
- tokenTicker: 'CBB',
- tokenName: 'Cashtab Beta Bits',
- tokenDocumentUrl: 'https://cashtabapp.com/',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- '6e24e89b6d5284138c69777527760500b99614631bca7f2a5c38f4648dae9524',
- },
- '8ead21ce4b3b9e7b57607b97b65b5013496dc6e3dfdea162c08ce7265a66ebc8': {
- tokenTicker: 'IFP',
- tokenName: 'Infrastructure Funding Proposal Token',
- tokenDocumentUrl: 'ifp.cash',
- tokenDocumentHash:
- 'b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553',
- decimals: 8,
- tokenId:
- '8ead21ce4b3b9e7b57607b97b65b5013496dc6e3dfdea162c08ce7265a66ebc8',
- },
- 'e4e1a2fb071fa71ca727e08ed1d8ea52a9531c79d1e5f1ebf483c66b71a8621c': {
- tokenTicker: 'CPA',
- tokenName: 'Cashtab Prod Alpha',
- tokenDocumentUrl: 'thecryptoguy.com',
- tokenDocumentHash: '',
- decimals: 8,
- tokenId:
- 'e4e1a2fb071fa71ca727e08ed1d8ea52a9531c79d1e5f1ebf483c66b71a8621c',
- },
- '45f0ff5cae7e89da6b96c26c8c48a959214c5f0e983e78d0925f8956ca8848c6': {
- tokenTicker: 'CMA',
- tokenName: 'CashtabMintAlpha',
- tokenDocumentUrl: 'https://cashtabapp.com/',
- tokenDocumentHash: '',
- decimals: 5,
- tokenId:
- '45f0ff5cae7e89da6b96c26c8c48a959214c5f0e983e78d0925f8956ca8848c6',
- },
- '56e9b1d16c9989186c846187db57d9a9389c3ecc74e7237c1d1d0327cf904a55': {
- tokenTicker: 'CKA',
- tokenName: 'Chronik Alpha',
- tokenDocumentUrl: 'https://cashtab.com/',
- tokenDocumentHash: '',
- decimals: 8,
- tokenId:
- '56e9b1d16c9989186c846187db57d9a9389c3ecc74e7237c1d1d0327cf904a55',
- },
- '77ec4036ef8546ac46df6d3a5374e961216f92624627eaeef5d2e1a253df9fc6': {
- tokenTicker: 'CTLv3',
- tokenName: 'Cashtab Token Launch Launch Token v3',
- tokenDocumentUrl: 'coinex.com',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- '77ec4036ef8546ac46df6d3a5374e961216f92624627eaeef5d2e1a253df9fc6',
- },
- '98183238638ecb4ddc365056e22de0e8a05448c1e6084bae247fae5a74ad4f48': {
- tokenTicker: 'DVV',
- tokenName: 'Delta Variant Variants',
- tokenDocumentUrl: 'https://cashtabapp.com/',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- '98183238638ecb4ddc365056e22de0e8a05448c1e6084bae247fae5a74ad4f48',
- },
- 'bfddfcfc9fb9a8d61ed74fa94b5e32ccc03305797eea461658303df5805578ef': {
- tokenTicker: 'Sending Token',
- tokenName: 'Sending Token',
- tokenDocumentUrl: 'developer.bitcoin.com',
- tokenDocumentHash: '',
- decimals: 9,
- tokenId:
- 'bfddfcfc9fb9a8d61ed74fa94b5e32ccc03305797eea461658303df5805578ef',
- },
- '55180a2527901ed4d7ef8f4d61d38d3543b0e7ac3aba04e7f4d3165c3320a6da': {
- tokenTicker: 'cARRRl',
- tokenName: 'Dachshund Pirate Token',
- tokenDocumentUrl: 'https://cashtab.com/',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- '55180a2527901ed4d7ef8f4d61d38d3543b0e7ac3aba04e7f4d3165c3320a6da',
- },
- '6a9305a13135625f4b533256e8d2e21a7343005331e1839348a39040f61e09d3': {
- tokenTicker: 'SCOOG',
- tokenName: 'Scoogi Alpha',
- tokenDocumentUrl: 'cashtab.com',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- '6a9305a13135625f4b533256e8d2e21a7343005331e1839348a39040f61e09d3',
- },
- '48090bcd94cf53289ce84e1d4aeb8035f6ea7d80d37baa6343d0f71e7d67a3ef': {
- tokenTicker: 'WP5',
- tokenName: 'Webpack 5',
- tokenDocumentUrl: 'boomertakes.com',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- '48090bcd94cf53289ce84e1d4aeb8035f6ea7d80d37baa6343d0f71e7d67a3ef',
- },
- '27277911435164c511c7dbc3ef00ba5ce9edf8c1ccab93681cb0ad984b801ef1': {
- tokenTicker: 'SCOOG',
- tokenName: 'Scoogi Alpha',
- tokenDocumentUrl: 'cashtab.com',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- '27277911435164c511c7dbc3ef00ba5ce9edf8c1ccab93681cb0ad984b801ef1',
- },
- 'a3add503bba986398b39fa2200ce658423a597b4f7fe9de04a2da4501f8b05a3': {
- tokenTicker: 'SCOOG',
- tokenName: 'Scoogi Gamma',
- tokenDocumentUrl: 'cashtab.com',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- 'a3add503bba986398b39fa2200ce658423a597b4f7fe9de04a2da4501f8b05a3',
- },
- '8b402aab7682e1cef3da83bf754ae722cc95c3118dfe6e2149267f9a9e2ecc63': {
- tokenTicker: 'AUG5',
- tokenName: 'August 5',
- tokenDocumentUrl: 'https://cashtab.com/',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- '8b402aab7682e1cef3da83bf754ae722cc95c3118dfe6e2149267f9a9e2ecc63',
- },
- '2502bdc75d3afdce0742505d53e6d50cefb1268d7c2a835c06b701702b79e1b8': {
- tokenTicker: 'SCOOG',
- tokenName: 'Scoogi Epsilon',
- tokenDocumentUrl: 'cashtab.com',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- '2502bdc75d3afdce0742505d53e6d50cefb1268d7c2a835c06b701702b79e1b8',
- },
- 'f29939b961d8f3b27d7826e3f22451fcf9273ac84421312a20148b1e083a5bb0': {
- tokenTicker: 'SCOOG',
- tokenName: 'Scoogi Beta',
- tokenDocumentUrl: 'cashtab.com',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- 'f29939b961d8f3b27d7826e3f22451fcf9273ac84421312a20148b1e083a5bb0',
- },
- 'edb693529851379bcbd75008f78940df8232510e6a1c64d8dc81693ae2a53f66': {
- tokenTicker: 'SCOOG',
- tokenName: 'Scoogi Eta',
- tokenDocumentUrl: 'cashtab.com',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- 'edb693529851379bcbd75008f78940df8232510e6a1c64d8dc81693ae2a53f66',
- },
- 'c70d5f036368e184d2a52389b2f4c2471855aebaccbd418db24d4515ce062dbe': {
- tokenTicker: 'SCOOG',
- tokenName: 'Scoogi Zeta',
- tokenDocumentUrl: 'cashtab.com',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- 'c70d5f036368e184d2a52389b2f4c2471855aebaccbd418db24d4515ce062dbe',
- },
- 'b9877d8f8d2364b983707df905d592f534a3ada18e52aa529a0f72fcc535abf7': {
- tokenTicker: 'SRM',
- tokenName: 'Server Redundancy Mint',
- tokenDocumentUrl: 'https://cashtab.com/',
- tokenDocumentHash: '',
- decimals: 0,
- tokenId:
- 'b9877d8f8d2364b983707df905d592f534a3ada18e52aa529a0f72fcc535abf7',
- },
- '54dc2ecd5251f8dfda4c4f15ce05272116b01326076240e2b9cc0104d33b1484': {
- tokenTicker: 'Alita',
- tokenName: 'Alita',
- tokenDocumentUrl: 'alita.cash',
- tokenDocumentHash: '',
- decimals: 4,
- tokenId:
- '54dc2ecd5251f8dfda4c4f15ce05272116b01326076240e2b9cc0104d33b1484',
- },
- 'cf601c56b58bc05a39a95374a4a865f0a8b56544ea937b30fb46315441717c50': {
- tokenTicker: 'UDT',
- tokenName: 'UpdateTest',
- tokenDocumentUrl: 'https://cashtab.com/',
- tokenDocumentHash: '',
- decimals: 7,
- tokenId:
- 'cf601c56b58bc05a39a95374a4a865f0a8b56544ea937b30fb46315441717c50',
- },
-};
-const calculatedTxHistoryTokenInfoById = new Map();
-const legacyTxHistoryTokenInfoByIdTokenIds = Object.keys(
- legacyTxHistoryTokenInfoById,
-);
-for (const tokenId of legacyTxHistoryTokenInfoByIdTokenIds) {
- const legacyGenesisInfo = JSON.parse(
- JSON.stringify(legacyTxHistoryTokenInfoById[tokenId]),
- );
- // Remove the tokenId key which we do not need stored at the value
- delete legacyGenesisInfo.tokenId;
- calculatedTxHistoryTokenInfoById.set(tokenId, legacyGenesisInfo);
-}
-export const txHistoryTokenInfoById = calculatedTxHistoryTokenInfoById;
-
export const stakingRwd = {
tx: {
txid: 'c8b0783e36ab472f26108007ffa522ee82b79db3777c84b0448f5b9ef35be895',
@@ -8187,15 +7637,7 @@
burnsMintBatons: false,
},
],
- genesisInfo: {
- decimals: 0,
- success: true,
- tokenDocumentHash: '',
- tokenDocumentUrl:
- 'https://www.who.int/emergencies/diseases/novel-coronavirus-2019/covid-19-vaccines',
- tokenName: 'Covid19 Lifetime Immunity',
- tokenTicker: 'NOCOVID',
- },
+ assumedTokenDecimals: false,
etokenAmount: '12',
airdropFlag: false,
airdropTokenId: '',
@@ -8359,15 +7801,7 @@
burnsMintBatons: false,
},
],
- genesisInfo: {
- decimals: 0,
- success: true,
- tokenDocumentHash: '',
- tokenDocumentUrl:
- 'https://www.who.int/emergencies/diseases/novel-coronavirus-2019/covid-19-vaccines',
- tokenName: 'Covid19 Lifetime Immunity',
- tokenTicker: 'NOCOVID',
- },
+ assumedTokenDecimals: false,
etokenAmount: '17',
airdropFlag: false,
airdropTokenId: '',
@@ -8474,14 +7908,7 @@
burnsMintBatons: false,
},
],
- genesisInfo: {
- decimals: 7,
- success: true,
- tokenDocumentHash: '',
- tokenDocumentUrl: 'https://cashtab.com/',
- tokenName: 'UpdateTest',
- tokenTicker: 'UDT',
- },
+ assumedTokenDecimals: false,
airdropFlag: false,
airdropTokenId: '',
opReturnMessage: '',
@@ -8637,14 +8064,7 @@
burnsMintBatons: false,
},
],
- genesisInfo: {
- decimals: 9,
- success: true,
- tokenDocumentHash: '',
- tokenDocumentUrl: 'https://cashtabapp.com/',
- tokenName: 'CashTabBits',
- tokenTicker: 'CTB',
- },
+ assumedTokenDecimals: false,
airdropFlag: false,
airdropTokenId: '',
opReturnMessage: '',
@@ -9474,14 +8894,7 @@
burnsMintBatons: false,
},
],
- genesisInfo: {
- tokenTicker: 'LVV',
- tokenName: 'Lambda Variant Variants',
- tokenDocumentUrl: 'https://cashtabapp.com/',
- tokenDocumentHash: '',
- decimals: 0,
- success: true,
- },
+ assumedTokenDecimals: false,
airdropFlag: false,
airdropTokenId: '',
opReturnMessage: '',
@@ -9615,17 +9028,7 @@
burnsMintBatons: false,
},
],
- genesisInfo: {
- tokenTicker: 'WDT',
- tokenName:
- 'Test Token With Exceptionally Long Name For CSS And Style Revisions',
- tokenDocumentUrl:
- 'https://www.ImpossiblyLongWebsiteDidYouThinkWebDevWouldBeFun.org',
- tokenDocumentHash:
- '85b591c15c9f49531e39fcfeb2a5a26b2bd0f7c018fb9cd71b5d92dfb732d5cc',
- decimals: 7,
- success: true,
- },
+ assumedTokenDecimals: false,
airdropFlag: false,
airdropTokenId: '',
opReturnMessage: '',
@@ -9781,14 +9184,7 @@
burnsMintBatons: false,
},
],
- genesisInfo: {
- tokenTicker: 'CTB',
- tokenName: 'CashTabBits',
- tokenDocumentUrl: 'https://cashtabapp.com/',
- tokenDocumentHash: '',
- decimals: 9,
- success: true,
- },
+ assumedTokenDecimals: false,
airdropFlag: false,
airdropTokenId: '',
opReturnMessage: '',
@@ -10483,3 +9879,8795 @@
xecAmount: 0,
},
};
+
+/**
+ * Mock chronik.token(tokenId) and chronik.tx(tokenId) for
+ * several slpv1 tokens
+ *
+ * The below mocks
+ * chronikSlpTokens, chronikTokenMocks, and mockLargeTokenCache are all related
+ *
+ * chronikSlpUtxos - large array of slp tokens as Cashtab would store them (less the address, not needed in these tests)
+ * chronikTokenMocks - mock chronik calls required to get token info
+ * mockLargeTokenCache - expected token cache for a wallet with all of these tokens
+ * keyValueBalanceArray - key value array of expected tokens => tokenBalance map
+ *
+ * Useful for testing wallet structure org functions
+ */
+
+export const chronikSlpUtxos = [
+ {
+ outpoint: {
+ txid: '525457276f1b6984170c9b35a8312d4988fce495723eabadd2afcdb3b872b2f1',
+ outIdx: 1,
+ },
+ blockHeight: 680782,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ 'bf24d955f59351e738ecd905966606a6837e478e1982943d724eab10caad82fd',
+ tokenType: [Object],
+ amount: '1',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: 'b35c502f388cdfbdd6841b7a73e973149b3c8deca76295a3e4665939e0562796',
+ outIdx: 2,
+ },
+ blockHeight: 681191,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ 'dd84ca78db4d617221b58eabc6667af8fe2f7eadbfcc213d35be9f1b419beb8d',
+ tokenType: [Object],
+ amount: '1',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '7987f68aa70d29ac0e0ac31d74354a8b1cd515c9893f6a5cdc7a3bf505e08b05',
+ outIdx: 1,
+ },
+ blockHeight: 685181,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e',
+ tokenType: [Object],
+ amount: '1',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '9e8483407944d9b75c331ebd6178b0cabc3e8c3b5bb0492b7b2256c8740f655a',
+ outIdx: 1,
+ },
+ blockHeight: 709251,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ 'f36e1b3d9a2aaf74f132fef3834e9743b945a667a4204e761b85f2e7b65fd41a',
+ tokenType: [Object],
+ amount: '1000',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '18c0360f0db5399223cbed48f55c4cee9d9914c8a4a7dedcf9172a36201e9896',
+ outIdx: 1,
+ },
+ blockHeight: 717055,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ 'e859eeb52e7afca6217fb36784b3b6d3c7386a52f391dd0d00f2ec03a5e8e77b',
+ tokenType: [Object],
+ amount: '10',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '0bd0c49135b94b99989ec3b0396020a96fcbe2925bb25c40120dc047c0a097ec',
+ outIdx: 1,
+ },
+ blockHeight: 726826,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '44929ff3b1fc634f982fede112cf12b21199a2ebbcf718412a38de9177d77168',
+ tokenType: [Object],
+ amount: '2',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '8f645ce7b231a3ea81168229c1b6a1157e8a58fb8a8a127a80efc2ed39c4f72e',
+ outIdx: 1,
+ },
+ blockHeight: 727176,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ 'b40d1f6acdb6ee68d7eca0167fe2753c076bc309b2e3b1af8bff70ca34b945b0',
+ tokenType: [Object],
+ amount: '5000',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '3703d46c5c52b0e55f3bd549e14c5617a47f802413f4acf7a27545437eb51a38',
+ outIdx: 1,
+ },
+ blockHeight: 741200,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '8ead21ce4b3b9e7b57607b97b65b5013496dc6e3dfdea162c08ce7265a66ebc8',
+ tokenType: [Object],
+ amount: '100000000',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '40d4c93e82b82f5768e93a0da9c3c065856733d136876a90182590c8e115d1c4',
+ outIdx: 1,
+ },
+ blockHeight: 757311,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '77ec4036ef8546ac46df6d3a5374e961216f92624627eaeef5d2e1a253df9fc6',
+ tokenType: [Object],
+ amount: '116',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '696265ced15b8fdbacfa1a4f5e779575ff5faaf3ff4ad09e5691b2ed4cf50a84',
+ outIdx: 2,
+ },
+ blockHeight: 758209,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ 'da9460ce4b1c92b4f6ef4e4a6bc2d05539f49d02b17681389d9ce22b8dca50f0',
+ tokenType: [Object],
+ amount: '311',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '28428450ffa24dae7427ba8456fd5465b0da478fd183be845a27fdc0205df45f',
+ outIdx: 1,
+ },
+ blockHeight: 758645,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '54dc2ecd5251f8dfda4c4f15ce05272116b01326076240e2b9cc0104d33b1484',
+ tokenType: [Object],
+ amount: '4588000000',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '9a3522b610d153934b951cd6dd91676e5e4f3020531bd8a2e8015193c383029e',
+ outIdx: 1,
+ },
+ blockHeight: 758887,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '54dc2ecd5251f8dfda4c4f15ce05272116b01326076240e2b9cc0104d33b1484',
+ tokenType: [Object],
+ amount: '229400000',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: 'cf601c56b58bc05a39a95374a4a865f0a8b56544ea937b30fb46315441717c50',
+ outIdx: 1,
+ },
+ blockHeight: 759037,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ 'cf601c56b58bc05a39a95374a4a865f0a8b56544ea937b30fb46315441717c50',
+ tokenType: [Object],
+ amount: '7777777777',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: 'e3752bd648b2234957690ae408b08fe4eaf95912aa1b9790dc569c99e2a1f37a',
+ outIdx: 1,
+ },
+ blockHeight: 759839,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '54dc2ecd5251f8dfda4c4f15ce05272116b01326076240e2b9cc0104d33b1484',
+ tokenType: [Object],
+ amount: '229400000',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: 'b808f6a831dcdfda2bd4c5f857f94e1a746a4effeda6a5ad742be6137884a4fb',
+ outIdx: 1,
+ },
+ blockHeight: 760076,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ 'acba1d7f354c6d4d001eb99d31de174e5cea8a31d692afd6e7eb8474ad541f55',
+ tokenType: [Object],
+ amount: '123456789',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '8b8a15bbcc69df215ac45bab882d8f122f3e09405c3ac093d12cd2dd79a141ec',
+ outIdx: 1,
+ },
+ blockHeight: 764737,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '0916e71779c9de7ee125741d3f5ab01f556356dbc86fd327a24f1e9e22ebc917',
+ tokenType: [Object],
+ amount: '1699',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '54cd8c25ff891a80f8276150244f052db7649a477eae2600ff17b49104258ee3',
+ outIdx: 2,
+ },
+ blockHeight: 767640,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb',
+ tokenType: [Object],
+ amount: '99999998',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '9d2b752d3d0bb0b6ffeab531b8c3ca0b2af56c116ad13fe7e799b0ab96348b29',
+ outIdx: 1,
+ },
+ blockHeight: 767649,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ 'ccf5fe5a387559c8ab9efdeb0c0ef1b444e677298cfddf07671245ce3cb3c79f',
+ tokenType: [Object],
+ amount: '100000000',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '7c75493d6e710173192ed1892273376ef54b755880cd5cb4aec3e2db309a1cce',
+ outIdx: 2,
+ },
+ blockHeight: 768787,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '7f8889682d57369ed0e32336f8b7e0ffec625a35cca183f4e81fde4e71a538a1',
+ tokenType: [Object],
+ amount: '1',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: 'a4e4438f1e5d2c680c5ad877a9c2e75b5eea05f7fc8a17e0cdb348f315e7dc49',
+ outIdx: 1,
+ },
+ blockHeight: 769675,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ 'f36e1b3d9a2aaf74f132fef3834e9743b945a667a4204e761b85f2e7b65fd41a',
+ tokenType: [Object],
+ amount: '200',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '019609426f88a9c2f13de980c7f7b2828c868fc6d53b1673421096b701ceae1a',
+ outIdx: 2,
+ },
+ blockHeight: 770363,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ 'bdb3b4215ca0622e0c4c07655522c376eaa891838a82f0217fa453bb0595a37c',
+ tokenType: [Object],
+ amount: '9900',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '48ec9f7a4b7dfd5fbd419a70b748ded04e167778784e65a39c8edeb496b1f1de',
+ outIdx: 1,
+ },
+ blockHeight: 770363,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '157e0cdef5d5c51bdea00eac9ab821d809bb9d03cf98da85833614bedb129be6',
+ tokenType: [Object],
+ amount: '82',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '07646eddeaa7c97431f3cf62c7ba4714473f4c7a6611740b9cac5d86c00f9a38',
+ outIdx: 2,
+ },
+ blockHeight: 770387,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ 'bdb3b4215ca0622e0c4c07655522c376eaa891838a82f0217fa453bb0595a37c',
+ tokenType: [Object],
+ amount: '9989',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: 'c39cd34c68ccb43cf640dd09f639c1e0b46d47224722ce5f26151ace40c663b3',
+ outIdx: 2,
+ },
+ blockHeight: 772042,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ 'ccf5fe5a387559c8ab9efdeb0c0ef1b444e677298cfddf07671245ce3cb3c79f',
+ tokenType: [Object],
+ amount: '42300000000',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: 'd24e98159db1772819a76f1249f7190a9edb9924d0f7c5336b260f68b245a83a',
+ outIdx: 2,
+ },
+ blockHeight: 774343,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '1101bd5d7b6bbc3176fb2b93d08e76ab532b04ff731d71502249e3cb9b6fcb1a',
+ tokenType: [Object],
+ amount: '999882000000000',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: 'feafd053d4166601d42949a768b9c3e8ee1f27912fc84b6190aeb022fba7fa39',
+ outIdx: 2,
+ },
+ blockHeight: 776118,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '6e24e89b6d5284138c69777527760500b99614631bca7f2a5c38f4648dae9524',
+ tokenType: [Object],
+ amount: '999999878',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '886da7de5f0143c8be863962e7345ea615cee30caec7532824641d0fd40cc5f2',
+ outIdx: 1,
+ },
+ blockHeight: 780736,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '4bd147fc5d5ff26249a9299c46b80920c0b81f59a60e05428262160ebee0b0c3',
+ tokenType: [Object],
+ amount: '2',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '886da7de5f0143c8be863962e7345ea615cee30caec7532824641d0fd40cc5f2',
+ outIdx: 2,
+ },
+ blockHeight: 780736,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '4bd147fc5d5ff26249a9299c46b80920c0b81f59a60e05428262160ebee0b0c3',
+ tokenType: [Object],
+ amount: '23',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: 'ce95a91b9d7ddc6efc6273f70d398cb18aeafe99fd75de6301406786d4d8be54',
+ outIdx: 2,
+ },
+ blockHeight: 780736,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '4bd147fc5d5ff26249a9299c46b80920c0b81f59a60e05428262160ebee0b0c3',
+ tokenType: [Object],
+ amount: '65',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: 'c04ae7f139eb16023a70d1bb39b1ae8745667edb09833e994a5b4d48976a111d',
+ outIdx: 2,
+ },
+ blockHeight: 782774,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ 'b9877d8f8d2364b983707df905d592f534a3ada18e52aa529a0f72fcc535abf7',
+ tokenType: [Object],
+ amount: '3',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: 'f2859d3d19e741bb40e9207cc1109db730ca69c458c6c204d14c2ebe7603c966',
+ outIdx: 2,
+ },
+ blockHeight: 783389,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ 'acba1d7f354c6d4d001eb99d31de174e5cea8a31d692afd6e7eb8474ad541f55',
+ tokenType: [Object],
+ amount: '123456844',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: 'e71fe380b0dd838f4ef1c5bb4d5d33fc9d8932c3f9096211f6069805828e7f63',
+ outIdx: 2,
+ },
+ blockHeight: 783638,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ 'b8f2a9e767a0be7b80c7e414ef2534586d4da72efddb39a4e70e501ab73375cc',
+ tokenType: [Object],
+ amount: '8988',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: 'ff5f864cfe257905e18f1db2dfd7f31b483e0ecdfe9a91391d21dd44a28e1803',
+ outIdx: 2,
+ },
+ blockHeight: 783638,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '4bd147fc5d5ff26249a9299c46b80920c0b81f59a60e05428262160ebee0b0c3',
+ tokenType: [Object],
+ amount: '995921',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '70ead4d94c43fe8c5576bb2528fd54380d8356f632ac962b1e03fb287607dfd4',
+ outIdx: 1,
+ },
+ blockHeight: 783693,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '70ead4d94c43fe8c5576bb2528fd54380d8356f632ac962b1e03fb287607dfd4',
+ tokenType: [Object],
+ amount: '100',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: 'ff9aa6eebcd1331f8684d53b441cfa3060a4ffc403b417d5728de8ab231f5516',
+ outIdx: 1,
+ },
+ blockHeight: 783694,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ 'ff9aa6eebcd1331f8684d53b441cfa3060a4ffc403b417d5728de8ab231f5516',
+ tokenType: [Object],
+ amount: '100',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: 'f077f207fc8a8557e5f0ffc6021685ab4b357e9b92d2b5c4192dcb7760ee6e29',
+ outIdx: 1,
+ },
+ blockHeight: 783695,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ 'f077f207fc8a8557e5f0ffc6021685ab4b357e9b92d2b5c4192dcb7760ee6e29',
+ tokenType: [Object],
+ amount: '100',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: 'c2c6b5a7b37e983c4e193900fcde2b8139ef4c3db2fd9689c354f6ea65354f15',
+ outIdx: 2,
+ },
+ blockHeight: 784246,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '3adbf501e21c711d20118e003711168eb39f560c01f4c6d6736fa3f3fceaa577',
+ tokenType: [Object],
+ amount: '999998999',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '27dee7774fdf4d5a268e498e6d9665bff2251a7049ef71b6d5671f395d8bd694',
+ outIdx: 1,
+ },
+ blockHeight: 784262,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '4bd147fc5d5ff26249a9299c46b80920c0b81f59a60e05428262160ebee0b0c3',
+ tokenType: [Object],
+ amount: '1',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '29793cfa3c533063211ad15f0567e6b815aab555aa8356388e2c96561d971644',
+ outIdx: 2,
+ },
+ blockHeight: 784460,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '3de671a7107d3803d78f7f4a4e5c794d0903a8d28d16076445c084943c1e2db8',
+ tokenType: [Object],
+ amount: '2100',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: 'f6090755d5dcf233c1cf749c1433eabc0fb0722601101e981df67d44219325e6',
+ outIdx: 2,
+ },
+ blockHeight: 787547,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '20a0b9337a78603c6681ed2bc541593375535dcd9979196620ce71f233f2f6f8',
+ tokenType: [Object],
+ amount: '2998978719999999999',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: 'e4d80b015e75fe2e54b5ef10571ce78c17086f96a7876d466f92d8c2a8c92b64',
+ outIdx: 2,
+ },
+ blockHeight: 792712,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '4db25a4b2f0b57415ce25fab6d9cb3ac2bbb444ff493dc16d0615a11ad06c875',
+ tokenType: [Object],
+ amount: '999824',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '6ffcc83e76226bd32821cc6862ce9b363b22594247a4e73ccf3701b0023592b2',
+ outIdx: 2,
+ },
+ blockHeight: 800716,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '98183238638ecb4ddc365056e22de0e8a05448c1e6084bae247fae5a74ad4f48',
+ tokenType: [Object],
+ amount: '999977636',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: 'fb70df00c07749082756054522d3f08691fd9caccd0e0abf736df23d22845a6e',
+ outIdx: 2,
+ },
+ blockHeight: 800716,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d',
+ tokenType: [Object],
+ amount: '5235120528888890',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '8f6676b602a9f074f10a7561fb7256bbce3b103a119f809a05485e42489d2233',
+ outIdx: 2,
+ },
+ blockHeight: 802851,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ 'b977630ae1b4a0fe3ab12385fdaaffd974e5bd352f2a817ce135c1ee6005a35d',
+ tokenType: [Object],
+ amount: '75',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: 'b7f225b4c4e055a35c1e08ce5eea7c1f3cf53c44662d6d95b631504634b1a3d9',
+ outIdx: 2,
+ },
+ blockHeight: 802851,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ 'b977630ae1b4a0fe3ab12385fdaaffd974e5bd352f2a817ce135c1ee6005a35d',
+ tokenType: [Object],
+ amount: '652',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '8a172dd9cd9eda533cdc731449c4d8728ab1924b843e5d5d2eda63535f7473d4',
+ outIdx: 2,
+ },
+ blockHeight: 803616,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '6376cae692cf0302ecdd63234c14cbb2b21cec75ab538335f90254cfb3ed44cc',
+ tokenType: [Object],
+ amount: '78',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '1127651ed9d822cd4ba3ff30211d064116575fdb692c1352e59cab841e8caf4d',
+ outIdx: 2,
+ },
+ blockHeight: 803741,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '6376cae692cf0302ecdd63234c14cbb2b21cec75ab538335f90254cfb3ed44cc',
+ tokenType: [Object],
+ amount: '43',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: 'a490c805218091549b2d802d6f0391c880cacd5145d0c516f62433637e49bd15',
+ outIdx: 1,
+ },
+ blockHeight: 824524,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d',
+ tokenType: [Object],
+ amount: '330000000',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: 'f4f21422dbf0ad5fe455994ee4d791a9d2e127fdfb46aa87abc3c250312fbbd0',
+ outIdx: 2,
+ },
+ blockHeight: 824524,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ 'bd1acc4c986de57af8d6d2a64aecad8c30ee80f37ae9d066d758923732ddc9ba',
+ tokenType: [Object],
+ amount: '24999698951',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: 'd7c43e4eb6d341ac69b52f89125887b17d00a16872c01a9d47b39fd4e55d50cf',
+ outIdx: 1,
+ },
+ blockHeight: 825739,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '639a8dba34788ff3ebd3977d4ac045825394285ee648bb1d159e1c12b787ff25',
+ tokenType: [Object],
+ amount: '1000000000',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '2c791301f75284f8ae86707ab87f24f2394e4b92d81a4f59bed52b56eaf452e3',
+ outIdx: 1,
+ },
+ blockHeight: 825842,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '45f0ff5cae7e89da6b96c26c8c48a959214c5f0e983e78d0925f8956ca8848c6',
+ tokenType: [Object],
+ amount: '5344445',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: 'a6050bea718f77e7964d140c4bb89cd88a1816eed1633f19d097835d5fa48df5',
+ outIdx: 1,
+ },
+ blockHeight: 832625,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ 'a6050bea718f77e7964d140c4bb89cd88a1816eed1633f19d097835d5fa48df5',
+ tokenType: [Object],
+ amount: '1000',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: 'a96f605eaf8b97889a73c5ee0e36597239f7fb17833a28076d2f3ca863f7ccfc',
+ outIdx: 1,
+ },
+ blockHeight: 832788,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ 'b19b4c83056f6e3dace0e786446a8ccd73f22cfc42c3013808c532ab43490a14',
+ tokenType: [Object],
+ amount: '10000000000000000000',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '423e24bf0715cfb80727e5e7a6ff7b9e37cb2f555c537ab06fdc7fd9b3a0ba3a',
+ outIdx: 1,
+ },
+ blockHeight: 833612,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ 'fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa',
+ tokenType: [Object],
+ amount: '10000000000',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '5167318214db9876a4095cae6d1d3b3e7a9af5467ee0e8344715ac12a2a871a9',
+ outIdx: 1,
+ },
+ blockHeight: 834541,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '79c5a1cec698350dd93f645fcae8d6ff3902b7cdc582839dfface3cb0c83d823',
+ tokenType: [Object],
+ amount: '9899',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '8d0c0b705122e197e47c338f017bef3456ae27deb5da93aaf2da0d480d1cea49',
+ outIdx: 2,
+ },
+ blockHeight: 835070,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ tokenType: [Object],
+ amount: '3325',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '01d63c4f4cb496829a6743f7b1805d086ea3877a1dd34b3f92ffba2c9c99f896',
+ outIdx: 1,
+ },
+ blockHeight: 835482,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '01d63c4f4cb496829a6743f7b1805d086ea3877a1dd34b3f92ffba2c9c99f896',
+ tokenType: [Object],
+ amount: '21000000',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: 'e93ea2ae7e4c7026e3fc55b431ff5c92173c5e24119c477981f1942e100be990',
+ outIdx: 2,
+ },
+ blockHeight: 835635,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ tokenType: [Object],
+ amount: '39',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: 'f18a297d1f2ab656ca284655704e07cf8ea269739f4d3af64c2dbd18bfe4d8ee',
+ outIdx: 1,
+ },
+ blockHeight: 836041,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '666c4318d1f7fef5f2c698262492c519018d4e9130f95d05f6be9f0fb7149e96',
+ tokenType: [Object],
+ amount: '94',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: 'f37027d1560c62a845d15025e418bdd1d0b127bf6fcfb83dfd9e872eb66d0d09',
+ outIdx: 2,
+ },
+ blockHeight: 836041,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ 'b132878bfa81cf1b9e19192045ed4c797b10944cc17ae07da06aed3d7b566cb7',
+ tokenType: [Object],
+ amount: '4',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '2358817d41cf41568e7431c2b4eec8e0dc882f6db0fcf824b5bc4b80c522a358',
+ outIdx: 1,
+ },
+ blockHeight: 836444,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ tokenType: [Object],
+ amount: '22',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '583f0379a82249f86e1c19fef574ae3a499aa8d4b1980884ddf1c15d8bd50db3',
+ outIdx: 1,
+ },
+ blockHeight: 836456,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ 'b132878bfa81cf1b9e19192045ed4c797b10944cc17ae07da06aed3d7b566cb7',
+ tokenType: [Object],
+ amount: '1',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '5b115c352a487503755bbb93582ff39e1095d698fa303c7dd31bbf19c4bbf39a',
+ outIdx: 1,
+ },
+ blockHeight: 836457,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ tokenType: [Object],
+ amount: '11',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '914827ddc2087db0e8ca8aed3c2a701f5873ea2f96f3837d6dce6f24ab53f854',
+ outIdx: 1,
+ },
+ blockHeight: 836458,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ tokenType: [Object],
+ amount: '1',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '9404761d1a01cca11c29eb8ed9ddc63966526d0eaa54f148e8862ab3e884132f',
+ outIdx: 1,
+ },
+ blockHeight: 836820,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '9404761d1a01cca11c29eb8ed9ddc63966526d0eaa54f148e8862ab3e884132f',
+ tokenType: [Object],
+ amount: '55000000000',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '0b1f0ecfe27292fb9f7031400d27d42b15ff13950635333c1a2774ba6e7eaa83',
+ outIdx: 1,
+ },
+ blockHeight: 837493,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '16b12bbacdbb8c8a799adbfd782bfff9843c1f9b0be148eaae02a1a7f74f95c4',
+ tokenType: [Object],
+ amount: '844601876543211',
+ isMintBaton: false,
+ },
+ },
+ {
+ outpoint: {
+ txid: '2f9b8eca06f9e753769b450a2929d9956d70eee8047daf629591fc5ed29d8aa5',
+ outIdx: 2,
+ },
+ blockHeight: 837494,
+ isCoinbase: false,
+ value: 546,
+ isFinal: true,
+ token: {
+ tokenId:
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ tokenType: [Object],
+ amount: '885',
+ isMintBaton: false,
+ },
+ },
+];
+export const chronikTokenMocks = {
+ 'bf24d955f59351e738ecd905966606a6837e478e1982943d724eab10caad82fd': {
+ token: {
+ tokenId:
+ 'bf24d955f59351e738ecd905966606a6837e478e1982943d724eab10caad82fd',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'ST',
+ tokenName: 'ST',
+ url: 'developer.bitcoin.com',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 625949,
+ hash: '00000000000000000071fae486bb8a703faacb1fdcc613bd024ac1c0870e16d8',
+ timestamp: 1583919726,
+ },
+ },
+ tx: {
+ txid: 'bf24d955f59351e738ecd905966606a6837e478e1982943d724eab10caad82fd',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: 'ac18fee0b9e2cb96fff3e1387f619f3fa010d5ac61a7f26f00b5d8ccb35dfa15',
+ outIdx: 13,
+ },
+ inputScript:
+ '483045022100da06aaec82dccaea628d08909b01820382f6d746970e31716c9cd14d191dd54902204ad630ec7727d6b2ad183dfa6585baa1fd2fe6fed642d8adabfa3eda495969cc412103317bf85b65f7443e4c0308064a2104a617bfe0467b4e8b6f3b01a8f4e78aaa7d',
+ value: 7055848,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91459b025ac71f8d6efc7e08fcad47cfab7c063c23a88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e4553495302535402535415646576656c6f7065722e626974636f696e2e636f6d4c000100010208000000000000018f',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a9142ba1f72161a53720df933ea9b2116351c4162abd88ac',
+ token: {
+ tokenId:
+ 'bf24d955f59351e738ecd905966606a6837e478e1982943d724eab10caad82fd',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '399',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '634ddf7468ff8fb493dcd1324f47452c0f668507863058182f861dce85a0dd1a',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a9142ba1f72161a53720df933ea9b2116351c4162abd88ac',
+ token: {
+ tokenId:
+ 'bf24d955f59351e738ecd905966606a6837e478e1982943d724eab10caad82fd',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '0',
+ isMintBaton: true,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '691b1af9b93a91f6c1974269d3167bfe440f304c610e099ca5ce4d24da60afa1',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 7054427,
+ outputScript:
+ '76a91459b025ac71f8d6efc7e08fcad47cfab7c063c23a88ac',
+ spentBy: {
+ txid: '634ddf7468ff8fb493dcd1324f47452c0f668507863058182f861dce85a0dd1a',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 328,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ 'bf24d955f59351e738ecd905966606a6837e478e1982943d724eab10caad82fd',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 625949,
+ hash: '00000000000000000071fae486bb8a703faacb1fdcc613bd024ac1c0870e16d8',
+ timestamp: 1583919726,
+ },
+ },
+ calculated: {
+ genesisSupply: '399',
+ genesisOutputScripts: [
+ '76a9142ba1f72161a53720df933ea9b2116351c4162abd88ac',
+ ],
+ genesisMintBatons: 1,
+ },
+ },
+ 'dd84ca78db4d617221b58eabc6667af8fe2f7eadbfcc213d35be9f1b419beb8d': {
+ token: {
+ tokenId:
+ 'dd84ca78db4d617221b58eabc6667af8fe2f7eadbfcc213d35be9f1b419beb8d',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'TAP',
+ tokenName: 'Thoughts and Prayers',
+ url: '',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 580703,
+ hash: '000000000000000000d4d1d3ecb1a6134e3e4bb2ffd457f267e5e44139f2505f',
+ timestamp: 1556742931,
+ },
+ },
+ tx: {
+ txid: 'dd84ca78db4d617221b58eabc6667af8fe2f7eadbfcc213d35be9f1b419beb8d',
+ version: 1,
+ inputs: [
+ {
+ prevOut: {
+ txid: '7b4717e7c27033516a13811549b9fcccc56c20de0cb195ab04525334c5e5d308',
+ outIdx: 3,
+ },
+ inputScript:
+ '4730440220790564ba25ea20d058d7175b36659d8635fd9df0e6b025cabebbe63a6b1ff93102200e31ed7c18b594cd4a141b7e44bca5374eb1d357139aebeeccc1317c2666f8e3412102975d8bd9f427a3af5391d701e7eeb39087e9b2be70c166c84864b3ac5bc72ab4',
+ value: 314238,
+ sequenceNo: 4294967294,
+ outputScript:
+ '76a9148b416c67003eb796880cbc0ad08d5130774974bc88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e45534953035441501454686f756768747320616e6420507261796572734c004c00010001020800000000000f4240',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a914458ea8631f32b296df9ab677b6e8a7e422e7161e88ac',
+ token: {
+ tokenId:
+ 'dd84ca78db4d617221b58eabc6667af8fe2f7eadbfcc213d35be9f1b419beb8d',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '1000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '29f125b70e67a336078e1e5ed87934da07d92a15e3a5884bc3efdee861327dc9',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a914458ea8631f32b296df9ab677b6e8a7e422e7161e88ac',
+ token: {
+ tokenId:
+ 'dd84ca78db4d617221b58eabc6667af8fe2f7eadbfcc213d35be9f1b419beb8d',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '0',
+ isMintBaton: true,
+ entryIdx: 0,
+ },
+ },
+ {
+ value: 312819,
+ outputScript:
+ '76a914d74575d2af329d25f44863d6c50675d26ad440ac88ac',
+ spentBy: {
+ txid: '29f125b70e67a336078e1e5ed87934da07d92a15e3a5884bc3efdee861327dc9',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 580702,
+ timeFirstSeen: 0,
+ size: 326,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ 'dd84ca78db4d617221b58eabc6667af8fe2f7eadbfcc213d35be9f1b419beb8d',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 580703,
+ hash: '000000000000000000d4d1d3ecb1a6134e3e4bb2ffd457f267e5e44139f2505f',
+ timestamp: 1556742931,
+ },
+ },
+ calculated: {
+ genesisSupply: '1000000',
+ genesisOutputScripts: [
+ '76a914458ea8631f32b296df9ab677b6e8a7e422e7161e88ac',
+ ],
+ genesisMintBatons: 1,
+ },
+ },
+ '50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e': {
+ token: {
+ tokenId:
+ '50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'TBC',
+ tokenName: 'tabcash',
+ url: 'https://cashtabapp.com/',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 674143,
+ hash: '000000000000000034c77993a35c74fe2dddace27198681ca1e89e928d0c2fff',
+ timestamp: 1613859311,
+ },
+ },
+ tx: {
+ txid: '50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: 'be38b0488679e25823b7a72b925ac695a7b486e7f78122994b913f3079b0b939',
+ outIdx: 2,
+ },
+ inputScript:
+ '483045022100e28006843eb071ec6d8dd105284f2ca625a28f4dc85418910b59a5ab13fc6c2002205921fb12b541d1cd1a63e7e012aca5735df3398525f64bac04337d21029413614121034509251caa5f01e2787c436949eb94d71dcc451bcde5791ae5b7109255f5f0a3',
+ value: 91048,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a914b8d9512d2adf8b4e70c45c26b6b00d75c28eaa9688ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e455349530354424307746162636173681768747470733a2f2f636173687461626170702e636f6d2f4c0001000102080000000000000064',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a914b8d9512d2adf8b4e70c45c26b6b00d75c28eaa9688ac',
+ token: {
+ tokenId:
+ '50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '100',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '618d0dd8c0c5fa5a34c6515c865dd72bb76f8311cd6ee9aef153bab20dabc0e6',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a914b8d9512d2adf8b4e70c45c26b6b00d75c28eaa9688ac',
+ token: {
+ tokenId:
+ '50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '0',
+ isMintBaton: true,
+ entryIdx: 0,
+ },
+ },
+ {
+ value: 89406,
+ outputScript:
+ '76a914b8d9512d2adf8b4e70c45c26b6b00d75c28eaa9688ac',
+ spentBy: {
+ txid: '618d0dd8c0c5fa5a34c6515c865dd72bb76f8311cd6ee9aef153bab20dabc0e6',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 336,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 674143,
+ hash: '000000000000000034c77993a35c74fe2dddace27198681ca1e89e928d0c2fff',
+ timestamp: 1613859311,
+ },
+ },
+ calculated: {
+ genesisSupply: '100',
+ genesisOutputScripts: [
+ '76a914b8d9512d2adf8b4e70c45c26b6b00d75c28eaa9688ac',
+ ],
+ genesisMintBatons: 1,
+ },
+ },
+ 'f36e1b3d9a2aaf74f132fef3834e9743b945a667a4204e761b85f2e7b65fd41a': {
+ token: {
+ tokenId:
+ 'f36e1b3d9a2aaf74f132fef3834e9743b945a667a4204e761b85f2e7b65fd41a',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'POW',
+ tokenName: 'ProofofWriting.com Token',
+ url: 'https://www.proofofwriting.com/26',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 685949,
+ hash: '0000000000000000436e71d5291d2fb067decc838dcb85a99ff6da1d28b89fad',
+ timestamp: 1620712051,
+ },
+ },
+ tx: {
+ txid: 'f36e1b3d9a2aaf74f132fef3834e9743b945a667a4204e761b85f2e7b65fd41a',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '33938d6bd403e4ffef94de3e9e2ba487f095dcba3544ac8fad4a93808cea0116',
+ outIdx: 1,
+ },
+ inputScript:
+ '483045022100dad1d237b541b4a4d29197dbb01fa9755c2e17bbafb42855f38442b428f0df6b02205772d3fb00b7a053b07169e1534770c091fce42b9e1d63199f46ff89856b3fc6412102ceb4a6eca1eec20ff8e7780326932e8d8295489628c7f2ec9acf8f37f639235e',
+ value: 49998867,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91485bab3680833cd9b3cc60953344fa740a2235bbd88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e4553495303504f571850726f6f666f6657726974696e672e636f6d20546f6b656e2168747470733a2f2f7777772e70726f6f666f6677726974696e672e636f6d2f32364c0001004c000800000000000f4240',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91485bab3680833cd9b3cc60953344fa740a2235bbd88ac',
+ token: {
+ tokenId:
+ 'f36e1b3d9a2aaf74f132fef3834e9743b945a667a4204e761b85f2e7b65fd41a',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '1000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '69238630eb9e6a9864bf6970ff5d326800cea41a819feebecfe1a6f0ed651f5c',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 49997563,
+ outputScript:
+ '76a91485bab3680833cd9b3cc60953344fa740a2235bbd88ac',
+ spentBy: {
+ txid: '3c665488929f852d93a5dfb6e4b4df7bc8f7a25fb4a2480d39e3de7a30437f69',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 329,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ 'f36e1b3d9a2aaf74f132fef3834e9743b945a667a4204e761b85f2e7b65fd41a',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 685949,
+ hash: '0000000000000000436e71d5291d2fb067decc838dcb85a99ff6da1d28b89fad',
+ timestamp: 1620712051,
+ },
+ },
+ calculated: {
+ genesisSupply: '1000000',
+ genesisOutputScripts: [
+ '76a91485bab3680833cd9b3cc60953344fa740a2235bbd88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ 'e859eeb52e7afca6217fb36784b3b6d3c7386a52f391dd0d00f2ec03a5e8e77b': {
+ token: {
+ tokenId:
+ 'e859eeb52e7afca6217fb36784b3b6d3c7386a52f391dd0d00f2ec03a5e8e77b',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'test',
+ tokenName: 'test',
+ url: 'https://cashtab.com/',
+ decimals: 1,
+ hash: '',
+ },
+ block: {
+ height: 717055,
+ hash: '0000000000000000113b17f038ac607eb5ef3c5636bf47088f692695b229d1cf',
+ timestamp: 1639066280,
+ },
+ },
+ tx: {
+ txid: 'e859eeb52e7afca6217fb36784b3b6d3c7386a52f391dd0d00f2ec03a5e8e77b',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: 'c717c4536760db5c9a444ce1c61dee3c692e78d05e62b880cac3f649630bfc63',
+ outIdx: 2,
+ },
+ inputScript:
+ '4730440220633ab93a41745a538c85f71adf934f32b5db2304df9b29af72808ac4f4951b7b022003dc12649727b2c9897c32eadc25255ca9aad1035a24156ae13834dd8c8c557a4121034cdb43b7a1277c4d818dc177aaea4e0bed5d464d240839d5488a278b716facd5',
+ value: 998991395,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a914f5f740bc76e56b77bcab8b4d7f888167f416fc6888ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e45534953047465737404746573741468747470733a2f2f636173687461622e636f6d2f4c0001014c0008000000000000000a',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a914f5f740bc76e56b77bcab8b4d7f888167f416fc6888ac',
+ token: {
+ tokenId:
+ 'e859eeb52e7afca6217fb36784b3b6d3c7386a52f391dd0d00f2ec03a5e8e77b',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '10',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '01e95bbde7013640637b4862812fece434bcfd7a97de852f30ef545add22498b',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 998990326,
+ outputScript:
+ '76a914f5f740bc76e56b77bcab8b4d7f888167f416fc6888ac',
+ spentBy: {
+ txid: '0cfd62634b11ef341fc760bd9ede68f51ed4dfeef5b4b6a42a70620104d5bdaf',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 296,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ 'e859eeb52e7afca6217fb36784b3b6d3c7386a52f391dd0d00f2ec03a5e8e77b',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 717055,
+ hash: '0000000000000000113b17f038ac607eb5ef3c5636bf47088f692695b229d1cf',
+ timestamp: 1639066280,
+ },
+ },
+ calculated: {
+ genesisSupply: '1.0',
+ genesisOutputScripts: [
+ '76a914f5f740bc76e56b77bcab8b4d7f888167f416fc6888ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ '44929ff3b1fc634f982fede112cf12b21199a2ebbcf718412a38de9177d77168': {
+ token: {
+ tokenId:
+ '44929ff3b1fc634f982fede112cf12b21199a2ebbcf718412a38de9177d77168',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'coin',
+ tokenName: 'johncoin',
+ url: 'https://cashtab.com/',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 723121,
+ hash: '00000000000000000ef48c91305f1054ae11c13e07eea788faa1f955aa4620fe',
+ timestamp: 1642724690,
+ },
+ },
+ tx: {
+ txid: '44929ff3b1fc634f982fede112cf12b21199a2ebbcf718412a38de9177d77168',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '5f7c1cdb36ab90951a1c3d2b35eebf1d27bea1a8925fcef6eb4da4be588e27d1',
+ outIdx: 1,
+ },
+ inputScript:
+ '47304402206eaea3002652d5aabec115ed05277034afb2f145e290edaba04ea21f08decc5402205ffcf324eb8d224db589609f51223f426c67e469687fb569dac8e16a0fd2b6c541210235fc1c027cad5ad3972fe9f23b1cc6fb35e68155a9b4eacb0da7ccce7abb8231',
+ value: 9622,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a914a76859a9ce3fdbe80cdc306f71074f08d9e4822f88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e4553495304636f696e086a6f686e636f696e1468747470733a2f2f636173687461622e636f6d2f4c0001004c000800000000000000c3',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a914c1aadc99f96fcfcfe5642ca29a53e701f0b801c388ac',
+ token: {
+ tokenId:
+ '44929ff3b1fc634f982fede112cf12b21199a2ebbcf718412a38de9177d77168',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '195',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '0bd0c49135b94b99989ec3b0396020a96fcbe2925bb25c40120dc047c0a097ec',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 8553,
+ outputScript:
+ '76a914c1aadc99f96fcfcfe5642ca29a53e701f0b801c388ac',
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 300,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '44929ff3b1fc634f982fede112cf12b21199a2ebbcf718412a38de9177d77168',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 723121,
+ hash: '00000000000000000ef48c91305f1054ae11c13e07eea788faa1f955aa4620fe',
+ timestamp: 1642724690,
+ },
+ },
+ calculated: {
+ genesisSupply: '195',
+ genesisOutputScripts: [
+ '76a914c1aadc99f96fcfcfe5642ca29a53e701f0b801c388ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ 'b40d1f6acdb6ee68d7eca0167fe2753c076bc309b2e3b1af8bff70ca34b945b0': {
+ token: {
+ tokenId:
+ 'b40d1f6acdb6ee68d7eca0167fe2753c076bc309b2e3b1af8bff70ca34b945b0',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'KAT',
+ tokenName: 'KA_Test',
+ url: 'https://cashtab.com/',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 727176,
+ hash: '00000000000000000a37233b9ed0520368c58437fc4ce5edbda386a4619440f5',
+ timestamp: 1645146139,
+ },
+ },
+ tx: {
+ txid: 'b40d1f6acdb6ee68d7eca0167fe2753c076bc309b2e3b1af8bff70ca34b945b0',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '159b70d26940f6bf968c086eb526982421169889f3492b0d025ac3cd777ec1cd',
+ outIdx: 0,
+ },
+ inputScript:
+ '473044022020a2a23fd89f4b4d5e4869cb46a760cb577f61d18f895318f2f125bcdc550d1202203bbe0471194c64d33964eddf601fcfbb58b1c5553b2acbade9dc08394c4ad5b841210303329ad4e5b324a95fb05f4e4d6dbcb36b90ef87dc958bd3af49de1b016ed9da',
+ value: 110000,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a914a528a001f9f027aae05085928d0b23172fd4b5a188ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e45534953034b4154074b415f546573741468747470733a2f2f636173687461622e636f6d2f4c0001004c00080000000005f5e100',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a914a528a001f9f027aae05085928d0b23172fd4b5a188ac',
+ token: {
+ tokenId:
+ 'b40d1f6acdb6ee68d7eca0167fe2753c076bc309b2e3b1af8bff70ca34b945b0',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '100000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '8f645ce7b231a3ea81168229c1b6a1157e8a58fb8a8a127a80efc2ed39c4f72e',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 108931,
+ outputScript:
+ '76a914a528a001f9f027aae05085928d0b23172fd4b5a188ac',
+ spentBy: {
+ txid: '8f645ce7b231a3ea81168229c1b6a1157e8a58fb8a8a127a80efc2ed39c4f72e',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 298,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ 'b40d1f6acdb6ee68d7eca0167fe2753c076bc309b2e3b1af8bff70ca34b945b0',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 727176,
+ hash: '00000000000000000a37233b9ed0520368c58437fc4ce5edbda386a4619440f5',
+ timestamp: 1645146139,
+ },
+ },
+ calculated: {
+ genesisSupply: '100000000',
+ genesisOutputScripts: [
+ '76a914a528a001f9f027aae05085928d0b23172fd4b5a188ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ '8ead21ce4b3b9e7b57607b97b65b5013496dc6e3dfdea162c08ce7265a66ebc8': {
+ token: {
+ tokenId:
+ '8ead21ce4b3b9e7b57607b97b65b5013496dc6e3dfdea162c08ce7265a66ebc8',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'IFP',
+ tokenName: 'Infrastructure Funding Proposal Token',
+ url: 'ifp.cash',
+ decimals: 8,
+ hash: 'b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553',
+ },
+ block: {
+ height: 650236,
+ hash: '0000000000000000029d56ae91f48538121ce5e64c656053a1ddfda72249338d',
+ timestamp: 1598560882,
+ },
+ },
+ tx: {
+ txid: '8ead21ce4b3b9e7b57607b97b65b5013496dc6e3dfdea162c08ce7265a66ebc8',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '13ba1f7dd1051ef254358ac94924b52e584b2e96b9d8c7a4c92defff0302bfc6',
+ outIdx: 0,
+ },
+ inputScript:
+ '48304502210083c37da94557747a11ff069a68cde4b3859fc22ab56dbfef0dbf28a6af805999022063e8041b9a42bd8f68b474d124f797e879855282347ed13e04f3ad18129ce33f412102bfc0d9d71891a7bd89b4a89f4675fd341a054561438f186e6bfd1007d818666a',
+ value: 551610,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91462e332f00918c58c3d8e9c66e6d47b33c549203f88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e455349530349465025496e6672617374727563747572652046756e64696e672050726f706f73616c20546f6b656e086966702e6361736820b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f55301084c0008000775f05a074000',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a9146e68110cc00a5d5f1c6c796c1a54f26b364cf06988ac',
+ token: {
+ tokenId:
+ '8ead21ce4b3b9e7b57607b97b65b5013496dc6e3dfdea162c08ce7265a66ebc8',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '2100000000000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: 'a00c5a27f07ed26b116f219d6e666ad171e1420d27f108417a51ac6fa9b03c03',
+ outIdx: 0,
+ },
+ },
+ {
+ value: 550715,
+ outputScript:
+ '76a91462e332f00918c58c3d8e9c66e6d47b33c549203f88ac',
+ spentBy: {
+ txid: 'fadf79b051e33dcfeea92f497a60c6ce36cd2a8ad230f879fb135eae08c1a0c4',
+ outIdx: 15,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 348,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '8ead21ce4b3b9e7b57607b97b65b5013496dc6e3dfdea162c08ce7265a66ebc8',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 650236,
+ hash: '0000000000000000029d56ae91f48538121ce5e64c656053a1ddfda72249338d',
+ timestamp: 1598560882,
+ },
+ },
+ calculated: {
+ genesisSupply: '21000000.00000000',
+ genesisOutputScripts: [
+ '76a9146e68110cc00a5d5f1c6c796c1a54f26b364cf06988ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ '77ec4036ef8546ac46df6d3a5374e961216f92624627eaeef5d2e1a253df9fc6': {
+ token: {
+ tokenId:
+ '77ec4036ef8546ac46df6d3a5374e961216f92624627eaeef5d2e1a253df9fc6',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'CTLv3',
+ tokenName: 'Cashtab Token Launch Launch Token v3',
+ url: 'coinex.com',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 684994,
+ hash: '0000000000000000384706dfb07ac54ff08d0b143bebc51b130dac5caa7c4eae',
+ timestamp: 1620160484,
+ },
+ },
+ tx: {
+ txid: '77ec4036ef8546ac46df6d3a5374e961216f92624627eaeef5d2e1a253df9fc6',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '0916e71779c9de7ee125741d3f5ab01f556356dbc86fd327a24f1e9e22ebc917',
+ outIdx: 2,
+ },
+ inputScript:
+ '483045022100888814e0ea95c9513fe58293b8e71ee34bb321b8502075168428d7aa1ec5c4b80220200da569892cd8514c2c20d0d914cb24fd09ea23fe186d56c691aa5e1ad3800f412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 1497154381,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e455349530543544c7633244361736874616220546f6b656e204c61756e6368204c61756e636820546f6b656e2076330a636f696e65782e636f6d4c0001004c0008000000000000014d',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ '77ec4036ef8546ac46df6d3a5374e961216f92624627eaeef5d2e1a253df9fc6',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '333',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '34caddbb70b152f555366d6719d7fcc7c263a2c77b8981819c1a0bfd7cce8e98',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 1497153077,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ spentBy: {
+ txid: 'e0d6d7d46d5fc6aaa4512a7aca9223c6d7ca30b8253dee1b40b8978fe7dc501e',
+ outIdx: 1,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 320,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '77ec4036ef8546ac46df6d3a5374e961216f92624627eaeef5d2e1a253df9fc6',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 684994,
+ hash: '0000000000000000384706dfb07ac54ff08d0b143bebc51b130dac5caa7c4eae',
+ timestamp: 1620160484,
+ },
+ },
+ calculated: {
+ genesisSupply: '333',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ 'da9460ce4b1c92b4f6ef4e4a6bc2d05539f49d02b17681389d9ce22b8dca50f0': {
+ token: {
+ tokenId:
+ 'da9460ce4b1c92b4f6ef4e4a6bc2d05539f49d02b17681389d9ce22b8dca50f0',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'SA',
+ tokenName: 'Spinner Alpha',
+ url: 'https://cashtabapp.com/',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 700677,
+ hash: '000000000000000000b31f812d4eacbe21ac1b6b55542cdc92de2634b263c8b7',
+ timestamp: 1629467912,
+ },
+ },
+ tx: {
+ txid: 'da9460ce4b1c92b4f6ef4e4a6bc2d05539f49d02b17681389d9ce22b8dca50f0',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '431f527f657b399d8753fb63aee6c806ca0f8907d93606c46b36a33dcb5cb5b9',
+ outIdx: 3,
+ },
+ inputScript:
+ '483045022100d1f85f02b397b6b5646449d797da19506d49cb6e80670e01ad82a213db97464402204a5b5d5e422f63a967959913417b996839b5ff6c56a7ced882cb10fb16e1ff1f412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 3491579877,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e455349530253410d5370696e6e657220416c7068611768747470733a2f2f636173687461626170702e636f6d2f4c0001004c0008000000000000014d',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ 'da9460ce4b1c92b4f6ef4e4a6bc2d05539f49d02b17681389d9ce22b8dca50f0',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '333',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '696265ced15b8fdbacfa1a4f5e779575ff5faaf3ff4ad09e5691b2ed4cf50a84',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 3491578808,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ spentBy: {
+ txid: '562d7f91e21f124c3aaa826e08f6a59f49343a7c0411ff077f5aacfd858f0ec4',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 307,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ 'da9460ce4b1c92b4f6ef4e4a6bc2d05539f49d02b17681389d9ce22b8dca50f0',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 700677,
+ hash: '000000000000000000b31f812d4eacbe21ac1b6b55542cdc92de2634b263c8b7',
+ timestamp: 1629467912,
+ },
+ },
+ calculated: {
+ genesisSupply: '333',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ '54dc2ecd5251f8dfda4c4f15ce05272116b01326076240e2b9cc0104d33b1484': {
+ token: {
+ tokenId:
+ '54dc2ecd5251f8dfda4c4f15ce05272116b01326076240e2b9cc0104d33b1484',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'Alita',
+ tokenName: 'Alita',
+ url: 'alita.cash',
+ decimals: 4,
+ hash: '',
+ },
+ block: {
+ height: 756373,
+ hash: '00000000000000000d62f1b66c08f0976bcdec2f08face2892ae4474b50100d9',
+ timestamp: 1662611972,
+ },
+ },
+ tx: {
+ txid: '54dc2ecd5251f8dfda4c4f15ce05272116b01326076240e2b9cc0104d33b1484',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '72eeff7b43dc066164d92e4c3fece47af3a40e89d46e893df1647cd29dd9f1e3',
+ outIdx: 0,
+ },
+ inputScript:
+ '473044022075166617aa473e86c72f34a5576029eb8766a035b481864ebc75759155efcce00220147e2d7e662123bd728fac700f109a245a0278959f65fc402a1e912e0a5732004121034cdb43b7a1277c4d818dc177aaea4e0bed5d464d240839d5488a278b716facd5',
+ value: 1000,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a914f5f740bc76e56b77bcab8b4d7f888167f416fc6888ac',
+ },
+ {
+ prevOut: {
+ txid: '46b6f61ca026e243d55668bf304df6a21e1fcb2113943cc6bd1fdeceaae85612',
+ outIdx: 2,
+ },
+ inputScript:
+ '4830450221009e98db4b91441190bb7e4745b9f249201d0b54c81c0a816af5f3491ffb21a7e902205a4d1347a5a9133c14e4f55319af00f1df836eba6552f30b44640e9373f4cabf4121034cdb43b7a1277c4d818dc177aaea4e0bed5d464d240839d5488a278b716facd5',
+ value: 750918004,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a914f5f740bc76e56b77bcab8b4d7f888167f416fc6888ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e4553495305416c69746105416c6974610a616c6974612e636173684c0001044c00080000befe6f672000',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a914f5f740bc76e56b77bcab8b4d7f888167f416fc6888ac',
+ token: {
+ tokenId:
+ '54dc2ecd5251f8dfda4c4f15ce05272116b01326076240e2b9cc0104d33b1484',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '210000000000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '2c336374c05f1c8f278d2a1d5f3195a17fe1bc50189ff67c9769a6afcd908ea9',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 750917637,
+ outputScript:
+ '76a914f5f740bc76e56b77bcab8b4d7f888167f416fc6888ac',
+ spentBy: {
+ txid: 'ca70157d5cf6275e0a36adbc3fabf671e3987f343cb35ec4ee7ed5c8d37b3233',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 436,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '54dc2ecd5251f8dfda4c4f15ce05272116b01326076240e2b9cc0104d33b1484',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 756373,
+ hash: '00000000000000000d62f1b66c08f0976bcdec2f08face2892ae4474b50100d9',
+ timestamp: 1662611972,
+ },
+ },
+ calculated: {
+ genesisSupply: '21000000000.0000',
+ genesisOutputScripts: [
+ '76a914f5f740bc76e56b77bcab8b4d7f888167f416fc6888ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ 'cf601c56b58bc05a39a95374a4a865f0a8b56544ea937b30fb46315441717c50': {
+ token: {
+ tokenId:
+ 'cf601c56b58bc05a39a95374a4a865f0a8b56544ea937b30fb46315441717c50',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'UDT',
+ tokenName: 'UpdateTest',
+ url: 'https://cashtab.com/',
+ decimals: 7,
+ hash: '',
+ },
+ block: {
+ height: 759037,
+ hash: '00000000000000000bc95bfdd45e71585f27139e71b56dd5bc86ef05d35b502f',
+ timestamp: 1664226709,
+ },
+ },
+ tx: {
+ txid: 'cf601c56b58bc05a39a95374a4a865f0a8b56544ea937b30fb46315441717c50',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: 'b142b79dbda8ae4aa580220bec76ae5ee78ff2c206a39ce20138c4f371c22aca',
+ outIdx: 0,
+ },
+ inputScript:
+ '483045022100ab2a1e04a156e9cc5204e11e77ba399347f3b7ea3e05d45897c7fb7c6854a7ff022065c7e096e0526a0af223ce32e5e162aa577c42f7da231c13e28ebc3532396f20412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 1300,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e45534953035544540a557064617465546573741468747470733a2f2f636173687461622e636f6d2f4c0001074c000800000001cf977871',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ 'cf601c56b58bc05a39a95374a4a865f0a8b56544ea937b30fb46315441717c50',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '7777777777',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 268,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ 'cf601c56b58bc05a39a95374a4a865f0a8b56544ea937b30fb46315441717c50',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 759037,
+ hash: '00000000000000000bc95bfdd45e71585f27139e71b56dd5bc86ef05d35b502f',
+ timestamp: 1664226709,
+ },
+ },
+ calculated: {
+ genesisSupply: '777.7777777',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ 'acba1d7f354c6d4d001eb99d31de174e5cea8a31d692afd6e7eb8474ad541f55': {
+ token: {
+ tokenId:
+ 'acba1d7f354c6d4d001eb99d31de174e5cea8a31d692afd6e7eb8474ad541f55',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'CTB',
+ tokenName: 'CashTabBits',
+ url: 'https://cashtabapp.com/',
+ decimals: 9,
+ hash: '',
+ },
+ block: {
+ height: 662874,
+ hash: '000000000000000055df35f930c6e9ef6f4c51f1df6650d53eb3390cb92503fa',
+ timestamp: 1606935101,
+ },
+ },
+ tx: {
+ txid: 'acba1d7f354c6d4d001eb99d31de174e5cea8a31d692afd6e7eb8474ad541f55',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: 'f887b8cc01da80969a3f5cfe72c2b3ed3b7352b0153d1df0e8c4208ffafb3dad',
+ outIdx: 0,
+ },
+ inputScript:
+ '47304402203eb4229f825fc4ff6cebe4768821cb8b65c55a39577ed17438f29207785dcbc4022075793f39aa7448c5a56ab5d1317fa822ccac1b010bb0a63c7adbad025d53a43c4121034509251caa5f01e2787c436949eb94d71dcc451bcde5791ae5b7109255f5f0a3',
+ value: 100000,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a914b8d9512d2adf8b4e70c45c26b6b00d75c28eaa9688ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e45534953034354420b43617368546162426974731768747470733a2f2f636173687461626170702e636f6d2f4c0001090102088ac7230489e80000',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a914b8d9512d2adf8b4e70c45c26b6b00d75c28eaa9688ac',
+ token: {
+ tokenId:
+ 'acba1d7f354c6d4d001eb99d31de174e5cea8a31d692afd6e7eb8474ad541f55',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '10000000000000000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: 'f517a560df3b7939bce51faddff4c3bac25fff3e94edbf93546cbeda738bf8f3',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a914b8d9512d2adf8b4e70c45c26b6b00d75c28eaa9688ac',
+ token: {
+ tokenId:
+ 'acba1d7f354c6d4d001eb99d31de174e5cea8a31d692afd6e7eb8474ad541f55',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '0',
+ isMintBaton: true,
+ entryIdx: 0,
+ },
+ },
+ {
+ value: 98358,
+ outputScript:
+ '76a914b8d9512d2adf8b4e70c45c26b6b00d75c28eaa9688ac',
+ spentBy: {
+ txid: '6a4c8bfa2e3ca345795dc3bde84d647390e9e1f2ff96e535cd2754d8ea5a3539',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 339,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ 'acba1d7f354c6d4d001eb99d31de174e5cea8a31d692afd6e7eb8474ad541f55',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 662874,
+ hash: '000000000000000055df35f930c6e9ef6f4c51f1df6650d53eb3390cb92503fa',
+ timestamp: 1606935101,
+ },
+ },
+ calculated: {
+ genesisSupply: '10000000000.000000000',
+ genesisOutputScripts: [
+ '76a914b8d9512d2adf8b4e70c45c26b6b00d75c28eaa9688ac',
+ ],
+ genesisMintBatons: 1,
+ },
+ },
+ '0916e71779c9de7ee125741d3f5ab01f556356dbc86fd327a24f1e9e22ebc917': {
+ token: {
+ tokenId:
+ '0916e71779c9de7ee125741d3f5ab01f556356dbc86fd327a24f1e9e22ebc917',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'CTL2',
+ tokenName: 'Cashtab Token Launch Launch Token v2',
+ url: 'thecryptoguy.com',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 684993,
+ hash: '00000000000000004c2f629c06444ec73fd059e1ee55e99d5e4b7bbff24f176a',
+ timestamp: 1620160437,
+ },
+ },
+ tx: {
+ txid: '0916e71779c9de7ee125741d3f5ab01f556356dbc86fd327a24f1e9e22ebc917',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '16b12bbacdbb8c8a799adbfd782bfff9843c1f9b0be148eaae02a1a7f74f95c4',
+ outIdx: 2,
+ },
+ inputScript:
+ '4730440220058d0e566c59804ac96c4a05dc7ab49f387b6046175c97a8c829994d280428050220220159d839b46539ce8b8d08577f970169032f59a993437719f491f945a45b13412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 1497155685,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e455349530443544c32244361736874616220546f6b656e204c61756e6368204c61756e636820546f6b656e2076321074686563727970746f6775792e636f6d4c0001004c000800000000000007d0',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ '0916e71779c9de7ee125741d3f5ab01f556356dbc86fd327a24f1e9e22ebc917',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '2000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '9f4c66b82f5b41f474f9670311e834667c0207a81f9e31a65731a7731e86c3ee',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 1497154381,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ spentBy: {
+ txid: '77ec4036ef8546ac46df6d3a5374e961216f92624627eaeef5d2e1a253df9fc6',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 324,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '0916e71779c9de7ee125741d3f5ab01f556356dbc86fd327a24f1e9e22ebc917',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 684993,
+ hash: '00000000000000004c2f629c06444ec73fd059e1ee55e99d5e4b7bbff24f176a',
+ timestamp: 1620160437,
+ },
+ },
+ calculated: {
+ genesisSupply: '2000',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb': {
+ token: {
+ tokenId:
+ 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'NAKAMOTO',
+ tokenName: 'NAKAMOTO',
+ url: '',
+ decimals: 8,
+ hash: '',
+ },
+ block: {
+ height: 555671,
+ hash: '000000000000000000aeb2168da809c07ede4de5ec2109df43bf49ef13805ddc',
+ timestamp: 1541634138,
+ },
+ },
+ tx: {
+ txid: 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb',
+ version: 1,
+ inputs: [
+ {
+ prevOut: {
+ txid: 'c6c9c6a2044029831ab4469c88c230f79778aae2265a0ad0f8df3cde724bb5b3',
+ outIdx: 2,
+ },
+ inputScript:
+ '47304402202fff3979f9cf0a5052655c8699081a77a653903de41547928db0b94601aa082502207cdb909e3a7b2b7f8a3eb80243a1bd2fd8ad9449a0ec30242ae4b187436d11a0412103b30e7096c6e3a3b45e5aba4ad8fe48a1fdd7c04de0de55a43095e7560b52e19d',
+ value: 546,
+ sequenceNo: 4294967294,
+ outputScript:
+ '76a91433c0448680ca324225eeca7a230cf191ab88400288ac',
+ },
+ {
+ prevOut: {
+ txid: '263795185b3623a1bc1dea322b0544d8851f0432b3dbc3f66a7a5109de1758d2',
+ outIdx: 0,
+ },
+ inputScript:
+ '473044022011a39acbbb80c4723822d434445fc4b3d72ad0212902fdb183a5408af00e158c02200eb3778b1af9f3a8fe28b6670f5fe543fb4c190f79f349273860125be05269b2412103b30e7096c6e3a3b45e5aba4ad8fe48a1fdd7c04de0de55a43095e7560b52e19d',
+ value: 65084,
+ sequenceNo: 4294967294,
+ outputScript:
+ '76a91433c0448680ca324225eeca7a230cf191ab88400288ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e45534953084e414b414d4f544f084e414b414d4f544f4c004c0001084c0008000775f05a074000',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91433c0448680ca324225eeca7a230cf191ab88400288ac',
+ token: {
+ tokenId:
+ 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '2100000000000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '5f4c275fe00896031757fb8f771cf9ff64ef90112ff2d8cd75c3d792338f7767',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 64650,
+ outputScript:
+ '76a91433c0448680ca324225eeca7a230cf191ab88400288ac',
+ spentBy: {
+ txid: '4bc56e2c0358dbfa169e0feadf8edade0b76773f3bfad3f44b042e9bc5cd5d7f',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 555670,
+ timeFirstSeen: 0,
+ size: 432,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 555671,
+ hash: '000000000000000000aeb2168da809c07ede4de5ec2109df43bf49ef13805ddc',
+ timestamp: 1541634138,
+ },
+ },
+ calculated: {
+ genesisSupply: '21000000.00000000',
+ genesisOutputScripts: [
+ '76a91433c0448680ca324225eeca7a230cf191ab88400288ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ 'ccf5fe5a387559c8ab9efdeb0c0ef1b444e677298cfddf07671245ce3cb3c79f': {
+ token: {
+ tokenId:
+ 'ccf5fe5a387559c8ab9efdeb0c0ef1b444e677298cfddf07671245ce3cb3c79f',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'XGB',
+ tokenName: 'Garmonbozia',
+ url: 'https://twinpeaks.fandom.com/wiki/Garmonbozia',
+ decimals: 8,
+ hash: '',
+ },
+ block: {
+ height: 685147,
+ hash: '00000000000000000955aad3a91d39a54197e5eb567660a41cb25c08430a991a',
+ timestamp: 1620241359,
+ },
+ },
+ tx: {
+ txid: 'ccf5fe5a387559c8ab9efdeb0c0ef1b444e677298cfddf07671245ce3cb3c79f',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '6cabd1d33ef0b992fa30be127f1a0323766fba6ed46a0c27e881c707c116f476',
+ outIdx: 0,
+ },
+ inputScript:
+ '4730440220288fe3c2dda913b7f9c002f944bd946e4a9c98bd5f94d7295fdc1e5bad64cca202200f80b8c84ac71105c01b94c88aec7a8327afed540333a7108dc07346d3b19e3c41210302850962f13b498608a38f82ce5a037da70d659bec50af746816d44e9e732e02',
+ value: 995151,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a914d4fa9121bcd065dd93e58831569cf51ef5a74f6188ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e45534953035847420b4761726d6f6e626f7a69612d68747470733a2f2f7477696e7065616b732e66616e646f6d2e636f6d2f77696b692f4761726d6f6e626f7a69614c0001084c0008000000174876e800',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a914d4fa9121bcd065dd93e58831569cf51ef5a74f6188ac',
+ token: {
+ tokenId:
+ 'ccf5fe5a387559c8ab9efdeb0c0ef1b444e677298cfddf07671245ce3cb3c79f',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '100000000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: 'f2d492da069429866c8ed59fd0d5283b8a8da881414633ac35979a2891030c57',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 993847,
+ outputScript:
+ '76a914d4fa9121bcd065dd93e58831569cf51ef5a74f6188ac',
+ spentBy: {
+ txid: '8c31247864b54642d8f6ef2a9e6a444a828beaa51e9afb3cdbc6e4cac9b39a89',
+ outIdx: 1,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 327,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ 'ccf5fe5a387559c8ab9efdeb0c0ef1b444e677298cfddf07671245ce3cb3c79f',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 685147,
+ hash: '00000000000000000955aad3a91d39a54197e5eb567660a41cb25c08430a991a',
+ timestamp: 1620241359,
+ },
+ },
+ calculated: {
+ genesisSupply: '1000.00000000',
+ genesisOutputScripts: [
+ '76a914d4fa9121bcd065dd93e58831569cf51ef5a74f6188ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ '7f8889682d57369ed0e32336f8b7e0ffec625a35cca183f4e81fde4e71a538a1': {
+ token: {
+ tokenId:
+ '7f8889682d57369ed0e32336f8b7e0ffec625a35cca183f4e81fde4e71a538a1',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'HONK',
+ tokenName: 'HONK HONK',
+ url: 'THE REAL HONK SLP TOKEN',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 576633,
+ hash: '000000000000000001400c74bf6ea59af97680bb6ee5b8918f0296795191dc56',
+ timestamp: 1554290938,
+ },
+ },
+ tx: {
+ txid: '7f8889682d57369ed0e32336f8b7e0ffec625a35cca183f4e81fde4e71a538a1',
+ version: 1,
+ inputs: [
+ {
+ prevOut: {
+ txid: 'e14a57668e7aa92f9931750649c828adc7aff1289ef4f458108d097c4663c684',
+ outIdx: 2,
+ },
+ inputScript:
+ '473044022045cd384954a2e3f0446e72345b87e117b1e553970a33c3ad135f5f2911bf804502205f07693f399b7922bd16f3318c392887234c89aff8b76ecb3fed0d18f6abfdd9412102fde03670ccc6950b76029ef131280b604df9b44d4520cd9df9023aade2082b07',
+ value: 99141,
+ sequenceNo: 4294967294,
+ outputScript:
+ '76a914726e13d2a9f4de19146a69d8a464d96674bc4ec288ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e4553495304484f4e4b09484f4e4b20484f4e4b17544845205245414c20484f4e4b20534c5020544f4b454e4c0001004c0008000000174876e800',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91453c0098567382f003437a016edcc47de1436746988ac',
+ token: {
+ tokenId:
+ '7f8889682d57369ed0e32336f8b7e0ffec625a35cca183f4e81fde4e71a538a1',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '100000000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: 'd9f1c4833aa9b6e91d589c46783ec4c7e6225b754d1c0d8cd06a7d65bc71e696',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 98290,
+ outputScript:
+ '76a9145afb7e1a1216788d7c69c509269d75b8750e750688ac',
+ spentBy: {
+ txid: '5691fa7fbf62db3964d9bc01ef27cdb392a5051b2c225054dc502b4bfadd377e',
+ outIdx: 1,
+ },
+ },
+ ],
+ lockTime: 576632,
+ timeFirstSeen: 0,
+ size: 304,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '7f8889682d57369ed0e32336f8b7e0ffec625a35cca183f4e81fde4e71a538a1',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 576633,
+ hash: '000000000000000001400c74bf6ea59af97680bb6ee5b8918f0296795191dc56',
+ timestamp: 1554290938,
+ },
+ },
+ calculated: {
+ genesisSupply: '100000000000',
+ genesisOutputScripts: [
+ '76a91453c0098567382f003437a016edcc47de1436746988ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ 'bdb3b4215ca0622e0c4c07655522c376eaa891838a82f0217fa453bb0595a37c': {
+ token: {
+ tokenId:
+ 'bdb3b4215ca0622e0c4c07655522c376eaa891838a82f0217fa453bb0595a37c',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'Service',
+ tokenName: 'Evc token',
+ url: 'https://cashtab.com',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 715115,
+ hash: '000000000000000008685ec611c9ab59dd1062431e3b40a7e27c0320c4993f68',
+ timestamp: 1637890451,
+ },
+ },
+ tx: {
+ txid: 'bdb3b4215ca0622e0c4c07655522c376eaa891838a82f0217fa453bb0595a37c',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '974929a5a09fe45c891414c8daaa75518e0490d9b4e0c736c5100699a84422f0',
+ outIdx: 2,
+ },
+ inputScript:
+ '483045022100d09d803b134f5e320a1487817342b56a017e11a69c2fa106814e3107d8c47fd30220300af9b456fa43049c41dca21d564c434504864c6fc4a3a36941ddaaddcba5b0412102f2d4a75908a466eec993f27fb985836490d9af52f110b15b60fe6cb17dbedf6d',
+ value: 97862,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91463a17ac732fd6afe8699b240a29b483246308de788ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e4553495307536572766963650945766320746f6b656e1368747470733a2f2f636173687461622e636f6d4c0001004c0008000000161e70f600',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91463a17ac732fd6afe8699b240a29b483246308de788ac',
+ token: {
+ tokenId:
+ 'bdb3b4215ca0622e0c4c07655522c376eaa891838a82f0217fa453bb0595a37c',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '95000000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '46da16acb51c912164e7bed0cc515ab6d8898e6d4d3e821d4ee7442587a9a50e',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 96793,
+ outputScript:
+ '76a91463a17ac732fd6afe8699b240a29b483246308de788ac',
+ spentBy: {
+ txid: 'd21ae699093349473539b13808618561a350d0c39acc00f3704ba474ad851370',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 304,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ 'bdb3b4215ca0622e0c4c07655522c376eaa891838a82f0217fa453bb0595a37c',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 715115,
+ hash: '000000000000000008685ec611c9ab59dd1062431e3b40a7e27c0320c4993f68',
+ timestamp: 1637890451,
+ },
+ },
+ calculated: {
+ genesisSupply: '95000000000',
+ genesisOutputScripts: [
+ '76a91463a17ac732fd6afe8699b240a29b483246308de788ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ '157e0cdef5d5c51bdea00eac9ab821d809bb9d03cf98da85833614bedb129be6': {
+ token: {
+ tokenId:
+ '157e0cdef5d5c51bdea00eac9ab821d809bb9d03cf98da85833614bedb129be6',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'CLNSP',
+ tokenName: 'ComponentLongNameSpeedLoad',
+ url: 'https://cashtabapp.com/',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 685168,
+ hash: '00000000000000001cd7cfe38ef8173732989f73bd4818e13db2b909c4cea007',
+ timestamp: 1620249731,
+ },
+ },
+ tx: {
+ txid: '157e0cdef5d5c51bdea00eac9ab821d809bb9d03cf98da85833614bedb129be6',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: 'e0d6d7d46d5fc6aaa4512a7aca9223c6d7ca30b8253dee1b40b8978fe7dc501e',
+ outIdx: 1,
+ },
+ inputScript:
+ '4730440220608c220025c34683b650ad8b33c3ee891f677f4b3162cec94c865e1e766094340220789e91fffcf5ffb15508429befd5c299f9e86cd49cf203649cbbe384a9998586412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 1496725917,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e4553495305434c4e53501a436f6d706f6e656e744c6f6e674e616d6553706565644c6f61641768747470733a2f2f636173687461626170702e636f6d2f4c0001004c00080000000000000064',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ '157e0cdef5d5c51bdea00eac9ab821d809bb9d03cf98da85833614bedb129be6',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '100',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '979f7741bb99ef43d7cf55ac5f070408fcb95dfce5818eb44f49e5b759a36d11',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 1496724613,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ spentBy: {
+ txid: '28669d88822a1e0c202fb68d6abc36c3b5acc9f1df3c6990d045b119e4b7cc4d',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 322,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '157e0cdef5d5c51bdea00eac9ab821d809bb9d03cf98da85833614bedb129be6',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 685168,
+ hash: '00000000000000001cd7cfe38ef8173732989f73bd4818e13db2b909c4cea007',
+ timestamp: 1620249731,
+ },
+ },
+ calculated: {
+ genesisSupply: '100',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ '1101bd5d7b6bbc3176fb2b93d08e76ab532b04ff731d71502249e3cb9b6fcb1a': {
+ token: {
+ tokenId:
+ '1101bd5d7b6bbc3176fb2b93d08e76ab532b04ff731d71502249e3cb9b6fcb1a',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'XBIT',
+ tokenName: 'eBits',
+ url: 'https://boomertakes.com/',
+ decimals: 9,
+ hash: '',
+ },
+ block: {
+ height: 680776,
+ hash: '00000000000000003667d7cd150a1a29c78f5fab9360ab3c0e32eba99f9e2c08',
+ timestamp: 1617733350,
+ },
+ },
+ tx: {
+ txid: '1101bd5d7b6bbc3176fb2b93d08e76ab532b04ff731d71502249e3cb9b6fcb1a',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: 'cac6ff7ff285f4ae709ca58aad490f51f079c043dfa7f7ecf32086d756fc18a7',
+ outIdx: 2,
+ },
+ inputScript:
+ '473044022062337ef2c17772572dc32f5ba7fb2a272c49009bc947edf8caeacb142ae74999022068752a66f9f653251355231bf9134a9c2309ffbb2070fdcbbf5f16270b45b48b4121034509251caa5f01e2787c436949eb94d71dcc451bcde5791ae5b7109255f5f0a3',
+ value: 83438,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a914b8d9512d2adf8b4e70c45c26b6b00d75c28eaa9688ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e4553495304584249540565426974731868747470733a2f2f626f6f6d657274616b65732e636f6d2f4c00010901020800038d7ea4c68000',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a914b8d9512d2adf8b4e70c45c26b6b00d75c28eaa9688ac',
+ token: {
+ tokenId:
+ '1101bd5d7b6bbc3176fb2b93d08e76ab532b04ff731d71502249e3cb9b6fcb1a',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '1000000000000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: 'ffb660d9ef11879a5c8fce3b11e56819289caf0db49b36b5bb9f90d535ebbc6f',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a914b8d9512d2adf8b4e70c45c26b6b00d75c28eaa9688ac',
+ token: {
+ tokenId:
+ '1101bd5d7b6bbc3176fb2b93d08e76ab532b04ff731d71502249e3cb9b6fcb1a',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '0',
+ isMintBaton: true,
+ entryIdx: 0,
+ },
+ },
+ {
+ value: 81796,
+ outputScript:
+ '76a914b8d9512d2adf8b4e70c45c26b6b00d75c28eaa9688ac',
+ spentBy: {
+ txid: 'ffb660d9ef11879a5c8fce3b11e56819289caf0db49b36b5bb9f90d535ebbc6f',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 335,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '1101bd5d7b6bbc3176fb2b93d08e76ab532b04ff731d71502249e3cb9b6fcb1a',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 680776,
+ hash: '00000000000000003667d7cd150a1a29c78f5fab9360ab3c0e32eba99f9e2c08',
+ timestamp: 1617733350,
+ },
+ },
+ calculated: {
+ genesisSupply: '1000000.000000000',
+ genesisOutputScripts: [
+ '76a914b8d9512d2adf8b4e70c45c26b6b00d75c28eaa9688ac',
+ ],
+ genesisMintBatons: 1,
+ },
+ },
+ '6e24e89b6d5284138c69777527760500b99614631bca7f2a5c38f4648dae9524': {
+ token: {
+ tokenId:
+ '6e24e89b6d5284138c69777527760500b99614631bca7f2a5c38f4648dae9524',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'CBB',
+ tokenName: 'Cashtab Beta Bits',
+ url: 'https://cashtabapp.com/',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 700469,
+ hash: '00000000000000000bb5f9bb8e292c0017c34e05708f74eae3ae09ff18f6bc89',
+ timestamp: 1629339994,
+ },
+ },
+ tx: {
+ txid: '6e24e89b6d5284138c69777527760500b99614631bca7f2a5c38f4648dae9524',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '5bb0ffba07c4c86bc058806fbe1eba76c6af21a1eb5907b7058f1b5f40125017',
+ outIdx: 1,
+ },
+ inputScript:
+ '4730440220478f8eb48e1ff3dd410a97d4033afd23d7ee39ec0ac0450dc6b9160ffe67c84102201b49185a7deb2701956d13601b67802c897a0bf5f0c261f8d259fdafc711ddf3412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 140758876,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e45534953034342421143617368746162204265746120426974731768747470733a2f2f636173687461626170702e636f6d2f4c0001004c0008000000003b9aca00',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ '6e24e89b6d5284138c69777527760500b99614631bca7f2a5c38f4648dae9524',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '1000000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '8ccb8b0eb8f93fcfa4978c60f8aee14bc7e6b4d965d8cb55093f9604f3242d57',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 140757807,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ spentBy: {
+ txid: 'c6457243bc0ff473b1a442b2f75155fcc020575bad69c45cd8edffa05cb6710a',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 311,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '6e24e89b6d5284138c69777527760500b99614631bca7f2a5c38f4648dae9524',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 700469,
+ hash: '00000000000000000bb5f9bb8e292c0017c34e05708f74eae3ae09ff18f6bc89',
+ timestamp: 1629339994,
+ },
+ },
+ calculated: {
+ genesisSupply: '1000000000',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ '4bd147fc5d5ff26249a9299c46b80920c0b81f59a60e05428262160ebee0b0c3': {
+ token: {
+ tokenId:
+ '4bd147fc5d5ff26249a9299c46b80920c0b81f59a60e05428262160ebee0b0c3',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'NOCOVID',
+ tokenName: 'Covid19 Lifetime Immunity',
+ url: 'https://www.who.int/emergencies/diseases/novel-coronavirus-2019/covid-19-vaccines',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 680063,
+ hash: '000000000000000012ad3d6dfb3505616ab9c3cb3772abac0448ddfc25043df4',
+ timestamp: 1617304616,
+ },
+ },
+ tx: {
+ txid: '4bd147fc5d5ff26249a9299c46b80920c0b81f59a60e05428262160ebee0b0c3',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: 'd849fbb04ce77870deaf0e2d9a67146b055f6d8bba18285f5c5f662e20d23199',
+ outIdx: 3,
+ },
+ inputScript:
+ '48304502210089d46c2873cc9d92927e7043e803c9ac1a705508e89de49af25869d7d12879d90220364ee750ac252487dae7bfb71e8de89085f486290654c3acc2efe4f1a08e99654121034509251caa5f01e2787c436949eb94d71dcc451bcde5791ae5b7109255f5f0a3',
+ value: 86422,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a914b8d9512d2adf8b4e70c45c26b6b00d75c28eaa9688ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e45534953074e4f434f56494419436f7669643139204c69666574696d6520496d6d756e6974794c5168747470733a2f2f7777772e77686f2e696e742f656d657267656e636965732f64697365617365732f6e6f76656c2d636f726f6e6176697275732d323031392f636f7669642d31392d76616363696e65734c00010001020800000000000f4240',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a914b8d9512d2adf8b4e70c45c26b6b00d75c28eaa9688ac',
+ token: {
+ tokenId:
+ '4bd147fc5d5ff26249a9299c46b80920c0b81f59a60e05428262160ebee0b0c3',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '1000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: 'cac6ff7ff285f4ae709ca58aad490f51f079c043dfa7f7ecf32086d756fc18a7',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a914b8d9512d2adf8b4e70c45c26b6b00d75c28eaa9688ac',
+ token: {
+ tokenId:
+ '4bd147fc5d5ff26249a9299c46b80920c0b81f59a60e05428262160ebee0b0c3',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '0',
+ isMintBaton: true,
+ entryIdx: 0,
+ },
+ },
+ {
+ value: 84780,
+ outputScript:
+ '76a914b8d9512d2adf8b4e70c45c26b6b00d75c28eaa9688ac',
+ spentBy: {
+ txid: 'cac6ff7ff285f4ae709ca58aad490f51f079c043dfa7f7ecf32086d756fc18a7',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 417,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '4bd147fc5d5ff26249a9299c46b80920c0b81f59a60e05428262160ebee0b0c3',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 680063,
+ hash: '000000000000000012ad3d6dfb3505616ab9c3cb3772abac0448ddfc25043df4',
+ timestamp: 1617304616,
+ },
+ },
+ calculated: {
+ genesisSupply: '1000000',
+ genesisOutputScripts: [
+ '76a914b8d9512d2adf8b4e70c45c26b6b00d75c28eaa9688ac',
+ ],
+ genesisMintBatons: 1,
+ },
+ },
+ 'b9877d8f8d2364b983707df905d592f534a3ada18e52aa529a0f72fcc535abf7': {
+ token: {
+ tokenId:
+ 'b9877d8f8d2364b983707df905d592f534a3ada18e52aa529a0f72fcc535abf7',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'SRM',
+ tokenName: 'Server Redundancy Mint',
+ url: 'https://cashtab.com/',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 757433,
+ hash: '000000000000000006f6ed1242ab08be563c8ea6898a38fa09b986e9507b8003',
+ timestamp: 1663251085,
+ },
+ },
+ tx: {
+ txid: 'b9877d8f8d2364b983707df905d592f534a3ada18e52aa529a0f72fcc535abf7',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '40d4c93e82b82f5768e93a0da9c3c065856733d136876a90182590c8e115d1c4',
+ outIdx: 2,
+ },
+ inputScript:
+ '473044022052d51327fd080fb9c8a55b853a6ebc7528b5ad769291405996e5a57bf9e2bfba02201c0855b2544e9689ecc0e154aae6dc451c7a3b5ddf92847905436213cd87dbc8412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 5828,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e455349530353524d1653657276657220526564756e64616e6379204d696e741468747470733a2f2f636173687461622e636f6d2f4c0001004c00080000000000000005',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ 'b9877d8f8d2364b983707df905d592f534a3ada18e52aa529a0f72fcc535abf7',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '5',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: 'c04ae7f139eb16023a70d1bb39b1ae8745667edb09833e994a5b4d48976a111d',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 4759,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ spentBy: {
+ txid: 'e5aa45cea8268f873b00134a1981e92e5022e5c15e3ef273be8552b349e01651',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 313,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ 'b9877d8f8d2364b983707df905d592f534a3ada18e52aa529a0f72fcc535abf7',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 757433,
+ hash: '000000000000000006f6ed1242ab08be563c8ea6898a38fa09b986e9507b8003',
+ timestamp: 1663251085,
+ },
+ },
+ calculated: {
+ genesisSupply: '5',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ 'b8f2a9e767a0be7b80c7e414ef2534586d4da72efddb39a4e70e501ab73375cc': {
+ token: {
+ tokenId:
+ 'b8f2a9e767a0be7b80c7e414ef2534586d4da72efddb39a4e70e501ab73375cc',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'CTD',
+ tokenName: 'Cashtab Dark',
+ url: 'https://cashtab.com/',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 726043,
+ hash: '00000000000000000182db32e000171006b7b7820181676b5fd8f29cc90d2b9c',
+ timestamp: 1644455332,
+ },
+ },
+ tx: {
+ txid: 'b8f2a9e767a0be7b80c7e414ef2534586d4da72efddb39a4e70e501ab73375cc',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '85e9379d5b9b371aa7f9464376290fbc6a40083ec14883460b649898f6d7c60b',
+ outIdx: 0,
+ },
+ inputScript:
+ '483045022100ed92efcd0c3fd8e241888d85751dc09856a2dbb73038ef6097a1cce91302741e022036c2941b90fbf4607b5a00c872a109630d26beda74763ca9c33f9e7703350053412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 10000,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e45534953034354440c43617368746162204461726b1468747470733a2f2f636173687461622e636f6d2f4c0001004c00080000000000002710',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ 'b8f2a9e767a0be7b80c7e414ef2534586d4da72efddb39a4e70e501ab73375cc',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '10000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '0283492a729cfb7999684e733f2ee76bc4f652b9047ff47dbe3534b8f5960697',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 8931,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ spentBy: {
+ txid: '28e406370381e1ef6764bbbb21cf7974e95b84b2c49d204ab9f471d88334af90',
+ outIdx: 5,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 304,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ 'b8f2a9e767a0be7b80c7e414ef2534586d4da72efddb39a4e70e501ab73375cc',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 726043,
+ hash: '00000000000000000182db32e000171006b7b7820181676b5fd8f29cc90d2b9c',
+ timestamp: 1644455332,
+ },
+ },
+ calculated: {
+ genesisSupply: '10000',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ '70ead4d94c43fe8c5576bb2528fd54380d8356f632ac962b1e03fb287607dfd4': {
+ token: {
+ tokenId:
+ '70ead4d94c43fe8c5576bb2528fd54380d8356f632ac962b1e03fb287607dfd4',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'NCBT',
+ tokenName: 'newChatBotTest',
+ url: 'alias.etokens.cash',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 783693,
+ hash: '000000000000000008db6b50a881d28867d152ada018afb4b995d3b64a1e17eb',
+ timestamp: 1679073789,
+ },
+ },
+ tx: {
+ txid: '70ead4d94c43fe8c5576bb2528fd54380d8356f632ac962b1e03fb287607dfd4',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '668baf5dc81fab21cbbcd1f3f82851ee65725e941ebb5f45b56b7c6b744488d5',
+ outIdx: 2,
+ },
+ inputScript:
+ '483045022100beb34be709c4060a4c343e899ec8ae5840954c41a0cefc1cfb31d212671f102f022044b1abde3005393e3247ee903646e9c1ecfe2a79b30768f2fde3abe4db485173412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 6212297,
+ sequenceNo: 4294967294,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e45534953044e4342540e6e657743686174426f745465737412616c6961732e65746f6b656e732e636173684c0001004c00080000000000000064',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ '70ead4d94c43fe8c5576bb2528fd54380d8356f632ac962b1e03fb287607dfd4',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '100',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ },
+ {
+ value: 6211296,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ spentBy: {
+ txid: 'c2c6b5a7b37e983c4e193900fcde2b8139ef4c3db2fd9689c354f6ea65354f15',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 305,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '70ead4d94c43fe8c5576bb2528fd54380d8356f632ac962b1e03fb287607dfd4',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 783693,
+ hash: '000000000000000008db6b50a881d28867d152ada018afb4b995d3b64a1e17eb',
+ timestamp: 1679073789,
+ },
+ },
+ calculated: {
+ genesisSupply: '100',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ 'ff9aa6eebcd1331f8684d53b441cfa3060a4ffc403b417d5728de8ab231f5516': {
+ token: {
+ tokenId:
+ 'ff9aa6eebcd1331f8684d53b441cfa3060a4ffc403b417d5728de8ab231f5516',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'NCBT',
+ tokenName: 'newChatBotTest',
+ url: 'alias.etokens.cash',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 783694,
+ hash: '00000000000000000bf1b32605951ddcf4d4d9d240f73f19b4f505b8d935fb1b',
+ timestamp: 1679074454,
+ },
+ },
+ tx: {
+ txid: 'ff9aa6eebcd1331f8684d53b441cfa3060a4ffc403b417d5728de8ab231f5516',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: 'f3963fe5f36b9735a89ee8a13c51b909839457b50926daf89a2b56cf9f9fba13',
+ outIdx: 2,
+ },
+ inputScript:
+ '473044022006360a62732061dc50a6ccee96ff432f8306482eccdfa04a381d69e92ec9ba090220754d5cdc43e321e4ab4875f9df6759b7c6202c90f8ca56b38186f8a5e7104c66412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 9030220,
+ sequenceNo: 4294967294,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e45534953044e4342540e6e657743686174426f745465737412616c6961732e65746f6b656e732e636173684c0001004c00080000000000000064',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ 'ff9aa6eebcd1331f8684d53b441cfa3060a4ffc403b417d5728de8ab231f5516',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '100',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ },
+ {
+ value: 9029219,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ spentBy: {
+ txid: '19cc36305423ddf2fefd400663a9938b5cb342a82ebd00f6251ee8bb5c58c855',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 304,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ 'ff9aa6eebcd1331f8684d53b441cfa3060a4ffc403b417d5728de8ab231f5516',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 783694,
+ hash: '00000000000000000bf1b32605951ddcf4d4d9d240f73f19b4f505b8d935fb1b',
+ timestamp: 1679074454,
+ },
+ },
+ calculated: {
+ genesisSupply: '100',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ 'f077f207fc8a8557e5f0ffc6021685ab4b357e9b92d2b5c4192dcb7760ee6e29': {
+ token: {
+ tokenId:
+ 'f077f207fc8a8557e5f0ffc6021685ab4b357e9b92d2b5c4192dcb7760ee6e29',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'NCBT',
+ tokenName: 'newChatBotTest',
+ url: 'alias.etokens.cash',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 783695,
+ hash: '000000000000000015ade1e6be40db716077affda1e9c38d163a63981d4fab41',
+ timestamp: 1679077205,
+ },
+ },
+ tx: {
+ txid: 'f077f207fc8a8557e5f0ffc6021685ab4b357e9b92d2b5c4192dcb7760ee6e29',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '9c0c01c1e8cc3c6d816a3b41d09d65fda69de082b74b6ede7832ed05527ec744',
+ outIdx: 3,
+ },
+ inputScript:
+ '47304402202425b99ebe499a5e8cada7375526251409d7800bf4bd128ca6494e7fa2ee6709022064c3b22d0611d7585c56cd8e8e655b74ed9bbbc8ab9a2277524dacc7a6939726412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 15250788,
+ sequenceNo: 4294967294,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e45534953044e4342540e6e657743686174426f745465737412616c6961732e65746f6b656e732e636173684c0001004c00080000000000000064',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ 'f077f207fc8a8557e5f0ffc6021685ab4b357e9b92d2b5c4192dcb7760ee6e29',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '100',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ },
+ {
+ value: 15249787,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ spentBy: {
+ txid: '03d227c6ae528bd6644487f394f5ddb065eea5c2ff97cae9b032d6efc46edea8',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 304,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ 'f077f207fc8a8557e5f0ffc6021685ab4b357e9b92d2b5c4192dcb7760ee6e29',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 783695,
+ hash: '000000000000000015ade1e6be40db716077affda1e9c38d163a63981d4fab41',
+ timestamp: 1679077205,
+ },
+ },
+ calculated: {
+ genesisSupply: '100',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ '3adbf501e21c711d20118e003711168eb39f560c01f4c6d6736fa3f3fceaa577': {
+ token: {
+ tokenId:
+ '3adbf501e21c711d20118e003711168eb39f560c01f4c6d6736fa3f3fceaa577',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'OMI',
+ tokenName: 'Omicron',
+ url: 'cdc.gov',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 717653,
+ hash: '000000000000000004cc2d26068bcd8dcab87841b0ce6b5150f4f8b6ccff6d10',
+ timestamp: 1639430827,
+ },
+ },
+ tx: {
+ txid: '3adbf501e21c711d20118e003711168eb39f560c01f4c6d6736fa3f3fceaa577',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: 'de3f45ae6172bd5d84872d45191889587c4acb1ee44c76a811ec7a65487b1052',
+ outIdx: 1,
+ },
+ inputScript:
+ '47304402203d613e2f0c10a37c9305130b896d9b00755c24b21c91d3115ed6f240fde78de102202c730ebfb3d109cd6c3f8fe89941c40a88e890a99d932a261eb71c144683d30e412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 206527138,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e45534953034f4d49074f6d6963726f6e076364632e676f764c0001004c0008000000003b9aca00',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ '3adbf501e21c711d20118e003711168eb39f560c01f4c6d6736fa3f3fceaa577',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '1000000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '702e1b64aed21bc764c83f638407f7f73245604d8d9c36f03e048a8005b8ccfd',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 206526069,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ spentBy: {
+ txid: 'f83ed4755d3356181a3a0f2a1b8181f7616d76149ce8bcccc751eb4a8c3b91f2',
+ outIdx: 1,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 285,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '3adbf501e21c711d20118e003711168eb39f560c01f4c6d6736fa3f3fceaa577',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 717653,
+ hash: '000000000000000004cc2d26068bcd8dcab87841b0ce6b5150f4f8b6ccff6d10',
+ timestamp: 1639430827,
+ },
+ },
+ calculated: {
+ genesisSupply: '1000000000',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ '3de671a7107d3803d78f7f4a4e5c794d0903a8d28d16076445c084943c1e2db8': {
+ token: {
+ tokenId:
+ '3de671a7107d3803d78f7f4a4e5c794d0903a8d28d16076445c084943c1e2db8',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'CLB',
+ tokenName: 'Cashtab Local Beta',
+ url: 'boomertakes.com',
+ decimals: 2,
+ hash: '',
+ },
+ block: {
+ height: 688194,
+ hash: '00000000000000003d718f77c7b914230be2357a1863542d9ce99994836e5eac',
+ timestamp: 1622049539,
+ },
+ },
+ tx: {
+ txid: '3de671a7107d3803d78f7f4a4e5c794d0903a8d28d16076445c084943c1e2db8',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '03010e17e77b038ced51869a077cc7e79d20b0c3322c909ed5ebc39d96d1a1a6',
+ outIdx: 0,
+ },
+ inputScript:
+ '47304402202215015f8d4ff32bf16d579c3db882c6d33ad32cddd05c846f13a1c89e04ec8e02203581865f2d9a0c5107467dcdc38b831156b831ab2d259cc6f234828f78151921412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 29074919,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e4553495303434c421243617368746162204c6f63616c20426574610f626f6f6d657274616b65732e636f6d4c0001024c000800000000000008ae',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ '3de671a7107d3803d78f7f4a4e5c794d0903a8d28d16076445c084943c1e2db8',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '2222',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '123a31b903c9a7de544a443a02f73e0cbee6304931704e55d0583a8aca8df48e',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 29073850,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ spentBy: {
+ txid: 'd83677da1b3ade24e9fdcc2a47e3ba87e1fbe1de9e13075d79d16819952a8789',
+ outIdx: 2,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 304,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '3de671a7107d3803d78f7f4a4e5c794d0903a8d28d16076445c084943c1e2db8',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 688194,
+ hash: '00000000000000003d718f77c7b914230be2357a1863542d9ce99994836e5eac',
+ timestamp: 1622049539,
+ },
+ },
+ calculated: {
+ genesisSupply: '22.22',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ '20a0b9337a78603c6681ed2bc541593375535dcd9979196620ce71f233f2f6f8': {
+ token: {
+ tokenId:
+ '20a0b9337a78603c6681ed2bc541593375535dcd9979196620ce71f233f2f6f8',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'VSP',
+ tokenName: 'Vespene Gas',
+ url: 'https://simple.wikipedia.org/wiki/StarCraft#Gameplay',
+ decimals: 9,
+ hash: '',
+ },
+ block: {
+ height: 763087,
+ hash: '0000000000000000015abcebc15e74036598855a9fdd976868ad99bb23b87a89',
+ timestamp: 1666631359,
+ },
+ },
+ tx: {
+ txid: '20a0b9337a78603c6681ed2bc541593375535dcd9979196620ce71f233f2f6f8',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: 'ac8be4ed7289014eb615cf8aa122cbd94283fe566142052d7ac8c6fab241fb51',
+ outIdx: 2,
+ },
+ inputScript:
+ '46304302200db47adc26bbb4ae4584ae455c5f078a4d2f624e898fab3159c74473677bc8b2021f371ea6c9acd051c96eaba2b229d06a0247dad2acf6cf0694792d22280dfe8e412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 1253,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e45534953035653500b56657370656e65204761733468747470733a2f2f73696d706c652e77696b6970656469612e6f72672f77696b692f5374617243726166742347616d65706c61794c0001094c000829a2241af62c0000',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ '20a0b9337a78603c6681ed2bc541593375535dcd9979196620ce71f233f2f6f8',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '3000000000000000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: 'fc1ada187e9f5da7616f481c79cd0fa3aafa3d4094288db6806e7508f76b5fcd',
+ outIdx: 1,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 299,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '20a0b9337a78603c6681ed2bc541593375535dcd9979196620ce71f233f2f6f8',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 763087,
+ hash: '0000000000000000015abcebc15e74036598855a9fdd976868ad99bb23b87a89',
+ timestamp: 1666631359,
+ },
+ },
+ calculated: {
+ genesisSupply: '3000000000.000000000',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ '4db25a4b2f0b57415ce25fab6d9cb3ac2bbb444ff493dc16d0615a11ad06c875': {
+ token: {
+ tokenId:
+ '4db25a4b2f0b57415ce25fab6d9cb3ac2bbb444ff493dc16d0615a11ad06c875',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'LVV',
+ tokenName: 'Lambda Variant Variants',
+ url: 'https://cashtabapp.com/',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 700722,
+ hash: '0000000000000000260ee4c3b4f4ddde127bc0105d685c0ef31775b612627222',
+ timestamp: 1629500864,
+ },
+ },
+ tx: {
+ txid: '4db25a4b2f0b57415ce25fab6d9cb3ac2bbb444ff493dc16d0615a11ad06c875',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: 'a5d17c2df7244939f73101bb55a0aeb91f53bb7117efb04047b7db645e145933',
+ outIdx: 1,
+ },
+ inputScript:
+ '4830450221008100fd6256019f3c8709ffe685fedec9dbf452951a44dcd1b928d0c9095b3d1b02204a756b30558ae60a673c28163e3c10bd1152d41be093aa7ad1d32f5886bc66e6412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 138443635,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e45534953034c5656174c616d6264612056617269616e742056617269616e74731768747470733a2f2f636173687461626170702e636f6d2f4c0001004c000800000000000f4240',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ '4db25a4b2f0b57415ce25fab6d9cb3ac2bbb444ff493dc16d0615a11ad06c875',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '1000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: 'ef80e1ceeada69a9639c320c1fba47ea4417cd3aad1be1635c3472ce28aaef33',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 138442566,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ spentBy: {
+ txid: '87faad4f282002da1a9d74059dbebfa41aff3df27a66b5fd01184c5f8afdf283',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 318,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '4db25a4b2f0b57415ce25fab6d9cb3ac2bbb444ff493dc16d0615a11ad06c875',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 700722,
+ hash: '0000000000000000260ee4c3b4f4ddde127bc0105d685c0ef31775b612627222',
+ timestamp: 1629500864,
+ },
+ },
+ calculated: {
+ genesisSupply: '1000000',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ '98183238638ecb4ddc365056e22de0e8a05448c1e6084bae247fae5a74ad4f48': {
+ token: {
+ tokenId:
+ '98183238638ecb4ddc365056e22de0e8a05448c1e6084bae247fae5a74ad4f48',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'DVV',
+ tokenName: 'Delta Variant Variants',
+ url: 'https://cashtabapp.com/',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 700469,
+ hash: '00000000000000000bb5f9bb8e292c0017c34e05708f74eae3ae09ff18f6bc89',
+ timestamp: 1629339994,
+ },
+ },
+ tx: {
+ txid: '98183238638ecb4ddc365056e22de0e8a05448c1e6084bae247fae5a74ad4f48',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '846c8e4045e8ba51ce3fed18bf2270ecfd5a448cb78adf6f22cae3bf89394075',
+ outIdx: 1,
+ },
+ inputScript:
+ '483045022100b0469fe06b1f961932edb02186baa703c65b796ffdc44ee8a81eb5d2ea532b44022075f34517bbbc68200e4d7fc7a5f2fbcebb8cc101044bda8b49ed47d9355e4a03412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 1121620547,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e45534953034456561644656c74612056617269616e742056617269616e74731768747470733a2f2f636173687461626170702e636f6d2f4c0001004c0008000000003b9ac9ff',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ '98183238638ecb4ddc365056e22de0e8a05448c1e6084bae247fae5a74ad4f48',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '999999999',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: 'e9675fb89a91fd2644e098d5865dcd8de1549d18577247d55813a9f8b383eb12',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 1121619478,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ spentBy: {
+ txid: '9eb3f392e7efd073cbe58e4d57d4c4cf755527074f935238493b0d357cc70b8d',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 317,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '98183238638ecb4ddc365056e22de0e8a05448c1e6084bae247fae5a74ad4f48',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 700469,
+ hash: '00000000000000000bb5f9bb8e292c0017c34e05708f74eae3ae09ff18f6bc89',
+ timestamp: 1629339994,
+ },
+ },
+ calculated: {
+ genesisSupply: '999999999',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ '7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d': {
+ token: {
+ tokenId:
+ '7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'WDT',
+ tokenName:
+ 'Test Token With Exceptionally Long Name For CSS And Style Revisions',
+ url: 'https://www.ImpossiblyLongWebsiteDidYouThinkWebDevWouldBeFun.org',
+ decimals: 7,
+ hash: '85b591c15c9f49531e39fcfeb2a5a26b2bd0f7c018fb9cd71b5d92dfb732d5cc',
+ },
+ block: {
+ height: 659948,
+ hash: '000000000000000002e096ec3fda458dab941cd2ab40a7be10d54e88c9b06f37',
+ timestamp: 1604423892,
+ },
+ },
+ tx: {
+ txid: '7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '14bd7a307aacb93675660b6fa957b0c8ab001d500cb07756524330f1863e9f9f',
+ outIdx: 2,
+ },
+ inputScript:
+ '47304402202cf16a38ccb1df93e60bc23b3113c05086f1a52522a98f4dcb38c3c48d7f734d02207f42466cbf73c3885b24536253f1e8262804b7774c5d867738a5c71e4464722741210361c15c24d617d75b51bd057e418020b3e7a07d91a41ddd0365bf168b418f79f6',
+ value: 46641,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a914f1f529e136738f1d93c5dc4be9306913a7f1855e88ac',
+ },
+ {
+ prevOut: {
+ txid: 'c44685e8f36e84838d11502438438c997fe79645ffe27b51e3395ef6b9a4b6e2',
+ outIdx: 0,
+ },
+ inputScript:
+ '47304402205278c22d848b7368365cfd08e64a6060e061fa9995161fef50086ad81cb2367502205f0af031e2f1bfcffd47348832e2127428abdea4f9dc0440b1dd387d84e74e8741210361c15c24d617d75b51bd057e418020b3e7a07d91a41ddd0365bf168b418f79f6',
+ value: 313547,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a914f1f529e136738f1d93c5dc4be9306913a7f1855e88ac',
+ },
+ {
+ prevOut: {
+ txid: '2441ce6b4b213afbf432e7ffd59cd597a14c2bbca0fe1a641095b5f634af7d40',
+ outIdx: 0,
+ },
+ inputScript:
+ '4730440220603fd0df5350ab5213384b57abe575ecad1627470b95a14a61c1d6d6a346056c02205505e66fee9be7ac73a8d1c8d08212dc4ac44e2e7ffd909e6790a7cd26fd68e941210361c15c24d617d75b51bd057e418020b3e7a07d91a41ddd0365bf168b418f79f6',
+ value: 31355,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a914f1f529e136738f1d93c5dc4be9306913a7f1855e88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e4553495303574454435465737420546f6b656e205769746820457863657074696f6e616c6c79204c6f6e67204e616d6520466f722043535320416e64205374796c65205265766973696f6e734068747470733a2f2f7777772e496d706f737369626c794c6f6e6757656273697465446964596f755468696e6b576562446576576f756c64426546756e2e6f72672085b591c15c9f49531e39fcfeb2a5a26b2bd0f7c018fb9cd71b5d92dfb732d5cc0107010208000000e8d4a51000',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91419884c453167cf3011a3363b4b1ebd926bde059f88ac',
+ token: {
+ tokenId:
+ '7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '1000000000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: 'ed7a0eb9f80ffcad92a20a9b8eb673561bde8ce143cec05fe4635020842a4c54',
+ outIdx: 56,
+ },
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91419884c453167cf3011a3363b4b1ebd926bde059f88ac',
+ token: {
+ tokenId:
+ '7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '0',
+ isMintBaton: true,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '67605f3d18135b52d95a4877a427d100c14f2610c63ee84eaf4856f883a0b70e',
+ outIdx: 2,
+ },
+ },
+ {
+ value: 389686,
+ outputScript:
+ '76a914f1f529e136738f1d93c5dc4be9306913a7f1855e88ac',
+ spentBy: {
+ txid: 'ed7a0eb9f80ffcad92a20a9b8eb673561bde8ce143cec05fe4635020842a4c54',
+ outIdx: 55,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 761,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 659948,
+ hash: '000000000000000002e096ec3fda458dab941cd2ab40a7be10d54e88c9b06f37',
+ timestamp: 1604423892,
+ },
+ },
+ calculated: {
+ genesisSupply: '100000.0000000',
+ genesisOutputScripts: [
+ '76a91419884c453167cf3011a3363b4b1ebd926bde059f88ac',
+ ],
+ genesisMintBatons: 1,
+ },
+ },
+ 'b977630ae1b4a0fe3ab12385fdaaffd974e5bd352f2a817ce135c1ee6005a35d': {
+ token: {
+ tokenId:
+ 'b977630ae1b4a0fe3ab12385fdaaffd974e5bd352f2a817ce135c1ee6005a35d',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'DNR',
+ tokenName: 'Denarius',
+ url: 'https://cashtab.com/',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 767340,
+ hash: '00000000000000000aa6f475f0ef63c88c19d56217972534fb5cb6f98586845a',
+ timestamp: 1669201819,
+ },
+ },
+ tx: {
+ txid: 'b977630ae1b4a0fe3ab12385fdaaffd974e5bd352f2a817ce135c1ee6005a35d',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: 'bfda9787b92a3093070f65f501b8ea87e79b54e3c0a48d0f2425dfa7f85713fb',
+ outIdx: 6,
+ },
+ inputScript:
+ '47304402202fcd960b6e450dedc8c7863cf43921edab63559ef07b855388ffe8a7dc926e3302203c738c9737cfd5fa6f9df69c341e6007c09a49cabfce8db34606d5b4530ce6c1412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 2981229,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e4553495303444e520844656e61726975731468747470733a2f2f636173687461622e636f6d2f4c0001004c000800000000000002f1',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ 'b977630ae1b4a0fe3ab12385fdaaffd974e5bd352f2a817ce135c1ee6005a35d',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '753',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '5f06207dea4762524dbe2d84900cc78711d079f2b2e909867ec5e9abdeb850aa',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 2980228,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ spentBy: {
+ txid: 'fa373dbcbac25cfc409b062d9974425a82621c05cecaeaebfd7e0a5a2dc23317',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 299,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ 'b977630ae1b4a0fe3ab12385fdaaffd974e5bd352f2a817ce135c1ee6005a35d',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 767340,
+ hash: '00000000000000000aa6f475f0ef63c88c19d56217972534fb5cb6f98586845a',
+ timestamp: 1669201819,
+ },
+ },
+ calculated: {
+ genesisSupply: '753',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ '6376cae692cf0302ecdd63234c14cbb2b21cec75ab538335f90254cfb3ed44cc': {
+ token: {
+ tokenId:
+ '6376cae692cf0302ecdd63234c14cbb2b21cec75ab538335f90254cfb3ed44cc',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'CLT',
+ tokenName: 'Cashtab Local Tests',
+ url: 'https://cashtab.com/',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 720056,
+ hash: '00000000000000001539b8b8d9e7d9459eb16ad84d387fc13326a34d7e09633d',
+ timestamp: 1640867749,
+ },
+ },
+ tx: {
+ txid: '6376cae692cf0302ecdd63234c14cbb2b21cec75ab538335f90254cfb3ed44cc',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '5538f30465c7c2a9c38ec70f060530153e665b4d336f2cde4b247989c8f2b813',
+ outIdx: 2,
+ },
+ inputScript:
+ '483045022100df3fe6fcf7b2afa0d5650e4c526f122e4ed032c3f8dff2b62b950f597c7def0b02201b0ce1ae4a4abe460ccf4801986eee825ea9d2bcff91e95f3d4f66e8a0c06837412103318d0e1109f32debc66952d0e3ec21b1cf96575ea4c2a97a6535628f7f8b10e6',
+ value: 1350,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a9144e532257c01b310b3b5c1fd947c79a72addf852388ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e4553495303434c541343617368746162204c6f63616c2054657374731468747470733a2f2f636173687461622e636f6d2f4c0001004c0008000000000000c350',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a9144e532257c01b310b3b5c1fd947c79a72addf852388ac',
+ token: {
+ tokenId:
+ '6376cae692cf0302ecdd63234c14cbb2b21cec75ab538335f90254cfb3ed44cc',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '50000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '9c6363fb537d529f512a12d292ea9682fe7159e6bf5ebfec5b7067b401d2dba4',
+ outIdx: 1,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 277,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '6376cae692cf0302ecdd63234c14cbb2b21cec75ab538335f90254cfb3ed44cc',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 720056,
+ hash: '00000000000000001539b8b8d9e7d9459eb16ad84d387fc13326a34d7e09633d',
+ timestamp: 1640867749,
+ },
+ },
+ calculated: {
+ genesisSupply: '50000',
+ genesisOutputScripts: [
+ '76a9144e532257c01b310b3b5c1fd947c79a72addf852388ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ 'bd1acc4c986de57af8d6d2a64aecad8c30ee80f37ae9d066d758923732ddc9ba': {
+ token: {
+ tokenId:
+ 'bd1acc4c986de57af8d6d2a64aecad8c30ee80f37ae9d066d758923732ddc9ba',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'TBS',
+ tokenName: 'TestBits',
+ url: 'https://thecryptoguy.com/',
+ decimals: 9,
+ hash: '',
+ },
+ block: {
+ height: 662989,
+ hash: '000000000000000022f3b95ea9544c77938f232601b87a82b5c375b81e0123ae',
+ timestamp: 1607034208,
+ },
+ },
+ tx: {
+ txid: 'bd1acc4c986de57af8d6d2a64aecad8c30ee80f37ae9d066d758923732ddc9ba',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '9b4361b24c756ff7a74ea5261be565acade0b246fb85422086ac273c1e4ee7d5',
+ outIdx: 2,
+ },
+ inputScript:
+ '4730440220033fd897a0c6ae88eac326562de260264e3197b336508b584d81f244e5a47b7a022013f78b1f954eab4027e377745315f9c35811ec2802fc4d7c4280312aa9e7eee94121034509251caa5f01e2787c436949eb94d71dcc451bcde5791ae5b7109255f5f0a3',
+ value: 94032,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a914b8d9512d2adf8b4e70c45c26b6b00d75c28eaa9688ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e45534953035442530854657374426974731968747470733a2f2f74686563727970746f6775792e636f6d2f4c0001090102088ac7230489e80000',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a914b8d9512d2adf8b4e70c45c26b6b00d75c28eaa9688ac',
+ token: {
+ tokenId:
+ 'bd1acc4c986de57af8d6d2a64aecad8c30ee80f37ae9d066d758923732ddc9ba',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '10000000000000000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: 'be38b0488679e25823b7a72b925ac695a7b486e7f78122994b913f3079b0b939',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a914b8d9512d2adf8b4e70c45c26b6b00d75c28eaa9688ac',
+ token: {
+ tokenId:
+ 'bd1acc4c986de57af8d6d2a64aecad8c30ee80f37ae9d066d758923732ddc9ba',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '0',
+ isMintBaton: true,
+ entryIdx: 0,
+ },
+ },
+ {
+ value: 92390,
+ outputScript:
+ '76a914b8d9512d2adf8b4e70c45c26b6b00d75c28eaa9688ac',
+ spentBy: {
+ txid: 'be38b0488679e25823b7a72b925ac695a7b486e7f78122994b913f3079b0b939',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 338,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ 'bd1acc4c986de57af8d6d2a64aecad8c30ee80f37ae9d066d758923732ddc9ba',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 662989,
+ hash: '000000000000000022f3b95ea9544c77938f232601b87a82b5c375b81e0123ae',
+ timestamp: 1607034208,
+ },
+ },
+ calculated: {
+ genesisSupply: '10000000000.000000000',
+ genesisOutputScripts: [
+ '76a914b8d9512d2adf8b4e70c45c26b6b00d75c28eaa9688ac',
+ ],
+ genesisMintBatons: 1,
+ },
+ },
+ '639a8dba34788ff3ebd3977d4ac045825394285ee648bb1d159e1c12b787ff25': {
+ token: {
+ tokenId:
+ '639a8dba34788ff3ebd3977d4ac045825394285ee648bb1d159e1c12b787ff25',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'CFL',
+ tokenName: 'Cashtab Facelift',
+ url: 'https://cashtab.com/',
+ decimals: 9,
+ hash: '',
+ },
+ block: {
+ height: 726826,
+ hash: '000000000000000007ba9fcd82bc10d70a55d4d74cb041cf234699c746d1c635',
+ timestamp: 1644953895,
+ },
+ },
+ tx: {
+ txid: '639a8dba34788ff3ebd3977d4ac045825394285ee648bb1d159e1c12b787ff25',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: 'f66bbeff49edc36dff6de0c2bf97ac4e94c3c328261ea43b5351a7d0a54d75ab',
+ outIdx: 2,
+ },
+ inputScript:
+ '4730440220365f13f47afacb3329e4dc0dbc2e68a2accb94fc08475828e4f320b93e08a36702201d3ffdb7fcd3c3240f8c0d609bcb36b446e4b4253fa7284d14eac1c3b5139844412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 9095,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e455349530343464c104361736874616220466163656c6966741468747470733a2f2f636173687461622e636f6d2f4c0001094c0008000009184e72a000',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ '639a8dba34788ff3ebd3977d4ac045825394285ee648bb1d159e1c12b787ff25',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '10000000000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: 'fefacb25eccd9c1c575da278b265c444f840e9261b041898fbf7f5cd85fb40a4',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 8026,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ spentBy: {
+ txid: 'f78ee9844a4584d6f13efbf2e40f0e488f25089aa047e61f54063894d01a3a17',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 307,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '639a8dba34788ff3ebd3977d4ac045825394285ee648bb1d159e1c12b787ff25',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 726826,
+ hash: '000000000000000007ba9fcd82bc10d70a55d4d74cb041cf234699c746d1c635',
+ timestamp: 1644953895,
+ },
+ },
+ calculated: {
+ genesisSupply: '10000.000000000',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ '45f0ff5cae7e89da6b96c26c8c48a959214c5f0e983e78d0925f8956ca8848c6': {
+ token: {
+ tokenId:
+ '45f0ff5cae7e89da6b96c26c8c48a959214c5f0e983e78d0925f8956ca8848c6',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'CMA',
+ tokenName: 'CashtabMintAlpha',
+ url: 'https://cashtabapp.com/',
+ decimals: 5,
+ hash: '',
+ },
+ block: {
+ height: 685170,
+ hash: '000000000000000025782a5b5b44efb49f9c3f86ef7355dc36010afc6624e3fd',
+ timestamp: 1620250206,
+ },
+ },
+ tx: {
+ txid: '45f0ff5cae7e89da6b96c26c8c48a959214c5f0e983e78d0925f8956ca8848c6',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '13f063c9720d2c1a4c01d67a710a20a20ccf1d2b2312a87bfe7f0ee5c4794c46',
+ outIdx: 0,
+ },
+ inputScript:
+ '47304402201c12e609e94a9d852d553a58c5685a0398713757f274cb72f0bcb3c49abbd369022072c33f3237859575b4d616a3857704285c1027fb8cdb0d55c0580a4be60474ad412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 994663,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e4553495303434d4110436173687461624d696e74416c7068611768747470733a2f2f636173687461626170702e636f6d2f4c0001054c0008000000000054c563',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ '45f0ff5cae7e89da6b96c26c8c48a959214c5f0e983e78d0925f8956ca8848c6',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '5555555',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '9989f6f4941d7cf3206b327d957b022b41bf7e449a11fd5dd5cf1e9bc93f1ecf',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 993359,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ spentBy: {
+ txid: '92566b9ae391bf2de6c99457fa56ab5f93af66634af563dbe0e1022ebc05ecd4',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 310,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '45f0ff5cae7e89da6b96c26c8c48a959214c5f0e983e78d0925f8956ca8848c6',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 685170,
+ hash: '000000000000000025782a5b5b44efb49f9c3f86ef7355dc36010afc6624e3fd',
+ timestamp: 1620250206,
+ },
+ },
+ calculated: {
+ genesisSupply: '55.55555',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ 'a6050bea718f77e7964d140c4bb89cd88a1816eed1633f19d097835d5fa48df5': {
+ token: {
+ tokenId:
+ 'a6050bea718f77e7964d140c4bb89cd88a1816eed1633f19d097835d5fa48df5',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'IWF',
+ tokenName: 'Insanity Wolf',
+ url: 'https://cashtab.com/',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 832625,
+ hash: '00000000000000001677f56a57d820e02079e4a3ed62d7aeb0acbf7fa937b8bb',
+ timestamp: 1708546646,
+ },
+ },
+ tx: {
+ txid: 'a6050bea718f77e7964d140c4bb89cd88a1816eed1633f19d097835d5fa48df5',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '8fc76031471a09072d3de5bbc5b0a50887639882df500d4ef6c939c69c4594c2',
+ outIdx: 3,
+ },
+ inputScript:
+ '4830450221009fe4253fe41a5badda24212d6af2120a52cae193629d216cbf830f693f2f57050220359de2e48f8506b7633341c52228c4249d00ec4e3504ee283827cee869fbc309412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 3317,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e45534953034957460d496e73616e69747920576f6c661468747470733a2f2f636173687461622e636f6d2f4c0001004c000800000000000003e8',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ 'a6050bea718f77e7964d140c4bb89cd88a1816eed1633f19d097835d5fa48df5',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '1000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ },
+ {
+ value: 2157,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ spentBy: {
+ txid: 'd8c694714c2d39a22b8d867530f37e796937ac4b9bc7c9528926649788d15f43',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 305,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ 'a6050bea718f77e7964d140c4bb89cd88a1816eed1633f19d097835d5fa48df5',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 832625,
+ hash: '00000000000000001677f56a57d820e02079e4a3ed62d7aeb0acbf7fa937b8bb',
+ timestamp: 1708546646,
+ },
+ },
+ calculated: {
+ genesisSupply: '1000',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ 'b19b4c83056f6e3dace0e786446a8ccd73f22cfc42c3013808c532ab43490a14': {
+ token: {
+ tokenId:
+ 'b19b4c83056f6e3dace0e786446a8ccd73f22cfc42c3013808c532ab43490a14',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'GYP',
+ tokenName: 'Gypsum',
+ url: 'https://cashtab.com/',
+ decimals: 9,
+ hash: '',
+ },
+ block: {
+ height: 832778,
+ hash: '000000000000000002113ac0f6519d1a51a933bb5c8f665875d5ff5ead6e0274',
+ timestamp: 1708641780,
+ },
+ },
+ tx: {
+ txid: 'b19b4c83056f6e3dace0e786446a8ccd73f22cfc42c3013808c532ab43490a14',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: 'ef1ddcac70e02ad6caf2dc37f0a337d349c8abaf32312b55e7dfaa6085643b06',
+ outIdx: 0,
+ },
+ inputScript:
+ '473044022002d7028ecd2a1ece84ce03160fdb5e93784b954c31382ffd3e78c75aca4ef16302205f81fdb6993f63b963f1a0590d4e32e51b5ad8383ad09ee4182ffd2966673a7a412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 998111,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e45534953034759500647797073756d1468747470733a2f2f636173687461622e636f6d2f4c0001094c00088ac7230489e80000',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ 'b19b4c83056f6e3dace0e786446a8ccd73f22cfc42c3013808c532ab43490a14',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '10000000000000000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '56cc72b07a374990d767a569120308812d0da4ef0c0d669a1966a648e759669a',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 996966,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ spentBy: {
+ txid: '51bc5da566c85b486b37f1c4d3c0220b7bc11ad992c1b92f99233cf35a8794c1',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 297,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ 'b19b4c83056f6e3dace0e786446a8ccd73f22cfc42c3013808c532ab43490a14',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 832778,
+ hash: '000000000000000002113ac0f6519d1a51a933bb5c8f665875d5ff5ead6e0274',
+ timestamp: 1708641780,
+ },
+ },
+ calculated: {
+ genesisSupply: '10000000000.000000000',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ 'fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa': {
+ token: {
+ tokenId:
+ 'fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'GRP',
+ tokenName: 'GRUMPY',
+ url: 'https://bit.ly/GrumpyDoc',
+ decimals: 2,
+ hash: '',
+ },
+ block: {
+ height: 713853,
+ hash: '0000000000000000006a051e51b50e44d3394ab49c9db896c2484770ed613fb2',
+ timestamp: 1637109257,
+ },
+ },
+ tx: {
+ txid: 'fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: 'b8af3a4ad68cc300e1f9d331762a1a62c0c344c3b3fb554af6a35e634907feab',
+ outIdx: 0,
+ },
+ inputScript:
+ '47304402204db8555a3141e86b979257feadc41e903a779a61971e2e63a386f1084c52ff2a022010d7f7f9d41b474ff5c4bd979916e2cd29627a2d6194fcc6af6485a979091cbe412103632f603f43ae61afece65288d7d92e55188783edb74e205be974b8cd1cd36a1e',
+ value: 50000,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a9141c13ddb8dd422bbe02dc2ae8798b4549a67a3c1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e4553495303475250064752554d50591868747470733a2f2f6269742e6c792f4772756d7079446f634c0001024c0008000000e8d4a51000',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a9141c13ddb8dd422bbe02dc2ae8798b4549a67a3c1d88ac',
+ token: {
+ tokenId:
+ 'fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '1000000000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '94cc23c0a01ee35b8b9380b739f1f8d8f6d0e2c09a7785f3d63b928afd23357f',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 48931,
+ outputScript:
+ '76a9141c13ddb8dd422bbe02dc2ae8798b4549a67a3c1d88ac',
+ spentBy: {
+ txid: '94cc23c0a01ee35b8b9380b739f1f8d8f6d0e2c09a7785f3d63b928afd23357f',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 301,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ 'fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 713853,
+ hash: '0000000000000000006a051e51b50e44d3394ab49c9db896c2484770ed613fb2',
+ timestamp: 1637109257,
+ },
+ },
+ calculated: {
+ genesisSupply: '10000000000.00',
+ genesisOutputScripts: [
+ '76a9141c13ddb8dd422bbe02dc2ae8798b4549a67a3c1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ '79c5a1cec698350dd93f645fcae8d6ff3902b7cdc582839dfface3cb0c83d823': {
+ token: {
+ tokenId:
+ '79c5a1cec698350dd93f645fcae8d6ff3902b7cdc582839dfface3cb0c83d823',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'TRIB',
+ tokenName: 'eCash Herald',
+ url: 'https://cashtab.com/',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 782665,
+ hash: '00000000000000001239831f90580c859ec174316e91961cf0e8cde57c0d3acb',
+ timestamp: 1678408305,
+ },
+ },
+ tx: {
+ txid: '79c5a1cec698350dd93f645fcae8d6ff3902b7cdc582839dfface3cb0c83d823',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: 'b6b9ae8ea74be20c82307df38d9ba3994e77613b1fe26b25d5688fcbd4f468f8',
+ outIdx: 1,
+ },
+ inputScript:
+ '47304402204297897dbf74589a2e4872c488144d98a03f446878f7e4d22833bf221faf127002201c33519f5e3f662ac3e0da53ff35ef40057d482bfb75310c0c05d402b208dfdf412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 9039904,
+ sequenceNo: 4294967294,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e4553495304545249420c654361736820486572616c641468747470733a2f2f636173687461622e636f6d2f4c0001004c00080000000000002710',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ '79c5a1cec698350dd93f645fcae8d6ff3902b7cdc582839dfface3cb0c83d823',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '10000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '27a2471afab33d82b9404df12e1fa242488a9439a68e540dcf8f811ef39c11cf',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 9038903,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ spentBy: {
+ txid: 'ff2d098a14929713f392d46963c5b09c2fa5f38f84793f04e55e94f3bc7eac23',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 304,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '79c5a1cec698350dd93f645fcae8d6ff3902b7cdc582839dfface3cb0c83d823',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 782665,
+ hash: '00000000000000001239831f90580c859ec174316e91961cf0e8cde57c0d3acb',
+ timestamp: 1678408305,
+ },
+ },
+ calculated: {
+ genesisSupply: '10000',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109': {
+ token: {
+ tokenId:
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'BEAR',
+ tokenName: 'BearNip',
+ url: 'https://cashtab.com/',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 782665,
+ hash: '00000000000000001239831f90580c859ec174316e91961cf0e8cde57c0d3acb',
+ timestamp: 1678408305,
+ },
+ },
+ tx: {
+ txid: '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '0e737a2f6373649341b406334341202a5ddbbdb389c55da40570b641dc23d036',
+ outIdx: 1,
+ },
+ inputScript:
+ '473044022055444db90f98b462ca29a6f51981da4015623ddc34dc1f575852426ccb785f0402206e786d4056be781ca1720a0a915b040e0a9e8716b8e4d30b0779852c191fdeb3412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 6231556,
+ sequenceNo: 4294967294,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e45534953044245415207426561724e69701468747470733a2f2f636173687461622e636f6d2f4c0001004c0008000000000000115c',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '4444',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '9e7f91826cfd3adf9867c1b3d102594eff4743825fad9883c35d26fb3bdc1693',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 6230555,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ spentBy: {
+ txid: '27a2471afab33d82b9404df12e1fa242488a9439a68e540dcf8f811ef39c11cf',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 299,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 782665,
+ hash: '00000000000000001239831f90580c859ec174316e91961cf0e8cde57c0d3acb',
+ timestamp: 1678408305,
+ },
+ },
+ calculated: {
+ genesisSupply: '4444',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ '01d63c4f4cb496829a6743f7b1805d086ea3877a1dd34b3f92ffba2c9c99f896': {
+ token: {
+ tokenId:
+ '01d63c4f4cb496829a6743f7b1805d086ea3877a1dd34b3f92ffba2c9c99f896',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'BULL',
+ tokenName: 'Bull',
+ url: 'https://cashtab.com/',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 835482,
+ hash: '0000000000000000133bf16cb7fdab5c6ff64a874632eb2fe80265e34a6ad99f',
+ timestamp: 1710174132,
+ },
+ },
+ tx: {
+ txid: '01d63c4f4cb496829a6743f7b1805d086ea3877a1dd34b3f92ffba2c9c99f896',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: 'f211007def30735a245bdaa6f9efe429c999e02713f6ce6328478da3444b7248',
+ outIdx: 1,
+ },
+ inputScript:
+ '47304402207801a307548c5ecccd6e37043bda5e96cb9d27c93e4e60deaff4344605f138b202201a7fd155a42171c4b3331425b3e708df4e9606edfd221b2e500e3fb6bb541f2b412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 981921,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e455349530442554c4c0442756c6c1468747470733a2f2f636173687461622e636f6d2f4c0001004c00080000000001406f40',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ '01d63c4f4cb496829a6743f7b1805d086ea3877a1dd34b3f92ffba2c9c99f896',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '21000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ },
+ {
+ value: 981078,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ spentBy: {
+ txid: '4d8c8d06b724493f5ab172a18d9bf9f4d8419c09bc5a93fe780902b21dab75ba',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 296,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '01d63c4f4cb496829a6743f7b1805d086ea3877a1dd34b3f92ffba2c9c99f896',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 835482,
+ hash: '0000000000000000133bf16cb7fdab5c6ff64a874632eb2fe80265e34a6ad99f',
+ timestamp: 1710174132,
+ },
+ },
+ calculated: {
+ genesisSupply: '21000000',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ '666c4318d1f7fef5f2c698262492c519018d4e9130f95d05f6be9f0fb7149e96': {
+ token: {
+ tokenId:
+ '666c4318d1f7fef5f2c698262492c519018d4e9130f95d05f6be9f0fb7149e96',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'CPG',
+ tokenName: 'Cashtab Prod Gamma',
+ url: 'thecryptoguy.com',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 688495,
+ hash: '000000000000000028aa42a7c622846b742465dfaaf41d29f955c1b8ee890c9e',
+ timestamp: 1622237370,
+ },
+ },
+ tx: {
+ txid: '666c4318d1f7fef5f2c698262492c519018d4e9130f95d05f6be9f0fb7149e96',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: 'd83677da1b3ade24e9fdcc2a47e3ba87e1fbe1de9e13075d79d16819952a8789',
+ outIdx: 1,
+ },
+ inputScript:
+ '473044022026270f7aea8af1edf82758749f1e1c68accbb3a2719e9c37a49b55f098a4c22302206f5be10f536837f0001f555e968a7a977186d5acfa405e0e47b9df033815ccee412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 26811307,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e455349530343504712436173687461622050726f642047616d6d611074686563727970746f6775792e636f6d4c0001004c00080000000000000064',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ '666c4318d1f7fef5f2c698262492c519018d4e9130f95d05f6be9f0fb7149e96',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '100',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: 'fb50eac73a4fd5e2a701e0dbf4e575cea9c083e061b1db722e057164c7317e5b',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 26810238,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ spentBy: {
+ txid: '5f0ab0ecfb8807dfdbc97eb421b940cef3c1c70a4c99fd96c39414de42f32338',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 305,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '666c4318d1f7fef5f2c698262492c519018d4e9130f95d05f6be9f0fb7149e96',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 688495,
+ hash: '000000000000000028aa42a7c622846b742465dfaaf41d29f955c1b8ee890c9e',
+ timestamp: 1622237370,
+ },
+ },
+ calculated: {
+ genesisSupply: '100',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ 'b132878bfa81cf1b9e19192045ed4c797b10944cc17ae07da06aed3d7b566cb7': {
+ token: {
+ tokenId:
+ 'b132878bfa81cf1b9e19192045ed4c797b10944cc17ae07da06aed3d7b566cb7',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'ABC',
+ tokenName: 'ABC',
+ url: 'https://cashtab.com/',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 832725,
+ hash: '000000000000000016d97961a24ac3460160bbc439810cd2af684264ae15083b',
+ timestamp: 1708607039,
+ },
+ },
+ tx: {
+ txid: 'b132878bfa81cf1b9e19192045ed4c797b10944cc17ae07da06aed3d7b566cb7',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '9866faa3294afc3f4dd5669c67ee4d0ded42db25d08728fe07166e9cda9ee8f9',
+ outIdx: 3,
+ },
+ inputScript:
+ '483045022100fb14b5f82605972478186c91ff6fab2051b46abd2a8aa9774b3e9276715daf39022046a62933cc3acf59129fbf373ef05480342312bc33aaa8bf7fb5a0495b5dc80e412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 1617,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e4553495303414243034142431468747470733a2f2f636173687461622e636f6d2f4c0001004c0008000000000000000c',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ 'b132878bfa81cf1b9e19192045ed4c797b10944cc17ae07da06aed3d7b566cb7',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '12',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '41fd4cb3ce0162e44cfd5a446b389afa6b35461d466d55321be412a518c56d63',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 261,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ 'b132878bfa81cf1b9e19192045ed4c797b10944cc17ae07da06aed3d7b566cb7',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 832725,
+ hash: '000000000000000016d97961a24ac3460160bbc439810cd2af684264ae15083b',
+ timestamp: 1708607039,
+ },
+ },
+ calculated: {
+ genesisSupply: '12',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ '9404761d1a01cca11c29eb8ed9ddc63966526d0eaa54f148e8862ab3e884132f': {
+ token: {
+ tokenId:
+ '9404761d1a01cca11c29eb8ed9ddc63966526d0eaa54f148e8862ab3e884132f',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timeFirstSeen: '1711020786',
+ genesisInfo: {
+ tokenTicker: 'CAFF',
+ tokenName: 'Coffee',
+ url: 'https://cashtab.com/',
+ decimals: 9,
+ hash: '',
+ },
+ block: {
+ height: 836820,
+ hash: '00000000000000000afa24f7d3cab51184e1469cecd61bf472d3a3fcc907bc19',
+ timestamp: 1711021281,
+ },
+ },
+ tx: {
+ txid: '9404761d1a01cca11c29eb8ed9ddc63966526d0eaa54f148e8862ab3e884132f',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '1dcefe4f3afa79c312641d57497b0db7bc9ef85f4e119a3e6c9968ce1507443c',
+ outIdx: 2,
+ },
+ inputScript:
+ '473044022018a26c1aaade553fd448ef86c8511bc8e603b755267588ed2406789c5e5fbc69022011a48bcb93c1ec7384b23c4a9b5b3c8a059bf3cb427a02935bc6e4ab77c810df412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 2214,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e45534953044341464606436f666665651468747470733a2f2f636173687461622e636f6d2f4c0001094c00080000000cce416600',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ '9404761d1a01cca11c29eb8ed9ddc63966526d0eaa54f148e8862ab3e884132f',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '55000000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ },
+ {
+ value: 1369,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 1711020786,
+ size: 298,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '9404761d1a01cca11c29eb8ed9ddc63966526d0eaa54f148e8862ab3e884132f',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 836820,
+ hash: '00000000000000000afa24f7d3cab51184e1469cecd61bf472d3a3fcc907bc19',
+ timestamp: 1711021281,
+ },
+ },
+ calculated: {
+ genesisSupply: '55.000000000',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ '16b12bbacdbb8c8a799adbfd782bfff9843c1f9b0be148eaae02a1a7f74f95c4': {
+ token: {
+ tokenId:
+ '16b12bbacdbb8c8a799adbfd782bfff9843c1f9b0be148eaae02a1a7f74f95c4',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'CGEN',
+ tokenName: 'Cashtab Genesis',
+ url: 'https://boomertakes.com/',
+ decimals: 9,
+ hash: '',
+ },
+ block: {
+ height: 684837,
+ hash: '00000000000000001d065fdd22416c4e8e99803964f4fb9c91af6feb5ead5ff3',
+ timestamp: 1620082584,
+ },
+ },
+ tx: {
+ txid: '16b12bbacdbb8c8a799adbfd782bfff9843c1f9b0be148eaae02a1a7f74f95c4',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '11ae0a8c62deeadbffe82ddea823e731dba7172a672bd98628bf8bd3c0e15b50',
+ outIdx: 3,
+ },
+ inputScript:
+ '473044022009777275694aab45f8c5589308b8f525c4b9b7f0b0a4b80b01531988313e92fc02206e7f0afa725f407f59f85482f26ea20a70c5fe533c0592c95733a4418054c025412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 1497156989,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e45534953044347454e0f436173687461622047656e657369731868747470733a2f2f626f6f6d657274616b65732e636f6d2f4c0001094c000800038d7ea4c68000',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ '16b12bbacdbb8c8a799adbfd782bfff9843c1f9b0be148eaae02a1a7f74f95c4',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '1000000000000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '4f5af8d3dc9d1fb3dc803a80589cab62c78235264aa90e4f8066b7960804cd74',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 1497155685,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ spentBy: {
+ txid: '0916e71779c9de7ee125741d3f5ab01f556356dbc86fd327a24f1e9e22ebc917',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 311,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '16b12bbacdbb8c8a799adbfd782bfff9843c1f9b0be148eaae02a1a7f74f95c4',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 684837,
+ hash: '00000000000000001d065fdd22416c4e8e99803964f4fb9c91af6feb5ead5ff3',
+ timestamp: 1620082584,
+ },
+ },
+ calculated: {
+ genesisSupply: '1000000.000000000',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+};
+export const keyValueBalanceArray = [
+ ['bf24d955f59351e738ecd905966606a6837e478e1982943d724eab10caad82fd', '1'],
+ ['dd84ca78db4d617221b58eabc6667af8fe2f7eadbfcc213d35be9f1b419beb8d', '1'],
+ ['50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e', '1'],
+ [
+ 'f36e1b3d9a2aaf74f132fef3834e9743b945a667a4204e761b85f2e7b65fd41a',
+ '1200',
+ ],
+ ['e859eeb52e7afca6217fb36784b3b6d3c7386a52f391dd0d00f2ec03a5e8e77b', '1.0'],
+ ['44929ff3b1fc634f982fede112cf12b21199a2ebbcf718412a38de9177d77168', '2'],
+ [
+ 'b40d1f6acdb6ee68d7eca0167fe2753c076bc309b2e3b1af8bff70ca34b945b0',
+ '5000',
+ ],
+ [
+ '8ead21ce4b3b9e7b57607b97b65b5013496dc6e3dfdea162c08ce7265a66ebc8',
+ '1.00000000',
+ ],
+ ['77ec4036ef8546ac46df6d3a5374e961216f92624627eaeef5d2e1a253df9fc6', '116'],
+ ['da9460ce4b1c92b4f6ef4e4a6bc2d05539f49d02b17681389d9ce22b8dca50f0', '311'],
+ [
+ '54dc2ecd5251f8dfda4c4f15ce05272116b01326076240e2b9cc0104d33b1484',
+ '504680.0000',
+ ],
+ [
+ 'cf601c56b58bc05a39a95374a4a865f0a8b56544ea937b30fb46315441717c50',
+ '777.7777777',
+ ],
+ [
+ 'acba1d7f354c6d4d001eb99d31de174e5cea8a31d692afd6e7eb8474ad541f55',
+ '.246913633',
+ ],
+ [
+ '0916e71779c9de7ee125741d3f5ab01f556356dbc86fd327a24f1e9e22ebc917',
+ '1699',
+ ],
+ [
+ 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb',
+ '.99999998',
+ ],
+ [
+ 'ccf5fe5a387559c8ab9efdeb0c0ef1b444e677298cfddf07671245ce3cb3c79f',
+ '424.00000000',
+ ],
+ ['7f8889682d57369ed0e32336f8b7e0ffec625a35cca183f4e81fde4e71a538a1', '1'],
+ [
+ 'bdb3b4215ca0622e0c4c07655522c376eaa891838a82f0217fa453bb0595a37c',
+ '19889',
+ ],
+ ['157e0cdef5d5c51bdea00eac9ab821d809bb9d03cf98da85833614bedb129be6', '82'],
+ [
+ '1101bd5d7b6bbc3176fb2b93d08e76ab532b04ff731d71502249e3cb9b6fcb1a',
+ '999882.000000000',
+ ],
+ [
+ '6e24e89b6d5284138c69777527760500b99614631bca7f2a5c38f4648dae9524',
+ '999999878',
+ ],
+ [
+ '4bd147fc5d5ff26249a9299c46b80920c0b81f59a60e05428262160ebee0b0c3',
+ '996012',
+ ],
+ ['b9877d8f8d2364b983707df905d592f534a3ada18e52aa529a0f72fcc535abf7', '3'],
+ [
+ 'b8f2a9e767a0be7b80c7e414ef2534586d4da72efddb39a4e70e501ab73375cc',
+ '8988',
+ ],
+ ['70ead4d94c43fe8c5576bb2528fd54380d8356f632ac962b1e03fb287607dfd4', '100'],
+ ['ff9aa6eebcd1331f8684d53b441cfa3060a4ffc403b417d5728de8ab231f5516', '100'],
+ ['f077f207fc8a8557e5f0ffc6021685ab4b357e9b92d2b5c4192dcb7760ee6e29', '100'],
+ [
+ '3adbf501e21c711d20118e003711168eb39f560c01f4c6d6736fa3f3fceaa577',
+ '999998999',
+ ],
+ [
+ '3de671a7107d3803d78f7f4a4e5c794d0903a8d28d16076445c084943c1e2db8',
+ '21.00',
+ ],
+ [
+ '20a0b9337a78603c6681ed2bc541593375535dcd9979196620ce71f233f2f6f8',
+ '2998978719.999999999',
+ ],
+ [
+ '4db25a4b2f0b57415ce25fab6d9cb3ac2bbb444ff493dc16d0615a11ad06c875',
+ '999824',
+ ],
+ [
+ '98183238638ecb4ddc365056e22de0e8a05448c1e6084bae247fae5a74ad4f48',
+ '999977636',
+ ],
+ [
+ '7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d',
+ '523512085.8888890',
+ ],
+ ['b977630ae1b4a0fe3ab12385fdaaffd974e5bd352f2a817ce135c1ee6005a35d', '727'],
+ ['6376cae692cf0302ecdd63234c14cbb2b21cec75ab538335f90254cfb3ed44cc', '121'],
+ [
+ 'bd1acc4c986de57af8d6d2a64aecad8c30ee80f37ae9d066d758923732ddc9ba',
+ '24.999698951',
+ ],
+ [
+ '639a8dba34788ff3ebd3977d4ac045825394285ee648bb1d159e1c12b787ff25',
+ '1.000000000',
+ ],
+ [
+ '45f0ff5cae7e89da6b96c26c8c48a959214c5f0e983e78d0925f8956ca8848c6',
+ '53.44445',
+ ],
+ [
+ 'a6050bea718f77e7964d140c4bb89cd88a1816eed1633f19d097835d5fa48df5',
+ '1000',
+ ],
+ [
+ 'b19b4c83056f6e3dace0e786446a8ccd73f22cfc42c3013808c532ab43490a14',
+ '10000000000.000000000',
+ ],
+ [
+ 'fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa',
+ '100000000.00',
+ ],
+ [
+ '79c5a1cec698350dd93f645fcae8d6ff3902b7cdc582839dfface3cb0c83d823',
+ '9899',
+ ],
+ [
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ '4283',
+ ],
+ [
+ '01d63c4f4cb496829a6743f7b1805d086ea3877a1dd34b3f92ffba2c9c99f896',
+ '21000000',
+ ],
+ ['666c4318d1f7fef5f2c698262492c519018d4e9130f95d05f6be9f0fb7149e96', '94'],
+ ['b132878bfa81cf1b9e19192045ed4c797b10944cc17ae07da06aed3d7b566cb7', '5'],
+ [
+ '9404761d1a01cca11c29eb8ed9ddc63966526d0eaa54f148e8862ab3e884132f',
+ '55.000000000',
+ ],
+ [
+ '16b12bbacdbb8c8a799adbfd782bfff9843c1f9b0be148eaae02a1a7f74f95c4',
+ '844601.876543211',
+ ],
+];
+
+// Build a mock token cache from these chronik mocks
+const largeTokenCache = new CashtabCache().tokens;
+for (const tokenId of Object.keys(chronikTokenMocks)) {
+ const { token, calculated } = chronikTokenMocks[tokenId];
+ const { timeFirstSeen, genesisInfo, tokenType } = token;
+ const { genesisSupply, genesisOutputScripts, genesisMintBatons } =
+ calculated;
+ const cachedInfo = {
+ timeFirstSeen,
+ genesisInfo,
+ tokenType,
+ genesisSupply,
+ genesisOutputScripts,
+ genesisMintBatons,
+ };
+ if ('block' in token) {
+ cachedInfo.block = token.block;
+ }
+ largeTokenCache.set(tokenId, cachedInfo);
+}
+export const mockLargeTokenCache = largeTokenCache;
+
+/**
+ * getTxHistory mocks
+ * Mock a wallet with tx history at two different paths to confirm expected behavior
+ */
+
+export const mockTxHistoryWalletJson = {
+ ...validWalletJson,
+ paths: [
+ [
+ 1899,
+ {
+ address: 'ecash:qz2708636snqhsxu8wnlka78h6fdp77ar59jrf5035',
+ hash: '95e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d',
+ wif: 'string',
+ },
+ ],
+ [
+ 145,
+ {
+ address: 'ecash:qqxefwshnmppcsjp0fc6w7rnkdsexc7cagdus7ugd0',
+ hash: '0d94ba179ec21c42417a71a77873b3619363d8ea',
+ wif: 'string',
+ },
+ ],
+ ],
+};
+export const mockPath1899History = [
+ {
+ txid: '66c3321dcaf4eba9e05b6167e9714c4a7b660917c2f5d29d65a519944d4c62e7',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '7171e77e21a57df5193fe387aa5e3d646dd5438c18c80a5a997fd3c2300fc679',
+ outIdx: 1,
+ },
+ inputScript:
+ '483045022100fbe76f31450482a18941ed90fee302662e5e6184d9d84fda6f2a4df9b1d1697a022041432311f5563007d46ade3536fb5988b9c97e2e8aeeec59c15c3efb5c4d0f70412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 1676077,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 1100,
+ outputScript:
+ '76a91476458db0ed96fe9863fc1ccec9fa2cfab884b0f688ac',
+ spentBy: {
+ txid: '24eae444d765406d8362da437d66a7cf50b95685198692bd2253bafd4bd003a0',
+ outIdx: 2,
+ },
+ },
+ {
+ value: 1674751,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 1710794721,
+ size: 226,
+ isCoinbase: false,
+ tokenEntries: [],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
+ block: {
+ height: 836458,
+ hash: '000000000000000011a4069425835dd50ffd7eed5e7fd2e6e464e3996d74cf71',
+ timestamp: 1710799378,
+ },
+ },
+ {
+ txid: 'acc7bf16ee329a9a6c40cdaa5fca01fdfc44f143393346821b4bc58557cfb70c',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '16c72330503bc3e6435ab45ca34f4ac1e2f88701db9c8c42efa21236514ba9ed',
+ outIdx: 7,
+ },
+ inputScript:
+ '473044022066325bcd7ba631d13d08f202714626fa7ec353febc985051d56a68edc19b0f900220016d4cb2308fa378ee04b101411cbfba88d99fd5e6d8b12170e17bca3d671c79412102c237f49dd4c812f27b09d69d4c8a4da12744fda8ad63ce151fed2a3f41fd8795',
+ value: 442567277,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91476458db0ed96fe9863fc1ccec9fa2cfab884b0f688ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 3300,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ {
+ value: 442563522,
+ outputScript:
+ '76a91476458db0ed96fe9863fc1ccec9fa2cfab884b0f688ac',
+ spentBy: {
+ txid: '08fa8a346851d44fd4b6765c65008670ccadf8dabcae59686814279a449ada06',
+ outIdx: 2,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 1710794713,
+ size: 225,
+ isCoinbase: false,
+ tokenEntries: [],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
+ block: {
+ height: 836458,
+ hash: '000000000000000011a4069425835dd50ffd7eed5e7fd2e6e464e3996d74cf71',
+ timestamp: 1710799378,
+ },
+ },
+ {
+ txid: '521468e91cf3d3b32d03e60c68ac12ff94606bd535267971d886f6febb225f9d',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '3b13ffef338f913da39f5be9c1a363a87b5a6724f41b623f324c4e1b0c96e012',
+ outIdx: 1,
+ },
+ inputScript:
+ '483045022100dba6667c91a695a7b1b509c901a7ce1fc7c859f2ad4e636729efc697e09177b802206fd4a2d53eaf96e010abdc562d2cc3a19f5ee5427a868105b9814f17eb6a6d72412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 988104,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 1100,
+ outputScript:
+ '76a91476458db0ed96fe9863fc1ccec9fa2cfab884b0f688ac',
+ spentBy: {
+ txid: '24eae444d765406d8362da437d66a7cf50b95685198692bd2253bafd4bd003a0',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 986778,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 1710794691,
+ size: 226,
+ isCoinbase: false,
+ tokenEntries: [],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
+ block: {
+ height: 836458,
+ hash: '000000000000000011a4069425835dd50ffd7eed5e7fd2e6e464e3996d74cf71',
+ timestamp: 1710799378,
+ },
+ },
+ {
+ txid: '19488e3cccbbc685a1016567b2acc2b52012a541b25ed4fee43f914f788eda5e',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '16c72330503bc3e6435ab45ca34f4ac1e2f88701db9c8c42efa21236514ba9ed',
+ outIdx: 4,
+ },
+ inputScript:
+ '47304402202f1e5ef2f5f17d3c9f7b65094e903c39db01533ae24898492d30b329b98b3b4a022066cf37253c016fde0ce3b57c5a645605cfdbc10623970e97f68e66592275dc88412102c237f49dd4c812f27b09d69d4c8a4da12744fda8ad63ce151fed2a3f41fd8795',
+ value: 440000,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91476458db0ed96fe9863fc1ccec9fa2cfab884b0f688ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 1100,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ {
+ value: 438445,
+ outputScript:
+ '76a91476458db0ed96fe9863fc1ccec9fa2cfab884b0f688ac',
+ spentBy: {
+ txid: '49e2dd75d2309fee1a8c69d31090ad0f5bdd60eaf32bf1eea1ed276dab33e26f',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 1710794683,
+ size: 225,
+ isCoinbase: false,
+ tokenEntries: [],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
+ block: {
+ height: 836458,
+ hash: '000000000000000011a4069425835dd50ffd7eed5e7fd2e6e464e3996d74cf71',
+ timestamp: 1710799378,
+ },
+ },
+ {
+ txid: '914827ddc2087db0e8ca8aed3c2a701f5873ea2f96f3837d6dce6f24ab53f854',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '5b115c352a487503755bbb93582ff39e1095d698fa303c7dd31bbf19c4bbf39a',
+ outIdx: 2,
+ },
+ inputScript:
+ '4730440220268dcf8d1be3fb33cdcd79b644acb12cdbf100040a51abf828a02fe17c34a03a0220141dce2d7292a49d82f13642e854f27326607dd8e3c13f7905632d373a56c70a412102c237f49dd4c812f27b09d69d4c8a4da12744fda8ad63ce151fed2a3f41fd8795',
+ value: 546,
+ sequenceNo: 4294967295,
+ token: {
+ tokenId:
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '9',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ outputScript:
+ '76a91476458db0ed96fe9863fc1ccec9fa2cfab884b0f688ac',
+ },
+ {
+ prevOut: {
+ txid: 'b3ca2414e646fbc53c6d789a242ea9afc1e84ec1e62ed8f5d58ab93d43207b66',
+ outIdx: 0,
+ },
+ inputScript:
+ '483045022100c7106fb50492ac6726a6cae234ac7424842daee2285fb5a3c8005262a9fdbb06022061c24760989da27c0e3f372646243334d6048894a49aae3459a3f9ebabdc41d0412102c237f49dd4c812f27b09d69d4c8a4da12744fda8ad63ce151fed2a3f41fd8795',
+ value: 1100,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91476458db0ed96fe9863fc1ccec9fa2cfab884b0f688ac',
+ },
+ {
+ prevOut: {
+ txid: '848af498277a4250bde6951849df0e66b9bc5a3b8766efbd43d3e660b773edc5',
+ outIdx: 1,
+ },
+ inputScript:
+ '483045022100c1eca663e5c9f06db6f3844254ff197bbbd106897ffef37300d9ce65b17f4ece02203f80564ba7e4d833db4ef6097c69dcb9ae9abce3cc2ab2c75f17a4c23059abfa412102c237f49dd4c812f27b09d69d4c8a4da12744fda8ad63ce151fed2a3f41fd8795',
+ value: 3181522,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91476458db0ed96fe9863fc1ccec9fa2cfab884b0f688ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010453454e44203fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109080000000000000001080000000000000008',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '1',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91476458db0ed96fe9863fc1ccec9fa2cfab884b0f688ac',
+ token: {
+ tokenId:
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '8',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '94bf7fb1b2d37fed71085f9f32415f7426ed7cde692b9a9320ff6c811aa2db74',
+ outIdx: 0,
+ },
+ },
+ {
+ value: 3180811,
+ outputScript:
+ '76a91476458db0ed96fe9863fc1ccec9fa2cfab884b0f688ac',
+ spentBy: {
+ txid: '20c513c9ae5f3966f8dae10c7e0681505756a5a0b4e4f707b366cdf51663c386',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 1710794373,
+ size: 628,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'SEND',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 836458,
+ hash: '000000000000000011a4069425835dd50ffd7eed5e7fd2e6e464e3996d74cf71',
+ timestamp: 1710799378,
+ },
+ },
+];
+export const mockPath145History = [
+ {
+ txid: '490a06b01b8d1793b81b5230ce2045132af0f0ec9cc7be860bb72e6a727d5bd4',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '811a943532212685dce70bab73ba4facb06aced2f3752f5115176d4c970ef90b',
+ outIdx: 2,
+ },
+ inputScript:
+ '4830450221008a6bb3c19db22b601ca5110415e0be8c56877b58741f7d6f50c57a8bd96f988d0220507a171d02a4fa7facc463bf62ce673a69d0d28fe3b6728a683c2ffc7a93418d4121021d7fd45a888292cf3a022a95acdbcf82f9f2d5bbbfbdbc740acd558a9f25b5d0',
+ value: 546,
+ sequenceNo: 4294967295,
+ token: {
+ tokenId:
+ '20a0b9337a78603c6681ed2bc541593375535dcd9979196620ce71f233f2f6f8',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '999900000000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ outputScript:
+ '76a9140d94ba179ec21c42417a71a77873b3619363d8ea88ac',
+ },
+ {
+ prevOut: {
+ txid: 'cfe4f1458af2be9f76e7a45c47a9c450aded46d3e5b41d97dfd3c56b2c16c7ca',
+ outIdx: 2,
+ },
+ inputScript:
+ '48304502210096482807afee1009914e934326930379ea308402643e786a1ac35786160cca37022070fe57cff80dba8475598c30b9515afa5e14caebf1ba1c7599554b9f9f7c89354121021d7fd45a888292cf3a022a95acdbcf82f9f2d5bbbfbdbc740acd558a9f25b5d0',
+ value: 44907604,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a9140d94ba179ec21c42417a71a77873b3619363d8ea88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010453454e442020a0b9337a78603c6681ed2bc541593375535dcd9979196620ce71f233f2f6f80800000007aef40a000800038d5fad5b8e00',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a9146ffbe7c7d7bd01295eb1e371de9550339bdcf9fd88ac',
+ token: {
+ tokenId:
+ '20a0b9337a78603c6681ed2bc541593375535dcd9979196620ce71f233f2f6f8',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '33000000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a9140d94ba179ec21c42417a71a77873b3619363d8ea88ac',
+ token: {
+ tokenId:
+ '20a0b9337a78603c6681ed2bc541593375535dcd9979196620ce71f233f2f6f8',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '999867000000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ },
+ {
+ value: 44906091,
+ outputScript:
+ '76a9140d94ba179ec21c42417a71a77873b3619363d8ea88ac',
+ spentBy: {
+ txid: 'd711c97ff4fe19df3419c570b082bfefc99e5b3d093c0ca8e8397404573c98f3',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 481,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '20a0b9337a78603c6681ed2bc541593375535dcd9979196620ce71f233f2f6f8',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'SEND',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 833081,
+ hash: '0000000000000000158bbff44ccbfe7b4dcfa9cbd48d58a225c0cf92e199f2e9',
+ timestamp: 1708821393,
+ },
+ },
+ {
+ txid: '8bf2566feb21f4681fbf97155d78b388b9fc1fd6a6e4bc0e21324db5a9e7a7ac',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '7e1a29815174e7bb1af2275d8d15a31f3b6f9a6567d8489da1da406f85c809bf',
+ outIdx: 1,
+ },
+ inputScript:
+ '483045022100c2bc2700a443a772b07794660142c1eec7965c8f52e41c549ebba5dfeb2bc509022076884bfa70da9479414e572c450a8b6c667cf499f3367d4ed2ad786a5be2fbc54121021d7fd45a888292cf3a022a95acdbcf82f9f2d5bbbfbdbc740acd558a9f25b5d0',
+ value: 45114487,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a9140d94ba179ec21c42417a71a77873b3619363d8ea88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 100383,
+ outputScript:
+ '76a914f5b3312155fe3781140dee0e84023f64cf73a6b588ac',
+ },
+ {
+ value: 45013649,
+ outputScript:
+ '76a9140d94ba179ec21c42417a71a77873b3619363d8ea88ac',
+ spentBy: {
+ txid: 'fa984e50466e064068368e0d456e5a8a774adc6005ece87a32337b779eb4c422',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 226,
+ isCoinbase: false,
+ tokenEntries: [],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
+ block: {
+ height: 827549,
+ hash: '00000000000000000645c0726241fa2c04155544314090a1ddf3ac6e2fdc724b',
+ timestamp: 1705492712,
+ },
+ },
+ {
+ txid: 'c28d33a9865ca5e063f457b626754a4cb65966b6b0c9e81b77ceef4b24b47c86',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: 'abf9d2a474685bf36bd34adb9773255c2c4ee3659a48b93eba19227c66f0179c',
+ outIdx: 1,
+ },
+ inputScript:
+ '4830450221008a4a4be8d5ee42c42af259946c4124827e04b3f01b5ea3947089b61108b2ce8c022002d9b52778dc30fd69b9ca11c527ea9fbdce649c654c5a169b8b5c25060e52c74121021d7fd45a888292cf3a022a95acdbcf82f9f2d5bbbfbdbc740acd558a9f25b5d0',
+ value: 45419254,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a9140d94ba179ec21c42417a71a77873b3619363d8ea88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 101053,
+ outputScript:
+ '76a91443a15be66386024ed7f87d404048c39fb6f0fce788ac',
+ },
+ {
+ value: 45317746,
+ outputScript:
+ '76a9140d94ba179ec21c42417a71a77873b3619363d8ea88ac',
+ spentBy: {
+ txid: '6d182b409b9969ba0a15e65a63ee0162f9003850bdc8ad99b88fc6e855ef3c76',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 226,
+ isCoinbase: false,
+ tokenEntries: [],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
+ block: {
+ height: 827330,
+ hash: '000000000000000014f2dc077361008081ac360ad6ccdaf4668786687a8df971',
+ timestamp: 1705365441,
+ },
+ },
+ {
+ txid: 'abf9d2a474685bf36bd34adb9773255c2c4ee3659a48b93eba19227c66f0179c',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '333851525d62f6e41d9445c488a88ef2c706d094248341d68369c24f2b38d4c6',
+ outIdx: 1,
+ },
+ inputScript:
+ '483045022100a9f318a6516e98c7eef150c697cfd227e6387a36727351a5448ab597819647db022003ee62af32cd383c6df39cc29a7c79b73e7a3734eae9252aaafbe02fe2c648ea4121021d7fd45a888292cf3a022a95acdbcf82f9f2d5bbbfbdbc740acd558a9f25b5d0',
+ value: 45520841,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a9140d94ba179ec21c42417a71a77873b3619363d8ea88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 101132,
+ outputScript:
+ '76a91443a15be66386024ed7f87d404048c39fb6f0fce788ac',
+ },
+ {
+ value: 45419254,
+ outputScript:
+ '76a9140d94ba179ec21c42417a71a77873b3619363d8ea88ac',
+ spentBy: {
+ txid: 'c28d33a9865ca5e063f457b626754a4cb65966b6b0c9e81b77ceef4b24b47c86',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 226,
+ isCoinbase: false,
+ tokenEntries: [],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
+ block: {
+ height: 827330,
+ hash: '000000000000000014f2dc077361008081ac360ad6ccdaf4668786687a8df971',
+ timestamp: 1705365441,
+ },
+ },
+ {
+ txid: '7e1a29815174e7bb1af2275d8d15a31f3b6f9a6567d8489da1da406f85c809bf',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '6d182b409b9969ba0a15e65a63ee0162f9003850bdc8ad99b88fc6e855ef3c76',
+ outIdx: 1,
+ },
+ inputScript:
+ '47304402203b88cbdb66bcf921259eb1a9c33345048de4aaab35b8e51d80067812232c791e02207f30aaaf1e4548f97a168a6f210f085e8521982cdfd9055a6fe6c7769b29d7484121021d7fd45a888292cf3a022a95acdbcf82f9f2d5bbbfbdbc740acd558a9f25b5d0',
+ value: 45216157,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a9140d94ba179ec21c42417a71a77873b3619363d8ea88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 101215,
+ outputScript:
+ '76a91443a15be66386024ed7f87d404048c39fb6f0fce788ac',
+ },
+ {
+ value: 45114487,
+ outputScript:
+ '76a9140d94ba179ec21c42417a71a77873b3619363d8ea88ac',
+ spentBy: {
+ txid: '8bf2566feb21f4681fbf97155d78b388b9fc1fd6a6e4bc0e21324db5a9e7a7ac',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 225,
+ isCoinbase: false,
+ tokenEntries: [],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
+ block: {
+ height: 827330,
+ hash: '000000000000000014f2dc077361008081ac360ad6ccdaf4668786687a8df971',
+ timestamp: 1705365441,
+ },
+ },
+];
+export const tokensInHistory = {
+ '20a0b9337a78603c6681ed2bc541593375535dcd9979196620ce71f233f2f6f8': {
+ token: {
+ tokenId:
+ '20a0b9337a78603c6681ed2bc541593375535dcd9979196620ce71f233f2f6f8',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'VSP',
+ tokenName: 'Vespene Gas',
+ url: 'https://simple.wikipedia.org/wiki/StarCraft#Gameplay',
+ decimals: 9,
+ hash: '',
+ },
+ block: {
+ height: 763087,
+ hash: '0000000000000000015abcebc15e74036598855a9fdd976868ad99bb23b87a89',
+ timestamp: 1666631359,
+ },
+ },
+ tx: {
+ txid: '20a0b9337a78603c6681ed2bc541593375535dcd9979196620ce71f233f2f6f8',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: 'ac8be4ed7289014eb615cf8aa122cbd94283fe566142052d7ac8c6fab241fb51',
+ outIdx: 2,
+ },
+ inputScript:
+ '46304302200db47adc26bbb4ae4584ae455c5f078a4d2f624e898fab3159c74473677bc8b2021f371ea6c9acd051c96eaba2b229d06a0247dad2acf6cf0694792d22280dfe8e412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 1253,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e45534953035653500b56657370656e65204761733468747470733a2f2f73696d706c652e77696b6970656469612e6f72672f77696b692f5374617243726166742347616d65706c61794c0001094c000829a2241af62c0000',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ '20a0b9337a78603c6681ed2bc541593375535dcd9979196620ce71f233f2f6f8',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '3000000000000000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: 'fc1ada187e9f5da7616f481c79cd0fa3aafa3d4094288db6806e7508f76b5fcd',
+ outIdx: 1,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 299,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '20a0b9337a78603c6681ed2bc541593375535dcd9979196620ce71f233f2f6f8',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 763087,
+ hash: '0000000000000000015abcebc15e74036598855a9fdd976868ad99bb23b87a89',
+ timestamp: 1666631359,
+ },
+ },
+ calculated: {
+ genesisSupply: '3000000000.000000000',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109': {
+ token: {
+ tokenId:
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timefirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'BEAR',
+ tokenName: 'BearNip',
+ url: 'https://cashtab.com/',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 782665,
+ hash: '00000000000000001239831f90580c859ec174316e91961cf0e8cde57c0d3acb',
+ timestamp: 1678408305,
+ },
+ },
+ tx: {
+ txid: '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '0e737a2f6373649341b406334341202a5ddbbdb389c55da40570b641dc23d036',
+ outIdx: 1,
+ },
+ inputScript:
+ '473044022055444db90f98b462ca29a6f51981da4015623ddc34dc1f575852426ccb785f0402206e786d4056be781ca1720a0a915b040e0a9e8716b8e4d30b0779852c191fdeb3412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 6231556,
+ sequenceNo: 4294967294,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e45534953044245415207426561724e69701468747470733a2f2f636173687461622e636f6d2f4c0001004c0008000000000000115c',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '4444',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '9e7f91826cfd3adf9867c1b3d102594eff4743825fad9883c35d26fb3bdc1693',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 6230555,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ spentBy: {
+ txid: '27a2471afab33d82b9404df12e1fa242488a9439a68e540dcf8f811ef39c11cf',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 299,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 782665,
+ hash: '00000000000000001239831f90580c859ec174316e91961cf0e8cde57c0d3acb',
+ timestamp: 1678408305,
+ },
+ },
+ calculated: {
+ genesisSupply: '4444',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ },
+};
+// Build a mock token cache from these chronik mocks
+export const mockParseTxTokenCache = new CashtabCache([
+ [
+ 'acba1d7f354c6d4d001eb99d31de174e5cea8a31d692afd6e7eb8474ad541f55',
+ {
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timeFirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'CTB',
+ tokenName: 'CashTabBits',
+ url: 'https://cashtabapp.com/',
+ decimals: 9,
+ hash: '',
+ },
+ block: {
+ height: 662874,
+ hash: '000000000000000055df35f930c6e9ef6f4c51f1df6650d53eb3390cb92503fa',
+ timestamp: 1606935101,
+ },
+ // We do not need to mock genesisSupply, genesisOutputScripts, or genesisMintBatons (yet)
+ // for parseChronikTx
+ },
+ ],
+ [
+ '7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d',
+ {
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timeFirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'WDT',
+ tokenName:
+ 'Test Token With Exceptionally Long Name For CSS And Style Revisions',
+ url: 'https://www.ImpossiblyLongWebsiteDidYouThinkWebDevWouldBeFun.org',
+ decimals: 7,
+ hash: '85b591c15c9f49531e39fcfeb2a5a26b2bd0f7c018fb9cd71b5d92dfb732d5cc',
+ },
+ block: {
+ height: 659948,
+ hash: '000000000000000002e096ec3fda458dab941cd2ab40a7be10d54e88c9b06f37',
+ timestamp: 1604423892,
+ },
+ },
+ ],
+ [
+ '4db25a4b2f0b57415ce25fab6d9cb3ac2bbb444ff493dc16d0615a11ad06c875',
+ {
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timeFirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'LVV',
+ tokenName: 'Lambda Variant Variants',
+ url: 'https://cashtabapp.com/',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 700722,
+ hash: '0000000000000000260ee4c3b4f4ddde127bc0105d685c0ef31775b612627222',
+ timestamp: 1629500864,
+ },
+ },
+ ],
+ [
+ 'cf601c56b58bc05a39a95374a4a865f0a8b56544ea937b30fb46315441717c50',
+ {
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timeFirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'UDT',
+ tokenName: 'UpdateTest',
+ url: 'https://cashtab.com/',
+ decimals: 7,
+ hash: '',
+ },
+ block: {
+ height: 759037,
+ hash: '00000000000000000bc95bfdd45e71585f27139e71b56dd5bc86ef05d35b502f',
+ timestamp: 1664226709,
+ },
+ },
+ ],
+ [
+ '4bd147fc5d5ff26249a9299c46b80920c0b81f59a60e05428262160ebee0b0c3',
+ {
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timeFirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'NOCOVID',
+ tokenName: 'Covid19 Lifetime Immunity',
+ url: 'https://www.who.int/emergencies/diseases/novel-coronavirus-2019/covid-19-vaccines',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 680063,
+ hash: '000000000000000012ad3d6dfb3505616ab9c3cb3772abac0448ddfc25043df4',
+ timestamp: 1617304616,
+ },
+ },
+ ],
+]).tokens;
+
+const txHistoryTokenCache = new CashtabCache().tokens;
+for (const tokenId of Object.keys(tokensInHistory)) {
+ const { token, calculated } = tokensInHistory[tokenId];
+ const { timeFirstSeen, genesisInfo, tokenType } = token;
+ const { genesisSupply, genesisOutputScripts, genesisMintBatons } =
+ calculated;
+ const cachedInfo = {
+ timeFirstSeen,
+ genesisInfo,
+ tokenType,
+ genesisSupply,
+ genesisOutputScripts,
+ genesisMintBatons,
+ };
+ if ('block' in token) {
+ cachedInfo.block = token.block;
+ }
+ txHistoryTokenCache.set(tokenId, cachedInfo);
+}
+export const mockTxHistoryTokenCache = txHistoryTokenCache;
+
+export const expectedParsedTxHistory = [
+ {
+ txid: '66c3321dcaf4eba9e05b6167e9714c4a7b660917c2f5d29d65a519944d4c62e7',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '7171e77e21a57df5193fe387aa5e3d646dd5438c18c80a5a997fd3c2300fc679',
+ outIdx: 1,
+ },
+ inputScript:
+ '483045022100fbe76f31450482a18941ed90fee302662e5e6184d9d84fda6f2a4df9b1d1697a022041432311f5563007d46ade3536fb5988b9c97e2e8aeeec59c15c3efb5c4d0f70412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 1676077,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 1100,
+ outputScript:
+ '76a91476458db0ed96fe9863fc1ccec9fa2cfab884b0f688ac',
+ spentBy: {
+ txid: '24eae444d765406d8362da437d66a7cf50b95685198692bd2253bafd4bd003a0',
+ outIdx: 2,
+ },
+ },
+ {
+ value: 1674751,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 1710794721,
+ size: 226,
+ isCoinbase: false,
+ tokenEntries: [],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
+ block: {
+ height: 836458,
+ hash: '000000000000000011a4069425835dd50ffd7eed5e7fd2e6e464e3996d74cf71',
+ timestamp: 1710799378,
+ },
+ parsed: {
+ incoming: false,
+ xecAmount: 11,
+ isEtokenTx: false,
+ airdropFlag: false,
+ airdropTokenId: '',
+ opReturnMessage: '',
+ isCashtabMessage: false,
+ isEncryptedMessage: false,
+ replyAddress: 'ecash:qz2708636snqhsxu8wnlka78h6fdp77ar59jrf5035',
+ aliasFlag: false,
+ },
+ },
+ {
+ txid: 'acc7bf16ee329a9a6c40cdaa5fca01fdfc44f143393346821b4bc58557cfb70c',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '16c72330503bc3e6435ab45ca34f4ac1e2f88701db9c8c42efa21236514ba9ed',
+ outIdx: 7,
+ },
+ inputScript:
+ '473044022066325bcd7ba631d13d08f202714626fa7ec353febc985051d56a68edc19b0f900220016d4cb2308fa378ee04b101411cbfba88d99fd5e6d8b12170e17bca3d671c79412102c237f49dd4c812f27b09d69d4c8a4da12744fda8ad63ce151fed2a3f41fd8795',
+ value: 442567277,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91476458db0ed96fe9863fc1ccec9fa2cfab884b0f688ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 3300,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ {
+ value: 442563522,
+ outputScript:
+ '76a91476458db0ed96fe9863fc1ccec9fa2cfab884b0f688ac',
+ spentBy: {
+ txid: '08fa8a346851d44fd4b6765c65008670ccadf8dabcae59686814279a449ada06',
+ outIdx: 2,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 1710794713,
+ size: 225,
+ isCoinbase: false,
+ tokenEntries: [],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
+ block: {
+ height: 836458,
+ hash: '000000000000000011a4069425835dd50ffd7eed5e7fd2e6e464e3996d74cf71',
+ timestamp: 1710799378,
+ },
+ parsed: {
+ incoming: true,
+ xecAmount: 33,
+ isEtokenTx: false,
+ airdropFlag: false,
+ airdropTokenId: '',
+ opReturnMessage: '',
+ isCashtabMessage: false,
+ isEncryptedMessage: false,
+ replyAddress: 'ecash:qpmytrdsakt0axrrlswvaj069nat3p9s7cjctmjasj',
+ aliasFlag: false,
+ },
+ },
+ {
+ txid: '521468e91cf3d3b32d03e60c68ac12ff94606bd535267971d886f6febb225f9d',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '3b13ffef338f913da39f5be9c1a363a87b5a6724f41b623f324c4e1b0c96e012',
+ outIdx: 1,
+ },
+ inputScript:
+ '483045022100dba6667c91a695a7b1b509c901a7ce1fc7c859f2ad4e636729efc697e09177b802206fd4a2d53eaf96e010abdc562d2cc3a19f5ee5427a868105b9814f17eb6a6d72412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 988104,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 1100,
+ outputScript:
+ '76a91476458db0ed96fe9863fc1ccec9fa2cfab884b0f688ac',
+ spentBy: {
+ txid: '24eae444d765406d8362da437d66a7cf50b95685198692bd2253bafd4bd003a0',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 986778,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 1710794691,
+ size: 226,
+ isCoinbase: false,
+ tokenEntries: [],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
+ block: {
+ height: 836458,
+ hash: '000000000000000011a4069425835dd50ffd7eed5e7fd2e6e464e3996d74cf71',
+ timestamp: 1710799378,
+ },
+ parsed: {
+ incoming: false,
+ xecAmount: 11,
+ isEtokenTx: false,
+ airdropFlag: false,
+ airdropTokenId: '',
+ opReturnMessage: '',
+ isCashtabMessage: false,
+ isEncryptedMessage: false,
+ replyAddress: 'ecash:qz2708636snqhsxu8wnlka78h6fdp77ar59jrf5035',
+ aliasFlag: false,
+ },
+ },
+ {
+ txid: '19488e3cccbbc685a1016567b2acc2b52012a541b25ed4fee43f914f788eda5e',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '16c72330503bc3e6435ab45ca34f4ac1e2f88701db9c8c42efa21236514ba9ed',
+ outIdx: 4,
+ },
+ inputScript:
+ '47304402202f1e5ef2f5f17d3c9f7b65094e903c39db01533ae24898492d30b329b98b3b4a022066cf37253c016fde0ce3b57c5a645605cfdbc10623970e97f68e66592275dc88412102c237f49dd4c812f27b09d69d4c8a4da12744fda8ad63ce151fed2a3f41fd8795',
+ value: 440000,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91476458db0ed96fe9863fc1ccec9fa2cfab884b0f688ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 1100,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ {
+ value: 438445,
+ outputScript:
+ '76a91476458db0ed96fe9863fc1ccec9fa2cfab884b0f688ac',
+ spentBy: {
+ txid: '49e2dd75d2309fee1a8c69d31090ad0f5bdd60eaf32bf1eea1ed276dab33e26f',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 1710794683,
+ size: 225,
+ isCoinbase: false,
+ tokenEntries: [],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
+ block: {
+ height: 836458,
+ hash: '000000000000000011a4069425835dd50ffd7eed5e7fd2e6e464e3996d74cf71',
+ timestamp: 1710799378,
+ },
+ parsed: {
+ incoming: true,
+ xecAmount: 11,
+ isEtokenTx: false,
+ airdropFlag: false,
+ airdropTokenId: '',
+ opReturnMessage: '',
+ isCashtabMessage: false,
+ isEncryptedMessage: false,
+ replyAddress: 'ecash:qpmytrdsakt0axrrlswvaj069nat3p9s7cjctmjasj',
+ aliasFlag: false,
+ },
+ },
+ {
+ txid: '914827ddc2087db0e8ca8aed3c2a701f5873ea2f96f3837d6dce6f24ab53f854',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '5b115c352a487503755bbb93582ff39e1095d698fa303c7dd31bbf19c4bbf39a',
+ outIdx: 2,
+ },
+ inputScript:
+ '4730440220268dcf8d1be3fb33cdcd79b644acb12cdbf100040a51abf828a02fe17c34a03a0220141dce2d7292a49d82f13642e854f27326607dd8e3c13f7905632d373a56c70a412102c237f49dd4c812f27b09d69d4c8a4da12744fda8ad63ce151fed2a3f41fd8795',
+ value: 546,
+ sequenceNo: 4294967295,
+ token: {
+ tokenId:
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '9',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ outputScript:
+ '76a91476458db0ed96fe9863fc1ccec9fa2cfab884b0f688ac',
+ },
+ {
+ prevOut: {
+ txid: 'b3ca2414e646fbc53c6d789a242ea9afc1e84ec1e62ed8f5d58ab93d43207b66',
+ outIdx: 0,
+ },
+ inputScript:
+ '483045022100c7106fb50492ac6726a6cae234ac7424842daee2285fb5a3c8005262a9fdbb06022061c24760989da27c0e3f372646243334d6048894a49aae3459a3f9ebabdc41d0412102c237f49dd4c812f27b09d69d4c8a4da12744fda8ad63ce151fed2a3f41fd8795',
+ value: 1100,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91476458db0ed96fe9863fc1ccec9fa2cfab884b0f688ac',
+ },
+ {
+ prevOut: {
+ txid: '848af498277a4250bde6951849df0e66b9bc5a3b8766efbd43d3e660b773edc5',
+ outIdx: 1,
+ },
+ inputScript:
+ '483045022100c1eca663e5c9f06db6f3844254ff197bbbd106897ffef37300d9ce65b17f4ece02203f80564ba7e4d833db4ef6097c69dcb9ae9abce3cc2ab2c75f17a4c23059abfa412102c237f49dd4c812f27b09d69d4c8a4da12744fda8ad63ce151fed2a3f41fd8795',
+ value: 3181522,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91476458db0ed96fe9863fc1ccec9fa2cfab884b0f688ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010453454e44203fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109080000000000000001080000000000000008',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '1',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91476458db0ed96fe9863fc1ccec9fa2cfab884b0f688ac',
+ token: {
+ tokenId:
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '8',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '94bf7fb1b2d37fed71085f9f32415f7426ed7cde692b9a9320ff6c811aa2db74',
+ outIdx: 0,
+ },
+ },
+ {
+ value: 3180811,
+ outputScript:
+ '76a91476458db0ed96fe9863fc1ccec9fa2cfab884b0f688ac',
+ spentBy: {
+ txid: '20c513c9ae5f3966f8dae10c7e0681505756a5a0b4e4f707b366cdf51663c386',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 1710794373,
+ size: 628,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'SEND',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 836458,
+ hash: '000000000000000011a4069425835dd50ffd7eed5e7fd2e6e464e3996d74cf71',
+ timestamp: 1710799378,
+ },
+ parsed: {
+ incoming: true,
+ xecAmount: 5.46,
+ isEtokenTx: true,
+ etokenAmount: '1',
+ isTokenBurn: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'SEND',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ airdropFlag: false,
+ airdropTokenId: '',
+ opReturnMessage: '',
+ isCashtabMessage: false,
+ isEncryptedMessage: false,
+ replyAddress: 'ecash:qpmytrdsakt0axrrlswvaj069nat3p9s7cjctmjasj',
+ assumedTokenDecimals: false,
+ },
+ },
+ {
+ txid: '490a06b01b8d1793b81b5230ce2045132af0f0ec9cc7be860bb72e6a727d5bd4',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '811a943532212685dce70bab73ba4facb06aced2f3752f5115176d4c970ef90b',
+ outIdx: 2,
+ },
+ inputScript:
+ '4830450221008a6bb3c19db22b601ca5110415e0be8c56877b58741f7d6f50c57a8bd96f988d0220507a171d02a4fa7facc463bf62ce673a69d0d28fe3b6728a683c2ffc7a93418d4121021d7fd45a888292cf3a022a95acdbcf82f9f2d5bbbfbdbc740acd558a9f25b5d0',
+ value: 546,
+ sequenceNo: 4294967295,
+ token: {
+ tokenId:
+ '20a0b9337a78603c6681ed2bc541593375535dcd9979196620ce71f233f2f6f8',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '999900000000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ outputScript:
+ '76a9140d94ba179ec21c42417a71a77873b3619363d8ea88ac',
+ },
+ {
+ prevOut: {
+ txid: 'cfe4f1458af2be9f76e7a45c47a9c450aded46d3e5b41d97dfd3c56b2c16c7ca',
+ outIdx: 2,
+ },
+ inputScript:
+ '48304502210096482807afee1009914e934326930379ea308402643e786a1ac35786160cca37022070fe57cff80dba8475598c30b9515afa5e14caebf1ba1c7599554b9f9f7c89354121021d7fd45a888292cf3a022a95acdbcf82f9f2d5bbbfbdbc740acd558a9f25b5d0',
+ value: 44907604,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a9140d94ba179ec21c42417a71a77873b3619363d8ea88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010453454e442020a0b9337a78603c6681ed2bc541593375535dcd9979196620ce71f233f2f6f80800000007aef40a000800038d5fad5b8e00',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a9146ffbe7c7d7bd01295eb1e371de9550339bdcf9fd88ac',
+ token: {
+ tokenId:
+ '20a0b9337a78603c6681ed2bc541593375535dcd9979196620ce71f233f2f6f8',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '33000000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a9140d94ba179ec21c42417a71a77873b3619363d8ea88ac',
+ token: {
+ tokenId:
+ '20a0b9337a78603c6681ed2bc541593375535dcd9979196620ce71f233f2f6f8',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '999867000000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ },
+ {
+ value: 44906091,
+ outputScript:
+ '76a9140d94ba179ec21c42417a71a77873b3619363d8ea88ac',
+ spentBy: {
+ txid: 'd711c97ff4fe19df3419c570b082bfefc99e5b3d093c0ca8e8397404573c98f3',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 481,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '20a0b9337a78603c6681ed2bc541593375535dcd9979196620ce71f233f2f6f8',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'SEND',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 833081,
+ hash: '0000000000000000158bbff44ccbfe7b4dcfa9cbd48d58a225c0cf92e199f2e9',
+ timestamp: 1708821393,
+ },
+ parsed: {
+ incoming: false,
+ xecAmount: 5.46,
+ isEtokenTx: true,
+ etokenAmount: '33',
+ isTokenBurn: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '20a0b9337a78603c6681ed2bc541593375535dcd9979196620ce71f233f2f6f8',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'SEND',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ airdropFlag: false,
+ airdropTokenId: '',
+ opReturnMessage: '',
+ isCashtabMessage: false,
+ isEncryptedMessage: false,
+ replyAddress: 'ecash:qqxefwshnmppcsjp0fc6w7rnkdsexc7cagdus7ugd0',
+ assumedTokenDecimals: false,
+ },
+ },
+ {
+ txid: '8bf2566feb21f4681fbf97155d78b388b9fc1fd6a6e4bc0e21324db5a9e7a7ac',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '7e1a29815174e7bb1af2275d8d15a31f3b6f9a6567d8489da1da406f85c809bf',
+ outIdx: 1,
+ },
+ inputScript:
+ '483045022100c2bc2700a443a772b07794660142c1eec7965c8f52e41c549ebba5dfeb2bc509022076884bfa70da9479414e572c450a8b6c667cf499f3367d4ed2ad786a5be2fbc54121021d7fd45a888292cf3a022a95acdbcf82f9f2d5bbbfbdbc740acd558a9f25b5d0',
+ value: 45114487,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a9140d94ba179ec21c42417a71a77873b3619363d8ea88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 100383,
+ outputScript:
+ '76a914f5b3312155fe3781140dee0e84023f64cf73a6b588ac',
+ },
+ {
+ value: 45013649,
+ outputScript:
+ '76a9140d94ba179ec21c42417a71a77873b3619363d8ea88ac',
+ spentBy: {
+ txid: 'fa984e50466e064068368e0d456e5a8a774adc6005ece87a32337b779eb4c422',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 226,
+ isCoinbase: false,
+ tokenEntries: [],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
+ block: {
+ height: 827549,
+ hash: '00000000000000000645c0726241fa2c04155544314090a1ddf3ac6e2fdc724b',
+ timestamp: 1705492712,
+ },
+ parsed: {
+ incoming: false,
+ xecAmount: 1003.83,
+ isEtokenTx: false,
+ airdropFlag: false,
+ airdropTokenId: '',
+ opReturnMessage: '',
+ isCashtabMessage: false,
+ isEncryptedMessage: false,
+ replyAddress: 'ecash:qqxefwshnmppcsjp0fc6w7rnkdsexc7cagdus7ugd0',
+ aliasFlag: false,
+ },
+ },
+ {
+ txid: 'c28d33a9865ca5e063f457b626754a4cb65966b6b0c9e81b77ceef4b24b47c86',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: 'abf9d2a474685bf36bd34adb9773255c2c4ee3659a48b93eba19227c66f0179c',
+ outIdx: 1,
+ },
+ inputScript:
+ '4830450221008a4a4be8d5ee42c42af259946c4124827e04b3f01b5ea3947089b61108b2ce8c022002d9b52778dc30fd69b9ca11c527ea9fbdce649c654c5a169b8b5c25060e52c74121021d7fd45a888292cf3a022a95acdbcf82f9f2d5bbbfbdbc740acd558a9f25b5d0',
+ value: 45419254,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a9140d94ba179ec21c42417a71a77873b3619363d8ea88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 101053,
+ outputScript:
+ '76a91443a15be66386024ed7f87d404048c39fb6f0fce788ac',
+ },
+ {
+ value: 45317746,
+ outputScript:
+ '76a9140d94ba179ec21c42417a71a77873b3619363d8ea88ac',
+ spentBy: {
+ txid: '6d182b409b9969ba0a15e65a63ee0162f9003850bdc8ad99b88fc6e855ef3c76',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 226,
+ isCoinbase: false,
+ tokenEntries: [],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
+ block: {
+ height: 827330,
+ hash: '000000000000000014f2dc077361008081ac360ad6ccdaf4668786687a8df971',
+ timestamp: 1705365441,
+ },
+ parsed: {
+ incoming: false,
+ xecAmount: 1010.53,
+ isEtokenTx: false,
+ airdropFlag: false,
+ airdropTokenId: '',
+ opReturnMessage: '',
+ isCashtabMessage: false,
+ isEncryptedMessage: false,
+ replyAddress: 'ecash:qqxefwshnmppcsjp0fc6w7rnkdsexc7cagdus7ugd0',
+ aliasFlag: false,
+ },
+ },
+ {
+ txid: 'abf9d2a474685bf36bd34adb9773255c2c4ee3659a48b93eba19227c66f0179c',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '333851525d62f6e41d9445c488a88ef2c706d094248341d68369c24f2b38d4c6',
+ outIdx: 1,
+ },
+ inputScript:
+ '483045022100a9f318a6516e98c7eef150c697cfd227e6387a36727351a5448ab597819647db022003ee62af32cd383c6df39cc29a7c79b73e7a3734eae9252aaafbe02fe2c648ea4121021d7fd45a888292cf3a022a95acdbcf82f9f2d5bbbfbdbc740acd558a9f25b5d0',
+ value: 45520841,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a9140d94ba179ec21c42417a71a77873b3619363d8ea88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 101132,
+ outputScript:
+ '76a91443a15be66386024ed7f87d404048c39fb6f0fce788ac',
+ },
+ {
+ value: 45419254,
+ outputScript:
+ '76a9140d94ba179ec21c42417a71a77873b3619363d8ea88ac',
+ spentBy: {
+ txid: 'c28d33a9865ca5e063f457b626754a4cb65966b6b0c9e81b77ceef4b24b47c86',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 226,
+ isCoinbase: false,
+ tokenEntries: [],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
+ block: {
+ height: 827330,
+ hash: '000000000000000014f2dc077361008081ac360ad6ccdaf4668786687a8df971',
+ timestamp: 1705365441,
+ },
+ parsed: {
+ incoming: false,
+ xecAmount: 1011.32,
+ isEtokenTx: false,
+ airdropFlag: false,
+ airdropTokenId: '',
+ opReturnMessage: '',
+ isCashtabMessage: false,
+ isEncryptedMessage: false,
+ replyAddress: 'ecash:qqxefwshnmppcsjp0fc6w7rnkdsexc7cagdus7ugd0',
+ aliasFlag: false,
+ },
+ },
+ {
+ txid: '7e1a29815174e7bb1af2275d8d15a31f3b6f9a6567d8489da1da406f85c809bf',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '6d182b409b9969ba0a15e65a63ee0162f9003850bdc8ad99b88fc6e855ef3c76',
+ outIdx: 1,
+ },
+ inputScript:
+ '47304402203b88cbdb66bcf921259eb1a9c33345048de4aaab35b8e51d80067812232c791e02207f30aaaf1e4548f97a168a6f210f085e8521982cdfd9055a6fe6c7769b29d7484121021d7fd45a888292cf3a022a95acdbcf82f9f2d5bbbfbdbc740acd558a9f25b5d0',
+ value: 45216157,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a9140d94ba179ec21c42417a71a77873b3619363d8ea88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 101215,
+ outputScript:
+ '76a91443a15be66386024ed7f87d404048c39fb6f0fce788ac',
+ },
+ {
+ value: 45114487,
+ outputScript:
+ '76a9140d94ba179ec21c42417a71a77873b3619363d8ea88ac',
+ spentBy: {
+ txid: '8bf2566feb21f4681fbf97155d78b388b9fc1fd6a6e4bc0e21324db5a9e7a7ac',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 225,
+ isCoinbase: false,
+ tokenEntries: [],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
+ block: {
+ height: 827330,
+ hash: '000000000000000014f2dc077361008081ac360ad6ccdaf4668786687a8df971',
+ timestamp: 1705365441,
+ },
+ parsed: {
+ incoming: false,
+ xecAmount: 1012.15,
+ isEtokenTx: false,
+ airdropFlag: false,
+ airdropTokenId: '',
+ opReturnMessage: '',
+ isCashtabMessage: false,
+ isEncryptedMessage: false,
+ replyAddress: 'ecash:qqxefwshnmppcsjp0fc6w7rnkdsexc7cagdus7ugd0',
+ aliasFlag: false,
+ },
+ },
+];
+
+const tokenInfoErrorParsedTxHistory = JSON.parse(
+ JSON.stringify(expectedParsedTxHistory),
+);
+for (const tx of tokenInfoErrorParsedTxHistory) {
+ if ('assumedTokenDecimals' in tx.parsed) {
+ // If we had cached token info before, we do not have it now
+ tx.parsed.assumedTokenDecimals = true;
+ }
+ if (tx.parsed.etokenAmount === '33') {
+ // Update amount for the one assumed tx where decimals is not really 0
+ tx.parsed.etokenAmount = '33000000000';
+ }
+}
+
+export const noCachedInfoParsedTxHistory = tokenInfoErrorParsedTxHistory;
diff --git a/cashtab/src/chronik/fixtures/vectors.js b/cashtab/src/chronik/fixtures/vectors.js
--- a/cashtab/src/chronik/fixtures/vectors.js
+++ b/cashtab/src/chronik/fixtures/vectors.js
@@ -7,7 +7,6 @@
mockAliasWallet,
mockParseTxWalletAirdrop,
mockParseTxWalletEncryptedMsg,
- txHistoryTokenInfoById,
stakingRwd,
incomingXec,
outgoingXec,
@@ -39,157 +38,169 @@
mockFlatTxHistoryWithAllUnconfirmed,
mockSortedFlatTxHistoryWithAllUnconfirmed,
AlpTx,
+ mockParseTxTokenCache,
} from './mocks';
import { mockChronikUtxos, mockOrganizedUtxosByType } from './chronikUtxos';
export default {
- parseChronikTx: {
+ parseTx: {
expectedReturns: [
{
description: 'Staking rewards coinbase tx',
tx: stakingRwd.tx,
wallet: mockParseTxWallet,
- tokenInfoById: txHistoryTokenInfoById,
+ cachedTokens: mockParseTxTokenCache,
parsed: stakingRwd.parsed,
},
{
description: 'Incoming XEC tx',
tx: incomingXec.tx,
wallet: mockParseTxWallet,
- tokenInfoById: txHistoryTokenInfoById,
+ cachedTokens: mockParseTxTokenCache,
parsed: incomingXec.parsed,
},
{
description: 'Outgoing XEC tx',
tx: outgoingXec.tx,
wallet: mockParseTxWallet,
- tokenInfoById: txHistoryTokenInfoById,
+ cachedTokens: mockParseTxTokenCache,
parsed: outgoingXec.parsed,
},
{
description: 'Alias registration',
tx: aliasRegistration.tx,
wallet: mockAliasWallet,
- tokenInfoById: txHistoryTokenInfoById,
+ cachedTokens: mockParseTxTokenCache,
parsed: aliasRegistration.parsed,
},
{
description: 'Incoming eToken',
tx: incomingEtoken.tx,
wallet: mockParseTxWallet,
- tokenInfoById: txHistoryTokenInfoById,
+ cachedTokens: mockParseTxTokenCache,
parsed: incomingEtoken.parsed,
},
+ {
+ description:
+ 'Incoming eToken that for some reason does not get cached',
+ tx: incomingEtoken.tx,
+ wallet: mockParseTxWallet,
+ cachedTokens: new Map(),
+ parsed: {
+ ...incomingEtoken.parsed,
+ assumedTokenDecimals: true,
+ },
+ },
{
description: 'Outgoing eToken',
tx: outgoingEtoken.tx,
wallet: mockParseTxWallet,
- tokenInfoById: txHistoryTokenInfoById,
+ cachedTokens: mockParseTxTokenCache,
parsed: outgoingEtoken.parsed,
},
{
description: 'Genesis tx',
tx: genesisTx.tx,
wallet: mockParseTxWalletAirdrop,
- tokenInfoById: txHistoryTokenInfoById,
+ cachedTokens: mockParseTxTokenCache,
parsed: genesisTx.parsed,
},
{
description: 'Incoming eToken tx with 9 decimals',
tx: incomingEtokenNineDecimals.tx,
wallet: mockParseTxWalletAirdrop,
- tokenInfoById: txHistoryTokenInfoById,
+ cachedTokens: mockParseTxTokenCache,
parsed: incomingEtokenNineDecimals.parsed,
},
{
description: 'Legacy airdrop tx',
tx: legacyAirdropTx.tx,
wallet: mockParseTxWalletAirdrop,
- tokenInfoById: txHistoryTokenInfoById,
+ cachedTokens: mockParseTxTokenCache,
parsed: legacyAirdropTx.parsed,
},
{
description: 'Outgoing encrypted msg (deprecated)',
tx: outgoingEncryptedMsg.tx,
wallet: mockParseTxWalletEncryptedMsg,
- tokenInfoById: txHistoryTokenInfoById,
+ cachedTokens: mockParseTxTokenCache,
parsed: outgoingEncryptedMsg.parsed,
},
{
description: 'Incoming encrypted msg (deprecated)',
tx: incomingEncryptedMsg.tx,
wallet: mockParseTxWalletEncryptedMsg,
- tokenInfoById: txHistoryTokenInfoById,
+ cachedTokens: mockParseTxTokenCache,
parsed: incomingEncryptedMsg.parsed,
},
{
description: 'Token burn tx',
tx: tokenBurn.tx,
wallet: mockParseTxWalletAirdrop,
- tokenInfoById: txHistoryTokenInfoById,
+ cachedTokens: mockParseTxTokenCache,
parsed: tokenBurn.parsed,
},
{
description: 'Token burn tx with decimals',
tx: tokenBurnDecimals.tx,
wallet: mockParseTxWalletAirdrop,
- tokenInfoById: txHistoryTokenInfoById,
+ cachedTokens: mockParseTxTokenCache,
parsed: tokenBurnDecimals.parsed,
},
{
description: 'Incoming eToken tx less than zero with decimals',
tx: incomingEtokenTwo.tx,
wallet: mockParseTxWalletAirdrop,
- tokenInfoById: txHistoryTokenInfoById,
+ cachedTokens: mockParseTxTokenCache,
parsed: incomingEtokenTwo.parsed,
},
{
description: 'SWaP tx',
tx: swapTx.tx,
wallet: mockSwapWallet,
- tokenInfoById: txHistoryTokenInfoById,
+ cachedTokens: mockParseTxTokenCache,
parsed: swapTx.parsed,
},
{
description: 'Pre-spec alias registration (now off spec)',
tx: aliasOffSpec.tx,
wallet: mockParseTxWallet,
- tokenInfoById: txHistoryTokenInfoById,
+ cachedTokens: mockParseTxTokenCache,
parsed: aliasOffSpec.parsed,
},
{
description: 'PayButton tx with no data and payment id',
tx: PayButtonNoDataYesNonce.tx,
wallet: mockParseTxWallet,
- tokenInfoById: txHistoryTokenInfoById,
+ cachedTokens: mockParseTxTokenCache,
parsed: PayButtonNoDataYesNonce.parsed,
},
{
description: 'PayButton tx with data and payment id',
tx: PayButtonYesDataYesNonce.tx,
wallet: mockParseTxWallet,
- tokenInfoById: txHistoryTokenInfoById,
+ cachedTokens: mockParseTxTokenCache,
parsed: PayButtonYesDataYesNonce.parsed,
},
{
description: 'PayButton tx with no data and no payment id',
tx: PayButtonEmpty.tx,
wallet: mockParseTxWallet,
- tokenInfoById: txHistoryTokenInfoById,
+ cachedTokens: mockParseTxTokenCache,
parsed: PayButtonEmpty.parsed,
},
{
description: 'PayButton tx with data and no payment id',
tx: PayButtonYesDataNoNonce.tx,
wallet: mockParseTxWallet,
- tokenInfoById: txHistoryTokenInfoById,
+ cachedTokens: mockParseTxTokenCache,
parsed: PayButtonYesDataNoNonce.parsed,
},
{
description: 'PayButton tx with unsupported version number',
tx: PayButtonBadVersion.tx,
wallet: mockParseTxWallet,
- tokenInfoById: txHistoryTokenInfoById,
+ cachedTokens: mockParseTxTokenCache,
parsed: PayButtonBadVersion.parsed,
},
{
@@ -197,14 +208,14 @@
'Paybutton tx that does not have spec number of pushes',
tx: PayButtonOffSpec.tx,
wallet: mockParseTxWallet,
- tokenInfoById: txHistoryTokenInfoById,
+ cachedTokens: mockParseTxTokenCache,
parsed: PayButtonOffSpec.parsed,
},
{
description: 'External msg received from Electrum',
tx: MsgFromElectrum.tx,
wallet: mockParseTxWallet,
- tokenInfoById: txHistoryTokenInfoById,
+ cachedTokens: mockParseTxTokenCache,
parsed: MsgFromElectrum.parsed,
},
{
@@ -212,11 +223,10 @@
'Before adding support for tokens other than SLPV1, an ALP tx is parsed as an eCash tx',
tx: AlpTx.tx,
wallet: mockParseTxWallet,
- tokenInfoById: txHistoryTokenInfoById,
+ cachedTokens: mockParseTxTokenCache,
parsed: AlpTx.parsed,
},
],
- expectedErrors: [],
},
sortAndTrimChronikTxHistory: {
expectedReturns: [
@@ -279,4 +289,808 @@
},
],
},
+ getTokenGenesisInfo: {
+ expectedReturns: [
+ {
+ description: 'slpv1 token with no minting batons',
+ tokenId:
+ 'b132878bfa81cf1b9e19192045ed4c797b10944cc17ae07da06aed3d7b566cb7',
+ tokenInfo: {
+ tokenId:
+ 'b132878bfa81cf1b9e19192045ed4c797b10944cc17ae07da06aed3d7b566cb7',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timeFirstSeen: '0',
+ genesisInfo: {
+ tokenTicker: 'ABC',
+ tokenName: 'ABC',
+ url: 'https://cashtab.com/',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 832725,
+ hash: '000000000000000016d97961a24ac3460160bbc439810cd2af684264ae15083b',
+ timestamp: 1708607039,
+ },
+ },
+ genesisTx: {
+ txid: 'b132878bfa81cf1b9e19192045ed4c797b10944cc17ae07da06aed3d7b566cb7',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '9866faa3294afc3f4dd5669c67ee4d0ded42db25d08728fe07166e9cda9ee8f9',
+ outIdx: 3,
+ },
+ inputScript:
+ '483045022100fb14b5f82605972478186c91ff6fab2051b46abd2a8aa9774b3e9276715daf39022046a62933cc3acf59129fbf373ef05480342312bc33aaa8bf7fb5a0495b5dc80e412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 1617,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e4553495303414243034142431468747470733a2f2f636173687461622e636f6d2f4c0001004c0008000000000000000c',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ 'b132878bfa81cf1b9e19192045ed4c797b10944cc17ae07da06aed3d7b566cb7',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '12',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '41fd4cb3ce0162e44cfd5a446b389afa6b35461d466d55321be412a518c56d63',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 261,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ 'b132878bfa81cf1b9e19192045ed4c797b10944cc17ae07da06aed3d7b566cb7',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 832725,
+ hash: '000000000000000016d97961a24ac3460160bbc439810cd2af684264ae15083b',
+ timestamp: 1708607039,
+ },
+ },
+ returned: {
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timeFirstSeen: '0',
+ genesisInfo: {
+ tokenTicker: 'ABC',
+ tokenName: 'ABC',
+ url: 'https://cashtab.com/',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 832725,
+ hash: '000000000000000016d97961a24ac3460160bbc439810cd2af684264ae15083b',
+ timestamp: 1708607039,
+ },
+ genesisMintBatons: 0,
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisSupply: '12',
+ },
+ },
+ {
+ description:
+ 'slpv1 token with no minting batons unconfirmed genesis tx',
+ tokenId:
+ 'b132878bfa81cf1b9e19192045ed4c797b10944cc17ae07da06aed3d7b566cb7',
+ tokenInfo: {
+ tokenId:
+ 'b132878bfa81cf1b9e19192045ed4c797b10944cc17ae07da06aed3d7b566cb7',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timeFirstSeen: '0',
+ genesisInfo: {
+ tokenTicker: 'ABC',
+ tokenName: 'ABC',
+ url: 'https://cashtab.com/',
+ decimals: 0,
+ hash: '',
+ },
+ },
+ genesisTx: {
+ txid: 'b132878bfa81cf1b9e19192045ed4c797b10944cc17ae07da06aed3d7b566cb7',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '9866faa3294afc3f4dd5669c67ee4d0ded42db25d08728fe07166e9cda9ee8f9',
+ outIdx: 3,
+ },
+ inputScript:
+ '483045022100fb14b5f82605972478186c91ff6fab2051b46abd2a8aa9774b3e9276715daf39022046a62933cc3acf59129fbf373ef05480342312bc33aaa8bf7fb5a0495b5dc80e412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 1617,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e4553495303414243034142431468747470733a2f2f636173687461622e636f6d2f4c0001004c0008000000000000000c',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ 'b132878bfa81cf1b9e19192045ed4c797b10944cc17ae07da06aed3d7b566cb7',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '12',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '41fd4cb3ce0162e44cfd5a446b389afa6b35461d466d55321be412a518c56d63',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 261,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ 'b132878bfa81cf1b9e19192045ed4c797b10944cc17ae07da06aed3d7b566cb7',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ },
+ returned: {
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timeFirstSeen: '0',
+ genesisInfo: {
+ tokenTicker: 'ABC',
+ tokenName: 'ABC',
+ url: 'https://cashtab.com/',
+ decimals: 0,
+ hash: '',
+ },
+ genesisMintBatons: 0,
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisSupply: '12',
+ },
+ },
+ {
+ description: 'slpv1 token with minting baton',
+ tokenId:
+ '50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e',
+ tokenInfo: {
+ tokenId:
+ '50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timeFirstSeen: '0',
+ genesisInfo: {
+ tokenTicker: 'TBC',
+ tokenName: 'tabcash',
+ url: 'https://cashtabapp.com/',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 674143,
+ hash: '000000000000000034c77993a35c74fe2dddace27198681ca1e89e928d0c2fff',
+ timestamp: 1613859311,
+ },
+ },
+ genesisTx: {
+ txid: '50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: 'be38b0488679e25823b7a72b925ac695a7b486e7f78122994b913f3079b0b939',
+ outIdx: 2,
+ },
+ inputScript:
+ '483045022100e28006843eb071ec6d8dd105284f2ca625a28f4dc85418910b59a5ab13fc6c2002205921fb12b541d1cd1a63e7e012aca5735df3398525f64bac04337d21029413614121034509251caa5f01e2787c436949eb94d71dcc451bcde5791ae5b7109255f5f0a3',
+ value: 91048,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a914b8d9512d2adf8b4e70c45c26b6b00d75c28eaa9688ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e455349530354424307746162636173681768747470733a2f2f636173687461626170702e636f6d2f4c0001000102080000000000000064',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a914b8d9512d2adf8b4e70c45c26b6b00d75c28eaa9688ac',
+ token: {
+ tokenId:
+ '50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '100',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '618d0dd8c0c5fa5a34c6515c865dd72bb76f8311cd6ee9aef153bab20dabc0e6',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a914b8d9512d2adf8b4e70c45c26b6b00d75c28eaa9688ac',
+ token: {
+ tokenId:
+ '50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '0',
+ isMintBaton: true,
+ entryIdx: 0,
+ },
+ },
+ {
+ value: 89406,
+ outputScript:
+ '76a914b8d9512d2adf8b4e70c45c26b6b00d75c28eaa9688ac',
+ spentBy: {
+ txid: '618d0dd8c0c5fa5a34c6515c865dd72bb76f8311cd6ee9aef153bab20dabc0e6',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 336,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 674143,
+ hash: '000000000000000034c77993a35c74fe2dddace27198681ca1e89e928d0c2fff',
+ timestamp: 1613859311,
+ },
+ },
+ returned: {
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timeFirstSeen: '0',
+ genesisInfo: {
+ tokenTicker: 'TBC',
+ tokenName: 'tabcash',
+ url: 'https://cashtabapp.com/',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 674143,
+ hash: '000000000000000034c77993a35c74fe2dddace27198681ca1e89e928d0c2fff',
+ timestamp: 1613859311,
+ },
+ genesisMintBatons: 1,
+ genesisOutputScripts: [
+ '76a914b8d9512d2adf8b4e70c45c26b6b00d75c28eaa9688ac',
+ ],
+ genesisSupply: '100',
+ },
+ },
+ {
+ description: 'ALP token with a minting baton',
+ tokenId:
+ 'cdcdcdcdcdc9dda4c92bb1145aa84945c024346ea66fd4b699e344e45df2e145',
+ tokenInfo: {
+ tokenId:
+ 'cdcdcdcdcdc9dda4c92bb1145aa84945c024346ea66fd4b699e344e45df2e145',
+ tokenType: {
+ protocol: 'ALP',
+ type: 'ALP_TOKEN_TYPE_STANDARD',
+ number: 0,
+ },
+ timeFirstSeen: '0',
+ genesisInfo: {
+ tokenTicker: 'CRD',
+ tokenName: 'Credo In Unum Deo',
+ url: 'https://crd.network/token',
+ decimals: 4,
+ data: {},
+ authPubkey:
+ '0334b744e6338ad438c92900c0ed1869c3fd2c0f35a4a9b97a88447b6e2b145f10',
+ },
+ block: {
+ height: 795680,
+ hash: '00000000000000000b7e89959ee52ca1cd691e1fc3b4891c1888f84261c83e73',
+ timestamp: 1686305735,
+ },
+ },
+ genesisTx: {
+ txid: 'cdcdcdcdcdc9dda4c92bb1145aa84945c024346ea66fd4b699e344e45df2e145',
+ version: 1,
+ inputs: [
+ {
+ prevOut: {
+ txid: 'dd2020be54ad3dccf98548512e6f735cac002434bbddb61f19cbe6f3f1de04da',
+ outIdx: 0,
+ },
+ inputScript:
+ '4130ef71df9d2daacf48d05a0361e103e087b636f4d68af8decd769227caf198003991629bf7057fa1572fc0dd3581115a1b06b5c0eafc88555e58521956fe5cbc410768999600fc71a024752102d8cb55aaf01f84335130bf7b3751267e5cf3398a60e5162ff93ec8d77f14850fac',
+ value: 4000,
+ sequenceNo: 4294967295,
+ outputScript:
+ 'a91464275fca443d169d23d077c85ad1bb7a31b6e05987',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a504c63534c5032000747454e455349530343524411437265646f20496e20556e756d2044656f1968747470733a2f2f6372642e6e6574776f726b2f746f6b656e00210334b744e6338ad438c92900c0ed1869c3fd2c0f35a4a9b97a88447b6e2b145f10040001',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a914bbb6c4fecc56ecce35958f87c2367cd3f5e88c2788ac',
+ token: {
+ tokenId:
+ 'cdcdcdcdcdc9dda4c92bb1145aa84945c024346ea66fd4b699e344e45df2e145',
+ tokenType: {
+ protocol: 'ALP',
+ type: 'ALP_TOKEN_TYPE_STANDARD',
+ number: 0,
+ },
+ amount: '0',
+ isMintBaton: true,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: 'ff06c312bef229f6f27989326d9be7e0e142aaa84538967b104b262af69f7f00',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 777777,
+ timeFirstSeen: 0,
+ size: 308,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ 'cdcdcdcdcdc9dda4c92bb1145aa84945c024346ea66fd4b699e344e45df2e145',
+ tokenType: {
+ protocol: 'ALP',
+ type: 'ALP_TOKEN_TYPE_STANDARD',
+ number: 0,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 795680,
+ hash: '00000000000000000b7e89959ee52ca1cd691e1fc3b4891c1888f84261c83e73',
+ timestamp: 1686305735,
+ },
+ },
+ returned: {
+ tokenType: {
+ protocol: 'ALP',
+ type: 'ALP_TOKEN_TYPE_STANDARD',
+ number: 0,
+ },
+ timeFirstSeen: '0',
+ genesisInfo: {
+ tokenTicker: 'CRD',
+ tokenName: 'Credo In Unum Deo',
+ url: 'https://crd.network/token',
+ decimals: 4,
+ data: {},
+ authPubkey:
+ '0334b744e6338ad438c92900c0ed1869c3fd2c0f35a4a9b97a88447b6e2b145f10',
+ },
+ block: {
+ height: 795680,
+ hash: '00000000000000000b7e89959ee52ca1cd691e1fc3b4891c1888f84261c83e73',
+ timestamp: 1686305735,
+ },
+ genesisMintBatons: 1,
+ genesisOutputScripts: [
+ '76a914bbb6c4fecc56ecce35958f87c2367cd3f5e88c2788ac',
+ ],
+ genesisSupply: '0.0000',
+ },
+ },
+ {
+ description: 'slpv2 genesis tx',
+ tokenId:
+ '7e7dacd72dcdb14e00a03dd3aff47f019ed51a6f1f4e4f532ae50692f62bc4e5', // BUX
+ tokenInfo: {
+ tokenId:
+ '7e7dacd72dcdb14e00a03dd3aff47f019ed51a6f1f4e4f532ae50692f62bc4e5',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timeFirstSeen: '0',
+ genesisInfo: {
+ tokenTicker: 'BUX',
+ tokenName: 'Badger Universal Token',
+ url: 'https://bux.digital',
+ decimals: 4,
+ hash: '',
+ },
+ block: {
+ height: 726564,
+ hash: '000000000000000010ea35897b2b7373261fdfbca3d02e4f9a6eeb79dc914315',
+ timestamp: 1644797123,
+ },
+ },
+ genesisTx: {
+ txid: '7e7dacd72dcdb14e00a03dd3aff47f019ed51a6f1f4e4f532ae50692f62bc4e5',
+ version: 1,
+ inputs: [
+ {
+ prevOut: {
+ txid: 'b5605cdda8e5cc5f475f2473f34ad01b29fa0995bac5d37dcb54b858f76db61f',
+ outIdx: 0,
+ },
+ inputScript:
+ '41614bc7f35d66b30c017e111c98ad22086730435bea6cf0ec54188ca425863f2a60ee808a11564258d0defc2bfa1505953e18a8108409fb048cfa39bdacc82fce4121027e6cf8229495afadcb5a7e40365bbc82afcf145eacca3193151e68a61fc81743',
+ value: 3200,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a914502ee2f475081f2031861f3a275c52722199280e88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e45534953034255581642616467657220556e6976657273616c20546f6b656e1368747470733a2f2f6275782e6469676974616c4c0001040102080000000000000000',
+ },
+ {
+ value: 2300,
+ outputScript:
+ 'a9144d80de3cda49fd1bd98eb535da0f2e4880935ea987',
+ spentBy: {
+ txid: '459a8dbf3b31750ddaaed4d2c6a12fb42ef1b83fc0f67175f43332962932aa7d',
+ outIdx: 0,
+ },
+ },
+ {
+ value: 546,
+ outputScript:
+ 'a91420d151c5ab4ca4154407626069eaafd8ce6306fc87',
+ token: {
+ tokenId:
+ '7e7dacd72dcdb14e00a03dd3aff47f019ed51a6f1f4e4f532ae50692f62bc4e5',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '0',
+ isMintBaton: true,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '459a8dbf3b31750ddaaed4d2c6a12fb42ef1b83fc0f67175f43332962932aa7d',
+ outIdx: 1,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 302,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '7e7dacd72dcdb14e00a03dd3aff47f019ed51a6f1f4e4f532ae50692f62bc4e5',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 726564,
+ hash: '000000000000000010ea35897b2b7373261fdfbca3d02e4f9a6eeb79dc914315',
+ timestamp: 1644797123,
+ },
+ },
+ returned: {
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timeFirstSeen: '0',
+ genesisInfo: {
+ tokenTicker: 'BUX',
+ tokenName: 'Badger Universal Token',
+ url: 'https://bux.digital',
+ decimals: 4,
+ hash: '',
+ },
+ block: {
+ height: 726564,
+ hash: '000000000000000010ea35897b2b7373261fdfbca3d02e4f9a6eeb79dc914315',
+ timestamp: 1644797123,
+ },
+ genesisMintBatons: 1,
+ genesisOutputScripts: [
+ 'a91420d151c5ab4ca4154407626069eaafd8ce6306fc87',
+ ],
+ genesisSupply: '0.0000',
+ },
+ },
+ {
+ description: 'Slp type 2 token (BUX)',
+ tokenId:
+ '52b12c03466936e7e3b2dcfcff847338c53c611ba8ab74dd8e4dadf7ded12cf6',
+ tokenInfo: {
+ tokenId:
+ '52b12c03466936e7e3b2dcfcff847338c53c611ba8ab74dd8e4dadf7ded12cf6',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_MINT_VAULT',
+ number: 2,
+ },
+ timeFirstSeen: '0',
+ genesisInfo: {
+ tokenTicker: 'BUX',
+ tokenName: 'Badger Universal Token',
+ url: 'https://bux.digital',
+ decimals: 4,
+ mintVaultScripthash:
+ '08d6edf91c7b93d18306d3b8244587e43f11df4b',
+ hash: '',
+ },
+ block: {
+ height: 811408,
+ hash: '000000000000000016d3b567884f11f44592ce7cd2642e74014b1c65bc6a5c81',
+ timestamp: 1695700586,
+ },
+ },
+ genesisTx: {
+ txid: '52b12c03466936e7e3b2dcfcff847338c53c611ba8ab74dd8e4dadf7ded12cf6',
+ version: 1,
+ inputs: [
+ {
+ prevOut: {
+ txid: '8586a0e6dc08653dc5b88afe751efbb97d78246482985d01802c98b75f873fba',
+ outIdx: 10,
+ },
+ inputScript:
+ '473044022040b7bb9093b092003b5c41090f4b7560a7bcfed35278fd05d2f1083653529ea902205a11af8aea5d16a01dc7648397eb6b04369dda9e3e9ecc4a9efe3f5b4a41a1dd412102fafcdb1f5f0d2e49909fbafc18f339bcfc2b765b3def934d501eb798e626c7b3',
+ value: 3851630,
+ sequenceNo: 4294967294,
+ outputScript:
+ '76a91452558a0640aae72592c3b336a3a4959ce97906b488ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001020747454e45534953034255581642616467657220556e6976657273616c20546f6b656e1368747470733a2f2f6275782e6469676974616c4c0001041408d6edf91c7b93d18306d3b8244587e43f11df4b080000000000000000',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91452558a0640aae72592c3b336a3a4959ce97906b488ac',
+ },
+ {
+ value: 3850752,
+ outputScript:
+ '76a914f4592a09e8da1a2157916963bc0fb7fe682df73e88ac',
+ },
+ ],
+ lockTime: 811407,
+ timeFirstSeen: 0,
+ size: 331,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '52b12c03466936e7e3b2dcfcff847338c53c611ba8ab74dd8e4dadf7ded12cf6',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_MINT_VAULT',
+ number: 2,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 811408,
+ hash: '000000000000000016d3b567884f11f44592ce7cd2642e74014b1c65bc6a5c81',
+ timestamp: 1695700586,
+ },
+ },
+ returned: {
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_MINT_VAULT',
+ number: 2,
+ },
+ timeFirstSeen: '0',
+ genesisInfo: {
+ tokenTicker: 'BUX',
+ tokenName: 'Badger Universal Token',
+ url: 'https://bux.digital',
+ decimals: 4,
+ mintVaultScripthash:
+ '08d6edf91c7b93d18306d3b8244587e43f11df4b',
+ hash: '',
+ },
+ block: {
+ height: 811408,
+ hash: '000000000000000016d3b567884f11f44592ce7cd2642e74014b1c65bc6a5c81',
+ timestamp: 1695700586,
+ },
+ genesisMintBatons: 0,
+ genesisOutputScripts: [],
+ genesisSupply: '0.0000',
+ },
+ },
+ ],
+ expectedErrors: [
+ {
+ description:
+ 'Error is thrown if 1st chronik API call not completed successfully',
+ tokenId:
+ '1111111111111111111111111111111111111111111111111111111111111111',
+ tokenInfo: new Error(
+ 'Bad response from chronik.token(tokenId)',
+ ),
+ genesisTx: {}, // non-error response
+ msg: new Error('Bad response from chronik.token(tokenId)'),
+ },
+ {
+ description:
+ 'Error is thrown if 2nd chronik API call not completed successfully',
+ tokenId:
+ '1111111111111111111111111111111111111111111111111111111111111111',
+ tokenInfo: {}, // non-error response
+ genesisTx: new Error('Bad response from chronik.tx(tokenId)'),
+ msg: new Error('Bad response from chronik.tx(tokenId)'),
+ },
+ ],
+ },
};
diff --git a/cashtab/src/chronik/index.js b/cashtab/src/chronik/index.js
--- a/cashtab/src/chronik/index.js
+++ b/cashtab/src/chronik/index.js
@@ -8,8 +8,7 @@
import { chronik as chronikConfig } from 'config/chronik';
import { getStackArray } from 'ecash-script';
import cashaddr from 'ecashaddrjs';
-import CashtabCache from 'config/CashtabCache';
-import { toXec } from 'wallet';
+import { toXec, decimalizeTokenAmount, undecimalizeTokenAmount } from 'wallet';
export const getTxHistoryPage = async (chronik, hash160, page = 0) => {
let txHistoryPage;
@@ -61,74 +60,52 @@
return false;
};
-// Return false if do not get a valid response
-// TODO deprecate, we should be getting this from cache
-// This info will be cached on app startup
-export const getTokenStats = async (chronik, tokenId) => {
- try {
- // token attributes available via chronik's token() method
- let tokenResponseObj = await chronik.token(tokenId);
-
- return tokenResponseObj;
- } catch (err) {
- console.log(
- `Error fetching token stats for tokenId ${tokenId}: ` + err,
- );
- return false;
- }
-};
-
/**
- *
+ * Return a promise to fetch all utxos at an address (and add a 'path' key to them)
+ * We need the path key so that we know which wif to sign this utxo with
+ * If we add HD wallet support, we will need to add an address key, and change the structure of wallet.paths
* @param {ChronikClientNode} chronik
- * @param {string} hash160
- * @returns chronik-client response object
+ * @param {string} address
+ * @param {number} path
+ * @returns {Promise}
*/
-export const getUtxosSingleHashChronik = async (chronik, hash160) => {
- // Get utxos at a single address, which chronik takes in as a hash160
- const utxos = await chronik.script('p2pkh', hash160).utxos();
- return utxos.utxos;
-};
-
-export const returnGetUtxosChronikPromise = (chronik, hash160AndAddressObj) => {
- /*
- Chronik thinks in hash160s, but people and wallets think in addresses
- Add the address to each utxo
- */
+export const returnGetPathedUtxosPromise = (chronik, address, path) => {
return new Promise((resolve, reject) => {
- getUtxosSingleHashChronik(chronik, hash160AndAddressObj.hash).then(
- result => {
- for (let i = 0; i < result.length; i += 1) {
- const thisUtxo = result[i];
- thisUtxo.address = hash160AndAddressObj.address;
- }
- resolve(result);
- },
- err => {
- reject(err);
- },
- );
+ chronik
+ .address(address)
+ .utxos()
+ .then(
+ result => {
+ for (const utxo of result.utxos) {
+ utxo.path = path;
+ }
+ resolve(result.utxos);
+ },
+ err => {
+ reject(err);
+ },
+ );
});
};
-export const getUtxosChronik = async (chronik, hash160sMappedToAddresses) => {
- /*
- Chronik only accepts utxo requests for one address at a time
- Construct an array of promises for each address
- Note: Chronik requires the hash160 of an address for this request
- */
+/**
+ * Get all utxos for a given wallet
+ * @param {ChronikClientNode} chronik
+ * @param {object} wallet a cashtab wallet
+ * @returns
+ */
+export const getUtxos = async (chronik, wallet) => {
const chronikUtxoPromises = [];
- for (let i = 0; i < hash160sMappedToAddresses.length; i += 1) {
- const thisPromise = returnGetUtxosChronikPromise(
+ wallet.paths.forEach((pathInfo, path) => {
+ const thisPromise = returnGetPathedUtxosPromise(
chronik,
- hash160sMappedToAddresses[i],
+ pathInfo.address,
+ path,
);
chronikUtxoPromises.push(thisPromise);
- }
- const allUtxos = await Promise.all(chronikUtxoPromises);
- // Since each individual utxo has address information, no need to keep them in distinct arrays
- // Combine into one array of all utxos
- const flatUtxos = allUtxos.flat();
+ });
+ const utxoResponsesByPath = await Promise.all(chronikUtxoPromises);
+ const flatUtxos = utxoResponsesByPath.flat();
return flatUtxos;
};
@@ -154,250 +131,37 @@
};
/**
- * Build tokens array without accounting for token genesis info
- * TODO this should be a map, not an array of objects. Handle after migration
- * @param {Tx_InNode[]} slpUtxos
- * @returns
+ * Get just the tx objects from chronik history() responses
+ * @param {TxHistoryPage_InNode[]} txHistoryOfAllAddresses
+ * @returns {Tx_InNode[]}
*/
-export const getPreliminaryTokensArray = slpUtxos => {
- // Iterate over the slpUtxos to create the 'tokens' object
- let tokensById = {};
-
- slpUtxos.forEach(slpUtxos => {
- /*
- Note that a wallet could have many eToken utxos all belonging to the same eToken
- For example, a user could have 100 of a certain eToken, but this is composed of
- four utxos, one for 17, one for 50, one for 30, one for 3
- */
-
- // Start with the existing object for this particular token, if it exists
- let token = tokensById[slpUtxos.token.tokenId];
-
- if (token) {
- if (slpUtxos.token.amount) {
- token.balance = token.balance.plus(
- new BN(slpUtxos.token.amount),
- );
- }
- } else {
- // If it does not exist, create it
- token = {};
- token.tokenId = slpUtxos.token.tokenId;
- if (slpUtxos.token.amount) {
- token.balance = new BN(slpUtxos.token.amount);
- } else {
- token.balance = new BN(0);
- }
- tokensById[slpUtxos.token.tokenId] = token;
- }
- });
-
- const preliminaryTokensArray = Object.values(tokensById);
- return preliminaryTokensArray;
-};
-
-/**
- * Get and cache genesisInfo for a token
- * @param {object} chronik chronik-client instance
- * @param {string} tokenId tokenId you want genesisInfo for
- * @param {Map} cachedTokens the map stored at cashtabCache.tokens
- * @returns {promise} promise resolving to chronik's genesisInfo key from chronik.token(tokenId)
- */
-export const returnGetTokenInfoChronikPromise = (
- chronik,
- tokenId,
- cachedTokens,
-) => {
- /*
- The chronik.tx(txid) API call returns extensive transaction information
- For the purposes of finalizing token information, we only need the token metadata
-
- This function returns a promise that extracts only this needed information from
- the chronik.tx(txid) API call
-
- In this way, calling Promise.all() on an array of tokenIds that lack metadata
- will return an array with all required metadata
- */
- return new Promise((resolve, reject) => {
- chronik.token(tokenId).then(
- result => {
- if (typeof result !== 'undefined') {
- if ('slpTxData' in result) {
- // NNG chronik
- cachedTokens.set(tokenId, result.slpTxData.genesisInfo);
- resolve(result.slpTxData.genesisInfo);
- }
- if ('genesisInfo' in result) {
- // in-node chronik
- cachedTokens.set(tokenId, result.genesisInfo);
- resolve(result.genesisInfo);
- }
- }
-
- reject(
- new Error(
- `Invalid token info format from chronik.token(${tokenId})`,
- ),
- );
- },
- err => {
- reject(err);
- },
- );
- });
-};
-
-/**
- * Add genesisInfo and calculate balance using now-known token decimals
- * @param {array} preliminaryTokensArray array of token objects formatted to be read by Cashtab
- * returned by getPreliminaryTokensArray
- * @param {Map} cachedTokens the map stored at cashtabCache.tokens
- * @returns {array} finalTokensArray = preliminaryTokensArray updated for decimals for
- * tokens where we did not yet have this info from cache or chronik
- */
-export const processPreliminaryTokensArray = (
- preliminaryTokensArray,
- cachedTokens,
-) => {
- /* Iterate over preliminaryTokensArray to
-
- 1 - Add slp metadata (token ticker, name, other metadata)
- 2 - Calculate the token balance. Token balance in
- preliminaryTokensArray does not take into account the
- decimal places of the token...so it is incorrect.
-
- */
- const finalTokenArray = [];
- for (let i = 0; i < preliminaryTokensArray.length; i += 1) {
- const thisToken = preliminaryTokensArray[i];
- const thisTokenId = thisToken.tokenId;
-
- // Because tokenInfoByTokenId is indexed by tokenId, it's easy to reference
- const thisTokenInfo = cachedTokens.get(thisTokenId);
-
- // The decimals are specifically needed to calculate the correct balance
- const thisTokenDecimals = thisTokenInfo.decimals;
-
- // Add info object to token
- thisToken.info = thisTokenInfo;
-
- // Update balance according to decimals and store it as a string
- thisToken.balance = thisToken.balance
- .shiftedBy(-1 * thisTokenDecimals)
- .toString();
-
- // Now that you have the metadata and the correct balance,
- // preliminaryTokenInfo is finalTokenInfo
- finalTokenArray.push(thisToken);
- }
- return finalTokenArray;
-};
-
-/**
- * Add tokenDecimals info to walletState.tokens and update cachedTokens if you have uncached tokens
- * @param {object} chronik chronik-client instance
- * @param {array} preliminaryTokensArray return value from getPreliminaryTokensArray
- * @param {Map} cachedTokens the map stored at cashtabCache.tokens
- * @returns {object}
- * {
- * tokens {array} output of processPreliminaryTokensArray
- * cachedTokens {Map} the map stored at cashtabCache.tokens, either same as input or updated with new tokens
- * newTokensToCache {boolean} true if we have added more tokens to cache
- * }
- */
-export const finalizeTokensArray = async (
- chronik,
- preliminaryTokensArray,
- cachedTokens = new CashtabCache().tokens,
-) => {
- // Iterate over preliminaryTokensArray to determine what tokens you need to make API calls for
-
- // Create an array of promises
- // Each promise is a chronik API call to obtain token metadata for this token ID
- const getTokenInfoPromises = [];
-
- const UNKNOWN_TOKEN_ID =
- '0000000000000000000000000000000000000000000000000000000000000000';
-
- for (let i = 0; i < preliminaryTokensArray.length; i += 1) {
- const thisTokenId = preliminaryTokensArray[i].tokenId;
- // See if you already have this info in cachedTokenInfo
- if (cachedTokens.has(thisTokenId)) {
- // If you already have this info in cache,
- // do not create an API request for it
- continue;
- }
- if (thisTokenId === UNKNOWN_TOKEN_ID) {
- // If we have unknown token utxos, hardcode cache info
- // Calling chronik.token(UNKNOWN_TOKEN_ID) will always throw an error
- cachedTokens.set(UNKNOWN_TOKEN_ID, {
- decimals: 0,
- tokenTicker: 'UNKNOWN',
- tokenName: 'Unknown Token',
- url: 'N/A',
- });
- continue;
- }
- const thisTokenInfoPromise = returnGetTokenInfoChronikPromise(
- chronik,
- thisTokenId,
- cachedTokens,
- );
- getTokenInfoPromises.push(thisTokenInfoPromise);
- }
-
- const newTokensToCache = getTokenInfoPromises.length > 0;
-
- // Fetch uncached token genesisInfo and add to cache
- try {
- await Promise.all(getTokenInfoPromises);
- } catch (err) {
- console.log(`Error in Promise.all(getTokenInfoPromises)`, err);
- }
-
- // Now use cachedTokenInfoByTokenId object to finalize token info
- // Split this out into a separate function so you can unit test
- const finalTokenArray = processPreliminaryTokensArray(
- preliminaryTokensArray,
- cachedTokens,
- );
-
- // Sort tokens alphabetically by ticker
- finalTokenArray.sort((a, b) =>
- a.info.tokenTicker.localeCompare(b.info.tokenTicker),
- );
-
- return { tokens: finalTokenArray, cachedTokens, newTokensToCache };
-};
-
export const flattenChronikTxHistory = txHistoryOfAllAddresses => {
- // Create an array of all txs
-
let flatTxHistoryArray = [];
- for (let i = 0; i < txHistoryOfAllAddresses.length; i += 1) {
- const txHistoryResponseOfThisAddress = txHistoryOfAllAddresses[i];
- const txHistoryOfThisAddress = txHistoryResponseOfThisAddress.txs;
- flatTxHistoryArray = flatTxHistoryArray.concat(txHistoryOfThisAddress);
+ for (const txHistoryThisAddress of txHistoryOfAllAddresses) {
+ flatTxHistoryArray = flatTxHistoryArray.concat(
+ txHistoryThisAddress.txs,
+ );
}
return flatTxHistoryArray;
};
-export const sortAndTrimChronikTxHistory = (
- flatTxHistoryArray,
- txHistoryCount,
-) => {
- // Isolate unconfirmed txs
- // In chronik, unconfirmed txs have an `undefined` block key
+/**
+ * Sort an array of chronik txs chronologically and return the first renderedCount of them
+ * @param {Tx_InNode[]} txs
+ * @param {number} renderedCount how many txs to return
+ * @returns
+ */
+export const sortAndTrimChronikTxHistory = (txs, renderedCount) => {
const unconfirmedTxs = [];
const confirmedTxs = [];
- for (let i = 0; i < flatTxHistoryArray.length; i += 1) {
- const thisTx = flatTxHistoryArray[i];
- if (typeof thisTx.block === 'undefined') {
- unconfirmedTxs.push(thisTx);
+ for (const tx of txs) {
+ if (typeof tx.block === 'undefined') {
+ unconfirmedTxs.push(tx);
} else {
- confirmedTxs.push(thisTx);
+ confirmedTxs.push(tx);
}
}
+
// Sort confirmed txs by blockheight, and then timeFirstSeen
const sortedConfirmedTxHistoryArray = confirmedTxs.sort(
(a, b) =>
@@ -406,52 +170,32 @@
// For blocks with the same height, we want more recent timeFirstSeen i.e. higher timeFirstSeen to have earlier array indices
b.timeFirstSeen - a.timeFirstSeen,
);
+
// Sort unconfirmed txs by timeFirstSeen
const sortedUnconfirmedTxHistoryArray = unconfirmedTxs.sort(
(a, b) => b.timeFirstSeen - a.timeFirstSeen,
);
+
// The unconfirmed txs are more recent, so they should be inserted into an array before the confirmed txs
const sortedChronikTxHistoryArray = sortedUnconfirmedTxHistoryArray.concat(
sortedConfirmedTxHistoryArray,
);
const trimmedAndSortedChronikTxHistoryArray =
- sortedChronikTxHistoryArray.splice(0, txHistoryCount);
+ sortedChronikTxHistoryArray.splice(0, renderedCount);
return trimmedAndSortedChronikTxHistoryArray;
};
-export const returnGetTxHistoryChronikPromise = (
- chronik,
- hash160AndAddressObj,
-) => {
- /*
- Chronik thinks in hash160s, but people and wallets think in addresses
- Add the address to each utxo
- */
- return new Promise((resolve, reject) => {
- chronik
- .script('p2pkh', hash160AndAddressObj.hash)
- .history(/*page=*/ 0, /*page_size=*/ chronikConfig.txHistoryCount)
- .then(
- result => {
- resolve(result);
- },
- err => {
- reject(err);
- },
- );
- });
-};
-
/**
- *
+ * Parse a Tx_InNode object for rendering in Cashtab
+ * TODO Potentially more efficient to do this calculation in the Tx.js component
* @param {Tx_InNode} tx
* @param {object} wallet cashtab wallet
* @param {Map} cachedTokens
* @returns
*/
-export const parseChronikTx = (tx, wallet, cachedTokens) => {
+export const parseTx = (tx, wallet, cachedTokens) => {
const walletHash160s = getHashArrayFromWallet(wallet);
const { inputs, outputs, tokenEntries } = tx;
@@ -751,29 +495,18 @@
const xecAmount = toXec(satoshis);
// Get decimal info for correct etokenAmount
- let genesisInfo = {};
-
+ let assumedTokenDecimals = false;
if (isEtokenTx) {
- // Get token genesis info from cache
+ // Parse with decimals = 0 if you do not have this token cached for some reason
+ // Acceptable error rendering in tx history
let decimals = 0;
- try {
- genesisInfo = cachedTokens.get(tokenId);
- if (typeof genesisInfo !== 'undefined') {
- genesisInfo.success = true;
- decimals = genesisInfo.decimals;
- etokenAmount = etokenAmount.shiftedBy(-1 * decimals);
- } else {
- genesisInfo = { success: false };
- }
- } catch (err) {
- console.log(
- `Error getting token info from cache in parseChronikTx for ${tx.txid}`,
- err,
- );
- // To keep this function synchronous, do not get this info from the API if it is not in cache
- // Instead, return a flag so that useWallet.js knows and can fetch this info + add it to cache
- genesisInfo = { success: false };
+ const cachedTokenInfo = cachedTokens.get(tokenId);
+ if (typeof cachedTokenInfo !== 'undefined') {
+ decimals = cachedTokenInfo.genesisInfo.decimals;
+ } else {
+ assumedTokenDecimals = true;
}
+ etokenAmount = etokenAmount.shiftedBy(-1 * decimals);
}
etokenAmount = etokenAmount.toString();
@@ -786,13 +519,13 @@
etokenAmount,
isTokenBurn,
tokenEntries: tx.tokenEntries,
- genesisInfo,
airdropFlag,
airdropTokenId,
opReturnMessage: '',
isCashtabMessage,
isEncryptedMessage,
replyAddress,
+ assumedTokenDecimals,
};
}
// Otherwise do not include these fields
@@ -812,89 +545,72 @@
/**
* Get tx history of cashtab wallet
- * @param {object} chronik chronik-client instance
+ * - Get tx history of each path in wallet
+ * - sort by timeFirstSeen + block
+ * - Trim to number of txs Cashtab renders
+ * - Parse txs for rendering in Cashtab
+ * - Update cachedTokens with any new tokenIds
+ * @param {ChronikClientNode} chronik chronik-client instance
* @param {object} wallet cashtab wallet
* @param {Map} cachedTokens the map stored at cashtabCache.tokens
- * @returns {object}
- * {
- * parsedTxHistory {array} tx history output parsed for rendering txs in Cashtab
- * cachedTokensAfterHistory {Map} cachedTokens the map stored at cashtabCache.tokens updated for any tokens found in tx history
- * txHistoryNewTokensToCache {boolean} true if we have added tokens
- * }
+ * @returns {array} Tx_InNode[], each tx also has a 'parsed' key with other rendering info
*/
-export const getTxHistoryChronik = async (chronik, wallet, cachedTokens) => {
- // Create array of promises to get chronik history for each address
- // Combine them all and sort by blockheight and firstSeen
- // Add all the info cashtab needs to make them useful
-
- let txHistoryPromises = [];
- for (let i = 0; i < wallet.paths.length; i += 1) {
- const txHistoryPromise = returnGetTxHistoryChronikPromise(
- chronik,
- wallet.paths[i],
- );
- txHistoryPromises.push(txHistoryPromise);
- }
- let txHistoryOfAllAddresses;
- try {
- txHistoryOfAllAddresses = await Promise.all(txHistoryPromises);
- } catch (err) {
- console.log(`Error in Promise.all(txHistoryPromises)`, err);
- }
+export const getHistory = async (chronik, wallet, cachedTokens) => {
+ const txHistoryPromises = [];
+ wallet.paths.forEach(pathInfo => {
+ txHistoryPromises.push(chronik.address(pathInfo.address).history());
+ });
+
+ // Just throw an error if you get a chronik error
+ // This will be handled in the update loop
+ const txHistoryOfAllAddresses = await Promise.all(txHistoryPromises);
+
const flatTxHistoryArray = flattenChronikTxHistory(txHistoryOfAllAddresses);
- const sortedTxHistoryArray = sortAndTrimChronikTxHistory(
+ const renderedTxs = sortAndTrimChronikTxHistory(
flatTxHistoryArray,
chronikConfig.txHistoryCount,
);
// Parse txs
- const chronikTxHistory = [];
- const uncachedTokenIds = new Set();
- for (let i = 0; i < sortedTxHistoryArray.length; i += 1) {
- const sortedTx = sortedTxHistoryArray[i];
- // Add token genesis info so parsing function can calculate amount by decimals
- sortedTx.parsed = parseChronikTx(sortedTx, wallet, cachedTokens);
- // Check to see if this tx was from a token without genesisInfo in cachedTokens
- if (
- sortedTx.parsed.isEtokenTx &&
- sortedTx.parsed.genesisInfo &&
- !sortedTx.parsed.genesisInfo.success
- ) {
- // Only add if the token id is not already in uncachedTokenIds
- const uncachedTokenId = sortedTx.parsed.tokenEntries[0].tokenId;
- uncachedTokenIds.add(uncachedTokenId);
+ const history = [];
+ for (const tx of renderedTxs) {
+ const { tokenEntries } = tx;
+
+ // Get all tokenIds associated with this tx
+ const tokenIds = new Set();
+ for (const tokenEntry of tokenEntries) {
+ tokenIds.add(tokenEntry.tokenId);
}
- chronikTxHistory.push(sortedTx);
- }
- const txHistoryNewTokensToCache = uncachedTokenIds.size > 0;
+ // Cache any tokenIds you do not have cached
+ for (const tokenId of [...tokenIds]) {
+ if (typeof cachedTokens.get(tokenId) === 'undefined') {
+ // Add it to cache right here
+ try {
+ const newTokenCacheInfo = await getTokenGenesisInfo(
+ chronik,
+ tokenId,
+ );
+ cachedTokens.set(tokenId, newTokenCacheInfo);
+ } catch (err) {
+ // If you have an error getting the calculated token cache info, do not throw
+ // Could be some token out there that we do not parse properly with getTokenGenesisInfo
+ // Log it
+ // parseTx is tolerant to not having the info in cache
+ console.error(
+ `Error in getTokenGenesisInfo for tokenId ${tokenId}`,
+ err,
+ );
+ }
+ }
+ }
- // Iterate over uncachedTokenIds to get genesis info and add to cache
- const getTokenInfoPromises = [];
- for (const uncachedTokenId of uncachedTokenIds) {
- const thisTokenInfoPromise = returnGetTokenInfoChronikPromise(
- chronik,
- uncachedTokenId,
- cachedTokens,
- );
- getTokenInfoPromises.push(thisTokenInfoPromise);
- }
+ tx.parsed = parseTx(tx, wallet, cachedTokens);
- // Get all the token info you need
- try {
- await Promise.all(getTokenInfoPromises);
- } catch (err) {
- console.log(
- `Error in Promise.all(getTokenInfoPromises) in getTxHistoryChronik`,
- err,
- );
+ history.push(tx);
}
- return {
- parsedTxHistory: chronikTxHistory,
- cachedTokensAfterHistory: cachedTokens,
- txHistoryNewTokensToCache,
- };
+ return history;
};
export const getMintAddress = async (chronik, tokenId) => {
@@ -923,3 +639,142 @@
return err;
}
};
+
+/**
+ * Get all info about a token used in Cashtab's token cache
+ * @param {ChronikClientNode} chronik
+ * @param {string} tokenId
+ * @returns {object}
+ */
+export const getTokenGenesisInfo = async (chronik, tokenId) => {
+ // We can get timeFirstSeen, block, tokenType, and genesisInfo from the token() endpoint
+ // If we call this endpoint before the genesis tx is confirmed, we will not get block
+ // So, block does not need to be included
+
+ const tokenInfo = await chronik.token(tokenId);
+ const genesisTxInfo = await chronik.tx(tokenId);
+
+ const { timeFirstSeen, genesisInfo, tokenType } = tokenInfo;
+ const decimals = genesisInfo.decimals;
+
+ // Initialize variables for determined quantities we want to cache
+
+ /**
+ * genesisSupply {string}
+ * Quantity of token created at mint
+ * Note: we may have genesisSupply at different genesisAddresses
+ * We do not track this information, only total genesisSupply
+ * Cached as a decimalized string, e.g. 0.000 if 0 with 3 decimal places
+ * 1000.000000000 if one thousand with 9 decimal places
+ */
+ let genesisSupply = decimalizeTokenAmount('0', decimals);
+
+ /**
+ * genesisMintBatons {number}
+ * Number of mint batons created in the genesis tx for this token
+ */
+ let genesisMintBatons = 0;
+
+ /**
+ * genesisOutputScripts {Set(<outputScript>)}
+ * Address(es) where initial token supply was minted
+ */
+ let genesisOutputScripts = new Set();
+
+ // Iterate over outputs
+ for (const output of genesisTxInfo.outputs) {
+ if ('token' in output && output.token.tokenId === tokenId) {
+ // If this output of this genesis tx is associated with this tokenId
+
+ const { token, outputScript } = output;
+
+ // Add its outputScript to genesisOutputScripts
+ genesisOutputScripts.add(outputScript);
+
+ const { isMintBaton, amount } = token;
+ if (isMintBaton) {
+ // If it is a mintBaton, increment genesisMintBatons
+ genesisMintBatons += 1;
+ }
+
+ // Increment genesisSupply
+ // decimalizeTokenAmount, undecimalizeTokenAmount
+ //genesisSupply = genesisSupply.plus(new BN(amount));
+
+ genesisSupply = decimalizeTokenAmount(
+ (
+ BigInt(undecimalizeTokenAmount(genesisSupply, decimals)) +
+ BigInt(amount)
+ ).toString(),
+ decimals,
+ );
+ }
+ }
+
+ const tokenCache = {
+ tokenType,
+ genesisInfo,
+ timeFirstSeen,
+ genesisSupply,
+ // Return genesisOutputScripts as an array as we no longer require Set features
+ genesisOutputScripts: [...genesisOutputScripts],
+ genesisMintBatons,
+ };
+ if ('block' in tokenInfo) {
+ // If the genesis tx is confirmed at the time we check
+ tokenCache.block = tokenInfo.block;
+ }
+
+ // Note: if it is not confirmed, we can update the cache later when we try to use this value
+
+ return tokenCache;
+};
+
+/**
+ * Get decimalized balance of every token held by a wallet
+ * Update Cashtab's tokenCache if any tokens are uncached
+ * @param {ChronikClientNode} chronik
+ * @param {array} slpUtxos array of token utxos from chronik
+ * @param {Map} tokenCache Cashtab's token cache
+ * @returns {Map} Map of tokenId => token balance as decimalized string
+ * Also updates tokenCache
+ */
+export const getTokenBalances = async (chronik, slpUtxos, tokenCache) => {
+ const walletStateTokens = new Map();
+ for (const utxo of slpUtxos) {
+ // Every utxo in slpUtxos will have a tokenId
+ const { token } = utxo;
+ const { tokenId, amount } = token;
+ // Is this token cached?
+ let cachedTokenInfo = tokenCache.get(tokenId);
+ if (typeof cachedTokenInfo === 'undefined') {
+ // If we have not cached this token before, cache it
+ cachedTokenInfo = await getTokenGenesisInfo(chronik, tokenId);
+ tokenCache.set(tokenId, cachedTokenInfo);
+ }
+ // Now decimals is available
+ const decimals = cachedTokenInfo.genesisInfo.decimals;
+
+ const tokenBalanceInMap = walletStateTokens.get(tokenId);
+
+ // Update or initialize token balance as a decimalized string in walletStateTokens Map
+ walletStateTokens.set(
+ tokenId,
+ typeof tokenBalanceInMap === 'undefined'
+ ? decimalizeTokenAmount(amount, decimals)
+ : decimalizeTokenAmount(
+ (
+ BigInt(
+ undecimalizeTokenAmount(
+ tokenBalanceInMap,
+ decimals,
+ ),
+ ) + BigInt(amount)
+ ).toString(),
+ decimals,
+ ),
+ );
+ }
+
+ return walletStateTokens;
+};
diff --git a/cashtab/src/components/Airdrop/Airdrop.js b/cashtab/src/components/Airdrop/Airdrop.js
--- a/cashtab/src/components/Airdrop/Airdrop.js
+++ b/cashtab/src/components/Airdrop/Airdrop.js
@@ -183,9 +183,7 @@
const excludedAddresses = [];
if (ignoreOwnAddress) {
- excludedAddresses.push(
- wallet.paths.find(pathInfo => pathInfo.path === 1899).address,
- );
+ excludedAddresses.push(wallet.paths.get(1899).address);
}
if (ignoreMintAddress) {
let mintAddress;
diff --git a/cashtab/src/components/Alias/Alias.js b/cashtab/src/components/Alias/Alias.js
--- a/cashtab/src/components/Alias/Alias.js
+++ b/cashtab/src/components/Alias/Alias.js
@@ -95,9 +95,7 @@
const { settings, wallets } = cashtabState;
const wallet = wallets.length > 0 ? wallets[0] : false;
const defaultAddress =
- wallet !== false
- ? wallet.paths.find(pathInfo => pathInfo.path === 1899).address
- : '';
+ wallet !== false ? wallet.paths.get(1899).address : '';
const walletState = getWalletState(wallet);
const { balanceSats, tokens } = walletState;
const [formData, setFormData] = useState({
diff --git a/cashtab/src/components/Alias/__tests__/Alias.test.js b/cashtab/src/components/Alias/__tests__/Alias.test.js
--- a/cashtab/src/components/Alias/__tests__/Alias.test.js
+++ b/cashtab/src/components/Alias/__tests__/Alias.test.js
@@ -84,9 +84,7 @@
localforage,
);
- const defaultAddress = walletWithXecAndTokens.paths.find(
- pathInfo => pathInfo.path === 1899,
- ).address;
+ const defaultAddress = walletWithXecAndTokens.paths.get(1899).address;
// Mock the fetch call to alias-server's '/prices' endpoint
const aliasPricesFetchUrl = `${aliasSettings.aliasServerBaseUrl}/prices`;
@@ -147,9 +145,7 @@
json: () => Promise.resolve(aliasPricesResp),
});
- const defaultAddress = walletWithXecAndTokens.paths.find(
- pathInfo => pathInfo.path === 1899,
- ).address;
+ const defaultAddress = walletWithXecAndTokens.paths.get(1899).address;
// Mock the refreshAliases() call to alias-server's '/address' endpoint upon component load
const addressFetchUrl = `${aliasSettings.aliasServerBaseUrl}/address/${defaultAddress}`;
@@ -200,9 +196,7 @@
json: () => Promise.resolve(aliasPricesResp),
});
- const defaultAddress = walletWithXecAndTokens.paths.find(
- pathInfo => pathInfo.path === 1899,
- ).address;
+ const defaultAddress = walletWithXecAndTokens.paths.get(1899).address;
// Mock the refreshAliases() call to alias-server's '/address' endpoint upon component load
const addressFetchUrl = `${aliasSettings.aliasServerBaseUrl}/address/${defaultAddress}`;
@@ -244,9 +238,7 @@
localforage,
);
- const defaultAddress = walletWithXecAndTokens.paths.find(
- pathInfo => pathInfo.path === 1899,
- ).address;
+ const defaultAddress = walletWithXecAndTokens.paths.get(1899).address;
// Note: Not mocking the '/prices' API call here in order to populate aliasValidationError
diff --git a/cashtab/src/components/Alias/fixtures/mocks.js b/cashtab/src/components/Alias/fixtures/mocks.js
--- a/cashtab/src/components/Alias/fixtures/mocks.js
+++ b/cashtab/src/components/Alias/fixtures/mocks.js
@@ -4,9 +4,7 @@
import { walletWithXecAndTokens } from 'components/fixtures/mocks';
-const defaultAddress = walletWithXecAndTokens.paths.find(
- pathInfo => pathInfo.path === 1899,
-).address;
+const defaultAddress = walletWithXecAndTokens.paths.get(1899).address;
export const aliasAddressTwoRegisteredOnePending = {
registered: [
{
diff --git a/cashtab/src/components/AppModes/Extension.js b/cashtab/src/components/AppModes/Extension.js
--- a/cashtab/src/components/AppModes/Extension.js
+++ b/cashtab/src/components/AppModes/Extension.js
@@ -30,9 +30,7 @@
// Get address from active wallet
let address;
try {
- address = wallet.paths.find(
- pathInfo => pathInfo.path === 1899,
- ).address;
+ address = wallet.paths.get(1899).address;
console.log(`Address fetched from extension`, address);
} catch (err) {
// The wallet object can be 'false' when Cashtab first loads. In this case, we want this function to do nothing.
diff --git a/cashtab/src/components/Common/WalletLabel.js b/cashtab/src/components/Common/WalletLabel.js
--- a/cashtab/src/components/Common/WalletLabel.js
+++ b/cashtab/src/components/Common/WalletLabel.js
@@ -49,9 +49,7 @@
`;
const WalletLabel = ({ wallets, settings, updateCashtabState }) => {
- const address = wallets[0].paths.find(
- pathInfo => pathInfo.path === 1899,
- ).address;
+ const address = wallets[0].paths.get(1899).address;
const handleSelectWallet = e => {
const walletName = e.target.value;
@@ -109,19 +107,12 @@
PropTypes.shape({
mnemonic: PropTypes.string,
name: PropTypes.string,
- paths: PropTypes.arrayOf(
- PropTypes.shape({
- address: PropTypes.string,
- hash: PropTypes.string,
- path: PropTypes.number,
- wif: PropTypes.string,
- }),
- ),
+ paths: PropTypes.instanceOf(Map),
state: PropTypes.shape({
balanceSats: PropTypes.number,
nonSlpUtxos: PropTypes.array, // Tx_InNode[]
slpUtxos: PropTypes.array, // Tx_InNode[]
- tokens: PropTypes.array,
+ tokens: PropTypes.instanceOf(Map),
parsedTxHistory: PropTypes.array,
}),
}),
diff --git a/cashtab/src/components/Configure/Configure.js b/cashtab/src/components/Configure/Configure.js
--- a/cashtab/src/components/Configure/Configure.js
+++ b/cashtab/src/components/Configure/Configure.js
@@ -1052,9 +1052,7 @@
}
// initialise saved wallet name and address to state for confirmation modal
setManualContactName(wallet.name);
- setManualContactAddress(
- wallet.paths.find(pathInfo => pathInfo.path === 1899).address,
- );
+ setManualContactAddress(wallet.paths.get(1899).address);
setSavedWalletContactModal(true);
};
diff --git a/cashtab/src/components/Configure/__tests__/Configure.test.js b/cashtab/src/components/Configure/__tests__/Configure.test.js
--- a/cashtab/src/components/Configure/__tests__/Configure.test.js
+++ b/cashtab/src/components/Configure/__tests__/Configure.test.js
@@ -22,6 +22,7 @@
import { validSavedWallets } from 'components/fixtures/mocks';
import CashtabTestWrapper from 'components/fixtures/CashtabTestWrapper';
import * as bip39 from 'bip39';
+import { cashtabWalletsFromJSON } from 'helpers';
// https://stackoverflow.com/questions/39830580/jest-test-fails-typeerror-window-matchmedia-is-not-a-function
Object.defineProperty(window, 'matchMedia', {
@@ -105,8 +106,7 @@
// Add a new saved wallet that can be rendered
const addedSavedWalletContact = {
- address: savedWallet.paths.find(pathInfo => pathInfo.path === 1899)
- .address,
+ address: savedWallet.paths.get(1899).address,
name: savedWallet.name,
};
await localforage.setItem('wallets', [
@@ -473,7 +473,10 @@
);
// nor is it in localforage
- const walletsNow = await localforage.getItem('wallets');
+ const walletsNow = cashtabWalletsFromJSON(
+ await localforage.getItem('wallets'),
+ );
+
const expectedWalletsNow = [
...[walletWithXecAndTokens].concat(validSavedWallets),
];
diff --git a/cashtab/src/components/Etokens/CreateTokenForm.js b/cashtab/src/components/Etokens/CreateTokenForm.js
--- a/cashtab/src/components/Etokens/CreateTokenForm.js
+++ b/cashtab/src/components/Etokens/CreateTokenForm.js
@@ -463,7 +463,7 @@
// Get target outputs for an SLP v1 genesis tx
const targetOutputs = getSlpGenesisTargetOutput(
configObj,
- wallet.paths.find(pathInfo => pathInfo.path === 1899).address,
+ wallet.paths.get(1899).address,
);
const { response } = await sendXec(
chronik,
diff --git a/cashtab/src/components/Etokens/Etokens.js b/cashtab/src/components/Etokens/Etokens.js
--- a/cashtab/src/components/Etokens/Etokens.js
+++ b/cashtab/src/components/Etokens/Etokens.js
@@ -10,6 +10,7 @@
import TokenList from './TokenList';
import { getWalletState } from 'utils/cashMethods';
import appConfig from 'config/app';
+import { getUserLocale } from 'helpers';
const EtokensCtn = styled.div`
color: ${props => props.theme.contrast};
@@ -39,10 +40,11 @@
const Etokens = () => {
const ContextValue = React.useContext(WalletContext);
const { loading, cashtabState } = ContextValue;
- const { wallets } = cashtabState;
+ const { wallets, cashtabCache } = cashtabState;
const wallet = wallets.length > 0 ? wallets[0] : false;
const walletState = getWalletState(wallet);
const { tokens } = walletState;
+ const userLocale = getUserLocale(navigator);
return (
<>
{loading ? (
@@ -58,8 +60,12 @@
>
Create eToken
</CreateToken>
- {tokens && tokens.length > 0 ? (
- <TokenList wallet={wallet} tokens={tokens} />
+ {tokens && tokens.size > 0 ? (
+ <TokenList
+ tokens={tokens}
+ tokenCache={cashtabCache.tokens}
+ userLocale={userLocale}
+ />
) : (
<p>
Tokens sent to your {appConfig.tokenTicker}{' '}
diff --git a/cashtab/src/components/Etokens/TokenList.js b/cashtab/src/components/Etokens/TokenList.js
--- a/cashtab/src/components/Etokens/TokenList.js
+++ b/cashtab/src/components/Etokens/TokenList.js
@@ -6,30 +6,27 @@
import PropTypes from 'prop-types';
import TokenListItem from './TokenListItem';
import { Link } from 'react-router-dom';
-import { formatTokenBalance } from 'utils/formatting';
-import { BN } from 'slp-mdm';
+import { decimalizedTokenQtyToLocaleFormat } from 'utils/formatting';
-const TokenList = ({ tokens }) => {
- return (
- <div>
- {tokens.map(token => (
- <Link key={token.tokenId} to={`/send-token/${token.tokenId}`}>
- <TokenListItem
- ticker={token.info.tokenTicker}
- tokenId={token.tokenId}
- balance={formatTokenBalance(
- new BN(token.balance),
- token.info.decimals,
- )}
- />
- </Link>
- ))}
- </div>
- );
+const TokenList = ({ tokens, tokenCache, userLocale }) => {
+ return Array.from(tokens).map(keyValueArray => (
+ <Link key={keyValueArray[0]} to={`/send-token/${keyValueArray[0]}`}>
+ <TokenListItem
+ tokenId={keyValueArray[0]}
+ balance={decimalizedTokenQtyToLocaleFormat(
+ keyValueArray[1],
+ userLocale,
+ )}
+ cachedTokenInfo={tokenCache.get(keyValueArray[0])}
+ />
+ </Link>
+ ));
};
TokenList.propTypes = {
- tokens: PropTypes.array,
+ tokens: PropTypes.instanceOf(Map),
+ tokenCache: PropTypes.instanceOf(Map),
+ userLocale: PropTypes.string,
};
export default TokenList;
diff --git a/cashtab/src/components/Etokens/TokenListItem.js b/cashtab/src/components/Etokens/TokenListItem.js
--- a/cashtab/src/components/Etokens/TokenListItem.js
+++ b/cashtab/src/components/Etokens/TokenListItem.js
@@ -36,14 +36,23 @@
}
`;
-const TokenListItem = ({ ticker, balance, tokenId }) => {
+/**
+ * Display token ticker and balance as a table item
+ * All tokens should be cached when this screen is rendered
+ * But, in case it isn't for any reason, handle this case
+ */
+const TokenListItem = ({ tokenId, balance, cachedTokenInfo }) => {
return (
<Wrapper>
<TokenNameCtn>
<TokenIconWrapper>
<TokenIcon size={32} tokenId={tokenId} />
</TokenIconWrapper>
- <h4>{ticker}</h4>
+ <h4>
+ {typeof cachedTokenInfo !== 'undefined'
+ ? cachedTokenInfo.genesisInfo.tokenTicker
+ : 'UNCACHED'}
+ </h4>
</TokenNameCtn>
<h4>{balance}</h4>
@@ -55,6 +64,31 @@
ticker: PropTypes.string,
balance: PropTypes.string,
tokenId: PropTypes.string,
+ cachedTokenInfo: PropTypes.oneOfType([
+ undefined,
+ PropTypes.shape({
+ block: PropTypes.shape({
+ hash: PropTypes.string,
+ height: PropTypes.number,
+ timestamp: PropTypes.number,
+ }),
+ genesisInfo: PropTypes.shape({
+ decimals: PropTypes.number,
+ hash: PropTypes.string,
+ tokenName: PropTypes.string,
+ tokenTicker: PropTypes.string,
+ url: PropTypes.string,
+ }),
+ genesisMintBatons: PropTypes.number,
+ genesisOutputScripts: PropTypes.arrayOf(PropTypes.string),
+ timeFirstSeen: PropTypes.number,
+ tokenType: PropTypes.shape({
+ number: PropTypes.number,
+ protocol: PropTypes.string,
+ type: PropTypes.string,
+ }),
+ }),
+ ]),
};
export default TokenListItem;
diff --git a/cashtab/src/components/Home/Tx.js b/cashtab/src/components/Home/Tx.js
--- a/cashtab/src/components/Home/Tx.js
+++ b/cashtab/src/components/Home/Tx.js
@@ -424,6 +424,18 @@
const Tx = ({ data, fiatPrice, fiatCurrency, cashtabState }) => {
const { contactList, settings, cashtabCache } = cashtabState;
const { tokens } = cashtabCache;
+
+ // For now, we only parse tokenEntries[0]
+ let tokenId, cachedTokenInfo;
+ if (
+ data.parsed.isEtokenTx &&
+ Array.isArray(data.tokenEntries) &&
+ data.tokenEntries.length > 0
+ ) {
+ tokenId = data.parsed.tokenEntries[0].tokenId;
+ cachedTokenInfo = tokens.get(tokenId);
+ }
+
const [displayedMessage, setDisplayedMessage] = useState(false);
const handleShowMessage = () => {
setDisplayedMessage(!displayedMessage);
@@ -610,20 +622,18 @@
+{' '}
{data.parsed.etokenAmount.toString()}
&nbsp;
- {
- data
- .parsed
+ {typeof cachedTokenInfo !==
+ 'undefined' &&
+ cachedTokenInfo
.genesisInfo
- .tokenTicker
- }
+ .tokenTicker}
</TokenTxAmtGenesis>
<TokenName>
- {
- data
- .parsed
+ {typeof cachedTokenInfo !==
+ 'undefined' &&
+ cachedTokenInfo
.genesisInfo
- .tokenName
- }
+ .tokenName}
</TokenName>
</>
) : (
@@ -632,20 +642,18 @@
-{' '}
{data.parsed.etokenAmount.toString()}
&nbsp;
- {
- data
- .parsed
+ {typeof cachedTokenInfo !==
+ 'undefined' &&
+ cachedTokenInfo
.genesisInfo
- .tokenTicker
- }
+ .tokenTicker}
</TokenTxAmt>
<TokenName>
- {
- data
- .parsed
+ {typeof cachedTokenInfo !==
+ 'undefined' &&
+ cachedTokenInfo
.genesisInfo
- .tokenName
- }
+ .tokenName}
</TokenName>
</>
)}
@@ -656,20 +664,18 @@
+{' '}
{data.parsed.etokenAmount.toString()}
&nbsp;
- {
- data
- .parsed
+ {typeof cachedTokenInfo !==
+ 'undefined' &&
+ cachedTokenInfo
.genesisInfo
- .tokenTicker
- }
+ .tokenTicker}
</TokenTxAmtReceived>
<TokenName>
- {
- data
- .parsed
+ {typeof cachedTokenInfo !==
+ 'undefined' &&
+ cachedTokenInfo
.genesisInfo
- .tokenName
- }
+ .tokenName}
</TokenName>
</RightTextCtn>
)}
diff --git a/cashtab/src/components/Receive/Receive.js b/cashtab/src/components/Receive/Receive.js
--- a/cashtab/src/components/Receive/Receive.js
+++ b/cashtab/src/components/Receive/Receive.js
@@ -52,11 +52,7 @@
<QrCodeCtn data-testid="qr-code-ctn">
<QRCode
id="borderedQRCode"
- address={
- wallet.paths.find(
- pathInfo => pathInfo.path === 1899,
- ).address
- }
+ address={wallet.paths.get(1899).address}
size={getQrCodeWidth(width)}
logoSizePx={width > 500 ? 48 : 24}
/>
diff --git a/cashtab/src/components/Send/SendToken.js b/cashtab/src/components/Send/SendToken.js
--- a/cashtab/src/components/Send/SendToken.js
+++ b/cashtab/src/components/Send/SendToken.js
@@ -17,7 +17,6 @@
import { getWalletState } from 'utils/cashMethods';
import ApiError from 'components/Common/ApiError';
import { isValidEtokenBurnAmount, parseAddressInput } from 'validation';
-import { getTokenStats } from 'chronik';
import { formatDate } from 'utils/formatting';
import styled from 'styled-components';
import TokenIcon from 'components/Etokens/TokenIcon';
@@ -44,6 +43,7 @@
} from 'components/Common/Inputs';
import CopyToClipboard from 'components/Common/CopyToClipboard';
import { ThemedCopySolid } from 'components/Common/CustomIcons';
+import { decimalizedTokenQtyToLocaleFormat } from 'utils/formatting';
const TokenStatsTable = styled.div`
display: flex;
@@ -52,6 +52,7 @@
justify-content: center;
width: 100%;
color: ${props => props.theme.contrast};
+ margin-bottom: 12px;
`;
const TokenStatsRow = styled.div`
width: 100%;
@@ -76,9 +77,9 @@
const SendToken = () => {
let navigate = useNavigate();
- const { apiError, cashtabState, loading, chronik, chaintipBlockheight } =
+ const { apiError, cashtabState, chronik, chaintipBlockheight, loading } =
React.useContext(WalletContext);
- const { settings, wallets } = cashtabState;
+ const { settings, wallets, cashtabCache } = cashtabState;
const wallet = wallets.length > 0 ? wallets[0] : false;
const walletState = getWalletState(wallet);
const { tokens, balanceSats } = walletState;
@@ -86,9 +87,23 @@
const params = useParams();
const tokenId = params.tokenId;
- const token = tokens.find(token => token.tokenId === tokenId);
+ const tokenBalance = tokens.get(tokenId);
+ const cachedInfo =
+ typeof cashtabCache.tokens.get(tokenId) !== 'undefined'
+ ? cashtabCache.tokens.get(tokenId)
+ : {
+ genesisInfo: {
+ tokenName: 'UNCACHED',
+ tokenTicker: 'UNCACHED',
+ decimals: 0,
+ },
+ genesisSupply: 0,
+ genesisMintBatons: 0,
+ };
+
+ const { genesisInfo, genesisSupply, genesisMintBatons } = cachedInfo;
+ const { tokenName, tokenTicker, url, decimals } = genesisInfo;
- const [tokenStats, setTokenStats] = useState(null);
const [sendTokenAddressError, setSendTokenAddressError] = useState(false);
const [sendTokenAmountError, setSendTokenAmountError] = useState(false);
const [showConfirmBurnEtoken, setShowConfirmBurnEtoken] = useState(false);
@@ -112,7 +127,11 @@
const userLocale = getUserLocale(navigator);
useEffect(() => {
- if (typeof token === 'undefined' && loading === false) {
+ if (
+ loading === false &&
+ (typeof tokenBalance === 'undefined' ||
+ typeof cashtabCache.tokens.get(tokenId) === 'undefined')
+ ) {
// token can be undefined when the app is loading
// in practice, this only happens in integration tests or when the user navigates directly
// to send/tokenId screen, as cashtab locks UI while it loads
@@ -120,19 +139,8 @@
// In this case -- loading === true and token === undefined -- navigate to the home page
navigate('/');
}
- }, [loading, token]);
+ }, [loading, tokenBalance, cashtabCache]);
- // Fetch token stats if you do not have them and API did not return an error
- if (tokenStats === null) {
- getTokenStats(chronik, tokenId).then(
- result => {
- setTokenStats(result);
- },
- err => {
- console.log(`Error getting token stats: ${err}`);
- },
- );
- }
// Clears address and amount fields following a send token notification
const clearInputForms = () => {
setFormData({
@@ -178,7 +186,7 @@
wallet.state.slpUtxos,
tokenId,
amount,
- token.info.decimals,
+ decimals,
);
// Get targetOutputs for an slpv1 send tx
@@ -232,7 +240,7 @@
if (!isNaN(value)) {
const bigValue = new BN(value);
// Returns 1 if greater, -1 if less, 0 if the same, null if n/a
- isGreaterThanBalance = bigValue.comparedTo(new BN(token.balance));
+ isGreaterThanBalance = bigValue.comparedTo(tokenBalance);
}
// Validate value for > 0
@@ -240,11 +248,11 @@
error = 'Amount must be a number';
} else if (value <= 0) {
error = 'Amount must be greater than 0';
- } else if (token && token.balance && isGreaterThanBalance === 1) {
- error = `Amount cannot exceed your ${token.info.tokenTicker} balance of ${token.balance}`;
+ } else if (tokenBalance && isGreaterThanBalance === 1) {
+ error = `Amount cannot exceed your ${tokenTicker} balance of ${tokenBalance}`;
} else if (!isNaN(value) && value.toString().includes('.')) {
- if (value.toString().split('.')[1].length > token.info.decimals) {
- error = `This token only supports ${token.info.decimals} decimal places`;
+ if (value.toString().split('.')[1].length > decimals) {
+ error = `This token only supports ${decimals} decimal places`;
}
}
setSendTokenAmountError(error);
@@ -322,7 +330,7 @@
// Clear this error before updating field
setSendTokenAmountError(false);
try {
- let amount = token.balance;
+ let amount = tokenBalance;
setFormData({
...formData,
@@ -356,14 +364,11 @@
};
const handleEtokenBurnAmountChange = e => {
- console.log(`handleEtokenBurnAmountChange`);
const { name, value } = e.target;
- console.log(`name`, name);
- console.log(`value`, value);
let error = false;
- if (!isValidEtokenBurnAmount(new BN(value), token.balance)) {
- error = 'Burn amount must be between 1 and ' + token.balance;
+ if (!isValidEtokenBurnAmount(new BN(value), tokenBalance)) {
+ error = 'Burn amount must be between 1 and ' + tokenBalance;
}
setBurnTokenAmountError(error);
@@ -379,7 +384,7 @@
handleEtokenBurnAmountChange({
target: {
name: 'burnAmount',
- value: token.balance,
+ value: tokenBalance,
},
});
};
@@ -398,7 +403,7 @@
wallet.state.slpUtxos,
tokenId,
formData.burnAmount,
- token.info.decimals,
+ decimals,
);
// Get targetOutputs for an slpv1 burn tx
@@ -448,11 +453,11 @@
const handleBurnConfirmationInput = e => {
const { value } = e.target;
- if (value && value === `burn ${token.info.tokenTicker}`) {
+ if (value && value === `burn ${tokenTicker}`) {
setBurnConfirmationError(false);
} else {
setBurnConfirmationError(
- `Input must exactly match "burn ${token.info.tokenTicker}"`,
+ `Input must exactly match "burn ${tokenTicker}"`,
);
}
setConfirmationOfEtokenToBeBurnt(value);
@@ -466,188 +471,203 @@
return (
<>
- {isModalVisible && (
- <Modal
- title="Confirm Send"
- description={`Send ${formData.amount}${' '}
- ${token.info.tokenTicker} to ${formData.address}?`}
- handleOk={handleOk}
- handleCancel={handleCancel}
- showCancelButton
- >
- <p>
- {token && token.info && formData
- ? `Are you sure you want to send ${
- formData.amount
- }${' '}
- ${token.info.tokenTicker} to ${formData.address}?`
- : ''}
- </p>
- </Modal>
- )}
- {token && (
- <SidePaddingCtn>
- {/* eToken burn modal */}
- {showConfirmBurnEtoken && (
- <Modal
- title={`Confirm ${token.info.tokenTicker} burn`}
- description={`Burn ${formData.burnAmount} ${token.info.tokenTicker}?`}
- handleOk={burn}
- handleCancel={() => setShowConfirmBurnEtoken(false)}
- showCancelButton
- height={250}
- >
- <ModalInput
- placeholder={`Type "burn ${token.info.tokenTicker}" to confirm`}
- name="etokenToBeBurnt"
- value={confirmationOfEtokenToBeBurnt}
- error={burnConfirmationError}
- handleInput={handleBurnConfirmationInput}
- />
- </Modal>
- )}
- <BalanceHeaderToken
- balance={new BN(token.balance)}
- ticker={token.info.tokenTicker}
- tokenDecimals={token.info.decimals}
- />
- <TokenStatsTable
- title={`Token info for "${token.info.tokenName}"`}
- >
- <TokenStatsRow>
- <TokenStatsCol colSpan={2}>
- <CopyToClipboard data={token.tokenId} showToast>
- <TokenIcon size={128} tokenId={tokenId} />
- </CopyToClipboard>
- </TokenStatsCol>
- </TokenStatsRow>
- <TokenStatsRow>
- <TokenStatsCol>
- Token Id: {token.tokenId.slice(0, 3)}...
- {token.tokenId.slice(-3)}
- </TokenStatsCol>
- <TokenStatsCol>
- <CopyToClipboard data={token.tokenId} showToast>
- <ThemedCopySolid />
- </CopyToClipboard>
- </TokenStatsCol>
- </TokenStatsRow>
- <TokenStatsRow>
- <TokenStatsCol>
- {token.info.decimals} decimal places
- </TokenStatsCol>
- </TokenStatsRow>
-
- {tokenStats && (
- <>
- <TokenStatsRow>
- {tokenStats.genesisInfo.url}
- </TokenStatsRow>
- <TokenStatsRow>
- Minted{' '}
- {tokenStats.block &&
- tokenStats.block.timestamp !== null
- ? formatDate(
- tokenStats.block.timestamp,
- navigator.language,
- )
- : 'Just now (Genesis tx confirming)'}
- </TokenStatsRow>
- </>
+ {tokenBalance &&
+ typeof cashtabCache.tokens.get(tokenId) !== 'undefined' && (
+ <SidePaddingCtn>
+ {isModalVisible && (
+ <Modal
+ title="Confirm Send"
+ description={`Send ${formData.amount}${' '}
+ ${tokenTicker} to ${formData.address}?`}
+ handleOk={handleOk}
+ handleCancel={handleCancel}
+ showCancelButton
+ >
+ <p>
+ Are you sure you want to send{' '}
+ {formData.amount} {tokenTicker} to{' '}
+ {formData.address}?
+ </p>
+ </Modal>
)}
- </TokenStatsTable>
- <InputWithScanner
- placeholder={
- aliasSettings.aliasEnabled
- ? `Address or Alias`
- : `Address`
- }
- name="address"
- value={formData.address}
- handleInput={handleTokenAddressChange}
- error={sendTokenAddressError}
- loadWithScannerOpen={openWithScanner}
- />
- <AliasAddressPreviewLabel>
- <TxLink
- key={aliasInputAddress}
- href={`${explorer.blockExplorerUrl}/address/${aliasInputAddress}`}
- target="_blank"
- rel="noreferrer"
- >
- {aliasInputAddress &&
- `${aliasInputAddress.slice(
- 0,
- 10,
- )}...${aliasInputAddress.slice(-5)}`}
- </TxLink>
- </AliasAddressPreviewLabel>
- <br />
- <SendTokenInput
- name="amount"
- value={formData.amount}
- error={sendTokenAmountError}
- placeholder="Amount"
- decimals={token.info.decimals}
- handleInput={handleSlpAmountChange}
- handleOnMax={onMax}
- />
-
- <SecondaryButton
- style={{ marginTop: '24px' }}
- disabled={
- apiError ||
- sendTokenAmountError ||
- sendTokenAddressError
- }
- onClick={() => checkForConfirmationBeforeSendEtoken()}
- >
- Send {token.info.tokenName}
- </SecondaryButton>
-
- {apiError && <ApiError />}
-
- <TokenStatsTable
- title={`Token info for "${token.info.tokenName}"`}
- >
- <TokenStatsRow>
- <Link
- style={{ width: '100%' }}
- to="/airdrop"
- state={{
- airdropEtokenId: token.tokenId,
- }}
+ {showConfirmBurnEtoken && (
+ <Modal
+ title={`Confirm ${tokenTicker} burn`}
+ description={`Burn ${formData.burnAmount} ${tokenTicker}?`}
+ handleOk={burn}
+ handleCancel={() =>
+ setShowConfirmBurnEtoken(false)
+ }
+ showCancelButton
+ height={250}
>
- <PrimaryButton style={{ marginTop: '12px' }}>
- Airdrop
- </PrimaryButton>
- </Link>
- </TokenStatsRow>
- <TokenStatsRow>
- <InputFlex>
- <SendTokenInput
- name="burnAmount"
- value={formData.burnAmount}
- error={burnTokenAmountError}
- placeholder="Burn Amount"
- decimals={token.info.decimals}
- handleInput={handleEtokenBurnAmountChange}
- handleOnMax={onMaxBurn}
+ <ModalInput
+ placeholder={`Type "burn ${tokenTicker}" to confirm`}
+ name="etokenToBeBurnt"
+ value={confirmationOfEtokenToBeBurnt}
+ error={burnConfirmationError}
+ handleInput={handleBurnConfirmationInput}
/>
+ </Modal>
+ )}
+ <BalanceHeaderToken
+ balance={new BN(tokenBalance)}
+ ticker={tokenTicker}
+ tokenDecimals={decimals}
+ />
+ <TokenStatsTable
+ title={`Token info for "${tokenName}"`}
+ >
+ <TokenStatsRow>
+ <TokenStatsCol colSpan={2}>
+ <CopyToClipboard data={tokenId} showToast>
+ <TokenIcon
+ size={128}
+ tokenId={tokenId}
+ />
+ </CopyToClipboard>
+ </TokenStatsCol>
+ </TokenStatsRow>
+ <TokenStatsRow>
+ <TokenStatsCol>
+ Token Id: {tokenId.slice(0, 3)}...
+ {tokenId.slice(-3)}
+ </TokenStatsCol>
+ <TokenStatsCol>
+ <CopyToClipboard data={tokenId} showToast>
+ <ThemedCopySolid />
+ </CopyToClipboard>
+ </TokenStatsCol>
+ </TokenStatsRow>
+ <TokenStatsRow>
+ <TokenStatsCol>
+ {decimals} decimal places
+ </TokenStatsCol>
+ </TokenStatsRow>
+ <TokenStatsRow>{url}</TokenStatsRow>
+ <TokenStatsRow>
+ Minted{' '}
+ {typeof cachedInfo.block !== 'undefined'
+ ? formatDate(
+ cachedInfo.block.timestamp,
+ navigator.language,
+ )
+ : formatDate(
+ cachedInfo.timeFirstSeen,
+ navigator.language,
+ )}
+ </TokenStatsRow>
+ <TokenStatsRow>
+ Genesis Supply:{' '}
+ {decimalizedTokenQtyToLocaleFormat(
+ genesisSupply,
+ userLocale,
+ )}
+ </TokenStatsRow>
+ <TokenStatsRow>
+ {genesisMintBatons === 0
+ ? 'Fixed Supply'
+ : 'Variable Supply'}
+ </TokenStatsRow>
+ </TokenStatsTable>
+ <InputWithScanner
+ placeholder={
+ aliasSettings.aliasEnabled
+ ? `Address or Alias`
+ : `Address`
+ }
+ name="address"
+ value={formData.address}
+ handleInput={handleTokenAddressChange}
+ error={sendTokenAddressError}
+ loadWithScannerOpen={openWithScanner}
+ />
+ <AliasAddressPreviewLabel>
+ <TxLink
+ key={aliasInputAddress}
+ href={`${explorer.blockExplorerUrl}/address/${aliasInputAddress}`}
+ target="_blank"
+ rel="noreferrer"
+ >
+ {aliasInputAddress &&
+ `${aliasInputAddress.slice(
+ 0,
+ 10,
+ )}...${aliasInputAddress.slice(-5)}`}
+ </TxLink>
+ </AliasAddressPreviewLabel>
+ <br />
+ <SendTokenInput
+ name="amount"
+ value={formData.amount}
+ error={sendTokenAmountError}
+ placeholder="Amount"
+ decimals={decimals}
+ handleInput={handleSlpAmountChange}
+ handleOnMax={onMax}
+ />
+
+ <SecondaryButton
+ style={{ marginTop: '24px' }}
+ disabled={
+ apiError ||
+ sendTokenAmountError ||
+ sendTokenAddressError
+ }
+ onClick={() =>
+ checkForConfirmationBeforeSendEtoken()
+ }
+ >
+ Send {tokenName}
+ </SecondaryButton>
- <Button
- type="primary"
- onClick={handleBurnAmountInput}
- danger
+ {apiError && <ApiError />}
+
+ <TokenStatsTable
+ title={`Token info for "${tokenName}"`}
+ >
+ <TokenStatsRow>
+ <Link
+ style={{ width: '100%' }}
+ to="/airdrop"
+ state={{
+ airdropEtokenId: tokenId,
+ }}
>
- Burn&nbsp;
- {token.info.tokenTicker}
- </Button>
- </InputFlex>
- </TokenStatsRow>
- </TokenStatsTable>
- </SidePaddingCtn>
- )}
+ <PrimaryButton
+ style={{ marginTop: '12px' }}
+ >
+ Airdrop
+ </PrimaryButton>
+ </Link>
+ </TokenStatsRow>
+ <TokenStatsRow>
+ <InputFlex>
+ <SendTokenInput
+ name="burnAmount"
+ value={formData.burnAmount}
+ error={burnTokenAmountError}
+ placeholder="Burn Amount"
+ decimals={decimals}
+ handleInput={
+ handleEtokenBurnAmountChange
+ }
+ handleOnMax={onMaxBurn}
+ />
+
+ <Button
+ type="primary"
+ onClick={handleBurnAmountInput}
+ danger
+ >
+ Burn&nbsp;
+ {tokenTicker}
+ </Button>
+ </InputFlex>
+ </TokenStatsRow>
+ </TokenStatsTable>
+ </SidePaddingCtn>
+ )}
</>
);
};
diff --git a/cashtab/src/components/Send/__tests__/SendToken.test.js b/cashtab/src/components/Send/__tests__/SendToken.test.js
--- a/cashtab/src/components/Send/__tests__/SendToken.test.js
+++ b/cashtab/src/components/Send/__tests__/SendToken.test.js
@@ -52,7 +52,8 @@
'3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109';
const SEND_TOKEN_DECIMALS = 0;
const SEND_TOKEN_TICKER = 'BEAR';
-const SEND_TOKEN_BALANCE = walletWithXecAndTokens.state.tokens[0].balance;
+const SEND_TOKEN_BALANCE =
+ walletWithXecAndTokens.state.tokens.get(SEND_TOKEN_TOKENID);
// See src/validation, ref parseAddressInput
// See SendToken for some modified errors (SendToken does not support bip21)
diff --git a/cashtab/src/components/SignVerifyMsg/SignVerifyMsg.js b/cashtab/src/components/SignVerifyMsg/SignVerifyMsg.js
--- a/cashtab/src/components/SignVerifyMsg/SignVerifyMsg.js
+++ b/cashtab/src/components/SignVerifyMsg/SignVerifyMsg.js
@@ -88,7 +88,7 @@
try {
// First, get required params
const keyPair = utxolib.ECPair.fromWIF(
- wallet.paths.find(pathInfo => pathInfo.path === 1899).wif,
+ wallet.paths.get(1899).wif,
utxolib.networks.ecash,
);
// Reference https://github.com/Permissionless-Software-Foundation/bch-js/blob/master/src/bitcoincash.js#L161
@@ -232,18 +232,12 @@
name="signMessageAddress"
disabled={true}
value={
- wallet.paths.find(
- pathInfo =>
- pathInfo.path === 1899,
- ).address
+ wallet.paths.get(1899).address
}
/>
<CopyToClipboard
data={
- wallet.paths.find(
- pathInfo =>
- pathInfo.path === 1899,
- ).address
+ wallet.paths.get(1899).address
}
showToast
>
diff --git a/cashtab/src/components/__tests__/App.test.js b/cashtab/src/components/__tests__/App.test.js
--- a/cashtab/src/components/__tests__/App.test.js
+++ b/cashtab/src/components/__tests__/App.test.js
@@ -11,12 +11,15 @@
import {
walletWithXecAndTokens,
walletWithXecAndTokens_pre_2_1_0,
+ walletWithXecAndTokens_pre_2_9_0,
freshWalletWithOneIncomingCashtabMsg,
requiredUtxoThisToken,
easterEggTokenChronikTokenDetails,
- vipTokenChronikTokenDetails,
+ vipTokenChronikTokenMocks,
validSavedWallets_pre_2_1_0,
+ validSavedWallets_pre_2_9_0,
validSavedWallets,
+ mockCacheWalletWithXecAndTokens,
} from 'components/fixtures/mocks';
import 'fake-indexeddb/auto';
import localforage from 'localforage';
@@ -31,9 +34,15 @@
import CashtabTestWrapper from 'components/fixtures/CashtabTestWrapper';
import { explorer } from 'config/explorer';
import { legacyMockTokenInfoById } from 'chronik/fixtures/chronikUtxos';
-import { cashtabCacheToJSON } from 'helpers';
+import {
+ cashtabCacheToJSON,
+ storedCashtabCacheToMap,
+ cashtabWalletFromJSON,
+ cashtabWalletsFromJSON,
+} from 'helpers';
import { createCashtabWallet } from 'wallet';
import { isValidCashtabWallet } from 'validation';
+import CashtabCache from 'config/CashtabCache';
// https://stackoverflow.com/questions/39830580/jest-test-fails-typeerror-window-matchmedia-is-not-a-function
Object.defineProperty(window, 'matchMedia', {
@@ -606,7 +615,11 @@
// Make sure the app can get this token's genesis info by calling a mock
mockedChronik.setMock('token', {
input: appConfig.vipSettingsTokenId,
- output: vipTokenChronikTokenDetails,
+ output: vipTokenChronikTokenMocks.token,
+ });
+ mockedChronik.setMock('tx', {
+ input: appConfig.vipSettingsTokenId,
+ output: vipTokenChronikTokenMocks.tx,
});
// Can verify in Electrum that this tx is sent at 1.0 sat/byte
@@ -737,15 +750,13 @@
},
};
// Modify walletWithXecAndTokens to have the required token for this feature
- let walletWithEasterEggToken = JSON.parse(
- JSON.stringify(walletWithXecAndTokens),
- );
- walletWithEasterEggToken = {
- ...walletWithEasterEggToken,
+
+ const walletWithEasterEggToken = {
+ ...walletWithXecAndTokens,
state: {
- ...walletWithEasterEggToken.state,
+ ...walletWithXecAndTokens.state,
slpUtxos: [
- ...walletWithEasterEggToken.state.slpUtxos,
+ ...walletWithXecAndTokens.state.slpUtxos,
requiredEasterEggUtxo,
],
},
@@ -767,7 +778,7 @@
// We see the easter egg
expect(await screen.findByAltText('tabcash')).toBeInTheDocument();
});
- it('If Cashtab starts with 1.5.* cashtabCache, it is wiped and migrated to 1.6.* cashtabCache', async () => {
+ it('If Cashtab starts with 1.5.* cashtabCache, it is wiped and migrated to 2.9.0 cashtabCache', async () => {
// Note: this is what will happen for all Cashtab users when this diff lands
const mockedChronik =
await initializeCashtabStateAtLegacyWalletKeysForTests(
@@ -780,31 +791,20 @@
render(<CashtabTestWrapper chronik={mockedChronik} />);
- const expectedCashtabCacheTokens = new Map();
-
- // Tokens from wallet utxos will be added to cache on app load
- expectedCashtabCacheTokens.set(
- '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
- {
- decimals: 0,
- success: true,
- hash: '',
- url: 'https://cashtab.com/',
- tokenName: 'BearNip',
- tokenTicker: 'BEAR',
- },
- );
+ const expectedCashtabCacheTokens = new CashtabCache([
+ [
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ mockCacheWalletWithXecAndTokens,
+ ],
+ ]);
- // Result will be stored as a keyvalue array and must be converted to a map
- // We do the reverse to get the expected storage value
- const expectedStoredCashtabCache = cashtabCacheToJSON({
- tokens: expectedCashtabCacheTokens,
- });
// Confirm cashtabCache in localforage matches expected result
await waitFor(async () =>
- expect(await localforage.getItem('cashtabCache')).toEqual(
- expectedStoredCashtabCache,
- ),
+ expect(
+ storedCashtabCacheToMap(
+ await localforage.getItem('cashtabCache'),
+ ),
+ ).toEqual(expectedCashtabCacheTokens),
);
});
it('A new user can import a mnemonic', async () => {
@@ -874,18 +874,19 @@
// The imported wallet is in localforage
const wallets = await localforage.getItem('wallets');
- const importedWallet = wallets[0];
+ const importedWallet = cashtabWalletFromJSON(wallets[0]);
// The imported wallet matches our expected mock except for name, which is autoset on import
// The imported wallet is not imported with legacy paths (145 and 245)
- const expectedPathInfo = walletWithXecAndTokens.paths.find(
- pathInfo => pathInfo.path === 1899,
- );
- expect(importedWallet).toEqual({
+ const expectedPathInfo = walletWithXecAndTokens.paths.get(1899);
+ // We expect the wallet to be walletWithXecAndTokens, except new name and no legacy paths
+ const expectedWallet = {
...walletWithXecAndTokens,
name: 'qqa9l',
- paths: [expectedPathInfo],
- });
+ paths: new Map([[1899, expectedPathInfo]]),
+ };
+
+ expect(importedWallet).toEqual(expectedWallet);
// Apart from state, which is blank from createCashtabWallet,
// the imported wallet matches what we get from createCashtabWallet
@@ -913,7 +914,7 @@
// Check wallet in localforage
const wallets = await localforage.getItem('wallets');
- const migratedWallet = wallets[0];
+ const migratedWallet = cashtabWalletFromJSON(wallets[0]);
// The wallet has been migrated
expect(migratedWallet).toEqual(walletWithXecAndTokens);
@@ -943,7 +944,9 @@
);
// Check wallets
- const walletsAfterLoad = await localforage.getItem('wallets');
+ const walletsAfterLoad = cashtabWalletsFromJSON(
+ await localforage.getItem('wallets'),
+ );
const savedWallets = walletsAfterLoad.slice(1);
@@ -974,7 +977,9 @@
);
// Check wallets
- const walletsAfterLoad = await localforage.getItem('wallets');
+ const walletsAfterLoad = cashtabWalletsFromJSON(
+ await localforage.getItem('wallets'),
+ );
const savedWallets = walletsAfterLoad.slice(1);
@@ -983,7 +988,7 @@
expect(savedWallets).toEqual(validSavedWallets);
});
});
- it('Migrating (version >= 1.6.0 and < 2.1.0): A user with multiple invalid wallets in savedWallets has them migrated', async () => {
+ it('Migrating (version >= 1.6.0 and < 2.1.0): A user with multiple invalid wallets stored at wallets key has them migrated', async () => {
// Create a savedWallets array with 4 valid wallets and 1 invalid wallet
const mixedValidWallets = [
walletWithXecAndTokens,
@@ -1009,7 +1014,9 @@
);
// Check wallets
- const walletsAfterLoad = await localforage.getItem('wallets');
+ const walletsAfterLoad = cashtabWalletsFromJSON(
+ await localforage.getItem('wallets'),
+ );
const savedWallets = walletsAfterLoad.slice(1);
@@ -1033,12 +1040,12 @@
// Check wallet in localforage
const wallets = await localforage.getItem('wallets');
- const migratedWallet = wallets[0];
+ const migratedWallet = cashtabWalletFromJSON(wallets[0]);
// The wallet has been migrated
expect(migratedWallet).toEqual(walletWithXecAndTokens);
});
- it('A user with all valid wallets in savedWallets does not have any savedWallets migrated', async () => {
+ it('A user with all valid wallets stored at wallets key does not have any wallets migrated', async () => {
const mockedChronik = await initializeCashtabStateForTests(
[walletWithXecAndTokens, ...validSavedWallets],
localforage,
@@ -1051,10 +1058,143 @@
'9,513.12 XEC',
);
+ const walletsAfterLoad = cashtabWalletsFromJSON(
+ await localforage.getItem('wallets'),
+ );
+
// The savedWallets array stored at the savedWallets key is unchanged
- expect(await localforage.getItem('wallets')).toEqual([
+ expect(walletsAfterLoad).toEqual([
walletWithXecAndTokens,
...validSavedWallets,
]);
});
+ it('Migrating (version < 2.9.0): A user with multiple invalid wallets stored at wallets key has them migrated', async () => {
+ // Create a savedWallets array with 4 valid wallets and 1 invalid wallet
+ const mixedValidWallets = [
+ walletWithXecAndTokens,
+ ...validSavedWallets_pre_2_9_0.slice(0, 3),
+ ...validSavedWallets.slice(3),
+ ];
+
+ // The wallets at indices 1, 2, and 3 are invalid
+ expect(isValidCashtabWallet(mixedValidWallets[1])).toBe(false);
+ expect(isValidCashtabWallet(mixedValidWallets[2])).toBe(false);
+ expect(isValidCashtabWallet(mixedValidWallets[3])).toBe(false);
+
+ const mockedChronik = await initializeCashtabStateForTests(
+ mixedValidWallets,
+ localforage,
+ );
+
+ render(<CashtabTestWrapper chronik={mockedChronik} />);
+
+ // Wait balance to be rendered correctly so we know Cashtab has loaded the wallet
+ expect(await screen.findByTestId('balance-xec')).toHaveTextContent(
+ '9,513.12 XEC',
+ );
+
+ // Check wallets
+ const walletsAfterLoad = cashtabWalletsFromJSON(
+ await localforage.getItem('wallets'),
+ );
+
+ const savedWallets = walletsAfterLoad.slice(1);
+
+ // We expect savedWallets in localforage to have been migrated
+ await waitFor(async () => {
+ expect(savedWallets).toEqual(validSavedWallets);
+ });
+ });
+ it('Migrating (version < 2.9.0): A user with an invalid Cashtab wallet as the active wallet is migrated on startup', async () => {
+ const mockedChronik = await initializeCashtabStateForTests(
+ walletWithXecAndTokens_pre_2_9_0,
+ localforage,
+ );
+
+ render(<CashtabTestWrapper chronik={mockedChronik} />);
+
+ // Wait balance to be rendered correctly so we know Cashtab has loaded the wallet
+ expect(await screen.findByTestId('balance-xec')).toHaveTextContent(
+ '9,513.12 XEC',
+ );
+
+ // Check wallet in localforage
+ const wallets = await localforage.getItem('wallets');
+ const migratedWallet = cashtabWalletFromJSON(wallets[0]);
+
+ // The wallet has been migrated
+ expect(migratedWallet).toEqual(walletWithXecAndTokens);
+ });
+ it('If Cashtab starts with < 2.9.0 cashtabCache, it is wiped and migrated to 2.9.0 cashtabCache', async () => {
+ // Note: this is what will happen for all Cashtab users when this diff lands
+ const mockedChronik = await initializeCashtabStateForTests(
+ walletWithXecAndTokens,
+ localforage,
+ );
+
+ // Mock cashtabCache at > 1.5.0 and < 2.9.0
+ const pre_2_9_0_tokens_cache = new Map();
+
+ // Tokens from wallet utxos will be added to cache on app load
+ pre_2_9_0_tokens_cache.set(
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ {
+ decimals: 0,
+ success: true,
+ hash: '',
+ url: 'https://cashtab.com/',
+ tokenName: 'BearNip',
+ tokenTicker: 'BEAR',
+ },
+ );
+
+ // Result will be stored as a keyvalue array and must be converted to a map
+ // We do the reverse to get the expected storage value
+ const expectedStoredCashtabCache = cashtabCacheToJSON({
+ tokens: pre_2_9_0_tokens_cache,
+ });
+ await localforage.setItem('cashtabCache', expectedStoredCashtabCache);
+
+ render(<CashtabTestWrapper chronik={mockedChronik} />);
+
+ // Confirm cashtabCache has been migrated to post-2.9.0 format
+ await waitFor(async () =>
+ expect(
+ storedCashtabCacheToMap(
+ await localforage.getItem('cashtabCache'),
+ ),
+ ).toEqual(
+ new CashtabCache([
+ [
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ {
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ genesisInfo: {
+ tokenTicker: 'BEAR',
+ tokenName: 'BearNip',
+ url: 'https://cashtab.com/',
+ decimals: 0,
+ hash: '',
+ },
+ timeFirstSeen: 0,
+ genesisSupply: '4444',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ block: {
+ height: 782665,
+ hash: '00000000000000001239831f90580c859ec174316e91961cf0e8cde57c0d3acb',
+ timestamp: 1678408305,
+ },
+ },
+ ],
+ ]),
+ ),
+ );
+ });
});
diff --git a/cashtab/src/components/fixtures/__tests__/index.test.js b/cashtab/src/components/fixtures/__tests__/index.test.js
--- a/cashtab/src/components/fixtures/__tests__/index.test.js
+++ b/cashtab/src/components/fixtures/__tests__/index.test.js
@@ -13,7 +13,7 @@
import { chronik as chronikConfig } from 'config/chronik';
import { CashtabSettings } from 'config/cashtabSettings';
import CashtabCache from 'config/CashtabCache';
-import { cashtabCacheToJSON } from 'helpers';
+import { cashtabCacheToJSON, cashtabWalletsFromJSON } from 'helpers';
describe('Correctly prepares Cashtab mocked chronik client and localforage environment for Cashtab pre 1.7.* for unit tests', () => {
afterEach(async () => {
@@ -51,7 +51,6 @@
);
const CASHTAB_TESTS_TIPHEIGHT = 800000;
- const CASHTAB_ADDRESS_TYPE = 'p2pkh';
// We can get the chaintip
expect(await mockChronikClient.blockchainInfo()).toEqual({
@@ -61,7 +60,7 @@
// Path1899 utxos as expected
expect(
await mockChronikClient
- .script(CASHTAB_ADDRESS_TYPE, wallet.Path1899.hash160)
+ .address(wallet.Path1899.cashAddress)
.utxos(),
).toEqual({
outputScript: `76a914${wallet.Path1899.hash160}88ac`,
@@ -70,7 +69,7 @@
// Path145 utxos empty
expect(
await mockChronikClient
- .script(CASHTAB_ADDRESS_TYPE, wallet.Path145.hash160)
+ .address(wallet.Path145.cashAddress)
.utxos(),
).toEqual({
outputScript: `76a914${wallet.Path145.hash160}88ac`,
@@ -80,7 +79,7 @@
// Path245 utxos empty
expect(
await mockChronikClient
- .script(CASHTAB_ADDRESS_TYPE, wallet.Path245.hash160)
+ .address(wallet.Path245.cashAddress)
.utxos(),
).toEqual({
outputScript: `76a914${wallet.Path245.hash160}88ac`,
@@ -90,13 +89,13 @@
// Path1899 history
expect(
await mockChronikClient
- .script(CASHTAB_ADDRESS_TYPE, wallet.Path1899.hash160)
+ .address(wallet.Path1899.cashAddress)
.history(0, chronikConfig.txHistoryCount),
).toEqual({ numPages: 1, txs: wallet.state.parsedTxHistory });
// Path145 history empty
expect(
await mockChronikClient
- .script(CASHTAB_ADDRESS_TYPE, wallet.Path145.hash160)
+ .address(wallet.Path145.cashAddress)
.history(0, chronikConfig.txHistoryCount),
).toEqual({
numPages: 0,
@@ -106,7 +105,7 @@
// Path245 history empty
expect(
await mockChronikClient
- .script(CASHTAB_ADDRESS_TYPE, wallet.Path245.hash160)
+ .address(wallet.Path245.cashAddress)
.history(0, chronikConfig.txHistoryCount),
).toEqual({
numPages: 0,
@@ -127,35 +126,35 @@
await expect(
apiErrorChronikClient
- .script(CASHTAB_ADDRESS_TYPE, wallet.Path1899.hash160)
+ .address(wallet.Path1899.cashAddress)
.utxos(),
).rejects.toThrow('Error fetching utxos');
await expect(
apiErrorChronikClient
- .script(CASHTAB_ADDRESS_TYPE, wallet.Path145.hash160)
+ .address(wallet.Path145.cashAddress)
.utxos(),
).rejects.toThrow('Error fetching utxos');
await expect(
apiErrorChronikClient
- .script(CASHTAB_ADDRESS_TYPE, wallet.Path245.hash160)
+ .address(wallet.Path245.cashAddress)
.utxos(),
).rejects.toThrow('Error fetching utxos');
await expect(
apiErrorChronikClient
- .script(CASHTAB_ADDRESS_TYPE, wallet.Path1899.hash160)
+ .address(wallet.Path1899.cashAddress)
.history(0, chronikConfig.txHistoryCount),
).rejects.toThrow('Error fetching history');
await expect(
apiErrorChronikClient
- .script(CASHTAB_ADDRESS_TYPE, wallet.Path145.hash160)
+ .address(wallet.Path145.cashAddress)
.history(0, chronikConfig.txHistoryCount),
).rejects.toThrow('Error fetching history');
await expect(
apiErrorChronikClient
- .script(CASHTAB_ADDRESS_TYPE, wallet.Path245.hash160)
+ .address(wallet.Path245.cashAddress)
.history(0, chronikConfig.txHistoryCount),
).rejects.toThrow('Error fetching history');
@@ -207,7 +206,6 @@
);
const CASHTAB_TESTS_TIPHEIGHT = 800000;
- const CASHTAB_ADDRESS_TYPE = 'p2pkh';
// We can get the chaintip
expect(await mockChronikClient.blockchainInfo()).toEqual({
@@ -216,16 +214,16 @@
// All wallets have mocks ready
for (const wallet of wallets) {
- for (const path of wallet.paths) {
- if (path.path === 1899) {
+ wallet.paths.forEach(async (pathInfo, path) => {
+ if (path === 1899) {
// OK to ignore because we test if/else
// eslint-disable-next-line jest/no-conditional-expect
expect(
await mockChronikClient
- .script(CASHTAB_ADDRESS_TYPE, path.hash)
+ .address(pathInfo.address)
.utxos(),
).toEqual({
- outputScript: `76a914${path.hash}88ac`,
+ outputScript: `76a914${pathInfo.hash}88ac`,
utxos: wallet.state.nonSlpUtxos.concat(
wallet.state.slpUtxos,
),
@@ -235,7 +233,7 @@
expect(
(
await mockChronikClient
- .script(CASHTAB_ADDRESS_TYPE, path.hash)
+ .address(pathInfo.address)
.history(0, chronikConfig.txHistoryCount)
).txs,
).toEqual(wallet.state.parsedTxHistory);
@@ -245,10 +243,10 @@
// eslint-disable-next-line jest/no-conditional-expect
expect(
await mockChronikClient
- .script(CASHTAB_ADDRESS_TYPE, path.hash)
+ .address(pathInfo.address)
.utxos(),
).toEqual({
- outputScript: `76a914${path.hash}88ac`,
+ outputScript: `76a914${pathInfo.hash}88ac`,
utxos: [],
});
// history
@@ -256,12 +254,12 @@
expect(
(
await mockChronikClient
- .script(CASHTAB_ADDRESS_TYPE, path.hash)
+ .address(pathInfo.address)
.history(0, chronikConfig.txHistoryCount)
).txs,
).toEqual([]);
}
- }
+ });
// Next, initialize with API error
const apiErrorChronikClient =
@@ -276,22 +274,23 @@
apiErrorChronikClient.blockchainInfo(),
).rejects.toThrow('Error fetching blockchainInfo');
- for (const path of wallet.paths) {
+ wallet.paths.forEach(async pathInfo => {
await expect(
- apiErrorChronikClient
- .script(CASHTAB_ADDRESS_TYPE, path.hash)
- .utxos(),
+ apiErrorChronikClient.address(pathInfo.address).utxos(),
).rejects.toThrow('Error fetching utxos');
await expect(
apiErrorChronikClient
- .script(CASHTAB_ADDRESS_TYPE, path.hash)
+ .address(pathInfo.address)
.history(0, chronikConfig.txHistoryCount),
).rejects.toThrow('Error fetching history');
- }
+ });
}
// Expect localforage wallet and defaults
- expect(await localforage.getItem('wallets')).toEqual(wallets);
+ const storedWallets = cashtabWalletsFromJSON(
+ await localforage.getItem('wallets'),
+ );
+ expect(storedWallets).toEqual(wallets);
// Note: we do not necessarily expect cashtabCache to be set, depends on wallet content
// Note: settings would only be set if changed from defaults
diff --git a/cashtab/src/components/fixtures/helpers.js b/cashtab/src/components/fixtures/helpers.js
--- a/cashtab/src/components/fixtures/helpers.js
+++ b/cashtab/src/components/fixtures/helpers.js
@@ -5,7 +5,7 @@
import { MockChronikClient } from '../../../../modules/mock-chronik-client';
import { CashtabSettings } from 'config/cashtabSettings';
import CashtabCache from 'config/CashtabCache';
-import { cashtabCacheToJSON } from 'helpers';
+import { cashtabCacheToJSON, cashtabWalletToJSON } from 'helpers';
/**
* Get expected mock values for chronik client for a given mock wallet
@@ -35,7 +35,27 @@
wallets = Array.isArray(wallets) ? wallets : [wallets];
// Set wallets in localforage
- await localforage.setItem('wallets', wallets);
+
+ // If wallet is post-2.9.0, make sure the JSON is in localforage and not the actual wallet
+ let localforageWallets = [];
+ for (const wallet of wallets) {
+ if (
+ // Pre 2.1.0 wallet
+ 'Path145' in wallet ||
+ // Pre 2.9.0 wallet
+ (Array.isArray(wallet.paths) &&
+ wallet.paths.length > 0 &&
+ typeof wallet.paths[0].path !== 'undefined')
+ ) {
+ // Pre-2.9.0 wallet, expected to be in localforage as-is
+ localforageWallets.push(wallet);
+ } else {
+ // Post-2.9.0 wallet, expected to be in localforage as JSON
+ localforageWallets.push(cashtabWalletToJSON(wallet));
+ }
+ }
+
+ await localforage.setItem('wallets', localforageWallets);
// All other localforage items will be unset unless the user has customized them
// Cashtab will use defaults
@@ -50,6 +70,53 @@
return chronikClient;
};
+/**
+ * Get expected mock values for chronik client for a given mock wallet created before Cashtab 2.9.0
+ * Used to support integration testing in Cashtab
+ * Default methods may be overwritten in individual unit tests to test special conditions
+ * @param {array | object | boolean} wallets Array of wallets stored in localforage.
+ * If object, convert to array of length 1.
+ * False if user has not yet created a wallet.
+ * @param {object} localforage the localforage instance used in your test
+ * @param {boolean} apiError Default false. If true, return a mockedChronik that throws errors.
+ * @returns {object} mockChronikClient, a mock chronik client instance prepopulated for expected Cashtab API calls
+ */
+export const initializeCashtabStateAtPre2_9_0ForTests = async (
+ wallets,
+ localforage,
+ apiError = false,
+) => {
+ // Mock successful utxos calls in chronik
+ const chronikClient = new MockChronikClient();
+
+ if (wallets === false) {
+ // No info to give to chronik, do not populate mocks
+ return chronikClient;
+ // We do not expect anything in localforage for this case
+ }
+
+ wallets = Array.isArray(wallets) ? wallets : [wallets];
+
+ // Set wallets in localforage
+ await localforage.setItem('wallets', wallets);
+
+ // All other localforage items will be unset unless the user has customized them
+ // Cashtab will use defaults
+ // localforage may be modified in individual test cases to test cases of user with
+ // non-default settings, cashtabCache, or contactList
+
+ // Mock returns for chronik calls expected in useWallet's update routine for all wallets
+ for (const wallet of wallets) {
+ prepareMockedChronikCallsForPre_2_9_0Wallet(
+ chronikClient,
+ wallet,
+ apiError,
+ );
+ }
+
+ return chronikClient;
+};
+
/**
* Get expected mock values for chronik client for a given mock wallet for a pre 2.0.0 Cashtab user
* Used to support integration testing in Cashtab
@@ -109,13 +176,11 @@
? new Error('Error fetching blockchainInfo')
: { tipHeight: CASHTAB_TESTS_TIPHEIGHT },
});
+
// Mock scriptutxos to match context
- // Cashtab only supports p2pkh addresses
- const CASHTAB_ADDRESS_TYPE = 'p2pkh';
- chronikClient.setScript(CASHTAB_ADDRESS_TYPE, wallet.Path1899.hash160);
- chronikClient.setUtxos(
- CASHTAB_ADDRESS_TYPE,
- wallet.Path1899.hash160,
+ chronikClient.setAddress(wallet.Path1899.cashAddress);
+ chronikClient.setUtxosByAddress(
+ wallet.Path1899.cashAddress,
apiError
? new Error('Error fetching utxos')
: {
@@ -125,10 +190,9 @@
);
// We set legacy paths to contain no utxos
- chronikClient.setScript(CASHTAB_ADDRESS_TYPE, wallet.Path145.hash160);
- chronikClient.setUtxos(
- CASHTAB_ADDRESS_TYPE,
- wallet.Path145.hash160,
+ chronikClient.setAddress(wallet.Path145.cashAddress);
+ chronikClient.setUtxosByAddress(
+ wallet.Path145.cashAddress,
apiError
? new Error('Error fetching utxos')
: {
@@ -136,10 +200,9 @@
utxos: [],
},
);
- chronikClient.setScript(CASHTAB_ADDRESS_TYPE, wallet.Path245.hash160);
- chronikClient.setUtxos(
- CASHTAB_ADDRESS_TYPE,
- wallet.Path245.hash160,
+ chronikClient.setAddress(wallet.Path245.cashAddress);
+ chronikClient.setUtxosByAddress(
+ wallet.Path245.cashAddress,
apiError
? new Error('Error fetching utxos')
: {
@@ -149,50 +212,31 @@
);
// TX history mocks
- chronikClient.setTxHistory(
- CASHTAB_ADDRESS_TYPE,
- wallet.Path1899.hash160,
+ chronikClient.setTxHistoryByAddress(
+ wallet.Path1899.cashAddress,
apiError
? new Error('Error fetching history')
: wallet.state.parsedTxHistory,
);
// We set legacy paths to contain no utxos
- chronikClient.setTxHistory(
- CASHTAB_ADDRESS_TYPE,
- wallet.Path145.hash160,
+ chronikClient.setTxHistoryByAddress(
+ wallet.Path145.cashAddress,
apiError ? new Error('Error fetching history') : [],
);
- chronikClient.setTxHistory(
- CASHTAB_ADDRESS_TYPE,
- wallet.Path245.hash160,
+ chronikClient.setTxHistoryByAddress(
+ wallet.Path245.cashAddress,
apiError ? new Error('Error fetching history') : [],
);
-
- // Mock chronik.tx(tokenId) calls for tokens in tx history
- for (const tx of wallet.state.parsedTxHistory) {
- const mockedTokenResponse = {
- genesisInfo: tx.parsed.genesisInfo,
- };
- if (tx.parsed.isEtokenTx) {
- chronikClient.setMock('token', {
- input:
- 'tokenEntries' in tx.parsed
- ? tx.parsed.tokenEntries[0].tokenId
- : tx.parsed.slpMeta.tokenId,
- output: mockedTokenResponse,
- });
- }
- }
};
/**
*
* @param {object} chronikClient a mockedChronikClient object
- * @param {object} wallet a valid cashtab wallet object
+ * @param {object} wallet a valid cashtab wallet object from before cashtab 2.9.0 and after 2.1.0
* @param {boolean} apiError true if we want to set api errors in mocked chronik
* @returns modifies chronikClient in place to have expected API calls for wallet loading available
*/
-export const prepareMockedChronikCallsForWallet = (
+export const prepareMockedChronikCallsForPre_2_9_0Wallet = (
chronikClient,
wallet,
apiError = false,
@@ -205,9 +249,6 @@
: { tipHeight: CASHTAB_TESTS_TIPHEIGHT },
});
- // Cashtab only supports p2pkh addresses
- const CASHTAB_ADDRESS_TYPE = 'p2pkh';
-
// If you are mocking a legacy wallet to test a migration, return prepareMockedChronikCallsForLegacyWallet
if (!('paths' in wallet)) {
return prepareMockedChronikCallsForLegacyWallet(
@@ -220,10 +261,9 @@
// Iterate over paths to create chronik mocks
for (const path of wallet.paths) {
// Mock scriptutxos to match context
- chronikClient.setScript(CASHTAB_ADDRESS_TYPE, path.hash);
- chronikClient.setUtxos(
- CASHTAB_ADDRESS_TYPE,
- path.hash,
+ chronikClient.setAddress(path.address);
+ chronikClient.setUtxosByAddress(
+ path.address,
apiError
? new Error('Error fetching utxos')
: {
@@ -238,9 +278,8 @@
);
// Mock tx history
- chronikClient.setTxHistory(
- CASHTAB_ADDRESS_TYPE,
- path.hash,
+ chronikClient.setTxHistoryByAddress(
+ path.address,
apiError
? new Error('Error fetching history')
: path.path === 1899
@@ -249,22 +288,209 @@
[],
);
}
+};
- // Mock chronik.tx(tokenId) calls for tokens in tx history
+/**
+ * Prepare chronik calls for a wallet of Cashtab version >= 2.9.0
+ * @param {object} chronikClient a mockedChronikClient object
+ * @param {object} wallet a valid cashtab wallet object
+ * @param {boolean} apiError true if we want to set api errors in mocked chronik
+ * @returns modifies chronikClient in place to have expected API calls for wallet loading available
+ */
+export const prepareMockedChronikCallsForWallet = (
+ chronikClient,
+ wallet,
+ apiError = false,
+) => {
+ // mock chronik endpoint returns
+ const CASHTAB_TESTS_TIPHEIGHT = 800000;
+ chronikClient.setMock('blockchainInfo', {
+ output: apiError
+ ? new Error('Error fetching blockchainInfo')
+ : { tipHeight: CASHTAB_TESTS_TIPHEIGHT },
+ });
+
+ // Mock token calls
+ // This info is same shape for all wallets supported in these functions
+ // Get tokenIds you need chronik.tx(tokenId) and chronik.token(tokenId) calls for
+ // These can come from tx history and slpUtxos
+ const tokenIdsToMock = new Set();
+ for (const utxo of wallet.state.slpUtxos) {
+ tokenIdsToMock.add(utxo.token.tokenId);
+ }
for (const tx of wallet.state.parsedTxHistory) {
- const mockedTokenResponse = {
- genesisInfo: tx.parsed.genesisInfo,
- };
if (tx.parsed.isEtokenTx) {
- chronikClient.setMock('token', {
- input:
- 'tokenEntries' in tx.parsed
- ? tx.parsed.tokenEntries[0].tokenId
- : tx.parsed.slpMeta.tokenId,
- output: mockedTokenResponse,
- });
+ const tokenId =
+ 'tokenEntries' in tx.parsed
+ ? tx.parsed.tokenEntries[0].tokenId
+ : tx.parsed.slpMeta.tokenId;
+ tokenIdsToMock.add(tokenId);
}
}
+
+ for (const tokenId of [...tokenIdsToMock]) {
+ const mockedTokenResponse = {
+ tokenId: tokenId,
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timeFirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'BEAR',
+ tokenName: 'BearNip',
+ url: 'https://cashtab.com/',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 782665,
+ hash: '00000000000000001239831f90580c859ec174316e91961cf0e8cde57c0d3acb',
+ timestamp: 1678408305,
+ },
+ };
+ chronikClient.setMock('token', {
+ input: tokenId,
+ output: mockedTokenResponse,
+ });
+ const mockedTxResponse = {
+ txid: tokenId,
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: '0e737a2f6373649341b406334341202a5ddbbdb389c55da40570b641dc23d036',
+ outIdx: 1,
+ },
+ inputScript:
+ '473044022055444db90f98b462ca29a6f51981da4015623ddc34dc1f575852426ccb785f0402206e786d4056be781ca1720a0a915b040e0a9e8716b8e4d30b0779852c191fdeb3412103771805b54969a9bea4e3eb14a82851c67592156ddb5e52d3d53677d14a40fba6',
+ value: 6231556,
+ sequenceNo: 4294967294,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e45534953044245415207426561724e69701468747470733a2f2f636173687461622e636f6d2f4c0001004c0008000000000000115c',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ token: {
+ tokenId:
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '4444',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '9e7f91826cfd3adf9867c1b3d102594eff4743825fad9883c35d26fb3bdc1693',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 6230555,
+ outputScript:
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ spentBy: {
+ txid: '27a2471afab33d82b9404df12e1fa242488a9439a68e540dcf8f811ef39c11cf',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 299,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 782665,
+ hash: '00000000000000001239831f90580c859ec174316e91961cf0e8cde57c0d3acb',
+ timestamp: 1678408305,
+ },
+ };
+ chronikClient.setMock('tx', {
+ input: tokenId,
+ output: mockedTxResponse,
+ });
+ }
+
+ // If you are mocking a legacy wallet to test a migration, return prepareMockedChronikCallsForLegacyWallet
+ if (!('paths' in wallet)) {
+ return prepareMockedChronikCallsForLegacyWallet(
+ chronikClient,
+ wallet,
+ apiError,
+ );
+ }
+ // If paths is an array and not a map, call appropriate function
+ if (Array.isArray(wallet.paths)) {
+ return prepareMockedChronikCallsForPre_2_9_0Wallet(
+ chronikClient,
+ wallet,
+ apiError,
+ );
+ }
+
+ // Iterate over paths to create chronik mocks
+ wallet.paths.forEach((pathInfo, path) => {
+ // Mock scriptutxos to match context
+ chronikClient.setAddress(pathInfo.address);
+ chronikClient.setUtxosByAddress(
+ pathInfo.address,
+ apiError
+ ? new Error('Error fetching utxos')
+ : {
+ outputScript: `76a914${pathInfo.hash}88ac`,
+ utxos:
+ path === 1899
+ ? wallet.state.nonSlpUtxos.concat(
+ wallet.state.slpUtxos,
+ )
+ : [],
+ },
+ );
+
+ // Mock tx history
+ chronikClient.setTxHistoryByAddress(
+ pathInfo.address,
+ apiError
+ ? new Error('Error fetching history')
+ : path === 1899
+ ? wallet.state.parsedTxHistory
+ : // No tx history at legacy paths
+ [],
+ );
+ });
};
/**
diff --git a/cashtab/src/components/fixtures/mocks.js b/cashtab/src/components/fixtures/mocks.js
--- a/cashtab/src/components/fixtures/mocks.js
+++ b/cashtab/src/components/fixtures/mocks.js
@@ -874,7 +874,7 @@
},
};
-export const walletWithXecAndTokens = {
+export const walletWithXecAndTokens_pre_2_9_0 = {
mnemonic:
'beauty shoe decline spend still weird slot snack coach flee between paper',
name: 'Transaction Fixtures',
@@ -911,30 +911,74 @@
},
};
+export const walletWithXecAndTokens = {
+ ...walletWithXecAndTokens_pre_2_9_0,
+ paths: new Map([
+ [
+ 1899,
+ {
+ address: 'ecash:qqa9lv3kjd8vq7952p7rq0f6lkpqvlu0cydvxtd70g',
+ hash: '3a5fb236934ec078b4507c303d3afd82067f8fc1',
+ wif: 'KywWPgaLDwvW1tWUtUvs13jgqaaWMoNANLVYoKcK9Ddbpnch7Cmw',
+ },
+ ],
+ [
+ 145,
+ {
+ address: 'ecash:qz3glzzjlp503rn3a3nxccedd7rwj78sgczljhvzv3',
+ hash: 'a28f8852f868f88e71ec666c632d6f86e978f046',
+ wif: 'L2HnC8ZT5JuwVFjrAjJUBs2tmmBoxdVa1MVCJccqV8S9YPoR1NuZ',
+ },
+ ],
+ [
+ 245,
+ {
+ address: 'ecash:qpsqa7cj5mup8mx0zvt34z7xyp2jztvdds67wajntk',
+ hash: '600efb12a6f813eccf13171a8bc62055212d8d6c',
+ wif: 'L3ndnMkn4574McqhPujguusu48NrmeLUgWYMkRpYQGLXDGAwGmPq',
+ },
+ ],
+ ]),
+ state: {
+ ...walletWithXecAndTokens_pre_2_9_0.state,
+ tokens: new Map([
+ [
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ '1',
+ ],
+ ]),
+ },
+};
+
export const freshWalletWithOneIncomingCashtabMsg = {
mnemonic: 'some words that would give it all away',
name: '[Burned] useWallet Mock',
- paths: [
- {
- // New shape of path info
- path: 1899,
- address: 'ecash:qrfjv9kglpyazkdsyf0nd9nvewzagf0xsvv84u226e',
- hash: 'd32616c8f849d159b0225f36966ccb85d425e683',
- wif: 'nope',
- },
- {
- path: 145,
- address: 'ecash:qqdukdf3cdgn0nes83x4ln87hd0mpqvh7uky87rj0a',
- hash: '1bcb3531c35137cf303c4d5fccfebb5fb08197f7',
- wif: 'nope',
- },
- {
- path: 245,
- address: 'ecash:qqqtqscqym24ps40v5n2wl88n9zlgu3hqyjzt84eay',
- hash: '00b0430026d550c2af6526a77ce79945f4723701',
- wif: 'nope',
- },
- ],
+ paths: new Map([
+ [
+ 1899,
+ {
+ address: 'ecash:qrfjv9kglpyazkdsyf0nd9nvewzagf0xsvv84u226e',
+ hash: 'd32616c8f849d159b0225f36966ccb85d425e683',
+ wif: 'nope',
+ },
+ ],
+ [
+ 145,
+ {
+ address: 'ecash:qqdukdf3cdgn0nes83x4ln87hd0mpqvh7uky87rj0a',
+ hash: '1bcb3531c35137cf303c4d5fccfebb5fb08197f7',
+ wif: 'nope',
+ },
+ ],
+ [
+ 245,
+ {
+ address: 'ecash:qqqtqscqym24ps40v5n2wl88n9zlgu3hqyjzt84eay',
+ hash: '00b0430026d550c2af6526a77ce79945f4723701',
+ wif: 'nope',
+ },
+ ],
+ ]),
state: {
balanceSats: 1000000,
slpUtxos: [],
@@ -951,7 +995,7 @@
address: 'ecash:qrfjv9kglpyazkdsyf0nd9nvewzagf0xsvv84u226e',
},
],
- tokens: [],
+ tokens: new Map(),
parsedTxHistory: [
{
txid: 'f11648484c5ac6bf65c04632208d60e809014ed288171cb96e059d0ed7678fde',
@@ -1786,25 +1830,112 @@
},
};
-export const vipTokenChronikTokenDetails = {
- tokenId: 'fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- timeFirstSeen: '0',
- genesisInfo: {
- tokenTicker: 'GRP',
- tokenName: 'GRUMPY',
- url: 'https://bit.ly/GrumpyDoc',
- decimals: 2,
- hash: '',
+export const vipTokenChronikTokenMocks = {
+ token: {
+ tokenId:
+ 'fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timeFirstSeen: '0',
+ genesisInfo: {
+ tokenTicker: 'GRP',
+ tokenName: 'GRUMPY',
+ url: 'https://bit.ly/GrumpyDoc',
+ decimals: 2,
+ hash: '',
+ },
+ block: {
+ height: 713853,
+ hash: '0000000000000000006a051e51b50e44d3394ab49c9db896c2484770ed613fb2',
+ timestamp: 1637109257,
+ },
},
- block: {
- height: 713853,
- hash: '0000000000000000006a051e51b50e44d3394ab49c9db896c2484770ed613fb2',
- timestamp: 1637109257,
+ tx: {
+ txid: 'fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: 'b8af3a4ad68cc300e1f9d331762a1a62c0c344c3b3fb554af6a35e634907feab',
+ outIdx: 0,
+ },
+ inputScript:
+ '47304402204db8555a3141e86b979257feadc41e903a779a61971e2e63a386f1084c52ff2a022010d7f7f9d41b474ff5c4bd979916e2cd29627a2d6194fcc6af6485a979091cbe412103632f603f43ae61afece65288d7d92e55188783edb74e205be974b8cd1cd36a1e',
+ value: 50000,
+ sequenceNo: 4294967295,
+ outputScript:
+ '76a9141c13ddb8dd422bbe02dc2ae8798b4549a67a3c1d88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 0,
+ outputScript:
+ '6a04534c500001010747454e4553495303475250064752554d50591868747470733a2f2f6269742e6c792f4772756d7079446f634c0001024c0008000000e8d4a51000',
+ },
+ {
+ value: 546,
+ outputScript:
+ '76a9141c13ddb8dd422bbe02dc2ae8798b4549a67a3c1d88ac',
+ token: {
+ tokenId:
+ 'fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ amount: '1000000000000',
+ isMintBaton: false,
+ entryIdx: 0,
+ },
+ spentBy: {
+ txid: '94cc23c0a01ee35b8b9380b739f1f8d8f6d0e2c09a7785f3d63b928afd23357f',
+ outIdx: 1,
+ },
+ },
+ {
+ value: 48931,
+ outputScript:
+ '76a9141c13ddb8dd422bbe02dc2ae8798b4549a67a3c1d88ac',
+ spentBy: {
+ txid: '94cc23c0a01ee35b8b9380b739f1f8d8f6d0e2c09a7785f3d63b928afd23357f',
+ outIdx: 0,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 0,
+ size: 301,
+ isCoinbase: false,
+ tokenEntries: [
+ {
+ tokenId:
+ 'fb4233e8a568993976ed38a81c2671587c5ad09552dedefa78760deed6ff87aa',
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ txType: 'GENESIS',
+ isInvalid: false,
+ burnSummary: '',
+ failedColorings: [],
+ actualBurnAmount: '0',
+ intentionalBurn: '0',
+ burnsMintBatons: false,
+ },
+ ],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NORMAL',
+ block: {
+ height: 713853,
+ hash: '0000000000000000006a051e51b50e44d3394ab49c9db896c2484770ed613fb2',
+ timestamp: 1637109257,
+ },
},
};
@@ -2096,7 +2227,7 @@
},
];
-const validSavedWalletsBuilder = [];
+const validSavedWalletsBuilder_pre_2_9_0 = [];
for (const unmigratedWallet of validSavedWallets_pre_2_1_0) {
// Clone legacy wallet
const migratedWallet = JSON.parse(JSON.stringify(unmigratedWallet));
@@ -2136,7 +2267,118 @@
? parseInt(unmigratedWallet.state.balances.totalBalanceInSatoshis)
: 0;
+ validSavedWalletsBuilder_pre_2_9_0.push(migratedWallet);
+}
+
+export const validSavedWallets_pre_2_9_0 = validSavedWalletsBuilder_pre_2_9_0;
+
+const validSavedWalletsBuilder = [];
+for (const unmigratedWallet of validSavedWalletsBuilder_pre_2_9_0) {
+ // Clone legacy wallet
+ const migratedWallet = { ...unmigratedWallet };
+ // Build new paths array
+ migratedWallet.paths = new Map([
+ [
+ 1899,
+ {
+ hash: unmigratedWallet.paths.find(
+ pathInfo => pathInfo.path === 1899,
+ ).hash,
+ address: unmigratedWallet.paths.find(
+ pathInfo => pathInfo.path === 1899,
+ ).address,
+ wif: unmigratedWallet.paths.find(
+ pathInfo => pathInfo.path === 1899,
+ ).wif,
+ },
+ ],
+ [
+ 145,
+ {
+ hash: unmigratedWallet.paths.find(
+ pathInfo => pathInfo.path === 145,
+ ).hash,
+ address: unmigratedWallet.paths.find(
+ pathInfo => pathInfo.path === 145,
+ ).address,
+ wif: unmigratedWallet.paths.find(
+ pathInfo => pathInfo.path === 145,
+ ).wif,
+ },
+ ],
+ [
+ 245,
+ {
+ hash: unmigratedWallet.paths.find(
+ pathInfo => pathInfo.path === 245,
+ ).hash,
+ address: unmigratedWallet.paths.find(
+ pathInfo => pathInfo.path === 245,
+ ).address,
+ wif: unmigratedWallet.paths.find(
+ pathInfo => pathInfo.path === 245,
+ ).wif,
+ },
+ ],
+ ]);
+ // Build new state.tokens map
+ // These are empty wallets so it's empty
+ migratedWallet.state.tokens = new Map();
+
validSavedWalletsBuilder.push(migratedWallet);
}
export const validSavedWallets = validSavedWalletsBuilder;
+
+export const mockCacheWalletWithXecAndTokens = {
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ genesisInfo: {
+ tokenTicker: 'BEAR',
+ tokenName: 'BearNip',
+ url: 'https://cashtab.com/',
+ decimals: 0,
+ hash: '',
+ },
+ timeFirstSeen: 0,
+ genesisSupply: '4444',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ block: {
+ height: 782665,
+ hash: '00000000000000001239831f90580c859ec174316e91961cf0e8cde57c0d3acb',
+ timestamp: 1678408305,
+ },
+};
+
+// tokenId b8f2a9e767a0be7b80c7e414ef2534586d4da72efddb39a4e70e501ab73375cc
+export const mockCachedInfoCashtabDark = {
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timeFirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'CTD',
+ tokenName: 'Cashtab Dark',
+ url: 'https://cashtab.com/',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 726043,
+ hash: '00000000000000000182db32e000171006b7b7820181676b5fd8f29cc90d2b9c',
+ timestamp: 1644455332,
+ },
+ genesisSupply: '10000',
+ genesisMintBatons: 0,
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+};
diff --git a/cashtab/src/config/CashtabCache.js b/cashtab/src/config/CashtabCache.js
--- a/cashtab/src/config/CashtabCache.js
+++ b/cashtab/src/config/CashtabCache.js
@@ -3,10 +3,42 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
// Default cashtab cache object used for validation and initialization of new wallets without a cache
+// We include an info object for unknown token id "0000000000000000000000000000000000000000000000000000000000000000"
+// We may come across utxos with this tokenId as it may be returned by chronik, however
+// we cannot get chronik.tx(UNKNOWN_TOKEN_ID) or chronik.token(UNKNOWN_TOKEN_ID)
+
+export const UNKNOWN_TOKEN_ID =
+ '0000000000000000000000000000000000000000000000000000000000000000';
+export const UNKNOWN_TOKEN_CACHED_INFO = {
+ tokenType: {
+ protocol: 'UNKNOWN',
+ type: 'UNKNOWN',
+ number: 0,
+ },
+ timeFirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'UNKNOWN',
+ tokenName: 'UNKNOWN',
+ url: 'UNKNOWN',
+ decimals: 0,
+ hash: 'UNKNOWN',
+ },
+ block: {
+ height: 0,
+ hash: 'UNKNOWN',
+ timestamp: 0,
+ },
+ genesisSupply: '0',
+ genesisMintBatons: 0,
+ genesisOutputScripts: [],
+};
class CashtabCache {
constructor(tokens = new Map()) {
- this.tokens = tokens;
+ const defaultTokensCache = new Map([
+ [UNKNOWN_TOKEN_ID, UNKNOWN_TOKEN_CACHED_INFO],
+ ]);
+ this.tokens = new Map([...defaultTokensCache, ...tokens]);
}
}
diff --git a/cashtab/src/helpers/__tests__/index.test.js b/cashtab/src/helpers/__tests__/index.test.js
--- a/cashtab/src/helpers/__tests__/index.test.js
+++ b/cashtab/src/helpers/__tests__/index.test.js
@@ -7,6 +7,10 @@
getUserLocale,
cashtabCacheToJSON,
storedCashtabCacheToMap,
+ cashtabWalletFromJSON,
+ cashtabWalletToJSON,
+ cashtabWalletsFromJSON,
+ cashtabWalletsToJSON,
} from 'helpers';
import vectors from 'helpers/fixtures/vectors';
@@ -38,13 +42,45 @@
const { description, cashtabCache, cashtabCacheJson } =
expectedReturn;
it(`cashtabCacheToJSON and storedCashtabCacheToMap: ${description}`, () => {
- expect(cashtabCacheToJSON(cashtabCache)).toStrictEqual(
+ expect(cashtabCacheToJSON(cashtabCache)).toEqual(
cashtabCacheJson,
);
- expect(storedCashtabCacheToMap(cashtabCacheJson)).toStrictEqual(
+ expect(storedCashtabCacheToMap(cashtabCacheJson)).toEqual(
cashtabCache,
);
});
});
});
+ describe('Converts cashtabWallet to and from JSON for storage and in-app use', () => {
+ const { expectedReturns } = vectors.cashtabWalletToJSON;
+
+ expectedReturns.forEach(expectedReturn => {
+ const { description, cashtabWallet, cashtabWalletJSON } =
+ expectedReturn;
+ it(`cashtabWalletToJSON and cashtabWalletFromJSON: ${description}`, () => {
+ expect(cashtabWalletToJSON(cashtabWallet)).toStrictEqual(
+ cashtabWalletJSON,
+ );
+ expect(cashtabWalletFromJSON(cashtabWalletJSON)).toStrictEqual(
+ cashtabWallet,
+ );
+ });
+ });
+ });
+ describe('Converts cashtabWallets (array) to and from JSON for storage and in-app use', () => {
+ const { expectedReturns } = vectors.cashtabWalletsToJSON;
+
+ expectedReturns.forEach(expectedReturn => {
+ const { description, cashtabWallets, cashtabWalletsJSON } =
+ expectedReturn;
+ it(`cashtabWalletsToJSON and cashtabWalletsFromJSON: ${description}`, () => {
+ expect(cashtabWalletsToJSON(cashtabWallets)).toStrictEqual(
+ cashtabWalletsJSON,
+ );
+ expect(
+ cashtabWalletsFromJSON(cashtabWalletsJSON),
+ ).toStrictEqual(cashtabWallets);
+ });
+ });
+ });
});
diff --git a/cashtab/src/helpers/fixtures/mocks.js b/cashtab/src/helpers/fixtures/mocks.js
--- a/cashtab/src/helpers/fixtures/mocks.js
+++ b/cashtab/src/helpers/fixtures/mocks.js
@@ -2,9 +2,132 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-const mockTokenCache = new Map();
+import CashtabCache from 'config/CashtabCache';
-mockTokenCache.set(
+/**
+ * Build mockCashtabCache
+ * Valid shape of cashtabCache as of 2.9.0
+ */
+export const mockCashtabCache = new CashtabCache([
+ [
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ {
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timeFirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'BEAR',
+ tokenName: 'BearNip',
+ url: 'https://cashtab.com/',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 782665,
+ hash: '00000000000000001239831f90580c859ec174316e91961cf0e8cde57c0d3acb',
+ timestamp: 1678408305,
+ },
+ genesisSupply: '4444',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ ],
+ [
+ 'b8f2a9e767a0be7b80c7e414ef2534586d4da72efddb39a4e70e501ab73375cc',
+ {
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timeFirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'CTD',
+ tokenName: 'Cashtab Dark',
+ url: 'https://cashtab.com/',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 726043,
+ hash: '00000000000000000182db32e000171006b7b7820181676b5fd8f29cc90d2b9c',
+ timestamp: 1644455332,
+ },
+ genesisSupply: '10000',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ ],
+]);
+
+/**
+ * Build mockCashtabCacheNoBlocks
+ * Valid shape of cashtabCache as of 2.9.0
+ * We may or may not have block in cache
+ */
+export const mockCashtabCacheNoBlocks = new CashtabCache([
+ [
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ {
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timeFirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'BEAR',
+ tokenName: 'BearNip',
+ url: 'https://cashtab.com/',
+ decimals: 0,
+ hash: '',
+ },
+ genesisSupply: '4444',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ ],
+ [
+ 'b8f2a9e767a0be7b80c7e414ef2534586d4da72efddb39a4e70e501ab73375cc',
+ {
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
+ },
+ timeFirstSeen: 0,
+ genesisInfo: {
+ tokenTicker: 'CTD',
+ tokenName: 'Cashtab Dark',
+ url: 'https://cashtab.com/',
+ decimals: 0,
+ hash: '',
+ },
+ genesisSupply: '10000',
+ genesisOutputScripts: [
+ '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac',
+ ],
+ genesisMintBatons: 0,
+ },
+ ],
+]);
+
+/**
+ * mockTokenCache_pre_2_9_0
+ * Valid cashtabCache before 2.9.0 upgrade
+ */
+const mockTokenCache_pre_2_9_0 = new Map();
+
+mockTokenCache_pre_2_9_0.set(
'3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
{
tokenTicker: 'BEAR',
@@ -15,7 +138,7 @@
},
);
-mockTokenCache.set(
+mockTokenCache_pre_2_9_0.set(
'b8f2a9e767a0be7b80c7e414ef2534586d4da72efddb39a4e70e501ab73375cc',
{
tokenTicker: 'CTD',
@@ -26,4 +149,108 @@
},
);
-export const mockCashtabCache = { tokens: mockTokenCache };
+export const mockCashtabCache_pre_2_9_0 = { tokens: mockTokenCache_pre_2_9_0 };
+
+export const emptyCashtabWalletJson = {
+ mnemonic: 'one two three four five six seven eight nine ten eleven twelve',
+ name: 'test',
+ paths: [
+ [
+ 1899,
+ {
+ address: 'string',
+ hash: 'string',
+ wif: 'string',
+ },
+ ],
+ ],
+ state: {
+ balanceSats: 0,
+ nonSlpUtxos: [],
+ slpUtxos: [],
+ tokens: [],
+ },
+};
+
+export const emptyCashtabWalletMultiPathJson = {
+ mnemonic: 'one two three four five six seven eight nine ten eleven twelve',
+ name: 'test',
+ paths: [
+ [
+ 1899,
+ {
+ address: 'string',
+ hash: 'string',
+ wif: 'string',
+ },
+ ],
+ [
+ 145,
+ {
+ address: 'string',
+ hash: 'string',
+ wif: 'string',
+ },
+ ],
+ [
+ 245,
+ {
+ address: 'string',
+ hash: 'string',
+ wif: 'string',
+ },
+ ],
+ ],
+ state: {
+ balanceSats: 0,
+ nonSlpUtxos: [],
+ slpUtxos: [],
+ tokens: [],
+ },
+};
+
+export const cashtabWalletMultiPathWithTokensJson = {
+ mnemonic: 'one two three four five six seven eight nine ten eleven twelve',
+ name: 'test',
+ paths: [
+ [
+ 1899,
+ {
+ address: 'string',
+ hash: 'string',
+ wif: 'string',
+ },
+ ],
+ [
+ 145,
+ {
+ address: 'string',
+ hash: 'string',
+ wif: 'string',
+ },
+ ],
+ [
+ 245,
+ {
+ address: 'string',
+ hash: 'string',
+ wif: 'string',
+ },
+ ],
+ ],
+ state: {
+ balanceSats: 0,
+ nonSlpUtxos: [],
+ slpUtxos: [],
+ tokens: [
+ [
+ '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
+ '100.123',
+ ],
+ [
+ '20a0b9337a78603c6681ed2bc541593375535dcd9979196620ce71f233f2f6f8',
+ '123.456789',
+ ],
+ ],
+ },
+};
diff --git a/cashtab/src/helpers/fixtures/vectors.js b/cashtab/src/helpers/fixtures/vectors.js
--- a/cashtab/src/helpers/fixtures/vectors.js
+++ b/cashtab/src/helpers/fixtures/vectors.js
@@ -2,7 +2,24 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-import { mockCashtabCache } from 'helpers/fixtures/mocks';
+import {
+ mockCashtabCache,
+ emptyCashtabWalletJson,
+ emptyCashtabWalletMultiPathJson,
+ cashtabWalletMultiPathWithTokensJson,
+} from 'helpers/fixtures/mocks';
+import CashtabCache, {
+ UNKNOWN_TOKEN_ID,
+ UNKNOWN_TOKEN_CACHED_INFO,
+} from 'config/CashtabCache';
+import {
+ mockCacheWalletWithXecAndTokens,
+ mockCachedInfoCashtabDark,
+ walletWithXecAndTokens_pre_2_1_0,
+ walletWithXecAndTokens_pre_2_9_0,
+ validSavedWallets_pre_2_1_0,
+ validSavedWallets_pre_2_9_0,
+} from 'components/fixtures/mocks';
import appConfig from 'config/app';
// Test vectors for helper functions
@@ -61,25 +78,14 @@
cashtabCache: mockCashtabCache,
cashtabCacheJson: {
tokens: [
+ [UNKNOWN_TOKEN_ID, UNKNOWN_TOKEN_CACHED_INFO],
[
'3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
- {
- decimals: 0,
- hash: '',
- tokenName: 'BearNip',
- tokenTicker: 'BEAR',
- url: 'https://cashtab.com/',
- },
+ mockCacheWalletWithXecAndTokens,
],
[
'b8f2a9e767a0be7b80c7e414ef2534586d4da72efddb39a4e70e501ab73375cc',
- {
- decimals: 0,
- hash: '',
- tokenName: 'Cashtab Dark',
- tokenTicker: 'CTD',
- url: 'https://cashtab.com/',
- },
+ mockCachedInfoCashtabDark,
],
],
},
@@ -87,8 +93,171 @@
{
description:
'Converts cashtabCache with empty token cache to JSON for storage',
- cashtabCache: { tokens: new Map() },
- cashtabCacheJson: { tokens: [] },
+ cashtabCache: new CashtabCache(),
+ cashtabCacheJson: {
+ tokens: [[UNKNOWN_TOKEN_ID, UNKNOWN_TOKEN_CACHED_INFO]],
+ },
+ },
+ ],
+ },
+ cashtabWalletToJSON: {
+ expectedReturns: [
+ {
+ description: 'Newly created Cashtab wallet',
+ cashtabWallet: {
+ ...emptyCashtabWalletJson,
+ paths: new Map(emptyCashtabWalletJson.paths),
+ state: {
+ ...emptyCashtabWalletJson.state,
+ tokens: new Map(emptyCashtabWalletJson.state.tokens),
+ },
+ },
+ cashtabWalletJSON: emptyCashtabWalletJson,
+ },
+ {
+ description: 'Pre-2.1.0 wallet is unchanged',
+ cashtabWallet: walletWithXecAndTokens_pre_2_1_0,
+ cashtabWalletJSON: walletWithXecAndTokens_pre_2_1_0,
+ },
+ {
+ description: 'Pre-2.9.0 wallet is unchanged',
+ cashtabWallet: walletWithXecAndTokens_pre_2_9_0,
+ cashtabWalletJSON: walletWithXecAndTokens_pre_2_9_0,
+ },
+ {
+ description: 'Cashtab wallet with multiple paths',
+ cashtabWallet: {
+ ...emptyCashtabWalletMultiPathJson,
+ paths: new Map(emptyCashtabWalletMultiPathJson.paths),
+ state: {
+ ...emptyCashtabWalletMultiPathJson.state,
+ tokens: new Map(
+ emptyCashtabWalletMultiPathJson.state.tokens,
+ ),
+ },
+ },
+ cashtabWalletJSON: emptyCashtabWalletMultiPathJson,
+ },
+ {
+ description:
+ 'Cashtab wallet with multiple paths and tokens in state',
+ cashtabWallet: {
+ ...cashtabWalletMultiPathWithTokensJson,
+ paths: new Map(cashtabWalletMultiPathWithTokensJson.paths),
+ state: {
+ ...cashtabWalletMultiPathWithTokensJson.state,
+ tokens: new Map(
+ cashtabWalletMultiPathWithTokensJson.state.tokens,
+ ),
+ },
+ },
+ cashtabWalletJSON: cashtabWalletMultiPathWithTokensJson,
+ },
+ ],
+ },
+ cashtabWalletsToJSON: {
+ expectedReturns: [
+ {
+ description: 'Newly created Cashtab wallets',
+ cashtabWallets: [
+ {
+ ...emptyCashtabWalletJson,
+ paths: new Map(emptyCashtabWalletJson.paths),
+ state: {
+ ...emptyCashtabWalletJson.state,
+ tokens: new Map(
+ emptyCashtabWalletJson.state.tokens,
+ ),
+ },
+ },
+ {
+ ...emptyCashtabWalletJson,
+ paths: new Map(emptyCashtabWalletJson.paths),
+ state: {
+ ...emptyCashtabWalletJson.state,
+ tokens: new Map(
+ emptyCashtabWalletJson.state.tokens,
+ ),
+ },
+ },
+ ],
+ cashtabWalletsJSON: [
+ emptyCashtabWalletJson,
+ emptyCashtabWalletJson,
+ ],
+ },
+ {
+ description: 'Pre-2.1.0 wallets are unchanged',
+ cashtabWallets: validSavedWallets_pre_2_1_0,
+ cashtabWalletsJSON: validSavedWallets_pre_2_1_0,
+ },
+ {
+ description: 'Pre-2.9.0 wallets are unchanged',
+ cashtabWallets: validSavedWallets_pre_2_9_0,
+ cashtabWalletsJSON: validSavedWallets_pre_2_9_0,
+ },
+ {
+ description: 'Cashtab wallets with multiple paths',
+ cashtabWallets: [
+ {
+ ...emptyCashtabWalletMultiPathJson,
+ paths: new Map(emptyCashtabWalletMultiPathJson.paths),
+ state: {
+ ...emptyCashtabWalletMultiPathJson.state,
+ tokens: new Map(
+ emptyCashtabWalletMultiPathJson.state.tokens,
+ ),
+ },
+ },
+ {
+ ...emptyCashtabWalletMultiPathJson,
+ paths: new Map(emptyCashtabWalletMultiPathJson.paths),
+ state: {
+ ...emptyCashtabWalletMultiPathJson.state,
+ tokens: new Map(
+ emptyCashtabWalletMultiPathJson.state.tokens,
+ ),
+ },
+ },
+ ],
+ cashtabWalletsJSON: [
+ emptyCashtabWalletMultiPathJson,
+ emptyCashtabWalletMultiPathJson,
+ ],
+ },
+ {
+ description:
+ 'Cashtab wallets with multiple paths and tokens in state',
+ cashtabWallets: [
+ {
+ ...cashtabWalletMultiPathWithTokensJson,
+ paths: new Map(
+ cashtabWalletMultiPathWithTokensJson.paths,
+ ),
+ state: {
+ ...cashtabWalletMultiPathWithTokensJson.state,
+ tokens: new Map(
+ cashtabWalletMultiPathWithTokensJson.state.tokens,
+ ),
+ },
+ },
+ {
+ ...cashtabWalletMultiPathWithTokensJson,
+ paths: new Map(
+ cashtabWalletMultiPathWithTokensJson.paths,
+ ),
+ state: {
+ ...cashtabWalletMultiPathWithTokensJson.state,
+ tokens: new Map(
+ cashtabWalletMultiPathWithTokensJson.state.tokens,
+ ),
+ },
+ },
+ ],
+ cashtabWalletsJSON: [
+ cashtabWalletMultiPathWithTokensJson,
+ cashtabWalletMultiPathWithTokensJson,
+ ],
},
],
},
diff --git a/cashtab/src/helpers/index.js b/cashtab/src/helpers/index.js
--- a/cashtab/src/helpers/index.js
+++ b/cashtab/src/helpers/index.js
@@ -54,6 +54,83 @@
};
};
+/**
+ * Convert stored cashtabWallet, which includes Map type stored as keyvalue array to some keys
+ * to include actual Maps at these keys
+ * @param {JSON} storedCashtabWallet
+ * @returns {object}
+ */
+export const cashtabWalletFromJSON = storedCashtabWallet => {
+ // If you are pulling a pre-2.9.0 wallet out of storage, no conversion necessary
+ // Cashtab will find this wallet invalid and migrate it
+ // But, you need to ber able to handle pulling old wallets from storage
+ if (
+ 'Path1899' in storedCashtabWallet ||
+ // Pre 2.9.0 wallet
+ (Array.isArray(storedCashtabWallet.paths) &&
+ storedCashtabWallet.paths.length > 0 &&
+ typeof storedCashtabWallet.paths[0].path !== 'undefined')
+ ) {
+ return storedCashtabWallet;
+ }
+ return {
+ ...storedCashtabWallet,
+ paths: new Map(storedCashtabWallet.paths),
+ state: {
+ ...storedCashtabWallet.state,
+ tokens: new Map(storedCashtabWallet.state.tokens),
+ },
+ };
+};
+
+/**
+ * Store Map objects as keyvalue arrays before saving in localforage
+ * @param {object} cashtabWallet
+ * @returns {JSON}
+ */
+export const cashtabWalletToJSON = cashtabWallet => {
+ if (!(cashtabWallet.paths instanceof Map)) {
+ // Cashtab wallets before 2.9.0 were already JSON
+ // We do not plan to ever use this function on such a wallet
+ // Handle so we can be sure no errors are thrown
+ return cashtabWallet;
+ }
+ return {
+ ...cashtabWallet,
+ paths: Array.from(cashtabWallet.paths.entries()),
+ state: {
+ ...cashtabWallet.state,
+ tokens: Array.from(cashtabWallet.state.tokens.entries()),
+ },
+ };
+};
+
+/**
+ * Convert cashtab wallets to JSON for localforage writing
+ * @param {array} wallets array of valid cashtab wallets
+ * @returns {array} jsonWallets
+ */
+export const cashtabWalletsToJSON = wallets => {
+ const jsonWallets = [];
+ for (const wallet of wallets) {
+ jsonWallets.push(cashtabWalletToJSON(wallet));
+ }
+ return jsonWallets;
+};
+
+/**
+ * Convert cashtab wallets from JSON after reading from localforage
+ * @param {array} storedWallets array of stored JSON cashtab wallets
+ * @returns {array} wallets
+ */
+export const cashtabWalletsFromJSON = storedWallets => {
+ const wallets = [];
+ for (const storedWallet of storedWallets) {
+ wallets.push(cashtabWalletFromJSON(storedWallet));
+ }
+ return wallets;
+};
+
/**
* Get the width of a given string of text
* Useful to customize the width of a component according to the size of displayed text
diff --git a/cashtab/src/hooks/__tests__/useWallet.test.js b/cashtab/src/hooks/__tests__/useWallet.test.js
--- a/cashtab/src/hooks/__tests__/useWallet.test.js
+++ b/cashtab/src/hooks/__tests__/useWallet.test.js
@@ -7,7 +7,6 @@
import 'fake-indexeddb/auto';
import localforage from 'localforage';
import {
- walletWithXecAndTokens,
cashtabSettingsGbp,
nonDefaultContactList,
nonDefaultCashtabCache,
@@ -22,6 +21,11 @@
import aliasSettings from 'config/alias';
import { cashtabCacheToJSON, storedCashtabCacheToMap } from 'helpers';
import CashtabCache from 'config/CashtabCache';
+import {
+ walletWithXecAndTokens,
+ mockCacheWalletWithXecAndTokens,
+ mockCachedInfoCashtabDark,
+} from 'components/fixtures/mocks';
describe('useWallet hook rendering in different localforage states', () => {
const xecPrice = 0.00003;
@@ -54,24 +58,12 @@
mockTokenCache.set(
'3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
- {
- tokenTicker: 'BEAR',
- tokenName: 'BearNip',
- url: 'https://cashtab.com/',
- decimals: 0,
- hash: '',
- },
+ mockCacheWalletWithXecAndTokens,
);
mockTokenCache.set(
'b8f2a9e767a0be7b80c7e414ef2534586d4da72efddb39a4e70e501ab73375cc',
- {
- tokenTicker: 'CTD',
- tokenName: 'Cashtab Dark',
- url: 'https://cashtab.com/',
- decimals: 0,
- hash: '',
- },
+ mockCachedInfoCashtabDark,
);
const mockCashtabCache = { tokens: mockTokenCache };
@@ -185,14 +177,7 @@
expectedUpdatedCache.tokens.set(
'3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
- {
- decimals: 0,
- success: true,
- tokenDocumentHash: '',
- tokenDocumentUrl: 'https://cashtab.com/',
- tokenName: 'BearNip',
- tokenTicker: 'BEAR',
- },
+ mockCacheWalletWithXecAndTokens,
);
await waitFor(() =>
@@ -267,7 +252,11 @@
);
await act(async () => {
- await result.current.processChronikWsMsg(mockWebsocketMsg);
+ await result.current.processChronikWsMsg(
+ mockWebsocketMsg,
+ result.current.cashtabState,
+ result.current.fiatPrice,
+ );
});
// Verify upon `BlockConnected` events processChronikWsMsg() updates the aliasPrices state var
@@ -392,7 +381,11 @@
);
await act(async () => {
- await result.current.processChronikWsMsg(mockWebsocketMsg);
+ await result.current.processChronikWsMsg(
+ mockWebsocketMsg,
+ result.current.cashtabState,
+ result.current.fiatPrice,
+ );
});
// Verify upon `BlockConnected` events processChronikWsMsg() updates the aliasPrices state var
@@ -546,7 +539,11 @@
});
await act(async () => {
- await result.current.processChronikWsMsg(mockWebsocketMsg);
+ await result.current.processChronikWsMsg(
+ mockWebsocketMsg,
+ result.current.cashtabState,
+ result.current.fiatPrice,
+ );
});
// Verify upon `BlockConnected` events processChronikWsMsg() does not update the aliasPrices state var
@@ -581,7 +578,11 @@
);
await act(async () => {
- await result.current.processChronikWsMsg(mockWebsocketMsg);
+ await result.current.processChronikWsMsg(
+ mockWebsocketMsg,
+ result.current.cashtabState,
+ result.current.fiatPrice,
+ );
});
// Verify the `aliasServerError` state var in useWallet is updated
@@ -703,14 +704,7 @@
const expectedCache = new CashtabCache();
expectedCache.tokens.set(
'3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
- {
- decimals: 0,
- success: true,
- tokenDocumentHash: '',
- tokenDocumentUrl: 'https://cashtab.com/',
- tokenName: 'BearNip',
- tokenTicker: 'BEAR',
- },
+ mockCacheWalletWithXecAndTokens,
);
// cashtabCache has one token added from tx history
diff --git a/cashtab/src/hooks/fixtures/mocks.js b/cashtab/src/hooks/fixtures/mocks.js
--- a/cashtab/src/hooks/fixtures/mocks.js
+++ b/cashtab/src/hooks/fixtures/mocks.js
@@ -3,877 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
import { CashtabSettings } from 'config/cashtabSettings';
-
-export const walletWithXecAndTokens = {
- mnemonic:
- 'beauty shoe decline spend still weird slot snack coach flee between paper',
- name: 'Transaction Fixtures',
- paths: [
- {
- // New shape of path info
- path: 1899,
- address: 'ecash:qqa9lv3kjd8vq7952p7rq0f6lkpqvlu0cydvxtd70g',
- hash: '3a5fb236934ec078b4507c303d3afd82067f8fc1',
- wif: 'KywWPgaLDwvW1tWUtUvs13jgqaaWMoNANLVYoKcK9Ddbpnch7Cmw',
- },
- {
- path: 145,
- address: 'ecash:qz3glzzjlp503rn3a3nxccedd7rwj78sgczljhvzv3',
- hash: 'a28f8852f868f88e71ec666c632d6f86e978f046',
- wif: 'L2HnC8ZT5JuwVFjrAjJUBs2tmmBoxdVa1MVCJccqV8S9YPoR1NuZ',
- },
- {
- path: 245,
- address: 'ecash:qpsqa7cj5mup8mx0zvt34z7xyp2jztvdds67wajntk',
- hash: '600efb12a6f813eccf13171a8bc62055212d8d6c',
- wif: 'L3ndnMkn4574McqhPujguusu48NrmeLUgWYMkRpYQGLXDGAwGmPq',
- },
- ],
- state: {
- balanceSats: 951312,
- slpUtxos: [
- {
- outpoint: {
- txid: '3b0760858b0b20ff50d0db67793892d29d2466b86a0116f7e232792da0c22330',
- outIdx: 1,
- },
- blockHeight: -1,
- isCoinbase: false,
- value: 546,
- address: 'ecash:qqa9lv3kjd8vq7952p7rq0f6lkpqvlu0cydvxtd70g',
- tokenQty: '1',
- tokenId:
- '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
- decimals: 0,
- isFinal: true,
- token: {
- tokenId:
- '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- amount: '1',
- isMintBaton: false,
- },
- },
- ],
- nonSlpUtxos: [
- {
- outpoint: {
- txid: '218a1e058ed0fda76573eabf43ad3ded7e7192e42621893a60aaa152ba7f66fe',
- outIdx: 2,
- },
- blockHeight: 815549,
- isCoinbase: false,
- value: 951312,
- address: 'ecash:qqa9lv3kjd8vq7952p7rq0f6lkpqvlu0cydvxtd70g',
- isFinal: true,
- },
- ],
- tokens: [
- {
- tokenId:
- '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
- balance: '1',
- info: {
- tokenTicker: 'BEAR',
- tokenName: 'BearNip',
- tokenDocumentUrl: 'https://cashtab.com/',
- tokenDocumentHash: '',
- decimals: 0,
- success: true,
- },
- },
- ],
- parsedTxHistory: [
- {
- txid: '3b0760858b0b20ff50d0db67793892d29d2466b86a0116f7e232792da0c22330',
- version: 2,
- inputs: [
- {
- prevOut: {
- txid: '119310063bb553f02efc3112ea171b251aae968f25a91d42dcd855958134e3be',
- outIdx: 0,
- },
- inputScript:
- '483045022100b8699595913167f3abd5c6dde588fe9dd89e56e811436d0cc02e81a6623a93c1022043954f663eb37a4e0a7cb28bd8ff857d0913cc771832b0e7ccf2b2fbaa9f3ae0412103318d0e1109f32debc66952d0e3ec21b1cf96575ea4c2a97a6535628f7f8b10e6',
- value: 1100,
- sequenceNo: 4294967295,
- outputScript:
- '76a9144e532257c01b310b3b5c1fd947c79a72addf852388ac',
- },
- {
- prevOut: {
- txid: '30993d9a96b1ca91a7726450e6524c41c52cef1b75cb0b5b2e196dfa5b3bb1c6',
- outIdx: 0,
- },
- inputScript:
- '47304402205d3d1e7f83609498d7d7c18cfaa8f4c940c3e12608334b946744c423465cc9f002202199ac5b760c4eb27ee1bf28e94d8e42a6932709d73b387a760269ce2d73aa58412103318d0e1109f32debc66952d0e3ec21b1cf96575ea4c2a97a6535628f7f8b10e6',
- value: 2200,
- sequenceNo: 4294967295,
- outputScript:
- '76a9144e532257c01b310b3b5c1fd947c79a72addf852388ac',
- },
- {
- prevOut: {
- txid: '9e7f91826cfd3adf9867c1b3d102594eff4743825fad9883c35d26fb3bdc1693',
- outIdx: 1,
- },
- inputScript:
- '4730440220649bd38855be5a18bc3b373eec33d9420b9fde009548c79bcccd67a4bef37359022075f64385c0c40670bc03b268554dc7280f0b9dbffbf22c2cb4c76da4898ed1a0412103318d0e1109f32debc66952d0e3ec21b1cf96575ea4c2a97a6535628f7f8b10e6',
- value: 546,
- sequenceNo: 4294967295,
- token: {
- tokenId:
- '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- amount: '888',
- isMintBaton: false,
- entryIdx: 0,
- },
- outputScript:
- '76a9144e532257c01b310b3b5c1fd947c79a72addf852388ac',
- },
- ],
- outputs: [
- {
- value: 0,
- outputScript:
- '6a04534c500001010453454e44203fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109080000000000000001080000000000000377',
- },
- {
- value: 546,
- outputScript:
- '76a9143a5fb236934ec078b4507c303d3afd82067f8fc188ac',
- token: {
- tokenId:
- '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- amount: '1',
- isMintBaton: false,
- entryIdx: 0,
- },
- },
- {
- value: 546,
- outputScript:
- '76a9144e532257c01b310b3b5c1fd947c79a72addf852388ac',
- token: {
- tokenId:
- '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- amount: '887',
- isMintBaton: false,
- entryIdx: 0,
- },
- spentBy: {
- txid: '7004e450f904fc46c75e86deb48c57438e8efd8142e7bac7efe225d775c5f135',
- outIdx: 1,
- },
- },
- {
- value: 1319,
- outputScript:
- '76a9144e532257c01b310b3b5c1fd947c79a72addf852388ac',
- spentBy: {
- txid: '8f076ddab7bcbf37ec993e9b39e75ad1878e35654f380ea9f6f1ebd500711b27',
- outIdx: 25,
- },
- },
- ],
- lockTime: 0,
- timeFirstSeen: 0,
- size: 627,
- isCoinbase: false,
- tokenEntries: [
- {
- tokenId:
- '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- txType: 'SEND',
- isInvalid: false,
- burnSummary: '',
- failedColorings: [],
- actualBurnAmount: '0',
- intentionalBurn: '0',
- burnsMintBatons: false,
- },
- ],
- tokenFailedParsings: [],
- tokenStatus: 'TOKEN_STATUS_NORMAL',
- parsed: {
- incoming: true,
- xecAmount: '5.46',
- isEtokenTx: true,
- etokenAmount: '1',
- isTokenBurn: false,
- tokenEntries: [
- {
- tokenId:
- '3fee3384150b030490b7bee095a63900f66a45f2d8e3002ae2cf17ce3ef4d109',
- tokenType: {
- protocol: 'SLP',
- type: 'SLP_TOKEN_TYPE_FUNGIBLE',
- number: 1,
- },
- txType: 'SEND',
- isInvalid: false,
- burnSummary: '',
- failedColorings: [],
- actualBurnAmount: '0',
- intentionalBurn: '0',
- burnsMintBatons: false,
- },
- ],
- genesisInfo: {
- tokenTicker: 'BEAR',
- tokenName: 'BearNip',
- tokenDocumentUrl: 'https://cashtab.com/',
- tokenDocumentHash: '',
- decimals: 0,
- success: true,
- },
- airdropFlag: false,
- airdropTokenId: '',
- opReturnMessage: '',
- isCashtabMessage: false,
- isEncryptedMessage: false,
- replyAddress:
- 'ecash:qp89xgjhcqdnzzemts0aj378nfe2mhu9yvxj9nhgg6',
- },
- },
- {
- txid: '218a1e058ed0fda76573eabf43ad3ded7e7192e42621893a60aaa152ba7f66fe',
- version: 2,
- inputs: [
- {
- prevOut: {
- txid: '9f25f4e161472920f624ed6579ccdaf8d096263ab31e157deaa9c987269ead8a',
- outIdx: 2,
- },
- inputScript:
- '47304402201cfc6d40bb6a6ee8faae9a3d373742009fa30c6c02a0fcfe055079b62a65d582022013497e2ae6b417262680990ea5d03fe67ac25f7a2a79121fb9b0f633adf458274121031d4603bdc23aca9432f903e3cf5975a3f655cc3fa5057c61d00dfc1ca5dfd02d',
- value: 952320,
- sequenceNo: 4294967295,
- outputScript:
- '76a9143a5fb236934ec078b4507c303d3afd82067f8fc188ac',
- },
- ],
- outputs: [
- {
- value: 0,
- outputScript:
- '6a042e78656300066e6577746f6e15003a5fb236934ec078b4507c303d3afd82067f8fc1',
- },
- {
- value: 553,
- outputScript:
- 'a914d37c4c809fe9840e7bfa77b86bd47163f6fb6c6087',
- spentBy: {
- txid: '9cfd8cbe3235d04d6478f8b95f6206c7bf32029b36138a3cc28c3168042f602f',
- outIdx: 83,
- },
- },
- {
- value: 951312,
- outputScript:
- '76a9143a5fb236934ec078b4507c303d3afd82067f8fc188ac',
- spentBy: {
- txid: '1898c151a8dc84edfbd8f254458226f13422220b5cd7f0ab4e956929218dd38a',
- outIdx: 0,
- },
- },
- ],
- lockTime: 0,
- timeFirstSeen: 0,
- size: 268,
- isCoinbase: false,
- tokenEntries: [],
- tokenFailedParsings: [],
- tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
- block: {
- height: 815549,
- hash: '00000000000000000ea3601057ba423805f91d9d813a41a91ae908b68ff6cbce',
- timestamp: 1698187386,
- },
- parsed: {
- incoming: false,
- xecAmount: '5.53',
- isEtokenTx: false,
- airdropFlag: false,
- airdropTokenId: '',
- opReturnMessage: 'newton',
- isCashtabMessage: false,
- isEncryptedMessage: false,
- replyAddress:
- 'ecash:qqa9lv3kjd8vq7952p7rq0f6lkpqvlu0cydvxtd70g',
- aliasFlag: true,
- },
- },
- {
- txid: '9f25f4e161472920f624ed6579ccdaf8d096263ab31e157deaa9c987269ead8a',
- version: 2,
- inputs: [
- {
- prevOut: {
- txid: '42c39baded510db31aebaf9172d307afa199dd734a6189ea4bc3530438d715ca',
- outIdx: 2,
- },
- inputScript:
- '473044022040513dc15ce7601f937ea83a94a90fd55da07b6a2a95a344a3df63d34489985e022072bd23d71ab5502ee2f254cc58aa0bc2f499370f693f77b1bbb87fe3aaee66d44121031d4603bdc23aca9432f903e3cf5975a3f655cc3fa5057c61d00dfc1ca5dfd02d',
- value: 953326,
- sequenceNo: 4294967295,
- outputScript:
- '76a9143a5fb236934ec078b4507c303d3afd82067f8fc188ac',
- },
- ],
- outputs: [
- {
- value: 0,
- outputScript:
- '6a042e786563000d646f657374686973636c65617215003a5fb236934ec078b4507c303d3afd82067f8fc1',
- },
- {
- value: 551,
- outputScript:
- 'a914d37c4c809fe9840e7bfa77b86bd47163f6fb6c6087',
- spentBy: {
- txid: '4eb00ceabdebb4f6a4fd66d19f9f573c45fe5eb966cdd421eee07ba371771b6d',
- outIdx: 222,
- },
- },
- {
- value: 952320,
- outputScript:
- '76a9143a5fb236934ec078b4507c303d3afd82067f8fc188ac',
- spentBy: {
- txid: '218a1e058ed0fda76573eabf43ad3ded7e7192e42621893a60aaa152ba7f66fe',
- outIdx: 0,
- },
- },
- ],
- lockTime: 0,
- timeFirstSeen: 0,
- size: 275,
- isCoinbase: false,
- tokenEntries: [],
- tokenFailedParsings: [],
- tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
- block: {
- height: 814357,
- hash: '000000000000000009004fa50065ef6deb091f0d075cf1ef01811d0706c9a8c2',
- timestamp: 1697463218,
- },
- parsed: {
- incoming: false,
- xecAmount: '5.51',
- isEtokenTx: false,
- airdropFlag: false,
- airdropTokenId: '',
- opReturnMessage: 'doesthisclear',
- isCashtabMessage: false,
- isEncryptedMessage: false,
- replyAddress:
- 'ecash:qqa9lv3kjd8vq7952p7rq0f6lkpqvlu0cydvxtd70g',
- aliasFlag: true,
- },
- },
- {
- txid: '42c39baded510db31aebaf9172d307afa199dd734a6189ea4bc3530438d715ca',
- version: 2,
- inputs: [
- {
- prevOut: {
- txid: '5aa64624e493502d083089f5a58069887bc99a6d5569b27df7c7570e024bbf20',
- outIdx: 2,
- },
- inputScript:
- '47304402206feb284b4583db2ba6bd0a03cda7ac1571faec3f0f6ab996e4c8b2592726e626022066fe0a6d8887ba64ea7ac9a7472bc6e8ede63baeea3f7f7250e4aadfd9dfebf84121031d4603bdc23aca9432f903e3cf5975a3f655cc3fa5057c61d00dfc1ca5dfd02d',
- value: 954332,
- sequenceNo: 4294967295,
- outputScript:
- '76a9143a5fb236934ec078b4507c303d3afd82067f8fc188ac',
- },
- ],
- outputs: [
- {
- value: 0,
- outputScript:
- '6a042e7865630008776f726b736e6f7715003a5fb236934ec078b4507c303d3afd82067f8fc1',
- },
- {
- value: 551,
- outputScript:
- 'a914d37c4c809fe9840e7bfa77b86bd47163f6fb6c6087',
- spentBy: {
- txid: 'c7c58e59639f29c726752c57f19403f3855f25b758640a96adae4710e27b2eae',
- outIdx: 17,
- },
- },
- {
- value: 953326,
- outputScript:
- '76a9143a5fb236934ec078b4507c303d3afd82067f8fc188ac',
- spentBy: {
- txid: '9f25f4e161472920f624ed6579ccdaf8d096263ab31e157deaa9c987269ead8a',
- outIdx: 0,
- },
- },
- ],
- lockTime: 0,
- timeFirstSeen: 0,
- size: 270,
- isCoinbase: false,
- tokenEntries: [],
- tokenFailedParsings: [],
- tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
- block: {
- height: 813934,
- hash: '00000000000000001533643253107df49b2291beb9d5cd5c7f4f51bf26572e53',
- timestamp: 1697216026,
- },
- parsed: {
- incoming: false,
- xecAmount: '5.51',
- isEtokenTx: false,
- airdropFlag: false,
- airdropTokenId: '',
- opReturnMessage: 'worksnow',
- isCashtabMessage: false,
- isEncryptedMessage: false,
- replyAddress:
- 'ecash:qqa9lv3kjd8vq7952p7rq0f6lkpqvlu0cydvxtd70g',
- aliasFlag: true,
- },
- },
- {
- txid: '5aa64624e493502d083089f5a58069887bc99a6d5569b27df7c7570e024bbf20',
- version: 2,
- inputs: [
- {
- prevOut: {
- txid: 'b26c42ba0cc48f0d3af442b445f19c267189f84dbeb7e366ec7c921f5195aca7',
- outIdx: 2,
- },
- inputScript:
- '47304402202bfc9d29d53f3e2a721472469d0c16726badb0534044e101b990b2413d6d37c80220321cfe15eeea3014012c082693f3ff49f6892b5fe96bc0b980195c7090af1d9a4121031d4603bdc23aca9432f903e3cf5975a3f655cc3fa5057c61d00dfc1ca5dfd02d',
- value: 955341,
- sequenceNo: 4294967295,
- outputScript:
- '76a9143a5fb236934ec078b4507c303d3afd82067f8fc188ac',
- },
- ],
- outputs: [
- {
- value: 0,
- outputScript:
- '6a042e7865630005746573743415003a5fb236934ec078b4507c303d3afd82067f8fc1',
- },
- {
- value: 554,
- outputScript:
- 'a914d37c4c809fe9840e7bfa77b86bd47163f6fb6c6087',
- spentBy: {
- txid: 'c7c58e59639f29c726752c57f19403f3855f25b758640a96adae4710e27b2eae',
- outIdx: 5,
- },
- },
- {
- value: 954332,
- outputScript:
- '76a9143a5fb236934ec078b4507c303d3afd82067f8fc188ac',
- spentBy: {
- txid: '42c39baded510db31aebaf9172d307afa199dd734a6189ea4bc3530438d715ca',
- outIdx: 0,
- },
- },
- ],
- lockTime: 0,
- timeFirstSeen: 0,
- size: 267,
- isCoinbase: false,
- tokenEntries: [],
- tokenFailedParsings: [],
- tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
- block: {
- height: 813923,
- hash: '0000000000000000166ee88a29775a1098813f4316a5afbe835d21e0d74fda24',
- timestamp: 1697211295,
- },
- parsed: {
- incoming: false,
- xecAmount: '5.54',
- isEtokenTx: false,
- airdropFlag: false,
- airdropTokenId: '',
- opReturnMessage: 'test4',
- isCashtabMessage: false,
- isEncryptedMessage: false,
- replyAddress:
- 'ecash:qqa9lv3kjd8vq7952p7rq0f6lkpqvlu0cydvxtd70g',
- aliasFlag: true,
- },
- },
- {
- txid: 'b26c42ba0cc48f0d3af442b445f19c267189f84dbeb7e366ec7c921f5195aca7',
- version: 2,
- inputs: [
- {
- prevOut: {
- txid: 'f86f20336955bca4e15588d81d029ad2c0dfa498b8be6aced2b63ba3bea1be0a',
- outIdx: 2,
- },
- inputScript:
- '483045022100952173ce8b1a2f5cc30be77cd32c6b285ff3f96d36ba0296082ca551204c578502201afcad7d0b2426e1c168c1a1b4a98c637a4c808a6c8fd35c298e9cb7cf6cdc474121031d4603bdc23aca9432f903e3cf5975a3f655cc3fa5057c61d00dfc1ca5dfd02d',
- value: 956351,
- sequenceNo: 4294967295,
- outputScript:
- '76a9143a5fb236934ec078b4507c303d3afd82067f8fc188ac',
- },
- ],
- outputs: [
- {
- value: 0,
- outputScript:
- '6a042e78656300047465737415003a5fb236934ec078b4507c303d3afd82067f8fc1',
- },
- {
- value: 555,
- outputScript:
- 'a914d37c4c809fe9840e7bfa77b86bd47163f6fb6c6087',
- spentBy: {
- txid: 'c7c58e59639f29c726752c57f19403f3855f25b758640a96adae4710e27b2eae',
- outIdx: 2,
- },
- },
- {
- value: 955341,
- outputScript:
- '76a9143a5fb236934ec078b4507c303d3afd82067f8fc188ac',
- spentBy: {
- txid: '5aa64624e493502d083089f5a58069887bc99a6d5569b27df7c7570e024bbf20',
- outIdx: 0,
- },
- },
- ],
- lockTime: 0,
- timeFirstSeen: 0,
- size: 267,
- isCoinbase: false,
- tokenEntries: [],
- tokenFailedParsings: [],
- tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
- block: {
- height: 813922,
- hash: '00000000000000000a1807a17ebcda93947db968e9a112b54ec70237d1a76288',
- timestamp: 1697211196,
- },
- parsed: {
- incoming: false,
- xecAmount: '5.55',
- isEtokenTx: false,
- airdropFlag: false,
- airdropTokenId: '',
- opReturnMessage: 'test',
- isCashtabMessage: false,
- isEncryptedMessage: false,
- replyAddress:
- 'ecash:qqa9lv3kjd8vq7952p7rq0f6lkpqvlu0cydvxtd70g',
- aliasFlag: true,
- },
- },
- {
- txid: 'f86f20336955bca4e15588d81d029ad2c0dfa498b8be6aced2b63ba3bea1be0a',
- version: 2,
- inputs: [
- {
- prevOut: {
- txid: 'f17814a75dad000557f19a3a3f6fcc124ab7880292c9fad4c64dc034d5e46551',
- outIdx: 2,
- },
- inputScript:
- '473044022024d33fa299f1ce126fe5271e26c9fc9e60b10924e2f4aa5fda8bbd46547f0503022077bff168765403d1282f73b7cffd9643b9dd6854e7dbb3ba1f5897bd4a9f63304121031d4603bdc23aca9432f903e3cf5975a3f655cc3fa5057c61d00dfc1ca5dfd02d',
- value: 957361,
- sequenceNo: 4294967295,
- outputScript:
- '76a9143a5fb236934ec078b4507c303d3afd82067f8fc188ac',
- },
- ],
- outputs: [
- {
- value: 0,
- outputScript:
- '6a042e78656300047465737415003a5fb236934ec078b4507c303d3afd82067f8fc1',
- },
- {
- value: 555,
- outputScript:
- 'a914d37c4c809fe9840e7bfa77b86bd47163f6fb6c6087',
- spentBy: {
- txid: 'c7c58e59639f29c726752c57f19403f3855f25b758640a96adae4710e27b2eae',
- outIdx: 3,
- },
- },
- {
- value: 956351,
- outputScript:
- '76a9143a5fb236934ec078b4507c303d3afd82067f8fc188ac',
- spentBy: {
- txid: 'b26c42ba0cc48f0d3af442b445f19c267189f84dbeb7e366ec7c921f5195aca7',
- outIdx: 0,
- },
- },
- ],
- lockTime: 0,
- timeFirstSeen: 0,
- size: 266,
- isCoinbase: false,
- tokenEntries: [],
- tokenFailedParsings: [],
- tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
- block: {
- height: 813922,
- hash: '00000000000000000a1807a17ebcda93947db968e9a112b54ec70237d1a76288',
- timestamp: 1697211196,
- },
- parsed: {
- incoming: false,
- xecAmount: '5.55',
- isEtokenTx: false,
- airdropFlag: false,
- airdropTokenId: '',
- opReturnMessage: 'test',
- isCashtabMessage: false,
- isEncryptedMessage: false,
- replyAddress:
- 'ecash:qqa9lv3kjd8vq7952p7rq0f6lkpqvlu0cydvxtd70g',
- aliasFlag: true,
- },
- },
- {
- txid: 'f17814a75dad000557f19a3a3f6fcc124ab7880292c9fad4c64dc034d5e46551',
- version: 2,
- inputs: [
- {
- prevOut: {
- txid: '7eacd3b752003fe761e359cac3d98b1faf4f1dd411150eabc89da8208a312b0e',
- outIdx: 2,
- },
- inputScript:
- '483045022100e27a4f1c3521ae72c3b1970846616e3ac9f6048066e4566c2d03c1132fb414f50220750243534faa1603bade7c498d8e4390960a59451c858207f80f300f6a57c4534121031d4603bdc23aca9432f903e3cf5975a3f655cc3fa5057c61d00dfc1ca5dfd02d',
- value: 958370,
- sequenceNo: 4294967295,
- outputScript:
- '76a9143a5fb236934ec078b4507c303d3afd82067f8fc188ac',
- },
- ],
- outputs: [
- {
- value: 0,
- outputScript:
- '6a042e7865630005616c69617315003a5fb236934ec078b4507c303d3afd82067f8fc1',
- },
- {
- value: 554,
- outputScript:
- 'a914d37c4c809fe9840e7bfa77b86bd47163f6fb6c6087',
- spentBy: {
- txid: '8bda10d3e08120a0916c0bcc853d2ee0c0d8f7e03a45011d8cafb8fd0c400e50',
- outIdx: 145,
- },
- },
- {
- value: 957361,
- outputScript:
- '76a9143a5fb236934ec078b4507c303d3afd82067f8fc188ac',
- spentBy: {
- txid: 'f86f20336955bca4e15588d81d029ad2c0dfa498b8be6aced2b63ba3bea1be0a',
- outIdx: 0,
- },
- },
- ],
- lockTime: 0,
- timeFirstSeen: 0,
- size: 268,
- isCoinbase: false,
- tokenEntries: [],
- tokenFailedParsings: [],
- tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
- block: {
- height: 813615,
- hash: '000000000000000006b8990c77dd7a0d3a850a052b6f0bd60b82d44d1ffa7a55',
- timestamp: 1697025138,
- },
- parsed: {
- incoming: false,
- xecAmount: '5.54',
- isEtokenTx: false,
- airdropFlag: false,
- airdropTokenId: '',
- opReturnMessage: 'alias',
- isCashtabMessage: false,
- isEncryptedMessage: false,
- replyAddress:
- 'ecash:qqa9lv3kjd8vq7952p7rq0f6lkpqvlu0cydvxtd70g',
- aliasFlag: true,
- },
- },
- {
- txid: '7eacd3b752003fe761e359cac3d98b1faf4f1dd411150eabc89da8208a312b0e',
- version: 2,
- inputs: [
- {
- prevOut: {
- txid: '8b3cb0e6c38ee01f9e1e98d611895ff2cd09ad9b4fea73f76f951be815278c26',
- outIdx: 2,
- },
- inputScript:
- '473044022076ae9639a9cfac3a4189c30eb1ac68daa75850407a2303cb297cc4b1a44a17db0220277681c0346c1b11eb312795c911619935aae6d50d4d03ef5e7dcc916fa28a3d4121031d4603bdc23aca9432f903e3cf5975a3f655cc3fa5057c61d00dfc1ca5dfd02d',
- value: 959379,
- sequenceNo: 4294967295,
- outputScript:
- '76a9143a5fb236934ec078b4507c303d3afd82067f8fc188ac',
- },
- ],
- outputs: [
- {
- value: 0,
- outputScript:
- '6a042e7865630005616c69617315003a5fb236934ec078b4507c303d3afd82067f8fc1',
- },
- {
- value: 554,
- outputScript:
- 'a914d37c4c809fe9840e7bfa77b86bd47163f6fb6c6087',
- spentBy: {
- txid: '8bda10d3e08120a0916c0bcc853d2ee0c0d8f7e03a45011d8cafb8fd0c400e50',
- outIdx: 144,
- },
- },
- {
- value: 958370,
- outputScript:
- '76a9143a5fb236934ec078b4507c303d3afd82067f8fc188ac',
- spentBy: {
- txid: 'f17814a75dad000557f19a3a3f6fcc124ab7880292c9fad4c64dc034d5e46551',
- outIdx: 0,
- },
- },
- ],
- lockTime: 0,
- timeFirstSeen: 0,
- size: 267,
- isCoinbase: false,
- tokenEntries: [],
- tokenFailedParsings: [],
- tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
- block: {
- height: 813615,
- hash: '000000000000000006b8990c77dd7a0d3a850a052b6f0bd60b82d44d1ffa7a55',
- timestamp: 1697025138,
- },
- parsed: {
- incoming: false,
- xecAmount: '5.54',
- isEtokenTx: false,
- airdropFlag: false,
- airdropTokenId: '',
- opReturnMessage: 'alias',
- isCashtabMessage: false,
- isEncryptedMessage: false,
- replyAddress:
- 'ecash:qqa9lv3kjd8vq7952p7rq0f6lkpqvlu0cydvxtd70g',
- aliasFlag: true,
- },
- },
- {
- txid: '8b3cb0e6c38ee01f9e1e98d611895ff2cd09ad9b4fea73f76f951be815278c26',
- version: 2,
- inputs: [
- {
- prevOut: {
- txid: '727a08ebbaef244d136ffb4ab8db256475db8a83cb2acbdfafa42617019d7dc7',
- outIdx: 3,
- },
- inputScript:
- '473044022037e2b4ac09f71432e97d71938dac7b5f0abcd84a8ea995708b0d58c38fcc743302207570250fe9f8b98b8f7079aafb1c53e796584efd910ed9f7e1f75f491f95e7564121031d4603bdc23aca9432f903e3cf5975a3f655cc3fa5057c61d00dfc1ca5dfd02d',
- value: 962056,
- sequenceNo: 4294967295,
- outputScript:
- '76a9143a5fb236934ec078b4507c303d3afd82067f8fc188ac',
- },
- ],
- outputs: [
- {
- value: 0,
- outputScript: '6a04007461620b7374696c6c20776f726b73',
- },
- {
- value: 2200,
- outputScript:
- '76a9146ffbe7c7d7bd01295eb1e371de9550339bdcf9fd88ac',
- spentBy: {
- txid: 'ba69815ef87cb48585a40968d6ff7764cbef4f021fdd015c5eb25afe75feb0a1',
- outIdx: 0,
- },
- },
- {
- value: 959379,
- outputScript:
- '76a9143a5fb236934ec078b4507c303d3afd82067f8fc188ac',
- spentBy: {
- txid: '7eacd3b752003fe761e359cac3d98b1faf4f1dd411150eabc89da8208a312b0e',
- outIdx: 0,
- },
- },
- ],
- lockTime: 0,
- timeFirstSeen: 0,
- size: 252,
- isCoinbase: false,
- tokenEntries: [],
- tokenFailedParsings: [],
- tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
- block: {
- height: 812408,
- hash: '00000000000000000b2dfec91630d335b0233fb323a7acbb297b586d1d0d0678',
- timestamp: 1696282475,
- },
- parsed: {
- incoming: false,
- xecAmount: '22',
- isEtokenTx: false,
- airdropFlag: false,
- airdropTokenId: '',
- opReturnMessage: 'still works',
- isCashtabMessage: true,
- isEncryptedMessage: false,
- replyAddress:
- 'ecash:qqa9lv3kjd8vq7952p7rq0f6lkpqvlu0cydvxtd70g',
- aliasFlag: false,
- },
- },
- ],
- },
-};
+import CashtabCache from 'config/CashtabCache';
export const nonDefaultContactList = [
{
@@ -882,20 +12,36 @@
},
];
-export const nonDefaultCashtabCache = {
- tokens: new Map([
- [
- '1f6a65e7a4bde92c0a012de2bcf4007034504a765377cdf08a3ee01d1eaa6901',
- {
- decimals: 0,
- tokenDocumentHash: '',
- tokenDocumentUrl: '',
- tokenName: 'Burger',
- tokenTicker: '🍔',
+export const nonDefaultCashtabCache = new CashtabCache([
+ [
+ '1f6a65e7a4bde92c0a012de2bcf4007034504a765377cdf08a3ee01d1eaa6901',
+ {
+ tokenType: {
+ protocol: 'SLP',
+ type: 'SLP_TOKEN_TYPE_FUNGIBLE',
+ number: 1,
},
- ],
- ]),
-};
+ timeFirstSeen: '0',
+ genesisInfo: {
+ tokenTicker: '🍔',
+ tokenName: 'Burger',
+ url: 'https://c4.wallpaperflare.com/wallpaper/58/564/863/giant-hamburger-wallpaper-preview.jpg',
+ decimals: 0,
+ hash: '',
+ },
+ block: {
+ height: 619053,
+ hash: '0000000000000000005b1e5a9a6db0570e8836cd8515e9c390ceb6ae174a2bae',
+ timestamp: 1579759858,
+ },
+ genesisSupply: '1000000',
+ genesisMintBatons: 1,
+ genesisOutputScripts: [
+ '76a9140cc24aac9b8196c706aee203c0df1e062d8c4d9b88ac',
+ ],
+ },
+ ],
+]);
// Create a CashtabSettings object at default settings except fiat currency is gbp
export const cashtabSettingsGbp = new CashtabSettings('gbp');
diff --git a/cashtab/src/hooks/useWallet.js b/cashtab/src/hooks/useWallet.js
--- a/cashtab/src/hooks/useWallet.js
+++ b/cashtab/src/hooks/useWallet.js
@@ -3,7 +3,6 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
import React, { useState, useEffect } from 'react';
-import { BN } from 'slp-mdm';
import { getHashArrayFromWallet } from 'utils/cashMethods';
import {
isValidCashtabSettings,
@@ -14,20 +13,23 @@
} from 'validation';
import localforage from 'localforage';
import {
- getUtxosChronik,
+ getUtxos,
+ getHistory,
organizeUtxosByType,
- getPreliminaryTokensArray,
- finalizeTokensArray,
- getTxHistoryChronik,
- parseChronikTx,
- returnGetTokenInfoChronikPromise,
+ parseTx,
+ getTokenBalances,
} from 'chronik';
import { queryAliasServer } from 'alias';
import appConfig from 'config/app';
import aliasSettings from 'config/alias';
import { CashReceivedNotificationIcon } from 'components/Common/CustomIcons';
import { supportedFiatCurrencies } from 'config/cashtabSettings';
-import { cashtabCacheToJSON, storedCashtabCacheToMap } from 'helpers';
+import {
+ cashtabCacheToJSON,
+ storedCashtabCacheToMap,
+ cashtabWalletsFromJSON,
+ cashtabWalletsToJSON,
+} from 'helpers';
import { createCashtabWallet, getLegacyPaths, getBalanceSats } from 'wallet';
import { toast } from 'react-toastify';
import CashtabState from 'config/CashtabState';
@@ -50,7 +52,6 @@
const [aliasIntervalId, setAliasIntervalId] = useState(null);
const [chaintipBlockheight, setChaintipBlockheight] = useState(0);
const [cashtabState, setCashtabState] = useState(new CashtabState());
- const { settings, cashtabCache, wallets } = cashtabState;
const locale = getUserLocale();
const update = async cashtabState => {
@@ -63,35 +64,30 @@
const activeWallet = cashtabState.wallets[0];
try {
- const chronikUtxos = await getUtxosChronik(
- chronik,
- activeWallet.paths,
- );
+ const chronikUtxos = await getUtxos(chronik, activeWallet);
const { slpUtxos, nonSlpUtxos } = organizeUtxosByType(chronikUtxos);
- const preliminaryTokensArray = getPreliminaryTokensArray(slpUtxos);
+ // Get map of all tokenIds held by this wallet and their balances
+ // Note: this function will also update cashtabCache.tokens if any tokens in slpUtxos are not in cache
+ const tokens = await getTokenBalances(
+ chronik,
+ slpUtxos,
+ cashtabState.cashtabCache.tokens,
+ );
- const { tokens, cachedTokens, newTokensToCache } =
- await finalizeTokensArray(
- chronik,
- preliminaryTokensArray,
- cashtabState.cashtabCache.tokens,
- );
+ // Fetch and parse tx history
+ // Note: this function will also update cashtabCache.tokens if any tokens in tx history are not in cache
+ const parsedTxHistory = await getHistory(
+ chronik,
+ activeWallet,
+ cashtabState.cashtabCache.tokens,
+ );
- const {
- parsedTxHistory,
- cachedTokensAfterHistory,
- txHistoryNewTokensToCache,
- } = await getTxHistoryChronik(chronik, activeWallet, cachedTokens);
-
- // If you have updated cachedTokens from finalizeTokensArray or getTxHistoryChronik
- // Update in state and localforage
- if (newTokensToCache || txHistoryNewTokensToCache) {
- updateCashtabState('cashtabCache', {
- ...cashtabState.cashtabCache,
- tokens: cachedTokensAfterHistory,
- });
- }
+ // Update cashtabCache.tokens in state and localforage
+ updateCashtabState('cashtabCache', {
+ ...cashtabState.cashtabCache,
+ tokens: cashtabState.cashtabCache.tokens,
+ });
const newState = {
balanceSats: getBalanceSats(nonSlpUtxos),
@@ -158,6 +154,9 @@
if (key === 'cashtabCache') {
value = cashtabCacheToJSON(value);
}
+ if (key === 'wallets') {
+ value = cashtabWalletsToJSON(value);
+ }
// We lock the UI by setting loading to true while we set items in localforage
// This is to prevent rapid user action from corrupting the db
@@ -353,6 +352,11 @@
if (wallets !== null) {
// If we find wallets in localforage
+ // In this case, we do not need to migrate from the wallet and savedWallets keys
+ // We may or may not need to migrate wallets found at the wallets key to a new format
+
+ // Revive from storage
+ wallets = cashtabWalletsFromJSON(wallets);
// Iterate over all wallets. If valid, do not change. If invalid, migrate and update array.
wallets = await Promise.all(
@@ -505,6 +509,8 @@
const processChronikWsMsg = async (msg, cashtabState, fiatPrice) => {
// get the message type
const { msgType } = msg;
+ // get cashtabState params from param, so you know they are the most recent
+ const { settings, cashtabCache } = cashtabState;
// Cashtab only processes "first seen" transactions and new blocks, i.e. where
// type === 'AddedToMempool' or 'BlockConnected'
// Dev note: Other chronik msg types
@@ -556,75 +562,67 @@
);
}
+ let tokenCacheForParsingThisTx = cashtabCache.tokens;
+ let thisTokenCachedInfo;
+ if (
+ incomingTxDetails.tokenStatus !== 'TOKEN_STATUS_NON_TOKEN' &&
+ incomingTxDetails.tokenEntries.length > 0
+ ) {
+ // If this is a token tx with at least one tokenId that is NOT cached, get token info
+ // TODO we must get token info for multiple token IDs when we start supporting
+ // token types other than slpv1
+ const tokenId = incomingTxDetails.tokenEntries[0].tokenId;
+ thisTokenCachedInfo = cashtabCache.tokens.get(tokenId);
+ if (typeof thisTokenCachedInfo === 'undefined') {
+ // If we do not have this token cached
+ // Note we do not update the cache here because this is handled in update
+ try {
+ thisTokenCachedInfo = await chronik.token(tokenId);
+ tokenCacheForParsingThisTx.set(
+ tokenId,
+ thisTokenCachedInfo,
+ );
+ } catch (err) {
+ console.error(
+ `Error fetching chronik.token(${tokenId})`,
+ err,
+ );
+
+ // Do not throw, in this case tokenCacheForParsingThisTx will still not
+ // include this token info, and the tx will be parsed as if it has 0 decimals
+
+ // We do not show the (wrong) amount in the notification if this is the case
+ }
+ }
+ }
+
// parse tx for notification
- const parsedChronikTx = parseChronikTx(
+ const parsedTx = parseTx(
incomingTxDetails,
cashtabState.wallets[0],
- cashtabCache.tokens,
+ tokenCacheForParsingThisTx,
);
- /* If this is an incoming eToken tx and parseChronikTx was not able to get genesis info
- from cache, then get genesis info from API and add to cache */
- if (parsedChronikTx.incoming) {
- if (parsedChronikTx.isEtokenTx) {
- let eTokenAmountReceived = parsedChronikTx.etokenAmount;
- if (parsedChronikTx.genesisInfo.success) {
- const eTokenReceivedString = `Received ${eTokenAmountReceived} ${parsedChronikTx.genesisInfo.tokenTicker} (${parsedChronikTx.genesisInfo.tokenName})`;
- toast(eTokenReceivedString, {
- icon: (
- <TokenIcon
- size={32}
- tokenId={
- parsedChronikTx.tokenEntries[0].tokenId
- }
- />
- ),
- });
- } else {
- // Get genesis info from API and add to cache
- try {
- // Get the genesis info and add it to cache
- const incomingTokenId =
- parsedChronikTx.tokenEntries[0].tokenId;
-
- const genesisInfoPromise =
- returnGetTokenInfoChronikPromise(
- chronik,
- incomingTokenId,
- cashtabCache.tokens,
- );
- const genesisInfo = await genesisInfoPromise;
-
- // Do not update in state and localforage, as update loop will do this
-
- // Calculate eToken amount with decimals
- eTokenAmountReceived = new BN(
- parsedChronikTx.etokenAmount,
- ).shiftedBy(-1 * genesisInfo.decimals);
-
- const eTokenFirstReceivedString = `Received ${eTokenAmountReceived.toString()} ${
- genesisInfo.tokenTicker
- } (${
- genesisInfo.tokenName
- }) (new token in this wallet)`;
- toast(eTokenFirstReceivedString, {
- icon: (
- <TokenIcon
- size={32}
- tokenId={incomingTokenId}
- />
- ),
- });
- } catch (err) {
- console.log(
- `Error fetching genesisInfo for incoming token tx ${parsedChronikTx}`,
- err,
- );
- }
- }
+ if (parsedTx.incoming) {
+ if (parsedTx.isEtokenTx) {
+ let eTokenAmountReceived = parsedTx.etokenAmount;
+ const eTokenReceivedString = `Received ${
+ parsedTx.assumedTokenDecimals ? '' : eTokenAmountReceived
+ } ${
+ typeof thisTokenCachedInfo !== 'undefined'
+ ? `${thisTokenCachedInfo.genesisInfo.tokenTicker} (${thisTokenCachedInfo.genesisInfo.tokenName})`
+ : ''
+ }`;
+ toast(eTokenReceivedString, {
+ icon: (
+ <TokenIcon
+ size={32}
+ tokenId={parsedTx.tokenEntries[0].tokenId}
+ />
+ ),
+ });
} else {
- const xecAmount = parsedChronikTx.xecAmount;
- // CashReceivedNotificationIcon
+ const xecAmount = parsedTx.xecAmount;
const xecReceivedString = `Received ${xecAmount.toLocaleString(
locale,
)} ${appConfig.ticker}${
@@ -791,38 +789,48 @@
updateWebsocket(cashtabState, fiatPrice);
}, [cashtabState, fiatPrice, ws, cashtabLoaded]);
- const refreshAliasesOnStartup = async () => {
- // Initialize a new periodic refresh of aliases which ONLY calls the API if
- // there are pending aliases since confirmed aliases would not change over time
- // The interval is also only initialized if there are no other intervals present.
- if (aliasSettings.aliasEnabled) {
- if (wallets.length > 0 && aliasIntervalId === null) {
- // Get Path1899 address from wallet
- const path1899Info = wallets[0].paths.find(
- pathInfo => pathInfo.path === 1899,
+ /**
+ * Set an interval to monitor pending alias txs
+ * @param {string} address
+ * @returns callback function to cleanup interval
+ */
+ const refreshAliasesOnStartup = async address => {
+ // Initial refresh to ensure `aliases` state var is up to date
+ await refreshAliases(address);
+ const aliasRefreshInterval = 30000;
+ const intervalId = setInterval(async function () {
+ if (aliases?.pending?.length > 0) {
+ console.log(
+ 'useEffect(): Refreshing registered and pending aliases',
);
- const defaultAddress = path1899Info.address;
- // Initial refresh to ensure `aliases` state var is up to date
- await refreshAliases(defaultAddress);
- const aliasRefreshInterval = 30000;
- const intervalId = setInterval(async function () {
- if (aliases?.pending?.length > 0) {
- console.log(
- 'useEffect(): Refreshing registered and pending aliases',
- );
- await refreshAliases(defaultAddress);
- }
- }, aliasRefreshInterval);
- setAliasIntervalId(intervalId);
- // Clear the interval when useWallet unmounts
- return () => clearInterval(intervalId);
+ await refreshAliases(address);
}
- }
+ }, aliasRefreshInterval);
+ setAliasIntervalId(intervalId);
+ // Clear the interval when useWallet unmounts
+ return () => clearInterval(intervalId);
};
useEffect(() => {
- refreshAliasesOnStartup();
- }, [aliases?.pending?.length]);
+ if (
+ aliasSettings.aliasEnabled &&
+ aliases?.pending?.length > 0 &&
+ aliasIntervalId === null &&
+ typeof cashtabState.wallets !== 'undefined' &&
+ cashtabState.wallets.length > 0
+ ) {
+ // If
+ // 1) aliases are enabled in Cashtab
+ // 2) we have pending aliases
+ // 3) No interval is set to watch these pending aliases
+ // 4) We have an active wallet
+ // Set an interval to watch these pending aliases
+ refreshAliasesOnStartup(cashtabState.wallets[0].paths.get(1899));
+ } else if (aliases?.pending?.length === 0 && aliasIntervalId !== null) {
+ // If we have no pending aliases but we still have an interval to check them, clearInterval
+ clearInterval(aliasIntervalId);
+ }
+ }, [cashtabState.wallets[0]?.name, aliases]);
return {
chronik,
diff --git a/cashtab/src/transactions/__tests__/index.test.js b/cashtab/src/transactions/__tests__/index.test.js
--- a/cashtab/src/transactions/__tests__/index.test.js
+++ b/cashtab/src/transactions/__tests__/index.test.js
@@ -20,7 +20,7 @@
sendSlp,
} from '../fixtures/vectors';
-describe('Improved Cashtab transaction broadcasting function', () => {
+describe('We can broadcast XEC transactions', () => {
// Unit test for each vector in fixtures for the sendingXecToSingleAddress case
const { txs, errors } = sendXecVectors;
diff --git a/cashtab/src/transactions/fixtures/mocks.js b/cashtab/src/transactions/fixtures/mocks.js
--- a/cashtab/src/transactions/fixtures/mocks.js
+++ b/cashtab/src/transactions/fixtures/mocks.js
@@ -1,31 +1,39 @@
-// Copyright (c) 2023-2024 The Bitcoin developers
+// Copyright (c) 2024 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+import { cashtabWalletToJSON, cashtabWalletFromJSON } from 'helpers';
+
const wallet = {
mnemonic:
'beauty shoe decline spend still weird slot snack coach flee between paper',
name: 'Transaction Fixtures',
- paths: [
- {
- path: 1899,
- hash: '3a5fb236934ec078b4507c303d3afd82067f8fc1',
- address: 'ecash:qqa9lv3kjd8vq7952p7rq0f6lkpqvlu0cydvxtd70g',
- wif: 'KywWPgaLDwvW1tWUtUvs13jgqaaWMoNANLVYoKcK9Ddbpnch7Cmw',
- },
- {
- path: 145,
- hash: 'a28f8852f868f88e71ec666c632d6f86e978f046',
- address: 'ecash:qz3glzzjlp503rn3a3nxccedd7rwj78sgczljhvzv3',
- wif: 'L2HnC8ZT5JuwVFjrAjJUBs2tmmBoxdVa1MVCJccqV8S9YPoR1NuZ',
- },
- {
- path: 245,
- hash: '600efb12a6f813eccf13171a8bc62055212d8d6c',
- address: 'ecash:qpsqa7cj5mup8mx0zvt34z7xyp2jztvdds67wajntk',
- wif: 'L3ndnMkn4574McqhPujguusu48NrmeLUgWYMkRpYQGLXDGAwGmPq',
- },
- ],
+ paths: new Map([
+ [
+ 1899,
+ {
+ hash: '3a5fb236934ec078b4507c303d3afd82067f8fc1',
+ address: 'ecash:qqa9lv3kjd8vq7952p7rq0f6lkpqvlu0cydvxtd70g',
+ wif: 'KywWPgaLDwvW1tWUtUvs13jgqaaWMoNANLVYoKcK9Ddbpnch7Cmw',
+ },
+ ],
+ [
+ 145,
+ {
+ hash: 'a28f8852f868f88e71ec666c632d6f86e978f046',
+ address: 'ecash:qz3glzzjlp503rn3a3nxccedd7rwj78sgczljhvzv3',
+ wif: 'L2HnC8ZT5JuwVFjrAjJUBs2tmmBoxdVa1MVCJccqV8S9YPoR1NuZ',
+ },
+ ],
+ [
+ 245,
+ {
+ hash: '600efb12a6f813eccf13171a8bc62055212d8d6c',
+ address: 'ecash:qpsqa7cj5mup8mx0zvt34z7xyp2jztvdds67wajntk',
+ wif: 'L3ndnMkn4574McqhPujguusu48NrmeLUgWYMkRpYQGLXDGAwGmPq',
+ },
+ ],
+ ]),
state: {
balanceSats: 135000,
slpUtxos: [],
@@ -39,7 +47,7 @@
isCoinbase: false,
value: '25000',
network: 'XEC',
- address: 'ecash:qqa9lv3kjd8vq7952p7rq0f6lkpqvlu0cydvxtd70g',
+ path: 1899,
},
{
outpoint: {
@@ -50,7 +58,7 @@
isCoinbase: false,
value: '100000',
network: 'XEC',
- address: 'ecash:qqa9lv3kjd8vq7952p7rq0f6lkpqvlu0cydvxtd70g',
+ path: 1899,
},
{
outpoint: {
@@ -61,10 +69,10 @@
isCoinbase: false,
value: '10000',
network: 'XEC',
- address: 'ecash:qqa9lv3kjd8vq7952p7rq0f6lkpqvlu0cydvxtd70g',
+ path: 1899,
},
],
- tokens: [],
+ tokens: new Map(),
parsedTxHistory: [
{
txid: '6854f1eeed12293926e0223e0b59f9b3db3650fe486680ca7d705a0c990b1dc3',
@@ -305,26 +313,32 @@
mnemonic:
'beauty shoe decline spend still weird slot snack coach flee between paper',
name: 'Transaction Fixtures',
- paths: [
- {
- path: 1899,
- hash: '3a5fb236934ec078b4507c303d3afd82067f8fc1',
- address: 'ecash:qqa9lv3kjd8vq7952p7rq0f6lkpqvlu0cydvxtd70g',
- wif: 'KywWPgaLDwvW1tWUtUvs13jgqaaWMoNANLVYoKcK9Ddbpnch7Cmw',
- },
- {
- path: 145,
- hash: 'a28f8852f868f88e71ec666c632d6f86e978f046',
- address: 'ecash:qz3glzzjlp503rn3a3nxccedd7rwj78sgczljhvzv3',
- wif: 'L2HnC8ZT5JuwVFjrAjJUBs2tmmBoxdVa1MVCJccqV8S9YPoR1NuZ',
- },
- {
- path: 245,
- hash: '600efb12a6f813eccf13171a8bc62055212d8d6c',
- address: 'ecash:qpsqa7cj5mup8mx0zvt34z7xyp2jztvdds67wajntk',
- wif: 'L3ndnMkn4574McqhPujguusu48NrmeLUgWYMkRpYQGLXDGAwGmPq',
- },
- ],
+ paths: new Map([
+ [
+ 1899,
+ {
+ hash: '3a5fb236934ec078b4507c303d3afd82067f8fc1',
+ address: 'ecash:qqa9lv3kjd8vq7952p7rq0f6lkpqvlu0cydvxtd70g',
+ wif: 'KywWPgaLDwvW1tWUtUvs13jgqaaWMoNANLVYoKcK9Ddbpnch7Cmw',
+ },
+ ],
+ [
+ 145,
+ {
+ hash: 'a28f8852f868f88e71ec666c632d6f86e978f046',
+ address: 'ecash:qz3glzzjlp503rn3a3nxccedd7rwj78sgczljhvzv3',
+ wif: 'L2HnC8ZT5JuwVFjrAjJUBs2tmmBoxdVa1MVCJccqV8S9YPoR1NuZ',
+ },
+ ],
+ [
+ 245,
+ {
+ hash: '600efb12a6f813eccf13171a8bc62055212d8d6c',
+ address: 'ecash:qpsqa7cj5mup8mx0zvt34z7xyp2jztvdds67wajntk',
+ wif: 'L3ndnMkn4574McqhPujguusu48NrmeLUgWYMkRpYQGLXDGAwGmPq',
+ },
+ ],
+ ]),
state: {
balanceSats: 135000,
slpUtxos: [],
@@ -338,7 +352,7 @@
isCoinbase: true,
value: '25000',
network: 'XEC',
- address: 'ecash:qqa9lv3kjd8vq7952p7rq0f6lkpqvlu0cydvxtd70g',
+ path: 1899,
},
{
outpoint: {
@@ -349,7 +363,7 @@
isCoinbase: true,
value: '100000',
network: 'XEC',
- address: 'ecash:qqa9lv3kjd8vq7952p7rq0f6lkpqvlu0cydvxtd70g',
+ path: 1899,
},
{
outpoint: {
@@ -360,10 +374,10 @@
isCoinbase: true,
value: '10000',
network: 'XEC',
- address: 'ecash:qqa9lv3kjd8vq7952p7rq0f6lkpqvlu0cydvxtd70g',
+ path: 1899,
},
],
- tokens: [],
+ tokens: new Map([]),
parsedTxHistory: [
{
txid: '6854f1eeed12293926e0223e0b59f9b3db3650fe486680ca7d705a0c990b1dc3',
@@ -601,7 +615,9 @@
};
// Create a wallet with utxos at multiple addresses
-const utxosAtManyAddressesWallet = JSON.parse(JSON.stringify(wallet));
+const utxosAtManyAddressesWallet = cashtabWalletFromJSON(
+ JSON.parse(JSON.stringify(cashtabWalletToJSON(wallet))),
+);
const multiAddressUtxos = [
{
outpoint: {
@@ -612,7 +628,7 @@
isCoinbase: false,
value: '25000',
network: 'XEC',
- address: wallet.paths.find(pathInfo => pathInfo.path === 145).address,
+ path: 145,
},
{
outpoint: {
@@ -623,7 +639,7 @@
isCoinbase: false,
value: '100000',
network: 'XEC',
- address: wallet.paths.find(pathInfo => pathInfo.path === 245).address,
+ path: 245,
},
{
outpoint: {
@@ -634,23 +650,26 @@
isCoinbase: false,
value: '10000',
network: 'XEC',
- address: wallet.paths.find(pathInfo => pathInfo.path === 1899).address,
+ path: 1899,
},
];
utxosAtManyAddressesWallet.state.nonSlpUtxos = multiAddressUtxos;
// Create a wallet that has a corrupted private key
// Not expected to ever happen in Cashtab
-const walletWithInvalidPrivateKey = JSON.parse(JSON.stringify(wallet));
-// Take a portion of a valid wif to keep base58 chars
-const badWifPath1899Info = walletWithInvalidPrivateKey.paths.find(
- pathInfo => pathInfo.path === 1899,
+// cashtabWalletToJSON
+const walletWithInvalidPrivateKey = cashtabWalletFromJSON(
+ JSON.parse(JSON.stringify(cashtabWalletToJSON(wallet))),
);
+// Take a portion of a valid wif to keep base58 chars
+const badWifPath1899Info = walletWithInvalidPrivateKey.paths.get(1899);
badWifPath1899Info.wif = badWifPath1899Info.wif.slice(0, 20);
// Create a wallet with very large utxos
const TOTAL_ECASH_SUPPLY_SATS = 2100000000000000;
-const allTheXecWallet = JSON.parse(JSON.stringify(wallet));
+const allTheXecWallet = cashtabWalletFromJSON(
+ JSON.parse(JSON.stringify(cashtabWalletToJSON(wallet))),
+);
const largeUtxo = {
outpoint: {
txid: '6854f1eeed12293926e0223e0b59f9b3db3650fe486680ca7d705a0c990b1dc3',
@@ -660,7 +679,7 @@
isCoinbase: false,
value: TOTAL_ECASH_SUPPLY_SATS,
network: 'XEC',
- address: 'ecash:qqa9lv3kjd8vq7952p7rq0f6lkpqvlu0cydvxtd70g',
+ path: 1899,
};
allTheXecWallet.state.nonSlpUtxos = [largeUtxo];
@@ -670,26 +689,32 @@
mnemonic:
'industry limit sense cruel neglect loud chase usual advance method talk come',
name: 'SLP V1 Send',
- paths: [
- {
- path: 1899,
- hash: 'c38232a045a85c84e5733d60e867dcee9ad4b18d',
- address: 'ecash:qrpcyv4qgk59ep89wv7kp6r8mnhf449335wt7lud8u',
- wif: 'KyEQdr8GzqtwzHHB8kiaWLiUCWYGgz76t7gF2z9aSjWnsVikJZUX',
- },
- {
- path: 245,
- hash: '3d97ee01c3d021c3efcf529c3136f7b8b86c1ed0',
- address: 'ecash:qq7e0mspc0gzrsl0eaffcvfk77utsmq76qnat0vlkj',
- wif: 'L4GFvCRSz8fbS64W7teTjnGbV5A8iPdz1GyPqHvAj8vxzqZjwZbw',
- },
- {
- path: 145,
- hash: '33a070d3931a4993207771ae1aa92aa05491e8b2',
- address: 'ecash:qqe6quxnjvdynyeqwac6ux4f92s9fy0gkg6ek2jtfh',
- wif: 'L5GHzdq3qfTmUKLxZ3fuvfu9yvgsQH3wWcXU2BfD3qp88RTXF88M',
- },
- ],
+ paths: new Map([
+ [
+ 1899,
+ {
+ hash: 'c38232a045a85c84e5733d60e867dcee9ad4b18d',
+ address: 'ecash:qrpcyv4qgk59ep89wv7kp6r8mnhf449335wt7lud8u',
+ wif: 'KyEQdr8GzqtwzHHB8kiaWLiUCWYGgz76t7gF2z9aSjWnsVikJZUX',
+ },
+ ],
+ [
+ 245,
+ {
+ hash: '3d97ee01c3d021c3efcf529c3136f7b8b86c1ed0',
+ address: 'ecash:qq7e0mspc0gzrsl0eaffcvfk77utsmq76qnat0vlkj',
+ wif: 'L4GFvCRSz8fbS64W7teTjnGbV5A8iPdz1GyPqHvAj8vxzqZjwZbw',
+ },
+ ],
+ [
+ 145,
+ {
+ hash: '33a070d3931a4993207771ae1aa92aa05491e8b2',
+ address: 'ecash:qqe6quxnjvdynyeqwac6ux4f92s9fy0gkg6ek2jtfh',
+ wif: 'L5GHzdq3qfTmUKLxZ3fuvfu9yvgsQH3wWcXU2BfD3qp88RTXF88M',
+ },
+ ],
+ ]),
state: {
balanceSats: 1000000,
slpUtxos: [
@@ -698,71 +723,70 @@
txid: '4fa08436ac4611ee2523eede281c4c8d7c1d1a9367661e1754775d8b7ae2b199',
outIdx: 1,
},
- value: '546',
+ value: 546,
token: {
tokenId:
'b19b4c83056f6e3dace0e786446a8ccd73f22cfc42c3013808c532ab43490a14',
amount: '1000000000',
isMintBaton: false,
},
- // Note: the address is not provided by NNG or in-node, and is added by Cashtab
- address: 'ecash:qrpcyv4qgk59ep89wv7kp6r8mnhf449335wt7lud8u',
+ path: 1899,
},
{
outpoint: {
txid: '51bc5da566c85b486b37f1c4d3c0220b7bc11ad992c1b92f99233cf35a8794c1',
outIdx: 1,
},
- value: '546',
+ value: 546,
token: {
tokenId:
'b19b4c83056f6e3dace0e786446a8ccd73f22cfc42c3013808c532ab43490a14',
amount: '9999996998999999999',
isMintBaton: false,
},
- address: 'ecash:qrpcyv4qgk59ep89wv7kp6r8mnhf449335wt7lud8u',
+ path: 1899,
},
{
outpoint: {
txid: '56cc72b07a374990d767a569120308812d0da4ef0c0d669a1966a648e759669a',
outIdx: 1,
},
- value: '546',
+ value: 546,
token: {
tokenId:
'b19b4c83056f6e3dace0e786446a8ccd73f22cfc42c3013808c532ab43490a14',
amount: '1000000000000',
isMintBaton: false,
},
- address: 'ecash:qrpcyv4qgk59ep89wv7kp6r8mnhf449335wt7lud8u',
+ path: 1899,
},
{
outpoint: {
txid: 'c294d534331256c1f00016fb487f0079b926ab69bd8339350e4c356a1e17dc0d',
outIdx: 1,
},
- value: '546',
+ value: 546,
token: {
tokenId:
'b19b4c83056f6e3dace0e786446a8ccd73f22cfc42c3013808c532ab43490a14',
amount: '1',
isMintBaton: false,
},
- address: 'ecash:qrpcyv4qgk59ep89wv7kp6r8mnhf449335wt7lud8u',
+ path: 1899,
},
{
outpoint: {
txid: 'd8c694714c2d39a22b8d867530f37e796937ac4b9bc7c9528926649788d15f43',
outIdx: 1,
},
- value: '546',
+ value: 546,
token: {
tokenId:
'b19b4c83056f6e3dace0e786446a8ccd73f22cfc42c3013808c532ab43490a14',
amount: '2000000000000',
isMintBaton: false,
},
- address: 'ecash:qrpcyv4qgk59ep89wv7kp6r8mnhf449335wt7lud8u',
+ path: 1899,
},
],
nonSlpUtxos: [
@@ -775,26 +799,15 @@
isCoinbase: false,
value: '1000000',
network: 'XEC',
- address: 'ecash:qrpcyv4qgk59ep89wv7kp6r8mnhf449335wt7lud8u',
- },
- ],
- tokens: [
- {
- tokenId:
- 'b19b4c83056f6e3dace0e786446a8ccd73f22cfc42c3013808c532ab43490a14',
- balance: '10000000000',
- info: {
- tokenTicker: 'GYP',
- tokenName: 'Gypsum',
- tokenDocumentUrl: 'https://cashtab.com/',
- tokenDocumentHash: '',
- decimals: 9,
- tokenId:
- 'b19b4c83056f6e3dace0e786446a8ccd73f22cfc42c3013808c532ab43490a14',
- success: true,
- },
+ path: 1899,
},
],
+ tokens: new Map([
+ [
+ 'b19b4c83056f6e3dace0e786446a8ccd73f22cfc42c3013808c532ab43490a14',
+ '10000000000',
+ ],
+ ]),
parsedTxHistory: [],
},
};
diff --git a/cashtab/src/transactions/fixtures/vectors.js b/cashtab/src/transactions/fixtures/vectors.js
--- a/cashtab/src/transactions/fixtures/vectors.js
+++ b/cashtab/src/transactions/fixtures/vectors.js
@@ -517,7 +517,7 @@
export const sendSlp = {
expectedReturns: [
{
- description: 'SLP send and burn with token change, NNG utxo shape',
+ description: 'SLP send and burn with token change',
wallet: walletWithTokensInNode,
tokenId:
'b19b4c83056f6e3dace0e786446a8ccd73f22cfc42c3013808c532ab43490a14',
@@ -533,28 +533,28 @@
txid: '4fa08436ac4611ee2523eede281c4c8d7c1d1a9367661e1754775d8b7ae2b199',
outIdx: 1,
},
- value: '546',
+ value: 546,
token: {
tokenId:
'b19b4c83056f6e3dace0e786446a8ccd73f22cfc42c3013808c532ab43490a14',
amount: '1000000000',
isMintBaton: false,
},
- address: 'ecash:qrpcyv4qgk59ep89wv7kp6r8mnhf449335wt7lud8u',
+ path: 1899,
},
{
outpoint: {
txid: '51bc5da566c85b486b37f1c4d3c0220b7bc11ad992c1b92f99233cf35a8794c1',
outIdx: 1,
},
- value: '546',
+ value: 546,
token: {
tokenId:
'b19b4c83056f6e3dace0e786446a8ccd73f22cfc42c3013808c532ab43490a14',
amount: '9999996998999999999',
isMintBaton: false,
},
- address: 'ecash:qrpcyv4qgk59ep89wv7kp6r8mnhf449335wt7lud8u',
+ path: 1899,
},
],
sendAmounts: [new BN('10000000000'), new BN('9999996989999999999')],
@@ -566,8 +566,7 @@
},
},
{
- description:
- 'SLP send and BURN with no token change, NNG utxo shape',
+ description: 'SLP send and BURN with no token change',
wallet: walletWithTokensInNode,
tokenId:
'b19b4c83056f6e3dace0e786446a8ccd73f22cfc42c3013808c532ab43490a14',
@@ -590,7 +589,7 @@
amount: '1000000000',
isMintBaton: false,
},
- address: 'ecash:qrpcyv4qgk59ep89wv7kp6r8mnhf449335wt7lud8u',
+ path: 1899,
},
],
sendAmounts: [new BN('1000000000')],
diff --git a/cashtab/src/transactions/index.js b/cashtab/src/transactions/index.js
--- a/cashtab/src/transactions/index.js
+++ b/cashtab/src/transactions/index.js
@@ -11,16 +11,14 @@
/**
* Sign tx inputs
* @param {object} txBuilder an initialized TransactionBuilder with inputs and outputs added
- * @param {array} accounts [...{address: <cashaddr>, wif: <wif>}]
+ * @param {array} paths paths key of a cashtab wallet
* @param {array} inputs [...{address: <cashaddr>, value: <number>}]
* @throws {error} if private key is corrupted or wif is undefined
*/
-export const signInputs = (txBuilder, accounts, inputs) => {
+export const signInputs = (txBuilder, paths, inputs) => {
inputs.forEach((input, index) => {
// Select the correct signing key based on the address of the input
- const wif = accounts
- .filter(acc => acc.address === input.address)
- .pop().wif;
+ const wif = paths.get(input.path).wif;
// TODO store this in wallet instead of generating it every time you sign a tx
const utxoECPair = utxolib.ECPair.fromWIF(wif, utxolib.networks.ecash);
@@ -97,9 +95,7 @@
// Change address is wallet address
// Use Path1899 address as change address
- output.address = wallet.paths.find(
- pathInfo => pathInfo.path === 1899,
- ).address;
+ output.address = wallet.paths.get(1899).address;
}
// TODO add cashaddr support for eCash to txBuilder in utxo-lib
diff --git a/cashtab/src/utils/__tests__/formatting.test.js b/cashtab/src/utils/__tests__/formatting.test.js
--- a/cashtab/src/utils/__tests__/formatting.test.js
+++ b/cashtab/src/utils/__tests__/formatting.test.js
@@ -8,7 +8,9 @@
formatFiatBalance,
formatBalance,
formatTokenBalance,
+ decimalizedTokenQtyToLocaleFormat,
} from 'utils/formatting';
+import vectors from 'utils/fixtures/vectors';
describe('Correctly executes formatting functions', () => {
it(`test formatBalance with an input of 0`, () => {
@@ -126,4 +128,19 @@
const testBalance = new BN(10000);
expect(formatTokenBalance(testBalance, 8)).toBe('10,000.00000000');
});
+ describe('We can format decimalized token strings for userLocale', () => {
+ const { expectedReturns } = vectors.decimalizedTokenQtyToLocaleFormat;
+ expectedReturns.forEach(vector => {
+ const { description, decimalizedTokenQty, userLocale, returned } =
+ vector;
+ it(`decimalizedTokenQtyToLocaleFormat: ${description}`, () => {
+ expect(
+ decimalizedTokenQtyToLocaleFormat(
+ decimalizedTokenQty,
+ userLocale,
+ ),
+ ).toBe(returned);
+ });
+ });
+ });
});
diff --git a/cashtab/src/utils/cashMethods.js b/cashtab/src/utils/cashMethods.js
--- a/cashtab/src/utils/cashMethods.js
+++ b/cashtab/src/utils/cashMethods.js
@@ -39,8 +39,8 @@
*/
export const getHashArrayFromWallet = wallet => {
const hashArray = [];
- for (const path of wallet.paths) {
- hashArray.push(path.hash);
- }
+ wallet.paths.forEach(pathInfo => {
+ hashArray.push(pathInfo.hash);
+ });
return hashArray;
};
diff --git a/cashtab/src/utils/fixtures/vectors.js b/cashtab/src/utils/fixtures/vectors.js
new file mode 100644
--- /dev/null
+++ b/cashtab/src/utils/fixtures/vectors.js
@@ -0,0 +1,61 @@
+// Copyright (c) 2024 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+import { UNSAFE_INTEGER_STRING } from 'wallet/fixtures/vectors';
+export default {
+ decimalizedTokenQtyToLocaleFormat: {
+ expectedReturns: [
+ {
+ description: '9-decimal token',
+ decimalizedTokenQty: '100.123456789',
+ userLocale: 'en-US',
+ returned: '100.123456789',
+ },
+ {
+ description: 'Max possible eToken qty',
+ decimalizedTokenQty: UNSAFE_INTEGER_STRING,
+ userLocale: 'en-US',
+ returned: '10,000,000,000,000,000',
+ },
+ {
+ description: 'Max possible eToken qty with decimals',
+ decimalizedTokenQty: `${UNSAFE_INTEGER_STRING}.123456789`,
+ userLocale: 'en-US',
+ returned: '10,000,000,000,000,000.123456789',
+ },
+ {
+ description:
+ 'One less than max possible eToken qty with decimals',
+ decimalizedTokenQty: '9999999999999999.999999999',
+ userLocale: 'en-US',
+ returned: '9,999,999,999,999,999.999999999',
+ },
+ {
+ description: 'A pretty normal token quantity',
+ decimalizedTokenQty: '1000',
+ userLocale: 'en-US',
+ returned: '1,000',
+ },
+ {
+ description: 'Smallest possible eToken quantity',
+ decimalizedTokenQty: '0.000000001',
+ userLocale: 'en-US',
+ returned: '0.000000001',
+ },
+ {
+ description: 'Smallest possible eToken quantity, but French',
+ decimalizedTokenQty: '0.000000001',
+ userLocale: 'fr-FR',
+ returned: '0,000000001',
+ },
+ {
+ description:
+ 'One less than max possible eToken qty with decimals, but french',
+ decimalizedTokenQty: '9999999999999999.999999999',
+ userLocale: 'fr-FR',
+ returned: '9 999 999 999 999 999,999999999',
+ },
+ ],
+ },
+};
diff --git a/cashtab/src/utils/formatting.js b/cashtab/src/utils/formatting.js
--- a/cashtab/src/utils/formatting.js
+++ b/cashtab/src/utils/formatting.js
@@ -95,3 +95,45 @@
return unformattedBalance;
}
};
+
+/**
+ * Add locale number formatting to a decimalized token quantity
+ * @param {string} decimalizedTokenQty e.g. 100.123
+ * @param {string} userLocale e.g. 'en-US'
+ */
+export const decimalizedTokenQtyToLocaleFormat = (
+ decimalizedTokenQty,
+ userLocale,
+) => {
+ // Note that we cannot parseFloat(decimalizedTokenQty) because it will round some numbers at
+ // upper end of possible token quantities
+ // So, use a string method
+
+ // Get the decimal point of this locale
+ const localeDecimalSymbol = Number(1).toLocaleString(userLocale, {
+ minimumFractionDigits: 1,
+ maximumFractionDigits: 1,
+ })[1];
+
+ // Get the thousands separator of this locale
+ const localeThousandsSymbol = Number(1000).toLocaleString(userLocale, {
+ minimumFractionDigits: 0,
+ maximumFractionDigits: 0,
+ })[1];
+
+ // While we support output format in other locales, Cashtab only handles decimalized strings with '.'
+ // Split for decimals
+ const beforeAndAfterDecimalStrings = decimalizedTokenQty.split('.');
+ const beforeDecimalString = beforeAndAfterDecimalStrings[0];
+
+ // Add thousands separator to beforeDecimalString
+ let localeTokenString = beforeDecimalString.replace(
+ /\B(?=(\d{3})+(?!\d))/g,
+ localeThousandsSymbol,
+ );
+ if (beforeAndAfterDecimalStrings.length > 1) {
+ localeTokenString = `${localeTokenString}${localeDecimalSymbol}${beforeAndAfterDecimalStrings[1]}`;
+ }
+
+ return localeTokenString;
+};
diff --git a/cashtab/src/validation/fixtures/mocks.js b/cashtab/src/validation/fixtures/mocks.js
--- a/cashtab/src/validation/fixtures/mocks.js
+++ b/cashtab/src/validation/fixtures/mocks.js
@@ -52,10 +52,25 @@
},
};
-export const validWallet = {
+export const validWalletJson = {
mnemonic: 'one two three four five six seven eight nine ten eleven twelve',
name: 'test',
- paths: [{ path: 1899, address: 'string', hash: 'string', wif: 'string' }],
+ paths: [[1899, { address: 'string', hash: 'string', wif: 'string' }]],
+ state: {
+ balanceSats: 0,
+ nonSlpUtxos: [],
+ slpUtxos: [],
+ tokens: [],
+ },
+};
+
+export const validWalletJsonMultiPath = {
+ mnemonic: 'one two three four five six seven eight nine ten eleven twelve',
+ name: 'test',
+ paths: [
+ [1899, { address: 'string', hash: 'string', wif: 'string' }],
+ [145, { address: 'string', hash: 'string', wif: 'string' }],
+ ],
state: {
balanceSats: 1000,
nonSlpUtxos: [],
diff --git a/cashtab/src/validation/fixtures/vectors.js b/cashtab/src/validation/fixtures/vectors.js
--- a/cashtab/src/validation/fixtures/vectors.js
+++ b/cashtab/src/validation/fixtures/vectors.js
@@ -6,12 +6,21 @@
import appConfig from 'config/app';
import { CashtabSettings } from 'config/cashtabSettings';
import CashtabCache from 'config/CashtabCache';
-import { mockCashtabCache } from 'helpers/fixtures/mocks';
-import { validWallet } from 'validation/fixtures/mocks';
+import {
+ mockCashtabCache,
+ mockCashtabCacheNoBlocks,
+ mockCashtabCache_pre_2_9_0,
+} from 'helpers/fixtures/mocks';
+import {
+ validWalletJson,
+ validWalletJsonMultiPath,
+} from 'validation/fixtures/mocks';
+import { walletWithXecAndTokens_pre_2_9_0 } from 'components/fixtures/mocks';
import { toXec } from 'wallet';
+import { cashtabWalletFromJSON } from 'helpers';
const cloneObjectWithDeletedKey = (object, key) => {
- const clonedObject = JSON.parse(JSON.stringify(object));
+ const clonedObject = { ...object };
delete clonedObject[key];
return clonedObject;
};
@@ -854,11 +863,28 @@
cashtabCache: { tokens: {} },
isValid: false,
},
+ {
+ description: 'Returns false for cashtabCache before 2.9.0',
+ cashtabCache: mockCashtabCache_pre_2_9_0,
+ isValid: false,
+ },
+ {
+ description:
+ 'Returns false for current version cashtabCache if it is missing the unknown token id',
+ cashtabCache: { tokens: new Map() },
+ isValid: false,
+ },
{
description: 'Returns true for current version cashtabCache',
cashtabCache: mockCashtabCache,
isValid: true,
},
+ {
+ description:
+ 'Returns true for current version cashtabCache if blocks key is missing',
+ cashtabCache: mockCashtabCacheNoBlocks,
+ isValid: true,
+ },
{
description: 'Returns true for default cashtabCache',
cashtabCache: new CashtabCache(),
@@ -870,9 +896,20 @@
expectedReturns: [
{
description: 'Returns true for a valid Cashtab wallet',
- wallet: validWallet,
+ wallet: cashtabWalletFromJSON(validWalletJson),
returned: true,
},
+ {
+ description:
+ 'Returns false for a JSON-loaded pre-2.9.0 Cashtab wallet',
+ wallet: cashtabWalletFromJSON(walletWithXecAndTokens_pre_2_9_0),
+ returned: false,
+ },
+ {
+ description: 'Returns false for a pre-2.9.0 Cashtab wallet',
+ wallet: walletWithXecAndTokens_pre_2_9_0,
+ returned: false,
+ },
{
description: 'Returns false if not an object',
wallet: 'a string',
@@ -886,32 +923,50 @@
},
{
description: 'Returns false if wallet is missing state',
- wallet: cloneObjectWithDeletedKey(validWallet, 'state'),
+ wallet: cloneObjectWithDeletedKey(
+ cashtabWalletFromJSON(validWalletJson),
+ 'state',
+ ),
returned: false,
},
{
description: 'Returns false if wallet is missing mnemonic',
- wallet: cloneObjectWithDeletedKey(validWallet, 'mnemonic'),
+ wallet: cloneObjectWithDeletedKey(
+ cashtabWalletFromJSON(validWalletJson),
+ 'mnemonic',
+ ),
returned: false,
},
{
description: 'Returns false if wallet is missing name',
- wallet: cloneObjectWithDeletedKey(validWallet, 'name'),
+ wallet: cloneObjectWithDeletedKey(
+ cashtabWalletFromJSON(validWalletJson),
+ 'name',
+ ),
returned: false,
},
{
description: 'Returns false if wallet is missing paths',
- wallet: cloneObjectWithDeletedKey(validWallet, 'paths'),
+ wallet: cloneObjectWithDeletedKey(
+ cashtabWalletFromJSON(validWalletJson),
+ 'paths',
+ ),
returned: false,
},
{
description:
'Returns false if wallet is missing hash in path1899 path object',
wallet: {
- ...validWallet,
- paths: [
- cloneObjectWithDeletedKey(validWallet.paths[0], 'hash'),
- ],
+ ...cashtabWalletFromJSON(validWalletJson),
+ paths: new Map([
+ [
+ 1899,
+ {
+ address: 'string',
+ wif: 'string',
+ },
+ ],
+ ]),
},
returned: false,
},
@@ -919,54 +974,78 @@
description:
'Returns false if wallet is missing address in path1899 path object',
wallet: {
- ...validWallet,
- paths: [
- cloneObjectWithDeletedKey(
- validWallet.paths[0],
- 'address',
- ),
- ],
+ ...cashtabWalletFromJSON(validWalletJson),
+ paths: new Map([
+ [
+ 1899,
+ {
+ hash: 'string',
+ wif: 'string',
+ },
+ ],
+ ]),
},
returned: false,
},
{
description:
- 'Returns false if wallet is missing wif in path1899 path object',
+ 'Returns false if wallet is missing address in path1899 path object',
wallet: {
- ...validWallet,
- paths: [
- cloneObjectWithDeletedKey(validWallet.paths[0], 'wif'),
- ],
+ ...cashtabWalletFromJSON(validWalletJson),
+ paths: new Map([
+ [
+ 1899,
+ {
+ address: 'string',
+ hash: 'string',
+ },
+ ],
+ ]),
},
returned: false,
},
+ {
+ description: 'Returns true for a multi-path wallet',
+ wallet: cashtabWalletFromJSON(validWalletJsonMultiPath),
+ returned: true,
+ },
{
description:
'Returns false if wallet is missing wif in a secondary path object',
wallet: {
- ...validWallet,
- paths: [
- { ...validWallet.paths[0] },
- {
- ...cloneObjectWithDeletedKey(
- validWallet.paths[0],
- 'wif',
- ),
- path: 145,
- },
- ],
+ ...cashtabWalletFromJSON(validWalletJson),
+ paths: new Map([
+ [
+ 1899,
+ {
+ hash: 'string',
+ address: 'string',
+ wif: 'string',
+ },
+ ],
+ [
+ 145,
+ {
+ hash: 'string',
+ address: 'string',
+ },
+ ],
+ ]),
},
returned: false,
},
{
description: 'Returns false if wallet has no path info objects',
- wallet: { ...validWallet, paths: [] },
+ wallet: {
+ ...cashtabWalletFromJSON(validWalletJson),
+ paths: new Map(),
+ },
returned: false,
},
{
description: 'Returns false if wallet.state is not an object',
wallet: {
- ...validWallet,
+ ...cashtabWalletFromJSON(validWalletJson),
state: 'string',
},
returned: false,
@@ -974,36 +1053,45 @@
{
description: 'Returns false if no balanceSats in wallet.state',
wallet: {
- ...validWallet,
- state: cloneObjectWithDeletedKey(
- validWallet.state,
- 'balanceSats',
- ),
+ ...cashtabWalletFromJSON(validWalletJson),
+ state: {
+ ...cloneObjectWithDeletedKey(
+ cashtabWalletFromJSON(validWalletJson).state,
+ 'balanceSats',
+ ),
+ },
},
returned: false,
},
{
description: 'Returns false if balances in wallet.state',
wallet: {
- ...validWallet,
- state: { ...validWallet.state, balances: {} },
+ ...cashtabWalletFromJSON(validWalletJson),
+ state: {
+ ...cashtabWalletFromJSON(validWalletJson).state,
+ balances: {},
+ },
},
returned: false,
},
{
description: 'Returns false if balanceSats is not a number',
wallet: {
- ...validWallet,
- state: { ...validWallet.state, balanceSats: '100' },
+ ...cashtabWalletFromJSON(validWalletJson),
+ state: {
+ ...validWalletJson.state,
+ balanceSats: '100',
+ tokens: new Map(),
+ },
},
returned: false,
},
{
description: 'Returns false if no slpUtxos in wallet.state',
wallet: {
- ...validWallet,
+ ...cashtabWalletFromJSON(validWalletJson),
state: cloneObjectWithDeletedKey(
- validWallet.state,
+ cashtabWalletFromJSON(validWalletJson).state,
'slpUtxos',
),
},
@@ -1012,9 +1100,9 @@
{
description: 'Returns false if no nonSlpUtxos in wallet.state',
wallet: {
- ...validWallet,
+ ...cashtabWalletFromJSON(validWalletJson),
state: cloneObjectWithDeletedKey(
- validWallet.state,
+ cashtabWalletFromJSON(validWalletJson).state,
'nonSlpUtxos',
),
},
@@ -1023,9 +1111,9 @@
{
description: 'Returns false if no tokens in wallet.state',
wallet: {
- ...validWallet,
+ ...cashtabWalletFromJSON(validWalletJson),
state: cloneObjectWithDeletedKey(
- validWallet.state,
+ cashtabWalletFromJSON(validWalletJson).state,
'tokens',
),
},
@@ -1035,8 +1123,11 @@
description:
'Returns false if hydratedUtxoDetails is in wallet.state',
wallet: {
- ...validWallet,
- state: { ...validWallet.state, hydratedUtxoDetails: [] },
+ ...cashtabWalletFromJSON(validWalletJson),
+ state: {
+ ...cashtabWalletFromJSON(validWalletJson).state,
+ hydratedUtxoDetails: [],
+ },
},
returned: false,
},
@@ -1044,8 +1135,11 @@
description:
'Returns false if slpBalancesAndUtxos is in wallet.state',
wallet: {
- ...validWallet,
- state: { ...validWallet.state, slpBalancesAndUtxos: [] },
+ ...cashtabWalletFromJSON(validWalletJson),
+ state: {
+ ...cashtabWalletFromJSON(validWalletJson).state,
+ slpBalancesAndUtxos: [],
+ },
},
returned: false,
},
diff --git a/cashtab/src/validation/index.js b/cashtab/src/validation/index.js
--- a/cashtab/src/validation/index.js
+++ b/cashtab/src/validation/index.js
@@ -18,6 +18,7 @@
import aliasSettings from 'config/alias';
import { getAliasByteCount } from 'opreturn';
import { fiatToSatoshis } from 'wallet';
+import { UNKNOWN_TOKEN_ID } from 'config/CashtabCache';
/**
* Checks whether the instantiated sideshift library object has loaded
@@ -348,9 +349,31 @@
if (!(cashtabCache.tokens instanceof Map)) {
return false;
}
- // We do not validate all contents of the stored map, as these are from chronik
- // We assume chronik unit tests handle this
- return true;
+
+ if (typeof cashtabCache.tokens.get(UNKNOWN_TOKEN_ID) === 'undefined') {
+ // Cashtab Cache is invalid if it does not include UNKNOWN_TOKEN_ID
+ return false;
+ }
+
+ // Validate contents of map as shape may change
+
+ // Initialize flag because returning from a forEach does not do what you think it does
+ let isValidCachedInfo = true;
+
+ cashtabCache.tokens.forEach(cachedInfo => {
+ if (
+ !('tokenType' in cachedInfo) ||
+ !('genesisInfo' in cachedInfo) ||
+ !('timeFirstSeen' in cachedInfo) ||
+ !('genesisSupply' in cachedInfo) ||
+ !('genesisOutputScripts' in cachedInfo) ||
+ !('genesisMintBatons' in cachedInfo)
+ ) {
+ isValidCachedInfo = false;
+ }
+ });
+
+ return isValidCachedInfo;
};
export const isValidEtokenBurnAmount = (tokenBurnAmount, maxAmount) => {
@@ -704,21 +727,36 @@
if (!('paths' in wallet)) {
return false;
}
- if (wallet.paths.length < 1) {
+ if (Array.isArray(wallet.paths)) {
+ // wallet.paths should be a map
+ return false;
+ }
+ if (wallet.paths.size < 1) {
// Wallet must have at least one path info object
return false;
}
// Validate each path
- for (const path of wallet.paths) {
- if (
- !('path' in path) ||
- !('hash' in path) ||
- !('address' in path) ||
- !('wif' in path)
- ) {
+ // We use pathsValid as a flag as `return false` from a forEach does not do what you think it does
+ let pathsValid = true;
+ // Return false if we do not have Path1899
+ // This also handles the case of a JSON-activated pre-2.9.0 wallet
+
+ if (typeof wallet.paths.get(1899) === 'undefined') {
+ return false;
+ }
+ wallet.paths.forEach((value, key) => {
+ if (typeof key !== 'number') {
+ // Wallet is invalid if key is not a number
+ pathsValid = false;
+ }
+ if (!('hash' in value) || !('address' in value) || !('wif' in value)) {
// If any given path does not have all of these keys, the wallet is invalid
- return false;
+ pathsValid = false;
}
+ });
+ if (!pathsValid) {
+ // Invalid path
+ return false;
}
return (
typeof wallet === 'object' &&
diff --git a/cashtab/src/wallet/__tests__/index.test.js b/cashtab/src/wallet/__tests__/index.test.js
--- a/cashtab/src/wallet/__tests__/index.test.js
+++ b/cashtab/src/wallet/__tests__/index.test.js
@@ -11,6 +11,9 @@
fiatToSatoshis,
getLegacyPaths,
getWalletsForNewActiveWallet,
+ decimalizeTokenAmount,
+ undecimalizeTokenAmount,
+ removeLeadingZeros,
} from 'wallet';
import { isValidCashtabWallet } from 'validation';
import vectors from '../fixtures/vectors';
@@ -135,4 +138,60 @@
});
});
});
+ describe('We can decimalize a token amount string and undecimalize it back', () => {
+ const { expectedReturns, expectedErrors } =
+ vectors.decimalizeTokenAmount;
+ expectedReturns.forEach(expectedReturn => {
+ const { description, amount, decimals, returned } = expectedReturn;
+ it(`decimalizeTokenAmount: ${description}`, () => {
+ expect(decimalizeTokenAmount(amount, decimals)).toBe(returned);
+ });
+ it(`undecimalizeTokenAmount: ${description}`, () => {
+ expect(undecimalizeTokenAmount(returned, decimals)).toBe(
+ amount,
+ );
+ });
+ });
+ expectedErrors.forEach(expectedError => {
+ const { description, amount, decimals, error } = expectedError;
+ it(`decimalizeTokenAmount throws error for: ${description}`, () => {
+ expect(() => decimalizeTokenAmount(amount, decimals)).toThrow(
+ error,
+ );
+ });
+ });
+ });
+ describe('We can undecimalize a decimalizedTokenAmount string, and we throw expected errors if undecimalizeTokenAmount is invalid', () => {
+ const { expectedReturns, expectedErrors } =
+ vectors.undecimalizeTokenAmount;
+ expectedReturns.forEach(expectedReturn => {
+ const { description, decimalizedAmount, decimals, returned } =
+ expectedReturn;
+ it(`undecimalizeTokenAmount: ${description}`, () => {
+ expect(
+ undecimalizeTokenAmount(decimalizedAmount, decimals),
+ ).toBe(returned);
+ });
+ // Note that we cannot round trip these tests, as decimalizeTokenAmount will
+ // always return exact precision, while undecimalizeTokenAmount tolerates underprecision
+ });
+ expectedErrors.forEach(expectedError => {
+ const { description, decimalizedAmount, decimals, error } =
+ expectedError;
+ it(`undecimalizeTokenAmount throws error for: ${description}`, () => {
+ expect(() =>
+ undecimalizeTokenAmount(decimalizedAmount, decimals),
+ ).toThrow(error);
+ });
+ });
+ });
+ describe('Removes leading zeros from a string', () => {
+ const { expectedReturns } = vectors.removeLeadingZeros;
+ expectedReturns.forEach(expectedReturn => {
+ const { description, givenString, returned } = expectedReturn;
+ it(`removeLeadingZeros: ${description}`, () => {
+ expect(removeLeadingZeros(givenString)).toBe(returned);
+ });
+ });
+ });
});
diff --git a/cashtab/src/wallet/fixtures/vectors.js b/cashtab/src/wallet/fixtures/vectors.js
--- a/cashtab/src/wallet/fixtures/vectors.js
+++ b/cashtab/src/wallet/fixtures/vectors.js
@@ -2,6 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+export const UNSAFE_INTEGER_STRING = '10000000000000000';
export default {
getBalanceSatsVectors: {
expectedReturns: [
@@ -97,13 +98,12 @@
{
description:
'Returns true if wallet has token in exactly required amount',
- tokens: [
- {
- tokenId:
- '28eb601e438b1df2f49b3d783f7b236496ad9c07e4af35e8d6c5050732ef030a',
- balance: '100',
- },
- ],
+ tokens: new Map([
+ [
+ '28eb601e438b1df2f49b3d783f7b236496ad9c07e4af35e8d6c5050732ef030a',
+ '100',
+ ],
+ ]),
tokenId:
'28eb601e438b1df2f49b3d783f7b236496ad9c07e4af35e8d6c5050732ef030a',
tokenQty: '100',
@@ -112,13 +112,12 @@
{
description:
'Returns false if wallet has token but less than required amount',
- tokens: [
- {
- tokenId:
- '28eb601e438b1df2f49b3d783f7b236496ad9c07e4af35e8d6c5050732ef030a',
- balance: '99',
- },
- ],
+ tokens: new Map([
+ [
+ '28eb601e438b1df2f49b3d783f7b236496ad9c07e4af35e8d6c5050732ef030a',
+ '99',
+ ],
+ ]),
tokenId:
'28eb601e438b1df2f49b3d783f7b236496ad9c07e4af35e8d6c5050732ef030a',
tokenQty: '100',
@@ -126,13 +125,12 @@
},
{
description: 'Returns false if wallet does not have this token',
- tokens: [
- {
- tokenId:
- '28eb601e438b1df2f49b3d783f7b236496ad9c07e4af35e8d6c5050732ef030a',
- balance: '99',
- },
- ],
+ tokens: new Map([
+ [
+ '28eb601e438b1df2f49b3d783f7b236496ad9c07e4af35e8d6c5050732ef030a',
+ '99',
+ ],
+ ]),
tokenId:
'50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e',
tokenQty: '100',
@@ -152,20 +150,22 @@
balanceSats: 0,
slpUtxos: [],
nonSlpUtxos: [],
- tokens: [],
+ tokens: new Map(),
parsedTxHistory: [],
},
mnemonic:
'beauty shoe decline spend still weird slot snack coach flee between paper',
- paths: [
- {
- path: 1899,
- address:
- 'ecash:qqa9lv3kjd8vq7952p7rq0f6lkpqvlu0cydvxtd70g',
- hash: '3a5fb236934ec078b4507c303d3afd82067f8fc1',
- wif: 'KywWPgaLDwvW1tWUtUvs13jgqaaWMoNANLVYoKcK9Ddbpnch7Cmw',
- },
- ],
+ paths: new Map([
+ [
+ 1899,
+ {
+ address:
+ 'ecash:qqa9lv3kjd8vq7952p7rq0f6lkpqvlu0cydvxtd70g',
+ hash: '3a5fb236934ec078b4507c303d3afd82067f8fc1',
+ wif: 'KywWPgaLDwvW1tWUtUvs13jgqaaWMoNANLVYoKcK9Ddbpnch7Cmw',
+ },
+ ],
+ ]),
name: 'qqa9l',
},
},
@@ -227,6 +227,18 @@
},
returned: [145, 245],
},
+ {
+ description:
+ 'Determines legacy paths for a post-2.9.0 wallet with legacy paths',
+ wallet: {
+ paths: new Map([
+ [1899, { address: 'string' }],
+ [145, { address: 'string' }],
+ [245, { address: 'string' }],
+ ]),
+ },
+ returned: [145, 245],
+ },
{
description:
'Determines legacy paths for a pre-2.2.0 wallet with legacy paths',
@@ -293,4 +305,183 @@
},
],
},
+ decimalizeTokenAmount: {
+ expectedReturns: [
+ {
+ description:
+ 'Decimalizes amount for 0-decimal token amount larger than JS max safe integer',
+ amount: UNSAFE_INTEGER_STRING,
+ decimals: 0,
+ returned: UNSAFE_INTEGER_STRING,
+ },
+ {
+ description:
+ 'Decimalizes amount for 9-decimal token amount larger than JS max safe integer',
+ amount: UNSAFE_INTEGER_STRING,
+ decimals: 9,
+ returned: '10000000.000000000',
+ },
+ {
+ description:
+ 'Decimalizes amount for 9-decimal token amount larger than JS max safe integer with non-zero decimal places',
+ amount: '11111111123456789',
+ decimals: 9,
+ returned: '11111111.123456789',
+ },
+ {
+ description: 'Decimalizes 0 by adding expected decimal places',
+ amount: '0',
+ decimals: 5,
+ returned: '0.00000',
+ },
+ {
+ description:
+ 'Decimalizes a number less than 1 by adding expected decimal places',
+ amount: '123',
+ decimals: 9,
+ returned: '0.000000123',
+ },
+ {
+ description: 'Decimalizes smallest amount of slpv1 spec',
+ amount: '1',
+ decimals: 9,
+ returned: '0.000000001',
+ },
+ {
+ description:
+ 'Can decimalize for arbitrary decimals, as long as decimals is an integer',
+ amount: '11111111123456789123456789',
+ decimals: 18,
+ returned: '11111111.123456789123456789',
+ },
+ ],
+ expectedErrors: [
+ {
+ description: 'Throws error if input is not a string',
+ amount: 50,
+ decimals: 0,
+ error: 'amount must be a string',
+ },
+ {
+ description:
+ 'Throws error if input is not a stringified integer',
+ amount: '123.45',
+ decimals: 0,
+ error: 'amount must be a stringified integer',
+ },
+ {
+ description: 'Throws error if decimals is not an integer',
+ amount: '123',
+ decimals: 1.1234,
+ error: 'decimals must be an integer',
+ },
+ ],
+ },
+ undecimalizeTokenAmount: {
+ expectedReturns: [
+ {
+ description:
+ 'Returns expected amount for a 0-decimal token that has a decimal point at the end',
+ decimalizedAmount: '100.',
+ decimals: 0,
+ returned: '100',
+ },
+ {
+ description:
+ 'Handles a decimalized amount with no decimal place',
+ decimalizedAmount: '100',
+ decimals: 9,
+ returned: '100000000000',
+ },
+ {
+ description:
+ 'Handles a decimalized amount with under-specified decimal places',
+ decimalizedAmount: '100.123',
+ decimals: 9,
+ returned: '100123000000',
+ },
+ ],
+ expectedErrors: [
+ {
+ description:
+ 'Throws error if decimalizedAmount is not a string',
+ decimalizedAmount: 100,
+ decimals: 1,
+ error: 'decimalizedAmount must be a string',
+ },
+ {
+ description:
+ 'Throws error if decimalizedAmount is an empty string',
+ decimalizedAmount: '',
+ decimals: 1,
+ error: `decimalizedAmount must be a non-empty string containing only decimal numbers and optionally one decimal point "."`,
+ },
+ {
+ description:
+ 'Throws error if decimalizedAmount includes more than one decimal',
+ decimalizedAmount: '100..2',
+ decimals: 1,
+ error: `decimalizedAmount must be a non-empty string containing only decimal numbers and optionally one decimal point "."`,
+ },
+ {
+ description:
+ 'Throws error if decimalizedAmount includes a decimal point that is not a period',
+ decimalizedAmount: '100,25',
+ decimals: 1,
+ error: `decimalizedAmount must be a non-empty string containing only decimal numbers and optionally one decimal point "."`,
+ },
+ {
+ description:
+ 'Throws error if decimalizedAmount includes alphabet characters',
+ decimalizedAmount: 'not a valid decimalizedAmount',
+ decimals: 1,
+ error: `decimalizedAmount must be a non-empty string containing only decimal numbers and optionally one decimal point "."`,
+ },
+ {
+ description: 'Throws error if decimals is invalid',
+ decimalizedAmount: '100.123',
+ decimals: 1.23,
+ error: 'decimals must be an integer',
+ },
+ {
+ description:
+ 'Throws precision error if decimals are over-specified for a 0-decimal token',
+ decimalizedAmount: '100.0',
+ decimals: 0,
+ error: 'decimalizedAmount specified at greater precision than supported token decimals',
+ },
+ {
+ description:
+ 'Throws precision error if decimals are over-specified for a 9-decimal token',
+ decimalizedAmount: '100.1234567891',
+ decimals: 9,
+ error: 'decimalizedAmount specified at greater precision than supported token decimals',
+ },
+ ],
+ },
+ removeLeadingZeros: {
+ expectedReturns: [
+ {
+ description: 'Removes leading zeros from a number string',
+ givenString: '00000123',
+ returned: '123',
+ },
+ {
+ description: 'Removes leading zeros from a string of all zeros',
+ givenString: '0000000',
+ returned: '0',
+ },
+ {
+ description: 'Preserves trailing zeros',
+ givenString: '0000123000',
+ returned: '123000',
+ },
+ {
+ description:
+ 'Removes leading zeros and preserves trailing zeros from an arbitrary string',
+ givenString: '00000howaboutthisstring000',
+ returned: 'howaboutthisstring000',
+ },
+ ],
+ },
};
diff --git a/cashtab/src/wallet/index.js b/cashtab/src/wallet/index.js
--- a/cashtab/src/wallet/index.js
+++ b/cashtab/src/wallet/index.js
@@ -10,6 +10,8 @@
import appConfig from 'config/app';
const SATOSHIS_PER_XEC = 100;
+const STRINGIFIED_INTEGER_REGEX = /^[0-9]+$/;
+const STRINGIFIED_DECIMALIZED_REGEX = /^\d*\.?\d*$/;
/**
* Get total value of satoshis associated with an array of chronik utxos
@@ -57,18 +59,18 @@
/**
* Determine if a given wallet has enough of a certain token to unlock a feature
- * @param {object} tokens decimalized balance summary tokens reference from wallet.state
+ * @param {Map} tokens decimalized balance summary tokens reference from wallet.state
* @param {string} tokenId tokenId of the token we are checking
* @param {string} tokenQty quantity of the token required for unlock, decimalized string
*/
export const hasEnoughToken = (tokens, tokenId, tokenQty) => {
// Filter for tokenId
- const thisToken = tokens.filter(token => token.tokenId === tokenId);
+ const thisTokenBalance = tokens.get(tokenId);
// Confirm we have this token at all
- if (thisToken.length === 0) {
+ if (typeof thisTokenBalance === 'undefined') {
return false;
}
- return new BN(thisToken[0].balance).gte(tokenQty);
+ return new BN(thisTokenBalance).gte(tokenQty);
};
/**
@@ -85,7 +87,7 @@
balanceSats: 0,
slpUtxos: [],
nonSlpUtxos: [],
- tokens: [],
+ tokens: new Map(),
parsedTxHistory: [],
},
};
@@ -108,14 +110,14 @@
// We always derive path 1899
const pathsToDerive = [appConfig.derivationPath, ...additionalPaths];
- wallet.paths = [];
+ wallet.paths = new Map();
for (const path of pathsToDerive) {
const pathInfo = getPathInfo(masterHDNode, path);
if (path === appConfig.derivationPath) {
// Initialize wallet name with first 5 chars of Path1899 address
wallet.name = pathInfo.address.slice(6, 11);
}
- wallet.paths.push(pathInfo);
+ wallet.paths.set(path, pathInfo);
}
return wallet;
@@ -135,7 +137,6 @@
const { hash } = cashaddr.decode(address, true);
return {
- path: abbreviatedDerivationPath,
hash,
address,
wif: node.toWIF(),
@@ -175,12 +176,21 @@
export const getLegacyPaths = wallet => {
const legacyPaths = [];
if ('paths' in wallet) {
- // If we are migrating a wallet created after version 2.2.0 that includes more paths than 1899
- for (const path of wallet.paths) {
- if (path.path !== 1899) {
- // Path 1899 will be added by default, it is not an 'extra' path
- legacyPaths.push(path.path);
+ if (Array.isArray(wallet.paths)) {
+ // If we are migrating a wallet pre 2.9.0 and post 2.2.0
+ for (const path of wallet.paths) {
+ if (path.path !== 1899) {
+ // Path 1899 will be added by default, it is not an 'extra' path
+ legacyPaths.push(path.path);
+ }
}
+ } else {
+ // Cashtab wallet post 2.9.0
+ wallet.paths.forEach((pathInfo, path) => {
+ if (path !== 1899) {
+ legacyPaths.push(path);
+ }
+ });
}
}
if ('Path145' in wallet) {
@@ -225,3 +235,140 @@
// Put walletToActivate at 0-index
return [walletToActivate, ...currentWallets];
};
+
+/**
+ * Convert a token amount like one from an in-node chronik utxo to a decimalized string
+ * @param {string} amount undecimalized token amount as a string, e.g. 10012345 at 5 decimals
+ * @param {Integer} decimals
+ * @returns {string} decimalized token amount as a string, e.g. 100.12345
+ */
+export const decimalizeTokenAmount = (amount, decimals) => {
+ if (typeof amount !== 'string') {
+ throw new Error('amount must be a string');
+ }
+ if (!STRINGIFIED_INTEGER_REGEX.test(amount)) {
+ throw new Error('amount must be a stringified integer');
+ }
+ if (!Number.isInteger(decimals)) {
+ throw new Error('decimals must be an integer');
+ }
+ if (decimals === 0) {
+ // If we have 0 decimal places, and amount is a stringified integer
+ // amount is already correct
+ return amount;
+ }
+
+ // Do you need to pad with leading 0's?
+ // For example, you have have "1" with 9 decimal places
+ // This should be 0.000000001 strlength 1, decimals 9
+ // So, you must add 9 zeros before the 1 before proceeding
+ // You may have "123" with 9 decimal places strlength 3, decimals 9
+ // This should be 0.000000123
+ // So, you must add 7 zeros before the 123 before proceeding
+ if (decimals > amount.length) {
+ // We pad with decimals - amount.length 0s, plus an extra zero so we return "0.000" instead of ".000"
+ amount = `${new Array(decimals - amount.length + 1)
+ .fill(0)
+ .join('')}${amount}`;
+ }
+
+ // Insert decimal point in proper place
+ const stringAfterDecimalPoint = amount.slice(-1 * decimals);
+ const stringBeforeDecimalPoint = amount.slice(
+ 0,
+ amount.length - stringAfterDecimalPoint.length,
+ );
+ return `${stringBeforeDecimalPoint}.${stringAfterDecimalPoint}`;
+};
+
+/**
+ * Convert a decimalized token amount to an undecimalized amount
+ * Useful to perform integer math as you can use BigInt for amounts greater than Number.MAX_SAFE_INTEGER in js
+ * @param {string} decimalizedAmount decimalized token amount as a string, e.g. 100.12345 for a 5-decimals token
+ * @param {Integer} decimals
+ * @returns {string} undecimalized token amount as a string, e.g. 10012345 for a 5-decimals token
+ */
+export const undecimalizeTokenAmount = (decimalizedAmount, decimals) => {
+ if (typeof decimalizedAmount !== 'string') {
+ throw new Error('decimalizedAmount must be a string');
+ }
+ if (
+ !STRINGIFIED_DECIMALIZED_REGEX.test(decimalizedAmount) ||
+ decimalizedAmount.length === 0
+ ) {
+ throw new Error(
+ `decimalizedAmount must be a non-empty string containing only decimal numbers and optionally one decimal point "."`,
+ );
+ }
+ if (!Number.isInteger(decimals)) {
+ throw new Error('decimals must be an integer');
+ }
+
+ // If decimals is 0, we should not have a decimal point, or it should be at the very end
+ if (decimals === 0) {
+ if (!decimalizedAmount.includes('.')) {
+ // If 0 decimals and no '.' in decimalizedAmount, it's the same
+ return decimalizedAmount;
+ }
+ if (decimalizedAmount.slice(-1) !== '.') {
+ // If we have a decimal anywhere but at the very end, throw precision error
+ throw new Error(
+ 'decimalizedAmount specified at greater precision than supported token decimals',
+ );
+ }
+ // Everything before the decimal point is what we want
+ return decimalizedAmount.split('.')[0];
+ }
+
+ // How many decimal places does decimalizedAmount account for
+ const accountedDecimals = decimalizedAmount.includes('.')
+ ? decimalizedAmount.split('.')[1].length
+ : 0;
+
+ // Remove decimal point from the string
+ let undecimalizedAmountString = decimalizedAmount.split('.').join('');
+ // Remove leading zeros, if any
+ undecimalizedAmountString = removeLeadingZeros(undecimalizedAmountString);
+
+ if (accountedDecimals === decimals) {
+ // If decimalized amount is accounting for all decimals, we simply remove the decimal point
+ return undecimalizedAmountString;
+ }
+
+ const unAccountedDecimals = decimals - accountedDecimals;
+ if (unAccountedDecimals > 0) {
+ // Handle too little precision
+ // say, a token amount for a 9-decimal token is only specified at 3 decimals
+ // e.g. 100.123
+ const zerosToAdd = new Array(unAccountedDecimals).fill(0).join('');
+ return `${undecimalizedAmountString}${zerosToAdd}`;
+ }
+
+ // Do not accept too much precision
+ // say, a token amount for a 3-decimal token is specified at 5 decimals
+ // e.g. 100.12300 or 100.12345
+ // Note if it is specied at 100.12345, we have an error, really too much precision
+ throw new Error(
+ 'decimalizedAmount specified at greater precision than supported token decimals',
+ );
+};
+
+/**
+ * Remove leading '0' characters from any string
+ * @param {string} string
+ */
+export const removeLeadingZeros = givenString => {
+ let leadingZeroCount = 0;
+ // We only iterate up to the 2nd-to-last character
+ // i.e. we only iterate over "leading" characters
+ for (let i = 0; i < givenString.length - 1; i += 1) {
+ const thisChar = givenString[i];
+ if (thisChar === '0') {
+ leadingZeroCount += 1;
+ } else {
+ // Once you hit something other than '0', there are no more "leading" zeros
+ break;
+ }
+ }
+ return givenString.slice(leadingZeroCount, givenString.length);
+};

File Metadata

Mime Type
text/plain
Expires
Wed, May 21, 00:17 (1 h, 6 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5866198
Default Alt Text
D15784.id46587.diff (808 KB)

Event Timeline