@unicitylabs/sphere-sdk 0.9.0-dev.1 → 0.9.0

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.
@@ -1,679 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // token-engine/index.ts
21
- var token_engine_exports = {};
22
- __export(token_engine_exports, {
23
- SpherePaymentData: () => SpherePaymentData,
24
- createSphereTokenEngine: () => createSphereTokenEngine,
25
- createUnicityIdMinter: () => createUnicityIdMinter,
26
- decodeSpherePaymentData: () => decodeSpherePaymentData,
27
- deriveDirectAddress: () => deriveDirectAddress,
28
- sphereAssetToSdk: () => sphereAssetToSdk
29
- });
30
- module.exports = __toCommonJS(token_engine_exports);
31
-
32
- // token-engine/sdk.ts
33
- var import_StateTransitionClient = require("@unicitylabs/state-transition-sdk/lib/StateTransitionClient.js");
34
- var import_AggregatorClient = require("@unicitylabs/state-transition-sdk/lib/api/AggregatorClient.js");
35
- var import_NetworkId = require("@unicitylabs/state-transition-sdk/lib/api/NetworkId.js");
36
- var import_CertificationData = require("@unicitylabs/state-transition-sdk/lib/api/CertificationData.js");
37
- var import_CertificationResponse = require("@unicitylabs/state-transition-sdk/lib/api/CertificationResponse.js");
38
- var import_StateId = require("@unicitylabs/state-transition-sdk/lib/api/StateId.js");
39
- var import_InclusionProof = require("@unicitylabs/state-transition-sdk/lib/api/InclusionProof.js");
40
- var import_InclusionProofResponse = require("@unicitylabs/state-transition-sdk/lib/api/InclusionProofResponse.js");
41
- var import_RootTrustBase = require("@unicitylabs/state-transition-sdk/lib/api/bft/RootTrustBase.js");
42
- var import_InclusionProofUtils = require("@unicitylabs/state-transition-sdk/lib/util/InclusionProofUtils.js");
43
- var import_Token = require("@unicitylabs/state-transition-sdk/lib/transaction/Token.js");
44
- var import_MintTransaction = require("@unicitylabs/state-transition-sdk/lib/transaction/MintTransaction.js");
45
- var import_TransferTransaction = require("@unicitylabs/state-transition-sdk/lib/transaction/TransferTransaction.js");
46
- var import_CertifiedMintTransaction = require("@unicitylabs/state-transition-sdk/lib/transaction/CertifiedMintTransaction.js");
47
- var import_CertifiedTransferTransaction = require("@unicitylabs/state-transition-sdk/lib/transaction/CertifiedTransferTransaction.js");
48
- var import_TokenId = require("@unicitylabs/state-transition-sdk/lib/transaction/TokenId.js");
49
- var import_TokenType = require("@unicitylabs/state-transition-sdk/lib/transaction/TokenType.js");
50
- var import_TokenSalt = require("@unicitylabs/state-transition-sdk/lib/transaction/TokenSalt.js");
51
- var import_MintJustificationVerifierService = require("@unicitylabs/state-transition-sdk/lib/transaction/verification/MintJustificationVerifierService.js");
52
- var import_EncodedPredicate = require("@unicitylabs/state-transition-sdk/lib/predicate/EncodedPredicate.js");
53
- var import_SignaturePredicate = require("@unicitylabs/state-transition-sdk/lib/predicate/builtin/SignaturePredicate.js");
54
- var import_SignaturePredicateUnlockScript = require("@unicitylabs/state-transition-sdk/lib/predicate/builtin/SignaturePredicateUnlockScript.js");
55
- var import_BurnPredicate = require("@unicitylabs/state-transition-sdk/lib/predicate/builtin/BurnPredicate.js");
56
- var import_PredicateVerifierService = require("@unicitylabs/state-transition-sdk/lib/predicate/verification/PredicateVerifierService.js");
57
- var import_SigningService = require("@unicitylabs/state-transition-sdk/lib/crypto/secp256k1/SigningService.js");
58
- var import_Signature = require("@unicitylabs/state-transition-sdk/lib/crypto/secp256k1/Signature.js");
59
- var import_MintSigningService = require("@unicitylabs/state-transition-sdk/lib/crypto/MintSigningService.js");
60
- var import_HashAlgorithm = require("@unicitylabs/state-transition-sdk/lib/crypto/hash/HashAlgorithm.js");
61
- var import_DataHash = require("@unicitylabs/state-transition-sdk/lib/crypto/hash/DataHash.js");
62
- var import_DataHasher = require("@unicitylabs/state-transition-sdk/lib/crypto/hash/DataHasher.js");
63
- var import_DataHasherFactory = require("@unicitylabs/state-transition-sdk/lib/crypto/hash/DataHasherFactory.js");
64
- var import_CborSerializer = require("@unicitylabs/state-transition-sdk/lib/serialization/cbor/CborSerializer.js");
65
- var import_CborDeserializer = require("@unicitylabs/state-transition-sdk/lib/serialization/cbor/CborDeserializer.js");
66
- var import_CborError = require("@unicitylabs/state-transition-sdk/lib/serialization/cbor/CborError.js");
67
- var import_Asset = require("@unicitylabs/state-transition-sdk/lib/payment/asset/Asset.js");
68
- var import_AssetId = require("@unicitylabs/state-transition-sdk/lib/payment/asset/AssetId.js");
69
- var import_PaymentAssetCollection = require("@unicitylabs/state-transition-sdk/lib/payment/asset/PaymentAssetCollection.js");
70
- var import_TokenSplit = require("@unicitylabs/state-transition-sdk/lib/payment/TokenSplit.js");
71
- var import_SplitTokenRequest = require("@unicitylabs/state-transition-sdk/lib/payment/SplitTokenRequest.js");
72
- var import_SplitToken = require("@unicitylabs/state-transition-sdk/lib/payment/SplitToken.js");
73
- var import_SplitAssetProof = require("@unicitylabs/state-transition-sdk/lib/payment/SplitAssetProof.js");
74
- var import_SplitMintJustification = require("@unicitylabs/state-transition-sdk/lib/payment/SplitMintJustification.js");
75
- var import_SplitMintJustificationVerifier = require("@unicitylabs/state-transition-sdk/lib/payment/SplitMintJustificationVerifier.js");
76
- var import_VerificationStatus = require("@unicitylabs/state-transition-sdk/lib/verification/VerificationStatus.js");
77
- var import_VerificationResult = require("@unicitylabs/state-transition-sdk/lib/verification/VerificationResult.js");
78
- var import_UnicityId = require("@unicitylabs/state-transition-sdk/lib/unicity-id/UnicityId.js");
79
- var import_UnicityIdMintTransaction = require("@unicitylabs/state-transition-sdk/lib/unicity-id/UnicityIdMintTransaction.js");
80
- var import_CertifiedUnicityIdMintTransaction = require("@unicitylabs/state-transition-sdk/lib/unicity-id/CertifiedUnicityIdMintTransaction.js");
81
- var import_UnicityIdToken = require("@unicitylabs/state-transition-sdk/lib/unicity-id/UnicityIdToken.js");
82
- var import_HexConverter = require("@unicitylabs/state-transition-sdk/lib/util/HexConverter.js");
83
- var import_BigintConverter = require("@unicitylabs/state-transition-sdk/lib/util/BigintConverter.js");
84
- var import_BitString = require("@unicitylabs/state-transition-sdk/lib/util/BitString.js");
85
-
86
- // token-engine/identity.ts
87
- var UNICITY_TOKEN_TYPE_HEX = "f8aa13834268d29355ff12183066f0cb902003629bbc5eb9ef0efbe397867509";
88
- var SIGNING_ALGORITHM = "secp256k1";
89
- var EMBEDDED_PREDICATE_UNMASKED = 0;
90
- var HASH_ALGORITHM_SHA256 = 0n;
91
- var SHA256_IMPRINT_PREFIX = new Uint8Array([0, 0]);
92
- function hexToBytes(hex) {
93
- const bytes = new Uint8Array(hex.length / 2);
94
- for (let i = 0; i < bytes.length; i++) {
95
- bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
96
- }
97
- return bytes;
98
- }
99
- function sha256(data) {
100
- return new import_DataHasher.DataHasher(import_HashAlgorithm.HashAlgorithm.SHA256).update(data).digest().then((h) => h.data);
101
- }
102
- async function deriveDirectAddress(publicKey) {
103
- const tokenTypeCbor = import_CborSerializer.CborSerializer.encodeByteString(hexToBytes(UNICITY_TOKEN_TYPE_HEX));
104
- const reference = import_CborSerializer.CborSerializer.encodeArray(
105
- import_CborSerializer.CborSerializer.encodeByteString(new Uint8Array([EMBEDDED_PREDICATE_UNMASKED])),
106
- import_CborSerializer.CborSerializer.encodeByteString(tokenTypeCbor),
107
- import_CborSerializer.CborSerializer.encodeTextString(SIGNING_ALGORITHM),
108
- import_CborSerializer.CborSerializer.encodeUnsignedInteger(HASH_ALGORITHM_SHA256),
109
- import_CborSerializer.CborSerializer.encodeByteString(publicKey)
110
- );
111
- const refHash = await sha256(reference);
112
- const imprint = new Uint8Array([...SHA256_IMPRINT_PREFIX, ...refHash]);
113
- const checksum = (await sha256(imprint)).slice(0, 4);
114
- return `DIRECT://${import_HexConverter.HexConverter.encode(imprint)}${import_HexConverter.HexConverter.encode(checksum)}`;
115
- }
116
-
117
- // core/errors.ts
118
- var SphereError = class extends Error {
119
- code;
120
- cause;
121
- constructor(message, code, cause) {
122
- super(message);
123
- this.name = "SphereError";
124
- this.code = code;
125
- this.cause = cause;
126
- }
127
- };
128
-
129
- // core/logger.ts
130
- var LOGGER_KEY = "__sphere_sdk_logger__";
131
- function getState() {
132
- const g = globalThis;
133
- if (!g[LOGGER_KEY]) {
134
- g[LOGGER_KEY] = { debug: false, tags: {}, handler: null };
135
- }
136
- return g[LOGGER_KEY];
137
- }
138
- function isEnabled(tag) {
139
- const state = getState();
140
- if (tag in state.tags) return state.tags[tag];
141
- return state.debug;
142
- }
143
- var logger = {
144
- /**
145
- * Configure the logger. Can be called multiple times (last write wins).
146
- * Typically called by createBrowserProviders(), createNodeProviders(), or Sphere.init().
147
- */
148
- configure(config) {
149
- const state = getState();
150
- if (config.debug !== void 0) state.debug = config.debug;
151
- if (config.handler !== void 0) state.handler = config.handler;
152
- },
153
- /**
154
- * Enable/disable debug logging for a specific tag.
155
- * Per-tag setting overrides the global debug flag.
156
- *
157
- * @example
158
- * ```ts
159
- * logger.setTagDebug('Nostr', true); // enable only Nostr logs
160
- * logger.setTagDebug('Nostr', false); // disable Nostr logs even if global debug=true
161
- * ```
162
- */
163
- setTagDebug(tag, enabled) {
164
- getState().tags[tag] = enabled;
165
- },
166
- /**
167
- * Clear per-tag override, falling back to global debug flag.
168
- */
169
- clearTagDebug(tag) {
170
- delete getState().tags[tag];
171
- },
172
- /** Returns true if debug mode is enabled for the given tag (or globally). */
173
- isDebugEnabled(tag) {
174
- if (tag) return isEnabled(tag);
175
- return getState().debug;
176
- },
177
- /**
178
- * Debug-level log. Only shown when debug is enabled (globally or for this tag).
179
- * Use for detailed operational information.
180
- */
181
- debug(tag, message, ...args) {
182
- if (!isEnabled(tag)) return;
183
- const state = getState();
184
- if (state.handler) {
185
- state.handler("debug", tag, message, ...args);
186
- } else {
187
- console.log(`[${tag}]`, message, ...args);
188
- }
189
- },
190
- /**
191
- * Warning-level log. ALWAYS shown regardless of debug flag.
192
- * Use for important but non-critical issues (timeouts, retries, degraded state).
193
- */
194
- warn(tag, message, ...args) {
195
- const state = getState();
196
- if (state.handler) {
197
- state.handler("warn", tag, message, ...args);
198
- } else {
199
- console.warn(`[${tag}]`, message, ...args);
200
- }
201
- },
202
- /**
203
- * Error-level log. ALWAYS shown regardless of debug flag.
204
- * Use for critical failures that should never be silenced.
205
- */
206
- error(tag, message, ...args) {
207
- const state = getState();
208
- if (state.handler) {
209
- state.handler("error", tag, message, ...args);
210
- } else {
211
- console.error(`[${tag}]`, message, ...args);
212
- }
213
- },
214
- /** Reset all logger state (debug flag, tags, handler). Primarily for tests. */
215
- reset() {
216
- const g = globalThis;
217
- delete g[LOGGER_KEY];
218
- }
219
- };
220
-
221
- // token-engine/SpherePaymentData.ts
222
- var COIN_ID_PATTERN = /^([0-9a-f]{2})+$/;
223
- function assertAsset(coinId, amount) {
224
- if (!COIN_ID_PATTERN.test(coinId)) {
225
- throw new SphereError(`Invalid coin id (expected even-length lowercase hex): "${coinId}"`, "VALIDATION_ERROR");
226
- }
227
- if (amount < 0n) {
228
- throw new SphereError(`Asset amount must be non-negative: ${amount.toString()}`, "VALIDATION_ERROR");
229
- }
230
- }
231
- function sphereAssetToSdk(coinId, amount) {
232
- assertAsset(coinId, amount);
233
- return new import_Asset.Asset(new import_AssetId.AssetId(import_HexConverter.HexConverter.decode(coinId)), amount);
234
- }
235
- var SpherePaymentData = class _SpherePaymentData {
236
- constructor(assets, _memo = null) {
237
- this.assets = assets;
238
- this._memo = _memo;
239
- }
240
- /** Sphere-private CBOR tag (verified free in the v2 SDK tag space). */
241
- static CBOR_TAG = 39050n;
242
- /** Envelope version; bump when the structure changes. */
243
- static VERSION = 1n;
244
- /** Opaque, app-defined memo carried alongside the value (e.g. invoice attribution). */
245
- get memo() {
246
- return this._memo ? new Uint8Array(this._memo) : null;
247
- }
248
- /** Wrap an existing SDK asset collection (+ optional opaque memo). */
249
- static create(assets, memo = null) {
250
- return new _SpherePaymentData(assets, memo);
251
- }
252
- /** Build from a sphere-domain value (hex coin id → bigint amount) + optional opaque memo. */
253
- static fromValue(value, memo = null) {
254
- const assets = value.assets.map((a) => sphereAssetToSdk(a.coinId, a.amount));
255
- return new _SpherePaymentData(import_PaymentAssetCollection.PaymentAssetCollection.create(...assets), memo);
256
- }
257
- /** Decode from the CBOR envelope produced by {@link encode}. */
258
- static fromCBOR(bytes) {
259
- const tag = import_CborDeserializer.CborDeserializer.decodeTag(bytes);
260
- if (tag.tag !== _SpherePaymentData.CBOR_TAG) {
261
- throw new import_CborError.CborError(`Invalid SpherePaymentData tag: ${tag.tag}`);
262
- }
263
- const fields = import_CborDeserializer.CborDeserializer.decodeArray(tag.data, 3);
264
- const version = import_CborDeserializer.CborDeserializer.decodeUnsignedInteger(fields[0]);
265
- if (version !== _SpherePaymentData.VERSION) {
266
- throw new import_CborError.CborError(`Unsupported SpherePaymentData version: ${version}`);
267
- }
268
- const memo = import_CborDeserializer.CborDeserializer.decodeNullable(fields[2], import_CborDeserializer.CborDeserializer.decodeByteString);
269
- return new _SpherePaymentData(import_PaymentAssetCollection.PaymentAssetCollection.fromCBOR(fields[1]), memo);
270
- }
271
- /** Deterministic, versioned, tagged CBOR: `tag(39050)[ version, assets, memo? ]`. */
272
- encode() {
273
- return Promise.resolve(
274
- import_CborSerializer.CborSerializer.encodeTag(
275
- _SpherePaymentData.CBOR_TAG,
276
- import_CborSerializer.CborSerializer.encodeArray(
277
- import_CborSerializer.CborSerializer.encodeUnsignedInteger(_SpherePaymentData.VERSION),
278
- this.assets.toCBOR(),
279
- import_CborSerializer.CborSerializer.encodeNullable(this._memo, import_CborSerializer.CborSerializer.encodeByteString)
280
- )
281
- )
282
- );
283
- }
284
- /** Project to a sphere-domain value (hex coin id + bigint amount), preserving order. */
285
- toValue() {
286
- return {
287
- assets: this.assets.toArray().map((a) => ({
288
- coinId: import_HexConverter.HexConverter.encode(a.id.bytes),
289
- amount: a.value
290
- }))
291
- };
292
- }
293
- /** Balance of a single coin within this payload (0n when absent). */
294
- balanceOf(coinId) {
295
- if (!COIN_ID_PATTERN.test(coinId)) {
296
- throw new SphereError(`Invalid coin id (expected even-length lowercase hex): "${coinId}"`, "VALIDATION_ERROR");
297
- }
298
- const asset = this.assets.get(new import_AssetId.AssetId(import_HexConverter.HexConverter.decode(coinId)));
299
- return asset ? asset.value : 0n;
300
- }
301
- };
302
- function decodeSpherePaymentData(bytes) {
303
- return Promise.resolve(SpherePaymentData.fromCBOR(bytes));
304
- }
305
-
306
- // token-engine/token-blob.ts
307
- var TOKEN_BLOB_VERSION = 1;
308
-
309
- // token-engine/SphereTokenEngine.ts
310
- var SphereTokenEngine = class {
311
- constructor(deps) {
312
- this.deps = deps;
313
- }
314
- // ── identity ────────────────────────────────────────────────────────────────
315
- getIdentity() {
316
- return { chainPubkey: new Uint8Array(this.deps.signingService.publicKey) };
317
- }
318
- /** Legacy DIRECT:// address (Path A). Async: the derivation hashes via the SDK. */
319
- deriveIdentityAddress(pubkey) {
320
- return deriveDirectAddress(pubkey ?? this.deps.signingService.publicKey);
321
- }
322
- // ── value (read) ─────────────────────────────────────────────────────────────
323
- readValue(token) {
324
- return token.value;
325
- }
326
- balanceOf(token, coinId) {
327
- let sum = 0n;
328
- for (const asset of token.value?.assets ?? []) {
329
- if (asset.coinId === coinId) sum += asset.amount;
330
- }
331
- return sum;
332
- }
333
- tokenId(token) {
334
- return token.blob.tokenId;
335
- }
336
- readMemo(token) {
337
- const sdkToken = token.sdkToken;
338
- if (sdkToken.transactions.length > 0) {
339
- return sdkToken.latestTransaction.data;
340
- }
341
- const data = sdkToken.genesis.data;
342
- if (data && this.isSpherePaymentData(data)) {
343
- return SpherePaymentData.fromCBOR(data).memo;
344
- }
345
- return null;
346
- }
347
- readTokenData(token) {
348
- const data = token.sdkToken.genesis.data;
349
- return data ? new Uint8Array(data) : null;
350
- }
351
- // ── lifecycle ────────────────────────────────────────────────────────────────
352
- async mint(params, options) {
353
- const recipient = import_SignaturePredicate.SignaturePredicate.create(params.recipientPubkey);
354
- const data = params.value ? await SpherePaymentData.fromValue(params.value).encode() : null;
355
- const mintTx = await import_MintTransaction.MintTransaction.create(this.deps.networkId, recipient, data);
356
- const certificationData = await import_CertificationData.CertificationData.fromMintTransaction(mintTx);
357
- const response = await this.deps.client.submitCertificationRequest(certificationData);
358
- if (response.status !== import_CertificationResponse.CertificationStatus.SUCCESS) {
359
- throw new SphereError(`Mint certification failed: ${response.status}`, "AGGREGATOR_ERROR");
360
- }
361
- const proof = await (0, import_InclusionProofUtils.waitInclusionProof)(
362
- this.deps.client,
363
- this.deps.trustBase,
364
- this.deps.predicateVerifier,
365
- mintTx,
366
- options?.signal
367
- );
368
- const certified = await mintTx.toCertifiedTransaction(this.deps.trustBase, this.deps.predicateVerifier, proof);
369
- const token = await import_Token.Token.mint(
370
- this.deps.trustBase,
371
- this.deps.predicateVerifier,
372
- this.deps.mintJustificationVerifier,
373
- certified
374
- );
375
- return this.wrapToken(token);
376
- }
377
- async mintDataToken(params, options) {
378
- const recipient = import_SignaturePredicate.SignaturePredicate.create(params.recipientPubkey);
379
- const tokenType = params.tokenType ? new import_TokenType.TokenType(params.tokenType) : import_TokenType.TokenType.generate();
380
- const salt = params.salt ? import_TokenSalt.TokenSalt.fromBytes(params.salt) : import_TokenSalt.TokenSalt.generate();
381
- const mintTx = await import_MintTransaction.MintTransaction.create(this.deps.networkId, recipient, params.data, tokenType, salt);
382
- const certificationData = await import_CertificationData.CertificationData.fromMintTransaction(mintTx);
383
- const response = await this.deps.client.submitCertificationRequest(certificationData);
384
- if (response.status !== import_CertificationResponse.CertificationStatus.SUCCESS) {
385
- throw new SphereError(`Data-token mint failed: ${response.status}`, "AGGREGATOR_ERROR");
386
- }
387
- const proof = await (0, import_InclusionProofUtils.waitInclusionProof)(
388
- this.deps.client,
389
- this.deps.trustBase,
390
- this.deps.predicateVerifier,
391
- mintTx,
392
- options?.signal
393
- );
394
- const certified = await mintTx.toCertifiedTransaction(this.deps.trustBase, this.deps.predicateVerifier, proof);
395
- const token = await import_Token.Token.mint(
396
- this.deps.trustBase,
397
- this.deps.predicateVerifier,
398
- this.deps.mintJustificationVerifier,
399
- certified
400
- );
401
- return this.wrapToken(token);
402
- }
403
- async transfer(params, options) {
404
- this.assertOwned(params.token);
405
- const recipient = import_SignaturePredicate.SignaturePredicate.create(params.recipientPubkey);
406
- const stateMask = crypto.getRandomValues(new Uint8Array(32));
407
- const transferTx = await import_TransferTransaction.TransferTransaction.create(params.token.sdkToken, recipient, stateMask, params.data ?? null);
408
- const unlockScript = await import_SignaturePredicateUnlockScript.SignaturePredicateUnlockScript.create(transferTx, this.deps.signingService);
409
- const certificationData = await import_CertificationData.CertificationData.fromTransaction(transferTx, unlockScript);
410
- const response = await this.deps.client.submitCertificationRequest(certificationData);
411
- if (response.status !== import_CertificationResponse.CertificationStatus.SUCCESS) {
412
- throw new SphereError(`Transfer certification failed: ${response.status}`, "TRANSFER_FAILED");
413
- }
414
- const proof = await (0, import_InclusionProofUtils.waitInclusionProof)(
415
- this.deps.client,
416
- this.deps.trustBase,
417
- this.deps.predicateVerifier,
418
- transferTx,
419
- options?.signal
420
- );
421
- const certified = await transferTx.toCertifiedTransaction(this.deps.trustBase, this.deps.predicateVerifier, proof);
422
- const transferred = await params.token.sdkToken.transfer(this.deps.trustBase, this.deps.predicateVerifier, certified);
423
- return this.wrapToken(transferred);
424
- }
425
- async split(params, options) {
426
- this.assertOwned(params.token);
427
- if (params.outputs.length === 0) {
428
- throw new SphereError("Split requires at least one output", "VALIDATION_ERROR");
429
- }
430
- const requests = params.outputs.map(
431
- (o) => import_SplitTokenRequest.SplitTokenRequest.create(
432
- import_SignaturePredicate.SignaturePredicate.create(o.recipientPubkey),
433
- import_PaymentAssetCollection.PaymentAssetCollection.create(sphereAssetToSdk(o.coinId, o.amount))
434
- )
435
- );
436
- const split = await import_TokenSplit.TokenSplit.split(params.token.sdkToken, decodeSpherePaymentData, requests);
437
- const burnUnlock = await import_SignaturePredicateUnlockScript.SignaturePredicateUnlockScript.create(split.burn.transaction, this.deps.signingService);
438
- const burnCert = await import_CertificationData.CertificationData.fromTransaction(split.burn.transaction, burnUnlock);
439
- const burnResponse = await this.deps.client.submitCertificationRequest(burnCert);
440
- if (burnResponse.status !== import_CertificationResponse.CertificationStatus.SUCCESS) {
441
- throw new SphereError(`Split burn failed: ${burnResponse.status}`, "TRANSFER_FAILED");
442
- }
443
- const burnProof = await (0, import_InclusionProofUtils.waitInclusionProof)(
444
- this.deps.client,
445
- this.deps.trustBase,
446
- this.deps.predicateVerifier,
447
- split.burn.transaction,
448
- options?.signal
449
- );
450
- const burnCertified = await split.burn.transaction.toCertifiedTransaction(
451
- this.deps.trustBase,
452
- this.deps.predicateVerifier,
453
- burnProof
454
- );
455
- const burntToken = await params.token.sdkToken.transfer(
456
- this.deps.trustBase,
457
- this.deps.predicateVerifier,
458
- burnCertified
459
- );
460
- const outputs = [];
461
- for (let i = 0; i < split.tokens.length; i++) {
462
- const splitToken = split.tokens[i];
463
- const data = await SpherePaymentData.create(splitToken.assets, params.outputs[i].data ?? null).encode();
464
- const justification = import_SplitMintJustification.SplitMintJustification.create(burntToken, splitToken.proofs).toCBOR();
465
- const mintTx = await import_MintTransaction.MintTransaction.create(
466
- splitToken.networkId,
467
- splitToken.recipient,
468
- data,
469
- splitToken.tokenType,
470
- splitToken.salt,
471
- justification
472
- );
473
- const certData = await import_CertificationData.CertificationData.fromMintTransaction(mintTx);
474
- const response = await this.deps.client.submitCertificationRequest(certData);
475
- if (response.status !== import_CertificationResponse.CertificationStatus.SUCCESS) {
476
- throw new SphereError(`Split mint failed: ${response.status}`, "AGGREGATOR_ERROR");
477
- }
478
- const proof = await (0, import_InclusionProofUtils.waitInclusionProof)(
479
- this.deps.client,
480
- this.deps.trustBase,
481
- this.deps.predicateVerifier,
482
- mintTx,
483
- options?.signal
484
- );
485
- const certified = await mintTx.toCertifiedTransaction(this.deps.trustBase, this.deps.predicateVerifier, proof);
486
- const token = await import_Token.Token.mint(
487
- this.deps.trustBase,
488
- this.deps.predicateVerifier,
489
- this.deps.mintJustificationVerifier,
490
- certified
491
- );
492
- outputs.push(this.wrapToken(token));
493
- }
494
- return { outputs };
495
- }
496
- // ── verification ─────────────────────────────────────────────────────────────
497
- async verify(token, _options) {
498
- const result = await token.sdkToken.verify(
499
- this.deps.trustBase,
500
- this.deps.predicateVerifier,
501
- this.deps.mintJustificationVerifier
502
- );
503
- return result.status === import_VerificationStatus.VerificationStatus.OK ? { ok: true } : { ok: false, reason: String(result.status) };
504
- }
505
- isOwnedBy(token, pubkey) {
506
- const owner = token.sdkToken.latestTransaction.recipient;
507
- const claimed = import_EncodedPredicate.EncodedPredicate.fromPredicate(import_SignaturePredicate.SignaturePredicate.create(pubkey));
508
- return import_EncodedPredicate.EncodedPredicate.equals(owner, claimed);
509
- }
510
- async isSpent(token, _options) {
511
- const probe = await import_TransferTransaction.TransferTransaction.create(
512
- token.sdkToken,
513
- import_SignaturePredicate.SignaturePredicate.create(this.deps.signingService.publicKey),
514
- new Uint8Array(32)
515
- );
516
- const stateId = await import_StateId.StateId.fromTransaction(probe);
517
- const response = await this.deps.client.getInclusionProof(stateId);
518
- return response.inclusionProof.inclusionCertificate !== null;
519
- }
520
- // ── serialization ────────────────────────────────────────────────────────────
521
- encodeToken(token) {
522
- return token.blob;
523
- }
524
- async decodeToken(blob) {
525
- const sdkToken = await import_Token.Token.fromCBOR(blob.token);
526
- if (sdkToken.genesis.networkId.id !== this.deps.networkId.id) {
527
- throw new SphereError(
528
- `Token network mismatch: token is on network ${sdkToken.genesis.networkId.id}, engine on ${this.deps.networkId.id}`,
529
- "VALIDATION_ERROR"
530
- );
531
- }
532
- return this.wrapToken(sdkToken);
533
- }
534
- // ── internals ────────────────────────────────────────────────────────────────
535
- /** Fail fast if this engine's key does not own the token's current state. */
536
- assertOwned(token) {
537
- if (!this.isOwnedBy(token, this.deps.signingService.publicKey)) {
538
- throw new SphereError("Cannot transfer a token not owned by this engine identity", "VALIDATION_ERROR");
539
- }
540
- }
541
- /** Wrap an SDK token into a SphereToken: cache its blob (incl. stable tokenId) + decoded value. */
542
- wrapToken(sdkToken) {
543
- const data = sdkToken.genesis.data;
544
- let value = null;
545
- if (data && this.isSpherePaymentData(data)) {
546
- try {
547
- value = SpherePaymentData.fromCBOR(data).toValue();
548
- } catch (err) {
549
- throw new SphereError(
550
- `Failed to decode token payment data: ${err instanceof Error ? err.message : String(err)}`,
551
- "VALIDATION_ERROR"
552
- );
553
- }
554
- }
555
- const blob = {
556
- v: TOKEN_BLOB_VERSION,
557
- network: sdkToken.genesis.networkId.id,
558
- tokenId: import_HexConverter.HexConverter.encode(sdkToken.id.bytes),
559
- token: sdkToken.toCBOR()
560
- };
561
- return { sdkToken, blob, value };
562
- }
563
- /** True if the bytes are a SpherePaymentData envelope (value token) vs a raw data token. */
564
- isSpherePaymentData(data) {
565
- try {
566
- return import_CborDeserializer.CborDeserializer.decodeTag(data).tag === SpherePaymentData.CBOR_TAG;
567
- } catch {
568
- return false;
569
- }
570
- }
571
- };
572
-
573
- // token-engine/factory.ts
574
- async function createSphereTokenEngine(config) {
575
- if (config.trustBaseJson == null) {
576
- throw new SphereError("Engine config requires a trust base (trustBaseJson)", "INVALID_CONFIG");
577
- }
578
- if (!config.apiKey) {
579
- logger.warn(
580
- "TokenEngine",
581
- "No aggregator apiKey \u2014 pass config.oracle.apiKey (testnet2 value in .env.example; mainnet from a secret env var). Gateway requests will be unauthenticated."
582
- );
583
- }
584
- const trustBase = import_RootTrustBase.RootTrustBase.fromJSON(config.trustBaseJson);
585
- const predicateVerifier = import_PredicateVerifierService.PredicateVerifierService.create();
586
- const mintJustificationVerifier = new import_MintJustificationVerifierService.MintJustificationVerifierService();
587
- mintJustificationVerifier.register(
588
- new import_SplitMintJustificationVerifier.SplitMintJustificationVerifier(trustBase, predicateVerifier, decodeSpherePaymentData)
589
- );
590
- const deps = {
591
- client: new import_StateTransitionClient.StateTransitionClient(new import_AggregatorClient.AggregatorClient(config.aggregatorUrl, config.apiKey ?? null)),
592
- trustBase,
593
- predicateVerifier,
594
- mintJustificationVerifier,
595
- signingService: new import_SigningService.SigningService(config.privateKey),
596
- // The trust base is the single source of truth for the network id (it carries
597
- // NetworkId.fromId, so any id works — e.g. testnet2 = 4 — with no enum entry).
598
- networkId: trustBase.networkId
599
- };
600
- return new SphereTokenEngine(deps);
601
- }
602
-
603
- // token-engine/unicity-id.ts
604
- var SelfIssuedUnicityIdMinter = class {
605
- constructor(client, trustBase, predicateVerifier, signingService) {
606
- this.client = client;
607
- this.trustBase = trustBase;
608
- this.predicateVerifier = predicateVerifier;
609
- this.signingService = signingService;
610
- }
611
- async mintUnicityIdToken(name, options) {
612
- const unicityId = new import_UnicityId.UnicityId(name);
613
- const self = import_SignaturePredicate.SignaturePredicate.fromSigningService(this.signingService);
614
- const mintTx = await import_UnicityIdMintTransaction.UnicityIdMintTransaction.create(
615
- self,
616
- // issuer lock script (self-issued)
617
- self,
618
- // recipient — locks the minted token state to this wallet
619
- unicityId,
620
- new import_TokenType.TokenType(import_HexConverter.HexConverter.decode(UNICITY_TOKEN_TYPE_HEX)),
621
- self
622
- // target predicate the unicity id resolves to
623
- );
624
- const certificationData = await import_CertificationData.CertificationData.fromTransaction(
625
- mintTx,
626
- await import_SignaturePredicateUnlockScript.SignaturePredicateUnlockScript.create(mintTx, this.signingService)
627
- );
628
- const response = await this.client.submitCertificationRequest(certificationData);
629
- if (response.status !== import_CertificationResponse.CertificationStatus.SUCCESS) {
630
- logger.warn(
631
- "UnicityIdMinter",
632
- `Certification request returned ${response.status} for "@${name}" \u2014 attempting proof recovery (idempotent re-mint).`
633
- );
634
- }
635
- try {
636
- const proof = await (0, import_InclusionProofUtils.waitInclusionProof)(
637
- this.client,
638
- this.trustBase,
639
- this.predicateVerifier,
640
- mintTx,
641
- options?.signal
642
- );
643
- const certified = await mintTx.toCertifiedTransaction(this.trustBase, this.predicateVerifier, proof);
644
- const token = await import_UnicityIdToken.UnicityIdToken.mint(this.trustBase, this.predicateVerifier, certified);
645
- return {
646
- tokenCborHex: import_HexConverter.HexConverter.encode(token.toCBOR()),
647
- tokenId: import_HexConverter.HexConverter.encode(token.id.bytes)
648
- };
649
- } catch (err) {
650
- const detail = err instanceof Error ? err.message : String(err);
651
- throw new SphereError(
652
- `Unicity ID mint failed for "@${name}": ${detail}` + (response.status !== import_CertificationResponse.CertificationStatus.SUCCESS ? ` (certification status: ${response.status})` : ""),
653
- "AGGREGATOR_ERROR"
654
- );
655
- }
656
- }
657
- };
658
- function createUnicityIdMinter(config) {
659
- if (config.trustBaseJson == null) {
660
- throw new SphereError("Unicity ID minter requires a trust base (trustBaseJson)", "INVALID_CONFIG");
661
- }
662
- const trustBase = import_RootTrustBase.RootTrustBase.fromJSON(config.trustBaseJson);
663
- return new SelfIssuedUnicityIdMinter(
664
- new import_StateTransitionClient.StateTransitionClient(new import_AggregatorClient.AggregatorClient(config.aggregatorUrl, config.apiKey ?? null)),
665
- trustBase,
666
- import_PredicateVerifierService.PredicateVerifierService.create(),
667
- new import_SigningService.SigningService(config.privateKey)
668
- );
669
- }
670
- // Annotate the CommonJS export names for ESM import in node:
671
- 0 && (module.exports = {
672
- SpherePaymentData,
673
- createSphereTokenEngine,
674
- createUnicityIdMinter,
675
- decodeSpherePaymentData,
676
- deriveDirectAddress,
677
- sphereAssetToSdk
678
- });
679
- //# sourceMappingURL=index.cjs.map