I am trying to concatenate two strings and then convert to bytes using pack(). However this prepends some bytes to the front of the result.

var str1 : string = "TEST INDEX #";
var str2 = concat(str1, nat_to_string(index));
var str3 = pack(str2);

The result is 0x05010000000d5445535420494e444558202331. It appears 05010000000d is being prepended.

Is there a way to remove those bytes? Or another builtin function that I have missed?

I tried using slice to remove them (an idea from another post that had the same issue with smartpy).

var byt2 = slice(str3, 0, 6);

However, when adding the result from slice into a var of type map<string, bytes> I get the following error:

Archetype compiler: File "indexer.arl", line 62, characters 1154-1158: Incompatible types: found 'option' but expected 'bytes'

I'm unsure where my vars are getting converted to option.

From what i understand, the prepended bytes contain length information so the slice method might not be very scalable.

I would like to store the result in the token_metadata storage so the prepended bytes are not playing nicely with BCD or tzkt.

Thank you

1 Answer 1


the slice builtin returns an option as mentioned here.

Hence you need to extract the value from the option, with ?= assignment instruction for example:

var byt2 ?= slice(str3, 0, 6) : "INVALID_STR";

You should use VScode to edit archetype because the extension will show you the error in place.

Unfortunately the pack builtin does not use hex encoding or byte encoding that could be read by BCD or tzkt for example; hence you can't really use it for metadata.

If you want hex encoding for example, you can implement it like this:

function string_to_hex(s : string) : string {
  const hex : map<string, string> = [
    (" ","20"); ("!","21"); ("\"","22");("#","23"); ("$","24"); ("%","25"); ("&","26"); ("'","27");
    ("(","28"); (")","29"); ("*","2A"); ("+","2B"); (",","2C"); ("-","2D"); (".","2E"); ("/","2F");
    ("0","30"); ("1","31"); ("2","32"); ("3","33"); ("4","34"); ("5","35"); ("6","36"); ("7","37");
    ("8","38"); ("9","39"); (":","3A"); (";","3B"); ("<","3C"); ("=","3D"); (">","3E"); ("?","3F");
    ("@","40"); ("A","41"); ("B","42"); ("C","43"); ("D","44"); ("E","45"); ("F","46"); ("G","47");
    ("H","48"); ("I","49"); ("J","4A"); ("K","4B"); ("L","4C"); ("M","4D"); ("N","4E"); ("O","4F");
    ("P","50"); ("Q","51"); ("R","52"); ("S","53"); ("T","54"); ("U","55"); ("V","56"); ("W","57");
    ("X","58"); ("Y","59"); ("Z","5A");("[","5B"); ("\\","5C"); ("]","5D"); ("^","5E"); ("_","5F");
    ("`","60"); ("a","61"); ("b","62"); ("c","63"); ("d","64"); ("e","65"); ("f","66"); ("g","67");
    ("h","68"); ("i","69"); ("j","6A"); ("k","6B"); ("l","6C"); ("m","6D"); ("n","6E"); ("o","6F");
    ("p","70"); ("q","71"); ("r","72"); ("s","73"); ("t","74"); ("u","75"); ("v","76"); ("w","77");
    ("x","78"); ("y","79"); ("z","7A"); ("{","7B"); ("|","7C"); ("}","7D"); ("~","7E")
  var res : list<string> = [];
  iter i to length(s) do
    res.prepend((slice(s, abs(i), 1) ? (hex[the] ? the : "") : ""))
  return concat(reverse(res))

if you want string_to_bytes, just let us know, we will provide you with the code.

These two builtins are typically something we could add to the archetype builtins.

  • Thank you Benoit, this was very helpful. I have installed the vscode extension and it's been helpful when integrating the string_to_hex function above. Thank you for the offer about the code for string_to_bytes, that would be helpful as I would like to convert the string to bytes. Maybe some others here would also find it useful. Thanks again!
    – TomCollins
    Commented Feb 24, 2023 at 2:10
  • I modified your code to for string_to_bytes, testing just numbers. Seems to work nicely.
    – TomCollins
    Commented Feb 27, 2023 at 5:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.