diff --git a/README.md b/README.md index e69de29..d476e43 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,50 @@ +# chainconfig — IPI Single Source of Truth (SSOT) + +`config.json` jest **jedynym źródłem prawdy** parametrów sieci IPI. +Wszystkie konsumenty (`wallet-core.js`, `ipi-rpc`, portfele Keplr-kompatybilne i aplikacje) +powinny czytać wartości stąd, zamiast trzymać własne kopie chain-id / denom / endpointów. + +## Użycie + +```js +import config, { getEndpoints, getChainId, validateConfig } from "chain"; + +validateConfig(); // rzuca wyjątek gdy brakuje wymaganych pól +const { rpc, rest, grpc } = getEndpoints(); +const chainId = getChainId("testnet"); // "ipi-testnet-1" +``` + +Domyślny eksport to sparsowany obiekt `config.json` (import JSON). + +## Schemat pól + +| Pole | Typ | Opis | +| --- | --- | --- | +| `chainId` | string | Aktywny chain-id sieci głównej (`ipi-mainnet-2`). | +| `chainName` | string | Czytelna nazwa sieci. | +| `bip44.coinType` / `slip44` | number | SLIP-44 coin type (`118`, standard Cosmos). | +| `bech32Config` | object | Pełny zestaw prefiksów bech32 (Keplr). | +| `bech32Prefix` | string | Skrócony prefiks konta (`ipi`) — wygoda dla narzędzi. | +| `currencies[]` | array | Waluty wyświetlane: `coinDenom`, `coinMinimalDenom`, `coinDecimals`. | +| `feeCurrencies[]` | array | Jak wyżej + `gasPriceStep` (`low`/`average`/`high`). | +| `stakeCurrency` | object | Waluta stakingu. | +| `features[]` | array | Włączone moduły łańcucha (`stargate`, `cosmwasm`). | +| `endpoints` | object | `rpc` / `rest` (LCD) / `grpc`. | +| `blockTime` | number | Docelowy czas bloku (sekundy, wartość przybliżona). | +| `explorer` | string | URL eksploratora. | +| `networks` | object | Chain-id per sieć: `mainnet`, `testnet`. | + +## Denominacja + +Bazowy denom to `nipi` (nano-IPI), display `IPI`, `coinDecimals: 9` +(1 IPI = 1 000 000 000 nipi). + +## Uwagi (DRAFT — do review po Fala 1 devnet) + +- `endpoints.grpc` (`ipicoin.eu:9090`) oraz `networks.testnet.chainId` (`ipi-testnet-1`) + to wartości robocze do potwierdzenia po uruchomieniu devnet. +- `gasPriceStep` i `blockTime` — wartości domyślne do kalibracji. + +## Licencja + +Apache 2.0 © IPI DAO 2026. Maintainership: Sett Sarverott. diff --git a/config.json b/config.json index 5163176..02fe853 100644 --- a/config.json +++ b/config.json @@ -3,9 +3,11 @@ "chainName": "IPI Mainnet 2", "rpc": "https://ipicoin.eu/rpc", "rest": "https://ipicoin.eu/api", + "grpc": "https://ipicoin.eu:9090", "bip44": { "coinType": 118 }, + "slip44": 118, "bech32Config": { "bech32PrefixAccAddr": "ipi", "bech32PrefixAccPub": "ipipub", @@ -14,6 +16,7 @@ "bech32PrefixConsAddr": "ipivalcons", "bech32PrefixConsPub": "ipivalconspub" }, + "bech32Prefix": "ipi", "currencies": [ { "coinDenom": "IPI", @@ -25,7 +28,12 @@ { "coinDenom": "IPI", "coinMinimalDenom": "nipi", - "coinDecimals": 9 + "coinDecimals": 9, + "gasPriceStep": { + "low": 0.01, + "average": 0.025, + "high": 0.04 + } } ], "stakeCurrency": { @@ -33,5 +41,15 @@ "coinMinimalDenom": "nipi", "coinDecimals": 9 }, - "features": ["stargate", "cosmwasm"] + "features": ["stargate", "cosmwasm"], + "blockTime": 6, + "explorer": "https://ipicoin.eu", + "networks": { + "mainnet": { + "chainId": "ipi-mainnet-2" + }, + "testnet": { + "chainId": "ipi-testnet-1" + } + } } diff --git a/index.js b/index.js index 1836517..935a6e6 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,81 @@ // on Apache license 2.0 @ IPI DAO 2026 // maintainership by Sett Sarverott -import chainConfiguration from "./config.json" with {type: 'json'}; +import chainConfiguration from "./config.json" with { type: "json" }; +/** + * Single Source of Truth (SSOT) for IPI network parameters. + * Consumed by wallet-core.js, ipi-rpc and downstream apps. + */ export default chainConfiguration; + +export const config = chainConfiguration; + +/** Returns the network endpoints (rpc / rest / grpc) from the top-level SSOT fields. */ +export function getEndpoints(cfg = chainConfiguration) { + return { + rpc: cfg.rpc, + rest: cfg.rest, + grpc: cfg.grpc, + }; +} + +/** Returns the chain-id for a given network ("mainnet" | "testnet"). */ +export function getChainId(network = "mainnet") { + return chainConfiguration.networks?.[network]?.chainId ?? chainConfiguration.chainId; +} + +/** Shape + value validation — throws on missing required fields or non-canonical values. */ +export function validateConfig(cfg = chainConfiguration) { + const required = [ + "chainId", + "chainName", + "bech32Prefix", + "rpc", + "rest", + "grpc", + "currencies", + "feeCurrencies", + "stakeCurrency", + ]; + const missing = required.filter((key) => cfg[key] === undefined); + if (missing.length > 0) { + throw new Error(`chainconfig: missing required fields: ${missing.join(", ")}`); + } + + // Value validation — enforce canonical IPI network parameters (SSOT invariants). + const errors = []; + + if (typeof cfg.chainId !== "string" || cfg.chainId.trim() === "") { + errors.push("chainId must be a non-empty string"); + } + if (cfg.bech32Prefix !== "ipi") { + errors.push(`bech32Prefix must be "ipi" (got ${JSON.stringify(cfg.bech32Prefix)})`); + } + if (cfg.bip44?.coinType !== 118) { + errors.push(`bip44.coinType must be 118 (got ${JSON.stringify(cfg.bip44?.coinType)})`); + } + + // Every currency list entry must carry the canonical base denom + decimals. + const currencyGroups = { + currencies: cfg.currencies, + feeCurrencies: cfg.feeCurrencies, + stakeCurrency: cfg.stakeCurrency, + }; + for (const [name, group] of Object.entries(currencyGroups)) { + const entries = Array.isArray(group) ? group : [group]; + for (const entry of entries) { + if (entry?.coinMinimalDenom !== "nipi") { + errors.push(`${name}: coinMinimalDenom must be "nipi" (got ${JSON.stringify(entry?.coinMinimalDenom)})`); + } + if (entry?.coinDecimals !== 9) { + errors.push(`${name}: coinDecimals must be 9 (got ${JSON.stringify(entry?.coinDecimals)})`); + } + } + } + + if (errors.length > 0) { + throw new Error(`chainconfig: invalid values: ${errors.join("; ")}`); + } + return true; +} diff --git a/package.json b/package.json index ca10f21..b40ae24 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "type": "git", "url": "git+https://github.com/ipicoin/chainconfig.git" }, - "license": "ISC", + "license": "Apache-2.0", "author": "IPI DAO", "type": "module", "main": "index.js",