@unicitylabs/sphere-sdk 0.14.10 → 0.14.11-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/connect/index.cjs +1 -1
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/index.js +1 -1
- package/dist/connect/index.js.map +1 -1
- package/dist/core/index.cjs +139 -16
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +2 -0
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.js +139 -16
- package/dist/core/index.js.map +1 -1
- package/dist/impl/browser/connect/index.cjs +1 -1
- package/dist/impl/browser/connect/index.cjs.map +1 -1
- package/dist/impl/browser/connect/index.js +1 -1
- package/dist/impl/browser/connect/index.js.map +1 -1
- package/dist/index.cjs +139 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +139 -16
- package/dist/index.js.map +1 -1
- package/dist/modules/payments-v2/index.cjs +139 -16
- package/dist/modules/payments-v2/index.cjs.map +1 -1
- package/dist/modules/payments-v2/index.d.cts +6 -2
- package/dist/modules/payments-v2/index.d.ts +6 -2
- package/dist/modules/payments-v2/index.js +139 -16
- package/dist/modules/payments-v2/index.js.map +1 -1
- package/package.json +1 -1
package/dist/core/index.cjs
CHANGED
|
@@ -12359,6 +12359,90 @@ async function splitOpIndex(deps, envelope) {
|
|
|
12359
12359
|
return Array.isArray(payload.direct) ? payload.direct.length : 0;
|
|
12360
12360
|
}
|
|
12361
12361
|
|
|
12362
|
+
// modules/payments-v2/mint-params.ts
|
|
12363
|
+
function mintParams(recipientPubkey, coinId, amount) {
|
|
12364
|
+
return { recipientPubkey, value: { assets: [{ coinId, amount }] } };
|
|
12365
|
+
}
|
|
12366
|
+
|
|
12367
|
+
// modules/payments-v2/prewarm-cache.ts
|
|
12368
|
+
var PrewarmCache = class _PrewarmCache {
|
|
12369
|
+
entries = /* @__PURE__ */ new Map();
|
|
12370
|
+
generation = 0;
|
|
12371
|
+
static key(tokenId, stateHash) {
|
|
12372
|
+
return `${tokenId}:${stateHash}`;
|
|
12373
|
+
}
|
|
12374
|
+
/** Claim the cache for a warm about to start; supersedes any warm already running. */
|
|
12375
|
+
begin() {
|
|
12376
|
+
this.entries.clear();
|
|
12377
|
+
this.generation += 1;
|
|
12378
|
+
return this.generation;
|
|
12379
|
+
}
|
|
12380
|
+
/**
|
|
12381
|
+
* Publish a warm's result, unless it was cancelled or superseded while its
|
|
12382
|
+
* fetch was in flight — a cancel that only cleared what had landed so far
|
|
12383
|
+
* would be undone by the continuation of the very warm it cancelled.
|
|
12384
|
+
*/
|
|
12385
|
+
commit(generation, warmed) {
|
|
12386
|
+
if (generation !== this.generation) return;
|
|
12387
|
+
for (const [tokenId, stateHash, bytes] of warmed) {
|
|
12388
|
+
this.entries.set(_PrewarmCache.key(tokenId, stateHash), bytes);
|
|
12389
|
+
}
|
|
12390
|
+
}
|
|
12391
|
+
get(tokenId, stateHash) {
|
|
12392
|
+
if (stateHash === void 0) return void 0;
|
|
12393
|
+
return this.entries.get(_PrewarmCache.key(tokenId, stateHash));
|
|
12394
|
+
}
|
|
12395
|
+
clear() {
|
|
12396
|
+
this.entries.clear();
|
|
12397
|
+
this.generation += 1;
|
|
12398
|
+
}
|
|
12399
|
+
get size() {
|
|
12400
|
+
return this.entries.size;
|
|
12401
|
+
}
|
|
12402
|
+
};
|
|
12403
|
+
async function warmSendSources(deps, request) {
|
|
12404
|
+
const ids = deps.queue.previewSelection(request);
|
|
12405
|
+
if (ids.length === 0) return;
|
|
12406
|
+
const generation = deps.cache.begin();
|
|
12407
|
+
const at = new Map(ids.map((id) => [id, deps.view.stateHashOf(id)]));
|
|
12408
|
+
let blobs;
|
|
12409
|
+
try {
|
|
12410
|
+
blobs = await deps.storagePort.getBlobs([...ids]);
|
|
12411
|
+
} catch {
|
|
12412
|
+
return;
|
|
12413
|
+
}
|
|
12414
|
+
const warmed = [];
|
|
12415
|
+
for (const [tokenId, bytes] of blobs) {
|
|
12416
|
+
const stateHash = at.get(tokenId);
|
|
12417
|
+
if (stateHash !== void 0) warmed.push([tokenId, stateHash, bytes]);
|
|
12418
|
+
}
|
|
12419
|
+
deps.cache.commit(generation, warmed);
|
|
12420
|
+
}
|
|
12421
|
+
async function takeSourceBlobs(deps, sourceIds) {
|
|
12422
|
+
const blobs = /* @__PURE__ */ new Map();
|
|
12423
|
+
const missing = [];
|
|
12424
|
+
let trustCache = deps.cache.size > 0;
|
|
12425
|
+
if (trustCache) {
|
|
12426
|
+
try {
|
|
12427
|
+
await deps.view.delta();
|
|
12428
|
+
} catch {
|
|
12429
|
+
trustCache = false;
|
|
12430
|
+
}
|
|
12431
|
+
}
|
|
12432
|
+
for (const tokenId of sourceIds) {
|
|
12433
|
+
const warm = trustCache ? deps.cache.get(tokenId, deps.view.stateHashOf(tokenId)) : void 0;
|
|
12434
|
+
if (warm === void 0) missing.push(tokenId);
|
|
12435
|
+
else blobs.set(tokenId, warm);
|
|
12436
|
+
}
|
|
12437
|
+
deps.cache.clear();
|
|
12438
|
+
if (missing.length > 0) {
|
|
12439
|
+
for (const [tokenId, bytes] of await deps.storagePort.getBlobs(missing)) {
|
|
12440
|
+
blobs.set(tokenId, bytes);
|
|
12441
|
+
}
|
|
12442
|
+
}
|
|
12443
|
+
return blobs;
|
|
12444
|
+
}
|
|
12445
|
+
|
|
12362
12446
|
// modules/payments-v2/inventory/presentation.ts
|
|
12363
12447
|
function toToken(tokenId, snapshot, asset, registry, flags) {
|
|
12364
12448
|
const iconUrl = registry.getIconUrl(asset.coinId);
|
|
@@ -12445,6 +12529,13 @@ function priceOne(asset, quote) {
|
|
|
12445
12529
|
fiatValueEur: quote.priceEur != null ? human * quote.priceEur : null
|
|
12446
12530
|
};
|
|
12447
12531
|
}
|
|
12532
|
+
function transferringToken(tokenId, coinId, amount, registry, now) {
|
|
12533
|
+
const snapshot = { assets: [], createdAt: now, updatedAt: now };
|
|
12534
|
+
return toToken(tokenId, snapshot, { coinId, amount: amount.toString() }, registry, {
|
|
12535
|
+
transferring: true,
|
|
12536
|
+
suspectedSpent: false
|
|
12537
|
+
});
|
|
12538
|
+
}
|
|
12448
12539
|
|
|
12449
12540
|
// modules/payments-v2/machine/payload.ts
|
|
12450
12541
|
function buildPayload(recipientPubkey, request, spend, spentStates) {
|
|
@@ -12683,6 +12774,15 @@ var InventoryView = class {
|
|
|
12683
12774
|
}
|
|
12684
12775
|
return out;
|
|
12685
12776
|
}
|
|
12777
|
+
/**
|
|
12778
|
+
* Current mirrored state of an ACTIVE token, or undefined when it is unknown
|
|
12779
|
+
* or tombstoned. Exists so a cached blob can be state-scoped (F6): a blob is
|
|
12780
|
+
* only reusable while the token still sits at the state it was fetched at.
|
|
12781
|
+
*/
|
|
12782
|
+
stateHashOf(tokenId) {
|
|
12783
|
+
const entry = this.mirror.get(tokenId);
|
|
12784
|
+
return entry !== void 0 && entry.status === "active" ? entry.stateHash : void 0;
|
|
12785
|
+
}
|
|
12686
12786
|
tokens(registry, filter) {
|
|
12687
12787
|
const out = [];
|
|
12688
12788
|
for (const [tokenId, entry] of this.mirror) {
|
|
@@ -13602,6 +13702,31 @@ var SpendQueue = class {
|
|
|
13602
13702
|
}
|
|
13603
13703
|
return { kind: "queued", settled: this.enqueue(reservationId, request.coinId, amount) };
|
|
13604
13704
|
}
|
|
13705
|
+
/**
|
|
13706
|
+
* The sources `plan()` WOULD pick right now, reserving nothing and queueing
|
|
13707
|
+
* nothing — a read-only probe used to warm blobs while the user is still
|
|
13708
|
+
* looking at the confirm screen.
|
|
13709
|
+
*
|
|
13710
|
+
* Deliberately side-effect free: reserving here would pin the user's balance
|
|
13711
|
+
* across think-time and strand it if they never press send. The consequence is
|
|
13712
|
+
* that the real `plan()` may pick differently (inventory moves, another send
|
|
13713
|
+
* reserves first); callers must treat the result as a HINT and tolerate a miss,
|
|
13714
|
+
* never as a commitment that these sources will be spent.
|
|
13715
|
+
*/
|
|
13716
|
+
previewSelection(request) {
|
|
13717
|
+
if (this.destroyed) return [];
|
|
13718
|
+
let amount;
|
|
13719
|
+
try {
|
|
13720
|
+
amount = parseAmount(request.amount);
|
|
13721
|
+
} catch {
|
|
13722
|
+
return [];
|
|
13723
|
+
}
|
|
13724
|
+
const { freeView, freeTotal } = this.freeView(request.coinId);
|
|
13725
|
+
if (freeTotal < amount) return [];
|
|
13726
|
+
const plan = selectCoins(freeView, amount, { workBudget: this.deps.workBudget });
|
|
13727
|
+
if (plan === null) return [];
|
|
13728
|
+
return [...plan.direct, ...plan.split !== void 0 ? [plan.split.tokenId] : []];
|
|
13729
|
+
}
|
|
13605
13730
|
// Coverage math: free + Σ declared expected change of in-flight sends —
|
|
13606
13731
|
// never the full amount of in-flight sources (§5.3).
|
|
13607
13732
|
declareExpectedChange(transferId, coinId, amount) {
|
|
@@ -13951,6 +14076,7 @@ var PaymentsFacade = class {
|
|
|
13951
14076
|
now: () => this.nowMs()
|
|
13952
14077
|
});
|
|
13953
14078
|
}
|
|
14079
|
+
prewarmed = new PrewarmCache();
|
|
13954
14080
|
view;
|
|
13955
14081
|
ledger;
|
|
13956
14082
|
queue;
|
|
@@ -14044,6 +14170,15 @@ var PaymentsFacade = class {
|
|
|
14044
14170
|
return derivePendingTransfers(this.machineStores, this.machineDeps.decryptPayload);
|
|
14045
14171
|
}
|
|
14046
14172
|
// ── money movement ─────────────────────────────────────────────────────────
|
|
14173
|
+
async prewarmSend(request) {
|
|
14174
|
+
await warmSendSources(this.warmDeps(), request);
|
|
14175
|
+
}
|
|
14176
|
+
discardPrewarm() {
|
|
14177
|
+
this.prewarmed.clear();
|
|
14178
|
+
}
|
|
14179
|
+
warmDeps() {
|
|
14180
|
+
return { queue: this.queue, view: this.view, storagePort: this.deps.storagePort, cache: this.prewarmed };
|
|
14181
|
+
}
|
|
14047
14182
|
send(request) {
|
|
14048
14183
|
return this.track(this.sendOutcome(request));
|
|
14049
14184
|
}
|
|
@@ -14253,7 +14388,7 @@ var PaymentsFacade = class {
|
|
|
14253
14388
|
}
|
|
14254
14389
|
async materialize(transferId, recipientPubkey, request, spend, sourceIds) {
|
|
14255
14390
|
const engine = this.engine();
|
|
14256
|
-
const blobs = await this.
|
|
14391
|
+
const blobs = await takeSourceBlobs(this.warmDeps(), sourceIds);
|
|
14257
14392
|
const sources = /* @__PURE__ */ new Map();
|
|
14258
14393
|
const sourceTokens = [];
|
|
14259
14394
|
const spentStates = {};
|
|
@@ -14266,7 +14401,7 @@ var PaymentsFacade = class {
|
|
|
14266
14401
|
const keys = await engine.deliveryKeys(bytes);
|
|
14267
14402
|
spentStates[tokenId] = { local: keys.stateHash, protocol: keys.stateHash };
|
|
14268
14403
|
sources.set(tokenId, token);
|
|
14269
|
-
sourceTokens.push(
|
|
14404
|
+
sourceTokens.push(transferringToken(tokenId, request.coinId, engine.balanceOf(token, request.coinId), this.deps.registry, this.nowMs()));
|
|
14270
14405
|
}
|
|
14271
14406
|
const payload = buildPayload(recipientPubkey, request, spend, spentStates);
|
|
14272
14407
|
const plan = {
|
|
@@ -14410,7 +14545,7 @@ var PaymentsFacade = class {
|
|
|
14410
14545
|
await this.machineStores.mintJournal.upsert(entry);
|
|
14411
14546
|
let token;
|
|
14412
14547
|
try {
|
|
14413
|
-
token = await engine.mint(this.
|
|
14548
|
+
token = await engine.mint(mintParams(this.ownPubkeyBytes, coinId, amount), { transferId: mintId });
|
|
14414
14549
|
} catch (err) {
|
|
14415
14550
|
this.heartbeat.arm();
|
|
14416
14551
|
return { success: false, error: messageOf(err) };
|
|
@@ -14469,7 +14604,7 @@ var PaymentsFacade = class {
|
|
|
14469
14604
|
});
|
|
14470
14605
|
return false;
|
|
14471
14606
|
}
|
|
14472
|
-
const token = await engine.mint(this.
|
|
14607
|
+
const token = await engine.mint(mintParams(this.ownPubkeyBytes, entry.coinId, BigInt(entry.amount)), {
|
|
14473
14608
|
transferId: entry.mintId
|
|
14474
14609
|
});
|
|
14475
14610
|
if (token.blob.tokenId !== entry.tokenId) {
|
|
@@ -14478,12 +14613,6 @@ var PaymentsFacade = class {
|
|
|
14478
14613
|
await this.finalizeMint(engine, entry.mintId, token, entry.coinId, entry.amount);
|
|
14479
14614
|
return true;
|
|
14480
14615
|
}
|
|
14481
|
-
mintParams(coinId, amount) {
|
|
14482
|
-
return {
|
|
14483
|
-
recipientPubkey: this.ownPubkeyBytes,
|
|
14484
|
-
value: { assets: [{ coinId, amount }] }
|
|
14485
|
-
};
|
|
14486
|
-
}
|
|
14487
14616
|
async tokenInServerInventory(tokenId) {
|
|
14488
14617
|
let page = await this.deps.storagePort.listInventory();
|
|
14489
14618
|
for (let i = 0; i < INVENTORY_SCAN_PAGE_LIMIT; i++) {
|
|
@@ -14512,12 +14641,6 @@ var PaymentsFacade = class {
|
|
|
14512
14641
|
page = await this.deps.storagePort.listInventory(page.cursor);
|
|
14513
14642
|
}
|
|
14514
14643
|
}
|
|
14515
|
-
toUiToken(tokenId, coinId, amount) {
|
|
14516
|
-
const now = this.nowMs();
|
|
14517
|
-
const snapshot = { assets: [], createdAt: now, updatedAt: now };
|
|
14518
|
-
const flags = { transferring: true, suspectedSpent: false };
|
|
14519
|
-
return toToken(tokenId, snapshot, { coinId, amount: amount.toString() }, this.deps.registry, flags);
|
|
14520
|
-
}
|
|
14521
14644
|
track(op) {
|
|
14522
14645
|
const settled = op.then(() => void 0, () => void 0);
|
|
14523
14646
|
this.pendingOps.add(settled);
|