Custom migration sources
Plug any wallet plugin into the migration engine and inherit chunking, idempotency, the report, the UI, and the CLI for free.
What the engine gives you
Registering a source teaches Elite Balance where another wallet plugin keeps its balances. Everything else is inherited: background chunking, at-most-once imports per customer, the anomaly report, the reconciliation verdict, the Migration screen card with the deactivate-first step, and wp rb-elbal migrate your-source.
The contract
Implement RoundBorders\EliteBalance\Migration\SourceInterface:
| Method | Returns | Purpose |
|---|---|---|
id() | string | Unique lowercase key, e.g. acme. |
label() | string | Human name shown in the UI. |
detect() | array | ['available' => bool, 'blockers' => string[]]. Available means data exists on this site. Blockers are HARD blockers only (things the framework cannot fix, like a network-activated source plugin). |
active_plugin_files() | string[] | Plugin basenames currently active that must be deactivated before a real run. The screen offers deactivating them as the one-click freeze step; return an empty array when nothing needs freezing. |
count() | int | How many customers hold an importable (positive) balance. |
total() | string | The summed importable balance, canonical, for the reconciliation check. |
max_user_id() | int | The highest user ID carrying source data (the snapshot boundary). |
rows( $cursor, $max, $limit ) | array | The next slice, keyset-paginated by user ID: each row is ['user_id' => int, 'amount' => string or null, 'issue' => string or null]. |
Two rules make the report trustworthy: rows() must return every user with source data exactly once across the walk, including zeros and broken values, and unparseable values must come back with amount => null and an issue label instead of being skipped. The engine decides what to skip and what to report; sources never silently drop anyone.
The engine assigns the idempotency key (migration:{source}:{user_id}), so re-runs replay automatically. You never handle that.
Registering
add_filter( 'rb_elite_balance_migration_sources', function ( $sources ) {
$sources['acme'] = new Acme_Wallet_Source();
return $sources;
} );
The source appears on the Migration screen with its own card, and works from the CLI immediately:
wp rb-elbal migrate acme --deactivate --yes
Model to copy: the built-in WP Swings source reads one user meta per customer with keyset pagination and classifies bad values instead of skipping them. Yours will usually be under a hundred lines.
Stuck, or found a gap in these docs? Tell us and a human who works on the plugin answers.
Contact support →