# How to Secure Pledge with Hardware Wallet

Updated: 1/11/25 - updated to use Conway commands

{% hint style="info" %}
Credits to  <img src="https://img.cexplorer.io/a/5/7/2/1/pool12wpfng6cu7dz38yduaul3ngfm44xhv5xmech68m5fwe4wu77udd.png" alt="" data-size="line"> [<mark style="color:red;">Apex Cardano Pool</mark>](https://apexpool.info/) and <img src="https://earncoinpool.com/images/coin_v3.png" alt="" data-size="line"> [Earn Coin Pool](https://earncoinpool.com/) for documenting the procedure.
{% endhint %}

There are basically 3 main things we need to do in order to add hardware wallet: \
\
**1)** Install cardano-hw-cli on air gapped machine to generate keys. \
\
**2)** Generate new Pool Registration Certificate and build transaction.\
\
**3)** Witness and Submit transaction for new Pool Registration Certificate to the blockchain

## Before we get started

{% hint style="info" %}
**Good to know:** The scripts were tested with a Ledger hardware wallet and using the cardano-hw-cli version 1.16.0-rc.1 (latest available at the time of writing this guide). They should also work with Trezor wallets.
{% endhint %}

{% hint style="warning" %}
The new owner becomes active after **2 full epochs**, the initial owner of the stake pool cannot be replaced with the new one immediately (unless each of the wallets has enough ADA in it to cover the pledge).&#x20;

After the second owner and its delegation to the stake pool become active, the pledge can be moved from the initial wallet to the hardware wallet and if desired the first wallet can be removed from the stake pool owners. Removing it is optional. **Please note** that you can't use your hardware wallet as payment wallet yet, so you may want to keep your original pledge wallet to use as payment for pool updates.
{% endhint %}

<details>

<summary><strong>Steps we will take in this guide:</strong></summary>

1. &#x20;[Delegate Hardware Wallet to your Pool](#step-1-delegate-hardware-wallet-to-your-pool)\
   \
   **PART 1 - Install cardano-hw-cli on Air Gapped Machine and generate Keys**
2. [Copy cardano-hw-cli Install Files to USB](#step-2-copy-cardano-hw-cli-install-files-to-usb)
3. [Copy udev rules from Ledger Site to USB](#step-3-copy-udev-rules-from-ledger-site-to-usb) (Ledger Users)
4. [Copy Install Files to Air Gapped Machine and Install](#step-4-copy-install-files-to-air-gapped-machine-and-install)
5. [Generate Verification Key and Hardware Wallet Signing File](#step-5-generate-verification-key-and-hardware-wallet-signing-file)\
   \
   **Part 2- Generate New Pool Registration Certificate**
6. [Create New Stake Pool Registration Certificate](#step-6-create-new-stake-pool-registration-certificate)
7. [Build Transaction to Submit Stake Pool Registration Certificate](#step-7-build-transaction-to-submit-stake-pool-registration-certificate)&#x20;
8. [Transfer tx.raw to Air Gapped Machine](#step-8-transfer-tx.raw-to-air-gapped-machine)\
   \
   **Part 3 - Witness Transaction and submit to blockchain**
9. [Witness with Cold Key](#step-9-witness-with-cold-key)
10. [Witness with Payment Key](#step-10-witness-with-payment-key)
11. [Witness with Stake Key of First Pool Owner](#step-11-witness-with-stake-key-of-first-pool-owner)
12. [Witness with hw-Stake Key](#step-12-witness-with-hw-stake-key)
13. [Assemble Transaction](#step-13-assemble-transaction)
14. [Copy tx.multisign to Hot Environment](#step-14-copy-tx.multisign-to-hot-environment)
15. [Submit Signed Transaction File to the Blockchain](#step-15-submit-signed-transaction-file-to-the-blockchain)

</details>

## Step 1 - Delegate Hardware Wallet to your Pool

First step is to make sure you delegate you hardware wallet which will be your 2nd pool owner, to your stake pool with Daedalus or Yoroi or Eternl or so on.

{% hint style="info" %}
Remember you will need at least 4 ADA on your hardware wallet in order to delegate to your pool.
{% endhint %}

## Step 2 - Copy cardano-hw-cli Install Files to USB

For this guide we will be downloading `cardano-hw-cli_1.16.0-rc.1-1.deb`. For other distributions than Ubuntu or Debian, download the .tar.gz. extract it and copy cardano-hw-cli somewhere in the PATH (in /usr/local/bin or where cardano-cli is) on your air gapped machine.<br>

Download files can be found here: <https://github.com/vacuumlabs/cardano-hw-cli/releases/tag/v1.16.0-rc.1>\
\
Reference: <https://github.com/vacuumlabs/cardano-hw-cli/blob/develop/docs/installation.md>

## Step 3 - Copy udev rules from Ledger Site to USB

For this guide we use ledger, The first time you connect your hardware wallet you may need to add the udev rules. (If your device is on and connect but you get an error that your device isn't connected, then you need add\_udev\_rules.sh)

For Linux copy the following file to your USB:\
<https://raw.githubusercontent.com/LedgerHQ/udev-rules/master/add_udev_rules.sh>\
\
`#Referrence:` [`https://support.ledger.com/hc/en-us/articles/115005165269-Fix-USB-connection-issues-with-Ledger-Live`](https://support.ledger.com/hc/en-us/articles/115005165269-Fix-USB-connection-issues-with-Ledger-Live?support=true)

`and`

[`https://github.com/LedgerHQ/udev-rules`](https://github.com/LedgerHQ/udev-rules)

## Step 4 - Copy Install Files to Air Gapped Machine and Install

Copy cardano-hw-cli install file and add\_udev\_rules.sh to air gapped machine.

{% hint style="info" %}
For this guide we copied the .deb file and add\_udev\_rules.sh to our `$NODE_HOME.`
{% endhint %}

### Part 1

Copy cardano-hw-cli install files to air gapped machine.

To Install run the following commands:

<pre><code><strong>cd $NODE_HOME
</strong>sudo dpkg --install ./cardano-hw-cli_1.16.0-rc.1-1.deb
</code></pre>

Check install version, run:

```
cardano-hw-cli version
```

{% hint style="info" %}
**Good to Know**: to find location of cardano-hw-cli run:\ <mark style="color:orange;">which cardano-hw-cli</mark><br>

Or If you wish to uninstall `cardano-hw-cli`, run:\ <mark style="color:orange;">sudo dpkg --remove cardano-hw-cli</mark>
{% endhint %}

### Part 2 (If using Ledger Device)

Now add udev rules by running the following command:

```
sudo bash add_udev_rules.sh
```

## Step 5 - Generate Verification Key and Hardware Wallet Signing File

We will now use `cardano-hw-cli` to extract two files from the hardware wallet:\
\
**1) The stake key verification key `hw-stake.vkey` (".vkey")** \
The `hw-stake.vkey` file will be required when creating the new stake pool registration certificate.\
and\
\
**2)** **The hardware signing file `hw-stake.hwsfile` (".hwsfile")**\
The `hw-stake.hwsfile` file will be required for witnessing transactions with the hardware wallet.

{% hint style="info" %}
**`hw-stake.vkey`** is not sensitive and may be shared publicly. **`hw-stake.hwsfile`** does NOT contain the raw private key.
{% endhint %}

{% tabs %}
{% tab title="On Air Gapped Machine" %}
{% hint style="danger" %}
This script must be executed with the hardware wallet connected to the computer and unlocked, and with the Cardano application started. It will be required to confirm the key export on the hardware wallet.
{% endhint %}

To generate the verification key and hardware wallet signing file, type:

```
cd $NODE_HOME
cardano-hw-cli address key-gen \
--path 1852H/1815H/0H/2/0 \
--verification-key-file hw-stake.vkey \
--hw-signing-file hw-stake.hwsfile
```

{% endtab %}
{% endtabs %}

## Step 6 - Create New Stake Pool Registration Certificate

In order to add a new owner to the stake pool, a new stake pool registration certificate needs to be created. This will secure both your **pool pledge account** and **pool reward account** with a hardware wallet.

{% hint style="success" %}
Since we need to create a new stake pool registration certificate we are going to walk through how to create an env file that contains our pool information and a script to generate a new certificate. This will allow us to make future pool changes easier and help avoid errors.

If you want to skip this step you can see an example command to create new stake pool registration certificate with hardware wallet under the "Standard Method" tab below.
{% endhint %}

{% hint style="danger" %}
**ON Air Gapped Machine**
{% endhint %}

{% tabs %}
{% tab title="Best Practice" %}
{% hint style="info" %}
Notice the **pool-reward-account** and additional **pool-ownerstake-verification-key-file** lines point to **hw-stake.vkey**.
{% endhint %}

**1)** First let's start by creating a pool-scripts folder in our $NODE\_HOME.&#x20;

```
cd $NODE_HOME
mkdir pool-scripts
```

**2)** Let's create an env file for our pool in the pool-scripts folder:

```
cat > $NODE_HOME/pool-scripts/env << 'EOF' 
#!/bin/bash

PLEDGE=25000000000  # 25,000 ADA
COST=170000000     #  170 ADA
MARGIN=0.03        #    3 %

NET="--mainnet"  #mainnet
RELAY1_HOST=relay1.stakepool.url
RELAY1_PORT=6000
RELAY2_HOST=relay2.stakepool.url
RELAY2_PORT=6000
METADATA_URL=https://stakepool.url/poolmetadata.json
METADATA_HASH=$(cat $NODE_HOME/poolMetaDataHash.txt)
EOF
```

Edit all the values to match your data. Paths are based on normal coincashew install, please update paths as necessary. The usual values for port are 3001 or 6000, but any valid port can be used.

It is also possible to use IP Addresses

**3)** Create `pool-registration.sh` script in the pool-scripts folder:

```
cat > $NODE_HOME/pool-scripts/pool-registration.sh << 'EOF' 
#!/bin/bash


source ./env

cardano-cli conway stake-pool registration-certificate \
--cold-verification-key-file $HOME/cold-keys/node.vkey \
--vrf-verification-key-file $NODE_HOME/vrf.vkey \
--pool-pledge ${PLEDGE} \
--pool-cost ${COST} \
--pool-margin ${MARGIN} \
--pool-reward-account-verification-key-file $NODE_HOME/hw-stake.vkey \
--pool-owner-stake-verification-key-file $NODE_HOME/stake.vkey \
--pool-owner-stake-verification-key-file $NODE_HOME/hw-stake.vkey \
${NET} \
--single-host-pool-relay ${RELAY1_HOST} \
--pool-relay-port ${RELAY1_PORT} \
--single-host-pool-relay ${RELAY2_HOST} \
--pool-relay-port ${RELAY2_PORT} \
--metadata-url ${METADATA_URL} \
--metadata-hash ${METADATA_HASH} \
--out-file $NODE_HOME/pool.cert
EOF
```

If you are using IP Addresses instead of hostnames for the registered relays, replace `--single-host-pool-relay` with `--pool-relay-ipv4` in the script.

You can register as many relays as you want (one or more). You just have to repeat the `--single-host-pool-relay` and `--pool-relay-port` parameters for each of them.

The pledge wallet and the rewards wallet are the same one in this case. But it is possible to create and set different wallets for them.\
\
Paths are based on normal coincashew install, please update paths as necessary.&#x20;

**Next:**

Add execute permissions to the pool-registration script.

```
chmod +x $NODE_HOME/pool-scripts/pool-registration.sh
```

⚠️The script must be executed in order to generate the new stake pool registration certificate, which will need to be submitted with a transaction.

Run pool-registration script with:

```
cd $NODE_HOME/pool-scripts
./pool-registration.sh
```

{% endtab %}

{% tab title="Standard Method" %}
{% hint style="info" %}
Notice the **pool-reward-account** and additional **pool-ownerstake-verification-key-file** lines point to **hw-stake.vkey**.
{% endhint %}

In the below example we assume a pledge of 25,000(done in lovelace so 25,000 x 1,000,000), min fee for pool cost at 170(in lovelace as well) and a pool margin of 3%. This example shows sample of 2 ip relays with port 6000 and a sample metadata url, please adjust to match your pool. Please remember to remove <> as well.

{% hint style="success" %}
Verify the paths to your different keys below
{% endhint %}

Run the following commands once you update the below with your values, to generate **New Stake Pool Registration Certificate**

```
cd $NODE_HOME

cardano-cli stake-pool registration-certificate \
    --cold-verification-key-file $HOME/cold-keys/node.vkey \
    --vrf-verification-key-file vrf.vkey \
    --pool-pledge 25000000000 \
    --pool-cost 170000000 \
    --pool-margin 0.03 \
    --pool-reward-account-verification-key-file hw-stake.vkey \
    --pool-owner-stake-verification-key-file stake.vkey \
    --pool-owner-stake-verification-key-file hw-stake.vkey \
    --mainnet \
    --pool-relay-port 6000 \
    --pool-relay-ipv4 <example 123.123.123.123> \
    --pool-relay-port 6000 \
    --pool-relay-ipv4 <example: 321.321.321.321> \
    --metadata-url <example: https://mysite.com/poolMetaData.json> \
    --metadata-hash $(cat poolMetaDataHash.txt) \
    --out-file pool.cert
```

{% endtab %}
{% endtabs %}

## Step 7 - Build Transaction to Submit Stake Pool Registration Certificate&#x20;

In order to finish adding the hardware wallet as stake pool owner, we must submit Certificate to the blockchain with transactions.

{% tabs %}
{% tab title="On Node" %}

### Part 1 - Copy pool.cert to your hot environment.

Copy your pool.cert from air gapped machine to your node

### Part 2 - Build Transaction File (tx.raw)

First find UTXO without NFT and change tx-in\
Run:

```
cd $NODE_HOME
cardano-cli conway query utxo \
    --address $(cat payment.addr) \
    --mainnet
```

Select UTXO without NFT and change tx-in and don't forget to remove<>

```
cardano-cli conway transaction build \
--mainnet \
--witness-override 4 \
--tx-in <example: 45de23872ce59c8b6f2fb5e2f39741e0dd8a45f9b496c46ed117396a21b5f4bc#0> \
--change-address $(cat payment.addr) \
--certificate-file pool.cert \
--out-file tx.raw
```

{% endtab %}
{% endtabs %}

{% hint style="success" %}
Now let's double check that we have the correct values for our pool.cert
{% endhint %}

To double check that we have the correct values for our pool.cert run:

```
cardano-cli debug transaction view \
--tx-body-file tx.raw
```

## Step 8 - Transfer tx.raw to Air Gapped Machine

The transaction for submitting the new stake pool registration certificate needs to be signed with 4 signing keys:

* Witness cold key (node.skey)
* Witness payment key -to pay the transaction fees (payment.skey)
* Witness of the first stake pool owner stake key (stake.skey)
* the hardware wallet stake key -the new pool owner (hw-stake.hwsfile)

When not using a hardware wallet, the transaction to submit a stake pool registration certificate can be signed with one command.&#x20;

However due to the way the hardware wallet can sign transactions, the transaction must be **witnessed by all 4 signing key**, and then all the witness files must be combined into a signed transaction file, which will be submitted to the blockchain.

Now we need to do our 4 witnesses. To do so we need to move back to our air gapped machine.  **Copy your tx.raw file to you air gapped machine**. For this guide we will put it in $NODE\_HOME

## Step 9 - Witness with Cold Key

{% tabs %}
{% tab title="On Air Gapped Machine" %}
Now on air gapped let's create first witness with cold key

<pre><code><strong>cd $NODE_HOME
</strong><strong>cardano-cli conway transaction witness \
</strong>--tx-body-file tx.raw \
--signing-key-file $HOME/cold-keys/node.skey \
--mainnet \
--out-file tx-cold.witness
</code></pre>

{% endtab %}
{% endtabs %}

## Step 10 - Witness with Payment Key

{% tabs %}
{% tab title="On Air Gapped Machine" %}
Still on air gapped machine let's create our 2nd witness with payment key.&#x20;

{% hint style="warning" %}
As of now you can't use your hardware wallet as payment address so you will need to use any other payment address and use it's payment key below.
{% endhint %}

```
cd $NODE_HOME
cardano-cli conway transaction witness \
--tx-body-file tx.raw \
--signing-key-file payment.skey \
--mainnet \
--out-file tx-payment.witness
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
If you are able in the future to use your hardware wallet as payment wallet you can export the payment key on your air gapped machine by running the following command. When executing this command, the hardware wallet will need to be connected to the computer and unlocked, and with the Cardano application started. It will be required to confirm the export.
{% endhint %}

<details>

<summary>How to Export Payment Key from Hardware Wallet</summary>

ON AIR GAPPED MACHINE with Hardware wallet plugged in and unlocked with Cardano app opened:

```
cd $NODE_HOME
cardano-hw-cli address key-gen \
--path 1852H/1815H/0H/0/0 \
--verification-key-file hw-payment.vkey \
--hw-signing-file hw-payment.hwsfile
```

</details>

## Step 11 - Witness with Stake Key of First Pool Owner

{% tabs %}
{% tab title="On Air Gapped Machine" %}
Still on air gapped machine let's create our 3nd witness with the stake key of the first pool owner.&#x20;

```
cd $NODE_HOME
cardano-cli conway transaction witness \
--tx-body-file tx.raw \
--signing-key-file stake.skey \
--mainnet \
--out-file tx-stake.witness
```

{% endtab %}
{% endtabs %}

## Step 12 - Witness with hw-Stake Key

{% tabs %}
{% tab title="On Air Gapped Machine" %}
{% hint style="danger" %}
When executing this command, the hardware wallet will need to be connected to the computer and unlocked, and with the Cardano application started. It will be required to confirm the witness.
{% endhint %}

Still on air gapped machine let's create our 4nd and final witness with the hw-stake key of the second pool owner.&#x20;

<pre><code><strong>cd $NODE_HOME
</strong><strong>cardano-hw-cli transaction witness \
</strong>--tx-file tx.raw \
--hw-signing-file hw-stake.hwsfile \
--mainnet \
--out-file tx-hw-stake.witness
</code></pre>

{% endtab %}
{% endtabs %}

## Step 13 - Assemble Transaction

{% tabs %}
{% tab title="On Air Gapped Machine" %}
Now we will create the signed transaction file, which needs to be submitted to the blockchain. Still on air gapped machine assemble transaction by running the following command:

```
cd $NODE_HOME
cardano-cli conway transaction assemble \
--tx-body-file tx.raw \
--witness-file tx-cold.witness \
--witness-file tx-payment.witness \
--witness-file tx-stake.witness \
--witness-file tx-hw-stake.witness \
--out-file tx.multisign
```

{% endtab %}
{% endtabs %}

## Step 14 - Copy tx.multisign to Hot Environment

Copy your tx.multisign from air gapped machine to your node in hot environment.

## Step 15 - Submit Signed Transaction File to the Blockchain &#x20;

{% tabs %}
{% tab title="On Node" %}
Submit transaction to blockchain with this command:

```
cd $NODE_HOME
cardano-cli conway transaction submit \
--tx-file tx.multisign \
--mainnet
```

Wait a few minutes for transaction to reach chain, then you can go to <https://cardanoscan.io/> and search your pool. Then scroll down and click on pool updates tab.

<figure><img src="https://2549074837-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F8PjW7zFPfe4PgCsPtkZx%2Fuploads%2FKSLUyN3h1Pu80ffKgDqI%2Fcardanoscan_1.png?alt=media&#x26;token=04df885d-0078-488c-a3f2-1d12c6af6132" alt=""><figcaption></figcaption></figure>

Then click on transaction and scroll down to Pool Certificates tab. Here you can confirm the data submitted.

<figure><img src="https://2549074837-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F8PjW7zFPfe4PgCsPtkZx%2Fuploads%2FSFi0KYIJaqJqf3f96KcN%2Fcardanoscan_2.png?alt=media&#x26;token=377a78e7-e9fd-406f-b5ca-a5178648dff6" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Remember to clean up files and delete files like tx.raw, tx.multisign and pool.cert from your node.

Also a great time to do another backup!
{% endhint %}
{% endtab %}
{% endtabs %}

{% hint style="danger" %}
The new owner becomes active after **2 full epochs**&#x20;

So Remember to **wait 2 Epochs** before transferring funds between wallets so that your pledge is met.&#x20;
{% endhint %}

### Verify when your Pool Certificate will be active

You can use [cexplorer.io](https://cexplorer.io) to verify when your pool certificate changes will be active.

Go to [cexplorer.io](https://cexplorer.io) and search for your pool and go to your pool page. Then scroll down on your pool page and click on "**About**" tab.

<figure><img src="https://2549074837-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F8PjW7zFPfe4PgCsPtkZx%2Fuploads%2FONAFDf6PN2HfLnnRIATm%2Fcexplorer_01.png?alt=media&#x26;token=759af057-1ec2-4139-b842-3855366a8a2d" alt=""><figcaption><p>Clink on "About" tab</p></figcaption></figure>

Now scroll down to **Pool Certificates**. Here it will show what epoch your changes will be active. You can also see the updates to your Owner Addresses and Reward Address here.

<figure><img src="https://2549074837-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F8PjW7zFPfe4PgCsPtkZx%2Fuploads%2FDVDIzsZUpwfS4liVdtg7%2Fcexplorer_02.png?alt=media&#x26;token=ba514c5c-e62a-4349-8ed9-64806cc8cef3" alt=""><figcaption></figcaption></figure>

## Congratulations you did it!

## Updating your Pool Registration Certificate Moving Forward

Next time you want to update your Pool Registration for example to adjust min fee, margin or pledge you will simply nano your env file on your air gapped machine with the updated info you want to use. Use command:

```
sudo nano $NODE_HOME/pool-scripts/env
```

Sample env file:

```
#!/bin/bash

PLEDGE=25000000000  # 25,000 ADA
COST=340000000     #  340 ADA
MARGIN=0.01        #    1 %

NET="--mainnet"  #mainnet
RELAY1_HOST=relay1.stakepool.url
RELAY1_PORT=6000
RELAY2_HOST=relay2.stakepool.url
RELAY2_PORT=6000
METADATA_URL=https://stakepool.url/poolmetadata.json
METADATA_HASH=$(cat $NODE_HOME/poolMetaDataHash.txt)
```

**Then run** [**Steps 6**](#step-6-create-new-stake-pool-registration-certificate) **through Step 15 again and you are all set!**

{% hint style="info" %}
If you need or want to update relays you will need to nano changes to env file and pool-registration.sh from [Step 6](#step-6-create-new-stake-pool-registration-certificate)
{% endhint %}

## Contributors&#x20;

Thanks to the following pools for helping to put together these guides. Please consider delegating to their pools to support them.  Are you a pool? Consider buying them a coffee

![](https://img.cexplorer.io/a/5/7/2/1/pool12wpfng6cu7dz38yduaul3ngfm44xhv5xmech68m5fwe4wu77udd.png) [Apex Cardano Pool - Ticker: APEX](https://cexplorer.io/pool/pool12wpfng6cu7dz38yduaul3ngfm44xhv5xmech68m5fwe4wu77udd)

![](https://img.cexplorer.io/7/e/1/9/f/pool16cdtqyk0fvxzfkhjg3esjcuty4tnlpds5lj0lkmqmwdjyzaj7p8.png)  [Earn Coin Pool - Ticker: ECP](https://cexplorer.io/pool/pool16cdtqyk0fvxzfkhjg3esjcuty4tnlpds5lj0lkmqmwdjyzaj7p8)

![xSPO Alliance Logo](https://2549074837-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F8PjW7zFPfe4PgCsPtkZx%2Fuploads%2F0sqzqoHnqVXizi2RHABd%2FxSPO_NFT_64x64.png?alt=media\&token=1c1b130e-26df-4b1e-8e0e-e85fae1ee73e) [xSPO Alliance](http://xspo-alliance.org/discord)
