Error creating Staking Delegation transaction with Yoroi Wallet using CIP30

Hi! I’m trying to create a stake delegation transaction using cardano-serialization-lib, js, and Yoroi with the CIP30 API (Cardano dApp-Wallet Web Bridge https://cips.cardano.org/cips/cip30/)

I’m using Yoroi Nightly and Testnet

Code:

delegate = async () => {
    const bech32Addr = this.state.changeAddress //obtaining my payment address
    const address = Address.from_bech32(bech32Addr)
    const baseAddress = BaseAddress.from_address(address);
    const txUnspentOutputs = await this.getTxUnspentOutputs();

    
    const txBuilder = await this.initTransactionBuilder(); // creating transaction
    txBuilder.add_inputs_from(txUnspentOutputs, 0)

    const certs = Certificates.new();
    
    const poolId = this.state.poolId
    const poolKeyHash = Ed25519KeyHash.from_bytes(Buffer.from(poolId, 'hex'));

    //Adding StakeDelegation Certificate
    certs.add(
        Certificate.new_stake_delegation(
            StakeDelegation.new(
                baseAddress.stake_cred(),
                poolKeyHash
            )
        )
    );

    txBuilder.set_certs(certs)  

    txBuilder.add_change_if_needed(address)

    const txBody = txBuilder.build();

    const transactionWitnessSet = TransactionWitnessSet.new();
    const tx = Transaction.new(
        txBody,
        TransactionWitnessSet.from_bytes(transactionWitnessSet.to_bytes())
    )

    // "this.API" is the Yoroi API created using "window.cardano.yoroi.enable()"
    let txVkeyWitnesses = await this.API.signTx(Buffer.from(tx.to_bytes(), "utf8").toString("hex"), true);
    txVkeyWitnesses = TransactionWitnessSet.from_bytes(Buffer.from(txVkeyWitnesses, "hex"));

    transactionWitnessSet.set_vkeys(txVkeyWitnesses.vkeys());
    const signedTx = Transaction.new(
        tx.body(),
        transactionWitnessSet
    );
    const submittedTxHash = await this.API.submitTx(Buffer.from(signedTx.to_bytes(), "utf8").toString("hex"));
}

initTransactionBuilder code:

    /**
     * Every transaction starts with initializing the
     * TransactionBuilder and setting the protocol parameters
     * This is boilerplate
     * @returns {Promise<TransactionBuilder>}
     */
    initTransactionBuilder = async () => {

        const txBuilder = TransactionBuilder.new(
            TransactionBuilderConfigBuilder.new()
                .fee_algo(LinearFee.new(BigNum.from_str(this.protocolParams.linearFee.minFeeA), BigNum.from_str(this.protocolParams.linearFee.minFeeB)))
                .pool_deposit(BigNum.from_str(this.protocolParams.poolDeposit))
                .key_deposit(BigNum.from_str(this.protocolParams.keyDeposit))
                .coins_per_utxo_word(BigNum.from_str(this.protocolParams.coinsPerUtxoWord))
                .max_value_size(this.protocolParams.maxValSize)
                .max_tx_size(this.protocolParams.maxTxSize)
                .prefer_pure_change(true)
                .build()
        );

        return txBuilder
    }

This exact code is working correctly with the following Wallets (also using CIP30):

  • Nami
  • Flint
  • CCVault / Eternl
  • Typhon
  • Nufi

The only Wallet that doesn’t work is Yoroi.

This is the error I’m getting:

"transaction submit error ShelleyTxValidationError ShelleyBasedEraBabbage (ApplyTxError [UtxowFailure (FromAlonzoUtxowFail (WrappedShelleyEraFailure (MissingVKeyWitnessesUTXOW (WitHashes (fromList [KeyHash "bdd5302aa402af3018f558b9eef255751633abc32c7352d9eb1d2f37"])))))])"

Maybe I’m wrong but I think Yoroi is not signing the StakeDelegation certificate.

I also tried adding the StakeRegistration Certificate and the result is the same.

I’m able to create regular transactions with Yoroi (only sending ADA), I just can’t do transactions related to Staking.

If you are wondering why I want to do this and not use the Yoroi UI is because I want to add metadata to the transaction and also so the users can delegate directly from my website.