Icblast 2.0.6 - alpha. (Not production ready) Just got released.
It is wrapping around Agentjs and provides extra convenience and functionality. It is very opinionated.
What it does: converts all input, passes it to Agentjs actor, then converts the output and returns it.
Opinions:
Opt has to be undefined not []
The main argument against is that Opt Opt Opt Nat8 is valid candid. However, my opinion is that nobody should create APIs that differentiate opt levels. {param:[]}
{param:[[]]}
and {param:[[[]]]}
should be treated the same.
with agentjs you had to write {parm : [[[3]]]}
or {parm: []}
with icblast you have to write {parm:3}
or {}
Using agentjs directly:
icrc1_transfer({"to":{"owner":Principal.fromText("ryjl3-tyaaa-aaaaa-aaaba-cai"),"subaccount":[]},
"fee":[],"memo":[],"from_subaccount":[],"created_at_time":[],"amount":123})
Using icblast:
icrc1_transfer({to: {owner: "ryjl3-tyaaa-aaaaa-aaaba-cai"}, amount: 123})
Both are doing the same thing. Responses also get the same treatment.
Err has to be thrown not returned
Using agentjs:
let resp = await can.balance();
if ("Err" in resp) throw resp.Err;
let balance = resp.Ok.e8s;
You can also write this:
let {Ok : {e8s : balance}} = await can.balance();
// balance = 123123
But then when the canister returns Err, it won’t propagate correctly and you will see something like “Error: Not found e8s in undefined” instead of “Canister error : account not found”
With Icblast:
let {e8s: balance} = await can.balance();
Responses should be easily serializable, so they can get stored in app state
toState(…) will convert nested object values:
- principal → string principal
- uint8array → hex string
- other typed arrays → array
- biging → string bigint
toState is optional
let x = await can.get_things()
let sum = x + 1_000n;
// also handle binary data
// when you are ready and want to put in state
setState(toState(x));
// or
console.log(JSON.stringify(toState(x))); // you will get error if trying to serialize obj with bigint without toState
// also (without toState) Uint8Array will become an object {0:123, 1:221, 3:123,...}
toState will have everything converted, serializable, and ready to be stored in state.
Without icblast’s toState, you will have uint8arrays and bigints nested in your responses which will cause trouble in state, React, Redux, etc…
Actor has to easily handle serialized values:
Once stored in state with toState, the values can be easily used in calls.
Example: In case it stumbles upon a string hex when expecting uint8array, it will convert it automagically . It knows it’s looking for a Principal and it’s fed a string, so why not try to covert it? It will throw if it’s wrong
- string principals → principals
- string hex (accounts & subaccounts) → Uint8array
- string bigint → bigint
This is valid:
ledger.transfer({
owner: "ryjl3-tyaaa-aaaaa-aaaba-cai",
subaccount:"ffee00"},
amount: "232423234234234"}
The Interface description the generated idl.js has to be traversable
Currently, it’s not easily traversable.
Icblast’s explainer(idlFactory)
will do some magic and return a traversable obj. Good for explorers and other advanced usages like all the conversions above.
Github: [GitHub - infu/icblast]
Try the new icblast interface at Blast [https://jglts-daaaa-aaaai-qnpma-cai.ic0.app/]
Not properly tested yet and also not tested with all versions of agentjs.
NPM package will change and dependencies will be removed.
Expect beta release soon. If you have any extra ideas, they are welcome.
For whoever is interested in how the magic works - icblast/actress.js at main · infu/icblast · GitHub