@unicitylabs/sphere-sdk 0.14.11-dev.8 → 0.15.0-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/README.md +55 -17
- package/dist/connect/index.cjs +10 -17
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/index.js +10 -17
- package/dist/connect/index.js.map +1 -1
- package/dist/core/index.cjs +98 -99
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +5 -14
- package/dist/core/index.d.ts +5 -14
- package/dist/core/index.js +98 -99
- package/dist/core/index.js.map +1 -1
- package/dist/impl/browser/connect/index.cjs +3 -3
- package/dist/impl/browser/connect/index.cjs.map +1 -1
- package/dist/impl/browser/connect/index.js +3 -3
- package/dist/impl/browser/connect/index.js.map +1 -1
- package/dist/impl/browser/index.cjs.map +1 -1
- package/dist/impl/browser/index.js.map +1 -1
- package/dist/impl/nodejs/connect/index.cjs +2 -2
- package/dist/impl/nodejs/connect/index.cjs.map +1 -1
- package/dist/impl/nodejs/connect/index.js +2 -2
- package/dist/impl/nodejs/connect/index.js.map +1 -1
- package/dist/impl/nodejs/index.cjs.map +1 -1
- package/dist/impl/nodejs/index.js.map +1 -1
- package/dist/impl/wallet-api-v2/index.cjs +95 -1
- package/dist/impl/wallet-api-v2/index.cjs.map +1 -1
- package/dist/impl/wallet-api-v2/index.js +95 -1
- package/dist/impl/wallet-api-v2/index.js.map +1 -1
- package/dist/index.cjs +98 -99
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -11
- package/dist/index.d.ts +6 -11
- package/dist/index.js +98 -99
- package/dist/index.js.map +1 -1
- package/dist/modules/payments-v2/index.cjs +149 -193
- package/dist/modules/payments-v2/index.cjs.map +1 -1
- package/dist/modules/payments-v2/index.d.cts +8 -5
- package/dist/modules/payments-v2/index.d.ts +8 -5
- package/dist/modules/payments-v2/index.js +146 -192
- package/dist/modules/payments-v2/index.js.map +1 -1
- package/dist/token-engine/index.cjs +43 -57
- package/dist/token-engine/index.cjs.map +1 -1
- package/dist/token-engine/index.d.cts +0 -4
- package/dist/token-engine/index.d.ts +0 -4
- package/dist/token-engine/index.js +43 -57
- package/dist/token-engine/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -356,6 +356,11 @@ type AckOutcome = {
|
|
|
356
356
|
readonly deliveryId: string;
|
|
357
357
|
readonly status: 'conflict';
|
|
358
358
|
};
|
|
359
|
+
/** ackBatch failed in a way a per-entry retry would hit too — do not fall back. */
|
|
360
|
+
interface RetryableAckError extends Error {
|
|
361
|
+
readonly retryable: true;
|
|
362
|
+
}
|
|
363
|
+
declare function isRetryableAckError(err: unknown): err is RetryableAckError;
|
|
359
364
|
|
|
360
365
|
interface IntentPayload {
|
|
361
366
|
v: 2;
|
|
@@ -437,6 +442,8 @@ interface StorageProvider extends BaseProvider {
|
|
|
437
442
|
loadTrackedAddresses(): Promise<TrackedAddressEntry[]>;
|
|
438
443
|
}
|
|
439
444
|
|
|
445
|
+
/** Never `storage.clear()` — that takes the keys too. */
|
|
446
|
+
declare function sweepSupersededState(storage: StorageProvider): Promise<void>;
|
|
440
447
|
interface ScopedKV {
|
|
441
448
|
get<T>(key: string): Promise<T | null>;
|
|
442
449
|
set<T>(key: string, value: T): Promise<void>;
|
|
@@ -539,10 +546,6 @@ interface SphereValue {
|
|
|
539
546
|
* `token`, so it is NOT stored — only cached at runtime on SphereToken.value.
|
|
540
547
|
*/
|
|
541
548
|
interface TokenBlob {
|
|
542
|
-
/** Blob format version (sphere storage migrations; independent of SDK CBOR). */
|
|
543
|
-
readonly v: number;
|
|
544
|
-
/** NetworkId.id the token belongs to (mainnet=1 / testnet=2 / local=3). */
|
|
545
|
-
readonly network: number;
|
|
546
549
|
/**
|
|
547
550
|
* Genesis-stable token id — 64-char lowercase hex of the v2 `TokenId.bytes`
|
|
548
551
|
* (same across every state of the token). Stored on the blob so dedup / listing
|
|
@@ -1174,4 +1177,4 @@ declare class PaymentsFacade implements PaymentsV2 {
|
|
|
1174
1177
|
declare const HEARTBEAT_SEED_MS = 5000;
|
|
1175
1178
|
declare const HEARTBEAT_CAP_MS = 120000;
|
|
1176
1179
|
|
|
1177
|
-
export { ATTENTION_MINT_UNRESOLVED, ATTENTION_RECIPIENT_NETWORK_UNVERIFIED, ATTENTION_RESEED_REJECTED, type ApplyDeltaResult, type CheckpointReseeder, type ConnectionStatus, type DeliverOptions, type DeliveryJournalEntry, type DeliveryPort, type DeliveryReceipt, type DeterministicMintCapable, type FacadeClient, type FacadeSession, HEARTBEAT_CAP_MS, HEARTBEAT_SEED_MS, type HistoryEntry, type HistoryPage, type IncomingDelivery, type IntentBackstopEntry, type IntentPayload, type InventoryAsset, type InventoryItem, type InventoryPage, MAX_RESELECT, type MintJournalEntry, type MintResult, type OpOutcome, type OutcomeClass, type PaymentRequestStatus, type PaymentRequestView, PaymentsFacade, type PaymentsFacadeDeps, type PaymentsRequestsApi, type PaymentsV2, type PaymentsV2Events, type PendingTransfer, type PlannedOp, type RecipientInfo, STORE_KEYS, type ScopedKV, type SendRequest, type SettlingLink, type ShortfallEntry, type StoragePort, type StreamCursor, type StreamName, createScopedKV, supportsDeterministicMint };
|
|
1180
|
+
export { ATTENTION_MINT_UNRESOLVED, ATTENTION_RECIPIENT_NETWORK_UNVERIFIED, ATTENTION_RESEED_REJECTED, type AckOutcome, type AckRequest, type ApplyDeltaResult, type CheckpointReseeder, type ConnectionStatus, type DeliverOptions, type DeliveryJournalEntry, type DeliveryPort, type DeliveryReceipt, type DeterministicMintCapable, type FacadeClient, type FacadeSession, HEARTBEAT_CAP_MS, HEARTBEAT_SEED_MS, type HistoryEntry, type HistoryPage, type IncomingDelivery, type IntentBackstopEntry, type IntentPayload, type InventoryAsset, type InventoryItem, type InventoryPage, MAX_RESELECT, type MintJournalEntry, type MintResult, type OpOutcome, type OutcomeClass, type PaymentRequestStatus, type PaymentRequestView, PaymentsFacade, type PaymentsFacadeDeps, type PaymentsRequestsApi, type PaymentsV2, type PaymentsV2Events, type PendingTransfer, type PlannedOp, type RecipientInfo, type RetryableAckError, STORE_KEYS, type ScopedKV, type SendRequest, type SettlingLink, type ShortfallEntry, type StoragePort, type StreamCursor, type StreamName, createScopedKV, isRetryableAckError, supportsDeterministicMint, sweepSupersededState };
|
|
@@ -356,6 +356,11 @@ type AckOutcome = {
|
|
|
356
356
|
readonly deliveryId: string;
|
|
357
357
|
readonly status: 'conflict';
|
|
358
358
|
};
|
|
359
|
+
/** ackBatch failed in a way a per-entry retry would hit too — do not fall back. */
|
|
360
|
+
interface RetryableAckError extends Error {
|
|
361
|
+
readonly retryable: true;
|
|
362
|
+
}
|
|
363
|
+
declare function isRetryableAckError(err: unknown): err is RetryableAckError;
|
|
359
364
|
|
|
360
365
|
interface IntentPayload {
|
|
361
366
|
v: 2;
|
|
@@ -437,6 +442,8 @@ interface StorageProvider extends BaseProvider {
|
|
|
437
442
|
loadTrackedAddresses(): Promise<TrackedAddressEntry[]>;
|
|
438
443
|
}
|
|
439
444
|
|
|
445
|
+
/** Never `storage.clear()` — that takes the keys too. */
|
|
446
|
+
declare function sweepSupersededState(storage: StorageProvider): Promise<void>;
|
|
440
447
|
interface ScopedKV {
|
|
441
448
|
get<T>(key: string): Promise<T | null>;
|
|
442
449
|
set<T>(key: string, value: T): Promise<void>;
|
|
@@ -539,10 +546,6 @@ interface SphereValue {
|
|
|
539
546
|
* `token`, so it is NOT stored — only cached at runtime on SphereToken.value.
|
|
540
547
|
*/
|
|
541
548
|
interface TokenBlob {
|
|
542
|
-
/** Blob format version (sphere storage migrations; independent of SDK CBOR). */
|
|
543
|
-
readonly v: number;
|
|
544
|
-
/** NetworkId.id the token belongs to (mainnet=1 / testnet=2 / local=3). */
|
|
545
|
-
readonly network: number;
|
|
546
549
|
/**
|
|
547
550
|
* Genesis-stable token id — 64-char lowercase hex of the v2 `TokenId.bytes`
|
|
548
551
|
* (same across every state of the token). Stored on the blob so dedup / listing
|
|
@@ -1174,4 +1177,4 @@ declare class PaymentsFacade implements PaymentsV2 {
|
|
|
1174
1177
|
declare const HEARTBEAT_SEED_MS = 5000;
|
|
1175
1178
|
declare const HEARTBEAT_CAP_MS = 120000;
|
|
1176
1179
|
|
|
1177
|
-
export { ATTENTION_MINT_UNRESOLVED, ATTENTION_RECIPIENT_NETWORK_UNVERIFIED, ATTENTION_RESEED_REJECTED, type ApplyDeltaResult, type CheckpointReseeder, type ConnectionStatus, type DeliverOptions, type DeliveryJournalEntry, type DeliveryPort, type DeliveryReceipt, type DeterministicMintCapable, type FacadeClient, type FacadeSession, HEARTBEAT_CAP_MS, HEARTBEAT_SEED_MS, type HistoryEntry, type HistoryPage, type IncomingDelivery, type IntentBackstopEntry, type IntentPayload, type InventoryAsset, type InventoryItem, type InventoryPage, MAX_RESELECT, type MintJournalEntry, type MintResult, type OpOutcome, type OutcomeClass, type PaymentRequestStatus, type PaymentRequestView, PaymentsFacade, type PaymentsFacadeDeps, type PaymentsRequestsApi, type PaymentsV2, type PaymentsV2Events, type PendingTransfer, type PlannedOp, type RecipientInfo, STORE_KEYS, type ScopedKV, type SendRequest, type SettlingLink, type ShortfallEntry, type StoragePort, type StreamCursor, type StreamName, createScopedKV, supportsDeterministicMint };
|
|
1180
|
+
export { ATTENTION_MINT_UNRESOLVED, ATTENTION_RECIPIENT_NETWORK_UNVERIFIED, ATTENTION_RESEED_REJECTED, type AckOutcome, type AckRequest, type ApplyDeltaResult, type CheckpointReseeder, type ConnectionStatus, type DeliverOptions, type DeliveryJournalEntry, type DeliveryPort, type DeliveryReceipt, type DeterministicMintCapable, type FacadeClient, type FacadeSession, HEARTBEAT_CAP_MS, HEARTBEAT_SEED_MS, type HistoryEntry, type HistoryPage, type IncomingDelivery, type IntentBackstopEntry, type IntentPayload, type InventoryAsset, type InventoryItem, type InventoryPage, MAX_RESELECT, type MintJournalEntry, type MintResult, type OpOutcome, type OutcomeClass, type PaymentRequestStatus, type PaymentRequestView, PaymentsFacade, type PaymentsFacadeDeps, type PaymentsRequestsApi, type PaymentsV2, type PaymentsV2Events, type PendingTransfer, type PlannedOp, type RecipientInfo, type RetryableAckError, STORE_KEYS, type ScopedKV, type SendRequest, type SettlingLink, type ShortfallEntry, type StoragePort, type StreamCursor, type StreamName, createScopedKV, isRetryableAckError, supportsDeterministicMint, sweepSupersededState };
|
|
@@ -1,6 +1,114 @@
|
|
|
1
|
+
// modules/payments-v2/ports.ts
|
|
2
|
+
function isRetryableAckError(err) {
|
|
3
|
+
return err !== null && typeof err === "object" && err.retryable === true;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
// core/logger.ts
|
|
7
|
+
var LOGGER_KEY = "__sphere_sdk_logger__";
|
|
8
|
+
function getState() {
|
|
9
|
+
const g = globalThis;
|
|
10
|
+
if (!g[LOGGER_KEY]) {
|
|
11
|
+
g[LOGGER_KEY] = { debug: false, tags: {}, handler: null };
|
|
12
|
+
}
|
|
13
|
+
return g[LOGGER_KEY];
|
|
14
|
+
}
|
|
15
|
+
function isEnabled(tag) {
|
|
16
|
+
const state = getState();
|
|
17
|
+
if (tag in state.tags) return state.tags[tag];
|
|
18
|
+
return state.debug;
|
|
19
|
+
}
|
|
20
|
+
var logger = {
|
|
21
|
+
/**
|
|
22
|
+
* Configure the logger. Can be called multiple times (last write wins).
|
|
23
|
+
* Typically called by createBrowserProviders(), createNodeProviders(), or Sphere.init().
|
|
24
|
+
*/
|
|
25
|
+
configure(config) {
|
|
26
|
+
const state = getState();
|
|
27
|
+
if (config.debug !== void 0) state.debug = config.debug;
|
|
28
|
+
if (config.handler !== void 0) state.handler = config.handler;
|
|
29
|
+
},
|
|
30
|
+
/**
|
|
31
|
+
* Enable/disable debug logging for a specific tag.
|
|
32
|
+
* Per-tag setting overrides the global debug flag.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* logger.setTagDebug('Nostr', true); // enable only Nostr logs
|
|
37
|
+
* logger.setTagDebug('Nostr', false); // disable Nostr logs even if global debug=true
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
setTagDebug(tag, enabled) {
|
|
41
|
+
getState().tags[tag] = enabled;
|
|
42
|
+
},
|
|
43
|
+
/**
|
|
44
|
+
* Clear per-tag override, falling back to global debug flag.
|
|
45
|
+
*/
|
|
46
|
+
clearTagDebug(tag) {
|
|
47
|
+
delete getState().tags[tag];
|
|
48
|
+
},
|
|
49
|
+
/** Returns true if debug mode is enabled for the given tag (or globally). */
|
|
50
|
+
isDebugEnabled(tag) {
|
|
51
|
+
if (tag) return isEnabled(tag);
|
|
52
|
+
return getState().debug;
|
|
53
|
+
},
|
|
54
|
+
/**
|
|
55
|
+
* Debug-level log. Only shown when debug is enabled (globally or for this tag).
|
|
56
|
+
* Use for detailed operational information.
|
|
57
|
+
*/
|
|
58
|
+
debug(tag, message, ...args) {
|
|
59
|
+
if (!isEnabled(tag)) return;
|
|
60
|
+
const state = getState();
|
|
61
|
+
if (state.handler) {
|
|
62
|
+
state.handler("debug", tag, message, ...args);
|
|
63
|
+
} else {
|
|
64
|
+
console.log(`[${tag}]`, message, ...args);
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
/**
|
|
68
|
+
* Warning-level log. ALWAYS shown regardless of debug flag.
|
|
69
|
+
* Use for important but non-critical issues (timeouts, retries, degraded state).
|
|
70
|
+
*/
|
|
71
|
+
warn(tag, message, ...args) {
|
|
72
|
+
const state = getState();
|
|
73
|
+
if (state.handler) {
|
|
74
|
+
state.handler("warn", tag, message, ...args);
|
|
75
|
+
} else {
|
|
76
|
+
console.warn(`[${tag}]`, message, ...args);
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
/**
|
|
80
|
+
* Error-level log. ALWAYS shown regardless of debug flag.
|
|
81
|
+
* Use for critical failures that should never be silenced.
|
|
82
|
+
*/
|
|
83
|
+
error(tag, message, ...args) {
|
|
84
|
+
const state = getState();
|
|
85
|
+
if (state.handler) {
|
|
86
|
+
state.handler("error", tag, message, ...args);
|
|
87
|
+
} else {
|
|
88
|
+
console.error(`[${tag}]`, message, ...args);
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
/** Reset all logger state (debug flag, tags, handler). Primarily for tests. */
|
|
92
|
+
reset() {
|
|
93
|
+
const g = globalThis;
|
|
94
|
+
delete g[LOGGER_KEY];
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
|
|
1
98
|
// modules/payments-v2/stores.ts
|
|
99
|
+
var KV_PREFIX = "pv2g2:";
|
|
100
|
+
var SUPERSEDED_KV_PREFIXES = ["pv2:"];
|
|
101
|
+
async function sweepSupersededState(storage) {
|
|
102
|
+
for (const prefix of SUPERSEDED_KV_PREFIXES) {
|
|
103
|
+
try {
|
|
104
|
+
await storage.clear(prefix);
|
|
105
|
+
} catch (err) {
|
|
106
|
+
logger.warn("PaymentsV2", `could not clear superseded state under "${prefix}": ${String(err)}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
2
110
|
function createScopedKV(storage, network, chainPubkey) {
|
|
3
|
-
const prefix =
|
|
111
|
+
const prefix = `${KV_PREFIX}${network}:${chainPubkey}:`;
|
|
4
112
|
return {
|
|
5
113
|
async get(key) {
|
|
6
114
|
const raw = await storage.get(prefix + key);
|
|
@@ -449,69 +557,6 @@ function randomUUID() {
|
|
|
449
557
|
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]}`;
|
|
450
558
|
}
|
|
451
559
|
|
|
452
|
-
// token-engine/sdk.ts
|
|
453
|
-
import { StateTransitionClient } from "@unicitylabs/state-transition-sdk/lib/StateTransitionClient.js";
|
|
454
|
-
import { AggregatorClient } from "@unicitylabs/state-transition-sdk/lib/api/AggregatorClient.js";
|
|
455
|
-
import { NetworkId } from "@unicitylabs/state-transition-sdk/lib/api/NetworkId.js";
|
|
456
|
-
import { CertificationData } from "@unicitylabs/state-transition-sdk/lib/api/CertificationData.js";
|
|
457
|
-
import { CertificationResponse, CertificationStatus } from "@unicitylabs/state-transition-sdk/lib/api/CertificationResponse.js";
|
|
458
|
-
import { StateId } from "@unicitylabs/state-transition-sdk/lib/api/StateId.js";
|
|
459
|
-
import { InclusionProof } from "@unicitylabs/state-transition-sdk/lib/api/InclusionProof.js";
|
|
460
|
-
import { InclusionProofResponse } from "@unicitylabs/state-transition-sdk/lib/api/InclusionProofResponse.js";
|
|
461
|
-
import { JsonRpcNetworkError } from "@unicitylabs/state-transition-sdk/lib/api/json-rpc/JsonRpcNetworkError.js";
|
|
462
|
-
import { RootTrustBase } from "@unicitylabs/state-transition-sdk/lib/api/bft/RootTrustBase.js";
|
|
463
|
-
import { waitInclusionProof } from "@unicitylabs/state-transition-sdk/lib/util/InclusionProofUtils.js";
|
|
464
|
-
import { InclusionProofVerificationStatus } from "@unicitylabs/state-transition-sdk/lib/transaction/verification/rule/InclusionProofVerificationRule.js";
|
|
465
|
-
import { Token } from "@unicitylabs/state-transition-sdk/lib/transaction/Token.js";
|
|
466
|
-
import { MintTransaction } from "@unicitylabs/state-transition-sdk/lib/transaction/MintTransaction.js";
|
|
467
|
-
import { TransferTransaction } from "@unicitylabs/state-transition-sdk/lib/transaction/TransferTransaction.js";
|
|
468
|
-
import { CertifiedMintTransaction } from "@unicitylabs/state-transition-sdk/lib/transaction/CertifiedMintTransaction.js";
|
|
469
|
-
import { CertifiedTransferTransaction } from "@unicitylabs/state-transition-sdk/lib/transaction/CertifiedTransferTransaction.js";
|
|
470
|
-
import { TokenId } from "@unicitylabs/state-transition-sdk/lib/transaction/TokenId.js";
|
|
471
|
-
import { TokenType } from "@unicitylabs/state-transition-sdk/lib/transaction/TokenType.js";
|
|
472
|
-
import { TokenSalt } from "@unicitylabs/state-transition-sdk/lib/transaction/TokenSalt.js";
|
|
473
|
-
import { StateMask } from "@unicitylabs/state-transition-sdk/lib/transaction/StateMask.js";
|
|
474
|
-
import { MintJustificationVerifierService } from "@unicitylabs/state-transition-sdk/lib/transaction/verification/MintJustificationVerifierService.js";
|
|
475
|
-
import { TokenIssuanceVerifierService } from "@unicitylabs/state-transition-sdk/lib/transaction/verification/TokenIssuanceVerifierService.js";
|
|
476
|
-
import { VerificationContext } from "@unicitylabs/state-transition-sdk/lib/transaction/verification/VerificationContext.js";
|
|
477
|
-
import { UnicityCertificateVerifier } from "@unicitylabs/state-transition-sdk/lib/api/bft/verification/UnicityCertificateVerifier.js";
|
|
478
|
-
import { UnicitySealQuorumSignaturesVerificationRule } from "@unicitylabs/state-transition-sdk/lib/api/bft/verification/rule/UnicitySealQuorumSignaturesVerificationRule.js";
|
|
479
|
-
import { VerifiedSealCache } from "@unicitylabs/state-transition-sdk/lib/api/bft/verification/VerifiedSealCache.js";
|
|
480
|
-
import { Secp256k1SignatureVerifier } from "@unicitylabs/state-transition-sdk/lib/crypto/secp256k1/Secp256k1SignatureVerifier.js";
|
|
481
|
-
import { WorkerTokenVerifier } from "@unicitylabs/state-transition-sdk/lib/transaction/verification/worker/WorkerTokenVerifier.js";
|
|
482
|
-
import { EncodedPredicate } from "@unicitylabs/state-transition-sdk/lib/predicate/EncodedPredicate.js";
|
|
483
|
-
import { SignaturePredicate } from "@unicitylabs/state-transition-sdk/lib/predicate/builtin/SignaturePredicate.js";
|
|
484
|
-
import { SignaturePredicateUnlockScript } from "@unicitylabs/state-transition-sdk/lib/predicate/builtin/SignaturePredicateUnlockScript.js";
|
|
485
|
-
import { BurnPredicate } from "@unicitylabs/state-transition-sdk/lib/predicate/builtin/BurnPredicate.js";
|
|
486
|
-
import { PredicateVerifierService } from "@unicitylabs/state-transition-sdk/lib/predicate/verification/PredicateVerifierService.js";
|
|
487
|
-
import { SigningService } from "@unicitylabs/state-transition-sdk/lib/crypto/secp256k1/SigningService.js";
|
|
488
|
-
import { Signature } from "@unicitylabs/state-transition-sdk/lib/crypto/secp256k1/Signature.js";
|
|
489
|
-
import { MintSigningService } from "@unicitylabs/state-transition-sdk/lib/crypto/MintSigningService.js";
|
|
490
|
-
import { HashAlgorithm } from "@unicitylabs/state-transition-sdk/lib/crypto/hash/HashAlgorithm.js";
|
|
491
|
-
import { DataHash } from "@unicitylabs/state-transition-sdk/lib/crypto/hash/DataHash.js";
|
|
492
|
-
import { DataHasher } from "@unicitylabs/state-transition-sdk/lib/crypto/hash/DataHasher.js";
|
|
493
|
-
import { DataHasherFactory } from "@unicitylabs/state-transition-sdk/lib/crypto/hash/DataHasherFactory.js";
|
|
494
|
-
import { CborSerializer } from "@unicitylabs/state-transition-sdk/lib/serialization/cbor/CborSerializer.js";
|
|
495
|
-
import { CborDeserializer } from "@unicitylabs/state-transition-sdk/lib/serialization/cbor/CborDeserializer.js";
|
|
496
|
-
import { CborError } from "@unicitylabs/state-transition-sdk/lib/serialization/cbor/CborError.js";
|
|
497
|
-
import { Asset } from "@unicitylabs/state-transition-sdk/lib/payment/asset/Asset.js";
|
|
498
|
-
import { AssetId } from "@unicitylabs/state-transition-sdk/lib/payment/asset/AssetId.js";
|
|
499
|
-
import { PaymentAssetCollection } from "@unicitylabs/state-transition-sdk/lib/payment/asset/PaymentAssetCollection.js";
|
|
500
|
-
import { TokenSplit } from "@unicitylabs/state-transition-sdk/lib/payment/TokenSplit.js";
|
|
501
|
-
import { SplitTokenRequest } from "@unicitylabs/state-transition-sdk/lib/payment/SplitTokenRequest.js";
|
|
502
|
-
import { SplitToken } from "@unicitylabs/state-transition-sdk/lib/payment/SplitToken.js";
|
|
503
|
-
import { SplitAllocationProof } from "@unicitylabs/state-transition-sdk/lib/payment/SplitAllocationProof.js";
|
|
504
|
-
import { SplitMintJustification } from "@unicitylabs/state-transition-sdk/lib/payment/SplitMintJustification.js";
|
|
505
|
-
import { SplitMintJustificationVerifier } from "@unicitylabs/state-transition-sdk/lib/payment/SplitMintJustificationVerifier.js";
|
|
506
|
-
import { VerificationStatus } from "@unicitylabs/state-transition-sdk/lib/verification/VerificationStatus.js";
|
|
507
|
-
import { VerificationResult } from "@unicitylabs/state-transition-sdk/lib/verification/VerificationResult.js";
|
|
508
|
-
import { HexConverter } from "@unicitylabs/state-transition-sdk/lib/util/HexConverter.js";
|
|
509
|
-
import { BigintConverter } from "@unicitylabs/state-transition-sdk/lib/util/BigintConverter.js";
|
|
510
|
-
import { BitString } from "@unicitylabs/state-transition-sdk/lib/util/BitString.js";
|
|
511
|
-
|
|
512
|
-
// token-engine/token-blob.ts
|
|
513
|
-
var TOKEN_BLOB_VERSION = 1;
|
|
514
|
-
|
|
515
560
|
// modules/payments-v2/async.ts
|
|
516
561
|
var SingleFlight = class {
|
|
517
562
|
flight = null;
|
|
@@ -1156,12 +1201,7 @@ var TransferMachine = class {
|
|
|
1156
1201
|
let total = 0n;
|
|
1157
1202
|
for (const outcome of committed) {
|
|
1158
1203
|
if (outcome.recipientBlob === void 0) continue;
|
|
1159
|
-
const token = await engine.decodeToken({
|
|
1160
|
-
v: TOKEN_BLOB_VERSION,
|
|
1161
|
-
network: 0,
|
|
1162
|
-
tokenId: "",
|
|
1163
|
-
token: outcome.recipientBlob
|
|
1164
|
-
});
|
|
1204
|
+
const token = await engine.decodeToken({ tokenId: "", token: outcome.recipientBlob });
|
|
1165
1205
|
total += engine.balanceOf(token, coinId);
|
|
1166
1206
|
}
|
|
1167
1207
|
return total.toString();
|
|
@@ -1277,8 +1317,9 @@ async function fetchSources(deps, jobs) {
|
|
|
1277
1317
|
const engine = deps.engine();
|
|
1278
1318
|
for (const [tokenId, bytes] of blobs) {
|
|
1279
1319
|
try {
|
|
1280
|
-
decoded.set(tokenId, await engine.decodeToken({
|
|
1281
|
-
} catch {
|
|
1320
|
+
decoded.set(tokenId, await engine.decodeToken({ tokenId, token: bytes }));
|
|
1321
|
+
} catch (err) {
|
|
1322
|
+
logger.warn("PaymentsV2", `resume: source ${tokenId} did not decode \u2014 ${String(err)}`);
|
|
1282
1323
|
}
|
|
1283
1324
|
}
|
|
1284
1325
|
return decoded;
|
|
@@ -3102,103 +3143,6 @@ var InventoryView = class {
|
|
|
3102
3143
|
}
|
|
3103
3144
|
};
|
|
3104
3145
|
|
|
3105
|
-
// core/logger.ts
|
|
3106
|
-
var LOGGER_KEY = "__sphere_sdk_logger__";
|
|
3107
|
-
function getState() {
|
|
3108
|
-
const g = globalThis;
|
|
3109
|
-
if (!g[LOGGER_KEY]) {
|
|
3110
|
-
g[LOGGER_KEY] = { debug: false, tags: {}, handler: null };
|
|
3111
|
-
}
|
|
3112
|
-
return g[LOGGER_KEY];
|
|
3113
|
-
}
|
|
3114
|
-
function isEnabled(tag) {
|
|
3115
|
-
const state = getState();
|
|
3116
|
-
if (tag in state.tags) return state.tags[tag];
|
|
3117
|
-
return state.debug;
|
|
3118
|
-
}
|
|
3119
|
-
var logger = {
|
|
3120
|
-
/**
|
|
3121
|
-
* Configure the logger. Can be called multiple times (last write wins).
|
|
3122
|
-
* Typically called by createBrowserProviders(), createNodeProviders(), or Sphere.init().
|
|
3123
|
-
*/
|
|
3124
|
-
configure(config) {
|
|
3125
|
-
const state = getState();
|
|
3126
|
-
if (config.debug !== void 0) state.debug = config.debug;
|
|
3127
|
-
if (config.handler !== void 0) state.handler = config.handler;
|
|
3128
|
-
},
|
|
3129
|
-
/**
|
|
3130
|
-
* Enable/disable debug logging for a specific tag.
|
|
3131
|
-
* Per-tag setting overrides the global debug flag.
|
|
3132
|
-
*
|
|
3133
|
-
* @example
|
|
3134
|
-
* ```ts
|
|
3135
|
-
* logger.setTagDebug('Nostr', true); // enable only Nostr logs
|
|
3136
|
-
* logger.setTagDebug('Nostr', false); // disable Nostr logs even if global debug=true
|
|
3137
|
-
* ```
|
|
3138
|
-
*/
|
|
3139
|
-
setTagDebug(tag, enabled) {
|
|
3140
|
-
getState().tags[tag] = enabled;
|
|
3141
|
-
},
|
|
3142
|
-
/**
|
|
3143
|
-
* Clear per-tag override, falling back to global debug flag.
|
|
3144
|
-
*/
|
|
3145
|
-
clearTagDebug(tag) {
|
|
3146
|
-
delete getState().tags[tag];
|
|
3147
|
-
},
|
|
3148
|
-
/** Returns true if debug mode is enabled for the given tag (or globally). */
|
|
3149
|
-
isDebugEnabled(tag) {
|
|
3150
|
-
if (tag) return isEnabled(tag);
|
|
3151
|
-
return getState().debug;
|
|
3152
|
-
},
|
|
3153
|
-
/**
|
|
3154
|
-
* Debug-level log. Only shown when debug is enabled (globally or for this tag).
|
|
3155
|
-
* Use for detailed operational information.
|
|
3156
|
-
*/
|
|
3157
|
-
debug(tag, message, ...args) {
|
|
3158
|
-
if (!isEnabled(tag)) return;
|
|
3159
|
-
const state = getState();
|
|
3160
|
-
if (state.handler) {
|
|
3161
|
-
state.handler("debug", tag, message, ...args);
|
|
3162
|
-
} else {
|
|
3163
|
-
console.log(`[${tag}]`, message, ...args);
|
|
3164
|
-
}
|
|
3165
|
-
},
|
|
3166
|
-
/**
|
|
3167
|
-
* Warning-level log. ALWAYS shown regardless of debug flag.
|
|
3168
|
-
* Use for important but non-critical issues (timeouts, retries, degraded state).
|
|
3169
|
-
*/
|
|
3170
|
-
warn(tag, message, ...args) {
|
|
3171
|
-
const state = getState();
|
|
3172
|
-
if (state.handler) {
|
|
3173
|
-
state.handler("warn", tag, message, ...args);
|
|
3174
|
-
} else {
|
|
3175
|
-
console.warn(`[${tag}]`, message, ...args);
|
|
3176
|
-
}
|
|
3177
|
-
},
|
|
3178
|
-
/**
|
|
3179
|
-
* Error-level log. ALWAYS shown regardless of debug flag.
|
|
3180
|
-
* Use for critical failures that should never be silenced.
|
|
3181
|
-
*/
|
|
3182
|
-
error(tag, message, ...args) {
|
|
3183
|
-
const state = getState();
|
|
3184
|
-
if (state.handler) {
|
|
3185
|
-
state.handler("error", tag, message, ...args);
|
|
3186
|
-
} else {
|
|
3187
|
-
console.error(`[${tag}]`, message, ...args);
|
|
3188
|
-
}
|
|
3189
|
-
},
|
|
3190
|
-
/** Reset all logger state (debug flag, tags, handler). Primarily for tests. */
|
|
3191
|
-
reset() {
|
|
3192
|
-
const g = globalThis;
|
|
3193
|
-
delete g[LOGGER_KEY];
|
|
3194
|
-
}
|
|
3195
|
-
};
|
|
3196
|
-
|
|
3197
|
-
// modules/payments-v2/ports.ts
|
|
3198
|
-
function isRetryableAckError(err) {
|
|
3199
|
-
return err !== null && typeof err === "object" && err.retryable === true;
|
|
3200
|
-
}
|
|
3201
|
-
|
|
3202
3146
|
// modules/payments-v2/receive/Receive.ts
|
|
3203
3147
|
var ACK_BATCH_SIZE = 200;
|
|
3204
3148
|
var REFRESH_INTERVAL_MS = 2500;
|
|
@@ -3247,22 +3191,24 @@ var Receive = class {
|
|
|
3247
3191
|
* the tokens just accepted, and the balance would still only move at the end.
|
|
3248
3192
|
* Ordering is preserved: store() still precedes the ack (§5.7).
|
|
3249
3193
|
*/
|
|
3250
|
-
async maybeRefresh(
|
|
3194
|
+
async maybeRefresh(ctx) {
|
|
3195
|
+
const { deps, pending, pageEpoch } = ctx;
|
|
3251
3196
|
if (deps.refreshView === void 0) return;
|
|
3252
3197
|
const now = deps.now?.() ?? Date.now();
|
|
3253
3198
|
if (now - this.lastRefreshAt < REFRESH_INTERVAL_MS) return;
|
|
3254
3199
|
this.lastRefreshAt = now;
|
|
3255
|
-
await flushAcks(deps, pending,
|
|
3256
|
-
deps.refreshView();
|
|
3200
|
+
if ((await flushAcks(deps, pending, pageEpoch)).progressed) deps.refreshView();
|
|
3257
3201
|
}
|
|
3258
3202
|
/** One listing pass: process each entry, flushing and refreshing as it goes. */
|
|
3259
3203
|
async drainPages(ctx, basis) {
|
|
3260
|
-
const { deps,
|
|
3204
|
+
const { deps, pending, pageEpoch, claimable } = ctx;
|
|
3261
3205
|
for await (const entry of deps.delivery.incoming(basis === null ? void 0 : String(basis.cursor))) {
|
|
3262
|
-
const
|
|
3263
|
-
await this.processEntry(
|
|
3264
|
-
if (pending.length >= ACK_BATCH_SIZE)
|
|
3265
|
-
|
|
3206
|
+
const claimableBefore = claimable.n;
|
|
3207
|
+
await this.processEntry(ctx, entry);
|
|
3208
|
+
if (pending.length >= ACK_BATCH_SIZE) {
|
|
3209
|
+
if (!(await flushAcks(deps, pending, pageEpoch)).progressed) return;
|
|
3210
|
+
}
|
|
3211
|
+
if (claimable.n > claimableBefore) await this.maybeRefresh(ctx);
|
|
3266
3212
|
}
|
|
3267
3213
|
await flushAcks(deps, pending, pageEpoch);
|
|
3268
3214
|
}
|
|
@@ -3273,11 +3219,16 @@ var Receive = class {
|
|
|
3273
3219
|
const stored = [];
|
|
3274
3220
|
const pending = [];
|
|
3275
3221
|
const pageEpoch = () => deps.delivery.incomingEpoch() ?? deps.syncEpoch();
|
|
3222
|
+
const claimable = { n: 0 };
|
|
3223
|
+
const finish = () => {
|
|
3224
|
+
if (claimable.n > 0) deps.refreshView?.();
|
|
3225
|
+
return stored;
|
|
3226
|
+
};
|
|
3276
3227
|
try {
|
|
3277
3228
|
const record = await deps.kv.get(STORE_KEYS.streamCursor("mailbox"));
|
|
3278
3229
|
let basis = record !== null && record.syncEpoch === deps.syncEpoch() ? record : null;
|
|
3279
3230
|
for (let pass = 0; pass < 2; pass++) {
|
|
3280
|
-
await this.drainPages({ deps, engine, pending, stored, pageEpoch }, basis);
|
|
3231
|
+
await this.drainPages({ deps, engine, pending, stored, pageEpoch, claimable }, basis);
|
|
3281
3232
|
const served = deps.delivery.incomingEpoch();
|
|
3282
3233
|
if (basis === null || served === null || served === basis.syncEpoch) break;
|
|
3283
3234
|
await deps.kv.remove(STORE_KEYS.streamCursor("mailbox"));
|
|
@@ -3285,22 +3236,25 @@ var Receive = class {
|
|
|
3285
3236
|
}
|
|
3286
3237
|
} catch (err) {
|
|
3287
3238
|
logger.warn("PaymentsV2", "receive drain interrupted \u2014 unacked entries retry next drain:", err);
|
|
3288
|
-
if (isRetryableAckError(err)) return
|
|
3239
|
+
if (isRetryableAckError(err)) return finish();
|
|
3289
3240
|
await flushAcks(deps, pending, pageEpoch).catch((flushErr) => {
|
|
3290
3241
|
logger.warn("PaymentsV2", "receive ack flush failed \u2014 cursor holds at the acked prefix:", flushErr);
|
|
3242
|
+
return { progressed: false };
|
|
3291
3243
|
});
|
|
3292
3244
|
}
|
|
3293
|
-
|
|
3294
|
-
return stored;
|
|
3245
|
+
return finish();
|
|
3295
3246
|
}
|
|
3296
|
-
async processEntry(
|
|
3247
|
+
async processEntry(ctx, entry) {
|
|
3248
|
+
const { deps, engine, pending, stored, claimable } = ctx;
|
|
3297
3249
|
const screened = await screen(deps, engine, entry);
|
|
3298
3250
|
if (screened.kind === "ack") {
|
|
3299
3251
|
pending.push(screened.ack);
|
|
3252
|
+
if (screened.ack.disposition === "claimed") claimable.n += 1;
|
|
3300
3253
|
return;
|
|
3301
3254
|
}
|
|
3302
3255
|
await deps.view.store(screened.record);
|
|
3303
3256
|
pending.push(claimAck(entry));
|
|
3257
|
+
claimable.n += 1;
|
|
3304
3258
|
const transfer = await announce(deps, entry, screened.record);
|
|
3305
3259
|
stored.push(transfer);
|
|
3306
3260
|
deps.emit("transfer:incoming", transfer);
|
|
@@ -3310,13 +3264,9 @@ async function screen(deps, engine, entry) {
|
|
|
3310
3264
|
const blobBytes = await entry.fetchBlob();
|
|
3311
3265
|
let token;
|
|
3312
3266
|
try {
|
|
3313
|
-
token = await engine.decodeToken({
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
tokenId: "",
|
|
3317
|
-
token: blobBytes
|
|
3318
|
-
});
|
|
3319
|
-
} catch {
|
|
3267
|
+
token = await engine.decodeToken({ tokenId: "", token: blobBytes });
|
|
3268
|
+
} catch (err) {
|
|
3269
|
+
logger.warn("PaymentsV2", `receive: undecodable blob rejected \u2014 ${String(err)}`);
|
|
3320
3270
|
return { kind: "ack", ack: rejectAck(entry, "invalid") };
|
|
3321
3271
|
}
|
|
3322
3272
|
const verdict = await engine.verify(token);
|
|
@@ -3361,7 +3311,8 @@ async function announce(deps, entry, record) {
|
|
|
3361
3311
|
};
|
|
3362
3312
|
}
|
|
3363
3313
|
async function flushAcks(deps, pending, epochOf) {
|
|
3364
|
-
if (pending.length === 0) return;
|
|
3314
|
+
if (pending.length === 0) return { progressed: true };
|
|
3315
|
+
const before = pending.length;
|
|
3365
3316
|
let lastAcked = null;
|
|
3366
3317
|
try {
|
|
3367
3318
|
const settled = await settleAcks(deps, pending);
|
|
@@ -3379,6 +3330,7 @@ async function flushAcks(deps, pending, epochOf) {
|
|
|
3379
3330
|
await deps.kv.set(STORE_KEYS.streamCursor("mailbox"), record);
|
|
3380
3331
|
}
|
|
3381
3332
|
}
|
|
3333
|
+
return { progressed: pending.length < before };
|
|
3382
3334
|
}
|
|
3383
3335
|
async function settleAcks(deps, pending) {
|
|
3384
3336
|
const batch = deps.delivery.ackBatch?.bind(deps.delivery);
|
|
@@ -4717,7 +4669,7 @@ var PaymentsFacade = class {
|
|
|
4717
4669
|
if (bytes === void 0) {
|
|
4718
4670
|
throw new SphereError(`Selected source ${tokenId} has no blob in storage`, "STORAGE_ERROR");
|
|
4719
4671
|
}
|
|
4720
|
-
const token = await engine.decodeToken({
|
|
4672
|
+
const token = await engine.decodeToken({ tokenId, token: bytes });
|
|
4721
4673
|
const keys = await engine.deliveryKeys(bytes);
|
|
4722
4674
|
spentStates[tokenId] = { local: keys.stateHash, protocol: keys.stateHash };
|
|
4723
4675
|
sources.set(tokenId, token);
|
|
@@ -4981,7 +4933,9 @@ export {
|
|
|
4981
4933
|
PaymentsFacade,
|
|
4982
4934
|
STORE_KEYS,
|
|
4983
4935
|
createScopedKV,
|
|
4984
|
-
|
|
4936
|
+
isRetryableAckError,
|
|
4937
|
+
supportsDeterministicMint,
|
|
4938
|
+
sweepSupersededState
|
|
4985
4939
|
};
|
|
4986
4940
|
/*! Bundled license information:
|
|
4987
4941
|
|