@formo/analytics 1.38.2 → 1.40.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 (74) hide show
  1. package/dist/cjs/src/FormoAnalytics.d.ts +4 -1
  2. package/dist/cjs/src/FormoAnalytics.js +56 -36
  3. package/dist/cjs/src/FormoAnalyticsProvider.js +20 -0
  4. package/dist/cjs/src/event/EventFactory.d.ts +9 -1
  5. package/dist/cjs/src/event/EventFactory.js +31 -16
  6. package/dist/cjs/src/event/EventManager.d.ts +3 -1
  7. package/dist/cjs/src/event/EventManager.js +33 -4
  8. package/dist/cjs/src/event/cancellation.d.ts +4 -0
  9. package/dist/cjs/src/event/cancellation.js +7 -0
  10. package/dist/cjs/src/event/type.d.ts +1 -0
  11. package/dist/cjs/src/event/utils.d.ts +5 -1
  12. package/dist/cjs/src/event/utils.js +57 -2
  13. package/dist/cjs/src/evm/EvmEventTracker.d.ts +7 -0
  14. package/dist/cjs/src/evm/EvmEventTracker.js +31 -5
  15. package/dist/cjs/src/queue/EventQueue.d.ts +1 -0
  16. package/dist/cjs/src/queue/EventQueue.js +11 -6
  17. package/dist/cjs/src/solana/SolanaManager.d.ts +37 -9
  18. package/dist/cjs/src/solana/SolanaManager.js +135 -20
  19. package/dist/cjs/src/solana/SolanaStoreHandler.d.ts +6 -0
  20. package/dist/cjs/src/solana/SolanaStoreHandler.js +17 -8
  21. package/dist/cjs/src/solana/SolanaWalletStandardRegistry.d.ts +163 -0
  22. package/dist/cjs/src/solana/SolanaWalletStandardRegistry.js +447 -0
  23. package/dist/cjs/src/solana/index.d.ts +10 -5
  24. package/dist/cjs/src/solana/index.js +12 -6
  25. package/dist/cjs/src/solana/storeTypes.d.ts +20 -1
  26. package/dist/cjs/src/solana/types.d.ts +32 -9
  27. package/dist/cjs/src/solana/types.js +15 -0
  28. package/dist/cjs/src/solana/walletStandardTypes.d.ts +54 -0
  29. package/dist/cjs/src/solana/walletStandardTypes.js +21 -0
  30. package/dist/cjs/src/storage/StorageManager.d.ts +2 -0
  31. package/dist/cjs/src/storage/StorageManager.js +6 -0
  32. package/dist/cjs/src/storage/index.d.ts +1 -0
  33. package/dist/cjs/src/storage/index.js +7 -1
  34. package/dist/cjs/src/types/base.d.ts +15 -5
  35. package/dist/cjs/src/version.d.ts +1 -1
  36. package/dist/cjs/src/version.js +1 -1
  37. package/dist/esm/src/FormoAnalytics.d.ts +4 -1
  38. package/dist/esm/src/FormoAnalytics.js +54 -34
  39. package/dist/esm/src/FormoAnalyticsProvider.js +20 -0
  40. package/dist/esm/src/event/EventFactory.d.ts +9 -1
  41. package/dist/esm/src/event/EventFactory.js +31 -16
  42. package/dist/esm/src/event/EventManager.d.ts +3 -1
  43. package/dist/esm/src/event/EventManager.js +33 -4
  44. package/dist/esm/src/event/cancellation.d.ts +4 -0
  45. package/dist/esm/src/event/cancellation.js +4 -0
  46. package/dist/esm/src/event/type.d.ts +1 -0
  47. package/dist/esm/src/event/utils.d.ts +5 -1
  48. package/dist/esm/src/event/utils.js +56 -3
  49. package/dist/esm/src/evm/EvmEventTracker.d.ts +7 -0
  50. package/dist/esm/src/evm/EvmEventTracker.js +31 -5
  51. package/dist/esm/src/queue/EventQueue.d.ts +1 -0
  52. package/dist/esm/src/queue/EventQueue.js +11 -6
  53. package/dist/esm/src/solana/SolanaManager.d.ts +37 -9
  54. package/dist/esm/src/solana/SolanaManager.js +135 -20
  55. package/dist/esm/src/solana/SolanaStoreHandler.d.ts +6 -0
  56. package/dist/esm/src/solana/SolanaStoreHandler.js +18 -9
  57. package/dist/esm/src/solana/SolanaWalletStandardRegistry.d.ts +163 -0
  58. package/dist/esm/src/solana/SolanaWalletStandardRegistry.js +444 -0
  59. package/dist/esm/src/solana/index.d.ts +10 -5
  60. package/dist/esm/src/solana/index.js +10 -5
  61. package/dist/esm/src/solana/storeTypes.d.ts +20 -1
  62. package/dist/esm/src/solana/types.d.ts +32 -9
  63. package/dist/esm/src/solana/types.js +14 -0
  64. package/dist/esm/src/solana/walletStandardTypes.d.ts +54 -0
  65. package/dist/esm/src/solana/walletStandardTypes.js +18 -0
  66. package/dist/esm/src/storage/StorageManager.d.ts +2 -0
  67. package/dist/esm/src/storage/StorageManager.js +6 -0
  68. package/dist/esm/src/storage/index.d.ts +1 -0
  69. package/dist/esm/src/storage/index.js +5 -0
  70. package/dist/esm/src/types/base.d.ts +15 -5
  71. package/dist/esm/src/version.d.ts +1 -1
  72. package/dist/esm/src/version.js +1 -1
  73. package/dist/index.umd.min.js +1 -1
  74. package/package.json +2 -2
@@ -1,32 +1,124 @@
1
1
  /**
2
2
  * SolanaManager
3
3
  *
4
- * Manages the lifecycle of the Solana store integration.
5
- * Subscribes to framework-kit's zustand store for automatic event capture
6
- * of wallet connect/disconnect and transaction lifecycle events.
4
+ * Owns the two ways the SDK learns about Solana wallets:
7
5
  *
8
- * For signMessage/signTransaction tracking (not captured by the store),
6
+ * 1. `SolanaWalletStandardRegistry`: discovers wallets through the Wallet
7
+ * Standard and reports detect / connect / disconnect. On by default, so
8
+ * compatible wallets registered by Solana Kit, wallet-adapter,
9
+ * framework-kit, or another host are covered with no configuration,
10
+ * exactly like EVM wallets through EIP-6963. `solana: false` turns it off.
11
+ * 2. `SolanaStoreHandler`: subscribes to framework-kit's zustand store for
12
+ * connect / disconnect / cluster changes AND the transaction lifecycle.
13
+ * Opt-in through `solana: { store }` or `formo.solana.setStore()`.
14
+ *
15
+ * Both observe the same Wallet Standard connection when a framework-kit app
16
+ * connects. A store supplied at initialization owns wallet events; a store
17
+ * attached later takes ownership when it observes its first connection and
18
+ * adopts any connect the registry already reported. One connect per
19
+ * connection, whichever path an app is on.
20
+ *
21
+ * For signMessage/signTransaction tracking (not captured by either path),
9
22
  * use formo.signature() directly with the address and chainId.
10
23
  *
11
- * For manual event tracking without the store, use the core API directly:
24
+ * For manual event tracking, use the core API directly:
12
25
  * formo.transaction(), formo.signature(), formo.connect(), formo.disconnect().
13
26
  */
14
27
  import { logger } from "../logger";
15
28
  import { SolanaStoreHandler } from "./SolanaStoreHandler";
29
+ import { SolanaWalletStandardRegistry } from "./SolanaWalletStandardRegistry";
30
+ import { SOLANA_CLUSTERS_BY_ID, } from "./types";
16
31
  var SolanaManager = /** @class */ (function () {
17
- function SolanaManager(formo, options) {
32
+ /**
33
+ * @param formo - The SDK instance events are reported to.
34
+ * @param options - `options.solana` as passed to the SDK, if an object.
35
+ * @param enabled - Whether Solana tracking is enabled. False only when the
36
+ * host app passed `solana: false`; both discovery and stores then stay off.
37
+ */
38
+ function SolanaManager(formo, options, enabled) {
39
+ if (enabled === void 0) { enabled = true; }
40
+ var _this = this;
18
41
  this.formo = formo;
19
- if (options === null || options === void 0 ? void 0 : options.store) {
20
- logger.info("SolanaManager: Initializing store-based Solana tracking");
21
- this.storeHandler = new SolanaStoreHandler(formo, options.store, {
22
- cluster: options.cluster,
23
- });
24
- }
25
- else if (options === null || options === void 0 ? void 0 : options.cluster) {
42
+ this.enabled = enabled;
43
+ this.storeOwnsWalletEvents = false;
44
+ if (!enabled)
45
+ return;
46
+ if (options === null || options === void 0 ? void 0 : options.cluster) {
26
47
  // Store pending cluster for when setStore is called later
27
48
  this.pendingCluster = options.cluster;
28
49
  }
50
+ // A store supplied at initialization owns wallet events from the outset:
51
+ // unlike a store attached later, it has not missed any prior registry
52
+ // state and it knows the cluster more precisely.
53
+ this.storeOwnsWalletEvents = !!(options === null || options === void 0 ? void 0 : options.store);
54
+ this.registry = new SolanaWalletStandardRegistry({
55
+ isAutocaptureEnabled: function (t) { return _this.formo.isAutocaptureEnabled(t); },
56
+ willTrackEvent: function (chainId) { return _this.formo.willTrackEvent(chainId); },
57
+ detect: function (params) { return _this.formo.detect(params); },
58
+ connect: function (params, properties) {
59
+ return _this.formo.connect(params, properties);
60
+ },
61
+ disconnect: function (params) { return _this.formo.disconnect(params); },
62
+ chain: function (params) { return _this.formo.chain(params); },
63
+ syncWalletState: function (params) { return _this.formo.syncWalletState(params); },
64
+ currentAddress: function () { return _this.formo.currentAddress; },
65
+ ownsWalletEvents: function () { return !_this.storeOwnsWalletEvents; },
66
+ }, { cluster: options === null || options === void 0 ? void 0 : options.cluster });
67
+ if (options === null || options === void 0 ? void 0 : options.store) {
68
+ logger.info("SolanaManager: Initializing store-based Solana tracking");
69
+ this.attachStore(options.store, options.cluster);
70
+ }
29
71
  }
72
+ SolanaManager.prototype.attachStore = function (store, cluster) {
73
+ var _this = this;
74
+ var _a;
75
+ this.storeHandler = new SolanaStoreHandler(this.formo, store, {
76
+ cluster: cluster,
77
+ beforeWalletConnect: function (connection) {
78
+ var _a, _b;
79
+ // The store's cluster is authoritative even when chain autocapture is
80
+ // disabled. Keep central attribution correct without manufacturing a
81
+ // chain event in that mode.
82
+ _this.formo.syncWalletState({
83
+ address: connection.address,
84
+ chainId: connection.chainId,
85
+ });
86
+ if (_this.storeOwnsWalletEvents)
87
+ return true;
88
+ var reported = (_a = _this.registry) === null || _a === void 0 ? void 0 : _a.takeReportedConnection(connection.address, connection.rdns);
89
+ _this.storeOwnsWalletEvents = true;
90
+ // If Wallet Standard got there first, the store adopts that live
91
+ // connection instead of emitting it again. Correct its cluster if
92
+ // the store has more precise information.
93
+ if (!reported) {
94
+ // Nothing to adopt. Either the registry never reported this
95
+ // connection, or it reported it under another identity, in which
96
+ // case the store is about to emit a second connect for the same
97
+ // live connection. Both paths derive the rdns from the wallet's
98
+ // own name, so a mismatch means the store's connector is labelled
99
+ // differently from the registered wallet.
100
+ var held = (_b = _this.registry) === null || _b === void 0 ? void 0 : _b.reportedConnectionRdns(connection.address);
101
+ if (held) {
102
+ logger.warn("SolanaManager: Store connector does not match the discovered wallet; the connection is reported twice", { storeRdns: connection.rdns, walletRdns: held });
103
+ }
104
+ return true;
105
+ }
106
+ if (reported.chainId !== connection.chainId &&
107
+ _this.formo.isAutocaptureEnabled("chain")) {
108
+ _this.formo.chain(connection).catch(function (error) {
109
+ logger.error("SolanaManager: Error correcting cluster during store handoff", error);
110
+ });
111
+ }
112
+ return false;
113
+ },
114
+ });
115
+ // Keep the registry's snapshot on the store's detected cluster. This is
116
+ // silent once the store owns events; during a late handoff it corrects a
117
+ // registry-reported connection before the store adopts it.
118
+ var detectedCluster = SOLANA_CLUSTERS_BY_ID[this.storeHandler.getChainId()];
119
+ if (detectedCluster)
120
+ (_a = this.registry) === null || _a === void 0 ? void 0 : _a.setCluster(detectedCluster);
121
+ };
30
122
  /**
31
123
  * Set the framework-kit zustand store for automatic event tracking.
32
124
  * This enables autocapture mode — connect/disconnect and transaction events
@@ -45,29 +137,52 @@ var SolanaManager = /** @class */ (function () {
45
137
  */
46
138
  SolanaManager.prototype.setStore = function (store, options) {
47
139
  var _a;
140
+ if (!this.enabled) {
141
+ logger.warn("SolanaManager: Ignoring setStore. Solana tracking is off for this instance (solana: false, or the SDK was cleaned up)");
142
+ return;
143
+ }
48
144
  (_a = this.storeHandler) === null || _a === void 0 ? void 0 : _a.cleanup();
49
- this.storeHandler = new SolanaStoreHandler(this.formo, store, {
50
- cluster: (options === null || options === void 0 ? void 0 : options.cluster) || this.pendingCluster,
51
- });
145
+ this.storeHandler = undefined;
146
+ this.storeOwnsWalletEvents = false;
147
+ this.attachStore(store, (options === null || options === void 0 ? void 0 : options.cluster) || this.pendingCluster);
52
148
  this.pendingCluster = undefined;
53
149
  };
54
150
  /**
55
- * Update the cluster/network. Only needed if the store endpoint doesn't
56
- * contain a recognizable cluster name (e.g. custom RPC URLs).
57
- * In most cases, the cluster is auto-detected from the store's endpoint.
151
+ * Update the cluster/network.
152
+ *
153
+ * With a framework-kit store, only needed if the store endpoint doesn't
154
+ * contain a recognizable cluster name (e.g. custom RPC URLs). Without one,
155
+ * this is how a non-mainnet app tells the SDK which cluster its Wallet
156
+ * Standard connections are on, since the standard itself cannot say.
58
157
  */
59
158
  SolanaManager.prototype.setCluster = function (cluster) {
159
+ var _a;
160
+ if (!this.enabled)
161
+ return;
60
162
  if (this.storeHandler) {
61
163
  this.storeHandler.setCluster(cluster);
62
164
  }
63
165
  else {
64
166
  this.pendingCluster = cluster;
65
167
  }
168
+ (_a = this.registry) === null || _a === void 0 ? void 0 : _a.setCluster(cluster);
66
169
  };
170
+ Object.defineProperty(SolanaManager.prototype, "discoveredWallets", {
171
+ /** Names of the Wallet Standard wallets discovered so far. */
172
+ get: function () {
173
+ var _a, _b;
174
+ return (_b = (_a = this.registry) === null || _a === void 0 ? void 0 : _a.walletNames) !== null && _b !== void 0 ? _b : [];
175
+ },
176
+ enumerable: false,
177
+ configurable: true
178
+ });
67
179
  SolanaManager.prototype.cleanup = function () {
68
- var _a;
180
+ var _a, _b;
69
181
  (_a = this.storeHandler) === null || _a === void 0 ? void 0 : _a.cleanup();
70
182
  this.storeHandler = undefined;
183
+ this.storeOwnsWalletEvents = false;
184
+ (_b = this.registry) === null || _b === void 0 ? void 0 : _b.cleanup();
185
+ this.registry = undefined;
71
186
  };
72
187
  return SolanaManager;
73
188
  }());
@@ -48,8 +48,14 @@ export declare class SolanaStoreHandler {
48
48
  * When true, auto-detection from the store endpoint is disabled.
49
49
  */
50
50
  private explicitCluster;
51
+ private beforeWalletConnect?;
51
52
  constructor(formoAnalytics: FormoAnalytics, store: SolanaClientStore, options?: {
52
53
  cluster?: SolanaCluster;
54
+ beforeWalletConnect?: (connection: {
55
+ address: string;
56
+ chainId: number;
57
+ rdns: string;
58
+ }) => boolean;
53
59
  });
54
60
  /**
55
61
  * Update the cluster/network.
@@ -25,7 +25,7 @@ var __assign = (this && this.__assign) || function () {
25
25
  };
26
26
  import { TransactionStatus } from "../types/events";
27
27
  import { logger } from "../logger";
28
- import { SOLANA_CHAIN_IDS } from "./types";
28
+ import { SOLANA_CHAIN_IDS, solanaWalletRdns, } from "./types";
29
29
  import { isBlockedSolanaAddress } from "./address";
30
30
  /**
31
31
  * Clean up old entries from a Set to prevent memory leaks.
@@ -66,6 +66,7 @@ var SolanaStoreHandler = /** @class */ (function () {
66
66
  this.formo = formoAnalytics;
67
67
  this.store = store;
68
68
  this.explicitCluster = !!(options === null || options === void 0 ? void 0 : options.cluster);
69
+ this.beforeWalletConnect = options === null || options === void 0 ? void 0 : options.beforeWalletConnect;
69
70
  this.cluster = (options === null || options === void 0 ? void 0 : options.cluster) || this.detectClusterFromStore(store) || "mainnet-beta";
70
71
  this.chainId = SOLANA_CHAIN_IDS[this.cluster];
71
72
  logger.info("SolanaStoreHandler: Initializing framework-kit store integration", {
@@ -138,7 +139,7 @@ var SolanaStoreHandler = /** @class */ (function () {
138
139
  logger.info("SolanaStoreHandler: Wallet subscription set up");
139
140
  };
140
141
  SolanaStoreHandler.prototype.checkInitialWalletState = function () {
141
- var _a;
142
+ var _a, _b, _c;
142
143
  var state = this.store.getState();
143
144
  var wallet = state.wallet;
144
145
  if (wallet.status === "connected") {
@@ -151,11 +152,17 @@ var SolanaStoreHandler = /** @class */ (function () {
151
152
  address: address,
152
153
  chainId: this.chainId,
153
154
  });
154
- if (this.formo.isAutocaptureEnabled("connect")) {
155
- var connectorName = ((_a = wallet.session.connector) === null || _a === void 0 ? void 0 : _a.name) || wallet.connectorId;
155
+ var connectorName = ((_a = wallet.session.connector) === null || _a === void 0 ? void 0 : _a.name) || wallet.connectorId;
156
+ var rdns = solanaWalletRdns(connectorName);
157
+ var shouldEmit = (_c = (_b = this.beforeWalletConnect) === null || _b === void 0 ? void 0 : _b.call(this, {
158
+ address: address,
159
+ chainId: this.chainId,
160
+ rdns: rdns,
161
+ })) !== null && _c !== void 0 ? _c : true;
162
+ if (shouldEmit && this.formo.isAutocaptureEnabled("connect")) {
156
163
  this.formo.connect({ chainId: this.chainId, address: address }, {
157
164
  providerName: connectorName,
158
- rdns: "sol.wallet.".concat(connectorName.toLowerCase().replace(/\s+/g, "")),
165
+ rdns: rdns,
159
166
  }).catch(function (error) {
160
167
  logger.error("SolanaStoreHandler: Error emitting initial connect", error);
161
168
  });
@@ -187,7 +194,7 @@ var SolanaStoreHandler = /** @class */ (function () {
187
194
  this.lastWalletStatus = wallet.status;
188
195
  };
189
196
  SolanaStoreHandler.prototype.handleConnect = function (wallet) {
190
- var _a;
197
+ var _a, _b, _c;
191
198
  var address = wallet.session.account.address;
192
199
  if (!address || isBlockedSolanaAddress(address)) {
193
200
  return;
@@ -203,11 +210,13 @@ var SolanaStoreHandler = /** @class */ (function () {
203
210
  chainId: chainId,
204
211
  connector: wallet.connectorId,
205
212
  });
206
- if (this.formo.isAutocaptureEnabled("connect")) {
207
- var connectorName = ((_a = wallet.session.connector) === null || _a === void 0 ? void 0 : _a.name) || wallet.connectorId;
213
+ var connectorName = ((_a = wallet.session.connector) === null || _a === void 0 ? void 0 : _a.name) || wallet.connectorId;
214
+ var rdns = solanaWalletRdns(connectorName);
215
+ var shouldEmit = (_c = (_b = this.beforeWalletConnect) === null || _b === void 0 ? void 0 : _b.call(this, { address: address, chainId: chainId, rdns: rdns })) !== null && _c !== void 0 ? _c : true;
216
+ if (shouldEmit && this.formo.isAutocaptureEnabled("connect")) {
208
217
  this.formo.connect({ chainId: chainId, address: address }, {
209
218
  providerName: connectorName,
210
- rdns: "sol.wallet.".concat(connectorName.toLowerCase().replace(/\s+/g, "")),
219
+ rdns: rdns,
211
220
  }).catch(function (error) {
212
221
  logger.error("SolanaStoreHandler: Error emitting connect", error);
213
222
  });
@@ -0,0 +1,163 @@
1
+ /**
2
+ * SolanaWalletStandardRegistry
3
+ *
4
+ * Which Solana wallets exist, and whether each is connected. The Solana
5
+ * analogue of `EvmProviderRegistry` + EIP-6963.
6
+ *
7
+ * Compatible wallets (Phantom, Solflare, Backpack, ...) announce themselves
8
+ * through the Wallet Standard's window-event handshake. Solana Kit,
9
+ * wallet-adapter, and framework-kit use these registered wallets. Observing
10
+ * the handshake covers those wallets without coupling Formo to the host
11
+ * library: the registry announces `wallet-standard:app-ready`, listens for
12
+ * `wallet-standard:register-wallet`, and subscribes to each wallet's
13
+ * `standard:events` `change` event.
14
+ *
15
+ * What it reports:
16
+ * - `detect` when a wallet registers (session-deduped by the SDK on rdns).
17
+ * - `connect` when a wallet's Solana accounts go from none to some, or the
18
+ * first account changes; `disconnect` when they go from some to none.
19
+ * - `chain` when the configured cluster changes while a wallet is connected.
20
+ *
21
+ * What it does not do: wrap any wallet method, issue any request to a
22
+ * wallet, or depend on `@wallet-standard/*` (the handshake is a few lines,
23
+ * and the SDK's dependency policy is two runtime dependencies, forever).
24
+ *
25
+ * Cluster: the Wallet Standard lists every cluster a wallet SUPPORTS, not
26
+ * the one the app is using, so the cluster is `options.solana.cluster` when
27
+ * given, else mainnet-beta when the wallet supports it, else the first
28
+ * Solana cluster it lists. A framework-kit app gets the cluster from its
29
+ * store instead, through `SolanaStoreHandler`.
30
+ *
31
+ * @see https://github.com/wallet-standard/wallet-standard
32
+ */
33
+ import type { AutocaptureEventType } from "../tracking/TrackingPolicy";
34
+ import { SolanaCluster, UnsubscribeFn } from "./types";
35
+ /** What the registry needs from the SDK that owns it. */
36
+ export interface SolanaWalletStandardRegistryDeps {
37
+ isAutocaptureEnabled(eventType: AutocaptureEventType): boolean;
38
+ willTrackEvent(chainId: number): boolean;
39
+ detect(params: {
40
+ providerName: string;
41
+ rdns: string;
42
+ }): Promise<void>;
43
+ connect(params: {
44
+ chainId: number;
45
+ address: string;
46
+ }, properties: {
47
+ providerName: string;
48
+ rdns: string;
49
+ }): Promise<void>;
50
+ disconnect(params: {
51
+ chainId: number;
52
+ address: string;
53
+ }): Promise<void>;
54
+ chain(params: {
55
+ chainId: number;
56
+ address: string;
57
+ }): Promise<void>;
58
+ /**
59
+ * Record wallet and chain state centrally WITHOUT emitting an event.
60
+ *
61
+ * Observing a chain is not the same as reporting one: the exclusion gate
62
+ * keys off the central chain, so a cluster switch has to land there even
63
+ * when `autocapture.chain` is off. The EVM tracker separates the two the
64
+ * same way.
65
+ * @see FormoAnalytics.syncWalletState
66
+ */
67
+ syncWalletState(params: {
68
+ chainId: number;
69
+ address: string;
70
+ }): void;
71
+ /** The wallet the SDK currently treats as active, across namespaces. */
72
+ currentAddress(): string | undefined;
73
+ /**
74
+ * Whether THIS registry reports connections.
75
+ *
76
+ * A framework-kit app connects through the very same Wallet Standard
77
+ * wallet, so its store and this registry both see every connection. The
78
+ * store is the better witness there (it knows the cluster and connector),
79
+ * so once it has observed or adopted a connection the registry keeps
80
+ * discovering wallets and emitting `detect`, but leaves connect and
81
+ * disconnect to the store. Exactly one connect per connection, either way.
82
+ */
83
+ ownsWalletEvents(): boolean;
84
+ }
85
+ export interface SolanaWalletStandardRegistryOptions {
86
+ /** The cluster the app uses. Overrides what is derived from the wallet. */
87
+ cluster?: SolanaCluster;
88
+ }
89
+ export declare class SolanaWalletStandardRegistry {
90
+ private readonly deps;
91
+ private wallets;
92
+ private cluster?;
93
+ private removeWindowListener?;
94
+ /** Set by cleanup(); a torn-down registry refuses late registrations. */
95
+ private isCleanedUp;
96
+ /**
97
+ * Handed to every wallet. Wallets keep it and may call `register` long
98
+ * after the handshake, which is why `register` checks `isCleanedUp`.
99
+ */
100
+ private readonly api;
101
+ constructor(deps: SolanaWalletStandardRegistryDeps, options?: SolanaWalletStandardRegistryOptions);
102
+ /**
103
+ * The Wallet Standard handshake, both directions.
104
+ *
105
+ * A wallet injected before us hears `app-ready` and registers at once; a
106
+ * wallet injected after us dispatches `register-wallet`, which we answer.
107
+ * Neither is optional: an extension's content script and the app's bundle
108
+ * race, and which one wins differs per page load.
109
+ */
110
+ private listen;
111
+ /**
112
+ * Add wallets once. Returns an unregister function, as the standard asks.
113
+ *
114
+ * Public so an integration that already holds a wallet object (its own
115
+ * `getWallets()` call, say) can hand it over without the window handshake.
116
+ */
117
+ register(...wallets: unknown[]): UnsubscribeFn;
118
+ private track;
119
+ private untrack;
120
+ private onChange;
121
+ /**
122
+ * Compare what the wallet now authorizes with what was last reported.
123
+ *
124
+ * none → some is a connect, some → none a disconnect, and a different
125
+ * first account is a disconnect followed by a connect, matching what the
126
+ * framework-kit store handler reports for the same transitions.
127
+ */
128
+ private reconcile;
129
+ private reportConnect;
130
+ private reportDisconnect;
131
+ /**
132
+ * The chain id to report for a wallet.
133
+ *
134
+ * The Wallet Standard cannot say which cluster the app is on, only which
135
+ * ones the wallet supports, so an explicit cluster wins, then mainnet-beta
136
+ * if supported (nearly every wallet lists every cluster, and production
137
+ * traffic is mainnet), then the first cluster listed.
138
+ */
139
+ private chainIdFor;
140
+ /**
141
+ * Set the cluster the app uses. A connected wallet's chain id follows,
142
+ * with a `chain` event, the same as the store handler on a cluster switch.
143
+ */
144
+ setCluster(cluster: SolanaCluster): void;
145
+ /** Names of every wallet discovered so far, for the debug helpers. */
146
+ get walletNames(): string[];
147
+ /**
148
+ * The rdns this registry reported a still-live connect for `address`
149
+ * under, if any. Lets a failed store adoption name both identities.
150
+ */
151
+ reportedConnectionRdns(address: string): string | undefined;
152
+ /**
153
+ * Transfer a connect already emitted by this registry to a store handler.
154
+ * The state remains connected, but the same transition must not be emitted
155
+ * a second time when framework-kit's store catches up.
156
+ */
157
+ takeReportedConnection(address: string, rdns: string): {
158
+ address: string;
159
+ chainId: number;
160
+ } | undefined;
161
+ cleanup(): void;
162
+ }
163
+ //# sourceMappingURL=SolanaWalletStandardRegistry.d.ts.map