@ledgerhq/coin-tezos 7.12.0 → 8.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 (189) hide show
  1. package/CHANGELOG.md +28 -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/craftRawOperations.d.ts +2 -1
  16. package/lib/logic/craftRawOperations.d.ts.map +1 -1
  17. package/lib/logic/craftRawOperations.js +5 -8
  18. package/lib/logic/craftRawOperations.js.map +1 -1
  19. package/lib/logic/craftTransaction.d.ts +3 -2
  20. package/lib/logic/craftTransaction.d.ts.map +1 -1
  21. package/lib/logic/craftTransaction.js +6 -9
  22. package/lib/logic/craftTransaction.js.map +1 -1
  23. package/lib/logic/estimateFees.d.ts +2 -1
  24. package/lib/logic/estimateFees.d.ts.map +1 -1
  25. package/lib/logic/estimateFees.js +24 -19
  26. package/lib/logic/estimateFees.js.map +1 -1
  27. package/lib/logic/getBalance.d.ts +2 -1
  28. package/lib/logic/getBalance.d.ts.map +1 -1
  29. package/lib/logic/getBalance.js +7 -8
  30. package/lib/logic/getBalance.js.map +1 -1
  31. package/lib/logic/getBlock.d.ts +2 -1
  32. package/lib/logic/getBlock.d.ts.map +1 -1
  33. package/lib/logic/getBlock.js +12 -10
  34. package/lib/logic/getBlock.js.map +1 -1
  35. package/lib/logic/getBlockInfo.d.ts +2 -1
  36. package/lib/logic/getBlockInfo.d.ts.map +1 -1
  37. package/lib/logic/getBlockInfo.js +5 -3
  38. package/lib/logic/getBlockInfo.js.map +1 -1
  39. package/lib/logic/getStakes.d.ts +3 -2
  40. package/lib/logic/getStakes.d.ts.map +1 -1
  41. package/lib/logic/getStakes.js +9 -9
  42. package/lib/logic/getStakes.js.map +1 -1
  43. package/lib/logic/lastBlock.d.ts +2 -1
  44. package/lib/logic/lastBlock.d.ts.map +1 -1
  45. package/lib/logic/lastBlock.js +4 -6
  46. package/lib/logic/lastBlock.js.map +1 -1
  47. package/lib/logic/listOperations.d.ts +2 -1
  48. package/lib/logic/listOperations.d.ts.map +1 -1
  49. package/lib/logic/listOperations.js +8 -6
  50. package/lib/logic/listOperations.js.map +1 -1
  51. package/lib/logic/tezosToolkit.d.ts +2 -1
  52. package/lib/logic/tezosToolkit.d.ts.map +1 -1
  53. package/lib/logic/tezosToolkit.js +2 -6
  54. package/lib/logic/tezosToolkit.js.map +1 -1
  55. package/lib/logic/validateIntent.d.ts +2 -1
  56. package/lib/logic/validateIntent.d.ts.map +1 -1
  57. package/lib/logic/validateIntent.js +12 -13
  58. package/lib/logic/validateIntent.js.map +1 -1
  59. package/lib/network/bakers.d.ts +5 -4
  60. package/lib/network/bakers.d.ts.map +1 -1
  61. package/lib/network/bakers.js +9 -10
  62. package/lib/network/bakers.js.map +1 -1
  63. package/lib/network/index.d.ts +1 -1
  64. package/lib/network/index.d.ts.map +1 -1
  65. package/lib/network/index.js +2 -5
  66. package/lib/network/index.js.map +1 -1
  67. package/lib/network/tzkt.d.ts +16 -9
  68. package/lib/network/tzkt.d.ts.map +1 -1
  69. package/lib/network/tzkt.js +341 -333
  70. package/lib/network/tzkt.js.map +1 -1
  71. package/lib/utils.d.ts +2 -1
  72. package/lib/utils.d.ts.map +1 -1
  73. package/lib/utils.js +1 -6
  74. package/lib/utils.js.map +1 -1
  75. package/lib-es/api/index.d.ts +1 -2
  76. package/lib-es/api/index.d.ts.map +1 -1
  77. package/lib-es/api/index.js +40 -36
  78. package/lib-es/api/index.js.map +1 -1
  79. package/lib-es/api/types.d.ts +3 -2
  80. package/lib-es/api/types.d.ts.map +1 -1
  81. package/lib-es/config.d.ts +3 -1
  82. package/lib-es/config.d.ts.map +1 -1
  83. package/lib-es/config.js.map +1 -1
  84. package/lib-es/logic/broadcast.d.ts +2 -1
  85. package/lib-es/logic/broadcast.d.ts.map +1 -1
  86. package/lib-es/logic/broadcast.js +3 -2
  87. package/lib-es/logic/broadcast.js.map +1 -1
  88. package/lib-es/logic/craftRawOperations.d.ts +2 -1
  89. package/lib-es/logic/craftRawOperations.d.ts.map +1 -1
  90. package/lib-es/logic/craftRawOperations.js +5 -5
  91. package/lib-es/logic/craftRawOperations.js.map +1 -1
  92. package/lib-es/logic/craftTransaction.d.ts +3 -2
  93. package/lib-es/logic/craftTransaction.d.ts.map +1 -1
  94. package/lib-es/logic/craftTransaction.js +6 -6
  95. package/lib-es/logic/craftTransaction.js.map +1 -1
  96. package/lib-es/logic/estimateFees.d.ts +2 -1
  97. package/lib-es/logic/estimateFees.d.ts.map +1 -1
  98. package/lib-es/logic/estimateFees.js +24 -16
  99. package/lib-es/logic/estimateFees.js.map +1 -1
  100. package/lib-es/logic/getBalance.d.ts +2 -1
  101. package/lib-es/logic/getBalance.d.ts.map +1 -1
  102. package/lib-es/logic/getBalance.js +5 -3
  103. package/lib-es/logic/getBalance.js.map +1 -1
  104. package/lib-es/logic/getBlock.d.ts +2 -1
  105. package/lib-es/logic/getBlock.d.ts.map +1 -1
  106. package/lib-es/logic/getBlock.js +10 -8
  107. package/lib-es/logic/getBlock.js.map +1 -1
  108. package/lib-es/logic/getBlockInfo.d.ts +2 -1
  109. package/lib-es/logic/getBlockInfo.d.ts.map +1 -1
  110. package/lib-es/logic/getBlockInfo.js +4 -2
  111. package/lib-es/logic/getBlockInfo.js.map +1 -1
  112. package/lib-es/logic/getStakes.d.ts +3 -2
  113. package/lib-es/logic/getStakes.d.ts.map +1 -1
  114. package/lib-es/logic/getStakes.js +9 -6
  115. package/lib-es/logic/getStakes.js.map +1 -1
  116. package/lib-es/logic/lastBlock.d.ts +2 -1
  117. package/lib-es/logic/lastBlock.d.ts.map +1 -1
  118. package/lib-es/logic/lastBlock.js +4 -3
  119. package/lib-es/logic/lastBlock.js.map +1 -1
  120. package/lib-es/logic/listOperations.d.ts +2 -1
  121. package/lib-es/logic/listOperations.d.ts.map +1 -1
  122. package/lib-es/logic/listOperations.js +7 -5
  123. package/lib-es/logic/listOperations.js.map +1 -1
  124. package/lib-es/logic/tezosToolkit.d.ts +2 -1
  125. package/lib-es/logic/tezosToolkit.d.ts.map +1 -1
  126. package/lib-es/logic/tezosToolkit.js +2 -3
  127. package/lib-es/logic/tezosToolkit.js.map +1 -1
  128. package/lib-es/logic/validateIntent.d.ts +2 -1
  129. package/lib-es/logic/validateIntent.d.ts.map +1 -1
  130. package/lib-es/logic/validateIntent.js +10 -8
  131. package/lib-es/logic/validateIntent.js.map +1 -1
  132. package/lib-es/network/bakers.d.ts +5 -4
  133. package/lib-es/network/bakers.d.ts.map +1 -1
  134. package/lib-es/network/bakers.js +9 -10
  135. package/lib-es/network/bakers.js.map +1 -1
  136. package/lib-es/network/index.d.ts +1 -1
  137. package/lib-es/network/index.d.ts.map +1 -1
  138. package/lib-es/network/index.js +1 -1
  139. package/lib-es/network/index.js.map +1 -1
  140. package/lib-es/network/tzkt.d.ts +16 -9
  141. package/lib-es/network/tzkt.d.ts.map +1 -1
  142. package/lib-es/network/tzkt.js +340 -333
  143. package/lib-es/network/tzkt.js.map +1 -1
  144. package/lib-es/utils.d.ts +2 -1
  145. package/lib-es/utils.d.ts.map +1 -1
  146. package/lib-es/utils.js +1 -3
  147. package/lib-es/utils.js.map +1 -1
  148. package/package.json +2 -2
  149. package/src/api/index-mainnet.integ.test.ts +34 -30
  150. package/src/api/index.integ.test.ts +69 -53
  151. package/src/api/index.test.ts +99 -60
  152. package/src/api/index.ts +52 -36
  153. package/src/api/types.ts +3 -2
  154. package/src/config.ts +4 -1
  155. package/src/logic/broadcast.integ.test.ts +12 -13
  156. package/src/logic/broadcast.ts +4 -2
  157. package/src/logic/craftRawOperations.test.ts +47 -33
  158. package/src/logic/craftRawOperations.ts +6 -4
  159. package/src/logic/craftTransaction.integ.test.ts +12 -5
  160. package/src/logic/craftTransaction.test.ts +39 -31
  161. package/src/logic/craftTransaction.ts +10 -5
  162. package/src/logic/estimateFees.integ.test.ts +7 -7
  163. package/src/logic/estimateFees.test.ts +52 -49
  164. package/src/logic/estimateFees.ts +34 -22
  165. package/src/logic/getBalance.test.ts +19 -17
  166. package/src/logic/getBalance.ts +6 -3
  167. package/src/logic/getBlock.integ.test.ts +8 -30
  168. package/src/logic/getBlock.test.ts +91 -81
  169. package/src/logic/getBlock.ts +11 -8
  170. package/src/logic/getBlockInfo.integ.test.ts +9 -18
  171. package/src/logic/getBlockInfo.test.ts +19 -9
  172. package/src/logic/getBlockInfo.ts +5 -2
  173. package/src/logic/getStakes.test.ts +46 -49
  174. package/src/logic/getStakes.ts +14 -5
  175. package/src/logic/lastBlock.ts +5 -3
  176. package/src/logic/listOperations.integ.test.ts +40 -67
  177. package/src/logic/listOperations.test.ts +65 -59
  178. package/src/logic/listOperations.ts +8 -3
  179. package/src/logic/tezosToolkit.ts +3 -3
  180. package/src/logic/validateIntent.test.ts +78 -74
  181. package/src/logic/validateIntent.ts +17 -7
  182. package/src/network/bakers.integ.test.ts +2 -5
  183. package/src/network/bakers.test.ts +5 -6
  184. package/src/network/bakers.ts +13 -10
  185. package/src/network/index.ts +2 -1
  186. package/src/network/tzkt.integ.test.ts +3 -14
  187. package/src/network/tzkt.test.ts +128 -96
  188. package/src/network/tzkt.ts +426 -393
  189. package/src/utils.ts +2 -3
@@ -6,15 +6,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
6
6
  };
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
8
  exports.fetchBlockReveals = exports.fetchBlockOriginations = exports.fetchBlockStaking = exports.fetchBlockDelegations = exports.fetchBlockTokenTransfers = exports.fetchBlockTransactions = exports.fetchAllTransactions = void 0;
9
+ exports.createTzktApi = createTzktApi;
9
10
  const url_1 = __importDefault(require("url"));
10
11
  const live_network_1 = __importDefault(require("@ledgerhq/live-network"));
11
12
  const logs_1 = require("@ledgerhq/logs");
12
- const config_1 = __importDefault(require("../config"));
13
13
  /** TzKT hard-caps `limit` at 10 000; we use a safer page size to stay well under that. */
14
14
  const BLOCK_PAGE_SIZE = 1000;
15
15
  /** Maximum number of IDs per `id.in` request to keep URLs under the Cloudflare proxy limit (~16 KB). */
16
16
  const ID_IN_CHUNK_SIZE = 100;
17
- const getExplorerUrl = () => config_1.default.getCoinConfig().explorer.url;
18
17
  /**
19
18
  * Coalesces concurrent `getAccountByAddress` calls for the same explorer+address into a
20
19
  * single request. During a sync both `getBalance` and the readiness hook hit this endpoint
@@ -35,349 +34,359 @@ function chunk(arr, size) {
35
34
  return result;
36
35
  }
37
36
  /**
38
- * Internal helper shared by `getOperationsTransactions` and `getOperationsOrigination`.
39
- * Both endpoints accept the same query shape; only the URL path differs.
37
+ * Builds the TzKT explorer client bound to the given coin config (ADR-019). The caller resolves the
38
+ * config from its {@link Context} and passes it in, rather than the client reading a module-level
39
+ * singleton.
40
40
  */
41
- async function getOperationsByType(type, level, cursor, apiQueryParams = {}) {
42
- // "sort.asc": "id" guarantees forward progress for cursor-based paging (offset.cr).
43
- // Without an explicit sort the API default may be descending, which would cause the
44
- // cursor to go backwards and produce duplicates or an infinite loop.
45
- const params = {
46
- 'level.gte': level,
47
- limit: BLOCK_PAGE_SIZE,
48
- 'sort.asc': 'id',
49
- ...clearUndefined(apiQueryParams),
50
- };
51
- if (cursor !== undefined)
52
- params['offset.cr'] = cursor;
53
- const { data } = await (0, live_network_1.default)({
54
- url: `${getExplorerUrl()}/v1/operations/${type}`,
55
- params,
56
- });
57
- return data;
58
- }
59
- const api = {
60
- async getBlockCount() {
61
- const { data } = await (0, live_network_1.default)({
62
- url: `${getExplorerUrl()}/v1/blocks/count`,
63
- });
64
- return data;
65
- },
66
- async getLastBlock() {
67
- const { data } = await (0, live_network_1.default)({
68
- url: `${getExplorerUrl()}/v1/blocks`,
69
- params: {
70
- 'sort.desc': 'level',
71
- },
72
- });
73
- return {
74
- hash: data[0].hash,
75
- level: data[0].level,
76
- date: new Date(data[0].timestamp),
77
- };
78
- },
79
- async getAccountByAddress(address) {
80
- const key = `${getExplorerUrl()}|${address}`;
81
- const existing = accountByAddressInflight.get(key);
82
- if (existing)
83
- return existing;
84
- const request = (0, live_network_1.default)({
85
- url: `${getExplorerUrl()}/v1/accounts/${address}`,
86
- })
87
- .then(({ data }) => data)
88
- .finally(() => accountByAddressInflight.delete(key));
89
- accountByAddressInflight.set(key, request);
90
- return request;
91
- },
92
- /**
93
- * Returns the total `actualAmount` (mutez) summed over the account's `finalizable`
94
- * unstake requests — the portion of `unstakedBalance` whose unlock cycle has been
95
- * reached and that can be reclaimed via `finalize_unstake`. The complementary
96
- * `unstakedBalance - finalizable` portion is still in the deactivation delay window.
97
- *
98
- * TzKT's account endpoint does not expose this split, so we sum from
99
- * `/v1/staking/unstake_requests`. https://api.tzkt.io/#operation/Staking_GetUnstakeRequests
100
- *
101
- * `limit=1000` covers any realistic number of concurrent finalizable requests for
102
- * a single staker — we do not paginate.
103
- */
104
- async getUnstakeRequestsFinalizable(address) {
105
- const { data } = await (0, live_network_1.default)({
106
- url: `${getExplorerUrl()}/v1/staking/unstake_requests`,
107
- params: {
108
- 'staker.eq': address,
109
- status: 'finalizable',
110
- 'select.values': 'actualAmount',
111
- limit: 1000,
112
- },
113
- });
114
- return data.reduce((sum, n) => sum + BigInt(n), 0n);
115
- },
116
- /**
117
- * Pending + finalizable unstake requests, by id ascending. Uses `status.ne=finalized` because
118
- * TzKT ignores `status.in=pending,finalizable` on this endpoint and returns finalized requests.
119
- * https://api.tzkt.io/#operation/Staking_GetUnstakeRequests
120
- */
121
- async getUnstakeRequests(address) {
122
- const { data } = await (0, live_network_1.default)({
123
- url: `${getExplorerUrl()}/v1/staking/unstake_requests`,
124
- params: {
125
- 'staker.eq': address,
126
- 'status.ne': 'finalized',
127
- 'sort.asc': 'id',
128
- limit: 1000,
129
- },
130
- });
131
- return data;
132
- },
133
- // https://api.tzkt.io/#operation/Accounts_GetOperations
134
- async getAccountOperations(address, query) {
135
- // Remove undefined from query
136
- Object.entries(query).forEach(([key, value]) => value === undefined && delete query[key]);
137
- const { data } = await (0, live_network_1.default)({
138
- url: url_1.default.format({
139
- pathname: `${getExplorerUrl()}/v1/accounts/${address}/operations`,
140
- query,
141
- }),
142
- });
143
- return data;
144
- },
145
- // https://api.tzkt.io/#operation/Blocks_GetByLevel
146
- async getBlockByLevel(level) {
147
- const { data } = await (0, live_network_1.default)({
148
- url: `${getExplorerUrl()}/v1/blocks/${level}`,
149
- });
150
- return data;
151
- },
152
- /**
153
- * Resolves block hashes for the given levels in a single request.
154
- * Uses `/v1/blocks?level.in=...&select.values=level,hash`, which TzKT honours
155
- * (unlike `/v1/blocks/{level}?select=...`, where `select` is ignored). Used
156
- * for cheap backfill of `block.hash` on operations whose level is known but
157
- * whose response omits the block field (e.g. `/accounts/{addr}/operations`
158
- * for staking ops). Levels that don't resolve are absent from the result map.
159
- */
160
- async getBlockHashesByLevels(levels) {
161
- if (levels.length === 0)
162
- return new Map();
163
- const { data } = await (0, live_network_1.default)({
164
- url: `${getExplorerUrl()}/v1/blocks`,
165
- params: {
166
- 'level.in': levels.join(','),
167
- 'select.values': 'level,hash',
168
- limit: levels.length,
169
- },
170
- });
171
- return new Map(data);
172
- },
41
+ function createTzktApi(config) {
42
+ const explorerUrl = config.explorer.url;
173
43
  /**
174
- * Fetches a single page of `transaction` operations at the given block level.
175
- * Internal used by `fetchBlockTransactions` which handles pagination.
176
- * https://api.tzkt.io/#operation/Operations_GetTransactions
44
+ * Internal helper shared by `getOperationsTransactions` and `getOperationsOrigination`.
45
+ * Both endpoints accept the same query shape; only the URL path differs.
177
46
  */
178
- async getBlockTransactionsPage(level, cursor) {
47
+ async function getOperationsByType(type, level, cursor, apiQueryParams = {}) {
179
48
  // "sort.asc": "id" guarantees forward progress for cursor-based paging (offset.cr).
180
49
  // Without an explicit sort the API default may be descending, which would cause the
181
50
  // cursor to go backwards and produce duplicates or an infinite loop.
182
- const params = { level, limit: BLOCK_PAGE_SIZE, 'sort.asc': 'id' };
183
- if (cursor !== undefined)
184
- params['offset.cr'] = cursor;
185
- const { data } = await (0, live_network_1.default)({
186
- url: `${getExplorerUrl()}/v1/operations/transactions`,
187
- params,
188
- });
189
- return data;
190
- },
191
- /**
192
- * Fetches a list of `transaction` operations after the given level.
193
- * https://api.tzkt.io/#operation/Operations_GetTransactions
194
- */
195
- async getOperationsTransactions(level, cursor, apiQueryParams = {}) {
196
- return getOperationsByType('transactions', level, cursor, apiQueryParams);
197
- },
198
- /**
199
- * Fetches a list of `originations` operations after the given level.
200
- * https://api.tzkt.io/#operation/Operations_GetOriginations
201
- */
202
- async getOperationsOrigination(level, cursor, apiQueryParams = {}) {
203
- return getOperationsByType('originations', level, cursor, apiQueryParams);
204
- },
205
- /**
206
- * Fetches a single page of FA token transfers at the given block level.
207
- * Internal — used by `fetchBlockTokenTransfers` which handles pagination.
208
- * https://api.tzkt.io/#operation/Tokens_GetTokenTransfers
209
- */
210
- async getBlockTokenTransfersPage(level, cursor) {
211
- // Same rationale as getBlockTransactionsPage: explicit ascending sort keeps the
212
- // offset.cr cursor advancing forward regardless of the API's default ordering.
213
51
  const params = {
214
- level,
52
+ 'level.gte': level,
215
53
  limit: BLOCK_PAGE_SIZE,
216
54
  'sort.asc': 'id',
217
- 'token.standard': 'fa2',
218
- };
219
- if (cursor !== undefined)
220
- params['offset.cr'] = cursor;
221
- const { data } = await (0, live_network_1.default)({
222
- url: `${getExplorerUrl()}/v1/tokens/transfers`,
223
- params,
224
- });
225
- return data;
226
- },
227
- /**
228
- * Fetches the latest FA token transfers since the given level.
229
- * https://api.tzkt.io/#operation/Tokens_GetTokenTransfers
230
- */
231
- async getTokenTransfers(apiQueryParams = {}) {
232
- const params = {
233
55
  ...clearUndefined(apiQueryParams),
234
56
  };
235
- const { data } = await (0, live_network_1.default)({
236
- url: `${getExplorerUrl()}/v1/tokens/transfers`,
237
- params,
238
- });
239
- return data;
240
- },
241
- /**
242
- * Fetches a single page of `origination` operations at the given block level.
243
- * Internal — used by `fetchBlockOriginations` which handles pagination.
244
- * https://api.tzkt.io/#operation/Operations_GetOriginations
245
- */
246
- async getBlockOriginationsPage(level, cursor) {
247
- const params = { level, limit: BLOCK_PAGE_SIZE, 'sort.asc': 'id' };
248
- if (cursor !== undefined)
249
- params['offset.cr'] = cursor;
250
- const { data } = await (0, live_network_1.default)({
251
- url: `${getExplorerUrl()}/v1/operations/originations`,
252
- params,
253
- });
254
- return data;
255
- },
256
- /**
257
- * Fetches a single page of `reveal` operations at the given block level.
258
- * Internal — used by `fetchBlockReveals` which handles pagination.
259
- * https://api.tzkt.io/#operation/Operations_GetReveals
260
- */
261
- async getBlockRevealsPage(level, cursor) {
262
- const params = { level, limit: BLOCK_PAGE_SIZE, 'sort.asc': 'id' };
263
- if (cursor !== undefined)
264
- params['offset.cr'] = cursor;
265
- const { data } = await (0, live_network_1.default)({
266
- url: `${getExplorerUrl()}/v1/operations/reveals`,
267
- params,
268
- });
269
- return data;
270
- },
271
- /**
272
- * Fetches a single page of `delegation` operations at the given block level.
273
- * Internal — used by `fetchBlockDelegations` which handles pagination.
274
- * https://api.tzkt.io/#operation/Operations_GetDelegations
275
- */
276
- async getBlockDelegationsPage(level, cursor) {
277
- const params = { level, limit: BLOCK_PAGE_SIZE, 'sort.asc': 'id' };
278
- if (cursor !== undefined)
279
- params['offset.cr'] = cursor;
280
- const { data } = await (0, live_network_1.default)({
281
- url: `${getExplorerUrl()}/v1/operations/delegations`,
282
- params,
283
- });
284
- return data;
285
- },
286
- /**
287
- * Fetches a single page of `staking` operations at the given block level.
288
- * Internal — used by `fetchBlockStaking` which handles pagination.
289
- * https://api.tzkt.io/#operation/Operations_GetStaking
290
- */
291
- async getBlockStakingPage(level, cursor) {
292
- const params = { level, limit: BLOCK_PAGE_SIZE, 'sort.asc': 'id' };
293
57
  if (cursor !== undefined)
294
58
  params['offset.cr'] = cursor;
295
59
  const { data } = await (0, live_network_1.default)({
296
- url: `${getExplorerUrl()}/v1/operations/staking`,
60
+ url: `${explorerUrl}/v1/operations/${type}`,
297
61
  params,
298
62
  });
299
63
  return data;
300
- },
301
- /**
302
- * Fetches FA2 token transfers for a given account.
303
- * Translates `query.sort` to TzKT's `sort.asc=id` / `sort.desc=id`.
304
- * The lower-level `getTokenTransfers` helper is a generic pass-through and does not pin the sort.
305
- * https://api.tzkt.io/#operation/Tokens_GetTokenTransfers
306
- */
307
- async getAccountTokenTransfers(address, query) {
308
- const sortKey = query.sort === 'Descending' ? 'sort.desc' : 'sort.asc';
309
- const params = {
310
- 'anyof.from.to': address,
311
- 'token.standard': 'fa2',
312
- [sortKey]: 'id',
313
- limit: query.limit,
314
- 'level.ge': query['level.ge'],
315
- 'level.lt': query['level.lt'],
316
- 'level.gt': query['level.gt'],
317
- 'id.lt': query['id.lt'],
318
- 'id.gt': query['id.gt'],
319
- };
320
- const data = await api.getTokenTransfers(clearUndefined(params));
321
- const transactionIds = data
322
- .map((t) => t.transactionId)
323
- .filter((id) => typeof id === 'number');
324
- const originationIds = data
325
- .map((t) => t.originationId)
326
- .filter((id) => typeof id === 'number');
327
- if (transactionIds.length === 0 && originationIds.length === 0) {
328
- return [];
329
- }
330
- const transactions = transactionIds.length
331
- ? (await Promise.all(chunk(transactionIds, ID_IN_CHUNK_SIZE).map((ids) => api.getOperationsTransactions(query['level.ge'] || 0, undefined, {
332
- 'id.in': ids.join(','),
333
- })))).flat()
334
- : [];
335
- const originations = originationIds.length
336
- ? (await Promise.all(chunk(originationIds, ID_IN_CHUNK_SIZE).map((ids) => api.getOperationsOrigination(query['level.ge'] || 0, undefined, {
337
- 'id.in': ids.join(','),
338
- })))).flat()
339
- : [];
340
- // Build id -> operation maps once so per-transfer lookups are O(1) instead of O(n).
341
- // Keys are widened to `number | undefined` so lookups with a missing id naturally
342
- // return `undefined` (no entry is ever stored under the `undefined` key).
343
- const transactionsById = new Map(transactions.map((t) => [t.id, t]));
344
- const originationsById = new Map(originations.map((o) => [o.id, o]));
345
- return data.map((token) => {
346
- const transaction = transactionsById.get(token.transactionId);
347
- const origination = originationsById.get(token.originationId);
64
+ }
65
+ const api = {
66
+ async getBlockCount() {
67
+ const { data } = await (0, live_network_1.default)({
68
+ url: `${explorerUrl}/v1/blocks/count`,
69
+ });
70
+ return data;
71
+ },
72
+ async getLastBlock() {
73
+ const { data } = await (0, live_network_1.default)({
74
+ url: `${explorerUrl}/v1/blocks`,
75
+ params: {
76
+ 'sort.desc': 'level',
77
+ },
78
+ });
348
79
  return {
349
- ...token,
350
- hash: transaction?.hash ?? origination?.hash ?? '',
351
- block: transaction?.block ?? origination?.block ?? '',
80
+ hash: data[0].hash,
81
+ level: data[0].level,
82
+ date: new Date(data[0].timestamp),
352
83
  };
353
- });
354
- },
355
- /**
356
- * Fetches FA2 token balances for a given account.
357
- * When `tokenFilter` is omitted, all FA2 token balances are returned.
358
- * Pass `tokenFilter` to query a specific FA2 contract + token id (e.g. send-max for FA2).
359
- * https://api.tzkt.io/#operation/Tokens_GetTokenBalances
360
- */
361
- async getTokensBalances(address, tokenFilter) {
362
- const params = {
363
- account: address,
364
- 'token.standard': 'fa2',
365
- };
366
- if (tokenFilter) {
367
- params['token.contract'] = tokenFilter.contractAddress;
368
- params['token.tokenId'] = String(tokenFilter.tokenId);
369
- }
370
- const { data } = await (0, live_network_1.default)({
371
- url: `${getExplorerUrl()}/v1/tokens/balances`,
372
- params,
373
- });
374
- return data;
375
- },
376
- };
84
+ },
85
+ async getAccountByAddress(address) {
86
+ const key = `${explorerUrl}|${address}`;
87
+ const existing = accountByAddressInflight.get(key);
88
+ if (existing)
89
+ return existing;
90
+ const request = (0, live_network_1.default)({
91
+ url: `${explorerUrl}/v1/accounts/${address}`,
92
+ })
93
+ .then(({ data }) => data)
94
+ .finally(() => accountByAddressInflight.delete(key));
95
+ accountByAddressInflight.set(key, request);
96
+ return request;
97
+ },
98
+ /**
99
+ * Returns the total `actualAmount` (mutez) summed over the account's `finalizable`
100
+ * unstake requests — the portion of `unstakedBalance` whose unlock cycle has been
101
+ * reached and that can be reclaimed via `finalize_unstake`. The complementary
102
+ * `unstakedBalance - finalizable` portion is still in the deactivation delay window.
103
+ *
104
+ * TzKT's account endpoint does not expose this split, so we sum from
105
+ * `/v1/staking/unstake_requests`. https://api.tzkt.io/#operation/Staking_GetUnstakeRequests
106
+ *
107
+ * `limit=1000` covers any realistic number of concurrent finalizable requests for
108
+ * a single staker — we do not paginate.
109
+ */
110
+ async getUnstakeRequestsFinalizable(address) {
111
+ const { data } = await (0, live_network_1.default)({
112
+ url: `${explorerUrl}/v1/staking/unstake_requests`,
113
+ params: {
114
+ 'staker.eq': address,
115
+ status: 'finalizable',
116
+ 'select.values': 'actualAmount',
117
+ limit: 1000,
118
+ },
119
+ });
120
+ return data.reduce((sum, n) => sum + BigInt(n), 0n);
121
+ },
122
+ /**
123
+ * Pending + finalizable unstake requests, by id ascending. Uses `status.ne=finalized` because
124
+ * TzKT ignores `status.in=pending,finalizable` on this endpoint and returns finalized requests.
125
+ * https://api.tzkt.io/#operation/Staking_GetUnstakeRequests
126
+ */
127
+ async getUnstakeRequests(address) {
128
+ const { data } = await (0, live_network_1.default)({
129
+ url: `${explorerUrl}/v1/staking/unstake_requests`,
130
+ params: {
131
+ 'staker.eq': address,
132
+ 'status.ne': 'finalized',
133
+ 'sort.asc': 'id',
134
+ limit: 1000,
135
+ },
136
+ });
137
+ return data;
138
+ },
139
+ // https://api.tzkt.io/#operation/Accounts_GetOperations
140
+ async getAccountOperations(address, query) {
141
+ // Remove undefined from query
142
+ Object.entries(query).forEach(([key, value]) => value === undefined && delete query[key]);
143
+ const { data } = await (0, live_network_1.default)({
144
+ url: url_1.default.format({
145
+ pathname: `${explorerUrl}/v1/accounts/${address}/operations`,
146
+ query,
147
+ }),
148
+ });
149
+ return data;
150
+ },
151
+ // https://api.tzkt.io/#operation/Blocks_GetByLevel
152
+ async getBlockByLevel(level) {
153
+ const { data } = await (0, live_network_1.default)({
154
+ url: `${explorerUrl}/v1/blocks/${level}`,
155
+ });
156
+ return data;
157
+ },
158
+ /**
159
+ * Resolves block hashes for the given levels in a single request.
160
+ * Uses `/v1/blocks?level.in=...&select.values=level,hash`, which TzKT honours
161
+ * (unlike `/v1/blocks/{level}?select=...`, where `select` is ignored). Used
162
+ * for cheap backfill of `block.hash` on operations whose level is known but
163
+ * whose response omits the block field (e.g. `/accounts/{addr}/operations`
164
+ * for staking ops). Levels that don't resolve are absent from the result map.
165
+ */
166
+ async getBlockHashesByLevels(levels) {
167
+ if (levels.length === 0)
168
+ return new Map();
169
+ const { data } = await (0, live_network_1.default)({
170
+ url: `${explorerUrl}/v1/blocks`,
171
+ params: {
172
+ 'level.in': levels.join(','),
173
+ 'select.values': 'level,hash',
174
+ limit: levels.length,
175
+ },
176
+ });
177
+ return new Map(data);
178
+ },
179
+ /**
180
+ * Fetches a single page of `transaction` operations at the given block level.
181
+ * Internal — used by `fetchBlockTransactions` which handles pagination.
182
+ * https://api.tzkt.io/#operation/Operations_GetTransactions
183
+ */
184
+ async getBlockTransactionsPage(level, cursor) {
185
+ // "sort.asc": "id" guarantees forward progress for cursor-based paging (offset.cr).
186
+ // Without an explicit sort the API default may be descending, which would cause the
187
+ // cursor to go backwards and produce duplicates or an infinite loop.
188
+ const params = { level, limit: BLOCK_PAGE_SIZE, 'sort.asc': 'id' };
189
+ if (cursor !== undefined)
190
+ params['offset.cr'] = cursor;
191
+ const { data } = await (0, live_network_1.default)({
192
+ url: `${explorerUrl}/v1/operations/transactions`,
193
+ params,
194
+ });
195
+ return data;
196
+ },
197
+ /**
198
+ * Fetches a list of `transaction` operations after the given level.
199
+ * https://api.tzkt.io/#operation/Operations_GetTransactions
200
+ */
201
+ async getOperationsTransactions(level, cursor, apiQueryParams = {}) {
202
+ return getOperationsByType('transactions', level, cursor, apiQueryParams);
203
+ },
204
+ /**
205
+ * Fetches a list of `originations` operations after the given level.
206
+ * https://api.tzkt.io/#operation/Operations_GetOriginations
207
+ */
208
+ async getOperationsOrigination(level, cursor, apiQueryParams = {}) {
209
+ return getOperationsByType('originations', level, cursor, apiQueryParams);
210
+ },
211
+ /**
212
+ * Fetches a single page of FA token transfers at the given block level.
213
+ * Internal — used by `fetchBlockTokenTransfers` which handles pagination.
214
+ * https://api.tzkt.io/#operation/Tokens_GetTokenTransfers
215
+ */
216
+ async getBlockTokenTransfersPage(level, cursor) {
217
+ // Same rationale as getBlockTransactionsPage: explicit ascending sort keeps the
218
+ // offset.cr cursor advancing forward regardless of the API's default ordering.
219
+ const params = {
220
+ level,
221
+ limit: BLOCK_PAGE_SIZE,
222
+ 'sort.asc': 'id',
223
+ 'token.standard': 'fa2',
224
+ };
225
+ if (cursor !== undefined)
226
+ params['offset.cr'] = cursor;
227
+ const { data } = await (0, live_network_1.default)({
228
+ url: `${explorerUrl}/v1/tokens/transfers`,
229
+ params,
230
+ });
231
+ return data;
232
+ },
233
+ /**
234
+ * Fetches the latest FA token transfers since the given level.
235
+ * https://api.tzkt.io/#operation/Tokens_GetTokenTransfers
236
+ */
237
+ async getTokenTransfers(apiQueryParams = {}) {
238
+ const params = {
239
+ ...clearUndefined(apiQueryParams),
240
+ };
241
+ const { data } = await (0, live_network_1.default)({
242
+ url: `${explorerUrl}/v1/tokens/transfers`,
243
+ params,
244
+ });
245
+ return data;
246
+ },
247
+ /**
248
+ * Fetches a single page of `origination` operations at the given block level.
249
+ * Internal — used by `fetchBlockOriginations` which handles pagination.
250
+ * https://api.tzkt.io/#operation/Operations_GetOriginations
251
+ */
252
+ async getBlockOriginationsPage(level, cursor) {
253
+ const params = { level, limit: BLOCK_PAGE_SIZE, 'sort.asc': 'id' };
254
+ if (cursor !== undefined)
255
+ params['offset.cr'] = cursor;
256
+ const { data } = await (0, live_network_1.default)({
257
+ url: `${explorerUrl}/v1/operations/originations`,
258
+ params,
259
+ });
260
+ return data;
261
+ },
262
+ /**
263
+ * Fetches a single page of `reveal` operations at the given block level.
264
+ * Internal — used by `fetchBlockReveals` which handles pagination.
265
+ * https://api.tzkt.io/#operation/Operations_GetReveals
266
+ */
267
+ async getBlockRevealsPage(level, cursor) {
268
+ const params = { level, limit: BLOCK_PAGE_SIZE, 'sort.asc': 'id' };
269
+ if (cursor !== undefined)
270
+ params['offset.cr'] = cursor;
271
+ const { data } = await (0, live_network_1.default)({
272
+ url: `${explorerUrl}/v1/operations/reveals`,
273
+ params,
274
+ });
275
+ return data;
276
+ },
277
+ /**
278
+ * Fetches a single page of `delegation` operations at the given block level.
279
+ * Internal — used by `fetchBlockDelegations` which handles pagination.
280
+ * https://api.tzkt.io/#operation/Operations_GetDelegations
281
+ */
282
+ async getBlockDelegationsPage(level, cursor) {
283
+ const params = { level, limit: BLOCK_PAGE_SIZE, 'sort.asc': 'id' };
284
+ if (cursor !== undefined)
285
+ params['offset.cr'] = cursor;
286
+ const { data } = await (0, live_network_1.default)({
287
+ url: `${explorerUrl}/v1/operations/delegations`,
288
+ params,
289
+ });
290
+ return data;
291
+ },
292
+ /**
293
+ * Fetches a single page of `staking` operations at the given block level.
294
+ * Internal — used by `fetchBlockStaking` which handles pagination.
295
+ * https://api.tzkt.io/#operation/Operations_GetStaking
296
+ */
297
+ async getBlockStakingPage(level, cursor) {
298
+ const params = { level, limit: BLOCK_PAGE_SIZE, 'sort.asc': 'id' };
299
+ if (cursor !== undefined)
300
+ params['offset.cr'] = cursor;
301
+ const { data } = await (0, live_network_1.default)({
302
+ url: `${explorerUrl}/v1/operations/staking`,
303
+ params,
304
+ });
305
+ return data;
306
+ },
307
+ /**
308
+ * Fetches FA2 token transfers for a given account.
309
+ * Translates `query.sort` to TzKT's `sort.asc=id` / `sort.desc=id`.
310
+ * The lower-level `getTokenTransfers` helper is a generic pass-through and does not pin the sort.
311
+ * https://api.tzkt.io/#operation/Tokens_GetTokenTransfers
312
+ */
313
+ async getAccountTokenTransfers(address, query) {
314
+ const sortKey = query.sort === 'Descending' ? 'sort.desc' : 'sort.asc';
315
+ const params = {
316
+ 'anyof.from.to': address,
317
+ 'token.standard': 'fa2',
318
+ [sortKey]: 'id',
319
+ limit: query.limit,
320
+ 'level.ge': query['level.ge'],
321
+ 'level.lt': query['level.lt'],
322
+ 'level.gt': query['level.gt'],
323
+ 'id.lt': query['id.lt'],
324
+ 'id.gt': query['id.gt'],
325
+ };
326
+ const data = await api.getTokenTransfers(clearUndefined(params));
327
+ const transactionIds = data
328
+ .map((t) => t.transactionId)
329
+ .filter((id) => typeof id === 'number');
330
+ const originationIds = data
331
+ .map((t) => t.originationId)
332
+ .filter((id) => typeof id === 'number');
333
+ if (transactionIds.length === 0 && originationIds.length === 0) {
334
+ return [];
335
+ }
336
+ const transactions = transactionIds.length
337
+ ? (await Promise.all(chunk(transactionIds, ID_IN_CHUNK_SIZE).map((ids) => api.getOperationsTransactions(query['level.ge'] || 0, undefined, {
338
+ 'id.in': ids.join(','),
339
+ })))).flat()
340
+ : [];
341
+ const originations = originationIds.length
342
+ ? (await Promise.all(chunk(originationIds, ID_IN_CHUNK_SIZE).map((ids) => api.getOperationsOrigination(query['level.ge'] || 0, undefined, {
343
+ 'id.in': ids.join(','),
344
+ })))).flat()
345
+ : [];
346
+ // Build id -> operation maps once so per-transfer lookups are O(1) instead of O(n).
347
+ // Keys are widened to `number | undefined` so lookups with a missing id naturally
348
+ // return `undefined` (no entry is ever stored under the `undefined` key).
349
+ const transactionsById = new Map(transactions.map((t) => [t.id, t]));
350
+ const originationsById = new Map(originations.map((o) => [o.id, o]));
351
+ return data.map((token) => {
352
+ const transaction = transactionsById.get(token.transactionId);
353
+ const origination = originationsById.get(token.originationId);
354
+ return {
355
+ ...token,
356
+ hash: transaction?.hash ?? origination?.hash ?? '',
357
+ block: transaction?.block ?? origination?.block ?? '',
358
+ };
359
+ });
360
+ },
361
+ /**
362
+ * Fetches FA2 token balances for a given account.
363
+ * When `tokenFilter` is omitted, all FA2 token balances are returned.
364
+ * Pass `tokenFilter` to query a specific FA2 contract + token id (e.g. send-max for FA2).
365
+ * https://api.tzkt.io/#operation/Tokens_GetTokenBalances
366
+ */
367
+ async getTokensBalances(address, tokenFilter) {
368
+ const params = {
369
+ account: address,
370
+ 'token.standard': 'fa2',
371
+ };
372
+ if (tokenFilter) {
373
+ params['token.contract'] = tokenFilter.contractAddress;
374
+ params['token.tokenId'] = String(tokenFilter.tokenId);
375
+ }
376
+ const { data } = await (0, live_network_1.default)({
377
+ url: `${explorerUrl}/v1/tokens/balances`,
378
+ params,
379
+ });
380
+ return data;
381
+ },
382
+ };
383
+ return api;
384
+ }
377
385
  // TODO this has same purpose as api/listOperations
378
- const fetchAllTransactions = async (address, lastId) => {
386
+ const fetchAllTransactions = async (config, address, lastId) => {
387
+ const api = createTzktApi(config);
379
388
  let ops = [];
380
- let maxIteration = config_1.default.getCoinConfig().explorer.maxTxQuery;
389
+ let maxIteration = config.explorer.maxTxQuery;
381
390
  do {
382
391
  const newOps = await api.getAccountOperations(address, {
383
392
  lastId,
@@ -406,10 +415,10 @@ exports.fetchAllTransactions = fetchAllTransactions;
406
415
  * requests when needed and is therefore safe for dense blocks.
407
416
  * A safety cap (`maxTxQuery`) prevents infinite loops on pathological responses.
408
417
  */
409
- async function fetchBlockPaginated(pageFn, level, label) {
418
+ async function fetchBlockPaginated(config, pageFn, level, label) {
410
419
  const items = [];
411
420
  let cursor;
412
- let maxIteration = config_1.default.getCoinConfig().explorer.maxTxQuery;
421
+ let maxIteration = config.explorer.maxTxQuery;
413
422
  do {
414
423
  const page = await pageFn(level, cursor);
415
424
  if (page.length === 0)
@@ -424,17 +433,16 @@ async function fetchBlockPaginated(pageFn, level, label) {
424
433
  }
425
434
  return items;
426
435
  }
427
- const fetchBlockTransactions = (level) => fetchBlockPaginated(api.getBlockTransactionsPage, level, 'fetchBlockTransactions');
436
+ const fetchBlockTransactions = (config, level) => fetchBlockPaginated(config, createTzktApi(config).getBlockTransactionsPage, level, 'fetchBlockTransactions');
428
437
  exports.fetchBlockTransactions = fetchBlockTransactions;
429
- const fetchBlockTokenTransfers = (level) => fetchBlockPaginated(api.getBlockTokenTransfersPage, level, 'fetchBlockTokenTransfers');
438
+ const fetchBlockTokenTransfers = (config, level) => fetchBlockPaginated(config, createTzktApi(config).getBlockTokenTransfersPage, level, 'fetchBlockTokenTransfers');
430
439
  exports.fetchBlockTokenTransfers = fetchBlockTokenTransfers;
431
- const fetchBlockDelegations = (level) => fetchBlockPaginated(api.getBlockDelegationsPage, level, 'fetchBlockDelegations');
440
+ const fetchBlockDelegations = (config, level) => fetchBlockPaginated(config, createTzktApi(config).getBlockDelegationsPage, level, 'fetchBlockDelegations');
432
441
  exports.fetchBlockDelegations = fetchBlockDelegations;
433
- const fetchBlockStaking = (level) => fetchBlockPaginated(api.getBlockStakingPage, level, 'fetchBlockStaking');
442
+ const fetchBlockStaking = (config, level) => fetchBlockPaginated(config, createTzktApi(config).getBlockStakingPage, level, 'fetchBlockStaking');
434
443
  exports.fetchBlockStaking = fetchBlockStaking;
435
- const fetchBlockOriginations = (level) => fetchBlockPaginated(api.getBlockOriginationsPage, level, 'fetchBlockOriginations');
444
+ const fetchBlockOriginations = (config, level) => fetchBlockPaginated(config, createTzktApi(config).getBlockOriginationsPage, level, 'fetchBlockOriginations');
436
445
  exports.fetchBlockOriginations = fetchBlockOriginations;
437
- const fetchBlockReveals = (level) => fetchBlockPaginated(api.getBlockRevealsPage, level, 'fetchBlockReveals');
446
+ const fetchBlockReveals = (config, level) => fetchBlockPaginated(config, createTzktApi(config).getBlockRevealsPage, level, 'fetchBlockReveals');
438
447
  exports.fetchBlockReveals = fetchBlockReveals;
439
- exports.default = api;
440
448
  //# sourceMappingURL=tzkt.js.map