import { PolkadotSigner } from 'polkadot-api'; import { NonRetryableError } from './errors.js'; declare function formatPasBalance(plancks: bigint): string; interface PoolAccount { index: number; path: string; publicKey: Uint8Array; signer: PolkadotSigner; address: string; } interface PoolAuthorization extends PoolAccount { transactions: bigint; renewBytes: bigint; expiration: number; } declare const DEPLOY_PATH_PREFIX = "//deploy"; declare function poolAccountDerivationPath(index: number): string; /** Inverse of poolAccountDerivationPath: N for "//deploy/N", else undefined. */ declare function parsePoolDerivationIndex(path: string): number | undefined; declare function assetHubTopUpAmount(balanceRaw: bigint, thresholdRaw: bigint, targetRaw: bigint): bigint; /** * The mnemonic the `//deploy/N` pool is derived from, for EVERY entry point that touches the * pool — the deploy path and `bulletin-bootstrap` alike. * * The two used to disagree: the deploy path read `BULLETIN_POOL_MNEMONIC` only, while bootstrap * also accepted `MNEMONIC`. With `MNEMONIC` set and `BULLETIN_POOL_MNEMONIC` unset — the normal * shape for anyone exporting a single mnemonic, and what the nightly E2E jobs do — bootstrap * authorized one set of accounts while deploys uploaded from another, and the only symptom was * an unauthorized-storage failure on an env that had just been bootstrapped. * * `MNEMONIC` deliberately does NOT participate: it names the DotNS signing account, and the pool * is a distinct, shared identity. Accepting it here would silently re-point every pool deploy at * an account with no grant. See `describeIgnoredPoolMnemonicEnv` for the warning bootstrap prints * when the two are confusable. */ declare function resolvePoolMnemonic(explicit?: string): string; /** * Warning text for the one case where an operator can reasonably expect `MNEMONIC` to drive pool * derivation and it does not, or null when there is nothing to say. Pure so it can be unit-tested * without spawning the bootstrap CLI. */ declare function describeIgnoredPoolMnemonicEnv(env?: Record, explicitFlag?: string): string | null; declare function derivePoolAccounts(poolSize?: number, mnemonic?: string): PoolAccount[]; interface BulletinAuthorization { expiration: number; transactionsAllowance: number; transactionsUsed: number; bytesAllowance: bigint; bytesUsed: bigint; bytesPermanentUsed: bigint; } declare const ACCOUNT_AUTHORIZATION_FIELDS: readonly ["expires_at", "bytes_allowance", "bytes_used", "bytes_permanent_used", "transactions_allowance", "transactions_used"]; /** * Read an account's Bulletin storage authorization via the * `BulletinTransactionStorageApi::account_authorization` runtime API — the one * chain entry point for this, replacing the old `TransactionStorage.Authorizations` * read. That entry is no longer client-readable: its `AuthorizationExtent` carries * an opaque consumer payload (`extra`) where `bytes_permanent` used to sit. * * Returns null both when the account was never authorized and when its grant has * lapsed — the API filters expired entries, so a non-null result is always active. * * A `Some` missing any field throws instead of defaulting to 0: a renamed field * would otherwise read as "no allowance, expires at block 0" and fail every deploy * with a message pointing at the account rather than at the chain. */ declare function readAccountAuthorization(api: any, address: string): Promise; declare function remainingRenewBytes(auth: BulletinAuthorization): bigint; declare function remainingTransactions(auth: BulletinAuthorization): bigint; declare function remainingStoreBytes(auth: BulletinAuthorization): bigint; interface AuthorizationNeeds { transactions: number; bytes?: bigint; } declare const DEFAULT_AUTHORIZATION_NEEDS: AuthorizationNeeds; declare function quotaHeadroomDimensions(auth: BulletinAuthorization, needs?: AuthorizationNeeds): Array<"transactions" | "bytes">; declare function isAuthorizationSufficient(auth: { expiration: number; } | null | undefined, currentBlock: number): boolean; declare function accountsNeedingAuthorization(auths: PoolAuthorization[], currentBlock: number): PoolAuthorization[]; declare const BULLETIN_BLOCK_TIME_SECS = 6; declare const BULLETIN_BLOCKS_PER_DAY: number; declare function accountsNeedingReauthorization(auths: PoolAuthorization[], currentBlock: number, bufferBlocks?: number): PoolAuthorization[]; interface AutoReauthorizeEnv { network?: string; bulletinAutoAuthorize?: boolean; } declare function isAutoReauthorizeAllowed(env: AutoReauthorizeEnv | null | undefined): boolean; interface SelectionResult { account: PoolAuthorization; eligibleCount: number; } declare function selectAccount(authorizations: PoolAuthorization[], random?: () => number, pinnedIndex?: number): SelectionResult; declare const STUCK_NONCE_GAP_THRESHOLD = 8; declare const NONCE_HEALTH_SAMPLES = 8; type NonceHealthVerdict = "healthy" | "stuck" | "unknown"; interface NonceHealth { verdict: NonceHealthVerdict; onchain?: number; /** Max system_accountNextIndex over the successful samples. */ nextIndex?: number; gap?: number; samples: number[]; /** #1658: some sample is within the threshold of the chain while the max is beyond it (a queue local to one backend). */ backendLocal?: boolean; /** Why the verdict is "unknown". */ reason?: string; } declare function nonceGapVerdict(onchain: number, nextIndex: number, threshold?: number): "healthy" | "stuck"; declare function withTimeout(fn: () => Promise, ms: number, what: string): Promise; interface NonceHealthDeps { /** The account's nonce in System.Account at the BEST block (not finalized: nextIndex is best + pool). */ readOnchainNonce: (address: string) => Promise; /** One system_accountNextIndex read over a fresh connection. `sample` is 0..samples-1. */ readNextIndex: (address: string, sample: number) => Promise; samples?: number; timeoutMs?: number; threshold?: number; /** Wait before each stuck-vs-busy re-read of the on-chain nonce. */ confirmDelayMs?: number; /** How many re-reads (each after confirmDelayMs) before a flat nonce counts. */ confirmReads?: number; sleep?: (ms: number) => Promise; } /** Never throws: any RPC failure yields verdict "unknown" so the caller can proceed as before. */ declare function checkPoolAccountNonceHealth(address: string, deps: NonceHealthDeps): Promise; interface StuckPoolAccount { index: number; address: string; health: NonceHealth; } interface HealthySelectionResult extends SelectionResult { skippedStuck: StuckPoolAccount[]; } /** Thrown when BULLETIN_POOL_ACCOUNT_INDEX pins an account whose queue is stuck. */ declare class StuckPoolAccountError extends NonRetryableError { readonly skippedStuck: StuckPoolAccount[]; constructor(message: string, skippedStuck: StuckPoolAccount[]); } interface HealthySelectionOptions { pinnedIndex?: number; random?: () => number; checkHealth: (account: PoolAuthorization) => Promise; log?: { warn: (msg: string) => void; }; } /** The fail-fast message for a signer whose queue is stuck; `remedy` is the caller-specific way out. */ declare function stuckQueueMessage(who: string, address: string, h: NonceHealth, remedy: string): string; /** * selectAccount() plus a stuck-queue check on the chosen account (#1637). * Unpinned: a stuck draw is skipped and the next one is drawn uniformly from * the rest. Never sort by gap: that is the bias tools/verify_pool_distribution.py * guards against. Pinned: a stuck account fails fast. */ declare function selectHealthyPoolAccount(authorizations: PoolAuthorization[], { pinnedIndex, random, checkHealth, log }: HealthySelectionOptions): Promise; declare function fetchPoolAuthorizations(api: any, accounts: PoolAccount[]): Promise; declare function isTestnetSpecName(specName: string | undefined | null): boolean; declare function testnetFromNetworkField(network?: string | null): boolean | undefined; declare function detectTestnet(api: any, network?: string | null): Promise; declare function _resetTestnetCacheForTests(): void; interface EnsureAuthorizedResult { quotaExhausted: boolean; dimensions: Array<"transactions" | "bytes">; } declare function ensureAuthorized(api: any, address: string, label?: string, opts?: { autoAuthorize?: boolean; authorizer?: string; network?: string; needs?: AuthorizationNeeds; precheckedAuth?: { auth: BulletinAuthorization | null; currentBlock: number; }; }): Promise; interface EnsurePoolFundedOptions { envEntry: AutoReauthorizeEnv | null | undefined; thresholdRaw?: bigint; targetRaw?: bigint; funderMnemonic?: string; funderDerivationPath?: string; } declare function ensurePoolAccountsFundedOnAssetHub(assetHubRpc: string, poolSize: number, poolMnemonic: string | undefined, opts: EnsurePoolFundedOptions): Promise; interface BootstrapPoolOptions { authorizerMnemonic?: string; envAuthorizer?: string; bulletinAuthorizeV2?: boolean; reauthBufferBlocks?: number; allowAutoReauthorize?: boolean; network?: string; } declare function bootstrapPool(bulletinRpc: string, poolSize?: number, mnemonic?: string, opts?: BootstrapPoolOptions): Promise; export { ACCOUNT_AUTHORIZATION_FIELDS, type AuthorizationNeeds, type AutoReauthorizeEnv, BULLETIN_BLOCKS_PER_DAY, BULLETIN_BLOCK_TIME_SECS, type BootstrapPoolOptions, type BulletinAuthorization, DEFAULT_AUTHORIZATION_NEEDS, DEPLOY_PATH_PREFIX, type EnsureAuthorizedResult, type EnsurePoolFundedOptions, type HealthySelectionOptions, type HealthySelectionResult, NONCE_HEALTH_SAMPLES, type NonceHealth, type NonceHealthDeps, type NonceHealthVerdict, type PoolAccount, type PoolAuthorization, STUCK_NONCE_GAP_THRESHOLD, type SelectionResult, type StuckPoolAccount, StuckPoolAccountError, _resetTestnetCacheForTests, accountsNeedingAuthorization, accountsNeedingReauthorization, assetHubTopUpAmount, bootstrapPool, checkPoolAccountNonceHealth, derivePoolAccounts, describeIgnoredPoolMnemonicEnv, detectTestnet, ensureAuthorized, ensurePoolAccountsFundedOnAssetHub, fetchPoolAuthorizations, formatPasBalance, isAuthorizationSufficient, isAutoReauthorizeAllowed, isTestnetSpecName, nonceGapVerdict, parsePoolDerivationIndex, poolAccountDerivationPath, quotaHeadroomDimensions, readAccountAuthorization, remainingRenewBytes, remainingStoreBytes, remainingTransactions, resolvePoolMnemonic, selectAccount, selectHealthyPoolAccount, stuckQueueMessage, testnetFromNetworkField, withTimeout };