ton-sdk-ruby 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f7fff8c0e9e038b0aacb1c5c68c3c39c1bbc293815fc296a01927ccf9798c0a7
4
+ data.tar.gz: 69d92e29e24377da266692e0a45656ed97e79bd4507d0e9b67807dd7b588b4b7
5
+ SHA512:
6
+ metadata.gz: 91a850a5872fe1dd7d9737239b5610402361e8b29b3deb210c9bdc5221982015a42168e55f16076672c0fe599d4a11f94f8d3b2c04e4b41720e622e8c6869089
7
+ data.tar.gz: 04b2344e2377b1cdf507559eae021784ad04048646236b2df40a73a538350ac72482dd148da1d4993d2f964bd369ea5aad034e6f6e3f487e8adcd8fdefca9b3b
data/bin/ton-sdk-ruby ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ GEM_DIR = File.dirname(__FILE__) + '/..'
4
+
5
+ if ARGV[0] == 'start'
6
+ p 'start'
7
+ end
@@ -0,0 +1,169 @@
1
+ module TonSdkRuby
2
+ class BitArray < Array
3
+
4
+ attr_accessor :read_cursor
5
+
6
+ def initialize(size: 0, value: false)
7
+ @read_cursor = 0
8
+ super(size) { |_| get_value(value) }
9
+ end
10
+
11
+ def to_s
12
+ self.map { |e| e ? 1 : 0 }.join('')
13
+ end
14
+
15
+ def show_cursor
16
+ self.map { |e| e ? 1 : 0 }.join('').insert(cursor, '⏶')
17
+ end
18
+
19
+ def set_bit!(index: nil, value: nil)
20
+ raise "Wrong index #{index}. Out of bounds array" if index > size || index < 0
21
+ self[index] = get_value(value)
22
+ end
23
+
24
+ def get_bit(index: nil)
25
+ raise "Wrong index #{index}. Out of bounds array" if index > size - 1 || index < 0
26
+ self[index]
27
+ end
28
+
29
+ def set_byte!(index: nil, value: nil)
30
+ set_number!(index: index, value: value, size: 8)
31
+ end
32
+
33
+ def get_byte(index: nil)
34
+ raise "Wrong index #{index}. Out of bounds array" if index > size - 1 || index < 0
35
+ self[index..index+7].map { |e| e.to_i}.join('').to_i(2)
36
+ end
37
+
38
+ def store_uint!(value: nil, size: nil)
39
+ store_number!(value: value, size: size)
40
+ end
41
+
42
+ def store_sint!(value: nil, size: nil)
43
+ # i.e. signed int and one first bit reserved for sign size = (size - 1)
44
+ # and restrict for max value = value >= (1 << size - 1)
45
+ max_sint = (1 << size - 1)
46
+ raise "Wrong value #{value}" if value < -max_sint || value >= max_sint
47
+ set_number!(value: value, size: size)
48
+ end
49
+
50
+ def read_uint!(bits_amount: nil)
51
+ raise "Wrong bits_amount #{bits_amount}" if bits_amount > self.size
52
+ bits_string = ""
53
+ (read_cursor + bits_amount).times do |index|
54
+ bits_string << self[index] ? '1' : '0'
55
+ @read_cursor = index
56
+ end
57
+ bits_string.to_i(2)
58
+ end
59
+
60
+ def read_sint!(bits_amount: nil)
61
+ raise "Wrong bits_amount #{bits_amount}" if bits_amount > self.size
62
+ negative_sign = false
63
+ bits_string = ""
64
+ (read_cursor + bits_amount).times do |index|
65
+ bits_string << (self[index] ? '1' : '0')
66
+ @read_cursor = index
67
+ end
68
+ calc_signed_integer(bits_string: bits_string)
69
+ end
70
+
71
+
72
+ private
73
+
74
+ # 00001101 -> set as 00001101
75
+ def set_number!(index: nil, value: nil, size: nil)
76
+ index = index ? index : self.size
77
+ raise "Wrong index #{index}. Out of bounds array" if index > self.size || index < 0
78
+ # if size = 4 bit and max value in bits = 1111, then error (value >= 10000) == (value >= (1 << 4))
79
+ raise "Wrong value #{value}" if value >= (1 << size)
80
+ size.times do |i|
81
+ bit_index = size - i - 1
82
+ # if size = 4 bit and value in bots = 1000, then (1000 >> (4 - 1)) == 0001
83
+ most_significant_bit = (value >> bit_index)
84
+ # p most_significant_bit.to_s(2)
85
+ # & (AND) 101 & 1 == 001 or 101 & 001 == 001
86
+ bit = (most_significant_bit & 1) == 1
87
+ set_bit!(index: index, value: bit)
88
+ index += 1
89
+ end
90
+ self
91
+ end
92
+
93
+ # # 00001101 -> set as 00001101
94
+ # def store_number!(index: nil, value: nil, size: nil)
95
+ # @cursor = index ? index : cursor
96
+ # raise "Wrong index #{cursor}. Out of bounds array" if cursor > self.size || cursor < 0
97
+ # # if size = 4 bit and max value in bits = 1111, then error (value >= 10000) == (value >= (1 << 4))
98
+ # raise "Wrong value #{value}" if value < 0 || value >= (1 << size)
99
+ # size.times do |i|
100
+ # bit_index = size - i - 1
101
+ # # if size = 4 bit and value in bots = 1000, then (1000 >> (4 - 1)) == 0001
102
+ # most_significant_bit = (value >> bit_index)
103
+ # # p most_significant_bit.to_s(2)
104
+ # # & (AND) 101 & 1 == 001 or 101 & 001 == 001
105
+ # bit = (most_significant_bit & 1) == 1
106
+ # set_bit!(index: cursor, value: bit)
107
+ # @cursor += 1
108
+ # end
109
+ # self
110
+ # end
111
+
112
+ def calc_signed_integer(bits_string: nil)
113
+ value = bits_string.to_i(2)
114
+ index = bits_string.size - 1
115
+ (value & ~(1 << index)) - (value & (1 << index))
116
+ end
117
+
118
+ def get_value(val)
119
+ if val.class == TrueClass
120
+ val
121
+ elsif val.class == FalseClass
122
+ val
123
+ elsif val.class == String
124
+ val == "1" ? true : false
125
+ elsif val.class == Integer
126
+ val == 0 ? false : true
127
+ else
128
+ raise "Wrong data type of #{val}"
129
+ end
130
+ end
131
+ end
132
+ end
133
+
134
+ class FalseClass
135
+ def to_i
136
+ 0
137
+ end
138
+ end
139
+
140
+ class TrueClass
141
+ def to_i
142
+ 1
143
+ end
144
+ end
145
+
146
+
147
+
148
+
149
+
150
+
151
+
152
+
153
+
154
+
155
+
156
+
157
+
158
+
159
+
160
+
161
+
162
+
163
+
164
+
165
+
166
+
167
+
168
+
169
+
@@ -0,0 +1,261 @@
1
+ module TonSdkRuby
2
+ class Builder
3
+ attr_reader :size, :refs, :bits
4
+
5
+ def bytes
6
+ bits_to_bytes(@bits)
7
+ end
8
+
9
+ def remainder
10
+ size - bits.length
11
+ end
12
+
13
+ def initialize(size = 1023)
14
+ @size = size
15
+ @bits = []
16
+ @refs = []
17
+ end
18
+
19
+ def store_slice(slice)
20
+ require_type('slice', slice, Slice)
21
+ Builder.check_slice_type(slice)
22
+
23
+ bits = slice.bits
24
+ refs = slice.refs
25
+
26
+ check_bits_overflow(bits.length)
27
+ check_refs_overflow(refs.length)
28
+ store_bits(bits)
29
+
30
+ refs.each { |ref| store_ref(ref) }
31
+
32
+ self
33
+ end
34
+
35
+ def store_ref(ref)
36
+ require_type('ref', ref, Cell)
37
+ Builder.check_refs_type([ref])
38
+ check_refs_overflow(1)
39
+ @refs.push(ref)
40
+
41
+ self
42
+ end
43
+
44
+ def store_maybe_ref(ref = nil)
45
+ require_type('ref', ref, Cell) if ref
46
+ return store_bit(0) unless ref
47
+ store_bit(1).store_ref(ref)
48
+ end
49
+
50
+ def store_refs(refs)
51
+ Builder.check_refs_type(refs)
52
+ check_refs_overflow(refs.length)
53
+ @refs.push(*refs)
54
+
55
+ self
56
+ end
57
+
58
+ def store_bit(bit)
59
+ bit = bit.to_i
60
+ value = Builder.check_bits_type_and_normalize([bit])
61
+ check_bits_overflow(1)
62
+ @bits += value
63
+
64
+ self
65
+ end
66
+
67
+ def store_bits(bits)
68
+ require_type('bits', bits, Array)
69
+ require_type('bit', bits[0], Integer) if bits.size > 0
70
+ value = Builder.check_bits_type_and_normalize(bits)
71
+ check_bits_overflow(value.length)
72
+ @bits += value
73
+
74
+ self
75
+ end
76
+
77
+ def store_int(value, size)
78
+ int = value.is_a?(Integer) ? value : value.to_i
79
+ int_bits = 1 << (size - 1)
80
+
81
+ if int < -int_bits || int >= int_bits
82
+ raise StandardError.new("Builder: can't store an Int, because its value allocates more space than provided.")
83
+ end
84
+
85
+ store_number(int, size)
86
+
87
+ self
88
+ end
89
+
90
+ def store_uint(value, size)
91
+ uint = value.is_a?(Integer) ? value : value.to_i
92
+ if uint < 0 || uint >= (1 << size)
93
+ raise StandardError.new("Builder: can't store an UInt, because its value allocates more space than provided.")
94
+ end
95
+
96
+ store_number(uint, size)
97
+
98
+ self
99
+ end
100
+
101
+ def store_var_int(value, length)
102
+ int = value.is_a?(Integer) ? value : value.to_i
103
+ size = (Math.log2(length)).ceil
104
+ size_bytes = (int.to_s(2).length.to_f / 8).ceil
105
+ size_bits = size_bytes * 8
106
+
107
+ check_bits_overflow(size + size_bits)
108
+
109
+ if int == 0
110
+ store_uint(0, size)
111
+ else
112
+ store_uint(size_bytes, size).store_int(value, size_bits)
113
+ end
114
+
115
+ self
116
+ end
117
+
118
+ def store_var_uint(value, length)
119
+ uint = value.is_a?(Integer) ? value : value.to_i
120
+ size = (Math.log2(length)).ceil
121
+ size_bytes = (uint.to_s(2).length.to_f / 8).ceil
122
+ size_bits = size_bytes * 8
123
+
124
+ check_bits_overflow(size + size_bits)
125
+
126
+ if uint == 0
127
+ store_uint(0, size)
128
+ else
129
+ store_uint(size_bytes, size).store_uint(value, size_bits)
130
+ end
131
+
132
+ self
133
+ end
134
+
135
+ def store_bytes(value)
136
+ require_type('value', value, Array)
137
+ check_bits_overflow(value.size * 8)
138
+ value.each { |byte| store_uint(byte, 8) }
139
+
140
+ self
141
+ end
142
+
143
+ def store_string(value)
144
+ require_type('value', value, String)
145
+ bytes = string_to_bytes(value)
146
+
147
+ store_bytes(bytes)
148
+
149
+ self
150
+ end
151
+
152
+ def store_address(address = nil)
153
+ require_type('address', address, Address) if address
154
+ if address.nil?
155
+ store_bits([0, 0])
156
+ return self
157
+ end
158
+
159
+ anycast = 0
160
+ address_bits_size = 2 + 1 + 8 + 256
161
+
162
+ Builder.check_address_type(address)
163
+ check_bits_overflow(address_bits_size)
164
+ store_bits([1, 0])
165
+ store_uint(anycast, 1)
166
+ store_int(address.workchain, 8)
167
+ store_bytes(address.hash)
168
+
169
+ self
170
+ end
171
+
172
+ def store_coins(coins)
173
+ require_type('coins', coins, Coins)
174
+ if coins.negative?
175
+ raise 'Builder: coins value can\'t be negative.'
176
+ end
177
+
178
+ nano = coins.to_nano
179
+
180
+ # https://github.com/ton-blockchain/ton/blob/master/crypto/block/block.tlb#L116
181
+ store_var_uint(nano, 16)
182
+
183
+ self
184
+ end
185
+
186
+ def store_dict(hashmap = nil)
187
+ return store_bit(0) unless hashmap
188
+
189
+ slice = hashmap.cell.parse
190
+ store_slice(slice)
191
+
192
+ self
193
+ end
194
+
195
+ def clone
196
+ data = Builder.new(size)
197
+
198
+ # Use getters to get copy of arrays
199
+ data.store_bits(bits)
200
+ refs.each { |ref| data.store_ref(ref) }
201
+
202
+ data
203
+ end
204
+
205
+ def cell(type = CellType::Ordinary)
206
+ # Use getters to get copies of arrays
207
+ cell = Cell.new(bits: bits, refs: refs, type: type)
208
+
209
+ cell
210
+ end
211
+
212
+ private
213
+
214
+ def self.check_slice_type(slice)
215
+ unless slice.is_a?(Slice)
216
+ raise StandardError, "Builder: can't store slice, because it's type is not a Slice."
217
+ end
218
+ end
219
+
220
+ def self.check_address_type(address)
221
+ unless address.is_a?(Address)
222
+ raise StandardError, "Builder: can't store address, because it's type is not an Address."
223
+ end
224
+ end
225
+
226
+ def check_bits_overflow(size)
227
+ if size > remainder
228
+ raise StandardError.new("Builder: bits overflow. Can't add #{size} bits. Only #{remainder} bits left.")
229
+ end
230
+ end
231
+
232
+ def self.check_refs_type(refs)
233
+ unless refs.all? { |cell| cell.is_a?(Cell) }
234
+ raise StandardError, "Builder: can't store ref, because it's type is not a Cell."
235
+ end
236
+ end
237
+
238
+ def self.check_bits_type_and_normalize(bits)
239
+ bits.map do |bit|
240
+ unless [0, 1, false, true].include?(bit)
241
+ raise StandardError.new("Builder: can't store bit, because its type is not a Number or Boolean, or value doesn't equal 0 nor 1.")
242
+ end
243
+
244
+ bit == 1 || bit == true ? 1 : 0
245
+ end
246
+ end
247
+
248
+ def check_refs_overflow(size)
249
+ if size > (4 - @refs.length)
250
+ raise StandardError.new("Builder: refs overflow. Can't add #{size} refs. Only #{4 - @refs.length} refs left.")
251
+ end
252
+ end
253
+
254
+ def store_number(value, size)
255
+ bits = Array.new(size) { |i| ((value >> i) & 1) == 1 ? 1 : 0 }.reverse
256
+ store_bits(bits)
257
+ self
258
+ end
259
+
260
+ end
261
+ end