MCPcopy Create free account
hub / github.com/Eversmile12/sharedcontext / initExistingCommand

Function initExistingCommand

src/cli/init.ts:128–200  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

126 * Derives the wallet, queries Arweave for shards, and reconstructs local state.
127 */
128export async function initExistingCommand(): Promise<void> {
129 if (existsSync(DB_PATH)) {
130 console.log("SharedContext is already initialized at ~/.sharedcontext/");
131 console.log("To reinitialize, delete ~/.sharedcontext/ first.");
132 return;
133 }
134
135 console.log(BANNER);
136 console.log("Restore SharedContext from recovery phrase.\n");
137
138 const input = await prompt(`Enter your ${PHRASE_WORD_COUNT}-word recovery phrase: `);
139 const words = input.split(/\s+/).map((w) => w.toLowerCase());
140
141 const validation = validatePhrase(words);
142 if (!validation.valid) {
143 console.error(`Invalid phrase: ${validation.error}`);
144 process.exit(1);
145 }
146
147 const phrase = phraseToString(words);
148
149 // Derive deterministic identity from phrase
150 console.log("Deriving identity...");
151 const keypair = deriveKeypairFromPhrase(phrase);
152 console.log(`Wallet: ${keypair.address}`);
153
154 mkdirSync(SHAREDCONTEXT_DIR, { recursive: true });
155
156 console.log("\nQuerying Arweave and reconstructing local state...");
157
158 try {
159 const result = await pullAndReconstruct(keypair.address, phrase, DB_PATH);
160
161 // Persist identity material locally so normal CLI flows work after restore.
162 const identity = await fetchIdentity(keypair.address);
163 if (!identity) {
164 throw new Error(
165 "Recovery failed: identity transaction not found on Arweave."
166 );
167 }
168 writeFileSync(SALT_PATH, Buffer.from(identity.salt), { mode: 0o600 });
169 writeFileSync(IDENTITY_PATH, identity.encryptedPrivateKey, { mode: 0o600 });
170
171 // Sanity check: recovered encrypted key must decrypt to phrase-derived identity key.
172 const key = deriveKey(phrase, identity.salt);
173 const recoveredPrivateKey = decrypt(identity.encryptedPrivateKey, key);
174 if (Buffer.compare(Buffer.from(recoveredPrivateKey), Buffer.from(keypair.privateKey)) !== 0) {
175 throw new Error(
176 "Recovered identity does not match the provided recovery phrase."
177 );
178 }
179
180 console.log(`Recovered ${result.factCount} fact(s), version ${result.version}.`);
181 } catch (err) {
182 const { rmSync } = await import("fs");
183 rmSync(SHAREDCONTEXT_DIR, { recursive: true, force: true });
184 throw err;
185 }

Callers 1

index.tsFile · 0.85

Calls 11

promptFunction · 0.85
validatePhraseFunction · 0.85
phraseToStringFunction · 0.85
deriveKeypairFromPhraseFunction · 0.85
pullAndReconstructFunction · 0.85
fetchIdentityFunction · 0.85
deriveKeyFunction · 0.85
decryptFunction · 0.85
keychainStoreFunction · 0.85
toErrorMessageFunction · 0.85
printAutoSetupSummaryFunction · 0.85

Tested by

no test coverage detected