datahaven/test/scripts/fund-providers.ts
Gonza Montiel 6dae38f587
feat: 🚀 add storage-hub nodes to CLI (#287)
##  Add StorageHub nodes to CLI

This PR adds StorageHub node infrastructure to the CLI and fixes CLI
flag handling and improves the CLI logic a bit.

### Fix: CLI safeguards
- Prevents contract deployment and validator operations when `--ndc`
flag is used
- Skips Kurtosis service display in summary when `--nlk` flag is used

### Feat: Dockerized Storage Hub Nodes
- Adds 5 Docker containers: PostgreSQL, MSP, BSP, Indexer, and Fisherman
nodes
- New CLI flags: `--storagehub` `--no-storagehub` to control StorageHub
nodes launch
- Automatic provider funding and registration (Charleth for MSP and
Dorothy for BSP)
- Exposes nodes on ports 9945-9948 for local development

**TODO**
- [x] MSP & BSP associated pre-funded account.
- [x] Call `forceMspSignUp` and `forceBspSignUp` extrinsics

---------

Co-authored-by: Steve Degosserie <723552+stiiifff@users.noreply.github.com>
2025-11-22 11:49:14 +01:00

109 lines
4.1 KiB
TypeScript

import { logger } from "utils";
import { SUBSTRATE_FUNDED_ACCOUNTS } from "utils/constants";
import { createPapiConnectors } from "utils/papi";
import type { LaunchedNetwork } from "../launcher/types/launchedNetwork";
export interface FundProvidersOptions {
launchedNetwork: LaunchedNetwork;
}
/**
* Provider account information for MSP and BSP nodes.
*
* DataHaven uses AccountId20 (Ethereum-style 20-byte addresses).
* In dev chains, CHARLETH and DOROTHY are pre-funded development accounts
* that correspond to //Charlie and //Dave derivations.
*
* For StorageHub providers, we use:
* - CHARLETH (//Charlie equivalent) for MSP
* - DOROTHY (//Dave equivalent) for BSP (as //Eve might not have pre-funded AccountId20)
*/
const PROVIDER_ACCOUNTS = {
// MSP account (Charleth = Charlie in AccountId20 format)
msp: {
name: "Charleth",
address: SUBSTRATE_FUNDED_ACCOUNTS.CHARLETH.publicKey, // 20-byte address
derivation: "//Charlie"
},
// BSP account (Dorothy = Dave in AccountId20 format, using instead of Eve)
bsp: {
name: "Dorothy",
address: SUBSTRATE_FUNDED_ACCOUNTS.DOROTHY.publicKey, // 20-byte address
derivation: "//Dave" // Using Dave instead of Eve for BSP
}
} as const;
/**
* Minimum balance required for provider operations.
* This includes:
* - Registration deposit (SpMinDeposit = 100 HAVE)
* - Transaction fees
* - Operational costs
*/
const MIN_PROVIDER_BALANCE = BigInt(200) * BigInt(10 ** 18); // 200 HAVE
/**
* Funds StorageHub provider accounts (MSP and BSP) with native tokens.
*
* In development chains, //Charlie and //Eve are pre-funded, so this function
* primarily verifies they have sufficient balance for provider operations.
* If the balance is insufficient, it can transfer additional funds from Alice.
*
* @param options - Configuration options including the launched network
*/
export async function fundProviders(options: FundProvidersOptions): Promise<void> {
logger.info("💰 Checking and funding StorageHub provider accounts...");
const aliceContainerName = `datahaven-alice-${options.launchedNetwork.networkId}`;
const alicePort = options.launchedNetwork.getContainerPort(aliceContainerName);
const { client, typedApi } = createPapiConnectors(`ws://127.0.0.1:${alicePort}`);
try {
// Check MSP account balance
logger.info(`Checking MSP account (${PROVIDER_ACCOUNTS.msp.name})...`);
const mspAccount = await typedApi.query.System.Account.getValue(PROVIDER_ACCOUNTS.msp.address);
const mspBalance = mspAccount?.data?.free ?? BigInt(0);
logger.debug(`MSP balance: ${mspBalance.toString()}`);
if (mspBalance < MIN_PROVIDER_BALANCE) {
logger.warn(`MSP account has insufficient balance (${mspBalance} < ${MIN_PROVIDER_BALANCE})`);
logger.info(
"Note: In dev chains, //Charlie should be pre-funded. If balance is low, ensure the chain is properly initialized."
);
} else {
logger.success(`MSP account has sufficient balance: ${mspBalance.toString()}`);
}
// Check BSP account balance
logger.info(`Checking BSP account (${PROVIDER_ACCOUNTS.bsp.name})...`);
const bspAccount = await typedApi.query.System.Account.getValue(PROVIDER_ACCOUNTS.bsp.address);
const bspBalance = bspAccount?.data?.free ?? BigInt(0);
logger.debug(`BSP balance: ${bspBalance.toString()}`);
if (bspBalance < MIN_PROVIDER_BALANCE) {
logger.warn(`BSP account has insufficient balance (${bspBalance} < ${MIN_PROVIDER_BALANCE})`);
logger.info(
"Note: In dev chains, //Eve should be pre-funded. If balance is low, ensure the chain is properly initialized."
);
} else {
logger.success(`BSP account has sufficient balance: ${bspBalance.toString()}`);
}
logger.success("Provider accounts funding check completed");
} catch (error) {
logger.error(`Failed to check provider balances: ${error}`);
throw error;
} finally {
client.destroy();
}
}
/**
* Gets the provider account addresses.
*
* @returns Object containing MSP and BSP account information
*/
export function getProviderAccounts() {
return PROVIDER_ACCOUNTS;
}