@meshsdk/transaction 1.6.0-alpha.11

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.
@@ -0,0 +1,63 @@
1
+ import type { NativeScript } from "@meshsdk/common";
2
+
3
+ import {
4
+ buildScriptPubkey,
5
+ deserializeEd25519KeyHash,
6
+ toNativeScript,
7
+ resolvePaymentKeyHash,
8
+ } from "@meshsdk/core-cst";
9
+
10
+ export class ForgeScript {
11
+ static withOneSignature(address: string): string {
12
+ const keyHash = deserializeEd25519KeyHash(resolvePaymentKeyHash(address));
13
+ return buildScriptPubkey(keyHash).toCbor();
14
+ }
15
+
16
+ // static withAtLeastNSignatures(
17
+ // addresses: string[], minimumRequired: number,
18
+ // ): string {
19
+ // const nativeScripts = csl.NativeScripts.new();
20
+
21
+ // addresses.forEach((address) => {
22
+ // const keyHash = deserializeEd25519KeyHash(
23
+ // resolvePaymentKeyHash(address),
24
+ // );
25
+ // nativeScripts.add(buildScriptPubkey(keyHash));
26
+ // });
27
+
28
+ // const scriptNOfK = csl.ScriptNOfK.new(minimumRequired, nativeScripts);
29
+ // return csl.NativeScript.new_script_any(scriptNOfK).to_hex();
30
+ // }
31
+
32
+ // static withAnySignature(addresses: string[]): string {
33
+ // const nativeScripts = csl.NativeScripts.new();
34
+
35
+ // addresses.forEach((address) => {
36
+ // const keyHash = deserializeEd25519KeyHash(
37
+ // resolvePaymentKeyHash(address),
38
+ // );
39
+ // nativeScripts.add(buildScriptPubkey(keyHash));
40
+ // });
41
+
42
+ // const scriptAny = csl.ScriptAny.new(nativeScripts);
43
+ // return csl.NativeScript.new_script_any(scriptAny).to_hex();
44
+ // }
45
+
46
+ // static withAllSignatures(addresses: string[]): string {
47
+ // const nativeScripts = csl.NativeScripts.new();
48
+
49
+ // addresses.forEach((address) => {
50
+ // const keyHash = deserializeEd25519KeyHash(
51
+ // resolvePaymentKeyHash(address),
52
+ // );
53
+ // nativeScripts.add(buildScriptPubkey(keyHash));
54
+ // });
55
+
56
+ // const scriptAll = csl.ScriptAll.new(nativeScripts);
57
+ // return csl.NativeScript.new_script_any(scriptAll).to_hex();
58
+ // }
59
+
60
+ static fromNativeScript(script: NativeScript): string {
61
+ return toNativeScript(script).toCbor();
62
+ }
63
+ }
@@ -0,0 +1 @@
1
+ export * from "./forge.script";
@@ -0,0 +1,609 @@
1
+ import {
2
+ Action,
3
+ Asset,
4
+ Budget,
5
+ CIP68_100,
6
+ CIP68_222,
7
+ DEFAULT_REDEEMER_BUDGET,
8
+ Data,
9
+ IInitiator,
10
+ Mint,
11
+ NativeScript,
12
+ POLICY_ID_LENGTH,
13
+ PlutusScript,
14
+ PoolParams,
15
+ Recipient,
16
+ SUPPORTED_TOKENS,
17
+ Token,
18
+ UTxO,
19
+ hexToString,
20
+ metadataToCip68,
21
+ stringToHex,
22
+ } from "@meshsdk/common";
23
+ import { MeshTxBuilder, MeshTxBuilderOptions } from "../mesh-tx-builder";
24
+ import {
25
+ deserializeNativeScript,
26
+ deserializePlutusScript,
27
+ fromScriptRef,
28
+ } from "@meshsdk/core-cst";
29
+
30
+ export interface TransactionOptions extends MeshTxBuilderOptions {
31
+ initiator: IInitiator;
32
+ }
33
+
34
+ export class Transaction {
35
+ txBuilder: MeshTxBuilder;
36
+ initiator: IInitiator;
37
+ isCollateralNeeded: boolean = false;
38
+
39
+ constructor(options: TransactionOptions) {
40
+ this.txBuilder = new MeshTxBuilder(options);
41
+ this.initiator = options.initiator;
42
+ }
43
+
44
+ /**
45
+ * Adds an output to the transaction.
46
+ *
47
+ * @param recipient The recipient of the output.
48
+ * @param assets The assets to send. Provide string for lovelace and Asset[] for tokens and/or lovelace.
49
+ * @returns The transaction builder.
50
+ * @see {@link https://meshjs.dev/apis/transaction#sendAssets}
51
+ */
52
+ sendAssets(recipient: Recipient, assets: Asset[] | string): Transaction {
53
+ if (typeof assets === "string") {
54
+ assets = [
55
+ {
56
+ unit: "lovelace",
57
+ quantity: assets,
58
+ },
59
+ ];
60
+ }
61
+ if (typeof recipient === "string") {
62
+ this.txBuilder.txOut(recipient, assets);
63
+ }
64
+ if (typeof recipient === "object") {
65
+ this.txBuilder.txOut(recipient.address, assets);
66
+ if (recipient.datum) {
67
+ if (recipient.datum.inline) {
68
+ this.txBuilder.txOutInlineDatumValue(recipient.datum.value);
69
+ } else {
70
+ this.txBuilder.txOutDatumHashValue(recipient.datum.value);
71
+ }
72
+ }
73
+ }
74
+
75
+ return this;
76
+ }
77
+
78
+ /**
79
+ * Suggest deprecated - Adds a transaction output to the transaction.
80
+ * Use sendAssets instead:
81
+ * ```ts
82
+ * this.sendAssets(recipient, lovelace);
83
+ * ```
84
+ *
85
+ * Deprecation reason - Unnecessary implementation which might cause confusion.
86
+ *
87
+ * @param {Recipient} recipient The recipient of the transaction.
88
+ * @param {string} lovelace The amount of lovelace to send.
89
+ * @returns {Transaction} The Transaction object.
90
+ * @see {@link https://meshjs.dev/apis/transaction#sendAda}
91
+ */
92
+ sendLovelace(recipient: Recipient, lovelace: string): Transaction {
93
+ return this.sendAssets(recipient, lovelace);
94
+ }
95
+
96
+ /**
97
+ * Suggest deprecated - Adds stable coins transaction output to the transaction.
98
+ * Please use sendAssets with helper function to obtain token unit instead:
99
+ * ```ts
100
+ * const assets = [{ unit: SUPPORTED_TOKENS.GIMBAL, quantity: "100" }]
101
+ * transaction.sendAssets(recipient, assets)
102
+ * ```
103
+ *
104
+ * Deprecation reason - Required maintenance on tokens.
105
+ *
106
+ * @param {Recipient} recipient The recipient of the transaction.
107
+ * @param {Token} ticker The ticker of the token to send.
108
+ * @param {string} amount The amount of the token to send.
109
+ * @returns {Transaction} The Transaction object.
110
+ * @see {@link https://meshjs.dev/apis/transaction#sendToken}
111
+ */
112
+ sendToken(recipient: Recipient, ticker: Token, amount: string): Transaction {
113
+ const assets = [{ unit: SUPPORTED_TOKENS[ticker], quantity: amount }];
114
+ return this.sendAssets(recipient, assets);
115
+ }
116
+
117
+ /**
118
+ * Adds an output to the transaction.
119
+ * Suggest deprecated - use sendAssets instead:
120
+ *
121
+ * ```ts
122
+ * const assets = value.output.amount;
123
+ * this.sendAssets(recipient, assets);
124
+ * ```
125
+ * Deprecation reason - Unnecessary implementation which might cause confusion.
126
+ *
127
+ * @param {Recipient} recipient The recipient of the output.
128
+ * @param {UTxO} value The UTxO value of the output.
129
+ * @returns {Transaction} The Transaction object.
130
+ */
131
+ sendValue(recipient: Recipient, value: UTxO): Transaction {
132
+ const assets = value.output.amount;
133
+ return this.sendAssets(recipient, assets);
134
+ }
135
+
136
+ /**
137
+ * Sets the inputs for the transaction.
138
+ *
139
+ * @param {UTxO[]} inputs The inputs to set.
140
+ * @returns {Transaction} The transaction.
141
+ */
142
+ setTxInputs(inputs: UTxO[]): Transaction {
143
+ inputs.forEach((input) => {
144
+ this.txBuilder.txIn(
145
+ input.input.txHash,
146
+ input.input.outputIndex,
147
+ input.output.amount,
148
+ input.output.address
149
+ );
150
+ });
151
+
152
+ return this;
153
+ }
154
+
155
+ /**
156
+ * Sets the reference inputs for the transaction.
157
+ *
158
+ * @param {UTxO[]} inputs The reference inputs to set.
159
+ * @returns {Transaction} The transaction.
160
+ */
161
+ setTxRefInputs(inputs: UTxO[]): Transaction {
162
+ inputs.forEach((input) => {
163
+ this.txBuilder.readOnlyTxInReference(
164
+ input.input.txHash,
165
+ input.input.outputIndex
166
+ );
167
+ });
168
+
169
+ return this;
170
+ }
171
+
172
+ /**
173
+ * Sets the native script for the transaction.
174
+ * @param {NativeScript} script The native script to spend from.
175
+ * @param {UTxO} utxo The UTxO attached to the script.
176
+ * @returns {Transaction} The Transaction object.
177
+ */
178
+ setNativeScriptInput(script: NativeScript, utxo: UTxO): Transaction {
179
+ const { scriptCbor } =
180
+ this.txBuilder.serializer.deserializer.script.deserializeNativeScript(
181
+ script
182
+ );
183
+ this.txBuilder
184
+ .txIn(
185
+ utxo.input.txHash,
186
+ utxo.input.outputIndex,
187
+ utxo.output.amount,
188
+ utxo.output.address
189
+ )
190
+ .txInScript(scriptCbor!);
191
+
192
+ return this;
193
+ }
194
+
195
+ // TODO: nuke this probably as the input type is too confusing
196
+ redeemValue(options: {
197
+ value: UTxO;
198
+ script: PlutusScript | UTxO;
199
+ redeemer?: Pick<Action, "data"> & { budget?: Budget };
200
+ datum?: Data | UTxO;
201
+ }): Transaction {
202
+ const { value, script, datum, redeemer } = options;
203
+ const red = redeemer || {
204
+ data: { alternative: 0, fields: ["mesh"] },
205
+ budget: DEFAULT_REDEEMER_BUDGET,
206
+ };
207
+
208
+ if ("code" in script) {
209
+ // Provided script for redemption
210
+ this.isCollateralNeeded = true;
211
+ this.spendingPlutusScript(script)
212
+ .txIn(
213
+ value.input.txHash,
214
+ value.input.outputIndex,
215
+ value.output.amount,
216
+ value.output.address
217
+ )
218
+ .txInScript(script.code)
219
+ .txInRedeemerValue(red.data, "Mesh", red.budget);
220
+ }
221
+
222
+ if ("output" in script) {
223
+ // Reference script for redemption
224
+ if (!script.output.scriptRef) {
225
+ throw new Error("redeemValue: No script reference found in UTxO");
226
+ }
227
+ const scriptRef = fromScriptRef(script.output.scriptRef);
228
+ if (!scriptRef || !("code" in scriptRef)) {
229
+ throw new Error("redeemValue: Script reference not found");
230
+ }
231
+
232
+ this.isCollateralNeeded = true;
233
+ this.spendingPlutusScript(scriptRef)
234
+ .txIn(
235
+ value.input.txHash,
236
+ value.input.outputIndex,
237
+ value.output.amount,
238
+ value.output.address
239
+ )
240
+ .spendingTxInReference(
241
+ script.input.txHash,
242
+ script.input.outputIndex,
243
+ script.output.scriptHash
244
+ )
245
+ .txInRedeemerValue(red.data, "Mesh", red.budget);
246
+ }
247
+
248
+ if (datum) {
249
+ // Provided datum for redemption
250
+ this.txBuilder.txInDatumValue(datum);
251
+ } else {
252
+ // Reference datum for redemption
253
+ this.txBuilder.txInInlineDatumPresent();
254
+ }
255
+ // if (typeof datum === "object" && "output" in datum) {
256
+ // // Reference datum for redemption
257
+ // } else {
258
+ // // Provided datum for redemption
259
+ // if (datum) {
260
+ // }
261
+ // }
262
+
263
+ return this;
264
+ }
265
+
266
+ // TODO: nuke this probably as the input type is too confusing
267
+ mintAsset(
268
+ forgeScript: string | PlutusScript | UTxO,
269
+ mint: Mint,
270
+ redeemer?: Pick<Action, "data"> & { budget?: Budget }
271
+ ): Transaction {
272
+ const assetQuantity = mint.assetQuantity;
273
+ let assetNameHex = stringToHex(mint.assetName);
274
+ const referenceAssetNameHex = CIP68_100(assetNameHex);
275
+ if (mint.cip68ScriptAddress) {
276
+ assetNameHex = CIP68_222(assetNameHex);
277
+ }
278
+ let policyId = "";
279
+ switch (typeof forgeScript) {
280
+ case "string":
281
+ policyId = deserializeNativeScript(forgeScript).hash().toString();
282
+ this.txBuilder
283
+ .mint(assetQuantity, policyId, assetNameHex)
284
+ .mintingScript(forgeScript);
285
+ if (mint.cip68ScriptAddress) {
286
+ this.txBuilder
287
+ .mint(assetQuantity, policyId, referenceAssetNameHex)
288
+ .mintingScript(forgeScript);
289
+ }
290
+
291
+ break;
292
+
293
+ case "object":
294
+ if (!redeemer)
295
+ throw new Error(
296
+ "burnAsset: Redeemer data is required for Plutus minting"
297
+ );
298
+ if ("code" in forgeScript) {
299
+ // Burn plutus script assets with provided script
300
+ policyId = deserializePlutusScript(
301
+ forgeScript.code,
302
+ forgeScript.version
303
+ )
304
+ .hash()
305
+ .toString();
306
+
307
+ this.isCollateralNeeded = true;
308
+ this.mintPlutusScript(forgeScript)
309
+ .mint(assetQuantity, policyId, assetNameHex)
310
+ .mintingScript(forgeScript.code)
311
+ .mintRedeemerValue(redeemer.data, "Mesh", redeemer.budget);
312
+ if (mint.cip68ScriptAddress) {
313
+ this.mintPlutusScript(forgeScript)
314
+ .mint(assetQuantity, policyId, referenceAssetNameHex)
315
+ .mintingScript(forgeScript.code)
316
+ .mintRedeemerValue(redeemer.data, "Mesh", redeemer.budget);
317
+ }
318
+ break;
319
+ }
320
+ if ("output" in forgeScript) {
321
+ // Burn plutus script assets with reference script
322
+ if (!forgeScript.output.scriptRef) {
323
+ throw new Error("mintAsset: No script reference found in UTxO");
324
+ }
325
+ const script = fromScriptRef(forgeScript.output.scriptRef);
326
+ if (!script) {
327
+ throw new Error("mintAsset: Script reference not found");
328
+ }
329
+
330
+ if ("code" in script) {
331
+ policyId = deserializePlutusScript(script.code, script.version)
332
+ .hash()
333
+ .toString();
334
+
335
+ this.isCollateralNeeded = true;
336
+ this.mintPlutusScript(script)
337
+ .mint(assetQuantity, policyId, assetNameHex)
338
+ .mintTxInReference(
339
+ forgeScript.input.txHash,
340
+ forgeScript.input.outputIndex
341
+ )
342
+ .mintRedeemerValue(redeemer.data, "Mesh", redeemer.budget);
343
+ if (mint.cip68ScriptAddress) {
344
+ this.mintPlutusScript(script)
345
+ .mint(assetQuantity, policyId, referenceAssetNameHex)
346
+ .mintTxInReference(
347
+ forgeScript.input.txHash,
348
+ forgeScript.input.outputIndex
349
+ )
350
+ .mintRedeemerValue(redeemer.data, "Mesh", redeemer.budget);
351
+ break;
352
+ }
353
+
354
+ break;
355
+ } else {
356
+ // TODO: to implement reference script minting for native script tokens
357
+ throw new Error(
358
+ "mintAsset: Reference script minting not implemented"
359
+ );
360
+ // this.txBuilder
361
+ // .mint(assetQuantity, policyId, assetName)
362
+ // .mintTxInReference(
363
+ // forgeScript.input.txHash,
364
+ // forgeScript.input.outputIndex
365
+ // );
366
+ }
367
+ }
368
+ break;
369
+ }
370
+
371
+ if (mint.metadata && mint.label) {
372
+ this.setMetadata(Number(mint.label), {
373
+ [policyId]: {
374
+ [mint.assetName]: mint.metadata,
375
+ },
376
+ version: 1,
377
+ });
378
+ }
379
+ if (mint.recipient) {
380
+ this.sendAssets(mint.recipient, [
381
+ { unit: policyId + assetNameHex, quantity: mint.assetQuantity },
382
+ ]);
383
+ }
384
+ if (mint.cip68ScriptAddress) {
385
+ this.sendAssets(
386
+ {
387
+ address: mint.cip68ScriptAddress,
388
+ datum: { inline: true, value: metadataToCip68(mint.metadata) },
389
+ },
390
+ [
391
+ {
392
+ unit: policyId + referenceAssetNameHex,
393
+ quantity: mint.assetQuantity,
394
+ },
395
+ ]
396
+ );
397
+ }
398
+
399
+ return this;
400
+ }
401
+
402
+ // TODO: nuke this probably as the input type is too confusing
403
+ // TO be deprecated as it doesnt support reference script minting native assets
404
+ burnAsset(
405
+ forgeScript: string | PlutusScript | UTxO,
406
+ asset: Asset,
407
+ redeemer?: Pick<Action, "data"> & { budget?: Budget }
408
+ ): Transaction {
409
+ const assetQuantity = "-" + asset.quantity;
410
+ const mint: Mint = {
411
+ assetName: hexToString(asset.unit.slice(POLICY_ID_LENGTH)),
412
+ assetQuantity: assetQuantity,
413
+ };
414
+ try {
415
+ this.mintAsset(forgeScript, mint, redeemer);
416
+ } catch (error) {
417
+ throw new Error("burnAsset: " + error);
418
+ }
419
+
420
+ return this;
421
+ }
422
+
423
+ /**
424
+ * Sets the change address for the transaction.
425
+ *
426
+ * @param {string} changeAddress The change address.
427
+ * @returns {Transaction} The Transaction object.
428
+ */
429
+ setChangeAddress(changeAddress: string): Transaction {
430
+ this.txBuilder.changeAddress(changeAddress);
431
+ return this;
432
+ }
433
+
434
+ /**
435
+ * Sets the collateral for the transaction.
436
+ *
437
+ * @param {UTxO[]} collateral - Set the UTxO for collateral.
438
+ * @returns {Transaction} The Transaction object.
439
+ */
440
+ setCollateral(collateral: UTxO[]): Transaction {
441
+ collateral.forEach((collateralUtxo) => {
442
+ this.txBuilder.txInCollateral(
443
+ collateralUtxo.input.txHash,
444
+ collateralUtxo.input.outputIndex,
445
+ collateralUtxo.output.amount,
446
+ collateralUtxo.output.address
447
+ );
448
+ });
449
+
450
+ return this;
451
+ }
452
+
453
+ /**
454
+ * Sets the required signers for the transaction.
455
+ *
456
+ * @param {string[]} addresses The addresses of the required signers.
457
+ * @returns {Transaction} The Transaction object.
458
+ */
459
+ setRequiredSigners(addresses: string[]): Transaction {
460
+ addresses.forEach((address) => {
461
+ const { pubKeyHash } =
462
+ this.txBuilder.serializer.deserializer.key.deserializeAddress(address);
463
+ this.txBuilder.requiredSignerHash(pubKeyHash);
464
+ });
465
+
466
+ return this;
467
+ }
468
+
469
+ /**
470
+ * Set the time to live for the transaction.
471
+ *
472
+ * @param {string} slot The slot number to expire the transaction at.
473
+ * @returns {Transaction} The Transaction object.
474
+ * @see {@link https://meshjs.dev/apis/transaction#setTimeLimit}
475
+ */
476
+ setTimeToExpire(slot: string): Transaction {
477
+ this.txBuilder.invalidHereafter(Number(slot));
478
+ return this;
479
+ }
480
+
481
+ /**
482
+ * Sets the start slot for the transaction.
483
+ *
484
+ * @param {string} slot The start slot for the transaction.
485
+ * @returns {Transaction} The Transaction object.
486
+ * @see {@link https://meshjs.dev/apis/transaction#setTimeLimit}
487
+ */
488
+ setTimeToStart(slot: string): Transaction {
489
+ this.txBuilder.invalidBefore(Number(slot));
490
+ return this;
491
+ }
492
+
493
+ /**
494
+ * Add a JSON metadata entry to the transaction.
495
+ *
496
+ * @param {number} key The key to use for the metadata entry.
497
+ * @param {unknown} value The value to use for the metadata entry.
498
+ * @returns {Transaction} The Transaction object.
499
+ * @see {@link https://meshjs.dev/apis/transaction#setMetadata}
500
+ */
501
+ setMetadata(key: number, value: unknown): Transaction {
502
+ this.txBuilder.metadataValue(key.toString(), value as object);
503
+ return this;
504
+ }
505
+
506
+ withdrawRewards(rewardAddress: string, lovelace: string): Transaction {
507
+ this.txBuilder.withdrawal(rewardAddress, lovelace);
508
+ return this;
509
+ }
510
+
511
+ delegateStake(rewardAddress: string, poolId: string): Transaction {
512
+ this.txBuilder.delegateStakeCertificate(
513
+ this.txBuilder.serializer.resolver.keys.resolveStakeKeyHash(
514
+ rewardAddress
515
+ ),
516
+ this.txBuilder.serializer.resolver.keys.resolveEd25519KeyHash(poolId)
517
+ );
518
+ return this;
519
+ }
520
+
521
+ deregisterStake(rewardAddress: string): Transaction {
522
+ this.txBuilder.deregisterStakeCertificate(
523
+ this.txBuilder.serializer.resolver.keys.resolveStakeKeyHash(rewardAddress)
524
+ );
525
+ return this;
526
+ }
527
+
528
+ registerStake(rewardAddress: string): Transaction {
529
+ this.txBuilder.registerStakeCertificate(
530
+ this.txBuilder.serializer.resolver.keys.resolveStakeKeyHash(rewardAddress)
531
+ );
532
+ return this;
533
+ }
534
+
535
+ // TODO: test
536
+ registerPool(params: PoolParams): Transaction {
537
+ this.txBuilder.registerPoolCertificate(params);
538
+ return this;
539
+ }
540
+
541
+ // TODO: test
542
+ retirePool(poolId: string, epochNo: number): Transaction {
543
+ this.txBuilder.retirePoolCertificate(poolId, epochNo);
544
+ return this;
545
+ }
546
+
547
+ async build(): Promise<string> {
548
+ try {
549
+ await this.addCollateralIfNeeded();
550
+ await this.addTxInputsAsNeeded();
551
+ await this.addChangeAddress();
552
+
553
+ return this.txBuilder.complete();
554
+ } catch (error) {
555
+ throw new Error(
556
+ `[Transaction] An error occurred during build: ${error}.`
557
+ );
558
+ }
559
+ }
560
+
561
+ protected mintPlutusScript(script: PlutusScript) {
562
+ switch (script.version) {
563
+ case "V1":
564
+ this.txBuilder.mintPlutusScriptV1();
565
+ break;
566
+ case "V2":
567
+ this.txBuilder.mintPlutusScriptV2();
568
+ break;
569
+ case "V3":
570
+ this.txBuilder.mintPlutusScriptV3();
571
+ break;
572
+ }
573
+ return this.txBuilder;
574
+ }
575
+
576
+ protected spendingPlutusScript(script: PlutusScript) {
577
+ switch (script.version) {
578
+ case "V1":
579
+ this.txBuilder.spendingPlutusScriptV1();
580
+ break;
581
+ case "V2":
582
+ this.txBuilder.spendingPlutusScriptV2();
583
+ break;
584
+ case "V3":
585
+ this.txBuilder.spendingPlutusScriptV3();
586
+ break;
587
+ }
588
+ return this.txBuilder;
589
+ }
590
+
591
+ private async addCollateralIfNeeded() {
592
+ if (this.isCollateralNeeded) {
593
+ const collaterals = await this.initiator.getCollateral();
594
+ this.setCollateral(collaterals);
595
+ }
596
+ }
597
+
598
+ private async addTxInputsAsNeeded() {
599
+ const utxos = await this.initiator.getUtxos();
600
+ this.txBuilder.selectUtxosFrom(utxos);
601
+ }
602
+
603
+ private async addChangeAddress() {
604
+ if (this.txBuilder.meshTxBuilderBody.changeAddress === "") {
605
+ const changeAddress = await this.initiator.getChangeAddress();
606
+ this.setChangeAddress(changeAddress);
607
+ }
608
+ }
609
+ }