@aephia/atlas-kit 0.6.0-next.165 → 0.6.0-next.167

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.
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/client/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAKV,OAAO,EAEP,UAAU,EAKV,kBAAkB,EAElB,WAAW,EACX,kBAAkB,EAMlB,8BAA8B,EAC/B,MAAM,gBAAgB,CAAC;AA6QxB,UAAU,4BAA4B;IACpC,QAAQ,CAAC,SAAS,EAAE,SAAS,OAAO,EAAE,CAAC;IACvC,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,8BAA8B,CAAC,UAAU,CAAC,CAAC;CAC7D;AAED,+EAA+E;AAC/E,wBAAsB,+BAA+B,CACnD,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,OAAO,EACf,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,4BAA4B,CAAC,CA6FvC;AAED,gFAAgF;AAChF,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,WAAW,EACpB,SAAS,CAAC,EAAE,UAAU,GACrB,UAAU,CAMZ;AAioDD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,WAAW,CAiG1E"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/client/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAKV,OAAO,EAEP,UAAU,EAMV,kBAAkB,EAElB,WAAW,EACX,kBAAkB,EAMlB,8BAA8B,EAC/B,MAAM,gBAAgB,CAAC;AA6SxB,UAAU,4BAA4B;IACpC,QAAQ,CAAC,SAAS,EAAE,SAAS,OAAO,EAAE,CAAC;IACvC,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,8BAA8B,CAAC,UAAU,CAAC,CAAC;CAC7D;AAED,+EAA+E;AAC/E,wBAAsB,+BAA+B,CACnD,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,OAAO,EACf,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,4BAA4B,CAAC,CA6FvC;AAED,gFAAgF;AAChF,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,WAAW,EACpB,SAAS,CAAC,EAAE,UAAU,GACrB,UAAU,CAMZ;AAm/DD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,WAAW,CAiG1E"}
@@ -89,6 +89,19 @@ function validateDiscoveryFilters(filters) {
89
89
  }
90
90
  }
91
91
  }
92
+ function assertDiscriminatorFilter(definition, filters) {
93
+ const discriminator = [...definition.discriminator];
94
+ const present = filters.some((filter) => filter.offset === 0 &&
95
+ filter.bytes.length >= discriminator.length &&
96
+ discriminator.every((byte, index) => filter.bytes[index] === byte));
97
+ if (!present) {
98
+ throw new InvalidDerivationInputError(`The ${definition.type} discovery subscription filter set`, `${filters.length} filter(s) without the account discriminator at offset 0`, 'Add the account discriminator filter at offset 0 so the program subscription streams only this account type.');
99
+ }
100
+ }
101
+ function matchesFilters(data, filters) {
102
+ return filters.every((filter) => filter.offset + filter.bytes.length <= data.length &&
103
+ filter.bytes.every((byte, index) => data[filter.offset + index] === byte));
104
+ }
92
105
  function copyReadMetaFilters(filters) {
93
106
  return Object.freeze(filters.map((filter) => Object.freeze({
94
107
  bytes: Object.freeze([...filter.bytes]),
@@ -286,6 +299,7 @@ function createDataPort(cluster, provider, indexer, subscriptionProvider, defaul
286
299
  let invalidationSequence = 0;
287
300
  let reconciliationGeneration = 0;
288
301
  let nextRawReadSequence = 0;
302
+ let nextDiscoverySequence = 0;
289
303
  let nextDefinitionId = 0;
290
304
  lifecycle.signal.addEventListener('abort', () => {
291
305
  cache.clear();
@@ -557,10 +571,12 @@ function createDataPort(cluster, provider, indexer, subscriptionProvider, defaul
557
571
  }
558
572
  })();
559
573
  }
560
- function sharedDiscovery(programAddress, filters, commitment, discoveryInvalidationGeneration, addressReconciliationGeneration) {
574
+ function sharedDiscovery(programAddress, filters, commitment, discoveryInvalidationGeneration, addressReconciliationGeneration, minimumSequence = 0) {
561
575
  const registryKey = discoveryReadKey(programAddress, filters, commitment, discoveryInvalidationGeneration, addressReconciliationGeneration);
562
576
  const existing = discoveryReads.get(registryKey);
563
- if (existing !== undefined) {
577
+ // A stream closing a subscription gap cannot join a discovery that began
578
+ // before its registration or reconnect.
579
+ if (existing !== undefined && existing.sequence >= minimumSequence) {
564
580
  return existing;
565
581
  }
566
582
  let resolveDiscovery;
@@ -571,6 +587,7 @@ function createDataPort(cluster, provider, indexer, subscriptionProvider, defaul
571
587
  });
572
588
  const read = {
573
589
  promise,
590
+ sequence: nextDiscoverySequence++,
574
591
  };
575
592
  discoveryReads.set(registryKey, read);
576
593
  const operation = (async () => {
@@ -790,6 +807,43 @@ function createDataPort(cluster, provider, indexer, subscriptionProvider, defaul
790
807
  void promise.then(retainSettledResult, retainSettledResult);
791
808
  return promise;
792
809
  }
810
+ async function targetedDiscovery(definition, providerFilters, commitment, store, operationInvalidationSequence, signal, minimumSequence = 0) {
811
+ let accounts;
812
+ try {
813
+ const discoveryRead = sharedDiscovery(definition.programAddress, providerFilters, commitment, discoveryInvalidatedAt.get(definition.programAddress) ?? 0, reconciliationGeneration, minimumSequence);
814
+ accounts = await waitForCaller(discoveryRead.promise, signal);
815
+ }
816
+ catch (cause) {
817
+ if (signal?.aborted === true) {
818
+ throw abortReason(signal);
819
+ }
820
+ if (isDisposed()) {
821
+ throw new ContextDisposedError();
822
+ }
823
+ if (cause instanceof SageSdkError) {
824
+ throw cause;
825
+ }
826
+ 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 });
827
+ }
828
+ assertActive();
829
+ const snapshotsByAddress = new Map();
830
+ for (const account of accounts) {
831
+ assertProviderCommitment(account, commitment);
832
+ const snapshot = validateAndTimestamp(definition, copyRawAccount(account), provider.identity);
833
+ const existing = snapshotsByAddress.get(snapshot.address);
834
+ if (existing === undefined || isPreferredSnapshot(snapshot, existing)) {
835
+ snapshotsByAddress.set(snapshot.address, snapshot);
836
+ }
837
+ }
838
+ const snapshots = [...snapshotsByAddress.values()];
839
+ if (store) {
840
+ assertCacheCapacity(snapshots.map((snapshot) => keyFor(definition, snapshot.address)));
841
+ for (const snapshot of snapshots) {
842
+ storeSnapshot(keyFor(definition, snapshot.address), snapshot, operationInvalidationSequence);
843
+ }
844
+ }
845
+ return snapshots;
846
+ }
793
847
  async function readOptional(definition, address, options) {
794
848
  assertActive();
795
849
  throwIfAborted(options?.signal);
@@ -950,40 +1004,7 @@ function createDataPort(cluster, provider, indexer, subscriptionProvider, defaul
950
1004
  strategy: 'indexer',
951
1005
  }));
952
1006
  }
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
- }
1007
+ const snapshots = await targetedDiscovery(definition, providerFilters, commitment, request.policy !== 'no-store', operationInvalidationSequence, request.signal);
987
1008
  const slot = snapshots.reduce((earliest, snapshot) => earliest === undefined || snapshot.slot < earliest
988
1009
  ? snapshot.slot
989
1010
  : earliest, undefined);
@@ -1014,6 +1035,9 @@ function createDataPort(cluster, provider, indexer, subscriptionProvider, defaul
1014
1035
  rejectRegistration = reject;
1015
1036
  });
1016
1037
  let lastDelivered;
1038
+ // The snapshot onSnapshot is processing, so a slow callback cannot let
1039
+ // an older slot follow it; a rejected one can still be retried.
1040
+ let inFlight;
1017
1041
  let stopPromise;
1018
1042
  let resolveCompletion;
1019
1043
  const completion = new Promise((resolve) => {
@@ -1078,6 +1102,7 @@ function createDataPort(cluster, provider, indexer, subscriptionProvider, defaul
1078
1102
  return;
1079
1103
  pendingSnapshot = undefined;
1080
1104
  coalescedSnapshots = 0;
1105
+ inFlight = snapshot;
1081
1106
  try {
1082
1107
  const notification = observer.onSnapshot(snapshot);
1083
1108
  resolveRegistrationDeliveryStarted();
@@ -1089,6 +1114,9 @@ function createDataPort(cluster, provider, indexer, subscriptionProvider, defaul
1089
1114
  const error = normalizeSubscriptionError(cause, observerErrorMessage);
1090
1115
  pendingErrors.set(error.code, error);
1091
1116
  }
1117
+ finally {
1118
+ inFlight = undefined;
1119
+ }
1092
1120
  }
1093
1121
  }
1094
1122
  finally {
@@ -1114,7 +1142,7 @@ function createDataPort(cluster, provider, indexer, subscriptionProvider, defaul
1114
1142
  void runNotifications();
1115
1143
  };
1116
1144
  const queueSnapshotCandidate = (selected, awaitReconnect = false) => {
1117
- const deliveryBaseline = pendingSnapshot ?? lastDelivered;
1145
+ const deliveryBaseline = pendingSnapshot ?? inFlight ?? lastDelivered;
1118
1146
  if (deliveryBaseline !== undefined &&
1119
1147
  !isPreferredSnapshot(selected, deliveryBaseline)) {
1120
1148
  return;
@@ -1301,6 +1329,294 @@ function createDataPort(cluster, provider, indexer, subscriptionProvider, defaul
1301
1329
  await waitForCaller(registrationDeliveryStarted, registrationLifecycle.signal);
1302
1330
  return Object.freeze({ unsubscribe: stop });
1303
1331
  },
1332
+ async subscribeDiscovery(definition, request, observer) {
1333
+ assertActive();
1334
+ throwIfAborted(request.signal);
1335
+ const programProvider = subscriptionProvider;
1336
+ if (programProvider?.subscribeProgram === undefined) {
1337
+ throw new ProviderError('This SAGE context has no program subscription provider. Configure a WebSocket subscription provider that implements subscribeProgram, such as createRpcSubscriptionProvider over a Kit transport with programNotifications, before streaming account changes.', { accountType: definition.type });
1338
+ }
1339
+ validateDiscoveryFilters(request.filters);
1340
+ assertDiscriminatorFilter(definition, request.filters);
1341
+ const filters = copyProviderDiscoveryFilters(request.filters);
1342
+ const commitment = requestedCommitment(request);
1343
+ const registrationLifecycle = new AbortController();
1344
+ const { signal } = registrationLifecycle;
1345
+ let registration;
1346
+ let registrationAttempt;
1347
+ let stopPromise;
1348
+ let resolveCompletion;
1349
+ const completion = new Promise((resolve) => {
1350
+ resolveCompletion = resolve;
1351
+ });
1352
+ trackSubscription(completion);
1353
+ const streamErrorMessage = 'The account stream could not process a live z.ink update. Check the WebSocket provider and retry the subscription.';
1354
+ const observerErrorMessage = 'The account stream onSnapshot callback could not process a validated snapshot. Fix the consumer callback before retrying delivery.';
1355
+ // Every map is bounded by the addresses matching the filters, which is
1356
+ // capped at maxDiscoveryResults; transient errors are bounded by code.
1357
+ // The discovery round in which each address was last seen; a reconnect
1358
+ // reports only addresses not seen since its discovery started.
1359
+ const seenInRound = new Map();
1360
+ let discoveryRound = 0;
1361
+ const lastDelivered = new Map();
1362
+ // The snapshot onSnapshot is processing, so a slow callback cannot let
1363
+ // an older slot follow it; a rejected one can still be retried.
1364
+ let inFlight;
1365
+ const pending = new Map();
1366
+ // Removals stay keyed by address: each one is reported exactly once.
1367
+ const pendingRemovals = new Map();
1368
+ const coalesced = new Map();
1369
+ const pendingErrors = new Map();
1370
+ const coalescedErrors = new Map();
1371
+ let notificationRunning = false;
1372
+ let discovering = false;
1373
+ let rediscoveryPending = false;
1374
+ let pendingDiscoverySequence = 0;
1375
+ const emitDiagnostic = (event) => {
1376
+ try {
1377
+ observer.onDiagnostic?.(event);
1378
+ }
1379
+ catch {
1380
+ // Diagnostics never interrupt delivery or transport cleanup.
1381
+ }
1382
+ };
1383
+ const normalizeError = (cause, message) => cause instanceof SageSdkError
1384
+ ? cause
1385
+ : new ProviderError(message, {
1386
+ accountType: definition.type,
1387
+ cause,
1388
+ });
1389
+ const runNotifications = async () => {
1390
+ if (notificationRunning)
1391
+ return;
1392
+ notificationRunning = true;
1393
+ try {
1394
+ while (!signal.aborted && !isDisposed()) {
1395
+ const errorEntry = pendingErrors.entries().next().value;
1396
+ if (errorEntry !== undefined) {
1397
+ pendingErrors.delete(errorEntry[0]);
1398
+ coalescedErrors.delete(errorEntry[0]);
1399
+ try {
1400
+ await observer.onError(errorEntry[1]);
1401
+ }
1402
+ catch {
1403
+ // Consumer observer failures never terminate transport.
1404
+ }
1405
+ continue;
1406
+ }
1407
+ const removal = pendingRemovals.entries().next().value;
1408
+ if (removal !== undefined) {
1409
+ pendingRemovals.delete(removal[0]);
1410
+ try {
1411
+ await observer.onError(removal[1]);
1412
+ }
1413
+ catch {
1414
+ // Consumer observer failures never terminate transport.
1415
+ }
1416
+ continue;
1417
+ }
1418
+ const next = pending.entries().next().value;
1419
+ if (next === undefined)
1420
+ return;
1421
+ pending.delete(next[0]);
1422
+ coalesced.delete(next[0]);
1423
+ inFlight = next[1];
1424
+ try {
1425
+ await observer.onSnapshot(next[1]);
1426
+ // A reconnect may have reported the account missing meanwhile.
1427
+ if (seenInRound.has(next[0])) {
1428
+ lastDelivered.set(next[0], next[1]);
1429
+ }
1430
+ }
1431
+ catch (cause) {
1432
+ const error = normalizeError(cause, observerErrorMessage);
1433
+ pendingErrors.set(error.code, error);
1434
+ }
1435
+ finally {
1436
+ inFlight = undefined;
1437
+ }
1438
+ }
1439
+ }
1440
+ finally {
1441
+ notificationRunning = false;
1442
+ }
1443
+ };
1444
+ const reportError = (cause, message) => {
1445
+ if (signal.aborted)
1446
+ return;
1447
+ const error = normalizeError(cause, message);
1448
+ if (pendingErrors.has(error.code)) {
1449
+ const count = (coalescedErrors.get(error.code) ?? 0) + 1;
1450
+ coalescedErrors.set(error.code, count);
1451
+ emitDiagnostic({
1452
+ accountType: definition.type,
1453
+ address: error.address ?? definition.programAddress,
1454
+ coalescedCount: count,
1455
+ errorCode: error.code,
1456
+ kind: 'subscription-error-coalesced',
1457
+ });
1458
+ }
1459
+ pendingErrors.set(error.code, error);
1460
+ void runNotifications();
1461
+ };
1462
+ const queueSnapshot = (candidate) => {
1463
+ const address = candidate.address;
1464
+ const selected = cachedSnapshot(keyFor(definition, address), commitment) ??
1465
+ candidate;
1466
+ const baseline = pending.get(address) ??
1467
+ (inFlight?.address === address ? inFlight : undefined) ??
1468
+ lastDelivered.get(address);
1469
+ if (baseline !== undefined &&
1470
+ !isPreferredSnapshot(selected, baseline)) {
1471
+ return;
1472
+ }
1473
+ if (pending.has(address)) {
1474
+ const count = (coalesced.get(address) ?? 0) + 1;
1475
+ coalesced.set(address, count);
1476
+ emitDiagnostic({
1477
+ accountType: definition.type,
1478
+ address,
1479
+ coalescedCount: count,
1480
+ kind: 'subscription-snapshot-coalesced',
1481
+ });
1482
+ }
1483
+ pending.set(address, selected);
1484
+ void runNotifications();
1485
+ };
1486
+ const track = (address, round) => {
1487
+ if (!seenInRound.has(address)) {
1488
+ assertWithinLimit('streamed accounts', seenInRound.size + 1, maxDiscoveryResults);
1489
+ }
1490
+ seenInRound.set(address, round);
1491
+ // A validated sighting supersedes a removal not yet reported.
1492
+ pendingRemovals.delete(address);
1493
+ };
1494
+ const rediscover = () => {
1495
+ pendingDiscoverySequence = nextDiscoverySequence;
1496
+ if (discovering) {
1497
+ rediscoveryPending = true;
1498
+ return;
1499
+ }
1500
+ discovering = true;
1501
+ void (async () => {
1502
+ try {
1503
+ do {
1504
+ rediscoveryPending = false;
1505
+ const minimumSequence = pendingDiscoverySequence;
1506
+ const round = ++discoveryRound;
1507
+ try {
1508
+ const snapshots = await targetedDiscovery(definition, filters, commitment, true, invalidationSequence, signal, minimumSequence);
1509
+ for (const snapshot of snapshots) {
1510
+ track(snapshot.address, round);
1511
+ queueSnapshot(snapshot);
1512
+ }
1513
+ for (const [address, seen] of [...seenInRound]) {
1514
+ if (seen >= round)
1515
+ continue;
1516
+ seenInRound.delete(address);
1517
+ lastDelivered.delete(address);
1518
+ pending.delete(address);
1519
+ coalesced.delete(address);
1520
+ pendingRemovals.set(address, new AccountNotFoundError(definition.type, address));
1521
+ void runNotifications();
1522
+ }
1523
+ }
1524
+ catch (cause) {
1525
+ reportError(cause, streamErrorMessage);
1526
+ }
1527
+ } while (rediscoveryPending && !signal.aborted && !isDisposed());
1528
+ }
1529
+ finally {
1530
+ discovering = false;
1531
+ }
1532
+ })();
1533
+ };
1534
+ const enqueue = (event) => {
1535
+ if (signal.aborted || isDisposed())
1536
+ return;
1537
+ if (event.kind === 'reconnected') {
1538
+ rediscover();
1539
+ return;
1540
+ }
1541
+ try {
1542
+ assertAccountSize(event.account);
1543
+ const account = copyRawAccount(event.account);
1544
+ assertProviderCommitment(account, commitment);
1545
+ if (!matchesFilters(account.data, filters)) {
1546
+ throw new ProviderError(`The program subscription returned ${account.address}, which does not match the requested filters. Fix the WebSocket provider's program-subscription filters before retrying.`, { accountType: definition.type, address: account.address });
1547
+ }
1548
+ const snapshot = validateAndTimestamp(definition, account, programProvider.identity);
1549
+ track(snapshot.address, discoveryRound);
1550
+ storeSubscriptionSnapshot(keyFor(definition, snapshot.address), snapshot);
1551
+ queueSnapshot(snapshot);
1552
+ }
1553
+ catch (cause) {
1554
+ reportError(cause, streamErrorMessage);
1555
+ }
1556
+ };
1557
+ const abortRegistration = () => registrationLifecycle.abort(request.signal?.aborted === true
1558
+ ? request.signal.reason
1559
+ : lifecycle.signal.reason);
1560
+ request.signal?.addEventListener('abort', abortRegistration, {
1561
+ once: true,
1562
+ });
1563
+ lifecycle.signal.addEventListener('abort', abortRegistration, {
1564
+ once: true,
1565
+ });
1566
+ const stop = () => {
1567
+ if (stopPromise !== undefined)
1568
+ return stopPromise;
1569
+ let resolveStop;
1570
+ stopPromise = new Promise((resolve) => {
1571
+ resolveStop = resolve;
1572
+ });
1573
+ registrationLifecycle.abort();
1574
+ request.signal?.removeEventListener('abort', abortRegistration);
1575
+ lifecycle.signal.removeEventListener('abort', abortRegistration);
1576
+ void (async () => {
1577
+ try {
1578
+ if (registration !== undefined) {
1579
+ await registration.unsubscribe();
1580
+ }
1581
+ else {
1582
+ // A late registration is released in the background.
1583
+ void registrationAttempt?.then((late) => late.unsubscribe(), () => undefined);
1584
+ }
1585
+ }
1586
+ catch {
1587
+ // Disposal remains best-effort when a transport is already gone.
1588
+ }
1589
+ finally {
1590
+ resolveCompletion();
1591
+ resolveStop();
1592
+ }
1593
+ })();
1594
+ return stopPromise;
1595
+ };
1596
+ signal.addEventListener('abort', () => void stop(), { once: true });
1597
+ try {
1598
+ registrationAttempt = Promise.resolve().then(() => programProvider.subscribeProgram({
1599
+ commitment,
1600
+ filters,
1601
+ programAddress: definition.programAddress,
1602
+ signal,
1603
+ }, (event) => void enqueue(event)));
1604
+ void registrationAttempt.catch(() => undefined);
1605
+ registration = await waitForCaller(registrationAttempt, signal);
1606
+ }
1607
+ catch (cause) {
1608
+ const wasCancelled = signal.aborted;
1609
+ const cancellationReason = signal.reason;
1610
+ await stop();
1611
+ if (wasCancelled)
1612
+ throw cancellationReason;
1613
+ if (cause instanceof SageSdkError)
1614
+ throw cause;
1615
+ throw new ProviderError('The configured WebSocket provider could not register the requested program subscription. Check the provider connection and retry.', { accountType: definition.type });
1616
+ }
1617
+ rediscover();
1618
+ return Object.freeze({ unsubscribe: stop });
1619
+ },
1304
1620
  async readRaw(address, options) {
1305
1621
  assertActive();
1306
1622
  throwIfAborted(options?.signal);