IcAgent
¶ ↑
Ruby Agent Library for the Internet Computer¶ ↑
ic_agent
provides basic modules to interact with canisters on the DFINITY Internet Computer.
Installation¶ ↑
gem install ic_agent
Features¶ ↑
-
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
Modules & Usage¶ ↑
1. Principal¶ ↑
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
2. Identity¶ ↑
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])
3. Client¶ ↑
Create an instance:
client = IcAgent::Client.new(url = "https://ic0.app") client.status
4. Candid¶ ↑
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)
5. Agent¶ ↑
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))
6. Read System State¶ ↑
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")
7. Canister¶ ↑
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()
8. canister: ledger, management, cycles wallet ..¶ ↑
canister common tools:
ledger = IcAgent::Common::Ledger.new ledger.canister.name()
UNIT TEST¶ ↑
bundle exec rspec
Docker¶ ↑
-
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)>
Development¶ ↑
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.
Contributing¶ ↑
Bug reports and pull requests are welcome on GitHub at 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.
License¶ ↑
The gem is available as open source under the terms of the MIT License.
Code of Conduct¶ ↑
Everyone interacting in the IcAgent
project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.