@toon-protocol/townhouse 0.8.0 → 0.10.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.
@@ -0,0 +1,39 @@
1
+ import { createRequire } from 'module'; const require = createRequire(import.meta.url);
2
+
3
+ // src/constants.ts
4
+ var CONTAINER_PREFIX = "townhouse-";
5
+ var NODE_BTP_PORT = 3e3;
6
+ var DEFAULT_CONNECTOR_IMAGE = (
7
+ // v3.9.0 — wires Solana + Mina settlement end-to-end (toon-protocol/connector#86).
8
+ // Adds non-EVM key resolution (chainProviders[].keyId as a raw base58 private
9
+ // key, or SOLANA_PRIVATE_KEY / MINA_PRIVATE_KEY env), bootstrap registration of
10
+ // Solana/Mina payment-channel providers, and the non-EVM branch in the
11
+ // settlement executor. EVM settlement is unchanged. Builds on 3.8.1's dual-party
12
+ // Mina claim path (#84) and 3.8.0's libsql migration (#79) + relation-aware
13
+ // inbound claim validation (#78). No breaking changes to the SDK/admin contract
14
+ // within 3.x (verified >=3.3.2 through 3.9.0 — see packages/sdk/CONNECTOR_MIGRATION.md).
15
+ // Digest resolved via `docker buildx imagetools inspect` for tag 3.9.0. To bump:
16
+ // see CONNECTOR_RELEASE_CONTRACT.md.
17
+ "ghcr.io/toon-protocol/connector@sha256:673a49e30a5b9ae3968fe7ef5ca99b6ceca21bb69996bda68cd18ec335b874fe"
18
+ );
19
+ var ACCOUNT_INDEX_TOWN = 0;
20
+ var ACCOUNT_INDEX_MILL = 1;
21
+ var ACCOUNT_INDEX_DVM = 2;
22
+ var ACCOUNT_INDEX_APEX = 3;
23
+ var TOWN_HEALTH_PORT = 3100;
24
+ var MILL_HEALTH_PORT = 3200;
25
+ var DVM_HEALTH_PORT = 3400;
26
+
27
+ export {
28
+ CONTAINER_PREFIX,
29
+ NODE_BTP_PORT,
30
+ DEFAULT_CONNECTOR_IMAGE,
31
+ ACCOUNT_INDEX_TOWN,
32
+ ACCOUNT_INDEX_MILL,
33
+ ACCOUNT_INDEX_DVM,
34
+ ACCOUNT_INDEX_APEX,
35
+ TOWN_HEALTH_PORT,
36
+ MILL_HEALTH_PORT,
37
+ DVM_HEALTH_PORT
38
+ };
39
+ //# sourceMappingURL=chunk-BLNEL3QS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/constants.ts"],"sourcesContent":["/**\n * Shared constants for Townhouse package.\n *\n * Single source of truth for values used across multiple modules\n * (orchestrator, config-generator, CLI).\n */\n\n/** Container name prefix for all Townhouse-managed Docker containers */\nexport const CONTAINER_PREFIX = 'townhouse-';\n\n/** Internal BTP port exposed by node containers (Docker-internal only) */\nexport const NODE_BTP_PORT = 3000;\n\n/**\n * Default connector Docker image — digest-pinned per CONNECTOR_RELEASE_CONTRACT.md.\n *\n * To bump: capture a new digest by running the Story 45.1 publish workflow\n * against the desired connector tag, copy the resulting image-manifest.json\n * connector entry's digest, and update this constant + the contract canary\n * fixture. See packages/sdk/CONNECTOR_RELEASE_CONTRACT.md for the full bump\n * checklist + breaking-changes history.\n *\n * To read the human-readable tag for log output, consult dist/image-manifest.json:\n * manifest.images.connector.tag\n */\nexport const DEFAULT_CONNECTOR_IMAGE =\n // v3.9.0 — wires Solana + Mina settlement end-to-end (toon-protocol/connector#86).\n // Adds non-EVM key resolution (chainProviders[].keyId as a raw base58 private\n // key, or SOLANA_PRIVATE_KEY / MINA_PRIVATE_KEY env), bootstrap registration of\n // Solana/Mina payment-channel providers, and the non-EVM branch in the\n // settlement executor. EVM settlement is unchanged. Builds on 3.8.1's dual-party\n // Mina claim path (#84) and 3.8.0's libsql migration (#79) + relation-aware\n // inbound claim validation (#78). No breaking changes to the SDK/admin contract\n // within 3.x (verified >=3.3.2 through 3.9.0 — see packages/sdk/CONNECTOR_MIGRATION.md).\n // Digest resolved via `docker buildx imagetools inspect` for tag 3.9.0. To bump:\n // see CONNECTOR_RELEASE_CONTRACT.md.\n 'ghcr.io/toon-protocol/connector@sha256:673a49e30a5b9ae3968fe7ef5ca99b6ceca21bb69996bda68cd18ec335b874fe';\n\n/**\n * HD wallet account indices per node type (Story 21.4, D21-008).\n * BIP-44 paths: m/44'/{coin}'/ACCOUNT'/0/0\n */\nexport const ACCOUNT_INDEX_TOWN = 0;\nexport const ACCOUNT_INDEX_MILL = 1;\nexport const ACCOUNT_INDEX_DVM = 2;\n/**\n * Apex (connector) settlement account. The apex is the parent connector\n * (`g.townhouse`) that signs settlement claims; its key is derived from the\n * operator mnemonic at this index so the operator never has to supply a raw\n * settlement key. Index 3 continues the town/mill/dvm sequence (and matches the\n * dev convention where the apex is Anvil account[3], 0x90F79bf6…).\n */\nexport const ACCOUNT_INDEX_APEX = 3;\n\n/** BLS health port exposed by each node container type (internal Docker port). */\nexport const TOWN_HEALTH_PORT = 3100;\nexport const MILL_HEALTH_PORT = 3200;\nexport const DVM_HEALTH_PORT = 3400;\n"],"mappings":";;;AAQO,IAAM,mBAAmB;AAGzB,IAAM,gBAAgB;AActB,IAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWX;AAAA;AAMK,IAAM,qBAAqB;AAC3B,IAAM,qBAAqB;AAC3B,IAAM,oBAAoB;AAQ1B,IAAM,qBAAqB;AAG3B,IAAM,mBAAmB;AACzB,IAAM,mBAAmB;AACzB,IAAM,kBAAkB;","names":[]}
@@ -35,7 +35,7 @@ import {
35
35
  MILL_HEALTH_PORT,
36
36
  NODE_BTP_PORT,
37
37
  TOWN_HEALTH_PORT
38
- } from "./chunk-RCHQDZBZ.js";
38
+ } from "./chunk-BLNEL3QS.js";
39
39
  import {
40
40
  __commonJS,
41
41
  __require,
@@ -14187,6 +14187,56 @@ var HDKey = class _HDKey {
14187
14187
 
14188
14188
  // ../core/dist/index.js
14189
14189
  import { getPublicKey as getPublicKey5 } from "nostr-tools/pure";
14190
+ function hexToBytes3(hex) {
14191
+ const clean3 = hex.startsWith("0x") ? hex.slice(2) : hex;
14192
+ if (clean3.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(clean3)) {
14193
+ throw new Error(`Invalid hex string: ${hex}`);
14194
+ }
14195
+ return hexToBytes2(clean3);
14196
+ }
14197
+ function concatBytes3(...parts) {
14198
+ let len = 0;
14199
+ for (const p of parts) len += p.length;
14200
+ const out = new Uint8Array(len);
14201
+ let o = 0;
14202
+ for (const p of parts) {
14203
+ out.set(p, o);
14204
+ o += p.length;
14205
+ }
14206
+ return out;
14207
+ }
14208
+ var BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
14209
+ function base58Encode(bytes) {
14210
+ let zeros = 0;
14211
+ for (let i = 0; i < bytes.length && bytes[i] === 0; i++) zeros++;
14212
+ let value = 0n;
14213
+ for (const byte of bytes) {
14214
+ value = value * 256n + BigInt(byte);
14215
+ }
14216
+ let result = "";
14217
+ while (value > 0n) {
14218
+ result = BASE58_ALPHABET[Number(value % 58n)] + result;
14219
+ value = value / 58n;
14220
+ }
14221
+ for (let i = 0; i < zeros; i++) {
14222
+ result = "1" + result;
14223
+ }
14224
+ return result || "1";
14225
+ }
14226
+ var MINA_PRIVATE_KEY_VERSION = 90;
14227
+ function hexToMinaBase58PrivateKey(privateKey) {
14228
+ if (!/^(0x)?[0-9a-fA-F]{64}$/.test(privateKey)) {
14229
+ return privateKey;
14230
+ }
14231
+ const beScalar = hexToBytes3(privateKey);
14232
+ const leScalar = Uint8Array.from(beScalar).reverse();
14233
+ const payload = concatBytes3(
14234
+ Uint8Array.from([MINA_PRIVATE_KEY_VERSION, 1]),
14235
+ leScalar
14236
+ );
14237
+ const checksum2 = sha2562(sha2562(payload)).slice(0, 4);
14238
+ return base58Encode(concatBytes3(payload, checksum2));
14239
+ }
14190
14240
  var ILP_TO_SEMANTIC = Object.freeze({
14191
14241
  T00: "internal_error",
14192
14242
  T04: "insufficient_funds",
@@ -14505,13 +14555,25 @@ function writeHsConnectorConfig(configDir, config, options = {}) {
14505
14555
  }
14506
14556
  }
14507
14557
  const apexEvmKey = options.apexSettlementKeys?.evmPrivateKeyHex;
14558
+ const apexSolanaKey = options.apexSettlementKeys?.solanaPrivateKeyBase58;
14559
+ const apexMinaKey = options.apexSettlementKeys?.minaPrivateKeyBase58;
14508
14560
  const derived = resolveConfigNetworkProfile(
14509
14561
  config,
14510
14562
  apexEvmKey ?? DEFAULT_HS_CHAIN_PROVIDERS[0]?.keyId
14511
14563
  ).chainProviders;
14512
- const fillApexKey = (providers) => providers.map(
14513
- (p) => !p.keyId && p.chainType === "evm" && apexEvmKey ? { ...p, keyId: apexEvmKey } : p
14514
- );
14564
+ const fillApexKey = (providers) => providers.map((p) => {
14565
+ if (p.keyId) return p;
14566
+ if (p.chainType === "evm" && apexEvmKey) {
14567
+ return { ...p, keyId: apexEvmKey };
14568
+ }
14569
+ if (p.chainType === "solana" && apexSolanaKey) {
14570
+ return { ...p, keyId: apexSolanaKey };
14571
+ }
14572
+ if (p.chainType === "mina" && apexMinaKey) {
14573
+ return { ...p, keyId: apexMinaKey };
14574
+ }
14575
+ return p;
14576
+ });
14515
14577
  const hsConfig = derived.length > 0 ? { ...config, chainProviders: fillApexKey(derived) } : { ...config, chainProviders: [...DEFAULT_HS_CHAIN_PROVIDERS] };
14516
14578
  const generator = new ConnectorConfigGenerator(hsConfig);
14517
14579
  const baseConfig = generator.generate([]);
@@ -18076,15 +18138,15 @@ function deriveSolana(seed, accountIndex) {
18076
18138
  }
18077
18139
 
18078
18140
  // src/wallet/manager.ts
18079
- var BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
18080
- function base58Encode(bytes) {
18141
+ var BASE58_ALPHABET2 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
18142
+ function base58Encode2(bytes) {
18081
18143
  let zeros = 0;
18082
18144
  for (let i = 0; i < bytes.length && bytes[i] === 0; i++) zeros++;
18083
18145
  let value = 0n;
18084
18146
  for (const byte of bytes) value = value * 256n + BigInt(byte);
18085
18147
  let result = "";
18086
18148
  while (value > 0n) {
18087
- result = BASE58_ALPHABET[Number(value % 58n)] + result;
18149
+ result = BASE58_ALPHABET2[Number(value % 58n)] + result;
18088
18150
  value = value / 58n;
18089
18151
  }
18090
18152
  for (let i = 0; i < zeros; i++) result = "1" + result;
@@ -18237,7 +18299,7 @@ var WalletManager = class {
18237
18299
  accountIndex: derivationIndex
18238
18300
  });
18239
18301
  if (chainKeys.solana) {
18240
- solanaAddress = base58Encode(chainKeys.solana.publicKey);
18302
+ solanaAddress = base58Encode2(chainKeys.solana.publicKey);
18241
18303
  solanaPrivateKey = chainKeys.solana.privateKey;
18242
18304
  solanaDerivationPath = chainKeys.solana.path;
18243
18305
  }
@@ -18279,29 +18341,66 @@ var WalletManager = class {
18279
18341
  *
18280
18342
  * Returns the EVM private key as a `0x`-prefixed 64-char hex string — the
18281
18343
  * form the connector config's `keyId` expects (matches the dev placeholder
18282
- * `0x7c85…`). Throws when the wallet is locked. Structured as an object so
18283
- * Solana/Mina apex keys can be added in a later phase.
18344
+ * `0x7c85…`). Also returns Solana + Mina settlement keys (connector 3.9.0)
18345
+ * derived at the same `ACCOUNT_INDEX_APEX`, in the RAW base58 form the
18346
+ * connector resolves a non-EVM `keyId` as:
18347
+ * - Solana: base58 of the 32-byte Ed25519 seed,
18348
+ * - Mina: `EK…` base58check (via `hexToMinaBase58PrivateKey`).
18349
+ *
18350
+ * EVM derivation must always succeed (it throws on failure). Solana/Mina
18351
+ * derivation is best-effort: if `deriveMillKeys` throws (unsupported
18352
+ * platform, library load error) the corresponding key is OMITTED rather than
18353
+ * failing the whole method, so the EVM keyId path is never blocked.
18354
+ *
18355
+ * Async because `deriveMillKeys` is async. Throws when the wallet is locked.
18284
18356
  */
18285
- getApexSettlementKeys() {
18357
+ async getApexSettlementKeys() {
18286
18358
  if (!this.state) {
18287
18359
  throw new Error(
18288
18360
  "Wallet not initialized. Call generate() or fromMnemonic() first."
18289
18361
  );
18290
18362
  }
18363
+ const mnemonic = this.state.mnemonic;
18291
18364
  let seed;
18365
+ let evmPrivateKeyHex;
18292
18366
  try {
18293
- seed = mnemonicToSeedSync(this.state.mnemonic);
18367
+ seed = mnemonicToSeedSync(mnemonic);
18294
18368
  const path = `m/44'/60'/${ACCOUNT_INDEX_APEX}'/0/0`;
18295
18369
  const hd = HDKey.fromMasterSeed(seed).derive(path);
18296
18370
  if (!hd.privateKey) {
18297
18371
  throw new Error(`Apex EVM private key missing at ${path}`);
18298
18372
  }
18299
- return {
18300
- evmPrivateKeyHex: `0x${bytesToHex(new Uint8Array(hd.privateKey))}`
18301
- };
18373
+ evmPrivateKeyHex = `0x${bytesToHex(new Uint8Array(hd.privateKey))}`;
18302
18374
  } finally {
18303
18375
  if (seed) seed.fill(0);
18304
18376
  }
18377
+ let solanaPrivateKeyBase58;
18378
+ let minaPrivateKeyBase58;
18379
+ try {
18380
+ const chainKeys = await deriveMillKeys({
18381
+ mnemonic,
18382
+ chains: ["solana", "mina"],
18383
+ accountIndex: ACCOUNT_INDEX_APEX
18384
+ });
18385
+ if (chainKeys.solana) {
18386
+ solanaPrivateKeyBase58 = base58Encode(chainKeys.solana.privateKey);
18387
+ }
18388
+ if (chainKeys.mina) {
18389
+ minaPrivateKeyBase58 = hexToMinaBase58PrivateKey(
18390
+ chainKeys.mina.privateKey
18391
+ );
18392
+ }
18393
+ } catch (err) {
18394
+ const errMsg = err instanceof Error ? err.message : String(err);
18395
+ console.warn(
18396
+ `[WalletManager] deriveMillKeys failed for apex (accountIndex=${ACCOUNT_INDEX_APEX}): ${errMsg} \u2014 Solana/Mina apex keys omitted`
18397
+ );
18398
+ }
18399
+ return {
18400
+ evmPrivateKeyHex,
18401
+ ...solanaPrivateKeyBase58 ? { solanaPrivateKeyBase58 } : {},
18402
+ ...minaPrivateKeyBase58 ? { minaPrivateKeyBase58 } : {}
18403
+ };
18305
18404
  }
18306
18405
  /**
18307
18406
  * Returns the Solana Ed25519 private key seed for a node as a 64-char
@@ -18447,7 +18546,7 @@ var WalletManager = class {
18447
18546
  accountIndex
18448
18547
  });
18449
18548
  if (chainKeys.solana) {
18450
- chainExtras[nodeType].solanaAddress = base58Encode(
18549
+ chainExtras[nodeType].solanaAddress = base58Encode2(
18451
18550
  chainKeys.solana.publicKey
18452
18551
  );
18453
18552
  chainExtras[nodeType].solanaPrivateKey = chainKeys.solana.privateKey;
@@ -22904,4 +23003,4 @@ export {
22904
23003
  @scure/bip32/index.js:
22905
23004
  (*! scure-bip32 - MIT License (c) 2022 Patricio Palladino, Paul Miller (paulmillr.com) *)
22906
23005
  */
22907
- //# sourceMappingURL=chunk-BDT2FIQL.js.map
23006
+ //# sourceMappingURL=chunk-UBFITLPQ.js.map