How do I create a StorageMap of Vectors with a tuple of 2 strings?

I need to store this structure in storage:

// sha256(String)
'0x98798....': [
    // Vec<(String, String)>
    ['String Value', 'String Value']
]

I tried implementing it in the following ways:

    • StorageMap<b256, StorageBytes>
      In this case, the StorageBytes represents my Vec<(String, String)> . I tried to allocate and calculate the bytes for each item, but without success.
    • StorageMap<b256, StorageVec<(StorageString, StorageString)>>
      In this case, I couldn’t find a way to insert a StorageString into the StorageVec (I think it might not be possible).
    • StorageMap<b256, StorageVec<Metadata>
      Using a Struct with a String is not possible because the type “pointer” is not allowed in storage.
struct Metadata {
  name: String,
  value: String,
}

To better illustrate, I need to implement the same structure below in Solidity for Sway:

struct Metadata {
    string name;
    string value;
}
    
mapping(address => Metadata[]) public metadataMap;

What the best way to implement this structure?

1 Like

Pinging DevRel, will respond shortly.

1 Like

Hey @luisburigo! Apologies for the late reply but a StorageVec of String inside StorageMap of a b256 is possible.

You got it bang on with #2

Here is a working example for you:

contract;

use std::{
    auth::msg_sender,
    hash::Hash,
    storage::{
        storage_bytes::*,
        storage_string::*,
        storage_vec::*,
    },
    string::String,
};

storage {
    metadata: StorageMap<b256, StorageVec<StorageString>> = StorageMap {},
}

abi MyContract {
    #[storage(read, write)]
    fn test_function() -> bool;
}

impl MyContract for Contract {
    #[storage(read, write)]
    fn test_function() -> bool {
        // Setup and initalize vec storage
        let some_b256 = 0x0000000000000000000000000000000000000000000000000000000000000000;
        storage.metadata.insert(some_b256, StorageVec{});

        // Setup and initialize string storage
        storage.metadata.get(some_b256).push(StorageString{});

        // Store string
        let my_string = String::from_ascii_str("Fuel is blazingly fast");
        storage.metadata.get(some_b256).get(0).unwrap().write_slice(my_string);
        
        assert(storage.metadata.get(some_b256).get(0).unwrap().read_slice().unwrap() == my_string);
        true
    }
}

#[test]
fn test_example() {
    let contract_abi = abi(MyContract, CONTRACT_ID);
    let _ = contract_abi.test_function();
}

Hope this helps! :smile:

1 Like

Hello! Thank you for the response.

I implemented it, and the tests in Sway worked just fine, however, when running it through the TS SDK, the vector decode did not work.

I made another implementation to solve my case, which is at this link: sway-snippets/features/metadata-storage at main · luisburigo/sway-snippets · GitHub

Thank you for the help! :heart:

1 Like