Include trait metadata in `getContractsInterfaces` output
The contract interfaces returned by the getContractsInterfaces simnet method currently omit information about the expected traits when function parameters accept (direct or nested) trait implementations.
For example, the Clarity function:
(use-trait demo-trait .demo-trait.trait-name)
(define-public (fn-trait-params (trait-implementation <demo-trait>))
(ok true)
)
produces the following interface:
{
"name": "fn-trait-params",
"access": "public",
"args": [
{
"name": "trait-implementation",
"type": "trait_reference"
}
],
"outputs": {
"type": {
"response": {
"ok": "bool",
"error": "none"
}
}
}
}
The "type": "trait_reference" entry is too abstract and lacks metadata about the expected trait. This missing information limits the ability to build higher-level developer tools — for example, a property testing library for Clarity that can automatically generate valid arguments from function interfaces. Such functionality is currently planned for inclusion in Rendezvous v1.0.0. If this feature isn’t implemented upstream, it will instead rely on the workaround described below.
Describe the solution you'd like Include trait details directly in the returned function interface, as found in the contract AST. For example:
{
"name": "fn-trait-params",
"access": "public",
"args": [
{
"name": "trait-implementation",
"type": {
"trait_reference": {
"<Imported/Defined>": {
"name": "trait-name",
"contract_identifier": {
"issuer": [
26,
[109, 120, 222, 123, 6, 37, 223, 191, 193, 108, 58, 138, 87, 53, 246, 220, 61, 195, 242, 206]
],
"name": "demo-trait"
}
}
}
}
}
],
"outputs": {
"type": {
"response": {
"ok": "bool",
"error": "none"
}
}
}
}
Additional context
A workaround already exists in Rendezvous. The approach there recursively parses the function interface, detects "trait_reference" entries, tracks their nesting paths, and then uses the AST to enrich the interface with corresponding trait metadata. The relevant implementation can be found here.
Extending the current info getContractsInterfaces returns would allow the method to return complete and context-rich contract metadata out of the box, enabling more powerful and reliable developer tooling for Clarity.
@BowTiedRadone The contract interface you get in Clarinet is implemented upstream in stacks-core. This is basically the same thing that what the API returns as well (eg: https://api.hiro.so/v2/contracts/interface/SP4SZE494VC2YC5JYG7AYFQ44F5Q4PYV7DVMDPBG/stacking-dao-core-btc-v3)
We'll likely stick to this same data structure it for the foreseeable future.
Maybe another approach would be to augment it with either:
- another method such as
get_trait_reference_metadata(): Map<trait-name, metadata> - or directly extend the
contract_interfacewith it
{
"function": [ ... ],
"trait_references": {
"trait-implementation": {
"<Imported/Defined>": {
"name": "trait-name",
"contract_identifier": {
"issuer": [],
"name": "demo-trait"
}
}
}
}
}
What do you think about this approach?
If this feature isn’t implemented upstream, it will instead rely on the workaround described below
How would you feel about implementing it upstream instead?
@hugo-stacks I’ve been thinking about this. The main challenge we’re facing right now is figuring out which of all the imported or defined trait implementations a specific parameter actually needs.
- another method such as
get_trait_reference_metadata(): Map<trait-name, metadata>
Here, we don’t even know the trait name since the interface only gives us something like arg_name: "trait_reference".
- or directly extend the
contract_interfacewith it
Here, if a parameter can accept multiple trait implementations, we can’t tell which one applies.
Implementing this upstream sounds interesting, but I have another idea to explore. Given this by-trait API endpoint, would it be possible to add a method to clarinet-sdk that retrieves the ABI of the trait, and another that searches the project for valid implementations given the ABI?
we don’t even know the trait name since the interface only gives us something like arg_name: "trait_reference"
Ok, I see. Indeed, "type": "trait_reference" isn't super helpful.
I'll try to dig more and see what's possible here
would it be possible to add a method to clarinet-sdk that retrieves the ABI of the trait, and another that searches the project for valid implementations given the ABI?
Might be, that's a different ask, right?
@hugo-stacks Yes, this came up as another idea. It is a indeed a different ask based on the same pain point. Currently Rendezvous has to search contracts explicitly implementing specific trait references, while the Clarity VM is capable of deciding wether a contract implements a trait just by evaluating the contract source and comparing it to the ABI (I guess that's how it's done). This means Rendezvous users must use (impl-trait ) even if it is not required for deployment.
Yes, I get it. Just trying to keep this issue focused on 1 issue / pain point. To me, this problem:
would it be possible to add a method to clarinet-sdk that retrieves the ABI of the trait, and another that searches the project for valid implementations given the ABI?
Is a different pain-point than the original one - knowing which trait is expected in a function arg
I can open a separate issue for the latter if it helps!
Eventually. Although, while I think we might be able to prioritize this one, the other might not be prioritized soon-ish