@ledgerhq/coin-tezos 6.6.0 → 6.7.0-nightly.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 (335) hide show
  1. package/.unimportedrc.json +4 -30
  2. package/CHANGELOG.md +15 -0
  3. package/jest.integ.config.js +1 -0
  4. package/lib/api/index.d.ts.map +1 -1
  5. package/lib/api/index.integ.test.js +6 -0
  6. package/lib/api/index.integ.test.js.map +1 -1
  7. package/lib/api/index.js +221 -40
  8. package/lib/api/index.js.map +1 -1
  9. package/lib/api/index.test.js +84 -10
  10. package/lib/api/index.test.js.map +1 -1
  11. package/lib/api/types.d.ts +7 -6
  12. package/lib/api/types.d.ts.map +1 -1
  13. package/lib/config.d.ts +4 -3
  14. package/lib/config.d.ts.map +1 -1
  15. package/lib/config.js.map +1 -1
  16. package/lib/index.d.ts +1 -1
  17. package/lib/index.d.ts.map +1 -1
  18. package/lib/index.js +1 -3
  19. package/lib/index.js.map +1 -1
  20. package/lib/logic/craftTransaction.d.ts.map +1 -1
  21. package/lib/logic/craftTransaction.js +7 -0
  22. package/lib/logic/craftTransaction.js.map +1 -1
  23. package/lib/logic/craftTransaction.test.js +1 -0
  24. package/lib/logic/craftTransaction.test.js.map +1 -1
  25. package/lib/logic/estimateFees.d.ts.map +1 -1
  26. package/lib/logic/estimateFees.integ.test.js +8 -2
  27. package/lib/logic/estimateFees.integ.test.js.map +1 -1
  28. package/lib/logic/estimateFees.js +119 -45
  29. package/lib/logic/estimateFees.js.map +1 -1
  30. package/lib/logic/getBalance.js +1 -1
  31. package/lib/logic/getBalance.js.map +1 -1
  32. package/lib/logic/getStakes.d.ts +3 -0
  33. package/lib/logic/getStakes.d.ts.map +1 -0
  34. package/lib/logic/getStakes.js +26 -0
  35. package/lib/logic/getStakes.js.map +1 -0
  36. package/lib/logic/getStakes.test.d.ts +2 -0
  37. package/lib/logic/getStakes.test.d.ts.map +1 -0
  38. package/lib/logic/getStakes.test.js +133 -0
  39. package/lib/logic/getStakes.test.js.map +1 -0
  40. package/lib/logic/index.d.ts +2 -0
  41. package/lib/logic/index.d.ts.map +1 -1
  42. package/lib/logic/index.js +5 -1
  43. package/lib/logic/index.js.map +1 -1
  44. package/lib/logic/listOperations.d.ts.map +1 -1
  45. package/lib/logic/listOperations.js +69 -11
  46. package/lib/logic/listOperations.js.map +1 -1
  47. package/lib/logic/listOperations.test.js +14 -10
  48. package/lib/logic/listOperations.test.js.map +1 -1
  49. package/lib/logic/validateIntent.d.ts +3 -0
  50. package/lib/logic/validateIntent.d.ts.map +1 -0
  51. package/lib/logic/validateIntent.js +179 -0
  52. package/lib/logic/validateIntent.js.map +1 -0
  53. package/lib/logic/validateIntent.test.d.ts +2 -0
  54. package/lib/logic/validateIntent.test.d.ts.map +1 -0
  55. package/lib/logic/validateIntent.test.js +261 -0
  56. package/lib/logic/validateIntent.test.js.map +1 -0
  57. package/{lib-es/bridge → lib}/transaction.d.ts +1 -1
  58. package/lib/transaction.d.ts.map +1 -0
  59. package/lib/{bridge/transaction.js → transaction.js} +3 -3
  60. package/lib/transaction.js.map +1 -0
  61. package/lib/types/bridge.d.ts +3 -0
  62. package/lib/types/bridge.d.ts.map +1 -1
  63. package/lib/types/bridge.fixture.d.ts.map +1 -1
  64. package/lib/types/bridge.fixture.js +1 -0
  65. package/lib/types/bridge.fixture.js.map +1 -1
  66. package/lib/types/bridge.js.map +1 -1
  67. package/lib/utils.d.ts +50 -0
  68. package/lib/utils.d.ts.map +1 -0
  69. package/lib/utils.js +111 -0
  70. package/lib/utils.js.map +1 -0
  71. package/lib-es/api/index.d.ts.map +1 -1
  72. package/lib-es/api/index.integ.test.js +6 -0
  73. package/lib-es/api/index.integ.test.js.map +1 -1
  74. package/lib-es/api/index.js +222 -41
  75. package/lib-es/api/index.js.map +1 -1
  76. package/lib-es/api/index.test.js +84 -10
  77. package/lib-es/api/index.test.js.map +1 -1
  78. package/lib-es/api/types.d.ts +7 -6
  79. package/lib-es/api/types.d.ts.map +1 -1
  80. package/lib-es/config.d.ts +4 -3
  81. package/lib-es/config.d.ts.map +1 -1
  82. package/lib-es/config.js.map +1 -1
  83. package/lib-es/index.d.ts +1 -1
  84. package/lib-es/index.d.ts.map +1 -1
  85. package/lib-es/index.js +1 -1
  86. package/lib-es/index.js.map +1 -1
  87. package/lib-es/logic/craftTransaction.d.ts.map +1 -1
  88. package/lib-es/logic/craftTransaction.js +7 -0
  89. package/lib-es/logic/craftTransaction.js.map +1 -1
  90. package/lib-es/logic/craftTransaction.test.js +1 -0
  91. package/lib-es/logic/craftTransaction.test.js.map +1 -1
  92. package/lib-es/logic/estimateFees.d.ts.map +1 -1
  93. package/lib-es/logic/estimateFees.integ.test.js +8 -2
  94. package/lib-es/logic/estimateFees.integ.test.js.map +1 -1
  95. package/lib-es/logic/estimateFees.js +119 -45
  96. package/lib-es/logic/estimateFees.js.map +1 -1
  97. package/lib-es/logic/getBalance.js +1 -1
  98. package/lib-es/logic/getBalance.js.map +1 -1
  99. package/lib-es/logic/getStakes.d.ts +3 -0
  100. package/lib-es/logic/getStakes.d.ts.map +1 -0
  101. package/lib-es/logic/getStakes.js +20 -0
  102. package/lib-es/logic/getStakes.js.map +1 -0
  103. package/lib-es/logic/getStakes.test.d.ts +2 -0
  104. package/lib-es/logic/getStakes.test.d.ts.map +1 -0
  105. package/lib-es/logic/getStakes.test.js +128 -0
  106. package/lib-es/logic/getStakes.test.js.map +1 -0
  107. package/lib-es/logic/index.d.ts +2 -0
  108. package/lib-es/logic/index.d.ts.map +1 -1
  109. package/lib-es/logic/index.js +2 -0
  110. package/lib-es/logic/index.js.map +1 -1
  111. package/lib-es/logic/listOperations.d.ts.map +1 -1
  112. package/lib-es/logic/listOperations.js +69 -11
  113. package/lib-es/logic/listOperations.js.map +1 -1
  114. package/lib-es/logic/listOperations.test.js +14 -10
  115. package/lib-es/logic/listOperations.test.js.map +1 -1
  116. package/lib-es/logic/validateIntent.d.ts +3 -0
  117. package/lib-es/logic/validateIntent.d.ts.map +1 -0
  118. package/lib-es/logic/validateIntent.js +173 -0
  119. package/lib-es/logic/validateIntent.js.map +1 -0
  120. package/lib-es/logic/validateIntent.test.d.ts +2 -0
  121. package/lib-es/logic/validateIntent.test.d.ts.map +1 -0
  122. package/lib-es/logic/validateIntent.test.js +233 -0
  123. package/lib-es/logic/validateIntent.test.js.map +1 -0
  124. package/{lib/bridge → lib-es}/transaction.d.ts +1 -1
  125. package/lib-es/transaction.d.ts.map +1 -0
  126. package/lib-es/{bridge/transaction.js → transaction.js} +3 -3
  127. package/lib-es/transaction.js.map +1 -0
  128. package/lib-es/types/bridge.d.ts +3 -0
  129. package/lib-es/types/bridge.d.ts.map +1 -1
  130. package/lib-es/types/bridge.fixture.d.ts.map +1 -1
  131. package/lib-es/types/bridge.fixture.js +1 -0
  132. package/lib-es/types/bridge.fixture.js.map +1 -1
  133. package/lib-es/types/bridge.js.map +1 -1
  134. package/lib-es/utils.d.ts +50 -0
  135. package/lib-es/utils.d.ts.map +1 -0
  136. package/lib-es/utils.js +100 -0
  137. package/lib-es/utils.js.map +1 -0
  138. package/package.json +8 -11
  139. package/src/api/index.integ.test.ts +8 -1
  140. package/src/api/index.test.ts +93 -16
  141. package/src/api/index.ts +248 -55
  142. package/src/api/types.ts +11 -7
  143. package/src/config.ts +9 -2
  144. package/src/index.ts +1 -2
  145. package/src/logic/craftTransaction.test.ts +1 -0
  146. package/src/logic/craftTransaction.ts +8 -0
  147. package/src/logic/estimateFees.integ.test.ts +8 -2
  148. package/src/logic/estimateFees.ts +140 -49
  149. package/src/logic/getBalance.ts +1 -1
  150. package/src/logic/getStakes.test.ts +145 -0
  151. package/src/logic/getStakes.ts +20 -0
  152. package/src/logic/index.ts +2 -0
  153. package/src/logic/listOperations.test.ts +64 -54
  154. package/src/logic/listOperations.ts +70 -10
  155. package/src/logic/validateIntent.test.ts +274 -0
  156. package/src/logic/validateIntent.ts +207 -0
  157. package/src/{bridge/transaction.ts → transaction.ts} +4 -4
  158. package/src/types/bridge.fixture.ts +1 -0
  159. package/src/types/bridge.ts +6 -1
  160. package/src/utils.ts +111 -0
  161. package/lib/bridge/broadcast.d.ts +0 -4
  162. package/lib/bridge/broadcast.d.ts.map +0 -1
  163. package/lib/bridge/broadcast.js +0 -11
  164. package/lib/bridge/broadcast.js.map +0 -1
  165. package/lib/bridge/broadcast.test.d.ts +0 -2
  166. package/lib/bridge/broadcast.test.d.ts.map +0 -1
  167. package/lib/bridge/broadcast.test.js +0 -36
  168. package/lib/bridge/broadcast.test.js.map +0 -1
  169. package/lib/bridge/buildOptimisticOperation.d.ts +0 -4
  170. package/lib/bridge/buildOptimisticOperation.d.ts.map +0 -1
  171. package/lib/bridge/buildOptimisticOperation.js +0 -28
  172. package/lib/bridge/buildOptimisticOperation.js.map +0 -1
  173. package/lib/bridge/createTransaction.d.ts +0 -4
  174. package/lib/bridge/createTransaction.d.ts.map +0 -1
  175. package/lib/bridge/createTransaction.js +0 -24
  176. package/lib/bridge/createTransaction.js.map +0 -1
  177. package/lib/bridge/estimateMaxSpendable.d.ts +0 -5
  178. package/lib/bridge/estimateMaxSpendable.d.ts.map +0 -1
  179. package/lib/bridge/estimateMaxSpendable.js +0 -30
  180. package/lib/bridge/estimateMaxSpendable.js.map +0 -1
  181. package/lib/bridge/getFeesForTransaction.d.ts +0 -21
  182. package/lib/bridge/getFeesForTransaction.d.ts.map +0 -1
  183. package/lib/bridge/getFeesForTransaction.js +0 -39
  184. package/lib/bridge/getFeesForTransaction.js.map +0 -1
  185. package/lib/bridge/getTransactionStatus.d.ts +0 -4
  186. package/lib/bridge/getTransactionStatus.d.ts.map +0 -1
  187. package/lib/bridge/getTransactionStatus.js +0 -108
  188. package/lib/bridge/getTransactionStatus.js.map +0 -1
  189. package/lib/bridge/getTransactionStatus.test.d.ts +0 -2
  190. package/lib/bridge/getTransactionStatus.test.d.ts.map +0 -1
  191. package/lib/bridge/getTransactionStatus.test.js +0 -107
  192. package/lib/bridge/getTransactionStatus.test.js.map +0 -1
  193. package/lib/bridge/index.d.ts +0 -10
  194. package/lib/bridge/index.d.ts.map +0 -1
  195. package/lib/bridge/index.js +0 -59
  196. package/lib/bridge/index.js.map +0 -1
  197. package/lib/bridge/logic.d.ts +0 -10
  198. package/lib/bridge/logic.d.ts.map +0 -1
  199. package/lib/bridge/logic.js +0 -155
  200. package/lib/bridge/logic.js.map +0 -1
  201. package/lib/bridge/preload.d.ts +0 -9
  202. package/lib/bridge/preload.d.ts.map +0 -1
  203. package/lib/bridge/preload.js +0 -23
  204. package/lib/bridge/preload.js.map +0 -1
  205. package/lib/bridge/prepareTransaction.d.ts +0 -5
  206. package/lib/bridge/prepareTransaction.d.ts.map +0 -1
  207. package/lib/bridge/prepareTransaction.integ.test.d.ts +0 -2
  208. package/lib/bridge/prepareTransaction.integ.test.d.ts.map +0 -1
  209. package/lib/bridge/prepareTransaction.integ.test.js +0 -34
  210. package/lib/bridge/prepareTransaction.integ.test.js.map +0 -1
  211. package/lib/bridge/prepareTransaction.js +0 -57
  212. package/lib/bridge/prepareTransaction.js.map +0 -1
  213. package/lib/bridge/prepareTransaction.test.d.ts +0 -2
  214. package/lib/bridge/prepareTransaction.test.d.ts.map +0 -1
  215. package/lib/bridge/prepareTransaction.test.js +0 -178
  216. package/lib/bridge/prepareTransaction.test.js.map +0 -1
  217. package/lib/bridge/serialization.d.ts +0 -7
  218. package/lib/bridge/serialization.d.ts.map +0 -1
  219. package/lib/bridge/serialization.js +0 -26
  220. package/lib/bridge/serialization.js.map +0 -1
  221. package/lib/bridge/signOperation.d.ts +0 -16
  222. package/lib/bridge/signOperation.d.ts.map +0 -1
  223. package/lib/bridge/signOperation.js +0 -88
  224. package/lib/bridge/signOperation.js.map +0 -1
  225. package/lib/bridge/signOperation.test.d.ts +0 -2
  226. package/lib/bridge/signOperation.test.d.ts.map +0 -1
  227. package/lib/bridge/signOperation.test.js +0 -283
  228. package/lib/bridge/signOperation.test.js.map +0 -1
  229. package/lib/bridge/synchronization.d.ts +0 -5
  230. package/lib/bridge/synchronization.d.ts.map +0 -1
  231. package/lib/bridge/synchronization.integ.test.d.ts +0 -2
  232. package/lib/bridge/synchronization.integ.test.d.ts.map +0 -1
  233. package/lib/bridge/synchronization.integ.test.js +0 -32
  234. package/lib/bridge/synchronization.integ.test.js.map +0 -1
  235. package/lib/bridge/synchronization.js +0 -100
  236. package/lib/bridge/synchronization.js.map +0 -1
  237. package/lib/bridge/transaction.d.ts.map +0 -1
  238. package/lib/bridge/transaction.js.map +0 -1
  239. package/lib-es/bridge/broadcast.d.ts +0 -4
  240. package/lib-es/bridge/broadcast.d.ts.map +0 -1
  241. package/lib-es/bridge/broadcast.js +0 -7
  242. package/lib-es/bridge/broadcast.js.map +0 -1
  243. package/lib-es/bridge/broadcast.test.d.ts +0 -2
  244. package/lib-es/bridge/broadcast.test.d.ts.map +0 -1
  245. package/lib-es/bridge/broadcast.test.js +0 -31
  246. package/lib-es/bridge/broadcast.test.js.map +0 -1
  247. package/lib-es/bridge/buildOptimisticOperation.d.ts +0 -4
  248. package/lib-es/bridge/buildOptimisticOperation.d.ts.map +0 -1
  249. package/lib-es/bridge/buildOptimisticOperation.js +0 -21
  250. package/lib-es/bridge/buildOptimisticOperation.js.map +0 -1
  251. package/lib-es/bridge/createTransaction.d.ts +0 -4
  252. package/lib-es/bridge/createTransaction.d.ts.map +0 -1
  253. package/lib-es/bridge/createTransaction.js +0 -17
  254. package/lib-es/bridge/createTransaction.js.map +0 -1
  255. package/lib-es/bridge/estimateMaxSpendable.d.ts +0 -5
  256. package/lib-es/bridge/estimateMaxSpendable.d.ts.map +0 -1
  257. package/lib-es/bridge/estimateMaxSpendable.js +0 -23
  258. package/lib-es/bridge/estimateMaxSpendable.js.map +0 -1
  259. package/lib-es/bridge/getFeesForTransaction.d.ts +0 -21
  260. package/lib-es/bridge/getFeesForTransaction.d.ts.map +0 -1
  261. package/lib-es/bridge/getFeesForTransaction.js +0 -33
  262. package/lib-es/bridge/getFeesForTransaction.js.map +0 -1
  263. package/lib-es/bridge/getTransactionStatus.d.ts +0 -4
  264. package/lib-es/bridge/getTransactionStatus.d.ts.map +0 -1
  265. package/lib-es/bridge/getTransactionStatus.js +0 -101
  266. package/lib-es/bridge/getTransactionStatus.js.map +0 -1
  267. package/lib-es/bridge/getTransactionStatus.test.d.ts +0 -2
  268. package/lib-es/bridge/getTransactionStatus.test.d.ts.map +0 -1
  269. package/lib-es/bridge/getTransactionStatus.test.js +0 -102
  270. package/lib-es/bridge/getTransactionStatus.test.js.map +0 -1
  271. package/lib-es/bridge/index.d.ts +0 -10
  272. package/lib-es/bridge/index.d.ts.map +0 -1
  273. package/lib-es/bridge/index.js +0 -53
  274. package/lib-es/bridge/index.js.map +0 -1
  275. package/lib-es/bridge/logic.d.ts +0 -10
  276. package/lib-es/bridge/logic.d.ts.map +0 -1
  277. package/lib-es/bridge/logic.js +0 -145
  278. package/lib-es/bridge/logic.js.map +0 -1
  279. package/lib-es/bridge/preload.d.ts +0 -9
  280. package/lib-es/bridge/preload.d.ts.map +0 -1
  281. package/lib-es/bridge/preload.js +0 -17
  282. package/lib-es/bridge/preload.js.map +0 -1
  283. package/lib-es/bridge/prepareTransaction.d.ts +0 -5
  284. package/lib-es/bridge/prepareTransaction.d.ts.map +0 -1
  285. package/lib-es/bridge/prepareTransaction.integ.test.d.ts +0 -2
  286. package/lib-es/bridge/prepareTransaction.integ.test.d.ts.map +0 -1
  287. package/lib-es/bridge/prepareTransaction.integ.test.js +0 -29
  288. package/lib-es/bridge/prepareTransaction.integ.test.js.map +0 -1
  289. package/lib-es/bridge/prepareTransaction.js +0 -50
  290. package/lib-es/bridge/prepareTransaction.js.map +0 -1
  291. package/lib-es/bridge/prepareTransaction.test.d.ts +0 -2
  292. package/lib-es/bridge/prepareTransaction.test.d.ts.map +0 -1
  293. package/lib-es/bridge/prepareTransaction.test.js +0 -173
  294. package/lib-es/bridge/prepareTransaction.test.js.map +0 -1
  295. package/lib-es/bridge/serialization.d.ts +0 -7
  296. package/lib-es/bridge/serialization.d.ts.map +0 -1
  297. package/lib-es/bridge/serialization.js +0 -20
  298. package/lib-es/bridge/serialization.js.map +0 -1
  299. package/lib-es/bridge/signOperation.d.ts +0 -16
  300. package/lib-es/bridge/signOperation.d.ts.map +0 -1
  301. package/lib-es/bridge/signOperation.js +0 -83
  302. package/lib-es/bridge/signOperation.js.map +0 -1
  303. package/lib-es/bridge/signOperation.test.d.ts +0 -2
  304. package/lib-es/bridge/signOperation.test.d.ts.map +0 -1
  305. package/lib-es/bridge/signOperation.test.js +0 -255
  306. package/lib-es/bridge/signOperation.test.js.map +0 -1
  307. package/lib-es/bridge/synchronization.d.ts +0 -5
  308. package/lib-es/bridge/synchronization.d.ts.map +0 -1
  309. package/lib-es/bridge/synchronization.integ.test.d.ts +0 -2
  310. package/lib-es/bridge/synchronization.integ.test.d.ts.map +0 -1
  311. package/lib-es/bridge/synchronization.integ.test.js +0 -27
  312. package/lib-es/bridge/synchronization.integ.test.js.map +0 -1
  313. package/lib-es/bridge/synchronization.js +0 -70
  314. package/lib-es/bridge/synchronization.js.map +0 -1
  315. package/lib-es/bridge/transaction.d.ts.map +0 -1
  316. package/lib-es/bridge/transaction.js.map +0 -1
  317. package/src/bridge/broadcast.test.ts +0 -36
  318. package/src/bridge/broadcast.ts +0 -13
  319. package/src/bridge/buildOptimisticOperation.ts +0 -28
  320. package/src/bridge/createTransaction.ts +0 -19
  321. package/src/bridge/estimateMaxSpendable.ts +0 -37
  322. package/src/bridge/getFeesForTransaction.ts +0 -49
  323. package/src/bridge/getTransactionStatus.test.ts +0 -124
  324. package/src/bridge/getTransactionStatus.ts +0 -123
  325. package/src/bridge/index.ts +0 -74
  326. package/src/bridge/logic.ts +0 -171
  327. package/src/bridge/preload.ts +0 -18
  328. package/src/bridge/prepareTransaction.integ.test.ts +0 -35
  329. package/src/bridge/prepareTransaction.test.ts +0 -205
  330. package/src/bridge/prepareTransaction.ts +0 -69
  331. package/src/bridge/serialization.ts +0 -27
  332. package/src/bridge/signOperation.test.ts +0 -284
  333. package/src/bridge/signOperation.ts +0 -130
  334. package/src/bridge/synchronization.integ.test.ts +0 -33
  335. package/src/bridge/synchronization.ts +0 -100
@@ -10,7 +10,6 @@ import {
10
10
  isAPITransactionType,
11
11
  } from "../network/types";
12
12
  import { Operation } from "@ledgerhq/coin-framework/api/types";
13
- // import { TezosAsset } from "../api/types";
14
13
 
15
14
  /**
16
15
  * Returns list of "Transfer", "Delegate" and "Undelegate" Operations associated to an account.
@@ -38,25 +37,58 @@ export async function listOperations(
38
37
  options = { ...options, lastId: JSON.parse(token) };
39
38
  }
40
39
  const operations = await tzkt.getAccountOperations(address, options);
41
- const lastOperation = operations.slice(-1)[0];
40
+
41
+ // Apply limit after fetching since tzkt API might not respect the limit parameter
42
+ const limitedOperations = limit ? operations.slice(0, limit) : operations;
43
+
44
+ const lastOperation = limitedOperations.at(-1);
42
45
  // it's important to get the last id from the **unfiltered** operation list
43
46
  // otherwise we might miss operations
44
47
  const nextToken = lastOperation ? JSON.stringify(lastOperation?.id) : "";
45
- const filteredOperations = operations
48
+ const filteredOperations = limitedOperations
46
49
  .filter(op => isAPITransactionType(op) || isAPIDelegationType(op) || isAPIRevealType(op))
47
- .reduce((acc, op) => acc.concat(convertOperation(address, op)), [] as Operation[]);
50
+ .filter(op => {
51
+ // Filter out failed incoming tx
52
+ const hasFailed = op.status !== "applied";
53
+ if (hasFailed && isAPITransactionType(op)) {
54
+ const isIn = op.target?.address === address;
55
+ if (isIn) {
56
+ return false;
57
+ }
58
+ }
59
+ return true;
60
+ })
61
+ .map(op => convertOperation(address, op))
62
+ .flat();
48
63
  const sortedOperations = filteredOperations.sort(
49
64
  (a, b) => b.tx.date.getTime() - a.tx.date.getTime(),
50
65
  );
51
66
  return [sortedOperations, nextToken];
52
67
  }
53
68
 
69
+ /**
70
+ * Helper function to get the ledgerOpType for an operation
71
+ */
72
+ function getLedgerOpType(
73
+ operation: APITransactionType | APIDelegationType | APIRevealType,
74
+ normalizedType: Operation["type"],
75
+ ): string | undefined {
76
+ if (isAPIDelegationType(operation)) {
77
+ return operation.newDelegate?.address ? "DELEGATE" : "UNDELEGATE";
78
+ } else if (isAPIRevealType(operation)) {
79
+ return "REVEAL";
80
+ } else if (normalizedType === "FEES") {
81
+ return "FEES";
82
+ }
83
+ return undefined;
84
+ }
85
+
54
86
  // note that "initiator" of APITransactionType is never used in the conversion
55
87
  function convertOperation(
56
88
  address: string,
57
89
  operation: APITransactionType | APIDelegationType | APIRevealType,
58
90
  ): Operation {
59
- const { hash, sender, type, id } = operation;
91
+ const { hash, sender, id } = operation;
60
92
 
61
93
  let targetAddress = undefined;
62
94
  if (isAPITransactionType(operation)) {
@@ -66,22 +98,48 @@ function convertOperation(
66
98
  targetAddress = operation?.newDelegate?.address || operation?.prevDelegate?.address;
67
99
  }
68
100
 
69
- const recipients = [];
101
+ const recipients = targetAddress ? [targetAddress] : [];
70
102
  if (!targetAddress) {
71
103
  log("coin:tezos", "(logic/operations): No target address found for operation", operation);
72
- } else {
73
- recipients.push(targetAddress);
74
104
  }
75
105
 
76
106
  const senders = sender?.address ? [sender.address] : [];
77
107
 
78
- const amount = isAPIRevealType(operation) ? BigInt(0) : BigInt(operation.amount);
108
+ const amount = isAPIRevealType(operation) ? 0n : BigInt(operation.amount);
79
109
 
80
110
  const fee =
81
111
  BigInt(operation.storageFee ?? 0) +
82
112
  BigInt(operation.bakerFee ?? 0) +
83
113
  BigInt(operation.allocationFee ?? 0);
84
114
 
115
+ // Determine operation type inline
116
+ let normalizedType: Operation["type"];
117
+ if (isAPIDelegationType(operation)) {
118
+ normalizedType = operation.newDelegate?.address ? "DELEGATE" : "UNDELEGATE";
119
+ } else if (isAPITransactionType(operation)) {
120
+ const isOut = sender?.address === address;
121
+ const isIn = targetAddress === address;
122
+
123
+ if ((isOut && isIn) || amount === 0n) {
124
+ normalizedType = "FEES";
125
+ } else if (isOut) {
126
+ normalizedType = "OUT";
127
+ } else if (isIn) {
128
+ normalizedType = "IN";
129
+ } else {
130
+ normalizedType = "OUT"; // fallback
131
+ }
132
+ } else if (isAPIRevealType(operation)) {
133
+ normalizedType = "REVEAL";
134
+ } else {
135
+ // fallback for unknown types
136
+ log("coin:tezos", "(logic/operations): Unknown operation type, defaulting to OUT");
137
+ normalizedType = "OUT";
138
+ }
139
+
140
+ // Tezos uses "applied" for every sucess operation (something else=failed )
141
+ const hasFailed = operation.status && operation.status !== "applied";
142
+
85
143
  return {
86
144
  id: `${hash ?? ""}-${id}`,
87
145
  asset: { type: "native" },
@@ -97,7 +155,7 @@ function convertOperation(
97
155
  },
98
156
  date: new Date(operation.timestamp),
99
157
  },
100
- type: type,
158
+ type: normalizedType,
101
159
  value: amount,
102
160
  senders: senders,
103
161
  recipients: recipients,
@@ -105,6 +163,8 @@ function convertOperation(
105
163
  counter: operation.counter,
106
164
  gasLimit: operation.gasLimit,
107
165
  storageLimit: operation.storageLimit,
166
+ status: hasFailed ? "failed" : operation.status,
167
+ ledgerOpType: getLedgerOpType(operation, normalizedType),
108
168
  },
109
169
  };
110
170
  }
@@ -0,0 +1,274 @@
1
+ import { validateIntent } from "./validateIntent";
2
+ import * as estimateFeesModule from "./estimateFees";
3
+ import tzktApi from "../network/tzkt";
4
+ import coinConfig from "../config";
5
+ import {
6
+ RecipientRequired,
7
+ InvalidAddress,
8
+ InvalidAddressBecauseDestinationIsAlsoSource,
9
+ AmountRequired,
10
+ NotEnoughBalance,
11
+ } from "@ledgerhq/errors";
12
+
13
+ describe("validateIntent", () => {
14
+ const senderAddress = "tz1TzrmTBSuiVHV2VfMnGRMYvTEPCP42oSM8";
15
+ const validRecipient = "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx";
16
+
17
+ const mockEstimateFees = jest.spyOn(estimateFeesModule, "estimateFees");
18
+ const mockGetAccountByAddress = jest.spyOn(tzktApi, "getAccountByAddress");
19
+
20
+ beforeEach(() => {
21
+ jest.clearAllMocks();
22
+
23
+ coinConfig.setCoinConfig(() => ({
24
+ status: { type: "active" },
25
+ baker: { url: "http://baker.example.com" },
26
+ explorer: { url: "http://tezos.explorer.com", maxTxQuery: 100 },
27
+ node: { url: "http://tezos.node.com" },
28
+ fees: {
29
+ minGasLimit: 600,
30
+ minRevealGasLimit: 300,
31
+ minStorageLimit: 0,
32
+ minFees: 500,
33
+ minEstimatedFees: 500,
34
+ },
35
+ }));
36
+
37
+ mockEstimateFees.mockResolvedValue({
38
+ fees: BigInt(1000),
39
+ gasLimit: BigInt(10000),
40
+ storageLimit: BigInt(0),
41
+ estimatedFees: BigInt(1000),
42
+ });
43
+
44
+ mockGetAccountByAddress.mockResolvedValue({
45
+ type: "user",
46
+ address: senderAddress,
47
+ publicKey: "edpk...",
48
+ balance: 5000000,
49
+ revealed: true,
50
+ counter: 0,
51
+ delegationLevel: 0,
52
+ delegationTime: "2021-01-01T00:00:00Z",
53
+ numTransactions: 0,
54
+ firstActivityTime: "2021-01-01T00:00:00Z",
55
+ });
56
+ });
57
+
58
+ describe("recipient validation", () => {
59
+ it("should return RecipientRequired error when recipient is missing", async () => {
60
+ const result = await validateIntent({
61
+ intentType: "transaction",
62
+ asset: { type: "native" },
63
+ type: "send",
64
+ sender: senderAddress,
65
+ recipient: "",
66
+ amount: BigInt(1000),
67
+ });
68
+
69
+ expect(result.errors.recipient).toBeInstanceOf(RecipientRequired);
70
+ });
71
+
72
+ it("should return InvalidAddress error for invalid recipient", async () => {
73
+ const result = await validateIntent({
74
+ intentType: "transaction",
75
+ asset: { type: "native" },
76
+ type: "send",
77
+ sender: senderAddress,
78
+ recipient: "invalid_address",
79
+ amount: BigInt(1000),
80
+ });
81
+
82
+ expect(result.errors.recipient).toBeInstanceOf(InvalidAddress);
83
+ });
84
+
85
+ it("should return InvalidAddressBecauseDestinationIsAlsoSource when sender equals recipient", async () => {
86
+ const result = await validateIntent({
87
+ intentType: "transaction",
88
+ asset: { type: "native" },
89
+ type: "send",
90
+ sender: senderAddress,
91
+ recipient: senderAddress,
92
+ amount: BigInt(1000),
93
+ });
94
+
95
+ expect(result.errors.recipient).toBeInstanceOf(InvalidAddressBecauseDestinationIsAlsoSource);
96
+ });
97
+ });
98
+
99
+ describe("amount validation", () => {
100
+ it("should return AmountRequired error when amount is zero and not useAllAmount", async () => {
101
+ const result = await validateIntent({
102
+ intentType: "transaction",
103
+ asset: { type: "native" },
104
+ type: "send",
105
+ sender: senderAddress,
106
+ recipient: validRecipient,
107
+ amount: BigInt(0),
108
+ useAllAmount: false,
109
+ });
110
+
111
+ expect(result.errors.amount).toBeInstanceOf(AmountRequired);
112
+ });
113
+
114
+ it("should not return AmountRequired error when useAllAmount is true", async () => {
115
+ const result = await validateIntent({
116
+ intentType: "transaction",
117
+ asset: { type: "native" },
118
+ type: "send",
119
+ sender: senderAddress,
120
+ recipient: validRecipient,
121
+ amount: BigInt(0),
122
+ useAllAmount: true,
123
+ });
124
+
125
+ expect(result.errors.amount).toBeUndefined();
126
+ });
127
+ });
128
+
129
+ describe("balance validation", () => {
130
+ it("should return NotEnoughBalance error when amount exceeds balance", async () => {
131
+ const balance = 1000000; // 1 XTZ
132
+ const amount = 2000000; // 2 XTZ
133
+
134
+ mockGetAccountByAddress.mockResolvedValue({
135
+ type: "user",
136
+ address: senderAddress,
137
+ publicKey: "edpk...",
138
+ balance,
139
+ revealed: true,
140
+ counter: 0,
141
+ delegationLevel: 0,
142
+ delegationTime: "2021-01-01T00:00:00Z",
143
+ numTransactions: 0,
144
+ firstActivityTime: "2021-01-01T00:00:00Z",
145
+ });
146
+
147
+ const result = await validateIntent({
148
+ intentType: "transaction",
149
+ asset: { type: "native" },
150
+ type: "send",
151
+ sender: senderAddress,
152
+ recipient: validRecipient,
153
+ amount: BigInt(amount),
154
+ });
155
+
156
+ expect(result.errors.amount).toBeInstanceOf(NotEnoughBalance);
157
+ });
158
+
159
+ it("should pass validation when amount is within balance", async () => {
160
+ const balance = 5000000; // 5 XTZ
161
+ const amount = 1000000; // 1 XTZ
162
+
163
+ mockGetAccountByAddress.mockResolvedValue({
164
+ type: "user",
165
+ address: senderAddress,
166
+ publicKey: "edpk...",
167
+ balance,
168
+ revealed: true,
169
+ counter: 0,
170
+ delegationLevel: 0,
171
+ delegationTime: "2021-01-01T00:00:00Z",
172
+ numTransactions: 0,
173
+ firstActivityTime: "2021-01-01T00:00:00Z",
174
+ });
175
+
176
+ const result = await validateIntent({
177
+ intentType: "transaction",
178
+ asset: { type: "native" },
179
+ type: "send",
180
+ sender: senderAddress,
181
+ recipient: validRecipient,
182
+ amount: BigInt(amount),
183
+ });
184
+
185
+ expect(result.errors.amount).toBeUndefined();
186
+ expect(result.amount).toBe(BigInt(amount));
187
+ });
188
+ });
189
+
190
+ describe("transaction types", () => {
191
+ it("should pass validation for delegate transaction", async () => {
192
+ const result = await validateIntent({
193
+ intentType: "staking",
194
+ asset: { type: "native" },
195
+ type: "delegate",
196
+ sender: senderAddress,
197
+ recipient: validRecipient,
198
+ amount: BigInt(0),
199
+ });
200
+
201
+ expect(result.errors).toEqual({});
202
+ });
203
+
204
+ it("should pass validation for undelegate transaction", async () => {
205
+ const result = await validateIntent({
206
+ intentType: "staking",
207
+ asset: { type: "native" },
208
+ type: "undelegate",
209
+ sender: senderAddress,
210
+ recipient: "",
211
+ amount: BigInt(0),
212
+ });
213
+
214
+ expect(result.errors).toEqual({});
215
+ });
216
+
217
+ it("should handle stake intent (mapped to delegate)", async () => {
218
+ const result = await validateIntent({
219
+ intentType: "staking",
220
+ asset: { type: "native" },
221
+ type: "stake",
222
+ sender: senderAddress,
223
+ recipient: validRecipient,
224
+ amount: BigInt(0),
225
+ });
226
+
227
+ expect(result.errors).toEqual({});
228
+ });
229
+
230
+ it("should handle unstake intent (mapped to undelegate)", async () => {
231
+ const result = await validateIntent({
232
+ intentType: "staking",
233
+ asset: { type: "native" },
234
+ type: "unstake",
235
+ sender: senderAddress,
236
+ recipient: "",
237
+ amount: BigInt(0),
238
+ });
239
+
240
+ expect(result.errors).toEqual({});
241
+ });
242
+ });
243
+
244
+ describe("successful validation", () => {
245
+ it("should return valid result with correct values", async () => {
246
+ const amount = BigInt(1000000);
247
+ const estimatedFees = BigInt(1500);
248
+
249
+ mockEstimateFees.mockResolvedValue({
250
+ fees: BigInt(1000),
251
+ gasLimit: BigInt(10000),
252
+ storageLimit: BigInt(0),
253
+ estimatedFees,
254
+ });
255
+
256
+ const result = await validateIntent({
257
+ intentType: "transaction",
258
+ asset: { type: "native" },
259
+ type: "send",
260
+ sender: senderAddress,
261
+ recipient: validRecipient,
262
+ amount,
263
+ });
264
+
265
+ expect(result).toMatchObject({
266
+ errors: {},
267
+ warnings: {},
268
+ estimatedFees,
269
+ amount,
270
+ totalSpent: amount + estimatedFees,
271
+ });
272
+ });
273
+ });
274
+ });
@@ -0,0 +1,207 @@
1
+ import type { TransactionIntent, TransactionValidation } from "@ledgerhq/coin-framework/api/types";
2
+ import {
3
+ InvalidAddress,
4
+ RecipientRequired,
5
+ RecommendUndelegation,
6
+ NotEnoughBalance,
7
+ NotEnoughBalanceToDelegate,
8
+ AmountRequired,
9
+ InvalidAddressBecauseDestinationIsAlsoSource,
10
+ } from "@ledgerhq/errors";
11
+ import { validateAddress, ValidationResult } from "@taquito/utils";
12
+ import api from "../network/tzkt";
13
+ import { estimateFees } from "./estimateFees";
14
+ import { InvalidAddressBecauseAlreadyDelegated } from "../types/errors";
15
+ import { mapIntentTypeToTezosMode } from "../utils";
16
+
17
+ /**
18
+ * Validates basic recipient and amount for send transactions
19
+ */
20
+ function validateBasicSendParams(intent: TransactionIntent): Record<string, Error> {
21
+ const errors: Record<string, Error> = {};
22
+
23
+ if (intent.type !== "send") {
24
+ return errors;
25
+ }
26
+
27
+ if (!intent.recipient) {
28
+ errors.recipient = new RecipientRequired("");
29
+ } else if (validateAddress(intent.recipient) !== ValidationResult.VALID) {
30
+ errors.recipient = new InvalidAddress(undefined, { currencyName: "Tezos" });
31
+ } else if (intent.sender === intent.recipient) {
32
+ errors.recipient = new InvalidAddressBecauseDestinationIsAlsoSource();
33
+ }
34
+
35
+ if (intent.amount === 0n && !intent.useAllAmount) {
36
+ errors.amount = new AmountRequired();
37
+ } else if (intent.amount < 0n) {
38
+ errors.amount = new NotEnoughBalance();
39
+ }
40
+
41
+ return errors;
42
+ }
43
+
44
+ /**
45
+ * Validates specific transaction constraints based on account state
46
+ */
47
+ function validateTransactionConstraints(
48
+ intent: TransactionIntent,
49
+ senderInfo: any,
50
+ ): Record<string, Error> {
51
+ const errors: Record<string, Error> = {};
52
+
53
+ // send max not allowed on delegated accounts (must undelegate acc first)
54
+ if (intent.type === "send" && intent.useAllAmount) {
55
+ if (senderInfo.type === "user" && senderInfo.delegate?.address) {
56
+ errors.amount = new RecommendUndelegation();
57
+ }
58
+ }
59
+
60
+ // stake requires non-zero balance
61
+ if (intent.type === "stake") {
62
+ const balance = BigInt(senderInfo.balance || "0");
63
+ if (balance === 0n) {
64
+ errors.amount = new NotEnoughBalanceToDelegate();
65
+ }
66
+ }
67
+
68
+ return errors;
69
+ }
70
+
71
+ /**
72
+ * Maps Taquito-specific errors to our error types
73
+ */
74
+ function mapTaquitoErrors(taquitoError: string, intentType: string): Record<string, Error> {
75
+ const errors: Record<string, Error> = {};
76
+
77
+ if (taquitoError.endsWith("balance_too_low") || taquitoError.endsWith("subtraction_underflow")) {
78
+ if (intentType === "stake") {
79
+ errors.amount = new NotEnoughBalanceToDelegate();
80
+ } else {
81
+ errors.amount = new NotEnoughBalance();
82
+ }
83
+ } else if (taquitoError.endsWith("delegate.unchanged") && intentType === "stake") {
84
+ errors.recipient = new InvalidAddressBecauseAlreadyDelegated();
85
+ } else if (taquitoError.includes("empty_implicit_contract")) {
86
+ errors.amount = new NotEnoughBalanceToDelegate();
87
+ } else {
88
+ errors.amount = new Error(taquitoError);
89
+ }
90
+
91
+ return errors;
92
+ }
93
+
94
+ /**
95
+ * Calculates final amounts based on transaction type
96
+ */
97
+ function calculateAmounts(
98
+ intent: TransactionIntent,
99
+ senderInfo: any,
100
+ estimatedFees: bigint,
101
+ ): { amount: bigint; totalSpent: bigint } {
102
+ if (intent.type === "stake" || intent.type === "unstake") {
103
+ const amount = BigInt(senderInfo.type === "user" ? senderInfo.balance : 0);
104
+ return { amount, totalSpent: estimatedFees };
105
+ }
106
+
107
+ if (intent.type === "send" && intent.useAllAmount) {
108
+ if (senderInfo.type === "user") {
109
+ const balance = BigInt(senderInfo.balance);
110
+ const amount = balance > estimatedFees ? balance - estimatedFees : 0n;
111
+ return { amount, totalSpent: amount + estimatedFees };
112
+ }
113
+ return { amount: 0n, totalSpent: 0n };
114
+ }
115
+
116
+ const amount = intent.amount;
117
+ return { amount, totalSpent: amount + estimatedFees };
118
+ }
119
+
120
+ /**
121
+ * Validates balance coverage for the transaction
122
+ */
123
+ function validateBalanceCoverage(senderInfo: any, totalSpent: bigint): Record<string, Error> {
124
+ const errors: Record<string, Error> = {};
125
+
126
+ if (senderInfo.type === "user") {
127
+ const accountBalance = BigInt(senderInfo.balance);
128
+ if (totalSpent > accountBalance) {
129
+ errors.amount = new NotEnoughBalance();
130
+ }
131
+ }
132
+
133
+ return errors;
134
+ }
135
+
136
+ export async function validateIntent(intent: TransactionIntent): Promise<TransactionValidation> {
137
+ const errors: Record<string, Error> = {};
138
+ const warnings: Record<string, Error> = {};
139
+ let estimatedFees: bigint;
140
+ let amount: bigint;
141
+ let totalSpent: bigint;
142
+
143
+ // Basic validation for send transactions
144
+ const basicErrors = validateBasicSendParams(intent);
145
+ Object.assign(errors, basicErrors);
146
+
147
+ if (Object.keys(errors).length > 0) {
148
+ return { errors, warnings, estimatedFees: 0n, amount: 0n, totalSpent: 0n };
149
+ }
150
+
151
+ try {
152
+ // Get sender account information
153
+ const senderInfo = await api.getAccountByAddress(intent.sender);
154
+ if (senderInfo.type !== "user") throw new Error("unexpected account type");
155
+
156
+ // Validate transaction-specific constraints
157
+ const constraintErrors = validateTransactionConstraints(intent, senderInfo);
158
+ Object.assign(errors, constraintErrors);
159
+
160
+ if (Object.keys(errors).length > 0) {
161
+ return { errors, warnings, estimatedFees: 0n, amount: 0n, totalSpent: 0n };
162
+ }
163
+
164
+ // Estimate fees
165
+ if (senderInfo.revealed) {
166
+ const estimation = await estimateFees({
167
+ account: {
168
+ address: intent.sender,
169
+ revealed: senderInfo.revealed,
170
+ balance: BigInt(senderInfo.balance),
171
+ xpub: intent.senderPublicKey ?? senderInfo.publicKey,
172
+ },
173
+ transaction: {
174
+ mode: mapIntentTypeToTezosMode(intent.type),
175
+ recipient: intent.recipient,
176
+ amount: intent.amount,
177
+ useAllAmount: !!intent.useAllAmount,
178
+ },
179
+ });
180
+ estimatedFees = estimation.estimatedFees;
181
+
182
+ // Handle Taquito errors
183
+ if (estimation.taquitoError) {
184
+ const taquitoErrors = mapTaquitoErrors(estimation.taquitoError, intent.type);
185
+ Object.assign(errors, taquitoErrors);
186
+ }
187
+ } else {
188
+ estimatedFees = 2000n;
189
+ }
190
+
191
+ // Calculate final amounts
192
+ const amounts = calculateAmounts(intent, senderInfo, estimatedFees);
193
+ amount = amounts.amount;
194
+ totalSpent = amounts.totalSpent;
195
+
196
+ // Final balance validation
197
+ const balanceErrors = validateBalanceCoverage(senderInfo, totalSpent);
198
+ Object.assign(errors, balanceErrors);
199
+ } catch (e) {
200
+ errors.estimation = e as Error;
201
+ estimatedFees = 0n;
202
+ amount = intent.amount;
203
+ totalSpent = intent.amount;
204
+ }
205
+
206
+ return { errors, warnings, estimatedFees, amount, totalSpent };
207
+ }
@@ -1,5 +1,5 @@
1
1
  import { BigNumber } from "bignumber.js";
2
- import type { Transaction, TransactionRaw } from "../types";
2
+ import type { Transaction, TransactionRaw } from "./types";
3
3
  import { formatTransactionStatus } from "@ledgerhq/coin-framework/formatters";
4
4
  import {
5
5
  fromTransactionCommonRaw,
@@ -58,9 +58,9 @@ export const fromTransactionRaw = (tr: TransactionRaw): Transaction => {
58
58
  fees: new BigNumber(networkInfo.fees),
59
59
  },
60
60
  fees: tr.fees ? new BigNumber(tr.fees) : null,
61
- gasLimit: tr.gasLimit ? new BigNumber(tr.gasLimit) : null,
62
- storageLimit: tr.storageLimit ? new BigNumber(tr.storageLimit) : null,
63
- estimatedFees: tr.estimatedFees ? new BigNumber(tr.estimatedFees) : null,
61
+ gasLimit: tr.gasLimit ? new BigNumber(tr.gasLimit) : undefined,
62
+ storageLimit: tr.storageLimit ? new BigNumber(tr.storageLimit) : undefined,
63
+ estimatedFees: tr.estimatedFees ? new BigNumber(tr.estimatedFees) : undefined,
64
64
  taquitoError: tr.taquitoError,
65
65
  };
66
66
  };
@@ -47,6 +47,7 @@ export function createFixtureAccount(account?: Partial<TezosAccount>): TezosAcco
47
47
  swapHistory: [],
48
48
 
49
49
  tezosResources,
50
+ stakingPositions: account?.stakingPositions || [],
50
51
  };
51
52
  }
52
53
 
@@ -7,6 +7,7 @@ import type {
7
7
  TransactionStatusCommon,
8
8
  TransactionStatusCommonRaw,
9
9
  } from "@ledgerhq/types-live";
10
+ import type { Stake } from "@ledgerhq/coin-framework/api/index";
10
11
  import type { BigNumber } from "bignumber.js";
11
12
  import { TezosOperationMode } from "./model";
12
13
 
@@ -79,7 +80,11 @@ export type Delegation = {
79
80
  sendShouldWarnDelegation: boolean;
80
81
  };
81
82
 
82
- export type TezosAccount = Account & { tezosResources: TezosResources };
83
+ export type StakingPosition = Stake;
84
+ export type TezosAccount = Account & {
85
+ tezosResources: TezosResources;
86
+ stakingPositions: StakingPosition[];
87
+ };
83
88
  export function isTezosAccount(account: Account): account is TezosAccount {
84
89
  return "tezosResources" in account;
85
90
  }