@fased/fased 0.1.64 → 0.1.65

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.
Files changed (91) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +16 -9
  3. package/config/signer-policies/README.md +10 -1
  4. package/config/signer-protocol-v2.json +2 -0
  5. package/dist/brand.js +1 -1
  6. package/dist/build-info.json +3 -3
  7. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  8. package/dist/control-ui/assets/{app-bR-fO5ty.js → app-MaQnPa5G.js} +5 -5
  9. package/dist/control-ui/assets/{index-ckCxHwjy.js → index-D4YMr1fA.js} +3 -3
  10. package/dist/control-ui/assets/{mining-BgHFh0ei.js → mining-qMYs4aD-.js} +120 -120
  11. package/dist/control-ui/index.html +1 -1
  12. package/dist/control-ui/version.json +1 -1
  13. package/dist/extensions/sat-mining/src/rpc-read.js +59 -20
  14. package/dist/extensions/sat-mining/src/solana-submit.js +251 -8
  15. package/dist/extensions/sat-mining/src/submission-ledger.js +1 -1
  16. package/dist/plugin-sdk/{audio-preflight-BYxAt775.js → audio-preflight-I4IngVlJ.js} +1 -1
  17. package/dist/plugin-sdk/channel-plugin-common.d.ts +2 -2
  18. package/dist/plugin-sdk/{chunk-items-DIRHG2gJ.js → chunk-items-DLQ6_lLK.js} +1 -1
  19. package/dist/plugin-sdk/command-status.js +1 -1
  20. package/dist/plugin-sdk/{config-schema-BOT7kHb6.js → config-schema-D_8FVI1C.js} +28 -8
  21. package/dist/plugin-sdk/device-pair.d.ts +1 -1
  22. package/dist/plugin-sdk/discord.d.ts +3 -3
  23. package/dist/plugin-sdk/index.d.ts +5 -5
  24. package/dist/plugin-sdk/index.js +1 -1
  25. package/dist/plugin-sdk/{monitor-BCFDaqJ-.js → monitor-B4KF4Kpo.js} +3 -3
  26. package/dist/plugin-sdk/{monitor-BgbjRiPM.js → monitor-Bb6x1KAG.js} +3 -3
  27. package/dist/plugin-sdk/{openresponses-http-DFf87SMM.js → openresponses-http-DCTO8JkL.js} +1 -1
  28. package/dist/plugin-sdk/{pairing-message-CS-9BHug.d.ts → pairing-message-DHPDFZbC.d.ts} +1 -1
  29. package/dist/plugin-sdk/provider-web-search-config-contract.d.ts +1 -1
  30. package/dist/plugin-sdk/sat-runtime.d.ts +18 -2
  31. package/dist/plugin-sdk/sat-runtime.js +1 -1
  32. package/dist/plugin-sdk/{slack-BUTt8cxK.js → slack-BHmvqgjH.js} +3 -3
  33. package/dist/plugin-sdk/slack.d.ts +3 -3
  34. package/dist/plugin-sdk/{sticker-cache-D0wHVqjt.js → sticker-cache-By5AcorL.js} +2 -2
  35. package/dist/plugin-sdk/{telegram-actions-CC_qN4v0.js → telegram-actions-DGnBz1YT.js} +2 -2
  36. package/dist/plugin-sdk/telegram.d.ts +3 -3
  37. package/dist/plugin-sdk/{tmp-fased-dir-xOTGlzBE.d.ts → tmp-fased-dir-EJGTmL1Q.d.ts} +1 -1
  38. package/dist/plugin-sdk/{types-C3avNytw.d.ts → types-BdwdFCD6.d.ts} +2 -2
  39. package/dist/plugin-sdk/{types-DWfbSAaM.d.ts → types-BrCpYMxn.d.ts} +1 -1
  40. package/dist/plugin-sdk/{web-BXsJ1vqe.js → web-DUJwrTYs.js} +1 -1
  41. package/dist/plugin-sdk/whatsapp.d.ts +3 -3
  42. package/dist/wallet/local-socket-signer-protocol.js +18 -0
  43. package/dist/wallet/signer-protocol-v2.generated.js +2 -0
  44. package/dist/wallet/wallet-policy.js +3 -1
  45. package/extensions/acpx/package.json +1 -1
  46. package/extensions/bluebubbles/package.json +1 -1
  47. package/extensions/copilot-proxy/package.json +1 -1
  48. package/extensions/diagnostics-otel/package.json +1 -1
  49. package/extensions/fased-federation/package.json +1 -1
  50. package/extensions/google-gemini-cli-auth/package.json +1 -1
  51. package/extensions/imessage/package.json +1 -1
  52. package/extensions/irc/package.json +1 -1
  53. package/extensions/line/package.json +1 -1
  54. package/extensions/llm-task/package.json +1 -1
  55. package/extensions/lobster/package.json +1 -1
  56. package/extensions/matrix/CHANGELOG.md +6 -0
  57. package/extensions/matrix/package.json +1 -1
  58. package/extensions/mattermost/package.json +1 -1
  59. package/extensions/memory-core/package.json +2 -2
  60. package/extensions/memory-lancedb/package.json +1 -1
  61. package/extensions/minimax-portal-auth/package.json +1 -1
  62. package/extensions/msteams/CHANGELOG.md +6 -0
  63. package/extensions/msteams/package.json +1 -1
  64. package/extensions/nextcloud-talk/package.json +1 -1
  65. package/extensions/nostr/CHANGELOG.md +6 -0
  66. package/extensions/nostr/package.json +1 -1
  67. package/extensions/open-prose/package.json +1 -1
  68. package/extensions/sat-mining/index.ts +89 -1
  69. package/extensions/sat-mining/package.json +1 -1
  70. package/extensions/sat-mining/src/audit-store.ts +45 -4
  71. package/extensions/sat-mining/src/client.ts +13 -0
  72. package/extensions/sat-mining/src/rpc-read.ts +105 -21
  73. package/extensions/sat-mining/src/runtime.ts +2 -0
  74. package/extensions/sat-mining/src/solana-submit.ts +358 -21
  75. package/extensions/sat-mining/src/submission-ledger.ts +2 -1
  76. package/extensions/signal/package.json +1 -1
  77. package/extensions/synology-chat/package.json +1 -1
  78. package/extensions/tlon/package.json +1 -1
  79. package/extensions/twitch/CHANGELOG.md +6 -0
  80. package/extensions/twitch/package.json +1 -1
  81. package/extensions/voice-call/CHANGELOG.md +6 -0
  82. package/extensions/voice-call/package.json +1 -1
  83. package/extensions/zalo/CHANGELOG.md +6 -0
  84. package/extensions/zalo/package.json +1 -1
  85. package/extensions/zalouser/CHANGELOG.md +6 -0
  86. package/extensions/zalouser/package.json +1 -1
  87. package/install.sh +14 -18
  88. package/package.json +1 -1
  89. package/scripts/fased-managed-updater.mjs +1 -1
  90. package/scripts/fased-signer-owner-policy.mjs +13 -1
  91. package/scripts/start-managed.sh +4 -0
@@ -27,6 +27,8 @@ import {
27
27
  SAT_PROTOCOL_CONSTANTS,
28
28
  } from "./protocol-contract.js";
29
29
  import {
30
+ inspectSatAddressLookupTable,
31
+ inspectSatChainSlot,
30
32
  inspectSatCycle,
31
33
  inspectSatCycleRegistryMeta,
32
34
  inspectSatMinerCyclesByAddress,
@@ -74,6 +76,8 @@ const MINING_STAKE_SEED = "mining_stake";
74
76
  const TOKEN_PROGRAM_ID = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
75
77
  const ASSOCIATED_TOKEN_PROGRAM_ID = "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL";
76
78
  const SLOT_HASHES_SYSVAR_ID = "SysvarS1otHashes111111111111111111111111111";
79
+ const SAT_DISTRIBUTION_LOOKUP_MIN_MINERS = 16;
80
+ const SAT_LOOKUP_TABLE_EXTEND_CHUNK_SIZE = 20;
77
81
 
78
82
  const IX = SAT_INSTRUCTION_DISCRIMINATORS;
79
83
 
@@ -324,12 +328,27 @@ export async function resolveSatValidatorAuthority(_config: SatMiningConfig) {
324
328
  type SatInstructionSubmitSpec = {
325
329
  data: Buffer;
326
330
  programId?: string;
331
+ addressLookupTables?: string[];
332
+ manageAddressLookupTable?: { lookupTableAddress?: string };
327
333
  accountResolver: (
328
334
  solana: SolanaModuleLike,
329
335
  signer: import("@solana/web3.js").PublicKey,
330
336
  ) => Promise<SolanaAccountMeta[] | SatResolvedInstruction>;
331
337
  };
332
338
 
339
+ type SatInstructionSubmitResult = {
340
+ txHash: string;
341
+ signer: string;
342
+ signerState: SatSignerOperation["state"];
343
+ requestId: string;
344
+ transactionVersion: "legacy" | "v0";
345
+ lookupTableAddress?: string;
346
+ lookupTableCreated?: boolean;
347
+ lookupTableExtended?: boolean;
348
+ lookupTableAddressCount?: number;
349
+ lookupTableTransactionHashes?: string[];
350
+ };
351
+
333
352
  async function prepareLocalSignerSubmitContext(cfg: FasedAgentConfig, env: NodeJS.ProcessEnv) {
334
353
  const effectiveEnv = resolveSatEffectiveEnv(cfg, env);
335
354
  const solana = await loadSolanaWeb3();
@@ -375,6 +394,9 @@ async function buildLocalSignerInstructionRequest(params: {
375
394
  isSigner: key.isSigner,
376
395
  isWritable: key.isWritable,
377
396
  })),
397
+ ...(params.spec.addressLookupTables?.length
398
+ ? { addressLookupTables: params.spec.addressLookupTables }
399
+ : {}),
378
400
  ...(context ? { context } : {}),
379
401
  };
380
402
  }
@@ -399,7 +421,7 @@ const REQUIRED_SAT_SIGNER_FEATURES = [
399
421
 
400
422
  async function requireTypedSatSignerCapabilities(
401
423
  socketPath: string,
402
- intentType: "solana.satAction" | "solana.vaultBondAction",
424
+ intentType: "solana.satAction" | "solana.satLookupTable" | "solana.vaultBondAction",
403
425
  ) {
404
426
  const result = await callLocalSocketSigner<{
405
427
  ready?: boolean;
@@ -428,6 +450,10 @@ async function requireTypedSatSignerCapabilities(
428
450
  "durableReviewAuthorization",
429
451
  ].filter((feature) => !features.has(feature))
430
452
  : [];
453
+ const missingLookupFeatures =
454
+ intentType === "solana.satLookupTable" && !features.has("typedSATAddressLookupTables")
455
+ ? ["typedSATAddressLookupTables"]
456
+ : [];
431
457
  if (
432
458
  result.ready !== true ||
433
459
  protocol?.current !== 2 ||
@@ -437,6 +463,7 @@ async function requireTypedSatSignerCapabilities(
437
463
  protocol.max < 2 ||
438
464
  !capabilities?.intentTypes?.includes(intentType) ||
439
465
  missingFeatures.length > 0 ||
466
+ missingLookupFeatures.length > 0 ||
440
467
  (intentType === "solana.vaultBondAction" && !features.has("typedVaultBondActions")) ||
441
468
  missingVaultReviewFeatures.length > 0 ||
442
469
  missingStates.length > 0
@@ -445,8 +472,10 @@ async function requireTypedSatSignerCapabilities(
445
472
  `local-socket-signer does not support the required typed SAT protocol-v2 contract${
446
473
  missingFeatures.length > 0 ? `; missing features: ${missingFeatures.join(", ")}` : ""
447
474
  }${missingVaultReviewFeatures.length > 0 ? `; missing reviewed Vault features: ${missingVaultReviewFeatures.join(", ")}` : ""}${
448
- missingStates.length > 0 ? `; missing states: ${missingStates.join(", ")}` : ""
449
- }`,
475
+ missingLookupFeatures.length > 0
476
+ ? `; missing SAT lookup features: ${missingLookupFeatures.join(", ")}`
477
+ : ""
478
+ }${missingStates.length > 0 ? `; missing states: ${missingStates.join(", ")}` : ""}`,
450
479
  );
451
480
  }
452
481
  }
@@ -495,6 +524,14 @@ function signerStateForLedger(state: SatSignerOperation["state"]): SatSubmission
495
524
  return state;
496
525
  }
497
526
 
527
+ type SatLookupTableAction = "create" | "extend" | "deactivate" | "close";
528
+
529
+ function assertSatLookupTableAction(value: string): asserts value is SatLookupTableAction {
530
+ if (value !== "create" && value !== "extend" && value !== "deactivate" && value !== "close") {
531
+ throw new Error(`unsupported SAT lookup-table action ${value}`);
532
+ }
533
+ }
534
+
498
535
  class SatSubmissionUnresolvedError extends Error {
499
536
  readonly requestId: string;
500
537
  readonly signature?: string;
@@ -516,32 +553,54 @@ class SatSubmissionUnresolvedError extends Error {
516
553
  async function executeTypedSatIntent(params: {
517
554
  socketPath: string;
518
555
  walletId: string;
519
- action: SatSignerAction | "cleanupBatch";
556
+ action: SatSignerAction | "cleanupBatch" | "create" | "extend" | "deactivate" | "close";
520
557
  instruction?: Awaited<ReturnType<typeof buildLocalSignerInstructionRequest>>;
521
558
  instructions?: Array<Awaited<ReturnType<typeof buildLocalSignerInstructionRequest>>>;
559
+ lookupTable?: { address: string; recentSlot?: string; addresses?: string[] };
522
560
  cluster: "local" | "devnet" | "mainnet-beta";
523
561
  env: NodeJS.ProcessEnv;
524
562
  }) {
525
- const isVaultBond = params.action !== "cleanupBatch" && VAULT_BOND_ACTIONS.has(params.action);
526
- const intentType = isVaultBond ? "solana.vaultBondAction" : "solana.satAction";
563
+ const isLookupTable = params.lookupTable != null;
564
+ const isVaultBond =
565
+ !isLookupTable &&
566
+ params.action !== "cleanupBatch" &&
567
+ VAULT_BOND_ACTIONS.has(params.action as SatSignerAction);
568
+ const intentType = isLookupTable
569
+ ? "solana.satLookupTable"
570
+ : isVaultBond
571
+ ? "solana.vaultBondAction"
572
+ : "solana.satAction";
527
573
  await requireTypedSatSignerCapabilities(params.socketPath, intentType);
528
- const intent = isVaultBond
574
+ const intent = isLookupTable
529
575
  ? (() => {
530
- if (!params.instruction || params.instructions) {
531
- throw new Error("typed Vault bond execution requires exactly one semantic instruction");
576
+ if (params.instruction || params.instructions || !params.lookupTable) {
577
+ throw new Error("typed SAT lookup-table execution accepts only semantic lookup details");
532
578
  }
579
+ const action = params.action;
580
+ assertSatLookupTableAction(action);
533
581
  return {
534
- type: "solana.vaultBondAction" as const,
535
- cluster: params.cluster,
536
- ...params.instruction,
582
+ type: "solana.satLookupTable" as const,
583
+ action,
584
+ lookupTable: params.lookupTable,
537
585
  };
538
586
  })()
539
- : {
540
- type: "solana.satAction" as const,
541
- action: params.action,
542
- ...(params.instruction ?? {}),
543
- ...(params.instructions ? { instructions: params.instructions } : {}),
544
- };
587
+ : isVaultBond
588
+ ? (() => {
589
+ if (!params.instruction || params.instructions) {
590
+ throw new Error("typed Vault bond execution requires exactly one semantic instruction");
591
+ }
592
+ return {
593
+ type: "solana.vaultBondAction" as const,
594
+ cluster: params.cluster,
595
+ ...params.instruction,
596
+ };
597
+ })()
598
+ : {
599
+ type: "solana.satAction" as const,
600
+ action: params.action,
601
+ ...(params.instruction ?? {}),
602
+ ...(params.instructions ? { instructions: params.instructions } : {}),
603
+ };
545
604
  const policy = await callLocalSocketSigner<{ hash: string }>(params.socketPath, {
546
605
  op: "v2.policy.get",
547
606
  walletId: params.walletId,
@@ -854,14 +913,218 @@ async function executeTypedSatIntent(params: {
854
913
  return { ...operation, signature: operation.signature };
855
914
  }
856
915
 
916
+ type SatLookupSubmitContext = Awaited<ReturnType<typeof prepareLocalSignerSubmitContext>> & {
917
+ walletId: string;
918
+ };
919
+
920
+ function assertSatLookupTableEnabled(env: NodeJS.ProcessEnv): void {
921
+ if (String(env.FASED_SAT_ENABLE_ALT_V0 ?? "").trim() !== "1") {
922
+ throw new Error("SAT ALT/v0 support is disabled; set FASED_SAT_ENABLE_ALT_V0=1");
923
+ }
924
+ }
925
+
926
+ async function executeTypedSatLookupOperation(params: {
927
+ context: SatLookupSubmitContext;
928
+ cfg: FasedAgentConfig;
929
+ action: "create" | "extend" | "deactivate" | "close";
930
+ address: string;
931
+ recentSlot?: number;
932
+ addresses?: string[];
933
+ }) {
934
+ return await executeTypedSatIntent({
935
+ socketPath: params.context.socketPath,
936
+ walletId: params.context.walletId,
937
+ action: params.action,
938
+ lookupTable: {
939
+ address: params.address,
940
+ ...(params.recentSlot == null ? {} : { recentSlot: String(params.recentSlot) }),
941
+ ...(params.addresses?.length ? { addresses: params.addresses } : {}),
942
+ },
943
+ cluster: resolveSatCluster(params.cfg),
944
+ env: params.context.effectiveEnv,
945
+ });
946
+ }
947
+
948
+ async function readValidatedSatLookupTable(params: {
949
+ config: SatMiningConfig;
950
+ address: string;
951
+ authority: string;
952
+ }) {
953
+ const state = await inspectSatAddressLookupTable(params.config, { address: params.address });
954
+ if (!state) {
955
+ return null;
956
+ }
957
+ if (state.authority !== params.authority) {
958
+ throw new Error("SAT distribution lookup table is not controlled by the Mining signer");
959
+ }
960
+ if (!state.active) {
961
+ throw new Error("SAT distribution lookup table is not active");
962
+ }
963
+ return state;
964
+ }
965
+
966
+ async function waitForSatLookupTable(params: {
967
+ config: SatMiningConfig;
968
+ address: string;
969
+ authority: string;
970
+ requireNextSlot: boolean;
971
+ }) {
972
+ let lastError: unknown;
973
+ for (let attempt = 0; attempt < 24; attempt += 1) {
974
+ try {
975
+ const state = await readValidatedSatLookupTable(params);
976
+ if (state) {
977
+ const currentSlot = await inspectSatChainSlot(params.config);
978
+ if (!params.requireNextSlot || currentSlot > state.lastExtendedSlot) {
979
+ return state;
980
+ }
981
+ }
982
+ } catch (error) {
983
+ lastError = error;
984
+ }
985
+ await new Promise((resolve) => setTimeout(resolve, 250));
986
+ }
987
+ throw new Error(
988
+ `SAT distribution lookup table did not become active for use within 6s${
989
+ lastError instanceof Error ? `: ${lastError.message}` : ""
990
+ }`,
991
+ );
992
+ }
993
+
994
+ async function ensureSatDistributionLookupTable(params: {
995
+ context: SatLookupSubmitContext;
996
+ cfg: FasedAgentConfig;
997
+ config: SatMiningConfig;
998
+ lookupTableAddress?: string;
999
+ addresses: string[];
1000
+ }) {
1001
+ assertSatLookupTableEnabled(params.context.effectiveEnv);
1002
+ const desiredAddresses = [...new Set(params.addresses.map((entry) => entry.trim()))].filter(
1003
+ Boolean,
1004
+ );
1005
+ if (desiredAddresses.length === 0 || desiredAddresses.length > 256) {
1006
+ throw new Error("SAT distribution lookup table requires 1-256 exact account addresses");
1007
+ }
1008
+ let lookupTable = params.lookupTableAddress?.trim() ?? "";
1009
+ let state = lookupTable
1010
+ ? await readValidatedSatLookupTable({
1011
+ config: params.config,
1012
+ address: lookupTable,
1013
+ authority: params.context.signerAddress,
1014
+ })
1015
+ : null;
1016
+ let created = false;
1017
+ const transactionHashes: string[] = [];
1018
+ if (!lookupTable) {
1019
+ const currentSlot = await inspectSatChainSlot(params.config);
1020
+ const recentSlot = Math.max(0, currentSlot - 1);
1021
+ const [, derivedAddress] = params.context.solana.AddressLookupTableProgram.createLookupTable({
1022
+ authority: params.context.signer,
1023
+ payer: params.context.signer,
1024
+ recentSlot,
1025
+ });
1026
+ lookupTable = derivedAddress.toBase58();
1027
+ state = await readValidatedSatLookupTable({
1028
+ config: params.config,
1029
+ address: lookupTable,
1030
+ authority: params.context.signerAddress,
1031
+ });
1032
+ if (!state) {
1033
+ try {
1034
+ const submitted = await executeTypedSatLookupOperation({
1035
+ context: params.context,
1036
+ cfg: params.cfg,
1037
+ action: "create",
1038
+ address: lookupTable,
1039
+ recentSlot,
1040
+ });
1041
+ transactionHashes.push(submitted.signature);
1042
+ created = true;
1043
+ } catch (error) {
1044
+ if (error instanceof SatSubmissionUnresolvedError) {
1045
+ throw error;
1046
+ }
1047
+ try {
1048
+ state = await waitForSatLookupTable({
1049
+ config: params.config,
1050
+ address: lookupTable,
1051
+ authority: params.context.signerAddress,
1052
+ requireNextSlot: false,
1053
+ });
1054
+ } catch {
1055
+ throw error;
1056
+ }
1057
+ }
1058
+ state ??= await waitForSatLookupTable({
1059
+ config: params.config,
1060
+ address: lookupTable,
1061
+ authority: params.context.signerAddress,
1062
+ requireNextSlot: false,
1063
+ });
1064
+ }
1065
+ }
1066
+ if (!state) {
1067
+ throw new Error("SAT distribution lookup table was not found at the confirmed commitment");
1068
+ }
1069
+ const existing = new Set(state.addresses);
1070
+ const missing = desiredAddresses.filter((entry) => !existing.has(entry));
1071
+ for (let offset = 0; offset < missing.length; offset += SAT_LOOKUP_TABLE_EXTEND_CHUNK_SIZE) {
1072
+ const addresses = missing.slice(offset, offset + SAT_LOOKUP_TABLE_EXTEND_CHUNK_SIZE);
1073
+ try {
1074
+ const submitted = await executeTypedSatLookupOperation({
1075
+ context: params.context,
1076
+ cfg: params.cfg,
1077
+ action: "extend",
1078
+ address: lookupTable,
1079
+ addresses,
1080
+ });
1081
+ transactionHashes.push(submitted.signature);
1082
+ } catch (error) {
1083
+ if (error instanceof SatSubmissionUnresolvedError) {
1084
+ throw error;
1085
+ }
1086
+ const concurrentState = await waitForSatLookupTable({
1087
+ config: params.config,
1088
+ address: lookupTable,
1089
+ authority: params.context.signerAddress,
1090
+ requireNextSlot: false,
1091
+ }).catch(() => null);
1092
+ if (
1093
+ !concurrentState ||
1094
+ addresses.some((address) => !concurrentState.addresses.includes(address))
1095
+ ) {
1096
+ throw error;
1097
+ }
1098
+ }
1099
+ }
1100
+ const ready = await waitForSatLookupTable({
1101
+ config: params.config,
1102
+ address: lookupTable,
1103
+ authority: params.context.signerAddress,
1104
+ requireNextSlot: true,
1105
+ });
1106
+ for (const address of desiredAddresses) {
1107
+ if (!ready.addresses.includes(address)) {
1108
+ throw new Error(`SAT distribution lookup table did not persist required account ${address}`);
1109
+ }
1110
+ }
1111
+ return {
1112
+ lookupTable,
1113
+ created,
1114
+ extended: missing.length > 0,
1115
+ addressCount: ready.addresses.length,
1116
+ transactionHashes,
1117
+ };
1118
+ }
1119
+
857
1120
  async function submitInstructionViaLocalSigner(
858
1121
  params: {
859
1122
  cfg: FasedAgentConfig;
860
1123
  env: NodeJS.ProcessEnv;
861
1124
  } & SatInstructionSubmitSpec,
862
- ) {
1125
+ ): Promise<SatInstructionSubmitResult> {
863
1126
  const context = await prepareLocalSignerSubmitContext(params.cfg, params.env);
864
- const request = await buildLocalSignerInstructionRequest({
1127
+ const baseRequest = await buildLocalSignerInstructionRequest({
865
1128
  solana: context.solana,
866
1129
  signer: context.signer,
867
1130
  env: context.effectiveEnv,
@@ -870,6 +1133,19 @@ async function submitInstructionViaLocalSigner(
870
1133
  if (!context.walletId) {
871
1134
  throw new Error("typed SAT signing requires an explicit mining walletId");
872
1135
  }
1136
+ let managedLookupTable: Awaited<ReturnType<typeof ensureSatDistributionLookupTable>> | undefined;
1137
+ if (params.manageAddressLookupTable) {
1138
+ managedLookupTable = await ensureSatDistributionLookupTable({
1139
+ context: { ...context, walletId: context.walletId },
1140
+ cfg: params.cfg,
1141
+ config: params.cfg as unknown as SatMiningConfig,
1142
+ lookupTableAddress: params.manageAddressLookupTable.lookupTableAddress,
1143
+ addresses: baseRequest.keys.filter((key) => !key.isSigner).map((key) => key.pubkey),
1144
+ });
1145
+ }
1146
+ const request = managedLookupTable
1147
+ ? { ...baseRequest, addressLookupTables: [managedLookupTable.lookupTable] }
1148
+ : baseRequest;
873
1149
  const submitted = await executeTypedSatIntent({
874
1150
  socketPath: context.socketPath,
875
1151
  walletId: context.walletId,
@@ -883,6 +1159,20 @@ async function submitInstructionViaLocalSigner(
883
1159
  signer: context.signerAddress,
884
1160
  signerState: submitted.state,
885
1161
  requestId: submitted.requestId,
1162
+ ...(request.addressLookupTables?.length
1163
+ ? {
1164
+ transactionVersion: "v0" as const,
1165
+ lookupTableAddress: request.addressLookupTables[0],
1166
+ }
1167
+ : { transactionVersion: "legacy" as const }),
1168
+ ...(managedLookupTable
1169
+ ? {
1170
+ lookupTableCreated: managedLookupTable.created,
1171
+ lookupTableExtended: managedLookupTable.extended,
1172
+ lookupTableAddressCount: managedLookupTable.addressCount,
1173
+ lookupTableTransactionHashes: managedLookupTable.transactionHashes,
1174
+ }
1175
+ : {}),
886
1176
  };
887
1177
  }
888
1178
 
@@ -901,6 +1191,8 @@ async function submitInstruction(
901
1191
  env: effectiveEnv,
902
1192
  data: params.data,
903
1193
  programId: params.programId,
1194
+ addressLookupTables: params.addressLookupTables,
1195
+ manageAddressLookupTable: params.manageAddressLookupTable,
904
1196
  accountResolver: params.accountResolver,
905
1197
  });
906
1198
  }
@@ -2702,13 +2994,29 @@ export async function submitSatScoreCyclePage(
2702
2994
 
2703
2995
  export async function submitSatDistributeCyclePage(
2704
2996
  _config: SatMiningConfig,
2705
- params: { cycleId: number; pageIndex: number; chunkIndex: number; minerCycleAccounts?: string[] },
2997
+ params: {
2998
+ cycleId: number;
2999
+ pageIndex: number;
3000
+ chunkIndex: number;
3001
+ minerCycleAccounts?: string[];
3002
+ lookupTableAddress?: string;
3003
+ },
2706
3004
  ) {
2707
3005
  const cfg = loadConfigForSatRuntime(_config);
3006
+ const lookupTableAddress = params.lookupTableAddress?.trim() ?? "";
3007
+ const requiresLookupTable =
3008
+ (params.minerCycleAccounts?.length ?? 0) >= SAT_DISTRIBUTION_LOOKUP_MIN_MINERS;
2708
3009
  return submitInstruction({
2709
3010
  cfg,
2710
3011
  env: process.env,
2711
3012
  data: buildDistributeCyclePageData(params),
3013
+ ...(lookupTableAddress || requiresLookupTable
3014
+ ? {
3015
+ manageAddressLookupTable: {
3016
+ ...(lookupTableAddress ? { lookupTableAddress } : {}),
3017
+ },
3018
+ }
3019
+ : {}),
2712
3020
  accountResolver: async (solana, signer) => {
2713
3021
  const programId = new solana.PublicKey(SAT_PROGRAM_ID());
2714
3022
  const [satCycleState] = solana.PublicKey.findProgramAddressSync(
@@ -2798,6 +3106,35 @@ export async function submitSatDistributeCyclePage(
2798
3106
  });
2799
3107
  }
2800
3108
 
3109
+ export async function submitSatCleanupDistributionLookupTable(
3110
+ _config: SatMiningConfig,
3111
+ params: { lookupTableAddress: string; action: "deactivate" | "close" },
3112
+ ) {
3113
+ const cfg = loadConfigForSatRuntime(_config);
3114
+ const context = await prepareLocalSignerSubmitContext(cfg, process.env);
3115
+ assertSatLookupTableEnabled(context.effectiveEnv);
3116
+ if (!context.walletId) {
3117
+ throw new Error("typed SAT lookup-table cleanup requires an explicit mining walletId");
3118
+ }
3119
+ const lookupTable = params.lookupTableAddress.trim();
3120
+ if (!lookupTable) {
3121
+ throw new Error("SAT distribution lookup table address is required");
3122
+ }
3123
+ const submitted = await executeTypedSatLookupOperation({
3124
+ context: { ...context, walletId: context.walletId },
3125
+ cfg,
3126
+ action: params.action,
3127
+ address: lookupTable,
3128
+ });
3129
+ return {
3130
+ lookupTable,
3131
+ action: params.action,
3132
+ transactionHashes: [submitted.signature],
3133
+ signerState: submitted.state,
3134
+ requestId: submitted.requestId,
3135
+ };
3136
+ }
3137
+
2801
3138
  export async function submitSatClaimCycleRewards(
2802
3139
  _config: SatMiningConfig,
2803
3140
  params: { cycleId: number },
@@ -113,6 +113,7 @@ export function buildSatSubmissionOperationKey(intent: {
113
113
  action?: unknown;
114
114
  keys?: unknown;
115
115
  instructions?: unknown;
116
+ lookupTable?: unknown;
116
117
  }): string {
117
118
  const action =
118
119
  typeof intent.action === "string" && intent.action.trim() ? intent.action.trim() : "sat";
@@ -121,7 +122,7 @@ export function buildSatSubmissionOperationKey(intent: {
121
122
  const candidate = instruction as { action?: unknown; keys?: unknown };
122
123
  return { action: candidate.action, keys: candidate.keys };
123
124
  })
124
- : intent.keys;
125
+ : (intent.keys ?? intent.lookupTable);
125
126
  return `${action}:${sha256(JSON.stringify(canonicalize(accountShape))).slice(0, 24)}`;
126
127
  }
127
128
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fased/signal",
3
- "version": "0.1.64",
3
+ "version": "0.1.65",
4
4
  "private": true,
5
5
  "description": "FasedAgent Signal channel plugin",
6
6
  "type": "module",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fased/synology-chat",
3
- "version": "0.1.64",
3
+ "version": "0.1.65",
4
4
  "description": "Synology Chat channel plugin for FasedAgent",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fased/tlon",
3
- "version": "0.1.64",
3
+ "version": "0.1.65",
4
4
  "description": "FasedAgent Tlon/Urbit channel plugin",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.65
4
+
5
+ ### Changes
6
+
7
+ - Version alignment with core FasedAgent release numbers.
8
+
3
9
  ## 0.1.64
4
10
 
5
11
  ### Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fased/twitch",
3
- "version": "0.1.64",
3
+ "version": "0.1.65",
4
4
  "description": "FasedAgent Twitch channel plugin",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.65
4
+
5
+ ### Changes
6
+
7
+ - Version alignment with core FasedAgent release numbers.
8
+
3
9
  ## 0.1.64
4
10
 
5
11
  ### Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fased/voice-call",
3
- "version": "0.1.64",
3
+ "version": "0.1.65",
4
4
  "description": "FasedAgent voice-call plugin",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.65
4
+
5
+ ### Changes
6
+
7
+ - Version alignment with core FasedAgent release numbers.
8
+
3
9
  ## 0.1.64
4
10
 
5
11
  ### Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fased/zalo",
3
- "version": "0.1.64",
3
+ "version": "0.1.65",
4
4
  "description": "FasedAgent Zalo channel plugin",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.65
4
+
5
+ ### Changes
6
+
7
+ - Version alignment with core FasedAgent release numbers.
8
+
3
9
  ## 0.1.64
4
10
 
5
11
  ### Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fased/zalouser",
3
- "version": "0.1.64",
3
+ "version": "0.1.65",
4
4
  "description": "FasedAgent Zalo Personal Account plugin via zca-cli",
5
5
  "type": "module",
6
6
  "dependencies": {