rubysol 0.1.0
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 +7 -0
- data/CHANGELOG.md +3 -0
- data/Manifest.txt +13 -0
- data/README.md +170 -0
- data/Rakefile +33 -0
- data/lib/rubysol/abi_proxy.rb +206 -0
- data/lib/rubysol/contract/crypto.rb +27 -0
- data/lib/rubysol/contract/runtime.rb +56 -0
- data/lib/rubysol/contract.rb +400 -0
- data/lib/rubysol/generator.rb +394 -0
- data/lib/rubysol/library.rb +126 -0
- data/lib/rubysol/runtime.rb +82 -0
- data/lib/rubysol/version.rb +23 -0
- data/lib/rubysol.rb +117 -0
- metadata +138 -0
@@ -0,0 +1,394 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
##
|
4
|
+
# "centralize"
|
5
|
+
## meta-programming magic (code generation) in module here - why? why not?
|
6
|
+
## find a better name e.g Magic? Pilot? or CodeGen or Metagen or ???
|
7
|
+
module Generator
|
8
|
+
|
9
|
+
|
10
|
+
############
|
11
|
+
## helpers
|
12
|
+
def self._demodulize( path )
|
13
|
+
## turn class.name into a symbol cutting off all namepspaces (::)
|
14
|
+
## e.g. Contracts::ERC20 => ERC20
|
15
|
+
##
|
16
|
+
## note: ActiveSupport::String#demodulize is the same (for string)
|
17
|
+
|
18
|
+
path = path.to_s
|
19
|
+
if i = path.rindex('::')
|
20
|
+
path[(i+2)..-1]
|
21
|
+
else
|
22
|
+
path
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
module Function
|
29
|
+
####
|
30
|
+
## rename to pack_params/args or cook_params or typed_params or ???
|
31
|
+
|
32
|
+
|
33
|
+
def self.typecheck( type, value )
|
34
|
+
## check if value is already typed?
|
35
|
+
if value.is_a?( Types::Typed )
|
36
|
+
## type check
|
37
|
+
raise TypeError, "type #{type} expected; got #{value.pretty_print_inspect}" unless type == value.type
|
38
|
+
value
|
39
|
+
else
|
40
|
+
## assume "literal" value
|
41
|
+
type.new( value )
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
def self.params( method, inputs, *args_unsafe, **kwargs_unsafe )
|
47
|
+
m = method
|
48
|
+
params = m.parameters
|
49
|
+
## puts "params for #{m} - #{m.owner}:"
|
50
|
+
## pp params
|
51
|
+
|
52
|
+
## e.g.
|
53
|
+
## [[:keyreq, :name],
|
54
|
+
## [:keyreq, :symbol],
|
55
|
+
## [:keyreq, :decimals],
|
56
|
+
## [:keyreq, :totalSupply]]
|
57
|
+
## get keys
|
58
|
+
keys = params.map { |param| param[1] }
|
59
|
+
## puts "keys:"
|
60
|
+
## pp keys
|
61
|
+
|
62
|
+
kwargs = if !args_unsafe.empty?
|
63
|
+
values = inputs.zip( args_unsafe ).map do |type, value|
|
64
|
+
typecheck( type, value )
|
65
|
+
end
|
66
|
+
## puts "args:"
|
67
|
+
## puts values.pretty_print_inspect
|
68
|
+
|
69
|
+
keys.zip( values ).map do |key,value|
|
70
|
+
[key,value]
|
71
|
+
end.to_h
|
72
|
+
elsif !kwargs_unsafe.empty?
|
73
|
+
types = keys.zip( inputs ).map do |key,type|
|
74
|
+
[key,type]
|
75
|
+
end.to_h
|
76
|
+
## puts "types:"
|
77
|
+
## pp types
|
78
|
+
kwargs_unsafe.map do |key,value|
|
79
|
+
type = types[key]
|
80
|
+
raise ArgumentError, "unknown kwarg #{key}; sorry" if type.nil?
|
81
|
+
[key, typecheck( type, value)]
|
82
|
+
end.to_h
|
83
|
+
else
|
84
|
+
## assume no args - e.g. construct - double check for empty input spec/def!!!
|
85
|
+
if inputs.empty?
|
86
|
+
{}
|
87
|
+
else
|
88
|
+
raise ArgumentError, "Array (args) or Hash (kwargs) required for func call; sorry"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
unless kwargs.empty?
|
93
|
+
puts "#{kwargs.size} kwarg(s):"
|
94
|
+
pp kwargs
|
95
|
+
end
|
96
|
+
|
97
|
+
kwargs
|
98
|
+
end
|
99
|
+
end # module Function
|
100
|
+
|
101
|
+
|
102
|
+
## to rename to generate_typed or generate_wrapped or ??
|
103
|
+
## typed_method??
|
104
|
+
def self.typed_function( contract_class, name, inputs: )
|
105
|
+
## note: must? find matching method in class
|
106
|
+
## todo/fix: use methods( false) if available (do NOT look-up in subclasses or such)
|
107
|
+
|
108
|
+
## note: make sure name and contract_name is always a symbol
|
109
|
+
name = name.to_sym
|
110
|
+
contract_name = _demodulize( contract_class.name ).to_sym
|
111
|
+
|
112
|
+
exists = contract_class.instance_methods( false ).include?( name )
|
113
|
+
if !exists
|
114
|
+
error_message = "[ERRRO] no method #{name} found for sig in class #{contract_class.name}"
|
115
|
+
puts error_message
|
116
|
+
## fix: change to NoMethodError - exists?
|
117
|
+
raise NameError, error_message
|
118
|
+
end
|
119
|
+
|
120
|
+
## note: method lookup via method needs an object / INSTANCE
|
121
|
+
## NOT working with class only!!!!
|
122
|
+
## m = contract_class.method( name )
|
123
|
+
## puts " bingo! #{name} - #{m.owner}"
|
124
|
+
puts " bingo! #{name}"
|
125
|
+
|
126
|
+
|
127
|
+
## avoid recursive circle
|
128
|
+
## exlcude method from method_add automagic wrapping/generation
|
129
|
+
|
130
|
+
contract_class.sigs_exclude << :"__#{contract_name}__#{name}_unsafe"
|
131
|
+
contract_class.sigs_exclude << :"__#{contract_name}__#{name}"
|
132
|
+
contract_class.sigs_exclude << name
|
133
|
+
|
134
|
+
|
135
|
+
##
|
136
|
+
## use :name_raw instead of :name_unsafe - why? why not?
|
137
|
+
|
138
|
+
## rewire
|
139
|
+
## alias_method :name_unsafe, :name
|
140
|
+
## alias_method :name, :name_typed
|
141
|
+
contract_class.class_eval do
|
142
|
+
|
143
|
+
define_method :"__#{contract_name}__#{name}" do |*args_unsafe,**kwargs_unsafe|
|
144
|
+
puts "==> calling __#{contract_name}__#{name} (class #{contract_class.name})"
|
145
|
+
|
146
|
+
m = method( :"__#{contract_name}__#{name}_unsafe" )
|
147
|
+
kwargs = Function.params( m, inputs, *args_unsafe, **kwargs_unsafe )
|
148
|
+
|
149
|
+
ret = m.call( **kwargs )
|
150
|
+
## todo/fix:
|
151
|
+
## check returns type / value too
|
152
|
+
ret
|
153
|
+
end
|
154
|
+
|
155
|
+
## note: must add class/contract name (via prefix) here!!
|
156
|
+
## rename (unsafe/untyped) method
|
157
|
+
alias_method :"__#{contract_name}__#{name}_unsafe", name
|
158
|
+
alias_method name, :"__#{contract_name}__#{name}"
|
159
|
+
## if name == :constructor ### add ERC20() or such
|
160
|
+
## alias_method contract_name, :"__#{contract_name}__#{name}"
|
161
|
+
## end
|
162
|
+
## - use leading underscore - why? why not? e.g. _ERC20()
|
163
|
+
## as alternative to NOT conflict with global conversion function - why? why not?
|
164
|
+
end
|
165
|
+
end # method typed_function
|
166
|
+
|
167
|
+
|
168
|
+
def self.typed_library_function( contract_class, name, inputs: )
|
169
|
+
## note: must? find matching method in class
|
170
|
+
## todo/fix: use methods( false) if available (do NOT look-up in subclasses or such)
|
171
|
+
|
172
|
+
## todo - make sure contract_class is a module (not a class) !!!!
|
173
|
+
|
174
|
+
## note: make sure name and contract_name is always a symbol
|
175
|
+
name = name.to_sym
|
176
|
+
contract_name = _demodulize( contract_class.name ).to_sym
|
177
|
+
|
178
|
+
exists = contract_class.instance_methods( false ).include?( name )
|
179
|
+
if !exists
|
180
|
+
error_message = "[ERRRO] no method #{name} found for sig in module #{contract_class.name}"
|
181
|
+
puts error_message
|
182
|
+
## fix: change to NoMethodError - exists?
|
183
|
+
raise NameError, error_message
|
184
|
+
end
|
185
|
+
|
186
|
+
## note: method lookup via method needs an object / INSTANCE
|
187
|
+
## NOT working with class only!!!!
|
188
|
+
## m = contract_class.method( name )
|
189
|
+
## puts " bingo! #{name} - #{m.owner}"
|
190
|
+
puts " bingo! #{name}"
|
191
|
+
|
192
|
+
|
193
|
+
## avoid recursive circle
|
194
|
+
## exlcude method from method_add automagic wrapping/generation
|
195
|
+
|
196
|
+
contract_class.sigs_exclude << :"#{name}_unsafe"
|
197
|
+
contract_class.sigs_exclude << name
|
198
|
+
|
199
|
+
##
|
200
|
+
## use :name_raw instead of :name_unsafe - why? why not?
|
201
|
+
|
202
|
+
## rewire
|
203
|
+
## alias_method :name_unsafe, :name
|
204
|
+
## alias_method :name, :name_typed
|
205
|
+
contract_class.class_eval do
|
206
|
+
|
207
|
+
alias_method :"#{name}_unsafe", name
|
208
|
+
|
209
|
+
define_method name do |*args_unsafe,**kwargs_unsafe|
|
210
|
+
puts "==> calling #{contract_name}.#{name} (module #{contract_class.name})"
|
211
|
+
|
212
|
+
m = method( :"#{name}_unsafe" )
|
213
|
+
kwargs = Function.params( m, inputs, *args_unsafe, **kwargs_unsafe )
|
214
|
+
|
215
|
+
ret = m.call( **kwargs )
|
216
|
+
## todo/fix:
|
217
|
+
## check returns type / value too
|
218
|
+
ret
|
219
|
+
end
|
220
|
+
|
221
|
+
## make into module functions!!!
|
222
|
+
module_function name
|
223
|
+
module_function :"#{name}_unsafe"
|
224
|
+
end
|
225
|
+
end # method typed_library_function
|
226
|
+
|
227
|
+
|
228
|
+
|
229
|
+
###
|
230
|
+
# add public getters helpers
|
231
|
+
def self.getter_function( contract_class, name, type )
|
232
|
+
## note: make sure name is always a symbol
|
233
|
+
name = name.to_sym
|
234
|
+
|
235
|
+
if type.mapping?
|
236
|
+
mapping_getter_function( contract_class, name, type )
|
237
|
+
elsif type.array?
|
238
|
+
puts "[debug] auto-generate public array getter - #{name} : #{type}:"
|
239
|
+
|
240
|
+
|
241
|
+
## auto-add/register sig(nature) in here - why? why not?
|
242
|
+
## contract_class.sig( name,
|
243
|
+
## [Types::Typed::UIntType.instance],
|
244
|
+
## :view, returns: type.sub_type )
|
245
|
+
|
246
|
+
## auto-add/register sig(nature) in here - why? why not?
|
247
|
+
## fix-fix-fix - check if outputs is an array (or still single type?)
|
248
|
+
contract_class.sigs[ name ] = { inputs: [typeof(Types::UInt)],
|
249
|
+
outputs: [typeof(type.sub_type)],
|
250
|
+
options: [:view,:public] }
|
251
|
+
contract_class.sigs_exclude << name
|
252
|
+
|
253
|
+
|
254
|
+
contract_class.class_eval do
|
255
|
+
## note: hack: must use kwargs for now!!! index: (not index) for now
|
256
|
+
define_method name do |index:|
|
257
|
+
puts "[debug] call public (state) array getter for #{name} : #{type} with index #{index} (#{contract_class.name})"
|
258
|
+
puts "[debug] self -> #{self}"
|
259
|
+
value = instance_variable_get( :"@#{name}" )
|
260
|
+
value[index]
|
261
|
+
end
|
262
|
+
end # class_evel
|
263
|
+
|
264
|
+
## auto-add typed wrapper!!!!!
|
265
|
+
typed_function( contract_class, name, inputs: [typeof(Types::UInt)] )
|
266
|
+
else
|
267
|
+
puts "[debug] auto-generate public getter - #{name} : #{type}:"
|
268
|
+
|
269
|
+
## auto-add/register sig(nature) in here - why? why not?
|
270
|
+
## fix-fix-fix - check if outputs is an array (or still single type?)
|
271
|
+
contract_class.sigs[ name ] = { inputs: [],
|
272
|
+
outputs: [typeof(type)],
|
273
|
+
options: [:view, :public] }
|
274
|
+
contract_class.sigs_exclude << name
|
275
|
+
|
276
|
+
|
277
|
+
contract_class.class_eval do
|
278
|
+
define_method name do
|
279
|
+
puts "[debug] call public (state) getter for #{name} : #{type} (#{contract_class.name})"
|
280
|
+
puts "[debug] self -> #{self}"
|
281
|
+
value = instance_variable_get( :"@#{name}" )
|
282
|
+
value
|
283
|
+
end
|
284
|
+
end # class_eval
|
285
|
+
|
286
|
+
## auto-add typed wrapper!!!!!
|
287
|
+
typed_function( contract_class, name, inputs: [] )
|
288
|
+
end # if
|
289
|
+
|
290
|
+
## puts "after - instance_methods:"
|
291
|
+
## pp contract_class.instance_methods( false )
|
292
|
+
end # method getter_function
|
293
|
+
|
294
|
+
|
295
|
+
|
296
|
+
def self.mapping_getter_function( contract_class, name, type )
|
297
|
+
## note: make sure name is always a symbol
|
298
|
+
name = name.to_sym
|
299
|
+
|
300
|
+
index = 0
|
301
|
+
current_type = type
|
302
|
+
|
303
|
+
sig_args = []
|
304
|
+
while current_type.mapping? do
|
305
|
+
sig_args << current_type.key_type
|
306
|
+
current_type = current_type.value_type
|
307
|
+
index += 1
|
308
|
+
end
|
309
|
+
|
310
|
+
|
311
|
+
puts "[debug] auto-generate public mapping getter - #{name} : #{type} (#{contract_class.name}):"
|
312
|
+
puts "sig_args:"
|
313
|
+
pp sig_args
|
314
|
+
## auto-add/register sig(nature) in here - why? why not?
|
315
|
+
## contract_class.sig( name, sig_args, :view, returns: current_type)
|
316
|
+
puts " index: #{index}"
|
317
|
+
# {:arg0=>:address}
|
318
|
+
# index: 1
|
319
|
+
|
320
|
+
## check - if sig_args is alreay array of types (or typedclasses???)
|
321
|
+
sig_args = sig_args.map {|sig_arg| typeof(sig_arg) }
|
322
|
+
|
323
|
+
contract_class.sigs[ name ] = { inputs: sig_args,
|
324
|
+
outputs: [typeof(current_type)],
|
325
|
+
options: [:view, :public] }
|
326
|
+
contract_class.sigs_exclude << name
|
327
|
+
|
328
|
+
|
329
|
+
puts contract_class.sigs[ name ].pretty_print_inspect
|
330
|
+
|
331
|
+
|
332
|
+
contract_class.class_eval do
|
333
|
+
## note: hack: must use kwargs for now!!! arg0, arg1, arg2, for now
|
334
|
+
define_method name do |arg0:, arg1: nil, arg2: nil, arg3: nil|
|
335
|
+
puts "[debug] call public (state) mapping getter for #{name} : #{type} - index: #{index} (#{contract_class.name})"
|
336
|
+
puts "[debug] self -> #{self}"
|
337
|
+
args = [arg0, arg1, arg2, arg3]
|
338
|
+
puts "[debug] args -> #{args.pretty_print_inspect}"
|
339
|
+
|
340
|
+
## raise ArgumentError, "expected #{index} argument(s); got #{args.size}" if args.size != index
|
341
|
+
|
342
|
+
value = instance_variable_get( "@#{name}" )
|
343
|
+
(0...index).each do |i|
|
344
|
+
value = value[ args[i] ]
|
345
|
+
end
|
346
|
+
value
|
347
|
+
end
|
348
|
+
end # class_eval
|
349
|
+
|
350
|
+
## auto-add typed wrapper!!!!!
|
351
|
+
typed_function( contract_class, name, inputs: sig_args )
|
352
|
+
|
353
|
+
end # method mapping_getter_function
|
354
|
+
|
355
|
+
|
356
|
+
|
357
|
+
##
|
358
|
+
# add global contract function to lookup AND typecheck
|
359
|
+
## contracts using Contract.at
|
360
|
+
## add via Module and Kernel - why? why not?
|
361
|
+
module Globals
|
362
|
+
end # module Globals
|
363
|
+
|
364
|
+
## todo/check: move Kernel include to rubidity.rb script (with requires) - why? why not?
|
365
|
+
::Kernel.include( Globals )
|
366
|
+
|
367
|
+
def self.global_function( contract_class )
|
368
|
+
## todo/check: check if method exists already - why? why not?
|
369
|
+
|
370
|
+
contract_name = _demodulize( contract_class.name ).to_sym
|
371
|
+
|
372
|
+
## use module_eval if exists? why? why not?
|
373
|
+
## example:
|
374
|
+
## def ERC20( address )
|
375
|
+
## klass = ERC20
|
376
|
+
## puts "==> calling #{klass.name}( #{address.pretty_print_inspect })"
|
377
|
+
## obj = klass.at( address )
|
378
|
+
## raise ArgumentError, "no #{klass.name} contract @ addreess #{address} found; sorry" if obj.nil?
|
379
|
+
## puts " bingo! #{obj.class.name} (#{obj.class.parent_contracts}) contract found @ #{address}"
|
380
|
+
## obj
|
381
|
+
## end
|
382
|
+
Globals.class_eval do
|
383
|
+
define_method contract_name do |address|
|
384
|
+
klass = contract_class
|
385
|
+
puts "==> calling #{klass.name}( #{address.pretty_print_inspect })"
|
386
|
+
obj = klass.at( address )
|
387
|
+
raise ArgumentError, "no #{klass.name} contract @ address #{address} found; sorry" if obj.nil?
|
388
|
+
puts " bingo! #{obj.class.name} (#{obj.class.parent_contracts}) contract found @ #{address}"
|
389
|
+
obj
|
390
|
+
end
|
391
|
+
end
|
392
|
+
end
|
393
|
+
end # module Generator
|
394
|
+
|
@@ -0,0 +1,126 @@
|
|
1
|
+
|
2
|
+
module Library
|
3
|
+
|
4
|
+
def self.extended(base)
|
5
|
+
puts "==> turn (extend) module >#{base.name}< into library"
|
6
|
+
base.include( Types ) ## make solidity types availbe (Address, Bytes, etc.)
|
7
|
+
base.extend( ClassMethods )
|
8
|
+
## todo/fix: add runtime and crypto methods too? why? why not?
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
def struct( class_name, **attributes )
|
14
|
+
typedclass = Types::Struct.new( class_name, scope: self, **attributes )
|
15
|
+
typedclass
|
16
|
+
end
|
17
|
+
|
18
|
+
def enum( class_name, *args )
|
19
|
+
typedclass = Types::Enum.new( class_name, *args, scope: self )
|
20
|
+
typedclass
|
21
|
+
end
|
22
|
+
|
23
|
+
####
|
24
|
+
# note: sig machinery with method_added MUST come last here
|
25
|
+
def sigs
|
26
|
+
@sigs ||= {}
|
27
|
+
end
|
28
|
+
|
29
|
+
def sigs_unnamed ## unnamed sigs stack
|
30
|
+
@sigs_unnamed ||= []
|
31
|
+
end
|
32
|
+
|
33
|
+
## ignore this methods;
|
34
|
+
## do NOT (auto-)generate wrapper method popping (unnamed) sig from stack!!!
|
35
|
+
def sigs_exclude
|
36
|
+
## note: always exclude globals
|
37
|
+
## get or can get changed via runtime modules (simulacrm) and such!!!
|
38
|
+
## e.g. msg.sender, block.timestamp, tx.origin, etc.
|
39
|
+
@sigs_exclude ||= [:block, :tx, :msg]
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
|
44
|
+
def sig( args=[], *options, returns: nil )
|
45
|
+
|
46
|
+
puts "[debug] add sig args: #{args.inspect}, options: #{options.inspect}, returns: #{returns.inspect}"
|
47
|
+
## use inputs for args) and outputs for returns - why? why not?
|
48
|
+
|
49
|
+
## check if include explicit visibility in options
|
50
|
+
if options.include?( :public ) ||
|
51
|
+
options.include?( :private ) ||
|
52
|
+
options.include?( :internal )
|
53
|
+
# do nothing / pass-along as is
|
54
|
+
else
|
55
|
+
# auto-add default up-front - :public or :internal if name starting with underscore (_)
|
56
|
+
visibility = name.start_with?( '_' ) ? :internal : :public
|
57
|
+
options.unshift( visibility )
|
58
|
+
end
|
59
|
+
|
60
|
+
####
|
61
|
+
# auto-convert args (inputs), returns (outputs) to type (defs)
|
62
|
+
args = args.map { |value| typeof( value ) }
|
63
|
+
|
64
|
+
###
|
65
|
+
## note: turn returns into an array - empty if nil, etc.
|
66
|
+
## always wrap into array
|
67
|
+
returns = if returns.nil?
|
68
|
+
[]
|
69
|
+
elsif returns.is_a?( ::Array )
|
70
|
+
returns
|
71
|
+
else ## assume single type
|
72
|
+
[returns]
|
73
|
+
end
|
74
|
+
|
75
|
+
returns = returns.map { |value| typeof( value ) }
|
76
|
+
|
77
|
+
|
78
|
+
@sigs_unnamed ||= []
|
79
|
+
@sigs_unnamed.push( { inputs: args,
|
80
|
+
outputs: returns,
|
81
|
+
options: options } )
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
|
86
|
+
def method_added( name )
|
87
|
+
|
88
|
+
if sigs_exclude.include?( name )
|
89
|
+
puts "--- skip method added hook >#{name}< - found in sigs exclude"
|
90
|
+
return ## do nothing;
|
91
|
+
else
|
92
|
+
puts "==> method added hook >#{name}<... processing..."
|
93
|
+
end
|
94
|
+
|
95
|
+
## pp name
|
96
|
+
## pp name.class.name
|
97
|
+
|
98
|
+
name = name.to_sym ## note: make sure name is ALWAYS a symbol
|
99
|
+
|
100
|
+
## note: method lookup via method needs an object / INSTANCE
|
101
|
+
## NOT working with class only!!!!
|
102
|
+
|
103
|
+
# m = method( name )
|
104
|
+
# pp m.name
|
105
|
+
# pp m.parameters
|
106
|
+
# pp m
|
107
|
+
|
108
|
+
raise "no unnamed sig(nature) on stack for method >#{name}< in module >#{self.name}<; sorry" if sigs_unnamed.size == 0
|
109
|
+
sig_unnamed = sigs_unnamed.pop
|
110
|
+
puts " using sig_unnamed: #{sig_unnamed.inspect}"
|
111
|
+
|
112
|
+
|
113
|
+
@sigs ||= {}
|
114
|
+
raise "duplicate method sig(nature) for method >#{name}< in module >#{self.name}<; sorry" if @sigs.has_key?( name )
|
115
|
+
@sigs[ name ] = sig_unnamed
|
116
|
+
|
117
|
+
|
118
|
+
|
119
|
+
puts " generate typed_library_function >#{name}<"
|
120
|
+
Generator.typed_library_function( self, name,
|
121
|
+
inputs: sig_unnamed[ :inputs ] )
|
122
|
+
|
123
|
+
puts "<== method added hook >#{name}< done."
|
124
|
+
end
|
125
|
+
end # module ClassMethods
|
126
|
+
end # module Library
|
@@ -0,0 +1,82 @@
|
|
1
|
+
## todo/ find a better name - why? why not?
|
2
|
+
## change to Blockchain/Chain/Node/Client/Runner/Ctx/Context or ???
|
3
|
+
class Runtime
|
4
|
+
|
5
|
+
|
6
|
+
class Message
|
7
|
+
attr_reader :sender
|
8
|
+
|
9
|
+
def sender=(address)
|
10
|
+
## note: allow literal and typed address
|
11
|
+
@sender = address.is_a?( Types::Address) ?
|
12
|
+
address : Types::Address.new( address )
|
13
|
+
end
|
14
|
+
end # class Message
|
15
|
+
|
16
|
+
|
17
|
+
class Tx
|
18
|
+
attr_reader :origin
|
19
|
+
def origin=(address)
|
20
|
+
@origin = address.is_a?( Types::Address ) ?
|
21
|
+
address : Types::Address.new( address )
|
22
|
+
end
|
23
|
+
|
24
|
+
def log_event( event )
|
25
|
+
puts "==> log_event:"
|
26
|
+
pp event
|
27
|
+
end
|
28
|
+
=begin
|
29
|
+
def log_event(event)
|
30
|
+
call_receipt.logs << event
|
31
|
+
event
|
32
|
+
end
|
33
|
+
=end
|
34
|
+
end # class Tx
|
35
|
+
|
36
|
+
|
37
|
+
class Block
|
38
|
+
attr_accessor :number, :timestamp
|
39
|
+
|
40
|
+
# def initialize(current_transaction)
|
41
|
+
# @current_transaction = current_transaction
|
42
|
+
# end
|
43
|
+
|
44
|
+
def blockhash( block_number )
|
45
|
+
##
|
46
|
+
# unless @current_transaction.ethscription.block_number == block_number.value # TODO FIX
|
47
|
+
# raise "Not implemented"
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# @current_transaction.ethscription.block_blockhash
|
51
|
+
|
52
|
+
# todo - check what ("dummy") to return here??
|
53
|
+
end
|
54
|
+
|
55
|
+
def number=(number)
|
56
|
+
@number = number.is_a?( Types::UInt ) ?
|
57
|
+
number : Types::UInt.new( number )
|
58
|
+
end
|
59
|
+
|
60
|
+
def timestamp=(timestamp)
|
61
|
+
@timestamp = timestamp.is_a?( Types::Timestamp ) ?
|
62
|
+
timestamp : Types::Timestamp.new( timestamp )
|
63
|
+
end
|
64
|
+
end # class Block
|
65
|
+
|
66
|
+
|
67
|
+
|
68
|
+
def self.msg() @msg ||= Message.new; end
|
69
|
+
def self.block() @block ||= Block.new; end
|
70
|
+
|
71
|
+
|
72
|
+
## use begin_transaction or
|
73
|
+
## new_transaction or __ - why? why not?
|
74
|
+
def self.start_transaction() @tx = Tx.new; end
|
75
|
+
def self.current_transaction() @tx ||= Tx.new; end
|
76
|
+
|
77
|
+
class << self
|
78
|
+
alias_method :start_tx, :start_transaction
|
79
|
+
alias_method :current_tx, :current_transaction
|
80
|
+
end
|
81
|
+
end # class Runtime
|
82
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Rubysol
|
2
|
+
module Module
|
3
|
+
module Lang
|
4
|
+
MAJOR = 0
|
5
|
+
MINOR = 1
|
6
|
+
PATCH = 0
|
7
|
+
VERSION = [MAJOR,MINOR,PATCH].join('.')
|
8
|
+
|
9
|
+
def self.version
|
10
|
+
VERSION
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.banner
|
14
|
+
"rubysol/#{VERSION} on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}] in (#{root})"
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.root
|
18
|
+
File.expand_path( File.dirname(File.dirname(File.dirname(File.dirname(__FILE__)))) )
|
19
|
+
end
|
20
|
+
|
21
|
+
end # module Lang
|
22
|
+
end # module Module
|
23
|
+
end # module Rubysol
|