ton-client-ruby 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/ton-client-ruby +2 -2
- data/lib/code_generator/api_converter.rb +399 -0
- data/lib/code_generator/code_generator.rb +318 -0
- data/lib/code_generator/helpers.rb +13 -0
- data/lib/ton-client-ruby/version.rb +1 -1
- metadata +4 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b17d66a87de3133d8f5a6f84d76615156c7bf9648da6825584a269c33cad85bb
|
4
|
+
data.tar.gz: dab93ec7b176f1d70478ee2bc95b0a77a47104586a49bc0acc43032ab87649ff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 26cd4d5b9531449e9922b2cdf4ec9222bd2101a15ee27740a68865492cebc8c08f799ea40b1f8ea35d116792c062ef6cbd7923e49784d8628163429e612f7a0c
|
7
|
+
data.tar.gz: deff9cde16ae317c0783bf1ddac5c7c65fb6c58c982adcaf601391d872eb95022351ecec7196b856327efe9de4c5bd0e0c07d6fa1b169a96c4eb28d63b8d14bf
|
data/bin/ton-client-ruby
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require File.dirname(__FILE__) + '/../code_generator/api_converter.rb'
|
4
|
-
require File.dirname(__FILE__) + '/../code_generator/code_generator.rb'
|
3
|
+
require File.dirname(__FILE__) + '/../lib/code_generator/api_converter.rb'
|
4
|
+
require File.dirname(__FILE__) + '/../lib/code_generator/code_generator.rb'
|
5
5
|
|
6
6
|
GEM_DIR = File.dirname(__FILE__) + '/..'
|
7
7
|
|
@@ -0,0 +1,399 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'byebug'
|
3
|
+
require File.dirname(__FILE__) + '/helpers.rb'
|
4
|
+
|
5
|
+
|
6
|
+
|
7
|
+
class ApiConverter
|
8
|
+
include InstanceHelpers
|
9
|
+
|
10
|
+
attr_reader :api_hash
|
11
|
+
|
12
|
+
def initialize(api_json)
|
13
|
+
@api_hash = JSON.parse(api_json)
|
14
|
+
end
|
15
|
+
|
16
|
+
def convert
|
17
|
+
ruby_types = ApiRubyTypes.new(version: api_hash['version'], modules: [])
|
18
|
+
|
19
|
+
(api_hash['modules'] || []).each do |mod|
|
20
|
+
new_mod = convert_module(mod)
|
21
|
+
ruby_types.modules << new_mod
|
22
|
+
ruby_types.all_types.merge!(new_mod.types_hash)
|
23
|
+
end
|
24
|
+
|
25
|
+
ruby_types
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def convert_module(mod)
|
31
|
+
new_module = Module.new(name: mod['name'], alias: [], functions: [], enums: [], types: [], summary: mod['summary'], description: mod['description'])
|
32
|
+
(mod['types'] || []).each do |type|
|
33
|
+
if type['type'] == 'EnumOfTypes'
|
34
|
+
new_enum, new_struct = convert_fucking_enum_of_types(type)
|
35
|
+
new_module.enums << new_enum
|
36
|
+
new_module.types << new_struct
|
37
|
+
new_module.types_hash[new_enum.name] = new_enum
|
38
|
+
new_module.types_hash[new_struct.name] = new_struct
|
39
|
+
elsif type['type'] == 'EnumOfConsts'
|
40
|
+
new_type = convertEnumOfConsts(type)
|
41
|
+
new_module.enums << new_type
|
42
|
+
new_module.types_hash[new_type.name] = new_type
|
43
|
+
elsif type['type'] == 'Struct'
|
44
|
+
new_type = convertStruct(type)
|
45
|
+
new_module.types << new_type
|
46
|
+
new_module.types_hash[new_type.name] = new_type
|
47
|
+
elsif type['type'] == 'Number'
|
48
|
+
new_type = convertTypeAlias(type)
|
49
|
+
new_module.alias << new_type
|
50
|
+
new_module.types_hash[new_type.name] = new_type
|
51
|
+
else
|
52
|
+
raise "Unkown NEW TYPE for module #{type['name']} \"types\": #{type['types']}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# /// FUNCTIONS
|
57
|
+
(mod['functions'] || []).each do |function|
|
58
|
+
result = ""
|
59
|
+
if function['result']['type'] == "Generic"
|
60
|
+
ref_type = function['result']['generic_args'].first&.send(:[], 'type') || ""
|
61
|
+
if ref_type == "Ref"
|
62
|
+
ref_name = function['result']['generic_args'].first&.send(:[], 'ref_name') || ""
|
63
|
+
if ref_name[/^(.+)\.(.+)$/]
|
64
|
+
mod = $1
|
65
|
+
type = $2
|
66
|
+
result = "#{lib_prefix}#{type}"
|
67
|
+
else
|
68
|
+
raise "Bad function result ref_name: #{ref_name}, function name: #{function['name']}, result: #{function['result']}"
|
69
|
+
end
|
70
|
+
elsif ref_type == "None"
|
71
|
+
result = "Void"
|
72
|
+
end
|
73
|
+
else
|
74
|
+
raise "New function result type !"
|
75
|
+
end
|
76
|
+
|
77
|
+
# /// function
|
78
|
+
newFunction = StructFunction.new(name: checkFunctionName(function['name']), arguments: [], result: result, summary: function['summary'], description: function['description'])
|
79
|
+
# /// FUNCTION PARAMETERS
|
80
|
+
paramsCount = 0
|
81
|
+
(function['params'] || []).each do |parameter|
|
82
|
+
if parameter['name'] == "params"
|
83
|
+
paramsCount += 1
|
84
|
+
if parameter['type'] == "Ref"
|
85
|
+
ref_name = parameter['ref_name'] || ""
|
86
|
+
if ref_name[/^(.+)\.(.+)$/]
|
87
|
+
mod = $1
|
88
|
+
type = $2
|
89
|
+
newFunction.arguments << FunctionArgument.new(name: "payload", type: "#{lib_prefix}#{type}")
|
90
|
+
else
|
91
|
+
raise "Bad function params ref_name: #{ref_name}, function name: #{function['name']}, result: #{function['result']}"
|
92
|
+
end
|
93
|
+
else
|
94
|
+
raise "NEW CASE! New parameter type: #{parameter['type']}"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
raise "NEW CASE ! More then one parameter for functions !" if paramsCount > 1
|
98
|
+
end
|
99
|
+
|
100
|
+
new_module.functions << newFunction
|
101
|
+
end
|
102
|
+
|
103
|
+
new_module
|
104
|
+
end
|
105
|
+
|
106
|
+
def convertTypeAlias(from)
|
107
|
+
TypeAlias.new(name: "#{lib_prefix}#{from['name']}", type: generateType(from))
|
108
|
+
end
|
109
|
+
|
110
|
+
def convertStruct(from)
|
111
|
+
result = TypeStruct.new(name: "#{lib_prefix}#{from['name']}", parents: [], fields: [], functions: [])
|
112
|
+
(from['struct_fields'] || []).each do |field|
|
113
|
+
if isValidPropertyName(field['name'])
|
114
|
+
type = generateType(field)
|
115
|
+
if ( (from['name'] || "")[/Params/] || (field['name'] || "")[/input/]) && type[/Value/]
|
116
|
+
type = "Value"
|
117
|
+
elsif (field['name'] || "")[/^dictionary$/]
|
118
|
+
type = "#{lib_prefix}MnemonicDictionary"
|
119
|
+
elsif type[/Abi<Optional>/]
|
120
|
+
type = "Value<Optional>"
|
121
|
+
elsif type[/Abi/]
|
122
|
+
type = "Value"
|
123
|
+
end
|
124
|
+
property = StructField.new(name: checkPropertyName(field['name']), type: type, summary: field['summary'], description: field['description'])
|
125
|
+
result.fields << property
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
result
|
130
|
+
end
|
131
|
+
|
132
|
+
private def checkPropertyName(name)
|
133
|
+
result = ""
|
134
|
+
raise "Property Name is nil" unless name
|
135
|
+
|
136
|
+
case name
|
137
|
+
when "public"
|
138
|
+
result = "public"
|
139
|
+
else
|
140
|
+
result = name
|
141
|
+
end
|
142
|
+
|
143
|
+
return result
|
144
|
+
end
|
145
|
+
|
146
|
+
private def checkFunctionName(name)
|
147
|
+
result = ""
|
148
|
+
raise "Property Name is nil" unless name
|
149
|
+
case name
|
150
|
+
when "init"
|
151
|
+
result = "init"
|
152
|
+
else
|
153
|
+
result = name
|
154
|
+
end
|
155
|
+
|
156
|
+
return result
|
157
|
+
end
|
158
|
+
|
159
|
+
private def isValidPropertyName(name)
|
160
|
+
!(name || " ")[/\s/]
|
161
|
+
end
|
162
|
+
|
163
|
+
def convertEnumOfConsts(from)
|
164
|
+
result = TypeEnum.new(name: "#{lib_prefix}#{from['name']}", parents: [], cases: [], summary: from['summary'], description: from['description'])
|
165
|
+
(from['enum_consts'] || []).each do |enumConst|
|
166
|
+
caseName = enumConst['name']
|
167
|
+
caseValue = enumConst['value']
|
168
|
+
result.cases << EnumCase.new(name: caseName, value: caseValue, summary: enumConst['summary'], description: enumConst['description'])
|
169
|
+
end
|
170
|
+
|
171
|
+
return result
|
172
|
+
end
|
173
|
+
|
174
|
+
def convert_fucking_enum_of_types(enum)
|
175
|
+
result = [
|
176
|
+
TypeEnum.new(name: generate_enum_name(enum['name']), parents: [], cases: []),
|
177
|
+
TypeStruct.new(name: generate_struct_name(enum['name']), parents: [], fields: [], functions: [], summary: enum['summary'], description: enum['description'])
|
178
|
+
]
|
179
|
+
properties_name_set = Set.new
|
180
|
+
properties = []
|
181
|
+
(enum['enum_types'] || []).each do |enum_type|
|
182
|
+
result[0].cases << EnumCase.new(name: enum_type['name'], value: enum_type['name'])
|
183
|
+
(enum_type['struct_fields'] || []).each do |field|
|
184
|
+
if !properties_name_set.include?(field['name'])
|
185
|
+
properties << field
|
186
|
+
end
|
187
|
+
properties_name_set << field['name']
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
result[1].fields << StructField.new(name: "type", type: generate_enum_name(enum['name']))
|
192
|
+
properties.each do |property|
|
193
|
+
type = generateType(property)
|
194
|
+
if property['name'][/^dictionary$/]
|
195
|
+
type = "#{lib_prefix}MnemonicDictionary"
|
196
|
+
end
|
197
|
+
result[1].fields << StructField.new(name: property['name'], type: type, summary: property['summary'], description: property['description'])
|
198
|
+
end
|
199
|
+
result
|
200
|
+
end
|
201
|
+
|
202
|
+
private def generateSimpleType(type)
|
203
|
+
tempType = ""
|
204
|
+
|
205
|
+
if type['type'] == "Ref"
|
206
|
+
if type['ref_name'] == "Value" || type['ref_name'] == "API"
|
207
|
+
tempType = "Value"
|
208
|
+
else
|
209
|
+
return type['optional'] ? "#{generateRefType(type['ref_name'] || "nil")}<Optional>" : generateRefType(type['ref_name'] || "nil")
|
210
|
+
end
|
211
|
+
else
|
212
|
+
tempType = type['type']
|
213
|
+
end
|
214
|
+
tempType = "#{tempType}<Optional>" if type['optional']
|
215
|
+
|
216
|
+
tempType
|
217
|
+
end
|
218
|
+
|
219
|
+
private def generateRefType(type)
|
220
|
+
result = ""
|
221
|
+
|
222
|
+
if type[/(.+)\.(.+)/]
|
223
|
+
mod = $1
|
224
|
+
typeName = $2
|
225
|
+
result = "#{lib_prefix}#{typeName}"
|
226
|
+
else
|
227
|
+
result = "#{lib_prefix}#{type}"
|
228
|
+
end
|
229
|
+
|
230
|
+
result
|
231
|
+
end
|
232
|
+
|
233
|
+
private def generateType(type)
|
234
|
+
if type['type'] == "Optional" && type['optional_inner']
|
235
|
+
type['optional'] = true
|
236
|
+
type['optional_inner']['optional'] = true
|
237
|
+
if type['optional_inner']['type'] == "Optional"
|
238
|
+
return generateType(type['optional_inner'])
|
239
|
+
else
|
240
|
+
return generateSimpleType(type['optional_inner'])
|
241
|
+
end
|
242
|
+
else
|
243
|
+
return generateSimpleType(type)
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
private def generate_enum_name(name)
|
248
|
+
"#{lib_prefix}#{name}#{lib_enum_postfix}"
|
249
|
+
end
|
250
|
+
|
251
|
+
private def generate_struct_name(name)
|
252
|
+
"#{lib_prefix}#{name}"
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
|
257
|
+
class ApiRubyTypes
|
258
|
+
attr_accessor :version
|
259
|
+
attr_accessor :modules
|
260
|
+
attr_accessor :all_types
|
261
|
+
|
262
|
+
def initialize(params)
|
263
|
+
@all_types = {}
|
264
|
+
params.each do |k, v|
|
265
|
+
if self.respond_to?(k.to_sym)
|
266
|
+
instance_variable_set("@#{k}".to_sym, v)
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
class Module
|
273
|
+
attr_accessor :name
|
274
|
+
attr_accessor :summary
|
275
|
+
attr_accessor :description
|
276
|
+
attr_accessor :alias
|
277
|
+
attr_accessor :enums
|
278
|
+
attr_accessor :types
|
279
|
+
attr_accessor :types_hash
|
280
|
+
attr_accessor :functions
|
281
|
+
attr_accessor :summary
|
282
|
+
attr_accessor :description
|
283
|
+
|
284
|
+
def initialize(params)
|
285
|
+
@types_hash = {}
|
286
|
+
params.each do |k, v|
|
287
|
+
if self.respond_to?(k.to_sym)
|
288
|
+
instance_variable_set("@#{k}".to_sym, v)
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
class TypeAlias
|
295
|
+
attr_accessor :name
|
296
|
+
attr_accessor :type
|
297
|
+
attr_accessor :summary
|
298
|
+
attr_accessor :description
|
299
|
+
|
300
|
+
def initialize(params)
|
301
|
+
params.each do |k, v|
|
302
|
+
if self.respond_to?(k.to_sym)
|
303
|
+
instance_variable_set("@#{k}".to_sym, v)
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
class TypeEnum
|
310
|
+
attr_accessor :name
|
311
|
+
attr_accessor :parents
|
312
|
+
attr_accessor :cases
|
313
|
+
attr_accessor :summary
|
314
|
+
attr_accessor :description
|
315
|
+
|
316
|
+
def initialize(params)
|
317
|
+
params.each do |k, v|
|
318
|
+
if self.respond_to?(k.to_sym)
|
319
|
+
instance_variable_set("@#{k}".to_sym, v)
|
320
|
+
end
|
321
|
+
end
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
class EnumCase
|
326
|
+
attr_accessor :name
|
327
|
+
attr_accessor :value
|
328
|
+
attr_accessor :summary
|
329
|
+
attr_accessor :description
|
330
|
+
|
331
|
+
def initialize(params)
|
332
|
+
params.each do |k, v|
|
333
|
+
if self.respond_to?(k)
|
334
|
+
instance_variable_set("@#{k}".to_sym, v)
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
class TypeStruct
|
341
|
+
attr_accessor :name
|
342
|
+
attr_accessor :parents
|
343
|
+
attr_accessor :fields
|
344
|
+
attr_accessor :functions
|
345
|
+
attr_accessor :summary
|
346
|
+
attr_accessor :description
|
347
|
+
|
348
|
+
def initialize(params)
|
349
|
+
params.each do |k, v|
|
350
|
+
if self.respond_to?(k.to_sym)
|
351
|
+
instance_variable_set("@#{k}".to_sym, v)
|
352
|
+
end
|
353
|
+
end
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
class StructField
|
358
|
+
attr_accessor :name
|
359
|
+
attr_accessor :type
|
360
|
+
attr_accessor :summary
|
361
|
+
attr_accessor :description
|
362
|
+
|
363
|
+
def initialize(params)
|
364
|
+
params.each do |k, v|
|
365
|
+
if self.respond_to?(k.to_sym)
|
366
|
+
instance_variable_set("@#{k}".to_sym, v)
|
367
|
+
end
|
368
|
+
end
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
class StructFunction
|
373
|
+
attr_accessor :name
|
374
|
+
attr_accessor :arguments
|
375
|
+
attr_accessor :result
|
376
|
+
attr_accessor :summary
|
377
|
+
attr_accessor :description
|
378
|
+
|
379
|
+
def initialize(params)
|
380
|
+
params.each do |k, v|
|
381
|
+
if self.respond_to?(k.to_sym)
|
382
|
+
instance_variable_set("@#{k}".to_sym, v)
|
383
|
+
end
|
384
|
+
end
|
385
|
+
end
|
386
|
+
end
|
387
|
+
|
388
|
+
class FunctionArgument
|
389
|
+
attr_accessor :name
|
390
|
+
attr_accessor :type
|
391
|
+
|
392
|
+
def initialize(params)
|
393
|
+
params.each do |k, v|
|
394
|
+
if self.respond_to?(k.to_sym)
|
395
|
+
instance_variable_set("@#{k}".to_sym, v)
|
396
|
+
end
|
397
|
+
end
|
398
|
+
end
|
399
|
+
end
|
@@ -0,0 +1,318 @@
|
|
1
|
+
require 'byebug'
|
2
|
+
require 'json'
|
3
|
+
require File.dirname(__FILE__) + '/helpers.rb'
|
4
|
+
|
5
|
+
class CodeGenerator
|
6
|
+
include InstanceHelpers
|
7
|
+
|
8
|
+
attr_accessor :types
|
9
|
+
attr_accessor :root_dir
|
10
|
+
|
11
|
+
TAB = " "
|
12
|
+
|
13
|
+
def initialize(types, root_dir)
|
14
|
+
@types = types
|
15
|
+
@root_dir = root_dir
|
16
|
+
end
|
17
|
+
|
18
|
+
def generate_self_code
|
19
|
+
generateModules(types)
|
20
|
+
generateReadme(types)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def generateModules(types)
|
26
|
+
types.modules.each do |mod|
|
27
|
+
modulesFolder = root_dir + "/lib/ton-client-ruby/Client"
|
28
|
+
moduleFilePath = "#{modulesFolder}/#{mod.name.capitalize}.rb"
|
29
|
+
newModuleContent = ""
|
30
|
+
if mod.name == "client"
|
31
|
+
newModuleContent = generateClientModule(mod, types.modules)
|
32
|
+
else
|
33
|
+
newModuleContent = generateModule(mod)
|
34
|
+
end
|
35
|
+
if File.exists?(moduleFilePath)
|
36
|
+
File.delete(moduleFilePath)
|
37
|
+
end
|
38
|
+
File.open(moduleFilePath, 'w+') { |f| f.write(newModuleContent) }
|
39
|
+
end
|
40
|
+
|
41
|
+
p 'generate_self_code ok'
|
42
|
+
end
|
43
|
+
|
44
|
+
def generateReadme(types)
|
45
|
+
readmePath = root_dir + "/README.md"
|
46
|
+
content = %{
|
47
|
+
# Ruby Client for Free TON SDK
|
48
|
+
|
49
|
+
[]()
|
50
|
+
|
51
|
+
## Install
|
52
|
+
|
53
|
+
Install gem
|
54
|
+
```bash
|
55
|
+
gem install ton-client-ruby
|
56
|
+
```
|
57
|
+
|
58
|
+
Install TON-SDK
|
59
|
+
```bash
|
60
|
+
ton-client-ruby setup
|
61
|
+
```
|
62
|
+
|
63
|
+
### Manual build FreeTON SDK
|
64
|
+
0. Install Rust to your OS
|
65
|
+
1. git clone https://github.com/tonlabs/TON-SDK
|
66
|
+
2. cd ./TON-SDK
|
67
|
+
3. cargo update
|
68
|
+
4. cargo build --release
|
69
|
+
|
70
|
+
## Usage
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
# For MAcOS
|
74
|
+
TonClient.configure { |config| config.ffi_lib(./TON-SDK/target/release/libton_client.dylib) }
|
75
|
+
# For Linux
|
76
|
+
# TonClient.configure { |config| config.ffi_lib(./TON-SDK/target/release/libton_client.so) }
|
77
|
+
|
78
|
+
client = TonClient.create(config: {network: {server_address: "net.ton.dev"}})
|
79
|
+
|
80
|
+
# All methods are asynchronous
|
81
|
+
|
82
|
+
# example: call method for Crypto module
|
83
|
+
payload = {composite: '17ED48941A08F981'}
|
84
|
+
client.crypto.factorize(payload) do |response|
|
85
|
+
p response.result['factors']
|
86
|
+
end
|
87
|
+
|
88
|
+
# e.g. ...
|
89
|
+
```\n\n
|
90
|
+
}
|
91
|
+
content << "## All Modules, methods and types\n\n"
|
92
|
+
|
93
|
+
# types
|
94
|
+
content << "<details>\n#{TAB}<summary>Types</summary>\n\n"
|
95
|
+
|
96
|
+
content << "#{customTypes()}\n"
|
97
|
+
|
98
|
+
types.modules.each do |mod|
|
99
|
+
(mod.enums || []).each do |type|
|
100
|
+
content << checkComment(type.summary, 0) if type.summary
|
101
|
+
content << checkComment(type.description, 0) if type.description
|
102
|
+
content << "\n- #### #{type.name}\n"
|
103
|
+
(type.cases || []).each do |enum_case|
|
104
|
+
content << "#{checkComment(enum_case.summary, 1).gsub(/#/, '')}" if enum_case.summary
|
105
|
+
content << "#{checkComment(enum_case.description, 1).gsub(/#/, '')}" if enum_case.description
|
106
|
+
content << "#{TAB}- case #{enum_case.name} = #{enum_case.value}\n\n"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
(mod.types || []).each do |type|
|
111
|
+
content << checkComment(type.summary, 0) if type.summary
|
112
|
+
content << checkComment(type.description, 0) if type.description
|
113
|
+
content << "\n- #### #{type.name}\n"
|
114
|
+
(type.fields || []).each do |field|
|
115
|
+
content << "#{checkComment(field.summary, 1).gsub(/#/, '')}\n" if field.summary
|
116
|
+
content << "#{checkComment(field.description, 1).gsub(/#/, '')}\n" if field.description
|
117
|
+
content << "#{TAB}- #{field.name}: #{field.type}\n\n"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
content << "</details>\n\n"
|
122
|
+
|
123
|
+
# methods
|
124
|
+
types.modules.each do |mod|
|
125
|
+
content << "<details>\n#{TAB}<summary>#{mod.name&.upcase}</summary>\n\n"
|
126
|
+
(mod.functions || []).each do |function|
|
127
|
+
content << "```ruby\n"
|
128
|
+
content << checkComment(function.summary, 2) if function.summary
|
129
|
+
content << checkComment(function.description, 2) if function.description
|
130
|
+
content << "\n#{TAB}#{TAB}def #{function.name}"
|
131
|
+
if function.arguments.empty?
|
132
|
+
content << "(&block)\n"
|
133
|
+
else
|
134
|
+
content << "(payload, &block)\n"
|
135
|
+
end
|
136
|
+
content << getFunctionComment(function, types)
|
137
|
+
content << "```\n"
|
138
|
+
end
|
139
|
+
content << "</details>\n\n"
|
140
|
+
end
|
141
|
+
|
142
|
+
content << %{
|
143
|
+
\n## Tests
|
144
|
+
|
145
|
+
1. create __.env.test__ file inside root directory of this library with variables
|
146
|
+
|
147
|
+
example for NodeSE
|
148
|
+
```
|
149
|
+
spec_ffi=./TON-SDK/target/release/libton_client.dylib
|
150
|
+
server_address=http://localhost:80
|
151
|
+
giver_abi_name=GiverNodeSE
|
152
|
+
giver_amount=10000000000
|
153
|
+
```
|
154
|
+
2. Run tests: inside folder of this library execute this commands
|
155
|
+
**rspec spec/binding.rb**
|
156
|
+
**rspec spec/client.rb**
|
157
|
+
**rspec spec/context.rb**
|
158
|
+
**rspec spec/abi.rb**
|
159
|
+
**rspec spec/boc.rb**
|
160
|
+
**rspec spec/crypto.rb**
|
161
|
+
**rspec spec/net.rb**
|
162
|
+
**rspec spec/processing.rb**
|
163
|
+
**rspec spec/tvm.rb**
|
164
|
+
**rspec spec/utils.rb**
|
165
|
+
}
|
166
|
+
content = checkContent(content)
|
167
|
+
if File.exists?(readmePath)
|
168
|
+
File.delete(readmePath)
|
169
|
+
end
|
170
|
+
File.open(readmePath, 'w+') { |f| f.write(content) }
|
171
|
+
end
|
172
|
+
|
173
|
+
private def checkContent(content)
|
174
|
+
content.gsub!(/^([\s]+)# RESPONSE/, "\n\\1# RESPONSE")
|
175
|
+
content.gsub(/<Optional>/i, '<Optional>')
|
176
|
+
end
|
177
|
+
|
178
|
+
def customTypes
|
179
|
+
content = %{
|
180
|
+
- #### #{lib_prefix}MnemonicDictionary
|
181
|
+
#{TAB}- case TON = 0
|
182
|
+
#{TAB}- case ENGLISH = 1
|
183
|
+
#{TAB}- case CHINESE_SIMPLIFIED = 2
|
184
|
+
#{TAB}- case CHINESE_TRADITIONAL = 3
|
185
|
+
#{TAB}- case FRENCH = 4
|
186
|
+
#{TAB}- case ITALIAN = 5
|
187
|
+
#{TAB}- case JAPANESE = 6
|
188
|
+
#{TAB}- case KOREAN = 7
|
189
|
+
#{TAB}- case SPANISH = 8
|
190
|
+
}
|
191
|
+
content
|
192
|
+
end
|
193
|
+
|
194
|
+
private def checkComment(string, tabs = 1)
|
195
|
+
replacedString = "\n"
|
196
|
+
tab = ""
|
197
|
+
tabs.times do |i|
|
198
|
+
tab << TAB
|
199
|
+
end
|
200
|
+
comment = "#"
|
201
|
+
replacedString << "#{tab}#{comment} "
|
202
|
+
symbolsWithSpace = "\\.|\\:|\\!|\\?|\\;"
|
203
|
+
regxp = /([^#{symbolsWithSpace}])\n/
|
204
|
+
result = string
|
205
|
+
result.gsub!(/\n+/, "\n")
|
206
|
+
result.gsub!(/ \n/, "\n#{comment} ")
|
207
|
+
result.gsub!(/(#{symbolsWithSpace})\s*\n/, "\\1#{replacedString}")
|
208
|
+
result.gsub!(regxp, "\\1")
|
209
|
+
"#{tab}# #{result}"
|
210
|
+
end
|
211
|
+
|
212
|
+
private def generateClientModule(mod, modules)
|
213
|
+
content = "module TonClient\n\n#{TAB}class #{mod.name.capitalize}\n#{TAB}#{TAB}include CommonInstanceHelpers\n\n"
|
214
|
+
content << "#{TAB}#{TAB}attr_reader :core, :context\n"
|
215
|
+
content << "#{TAB}#{TAB}private_accessor "
|
216
|
+
modules.each_with_index do |m, i|
|
217
|
+
next if m.name.downcase == 'client'
|
218
|
+
content << ((modules.size - 1) == i ? ":_#{m.name}\n" : ":_#{m.name}, ")
|
219
|
+
end
|
220
|
+
content << "#{TAB}#{TAB}MODULE = self.to_s.downcase.gsub(/^(.+::|)(\\w+)$/, '\\2').freeze\n\n"
|
221
|
+
content << "#{TAB}#{TAB}def initialize(context: Context.new, core: TonClient::TonBinding)\n"
|
222
|
+
content << "#{TAB}#{TAB}#{TAB}@context = context\n"
|
223
|
+
content << "#{TAB}#{TAB}#{TAB}@core = core\n#{TAB}#{TAB}end\n\n"
|
224
|
+
content << "#{TAB}#{TAB}def destroy_context\n"
|
225
|
+
content << "#{TAB}#{TAB}#{TAB}core.tc_destroy_context(context.id)\n#{TAB}#{TAB}end\n\n"
|
226
|
+
modules.each_with_index do |m, i|
|
227
|
+
next if m.name.downcase == 'client'
|
228
|
+
content << "#{TAB}#{TAB}def #{m.name}\n"
|
229
|
+
content << "#{TAB}#{TAB}#{TAB}_#{m.name} ||= #{m.name.capitalize}.new(context: context)\n"
|
230
|
+
content << "#{TAB}#{TAB}end\n\n"
|
231
|
+
end
|
232
|
+
|
233
|
+
mod.functions.each do |func|
|
234
|
+
content << gen_function(func, types)
|
235
|
+
end
|
236
|
+
|
237
|
+
content << "#{TAB}end\n"
|
238
|
+
content << "end\n\n"
|
239
|
+
|
240
|
+
content
|
241
|
+
end
|
242
|
+
|
243
|
+
private def generateModule(mod)
|
244
|
+
content = "module TonClient\n\n#{TAB}class #{mod.name.capitalize}\n#{TAB}#{TAB}include CommonInstanceHelpers\n\n"
|
245
|
+
content << "#{TAB}#{TAB}attr_reader :core, :context\n"
|
246
|
+
content << "#{TAB}#{TAB}MODULE = self.to_s.downcase.gsub(/^(.+::|)(\\w+)$/, '\\2').freeze\n\n"
|
247
|
+
content << "#{TAB}#{TAB}def initialize(context: Context.new, core: TonClient::TonBinding)\n"
|
248
|
+
content << "#{TAB}#{TAB}#{TAB}@context = context\n"
|
249
|
+
content << "#{TAB}#{TAB}#{TAB}@core = core\n"
|
250
|
+
content << "#{TAB}#{TAB}end\n\n"
|
251
|
+
|
252
|
+
mod.functions.each do |func|
|
253
|
+
content << gen_function(func, types)
|
254
|
+
end
|
255
|
+
|
256
|
+
content << "#{TAB}end\n"
|
257
|
+
content << "end\n\n"
|
258
|
+
|
259
|
+
content
|
260
|
+
end
|
261
|
+
|
262
|
+
private def gen_function(function, types)
|
263
|
+
content = getFunctionComment(function, types)
|
264
|
+
content << "#{TAB}#{TAB}def #{function.name}"
|
265
|
+
if function.arguments.empty?
|
266
|
+
content << "(&block)\n"
|
267
|
+
content << "#{TAB}#{TAB}#{TAB}core.requestLibrary(context: context.id, method_name: full_method_name(MODULE, __method__.to_s), payload: {}, &block)\n"
|
268
|
+
else
|
269
|
+
content << "(payload, &block)\n"
|
270
|
+
content << "#{TAB}#{TAB}#{TAB}core.requestLibrary(context: context.id, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block)\n"
|
271
|
+
end
|
272
|
+
content << "#{TAB}#{TAB}end\n\n"
|
273
|
+
|
274
|
+
content
|
275
|
+
end
|
276
|
+
|
277
|
+
def getFunctionComment(function, types)
|
278
|
+
content = ''
|
279
|
+
if argument = function.arguments.first
|
280
|
+
content << "#{TAB}#{TAB}# INPUT: #{argument.type}\n"
|
281
|
+
if types.all_types[argument.type].respond_to?(:fields)
|
282
|
+
types.all_types[argument.type].fields.each do |arg|
|
283
|
+
content << "#{TAB}#{TAB}# #{arg.name}: #{arg.type} - "
|
284
|
+
content << "#{TAB}#{TAB}# #{checkComment(arg.summary, 2)}" if arg.summary
|
285
|
+
content << "#{TAB}#{TAB}# #{checkComment(arg.description, 2)}" if arg.description
|
286
|
+
content << "\n"
|
287
|
+
end
|
288
|
+
elsif types.all_types[argument.type].respond_to?(:cases)
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
if types.all_types[function.result]
|
293
|
+
content << "#{TAB}#{TAB}# RESPONSE: #{function.result}\n"
|
294
|
+
if types.all_types[function.result].respond_to?(:fields)
|
295
|
+
types.all_types[function.result].fields.each do |arg|
|
296
|
+
content << "#{TAB}#{TAB}# #{arg.name}: #{arg.type} - "
|
297
|
+
content << "#{TAB}#{TAB}# #{checkComment(arg.summary, 2)}" if arg.summary
|
298
|
+
content << "#{TAB}#{TAB}# #{checkComment(arg.description, 2)}" if arg.description
|
299
|
+
content << "\n"
|
300
|
+
end
|
301
|
+
elsif types.all_types[function.result].respond_to?(:cases)
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
content
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
|
310
|
+
|
311
|
+
|
312
|
+
|
313
|
+
|
314
|
+
|
315
|
+
|
316
|
+
|
317
|
+
|
318
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ton-client-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- nerzh
|
@@ -103,6 +103,9 @@ extensions: []
|
|
103
103
|
extra_rdoc_files: []
|
104
104
|
files:
|
105
105
|
- bin/ton-client-ruby
|
106
|
+
- lib/code_generator/api_converter.rb
|
107
|
+
- lib/code_generator/code_generator.rb
|
108
|
+
- lib/code_generator/helpers.rb
|
106
109
|
- lib/ton-client-ruby.rb
|
107
110
|
- lib/ton-client-ruby/Binding/binding.rb
|
108
111
|
- lib/ton-client-ruby/Binding/struct.rb
|