@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.cjs
CHANGED
|
@@ -9541,7 +9541,18 @@ function pause(ms, signal) {
|
|
|
9541
9541
|
);
|
|
9542
9542
|
});
|
|
9543
9543
|
}
|
|
9544
|
-
async function
|
|
9544
|
+
async function retryTransient(attempt, signal, intervalMs) {
|
|
9545
|
+
for (; ; ) {
|
|
9546
|
+
try {
|
|
9547
|
+
return await attempt();
|
|
9548
|
+
} catch (err) {
|
|
9549
|
+
if (signal.aborted) throw err;
|
|
9550
|
+
if (!isTransientGatewayError(err)) throw err;
|
|
9551
|
+
await pause(intervalMs, signal);
|
|
9552
|
+
}
|
|
9553
|
+
}
|
|
9554
|
+
}
|
|
9555
|
+
function certificationDeadline(timeoutMs, external, label) {
|
|
9545
9556
|
const controller = new AbortController();
|
|
9546
9557
|
const relayAbort = () => {
|
|
9547
9558
|
controller.abort(external?.reason);
|
|
@@ -9551,34 +9562,29 @@ async function awaitProofBounded(deps, transaction, external) {
|
|
|
9551
9562
|
else external.addEventListener("abort", relayAbort, { once: true });
|
|
9552
9563
|
}
|
|
9553
9564
|
const timer = setTimeout(() => {
|
|
9554
|
-
controller.abort(
|
|
9555
|
-
|
|
9556
|
-
|
|
9557
|
-
|
|
9558
|
-
|
|
9559
|
-
|
|
9560
|
-
|
|
9561
|
-
try {
|
|
9562
|
-
for (; ; ) {
|
|
9563
|
-
try {
|
|
9564
|
-
return await (0, import_InclusionProofUtils.waitInclusionProof)(
|
|
9565
|
-
deps.client,
|
|
9566
|
-
deps.trustBase,
|
|
9567
|
-
deps.predicateVerifier,
|
|
9568
|
-
transaction,
|
|
9569
|
-
controller.signal,
|
|
9570
|
-
deps.intervalMs
|
|
9571
|
-
);
|
|
9572
|
-
} catch (err) {
|
|
9573
|
-
if (controller.signal.aborted) throw err;
|
|
9574
|
-
if (!isTransientGatewayError(err)) throw err;
|
|
9575
|
-
await pause(deps.intervalMs, controller.signal);
|
|
9576
|
-
}
|
|
9565
|
+
controller.abort(new SphereError(`${label} within ${String(timeoutMs)} ms`, "AGGREGATOR_ERROR"));
|
|
9566
|
+
}, timeoutMs);
|
|
9567
|
+
return {
|
|
9568
|
+
signal: controller.signal,
|
|
9569
|
+
dispose: () => {
|
|
9570
|
+
clearTimeout(timer);
|
|
9571
|
+
external?.removeEventListener("abort", relayAbort);
|
|
9577
9572
|
}
|
|
9578
|
-
}
|
|
9579
|
-
|
|
9580
|
-
|
|
9581
|
-
|
|
9573
|
+
};
|
|
9574
|
+
}
|
|
9575
|
+
async function awaitProofBounded(deps, transaction, signal) {
|
|
9576
|
+
return retryTransient(
|
|
9577
|
+
() => (0, import_InclusionProofUtils.waitInclusionProof)(
|
|
9578
|
+
deps.client,
|
|
9579
|
+
deps.trustBase,
|
|
9580
|
+
deps.predicateVerifier,
|
|
9581
|
+
transaction,
|
|
9582
|
+
signal,
|
|
9583
|
+
deps.intervalMs
|
|
9584
|
+
),
|
|
9585
|
+
signal,
|
|
9586
|
+
deps.intervalMs
|
|
9587
|
+
);
|
|
9582
9588
|
}
|
|
9583
9589
|
|
|
9584
9590
|
// token-engine/errors.ts
|
|
@@ -9620,6 +9626,21 @@ var CheckpointTrustbaseMismatchError = class extends SphereError {
|
|
|
9620
9626
|
}
|
|
9621
9627
|
};
|
|
9622
9628
|
|
|
9629
|
+
// token-engine/certification-outcome.ts
|
|
9630
|
+
function certificationFailure(err, failLabel, submitError, submitRejectedCleanly) {
|
|
9631
|
+
if (err instanceof Error && err.message === `Invalid inclusion proof status: ${import_InclusionProofVerificationRule.InclusionProofVerificationStatus.TRANSACTION_HASH_MISMATCH}`) {
|
|
9632
|
+
return new TransferConflictError(
|
|
9633
|
+
`${failLabel}: the source state was already consumed by a different transaction (lost race \u2014 abort this intent and re-plan under a new transferId)`,
|
|
9634
|
+
err
|
|
9635
|
+
);
|
|
9636
|
+
}
|
|
9637
|
+
if (submitRejectedCleanly) return submitError;
|
|
9638
|
+
return new ProofUnconfirmedError(
|
|
9639
|
+
`${failLabel}: certification unconfirmed \u2014 the source spend may be on-chain; keep the intent open and resume under the same transferId`,
|
|
9640
|
+
submitError ?? err
|
|
9641
|
+
);
|
|
9642
|
+
}
|
|
9643
|
+
|
|
9623
9644
|
// token-engine/token-blob.ts
|
|
9624
9645
|
var TOKEN_BLOB_TAG = 39051n;
|
|
9625
9646
|
var TOKEN_BLOB_VERSION = 1;
|
|
@@ -10142,10 +10163,28 @@ var SphereTokenEngine = class {
|
|
|
10142
10163
|
* failure, not a resume case).
|
|
10143
10164
|
*/
|
|
10144
10165
|
async submitAndAwaitProof(certificationData, transaction, failLabel, failCode, options) {
|
|
10166
|
+
const deadline = certificationDeadline(
|
|
10167
|
+
this.proofTimeoutMs,
|
|
10168
|
+
options?.signal,
|
|
10169
|
+
`${failLabel}: not certified`
|
|
10170
|
+
);
|
|
10171
|
+
try {
|
|
10172
|
+
return await this.submitThenProve(certificationData, transaction, failLabel, failCode, deadline.signal);
|
|
10173
|
+
} finally {
|
|
10174
|
+
deadline.dispose();
|
|
10175
|
+
}
|
|
10176
|
+
}
|
|
10177
|
+
/** One certification attempt under one deadline: the metered submit retries
|
|
10178
|
+
* transient answers instead of falling through to a proof that cannot exist. */
|
|
10179
|
+
async submitThenProve(certificationData, transaction, failLabel, failCode, signal) {
|
|
10145
10180
|
let submitError = null;
|
|
10146
10181
|
let submitRejectedCleanly = false;
|
|
10147
10182
|
try {
|
|
10148
|
-
const response = await
|
|
10183
|
+
const response = await retryTransient(
|
|
10184
|
+
() => this.deps.client.submitCertificationRequest(certificationData),
|
|
10185
|
+
signal,
|
|
10186
|
+
this.deps.proofPollIntervalMs ?? DEFAULT_PROOF_POLL_INTERVAL_MS
|
|
10187
|
+
);
|
|
10149
10188
|
if (response.status !== import_CertificationResponse.CertificationStatus.SUCCESS) {
|
|
10150
10189
|
submitError = new SphereError(`${failLabel}: ${response.status}`, failCode);
|
|
10151
10190
|
submitRejectedCleanly = CLEAN_REJECT_STATUSES.has(response.status);
|
|
@@ -10159,33 +10198,21 @@ var SphereTokenEngine = class {
|
|
|
10159
10198
|
client: this.deps.client,
|
|
10160
10199
|
trustBase: this.deps.trustBase,
|
|
10161
10200
|
predicateVerifier: this.deps.predicateVerifier,
|
|
10162
|
-
timeoutMs: this.proofTimeoutMs,
|
|
10163
10201
|
intervalMs: this.deps.proofPollIntervalMs ?? DEFAULT_PROOF_POLL_INTERVAL_MS
|
|
10164
10202
|
// #683
|
|
10165
10203
|
},
|
|
10166
10204
|
transaction,
|
|
10167
|
-
|
|
10205
|
+
signal
|
|
10168
10206
|
);
|
|
10169
10207
|
} catch (err) {
|
|
10170
|
-
|
|
10171
|
-
throw new TransferConflictError(
|
|
10172
|
-
`${failLabel}: the source state was already consumed by a different transaction (lost race \u2014 abort this intent and re-plan under a new transferId)`,
|
|
10173
|
-
err
|
|
10174
|
-
);
|
|
10175
|
-
}
|
|
10176
|
-
if (submitRejectedCleanly) throw submitError;
|
|
10177
|
-
throw new ProofUnconfirmedError(
|
|
10178
|
-
`${failLabel}: certification unconfirmed \u2014 the source spend may be on-chain; keep the intent open and resume under the same transferId`,
|
|
10179
|
-
submitError ?? err
|
|
10180
|
-
);
|
|
10208
|
+
throw certificationFailure(err, failLabel, submitError, submitRejectedCleanly);
|
|
10181
10209
|
}
|
|
10182
10210
|
}
|
|
10183
10211
|
/**
|
|
10184
|
-
* One inclusion-proof wait, with the deadline OWNED here (#739)
|
|
10185
|
-
*
|
|
10186
|
-
*
|
|
10187
|
-
*
|
|
10188
|
-
* (keep-open), which is the correct posture: the spend may be on-chain.
|
|
10212
|
+
* One inclusion-proof wait, with the deadline OWNED here (#739) so it is bounded
|
|
10213
|
+
* and configurable rather than the SDK's fixed default. A hit throws, and the
|
|
10214
|
+
* caller maps it to ProofUnconfirmedError (keep-open) — the correct posture,
|
|
10215
|
+
* since the spend may be on-chain.
|
|
10189
10216
|
*/
|
|
10190
10217
|
/** Fail fast if this engine's key does not own the token's current state. */
|
|
10191
10218
|
assertOwned(token) {
|
|
@@ -11520,7 +11547,7 @@ function createMachineStores(kv) {
|
|
|
11520
11547
|
}
|
|
11521
11548
|
|
|
11522
11549
|
// modules/payments-v2/machine/TransferMachine.ts
|
|
11523
|
-
var CERTIFY_WIDTH =
|
|
11550
|
+
var CERTIFY_WIDTH = 20;
|
|
11524
11551
|
var KEEP_OPEN_CODES = /* @__PURE__ */ new Set([
|
|
11525
11552
|
"CERTIFICATION_UNCONFIRMED",
|
|
11526
11553
|
"CHECKPOINT_PERSIST_FAILED",
|
|
@@ -11616,12 +11643,15 @@ var TransferMachine = class {
|
|
|
11616
11643
|
payload: r.payload,
|
|
11617
11644
|
...r.payload.memo !== void 0 ? { memo: r.payload.memo } : {}
|
|
11618
11645
|
};
|
|
11619
|
-
const
|
|
11646
|
+
const outcomes = await this.resumeOps(ctx, engine, r);
|
|
11647
|
+
const { committed, cls, firstError } = summarize(outcomes);
|
|
11648
|
+
const conflicts = this.toConflicts(engine, r, outcomes);
|
|
11620
11649
|
if (committed.length === 0 && conflicts.length > 0) throw conflicts[0].error;
|
|
11621
11650
|
let deliveryPending = false;
|
|
11622
11651
|
if (committed.length > 0) {
|
|
11623
11652
|
deliveryPending = await this.deliverSet(r.transferId, r.payload.recipient, r.payload.memo, committed);
|
|
11624
11653
|
}
|
|
11654
|
+
if (cls !== null && cls !== "conflict") throw firstError;
|
|
11625
11655
|
await this.applyCommitted(engine, r.transferId, committed);
|
|
11626
11656
|
if (conflicts.length > 0) {
|
|
11627
11657
|
return { deliveryPending, partial: await this.settlePartial(engine, r, committed, conflicts) };
|
|
@@ -11706,25 +11736,28 @@ var TransferMachine = class {
|
|
|
11706
11736
|
);
|
|
11707
11737
|
return { recipientBlob: outputs[0].blob.token, changeBlob: outputs[1].blob.token };
|
|
11708
11738
|
}
|
|
11739
|
+
/** Raw outcomes; `summarize` alone decides what they mean — same as the send path. */
|
|
11709
11740
|
async resumeOps(ctx, engine, r) {
|
|
11710
|
-
const
|
|
11711
|
-
const conflicts = [];
|
|
11741
|
+
const outcomes = [];
|
|
11712
11742
|
for (const op of buildOps(r.payload)) {
|
|
11713
11743
|
const journaled = op.kind === "direct" ? r.journaled.get(op.opIndex) : void 0;
|
|
11714
11744
|
if (journaled !== void 0) {
|
|
11715
|
-
|
|
11745
|
+
outcomes.push({ op, certified: true, recipientBlob: hexToBytes4(journaled.blobHex) });
|
|
11716
11746
|
continue;
|
|
11717
11747
|
}
|
|
11718
|
-
|
|
11719
|
-
const
|
|
11720
|
-
if (
|
|
11721
|
-
committed.push(outcome);
|
|
11722
|
-
continue;
|
|
11723
|
-
}
|
|
11724
|
-
if (classifyError(outcome.error) !== "conflict") throw outcome.error;
|
|
11725
|
-
conflicts.push({ op, error: outcome.error, amount: conflictAmount(engine, r.payload, op, source) });
|
|
11748
|
+
outcomes.push(await this.certifyOne(ctx, engine, op, r.sources.get(op.sourceTokenId)));
|
|
11749
|
+
const last = outcomes[outcomes.length - 1];
|
|
11750
|
+
if (last.error !== void 0 && classifyError(last.error) !== "conflict") break;
|
|
11726
11751
|
}
|
|
11727
|
-
return
|
|
11752
|
+
return outcomes;
|
|
11753
|
+
}
|
|
11754
|
+
/** Conflicted ops with the amount each leaves undelivered (#690 shortfall math). */
|
|
11755
|
+
toConflicts(engine, r, outcomes) {
|
|
11756
|
+
return outcomes.filter((o) => !o.certified && classifyError(o.error) === "conflict").map((o) => ({
|
|
11757
|
+
op: o.op,
|
|
11758
|
+
error: o.error,
|
|
11759
|
+
amount: conflictAmount(engine, r.payload, o.op, r.sources.get(o.op.sourceTokenId))
|
|
11760
|
+
}));
|
|
11728
11761
|
}
|
|
11729
11762
|
async deliverSet(transferId, recipientPubkey, memo, committed) {
|
|
11730
11763
|
const journaled = committed.filter((o) => o.error === void 0 && o.recipientBlob !== void 0);
|