@ledgerhq/coin-tezos 7.12.0 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -0
- package/lib/api/index.d.ts +1 -2
- package/lib/api/index.d.ts.map +1 -1
- package/lib/api/index.js +45 -44
- package/lib/api/index.js.map +1 -1
- package/lib/api/types.d.ts +3 -2
- package/lib/api/types.d.ts.map +1 -1
- package/lib/config.d.ts +3 -1
- package/lib/config.d.ts.map +1 -1
- package/lib/config.js.map +1 -1
- package/lib/logic/broadcast.d.ts +2 -1
- package/lib/logic/broadcast.d.ts.map +1 -1
- package/lib/logic/broadcast.js +3 -2
- package/lib/logic/broadcast.js.map +1 -1
- package/lib/logic/combine.d.ts +1 -1
- package/lib/logic/combine.d.ts.map +1 -1
- package/lib/logic/combine.js +4 -1
- package/lib/logic/combine.js.map +1 -1
- package/lib/logic/craftRawOperations.d.ts +2 -1
- package/lib/logic/craftRawOperations.d.ts.map +1 -1
- package/lib/logic/craftRawOperations.js +5 -8
- package/lib/logic/craftRawOperations.js.map +1 -1
- package/lib/logic/craftTransaction.d.ts +3 -2
- package/lib/logic/craftTransaction.d.ts.map +1 -1
- package/lib/logic/craftTransaction.js +6 -9
- package/lib/logic/craftTransaction.js.map +1 -1
- package/lib/logic/estimateFees.d.ts +2 -1
- package/lib/logic/estimateFees.d.ts.map +1 -1
- package/lib/logic/estimateFees.js +24 -19
- package/lib/logic/estimateFees.js.map +1 -1
- package/lib/logic/getBalance.d.ts +2 -1
- package/lib/logic/getBalance.d.ts.map +1 -1
- package/lib/logic/getBalance.js +7 -8
- package/lib/logic/getBalance.js.map +1 -1
- package/lib/logic/getBlock.d.ts +2 -1
- package/lib/logic/getBlock.d.ts.map +1 -1
- package/lib/logic/getBlock.js +12 -10
- package/lib/logic/getBlock.js.map +1 -1
- package/lib/logic/getBlockInfo.d.ts +2 -1
- package/lib/logic/getBlockInfo.d.ts.map +1 -1
- package/lib/logic/getBlockInfo.js +5 -3
- package/lib/logic/getBlockInfo.js.map +1 -1
- package/lib/logic/getStakes.d.ts +3 -2
- package/lib/logic/getStakes.d.ts.map +1 -1
- package/lib/logic/getStakes.js +9 -9
- package/lib/logic/getStakes.js.map +1 -1
- package/lib/logic/lastBlock.d.ts +2 -1
- package/lib/logic/lastBlock.d.ts.map +1 -1
- package/lib/logic/lastBlock.js +4 -6
- package/lib/logic/lastBlock.js.map +1 -1
- package/lib/logic/listOperations.d.ts +2 -1
- package/lib/logic/listOperations.d.ts.map +1 -1
- package/lib/logic/listOperations.js +8 -6
- package/lib/logic/listOperations.js.map +1 -1
- package/lib/logic/tezosToolkit.d.ts +2 -1
- package/lib/logic/tezosToolkit.d.ts.map +1 -1
- package/lib/logic/tezosToolkit.js +2 -6
- package/lib/logic/tezosToolkit.js.map +1 -1
- package/lib/logic/validateIntent.d.ts +2 -1
- package/lib/logic/validateIntent.d.ts.map +1 -1
- package/lib/logic/validateIntent.js +12 -13
- package/lib/logic/validateIntent.js.map +1 -1
- package/lib/network/bakers.d.ts +5 -4
- package/lib/network/bakers.d.ts.map +1 -1
- package/lib/network/bakers.js +9 -10
- package/lib/network/bakers.js.map +1 -1
- package/lib/network/index.d.ts +1 -1
- package/lib/network/index.d.ts.map +1 -1
- package/lib/network/index.js +2 -5
- package/lib/network/index.js.map +1 -1
- package/lib/network/tzkt.d.ts +16 -9
- package/lib/network/tzkt.d.ts.map +1 -1
- package/lib/network/tzkt.js +341 -333
- package/lib/network/tzkt.js.map +1 -1
- package/lib/utils.d.ts +2 -1
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +1 -6
- package/lib/utils.js.map +1 -1
- package/lib-es/api/index.d.ts +1 -2
- package/lib-es/api/index.d.ts.map +1 -1
- package/lib-es/api/index.js +40 -36
- package/lib-es/api/index.js.map +1 -1
- package/lib-es/api/types.d.ts +3 -2
- package/lib-es/api/types.d.ts.map +1 -1
- package/lib-es/config.d.ts +3 -1
- package/lib-es/config.d.ts.map +1 -1
- package/lib-es/config.js.map +1 -1
- package/lib-es/logic/broadcast.d.ts +2 -1
- package/lib-es/logic/broadcast.d.ts.map +1 -1
- package/lib-es/logic/broadcast.js +3 -2
- package/lib-es/logic/broadcast.js.map +1 -1
- package/lib-es/logic/combine.d.ts +1 -1
- package/lib-es/logic/combine.d.ts.map +1 -1
- package/lib-es/logic/combine.js +4 -1
- package/lib-es/logic/combine.js.map +1 -1
- package/lib-es/logic/craftRawOperations.d.ts +2 -1
- package/lib-es/logic/craftRawOperations.d.ts.map +1 -1
- package/lib-es/logic/craftRawOperations.js +5 -5
- package/lib-es/logic/craftRawOperations.js.map +1 -1
- package/lib-es/logic/craftTransaction.d.ts +3 -2
- package/lib-es/logic/craftTransaction.d.ts.map +1 -1
- package/lib-es/logic/craftTransaction.js +6 -6
- package/lib-es/logic/craftTransaction.js.map +1 -1
- package/lib-es/logic/estimateFees.d.ts +2 -1
- package/lib-es/logic/estimateFees.d.ts.map +1 -1
- package/lib-es/logic/estimateFees.js +24 -16
- package/lib-es/logic/estimateFees.js.map +1 -1
- package/lib-es/logic/getBalance.d.ts +2 -1
- package/lib-es/logic/getBalance.d.ts.map +1 -1
- package/lib-es/logic/getBalance.js +5 -3
- package/lib-es/logic/getBalance.js.map +1 -1
- package/lib-es/logic/getBlock.d.ts +2 -1
- package/lib-es/logic/getBlock.d.ts.map +1 -1
- package/lib-es/logic/getBlock.js +10 -8
- package/lib-es/logic/getBlock.js.map +1 -1
- package/lib-es/logic/getBlockInfo.d.ts +2 -1
- package/lib-es/logic/getBlockInfo.d.ts.map +1 -1
- package/lib-es/logic/getBlockInfo.js +4 -2
- package/lib-es/logic/getBlockInfo.js.map +1 -1
- package/lib-es/logic/getStakes.d.ts +3 -2
- package/lib-es/logic/getStakes.d.ts.map +1 -1
- package/lib-es/logic/getStakes.js +9 -6
- package/lib-es/logic/getStakes.js.map +1 -1
- package/lib-es/logic/lastBlock.d.ts +2 -1
- package/lib-es/logic/lastBlock.d.ts.map +1 -1
- package/lib-es/logic/lastBlock.js +4 -3
- package/lib-es/logic/lastBlock.js.map +1 -1
- package/lib-es/logic/listOperations.d.ts +2 -1
- package/lib-es/logic/listOperations.d.ts.map +1 -1
- package/lib-es/logic/listOperations.js +7 -5
- package/lib-es/logic/listOperations.js.map +1 -1
- package/lib-es/logic/tezosToolkit.d.ts +2 -1
- package/lib-es/logic/tezosToolkit.d.ts.map +1 -1
- package/lib-es/logic/tezosToolkit.js +2 -3
- package/lib-es/logic/tezosToolkit.js.map +1 -1
- package/lib-es/logic/validateIntent.d.ts +2 -1
- package/lib-es/logic/validateIntent.d.ts.map +1 -1
- package/lib-es/logic/validateIntent.js +10 -8
- package/lib-es/logic/validateIntent.js.map +1 -1
- package/lib-es/network/bakers.d.ts +5 -4
- package/lib-es/network/bakers.d.ts.map +1 -1
- package/lib-es/network/bakers.js +9 -10
- package/lib-es/network/bakers.js.map +1 -1
- package/lib-es/network/index.d.ts +1 -1
- package/lib-es/network/index.d.ts.map +1 -1
- package/lib-es/network/index.js +1 -1
- package/lib-es/network/index.js.map +1 -1
- package/lib-es/network/tzkt.d.ts +16 -9
- package/lib-es/network/tzkt.d.ts.map +1 -1
- package/lib-es/network/tzkt.js +340 -333
- package/lib-es/network/tzkt.js.map +1 -1
- package/lib-es/utils.d.ts +2 -1
- package/lib-es/utils.d.ts.map +1 -1
- package/lib-es/utils.js +1 -3
- package/lib-es/utils.js.map +1 -1
- package/package.json +2 -2
- package/src/api/index-mainnet.integ.test.ts +34 -30
- package/src/api/index.integ.test.ts +69 -53
- package/src/api/index.test.ts +99 -60
- package/src/api/index.ts +52 -36
- package/src/api/types.ts +3 -2
- package/src/config.ts +4 -1
- package/src/logic/broadcast.integ.test.ts +12 -13
- package/src/logic/broadcast.ts +4 -2
- package/src/logic/combine.test.ts +17 -0
- package/src/logic/combine.ts +5 -2
- package/src/logic/craftRawOperations.test.ts +47 -33
- package/src/logic/craftRawOperations.ts +6 -4
- package/src/logic/craftTransaction.integ.test.ts +12 -5
- package/src/logic/craftTransaction.test.ts +39 -31
- package/src/logic/craftTransaction.ts +10 -5
- package/src/logic/estimateFees.integ.test.ts +7 -7
- package/src/logic/estimateFees.test.ts +52 -49
- package/src/logic/estimateFees.ts +34 -22
- package/src/logic/getBalance.test.ts +19 -17
- package/src/logic/getBalance.ts +6 -3
- package/src/logic/getBlock.integ.test.ts +8 -30
- package/src/logic/getBlock.test.ts +91 -81
- package/src/logic/getBlock.ts +11 -8
- package/src/logic/getBlockInfo.integ.test.ts +9 -18
- package/src/logic/getBlockInfo.test.ts +19 -9
- package/src/logic/getBlockInfo.ts +5 -2
- package/src/logic/getStakes.test.ts +46 -49
- package/src/logic/getStakes.ts +14 -5
- package/src/logic/lastBlock.ts +5 -3
- package/src/logic/listOperations.integ.test.ts +40 -67
- package/src/logic/listOperations.test.ts +65 -59
- package/src/logic/listOperations.ts +8 -3
- package/src/logic/tezosToolkit.ts +3 -3
- package/src/logic/validateIntent.test.ts +78 -74
- package/src/logic/validateIntent.ts +17 -7
- package/src/network/bakers.integ.test.ts +2 -5
- package/src/network/bakers.test.ts +5 -6
- package/src/network/bakers.ts +13 -10
- package/src/network/index.ts +2 -1
- package/src/network/tzkt.integ.test.ts +3 -14
- package/src/network/tzkt.test.ts +128 -96
- package/src/network/tzkt.ts +426 -393
- package/src/utils.ts +2 -3
|
@@ -4,13 +4,16 @@
|
|
|
4
4
|
import type { TezosCoinConfig } from '../config'
|
|
5
5
|
import type { TezosApiBaker } from './bakers'
|
|
6
6
|
import network from '@ledgerhq/live-network/network'
|
|
7
|
-
import coinConfig from '../config'
|
|
8
7
|
import { mockConfig } from '../test/config'
|
|
9
8
|
import { asBaker, cache } from './bakers'
|
|
10
9
|
|
|
11
10
|
jest.mock('@ledgerhq/live-network/network')
|
|
12
11
|
const mockedNetwork = jest.mocked(network)
|
|
13
12
|
|
|
13
|
+
// `cache` is keyed by config (its LRU resolver is `config.baker.url`), so it must be called with a
|
|
14
|
+
// config. Previously the config was provided via `coinConfig.setCoinConfig(...)`.
|
|
15
|
+
const config = mockConfig as TezosCoinConfig
|
|
16
|
+
|
|
14
17
|
const data: TezosApiBaker[] = [
|
|
15
18
|
{
|
|
16
19
|
address: 'tz1Kf25fX1VdmYGSEzwFy1wNmkbSEZ2V83sY',
|
|
@@ -167,10 +170,6 @@ const data: TezosApiBaker[] = [
|
|
|
167
170
|
]
|
|
168
171
|
|
|
169
172
|
describe('Tezos Baker', () => {
|
|
170
|
-
beforeAll(() => {
|
|
171
|
-
coinConfig.setCoinConfig((): TezosCoinConfig => mockConfig as TezosCoinConfig)
|
|
172
|
-
})
|
|
173
|
-
|
|
174
173
|
afterEach(() => {
|
|
175
174
|
jest.clearAllMocks()
|
|
176
175
|
cache.reset()
|
|
@@ -192,7 +191,7 @@ describe('Tezos Baker', () => {
|
|
|
192
191
|
})
|
|
193
192
|
|
|
194
193
|
it('Ledger Baker should be first in the list', async () => {
|
|
195
|
-
const bakers = await cache()
|
|
194
|
+
const bakers = await cache(config)
|
|
196
195
|
expect(bakers[0].name).toBe('Ledger by Kiln')
|
|
197
196
|
})
|
|
198
197
|
})
|
package/src/network/bakers.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// SPDX-FileCopyrightText: © 2026 LEDGER SAS
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
|
+
import type { TezosCoinConfig } from '../config'
|
|
4
5
|
import type { Baker } from '../types'
|
|
5
6
|
import { makeLRUCache } from '@ledgerhq/live-network/cache'
|
|
6
7
|
import network from '@ledgerhq/live-network/network'
|
|
7
8
|
import { log } from '@ledgerhq/logs'
|
|
8
|
-
import coinConfig from '../config'
|
|
9
9
|
import { ledgerValidatorAddress } from './bakers.whitelist-default'
|
|
10
10
|
|
|
11
11
|
export type TezosApiBaker = {
|
|
@@ -40,9 +40,9 @@ export type TezosBakerFeature = {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
export const cache = makeLRUCache(
|
|
43
|
-
async (): Promise<Baker[]> => {
|
|
43
|
+
async (config: TezosCoinConfig): Promise<Baker[]> => {
|
|
44
44
|
const bakers: Baker[] = []
|
|
45
|
-
const TEZOS_API_BASE_URL =
|
|
45
|
+
const TEZOS_API_BASE_URL = config.baker.url
|
|
46
46
|
const { data } = await network<TezosApiBaker[]>({
|
|
47
47
|
url: `${TEZOS_API_BASE_URL}/v3/bakers`,
|
|
48
48
|
})
|
|
@@ -67,13 +67,13 @@ export const cache = makeLRUCache(
|
|
|
67
67
|
log('tezos/bakers', 'loaded ' + bakers.length + ' bakers')
|
|
68
68
|
return [ledgerBaker, ...bakers]
|
|
69
69
|
},
|
|
70
|
-
() =>
|
|
70
|
+
(config: TezosCoinConfig) => config.baker.url
|
|
71
71
|
)
|
|
72
72
|
|
|
73
73
|
let _lastBakers: Baker[] = []
|
|
74
74
|
|
|
75
|
-
export const fetchAllBakers = async (): Promise<Baker[]> => {
|
|
76
|
-
const allBakers = await cache.force()
|
|
75
|
+
export const fetchAllBakers = async (config: TezosCoinConfig): Promise<Baker[]> => {
|
|
76
|
+
const allBakers = await cache.force(config)
|
|
77
77
|
_lastBakers = allBakers
|
|
78
78
|
return allBakers
|
|
79
79
|
}
|
|
@@ -85,8 +85,11 @@ export const listBakersWithDefault = (whitelistAddresses: string[]): Baker[] =>
|
|
|
85
85
|
return whitelist(_lastBakers, whitelistAddresses)
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
export const listBakers = async (
|
|
89
|
-
|
|
88
|
+
export const listBakers = async (
|
|
89
|
+
config: TezosCoinConfig,
|
|
90
|
+
whitelistAddresses: string[]
|
|
91
|
+
): Promise<Baker[]> => {
|
|
92
|
+
_lastBakers = await cache(config)
|
|
90
93
|
return whitelist(_lastBakers, whitelistAddresses)
|
|
91
94
|
}
|
|
92
95
|
|
|
@@ -94,10 +97,10 @@ export function getBakerSync(addr: string): Baker | undefined {
|
|
|
94
97
|
return _lastBakers.find((baker) => baker.address === addr)
|
|
95
98
|
}
|
|
96
99
|
|
|
97
|
-
export async function loadBaker(addr: string): Promise<Baker | undefined> {
|
|
100
|
+
export async function loadBaker(config: TezosCoinConfig, addr: string): Promise<Baker | undefined> {
|
|
98
101
|
const cacheBaker = getBakerSync(addr)
|
|
99
102
|
if (cacheBaker) return cacheBaker
|
|
100
|
-
const bakers = await cache()
|
|
103
|
+
const bakers = await cache(config)
|
|
101
104
|
const baker = bakers.find((baker) => baker.address === addr)
|
|
102
105
|
return baker
|
|
103
106
|
}
|
package/src/network/index.ts
CHANGED
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
4
|
import type { TezosCoinConfig } from '../config'
|
|
5
|
-
import
|
|
6
|
-
import api from './tzkt'
|
|
5
|
+
import { createTzktApi } from './tzkt'
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* Mainnet integration tests for multi-asset FA2 support (LIVE-29210).
|
|
@@ -33,18 +32,8 @@ const mainnetConfig = (): TezosCoinConfig =>
|
|
|
33
32
|
}) as TezosCoinConfig
|
|
34
33
|
|
|
35
34
|
describe('TzKT multi-asset FA2 — mainnet', () => {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
beforeAll(() => {
|
|
39
|
-
originalGetCoinConfig = coinConfig.getCoinConfig
|
|
40
|
-
coinConfig.setCoinConfig(mainnetConfig)
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
afterAll(() => {
|
|
44
|
-
if (originalGetCoinConfig) {
|
|
45
|
-
coinConfig.setCoinConfig(originalGetCoinConfig)
|
|
46
|
-
}
|
|
47
|
-
})
|
|
35
|
+
const config: TezosCoinConfig = mainnetConfig()
|
|
36
|
+
const api = createTzktApi(config)
|
|
48
37
|
|
|
49
38
|
describe('getTokensBalances', () => {
|
|
50
39
|
it('returns balances for multiple tokenIds on the same contract', async () => {
|
package/src/network/tzkt.test.ts
CHANGED
|
@@ -13,15 +13,13 @@ import type {
|
|
|
13
13
|
APITokenBalance,
|
|
14
14
|
APITokenTransfer,
|
|
15
15
|
APITransactionType,
|
|
16
|
-
AccountsGetOperationsOptions,
|
|
17
16
|
} from './types'
|
|
18
17
|
// tzkt.ts imports `network` from "@ledgerhq/live-network" (the package root, not the /network
|
|
19
18
|
// subpath). We mock the same path so Jest's module registry intercepts those calls.
|
|
20
19
|
import network from '@ledgerhq/live-network'
|
|
21
20
|
import { log } from '@ledgerhq/logs'
|
|
22
|
-
import coinConfig from '../config'
|
|
23
21
|
import { mockConfig } from '../test/config'
|
|
24
|
-
import
|
|
22
|
+
import { createTzktApi } from './tzkt'
|
|
25
23
|
import {
|
|
26
24
|
fetchAllTransactions,
|
|
27
25
|
fetchBlockDelegations,
|
|
@@ -35,6 +33,18 @@ jest.mock('@ledgerhq/logs')
|
|
|
35
33
|
const mockedNetwork = jest.mocked(network)
|
|
36
34
|
const mockedLog = jest.mocked(log)
|
|
37
35
|
|
|
36
|
+
// The tzkt module is NOT mocked here. `createTzktApi(config)` returns a plain object whose methods
|
|
37
|
+
// close over `config.explorer.url` and delegate to the mocked `network`. Each method also calls its
|
|
38
|
+
// sibling methods through this same object (closure, not `this`), so spying on the instance's
|
|
39
|
+
// methods (see `spyOnApi`) intercepts intra-object calls such as `getAccountTokenTransfers` →
|
|
40
|
+
// `getOperationsTransactions`.
|
|
41
|
+
//
|
|
42
|
+
// The paginated helpers (`fetchAllTransactions`, `fetchBlock*`) are top-level functions that build
|
|
43
|
+
// their OWN fresh `createTzktApi(config)` instance internally, so spying on `api` cannot intercept
|
|
44
|
+
// them. Those tests therefore drive the mocked `network` directly.
|
|
45
|
+
const config = mockConfig as TezosCoinConfig
|
|
46
|
+
const api = createTzktApi(config)
|
|
47
|
+
|
|
38
48
|
// ---------------------------------------------------------------------------
|
|
39
49
|
// Helpers
|
|
40
50
|
// ---------------------------------------------------------------------------
|
|
@@ -106,10 +116,6 @@ function spyOnApi<K extends keyof typeof api>(method: K) {
|
|
|
106
116
|
// ---------------------------------------------------------------------------
|
|
107
117
|
|
|
108
118
|
describe('tzkt network API', () => {
|
|
109
|
-
beforeAll(() => {
|
|
110
|
-
coinConfig.setCoinConfig((): TezosCoinConfig => mockConfig as TezosCoinConfig)
|
|
111
|
-
})
|
|
112
|
-
|
|
113
119
|
afterEach(() => {
|
|
114
120
|
localSpies.splice(0).forEach((spy) => spy.mockRestore())
|
|
115
121
|
jest.clearAllMocks()
|
|
@@ -847,59 +853,63 @@ describe('tzkt network API', () => {
|
|
|
847
853
|
// fetchAllTransactions
|
|
848
854
|
// -------------------------------------------------------------------------
|
|
849
855
|
|
|
856
|
+
// `fetchAllTransactions` builds its own internal `createTzktApi(config)` instance and calls
|
|
857
|
+
// `getAccountOperations` on it, so a spy on the local `api` cannot intercept it. Instead we drive
|
|
858
|
+
// the mocked `network`: each `getAccountOperations` call maps to exactly one `network(...)` whose
|
|
859
|
+
// `.data` is the page. The page cursor (`lastId`) is serialized into the request URL.
|
|
850
860
|
describe('fetchAllTransactions', () => {
|
|
851
861
|
it('returns empty when the first page is empty', async () => {
|
|
852
|
-
|
|
862
|
+
mockedNetwork.mockReturnValue(networkResponse([]) as ReturnType<typeof network>)
|
|
853
863
|
|
|
854
|
-
const result = await fetchAllTransactions('tz1acc')
|
|
864
|
+
const result = await fetchAllTransactions(config, 'tz1acc')
|
|
855
865
|
|
|
856
866
|
expect(result).toEqual([])
|
|
857
867
|
})
|
|
858
868
|
|
|
859
869
|
it('concatenates pages until an empty response', async () => {
|
|
860
|
-
|
|
861
|
-
.
|
|
862
|
-
.
|
|
863
|
-
.
|
|
864
|
-
.mockResolvedValueOnce([])
|
|
870
|
+
mockedNetwork
|
|
871
|
+
.mockReturnValueOnce(networkResponse([makeOperation(1)]) as ReturnType<typeof network>)
|
|
872
|
+
.mockReturnValueOnce(networkResponse([makeOperation(2)]) as ReturnType<typeof network>)
|
|
873
|
+
.mockReturnValueOnce(networkResponse([]) as ReturnType<typeof network>)
|
|
865
874
|
|
|
866
|
-
const result = await fetchAllTransactions('tz1acc')
|
|
875
|
+
const result = await fetchAllTransactions(config, 'tz1acc')
|
|
867
876
|
|
|
868
877
|
expect(result).toEqual([makeOperation(1), makeOperation(2)])
|
|
869
|
-
expect(
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
expect(
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
878
|
+
expect(mockedNetwork).toHaveBeenCalledTimes(3)
|
|
879
|
+
// First page: no cursor (lastId undefined is stripped from the query), sort ascending.
|
|
880
|
+
const firstUrl = (mockedNetwork.mock.calls[0][0] as { url: string }).url
|
|
881
|
+
expect(firstUrl).toContain('/v1/accounts/tz1acc/operations')
|
|
882
|
+
expect(firstUrl).not.toMatch(/lastId=/)
|
|
883
|
+
expect(firstUrl).toContain('sort=Ascending')
|
|
884
|
+
expect(firstUrl).toContain('level.ge=0')
|
|
885
|
+
// Second page: cursor advances to the id of the last op returned by the first page.
|
|
886
|
+
const secondUrl = (mockedNetwork.mock.calls[1][0] as { url: string }).url
|
|
887
|
+
expect(secondUrl).toContain('lastId=1')
|
|
888
|
+
expect(secondUrl).toContain('sort=Ascending')
|
|
889
|
+
expect(secondUrl).toContain('level.ge=0')
|
|
880
890
|
})
|
|
881
891
|
|
|
882
892
|
it('logs and returns when the last operation has a falsy id', async () => {
|
|
883
893
|
const opMissingId = { ...makeOperation(1), id: 0 } as APIOperation
|
|
884
|
-
|
|
894
|
+
mockedNetwork.mockReturnValue(networkResponse([opMissingId]) as ReturnType<typeof network>)
|
|
885
895
|
|
|
886
|
-
const result = await fetchAllTransactions('tz1acc')
|
|
896
|
+
const result = await fetchAllTransactions(config, 'tz1acc')
|
|
887
897
|
|
|
888
898
|
expect(result).toEqual([opMissingId])
|
|
889
899
|
expect(mockedLog).toHaveBeenCalledWith('tezos', 'id missing!')
|
|
890
900
|
})
|
|
891
901
|
|
|
892
902
|
it('stops after maxTxQuery iterations', async () => {
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
903
|
+
// Always return one op with a truthy id so the loop would continue without the cap. The id
|
|
904
|
+
// increases every call so cursors keep advancing (matching the previous spy implementation).
|
|
905
|
+
let nextId = 0
|
|
906
|
+
mockedNetwork.mockImplementation(
|
|
907
|
+
() => networkResponse([makeOperation(++nextId)]) as ReturnType<typeof network>
|
|
908
|
+
)
|
|
899
909
|
|
|
900
|
-
const result = await fetchAllTransactions('tz1acc')
|
|
910
|
+
const result = await fetchAllTransactions(config, 'tz1acc')
|
|
901
911
|
|
|
902
|
-
expect(
|
|
912
|
+
expect(mockedNetwork).toHaveBeenCalledTimes(mockConfig.explorer.maxTxQuery)
|
|
903
913
|
expect(result).toHaveLength(mockConfig.explorer.maxTxQuery)
|
|
904
914
|
})
|
|
905
915
|
})
|
|
@@ -1032,20 +1042,23 @@ describe('tzkt network API', () => {
|
|
|
1032
1042
|
// fetchBlockTransactions — pagination logic
|
|
1033
1043
|
// -------------------------------------------------------------------------
|
|
1034
1044
|
|
|
1045
|
+
// `fetchBlockTransactions` builds its own internal `createTzktApi(config)` and calls
|
|
1046
|
+
// `getBlockTransactionsPage` on it, so a spy on the local `api` cannot intercept it. Each page
|
|
1047
|
+
// fetch maps to one `network(...)`; the cursor is passed through as the `offset.cr` param.
|
|
1035
1048
|
describe('fetchBlockTransactions', () => {
|
|
1036
1049
|
it('returns an empty array when the first page is empty', async () => {
|
|
1037
|
-
|
|
1050
|
+
mockedNetwork.mockReturnValue(networkResponse([]) as ReturnType<typeof network>)
|
|
1038
1051
|
|
|
1039
|
-
const result = await fetchBlockTransactions(100)
|
|
1052
|
+
const result = await fetchBlockTransactions(config, 100)
|
|
1040
1053
|
|
|
1041
1054
|
expect(result).toEqual([])
|
|
1042
1055
|
})
|
|
1043
1056
|
|
|
1044
1057
|
it('returns a single page when the page is smaller than the page size', async () => {
|
|
1045
1058
|
const txs = [makeTxItem(1), makeTxItem(2)]
|
|
1046
|
-
|
|
1059
|
+
mockedNetwork.mockReturnValue(networkResponse(txs) as ReturnType<typeof network>)
|
|
1047
1060
|
|
|
1048
|
-
const result = await fetchBlockTransactions(100)
|
|
1061
|
+
const result = await fetchBlockTransactions(config, 100)
|
|
1049
1062
|
|
|
1050
1063
|
expect(result).toEqual(txs)
|
|
1051
1064
|
})
|
|
@@ -1054,28 +1067,32 @@ describe('tzkt network API', () => {
|
|
|
1054
1067
|
const fullPage = Array.from({ length: 1000 }, (_, i) => makeTxItem(i + 1))
|
|
1055
1068
|
const lastPage = [makeTxItem(1001), makeTxItem(1002)]
|
|
1056
1069
|
|
|
1057
|
-
|
|
1058
|
-
.
|
|
1059
|
-
.
|
|
1060
|
-
.mockResolvedValueOnce(lastPage)
|
|
1070
|
+
mockedNetwork
|
|
1071
|
+
.mockReturnValueOnce(networkResponse(fullPage) as ReturnType<typeof network>)
|
|
1072
|
+
.mockReturnValueOnce(networkResponse(lastPage) as ReturnType<typeof network>)
|
|
1061
1073
|
|
|
1062
|
-
const result = await fetchBlockTransactions(100)
|
|
1074
|
+
const result = await fetchBlockTransactions(config, 100)
|
|
1063
1075
|
|
|
1064
1076
|
expect(result).toHaveLength(1002)
|
|
1065
|
-
expect(
|
|
1066
|
-
|
|
1077
|
+
expect(mockedNetwork).toHaveBeenCalledTimes(2)
|
|
1078
|
+
const firstParams = (mockedNetwork.mock.calls[0][0] as { params: Record<string, unknown> })
|
|
1079
|
+
.params
|
|
1080
|
+
expect(firstParams).toMatchObject({ level: 100 })
|
|
1081
|
+
expect(firstParams).not.toHaveProperty('offset.cr')
|
|
1067
1082
|
// cursor = last item id of first page = 1000
|
|
1068
|
-
|
|
1083
|
+
const secondParams = (mockedNetwork.mock.calls[1][0] as { params: Record<string, unknown> })
|
|
1084
|
+
.params
|
|
1085
|
+
expect(secondParams).toMatchObject({ level: 100, 'offset.cr': 1000 })
|
|
1069
1086
|
})
|
|
1070
1087
|
|
|
1071
1088
|
it('stops after maxTxQuery iterations regardless of page length', async () => {
|
|
1072
1089
|
// maxTxQuery = 100 (from mockConfig); every call returns a full page to keep the loop going
|
|
1073
1090
|
const fullPage = Array.from({ length: 1000 }, (_, i) => makeTxItem(i + 1))
|
|
1074
|
-
|
|
1091
|
+
mockedNetwork.mockReturnValue(networkResponse(fullPage) as ReturnType<typeof network>)
|
|
1075
1092
|
|
|
1076
|
-
const result = await fetchBlockTransactions(100)
|
|
1093
|
+
const result = await fetchBlockTransactions(config, 100)
|
|
1077
1094
|
|
|
1078
|
-
expect(
|
|
1095
|
+
expect(mockedNetwork).toHaveBeenCalledTimes(100)
|
|
1079
1096
|
expect(result).toHaveLength(100_000)
|
|
1080
1097
|
expect(mockedLog).toHaveBeenCalledWith(
|
|
1081
1098
|
'tezos',
|
|
@@ -1088,20 +1105,21 @@ describe('tzkt network API', () => {
|
|
|
1088
1105
|
// fetchBlockTokenTransfers — pagination logic
|
|
1089
1106
|
// -------------------------------------------------------------------------
|
|
1090
1107
|
|
|
1108
|
+
// Driven through the mocked `network` (see the note on `fetchBlockTransactions`).
|
|
1091
1109
|
describe('fetchBlockTokenTransfers', () => {
|
|
1092
1110
|
it('returns an empty array when the first page is empty', async () => {
|
|
1093
|
-
|
|
1111
|
+
mockedNetwork.mockReturnValue(networkResponse([]) as ReturnType<typeof network>)
|
|
1094
1112
|
|
|
1095
|
-
const result = await fetchBlockTokenTransfers(100)
|
|
1113
|
+
const result = await fetchBlockTokenTransfers(config, 100)
|
|
1096
1114
|
|
|
1097
1115
|
expect(result).toEqual([])
|
|
1098
1116
|
})
|
|
1099
1117
|
|
|
1100
1118
|
it('returns a single page when the page is smaller than the page size', async () => {
|
|
1101
1119
|
const items = [makeTokenItem(1), makeTokenItem(2)]
|
|
1102
|
-
|
|
1120
|
+
mockedNetwork.mockReturnValue(networkResponse(items) as ReturnType<typeof network>)
|
|
1103
1121
|
|
|
1104
|
-
const result = await fetchBlockTokenTransfers(100)
|
|
1122
|
+
const result = await fetchBlockTokenTransfers(config, 100)
|
|
1105
1123
|
|
|
1106
1124
|
expect(result).toEqual(items)
|
|
1107
1125
|
})
|
|
@@ -1110,26 +1128,30 @@ describe('tzkt network API', () => {
|
|
|
1110
1128
|
const fullPage = Array.from({ length: 1000 }, (_, i) => makeTokenItem(i + 1))
|
|
1111
1129
|
const lastPage = [makeTokenItem(1001)]
|
|
1112
1130
|
|
|
1113
|
-
|
|
1114
|
-
.
|
|
1115
|
-
.
|
|
1116
|
-
.mockResolvedValueOnce(lastPage)
|
|
1131
|
+
mockedNetwork
|
|
1132
|
+
.mockReturnValueOnce(networkResponse(fullPage) as ReturnType<typeof network>)
|
|
1133
|
+
.mockReturnValueOnce(networkResponse(lastPage) as ReturnType<typeof network>)
|
|
1117
1134
|
|
|
1118
|
-
const result = await fetchBlockTokenTransfers(100)
|
|
1135
|
+
const result = await fetchBlockTokenTransfers(config, 100)
|
|
1119
1136
|
|
|
1120
1137
|
expect(result).toHaveLength(1001)
|
|
1121
|
-
expect(
|
|
1122
|
-
|
|
1123
|
-
|
|
1138
|
+
expect(mockedNetwork).toHaveBeenCalledTimes(2)
|
|
1139
|
+
const firstParams = (mockedNetwork.mock.calls[0][0] as { params: Record<string, unknown> })
|
|
1140
|
+
.params
|
|
1141
|
+
expect(firstParams).toMatchObject({ level: 100 })
|
|
1142
|
+
expect(firstParams).not.toHaveProperty('offset.cr')
|
|
1143
|
+
const secondParams = (mockedNetwork.mock.calls[1][0] as { params: Record<string, unknown> })
|
|
1144
|
+
.params
|
|
1145
|
+
expect(secondParams).toMatchObject({ level: 100, 'offset.cr': 1000 })
|
|
1124
1146
|
})
|
|
1125
1147
|
|
|
1126
1148
|
it('stops after maxTxQuery iterations regardless of page length', async () => {
|
|
1127
1149
|
const fullPage = Array.from({ length: 1000 }, (_, i) => makeTokenItem(i + 1))
|
|
1128
|
-
|
|
1150
|
+
mockedNetwork.mockReturnValue(networkResponse(fullPage) as ReturnType<typeof network>)
|
|
1129
1151
|
|
|
1130
|
-
const result = await fetchBlockTokenTransfers(100)
|
|
1152
|
+
const result = await fetchBlockTokenTransfers(config, 100)
|
|
1131
1153
|
|
|
1132
|
-
expect(
|
|
1154
|
+
expect(mockedNetwork).toHaveBeenCalledTimes(100)
|
|
1133
1155
|
expect(result).toHaveLength(100_000)
|
|
1134
1156
|
expect(mockedLog).toHaveBeenCalledWith(
|
|
1135
1157
|
'tezos',
|
|
@@ -1181,20 +1203,21 @@ describe('tzkt network API', () => {
|
|
|
1181
1203
|
// fetchBlockDelegations — pagination logic
|
|
1182
1204
|
// -------------------------------------------------------------------------
|
|
1183
1205
|
|
|
1206
|
+
// Driven through the mocked `network` (see the note on `fetchBlockTransactions`).
|
|
1184
1207
|
describe('fetchBlockDelegations', () => {
|
|
1185
1208
|
it('returns an empty array when the first page is empty', async () => {
|
|
1186
|
-
|
|
1209
|
+
mockedNetwork.mockReturnValue(networkResponse([]) as ReturnType<typeof network>)
|
|
1187
1210
|
|
|
1188
|
-
const result = await fetchBlockDelegations(100)
|
|
1211
|
+
const result = await fetchBlockDelegations(config, 100)
|
|
1189
1212
|
|
|
1190
1213
|
expect(result).toEqual([])
|
|
1191
1214
|
})
|
|
1192
1215
|
|
|
1193
1216
|
it('returns a single page when the page is smaller than the page size', async () => {
|
|
1194
1217
|
const items = [makeDelegationItem(1), makeDelegationItem(2)]
|
|
1195
|
-
|
|
1218
|
+
mockedNetwork.mockReturnValue(networkResponse(items) as ReturnType<typeof network>)
|
|
1196
1219
|
|
|
1197
|
-
const result = await fetchBlockDelegations(100)
|
|
1220
|
+
const result = await fetchBlockDelegations(config, 100)
|
|
1198
1221
|
|
|
1199
1222
|
expect(result).toEqual(items)
|
|
1200
1223
|
})
|
|
@@ -1203,26 +1226,30 @@ describe('tzkt network API', () => {
|
|
|
1203
1226
|
const fullPage = Array.from({ length: 1000 }, (_, i) => makeDelegationItem(i + 1))
|
|
1204
1227
|
const lastPage = [makeDelegationItem(1001)]
|
|
1205
1228
|
|
|
1206
|
-
|
|
1207
|
-
.
|
|
1208
|
-
.
|
|
1209
|
-
.mockResolvedValueOnce(lastPage)
|
|
1229
|
+
mockedNetwork
|
|
1230
|
+
.mockReturnValueOnce(networkResponse(fullPage) as ReturnType<typeof network>)
|
|
1231
|
+
.mockReturnValueOnce(networkResponse(lastPage) as ReturnType<typeof network>)
|
|
1210
1232
|
|
|
1211
|
-
const result = await fetchBlockDelegations(100)
|
|
1233
|
+
const result = await fetchBlockDelegations(config, 100)
|
|
1212
1234
|
|
|
1213
1235
|
expect(result).toHaveLength(1001)
|
|
1214
|
-
expect(
|
|
1215
|
-
|
|
1216
|
-
|
|
1236
|
+
expect(mockedNetwork).toHaveBeenCalledTimes(2)
|
|
1237
|
+
const firstParams = (mockedNetwork.mock.calls[0][0] as { params: Record<string, unknown> })
|
|
1238
|
+
.params
|
|
1239
|
+
expect(firstParams).toMatchObject({ level: 100 })
|
|
1240
|
+
expect(firstParams).not.toHaveProperty('offset.cr')
|
|
1241
|
+
const secondParams = (mockedNetwork.mock.calls[1][0] as { params: Record<string, unknown> })
|
|
1242
|
+
.params
|
|
1243
|
+
expect(secondParams).toMatchObject({ level: 100, 'offset.cr': 1000 })
|
|
1217
1244
|
})
|
|
1218
1245
|
|
|
1219
1246
|
it('stops after maxTxQuery iterations regardless of page length', async () => {
|
|
1220
1247
|
const fullPage = Array.from({ length: 1000 }, (_, i) => makeDelegationItem(i + 1))
|
|
1221
|
-
|
|
1248
|
+
mockedNetwork.mockReturnValue(networkResponse(fullPage) as ReturnType<typeof network>)
|
|
1222
1249
|
|
|
1223
|
-
const result = await fetchBlockDelegations(100)
|
|
1250
|
+
const result = await fetchBlockDelegations(config, 100)
|
|
1224
1251
|
|
|
1225
|
-
expect(
|
|
1252
|
+
expect(mockedNetwork).toHaveBeenCalledTimes(100)
|
|
1226
1253
|
expect(result).toHaveLength(100_000)
|
|
1227
1254
|
expect(mockedLog).toHaveBeenCalledWith(
|
|
1228
1255
|
'tezos',
|
|
@@ -1274,20 +1301,21 @@ describe('tzkt network API', () => {
|
|
|
1274
1301
|
// fetchBlockStaking — pagination logic
|
|
1275
1302
|
// -------------------------------------------------------------------------
|
|
1276
1303
|
|
|
1304
|
+
// Driven through the mocked `network` (see the note on `fetchBlockTransactions`).
|
|
1277
1305
|
describe('fetchBlockStaking', () => {
|
|
1278
1306
|
it('returns an empty array when the first page is empty', async () => {
|
|
1279
|
-
|
|
1307
|
+
mockedNetwork.mockReturnValue(networkResponse([]) as ReturnType<typeof network>)
|
|
1280
1308
|
|
|
1281
|
-
const result = await fetchBlockStaking(100)
|
|
1309
|
+
const result = await fetchBlockStaking(config, 100)
|
|
1282
1310
|
|
|
1283
1311
|
expect(result).toEqual([])
|
|
1284
1312
|
})
|
|
1285
1313
|
|
|
1286
1314
|
it('returns a single page when the page is smaller than the page size', async () => {
|
|
1287
1315
|
const items = [makeStakingItem(1), makeStakingItem(2)]
|
|
1288
|
-
|
|
1316
|
+
mockedNetwork.mockReturnValue(networkResponse(items) as ReturnType<typeof network>)
|
|
1289
1317
|
|
|
1290
|
-
const result = await fetchBlockStaking(100)
|
|
1318
|
+
const result = await fetchBlockStaking(config, 100)
|
|
1291
1319
|
|
|
1292
1320
|
expect(result).toEqual(items)
|
|
1293
1321
|
})
|
|
@@ -1296,26 +1324,30 @@ describe('tzkt network API', () => {
|
|
|
1296
1324
|
const fullPage = Array.from({ length: 1000 }, (_, i) => makeStakingItem(i + 1))
|
|
1297
1325
|
const lastPage = [makeStakingItem(1001)]
|
|
1298
1326
|
|
|
1299
|
-
|
|
1300
|
-
.
|
|
1301
|
-
.
|
|
1302
|
-
.mockResolvedValueOnce(lastPage)
|
|
1327
|
+
mockedNetwork
|
|
1328
|
+
.mockReturnValueOnce(networkResponse(fullPage) as ReturnType<typeof network>)
|
|
1329
|
+
.mockReturnValueOnce(networkResponse(lastPage) as ReturnType<typeof network>)
|
|
1303
1330
|
|
|
1304
|
-
const result = await fetchBlockStaking(100)
|
|
1331
|
+
const result = await fetchBlockStaking(config, 100)
|
|
1305
1332
|
|
|
1306
1333
|
expect(result).toHaveLength(1001)
|
|
1307
|
-
expect(
|
|
1308
|
-
|
|
1309
|
-
|
|
1334
|
+
expect(mockedNetwork).toHaveBeenCalledTimes(2)
|
|
1335
|
+
const firstParams = (mockedNetwork.mock.calls[0][0] as { params: Record<string, unknown> })
|
|
1336
|
+
.params
|
|
1337
|
+
expect(firstParams).toMatchObject({ level: 100 })
|
|
1338
|
+
expect(firstParams).not.toHaveProperty('offset.cr')
|
|
1339
|
+
const secondParams = (mockedNetwork.mock.calls[1][0] as { params: Record<string, unknown> })
|
|
1340
|
+
.params
|
|
1341
|
+
expect(secondParams).toMatchObject({ level: 100, 'offset.cr': 1000 })
|
|
1310
1342
|
})
|
|
1311
1343
|
|
|
1312
1344
|
it('stops after maxTxQuery iterations regardless of page length', async () => {
|
|
1313
1345
|
const fullPage = Array.from({ length: 1000 }, (_, i) => makeStakingItem(i + 1))
|
|
1314
|
-
|
|
1346
|
+
mockedNetwork.mockReturnValue(networkResponse(fullPage) as ReturnType<typeof network>)
|
|
1315
1347
|
|
|
1316
|
-
const result = await fetchBlockStaking(100)
|
|
1348
|
+
const result = await fetchBlockStaking(config, 100)
|
|
1317
1349
|
|
|
1318
|
-
expect(
|
|
1350
|
+
expect(mockedNetwork).toHaveBeenCalledTimes(100)
|
|
1319
1351
|
expect(result).toHaveLength(100_000)
|
|
1320
1352
|
expect(mockedLog).toHaveBeenCalledWith(
|
|
1321
1353
|
'tezos',
|