ic_agent 0.1.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/.ruby-version +1 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Dockerfile +17 -0
- data/Gemfile +23 -0
- data/Gemfile.lock +108 -0
- data/LICENSE.txt +21 -0
- data/README.md +217 -0
- data/Rakefile +4 -0
- data/ic_agent.gemspec +53 -0
- data/lib/ic_agent/agent.rb +176 -0
- data/lib/ic_agent/ast/assembler.rb +192 -0
- data/lib/ic_agent/ast/did_grammar.treetop +159 -0
- data/lib/ic_agent/ast/did_grammar_v1.treetop +111 -0
- data/lib/ic_agent/ast/nodes/named_nodes.rb +410 -0
- data/lib/ic_agent/ast/nodes/string_literal.rb +17 -0
- data/lib/ic_agent/ast/parser.rb +85 -0
- data/lib/ic_agent/ast/writer.rb +19 -0
- data/lib/ic_agent/candid.rb +1671 -0
- data/lib/ic_agent/canister.rb +270 -0
- data/lib/ic_agent/certificate.rb +55 -0
- data/lib/ic_agent/client.rb +47 -0
- data/lib/ic_agent/common/cycles_wallet.rb +275 -0
- data/lib/ic_agent/common/governance.rb +366 -0
- data/lib/ic_agent/common/ledger.rb +177 -0
- data/lib/ic_agent/common/management.rb +69 -0
- data/lib/ic_agent/identity.rb +125 -0
- data/lib/ic_agent/principal.rb +112 -0
- data/lib/ic_agent/system_state.rb +43 -0
- data/lib/ic_agent/utils.rb +71 -0
- data/lib/ic_agent/version.rb +5 -0
- data/lib/ic_agent.rb +37 -0
- data/sig/ic_agent.rbs +4 -0
- metadata +288 -0
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
require 'rubytree'
|
|
2
|
+
|
|
3
|
+
module IcAgent
|
|
4
|
+
class Canister
|
|
5
|
+
def initialize(agent, canister_id, candid=nil)
|
|
6
|
+
@agent = agent
|
|
7
|
+
@canister_id = canister_id
|
|
8
|
+
if candid
|
|
9
|
+
@candid = candid
|
|
10
|
+
else
|
|
11
|
+
candid = @agent.query_raw(canister_id, '__get_candid_interface_tmp_hack', encode([]))
|
|
12
|
+
@candid = candid[0]['value']
|
|
13
|
+
end
|
|
14
|
+
if candid.nil?
|
|
15
|
+
puts candid
|
|
16
|
+
puts 'Please provide candid description'
|
|
17
|
+
raise BaseException, "canister #{@canister_id} has no __get_candid_interface_tmp_hack method."
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
parser = IcAgent::Ast::Parser.new
|
|
21
|
+
parser.parse(@candid)
|
|
22
|
+
|
|
23
|
+
ic_service_methods = parser.ic_service_methods.elements
|
|
24
|
+
ic_service_methods.each do |item|
|
|
25
|
+
service_method = item.to_obj
|
|
26
|
+
method_name = service_method['ic_service_method_name']
|
|
27
|
+
anno = service_method['ic_service_method_query']
|
|
28
|
+
args = service_method['ic_service_method_params']
|
|
29
|
+
rets = service_method['ic_service_method_return']
|
|
30
|
+
|
|
31
|
+
args_arr = args.nil? ? [] : args.split(',').map(&:strip)
|
|
32
|
+
args_type_arrs = []
|
|
33
|
+
args_arr.each do |arg|
|
|
34
|
+
args_type_arrs << get_param_to_ic_type(parser, arg)
|
|
35
|
+
end
|
|
36
|
+
ret_type = get_param_to_ic_type(parser, rets)
|
|
37
|
+
|
|
38
|
+
add_caniter_method(method_name, args, args_type_arrs, ret_type, anno)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def service_param_child(parser, args_name, now_args = [], child_args = [], done_args = [])
|
|
45
|
+
arg_opt = args_name.include?(' ') ? args_name.split(' ')[0] : args_name
|
|
46
|
+
arg_child_item = []
|
|
47
|
+
if IcAgent::Candid::ALL_TYPES.include?(arg_opt)
|
|
48
|
+
arg_child_item = args_name.split(' ')[1..] if args_name.include?(' ')
|
|
49
|
+
else
|
|
50
|
+
input_body = parser.ic_type_by_name(arg_opt)
|
|
51
|
+
input_body_obj = input_body.to_obj
|
|
52
|
+
arg_child_item = input_body_obj['type_child_item_values']
|
|
53
|
+
done_args << arg_opt
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
child_args = child_args + arg_child_item.flatten - done_args - IcAgent::Candid::ALL_TYPES
|
|
57
|
+
child_args = child_args.uniq
|
|
58
|
+
|
|
59
|
+
add_childs = child_args - now_args
|
|
60
|
+
now_args += add_childs
|
|
61
|
+
|
|
62
|
+
if child_args.length > 0
|
|
63
|
+
next_args_name = child_args.pop
|
|
64
|
+
return service_param_child(parser, next_args_name, now_args, child_args, done_args)
|
|
65
|
+
end
|
|
66
|
+
now_args
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def build_param_tree(parser, type_name, current_node = nil, tree_root_node = nil)
|
|
70
|
+
if current_node.nil?
|
|
71
|
+
root_type = parser.ic_type_by_name(type_name)
|
|
72
|
+
refer_nodes = root_type.type_child_refer_items.nil? ? [] : root_type.type_child_refer_items
|
|
73
|
+
root_node = Tree::TreeNode.new(type_name,
|
|
74
|
+
{ 'total_child': refer_nodes.size,
|
|
75
|
+
'all_child': refer_nodes,
|
|
76
|
+
'child_refer': refer_nodes,
|
|
77
|
+
'self_refer': false,
|
|
78
|
+
'refer_path': [type_name],
|
|
79
|
+
'ic_type': nil,
|
|
80
|
+
'prototype': root_type.type_param_content,
|
|
81
|
+
'content': root_type.type_param_content })
|
|
82
|
+
tree_root_node = root_node
|
|
83
|
+
else
|
|
84
|
+
root_node = current_node
|
|
85
|
+
refer_nodes = current_node.content[:child_refer]
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
if tree_root_node && current_node && tree_root_node.name != current_node.name && current_node.content[:child_refer].size == 0
|
|
89
|
+
parent_node = current_node.parent
|
|
90
|
+
parent_node.content[:child_refer].delete(current_node.name)
|
|
91
|
+
# update parent ic types
|
|
92
|
+
child_key_types = {}
|
|
93
|
+
current_node.children.each do |child_node|
|
|
94
|
+
child_key_types[child_node.name] = child_node.content[:ic_type]
|
|
95
|
+
end
|
|
96
|
+
ic_type = IcAgent::Ast::Assembler.build_type(current_node.content[:prototype], child_key_types)
|
|
97
|
+
current_node.content[:ic_type] = ic_type
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
# replace parent content
|
|
101
|
+
new_content = replace_root_child_code(parent_node.content[:content], current_node.name, current_node.content[:content])
|
|
102
|
+
parent_node.content[:content] = new_content
|
|
103
|
+
|
|
104
|
+
# clear refer_path
|
|
105
|
+
refer_index = tree_root_node.content[:refer_path].index(current_node.name)
|
|
106
|
+
tree_root_node.content[:refer_path] = tree_root_node.content[:refer_path].slice(0, refer_index) if refer_index
|
|
107
|
+
build_param_tree(parser, parent_node.name, parent_node, tree_root_node)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
if tree_root_node.nil? || tree_root_node.content[:child_refer].size > 0
|
|
111
|
+
if refer_nodes.size > 0
|
|
112
|
+
refer_node = refer_nodes[0]
|
|
113
|
+
# self refer
|
|
114
|
+
if tree_root_node && tree_root_node.content[:refer_path].include?(refer_node)
|
|
115
|
+
child_node = Tree::TreeNode.new(refer_node, { 'total_child': 0, 'child_refer': [], 'self_refer': true, 'content': nil })
|
|
116
|
+
root_node << child_node
|
|
117
|
+
root_node.content[:child_refer].delete(refer_node)
|
|
118
|
+
build_param_tree(parser, root_node.name, root_node, tree_root_node)
|
|
119
|
+
else
|
|
120
|
+
# non self refer
|
|
121
|
+
child_type = parser.ic_type_by_name(refer_node)
|
|
122
|
+
child_refer_nodes = child_type.type_child_refer_items
|
|
123
|
+
if child_refer_nodes.size == 0
|
|
124
|
+
# set ic type
|
|
125
|
+
ic_type = IcAgent::Ast::Assembler.build_type(child_type.type_param_content)
|
|
126
|
+
child_node = Tree::TreeNode.new(refer_node, { 'total_child': 0,
|
|
127
|
+
'child_refer': [],
|
|
128
|
+
'self_refer': false,
|
|
129
|
+
'ic_type': ic_type,
|
|
130
|
+
'prototype': child_type.type_param_content,
|
|
131
|
+
'content': child_type.type_param_content })
|
|
132
|
+
root_node << child_node
|
|
133
|
+
root_node.content[:child_refer].delete(refer_node)
|
|
134
|
+
|
|
135
|
+
# replace parent content
|
|
136
|
+
new_content = replace_root_child_code(root_node.content[:content], refer_node, child_type.type_param_content)
|
|
137
|
+
root_node.content[:content] = new_content
|
|
138
|
+
build_param_tree(parser, root_node.name, root_node, tree_root_node)
|
|
139
|
+
else
|
|
140
|
+
child_node = Tree::TreeNode.new(refer_node, { 'total_child': child_refer_nodes.size,
|
|
141
|
+
'child_refer': child_refer_nodes,
|
|
142
|
+
'self_refer': false,
|
|
143
|
+
'prototype': child_type.type_param_content,
|
|
144
|
+
'content': child_type.type_param_content })
|
|
145
|
+
root_node << child_node
|
|
146
|
+
tree_root_node.content[:all_child] = (tree_root_node.content[:all_child] + child_refer_nodes).uniq
|
|
147
|
+
|
|
148
|
+
# add refer_path
|
|
149
|
+
tree_root_node.content[:refer_path] << refer_node
|
|
150
|
+
build_param_tree(parser, refer_node, child_node, tree_root_node)
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# update root_node ic types
|
|
157
|
+
if root_node.content[:ic_type].nil?
|
|
158
|
+
child_key_types = {}
|
|
159
|
+
root_node.children.each do |child_node|
|
|
160
|
+
child_key_types[child_node.name] = child_node.content[:ic_type]
|
|
161
|
+
end
|
|
162
|
+
ic_type = IcAgent::Ast::Assembler.build_type(root_node.content[:prototype], child_key_types)
|
|
163
|
+
root_node.content[:ic_type] = ic_type
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
root_node
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# params array recursively call, traverse, and replace
|
|
170
|
+
def service_params_replace(arr, search_value, replace_value)
|
|
171
|
+
arr.map! do |element|
|
|
172
|
+
if element.is_a?(Array)
|
|
173
|
+
service_params_replace(element, search_value, replace_value)
|
|
174
|
+
else
|
|
175
|
+
element == search_value ? replace_value : element
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def refer_type(param)
|
|
181
|
+
param_arr = param.strip.split(' ')
|
|
182
|
+
refer_type = param_arr - IcAgent::Candid::ALL_TYPES
|
|
183
|
+
refer_type.empty? ? nil : refer_type[0]
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def only_refer_type?(param)
|
|
187
|
+
refer_types = IcAgent::Ast::Assembler.get_params_refer_values(param)
|
|
188
|
+
param.index(' ').nil? && refer_types.size == 1
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def get_param_to_ic_type(parser, param)
|
|
192
|
+
ic_refer_types = {}
|
|
193
|
+
refer_types = IcAgent::Ast::Assembler.get_params_refer_values(param)
|
|
194
|
+
refer_types.each do |refer_code|
|
|
195
|
+
ic_refer_types[refer_code] = build_param_tree(parser, refer_code, nil, nil).content[:ic_type]
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
ic_type = nil
|
|
199
|
+
if param.index(' ') || refer_types.size > 1
|
|
200
|
+
ic_type = IcAgent::Ast::Assembler.build_type(param, ic_refer_types)
|
|
201
|
+
elsif ic_refer_types.keys.size == 1
|
|
202
|
+
ic_type = ic_refer_types.values[0]
|
|
203
|
+
end
|
|
204
|
+
ic_type
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def decode_type_arg(parser, arg)
|
|
208
|
+
base_arg = arg.strip
|
|
209
|
+
decode_arg = base_arg
|
|
210
|
+
unless base_arg.include?(' ') || IcAgent::Candid::ALL_TYPES.any? { |str| base_arg.include?(str) }
|
|
211
|
+
arg_type = parser.ic_type_by_name(base_arg)
|
|
212
|
+
decode_arg = arg_type.type_param_content
|
|
213
|
+
end
|
|
214
|
+
decode_arg
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def replace_root_child_code(root_text, find_text, replace_text)
|
|
218
|
+
new_root_text = root_text
|
|
219
|
+
parts = new_root_text.split(";")
|
|
220
|
+
|
|
221
|
+
if parts.size > 0
|
|
222
|
+
parts.map do |part|
|
|
223
|
+
last_index = part.rindex(find_text)
|
|
224
|
+
e_last_index = part.rindex("#{find_text}}")
|
|
225
|
+
b_last_index = part.rindex("#{find_text} ")
|
|
226
|
+
part[last_index..(last_index + find_text.size - 1)] = replace_text if last_index && (e_last_index || b_last_index || (last_index + find_text.size) == part.size)
|
|
227
|
+
end
|
|
228
|
+
new_root_text = parts.join(";")
|
|
229
|
+
else
|
|
230
|
+
last_index = new_root_text.rindex(find_text)
|
|
231
|
+
e_last_index = new_root_text.rindex("#{find_text}}")
|
|
232
|
+
b_last_index = new_root_text.rindex("#{find_text} ")
|
|
233
|
+
new_root_text[last_index..(last_index + find_text.size - 1)] = replace_text if last_index && (e_last_index || b_last_index || (last_index + find_text.size) == part.size)
|
|
234
|
+
end
|
|
235
|
+
new_root_text
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def add_caniter_method(method_name, type_args, args_types, rets_type, anno = nil)
|
|
239
|
+
self.class.class_eval do
|
|
240
|
+
define_method(method_name) do |*args|
|
|
241
|
+
init_method_name = method_name
|
|
242
|
+
init_method_args = type_args.nil? ? [] : type_args.split(',').map(&:strip)
|
|
243
|
+
init_method_anno = anno
|
|
244
|
+
init_method_types = args_types
|
|
245
|
+
init_method_ret_type = rets_type
|
|
246
|
+
|
|
247
|
+
if init_method_args.length != args.length
|
|
248
|
+
raise ArgumentError, 'Arguments length not match'
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
arguments = []
|
|
252
|
+
args.each_with_index do |arg, i|
|
|
253
|
+
arguments << { 'type': init_method_types[i], 'value': arg }
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
effective_canister_id = @canister_id == 'aaaaa-aa' && init_method_args.length > 0 && init_method_args[0].is_a?(Hash) && init_method_args[0].key?('canister_id') ? init_method_args[0]['canister_id'] : @canister_id
|
|
257
|
+
res = if init_method_anno == 'query'
|
|
258
|
+
@agent.query_raw(@canister_id, init_method_name, IcAgent::Candid.encode(arguments), init_method_ret_type, effective_canister_id)
|
|
259
|
+
else
|
|
260
|
+
@agent.update_raw(@canister_id, init_method_name, IcAgent::Candid.encode(arguments), init_method_ret_type, effective_canister_id)
|
|
261
|
+
end
|
|
262
|
+
return res unless res.is_a?(Array)
|
|
263
|
+
|
|
264
|
+
res.map { |item| item['value'] }
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module IcAgent
|
|
2
|
+
class NodeId
|
|
3
|
+
EMPTY = 0
|
|
4
|
+
FORK = 1
|
|
5
|
+
LABELED = 2
|
|
6
|
+
LEAF = 3
|
|
7
|
+
PRUNED = 4
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
class Certificate
|
|
11
|
+
def self.lookup(path, cert)
|
|
12
|
+
lookup_path(path, cert.value['tree'])
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.lookup_path(path, tree)
|
|
16
|
+
offset = 0
|
|
17
|
+
if path.length == 0
|
|
18
|
+
if tree[0] == NodeId::LEAF
|
|
19
|
+
return tree[1]
|
|
20
|
+
else
|
|
21
|
+
return nil
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
label = path[0].is_a?(String) ? path[0].encode : path[0]
|
|
25
|
+
t = find_label(label, flatten_forks(tree))
|
|
26
|
+
if t
|
|
27
|
+
offset += 1
|
|
28
|
+
lookup_path(path[offset..-1], t)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.flatten_forks(t)
|
|
33
|
+
if t[0] == NodeId::EMPTY
|
|
34
|
+
[]
|
|
35
|
+
elsif t[0] == NodeId::FORK
|
|
36
|
+
val1 = flatten_forks(t[1])
|
|
37
|
+
val2 = flatten_forks(t[2])
|
|
38
|
+
val1.concat(val2)
|
|
39
|
+
val1
|
|
40
|
+
else
|
|
41
|
+
[t]
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def self.find_label(l, trees)
|
|
46
|
+
trees.each do |t|
|
|
47
|
+
if t[0] == NodeId::LABELED
|
|
48
|
+
p = t[1]
|
|
49
|
+
return t[2] if l == p
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
nil
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
require 'faraday'
|
|
2
|
+
|
|
3
|
+
module IcAgent
|
|
4
|
+
class Client
|
|
5
|
+
DEFAULT_TIMEOUT = 120
|
|
6
|
+
DEFAULT_TIMEOUT_QUERY = 30
|
|
7
|
+
|
|
8
|
+
def initialize(url = 'https://ic0.app')
|
|
9
|
+
@url = url
|
|
10
|
+
@conn = Faraday.new(url: url) do |faraday|
|
|
11
|
+
faraday.request :url_encoded
|
|
12
|
+
faraday.adapter Faraday.default_adapter
|
|
13
|
+
faraday.headers['Content-Type'] = 'application/cbor'
|
|
14
|
+
faraday.options.timeout = DEFAULT_TIMEOUT
|
|
15
|
+
faraday.options.open_timeout = DEFAULT_TIMEOUT_QUERY
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def query(canister_id, data)
|
|
20
|
+
endpoint = "/api/v2/canister/#{canister_id}/query"
|
|
21
|
+
ret = @conn.post(endpoint, data)
|
|
22
|
+
ret.body.force_encoding('ISO-8859-1').encode('UTF-8')
|
|
23
|
+
ret.body
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def call(canister_id, req_id, data)
|
|
27
|
+
endpoint = "/api/v2/canister/#{canister_id}/call"
|
|
28
|
+
ret = @conn.post(endpoint, data)
|
|
29
|
+
ret.body.force_encoding('ISO-8859-1').encode('UTF-8')
|
|
30
|
+
req_id
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def read_state(canister_id, data)
|
|
34
|
+
endpoint = "/api/v2/canister/#{canister_id}/read_state"
|
|
35
|
+
ret = @conn.post(endpoint, data)
|
|
36
|
+
ret.body.force_encoding('ISO-8859-1').encode('UTF-8')
|
|
37
|
+
ret.body
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def status(timeout: DEFAULT_TIMEOUT_QUERY)
|
|
41
|
+
endpoint = '/api/v2/status'
|
|
42
|
+
ret = @conn.get(endpoint, timeout: timeout)
|
|
43
|
+
puts "client.status: #{ret.body.force_encoding('ISO-8859-1').encode('UTF-8')}"
|
|
44
|
+
ret.body
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
module IcAgent
|
|
2
|
+
module Common
|
|
3
|
+
class CyclesWallet
|
|
4
|
+
DID_FILE = <<~DIDL_DOC
|
|
5
|
+
type EventKind = variant {
|
|
6
|
+
CyclesSent: record {
|
|
7
|
+
to: principal;
|
|
8
|
+
amount: nat64;
|
|
9
|
+
refund: nat64;
|
|
10
|
+
};
|
|
11
|
+
CyclesReceived: record {
|
|
12
|
+
from: principal;
|
|
13
|
+
amount: nat64;
|
|
14
|
+
memo: opt text;
|
|
15
|
+
};
|
|
16
|
+
AddressAdded: record {
|
|
17
|
+
id: principal;
|
|
18
|
+
name: opt text;
|
|
19
|
+
role: Role;
|
|
20
|
+
};
|
|
21
|
+
AddressRemoved: record {
|
|
22
|
+
id: principal;
|
|
23
|
+
};
|
|
24
|
+
CanisterCreated: record {
|
|
25
|
+
canister: principal;
|
|
26
|
+
cycles: nat64;
|
|
27
|
+
};
|
|
28
|
+
CanisterCalled: record {
|
|
29
|
+
canister: principal;
|
|
30
|
+
method_name: text;
|
|
31
|
+
cycles: nat64;
|
|
32
|
+
};
|
|
33
|
+
WalletDeployed: record {
|
|
34
|
+
canister: principal;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
type EventKind128 = variant {
|
|
39
|
+
CyclesSent: record {
|
|
40
|
+
to: principal;
|
|
41
|
+
amount: nat;
|
|
42
|
+
refund: nat;
|
|
43
|
+
};
|
|
44
|
+
CyclesReceived: record {
|
|
45
|
+
from: principal;
|
|
46
|
+
amount: nat;
|
|
47
|
+
memo: opt text;
|
|
48
|
+
};
|
|
49
|
+
AddressAdded: record {
|
|
50
|
+
id: principal;
|
|
51
|
+
name: opt text;
|
|
52
|
+
role: Role;
|
|
53
|
+
};
|
|
54
|
+
AddressRemoved: record {
|
|
55
|
+
id: principal;
|
|
56
|
+
};
|
|
57
|
+
CanisterCreated: record {
|
|
58
|
+
canister: principal;
|
|
59
|
+
cycles: nat;
|
|
60
|
+
};
|
|
61
|
+
CanisterCalled: record {
|
|
62
|
+
canister: principal;
|
|
63
|
+
method_name: text;
|
|
64
|
+
cycles: nat;
|
|
65
|
+
};
|
|
66
|
+
WalletDeployed: record {
|
|
67
|
+
canister: principal;
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
type Event = record {
|
|
72
|
+
id: nat32;
|
|
73
|
+
timestamp: nat64;
|
|
74
|
+
kind: EventKind;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
type Event128 = record {
|
|
78
|
+
id: nat32;
|
|
79
|
+
timestamp: nat64;
|
|
80
|
+
kind: EventKind128;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
type Role = variant {
|
|
84
|
+
Contact;
|
|
85
|
+
Custodian;
|
|
86
|
+
Controller;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
type Kind = variant {
|
|
90
|
+
Unknown;
|
|
91
|
+
User;
|
|
92
|
+
Canister;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// An entry in the address book. It must have an ID and a role.
|
|
96
|
+
type AddressEntry = record {
|
|
97
|
+
id: principal;
|
|
98
|
+
name: opt text;
|
|
99
|
+
kind: Kind;
|
|
100
|
+
role: Role;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
type ManagedCanisterInfo = record {
|
|
104
|
+
id: principal;
|
|
105
|
+
name: opt text;
|
|
106
|
+
created_at: nat64;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
type ManagedCanisterEventKind = variant {
|
|
110
|
+
CyclesSent: record {
|
|
111
|
+
amount: nat64;
|
|
112
|
+
refund: nat64;
|
|
113
|
+
};
|
|
114
|
+
Called: record {
|
|
115
|
+
method_name: text;
|
|
116
|
+
cycles: nat64;
|
|
117
|
+
};
|
|
118
|
+
Created: record {
|
|
119
|
+
cycles: nat64;
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
type ManagedCanisterEventKind128 = variant {
|
|
124
|
+
CyclesSent: record {
|
|
125
|
+
amount: nat;
|
|
126
|
+
refund: nat;
|
|
127
|
+
};
|
|
128
|
+
Called: record {
|
|
129
|
+
method_name: text;
|
|
130
|
+
cycles: nat;
|
|
131
|
+
};
|
|
132
|
+
Created: record {
|
|
133
|
+
cycles: nat;
|
|
134
|
+
};
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
type ManagedCanisterEvent = record {
|
|
138
|
+
id: nat32;
|
|
139
|
+
timestamp: nat64;
|
|
140
|
+
kind: ManagedCanisterEventKind;
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
type ManagedCanisterEvent128 = record {
|
|
144
|
+
id: nat32;
|
|
145
|
+
timestamp: nat64;
|
|
146
|
+
kind: ManagedCanisterEventKind128;
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
type ReceiveOptions = record {
|
|
150
|
+
memo: opt text;
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
type WalletResultCreate = variant {
|
|
154
|
+
Ok : record { canister_id: principal };
|
|
155
|
+
Err: text;
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
type WalletResult = variant {
|
|
159
|
+
Ok : null;
|
|
160
|
+
Err : text;
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
type WalletResultCall = variant {
|
|
164
|
+
Ok : record { return: blob };
|
|
165
|
+
Err : text;
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
type CanisterSettings = record {
|
|
169
|
+
controller: opt principal;
|
|
170
|
+
controllers: opt vec principal;
|
|
171
|
+
compute_allocation: opt nat;
|
|
172
|
+
memory_allocation: opt nat;
|
|
173
|
+
freezing_threshold: opt nat;
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
type CreateCanisterArgs = record {
|
|
177
|
+
cycles: nat64;
|
|
178
|
+
settings: CanisterSettings;
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
type CreateCanisterArgs128 = record {
|
|
182
|
+
cycles: nat;
|
|
183
|
+
settings: CanisterSettings;
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
// Assets
|
|
187
|
+
type HeaderField = record { text; text; };
|
|
188
|
+
|
|
189
|
+
type HttpRequest = record {
|
|
190
|
+
method: text;
|
|
191
|
+
url: text;
|
|
192
|
+
headers: vec HeaderField;
|
|
193
|
+
body: blob;
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
type HttpResponse = record {
|
|
197
|
+
status_code: nat16;
|
|
198
|
+
headers: vec HeaderField;
|
|
199
|
+
body: blob;
|
|
200
|
+
streaming_strategy: opt StreamingStrategy;
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
type StreamingCallbackHttpResponse = record {
|
|
204
|
+
body: blob;
|
|
205
|
+
token: opt Token;
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
type Token = record {};
|
|
209
|
+
|
|
210
|
+
type StreamingStrategy = variant {
|
|
211
|
+
Callback: record {
|
|
212
|
+
callback: func (Token) -> (StreamingCallbackHttpResponse) query;
|
|
213
|
+
token: Token;
|
|
214
|
+
};
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
service : {
|
|
218
|
+
wallet_api_version: () -> (text) query;
|
|
219
|
+
name: () -> (opt text) query;
|
|
220
|
+
set_name: (text) -> ();
|
|
221
|
+
get_controllers: () -> (vec principal) query;
|
|
222
|
+
add_controller: (principal) -> ();
|
|
223
|
+
remove_controller: (principal) -> (WalletResult);
|
|
224
|
+
get_custodians: () -> (vec principal) query;
|
|
225
|
+
authorize: (principal) -> ();
|
|
226
|
+
deauthorize: (principal) -> (WalletResult);
|
|
227
|
+
wallet_balance: () -> (record { amount: nat64 }) query;
|
|
228
|
+
wallet_balance128: () -> (record { amount: nat }) query;
|
|
229
|
+
wallet_send: (record { canister: principal; amount: nat64 }) -> (WalletResult);
|
|
230
|
+
wallet_send128: (record { canister: principal; amount: nat }) -> (WalletResult);
|
|
231
|
+
wallet_receive: (opt ReceiveOptions) -> (); // Endpoint for receiving cycles.
|
|
232
|
+
wallet_create_canister: (CreateCanisterArgs) -> (WalletResultCreate);
|
|
233
|
+
wallet_create_canister128: (CreateCanisterArgs128) -> (WalletResultCreate);
|
|
234
|
+
wallet_create_wallet: (CreateCanisterArgs) -> (WalletResultCreate);
|
|
235
|
+
wallet_create_wallet128: (CreateCanisterArgs128) -> (WalletResultCreate);
|
|
236
|
+
wallet_store_wallet_wasm: (record {
|
|
237
|
+
wasm_module: blob;
|
|
238
|
+
}) -> ();
|
|
239
|
+
wallet_call: (record {
|
|
240
|
+
canister: principal;
|
|
241
|
+
method_name: text;
|
|
242
|
+
args: blob;
|
|
243
|
+
cycles: nat64;
|
|
244
|
+
}) -> (WalletResultCall);
|
|
245
|
+
wallet_call128: (record {
|
|
246
|
+
canister: principal;
|
|
247
|
+
method_name: text;
|
|
248
|
+
args: blob;
|
|
249
|
+
cycles: nat;
|
|
250
|
+
}) -> (WalletResultCall);
|
|
251
|
+
add_address: (address: AddressEntry) -> ();
|
|
252
|
+
list_addresses: () -> (vec AddressEntry) query;
|
|
253
|
+
remove_address: (address: principal) -> (WalletResult);
|
|
254
|
+
get_events: (opt record { from: opt nat32; to: opt nat32; }) -> (vec Event) query;
|
|
255
|
+
get_events128: (opt record { from: opt nat32; to: opt nat32; }) -> (vec Event128) query;
|
|
256
|
+
get_chart: (opt record { count: opt nat32; precision: opt nat64; } ) -> (vec record { nat64; nat64; }) query;
|
|
257
|
+
list_managed_canisters: (record { from: opt nat32; to: opt nat32; }) -> (vec ManagedCanisterInfo, nat32) query;
|
|
258
|
+
get_managed_canister_events: (record { canister: principal; from: opt nat32; to: opt nat32; }) -> (opt vec ManagedCanisterEvent) query;
|
|
259
|
+
get_managed_canister_events128: (record { canister: principal; from: opt nat32; to: opt nat32; }) -> (opt vec ManagedCanisterEvent128) query;
|
|
260
|
+
set_short_name: (principal, opt text) -> (opt ManagedCanisterInfo);
|
|
261
|
+
http_request: (request: HttpRequest) -> (HttpResponse) query;
|
|
262
|
+
}
|
|
263
|
+
DIDL_DOC
|
|
264
|
+
|
|
265
|
+
attr_accessor :identity, :client, :agent, :canister
|
|
266
|
+
|
|
267
|
+
def initialize(iden = nil, wallet_id)
|
|
268
|
+
@identity = iden.nil? ? IcAgent::Identity.new : iden
|
|
269
|
+
@client = IcAgent::Client.new
|
|
270
|
+
@agent = IcAgent::Agent.new(@identity, @client)
|
|
271
|
+
@canister = IcAgent::Canister.new(@agent, wallet_id, DID_FILE)
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
end
|