ic_agent 0.1.4 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -8,10 +8,56 @@ module IcAgent
8
8
  end
9
9
 
10
10
  class Certificate
11
+ # Performs a lookup operation in the certificate tree based on the given path.
12
+ #
13
+ # Parameters:
14
+ # - path: The path to lookup.
15
+ # - cert: The certificate object containing the tree.
16
+ #
17
+ # Returns: The value found at the specified path in the tree.
11
18
  def self.lookup(path, cert)
12
19
  lookup_path(path, cert.value['tree'])
13
20
  end
14
21
 
22
+ # Retrieves the signature from a certificate.
23
+ #
24
+ # Parameters:
25
+ # - cert: The certificate object.
26
+ #
27
+ # Returns: The signature value.
28
+ def self.signature(cert)
29
+ cert.value['signature']
30
+ end
31
+
32
+ # Retrieves the delegation from a certificate.
33
+ #
34
+ # Parameters:
35
+ # - cert: The certificate object.
36
+ #
37
+ # Returns: The delegation value.
38
+ def self.delegation(cert)
39
+ cert.value['delegation']
40
+ end
41
+
42
+ # Retrieves the tree from a certificate.
43
+ #
44
+ # Parameters:
45
+ # - cert: The certificate object.
46
+ #
47
+ # Returns: The tree value.
48
+ def self.tree(cert)
49
+ cert.value['tree']
50
+ end
51
+
52
+ private
53
+
54
+ # Recursive helper method for performing the lookup operation.
55
+ #
56
+ # Parameters:
57
+ # - path: The remaining path to lookup.
58
+ # - tree: The current tree node to search in.
59
+ #
60
+ # Returns: The value found at the specified path in the tree.
15
61
  def self.lookup_path(path, tree)
16
62
  offset = 0
17
63
  if path.length == 0
@@ -29,6 +75,12 @@ module IcAgent
29
75
  end
30
76
  end
31
77
 
78
+ # Flattens fork nodes in the tree into a single array.
79
+ #
80
+ # Parameters:
81
+ # - t: The tree node to flatten.
82
+ #
83
+ # Returns: The flattened array of tree nodes.
32
84
  def self.flatten_forks(t)
33
85
  if t[0] == NodeId::EMPTY
34
86
  []
@@ -42,6 +94,13 @@ module IcAgent
42
94
  end
43
95
  end
44
96
 
97
+ # Finds a labeled tree node with the specified label in the given array of trees.
98
+ #
99
+ # Parameters:
100
+ # - l: The label to search for.
101
+ # - trees: The array of trees to search in.
102
+ #
103
+ # Returns: The labeled tree node with the matching label, or nil if not found.
45
104
  def self.find_label(l, trees)
46
105
  trees.each do |t|
47
106
  if t[0] == NodeId::LABELED
@@ -51,5 +110,44 @@ module IcAgent
51
110
  end
52
111
  nil
53
112
  end
113
+
114
+ # Recursively reconstructs the hash value of a tree node.
115
+ #
116
+ # Parameters:
117
+ # - t: The tree node to reconstruct.
118
+ #
119
+ # Returns: The reconstructed hash value of the tree node.
120
+ def self.reconstruct(t)
121
+ case t[0]
122
+ when IcAgent::NodeId::EMPTY
123
+ domain_sep = domain_sep('ic-hashtree-empty')
124
+ Digest::SHA256.digest(domain_sep)
125
+ when IcAgent::NodeId::PRUNED
126
+ t[1]
127
+ when IcAgent::NodeId::LEAF
128
+ domain_sep = domain_sep('ic-hashtree-leaf')
129
+ Digest::SHA256.digest(domain_sep + t[1])
130
+ when IcAgent::NodeId::LABELED
131
+ domain_sep = domain_sep('ic-hashtree-labeled')
132
+ Digest::SHA256.digest(domain_sep + t[1] + reconstruct(t[2]))
133
+ when IcAgent::NodeId::FORK
134
+ domain_sep = domain_sep('ic-hashtree-fork')
135
+ Digest::SHA256.digest(domain_sep + reconstruct(t[1]) + reconstruct(t[2]))
136
+ else
137
+ raise 'unreachable'
138
+ end
139
+ end
140
+
141
+ # Generates the domain separation prefix for hash computations.
142
+ #
143
+ # Parameters:
144
+ # - s: The domain separation string.
145
+ #
146
+ # Returns: The domain separation prefix as a binary string.
147
+ def self.domain_sep(s)
148
+ len = [s.bytesize].pack('C')
149
+ str = s.encode(Encoding::UTF_8)
150
+ len + str
151
+ end
54
152
  end
55
153
  end
@@ -5,6 +5,10 @@ module IcAgent
5
5
  DEFAULT_TIMEOUT = 120
6
6
  DEFAULT_TIMEOUT_QUERY = 30
7
7
 
8
+ # Initializes a new instance of the Client class.
9
+ #
10
+ # Parameters:
11
+ # - url: The URL of the IC agent. Defaults to 'https://ic0.app'.
8
12
  def initialize(url = 'https://ic0.app')
9
13
  @url = url
10
14
  @conn = Faraday.new(url: url) do |faraday|
@@ -16,6 +20,13 @@ module IcAgent
16
20
  end
17
21
  end
18
22
 
23
+ # Sends a query to a canister.
24
+ #
25
+ # Parameters:
26
+ # - canister_id: The ID of the canister to query.
27
+ # - data: The data to send with the query.
28
+ #
29
+ # Returns: The response from the canister as a UTF-8 encoded string.
19
30
  def query(canister_id, data)
20
31
  endpoint = "/api/v2/canister/#{canister_id}/query"
21
32
  ret = @conn.post(endpoint, data)
@@ -23,6 +34,14 @@ module IcAgent
23
34
  ret.body
24
35
  end
25
36
 
37
+ # Calls a function on a canister.
38
+ #
39
+ # Parameters:
40
+ # - canister_id: The ID of the canister to call.
41
+ # - req_id: The request ID.
42
+ # - data: The data to send with the call.
43
+ #
44
+ # Returns: The request ID.
26
45
  def call(canister_id, req_id, data)
27
46
  endpoint = "/api/v2/canister/#{canister_id}/call"
28
47
  ret = @conn.post(endpoint, data)
@@ -30,6 +49,13 @@ module IcAgent
30
49
  req_id
31
50
  end
32
51
 
52
+ # Reads the state of a canister.
53
+ #
54
+ # Parameters:
55
+ # - canister_id: The ID of the canister to read the state from.
56
+ # - data: The data to send with the read_state request.
57
+ #
58
+ # Returns: The response from the canister as a UTF-8 encoded string.
33
59
  def read_state(canister_id, data)
34
60
  endpoint = "/api/v2/canister/#{canister_id}/read_state"
35
61
  ret = @conn.post(endpoint, data)
@@ -37,6 +63,12 @@ module IcAgent
37
63
  ret.body
38
64
  end
39
65
 
66
+ # Retrieves the status of the IC agent.
67
+ #
68
+ # Parameters:
69
+ # - timeout: The timeout for the status request. Defaults to DEFAULT_TIMEOUT_QUERY.
70
+ #
71
+ # Returns: The response from the status endpoint as a UTF-8 encoded string.
40
72
  def status(timeout: DEFAULT_TIMEOUT_QUERY)
41
73
  endpoint = '/api/v2/status'
42
74
  ret = @conn.get(endpoint, timeout: timeout)
@@ -261,6 +261,11 @@ module IcAgent
261
261
 
262
262
  attr_accessor :identity, :client, :agent, :canister
263
263
 
264
+ # Constructor for the CyclesWallet class.
265
+ #
266
+ # Parameters:
267
+ # - iden: (Optional) An instance of the Identity class.
268
+ # - wallet_id: The ID of the CyclesWallet.
264
269
  def initialize(iden = nil, wallet_id)
265
270
  @identity = iden.nil? ? IcAgent::Identity.new : iden
266
271
  @client = IcAgent::Client.new
@@ -355,6 +355,10 @@ module IcAgent
355
355
 
356
356
  attr_accessor :identity, :client, :agent, :canister
357
357
 
358
+ # Constructor for the Governance class.
359
+ #
360
+ # Parameters:
361
+ # - iden: (Optional) An instance of the Identity class.
358
362
  def initialize(iden = nil)
359
363
  @identity = iden.nil? ? IcAgent::Identity.new : iden
360
364
  @client = IcAgent::Client.new
@@ -166,6 +166,10 @@ module IcAgent
166
166
 
167
167
  attr_accessor :identity, :client, :agent, :canister
168
168
 
169
+ # Constructor for the Ledger class.
170
+ #
171
+ # Parameters:
172
+ # - iden: (Optional) An instance of the Identity class.
169
173
  def initialize(iden = nil)
170
174
  @identity = iden.nil? ? IcAgent::Identity.new : iden
171
175
  @client = IcAgent::Client.new
@@ -182,6 +182,10 @@ module IcAgent
182
182
 
183
183
  attr_accessor :identity, :client, :agent, :canister
184
184
 
185
+ # Constructor for the Management class.
186
+ #
187
+ # Parameters:
188
+ # - iden: (Optional) An instance of the Identity class.
185
189
  def initialize(iden = nil)
186
190
  @identity = iden.nil? ? IcAgent::Identity.new : iden
187
191
  @client = IcAgent::Client.new
@@ -11,6 +11,12 @@ module IcAgent
11
11
  class Identity
12
12
  attr_reader :privkey, :pubkey, :der_pubkey, :sk, :vk, :key_type
13
13
 
14
+ # Initializes a new instance of the Identity class.
15
+ #
16
+ # Parameters:
17
+ # - privkey: The private key of the identity in hexadecimal format. Defaults to an empty string.
18
+ # - type: The key type of the identity. Defaults to 'ed25519'.
19
+ # - anonymous: A flag indicating whether the identity is anonymous. Defaults to false.
14
20
  def initialize(privkey = '', type = 'ed25519', anonymous = false)
15
21
  privkey = [privkey].pack('H*')
16
22
  @anonymous = anonymous
@@ -37,6 +43,12 @@ module IcAgent
37
43
  end
38
44
  end
39
45
 
46
+ # Creates a new Identity instance from a seed phrase (mnemonic).
47
+ #
48
+ # Parameters:
49
+ # - mnemonic: The seed phrase (mnemonic) used to generate the identity.
50
+ #
51
+ # Returns: The Identity instance.
40
52
  def self.from_seed(mnemonic)
41
53
  seed = Bitcoin::Trezor::Mnemonic.to_seed(mnemonic)
42
54
  privkey = seed[0..63]
@@ -44,6 +56,9 @@ module IcAgent
44
56
  Identity.new(privkey = privkey, type = key_type)
45
57
  end
46
58
 
59
+ # Returns the sender Principal associated with the Identity.
60
+ #
61
+ # Returns: The sender Principal.
47
62
  def sender
48
63
  if @anonymous
49
64
  IcAgent::Principal.anonymous
@@ -52,6 +67,12 @@ module IcAgent
52
67
  end
53
68
  end
54
69
 
70
+ # Signs a message using the Identity.
71
+ #
72
+ # Parameters:
73
+ # - msg: The message to sign.
74
+ #
75
+ # Returns: An array containing the DER-encoded public key and the signature.
55
76
  def sign(msg)
56
77
  if @anonymous
57
78
  [nil, nil]
@@ -65,6 +86,13 @@ module IcAgent
65
86
  end
66
87
  end
67
88
 
89
+ # Verifies a message signature using the Identity.
90
+ #
91
+ # Parameters:
92
+ # - msg: The message to verify.
93
+ # - sig: The signature to verify.
94
+ #
95
+ # Returns: `true` if the signature is valid, otherwise `false`.
68
96
  def verify(msg, sig)
69
97
  if @anonymous
70
98
  false
@@ -73,6 +101,9 @@ module IcAgent
73
101
  end
74
102
  end
75
103
 
104
+ # Returns the PEM-encoded private key of the Identity.
105
+ #
106
+ # Returns: The PEM-encoded private key.
76
107
  def to_pem
77
108
  der = @key_type == 'secp256k1' ? "#{IcAgent::IC_PUBKEY_SECP_DER_HERD}#{@sk.data.unpack1('H*')}".hex2str : "#{IcAgent::IC_PUBKEY_ED_DER_HEAD}#{@sk.to_bytes.unpack1('H*')}".hex2str
78
109
  b64 = Base64.strict_encode64(der)
@@ -92,20 +123,41 @@ module IcAgent
92
123
  class DelegateIdentity
93
124
  attr_reader :identity, :delegations, :der_pubkey
94
125
 
126
+ # Initializes a new instance of the DelegateIdentity class.
127
+ #
128
+ # Parameters:
129
+ # - identity: The Identity associated with the DelegateIdentity.
130
+ # - delegation: The delegation JSON object containing the delegated keys.
95
131
  def initialize(identity, delegation)
96
132
  @identity = identity
97
133
  @delegations = delegation['delegations'].map { |d| d }
98
134
  @der_pubkey = [delegation['publicKey']].pack('H*')
99
135
  end
100
136
 
137
+ # Signs a message using the DelegateIdentity.
138
+ #
139
+ # Parameters:
140
+ # - msg: The message to sign.
141
+ #
142
+ # Returns: An array containing the DER-encoded public key and the signature.
101
143
  def sign(msg)
102
144
  @identity.sign(msg)
103
145
  end
104
146
 
147
+ # Returns the sender Principal associated with the DelegateIdentity.
148
+ #
149
+ # Returns: The sender Principal.
105
150
  def sender
106
151
  Principal.self_authenticating(@der_pubkey)
107
152
  end
108
153
 
154
+ # Creates a new DelegateIdentity instance from JSON representations of the Identity and delegation.
155
+ #
156
+ # Parameters:
157
+ # - ic_identity: The JSON representation of the Identity.
158
+ # - ic_delegation: The JSON representation of the delegation.
159
+ #
160
+ # Returns: The DelegateIdentity instance.
109
161
  def self.from_json(ic_identity, ic_delegation)
110
162
  parsed_ic_identity = JSON.parse(ic_identity)
111
163
  parsed_ic_delegation = JSON.parse(ic_delegation)
@@ -7,16 +7,21 @@ module IcAgent
7
7
  MAX_LENGTH_IN_BYTES = 29
8
8
 
9
9
  class PrincipalSort
10
- OpaqueId = 1
11
- SelfAuthenticating = 2
12
- DerivedId = 3
13
- Anonymous = 4
10
+ OPAQUE_ID = 1
11
+ SELF_AUTHENTICATING = 2
12
+ DERIVED_ID = 3
13
+ ANONYMOUS = 4
14
14
  # Unassigned
15
15
  end
16
16
 
17
+ # Base class for Principal.
17
18
  class Principal
18
19
  attr_reader :len, :bytes, :is_principal, :hex
19
20
 
21
+ # Initializes a new instance of the Principal class.
22
+ #
23
+ # Parameters:
24
+ # - bytes: The bytes representing the principal. Defaults to an empty string.
20
25
  def initialize(bytes: ''.b)
21
26
  @len = bytes.length
22
27
  @bytes = bytes
@@ -24,23 +29,41 @@ module IcAgent
24
29
  @is_principal = true
25
30
  end
26
31
 
32
+ # Creates a new Principal instance representing the management canister.
33
+ #
34
+ # Returns: The Principal instance representing the management canister.
27
35
  def self.management_canister
28
36
  Principal.new
29
37
  end
30
38
 
39
+ # Creates a new self-authenticating Principal.
40
+ #
41
+ # Parameters:
42
+ # - pubkey: The public key associated with the self-authenticating Principal.
43
+ #
44
+ # Returns: The self-authenticating Principal instance.
31
45
  def self.self_authenticating(pubkey)
32
46
  # check pubkey.size for is ed25519 or secp256k1
33
47
  pubkey = [pubkey].pack('H*') if pubkey.size != 44 && pubkey.size != 88
34
48
 
35
49
  hash_ = OpenSSL::Digest::SHA224.digest(pubkey)
36
- hash_ += [PrincipalSort::SelfAuthenticating].pack('C')
50
+ hash_ += [PrincipalSort::SELF_AUTHENTICATING].pack('C')
37
51
  Principal.new(bytes: hash_)
38
52
  end
39
53
 
54
+ # Creates a new anonymous Principal.
55
+ #
56
+ # Returns: The anonymous Principal instance.
40
57
  def self.anonymous
41
58
  Principal.new(bytes: "\x04".b)
42
59
  end
43
60
 
61
+ # Creates a new Principal from a string representation.
62
+ #
63
+ # Parameters:
64
+ # - s: The string representation of the Principal.
65
+ #
66
+ # Returns: The Principal instance.
44
67
  def self.from_str(s)
45
68
  s1 = s.delete('-')
46
69
  pad_len = ((s1.length / 8.0).ceil * 8) - s1.length
@@ -53,10 +76,19 @@ module IcAgent
53
76
  p
54
77
  end
55
78
 
79
+ # Creates a new Principal from a hexadecimal string representation.
80
+ #
81
+ # Parameters:
82
+ # - s: The hexadecimal string representation of the Principal.
83
+ #
84
+ # Returns: The Principal instance.
56
85
  def self.from_hex(s)
57
86
  Principal.new(bytes: [s].pack('H*'))
58
87
  end
59
88
 
89
+ # Converts the Principal to a string representation.
90
+ #
91
+ # Returns: The string representation of the Principal.
60
92
  def to_str
61
93
  checksum = Zlib.crc32(@bytes) & 0xFFFFFFFF
62
94
  b = ''
@@ -71,6 +103,12 @@ module IcAgent
71
103
  ret + s
72
104
  end
73
105
 
106
+ # Converts the Principal to an AccountIdentifier.
107
+ #
108
+ # Parameters:
109
+ # - sub_account: The sub-account identifier. Defaults to 0.
110
+ #
111
+ # Returns: The AccountIdentifier instance.
74
112
  def to_account_id(sub_account = 0)
75
113
  AccountIdentifier.generate(self, sub_account)
76
114
  end
@@ -78,17 +116,70 @@ module IcAgent
78
116
  def to_s
79
117
  to_str
80
118
  end
119
+
120
+ # Compares the Principal with another Principal.
121
+ #
122
+ # Parameters:
123
+ # - other: The other Principal to compare with.
124
+ #
125
+ # Returns: The comparison result as a string ('lt', 'eq', or 'gt').
126
+ def compare_to(other)
127
+ (0...[self.bytes.length, other.bytes.length].min).each do |i|
128
+ if self.bytes[i] < other.bytes[i]
129
+ return 'lt'
130
+ elsif self.bytes[i] > other.bytes[i]
131
+ return 'gt'
132
+ end
133
+ end
134
+
135
+ if self.bytes.length < other.bytes.length
136
+ 'lt'
137
+ elsif self.bytes.length > other.bytes.length
138
+ 'gt'
139
+ else
140
+ 'eq'
141
+ end
142
+ end
143
+
144
+ # Utility method checking whether a provided Principal is less than or equal to the current one using the `compare_to` method.
145
+ #
146
+ # Parameters:
147
+ # - other: The other Principal to compare with.
148
+ #
149
+ # Returns: `true` if the current Principal is less than or equal to the provided Principal, otherwise `false`.
150
+ def lt_eq(other)
151
+ cmp = compare_to(other)
152
+ %w[lt eq].include?(cmp)
153
+ end
154
+
155
+ # Utility method checking whether a provided Principal is greater than or equal to the current one using the `compare_to` method.
156
+ #
157
+ # Parameters:
158
+ # - other: The other Principal to compare with.
159
+ #
160
+ # Returns: `true` if the current Principal is greater than or equal to the provided Principal, otherwise `false`.
161
+ def gt_eq(other)
162
+ cmp = compare_to(other)
163
+ %w[gt eq].include?(cmp)
164
+ end
81
165
  end
82
166
 
83
167
  class AccountIdentifier
84
168
  attr_reader :bytes
85
169
 
170
+ # Initializes a new instance of the AccountIdentifier class.
171
+ #
172
+ # Parameters:
173
+ # - hash: The hash representing the AccountIdentifier.
86
174
  def initialize(hash)
87
175
  raise 'Invalid hash length' unless hash.length == 32
88
176
 
89
177
  @bytes = hash
90
178
  end
91
179
 
180
+ # Converts the AccountIdentifier to a string representation.
181
+ #
182
+ # Returns: The string representation of the AccountIdentifier.
92
183
  def to_str
93
184
  '0x' + @bytes.unpack1('H*')
94
185
  end
@@ -97,12 +188,19 @@ module IcAgent
97
188
  to_str
98
189
  end
99
190
 
191
+ # Generates a new AccountIdentifier from a Principal.
192
+ #
193
+ # Parameters:
194
+ # - principal: The Principal associated with the AccountIdentifier.
195
+ # - sub_account: The sub-account identifier. Defaults to 0.
196
+ #
197
+ # Returns: The AccountIdentifier instance.
100
198
  def self.generate(principal, sub_account = 0)
101
199
  sha224 = OpenSSL::Digest::SHA224.new
102
200
  sha224 << "\naccount-id"
103
201
  sha224 << principal.bytes
104
202
  format_sub_account = "%08d" % sub_account
105
- sub_account = format_sub_account.chars.map {|c| c.to_i}.pack('N*')
203
+ sub_account = format_sub_account.chars.map { |c| c.to_i }.pack('N*')
106
204
  sha224 << sub_account
107
205
  hash = sha224.digest
108
206
  checksum = Zlib.crc32(hash) & 0xFFFFFFFF
@@ -5,6 +5,13 @@ require 'cbor'
5
5
 
6
6
  module IcAgent
7
7
  class SyetemState
8
+ # Retrieves the system time from a canister's state.
9
+ #
10
+ # Parameters:
11
+ # - agent: The IcAgent::Client instance.
12
+ # - canister_id: The ID of the canister.
13
+ #
14
+ # Returns: The system time as a timestamp.
8
15
  def self.time(agent, canister_id)
9
16
  cert = agent.read_state_raw(canister_id, [['time']])
10
17
  timestamp = Certificate.lookup(['time'], cert)
@@ -12,6 +19,14 @@ module IcAgent
12
19
  LEB128.decode_signed(str_io)
13
20
  end
14
21
 
22
+ # Retrieves the public key of a subnet from a canister's state.
23
+ #
24
+ # Parameters:
25
+ # - agent: The IcAgent::Client instance.
26
+ # - canister_id: The ID of the canister.
27
+ # - subnet_id: The ID of the subnet.
28
+ #
29
+ # Returns: The public key of the subnet in hexadecimal format.
15
30
  def self.subnet_public_key(agent, canister_id, subnet_id)
16
31
  path = ['subnet', Principal.from_str(subnet_id).bytes, 'public_key']
17
32
  cert = agent.read_state_raw(canister_id, [path])
@@ -19,6 +34,14 @@ module IcAgent
19
34
  pubkey.str2hex
20
35
  end
21
36
 
37
+ # Retrieves the canister ranges of a subnet from a canister's state.
38
+ #
39
+ # Parameters:
40
+ # - agent: The IcAgent::Client instance.
41
+ # - canister_id: The ID of the canister.
42
+ # - subnet_id: The ID of the subnet.
43
+ #
44
+ # Returns: An array of canister ranges, where each range is represented as an array of Principal instances.
22
45
  def self.subnet_canister_ranges(agent, canister_id, subnet_id)
23
46
  path = ['subnet', Principal.from_str(subnet_id).bytes, 'canister_ranges']
24
47
  cert = agent.read_state_raw(canister_id, [path])
@@ -26,6 +49,13 @@ module IcAgent
26
49
  CBOR.decode(ranges).value.map { |range| range.map { |item| Principal.new(bytes: item) } }
27
50
  end
28
51
 
52
+ # Retrieves the module hash of a canister from a canister's state.
53
+ #
54
+ # Parameters:
55
+ # - agent: The IcAgent::Client instance.
56
+ # - canister_id: The ID of the canister.
57
+ #
58
+ # Returns: The module hash of the canister in hexadecimal format.
29
59
  def self.canister_module_hash(agent, canister_id)
30
60
  path = ['canister', Principal.from_str(canister_id).bytes, 'module_hash']
31
61
  cert = agent.read_state_raw(canister_id, [path])
@@ -33,6 +63,13 @@ module IcAgent
33
63
  module_hash.str2hex
34
64
  end
35
65
 
66
+ # Retrieves the controllers of a canister from a canister's state.
67
+ #
68
+ # Parameters:
69
+ # - agent: The IcAgent::Client instance.
70
+ # - canister_id: The ID of the canister.
71
+ #
72
+ # Returns: An array of Principal instances representing the controllers of the canister.
36
73
  def self.canister_controllers(agent, canister_id)
37
74
  path = ['canister', Principal.from_str(canister_id).bytes, 'controllers']
38
75
  cert = agent.read_state_raw(canister_id, [path])
@@ -3,6 +3,12 @@ require 'leb128'
3
3
 
4
4
  module IcAgent
5
5
  module Utils
6
+ # Encodes a list of items into a binary string.
7
+ #
8
+ # Parameters:
9
+ # - l: The list of items to encode.
10
+ #
11
+ # Returns: The binary string representation of the encoded list.
6
12
  def self.encode_list(l)
7
13
  ret = ''
8
14
  l.each do |item|
@@ -21,7 +27,12 @@ module IcAgent
21
27
  ret
22
28
  end
23
29
 
24
- # used for sort record by key
30
+ # Computes a hash value for sorting records by key.
31
+ #
32
+ # Parameters:
33
+ # - s: The key to hash.
34
+ #
35
+ # Returns: The computed hash value.
25
36
  def self.label_hash(s)
26
37
  if s =~ /(^_\d+_$)|(^_0x[0-9a-fA-F]+_$)/
27
38
  num = s[1..-2]
@@ -41,6 +52,12 @@ module IcAgent
41
52
  idl_hash(s)
42
53
  end
43
54
 
55
+ # Computes a hash value for an IDL string.
56
+ #
57
+ # Parameters:
58
+ # - s: The IDL string to hash.
59
+ #
60
+ # Returns: The computed hash value.
44
61
  def self.idl_hash(s)
45
62
  h = 0
46
63
  s.bytes.each do |c|
@@ -49,6 +66,12 @@ module IcAgent
49
66
  h
50
67
  end
51
68
 
69
+ # Converts a data structure into a request ID.
70
+ #
71
+ # Parameters:
72
+ # - d: The data structure to convert.
73
+ #
74
+ # Returns: The request ID as a binary string.
52
75
  def self.to_request_id(d)
53
76
  return nil unless d.is_a?(Hash)
54
77
 
@@ -67,9 +90,14 @@ module IcAgent
67
90
  Digest::SHA256.digest(s)
68
91
  end
69
92
 
93
+ # Decodes a binary blob into a string.
94
+ #
95
+ # Parameters:
96
+ # - blob_bytes: The binary blob to decode.
97
+ #
98
+ # Returns: The decoded string.
70
99
  def self.decode_blob(blob_bytes)
71
100
  blob_bytes.pack('C*')
72
101
  end
73
102
  end
74
103
  end
75
-
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module IcAgent
4
- VERSION = '0.1.4'
4
+ VERSION = '0.2.1'
5
5
  end