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 +7 -0
- data/bin/ton-sdk-ruby +7 -0
- data/lib/ton-sdk-ruby/bit_array/bit_array.rb +169 -0
- data/lib/ton-sdk-ruby/boc/builder.rb +261 -0
- data/lib/ton-sdk-ruby/boc/cell.rb +362 -0
- data/lib/ton-sdk-ruby/boc/hashmap.rb +398 -0
- data/lib/ton-sdk-ruby/boc/mask.rb +46 -0
- data/lib/ton-sdk-ruby/boc/serializer.rb +428 -0
- data/lib/ton-sdk-ruby/boc/slice.rb +335 -0
- data/lib/ton-sdk-ruby/johnny_mnemonic/ton_mnemonic.rb +144 -0
- data/lib/ton-sdk-ruby/johnny_mnemonic/utils.rb +40 -0
- data/lib/ton-sdk-ruby/johnny_mnemonic/words/english.json +2050 -0
- data/lib/ton-sdk-ruby/providers/provider.rb +41 -0
- data/lib/ton-sdk-ruby/providers/toncenter.rb +71 -0
- data/lib/ton-sdk-ruby/types/address.rb +203 -0
- data/lib/ton-sdk-ruby/types/block.rb +388 -0
- data/lib/ton-sdk-ruby/types/coins.rb +188 -0
- data/lib/ton-sdk-ruby/utils/bits.rb +25 -0
- data/lib/ton-sdk-ruby/utils/checksum.rb +46 -0
- data/lib/ton-sdk-ruby/utils/hash.rb +15 -0
- data/lib/ton-sdk-ruby/utils/helpers.rb +161 -0
- data/lib/ton-sdk-ruby/utils/numbers.rb +42 -0
- data/lib/ton-sdk-ruby/version.rb +4 -0
- data/lib/ton-sdk-ruby.rb +29 -0
- metadata +137 -0
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,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
|