# Migrate to Polkadot Asset Hub

This guide describes the process for migrating your Substrate ledgers from the old Relay chain to the new Polkadot Asset Hub chain. The ledgers affected by this change are Polkadot mainnet and Westend.

The migration is divided into two main phases:

1. Infrastructure and configuration: This phase involves software updates and configuration changes, with different responsibilities for SaaS and On-Premises customers.
2. Ledger and account management: This phase involves submitting intents to register the new ledger and update accounts. These steps are required for all customers.


## Infrastructure and configuration updates

### SaaS customers

Ensure that your Ripple Custody version is above STS 1.25.1.

### On-premises customers

#### Upgrade Ripple Custody

Ensure that your Ripple Custody versions is above LTS 1.19.9.

#### Deploy the new indexer and configure ledger accounting

You must deploy a new indexer for the Asset Hub chain and update your Ledger Accounting `ConfigMap`. The steps to do this vary depending on whether you are using Helm Next or Helm Flat.

**Helm Next configuration**
Add the new indexer and update the `ConfigMap` by editing your values.yaml file to include the following configuration:


```
ledger-accounting:
      ledgers:
        substrate:
          networks:
          - indexer:
              values:
                node:
                  endpoint:
                    url: wss://.../ws/polkadot/westend/xxx
                  sidecar:
                    url: https://.../v2/xxx/polkadot/westend
            name: westend
          - indexer:
              values:
                node:
                  endpoint:
                    url: wss://.../ws/polkadot/mainnet/xxx
                  sidecar:
                    url: https://.../v2/xxx/polkadot/mainnet
            name: polkadot
          - name: westend-assethub
            indexer:
              values:
                node:
                  endpoint:
                    url: wss://xxx
                  sidecar:
                    url: https://xxx
            raw_config: |
              ledger.substrate-westend-assethub = ${silo.ledger-accounting.ledger.substrate-westend}
              ledger.substrate-westend-assethub.id = "substrate-westend-assethub"
              ledger.substrate-westend-assethub.tracker.identifier = "substrate-assethub"
              ledger.substrate-westend-assethub.tracker.base-url = "http://substrate-indexer-substrate-westend-assethub"
              
              ledgers += ${silo.ledger-accounting.ledger.substrate-westend-assethub}
              tracker.substrate-westend-assethub.base-url = "http://substrate-indexer-substrate-westend-assethub"
```

**Helm Flat configuration**

The process for Helm Flat requires manual intervention.

1. Add the new indexer to your Helm Flat configuration.
2. Manually patch the `ConfigMap`. Helm Flat does not support applying the `raw_config` section directly. After deploying the new indexer, edit the `ConfigMap` of the ledger accounting service using Kubernetes commands and Paste the following lines into the `ConfigMap` data:



```
ledger.substrate-westend-assethub = ${silo.ledger-accounting.ledger.substrate-westend}
ledger.substrate-westend-assethub.id = "substrate-westend-assethub"
ledger.substrate-westend-assethub.tracker.identifier = "substrate-assethub"
ledger.substrate-westend-assethub.tracker.base-url = "http://substrate-indexer-substrate-westend-assethub"

ledgers += ${silo.ledger-accounting.ledger.substrate-westend-assethub}
tracker.substrate-westend-assethub.base-url = "http://substrate-indexer-substrate-westend-assethub"
```

#### Reboot ledger accounting

After applying any configuration change, you may need to reboot Ledger Accounting for the changes to take effect.

## Ledger and account management

### Register and verify the new ledger

To register the new ledger, you must submit a `v0_CreateLedger` intent. Below is a template of the JSON payload you'll need to use.

Important warning
The parameters within the `payload` section must be kept exactly as they appear in the template. They are correct as of September 2025. However, Substrate ledger parameters, in particular the `transactionVersion` may change over time. If they are no longer valid when you attempt this migration please contact your CPE.


```
{
	"request": {
		"author": {
			"id": "...",
			"domainId": "..."
		},
		"expiryAt": "2035-11-29T17:30:00.621Z",
		"targetDomainId": "...",
		"id": "...",
		"payload": {
			"id": "substrate-westend-assethub",
			"alias": "Westend AssetHub",
			"parameters": {
				"type": "Substrate",
				"genesisHash": "0x67f9723393ef76214df0118c34bbbd3dbebc8ed46a10973a8c969d48fe7598c9",
				"addressPrefix": 42,
				"nativeTickerName": "Westend",
				"nativeTickerSymbol": "WND",
				"nativeTickerDecimals": 12,
				"supportedRuntimeVersions": [
					{
						"chainType": "AssetHub",
						"pallets": [
							{
								"name": "balances",
								"methods": [
									{
										"name": "transfer_keep_alive",
										"methodId": 3,
										"feeParameters": {
											"base": 41063000,
											"type": "MethodWeight",
											"reads": 1,
											"writes": 1
										}
									}
								],
								"moduleId": 10
							},
							{
								"name": "staking",
								"methods": [
									{
										"name": "bond",
										"methodId": 0,
										"feeParameters": {
											"base": 57791000,
											"type": "MethodWeight",
											"reads": 5,
											"writes": 4
										}
									},
									{
										"name": "bond_extra",
										"methodId": 1,
										"feeParameters": {
											"base": 105431000,
											"type": "MethodWeight",
											"reads": 10,
											"writes": 7
										}
									},
									{
										"name": "unbond",
										"methodId": 2,
										"feeParameters": {
											"base": 114771000,
											"type": "MethodWeight",
											"reads": 13,
											"writes": 7
										}
									},
									{
										"name": "withdraw_unbonded",
										"methodId": 3,
										"feeParameters": {
											"base": 110590540,
											"type": "MethodWeight",
											"reads": 14,
											"writes": 12
										}
									},
									{
										"name": "nominate",
										"methodId": 5,
										"feeParameters": {
											"base": 139574094,
											"type": "MethodWeight",
											"reads": 28,
											"writes": 6
										}
									},
									{
										"name": "chill",
										"methodId": 6,
										"feeParameters": {
											"base": 67641000,
											"type": "MethodWeight",
											"reads": 9,
											"writes": 6
										}
									},
									{
										"name": "set_payee",
										"methodId": 7,
										"feeParameters": {
											"base": 26060000,
											"type": "MethodWeight",
											"reads": 2,
											"writes": 1
										}
									},
									{
										"name": "set_controller",
										"methodId": 8,
										"feeParameters": {
											"base": 29380000,
											"type": "MethodWeight",
											"reads": 3,
											"writes": 3
										}
									},
									{
										"name": "rebond",
										"methodId": 19,
										"feeParameters": {
											"base": 102961223,
											"type": "MethodWeight",
											"reads": 10,
											"writes": 7
										}
									}
								],
								"moduleId": 80
							}
						],
						"feeParameters": {
							"type": "TransactionPayment",
							"readWeight": 25000000,
							"writeWeight": 100000000,
							"baseExtrinsic": 125000000,
							"transactionByteFee": "10000000",
							"weightToFeePolynomial": [
								"0",
								"8.0"
							]
						},
						"transactionVersion": 16
					}
				]
			},
			"description": null,
			"customProperties": {},
			"type": "v0_CreateLedger"
		},
		"description": "Add ledger Asset Hub Westend",
		"customProperties": {},
		"type": "Propose"
	},
	"signature": "..."
}
```

#### Verify the ledger

After submitting the intent, you must verify that it has been **Executed**.

You can now create new accounts and perform native transfers or staking operations on the new ledger.

### Re-utilize existing accounts

If you want to use existing accounts from the old relay chain, you must submit a `v0_AddAccountLedgers` intent to add the new ledger to the existing account.

An example payload would look like:


```
"payload": {
    "reference": {
        "id": "...",
        "revision": 1
    },
    "ledgerIds": [
        "substrate-westend-assethub"
    ],
    "type": "v0_AddAccountLedgers"
}
```

Once the ledger is activated in the account, you must verify that:

- The address for `substrate-westend-assethub` was generated and matches the existing address in `substrate-westend`.
- The balance of the native ticker matches on both the old and new ledgers.


### Recommended post-migration actions

Ripple Custody recommends these non-mandatory actions to prevent confusion for users:

* **Allowlist (if necessary) and then change the name** of the old native ticker on the relay chain, following the instructions here:
  - [Allowlist tokens](https://docs.ripple.com/products/custody/api/accounting-entities/token-management/allowlist)
  - [Update tokens](https://docs.ripple.com/products/custody/api/accounting-entities/token-management/update)
* **Lock the ticker** on the old relay chain using the `v0_LockTicker`intent.
* **Create new policies** to reject `v0_CreateTransactionOrder` intents where the `ledgerId` matches the old relay chain ledger. An example is provided below.



```
"payload": {
	"id": "...",
	"alias": "reject orders in old relay chains",
	"rank": 1000,
	"intentTypes": [
		"v0_CreateTransactionOrder"
	],
	"scope": "SelfAndDescendants",
	"scriptingEngine": "Javascript_v0",
	"condition": {
		"expression": "context.request.payload.parameters.type == 'Substrate' && (context.request.payload.ledgerId == 'substrate-westend',
		"type": "Expression"
	},
	"workflow": [],
	"lock": "Unlocked",
	"description": "Rejects transactions on the legacy Polkadot and Westend relay chains.",
	"customProperties": {},
	"type": "v0_CreatePolicy"
}
```

* **Verify** that all `v0_CreateTransactionOrder` intents are registered with the correct new ledger. For example, for a staking Bond operation:



```
"payload": {
	"id": "...",
	"accountId": "...",
	"ledgerId":"substrate-westend-assethub",
	"parameters": {
		"pallet": {
			"method": {
				"value": "...",
				"payee": {
					"destination":{
						"accountId":"...",
						"type":"Account"
					},
					"type": "Account"
				},
				"type": "Bond"
			},
			"type": "Staking"
		},
		"feeStrategy": {
			"priority": "High",
			"type": "Priority"
		},
		"maximumFee": null,
		"type": "Substrate"
	},
	"description": "...",
	"customProperties": {},
	"type": "v0_CreateTransactionOrder"
}
```