@unicitylabs/sphere-sdk 0.6.2 → 0.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/index.cjs +1351 -52
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +342 -3
- package/dist/core/index.d.ts +342 -3
- package/dist/core/index.js +1357 -48
- package/dist/core/index.js.map +1 -1
- package/dist/impl/browser/index.cjs +109 -11
- package/dist/impl/browser/index.cjs.map +1 -1
- package/dist/impl/browser/index.js +109 -11
- package/dist/impl/browser/index.js.map +1 -1
- package/dist/impl/browser/ipfs.cjs +38 -10
- package/dist/impl/browser/ipfs.cjs.map +1 -1
- package/dist/impl/browser/ipfs.js +38 -10
- package/dist/impl/browser/ipfs.js.map +1 -1
- package/dist/impl/nodejs/index.cjs +105 -11
- package/dist/impl/nodejs/index.cjs.map +1 -1
- package/dist/impl/nodejs/index.d.cts +43 -0
- package/dist/impl/nodejs/index.d.ts +43 -0
- package/dist/impl/nodejs/index.js +105 -11
- package/dist/impl/nodejs/index.js.map +1 -1
- package/dist/index.cjs +1334 -61
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +43 -2
- package/dist/index.d.ts +43 -2
- package/dist/index.js +1333 -50
- package/dist/index.js.map +1 -1
- package/dist/l1/index.d.cts +717 -0
- package/dist/l1/index.d.ts +717 -0
- package/package.json +1 -1
|
@@ -758,7 +758,7 @@ var STORE_TOKENS = "tokens";
|
|
|
758
758
|
var STORE_META = "meta";
|
|
759
759
|
var STORE_HISTORY = "history";
|
|
760
760
|
var connectionSeq2 = 0;
|
|
761
|
-
var IndexedDBTokenStorageProvider = class {
|
|
761
|
+
var IndexedDBTokenStorageProvider = class _IndexedDBTokenStorageProvider {
|
|
762
762
|
id = "indexeddb-token-storage";
|
|
763
763
|
name = "IndexedDB Token Storage";
|
|
764
764
|
type = "local";
|
|
@@ -1206,6 +1206,16 @@ var IndexedDBTokenStorageProvider = class {
|
|
|
1206
1206
|
db.close();
|
|
1207
1207
|
}
|
|
1208
1208
|
}
|
|
1209
|
+
/**
|
|
1210
|
+
* Create an independent instance for a different address.
|
|
1211
|
+
* The new instance shares the same config but has its own IDB connection.
|
|
1212
|
+
*/
|
|
1213
|
+
createForAddress() {
|
|
1214
|
+
return new _IndexedDBTokenStorageProvider({
|
|
1215
|
+
dbNamePrefix: this.dbNamePrefix,
|
|
1216
|
+
debug: this.debug
|
|
1217
|
+
});
|
|
1218
|
+
}
|
|
1209
1219
|
};
|
|
1210
1220
|
function createIndexedDBTokenStorageProvider(config) {
|
|
1211
1221
|
return new IndexedDBTokenStorageProvider(config);
|
|
@@ -1634,6 +1644,8 @@ var NostrTransportProvider = class {
|
|
|
1634
1644
|
storage = null;
|
|
1635
1645
|
/** In-memory max event timestamp to avoid read-before-write races in updateLastEventTimestamp. */
|
|
1636
1646
|
lastEventTs = 0;
|
|
1647
|
+
/** Fallback 'since' timestamp for first-time address subscriptions (consumed once). */
|
|
1648
|
+
fallbackSince = null;
|
|
1637
1649
|
identity = null;
|
|
1638
1650
|
keyManager = null;
|
|
1639
1651
|
status = "disconnected";
|
|
@@ -1666,6 +1678,48 @@ var NostrTransportProvider = class {
|
|
|
1666
1678
|
};
|
|
1667
1679
|
this.storage = config.storage ?? null;
|
|
1668
1680
|
}
|
|
1681
|
+
/**
|
|
1682
|
+
* Get the WebSocket factory (used by MultiAddressTransportMux to share the same factory).
|
|
1683
|
+
*/
|
|
1684
|
+
getWebSocketFactory() {
|
|
1685
|
+
return this.config.createWebSocket;
|
|
1686
|
+
}
|
|
1687
|
+
/**
|
|
1688
|
+
* Get the configured relay URLs.
|
|
1689
|
+
*/
|
|
1690
|
+
getConfiguredRelays() {
|
|
1691
|
+
return [...this.config.relays];
|
|
1692
|
+
}
|
|
1693
|
+
/**
|
|
1694
|
+
* Get the storage adapter.
|
|
1695
|
+
*/
|
|
1696
|
+
getStorageAdapter() {
|
|
1697
|
+
return this.storage;
|
|
1698
|
+
}
|
|
1699
|
+
/**
|
|
1700
|
+
* Suppress event subscriptions — unsubscribe wallet/chat filters
|
|
1701
|
+
* but keep the connection alive for resolve/identity-binding operations.
|
|
1702
|
+
* Used when MultiAddressTransportMux takes over event handling.
|
|
1703
|
+
*/
|
|
1704
|
+
suppressSubscriptions() {
|
|
1705
|
+
if (!this.nostrClient) return;
|
|
1706
|
+
if (this.walletSubscriptionId) {
|
|
1707
|
+
this.nostrClient.unsubscribe(this.walletSubscriptionId);
|
|
1708
|
+
this.walletSubscriptionId = null;
|
|
1709
|
+
}
|
|
1710
|
+
if (this.chatSubscriptionId) {
|
|
1711
|
+
this.nostrClient.unsubscribe(this.chatSubscriptionId);
|
|
1712
|
+
this.chatSubscriptionId = null;
|
|
1713
|
+
}
|
|
1714
|
+
if (this.mainSubscriptionId) {
|
|
1715
|
+
this.nostrClient.unsubscribe(this.mainSubscriptionId);
|
|
1716
|
+
this.mainSubscriptionId = null;
|
|
1717
|
+
}
|
|
1718
|
+
this._subscriptionsSuppressed = true;
|
|
1719
|
+
logger.debug("Nostr", "Subscriptions suppressed \u2014 mux handles event routing");
|
|
1720
|
+
}
|
|
1721
|
+
// Flag to prevent re-subscription after suppressSubscriptions()
|
|
1722
|
+
_subscriptionsSuppressed = false;
|
|
1669
1723
|
// ===========================================================================
|
|
1670
1724
|
// BaseProvider Implementation
|
|
1671
1725
|
// ===========================================================================
|
|
@@ -1844,6 +1898,8 @@ var NostrTransportProvider = class {
|
|
|
1844
1898
|
// ===========================================================================
|
|
1845
1899
|
async setIdentity(identity) {
|
|
1846
1900
|
this.identity = identity;
|
|
1901
|
+
this.processedEventIds.clear();
|
|
1902
|
+
this.lastEventTs = 0;
|
|
1847
1903
|
const secretKey = Buffer2.from(identity.privateKey, "hex");
|
|
1848
1904
|
this.keyManager = NostrKeyManager.fromPrivateKey(secretKey);
|
|
1849
1905
|
const nostrPubkey = this.keyManager.getPublicKeyHex();
|
|
@@ -1886,6 +1942,9 @@ var NostrTransportProvider = class {
|
|
|
1886
1942
|
await this.subscribeToEvents();
|
|
1887
1943
|
}
|
|
1888
1944
|
}
|
|
1945
|
+
setFallbackSince(sinceSeconds) {
|
|
1946
|
+
this.fallbackSince = sinceSeconds;
|
|
1947
|
+
}
|
|
1889
1948
|
/**
|
|
1890
1949
|
* Get the Nostr-format public key (32 bytes / 64 hex chars)
|
|
1891
1950
|
* This is the x-coordinate only, without the 02/03 prefix.
|
|
@@ -2793,6 +2852,10 @@ var NostrTransportProvider = class {
|
|
|
2793
2852
|
chatEoseFired = false;
|
|
2794
2853
|
async subscribeToEvents() {
|
|
2795
2854
|
logger.debug("Nostr", "subscribeToEvents called, identity:", !!this.identity, "keyManager:", !!this.keyManager, "nostrClient:", !!this.nostrClient);
|
|
2855
|
+
if (this._subscriptionsSuppressed) {
|
|
2856
|
+
logger.debug("Nostr", "subscribeToEvents: suppressed \u2014 mux handles event routing");
|
|
2857
|
+
return;
|
|
2858
|
+
}
|
|
2796
2859
|
if (!this.identity || !this.keyManager || !this.nostrClient) {
|
|
2797
2860
|
logger.debug("Nostr", "subscribeToEvents: skipped - no identity, keyManager, or nostrClient");
|
|
2798
2861
|
return;
|
|
@@ -2819,7 +2882,13 @@ var NostrTransportProvider = class {
|
|
|
2819
2882
|
if (stored) {
|
|
2820
2883
|
since = parseInt(stored, 10);
|
|
2821
2884
|
this.lastEventTs = since;
|
|
2885
|
+
this.fallbackSince = null;
|
|
2822
2886
|
logger.debug("Nostr", "Resuming from stored event timestamp:", since);
|
|
2887
|
+
} else if (this.fallbackSince !== null) {
|
|
2888
|
+
since = this.fallbackSince;
|
|
2889
|
+
this.lastEventTs = since;
|
|
2890
|
+
this.fallbackSince = null;
|
|
2891
|
+
logger.debug("Nostr", "Using fallback since timestamp:", since);
|
|
2823
2892
|
} else {
|
|
2824
2893
|
since = Math.floor(Date.now() / 1e3);
|
|
2825
2894
|
logger.debug("Nostr", "No stored timestamp, starting from now:", since);
|
|
@@ -2827,6 +2896,7 @@ var NostrTransportProvider = class {
|
|
|
2827
2896
|
} catch (err) {
|
|
2828
2897
|
logger.debug("Nostr", "Failed to read last event timestamp, falling back to now:", err);
|
|
2829
2898
|
since = Math.floor(Date.now() / 1e3);
|
|
2899
|
+
this.fallbackSince = null;
|
|
2830
2900
|
}
|
|
2831
2901
|
} else {
|
|
2832
2902
|
since = Math.floor(Date.now() / 1e3) - 86400;
|
|
@@ -4847,11 +4917,17 @@ var AsyncSerialQueue = class {
|
|
|
4847
4917
|
var WriteBuffer = class {
|
|
4848
4918
|
/** Full TXF data from save() calls — latest wins */
|
|
4849
4919
|
txfData = null;
|
|
4920
|
+
/** IPNS context captured at save() time — ensures flush writes to the correct
|
|
4921
|
+
* IPNS record even if identity changes between save() and flush(). */
|
|
4922
|
+
capturedIpnsKeyPair = null;
|
|
4923
|
+
capturedIpnsName = null;
|
|
4850
4924
|
get isEmpty() {
|
|
4851
4925
|
return this.txfData === null;
|
|
4852
4926
|
}
|
|
4853
4927
|
clear() {
|
|
4854
4928
|
this.txfData = null;
|
|
4929
|
+
this.capturedIpnsKeyPair = null;
|
|
4930
|
+
this.capturedIpnsName = null;
|
|
4855
4931
|
}
|
|
4856
4932
|
/**
|
|
4857
4933
|
* Merge another buffer's contents into this one (for rollback).
|
|
@@ -4860,12 +4936,14 @@ var WriteBuffer = class {
|
|
|
4860
4936
|
mergeFrom(other) {
|
|
4861
4937
|
if (other.txfData && !this.txfData) {
|
|
4862
4938
|
this.txfData = other.txfData;
|
|
4939
|
+
this.capturedIpnsKeyPair = other.capturedIpnsKeyPair;
|
|
4940
|
+
this.capturedIpnsName = other.capturedIpnsName;
|
|
4863
4941
|
}
|
|
4864
4942
|
}
|
|
4865
4943
|
};
|
|
4866
4944
|
|
|
4867
4945
|
// impl/shared/ipfs/ipfs-storage-provider.ts
|
|
4868
|
-
var IpfsStorageProvider = class {
|
|
4946
|
+
var IpfsStorageProvider = class _IpfsStorageProvider {
|
|
4869
4947
|
id = "ipfs";
|
|
4870
4948
|
name = "IPFS Storage";
|
|
4871
4949
|
type = "p2p";
|
|
@@ -4910,7 +4988,12 @@ var IpfsStorageProvider = class {
|
|
|
4910
4988
|
flushDebounceMs;
|
|
4911
4989
|
/** Set to true during shutdown to prevent new flushes */
|
|
4912
4990
|
isShuttingDown = false;
|
|
4991
|
+
/** Stored config for createForAddress() cloning */
|
|
4992
|
+
_config;
|
|
4993
|
+
_statePersistenceCtor;
|
|
4913
4994
|
constructor(config, statePersistence) {
|
|
4995
|
+
this._config = config;
|
|
4996
|
+
this._statePersistenceCtor = statePersistence;
|
|
4914
4997
|
const gateways = config?.gateways ?? getIpfsGatewayUrls();
|
|
4915
4998
|
this.debug = config?.debug ?? false;
|
|
4916
4999
|
this.ipnsLifetimeMs = config?.ipnsLifetimeMs ?? 99 * 365 * 24 * 60 * 60 * 1e3;
|
|
@@ -5030,6 +5113,7 @@ var IpfsStorageProvider = class {
|
|
|
5030
5113
|
}
|
|
5031
5114
|
async shutdown() {
|
|
5032
5115
|
this.isShuttingDown = true;
|
|
5116
|
+
logger.debug("IPFS-Storage", `shutdown: ipnsName=${this.ipnsName?.slice(0, 20)}..., pendingEmpty=${this.pendingBuffer.isEmpty}, capturedIpns=${this.pendingBuffer.capturedIpnsName?.slice(0, 20) ?? "none"}`);
|
|
5033
5117
|
if (this.flushTimer) {
|
|
5034
5118
|
clearTimeout(this.flushTimer);
|
|
5035
5119
|
this.flushTimer = null;
|
|
@@ -5062,6 +5146,8 @@ var IpfsStorageProvider = class {
|
|
|
5062
5146
|
return { success: false, error: "Not initialized", timestamp: Date.now() };
|
|
5063
5147
|
}
|
|
5064
5148
|
this.pendingBuffer.txfData = data;
|
|
5149
|
+
this.pendingBuffer.capturedIpnsKeyPair = this.ipnsKeyPair;
|
|
5150
|
+
this.pendingBuffer.capturedIpnsName = this.ipnsName;
|
|
5065
5151
|
this.scheduleFlush();
|
|
5066
5152
|
return { success: true, timestamp: Date.now() };
|
|
5067
5153
|
}
|
|
@@ -5072,8 +5158,12 @@ var IpfsStorageProvider = class {
|
|
|
5072
5158
|
* Perform the actual upload + IPNS publish synchronously.
|
|
5073
5159
|
* Called by executeFlush() and sync() — never by public save().
|
|
5074
5160
|
*/
|
|
5075
|
-
async _doSave(data) {
|
|
5076
|
-
|
|
5161
|
+
async _doSave(data, overrideIpns) {
|
|
5162
|
+
const ipnsKeyPair = overrideIpns?.keyPair ?? this.ipnsKeyPair;
|
|
5163
|
+
const ipnsName = overrideIpns?.name ?? this.ipnsName;
|
|
5164
|
+
const metaAddr = data?._meta?.address;
|
|
5165
|
+
logger.debug("IPFS-Storage", `_doSave: ipnsName=${ipnsName?.slice(0, 20)}..., override=${!!overrideIpns}, meta.address=${metaAddr?.slice(0, 20) ?? "none"}`);
|
|
5166
|
+
if (!ipnsKeyPair || !ipnsName) {
|
|
5077
5167
|
return { success: false, error: "Not initialized", timestamp: Date.now() };
|
|
5078
5168
|
}
|
|
5079
5169
|
this.emitEvent({ type: "storage:saving", timestamp: Date.now() });
|
|
@@ -5082,7 +5172,7 @@ var IpfsStorageProvider = class {
|
|
|
5082
5172
|
const metaUpdate = {
|
|
5083
5173
|
...data._meta,
|
|
5084
5174
|
version: this.dataVersion,
|
|
5085
|
-
ipnsName
|
|
5175
|
+
ipnsName,
|
|
5086
5176
|
updatedAt: Date.now()
|
|
5087
5177
|
};
|
|
5088
5178
|
if (this.remoteCid) {
|
|
@@ -5094,13 +5184,13 @@ var IpfsStorageProvider = class {
|
|
|
5094
5184
|
const baseSeq = this.ipnsSequenceNumber > this.lastKnownRemoteSequence ? this.ipnsSequenceNumber : this.lastKnownRemoteSequence;
|
|
5095
5185
|
const newSeq = baseSeq + 1n;
|
|
5096
5186
|
const marshalledRecord = await createSignedRecord(
|
|
5097
|
-
|
|
5187
|
+
ipnsKeyPair,
|
|
5098
5188
|
cid,
|
|
5099
5189
|
newSeq,
|
|
5100
5190
|
this.ipnsLifetimeMs
|
|
5101
5191
|
);
|
|
5102
5192
|
const publishResult = await this.httpClient.publishIpns(
|
|
5103
|
-
|
|
5193
|
+
ipnsName,
|
|
5104
5194
|
marshalledRecord
|
|
5105
5195
|
);
|
|
5106
5196
|
if (!publishResult.success) {
|
|
@@ -5115,14 +5205,14 @@ var IpfsStorageProvider = class {
|
|
|
5115
5205
|
this.ipnsSequenceNumber = newSeq;
|
|
5116
5206
|
this.lastCid = cid;
|
|
5117
5207
|
this.remoteCid = cid;
|
|
5118
|
-
this.cache.setIpnsRecord(
|
|
5208
|
+
this.cache.setIpnsRecord(ipnsName, {
|
|
5119
5209
|
cid,
|
|
5120
5210
|
sequence: newSeq,
|
|
5121
5211
|
gateway: "local"
|
|
5122
5212
|
});
|
|
5123
5213
|
this.cache.setContent(cid, updatedData);
|
|
5124
|
-
this.cache.markIpnsFresh(
|
|
5125
|
-
await this.statePersistence.save(
|
|
5214
|
+
this.cache.markIpnsFresh(ipnsName);
|
|
5215
|
+
await this.statePersistence.save(ipnsName, {
|
|
5126
5216
|
sequenceNumber: newSeq.toString(),
|
|
5127
5217
|
lastCid: cid,
|
|
5128
5218
|
version: this.dataVersion
|
|
@@ -5174,7 +5264,8 @@ var IpfsStorageProvider = class {
|
|
|
5174
5264
|
const baseData = active.txfData ?? {
|
|
5175
5265
|
_meta: { version: 0, address: this.identity?.directAddress ?? "", formatVersion: "2.0", updatedAt: 0 }
|
|
5176
5266
|
};
|
|
5177
|
-
const
|
|
5267
|
+
const overrideIpns = active.capturedIpnsKeyPair && active.capturedIpnsName ? { keyPair: active.capturedIpnsKeyPair, name: active.capturedIpnsName } : void 0;
|
|
5268
|
+
const result = await this._doSave(baseData, overrideIpns);
|
|
5178
5269
|
if (!result.success) {
|
|
5179
5270
|
throw new SphereError(result.error ?? "Save failed", "STORAGE_ERROR");
|
|
5180
5271
|
}
|
|
@@ -5477,6 +5568,13 @@ var IpfsStorageProvider = class {
|
|
|
5477
5568
|
log(message) {
|
|
5478
5569
|
logger.debug("IPFS-Storage", message);
|
|
5479
5570
|
}
|
|
5571
|
+
/**
|
|
5572
|
+
* Create an independent instance for a different address.
|
|
5573
|
+
* Shares the same gateway/timeout config but has fresh IPNS state.
|
|
5574
|
+
*/
|
|
5575
|
+
createForAddress() {
|
|
5576
|
+
return new _IpfsStorageProvider(this._config, this._statePersistenceCtor);
|
|
5577
|
+
}
|
|
5480
5578
|
};
|
|
5481
5579
|
|
|
5482
5580
|
// impl/browser/ipfs/browser-ipfs-state-persistence.ts
|