Arbitrary data is the expected case arbitrary data, in which case we should
[x] display it as hex-encoded (with 0x prefix) uppercase hexadecimal formatting (thus you'll have to base64 decode it to bytes and convert those bytes into hexadecimal characters;
But since the introduction of the 3Bot Mobile App as well as the Threefold Desktop Wallet there is also a formatting scheme clients can use to allow users to send UTF-8 unicode messages and/or include the sender's id in the arbitrary data.
The format looks as follows:
| 6 Byte | 1 Byte | 1 Byte | 1 Byte | x Bytes | y Bytes |
| ccksum | type | name length (x) | message length (y) | name (opt) | message (opt) |
[x] For this feature you only need to decode, not encode, so this should be quite easy and you can probably implement it following this pseudo code:
base64 decode the arbitrary data to an Uint8Array;
in case the length < 9 (of the array) you already know it cannot be formatted data and you can simply hex-encode it as described at the start of this issue;
else (if the length >= 9), you can skip the checksum, let's not implement that for now, as that would require libraries, so skip the first 6 bytes and check the first byte;
if type byte equals 1, continue, else encode everything as a hex-encoded message as describe above. If ok, skip that type byte and move on, the first 2 bytes (call them byte x and y) can be used as follows:
byte x can be casted to an integer and represents the length of the sender
byte y can be casted to an integer and represents the length of the message
the total length (of the Uint8Array) should be 6+senderLength+messageLength+2 (or senderLength+messageLength+2 in case you already sliced the first 6 bytes off for good), if it is not like that, than let's consider it invalid and simply represent it as a hex-encoded message once again as described at the top of this issue;
if the total length does check out, than you know you can again skip 2 byte (the bytes of the lengths you just read and evaluated), the last step will than involve in:
if senderLength > 0 decoding the first senderLength bytes as an UTF-8 encoded string representing the sender (be careful here as by default javascript uses UTF-16, so you'll have to do some trickery (1));
if senderLength > 0, skip the senderLength bytes, and if messageLength > 0, you'll than have messageLength bytes left that you can decode as an UTF-8 encoded string representing the message (be careful here as by default javascript uses UTF-16, so you'll have to do some trickery (1));
If this all worked, you can show 2 rows, one representing the message and one the sender (or just one row in case just 1 was defined. In case none were defined simply display an empty string as a single row.
(1): not so much trickery turns out, with any modern browser you should be able to do const str = new TextDecoder().decode(bytes)
Arbitrary data is the expected case arbitrary data, in which case we should
0x
prefix) uppercase hexadecimal formatting (thus you'll have to base64 decode it to bytes and convert those bytes into hexadecimal characters;But since the introduction of the 3Bot Mobile App as well as the Threefold Desktop Wallet there is also a formatting scheme clients can use to allow users to send UTF-8 unicode messages and/or include the sender's id in the arbitrary data.
The format looks as follows:
[x] For this feature you only need to decode, not encode, so this should be quite easy and you can probably implement it following this pseudo code:
base64
decode the arbitrary data to anUint8Array
;in case the
length < 9
(of the array) you already know it cannot be formatted data and you can simply hex-encode it as described at the start of this issue;else (if the
length >= 9
), you can skip the checksum, let's not implement that for now, as that would require libraries, so skip the first6 bytes
and check the first byte;if type byte equals 1, continue, else encode everything as a hex-encoded message as describe above. If ok, skip that type byte and move on, the first 2 bytes (call them byte x and y) can be used as follows:
Uint8Array
) should be6+senderLength+messageLength+2
(orsenderLength+messageLength+2
in case you already sliced the first 6 bytes off for good), if it is not like that, than let's consider it invalid and simply represent it as a hex-encoded message once again as described at the top of this issue;2 byte
(the bytes of the lengths you just read and evaluated), the last step will than involve in:if senderLength > 0
decoding the first senderLength bytes as an UTF-8 encoded string representing the sender (be careful here as by default javascript uses UTF-16, so you'll have to do some trickery (1));if senderLength > 0
, skip the senderLength bytes, and ifmessageLength > 0
, you'll than have messageLength bytes left that you can decode as an UTF-8 encoded string representing the message (be careful here as by default javascript uses UTF-16, so you'll have to do some trickery (1));If this all worked, you can show 2 rows, one representing the message and one the sender (or just one row in case just 1 was defined. In case none were defined simply display an empty string as a single row.
(1): not so much trickery turns out, with any modern browser you should be able to do
const str = new TextDecoder().decode(bytes)