xrpl-ruby 0.0.1 → 0.2.4

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: fe5e22e400d255c2c834133232433c9c8a513d3c1fba93dc06f46e18d90b1c3d
4
- data.tar.gz: 0512e71a026bef8893fa8855c702ccdb09e18ce219f286c3cea33b2b5d477e38
3
+ metadata.gz: 6895a3507b4f4d76bb12cd9c150c2f395a35e44146ee45dea5579076c780fc56
4
+ data.tar.gz: a641537d7f0ce171f7ddf5380b0e3ab0d396a5a2ec5f884e090fe12ba1b49eb6
5
5
  SHA512:
6
- metadata.gz: c7b52d5c38ead6d5d5910cbd5132be7ea783e24b8c21f452d56138c9e806d016d9186d3213913372b3d5cb8d1c0bdca9c6acf8f7c9de1c5416571bf9d0873b2e
7
- data.tar.gz: '00914805ec76c9fe7a2b475881efde3408f6f609f3ffaedc30d21fe845d3dd247051158561c29fe69af688238d4c86fb5a4124747c806bfe6a64f4c31a244020'
6
+ metadata.gz: 453610629153989c93ff0ac3e504dfd4fa8fb90ccc3adbbac104522dee5b03192a7a6ba1d4206424f17174080ece7b897fc02b5bd513432979269df0dba7768b
7
+ data.tar.gz: ca5696e3df36e747e395f351043223d81a7445970db5d8b40d3cd398f9a1c70bff3495f926dea412920bb81cdfdbb78a825c9b3afa13e6b381ba84ea04ecfec4
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AddressCodec
4
+
5
+ class AddressCodec < XrpCodec
6
+
7
+ PREFIX_BYTES = {
8
+ main: [0x05, 0x44],
9
+ test: [0x04, 0x93]
10
+ }
11
+
12
+ MAX_32_BIT_UNSIGNED_INT = 4294967295
13
+
14
+ def classic_address_to_x_address(classic_address, tag, test)
15
+ account_id = decode_account_id(classic_address)
16
+ encode_x_address(account_id, tag, test)
17
+ end
18
+
19
+ def encode_x_address(account_id, tag, test)
20
+ if account_id.length != 20
21
+ # RIPEMD160 -> 160 Bits = 20 Bytes
22
+ raise 'Account ID must be 20 bytes'
23
+ end
24
+ if tag != false && tag > MAX_32_BIT_UNSIGNED_INT
25
+ raise 'Invalid tag'
26
+ end
27
+ the_tag = tag || 0
28
+ flag = tag == false || tag.nil? ? 0 : 1
29
+
30
+ bytes = concat_args(
31
+ test ? PREFIX_BYTES[:test] : PREFIX_BYTES[:main],
32
+ account_id,
33
+ [
34
+ flag,
35
+ the_tag & 0xff,
36
+ (the_tag >> 8) & 0xff,
37
+ (the_tag >> 16) & 0xff,
38
+ (the_tag >> 24) & 0xff,
39
+ 0,
40
+ 0,
41
+ 0,
42
+ 0
43
+ ]
44
+ )
45
+
46
+ encode_checked(bytes)
47
+ end
48
+
49
+ def x_address_to_classic_address(x_address)
50
+ decoded = decode_x_address(x_address)
51
+ account_id = decoded[:account_id]
52
+ tag = decoded[:tag]
53
+ test = decoded[:test]
54
+ classic_address = encode_account_id(account_id)
55
+ {
56
+ classic_address: classic_address,
57
+ tag: tag,
58
+ test: test
59
+ }
60
+ end
61
+
62
+ def decode_x_address(x_address)
63
+ decoded = decode_checked(x_address)
64
+ test = is_uint8_array_for_test_address(decoded)
65
+ account_id = decoded[2, 20]
66
+ tag = tag_from_uint8_array(decoded)
67
+ {
68
+ account_id: account_id,
69
+ tag: tag,
70
+ test: test
71
+ }
72
+ end
73
+
74
+ def valid_x_address?(x_address)
75
+ begin
76
+ decode_x_address(x_address)
77
+ rescue
78
+ return false
79
+ end
80
+ true
81
+ end
82
+
83
+ private
84
+
85
+ def is_uint8_array_for_test_address(buf)
86
+ decoded_prefix = buf[0, 2]
87
+ if decoded_prefix == PREFIX_BYTES[:main]
88
+ return false
89
+ end
90
+ if decoded_prefix == PREFIX_BYTES[:test]
91
+ return true
92
+ end
93
+
94
+ raise 'Invalid X-address: bad prefix'
95
+ end
96
+
97
+ def tag_from_uint8_array(bytes)
98
+ flag = bytes[22]
99
+ if flag >= 2
100
+ # Keine Unterstützung für 64-Bit-Tags zu diesem Zeitpunkt
101
+ raise 'Unsupported X-address'
102
+ end
103
+ if flag == 1
104
+ # Little-endian zu Big-endian
105
+ return bytes[23] + bytes[24] * 0x100 + bytes[25] * 0x10000 + bytes[26] * 0x1000000
106
+ end
107
+ if flag != 0
108
+ raise 'flag must be zero to indicate no tag'
109
+ end
110
+ if '0000000000000000' != bytes_to_hex(bytes[23, 8])
111
+ raise 'remaining bytes must be zero'
112
+ end
113
+ false
114
+ end
115
+
116
+ end
117
+
118
+ end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ require 'digest'
4
+ require_relative "../core/core"
5
+
6
+ module AddressCodec
7
+ class Codec
8
+
9
+ def initialize
10
+ @codec = Core::Base58XRP.new
11
+ end
12
+
13
+ def encode(bytes, opts)
14
+ versions = opts[:versions]
15
+ encode_versioned(bytes, versions, opts[:expected_length])
16
+ end
17
+
18
+ def decode(base58string, opts)
19
+ versions = opts[:versions]
20
+ types = opts[:version_types]
21
+
22
+ without_sum = decode_checked(base58string)
23
+
24
+ if versions.length > 1 && !opts[:expected_length]
25
+ raise 'expected_length is required because there are >= 2 possible versions'
26
+ end
27
+
28
+ version_length_guess = versions[0].is_a?(Numeric) ? 1 : versions[0].length
29
+ payload_length = opts[:expected_length] || without_sum.length - version_length_guess
30
+ version_bytes = without_sum[0...-payload_length]
31
+ payload = without_sum[-payload_length..-1]
32
+
33
+ versions.each_with_index do |version, i|
34
+ version = Array(version)
35
+ if version_bytes == version
36
+ return {
37
+ version: version,
38
+ bytes: payload,
39
+ type: types ? types[i] : nil
40
+ }
41
+ end
42
+ end
43
+
44
+ raise 'version_invalid: version bytes do not match any of the provided version(s)'
45
+ end
46
+
47
+ def encode_checked(bytes)
48
+ check = sha256(sha256(bytes))[0, 4]
49
+ encode_raw(bytes + check)
50
+ end
51
+
52
+ def decode_checked(base58string)
53
+ bytes = decode_raw(base58string)
54
+
55
+ if bytes.length < 5
56
+ raise 'invalid_input_size: decoded data must have length >= 5'
57
+ end
58
+
59
+ unless verify_check_sum(bytes)
60
+ raise 'checksum_invalid'
61
+ end
62
+
63
+ bytes[0...-4]
64
+ end
65
+
66
+ private
67
+
68
+ def encode_versioned(bytes, versions, expected_length)
69
+ unless check_byte_length(bytes, expected_length)
70
+ raise 'unexpected_payload_length: bytes.length does not match expected_length. Ensure that the bytes are a Uint8Array.'
71
+ end
72
+
73
+ encode_checked(concat_args(versions, bytes))
74
+ end
75
+
76
+ def encode_raw(bytes)
77
+ @codec.encode(bytes.pack('C*'))
78
+ end
79
+
80
+ def decode_raw(base58string)
81
+ @codec.decode(base58string).unpack('C*')
82
+ end
83
+
84
+ def sha256(bytes)
85
+ binary_value = bytes.pack('C*')
86
+ binary_hash = Digest::SHA256.digest(binary_value)
87
+ binary_hash.unpack('C*')
88
+ end
89
+
90
+ def verify_check_sum(bytes)
91
+ computed = sha256(sha256(bytes[0...-4]))[0, 4]
92
+ checksum = bytes[-4, 4]
93
+ computed == checksum
94
+ end
95
+
96
+ end
97
+
98
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../core/core"
4
+
5
+ module AddressCodec
6
+
7
+ class XrpCodec < Codec
8
+
9
+ # base58 encodings: https://xrpl.org/base58-encodings.html
10
+ ACCOUNT_ID = 0 # Account address (20 bytes)
11
+ ACCOUNT_PUBLIC_KEY = 0x23 # Account public key (33 bytes)
12
+ FAMILY_SEED = 0x21 # 33; Seed value (for secret keys) (16 bytes)
13
+ NODE_PUBLIC = 0x1c # 28; Validation public key (33 bytes)
14
+ ED25519_SEED = [0x01, 0xe1, 0x4b].freeze # [1, 225, 75]
15
+
16
+ def encode_seed(entropy, type = nil)
17
+ unless check_byte_length(entropy, 16)
18
+ raise 'entropy must have length 16'
19
+ end
20
+
21
+ opts = {
22
+ expected_length: 16,
23
+ versions: type == 'ed25519' ? ED25519_SEED : [FAMILY_SEED]
24
+ }
25
+
26
+ # prefixes entropy with version bytes
27
+ encode(entropy, opts)
28
+ end
29
+
30
+ def decode_seed(seed, opts = {
31
+ version_types: ['ed25519', 'secp256k1'],
32
+ versions: [ED25519_SEED, FAMILY_SEED],
33
+ expected_length: 16
34
+ })
35
+ decode(seed, opts)
36
+ end
37
+
38
+ def encode_account_id(bytes)
39
+ opts = { versions: [ACCOUNT_ID], expected_length: 20 }
40
+ encode(bytes, opts)
41
+ end
42
+
43
+ def decode_account_id(account_id)
44
+ opts = { versions: [ACCOUNT_ID], expected_length: 20 }
45
+ decode(account_id, opts)[:bytes]
46
+ end
47
+
48
+ def decode_node_public(base58string)
49
+ opts = { versions: [NODE_PUBLIC], expected_length: 33 }
50
+ decode(base58string, opts)[:bytes]
51
+ end
52
+
53
+ def encode_node_public(bytes)
54
+ opts = { versions: [NODE_PUBLIC], expected_length: 33 }
55
+ encode(bytes, opts)
56
+ end
57
+
58
+ def encode_account_public(bytes)
59
+ opts = { versions: [ACCOUNT_PUBLIC_KEY], expected_length: 33 }
60
+ encode(bytes, opts)
61
+ end
62
+
63
+ def decode_account_public(base58string)
64
+ opts = { versions: [ACCOUNT_PUBLIC_KEY], expected_length: 33 }
65
+ decode(base58string, opts)[:bytes]
66
+ end
67
+
68
+ def valid_classic_address?(address)
69
+ begin
70
+ decode_account_id(address)
71
+ rescue
72
+ return false
73
+ end
74
+ true
75
+ end
76
+
77
+ end
78
+
79
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BinaryCodec
4
+ class BinaryCodec
5
+
6
+ # from here: https://github.com/XRPLF/xrpl.js/blob/main/packages/ripple-binary-codec/src/binary.ts
7
+
8
+ def make_parser(bytes, definitions = nil)
9
+ BinaryParser.new(bytes.is_a?(String) ? bytes : bytes_to_hex(bytes))
10
+ end
11
+
12
+ #def read_json(parser, definitions = DEFAULT_DEFINITIONS)
13
+ def read_json(parser)
14
+ # parser.read_type(core_types[:STObject]).to_json(definitions)
15
+ parser.read_type(core_types[:STObject]).to_json()
16
+ end
17
+
18
+ def binary_to_json(hex)
19
+ parser = make_parser(hex)
20
+ read_json(parser)
21
+ end
22
+
23
+ def serialize_object(obj, definitions = nil)
24
+ BytesList.new.put_type(core_types[:STObject], obj)
25
+ end
26
+
27
+ def signing_data(transaction, prefix = HashPrefix[:transaction_sig], opts = {})
28
+ serialize_object(
29
+ transaction,
30
+ prefix: prefix,
31
+ signing_fields_only: true,
32
+ definitions: opts[:definitions]
33
+ )
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BinaryCodec
4
+ TYPE_WIDTH = 2
5
+ LEDGER_ENTRY_WIDTH = 2
6
+ TRANSACTION_TYPE_WIDTH = 2
7
+ TRANSACTION_RESULT_WIDTH = 1
8
+ end