1

I'm trying to mint a native asset reusing the keys that Nami already uses. This is to make a minting service that is connected to a specific wallet, and that wallet is always able to mint more tokens if they want to.

However, it doesn't seem like Nami is providing all the signatures that I need. When submitting the transaction I get the following error:

transaction submit error ShelleyTxValidationError ShelleyBasedEraAlonzo (ApplyTxError [UtxowFailure (WrappedShelleyEraFailure (MissingScriptWitnessesUTXOW (fromList [ScriptHash \"9f84ae8b52e374a0cd09e7ec10854309f8dd7b1f5caf69dd658ed6c5\"]))),UtxowFailure (WrappedShelleyEraFailure (UtxoFailure (UtxosFailure (CollectErrors [NoRedeemer (Minting (PolicyID {policyID = ScriptHash \"9f84ae8b52e374a0cd09e7ec10854309f8dd7b1f5caf69dd658ed6c5\"})),NoWitness (ScriptHash \"9f84ae8b52e374a0cd09e7ec10854309f8dd7b1f5caf69dd658ed6c5\")]))))])

I seem to be missing the witness for the native asset script. Is there any way of making Nami sign this or is it impossible? Note that I'm already using the signTx(...) endpoint so it seems to be signing the entire transaction just not what is required by the minting script.

Code:

async function mint(mintData: MintData, wasm: any, walletConnector: WalletConnector){
  const userAddress: Address = wasm.Address.from_bytes(
    Buffer.from(mintData.address, "hex")
  )
  
  const p = await initTx() 

  const txBuilder: TransactionBuilder = wasm.TransactionBuilder.new(
    wasm.TransactionBuilderConfigBuilder.new()
      .fee_algo(wasm.LinearFee.new(wasm.BigNum.from_str(p.linearFee.minFeeA),
                                  wasm.BigNum.from_str(p.linearFee.minFeeB)))
      .pool_deposit(wasm.BigNum.from_str(p.poolDeposit))
      .key_deposit(wasm.BigNum.from_str(p.keyDeposit))
      .coins_per_utxo_word(wasm.BigNum.from_str(p.coinsPerUtxoWord))
      .max_value_size(p.maxValSize)
      .max_tx_size(p.maxTxSize)
      .build()
  );
  
  const invalidHereafter=10

  if (p.slot === null){
    return
  }

  const ttl = p.slot+invalidHereafter
  const timelockExpiry = wasm.TimelockExpiry.new(ttl)
  const timeLockedPolicyScript = wasm.NativeScript.new_timelock_expiry(timelockExpiry)
  const policyScripts = wasm.NativeScripts.new()
  policyScripts.add(timeLockedPolicyScript)
  const scriptHash = wasm.ScriptHash.from_bytes(timeLockedPolicyScript.hash().to_bytes())
  const policyID = bytesToString(timeLockedPolicyScript.hash().to_bytes())

  //const assetName = Buffer.from(mintData.tokenName, 'hex')
  txBuilder.add_mint_asset_and_output_min_required_coin(
    timeLockedPolicyScript, 
    wasm.AssetName.new(mintData.tokenName), 
    wasm.Int.new_i32(mintData.amount),
    userAddress,
    );
  

  const valueFilter: Value = wasm.Value.new(wasm.BigNum.from_str("5000000")) 
  //Add inputs
  const utxos: TransactionUnspentOutputs = wasm.TransactionUnspentOutputs.new();
  (await walletConnector.getUtxos(Buffer.from(valueFilter.to_bytes()).toString('hex')))
                .forEach(rawUTXO => {
                  const utxo: TransactionUnspentOutput = wasm.TransactionUnspentOutput.from_bytes(Buffer.from(rawUTXO, "hex"))
                  utxos.add(utxo)
                })

  
  txBuilder.add_inputs_from(utxos, 0)

  txBuilder.add_change_if_needed(userAddress)
  
  const toBeSignedTx: Transaction = txBuilder.build_tx();
  const rawToBeSignedTx: string = Buffer.from(toBeSignedTx.to_bytes()).toString('hex')

  const rawWitnesses: string = await walletConnector.signTx(rawToBeSignedTx)
  const witnessSet = wasm.TransactionWitnessSet.from_bytes(
    Buffer.from(rawWitnesses, "hex")
  )
  const witnessSets: TransactionWitnessSets = wasm.TransactionWitnessSets.new()
  witnessSets.add(witnessSet)

  const submitTx: Transaction = 
    wasm.Transaction.new(
      toBeSignedTx.body(),
      witnessSet
    )
  const rawSubmitTx: string = Buffer.from(submitTx.to_bytes()).toString('hex')
  walletConnector.submitTx(rawSubmitTx) // <- Error occurs when submitting

}
3
  • lol I probably need to use signData(...) I'll update the post if that turns out to be the solution Commented Dec 11, 2021 at 10:59
  • Where are you running it? is it Ts ? what is this walletConnector objet? Commented Dec 14, 2021 at 14:51
  • Yes it is possible, i am doing it with out any problems. So the problem must be somewhere in your code. As far as i see you are signing correctly. And you are not adding addressKeyHash in the policy, so there might be a problem related to other utxo? how are you getting the utxos? ... Can you send a simpler Tx, with out minting? Commented Dec 14, 2021 at 15:02

2 Answers 2

0

This error indicates you have all the witnesses you need for the transaction except the minting script and the policy key witness for minting.

You should be able to add a witnessSet to the transaction containing the missing policy script and policy key witness(es) before submitting.

0

Instead of using a time-locked script, I required the user to include their wallet key as a witness.

Solution:


export async function mint(mintData: MintData, wasm: any, walletConnector: WalletConnector){
    const userAddress: Address = mintData.address.to_address()
    const netId: NetworkID = await walletConnector.getNetworkId()
    const p = initTxStatic(netId) 
  
    const txBuilder: TransactionBuilder = wasm.TransactionBuilder.new(
      wasm.TransactionBuilderConfigBuilder.new()
        .fee_algo(wasm.LinearFee.new(wasm.BigNum.from_str(p.linearFee.minFeeA),
                                    wasm.BigNum.from_str(p.linearFee.minFeeB)))
        .pool_deposit(wasm.BigNum.from_str(p.poolDeposit))
        .key_deposit(wasm.BigNum.from_str(p.keyDeposit))
        .coins_per_utxo_word(wasm.BigNum.from_str(p.coinsPerUtxoWord))
        .max_value_size(p.maxValSize)
        .max_tx_size(p.maxTxSize)
        .build()
    );
    
    const baseAddress: BaseAddress = wasm.BaseAddress.from_address(userAddress)
    const scriptPubKey = wasm.ScriptPubkey.new(baseAddress.payment_cred().to_keyhash())
    const pubKeyScript = wasm.NativeScript.new_script_pubkey(scriptPubKey)
    const policyScripts = wasm.NativeScripts.new()
    policyScripts.add(pubKeyScript)
  
    const hexString = Util.hexEncode(mintData.assetName)
    const assetName: Uint8Array = Uint8Array.from(Buffer.from(hexString, 'hex'));
    txBuilder.add_mint_asset_and_output_min_required_coin(
      pubKeyScript, 
      wasm.AssetName.new(assetName), 
      wasm.Int.new_i32(mintData.amount),
      userAddress,
      );
    
  
    const valueFilter: Value = wasm.Value.new(wasm.BigNum.from_str("5000000")) 
    //Add inputs
    const utxos: TransactionUnspentOutputs = wasm.TransactionUnspentOutputs.new();
    const outputs: TransactionUnspentOutput[]  = (await walletConnector.getUtxos(valueFilter))
    outputs.forEach(utxo => utxos.add(utxo))
  
    
    txBuilder.add_inputs_from(utxos, 0)
  
    txBuilder.add_change_if_needed(userAddress)
    
    const toBeSignedTx: Transaction = txBuilder.build_tx();
  
    const witnessSet: TransactionWitnessSet = await walletConnector.signTx(toBeSignedTx)
  
    witnessSet.set_native_scripts(policyScripts)
  
    const submitTx: Transaction = 
      wasm.Transaction.new(
        toBeSignedTx.body(),
        witnessSet,
        undefined
      )
    await walletConnector.submitTx(submitTx)
  
  }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.