@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
|
@@ -368,7 +368,7 @@ var path2 = __toESM(require("path"), 1);
|
|
|
368
368
|
var META_FILE = "_meta.json";
|
|
369
369
|
var TOMBSTONES_FILE = "_tombstones.json";
|
|
370
370
|
var HISTORY_FILE = "_history.json";
|
|
371
|
-
var FileTokenStorageProvider = class {
|
|
371
|
+
var FileTokenStorageProvider = class _FileTokenStorageProvider {
|
|
372
372
|
id = "file-token-storage";
|
|
373
373
|
name = "File Token Storage";
|
|
374
374
|
type = "local";
|
|
@@ -595,6 +595,12 @@ var FileTokenStorageProvider = class {
|
|
|
595
595
|
}
|
|
596
596
|
return imported;
|
|
597
597
|
}
|
|
598
|
+
/**
|
|
599
|
+
* Create an independent instance for a different address.
|
|
600
|
+
*/
|
|
601
|
+
createForAddress() {
|
|
602
|
+
return new _FileTokenStorageProvider({ tokensDir: this.baseTokensDir });
|
|
603
|
+
}
|
|
598
604
|
};
|
|
599
605
|
function createFileTokenStorageProvider(config) {
|
|
600
606
|
return new FileTokenStorageProvider(config);
|
|
@@ -1118,6 +1124,8 @@ var NostrTransportProvider = class {
|
|
|
1118
1124
|
storage = null;
|
|
1119
1125
|
/** In-memory max event timestamp to avoid read-before-write races in updateLastEventTimestamp. */
|
|
1120
1126
|
lastEventTs = 0;
|
|
1127
|
+
/** Fallback 'since' timestamp for first-time address subscriptions (consumed once). */
|
|
1128
|
+
fallbackSince = null;
|
|
1121
1129
|
identity = null;
|
|
1122
1130
|
keyManager = null;
|
|
1123
1131
|
status = "disconnected";
|
|
@@ -1150,6 +1158,48 @@ var NostrTransportProvider = class {
|
|
|
1150
1158
|
};
|
|
1151
1159
|
this.storage = config.storage ?? null;
|
|
1152
1160
|
}
|
|
1161
|
+
/**
|
|
1162
|
+
* Get the WebSocket factory (used by MultiAddressTransportMux to share the same factory).
|
|
1163
|
+
*/
|
|
1164
|
+
getWebSocketFactory() {
|
|
1165
|
+
return this.config.createWebSocket;
|
|
1166
|
+
}
|
|
1167
|
+
/**
|
|
1168
|
+
* Get the configured relay URLs.
|
|
1169
|
+
*/
|
|
1170
|
+
getConfiguredRelays() {
|
|
1171
|
+
return [...this.config.relays];
|
|
1172
|
+
}
|
|
1173
|
+
/**
|
|
1174
|
+
* Get the storage adapter.
|
|
1175
|
+
*/
|
|
1176
|
+
getStorageAdapter() {
|
|
1177
|
+
return this.storage;
|
|
1178
|
+
}
|
|
1179
|
+
/**
|
|
1180
|
+
* Suppress event subscriptions — unsubscribe wallet/chat filters
|
|
1181
|
+
* but keep the connection alive for resolve/identity-binding operations.
|
|
1182
|
+
* Used when MultiAddressTransportMux takes over event handling.
|
|
1183
|
+
*/
|
|
1184
|
+
suppressSubscriptions() {
|
|
1185
|
+
if (!this.nostrClient) return;
|
|
1186
|
+
if (this.walletSubscriptionId) {
|
|
1187
|
+
this.nostrClient.unsubscribe(this.walletSubscriptionId);
|
|
1188
|
+
this.walletSubscriptionId = null;
|
|
1189
|
+
}
|
|
1190
|
+
if (this.chatSubscriptionId) {
|
|
1191
|
+
this.nostrClient.unsubscribe(this.chatSubscriptionId);
|
|
1192
|
+
this.chatSubscriptionId = null;
|
|
1193
|
+
}
|
|
1194
|
+
if (this.mainSubscriptionId) {
|
|
1195
|
+
this.nostrClient.unsubscribe(this.mainSubscriptionId);
|
|
1196
|
+
this.mainSubscriptionId = null;
|
|
1197
|
+
}
|
|
1198
|
+
this._subscriptionsSuppressed = true;
|
|
1199
|
+
logger.debug("Nostr", "Subscriptions suppressed \u2014 mux handles event routing");
|
|
1200
|
+
}
|
|
1201
|
+
// Flag to prevent re-subscription after suppressSubscriptions()
|
|
1202
|
+
_subscriptionsSuppressed = false;
|
|
1153
1203
|
// ===========================================================================
|
|
1154
1204
|
// BaseProvider Implementation
|
|
1155
1205
|
// ===========================================================================
|
|
@@ -1328,6 +1378,8 @@ var NostrTransportProvider = class {
|
|
|
1328
1378
|
// ===========================================================================
|
|
1329
1379
|
async setIdentity(identity) {
|
|
1330
1380
|
this.identity = identity;
|
|
1381
|
+
this.processedEventIds.clear();
|
|
1382
|
+
this.lastEventTs = 0;
|
|
1331
1383
|
const secretKey = import_buffer.Buffer.from(identity.privateKey, "hex");
|
|
1332
1384
|
this.keyManager = import_nostr_js_sdk.NostrKeyManager.fromPrivateKey(secretKey);
|
|
1333
1385
|
const nostrPubkey = this.keyManager.getPublicKeyHex();
|
|
@@ -1370,6 +1422,9 @@ var NostrTransportProvider = class {
|
|
|
1370
1422
|
await this.subscribeToEvents();
|
|
1371
1423
|
}
|
|
1372
1424
|
}
|
|
1425
|
+
setFallbackSince(sinceSeconds) {
|
|
1426
|
+
this.fallbackSince = sinceSeconds;
|
|
1427
|
+
}
|
|
1373
1428
|
/**
|
|
1374
1429
|
* Get the Nostr-format public key (32 bytes / 64 hex chars)
|
|
1375
1430
|
* This is the x-coordinate only, without the 02/03 prefix.
|
|
@@ -2277,6 +2332,10 @@ var NostrTransportProvider = class {
|
|
|
2277
2332
|
chatEoseFired = false;
|
|
2278
2333
|
async subscribeToEvents() {
|
|
2279
2334
|
logger.debug("Nostr", "subscribeToEvents called, identity:", !!this.identity, "keyManager:", !!this.keyManager, "nostrClient:", !!this.nostrClient);
|
|
2335
|
+
if (this._subscriptionsSuppressed) {
|
|
2336
|
+
logger.debug("Nostr", "subscribeToEvents: suppressed \u2014 mux handles event routing");
|
|
2337
|
+
return;
|
|
2338
|
+
}
|
|
2280
2339
|
if (!this.identity || !this.keyManager || !this.nostrClient) {
|
|
2281
2340
|
logger.debug("Nostr", "subscribeToEvents: skipped - no identity, keyManager, or nostrClient");
|
|
2282
2341
|
return;
|
|
@@ -2303,7 +2362,13 @@ var NostrTransportProvider = class {
|
|
|
2303
2362
|
if (stored) {
|
|
2304
2363
|
since = parseInt(stored, 10);
|
|
2305
2364
|
this.lastEventTs = since;
|
|
2365
|
+
this.fallbackSince = null;
|
|
2306
2366
|
logger.debug("Nostr", "Resuming from stored event timestamp:", since);
|
|
2367
|
+
} else if (this.fallbackSince !== null) {
|
|
2368
|
+
since = this.fallbackSince;
|
|
2369
|
+
this.lastEventTs = since;
|
|
2370
|
+
this.fallbackSince = null;
|
|
2371
|
+
logger.debug("Nostr", "Using fallback since timestamp:", since);
|
|
2307
2372
|
} else {
|
|
2308
2373
|
since = Math.floor(Date.now() / 1e3);
|
|
2309
2374
|
logger.debug("Nostr", "No stored timestamp, starting from now:", since);
|
|
@@ -2311,6 +2376,7 @@ var NostrTransportProvider = class {
|
|
|
2311
2376
|
} catch (err) {
|
|
2312
2377
|
logger.debug("Nostr", "Failed to read last event timestamp, falling back to now:", err);
|
|
2313
2378
|
since = Math.floor(Date.now() / 1e3);
|
|
2379
|
+
this.fallbackSince = null;
|
|
2314
2380
|
}
|
|
2315
2381
|
} else {
|
|
2316
2382
|
since = Math.floor(Date.now() / 1e3) - 86400;
|
|
@@ -4278,11 +4344,17 @@ var AsyncSerialQueue = class {
|
|
|
4278
4344
|
var WriteBuffer = class {
|
|
4279
4345
|
/** Full TXF data from save() calls — latest wins */
|
|
4280
4346
|
txfData = null;
|
|
4347
|
+
/** IPNS context captured at save() time — ensures flush writes to the correct
|
|
4348
|
+
* IPNS record even if identity changes between save() and flush(). */
|
|
4349
|
+
capturedIpnsKeyPair = null;
|
|
4350
|
+
capturedIpnsName = null;
|
|
4281
4351
|
get isEmpty() {
|
|
4282
4352
|
return this.txfData === null;
|
|
4283
4353
|
}
|
|
4284
4354
|
clear() {
|
|
4285
4355
|
this.txfData = null;
|
|
4356
|
+
this.capturedIpnsKeyPair = null;
|
|
4357
|
+
this.capturedIpnsName = null;
|
|
4286
4358
|
}
|
|
4287
4359
|
/**
|
|
4288
4360
|
* Merge another buffer's contents into this one (for rollback).
|
|
@@ -4291,12 +4363,14 @@ var WriteBuffer = class {
|
|
|
4291
4363
|
mergeFrom(other) {
|
|
4292
4364
|
if (other.txfData && !this.txfData) {
|
|
4293
4365
|
this.txfData = other.txfData;
|
|
4366
|
+
this.capturedIpnsKeyPair = other.capturedIpnsKeyPair;
|
|
4367
|
+
this.capturedIpnsName = other.capturedIpnsName;
|
|
4294
4368
|
}
|
|
4295
4369
|
}
|
|
4296
4370
|
};
|
|
4297
4371
|
|
|
4298
4372
|
// impl/shared/ipfs/ipfs-storage-provider.ts
|
|
4299
|
-
var IpfsStorageProvider = class {
|
|
4373
|
+
var IpfsStorageProvider = class _IpfsStorageProvider {
|
|
4300
4374
|
id = "ipfs";
|
|
4301
4375
|
name = "IPFS Storage";
|
|
4302
4376
|
type = "p2p";
|
|
@@ -4341,7 +4415,12 @@ var IpfsStorageProvider = class {
|
|
|
4341
4415
|
flushDebounceMs;
|
|
4342
4416
|
/** Set to true during shutdown to prevent new flushes */
|
|
4343
4417
|
isShuttingDown = false;
|
|
4418
|
+
/** Stored config for createForAddress() cloning */
|
|
4419
|
+
_config;
|
|
4420
|
+
_statePersistenceCtor;
|
|
4344
4421
|
constructor(config, statePersistence) {
|
|
4422
|
+
this._config = config;
|
|
4423
|
+
this._statePersistenceCtor = statePersistence;
|
|
4345
4424
|
const gateways = config?.gateways ?? getIpfsGatewayUrls();
|
|
4346
4425
|
this.debug = config?.debug ?? false;
|
|
4347
4426
|
this.ipnsLifetimeMs = config?.ipnsLifetimeMs ?? 99 * 365 * 24 * 60 * 60 * 1e3;
|
|
@@ -4461,6 +4540,7 @@ var IpfsStorageProvider = class {
|
|
|
4461
4540
|
}
|
|
4462
4541
|
async shutdown() {
|
|
4463
4542
|
this.isShuttingDown = true;
|
|
4543
|
+
logger.debug("IPFS-Storage", `shutdown: ipnsName=${this.ipnsName?.slice(0, 20)}..., pendingEmpty=${this.pendingBuffer.isEmpty}, capturedIpns=${this.pendingBuffer.capturedIpnsName?.slice(0, 20) ?? "none"}`);
|
|
4464
4544
|
if (this.flushTimer) {
|
|
4465
4545
|
clearTimeout(this.flushTimer);
|
|
4466
4546
|
this.flushTimer = null;
|
|
@@ -4493,6 +4573,8 @@ var IpfsStorageProvider = class {
|
|
|
4493
4573
|
return { success: false, error: "Not initialized", timestamp: Date.now() };
|
|
4494
4574
|
}
|
|
4495
4575
|
this.pendingBuffer.txfData = data;
|
|
4576
|
+
this.pendingBuffer.capturedIpnsKeyPair = this.ipnsKeyPair;
|
|
4577
|
+
this.pendingBuffer.capturedIpnsName = this.ipnsName;
|
|
4496
4578
|
this.scheduleFlush();
|
|
4497
4579
|
return { success: true, timestamp: Date.now() };
|
|
4498
4580
|
}
|
|
@@ -4503,8 +4585,12 @@ var IpfsStorageProvider = class {
|
|
|
4503
4585
|
* Perform the actual upload + IPNS publish synchronously.
|
|
4504
4586
|
* Called by executeFlush() and sync() — never by public save().
|
|
4505
4587
|
*/
|
|
4506
|
-
async _doSave(data) {
|
|
4507
|
-
|
|
4588
|
+
async _doSave(data, overrideIpns) {
|
|
4589
|
+
const ipnsKeyPair = overrideIpns?.keyPair ?? this.ipnsKeyPair;
|
|
4590
|
+
const ipnsName = overrideIpns?.name ?? this.ipnsName;
|
|
4591
|
+
const metaAddr = data?._meta?.address;
|
|
4592
|
+
logger.debug("IPFS-Storage", `_doSave: ipnsName=${ipnsName?.slice(0, 20)}..., override=${!!overrideIpns}, meta.address=${metaAddr?.slice(0, 20) ?? "none"}`);
|
|
4593
|
+
if (!ipnsKeyPair || !ipnsName) {
|
|
4508
4594
|
return { success: false, error: "Not initialized", timestamp: Date.now() };
|
|
4509
4595
|
}
|
|
4510
4596
|
this.emitEvent({ type: "storage:saving", timestamp: Date.now() });
|
|
@@ -4513,7 +4599,7 @@ var IpfsStorageProvider = class {
|
|
|
4513
4599
|
const metaUpdate = {
|
|
4514
4600
|
...data._meta,
|
|
4515
4601
|
version: this.dataVersion,
|
|
4516
|
-
ipnsName
|
|
4602
|
+
ipnsName,
|
|
4517
4603
|
updatedAt: Date.now()
|
|
4518
4604
|
};
|
|
4519
4605
|
if (this.remoteCid) {
|
|
@@ -4525,13 +4611,13 @@ var IpfsStorageProvider = class {
|
|
|
4525
4611
|
const baseSeq = this.ipnsSequenceNumber > this.lastKnownRemoteSequence ? this.ipnsSequenceNumber : this.lastKnownRemoteSequence;
|
|
4526
4612
|
const newSeq = baseSeq + 1n;
|
|
4527
4613
|
const marshalledRecord = await createSignedRecord(
|
|
4528
|
-
|
|
4614
|
+
ipnsKeyPair,
|
|
4529
4615
|
cid,
|
|
4530
4616
|
newSeq,
|
|
4531
4617
|
this.ipnsLifetimeMs
|
|
4532
4618
|
);
|
|
4533
4619
|
const publishResult = await this.httpClient.publishIpns(
|
|
4534
|
-
|
|
4620
|
+
ipnsName,
|
|
4535
4621
|
marshalledRecord
|
|
4536
4622
|
);
|
|
4537
4623
|
if (!publishResult.success) {
|
|
@@ -4546,14 +4632,14 @@ var IpfsStorageProvider = class {
|
|
|
4546
4632
|
this.ipnsSequenceNumber = newSeq;
|
|
4547
4633
|
this.lastCid = cid;
|
|
4548
4634
|
this.remoteCid = cid;
|
|
4549
|
-
this.cache.setIpnsRecord(
|
|
4635
|
+
this.cache.setIpnsRecord(ipnsName, {
|
|
4550
4636
|
cid,
|
|
4551
4637
|
sequence: newSeq,
|
|
4552
4638
|
gateway: "local"
|
|
4553
4639
|
});
|
|
4554
4640
|
this.cache.setContent(cid, updatedData);
|
|
4555
|
-
this.cache.markIpnsFresh(
|
|
4556
|
-
await this.statePersistence.save(
|
|
4641
|
+
this.cache.markIpnsFresh(ipnsName);
|
|
4642
|
+
await this.statePersistence.save(ipnsName, {
|
|
4557
4643
|
sequenceNumber: newSeq.toString(),
|
|
4558
4644
|
lastCid: cid,
|
|
4559
4645
|
version: this.dataVersion
|
|
@@ -4605,7 +4691,8 @@ var IpfsStorageProvider = class {
|
|
|
4605
4691
|
const baseData = active.txfData ?? {
|
|
4606
4692
|
_meta: { version: 0, address: this.identity?.directAddress ?? "", formatVersion: "2.0", updatedAt: 0 }
|
|
4607
4693
|
};
|
|
4608
|
-
const
|
|
4694
|
+
const overrideIpns = active.capturedIpnsKeyPair && active.capturedIpnsName ? { keyPair: active.capturedIpnsKeyPair, name: active.capturedIpnsName } : void 0;
|
|
4695
|
+
const result = await this._doSave(baseData, overrideIpns);
|
|
4609
4696
|
if (!result.success) {
|
|
4610
4697
|
throw new SphereError(result.error ?? "Save failed", "STORAGE_ERROR");
|
|
4611
4698
|
}
|
|
@@ -4908,6 +4995,13 @@ var IpfsStorageProvider = class {
|
|
|
4908
4995
|
log(message) {
|
|
4909
4996
|
logger.debug("IPFS-Storage", message);
|
|
4910
4997
|
}
|
|
4998
|
+
/**
|
|
4999
|
+
* Create an independent instance for a different address.
|
|
5000
|
+
* Shares the same gateway/timeout config but has fresh IPNS state.
|
|
5001
|
+
*/
|
|
5002
|
+
createForAddress() {
|
|
5003
|
+
return new _IpfsStorageProvider(this._config, this._statePersistenceCtor);
|
|
5004
|
+
}
|
|
4911
5005
|
};
|
|
4912
5006
|
|
|
4913
5007
|
// impl/nodejs/ipfs/nodejs-ipfs-state-persistence.ts
|