@@ -98,45 +98,123 @@ func (c *Client) Run(gnoCode string) error {
9898}
9999
100100func (c * Client ) RunQuery (realmPath string , expression string ) ([]byte , error ) {
101- gnoCode := fmt .Sprintf (`package main
101+ parts := strings .Split (realmPath , "/" )
102+ packageAlias := parts [len (parts )- 1 ]
102103
103- import (
104- "%s"
105- )
104+ queryExpression := strings .Replace (expression , packageAlias + "." , realmPath + "." , 1 )
105+
106+ if strings .Contains (expression , ".Repository.Pull(" ) {
107+ return c .QueryFileInChunks (queryExpression )
108+ }
106109
107- func main() {
108- result := %s
109- content := make([]byte, len(result))
110- copy(content, result)
111- println(string(content))
110+ return c .QueryDirectInChunks (queryExpression )
112111}
113- ` , realmPath , expression )
114112
115- tmpFile := "/tmp/gnit_query.gno"
116- if err := os .WriteFile (tmpFile , []byte (gnoCode ), 0644 ); err != nil {
117- return nil , fmt .Errorf ("failed to create temp file: %w" , err )
113+ func (c * Client ) QueryFileInChunks (expression string ) ([]byte , error ) {
114+ sizeQuery := strings .Replace (expression , "Repository.Pull(" , "Repository.GetFileSize(" , 1 )
115+ sizeOutput , err := c .QueryEval (sizeQuery )
116+ if err != nil {
117+ return nil , fmt .Errorf ("failed to get file size: %w" , err )
118118 }
119- defer os .Remove (tmpFile )
120119
121- cmd := exec .Command ("gnokey" , "maketx" , "run" ,
122- "-gas-fee" , c .config .GasFee ,
123- "-gas-wanted" , c .config .GasWanted ,
124- "-broadcast" ,
125- "-chainid" , c .config .ChainID ,
126- "-remote" , c .config .Remote ,
127- c .config .Account ,
128- tmpFile )
120+ sizeOutput = strings .TrimPrefix (sizeOutput , "data: " )
121+ var size int
122+ if _ , err := fmt .Sscanf (sizeOutput , "(%d int)" , & size ); err != nil {
123+ return nil , fmt .Errorf ("failed to parse file size: %w" , err )
124+ }
129125
130- cmd .Stdin = os .Stdin
131- cmd .Stderr = os .Stderr
126+ if size < 0 {
127+ return nil , fmt .Errorf ("file not found" )
128+ }
129+
130+ if size == 0 {
131+ return []byte {}, nil
132+ }
133+
134+ var content []byte
135+ chunkSize := 200
136+ for offset := 0 ; offset < size ; offset += chunkSize {
137+ chunkQuery := strings .Replace (expression , "Repository.Pull(" , "Repository.GetFileChunk(" , 1 )
138+ chunkQuery = strings .Replace (chunkQuery , ")" , fmt .Sprintf (", %d, %d)" , offset , chunkSize ), 1 )
139+
140+ chunkOutput , err := c .QueryEval (chunkQuery )
141+ if err != nil {
142+ return nil , fmt .Errorf ("failed to get chunk at offset %d: %w" , offset , err )
143+ }
144+
145+ chunk := extractStringFromQuery (chunkOutput )
146+ content = append (content , []byte (chunk )... )
147+ }
148+
149+ return content , nil
150+ }
151+
152+ func (c * Client ) QueryEval (expression string ) (string , error ) {
153+ cmd := exec .Command ("gnokey" , "query" , "vm/qeval" ,
154+ "-data" , expression ,
155+ "-remote" , c .config .Remote )
132156
133157 output , err := cmd .Output ()
134158 if err != nil {
135- return nil , fmt .Errorf ("run query failed: %w" , err )
159+ return "" , fmt .Errorf ("query failed: %w" , err )
160+ }
161+
162+ return extractDataLine (string (output ))
163+ }
164+
165+ func extractStringFromQuery (output string ) string {
166+ output = strings .TrimPrefix (output , "data: " )
167+
168+ startIdx := strings .Index (output , `("` )
169+ if startIdx == - 1 {
170+ return ""
171+ }
172+ startIdx += 2
173+
174+ endIdx := strings .LastIndex (output , `" string)` )
175+ if endIdx == - 1 {
176+ return ""
177+ }
178+
179+ content := output [startIdx :endIdx ]
180+
181+ var result strings.Builder
182+ for i := 0 ; i < len (content ); i ++ {
183+ if content [i ] == '\\' && i + 1 < len (content ) {
184+ switch content [i + 1 ] {
185+ case 'n' :
186+ result .WriteByte ('\n' )
187+ i ++
188+ case 't' :
189+ result .WriteByte ('\t' )
190+ i ++
191+ case 'r' :
192+ result .WriteByte ('\r' )
193+ i ++
194+ case '\\' :
195+ result .WriteByte ('\\' )
196+ i ++
197+ case '"' :
198+ result .WriteByte ('"' )
199+ i ++
200+ default :
201+ result .WriteByte (content [i ])
202+ }
203+ } else {
204+ result .WriteByte (content [i ])
205+ }
206+ }
207+
208+ return result .String ()
209+ }
210+
211+ func (c * Client ) QueryDirectInChunks (expression string ) ([]byte , error ) {
212+ output , err := c .QueryEval (expression )
213+ if err != nil {
214+ return nil , err
136215 }
137216
138- content := extractTransactionOutput (string (output ))
139- return []byte (content ), nil
217+ return []byte (output ), nil
140218}
141219
142220func extractTransactionOutput (output string ) string {
0 commit comments