@unicitylabs/sphere-sdk 0.15.0 → 0.16.0-dev.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/README.md +15 -5
- package/dist/connect/index.cjs +26 -25
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/index.d.cts +4 -0
- package/dist/connect/index.d.ts +4 -0
- package/dist/connect/index.js +26 -25
- package/dist/connect/index.js.map +1 -1
- package/dist/core/index.cjs +728 -227
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +174 -23
- package/dist/core/index.d.ts +174 -23
- package/dist/core/index.js +728 -226
- package/dist/core/index.js.map +1 -1
- package/dist/impl/browser/connect/index.cjs +16 -25
- package/dist/impl/browser/connect/index.cjs.map +1 -1
- package/dist/impl/browser/connect/index.js +16 -25
- package/dist/impl/browser/connect/index.js.map +1 -1
- package/dist/impl/browser/index.cjs +333 -506
- package/dist/impl/browser/index.cjs.map +1 -1
- package/dist/impl/browser/index.js +333 -506
- package/dist/impl/browser/index.js.map +1 -1
- package/dist/impl/nodejs/connect/index.cjs +15 -24
- package/dist/impl/nodejs/connect/index.cjs.map +1 -1
- package/dist/impl/nodejs/connect/index.js +15 -24
- package/dist/impl/nodejs/connect/index.js.map +1 -1
- package/dist/impl/nodejs/index.cjs +300 -571
- package/dist/impl/nodejs/index.cjs.map +1 -1
- package/dist/impl/nodejs/index.d.cts +92 -15
- package/dist/impl/nodejs/index.d.ts +92 -15
- package/dist/impl/nodejs/index.js +300 -571
- package/dist/impl/nodejs/index.js.map +1 -1
- package/dist/impl/shared/wallet-api/index.d.cts +54 -2
- package/dist/impl/shared/wallet-api/index.d.ts +54 -2
- package/dist/index.cjs +730 -227
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +229 -110
- package/dist/index.d.ts +229 -110
- package/dist/index.js +730 -226
- package/dist/index.js.map +1 -1
- package/dist/modules/payments-v2/index.cjs +11 -7
- package/dist/modules/payments-v2/index.cjs.map +1 -1
- package/dist/modules/payments-v2/index.d.cts +56 -3
- package/dist/modules/payments-v2/index.d.ts +56 -3
- package/dist/modules/payments-v2/index.js +11 -7
- package/dist/modules/payments-v2/index.js.map +1 -1
- package/dist/token-engine/index.cjs +46 -0
- package/dist/token-engine/index.cjs.map +1 -1
- package/dist/token-engine/index.js +46 -0
- package/dist/token-engine/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -73,6 +73,25 @@ interface TrackedAddressEntry {
|
|
|
73
73
|
* All operations are async for platform flexibility
|
|
74
74
|
*/
|
|
75
75
|
interface StorageProvider extends BaseProvider {
|
|
76
|
+
/**
|
|
77
|
+
* Stable identity of the BACKING STORE this provider addresses — not of this
|
|
78
|
+
* object, and not of the class (`id` is a class constant like `'file-storage'`,
|
|
79
|
+
* which is exactly the wrong granularity).
|
|
80
|
+
*
|
|
81
|
+
* Two providers that return the SAME value address the same data, so erasing
|
|
82
|
+
* through one erases through the other: `Sphere.clear({ storage })` tears down
|
|
83
|
+
* the live Spheres of every provider sharing this value, not merely those built
|
|
84
|
+
* on this object. Compose it from everything that selects the store (file path,
|
|
85
|
+
* database name, key prefix) behind a scheme prefix, so two kinds of store can
|
|
86
|
+
* never collide on one string.
|
|
87
|
+
*
|
|
88
|
+
* It must not change over the provider's lifetime — it is read again on teardown,
|
|
89
|
+
* and a value that moved would strand the entry it was registered under.
|
|
90
|
+
*
|
|
91
|
+
* Optional: omit it and liveness falls back to per-object identity, i.e. a
|
|
92
|
+
* second provider over the same data is treated as unrelated.
|
|
93
|
+
*/
|
|
94
|
+
readonly backingStoreId?: string;
|
|
76
95
|
/**
|
|
77
96
|
* Set identity for scoped storage
|
|
78
97
|
*/
|
|
@@ -102,11 +121,44 @@ interface StorageProvider extends BaseProvider {
|
|
|
102
121
|
*/
|
|
103
122
|
clear(prefix?: string): Promise<void>;
|
|
104
123
|
/**
|
|
105
|
-
* Save tracked addresses (only user state: index, hidden, timestamps)
|
|
124
|
+
* Save tracked addresses (only user state: index, hidden, timestamps).
|
|
125
|
+
*
|
|
126
|
+
* MUST MERGE, NEVER REPLACE (#766 item 5). `entries` is ONE writer's snapshot,
|
|
127
|
+
* not the whole truth: every Sphere sharing this storage keeps its own copy of
|
|
128
|
+
* the registry and persists all of it, so writing the argument verbatim is a
|
|
129
|
+
* lost update — A activates index 1, B (whose snapshot predates that) activates
|
|
130
|
+
* index 2, and B's write erases index 1 while A still reports it. This happens
|
|
131
|
+
* on a single network with a single provider; do NOT "fix" it by renaming or
|
|
132
|
+
* network-scoping the key.
|
|
133
|
+
*
|
|
134
|
+
* The contract, implemented by `storage/tracked-addresses.ts` — reuse those
|
|
135
|
+
* helpers rather than re-deriving this:
|
|
136
|
+
* - read the stored registry, union it with `entries` BY `index`;
|
|
137
|
+
* - on a conflicting index, the entry with the greater `updatedAt` supplies
|
|
138
|
+
* `hidden`, and `createdAt` keeps the earlier value;
|
|
139
|
+
* - serialize concurrent calls on the provider instance, so one call's read
|
|
140
|
+
* cannot interleave with another's write;
|
|
141
|
+
* - a failed write must not brick later writes, and must still reject to its
|
|
142
|
+
* own caller.
|
|
143
|
+
*
|
|
144
|
+
* An `index` must be a UINT32 — a BIP32 child number. `deriveKeyAtPath` parseInt()s
|
|
145
|
+
* that path segment, so `1.5` derives index 1's keys and the row aliases a real
|
|
146
|
+
* address. The ceiling matters too: `deriveChildKey` pads the child number to 8 hex
|
|
147
|
+
* digits, so anything above `0xffffffff` emits extra bytes and derives off-standard.
|
|
148
|
+
* An `entries` row that is not one must REJECT the whole call (`mergeTrackedAddresses`
|
|
149
|
+
* throws `VALIDATION_ERROR`); dropping it silently on a write reports a save that
|
|
150
|
+
* never happened. Already-stored rows are dropped on READ instead, so one bad row
|
|
151
|
+
* cannot brick every later write. Validate before opening the write transaction if
|
|
152
|
+
* your platform would otherwise replace the reason with a generic abort.
|
|
153
|
+
*
|
|
154
|
+
* A union is safe because there is no delete path: entries are only ever added,
|
|
155
|
+
* and wiping the wallet removes the key itself (`Sphere.clear()`). Adding a
|
|
156
|
+
* per-entry delete would require revisiting this contract.
|
|
106
157
|
*/
|
|
107
158
|
saveTrackedAddresses(entries: TrackedAddressEntry[]): Promise<void>;
|
|
108
159
|
/**
|
|
109
|
-
* Load tracked addresses
|
|
160
|
+
* Load tracked addresses. Tolerant: unusable/corrupt storage reads as `[]`
|
|
161
|
+
* (see `parseTrackedAddresses` in `storage/tracked-addresses.ts`).
|
|
110
162
|
*/
|
|
111
163
|
loadTrackedAddresses(): Promise<TrackedAddressEntry[]>;
|
|
112
164
|
}
|
|
@@ -115,13 +167,14 @@ interface StorageProvider extends BaseProvider {
|
|
|
115
167
|
declare const NETWORKS: {
|
|
116
168
|
readonly mainnet: {
|
|
117
169
|
readonly name: "Mainnet";
|
|
118
|
-
readonly
|
|
119
|
-
readonly
|
|
170
|
+
readonly networkId: 1;
|
|
171
|
+
readonly aggregatorUrl: "https://gateway.mainnet.unicity.network";
|
|
172
|
+
readonly nostrRelays: readonly ["wss://nostr-relay.testnet.unicity.network"];
|
|
120
173
|
readonly groupRelays: readonly ["wss://sphere-relay.unicity.network"];
|
|
121
|
-
readonly tokenRegistryUrl: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.
|
|
174
|
+
readonly tokenRegistryUrl: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.mainnet.json";
|
|
122
175
|
};
|
|
123
176
|
readonly testnet: {
|
|
124
|
-
readonly name: "
|
|
177
|
+
readonly name: "Testnet";
|
|
125
178
|
readonly networkId: 4;
|
|
126
179
|
readonly aggregatorUrl: "https://gateway.testnet2.unicity.network";
|
|
127
180
|
readonly nostrRelays: readonly ["wss://nostr-relay.testnet.unicity.network"];
|
|
@@ -129,20 +182,13 @@ declare const NETWORKS: {
|
|
|
129
182
|
readonly tokenRegistryUrl: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.testnet2.json";
|
|
130
183
|
};
|
|
131
184
|
readonly testnet2: {
|
|
132
|
-
readonly name: "
|
|
185
|
+
readonly name: "Testnet";
|
|
133
186
|
readonly networkId: 4;
|
|
134
187
|
readonly aggregatorUrl: "https://gateway.testnet2.unicity.network";
|
|
135
188
|
readonly nostrRelays: readonly ["wss://nostr-relay.testnet.unicity.network"];
|
|
136
189
|
readonly groupRelays: readonly ["wss://sphere-relay.unicity.network"];
|
|
137
190
|
readonly tokenRegistryUrl: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.testnet2.json";
|
|
138
191
|
};
|
|
139
|
-
readonly dev: {
|
|
140
|
-
readonly name: "Development";
|
|
141
|
-
readonly aggregatorUrl: "https://dev-aggregator.dyndns.org/rpc";
|
|
142
|
-
readonly nostrRelays: readonly ["wss://nostr-relay.testnet.unicity.network"];
|
|
143
|
-
readonly groupRelays: readonly ["wss://sphere-relay.unicity.network"];
|
|
144
|
-
readonly tokenRegistryUrl: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.testnet.json";
|
|
145
|
-
};
|
|
146
192
|
};
|
|
147
193
|
type NetworkType = keyof typeof NETWORKS;
|
|
148
194
|
|
|
@@ -166,6 +212,8 @@ declare class FileStorageProvider implements StorageProvider {
|
|
|
166
212
|
readonly id = "file-storage";
|
|
167
213
|
readonly name = "File Storage";
|
|
168
214
|
readonly type: "local";
|
|
215
|
+
/** The resolved wallet file — two providers over one path share erasure (#766). */
|
|
216
|
+
readonly backingStoreId: string;
|
|
169
217
|
private dataDir;
|
|
170
218
|
private filePath;
|
|
171
219
|
private isTxtMode;
|
|
@@ -186,6 +234,26 @@ declare class FileStorageProvider implements StorageProvider {
|
|
|
186
234
|
has(key: string): Promise<boolean>;
|
|
187
235
|
keys(prefix?: string): Promise<string[]>;
|
|
188
236
|
clear(prefix?: string): Promise<void>;
|
|
237
|
+
/** Serializes the read-merge-write below, per provider instance. */
|
|
238
|
+
private trackedWrites;
|
|
239
|
+
/**
|
|
240
|
+
* Persist the tracked-address registry by MERGING, never replacing.
|
|
241
|
+
*
|
|
242
|
+
* Every Sphere over this storage holds its own snapshot and writes it in
|
|
243
|
+
* full, so a wholesale write drops the addresses this writer never saw
|
|
244
|
+
* (#766 item 5 — a lost update, reproducible on one network). Concurrent
|
|
245
|
+
* calls are serialized on `trackedWrites` so a read can never interleave
|
|
246
|
+
* with another call's write.
|
|
247
|
+
*
|
|
248
|
+
* Deliberately PER OBJECT, unlike the browser providers. Two objects over one
|
|
249
|
+
* `dataDir` share a `backingStoreId` but not this cache, and `save()` rewrites the
|
|
250
|
+
* WHOLE file from it — so a sibling's *unrelated* `set()` rolls the registry back
|
|
251
|
+
* regardless of how this one write is serialized. Sharing the chain here would make
|
|
252
|
+
* the cross-object contract case pass while leaving the provider unsafe. The real
|
|
253
|
+
* fix is #771 (refresh from disk under a per-file lock, on every write); until then
|
|
254
|
+
* `backingStoreId` scopes TEARDOWN only. Reviewers keep re-finding this — see the
|
|
255
|
+
* `unsupported:` note in tests/unit/storage/tracked-addresses-providers.test.ts.
|
|
256
|
+
*/
|
|
189
257
|
saveTrackedAddresses(entries: TrackedAddressEntry[]): Promise<void>;
|
|
190
258
|
loadTrackedAddresses(): Promise<TrackedAddressEntry[]>;
|
|
191
259
|
/**
|
|
@@ -584,6 +652,15 @@ declare class NostrTransportProvider implements TransportProvider {
|
|
|
584
652
|
suppressSubscriptions(): void;
|
|
585
653
|
private _subscriptionsSuppressed;
|
|
586
654
|
connect(): Promise<void>;
|
|
655
|
+
/**
|
|
656
|
+
* Race one client's relay connect against the configured timeout.
|
|
657
|
+
*
|
|
658
|
+
* The timer is cleared in a `finally` on EVERY path. `Promise.race` does not
|
|
659
|
+
* cancel the loser: an un-cleared `setTimeout` keeps Node's event loop pinned
|
|
660
|
+
* for the whole `config.timeout` after the call has already returned (and
|
|
661
|
+
* then rejects a promise nobody is listening to any more).
|
|
662
|
+
*/
|
|
663
|
+
private connectWithDeadline;
|
|
587
664
|
disconnect(): Promise<void>;
|
|
588
665
|
isConnected(): boolean;
|
|
589
666
|
getStatus(): ProviderStatus;
|
|
@@ -1545,7 +1622,7 @@ type NodeTransportConfig = BaseTransportConfig;
|
|
|
1545
1622
|
*/
|
|
1546
1623
|
type NodeOracleConfig = BaseOracleConfig & NodeOracleExtensions;
|
|
1547
1624
|
interface NodeProvidersConfig {
|
|
1548
|
-
/** Network preset: mainnet, testnet
|
|
1625
|
+
/** Network preset: mainnet, testnet or testnet2 */
|
|
1549
1626
|
network?: NetworkType;
|
|
1550
1627
|
/** Enable debug logging globally for all providers (default: false). Per-provider debug flags override this. */
|
|
1551
1628
|
debug?: boolean;
|
|
@@ -73,6 +73,25 @@ interface TrackedAddressEntry {
|
|
|
73
73
|
* All operations are async for platform flexibility
|
|
74
74
|
*/
|
|
75
75
|
interface StorageProvider extends BaseProvider {
|
|
76
|
+
/**
|
|
77
|
+
* Stable identity of the BACKING STORE this provider addresses — not of this
|
|
78
|
+
* object, and not of the class (`id` is a class constant like `'file-storage'`,
|
|
79
|
+
* which is exactly the wrong granularity).
|
|
80
|
+
*
|
|
81
|
+
* Two providers that return the SAME value address the same data, so erasing
|
|
82
|
+
* through one erases through the other: `Sphere.clear({ storage })` tears down
|
|
83
|
+
* the live Spheres of every provider sharing this value, not merely those built
|
|
84
|
+
* on this object. Compose it from everything that selects the store (file path,
|
|
85
|
+
* database name, key prefix) behind a scheme prefix, so two kinds of store can
|
|
86
|
+
* never collide on one string.
|
|
87
|
+
*
|
|
88
|
+
* It must not change over the provider's lifetime — it is read again on teardown,
|
|
89
|
+
* and a value that moved would strand the entry it was registered under.
|
|
90
|
+
*
|
|
91
|
+
* Optional: omit it and liveness falls back to per-object identity, i.e. a
|
|
92
|
+
* second provider over the same data is treated as unrelated.
|
|
93
|
+
*/
|
|
94
|
+
readonly backingStoreId?: string;
|
|
76
95
|
/**
|
|
77
96
|
* Set identity for scoped storage
|
|
78
97
|
*/
|
|
@@ -102,11 +121,44 @@ interface StorageProvider extends BaseProvider {
|
|
|
102
121
|
*/
|
|
103
122
|
clear(prefix?: string): Promise<void>;
|
|
104
123
|
/**
|
|
105
|
-
* Save tracked addresses (only user state: index, hidden, timestamps)
|
|
124
|
+
* Save tracked addresses (only user state: index, hidden, timestamps).
|
|
125
|
+
*
|
|
126
|
+
* MUST MERGE, NEVER REPLACE (#766 item 5). `entries` is ONE writer's snapshot,
|
|
127
|
+
* not the whole truth: every Sphere sharing this storage keeps its own copy of
|
|
128
|
+
* the registry and persists all of it, so writing the argument verbatim is a
|
|
129
|
+
* lost update — A activates index 1, B (whose snapshot predates that) activates
|
|
130
|
+
* index 2, and B's write erases index 1 while A still reports it. This happens
|
|
131
|
+
* on a single network with a single provider; do NOT "fix" it by renaming or
|
|
132
|
+
* network-scoping the key.
|
|
133
|
+
*
|
|
134
|
+
* The contract, implemented by `storage/tracked-addresses.ts` — reuse those
|
|
135
|
+
* helpers rather than re-deriving this:
|
|
136
|
+
* - read the stored registry, union it with `entries` BY `index`;
|
|
137
|
+
* - on a conflicting index, the entry with the greater `updatedAt` supplies
|
|
138
|
+
* `hidden`, and `createdAt` keeps the earlier value;
|
|
139
|
+
* - serialize concurrent calls on the provider instance, so one call's read
|
|
140
|
+
* cannot interleave with another's write;
|
|
141
|
+
* - a failed write must not brick later writes, and must still reject to its
|
|
142
|
+
* own caller.
|
|
143
|
+
*
|
|
144
|
+
* An `index` must be a UINT32 — a BIP32 child number. `deriveKeyAtPath` parseInt()s
|
|
145
|
+
* that path segment, so `1.5` derives index 1's keys and the row aliases a real
|
|
146
|
+
* address. The ceiling matters too: `deriveChildKey` pads the child number to 8 hex
|
|
147
|
+
* digits, so anything above `0xffffffff` emits extra bytes and derives off-standard.
|
|
148
|
+
* An `entries` row that is not one must REJECT the whole call (`mergeTrackedAddresses`
|
|
149
|
+
* throws `VALIDATION_ERROR`); dropping it silently on a write reports a save that
|
|
150
|
+
* never happened. Already-stored rows are dropped on READ instead, so one bad row
|
|
151
|
+
* cannot brick every later write. Validate before opening the write transaction if
|
|
152
|
+
* your platform would otherwise replace the reason with a generic abort.
|
|
153
|
+
*
|
|
154
|
+
* A union is safe because there is no delete path: entries are only ever added,
|
|
155
|
+
* and wiping the wallet removes the key itself (`Sphere.clear()`). Adding a
|
|
156
|
+
* per-entry delete would require revisiting this contract.
|
|
106
157
|
*/
|
|
107
158
|
saveTrackedAddresses(entries: TrackedAddressEntry[]): Promise<void>;
|
|
108
159
|
/**
|
|
109
|
-
* Load tracked addresses
|
|
160
|
+
* Load tracked addresses. Tolerant: unusable/corrupt storage reads as `[]`
|
|
161
|
+
* (see `parseTrackedAddresses` in `storage/tracked-addresses.ts`).
|
|
110
162
|
*/
|
|
111
163
|
loadTrackedAddresses(): Promise<TrackedAddressEntry[]>;
|
|
112
164
|
}
|
|
@@ -115,13 +167,14 @@ interface StorageProvider extends BaseProvider {
|
|
|
115
167
|
declare const NETWORKS: {
|
|
116
168
|
readonly mainnet: {
|
|
117
169
|
readonly name: "Mainnet";
|
|
118
|
-
readonly
|
|
119
|
-
readonly
|
|
170
|
+
readonly networkId: 1;
|
|
171
|
+
readonly aggregatorUrl: "https://gateway.mainnet.unicity.network";
|
|
172
|
+
readonly nostrRelays: readonly ["wss://nostr-relay.testnet.unicity.network"];
|
|
120
173
|
readonly groupRelays: readonly ["wss://sphere-relay.unicity.network"];
|
|
121
|
-
readonly tokenRegistryUrl: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.
|
|
174
|
+
readonly tokenRegistryUrl: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.mainnet.json";
|
|
122
175
|
};
|
|
123
176
|
readonly testnet: {
|
|
124
|
-
readonly name: "
|
|
177
|
+
readonly name: "Testnet";
|
|
125
178
|
readonly networkId: 4;
|
|
126
179
|
readonly aggregatorUrl: "https://gateway.testnet2.unicity.network";
|
|
127
180
|
readonly nostrRelays: readonly ["wss://nostr-relay.testnet.unicity.network"];
|
|
@@ -129,20 +182,13 @@ declare const NETWORKS: {
|
|
|
129
182
|
readonly tokenRegistryUrl: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.testnet2.json";
|
|
130
183
|
};
|
|
131
184
|
readonly testnet2: {
|
|
132
|
-
readonly name: "
|
|
185
|
+
readonly name: "Testnet";
|
|
133
186
|
readonly networkId: 4;
|
|
134
187
|
readonly aggregatorUrl: "https://gateway.testnet2.unicity.network";
|
|
135
188
|
readonly nostrRelays: readonly ["wss://nostr-relay.testnet.unicity.network"];
|
|
136
189
|
readonly groupRelays: readonly ["wss://sphere-relay.unicity.network"];
|
|
137
190
|
readonly tokenRegistryUrl: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.testnet2.json";
|
|
138
191
|
};
|
|
139
|
-
readonly dev: {
|
|
140
|
-
readonly name: "Development";
|
|
141
|
-
readonly aggregatorUrl: "https://dev-aggregator.dyndns.org/rpc";
|
|
142
|
-
readonly nostrRelays: readonly ["wss://nostr-relay.testnet.unicity.network"];
|
|
143
|
-
readonly groupRelays: readonly ["wss://sphere-relay.unicity.network"];
|
|
144
|
-
readonly tokenRegistryUrl: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.testnet.json";
|
|
145
|
-
};
|
|
146
192
|
};
|
|
147
193
|
type NetworkType = keyof typeof NETWORKS;
|
|
148
194
|
|
|
@@ -166,6 +212,8 @@ declare class FileStorageProvider implements StorageProvider {
|
|
|
166
212
|
readonly id = "file-storage";
|
|
167
213
|
readonly name = "File Storage";
|
|
168
214
|
readonly type: "local";
|
|
215
|
+
/** The resolved wallet file — two providers over one path share erasure (#766). */
|
|
216
|
+
readonly backingStoreId: string;
|
|
169
217
|
private dataDir;
|
|
170
218
|
private filePath;
|
|
171
219
|
private isTxtMode;
|
|
@@ -186,6 +234,26 @@ declare class FileStorageProvider implements StorageProvider {
|
|
|
186
234
|
has(key: string): Promise<boolean>;
|
|
187
235
|
keys(prefix?: string): Promise<string[]>;
|
|
188
236
|
clear(prefix?: string): Promise<void>;
|
|
237
|
+
/** Serializes the read-merge-write below, per provider instance. */
|
|
238
|
+
private trackedWrites;
|
|
239
|
+
/**
|
|
240
|
+
* Persist the tracked-address registry by MERGING, never replacing.
|
|
241
|
+
*
|
|
242
|
+
* Every Sphere over this storage holds its own snapshot and writes it in
|
|
243
|
+
* full, so a wholesale write drops the addresses this writer never saw
|
|
244
|
+
* (#766 item 5 — a lost update, reproducible on one network). Concurrent
|
|
245
|
+
* calls are serialized on `trackedWrites` so a read can never interleave
|
|
246
|
+
* with another call's write.
|
|
247
|
+
*
|
|
248
|
+
* Deliberately PER OBJECT, unlike the browser providers. Two objects over one
|
|
249
|
+
* `dataDir` share a `backingStoreId` but not this cache, and `save()` rewrites the
|
|
250
|
+
* WHOLE file from it — so a sibling's *unrelated* `set()` rolls the registry back
|
|
251
|
+
* regardless of how this one write is serialized. Sharing the chain here would make
|
|
252
|
+
* the cross-object contract case pass while leaving the provider unsafe. The real
|
|
253
|
+
* fix is #771 (refresh from disk under a per-file lock, on every write); until then
|
|
254
|
+
* `backingStoreId` scopes TEARDOWN only. Reviewers keep re-finding this — see the
|
|
255
|
+
* `unsupported:` note in tests/unit/storage/tracked-addresses-providers.test.ts.
|
|
256
|
+
*/
|
|
189
257
|
saveTrackedAddresses(entries: TrackedAddressEntry[]): Promise<void>;
|
|
190
258
|
loadTrackedAddresses(): Promise<TrackedAddressEntry[]>;
|
|
191
259
|
/**
|
|
@@ -584,6 +652,15 @@ declare class NostrTransportProvider implements TransportProvider {
|
|
|
584
652
|
suppressSubscriptions(): void;
|
|
585
653
|
private _subscriptionsSuppressed;
|
|
586
654
|
connect(): Promise<void>;
|
|
655
|
+
/**
|
|
656
|
+
* Race one client's relay connect against the configured timeout.
|
|
657
|
+
*
|
|
658
|
+
* The timer is cleared in a `finally` on EVERY path. `Promise.race` does not
|
|
659
|
+
* cancel the loser: an un-cleared `setTimeout` keeps Node's event loop pinned
|
|
660
|
+
* for the whole `config.timeout` after the call has already returned (and
|
|
661
|
+
* then rejects a promise nobody is listening to any more).
|
|
662
|
+
*/
|
|
663
|
+
private connectWithDeadline;
|
|
587
664
|
disconnect(): Promise<void>;
|
|
588
665
|
isConnected(): boolean;
|
|
589
666
|
getStatus(): ProviderStatus;
|
|
@@ -1545,7 +1622,7 @@ type NodeTransportConfig = BaseTransportConfig;
|
|
|
1545
1622
|
*/
|
|
1546
1623
|
type NodeOracleConfig = BaseOracleConfig & NodeOracleExtensions;
|
|
1547
1624
|
interface NodeProvidersConfig {
|
|
1548
|
-
/** Network preset: mainnet, testnet
|
|
1625
|
+
/** Network preset: mainnet, testnet or testnet2 */
|
|
1549
1626
|
network?: NetworkType;
|
|
1550
1627
|
/** Enable debug logging globally for all providers (default: false). Per-provider debug flags override this. */
|
|
1551
1628
|
debug?: boolean;
|