@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.
- package/CHANGELOG.md +16 -0
- package/README.md +16 -9
- package/config/signer-policies/README.md +10 -1
- package/config/signer-protocol-v2.json +2 -0
- package/dist/brand.js +1 -1
- package/dist/build-info.json +3 -3
- package/dist/canvas-host/a2ui/.bundle.hash +1 -1
- package/dist/control-ui/assets/{app-bR-fO5ty.js → app-MaQnPa5G.js} +5 -5
- package/dist/control-ui/assets/{index-ckCxHwjy.js → index-D4YMr1fA.js} +3 -3
- package/dist/control-ui/assets/{mining-BgHFh0ei.js → mining-qMYs4aD-.js} +120 -120
- package/dist/control-ui/index.html +1 -1
- package/dist/control-ui/version.json +1 -1
- package/dist/extensions/sat-mining/src/rpc-read.js +59 -20
- package/dist/extensions/sat-mining/src/solana-submit.js +251 -8
- package/dist/extensions/sat-mining/src/submission-ledger.js +1 -1
- package/dist/plugin-sdk/{audio-preflight-BYxAt775.js → audio-preflight-I4IngVlJ.js} +1 -1
- package/dist/plugin-sdk/channel-plugin-common.d.ts +2 -2
- package/dist/plugin-sdk/{chunk-items-DIRHG2gJ.js → chunk-items-DLQ6_lLK.js} +1 -1
- package/dist/plugin-sdk/command-status.js +1 -1
- package/dist/plugin-sdk/{config-schema-BOT7kHb6.js → config-schema-D_8FVI1C.js} +28 -8
- package/dist/plugin-sdk/device-pair.d.ts +1 -1
- package/dist/plugin-sdk/discord.d.ts +3 -3
- package/dist/plugin-sdk/index.d.ts +5 -5
- package/dist/plugin-sdk/index.js +1 -1
- package/dist/plugin-sdk/{monitor-BCFDaqJ-.js → monitor-B4KF4Kpo.js} +3 -3
- package/dist/plugin-sdk/{monitor-BgbjRiPM.js → monitor-Bb6x1KAG.js} +3 -3
- package/dist/plugin-sdk/{openresponses-http-DFf87SMM.js → openresponses-http-DCTO8JkL.js} +1 -1
- package/dist/plugin-sdk/{pairing-message-CS-9BHug.d.ts → pairing-message-DHPDFZbC.d.ts} +1 -1
- package/dist/plugin-sdk/provider-web-search-config-contract.d.ts +1 -1
- package/dist/plugin-sdk/sat-runtime.d.ts +18 -2
- package/dist/plugin-sdk/sat-runtime.js +1 -1
- package/dist/plugin-sdk/{slack-BUTt8cxK.js → slack-BHmvqgjH.js} +3 -3
- package/dist/plugin-sdk/slack.d.ts +3 -3
- package/dist/plugin-sdk/{sticker-cache-D0wHVqjt.js → sticker-cache-By5AcorL.js} +2 -2
- package/dist/plugin-sdk/{telegram-actions-CC_qN4v0.js → telegram-actions-DGnBz1YT.js} +2 -2
- package/dist/plugin-sdk/telegram.d.ts +3 -3
- package/dist/plugin-sdk/{tmp-fased-dir-xOTGlzBE.d.ts → tmp-fased-dir-EJGTmL1Q.d.ts} +1 -1
- package/dist/plugin-sdk/{types-C3avNytw.d.ts → types-BdwdFCD6.d.ts} +2 -2
- package/dist/plugin-sdk/{types-DWfbSAaM.d.ts → types-BrCpYMxn.d.ts} +1 -1
- package/dist/plugin-sdk/{web-BXsJ1vqe.js → web-DUJwrTYs.js} +1 -1
- package/dist/plugin-sdk/whatsapp.d.ts +3 -3
- package/dist/wallet/local-socket-signer-protocol.js +18 -0
- package/dist/wallet/signer-protocol-v2.generated.js +2 -0
- package/dist/wallet/wallet-policy.js +3 -1
- package/extensions/acpx/package.json +1 -1
- package/extensions/bluebubbles/package.json +1 -1
- package/extensions/copilot-proxy/package.json +1 -1
- package/extensions/diagnostics-otel/package.json +1 -1
- package/extensions/fased-federation/package.json +1 -1
- package/extensions/google-gemini-cli-auth/package.json +1 -1
- package/extensions/imessage/package.json +1 -1
- package/extensions/irc/package.json +1 -1
- package/extensions/line/package.json +1 -1
- package/extensions/llm-task/package.json +1 -1
- package/extensions/lobster/package.json +1 -1
- package/extensions/matrix/CHANGELOG.md +6 -0
- package/extensions/matrix/package.json +1 -1
- package/extensions/mattermost/package.json +1 -1
- package/extensions/memory-core/package.json +2 -2
- package/extensions/memory-lancedb/package.json +1 -1
- package/extensions/minimax-portal-auth/package.json +1 -1
- package/extensions/msteams/CHANGELOG.md +6 -0
- package/extensions/msteams/package.json +1 -1
- package/extensions/nextcloud-talk/package.json +1 -1
- package/extensions/nostr/CHANGELOG.md +6 -0
- package/extensions/nostr/package.json +1 -1
- package/extensions/open-prose/package.json +1 -1
- package/extensions/sat-mining/index.ts +89 -1
- package/extensions/sat-mining/package.json +1 -1
- package/extensions/sat-mining/src/audit-store.ts +45 -4
- package/extensions/sat-mining/src/client.ts +13 -0
- package/extensions/sat-mining/src/rpc-read.ts +105 -21
- package/extensions/sat-mining/src/runtime.ts +2 -0
- package/extensions/sat-mining/src/solana-submit.ts +358 -21
- package/extensions/sat-mining/src/submission-ledger.ts +2 -1
- package/extensions/signal/package.json +1 -1
- package/extensions/synology-chat/package.json +1 -1
- package/extensions/tlon/package.json +1 -1
- package/extensions/twitch/CHANGELOG.md +6 -0
- package/extensions/twitch/package.json +1 -1
- package/extensions/voice-call/CHANGELOG.md +6 -0
- package/extensions/voice-call/package.json +1 -1
- package/extensions/zalo/CHANGELOG.md +6 -0
- package/extensions/zalo/package.json +1 -1
- package/extensions/zalouser/CHANGELOG.md +6 -0
- package/extensions/zalouser/package.json +1 -1
- package/install.sh +14 -18
- package/package.json +1 -1
- package/scripts/fased-managed-updater.mjs +1 -1
- package/scripts/fased-signer-owner-policy.mjs +13 -1
- 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
|
-
|
|
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
|
|
526
|
-
const
|
|
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 =
|
|
574
|
+
const intent = isLookupTable
|
|
529
575
|
? (() => {
|
|
530
|
-
if (
|
|
531
|
-
throw new Error("typed
|
|
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.
|
|
535
|
-
|
|
536
|
-
|
|
582
|
+
type: "solana.satLookupTable" as const,
|
|
583
|
+
action,
|
|
584
|
+
lookupTable: params.lookupTable,
|
|
537
585
|
};
|
|
538
586
|
})()
|
|
539
|
-
:
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
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
|
|
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: {
|
|
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
|
|