@totemsdk/omnia-host 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -38,7 +38,7 @@ function createTotemNodeAdapter(options) {
38
38
  getTokensByCreator: (address) => provider.getTokensByCreator(address),
39
39
  broadcastTxPoW: (txpowHex) => provider.broadcastTxPoW(txpowHex),
40
40
  getMinTxPowWork: () => provider.getMinTxPowWork ? provider.getMinTxPowWork() : Promise.resolve(null),
41
- ...(provider.submitTransaction
41
+ ...(provider.submitTransaction && process.env.OMNIA_CHAIN_NO_TXNMINE !== '1'
42
42
  ? { submitTransaction: provider.submitTransaction.bind(provider) }
43
43
  : {}),
44
44
  async getMode() {
package/dist/cli.js CHANGED
@@ -1,10 +1,74 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
3
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
+ const node_path_1 = __importDefault(require("node:path"));
4
8
  const index_js_1 = require("./index.js");
9
+ const pairing_js_1 = require("./pairing.js");
5
10
  const signing_js_1 = require("./signing.js");
6
11
  const identity_js_1 = require("./identity.js");
12
+ const signer_port_js_1 = require("./signer-port.js");
13
+ async function runPair() {
14
+ const config = (0, index_js_1.loadConfigFromEnv)();
15
+ const port = Number(process.env.OMNIA_PAIR_PORT ?? 7789);
16
+ const host = process.env.OMNIA_PAIR_HOST ?? '127.0.0.1';
17
+ const origins = (process.env.OMNIA_PAIR_ORIGINS ?? '')
18
+ .split(',')
19
+ .map((value) => value.trim())
20
+ .filter(Boolean);
21
+ const capabilities = {
22
+ chain: { rpcUrl: config.chainRpcUrl, network: 'minima' },
23
+ lease: { modes: ['local', 'hybrid'] },
24
+ ...(config.p2pHubPort
25
+ ? {
26
+ p2p: {
27
+ hubUrl: `ws://${config.p2pHubHost ?? '127.0.0.1'}:${config.p2pHubPort}`,
28
+ scopes: ['p2p.pubsub'],
29
+ ...(config.p2pHubTopics ? { topicPrefixes: config.p2pHubTopics } : {}),
30
+ },
31
+ }
32
+ : {}),
33
+ };
34
+ const service = (0, pairing_js_1.createPairingService)({
35
+ storePath: node_path_1.default.join(node_path_1.default.dirname(config.dbPath), 'pairing.json'),
36
+ endpoint: `http://${host}:${port}`,
37
+ network: 'minima',
38
+ capabilities,
39
+ ...(origins.length ? { allowedOrigins: origins } : {}),
40
+ });
41
+ const server = (0, pairing_js_1.createPairingHttpServer)(service, { host, port });
42
+ const address = await server.listen();
43
+ const invitation = service.createInvitation();
44
+ if (process.argv.includes('--json')) {
45
+ console.log(JSON.stringify({ ...invitation, endpoint: `http://${address.host}:${address.port}` }, null, 2));
46
+ }
47
+ else {
48
+ console.log('');
49
+ console.log('Pair this node with your Totem extension');
50
+ console.log('');
51
+ console.log(`Node: ${service.nodeId}`);
52
+ console.log(`Network: ${service.network}`);
53
+ console.log(`Fingerprint: ${service.fingerprint}`);
54
+ console.log(`Endpoint: http://${address.host}:${address.port}`);
55
+ console.log(`Expires: ${new Date(invitation.expiresAt).toISOString()}`);
56
+ console.log('');
57
+ console.log(`Code: ${invitation.code}`);
58
+ console.log('');
59
+ console.log('Open Totem → Settings → Pair Node and paste the endpoint + code.');
60
+ }
61
+ await new Promise((resolve) => {
62
+ process.once('SIGINT', resolve);
63
+ process.once('SIGTERM', resolve);
64
+ });
65
+ await server.close();
66
+ }
7
67
  async function main() {
68
+ if (process.argv[2] === 'pair') {
69
+ await runPair();
70
+ return;
71
+ }
8
72
  const config = (0, index_js_1.loadConfigFromEnv)();
9
73
  const signing = config.readOnly || !(0, signing_js_1.hasSigningMaterial)(config)
10
74
  ? undefined
@@ -16,6 +80,9 @@ async function main() {
16
80
  ? {
17
81
  signer: signing.signer,
18
82
  leaseProvider: signing.leaseProvider,
83
+ signerPort: (0, signer_port_js_1.createLocalSignerPort)(signing),
84
+ transportKeyPair: signing.transportKeyPair,
85
+ transportPubkey: signing.transportPubkey,
19
86
  identity: identityAndManifest?.identity
20
87
  ? {
21
88
  address: signing.address,
package/dist/config.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { CustodyMode } from '@totemsdk/omnia';
1
2
  export interface OmniaHostConfig {
2
3
  port: number;
3
4
  host: string;
@@ -5,6 +6,14 @@ export interface OmniaHostConfig {
5
6
  chainRpcUrl: string;
6
7
  chainRpcPassword?: string;
7
8
  analyticsDbPath?: string;
9
+ /** Durable observation journal DB (default: alongside dbPath). */
10
+ observeDbPath?: string;
11
+ /** Observation network id (multi-network deployments). */
12
+ networkId?: string;
13
+ /** Stable observation source id (default: localPartyId or "omnia-host"). */
14
+ sourceNodeId?: string;
15
+ /** Disable the observation feed entirely (OMNIA_OBSERVE=0). */
16
+ observeDisabled?: boolean;
8
17
  relay?: string;
9
18
  localPubkey?: string;
10
19
  localPartyId?: string;
@@ -28,6 +37,11 @@ export interface OmniaHostConfig {
28
37
  deviceId?: string;
29
38
  /** "1" forces read-only mode even with keys present. */
30
39
  readOnly: boolean;
40
+ /**
41
+ * Deployment custody mode (RFC-058). Defaults to self-custody; hosted custody
42
+ * is explicit and policy-controlled. This does not change on-chain custody.
43
+ */
44
+ custodyMode?: CustodyMode;
31
45
  /** Identity file containing a delegated identity claim (operator root → service delegate). */
32
46
  identityFile?: string;
33
47
  /** EdgeServiceManifest serviceType (default "omnia-router"). */
@@ -42,6 +56,12 @@ export interface OmniaHostConfig {
42
56
  * Undefined disables token auth.
43
57
  */
44
58
  controlToken?: string;
59
+ /** RFC-062 local P2P hub (optional). One Hyperswarm shared by dapps. */
60
+ p2pHubPort?: number;
61
+ p2pHubHost?: string;
62
+ p2pHubToken?: string;
63
+ p2pHubOrigins?: string[];
64
+ p2pHubTopics?: string[];
45
65
  }
46
66
  /** Load the daemon configuration from the documented OMNIA_* environment. */
47
67
  export declare function loadConfigFromEnv(env?: NodeJS.ProcessEnv): OmniaHostConfig;
package/dist/config.js CHANGED
@@ -35,6 +35,27 @@ function parseOrigins(value) {
35
35
  .filter((part) => part.length > 0);
36
36
  return parts && parts.length > 0 ? parts : undefined;
37
37
  }
38
+ function parseOptionalPort(value, name) {
39
+ const trimmed = value?.trim();
40
+ if (!trimmed)
41
+ return undefined;
42
+ const port = Number(trimmed);
43
+ if (!Number.isInteger(port) || port < 1 || port > 65535) {
44
+ throw new Error(`${name} must be an integer between 1 and 65535; received ${value}`);
45
+ }
46
+ return port;
47
+ }
48
+ function parseList(value) {
49
+ const parts = value?.split(',').map((part) => part.trim()).filter(Boolean);
50
+ return parts && parts.length > 0 ? parts : undefined;
51
+ }
52
+ function parseCustodyMode(value) {
53
+ const mode = optional(value) ?? 'self';
54
+ if (mode !== 'self' && mode !== 'trust-minimised' && mode !== 'hosted') {
55
+ throw new Error(`OMNIA_CUSTODY must be self, trust-minimised or hosted; received ${value}`);
56
+ }
57
+ return mode;
58
+ }
38
59
  function parseSeed(value) {
39
60
  const seed = optional(value);
40
61
  if (!seed)
@@ -62,13 +83,18 @@ function loadConfigFromEnv(env = process.env) {
62
83
  if (seed && keyfile) {
63
84
  throw new Error('OMNIA_HOST_SEED and OMNIA_HOST_KEYFILE are mutually exclusive — set exactly one of them');
64
85
  }
86
+ const dbPath = env.OMNIA_HOST_DB?.trim() || node_path_1.default.join(dataRoot, 'omnia.sqlite');
65
87
  return {
66
88
  port: parsePort(env.OMNIA_HOST_PORT),
67
89
  host: env.OMNIA_HOST_BIND?.trim() || '127.0.0.1',
68
- dbPath: env.OMNIA_HOST_DB?.trim() || node_path_1.default.join(dataRoot, 'omnia.sqlite'),
90
+ dbPath,
69
91
  chainRpcUrl: env.OMNIA_CHAIN_RPC?.trim() || 'http://127.0.0.1:9005',
70
92
  chainRpcPassword: optional(env.OMNIA_CHAIN_RPC_PASSWORD),
71
93
  analyticsDbPath: optional(env.OMNIA_ANALYTICS_DB),
94
+ observeDbPath: optional(env.OMNIA_OBSERVE_DB) ?? node_path_1.default.join(node_path_1.default.dirname(dbPath), 'observe.sqlite'),
95
+ networkId: optional(env.OMNIA_NETWORK_ID),
96
+ sourceNodeId: optional(env.OMNIA_SOURCE_NODE_ID),
97
+ observeDisabled: env.OMNIA_OBSERVE?.trim() === '0' || env.OMNIA_OBSERVE?.trim().toLowerCase() === 'false',
72
98
  relay: optional(env.OMNIA_RELAY),
73
99
  localPubkey: optional(env.OMNIA_LOCAL_PUBKEY),
74
100
  localPartyId: optional(env.OMNIA_LOCAL_PARTY_ID),
@@ -82,9 +108,15 @@ function loadConfigFromEnv(env = process.env) {
82
108
  keyfilePassphrase: optional(env.OMNIA_HOST_KEYFILE_PASSPHRASE),
83
109
  deviceId: optional(env.OMNIA_HOST_DEVICE_ID),
84
110
  readOnly: env.OMNIA_HOST_READ_ONLY?.trim() === '1',
111
+ custodyMode: parseCustodyMode(env.OMNIA_CUSTODY),
85
112
  identityFile: optional(env.OMNIA_HOST_IDENTITY_FILE),
86
113
  serviceType: optional(env.OMNIA_HOST_SERVICE_TYPE) ?? 'omnia-router',
87
114
  allowedOrigins: parseOrigins(env.OMNIA_ALLOWED_ORIGINS),
115
+ p2pHubPort: parseOptionalPort(env.OMNIA_P2P_HUB_PORT, 'OMNIA_P2P_HUB_PORT'),
116
+ p2pHubHost: optional(env.OMNIA_P2P_HUB_HOST),
117
+ p2pHubToken: optional(env.OMNIA_P2P_HUB_TOKEN),
118
+ p2pHubOrigins: parseOrigins(env.OMNIA_P2P_HUB_ORIGINS),
119
+ p2pHubTopics: parseList(env.OMNIA_P2P_HUB_TOPICS),
88
120
  controlToken: optional(env.OMNIA_CONTROL_TOKEN),
89
121
  };
90
122
  }
package/dist/identity.js CHANGED
@@ -91,6 +91,7 @@ async function createHostManifest(config, signing, identity) {
91
91
  endpoints: [{ type: 'websocket', uri: `ws://${config.host}:${config.port}${config.wsPath}` }],
92
92
  capabilities: ['omnia:open-channel', 'omnia:update-channel', 'omnia:route', 'omnia:settle'],
93
93
  tags: ['omnia', 'payment-channel', 'daemon'],
94
+ transportPubkey: signing.transportPubkey,
94
95
  };
95
96
  // RFC-037: sign the manifest with the unified child TreeKey. Allocate a
96
97
  // one-time leaf via the lease so restarts never reuse a WOTS leaf.
package/dist/index.d.ts CHANGED
@@ -19,3 +19,6 @@ export type { HostApiContext } from './api/methods.js';
19
19
  export type { OperationStoreLike } from './api/methods.js';
20
20
  export { DisabledAnalyticsStore, DuckDbAnalyticsStore, initializeDuckDb } from './stores/analytics.js';
21
21
  export type { AnalyticsEvent, AnalyticsStore, DuckDbConnection } from './stores/analytics.js';
22
+ export { createLocalSignerPort, createPolicySignerPort } from './signer-port.js';
23
+ export type { SignerPolicy } from './signer-port.js';
24
+ export * from './observe/index.js';
package/dist/index.js CHANGED
@@ -1,6 +1,20 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
2
16
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.initializeDuckDb = exports.DuckDbAnalyticsStore = exports.DisabledAnalyticsStore = exports.createHostMethods = exports.GoRoutingProvider = exports.InProcessRoutingProvider = exports.createTotemNodeAdapter = exports.OperationStore = exports.SqliteChannelStore = exports.loadHostIdentity = exports.createHostManifest = exports.createHostIdentityAndManifest = exports.encryptSeedForKeyfile = exports.leaseStorageDir = exports.JsonFileStorageAdapter = exports.hasSigningMaterial = exports.createHostSigning = exports.createOmniaHost = exports.loadConfigFromEnv = void 0;
17
+ exports.createPolicySignerPort = exports.createLocalSignerPort = exports.initializeDuckDb = exports.DuckDbAnalyticsStore = exports.DisabledAnalyticsStore = exports.createHostMethods = exports.GoRoutingProvider = exports.InProcessRoutingProvider = exports.createTotemNodeAdapter = exports.OperationStore = exports.SqliteChannelStore = exports.loadHostIdentity = exports.createHostManifest = exports.createHostIdentityAndManifest = exports.encryptSeedForKeyfile = exports.leaseStorageDir = exports.JsonFileStorageAdapter = exports.hasSigningMaterial = exports.createHostSigning = exports.createOmniaHost = exports.loadConfigFromEnv = void 0;
4
18
  var config_js_1 = require("./config.js");
5
19
  Object.defineProperty(exports, "loadConfigFromEnv", { enumerable: true, get: function () { return config_js_1.loadConfigFromEnv; } });
6
20
  var lifecycle_js_1 = require("./lifecycle.js");
@@ -31,3 +45,8 @@ var analytics_js_1 = require("./stores/analytics.js");
31
45
  Object.defineProperty(exports, "DisabledAnalyticsStore", { enumerable: true, get: function () { return analytics_js_1.DisabledAnalyticsStore; } });
32
46
  Object.defineProperty(exports, "DuckDbAnalyticsStore", { enumerable: true, get: function () { return analytics_js_1.DuckDbAnalyticsStore; } });
33
47
  Object.defineProperty(exports, "initializeDuckDb", { enumerable: true, get: function () { return analytics_js_1.initializeDuckDb; } });
48
+ var signer_port_js_1 = require("./signer-port.js");
49
+ Object.defineProperty(exports, "createLocalSignerPort", { enumerable: true, get: function () { return signer_port_js_1.createLocalSignerPort; } });
50
+ Object.defineProperty(exports, "createPolicySignerPort", { enumerable: true, get: function () { return signer_port_js_1.createPolicySignerPort; } });
51
+ // Durable, replayable observation feed (RFC-0011 Amendment A).
52
+ __exportStar(require("./observe/index.js"), exports);
@@ -1,4 +1,6 @@
1
1
  import type { OmniaHostConfig } from './config.js';
2
+ import { ObservationBus } from './observe/bus.js';
3
+ import type { ObservationStore } from './observe/types.js';
2
4
  import type { OmniaSwarm, ChannelSigner, WotsLeaseProviderLike, MinimalChainProvider } from '@totemsdk/omnia';
3
5
  import { createOmniaSwarm } from '@totemsdk/omnia';
4
6
  import { OperationStore } from './stores/operations.js';
@@ -7,6 +9,7 @@ import { type ControlServer } from './api/jsonrpc.js';
7
9
  import { type TotemNodeAdapter } from './chain/totem-node-adapter.js';
8
10
  import { type RoutingProvider } from './router/routing-provider.js';
9
11
  import type { JsonRpcHandler } from './api/jsonrpc.js';
12
+ import { type HubNetwork } from '@totemsdk/p2p-hub';
10
13
  import { type OperationStoreLike } from './api/methods.js';
11
14
  import type { ChannelFactory, WotsLeaseBundle } from '@totemsdk/omnia-factory';
12
15
  import type { SpliceAcceptance, SpliceLeaseProvider, SpliceProposal } from '@totemsdk/omnia-splice';
@@ -17,6 +20,8 @@ export interface OmniaHostDependencies {
17
20
  operationStore?: OperationStore | Pick<OperationStore, 'close'>;
18
21
  signer?: ChannelSigner;
19
22
  leaseProvider?: WotsLeaseProviderLike;
23
+ /** RFC-058 signer port; defaults to a local signer in CLI deployments. */
24
+ signerPort?: import('@totemsdk/omnia').SignerPort;
20
25
  chainProvider?: MinimalChainProvider;
21
26
  controlServer?: ControlServer;
22
27
  chainAdapter?: TotemNodeAdapter;
@@ -24,6 +29,13 @@ export interface OmniaHostDependencies {
24
29
  methods?: Map<string, JsonRpcHandler>;
25
30
  operationStoreForApi?: OperationStoreLike;
26
31
  localParticipant?: import('@totemsdk/omnia').ChannelParticipant;
32
+ /** Stable ed25519 native transport keypair (derived from the host seed). */
33
+ transportKeyPair?: {
34
+ publicKey: Uint8Array;
35
+ secretKey: Uint8Array;
36
+ };
37
+ /** `0x`-prefixed transport public key published in the signed manifest. */
38
+ transportPubkey?: string;
27
39
  factories?: Map<string, ChannelFactory>;
28
40
  factoryBundles?: Record<string, WotsLeaseBundle>;
29
41
  spliceProposals?: Map<string, SpliceProposal>;
@@ -38,6 +50,14 @@ export interface OmniaHostDependencies {
38
50
  };
39
51
  /** Boot-time signed EdgeServiceManifest (getManifest). */
40
52
  manifest?: unknown;
53
+ /** Optional P2P hub network (tests/embedding). */
54
+ p2pHubNetwork?: HubNetwork;
55
+ /** Observation feed: inject a store/bus (tests/embedding) or disable it. */
56
+ observationStore?: ObservationStore;
57
+ observationBus?: ObservationBus;
58
+ observe?: boolean;
59
+ networkId?: string;
60
+ sourceNodeId?: string;
41
61
  }
42
62
  export interface OmniaHost {
43
63
  readonly config: OmniaHostConfig;
@@ -46,6 +66,8 @@ export interface OmniaHost {
46
66
  isStarted(): boolean;
47
67
  readonly swarm?: OmniaSwarm;
48
68
  readonly channels?: Map<string, OmniaChannel>;
69
+ /** Loopback WebSocket endpoint for local dapps, when enabled (RFC-062). */
70
+ readonly p2pHubUrl?: string;
49
71
  }
50
72
  /**
51
73
  * Phase-1 lifecycle shell. Subsystems will be attached in later phases while