ic_agent
provides basic modules to interact with canisters on the DFINITY Internet Computer.
gem install ic_agent
- principal create and generate
- candid types encode & decode
- support secp256k1 & ed25519 identity
- canister DID file parsing
- canister class, initialized with canister id and DID file
- common canister interfaces: ledger, management, nns, cycles wallet
- BLS Verify
Create an instance:
require "lib/ic_agent/principal"
p = IcAgent::Principal.new # default is management canister id `aaaaa-aa`
p1 = IcAgent::Principal.new(bytes: '') # create an instance from bytes
p2 = IcAgent::Principal.anonymous() # create anonymous principal
p3 = IcAgent::Principal.self_authenticating(pubkey) # create a principal from public key
p4 = IcAgent::Principal.from_str('aaaaa-aa') # create an instance from string
p5 = IcAgent::Principal.from_hex('xxx') # create an instance from hex
Class methods:
p.bytes # principal bytes
p.len # byte array length
p.to_str() # convert to string
Create an instance:
require "lib/ic_agent/identity"
i = IcAgent::Identity.new # create an identity instance, key is randomly generated
i1 = IcAgent::Identity.new(privkey = '833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42') # create an instance from private key
i2 = IcAgent::Identity.new(privkey = '833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42', type = 'secp256k1')
Sign a message and Verify:
msg = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
sig = i.sign(msg) # sig = (der_encoded_pubkey, signature)
ver = i.verify(msg, sig[1])
Create an instance:
client = IcAgent::Client.new(url = "https://ic0.app")
client.status
Encode parameters:
# params is an array, return value is encoded bytes
params = [{'type': IcAgent::Candid::BaseTypes.nat, 'value': 10}]
data = IcAgent::Candid.encode(params)
params = [{'type': IcAgent::Candid::BaseTypes.null, 'value': nil}]
data = IcAgent::Candid.encode(params)
Decode parameters:
# data is bytes, return value is an parameter array
params = IcAgent::Candid.decode(data)
Create an instance:
# Identity and Client are dependencies of Agent
iden = IcAgent::Identity.new
client = IcAgent::Client.new
agent = IcAgent::Agent.new(iden, client)
Query call:
# query the name of token canister `gvbup-jyaaa-aaaah-qcdwa-cai`
name = agent.query_raw("gvbup-jyaaa-aaaah-qcdwa-cai", "name", IcAgent::Candid.encode([]))
Update call:
# transfer 100 token to blackhole address `aaaaa-aa`
params = [
{ 'type': IcAgent::Candid::BaseTypes.principal, 'value': 'aaaaa-aa' },
{ 'type': IcAgent::Candid::BaseTypes.nat, 'value': 10000000000 }
]
result = agent.update_raw("gvbup-jyaaa-aaaah-qcdwa-cai", "transfer", IcAgent::Candid.encode(params))
Create an instance:
# Identity and Client are dependencies of Agent
iden = IcAgent::Identity.new
client = IcAgent::Client.new
agent = IcAgent::Agent.new(iden, client)
time = IcAgent::SyetemState.time(agent, "gvbup-jyaaa-aaaah-qcdwa-cai")
subnet_public_key = IcAgent::SyetemState.subnet_public_key(agent, "gvbup-jyaaa-aaaah-qcdwa-cai", "pjljw-kztyl-46ud4-ofrj6-nzkhm-3n4nt-wi3jt-ypmav-ijqkt-gjf66-uae")
Create a canister instance with candid interface file and canister id, and call canister method with canister instance:
agent = IcAgent::Agent.new(iden, client)
gov_canister_id = 'rrkah-fqaaa-aaaaa-aaaaq-cai'
gov_didl = <<~DIDL_DOC
// type
type AccountIdentifier = record { hash : vec nat8 };
type Action = variant {
RegisterKnownNeuron : KnownNeuron;
ManageNeuron : ManageNeuron;
ExecuteNnsFunction : ExecuteNnsFunction;
RewardNodeProvider : RewardNodeProvider;
SetDefaultFollowees : SetDefaultFollowees;
RewardNodeProviders : RewardNodeProviders;
ManageNetworkEconomics : NetworkEconomics;
ApproveGenesisKyc : ApproveGenesisKyc;
AddOrRemoveNodeProvider : AddOrRemoveNodeProvider;
Motion : Motion;
};
......
DIDL_DOC
gov_canister = IcAgent::Canister.new(agent, gov_canister_id, gov_didl)
res = gov_canister.get_neuron_ids()
canister common tools:
ledger = IcAgent::Common::Ledger.new
ledger.canister.name()
bundle exec rspec
- update to latest image
docker pull tuminfei1981/ruby_ic_agent:latest
- Run image:
docker run -it tuminfei1981/ruby_ic_agent:latest
This will enter the container with a linux shell opened.
/usr/src/app #
- Type
rspec
to run all tests
/usr/src/app # bundle exec rspec
.............................
Finished in 5.56 seconds (files took 0.12067 seconds to load)
29 examples, 0 failures
- Or, type
./bin/console
to enter the ruby interactive environment and run any ic_agent code
/usr/src/app # ./bin/console
[1] pry(main)> p = IcAgent::Principal.new
=> #<IcAgent::Principal:0x000000013a54a548 @bytes="", @hex="", @is_principal=true, @len=0>
[2] pry(main)> p.to_s
=> "aaaaa-aa"
[3] pry(main)>
After checking out the repo, run bin/setup
to install dependencies. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
. To release a new version, update the version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version, push git commits and the created tag, and push the .gem
file to rubygems.org.
Bug reports and pull requests are welcome on GitHub at https://github.com/tuminfei/ic_agent. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.
The gem is available as open source under the terms of the MIT License.
Everyone interacting in the IcAgent project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.