import { DeployOptions } from '../deploy.js'; import { OwnershipResult } from '../dotns.js'; import { LoadedProductConfig } from './config-load.js'; import 'polkadot-api/ws'; import 'multiformats/cid'; import '../manifest.js'; import '../dotns-protocol.js'; import '../environments.js'; import 'polkadot-api'; import '../errors.js'; import '../personhood/bootstrap.js'; import '../personhood/bind-personal-id.js'; import '../personhood/claim-pgas.js'; import '../personhood/bind-paid-alias.js'; import '../personhood/chain-prereqs.js'; import './types.js'; /** * Manifest publish orchestrator for RFC paritytech/triangle-js-sdks #0001 Steps 4 through 7. * * Wires [`storeFile`](../deploy.ts) and [`storeDirectory`](../deploy.ts) for * Bulletin uploads with [`DotNS`](../dotns.ts) for the on-chain text-record * writes. Each executable's contenthash and execution manifest are committed * atomically with `Utility.batch_all`, because either record without its * matching peer is not a valid launch contract. Root metadata and independent * executable kinds remain separate transactions; snapshot/rollback and the * Step 8 round-trip verification remain tracked follow-ups. */ interface PublishManifestOptions { /** Loaded + validated product config (call loadProductConfig first). */ loaded: LoadedProductConfig; /** Domain the legacy deploy targeted. Must match config.domain. */ domain: string; /** * Build-dir argument passed to the CLI plus the CID it produced. When the * resolved path of an executable in the config matches buildDir, we reuse * this CID instead of re-uploading the same bytes. */ buildDirCid?: { absPath: string; cid: string; }; /** * Env id (e.g. "paseo-next-v2"). Drives DotNS RPC + contract resolution * AND (#1094) the Bulletin endpoint the icon/executable uploads target — * both use the same resolved env, matching the legacy deploy. */ env?: string; /** Optional bulletin RPC override — same precedence as the legacy deploy's `--rpc` (#1094). */ rpc?: string; /** Required: signer mnemonic. */ mnemonic?: string; /** Optional Substrate-style derivation path. */ derivationPath?: string; /** Sign as the RFC-0022 product account, the same key deploy() registers the name with. */ productName?: string; } interface PublishManifestResult { iconCid: string; executableCids: Record; textRecordsWritten: number; } /** * Publish a product manifest on top of an already-completed legacy deploy. * * Uploads the icon and any executables that aren't covered by `buildDirCid`, * then writes the root + per-executable text records on dotNS. Subnames * (`app|widget|funding|worker.`) are created on demand and pointed at the * content resolver before any `setText`. * * #1187: the whole body (icon/executable upload + DotNS writes) runs inside * `withManifestSpan`, which gives this phase its own Sentry root span. Without * it, `setDeployAttribute` calls here (and #1158's * `deploy.dotns.nonce_contention_retries`, which fires from inside * setContenthash/setTextRecord's shared-signer retry path) silently no-op — * `deployRootSpan` is null once `deploy()` has already returned, which it has * by the time bin/bulletin-deploy calls publishManifest. */ declare function publishManifest(opts: PublishManifestOptions): Promise; /** * #1187 perf win: `registerSubdomain` already sets the fresh subname's * resolver to the content resolver atomically (`setSubnodeOwner` + * `setResolver`, batched via `Utility.batch_all` — see dotns.ts * `registerSubdomain`). Calling `ensureContentResolver` again right after a * fresh register was therefore a wasted chain read on every executable of * every fresh deploy. Only the already-owned path still needs it — a * pre-existing subname can have a stale or unset resolver. * * Takes a minimal injectable `dotns`-like interface (rather than the * concrete `DotNS` class) purely so this branch can be unit-tested without a * live chain connection; `publishManifestBody` always calls it with a real * `DotNS` instance. */ interface RegisterOrEnsureResolverDeps { registerSubdomain(sublabel: string, parentLabel: string): Promise; ensureContentResolver(domainName: string): Promise<{ changed: boolean; }>; } declare function registerOrEnsureResolver(dotns: RegisterOrEnsureResolverDeps, ownership: OwnershipResult, execKind: string, baseLabel: string, domain: string): Promise<{ registered: boolean; }>; declare function manifestSignerOptions(opts: Pick): Pick; declare function domainMatchesEnvTld(domain: string, tld: string): boolean; export { type PublishManifestOptions, type PublishManifestResult, type RegisterOrEnsureResolverDeps, domainMatchesEnvTld, manifestSignerOptions, publishManifest, registerOrEnsureResolver };