@unicitylabs/sphere-sdk 0.6.2 → 0.6.4
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 +4317 -1470
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +350 -3
- package/dist/core/index.d.ts +350 -3
- package/dist/core/index.js +4321 -1452
- package/dist/core/index.js.map +1 -1
- package/dist/impl/browser/index.cjs +154 -21
- package/dist/impl/browser/index.cjs.map +1 -1
- package/dist/impl/browser/index.js +154 -21
- 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 +150 -21
- package/dist/impl/nodejs/index.cjs.map +1 -1
- package/dist/impl/nodejs/index.d.cts +55 -0
- package/dist/impl/nodejs/index.d.ts +55 -0
- package/dist/impl/nodejs/index.js +150 -21
- package/dist/impl/nodejs/index.js.map +1 -1
- package/dist/index.cjs +4301 -1480
- 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 +4314 -1471
- 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);
|
|
@@ -1625,7 +1635,7 @@ function defaultUUIDGenerator() {
|
|
|
1625
1635
|
var COMPOSING_INDICATOR_KIND = 25050;
|
|
1626
1636
|
var TIMESTAMP_RANDOMIZATION = 2 * 24 * 60 * 60;
|
|
1627
1637
|
var EVENT_KINDS = NOSTR_EVENT_KINDS;
|
|
1628
|
-
var NostrTransportProvider = class {
|
|
1638
|
+
var NostrTransportProvider = class _NostrTransportProvider {
|
|
1629
1639
|
id = "nostr";
|
|
1630
1640
|
name = "Nostr Transport";
|
|
1631
1641
|
type = "p2p";
|
|
@@ -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.
|
|
@@ -2107,11 +2166,11 @@ var NostrTransportProvider = class {
|
|
|
2107
2166
|
return this.resolveNametagInfo(identifier);
|
|
2108
2167
|
}
|
|
2109
2168
|
async resolveNametag(nametag) {
|
|
2110
|
-
this.
|
|
2169
|
+
await this.ensureConnectedForResolve();
|
|
2111
2170
|
return this.nostrClient.queryPubkeyByNametag(nametag);
|
|
2112
2171
|
}
|
|
2113
2172
|
async resolveNametagInfo(nametag) {
|
|
2114
|
-
this.
|
|
2173
|
+
await this.ensureConnectedForResolve();
|
|
2115
2174
|
const binding = await this.nostrClient.queryBindingByNametag(nametag);
|
|
2116
2175
|
if (!binding) {
|
|
2117
2176
|
logger.debug("Nostr", `resolveNametagInfo: no binding events found for Unicity ID "${nametag}"`);
|
|
@@ -2124,7 +2183,7 @@ var NostrTransportProvider = class {
|
|
|
2124
2183
|
* Performs reverse lookup via nostr-js-sdk with first-seen-wins anti-hijacking.
|
|
2125
2184
|
*/
|
|
2126
2185
|
async resolveAddressInfo(address) {
|
|
2127
|
-
this.
|
|
2186
|
+
await this.ensureConnectedForResolve();
|
|
2128
2187
|
const binding = await this.nostrClient.queryBindingByAddress(address);
|
|
2129
2188
|
if (!binding) return null;
|
|
2130
2189
|
return this.bindingInfoToPeerInfo(binding);
|
|
@@ -2159,7 +2218,7 @@ var NostrTransportProvider = class {
|
|
|
2159
2218
|
* Queries binding events authored by the given pubkey.
|
|
2160
2219
|
*/
|
|
2161
2220
|
async resolveTransportPubkeyInfo(transportPubkey) {
|
|
2162
|
-
this.
|
|
2221
|
+
await this.ensureConnectedForResolve();
|
|
2163
2222
|
const events = await this.queryEvents({
|
|
2164
2223
|
kinds: [EVENT_KINDS.NAMETAG_BINDING],
|
|
2165
2224
|
authors: [transportPubkey],
|
|
@@ -2194,7 +2253,7 @@ var NostrTransportProvider = class {
|
|
|
2194
2253
|
* Used for HD address discovery — single relay query with multi-author filter.
|
|
2195
2254
|
*/
|
|
2196
2255
|
async discoverAddresses(transportPubkeys) {
|
|
2197
|
-
this.
|
|
2256
|
+
await this.ensureConnectedForResolve();
|
|
2198
2257
|
if (transportPubkeys.length === 0) return [];
|
|
2199
2258
|
const events = await this.queryEvents({
|
|
2200
2259
|
kinds: [EVENT_KINDS.NAMETAG_BINDING],
|
|
@@ -2233,7 +2292,10 @@ var NostrTransportProvider = class {
|
|
|
2233
2292
|
* @returns Decrypted nametag or null if none found
|
|
2234
2293
|
*/
|
|
2235
2294
|
async recoverNametag() {
|
|
2236
|
-
this.
|
|
2295
|
+
await this.ensureConnectedForResolve();
|
|
2296
|
+
if (!this.identity) {
|
|
2297
|
+
throw new SphereError("Identity not set", "NOT_INITIALIZED");
|
|
2298
|
+
}
|
|
2237
2299
|
if (!this.identity || !this.keyManager) {
|
|
2238
2300
|
throw new SphereError("Identity not set", "NOT_INITIALIZED");
|
|
2239
2301
|
}
|
|
@@ -2793,6 +2855,10 @@ var NostrTransportProvider = class {
|
|
|
2793
2855
|
chatEoseFired = false;
|
|
2794
2856
|
async subscribeToEvents() {
|
|
2795
2857
|
logger.debug("Nostr", "subscribeToEvents called, identity:", !!this.identity, "keyManager:", !!this.keyManager, "nostrClient:", !!this.nostrClient);
|
|
2858
|
+
if (this._subscriptionsSuppressed) {
|
|
2859
|
+
logger.debug("Nostr", "subscribeToEvents: suppressed \u2014 mux handles event routing");
|
|
2860
|
+
return;
|
|
2861
|
+
}
|
|
2796
2862
|
if (!this.identity || !this.keyManager || !this.nostrClient) {
|
|
2797
2863
|
logger.debug("Nostr", "subscribeToEvents: skipped - no identity, keyManager, or nostrClient");
|
|
2798
2864
|
return;
|
|
@@ -2819,7 +2885,13 @@ var NostrTransportProvider = class {
|
|
|
2819
2885
|
if (stored) {
|
|
2820
2886
|
since = parseInt(stored, 10);
|
|
2821
2887
|
this.lastEventTs = since;
|
|
2888
|
+
this.fallbackSince = null;
|
|
2822
2889
|
logger.debug("Nostr", "Resuming from stored event timestamp:", since);
|
|
2890
|
+
} else if (this.fallbackSince !== null) {
|
|
2891
|
+
since = this.fallbackSince;
|
|
2892
|
+
this.lastEventTs = since;
|
|
2893
|
+
this.fallbackSince = null;
|
|
2894
|
+
logger.debug("Nostr", "Using fallback since timestamp:", since);
|
|
2823
2895
|
} else {
|
|
2824
2896
|
since = Math.floor(Date.now() / 1e3);
|
|
2825
2897
|
logger.debug("Nostr", "No stored timestamp, starting from now:", since);
|
|
@@ -2827,6 +2899,7 @@ var NostrTransportProvider = class {
|
|
|
2827
2899
|
} catch (err) {
|
|
2828
2900
|
logger.debug("Nostr", "Failed to read last event timestamp, falling back to now:", err);
|
|
2829
2901
|
since = Math.floor(Date.now() / 1e3);
|
|
2902
|
+
this.fallbackSince = null;
|
|
2830
2903
|
}
|
|
2831
2904
|
} else {
|
|
2832
2905
|
since = Math.floor(Date.now() / 1e3) - 86400;
|
|
@@ -2958,6 +3031,31 @@ var NostrTransportProvider = class {
|
|
|
2958
3031
|
throw new SphereError("NostrTransportProvider not connected", "TRANSPORT_ERROR");
|
|
2959
3032
|
}
|
|
2960
3033
|
}
|
|
3034
|
+
/**
|
|
3035
|
+
* Async version of ensureConnected — reconnects if the original transport
|
|
3036
|
+
* lost its WebSocket while subscriptions are suppressed (mux handles events).
|
|
3037
|
+
* Used by resolve methods which are always async.
|
|
3038
|
+
*/
|
|
3039
|
+
async ensureConnectedForResolve() {
|
|
3040
|
+
if (this.isConnected()) return;
|
|
3041
|
+
if (this._subscriptionsSuppressed && this.nostrClient) {
|
|
3042
|
+
logger.debug("Nostr", "Suppressed transport disconnected \u2014 reconnecting for resolve");
|
|
3043
|
+
try {
|
|
3044
|
+
await Promise.race([
|
|
3045
|
+
this.nostrClient.connect(...this.config.relays),
|
|
3046
|
+
new Promise(
|
|
3047
|
+
(_, reject) => setTimeout(() => reject(new Error("reconnect timeout")), 5e3)
|
|
3048
|
+
)
|
|
3049
|
+
]);
|
|
3050
|
+
if (this.nostrClient.isConnected()) {
|
|
3051
|
+
this.status = "connected";
|
|
3052
|
+
return;
|
|
3053
|
+
}
|
|
3054
|
+
} catch {
|
|
3055
|
+
}
|
|
3056
|
+
}
|
|
3057
|
+
throw new SphereError("NostrTransportProvider not connected", "TRANSPORT_ERROR");
|
|
3058
|
+
}
|
|
2961
3059
|
ensureReady() {
|
|
2962
3060
|
this.ensureConnected();
|
|
2963
3061
|
if (!this.identity) {
|
|
@@ -2979,16 +3077,23 @@ var NostrTransportProvider = class {
|
|
|
2979
3077
|
* because NIP17.createGiftWrap hardcodes kind 14 for the inner rumor.
|
|
2980
3078
|
*/
|
|
2981
3079
|
createCustomKindGiftWrap(recipientPubkeyHex, content, rumorKind) {
|
|
2982
|
-
|
|
3080
|
+
return _NostrTransportProvider.createCustomKindGiftWrap(this.keyManager, recipientPubkeyHex, content, rumorKind);
|
|
3081
|
+
}
|
|
3082
|
+
/**
|
|
3083
|
+
* Create a NIP-17 gift wrap with a custom rumor kind.
|
|
3084
|
+
* Shared between NostrTransportProvider and MultiAddressTransportMux.
|
|
3085
|
+
*/
|
|
3086
|
+
static createCustomKindGiftWrap(keyManager, recipientPubkeyHex, content, rumorKind) {
|
|
3087
|
+
const senderPubkey = keyManager.getPublicKeyHex();
|
|
2983
3088
|
const now = Math.floor(Date.now() / 1e3);
|
|
2984
3089
|
const rumorTags = [["p", recipientPubkeyHex]];
|
|
2985
3090
|
const rumorSerialized = JSON.stringify([0, senderPubkey, now, rumorKind, rumorTags, content]);
|
|
2986
3091
|
const rumorId = bytesToHex(sha256(new TextEncoder().encode(rumorSerialized)));
|
|
2987
3092
|
const rumor = { id: rumorId, pubkey: senderPubkey, created_at: now, kind: rumorKind, tags: rumorTags, content };
|
|
2988
3093
|
const recipientPubkeyBytes = hexToBytes(recipientPubkeyHex);
|
|
2989
|
-
const encryptedRumor = NIP44.encrypt(JSON.stringify(rumor),
|
|
3094
|
+
const encryptedRumor = NIP44.encrypt(JSON.stringify(rumor), keyManager.getPrivateKey(), recipientPubkeyBytes);
|
|
2990
3095
|
const sealTimestamp = now + Math.floor(Math.random() * 2 * TIMESTAMP_RANDOMIZATION) - TIMESTAMP_RANDOMIZATION;
|
|
2991
|
-
const seal = NostrEventClass.create(
|
|
3096
|
+
const seal = NostrEventClass.create(keyManager, {
|
|
2992
3097
|
kind: EventKinds.SEAL,
|
|
2993
3098
|
tags: [],
|
|
2994
3099
|
content: encryptedRumor,
|
|
@@ -4847,11 +4952,17 @@ var AsyncSerialQueue = class {
|
|
|
4847
4952
|
var WriteBuffer = class {
|
|
4848
4953
|
/** Full TXF data from save() calls — latest wins */
|
|
4849
4954
|
txfData = null;
|
|
4955
|
+
/** IPNS context captured at save() time — ensures flush writes to the correct
|
|
4956
|
+
* IPNS record even if identity changes between save() and flush(). */
|
|
4957
|
+
capturedIpnsKeyPair = null;
|
|
4958
|
+
capturedIpnsName = null;
|
|
4850
4959
|
get isEmpty() {
|
|
4851
4960
|
return this.txfData === null;
|
|
4852
4961
|
}
|
|
4853
4962
|
clear() {
|
|
4854
4963
|
this.txfData = null;
|
|
4964
|
+
this.capturedIpnsKeyPair = null;
|
|
4965
|
+
this.capturedIpnsName = null;
|
|
4855
4966
|
}
|
|
4856
4967
|
/**
|
|
4857
4968
|
* Merge another buffer's contents into this one (for rollback).
|
|
@@ -4860,12 +4971,14 @@ var WriteBuffer = class {
|
|
|
4860
4971
|
mergeFrom(other) {
|
|
4861
4972
|
if (other.txfData && !this.txfData) {
|
|
4862
4973
|
this.txfData = other.txfData;
|
|
4974
|
+
this.capturedIpnsKeyPair = other.capturedIpnsKeyPair;
|
|
4975
|
+
this.capturedIpnsName = other.capturedIpnsName;
|
|
4863
4976
|
}
|
|
4864
4977
|
}
|
|
4865
4978
|
};
|
|
4866
4979
|
|
|
4867
4980
|
// impl/shared/ipfs/ipfs-storage-provider.ts
|
|
4868
|
-
var IpfsStorageProvider = class {
|
|
4981
|
+
var IpfsStorageProvider = class _IpfsStorageProvider {
|
|
4869
4982
|
id = "ipfs";
|
|
4870
4983
|
name = "IPFS Storage";
|
|
4871
4984
|
type = "p2p";
|
|
@@ -4910,7 +5023,12 @@ var IpfsStorageProvider = class {
|
|
|
4910
5023
|
flushDebounceMs;
|
|
4911
5024
|
/** Set to true during shutdown to prevent new flushes */
|
|
4912
5025
|
isShuttingDown = false;
|
|
5026
|
+
/** Stored config for createForAddress() cloning */
|
|
5027
|
+
_config;
|
|
5028
|
+
_statePersistenceCtor;
|
|
4913
5029
|
constructor(config, statePersistence) {
|
|
5030
|
+
this._config = config;
|
|
5031
|
+
this._statePersistenceCtor = statePersistence;
|
|
4914
5032
|
const gateways = config?.gateways ?? getIpfsGatewayUrls();
|
|
4915
5033
|
this.debug = config?.debug ?? false;
|
|
4916
5034
|
this.ipnsLifetimeMs = config?.ipnsLifetimeMs ?? 99 * 365 * 24 * 60 * 60 * 1e3;
|
|
@@ -5030,6 +5148,7 @@ var IpfsStorageProvider = class {
|
|
|
5030
5148
|
}
|
|
5031
5149
|
async shutdown() {
|
|
5032
5150
|
this.isShuttingDown = true;
|
|
5151
|
+
logger.debug("IPFS-Storage", `shutdown: ipnsName=${this.ipnsName?.slice(0, 20)}..., pendingEmpty=${this.pendingBuffer.isEmpty}, capturedIpns=${this.pendingBuffer.capturedIpnsName?.slice(0, 20) ?? "none"}`);
|
|
5033
5152
|
if (this.flushTimer) {
|
|
5034
5153
|
clearTimeout(this.flushTimer);
|
|
5035
5154
|
this.flushTimer = null;
|
|
@@ -5062,6 +5181,8 @@ var IpfsStorageProvider = class {
|
|
|
5062
5181
|
return { success: false, error: "Not initialized", timestamp: Date.now() };
|
|
5063
5182
|
}
|
|
5064
5183
|
this.pendingBuffer.txfData = data;
|
|
5184
|
+
this.pendingBuffer.capturedIpnsKeyPair = this.ipnsKeyPair;
|
|
5185
|
+
this.pendingBuffer.capturedIpnsName = this.ipnsName;
|
|
5065
5186
|
this.scheduleFlush();
|
|
5066
5187
|
return { success: true, timestamp: Date.now() };
|
|
5067
5188
|
}
|
|
@@ -5072,8 +5193,12 @@ var IpfsStorageProvider = class {
|
|
|
5072
5193
|
* Perform the actual upload + IPNS publish synchronously.
|
|
5073
5194
|
* Called by executeFlush() and sync() — never by public save().
|
|
5074
5195
|
*/
|
|
5075
|
-
async _doSave(data) {
|
|
5076
|
-
|
|
5196
|
+
async _doSave(data, overrideIpns) {
|
|
5197
|
+
const ipnsKeyPair = overrideIpns?.keyPair ?? this.ipnsKeyPair;
|
|
5198
|
+
const ipnsName = overrideIpns?.name ?? this.ipnsName;
|
|
5199
|
+
const metaAddr = data?._meta?.address;
|
|
5200
|
+
logger.debug("IPFS-Storage", `_doSave: ipnsName=${ipnsName?.slice(0, 20)}..., override=${!!overrideIpns}, meta.address=${metaAddr?.slice(0, 20) ?? "none"}`);
|
|
5201
|
+
if (!ipnsKeyPair || !ipnsName) {
|
|
5077
5202
|
return { success: false, error: "Not initialized", timestamp: Date.now() };
|
|
5078
5203
|
}
|
|
5079
5204
|
this.emitEvent({ type: "storage:saving", timestamp: Date.now() });
|
|
@@ -5082,7 +5207,7 @@ var IpfsStorageProvider = class {
|
|
|
5082
5207
|
const metaUpdate = {
|
|
5083
5208
|
...data._meta,
|
|
5084
5209
|
version: this.dataVersion,
|
|
5085
|
-
ipnsName
|
|
5210
|
+
ipnsName,
|
|
5086
5211
|
updatedAt: Date.now()
|
|
5087
5212
|
};
|
|
5088
5213
|
if (this.remoteCid) {
|
|
@@ -5094,13 +5219,13 @@ var IpfsStorageProvider = class {
|
|
|
5094
5219
|
const baseSeq = this.ipnsSequenceNumber > this.lastKnownRemoteSequence ? this.ipnsSequenceNumber : this.lastKnownRemoteSequence;
|
|
5095
5220
|
const newSeq = baseSeq + 1n;
|
|
5096
5221
|
const marshalledRecord = await createSignedRecord(
|
|
5097
|
-
|
|
5222
|
+
ipnsKeyPair,
|
|
5098
5223
|
cid,
|
|
5099
5224
|
newSeq,
|
|
5100
5225
|
this.ipnsLifetimeMs
|
|
5101
5226
|
);
|
|
5102
5227
|
const publishResult = await this.httpClient.publishIpns(
|
|
5103
|
-
|
|
5228
|
+
ipnsName,
|
|
5104
5229
|
marshalledRecord
|
|
5105
5230
|
);
|
|
5106
5231
|
if (!publishResult.success) {
|
|
@@ -5115,14 +5240,14 @@ var IpfsStorageProvider = class {
|
|
|
5115
5240
|
this.ipnsSequenceNumber = newSeq;
|
|
5116
5241
|
this.lastCid = cid;
|
|
5117
5242
|
this.remoteCid = cid;
|
|
5118
|
-
this.cache.setIpnsRecord(
|
|
5243
|
+
this.cache.setIpnsRecord(ipnsName, {
|
|
5119
5244
|
cid,
|
|
5120
5245
|
sequence: newSeq,
|
|
5121
5246
|
gateway: "local"
|
|
5122
5247
|
});
|
|
5123
5248
|
this.cache.setContent(cid, updatedData);
|
|
5124
|
-
this.cache.markIpnsFresh(
|
|
5125
|
-
await this.statePersistence.save(
|
|
5249
|
+
this.cache.markIpnsFresh(ipnsName);
|
|
5250
|
+
await this.statePersistence.save(ipnsName, {
|
|
5126
5251
|
sequenceNumber: newSeq.toString(),
|
|
5127
5252
|
lastCid: cid,
|
|
5128
5253
|
version: this.dataVersion
|
|
@@ -5174,7 +5299,8 @@ var IpfsStorageProvider = class {
|
|
|
5174
5299
|
const baseData = active.txfData ?? {
|
|
5175
5300
|
_meta: { version: 0, address: this.identity?.directAddress ?? "", formatVersion: "2.0", updatedAt: 0 }
|
|
5176
5301
|
};
|
|
5177
|
-
const
|
|
5302
|
+
const overrideIpns = active.capturedIpnsKeyPair && active.capturedIpnsName ? { keyPair: active.capturedIpnsKeyPair, name: active.capturedIpnsName } : void 0;
|
|
5303
|
+
const result = await this._doSave(baseData, overrideIpns);
|
|
5178
5304
|
if (!result.success) {
|
|
5179
5305
|
throw new SphereError(result.error ?? "Save failed", "STORAGE_ERROR");
|
|
5180
5306
|
}
|
|
@@ -5477,6 +5603,13 @@ var IpfsStorageProvider = class {
|
|
|
5477
5603
|
log(message) {
|
|
5478
5604
|
logger.debug("IPFS-Storage", message);
|
|
5479
5605
|
}
|
|
5606
|
+
/**
|
|
5607
|
+
* Create an independent instance for a different address.
|
|
5608
|
+
* Shares the same gateway/timeout config but has fresh IPNS state.
|
|
5609
|
+
*/
|
|
5610
|
+
createForAddress() {
|
|
5611
|
+
return new _IpfsStorageProvider(this._config, this._statePersistenceCtor);
|
|
5612
|
+
}
|
|
5480
5613
|
};
|
|
5481
5614
|
|
|
5482
5615
|
// impl/browser/ipfs/browser-ipfs-state-persistence.ts
|