@unicitylabs/sphere-sdk 0.7.1-dev.2 → 0.7.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 +63 -77
- package/dist/core/index.cjs +771 -118
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +187 -6
- package/dist/core/index.d.ts +187 -6
- package/dist/core/index.js +770 -118
- package/dist/core/index.js.map +1 -1
- package/dist/impl/browser/index.cjs +11 -0
- package/dist/impl/browser/index.cjs.map +1 -1
- package/dist/impl/browser/index.js +11 -0
- package/dist/impl/browser/index.js.map +1 -1
- package/dist/impl/nodejs/index.cjs +11 -0
- package/dist/impl/nodejs/index.cjs.map +1 -1
- package/dist/impl/nodejs/index.d.cts +10 -1
- package/dist/impl/nodejs/index.d.ts +10 -1
- package/dist/impl/nodejs/index.js +11 -0
- package/dist/impl/nodejs/index.js.map +1 -1
- package/dist/index.cjs +899 -118
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +258 -1
- package/dist/index.d.ts +258 -1
- package/dist/index.js +881 -118
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/core/index.d.cts
CHANGED
|
@@ -768,8 +768,22 @@ interface MultiAddressTransportMuxConfig {
|
|
|
768
768
|
storage?: TransportStorageAdapter;
|
|
769
769
|
/** Private key for the Mux's NostrClient identity. If provided, the Mux
|
|
770
770
|
* authenticates as this key — required for relays that filter gift-wrap
|
|
771
|
-
* event delivery to the recipient's subscription.
|
|
771
|
+
* event delivery to the recipient's subscription.
|
|
772
|
+
* Ignored when {@link sharedNostrClient} is set. */
|
|
772
773
|
identityPrivateKey?: Uint8Array;
|
|
774
|
+
/**
|
|
775
|
+
* Optional pre-existing {@link NostrClient} to reuse instead of opening a
|
|
776
|
+
* fresh WebSocket per relay (#123). When set, the Mux skips both the
|
|
777
|
+
* {@code new NostrClient(...)} construction and {@code connect()} — it
|
|
778
|
+
* only registers subscription/connection listeners on the shared
|
|
779
|
+
* client. The Mux does NOT take ownership: its {@code disconnect()}
|
|
780
|
+
* leaves the client connected, since the caller (e.g. the original
|
|
781
|
+
* {@link NostrTransportProvider}) still uses it for resolve calls.
|
|
782
|
+
*
|
|
783
|
+
* Use a getter when the client may be created lazily (e.g. before the
|
|
784
|
+
* provider has connected).
|
|
785
|
+
*/
|
|
786
|
+
sharedNostrClient?: NostrClient | null | (() => NostrClient | null);
|
|
773
787
|
}
|
|
774
788
|
declare class MultiAddressTransportMux {
|
|
775
789
|
private config;
|
|
@@ -783,14 +797,14 @@ declare class MultiAddressTransportMux {
|
|
|
783
797
|
private chatSubscriptionId;
|
|
784
798
|
private chatEoseFired;
|
|
785
799
|
private resubscribeTimer;
|
|
786
|
-
private lastWalletEventAt;
|
|
787
|
-
private lastChatEventAt;
|
|
788
|
-
private healthCheckTimer;
|
|
789
800
|
private chatEoseHandlers;
|
|
790
801
|
private processedEventIds;
|
|
791
802
|
private static readonly MAX_PROCESSED_IDS;
|
|
792
803
|
private eventCallbacks;
|
|
793
804
|
private readonly identityPrivateKey;
|
|
805
|
+
private readonly sharedNostrClientGetter;
|
|
806
|
+
private usingSharedClient;
|
|
807
|
+
private connectionListener;
|
|
794
808
|
constructor(config: MultiAddressTransportMuxConfig);
|
|
795
809
|
/**
|
|
796
810
|
* Add an address to the multiplexer.
|
|
@@ -815,6 +829,58 @@ declare class MultiAddressTransportMux {
|
|
|
815
829
|
connect(): Promise<void>;
|
|
816
830
|
disconnect(): Promise<void>;
|
|
817
831
|
isConnected(): boolean;
|
|
832
|
+
/**
|
|
833
|
+
* Build the connection listener used by both {@link connect} and
|
|
834
|
+
* {@link rebindToSharedClient}.
|
|
835
|
+
*
|
|
836
|
+
* Behavioral notes:
|
|
837
|
+
* - When the Mux is sharing a {@link NostrClient} with the host
|
|
838
|
+
* transport (#123), we deliberately do NOT emit
|
|
839
|
+
* {@code transport:connected} / {@code transport:reconnecting} here
|
|
840
|
+
* — the host transport's own listener already emits those for the
|
|
841
|
+
* same socket event. Re-subscribing after a reconnect IS still our
|
|
842
|
+
* responsibility, since the host has
|
|
843
|
+
* {@code suppressSubscriptions()}'d its own filters.
|
|
844
|
+
* - {@code onConnect} does not emit {@code transport:connected}.
|
|
845
|
+
* The SDK only fires {@code onConnect} on the initial socket
|
|
846
|
+
* connection (subsequent reconnects use {@code onReconnected}),
|
|
847
|
+
* and {@link connect()}'s bottom already emits
|
|
848
|
+
* {@code transport:connected} once that returns. Emitting here too
|
|
849
|
+
* would double-fire on every initial connect.
|
|
850
|
+
* - Each callback bails out early when the Mux is not in an active
|
|
851
|
+
* state ({@code disconnected} / {@code error}). Listeners are
|
|
852
|
+
* removed on {@code disconnect()} before the callback can fire,
|
|
853
|
+
* so this guard is mainly defense-in-depth against any in-flight
|
|
854
|
+
* callback that lands during teardown — but having it at the top
|
|
855
|
+
* means we never emit a misleading {@code transport:connected}
|
|
856
|
+
* from a Mux that has already torn down.
|
|
857
|
+
*/
|
|
858
|
+
private buildConnectionListener;
|
|
859
|
+
/**
|
|
860
|
+
* Re-attach to a freshly-created shared NostrClient.
|
|
861
|
+
*
|
|
862
|
+
* Call this after the host (e.g. {@link NostrTransportProvider}) has
|
|
863
|
+
* recreated its NostrClient — typically because the wallet's active
|
|
864
|
+
* identity changed and the SDK's NostrClient does not support
|
|
865
|
+
* changing identity at runtime. The previous client has already
|
|
866
|
+
* been disconnected by the host, so its server-side subscriptions
|
|
867
|
+
* are gone — we just adopt the new client and re-issue our own.
|
|
868
|
+
*
|
|
869
|
+
* The caller is responsible for ordering: by the time rebind runs,
|
|
870
|
+
* the host transport's new NostrClient must already be created and
|
|
871
|
+
* connected. In Sphere this is guaranteed because we await
|
|
872
|
+
* {@code transport.setIdentity()} before calling rebind.
|
|
873
|
+
*
|
|
874
|
+
* Returns silently in two cases that are not caller errors:
|
|
875
|
+
* - the Mux owns its own client (not sharing) — nothing to rebind
|
|
876
|
+
* - the shared client reference hasn't changed (rebind is a no-op)
|
|
877
|
+
*
|
|
878
|
+
* Throws otherwise (rather than silently no-op'ing) so a wiring
|
|
879
|
+
* mistake — for instance, calling rebind before the host's new
|
|
880
|
+
* client is ready — surfaces immediately instead of leaving the
|
|
881
|
+
* Mux pinned to a stale client.
|
|
882
|
+
*/
|
|
883
|
+
rebindToSharedClient(): Promise<void>;
|
|
818
884
|
/**
|
|
819
885
|
* One-shot fetch of pending events from the relay.
|
|
820
886
|
* Creates a temporary subscription, waits for EOSE (or timeout),
|
|
@@ -835,7 +901,6 @@ declare class MultiAddressTransportMux {
|
|
|
835
901
|
* Called whenever addresses are added/removed.
|
|
836
902
|
*/
|
|
837
903
|
private updateSubscriptions;
|
|
838
|
-
private startHealthCheck;
|
|
839
904
|
/**
|
|
840
905
|
* Schedule a re-subscription after a relay-initiated subscription closure.
|
|
841
906
|
* Debounced: if both wallet and chat subscriptions fire onError in quick
|
|
@@ -4248,6 +4313,42 @@ declare class PaymentsModule {
|
|
|
4248
4313
|
* @returns MintNametagResult with success status and token if successful
|
|
4249
4314
|
*/
|
|
4250
4315
|
mintNametag(nametag: string): Promise<MintNametagResult>;
|
|
4316
|
+
/**
|
|
4317
|
+
* Mint a fungible token directly to this wallet (genesis mint).
|
|
4318
|
+
*
|
|
4319
|
+
* Useful for test setups that need to seed a wallet with specific token
|
|
4320
|
+
* balances WITHOUT depending on the testnet faucet HTTP service. The
|
|
4321
|
+
* resulting token has the canonical CoinId bytes (passed in `coinIdHex`)
|
|
4322
|
+
* — when those bytes match a registered symbol in the TokenRegistry,
|
|
4323
|
+
* the token shows up under the symbol's name (e.g. "UCT"). There is no
|
|
4324
|
+
* cryptographic restriction on which key may issue a given CoinId; the
|
|
4325
|
+
* aggregator records the mint regardless of issuer identity.
|
|
4326
|
+
*
|
|
4327
|
+
* The flow:
|
|
4328
|
+
* 1. Generate a random TokenId.
|
|
4329
|
+
* 2. Build TokenCoinData with [(coinId, amount)].
|
|
4330
|
+
* 3. Build MintTransactionData with recipient = self (UnmaskedPredicate
|
|
4331
|
+
* from this wallet's signing service).
|
|
4332
|
+
* 4. Submit MintCommitment to the aggregator.
|
|
4333
|
+
* 5. Wait for the inclusion proof.
|
|
4334
|
+
* 6. Construct an SDK Token via Token.mint().
|
|
4335
|
+
* 7. Convert to wallet Token format and call addToken().
|
|
4336
|
+
*
|
|
4337
|
+
* @param coinIdHex - 64-char lowercase hex CoinId. Must match the bytes
|
|
4338
|
+
* used by the registered symbol if you want the wallet to recognize
|
|
4339
|
+
* the token as that symbol (e.g. UCT's coinId from the public registry).
|
|
4340
|
+
* @param amount - Amount in smallest units (multiply by 10^decimals
|
|
4341
|
+
* when converting from human values).
|
|
4342
|
+
* @returns Result with the resulting wallet Token and its on-chain id.
|
|
4343
|
+
*/
|
|
4344
|
+
mintFungibleToken(coinIdHex: string, amount: bigint): Promise<{
|
|
4345
|
+
success: true;
|
|
4346
|
+
token: Token;
|
|
4347
|
+
tokenId: string;
|
|
4348
|
+
} | {
|
|
4349
|
+
success: false;
|
|
4350
|
+
error: string;
|
|
4351
|
+
}>;
|
|
4251
4352
|
/**
|
|
4252
4353
|
* Check if a nametag is available for minting
|
|
4253
4354
|
* @param nametag - The nametag to check (e.g., "alice" or "@alice")
|
|
@@ -4727,6 +4828,24 @@ declare class AccountingModule {
|
|
|
4727
4828
|
private dirtyLedgerEntries;
|
|
4728
4829
|
/** Count of unknown (not in invoiceTermsCache) invoice IDs in the ledger. */
|
|
4729
4830
|
private unknownLedgerCount;
|
|
4831
|
+
/**
|
|
4832
|
+
* Per-unknown-invoice first-seen timestamp for TTL eviction.
|
|
4833
|
+
*
|
|
4834
|
+
* W1 (steelman round-4): without TTL, an attacker who can deliver 500
|
|
4835
|
+
* inbound transfers with synthesized memo invoiceIds permanently exhausts
|
|
4836
|
+
* the unknown-ledger cap, after which legitimate orphan transfers (out-of-
|
|
4837
|
+
* order delivery for real swaps) are silently dropped at the cap-check.
|
|
4838
|
+
*
|
|
4839
|
+
* Round-5 perf: gated by `unknownLedgerNextSweepMs` to amortize the
|
|
4840
|
+
* sweep cost. The naive every-call sweep is O(N) where N=cap=500;
|
|
4841
|
+
* combined with the per-token cleanup loop inside the sweep it became
|
|
4842
|
+
* O(N×M) on every transfer under flood. Now we sweep at most every
|
|
4843
|
+
* `UNKNOWN_LEDGER_SWEEP_INTERVAL_MS` (60s) UNLESS the cap is currently
|
|
4844
|
+
* full, in which case we sweep on each call (the only path that can
|
|
4845
|
+
* actually drop a legitimate orphan).
|
|
4846
|
+
*/
|
|
4847
|
+
private unknownLedgerFirstSeen;
|
|
4848
|
+
private unknownLedgerNextSweepMs;
|
|
4730
4849
|
/** W17: Tracks whether tokenScanState has been mutated since last flush. */
|
|
4731
4850
|
private tokenScanDirty;
|
|
4732
4851
|
/** W2 fix: Serialization guard for _flushDirtyLedgerEntries. */
|
|
@@ -4911,6 +5030,21 @@ declare class AccountingModule {
|
|
|
4911
5030
|
* @throws {SphereError} `NOT_INITIALIZED` — module not initialized.
|
|
4912
5031
|
*/
|
|
4913
5032
|
getInvoice(invoiceId: string): InvoiceRef | null;
|
|
5033
|
+
/**
|
|
5034
|
+
* Return the set of token IDs that are currently linked to the given
|
|
5035
|
+
* invoice. Populated by both the on-chain `_processTokenTransactions`
|
|
5036
|
+
* path (tokens with `inv:` references) and the transport-memo orphan
|
|
5037
|
+
* buffering path in `_handleIncomingTransfer`.
|
|
5038
|
+
*
|
|
5039
|
+
* Used by callers that want to scope per-invoice operations (e.g.
|
|
5040
|
+
* SwapModule.verifyPayout's L3 validation) to only the tokens that
|
|
5041
|
+
* cover this invoice — avoiding false negatives when the wallet
|
|
5042
|
+
* contains unrelated tokens of the same currency in unconfirmed or
|
|
5043
|
+
* spent state.
|
|
5044
|
+
*
|
|
5045
|
+
* Returns an empty set if no tokens are currently linked.
|
|
5046
|
+
*/
|
|
5047
|
+
getTokenIdsForInvoice(invoiceId: string): Set<string>;
|
|
4914
5048
|
/**
|
|
4915
5049
|
* Explicitly close an invoice. Only target parties may close (§8.3).
|
|
4916
5050
|
*
|
|
@@ -5258,6 +5392,35 @@ declare class AccountingModule {
|
|
|
5258
5392
|
* await and the null assignment, so we loop until the field is null.
|
|
5259
5393
|
*/
|
|
5260
5394
|
private _drainFlushPromise;
|
|
5395
|
+
/**
|
|
5396
|
+
* Synchronously persist any pending provisional ledger entry for `invoiceId`
|
|
5397
|
+
* before returning to the caller. Used by `payInvoice` and
|
|
5398
|
+
* `returnInvoicePayment` to make the in-memory provisional entry durable
|
|
5399
|
+
* inside the same per-invoice gate that wrote it, closing the
|
|
5400
|
+
* crash-mid-conclude race that produces over-coverage on receivers.
|
|
5401
|
+
*
|
|
5402
|
+
* Implementation:
|
|
5403
|
+
* 1. Schedule a flush via the existing `_flushPromise` chain (so
|
|
5404
|
+
* concurrent `_handleTokenChange` callers waiting on the chain
|
|
5405
|
+
* observe ours as part of the sequence).
|
|
5406
|
+
* 2. Await OUR flush directly — NOT `_drainFlushPromise()`, which would
|
|
5407
|
+
* spin while concurrent token changes keep extending the chain and
|
|
5408
|
+
* hold the per-invoice gate for an unbounded number of additional
|
|
5409
|
+
* flushes. We only need OUR provisional entry durable.
|
|
5410
|
+
* 3. `_flushDirtyLedgerEntries` swallows per-invoice `storage.set`
|
|
5411
|
+
* rejections internally (sets a local `step1Failed` flag), leaving
|
|
5412
|
+
* the dirty entry on the set without re-throwing. So we post-check
|
|
5413
|
+
* `dirtyLedgerEntries.has(invoiceId)` and throw a `STORAGE_ERROR`
|
|
5414
|
+
* `SphereError` if our entry is still dirty — propagating to the
|
|
5415
|
+
* caller so they learn about the durability failure rather than
|
|
5416
|
+
* receiving a silent "success" return that lies on disk.
|
|
5417
|
+
*
|
|
5418
|
+
* @param invoiceId The invoice whose provisional entry must be durable.
|
|
5419
|
+
* @param callContext Used in the error message so the caller is named
|
|
5420
|
+
* ('payInvoice' / 'returnInvoicePayment') without
|
|
5421
|
+
* forcing a stack-trace inspection.
|
|
5422
|
+
*/
|
|
5423
|
+
private _persistProvisionalAndVerify;
|
|
5261
5424
|
/**
|
|
5262
5425
|
* Handle an incoming transfer event from PaymentsModule (§6.2).
|
|
5263
5426
|
*
|
|
@@ -6328,6 +6491,23 @@ type LegacyFileType = 'dat' | 'txt' | 'json' | 'mnemonic' | 'unknown';
|
|
|
6328
6491
|
*/
|
|
6329
6492
|
type DecryptionProgressCallback = (iteration: number, total: number) => Promise<void> | void;
|
|
6330
6493
|
|
|
6494
|
+
/**
|
|
6495
|
+
* Compute the Unicity L3 DIRECT:// address that corresponds to a given
|
|
6496
|
+
* compressed secp256k1 public key.
|
|
6497
|
+
*
|
|
6498
|
+
* Deterministic — the underlying primitive `UnmaskedPredicateReference.create`
|
|
6499
|
+
* only uses the public key, so the private key is never needed. This lets
|
|
6500
|
+
* a backend trust only one thing from the client (the chain pubkey, whose
|
|
6501
|
+
* ownership the client proves via signature) and derive everything else
|
|
6502
|
+
* locally. Closes the entire class of "client claims an identifier the
|
|
6503
|
+
* server can't verify" bugs at the API level.
|
|
6504
|
+
*
|
|
6505
|
+
* @param chainPubkey 33-byte compressed secp256k1 pubkey, hex-encoded
|
|
6506
|
+
* (66 chars, leading 02 or 03).
|
|
6507
|
+
* @throws if chainPubkey doesn't match the compressed-secp256k1 format.
|
|
6508
|
+
*/
|
|
6509
|
+
declare function computeDirectAddressFromChainPubkey(chainPubkey: string): Promise<string>;
|
|
6510
|
+
|
|
6331
6511
|
declare function isValidNametag(nametag: string): boolean;
|
|
6332
6512
|
|
|
6333
6513
|
/** Steps reported by the onProgress callback during wallet init/create/load/import */
|
|
@@ -6569,6 +6749,7 @@ interface SphereInitResult {
|
|
|
6569
6749
|
/** Generated mnemonic (only if autoGenerate was used) */
|
|
6570
6750
|
generatedMnemonic?: string;
|
|
6571
6751
|
}
|
|
6752
|
+
|
|
6572
6753
|
/**
|
|
6573
6754
|
* Holds all per-address module instances.
|
|
6574
6755
|
* Each HD address gets its own set so modules can run independently in background.
|
|
@@ -7815,4 +7996,4 @@ interface CheckNetworkHealthOptions {
|
|
|
7815
7996
|
*/
|
|
7816
7997
|
declare function checkNetworkHealth(network?: NetworkType, options?: CheckNetworkHealthOptions): Promise<NetworkHealthResult>;
|
|
7817
7998
|
|
|
7818
|
-
export { type AddressInfo, type AddressModuleSet, CHARSET, type CheckNetworkHealthOptions, CurrencyUtils, DEFAULT_DERIVATION_PATH, DEFAULT_TOKEN_DECIMALS, type DerivedKey, type DiscoverAddressProgress, type DiscoverAddressesOptions, type DiscoverAddressesResult, type DiscoveredAddress, type EncryptedData, type EncryptionOptions, type InitProgress, type InitProgressCallback, type InitProgressStep, type KeyPair, type L1Config, type LogHandler, type LogLevel, type LoggerConfig, type MasterKey, SIGN_MESSAGE_PREFIX, type ScanAddressProgress, type ScanAddressesOptions, type ScanAddressesResult, type ScannedAddressResult, Sphere, type SphereCreateOptions, SphereError, type SphereErrorCode, type SphereImportOptions, type SphereInitOptions, type SphereInitResult, type SphereLoadOptions, base58Decode, base58Encode, bytesToHex, checkNetworkHealth, computeHash160, convertBits, createAddress, createBech32, createKeyPair, createSphere, decodeBech32, decrypt, decryptJson, decryptMnemonic, decryptSimple, decryptWithSalt, deriveAddressInfo, deriveChildKey, deriveKeyAtPath, deserializeEncrypted, discoverAddressesImpl, doubleSha256, ec, encodeBech32, encrypt, encryptMnemonic, encryptSimple, entropyToMnemonic, extractFromText, findPattern, formatAmount, generateAddressInfo, generateMasterKey, generateMnemonic, generateRandomKey, getAddressHrp, getPublicKey, getSphere, hash160, hash160ToBytes, hashSignMessage, hexToBytes, identityFromMnemonic, identityFromMnemonicSync, importSphere, initSphere, isEncryptedData, isSphereError, isValidBech32, isValidNametag, isValidPrivateKey, loadSphere, logger, mnemonicToEntropy, mnemonicToSeed, mnemonicToSeedSync, privateKeyToAddressInfo, publicKeyToAddress, randomBytes, randomHex, randomUUID, ripemd160, scanAddressesImpl, serializeEncrypted, sha256, signMessage, sleep, sphereExists, toHumanReadable, toSmallestUnit, validateMnemonic, verifySignedMessage };
|
|
7999
|
+
export { type AddressInfo, type AddressModuleSet, CHARSET, type CheckNetworkHealthOptions, CurrencyUtils, DEFAULT_DERIVATION_PATH, DEFAULT_TOKEN_DECIMALS, type DerivedKey, type DiscoverAddressProgress, type DiscoverAddressesOptions, type DiscoverAddressesResult, type DiscoveredAddress, type EncryptedData, type EncryptionOptions, type InitProgress, type InitProgressCallback, type InitProgressStep, type KeyPair, type L1Config, type LogHandler, type LogLevel, type LoggerConfig, type MasterKey, SIGN_MESSAGE_PREFIX, type ScanAddressProgress, type ScanAddressesOptions, type ScanAddressesResult, type ScannedAddressResult, Sphere, type SphereCreateOptions, SphereError, type SphereErrorCode, type SphereImportOptions, type SphereInitOptions, type SphereInitResult, type SphereLoadOptions, base58Decode, base58Encode, bytesToHex, checkNetworkHealth, computeDirectAddressFromChainPubkey, computeHash160, convertBits, createAddress, createBech32, createKeyPair, createSphere, decodeBech32, decrypt, decryptJson, decryptMnemonic, decryptSimple, decryptWithSalt, deriveAddressInfo, deriveChildKey, deriveKeyAtPath, deserializeEncrypted, discoverAddressesImpl, doubleSha256, ec, encodeBech32, encrypt, encryptMnemonic, encryptSimple, entropyToMnemonic, extractFromText, findPattern, formatAmount, generateAddressInfo, generateMasterKey, generateMnemonic, generateRandomKey, getAddressHrp, getPublicKey, getSphere, hash160, hash160ToBytes, hashSignMessage, hexToBytes, identityFromMnemonic, identityFromMnemonicSync, importSphere, initSphere, isEncryptedData, isSphereError, isValidBech32, isValidNametag, isValidPrivateKey, loadSphere, logger, mnemonicToEntropy, mnemonicToSeed, mnemonicToSeedSync, privateKeyToAddressInfo, publicKeyToAddress, randomBytes, randomHex, randomUUID, ripemd160, scanAddressesImpl, serializeEncrypted, sha256, signMessage, sleep, sphereExists, toHumanReadable, toSmallestUnit, validateMnemonic, verifySignedMessage };
|
package/dist/core/index.d.ts
CHANGED
|
@@ -768,8 +768,22 @@ interface MultiAddressTransportMuxConfig {
|
|
|
768
768
|
storage?: TransportStorageAdapter;
|
|
769
769
|
/** Private key for the Mux's NostrClient identity. If provided, the Mux
|
|
770
770
|
* authenticates as this key — required for relays that filter gift-wrap
|
|
771
|
-
* event delivery to the recipient's subscription.
|
|
771
|
+
* event delivery to the recipient's subscription.
|
|
772
|
+
* Ignored when {@link sharedNostrClient} is set. */
|
|
772
773
|
identityPrivateKey?: Uint8Array;
|
|
774
|
+
/**
|
|
775
|
+
* Optional pre-existing {@link NostrClient} to reuse instead of opening a
|
|
776
|
+
* fresh WebSocket per relay (#123). When set, the Mux skips both the
|
|
777
|
+
* {@code new NostrClient(...)} construction and {@code connect()} — it
|
|
778
|
+
* only registers subscription/connection listeners on the shared
|
|
779
|
+
* client. The Mux does NOT take ownership: its {@code disconnect()}
|
|
780
|
+
* leaves the client connected, since the caller (e.g. the original
|
|
781
|
+
* {@link NostrTransportProvider}) still uses it for resolve calls.
|
|
782
|
+
*
|
|
783
|
+
* Use a getter when the client may be created lazily (e.g. before the
|
|
784
|
+
* provider has connected).
|
|
785
|
+
*/
|
|
786
|
+
sharedNostrClient?: NostrClient | null | (() => NostrClient | null);
|
|
773
787
|
}
|
|
774
788
|
declare class MultiAddressTransportMux {
|
|
775
789
|
private config;
|
|
@@ -783,14 +797,14 @@ declare class MultiAddressTransportMux {
|
|
|
783
797
|
private chatSubscriptionId;
|
|
784
798
|
private chatEoseFired;
|
|
785
799
|
private resubscribeTimer;
|
|
786
|
-
private lastWalletEventAt;
|
|
787
|
-
private lastChatEventAt;
|
|
788
|
-
private healthCheckTimer;
|
|
789
800
|
private chatEoseHandlers;
|
|
790
801
|
private processedEventIds;
|
|
791
802
|
private static readonly MAX_PROCESSED_IDS;
|
|
792
803
|
private eventCallbacks;
|
|
793
804
|
private readonly identityPrivateKey;
|
|
805
|
+
private readonly sharedNostrClientGetter;
|
|
806
|
+
private usingSharedClient;
|
|
807
|
+
private connectionListener;
|
|
794
808
|
constructor(config: MultiAddressTransportMuxConfig);
|
|
795
809
|
/**
|
|
796
810
|
* Add an address to the multiplexer.
|
|
@@ -815,6 +829,58 @@ declare class MultiAddressTransportMux {
|
|
|
815
829
|
connect(): Promise<void>;
|
|
816
830
|
disconnect(): Promise<void>;
|
|
817
831
|
isConnected(): boolean;
|
|
832
|
+
/**
|
|
833
|
+
* Build the connection listener used by both {@link connect} and
|
|
834
|
+
* {@link rebindToSharedClient}.
|
|
835
|
+
*
|
|
836
|
+
* Behavioral notes:
|
|
837
|
+
* - When the Mux is sharing a {@link NostrClient} with the host
|
|
838
|
+
* transport (#123), we deliberately do NOT emit
|
|
839
|
+
* {@code transport:connected} / {@code transport:reconnecting} here
|
|
840
|
+
* — the host transport's own listener already emits those for the
|
|
841
|
+
* same socket event. Re-subscribing after a reconnect IS still our
|
|
842
|
+
* responsibility, since the host has
|
|
843
|
+
* {@code suppressSubscriptions()}'d its own filters.
|
|
844
|
+
* - {@code onConnect} does not emit {@code transport:connected}.
|
|
845
|
+
* The SDK only fires {@code onConnect} on the initial socket
|
|
846
|
+
* connection (subsequent reconnects use {@code onReconnected}),
|
|
847
|
+
* and {@link connect()}'s bottom already emits
|
|
848
|
+
* {@code transport:connected} once that returns. Emitting here too
|
|
849
|
+
* would double-fire on every initial connect.
|
|
850
|
+
* - Each callback bails out early when the Mux is not in an active
|
|
851
|
+
* state ({@code disconnected} / {@code error}). Listeners are
|
|
852
|
+
* removed on {@code disconnect()} before the callback can fire,
|
|
853
|
+
* so this guard is mainly defense-in-depth against any in-flight
|
|
854
|
+
* callback that lands during teardown — but having it at the top
|
|
855
|
+
* means we never emit a misleading {@code transport:connected}
|
|
856
|
+
* from a Mux that has already torn down.
|
|
857
|
+
*/
|
|
858
|
+
private buildConnectionListener;
|
|
859
|
+
/**
|
|
860
|
+
* Re-attach to a freshly-created shared NostrClient.
|
|
861
|
+
*
|
|
862
|
+
* Call this after the host (e.g. {@link NostrTransportProvider}) has
|
|
863
|
+
* recreated its NostrClient — typically because the wallet's active
|
|
864
|
+
* identity changed and the SDK's NostrClient does not support
|
|
865
|
+
* changing identity at runtime. The previous client has already
|
|
866
|
+
* been disconnected by the host, so its server-side subscriptions
|
|
867
|
+
* are gone — we just adopt the new client and re-issue our own.
|
|
868
|
+
*
|
|
869
|
+
* The caller is responsible for ordering: by the time rebind runs,
|
|
870
|
+
* the host transport's new NostrClient must already be created and
|
|
871
|
+
* connected. In Sphere this is guaranteed because we await
|
|
872
|
+
* {@code transport.setIdentity()} before calling rebind.
|
|
873
|
+
*
|
|
874
|
+
* Returns silently in two cases that are not caller errors:
|
|
875
|
+
* - the Mux owns its own client (not sharing) — nothing to rebind
|
|
876
|
+
* - the shared client reference hasn't changed (rebind is a no-op)
|
|
877
|
+
*
|
|
878
|
+
* Throws otherwise (rather than silently no-op'ing) so a wiring
|
|
879
|
+
* mistake — for instance, calling rebind before the host's new
|
|
880
|
+
* client is ready — surfaces immediately instead of leaving the
|
|
881
|
+
* Mux pinned to a stale client.
|
|
882
|
+
*/
|
|
883
|
+
rebindToSharedClient(): Promise<void>;
|
|
818
884
|
/**
|
|
819
885
|
* One-shot fetch of pending events from the relay.
|
|
820
886
|
* Creates a temporary subscription, waits for EOSE (or timeout),
|
|
@@ -835,7 +901,6 @@ declare class MultiAddressTransportMux {
|
|
|
835
901
|
* Called whenever addresses are added/removed.
|
|
836
902
|
*/
|
|
837
903
|
private updateSubscriptions;
|
|
838
|
-
private startHealthCheck;
|
|
839
904
|
/**
|
|
840
905
|
* Schedule a re-subscription after a relay-initiated subscription closure.
|
|
841
906
|
* Debounced: if both wallet and chat subscriptions fire onError in quick
|
|
@@ -4248,6 +4313,42 @@ declare class PaymentsModule {
|
|
|
4248
4313
|
* @returns MintNametagResult with success status and token if successful
|
|
4249
4314
|
*/
|
|
4250
4315
|
mintNametag(nametag: string): Promise<MintNametagResult>;
|
|
4316
|
+
/**
|
|
4317
|
+
* Mint a fungible token directly to this wallet (genesis mint).
|
|
4318
|
+
*
|
|
4319
|
+
* Useful for test setups that need to seed a wallet with specific token
|
|
4320
|
+
* balances WITHOUT depending on the testnet faucet HTTP service. The
|
|
4321
|
+
* resulting token has the canonical CoinId bytes (passed in `coinIdHex`)
|
|
4322
|
+
* — when those bytes match a registered symbol in the TokenRegistry,
|
|
4323
|
+
* the token shows up under the symbol's name (e.g. "UCT"). There is no
|
|
4324
|
+
* cryptographic restriction on which key may issue a given CoinId; the
|
|
4325
|
+
* aggregator records the mint regardless of issuer identity.
|
|
4326
|
+
*
|
|
4327
|
+
* The flow:
|
|
4328
|
+
* 1. Generate a random TokenId.
|
|
4329
|
+
* 2. Build TokenCoinData with [(coinId, amount)].
|
|
4330
|
+
* 3. Build MintTransactionData with recipient = self (UnmaskedPredicate
|
|
4331
|
+
* from this wallet's signing service).
|
|
4332
|
+
* 4. Submit MintCommitment to the aggregator.
|
|
4333
|
+
* 5. Wait for the inclusion proof.
|
|
4334
|
+
* 6. Construct an SDK Token via Token.mint().
|
|
4335
|
+
* 7. Convert to wallet Token format and call addToken().
|
|
4336
|
+
*
|
|
4337
|
+
* @param coinIdHex - 64-char lowercase hex CoinId. Must match the bytes
|
|
4338
|
+
* used by the registered symbol if you want the wallet to recognize
|
|
4339
|
+
* the token as that symbol (e.g. UCT's coinId from the public registry).
|
|
4340
|
+
* @param amount - Amount in smallest units (multiply by 10^decimals
|
|
4341
|
+
* when converting from human values).
|
|
4342
|
+
* @returns Result with the resulting wallet Token and its on-chain id.
|
|
4343
|
+
*/
|
|
4344
|
+
mintFungibleToken(coinIdHex: string, amount: bigint): Promise<{
|
|
4345
|
+
success: true;
|
|
4346
|
+
token: Token;
|
|
4347
|
+
tokenId: string;
|
|
4348
|
+
} | {
|
|
4349
|
+
success: false;
|
|
4350
|
+
error: string;
|
|
4351
|
+
}>;
|
|
4251
4352
|
/**
|
|
4252
4353
|
* Check if a nametag is available for minting
|
|
4253
4354
|
* @param nametag - The nametag to check (e.g., "alice" or "@alice")
|
|
@@ -4727,6 +4828,24 @@ declare class AccountingModule {
|
|
|
4727
4828
|
private dirtyLedgerEntries;
|
|
4728
4829
|
/** Count of unknown (not in invoiceTermsCache) invoice IDs in the ledger. */
|
|
4729
4830
|
private unknownLedgerCount;
|
|
4831
|
+
/**
|
|
4832
|
+
* Per-unknown-invoice first-seen timestamp for TTL eviction.
|
|
4833
|
+
*
|
|
4834
|
+
* W1 (steelman round-4): without TTL, an attacker who can deliver 500
|
|
4835
|
+
* inbound transfers with synthesized memo invoiceIds permanently exhausts
|
|
4836
|
+
* the unknown-ledger cap, after which legitimate orphan transfers (out-of-
|
|
4837
|
+
* order delivery for real swaps) are silently dropped at the cap-check.
|
|
4838
|
+
*
|
|
4839
|
+
* Round-5 perf: gated by `unknownLedgerNextSweepMs` to amortize the
|
|
4840
|
+
* sweep cost. The naive every-call sweep is O(N) where N=cap=500;
|
|
4841
|
+
* combined with the per-token cleanup loop inside the sweep it became
|
|
4842
|
+
* O(N×M) on every transfer under flood. Now we sweep at most every
|
|
4843
|
+
* `UNKNOWN_LEDGER_SWEEP_INTERVAL_MS` (60s) UNLESS the cap is currently
|
|
4844
|
+
* full, in which case we sweep on each call (the only path that can
|
|
4845
|
+
* actually drop a legitimate orphan).
|
|
4846
|
+
*/
|
|
4847
|
+
private unknownLedgerFirstSeen;
|
|
4848
|
+
private unknownLedgerNextSweepMs;
|
|
4730
4849
|
/** W17: Tracks whether tokenScanState has been mutated since last flush. */
|
|
4731
4850
|
private tokenScanDirty;
|
|
4732
4851
|
/** W2 fix: Serialization guard for _flushDirtyLedgerEntries. */
|
|
@@ -4911,6 +5030,21 @@ declare class AccountingModule {
|
|
|
4911
5030
|
* @throws {SphereError} `NOT_INITIALIZED` — module not initialized.
|
|
4912
5031
|
*/
|
|
4913
5032
|
getInvoice(invoiceId: string): InvoiceRef | null;
|
|
5033
|
+
/**
|
|
5034
|
+
* Return the set of token IDs that are currently linked to the given
|
|
5035
|
+
* invoice. Populated by both the on-chain `_processTokenTransactions`
|
|
5036
|
+
* path (tokens with `inv:` references) and the transport-memo orphan
|
|
5037
|
+
* buffering path in `_handleIncomingTransfer`.
|
|
5038
|
+
*
|
|
5039
|
+
* Used by callers that want to scope per-invoice operations (e.g.
|
|
5040
|
+
* SwapModule.verifyPayout's L3 validation) to only the tokens that
|
|
5041
|
+
* cover this invoice — avoiding false negatives when the wallet
|
|
5042
|
+
* contains unrelated tokens of the same currency in unconfirmed or
|
|
5043
|
+
* spent state.
|
|
5044
|
+
*
|
|
5045
|
+
* Returns an empty set if no tokens are currently linked.
|
|
5046
|
+
*/
|
|
5047
|
+
getTokenIdsForInvoice(invoiceId: string): Set<string>;
|
|
4914
5048
|
/**
|
|
4915
5049
|
* Explicitly close an invoice. Only target parties may close (§8.3).
|
|
4916
5050
|
*
|
|
@@ -5258,6 +5392,35 @@ declare class AccountingModule {
|
|
|
5258
5392
|
* await and the null assignment, so we loop until the field is null.
|
|
5259
5393
|
*/
|
|
5260
5394
|
private _drainFlushPromise;
|
|
5395
|
+
/**
|
|
5396
|
+
* Synchronously persist any pending provisional ledger entry for `invoiceId`
|
|
5397
|
+
* before returning to the caller. Used by `payInvoice` and
|
|
5398
|
+
* `returnInvoicePayment` to make the in-memory provisional entry durable
|
|
5399
|
+
* inside the same per-invoice gate that wrote it, closing the
|
|
5400
|
+
* crash-mid-conclude race that produces over-coverage on receivers.
|
|
5401
|
+
*
|
|
5402
|
+
* Implementation:
|
|
5403
|
+
* 1. Schedule a flush via the existing `_flushPromise` chain (so
|
|
5404
|
+
* concurrent `_handleTokenChange` callers waiting on the chain
|
|
5405
|
+
* observe ours as part of the sequence).
|
|
5406
|
+
* 2. Await OUR flush directly — NOT `_drainFlushPromise()`, which would
|
|
5407
|
+
* spin while concurrent token changes keep extending the chain and
|
|
5408
|
+
* hold the per-invoice gate for an unbounded number of additional
|
|
5409
|
+
* flushes. We only need OUR provisional entry durable.
|
|
5410
|
+
* 3. `_flushDirtyLedgerEntries` swallows per-invoice `storage.set`
|
|
5411
|
+
* rejections internally (sets a local `step1Failed` flag), leaving
|
|
5412
|
+
* the dirty entry on the set without re-throwing. So we post-check
|
|
5413
|
+
* `dirtyLedgerEntries.has(invoiceId)` and throw a `STORAGE_ERROR`
|
|
5414
|
+
* `SphereError` if our entry is still dirty — propagating to the
|
|
5415
|
+
* caller so they learn about the durability failure rather than
|
|
5416
|
+
* receiving a silent "success" return that lies on disk.
|
|
5417
|
+
*
|
|
5418
|
+
* @param invoiceId The invoice whose provisional entry must be durable.
|
|
5419
|
+
* @param callContext Used in the error message so the caller is named
|
|
5420
|
+
* ('payInvoice' / 'returnInvoicePayment') without
|
|
5421
|
+
* forcing a stack-trace inspection.
|
|
5422
|
+
*/
|
|
5423
|
+
private _persistProvisionalAndVerify;
|
|
5261
5424
|
/**
|
|
5262
5425
|
* Handle an incoming transfer event from PaymentsModule (§6.2).
|
|
5263
5426
|
*
|
|
@@ -6328,6 +6491,23 @@ type LegacyFileType = 'dat' | 'txt' | 'json' | 'mnemonic' | 'unknown';
|
|
|
6328
6491
|
*/
|
|
6329
6492
|
type DecryptionProgressCallback = (iteration: number, total: number) => Promise<void> | void;
|
|
6330
6493
|
|
|
6494
|
+
/**
|
|
6495
|
+
* Compute the Unicity L3 DIRECT:// address that corresponds to a given
|
|
6496
|
+
* compressed secp256k1 public key.
|
|
6497
|
+
*
|
|
6498
|
+
* Deterministic — the underlying primitive `UnmaskedPredicateReference.create`
|
|
6499
|
+
* only uses the public key, so the private key is never needed. This lets
|
|
6500
|
+
* a backend trust only one thing from the client (the chain pubkey, whose
|
|
6501
|
+
* ownership the client proves via signature) and derive everything else
|
|
6502
|
+
* locally. Closes the entire class of "client claims an identifier the
|
|
6503
|
+
* server can't verify" bugs at the API level.
|
|
6504
|
+
*
|
|
6505
|
+
* @param chainPubkey 33-byte compressed secp256k1 pubkey, hex-encoded
|
|
6506
|
+
* (66 chars, leading 02 or 03).
|
|
6507
|
+
* @throws if chainPubkey doesn't match the compressed-secp256k1 format.
|
|
6508
|
+
*/
|
|
6509
|
+
declare function computeDirectAddressFromChainPubkey(chainPubkey: string): Promise<string>;
|
|
6510
|
+
|
|
6331
6511
|
declare function isValidNametag(nametag: string): boolean;
|
|
6332
6512
|
|
|
6333
6513
|
/** Steps reported by the onProgress callback during wallet init/create/load/import */
|
|
@@ -6569,6 +6749,7 @@ interface SphereInitResult {
|
|
|
6569
6749
|
/** Generated mnemonic (only if autoGenerate was used) */
|
|
6570
6750
|
generatedMnemonic?: string;
|
|
6571
6751
|
}
|
|
6752
|
+
|
|
6572
6753
|
/**
|
|
6573
6754
|
* Holds all per-address module instances.
|
|
6574
6755
|
* Each HD address gets its own set so modules can run independently in background.
|
|
@@ -7815,4 +7996,4 @@ interface CheckNetworkHealthOptions {
|
|
|
7815
7996
|
*/
|
|
7816
7997
|
declare function checkNetworkHealth(network?: NetworkType, options?: CheckNetworkHealthOptions): Promise<NetworkHealthResult>;
|
|
7817
7998
|
|
|
7818
|
-
export { type AddressInfo, type AddressModuleSet, CHARSET, type CheckNetworkHealthOptions, CurrencyUtils, DEFAULT_DERIVATION_PATH, DEFAULT_TOKEN_DECIMALS, type DerivedKey, type DiscoverAddressProgress, type DiscoverAddressesOptions, type DiscoverAddressesResult, type DiscoveredAddress, type EncryptedData, type EncryptionOptions, type InitProgress, type InitProgressCallback, type InitProgressStep, type KeyPair, type L1Config, type LogHandler, type LogLevel, type LoggerConfig, type MasterKey, SIGN_MESSAGE_PREFIX, type ScanAddressProgress, type ScanAddressesOptions, type ScanAddressesResult, type ScannedAddressResult, Sphere, type SphereCreateOptions, SphereError, type SphereErrorCode, type SphereImportOptions, type SphereInitOptions, type SphereInitResult, type SphereLoadOptions, base58Decode, base58Encode, bytesToHex, checkNetworkHealth, computeHash160, convertBits, createAddress, createBech32, createKeyPair, createSphere, decodeBech32, decrypt, decryptJson, decryptMnemonic, decryptSimple, decryptWithSalt, deriveAddressInfo, deriveChildKey, deriveKeyAtPath, deserializeEncrypted, discoverAddressesImpl, doubleSha256, ec, encodeBech32, encrypt, encryptMnemonic, encryptSimple, entropyToMnemonic, extractFromText, findPattern, formatAmount, generateAddressInfo, generateMasterKey, generateMnemonic, generateRandomKey, getAddressHrp, getPublicKey, getSphere, hash160, hash160ToBytes, hashSignMessage, hexToBytes, identityFromMnemonic, identityFromMnemonicSync, importSphere, initSphere, isEncryptedData, isSphereError, isValidBech32, isValidNametag, isValidPrivateKey, loadSphere, logger, mnemonicToEntropy, mnemonicToSeed, mnemonicToSeedSync, privateKeyToAddressInfo, publicKeyToAddress, randomBytes, randomHex, randomUUID, ripemd160, scanAddressesImpl, serializeEncrypted, sha256, signMessage, sleep, sphereExists, toHumanReadable, toSmallestUnit, validateMnemonic, verifySignedMessage };
|
|
7999
|
+
export { type AddressInfo, type AddressModuleSet, CHARSET, type CheckNetworkHealthOptions, CurrencyUtils, DEFAULT_DERIVATION_PATH, DEFAULT_TOKEN_DECIMALS, type DerivedKey, type DiscoverAddressProgress, type DiscoverAddressesOptions, type DiscoverAddressesResult, type DiscoveredAddress, type EncryptedData, type EncryptionOptions, type InitProgress, type InitProgressCallback, type InitProgressStep, type KeyPair, type L1Config, type LogHandler, type LogLevel, type LoggerConfig, type MasterKey, SIGN_MESSAGE_PREFIX, type ScanAddressProgress, type ScanAddressesOptions, type ScanAddressesResult, type ScannedAddressResult, Sphere, type SphereCreateOptions, SphereError, type SphereErrorCode, type SphereImportOptions, type SphereInitOptions, type SphereInitResult, type SphereLoadOptions, base58Decode, base58Encode, bytesToHex, checkNetworkHealth, computeDirectAddressFromChainPubkey, computeHash160, convertBits, createAddress, createBech32, createKeyPair, createSphere, decodeBech32, decrypt, decryptJson, decryptMnemonic, decryptSimple, decryptWithSalt, deriveAddressInfo, deriveChildKey, deriveKeyAtPath, deserializeEncrypted, discoverAddressesImpl, doubleSha256, ec, encodeBech32, encrypt, encryptMnemonic, encryptSimple, entropyToMnemonic, extractFromText, findPattern, formatAmount, generateAddressInfo, generateMasterKey, generateMnemonic, generateRandomKey, getAddressHrp, getPublicKey, getSphere, hash160, hash160ToBytes, hashSignMessage, hexToBytes, identityFromMnemonic, identityFromMnemonicSync, importSphere, initSphere, isEncryptedData, isSphereError, isValidBech32, isValidNametag, isValidPrivateKey, loadSphere, logger, mnemonicToEntropy, mnemonicToSeed, mnemonicToSeedSync, privateKeyToAddressInfo, publicKeyToAddress, randomBytes, randomHex, randomUUID, ripemd160, scanAddressesImpl, serializeEncrypted, sha256, signMessage, sleep, sphereExists, toHumanReadable, toSmallestUnit, validateMnemonic, verifySignedMessage };
|