@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 { TransactionIntent } from '@ledgerhq/coin-module-framework/api/types'
5
6
  import {
6
7
  RecipientRequired,
@@ -9,7 +10,6 @@ import {
9
10
  AmountRequired,
10
11
  NotEnoughBalance,
11
12
  } from '@ledgerhq/coin-module-framework/errors'
12
- import coinConfig from '../config'
13
13
  import {
14
14
  InvalidAddressBecauseAlreadyDelegated,
15
15
  MustDelegateBeforeStaking,
@@ -30,12 +30,12 @@ const mockGetTokensBalances = jest.fn()
30
30
  const mockGetUnstakeRequestsFinalizable = jest.fn()
31
31
  jest.mock('../network/tzkt', () => ({
32
32
  __esModule: true,
33
- default: {
33
+ createTzktApi: () => ({
34
34
  getAccountByAddress: (...args: unknown[]) => mockGetAccountByAddress(...args),
35
35
  getTokensBalances: (...args: unknown[]) => mockGetTokensBalances(...args),
36
36
  getUnstakeRequestsFinalizable: (...args: unknown[]) =>
37
37
  mockGetUnstakeRequestsFinalizable(...args),
38
- },
38
+ }),
39
39
  }))
40
40
 
41
41
  describe('validateIntent', () => {
@@ -56,23 +56,27 @@ describe('validateIntent', () => {
56
56
  ...overrides,
57
57
  })
58
58
 
59
+ const context: TezosContext = {
60
+ config: async () =>
61
+ ({
62
+ status: { type: 'active' },
63
+ baker: { url: 'http://baker.example.com' },
64
+ explorer: { url: 'http://tezos.explorer.com', maxTxQuery: 100 },
65
+ node: { url: 'http://tezos.node.com' },
66
+ fees: {
67
+ minGasLimit: 600,
68
+ minRevealGasLimit: 300,
69
+ minStorageLimit: 0,
70
+ minFees: 500,
71
+ minEstimatedFees: 500,
72
+ },
73
+ }) as unknown as TezosCoinConfig,
74
+ logger: () => undefined,
75
+ }
76
+
59
77
  beforeEach(() => {
60
78
  jest.clearAllMocks()
61
79
 
62
- coinConfig.setCoinConfig(() => ({
63
- status: { type: 'active' },
64
- baker: { url: 'http://baker.example.com' },
65
- explorer: { url: 'http://tezos.explorer.com', maxTxQuery: 100 },
66
- node: { url: 'http://tezos.node.com' },
67
- fees: {
68
- minGasLimit: 600,
69
- minRevealGasLimit: 300,
70
- minStorageLimit: 0,
71
- minFees: 500,
72
- minEstimatedFees: 500,
73
- },
74
- }))
75
-
76
80
  mockEstimateFees.mockResolvedValue({
77
81
  fees: 1000n,
78
82
  gasLimit: 10000n,
@@ -87,7 +91,7 @@ describe('validateIntent', () => {
87
91
 
88
92
  describe('recipient validation', () => {
89
93
  it('should return RecipientRequired error when recipient is missing', async () => {
90
- const result = await validateIntent({
94
+ const result = await validateIntent(context, {
91
95
  intentType: 'transaction',
92
96
  asset: { type: 'native' },
93
97
  type: 'send',
@@ -100,7 +104,7 @@ describe('validateIntent', () => {
100
104
  })
101
105
 
102
106
  it('should return InvalidAddress error for invalid recipient', async () => {
103
- const result = await validateIntent({
107
+ const result = await validateIntent(context, {
104
108
  intentType: 'transaction',
105
109
  asset: { type: 'native' },
106
110
  type: 'send',
@@ -113,7 +117,7 @@ describe('validateIntent', () => {
113
117
  })
114
118
 
115
119
  it('should return InvalidAddressBecauseDestinationIsAlsoSource when sender equals recipient', async () => {
116
- const result = await validateIntent({
120
+ const result = await validateIntent(context, {
117
121
  intentType: 'transaction',
118
122
  asset: { type: 'native' },
119
123
  type: 'send',
@@ -128,7 +132,7 @@ describe('validateIntent', () => {
128
132
 
129
133
  describe('amount validation', () => {
130
134
  it('should return AmountRequired error when amount is zero and not useAllAmount', async () => {
131
- const result = await validateIntent({
135
+ const result = await validateIntent(context, {
132
136
  intentType: 'transaction',
133
137
  asset: { type: 'native' },
134
138
  type: 'send',
@@ -142,7 +146,7 @@ describe('validateIntent', () => {
142
146
  })
143
147
 
144
148
  it('should not return AmountRequired error when useAllAmount is true', async () => {
145
- const result = await validateIntent({
149
+ const result = await validateIntent(context, {
146
150
  intentType: 'transaction',
147
151
  asset: { type: 'native' },
148
152
  type: 'send',
@@ -156,7 +160,7 @@ describe('validateIntent', () => {
156
160
  })
157
161
 
158
162
  it('should return NotEnoughBalance when amount is negative', async () => {
159
- const result = await validateIntent({
163
+ const result = await validateIntent(context, {
160
164
  intentType: 'transaction',
161
165
  asset: { type: 'native' },
162
166
  type: 'send',
@@ -176,7 +180,7 @@ describe('validateIntent', () => {
176
180
  })
177
181
  )
178
182
 
179
- const result = await validateIntent({
183
+ const result = await validateIntent(context, {
180
184
  intentType: 'staking',
181
185
  asset: { type: 'native' },
182
186
  type: 'stake',
@@ -197,7 +201,7 @@ describe('validateIntent', () => {
197
201
  it('uses only fees as totalSpent for unstake', async () => {
198
202
  mockGetAccountByAddress.mockResolvedValue(makeUserAccount({ stakedBalance: 4000 }))
199
203
 
200
- const result = await validateIntent({
204
+ const result = await validateIntent(context, {
201
205
  intentType: 'staking',
202
206
  asset: { type: 'native' },
203
207
  type: 'unstake',
@@ -218,7 +222,7 @@ describe('validateIntent', () => {
218
222
  it('uses amount 0 and only fees as totalSpent for finalize_unstake', async () => {
219
223
  mockGetUnstakeRequestsFinalizable.mockResolvedValue(1234n)
220
224
 
221
- const result = await validateIntent({
225
+ const result = await validateIntent(context, {
222
226
  intentType: 'staking',
223
227
  asset: { type: 'native' },
224
228
  type: 'finalize_unstake',
@@ -246,7 +250,7 @@ describe('validateIntent', () => {
246
250
  })
247
251
  )
248
252
 
249
- const result = await validateIntent({
253
+ const result = await validateIntent(context, {
250
254
  intentType: 'transaction',
251
255
  asset: { type: 'native' },
252
256
  type: 'send',
@@ -264,7 +268,7 @@ describe('validateIntent', () => {
264
268
  })
265
269
 
266
270
  it('should return MustDelegateBeforeStaking when stake intent has no delegate', async () => {
267
- const result = await validateIntent({
271
+ const result = await validateIntent(context, {
268
272
  intentType: 'staking',
269
273
  asset: { type: 'native' },
270
274
  type: 'stake',
@@ -289,7 +293,7 @@ describe('validateIntent', () => {
289
293
  counter: 0,
290
294
  })
291
295
 
292
- const result = await validateIntent({
296
+ const result = await validateIntent(context, {
293
297
  intentType: 'staking',
294
298
  asset: { type: 'native' },
295
299
  type: 'stake',
@@ -312,7 +316,7 @@ describe('validateIntent', () => {
312
316
  })
313
317
  )
314
318
 
315
- const result = await validateIntent({
319
+ const result = await validateIntent(context, {
316
320
  intentType: 'staking',
317
321
  asset: { type: 'native' },
318
322
  type: 'stake',
@@ -340,7 +344,7 @@ describe('validateIntent', () => {
340
344
  amount: 4_500_000n,
341
345
  })
342
346
 
343
- const result = await validateIntent({
347
+ const result = await validateIntent(context, {
344
348
  intentType: 'staking',
345
349
  asset: { type: 'native' },
346
350
  type: 'stake',
@@ -370,7 +374,7 @@ describe('validateIntent', () => {
370
374
  amount: 0n,
371
375
  })
372
376
 
373
- const result = await validateIntent({
377
+ const result = await validateIntent(context, {
374
378
  intentType: 'staking',
375
379
  asset: { type: 'native' },
376
380
  type: 'stake',
@@ -401,7 +405,7 @@ describe('validateIntent', () => {
401
405
  estimatedFees: 1000n,
402
406
  })
403
407
 
404
- const result = await validateIntent({
408
+ const result = await validateIntent(context, {
405
409
  intentType: 'staking',
406
410
  asset: { type: 'native' },
407
411
  type: 'stake',
@@ -433,7 +437,7 @@ describe('validateIntent', () => {
433
437
  estimatedFees: 1000n,
434
438
  })
435
439
 
436
- const result = await validateIntent({
440
+ const result = await validateIntent(context, {
437
441
  intentType: 'staking',
438
442
  asset: { type: 'native' },
439
443
  type: 'stake',
@@ -450,7 +454,7 @@ describe('validateIntent', () => {
450
454
  it('should return TezosNotEnoughStaked when unstake has no staked balance', async () => {
451
455
  mockGetAccountByAddress.mockResolvedValue(makeUserAccount({ stakedBalance: 0 }))
452
456
 
453
- const result = await validateIntent({
457
+ const result = await validateIntent(context, {
454
458
  intentType: 'staking',
455
459
  asset: { type: 'native' },
456
460
  type: 'unstake',
@@ -466,7 +470,7 @@ describe('validateIntent', () => {
466
470
  it('should return AmountRequired when unstake amount is zero', async () => {
467
471
  mockGetAccountByAddress.mockResolvedValue(makeUserAccount({ stakedBalance: 4000 }))
468
472
 
469
- const result = await validateIntent({
473
+ const result = await validateIntent(context, {
470
474
  intentType: 'staking',
471
475
  asset: { type: 'native' },
472
476
  type: 'unstake',
@@ -482,7 +486,7 @@ describe('validateIntent', () => {
482
486
  it('should return TezosNotEnoughStaked when unstake amount exceeds staked balance', async () => {
483
487
  mockGetAccountByAddress.mockResolvedValue(makeUserAccount({ stakedBalance: 4000 }))
484
488
 
485
- const result = await validateIntent({
489
+ const result = await validateIntent(context, {
486
490
  intentType: 'staking',
487
491
  asset: { type: 'native' },
488
492
  type: 'unstake',
@@ -499,7 +503,7 @@ describe('validateIntent', () => {
499
503
  it('should resolve unstake useAllAmount to full stakedBalance', async () => {
500
504
  mockGetAccountByAddress.mockResolvedValue(makeUserAccount({ stakedBalance: 4000 }))
501
505
 
502
- const result = await validateIntent({
506
+ const result = await validateIntent(context, {
503
507
  intentType: 'staking',
504
508
  asset: { type: 'native' },
505
509
  type: 'unstake',
@@ -517,7 +521,7 @@ describe('validateIntent', () => {
517
521
  it('should return TezosNotEnoughStaked when unstake useAllAmount with zero stakedBalance', async () => {
518
522
  mockGetAccountByAddress.mockResolvedValue(makeUserAccount({ stakedBalance: 0 }))
519
523
 
520
- const result = await validateIntent({
524
+ const result = await validateIntent(context, {
521
525
  intentType: 'staking',
522
526
  asset: { type: 'native' },
523
527
  type: 'unstake',
@@ -542,7 +546,7 @@ describe('validateIntent', () => {
542
546
  estimatedFees: 1000n,
543
547
  })
544
548
 
545
- const result = await validateIntent({
549
+ const result = await validateIntent(context, {
546
550
  intentType: 'staking',
547
551
  asset: { type: 'native' },
548
552
  type: 'unstake',
@@ -558,7 +562,7 @@ describe('validateIntent', () => {
558
562
  it('should return NotEnoughBalance when finalize_unstake has nothing finalizable', async () => {
559
563
  mockGetUnstakeRequestsFinalizable.mockResolvedValue(0n)
560
564
 
561
- const result = await validateIntent({
565
+ const result = await validateIntent(context, {
562
566
  intentType: 'staking',
563
567
  asset: { type: 'native' },
564
568
  type: 'finalize_unstake',
@@ -579,7 +583,7 @@ describe('validateIntent', () => {
579
583
 
580
584
  mockGetAccountByAddress.mockResolvedValue(makeUserAccount({ balance }))
581
585
 
582
- const result = await validateIntent({
586
+ const result = await validateIntent(context, {
583
587
  intentType: 'transaction',
584
588
  asset: { type: 'native' },
585
589
  type: 'send',
@@ -593,7 +597,7 @@ describe('validateIntent', () => {
593
597
 
594
598
  it('should pass validation when amount is within balance', async () => {
595
599
  const amount = 1000000n
596
- const result = await validateIntent({
600
+ const result = await validateIntent(context, {
597
601
  intentType: 'transaction',
598
602
  asset: { type: 'native' },
599
603
  type: 'send',
@@ -612,7 +616,7 @@ describe('validateIntent', () => {
612
616
  makeUserAccount({ balance: 5_000_000, stakedBalance: 5_000_000 })
613
617
  )
614
618
 
615
- const result = await validateIntent({
619
+ const result = await validateIntent(context, {
616
620
  intentType: 'staking',
617
621
  asset: { type: 'native' },
618
622
  type: 'undelegate',
@@ -629,7 +633,7 @@ describe('validateIntent', () => {
629
633
  makeUserAccount({ balance: 5_000_000, stakedBalance: 4_000_000 })
630
634
  )
631
635
 
632
- const result = await validateIntent({
636
+ const result = await validateIntent(context, {
633
637
  intentType: 'staking',
634
638
  asset: { type: 'native' },
635
639
  type: 'delegate',
@@ -648,7 +652,7 @@ describe('validateIntent', () => {
648
652
  makeUserAccount({ balance: 2_000_000, stakedBalance: 1_000_000 })
649
653
  )
650
654
 
651
- const result = await validateIntent({
655
+ const result = await validateIntent(context, {
652
656
  intentType: 'transaction',
653
657
  asset: { type: 'native' },
654
658
  type: 'send',
@@ -668,7 +672,7 @@ describe('validateIntent', () => {
668
672
  makeUserAccount({ balance: 300_322, unstakedBalance: 300_102 })
669
673
  )
670
674
 
671
- const result = await validateIntent({
675
+ const result = await validateIntent(context, {
672
676
  intentType: 'transaction',
673
677
  asset: { type: 'native' },
674
678
  type: 'send',
@@ -683,7 +687,7 @@ describe('validateIntent', () => {
683
687
 
684
688
  describe('transaction types', () => {
685
689
  it('should pass validation for delegate transaction', async () => {
686
- const result = await validateIntent({
690
+ const result = await validateIntent(context, {
687
691
  intentType: 'staking',
688
692
  asset: { type: 'native' },
689
693
  type: 'delegate',
@@ -696,7 +700,7 @@ describe('validateIntent', () => {
696
700
  })
697
701
 
698
702
  it('should pass validation for undelegate transaction', async () => {
699
- const result = await validateIntent({
703
+ const result = await validateIntent(context, {
700
704
  intentType: 'staking',
701
705
  asset: { type: 'native' },
702
706
  type: 'undelegate',
@@ -716,7 +720,7 @@ describe('validateIntent', () => {
716
720
  })
717
721
  )
718
722
 
719
- const result = await validateIntent({
723
+ const result = await validateIntent(context, {
720
724
  intentType: 'staking',
721
725
  asset: { type: 'native' },
722
726
  type: 'stake',
@@ -731,7 +735,7 @@ describe('validateIntent', () => {
731
735
  it('should pass validation for unstake transaction', async () => {
732
736
  mockGetAccountByAddress.mockResolvedValue(makeUserAccount({ stakedBalance: 4000 }))
733
737
 
734
- const result = await validateIntent({
738
+ const result = await validateIntent(context, {
735
739
  intentType: 'staking',
736
740
  asset: { type: 'native' },
737
741
  type: 'unstake',
@@ -746,7 +750,7 @@ describe('validateIntent', () => {
746
750
  it('should pass validation for finalize_unstake transaction', async () => {
747
751
  mockGetUnstakeRequestsFinalizable.mockResolvedValue(4000n)
748
752
 
749
- const result = await validateIntent({
753
+ const result = await validateIntent(context, {
750
754
  intentType: 'staking',
751
755
  asset: { type: 'native' },
752
756
  type: 'finalize_unstake',
@@ -769,7 +773,7 @@ describe('validateIntent', () => {
769
773
  taquitoError: 'proto.001-PtAtLas.contract.balance_too_low',
770
774
  })
771
775
 
772
- const result = await validateIntent({
776
+ const result = await validateIntent(context, {
773
777
  intentType: 'transaction',
774
778
  asset: { type: 'native' },
775
779
  type: 'send',
@@ -797,7 +801,7 @@ describe('validateIntent', () => {
797
801
  taquitoError: 'proto.001-PtAtLas.contract.balance_too_low',
798
802
  })
799
803
 
800
- const result = await validateIntent({
804
+ const result = await validateIntent(context, {
801
805
  intentType: 'staking',
802
806
  asset: { type: 'native' },
803
807
  type: 'stake',
@@ -818,7 +822,7 @@ describe('validateIntent', () => {
818
822
  taquitoError: 'some.path.subtraction_underflow',
819
823
  })
820
824
 
821
- const result = await validateIntent({
825
+ const result = await validateIntent(context, {
822
826
  intentType: 'transaction',
823
827
  asset: { type: 'native' },
824
828
  type: 'send',
@@ -846,7 +850,7 @@ describe('validateIntent', () => {
846
850
  taquitoError: 'proto.024-PtTALLiN.delegate.unchanged',
847
851
  })
848
852
 
849
- const result = await validateIntent({
853
+ const result = await validateIntent(context, {
850
854
  intentType: 'staking',
851
855
  asset: { type: 'native' },
852
856
  type: 'stake',
@@ -874,7 +878,7 @@ describe('validateIntent', () => {
874
878
  taquitoError: 'proto.024-PtTALLiN.delegate.unchanged',
875
879
  })
876
880
 
877
- const result = await validateIntent({
881
+ const result = await validateIntent(context, {
878
882
  intentType: 'staking',
879
883
  asset: { type: 'native' },
880
884
  type: 'delegate',
@@ -895,7 +899,7 @@ describe('validateIntent', () => {
895
899
  taquitoError: 'proto.empty_implicit_contract',
896
900
  })
897
901
 
898
- const result = await validateIntent({
902
+ const result = await validateIntent(context, {
899
903
  intentType: 'staking',
900
904
  asset: { type: 'native' },
901
905
  type: 'delegate',
@@ -923,7 +927,7 @@ describe('validateIntent', () => {
923
927
  taquitoError: 'proto.empty_implicit_contract',
924
928
  })
925
929
 
926
- const result = await validateIntent({
930
+ const result = await validateIntent(context, {
927
931
  intentType: 'staking',
928
932
  asset: { type: 'native' },
929
933
  type: 'stake',
@@ -945,7 +949,7 @@ describe('validateIntent', () => {
945
949
  taquitoError: 'proto.alpha.staking.too_much_unstaked',
946
950
  })
947
951
 
948
- const result = await validateIntent({
952
+ const result = await validateIntent(context, {
949
953
  intentType: 'staking',
950
954
  asset: { type: 'native' },
951
955
  type: 'unstake',
@@ -972,7 +976,7 @@ describe('validateIntent', () => {
972
976
  taquitoError: 'proto.alpha.contract.must_be_delegated_to_stake',
973
977
  })
974
978
 
975
- const result = await validateIntent({
979
+ const result = await validateIntent(context, {
976
980
  intentType: 'staking',
977
981
  asset: { type: 'native' },
978
982
  type: 'stake',
@@ -1000,7 +1004,7 @@ describe('validateIntent', () => {
1000
1004
  'proto.alpha.cannot_stake_with_unfinalizable_unstake_requests_to_another_delegate',
1001
1005
  })
1002
1006
 
1003
- const result = await validateIntent({
1007
+ const result = await validateIntent(context, {
1004
1008
  intentType: 'staking',
1005
1009
  asset: { type: 'native' },
1006
1010
  type: 'stake',
@@ -1022,7 +1026,7 @@ describe('validateIntent', () => {
1022
1026
  taquitoError: 'proto.unknown_rpc_failure',
1023
1027
  })
1024
1028
 
1025
- const result = await validateIntent({
1029
+ const result = await validateIntent(context, {
1026
1030
  intentType: 'transaction',
1027
1031
  asset: { type: 'native' },
1028
1032
  type: 'send',
@@ -1041,7 +1045,7 @@ describe('validateIntent', () => {
1041
1045
  mockGetAccountByAddress.mockResolvedValue(makeUserAccount({ revealed: false }))
1042
1046
 
1043
1047
  const amount = 1000000n
1044
- const result = await validateIntent({
1048
+ const result = await validateIntent(context, {
1045
1049
  intentType: 'transaction',
1046
1050
  asset: { type: 'native' },
1047
1051
  type: 'send',
@@ -1059,7 +1063,7 @@ describe('validateIntent', () => {
1059
1063
  it('sets estimation error when getAccountByAddress rejects', async () => {
1060
1064
  mockGetAccountByAddress.mockRejectedValue(new Error('network failure'))
1061
1065
 
1062
- const result = await validateIntent({
1066
+ const result = await validateIntent(context, {
1063
1067
  intentType: 'transaction',
1064
1068
  asset: { type: 'native' },
1065
1069
  type: 'send',
@@ -1082,7 +1086,7 @@ describe('validateIntent', () => {
1082
1086
  counter: 0,
1083
1087
  })
1084
1088
 
1085
- const result = await validateIntent({
1089
+ const result = await validateIntent(context, {
1086
1090
  intentType: 'transaction',
1087
1091
  asset: { type: 'native' },
1088
1092
  type: 'send',
@@ -1121,7 +1125,7 @@ describe('validateIntent', () => {
1121
1125
  },
1122
1126
  ])
1123
1127
 
1124
- const result = await validateIntent({
1128
+ const result = await validateIntent(context, {
1125
1129
  intentType: 'transaction',
1126
1130
  asset: { type: 'token', assetReference: `${contract}:0` },
1127
1131
  type: 'send',
@@ -1149,7 +1153,7 @@ describe('validateIntent', () => {
1149
1153
  taquitoError: 'proto.024-PtTALLiN.michelson_v1.script_rejected',
1150
1154
  })
1151
1155
 
1152
- const result = await validateIntent({
1156
+ const result = await validateIntent(context, {
1153
1157
  intentType: 'transaction',
1154
1158
  asset: { type: 'token', assetReference: 'KT1CpeSQKdkhWi4pinYcseCFKmDhs5M74BkU:0' },
1155
1159
  type: 'send',
@@ -1165,7 +1169,7 @@ describe('validateIntent', () => {
1165
1169
  const contract = 'KT1CpeSQKdkhWi4pinYcseCFKmDhs5M74BkU'
1166
1170
  mockGetTokensBalances.mockResolvedValue([])
1167
1171
 
1168
- const result = await validateIntent({
1172
+ const result = await validateIntent(context, {
1169
1173
  intentType: 'transaction',
1170
1174
  asset: { type: 'token', assetReference: `${contract}:0` },
1171
1175
  type: 'send',
@@ -1190,7 +1194,7 @@ describe('validateIntent', () => {
1190
1194
  amount: 0n,
1191
1195
  })
1192
1196
 
1193
- const result = await validateIntent({
1197
+ const result = await validateIntent(context, {
1194
1198
  intentType: 'transaction',
1195
1199
  asset: { type: 'native' },
1196
1200
  type: 'send',
@@ -1215,7 +1219,7 @@ describe('validateIntent', () => {
1215
1219
  amount: estimatedFromTaquito,
1216
1220
  })
1217
1221
 
1218
- const result = await validateIntent({
1222
+ const result = await validateIntent(context, {
1219
1223
  intentType: 'transaction',
1220
1224
  asset: { type: 'native' },
1221
1225
  type: 'send',
@@ -1241,7 +1245,7 @@ describe('validateIntent', () => {
1241
1245
  amount: 0n,
1242
1246
  })
1243
1247
 
1244
- const result = await validateIntent({
1248
+ const result = await validateIntent(context, {
1245
1249
  intentType: 'transaction',
1246
1250
  asset: { type: 'native' },
1247
1251
  type: 'send',
@@ -1278,7 +1282,7 @@ describe('validateIntent', () => {
1278
1282
  })
1279
1283
  )
1280
1284
 
1281
- const result = await validateIntent({
1285
+ const result = await validateIntent(context, {
1282
1286
  intentType: 'transaction',
1283
1287
  asset: { type: 'native' },
1284
1288
  type: 'send',
@@ -1308,7 +1312,7 @@ describe('validateIntent', () => {
1308
1312
  estimatedFees,
1309
1313
  })
1310
1314
 
1311
- const result = await validateIntent({
1315
+ const result = await validateIntent(context, {
1312
1316
  intentType: 'transaction',
1313
1317
  asset: { type: 'native' },
1314
1318
  type: 'send',
@@ -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 { APIManagerAccount } from '../network/types'
5
6
  import type { TezosOperationMode } from '../types/model'
6
7
  import type {
@@ -16,7 +17,7 @@ import {
16
17
  } from '@ledgerhq/coin-module-framework/errors'
17
18
  import { validateAddress, ValidationResult } from '@taquito/utils'
18
19
  import { hasManagerKey } from '../network/types'
19
- import api from '../network/tzkt'
20
+ import { createTzktApi } from '../network/tzkt'
20
21
  import {
21
22
  InvalidAddressBecauseAlreadyDelegated,
22
23
  MustDelegateBeforeStaking,
@@ -257,6 +258,7 @@ function validateBalanceCoverage(
257
258
  }
258
259
 
259
260
  async function estimateFeesForIntent(
261
+ context: TezosContext,
260
262
  intent: TransactionIntent,
261
263
  senderInfo: APIManagerAccount
262
264
  ): Promise<{
@@ -270,7 +272,7 @@ async function estimateFeesForIntent(
270
272
 
271
273
  const tezosMode = resolveValidationOperationMode(intent)
272
274
  const tokenInfo = tezosMode === 'send_token' ? parseTezosTokenAsset(intent.asset)! : undefined
273
- const estimation = await estimateFees({
275
+ const estimation = await estimateFees(context, {
274
276
  account: {
275
277
  address: intent.sender,
276
278
  revealed: senderInfo.revealed,
@@ -305,7 +307,10 @@ async function estimateFeesForIntent(
305
307
  }
306
308
  }
307
309
 
308
- async function fetchTokenBalanceForSendMax(intent: TransactionIntent): Promise<bigint | undefined> {
310
+ async function fetchTokenBalanceForSendMax(
311
+ config: TezosCoinConfig,
312
+ intent: TransactionIntent
313
+ ): Promise<bigint | undefined> {
309
314
  if (intent.type !== 'send' || !intent.useAllAmount) {
310
315
  return undefined
311
316
  }
@@ -320,7 +325,7 @@ async function fetchTokenBalanceForSendMax(intent: TransactionIntent): Promise<b
320
325
  return undefined
321
326
  }
322
327
 
323
- const tokenBalances = await api.getTokensBalances(intent.sender, {
328
+ const tokenBalances = await createTzktApi(config).getTokensBalances(intent.sender, {
324
329
  contractAddress: tokenInfo.contractAddress,
325
330
  tokenId: tokenInfo.tokenId,
326
331
  })
@@ -334,7 +339,12 @@ async function fetchTokenBalanceForSendMax(intent: TransactionIntent): Promise<b
334
339
 
335
340
  // Coverage is checked against live TzKT state (senderInfo) below, not the framework-provided
336
341
  // balances: the synced spendableBalance can lag between consecutive operations.
337
- export async function validateIntent(intent: TransactionIntent): Promise<TransactionValidation> {
342
+ export async function validateIntent(
343
+ context: TezosContext,
344
+ intent: TransactionIntent
345
+ ): Promise<TransactionValidation> {
346
+ const config = await context.config()
347
+ const api = createTzktApi(config)
338
348
  const errors: Record<string, Error> = {}
339
349
  const warnings: Record<string, Error> = {}
340
350
  let estimatedFees: bigint
@@ -368,12 +378,12 @@ export async function validateIntent(intent: TransactionIntent): Promise<Transac
368
378
  return { errors, warnings, estimatedFees: 0n, amount: intent.amount, totalSpent: 0n }
369
379
  }
370
380
 
371
- const feeResult = await estimateFeesForIntent(intent, senderInfo)
381
+ const feeResult = await estimateFeesForIntent(context, intent, senderInfo)
372
382
  estimatedFees = feeResult.estimatedFees
373
383
  estimatedAmount = feeResult.estimatedAmount
374
384
  Object.assign(errors, feeResult.errors)
375
385
 
376
- const tokenBalanceForSendMax = await fetchTokenBalanceForSendMax(intent)
386
+ const tokenBalanceForSendMax = await fetchTokenBalanceForSendMax(config, intent)
377
387
 
378
388
  const amounts = calculateAmounts(
379
389
  intent,
@@ -2,18 +2,15 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import type { TezosCoinConfig } from '../config'
5
- import coinConfig from '../config'
6
5
  import { listBakers } from '../network/bakers'
7
6
  import whitelist from '../network/bakers.whitelist-default'
8
7
  import { mockConfig } from '../test/config'
9
8
 
10
9
  describe('tezos bakers', () => {
11
- beforeAll(() => {
12
- coinConfig.setCoinConfig((): TezosCoinConfig => mockConfig as TezosCoinConfig)
13
- })
10
+ const config: TezosCoinConfig = mockConfig as TezosCoinConfig
14
11
 
15
12
  test('atleast 10 whitelisted bakers are online', async () => {
16
- const bakers = await listBakers(whitelist)
13
+ const bakers = await listBakers(config, whitelist)
17
14
  const retrievedAddresses = bakers.map((o) => o.address)
18
15
  let available = 0
19
16
  for (const whitelisted of whitelist) {