22// Copyright © 2026 TON Core
33
44import * as path from "node:path"
5+ import * as fs from "node:fs"
56
67import { URI } from "vscode-uri"
78
8- import { readFileVFS , globalVFS , existsVFS } from "@server/vfs/files-adapter"
9-
109export interface WalletInfo {
1110 readonly name : string
1211 readonly isLocal : boolean
@@ -15,12 +14,17 @@ export interface WalletInfo {
1514export class ActonToml {
1615 public constructor ( private readonly uri : string ) { }
1716
18- private async readContent ( uri : string ) : Promise < string | undefined > {
19- return readFileVFS ( globalVFS , uri )
17+ private readContent ( uri : string ) : string | undefined {
18+ try {
19+ const fsPath = URI . parse ( uri ) . fsPath
20+ return fs . readFileSync ( fsPath , "utf8" )
21+ } catch {
22+ return undefined
23+ }
2024 }
2125
22- public async getContractIds ( ) : Promise < string [ ] > {
23- const content = await this . readContent ( this . uri )
26+ public getContractIds ( ) : string [ ] {
27+ const content = this . readContent ( this . uri )
2428 if ( ! content ) return [ ]
2529
2630 const contractIds : string [ ] = [ ]
@@ -36,38 +40,59 @@ export class ActonToml {
3640 return contractIds
3741 }
3842
39- public async getWallets ( ) : Promise < WalletInfo [ ] > {
43+ public getMappings ( ) : Map < string , string > {
44+ const content = this . readContent ( this . uri )
45+ if ( ! content ) return new Map ( )
46+
47+ const mappings : Map < string , string > = new Map ( )
48+ // Simple manual parsing for [mappings] table
49+ const lines = content . split ( "\n" )
50+ let inMappings = false
51+ for ( const line of lines ) {
52+ const trimmed = line . trim ( )
53+ if ( trimmed === "[mappings]" ) {
54+ inMappings = true
55+ continue
56+ }
57+ if ( trimmed . startsWith ( "[" ) && trimmed !== "[mappings]" ) {
58+ inMappings = false
59+ continue
60+ }
61+ if ( inMappings && trimmed . includes ( "=" ) ) {
62+ const [ rawKey , rawValue ] = trimmed . split ( "=" ) . map ( s => s . trim ( ) )
63+ if ( rawKey && rawValue ) {
64+ // remove quotes from key and then @ prefix
65+ const cleanKey = rawKey . replace ( / ^ [ " ' ] | [ " ' ] $ / g, "" )
66+ const key = cleanKey . startsWith ( "@" ) ? cleanKey . slice ( 1 ) : cleanKey
67+ // remove quotes from value
68+ const cleanValue = rawValue . replace ( / ^ [ " ' ] | [ " ' ] $ / g, "" )
69+ mappings . set ( key , cleanValue )
70+ }
71+ }
72+ }
73+ return mappings
74+ }
75+
76+ public get workingDir ( ) : string {
77+ return path . dirname ( URI . parse ( this . uri ) . fsPath )
78+ }
79+
80+ public getWallets ( ) : WalletInfo [ ] {
4081 const wallets : WalletInfo [ ] = [ ]
4182
4283 const baseUri = URI . parse ( this . uri )
4384 const dirPath = path . dirname ( baseUri . fsPath )
4485
4586 const walletsTomlUri = URI . file ( path . join ( dirPath , "wallets.toml" ) ) . toString ( )
46- const walletsContent = await this . readContent ( walletsTomlUri )
87+ const walletsContent = this . readContent ( walletsTomlUri )
4788 if ( walletsContent ) {
48- // Match [wallets.NAME] where NAME does not contain a dot
49- const walletRegex = / ^ \[ w a l l e t s \. ( [ ^ \s . \] ] + ) ] / gm
50- let match : RegExpExecArray | null
51- while ( ( match = walletRegex . exec ( walletsContent ) ) !== null ) {
52- const name = match [ 1 ]
53- if ( name ) {
54- wallets . push ( { name, isLocal : true } )
55- }
56- }
89+ wallets . push ( ...this . parseWallets ( walletsContent , true ) )
5790 }
5891
5992 const globalWalletsTomlUri = URI . file ( path . join ( dirPath , "global.wallets.toml" ) ) . toString ( )
60- const globalWalletsContent = await this . readContent ( globalWalletsTomlUri )
93+ const globalWalletsContent = this . readContent ( globalWalletsTomlUri )
6194 if ( globalWalletsContent ) {
62- // Match [wallets.NAME] where NAME does not contain a dot
63- const walletRegex = / ^ \[ w a l l e t s \. ( [ ^ \s . \] ] + ) ] / gm
64- let match : RegExpExecArray | null
65- while ( ( match = walletRegex . exec ( globalWalletsContent ) ) !== null ) {
66- const name = match [ 1 ]
67- if ( name ) {
68- wallets . push ( { name, isLocal : false } )
69- }
70- }
95+ wallets . push ( ...this . parseWallets ( globalWalletsContent , false ) )
7196 }
7297
7398 const seen : Set < string > = new Set ( )
@@ -78,15 +103,29 @@ export class ActonToml {
78103 } )
79104 }
80105
81- public static async find ( startUri : string ) : Promise < ActonToml | undefined > {
106+ private parseWallets ( content : string , isLocal : boolean ) : WalletInfo [ ] {
107+ const wallets : WalletInfo [ ] = [ ]
108+ // Match [wallets.NAME] where NAME does not contain a dot
109+ const walletRegex = / ^ \[ w a l l e t s \. ( [ ^ \s . \] ] + ) ] / gm
110+ let match : RegExpExecArray | null
111+ while ( ( match = walletRegex . exec ( content ) ) !== null ) {
112+ const name = match [ 1 ]
113+ if ( name ) {
114+ wallets . push ( { name, isLocal} )
115+ }
116+ }
117+ return wallets
118+ }
119+
120+ public static discover ( startUri : string ) : ActonToml | undefined {
82121 let currentPath = URI . parse ( startUri ) . fsPath
83122
84123 for ( let i = 0 ; i < 10 ; i ++ ) {
85124 const dir = path . dirname ( currentPath )
86125 const tomlPath = path . join ( dir , "Acton.toml" )
87- const tomlUri = URI . file ( tomlPath ) . toString ( )
88126
89- if ( await existsVFS ( globalVFS , tomlUri ) ) {
127+ if ( fs . existsSync ( tomlPath ) ) {
128+ const tomlUri = URI . file ( tomlPath ) . toString ( )
90129 return new ActonToml ( tomlUri )
91130 }
92131
0 commit comments