Search code examples
multiversx

Retreive a struct/list of structs as views from a smart contract


I am trying to get the data of a single struct and the data of a list of this struct in view methods in a smart contract. The struct would be something like:

#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, TypeAbi, Clone)]
pub struct Stream<M: ManagedTypeApi> {
    pub id: u64,
    pub payment: BigUint<M>,
    pub enddate: u64,
    pub receiver: ManagedAddress<M>,
}

A single view would be like:

#[view(getStream)]
fn get_stream(&self, id: u64) -> Stream<Self::Api> {
    let payment = self.payment( id.clone() ).get().clone();
    let enddate = self.enddate( id.clone() ).get().clone();
    let receiver = self.receiver( id.clone() ).get().clone();
    Stream {
        id,
        payment,
        enddate,
        receiver,
    }
}

in the mandos tests I would expect something like:

"expect": {
    "out": [
        "u64:1",
        "100,000,000,000",
        "u64:200,000",
        "address:my_address"
    ]
],

but in the test I always get an un-encoded byte result like:

Want: ["u64:1", "100,000,000,000", "u64:200,000", "address:my_address"]. Have: [0x000000000000000100000005174876e8000000000000030d406d795f616464726573735f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f]

I also tried different return types such as ManagedMultiResultVec, ManagedMultiResultVec or MultiResult with ManagedVec in general. But all seem to produce this output for me.

I also could not find out how I can retrieve and decode such a result in a dApp in TypeScript with the erdjs lib.

Can someone tell me what I have missed?


Solution

  • In mandos, you should expect this as out:

    ["u64:1|biguint:100,000,000,000|u64:200,000|address:my_address"]
    

    Or

    {
    "0id": "u64:1",
    "1payment": "biguint:100,000,000,000",
    "2enddate": "u64:200,000",
    "3receiver": "address:my_address"
    }
    

    I think that should be right.

    And in a Dapp, you need the ABI file of the contract and need to do something like:

    const result = ...; // do transaction here
    
    const abi = await SmartContractAbi.fromAbiPath('...abi.json');
    
    result.setEndpointDefinition(abi.getEndpoint('get_stream'));
    
    console.log(result.unpackOutput());
    

    From there you can figure out how to convert the result.