@aephia/atlas-kit 0.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 (279) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +124 -0
  3. package/dist/bindings.d.ts +11 -0
  4. package/dist/bindings.d.ts.map +1 -0
  5. package/dist/bindings.js +11 -0
  6. package/dist/bindings.js.map +1 -0
  7. package/dist/cargo/actions/index.d.ts +122 -0
  8. package/dist/cargo/actions/index.d.ts.map +1 -0
  9. package/dist/cargo/actions/index.js +526 -0
  10. package/dist/cargo/actions/index.js.map +1 -0
  11. package/dist/cargo/index.d.ts +77 -0
  12. package/dist/cargo/index.d.ts.map +1 -0
  13. package/dist/cargo/index.js +102 -0
  14. package/dist/cargo/index.js.map +1 -0
  15. package/dist/claim-stakes/index.d.ts +64 -0
  16. package/dist/claim-stakes/index.d.ts.map +1 -0
  17. package/dist/claim-stakes/index.js +97 -0
  18. package/dist/claim-stakes/index.js.map +1 -0
  19. package/dist/client/context.d.ts +21 -0
  20. package/dist/client/context.d.ts.map +1 -0
  21. package/dist/client/context.js +1374 -0
  22. package/dist/client/context.js.map +1 -0
  23. package/dist/client/contracts.d.ts +671 -0
  24. package/dist/client/contracts.d.ts.map +1 -0
  25. package/dist/client/contracts.js +2 -0
  26. package/dist/client/contracts.js.map +1 -0
  27. package/dist/client/deployments.d.ts +3 -0
  28. package/dist/client/deployments.d.ts.map +1 -0
  29. package/dist/client/deployments.js +2 -0
  30. package/dist/client/deployments.js.map +1 -0
  31. package/dist/client/errors.d.ts +227 -0
  32. package/dist/client/errors.d.ts.map +1 -0
  33. package/dist/client/errors.js +288 -0
  34. package/dist/client/errors.js.map +1 -0
  35. package/dist/client/index.d.ts +7 -0
  36. package/dist/client/index.d.ts.map +1 -0
  37. package/dist/client/index.js +5 -0
  38. package/dist/client/index.js.map +1 -0
  39. package/dist/client/lifecycle.d.ts +4 -0
  40. package/dist/client/lifecycle.d.ts.map +1 -0
  41. package/dist/client/lifecycle.js +10 -0
  42. package/dist/client/lifecycle.js.map +1 -0
  43. package/dist/client/provider-errors.d.ts +9 -0
  44. package/dist/client/provider-errors.d.ts.map +1 -0
  45. package/dist/client/provider-errors.js +12 -0
  46. package/dist/client/provider-errors.js.map +1 -0
  47. package/dist/client/reconciliation.d.ts +10 -0
  48. package/dist/client/reconciliation.d.ts.map +1 -0
  49. package/dist/client/reconciliation.js +9 -0
  50. package/dist/client/reconciliation.js.map +1 -0
  51. package/dist/client/refs.d.ts +23 -0
  52. package/dist/client/refs.d.ts.map +1 -0
  53. package/dist/client/refs.js +12 -0
  54. package/dist/client/refs.js.map +1 -0
  55. package/dist/combat/index.d.ts +256 -0
  56. package/dist/combat/index.d.ts.map +1 -0
  57. package/dist/combat/index.js +222 -0
  58. package/dist/combat/index.js.map +1 -0
  59. package/dist/crafting/index.d.ts +308 -0
  60. package/dist/crafting/index.d.ts.map +1 -0
  61. package/dist/crafting/index.js +400 -0
  62. package/dist/crafting/index.js.map +1 -0
  63. package/dist/factions/index.d.ts +292 -0
  64. package/dist/factions/index.d.ts.map +1 -0
  65. package/dist/factions/index.js +334 -0
  66. package/dist/factions/index.js.map +1 -0
  67. package/dist/fleets/actions/index.d.ts +200 -0
  68. package/dist/fleets/actions/index.d.ts.map +1 -0
  69. package/dist/fleets/actions/index.js +854 -0
  70. package/dist/fleets/actions/index.js.map +1 -0
  71. package/dist/fleets/index.d.ts +100 -0
  72. package/dist/fleets/index.d.ts.map +1 -0
  73. package/dist/fleets/index.js +124 -0
  74. package/dist/fleets/index.js.map +1 -0
  75. package/dist/identity/index.d.ts +225 -0
  76. package/dist/identity/index.d.ts.map +1 -0
  77. package/dist/identity/index.js +341 -0
  78. package/dist/identity/index.js.map +1 -0
  79. package/dist/index.d.ts +401 -0
  80. package/dist/index.d.ts.map +1 -0
  81. package/dist/index.js +519 -0
  82. package/dist/index.js.map +1 -0
  83. package/dist/internal/c4/adapter.d.ts +6 -0
  84. package/dist/internal/c4/adapter.d.ts.map +1 -0
  85. package/dist/internal/c4/adapter.js +2 -0
  86. package/dist/internal/c4/adapter.js.map +1 -0
  87. package/dist/internal/c4/bindings.d.ts +4 -0
  88. package/dist/internal/c4/bindings.d.ts.map +1 -0
  89. package/dist/internal/c4/bindings.js +4 -0
  90. package/dist/internal/c4/bindings.js.map +1 -0
  91. package/dist/internal/c4/character-modifier.d.ts +5 -0
  92. package/dist/internal/c4/character-modifier.d.ts.map +1 -0
  93. package/dist/internal/c4/character-modifier.js +100 -0
  94. package/dist/internal/c4/character-modifier.js.map +1 -0
  95. package/dist/internal/c4/claim-stake.d.ts +140 -0
  96. package/dist/internal/c4/claim-stake.d.ts.map +1 -0
  97. package/dist/internal/c4/claim-stake.js +205 -0
  98. package/dist/internal/c4/claim-stake.js.map +1 -0
  99. package/dist/internal/c4/combat.d.ts +98 -0
  100. package/dist/internal/c4/combat.d.ts.map +1 -0
  101. package/dist/internal/c4/combat.js +232 -0
  102. package/dist/internal/c4/combat.js.map +1 -0
  103. package/dist/internal/c4/crafting.d.ts +170 -0
  104. package/dist/internal/c4/crafting.d.ts.map +1 -0
  105. package/dist/internal/c4/crafting.js +387 -0
  106. package/dist/internal/c4/crafting.js.map +1 -0
  107. package/dist/internal/c4/factions.d.ts +248 -0
  108. package/dist/internal/c4/factions.d.ts.map +1 -0
  109. package/dist/internal/c4/factions.js +589 -0
  110. package/dist/internal/c4/factions.js.map +1 -0
  111. package/dist/internal/c4/fleet-crew-binding.d.ts +12 -0
  112. package/dist/internal/c4/fleet-crew-binding.d.ts.map +1 -0
  113. package/dist/internal/c4/fleet-crew-binding.js +51 -0
  114. package/dist/internal/c4/fleet-crew-binding.js.map +1 -0
  115. package/dist/internal/c4/fleet.d.ts +310 -0
  116. package/dist/internal/c4/fleet.d.ts.map +1 -0
  117. package/dist/internal/c4/fleet.js +393 -0
  118. package/dist/internal/c4/fleet.js.map +1 -0
  119. package/dist/internal/c4/game.d.ts +192 -0
  120. package/dist/internal/c4/game.d.ts.map +1 -0
  121. package/dist/internal/c4/game.js +396 -0
  122. package/dist/internal/c4/game.js.map +1 -0
  123. package/dist/internal/c4/identity.d.ts +193 -0
  124. package/dist/internal/c4/identity.d.ts.map +1 -0
  125. package/dist/internal/c4/identity.js +180 -0
  126. package/dist/internal/c4/identity.js.map +1 -0
  127. package/dist/internal/c4/loot-layout.d.ts +20 -0
  128. package/dist/internal/c4/loot-layout.d.ts.map +1 -0
  129. package/dist/internal/c4/loot-layout.js +29 -0
  130. package/dist/internal/c4/loot-layout.js.map +1 -0
  131. package/dist/internal/c4/loyalty.d.ts +102 -0
  132. package/dist/internal/c4/loyalty.d.ts.map +1 -0
  133. package/dist/internal/c4/loyalty.js +318 -0
  134. package/dist/internal/c4/loyalty.js.map +1 -0
  135. package/dist/internal/c4/market.d.ts +112 -0
  136. package/dist/internal/c4/market.d.ts.map +1 -0
  137. package/dist/internal/c4/market.js +247 -0
  138. package/dist/internal/c4/market.js.map +1 -0
  139. package/dist/internal/c4/pda.d.ts +6 -0
  140. package/dist/internal/c4/pda.d.ts.map +1 -0
  141. package/dist/internal/c4/pda.js +45 -0
  142. package/dist/internal/c4/pda.js.map +1 -0
  143. package/dist/internal/c4/profile-faction.d.ts +14 -0
  144. package/dist/internal/c4/profile-faction.d.ts.map +1 -0
  145. package/dist/internal/c4/profile-faction.js +69 -0
  146. package/dist/internal/c4/profile-faction.js.map +1 -0
  147. package/dist/internal/c4/rewards.d.ts +135 -0
  148. package/dist/internal/c4/rewards.d.ts.map +1 -0
  149. package/dist/internal/c4/rewards.js +305 -0
  150. package/dist/internal/c4/rewards.js.map +1 -0
  151. package/dist/internal/c4/scanning.d.ts +85 -0
  152. package/dist/internal/c4/scanning.d.ts.map +1 -0
  153. package/dist/internal/c4/scanning.js +180 -0
  154. package/dist/internal/c4/scanning.js.map +1 -0
  155. package/dist/internal/c4/starbase.d.ts +186 -0
  156. package/dist/internal/c4/starbase.d.ts.map +1 -0
  157. package/dist/internal/c4/starbase.js +259 -0
  158. package/dist/internal/c4/starbase.js.map +1 -0
  159. package/dist/internal/c4/world.d.ts +294 -0
  160. package/dist/internal/c4/world.d.ts.map +1 -0
  161. package/dist/internal/c4/world.js +417 -0
  162. package/dist/internal/c4/world.js.map +1 -0
  163. package/dist/internal/cargo.d.ts +65 -0
  164. package/dist/internal/cargo.d.ts.map +1 -0
  165. package/dist/internal/cargo.js +46 -0
  166. package/dist/internal/cargo.js.map +1 -0
  167. package/dist/internal/claim-stake.d.ts +31 -0
  168. package/dist/internal/claim-stake.d.ts.map +1 -0
  169. package/dist/internal/claim-stake.js +20 -0
  170. package/dist/internal/claim-stake.js.map +1 -0
  171. package/dist/internal/fleet.d.ts +165 -0
  172. package/dist/internal/fleet.d.ts.map +1 -0
  173. package/dist/internal/fleet.js +179 -0
  174. package/dist/internal/fleet.js.map +1 -0
  175. package/dist/internal/game-context.d.ts +4 -0
  176. package/dist/internal/game-context.d.ts.map +1 -0
  177. package/dist/internal/game-context.js +9 -0
  178. package/dist/internal/game-context.js.map +1 -0
  179. package/dist/internal/immutable-tree.d.ts +5 -0
  180. package/dist/internal/immutable-tree.d.ts.map +1 -0
  181. package/dist/internal/immutable-tree.js +47 -0
  182. package/dist/internal/immutable-tree.js.map +1 -0
  183. package/dist/internal/json.d.ts +7 -0
  184. package/dist/internal/json.d.ts.map +1 -0
  185. package/dist/internal/json.js +33 -0
  186. package/dist/internal/json.js.map +1 -0
  187. package/dist/internal/planning/authorization-adapter.d.ts +63 -0
  188. package/dist/internal/planning/authorization-adapter.d.ts.map +1 -0
  189. package/dist/internal/planning/authorization-adapter.js +222 -0
  190. package/dist/internal/planning/authorization-adapter.js.map +1 -0
  191. package/dist/internal/read-meta.d.ts +84 -0
  192. package/dist/internal/read-meta.d.ts.map +1 -0
  193. package/dist/internal/read-meta.js +28 -0
  194. package/dist/internal/read-meta.js.map +1 -0
  195. package/dist/internal/resolved-snapshot.d.ts +3 -0
  196. package/dist/internal/resolved-snapshot.d.ts.map +1 -0
  197. package/dist/internal/resolved-snapshot.js +11 -0
  198. package/dist/internal/resolved-snapshot.js.map +1 -0
  199. package/dist/internal/zink/provider.d.ts +9 -0
  200. package/dist/internal/zink/provider.d.ts.map +1 -0
  201. package/dist/internal/zink/provider.js +213 -0
  202. package/dist/internal/zink/provider.js.map +1 -0
  203. package/dist/loyalty/index.d.ts +195 -0
  204. package/dist/loyalty/index.d.ts.map +1 -0
  205. package/dist/loyalty/index.js +289 -0
  206. package/dist/loyalty/index.js.map +1 -0
  207. package/dist/markets/index.d.ts +195 -0
  208. package/dist/markets/index.d.ts.map +1 -0
  209. package/dist/markets/index.js +232 -0
  210. package/dist/markets/index.js.map +1 -0
  211. package/dist/mining/index.d.ts +156 -0
  212. package/dist/mining/index.d.ts.map +1 -0
  213. package/dist/mining/index.js +236 -0
  214. package/dist/mining/index.js.map +1 -0
  215. package/dist/planning/assembly.d.ts +42 -0
  216. package/dist/planning/assembly.d.ts.map +1 -0
  217. package/dist/planning/assembly.js +141 -0
  218. package/dist/planning/assembly.js.map +1 -0
  219. package/dist/planning/composition.d.ts +4 -0
  220. package/dist/planning/composition.d.ts.map +1 -0
  221. package/dist/planning/composition.js +76 -0
  222. package/dist/planning/composition.js.map +1 -0
  223. package/dist/planning/execution.d.ts +93 -0
  224. package/dist/planning/execution.d.ts.map +1 -0
  225. package/dist/planning/execution.js +549 -0
  226. package/dist/planning/execution.js.map +1 -0
  227. package/dist/planning/index.d.ts +219 -0
  228. package/dist/planning/index.d.ts.map +1 -0
  229. package/dist/planning/index.js +375 -0
  230. package/dist/planning/index.js.map +1 -0
  231. package/dist/planning/plan-instances.d.ts +3 -0
  232. package/dist/planning/plan-instances.d.ts.map +1 -0
  233. package/dist/planning/plan-instances.js +8 -0
  234. package/dist/planning/plan-instances.js.map +1 -0
  235. package/dist/planning/plan-sequence-checkpoint.d.ts +154 -0
  236. package/dist/planning/plan-sequence-checkpoint.d.ts.map +1 -0
  237. package/dist/planning/plan-sequence-checkpoint.js +449 -0
  238. package/dist/planning/plan-sequence-checkpoint.js.map +1 -0
  239. package/dist/planning/plan-sequence-execution.d.ts +72 -0
  240. package/dist/planning/plan-sequence-execution.d.ts.map +1 -0
  241. package/dist/planning/plan-sequence-execution.js +410 -0
  242. package/dist/planning/plan-sequence-execution.js.map +1 -0
  243. package/dist/planning/plan-sequence.d.ts +244 -0
  244. package/dist/planning/plan-sequence.d.ts.map +1 -0
  245. package/dist/planning/plan-sequence.js +264 -0
  246. package/dist/planning/plan-sequence.js.map +1 -0
  247. package/dist/planning/simulation.d.ts +50 -0
  248. package/dist/planning/simulation.d.ts.map +1 -0
  249. package/dist/planning/simulation.js +69 -0
  250. package/dist/planning/simulation.js.map +1 -0
  251. package/dist/registry/combat.d.ts +5 -0
  252. package/dist/registry/combat.d.ts.map +1 -0
  253. package/dist/registry/combat.js +7 -0
  254. package/dist/registry/combat.js.map +1 -0
  255. package/dist/registry/index.d.ts +138 -0
  256. package/dist/registry/index.d.ts.map +1 -0
  257. package/dist/registry/index.js +397 -0
  258. package/dist/registry/index.js.map +1 -0
  259. package/dist/rewards/index.d.ts +202 -0
  260. package/dist/rewards/index.d.ts.map +1 -0
  261. package/dist/rewards/index.js +290 -0
  262. package/dist/rewards/index.js.map +1 -0
  263. package/dist/scanning/index.d.ts +185 -0
  264. package/dist/scanning/index.d.ts.map +1 -0
  265. package/dist/scanning/index.js +207 -0
  266. package/dist/scanning/index.js.map +1 -0
  267. package/dist/starbases/actions/index.d.ts +60 -0
  268. package/dist/starbases/actions/index.d.ts.map +1 -0
  269. package/dist/starbases/actions/index.js +245 -0
  270. package/dist/starbases/actions/index.js.map +1 -0
  271. package/dist/starbases/index.d.ts +165 -0
  272. package/dist/starbases/index.d.ts.map +1 -0
  273. package/dist/starbases/index.js +213 -0
  274. package/dist/starbases/index.js.map +1 -0
  275. package/dist/world/index.d.ts +180 -0
  276. package/dist/world/index.d.ts.map +1 -0
  277. package/dist/world/index.js +265 -0
  278. package/dist/world/index.js.map +1 -0
  279. package/package.json +140 -0
@@ -0,0 +1,1374 @@
1
+ import { isAddress } from '@solana/kit';
2
+ import { AccountDecodeError, AccountNotFoundError, ContextDisposedError, InvalidAccountOwnerError, InvalidDerivationInputError, InvalidDiscriminatorError, MissingGameContextError, ProviderError, ResourceLimitExceededError, RelationshipNotDiscoverableError, SageSdkError, } from './errors.js';
3
+ import { ProviderAccountAddressMismatchError } from './provider-errors.js';
4
+ import { markContextDisposed } from './lifecycle.js';
5
+ import { ZINK_PTR_GAME_ADDRESS } from './deployments.js';
6
+ import { attachJsonSerialization } from '../internal/json.js';
7
+ import { deepFreeze } from '../internal/immutable-tree.js';
8
+ import { attachReadMeta } from '../internal/read-meta.js';
9
+ import { createZinkProvider } from '../internal/zink/provider.js';
10
+ import { INVALIDATE_CONTEXT_ADDRESSES, READ_CONTEXT_RAW_ACCOUNTS, } from './reconciliation.js';
11
+ const DEFAULT_COMMITMENT = 'confirmed';
12
+ const DEFAULT_MAX_AGE_MS = 30_000;
13
+ const DEFAULT_MAX_ACCOUNT_DATA_BYTES = 4 * 1024 * 1024;
14
+ const DEFAULT_MAX_CACHE_ENTRIES = 10_000;
15
+ const DEFAULT_MAX_DISCOVERY_RESULTS = 10_000;
16
+ const DEFAULT_MAX_READ_MANY_ACCOUNTS = 10_000;
17
+ const MAX_CONCURRENT_FALLBACK_READS = 8;
18
+ const RECONNECT_READ_COALESCE_MS = 250;
19
+ const CONTEXT_DISCOVERY_RUNTIME = new WeakMap();
20
+ const COMMITMENT_STRENGTH = {
21
+ processed: 0,
22
+ confirmed: 1,
23
+ finalized: 2,
24
+ };
25
+ const COMPATIBLE_COMMITMENTS = {
26
+ processed: ['processed', 'confirmed', 'finalized'],
27
+ confirmed: ['confirmed', 'finalized'],
28
+ finalized: ['finalized'],
29
+ };
30
+ class IndexerCandidateConflictError extends AccountDecodeError {
31
+ }
32
+ function clusterName(cluster) {
33
+ return typeof cluster === 'string' ? cluster : cluster.name;
34
+ }
35
+ function isProviderAddress(value) {
36
+ return (typeof value === 'string' &&
37
+ value.length >= 32 &&
38
+ value.length <= 44 &&
39
+ isAddress(value));
40
+ }
41
+ function isRawAccount(value) {
42
+ if (value === null || typeof value !== 'object')
43
+ return false;
44
+ const account = value;
45
+ return (isProviderAddress(account.address) &&
46
+ isProviderAddress(account.owner) &&
47
+ typeof account.lamports === 'bigint' &&
48
+ account.data instanceof Uint8Array &&
49
+ typeof account.data.byteLength === 'number' &&
50
+ typeof account.executable === 'boolean' &&
51
+ typeof account.slot === 'bigint' &&
52
+ (account.commitment === 'processed' ||
53
+ account.commitment === 'confirmed' ||
54
+ account.commitment === 'finalized'));
55
+ }
56
+ function cacheKey(cluster, definition, address, definitionId) {
57
+ return JSON.stringify([
58
+ clusterName(cluster),
59
+ definition.programAddress,
60
+ definition.type,
61
+ address,
62
+ definitionId,
63
+ ]);
64
+ }
65
+ function isPreferredSnapshot(candidate, current) {
66
+ return (candidate.slot > current.slot ||
67
+ (candidate.slot === current.slot &&
68
+ COMMITMENT_STRENGTH[candidate.commitment] >
69
+ COMMITMENT_STRENGTH[current.commitment]));
70
+ }
71
+ function isCompatible(available, requested) {
72
+ return COMMITMENT_STRENGTH[available] >= COMMITMENT_STRENGTH[requested];
73
+ }
74
+ function assertProviderCommitment(account, requested) {
75
+ if (!isCompatible(account.commitment, requested)) {
76
+ throw new ProviderError(`The configured provider returned ${account.commitment} data for a ${requested} request at ${account.address}. Fix the provider commitment handling before retrying.`, { address: account.address });
77
+ }
78
+ }
79
+ function copyProviderDiscoveryFilters(filters) {
80
+ return Object.freeze(filters.map((filter) => Object.freeze({
81
+ bytes: new Uint8Array(filter.bytes),
82
+ offset: filter.offset,
83
+ })));
84
+ }
85
+ function validateDiscoveryFilters(filters) {
86
+ for (const filter of filters) {
87
+ if (!Number.isSafeInteger(filter.offset) || filter.offset < 0) {
88
+ throw new InvalidDerivationInputError('Discovery filter offset', filter.offset, 'Use a nonnegative safe integer byte offset before discovering game accounts.');
89
+ }
90
+ }
91
+ }
92
+ function copyReadMetaFilters(filters) {
93
+ return Object.freeze(filters.map((filter) => Object.freeze({
94
+ bytes: Object.freeze([...filter.bytes]),
95
+ offset: filter.offset,
96
+ })));
97
+ }
98
+ function abortReason(signal) {
99
+ return signal.reason;
100
+ }
101
+ function throwIfAborted(signal) {
102
+ if (signal?.aborted === true) {
103
+ throw abortReason(signal);
104
+ }
105
+ }
106
+ function assertWithinLimit(resource, actual, limit) {
107
+ if (actual > limit) {
108
+ throw new ResourceLimitExceededError(resource, actual, limit);
109
+ }
110
+ }
111
+ function configuredLimit(name, value, fallback) {
112
+ const selected = value ?? fallback;
113
+ if (!Number.isSafeInteger(selected) || selected < 1) {
114
+ throw new RangeError(`${name} must be a positive safe integer. Correct the context option before creating the SAGE context.`);
115
+ }
116
+ return selected;
117
+ }
118
+ function configuredMaxAgeMs(value) {
119
+ const selected = value ?? DEFAULT_MAX_AGE_MS;
120
+ if (selected !== Number.POSITIVE_INFINITY &&
121
+ (!Number.isFinite(selected) || selected < 0)) {
122
+ throw new InvalidDerivationInputError('Cache freshness maxAgeMs', selected, 'Use a nonnegative finite millisecond duration or Infinity before reading game state.');
123
+ }
124
+ return selected;
125
+ }
126
+ async function waitForCaller(promise, signal) {
127
+ if (signal === undefined) {
128
+ return promise;
129
+ }
130
+ throwIfAborted(signal);
131
+ return new Promise((resolve, reject) => {
132
+ const abort = () => reject(abortReason(signal));
133
+ signal.addEventListener('abort', abort, { once: true });
134
+ void promise.then(resolve, reject).finally(() => {
135
+ signal.removeEventListener('abort', abort);
136
+ });
137
+ });
138
+ }
139
+ /** Internal context-owned bridge to the optional wallet discovery provider. */
140
+ export async function discoverWalletProfileCandidates(context, wallet, options) {
141
+ const runtime = CONTEXT_DISCOVERY_RUNTIME.get(context);
142
+ if (runtime === undefined || runtime.walletProfiles === undefined) {
143
+ throw new RelationshipNotDiscoverableError('Wallet-to-Profile discovery is unavailable. Configure discovery.walletProfiles or pass known Profile addresses with strategy "known-addresses".', { accountType: 'profile', strategy: 'wallet-profile-provider' });
144
+ }
145
+ const walletProfiles = runtime.walletProfiles;
146
+ if (runtime.isDisposed())
147
+ throw new ContextDisposedError();
148
+ throwIfAborted(options?.signal);
149
+ const commitment = options?.commitment ?? runtime.defaultCommitment;
150
+ const callerSignal = options?.signal === undefined
151
+ ? runtime.lifecycle.signal
152
+ : AbortSignal.any([runtime.lifecycle.signal, options.signal]);
153
+ const discoveryKey = JSON.stringify([wallet, commitment]);
154
+ let operation = runtime.walletProfileDiscoveries.get(discoveryKey);
155
+ if (operation === undefined) {
156
+ let resolveDiscovery;
157
+ let rejectDiscovery;
158
+ operation = new Promise((resolve, reject) => {
159
+ resolveDiscovery = resolve;
160
+ rejectDiscovery = reject;
161
+ });
162
+ runtime.walletProfileDiscoveries.set(discoveryKey, operation);
163
+ const providerOperation = (async () => {
164
+ try {
165
+ const candidates = await walletProfiles.discoverProfileAddresses({
166
+ commitment,
167
+ signal: runtime.lifecycle.signal,
168
+ wallet,
169
+ });
170
+ if (runtime.isDisposed())
171
+ throw new ContextDisposedError();
172
+ if (!Array.isArray(candidates)) {
173
+ throw new ProviderError('The configured wallet-to-Profile discovery provider returned malformed Profile addresses. Fix the provider response to return only valid z.ink/Solana addresses before retrying.', {
174
+ accountType: 'profile',
175
+ provider: walletProfiles.identity,
176
+ strategy: 'wallet-profile-provider',
177
+ });
178
+ }
179
+ assertWithinLimit('wallet Profile candidates', candidates.length, runtime.maxDiscoveryResults);
180
+ if (candidates.some((candidate) => typeof candidate !== 'string' || !isAddress(candidate))) {
181
+ throw new ProviderError('The configured wallet-to-Profile discovery provider returned malformed Profile addresses. Fix the provider response to return only valid z.ink/Solana addresses before retrying discovery.', {
182
+ accountType: 'profile',
183
+ provider: walletProfiles.identity,
184
+ strategy: 'wallet-profile-provider',
185
+ });
186
+ }
187
+ return Object.freeze([...candidates]);
188
+ }
189
+ catch (cause) {
190
+ if (runtime.isDisposed())
191
+ throw new ContextDisposedError();
192
+ if (cause instanceof SageSdkError)
193
+ throw cause;
194
+ throw new ProviderError('The configured wallet-to-Profile discovery provider could not return Profile addresses. Check the provider connection and retry discovery.', {
195
+ accountType: 'profile',
196
+ provider: walletProfiles.identity,
197
+ strategy: 'wallet-profile-provider',
198
+ });
199
+ }
200
+ finally {
201
+ if (runtime.walletProfileDiscoveries.get(discoveryKey) === operation) {
202
+ runtime.walletProfileDiscoveries.delete(discoveryKey);
203
+ }
204
+ }
205
+ })();
206
+ void providerOperation.then(resolveDiscovery, rejectDiscovery);
207
+ void operation.catch(() => undefined);
208
+ }
209
+ return {
210
+ addresses: await waitForCaller(operation, callerSignal),
211
+ commitment,
212
+ source: Object.freeze({ ...walletProfiles.identity }),
213
+ };
214
+ }
215
+ /** Internal helper for collection metadata produced without a provider call. */
216
+ export function contextCommitment(context, requested) {
217
+ return (requested ??
218
+ CONTEXT_DISCOVERY_RUNTIME.get(context)?.defaultCommitment ??
219
+ DEFAULT_COMMITMENT);
220
+ }
221
+ function validateAndDecode(definition, account, source, fetchedAt) {
222
+ if (account.owner !== definition.programAddress) {
223
+ throw new InvalidAccountOwnerError(definition.type, account.address, definition.programAddress, account.owner);
224
+ }
225
+ if (definition.discriminator.length === 0) {
226
+ throw new AccountDecodeError(definition.type, account.address, new TypeError('Account definitions require a non-empty discriminator. Fix the generated account definition before retrying.'));
227
+ }
228
+ const discriminatorMatches = account.data.length >= definition.discriminator.length &&
229
+ definition.discriminator.every((byte, index) => account.data[index] === byte);
230
+ if (!discriminatorMatches) {
231
+ throw new InvalidDiscriminatorError(definition.type, account.address);
232
+ }
233
+ const minimumDataLength = definition.minimumDataLength;
234
+ if (minimumDataLength !== undefined &&
235
+ (!Number.isSafeInteger(minimumDataLength) || minimumDataLength <= 0)) {
236
+ throw new AccountDecodeError(definition.type, account.address, new TypeError('Account definitions require minimumDataLength to be a positive safe integer. Fix the account definition before retrying.'));
237
+ }
238
+ if (minimumDataLength !== undefined &&
239
+ account.data.length < minimumDataLength) {
240
+ throw new AccountDecodeError(definition.type, account.address, new RangeError(`The ${definition.type} account requires at least ${String(minimumDataLength)} bytes before decoding, but the provider returned ${String(account.data.length)}.`));
241
+ }
242
+ let data;
243
+ try {
244
+ data = deepFreeze(definition.decode(account));
245
+ }
246
+ catch (cause) {
247
+ if (cause instanceof SageSdkError) {
248
+ throw cause;
249
+ }
250
+ throw new AccountDecodeError(definition.type, account.address, cause);
251
+ }
252
+ const envelope = {
253
+ accountType: definition.type,
254
+ address: account.address,
255
+ commitment: account.commitment,
256
+ data,
257
+ fetchedAt,
258
+ programAddress: definition.programAddress,
259
+ slot: account.slot,
260
+ source: deepFreeze({ ...source }),
261
+ };
262
+ return Object.freeze(attachJsonSerialization(envelope));
263
+ }
264
+ function copyRawAccount(account) {
265
+ return Object.freeze({
266
+ ...account,
267
+ data: new Uint8Array(account.data),
268
+ });
269
+ }
270
+ function createDataPort(cluster, provider, indexer, subscriptionProvider, defaultCommitment, defaultMaxAgeMs, isDisposed, lifecycle, maxAccountDataBytes, maxCacheEntries, maxDiscoveryResults, maxReadManyAccounts, trackSubscription) {
271
+ const cache = new Map();
272
+ const cacheKeysByAddress = new Map();
273
+ const activeCacheKeysByAddress = new Map();
274
+ const invalidatedAt = new Map();
275
+ const addressInvalidatedAt = new Map();
276
+ const discoveryInvalidatedAt = new Map();
277
+ const minimumRawReadSequence = new Map();
278
+ const minimumRawReadSequenceByAddress = new Map();
279
+ const definedReads = new Map();
280
+ const discoveryReads = new Map();
281
+ const indexerReads = new Map();
282
+ const rawReads = new Map();
283
+ const reconnectReads = new Map();
284
+ const snapshotFetchTimes = new WeakMap();
285
+ const definitionIds = new WeakMap();
286
+ let invalidationSequence = 0;
287
+ let reconciliationGeneration = 0;
288
+ let nextRawReadSequence = 0;
289
+ let nextDefinitionId = 0;
290
+ lifecycle.signal.addEventListener('abort', () => {
291
+ cache.clear();
292
+ cacheKeysByAddress.clear();
293
+ activeCacheKeysByAddress.clear();
294
+ invalidatedAt.clear();
295
+ addressInvalidatedAt.clear();
296
+ discoveryInvalidatedAt.clear();
297
+ minimumRawReadSequence.clear();
298
+ minimumRawReadSequenceByAddress.clear();
299
+ definedReads.clear();
300
+ discoveryReads.clear();
301
+ indexerReads.clear();
302
+ rawReads.clear();
303
+ reconnectReads.clear();
304
+ }, { once: true });
305
+ function assertActive() {
306
+ if (isDisposed()) {
307
+ throw new ContextDisposedError();
308
+ }
309
+ }
310
+ function assertAccountSize(account) {
311
+ if (!isRawAccount(account)) {
312
+ throw new ProviderError('The configured provider returned an invalid raw account. Fix the provider to return a complete account with valid z.ink/Solana address and owner fields and Uint8Array data before retrying.');
313
+ }
314
+ assertWithinLimit('account data bytes', account.data.byteLength, maxAccountDataBytes);
315
+ }
316
+ function requestedCommitment(options) {
317
+ return options?.commitment ?? defaultCommitment;
318
+ }
319
+ function definitionId(definition) {
320
+ const existing = definitionIds.get(definition);
321
+ if (existing !== undefined) {
322
+ return existing;
323
+ }
324
+ const id = nextDefinitionId++;
325
+ definitionIds.set(definition, id);
326
+ return id;
327
+ }
328
+ function keyFor(definition, address) {
329
+ return cacheKey(cluster, definition, address, definitionId(definition));
330
+ }
331
+ function rememberCacheKey(key, address, programAddress) {
332
+ const keys = cacheKeysByAddress.get(address) ?? new Map();
333
+ keys.set(key, programAddress);
334
+ cacheKeysByAddress.set(address, keys);
335
+ }
336
+ function forgetCacheKey(key, address) {
337
+ const keys = cacheKeysByAddress.get(address);
338
+ keys?.delete(key);
339
+ if (keys?.size === 0)
340
+ cacheKeysByAddress.delete(address);
341
+ }
342
+ function rememberActiveCacheKey(key, address, programAddress) {
343
+ const keys = activeCacheKeysByAddress.get(address) ??
344
+ new Map();
345
+ const active = keys.get(key);
346
+ keys.set(key, {
347
+ count: (active?.count ?? 0) + 1,
348
+ programAddress,
349
+ });
350
+ activeCacheKeysByAddress.set(address, keys);
351
+ }
352
+ function forgetActiveCacheKey(key, address) {
353
+ const keys = activeCacheKeysByAddress.get(address);
354
+ const active = keys?.get(key);
355
+ if (active === undefined)
356
+ return;
357
+ if (active.count === 1)
358
+ keys?.delete(key);
359
+ else
360
+ keys?.set(key, { ...active, count: active.count - 1 });
361
+ if (keys?.size === 0)
362
+ activeCacheKeysByAddress.delete(address);
363
+ }
364
+ function validateAndTimestamp(definition, account, source) {
365
+ const fetchedAt = Date.now();
366
+ const fetchedAtMonotonicMs = performance.now();
367
+ const snapshot = validateAndDecode(definition, account, source, fetchedAt);
368
+ snapshotFetchTimes.set(snapshot, fetchedAtMonotonicMs);
369
+ return snapshot;
370
+ }
371
+ function rawReadKey(address, commitment) {
372
+ return JSON.stringify([address, commitment]);
373
+ }
374
+ function discoveryReadKey(programAddress, filters, commitment, invalidationGeneration, addressReconciliationGeneration) {
375
+ return JSON.stringify([
376
+ programAddress,
377
+ commitment,
378
+ invalidationGeneration,
379
+ addressReconciliationGeneration,
380
+ filters.map((filter) => [filter.offset, [...filter.bytes]]),
381
+ ]);
382
+ }
383
+ function definedReadKey(key, commitment, invalidationGeneration, store) {
384
+ return JSON.stringify([key, commitment, invalidationGeneration, store]);
385
+ }
386
+ function cachedSnapshot(key, commitment, options) {
387
+ if (options?.refresh === true || options?.policy === 'no-store') {
388
+ return undefined;
389
+ }
390
+ const cachedByCommitment = cache.get(key);
391
+ if (cachedByCommitment === undefined) {
392
+ return undefined;
393
+ }
394
+ const maxAgeMs = configuredMaxAgeMs(options?.maxAgeMs ?? defaultMaxAgeMs);
395
+ let selected;
396
+ for (const available of COMPATIBLE_COMMITMENTS[commitment]) {
397
+ const cached = cachedByCommitment.get(available);
398
+ if (cached === undefined ||
399
+ performance.now() - cached.fetchedAtMonotonicMs >= maxAgeMs) {
400
+ continue;
401
+ }
402
+ const snapshot = cached.snapshot;
403
+ if (selected === undefined || isPreferredSnapshot(snapshot, selected)) {
404
+ selected = snapshot;
405
+ }
406
+ }
407
+ return selected;
408
+ }
409
+ function sharedRawReadEntry(address, commitment, minimumSequence = 0) {
410
+ const effectiveMinimumSequence = Math.max(minimumSequence, minimumRawReadSequenceByAddress.get(address) ?? 0);
411
+ for (const available of COMPATIBLE_COMMITMENTS[commitment]) {
412
+ const compatible = rawReads.get(rawReadKey(address, available));
413
+ if (compatible !== undefined &&
414
+ compatible.sequence >= effectiveMinimumSequence) {
415
+ return compatible;
416
+ }
417
+ }
418
+ let resolveRead;
419
+ let rejectRead;
420
+ const promise = new Promise((resolve, reject) => {
421
+ resolveRead = resolve;
422
+ rejectRead = reject;
423
+ });
424
+ const read = {
425
+ sequence: nextRawReadSequence++,
426
+ promise,
427
+ };
428
+ const registryKey = rawReadKey(address, commitment);
429
+ rawReads.set(registryKey, read);
430
+ const operation = (async () => {
431
+ try {
432
+ const account = await provider.readAccount(address, {
433
+ commitment,
434
+ signal: lifecycle.signal,
435
+ });
436
+ if (isDisposed()) {
437
+ throw new ContextDisposedError();
438
+ }
439
+ if (account !== undefined) {
440
+ assertAccountSize(account);
441
+ if (account.address !== address) {
442
+ throw new ProviderAccountAddressMismatchError(address, account.address);
443
+ }
444
+ assertProviderCommitment(account, commitment);
445
+ }
446
+ return account;
447
+ }
448
+ catch (cause) {
449
+ if (isDisposed()) {
450
+ throw new ContextDisposedError();
451
+ }
452
+ if (cause instanceof SageSdkError) {
453
+ throw cause;
454
+ }
455
+ throw new ProviderError('The configured provider could not read the requested z.ink account. Check the provider connection and retry.', { address });
456
+ }
457
+ finally {
458
+ if (rawReads.get(registryKey) === read) {
459
+ rawReads.delete(registryKey);
460
+ }
461
+ }
462
+ })();
463
+ void operation.then(resolveRead, rejectRead);
464
+ void promise.catch(() => undefined);
465
+ return read;
466
+ }
467
+ function sharedRawRead(address, commitment, minimumSequence = 0) {
468
+ return sharedRawReadEntry(address, commitment, minimumSequence).promise;
469
+ }
470
+ function findCompatibleRawRead(address, commitment, minimumSequence) {
471
+ const effectiveMinimumSequence = Math.max(minimumSequence, minimumRawReadSequenceByAddress.get(address) ?? 0);
472
+ for (const available of COMPATIBLE_COMMITMENTS[commitment]) {
473
+ const compatible = rawReads.get(rawReadKey(address, available));
474
+ if (compatible !== undefined &&
475
+ compatible.sequence >= effectiveMinimumSequence) {
476
+ return compatible;
477
+ }
478
+ }
479
+ return undefined;
480
+ }
481
+ function primeRawBatchReads(addresses, commitment, minimumSequenceFor) {
482
+ const pending = [...new Set(addresses)].filter((address) => findCompatibleRawRead(address, commitment, minimumSequenceFor(address)) === undefined);
483
+ if (pending.length === 0)
484
+ return;
485
+ const reads = pending.map((address) => {
486
+ let resolve;
487
+ let reject;
488
+ const promise = new Promise((accept, fail) => {
489
+ resolve = accept;
490
+ reject = fail;
491
+ });
492
+ const read = { promise, sequence: nextRawReadSequence++ };
493
+ rawReads.set(rawReadKey(address, commitment), read);
494
+ void promise.catch(() => undefined);
495
+ return { address, read, reject, resolve };
496
+ });
497
+ void (async () => {
498
+ try {
499
+ let accounts;
500
+ if (provider.readAccounts !== undefined) {
501
+ const result = await provider.readAccounts(Object.freeze([...pending]), {
502
+ commitment,
503
+ signal: lifecycle.signal,
504
+ });
505
+ if (!Array.isArray(result) ||
506
+ result.length !== pending.length ||
507
+ !result.every((account) => account === undefined || isRawAccount(account))) {
508
+ throw new ProviderError('The configured provider returned an invalid multiple-account response. Fix the provider to return undefined or a complete raw account for every requested address in the original order before retrying.');
509
+ }
510
+ accounts = result;
511
+ }
512
+ else {
513
+ const fallback = new Array(pending.length);
514
+ let nextIndex = 0;
515
+ const worker = async () => {
516
+ while (nextIndex < pending.length) {
517
+ const index = nextIndex++;
518
+ fallback[index] = await provider.readAccount(pending[index], {
519
+ commitment,
520
+ signal: lifecycle.signal,
521
+ });
522
+ }
523
+ };
524
+ await Promise.all(Array.from({
525
+ length: Math.min(pending.length, MAX_CONCURRENT_FALLBACK_READS),
526
+ }, worker));
527
+ accounts = fallback;
528
+ }
529
+ if (isDisposed())
530
+ throw new ContextDisposedError();
531
+ accounts.forEach((account, index) => {
532
+ if (account === undefined)
533
+ return;
534
+ assertAccountSize(account);
535
+ const requestedAddress = pending[index];
536
+ if (account.address !== requestedAddress) {
537
+ throw new ProviderAccountAddressMismatchError(requestedAddress, account.address);
538
+ }
539
+ assertProviderCommitment(account, commitment);
540
+ });
541
+ reads.forEach(({ resolve }, index) => resolve(accounts[index]));
542
+ }
543
+ catch (cause) {
544
+ const error = isDisposed()
545
+ ? new ContextDisposedError()
546
+ : cause instanceof SageSdkError
547
+ ? cause
548
+ : new ProviderError('The configured provider could not read the requested z.ink accounts. Check the provider connection and retry.');
549
+ reads.forEach(({ reject }) => reject(error));
550
+ }
551
+ finally {
552
+ reads.forEach(({ address, read }) => {
553
+ const registryKey = rawReadKey(address, commitment);
554
+ if (rawReads.get(registryKey) === read)
555
+ rawReads.delete(registryKey);
556
+ });
557
+ }
558
+ })();
559
+ }
560
+ function sharedDiscovery(programAddress, filters, commitment, discoveryInvalidationGeneration, addressReconciliationGeneration) {
561
+ const registryKey = discoveryReadKey(programAddress, filters, commitment, discoveryInvalidationGeneration, addressReconciliationGeneration);
562
+ const existing = discoveryReads.get(registryKey);
563
+ if (existing !== undefined) {
564
+ return existing;
565
+ }
566
+ let resolveDiscovery;
567
+ let rejectDiscovery;
568
+ const promise = new Promise((resolve, reject) => {
569
+ resolveDiscovery = resolve;
570
+ rejectDiscovery = reject;
571
+ });
572
+ const read = {
573
+ promise,
574
+ };
575
+ discoveryReads.set(registryKey, read);
576
+ const operation = (async () => {
577
+ try {
578
+ const result = await provider.discoverAccounts({
579
+ commitment,
580
+ filters: copyProviderDiscoveryFilters(filters),
581
+ programAddress,
582
+ signal: lifecycle.signal,
583
+ });
584
+ if (isDisposed()) {
585
+ throw new ContextDisposedError();
586
+ }
587
+ if (!Array.isArray(result)) {
588
+ throw new ProviderError('The configured provider returned an invalid account-discovery response. Fix the provider to return a raw-account array before retrying.');
589
+ }
590
+ assertWithinLimit('discovery results', result.length, maxDiscoveryResults);
591
+ result.forEach(assertAccountSize);
592
+ return result;
593
+ }
594
+ finally {
595
+ if (discoveryReads.get(registryKey) === read) {
596
+ discoveryReads.delete(registryKey);
597
+ }
598
+ }
599
+ })();
600
+ void operation.then(resolveDiscovery, rejectDiscovery);
601
+ void promise.catch(() => undefined);
602
+ return read;
603
+ }
604
+ function sharedIndexerDiscovery(activeIndexer, definition, filters, commitment, discoveryInvalidationGeneration, addressReconciliationGeneration) {
605
+ const registryKey = JSON.stringify([
606
+ 'indexer',
607
+ definition.type,
608
+ discoveryReadKey(definition.programAddress, filters, commitment, discoveryInvalidationGeneration, addressReconciliationGeneration),
609
+ ]);
610
+ const existing = indexerReads.get(registryKey);
611
+ if (existing !== undefined)
612
+ return existing;
613
+ let resolveDiscovery;
614
+ let rejectDiscovery;
615
+ const promise = new Promise((resolve, reject) => {
616
+ resolveDiscovery = resolve;
617
+ rejectDiscovery = reject;
618
+ });
619
+ indexerReads.set(registryKey, promise);
620
+ const operation = (async () => {
621
+ try {
622
+ const candidates = await activeIndexer.discoverAddresses({
623
+ accountType: definition.type,
624
+ commitment,
625
+ filters: copyProviderDiscoveryFilters(filters),
626
+ programAddress: definition.programAddress,
627
+ signal: lifecycle.signal,
628
+ });
629
+ if (isDisposed())
630
+ throw new ContextDisposedError();
631
+ if (!Array.isArray(candidates)) {
632
+ throw new ProviderError('The configured indexer returned malformed candidate addresses. Fix the indexer response to return only valid z.ink/Solana addresses before retrying discovery.', {
633
+ accountType: definition.type,
634
+ provider: activeIndexer.identity,
635
+ strategy: 'indexer',
636
+ });
637
+ }
638
+ assertWithinLimit('indexer candidates', candidates.length, maxDiscoveryResults);
639
+ if (candidates.some((candidate) => typeof candidate !== 'string' || !isAddress(candidate))) {
640
+ throw new ProviderError('The configured indexer returned malformed candidate addresses. Fix the indexer response to return only valid z.ink/Solana addresses before retrying discovery.', {
641
+ accountType: definition.type,
642
+ provider: activeIndexer.identity,
643
+ strategy: 'indexer',
644
+ });
645
+ }
646
+ return Object.freeze([...candidates]);
647
+ }
648
+ catch (cause) {
649
+ if (isDisposed())
650
+ throw new ContextDisposedError();
651
+ if (cause instanceof SageSdkError)
652
+ throw cause;
653
+ throw new ProviderError('The configured indexer could not discover candidate addresses. Check the indexer connection and retry discovery.', {
654
+ accountType: definition.type,
655
+ provider: activeIndexer.identity,
656
+ strategy: 'indexer',
657
+ });
658
+ }
659
+ finally {
660
+ if (indexerReads.get(registryKey) === promise) {
661
+ indexerReads.delete(registryKey);
662
+ }
663
+ }
664
+ })();
665
+ void operation.then(resolveDiscovery, rejectDiscovery);
666
+ void promise.catch(() => undefined);
667
+ return promise;
668
+ }
669
+ async function validateIndexerCandidate(definition, address, filters, commitment, signal) {
670
+ const account = await waitForCaller(sharedRawRead(address, commitment, minimumRawReadSequence.get(keyFor(definition, address))), signal);
671
+ if (account === undefined)
672
+ return undefined;
673
+ const conflicts = filters.some((filter) => filter.offset + filter.bytes.length > account.data.length ||
674
+ filter.bytes.some((byte, index) => account.data[filter.offset + index] !== byte));
675
+ if (conflicts) {
676
+ throw new IndexerCandidateConflictError(definition.type, address, new RangeError('The directly read account bytes contradicted the indexer discovery filters.'), `The indexer returned ${address}, but its direct z.ink account state no longer matches the requested ${definition.type} relationship. Refresh the indexer or use targeted RPC discovery before retrying.`);
677
+ }
678
+ return validateAndTimestamp(definition, copyRawAccount(account), provider.identity);
679
+ }
680
+ function storeSnapshot(key, snapshot, operationInvalidationSequence) {
681
+ if ((invalidatedAt.get(key) ?? 0) > operationInvalidationSequence ||
682
+ (addressInvalidatedAt.get(snapshot.address) ?? 0) >
683
+ operationInvalidationSequence) {
684
+ return;
685
+ }
686
+ let cachedByCommitment = cache.get(key);
687
+ if (cachedByCommitment === undefined) {
688
+ assertWithinLimit('cache entries', cache.size + 1, maxCacheEntries);
689
+ cachedByCommitment = new Map();
690
+ cache.set(key, cachedByCommitment);
691
+ rememberCacheKey(key, snapshot.address, snapshot.programAddress);
692
+ }
693
+ const existing = cachedByCommitment.get(snapshot.commitment);
694
+ if (existing === undefined || snapshot.slot >= existing.snapshot.slot) {
695
+ cachedByCommitment.set(snapshot.commitment, {
696
+ fetchedAtMonotonicMs: snapshotFetchTimes.get(snapshot),
697
+ snapshot,
698
+ });
699
+ }
700
+ }
701
+ function assertCacheCapacity(keys) {
702
+ const additional = new Set(keys.filter((key) => !cache.has(key))).size;
703
+ assertWithinLimit('cache entries', cache.size + additional, maxCacheEntries);
704
+ }
705
+ function storeSubscriptionSnapshot(key, snapshot) {
706
+ const cachedByCommitment = cache.get(key);
707
+ if (invalidatedAt.has(key) &&
708
+ !cachedByCommitment?.has(snapshot.commitment)) {
709
+ return;
710
+ }
711
+ let writableByCommitment = cachedByCommitment;
712
+ if (writableByCommitment === undefined) {
713
+ assertWithinLimit('cache entries', cache.size + 1, maxCacheEntries);
714
+ writableByCommitment = new Map();
715
+ cache.set(key, writableByCommitment);
716
+ rememberCacheKey(key, snapshot.address, snapshot.programAddress);
717
+ }
718
+ const existing = writableByCommitment.get(snapshot.commitment);
719
+ if (existing === undefined || snapshot.slot > existing.snapshot.slot) {
720
+ writableByCommitment.set(snapshot.commitment, {
721
+ fetchedAtMonotonicMs: snapshotFetchTimes.get(snapshot),
722
+ snapshot,
723
+ });
724
+ }
725
+ }
726
+ function sharedDefinedRead(definition, address, commitment, store, minimumReadSequence = 0) {
727
+ const key = keyFor(definition, address);
728
+ const invalidationGeneration = invalidatedAt.get(key) ?? 0;
729
+ for (const available of COMPATIBLE_COMMITMENTS[commitment]) {
730
+ const compatible = definedReads.get(definedReadKey(key, available, invalidationGeneration, store));
731
+ if (compatible !== undefined &&
732
+ compatible.rawReadSequence >= minimumReadSequence) {
733
+ return compatible.promise;
734
+ }
735
+ }
736
+ const rawRead = sharedRawReadEntry(address, commitment, Math.max(minimumReadSequence, minimumRawReadSequence.get(key) ?? 0));
737
+ let resolveRead;
738
+ let rejectRead;
739
+ const promise = new Promise((resolve, reject) => {
740
+ resolveRead = resolve;
741
+ rejectRead = reject;
742
+ });
743
+ const read = {
744
+ promise,
745
+ rawReadSequence: rawRead.sequence,
746
+ };
747
+ const registryKey = definedReadKey(key, commitment, invalidationGeneration, store);
748
+ definedReads.set(registryKey, read);
749
+ rememberActiveCacheKey(key, address, definition.programAddress);
750
+ const operationInvalidationSequence = invalidationSequence;
751
+ const operation = (async () => {
752
+ try {
753
+ const raw = await rawRead.promise;
754
+ if (raw === undefined) {
755
+ return undefined;
756
+ }
757
+ const snapshot = validateAndTimestamp(definition, copyRawAccount(raw), provider.identity);
758
+ if (store) {
759
+ storeSnapshot(key, snapshot, operationInvalidationSequence);
760
+ }
761
+ return snapshot;
762
+ }
763
+ finally {
764
+ forgetActiveCacheKey(key, address);
765
+ if (definedReads.get(registryKey) === read) {
766
+ definedReads.delete(registryKey);
767
+ }
768
+ }
769
+ })();
770
+ void operation.then(resolveRead, rejectRead);
771
+ void promise.catch(() => undefined);
772
+ return promise;
773
+ }
774
+ function sharedReconnectRead(definition, address, commitment) {
775
+ const key = keyFor(definition, address);
776
+ const registryKey = JSON.stringify([
777
+ key,
778
+ commitment,
779
+ invalidatedAt.get(key) ?? 0,
780
+ ]);
781
+ const existing = reconnectReads.get(registryKey);
782
+ if (existing !== undefined) {
783
+ return existing;
784
+ }
785
+ const promise = sharedDefinedRead(definition, address, commitment, true);
786
+ reconnectReads.set(registryKey, promise);
787
+ const retainSettledResult = () => {
788
+ setTimeout(() => reconnectReads.delete(registryKey), RECONNECT_READ_COALESCE_MS);
789
+ };
790
+ void promise.then(retainSettledResult, retainSettledResult);
791
+ return promise;
792
+ }
793
+ async function readOptional(definition, address, options) {
794
+ assertActive();
795
+ throwIfAborted(options?.signal);
796
+ configuredMaxAgeMs(options?.maxAgeMs ?? defaultMaxAgeMs);
797
+ const commitment = requestedCommitment(options);
798
+ const key = keyFor(definition, address);
799
+ const cached = cachedSnapshot(key, commitment, options);
800
+ if (cached !== undefined) {
801
+ return cached;
802
+ }
803
+ return waitForCaller(sharedDefinedRead(definition, address, commitment, options?.policy !== 'no-store'), options?.signal);
804
+ }
805
+ function invalidateKey(key, address, programAddress) {
806
+ cache.delete(key);
807
+ forgetCacheKey(key, address);
808
+ invalidationSequence += 1;
809
+ invalidatedAt.set(key, invalidationSequence);
810
+ discoveryInvalidatedAt.set(programAddress, invalidationSequence);
811
+ minimumRawReadSequence.set(key, nextRawReadSequence);
812
+ }
813
+ return Object.freeze({
814
+ [INVALIDATE_CONTEXT_ADDRESSES](addresses) {
815
+ assertActive();
816
+ const uniqueAddresses = new Set(addresses);
817
+ reconciliationGeneration += 1;
818
+ for (const address of uniqueAddresses) {
819
+ invalidationSequence += 1;
820
+ addressInvalidatedAt.set(address, invalidationSequence);
821
+ minimumRawReadSequenceByAddress.set(address, nextRawReadSequence);
822
+ const keys = new Map(cacheKeysByAddress.get(address) ?? []);
823
+ for (const [key, active] of activeCacheKeysByAddress.get(address) ??
824
+ []) {
825
+ keys.set(key, active.programAddress);
826
+ }
827
+ for (const [key, programAddress] of keys) {
828
+ invalidateKey(key, address, programAddress);
829
+ }
830
+ }
831
+ },
832
+ async [READ_CONTEXT_RAW_ACCOUNTS](addresses, options) {
833
+ assertActive();
834
+ throwIfAborted(options?.signal);
835
+ assertWithinLimit('readMany accounts', addresses.length, maxReadManyAccounts);
836
+ const commitment = requestedCommitment(options);
837
+ const unique = [...new Set(addresses)];
838
+ const minimumReadSequence = nextRawReadSequence;
839
+ primeRawBatchReads(unique, commitment, () => minimumReadSequence);
840
+ const accounts = new Map(await Promise.all(unique.map(async (address) => Object.freeze([
841
+ address,
842
+ await waitForCaller(sharedRawRead(address, commitment, minimumReadSequence), options?.signal),
843
+ ]))));
844
+ return Object.freeze(addresses.map((address) => {
845
+ const account = accounts.get(address);
846
+ return account === undefined ? undefined : copyRawAccount(account);
847
+ }));
848
+ },
849
+ invalidate(definition, address) {
850
+ assertActive();
851
+ const key = keyFor(definition, address);
852
+ invalidateKey(key, address, definition.programAddress);
853
+ },
854
+ async read(definition, address, options) {
855
+ const snapshot = await readOptional(definition, address, options);
856
+ if (snapshot === undefined) {
857
+ throw new AccountNotFoundError(definition.type, address);
858
+ }
859
+ return snapshot;
860
+ },
861
+ async readMany(definition, addresses, options) {
862
+ assertActive();
863
+ throwIfAborted(options?.signal);
864
+ assertWithinLimit('readMany accounts', addresses.length, maxReadManyAccounts);
865
+ configuredMaxAgeMs(options?.maxAgeMs ?? defaultMaxAgeMs);
866
+ const commitment = requestedCommitment(options);
867
+ const uncached = [...new Set(addresses)].filter((address) => cachedSnapshot(keyFor(definition, address), commitment, options) === undefined);
868
+ primeRawBatchReads(uncached, commitment, (candidate) => minimumRawReadSequence.get(keyFor(definition, candidate)) ?? 0);
869
+ return Object.freeze(await Promise.all(addresses.map((address) => readOptional(definition, address, options))));
870
+ },
871
+ async discover(definition, request) {
872
+ assertActive();
873
+ throwIfAborted(request.signal);
874
+ const operationInvalidationSequence = invalidationSequence;
875
+ const commitment = requestedCommitment(request);
876
+ validateDiscoveryFilters(request.filters);
877
+ const providerFilters = copyProviderDiscoveryFilters(request.filters);
878
+ const metadataFilters = copyReadMetaFilters(request.filters);
879
+ if (indexer !== undefined &&
880
+ request.strategy !== 'direct' &&
881
+ request.strategy !== 'derived') {
882
+ const candidates = await waitForCaller(sharedIndexerDiscovery(indexer, definition, providerFilters, commitment, discoveryInvalidatedAt.get(definition.programAddress) ?? 0, reconciliationGeneration), request.signal);
883
+ const uniqueCandidates = [...new Set(candidates)];
884
+ primeRawBatchReads(uniqueCandidates, commitment, (candidate) => minimumRawReadSequence.get(keyFor(definition, candidate)) ?? 0);
885
+ let validated;
886
+ try {
887
+ const validationResults = await Promise.allSettled(uniqueCandidates.map((address) => validateIndexerCandidate(definition, address, providerFilters, commitment, request.signal)));
888
+ const rejected = validationResults.find((result) => result.status === 'rejected');
889
+ if (rejected !== undefined)
890
+ throw rejected.reason;
891
+ validated = validationResults.map((result) => result.value);
892
+ }
893
+ catch (cause) {
894
+ if (request.signal?.aborted === true) {
895
+ throw abortReason(request.signal);
896
+ }
897
+ if (isDisposed())
898
+ throw new ContextDisposedError();
899
+ if (cause instanceof IndexerCandidateConflictError) {
900
+ throw new ProviderError('A configured indexer candidate conflicted with direct z.ink account state. Refresh the indexer or use targeted RPC discovery before retrying.', {
901
+ accountType: definition.type,
902
+ address: cause.address,
903
+ cause,
904
+ provider: indexer.identity,
905
+ strategy: 'indexer',
906
+ });
907
+ }
908
+ if (cause instanceof ProviderError) {
909
+ throw new ProviderError(cause.message, {
910
+ accountType: definition.type,
911
+ ...(cause.address !== undefined
912
+ ? { address: cause.address }
913
+ : {}),
914
+ cause,
915
+ provider: cause.provider ?? provider.identity,
916
+ strategy: 'indexer',
917
+ });
918
+ }
919
+ /* v8 ignore next -- candidate reads and decoders normalize unknown failures before this defensive boundary. */
920
+ if (!(cause instanceof SageSdkError)) {
921
+ throw new ProviderError('The configured direct provider could not validate an indexer candidate. Check the direct provider connection and retry discovery.', {
922
+ accountType: definition.type,
923
+ provider: provider.identity,
924
+ strategy: 'indexer',
925
+ });
926
+ }
927
+ throw cause;
928
+ }
929
+ const snapshots = validated.filter((snapshot) => snapshot !== undefined);
930
+ if (request.policy !== 'no-store') {
931
+ assertCacheCapacity(snapshots.map((snapshot) => keyFor(definition, snapshot.address)));
932
+ for (const snapshot of snapshots) {
933
+ storeSnapshot(keyFor(definition, snapshot.address), snapshot, operationInvalidationSequence);
934
+ }
935
+ }
936
+ const slot = snapshots.reduce((earliest, snapshot) => earliest === undefined || snapshot.slot < earliest
937
+ ? snapshot.slot
938
+ : earliest, undefined);
939
+ return Object.freeze(attachReadMeta(snapshots, {
940
+ commitment,
941
+ filters: metadataFilters,
942
+ indexer: Object.freeze({
943
+ candidateCount: candidates.length,
944
+ duplicateCount: candidates.length - uniqueCandidates.length,
945
+ missingCount: uniqueCandidates.length - snapshots.length,
946
+ validatedCount: snapshots.length,
947
+ }),
948
+ slot: slot ?? 0n,
949
+ source: Object.freeze({ ...indexer.identity }),
950
+ strategy: 'indexer',
951
+ }));
952
+ }
953
+ let accounts;
954
+ try {
955
+ const discoveryRead = sharedDiscovery(definition.programAddress, providerFilters, commitment, discoveryInvalidatedAt.get(definition.programAddress) ?? 0, reconciliationGeneration);
956
+ accounts = await waitForCaller(discoveryRead.promise, request.signal);
957
+ }
958
+ catch (cause) {
959
+ if (request.signal?.aborted === true) {
960
+ throw abortReason(request.signal);
961
+ }
962
+ if (isDisposed()) {
963
+ throw new ContextDisposedError();
964
+ }
965
+ if (cause instanceof SageSdkError) {
966
+ throw cause;
967
+ }
968
+ throw new ProviderError('The configured provider could not discover the requested z.ink accounts. Check the discovery filters and provider connection, then retry.', { accountType: definition.type });
969
+ }
970
+ assertActive();
971
+ const snapshotsByAddress = new Map();
972
+ for (const account of accounts) {
973
+ assertProviderCommitment(account, commitment);
974
+ const snapshot = validateAndTimestamp(definition, copyRawAccount(account), provider.identity);
975
+ const existing = snapshotsByAddress.get(snapshot.address);
976
+ if (existing === undefined || isPreferredSnapshot(snapshot, existing)) {
977
+ snapshotsByAddress.set(snapshot.address, snapshot);
978
+ }
979
+ }
980
+ const snapshots = [...snapshotsByAddress.values()];
981
+ if (request.policy !== 'no-store') {
982
+ assertCacheCapacity(snapshots.map((snapshot) => keyFor(definition, snapshot.address)));
983
+ for (const snapshot of snapshots) {
984
+ storeSnapshot(keyFor(definition, snapshot.address), snapshot, operationInvalidationSequence);
985
+ }
986
+ }
987
+ const slot = snapshots.reduce((earliest, snapshot) => earliest === undefined || snapshot.slot < earliest
988
+ ? snapshot.slot
989
+ : earliest, undefined);
990
+ return Object.freeze(attachReadMeta(snapshots, {
991
+ commitment,
992
+ filters: metadataFilters,
993
+ slot: slot ?? 0n,
994
+ source: Object.freeze({ ...provider.identity }),
995
+ strategy: request.strategy === 'indexer'
996
+ ? 'targeted-program-accounts'
997
+ : request.strategy,
998
+ }));
999
+ },
1000
+ async subscribe(definition, address, observer, options = {}) {
1001
+ assertActive();
1002
+ throwIfAborted(options.signal);
1003
+ if (subscriptionProvider === undefined) {
1004
+ throw new ProviderError('This SAGE context has no account subscription provider. Configure a WebSocket subscription provider before subscribing to live account updates.', { accountType: definition.type, address });
1005
+ }
1006
+ const commitment = requestedCommitment(options);
1007
+ const key = keyFor(definition, address);
1008
+ const registrationLifecycle = new AbortController();
1009
+ let registration;
1010
+ let resolveRegistration;
1011
+ let rejectRegistration;
1012
+ const registrationAttempt = new Promise((resolve, reject) => {
1013
+ resolveRegistration = resolve;
1014
+ rejectRegistration = reject;
1015
+ });
1016
+ let lastDelivered;
1017
+ let stopPromise;
1018
+ let resolveCompletion;
1019
+ const completion = new Promise((resolve) => {
1020
+ resolveCompletion = resolve;
1021
+ });
1022
+ trackSubscription(completion);
1023
+ let resolveRegistrationDeliveryStarted;
1024
+ const registrationDeliveryStarted = new Promise((resolve) => {
1025
+ resolveRegistrationDeliveryStarted = resolve;
1026
+ });
1027
+ const subscriptionErrorMessage = 'The account subscription could not process a live z.ink update. Check the WebSocket provider and retry the subscription.';
1028
+ const observerErrorMessage = 'The account subscription onSnapshot callback could not process a validated snapshot. Fix the consumer callback before retrying delivery.';
1029
+ let notificationRunning = false;
1030
+ let pendingSnapshot;
1031
+ let pendingSnapshotAwaitingReconnect = false;
1032
+ let reconnecting = false;
1033
+ let reconnectPending = false;
1034
+ let pendingReconnectReadSequence;
1035
+ const pendingErrors = new Map();
1036
+ const coalescedErrors = new Map();
1037
+ let coalescedSnapshots = 0;
1038
+ const emitDiagnostic = (event) => {
1039
+ try {
1040
+ observer.onDiagnostic?.(event);
1041
+ }
1042
+ catch {
1043
+ // Diagnostics never interrupt delivery or transport cleanup.
1044
+ }
1045
+ };
1046
+ const normalizeSubscriptionError = (cause, message) => cause instanceof SageSdkError
1047
+ ? cause
1048
+ : new ProviderError(message, {
1049
+ accountType: definition.type,
1050
+ address,
1051
+ cause,
1052
+ });
1053
+ const runNotifications = async () => {
1054
+ if (notificationRunning)
1055
+ return;
1056
+ notificationRunning = true;
1057
+ try {
1058
+ while (!registrationLifecycle.signal.aborted && !isDisposed()) {
1059
+ const errorEntry = pendingErrors.entries().next().value;
1060
+ if (errorEntry !== undefined) {
1061
+ pendingErrors.delete(errorEntry[0]);
1062
+ coalescedErrors.delete(errorEntry[0]);
1063
+ try {
1064
+ const notification = observer.onError(errorEntry[1]);
1065
+ resolveRegistrationDeliveryStarted();
1066
+ await notification;
1067
+ }
1068
+ catch {
1069
+ resolveRegistrationDeliveryStarted();
1070
+ // Consumer observer failures never terminate transport.
1071
+ }
1072
+ continue;
1073
+ }
1074
+ const snapshot = pendingSnapshot;
1075
+ if (snapshot === undefined)
1076
+ return;
1077
+ if (pendingSnapshotAwaitingReconnect)
1078
+ return;
1079
+ pendingSnapshot = undefined;
1080
+ coalescedSnapshots = 0;
1081
+ try {
1082
+ const notification = observer.onSnapshot(snapshot);
1083
+ resolveRegistrationDeliveryStarted();
1084
+ await notification;
1085
+ lastDelivered = snapshot;
1086
+ }
1087
+ catch (cause) {
1088
+ resolveRegistrationDeliveryStarted();
1089
+ const error = normalizeSubscriptionError(cause, observerErrorMessage);
1090
+ pendingErrors.set(error.code, error);
1091
+ }
1092
+ }
1093
+ }
1094
+ finally {
1095
+ notificationRunning = false;
1096
+ }
1097
+ };
1098
+ const reportError = (cause, message) => {
1099
+ if (registrationLifecycle.signal.aborted)
1100
+ return;
1101
+ const error = normalizeSubscriptionError(cause, message);
1102
+ if (pendingErrors.has(error.code)) {
1103
+ const count = (coalescedErrors.get(error.code) ?? 0) + 1;
1104
+ coalescedErrors.set(error.code, count);
1105
+ emitDiagnostic({
1106
+ accountType: definition.type,
1107
+ address,
1108
+ coalescedCount: count,
1109
+ errorCode: error.code,
1110
+ kind: 'subscription-error-coalesced',
1111
+ });
1112
+ }
1113
+ pendingErrors.set(error.code, error);
1114
+ void runNotifications();
1115
+ };
1116
+ const queueSnapshotCandidate = (selected, awaitReconnect = false) => {
1117
+ const deliveryBaseline = pendingSnapshot ?? lastDelivered;
1118
+ if (deliveryBaseline !== undefined &&
1119
+ !isPreferredSnapshot(selected, deliveryBaseline)) {
1120
+ return;
1121
+ }
1122
+ if (pendingSnapshot !== undefined) {
1123
+ coalescedSnapshots += 1;
1124
+ emitDiagnostic({
1125
+ accountType: definition.type,
1126
+ address,
1127
+ coalescedCount: coalescedSnapshots,
1128
+ kind: 'subscription-snapshot-coalesced',
1129
+ });
1130
+ }
1131
+ pendingSnapshot = selected;
1132
+ pendingSnapshotAwaitingReconnect = awaitReconnect;
1133
+ if (!awaitReconnect)
1134
+ void runNotifications();
1135
+ };
1136
+ const queueSelectedSnapshot = (fallback) => {
1137
+ queueSnapshotCandidate(cachedSnapshot(key, commitment) ?? fallback);
1138
+ };
1139
+ const decodeAccountEvent = (event) => {
1140
+ assertAccountSize(event.account);
1141
+ const account = copyRawAccount(event.account);
1142
+ if (account.address !== address) {
1143
+ throw new ProviderError(`The account subscription returned ${account.address} for requested address ${address}. Fix the WebSocket provider response before retrying.`, { accountType: definition.type, address });
1144
+ }
1145
+ assertProviderCommitment(account, commitment);
1146
+ const snapshot = validateAndTimestamp(definition, account, subscriptionProvider.identity);
1147
+ return snapshot;
1148
+ };
1149
+ const storeAndQueueSnapshot = (snapshot) => {
1150
+ storeSubscriptionSnapshot(key, snapshot);
1151
+ queueSelectedSnapshot(snapshot);
1152
+ };
1153
+ const processReconnect = (coalesce) => {
1154
+ if (reconnecting) {
1155
+ reconnectPending = true;
1156
+ pendingReconnectReadSequence = Math.max(pendingReconnectReadSequence ?? 0, nextRawReadSequence);
1157
+ return;
1158
+ }
1159
+ reconnecting = true;
1160
+ void (async () => {
1161
+ try {
1162
+ let useSettledReconnectRead = coalesce;
1163
+ do {
1164
+ const minimumReadSequence = pendingReconnectReadSequence;
1165
+ reconnectPending = false;
1166
+ pendingReconnectReadSequence = undefined;
1167
+ try {
1168
+ const snapshot = await waitForCaller(useSettledReconnectRead
1169
+ ? sharedReconnectRead(definition, address, commitment)
1170
+ : sharedDefinedRead(definition, address, commitment, true, minimumReadSequence), registrationLifecycle.signal);
1171
+ if (snapshot === undefined) {
1172
+ throw new AccountNotFoundError(definition.type, address);
1173
+ }
1174
+ queueSelectedSnapshot(snapshot);
1175
+ }
1176
+ catch (cause) {
1177
+ reportError(cause, subscriptionErrorMessage);
1178
+ }
1179
+ useSettledReconnectRead = false;
1180
+ } while (reconnectPending &&
1181
+ !registrationLifecycle.signal.aborted &&
1182
+ !isDisposed());
1183
+ }
1184
+ finally {
1185
+ reconnecting = false;
1186
+ if (pendingSnapshotAwaitingReconnect &&
1187
+ pendingSnapshot !== undefined &&
1188
+ !registrationLifecycle.signal.aborted &&
1189
+ !isDisposed()) {
1190
+ const pending = pendingSnapshot;
1191
+ pendingSnapshotAwaitingReconnect = false;
1192
+ try {
1193
+ storeSubscriptionSnapshot(key, pending);
1194
+ }
1195
+ catch (cause) {
1196
+ pendingSnapshot = undefined;
1197
+ reportError(cause, subscriptionErrorMessage);
1198
+ }
1199
+ }
1200
+ void runNotifications();
1201
+ }
1202
+ })();
1203
+ };
1204
+ const enqueue = (event) => {
1205
+ if (registrationLifecycle.signal.aborted || isDisposed())
1206
+ return;
1207
+ if (event.kind === 'reconnected') {
1208
+ processReconnect(true);
1209
+ return;
1210
+ }
1211
+ try {
1212
+ const snapshot = decodeAccountEvent(event);
1213
+ if (reconnecting) {
1214
+ const cached = cachedSnapshot(key, commitment);
1215
+ queueSnapshotCandidate(cached === undefined || isPreferredSnapshot(snapshot, cached)
1216
+ ? snapshot
1217
+ : cached, true);
1218
+ return;
1219
+ }
1220
+ storeAndQueueSnapshot(snapshot);
1221
+ }
1222
+ catch (cause) {
1223
+ reportError(cause, subscriptionErrorMessage);
1224
+ }
1225
+ };
1226
+ const abortRegistration = () => registrationLifecycle.abort(options.signal?.aborted === true
1227
+ ? options.signal.reason
1228
+ : lifecycle.signal.reason);
1229
+ options.signal?.addEventListener('abort', abortRegistration, {
1230
+ once: true,
1231
+ });
1232
+ lifecycle.signal.addEventListener('abort', abortRegistration, {
1233
+ once: true,
1234
+ });
1235
+ const cleanupRegistration = () => {
1236
+ const unsubscribeRegistration = async (activeRegistration) => {
1237
+ try {
1238
+ await activeRegistration.unsubscribe();
1239
+ }
1240
+ catch {
1241
+ // Disposal remains best-effort when a transport is already gone.
1242
+ }
1243
+ };
1244
+ if (registration === undefined) {
1245
+ void registrationAttempt.then(async (activeRegistration) => {
1246
+ registration = activeRegistration;
1247
+ await unsubscribeRegistration(activeRegistration);
1248
+ }, () => undefined);
1249
+ return Promise.resolve();
1250
+ }
1251
+ return unsubscribeRegistration(registration);
1252
+ };
1253
+ const stop = () => {
1254
+ if (stopPromise !== undefined)
1255
+ return stopPromise;
1256
+ let resolveStop;
1257
+ stopPromise = new Promise((resolve) => {
1258
+ resolveStop = resolve;
1259
+ });
1260
+ void (async () => {
1261
+ try {
1262
+ registrationLifecycle.abort();
1263
+ options.signal?.removeEventListener('abort', abortRegistration);
1264
+ lifecycle.signal.removeEventListener('abort', abortRegistration);
1265
+ await cleanupRegistration();
1266
+ }
1267
+ finally {
1268
+ resolveCompletion();
1269
+ resolveStop();
1270
+ }
1271
+ })();
1272
+ return stopPromise;
1273
+ };
1274
+ registrationLifecycle.signal.addEventListener('abort', () => void stop(), { once: true });
1275
+ try {
1276
+ try {
1277
+ const providerRegistration = subscriptionProvider.subscribeAccount({
1278
+ address,
1279
+ commitment,
1280
+ signal: registrationLifecycle.signal,
1281
+ }, (event) => void enqueue(event));
1282
+ void providerRegistration.then(resolveRegistration, rejectRegistration);
1283
+ }
1284
+ catch (cause) {
1285
+ rejectRegistration(cause);
1286
+ }
1287
+ registration = await waitForCaller(registrationAttempt, registrationLifecycle.signal);
1288
+ }
1289
+ catch (cause) {
1290
+ const wasCancelled = registrationLifecycle.signal.aborted;
1291
+ const cancellationReason = registrationLifecycle.signal.reason;
1292
+ await stop();
1293
+ if (wasCancelled) {
1294
+ throw cancellationReason;
1295
+ }
1296
+ if (cause instanceof SageSdkError)
1297
+ throw cause;
1298
+ throw new ProviderError('The configured WebSocket provider could not register the requested account subscription. Check the provider connection and retry.', { accountType: definition.type, address });
1299
+ }
1300
+ processReconnect(false);
1301
+ await waitForCaller(registrationDeliveryStarted, registrationLifecycle.signal);
1302
+ return Object.freeze({ unsubscribe: stop });
1303
+ },
1304
+ async readRaw(address, options) {
1305
+ assertActive();
1306
+ throwIfAborted(options?.signal);
1307
+ const account = await waitForCaller(sharedRawRead(address, requestedCommitment(options)), options?.signal);
1308
+ return account === undefined ? undefined : copyRawAccount(account);
1309
+ },
1310
+ });
1311
+ }
1312
+ /** Creates an isolated context synchronously without performing network I/O.
1313
+ *
1314
+ * @example
1315
+ * ```ts
1316
+ * declare const rpc: SageRpc;
1317
+ * const ctx = createSageContext({ cluster: 'zink-ptr', rpc });
1318
+ * ```
1319
+ */
1320
+ export function createSageContext(options) {
1321
+ if (options.cluster !== 'zink-ptr' && options.game === undefined) {
1322
+ throw new MissingGameContextError();
1323
+ }
1324
+ const game = options.game ?? ZINK_PTR_GAME_ADDRESS;
1325
+ const defaultMaxAgeMs = configuredMaxAgeMs(options.defaultMaxAgeMs);
1326
+ const maxAccountDataBytes = configuredLimit('maxAccountDataBytes', options.maxAccountDataBytes, DEFAULT_MAX_ACCOUNT_DATA_BYTES);
1327
+ const maxCacheEntries = configuredLimit('maxCacheEntries', options.maxCacheEntries, DEFAULT_MAX_CACHE_ENTRIES);
1328
+ const maxDiscoveryResults = configuredLimit('maxDiscoveryResults', options.maxDiscoveryResults, DEFAULT_MAX_DISCOVERY_RESULTS);
1329
+ const maxReadManyAccounts = configuredLimit('maxReadManyAccounts', options.maxReadManyAccounts, DEFAULT_MAX_READ_MANY_ACCOUNTS);
1330
+ let disposed = false;
1331
+ const lifecycle = new AbortController();
1332
+ const walletProfileDiscoveries = new Map();
1333
+ lifecycle.signal.addEventListener('abort', () => walletProfileDiscoveries.clear(), { once: true });
1334
+ const subscriptionCompletions = new Set();
1335
+ const trackSubscription = (completion) => {
1336
+ subscriptionCompletions.add(completion);
1337
+ void completion.finally(() => subscriptionCompletions.delete(completion));
1338
+ };
1339
+ const provider = options.provider ??
1340
+ createZinkProvider(options.rpc, clusterName(options.cluster), {
1341
+ maxAccountDataBytes,
1342
+ maxDiscoveryResults,
1343
+ });
1344
+ const data = createDataPort(options.cluster, provider, options.discovery?.indexer, options.subscriptions, options.commitment ?? DEFAULT_COMMITMENT, defaultMaxAgeMs, () => disposed, lifecycle, maxAccountDataBytes, maxCacheEntries, maxDiscoveryResults, maxReadManyAccounts, trackSubscription);
1345
+ const context = {
1346
+ cluster: options.cluster,
1347
+ data,
1348
+ game,
1349
+ ...(options.registrySnapshotStore === undefined
1350
+ ? {}
1351
+ : { registrySnapshotStore: options.registrySnapshotStore }),
1352
+ ...(options.writeRpc === undefined ? {} : { writeRpc: options.writeRpc }),
1353
+ async dispose() {
1354
+ if (!disposed) {
1355
+ disposed = true;
1356
+ markContextDisposed(context);
1357
+ lifecycle.abort(new ContextDisposedError());
1358
+ await Promise.all([...subscriptionCompletions]);
1359
+ }
1360
+ },
1361
+ };
1362
+ CONTEXT_DISCOVERY_RUNTIME.set(context, {
1363
+ defaultCommitment: options.commitment ?? DEFAULT_COMMITMENT,
1364
+ isDisposed: () => disposed,
1365
+ lifecycle,
1366
+ maxDiscoveryResults,
1367
+ walletProfileDiscoveries,
1368
+ ...(options.discovery?.walletProfiles === undefined
1369
+ ? {}
1370
+ : { walletProfiles: options.discovery.walletProfiles }),
1371
+ });
1372
+ return Object.freeze(context);
1373
+ }
1374
+ //# sourceMappingURL=context.js.map