@radix-effects/gateway 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,771 @@
1
+ import { Config, Data, Effect } from "effect";
2
+ import { GatewayApiClient as GatewayApiClient$1, ResponseError as ResponseError$1 } from "@radixdlt/babylon-gateway-api-sdk";
3
+ import { z } from "zod";
4
+ import { BigNumber } from "bignumber.js";
5
+
6
+ //#region src/gatewayApiClient.ts
7
+ var AccountLockerNotFoundError = class extends Data.TaggedError("AccountLockerNotFoundError") {};
8
+ var InternalServerError = class extends Data.TaggedError("InternalServerError") {};
9
+ var InvalidRequestError = class extends Data.TaggedError("InvalidRequestError") {};
10
+ var InvalidEntityError = class extends Data.TaggedError("InvalidEntityError") {};
11
+ var EntityNotFoundError = class extends Data.TaggedError("EntityNotFoundError") {};
12
+ var NotSyncedUpError = class extends Data.TaggedError("NotSyncedUpError") {};
13
+ var TransactionNotFoundError = class extends Data.TaggedError("TransactionNotFoundError") {};
14
+ var InvalidTransactionError = class extends Data.TaggedError("InvalidTransactionError") {};
15
+ var ResponseError = class extends Data.TaggedError("ResponseError") {};
16
+ var ErrorResponse = class extends Data.TaggedError("ErrorResponse") {};
17
+ var RateLimitExceededError = class extends Data.TaggedError("RateLimitExceededError") {};
18
+ var UnknownGatewayError = class extends Data.TaggedError("UnknownGatewayError") {};
19
+ var GatewayApiClient = class extends Effect.Service()("GatewayApiClient", { effect: Effect.gen(function* () {
20
+ const networkId = yield* Config.number("NETWORK_ID").pipe(Config.withDefault(1));
21
+ const basePath = yield* Config.string("GATEWAY_URL").pipe(Config.withDefault(void 0));
22
+ const applicationName = yield* Config.string("APPLICATION_NAME").pipe(Config.withDefault("@radix-effects/gateway"));
23
+ const gatewayApiKey = yield* Config.string("GATEWAY_BASIC_AUTH").pipe(Config.withDefault(void 0));
24
+ const gatewayApiClient = GatewayApiClient$1.initialize({
25
+ networkId,
26
+ basePath,
27
+ applicationName,
28
+ headers: gatewayApiKey ? { Authorization: `Basic ${gatewayApiKey}` } : void 0
29
+ });
30
+ const wrapMethod = (fn) => {
31
+ return (...args) => Effect.tryPromise({
32
+ try: () => fn(...args),
33
+ catch: (error) => {
34
+ if (typeof error === "object" && error !== null && "name" in error) {
35
+ if (error instanceof ResponseError$1) {
36
+ if (error.errorResponse) {
37
+ switch (error.errorResponse.details?.type) {
38
+ case "AccountLockerNotFoundError": return new AccountLockerNotFoundError({
39
+ ...error.errorResponse.details,
40
+ code: error.errorResponse.code,
41
+ message: error.message
42
+ });
43
+ case "InvalidRequestError": return new InvalidRequestError({
44
+ ...error.errorResponse.details,
45
+ code: error.errorResponse.code,
46
+ message: error.message
47
+ });
48
+ case "EntityNotFoundError": return new EntityNotFoundError({
49
+ ...error.errorResponse.details,
50
+ code: error.errorResponse.code,
51
+ message: error.message
52
+ });
53
+ case "InternalServerError": return new InternalServerError({
54
+ ...error.errorResponse.details,
55
+ code: error.errorResponse.code,
56
+ message: error.message
57
+ });
58
+ case "InvalidEntityError": return new InvalidEntityError({
59
+ ...error.errorResponse.details,
60
+ code: error.errorResponse.code,
61
+ message: error.message
62
+ });
63
+ case "InvalidTransactionError": return new InvalidTransactionError({
64
+ ...error.errorResponse.details,
65
+ code: error.errorResponse.code,
66
+ message: error.message
67
+ });
68
+ case "NotSyncedUpError": return new NotSyncedUpError({
69
+ ...error.errorResponse.details,
70
+ code: error.errorResponse.code,
71
+ message: error.message
72
+ });
73
+ case "TransactionNotFoundError": return new TransactionNotFoundError({
74
+ ...error.errorResponse.details,
75
+ code: error.errorResponse.code,
76
+ message: error.message
77
+ });
78
+ }
79
+ return new ErrorResponse(error.errorResponse);
80
+ }
81
+ if (error.fetchResponse.status === 429) return new RateLimitExceededError({
82
+ code: error.fetchResponse.status,
83
+ message: error.fetchResponse.statusText,
84
+ retryAfter: Number.parseInt(error.fetchResponse.headers.get("retry-after") ?? "0")
85
+ });
86
+ return new ResponseError(error);
87
+ }
88
+ }
89
+ return new UnknownGatewayError({ error });
90
+ }
91
+ });
92
+ };
93
+ return {
94
+ state: {
95
+ getEntityDetailsVaultAggregated: wrapMethod(gatewayApiClient.state.getEntityDetailsVaultAggregated.bind(gatewayApiClient.state)),
96
+ getValidators: wrapMethod(gatewayApiClient.state.getValidators.bind(gatewayApiClient.state)),
97
+ innerClient: {
98
+ stateEntityDetails: wrapMethod(gatewayApiClient.state.innerClient.stateEntityDetails.bind(gatewayApiClient.state.innerClient)),
99
+ entityFungiblesPage: wrapMethod(gatewayApiClient.state.innerClient.entityFungiblesPage.bind(gatewayApiClient.state.innerClient)),
100
+ entityNonFungiblesPage: wrapMethod(gatewayApiClient.state.innerClient.entityNonFungiblesPage.bind(gatewayApiClient.state.innerClient)),
101
+ entityNonFungibleIdsPage: wrapMethod(gatewayApiClient.state.innerClient.entityNonFungibleIdsPage.bind(gatewayApiClient.state.innerClient)),
102
+ entityNonFungibleResourceVaultPage: wrapMethod(gatewayApiClient.state.innerClient.entityNonFungibleResourceVaultPage.bind(gatewayApiClient.state.innerClient)),
103
+ keyValueStoreKeys: wrapMethod(gatewayApiClient.state.innerClient.keyValueStoreKeys.bind(gatewayApiClient.state.innerClient)),
104
+ keyValueStoreData: wrapMethod(gatewayApiClient.state.innerClient.keyValueStoreData.bind(gatewayApiClient.state.innerClient)),
105
+ nonFungibleData: wrapMethod(gatewayApiClient.state.innerClient.nonFungibleData.bind(gatewayApiClient.state.innerClient)),
106
+ nonFungibleLocation: wrapMethod(gatewayApiClient.state.innerClient.nonFungibleLocation.bind(gatewayApiClient.state.innerClient)),
107
+ nonFungibleIds: wrapMethod(gatewayApiClient.state.innerClient.nonFungibleIds.bind(gatewayApiClient.state.innerClient))
108
+ }
109
+ },
110
+ stream: { innerClient: { streamTransactions: wrapMethod(gatewayApiClient.stream.innerClient.streamTransactions.bind(gatewayApiClient.stream.innerClient)) } },
111
+ transaction: {
112
+ getCommittedDetails: wrapMethod(gatewayApiClient.transaction.getCommittedDetails.bind(gatewayApiClient.transaction)),
113
+ innerClient: {
114
+ transactionSubmit: wrapMethod(gatewayApiClient.transaction.innerClient.transactionSubmit.bind(gatewayApiClient.transaction.innerClient)),
115
+ transactionStatus: wrapMethod(gatewayApiClient.transaction.innerClient.transactionStatus.bind(gatewayApiClient.transaction.innerClient))
116
+ }
117
+ },
118
+ status: {
119
+ getCurrent: wrapMethod(gatewayApiClient.status.getCurrent.bind(gatewayApiClient.status)),
120
+ innerClient: { gatewayStatus: wrapMethod(gatewayApiClient.status.innerClient.gatewayStatus.bind(gatewayApiClient.status.innerClient)) }
121
+ },
122
+ extensions: { getResourceHolders: wrapMethod(gatewayApiClient.extensions.getResourceHolders.bind(gatewayApiClient.extensions)) },
123
+ rawClient: gatewayApiClient
124
+ };
125
+ }) }) {};
126
+
127
+ //#endregion
128
+ //#region src/state/entityFungiblesPage.ts
129
+ var EntityFungiblesPage = class extends Effect.Service()("EntityFungiblesPage", {
130
+ dependencies: [GatewayApiClient.Default],
131
+ effect: Effect.gen(function* () {
132
+ const gatewayClient = yield* GatewayApiClient;
133
+ const pageSize = yield* Config.number("GatewayApi__Endpoint__MaxPageSize").pipe(Config.withDefault(100));
134
+ const entityFungiblesPage = Effect.fnUntraced(function* (input) {
135
+ return yield* gatewayClient.state.innerClient.entityFungiblesPage({ stateEntityFungiblesPageRequest: {
136
+ ...input,
137
+ limit_per_page: pageSize
138
+ } });
139
+ });
140
+ return Effect.fnUntraced(function* (input) {
141
+ const result = yield* entityFungiblesPage(input);
142
+ let nextCursor = result?.next_cursor;
143
+ const items = result?.items ?? [];
144
+ while (nextCursor) {
145
+ const result$1 = yield* entityFungiblesPage({
146
+ ...input,
147
+ cursor: nextCursor
148
+ });
149
+ nextCursor = result$1.next_cursor;
150
+ items.push(...result$1.items);
151
+ }
152
+ return items;
153
+ });
154
+ })
155
+ }) {};
156
+
157
+ //#endregion
158
+ //#region src/helpers/chunker.ts
159
+ const chunker = (array, size) => {
160
+ return array.reduce((acc, item, index) => {
161
+ const chunkIndex = Math.floor(index / size);
162
+ if (!acc[chunkIndex]) acc[chunkIndex] = [];
163
+ acc[chunkIndex].push(item);
164
+ return acc;
165
+ }, []);
166
+ };
167
+
168
+ //#endregion
169
+ //#region src/state/nonFungibleData.ts
170
+ var NonFungibleData = class extends Effect.Service()("NonFungibleData", {
171
+ dependencies: [GatewayApiClient.Default],
172
+ effect: Effect.gen(function* () {
173
+ const gatewayClient = yield* GatewayApiClient;
174
+ const pageSize = yield* Config.number("GatewayApi__Endpoint__MaxPageSize").pipe(Config.withDefault(100));
175
+ return Effect.fnUntraced(function* (input) {
176
+ const chunks = chunker(input.non_fungible_ids, pageSize);
177
+ return yield* Effect.forEach(chunks, Effect.fnUntraced(function* (chunk) {
178
+ return yield* gatewayClient.state.innerClient.nonFungibleData({ stateNonFungibleDataRequest: {
179
+ ...input,
180
+ non_fungible_ids: chunk
181
+ } });
182
+ })).pipe(Effect.map((res) => {
183
+ return res.flatMap((item) => item.non_fungible_ids);
184
+ }));
185
+ });
186
+ })
187
+ }) {};
188
+
189
+ //#endregion
190
+ //#region src/state/entityNonFungiblesPage.ts
191
+ var EntityNonFungiblesPage = class extends Effect.Service()("EntityNonFungiblesPage", {
192
+ dependencies: [GatewayApiClient.Default],
193
+ effect: Effect.gen(function* () {
194
+ const gatewayClient = yield* GatewayApiClient;
195
+ const pageSize = yield* Config.number("GatewayApi__Endpoint__MaxPageSize").pipe(Config.withDefault(100));
196
+ return Effect.fnUntraced(function* (input) {
197
+ return yield* gatewayClient.state.innerClient.entityNonFungiblesPage({ stateEntityNonFungiblesPageRequest: {
198
+ ...input,
199
+ limit_per_page: pageSize
200
+ } });
201
+ });
202
+ })
203
+ }) {};
204
+
205
+ //#endregion
206
+ //#region src/state/getValidators.ts
207
+ const ValidatorSchema = z.object({
208
+ address: z.string(),
209
+ name: z.string(),
210
+ lsuResourceAddress: z.string(),
211
+ claimNftResourceAddress: z.string()
212
+ });
213
+ var GetValidators = class extends Effect.Service()("GetValidators", {
214
+ dependencies: [GatewayApiClient.Default],
215
+ effect: Effect.gen(function* () {
216
+ const gatewayClient = yield* GatewayApiClient;
217
+ return Effect.fn(function* () {
218
+ return (yield* gatewayClient.state.getValidators()).items.map((item) => {
219
+ const address = item.address;
220
+ const { name, lsuResourceAddress, claimNftResourceAddress } = item.metadata.items.reduce((acc, curr) => {
221
+ if (curr.key === "name" && curr.value.typed.type === "String") acc.name = curr.value.typed.value;
222
+ if (curr.key === "pool_unit" && curr.value.typed.type === "GlobalAddress") acc.lsuResourceAddress = curr.value.typed.value;
223
+ if (curr.key === "claim_nft" && curr.value.typed.type === "GlobalAddress") acc.claimNftResourceAddress = curr.value.typed.value;
224
+ return acc;
225
+ }, {
226
+ name: "",
227
+ lsuResourceAddress: "",
228
+ claimNftResourceAddress: ""
229
+ });
230
+ return {
231
+ address,
232
+ name,
233
+ lsuResourceAddress,
234
+ claimNftResourceAddress
235
+ };
236
+ });
237
+ });
238
+ })
239
+ }) {};
240
+
241
+ //#endregion
242
+ //#region src/state/getEntityDetailsVaultAggregated.ts
243
+ var GetEntityDetailsVaultAggregated = class extends Effect.Service()("GetEntityDetailsVaultAggregated", {
244
+ dependencies: [GatewayApiClient.Default],
245
+ effect: Effect.gen(function* () {
246
+ const gatewayClient = yield* GatewayApiClient;
247
+ const pageSize = yield* Config.number("GatewayApi__Endpoint__StateEntityDetailsPageSize").pipe(Config.withDefault(20));
248
+ return Effect.fnUntraced(function* (input, options, at_ledger_state) {
249
+ const chunks = chunker(input, pageSize);
250
+ return yield* Effect.forEach(chunks, Effect.fn(function* (addresses) {
251
+ return yield* gatewayClient.state.getEntityDetailsVaultAggregated(addresses, options, at_ledger_state);
252
+ })).pipe(Effect.map((res) => res.flat()));
253
+ });
254
+ })
255
+ }) {};
256
+
257
+ //#endregion
258
+ //#region src/state/entityNonFungibleIdsPage.ts
259
+ var EntityNonFungibleIdsPage = class extends Effect.Service()("EntityNonFungibleIdsPage", {
260
+ dependencies: [GatewayApiClient.Default],
261
+ effect: Effect.gen(function* () {
262
+ const gatewayClient = yield* GatewayApiClient;
263
+ const pageSize = yield* Config.number("GatewayApi__Endpoint__StateEntityDetailsPageSize").pipe(Config.withDefault(100));
264
+ return Effect.fn(function* (input) {
265
+ const makeRequest = (cursor) => gatewayClient.state.innerClient.entityNonFungibleIdsPage({ stateEntityNonFungibleIdsPageRequest: {
266
+ resource_address: input.resourceAddress,
267
+ vault_address: input.vaultAddress,
268
+ address: input.address,
269
+ at_ledger_state: input.at_ledger_state,
270
+ cursor,
271
+ limit_per_page: pageSize
272
+ } });
273
+ const result = yield* makeRequest(input.cursor);
274
+ let next_cursor = result.next_cursor;
275
+ const totalCount = result.total_count ?? 0;
276
+ const ids = [...result.items];
277
+ while (next_cursor && totalCount > 0) {
278
+ const result$1 = yield* makeRequest(next_cursor);
279
+ ids.push(...result$1.items);
280
+ next_cursor = result$1.next_cursor;
281
+ }
282
+ return {
283
+ ids,
284
+ address: input.address
285
+ };
286
+ });
287
+ })
288
+ }) {};
289
+
290
+ //#endregion
291
+ //#region src/getNonFungibleLocation.ts
292
+ var GetNonFungibleLocationService = class extends Effect.Service()("GetNonFungibleLocationService", {
293
+ dependencies: [GatewayApiClient.Default],
294
+ effect: Effect.gen(function* () {
295
+ const gatewayClient = yield* GatewayApiClient;
296
+ const pageSize = yield* Config.number("GatewayApi__Endpoint__MaxPageSize").pipe(Config.withDefault(100));
297
+ return Effect.fn(function* (input) {
298
+ const chunks = chunker(input.nonFungibleIds, pageSize);
299
+ return yield* Effect.forEach(chunks, Effect.fn(function* (nonFungibleIds) {
300
+ return yield* gatewayClient.state.innerClient.nonFungibleLocation({ stateNonFungibleLocationRequest: {
301
+ non_fungible_ids: nonFungibleIds,
302
+ resource_address: input.resourceAddress,
303
+ at_ledger_state: input.at_ledger_state
304
+ } });
305
+ })).pipe(Effect.map((res) => res.flat()));
306
+ });
307
+ })
308
+ }) {};
309
+
310
+ //#endregion
311
+ //#region src/getAddressByNonFungible.ts
312
+ var EntityNotFoundError$2 = class extends Data.TaggedError("EntityNotFoundError") {};
313
+ var GetAddressByNonFungibleService = class extends Effect.Service()("GetAddressByNonFungibleService", {
314
+ dependencies: [GetNonFungibleLocationService.Default],
315
+ effect: Effect.gen(function* () {
316
+ const getNonFungibleLocationService = yield* GetNonFungibleLocationService;
317
+ return Effect.fn(function* (input) {
318
+ let isBurned = true;
319
+ let nextStateVersion = input.at_ledger_state;
320
+ let address = "";
321
+ while (isBurned) {
322
+ const firstLocation = (yield* getNonFungibleLocationService({
323
+ resourceAddress: input.resourceAddress,
324
+ nonFungibleIds: [input.nonFungibleId],
325
+ at_ledger_state: nextStateVersion
326
+ }))[0];
327
+ if (!firstLocation) return yield* Effect.fail(new EntityNotFoundError$2({ message: `Non-fungible location not found for resource address ${input.resourceAddress} and non-fungible id ${input.nonFungibleId}` }));
328
+ const result = firstLocation.non_fungible_ids[0];
329
+ if (!result) return yield* Effect.fail(new EntityNotFoundError$2({ message: `Non-fungible location not found for resource address ${input.resourceAddress} and non-fungible id ${input.nonFungibleId}` }));
330
+ isBurned = result.is_burned;
331
+ nextStateVersion = { state_version: firstLocation.ledger_state.state_version - 1 };
332
+ if (result.owning_vault_global_ancestor_address) address = result.owning_vault_global_ancestor_address;
333
+ }
334
+ return {
335
+ address,
336
+ resourceAddress: input.resourceAddress,
337
+ nonFungibleId: input.nonFungibleId
338
+ };
339
+ });
340
+ })
341
+ }) {};
342
+
343
+ //#endregion
344
+ //#region src/getComponentState.ts
345
+ var InvalidComponentStateError = class {
346
+ constructor(error) {
347
+ this.error = error;
348
+ this._tag = "InvalidComponentStateError";
349
+ }
350
+ };
351
+ var GetComponentStateService = class extends Effect.Service()("GetComponentStateService", {
352
+ dependencies: [GetEntityDetailsVaultAggregated.Default],
353
+ effect: Effect.gen(function* () {
354
+ const getEntityDetails = yield* GetEntityDetailsVaultAggregated;
355
+ return { run: Effect.fnUntraced(function* (input) {
356
+ const entityDetails = yield* getEntityDetails(input.addresses, input.options, input.at_ledger_state);
357
+ const results = [];
358
+ for (const item of entityDetails) if (item.details?.type === "Component") {
359
+ const componentState = item.details.state;
360
+ const parsed = input.schema.safeParse(componentState);
361
+ if (parsed.isErr()) return yield* Effect.fail(new InvalidComponentStateError(parsed.error));
362
+ if (parsed.isOk()) results.push({
363
+ address: item.address,
364
+ state: parsed.value,
365
+ details: item
366
+ });
367
+ }
368
+ return results;
369
+ }) };
370
+ })
371
+ }) {};
372
+
373
+ //#endregion
374
+ //#region src/state/stateEntityDetails.ts
375
+ var StateEntityDetails = class extends Effect.Service()("StateEntityDetails", {
376
+ dependencies: [GatewayApiClient.Default],
377
+ effect: Effect.gen(function* () {
378
+ const gatewayClient = yield* GatewayApiClient;
379
+ const pageSize = yield* Config.number("GatewayApi__Endpoint__StateEntityDetailsPageSize").pipe(Config.withDefault(20));
380
+ const concurrency = yield* Config.number("GATEWAY_STATE_ENTITY_DETAILS_CONCURRENCY").pipe(Config.withDefault(5));
381
+ return Effect.fnUntraced(function* (input) {
382
+ const chunks = chunker(input.addresses, pageSize);
383
+ return yield* Effect.forEach(chunks, Effect.fnUntraced(function* (addresses) {
384
+ return yield* gatewayClient.state.innerClient.stateEntityDetails({ stateEntityDetailsRequest: {
385
+ ...input,
386
+ addresses
387
+ } });
388
+ }), { concurrency }).pipe(Effect.map((res) => {
389
+ return {
390
+ ledger_state: res[0].ledger_state,
391
+ items: res.flatMap((item) => item.items)
392
+ };
393
+ }));
394
+ });
395
+ })
396
+ }) {};
397
+
398
+ //#endregion
399
+ //#region src/getFungibleBalance.ts
400
+ var GetFungibleBalance = class extends Effect.Service()("GetFungibleBalance", {
401
+ dependencies: [EntityFungiblesPage.Default, StateEntityDetails.Default],
402
+ effect: Effect.gen(function* () {
403
+ const stateEntityDetails = yield* StateEntityDetails;
404
+ const entityFungiblesPage = yield* EntityFungiblesPage;
405
+ const concurrency = yield* Config.number("GATEWAY_GET_FUNGIBLE_BALANCE_CONCURRENCY").pipe(Config.withDefault(5));
406
+ const getAggregatedFungibleBalance = Effect.fnUntraced(function* (item, at_ledger_state) {
407
+ const address = item.address;
408
+ const nextCursor = item.fungible_resources?.next_cursor;
409
+ const totalCount = item.fungible_resources?.total_count ?? 0;
410
+ const allFungibleResources = item.fungible_resources?.items ?? [];
411
+ if (nextCursor && totalCount > 0) {
412
+ const result = yield* entityFungiblesPage({
413
+ address,
414
+ aggregation_level: "Global",
415
+ cursor: nextCursor,
416
+ at_ledger_state
417
+ });
418
+ allFungibleResources.push(...result);
419
+ }
420
+ const fungibleResources = allFungibleResources.map((item$1) => {
421
+ if (item$1.aggregation_level === "Global") {
422
+ const { aggregation_level, amount,...rest } = item$1;
423
+ return {
424
+ ...rest,
425
+ amount: new BigNumber(amount)
426
+ };
427
+ }
428
+ }).filter((item$1) => item$1 !== void 0).filter((item$1) => item$1.amount.gt(0));
429
+ return {
430
+ address: item.address,
431
+ items: fungibleResources
432
+ };
433
+ });
434
+ return Effect.fnUntraced(function* (input) {
435
+ const stateEntityDetailsResults = yield* stateEntityDetails({
436
+ addresses: input.addresses,
437
+ opt_ins: input.options,
438
+ at_ledger_state: input.at_ledger_state,
439
+ aggregation_level: "Global"
440
+ });
441
+ return yield* Effect.forEach(stateEntityDetailsResults.items, (item) => getAggregatedFungibleBalance(item, input.at_ledger_state), { concurrency }).pipe(Effect.map((results) => results.flat()));
442
+ });
443
+ })
444
+ }) {};
445
+
446
+ //#endregion
447
+ //#region src/keyValueStoreData.ts
448
+ var KeyValueStoreDataService = class extends Effect.Service()("KeyValueStoreDataService", {
449
+ dependencies: [GatewayApiClient.Default],
450
+ effect: Effect.gen(function* () {
451
+ const gatewayClient = yield* GatewayApiClient;
452
+ const pageSize = yield* Config.number("GatewayApi__Endpoint__MaxPageSize").pipe(Config.withDefault(100));
453
+ return Effect.fn(function* (input) {
454
+ const chunks = chunker(input.keys, pageSize);
455
+ return yield* Effect.forEach(chunks, Effect.fn(function* (keys) {
456
+ return yield* gatewayClient.state.innerClient.keyValueStoreData({ stateKeyValueStoreDataRequest: {
457
+ keys,
458
+ at_ledger_state: input.at_ledger_state,
459
+ key_value_store_address: input.key_value_store_address
460
+ } });
461
+ })).pipe(Effect.map((res) => res.flat()));
462
+ });
463
+ })
464
+ }) {};
465
+
466
+ //#endregion
467
+ //#region src/keyValueStoreKeys.ts
468
+ var KeyValueStoreKeysService = class extends Effect.Service()("KeyValueStoreKeysService", {
469
+ dependencies: [GatewayApiClient.Default],
470
+ effect: Effect.gen(function* () {
471
+ const gatewayClient = yield* GatewayApiClient;
472
+ const pageSize = yield* Config.number("GatewayApi__Endpoint__MaxPageSize").pipe(Config.withDefault(100));
473
+ return Effect.fn(function* (input) {
474
+ return yield* gatewayClient.state.innerClient.keyValueStoreKeys({ stateKeyValueStoreKeysRequest: {
475
+ ...input,
476
+ limit_per_page: pageSize
477
+ } });
478
+ });
479
+ })
480
+ }) {};
481
+
482
+ //#endregion
483
+ //#region src/getKeyValueStore.ts
484
+ var GetKeyValueStoreService = class extends Effect.Service()("GetKeyValueStoreService", {
485
+ dependencies: [KeyValueStoreKeysService.Default, KeyValueStoreDataService.Default],
486
+ effect: Effect.gen(function* () {
487
+ const keyValueStoreKeysService = yield* KeyValueStoreKeysService;
488
+ const keyValueStoreDataService = yield* KeyValueStoreDataService;
489
+ return Effect.fn(function* (input) {
490
+ const keyResults = yield* keyValueStoreKeysService({
491
+ key_value_store_address: input.address,
492
+ at_ledger_state: input.at_ledger_state
493
+ });
494
+ const allKeys = [...keyResults.items];
495
+ let nextCursor = keyResults.next_cursor;
496
+ while (nextCursor) {
497
+ const nextKeyResults = yield* keyValueStoreKeysService({
498
+ key_value_store_address: input.address,
499
+ at_ledger_state: input.at_ledger_state,
500
+ cursor: nextCursor
501
+ });
502
+ allKeys.push(...nextKeyResults.items);
503
+ nextCursor = nextKeyResults.next_cursor;
504
+ }
505
+ return yield* keyValueStoreDataService({
506
+ key_value_store_address: input.address,
507
+ keys: allKeys.map(({ key }) => ({ key_json: key.programmatic_json })),
508
+ at_ledger_state: input.at_ledger_state
509
+ }).pipe(Effect.map((res) => {
510
+ const { key_value_store_address, ledger_state } = res[0];
511
+ return {
512
+ key_value_store_address,
513
+ ledger_state,
514
+ entries: res.flatMap((item) => item.entries)
515
+ };
516
+ }));
517
+ });
518
+ })
519
+ }) {};
520
+
521
+ //#endregion
522
+ //#region src/getLedgerState.ts
523
+ var GetLedgerStateService = class extends Effect.Service()("GetLedgerStateService", {
524
+ dependencies: [GatewayApiClient.Default],
525
+ effect: Effect.gen(function* () {
526
+ const gatewayClient = yield* GatewayApiClient;
527
+ return Effect.fn("getLedgerStateService")(function* (input) {
528
+ return (yield* gatewayClient.stream.innerClient.streamTransactions({ streamTransactionsRequest: {
529
+ limit_per_page: 1,
530
+ at_ledger_state: input.at_ledger_state
531
+ } })).ledger_state;
532
+ });
533
+ })
534
+ }) {};
535
+
536
+ //#endregion
537
+ //#region src/getNftResourceManagers.ts
538
+ var GetNftResourceManagersService = class extends Effect.Service()("GetNftResourceManagersService", {
539
+ dependencies: [
540
+ GatewayApiClient.Default,
541
+ EntityNonFungiblesPage.Default,
542
+ EntityNonFungibleIdsPage.Default
543
+ ],
544
+ effect: Effect.gen(function* () {
545
+ const gatewayClient = yield* GatewayApiClient;
546
+ const entityNonFungiblesPageService = yield* EntityNonFungiblesPage;
547
+ const entityNonFungibleIdsPage = yield* EntityNonFungibleIdsPage;
548
+ const getNftResourceManagersConcurrency = yield* Config.number("GET_NFT_RESOURCE_MANAGERS_CONCURRENCY").pipe(Config.withDefault(10));
549
+ const stateEntityDetailsPageSize = yield* Config.number("GatewayApi__Endpoint__StateEntityDetailsPageSize").pipe(Config.withDefault(20));
550
+ const stateEntityDetailsConcurrency = yield* Config.number("GATEWAY_STATE_ENTITY_DETAILS_CONCURRENCY").pipe(Config.withDefault(10));
551
+ const getNftIdsConcurrency = yield* Config.number("GET_NFT_IDS_CONCURRENCY").pipe(Config.withDefault(20));
552
+ const AGGREGATION_LEVEL = "Vault";
553
+ const getNonFungibleResourceVaultPage = ({ address, cursor, resourceAddress: resource_address, optIns, at_ledger_state }) => gatewayClient.state.innerClient.entityNonFungibleResourceVaultPage({ stateEntityNonFungibleResourceVaultsPageRequest: {
554
+ address,
555
+ opt_ins: optIns,
556
+ at_ledger_state,
557
+ cursor,
558
+ resource_address
559
+ } });
560
+ const getNftIds = Effect.fn(function* ({ resourceManager, optIns, at_ledger_state, address }) {
561
+ const vaults = [...resourceManager.vaults.items];
562
+ let next_cursor = resourceManager.vaults.next_cursor;
563
+ const totalCount = resourceManager.vaults.total_count ?? 0;
564
+ while (next_cursor && totalCount > 0) {
565
+ const vaultsPage = yield* getNonFungibleResourceVaultPage({
566
+ address,
567
+ cursor: next_cursor,
568
+ resourceAddress: resourceManager.resource_address,
569
+ optIns,
570
+ at_ledger_state
571
+ });
572
+ vaults.push(...vaultsPage.items);
573
+ next_cursor = vaultsPage.next_cursor;
574
+ }
575
+ const nftIds = yield* Effect.forEach(vaults, Effect.fnUntraced(function* (vault) {
576
+ const nftIds$1 = vault?.items || [];
577
+ if (vault.next_cursor && vault.total_count > 0) {
578
+ const { ids } = yield* entityNonFungibleIdsPage({
579
+ vaultAddress: vault.vault_address,
580
+ resourceAddress: resourceManager.resource_address,
581
+ at_ledger_state,
582
+ address,
583
+ cursor: vault.next_cursor
584
+ });
585
+ nftIds$1.push(...ids);
586
+ }
587
+ return nftIds$1;
588
+ })).pipe(Effect.map((ids) => ids.flat()));
589
+ return {
590
+ resourceAddress: resourceManager.resource_address,
591
+ nftIds
592
+ };
593
+ });
594
+ const getStateEntityDetails = Effect.fn("getStateEntityDetails")(function* (input) {
595
+ const { addresses, optIns, at_ledger_state } = input;
596
+ return yield* Effect.forEach(chunker(addresses, stateEntityDetailsPageSize), Effect.fnUntraced(function* (addresses$1) {
597
+ return yield* gatewayClient.state.innerClient.stateEntityDetails({ stateEntityDetailsRequest: {
598
+ addresses: addresses$1,
599
+ opt_ins: optIns,
600
+ at_ledger_state,
601
+ aggregation_level: AGGREGATION_LEVEL
602
+ } });
603
+ }), { concurrency: stateEntityDetailsConcurrency });
604
+ });
605
+ const getResourceManagers = Effect.fn(function* (input) {
606
+ const { items, aggregationLevel, optIns, filterResourceAddresses } = input;
607
+ return yield* Effect.forEach(items, Effect.fnUntraced(function* (item) {
608
+ const resourceManagers = item.non_fungible_resources?.items ?? [];
609
+ const address = item.address;
610
+ let next_cursor = item.non_fungible_resources?.next_cursor;
611
+ const totalCount = item.non_fungible_resources?.total_count ?? 0;
612
+ while (next_cursor && totalCount > 0) {
613
+ const entityNonFungiblesPageResult = yield* entityNonFungiblesPageService({
614
+ address,
615
+ at_ledger_state: input.at_ledger_state,
616
+ aggregation_level: aggregationLevel,
617
+ opt_ins: optIns,
618
+ cursor: next_cursor
619
+ });
620
+ resourceManagers.push(...entityNonFungiblesPageResult.items);
621
+ next_cursor = entityNonFungiblesPageResult.next_cursor;
622
+ }
623
+ return {
624
+ address,
625
+ resourceManagers: filterResourceAddresses ? resourceManagers.filter((resourceManager) => filterResourceAddresses.includes(resourceManager.resource_address)) : resourceManagers
626
+ };
627
+ }));
628
+ });
629
+ return Effect.fn("getNftResourceManagersService")(function* (input) {
630
+ const optIns = {
631
+ ...input.options,
632
+ non_fungible_include_nfids: true
633
+ };
634
+ const filterResourceAddresses = input.resourceAddresses;
635
+ const stateEntityDetailsResults = yield* getStateEntityDetails({
636
+ addresses: input.addresses,
637
+ optIns,
638
+ at_ledger_state: input.at_ledger_state
639
+ });
640
+ const resourceManagerResults = yield* Effect.forEach(stateEntityDetailsResults, Effect.fnUntraced(function* (stateEntityDetails) {
641
+ return yield* getResourceManagers({
642
+ items: stateEntityDetails.items,
643
+ at_ledger_state: input.at_ledger_state,
644
+ aggregationLevel: AGGREGATION_LEVEL,
645
+ optIns,
646
+ filterResourceAddresses
647
+ });
648
+ }), { concurrency: getNftResourceManagersConcurrency }).pipe(Effect.map((items) => items.flat()));
649
+ return yield* Effect.forEach(resourceManagerResults, Effect.fnUntraced(function* (resourceManagerResult) {
650
+ const nftIds = yield* Effect.forEach(resourceManagerResult.resourceManagers, (resourceManager) => getNftIds({
651
+ resourceManager,
652
+ optIns,
653
+ at_ledger_state: input.at_ledger_state,
654
+ address: resourceManagerResult.address
655
+ }));
656
+ return {
657
+ address: resourceManagerResult.address,
658
+ items: nftIds
659
+ };
660
+ }), { concurrency: getNftIdsConcurrency });
661
+ });
662
+ })
663
+ }) {};
664
+
665
+ //#endregion
666
+ //#region src/getNonFungibleBalance.ts
667
+ var InvalidInputError = class {
668
+ constructor(error) {
669
+ this.error = error;
670
+ this._tag = "InvalidInputError";
671
+ }
672
+ };
673
+ var GetNonFungibleBalanceService = class extends Effect.Service()("GetNonFungibleBalanceService", {
674
+ dependencies: [NonFungibleData.Default, GetNftResourceManagersService.Default],
675
+ effect: Effect.gen(function* () {
676
+ const entityNonFungibleDataService = yield* NonFungibleData;
677
+ const getNftResourceManagersService = yield* GetNftResourceManagersService;
678
+ const getNonFungibleDataConcurrency = yield* Config.number("GATEWAY_GET_NON_FUNGIBLE_DATA_CONCURRENCY").pipe(Config.withDefault(15));
679
+ const getNonFungibleData = Effect.fn(function* (input) {
680
+ return yield* Effect.forEach(input.items, Effect.fn(function* (item) {
681
+ if (item.nftIds.length === 0) return yield* Effect.succeed({
682
+ resourceAddress: item.resourceAddress,
683
+ items: []
684
+ });
685
+ const items = (yield* entityNonFungibleDataService({
686
+ resource_address: item.resourceAddress,
687
+ non_fungible_ids: item.nftIds,
688
+ at_ledger_state: input.at_ledger_state
689
+ })).map((nftDataItem) => ({
690
+ id: nftDataItem.non_fungible_id,
691
+ lastUpdatedStateVersion: nftDataItem.last_updated_at_state_version,
692
+ sbor: nftDataItem.data?.programmatic_json,
693
+ isBurned: nftDataItem.is_burned
694
+ }));
695
+ return {
696
+ resourceAddress: item.resourceAddress,
697
+ items
698
+ };
699
+ }));
700
+ });
701
+ return Effect.fn("getNonFungibleBalanceService")(function* (input) {
702
+ const optIns = {
703
+ ...input.options,
704
+ non_fungible_include_nfids: true
705
+ };
706
+ const accountNonFungibleBalances = yield* getNftResourceManagersService({
707
+ addresses: input.addresses,
708
+ at_ledger_state: input.at_ledger_state,
709
+ resourceAddresses: input.resourceAddresses,
710
+ options: optIns
711
+ });
712
+ return { items: yield* Effect.forEach(accountNonFungibleBalances, Effect.fn(function* ({ address, items }) {
713
+ return {
714
+ address,
715
+ nonFungibleResources: yield* getNonFungibleData({
716
+ items,
717
+ at_ledger_state: input.at_ledger_state
718
+ })
719
+ };
720
+ }), { concurrency: getNonFungibleDataConcurrency }).pipe(Effect.withSpan("get non-fungible data for each account")) };
721
+ });
722
+ })
723
+ }) {};
724
+
725
+ //#endregion
726
+ //#region src/getResourceHolders.ts
727
+ var GetResourceHoldersService = class extends Effect.Service()("GetResourceHoldersService", {
728
+ dependencies: [GatewayApiClient.Default],
729
+ effect: Effect.gen(function* () {
730
+ const gatewayClient = yield* GatewayApiClient;
731
+ const getResourceHolders = Effect.fn(function* (input) {
732
+ return yield* gatewayClient.extensions.getResourceHolders(input.resourceAddress, input.cursor);
733
+ });
734
+ return Effect.fn(function* (input) {
735
+ const result = yield* getResourceHolders(input);
736
+ const allItems = [...result.items];
737
+ let nextCursor = result.next_cursor;
738
+ while (nextCursor) {
739
+ const nextResult = yield* getResourceHolders({
740
+ resourceAddress: input.resourceAddress,
741
+ cursor: nextCursor
742
+ });
743
+ allItems.push(...nextResult.items);
744
+ nextCursor = nextResult.next_cursor;
745
+ }
746
+ const holders = /* @__PURE__ */ new Map();
747
+ for (const item of allItems) holders.set(item.holder_address, item);
748
+ return Array.from(holders.values());
749
+ });
750
+ })
751
+ }) {};
752
+
753
+ //#endregion
754
+ //#region src/schemas.ts
755
+ const StateVersionSchema = z.object({ state_version: z.number() });
756
+ const TimestampSchema = z.object({ timestamp: z.date() });
757
+ const AtLedgerStateSchema = z.union([StateVersionSchema, TimestampSchema]);
758
+ var InvalidStateInputError = class {
759
+ constructor(error) {
760
+ this.error = error;
761
+ this._tag = "InvalidStateInputError";
762
+ }
763
+ };
764
+ const validateAtLedgerStateInput = (input) => Effect.gen(function* () {
765
+ const parsed = AtLedgerStateSchema.safeParse(input);
766
+ if (!parsed.success) return yield* Effect.fail(new InvalidStateInputError(parsed.error));
767
+ return parsed.data;
768
+ });
769
+
770
+ //#endregion
771
+ export { AccountLockerNotFoundError, AtLedgerStateSchema, EntityFungiblesPage, EntityNonFungibleIdsPage, EntityNonFungiblesPage, EntityNotFoundError, ErrorResponse, GatewayApiClient, GetAddressByNonFungibleService, GetComponentStateService, GetEntityDetailsVaultAggregated, GetFungibleBalance, GetKeyValueStoreService, GetLedgerStateService, GetNftResourceManagersService, GetNonFungibleBalanceService, GetNonFungibleLocationService, GetResourceHoldersService, GetValidators, InternalServerError, InvalidComponentStateError, InvalidEntityError, InvalidInputError, InvalidRequestError, InvalidStateInputError, InvalidTransactionError, KeyValueStoreDataService, KeyValueStoreKeysService, NonFungibleData, NotSyncedUpError, RateLimitExceededError, ResponseError, StateVersionSchema, TimestampSchema, TransactionNotFoundError, UnknownGatewayError, ValidatorSchema, validateAtLedgerStateInput };