ICRC-13: Canister Interface Detection
icrc: 13
title: ICRC-13 Canister Interface Detection
authors: ?
discussions-to: https://github.com/dfinity/ICRC/issues/13
status: Deliberating
category: ICRC
requires: None
supports: ICRC-12 (optional)
created: 2023-02-28
updated: 2023-02-28
Summary
A set of methods for publishing and detecting which interfaces a canister implements.
References
Introduction
The following is a simple ERC-165 like standard for the internet computer. This standard allows canister developers to explicitly state which standards their canisters supports. This allows integrators to programmatically negotiate how best to communicate between canisters.
Notes
- Canisters on the IC are potentially mutable. We should discuss best practices for how to leverage this standard as an integrator.
- A follow up standard might be created allowing canisters to declare a dependency on a canister and interface.
- Canisters implementing this standard should not be taken at face value. It is up to the developer interfacing with a canister implementing this standard to be aware of potential attack vectors.
- For example a canister could claim to be the ICRC-1 ICP token canister. Don't blindly index off token name.
Standard
icrc13_supports_interface
Given a text interface name like ICRC1, DLIP1v1, EXT returns a bool
icrc13_supported_interfaces
Given a text interface returns a vec text of all supported interfaces.
Candid
service : {
icrc13_supports_interface : (text) -> (bool);
icrc13_supported_interfaces : () -> (vec text);
}
Events
Canisters which implement this standard can choose to optionally implement the ICRC-12 events. Support is optional. However, If developers choose to implement events for ICRC-13 developers MUST implement all of the following ICRC-13 events.
type InterfaceAction = variant {
InterfaceAdded : text; // event_schema = "icrc13.v1.interface.added"
InterfaceRemoved : text; // event_schema = "icrc13.v1.interface.removed"
};
type InterfaceUpdated = record {
updated_at : u64; // When the mutation occurred.
action : opt; // Optional to allow for modification of types
}
A canister can expose its DID file, and ICRC-1 already supports icrc1_supported_standards. But I see how a more generic way of specifying it could be useful.
A text description of the interface may not suffice in this case, and a ERC165 interface signature is a canonical hash of all the function signatures.
Another alternative might be indexing (standard_key, string(candid.did)). But, integrators would still have to write clients.
Long term I have a feeling we can come up with a significantly more powerful set of standards leveraging the candid 'func' type. Until then I see this as a stop gap.
As far as I know canisters are unable to actually introspect on their exports. So, I'm not sure we stand to gain much with the canonical hash methodology and it makes the experience less intuitive for developers. Hash vs String.
Thoughts?