abi_coder_rb 0.2.7 → 0.2.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ae222b87f68b45367128a4cd07c5792208ed75ef4838dcf64e414fd60366ddff
4
- data.tar.gz: 344f59862c11ffbbf6127a350cc5066093da24433914bad779f9b75e3e9e97e1
3
+ metadata.gz: 2446e20c68206c39fddd2cc887136d0188a74283c82240f95d9fd3d7fce19d15
4
+ data.tar.gz: '0158a5505f945dc0655a1c80cf8722ff4d15610bf2e027fea15cd21de917aa1c'
5
5
  SHA512:
6
- metadata.gz: 92c783fb486a02c1df160acaf87c773ca9d2ef7e6637acdc441c69edf92c135f216d22708af285a0ebc02c3711c68f61b7d64cbbece681425c7fb82edee5ea16
7
- data.tar.gz: a5ac737f20cb1b66128e57ab27786b40d36e646a7836baa2b374339ca56825c4c486cf08e615fadbe81ddb6cd96224c80025040d586e6648c69c72a6e92b0d1f
6
+ metadata.gz: 26d7209d606865c01c539a3e5611e25477ce8ba3f2f1e9e54eb0c879ac510ca047979c066905a430fceab5f23f18b8c680b594341834a900d03e983d2241be03
7
+ data.tar.gz: cac0312067c262e52808ff92b7b36e9a85e87660e306f1e13205a19eb1107bb1a9fb423b2fd6641949c0e4e130b3bb20adb114c1d0fa83f00b5e81923173b2b3
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- abi_coder_rb (0.2.7)
4
+ abi_coder_rb (0.2.8)
5
5
  activesupport
6
6
 
7
7
  GEM
@@ -1,16 +1,25 @@
1
1
  module AbiCoderRb
2
- def encode_array(type, args)
2
+ def encode_array(type, args, packed = false)
3
3
  raise ArgumentError, "arg must be an array" unless args.is_a?(::Array)
4
4
 
5
+ _encode_array(type: type, args: args, packed: packed)
6
+ end
7
+
8
+ private
9
+
10
+ def _encode_array(type:, args:, packed: false)
5
11
  head = "".b
6
- tail = "".b # 使用二进制字符串
12
+ tail = "".b
7
13
 
8
- head += encode_uint256(args.size)
14
+ # 数组长度
15
+ head += encode_uint256(args.size) if type.is_a?(Array) && !packed
9
16
 
10
17
  subtype = type.subtype
11
18
  args.each do |arg|
12
19
  if subtype.dynamic?
13
- head += encode_uint256(32 * args.size + tail.size)
20
+ raise "#{type.class} with dynamic inner type is not supported in packed mode" if packed
21
+
22
+ head += encode_uint256(32 * args.size + tail.size) # 当前数据的位置指针
14
23
  tail += encode_type(subtype, arg)
15
24
  else
16
25
  head += encode_type(subtype, arg)
@@ -1,22 +1,11 @@
1
1
  module AbiCoderRb
2
- def encode_fixed_array(type, args)
2
+ def encode_fixed_array(type, args, packed = false)
3
3
  raise ArgumentError, "arg must be an array" unless args.is_a?(::Array)
4
4
  raise ArgumentError, "Wrong array size: found #{args.size}, expecting #{type.dim}" unless args.size == type.dim
5
5
 
6
6
  # fixed_array,是没有元素数量的编码de
7
7
  # 如果内部类型是静态的,就是一个一个元素编码后加起来。
8
8
  # 如果内部类型是动态的,先用位置一个一个编码加起来,然后是元素本体
9
- subtype = type.subtype
10
- if subtype.dynamic?
11
- head = "".b
12
- tail = "".b
13
- args.each do |arg|
14
- head += encode_uint256(32 * args.size + tail.size)
15
- tail += encode_type(subtype, arg)
16
- end
17
- head + tail
18
- else
19
- args.map { |arg| encode_type(type.subtype, arg) }.join
20
- end
9
+ _encode_array(type: type, args: args, packed: packed)
21
10
  end
22
11
  end
@@ -1,55 +1,67 @@
1
1
  module AbiCoderRb
2
- def encode_primitive_type(type, arg)
2
+ def encode_primitive_type(type, arg, packed = false)
3
3
  arg = before_encoding_action.call(type.format, arg) if before_encoding_action
4
4
  # 根据类型选择相应的编码方法
5
5
  case type
6
6
  when Uint
7
7
  # NOTE: for now size in bits always required
8
- encode_uint(arg, type.bits)
8
+ encode_uint(arg, type.bits, packed)
9
9
  when Int
10
10
  # NOTE: for now size in bits always required
11
- encode_int(arg, type.bits)
11
+ encode_int(arg, type.bits, packed)
12
12
  when Bool
13
- encode_bool(arg)
13
+ encode_bool(arg, packed)
14
14
  when String
15
- encode_string(arg)
15
+ encode_string(arg, packed)
16
16
  when FixedBytes
17
- encode_bytes(arg, type.length)
17
+ encode_bytes(arg, length: type.length, packed: packed)
18
18
  when Bytes
19
- encode_bytes(arg)
19
+ encode_bytes(arg, packed: packed)
20
20
  when Address
21
- encode_address(arg)
21
+ encode_address(arg, packed)
22
22
  else
23
23
  raise EncodingError, "Unknown type: #{type}"
24
24
  end
25
25
  end
26
26
 
27
- def encode_uint(arg, bits)
27
+ def encode_uint(arg, bits, packed = false)
28
28
  raise ArgumentError, "arg is not integer: #{arg}" unless arg.is_a?(Integer)
29
29
  raise ValueOutOfBounds, arg unless arg >= 0 && arg < 2**bits
30
30
 
31
- lpad_int(arg)
31
+ if packed
32
+ lpad_int(arg, bits / 8)
33
+ else
34
+ lpad_int(arg)
35
+ end
32
36
  end
33
37
 
34
38
  def encode_uint256(arg)
35
39
  encode_uint(arg, 256)
36
40
  end
37
41
 
38
- def encode_int(arg, _bits)
42
+ def encode_int(arg, bits, packed = false)
39
43
  ## raise EncodingError or ArgumentError - why? why not?
40
44
  raise ArgumentError, "arg is not integer: #{arg}" unless arg.is_a?(Integer)
41
45
 
42
- hex_to_bin(int_to_abi_signed_256bit(arg))
46
+ if packed
47
+ hex_to_bin(int_to_abi_signed(arg, bits))
48
+ else
49
+ hex_to_bin(int_to_abi_signed_256bit(arg))
50
+ end
43
51
  end
44
52
 
45
- def encode_bool(arg)
53
+ def encode_bool(arg, packed = false)
46
54
  ## raise EncodingError or ArgumentError - why? why not?
47
55
  raise ArgumentError, "arg is not bool: #{arg}" unless arg.is_a?(TrueClass) || arg.is_a?(FalseClass)
48
56
 
49
- lpad(arg ? BYTE_ONE : BYTE_ZERO) ## was lpad_int( arg ? 1 : 0 )
57
+ if packed
58
+ arg ? BYTE_ONE : BYTE_ZERO
59
+ else
60
+ lpad(arg ? BYTE_ONE : BYTE_ZERO) ## was lpad_int( arg ? 1 : 0 )
61
+ end
50
62
  end
51
63
 
52
- def encode_string(arg)
64
+ def encode_string(arg, packed = false)
53
65
  ## raise EncodingError or ArgumentError - why? why not?
54
66
  raise EncodingError, "Expecting string: #{arg}" unless arg.is_a?(::String)
55
67
 
@@ -57,12 +69,16 @@ module AbiCoderRb
57
69
 
58
70
  raise ValueOutOfBounds, "Integer invalid or out of range: #{arg.size}" if arg.size > UINT_MAX
59
71
 
60
- size = lpad_int(arg.size)
61
- value = rpad(arg, ceil32(arg.size))
62
- size + value
72
+ if packed
73
+ arg
74
+ else
75
+ size = lpad_int(arg.size)
76
+ value = rpad(arg, ceil32(arg.size))
77
+ size + value
78
+ end
63
79
  end
64
80
 
65
- def encode_bytes(arg, length = nil)
81
+ def encode_bytes(arg, length: nil, packed: false)
66
82
  ## raise EncodingError or ArgumentError - why? why not?
67
83
  raise EncodingError, "Expecting string: #{arg}" unless arg.is_a?(::String)
68
84
 
@@ -72,29 +88,36 @@ module AbiCoderRb
72
88
  raise ValueOutOfBounds, "invalid bytes length #{arg.size}, should be #{length}" if arg.size > length
73
89
  raise ValueOutOfBounds, "invalid bytes length #{length}" if length < 0 || length > 32
74
90
 
75
- rpad(arg)
91
+ packed ? arg : rpad(arg)
76
92
  else # variable length type (if length is nil)
77
93
  raise ValueOutOfBounds, "Integer invalid or out of range: #{arg.size}" if arg.size > UINT_MAX
78
94
 
79
- size = lpad_int(arg.size)
80
- value = rpad(arg, ceil32(arg.size))
81
- size + value
95
+ if packed
96
+ arg
97
+ else
98
+ size = lpad_int(arg.size)
99
+ value = rpad(arg, ceil32(arg.size))
100
+ size + value
101
+ end
82
102
  end
83
103
  end
84
104
 
85
- def encode_address(arg)
105
+ def encode_address(arg, packed = false)
86
106
  if arg.is_a?(Integer)
87
- lpad_int(arg)
88
- elsif arg.size == 20
89
- ## note: make sure encoding is always binary!!!
90
- arg = arg.b if arg.encoding != Encoding::BINARY
91
- lpad(arg)
92
- elsif arg.size == 40
93
- lpad_hex(arg)
94
- elsif arg.size == 42 && arg[0, 2] == "0x" ## todo/fix: allow 0X too - why? why not?
95
- lpad_hex(arg[2..-1])
96
- else
97
- raise EncodingError, "Could not parse address: #{arg}"
107
+ packed ? lpad_int(arg, 20) : lpad_int(arg)
108
+ elsif arg.is_a?(::String)
109
+ if arg.size == 20
110
+ ## note: make sure encoding is always binary!!!
111
+ arg = arg.b if arg.encoding != Encoding::BINARY
112
+ packed ? arg : lpad(arg)
113
+ elsif arg.size == 40
114
+ packed ? hex_to_bin(arg) : lpad_hex(arg)
115
+ elsif arg.size == 42 && arg[0, 2] == "0x" ## todo/fix: allow 0X too - why? why not?
116
+ arg = arg[2..-1] ## cut-off leading 0x
117
+ packed ? hex_to_bin(arg) : lpad_hex(arg)
118
+ else
119
+ raise EncodingError, "Could not parse address: #{arg}"
120
+ end
98
121
  end
99
122
  end
100
123
  end
@@ -1,11 +1,13 @@
1
1
  module AbiCoderRb
2
- def encode_tuple(tuple, args)
3
- encode_types(tuple.types, args)
2
+ def encode_tuple(tuple, args, packed = false)
3
+ raise "#{tuple.class} with multi inner types is not supported in packed mode" if packed && tuple.types.size > 1
4
+
5
+ encode_types(tuple.types, args, packed)
4
6
  end
5
7
 
6
8
  private
7
9
 
8
- def encode_types(types, args)
10
+ def encode_types(types, args, packed = false)
9
11
  raise ArgumentError, "args must be an array" unless args.is_a?(::Array)
10
12
 
11
13
  unless args.size == types.size
@@ -17,18 +19,18 @@ module AbiCoderRb
17
19
  head_size = types.map { |type| type.size || 32 }.sum
18
20
 
19
21
  # 初始化头部和尾部
20
- head = "".b
22
+ head = "".b # 如果是动态类型,头部是指针;如果是静态类型,头部是数据
21
23
  tail = "".b # 使用二进制字符串
22
24
 
23
25
  # 遍历类型并编码
24
26
  types.each_with_index do |type, i|
25
- if type.dynamic?
27
+ if !type.dynamic? || packed
28
+ # 只更新头部,也就是数据
29
+ head += encode_type(type, args[i], packed)
30
+ else
26
31
  # 动态类型: 更新头部和尾部
27
32
  head += encode_uint256(head_size + tail.size)
28
33
  tail += encode_type(type, args[i])
29
- else
30
- # 静态类型: 只更新头部
31
- head += encode_type(type, args[i])
32
34
  end
33
35
  end
34
36
 
@@ -5,25 +5,38 @@ require_relative "encode/encode_primitive_type"
5
5
 
6
6
  module AbiCoderRb
7
7
  # returns byte array
8
- def encode(type, value)
9
- # TODO: more checks?
10
- raise EncodingError, "Value can not be nil" if value.nil?
8
+ def encode(typestr_or_typestrs, value_or_values, packed = false)
9
+ if typestr_or_typestrs.is_a?(::Array)
10
+ raise EncodingError, "values should be an array" unless value_or_values.is_a?(::Array)
11
11
 
12
- parsed = Type.parse(type)
13
- encode_type(parsed, value)
12
+ typestrs = typestr_or_typestrs
13
+ values = value_or_values
14
+ typestrs.map.with_index do |typestr, i|
15
+ value = values[i]
16
+ encode(typestr, value, packed)
17
+ end.join
18
+ else
19
+ typestr = typestr_or_typestrs
20
+ value = value_or_values
21
+ # TODO: more checks?
22
+ raise EncodingError, "Value can not be nil" if value.nil?
23
+
24
+ parsed = Type.parse(typestr)
25
+ encode_type(parsed, value, packed)
26
+ end
14
27
  end
15
28
 
16
29
  private
17
30
 
18
- def encode_type(type, value)
31
+ def encode_type(type, value, packed = false)
19
32
  if type.is_a?(Tuple)
20
- encode_tuple(type, value)
33
+ encode_tuple(type, value, packed)
21
34
  elsif type.is_a?(Array)
22
- encode_array(type, value)
35
+ encode_array(type, value, packed)
23
36
  elsif type.is_a?(FixedArray)
24
- encode_fixed_array(type, value)
37
+ encode_fixed_array(type, value, packed)
25
38
  else
26
- encode_primitive_type(type, value)
39
+ encode_primitive_type(type, value, packed)
27
40
  end
28
41
  end
29
42
  end
@@ -27,15 +27,14 @@ module AbiCoderRb
27
27
  ## rename to lpad32 or such - why? why not?
28
28
  # example:
29
29
  # lpad("hello", 'x', 10) => "xxxxxxhello"
30
- def lpad(bin) ## note: same as builtin String#rjust !!!
31
- l = 32 # NOTE: default l word is 32 bytes
30
+ def lpad(bin, l = 32) ## note: same as builtin String#rjust !!!
32
31
  return bin if bin.size >= l
33
32
 
34
33
  BYTE_ZERO * (l - bin.size) + bin
35
34
  end
36
35
 
37
36
  ## rename to lpad32_int or such - why? why not?
38
- def lpad_int(n)
37
+ def lpad_int(n, l = 32)
39
38
  unless n.is_a?(Integer) && n >= 0 && n <= UINT_MAX
40
39
  raise ArgumentError,
41
40
  "Integer invalid or out of range: #{n}"
@@ -45,7 +44,7 @@ module AbiCoderRb
45
44
  hex = "0#{hex}" if hex.length.odd? # wasm, no .odd?
46
45
  bin = hex_to_bin(hex)
47
46
 
48
- lpad(bin)
47
+ lpad(bin, l)
49
48
  end
50
49
 
51
50
  ## rename to lpad32_hex or such - why? why not?
@@ -62,6 +61,18 @@ module AbiCoderRb
62
61
  x % 32 == 0 ? x : (x + 32 - x % 32)
63
62
  end
64
63
 
64
+ def int_to_abi_signed(value, bits)
65
+ min = -2**(bits - 1)
66
+ max = 2**(bits - 1) - 1
67
+ raise "Value out of range" if value < min || value > max
68
+
69
+ value = (1 << bits) + value if value < 0
70
+
71
+ hex_str = value.to_s(16)
72
+
73
+ hex_str.rjust(bits / 4, "0")
74
+ end
75
+
65
76
  def int_to_abi_signed_256bit(value)
66
77
  # 确保值在256位有符号整数范围内
67
78
  min = -2**255
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AbiCoderRb
4
- VERSION = "0.2.7"
4
+ VERSION = "0.2.8"
5
5
  end
data/tea.yaml ADDED
@@ -0,0 +1,6 @@
1
+ # https://tea.xyz/what-is-this-file
2
+ ---
3
+ version: 1.0.0
4
+ codeOwners:
5
+ - '0x08D5966A5226C74f59407bC3aB3a63a68488Da1D'
6
+ quorum: 1
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: abi_coder_rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.7
4
+ version: 0.2.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aki Wu
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-02-26 00:00:00.000000000 Z
11
+ date: 2024-04-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -74,6 +74,7 @@ files:
74
74
  - lib/abi_coder_rb/version.rb
75
75
  - lib/periphery/event_decoder.rb
76
76
  - sig/abi_coder_rb.rbs
77
+ - tea.yaml
77
78
  homepage: https://github.com/wuminzhe/abi_coder_rb
78
79
  licenses:
79
80
  - MIT