Error passing map field from JS SDK

Hey @philipp.chain @hanssv.chain @nikitafuchs.chain I’m working with some sophia contract where I need to pass a map(int, record) and I’m getting some error.

Here is my contract:

contract CryptoHamster =
   datatype event = NewHamster(indexed int, string, hash)
   
   record leg = {
      number:int,
      name:string}

   record hamster = {legs:map(int, leg)}

   record state = { hamsters: map(int,hamster)}

   stateful entrypoint init() = { hamsters = {} }

   stateful entrypoint addAllHamsterByMap(id:int, hamsters:map(int,hamster)) =
      put(state{hamsters=hamsters})

   entrypoint getHamster(id) =
     state.hamsters[id]

   stateful entrypoint my_sophia_init() = 
     let hamsters={[3]={legs={[3]={number=3,name="nombre"}}}}
     addAllHamsterByMap(3,hamsters)

And here is my test function:

 it('Should check if hamster has been created', async () => {
        let hamster_map = new Map();
        let hamster = new Map();
        let leg = {
            number:1,
            name:'Leg1'
         }
        hamster.set(1,leg)
       
        hamster_map.set(1,hamster)
        await instance.addAllHamsterByMap(1,hamster_map)

        let exists = (await instance.getHamster(1)).decodedResult

        assert.isTrue(exists, 'hamster has not been created')
    })

The error I’m getting is the following:

TypeError: Cannot read property ‘reduce’ of undefined

I tried passing the object directly, different structure and same result, however if I invoke my_sophia_init creating the map it works.

Am I creating the map the wrong way?

1 Like

I also tried this way of map construction:

 const measure_type_map =new Map(
            [
              [1, [1,'Humedad',1,'env_humidity',2]]
        ]);

With the exact same error.

Sorry I know nothing about JS…

Thanks @hanssv.chain, it seems like I’m on the same situation :smiley:

  1. Problem:

Your record hamster = { legs : map(int, leg) } is a record of legs with map inside, but in

let leg = {
  number: 1,
  name: 'Leg1'
}

hamster.set(1, leg)

you don’t add a record to the hamster map, but the map directly.

let hamsters = new Map();
let legs = new Map();
let leg = {
  number: 1,
  name: 'Leg1'
}
legs.set(1, leg)
hamsters.set(1, {legs: legs})
  1. Problem:
    There is a compiler bug that won’t allow decoding of records with only one attribute, as this gets overly optimized. So either you add a second attribute in {legs:map(int, leg)} or you remove the record and directly use the map.
1 Like

The fix for this bug is merged, but I don’t think it has made it into a release yet…

3 Likes

Thanks @philipp.chain !