Have an air-gap setup? Try this scan & send app!

On your AG computer:

  1. Produce message.json using dfx canister sign.
  2. Create a QR code using cat message.json|gzip -c|base64|qrencode -o message.png.
  3. Display message.png picture on the screen, maybe enlarge it to make a good scan target.

On your mobile phone, visit https://p5deo-6aaaa-aaaab-aaaxq-cai.raw.ic0.app, scan the QR code to send!

Caveat: dfx cannot yet produce a request status message in json, so checking request status of an update call is not yet supported.


It is meant to demonstrate a single-page app can be built without any backend (except asset), and also how raw transaction can be sent using regular http POST.

I also think it is possible to build a 3rd-party mobile wallet as a single-page app that talks to the ICP ledger & NNS, maybe even supporting existing Internet Identity too. But that is a separate topic.


Update: Just learned that dfx 0.7.1 already supports request status. Support has been added to the QR code scanner too.

1 Like

That’s really cool, thank you!

Unfortunately the response for get_full_neuron is a buffer, but I’m expecting Result_1 instead. Do we need to decode this with didc?

Annyong 403, can’t post the full answer. It’s written here instead:

Unfortunately the message execution result (most likely a Candid encoded value) cannot be displayed without a schema. I’m still trying to figure out a solution.

1 Like

@cryptoschindler I’ve updated the QR code scanner app to decode call results if it is from the ledger or governance canister. Please give it a try and let me know if you notice any problem.

A more general solution depends on whether the app can grab the candid IDL file of the the call target. I’m hoping someday all canisters can start to offer IDL as a standard service.

1 Like

@cryptoschindler thanks a lot for the nns-command-line-guide article by the way. I feel embarrassed that users have to go through all this pain. Now that the QR scanner app can support displaying results, maybe you can simplify the guide a bit.

Also, I’d suggest you change this line in the article:

(he works for DFINITY so this should be trustworthy).

to something like:

(since the transaction is already signed, the app can’t tamper with it)

What do you think?

1 Like

Hey Paul, thank you for getting back to me and also for the quick update of the app! I’ll test it tomorrow and get back to you :slight_smile:
And thank you for the suggestion regarding the article, I will implement it.

The decoding of principals & accounts doesn’t work yet, it would be nice to have this, otherwise I would need to write another guide on how to decode them :sweat_smile:

It would also be cool to have a copy button on the response so I don’t need to select the whole thing myself on mobile :slight_smile:

Do you have an example call that returns principal or account id?

BTW, the scanner only supports decoding using ledger & governance did file. I think more can be supported if the target canister provides an interface of getting the candid file (motoko canisters by default does this). Or if there is an open service that can return did file to me. Does the canlista canister have such an interface?

1 Like

It can and I’ll add it for you now.

1 Like

It’s this call to the ledger canister

dfx canister --network https://ic0.app --no-wallet sign \
ryjl3-tyaaa-aaaaa-aaaba-cai send_dfx \
    record { 
        memo = 1 : nat64; 
        amount = record {e8s = <AMOUNT_TO_SEND> : nat64}; 
        fee = record {e8s = 10_000 : nat64}; 
        to =  "<DESTINATION_ADDRESS>"

It returns both principals and addresses, but they’re not decoded properly.

That would be strange, because send_dfx only returns block height according to its candid file.

Oh yeah my bad, it’s get_full_neuron! Thanks for the heads up! It’s almost 40 degrees celsius here, I’m apparently malfunctioning :smile:

dfx canister --network=https://ic0.app --no-wallet sign \
rrkah-fqaaa-aaaaa-aaaaq-cai get_full_neuron \

Here you go:

service : {
getCandid: (principal) → ( variant { ok: text; err: variant {noCandidFound} } ) query;

dfx canister --network ic call kyhgh-oyaaa-aaaae-qaaha-cai getCandid ‘(principal “ryjl3-tyaaa-aaaaa-aaaba-cai”)’

That’ll get you the candid for rust (or any other) canisters in the listings, if they provided it.

User submitted candid is checked as valid candid by Canlista, but it currently assumes they submitted the candid that matches the canister id, so that base would need covering in the qr-scanner for now.

(This’ll actually fetch candid for the motoko canisters too.)

Edit: Wrong canister id copied! We’re all human… Updated.

1 Like

Thanks @cryptoschindler and @Ori . I’ve updated the app to print message result as candid instead of JSON. So principal IDs are printed properly, but account is still vec nat8 in candid, which is not pretty printed.

Also it is a lot smarter at figuring out the candid type, so you can use it against almost any canisters. It first tries to use __get_candid_interface_tmp_hack, and if that failed, it will try to use Canlista service.

A copy button is also added. Let me know if you experience any issue. Thanks!