xrpl-ruby 0.2.4 → 0.5.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 +4 -4
- data/lib/address-codec/address_codec.rb +21 -4
- data/lib/address-codec/codec.rb +15 -2
- data/lib/address-codec/xrp_codec.rb +29 -2
- data/lib/binary-codec/binary_codec.rb +46 -22
- data/lib/binary-codec/enums/definitions.json +592 -1
- data/lib/binary-codec/enums/definitions.rb +17 -5
- data/lib/binary-codec/enums/fields.rb +2 -0
- data/lib/binary-codec/serdes/binary_parser.rb +38 -0
- data/lib/binary-codec/serdes/binary_serializer.rb +18 -7
- data/lib/binary-codec/serdes/bytes_list.rb +11 -0
- data/lib/binary-codec/types/account_id.rb +18 -37
- data/lib/binary-codec/types/amount.rb +43 -23
- data/lib/binary-codec/types/blob.rb +14 -5
- data/lib/binary-codec/types/currency.rb +15 -4
- data/lib/binary-codec/types/hash.rb +37 -36
- data/lib/binary-codec/types/issue.rb +50 -0
- data/lib/binary-codec/types/path_set.rb +93 -0
- data/lib/binary-codec/types/serialized_type.rb +52 -28
- data/lib/binary-codec/types/st_array.rb +71 -0
- data/lib/binary-codec/types/st_object.rb +100 -3
- data/lib/binary-codec/types/uint.rb +116 -3
- data/lib/binary-codec/types/vector256.rb +53 -0
- data/lib/binary-codec/types/xchain_bridge.rb +47 -0
- data/lib/binary-codec/utilities.rb +18 -0
- data/lib/core/base_58_xrp.rb +2 -0
- data/lib/core/base_x.rb +10 -0
- data/lib/core/core.rb +44 -6
- data/lib/core/utilities.rb +38 -0
- data/lib/key-pairs/ed25519.rb +64 -0
- data/lib/key-pairs/key_pairs.rb +92 -0
- data/lib/key-pairs/secp256k1.rb +116 -0
- data/lib/wallet/wallet.rb +117 -0
- data/lib/xrpl-ruby.rb +25 -1
- metadata +26 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6c84782686e7934255929a23850a5f514d0435ff79e47cde2739ed1e940a0235
|
|
4
|
+
data.tar.gz: b6b1c24d77a63365e8bf45f8a8b702332315057a8a7ec820ef830264e3ba446e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9cdee47951edf9ac0a804e8f8335aea13625f0cf61f6262f229f1c7e8e569892821a201b80916f0f274ac8ed9c2de677a77e32c5ed113bfc5102d7dca7f0cafa
|
|
7
|
+
data.tar.gz: 6c6e8309646053ab8039c7eb9bac814d08c9984f8dba4a64ae290ce349ac5e8c739b7a81e1ecf6305d93623f2ca9ce5015e1435757b6aa9a3bf6e74e2c1a6759
|
|
@@ -11,21 +11,31 @@ module AddressCodec
|
|
|
11
11
|
|
|
12
12
|
MAX_32_BIT_UNSIGNED_INT = 4294967295
|
|
13
13
|
|
|
14
|
+
# Converts a classic address to an X-address.
|
|
15
|
+
# @param classic_address [String] The classic XRPL address to convert.
|
|
16
|
+
# @param tag [Integer, false, nil] The destination tag.
|
|
17
|
+
# @param test [Boolean] Whether the address is for a test network.
|
|
18
|
+
# @return [String] The encoded X-address.
|
|
14
19
|
def classic_address_to_x_address(classic_address, tag, test)
|
|
15
20
|
account_id = decode_account_id(classic_address)
|
|
16
21
|
encode_x_address(account_id, tag, test)
|
|
17
22
|
end
|
|
18
23
|
|
|
24
|
+
# Encodes an account ID and tag into an X-address.
|
|
25
|
+
# @param account_id [Array<Integer>] 20 bytes for the account ID.
|
|
26
|
+
# @param tag [Integer, false, nil] The destination tag.
|
|
27
|
+
# @param test [Boolean] Whether the address is for a test network.
|
|
28
|
+
# @return [String] The encoded X-address.
|
|
19
29
|
def encode_x_address(account_id, tag, test)
|
|
20
30
|
if account_id.length != 20
|
|
21
31
|
# RIPEMD160 -> 160 Bits = 20 Bytes
|
|
22
32
|
raise 'Account ID must be 20 bytes'
|
|
23
33
|
end
|
|
24
|
-
if tag != false && tag > MAX_32_BIT_UNSIGNED_INT
|
|
34
|
+
if tag && tag != false && tag > MAX_32_BIT_UNSIGNED_INT
|
|
25
35
|
raise 'Invalid tag'
|
|
26
36
|
end
|
|
27
37
|
the_tag = tag || 0
|
|
28
|
-
flag = tag == false || tag.nil? ? 0 : 1
|
|
38
|
+
flag = (tag == false || tag.nil?) ? 0 : 1
|
|
29
39
|
|
|
30
40
|
bytes = concat_args(
|
|
31
41
|
test ? PREFIX_BYTES[:test] : PREFIX_BYTES[:main],
|
|
@@ -46,6 +56,9 @@ module AddressCodec
|
|
|
46
56
|
encode_checked(bytes)
|
|
47
57
|
end
|
|
48
58
|
|
|
59
|
+
# Converts an X-address to a classic address.
|
|
60
|
+
# @param x_address [String] The X-address string to convert.
|
|
61
|
+
# @return [Hash] A hash containing :classic_address, :tag, and :test.
|
|
49
62
|
def x_address_to_classic_address(x_address)
|
|
50
63
|
decoded = decode_x_address(x_address)
|
|
51
64
|
account_id = decoded[:account_id]
|
|
@@ -59,6 +72,9 @@ module AddressCodec
|
|
|
59
72
|
}
|
|
60
73
|
end
|
|
61
74
|
|
|
75
|
+
# Decodes an X-address into its underlying account ID, tag, and network type.
|
|
76
|
+
# @param x_address [String] The X-address string to decode.
|
|
77
|
+
# @return [Hash] A hash containing :account_id, :tag, and :test.
|
|
62
78
|
def decode_x_address(x_address)
|
|
63
79
|
decoded = decode_checked(x_address)
|
|
64
80
|
test = is_uint8_array_for_test_address(decoded)
|
|
@@ -71,6 +87,9 @@ module AddressCodec
|
|
|
71
87
|
}
|
|
72
88
|
end
|
|
73
89
|
|
|
90
|
+
# Checks if a string is a valid X-address.
|
|
91
|
+
# @param x_address [String] The X-address string to check.
|
|
92
|
+
# @return [Boolean] True if the X-address is valid, false otherwise.
|
|
74
93
|
def valid_x_address?(x_address)
|
|
75
94
|
begin
|
|
76
95
|
decode_x_address(x_address)
|
|
@@ -97,11 +116,9 @@ module AddressCodec
|
|
|
97
116
|
def tag_from_uint8_array(bytes)
|
|
98
117
|
flag = bytes[22]
|
|
99
118
|
if flag >= 2
|
|
100
|
-
# Keine Unterstützung für 64-Bit-Tags zu diesem Zeitpunkt
|
|
101
119
|
raise 'Unsupported X-address'
|
|
102
120
|
end
|
|
103
121
|
if flag == 1
|
|
104
|
-
# Little-endian zu Big-endian
|
|
105
122
|
return bytes[23] + bytes[24] * 0x100 + bytes[25] * 0x10000 + bytes[26] * 0x1000000
|
|
106
123
|
end
|
|
107
124
|
if flag != 0
|
data/lib/address-codec/codec.rb
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
require 'digest'
|
|
4
|
-
require_relative "../core/core"
|
|
5
4
|
|
|
6
5
|
module AddressCodec
|
|
7
6
|
class Codec
|
|
@@ -10,11 +9,19 @@ module AddressCodec
|
|
|
10
9
|
@codec = Core::Base58XRP.new
|
|
11
10
|
end
|
|
12
11
|
|
|
12
|
+
# Encodes a byte array into a base58 string with a version prefix and checksum.
|
|
13
|
+
# @param bytes [Array<Integer>] The byte array to encode.
|
|
14
|
+
# @param opts [Hash] Options for encoding (e.g., :versions, :expected_length).
|
|
15
|
+
# @return [String] The encoded base58 string.
|
|
13
16
|
def encode(bytes, opts)
|
|
14
17
|
versions = opts[:versions]
|
|
15
18
|
encode_versioned(bytes, versions, opts[:expected_length])
|
|
16
19
|
end
|
|
17
20
|
|
|
21
|
+
# Decodes a base58 string and verifies its version and checksum.
|
|
22
|
+
# @param base58string [String] The base58 string to decode.
|
|
23
|
+
# @param opts [Hash] Options for decoding (e.g., :versions, :version_types, :expected_length).
|
|
24
|
+
# @return [Hash] The decoded data including version, bytes, and type.
|
|
18
25
|
def decode(base58string, opts)
|
|
19
26
|
versions = opts[:versions]
|
|
20
27
|
types = opts[:version_types]
|
|
@@ -44,11 +51,17 @@ module AddressCodec
|
|
|
44
51
|
raise 'version_invalid: version bytes do not match any of the provided version(s)'
|
|
45
52
|
end
|
|
46
53
|
|
|
54
|
+
# Encodes a byte array into a base58 string with a checksum.
|
|
55
|
+
# @param bytes [Array<Integer>] The byte array to encode.
|
|
56
|
+
# @return [String] The encoded base58 string.
|
|
47
57
|
def encode_checked(bytes)
|
|
48
58
|
check = sha256(sha256(bytes))[0, 4]
|
|
49
59
|
encode_raw(bytes + check)
|
|
50
60
|
end
|
|
51
61
|
|
|
62
|
+
# Decodes a base58 string and verifies its checksum.
|
|
63
|
+
# @param base58string [String] The base58 string to decode.
|
|
64
|
+
# @return [Array<Integer>] The decoded byte array (without checksum).
|
|
52
65
|
def decode_checked(base58string)
|
|
53
66
|
bytes = decode_raw(base58string)
|
|
54
67
|
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative "../core/core"
|
|
4
|
-
|
|
5
3
|
module AddressCodec
|
|
6
4
|
|
|
7
5
|
class XrpCodec < Codec
|
|
@@ -13,6 +11,10 @@ module AddressCodec
|
|
|
13
11
|
NODE_PUBLIC = 0x1c # 28; Validation public key (33 bytes)
|
|
14
12
|
ED25519_SEED = [0x01, 0xe1, 0x4b].freeze # [1, 225, 75]
|
|
15
13
|
|
|
14
|
+
# Encodes entropy into a seed string.
|
|
15
|
+
# @param entropy [Array<Integer>] 16 bytes of entropy.
|
|
16
|
+
# @param type [String, nil] The seed type ('ed25519' or 'secp256k1').
|
|
17
|
+
# @return [String] The encoded seed string.
|
|
16
18
|
def encode_seed(entropy, type = nil)
|
|
17
19
|
unless check_byte_length(entropy, 16)
|
|
18
20
|
raise 'entropy must have length 16'
|
|
@@ -27,6 +29,10 @@ module AddressCodec
|
|
|
27
29
|
encode(entropy, opts)
|
|
28
30
|
end
|
|
29
31
|
|
|
32
|
+
# Decodes a seed string into its underlying bytes and type.
|
|
33
|
+
# @param seed [String] The seed string to decode.
|
|
34
|
+
# @param opts [Hash] Options for decoding (e.g., :versions, :version_types, :expected_length).
|
|
35
|
+
# @return [Hash] The decoded data including version, bytes, and type.
|
|
30
36
|
def decode_seed(seed, opts = {
|
|
31
37
|
version_types: ['ed25519', 'secp256k1'],
|
|
32
38
|
versions: [ED25519_SEED, FAMILY_SEED],
|
|
@@ -35,36 +41,57 @@ module AddressCodec
|
|
|
35
41
|
decode(seed, opts)
|
|
36
42
|
end
|
|
37
43
|
|
|
44
|
+
# Encodes a byte array into an account ID string.
|
|
45
|
+
# @param bytes [Array<Integer>] 20 bytes for the account ID.
|
|
46
|
+
# @return [String] The encoded account ID string.
|
|
38
47
|
def encode_account_id(bytes)
|
|
39
48
|
opts = { versions: [ACCOUNT_ID], expected_length: 20 }
|
|
40
49
|
encode(bytes, opts)
|
|
41
50
|
end
|
|
42
51
|
|
|
52
|
+
# Decodes an account ID string into its underlying bytes.
|
|
53
|
+
# @param account_id [String] The account ID string to decode.
|
|
54
|
+
# @return [Array<Integer>] The decoded bytes.
|
|
43
55
|
def decode_account_id(account_id)
|
|
44
56
|
opts = { versions: [ACCOUNT_ID], expected_length: 20 }
|
|
45
57
|
decode(account_id, opts)[:bytes]
|
|
46
58
|
end
|
|
47
59
|
|
|
60
|
+
# Decodes a node public key string into its underlying bytes.
|
|
61
|
+
# @param base58string [String] The node public key string to decode.
|
|
62
|
+
# @return [Array<Integer>] The decoded bytes.
|
|
48
63
|
def decode_node_public(base58string)
|
|
49
64
|
opts = { versions: [NODE_PUBLIC], expected_length: 33 }
|
|
50
65
|
decode(base58string, opts)[:bytes]
|
|
51
66
|
end
|
|
52
67
|
|
|
68
|
+
# Encodes a byte array into a node public key string.
|
|
69
|
+
# @param bytes [Array<Integer>] 33 bytes for the node public key.
|
|
70
|
+
# @return [String] The encoded node public key string.
|
|
53
71
|
def encode_node_public(bytes)
|
|
54
72
|
opts = { versions: [NODE_PUBLIC], expected_length: 33 }
|
|
55
73
|
encode(bytes, opts)
|
|
56
74
|
end
|
|
57
75
|
|
|
76
|
+
# Encodes a byte array into an account public key string.
|
|
77
|
+
# @param bytes [Array<Integer>] 33 bytes for the account public key.
|
|
78
|
+
# @return [String] The encoded account public key string.
|
|
58
79
|
def encode_account_public(bytes)
|
|
59
80
|
opts = { versions: [ACCOUNT_PUBLIC_KEY], expected_length: 33 }
|
|
60
81
|
encode(bytes, opts)
|
|
61
82
|
end
|
|
62
83
|
|
|
84
|
+
# Decodes an account public key string into its underlying bytes.
|
|
85
|
+
# @param base58string [String] The account public key string to decode.
|
|
86
|
+
# @return [Array<Integer>] The decoded bytes.
|
|
63
87
|
def decode_account_public(base58string)
|
|
64
88
|
opts = { versions: [ACCOUNT_PUBLIC_KEY], expected_length: 33 }
|
|
65
89
|
decode(base58string, opts)[:bytes]
|
|
66
90
|
end
|
|
67
91
|
|
|
92
|
+
# Checks if a string is a valid classic XRPL address.
|
|
93
|
+
# @param address [String] The address string to check.
|
|
94
|
+
# @return [Boolean] True if the address is valid, false otherwise.
|
|
68
95
|
def valid_classic_address?(address)
|
|
69
96
|
begin
|
|
70
97
|
decode_account_id(address)
|
|
@@ -1,38 +1,62 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module BinaryCodec
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
# Hash prefixes for serialization.
|
|
5
|
+
HASH_PREFIX = {
|
|
6
|
+
transaction_sig: 0x53545800, # 'STX\0'
|
|
7
|
+
transaction_multi_sig: 0x534D5400, # 'SMT\0'
|
|
8
|
+
validation: 0x56414C00, # 'VAL\0'
|
|
9
|
+
proposal: 0x50525000 # 'PRP\0'
|
|
10
|
+
}.freeze
|
|
11
|
+
|
|
12
|
+
# from here: https://github.com/XRPLF/xrpl.js/blob/main/packages/ripple-binary-codec/src/binary.ts
|
|
13
|
+
class << self
|
|
14
|
+
# Creates a BinaryParser for the given bytes.
|
|
15
|
+
# @param bytes [String, Array<Integer>] The bytes to parse (hex string or byte array).
|
|
16
|
+
# @param definitions [Definitions, nil] Optional definitions.
|
|
17
|
+
# @return [BinaryParser] The created parser.
|
|
8
18
|
def make_parser(bytes, definitions = nil)
|
|
9
19
|
BinaryParser.new(bytes.is_a?(String) ? bytes : bytes_to_hex(bytes))
|
|
10
20
|
end
|
|
11
21
|
|
|
12
|
-
#
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
parser.read_type(core_types[:STObject]).to_json()
|
|
16
|
-
end
|
|
17
|
-
|
|
22
|
+
# Converts a hex string to its JSON representation.
|
|
23
|
+
# @param hex [String] The hex string to convert.
|
|
24
|
+
# @return [Hash] The decoded JSON object.
|
|
18
25
|
def binary_to_json(hex)
|
|
19
26
|
parser = make_parser(hex)
|
|
20
|
-
|
|
27
|
+
st_object = SerializedType.get_type_by_name('STObject')
|
|
28
|
+
JSON.parse(st_object.from_parser(parser).to_json)
|
|
21
29
|
end
|
|
22
30
|
|
|
23
|
-
|
|
24
|
-
|
|
31
|
+
# Converts a JSON object to its binary representation.
|
|
32
|
+
# @param json [Hash] The JSON object to convert.
|
|
33
|
+
# @return [String] The serialized hex string.
|
|
34
|
+
def json_to_binary(json)
|
|
35
|
+
st_object = SerializedType.get_type_by_name('STObject')
|
|
36
|
+
st_object.from(json).to_hex
|
|
25
37
|
end
|
|
26
38
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
39
|
+
# Generates signing data for a transaction.
|
|
40
|
+
# @param transaction [Hash] The transaction to serialize.
|
|
41
|
+
# @param prefix [Integer] The prefix to add to the serialized data.
|
|
42
|
+
# @param opts [Hash] Optional settings (e.g., :definitions, :signing_fields_only).
|
|
43
|
+
# @return [Array<Integer>] The serialized signing data.
|
|
44
|
+
def signing_data(transaction, prefix = HASH_PREFIX[:transaction_sig], opts = {})
|
|
45
|
+
# 1. Start with the prefix bytes
|
|
46
|
+
prefix_bytes = int_to_bytes(prefix, 4)
|
|
35
47
|
|
|
36
|
-
|
|
48
|
+
# 2. Serialize the object, only including signing fields
|
|
49
|
+
st_object_class = SerializedType.get_type_by_name('STObject')
|
|
50
|
+
|
|
51
|
+
filter = if opts[:signing_fields_only]
|
|
52
|
+
lambda { |field_name| Definitions.instance.get_field_instance(field_name).is_signing_field }
|
|
53
|
+
else
|
|
54
|
+
nil
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
serialized_bytes = st_object_class.from(transaction, filter).to_bytes
|
|
37
58
|
|
|
59
|
+
prefix_bytes + serialized_bytes
|
|
60
|
+
end
|
|
61
|
+
end
|
|
38
62
|
end
|