@formo/analytics 1.38.2 → 1.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/src/FormoAnalytics.js +9 -4
- package/dist/cjs/src/FormoAnalyticsProvider.js +20 -0
- package/dist/cjs/src/solana/SolanaManager.d.ts +37 -9
- package/dist/cjs/src/solana/SolanaManager.js +135 -20
- package/dist/cjs/src/solana/SolanaStoreHandler.d.ts +6 -0
- package/dist/cjs/src/solana/SolanaStoreHandler.js +17 -8
- package/dist/cjs/src/solana/SolanaWalletStandardRegistry.d.ts +163 -0
- package/dist/cjs/src/solana/SolanaWalletStandardRegistry.js +447 -0
- package/dist/cjs/src/solana/index.d.ts +10 -5
- package/dist/cjs/src/solana/index.js +12 -6
- package/dist/cjs/src/solana/storeTypes.d.ts +20 -1
- package/dist/cjs/src/solana/types.d.ts +32 -9
- package/dist/cjs/src/solana/types.js +15 -0
- package/dist/cjs/src/solana/walletStandardTypes.d.ts +54 -0
- package/dist/cjs/src/solana/walletStandardTypes.js +21 -0
- package/dist/cjs/src/types/base.d.ts +15 -5
- package/dist/cjs/src/version.d.ts +1 -1
- package/dist/cjs/src/version.js +1 -1
- package/dist/esm/src/FormoAnalytics.js +9 -4
- package/dist/esm/src/FormoAnalyticsProvider.js +20 -0
- package/dist/esm/src/solana/SolanaManager.d.ts +37 -9
- package/dist/esm/src/solana/SolanaManager.js +135 -20
- package/dist/esm/src/solana/SolanaStoreHandler.d.ts +6 -0
- package/dist/esm/src/solana/SolanaStoreHandler.js +18 -9
- package/dist/esm/src/solana/SolanaWalletStandardRegistry.d.ts +163 -0
- package/dist/esm/src/solana/SolanaWalletStandardRegistry.js +444 -0
- package/dist/esm/src/solana/index.d.ts +10 -5
- package/dist/esm/src/solana/index.js +10 -5
- package/dist/esm/src/solana/storeTypes.d.ts +20 -1
- package/dist/esm/src/solana/types.d.ts +32 -9
- package/dist/esm/src/solana/types.js +14 -0
- package/dist/esm/src/solana/walletStandardTypes.d.ts +54 -0
- package/dist/esm/src/solana/walletStandardTypes.js +18 -0
- package/dist/esm/src/types/base.d.ts +15 -5
- package/dist/esm/src/version.d.ts +1 -1
- package/dist/esm/src/version.js +1 -1
- package/dist/index.umd.min.js +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The subset of the Wallet Standard this SDK reads.
|
|
3
|
+
*
|
|
4
|
+
* Duck-typed on purpose: the SDK must not depend on `@wallet-standard/*`
|
|
5
|
+
* packages (see the dependency policy), and a wallet is discovered through
|
|
6
|
+
* window events, so nothing here is ever imported from a wallet library.
|
|
7
|
+
* Every field is what a conforming wallet exposes; the shapes are looser
|
|
8
|
+
* than the reference types so a slightly off wallet is skipped, not thrown
|
|
9
|
+
* on.
|
|
10
|
+
*
|
|
11
|
+
* @see https://github.com/wallet-standard/wallet-standard
|
|
12
|
+
*/
|
|
13
|
+
/** `namespace:reference`, e.g. `solana:mainnet` or `solana:devnet`. */
|
|
14
|
+
export type WalletStandardChain = string;
|
|
15
|
+
export interface WalletStandardAccount {
|
|
16
|
+
readonly address: string;
|
|
17
|
+
readonly publicKey?: unknown;
|
|
18
|
+
/** Chains this account can sign for. Absent on a non-conforming wallet. */
|
|
19
|
+
readonly chains?: readonly WalletStandardChain[];
|
|
20
|
+
readonly features?: readonly string[];
|
|
21
|
+
readonly label?: string;
|
|
22
|
+
readonly icon?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface WalletStandardWallet {
|
|
25
|
+
readonly version?: string;
|
|
26
|
+
readonly name: string;
|
|
27
|
+
readonly icon?: string;
|
|
28
|
+
/** Every chain the wallet supports, NOT the one currently selected. */
|
|
29
|
+
readonly chains: readonly WalletStandardChain[];
|
|
30
|
+
readonly features: Readonly<Record<string, unknown>>;
|
|
31
|
+
/** Accounts the app is currently authorized for; empty until connected. */
|
|
32
|
+
readonly accounts: readonly WalletStandardAccount[];
|
|
33
|
+
}
|
|
34
|
+
/** What a `standard:events` `change` event carries: only what changed. */
|
|
35
|
+
export interface WalletStandardChangeProperties {
|
|
36
|
+
readonly chains?: readonly WalletStandardChain[];
|
|
37
|
+
readonly features?: Readonly<Record<string, unknown>>;
|
|
38
|
+
readonly accounts?: readonly WalletStandardAccount[];
|
|
39
|
+
}
|
|
40
|
+
/** The `standard:events` feature. */
|
|
41
|
+
export interface WalletStandardEventsFeature {
|
|
42
|
+
readonly version?: string;
|
|
43
|
+
on(event: "change", listener: (properties: WalletStandardChangeProperties) => void): () => void;
|
|
44
|
+
}
|
|
45
|
+
/** The API an app hands to wallets so they can announce themselves. */
|
|
46
|
+
export interface WalletStandardRegisterApi {
|
|
47
|
+
register(...wallets: WalletStandardWallet[]): () => void;
|
|
48
|
+
}
|
|
49
|
+
/** Dispatched by the app on `window`; `detail` is the register API. */
|
|
50
|
+
export declare const WALLET_STANDARD_APP_READY_EVENT = "wallet-standard:app-ready";
|
|
51
|
+
/** Dispatched by a wallet on `window`; `detail` is a callback taking the API. */
|
|
52
|
+
export declare const WALLET_STANDARD_REGISTER_WALLET_EVENT = "wallet-standard:register-wallet";
|
|
53
|
+
export declare const WALLET_STANDARD_EVENTS_FEATURE = "standard:events";
|
|
54
|
+
//# sourceMappingURL=walletStandardTypes.d.ts.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The subset of the Wallet Standard this SDK reads.
|
|
4
|
+
*
|
|
5
|
+
* Duck-typed on purpose: the SDK must not depend on `@wallet-standard/*`
|
|
6
|
+
* packages (see the dependency policy), and a wallet is discovered through
|
|
7
|
+
* window events, so nothing here is ever imported from a wallet library.
|
|
8
|
+
* Every field is what a conforming wallet exposes; the shapes are looser
|
|
9
|
+
* than the reference types so a slightly off wallet is skipped, not thrown
|
|
10
|
+
* on.
|
|
11
|
+
*
|
|
12
|
+
* @see https://github.com/wallet-standard/wallet-standard
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.WALLET_STANDARD_EVENTS_FEATURE = exports.WALLET_STANDARD_REGISTER_WALLET_EVENT = exports.WALLET_STANDARD_APP_READY_EVENT = void 0;
|
|
16
|
+
/** Dispatched by the app on `window`; `detail` is the register API. */
|
|
17
|
+
exports.WALLET_STANDARD_APP_READY_EVENT = "wallet-standard:app-ready";
|
|
18
|
+
/** Dispatched by a wallet on `window`; `detail` is a callback taking the API. */
|
|
19
|
+
exports.WALLET_STANDARD_REGISTER_WALLET_EVENT = "wallet-standard:register-wallet";
|
|
20
|
+
exports.WALLET_STANDARD_EVENTS_FEATURE = "standard:events";
|
|
21
|
+
//# sourceMappingURL=walletStandardTypes.js.map
|
|
@@ -246,16 +246,26 @@ export interface Options {
|
|
|
246
246
|
*/
|
|
247
247
|
wagmi?: WagmiOptions;
|
|
248
248
|
/**
|
|
249
|
-
* Solana
|
|
250
|
-
*
|
|
251
|
-
*
|
|
249
|
+
* Solana wallet tracking.
|
|
250
|
+
*
|
|
251
|
+
* On by default: wallets are discovered through the Wallet Standard, the
|
|
252
|
+
* Solana analogue of EIP-6963, so connect and disconnect are autocaptured
|
|
253
|
+
* for compatible wallets registered with the page, including wallets used
|
|
254
|
+
* through Solana Kit, wallet-adapter, and framework-kit.
|
|
255
|
+
*
|
|
256
|
+
* - `false`: disable Solana wallet discovery and tracking entirely.
|
|
257
|
+
* - `SolanaOptions`: additionally pass `store: client.store` from
|
|
258
|
+
* framework-kit for transaction lifecycle events and cluster switches,
|
|
259
|
+
* or `cluster` to name the network a non-mainnet app is on.
|
|
252
260
|
*
|
|
253
261
|
* For signMessage/signTransaction, use formo.signature() directly
|
|
254
|
-
* (framework-kit
|
|
262
|
+
* (neither the Wallet Standard nor framework-kit's store reports these).
|
|
255
263
|
*
|
|
264
|
+
* @see https://github.com/wallet-standard/wallet-standard
|
|
256
265
|
* @see https://github.com/solana-foundation/framework-kit
|
|
266
|
+
* @default true
|
|
257
267
|
*/
|
|
258
|
-
solana?: SolanaOptions;
|
|
268
|
+
solana?: boolean | SolanaOptions;
|
|
259
269
|
/**
|
|
260
270
|
* Custom API host for sending events through your own domain to bypass ad blockers
|
|
261
271
|
* - If not provided, events are sent directly to events.formo.so
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const version = "1.
|
|
1
|
+
export declare const version = "1.39.0";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/cjs/src/version.js
CHANGED
|
@@ -3,5 +3,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.version = void 0;
|
|
4
4
|
// This file is auto-generated by scripts/update-version.js during npm version
|
|
5
5
|
// Do not edit manually - it will be overwritten
|
|
6
|
-
exports.version = '1.
|
|
6
|
+
exports.version = '1.39.0';
|
|
7
7
|
//# sourceMappingURL=version.js.map
|
|
@@ -242,9 +242,12 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
242
242
|
this.evmEvents.trackEIP1193Provider(provider);
|
|
243
243
|
}
|
|
244
244
|
}
|
|
245
|
-
//
|
|
246
|
-
|
|
247
|
-
|
|
245
|
+
// Solana wallets are discovered through the Wallet Standard
|
|
246
|
+
// unconditionally, the way EVM wallets are through EIP-6963: an app
|
|
247
|
+
// that never configures Solana still gets its connects. `solana: false`
|
|
248
|
+
// is the opt-out; an object adds framework-kit's store or a cluster.
|
|
249
|
+
if (options.solana !== false) {
|
|
250
|
+
this.solanaManager = new SolanaManager(this, typeof options.solana === "object" ? options.solana : undefined);
|
|
248
251
|
}
|
|
249
252
|
this._currentUrl = window.location.href;
|
|
250
253
|
// Seed currentAddress/currentChainId from the persisted snapshot before
|
|
@@ -1268,7 +1271,9 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
1268
1271
|
*/
|
|
1269
1272
|
get: function () {
|
|
1270
1273
|
if (!this.solanaManager) {
|
|
1271
|
-
|
|
1274
|
+
// Only reachable after `solana: false` (or after cleanup). The host
|
|
1275
|
+
// opted out of discovery, so this manager serves the store path only.
|
|
1276
|
+
this.solanaManager = new SolanaManager(this, undefined, false);
|
|
1272
1277
|
}
|
|
1273
1278
|
return this.solanaManager;
|
|
1274
1279
|
},
|
|
@@ -69,6 +69,18 @@ var defaultContext = {
|
|
|
69
69
|
hasOptedOutTracking: function () { return false; },
|
|
70
70
|
};
|
|
71
71
|
export var FormoAnalyticsContext = createContext(defaultContext);
|
|
72
|
+
var optionObjectIds = new WeakMap();
|
|
73
|
+
var nextOptionObjectId = 1;
|
|
74
|
+
var optionObjectId = function (value) {
|
|
75
|
+
if (!value)
|
|
76
|
+
return undefined;
|
|
77
|
+
var id = optionObjectIds.get(value);
|
|
78
|
+
if (id === undefined) {
|
|
79
|
+
id = nextOptionObjectId++;
|
|
80
|
+
optionObjectIds.set(value, id);
|
|
81
|
+
}
|
|
82
|
+
return id;
|
|
83
|
+
};
|
|
72
84
|
/**
|
|
73
85
|
* A stable key over the serializable parts of Options. The provider effect
|
|
74
86
|
* re-initialises the SDK when this key changes; anything that alters SDK
|
|
@@ -92,6 +104,14 @@ export var computeOptionsKey = function (options) {
|
|
|
92
104
|
logger: options.logger,
|
|
93
105
|
referral: options.referral,
|
|
94
106
|
evm: options.evm,
|
|
107
|
+
// `solana` is a boolean or an options object. A store is a live event
|
|
108
|
+
// source, so replacing it must reinitialize the SDK even when both the
|
|
109
|
+
// old and new options contain a store.
|
|
110
|
+
solana: typeof options.solana === "object" ? undefined : options.solana,
|
|
111
|
+
solanaStoreId: typeof options.solana === "object"
|
|
112
|
+
? optionObjectId(options.solana.store)
|
|
113
|
+
: undefined,
|
|
114
|
+
solanaCluster: typeof options.solana === "object" ? options.solana.cluster : undefined,
|
|
95
115
|
// For complex objects, just track their presence, not their content
|
|
96
116
|
hasProvider: !!options.provider,
|
|
97
117
|
hasWagmi: !!options.wagmi,
|
|
@@ -1,14 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* SolanaManager
|
|
3
3
|
*
|
|
4
|
-
*
|
|
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
|
-
*
|
|
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
|
|
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 { FormoAnalytics } from "../FormoAnalytics";
|
|
@@ -16,9 +29,19 @@ import { SolanaCluster, SolanaOptions } from "./types";
|
|
|
16
29
|
import { SolanaClientStore } from "./storeTypes";
|
|
17
30
|
export declare class SolanaManager {
|
|
18
31
|
private formo;
|
|
32
|
+
private readonly enabled;
|
|
19
33
|
private storeHandler?;
|
|
34
|
+
private registry?;
|
|
20
35
|
private pendingCluster?;
|
|
21
|
-
|
|
36
|
+
private storeOwnsWalletEvents;
|
|
37
|
+
/**
|
|
38
|
+
* @param formo - The SDK instance events are reported to.
|
|
39
|
+
* @param options - `options.solana` as passed to the SDK, if an object.
|
|
40
|
+
* @param enabled - Whether Solana tracking is enabled. False only when the
|
|
41
|
+
* host app passed `solana: false`; both discovery and stores then stay off.
|
|
42
|
+
*/
|
|
43
|
+
constructor(formo: FormoAnalytics, options?: SolanaOptions, enabled?: boolean);
|
|
44
|
+
private attachStore;
|
|
22
45
|
/**
|
|
23
46
|
* Set the framework-kit zustand store for automatic event tracking.
|
|
24
47
|
* This enables autocapture mode — connect/disconnect and transaction events
|
|
@@ -39,11 +62,16 @@ export declare class SolanaManager {
|
|
|
39
62
|
cluster?: SolanaCluster;
|
|
40
63
|
}): void;
|
|
41
64
|
/**
|
|
42
|
-
* Update the cluster/network.
|
|
43
|
-
*
|
|
44
|
-
*
|
|
65
|
+
* Update the cluster/network.
|
|
66
|
+
*
|
|
67
|
+
* With a framework-kit store, only needed if the store endpoint doesn't
|
|
68
|
+
* contain a recognizable cluster name (e.g. custom RPC URLs). Without one,
|
|
69
|
+
* this is how a non-mainnet app tells the SDK which cluster its Wallet
|
|
70
|
+
* Standard connections are on, since the standard itself cannot say.
|
|
45
71
|
*/
|
|
46
72
|
setCluster(cluster: SolanaCluster): void;
|
|
73
|
+
/** Names of the Wallet Standard wallets discovered so far. */
|
|
74
|
+
get discoveredWallets(): string[];
|
|
47
75
|
cleanup(): void;
|
|
48
76
|
}
|
|
49
77
|
//# sourceMappingURL=SolanaManager.d.ts.map
|
|
@@ -1,32 +1,124 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* SolanaManager
|
|
3
3
|
*
|
|
4
|
-
*
|
|
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
|
-
*
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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 =
|
|
50
|
-
|
|
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.
|
|
56
|
-
*
|
|
57
|
-
*
|
|
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
|
-
|
|
155
|
-
|
|
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:
|
|
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
|
-
|
|
207
|
-
|
|
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:
|
|
219
|
+
rdns: rdns,
|
|
211
220
|
}).catch(function (error) {
|
|
212
221
|
logger.error("SolanaStoreHandler: Error emitting connect", error);
|
|
213
222
|
});
|