core: export says which kind of secret, so other kinds can follow

/_wallet export name <k> rather than an index straight after export. The
bare form stays the seed mnemonic, and a profile's key can be added beside
the name one without the argument having to be guessed from its shape.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX
This commit is contained in:
Alain BrenzikoferandClaude Opus 5 committed 2026-09-14 08:09:04 +00:00
1 parent 8fcfd87b6b
commit ba673f95bf
5 files changed
+9 -9

No files matched your search

+1 -1
View File
@@ -453,7 +453,7 @@ undocumentedCommands =
"APIWallet",
"APIWalletCreate",
"APIWalletDelete",
"APIWalletExportDerivedSecret",
"APIWalletExportNameSecret",
"APIWalletExportSeedMnemonic",
"CheckChatRunning",
"ConfirmRemoteCtrl",
+1 -1
View File
@@ -70,7 +70,7 @@ Internal API. The names commands will call these; users will not.
/_wallet create new generate the seed, 24 words
/_wallet create mnemonic=<phrase> take the entropy from a mnemonic
/_wallet export the seed mnemonic
/_wallet export <k> one name key's secret, 0x and 64 hex digits
/_wallet export name <k> one name key's secret, 0x and 64 hex digits
/_wallet delete delete the seed
```
+2 -2
View File
@@ -420,7 +420,7 @@ data ChatCommand
| APIWallet
| APIWalletCreate {recoveryPhrase :: Maybe Text}
| APIWalletExportSeedMnemonic
| APIWalletExportDerivedSecret {nameIndex :: NameIndex}
| APIWalletExportNameSecret {nameIndex :: NameIndex}
| APIWalletDelete
| APISendCallInvitation ContactId CallType
| SendCallInvitation ContactName CallType
@@ -750,7 +750,7 @@ allowRemoteCommand = \case
APIWallet -> False
APIWalletCreate {} -> False
APIWalletExportSeedMnemonic -> False
APIWalletExportDerivedSecret {} -> False
APIWalletExportNameSecret {} -> False
APIWalletDelete -> False
_ -> True
+2 -2
View File
@@ -1509,7 +1509,7 @@ processChatCommand cxt nm = \case
seed <- deviceSeed
phrase <- either throwCmdError pure $ recoveryKeyPhrase seed
pure $ CRWalletSeedMnemonic user (safeDecodeUtf8 phrase)
APIWalletExportDerivedSecret nameIdx -> withUser $ \user -> do
APIWalletExportNameSecret nameIdx -> withUser $ \user -> do
seed <- deviceSeed
k <- either throwCmdError pure $ seedMaster seed >>= \m -> deriveNameKey m nameIdx
pure $ CRWalletDerivedSecret user (renderNameKeyPath nameIdx) (decodeLatin1 . strEncode $ addressFromPrivateKey k) (safeDecodeUtf8 $ nameKeySecret k)
@@ -5585,7 +5585,7 @@ chatCommandP =
"/_service_response " *> (APISendServiceResponse <$> A.decimal <* A.space <*> strP <* A.space <*> jsonP),
"/_wallet create new" $> APIWalletCreate Nothing,
"/_wallet create mnemonic=" *> (APIWalletCreate . Just <$> textP),
"/_wallet export " *> (APIWalletExportDerivedSecret <$> keyIndexP),
"/_wallet export name " *> (APIWalletExportNameSecret <$> keyIndexP),
"/_wallet export" $> APIWalletExportSeedMnemonic,
"/_wallet delete" $> APIWalletDelete,
"/_wallet" $> APIWallet,
+3 -3
View File
@@ -124,13 +124,13 @@ testWalletExportDerivedSecret :: HasCallStack => TestParams -> IO ()
testWalletExportDerivedSecret ps = withNewTestChat ps "alice" aliceProfile $ \alice -> do
alice ##> ("/_wallet create mnemonic=" <> B.unpack testPhrase)
_ <- nameRows alice
alice ##> "/_wallet export 1"
alice ##> "/_wallet export name 1"
alice <## "m/44'/60'/0'/0/1 0x6Fac4D18c912343BF86fa7049364Dd4E424Ab9C0 0x9a983cb3d832fbde5ab49d692b7a8bf5b5d232479c99333d0fc8e1d21f1b55b6"
-- a secret whose first byte is zero keeps its 64 hex digits
alice ##> "/_wallet export 15"
alice ##> "/_wallet export name 15"
alice <## "m/44'/60'/0'/0/15 0xa25d37554EB084969C85362f7E6B1A6108e51d0e 0x009a1ccd9c667416d9db6246a35d022b1799517c0cd8547bb07ce280c119ae3c"
-- an index BIP-32 cannot reach is rejected, not wrapped into another key
alice ##> "/_wallet export 4294967296"
alice ##> "/_wallet export name 4294967296"
alice <## "bad chat command: Failed reading: empty"
testWalletDelete :: HasCallStack => TestParams -> IO ()