@formo/analytics 1.38.0 → 1.38.2
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.d.ts +15 -4
- package/dist/cjs/src/FormoAnalytics.js +37 -6
- package/dist/cjs/src/FormoAnalyticsProvider.d.ts +8 -0
- package/dist/cjs/src/FormoAnalyticsProvider.js +41 -32
- package/dist/cjs/src/evm/EvmEventTracker.d.ts +100 -9
- package/dist/cjs/src/evm/EvmEventTracker.js +357 -19
- package/dist/cjs/src/evm/EvmProviderRegistry.d.ts +34 -2
- package/dist/cjs/src/evm/EvmProviderRegistry.js +61 -4
- package/dist/cjs/src/evm/EvmRequestTracker.d.ts +21 -4
- package/dist/cjs/src/evm/EvmRequestTracker.js +54 -28
- package/dist/cjs/src/version.d.ts +1 -1
- package/dist/cjs/src/version.js +1 -1
- package/dist/cjs/src/wagmi/WagmiEventHandler.d.ts +67 -1
- package/dist/cjs/src/wagmi/WagmiEventHandler.js +286 -39
- package/dist/cjs/src/wagmi/types.d.ts +6 -0
- package/dist/cjs/src/wagmi/utils.js +9 -1
- package/dist/esm/src/FormoAnalytics.d.ts +15 -4
- package/dist/esm/src/FormoAnalytics.js +37 -6
- package/dist/esm/src/FormoAnalyticsProvider.d.ts +8 -0
- package/dist/esm/src/FormoAnalyticsProvider.js +39 -31
- package/dist/esm/src/evm/EvmEventTracker.d.ts +100 -9
- package/dist/esm/src/evm/EvmEventTracker.js +357 -19
- package/dist/esm/src/evm/EvmProviderRegistry.d.ts +34 -2
- package/dist/esm/src/evm/EvmProviderRegistry.js +61 -4
- package/dist/esm/src/evm/EvmRequestTracker.d.ts +21 -4
- package/dist/esm/src/evm/EvmRequestTracker.js +54 -28
- package/dist/esm/src/version.d.ts +1 -1
- package/dist/esm/src/version.js +1 -1
- package/dist/esm/src/wagmi/WagmiEventHandler.d.ts +67 -1
- package/dist/esm/src/wagmi/WagmiEventHandler.js +286 -39
- package/dist/esm/src/wagmi/types.d.ts +6 -0
- package/dist/esm/src/wagmi/utils.js +9 -1
- package/dist/index.umd.min.js +1 -1
- package/package.json +2 -2
|
@@ -402,9 +402,9 @@ export declare class FormoAnalytics implements IFormoAnalytics {
|
|
|
402
402
|
*
|
|
403
403
|
* With several live SDK instances (multi write-key pages) registering
|
|
404
404
|
* the SAME provider, request-derived events (signatures, transactions)
|
|
405
|
-
* go to the most recently
|
|
406
|
-
*
|
|
407
|
-
* wrapper. Lifecycle events (connect, chain, disconnect) reach every
|
|
405
|
+
* go to the most recently CREATED live instance, regardless of the
|
|
406
|
+
* order registrations happen to land in - the same single-observer
|
|
407
|
+
* semantics discovery has always had for the request wrapper. Lifecycle events (connect, chain, disconnect) reach every
|
|
408
408
|
* instance. Fanning request observations out to all instances is a
|
|
409
409
|
* separate feature.
|
|
410
410
|
*
|
|
@@ -428,8 +428,19 @@ export declare class FormoAnalytics implements IFormoAnalytics {
|
|
|
428
428
|
* gap. Lifecycle (connect/chain/disconnect) stays store-driven: only the
|
|
429
429
|
* request wrapper installs here. Double counting is prevented in the
|
|
430
430
|
* wrapper via `shouldSkipRequestCapture`.
|
|
431
|
+
*
|
|
432
|
+
* `attribution` resolves, live, the name and rdns of the connector this
|
|
433
|
+
* provider was wrapped for. Request-derived events are named from the
|
|
434
|
+
* registry, which for an unannounced provider falls back to flag
|
|
435
|
+
* sniffing; recording the connector's resolver here keeps them in
|
|
436
|
+
* agreement with the hook-driven events for that connector.
|
|
431
437
|
*/
|
|
432
|
-
_wrapWagmiProvider(provider: EIP1193Provider)
|
|
438
|
+
_wrapWagmiProvider(provider: EIP1193Provider, chainId?: number, attribution?: () => {
|
|
439
|
+
name: string;
|
|
440
|
+
rdns?: string;
|
|
441
|
+
} | undefined): boolean;
|
|
442
|
+
/** INTERNAL. Chain updates for the fallback-wrapped provider. */
|
|
443
|
+
_rememberWagmiProviderChain(provider: EIP1193Provider, chainId: number | undefined): void;
|
|
433
444
|
registerProvider(provider: EIP1193Provider, info?: {
|
|
434
445
|
name?: string;
|
|
435
446
|
rdns?: string;
|
|
@@ -1018,6 +1018,9 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
1018
1018
|
// Drop anything already buffered so a pending timer/pagehide flush
|
|
1019
1019
|
// cannot ship events after consent withdrawal.
|
|
1020
1020
|
this.eventManager.clear();
|
|
1021
|
+
// Identity is purged below; registered sessions must be re-learned
|
|
1022
|
+
// on opt-in, and nothing else would retry an already-adopted one.
|
|
1023
|
+
this.evmEvents.markRegisteredAdoptionsPending();
|
|
1021
1024
|
this.reset();
|
|
1022
1025
|
logger_1.logger.info("Successfully opted out of tracking");
|
|
1023
1026
|
};
|
|
@@ -1337,9 +1340,9 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
1337
1340
|
*
|
|
1338
1341
|
* With several live SDK instances (multi write-key pages) registering
|
|
1339
1342
|
* the SAME provider, request-derived events (signatures, transactions)
|
|
1340
|
-
* go to the most recently
|
|
1341
|
-
*
|
|
1342
|
-
* wrapper. Lifecycle events (connect, chain, disconnect) reach every
|
|
1343
|
+
* go to the most recently CREATED live instance, regardless of the
|
|
1344
|
+
* order registrations happen to land in - the same single-observer
|
|
1345
|
+
* semantics discovery has always had for the request wrapper. Lifecycle events (connect, chain, disconnect) reach every
|
|
1343
1346
|
* instance. Fanning request observations out to all instances is a
|
|
1344
1347
|
* separate feature.
|
|
1345
1348
|
*
|
|
@@ -1363,15 +1366,43 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
1363
1366
|
* gap. Lifecycle (connect/chain/disconnect) stays store-driven: only the
|
|
1364
1367
|
* request wrapper installs here. Double counting is prevented in the
|
|
1365
1368
|
* wrapper via `shouldSkipRequestCapture`.
|
|
1369
|
+
*
|
|
1370
|
+
* `attribution` resolves, live, the name and rdns of the connector this
|
|
1371
|
+
* provider was wrapped for. Request-derived events are named from the
|
|
1372
|
+
* registry, which for an unannounced provider falls back to flag
|
|
1373
|
+
* sniffing; recording the connector's resolver here keeps them in
|
|
1374
|
+
* agreement with the hook-driven events for that connector.
|
|
1366
1375
|
*/
|
|
1367
|
-
FormoAnalytics.prototype._wrapWagmiProvider = function (provider) {
|
|
1376
|
+
FormoAnalytics.prototype._wrapWagmiProvider = function (provider, chainId, attribution) {
|
|
1368
1377
|
if (this.isCleanedUp || !(0, provider_1.isValidProvider)(provider))
|
|
1369
|
-
return;
|
|
1378
|
+
return false;
|
|
1370
1379
|
try {
|
|
1371
|
-
|
|
1380
|
+
// The tracker reports refusals (frozen provider, unrebindable
|
|
1381
|
+
// wrapper) by returning false rather than throwing; treat those as
|
|
1382
|
+
// failures too so the caller can retry later.
|
|
1383
|
+
if (!this.evmRequests.registerRequestListeners(provider)) {
|
|
1384
|
+
return false;
|
|
1385
|
+
}
|
|
1386
|
+
this.evm.rememberAttribution(provider, attribution);
|
|
1387
|
+
if (chainId !== undefined) {
|
|
1388
|
+
this.evm.rememberChain(provider, chainId);
|
|
1389
|
+
}
|
|
1390
|
+
return true;
|
|
1372
1391
|
}
|
|
1373
1392
|
catch (e) {
|
|
1374
1393
|
logger_1.logger.warn("Failed to wrap wagmi provider for hybrid capture", e);
|
|
1394
|
+
return false;
|
|
1395
|
+
}
|
|
1396
|
+
};
|
|
1397
|
+
/** INTERNAL. Chain updates for the fallback-wrapped provider. */
|
|
1398
|
+
FormoAnalytics.prototype._rememberWagmiProviderChain = function (provider, chainId) {
|
|
1399
|
+
if (this.isCleanedUp)
|
|
1400
|
+
return;
|
|
1401
|
+
try {
|
|
1402
|
+
this.evm.rememberChain(provider, chainId);
|
|
1403
|
+
}
|
|
1404
|
+
catch (_a) {
|
|
1405
|
+
/* bookkeeping only */
|
|
1375
1406
|
}
|
|
1376
1407
|
};
|
|
1377
1408
|
FormoAnalytics.prototype.registerProvider = function (provider, info) {
|
|
@@ -7,6 +7,14 @@ export interface FormoAnalyticsProviderProps {
|
|
|
7
7
|
children: ReactNode;
|
|
8
8
|
}
|
|
9
9
|
export declare const FormoAnalyticsContext: import("react").Context<IFormoAnalytics>;
|
|
10
|
+
/**
|
|
11
|
+
* A stable key over the serializable parts of Options. The provider effect
|
|
12
|
+
* re-initialises the SDK when this key changes; anything that alters SDK
|
|
13
|
+
* behaviour must be represented here, or a runtime change to it is silently
|
|
14
|
+
* ignored. Complex objects are tracked by presence, plus the flags that
|
|
15
|
+
* change what the SDK does with them.
|
|
16
|
+
*/
|
|
17
|
+
export declare const computeOptionsKey: (options?: Options) => string;
|
|
10
18
|
export declare const FormoAnalyticsProvider: FC<FormoAnalyticsProviderProps>;
|
|
11
19
|
export declare const useFormo: () => IFormoAnalytics;
|
|
12
20
|
//# sourceMappingURL=FormoAnalyticsProvider.d.ts.map
|
|
@@ -47,7 +47,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
47
47
|
}
|
|
48
48
|
};
|
|
49
49
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
-
exports.useFormo = exports.FormoAnalyticsProvider = exports.FormoAnalyticsContext = void 0;
|
|
50
|
+
exports.useFormo = exports.FormoAnalyticsProvider = exports.computeOptionsKey = exports.FormoAnalyticsContext = void 0;
|
|
51
51
|
var jsx_runtime_1 = require("react/jsx-runtime");
|
|
52
52
|
var react_1 = require("react");
|
|
53
53
|
var FormoAnalytics_1 = require("./FormoAnalytics");
|
|
@@ -72,6 +72,45 @@ var defaultContext = {
|
|
|
72
72
|
hasOptedOutTracking: function () { return false; },
|
|
73
73
|
};
|
|
74
74
|
exports.FormoAnalyticsContext = (0, react_1.createContext)(defaultContext);
|
|
75
|
+
/**
|
|
76
|
+
* A stable key over the serializable parts of Options. The provider effect
|
|
77
|
+
* re-initialises the SDK when this key changes; anything that alters SDK
|
|
78
|
+
* behaviour must be represented here, or a runtime change to it is silently
|
|
79
|
+
* ignored. Complex objects are tracked by presence, plus the flags that
|
|
80
|
+
* change what the SDK does with them.
|
|
81
|
+
*/
|
|
82
|
+
var computeOptionsKey = function (options) {
|
|
83
|
+
var _a;
|
|
84
|
+
if (!options)
|
|
85
|
+
return 'undefined';
|
|
86
|
+
var serializableOptions = {
|
|
87
|
+
tracking: options.tracking,
|
|
88
|
+
autocapture: options.autocapture,
|
|
89
|
+
crossSubdomainCookies: options.crossSubdomainCookies,
|
|
90
|
+
apiHost: options.apiHost,
|
|
91
|
+
flushAt: options.flushAt,
|
|
92
|
+
flushInterval: options.flushInterval,
|
|
93
|
+
retryCount: options.retryCount,
|
|
94
|
+
maxQueueSize: options.maxQueueSize,
|
|
95
|
+
logger: options.logger,
|
|
96
|
+
referral: options.referral,
|
|
97
|
+
evm: options.evm,
|
|
98
|
+
// For complex objects, just track their presence, not their content
|
|
99
|
+
hasProvider: !!options.provider,
|
|
100
|
+
hasWagmi: !!options.wagmi,
|
|
101
|
+
wagmiEip1193Fallback: !!((_a = options.wagmi) === null || _a === void 0 ? void 0 : _a.eip1193Fallback),
|
|
102
|
+
hasReady: !!options.ready,
|
|
103
|
+
};
|
|
104
|
+
try {
|
|
105
|
+
return JSON.stringify(serializableOptions);
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
// Fallback to timestamp if serialization fails
|
|
109
|
+
logger_1.logger.warn('Failed to serialize options, using timestamp', error);
|
|
110
|
+
return Date.now().toString();
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
exports.computeOptionsKey = computeOptionsKey;
|
|
75
114
|
var FormoAnalyticsProvider = function (props) {
|
|
76
115
|
var writeKey = props.writeKey, _a = props.disabled, disabled = _a === void 0 ? false : _a, children = props.children;
|
|
77
116
|
// Keep the app running without analytics if no Write Key is provided or disabled
|
|
@@ -91,37 +130,7 @@ var InitializedAnalytics = function (_a) {
|
|
|
91
130
|
var _b = (0, react_1.useState)(defaultContext), sdk = _b[0], setSdk = _b[1];
|
|
92
131
|
var sdkRef = (0, react_1.useRef)(defaultContext);
|
|
93
132
|
(0, storage_1.initStorageManager)(writeKey);
|
|
94
|
-
|
|
95
|
-
// We only care about serializable config values that would affect SDK behavior
|
|
96
|
-
var optionsKey = (0, react_1.useMemo)(function () {
|
|
97
|
-
if (!options)
|
|
98
|
-
return 'undefined';
|
|
99
|
-
// Extract only the serializable parts of options
|
|
100
|
-
var serializableOptions = {
|
|
101
|
-
tracking: options.tracking,
|
|
102
|
-
autocapture: options.autocapture,
|
|
103
|
-
crossSubdomainCookies: options.crossSubdomainCookies,
|
|
104
|
-
apiHost: options.apiHost,
|
|
105
|
-
flushAt: options.flushAt,
|
|
106
|
-
flushInterval: options.flushInterval,
|
|
107
|
-
retryCount: options.retryCount,
|
|
108
|
-
maxQueueSize: options.maxQueueSize,
|
|
109
|
-
logger: options.logger,
|
|
110
|
-
referral: options.referral,
|
|
111
|
-
// For complex objects, just track their presence, not their content
|
|
112
|
-
hasProvider: !!options.provider,
|
|
113
|
-
hasWagmi: !!options.wagmi,
|
|
114
|
-
hasReady: !!options.ready,
|
|
115
|
-
};
|
|
116
|
-
try {
|
|
117
|
-
return JSON.stringify(serializableOptions);
|
|
118
|
-
}
|
|
119
|
-
catch (error) {
|
|
120
|
-
// Fallback to timestamp if serialization fails
|
|
121
|
-
logger_1.logger.warn('Failed to serialize options, using timestamp', error);
|
|
122
|
-
return Date.now().toString();
|
|
123
|
-
}
|
|
124
|
-
}, [options]);
|
|
133
|
+
var optionsKey = (0, react_1.useMemo)(function () { return (0, exports.computeOptionsKey)(options); }, [options]);
|
|
125
134
|
(0, react_1.useEffect)(function () {
|
|
126
135
|
var isCleanedUp = false;
|
|
127
136
|
var initialize = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
@@ -52,10 +52,91 @@ export declare class EvmEventTracker {
|
|
|
52
52
|
* Announcement-driven cleanup must not touch them: they are never in an
|
|
53
53
|
* announcement list, so "missing from the announcement" is their normal
|
|
54
54
|
* state, not evidence of removal. A Set rather than a WeakSet because
|
|
55
|
-
*
|
|
56
|
-
* strongly
|
|
55
|
+
* the corrected-detect pass iterates it; the registry's detail list
|
|
56
|
+
* holds these providers strongly for the instance's life anyway.
|
|
57
57
|
*/
|
|
58
58
|
private externallyRegistered;
|
|
59
|
+
/**
|
|
60
|
+
* Registered providers whose session this SDK has NOT yet learned.
|
|
61
|
+
*
|
|
62
|
+
* Only these are retried on page hits and opt-in. Re-running adoption for
|
|
63
|
+
* every registered provider looked idempotent but was not: adoption is
|
|
64
|
+
* the same path a live `accountsChanged` takes, and that path treats a
|
|
65
|
+
* provider with a different address from the active one as a wallet
|
|
66
|
+
* switch. With two registered providers, or one registered next to a
|
|
67
|
+
* discovered wallet, every page hit emitted a disconnect and a connect
|
|
68
|
+
* that no user action caused.
|
|
69
|
+
*
|
|
70
|
+
* A provider enters at registration (it may have no session yet, or be
|
|
71
|
+
* refused because tracking is suppressed), again whenever a handler
|
|
72
|
+
* refuses its signal while suppressed (noted on entry AND at the
|
|
73
|
+
* suppressed commit, since the handlers gate on the active provider and
|
|
74
|
+
* re-check suppression after an await), and again for all of them when
|
|
75
|
+
* an opt-out purges identity. It leaves the first time a handler commits
|
|
76
|
+
* its session unsuppressed, or when it is untracked. Retrying reads the
|
|
77
|
+
* provider's SYNCHRONOUS accounts only - no RPC - so a registered
|
|
78
|
+
* provider whose session never fires `accountsChanged` (a wallet that
|
|
79
|
+
* signals `connect` alone while `autocapture.connect` is off, which
|
|
80
|
+
* installs a chain-only observer) is still adopted on the next hit. "No
|
|
81
|
+
* RPC" holds for the pending provider itself; the handler's switch
|
|
82
|
+
* arbitration may still ask the ACTIVE provider for its accounts, as it
|
|
83
|
+
* does for any live signal.
|
|
84
|
+
*
|
|
85
|
+
* Replay goes through the accounts handler, which has live wallet-switch
|
|
86
|
+
* semantics: a different provider with a different address is a switch.
|
|
87
|
+
* So a pending provider is replayed only while no OTHER wallet is active
|
|
88
|
+
* and known - it waits, at no cost, until that wallet is gone - unless
|
|
89
|
+
* its own signal was refused (`latestRefused`): then the replay does
|
|
90
|
+
* exactly what the live signal would have done, switch included.
|
|
91
|
+
*/
|
|
92
|
+
private pendingAdoptions;
|
|
93
|
+
/**
|
|
94
|
+
* The pending provider whose own live signal was refused while
|
|
95
|
+
* suppressed, LATEST only. The SDK follows one active wallet and the
|
|
96
|
+
* newest signal wins, so replaying only the last refused signal reaches
|
|
97
|
+
* the state the live signals would have reached, without the switches
|
|
98
|
+
* in between; an earlier refused provider stays pending, unprivileged.
|
|
99
|
+
*/
|
|
100
|
+
private latestRefused?;
|
|
101
|
+
private dropRefusal;
|
|
102
|
+
/**
|
|
103
|
+
* An opt-out purges wallet identity. Every registered session is then
|
|
104
|
+
* unknown again (pending; no refusal is ADDED, so the opt-in replay of a
|
|
105
|
+
* merely connected wallet does not switch, while a refusal already
|
|
106
|
+
* standing from an excluded route keeps its meaning), and the
|
|
107
|
+
* opt-in retry must re-learn all of them: with the active wallet's
|
|
108
|
+
* address gone, the accounts handler cannot even tell a second wallet's
|
|
109
|
+
* accounts apart from the active one's, and would ignore them.
|
|
110
|
+
*/
|
|
111
|
+
markRegisteredAdoptionsPending(): void;
|
|
112
|
+
/**
|
|
113
|
+
* Remember a registered provider's signal that suppression refuses.
|
|
114
|
+
*
|
|
115
|
+
* Replay privilege (`latestRefused`) goes only to a provider whose
|
|
116
|
+
* session the replay can actually read - synchronous accounts - so an
|
|
117
|
+
* accountless `connect` (a chain-only observation, or a session still
|
|
118
|
+
* pairing) cannot displace an earlier refusal that is adoptable.
|
|
119
|
+
*/
|
|
120
|
+
private noteRefusalIfSuppressed;
|
|
121
|
+
/**
|
|
122
|
+
* Registered providers whose session ended and have not signalled a
|
|
123
|
+
* new one. Some providers keep stale synchronous `accounts` after a
|
|
124
|
+
* disconnect; replaying those would re-install a session that is over.
|
|
125
|
+
* Any later session signal (connect, accountsChanged) lifts this.
|
|
126
|
+
*/
|
|
127
|
+
private awaitingNewSession;
|
|
128
|
+
/** A handler has learned this provider's session; nothing is pending. */
|
|
129
|
+
private settleAdoption;
|
|
130
|
+
/**
|
|
131
|
+
* A registered provider's session has ended. Its NEXT session is not
|
|
132
|
+
* yet learned, and may announce itself in a way no handler adopts (a
|
|
133
|
+
* `connect` alone while `autocapture.connect` is off installs a
|
|
134
|
+
* chain-only observer), so it is pending again for the page-hit retry.
|
|
135
|
+
*/
|
|
136
|
+
private reopenAdoption;
|
|
137
|
+
/** One retry scan at a time; a call during a scan queues one more. */
|
|
138
|
+
private retryInFlight;
|
|
139
|
+
private retryRequested;
|
|
59
140
|
/**
|
|
60
141
|
* The connect this SDK has already reported for a provider.
|
|
61
142
|
*
|
|
@@ -74,6 +155,11 @@ export declare class EvmEventTracker {
|
|
|
74
155
|
constructor(wallet: WalletStateStore, registry: EvmProviderRegistry, deps: EvmEventTrackerDeps);
|
|
75
156
|
/** Stop listening for wallet announcements. Called from SDK teardown. */
|
|
76
157
|
cleanup(): void;
|
|
158
|
+
/** Set by `cleanup()`; every awaited continuation checks it. */
|
|
159
|
+
private disposed;
|
|
160
|
+
/** Bumped when a registered provider's session ends. See reopenAdoption. */
|
|
161
|
+
private sessionGenerations;
|
|
162
|
+
private sessionGeneration;
|
|
77
163
|
/** Drop a provider's reported connect. Called when it stops being active. */
|
|
78
164
|
forgetAnnouncedConnect(provider: EIP1193Provider): void;
|
|
79
165
|
/**
|
|
@@ -109,14 +195,19 @@ export declare class EvmEventTracker {
|
|
|
109
195
|
*/
|
|
110
196
|
adoptExternalProvider(detail: EIP6963ProviderDetail): boolean;
|
|
111
197
|
/**
|
|
112
|
-
*
|
|
198
|
+
* Finish what registration could not.
|
|
199
|
+
*
|
|
200
|
+
* A registered provider's session may not have existed at registration,
|
|
201
|
+
* or its adoption was refused because tracking was suppressed (opt-out,
|
|
202
|
+
* excluded route) - and an existing session may never emit another
|
|
203
|
+
* accountsChanged, so nothing else would ever retry. Called when
|
|
204
|
+
* suppression can have ended (opt-in, page navigation).
|
|
113
205
|
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
* deduplicated by the same state and markers as any repeated signal.
|
|
206
|
+
* Adoption is retried ONLY for providers not yet adopted
|
|
207
|
+
* (`pendingAdoptions`), only from their synchronous accounts, and only
|
|
208
|
+
* once suppression has actually ended. The corrected-detect pass below
|
|
209
|
+
* runs for every registered provider: it is deduplicated per session by
|
|
210
|
+
* rdns, so repeating it is free.
|
|
120
211
|
*/
|
|
121
212
|
retryExternalAdoptions(): void;
|
|
122
213
|
private registerAccountsChangedListener;
|