@unicitylabs/sphere-sdk 0.14.4 → 0.14.6-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 +101 -79
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.js +101 -79
- 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 +101 -79
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +101 -79
- 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 +94 -78
- package/dist/token-engine/index.cjs.map +1 -1
- package/dist/token-engine/index.js +94 -78
- package/dist/token-engine/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -332,41 +332,35 @@ function resolveProofTimeoutMs(configured) {
|
|
|
332
332
|
}
|
|
333
333
|
return configured;
|
|
334
334
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
if (prop === "addEventListener") {
|
|
339
|
-
return (type, listener, options) => {
|
|
340
|
-
if (type === "abort" && target.aborted) {
|
|
341
|
-
queueMicrotask(() => {
|
|
342
|
-
listener.call(target, new Event("abort"));
|
|
343
|
-
});
|
|
344
|
-
return;
|
|
345
|
-
}
|
|
346
|
-
target.addEventListener(type, listener, options);
|
|
347
|
-
};
|
|
348
|
-
}
|
|
349
|
-
const value = Reflect.get(target, prop, target);
|
|
350
|
-
return typeof value === "function" ? value.bind(target) : value;
|
|
351
|
-
}
|
|
352
|
-
});
|
|
335
|
+
var TRANSIENT_HTTP_STATUSES = /* @__PURE__ */ new Set([408, 425, 429, 500, 502, 503, 504]);
|
|
336
|
+
function isTransientGatewayError(err) {
|
|
337
|
+
return err instanceof import_JsonRpcNetworkError.JsonRpcNetworkError && TRANSIENT_HTTP_STATUSES.has(err.status);
|
|
353
338
|
}
|
|
354
|
-
function
|
|
355
|
-
return new Promise((
|
|
356
|
-
|
|
357
|
-
reject(signal.reason);
|
|
358
|
-
return;
|
|
359
|
-
}
|
|
339
|
+
function pause(ms, signal) {
|
|
340
|
+
return new Promise((resolve) => {
|
|
341
|
+
const timer = setTimeout(resolve, ms);
|
|
360
342
|
signal.addEventListener(
|
|
361
343
|
"abort",
|
|
362
344
|
() => {
|
|
363
|
-
|
|
345
|
+
clearTimeout(timer);
|
|
346
|
+
resolve();
|
|
364
347
|
},
|
|
365
348
|
{ once: true }
|
|
366
349
|
);
|
|
367
350
|
});
|
|
368
351
|
}
|
|
369
|
-
async function
|
|
352
|
+
async function retryTransient(attempt, signal, intervalMs) {
|
|
353
|
+
for (; ; ) {
|
|
354
|
+
try {
|
|
355
|
+
return await attempt();
|
|
356
|
+
} catch (err) {
|
|
357
|
+
if (signal.aborted) throw err;
|
|
358
|
+
if (!isTransientGatewayError(err)) throw err;
|
|
359
|
+
await pause(intervalMs, signal);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
function certificationDeadline(timeoutMs, external, label) {
|
|
370
364
|
const controller = new AbortController();
|
|
371
365
|
const relayAbort = () => {
|
|
372
366
|
controller.abort(external?.reason);
|
|
@@ -376,41 +370,29 @@ async function awaitProofBounded(deps, transaction, external) {
|
|
|
376
370
|
else external.addEventListener("abort", relayAbort, { once: true });
|
|
377
371
|
}
|
|
378
372
|
const timer = setTimeout(() => {
|
|
379
|
-
controller.abort(
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
373
|
+
controller.abort(new SphereError(`${label} within ${String(timeoutMs)} ms`, "AGGREGATOR_ERROR"));
|
|
374
|
+
}, timeoutMs);
|
|
375
|
+
return {
|
|
376
|
+
signal: controller.signal,
|
|
377
|
+
dispose: () => {
|
|
378
|
+
clearTimeout(timer);
|
|
379
|
+
external?.removeEventListener("abort", relayAbort);
|
|
380
|
+
}
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
async function awaitProofBounded(deps, transaction, signal) {
|
|
384
|
+
return retryTransient(
|
|
385
|
+
() => (0, import_InclusionProofUtils.waitInclusionProof)(
|
|
386
|
+
deps.client,
|
|
387
|
+
deps.trustBase,
|
|
388
|
+
deps.predicateVerifier,
|
|
389
|
+
transaction,
|
|
390
|
+
signal,
|
|
391
|
+
deps.intervalMs
|
|
392
|
+
),
|
|
393
|
+
signal,
|
|
392
394
|
deps.intervalMs
|
|
393
395
|
);
|
|
394
|
-
wait.catch(() => void 0);
|
|
395
|
-
try {
|
|
396
|
-
return await Promise.race([wait, rejectOnAbort(controller.signal)]);
|
|
397
|
-
} finally {
|
|
398
|
-
clearTimeout(timer);
|
|
399
|
-
external?.removeEventListener("abort", relayAbort);
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
// core/uuid.ts
|
|
404
|
-
function randomUUID() {
|
|
405
|
-
const c = globalThis.crypto;
|
|
406
|
-
if (typeof c !== "undefined" && typeof c.randomUUID === "function") {
|
|
407
|
-
return c.randomUUID();
|
|
408
|
-
}
|
|
409
|
-
const b = c.getRandomValues(new Uint8Array(16));
|
|
410
|
-
b[6] = b[6] & 15 | 64;
|
|
411
|
-
b[8] = b[8] & 63 | 128;
|
|
412
|
-
const h = Array.from(b, (x) => x.toString(16).padStart(2, "0"));
|
|
413
|
-
return `${h[0]}${h[1]}${h[2]}${h[3]}-${h[4]}${h[5]}-${h[6]}${h[7]}-${h[8]}${h[9]}-${h[10]}${h[11]}${h[12]}${h[13]}${h[14]}${h[15]}`;
|
|
414
396
|
}
|
|
415
397
|
|
|
416
398
|
// token-engine/errors.ts
|
|
@@ -452,6 +434,34 @@ var CheckpointTrustbaseMismatchError = class extends SphereError {
|
|
|
452
434
|
}
|
|
453
435
|
};
|
|
454
436
|
|
|
437
|
+
// token-engine/certification-outcome.ts
|
|
438
|
+
function certificationFailure(err, failLabel, submitError, submitRejectedCleanly) {
|
|
439
|
+
if (err instanceof Error && err.message === `Invalid inclusion proof status: ${import_InclusionProofVerificationRule.InclusionProofVerificationStatus.TRANSACTION_HASH_MISMATCH}`) {
|
|
440
|
+
return new TransferConflictError(
|
|
441
|
+
`${failLabel}: the source state was already consumed by a different transaction (lost race \u2014 abort this intent and re-plan under a new transferId)`,
|
|
442
|
+
err
|
|
443
|
+
);
|
|
444
|
+
}
|
|
445
|
+
if (submitRejectedCleanly) return submitError;
|
|
446
|
+
return new ProofUnconfirmedError(
|
|
447
|
+
`${failLabel}: certification unconfirmed \u2014 the source spend may be on-chain; keep the intent open and resume under the same transferId`,
|
|
448
|
+
submitError ?? err
|
|
449
|
+
);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// core/uuid.ts
|
|
453
|
+
function randomUUID() {
|
|
454
|
+
const c = globalThis.crypto;
|
|
455
|
+
if (typeof c !== "undefined" && typeof c.randomUUID === "function") {
|
|
456
|
+
return c.randomUUID();
|
|
457
|
+
}
|
|
458
|
+
const b = c.getRandomValues(new Uint8Array(16));
|
|
459
|
+
b[6] = b[6] & 15 | 64;
|
|
460
|
+
b[8] = b[8] & 63 | 128;
|
|
461
|
+
const h = Array.from(b, (x) => x.toString(16).padStart(2, "0"));
|
|
462
|
+
return `${h[0]}${h[1]}${h[2]}${h[3]}-${h[4]}${h[5]}-${h[6]}${h[7]}-${h[8]}${h[9]}-${h[10]}${h[11]}${h[12]}${h[13]}${h[14]}${h[15]}`;
|
|
463
|
+
}
|
|
464
|
+
|
|
455
465
|
// token-engine/token-blob.ts
|
|
456
466
|
var TOKEN_BLOB_TAG = 39051n;
|
|
457
467
|
var TOKEN_BLOB_VERSION = 1;
|
|
@@ -1394,10 +1404,28 @@ var SphereTokenEngine = class {
|
|
|
1394
1404
|
* failure, not a resume case).
|
|
1395
1405
|
*/
|
|
1396
1406
|
async submitAndAwaitProof(certificationData, transaction, failLabel, failCode, options) {
|
|
1407
|
+
const deadline = certificationDeadline(
|
|
1408
|
+
this.proofTimeoutMs,
|
|
1409
|
+
options?.signal,
|
|
1410
|
+
`${failLabel}: not certified`
|
|
1411
|
+
);
|
|
1412
|
+
try {
|
|
1413
|
+
return await this.submitThenProve(certificationData, transaction, failLabel, failCode, deadline.signal);
|
|
1414
|
+
} finally {
|
|
1415
|
+
deadline.dispose();
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
/** One certification attempt under one deadline: the metered submit retries
|
|
1419
|
+
* transient answers instead of falling through to a proof that cannot exist. */
|
|
1420
|
+
async submitThenProve(certificationData, transaction, failLabel, failCode, signal) {
|
|
1397
1421
|
let submitError = null;
|
|
1398
1422
|
let submitRejectedCleanly = false;
|
|
1399
1423
|
try {
|
|
1400
|
-
const response = await
|
|
1424
|
+
const response = await retryTransient(
|
|
1425
|
+
() => this.deps.client.submitCertificationRequest(certificationData),
|
|
1426
|
+
signal,
|
|
1427
|
+
this.deps.proofPollIntervalMs ?? DEFAULT_PROOF_POLL_INTERVAL_MS
|
|
1428
|
+
);
|
|
1401
1429
|
if (response.status !== import_CertificationResponse.CertificationStatus.SUCCESS) {
|
|
1402
1430
|
submitError = new SphereError(`${failLabel}: ${response.status}`, failCode);
|
|
1403
1431
|
submitRejectedCleanly = CLEAN_REJECT_STATUSES.has(response.status);
|
|
@@ -1411,33 +1439,21 @@ var SphereTokenEngine = class {
|
|
|
1411
1439
|
client: this.deps.client,
|
|
1412
1440
|
trustBase: this.deps.trustBase,
|
|
1413
1441
|
predicateVerifier: this.deps.predicateVerifier,
|
|
1414
|
-
timeoutMs: this.proofTimeoutMs,
|
|
1415
1442
|
intervalMs: this.deps.proofPollIntervalMs ?? DEFAULT_PROOF_POLL_INTERVAL_MS
|
|
1416
1443
|
// #683
|
|
1417
1444
|
},
|
|
1418
1445
|
transaction,
|
|
1419
|
-
|
|
1446
|
+
signal
|
|
1420
1447
|
);
|
|
1421
1448
|
} catch (err) {
|
|
1422
|
-
|
|
1423
|
-
throw new TransferConflictError(
|
|
1424
|
-
`${failLabel}: the source state was already consumed by a different transaction (lost race \u2014 abort this intent and re-plan under a new transferId)`,
|
|
1425
|
-
err
|
|
1426
|
-
);
|
|
1427
|
-
}
|
|
1428
|
-
if (submitRejectedCleanly) throw submitError;
|
|
1429
|
-
throw new ProofUnconfirmedError(
|
|
1430
|
-
`${failLabel}: certification unconfirmed \u2014 the source spend may be on-chain; keep the intent open and resume under the same transferId`,
|
|
1431
|
-
submitError ?? err
|
|
1432
|
-
);
|
|
1449
|
+
throw certificationFailure(err, failLabel, submitError, submitRejectedCleanly);
|
|
1433
1450
|
}
|
|
1434
1451
|
}
|
|
1435
1452
|
/**
|
|
1436
|
-
* One inclusion-proof wait, with the deadline OWNED here (#739)
|
|
1437
|
-
*
|
|
1438
|
-
*
|
|
1439
|
-
*
|
|
1440
|
-
* (keep-open), which is the correct posture: the spend may be on-chain.
|
|
1453
|
+
* One inclusion-proof wait, with the deadline OWNED here (#739) so it is bounded
|
|
1454
|
+
* and configurable rather than the SDK's fixed default. A hit throws, and the
|
|
1455
|
+
* caller maps it to ProofUnconfirmedError (keep-open) — the correct posture,
|
|
1456
|
+
* since the spend may be on-chain.
|
|
1441
1457
|
*/
|
|
1442
1458
|
/** Fail fast if this engine's key does not own the token's current state. */
|
|
1443
1459
|
assertOwned(token) {
|