// SPDX-FileCopyrightText: © 2026 LEDGER SAS // SPDX-License-Identifier: Apache-2.0 import type { CurrencyConfig } from '../config' import type { CoinModuleApi, Memo, MemoNotSupported, TxData, TxDataNotSupported } from './types' import { notSupported } from './notSupported' /** * A full {@link CoinModuleApi} whose every capability is a "not supported" stub. * * Spread it and override what the chain does support, for a module that would rather * satisfy the complete contract directly than declare a `CoinModuleImpl` and be widened by * `withDefaults`: * * ```ts * export function createApi() { * return { * ...notSupportedApi(), * lastBlock, getBalance, listOperations, * } satisfies CoinModuleApi * } * ``` * * The two styles interoperate rather than compete, because the stubs are tagged: a value * built this way still tells the truth through `withDefaults`'s `supports()`, which treats a * tagged stub as an omitted method rather than as an implementation. So a module may be * authored either way, wrapped either way, and reports the same capabilities. * * It is also what a module can use when it does not implement everything the authoring type * requires — a read-only module, or a chain with no crafting path. The contract is satisfied * statically, and what the chain does not do stays visible at the definition site. * * `getAccountInfo` is the one method that does not throw: per ADR-045 a chain carrying no * extra account metadata is an answer, not a missing capability, so it resolves the * `{ type: 'none' }` sentinel — the same default `withDefaults` supplies. `listFeeOptions` is * left absent, likewise matching `withDefaults`. * * The return type is the contract itself, so a method added to `CoinModuleApi` makes this * fail to compile until it is covered here. */ export function notSupportedApi< ConfigType extends CurrencyConfig, MemoType extends Memo = MemoNotSupported, TxDataType extends TxData = TxDataNotSupported, >(): CoinModuleApi { return { // Required by the authoring type — a module spreading this one must override them to // be functional at all; they are stubbed here so the contract is satisfied statically. lastBlock: notSupported('lastBlock'), getBalance: notSupported('getBalance'), listOperations: notSupported('listOperations'), craftTransaction: notSupported('craftTransaction'), estimateFees: notSupported('estimateFees'), combine: notSupported('combine'), broadcast: notSupported('broadcast'), craftTransactionData: notSupported('craftTransactionData'), // Optional capabilities. getBlock: notSupported('getBlock'), getBlockInfo: notSupported('getBlockInfo'), getStakes: notSupported('getStakes'), getRewards: notSupported('getRewards'), getValidators: notSupported('getValidators'), call: notSupported('call'), craftRawTransaction: notSupported('craftRawTransaction'), register: notSupported('register'), getNextSequence: notSupported('getNextSequence'), validateIntent: notSupported('validateIntent'), validateAddress: notSupported('validateAddress'), // Not a capability: absent metadata is an answer (ADR-045). getAccountInfo: () => Promise.resolve({ type: 'none' }), } }