<p>As Manu already mentioned it seems like the provider on which <code>wallet.submitTx</code> is based on is passing a Contex of PlutusV1 while your script expects a context of PlutusV2</p>
<p>this is not the fault of mesh; rather than whatever the wallet uses to submit the transaction</p>
<p>You might want to try a different submission method; as an example you could perform a <a href="https://api.koios.rest/#post-/submittx" rel="nofollow noreferrer">POST request to koios</a>.</p>
<blockquote>
<p><strong>NOTE</strong> <code>netToDom</code> maps a given <code>KoiosNetwork</code> to the matching sub domain</p>
</blockquote>
<p>here is an example on how a transaciton is submitted using the code from <a href="https://github.com/HarmonicLabs/koios-pluts/blob/main/src/tx/submit.ts#L18" rel="nofollow noreferrer">koios-pluts</a></p>
<pre class="lang-typescript prettyprint-override"><code>export async function submitTx( tx: Tx, network: KoiosNetwork = &quot;mainnet&quot; ): Promise&lt;Hash32&gt;
{
    const net: KoiosNetwork = tx.body.network === &quot;testnet&quot; ?
        ( network === &quot;preview&quot; ? &quot;preview&quot; : &quot;preprod&quot; ) :
        &quot;mainnet&quot;;

    return fetch(`https://${netToDom(net)}.koios.rest/api/v0/submittx`, {
        method: &quot;post&quot;,
        headers: {
          'Content-Type': 'application/cbor'
        },
        body: tx.toCbor().toBuffer().buffer
    })
    .then(  res =&gt;  {

        if( !res.ok )
        throw new KoiosError(
            &quot;error submitting '&quot; + tx.hash.toString() + &quot;' transaction; &quot; +
            &quot;endpoint used: &quot; + `https://${netToDom(net)}.koios.rest/api/v0/submittx ` +
            &quot;JSON form of the tranascton: &quot; +
            JSON.stringify(
                tx.toJson(),
                undefined,
                2
            )
        );

        return tx.hash;
    })
}
</code></pre>

CC BY-SA 4.0
2023-04-29T22:45:05.847Z
2023-04-29T22:45:05.847Z
Michele Nuzzi
<p>Just an idea, instead of using:</p>
<pre><code>mkPolicy :: BuiltinData -&gt; PlutusV2.ScriptContext -&gt; Bool   
</code></pre>
<p>Use:</p>
<pre><code>mkPolicy :: BuiltinData -&gt; PlutusV1.ScriptContext -&gt; Bool   
</code></pre>
<p>It looks like MESH is creating a transaction with a valid redeemer but not a valid context. Could be that its creating a context of Plutus V1, witch is different data structure in Plutus V2 where there are more fields.</p>
<p>You will need to change other mentions to PlutusV2 and use PlutusV1 in your code.</p>

CC BY-SA 4.0
2023-02-14T17:09:24.977Z
2023-02-14T17:09:24.977Z
Manu Padilla
<p>Your script seems simple enough, and this is what it would look like in Helios (which is both an on-chain compiler and off-chain tx builder).   Maybe try it on helios and then try to debug what's wrong with your mesh implementation.</p>
<p>I've also got a video on minting an nft with Helios here <a href="https://www.youtube.com/watch?v=5iPqe-HNIUE" rel="nofollow noreferrer">https://www.youtube.com/watch?v=5iPqe-HNIUE</a></p>
<p><a href="https://github.com/lley154/helios-examples/blob/main/nft/pages/index.tsx" rel="nofollow noreferrer">https://github.com/lley154/helios-examples/blob/main/nft/pages/index.tsx</a></p>
<pre><code>...

  const mintNFT = async (params : any) =&gt; {

    const address = params[0];
    const name = params[1];
    const description = params[2];
    const img = params[3];
    const minAdaVal = new Value(BigInt(2000000));  // minimum Ada needed to send an NFT

    // Get wallet UTXOs
    const walletHelper = new WalletHelper(walletAPI);
    const utxos = await walletHelper.pickUtxos(minAdaVal);
 
    // Get change address
    const changeAddr = await walletHelper.changeAddress;

    // Determine the UTXO used for collateral
    const colatUtxo = await walletHelper.pickCollateral();

    // Start building the transaction
    const tx = new Tx();

    // Add the UTXO as inputs
    tx.addInputs(utxos[0]);

    const mintScript =`minting nft
    const TX_ID: ByteArray = #` + utxos[0][0].txId.hex + `
    const txId: TxId = TxId::new(TX_ID)
    const outputId: TxOutputId = TxOutputId::new(txId, ` + utxos[0][0].utxoIdx + `)
    
    func main(ctx: ScriptContext) -&gt; Bool {
        tx: Tx = ctx.tx;
        mph: MintingPolicyHash = ctx.get_current_minting_policy_hash();
    
        assetclass: AssetClass = AssetClass::new(
            mph, 
            &quot;` + name + `&quot;.encode_utf8()
        );
        value_minted: Value = tx.minted;
    
        // Validator logic starts
        (value_minted == Value::new(assetclass, 1)).trace(&quot;NFT:1 &quot;) &amp;&amp;
        tx.inputs.any((input: TxInput) -&gt; Bool {
                                        (input.output_id == outputId).trace(&quot;NFT2: &quot;)
                                        }
        )
    }`
    
    // Compile the helios minting script
    const mintProgram = Program.new(mintScript).compile(optimize);

    // Add the script as a witness to the transaction
    tx.attachScript(mintProgram);

    // Construct the NFT that we will want to send as an output
    const nftTokenName = ByteArrayData.fromString(name).toHex();
    const tokens: [number[], bigint][] = [[hexToBytes(nftTokenName), BigInt(1)]];

    // Create an empty Redeemer because we must always send a Redeemer with
    // a plutus script transaction even if we don't actually use it.
    const mintRedeemer = new ConstrData(0, []);

    // Indicate the minting we want to include as part of this transaction
    tx.mintTokens(
      mintProgram.mintingPolicyHash,
      tokens,
      mintRedeemer
    )

    // Construct the output and include both the minimum Ada as well as the minted NFT
    tx.addOutput(new TxOutput(
      Address.fromBech32(address),
      new Value(minAdaVal.lovelace, new Assets([[mintProgram.mintingPolicyHash, tokens]]))
    ));

    // Add the collateral utxo
    tx.addCollateral(colatUtxo);

    const networkParams = new NetworkParams(
      await fetch(networkParamsUrl)
          .then(response =&gt; response.json())
    )

    // Attached the metadata for the minting transaction
    tx.addMetadata(721, {&quot;map&quot;: [[mintProgram.mintingPolicyHash.hex, {&quot;map&quot;: [[name, 
                                      {
                                        &quot;map&quot;: [[&quot;name&quot;, name], 
                                                [&quot;description&quot;, description],
                                                [&quot;image&quot;, img]
                                              ]
                                      }
                                  ]]}
                                ]]
                        }
                  );

    console.log(&quot;tx before final&quot;, tx.dump());

    // Send any change back to the buyer
    await tx.finalize(networkParams, changeAddr);
    console.log(&quot;tx after final&quot;, tx.dump());

    console.log(&quot;Verifying signature...&quot;);
    const signatures = await walletAPI.signTx(tx);
    tx.addSignatures(signatures);
    
    console.log(&quot;Submitting transaction...&quot;);
    const txHash = await walletAPI.submitTx(tx);
    
    console.log(&quot;txHash&quot;, txHash);
    setTx({ txId: txHash.hex });

</code></pre>

CC BY-SA 4.0
2023-02-10T00:20:30.057Z
2023-02-10T00:20:30.057Z
lley154
<p>This my script for minting NFT:</p>
<pre class="lang-haskell prettyprint-override"><code>{-# INLINABLE mkPolicy #-}
mkPolicy :: BuiltinData -&gt; PlutusV2.ScriptContext -&gt; Bool
mkPolicy _ ctx = traceIfFalse &quot;wrong amount minted&quot; checkNFTAmount

  where
    info :: PlutusV2.TxInfo
    info = PlutusV2.scriptContextTxInfo ctx

    -- hasUTxO :: Bool
    -- hasUTxO = any (\i -&gt; PlutusV2.txInInfoOutRef i == mpTxOutRef r) $ PlutusV2.txInfoInputs info

    checkNFTAmount :: Bool
    checkNFTAmount = case Value.flattenValue (PlutusV2.txInfoMint info) of
       [(cs, tn', amt)] -&gt; cs  == ownCurrencySymbol ctx &amp;&amp; tn' == PlutusV2.TokenName &quot;&quot; &amp;&amp; amt == 1
       _                -&gt; False

{-
    As a Minting Policy
-}

compiledCode :: PlutusTx.CompiledCode (BuiltinData -&gt; BuiltinData -&gt; ())
compiledCode = $$(PlutusTx.compile [|| wrap ||])
  where
    wrap = Scripts.mkUntypedMintingPolicy mkPolicy 

policy :: Scripts.MintingPolicy
policy = PlutusV2.mkMintingPolicyScript compiledCode

script :: PlutusV2.Script
script = PlutusV2.unMintingPolicyScript policy
{-
    As a Short Byte String
-}

scriptSBS :: SBS.ShortByteString
scriptSBS = SBS.toShort . LBS.toStrict $ serialise script

{-
    As a Serialised Script
-}

serialisedScript :: PlutusScript PlutusScriptV2
serialisedScript = PlutusScriptSerialised scriptSBS

writeSerialisedScript :: IO ()
writeSerialisedScript = void $ writeFileTextEnvelope &quot;nft-mint-V2.plutus&quot; Nothing serialisedScript

</code></pre>
<p>I'm using Mesh to minting NFT with that script</p>
<pre class="lang-typescript prettyprint-override"><code>    const walletAddr = wallet.getPaymentAddress();
    const addressUtxo: UTxO[] = await provider.fetchAddressUTxOs(walletAddr);

    const redeemer: Partial&lt;Action&gt; = {
        tag: &quot;MINT&quot;,
        data: {
            alternative: 0,
            fields: [],
        },
    };

    const assetMetadata: AssetMetadata = {
        name: &quot;MyNFT&quot;,
        image: &quot;https://picsum.photos/200&quot;,
        mediaType: &quot;image/jpg&quot;,
        description: &quot;This NFT is minted by me.&quot;,
    };

    const asset: Mint = {
        assetName: &quot;MyNFT&quot;,
        assetQuantity: &quot;1&quot;,
        metadata: assetMetadata,
        label: &quot;721&quot;,
        recipient: walletAddr,
    };

    // Mint NFT

    const tx = new Transaction({ initiator: wallet });

    tx.mintAsset(script, asset, redeemer);
    tx.setCollateral([addressUtxo[0]]);

    const unsignedTx = await tx.build();
    const signedTx = await wallet.signTx(unsignedTx, true);
    try {
        const txHash = await wallet.submitTx(signedTx);
        console.log(txHash);
    } catch (e) {
        console.log(e);
    }
</code></pre>
<p>Unfortunately, it returned with this error:</p>
<pre><code>transaction submit error ShelleyTxValidationError ShelleyBasedEraBabbage 
(ApplyTxError 
[UtxowFailure 
(UtxoFailure 
(FromAlonzoUtxoFail 
(UtxosFailure 
(ValidationTagMismatch 
(IsValid True) 
(FailedUnexpectedly 
(PlutusFailure \\\&quot;\\\\nThe 2 arg plutus script (PlutusScript PlutusV2 ScriptHash \\\\\\\&quot;77f807bc9403ef0177cc2a9956bfd5628ee649680041ccf48a198fc0\\\\\\\&quot;) fails.
\\\\nCekError An error has occurred:  
User error:\\\\nThe machine terminated because of an error, either from a built-in function or from an explicit use of 'error'.
\\\\nThe protocol version is: ProtVer {pvMajor = 7, pvMinor = 0}\\\\nThe redeemer is: Constr 0 []\\\\
nThe second data argument, does not decode to a context
</code></pre>
<p>Does anyone faced this error before, what's wrong with my script?</p>

CC BY-SA 4.0
2023-02-08T12:46:49.800Z
I think this is to do with the conversion of `Data` to `ScriptContext`.  How are you compiling and serialising your policy?
james
CC BY-SA 4.0
2023-02-08T13:11:29.227Z
I updated the compile code above, can you take a look at that @james
Daniel Ng
CC BY-SA 4.0
2023-02-08T13:40:38.020Z
I think the script is produced correctly. Unfortunately, I cannot help with how it is used to construct a transaction using Mesh. You could start by verifying the script is correct by using cardano-cli.
james
<plutus><smart-contract><script><mesh>
"The second data argument, does not decode to a context" when minting NFT with Mesh
# "The second data argument, does not decode to a context" when minting NFT with Mesh

(Asked by: username_0 on 2023-02-08)

This my script for minting NFT:
{-# INLINABLE mkPolicy #-}
mkPolicy :: BuiltinData -> PlutusV2.ScriptContext -> Bool
mkPolicy _ ctx = traceIfFalse "wrong amount minted" checkNFTAmount

  where
    info :: PlutusV2.TxInfo
    info = PlutusV2.scriptContextTxInfo ctx

    -- hasUTxO :: Bool
    -- hasUTxO = any (\i -> PlutusV2.txInInfoOutRef i == mpTxOutRef r) $ PlutusV2.txInfoInputs info

    checkNFTAmount :: Bool
    checkNFTAmount = case Value.flattenValue (PlutusV2.txInfoMint info) of
       [(cs, tn', amt)] -> cs  == ownCurrencySymbol ctx && tn' == PlutusV2.TokenName "" && amt == 1
       _                -> False

{-
    As a Minting Policy
-}

compiledCode :: PlutusTx.CompiledCode (BuiltinData -> BuiltinData -> ())
compiledCode = $$(PlutusTx.compile [|| wrap ||])
  where
    wrap = Scripts.mkUntypedMintingPolicy mkPolicy 

policy :: Scripts.MintingPolicy
policy = PlutusV2.mkMintingPolicyScript compiledCode

script :: PlutusV2.Script
script = PlutusV2.unMintingPolicyScript policy
{-
    As a Short Byte String
-}

scriptSBS :: SBS.ShortByteString
scriptSBS = SBS.toShort . LBS.toStrict $ serialise script

{-
    As a Serialised Script
-}

serialisedScript :: PlutusScript PlutusScriptV2
serialisedScript = PlutusScriptSerialised scriptSBS

writeSerialisedScript :: IO ()
writeSerialisedScript = void $ writeFileTextEnvelope "nft-mint-V2.plutus" Nothing serialisedScript


I'm using Mesh to minting NFT with that script
    const walletAddr = wallet.getPaymentAddress();
    const addressUtxo: UTxO[] = await provider.fetchAddressUTxOs(walletAddr);

    const redeemer: Partial = {
        tag: "MINT",
        data: {
            alternative: 0,
            fields: [],
        },
    };

    const assetMetadata: AssetMetadata = {
        name: "MyNFT",
        image: "https://picsum.photos/200",
        mediaType: "image/jpg",
        description: "This NFT is minted by me.",
    };

    const asset: Mint = {
        assetName: "MyNFT",
        assetQuantity: "1",
        metadata: assetMetadata,
        label: "721",
        recipient: walletAddr,
    };

    // Mint NFT

    const tx = new Transaction({ initiator: wallet });

    tx.mintAsset(script, asset, redeemer);
    tx.setCollateral([addressUtxo[0]]);

    const unsignedTx = await tx.build();
    const signedTx = await wallet.signTx(unsignedTx, true);
    try {
        const txHash = await wallet.submitTx(signedTx);
        console.log(txHash);
    } catch (e) {
        console.log(e);
    }

Unfortunately, it returned with this error:
transaction submit error ShelleyTxValidationError ShelleyBasedEraBabbage 
(ApplyTxError 
[UtxowFailure 
(UtxoFailure 
(FromAlonzoUtxoFail 
(UtxosFailure 
(ValidationTagMismatch 
(IsValid True) 
(FailedUnexpectedly 
(PlutusFailure \\\"\\\\nThe 2 arg plutus script (PlutusScript PlutusV2 ScriptHash \\\\\\\"77f807bc9403ef0177cc2a9956bfd5628ee649680041ccf48a198fc0\\\\\\\") fails.
\\\\nCekError An error has occurred:  
User error:\\\\nThe machine terminated because of an error, either from a built-in function or from an explicit use of 'error'.
\\\\nThe protocol version is: ProtVer {pvMajor = 7, pvMinor = 0}\\\\nThe redeemer is: Constr 0 []\\\\
nThe second data argument, does not decode to a context

Does anyone faced this error before, what's wrong with my script?

**Tags:** plutus, smart-contract, script, mesh
> **Comments:**
> **username_1**: I think this is to do with the conversion of `Data` to `ScriptContext`.  How are you compiling and serialising your policy?  
> **username_0**: I updated the compile code above, can you take a look at that @james  
> **username_1**: I think the script is produced correctly. Unfortunately, I cannot help with how it is used to construct a transaction using Mesh. You could start by verifying the script is correct by using cardano-cli.  

---

## 3 answers

### Answer by username_2 on 2023-04-29. Score: 1

As Manu already mentioned it seems like the provider on which wallet.submitTx is based on is passing a Contex of PlutusV1 while your script expects a context of PlutusV2
this is not the fault of mesh; rather than whatever the wallet uses to submit the transaction
You might want to try a different submission method; as an example you could perform a POST request to koios.

NOTE netToDom maps a given KoiosNetwork to the matching sub domain

here is an example on how a transaciton is submitted using the code from koios-pluts
export async function submitTx( tx: Tx, network: KoiosNetwork = "mainnet" ): Promise
{
    const net: KoiosNetwork = tx.body.network === "testnet" ?
        ( network === "preview" ? "preview" : "preprod" ) :
        "mainnet";

    return fetch(`https://${netToDom(net)}.koios.rest/api/v0/submittx`, {
        method: "post",
        headers: {
          'Content-Type': 'application/cbor'
        },
        body: tx.toCbor().toBuffer().buffer
    })
    .then(  res =>  {

        if( !res.ok )
        throw new KoiosError(
            "error submitting '" + tx.hash.toString() + "' transaction; " +
            "endpoint used: " + `https://${netToDom(net)}.koios.rest/api/v0/submittx ` +
            "JSON form of the tranascton: " +
            JSON.stringify(
                tx.toJson(),
                undefined,
                2
            )
        );

        return tx.hash;
    })
}


---

### Answer by username_3 on 2023-02-14. Score: 0

Just an idea, instead of using:
mkPolicy :: BuiltinData -> PlutusV2.ScriptContext -> Bool   

Use:
mkPolicy :: BuiltinData -> PlutusV1.ScriptContext -> Bool   

It looks like MESH is creating a transaction with a valid redeemer but not a valid context. Could be that its creating a context of Plutus V1, witch is different data structure in Plutus V2 where there are more fields.
You will need to change other mentions to PlutusV2 and use PlutusV1 in your code.


---

### Answer by username_4 on 2023-02-10. Score: -1

Your script seems simple enough, and this is what it would look like in Helios (which is both an on-chain compiler and off-chain tx builder).   Maybe try it on helios and then try to debug what's wrong with your mesh implementation.
I've also got a video on minting an nft with Helios here https://www.youtube.com/watch?v=5iPqe-HNIUE
https://github.com/lley154/helios-examples/blob/main/nft/pages/index.tsx
...

  const mintNFT = async (params : any) => {

    const address = params[0];
    const name = params[1];
    const description = params[2];
    const img = params[3];
    const minAdaVal = new Value(BigInt(2000000));  // minimum Ada needed to send an NFT

    // Get wallet UTXOs
    const walletHelper = new WalletHelper(walletAPI);
    const utxos = await walletHelper.pickUtxos(minAdaVal);
 
    // Get change address
    const changeAddr = await walletHelper.changeAddress;

    // Determine the UTXO used for collateral
    const colatUtxo = await walletHelper.pickCollateral();

    // Start building the transaction
    const tx = new Tx();

    // Add the UTXO as inputs
    tx.addInputs(utxos[0]);

    const mintScript =`minting nft
    const TX_ID: ByteArray = #` + utxos[0][0].txId.hex + `
    const txId: TxId = TxId::new(TX_ID)
    const outputId: TxOutputId = TxOutputId::new(txId, ` + utxos[0][0].utxoIdx + `)
    
    func main(ctx: ScriptContext) -> Bool {
        tx: Tx = ctx.tx;
        mph: MintingPolicyHash = ctx.get_current_minting_policy_hash();
    
        assetclass: AssetClass = AssetClass::new(
            mph, 
            "` + name + `".encode_utf8()
        );
        value_minted: Value = tx.minted;
    
        // Validator logic starts
        (value_minted == Value::new(assetclass, 1)).trace("NFT:1 ") &&
        tx.inputs.any((input: TxInput) -> Bool {
                                        (input.output_id == outputId).trace("NFT2: ")
                                        }
        )
    }`
    
    // Compile the helios minting script
    const mintProgram = Program.new(mintScript).compile(optimize);

    // Add the script as a witness to the transaction
    tx.attachScript(mintProgram);

    // Construct the NFT that we will want to send as an output
    const nftTokenName = ByteArrayData.fromString(name).toHex();
    const tokens: [number[], bigint][] = [[hexToBytes(nftTokenName), BigInt(1)]];

    // Create an empty Redeemer because we must always send a Redeemer with
    // a plutus script transaction even if we don't actually use it.
    const mintRedeemer = new ConstrData(0, []);

    // Indicate the minting we want to include as part of this transaction
    tx.mintTokens(
      mintProgram.mintingPolicyHash,
      tokens,
      mintRedeemer
    )

    // Construct the output and include both the minimum Ada as well as the minted NFT
    tx.addOutput(new TxOutput(
      Address.fromBech32(address),
      new Value(minAdaVal.lovelace, new Assets([[mintProgram.mintingPolicyHash, tokens]]))
    ));

    // Add the collateral utxo
    tx.addCollateral(colatUtxo);

    const networkParams = new NetworkParams(
      await fetch(networkParamsUrl)
          .then(response => response.json())
    )

    // Attached the metadata for the minting transaction
    tx.addMetadata(721, {"map": [[mintProgram.mintingPolicyHash.hex, {"map": [[name, 
                                      {
                                        "map": [["name", name], 
                                                ["description", description],
                                                ["image", img]
                                              ]
                                      }
                                  ]]}
                                ]]
                        }
                  );

    console.log("tx before final", tx.dump());

    // Send any change back to the buyer
    await tx.finalize(networkParams, changeAddr);
    console.log("tx after final", tx.dump());

    console.log("Verifying signature...");
    const signatures = await walletAPI.signTx(tx);
    tx.addSignatures(signatures);
    
    console.log("Submitting transaction...");
    const txHash = await walletAPI.submitTx(tx);
    
    console.log("txHash", txHash);
    setTx({ txId: txHash.hex });


---

