@meshsdk/transaction 1.9.0-beta-38 → 1.9.0-beta-40

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/dist/index.cjs CHANGED
@@ -1858,6 +1858,7 @@ var MeshTxBuilderCore = class {
1858
1858
  plutusWithdrawalScriptVersion;
1859
1859
  addingPlutusVote = false;
1860
1860
  plutusVoteScriptVersion;
1861
+ manualFee;
1861
1862
  _protocolParams = import_common.DEFAULT_PROTOCOL_PARAMETERS;
1862
1863
  mintItem;
1863
1864
  txInQueueItem;
@@ -3093,9 +3094,29 @@ var MeshTxBuilderCore = class {
3093
3094
  * @returns The MeshTxBuilder instance
3094
3095
  */
3095
3096
  setFee = (fee) => {
3097
+ this.manualFee = fee;
3096
3098
  this.meshTxBuilderBody.fee = fee;
3097
3099
  return this;
3098
3100
  };
3101
+ /**
3102
+ * Sets a total collateral for the transaction to use, a collateral return
3103
+ * will be generated to either the change address or the specified collateral return address
3104
+ * @param collateral The specified collateral
3105
+ * @returns The MeshTxBuilder instance
3106
+ */
3107
+ setTotalCollateral = (collateral) => {
3108
+ this.meshTxBuilderBody.totalCollateral = collateral;
3109
+ return this;
3110
+ };
3111
+ /**
3112
+ * Sets the collateral return address, if none is set, the change address will be used
3113
+ * @param address The address to use for collateral return
3114
+ * @returns The MeshTxBuilder instance
3115
+ */
3116
+ setCollateralReturnAddress = (address) => {
3117
+ this.meshTxBuilderBody.collateralReturnAddress = address;
3118
+ return this;
3119
+ };
3099
3120
  /**
3100
3121
  * Sets the network to use, this is mainly to know the cost models to be used to calculate script integrity hash
3101
3122
  * @param network The specific network this transaction is being built for ("testnet" | "preview" | "preprod" | "mainnet")
@@ -3532,6 +3553,7 @@ var MeshTxBuilderCore = class {
3532
3553
  newBuilder.voteItem = this.voteItem ? structuredClone(this.voteItem) : void 0;
3533
3554
  newBuilder.collateralQueueItem = this.collateralQueueItem ? structuredClone(this.collateralQueueItem) : void 0;
3534
3555
  newBuilder.refScriptTxInQueueItem = this.refScriptTxInQueueItem ? structuredClone(this.refScriptTxInQueueItem) : void 0;
3556
+ newBuilder.manualFee = this.manualFee;
3535
3557
  return newBuilder;
3536
3558
  }
3537
3559
  };
@@ -3637,6 +3659,9 @@ var MeshTxBuilder = class _MeshTxBuilder extends MeshTxBuilderCore {
3637
3659
  complete = async (customizedTx) => {
3638
3660
  if (customizedTx) {
3639
3661
  this.meshTxBuilderBody = { ...this.meshTxBuilderBody, ...customizedTx };
3662
+ if (customizedTx.fee) {
3663
+ this.setFee(customizedTx.fee);
3664
+ }
3640
3665
  } else {
3641
3666
  this.queueAllLastItem();
3642
3667
  }
@@ -3656,11 +3681,12 @@ var MeshTxBuilder = class _MeshTxBuilder extends MeshTxBuilderCore {
3656
3681
  collateral.txIn.scriptSize = 0;
3657
3682
  }
3658
3683
  await this.completeTxParts();
3659
- this.sortTxParts();
3684
+ await this.sanitizeOutputs();
3660
3685
  const txPrototype = await this.selectUtxos();
3661
3686
  await this.updateByTxPrototype(txPrototype, true);
3662
3687
  this.queueAllLastItem();
3663
3688
  this.removeDuplicateInputs();
3689
+ this.sortTxParts();
3664
3690
  if (this.verbose) {
3665
3691
  console.log(
3666
3692
  "txBodyJson - after coin selection",
@@ -3699,7 +3725,7 @@ var MeshTxBuilder = class _MeshTxBuilder extends MeshTxBuilderCore {
3699
3725
  throw new Error(`Evaluate redeemers failed: ${String(error)}`);
3700
3726
  }
3701
3727
  }
3702
- const fee = clonedBuilder.calculateFee();
3728
+ const fee = clonedBuilder.getActualFee();
3703
3729
  const redeemers = clonedBuilder.getRedeemerCosts();
3704
3730
  return {
3705
3731
  fee,
@@ -3762,7 +3788,7 @@ var MeshTxBuilder = class _MeshTxBuilder extends MeshTxBuilderCore {
3762
3788
  for (let change of selectionSkeleton.change) {
3763
3789
  this.txOut(change.address, change.amount);
3764
3790
  }
3765
- this.meshTxBuilderBody.fee = this.meshTxBuilderBody.fee === "0" ? selectionSkeleton.fee.toString() : this.meshTxBuilderBody.fee;
3791
+ this.meshTxBuilderBody.fee = selectionSkeleton.fee.toString();
3766
3792
  this.updateRedeemer(
3767
3793
  this.meshTxBuilderBody,
3768
3794
  selectionSkeleton.redeemers ?? [],
@@ -3781,6 +3807,12 @@ var MeshTxBuilder = class _MeshTxBuilder extends MeshTxBuilderCore {
3781
3807
  );
3782
3808
  };
3783
3809
  sortTxParts = () => {
3810
+ this.sortInputs();
3811
+ this.sortMints();
3812
+ this.sortWithdrawals();
3813
+ this.sortVotes();
3814
+ };
3815
+ sortInputs = () => {
3784
3816
  this.meshTxBuilderBody.inputs.sort((a, b) => {
3785
3817
  if (a.txIn.txHash < b.txIn.txHash) return -1;
3786
3818
  if (a.txIn.txHash > b.txIn.txHash) return 1;
@@ -3788,12 +3820,97 @@ var MeshTxBuilder = class _MeshTxBuilder extends MeshTxBuilderCore {
3788
3820
  if (a.txIn.txIndex > b.txIn.txIndex) return 1;
3789
3821
  return 0;
3790
3822
  });
3823
+ };
3824
+ sortMints = () => {
3791
3825
  this.meshTxBuilderBody.mints.sort((a, b) => {
3792
3826
  if (a.policyId < b.policyId) return -1;
3793
3827
  if (a.policyId > b.policyId) return 1;
3794
3828
  return 0;
3795
3829
  });
3796
3830
  };
3831
+ compareCredentials = (credentialA, credentialB) => {
3832
+ if (credentialA.type === import_core_cst3.CredentialType.ScriptHash && credentialB.type === import_core_cst3.CredentialType.KeyHash) {
3833
+ return -1;
3834
+ }
3835
+ if (credentialA.type === import_core_cst3.CredentialType.KeyHash && credentialB.type === import_core_cst3.CredentialType.ScriptHash) {
3836
+ return 1;
3837
+ }
3838
+ if (credentialA.type === credentialB.type) {
3839
+ if (credentialA.hash < credentialB.hash) return -1;
3840
+ if (credentialA.hash > credentialB.hash) return 1;
3841
+ return 0;
3842
+ }
3843
+ return 0;
3844
+ };
3845
+ sortWithdrawals = () => {
3846
+ this.meshTxBuilderBody.withdrawals.sort((a, b) => {
3847
+ const credentialA = import_core_cst3.Address.fromString(a.address)?.asReward()?.getPaymentCredential();
3848
+ const credentialB = import_core_cst3.Address.fromString(b.address)?.asReward()?.getPaymentCredential();
3849
+ if (credentialA && credentialB) {
3850
+ return this.compareCredentials(credentialA, credentialB);
3851
+ }
3852
+ return 0;
3853
+ });
3854
+ };
3855
+ sortVotes = () => {
3856
+ const variantOrder = {
3857
+ ConstitutionalCommittee: 0,
3858
+ DRep: 1,
3859
+ StakingPool: 2
3860
+ };
3861
+ this.meshTxBuilderBody.votes.sort((a, b) => {
3862
+ const voterA = a.vote.voter;
3863
+ const voterB = b.vote.voter;
3864
+ const orderA = variantOrder[voterA.type];
3865
+ const orderB = variantOrder[voterB.type];
3866
+ if (orderA !== orderB) return orderA - orderB;
3867
+ if (voterA.type === "ConstitutionalCommittee" && voterB.type === "ConstitutionalCommittee") {
3868
+ const credA = voterA.hotCred;
3869
+ const credB = voterB.hotCred;
3870
+ if (credA.type === "ScriptHash" && credB.type === "KeyHash") {
3871
+ return -1;
3872
+ }
3873
+ if (credA.type === "KeyHash" && credB.type === "ScriptHash") {
3874
+ return 1;
3875
+ }
3876
+ if (credA.type === credB.type) {
3877
+ const hashA = credA.type === "KeyHash" ? credA.keyHash : credA.scriptHash;
3878
+ const hashB = credB.type === "KeyHash" ? credB.keyHash : credB.scriptHash;
3879
+ if (hashA < hashB) return -1;
3880
+ if (hashA > hashB) return 1;
3881
+ return 0;
3882
+ }
3883
+ return 0;
3884
+ }
3885
+ if (voterA.type === "DRep" && voterB.type === "DRep") {
3886
+ const drepA = (0, import_core_cst3.toDRep)(voterA.drepId);
3887
+ const drepB = (0, import_core_cst3.toDRep)(voterB.drepId);
3888
+ const scriptHashA = drepA.toScriptHash();
3889
+ const scriptHashB = drepB.toScriptHash();
3890
+ const keyHashA = drepA.toKeyHash();
3891
+ const keyHashB = drepB.toKeyHash();
3892
+ if (scriptHashA != null && scriptHashB != null) {
3893
+ if (scriptHashA < scriptHashB) return -1;
3894
+ if (scriptHashA > scriptHashB) return 1;
3895
+ return 0;
3896
+ }
3897
+ if (scriptHashA != null) return -1;
3898
+ if (scriptHashB != null) return 1;
3899
+ if (keyHashA != null && keyHashB != null) {
3900
+ if (keyHashA < keyHashB) return -1;
3901
+ if (keyHashA > keyHashB) return 1;
3902
+ return 0;
3903
+ }
3904
+ return 0;
3905
+ }
3906
+ if (voterA.type === "StakingPool" && voterB.type === "StakingPool") {
3907
+ if (voterA.keyHash < voterB.keyHash) return -1;
3908
+ if (voterA.keyHash > voterB.keyHash) return 1;
3909
+ return 0;
3910
+ }
3911
+ return 0;
3912
+ });
3913
+ };
3797
3914
  evaluateRedeemers = async () => {
3798
3915
  let txHex = this.serializer.serializeTxBody(
3799
3916
  this.meshTxBuilderBody,
@@ -3893,6 +4010,9 @@ var MeshTxBuilder = class _MeshTxBuilder extends MeshTxBuilderCore {
3893
4010
  completeUnbalancedSync = (customizedTx) => {
3894
4011
  if (customizedTx) {
3895
4012
  this.meshTxBuilderBody = customizedTx;
4013
+ if (customizedTx.fee) {
4014
+ this.setFee(customizedTx.fee);
4015
+ }
3896
4016
  } else {
3897
4017
  this.queueAllLastItem();
3898
4018
  }
@@ -4192,6 +4312,23 @@ var MeshTxBuilder = class _MeshTxBuilder extends MeshTxBuilderCore {
4192
4312
  this.addUtxosFromSelection();
4193
4313
  this.sortTxParts();
4194
4314
  };
4315
+ sanitizeOutputs = async () => {
4316
+ this.meshTxBuilderBody.outputs.forEach((output) => {
4317
+ let lovelaceFound = false;
4318
+ output.amount.forEach((asset) => {
4319
+ if (asset.unit === "lovelace" || asset.unit === "") {
4320
+ lovelaceFound = true;
4321
+ }
4322
+ });
4323
+ if (!lovelaceFound) {
4324
+ const minAda = this.calculateMinLovelaceForOutput(output);
4325
+ output.amount.push({
4326
+ unit: "lovelace",
4327
+ quantity: minAda.toString()
4328
+ });
4329
+ }
4330
+ });
4331
+ };
4195
4332
  collectAllRequiredSignatures = () => {
4196
4333
  const { paymentCreds, byronAddresses } = this.getInputsRequiredSignatures();
4197
4334
  const withdrawalCreds = this.getWithdrawalRequiredSignatures();
@@ -4278,7 +4415,7 @@ var MeshTxBuilder = class _MeshTxBuilder extends MeshTxBuilderCore {
4278
4415
  }
4279
4416
  } else if (certType.type === "RetirePool") {
4280
4417
  certCreds.add(certType.poolId);
4281
- } else if (certType.type === "DRepRegistration") {
4418
+ } else if (certType.type === "DRepRegistration" || certType.type === "DRepDeregistration" || certType.type === "DRepUpdate") {
4282
4419
  if (cert.type === "BasicCertificate") {
4283
4420
  const cstDrep = (0, import_core_cst3.toDRep)(certType.drepId);
4284
4421
  const keyHash = cstDrep.toKeyHash();
@@ -4291,7 +4428,7 @@ var MeshTxBuilder = class _MeshTxBuilder extends MeshTxBuilderCore {
4291
4428
  certCreds.add(pubKey);
4292
4429
  }
4293
4430
  }
4294
- } else if (certType.type === "StakeRegistrationAndDelegation" || certType.type === "VoteRegistrationAndDelegation" || certType.type === "StakeVoteRegistrationAndDelegation" || certType.type === "DeregisterStake") {
4431
+ } else if (certType.type === "StakeRegistrationAndDelegation" || certType.type === "VoteRegistrationAndDelegation" || certType.type === "StakeVoteRegistrationAndDelegation" || certType.type === "VoteDelegation" || certType.type === "RegisterStake" || certType.type === "StakeAndVoteDelegation" || certType.type === "DelegateStake" || certType.type === "DeregisterStake") {
4295
4432
  if (cert.type === "BasicCertificate") {
4296
4433
  const address = import_core_cst3.Address.fromString(certType.stakeKeyAddress);
4297
4434
  if (address) {
@@ -4786,6 +4923,13 @@ var MeshTxBuilder = class _MeshTxBuilder extends MeshTxBuilderCore {
4786
4923
  getSerializedSize = () => {
4787
4924
  return this.serializeMockTx().length / 2;
4788
4925
  };
4926
+ getActualFee = () => {
4927
+ if (this.manualFee) {
4928
+ return BigInt(this.manualFee);
4929
+ } else {
4930
+ return this.calculateFee();
4931
+ }
4932
+ };
4789
4933
  calculateFee = () => {
4790
4934
  const txSize = this.getSerializedSize();
4791
4935
  return this.calculateFeeForSerializedTx(txSize);
@@ -4822,7 +4966,7 @@ var MeshTxBuilder = class _MeshTxBuilder extends MeshTxBuilderCore {
4822
4966
  this.serializer.serializeOutput(currentOutput).length / 2
4823
4967
  );
4824
4968
  const txOutByteCost = BigInt(this._protocolParams.coinsPerUtxoSize);
4825
- const totalOutCost = 160n + BigInt(txOutSize) * txOutByteCost;
4969
+ const totalOutCost = (160n + BigInt(txOutSize)) * txOutByteCost;
4826
4970
  minAda = totalOutCost;
4827
4971
  if (lovelace < totalOutCost) {
4828
4972
  lovelace = totalOutCost;
@@ -4904,7 +5048,7 @@ var setLoveLace = (output, lovelace) => {
4904
5048
  };
4905
5049
  var getLovelace = (output) => {
4906
5050
  for (let asset of output.amount) {
4907
- if (asset.unit === "lovelace") {
5051
+ if (asset.unit === "lovelace" || asset.unit === "") {
4908
5052
  return BigInt(asset.quantity);
4909
5053
  }
4910
5054
  }
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { UTxO, TxOutput, Action, Protocol, MintItem, TxIn, Withdrawal, Vote, PubKeyTxIn, RefTxIn, MeshTxBuilderBody, Asset, BuilderData, LanguageVersion, Voter, VotingProcedure, PoolParams, Anchor, DRep, Metadatum, Network, Redeemer, IFetcher, ISubmitter, IEvaluator, IMeshTxSerializer, ScriptSource, SimpleScriptSourceInfo, Certificate, MintParam, Output, NativeScript as NativeScript$1, IInitiator, Recipient, Token, PlutusScript, Budget, Data, Mint } from '@meshsdk/common';
2
- import { NativeScript } from '@meshsdk/core-cst';
2
+ import { CredentialCore, NativeScript } from '@meshsdk/core-cst';
3
3
 
4
4
  interface TransactionPrototype {
5
5
  newInputs: Set<UTxO>;
@@ -20,6 +20,7 @@ declare class MeshTxBuilderCore {
20
20
  private plutusWithdrawalScriptVersion;
21
21
  private addingPlutusVote;
22
22
  private plutusVoteScriptVersion;
23
+ protected manualFee: string | undefined;
23
24
  protected _protocolParams: Protocol;
24
25
  protected mintItem?: MintItem;
25
26
  protected txInQueueItem?: TxIn;
@@ -484,6 +485,19 @@ declare class MeshTxBuilderCore {
484
485
  * @returns The MeshTxBuilder instance
485
486
  */
486
487
  setFee: (fee: string) => this;
488
+ /**
489
+ * Sets a total collateral for the transaction to use, a collateral return
490
+ * will be generated to either the change address or the specified collateral return address
491
+ * @param collateral The specified collateral
492
+ * @returns The MeshTxBuilder instance
493
+ */
494
+ setTotalCollateral: (collateral: string) => this;
495
+ /**
496
+ * Sets the collateral return address, if none is set, the change address will be used
497
+ * @param address The address to use for collateral return
498
+ * @returns The MeshTxBuilder instance
499
+ */
500
+ setCollateralReturnAddress: (address: string) => this;
487
501
  /**
488
502
  * Sets the network to use, this is mainly to know the cost models to be used to calculate script integrity hash
489
503
  * @param network The specific network this transaction is being built for ("testnet" | "preview" | "preprod" | "mainnet")
@@ -568,6 +582,11 @@ declare class MeshTxBuilder extends MeshTxBuilderCore {
568
582
  updateByTxPrototype: (selectionSkeleton: TransactionPrototype, final?: boolean) => Promise<void>;
569
583
  getUtxosForSelection: () => Promise<UTxO[]>;
570
584
  sortTxParts: () => void;
585
+ sortInputs: () => void;
586
+ sortMints: () => void;
587
+ protected compareCredentials: (credentialA: CredentialCore, credentialB: CredentialCore) => number;
588
+ sortWithdrawals: () => void;
589
+ sortVotes: () => void;
571
590
  evaluateRedeemers: () => Promise<void>;
572
591
  protected getRedeemerCosts: () => Omit<Action, "data">[];
573
592
  /**
@@ -604,6 +623,7 @@ declare class MeshTxBuilder extends MeshTxBuilderCore {
604
623
  protected isSimpleRefScriptInfoComplete: (simpleScriptSource: SimpleScriptSourceInfo) => boolean;
605
624
  protected completeSerialization: (customizedTx?: Partial<MeshTxBuilderBody>) => Promise<string>;
606
625
  protected completeTxParts: () => Promise<void>;
626
+ protected sanitizeOutputs: () => Promise<void>;
607
627
  protected collectAllRequiredSignatures: () => {
608
628
  keyHashes: Set<string>;
609
629
  byronAddresses: Set<string>;
@@ -641,6 +661,7 @@ declare class MeshTxBuilder extends MeshTxBuilderCore {
641
661
  stepUnits: bigint;
642
662
  };
643
663
  getSerializedSize: () => number;
664
+ getActualFee: () => bigint;
644
665
  calculateFee: () => bigint;
645
666
  calculateFeeForSerializedTx: (txSize: number) => bigint;
646
667
  calculateRefScriptFee: () => bigint;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { UTxO, TxOutput, Action, Protocol, MintItem, TxIn, Withdrawal, Vote, PubKeyTxIn, RefTxIn, MeshTxBuilderBody, Asset, BuilderData, LanguageVersion, Voter, VotingProcedure, PoolParams, Anchor, DRep, Metadatum, Network, Redeemer, IFetcher, ISubmitter, IEvaluator, IMeshTxSerializer, ScriptSource, SimpleScriptSourceInfo, Certificate, MintParam, Output, NativeScript as NativeScript$1, IInitiator, Recipient, Token, PlutusScript, Budget, Data, Mint } from '@meshsdk/common';
2
- import { NativeScript } from '@meshsdk/core-cst';
2
+ import { CredentialCore, NativeScript } from '@meshsdk/core-cst';
3
3
 
4
4
  interface TransactionPrototype {
5
5
  newInputs: Set<UTxO>;
@@ -20,6 +20,7 @@ declare class MeshTxBuilderCore {
20
20
  private plutusWithdrawalScriptVersion;
21
21
  private addingPlutusVote;
22
22
  private plutusVoteScriptVersion;
23
+ protected manualFee: string | undefined;
23
24
  protected _protocolParams: Protocol;
24
25
  protected mintItem?: MintItem;
25
26
  protected txInQueueItem?: TxIn;
@@ -484,6 +485,19 @@ declare class MeshTxBuilderCore {
484
485
  * @returns The MeshTxBuilder instance
485
486
  */
486
487
  setFee: (fee: string) => this;
488
+ /**
489
+ * Sets a total collateral for the transaction to use, a collateral return
490
+ * will be generated to either the change address or the specified collateral return address
491
+ * @param collateral The specified collateral
492
+ * @returns The MeshTxBuilder instance
493
+ */
494
+ setTotalCollateral: (collateral: string) => this;
495
+ /**
496
+ * Sets the collateral return address, if none is set, the change address will be used
497
+ * @param address The address to use for collateral return
498
+ * @returns The MeshTxBuilder instance
499
+ */
500
+ setCollateralReturnAddress: (address: string) => this;
487
501
  /**
488
502
  * Sets the network to use, this is mainly to know the cost models to be used to calculate script integrity hash
489
503
  * @param network The specific network this transaction is being built for ("testnet" | "preview" | "preprod" | "mainnet")
@@ -568,6 +582,11 @@ declare class MeshTxBuilder extends MeshTxBuilderCore {
568
582
  updateByTxPrototype: (selectionSkeleton: TransactionPrototype, final?: boolean) => Promise<void>;
569
583
  getUtxosForSelection: () => Promise<UTxO[]>;
570
584
  sortTxParts: () => void;
585
+ sortInputs: () => void;
586
+ sortMints: () => void;
587
+ protected compareCredentials: (credentialA: CredentialCore, credentialB: CredentialCore) => number;
588
+ sortWithdrawals: () => void;
589
+ sortVotes: () => void;
571
590
  evaluateRedeemers: () => Promise<void>;
572
591
  protected getRedeemerCosts: () => Omit<Action, "data">[];
573
592
  /**
@@ -604,6 +623,7 @@ declare class MeshTxBuilder extends MeshTxBuilderCore {
604
623
  protected isSimpleRefScriptInfoComplete: (simpleScriptSource: SimpleScriptSourceInfo) => boolean;
605
624
  protected completeSerialization: (customizedTx?: Partial<MeshTxBuilderBody>) => Promise<string>;
606
625
  protected completeTxParts: () => Promise<void>;
626
+ protected sanitizeOutputs: () => Promise<void>;
607
627
  protected collectAllRequiredSignatures: () => {
608
628
  keyHashes: Set<string>;
609
629
  byronAddresses: Set<string>;
@@ -641,6 +661,7 @@ declare class MeshTxBuilder extends MeshTxBuilderCore {
641
661
  stepUnits: bigint;
642
662
  };
643
663
  getSerializedSize: () => number;
664
+ getActualFee: () => bigint;
644
665
  calculateFee: () => bigint;
645
666
  calculateFeeForSerializedTx: (txSize: number) => bigint;
646
667
  calculateRefScriptFee: () => bigint;
package/dist/index.js CHANGED
@@ -1838,6 +1838,7 @@ var MeshTxBuilderCore = class {
1838
1838
  plutusWithdrawalScriptVersion;
1839
1839
  addingPlutusVote = false;
1840
1840
  plutusVoteScriptVersion;
1841
+ manualFee;
1841
1842
  _protocolParams = DEFAULT_PROTOCOL_PARAMETERS;
1842
1843
  mintItem;
1843
1844
  txInQueueItem;
@@ -3073,9 +3074,29 @@ var MeshTxBuilderCore = class {
3073
3074
  * @returns The MeshTxBuilder instance
3074
3075
  */
3075
3076
  setFee = (fee) => {
3077
+ this.manualFee = fee;
3076
3078
  this.meshTxBuilderBody.fee = fee;
3077
3079
  return this;
3078
3080
  };
3081
+ /**
3082
+ * Sets a total collateral for the transaction to use, a collateral return
3083
+ * will be generated to either the change address or the specified collateral return address
3084
+ * @param collateral The specified collateral
3085
+ * @returns The MeshTxBuilder instance
3086
+ */
3087
+ setTotalCollateral = (collateral) => {
3088
+ this.meshTxBuilderBody.totalCollateral = collateral;
3089
+ return this;
3090
+ };
3091
+ /**
3092
+ * Sets the collateral return address, if none is set, the change address will be used
3093
+ * @param address The address to use for collateral return
3094
+ * @returns The MeshTxBuilder instance
3095
+ */
3096
+ setCollateralReturnAddress = (address) => {
3097
+ this.meshTxBuilderBody.collateralReturnAddress = address;
3098
+ return this;
3099
+ };
3079
3100
  /**
3080
3101
  * Sets the network to use, this is mainly to know the cost models to be used to calculate script integrity hash
3081
3102
  * @param network The specific network this transaction is being built for ("testnet" | "preview" | "preprod" | "mainnet")
@@ -3512,6 +3533,7 @@ var MeshTxBuilderCore = class {
3512
3533
  newBuilder.voteItem = this.voteItem ? structuredClone(this.voteItem) : void 0;
3513
3534
  newBuilder.collateralQueueItem = this.collateralQueueItem ? structuredClone(this.collateralQueueItem) : void 0;
3514
3535
  newBuilder.refScriptTxInQueueItem = this.refScriptTxInQueueItem ? structuredClone(this.refScriptTxInQueueItem) : void 0;
3536
+ newBuilder.manualFee = this.manualFee;
3515
3537
  return newBuilder;
3516
3538
  }
3517
3539
  };
@@ -3617,6 +3639,9 @@ var MeshTxBuilder = class _MeshTxBuilder extends MeshTxBuilderCore {
3617
3639
  complete = async (customizedTx) => {
3618
3640
  if (customizedTx) {
3619
3641
  this.meshTxBuilderBody = { ...this.meshTxBuilderBody, ...customizedTx };
3642
+ if (customizedTx.fee) {
3643
+ this.setFee(customizedTx.fee);
3644
+ }
3620
3645
  } else {
3621
3646
  this.queueAllLastItem();
3622
3647
  }
@@ -3636,11 +3661,12 @@ var MeshTxBuilder = class _MeshTxBuilder extends MeshTxBuilderCore {
3636
3661
  collateral.txIn.scriptSize = 0;
3637
3662
  }
3638
3663
  await this.completeTxParts();
3639
- this.sortTxParts();
3664
+ await this.sanitizeOutputs();
3640
3665
  const txPrototype = await this.selectUtxos();
3641
3666
  await this.updateByTxPrototype(txPrototype, true);
3642
3667
  this.queueAllLastItem();
3643
3668
  this.removeDuplicateInputs();
3669
+ this.sortTxParts();
3644
3670
  if (this.verbose) {
3645
3671
  console.log(
3646
3672
  "txBodyJson - after coin selection",
@@ -3679,7 +3705,7 @@ var MeshTxBuilder = class _MeshTxBuilder extends MeshTxBuilderCore {
3679
3705
  throw new Error(`Evaluate redeemers failed: ${String(error)}`);
3680
3706
  }
3681
3707
  }
3682
- const fee = clonedBuilder.calculateFee();
3708
+ const fee = clonedBuilder.getActualFee();
3683
3709
  const redeemers = clonedBuilder.getRedeemerCosts();
3684
3710
  return {
3685
3711
  fee,
@@ -3742,7 +3768,7 @@ var MeshTxBuilder = class _MeshTxBuilder extends MeshTxBuilderCore {
3742
3768
  for (let change of selectionSkeleton.change) {
3743
3769
  this.txOut(change.address, change.amount);
3744
3770
  }
3745
- this.meshTxBuilderBody.fee = this.meshTxBuilderBody.fee === "0" ? selectionSkeleton.fee.toString() : this.meshTxBuilderBody.fee;
3771
+ this.meshTxBuilderBody.fee = selectionSkeleton.fee.toString();
3746
3772
  this.updateRedeemer(
3747
3773
  this.meshTxBuilderBody,
3748
3774
  selectionSkeleton.redeemers ?? [],
@@ -3761,6 +3787,12 @@ var MeshTxBuilder = class _MeshTxBuilder extends MeshTxBuilderCore {
3761
3787
  );
3762
3788
  };
3763
3789
  sortTxParts = () => {
3790
+ this.sortInputs();
3791
+ this.sortMints();
3792
+ this.sortWithdrawals();
3793
+ this.sortVotes();
3794
+ };
3795
+ sortInputs = () => {
3764
3796
  this.meshTxBuilderBody.inputs.sort((a, b) => {
3765
3797
  if (a.txIn.txHash < b.txIn.txHash) return -1;
3766
3798
  if (a.txIn.txHash > b.txIn.txHash) return 1;
@@ -3768,12 +3800,97 @@ var MeshTxBuilder = class _MeshTxBuilder extends MeshTxBuilderCore {
3768
3800
  if (a.txIn.txIndex > b.txIn.txIndex) return 1;
3769
3801
  return 0;
3770
3802
  });
3803
+ };
3804
+ sortMints = () => {
3771
3805
  this.meshTxBuilderBody.mints.sort((a, b) => {
3772
3806
  if (a.policyId < b.policyId) return -1;
3773
3807
  if (a.policyId > b.policyId) return 1;
3774
3808
  return 0;
3775
3809
  });
3776
3810
  };
3811
+ compareCredentials = (credentialA, credentialB) => {
3812
+ if (credentialA.type === CstCredentialType.ScriptHash && credentialB.type === CstCredentialType.KeyHash) {
3813
+ return -1;
3814
+ }
3815
+ if (credentialA.type === CstCredentialType.KeyHash && credentialB.type === CstCredentialType.ScriptHash) {
3816
+ return 1;
3817
+ }
3818
+ if (credentialA.type === credentialB.type) {
3819
+ if (credentialA.hash < credentialB.hash) return -1;
3820
+ if (credentialA.hash > credentialB.hash) return 1;
3821
+ return 0;
3822
+ }
3823
+ return 0;
3824
+ };
3825
+ sortWithdrawals = () => {
3826
+ this.meshTxBuilderBody.withdrawals.sort((a, b) => {
3827
+ const credentialA = CstAddress.fromString(a.address)?.asReward()?.getPaymentCredential();
3828
+ const credentialB = CstAddress.fromString(b.address)?.asReward()?.getPaymentCredential();
3829
+ if (credentialA && credentialB) {
3830
+ return this.compareCredentials(credentialA, credentialB);
3831
+ }
3832
+ return 0;
3833
+ });
3834
+ };
3835
+ sortVotes = () => {
3836
+ const variantOrder = {
3837
+ ConstitutionalCommittee: 0,
3838
+ DRep: 1,
3839
+ StakingPool: 2
3840
+ };
3841
+ this.meshTxBuilderBody.votes.sort((a, b) => {
3842
+ const voterA = a.vote.voter;
3843
+ const voterB = b.vote.voter;
3844
+ const orderA = variantOrder[voterA.type];
3845
+ const orderB = variantOrder[voterB.type];
3846
+ if (orderA !== orderB) return orderA - orderB;
3847
+ if (voterA.type === "ConstitutionalCommittee" && voterB.type === "ConstitutionalCommittee") {
3848
+ const credA = voterA.hotCred;
3849
+ const credB = voterB.hotCred;
3850
+ if (credA.type === "ScriptHash" && credB.type === "KeyHash") {
3851
+ return -1;
3852
+ }
3853
+ if (credA.type === "KeyHash" && credB.type === "ScriptHash") {
3854
+ return 1;
3855
+ }
3856
+ if (credA.type === credB.type) {
3857
+ const hashA = credA.type === "KeyHash" ? credA.keyHash : credA.scriptHash;
3858
+ const hashB = credB.type === "KeyHash" ? credB.keyHash : credB.scriptHash;
3859
+ if (hashA < hashB) return -1;
3860
+ if (hashA > hashB) return 1;
3861
+ return 0;
3862
+ }
3863
+ return 0;
3864
+ }
3865
+ if (voterA.type === "DRep" && voterB.type === "DRep") {
3866
+ const drepA = coreToCstDRep(voterA.drepId);
3867
+ const drepB = coreToCstDRep(voterB.drepId);
3868
+ const scriptHashA = drepA.toScriptHash();
3869
+ const scriptHashB = drepB.toScriptHash();
3870
+ const keyHashA = drepA.toKeyHash();
3871
+ const keyHashB = drepB.toKeyHash();
3872
+ if (scriptHashA != null && scriptHashB != null) {
3873
+ if (scriptHashA < scriptHashB) return -1;
3874
+ if (scriptHashA > scriptHashB) return 1;
3875
+ return 0;
3876
+ }
3877
+ if (scriptHashA != null) return -1;
3878
+ if (scriptHashB != null) return 1;
3879
+ if (keyHashA != null && keyHashB != null) {
3880
+ if (keyHashA < keyHashB) return -1;
3881
+ if (keyHashA > keyHashB) return 1;
3882
+ return 0;
3883
+ }
3884
+ return 0;
3885
+ }
3886
+ if (voterA.type === "StakingPool" && voterB.type === "StakingPool") {
3887
+ if (voterA.keyHash < voterB.keyHash) return -1;
3888
+ if (voterA.keyHash > voterB.keyHash) return 1;
3889
+ return 0;
3890
+ }
3891
+ return 0;
3892
+ });
3893
+ };
3777
3894
  evaluateRedeemers = async () => {
3778
3895
  let txHex = this.serializer.serializeTxBody(
3779
3896
  this.meshTxBuilderBody,
@@ -3873,6 +3990,9 @@ var MeshTxBuilder = class _MeshTxBuilder extends MeshTxBuilderCore {
3873
3990
  completeUnbalancedSync = (customizedTx) => {
3874
3991
  if (customizedTx) {
3875
3992
  this.meshTxBuilderBody = customizedTx;
3993
+ if (customizedTx.fee) {
3994
+ this.setFee(customizedTx.fee);
3995
+ }
3876
3996
  } else {
3877
3997
  this.queueAllLastItem();
3878
3998
  }
@@ -4172,6 +4292,23 @@ var MeshTxBuilder = class _MeshTxBuilder extends MeshTxBuilderCore {
4172
4292
  this.addUtxosFromSelection();
4173
4293
  this.sortTxParts();
4174
4294
  };
4295
+ sanitizeOutputs = async () => {
4296
+ this.meshTxBuilderBody.outputs.forEach((output) => {
4297
+ let lovelaceFound = false;
4298
+ output.amount.forEach((asset) => {
4299
+ if (asset.unit === "lovelace" || asset.unit === "") {
4300
+ lovelaceFound = true;
4301
+ }
4302
+ });
4303
+ if (!lovelaceFound) {
4304
+ const minAda = this.calculateMinLovelaceForOutput(output);
4305
+ output.amount.push({
4306
+ unit: "lovelace",
4307
+ quantity: minAda.toString()
4308
+ });
4309
+ }
4310
+ });
4311
+ };
4175
4312
  collectAllRequiredSignatures = () => {
4176
4313
  const { paymentCreds, byronAddresses } = this.getInputsRequiredSignatures();
4177
4314
  const withdrawalCreds = this.getWithdrawalRequiredSignatures();
@@ -4258,7 +4395,7 @@ var MeshTxBuilder = class _MeshTxBuilder extends MeshTxBuilderCore {
4258
4395
  }
4259
4396
  } else if (certType.type === "RetirePool") {
4260
4397
  certCreds.add(certType.poolId);
4261
- } else if (certType.type === "DRepRegistration") {
4398
+ } else if (certType.type === "DRepRegistration" || certType.type === "DRepDeregistration" || certType.type === "DRepUpdate") {
4262
4399
  if (cert.type === "BasicCertificate") {
4263
4400
  const cstDrep = coreToCstDRep(certType.drepId);
4264
4401
  const keyHash = cstDrep.toKeyHash();
@@ -4271,7 +4408,7 @@ var MeshTxBuilder = class _MeshTxBuilder extends MeshTxBuilderCore {
4271
4408
  certCreds.add(pubKey);
4272
4409
  }
4273
4410
  }
4274
- } else if (certType.type === "StakeRegistrationAndDelegation" || certType.type === "VoteRegistrationAndDelegation" || certType.type === "StakeVoteRegistrationAndDelegation" || certType.type === "DeregisterStake") {
4411
+ } else if (certType.type === "StakeRegistrationAndDelegation" || certType.type === "VoteRegistrationAndDelegation" || certType.type === "StakeVoteRegistrationAndDelegation" || certType.type === "VoteDelegation" || certType.type === "RegisterStake" || certType.type === "StakeAndVoteDelegation" || certType.type === "DelegateStake" || certType.type === "DeregisterStake") {
4275
4412
  if (cert.type === "BasicCertificate") {
4276
4413
  const address = CstAddress.fromString(certType.stakeKeyAddress);
4277
4414
  if (address) {
@@ -4766,6 +4903,13 @@ var MeshTxBuilder = class _MeshTxBuilder extends MeshTxBuilderCore {
4766
4903
  getSerializedSize = () => {
4767
4904
  return this.serializeMockTx().length / 2;
4768
4905
  };
4906
+ getActualFee = () => {
4907
+ if (this.manualFee) {
4908
+ return BigInt(this.manualFee);
4909
+ } else {
4910
+ return this.calculateFee();
4911
+ }
4912
+ };
4769
4913
  calculateFee = () => {
4770
4914
  const txSize = this.getSerializedSize();
4771
4915
  return this.calculateFeeForSerializedTx(txSize);
@@ -4802,7 +4946,7 @@ var MeshTxBuilder = class _MeshTxBuilder extends MeshTxBuilderCore {
4802
4946
  this.serializer.serializeOutput(currentOutput).length / 2
4803
4947
  );
4804
4948
  const txOutByteCost = BigInt(this._protocolParams.coinsPerUtxoSize);
4805
- const totalOutCost = 160n + BigInt(txOutSize) * txOutByteCost;
4949
+ const totalOutCost = (160n + BigInt(txOutSize)) * txOutByteCost;
4806
4950
  minAda = totalOutCost;
4807
4951
  if (lovelace < totalOutCost) {
4808
4952
  lovelace = totalOutCost;
@@ -4884,7 +5028,7 @@ var setLoveLace = (output, lovelace) => {
4884
5028
  };
4885
5029
  var getLovelace = (output) => {
4886
5030
  for (let asset of output.amount) {
4887
- if (asset.unit === "lovelace") {
5031
+ if (asset.unit === "lovelace" || asset.unit === "") {
4888
5032
  return BigInt(asset.quantity);
4889
5033
  }
4890
5034
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meshsdk/transaction",
3
- "version": "1.9.0-beta-38",
3
+ "version": "1.9.0-beta-40",
4
4
  "description": "Transactions - https://meshjs.dev/apis/transaction",
5
5
  "main": "./dist/index.cjs",
6
6
  "browser": "./dist/index.js",
@@ -35,8 +35,8 @@
35
35
  "typescript": "^5.3.3"
36
36
  },
37
37
  "dependencies": {
38
- "@meshsdk/common": "1.9.0-beta-38",
39
- "@meshsdk/core-cst": "1.9.0-beta-38",
38
+ "@meshsdk/common": "1.9.0-beta-40",
39
+ "@meshsdk/core-cst": "1.9.0-beta-40",
40
40
  "@cardano-sdk/core": "^0.45.5",
41
41
  "@cardano-sdk/util": "^0.15.5",
42
42
  "@cardano-sdk/input-selection": "^0.13.33",