@@ -290,7 +290,7 @@ const DIRECT_COMMANDS = {
290290 const hasWallet = fs . existsSync ( path . join ( BLOCKRUN_DIR , 'wallet.json' ) )
291291 || fs . existsSync ( path . join ( BLOCKRUN_DIR , 'solana-wallet.json' ) ) ;
292292 checks . push ( hasWallet ? '✓ wallet configured' : '⚠ no wallet — run: runcode setup' ) ;
293- checks . push ( fs . existsSync ( path . join ( BLOCKRUN_DIR , 'runcode-config.json' ) ) ? '✓ config file exists' : '⚠ no config — using defaults' ) ;
293+ checks . push ( fs . existsSync ( path . join ( BLOCKRUN_DIR , 'franklin-config.json' ) ) || fs . existsSync ( path . join ( BLOCKRUN_DIR , ' runcode-config.json') ) ? '✓ config file exists' : '⚠ no config — using defaults' ) ;
294294 // Check MCP
295295 const { listMcpServers } = await import ( '../mcp/client.js' ) ;
296296 const mcpServers = listMcpServers ( ) ;
@@ -398,49 +398,6 @@ const DIRECT_COMMANDS = {
398398 ctx . onEvent ( { kind : 'text_delta' , text } ) ;
399399 emitDone ( ctx ) ;
400400 } ,
401- '/wallet' : async ( ctx ) => {
402- const chain = ( await import ( '../config.js' ) ) . loadChain ( ) ;
403- try {
404- let address ;
405- let balance ;
406- const fetchTimeout = ( ms ) => new Promise ( ( _ , rej ) => setTimeout ( ( ) => rej ( new Error ( 'timeout' ) ) , ms ) ) ;
407- if ( chain === 'solana' ) {
408- const { getOrCreateSolanaWallet, setupAgentSolanaWallet } = await import ( '@blockrun/llm' ) ;
409- const w = await getOrCreateSolanaWallet ( ) ;
410- address = w . address ;
411- try {
412- const client = await setupAgentSolanaWallet ( { silent : true } ) ;
413- const bal = await Promise . race ( [ client . getBalance ( ) , fetchTimeout ( 5000 ) ] ) ;
414- balance = `$${ bal . toFixed ( 2 ) } USDC` ;
415- }
416- catch {
417- balance = '(unavailable)' ;
418- }
419- }
420- else {
421- const { getOrCreateWallet, setupAgentWallet } = await import ( '@blockrun/llm' ) ;
422- const w = getOrCreateWallet ( ) ;
423- address = w . address ;
424- try {
425- const client = setupAgentWallet ( { silent : true } ) ;
426- const bal = await Promise . race ( [ client . getBalance ( ) , fetchTimeout ( 5000 ) ] ) ;
427- balance = `$${ bal . toFixed ( 2 ) } USDC` ;
428- }
429- catch {
430- balance = '(unavailable)' ;
431- }
432- }
433- ctx . onEvent ( { kind : 'text_delta' , text : `**Wallet**\n` +
434- ` Chain: ${ chain } \n` +
435- ` Address: ${ address } \n` +
436- ` Balance: ${ balance } \n`
437- } ) ;
438- }
439- catch ( err ) {
440- ctx . onEvent ( { kind : 'text_delta' , text : `Wallet error: ${ err . message } \n` } ) ;
441- }
442- emitDone ( ctx ) ;
443- } ,
444401 '/clear' : ( ctx ) => {
445402 ctx . history . length = 0 ;
446403 resetTokenAnchor ( ) ;
@@ -693,6 +650,135 @@ export async function handleSlashCommand(input, ctx) {
693650 emitDone ( ctx ) ;
694651 return { handled : true } ;
695652 }
653+ // /wallet — show wallet info, import, or export
654+ if ( input === '/wallet' || input . startsWith ( '/wallet ' ) ) {
655+ const chain = ( await import ( '../config.js' ) ) . loadChain ( ) ;
656+ const args = input . slice ( 7 ) . trim ( ) ;
657+ // /wallet export — show private key
658+ if ( args === 'export' ) {
659+ try {
660+ if ( chain === 'solana' ) {
661+ const { loadSolanaWallet, getOrCreateSolanaWallet } = await import ( '@blockrun/llm' ) ;
662+ const key = loadSolanaWallet ( ) ;
663+ if ( ! key ) {
664+ ctx . onEvent ( { kind : 'text_delta' , text : 'No Solana wallet found. Run `/wallet` first.\n' } ) ;
665+ emitDone ( ctx ) ;
666+ return { handled : true } ;
667+ }
668+ const w = await getOrCreateSolanaWallet ( ) ;
669+ ctx . onEvent ( { kind : 'text_delta' , text : `**Wallet Export (Solana)**\n` +
670+ ` Address: ${ w . address } \n` +
671+ ` Private Key: ${ key } \n\n` +
672+ `⚠️ Keep this key safe. Anyone with it controls your funds.\n`
673+ } ) ;
674+ }
675+ else {
676+ const { loadWallet, getOrCreateWallet } = await import ( '@blockrun/llm' ) ;
677+ const key = loadWallet ( ) ;
678+ if ( ! key ) {
679+ ctx . onEvent ( { kind : 'text_delta' , text : 'No wallet found. Run `/wallet` first.\n' } ) ;
680+ emitDone ( ctx ) ;
681+ return { handled : true } ;
682+ }
683+ const w = getOrCreateWallet ( ) ;
684+ ctx . onEvent ( { kind : 'text_delta' , text : `**Wallet Export (Base)**\n` +
685+ ` Address: ${ w . address } \n` +
686+ ` Private Key: ${ key } \n\n` +
687+ `⚠️ Keep this key safe. Anyone with it controls your funds.\n`
688+ } ) ;
689+ }
690+ }
691+ catch ( err ) {
692+ ctx . onEvent ( { kind : 'text_delta' , text : `Export error: ${ err . message } \n` } ) ;
693+ }
694+ emitDone ( ctx ) ;
695+ return { handled : true } ;
696+ }
697+ // /wallet import <private-key>
698+ if ( args . startsWith ( 'import' ) ) {
699+ const key = args . slice ( 6 ) . trim ( ) ;
700+ if ( ! key ) {
701+ ctx . onEvent ( { kind : 'text_delta' , text : `**Usage:** \`/wallet import <private-key>\`\n\n` +
702+ ` Base: \`/wallet import 0x...\` (hex, 66 chars)\n` +
703+ ` Solana: \`/wallet import <bs58-key>\` (base58 encoded)\n`
704+ } ) ;
705+ emitDone ( ctx ) ;
706+ return { handled : true } ;
707+ }
708+ try {
709+ if ( chain === 'solana' ) {
710+ const { saveSolanaWallet, solanaPublicKey } = await import ( '@blockrun/llm' ) ;
711+ const address = await solanaPublicKey ( key ) ;
712+ saveSolanaWallet ( key ) ;
713+ ctx . onEvent ( { kind : 'text_delta' , text : `**Wallet Imported (Solana)**\n` +
714+ ` Address: ${ address } \n` +
715+ ` Saved to: ~/.blockrun/\n\n` +
716+ `Restart Franklin to use the new wallet.\n`
717+ } ) ;
718+ }
719+ else {
720+ const { privateKeyToAccount } = await import ( 'viem/accounts' ) ;
721+ const { saveWallet } = await import ( '@blockrun/llm' ) ;
722+ const account = privateKeyToAccount ( key ) ;
723+ saveWallet ( key ) ;
724+ ctx . onEvent ( { kind : 'text_delta' , text : `**Wallet Imported (Base)**\n` +
725+ ` Address: ${ account . address } \n` +
726+ ` Saved to: ~/.blockrun/\n\n` +
727+ `Restart Franklin to use the new wallet.\n`
728+ } ) ;
729+ }
730+ }
731+ catch ( err ) {
732+ ctx . onEvent ( { kind : 'text_delta' , text : `Import error: ${ err . message } \n` } ) ;
733+ }
734+ emitDone ( ctx ) ;
735+ return { handled : true } ;
736+ }
737+ // /wallet (no args) — show wallet info
738+ try {
739+ let address ;
740+ let balance ;
741+ const fetchTimeout = ( ms ) => new Promise ( ( _ , rej ) => setTimeout ( ( ) => rej ( new Error ( 'timeout' ) ) , ms ) ) ;
742+ if ( chain === 'solana' ) {
743+ const { getOrCreateSolanaWallet, setupAgentSolanaWallet } = await import ( '@blockrun/llm' ) ;
744+ const w = await getOrCreateSolanaWallet ( ) ;
745+ address = w . address ;
746+ try {
747+ const client = await setupAgentSolanaWallet ( { silent : true } ) ;
748+ const bal = await Promise . race ( [ client . getBalance ( ) , fetchTimeout ( 5000 ) ] ) ;
749+ balance = `$${ bal . toFixed ( 2 ) } USDC` ;
750+ }
751+ catch {
752+ balance = '(unavailable)' ;
753+ }
754+ }
755+ else {
756+ const { getOrCreateWallet, setupAgentWallet } = await import ( '@blockrun/llm' ) ;
757+ const w = getOrCreateWallet ( ) ;
758+ address = w . address ;
759+ try {
760+ const client = setupAgentWallet ( { silent : true } ) ;
761+ const bal = await Promise . race ( [ client . getBalance ( ) , fetchTimeout ( 5000 ) ] ) ;
762+ balance = `$${ bal . toFixed ( 2 ) } USDC` ;
763+ }
764+ catch {
765+ balance = '(unavailable)' ;
766+ }
767+ }
768+ ctx . onEvent ( { kind : 'text_delta' , text : `**Wallet**\n` +
769+ ` Chain: ${ chain } \n` +
770+ ` Address: ${ address } \n` +
771+ ` Balance: ${ balance } \n\n` +
772+ ` \`/wallet import <key>\` — import a personal wallet\n` +
773+ ` \`/wallet export\` — show private key\n`
774+ } ) ;
775+ }
776+ catch ( err ) {
777+ ctx . onEvent ( { kind : 'text_delta' , text : `Wallet error: ${ err . message } \n` } ) ;
778+ }
779+ emitDone ( ctx ) ;
780+ return { handled : true } ;
781+ }
696782 // /delete <...>
697783 if ( input . startsWith ( '/delete ' ) ) {
698784 const arg = input . slice ( '/delete ' . length ) . trim ( ) ;
0 commit comments