@unicitylabs/sphere-sdk 0.14.11-dev.5 → 0.14.11-dev.7
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 +180 -31
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.js +180 -31
- 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/impl/wallet-api-v2/index.cjs +72 -3
- package/dist/impl/wallet-api-v2/index.cjs.map +1 -1
- package/dist/impl/wallet-api-v2/index.d.cts +25 -1
- package/dist/impl/wallet-api-v2/index.d.ts +25 -1
- package/dist/impl/wallet-api-v2/index.js +72 -3
- package/dist/impl/wallet-api-v2/index.js.map +1 -1
- package/dist/index.cjs +180 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +180 -31
- package/dist/index.js.map +1 -1
- package/dist/modules/payments-v2/index.cjs +108 -28
- package/dist/modules/payments-v2/index.cjs.map +1 -1
- package/dist/modules/payments-v2/index.d.cts +15 -0
- package/dist/modules/payments-v2/index.d.ts +15 -0
- package/dist/modules/payments-v2/index.js +108 -28
- package/dist/modules/payments-v2/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -581,6 +581,26 @@ var SerialChain = class {
|
|
|
581
581
|
return run;
|
|
582
582
|
}
|
|
583
583
|
};
|
|
584
|
+
function coalesced(run) {
|
|
585
|
+
let inFlight = false;
|
|
586
|
+
let queued = false;
|
|
587
|
+
const start = () => {
|
|
588
|
+
inFlight = true;
|
|
589
|
+
void run().catch(() => void 0).finally(() => {
|
|
590
|
+
inFlight = false;
|
|
591
|
+
if (!queued) return;
|
|
592
|
+
queued = false;
|
|
593
|
+
start();
|
|
594
|
+
});
|
|
595
|
+
};
|
|
596
|
+
return () => {
|
|
597
|
+
if (inFlight) {
|
|
598
|
+
queued = true;
|
|
599
|
+
return;
|
|
600
|
+
}
|
|
601
|
+
start();
|
|
602
|
+
};
|
|
603
|
+
}
|
|
584
604
|
|
|
585
605
|
// modules/payments-v2/machine/journal.ts
|
|
586
606
|
var MAX_DELIVERY_ATTEMPTS = 6;
|
|
@@ -2886,6 +2906,16 @@ var InventoryView = class {
|
|
|
2886
2906
|
this.inFlight.add(tokenId);
|
|
2887
2907
|
this.deps.emit("inventory:updated");
|
|
2888
2908
|
}
|
|
2909
|
+
/** Reserve a whole plan as ONE change — per token emitted 54 events per send. */
|
|
2910
|
+
markInFlightMany(tokenIds) {
|
|
2911
|
+
let changed = false;
|
|
2912
|
+
for (const tokenId of tokenIds) {
|
|
2913
|
+
if (this.inFlight.has(tokenId)) continue;
|
|
2914
|
+
this.inFlight.add(tokenId);
|
|
2915
|
+
changed = true;
|
|
2916
|
+
}
|
|
2917
|
+
if (changed) this.deps.emit("inventory:updated");
|
|
2918
|
+
}
|
|
2889
2919
|
release(tokenId) {
|
|
2890
2920
|
if (this.inFlight.delete(tokenId)) this.deps.emit("inventory:updated");
|
|
2891
2921
|
}
|
|
@@ -3202,6 +3232,11 @@ var logger = {
|
|
|
3202
3232
|
}
|
|
3203
3233
|
};
|
|
3204
3234
|
|
|
3235
|
+
// modules/payments-v2/ports.ts
|
|
3236
|
+
function isRetryableAckError(err) {
|
|
3237
|
+
return err !== null && typeof err === "object" && err.retryable === true;
|
|
3238
|
+
}
|
|
3239
|
+
|
|
3205
3240
|
// modules/payments-v2/receive/Receive.ts
|
|
3206
3241
|
var ACK_BATCH_SIZE = 200;
|
|
3207
3242
|
var REFRESH_INTERVAL_MS = 2500;
|
|
@@ -3283,6 +3318,7 @@ var Receive = class {
|
|
|
3283
3318
|
}
|
|
3284
3319
|
} catch (err) {
|
|
3285
3320
|
logger.warn("PaymentsV2", "receive drain interrupted \u2014 unacked entries retry next drain:", err);
|
|
3321
|
+
if (isRetryableAckError(err)) return stored;
|
|
3286
3322
|
await flushAcks(deps, pending, pageEpoch).catch((flushErr) => {
|
|
3287
3323
|
logger.warn("PaymentsV2", "receive ack flush failed \u2014 cursor holds at the acked prefix:", flushErr);
|
|
3288
3324
|
});
|
|
@@ -3357,14 +3393,18 @@ async function announce(deps, entry, record) {
|
|
|
3357
3393
|
};
|
|
3358
3394
|
}
|
|
3359
3395
|
async function flushAcks(deps, pending, epochOf) {
|
|
3396
|
+
if (pending.length === 0) return;
|
|
3360
3397
|
let lastAcked = null;
|
|
3361
3398
|
try {
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
lastAcked =
|
|
3366
|
-
|
|
3399
|
+
const settled = await settleAcks(deps, pending);
|
|
3400
|
+
let i = 0;
|
|
3401
|
+
while (i < pending.length && settled.has(pending[i].deliveryId)) {
|
|
3402
|
+
lastAcked = pending[i].cursor;
|
|
3403
|
+
i += 1;
|
|
3367
3404
|
}
|
|
3405
|
+
const stuck = pending.filter((p) => !settled.has(p.deliveryId));
|
|
3406
|
+
pending.length = 0;
|
|
3407
|
+
pending.push(...stuck);
|
|
3368
3408
|
} finally {
|
|
3369
3409
|
if (lastAcked !== null) {
|
|
3370
3410
|
const record = { cursor: lastAcked, syncEpoch: epochOf() };
|
|
@@ -3372,14 +3412,65 @@ async function flushAcks(deps, pending, epochOf) {
|
|
|
3372
3412
|
}
|
|
3373
3413
|
}
|
|
3374
3414
|
}
|
|
3415
|
+
async function settleAcks(deps, pending) {
|
|
3416
|
+
const batch = deps.delivery.ackBatch?.bind(deps.delivery);
|
|
3417
|
+
if (batch === void 0) return settleOneByOne(deps, pending);
|
|
3418
|
+
let outcomes;
|
|
3419
|
+
try {
|
|
3420
|
+
outcomes = await batch(pending.map(toAckRequest));
|
|
3421
|
+
} catch (err) {
|
|
3422
|
+
if (isRetryableAckError(err)) throw err;
|
|
3423
|
+
logger.warn("PaymentsV2", "batched mailbox ack failed \u2014 settling one at a time:", err);
|
|
3424
|
+
return settleOneByOne(deps, pending);
|
|
3425
|
+
}
|
|
3426
|
+
const settled = new Set(outcomes.filter((o) => o.status === "settled").map((o) => o.deliveryId));
|
|
3427
|
+
const conflicts = outcomes.filter((o) => o.status === "conflict").map((o) => o.deliveryId);
|
|
3428
|
+
if (conflicts.length > 0) await resolveConflicts(deps, pending, conflicts, settled);
|
|
3429
|
+
return settled;
|
|
3430
|
+
}
|
|
3431
|
+
async function resolveConflicts(deps, pending, conflicts, settled) {
|
|
3432
|
+
for (const deliveryId of conflicts) {
|
|
3433
|
+
const entry = pending.find((p) => p.deliveryId === deliveryId);
|
|
3434
|
+
try {
|
|
3435
|
+
await rejectStaleClaim(deps, deliveryId, entry?.transferId);
|
|
3436
|
+
} catch (err) {
|
|
3437
|
+
logger.warn("PaymentsV2", `stale-reject failed for ${deliveryId} \u2014 cursor holds here:`, err);
|
|
3438
|
+
continue;
|
|
3439
|
+
}
|
|
3440
|
+
settled.add(deliveryId);
|
|
3441
|
+
}
|
|
3442
|
+
}
|
|
3443
|
+
async function rejectStaleClaim(deps, deliveryId, transferId) {
|
|
3444
|
+
logger.warn("PaymentsV2", `mailbox claim CONFLICT for ${deliveryId} \u2014 rejected('other') as stale`);
|
|
3445
|
+
await deps.delivery.ack(deliveryId, "rejected", "other");
|
|
3446
|
+
deps.attention(transferId ?? "", ATTENTION_CLAIM_CONFLICT, deliveryId);
|
|
3447
|
+
}
|
|
3448
|
+
async function settleOneByOne(deps, pending) {
|
|
3449
|
+
const settled = /* @__PURE__ */ new Set();
|
|
3450
|
+
for (const ack of pending) {
|
|
3451
|
+
try {
|
|
3452
|
+
await ackOne(deps, ack);
|
|
3453
|
+
} catch (err) {
|
|
3454
|
+
logger.warn("PaymentsV2", `mailbox ack failed for ${ack.deliveryId} \u2014 cursor holds here:`, err);
|
|
3455
|
+
break;
|
|
3456
|
+
}
|
|
3457
|
+
settled.add(ack.deliveryId);
|
|
3458
|
+
}
|
|
3459
|
+
return settled;
|
|
3460
|
+
}
|
|
3461
|
+
function toAckRequest(ack) {
|
|
3462
|
+
return {
|
|
3463
|
+
deliveryId: ack.deliveryId,
|
|
3464
|
+
disposition: ack.disposition,
|
|
3465
|
+
...ack.reason !== void 0 ? { reason: ack.reason } : {}
|
|
3466
|
+
};
|
|
3467
|
+
}
|
|
3375
3468
|
async function ackOne(deps, ack) {
|
|
3376
3469
|
try {
|
|
3377
3470
|
await deps.delivery.ack(ack.deliveryId, ack.disposition, ack.reason);
|
|
3378
3471
|
} catch (err) {
|
|
3379
3472
|
if (ack.disposition !== "claimed" || !isClaimConflict(err)) throw err;
|
|
3380
|
-
|
|
3381
|
-
await deps.delivery.ack(ack.deliveryId, "rejected", "other");
|
|
3382
|
-
deps.attention(ack.transferId ?? "", ATTENTION_CLAIM_CONFLICT, ack.deliveryId);
|
|
3473
|
+
await rejectStaleClaim(deps, ack.deliveryId, ack.transferId);
|
|
3383
3474
|
}
|
|
3384
3475
|
}
|
|
3385
3476
|
function claimAck(entry) {
|
|
@@ -4133,16 +4224,6 @@ function parseAmount(raw) {
|
|
|
4133
4224
|
function supportsDeterministicMint(engine) {
|
|
4134
4225
|
return engine.deterministicMint === true;
|
|
4135
4226
|
}
|
|
4136
|
-
function makeSingleFlightRefresh(refresh) {
|
|
4137
|
-
let inFlight = false;
|
|
4138
|
-
return () => {
|
|
4139
|
-
if (inFlight) return;
|
|
4140
|
-
inFlight = true;
|
|
4141
|
-
void refresh().catch(() => void 0).finally(() => {
|
|
4142
|
-
inFlight = false;
|
|
4143
|
-
});
|
|
4144
|
-
};
|
|
4145
|
-
}
|
|
4146
4227
|
function composeFacadeParts(deps, hooks) {
|
|
4147
4228
|
const ownPubkeyBytes = hexToBytes(deps.ownPubkey);
|
|
4148
4229
|
const ledger = new ReservationLedger();
|
|
@@ -4172,9 +4253,11 @@ function composeFacadeParts(deps, hooks) {
|
|
|
4172
4253
|
const machineDeps = buildMachineDeps(deps, hooks, historyStore);
|
|
4173
4254
|
const machineStores = createMachineStores(deps.kv);
|
|
4174
4255
|
const heldStates = /* @__PURE__ */ new Map();
|
|
4256
|
+
const refreshView = coalesced(() => view.delta());
|
|
4175
4257
|
return {
|
|
4176
4258
|
ownPubkeyBytes,
|
|
4177
4259
|
view,
|
|
4260
|
+
refreshView,
|
|
4178
4261
|
ledger,
|
|
4179
4262
|
pins: buildPins(deps, hooks, { ledger, view, machineStores, machineDeps }),
|
|
4180
4263
|
queue,
|
|
@@ -4183,7 +4266,7 @@ function composeFacadeParts(deps, hooks) {
|
|
|
4183
4266
|
machineDeps,
|
|
4184
4267
|
machine: new TransferMachine(machineDeps),
|
|
4185
4268
|
heldStates,
|
|
4186
|
-
receiveLoop: buildReceive(deps, hooks, historyStore, heldStates,
|
|
4269
|
+
receiveLoop: buildReceive(deps, hooks, historyStore, heldStates, refreshView),
|
|
4187
4270
|
requests: buildRequests(deps, hooks),
|
|
4188
4271
|
restoreDeps: buildRestoreDeps(deps, machineDeps, machineStores, view)
|
|
4189
4272
|
};
|
|
@@ -4250,7 +4333,7 @@ function buildMachineDeps(deps, hooks, historyStore) {
|
|
|
4250
4333
|
}
|
|
4251
4334
|
};
|
|
4252
4335
|
}
|
|
4253
|
-
function buildReceive(deps, hooks, historyStore, heldStates,
|
|
4336
|
+
function buildReceive(deps, hooks, historyStore, heldStates, refreshView) {
|
|
4254
4337
|
return new Receive({
|
|
4255
4338
|
delivery: deps.deliveryPort,
|
|
4256
4339
|
engine: () => hooks.engine(),
|
|
@@ -4264,10 +4347,7 @@ function buildReceive(deps, hooks, historyStore, heldStates, view) {
|
|
|
4264
4347
|
registry: deps.registry,
|
|
4265
4348
|
recordReceived: (record) => recordReceived(historyStore, record),
|
|
4266
4349
|
emit: (event, transfer) => deps.emit(event, transfer),
|
|
4267
|
-
|
|
4268
|
-
// firing per throttle tick regardless of the last one builds a queue that
|
|
4269
|
-
// drains in a burst at the END — a slower version of the bug being fixed.
|
|
4270
|
-
refreshView: makeSingleFlightRefresh(() => view.delta()),
|
|
4350
|
+
refreshView,
|
|
4271
4351
|
attention: (transferId, code, detail) => {
|
|
4272
4352
|
deps.emit(
|
|
4273
4353
|
"transfer:attention",
|
|
@@ -4319,6 +4399,7 @@ var PaymentsFacade = class {
|
|
|
4319
4399
|
isActiveOp: (id) => this.activeMoneyOps.has(id)
|
|
4320
4400
|
});
|
|
4321
4401
|
this.view = parts.view;
|
|
4402
|
+
this.wakeRefresh = parts.refreshView;
|
|
4322
4403
|
this.ledger = parts.ledger;
|
|
4323
4404
|
this.queue = parts.queue;
|
|
4324
4405
|
this.machine = parts.machine;
|
|
@@ -4348,6 +4429,7 @@ var PaymentsFacade = class {
|
|
|
4348
4429
|
now: () => this.nowMs()
|
|
4349
4430
|
});
|
|
4350
4431
|
}
|
|
4432
|
+
wakeRefresh;
|
|
4351
4433
|
prewarmed = new PrewarmCache();
|
|
4352
4434
|
view;
|
|
4353
4435
|
ledger;
|
|
@@ -4386,9 +4468,7 @@ var PaymentsFacade = class {
|
|
|
4386
4468
|
this.deps.session.subscribeStream("mailbox", () => {
|
|
4387
4469
|
this.trackTail(this.receiveLoop.drainOnce());
|
|
4388
4470
|
}),
|
|
4389
|
-
this.deps.session.subscribeStream("inventory",
|
|
4390
|
-
this.trackTail(this.view.delta());
|
|
4391
|
-
}),
|
|
4471
|
+
this.deps.session.subscribeStream("inventory", this.wakeRefresh),
|
|
4392
4472
|
this.deps.session.subscribeStream("payment_requests", () => {
|
|
4393
4473
|
this.trackTail(this.requests.drainIncoming());
|
|
4394
4474
|
})
|
|
@@ -4652,7 +4732,7 @@ var PaymentsFacade = class {
|
|
|
4652
4732
|
...spend.plan.direct,
|
|
4653
4733
|
...spend.plan.split !== void 0 ? [spend.plan.split.tokenId] : []
|
|
4654
4734
|
];
|
|
4655
|
-
|
|
4735
|
+
this.view.markInFlightMany(sourceIds);
|
|
4656
4736
|
if (spend.plan.split !== void 0) {
|
|
4657
4737
|
this.queue.declareExpectedChange(transferId, coinId, spend.plan.split.remainderAmount);
|
|
4658
4738
|
}
|