diff --git a/apps/gateway-ui/src/types.tsx b/apps/gateway-ui/src/types.tsx index 51f56b41..dddc764a 100644 --- a/apps/gateway-ui/src/types.tsx +++ b/apps/gateway-ui/src/types.tsx @@ -8,8 +8,11 @@ export interface Registration { fees: Fees; mint_channel_id: number; node_pub_key: string; - route_hints: object[]; // FIXME - valid_until: object; // FIXME + route_hints: object[]; // FIXME : https://github.com/fedimint/ui/issues/80 + valid_until: { + nanos_since_epoch: number; + secs_since_epoch: number; + }; } export interface Federation { diff --git a/apps/guardian-ui/src/GuardianApi.ts b/apps/guardian-ui/src/GuardianApi.ts index 690e9150..8ac65238 100644 --- a/apps/guardian-ui/src/GuardianApi.ts +++ b/apps/guardian-ui/src/GuardianApi.ts @@ -1,7 +1,9 @@ import { JsonRpcError, JsonRpcWebsocket } from 'jsonrpc-client-websocket'; import { ConfigGenParams, ConsensusState, PeerHashMap } from './setup/types'; import { + ConfigResponse, ConsensusStatus, + Gateway, ServerStatus, StatusResponse, Versions, @@ -20,7 +22,7 @@ export interface SocketAndAuthInterface { interface RpcInterface { call: ( method: SetupRpc | AdminRpc | SharedRpc, - params?: object | null + params?: unknown ) => Promise; // TODO: Consider moving this to `SocketAndAuthInterface` as part of the authentication methods. clearPassword: () => void; @@ -130,7 +132,14 @@ class BaseGuardianApi call = async ( method: SetupRpc | AdminRpc | SharedRpc, - params: object | null = null + params: unknown = null + ): Promise => { + return this.call_any_method(method, params); + }; + + call_any_method = async ( + method: string, + params: unknown = null ): Promise => { try { const websocket = await this.connect(); @@ -191,12 +200,22 @@ enum AdminRpc { fetchEpochCount = 'fetch_epoch_count', consensusStatus = 'consensus_status', connectionCode = 'connection_code', + config = 'config', + module = 'module', +} + +export enum LightningModuleRpc { + listGateways = 'list_gateways', } +type ModuleRpc = LightningModuleRpc; + export interface AdminApiInterface extends SharedApiInterface { version: () => Promise; fetchEpochCount: () => Promise; connectionCode: () => Promise; + config: (connection: string) => Promise; + moduleApiCall: (moduleId: number, rpc: ModuleRpc) => Promise; } export class GuardianApi @@ -332,4 +351,13 @@ export class GuardianApi connectionCode = (): Promise => { return this.base.call(AdminRpc.connectionCode); }; + + config = (connection: string): Promise => { + return this.base.call(AdminRpc.config, connection); + }; + + moduleApiCall = (moduleId: number, rpc: ModuleRpc): Promise => { + const method = `${AdminRpc.module}_${moduleId}_${rpc}`; + return this.base.call_any_method(method); + }; } diff --git a/apps/guardian-ui/src/components/ConnectGuardians.tsx b/apps/guardian-ui/src/components/ConnectGuardians.tsx index 9be7427c..81a09f5b 100644 --- a/apps/guardian-ui/src/components/ConnectGuardians.tsx +++ b/apps/guardian-ui/src/components/ConnectGuardians.tsx @@ -16,7 +16,7 @@ import { } from '@chakra-ui/react'; import { CopyInput, Table, TableRow } from '@fedimint/ui'; import { useConsensusPolling, useSetupContext } from '../hooks'; -import { ServerStatus } from '../types'; +import { ModuleKind, ServerStatus } from '../types'; import { GuardianRole } from '../setup/types'; import { getModuleParamsFromConfig } from '../utils/api'; import { ReactComponent as CopyIcon } from '../assets/svgs/copy.svg'; @@ -79,13 +79,13 @@ export const ConnectGuardians: React.FC = ({ next }) => { }, { label: 'Network', - value: getModuleParamsFromConfig(configGenParams, 'wallet')?.consensus - ?.network, + value: getModuleParamsFromConfig(configGenParams, ModuleKind.Wallet) + ?.consensus?.network, }, { label: 'Block confirmations', - value: getModuleParamsFromConfig(configGenParams, 'wallet')?.consensus - ?.finality_delay, + value: getModuleParamsFromConfig(configGenParams, ModuleKind.Wallet) + ?.consensus?.finality_delay, }, ]; diff --git a/apps/guardian-ui/src/components/SetConfiguration.tsx b/apps/guardian-ui/src/components/SetConfiguration.tsx index db8f84e0..a4291817 100644 --- a/apps/guardian-ui/src/components/SetConfiguration.tsx +++ b/apps/guardian-ui/src/components/SetConfiguration.tsx @@ -29,6 +29,7 @@ import { ReactComponent as FedimintLogo } from '../assets/svgs/fedimint.svg'; import { ReactComponent as BitcoinLogo } from '../assets/svgs/bitcoin.svg'; import { ReactComponent as ArrowRightIcon } from '../assets/svgs/arrow-right.svg'; import { formatApiErrorMessage, getModuleParamsFromConfig } from '../utils/api'; +import { ModuleKind } from '../types'; interface Props { next: () => void; @@ -69,11 +70,11 @@ export const SetConfiguration: React.FC = ({ next }: Props) => { setFederationName(params.meta?.federation_name || ''); setMintAmounts( - getModuleParamsFromConfig(params, 'mint')?.consensus?.mint_amounts || - mintAmounts + getModuleParamsFromConfig(params, ModuleKind.Mint)?.consensus + ?.mint_amounts || mintAmounts ); - const walletModule = getModuleParamsFromConfig(params, 'wallet'); + const walletModule = getModuleParamsFromConfig(params, ModuleKind.Wallet); if (walletModule) { setBlockConfirmations( diff --git a/apps/guardian-ui/src/setup/types.tsx b/apps/guardian-ui/src/setup/types.tsx index 50717c43..f6a70c36 100644 --- a/apps/guardian-ui/src/setup/types.tsx +++ b/apps/guardian-ui/src/setup/types.tsx @@ -1,4 +1,4 @@ -import { ServerStatus } from '../types'; +import { MetaConfig, ModuleKind, ServerStatus } from '../types'; export enum GuardianRole { Host = 'Host', @@ -42,22 +42,22 @@ export interface BitcoinRpc { export type PeerHashMap = Record; -export type LnFedimintModule = [ - 'ln', +export type LnModuleParams = [ + ModuleKind.Ln, { consensus?: object; local?: object; } ]; -export type MintFedimintModule = [ - 'mint', +export type MintModuleParams = [ + ModuleKind.Mint, { consensus?: { mint_amounts: number[] }; local?: object; } ]; -export type WalletFedimintModule = [ - 'wallet', +export type WalletModuleParams = [ + ModuleKind.Wallet, { consensus?: { finality_delay: number; network: Network }; local?: { @@ -65,20 +65,16 @@ export type WalletFedimintModule = [ }; } ]; -export type OtherFedimintModule = [string, object]; -export type AnyFedimintModule = - | LnFedimintModule - | MintFedimintModule - | WalletFedimintModule - | OtherFedimintModule; - -type Meta = { federation_name?: string }; - -type Modules = Record; +export type OtherModuleParams = [string, object]; +export type AnyModuleParams = + | LnModuleParams + | MintModuleParams + | WalletModuleParams + | OtherModuleParams; export type ConfigGenParams = { - meta: Meta; - modules: Modules; + meta: MetaConfig; + modules: Record; }; type ConsensusParams = ConfigGenParams & { diff --git a/apps/guardian-ui/src/types.tsx b/apps/guardian-ui/src/types.tsx index 8bf54f51..a3653aaf 100644 --- a/apps/guardian-ui/src/types.tsx +++ b/apps/guardian-ui/src/types.tsx @@ -47,3 +47,53 @@ export interface Versions { } >; } + +export enum ModuleKind { + Ln = 'ln', + Mint = 'mint', + Wallet = 'wallet', +} + +interface FedimintModule { + config: string; + kind: ModuleKind; + version: number; +} + +interface ApiEndpoint { + name: string; + url: string; +} + +export type MetaConfig = { federation_name?: string }; + +export interface ClientConfig { + consenus_version: number; + epoch_pk: string; + federation_id: string; + api_endpoint: Record; + modules: Record; + meta: MetaConfig; +} +export interface ConfigResponse { + client_config: ClientConfig; +} + +// These types are shared with the gateway-ui +export interface Fees { + base_msat: number; + proportional_millionths: number; +} + +export interface Gateway { + gateway_pub_key: string; + api: string; + fees: Fees; + mint_channel_id: number; + node_pub_key: string; + route_hints: object[]; // FIXME: https://github.com/fedimint/ui/issues/80 + valid_until: { + nanos_since_epoch: number; + secs_since_epoch: number; + }; +} diff --git a/apps/guardian-ui/src/utils/api.ts b/apps/guardian-ui/src/utils/api.ts index 2af283f3..a50c21bf 100644 --- a/apps/guardian-ui/src/utils/api.ts +++ b/apps/guardian-ui/src/utils/api.ts @@ -1,15 +1,15 @@ import { JsonRpcError } from 'jsonrpc-client-websocket'; -import { AnyFedimintModule, ConfigGenParams } from '../setup/types'; +import { AnyModuleParams, ConfigGenParams } from '../setup/types'; /** * Given a config and the name of the module, return the module */ -export function getModuleParamsFromConfig( +export function getModuleParamsFromConfig( config: ConfigGenParams | null, moduleName: T // Ignore any type below, it will be properly typed at call time via moduleName. // eslint-disable-next-line @typescript-eslint/no-explicit-any -): Extract[1] | null { +): Extract[1] | null { if (!config) return null; const module = Object.values(config.modules).find((m) => m[0] === moduleName); return module ? module[1] : null;