diff --git a/patches/@evolution-sdk__evolution@0.3.19.patch b/patches/@evolution-sdk__evolution@0.3.19.patch index f3e2991..64aed2f 100644 --- a/patches/@evolution-sdk__evolution@0.3.19.patch +++ b/patches/@evolution-sdk__evolution@0.3.19.patch @@ -13,6 +13,32 @@ index 483bee1..472ca67 100644 return [txIn, txOut]; }) : []; const payload = { +diff --git a/dist/sdk/builders/TxBuilderImpl.js b/dist/sdk/builders/TxBuilderImpl.js +index a11735f..7533295 100644 +--- a/dist/sdk/builders/TxBuilderImpl.js ++++ b/dist/sdk/builders/TxBuilderImpl.js +@@ -510,8 +510,10 @@ export const assembleTransaction = (inputs, outputs, fee) => Effect.gen(function + // Inline datums (InlineDatum) are NOT added to plutusData - they're already in the UTxO + } + // Compute scriptDataHash if there are Plutus scripts (redeemers present) ++ // Also compute for CIP-0069 no-redeemer scripts (Plutus reference inputs used for minting) ++ const hasPlutusRefScripts = state.referenceInputs.some(r => r.scriptRef && (r.scriptRef._tag === 'PlutusV1' || r.scriptRef._tag === 'PlutusV2' || r.scriptRef._tag === 'PlutusV3')); + let scriptDataHash; +- if (redeemers.length > 0) { ++ if (redeemers.length > 0 || hasPlutusRefScripts) { + // Get config to access provider for full protocol parameters + const config = yield* TxBuilderConfigTag; + if (!config.provider) { +@@ -972,7 +974,8 @@ export const calculateFeeIteratively = (inputUtxos, inputs, outputs, redeemers, + totalCollateral = state.collateral.totalAmount; + } + // Check if Plutus scripts are present (need scriptDataHash for accurate size) +- const hasPlutusScripts = fakeWitnessSet.plutusV1Scripts && fakeWitnessSet.plutusV1Scripts.length > 0 || fakeWitnessSet.plutusV2Scripts && fakeWitnessSet.plutusV2Scripts.length > 0 || fakeWitnessSet.plutusV3Scripts && fakeWitnessSet.plutusV3Scripts.length > 0; ++ // Also check reference inputs for CIP-0069 no-redeemer Plutus scripts ++ const hasPlutusScripts = fakeWitnessSet.plutusV1Scripts && fakeWitnessSet.plutusV1Scripts.length > 0 || fakeWitnessSet.plutusV2Scripts && fakeWitnessSet.plutusV2Scripts.length > 0 || fakeWitnessSet.plutusV3Scripts && fakeWitnessSet.plutusV3Scripts.length > 0 || state.referenceInputs.some(r => r.scriptRef && (r.scriptRef._tag === 'PlutusV1' || r.scriptRef._tag === 'PlutusV2' || r.scriptRef._tag === 'PlutusV3')); + // Create placeholder scriptDataHash if Plutus scripts are present + // This is needed for accurate size estimation (32 bytes + CBOR overhead) + const placeholderScriptDataHash = hasPlutusScripts ? new ScriptDataHash.ScriptDataHash({ diff --git a/src/sdk/provider/internal/BlockfrostEffect.ts b/src/sdk/provider/internal/BlockfrostEffect.ts index 4271f0b..6f0ccb3 100644 --- a/src/sdk/provider/internal/BlockfrostEffect.ts @@ -29,3 +55,75 @@ index 4271f0b..6f0ccb3 100644 return [txIn, txOut] }) : [] +diff --git a/src/sdk/builders/TxBuilderImpl.ts b/src/sdk/builders/TxBuilderImpl.ts +index a3efb7d..b435b3c 100644 +--- a/src/sdk/builders/TxBuilderImpl.ts ++++ b/src/sdk/builders/TxBuilderImpl.ts +@@ -653,8 +653,16 @@ export const assembleTransaction = ( + } + + // Compute scriptDataHash if there are Plutus scripts (redeemers present) ++ // Also compute for CIP-0069 no-redeemer scripts (Plutus reference inputs used for minting) ++ const hasPlutusRefScripts = state.referenceInputs.some( ++ (r) => ++ r.scriptRef && ++ (r.scriptRef._tag === "PlutusV1" || ++ r.scriptRef._tag === "PlutusV2" || ++ r.scriptRef._tag === "PlutusV3") ++ ) + let scriptDataHash: ReturnType | undefined +- if (redeemers.length > 0) { ++ if (redeemers.length > 0 || hasPlutusRefScripts) { + // Get config to access provider for full protocol parameters + const config = yield* TxBuilderConfigTag + +@@ -1213,10 +1221,18 @@ export const calculateFeeIteratively = ( + } + + // Check if Plutus scripts are present (need scriptDataHash for accurate size) ++ // Also check reference inputs for CIP-0069 no-redeemer Plutus scripts + const hasPlutusScripts = + (fakeWitnessSet.plutusV1Scripts && fakeWitnessSet.plutusV1Scripts.length > 0) || + (fakeWitnessSet.plutusV2Scripts && fakeWitnessSet.plutusV2Scripts.length > 0) || +- (fakeWitnessSet.plutusV3Scripts && fakeWitnessSet.plutusV3Scripts.length > 0) ++ (fakeWitnessSet.plutusV3Scripts && fakeWitnessSet.plutusV3Scripts.length > 0) || ++ state.referenceInputs.some( ++ (r) => ++ r.scriptRef && ++ (r.scriptRef._tag === "PlutusV1" || ++ r.scriptRef._tag === "PlutusV2" || ++ r.scriptRef._tag === "PlutusV3") ++ ) + + // Create placeholder scriptDataHash if Plutus scripts are present + // This is needed for accurate size estimation (32 bytes + CBOR overhead) +diff --git a/dist/utils/Hash.js b/dist/utils/Hash.js +index 71bc97f..bf9217c 100644 +--- a/dist/utils/Hash.js ++++ b/dist/utils/Hash.js +@@ -137,6 +137,10 @@ export const hashScriptData = (redeemers, costModels, datums, format = "array", + // Empty map + datumsBytes, new Uint8Array([0xa0]) // Empty map + ); ++ } else if (redeemers.length === 0 && !hasDatums) { ++ // CIP-0069 case: no redeemers, no datums, but language views needed. ++ // Conway era uses A0 (empty CBOR map) to represent absent redeemers. ++ payload = concatBytes(new Uint8Array([0xa0]), langViewsBytes); + } else { + // Normal case: [ redeemers | datums | language_views ] + const redeemersCollection = new Redeemers.Redeemers({ +diff --git a/src/utils/Hash.ts b/src/utils/Hash.ts +index f535ad5..b7e679e 100644 +--- a/src/utils/Hash.ts ++++ b/src/utils/Hash.ts +@@ -160,6 +160,10 @@ export const hashScriptData = ( + datumsBytes, + new Uint8Array([0xa0]) // Empty map + ) ++ } else if (redeemers.length === 0 && !hasDatums) { ++ // CIP-0069 case: no redeemers, no datums, but language views needed. ++ // Conway era uses A0 (empty CBOR map) to represent absent redeemers. ++ payload = concatBytes(new Uint8Array([0xa0]), langViewsBytes) + } else { + // Normal case: [ redeemers | datums | language_views ] + const redeemersCollection = new Redeemers.Redeemers({ values: [...redeemers] }) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b5dcaca..f180904 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,7 +6,7 @@ settings: patchedDependencies: '@evolution-sdk/evolution@0.3.19': - hash: 934855467f3b911bcd9728b54cc4061ffeec50f548c615eeebc6cb0a121fbc5c + hash: 192466773327d393a0602fae0396bea124d4da580be9028cc0b0e3dbaed81ef1 path: patches/@evolution-sdk__evolution@0.3.19.patch importers: @@ -15,7 +15,7 @@ importers: dependencies: '@evolution-sdk/evolution': specifier: ^0.3.19 - version: 0.3.19(patch_hash=934855467f3b911bcd9728b54cc4061ffeec50f548c615eeebc6cb0a121fbc5c)(@effect/cluster@0.48.16(@effect/platform@0.90.10(effect@3.19.19))(@effect/rpc@0.69.5(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(@effect/sql@0.44.2(@effect/experimental@0.54.6(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(@effect/workflow@0.9.6(@effect/platform@0.90.10(effect@3.19.19))(@effect/rpc@0.69.5(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(effect@3.19.19))(effect@3.19.19))(@effect/rpc@0.69.5(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(@effect/sql@0.44.2(@effect/experimental@0.54.6(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19)) + version: 0.3.19(patch_hash=192466773327d393a0602fae0396bea124d4da580be9028cc0b0e3dbaed81ef1)(@effect/cluster@0.48.16(@effect/platform@0.90.10(effect@3.19.19))(@effect/rpc@0.69.5(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(@effect/sql@0.44.2(@effect/experimental@0.54.6(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(@effect/workflow@0.9.6(@effect/platform@0.90.10(effect@3.19.19))(@effect/rpc@0.69.5(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(effect@3.19.19))(effect@3.19.19))(@effect/rpc@0.69.5(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(@effect/sql@0.44.2(@effect/experimental@0.54.6(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19)) '@inquirer/prompts': specifier: ^8.3.0 version: 8.3.0(@types/node@22.19.13) @@ -2397,7 +2397,7 @@ snapshots: '@eslint/core': 0.17.0 levn: 0.4.1 - '@evolution-sdk/evolution@0.3.19(patch_hash=934855467f3b911bcd9728b54cc4061ffeec50f548c615eeebc6cb0a121fbc5c)(@effect/cluster@0.48.16(@effect/platform@0.90.10(effect@3.19.19))(@effect/rpc@0.69.5(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(@effect/sql@0.44.2(@effect/experimental@0.54.6(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(@effect/workflow@0.9.6(@effect/platform@0.90.10(effect@3.19.19))(@effect/rpc@0.69.5(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(effect@3.19.19))(effect@3.19.19))(@effect/rpc@0.69.5(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(@effect/sql@0.44.2(@effect/experimental@0.54.6(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))': + '@evolution-sdk/evolution@0.3.19(patch_hash=192466773327d393a0602fae0396bea124d4da580be9028cc0b0e3dbaed81ef1)(@effect/cluster@0.48.16(@effect/platform@0.90.10(effect@3.19.19))(@effect/rpc@0.69.5(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(@effect/sql@0.44.2(@effect/experimental@0.54.6(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(@effect/workflow@0.9.6(@effect/platform@0.90.10(effect@3.19.19))(@effect/rpc@0.69.5(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(effect@3.19.19))(effect@3.19.19))(@effect/rpc@0.69.5(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(@effect/sql@0.44.2(@effect/experimental@0.54.6(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))': dependencies: '@effect/platform': 0.90.10(effect@3.19.19) '@effect/platform-node': 0.96.1(@effect/cluster@0.48.16(@effect/platform@0.90.10(effect@3.19.19))(@effect/rpc@0.69.5(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(@effect/sql@0.44.2(@effect/experimental@0.54.6(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(@effect/workflow@0.9.6(@effect/platform@0.90.10(effect@3.19.19))(@effect/rpc@0.69.5(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(effect@3.19.19))(effect@3.19.19))(@effect/platform@0.90.10(effect@3.19.19))(@effect/rpc@0.69.5(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(@effect/sql@0.44.2(@effect/experimental@0.54.6(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(@effect/platform@0.90.10(effect@3.19.19))(effect@3.19.19))(effect@3.19.19) diff --git a/src/mint.ts b/src/mint.ts index f02e221..1d69c02 100644 --- a/src/mint.ts +++ b/src/mint.ts @@ -122,10 +122,9 @@ const program = new Command() cborTxs.push(deployChain.cbor); // Mint transaction: mint token using the deployed reference script. - // Pass deployChain.available as availableUtxos so coin selection only uses - // off-chain UTxOs; this prevents on-chain UTxOs from being included in the - // additionalUtxoSet passed to the evaluator, which would cause an - // OverlappingAdditionalUtxo error. + // The scriptDataHash is computed by the SDK even without an explicit redeemer + // because the Aiken validator uses CIP-0069 (no-redeemer mint), which requires + // the scriptDataHash to commit to the PlutusV3 language views. const mintResult = await client .newTx() .mintAssets({ @@ -137,7 +136,6 @@ const program = new Command() .build({ changeAddress, availableUtxos: deployChain.available, - passAdditionalUtxos: true, }); const mintChain = await buildAndChain(mintResult, deployChain.available);