@chainvue/verus-sdk 0.4.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.
Files changed (64) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +75 -0
  3. package/dist/VerusSDK.d.ts +59 -0
  4. package/dist/VerusSDK.d.ts.map +1 -0
  5. package/dist/VerusSDK.js +170 -0
  6. package/dist/VerusSDK.js.map +1 -0
  7. package/dist/address/index.d.ts +16 -0
  8. package/dist/address/index.d.ts.map +1 -0
  9. package/dist/address/index.js +33 -0
  10. package/dist/address/index.js.map +1 -0
  11. package/dist/bundle.js +34129 -0
  12. package/dist/constants/index.d.ts +51 -0
  13. package/dist/constants/index.d.ts.map +1 -0
  14. package/dist/constants/index.js +53 -0
  15. package/dist/constants/index.js.map +1 -0
  16. package/dist/currency/classify.d.ts +14 -0
  17. package/dist/currency/classify.d.ts.map +1 -0
  18. package/dist/currency/classify.js +32 -0
  19. package/dist/currency/classify.js.map +1 -0
  20. package/dist/currency/index.d.ts +22 -0
  21. package/dist/currency/index.d.ts.map +1 -0
  22. package/dist/currency/index.js +87 -0
  23. package/dist/currency/index.js.map +1 -0
  24. package/dist/errors.d.ts +37 -0
  25. package/dist/errors.d.ts.map +1 -0
  26. package/dist/errors.js +69 -0
  27. package/dist/errors.js.map +1 -0
  28. package/dist/identity/index.d.ts +129 -0
  29. package/dist/identity/index.d.ts.map +1 -0
  30. package/dist/identity/index.js +691 -0
  31. package/dist/identity/index.js.map +1 -0
  32. package/dist/index.d.ts +24 -0
  33. package/dist/index.d.ts.map +1 -0
  34. package/dist/index.js +96 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/keys/index.d.ts +48 -0
  37. package/dist/keys/index.d.ts.map +1 -0
  38. package/dist/keys/index.js +169 -0
  39. package/dist/keys/index.js.map +1 -0
  40. package/dist/message/index.d.ts +18 -0
  41. package/dist/message/index.d.ts.map +1 -0
  42. package/dist/message/index.js +61 -0
  43. package/dist/message/index.js.map +1 -0
  44. package/dist/signing/index.d.ts +53 -0
  45. package/dist/signing/index.d.ts.map +1 -0
  46. package/dist/signing/index.js +100 -0
  47. package/dist/signing/index.js.map +1 -0
  48. package/dist/transfer/index.d.ts +37 -0
  49. package/dist/transfer/index.d.ts.map +1 -0
  50. package/dist/transfer/index.js +275 -0
  51. package/dist/transfer/index.js.map +1 -0
  52. package/dist/types/index.d.ts +359 -0
  53. package/dist/types/index.d.ts.map +1 -0
  54. package/dist/types/index.js +6 -0
  55. package/dist/types/index.js.map +1 -0
  56. package/dist/utils/index.d.ts +48 -0
  57. package/dist/utils/index.d.ts.map +1 -0
  58. package/dist/utils/index.js +141 -0
  59. package/dist/utils/index.js.map +1 -0
  60. package/dist/utxo/index.d.ts +21 -0
  61. package/dist/utxo/index.d.ts.map +1 -0
  62. package/dist/utxo/index.js +139 -0
  63. package/dist/utxo/index.js.map +1 -0
  64. package/package.json +65 -0
@@ -0,0 +1,691 @@
1
+ "use strict";
2
+ /**
3
+ * Identity transaction building utilities and workflows
4
+ *
5
+ * Handles:
6
+ * - Name commitment (Step 1 of identity creation)
7
+ * - Identity registration (Step 2)
8
+ * - Identity updates (modify, revoke, recover, lock, unlock)
9
+ * - Script/hash construction for CC outputs
10
+ */
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.nameAndParentAddrToIAddr = void 0;
16
+ exports.generateSalt = generateSalt;
17
+ exports.serializeNameReservation = serializeNameReservation;
18
+ exports.serializeAdvancedNameReservation = serializeAdvancedNameReservation;
19
+ exports.calculateCommitmentHash = calculateCommitmentHash;
20
+ exports.serializeCommitmentHash = serializeCommitmentHash;
21
+ exports.buildCommitmentScript = buildCommitmentScript;
22
+ exports.buildReservationScript = buildReservationScript;
23
+ exports.buildIdentityScript = buildIdentityScript;
24
+ exports.deriveIdentityAddress = deriveIdentityAddress;
25
+ exports.isVRSCParent = isVRSCParent;
26
+ exports.prepareNameCommitment = prepareNameCommitment;
27
+ exports.buildP2IDScript = buildP2IDScript;
28
+ exports.identityPaymentScript = identityPaymentScript;
29
+ exports.buildReferralPaymentScript = buildReferralPaymentScript;
30
+ exports.calculateRegistrationFees = calculateRegistrationFees;
31
+ exports.createIdentityObject = createIdentityObject;
32
+ exports.buildRegistrationFeeOutput = buildRegistrationFeeOutput;
33
+ exports.buildTokenChangeOutput = buildTokenChangeOutput;
34
+ exports.buildAndSignCommitment = buildAndSignCommitment;
35
+ exports.buildAndSignRegistration = buildAndSignRegistration;
36
+ exports.buildAndSignIdentityUpdate = buildAndSignIdentityUpdate;
37
+ const crypto_1 = require("crypto");
38
+ const bn_js_1 = __importDefault(require("bn.js"));
39
+ const verus_typescript_primitives_1 = require("verus-typescript-primitives");
40
+ const verus_typescript_primitives_2 = require("verus-typescript-primitives");
41
+ const verus_typescript_primitives_3 = require("verus-typescript-primitives");
42
+ Object.defineProperty(exports, "nameAndParentAddrToIAddr", { enumerable: true, get: function () { return verus_typescript_primitives_3.nameAndParentAddrToIAddr; } });
43
+ const utxo_lib_1 = require("@bitgo/utxo-lib");
44
+ const index_js_1 = require("../constants/index.js");
45
+ const index_js_2 = require("../utils/index.js");
46
+ const index_js_3 = require("../signing/index.js");
47
+ const index_js_4 = require("../utxo/index.js");
48
+ const errors_js_1 = require("../errors.js");
49
+ const index_js_5 = require("../keys/index.js");
50
+ const { createUnfundedIdentityUpdate, completeFundedIdentityUpdate } = utxo_lib_1.smarttxs;
51
+ const HASH160_BYTE_LENGTH = 20;
52
+ const HASH256_BYTE_LENGTH = 32;
53
+ /** Null identity hash (20 zero bytes) */
54
+ const NULL_ID_HASH = Buffer.alloc(HASH160_BYTE_LENGTH, 0);
55
+ /** Eval code for CAdvancedNameReservation (sub-ID) */
56
+ const EVAL_IDENTITY_ADVANCEDRESERVATION = 10;
57
+ // ─── Script / Hash Builders ────────────────────────────────────────
58
+ /**
59
+ * Generate a random 32-byte salt for name commitment
60
+ */
61
+ function generateSalt() {
62
+ return (0, crypto_1.randomBytes)(HASH256_BYTE_LENGTH);
63
+ }
64
+ /**
65
+ * Serialize a CNameReservation (for VRSC-parent identities)
66
+ */
67
+ function serializeNameReservation(name, referralHash, salt) {
68
+ const nameBytes = Buffer.from(name, 'utf8');
69
+ const compactSize = (0, index_js_2.writeCompactSize)(nameBytes.length);
70
+ return Buffer.concat([compactSize, nameBytes, referralHash, salt]);
71
+ }
72
+ /**
73
+ * Serialize a CAdvancedNameReservation (for PBaaS-parent identities)
74
+ */
75
+ function serializeAdvancedNameReservation(version, name, parentHash, referralHash, salt) {
76
+ const nameBytes = Buffer.from(name, 'utf8');
77
+ const compactSize = (0, index_js_2.writeCompactSize)(nameBytes.length);
78
+ const versionBuf = Buffer.alloc(4);
79
+ versionBuf.writeUInt32LE(version, 0);
80
+ return Buffer.concat([versionBuf, compactSize, nameBytes, parentHash, referralHash, salt]);
81
+ }
82
+ /**
83
+ * Calculate the commitment hash from a serialized name reservation
84
+ */
85
+ function calculateCommitmentHash(serializedReservation) {
86
+ return (0, index_js_2.sha256d)(serializedReservation);
87
+ }
88
+ /**
89
+ * Serialize a CCommitmentHash
90
+ */
91
+ function serializeCommitmentHash(hash) {
92
+ const tokenOutput = new verus_typescript_primitives_1.TokenOutput({
93
+ version: new bn_js_1.default(0),
94
+ values: new verus_typescript_primitives_1.CurrencyValueMap(),
95
+ });
96
+ const tokenBuf = tokenOutput.toBuffer();
97
+ return Buffer.concat([tokenBuf, hash]);
98
+ }
99
+ /**
100
+ * Build the commitment output script
101
+ */
102
+ function buildCommitmentScript(commitmentHashBuf, controlAddress) {
103
+ const controlDest = new verus_typescript_primitives_1.TxDestination(verus_typescript_primitives_1.KeyID.fromAddress(controlAddress));
104
+ const master = new verus_typescript_primitives_1.OptCCParams({
105
+ version: new bn_js_1.default(3),
106
+ eval_code: new bn_js_1.default(verus_typescript_primitives_2.EVALS.EVAL_NONE),
107
+ m: new bn_js_1.default(1),
108
+ n: new bn_js_1.default(1),
109
+ destinations: [controlDest],
110
+ vdata: [],
111
+ });
112
+ const params = new verus_typescript_primitives_1.OptCCParams({
113
+ version: new bn_js_1.default(3),
114
+ eval_code: new bn_js_1.default(verus_typescript_primitives_2.EVALS.EVAL_IDENTITY_COMMITMENT),
115
+ m: new bn_js_1.default(1),
116
+ n: new bn_js_1.default(1),
117
+ destinations: [controlDest],
118
+ vdata: [commitmentHashBuf],
119
+ });
120
+ const script = new verus_typescript_primitives_1.SmartTransactionScript(master, params);
121
+ return script.toBuffer();
122
+ }
123
+ /**
124
+ * Build the name reservation output script
125
+ */
126
+ function buildReservationScript(newIdentityIAddress, serializedReservation, isAdvanced = false) {
127
+ const identityDest = new verus_typescript_primitives_1.TxDestination(verus_typescript_primitives_1.IdentityID.fromAddress(newIdentityIAddress));
128
+ const evalCode = isAdvanced
129
+ ? EVAL_IDENTITY_ADVANCEDRESERVATION
130
+ : verus_typescript_primitives_2.EVALS.EVAL_IDENTITY_RESERVATION;
131
+ const master = new verus_typescript_primitives_1.OptCCParams({
132
+ version: new bn_js_1.default(3),
133
+ eval_code: new bn_js_1.default(verus_typescript_primitives_2.EVALS.EVAL_NONE),
134
+ m: new bn_js_1.default(1),
135
+ n: new bn_js_1.default(1),
136
+ destinations: [identityDest],
137
+ vdata: [],
138
+ });
139
+ const params = new verus_typescript_primitives_1.OptCCParams({
140
+ version: new bn_js_1.default(3),
141
+ eval_code: new bn_js_1.default(evalCode),
142
+ m: new bn_js_1.default(1),
143
+ n: new bn_js_1.default(1),
144
+ destinations: [identityDest],
145
+ vdata: [serializedReservation],
146
+ });
147
+ const script = new verus_typescript_primitives_1.SmartTransactionScript(master, params);
148
+ return script.toBuffer();
149
+ }
150
+ /**
151
+ * Build an identity definition output script from an Identity object
152
+ */
153
+ function buildIdentityScript(identity) {
154
+ const identityScript = verus_typescript_primitives_1.IdentityScript.fromIdentity(identity);
155
+ return identityScript.toBuffer();
156
+ }
157
+ /**
158
+ * Derive the identity i-address from a name and optional parent
159
+ */
160
+ function deriveIdentityAddress(name, parentIAddress) {
161
+ return (0, verus_typescript_primitives_3.nameAndParentAddrToIAddr)(name, parentIAddress || undefined);
162
+ }
163
+ /**
164
+ * Determine if a parent is the VRSC root system
165
+ */
166
+ function isVRSCParent(parentIAddress, network = 'mainnet') {
167
+ if (!parentIAddress)
168
+ return true;
169
+ const systemId = index_js_1.NETWORK_CONFIG[network].chainId;
170
+ return parentIAddress === systemId;
171
+ }
172
+ /**
173
+ * Build the full commitment data needed for Step 1 of identity creation
174
+ */
175
+ function prepareNameCommitment(name, controlAddress, referralIAddress, parentIAddress, network = 'mainnet') {
176
+ const salt = generateSalt();
177
+ const systemId = index_js_1.NETWORK_CONFIG[network].chainId;
178
+ const referralHash = referralIAddress
179
+ ? (0, index_js_2.iAddressToHash)(referralIAddress)
180
+ : NULL_ID_HASH;
181
+ const effectiveParent = parentIAddress && parentIAddress !== systemId
182
+ ? parentIAddress
183
+ : undefined;
184
+ const identityAddress = deriveIdentityAddress(name, effectiveParent || systemId);
185
+ let serializedReservation;
186
+ if (isVRSCParent(parentIAddress, network)) {
187
+ serializedReservation = serializeNameReservation(name, referralHash, salt);
188
+ }
189
+ else {
190
+ const parentHash = parentIAddress
191
+ ? (0, index_js_2.iAddressToHash)(parentIAddress)
192
+ : NULL_ID_HASH;
193
+ serializedReservation = serializeAdvancedNameReservation(1, name, parentHash, referralHash, salt);
194
+ }
195
+ const commitmentHash = calculateCommitmentHash(serializedReservation);
196
+ const serializedCommitmentHash = serializeCommitmentHash(commitmentHash);
197
+ const commitmentScript = buildCommitmentScript(commitmentHash, controlAddress);
198
+ return {
199
+ salt,
200
+ serializedReservation,
201
+ commitmentHash,
202
+ serializedCommitmentHash,
203
+ commitmentScript,
204
+ identityAddress,
205
+ };
206
+ }
207
+ /**
208
+ * Build a P2ID output script (pay to identity)
209
+ */
210
+ function buildP2IDScript(iAddress) {
211
+ const idHash = (0, index_js_2.iAddressToHash)(iAddress);
212
+ return utxo_lib_1.script.compile([
213
+ utxo_lib_1.opcodes.OP_DUP,
214
+ utxo_lib_1.opcodes.OP_HASH160,
215
+ idHash,
216
+ utxo_lib_1.opcodes.OP_EQUALVERIFY,
217
+ utxo_lib_1.opcodes.OP_CHECKSIG,
218
+ utxo_lib_1.opcodes.OP_CHECKCRYPTOCONDITION,
219
+ ]);
220
+ }
221
+ /**
222
+ * The standard pay-to-identity output script (CC EVAL_NONE 1-of-1 to an
223
+ * IdentityID) — byte-identical to what the chain itself produces when paying
224
+ * an identity (verified against on-chain P2ID outputs). Use this for change
225
+ * or payment outputs to an i-address.
226
+ */
227
+ function identityPaymentScript(iAddress) {
228
+ return buildReferralPaymentScript(iAddress);
229
+ }
230
+ /**
231
+ * Build a CC referral payment output script
232
+ */
233
+ function buildReferralPaymentScript(iAddress) {
234
+ const identityDest = new verus_typescript_primitives_1.TxDestination(verus_typescript_primitives_1.IdentityID.fromAddress(iAddress));
235
+ // Master: EVAL_NONE outputs have empty master (no index destinations)
236
+ // This matches the daemon's MakeMofNCCScript for EVAL_NONE condition objects
237
+ const master = new verus_typescript_primitives_1.OptCCParams({
238
+ version: new bn_js_1.default(3),
239
+ eval_code: new bn_js_1.default(verus_typescript_primitives_2.EVALS.EVAL_NONE),
240
+ m: new bn_js_1.default(0),
241
+ n: new bn_js_1.default(0),
242
+ destinations: [],
243
+ vdata: [],
244
+ });
245
+ const params = new verus_typescript_primitives_1.OptCCParams({
246
+ version: new bn_js_1.default(3),
247
+ eval_code: new bn_js_1.default(verus_typescript_primitives_2.EVALS.EVAL_NONE),
248
+ m: new bn_js_1.default(1),
249
+ n: new bn_js_1.default(1),
250
+ destinations: [identityDest],
251
+ vdata: [],
252
+ });
253
+ const script = new verus_typescript_primitives_1.SmartTransactionScript(master, params);
254
+ return script.toBuffer();
255
+ }
256
+ /**
257
+ * Calculate registration fee breakdown
258
+ */
259
+ function calculateRegistrationFees(hasReferral, totalFee = index_js_1.DEFAULT_REGISTRATION_FEE, referralLevels = index_js_1.DEFAULT_REFERRAL_LEVELS) {
260
+ if (!hasReferral) {
261
+ return { issuerFee: totalFee, referralAmount: 0, totalRequired: totalFee };
262
+ }
263
+ const issuerFee = Math.floor(totalFee * (referralLevels + 1) / (referralLevels + 2));
264
+ const referralAmount = Math.floor(totalFee / (referralLevels + 2));
265
+ const totalRequired = issuerFee + referralAmount * referralLevels;
266
+ return { issuerFee, referralAmount, totalRequired };
267
+ }
268
+ /**
269
+ * Build a new Identity object for registration
270
+ */
271
+ function createIdentityObject(params) {
272
+ const primaryKeys = params.primaryAddresses.map(addr => verus_typescript_primitives_1.KeyID.fromAddress(addr));
273
+ const identity = new verus_typescript_primitives_1.Identity({
274
+ version: verus_typescript_primitives_1.Identity.VERSION_CURRENT,
275
+ flags: new bn_js_1.default(0),
276
+ min_sigs: new bn_js_1.default(params.minSigs || 1),
277
+ primary_addresses: primaryKeys,
278
+ parent: verus_typescript_primitives_1.IdentityID.fromAddress(params.parentIAddress),
279
+ system_id: verus_typescript_primitives_1.IdentityID.fromAddress(params.systemId),
280
+ name: params.name,
281
+ revocation_authority: verus_typescript_primitives_1.IdentityID.fromAddress(params.revocationAuthority),
282
+ recovery_authority: verus_typescript_primitives_1.IdentityID.fromAddress(params.recoveryAuthority),
283
+ private_addresses: [],
284
+ unlock_after: new bn_js_1.default(0),
285
+ });
286
+ return identity;
287
+ }
288
+ /**
289
+ * Build a CReserveTransfer fee output for sub-ID registration
290
+ */
291
+ function buildRegistrationFeeOutput(parentCurrencyId, feeAmount, systemId, _controlAddress) {
292
+ const destination = new verus_typescript_primitives_1.TxDestination(verus_typescript_primitives_1.KeyID.fromAddress(index_js_1.RESERVE_TRANSFER_EVAL_PKH));
293
+ const values = new verus_typescript_primitives_1.CurrencyValueMap({
294
+ value_map: new Map([[parentCurrencyId, new bn_js_1.default(feeAmount)]]),
295
+ multivalue: false,
296
+ });
297
+ const parentHash = (0, verus_typescript_primitives_3.fromBase58Check)(parentCurrencyId).hash;
298
+ const transferDest = new verus_typescript_primitives_1.TransferDestination({
299
+ type: verus_typescript_primitives_1.DEST_ID,
300
+ destination_bytes: Buffer.from(parentHash),
301
+ });
302
+ const flags = verus_typescript_primitives_1.RESERVE_TRANSFER_VALID.or(verus_typescript_primitives_1.RESERVE_TRANSFER_BURN_CHANGE_PRICE);
303
+ const resTransfer = new verus_typescript_primitives_1.ReserveTransfer({
304
+ values,
305
+ version: new bn_js_1.default(1),
306
+ flags,
307
+ fee_currency_id: systemId,
308
+ fee_amount: new bn_js_1.default(index_js_1.RESERVE_TRANSFER_FEE),
309
+ transfer_destination: transferDest,
310
+ dest_currency_id: parentCurrencyId,
311
+ });
312
+ const master = new verus_typescript_primitives_1.OptCCParams({
313
+ version: new bn_js_1.default(3),
314
+ eval_code: new bn_js_1.default(verus_typescript_primitives_2.EVALS.EVAL_NONE),
315
+ m: new bn_js_1.default(1),
316
+ n: new bn_js_1.default(1),
317
+ destinations: [destination],
318
+ vdata: [],
319
+ });
320
+ const params = new verus_typescript_primitives_1.OptCCParams({
321
+ version: new bn_js_1.default(3),
322
+ eval_code: new bn_js_1.default(verus_typescript_primitives_2.EVALS.EVAL_RESERVE_TRANSFER),
323
+ m: new bn_js_1.default(1),
324
+ n: new bn_js_1.default(1),
325
+ destinations: [destination],
326
+ vdata: [resTransfer.toBuffer()],
327
+ });
328
+ const script = new verus_typescript_primitives_1.SmartTransactionScript(master, params);
329
+ return { script: script.toBuffer(), nativeValue: index_js_1.RESERVE_TRANSFER_FEE };
330
+ }
331
+ /**
332
+ * Build a token change output (EVAL_RESERVE_OUTPUT)
333
+ */
334
+ function buildTokenChangeOutput(changeAddress, currencyChanges) {
335
+ const destination = new verus_typescript_primitives_1.TxDestination(verus_typescript_primitives_1.KeyID.fromAddress(changeAddress));
336
+ const valueMap = new Map();
337
+ for (const [currency, amount] of currencyChanges) {
338
+ if (amount > 0) {
339
+ valueMap.set(currency, new bn_js_1.default(amount));
340
+ }
341
+ }
342
+ const values = new verus_typescript_primitives_1.CurrencyValueMap({
343
+ value_map: valueMap,
344
+ multivalue: false,
345
+ });
346
+ const tokenOutput = new verus_typescript_primitives_1.TokenOutput({ version: new bn_js_1.default(1), values });
347
+ const master = new verus_typescript_primitives_1.OptCCParams({
348
+ version: new bn_js_1.default(3),
349
+ eval_code: new bn_js_1.default(verus_typescript_primitives_2.EVALS.EVAL_NONE),
350
+ m: new bn_js_1.default(1),
351
+ n: new bn_js_1.default(1),
352
+ destinations: [destination],
353
+ vdata: [],
354
+ });
355
+ const params = new verus_typescript_primitives_1.OptCCParams({
356
+ version: new bn_js_1.default(3),
357
+ eval_code: new bn_js_1.default(verus_typescript_primitives_2.EVALS.EVAL_RESERVE_OUTPUT),
358
+ m: new bn_js_1.default(1),
359
+ n: new bn_js_1.default(1),
360
+ destinations: [destination],
361
+ vdata: [tokenOutput.toBuffer()],
362
+ });
363
+ const script = new verus_typescript_primitives_1.SmartTransactionScript(master, params);
364
+ return { script: script.toBuffer(), nativeValue: 0 };
365
+ }
366
+ // ─── Validation ──────────────────────────────────────────────────
367
+ const IDENTITY_NAME_RE = /^[a-z0-9_-]{1,64}$/;
368
+ function validateIdentityWif(wif) {
369
+ if (!wif || typeof wif !== 'string') {
370
+ throw new errors_js_1.InvalidWifError('WIF is required');
371
+ }
372
+ const check = (0, index_js_5.validateWif)(wif);
373
+ if (!check.valid) {
374
+ throw new errors_js_1.InvalidWifError(check.error);
375
+ }
376
+ }
377
+ function validateIdentityName(name) {
378
+ if (!name || typeof name !== 'string') {
379
+ throw new errors_js_1.InvalidNameError('', 'Name is required');
380
+ }
381
+ if (!IDENTITY_NAME_RE.test(name)) {
382
+ throw new errors_js_1.InvalidNameError(name);
383
+ }
384
+ }
385
+ // ─── Workflow Orchestrators ────────────────────────────────────────
386
+ /**
387
+ * Build and sign a name commitment transaction (Step 1 of identity creation)
388
+ */
389
+ function buildAndSignCommitment(params, network) {
390
+ validateIdentityWif(params.wif);
391
+ validateIdentityName(params.name);
392
+ if (!params.utxos || params.utxos.length === 0) {
393
+ throw new errors_js_1.TransactionBuildError('At least one UTXO is required');
394
+ }
395
+ const verusNetwork = (0, index_js_3.getNetwork)(network === 'testnet');
396
+ const networkConfig = index_js_1.NETWORK_CONFIG[network];
397
+ const commitment = prepareNameCommitment(params.name, params.changeAddress, params.referral, params.parent, network);
398
+ const utxos = params.utxos;
399
+ const selection = (0, index_js_4.selectUtxos)(utxos, 0, new Map(), 1, networkConfig.chainId, undefined, true);
400
+ const txb = new utxo_lib_1.TransactionBuilder(verusNetwork);
401
+ txb.setVersion(4);
402
+ txb.setExpiryHeight(params.expiryHeight || 0);
403
+ txb.setVersionGroupId(index_js_1.VERSION_GROUP_ID);
404
+ for (const utxo of selection.selected) {
405
+ txb.addInput(Buffer.from(utxo.txid, 'hex').reverse(), utxo.outputIndex, 0xffffffff, Buffer.from(utxo.script, 'hex'));
406
+ }
407
+ txb.addOutput(commitment.commitmentScript, 0);
408
+ if (selection.nativeChange > 0) {
409
+ txb.addOutput(params.changeAddress, selection.nativeChange);
410
+ }
411
+ const unsignedTx = txb.buildIncomplete();
412
+ const { signedTx, txid } = (0, index_js_3.signTransactionSmart)(unsignedTx.toHex(), params.wif, selection.selected, verusNetwork);
413
+ return {
414
+ signedTx,
415
+ txid,
416
+ fee: selection.fee,
417
+ identityAddress: commitment.identityAddress,
418
+ commitmentData: {
419
+ name: params.name,
420
+ salt: commitment.salt.toString('hex'),
421
+ referral: params.referral || null,
422
+ parent: params.parent || null,
423
+ namereservationHex: commitment.serializedReservation.toString('hex'),
424
+ commitmentHash: commitment.commitmentHash.toString('hex'),
425
+ },
426
+ };
427
+ }
428
+ /**
429
+ * Build and sign an identity registration transaction (Step 2)
430
+ */
431
+ function buildAndSignRegistration(params, network) {
432
+ validateIdentityWif(params.wif);
433
+ if (!params.primaryAddresses || params.primaryAddresses.length === 0) {
434
+ throw new errors_js_1.TransactionBuildError('At least one primary address is required');
435
+ }
436
+ if (!params.utxos || params.utxos.length === 0) {
437
+ throw new errors_js_1.TransactionBuildError('At least one funding UTXO is required');
438
+ }
439
+ const verusNetwork = (0, index_js_3.getNetwork)(network === 'testnet');
440
+ const networkConfig = index_js_1.NETWORK_CONFIG[network];
441
+ const systemId = networkConfig.chainId;
442
+ const commitData = params.commitmentData;
443
+ const parentIAddress = commitData.parent || systemId;
444
+ const isSubId = !isVRSCParent(commitData.parent || undefined, network);
445
+ const effectiveParent = isSubId ? commitData.parent : systemId;
446
+ const identityAddress = deriveIdentityAddress(commitData.name, effectiveParent);
447
+ const identity = createIdentityObject({
448
+ name: commitData.name,
449
+ primaryAddresses: params.primaryAddresses,
450
+ minSigs: params.minSigs,
451
+ revocationAuthority: params.revocationAuthority || identityAddress,
452
+ recoveryAuthority: params.recoveryAuthority || identityAddress,
453
+ parentIAddress,
454
+ systemId,
455
+ });
456
+ const identityScript = buildIdentityScript(identity);
457
+ const reservationScript = buildReservationScript(identityAddress, Buffer.from(commitData.namereservationHex, 'hex'), isSubId);
458
+ if (isSubId) {
459
+ return _buildSubIdRegistration(params, identity, identityScript, reservationScript, identityAddress, parentIAddress, systemId, verusNetwork);
460
+ }
461
+ return _buildVrscRegistration(params, identityScript, reservationScript, identityAddress, parentIAddress, systemId, verusNetwork);
462
+ }
463
+ function _buildVrscRegistration(params, identityScript, reservationScript, identityAddress, parentIAddress, systemId, network) {
464
+ const commitData = params.commitmentData;
465
+ const hasReferral = !!commitData.referral;
466
+ const fees = calculateRegistrationFees(hasReferral, params.registrationFee, params.referralLevels);
467
+ const referralOutputs = [];
468
+ if (hasReferral) {
469
+ const chain = (params.referralChain && params.referralChain.length > 0)
470
+ ? params.referralChain
471
+ : commitData.referral ? [commitData.referral] : [];
472
+ for (const referrerAddr of chain) {
473
+ referralOutputs.push({
474
+ script: buildReferralPaymentScript(referrerAddr),
475
+ value: fees.referralAmount,
476
+ });
477
+ }
478
+ }
479
+ // requiredNative = full registration fee (referral outputs come out of this total)
480
+ // implicit fee to miners = totalFee - sum(referral outputs) + txFee
481
+ const totalFee = params.registrationFee ?? index_js_1.DEFAULT_REGISTRATION_FEE;
482
+ const totalReferralPayments = referralOutputs.reduce((sum, o) => sum + o.value, 0);
483
+ const requiredNative = totalFee;
484
+ const numOutputs = 2 + referralOutputs.length + 1;
485
+ const selection = (0, index_js_4.selectUtxos)(params.utxos, requiredNative, new Map(), numOutputs, systemId, undefined, true);
486
+ const txb = new utxo_lib_1.TransactionBuilder(network);
487
+ txb.setVersion(4);
488
+ txb.setExpiryHeight(params.expiryHeight || 0);
489
+ txb.setVersionGroupId(index_js_1.VERSION_GROUP_ID);
490
+ const commitUtxo = params.commitmentUtxo;
491
+ txb.addInput(Buffer.from(commitUtxo.txid, 'hex').reverse(), commitUtxo.outputIndex, 0xffffffff, Buffer.from(commitUtxo.script, 'hex'));
492
+ for (const utxo of selection.selected) {
493
+ txb.addInput(Buffer.from(utxo.txid, 'hex').reverse(), utxo.outputIndex, 0xffffffff, Buffer.from(utxo.script, 'hex'));
494
+ }
495
+ txb.addOutput(identityScript, 0);
496
+ for (const referralOut of referralOutputs) {
497
+ txb.addOutput(referralOut.script, referralOut.value);
498
+ }
499
+ txb.addOutput(reservationScript, 0);
500
+ if (selection.nativeChange > 0) {
501
+ txb.addOutput(params.changeAddress, selection.nativeChange);
502
+ }
503
+ const unsignedTx = txb.buildIncomplete();
504
+ const allUtxos = [commitUtxo, ...selection.selected];
505
+ // The registration fee is burned as an IMPLICIT miner fee (identity and
506
+ // reservation outputs carry 0; referral payouts come out of the total) —
507
+ // this matches on-chain registrations, and the daemon exempts recognized
508
+ // identity definitions from its absurd-fee check (IS_HIGH_FEE). utxo-lib's
509
+ // client-side fee-rate cap (default 2500 sat/vbyte) must be told the
510
+ // intended absolute fee or build() throws "Transaction has absurd fees".
511
+ const expectedImplicitFee = commitUtxo.satoshis + totalFee - totalReferralPayments + selection.fee;
512
+ const { signedTx, txid } = (0, index_js_3.signTransactionSmart)(unsignedTx.toHex(), params.wif, allUtxos, network, expectedImplicitFee);
513
+ return {
514
+ signedTx,
515
+ txid,
516
+ fee: selection.fee,
517
+ identityAddress,
518
+ registrationFee: totalFee - totalReferralPayments,
519
+ referralPayments: referralOutputs.length,
520
+ referralAmountEach: fees.referralAmount,
521
+ inputsUsed: allUtxos.length,
522
+ nativeChange: selection.nativeChange,
523
+ };
524
+ }
525
+ function _buildSubIdRegistration(params, identity, identityScript, reservationScript, identityAddress, parentIAddress, systemId, network) {
526
+ const registrationFeeAmount = params.registrationFeeAmount;
527
+ if (!registrationFeeAmount || registrationFeeAmount <= 0) {
528
+ throw new Error('registrationFeeAmount is required for sub-ID registration. ' +
529
+ 'Specify the fee in parent currency satoshis.');
530
+ }
531
+ const feeOutput = buildRegistrationFeeOutput(parentIAddress, registrationFeeAmount, systemId, params.changeAddress);
532
+ const requiredCurrencies = new Map([
533
+ [parentIAddress, registrationFeeAmount],
534
+ ]);
535
+ const nativeImportFee = params.nativeImportFee || 0;
536
+ const nativeTarget = feeOutput.nativeValue + nativeImportFee;
537
+ const numOutputs = 4;
538
+ const selection = (0, index_js_4.selectUtxos)(params.utxos, nativeTarget, requiredCurrencies, numOutputs, systemId, undefined, true);
539
+ const txb = new utxo_lib_1.TransactionBuilder(network);
540
+ txb.setVersion(4);
541
+ txb.setExpiryHeight(params.expiryHeight || 0);
542
+ txb.setVersionGroupId(index_js_1.VERSION_GROUP_ID);
543
+ const commitUtxo = params.commitmentUtxo;
544
+ txb.addInput(Buffer.from(commitUtxo.txid, 'hex').reverse(), commitUtxo.outputIndex, 0xffffffff, Buffer.from(commitUtxo.script, 'hex'));
545
+ for (const utxo of selection.selected) {
546
+ txb.addInput(Buffer.from(utxo.txid, 'hex').reverse(), utxo.outputIndex, 0xffffffff, Buffer.from(utxo.script, 'hex'));
547
+ }
548
+ txb.addOutput(identityScript, 0);
549
+ txb.addOutput(feeOutput.script, feeOutput.nativeValue);
550
+ txb.addOutput(reservationScript, 0);
551
+ const hasTokenChange = selection.currencyChanges.size > 0;
552
+ if (hasTokenChange || selection.nativeChange > 0) {
553
+ if (hasTokenChange) {
554
+ const tokenChangeScript = buildTokenChangeOutput(params.changeAddress, selection.currencyChanges);
555
+ txb.addOutput(tokenChangeScript.script, selection.nativeChange);
556
+ }
557
+ else {
558
+ txb.addOutput(params.changeAddress, selection.nativeChange);
559
+ }
560
+ }
561
+ const unsignedTx = txb.buildIncomplete();
562
+ const allUtxos = [commitUtxo, ...selection.selected];
563
+ const { signedTx, txid } = (0, index_js_3.signTransactionSmart)(unsignedTx.toHex(), params.wif, allUtxos, network);
564
+ return {
565
+ signedTx,
566
+ txid,
567
+ fee: selection.fee,
568
+ identityAddress,
569
+ registrationFee: registrationFeeAmount,
570
+ referralPayments: 0,
571
+ referralAmountEach: 0,
572
+ inputsUsed: allUtxos.length,
573
+ nativeChange: selection.nativeChange,
574
+ };
575
+ }
576
+ /**
577
+ * Build and sign an identity update transaction
578
+ */
579
+ function buildAndSignIdentityUpdate(params, network, operation = 'update', lockUnlockParams) {
580
+ validateIdentityWif(params.wif);
581
+ if (!params.identityHex) {
582
+ throw new errors_js_1.TransactionBuildError('identityHex is required');
583
+ }
584
+ if (!params.utxos || params.utxos.length === 0) {
585
+ throw new errors_js_1.TransactionBuildError('At least one funding UTXO is required');
586
+ }
587
+ const verusNetwork = (0, index_js_3.getNetwork)(network === 'testnet');
588
+ const networkConfig = index_js_1.NETWORK_CONFIG[network];
589
+ const systemId = networkConfig.chainId;
590
+ const identity = new verus_typescript_primitives_1.Identity();
591
+ identity.fromBuffer(Buffer.from(params.identityHex, 'hex'));
592
+ switch (operation) {
593
+ case 'update': {
594
+ if (params.primaryAddresses) {
595
+ identity.setPrimaryAddresses(params.primaryAddresses);
596
+ }
597
+ if (params.minSigs !== undefined) {
598
+ identity.min_sigs = new bn_js_1.default(params.minSigs);
599
+ }
600
+ if (params.revocationAuthority) {
601
+ identity.setRevocation(params.revocationAuthority);
602
+ }
603
+ if (params.recoveryAuthority) {
604
+ identity.setRecovery(params.recoveryAuthority);
605
+ }
606
+ if (params.contentMap) {
607
+ for (const [key, value] of Object.entries(params.contentMap)) {
608
+ identity.content_map.set(key, Buffer.from(value, 'hex'));
609
+ }
610
+ }
611
+ if (params.contentMultimap) {
612
+ const jsonObj = {};
613
+ for (const [key, value] of Object.entries(params.contentMultimap)) {
614
+ jsonObj[key] = Array.isArray(value) ? value : [value];
615
+ }
616
+ identity.content_multimap = verus_typescript_primitives_1.ContentMultiMap.fromJson(jsonObj);
617
+ }
618
+ break;
619
+ }
620
+ case 'revoke': {
621
+ identity.clearContentMultiMap();
622
+ identity.revoke();
623
+ break;
624
+ }
625
+ case 'recover': {
626
+ identity.unrevoke();
627
+ identity.clearContentMultiMap();
628
+ if (params.primaryAddresses) {
629
+ identity.setPrimaryAddresses(params.primaryAddresses);
630
+ }
631
+ if (params.revocationAuthority) {
632
+ identity.setRevocation(params.revocationAuthority);
633
+ }
634
+ if (params.recoveryAuthority) {
635
+ identity.setRecovery(params.recoveryAuthority);
636
+ }
637
+ break;
638
+ }
639
+ case 'lock': {
640
+ const unlockAfter = lockUnlockParams?.unlockAfter;
641
+ if (!unlockAfter) {
642
+ throw new Error('unlockAfter (block height) is required for lock operation');
643
+ }
644
+ identity.lock(new bn_js_1.default(unlockAfter));
645
+ break;
646
+ }
647
+ case 'unlock': {
648
+ identity.unlock(new bn_js_1.default(0), new bn_js_1.default(params.expiryHeight || 0));
649
+ break;
650
+ }
651
+ }
652
+ const identityBuf = identity.toBuffer();
653
+ const unfundedHex = createUnfundedIdentityUpdate(identityBuf.toString('hex'), verusNetwork, params.expiryHeight || 0);
654
+ const selection = (0, index_js_4.selectUtxos)(params.utxos, 0, new Map(), 1, systemId, undefined, true);
655
+ const txb = new utxo_lib_1.TransactionBuilder(verusNetwork);
656
+ txb.setVersion(4);
657
+ txb.setExpiryHeight(params.expiryHeight || 0);
658
+ txb.setVersionGroupId(index_js_1.VERSION_GROUP_ID);
659
+ for (const utxo of selection.selected) {
660
+ txb.addInput(Buffer.from(utxo.txid, 'hex').reverse(), utxo.outputIndex, 0xffffffff, Buffer.from(utxo.script, 'hex'));
661
+ }
662
+ const unfundedTx = utxo_lib_1.Transaction.fromHex(unfundedHex, verusNetwork);
663
+ for (const out of unfundedTx.outs) {
664
+ txb.addOutput(out.script, out.value);
665
+ }
666
+ if (selection.nativeChange > 0) {
667
+ txb.addOutput(params.changeAddress, selection.nativeChange);
668
+ }
669
+ const fundedTx = txb.buildIncomplete();
670
+ const fundedHex = fundedTx.toHex();
671
+ const prevOutScripts = selection.selected.map(u => Buffer.from(u.script, 'hex'));
672
+ const idUtxo = params.identityUtxo;
673
+ const completedHex = completeFundedIdentityUpdate(fundedHex, verusNetwork, prevOutScripts, {
674
+ hash: Buffer.from(idUtxo.txid, 'hex').reverse(),
675
+ index: idUtxo.outputIndex,
676
+ sequence: 0xffffffff,
677
+ script: Buffer.from(idUtxo.script, 'hex'),
678
+ });
679
+ const allUtxos = [...selection.selected, idUtxo];
680
+ const { signedTx, txid } = (0, index_js_3.signTransactionSmart)(completedHex, params.wif, allUtxos, verusNetwork);
681
+ return {
682
+ signedTx,
683
+ txid,
684
+ fee: selection.fee,
685
+ identityAddress: identity.getIdentityAddress(),
686
+ operation,
687
+ inputsUsed: allUtxos.length,
688
+ nativeChange: selection.nativeChange,
689
+ };
690
+ }
691
+ //# sourceMappingURL=index.js.map