From 6e157f0235ef93e4b2a87d3525726f237d12365e Mon Sep 17 00:00:00 2001 From: "Emmanuel .A" Date: Sat, 14 Mar 2026 00:27:05 +0100 Subject: [PATCH 1/7] feat(tx builder): transaction builder interface V2 --- .../transaction-builder-v2/builder-core.ts | 94 +++++ .../src/types/transaction-builder-v2/index.ts | 5 + .../src/types/transaction-builder-v2/mint.ts | 25 ++ .../src/types/transaction-builder-v2/spend.ts | 32 ++ .../src/types/transaction-builder-v2/vote.ts | 22 ++ .../transaction-builder-v2/withdrawal.ts | 22 ++ .../src/types/transaction-builder/index.ts | 3 +- .../src/mesh-builder-v2/index.ts | 360 ++++++++++++++++++ .../src/mesh-tx-builder/index.ts | 1 + .../src/mesh-tx-builder/tx-builder-core.ts | 11 +- .../test/mesh-tx-builder-v2.test.ts | 138 +++++++ 11 files changed, 708 insertions(+), 5 deletions(-) create mode 100644 packages/mesh-common/src/types/transaction-builder-v2/builder-core.ts create mode 100644 packages/mesh-common/src/types/transaction-builder-v2/index.ts create mode 100644 packages/mesh-common/src/types/transaction-builder-v2/mint.ts create mode 100644 packages/mesh-common/src/types/transaction-builder-v2/spend.ts create mode 100644 packages/mesh-common/src/types/transaction-builder-v2/vote.ts create mode 100644 packages/mesh-common/src/types/transaction-builder-v2/withdrawal.ts create mode 100644 packages/mesh-transaction/src/mesh-builder-v2/index.ts create mode 100644 packages/mesh-transaction/test/mesh-tx-builder-v2.test.ts diff --git a/packages/mesh-common/src/types/transaction-builder-v2/builder-core.ts b/packages/mesh-common/src/types/transaction-builder-v2/builder-core.ts new file mode 100644 index 000000000..d9c764821 --- /dev/null +++ b/packages/mesh-common/src/types/transaction-builder-v2/builder-core.ts @@ -0,0 +1,94 @@ +import { MeshTxBuilder, RefTxIn, Voter, VotingProcedure } from "@meshsdk/core"; +import { SpendRedeemerBuilder } from "./spend"; +import { MintRedeemerBuilder } from "./mint"; +import { WithdrawRedeemerBuilder } from "./withdrawal"; +import { VoteRedeemerBuilder } from "./vote"; + +export interface _MeshTxBuilderV2 + extends Omit { + spendPlutusV1(txHash: string, txIndex: number): SpendRedeemerBuilder; + spendPlutusV2(txHash: string, txIndex: number): SpendRedeemerBuilder; + spendPlutusV3(txHash: string, txIndex: number): SpendRedeemerBuilder; + + mintPlutusV1( + quantity: string, + policyId: string, + assetName: string, + ): MintRedeemerBuilder; + mintPlutusV2( + quantity: string, + policyId: string, + assetName: string, + ): MintRedeemerBuilder; + mintPlutusV3( + quantity: string, + policyId: string, + assetName: string, + ): MintRedeemerBuilder; + + withdrawPlutusV1( + rewardAddress: string, + amount: string, + ): WithdrawRedeemerBuilder; + withdrawPlutusV2( + rewardAddress: string, + amount: string, + ): WithdrawRedeemerBuilder; + withdrawPlutusV3( + rewardAddress: string, + amount: string, + ): WithdrawRedeemerBuilder; + + votePlutusV1( + voter: Voter, + govActionId: RefTxIn, + votingProcedure: VotingProcedure, + ): VoteRedeemerBuilder; + votePlutusV2( + voter: Voter, + govActionId: RefTxIn, + votingProcedure: VotingProcedure, + ): VoteRedeemerBuilder; + votePlutusV3( + voter: Voter, + govActionId: RefTxIn, + votingProcedure: VotingProcedure, + ): VoteRedeemerBuilder; +} + +type ScriptMethodsToDrop = + | "spendingPlutusScript" + | "spendingPlutusScriptV1" + | "spendingPlutusScriptV2" + | "spendingPlutusScriptV3" + | "spendingTxInReference" + | "spendingReferenceTxInInlineDatumPresent" + | "spendingReferenceTxInRedeemerValue" + | "mintPlutusScript" + | "mintPlutusScriptV1" + | "mintPlutusScriptV2" + | "mintPlutusScriptV3" + | "mintingScript" + | "mintTxInReference" + | "mintReferenceTxInRedeemerValue" + | "mintRedeemerValue" + | "withdrawalPlutusScript" + | "withdrawalPlutusScriptV1" + | "withdrawalPlutusScriptV2" + | "withdrawalPlutusScriptV3" + | "withdrawalScript" + | "withdrawalTxInReference" + | "withdrawalReferenceTxInRedeemerValue" + | "withdrawalRedeemerValue" + | "votePlutusScript" + | "votePlutusScriptV1" + | "votePlutusScriptV2" + | "votePlutusScriptV3" + | "voteScript" + | "voteTxInReference" + | "voteReferenceTxInRedeemerValue" + | "voteRedeemerValue" + | "txInScript" + | "txInDatumValue" + | "txInInlineDatumPresent" + | "txInRedeemerValue"; diff --git a/packages/mesh-common/src/types/transaction-builder-v2/index.ts b/packages/mesh-common/src/types/transaction-builder-v2/index.ts new file mode 100644 index 000000000..58cb915ea --- /dev/null +++ b/packages/mesh-common/src/types/transaction-builder-v2/index.ts @@ -0,0 +1,5 @@ +export * from './builder-core'; +export * from './mint'; +export * from './spend'; +export * from './vote'; +export * from './withdrawal' \ No newline at end of file diff --git a/packages/mesh-common/src/types/transaction-builder-v2/mint.ts b/packages/mesh-common/src/types/transaction-builder-v2/mint.ts new file mode 100644 index 000000000..d6083b8bf --- /dev/null +++ b/packages/mesh-common/src/types/transaction-builder-v2/mint.ts @@ -0,0 +1,25 @@ +import { Asset, Budget, BuilderData } from "@meshsdk/core"; +import { _MeshTxBuilderV2 } from "./builder-core"; + +export interface MintRedeemerBuilder { + redeemerJson( + redeemer: BuilderData["content"], + exUnits?: Budget, + ): MintScriptBuilder; + redeemerCbor( + redeemer: BuilderData["content"], + exUnits?: Budget, + ): MintScriptBuilder; + } + export interface MintScriptBuilder { + script(scriptCbor: string): MintTxOutBuilder; + referenceScript( + txHash: string, + txIndex: number, + scriptSize?: string, + scriptHash?: string, + ): MintTxOutBuilder; + } + export interface MintTxOutBuilder { + txOut(address: string, amount: Asset[]): _MeshTxBuilderV2; + } \ No newline at end of file diff --git a/packages/mesh-common/src/types/transaction-builder-v2/spend.ts b/packages/mesh-common/src/types/transaction-builder-v2/spend.ts new file mode 100644 index 000000000..e1acfba09 --- /dev/null +++ b/packages/mesh-common/src/types/transaction-builder-v2/spend.ts @@ -0,0 +1,32 @@ +import { Asset, Budget, BuilderData } from "@meshsdk/core"; +import { _MeshTxBuilderV2 } from "./builder-core"; + +export interface SpendRedeemerBuilder { + redeemerJson( + redeemer: BuilderData["content"], + exUnits?: Budget, + ): SpendScriptBuilder; + redeemerCbor( + redeemer: BuilderData["content"], + exUnits?: Budget, + ): SpendScriptBuilder; + } + + export interface SpendScriptBuilder { + script(scriptCbor: string): SpendDatumBuilder; + referenceScript( + refTxHash: string, + refTxIndex: number, + scriptSize?: string, + scriptHash?: string, + ): SpendDatumBuilder; + } + export interface SpendDatumBuilder { + datumHash(datumHash: string): SpendTxOutBuilder; + datumCbor(datumCbor: BuilderData["content"]): SpendTxOutBuilder; + datumJson(datumJson: BuilderData["content"]): SpendTxOutBuilder; + } + + export interface SpendTxOutBuilder { + txOut(address: string, amount: Asset[]): _MeshTxBuilderV2; + } \ No newline at end of file diff --git a/packages/mesh-common/src/types/transaction-builder-v2/vote.ts b/packages/mesh-common/src/types/transaction-builder-v2/vote.ts new file mode 100644 index 000000000..8163d86e2 --- /dev/null +++ b/packages/mesh-common/src/types/transaction-builder-v2/vote.ts @@ -0,0 +1,22 @@ +import { Budget, BuilderData } from "@meshsdk/core"; +import { _MeshTxBuilderV2 } from "./builder-core"; + +export interface VoteRedeemerBuilder { + redeemerJson( + redeemer: BuilderData["content"], + exUnits?: Budget, + ): VoteScriptBuilder; + redeemerCbor( + redeemer: BuilderData["content"], + exUnits?: Budget, + ): VoteScriptBuilder; +} +export interface VoteScriptBuilder { + script(scriptCbor: string): _MeshTxBuilderV2; + referenceScript( + txHash: string, + txIndex: number, + scriptSize?: string, + scriptHash?: string, + ): _MeshTxBuilderV2; +} diff --git a/packages/mesh-common/src/types/transaction-builder-v2/withdrawal.ts b/packages/mesh-common/src/types/transaction-builder-v2/withdrawal.ts new file mode 100644 index 000000000..a4760ed44 --- /dev/null +++ b/packages/mesh-common/src/types/transaction-builder-v2/withdrawal.ts @@ -0,0 +1,22 @@ +import { Budget, BuilderData } from "@meshsdk/core"; +import { _MeshTxBuilderV2 } from "./builder-core"; + +export interface WithdrawRedeemerBuilder { + redeemerJson( + redeemer: BuilderData["content"], + exUnits?: Budget, + ): WithdrawScriptBuilder; + redeemerCbor( + redeemer: BuilderData["content"], + exUnits?: Budget, + ): WithdrawScriptBuilder; +} +export interface WithdrawScriptBuilder { + script(scriptCbor: string): _MeshTxBuilderV2; + referenceScript( + txHash: string, + txIndex: number, + scriptSize?: string, + scriptHash?: string, + ): _MeshTxBuilderV2; +} \ No newline at end of file diff --git a/packages/mesh-common/src/types/transaction-builder/index.ts b/packages/mesh-common/src/types/transaction-builder/index.ts index b03e62d93..df79ae535 100644 --- a/packages/mesh-common/src/types/transaction-builder/index.ts +++ b/packages/mesh-common/src/types/transaction-builder/index.ts @@ -19,6 +19,7 @@ export * from "./withdrawal"; export * from "./certificate"; export * from "./vote"; export * from "./proposal"; +export * from "./tx-builder-v2"; export type MeshTxBuilderBody = { inputs: TxIn[]; @@ -35,7 +36,7 @@ export type MeshTxBuilderBody = { certificates: Certificate[]; withdrawals: Withdrawal[]; votes: Vote[]; - proposals: Proposal[]; + proposals: Proposal[]; signingKey: string[]; extraInputs: UTxO[]; chainedTxs: string[]; diff --git a/packages/mesh-transaction/src/mesh-builder-v2/index.ts b/packages/mesh-transaction/src/mesh-builder-v2/index.ts new file mode 100644 index 000000000..d85fa92f9 --- /dev/null +++ b/packages/mesh-transaction/src/mesh-builder-v2/index.ts @@ -0,0 +1,360 @@ +import type { + _MeshTxBuilderV2, + BuilderData, + MintRedeemerBuilder, + MintScriptBuilder, + MintTxOutBuilder, + RefTxIn, + SpendDatumBuilder, + SpendRedeemerBuilder, + SpendScriptBuilder, + SpendTxOutBuilder, + Voter, + VoteRedeemerBuilder, + VoteScriptBuilder, + VotingProcedure, + WithdrawRedeemerBuilder, + WithdrawScriptBuilder, +} from "@meshsdk/common"; +import { Asset, Budget, DEFAULT_REDEEMER_BUDGET } from "@meshsdk/common"; +import { MeshTxBuilder, MeshTxBuilderOptions } from "@meshsdk/core"; + +import { MeshTxBuilderCore } from "../mesh-tx-builder/tx-builder-core"; + +class SpendBuilderImpl + implements + SpendRedeemerBuilder, + SpendScriptBuilder, + SpendDatumBuilder, + SpendTxOutBuilder +{ + constructor(private readonly core: MeshTxBuilder) {} + + redeemerJson( + redeemer: BuilderData["content"], + exUnits?: Budget, + ): SpendScriptBuilder { + this.core.txInRedeemerValue( + redeemer, + "JSON", + exUnits ?? { ...DEFAULT_REDEEMER_BUDGET }, + ); + return this; + } + + redeemerCbor( + redeemer: BuilderData["content"], + exUnits?: Budget, + ): SpendScriptBuilder { + this.core.txInRedeemerValue( + redeemer, + "CBOR", + exUnits ?? { ...DEFAULT_REDEEMER_BUDGET }, + ); + return this; + } + + script(scriptCbor: string): SpendDatumBuilder { + this.core.txInScript(scriptCbor); + return this; + } + + referenceScript( + refTxHash: string, + refTxIndex: number, + scriptSize?: string, + scriptHash?: string, + ): SpendDatumBuilder { + this.core.spendingTxInReference( + refTxHash, + refTxIndex, + scriptSize, + scriptHash, + ); + return this; + } + + datumJson(datum: BuilderData["content"]): SpendTxOutBuilder { + this.core.txOutInlineDatumValue(datum, "JSON"); + return this; + } + + datumCbor(datum: BuilderData["content"]): SpendTxOutBuilder { + this.core.txOutInlineDatumValue(datum, "CBOR"); + return this; + } + + datumHash(datumHash: string): SpendTxOutBuilder { + this.core.txOutDatumHashValue(datumHash); + return this; + } + + txOut(address: string, amount: Asset[]): _MeshTxBuilderV2 { + this.core.txInInlineDatumPresent(); + this.core.txOut(address, amount); + return this.core as unknown as _MeshTxBuilderV2; + } +} + +class MintBuilderImpl + implements MintRedeemerBuilder, MintScriptBuilder, MintTxOutBuilder +{ + constructor(private readonly core: MeshTxBuilder) {} + + redeemerJson( + redeemer: BuilderData["content"], + exUnits?: Budget, + ): MintScriptBuilder { + this.core.mintRedeemerValue( + redeemer, + "JSON", + exUnits ?? { ...DEFAULT_REDEEMER_BUDGET }, + ); + return this; + } + + redeemerCbor( + redeemer: BuilderData["content"], + exUnits?: Budget, + ): MintScriptBuilder { + this.core.mintRedeemerValue( + redeemer, + "CBOR", + exUnits ?? { ...DEFAULT_REDEEMER_BUDGET }, + ); + return this; + } + + script(scriptCbor: string): MintTxOutBuilder { + this.core.mintingScript(scriptCbor); + return this; + } + + referenceScript( + txHash: string, + txIndex: number, + scriptSize?: string, + scriptHash?: string, + ): MintTxOutBuilder { + this.core.mintTxInReference(txHash, txIndex, scriptSize, scriptHash); + return this; + } + + txOut(address: string, amount: Asset[]): _MeshTxBuilderV2 { + this.core.txOut(address, amount); + return this.core as unknown as _MeshTxBuilderV2; + } +} + +class WithdrawBuilderImpl + implements WithdrawRedeemerBuilder, WithdrawScriptBuilder +{ + constructor(private readonly core: MeshTxBuilder) {} + + redeemerJson( + redeemer: BuilderData["content"], + exUnits?: Budget, + ): WithdrawScriptBuilder { + this.core.withdrawalRedeemerValue( + redeemer, + "JSON", + exUnits ?? { ...DEFAULT_REDEEMER_BUDGET }, + ); + return this; + } + + redeemerCbor( + redeemer: BuilderData["content"], + exUnits?: Budget, + ): WithdrawScriptBuilder { + this.core.withdrawalRedeemerValue( + redeemer, + "CBOR", + exUnits ?? { ...DEFAULT_REDEEMER_BUDGET }, + ); + return this; + } + + script(scriptCbor: string): _MeshTxBuilderV2 { + this.core.withdrawalScript(scriptCbor); + return this.core as unknown as _MeshTxBuilderV2; + } + + referenceScript( + txHash: string, + txIndex: number, + scriptSize?: string, + scriptHash?: string, + ): _MeshTxBuilderV2 { + this.core.withdrawalTxInReference(txHash, txIndex, scriptSize, scriptHash); + return this.core as unknown as _MeshTxBuilderV2; + } +} + +class VoteBuilderImpl implements VoteRedeemerBuilder, VoteScriptBuilder { + constructor(private readonly core: MeshTxBuilder) {} + + redeemerJson( + redeemer: BuilderData["content"], + exUnits?: Budget, + ): VoteScriptBuilder { + this.core.voteRedeemerValue( + redeemer, + "JSON", + exUnits ?? { ...DEFAULT_REDEEMER_BUDGET }, + ); + return this; + } + + redeemerCbor( + redeemer: BuilderData["content"], + exUnits?: Budget, + ): VoteScriptBuilder { + this.core.voteRedeemerValue( + redeemer, + "CBOR", + exUnits ?? { ...DEFAULT_REDEEMER_BUDGET }, + ); + return this; + } + + script(scriptCbor: string): _MeshTxBuilderV2 { + this.core.voteScript(scriptCbor); + return this.core as unknown as _MeshTxBuilderV2; + } + + referenceScript( + txHash: string, + txIndex: number, + scriptSize?: string, + scriptHash?: string, + ): _MeshTxBuilderV2 { + this.core.voteTxInReference(txHash, txIndex, scriptSize, scriptHash); + return this.core as unknown as _MeshTxBuilderV2; + } +} + +class __MeshTxBuilderV2 extends MeshTxBuilder { + spendPlutusV1(txHash: string, txIndex: number): SpendRedeemerBuilder { + this.spendingPlutusScriptV1(); + this.txIn(txHash, txIndex); + return new SpendBuilderImpl(this); + } + spendPlutusV2(txHash: string, txIndex: number): SpendRedeemerBuilder { + this.spendingPlutusScriptV2(); + this.txIn(txHash, txIndex); + return new SpendBuilderImpl(this); + } + spendPlutusV3(txHash: string, txIndex: number): SpendRedeemerBuilder { + this.spendingPlutusScriptV3(); + this.txIn(txHash, txIndex); + return new SpendBuilderImpl(this); + } + + mintPlutusV1( + quantity: string, + policyId: string, + assetName: string, + ): MintRedeemerBuilder { + this.mintPlutusScriptV1(); + this.mint(quantity, policyId, assetName); + return new MintBuilderImpl(this); + } + mintPlutusV2( + quantity: string, + policyId: string, + assetName: string, + ): MintRedeemerBuilder { + this.mintPlutusScriptV2(); + this.mint(quantity, policyId, assetName); + return new MintBuilderImpl(this); + } + mintPlutusV3( + quantity: string, + policyId: string, + assetName: string, + ): MintRedeemerBuilder { + this.mintPlutusScriptV3(); + this.mint(quantity, policyId, assetName); + return new MintBuilderImpl(this); + } + + withdrawPlutusV1( + rewardAddress: string, + coin: string, + ): WithdrawRedeemerBuilder { + this.withdrawalPlutusScriptV1(); + this.withdrawal(rewardAddress, coin); + return new WithdrawBuilderImpl(this); + } + withdrawPlutusV2( + rewardAddress: string, + coin: string, + ): WithdrawRedeemerBuilder { + this.withdrawalPlutusScriptV2(); + this.withdrawal(rewardAddress, coin); + return new WithdrawBuilderImpl(this); + } + withdrawPlutusV3( + rewardAddress: string, + coin: string, + ): WithdrawRedeemerBuilder { + this.withdrawalPlutusScriptV3(); + this.withdrawal(rewardAddress, coin); + return new WithdrawBuilderImpl(this); + } + + votePlutusV1( + voter: Voter, + govActionId: RefTxIn, + votingProcedure: VotingProcedure, + ): VoteRedeemerBuilder { + this.votePlutusScriptV1(); + this.vote(voter, govActionId, votingProcedure); + return new VoteBuilderImpl(this); + } + votePlutusV2( + voter: Voter, + govActionId: RefTxIn, + votingProcedure: VotingProcedure, + ): VoteRedeemerBuilder { + this.votePlutusScriptV2(); + this.vote(voter, govActionId, votingProcedure); + return new VoteBuilderImpl(this); + } + votePlutusV3( + voter: Voter, + govActionId: RefTxIn, + votingProcedure: VotingProcedure, + ): VoteRedeemerBuilder { + this.votePlutusScriptV3(); + this.vote(voter, govActionId, votingProcedure); + return new VoteBuilderImpl(this); + } +} + +/** + * `MeshTxBuilderV2` is a strongly-typed wrapper around the core `MeshTxBuilder` + * that enforces a rigid Type-State machine for Plutus operations. + * + * It natively provides TypeScript autocomplete restrictions (Script -> Datum -> Redeemer) + * for transactions like spending, minting, withdrawing, and voting, dropping standalone + * script methods to prevent incorrect chained execution ordering. + * + * @example + * ```typescript + * const tx = new MeshTxBuilderV2({ + * fetcher: provider, + * evaluator: provider, + * }); + * + * tx.spendPlutusV3(txHash, index) + * .script(scriptCbor) + * .datumJson(datumValue) + * .redeemerJson(redeemerValue) + * .txOut(address, assets); // Drops you back into the main builder methods + * ``` + */ +export const MeshTxBuilderV2: new ( + options?: MeshTxBuilderOptions, +) => _MeshTxBuilderV2 = __MeshTxBuilderV2; diff --git a/packages/mesh-transaction/src/mesh-tx-builder/index.ts b/packages/mesh-transaction/src/mesh-tx-builder/index.ts index b6c6339f5..508a0e7fb 100644 --- a/packages/mesh-transaction/src/mesh-tx-builder/index.ts +++ b/packages/mesh-transaction/src/mesh-tx-builder/index.ts @@ -1878,3 +1878,4 @@ export const getOutputMinLovelace = ( }; export * from "./utils"; +export { MeshTxBuilderV2 } from "../mesh-builder-v2"; diff --git a/packages/mesh-transaction/src/mesh-tx-builder/tx-builder-core.ts b/packages/mesh-transaction/src/mesh-tx-builder/tx-builder-core.ts index 5ba3064ef..aa53f559d 100644 --- a/packages/mesh-transaction/src/mesh-tx-builder/tx-builder-core.ts +++ b/packages/mesh-transaction/src/mesh-tx-builder/tx-builder-core.ts @@ -13,7 +13,6 @@ import { DEFAULT_REDEEMER_BUDGET, DRep, DREP_DEPOSIT, - VOTING_PROPOSAL_DEPOSIT, emptyTxBuilderBody, GovernanceAction, LanguageVersion, @@ -29,8 +28,8 @@ import { PubKeyTxIn, Quantity, Redeemer, - RewardAddress, RefTxIn, + RewardAddress, TxIn, TxInParameter, Unit, @@ -38,6 +37,7 @@ import { UtxoSelection, Vote, Voter, + VOTING_PROPOSAL_DEPOSIT, VotingProcedure, Withdrawal, } from "@meshsdk/common"; @@ -1219,9 +1219,12 @@ export class MeshTxBuilderCore { type: BuilderData["type"] = "Mesh", exUnits = { ...DEFAULT_REDEEMER_BUDGET }, ) => { - if (!this.proposalItem) throw Error("proposalRedeemerValue: Undefined proposal"); + if (!this.proposalItem) + throw Error("proposalRedeemerValue: Undefined proposal"); if (!(this.proposalItem.type === "ScriptProposal")) - throw Error("proposalRedeemerValue: Adding redeemer to non plutus proposal"); + throw Error( + "proposalRedeemerValue: Adding redeemer to non plutus proposal", + ); this.proposalItem.redeemer = this.castBuilderDataToRedeemer( redeemer, type, diff --git a/packages/mesh-transaction/test/mesh-tx-builder-v2.test.ts b/packages/mesh-transaction/test/mesh-tx-builder-v2.test.ts new file mode 100644 index 000000000..422ce67ca --- /dev/null +++ b/packages/mesh-transaction/test/mesh-tx-builder-v2.test.ts @@ -0,0 +1,138 @@ +import { Asset, Budget, LanguageVersion } from "@meshsdk/common"; + +import { MeshTxBuilderV2 } from "../src"; + +describe("MeshTxBuilderV2 Grouped interfaces", () => { + it("should build a tx with spendPlutusV2", () => { + const tx = new MeshTxBuilderV2(); + const mockHash = + "0000000000000000000000000000000000000000000000000000000000000000"; + + tx.spendPlutusV2(mockHash, 0) + .redeemerJson({ action: "spend" }) + .script("112233") + .datumJson({ data: "foo" }) + .txOut( + "addr_test1vzuwvztxzv3j4a2wvy7xntry2a8y869svj4a7y7qy2wvywqzcqxny", + [], + ); + + // @ts-ignore + tx.queueAllLastItem(); + + const body = tx.meshTxBuilderBody; + + // Check we configured script spending correctly + const input = body.inputs[0]; + expect(input?.type).toBe("Script"); + + if (input?.type === "Script") { + expect(input.txIn.txHash).toBe(mockHash); + expect(input.txIn.txIndex).toBe(0); + + // script + expect(input.scriptTxIn.scriptSource?.type).toBe("Provided"); + if (input.scriptTxIn.scriptSource?.type === "Provided") { + expect(input.scriptTxIn.scriptSource?.script.code).toBe("112233"); + expect(input.scriptTxIn.scriptSource?.script.version).toBe("V2"); + } + + // datum + expect(input.scriptTxIn.datumSource?.type).toBe("Inline"); + + // redeemer + expect(input.scriptTxIn.redeemer?.data.type).toBe("JSON"); + } + + // Output + expect(body.outputs.length).toBe(1); + expect(body.outputs[0]?.address).toBe( + "addr_test1vzuwvztxzv3j4a2wvy7xntry2a8y869svj4a7y7qy2wvywqzcqxny", + ); + }); + + it("should have correct mintPlutus interface", () => { + const tx = new MeshTxBuilderV2(); + tx.mintPlutusV2("1", "policyId123", "assetName456") + .redeemerCbor("998877") + .script("556677") + .txOut( + "addr_test1vzuwvztxzv3j4a2wvy7xntry2a8y869svj4a7y7qy2wvywqzcqxny", + [], + ); + + // @ts-ignore + tx.queueAllLastItem(); + + const body = tx.meshTxBuilderBody; + + expect(body.mints[0]?.type).toBe("Plutus"); + expect(body.mints[0]?.policyId).toBe("policyId123"); + expect(body.mints[0]?.mintValue[0]?.amount).toBe("1"); + + if ( + body.mints[0]?.type === "Plutus" && + body.mints[0]?.scriptSource?.type === "Provided" + ) { + expect(body.mints[0]?.scriptSource.script.code).toBe("556677"); + } + + expect(body.mints[0]?.redeemer?.data.type).toBe("CBOR"); + }); + + it("should build a tx with withdrawPlutusV2", () => { + const tx = new MeshTxBuilderV2(); + tx.withdrawPlutusV2("stake_test1uqevw2xnsc0pvn9t9r9c7qryfqfeerchgrlm3ea2nefr9hqp8n5xl", "1000000") + .redeemerJson({ action: "withdraw" }) + .script("445566"); + + // @ts-ignore + tx.queueAllLastItem(); + + const body = tx.meshTxBuilderBody; + + expect(body.withdrawals.length).toBe(1); + expect(body.withdrawals[0]?.type).toBe("ScriptWithdrawal"); + if (body.withdrawals[0]?.type === "ScriptWithdrawal") { + expect(body.withdrawals[0]?.address).toBe("stake_test1uqevw2xnsc0pvn9t9r9c7qryfqfeerchgrlm3ea2nefr9hqp8n5xl"); + expect(body.withdrawals[0]?.coin).toBe("1000000"); + + expect(body.withdrawals[0]?.scriptSource?.type).toBe("Provided"); + if (body.withdrawals[0]?.scriptSource?.type === "Provided") { + expect(body.withdrawals[0]?.scriptSource.script.code).toBe("445566"); + } + + expect(body.withdrawals[0]?.redeemer?.data.type).toBe("JSON"); + } + }); + + it("should build a tx with votePlutusV2", () => { + const tx = new MeshTxBuilderV2(); + tx.votePlutusV2( + { type: "DRep", drepId: "drep_id_here" }, + { txHash: "0000000000000000000000000000000000000000000000000000000000000000", txIndex: 0 }, + { voteKind: "Yes" } + ) + .redeemerJson({ action: "vote" }) + .script("111111"); + + // @ts-ignore + tx.queueAllLastItem(); + + const body = tx.meshTxBuilderBody; + + expect(body.votes.length).toBe(1); + expect(body.votes[0]?.type).toBe("ScriptVote"); + if (body.votes[0]?.type === "ScriptVote") { + expect(body.votes[0]?.vote.voter.type).toBe("DRep"); + expect(body.votes[0]?.vote.votingProcedure.voteKind).toBe("Yes"); + + expect(body.votes[0]?.scriptSource?.type).toBe("Provided"); + if (body.votes[0]?.scriptSource?.type === "Provided") { + expect(body.votes[0]?.scriptSource.script.code).toBe("111111"); + } + + expect(body.votes[0]?.redeemer?.data.type).toBe("JSON"); + } + }); +}); From cd8c8c408c143c152f2b86e0c9e4757e0f266007 Mon Sep 17 00:00:00 2001 From: "Emmanuel .A" Date: Sat, 14 Mar 2026 00:28:07 +0100 Subject: [PATCH 2/7] feat(tx-builder): transaction builder interface v2 --- packages/mesh-common/src/types/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/mesh-common/src/types/index.ts b/packages/mesh-common/src/types/index.ts index ebac87471..a5f59df6e 100644 --- a/packages/mesh-common/src/types/index.ts +++ b/packages/mesh-common/src/types/index.ts @@ -25,3 +25,4 @@ export * from "./transaction-builder"; export * from "./deserialized"; export * from "./blueprint"; export * from "./governance"; +export * from "./transaction-builder-v2"; From acf26fde8bd26559d80c37717f590bad2e38f1dc Mon Sep 17 00:00:00 2001 From: "Emmanuel .A" Date: Tue, 17 Mar 2026 05:06:24 +0100 Subject: [PATCH 3/7] feat: integrate meshTxBuilder V2 prototype --- .../transaction-builder-v2/builder-core.ts | 32 +-- .../src/types/transaction-builder-v2/mint.ts | 45 ++-- .../src/types/transaction-builder-v2/spend.ts | 55 ++-- .../src/types/transaction-builder-v2/vote.ts | 22 +- .../transaction-builder-v2/withdrawal.ts | 24 +- .../src/types/transaction-builder/index.ts | 1 - packages/mesh-transaction/src/index.ts | 1 + .../index.ts | 241 +++++++++--------- .../src/mesh-tx-builder/index.ts | 1 - .../test/mesh-tx-builder-v2.test.ts | 19 +- 10 files changed, 224 insertions(+), 217 deletions(-) rename packages/mesh-transaction/src/{mesh-builder-v2 => mesh-tx-builder-v2}/index.ts (63%) diff --git a/packages/mesh-common/src/types/transaction-builder-v2/builder-core.ts b/packages/mesh-common/src/types/transaction-builder-v2/builder-core.ts index d9c764821..4c7cdf09b 100644 --- a/packages/mesh-common/src/types/transaction-builder-v2/builder-core.ts +++ b/packages/mesh-common/src/types/transaction-builder-v2/builder-core.ts @@ -1,59 +1,59 @@ import { MeshTxBuilder, RefTxIn, Voter, VotingProcedure } from "@meshsdk/core"; -import { SpendRedeemerBuilder } from "./spend"; -import { MintRedeemerBuilder } from "./mint"; -import { WithdrawRedeemerBuilder } from "./withdrawal"; -import { VoteRedeemerBuilder } from "./vote"; +import { SpendScriptBuilder } from "./spend"; +import { MintScriptBuilder } from "./mint"; +import { WithdrawScriptBuilder } from "./withdrawal"; +import { VoteScriptBuilder } from "./vote"; export interface _MeshTxBuilderV2 extends Omit { - spendPlutusV1(txHash: string, txIndex: number): SpendRedeemerBuilder; - spendPlutusV2(txHash: string, txIndex: number): SpendRedeemerBuilder; - spendPlutusV3(txHash: string, txIndex: number): SpendRedeemerBuilder; + spendPlutusV1(txHash: string, txIndex: number): SpendScriptBuilder; + spendPlutusV2(txHash: string, txIndex: number): SpendScriptBuilder; + spendPlutusV3(txHash: string, txIndex: number): SpendScriptBuilder; mintPlutusV1( quantity: string, policyId: string, assetName: string, - ): MintRedeemerBuilder; + ): MintScriptBuilder; mintPlutusV2( quantity: string, policyId: string, assetName: string, - ): MintRedeemerBuilder; + ): MintScriptBuilder; mintPlutusV3( quantity: string, policyId: string, assetName: string, - ): MintRedeemerBuilder; + ): MintScriptBuilder; withdrawPlutusV1( rewardAddress: string, amount: string, - ): WithdrawRedeemerBuilder; + ): WithdrawScriptBuilder; withdrawPlutusV2( rewardAddress: string, amount: string, - ): WithdrawRedeemerBuilder; + ): WithdrawScriptBuilder; withdrawPlutusV3( rewardAddress: string, amount: string, - ): WithdrawRedeemerBuilder; + ): WithdrawScriptBuilder; votePlutusV1( voter: Voter, govActionId: RefTxIn, votingProcedure: VotingProcedure, - ): VoteRedeemerBuilder; + ): VoteScriptBuilder; votePlutusV2( voter: Voter, govActionId: RefTxIn, votingProcedure: VotingProcedure, - ): VoteRedeemerBuilder; + ): VoteScriptBuilder; votePlutusV3( voter: Voter, govActionId: RefTxIn, votingProcedure: VotingProcedure, - ): VoteRedeemerBuilder; + ): VoteScriptBuilder; } type ScriptMethodsToDrop = diff --git a/packages/mesh-common/src/types/transaction-builder-v2/mint.ts b/packages/mesh-common/src/types/transaction-builder-v2/mint.ts index d6083b8bf..83913a77e 100644 --- a/packages/mesh-common/src/types/transaction-builder-v2/mint.ts +++ b/packages/mesh-common/src/types/transaction-builder-v2/mint.ts @@ -1,25 +1,28 @@ import { Asset, Budget, BuilderData } from "@meshsdk/core"; + import { _MeshTxBuilderV2 } from "./builder-core"; +export interface MintScriptBuilder { + script(scriptCbor: string): MintRedeemerBuilder; + referenceScript( + txHash: string, + txIndex: number, + scriptSize?: string, + scriptHash?: string, + ): MintRedeemerBuilder; +} + export interface MintRedeemerBuilder { - redeemerJson( - redeemer: BuilderData["content"], - exUnits?: Budget, - ): MintScriptBuilder; - redeemerCbor( - redeemer: BuilderData["content"], - exUnits?: Budget, - ): MintScriptBuilder; - } - export interface MintScriptBuilder { - script(scriptCbor: string): MintTxOutBuilder; - referenceScript( - txHash: string, - txIndex: number, - scriptSize?: string, - scriptHash?: string, - ): MintTxOutBuilder; - } - export interface MintTxOutBuilder { - txOut(address: string, amount: Asset[]): _MeshTxBuilderV2; - } \ No newline at end of file + redeemerJson( + redeemer: BuilderData["content"], + exUnits?: Budget, + ): MintTxOutBuilder; + redeemerCbor( + redeemer: BuilderData["content"], + exUnits?: Budget, + ): MintTxOutBuilder; +} + +export interface MintTxOutBuilder { + txOut(address: string, amount: Asset[]): _MeshTxBuilderV2; +} diff --git a/packages/mesh-common/src/types/transaction-builder-v2/spend.ts b/packages/mesh-common/src/types/transaction-builder-v2/spend.ts index e1acfba09..2f05144a7 100644 --- a/packages/mesh-common/src/types/transaction-builder-v2/spend.ts +++ b/packages/mesh-common/src/types/transaction-builder-v2/spend.ts @@ -1,32 +1,33 @@ import { Asset, Budget, BuilderData } from "@meshsdk/core"; import { _MeshTxBuilderV2 } from "./builder-core"; +export interface SpendScriptBuilder { + script(scriptCbor: string): SpendRedeemerBuilder; + referenceScript( + refTxHash: string, + refTxIndex: number, + scriptSize?: string, + scriptHash?: string, + ): SpendRedeemerBuilder; +} + export interface SpendRedeemerBuilder { - redeemerJson( - redeemer: BuilderData["content"], - exUnits?: Budget, - ): SpendScriptBuilder; - redeemerCbor( - redeemer: BuilderData["content"], - exUnits?: Budget, - ): SpendScriptBuilder; - } - - export interface SpendScriptBuilder { - script(scriptCbor: string): SpendDatumBuilder; - referenceScript( - refTxHash: string, - refTxIndex: number, - scriptSize?: string, - scriptHash?: string, - ): SpendDatumBuilder; - } - export interface SpendDatumBuilder { - datumHash(datumHash: string): SpendTxOutBuilder; - datumCbor(datumCbor: BuilderData["content"]): SpendTxOutBuilder; - datumJson(datumJson: BuilderData["content"]): SpendTxOutBuilder; - } + redeemerJson( + redeemer: BuilderData["content"], + exUnits?: Budget, + ): SpendTxOutBuilder; + redeemerCbor( + redeemer: BuilderData["content"], + exUnits?: Budget, + ): SpendTxOutBuilder; +} + +export interface SpendTxOutBuilder { + txOut(address: string, amount: Asset[]): SpendDatumBuilder; +} - export interface SpendTxOutBuilder { - txOut(address: string, amount: Asset[]): _MeshTxBuilderV2; - } \ No newline at end of file +export interface SpendDatumBuilder { + datumHash(datumHash: string): _MeshTxBuilderV2; + datumCbor(datumCbor: BuilderData["content"]): _MeshTxBuilderV2; + datumJson(datumJson: BuilderData["content"]): _MeshTxBuilderV2; +} \ No newline at end of file diff --git a/packages/mesh-common/src/types/transaction-builder-v2/vote.ts b/packages/mesh-common/src/types/transaction-builder-v2/vote.ts index 8163d86e2..13e7ec962 100644 --- a/packages/mesh-common/src/types/transaction-builder-v2/vote.ts +++ b/packages/mesh-common/src/types/transaction-builder-v2/vote.ts @@ -1,22 +1,24 @@ import { Budget, BuilderData } from "@meshsdk/core"; + import { _MeshTxBuilderV2 } from "./builder-core"; +export interface VoteScriptBuilder { + script(scriptCbor: string): VoteRedeemerBuilder; + referenceScript( + txHash: string, + txIndex: number, + scriptSize?: string, + scriptHash?: string, + ): VoteRedeemerBuilder; +} + export interface VoteRedeemerBuilder { redeemerJson( redeemer: BuilderData["content"], exUnits?: Budget, - ): VoteScriptBuilder; + ): _MeshTxBuilderV2; redeemerCbor( redeemer: BuilderData["content"], exUnits?: Budget, - ): VoteScriptBuilder; -} -export interface VoteScriptBuilder { - script(scriptCbor: string): _MeshTxBuilderV2; - referenceScript( - txHash: string, - txIndex: number, - scriptSize?: string, - scriptHash?: string, ): _MeshTxBuilderV2; } diff --git a/packages/mesh-common/src/types/transaction-builder-v2/withdrawal.ts b/packages/mesh-common/src/types/transaction-builder-v2/withdrawal.ts index a4760ed44..98d84cb26 100644 --- a/packages/mesh-common/src/types/transaction-builder-v2/withdrawal.ts +++ b/packages/mesh-common/src/types/transaction-builder-v2/withdrawal.ts @@ -1,22 +1,24 @@ import { Budget, BuilderData } from "@meshsdk/core"; + import { _MeshTxBuilderV2 } from "./builder-core"; +export interface WithdrawScriptBuilder { + script(scriptCbor: string): WithdrawRedeemerBuilder; + referenceScript( + txHash: string, + txIndex: number, + scriptSize?: string, + scriptHash?: string, + ): WithdrawRedeemerBuilder; +} + export interface WithdrawRedeemerBuilder { redeemerJson( redeemer: BuilderData["content"], exUnits?: Budget, - ): WithdrawScriptBuilder; + ): _MeshTxBuilderV2; redeemerCbor( redeemer: BuilderData["content"], exUnits?: Budget, - ): WithdrawScriptBuilder; -} -export interface WithdrawScriptBuilder { - script(scriptCbor: string): _MeshTxBuilderV2; - referenceScript( - txHash: string, - txIndex: number, - scriptSize?: string, - scriptHash?: string, ): _MeshTxBuilderV2; -} \ No newline at end of file +} diff --git a/packages/mesh-common/src/types/transaction-builder/index.ts b/packages/mesh-common/src/types/transaction-builder/index.ts index df79ae535..7735ede55 100644 --- a/packages/mesh-common/src/types/transaction-builder/index.ts +++ b/packages/mesh-common/src/types/transaction-builder/index.ts @@ -19,7 +19,6 @@ export * from "./withdrawal"; export * from "./certificate"; export * from "./vote"; export * from "./proposal"; -export * from "./tx-builder-v2"; export type MeshTxBuilderBody = { inputs: TxIn[]; diff --git a/packages/mesh-transaction/src/index.ts b/packages/mesh-transaction/src/index.ts index bb9ee5e08..abc7253ce 100644 --- a/packages/mesh-transaction/src/index.ts +++ b/packages/mesh-transaction/src/index.ts @@ -3,4 +3,5 @@ export * from "./scripts"; export * from "./transaction"; export * from "./utils"; export * from "./tx-parser"; +export * from "./mesh-tx-builder-v2"; export { LargestFirstInputSelector } from "./mesh-tx-builder/coin-selection"; diff --git a/packages/mesh-transaction/src/mesh-builder-v2/index.ts b/packages/mesh-transaction/src/mesh-tx-builder-v2/index.ts similarity index 63% rename from packages/mesh-transaction/src/mesh-builder-v2/index.ts rename to packages/mesh-transaction/src/mesh-tx-builder-v2/index.ts index d85fa92f9..6966b3861 100644 --- a/packages/mesh-transaction/src/mesh-builder-v2/index.ts +++ b/packages/mesh-transaction/src/mesh-tx-builder-v2/index.ts @@ -17,24 +17,42 @@ import type { WithdrawScriptBuilder, } from "@meshsdk/common"; import { Asset, Budget, DEFAULT_REDEEMER_BUDGET } from "@meshsdk/common"; -import { MeshTxBuilder, MeshTxBuilderOptions } from "@meshsdk/core"; - -import { MeshTxBuilderCore } from "../mesh-tx-builder/tx-builder-core"; +import { byteString, conStr0, MeshTxBuilder, MeshTxBuilderOptions } from "@meshsdk/core"; class SpendBuilderImpl implements - SpendRedeemerBuilder, SpendScriptBuilder, - SpendDatumBuilder, - SpendTxOutBuilder + SpendRedeemerBuilder, + SpendTxOutBuilder, + SpendDatumBuilder { - constructor(private readonly core: MeshTxBuilder) {} + constructor(private readonly builder: MeshTxBuilder & _MeshTxBuilderV2) {} + + script(scriptCbor: string): SpendRedeemerBuilder { + this.builder.txInScript(scriptCbor); + return this; + } + + referenceScript( + refTxHash: string, + refTxIndex: number, + scriptSize?: string, + scriptHash?: string, + ): SpendRedeemerBuilder { + this.builder.spendingTxInReference( + refTxHash, + refTxIndex, + scriptSize, + scriptHash, + ); + return this; + } redeemerJson( - redeemer: BuilderData["content"], + redeemer: BuilderData["content"],//check back exUnits?: Budget, - ): SpendScriptBuilder { - this.core.txInRedeemerValue( + ): SpendTxOutBuilder { + this.builder.txInRedeemerValue( redeemer, "JSON", exUnits ?? { ...DEFAULT_REDEEMER_BUDGET }, @@ -45,8 +63,8 @@ class SpendBuilderImpl redeemerCbor( redeemer: BuilderData["content"], exUnits?: Budget, - ): SpendScriptBuilder { - this.core.txInRedeemerValue( + ): SpendTxOutBuilder { + this.builder.txInRedeemerValue( redeemer, "CBOR", exUnits ?? { ...DEFAULT_REDEEMER_BUDGET }, @@ -54,58 +72,53 @@ class SpendBuilderImpl return this; } - script(scriptCbor: string): SpendDatumBuilder { - this.core.txInScript(scriptCbor); + txOut(address: string, amount: Asset[]): SpendDatumBuilder { + this.builder.txInInlineDatumPresent(); + this.builder.txOut(address, amount); return this; } - referenceScript( - refTxHash: string, - refTxIndex: number, - scriptSize?: string, - scriptHash?: string, - ): SpendDatumBuilder { - this.core.spendingTxInReference( - refTxHash, - refTxIndex, - scriptSize, - scriptHash, - ); - return this; + datumJson(datum: BuilderData["content"]): _MeshTxBuilderV2 { + this.builder.txOutInlineDatumValue(datum, "JSON"); + return this.builder as _MeshTxBuilderV2; } - datumJson(datum: BuilderData["content"]): SpendTxOutBuilder { - this.core.txOutInlineDatumValue(datum, "JSON"); - return this; + datumCbor(datum: BuilderData["content"]): _MeshTxBuilderV2 { + this.builder.txOutInlineDatumValue(datum, "CBOR"); + return this.builder as _MeshTxBuilderV2; } - datumCbor(datum: BuilderData["content"]): SpendTxOutBuilder { - this.core.txOutInlineDatumValue(datum, "CBOR"); - return this; + datumHash(datumHash: string): _MeshTxBuilderV2 { + this.builder.txOutDatumHashValue(datumHash); + return this.builder as _MeshTxBuilderV2; } +} - datumHash(datumHash: string): SpendTxOutBuilder { - this.core.txOutDatumHashValue(datumHash); +class MintBuilderImpl + implements MintScriptBuilder, MintRedeemerBuilder, MintTxOutBuilder +{ + constructor(private readonly builder: MeshTxBuilder & _MeshTxBuilderV2) {} + + script(scriptCbor: string): MintRedeemerBuilder { + this.builder.mintingScript(scriptCbor); return this; } - txOut(address: string, amount: Asset[]): _MeshTxBuilderV2 { - this.core.txInInlineDatumPresent(); - this.core.txOut(address, amount); - return this.core as unknown as _MeshTxBuilderV2; + referenceScript( + txHash: string, + txIndex: number, + scriptSize?: string, + scriptHash?: string, + ): MintRedeemerBuilder { + this.builder.mintTxInReference(txHash, txIndex, scriptSize, scriptHash); + return this; } -} - -class MintBuilderImpl - implements MintRedeemerBuilder, MintScriptBuilder, MintTxOutBuilder -{ - constructor(private readonly core: MeshTxBuilder) {} redeemerJson( redeemer: BuilderData["content"], exUnits?: Budget, - ): MintScriptBuilder { - this.core.mintRedeemerValue( + ): MintTxOutBuilder { + this.builder.mintRedeemerValue( redeemer, "JSON", exUnits ?? { ...DEFAULT_REDEEMER_BUDGET }, @@ -116,8 +129,8 @@ class MintBuilderImpl redeemerCbor( redeemer: BuilderData["content"], exUnits?: Budget, - ): MintScriptBuilder { - this.core.mintRedeemerValue( + ): MintTxOutBuilder { + this.builder.mintRedeemerValue( redeemer, "CBOR", exUnits ?? { ...DEFAULT_REDEEMER_BUDGET }, @@ -125,8 +138,19 @@ class MintBuilderImpl return this; } - script(scriptCbor: string): MintTxOutBuilder { - this.core.mintingScript(scriptCbor); + txOut(address: string, amount: Asset[]): _MeshTxBuilderV2 { + this.builder.txOut(address, amount); + return this.builder as _MeshTxBuilderV2; + } +} + +class WithdrawBuilderImpl + implements WithdrawScriptBuilder, WithdrawRedeemerBuilder +{ + constructor(private readonly builder: MeshTxBuilder & _MeshTxBuilderV2) {} + + script(scriptCbor: string): WithdrawRedeemerBuilder { + this.builder.withdrawalScript(scriptCbor); return this; } @@ -135,49 +159,42 @@ class MintBuilderImpl txIndex: number, scriptSize?: string, scriptHash?: string, - ): MintTxOutBuilder { - this.core.mintTxInReference(txHash, txIndex, scriptSize, scriptHash); + ): WithdrawRedeemerBuilder { + this.builder.withdrawalTxInReference(txHash, txIndex, scriptSize, scriptHash); return this; } - txOut(address: string, amount: Asset[]): _MeshTxBuilderV2 { - this.core.txOut(address, amount); - return this.core as unknown as _MeshTxBuilderV2; - } -} - -class WithdrawBuilderImpl - implements WithdrawRedeemerBuilder, WithdrawScriptBuilder -{ - constructor(private readonly core: MeshTxBuilder) {} - redeemerJson( redeemer: BuilderData["content"], exUnits?: Budget, - ): WithdrawScriptBuilder { - this.core.withdrawalRedeemerValue( + ): _MeshTxBuilderV2 { + this.builder.withdrawalRedeemerValue( redeemer, "JSON", exUnits ?? { ...DEFAULT_REDEEMER_BUDGET }, ); - return this; + return this.builder as _MeshTxBuilderV2; } redeemerCbor( redeemer: BuilderData["content"], exUnits?: Budget, - ): WithdrawScriptBuilder { - this.core.withdrawalRedeemerValue( + ): _MeshTxBuilderV2 { + this.builder.withdrawalRedeemerValue( redeemer, "CBOR", exUnits ?? { ...DEFAULT_REDEEMER_BUDGET }, ); - return this; + return this.builder as _MeshTxBuilderV2; } +} + +class VoteBuilderImpl implements VoteScriptBuilder, VoteRedeemerBuilder { + constructor(private readonly builder: MeshTxBuilder & _MeshTxBuilderV2) {} - script(scriptCbor: string): _MeshTxBuilderV2 { - this.core.withdrawalScript(scriptCbor); - return this.core as unknown as _MeshTxBuilderV2; + script(scriptCbor: string): VoteRedeemerBuilder { + this.builder.voteScript(scriptCbor); + return this; } referenceScript( @@ -185,67 +202,48 @@ class WithdrawBuilderImpl txIndex: number, scriptSize?: string, scriptHash?: string, - ): _MeshTxBuilderV2 { - this.core.withdrawalTxInReference(txHash, txIndex, scriptSize, scriptHash); - return this.core as unknown as _MeshTxBuilderV2; + ): VoteRedeemerBuilder { + this.builder.voteTxInReference(txHash, txIndex, scriptSize, scriptHash); + return this; } -} - -class VoteBuilderImpl implements VoteRedeemerBuilder, VoteScriptBuilder { - constructor(private readonly core: MeshTxBuilder) {} redeemerJson( redeemer: BuilderData["content"], exUnits?: Budget, - ): VoteScriptBuilder { - this.core.voteRedeemerValue( + ): _MeshTxBuilderV2 { + this.builder.voteRedeemerValue( redeemer, "JSON", exUnits ?? { ...DEFAULT_REDEEMER_BUDGET }, ); - return this; + return this.builder as _MeshTxBuilderV2; } redeemerCbor( redeemer: BuilderData["content"], exUnits?: Budget, - ): VoteScriptBuilder { - this.core.voteRedeemerValue( + ): _MeshTxBuilderV2 { + this.builder.voteRedeemerValue( redeemer, "CBOR", exUnits ?? { ...DEFAULT_REDEEMER_BUDGET }, ); - return this; - } - - script(scriptCbor: string): _MeshTxBuilderV2 { - this.core.voteScript(scriptCbor); - return this.core as unknown as _MeshTxBuilderV2; - } - - referenceScript( - txHash: string, - txIndex: number, - scriptSize?: string, - scriptHash?: string, - ): _MeshTxBuilderV2 { - this.core.voteTxInReference(txHash, txIndex, scriptSize, scriptHash); - return this.core as unknown as _MeshTxBuilderV2; + return this.builder as _MeshTxBuilderV2; } } -class __MeshTxBuilderV2 extends MeshTxBuilder { - spendPlutusV1(txHash: string, txIndex: number): SpendRedeemerBuilder { +class TxBuilderV2 extends MeshTxBuilder { + spendPlutusV1(txHash: string, txIndex: number): SpendScriptBuilder { this.spendingPlutusScriptV1(); this.txIn(txHash, txIndex); return new SpendBuilderImpl(this); } - spendPlutusV2(txHash: string, txIndex: number): SpendRedeemerBuilder { + spendPlutusV2(txHash: string, txIndex: number): SpendScriptBuilder { this.spendingPlutusScriptV2(); this.txIn(txHash, txIndex); return new SpendBuilderImpl(this); } - spendPlutusV3(txHash: string, txIndex: number): SpendRedeemerBuilder { + spendPlutusV3(txHash: string, txIndex: number): SpendScriptBuilder { this.spendingPlutusScriptV3(); this.txIn(txHash, txIndex); return new SpendBuilderImpl(this); @@ -255,7 +253,7 @@ class __MeshTxBuilderV2 extends MeshTxBuilder { quantity: string, policyId: string, assetName: string, - ): MintRedeemerBuilder { + ): MintScriptBuilder { this.mintPlutusScriptV1(); this.mint(quantity, policyId, assetName); return new MintBuilderImpl(this); @@ -264,7 +262,7 @@ class __MeshTxBuilderV2 extends MeshTxBuilder { quantity: string, policyId: string, assetName: string, - ): MintRedeemerBuilder { + ): MintScriptBuilder { this.mintPlutusScriptV2(); this.mint(quantity, policyId, assetName); return new MintBuilderImpl(this); @@ -273,7 +271,7 @@ class __MeshTxBuilderV2 extends MeshTxBuilder { quantity: string, policyId: string, assetName: string, - ): MintRedeemerBuilder { + ): MintScriptBuilder { this.mintPlutusScriptV3(); this.mint(quantity, policyId, assetName); return new MintBuilderImpl(this); @@ -281,16 +279,16 @@ class __MeshTxBuilderV2 extends MeshTxBuilder { withdrawPlutusV1( rewardAddress: string, - coin: string, - ): WithdrawRedeemerBuilder { + amount: string, + ): WithdrawScriptBuilder { this.withdrawalPlutusScriptV1(); - this.withdrawal(rewardAddress, coin); + this.withdrawal(rewardAddress, amount); return new WithdrawBuilderImpl(this); } withdrawPlutusV2( rewardAddress: string, coin: string, - ): WithdrawRedeemerBuilder { + ): WithdrawScriptBuilder { this.withdrawalPlutusScriptV2(); this.withdrawal(rewardAddress, coin); return new WithdrawBuilderImpl(this); @@ -298,7 +296,7 @@ class __MeshTxBuilderV2 extends MeshTxBuilder { withdrawPlutusV3( rewardAddress: string, coin: string, - ): WithdrawRedeemerBuilder { + ): WithdrawScriptBuilder { this.withdrawalPlutusScriptV3(); this.withdrawal(rewardAddress, coin); return new WithdrawBuilderImpl(this); @@ -308,7 +306,7 @@ class __MeshTxBuilderV2 extends MeshTxBuilder { voter: Voter, govActionId: RefTxIn, votingProcedure: VotingProcedure, - ): VoteRedeemerBuilder { + ): VoteScriptBuilder { this.votePlutusScriptV1(); this.vote(voter, govActionId, votingProcedure); return new VoteBuilderImpl(this); @@ -317,7 +315,7 @@ class __MeshTxBuilderV2 extends MeshTxBuilder { voter: Voter, govActionId: RefTxIn, votingProcedure: VotingProcedure, - ): VoteRedeemerBuilder { + ): VoteScriptBuilder { this.votePlutusScriptV2(); this.vote(voter, govActionId, votingProcedure); return new VoteBuilderImpl(this); @@ -326,7 +324,7 @@ class __MeshTxBuilderV2 extends MeshTxBuilder { voter: Voter, govActionId: RefTxIn, votingProcedure: VotingProcedure, - ): VoteRedeemerBuilder { + ): VoteScriptBuilder { this.votePlutusScriptV3(); this.vote(voter, govActionId, votingProcedure); return new VoteBuilderImpl(this); @@ -334,10 +332,10 @@ class __MeshTxBuilderV2 extends MeshTxBuilder { } /** - * `MeshTxBuilderV2` is a strongly-typed wrapper around the core `MeshTxBuilder` + * \`MeshTxBuilderV2\` is a strongly-typed wrapper around the core \`MeshTxBuilder\` * that enforces a rigid Type-State machine for Plutus operations. * - * It natively provides TypeScript autocomplete restrictions (Script -> Datum -> Redeemer) + * It natively provides TypeScript autocomplete restrictions (Script -> Redeemer -> TxOut -> Datum) * for transactions like spending, minting, withdrawing, and voting, dropping standalone * script methods to prevent incorrect chained execution ordering. * @@ -350,11 +348,12 @@ class __MeshTxBuilderV2 extends MeshTxBuilder { * * tx.spendPlutusV3(txHash, index) * .script(scriptCbor) - * .datumJson(datumValue) * .redeemerJson(redeemerValue) - * .txOut(address, assets); // Drops you back into the main builder methods + * .txOut(address, assets) + * .datumJson(datumValue); // Drops you back into the main builder methods * ``` */ + export const MeshTxBuilderV2: new ( options?: MeshTxBuilderOptions, -) => _MeshTxBuilderV2 = __MeshTxBuilderV2; +) => _MeshTxBuilderV2 = TxBuilderV2; \ No newline at end of file diff --git a/packages/mesh-transaction/src/mesh-tx-builder/index.ts b/packages/mesh-transaction/src/mesh-tx-builder/index.ts index 508a0e7fb..b6c6339f5 100644 --- a/packages/mesh-transaction/src/mesh-tx-builder/index.ts +++ b/packages/mesh-transaction/src/mesh-tx-builder/index.ts @@ -1878,4 +1878,3 @@ export const getOutputMinLovelace = ( }; export * from "./utils"; -export { MeshTxBuilderV2 } from "../mesh-builder-v2"; diff --git a/packages/mesh-transaction/test/mesh-tx-builder-v2.test.ts b/packages/mesh-transaction/test/mesh-tx-builder-v2.test.ts index 422ce67ca..f8caae1f7 100644 --- a/packages/mesh-transaction/test/mesh-tx-builder-v2.test.ts +++ b/packages/mesh-transaction/test/mesh-tx-builder-v2.test.ts @@ -2,6 +2,7 @@ import { Asset, Budget, LanguageVersion } from "@meshsdk/common"; import { MeshTxBuilderV2 } from "../src"; + describe("MeshTxBuilderV2 Grouped interfaces", () => { it("should build a tx with spendPlutusV2", () => { const tx = new MeshTxBuilderV2(); @@ -9,13 +10,13 @@ describe("MeshTxBuilderV2 Grouped interfaces", () => { "0000000000000000000000000000000000000000000000000000000000000000"; tx.spendPlutusV2(mockHash, 0) - .redeemerJson({ action: "spend" }) .script("112233") - .datumJson({ data: "foo" }) + .redeemerJson({ action: "spend" }) .txOut( "addr_test1vzuwvztxzv3j4a2wvy7xntry2a8y869svj4a7y7qy2wvywqzcqxny", - [], - ); + [] + ) + .datumJson({ data: "foo" }); // @ts-ignore tx.queueAllLastItem(); @@ -54,8 +55,8 @@ describe("MeshTxBuilderV2 Grouped interfaces", () => { it("should have correct mintPlutus interface", () => { const tx = new MeshTxBuilderV2(); tx.mintPlutusV2("1", "policyId123", "assetName456") - .redeemerCbor("998877") .script("556677") + .redeemerCbor("998877") .txOut( "addr_test1vzuwvztxzv3j4a2wvy7xntry2a8y869svj4a7y7qy2wvywqzcqxny", [], @@ -83,8 +84,8 @@ describe("MeshTxBuilderV2 Grouped interfaces", () => { it("should build a tx with withdrawPlutusV2", () => { const tx = new MeshTxBuilderV2(); tx.withdrawPlutusV2("stake_test1uqevw2xnsc0pvn9t9r9c7qryfqfeerchgrlm3ea2nefr9hqp8n5xl", "1000000") - .redeemerJson({ action: "withdraw" }) - .script("445566"); + .script("445566") + .redeemerJson({ action: "withdraw" }); // @ts-ignore tx.queueAllLastItem(); @@ -113,8 +114,8 @@ describe("MeshTxBuilderV2 Grouped interfaces", () => { { txHash: "0000000000000000000000000000000000000000000000000000000000000000", txIndex: 0 }, { voteKind: "Yes" } ) - .redeemerJson({ action: "vote" }) - .script("111111"); + .script("111111") + .redeemerJson({ action: "vote" }); // @ts-ignore tx.queueAllLastItem(); From 987fa76b95984209193b79eefbcd24c6260140ad Mon Sep 17 00:00:00 2001 From: "Emmanuel .A" Date: Wed, 18 Mar 2026 15:40:18 +0100 Subject: [PATCH 4/7] chore: json constrictor to only accept plutus data --- packages/mesh-common/src/data/json/aliases.ts | 8 ++-- .../mesh-common/src/data/json/constructors.ts | 47 +++++++++++++------ 2 files changed, 36 insertions(+), 19 deletions(-) diff --git a/packages/mesh-common/src/data/json/aliases.ts b/packages/mesh-common/src/data/json/aliases.ts index e38ebded8..cc71225bf 100644 --- a/packages/mesh-common/src/data/json/aliases.ts +++ b/packages/mesh-common/src/data/json/aliases.ts @@ -88,13 +88,13 @@ export type Tuple = { list: T }; * Aiken alias * The Plutus Data Option in JSON */ -export type Option = Some | None; +export type Option = Some | None; /** * Aiken alias * The Plutus Data Option - Some in JSON */ -export type Some = ConStr0<[T]>; +export type Some = ConStr0<[T]>; /** * Aiken alias @@ -246,7 +246,7 @@ export const tuple = (...args: T): Tuple => ({ * @param value The optional value of the option * @returns Return None constructor if the value is not provided, otherwise return Some constructor with the value */ -export const option = (value?: T): Option => { +export const option = (value?: T): Option => { if (!value) { return none(); } @@ -258,7 +258,7 @@ export const option = (value?: T): Option => { * @param value The value of the option * @returns The Plutus Data Option - Some object */ -export const some = (value: T): Some => conStr0([value]); +export const some = (value: T): Some => conStr0([value]); /** * The utility function to create a Plutus Data Option - None in JSON diff --git a/packages/mesh-common/src/data/json/constructors.ts b/packages/mesh-common/src/data/json/constructors.ts index 02743be99..4a1fc3146 100644 --- a/packages/mesh-common/src/data/json/constructors.ts +++ b/packages/mesh-common/src/data/json/constructors.ts @@ -1,27 +1,43 @@ +import { PlutusData } from "."; + /** * The Plutus Data constructor object, representing custom data type in JSON */ -export type ConStr = { constructor: N; fields: T }; - +export interface ConStr { + constructor: N; + fields: T; +} /** * The Plutus Data index 0 constructor object, representing custom data type in JSON */ -export type ConStr0 = ConStr<0, T>; +export interface ConStr0 extends ConStr< + 0, + T +> {} /** * The Plutus Data index 1 constructor object, representing custom data type in JSON */ -export type ConStr1 = ConStr<1, T>; +export interface ConStr1 extends ConStr< + 1, + T +> {} /** * The Plutus Data index 2 constructor object, representing custom data type in JSON */ -export type ConStr2 = ConStr<2, T>; +export interface ConStr2 extends ConStr< + 2, + T +> {} /** * The Plutus Data index 3 constructor object, representing custom data type in JSON */ -export type ConStr3 = ConStr<3, T>; +export interface ConStr3 extends ConStr< + 3, + T +> {} /** * The utility function to create a Plutus Data constructor object, representing custom data type in JSON @@ -29,17 +45,14 @@ export type ConStr3 = ConStr<3, T>; * @param fields The items in array * @returns The Plutus Data constructor object */ -export const conStr = ( +export const conStr = ( constructor: N, fields: T, ): ConStr => { if (!Array.isArray(fields)) { throw new Error("fields of a constructor must be an array"); } - return { - constructor, - fields, - }; + return { constructor, fields }; }; /** @@ -47,25 +60,29 @@ export const conStr = ( * @param fields The items of in array * @returns The Plutus Data constructor object */ -export const conStr0 = (fields: T): ConStr0 => conStr<0, T>(0, fields); +export const conStr0 = (fields: T): ConStr0 => + conStr<0, T>(0, fields); /** * The utility function to create a Plutus Data index 1 constructor object, representing custom data type in JSON * @param fields The items of in array * @returns The Plutus Data constructor object */ -export const conStr1 = (fields: T): ConStr1 => conStr<1, T>(1, fields); +export const conStr1 = (fields: T): ConStr1 => + conStr<1, T>(1, fields); /** * The utility function to create a Plutus Data index 2 constructor object, representing custom data type in JSON * @param fields The items of in array * @returns The Plutus Data constructor object */ -export const conStr2 = (fields: T): ConStr2 => conStr<2, T>(2, fields); +export const conStr2 = (fields: T): ConStr2 => + conStr<2, T>(2, fields); /** * The utility function to create a Plutus Data index 3 constructor object, representing custom data type in JSON * @param fields The items of in array * @returns The Plutus Data constructor object */ -export const conStr3 = (fields: T): ConStr3 => conStr<3, T>(3, fields); +export const conStr3 = (fields: T): ConStr3 => + conStr<3, T>(3, fields); From 52979b825134fe9810e088f7173cfbfb9bca6279 Mon Sep 17 00:00:00 2001 From: "Emmanuel .A" Date: Wed, 25 Mar 2026 17:16:24 +0100 Subject: [PATCH 5/7] feat: migrate files --- .../transaction-builder-v2/builder-core.ts | 94 ------------------- .../src/types/transaction-builder-v2/index.ts | 5 - .../src/types/transaction-builder-v2/mint.ts | 28 ------ .../src/types/transaction-builder-v2/spend.ts | 33 ------- .../src/types/transaction-builder-v2/vote.ts | 24 ----- .../transaction-builder-v2/withdrawal.ts | 24 ----- 6 files changed, 208 deletions(-) delete mode 100644 packages/mesh-common/src/types/transaction-builder-v2/builder-core.ts delete mode 100644 packages/mesh-common/src/types/transaction-builder-v2/index.ts delete mode 100644 packages/mesh-common/src/types/transaction-builder-v2/mint.ts delete mode 100644 packages/mesh-common/src/types/transaction-builder-v2/spend.ts delete mode 100644 packages/mesh-common/src/types/transaction-builder-v2/vote.ts delete mode 100644 packages/mesh-common/src/types/transaction-builder-v2/withdrawal.ts diff --git a/packages/mesh-common/src/types/transaction-builder-v2/builder-core.ts b/packages/mesh-common/src/types/transaction-builder-v2/builder-core.ts deleted file mode 100644 index 4c7cdf09b..000000000 --- a/packages/mesh-common/src/types/transaction-builder-v2/builder-core.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { MeshTxBuilder, RefTxIn, Voter, VotingProcedure } from "@meshsdk/core"; -import { SpendScriptBuilder } from "./spend"; -import { MintScriptBuilder } from "./mint"; -import { WithdrawScriptBuilder } from "./withdrawal"; -import { VoteScriptBuilder } from "./vote"; - -export interface _MeshTxBuilderV2 - extends Omit { - spendPlutusV1(txHash: string, txIndex: number): SpendScriptBuilder; - spendPlutusV2(txHash: string, txIndex: number): SpendScriptBuilder; - spendPlutusV3(txHash: string, txIndex: number): SpendScriptBuilder; - - mintPlutusV1( - quantity: string, - policyId: string, - assetName: string, - ): MintScriptBuilder; - mintPlutusV2( - quantity: string, - policyId: string, - assetName: string, - ): MintScriptBuilder; - mintPlutusV3( - quantity: string, - policyId: string, - assetName: string, - ): MintScriptBuilder; - - withdrawPlutusV1( - rewardAddress: string, - amount: string, - ): WithdrawScriptBuilder; - withdrawPlutusV2( - rewardAddress: string, - amount: string, - ): WithdrawScriptBuilder; - withdrawPlutusV3( - rewardAddress: string, - amount: string, - ): WithdrawScriptBuilder; - - votePlutusV1( - voter: Voter, - govActionId: RefTxIn, - votingProcedure: VotingProcedure, - ): VoteScriptBuilder; - votePlutusV2( - voter: Voter, - govActionId: RefTxIn, - votingProcedure: VotingProcedure, - ): VoteScriptBuilder; - votePlutusV3( - voter: Voter, - govActionId: RefTxIn, - votingProcedure: VotingProcedure, - ): VoteScriptBuilder; -} - -type ScriptMethodsToDrop = - | "spendingPlutusScript" - | "spendingPlutusScriptV1" - | "spendingPlutusScriptV2" - | "spendingPlutusScriptV3" - | "spendingTxInReference" - | "spendingReferenceTxInInlineDatumPresent" - | "spendingReferenceTxInRedeemerValue" - | "mintPlutusScript" - | "mintPlutusScriptV1" - | "mintPlutusScriptV2" - | "mintPlutusScriptV3" - | "mintingScript" - | "mintTxInReference" - | "mintReferenceTxInRedeemerValue" - | "mintRedeemerValue" - | "withdrawalPlutusScript" - | "withdrawalPlutusScriptV1" - | "withdrawalPlutusScriptV2" - | "withdrawalPlutusScriptV3" - | "withdrawalScript" - | "withdrawalTxInReference" - | "withdrawalReferenceTxInRedeemerValue" - | "withdrawalRedeemerValue" - | "votePlutusScript" - | "votePlutusScriptV1" - | "votePlutusScriptV2" - | "votePlutusScriptV3" - | "voteScript" - | "voteTxInReference" - | "voteReferenceTxInRedeemerValue" - | "voteRedeemerValue" - | "txInScript" - | "txInDatumValue" - | "txInInlineDatumPresent" - | "txInRedeemerValue"; diff --git a/packages/mesh-common/src/types/transaction-builder-v2/index.ts b/packages/mesh-common/src/types/transaction-builder-v2/index.ts deleted file mode 100644 index 58cb915ea..000000000 --- a/packages/mesh-common/src/types/transaction-builder-v2/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from './builder-core'; -export * from './mint'; -export * from './spend'; -export * from './vote'; -export * from './withdrawal' \ No newline at end of file diff --git a/packages/mesh-common/src/types/transaction-builder-v2/mint.ts b/packages/mesh-common/src/types/transaction-builder-v2/mint.ts deleted file mode 100644 index 83913a77e..000000000 --- a/packages/mesh-common/src/types/transaction-builder-v2/mint.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Asset, Budget, BuilderData } from "@meshsdk/core"; - -import { _MeshTxBuilderV2 } from "./builder-core"; - -export interface MintScriptBuilder { - script(scriptCbor: string): MintRedeemerBuilder; - referenceScript( - txHash: string, - txIndex: number, - scriptSize?: string, - scriptHash?: string, - ): MintRedeemerBuilder; -} - -export interface MintRedeemerBuilder { - redeemerJson( - redeemer: BuilderData["content"], - exUnits?: Budget, - ): MintTxOutBuilder; - redeemerCbor( - redeemer: BuilderData["content"], - exUnits?: Budget, - ): MintTxOutBuilder; -} - -export interface MintTxOutBuilder { - txOut(address: string, amount: Asset[]): _MeshTxBuilderV2; -} diff --git a/packages/mesh-common/src/types/transaction-builder-v2/spend.ts b/packages/mesh-common/src/types/transaction-builder-v2/spend.ts deleted file mode 100644 index 2f05144a7..000000000 --- a/packages/mesh-common/src/types/transaction-builder-v2/spend.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { Asset, Budget, BuilderData } from "@meshsdk/core"; -import { _MeshTxBuilderV2 } from "./builder-core"; - -export interface SpendScriptBuilder { - script(scriptCbor: string): SpendRedeemerBuilder; - referenceScript( - refTxHash: string, - refTxIndex: number, - scriptSize?: string, - scriptHash?: string, - ): SpendRedeemerBuilder; -} - -export interface SpendRedeemerBuilder { - redeemerJson( - redeemer: BuilderData["content"], - exUnits?: Budget, - ): SpendTxOutBuilder; - redeemerCbor( - redeemer: BuilderData["content"], - exUnits?: Budget, - ): SpendTxOutBuilder; -} - -export interface SpendTxOutBuilder { - txOut(address: string, amount: Asset[]): SpendDatumBuilder; -} - -export interface SpendDatumBuilder { - datumHash(datumHash: string): _MeshTxBuilderV2; - datumCbor(datumCbor: BuilderData["content"]): _MeshTxBuilderV2; - datumJson(datumJson: BuilderData["content"]): _MeshTxBuilderV2; -} \ No newline at end of file diff --git a/packages/mesh-common/src/types/transaction-builder-v2/vote.ts b/packages/mesh-common/src/types/transaction-builder-v2/vote.ts deleted file mode 100644 index 13e7ec962..000000000 --- a/packages/mesh-common/src/types/transaction-builder-v2/vote.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Budget, BuilderData } from "@meshsdk/core"; - -import { _MeshTxBuilderV2 } from "./builder-core"; - -export interface VoteScriptBuilder { - script(scriptCbor: string): VoteRedeemerBuilder; - referenceScript( - txHash: string, - txIndex: number, - scriptSize?: string, - scriptHash?: string, - ): VoteRedeemerBuilder; -} - -export interface VoteRedeemerBuilder { - redeemerJson( - redeemer: BuilderData["content"], - exUnits?: Budget, - ): _MeshTxBuilderV2; - redeemerCbor( - redeemer: BuilderData["content"], - exUnits?: Budget, - ): _MeshTxBuilderV2; -} diff --git a/packages/mesh-common/src/types/transaction-builder-v2/withdrawal.ts b/packages/mesh-common/src/types/transaction-builder-v2/withdrawal.ts deleted file mode 100644 index 98d84cb26..000000000 --- a/packages/mesh-common/src/types/transaction-builder-v2/withdrawal.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Budget, BuilderData } from "@meshsdk/core"; - -import { _MeshTxBuilderV2 } from "./builder-core"; - -export interface WithdrawScriptBuilder { - script(scriptCbor: string): WithdrawRedeemerBuilder; - referenceScript( - txHash: string, - txIndex: number, - scriptSize?: string, - scriptHash?: string, - ): WithdrawRedeemerBuilder; -} - -export interface WithdrawRedeemerBuilder { - redeemerJson( - redeemer: BuilderData["content"], - exUnits?: Budget, - ): _MeshTxBuilderV2; - redeemerCbor( - redeemer: BuilderData["content"], - exUnits?: Budget, - ): _MeshTxBuilderV2; -} From 545ed886ea1dd8098e4877cb5b3a44be059426bd Mon Sep 17 00:00:00 2001 From: "Emmanuel .A" Date: Wed, 25 Mar 2026 17:22:16 +0100 Subject: [PATCH 6/7] remove unused export --- packages/mesh-common/src/types/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/mesh-common/src/types/index.ts b/packages/mesh-common/src/types/index.ts index a5f59df6e..ebac87471 100644 --- a/packages/mesh-common/src/types/index.ts +++ b/packages/mesh-common/src/types/index.ts @@ -25,4 +25,3 @@ export * from "./transaction-builder"; export * from "./deserialized"; export * from "./blueprint"; export * from "./governance"; -export * from "./transaction-builder-v2"; From a1c33b85e31deab2462e3345aa817aa47b346c9e Mon Sep 17 00:00:00 2001 From: "Emmanuel .A" Date: Wed, 25 Mar 2026 17:22:49 +0100 Subject: [PATCH 7/7] feat: integrate meshTxBuilder V2 --- .../src/mesh-tx-builder-v2/index.ts | 18 +- .../src/mesh-tx-builder-v2/types.ts | 200 ++++++++++++++++++ 2 files changed, 211 insertions(+), 7 deletions(-) create mode 100644 packages/mesh-transaction/src/mesh-tx-builder-v2/types.ts diff --git a/packages/mesh-transaction/src/mesh-tx-builder-v2/index.ts b/packages/mesh-transaction/src/mesh-tx-builder-v2/index.ts index 6966b3861..ab26b2de0 100644 --- a/packages/mesh-transaction/src/mesh-tx-builder-v2/index.ts +++ b/packages/mesh-transaction/src/mesh-tx-builder-v2/index.ts @@ -1,23 +1,27 @@ import type { _MeshTxBuilderV2, - BuilderData, MintRedeemerBuilder, MintScriptBuilder, MintTxOutBuilder, - RefTxIn, SpendDatumBuilder, SpendRedeemerBuilder, SpendScriptBuilder, SpendTxOutBuilder, - Voter, VoteRedeemerBuilder, VoteScriptBuilder, - VotingProcedure, WithdrawRedeemerBuilder, WithdrawScriptBuilder, +} from "./types"; +import { + Asset, + Budget, + BuilderData, + DEFAULT_REDEEMER_BUDGET, + RefTxIn, + Voter, + VotingProcedure, } from "@meshsdk/common"; -import { Asset, Budget, DEFAULT_REDEEMER_BUDGET } from "@meshsdk/common"; -import { byteString, conStr0, MeshTxBuilder, MeshTxBuilderOptions } from "@meshsdk/core"; +import { MeshTxBuilder, MeshTxBuilderOptions } from "../mesh-tx-builder"; class SpendBuilderImpl implements @@ -356,4 +360,4 @@ class TxBuilderV2 extends MeshTxBuilder { export const MeshTxBuilderV2: new ( options?: MeshTxBuilderOptions, -) => _MeshTxBuilderV2 = TxBuilderV2; \ No newline at end of file +) => _MeshTxBuilderV2 = TxBuilderV2; diff --git a/packages/mesh-transaction/src/mesh-tx-builder-v2/types.ts b/packages/mesh-transaction/src/mesh-tx-builder-v2/types.ts new file mode 100644 index 000000000..bab8d5825 --- /dev/null +++ b/packages/mesh-transaction/src/mesh-tx-builder-v2/types.ts @@ -0,0 +1,200 @@ +import { Asset, Budget, BuilderData, RefTxIn, Voter, VotingProcedure } from "@meshsdk/common"; + +import { MeshTxBuilder } from "../mesh-tx-builder"; + +// ── Core V2 Builder Interface ────────────────────────────────────────── + +export interface _MeshTxBuilderV2 + extends Omit { + spendPlutusV1(txHash: string, txIndex: number): SpendScriptBuilder; + spendPlutusV2(txHash: string, txIndex: number): SpendScriptBuilder; + spendPlutusV3(txHash: string, txIndex: number): SpendScriptBuilder; + + mintPlutusV1( + quantity: string, + policyId: string, + assetName: string, + ): MintScriptBuilder; + mintPlutusV2( + quantity: string, + policyId: string, + assetName: string, + ): MintScriptBuilder; + mintPlutusV3( + quantity: string, + policyId: string, + assetName: string, + ): MintScriptBuilder; + + withdrawPlutusV1( + rewardAddress: string, + amount: string, + ): WithdrawScriptBuilder; + withdrawPlutusV2( + rewardAddress: string, + amount: string, + ): WithdrawScriptBuilder; + withdrawPlutusV3( + rewardAddress: string, + amount: string, + ): WithdrawScriptBuilder; + + votePlutusV1( + voter: Voter, + govActionId: RefTxIn, + votingProcedure: VotingProcedure, + ): VoteScriptBuilder; + votePlutusV2( + voter: Voter, + govActionId: RefTxIn, + votingProcedure: VotingProcedure, + ): VoteScriptBuilder; + votePlutusV3( + voter: Voter, + govActionId: RefTxIn, + votingProcedure: VotingProcedure, + ): VoteScriptBuilder; +} + +type ScriptMethodsToDrop = + | "spendingPlutusScript" + | "spendingPlutusScriptV1" + | "spendingPlutusScriptV2" + | "spendingPlutusScriptV3" + | "spendingTxInReference" + | "spendingReferenceTxInInlineDatumPresent" + | "spendingReferenceTxInRedeemerValue" + | "mintPlutusScript" + | "mintPlutusScriptV1" + | "mintPlutusScriptV2" + | "mintPlutusScriptV3" + | "mintingScript" + | "mintTxInReference" + | "mintReferenceTxInRedeemerValue" + | "mintRedeemerValue" + | "withdrawalPlutusScript" + | "withdrawalPlutusScriptV1" + | "withdrawalPlutusScriptV2" + | "withdrawalPlutusScriptV3" + | "withdrawalScript" + | "withdrawalTxInReference" + | "withdrawalReferenceTxInRedeemerValue" + | "withdrawalRedeemerValue" + | "votePlutusScript" + | "votePlutusScriptV1" + | "votePlutusScriptV2" + | "votePlutusScriptV3" + | "voteScript" + | "voteTxInReference" + | "voteReferenceTxInRedeemerValue" + | "voteRedeemerValue" + | "txInScript" + | "txInDatumValue" + | "txInInlineDatumPresent" + | "txInRedeemerValue"; + +// ── Spend Builder Types ──────────────────────────────────────────────── + +export interface SpendScriptBuilder { + script(scriptCbor: string): SpendRedeemerBuilder; + referenceScript( + refTxHash: string, + refTxIndex: number, + scriptSize?: string, + scriptHash?: string, + ): SpendRedeemerBuilder; +} + +export interface SpendRedeemerBuilder { + redeemerJson( + redeemer: BuilderData["content"], + exUnits?: Budget, + ): SpendTxOutBuilder; + redeemerCbor( + redeemer: BuilderData["content"], + exUnits?: Budget, + ): SpendTxOutBuilder; +} + +export interface SpendTxOutBuilder { + txOut(address: string, amount: Asset[]): SpendDatumBuilder; +} + +export interface SpendDatumBuilder { + datumHash(datumHash: string): _MeshTxBuilderV2; + datumCbor(datumCbor: BuilderData["content"]): _MeshTxBuilderV2; + datumJson(datumJson: BuilderData["content"]): _MeshTxBuilderV2; +} + +// ── Mint Builder Types ───────────────────────────────────────────────── + +export interface MintScriptBuilder { + script(scriptCbor: string): MintRedeemerBuilder; + referenceScript( + txHash: string, + txIndex: number, + scriptSize?: string, + scriptHash?: string, + ): MintRedeemerBuilder; +} + +export interface MintRedeemerBuilder { + redeemerJson( + redeemer: BuilderData["content"], + exUnits?: Budget, + ): MintTxOutBuilder; + redeemerCbor( + redeemer: BuilderData["content"], + exUnits?: Budget, + ): MintTxOutBuilder; +} + +export interface MintTxOutBuilder { + txOut(address: string, amount: Asset[]): _MeshTxBuilderV2; +} + +// ── Vote Builder Types ───────────────────────────────────────────────── + +export interface VoteScriptBuilder { + script(scriptCbor: string): VoteRedeemerBuilder; + referenceScript( + txHash: string, + txIndex: number, + scriptSize?: string, + scriptHash?: string, + ): VoteRedeemerBuilder; +} + +export interface VoteRedeemerBuilder { + redeemerJson( + redeemer: BuilderData["content"], + exUnits?: Budget, + ): _MeshTxBuilderV2; + redeemerCbor( + redeemer: BuilderData["content"], + exUnits?: Budget, + ): _MeshTxBuilderV2; +} + +// ── Withdrawal Builder Types ─────────────────────────────────────────── + +export interface WithdrawScriptBuilder { + script(scriptCbor: string): WithdrawRedeemerBuilder; + referenceScript( + txHash: string, + txIndex: number, + scriptSize?: string, + scriptHash?: string, + ): WithdrawRedeemerBuilder; +} + +export interface WithdrawRedeemerBuilder { + redeemerJson( + redeemer: BuilderData["content"], + exUnits?: Budget, + ): _MeshTxBuilderV2; + redeemerCbor( + redeemer: BuilderData["content"], + exUnits?: Budget, + ): _MeshTxBuilderV2; +}