@unicitylabs/sphere-sdk 0.14.5 → 0.14.6
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 +94 -61
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.js +94 -61
- 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.map +1 -1
- package/dist/impl/wallet-api-v2/index.js.map +1 -1
- package/dist/index.cjs +94 -61
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +94 -61
- package/dist/index.js.map +1 -1
- package/dist/modules/payments-v2/index.cjs +20 -14
- package/dist/modules/payments-v2/index.cjs.map +1 -1
- package/dist/modules/payments-v2/index.js +20 -14
- package/dist/modules/payments-v2/index.js.map +1 -1
- package/dist/token-engine/index.cjs +86 -59
- package/dist/token-engine/index.cjs.map +1 -1
- package/dist/token-engine/index.js +86 -59
- package/dist/token-engine/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9413,7 +9413,18 @@ function pause(ms, signal) {
|
|
|
9413
9413
|
);
|
|
9414
9414
|
});
|
|
9415
9415
|
}
|
|
9416
|
-
async function
|
|
9416
|
+
async function retryTransient(attempt, signal, intervalMs) {
|
|
9417
|
+
for (; ; ) {
|
|
9418
|
+
try {
|
|
9419
|
+
return await attempt();
|
|
9420
|
+
} catch (err) {
|
|
9421
|
+
if (signal.aborted) throw err;
|
|
9422
|
+
if (!isTransientGatewayError(err)) throw err;
|
|
9423
|
+
await pause(intervalMs, signal);
|
|
9424
|
+
}
|
|
9425
|
+
}
|
|
9426
|
+
}
|
|
9427
|
+
function certificationDeadline(timeoutMs, external, label) {
|
|
9417
9428
|
const controller = new AbortController();
|
|
9418
9429
|
const relayAbort = () => {
|
|
9419
9430
|
controller.abort(external?.reason);
|
|
@@ -9423,34 +9434,29 @@ async function awaitProofBounded(deps, transaction, external) {
|
|
|
9423
9434
|
else external.addEventListener("abort", relayAbort, { once: true });
|
|
9424
9435
|
}
|
|
9425
9436
|
const timer = setTimeout(() => {
|
|
9426
|
-
controller.abort(
|
|
9427
|
-
|
|
9428
|
-
|
|
9429
|
-
|
|
9430
|
-
|
|
9431
|
-
|
|
9432
|
-
|
|
9433
|
-
try {
|
|
9434
|
-
for (; ; ) {
|
|
9435
|
-
try {
|
|
9436
|
-
return await waitInclusionProof(
|
|
9437
|
-
deps.client,
|
|
9438
|
-
deps.trustBase,
|
|
9439
|
-
deps.predicateVerifier,
|
|
9440
|
-
transaction,
|
|
9441
|
-
controller.signal,
|
|
9442
|
-
deps.intervalMs
|
|
9443
|
-
);
|
|
9444
|
-
} catch (err) {
|
|
9445
|
-
if (controller.signal.aborted) throw err;
|
|
9446
|
-
if (!isTransientGatewayError(err)) throw err;
|
|
9447
|
-
await pause(deps.intervalMs, controller.signal);
|
|
9448
|
-
}
|
|
9437
|
+
controller.abort(new SphereError(`${label} within ${String(timeoutMs)} ms`, "AGGREGATOR_ERROR"));
|
|
9438
|
+
}, timeoutMs);
|
|
9439
|
+
return {
|
|
9440
|
+
signal: controller.signal,
|
|
9441
|
+
dispose: () => {
|
|
9442
|
+
clearTimeout(timer);
|
|
9443
|
+
external?.removeEventListener("abort", relayAbort);
|
|
9449
9444
|
}
|
|
9450
|
-
}
|
|
9451
|
-
|
|
9452
|
-
|
|
9453
|
-
|
|
9445
|
+
};
|
|
9446
|
+
}
|
|
9447
|
+
async function awaitProofBounded(deps, transaction, signal) {
|
|
9448
|
+
return retryTransient(
|
|
9449
|
+
() => waitInclusionProof(
|
|
9450
|
+
deps.client,
|
|
9451
|
+
deps.trustBase,
|
|
9452
|
+
deps.predicateVerifier,
|
|
9453
|
+
transaction,
|
|
9454
|
+
signal,
|
|
9455
|
+
deps.intervalMs
|
|
9456
|
+
),
|
|
9457
|
+
signal,
|
|
9458
|
+
deps.intervalMs
|
|
9459
|
+
);
|
|
9454
9460
|
}
|
|
9455
9461
|
|
|
9456
9462
|
// token-engine/errors.ts
|
|
@@ -9492,6 +9498,21 @@ var CheckpointTrustbaseMismatchError = class extends SphereError {
|
|
|
9492
9498
|
}
|
|
9493
9499
|
};
|
|
9494
9500
|
|
|
9501
|
+
// token-engine/certification-outcome.ts
|
|
9502
|
+
function certificationFailure(err, failLabel, submitError, submitRejectedCleanly) {
|
|
9503
|
+
if (err instanceof Error && err.message === `Invalid inclusion proof status: ${InclusionProofVerificationStatus.TRANSACTION_HASH_MISMATCH}`) {
|
|
9504
|
+
return new TransferConflictError(
|
|
9505
|
+
`${failLabel}: the source state was already consumed by a different transaction (lost race \u2014 abort this intent and re-plan under a new transferId)`,
|
|
9506
|
+
err
|
|
9507
|
+
);
|
|
9508
|
+
}
|
|
9509
|
+
if (submitRejectedCleanly) return submitError;
|
|
9510
|
+
return new ProofUnconfirmedError(
|
|
9511
|
+
`${failLabel}: certification unconfirmed \u2014 the source spend may be on-chain; keep the intent open and resume under the same transferId`,
|
|
9512
|
+
submitError ?? err
|
|
9513
|
+
);
|
|
9514
|
+
}
|
|
9515
|
+
|
|
9495
9516
|
// token-engine/token-blob.ts
|
|
9496
9517
|
var TOKEN_BLOB_TAG = 39051n;
|
|
9497
9518
|
var TOKEN_BLOB_VERSION = 1;
|
|
@@ -10014,10 +10035,28 @@ var SphereTokenEngine = class {
|
|
|
10014
10035
|
* failure, not a resume case).
|
|
10015
10036
|
*/
|
|
10016
10037
|
async submitAndAwaitProof(certificationData, transaction, failLabel, failCode, options) {
|
|
10038
|
+
const deadline = certificationDeadline(
|
|
10039
|
+
this.proofTimeoutMs,
|
|
10040
|
+
options?.signal,
|
|
10041
|
+
`${failLabel}: not certified`
|
|
10042
|
+
);
|
|
10043
|
+
try {
|
|
10044
|
+
return await this.submitThenProve(certificationData, transaction, failLabel, failCode, deadline.signal);
|
|
10045
|
+
} finally {
|
|
10046
|
+
deadline.dispose();
|
|
10047
|
+
}
|
|
10048
|
+
}
|
|
10049
|
+
/** One certification attempt under one deadline: the metered submit retries
|
|
10050
|
+
* transient answers instead of falling through to a proof that cannot exist. */
|
|
10051
|
+
async submitThenProve(certificationData, transaction, failLabel, failCode, signal) {
|
|
10017
10052
|
let submitError = null;
|
|
10018
10053
|
let submitRejectedCleanly = false;
|
|
10019
10054
|
try {
|
|
10020
|
-
const response = await
|
|
10055
|
+
const response = await retryTransient(
|
|
10056
|
+
() => this.deps.client.submitCertificationRequest(certificationData),
|
|
10057
|
+
signal,
|
|
10058
|
+
this.deps.proofPollIntervalMs ?? DEFAULT_PROOF_POLL_INTERVAL_MS
|
|
10059
|
+
);
|
|
10021
10060
|
if (response.status !== CertificationStatus.SUCCESS) {
|
|
10022
10061
|
submitError = new SphereError(`${failLabel}: ${response.status}`, failCode);
|
|
10023
10062
|
submitRejectedCleanly = CLEAN_REJECT_STATUSES.has(response.status);
|
|
@@ -10031,33 +10070,21 @@ var SphereTokenEngine = class {
|
|
|
10031
10070
|
client: this.deps.client,
|
|
10032
10071
|
trustBase: this.deps.trustBase,
|
|
10033
10072
|
predicateVerifier: this.deps.predicateVerifier,
|
|
10034
|
-
timeoutMs: this.proofTimeoutMs,
|
|
10035
10073
|
intervalMs: this.deps.proofPollIntervalMs ?? DEFAULT_PROOF_POLL_INTERVAL_MS
|
|
10036
10074
|
// #683
|
|
10037
10075
|
},
|
|
10038
10076
|
transaction,
|
|
10039
|
-
|
|
10077
|
+
signal
|
|
10040
10078
|
);
|
|
10041
10079
|
} catch (err) {
|
|
10042
|
-
|
|
10043
|
-
throw new TransferConflictError(
|
|
10044
|
-
`${failLabel}: the source state was already consumed by a different transaction (lost race \u2014 abort this intent and re-plan under a new transferId)`,
|
|
10045
|
-
err
|
|
10046
|
-
);
|
|
10047
|
-
}
|
|
10048
|
-
if (submitRejectedCleanly) throw submitError;
|
|
10049
|
-
throw new ProofUnconfirmedError(
|
|
10050
|
-
`${failLabel}: certification unconfirmed \u2014 the source spend may be on-chain; keep the intent open and resume under the same transferId`,
|
|
10051
|
-
submitError ?? err
|
|
10052
|
-
);
|
|
10080
|
+
throw certificationFailure(err, failLabel, submitError, submitRejectedCleanly);
|
|
10053
10081
|
}
|
|
10054
10082
|
}
|
|
10055
10083
|
/**
|
|
10056
|
-
* One inclusion-proof wait, with the deadline OWNED here (#739)
|
|
10057
|
-
*
|
|
10058
|
-
*
|
|
10059
|
-
*
|
|
10060
|
-
* (keep-open), which is the correct posture: the spend may be on-chain.
|
|
10084
|
+
* One inclusion-proof wait, with the deadline OWNED here (#739) so it is bounded
|
|
10085
|
+
* and configurable rather than the SDK's fixed default. A hit throws, and the
|
|
10086
|
+
* caller maps it to ProofUnconfirmedError (keep-open) — the correct posture,
|
|
10087
|
+
* since the spend may be on-chain.
|
|
10061
10088
|
*/
|
|
10062
10089
|
/** Fail fast if this engine's key does not own the token's current state. */
|
|
10063
10090
|
assertOwned(token) {
|
|
@@ -11392,7 +11419,7 @@ function createMachineStores(kv) {
|
|
|
11392
11419
|
}
|
|
11393
11420
|
|
|
11394
11421
|
// modules/payments-v2/machine/TransferMachine.ts
|
|
11395
|
-
var CERTIFY_WIDTH =
|
|
11422
|
+
var CERTIFY_WIDTH = 20;
|
|
11396
11423
|
var KEEP_OPEN_CODES = /* @__PURE__ */ new Set([
|
|
11397
11424
|
"CERTIFICATION_UNCONFIRMED",
|
|
11398
11425
|
"CHECKPOINT_PERSIST_FAILED",
|
|
@@ -11488,12 +11515,15 @@ var TransferMachine = class {
|
|
|
11488
11515
|
payload: r.payload,
|
|
11489
11516
|
...r.payload.memo !== void 0 ? { memo: r.payload.memo } : {}
|
|
11490
11517
|
};
|
|
11491
|
-
const
|
|
11518
|
+
const outcomes = await this.resumeOps(ctx, engine, r);
|
|
11519
|
+
const { committed, cls, firstError } = summarize(outcomes);
|
|
11520
|
+
const conflicts = this.toConflicts(engine, r, outcomes);
|
|
11492
11521
|
if (committed.length === 0 && conflicts.length > 0) throw conflicts[0].error;
|
|
11493
11522
|
let deliveryPending = false;
|
|
11494
11523
|
if (committed.length > 0) {
|
|
11495
11524
|
deliveryPending = await this.deliverSet(r.transferId, r.payload.recipient, r.payload.memo, committed);
|
|
11496
11525
|
}
|
|
11526
|
+
if (cls !== null && cls !== "conflict") throw firstError;
|
|
11497
11527
|
await this.applyCommitted(engine, r.transferId, committed);
|
|
11498
11528
|
if (conflicts.length > 0) {
|
|
11499
11529
|
return { deliveryPending, partial: await this.settlePartial(engine, r, committed, conflicts) };
|
|
@@ -11578,25 +11608,28 @@ var TransferMachine = class {
|
|
|
11578
11608
|
);
|
|
11579
11609
|
return { recipientBlob: outputs[0].blob.token, changeBlob: outputs[1].blob.token };
|
|
11580
11610
|
}
|
|
11611
|
+
/** Raw outcomes; `summarize` alone decides what they mean — same as the send path. */
|
|
11581
11612
|
async resumeOps(ctx, engine, r) {
|
|
11582
|
-
const
|
|
11583
|
-
const conflicts = [];
|
|
11613
|
+
const outcomes = [];
|
|
11584
11614
|
for (const op of buildOps(r.payload)) {
|
|
11585
11615
|
const journaled = op.kind === "direct" ? r.journaled.get(op.opIndex) : void 0;
|
|
11586
11616
|
if (journaled !== void 0) {
|
|
11587
|
-
|
|
11617
|
+
outcomes.push({ op, certified: true, recipientBlob: hexToBytes4(journaled.blobHex) });
|
|
11588
11618
|
continue;
|
|
11589
11619
|
}
|
|
11590
|
-
|
|
11591
|
-
const
|
|
11592
|
-
if (
|
|
11593
|
-
committed.push(outcome);
|
|
11594
|
-
continue;
|
|
11595
|
-
}
|
|
11596
|
-
if (classifyError(outcome.error) !== "conflict") throw outcome.error;
|
|
11597
|
-
conflicts.push({ op, error: outcome.error, amount: conflictAmount(engine, r.payload, op, source) });
|
|
11620
|
+
outcomes.push(await this.certifyOne(ctx, engine, op, r.sources.get(op.sourceTokenId)));
|
|
11621
|
+
const last = outcomes[outcomes.length - 1];
|
|
11622
|
+
if (last.error !== void 0 && classifyError(last.error) !== "conflict") break;
|
|
11598
11623
|
}
|
|
11599
|
-
return
|
|
11624
|
+
return outcomes;
|
|
11625
|
+
}
|
|
11626
|
+
/** Conflicted ops with the amount each leaves undelivered (#690 shortfall math). */
|
|
11627
|
+
toConflicts(engine, r, outcomes) {
|
|
11628
|
+
return outcomes.filter((o) => !o.certified && classifyError(o.error) === "conflict").map((o) => ({
|
|
11629
|
+
op: o.op,
|
|
11630
|
+
error: o.error,
|
|
11631
|
+
amount: conflictAmount(engine, r.payload, o.op, r.sources.get(o.op.sourceTokenId))
|
|
11632
|
+
}));
|
|
11600
11633
|
}
|
|
11601
11634
|
async deliverSet(transferId, recipientPubkey, memo, committed) {
|
|
11602
11635
|
const journaled = committed.filter((o) => o.error === void 0 && o.recipientBlob !== void 0);
|