@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.
Files changed (199) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/lib/api/index.d.ts +1 -2
  3. package/lib/api/index.d.ts.map +1 -1
  4. package/lib/api/index.js +45 -44
  5. package/lib/api/index.js.map +1 -1
  6. package/lib/api/types.d.ts +3 -2
  7. package/lib/api/types.d.ts.map +1 -1
  8. package/lib/config.d.ts +3 -1
  9. package/lib/config.d.ts.map +1 -1
  10. package/lib/config.js.map +1 -1
  11. package/lib/logic/broadcast.d.ts +2 -1
  12. package/lib/logic/broadcast.d.ts.map +1 -1
  13. package/lib/logic/broadcast.js +3 -2
  14. package/lib/logic/broadcast.js.map +1 -1
  15. package/lib/logic/combine.d.ts +1 -1
  16. package/lib/logic/combine.d.ts.map +1 -1
  17. package/lib/logic/combine.js +4 -1
  18. package/lib/logic/combine.js.map +1 -1
  19. package/lib/logic/craftRawOperations.d.ts +2 -1
  20. package/lib/logic/craftRawOperations.d.ts.map +1 -1
  21. package/lib/logic/craftRawOperations.js +5 -8
  22. package/lib/logic/craftRawOperations.js.map +1 -1
  23. package/lib/logic/craftTransaction.d.ts +3 -2
  24. package/lib/logic/craftTransaction.d.ts.map +1 -1
  25. package/lib/logic/craftTransaction.js +6 -9
  26. package/lib/logic/craftTransaction.js.map +1 -1
  27. package/lib/logic/estimateFees.d.ts +2 -1
  28. package/lib/logic/estimateFees.d.ts.map +1 -1
  29. package/lib/logic/estimateFees.js +24 -19
  30. package/lib/logic/estimateFees.js.map +1 -1
  31. package/lib/logic/getBalance.d.ts +2 -1
  32. package/lib/logic/getBalance.d.ts.map +1 -1
  33. package/lib/logic/getBalance.js +7 -8
  34. package/lib/logic/getBalance.js.map +1 -1
  35. package/lib/logic/getBlock.d.ts +2 -1
  36. package/lib/logic/getBlock.d.ts.map +1 -1
  37. package/lib/logic/getBlock.js +12 -10
  38. package/lib/logic/getBlock.js.map +1 -1
  39. package/lib/logic/getBlockInfo.d.ts +2 -1
  40. package/lib/logic/getBlockInfo.d.ts.map +1 -1
  41. package/lib/logic/getBlockInfo.js +5 -3
  42. package/lib/logic/getBlockInfo.js.map +1 -1
  43. package/lib/logic/getStakes.d.ts +3 -2
  44. package/lib/logic/getStakes.d.ts.map +1 -1
  45. package/lib/logic/getStakes.js +9 -9
  46. package/lib/logic/getStakes.js.map +1 -1
  47. package/lib/logic/lastBlock.d.ts +2 -1
  48. package/lib/logic/lastBlock.d.ts.map +1 -1
  49. package/lib/logic/lastBlock.js +4 -6
  50. package/lib/logic/lastBlock.js.map +1 -1
  51. package/lib/logic/listOperations.d.ts +2 -1
  52. package/lib/logic/listOperations.d.ts.map +1 -1
  53. package/lib/logic/listOperations.js +8 -6
  54. package/lib/logic/listOperations.js.map +1 -1
  55. package/lib/logic/tezosToolkit.d.ts +2 -1
  56. package/lib/logic/tezosToolkit.d.ts.map +1 -1
  57. package/lib/logic/tezosToolkit.js +2 -6
  58. package/lib/logic/tezosToolkit.js.map +1 -1
  59. package/lib/logic/validateIntent.d.ts +2 -1
  60. package/lib/logic/validateIntent.d.ts.map +1 -1
  61. package/lib/logic/validateIntent.js +12 -13
  62. package/lib/logic/validateIntent.js.map +1 -1
  63. package/lib/network/bakers.d.ts +5 -4
  64. package/lib/network/bakers.d.ts.map +1 -1
  65. package/lib/network/bakers.js +9 -10
  66. package/lib/network/bakers.js.map +1 -1
  67. package/lib/network/index.d.ts +1 -1
  68. package/lib/network/index.d.ts.map +1 -1
  69. package/lib/network/index.js +2 -5
  70. package/lib/network/index.js.map +1 -1
  71. package/lib/network/tzkt.d.ts +16 -9
  72. package/lib/network/tzkt.d.ts.map +1 -1
  73. package/lib/network/tzkt.js +341 -333
  74. package/lib/network/tzkt.js.map +1 -1
  75. package/lib/utils.d.ts +2 -1
  76. package/lib/utils.d.ts.map +1 -1
  77. package/lib/utils.js +1 -6
  78. package/lib/utils.js.map +1 -1
  79. package/lib-es/api/index.d.ts +1 -2
  80. package/lib-es/api/index.d.ts.map +1 -1
  81. package/lib-es/api/index.js +40 -36
  82. package/lib-es/api/index.js.map +1 -1
  83. package/lib-es/api/types.d.ts +3 -2
  84. package/lib-es/api/types.d.ts.map +1 -1
  85. package/lib-es/config.d.ts +3 -1
  86. package/lib-es/config.d.ts.map +1 -1
  87. package/lib-es/config.js.map +1 -1
  88. package/lib-es/logic/broadcast.d.ts +2 -1
  89. package/lib-es/logic/broadcast.d.ts.map +1 -1
  90. package/lib-es/logic/broadcast.js +3 -2
  91. package/lib-es/logic/broadcast.js.map +1 -1
  92. package/lib-es/logic/combine.d.ts +1 -1
  93. package/lib-es/logic/combine.d.ts.map +1 -1
  94. package/lib-es/logic/combine.js +4 -1
  95. package/lib-es/logic/combine.js.map +1 -1
  96. package/lib-es/logic/craftRawOperations.d.ts +2 -1
  97. package/lib-es/logic/craftRawOperations.d.ts.map +1 -1
  98. package/lib-es/logic/craftRawOperations.js +5 -5
  99. package/lib-es/logic/craftRawOperations.js.map +1 -1
  100. package/lib-es/logic/craftTransaction.d.ts +3 -2
  101. package/lib-es/logic/craftTransaction.d.ts.map +1 -1
  102. package/lib-es/logic/craftTransaction.js +6 -6
  103. package/lib-es/logic/craftTransaction.js.map +1 -1
  104. package/lib-es/logic/estimateFees.d.ts +2 -1
  105. package/lib-es/logic/estimateFees.d.ts.map +1 -1
  106. package/lib-es/logic/estimateFees.js +24 -16
  107. package/lib-es/logic/estimateFees.js.map +1 -1
  108. package/lib-es/logic/getBalance.d.ts +2 -1
  109. package/lib-es/logic/getBalance.d.ts.map +1 -1
  110. package/lib-es/logic/getBalance.js +5 -3
  111. package/lib-es/logic/getBalance.js.map +1 -1
  112. package/lib-es/logic/getBlock.d.ts +2 -1
  113. package/lib-es/logic/getBlock.d.ts.map +1 -1
  114. package/lib-es/logic/getBlock.js +10 -8
  115. package/lib-es/logic/getBlock.js.map +1 -1
  116. package/lib-es/logic/getBlockInfo.d.ts +2 -1
  117. package/lib-es/logic/getBlockInfo.d.ts.map +1 -1
  118. package/lib-es/logic/getBlockInfo.js +4 -2
  119. package/lib-es/logic/getBlockInfo.js.map +1 -1
  120. package/lib-es/logic/getStakes.d.ts +3 -2
  121. package/lib-es/logic/getStakes.d.ts.map +1 -1
  122. package/lib-es/logic/getStakes.js +9 -6
  123. package/lib-es/logic/getStakes.js.map +1 -1
  124. package/lib-es/logic/lastBlock.d.ts +2 -1
  125. package/lib-es/logic/lastBlock.d.ts.map +1 -1
  126. package/lib-es/logic/lastBlock.js +4 -3
  127. package/lib-es/logic/lastBlock.js.map +1 -1
  128. package/lib-es/logic/listOperations.d.ts +2 -1
  129. package/lib-es/logic/listOperations.d.ts.map +1 -1
  130. package/lib-es/logic/listOperations.js +7 -5
  131. package/lib-es/logic/listOperations.js.map +1 -1
  132. package/lib-es/logic/tezosToolkit.d.ts +2 -1
  133. package/lib-es/logic/tezosToolkit.d.ts.map +1 -1
  134. package/lib-es/logic/tezosToolkit.js +2 -3
  135. package/lib-es/logic/tezosToolkit.js.map +1 -1
  136. package/lib-es/logic/validateIntent.d.ts +2 -1
  137. package/lib-es/logic/validateIntent.d.ts.map +1 -1
  138. package/lib-es/logic/validateIntent.js +10 -8
  139. package/lib-es/logic/validateIntent.js.map +1 -1
  140. package/lib-es/network/bakers.d.ts +5 -4
  141. package/lib-es/network/bakers.d.ts.map +1 -1
  142. package/lib-es/network/bakers.js +9 -10
  143. package/lib-es/network/bakers.js.map +1 -1
  144. package/lib-es/network/index.d.ts +1 -1
  145. package/lib-es/network/index.d.ts.map +1 -1
  146. package/lib-es/network/index.js +1 -1
  147. package/lib-es/network/index.js.map +1 -1
  148. package/lib-es/network/tzkt.d.ts +16 -9
  149. package/lib-es/network/tzkt.d.ts.map +1 -1
  150. package/lib-es/network/tzkt.js +340 -333
  151. package/lib-es/network/tzkt.js.map +1 -1
  152. package/lib-es/utils.d.ts +2 -1
  153. package/lib-es/utils.d.ts.map +1 -1
  154. package/lib-es/utils.js +1 -3
  155. package/lib-es/utils.js.map +1 -1
  156. package/package.json +2 -2
  157. package/src/api/index-mainnet.integ.test.ts +34 -30
  158. package/src/api/index.integ.test.ts +69 -53
  159. package/src/api/index.test.ts +99 -60
  160. package/src/api/index.ts +52 -36
  161. package/src/api/types.ts +3 -2
  162. package/src/config.ts +4 -1
  163. package/src/logic/broadcast.integ.test.ts +12 -13
  164. package/src/logic/broadcast.ts +4 -2
  165. package/src/logic/combine.test.ts +17 -0
  166. package/src/logic/combine.ts +5 -2
  167. package/src/logic/craftRawOperations.test.ts +47 -33
  168. package/src/logic/craftRawOperations.ts +6 -4
  169. package/src/logic/craftTransaction.integ.test.ts +12 -5
  170. package/src/logic/craftTransaction.test.ts +39 -31
  171. package/src/logic/craftTransaction.ts +10 -5
  172. package/src/logic/estimateFees.integ.test.ts +7 -7
  173. package/src/logic/estimateFees.test.ts +52 -49
  174. package/src/logic/estimateFees.ts +34 -22
  175. package/src/logic/getBalance.test.ts +19 -17
  176. package/src/logic/getBalance.ts +6 -3
  177. package/src/logic/getBlock.integ.test.ts +8 -30
  178. package/src/logic/getBlock.test.ts +91 -81
  179. package/src/logic/getBlock.ts +11 -8
  180. package/src/logic/getBlockInfo.integ.test.ts +9 -18
  181. package/src/logic/getBlockInfo.test.ts +19 -9
  182. package/src/logic/getBlockInfo.ts +5 -2
  183. package/src/logic/getStakes.test.ts +46 -49
  184. package/src/logic/getStakes.ts +14 -5
  185. package/src/logic/lastBlock.ts +5 -3
  186. package/src/logic/listOperations.integ.test.ts +40 -67
  187. package/src/logic/listOperations.test.ts +65 -59
  188. package/src/logic/listOperations.ts +8 -3
  189. package/src/logic/tezosToolkit.ts +3 -3
  190. package/src/logic/validateIntent.test.ts +78 -74
  191. package/src/logic/validateIntent.ts +17 -7
  192. package/src/network/bakers.integ.test.ts +2 -5
  193. package/src/network/bakers.test.ts +5 -6
  194. package/src/network/bakers.ts +13 -10
  195. package/src/network/index.ts +2 -1
  196. package/src/network/tzkt.integ.test.ts +3 -14
  197. package/src/network/tzkt.test.ts +128 -96
  198. package/src/network/tzkt.ts +426 -393
  199. package/src/utils.ts +2 -3
@@ -1,6 +1,7 @@
1
1
  // SPDX-FileCopyrightText: © 2026 LEDGER SAS
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
+ import type { TezosCoinConfig, TezosContext } from '../config'
4
5
  import type {
5
6
  APIBlock,
6
7
  APIDelegationType,
@@ -16,15 +17,20 @@ const mockGetAccountTokenTransfers = jest.fn()
16
17
  const mockGetBlockHashesByLevels = jest.fn()
17
18
 
18
19
  jest.mock('../network', () => ({
19
- tzkt: {
20
+ createTzktApi: () => ({
20
21
  getAccountOperations: async (address: string, options: unknown) =>
21
22
  mockGetAccountOperations(address, options),
22
23
  getAccountTokenTransfers: async (address: string, options: unknown) =>
23
24
  mockGetAccountTokenTransfers(address, options),
24
25
  getBlockHashesByLevels: async (levels: number[]) => mockGetBlockHashesByLevels(levels),
25
- },
26
+ }),
26
27
  }))
27
28
 
29
+ const context: TezosContext = {
30
+ config: async () => ({}) as unknown as TezosCoinConfig,
31
+ logger: () => undefined,
32
+ }
33
+
28
34
  const options: {
29
35
  sort: 'Ascending' | 'Descending'
30
36
  minHeight: number
@@ -47,7 +53,7 @@ describe('listOperations', () => {
47
53
  })
48
54
 
49
55
  it('forwards level.lt from cursor on both streams when sort is Descending', async () => {
50
- await listOperations('tz1PaginationAddr', {
56
+ await listOperations(context, 'tz1PaginationAddr', {
51
57
  ...options,
52
58
  sort: 'Descending',
53
59
  token: JSON.stringify({ lastLevel: 5_000_000 }),
@@ -72,7 +78,7 @@ describe('listOperations', () => {
72
78
  })
73
79
 
74
80
  it('forwards level.ge continuation when sort is Ascending and cursor has lastLevel', async () => {
75
- await listOperations('tz1AscPage2', {
81
+ await listOperations(context, 'tz1AscPage2', {
76
82
  ...options,
77
83
  sort: 'Ascending',
78
84
  minHeight: 0,
@@ -96,7 +102,7 @@ describe('listOperations', () => {
96
102
  })
97
103
 
98
104
  it('ignores legacy id-based pagination cursor (fresh level window)', async () => {
99
- await listOperations('tz1Legacy', {
105
+ await listOperations(context, 'tz1Legacy', {
100
106
  ...options,
101
107
  token: JSON.stringify({ nativeLastId: 111, tokenLastId: 222 }),
102
108
  })
@@ -110,7 +116,7 @@ describe('listOperations', () => {
110
116
  })
111
117
 
112
118
  it('ignores invalid pagination cursor JSON', async () => {
113
- await listOperations('tz1BadCursor', {
119
+ await listOperations(context, 'tz1BadCursor', {
114
120
  ...options,
115
121
  token: 'not-valid-json{',
116
122
  })
@@ -124,7 +130,7 @@ describe('listOperations', () => {
124
130
  it('should return no operations', async () => {
125
131
  // Given
126
132
  // When
127
- const [results, token] = await listOperations('any address', options)
133
+ const [results, token] = await listOperations(context, 'any address', options)
128
134
  // Then
129
135
  expect(results).toEqual([])
130
136
  expect(token).toEqual('')
@@ -193,7 +199,7 @@ describe('listOperations', () => {
193
199
  // Given
194
200
  mockGetAccountOperations.mockResolvedValue([operation])
195
201
  // When — use someSenderAddress so transaction ops pass the sender/target filter
196
- const [results] = await listOperations(someSenderAddress, options)
202
+ const [results] = await listOperations(context, someSenderAddress, options)
197
203
  // Then
198
204
  expect(results).toEqual([
199
205
  {
@@ -241,7 +247,7 @@ describe('listOperations', () => {
241
247
  // Given
242
248
  mockGetAccountOperations.mockResolvedValue([operation])
243
249
  // When
244
- const [results, token] = await listOperations(someSenderAddress, {
250
+ const [results, token] = await listOperations(context, someSenderAddress, {
245
251
  ...options,
246
252
  limit: 1,
247
253
  sort: 'Descending',
@@ -268,7 +274,7 @@ describe('listOperations', () => {
268
274
  // Given
269
275
  mockGetAccountOperations.mockResolvedValue([operation])
270
276
  // When
271
- const [results, _] = await listOperations(someSenderAddress, options)
277
+ const [results, _] = await listOperations(context, someSenderAddress, options)
272
278
  // Then
273
279
  expect(results.length).toEqual(1)
274
280
  expect(results[0].details).toEqual({
@@ -287,7 +293,7 @@ describe('listOperations', () => {
287
293
  // Given
288
294
  mockGetAccountOperations.mockResolvedValue([operation])
289
295
  // When
290
- const [results, token] = await listOperations(someSenderAddress, options)
296
+ const [results, token] = await listOperations(context, someSenderAddress, options)
291
297
  // Then
292
298
  expect(results.length).toEqual(1)
293
299
  expect(results[0].recipients).toEqual([])
@@ -302,7 +308,7 @@ describe('listOperations', () => {
302
308
  // Given
303
309
  mockGetAccountOperations.mockResolvedValue([operation])
304
310
  // When
305
- const [results, _] = await listOperations(someSenderAddress, options)
311
+ const [results, _] = await listOperations(context, someSenderAddress, options)
306
312
  // Then
307
313
  expect(results.length).toEqual(1)
308
314
  expect(results[0].tx.fees).toEqual(BigInt(6))
@@ -313,7 +319,7 @@ describe('listOperations', () => {
313
319
  const operation = { ...undelegate, sender: null }
314
320
  mockGetAccountOperations.mockResolvedValue([operation])
315
321
  // When
316
- const [results, token] = await listOperations('any address', options)
322
+ const [results, token] = await listOperations(context, 'any address', options)
317
323
  // Then
318
324
  expect(results.length).toEqual(1)
319
325
  expect(results[0].senders).toEqual([])
@@ -324,7 +330,7 @@ describe('listOperations', () => {
324
330
  const op1 = { ...undelegate, level: '1', timestamp: '2022-09-12T01:00:00Z' }
325
331
  const op2 = { ...undelegate, level: '2', timestamp: '2022-09-12T01:01:00Z' }
326
332
  mockGetAccountOperations.mockResolvedValue([op1, op2])
327
- const [results, _] = await listOperations('any address', options)
333
+ const [results, _] = await listOperations(context, 'any address', options)
328
334
  expect(results.map((op) => op.tx.block.height)).toEqual(['2', '1'])
329
335
  })
330
336
 
@@ -340,7 +346,7 @@ describe('listOperations', () => {
340
346
  target: { address: someDestinationAddress },
341
347
  }
342
348
  mockGetAccountOperations.mockResolvedValue([internalTx])
343
- const [results] = await listOperations(someDestinationAddress, options)
349
+ const [results] = await listOperations(context, someDestinationAddress, options)
344
350
  expect(results[0]).toMatchObject({
345
351
  tx: {
346
352
  feesPayer: initiatorAddress,
@@ -358,7 +364,7 @@ describe('listOperations', () => {
358
364
  sender: null,
359
365
  }
360
366
  mockGetAccountOperations.mockResolvedValue([txNoSender])
361
- const [results] = await listOperations(someDestinationAddress, options)
367
+ const [results] = await listOperations(context, someDestinationAddress, options)
362
368
  expect(results[0].tx.feesPayer).toBeUndefined()
363
369
  expect(results[0]).toMatchObject({
364
370
  senders: [],
@@ -368,7 +374,7 @@ describe('listOperations', () => {
368
374
 
369
375
  it('uses sender as feesPayer for delegation (no initiator field)', async () => {
370
376
  mockGetAccountOperations.mockResolvedValue([delegate])
371
- const [results] = await listOperations('any address', options)
377
+ const [results] = await listOperations(context, 'any address', options)
372
378
  expect(results[0]).toMatchObject({
373
379
  tx: {
374
380
  feesPayer: someSenderAddress,
@@ -380,7 +386,7 @@ describe('listOperations', () => {
380
386
 
381
387
  it('uses sender as feesPayer for reveal', async () => {
382
388
  mockGetAccountOperations.mockResolvedValue([reveal])
383
- const [results] = await listOperations('any address', options)
389
+ const [results] = await listOperations(context, 'any address', options)
384
390
  expect(results[0]).toMatchObject({
385
391
  tx: {
386
392
  feesPayer: someSenderAddress,
@@ -414,7 +420,7 @@ describe('listOperations', () => {
414
420
  }
415
421
 
416
422
  mockGetAccountOperations.mockResolvedValue([topLevelTx, internalTx])
417
- const [results] = await listOperations(someSenderAddress, options)
423
+ const [results] = await listOperations(context, someSenderAddress, options)
418
424
 
419
425
  // Only the top-level tx should be kept; the internal sub-tx is filtered out
420
426
  expect(results).toHaveLength(1)
@@ -465,7 +471,7 @@ describe('listOperations', () => {
465
471
  }
466
472
 
467
473
  mockGetAccountOperations.mockResolvedValue([topLevelTx, internalTx1, internalTx2])
468
- const [results] = await listOperations(someSenderAddress, options)
474
+ const [results] = await listOperations(context, someSenderAddress, options)
469
475
 
470
476
  // Only top-level tx kept, but fees include internal sub-tx storage costs
471
477
  expect(results).toHaveLength(1)
@@ -493,7 +499,7 @@ describe('listOperations', () => {
493
499
  const appliedTransfer = { ...transfer, status: 'applied' as const, level: 100 }
494
500
  mockGetAccountOperations.mockResolvedValue([appliedTransfer])
495
501
  mockGetAccountTokenTransfers.mockResolvedValue([fa2])
496
- const [results, next] = await listOperations(someDestinationAddress, {
502
+ const [results, next] = await listOperations(context, someDestinationAddress, {
497
503
  ...options,
498
504
  limit: 1,
499
505
  sort: 'Descending',
@@ -562,7 +568,7 @@ describe('listOperations', () => {
562
568
  }
563
569
  mockGetAccountOperations.mockResolvedValue([appliedTransfer])
564
570
  mockGetAccountTokenTransfers.mockResolvedValue([fa2WithBlock])
565
- const [results] = await listOperations(someDestinationAddress, options)
571
+ const [results] = await listOperations(context, someDestinationAddress, options)
566
572
  const tokenOp = results.find((o) => o.asset.type === 'fa2')
567
573
 
568
574
  expect(tokenOp!.tx.block.hash).toBe('BLK_FROM_TRANSFER')
@@ -577,7 +583,7 @@ describe('listOperations', () => {
577
583
  target: { address: someDestinationAddress },
578
584
  }
579
585
  mockGetAccountOperations.mockResolvedValue([failedIn])
580
- const [results] = await listOperations(someDestinationAddress, options)
586
+ const [results] = await listOperations(context, someDestinationAddress, options)
581
587
  expect(results).toEqual([])
582
588
  })
583
589
 
@@ -590,7 +596,7 @@ describe('listOperations', () => {
590
596
  target: { address: someDestinationAddress },
591
597
  }
592
598
  mockGetAccountOperations.mockResolvedValue([failedOut])
593
- const [results] = await listOperations(someSenderAddress, options)
599
+ const [results] = await listOperations(context, someSenderAddress, options)
594
600
  expect(results).toHaveLength(1)
595
601
  const out = results[0]
596
602
  expect(out!.tx.failed).toBe(true)
@@ -606,7 +612,7 @@ describe('listOperations', () => {
606
612
  target: { address: someDestinationAddress },
607
613
  }
608
614
  mockGetAccountOperations.mockResolvedValue([incoming])
609
- const [results] = await listOperations(someDestinationAddress, options)
615
+ const [results] = await listOperations(context, someDestinationAddress, options)
610
616
  expect(results).toHaveLength(1)
611
617
  const row = results[0]
612
618
  expect(row!.type).toBe('IN')
@@ -623,7 +629,7 @@ describe('listOperations', () => {
623
629
  target: { address: someSenderAddress },
624
630
  }
625
631
  mockGetAccountOperations.mockResolvedValue([selfTx])
626
- const [results] = await listOperations(someSenderAddress, options)
632
+ const [results] = await listOperations(context, someSenderAddress, options)
627
633
  expect(results).toHaveLength(1)
628
634
  const selfRow = results[0]
629
635
  expect(selfRow!.type).toBe('FEES')
@@ -640,7 +646,7 @@ describe('listOperations', () => {
640
646
  target: { address: someDestinationAddress },
641
647
  }
642
648
  mockGetAccountOperations.mockResolvedValue([zeroTx])
643
- const [results] = await listOperations(someSenderAddress, options)
649
+ const [results] = await listOperations(context, someSenderAddress, options)
644
650
  expect(results).toHaveLength(1)
645
651
  const zeroRow = results[0]
646
652
  expect(zeroRow!.type).toBe('FEES')
@@ -652,7 +658,7 @@ describe('listOperations', () => {
652
658
  const op2 = { ...undelegate, id: 8002 }
653
659
  const op3 = { ...undelegate, id: 8003 }
654
660
  mockGetAccountOperations.mockResolvedValue([op1, op2, op3])
655
- const [results] = await listOperations('any address', { ...options, limit: 2 })
661
+ const [results] = await listOperations(context, 'any address', { ...options, limit: 2 })
656
662
  expect(results).toHaveLength(2)
657
663
  })
658
664
 
@@ -676,7 +682,7 @@ describe('listOperations', () => {
676
682
  }
677
683
  mockGetAccountOperations.mockResolvedValue([{ ...transfer, status: 'applied' as const }])
678
684
  mockGetAccountTokenTransfers.mockResolvedValue([fa2Out])
679
- const [results] = await listOperations(someSenderAddress, options)
685
+ const [results] = await listOperations(context, someSenderAddress, options)
680
686
  const tokenOut = results.find((o) => o.asset.type === 'fa2')
681
687
  expect(tokenOut!.type).toBe('OUT')
682
688
  expect(tokenOut!.details?.ledgerOpType).toBe('OUT')
@@ -700,7 +706,7 @@ describe('listOperations', () => {
700
706
  }
701
707
  mockGetAccountOperations.mockResolvedValue([])
702
708
  mockGetAccountTokenTransfers.mockResolvedValue([fa2Self])
703
- const [results] = await listOperations(someSenderAddress, options)
709
+ const [results] = await listOperations(context, someSenderAddress, options)
704
710
  const tokenSelf = results.find((o) => o.asset.type === 'fa2')
705
711
  expect(tokenSelf!.type).toBe('FEES')
706
712
  expect(tokenSelf!.details?.ledgerOpType).toBe('FEES')
@@ -725,7 +731,7 @@ describe('listOperations', () => {
725
731
  }
726
732
  mockGetAccountOperations.mockResolvedValue([])
727
733
  mockGetAccountTokenTransfers.mockResolvedValue([fa2Orphan])
728
- const [results] = await listOperations(someDestinationAddress, options)
734
+ const [results] = await listOperations(context, someDestinationAddress, options)
729
735
  const orphan = results.find((o) => o.asset.type === 'fa2')
730
736
  expect(orphan!.tx.fees).toBe(0n)
731
737
  expect(orphan!.tx.feesPayer).toBeUndefined()
@@ -751,7 +757,7 @@ describe('listOperations', () => {
751
757
  }
752
758
  mockGetAccountOperations.mockResolvedValue([])
753
759
  mockGetAccountTokenTransfers.mockResolvedValue([fa2NoBlock])
754
- const [results] = await listOperations(someDestinationAddress, options)
760
+ const [results] = await listOperations(context, someDestinationAddress, options)
755
761
  const noBlock = results.find((o) => o.asset.type === 'fa2')
756
762
  expect(noBlock!.tx.block.hash).toBe('')
757
763
  })
@@ -771,7 +777,7 @@ describe('listOperations', () => {
771
777
  }
772
778
  mockGetAccountOperations.mockResolvedValue([opHigh, opLow])
773
779
  mockGetAccountTokenTransfers.mockResolvedValue([])
774
- const [results] = await listOperations(someSenderAddress, {
780
+ const [results] = await listOperations(context, someSenderAddress, {
775
781
  sort: 'Descending',
776
782
  minHeight: 0,
777
783
  limit: 2,
@@ -786,7 +792,7 @@ describe('listOperations', () => {
786
792
  mockGetAccountOperations.mockResolvedValueOnce([op1, op2]).mockResolvedValueOnce([])
787
793
  mockGetAccountTokenTransfers.mockResolvedValue([])
788
794
 
789
- const [, token] = await listOperations(someSenderAddress, {
795
+ const [, token] = await listOperations(context, someSenderAddress, {
790
796
  sort: 'Descending',
791
797
  minHeight: 0,
792
798
  limit: 2,
@@ -799,7 +805,7 @@ describe('listOperations', () => {
799
805
  })
800
806
  )
801
807
 
802
- await listOperations(someSenderAddress, {
808
+ await listOperations(context, someSenderAddress, {
803
809
  sort: 'Descending',
804
810
  minHeight: 0,
805
811
  limit: 2,
@@ -842,7 +848,7 @@ describe('listOperations', () => {
842
848
  mockGetAccountOperations.mockResolvedValue([])
843
849
  mockGetAccountTokenTransfers.mockResolvedValueOnce([fa2b, fa2a]).mockResolvedValueOnce([])
844
850
 
845
- const [, cursor] = await listOperations(someDestinationAddress, {
851
+ const [, cursor] = await listOperations(context, someDestinationAddress, {
846
852
  sort: 'Descending',
847
853
  minHeight: 0,
848
854
  limit: 2,
@@ -855,7 +861,7 @@ describe('listOperations', () => {
855
861
  })
856
862
  )
857
863
 
858
- await listOperations(someDestinationAddress, {
864
+ await listOperations(context, someDestinationAddress, {
859
865
  sort: 'Descending',
860
866
  minHeight: 0,
861
867
  limit: 2,
@@ -912,7 +918,7 @@ describe('listOperations', () => {
912
918
  }
913
919
  mockGetAccountOperations.mockResolvedValue([parentTx, opOlder])
914
920
  mockGetAccountTokenTransfers.mockResolvedValue([fa2At1000, fa2Old])
915
- const [results] = await listOperations(someDestinationAddress, {
921
+ const [results] = await listOperations(context, someDestinationAddress, {
916
922
  sort: 'Descending',
917
923
  minHeight: 0,
918
924
  limit: 2,
@@ -959,7 +965,7 @@ describe('listOperations', () => {
959
965
  mockGetAccountOperations.mockResolvedValueOnce([nativeOp1, nativeOp2])
960
966
  mockGetAccountTokenTransfers.mockResolvedValueOnce([tokenAtLowLevel])
961
967
 
962
- const [page, cursor] = await listOperations(someDestinationAddress, {
968
+ const [page, cursor] = await listOperations(context, someDestinationAddress, {
963
969
  sort: 'Ascending',
964
970
  minHeight: 0,
965
971
  limit: 10,
@@ -975,7 +981,7 @@ describe('listOperations', () => {
975
981
  mockGetAccountOperations.mockResolvedValueOnce([nativeOp2, nativeOp1])
976
982
  mockGetAccountTokenTransfers.mockResolvedValueOnce([tokenAtLowLevel])
977
983
 
978
- const [page, cursor] = await listOperations(someDestinationAddress, {
984
+ const [page, cursor] = await listOperations(context, someDestinationAddress, {
979
985
  sort: 'Descending',
980
986
  minHeight: 0,
981
987
  limit: 10,
@@ -1006,7 +1012,7 @@ describe('listOperations', () => {
1006
1012
  mockGetAccountOperations.mockResolvedValueOnce([])
1007
1013
  mockGetAccountTokenTransfers.mockResolvedValueOnce([fa2])
1008
1014
 
1009
- const [results, cursor] = await listOperations(someDestinationAddress, {
1015
+ const [results, cursor] = await listOperations(context, someDestinationAddress, {
1010
1016
  sort: 'Descending',
1011
1017
  minHeight: 0,
1012
1018
  limit: 10,
@@ -1051,7 +1057,7 @@ describe('listOperations', () => {
1051
1057
  mockGetAccountOperations.mockResolvedValueOnce([nativeHigh])
1052
1058
  mockGetAccountTokenTransfers.mockResolvedValueOnce([fa2High, fa2Low])
1053
1059
 
1054
- const [, cursor] = await listOperations(someDestinationAddress, {
1060
+ const [, cursor] = await listOperations(context, someDestinationAddress, {
1055
1061
  sort: 'Descending',
1056
1062
  minHeight: 0,
1057
1063
  limit: 2,
@@ -1086,7 +1092,7 @@ describe('listOperations', () => {
1086
1092
  mockGetAccountTokenTransfers.mockResolvedValue([
1087
1093
  makeFA2Transfer('42', 'KT1MultiToken', 10_001),
1088
1094
  ])
1089
- const [results] = await listOperations(someDestinationAddress, options)
1095
+ const [results] = await listOperations(context, someDestinationAddress, options)
1090
1096
  const op = results.find((o) => o.asset.type === 'fa2')
1091
1097
  expect(op!.asset).toMatchObject({ assetReference: 'KT1MultiToken:42' })
1092
1098
  })
@@ -1094,7 +1100,7 @@ describe('listOperations', () => {
1094
1100
  it('includes :0 suffix in assetReference when tokenId is 0', async () => {
1095
1101
  mockGetAccountOperations.mockResolvedValue([])
1096
1102
  mockGetAccountTokenTransfers.mockResolvedValue([makeFA2Transfer('0', 'KT1Standard', 10_002)])
1097
- const [results] = await listOperations(someDestinationAddress, options)
1103
+ const [results] = await listOperations(context, someDestinationAddress, options)
1098
1104
  const op = results.find((o) => o.asset.type === 'fa2')
1099
1105
  expect(op!.asset).toMatchObject({ assetReference: 'KT1Standard:0' })
1100
1106
  })
@@ -1107,7 +1113,7 @@ describe('listOperations', () => {
1107
1113
  }
1108
1114
  mockGetAccountOperations.mockResolvedValue([])
1109
1115
  mockGetAccountTokenTransfers.mockResolvedValue([fa2NoTokenId])
1110
- const [results] = await listOperations(someDestinationAddress, options)
1116
+ const [results] = await listOperations(context, someDestinationAddress, options)
1111
1117
  const op = results.find((o) => o.asset.type === 'fa2')
1112
1118
  expect(op!.asset).toMatchObject({ assetReference: 'KT1NoId:0' })
1113
1119
  })
@@ -1144,7 +1150,7 @@ describe('listOperations', () => {
1144
1150
  const op = makeStaking(action, Number(expectedAmount))
1145
1151
  mockGetAccountOperations.mockResolvedValue([op])
1146
1152
 
1147
- const [results] = await listOperations(stakerAddress, options)
1153
+ const [results] = await listOperations(context, stakerAddress, options)
1148
1154
 
1149
1155
  expect(results).toHaveLength(1)
1150
1156
  expect(results[0]).toMatchObject({
@@ -1165,7 +1171,7 @@ describe('listOperations', () => {
1165
1171
  }
1166
1172
  mockGetAccountOperations.mockResolvedValue([op])
1167
1173
 
1168
- const [results] = await listOperations(stakerAddress, options)
1174
+ const [results] = await listOperations(context, stakerAddress, options)
1169
1175
 
1170
1176
  expect(results).toHaveLength(1)
1171
1177
  expect(results[0]).toMatchObject({
@@ -1178,7 +1184,7 @@ describe('listOperations', () => {
1178
1184
 
1179
1185
  it('uses sender as feesPayer for staking operations', async () => {
1180
1186
  mockGetAccountOperations.mockResolvedValue([makeStaking('stake', 100)])
1181
- const [results] = await listOperations(stakerAddress, options)
1187
+ const [results] = await listOperations(context, stakerAddress, options)
1182
1188
  expect(results[0].tx.feesPayer).toBe(stakerAddress)
1183
1189
  })
1184
1190
 
@@ -1191,7 +1197,7 @@ describe('listOperations', () => {
1191
1197
  } as unknown as APIStakingType
1192
1198
  mockGetAccountOperations.mockResolvedValue([op])
1193
1199
 
1194
- const [results] = await listOperations(stakerAddress, options)
1200
+ const [results] = await listOperations(context, stakerAddress, options)
1195
1201
 
1196
1202
  expect(results).toHaveLength(1)
1197
1203
  expect(results[0].value).toBe(500_000_000n)
@@ -1206,7 +1212,7 @@ describe('listOperations', () => {
1206
1212
  } as unknown as APIStakingType
1207
1213
  mockGetAccountOperations.mockResolvedValue([op])
1208
1214
 
1209
- const [results] = await listOperations(stakerAddress, options)
1215
+ const [results] = await listOperations(context, stakerAddress, options)
1210
1216
 
1211
1217
  expect(results).toHaveLength(1)
1212
1218
  expect(results[0].value).toBe(0n)
@@ -1215,7 +1221,7 @@ describe('listOperations', () => {
1215
1221
  it('includes staking ops alongside transfers in pagination', async () => {
1216
1222
  const stake = makeStaking('stake', 100)
1217
1223
  mockGetAccountOperations.mockResolvedValue([stake])
1218
- const [results, token] = await listOperations(stakerAddress, options)
1224
+ const [results, token] = await listOperations(context, stakerAddress, options)
1219
1225
  expect(results.length).toBe(1)
1220
1226
  expect(token).toBe('')
1221
1227
  })
@@ -1230,7 +1236,7 @@ describe('listOperations', () => {
1230
1236
  async (levels: number[]) => new Map(levels.map((level) => [level, `BL-fetched-${level}`]))
1231
1237
  )
1232
1238
 
1233
- const [results] = await listOperations(stakerAddress, options)
1239
+ const [results] = await listOperations(context, stakerAddress, options)
1234
1240
 
1235
1241
  expect(results).toHaveLength(3)
1236
1242
  expect(results.map((r) => r.tx.block.hash).sort()).toEqual([
@@ -1246,7 +1252,7 @@ describe('listOperations', () => {
1246
1252
  it('does not call getBlockHashesByLevels when staking ops already carry a block (string)', async () => {
1247
1253
  mockGetAccountOperations.mockResolvedValue([makeStaking('stake', 100)])
1248
1254
 
1249
- await listOperations(stakerAddress, options)
1255
+ await listOperations(context, stakerAddress, options)
1250
1256
 
1251
1257
  expect(mockGetBlockHashesByLevels).not.toHaveBeenCalled()
1252
1258
  })
@@ -1265,7 +1271,7 @@ describe('listOperations', () => {
1265
1271
  }
1266
1272
  mockGetAccountOperations.mockResolvedValue([stakeWithObjectBlock])
1267
1273
 
1268
- const [results] = await listOperations(stakerAddress, options)
1274
+ const [results] = await listOperations(context, stakerAddress, options)
1269
1275
 
1270
1276
  expect(results).toHaveLength(1)
1271
1277
  expect(results[0].tx.block.hash).toBe(inlineBlock.hash)
@@ -1277,7 +1283,7 @@ describe('listOperations', () => {
1277
1283
  mockGetAccountOperations.mockResolvedValue([op])
1278
1284
  mockGetBlockHashesByLevels.mockRejectedValue(new Error('rpc 503'))
1279
1285
 
1280
- const [results] = await listOperations(stakerAddress, options)
1286
+ const [results] = await listOperations(context, stakerAddress, options)
1281
1287
 
1282
1288
  expect(results).toHaveLength(1)
1283
1289
  expect(results[0].tx.block.hash).toBe('')
@@ -1289,7 +1295,7 @@ describe('listOperations', () => {
1289
1295
  mockGetAccountOperations.mockResolvedValue([present, absent])
1290
1296
  mockGetBlockHashesByLevels.mockResolvedValue(new Map([[4_200_000, 'BL-4200000']]))
1291
1297
 
1292
- const [results] = await listOperations(stakerAddress, options)
1298
+ const [results] = await listOperations(context, stakerAddress, options)
1293
1299
 
1294
1300
  const byLevel = Object.fromEntries(results.map((r) => [r.tx.block.height, r.tx.block.hash]))
1295
1301
  expect(byLevel[4_200_000]).toBe('BL-4200000')
@@ -1324,7 +1330,7 @@ describe('listOperations', () => {
1324
1330
 
1325
1331
  it('surfaces origination as a FEES operation with correct fees', async () => {
1326
1332
  mockGetAccountOperations.mockResolvedValue([makeOrigination()])
1327
- const [results] = await listOperations(originatorAddress, options)
1333
+ const [results] = await listOperations(context, originatorAddress, options)
1328
1334
 
1329
1335
  expect(results).toHaveLength(1)
1330
1336
  expect(results[0].type).toBe('FEES')
@@ -1336,7 +1342,7 @@ describe('listOperations', () => {
1336
1342
 
1337
1343
  it('surfaces origination as OUT when contractBalance > 0', async () => {
1338
1344
  mockGetAccountOperations.mockResolvedValue([makeOrigination({ contractBalance: 1000000 })])
1339
- const [results] = await listOperations(originatorAddress, options)
1345
+ const [results] = await listOperations(context, originatorAddress, options)
1340
1346
 
1341
1347
  expect(results).toHaveLength(1)
1342
1348
  expect(results[0].type).toBe('OUT')
@@ -1345,7 +1351,7 @@ describe('listOperations', () => {
1345
1351
 
1346
1352
  it('includes counter in details', async () => {
1347
1353
  mockGetAccountOperations.mockResolvedValue([makeOrigination()])
1348
- const [results] = await listOperations(originatorAddress, options)
1354
+ const [results] = await listOperations(context, originatorAddress, options)
1349
1355
 
1350
1356
  expect(results[0].details?.counter).toBe(10150476)
1351
1357
  })
@@ -1,11 +1,12 @@
1
1
  // SPDX-FileCopyrightText: © 2026 LEDGER SAS
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
+ import type { TezosCoinConfig, TezosContext } from '../config'
4
5
  import type { AccountsGetOperationsOptions } from '../network/types'
5
6
  import type { Operation } from '@ledgerhq/coin-module-framework/api/types'
6
7
  import { log } from '@ledgerhq/logs'
7
8
  import { STAKING_ACTION_TO_OP_TYPE } from '../constants'
8
- import { tzkt } from '../network'
9
+ import { createTzktApi } from '../network'
9
10
  import {
10
11
  type APIDelegationType,
11
12
  type APIOperation,
@@ -336,6 +337,7 @@ function computeNextToken(
336
337
  * @returns a list of operations is descending (newest first) order and a token to be used for pagination
337
338
  */
338
339
  export async function listOperations(
340
+ context: TezosContext,
339
341
  address: string,
340
342
  {
341
343
  token,
@@ -344,6 +346,8 @@ export async function listOperations(
344
346
  minHeight,
345
347
  }: { limit?: number; token?: string; sort: 'Ascending' | 'Descending'; minHeight: number }
346
348
  ): Promise<[Operation[], string]> {
349
+ const config = await context.config()
350
+ const tzkt = createTzktApi(config)
347
351
  const cursor = parseCursor(token)
348
352
 
349
353
  const nativeOptions: AccountsGetOperationsOptions = {
@@ -384,7 +388,7 @@ export async function listOperations(
384
388
  ? tokenTrimmed.trimmed
385
389
  : alignToBoundary(tokenTrimmed.trimmed, boundary, sort)
386
390
 
387
- const stakingBlockHashes = await fetchMissingStakingBlockHashes(nativeAligned)
391
+ const stakingBlockHashes = await fetchMissingStakingBlockHashes(config, nativeAligned)
388
392
 
389
393
  const parentMap = buildParentMap(nativeAligned)
390
394
 
@@ -420,6 +424,7 @@ type ConvertibleOperation =
420
424
  * failures are swallowed: callers fall back to `""` for levels not in the map.
421
425
  */
422
426
  async function fetchMissingStakingBlockHashes(
427
+ config: TezosCoinConfig,
423
428
  ops: readonly APIOperation[]
424
429
  ): Promise<Map<number, string>> {
425
430
  const missingLevels = new Set<number>()
@@ -428,7 +433,7 @@ async function fetchMissingStakingBlockHashes(
428
433
  }
429
434
  if (missingLevels.size === 0) return new Map()
430
435
  try {
431
- return await tzkt.getBlockHashesByLevels([...missingLevels])
436
+ return await createTzktApi(config).getBlockHashesByLevels([...missingLevels])
432
437
  } catch (err) {
433
438
  log('coin:tezos', 'fetchMissingStakingBlockHashes: skipped on fetch error', {
434
439
  reason: String(err),
@@ -1,14 +1,14 @@
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 { TezosToolkit } from '@taquito/taquito'
5
- import coinConfig from '../config'
6
6
 
7
7
  // Tezos client instance is cached to avoid costly rebuild at every request
8
8
  // Watch out: cache key is the URL, coin module can be instantiated several times with different URLs
9
9
  const servers = new Map<string, TezosToolkit>()
10
- export function getTezosToolkit(): TezosToolkit {
11
- const url = coinConfig.getCoinConfig().node.url
10
+ export function getTezosToolkit(config: TezosCoinConfig): TezosToolkit {
11
+ const url = config.node.url
12
12
  let server = servers.get(url)
13
13
  if (server === undefined) {
14
14
  server = new TezosToolkit(url)