@buildonspark/spark-sdk 0.1.44 → 0.1.46
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/CHANGELOG.md +17 -0
- package/dist/{RequestLightningSendInput-BxbCtwpV.d.cts → RequestLightningSendInput-2cSh_In4.d.cts} +1 -1
- package/dist/{RequestLightningSendInput-RGel43ks.d.ts → RequestLightningSendInput-CN6BNg_g.d.ts} +1 -1
- package/dist/address/index.cjs +2 -2
- package/dist/address/index.d.cts +2 -2
- package/dist/address/index.d.ts +2 -2
- package/dist/address/index.js +2 -2
- package/dist/{chunk-EKFD62HN.js → chunk-4EMV7HHW.js} +2 -1
- package/dist/{chunk-4Q2ZDYYU.js → chunk-BGGEVUJK.js} +1157 -208
- package/dist/{chunk-CIZNCBKE.js → chunk-C2S227QR.js} +648 -45
- package/dist/{chunk-WPTRVD2V.js → chunk-DXR2PXJU.js} +15 -15
- package/dist/{chunk-NBCNYDWJ.js → chunk-HHNQ3ZHC.js} +2 -2
- package/dist/{chunk-DAXGVPVM.js → chunk-HSCLBJEL.js} +2 -2
- package/dist/{chunk-6AFUC5M2.js → chunk-HWJWKEIU.js} +8 -2
- package/dist/{chunk-A2ZLMH6I.js → chunk-JB64OQES.js} +259 -327
- package/dist/{chunk-KEKGSH7B.js → chunk-KMUMFYFX.js} +3 -3
- package/dist/chunk-LHRD2WT6.js +2374 -0
- package/dist/{chunk-HTMXTJRK.js → chunk-N5VZVCGJ.js} +4 -4
- package/dist/{chunk-SQKXGAIR.js → chunk-NTFKFRQ2.js} +1 -1
- package/dist/{chunk-K4BJARWM.js → chunk-OBFKIEMP.js} +1 -1
- package/dist/{chunk-UBT6EDVJ.js → chunk-OFCJFZ4I.js} +1 -1
- package/dist/{chunk-XX4RRWOX.js → chunk-UXDODSDT.js} +8 -10
- package/dist/graphql/objects/index.d.cts +5 -4
- package/dist/graphql/objects/index.d.ts +5 -4
- package/dist/index-CKL5DodV.d.cts +214 -0
- package/dist/index-COm59SPw.d.ts +214 -0
- package/dist/index.cjs +4026 -1315
- package/dist/index.d.cts +764 -19
- package/dist/index.d.ts +764 -19
- package/dist/index.js +23 -27
- package/dist/index.node.cjs +4026 -1319
- package/dist/index.node.d.cts +10 -8
- package/dist/index.node.d.ts +10 -8
- package/dist/index.node.js +23 -31
- package/dist/native/index.cjs +4027 -1316
- package/dist/native/index.d.cts +281 -85
- package/dist/native/index.d.ts +281 -85
- package/dist/native/index.js +4018 -1307
- package/dist/{network-CfxLnaot.d.cts → network-Css46DAz.d.cts} +1 -1
- package/dist/{network-CroCOQ0B.d.ts → network-hynb7iTZ.d.ts} +1 -1
- package/dist/proto/lrc20.cjs +222 -19
- package/dist/proto/lrc20.d.cts +1 -1
- package/dist/proto/lrc20.d.ts +1 -1
- package/dist/proto/lrc20.js +2 -2
- package/dist/proto/spark.cjs +1154 -205
- package/dist/proto/spark.d.cts +1 -1
- package/dist/proto/spark.d.ts +1 -1
- package/dist/proto/spark.js +3 -1
- package/dist/proto/spark_token.cjs +1377 -58
- package/dist/proto/spark_token.d.cts +153 -15
- package/dist/proto/spark_token.d.ts +153 -15
- package/dist/proto/spark_token.js +40 -4
- package/dist/{sdk-types-CTbTdDbE.d.ts → sdk-types-CKBsylfW.d.ts} +1 -1
- package/dist/{sdk-types-BeCBoozO.d.cts → sdk-types-Ct8xmN7l.d.cts} +1 -1
- package/dist/services/config.cjs +2 -2
- package/dist/services/config.d.cts +5 -4
- package/dist/services/config.d.ts +5 -4
- package/dist/services/config.js +6 -6
- package/dist/services/connection.cjs +2438 -262
- package/dist/services/connection.d.cts +5 -4
- package/dist/services/connection.d.ts +5 -4
- package/dist/services/connection.js +4 -4
- package/dist/services/index.cjs +5937 -3154
- package/dist/services/index.d.cts +7 -6
- package/dist/services/index.d.ts +7 -6
- package/dist/services/index.js +17 -15
- package/dist/services/lrc-connection.cjs +223 -20
- package/dist/services/lrc-connection.d.cts +5 -4
- package/dist/services/lrc-connection.d.ts +5 -4
- package/dist/services/lrc-connection.js +4 -4
- package/dist/services/token-transactions.cjs +840 -236
- package/dist/services/token-transactions.d.cts +25 -7
- package/dist/services/token-transactions.d.ts +25 -7
- package/dist/services/token-transactions.js +5 -4
- package/dist/services/wallet-config.cjs +3 -1
- package/dist/services/wallet-config.d.cts +7 -5
- package/dist/services/wallet-config.d.ts +7 -5
- package/dist/services/wallet-config.js +3 -1
- package/dist/signer/signer.cjs +1 -1
- package/dist/signer/signer.d.cts +3 -2
- package/dist/signer/signer.d.ts +3 -2
- package/dist/signer/signer.js +2 -2
- package/dist/{signer-D7vfYik9.d.ts → signer-BP6F__oR.d.cts} +2 -6
- package/dist/{signer-DaY8c60s.d.cts → signer-BVZJXcq7.d.ts} +2 -6
- package/dist/{spark-C4ZrsgjC.d.cts → spark-DbzGfse6.d.cts} +93 -15
- package/dist/{spark-C4ZrsgjC.d.ts → spark-DbzGfse6.d.ts} +93 -15
- package/dist/spark_bindings/native/index.cjs +183 -0
- package/dist/spark_bindings/native/index.d.cts +14 -0
- package/dist/spark_bindings/native/index.d.ts +14 -0
- package/dist/spark_bindings/native/index.js +141 -0
- package/dist/spark_bindings/wasm/index.cjs +1093 -0
- package/dist/spark_bindings/wasm/index.d.cts +47 -0
- package/dist/spark_bindings/wasm/index.d.ts +47 -0
- package/dist/{chunk-K4C4W5FC.js → spark_bindings/wasm/index.js} +7 -6
- package/dist/types/index.cjs +1156 -208
- package/dist/types/index.d.cts +5 -4
- package/dist/types/index.d.ts +5 -4
- package/dist/types/index.js +2 -2
- package/dist/types-C-Rp0Oo7.d.cts +46 -0
- package/dist/types-C-Rp0Oo7.d.ts +46 -0
- package/dist/utils/index.cjs +65 -13
- package/dist/utils/index.d.cts +14 -134
- package/dist/utils/index.d.ts +14 -134
- package/dist/utils/index.js +13 -13
- package/package.json +22 -2
- package/src/index.node.ts +0 -1
- package/src/index.ts +0 -1
- package/src/native/index.ts +1 -2
- package/src/proto/common.ts +5 -5
- package/src/proto/google/protobuf/descriptor.ts +34 -34
- package/src/proto/google/protobuf/duration.ts +2 -2
- package/src/proto/google/protobuf/empty.ts +2 -2
- package/src/proto/google/protobuf/timestamp.ts +2 -2
- package/src/proto/mock.ts +4 -4
- package/src/proto/spark.ts +1452 -185
- package/src/proto/spark_authn.ts +7 -7
- package/src/proto/spark_token.ts +1668 -105
- package/src/proto/validate/validate.ts +24 -24
- package/src/services/bolt11-spark.ts +62 -187
- package/src/services/coop-exit.ts +3 -0
- package/src/services/lrc20.ts +1 -1
- package/src/services/token-transactions.ts +197 -9
- package/src/services/transfer.ts +22 -0
- package/src/services/tree-creation.ts +13 -0
- package/src/services/wallet-config.ts +2 -2
- package/src/spark-wallet/spark-wallet.node.ts +0 -4
- package/src/spark-wallet/spark-wallet.ts +76 -108
- package/src/spark-wallet/types.ts +39 -3
- package/src/tests/bolt11-spark.test.ts +7 -15
- package/src/tests/integration/ssp/coop-exit.test.ts +7 -7
- package/src/tests/integration/swap.test.ts +453 -433
- package/src/tests/integration/transfer.test.ts +261 -248
- package/src/tests/token-identifier.test.ts +54 -0
- package/src/tests/tokens.test.ts +218 -23
- package/src/utils/token-hashing.ts +320 -44
- package/src/utils/token-identifier.ts +88 -0
- package/src/utils/token-transaction-validation.ts +350 -5
- package/src/utils/token-transactions.ts +12 -8
- package/src/utils/transaction.ts +0 -6
- package/dist/chunk-B3AMIGJG.js +0 -1073
- package/dist/index-CZmDdSts.d.cts +0 -829
- package/dist/index-ClIRO_3y.d.ts +0 -829
- package/dist/wasm-7OWFHDMS.js +0 -21
|
@@ -142,6 +142,215 @@ var InternalValidationError = class extends SparkSDKError {
|
|
|
142
142
|
}
|
|
143
143
|
};
|
|
144
144
|
|
|
145
|
+
// src/proto/spark_token.ts
|
|
146
|
+
var import_wire5 = require("@bufbuild/protobuf/wire");
|
|
147
|
+
|
|
148
|
+
// src/proto/google/protobuf/timestamp.ts
|
|
149
|
+
var import_wire = require("@bufbuild/protobuf/wire");
|
|
150
|
+
|
|
151
|
+
// src/proto/spark.ts
|
|
152
|
+
var import_wire4 = require("@bufbuild/protobuf/wire");
|
|
153
|
+
|
|
154
|
+
// src/proto/common.ts
|
|
155
|
+
var import_wire2 = require("@bufbuild/protobuf/wire");
|
|
156
|
+
|
|
157
|
+
// src/proto/google/protobuf/empty.ts
|
|
158
|
+
var import_wire3 = require("@bufbuild/protobuf/wire");
|
|
159
|
+
|
|
160
|
+
// src/proto/spark.ts
|
|
161
|
+
function createBaseSparkAddress() {
|
|
162
|
+
return { identityPublicKey: new Uint8Array(0), paymentIntentFields: void 0 };
|
|
163
|
+
}
|
|
164
|
+
var SparkAddress = {
|
|
165
|
+
encode(message, writer = new import_wire4.BinaryWriter()) {
|
|
166
|
+
if (message.identityPublicKey.length !== 0) {
|
|
167
|
+
writer.uint32(10).bytes(message.identityPublicKey);
|
|
168
|
+
}
|
|
169
|
+
if (message.paymentIntentFields !== void 0) {
|
|
170
|
+
PaymentIntentFields.encode(message.paymentIntentFields, writer.uint32(18).fork()).join();
|
|
171
|
+
}
|
|
172
|
+
return writer;
|
|
173
|
+
},
|
|
174
|
+
decode(input, length) {
|
|
175
|
+
const reader = input instanceof import_wire4.BinaryReader ? input : new import_wire4.BinaryReader(input);
|
|
176
|
+
const end = length === void 0 ? reader.len : reader.pos + length;
|
|
177
|
+
const message = createBaseSparkAddress();
|
|
178
|
+
while (reader.pos < end) {
|
|
179
|
+
const tag = reader.uint32();
|
|
180
|
+
switch (tag >>> 3) {
|
|
181
|
+
case 1: {
|
|
182
|
+
if (tag !== 10) {
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
message.identityPublicKey = reader.bytes();
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
case 2: {
|
|
189
|
+
if (tag !== 18) {
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
message.paymentIntentFields = PaymentIntentFields.decode(reader, reader.uint32());
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if ((tag & 7) === 4 || tag === 0) {
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
reader.skip(tag & 7);
|
|
200
|
+
}
|
|
201
|
+
return message;
|
|
202
|
+
},
|
|
203
|
+
fromJSON(object) {
|
|
204
|
+
return {
|
|
205
|
+
identityPublicKey: isSet(object.identityPublicKey) ? bytesFromBase64(object.identityPublicKey) : new Uint8Array(0),
|
|
206
|
+
paymentIntentFields: isSet(object.paymentIntentFields) ? PaymentIntentFields.fromJSON(object.paymentIntentFields) : void 0
|
|
207
|
+
};
|
|
208
|
+
},
|
|
209
|
+
toJSON(message) {
|
|
210
|
+
const obj = {};
|
|
211
|
+
if (message.identityPublicKey.length !== 0) {
|
|
212
|
+
obj.identityPublicKey = base64FromBytes(message.identityPublicKey);
|
|
213
|
+
}
|
|
214
|
+
if (message.paymentIntentFields !== void 0) {
|
|
215
|
+
obj.paymentIntentFields = PaymentIntentFields.toJSON(message.paymentIntentFields);
|
|
216
|
+
}
|
|
217
|
+
return obj;
|
|
218
|
+
},
|
|
219
|
+
create(base) {
|
|
220
|
+
return SparkAddress.fromPartial(base ?? {});
|
|
221
|
+
},
|
|
222
|
+
fromPartial(object) {
|
|
223
|
+
const message = createBaseSparkAddress();
|
|
224
|
+
message.identityPublicKey = object.identityPublicKey ?? new Uint8Array(0);
|
|
225
|
+
message.paymentIntentFields = object.paymentIntentFields !== void 0 && object.paymentIntentFields !== null ? PaymentIntentFields.fromPartial(object.paymentIntentFields) : void 0;
|
|
226
|
+
return message;
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
function createBasePaymentIntentFields() {
|
|
230
|
+
return { id: new Uint8Array(0), assetIdentifier: void 0, assetAmount: new Uint8Array(0), memo: void 0 };
|
|
231
|
+
}
|
|
232
|
+
var PaymentIntentFields = {
|
|
233
|
+
encode(message, writer = new import_wire4.BinaryWriter()) {
|
|
234
|
+
if (message.id.length !== 0) {
|
|
235
|
+
writer.uint32(10).bytes(message.id);
|
|
236
|
+
}
|
|
237
|
+
if (message.assetIdentifier !== void 0) {
|
|
238
|
+
writer.uint32(18).bytes(message.assetIdentifier);
|
|
239
|
+
}
|
|
240
|
+
if (message.assetAmount.length !== 0) {
|
|
241
|
+
writer.uint32(26).bytes(message.assetAmount);
|
|
242
|
+
}
|
|
243
|
+
if (message.memo !== void 0) {
|
|
244
|
+
writer.uint32(34).string(message.memo);
|
|
245
|
+
}
|
|
246
|
+
return writer;
|
|
247
|
+
},
|
|
248
|
+
decode(input, length) {
|
|
249
|
+
const reader = input instanceof import_wire4.BinaryReader ? input : new import_wire4.BinaryReader(input);
|
|
250
|
+
const end = length === void 0 ? reader.len : reader.pos + length;
|
|
251
|
+
const message = createBasePaymentIntentFields();
|
|
252
|
+
while (reader.pos < end) {
|
|
253
|
+
const tag = reader.uint32();
|
|
254
|
+
switch (tag >>> 3) {
|
|
255
|
+
case 1: {
|
|
256
|
+
if (tag !== 10) {
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
259
|
+
message.id = reader.bytes();
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
case 2: {
|
|
263
|
+
if (tag !== 18) {
|
|
264
|
+
break;
|
|
265
|
+
}
|
|
266
|
+
message.assetIdentifier = reader.bytes();
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
case 3: {
|
|
270
|
+
if (tag !== 26) {
|
|
271
|
+
break;
|
|
272
|
+
}
|
|
273
|
+
message.assetAmount = reader.bytes();
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
case 4: {
|
|
277
|
+
if (tag !== 34) {
|
|
278
|
+
break;
|
|
279
|
+
}
|
|
280
|
+
message.memo = reader.string();
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
if ((tag & 7) === 4 || tag === 0) {
|
|
285
|
+
break;
|
|
286
|
+
}
|
|
287
|
+
reader.skip(tag & 7);
|
|
288
|
+
}
|
|
289
|
+
return message;
|
|
290
|
+
},
|
|
291
|
+
fromJSON(object) {
|
|
292
|
+
return {
|
|
293
|
+
id: isSet(object.id) ? bytesFromBase64(object.id) : new Uint8Array(0),
|
|
294
|
+
assetIdentifier: isSet(object.assetIdentifier) ? bytesFromBase64(object.assetIdentifier) : void 0,
|
|
295
|
+
assetAmount: isSet(object.assetAmount) ? bytesFromBase64(object.assetAmount) : new Uint8Array(0),
|
|
296
|
+
memo: isSet(object.memo) ? globalThis.String(object.memo) : void 0
|
|
297
|
+
};
|
|
298
|
+
},
|
|
299
|
+
toJSON(message) {
|
|
300
|
+
const obj = {};
|
|
301
|
+
if (message.id.length !== 0) {
|
|
302
|
+
obj.id = base64FromBytes(message.id);
|
|
303
|
+
}
|
|
304
|
+
if (message.assetIdentifier !== void 0) {
|
|
305
|
+
obj.assetIdentifier = base64FromBytes(message.assetIdentifier);
|
|
306
|
+
}
|
|
307
|
+
if (message.assetAmount.length !== 0) {
|
|
308
|
+
obj.assetAmount = base64FromBytes(message.assetAmount);
|
|
309
|
+
}
|
|
310
|
+
if (message.memo !== void 0) {
|
|
311
|
+
obj.memo = message.memo;
|
|
312
|
+
}
|
|
313
|
+
return obj;
|
|
314
|
+
},
|
|
315
|
+
create(base) {
|
|
316
|
+
return PaymentIntentFields.fromPartial(base ?? {});
|
|
317
|
+
},
|
|
318
|
+
fromPartial(object) {
|
|
319
|
+
const message = createBasePaymentIntentFields();
|
|
320
|
+
message.id = object.id ?? new Uint8Array(0);
|
|
321
|
+
message.assetIdentifier = object.assetIdentifier ?? void 0;
|
|
322
|
+
message.assetAmount = object.assetAmount ?? new Uint8Array(0);
|
|
323
|
+
message.memo = object.memo ?? void 0;
|
|
324
|
+
return message;
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
function bytesFromBase64(b64) {
|
|
328
|
+
if (globalThis.Buffer) {
|
|
329
|
+
return Uint8Array.from(globalThis.Buffer.from(b64, "base64"));
|
|
330
|
+
} else {
|
|
331
|
+
const bin = globalThis.atob(b64);
|
|
332
|
+
const arr = new Uint8Array(bin.length);
|
|
333
|
+
for (let i = 0; i < bin.length; ++i) {
|
|
334
|
+
arr[i] = bin.charCodeAt(i);
|
|
335
|
+
}
|
|
336
|
+
return arr;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
function base64FromBytes(arr) {
|
|
340
|
+
if (globalThis.Buffer) {
|
|
341
|
+
return globalThis.Buffer.from(arr).toString("base64");
|
|
342
|
+
} else {
|
|
343
|
+
const bin = [];
|
|
344
|
+
arr.forEach((byte) => {
|
|
345
|
+
bin.push(globalThis.String.fromCharCode(byte));
|
|
346
|
+
});
|
|
347
|
+
return globalThis.btoa(bin.join(""));
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
function isSet(value) {
|
|
351
|
+
return value !== null && value !== void 0;
|
|
352
|
+
}
|
|
353
|
+
|
|
145
354
|
// src/utils/token-hashing.ts
|
|
146
355
|
function hashTokenTransaction(tokenTransaction, partialHash = false) {
|
|
147
356
|
switch (tokenTransaction.version) {
|
|
@@ -224,13 +433,21 @@ function hashTokenTransactionV0(tokenTransaction, partialHash = false) {
|
|
|
224
433
|
});
|
|
225
434
|
}
|
|
226
435
|
hashObj2.update(issuerPubKey);
|
|
227
|
-
|
|
436
|
+
let timestampValue = 0;
|
|
437
|
+
const mintInput = tokenTransaction.tokenInputs.mintInput;
|
|
438
|
+
if ("issuerProvidedTimestamp" in mintInput) {
|
|
439
|
+
const v0MintInput = mintInput;
|
|
440
|
+
if (v0MintInput.issuerProvidedTimestamp != 0) {
|
|
441
|
+
timestampValue = v0MintInput.issuerProvidedTimestamp;
|
|
442
|
+
}
|
|
443
|
+
} else if ("clientCreatedTimestamp" in tokenTransaction && tokenTransaction.clientCreatedTimestamp) {
|
|
444
|
+
timestampValue = tokenTransaction.clientCreatedTimestamp.getTime();
|
|
445
|
+
}
|
|
446
|
+
if (timestampValue != 0) {
|
|
228
447
|
const timestampBytes = new Uint8Array(8);
|
|
229
448
|
new DataView(timestampBytes.buffer).setBigUint64(
|
|
230
449
|
0,
|
|
231
|
-
BigInt(
|
|
232
|
-
tokenTransaction.tokenInputs.mintInput.issuerProvidedTimestamp
|
|
233
|
-
),
|
|
450
|
+
BigInt(timestampValue),
|
|
234
451
|
true
|
|
235
452
|
// true for little-endian to match Go implementation
|
|
236
453
|
);
|
|
@@ -239,12 +456,95 @@ function hashTokenTransactionV0(tokenTransaction, partialHash = false) {
|
|
|
239
456
|
allHashes.push(hashObj2.digest());
|
|
240
457
|
}
|
|
241
458
|
}
|
|
459
|
+
if (tokenTransaction.tokenInputs?.$case === "createInput") {
|
|
460
|
+
const issuerPubKeyHashObj = import_sha2.sha256.create();
|
|
461
|
+
const createInput = tokenTransaction.tokenInputs.createInput;
|
|
462
|
+
if (!createInput.issuerPublicKey || createInput.issuerPublicKey.length === 0) {
|
|
463
|
+
throw new ValidationError("issuer public key cannot be nil or empty", {
|
|
464
|
+
field: "tokenInputs.createInput.issuerPublicKey"
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
issuerPubKeyHashObj.update(createInput.issuerPublicKey);
|
|
468
|
+
allHashes.push(issuerPubKeyHashObj.digest());
|
|
469
|
+
const tokenNameHashObj = import_sha2.sha256.create();
|
|
470
|
+
if (!createInput.tokenName || createInput.tokenName.length === 0) {
|
|
471
|
+
throw new ValidationError("token name cannot be empty", {
|
|
472
|
+
field: "tokenInputs.createInput.tokenName"
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
if (createInput.tokenName.length > 20) {
|
|
476
|
+
throw new ValidationError("token name cannot be longer than 20 bytes", {
|
|
477
|
+
field: "tokenInputs.createInput.tokenName",
|
|
478
|
+
value: createInput.tokenName,
|
|
479
|
+
expectedLength: 20,
|
|
480
|
+
actualLength: createInput.tokenName.length
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
const tokenNameBytes = new Uint8Array(20);
|
|
484
|
+
const tokenNameEncoder = new TextEncoder();
|
|
485
|
+
tokenNameBytes.set(tokenNameEncoder.encode(createInput.tokenName));
|
|
486
|
+
tokenNameHashObj.update(tokenNameBytes);
|
|
487
|
+
allHashes.push(tokenNameHashObj.digest());
|
|
488
|
+
const tokenTickerHashObj = import_sha2.sha256.create();
|
|
489
|
+
if (!createInput.tokenTicker || createInput.tokenTicker.length === 0) {
|
|
490
|
+
throw new ValidationError("token ticker cannot be empty", {
|
|
491
|
+
field: "tokenInputs.createInput.tokenTicker"
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
if (createInput.tokenTicker.length > 6) {
|
|
495
|
+
throw new ValidationError("token ticker cannot be longer than 6 bytes", {
|
|
496
|
+
field: "tokenInputs.createInput.tokenTicker",
|
|
497
|
+
value: createInput.tokenTicker,
|
|
498
|
+
expectedLength: 6,
|
|
499
|
+
actualLength: createInput.tokenTicker.length
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
const tokenTickerBytes = new Uint8Array(6);
|
|
503
|
+
const tokenTickerEncoder = new TextEncoder();
|
|
504
|
+
tokenTickerBytes.set(tokenTickerEncoder.encode(createInput.tokenTicker));
|
|
505
|
+
tokenTickerHashObj.update(tokenTickerBytes);
|
|
506
|
+
allHashes.push(tokenTickerHashObj.digest());
|
|
507
|
+
const decimalsHashObj = import_sha2.sha256.create();
|
|
508
|
+
const decimalsBytes = new Uint8Array(4);
|
|
509
|
+
new DataView(decimalsBytes.buffer).setUint32(
|
|
510
|
+
0,
|
|
511
|
+
createInput.decimals,
|
|
512
|
+
false
|
|
513
|
+
);
|
|
514
|
+
decimalsHashObj.update(decimalsBytes);
|
|
515
|
+
allHashes.push(decimalsHashObj.digest());
|
|
516
|
+
const maxSupplyHashObj = import_sha2.sha256.create();
|
|
517
|
+
if (!createInput.maxSupply) {
|
|
518
|
+
throw new ValidationError("max supply cannot be nil", {
|
|
519
|
+
field: "tokenInputs.createInput.maxSupply"
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
if (createInput.maxSupply.length !== 16) {
|
|
523
|
+
throw new ValidationError("max supply must be exactly 16 bytes", {
|
|
524
|
+
field: "tokenInputs.createInput.maxSupply",
|
|
525
|
+
value: createInput.maxSupply,
|
|
526
|
+
expectedLength: 16,
|
|
527
|
+
actualLength: createInput.maxSupply.length
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
maxSupplyHashObj.update(createInput.maxSupply);
|
|
531
|
+
allHashes.push(maxSupplyHashObj.digest());
|
|
532
|
+
const isFreezableHashObj = import_sha2.sha256.create();
|
|
533
|
+
const isFreezableByte = new Uint8Array([createInput.isFreezable ? 1 : 0]);
|
|
534
|
+
isFreezableHashObj.update(isFreezableByte);
|
|
535
|
+
allHashes.push(isFreezableHashObj.digest());
|
|
536
|
+
const creationEntityHashObj = import_sha2.sha256.create();
|
|
537
|
+
if (!partialHash && createInput.creationEntityPublicKey) {
|
|
538
|
+
creationEntityHashObj.update(createInput.creationEntityPublicKey);
|
|
539
|
+
}
|
|
540
|
+
allHashes.push(creationEntityHashObj.digest());
|
|
541
|
+
}
|
|
242
542
|
if (!tokenTransaction.tokenOutputs) {
|
|
243
543
|
throw new ValidationError("token outputs cannot be null", {
|
|
244
544
|
field: "tokenOutputs"
|
|
245
545
|
});
|
|
246
546
|
}
|
|
247
|
-
if (tokenTransaction.tokenOutputs.length === 0) {
|
|
547
|
+
if (tokenTransaction.tokenOutputs.length === 0 && tokenTransaction.tokenInputs?.$case !== "createInput") {
|
|
248
548
|
throw new ValidationError("token outputs cannot be empty", {
|
|
249
549
|
field: "tokenOutputs"
|
|
250
550
|
});
|
|
@@ -421,6 +721,26 @@ function hashTokenTransactionV1(tokenTransaction, partialHash = false) {
|
|
|
421
721
|
);
|
|
422
722
|
versionHashObj.update(versionBytes);
|
|
423
723
|
allHashes.push(versionHashObj.digest());
|
|
724
|
+
const typeHashObj = import_sha2.sha256.create();
|
|
725
|
+
const typeBytes = new Uint8Array(4);
|
|
726
|
+
let transactionType = 0;
|
|
727
|
+
if (tokenTransaction.tokenInputs?.$case === "mintInput") {
|
|
728
|
+
transactionType = 2 /* TOKEN_TRANSACTION_TYPE_MINT */;
|
|
729
|
+
} else if (tokenTransaction.tokenInputs?.$case === "transferInput") {
|
|
730
|
+
transactionType = 3 /* TOKEN_TRANSACTION_TYPE_TRANSFER */;
|
|
731
|
+
} else if (tokenTransaction.tokenInputs?.$case === "createInput") {
|
|
732
|
+
transactionType = 1 /* TOKEN_TRANSACTION_TYPE_CREATE */;
|
|
733
|
+
} else {
|
|
734
|
+
throw new ValidationError(
|
|
735
|
+
"token transaction must have exactly one input type",
|
|
736
|
+
{
|
|
737
|
+
field: "tokenInputs"
|
|
738
|
+
}
|
|
739
|
+
);
|
|
740
|
+
}
|
|
741
|
+
new DataView(typeBytes.buffer).setUint32(0, transactionType, false);
|
|
742
|
+
typeHashObj.update(typeBytes);
|
|
743
|
+
allHashes.push(typeHashObj.digest());
|
|
424
744
|
if (tokenTransaction.tokenInputs?.$case === "transferInput") {
|
|
425
745
|
if (!tokenTransaction.tokenInputs.transferInput.outputsToSpend) {
|
|
426
746
|
throw new ValidationError("outputs to spend cannot be null", {
|
|
@@ -432,6 +752,15 @@ function hashTokenTransactionV1(tokenTransaction, partialHash = false) {
|
|
|
432
752
|
field: "tokenInputs.transferInput.outputsToSpend"
|
|
433
753
|
});
|
|
434
754
|
}
|
|
755
|
+
const outputsLenHashObj2 = import_sha2.sha256.create();
|
|
756
|
+
const outputsLenBytes2 = new Uint8Array(4);
|
|
757
|
+
new DataView(outputsLenBytes2.buffer).setUint32(
|
|
758
|
+
0,
|
|
759
|
+
tokenTransaction.tokenInputs.transferInput.outputsToSpend.length,
|
|
760
|
+
false
|
|
761
|
+
);
|
|
762
|
+
outputsLenHashObj2.update(outputsLenBytes2);
|
|
763
|
+
allHashes.push(outputsLenHashObj2.digest());
|
|
435
764
|
for (const [
|
|
436
765
|
i,
|
|
437
766
|
output
|
|
@@ -468,8 +797,7 @@ function hashTokenTransactionV1(tokenTransaction, partialHash = false) {
|
|
|
468
797
|
hashObj2.update(voutBytes);
|
|
469
798
|
allHashes.push(hashObj2.digest());
|
|
470
799
|
}
|
|
471
|
-
}
|
|
472
|
-
if (tokenTransaction.tokenInputs?.$case === "mintInput") {
|
|
800
|
+
} else if (tokenTransaction.tokenInputs?.$case === "mintInput") {
|
|
473
801
|
const hashObj2 = import_sha2.sha256.create();
|
|
474
802
|
if (tokenTransaction.tokenInputs.mintInput.issuerPublicKey) {
|
|
475
803
|
const issuerPubKey = tokenTransaction.tokenInputs.mintInput.issuerPublicKey;
|
|
@@ -482,31 +810,113 @@ function hashTokenTransactionV1(tokenTransaction, partialHash = false) {
|
|
|
482
810
|
});
|
|
483
811
|
}
|
|
484
812
|
hashObj2.update(issuerPubKey);
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
tokenTransaction.tokenInputs.mintInput.issuerProvidedTimestamp
|
|
491
|
-
),
|
|
492
|
-
true
|
|
493
|
-
// true for little-endian to match Go implementation
|
|
813
|
+
allHashes.push(hashObj2.digest());
|
|
814
|
+
const tokenIdentifierHashObj = import_sha2.sha256.create();
|
|
815
|
+
if (tokenTransaction.tokenInputs.mintInput.tokenIdentifier) {
|
|
816
|
+
tokenIdentifierHashObj.update(
|
|
817
|
+
tokenTransaction.tokenInputs.mintInput.tokenIdentifier
|
|
494
818
|
);
|
|
495
|
-
|
|
819
|
+
} else {
|
|
820
|
+
tokenIdentifierHashObj.update(new Uint8Array(32));
|
|
496
821
|
}
|
|
497
|
-
allHashes.push(
|
|
822
|
+
allHashes.push(tokenIdentifierHashObj.digest());
|
|
823
|
+
}
|
|
824
|
+
} else if (tokenTransaction.tokenInputs?.$case === "createInput") {
|
|
825
|
+
const createInput = tokenTransaction.tokenInputs.createInput;
|
|
826
|
+
const issuerPubKeyHashObj = import_sha2.sha256.create();
|
|
827
|
+
if (!createInput.issuerPublicKey || createInput.issuerPublicKey.length === 0) {
|
|
828
|
+
throw new ValidationError("issuer public key cannot be nil or empty", {
|
|
829
|
+
field: "tokenInputs.createInput.issuerPublicKey"
|
|
830
|
+
});
|
|
831
|
+
}
|
|
832
|
+
issuerPubKeyHashObj.update(createInput.issuerPublicKey);
|
|
833
|
+
allHashes.push(issuerPubKeyHashObj.digest());
|
|
834
|
+
const tokenNameHashObj = import_sha2.sha256.create();
|
|
835
|
+
if (!createInput.tokenName || createInput.tokenName.length === 0) {
|
|
836
|
+
throw new ValidationError("token name cannot be empty", {
|
|
837
|
+
field: "tokenInputs.createInput.tokenName"
|
|
838
|
+
});
|
|
839
|
+
}
|
|
840
|
+
if (createInput.tokenName.length > 20) {
|
|
841
|
+
throw new ValidationError("token name cannot be longer than 20 bytes", {
|
|
842
|
+
field: "tokenInputs.createInput.tokenName",
|
|
843
|
+
value: createInput.tokenName,
|
|
844
|
+
expectedLength: 20,
|
|
845
|
+
actualLength: createInput.tokenName.length
|
|
846
|
+
});
|
|
847
|
+
}
|
|
848
|
+
const tokenNameEncoder = new TextEncoder();
|
|
849
|
+
tokenNameHashObj.update(tokenNameEncoder.encode(createInput.tokenName));
|
|
850
|
+
allHashes.push(tokenNameHashObj.digest());
|
|
851
|
+
const tokenTickerHashObj = import_sha2.sha256.create();
|
|
852
|
+
if (!createInput.tokenTicker || createInput.tokenTicker.length === 0) {
|
|
853
|
+
throw new ValidationError("token ticker cannot be empty", {
|
|
854
|
+
field: "tokenInputs.createInput.tokenTicker"
|
|
855
|
+
});
|
|
856
|
+
}
|
|
857
|
+
if (createInput.tokenTicker.length > 6) {
|
|
858
|
+
throw new ValidationError("token ticker cannot be longer than 6 bytes", {
|
|
859
|
+
field: "tokenInputs.createInput.tokenTicker",
|
|
860
|
+
value: createInput.tokenTicker,
|
|
861
|
+
expectedLength: 6,
|
|
862
|
+
actualLength: createInput.tokenTicker.length
|
|
863
|
+
});
|
|
864
|
+
}
|
|
865
|
+
const tokenTickerEncoder = new TextEncoder();
|
|
866
|
+
tokenTickerHashObj.update(
|
|
867
|
+
tokenTickerEncoder.encode(createInput.tokenTicker)
|
|
868
|
+
);
|
|
869
|
+
allHashes.push(tokenTickerHashObj.digest());
|
|
870
|
+
const decimalsHashObj = import_sha2.sha256.create();
|
|
871
|
+
const decimalsBytes = new Uint8Array(4);
|
|
872
|
+
new DataView(decimalsBytes.buffer).setUint32(
|
|
873
|
+
0,
|
|
874
|
+
createInput.decimals,
|
|
875
|
+
false
|
|
876
|
+
);
|
|
877
|
+
decimalsHashObj.update(decimalsBytes);
|
|
878
|
+
allHashes.push(decimalsHashObj.digest());
|
|
879
|
+
const maxSupplyHashObj = import_sha2.sha256.create();
|
|
880
|
+
if (!createInput.maxSupply) {
|
|
881
|
+
throw new ValidationError("max supply cannot be nil", {
|
|
882
|
+
field: "tokenInputs.createInput.maxSupply"
|
|
883
|
+
});
|
|
498
884
|
}
|
|
885
|
+
if (createInput.maxSupply.length !== 16) {
|
|
886
|
+
throw new ValidationError("max supply must be exactly 16 bytes", {
|
|
887
|
+
field: "tokenInputs.createInput.maxSupply",
|
|
888
|
+
value: createInput.maxSupply,
|
|
889
|
+
expectedLength: 16,
|
|
890
|
+
actualLength: createInput.maxSupply.length
|
|
891
|
+
});
|
|
892
|
+
}
|
|
893
|
+
maxSupplyHashObj.update(createInput.maxSupply);
|
|
894
|
+
allHashes.push(maxSupplyHashObj.digest());
|
|
895
|
+
const isFreezableHashObj = import_sha2.sha256.create();
|
|
896
|
+
isFreezableHashObj.update(
|
|
897
|
+
new Uint8Array([createInput.isFreezable ? 1 : 0])
|
|
898
|
+
);
|
|
899
|
+
allHashes.push(isFreezableHashObj.digest());
|
|
900
|
+
const creationEntityHashObj = import_sha2.sha256.create();
|
|
901
|
+
if (!partialHash && createInput.creationEntityPublicKey) {
|
|
902
|
+
creationEntityHashObj.update(createInput.creationEntityPublicKey);
|
|
903
|
+
}
|
|
904
|
+
allHashes.push(creationEntityHashObj.digest());
|
|
499
905
|
}
|
|
500
906
|
if (!tokenTransaction.tokenOutputs) {
|
|
501
907
|
throw new ValidationError("token outputs cannot be null", {
|
|
502
908
|
field: "tokenOutputs"
|
|
503
909
|
});
|
|
504
910
|
}
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
911
|
+
const outputsLenHashObj = import_sha2.sha256.create();
|
|
912
|
+
const outputsLenBytes = new Uint8Array(4);
|
|
913
|
+
new DataView(outputsLenBytes.buffer).setUint32(
|
|
914
|
+
0,
|
|
915
|
+
tokenTransaction.tokenOutputs.length,
|
|
916
|
+
false
|
|
917
|
+
);
|
|
918
|
+
outputsLenHashObj.update(outputsLenBytes);
|
|
919
|
+
allHashes.push(outputsLenHashObj.digest());
|
|
510
920
|
for (const [i, output] of tokenTransaction.tokenOutputs.entries()) {
|
|
511
921
|
if (!output) {
|
|
512
922
|
throw new ValidationError(`output cannot be null at index ${i}`, {
|
|
@@ -565,18 +975,16 @@ function hashTokenTransactionV1(tokenTransaction, partialHash = false) {
|
|
|
565
975
|
);
|
|
566
976
|
hashObj2.update(locktimeBytes);
|
|
567
977
|
}
|
|
568
|
-
if (output.tokenPublicKey) {
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
`token public key at index ${i} cannot be empty`,
|
|
572
|
-
{
|
|
573
|
-
field: `tokenOutputs[${i}].tokenPublicKey`,
|
|
574
|
-
index: i
|
|
575
|
-
}
|
|
576
|
-
);
|
|
577
|
-
}
|
|
978
|
+
if (!output.tokenPublicKey || output.tokenPublicKey.length === 0) {
|
|
979
|
+
hashObj2.update(new Uint8Array(33));
|
|
980
|
+
} else {
|
|
578
981
|
hashObj2.update(output.tokenPublicKey);
|
|
579
982
|
}
|
|
983
|
+
if (!output.tokenIdentifier || output.tokenIdentifier.length === 0) {
|
|
984
|
+
hashObj2.update(new Uint8Array(32));
|
|
985
|
+
} else {
|
|
986
|
+
hashObj2.update(output.tokenIdentifier);
|
|
987
|
+
}
|
|
580
988
|
if (output.tokenAmount) {
|
|
581
989
|
if (output.tokenAmount.length === 0) {
|
|
582
990
|
throw new ValidationError(
|
|
@@ -617,6 +1025,15 @@ function hashTokenTransactionV1(tokenTransaction, partialHash = false) {
|
|
|
617
1025
|
}
|
|
618
1026
|
return a.length - b.length;
|
|
619
1027
|
});
|
|
1028
|
+
const operatorLenHashObj = import_sha2.sha256.create();
|
|
1029
|
+
const operatorLenBytes = new Uint8Array(4);
|
|
1030
|
+
new DataView(operatorLenBytes.buffer).setUint32(
|
|
1031
|
+
0,
|
|
1032
|
+
sortedPubKeys.length,
|
|
1033
|
+
false
|
|
1034
|
+
);
|
|
1035
|
+
operatorLenHashObj.update(operatorLenBytes);
|
|
1036
|
+
allHashes.push(operatorLenHashObj.digest());
|
|
620
1037
|
for (const [i, pubKey] of sortedPubKeys.entries()) {
|
|
621
1038
|
if (!pubKey) {
|
|
622
1039
|
throw new ValidationError(
|
|
@@ -652,7 +1069,15 @@ function hashTokenTransactionV1(tokenTransaction, partialHash = false) {
|
|
|
652
1069
|
allHashes.push(hashObj.digest());
|
|
653
1070
|
const clientTimestampHashObj = import_sha2.sha256.create();
|
|
654
1071
|
const clientCreatedTs = tokenTransaction.clientCreatedTimestamp;
|
|
655
|
-
|
|
1072
|
+
if (!clientCreatedTs) {
|
|
1073
|
+
throw new ValidationError(
|
|
1074
|
+
"client created timestamp cannot be null for V1 token transactions",
|
|
1075
|
+
{
|
|
1076
|
+
field: "clientCreatedTimestamp"
|
|
1077
|
+
}
|
|
1078
|
+
);
|
|
1079
|
+
}
|
|
1080
|
+
const clientUnixTime = clientCreatedTs.getTime();
|
|
656
1081
|
const clientTimestampBytes = new Uint8Array(8);
|
|
657
1082
|
new DataView(clientTimestampBytes.buffer).setBigUint64(
|
|
658
1083
|
0,
|
|
@@ -773,7 +1198,7 @@ function areByteArraysEqual(a, b) {
|
|
|
773
1198
|
function hasDuplicates(array) {
|
|
774
1199
|
return new Set(array).size !== array.length;
|
|
775
1200
|
}
|
|
776
|
-
function
|
|
1201
|
+
function validateTokenTransactionV0(finalTokenTransaction, partialTokenTransaction, signingOperators, keyshareInfo, expectedWithdrawBondSats, expectedWithdrawRelativeBlockLocktime, expectedThreshold) {
|
|
777
1202
|
if (finalTokenTransaction.network !== partialTokenTransaction.network) {
|
|
778
1203
|
throw new InternalValidationError(
|
|
779
1204
|
"Network mismatch in response token transaction",
|
|
@@ -930,7 +1355,7 @@ function validateTokenTransaction(finalTokenTransaction, partialTokenTransaction
|
|
|
930
1355
|
}
|
|
931
1356
|
);
|
|
932
1357
|
}
|
|
933
|
-
if (!areByteArraysEqual(
|
|
1358
|
+
if (finalOutput.tokenPublicKey !== void 0 && partialOutput.tokenPublicKey !== void 0 && !areByteArraysEqual(
|
|
934
1359
|
finalOutput.tokenPublicKey,
|
|
935
1360
|
partialOutput.tokenPublicKey
|
|
936
1361
|
)) {
|
|
@@ -938,8 +1363,8 @@ function validateTokenTransaction(finalTokenTransaction, partialTokenTransaction
|
|
|
938
1363
|
"Token public key mismatch in token output",
|
|
939
1364
|
{
|
|
940
1365
|
outputIndex: i,
|
|
941
|
-
value: finalOutput.tokenPublicKey
|
|
942
|
-
expected: partialOutput.tokenPublicKey
|
|
1366
|
+
value: finalOutput.tokenPublicKey?.toString(),
|
|
1367
|
+
expected: partialOutput.tokenPublicKey?.toString()
|
|
943
1368
|
}
|
|
944
1369
|
);
|
|
945
1370
|
}
|
|
@@ -1017,222 +1442,264 @@ function validateTokenTransaction(finalTokenTransaction, partialTokenTransaction
|
|
|
1017
1442
|
}
|
|
1018
1443
|
}
|
|
1019
1444
|
}
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1445
|
+
function validateTokenTransaction(finalTokenTransaction, partialTokenTransaction, signingOperators, keyshareInfo, expectedWithdrawBondSats, expectedWithdrawRelativeBlockLocktime, expectedThreshold) {
|
|
1446
|
+
if (finalTokenTransaction.network !== partialTokenTransaction.network) {
|
|
1447
|
+
throw new InternalValidationError(
|
|
1448
|
+
"Network mismatch in response token transaction",
|
|
1449
|
+
{
|
|
1450
|
+
value: finalTokenTransaction.network,
|
|
1451
|
+
expected: partialTokenTransaction.network
|
|
1452
|
+
}
|
|
1453
|
+
);
|
|
1454
|
+
}
|
|
1455
|
+
if (!finalTokenTransaction.tokenInputs) {
|
|
1456
|
+
throw new InternalValidationError(
|
|
1457
|
+
"Token inputs missing in final transaction",
|
|
1458
|
+
{
|
|
1459
|
+
value: finalTokenTransaction
|
|
1460
|
+
}
|
|
1461
|
+
);
|
|
1462
|
+
}
|
|
1463
|
+
if (!partialTokenTransaction.tokenInputs) {
|
|
1464
|
+
throw new InternalValidationError(
|
|
1465
|
+
"Token inputs missing in partial transaction",
|
|
1466
|
+
{
|
|
1467
|
+
value: partialTokenTransaction
|
|
1468
|
+
}
|
|
1469
|
+
);
|
|
1470
|
+
}
|
|
1471
|
+
if (finalTokenTransaction.tokenInputs.$case !== partialTokenTransaction.tokenInputs.$case) {
|
|
1472
|
+
throw new InternalValidationError(
|
|
1473
|
+
`Transaction type mismatch: final transaction has ${finalTokenTransaction.tokenInputs.$case}, partial transaction has ${partialTokenTransaction.tokenInputs.$case}`,
|
|
1474
|
+
{
|
|
1475
|
+
value: finalTokenTransaction.tokenInputs.$case,
|
|
1476
|
+
expected: partialTokenTransaction.tokenInputs.$case
|
|
1477
|
+
}
|
|
1478
|
+
);
|
|
1479
|
+
}
|
|
1480
|
+
if (finalTokenTransaction.sparkOperatorIdentityPublicKeys.length !== partialTokenTransaction.sparkOperatorIdentityPublicKeys.length) {
|
|
1481
|
+
throw new InternalValidationError(
|
|
1482
|
+
"Spark operator identity public keys count mismatch",
|
|
1483
|
+
{
|
|
1484
|
+
value: finalTokenTransaction.sparkOperatorIdentityPublicKeys.length,
|
|
1485
|
+
expected: partialTokenTransaction.sparkOperatorIdentityPublicKeys.length
|
|
1486
|
+
}
|
|
1487
|
+
);
|
|
1488
|
+
}
|
|
1489
|
+
if (partialTokenTransaction.tokenInputs.$case === "mintInput" && finalTokenTransaction.tokenInputs.$case === "mintInput") {
|
|
1490
|
+
const finalMintInput = finalTokenTransaction.tokenInputs.mintInput;
|
|
1491
|
+
const partialMintInput = partialTokenTransaction.tokenInputs.mintInput;
|
|
1492
|
+
if (!areByteArraysEqual(
|
|
1493
|
+
finalMintInput.issuerPublicKey,
|
|
1494
|
+
partialMintInput.issuerPublicKey
|
|
1495
|
+
)) {
|
|
1496
|
+
throw new InternalValidationError(
|
|
1497
|
+
"Issuer public key mismatch in mint input",
|
|
1498
|
+
{
|
|
1499
|
+
value: finalMintInput.issuerPublicKey.toString(),
|
|
1500
|
+
expected: partialMintInput.issuerPublicKey.toString()
|
|
1501
|
+
}
|
|
1502
|
+
);
|
|
1049
1503
|
}
|
|
1050
|
-
|
|
1051
|
-
|
|
1504
|
+
} else if (partialTokenTransaction.tokenInputs.$case === "transferInput" && finalTokenTransaction.tokenInputs.$case === "transferInput") {
|
|
1505
|
+
const finalTransferInput = finalTokenTransaction.tokenInputs.transferInput;
|
|
1506
|
+
const partialTransferInput = partialTokenTransaction.tokenInputs.transferInput;
|
|
1507
|
+
if (finalTransferInput.outputsToSpend.length !== partialTransferInput.outputsToSpend.length) {
|
|
1508
|
+
throw new InternalValidationError(
|
|
1509
|
+
"Outputs to spend count mismatch in transfer input",
|
|
1510
|
+
{
|
|
1511
|
+
value: finalTransferInput.outputsToSpend.length,
|
|
1512
|
+
expected: partialTransferInput.outputsToSpend.length
|
|
1513
|
+
}
|
|
1514
|
+
);
|
|
1052
1515
|
}
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
case 1: {
|
|
1063
|
-
if (tag !== 10) {
|
|
1064
|
-
break;
|
|
1516
|
+
for (let i = 0; i < finalTransferInput.outputsToSpend.length; i++) {
|
|
1517
|
+
const finalOutput = finalTransferInput.outputsToSpend[i];
|
|
1518
|
+
const partialOutput = partialTransferInput.outputsToSpend[i];
|
|
1519
|
+
if (!finalOutput) {
|
|
1520
|
+
throw new InternalValidationError(
|
|
1521
|
+
"Token output to spend missing in final transaction",
|
|
1522
|
+
{
|
|
1523
|
+
outputIndex: i,
|
|
1524
|
+
value: finalOutput
|
|
1065
1525
|
}
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1526
|
+
);
|
|
1527
|
+
}
|
|
1528
|
+
if (!partialOutput) {
|
|
1529
|
+
throw new InternalValidationError(
|
|
1530
|
+
"Token output to spend missing in partial transaction",
|
|
1531
|
+
{
|
|
1532
|
+
outputIndex: i,
|
|
1533
|
+
value: partialOutput
|
|
1072
1534
|
}
|
|
1073
|
-
|
|
1074
|
-
continue;
|
|
1075
|
-
}
|
|
1535
|
+
);
|
|
1076
1536
|
}
|
|
1077
|
-
if ((
|
|
1078
|
-
|
|
1537
|
+
if (!areByteArraysEqual(
|
|
1538
|
+
finalOutput.prevTokenTransactionHash,
|
|
1539
|
+
partialOutput.prevTokenTransactionHash
|
|
1540
|
+
)) {
|
|
1541
|
+
throw new InternalValidationError(
|
|
1542
|
+
"Previous token transaction hash mismatch in transfer input",
|
|
1543
|
+
{
|
|
1544
|
+
outputIndex: i,
|
|
1545
|
+
value: finalOutput.prevTokenTransactionHash.toString(),
|
|
1546
|
+
expected: partialOutput.prevTokenTransactionHash.toString()
|
|
1547
|
+
}
|
|
1548
|
+
);
|
|
1549
|
+
}
|
|
1550
|
+
if (finalOutput.prevTokenTransactionVout !== partialOutput.prevTokenTransactionVout) {
|
|
1551
|
+
throw new InternalValidationError(
|
|
1552
|
+
"Previous token transaction vout mismatch in transfer input",
|
|
1553
|
+
{
|
|
1554
|
+
outputIndex: i,
|
|
1555
|
+
value: finalOutput.prevTokenTransactionVout,
|
|
1556
|
+
expected: partialOutput.prevTokenTransactionVout
|
|
1557
|
+
}
|
|
1558
|
+
);
|
|
1079
1559
|
}
|
|
1080
|
-
reader.skip(tag & 7);
|
|
1081
|
-
}
|
|
1082
|
-
return message;
|
|
1083
|
-
},
|
|
1084
|
-
fromJSON(object) {
|
|
1085
|
-
return {
|
|
1086
|
-
identityPublicKey: isSet(object.identityPublicKey) ? bytesFromBase64(object.identityPublicKey) : new Uint8Array(0),
|
|
1087
|
-
paymentIntentFields: isSet(object.paymentIntentFields) ? PaymentIntentFields.fromJSON(object.paymentIntentFields) : void 0
|
|
1088
|
-
};
|
|
1089
|
-
},
|
|
1090
|
-
toJSON(message) {
|
|
1091
|
-
const obj = {};
|
|
1092
|
-
if (message.identityPublicKey.length !== 0) {
|
|
1093
|
-
obj.identityPublicKey = base64FromBytes(message.identityPublicKey);
|
|
1094
|
-
}
|
|
1095
|
-
if (message.paymentIntentFields !== void 0) {
|
|
1096
|
-
obj.paymentIntentFields = PaymentIntentFields.toJSON(message.paymentIntentFields);
|
|
1097
1560
|
}
|
|
1098
|
-
return obj;
|
|
1099
|
-
},
|
|
1100
|
-
create(base) {
|
|
1101
|
-
return SparkAddress.fromPartial(base ?? {});
|
|
1102
|
-
},
|
|
1103
|
-
fromPartial(object) {
|
|
1104
|
-
const message = createBaseSparkAddress();
|
|
1105
|
-
message.identityPublicKey = object.identityPublicKey ?? new Uint8Array(0);
|
|
1106
|
-
message.paymentIntentFields = object.paymentIntentFields !== void 0 && object.paymentIntentFields !== null ? PaymentIntentFields.fromPartial(object.paymentIntentFields) : void 0;
|
|
1107
|
-
return message;
|
|
1108
1561
|
}
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
if (
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1562
|
+
if (finalTokenTransaction.tokenOutputs.length !== partialTokenTransaction.tokenOutputs.length) {
|
|
1563
|
+
throw new InternalValidationError("Token outputs count mismatch", {
|
|
1564
|
+
value: finalTokenTransaction.tokenOutputs.length,
|
|
1565
|
+
expected: partialTokenTransaction.tokenOutputs.length
|
|
1566
|
+
});
|
|
1567
|
+
}
|
|
1568
|
+
for (let i = 0; i < finalTokenTransaction.tokenOutputs.length; i++) {
|
|
1569
|
+
const finalOutput = finalTokenTransaction.tokenOutputs[i];
|
|
1570
|
+
const partialOutput = partialTokenTransaction.tokenOutputs[i];
|
|
1571
|
+
if (!finalOutput) {
|
|
1572
|
+
throw new InternalValidationError(
|
|
1573
|
+
"Token output missing in final transaction",
|
|
1574
|
+
{
|
|
1575
|
+
outputIndex: i,
|
|
1576
|
+
value: finalOutput
|
|
1577
|
+
}
|
|
1578
|
+
);
|
|
1123
1579
|
}
|
|
1124
|
-
if (
|
|
1125
|
-
|
|
1580
|
+
if (!partialOutput) {
|
|
1581
|
+
throw new InternalValidationError(
|
|
1582
|
+
"Token output missing in partial transaction",
|
|
1583
|
+
{
|
|
1584
|
+
outputIndex: i,
|
|
1585
|
+
value: partialOutput
|
|
1586
|
+
}
|
|
1587
|
+
);
|
|
1126
1588
|
}
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
if (tag !== 10) {
|
|
1138
|
-
break;
|
|
1139
|
-
}
|
|
1140
|
-
message.id = reader.bytes();
|
|
1141
|
-
continue;
|
|
1589
|
+
if (!areByteArraysEqual(
|
|
1590
|
+
finalOutput.ownerPublicKey,
|
|
1591
|
+
partialOutput.ownerPublicKey
|
|
1592
|
+
)) {
|
|
1593
|
+
throw new InternalValidationError(
|
|
1594
|
+
"Owner public key mismatch in token output",
|
|
1595
|
+
{
|
|
1596
|
+
outputIndex: i,
|
|
1597
|
+
value: finalOutput.ownerPublicKey.toString(),
|
|
1598
|
+
expected: partialOutput.ownerPublicKey.toString()
|
|
1142
1599
|
}
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1600
|
+
);
|
|
1601
|
+
}
|
|
1602
|
+
if (finalOutput.tokenPublicKey !== void 0 && partialOutput.tokenPublicKey !== void 0 && !areByteArraysEqual(
|
|
1603
|
+
finalOutput.tokenPublicKey,
|
|
1604
|
+
partialOutput.tokenPublicKey
|
|
1605
|
+
)) {
|
|
1606
|
+
throw new InternalValidationError(
|
|
1607
|
+
"Token public key mismatch in token output",
|
|
1608
|
+
{
|
|
1609
|
+
outputIndex: i,
|
|
1610
|
+
value: finalOutput.tokenPublicKey.toString(),
|
|
1611
|
+
expected: partialOutput.tokenPublicKey.toString()
|
|
1149
1612
|
}
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1613
|
+
);
|
|
1614
|
+
}
|
|
1615
|
+
if (!areByteArraysEqual(finalOutput.tokenAmount, partialOutput.tokenAmount)) {
|
|
1616
|
+
throw new InternalValidationError(
|
|
1617
|
+
"Token amount mismatch in token output",
|
|
1618
|
+
{
|
|
1619
|
+
outputIndex: i,
|
|
1620
|
+
value: finalOutput.tokenAmount.toString(),
|
|
1621
|
+
expected: partialOutput.tokenAmount.toString()
|
|
1156
1622
|
}
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1623
|
+
);
|
|
1624
|
+
}
|
|
1625
|
+
if (finalOutput.withdrawBondSats !== void 0) {
|
|
1626
|
+
if (finalOutput.withdrawBondSats !== expectedWithdrawBondSats) {
|
|
1627
|
+
throw new InternalValidationError(
|
|
1628
|
+
"Withdraw bond sats mismatch in token output",
|
|
1629
|
+
{
|
|
1630
|
+
outputIndex: i,
|
|
1631
|
+
value: finalOutput.withdrawBondSats,
|
|
1632
|
+
expected: expectedWithdrawBondSats
|
|
1160
1633
|
}
|
|
1161
|
-
|
|
1162
|
-
continue;
|
|
1163
|
-
}
|
|
1164
|
-
}
|
|
1165
|
-
if ((tag & 7) === 4 || tag === 0) {
|
|
1166
|
-
break;
|
|
1634
|
+
);
|
|
1167
1635
|
}
|
|
1168
|
-
reader.skip(tag & 7);
|
|
1169
|
-
}
|
|
1170
|
-
return message;
|
|
1171
|
-
},
|
|
1172
|
-
fromJSON(object) {
|
|
1173
|
-
return {
|
|
1174
|
-
id: isSet(object.id) ? bytesFromBase64(object.id) : new Uint8Array(0),
|
|
1175
|
-
assetIdentifier: isSet(object.assetIdentifier) ? bytesFromBase64(object.assetIdentifier) : void 0,
|
|
1176
|
-
assetAmount: isSet(object.assetAmount) ? bytesFromBase64(object.assetAmount) : new Uint8Array(0),
|
|
1177
|
-
memo: isSet(object.memo) ? globalThis.String(object.memo) : void 0
|
|
1178
|
-
};
|
|
1179
|
-
},
|
|
1180
|
-
toJSON(message) {
|
|
1181
|
-
const obj = {};
|
|
1182
|
-
if (message.id.length !== 0) {
|
|
1183
|
-
obj.id = base64FromBytes(message.id);
|
|
1184
|
-
}
|
|
1185
|
-
if (message.assetIdentifier !== void 0) {
|
|
1186
|
-
obj.assetIdentifier = base64FromBytes(message.assetIdentifier);
|
|
1187
1636
|
}
|
|
1188
|
-
if (
|
|
1189
|
-
|
|
1637
|
+
if (finalOutput.withdrawRelativeBlockLocktime !== void 0) {
|
|
1638
|
+
if (finalOutput.withdrawRelativeBlockLocktime !== expectedWithdrawRelativeBlockLocktime) {
|
|
1639
|
+
throw new InternalValidationError(
|
|
1640
|
+
"Withdraw relative block locktime mismatch in token output",
|
|
1641
|
+
{
|
|
1642
|
+
outputIndex: i,
|
|
1643
|
+
value: finalOutput.withdrawRelativeBlockLocktime,
|
|
1644
|
+
expected: expectedWithdrawRelativeBlockLocktime
|
|
1645
|
+
}
|
|
1646
|
+
);
|
|
1647
|
+
}
|
|
1190
1648
|
}
|
|
1191
|
-
if (
|
|
1192
|
-
|
|
1649
|
+
if (keyshareInfo.threshold !== expectedThreshold) {
|
|
1650
|
+
throw new InternalValidationError(
|
|
1651
|
+
"Threshold mismatch: expected " + expectedThreshold + " but got " + keyshareInfo.threshold,
|
|
1652
|
+
{
|
|
1653
|
+
field: "threshold",
|
|
1654
|
+
value: keyshareInfo.threshold,
|
|
1655
|
+
expected: expectedThreshold
|
|
1656
|
+
}
|
|
1657
|
+
);
|
|
1193
1658
|
}
|
|
1194
|
-
return obj;
|
|
1195
|
-
},
|
|
1196
|
-
create(base) {
|
|
1197
|
-
return PaymentIntentFields.fromPartial(base ?? {});
|
|
1198
|
-
},
|
|
1199
|
-
fromPartial(object) {
|
|
1200
|
-
const message = createBasePaymentIntentFields();
|
|
1201
|
-
message.id = object.id ?? new Uint8Array(0);
|
|
1202
|
-
message.assetIdentifier = object.assetIdentifier ?? void 0;
|
|
1203
|
-
message.assetAmount = object.assetAmount ?? new Uint8Array(0);
|
|
1204
|
-
message.memo = object.memo ?? void 0;
|
|
1205
|
-
return message;
|
|
1206
1659
|
}
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1660
|
+
if (keyshareInfo.ownerIdentifiers.length !== Object.keys(signingOperators).length) {
|
|
1661
|
+
throw new InternalValidationError(
|
|
1662
|
+
`Keyshare operator count (${keyshareInfo.ownerIdentifiers.length}) does not match signing operator count (${Object.keys(signingOperators).length})`,
|
|
1663
|
+
{
|
|
1664
|
+
keyshareInfo: keyshareInfo.ownerIdentifiers.length,
|
|
1665
|
+
signingOperators: Object.keys(signingOperators).length
|
|
1666
|
+
}
|
|
1667
|
+
);
|
|
1668
|
+
}
|
|
1669
|
+
if (hasDuplicates(keyshareInfo.ownerIdentifiers)) {
|
|
1670
|
+
throw new InternalValidationError(
|
|
1671
|
+
"Duplicate ownerIdentifiers found in keyshareInfo",
|
|
1672
|
+
{
|
|
1673
|
+
keyshareInfo: keyshareInfo.ownerIdentifiers
|
|
1674
|
+
}
|
|
1675
|
+
);
|
|
1676
|
+
}
|
|
1677
|
+
for (const identifier of keyshareInfo.ownerIdentifiers) {
|
|
1678
|
+
if (!signingOperators[identifier]) {
|
|
1679
|
+
throw new InternalValidationError(
|
|
1680
|
+
`Keyshare operator ${identifier} not found in signing operator list`,
|
|
1681
|
+
{
|
|
1682
|
+
keyshareInfo: identifier,
|
|
1683
|
+
signingOperators: Object.keys(signingOperators)
|
|
1684
|
+
}
|
|
1685
|
+
);
|
|
1216
1686
|
}
|
|
1217
|
-
return arr;
|
|
1218
1687
|
}
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
} else {
|
|
1224
|
-
const bin = [];
|
|
1225
|
-
arr.forEach((byte) => {
|
|
1226
|
-
bin.push(globalThis.String.fromCharCode(byte));
|
|
1688
|
+
if (finalTokenTransaction.clientCreatedTimestamp.getTime() !== partialTokenTransaction.clientCreatedTimestamp.getTime()) {
|
|
1689
|
+
throw new InternalValidationError("Client created timestamp mismatch", {
|
|
1690
|
+
value: finalTokenTransaction.clientCreatedTimestamp,
|
|
1691
|
+
expected: partialTokenTransaction.clientCreatedTimestamp
|
|
1227
1692
|
});
|
|
1228
|
-
return globalThis.btoa(bin.join(""));
|
|
1229
1693
|
}
|
|
1230
1694
|
}
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1695
|
+
|
|
1696
|
+
// src/services/token-transactions.ts
|
|
1697
|
+
var import_utils7 = require("@noble/hashes/utils");
|
|
1234
1698
|
|
|
1235
1699
|
// src/address/address.ts
|
|
1700
|
+
var import_secp256k1 = require("@noble/curves/secp256k1");
|
|
1701
|
+
var import_utils3 = require("@noble/hashes/utils");
|
|
1702
|
+
var import_base2 = require("@scure/base");
|
|
1236
1703
|
var import_uuidv7 = require("uuidv7");
|
|
1237
1704
|
var import_utils4 = require("@noble/curves/abstract/utils");
|
|
1238
1705
|
var AddressNetwork = {
|
|
@@ -1603,7 +2070,8 @@ var TokenTransactionService = class {
|
|
|
1603
2070
|
},
|
|
1604
2071
|
tokenOutputs,
|
|
1605
2072
|
sparkOperatorIdentityPublicKeys: this.collectOperatorIdentityPublicKeys(),
|
|
1606
|
-
expiryTime: void 0
|
|
2073
|
+
expiryTime: void 0,
|
|
2074
|
+
clientCreatedTimestamp: /* @__PURE__ */ new Date()
|
|
1607
2075
|
};
|
|
1608
2076
|
}
|
|
1609
2077
|
collectOperatorIdentityPublicKeys() {
|
|
@@ -1812,7 +2280,7 @@ var TokenTransactionService = class {
|
|
|
1812
2280
|
if (!startResponse.keyshareInfo) {
|
|
1813
2281
|
throw new Error("Keyshare info missing in start response");
|
|
1814
2282
|
}
|
|
1815
|
-
|
|
2283
|
+
validateTokenTransactionV0(
|
|
1816
2284
|
startResponse.finalTokenTransaction,
|
|
1817
2285
|
tokenTransaction,
|
|
1818
2286
|
signingOperators,
|
|
@@ -2063,7 +2531,26 @@ var TokenTransactionService = class {
|
|
|
2063
2531
|
);
|
|
2064
2532
|
}
|
|
2065
2533
|
}
|
|
2066
|
-
async fetchOwnedTokenOutputs(
|
|
2534
|
+
async fetchOwnedTokenOutputs(params) {
|
|
2535
|
+
if (this.config.getTokenTransactionVersion() === "V0") {
|
|
2536
|
+
return this.fetchOwnedTokenOutputsV0(params);
|
|
2537
|
+
} else {
|
|
2538
|
+
return this.fetchOwnedTokenOutputsV1(params);
|
|
2539
|
+
}
|
|
2540
|
+
}
|
|
2541
|
+
async queryTokenTransactions(params) {
|
|
2542
|
+
if (this.config.getTokenTransactionVersion() === "V0") {
|
|
2543
|
+
return this.queryTokenTransactionsV0(params);
|
|
2544
|
+
} else {
|
|
2545
|
+
return this.queryTokenTransactionsV1(params);
|
|
2546
|
+
}
|
|
2547
|
+
}
|
|
2548
|
+
async fetchOwnedTokenOutputsV0(params) {
|
|
2549
|
+
const {
|
|
2550
|
+
ownerPublicKeys,
|
|
2551
|
+
issuerPublicKeys: tokenPublicKeys = [],
|
|
2552
|
+
tokenIdentifiers = []
|
|
2553
|
+
} = params;
|
|
2067
2554
|
const sparkClient = await this.connectionManager.createSparkClient(
|
|
2068
2555
|
this.config.getCoordinatorAddress()
|
|
2069
2556
|
);
|
|
@@ -2071,6 +2558,7 @@ var TokenTransactionService = class {
|
|
|
2071
2558
|
const result = await sparkClient.query_token_outputs({
|
|
2072
2559
|
ownerPublicKeys,
|
|
2073
2560
|
tokenPublicKeys,
|
|
2561
|
+
tokenIdentifiers,
|
|
2074
2562
|
network: this.config.getNetworkProto()
|
|
2075
2563
|
});
|
|
2076
2564
|
return result.outputsWithPreviousTransactionData;
|
|
@@ -2078,7 +2566,7 @@ var TokenTransactionService = class {
|
|
|
2078
2566
|
throw new NetworkError(
|
|
2079
2567
|
"Failed to fetch owned token outputs",
|
|
2080
2568
|
{
|
|
2081
|
-
operation: "query_token_outputs",
|
|
2569
|
+
operation: "spark.query_token_outputs",
|
|
2082
2570
|
errorCount: 1,
|
|
2083
2571
|
errors: error instanceof Error ? error.message : String(error)
|
|
2084
2572
|
},
|
|
@@ -2086,11 +2574,127 @@ var TokenTransactionService = class {
|
|
|
2086
2574
|
);
|
|
2087
2575
|
}
|
|
2088
2576
|
}
|
|
2089
|
-
async
|
|
2090
|
-
const
|
|
2091
|
-
|
|
2092
|
-
[]
|
|
2577
|
+
async fetchOwnedTokenOutputsV1(params) {
|
|
2578
|
+
const {
|
|
2579
|
+
ownerPublicKeys,
|
|
2580
|
+
issuerPublicKeys = [],
|
|
2581
|
+
tokenIdentifiers = []
|
|
2582
|
+
} = params;
|
|
2583
|
+
const tokenClient = await this.connectionManager.createSparkTokenClient(
|
|
2584
|
+
this.config.getCoordinatorAddress()
|
|
2585
|
+
);
|
|
2586
|
+
try {
|
|
2587
|
+
const result = await tokenClient.query_token_outputs({
|
|
2588
|
+
ownerPublicKeys,
|
|
2589
|
+
issuerPublicKeys,
|
|
2590
|
+
tokenIdentifiers,
|
|
2591
|
+
network: this.config.getNetworkProto()
|
|
2592
|
+
});
|
|
2593
|
+
return result.outputsWithPreviousTransactionData;
|
|
2594
|
+
} catch (error) {
|
|
2595
|
+
throw new NetworkError(
|
|
2596
|
+
"Failed to fetch owned token outputs",
|
|
2597
|
+
{
|
|
2598
|
+
operation: "spark_token.query_token_outputs",
|
|
2599
|
+
errorCount: 1,
|
|
2600
|
+
errors: error instanceof Error ? error.message : String(error)
|
|
2601
|
+
},
|
|
2602
|
+
error
|
|
2603
|
+
);
|
|
2604
|
+
}
|
|
2605
|
+
}
|
|
2606
|
+
async queryTokenTransactionsV0(params) {
|
|
2607
|
+
const {
|
|
2608
|
+
ownerPublicKeys,
|
|
2609
|
+
issuerPublicKeys,
|
|
2610
|
+
tokenTransactionHashes,
|
|
2611
|
+
tokenIdentifiers,
|
|
2612
|
+
outputIds
|
|
2613
|
+
} = params;
|
|
2614
|
+
const sparkClient = await this.connectionManager.createSparkClient(
|
|
2615
|
+
this.config.getCoordinatorAddress()
|
|
2616
|
+
);
|
|
2617
|
+
let queryParams = {
|
|
2618
|
+
tokenPublicKeys: issuerPublicKeys?.map(import_utils7.hexToBytes),
|
|
2619
|
+
ownerPublicKeys: ownerPublicKeys?.map(import_utils7.hexToBytes),
|
|
2620
|
+
tokenIdentifiers: tokenIdentifiers?.map(import_utils7.hexToBytes),
|
|
2621
|
+
tokenTransactionHashes: tokenTransactionHashes?.map(import_utils7.hexToBytes),
|
|
2622
|
+
outputIds: outputIds || [],
|
|
2623
|
+
limit: 100,
|
|
2624
|
+
offset: 0
|
|
2625
|
+
};
|
|
2626
|
+
try {
|
|
2627
|
+
const response = await sparkClient.query_token_transactions(queryParams);
|
|
2628
|
+
return response.tokenTransactionsWithStatus.map((tx) => {
|
|
2629
|
+
const v1TokenTransaction = {
|
|
2630
|
+
version: 1,
|
|
2631
|
+
network: tx.tokenTransaction.network,
|
|
2632
|
+
tokenInputs: tx.tokenTransaction.tokenInputs,
|
|
2633
|
+
tokenOutputs: tx.tokenTransaction.tokenOutputs,
|
|
2634
|
+
sparkOperatorIdentityPublicKeys: tx.tokenTransaction.sparkOperatorIdentityPublicKeys,
|
|
2635
|
+
expiryTime: void 0,
|
|
2636
|
+
// V0 doesn't have expiry time
|
|
2637
|
+
clientCreatedTimestamp: tx.tokenTransaction?.tokenInputs?.$case === "mintInput" ? new Date(
|
|
2638
|
+
tx.tokenTransaction.tokenInputs.mintInput.issuerProvidedTimestamp * 1e3
|
|
2639
|
+
) : /* @__PURE__ */ new Date()
|
|
2640
|
+
};
|
|
2641
|
+
return {
|
|
2642
|
+
tokenTransaction: v1TokenTransaction,
|
|
2643
|
+
status: tx.status,
|
|
2644
|
+
confirmationMetadata: tx.confirmationMetadata
|
|
2645
|
+
};
|
|
2646
|
+
});
|
|
2647
|
+
} catch (error) {
|
|
2648
|
+
throw new NetworkError(
|
|
2649
|
+
"Failed to query token transactions",
|
|
2650
|
+
{
|
|
2651
|
+
operation: "spark.query_token_transactions",
|
|
2652
|
+
errorCount: 1,
|
|
2653
|
+
errors: error instanceof Error ? error.message : String(error)
|
|
2654
|
+
},
|
|
2655
|
+
error
|
|
2656
|
+
);
|
|
2657
|
+
}
|
|
2658
|
+
}
|
|
2659
|
+
async queryTokenTransactionsV1(params) {
|
|
2660
|
+
const {
|
|
2661
|
+
ownerPublicKeys,
|
|
2662
|
+
issuerPublicKeys,
|
|
2663
|
+
tokenTransactionHashes,
|
|
2664
|
+
tokenIdentifiers,
|
|
2665
|
+
outputIds
|
|
2666
|
+
} = params;
|
|
2667
|
+
const tokenClient = await this.connectionManager.createSparkTokenClient(
|
|
2668
|
+
this.config.getCoordinatorAddress()
|
|
2093
2669
|
);
|
|
2670
|
+
let queryParams = {
|
|
2671
|
+
issuerPublicKeys: issuerPublicKeys?.map(import_utils7.hexToBytes),
|
|
2672
|
+
ownerPublicKeys: ownerPublicKeys?.map(import_utils7.hexToBytes),
|
|
2673
|
+
tokenIdentifiers: tokenIdentifiers?.map(import_utils7.hexToBytes),
|
|
2674
|
+
tokenTransactionHashes: tokenTransactionHashes?.map(import_utils7.hexToBytes),
|
|
2675
|
+
outputIds: outputIds || [],
|
|
2676
|
+
limit: 100,
|
|
2677
|
+
offset: 0
|
|
2678
|
+
};
|
|
2679
|
+
try {
|
|
2680
|
+
const response = await tokenClient.query_token_transactions(queryParams);
|
|
2681
|
+
return response.tokenTransactionsWithStatus;
|
|
2682
|
+
} catch (error) {
|
|
2683
|
+
throw new NetworkError(
|
|
2684
|
+
"Failed to query token transactions",
|
|
2685
|
+
{
|
|
2686
|
+
operation: "spark_token.query_token_transactions",
|
|
2687
|
+
errorCount: 1,
|
|
2688
|
+
errors: error instanceof Error ? error.message : String(error)
|
|
2689
|
+
},
|
|
2690
|
+
error
|
|
2691
|
+
);
|
|
2692
|
+
}
|
|
2693
|
+
}
|
|
2694
|
+
async syncTokenOutputs(tokenOutputs) {
|
|
2695
|
+
const unsortedTokenOutputs = await this.fetchOwnedTokenOutputs({
|
|
2696
|
+
ownerPublicKeys: await this.config.signer.getTrackedPublicKeys()
|
|
2697
|
+
});
|
|
2094
2698
|
unsortedTokenOutputs.forEach((output) => {
|
|
2095
2699
|
const tokenKey = (0, import_utils6.bytesToHex)(output.output.tokenPublicKey);
|
|
2096
2700
|
const index = output.previousTransactionVout;
|