@unicitylabs/sphere-sdk 0.15.0 → 0.16.0-dev.1
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 +14 -23
- 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 +14 -23
- package/dist/connect/index.js.map +1 -1
- package/dist/core/index.cjs +726 -225
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +172 -21
- package/dist/core/index.d.ts +172 -21
- package/dist/core/index.js +726 -224
- package/dist/core/index.js.map +1 -1
- package/dist/impl/browser/connect/index.cjs +14 -23
- package/dist/impl/browser/connect/index.cjs.map +1 -1
- package/dist/impl/browser/connect/index.js +14 -23
- package/dist/impl/browser/connect/index.js.map +1 -1
- package/dist/impl/browser/index.cjs +331 -504
- package/dist/impl/browser/index.cjs.map +1 -1
- package/dist/impl/browser/index.js +331 -504
- package/dist/impl/browser/index.js.map +1 -1
- package/dist/impl/nodejs/connect/index.cjs +13 -22
- package/dist/impl/nodejs/connect/index.cjs.map +1 -1
- package/dist/impl/nodejs/connect/index.js +13 -22
- package/dist/impl/nodejs/connect/index.js.map +1 -1
- package/dist/impl/nodejs/index.cjs +298 -569
- package/dist/impl/nodejs/index.cjs.map +1 -1
- package/dist/impl/nodejs/index.d.cts +90 -13
- package/dist/impl/nodejs/index.d.ts +90 -13
- package/dist/impl/nodejs/index.js +298 -569
- 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 +728 -225
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +227 -108
- package/dist/index.d.ts +227 -108
- package/dist/index.js +728 -224
- 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
package/dist/index.d.cts
CHANGED
|
@@ -861,6 +861,25 @@ interface SphereStatus {
|
|
|
861
861
|
* All operations are async for platform flexibility
|
|
862
862
|
*/
|
|
863
863
|
interface StorageProvider extends BaseProvider {
|
|
864
|
+
/**
|
|
865
|
+
* Stable identity of the BACKING STORE this provider addresses — not of this
|
|
866
|
+
* object, and not of the class (`id` is a class constant like `'file-storage'`,
|
|
867
|
+
* which is exactly the wrong granularity).
|
|
868
|
+
*
|
|
869
|
+
* Two providers that return the SAME value address the same data, so erasing
|
|
870
|
+
* through one erases through the other: `Sphere.clear({ storage })` tears down
|
|
871
|
+
* the live Spheres of every provider sharing this value, not merely those built
|
|
872
|
+
* on this object. Compose it from everything that selects the store (file path,
|
|
873
|
+
* database name, key prefix) behind a scheme prefix, so two kinds of store can
|
|
874
|
+
* never collide on one string.
|
|
875
|
+
*
|
|
876
|
+
* It must not change over the provider's lifetime — it is read again on teardown,
|
|
877
|
+
* and a value that moved would strand the entry it was registered under.
|
|
878
|
+
*
|
|
879
|
+
* Optional: omit it and liveness falls back to per-object identity, i.e. a
|
|
880
|
+
* second provider over the same data is treated as unrelated.
|
|
881
|
+
*/
|
|
882
|
+
readonly backingStoreId?: string;
|
|
864
883
|
/**
|
|
865
884
|
* Set identity for scoped storage
|
|
866
885
|
*/
|
|
@@ -890,11 +909,44 @@ interface StorageProvider extends BaseProvider {
|
|
|
890
909
|
*/
|
|
891
910
|
clear(prefix?: string): Promise<void>;
|
|
892
911
|
/**
|
|
893
|
-
* Save tracked addresses (only user state: index, hidden, timestamps)
|
|
912
|
+
* Save tracked addresses (only user state: index, hidden, timestamps).
|
|
913
|
+
*
|
|
914
|
+
* MUST MERGE, NEVER REPLACE (#766 item 5). `entries` is ONE writer's snapshot,
|
|
915
|
+
* not the whole truth: every Sphere sharing this storage keeps its own copy of
|
|
916
|
+
* the registry and persists all of it, so writing the argument verbatim is a
|
|
917
|
+
* lost update — A activates index 1, B (whose snapshot predates that) activates
|
|
918
|
+
* index 2, and B's write erases index 1 while A still reports it. This happens
|
|
919
|
+
* on a single network with a single provider; do NOT "fix" it by renaming or
|
|
920
|
+
* network-scoping the key.
|
|
921
|
+
*
|
|
922
|
+
* The contract, implemented by `storage/tracked-addresses.ts` — reuse those
|
|
923
|
+
* helpers rather than re-deriving this:
|
|
924
|
+
* - read the stored registry, union it with `entries` BY `index`;
|
|
925
|
+
* - on a conflicting index, the entry with the greater `updatedAt` supplies
|
|
926
|
+
* `hidden`, and `createdAt` keeps the earlier value;
|
|
927
|
+
* - serialize concurrent calls on the provider instance, so one call's read
|
|
928
|
+
* cannot interleave with another's write;
|
|
929
|
+
* - a failed write must not brick later writes, and must still reject to its
|
|
930
|
+
* own caller.
|
|
931
|
+
*
|
|
932
|
+
* An `index` must be a UINT32 — a BIP32 child number. `deriveKeyAtPath` parseInt()s
|
|
933
|
+
* that path segment, so `1.5` derives index 1's keys and the row aliases a real
|
|
934
|
+
* address. The ceiling matters too: `deriveChildKey` pads the child number to 8 hex
|
|
935
|
+
* digits, so anything above `0xffffffff` emits extra bytes and derives off-standard.
|
|
936
|
+
* An `entries` row that is not one must REJECT the whole call (`mergeTrackedAddresses`
|
|
937
|
+
* throws `VALIDATION_ERROR`); dropping it silently on a write reports a save that
|
|
938
|
+
* never happened. Already-stored rows are dropped on READ instead, so one bad row
|
|
939
|
+
* cannot brick every later write. Validate before opening the write transaction if
|
|
940
|
+
* your platform would otherwise replace the reason with a generic abort.
|
|
941
|
+
*
|
|
942
|
+
* A union is safe because there is no delete path: entries are only ever added,
|
|
943
|
+
* and wiping the wallet removes the key itself (`Sphere.clear()`). Adding a
|
|
944
|
+
* per-entry delete would require revisiting this contract.
|
|
894
945
|
*/
|
|
895
946
|
saveTrackedAddresses(entries: TrackedAddressEntry[]): Promise<void>;
|
|
896
947
|
/**
|
|
897
|
-
* Load tracked addresses
|
|
948
|
+
* Load tracked addresses. Tolerant: unusable/corrupt storage reads as `[]`
|
|
949
|
+
* (see `parseTrackedAddresses` in `storage/tracked-addresses.ts`).
|
|
898
950
|
*/
|
|
899
951
|
loadTrackedAddresses(): Promise<TrackedAddressEntry[]>;
|
|
900
952
|
}
|
|
@@ -2002,8 +2054,12 @@ declare function getAddressStorageKey(addressId: string, key: string): string;
|
|
|
2002
2054
|
* @returns Sanitized identifier like "DIRECT_abc123_xyz789"
|
|
2003
2055
|
*/
|
|
2004
2056
|
declare function getAddressId(directAddress: string): string;
|
|
2005
|
-
/**
|
|
2006
|
-
|
|
2057
|
+
/**
|
|
2058
|
+
* Fallback Nostr relays, used only when no relay list is configured
|
|
2059
|
+
* (NostrTransportProvider / MultiAddressTransportMux). `relay.unicity.network`
|
|
2060
|
+
* was the v1 relay and no longer resolves, so it is not listed here.
|
|
2061
|
+
*/
|
|
2062
|
+
declare const DEFAULT_NOSTR_RELAYS: readonly ["wss://relay.damus.io", "wss://nos.lol", "wss://relay.nostr.band"];
|
|
2007
2063
|
/** Nostr event kinds used by SDK - must match @unicitylabs/nostr-js-sdk */
|
|
2008
2064
|
declare const NOSTR_EVENT_KINDS: {
|
|
2009
2065
|
/** NIP-04 encrypted direct message */
|
|
@@ -2051,7 +2107,12 @@ declare const NIP29_KINDS: {
|
|
|
2051
2107
|
/** Relay-signed group roles */
|
|
2052
2108
|
readonly GROUP_ROLES: 39003;
|
|
2053
2109
|
};
|
|
2054
|
-
/**
|
|
2110
|
+
/**
|
|
2111
|
+
* Default aggregator request timeout (ms)
|
|
2112
|
+
* Note: The aggregator is conceptually an oracle - a trusted service that provides
|
|
2113
|
+
* verifiable truth about token state through cryptographic inclusion proofs.
|
|
2114
|
+
* There is no default aggregator URL: every live network names its own gateway.
|
|
2115
|
+
*/
|
|
2055
2116
|
declare const DEFAULT_AGGREGATOR_TIMEOUT = 30000;
|
|
2056
2117
|
/** Default BIP32 derivation path (full path with chain/index) */
|
|
2057
2118
|
declare const DEFAULT_DERIVATION_PATH: "m/44'/0'/0'/0/0";
|
|
@@ -2068,10 +2129,11 @@ declare const DEFAULT_GROUP_RELAYS: readonly ["wss://sphere-relay.unicity.networ
|
|
|
2068
2129
|
declare const NETWORKS: {
|
|
2069
2130
|
readonly mainnet: {
|
|
2070
2131
|
readonly name: "Mainnet";
|
|
2071
|
-
readonly
|
|
2072
|
-
readonly
|
|
2132
|
+
readonly networkId: 1;
|
|
2133
|
+
readonly aggregatorUrl: "https://gateway.mainnet.unicity.network";
|
|
2134
|
+
readonly nostrRelays: readonly ["wss://nostr-relay.testnet.unicity.network"];
|
|
2073
2135
|
readonly groupRelays: readonly ["wss://sphere-relay.unicity.network"];
|
|
2074
|
-
readonly tokenRegistryUrl: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.
|
|
2136
|
+
readonly tokenRegistryUrl: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.mainnet.json";
|
|
2075
2137
|
};
|
|
2076
2138
|
readonly testnet: {
|
|
2077
2139
|
readonly name: "Testnet2";
|
|
@@ -2089,13 +2151,6 @@ declare const NETWORKS: {
|
|
|
2089
2151
|
readonly groupRelays: readonly ["wss://sphere-relay.unicity.network"];
|
|
2090
2152
|
readonly tokenRegistryUrl: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.testnet2.json";
|
|
2091
2153
|
};
|
|
2092
|
-
readonly dev: {
|
|
2093
|
-
readonly name: "Development";
|
|
2094
|
-
readonly aggregatorUrl: "https://dev-aggregator.dyndns.org/rpc";
|
|
2095
|
-
readonly nostrRelays: readonly ["wss://nostr-relay.testnet.unicity.network"];
|
|
2096
|
-
readonly groupRelays: readonly ["wss://sphere-relay.unicity.network"];
|
|
2097
|
-
readonly tokenRegistryUrl: "https://raw.githubusercontent.com/unicitynetwork/unicity-ids/refs/heads/main/unicity-ids.testnet.json";
|
|
2098
|
-
};
|
|
2099
2154
|
};
|
|
2100
2155
|
type NetworkType = keyof typeof NETWORKS;
|
|
2101
2156
|
/** Default timeouts (ms) */
|
|
@@ -2964,9 +3019,26 @@ interface SphereInitResult {
|
|
|
2964
3019
|
generatedMnemonic?: string;
|
|
2965
3020
|
}
|
|
2966
3021
|
declare class Sphere {
|
|
2967
|
-
private static
|
|
3022
|
+
private static readonly _liveByStorage;
|
|
3023
|
+
/** Fallback keys for providers that declare no `backingStoreId` — one per object. */
|
|
3024
|
+
private static readonly _objectStoreKeys;
|
|
3025
|
+
/**
|
|
3026
|
+
* How many times each backing store has been cleared. An init is invisible to `clear()`
|
|
3027
|
+
* until it PUBLISHES (#767), so a clear cannot destroy one in flight and would wipe the
|
|
3028
|
+
* store under it. Every init records this number before its first storage work and
|
|
3029
|
+
* publication refuses if it moved (#772). Only cleared stores get an entry, so the
|
|
3030
|
+
* strongly-held keys are bounded by the stores a process actually clears.
|
|
3031
|
+
*/
|
|
3032
|
+
private static readonly _clearGenerations;
|
|
2968
3033
|
private static _orphanCacheCleaned;
|
|
2969
3034
|
private _initialized;
|
|
3035
|
+
/**
|
|
3036
|
+
* Destroyed latch (#770). Distinct from `_initialized`, which destroy() clears LAST — after
|
|
3037
|
+
* every teardown step — so it cannot mark "teardown has begun". This is set as destroy()'s
|
|
3038
|
+
* very FIRST statement, so the WHOLE teardown window is guarded, not just the instant after
|
|
3039
|
+
* it. Read by ensureAlive() and by the §7 lifecycle mutex.
|
|
3040
|
+
*/
|
|
3041
|
+
private _destroyed;
|
|
2970
3042
|
private _trackedAddressesLoaded;
|
|
2971
3043
|
private _identity;
|
|
2972
3044
|
private _masterKey;
|
|
@@ -3019,6 +3091,8 @@ declare class Sphere {
|
|
|
3019
3091
|
* the rebuild after an api-key change share one pool configuration.
|
|
3020
3092
|
*/
|
|
3021
3093
|
private _verification;
|
|
3094
|
+
/** This Sphere's OWN token registry. Disposed by destroy(); never the process global. */
|
|
3095
|
+
private _registry;
|
|
3022
3096
|
private eventHandlers;
|
|
3023
3097
|
private _disabledProviders;
|
|
3024
3098
|
private _providerEventCleanups;
|
|
@@ -3090,6 +3164,23 @@ declare class Sphere {
|
|
|
3090
3164
|
* bundle). This method ensures the main bundle's TokenRegistry is configured.
|
|
3091
3165
|
*/
|
|
3092
3166
|
private static configureTokenRegistry;
|
|
3167
|
+
/**
|
|
3168
|
+
* Build the registry THIS Sphere owns, so its metadata cannot be repointed by another
|
|
3169
|
+
* Sphere's init. The global is still configured above for consumers that read it
|
|
3170
|
+
* directly; this instance is what the payments facade presents from.
|
|
3171
|
+
*/
|
|
3172
|
+
/**
|
|
3173
|
+
* Own a registry for the duration of `bringUp`, disposing it if any of that rejects.
|
|
3174
|
+
*
|
|
3175
|
+
* `bringUp` must cover EVERY fallible step from here until the Sphere is returned to
|
|
3176
|
+
* its caller — until then nobody holds anything they could destroy, so a
|
|
3177
|
+
* registry left behind is unreachable and its hourly fetch runs for the life of the
|
|
3178
|
+
* process. Guarding a named subset of the steps is what failed twice: the guarded region
|
|
3179
|
+
* and the fallible region were separate things, and drifted. Publication is the LAST
|
|
3180
|
+
* guarded step for the same reason: it can refuse, and a refusal must tear down.
|
|
3181
|
+
*/
|
|
3182
|
+
private static withOwnedRegistry;
|
|
3183
|
+
private static createOwnedRegistry;
|
|
3093
3184
|
/**
|
|
3094
3185
|
* Create new wallet with mnemonic
|
|
3095
3186
|
*/
|
|
@@ -3118,6 +3209,7 @@ declare class Sphere {
|
|
|
3118
3209
|
static clear(options: {
|
|
3119
3210
|
storage: StorageProvider;
|
|
3120
3211
|
}): Promise<void>;
|
|
3212
|
+
private static clearStore;
|
|
3121
3213
|
/**
|
|
3122
3214
|
* Raw `indexedDB.deleteDatabase` sweep of `sphere-token-storage-*` databases
|
|
3123
3215
|
* left by pre-flip versions (tokens are server-custody now). Browser-only,
|
|
@@ -3132,13 +3224,27 @@ declare class Sphere {
|
|
|
3132
3224
|
*/
|
|
3133
3225
|
private static cleanupOrphanedVestingCache;
|
|
3134
3226
|
/**
|
|
3135
|
-
*
|
|
3227
|
+
* The key a provider registers under: the store it addresses, so every provider
|
|
3228
|
+
* over one dataDir/DB shares an entry. A provider that declares no store keeps a
|
|
3229
|
+
* private key, leaving custom implementations scoped by object identity.
|
|
3136
3230
|
*/
|
|
3137
|
-
static
|
|
3231
|
+
private static storeKeyOf;
|
|
3232
|
+
/** The clears this store has seen. Absent means none — `clear()` creates the entry. */
|
|
3233
|
+
private static clearGenerationOf;
|
|
3234
|
+
private static bumpClearGeneration;
|
|
3138
3235
|
/**
|
|
3139
|
-
*
|
|
3236
|
+
* Make a fully-built Sphere reachable — or refuse, if `clear()` emptied the store
|
|
3237
|
+
* under it while it was building. Check and registration are one SYNCHRONOUS step on
|
|
3238
|
+
* purpose: split by an await, a clear could land between them and wipe a store whose
|
|
3239
|
+
* Sphere is already published. The refusal throws inside `withOwnedRegistry`, whose
|
|
3240
|
+
* teardown then destroys the half-built Sphere the caller never received.
|
|
3140
3241
|
*/
|
|
3141
|
-
static
|
|
3242
|
+
private static publishLive;
|
|
3243
|
+
/** Record a fully-built Sphere against the storage it owns. See `_liveByStorage`. */
|
|
3244
|
+
private static registerLive;
|
|
3245
|
+
private static unregisterLive;
|
|
3246
|
+
/** Snapshot — callers iterate this while destroy() mutates the underlying Set. */
|
|
3247
|
+
private static liveOn;
|
|
3142
3248
|
/**
|
|
3143
3249
|
* Validate mnemonic using BIP39
|
|
3144
3250
|
*/
|
|
@@ -3307,7 +3413,8 @@ declare class Sphere {
|
|
|
3307
3413
|
/**
|
|
3308
3414
|
* Import wallet from JSON backup
|
|
3309
3415
|
*
|
|
3310
|
-
* @returns
|
|
3416
|
+
* @returns `{ success, sphere?, mnemonic?, error? }`. `sphere` is the instance built
|
|
3417
|
+
* on the SUPPLIED storage — hold it, there is no global to look it up from (#766).
|
|
3311
3418
|
*
|
|
3312
3419
|
* @example
|
|
3313
3420
|
* ```ts
|
|
@@ -3324,6 +3431,7 @@ declare class Sphere {
|
|
|
3324
3431
|
password?: string;
|
|
3325
3432
|
}): Promise<{
|
|
3326
3433
|
success: boolean;
|
|
3434
|
+
sphere?: Sphere;
|
|
3327
3435
|
mnemonic?: string;
|
|
3328
3436
|
error?: string;
|
|
3329
3437
|
}>;
|
|
@@ -3423,6 +3531,18 @@ declare class Sphere {
|
|
|
3423
3531
|
* independently in background. The payments vertical is NOT created here —
|
|
3424
3532
|
* the caller starts it via stopThenStartPaymentsV2 (§7 single vertical).
|
|
3425
3533
|
*/
|
|
3534
|
+
/** Tear one address's module set down. Each address owns its own engine, so its own pool. */
|
|
3535
|
+
private static destroyModuleSet;
|
|
3536
|
+
/**
|
|
3537
|
+
* Undo a module set built while `destroy()` was running.
|
|
3538
|
+
*
|
|
3539
|
+
* `destroy()`'s teardown loop has already emptied `_addressModules`, so a set
|
|
3540
|
+
* registered after it would stay live and unreachable — its own engine (and worker
|
|
3541
|
+
* pool), and a transport mux `ensureTransportMux` rebuilt because teardown had just
|
|
3542
|
+
* nulled the field. Then re-raise, so the switch fails rather than reporting success
|
|
3543
|
+
* on a destroyed Sphere (#770, #772 review).
|
|
3544
|
+
*/
|
|
3545
|
+
private discardModulesBuiltDuringDestroy;
|
|
3426
3546
|
private initializeAddressModules;
|
|
3427
3547
|
/**
|
|
3428
3548
|
* Ensure the transport multiplexer exists and register an address.
|
|
@@ -3431,6 +3551,8 @@ declare class Sphere {
|
|
|
3431
3551
|
* @returns AddressTransportAdapter or null if transport is not Nostr-based
|
|
3432
3552
|
*/
|
|
3433
3553
|
private ensureTransportMux;
|
|
3554
|
+
/** A BIP32 child number: an integer in 0…0xffffffff. Anything else aliases an address. */
|
|
3555
|
+
private static assertDerivableIndex;
|
|
3434
3556
|
/**
|
|
3435
3557
|
* Derive address at a specific index
|
|
3436
3558
|
*
|
|
@@ -3669,6 +3791,29 @@ declare class Sphere {
|
|
|
3669
3791
|
* Strip @ prefix and normalize a nametag (lowercase, phone E.164, strip @unicity suffix).
|
|
3670
3792
|
*/
|
|
3671
3793
|
private cleanNametag;
|
|
3794
|
+
/**
|
|
3795
|
+
* Disconnect transport, storage and oracle, attempting each even if an earlier one
|
|
3796
|
+
* rejects. They are separate resources, and one failure must not skip the rest — that
|
|
3797
|
+
* is how a partial teardown leaves connections open, which is exactly the state the
|
|
3798
|
+
* failed-initialization path calls destroy() in.
|
|
3799
|
+
*/
|
|
3800
|
+
private disconnectProvidersIndependently;
|
|
3801
|
+
/** Run one teardown step, logging rather than propagating so the next one still runs. */
|
|
3802
|
+
private static safeDisconnect;
|
|
3803
|
+
/**
|
|
3804
|
+
* Tear this Sphere down: stop the vertical, destroy the modules, disconnect the providers
|
|
3805
|
+
* and zero the key material. Idempotent by construction (every step is null-guarded) and
|
|
3806
|
+
* deliberately WITHOUT an early return on re-entry, which would change what a double call
|
|
3807
|
+
* means.
|
|
3808
|
+
*
|
|
3809
|
+
* #770: the FIRST statement flips `_destroyed` — before any await, and before this queues
|
|
3810
|
+
* its own stop on the §7 lifecycle mutex. That position is load-bearing. Every guard reads
|
|
3811
|
+
* the flag, so from that instant any switchToAddress step not yet begun refuses; and
|
|
3812
|
+
* because it flips SYNCHRONOUSLY at entry, a stop/start pair the mutex runs after this call
|
|
3813
|
+
* sees `true` and skips its start. Set it beside `_initialized` at the bottom instead and a
|
|
3814
|
+
* concurrent switch re-arms a wallet whose owner already had destroy() return: fresh
|
|
3815
|
+
* sockets, a fresh wallet-api session, a whole fresh vertical nothing will ever stop.
|
|
3816
|
+
*/
|
|
3672
3817
|
destroy(): Promise<void>;
|
|
3673
3818
|
private storeMnemonic;
|
|
3674
3819
|
private storeMasterKey;
|
|
@@ -3706,7 +3851,17 @@ declare class Sphere {
|
|
|
3706
3851
|
private initializeModules;
|
|
3707
3852
|
/** §7 mutex: run one stop/start lifecycle op after all queued ones settle. */
|
|
3708
3853
|
private queuePaymentsV2Op;
|
|
3709
|
-
/**
|
|
3854
|
+
/**
|
|
3855
|
+
* Switch/boot: stop whatever runs, then start `index`'s vertical — atomically vs other
|
|
3856
|
+
* lifecycle ops.
|
|
3857
|
+
*
|
|
3858
|
+
* #770: the destroyed check between the two halves settles the FACADE vector on its own.
|
|
3859
|
+
* `_destroyed` flips synchronously at destroy() entry, so any closure that BEGINS executing
|
|
3860
|
+
* after destroy() was called sees `true`, and any closure already past the check has
|
|
3861
|
+
* facade.start() in flight — which destroy()'s own queued stop is necessarily ordered
|
|
3862
|
+
* after. The TRANSPORT vector is not on this mutex at all; the ensureAlive() calls in
|
|
3863
|
+
* switchToAddress are what cover it.
|
|
3864
|
+
*/
|
|
3710
3865
|
private stopThenStartPaymentsV2;
|
|
3711
3866
|
/**
|
|
3712
3867
|
* Compose + start the payments vertical for ONE address (the §7 rule:
|
|
@@ -3717,6 +3872,12 @@ declare class Sphere {
|
|
|
3717
3872
|
private startPaymentsV2Inner;
|
|
3718
3873
|
/** P9 §7: stop the active vertical and await quiescence (in-flight ops settle). */
|
|
3719
3874
|
private stopPaymentsV2Inner;
|
|
3875
|
+
/**
|
|
3876
|
+
* Refuse once destroy() has STARTED (#770). `_initialized` cannot carry this: destroy()
|
|
3877
|
+
* clears it last, so every teardown step is a window in which a concurrent call still reads
|
|
3878
|
+
* a ready Sphere and re-arms it.
|
|
3879
|
+
*/
|
|
3880
|
+
private ensureAlive;
|
|
3720
3881
|
private ensureReady;
|
|
3721
3882
|
private emitEvent;
|
|
3722
3883
|
private encrypt;
|
|
@@ -3725,7 +3886,6 @@ declare class Sphere {
|
|
|
3725
3886
|
declare const createSphere: typeof Sphere.create;
|
|
3726
3887
|
declare const loadSphere: typeof Sphere.load;
|
|
3727
3888
|
declare const initSphere: typeof Sphere.init;
|
|
3728
|
-
declare const getSphere: typeof Sphere.getInstance;
|
|
3729
3889
|
declare const sphereExists: typeof Sphere.exists;
|
|
3730
3890
|
|
|
3731
3891
|
/**
|
|
@@ -4241,7 +4401,7 @@ interface TokenDefinition {
|
|
|
4241
4401
|
/**
|
|
4242
4402
|
* Network type for registry lookup
|
|
4243
4403
|
*/
|
|
4244
|
-
type RegistryNetwork = 'testnet' | '
|
|
4404
|
+
type RegistryNetwork = 'testnet' | 'testnet2' | 'mainnet';
|
|
4245
4405
|
/**
|
|
4246
4406
|
* Configuration options for remote registry refresh
|
|
4247
4407
|
*/
|
|
@@ -4275,7 +4435,7 @@ interface TokenRegistryConfig {
|
|
|
4275
4435
|
*
|
|
4276
4436
|
* // Usually called automatically by createBrowserProviders / createNodeProviders
|
|
4277
4437
|
* TokenRegistry.configure({
|
|
4278
|
-
* remoteUrl: 'https://raw.githubusercontent.com/.../unicity-ids.
|
|
4438
|
+
* remoteUrl: 'https://raw.githubusercontent.com/.../unicity-ids.testnet2.json',
|
|
4279
4439
|
* storage: myStorageProvider,
|
|
4280
4440
|
* });
|
|
4281
4441
|
*
|
|
@@ -4296,6 +4456,12 @@ declare class TokenRegistry {
|
|
|
4296
4456
|
private lastRefreshAt;
|
|
4297
4457
|
private refreshPromise;
|
|
4298
4458
|
private initialLoadPromise;
|
|
4459
|
+
/** Bumped on every remoteUrl change; loads started in an older generation are discarded. */
|
|
4460
|
+
private generation;
|
|
4461
|
+
/** Set by dispose(). A disposed registry starts no work and applies no late result. */
|
|
4462
|
+
private disposed;
|
|
4463
|
+
/** Cancels the in-flight fetch (and its abort timer) when the registry is disposed. */
|
|
4464
|
+
private inFlight;
|
|
4299
4465
|
private constructor();
|
|
4300
4466
|
/**
|
|
4301
4467
|
* Get singleton instance of TokenRegistry
|
|
@@ -4315,6 +4481,29 @@ declare class TokenRegistry {
|
|
|
4315
4481
|
* @param options.autoRefresh - Start auto-refresh immediately (default: true)
|
|
4316
4482
|
*/
|
|
4317
4483
|
static configure(options: TokenRegistryConfig): void;
|
|
4484
|
+
/**
|
|
4485
|
+
* Create an INDEPENDENT registry, not the process-global singleton.
|
|
4486
|
+
*
|
|
4487
|
+
* One Sphere owns one of these, so two Spheres on different networks cannot wipe each
|
|
4488
|
+
* other's definitions — the singleton's `configure()` reaches into whatever instance
|
|
4489
|
+
* exists and repoints it, which is how a mainnet init silently retargeted a live
|
|
4490
|
+
* testnet2 wallet's decimals. Dispose it when the owner is destroyed.
|
|
4491
|
+
*/
|
|
4492
|
+
static create(options: TokenRegistryConfig): TokenRegistry;
|
|
4493
|
+
/** The body of configure(), on the instance, so owned registries share it exactly. */
|
|
4494
|
+
private applyConfig;
|
|
4495
|
+
/**
|
|
4496
|
+
* Stop this registry for good: no timer, no late apply, no late cache write.
|
|
4497
|
+
*
|
|
4498
|
+
* Sphere.destroy() calls this on the registry it owns. Without it a discarded Sphere
|
|
4499
|
+
* leaves an hourly fetch running forever — nothing in this file calls unref(), so in
|
|
4500
|
+
* Node it also keeps the event loop alive.
|
|
4501
|
+
*/
|
|
4502
|
+
dispose(): void;
|
|
4503
|
+
/** Whether dispose() has been called. Reads still work; they are simply frozen. */
|
|
4504
|
+
get isDisposed(): boolean;
|
|
4505
|
+
/** Per-instance readiness — the same contract as the static, for an owned registry. */
|
|
4506
|
+
waitForReady(timeoutMs?: number): Promise<boolean>;
|
|
4318
4507
|
/**
|
|
4319
4508
|
* Reset the singleton instance (useful for testing).
|
|
4320
4509
|
* Stops auto-refresh if running.
|
|
@@ -4369,6 +4558,14 @@ declare class TokenRegistry {
|
|
|
4369
4558
|
* Concurrent calls are deduplicated — only one fetch runs at a time.
|
|
4370
4559
|
*/
|
|
4371
4560
|
refreshFromRemote(): Promise<boolean>;
|
|
4561
|
+
/**
|
|
4562
|
+
* Fetch with a bounded timeout, exposing a cancel hook to dispose().
|
|
4563
|
+
*
|
|
4564
|
+
* Both the request and its abort timer keep Node's event loop alive for the full
|
|
4565
|
+
* FETCH_TIMEOUT_MS, so a registry disposed mid-flight must cancel them rather than
|
|
4566
|
+
* merely ignore the result.
|
|
4567
|
+
*/
|
|
4568
|
+
private fetchCancellable;
|
|
4372
4569
|
private doRefresh;
|
|
4373
4570
|
/**
|
|
4374
4571
|
* Start periodic auto-refresh from the remote URL.
|
|
@@ -4460,99 +4657,21 @@ declare class TokenRegistry {
|
|
|
4460
4657
|
*/
|
|
4461
4658
|
getCoinIdByName(name: string): string | undefined;
|
|
4462
4659
|
}
|
|
4660
|
+
|
|
4463
4661
|
/**
|
|
4464
|
-
*
|
|
4465
|
-
*
|
|
4466
|
-
* @returns Token definition or undefined
|
|
4662
|
+
* Readers bound to the PROCESS-GLOBAL registry: with two Spheres alive they answer for
|
|
4663
|
+
* whichever network configured it last. Prefer a Sphere-owned registry when it matters.
|
|
4467
4664
|
*/
|
|
4665
|
+
|
|
4468
4666
|
declare function getTokenDefinition(coinId: string): TokenDefinition | undefined;
|
|
4469
|
-
/**
|
|
4470
|
-
* Get token symbol by coin ID
|
|
4471
|
-
* @param coinId - 64-character hex string
|
|
4472
|
-
* @returns Symbol or truncated ID
|
|
4473
|
-
*/
|
|
4474
4667
|
declare function getTokenSymbol(coinId: string): string;
|
|
4475
|
-
/**
|
|
4476
|
-
* Get token name by coin ID
|
|
4477
|
-
* @param coinId - 64-character hex string
|
|
4478
|
-
* @returns Name or coin ID
|
|
4479
|
-
*/
|
|
4480
4668
|
declare function getTokenName(coinId: string): string;
|
|
4481
|
-
/**
|
|
4482
|
-
* Get token decimals by coin ID
|
|
4483
|
-
* @param coinId - 64-character hex string
|
|
4484
|
-
* @returns Decimals or 0
|
|
4485
|
-
*/
|
|
4486
4669
|
declare function getTokenDecimals(coinId: string): number;
|
|
4487
|
-
/**
|
|
4488
|
-
* Get token icon URL by coin ID
|
|
4489
|
-
* @param coinId - 64-character hex string
|
|
4490
|
-
* @param preferPng - Prefer PNG over SVG
|
|
4491
|
-
* @returns Icon URL or null
|
|
4492
|
-
*/
|
|
4493
4670
|
declare function getTokenIconUrl(coinId: string, preferPng?: boolean): string | null;
|
|
4494
|
-
/**
|
|
4495
|
-
* Check if coin ID is in registry
|
|
4496
|
-
* @param coinId - 64-character hex string
|
|
4497
|
-
* @returns true if known
|
|
4498
|
-
*/
|
|
4499
4671
|
declare function isKnownToken(coinId: string): boolean;
|
|
4500
|
-
/**
|
|
4501
|
-
* Get coin ID by symbol
|
|
4502
|
-
* @param symbol - Token symbol (e.g., "UCT")
|
|
4503
|
-
* @returns Coin ID or undefined
|
|
4504
|
-
*/
|
|
4505
4672
|
declare function getCoinIdBySymbol(symbol: string): string | undefined;
|
|
4506
|
-
/**
|
|
4507
|
-
* Get coin ID by name
|
|
4508
|
-
* @param name - Token name (e.g., "bitcoin")
|
|
4509
|
-
* @returns Coin ID or undefined
|
|
4510
|
-
*/
|
|
4511
4673
|
declare function getCoinIdByName(name: string): string | undefined;
|
|
4512
|
-
/**
|
|
4513
|
-
* Normalize a coin identifier to its canonical hash coinId.
|
|
4514
|
-
*
|
|
4515
|
-
* Accepts both symbolic names ("BTC", "ETH") and hash coinIds (64-char hex).
|
|
4516
|
-
* If the input is a short symbol, resolves it via the TokenRegistry.
|
|
4517
|
-
* Returns the input unchanged if it's already a hash coinId or unknown.
|
|
4518
|
-
*
|
|
4519
|
-
* @public
|
|
4520
|
-
*
|
|
4521
|
-
* @remarks
|
|
4522
|
-
* Heuristic: inputs matching `length <= 20 && /^[A-Za-z0-9]+$/` are treated
|
|
4523
|
-
* as symbolic names and looked up in the registry. Long inputs, hyphenated
|
|
4524
|
-
* inputs ("TOKEN-123"), or dotted inputs ("BTC.CASH") pass through unchanged.
|
|
4525
|
-
*
|
|
4526
|
-
* **Stability:** This function depends on `TokenRegistry` content. Adding a
|
|
4527
|
-
* new symbol that shadows a previously-unknown short alphanumeric coinId
|
|
4528
|
-
* changes normalization semantics retroactively. Consumers building stable
|
|
4529
|
-
* keys against this output should be aware that registry growth is a
|
|
4530
|
-
* non-breaking change *for unknown inputs* but a breaking change *for inputs
|
|
4531
|
-
* that newly resolve*.
|
|
4532
|
-
*
|
|
4533
|
-
* @param coinId - A symbolic name or hash coinId.
|
|
4534
|
-
* @returns The canonical hash coinId, or the original string if not resolvable.
|
|
4535
|
-
*/
|
|
4536
4674
|
declare function normalizeCoinId(coinId: string): string;
|
|
4537
|
-
/**
|
|
4538
|
-
* Compare two coin identifiers for equality, normalizing both sides.
|
|
4539
|
-
*
|
|
4540
|
-
* Handles mixed-format comparisons: "BTC" vs hash coinId, or two hash coinIds.
|
|
4541
|
-
* Both values are normalized to hash coinIds via the TokenRegistry before comparison.
|
|
4542
|
-
*
|
|
4543
|
-
* @public
|
|
4544
|
-
*
|
|
4545
|
-
* @remarks
|
|
4546
|
-
* Reflexive byte-equality short-circuit comes first; otherwise both sides
|
|
4547
|
-
* are normalized via {@link normalizeCoinId} and compared. Inherits the
|
|
4548
|
-
* registry-dependence caveat from `normalizeCoinId`. Two distinct symbols
|
|
4549
|
-
* that both fail to resolve will compare unequal even if they're semantic
|
|
4550
|
-
* aliases — register them as aliases in `TokenRegistry` for matching.
|
|
4551
|
-
*
|
|
4552
|
-
* @param a - First coin identifier (symbol or hash coinId).
|
|
4553
|
-
* @param b - Second coin identifier (symbol or hash coinId).
|
|
4554
|
-
* @returns true if both resolve to the same canonical coinId.
|
|
4555
|
-
*/
|
|
4556
4675
|
declare function coinIdsMatch(a: string, b: string): boolean;
|
|
4557
4676
|
|
|
4558
4677
|
/**
|
|
@@ -4618,4 +4737,4 @@ declare function normalizeAddress(address: string): string;
|
|
|
4618
4737
|
*/
|
|
4619
4738
|
declare function addressesMatch(a: string, b: string): boolean;
|
|
4620
4739
|
|
|
4621
|
-
export { AUTH_CHALLENGE_PREFIX, type AddressInfo, type AddressType, type AggregatorEvent, type AggregatorEventCallback, type AggregatorEventType, type AggregatorProvider, type Asset, type BaseProvider, type BroadcastHandler, type BroadcastMessage, COIN_TYPES, ChallengeTemplateError, type CheckNetworkHealthOptions, CoinGeckoPriceProvider, CommunicationsModule, type CommunicationsModuleConfig, type CommunicationsModuleDependencies, type ComposingIndicator, type ConversationPage, type CreateGroupOptions, DEFAULT_AGGREGATOR_TIMEOUT, DEFAULT_DERIVATION_PATH, DEFAULT_GROUP_RELAYS, DEFAULT_MARKET_API_URL, DEFAULT_NOSTR_RELAYS, type DecryptionProgressCallback, type DerivationMode, type DirectMessage, type DiscoverAddressProgress, type DiscoverAddressesOptions, type DiscoverAddressesResult, type DiscoveredAddress, type EncryptedData, FIELD_ENCRYPTION_HKDF_INFO, FIELD_ENVELOPE_MAX_BYTES, FIELD_ENVELOPE_NONCE_BYTES, FIELD_ENVELOPE_PREFIX, type FullIdentity, type GetConversationPageOptions, GroupChatModule, type GroupChatModuleConfig, type GroupChatModuleDependencies, type GroupData, type GroupMemberData, type GroupMessageData, GroupRole, GroupVisibility, type HealthCheckFn, type HistoryRecord, type Identity, type IdentityConfig, type IncomingBroadcast, type IncomingMessage, type IncomingTransfer, type InitProgress, type InitProgressCallback, type InitProgressStep, type IntentStatus, type IntentType, LIMITS, type LegacyFileParseResult, type LegacyFileParsedData, type LegacyFileType, type LogHandler, type LogLevel, type LoggerConfig, type MarketIntent, MarketModule, type MarketModuleConfig, type MarketModuleDependencies, type MessageHandler, NETWORKS, NIP29_KINDS, NOSTR_EVENT_KINDS, type NetworkHealthResult, type NetworkType, type OracleEvent, type OracleEventCallback, type OracleEventType, type OracleProvider, type ParsedAddress, PartialSendConflictError, type PeerInfo, type PostIntentRequest, type PostIntentResult, type PricePlatform, type PriceProvider, type PriceProviderConfig, type ProviderMetadata, type ProviderRole, type ProviderStatus, type ProviderStatusInfo, type RegistryNetwork, SIGN_MESSAGE_PREFIX, STORAGE_KEYS_ADDRESS, STORAGE_KEYS_GLOBAL, STORAGE_PREFIX, type SearchFilters, type SearchIntentResult, type SearchOptions, type SearchResult, type ServiceHealthResult, Sphere, type SphereCreateOptions, SphereError, type SphereErrorCode, type SphereEventHandler, type SphereEventMap, type SphereEventType, type SphereImportOptions, type SphereInitOptions, type SphereInitResult, type SphereLoadOptions, type SphereStatus, type StorageProvider, TEST_NOSTR_RELAYS, TIMEOUTS, type Token, type TokenDefinition, type TokenIcon, type TokenPrice, TokenRegistry, type TokenStatus, type TokenTransferDetail, type TrackedAddress, type TrackedAddressEntry, type HistoryRecord as TransactionHistoryEntry, type TransferRequest, type TransferResult, type TransferStatus, type TransportEvent, type TransportEventCallback, type TransportEventType, type TransportProvider, type WalletApiTransportConfig, type WalletInfo, type WalletJSON, type WalletJSONExportOptions, type WalletSource, addressesMatch, assertFieldEnvelopeShape, base58Decode, base58Encode, bytesToHex, checkNetworkHealth, coinIdsMatch, createCommunicationsModule, createGroupChatModule, createKeyPair, createMarketModule, createPriceProvider, createSphere, decrypt, decryptField, decryptFieldBytes, decryptJson, decryptMnemonic, decryptSimple, decryptTextFormatKey, decryptWithSalt, deriveAddressInfo, deriveChildKey, deriveFieldEncryptionKey, deriveKeyAtPath, doubleSha256, encrypt, encryptField, encryptFieldBytes, encryptMnemonic, encryptSimple, extractFromText, findPattern, formatAmount, generateAddressFromMasterKey, generateMasterKey, generateMnemonic, getAddressId, getAddressStorageKey, getCoinIdByName, getCoinIdBySymbol, getPublicKey,
|
|
4740
|
+
export { AUTH_CHALLENGE_PREFIX, type AddressInfo, type AddressType, type AggregatorEvent, type AggregatorEventCallback, type AggregatorEventType, type AggregatorProvider, type Asset, type BaseProvider, type BroadcastHandler, type BroadcastMessage, COIN_TYPES, ChallengeTemplateError, type CheckNetworkHealthOptions, CoinGeckoPriceProvider, CommunicationsModule, type CommunicationsModuleConfig, type CommunicationsModuleDependencies, type ComposingIndicator, type ConversationPage, type CreateGroupOptions, DEFAULT_AGGREGATOR_TIMEOUT, DEFAULT_DERIVATION_PATH, DEFAULT_GROUP_RELAYS, DEFAULT_MARKET_API_URL, DEFAULT_NOSTR_RELAYS, type DecryptionProgressCallback, type DerivationMode, type DirectMessage, type DiscoverAddressProgress, type DiscoverAddressesOptions, type DiscoverAddressesResult, type DiscoveredAddress, type EncryptedData, FIELD_ENCRYPTION_HKDF_INFO, FIELD_ENVELOPE_MAX_BYTES, FIELD_ENVELOPE_NONCE_BYTES, FIELD_ENVELOPE_PREFIX, type FullIdentity, type GetConversationPageOptions, GroupChatModule, type GroupChatModuleConfig, type GroupChatModuleDependencies, type GroupData, type GroupMemberData, type GroupMessageData, GroupRole, GroupVisibility, type HealthCheckFn, type HistoryRecord, type Identity, type IdentityConfig, type IncomingBroadcast, type IncomingMessage, type IncomingTransfer, type InitProgress, type InitProgressCallback, type InitProgressStep, type IntentStatus, type IntentType, LIMITS, type LegacyFileParseResult, type LegacyFileParsedData, type LegacyFileType, type LogHandler, type LogLevel, type LoggerConfig, type MarketIntent, MarketModule, type MarketModuleConfig, type MarketModuleDependencies, type MessageHandler, NETWORKS, NIP29_KINDS, NOSTR_EVENT_KINDS, type NetworkHealthResult, type NetworkType, type OracleEvent, type OracleEventCallback, type OracleEventType, type OracleProvider, type ParsedAddress, PartialSendConflictError, type PeerInfo, type PostIntentRequest, type PostIntentResult, type PricePlatform, type PriceProvider, type PriceProviderConfig, type ProviderMetadata, type ProviderRole, type ProviderStatus, type ProviderStatusInfo, type RegistryNetwork, SIGN_MESSAGE_PREFIX, STORAGE_KEYS_ADDRESS, STORAGE_KEYS_GLOBAL, STORAGE_PREFIX, type SearchFilters, type SearchIntentResult, type SearchOptions, type SearchResult, type ServiceHealthResult, Sphere, type SphereCreateOptions, SphereError, type SphereErrorCode, type SphereEventHandler, type SphereEventMap, type SphereEventType, type SphereImportOptions, type SphereInitOptions, type SphereInitResult, type SphereLoadOptions, type SphereStatus, type StorageProvider, TEST_NOSTR_RELAYS, TIMEOUTS, type Token, type TokenDefinition, type TokenIcon, type TokenPrice, TokenRegistry, type TokenStatus, type TokenTransferDetail, type TrackedAddress, type TrackedAddressEntry, type HistoryRecord as TransactionHistoryEntry, type TransferRequest, type TransferResult, type TransferStatus, type TransportEvent, type TransportEventCallback, type TransportEventType, type TransportProvider, type WalletApiTransportConfig, type WalletInfo, type WalletJSON, type WalletJSONExportOptions, type WalletSource, addressesMatch, assertFieldEnvelopeShape, base58Decode, base58Encode, bytesToHex, checkNetworkHealth, coinIdsMatch, createCommunicationsModule, createGroupChatModule, createKeyPair, createMarketModule, createPriceProvider, createSphere, decrypt, decryptField, decryptFieldBytes, decryptJson, decryptMnemonic, decryptSimple, decryptTextFormatKey, decryptWithSalt, deriveAddressInfo, deriveChildKey, deriveFieldEncryptionKey, deriveKeyAtPath, doubleSha256, encrypt, encryptField, encryptFieldBytes, encryptMnemonic, encryptSimple, extractFromText, findPattern, formatAmount, generateAddressFromMasterKey, generateMasterKey, generateMnemonic, getAddressId, getAddressStorageKey, getCoinIdByName, getCoinIdBySymbol, getPublicKey, getTokenDecimals, getTokenDefinition, getTokenIconUrl, getTokenName, getTokenSymbol, hash160, hashSignMessage, hexToBytes, identityFromMnemonicSync, initSphere, isKnownToken, isPossiblyCommittedSendOutcome, isSphereError, isTextWalletEncrypted, isValidAddress, isValidDirectAddress, isValidNametag, isValidPrivateKey, isWalletTextFormat, loadSphere, logger, mnemonicToSeedSync, normalizeAddress, normalizeCoinId, parseAddress, parseAndDecryptWalletText, parseTokenAmount, parseWalletText, randomBytes, randomHex, randomUUID, recoverPubkeyFromSignature, ripemd160, safeParseTokenAmount, sha256, signMessage, sleep, sphereExists, toHumanReadable, validateMnemonic, verifyChallengeTemplate, verifySignedMessage };
|