# Ledger accounting phase 2 migration guide

Ripple Custody version 1.43 brings [ledger accounting refactor phase 2](/pt-br/products/custody/support/change-history/v140#ledger-accounting-refactor-phase-2) to on-premises deployments. Phase 2 moves blockchain-specific operations — transaction preparation, nonce and sequence reservation, broadcast, confirmation tracking, and reorg handling — into the rewritten Unified Indexer Service (UIS v2) for EVM, Solana, Stellar, TRON, and XRPL networks. This guide describes the behavioral changes that phase 2 introduces for API integrations and the one-time migration procedure for on-premises deployments.

While the behavioral changes apply to both SaaS and on-premises deployments, the migration procedure applies to on-premises deployments only, and you run it yourself on version 1.43. For SaaS deployments, Ripple manages the migration -- SaaS deployments have run phase 2 since version 1.40.

In version 1.43, this guide replaces the Unified Indexer Service (UIS) migration guide: deployments that use legacy indexers or UIS v1 migrate directly to UIS v2.

## Behavioral changes

These behavioral changes apply to both SaaS and on-premises deployments.

On-premises customers should review these changes and update their integrations before they migrate:

- **`rawTransaction` is no longer populated.** For chains served by UIS v2, APIs that return a transaction no longer populate `rawTransaction` in the `ledgerTransactionData` object. To inspect a confirmed transaction on chain, use `ledgerTransactionData.ledgerTransactionId` with a blockchain explorer.
- **`senderLedgerSpecificMetadata` is no longer populated.** For chains served by UIS v2, APIs that return a transaction no longer populate `senderLedgerSpecificMetadata`. It was previously persisted during transaction preparation and used when broadcasting the transaction; UIS v2 no longer requires it.
- **XRPL fee estimation.** Transactions are no longer padded to a default of 200 drops, so standard payments submitted during network congestion are more likely to remain pending until the network clears. The validation previously applied to the specified-fee strategy no longer applies below 50 XRP. No transaction can consume more than 50 XRP in fees.
- **Solana fee estimation.** Ripple Custody estimates Solana transaction fees using a combination of derivation and on-chain simulation performed by the indexer, rather than deriving fee costs in the notary alone. This change is not expected to affect transaction behavior in any significant way.
- **Solana token transfer addresses.** For Solana token transfers, the `address` of each transfer sender and recipient is now the main wallet address (the system account). Previously, it was the derived associated token account (ATA) address. If your reporting or reconciliation relies on ATA addresses, update it before you migrate.
- **XRPL MPT clawback and burn transfers.** UIS v2 records Multi-Purpose Token (MPT) clawbacks and burns as transfers from the holder to the issuer, symmetric with minting, so the issuer's balance returns toward zero as supply is clawed back or burned. On UIS v1, a partial clawback or a burn creates a transfer with no recipient, so the issuer's balance doesn't change, and a full clawback creates no transfer, so neither balance changes. This behavior isn't fixed in UIS v1. Until you migrate, run a [force balance refresh](/pt-br/products/custody/reference/api/openapi/accounts/forceupdateaccountbalances) after each MPT clawback or burn to reconcile balances.
- **Reorg handling.** UIS v2 recovers from a chain reorganization by walking back to the common ancestor and reprocessing the canonical chain, without deleting transaction history; a transaction that's mined again is picked up in its new block. Forks deeper than 100 blocks aren't resolved automatically. If one occurs, contact your CPE.


## Prerequisites

Before starting the migration, confirm that:

- Your deployment runs version 1.43. LTS releases can't be skipped -- if you're on an earlier LTS release, upgrade through each LTS release in order until you reach version 1.43. Run the ledger accounting migrations on version 1.43 before you upgrade to a later version.
- Your deployment has completed the [ledger accounting phase 1 migration](/pt-br/products/custody/operations-and-maintenance/upgrading/ledger-accounting-migration), either on version 1.34 or on version 1.43 before you start this migration, and the phase 1 services, Temporal, and the transaction processor (`txnprocessor`) are running.
- You're ready to move every network of these protocols to UIS v2 at the same time. The migration runs only once. A network that you switch to UIS v2 after the migration completes goes live without its tracked addresses migrated.
- You have a maintenance window for the upgrade and the migration together. From the upgrade until every ledger shows `Ledger allowed in Cockpit API`, don't submit outbound transactions on EVM, Solana, Stellar, TRON, or XRPL ledgers.
- You can run the migration right after the upgrade. Delaying it is supported but not recommended: UIS v2 replays events from each ledger's last processed block, but if that block is more than 24 hours old, UIS v2 starts from the chain tip, and on-chain activity from the gap is never delivered.
- You have a current database backup, as for other migrations. Rollback isn't supported.


### Compatibility

The following table lists the indexers each phase supports for EVM, Solana, Stellar, TRON, and XRPL networks. Other protocols are unchanged.

| Phase | Supported indexers |
|  --- | --- |
| Before ledger accounting refactor phase 1 | Legacy, UIS v1, or a mix of both |
| Ledger accounting refactor phase 1 | Legacy, UIS v1, or a mix of both. Moving to phase 1 doesn't require an indexer change. |
| Ledger accounting refactor phase 2 | UIS v2 only. Every network of these protocols moves to UIS v2; legacy, UIS v1, and mixed setups are no longer supported for them. New protocols, such as Canton and Sui, support UIS v2 only. |


You can't move directly from a deployment without phase 1 to phase 2. If you haven't completed phase 1, complete it on version 1.43 first.

## Migration procedure

Migrating to UIS v2 is a one-time process. You update the chart values, upgrade your deployment, and then the migration runs on its own: the transaction processor copies each ledger's tracked addresses into UIS v2, and each ledger then switches to UIS v2.

The migration runs only once
Include every EVM, Solana, Stellar, TRON, and XRPL network in the same upgrade. A network that you switch to UIS v2 after the migration completes goes live without its tracked addresses migrated. Rollback isn't supported.

### Update the chart values

Update the values for the `harmonize` umbrella chart. The following example shows the settings that the migration needs, with one Ethereum network:

```yaml
harmonize-core:
  txnprocessor:
    install: true
    uisV2:
      integrationEnabled: true
      blockchainApi:
        baseUrl: "http://uis-v2-blockchain-api:8080"
      cockpitApi:
        baseUrl: "http://uis-v2-cockpit:8082"
        tenantName: "default-tenant"
        tenantApiKey: "<tenant-api-key>"    # must equal defaultTenantApiKey below

  ledger-accounting:
    uisv2:
      setup:
        network: true                       # registers each network with UIS v2
        defaultTenant: true                 # creates the tenant that txnprocessor uses
        defaultTenantName: "default-tenant"
        defaultTenantApiKey: "<tenant-api-key>"
    extraEnv:
      HMZ_TEMPORAL_MIGRATION_ENABLED: "true"
      HMZ_TEMPORAL_MIGRATION_PHASE_2_ENABLED: "true"
      HMZ_TEMPORAL_TXNPROCESSOR_CLIENT_BASE_URL: "http://txnprocessor"
    ledgers:
      ethereum:                             # keep your existing chain key
        networks:
          - name: testnet-sepolia           # keep your existing network name
            type: "uis-v2"                  # was "legacy" or "uis"
            indexer:
              values:
                node:
                  url:
                    http: "<node-rpc-url>"
```

Use the same tenant API key in both places
`txnprocessor.uisV2.cockpitApi.tenantApiKey` must equal `ledger-accounting.uisv2.setup.defaultTenantApiKey`. Generate a new UUID v4 for this key. Nothing checks that the two values match when you install. If they differ, every ledger fails to migrate, without an error in the UIS v2 logs. The tenant names don't need to match.

For each EVM, Solana, Stellar, TRON, and XRPL network:

- Set `type` to `"uis-v2"`, replacing `"legacy"` or `"uis"`.
- Keep your existing chain keys and network names. Change only `type`.
- If a ledger uses `raw_config`, declare `ledger.<name>.indexer-network-name` explicitly. The `ledger-accounting` chart generates this value automatically for every `type: "uis-v2"` ledger, because a ledger ID can differ from its UIS network name on mainnet (for example, `xrpl` and `xrpl-mainnet`). For a `raw_config` ledger, chart rendering fails without it, and the error message shows the exact line to add.


To read the tenant API key for `txnprocessor` from an existing Kubernetes Secret, set `txnprocessor.uisV2.cockpitApi.existingSecret`. The tenant setup (`defaultTenantApiKey`) needs the key as a plain value.

For node authentication and other UIS v2 settings, see [Unified Indexer Service](/pt-br/products/custody/overview/architecture/unified-indexer-service#on-premises-deployments).

### Upgrade the deployment

Run `helm upgrade` with the updated values. The upgrade also removes the old indexer pods for the migrated networks.

The upgrade fails immediately if a network of an unsupported protocol is set to `uis-v2`, or if a protocol mixes `legacy` and `uis-v2` networks.

### Check the network and tenant setup

1. For each network, check that it's registered with UIS v2:

```bash
kubectl logs deploy/uis-v2-indexer-<network> -c ensure-network-config
```
The log shows `✓ Network created` or `✓ Network already exists`, followed by `=== Configuration ready ===`. In UIS v2, a network is named `<chain>-<network>`, for example `ethereum-testnet-sepolia`. Networks under the `evm` chain key keep their name as is.
2. Check that the tenant was created:

```bash
kubectl logs job/uis-v2-default-tenant-seed
```
The log shows `Done — default tenant seeded with the configured key.` The job stays until your next deployment.


### Monitor the migration

The migration starts on its own. Follow its progress in the transaction processor logs:

```bash
kubectl logs deploy/txnprocessor
```

| Stage | Log message |
|  --- | --- |
| The migration starts | `Triggering auto ledger-indexer migration. reason=never-run` |
| Ledgers are found | `Found N eligible ledgers for Phase 2 migration` |
| Each ledger completes | `Ledger indexer migration complete for ledgerId=…` |
| The migration completes | `Ledger indexer migration workflow complete: …` |
| Each ledger runs on UIS v2 | `Ledger allowed in Cockpit API: …` |


You can also follow the migration in Temporal, where the workflow ID is `auto-ledger-indexer-migration`, and `auto-ledger-indexer-migration_<ledgerId>` for each ledger.

When every ledger shows `Ledger allowed in Cockpit API`, the migration is complete, and you can resume normal operations, including outbound transactions on these ledgers.

## Troubleshooting

| Log message | Meaning | What to do |
|  --- | --- | --- |
| `Activity Failed getMigrationStatus … WebClientResponseException$Unauthorized` | The tenant API key of `txnprocessor` doesn't match the tenant in UIS v2. | Make `tenantApiKey` equal `defaultTenantApiKey`, and then contact your CPE to retry the migration. |
| `DEFAULT TENANT SEED INCONSISTENT` | A tenant with that name already exists with a different key. | Use the existing tenant's key, or a new tenant name. |
| `Blockchain API integration disabled…` | `txnprocessor` isn't connected to UIS v2. | Set `txnprocessor.uisV2.integrationEnabled` to `true`. |
| `Auto ledger-indexer migration disabled. Skipping.` | Automatic migration is turned off. | Contact your Customer Partner Engineer (CPE). |
| `Aborting before perform_migration — operator must investigate and re-trigger.` | The ledger's addresses didn't reconcile. Nothing was written. | Contact your CPE. |
| `Migration failed for X of Y ledger(s)…` | Some ledgers failed. Completed ledgers are kept. | Contact your CPE to retry the migration. Completed ledgers are skipped. |
| `Auto ledger-indexer migration not triggered. Existing MigrationRun status=COMPLETED` | The migration already ran, and it doesn't run again. | A network that you switch to UIS v2 now isn't migrated. Contact your CPE before you switch it. |


Retrying a failed migration requires a change in the database. Don't make this change yourself: contact your CPE.

## Known issues and limitations

- **Old indexer schemas**: The upgrade removes the old indexer pods for the migrated networks, but their database schemas remain. You can drop them manually to reclaim the space.
- **Transactions stuck in `DETECTED`**: In rare cases, such as a misconfiguration, a transaction can't be confirmed. After a number of retries, the underlying event moves to a dead-letter queue, and an operator must resolve it through the admin API: `GET /admin/dead-letters` lists the stuck entries, and `POST /admin/recover/{id}` recovers or resolves one.


## Related documentation

- [Ledger accounting refactor, phase 2](/pt-br/products/custody/support/change-history/v140#ledger-accounting-refactor-phase-2) (version 1.40 release notes)
- [Ledger accounting phase 1 migration guide](/pt-br/products/custody/operations-and-maintenance/upgrading/ledger-accounting-migration)
- [Unified Indexer Service](/pt-br/products/custody/overview/architecture/unified-indexer-service)


## Support

For additional assistance with the migration, contact your Customer Partner Engineer (CPE) or Ripple Support.