Goal: Issuance $RUNE. total supply 21,000,000
Calculate the first data in protocol message
The first data push in a protocol message is decoded as a sequence integers. These integers are interpreted as a sequence of (ID, OUTPUT, AMOUNT) tuples
Integers are encoded as prefix varints, where the number of leading ones in a varint determines its length in bytes. There is many types of prefix varints, and here is the Bitcoin
To issue 21000000 rune we use this tuple [0 , 1, 21000000].
But why [0 , 1, 21000000]
?
Copy function encodeBitcoinVarInt(value) {
if (value < 0xfd) {
return [value];
} else if (value <= 0xffff) {
return [0xfd, value & 0xff, (value >> 8) & 0xff];
} else if (value <= 0xffffffff) {
return [0xfe, value & 0xff, (value >> 8) & 0xff, (value >> 16) & 0xff, (value >> 24) & 0xff];
} else {
return [
0xff,
value & 0xff,
(value >> 8) & 0xff,
(value >> 16) & 0xff,
(value >> 24) & 0xff,
(value >> 32) & 0xff,
(value >> 40) & 0xff,
(value >> 48) & 0xff,
(value >> 56) & 0xff,
];
}
}
function encodeBitcoinVarIntTuple(tuple) {
const encodedBytes = tuple.map(encodeBitcoinVarInt).flat();
// Convert the bytes to a hexadecimal string
const hexString = encodedBytes.map(byte => byte.toString(16).padStart(2, '0')).join('');
return hexString;
}
function decodeBitcoinVarInt(bytes, startIndex) {
const prefixByte = bytes[startIndex];
let value, bytesRead;
if (prefixByte < 0xfd) {
value = prefixByte;
bytesRead = 1;
} else if (prefixByte === 0xfd) {
value = bytes[startIndex + 1] + (bytes[startIndex + 2] << 8);
bytesRead = 3;
} else if (prefixByte === 0xfe) {
value =
bytes[startIndex + 1] +
(bytes[startIndex + 2] << 8) +
(bytes[startIndex + 3] << 16) +
(bytes[startIndex + 4] << 24);
bytesRead = 5;
} else {
value =
bytes[startIndex + 1] +
(bytes[startIndex + 2] << 8) +
(bytes[startIndex + 3] << 16) +
(bytes[startIndex + 4] << 24) +
(bytes[startIndex + 5] << 32) +
(bytes[startIndex + 6] << 40) +
(bytes[startIndex + 7] << 48) +
(bytes[startIndex + 8] << 56);
bytesRead = 9;
}
return { value, bytesRead };
}
function decodeBitcoinVarIntTuple(hexString) {
const hexBytes = hexString.match(/.{1,2}/g).map(byte => parseInt(byte, 16));
const decodedValues = [];
let index = 0;
while (index < hexBytes.length) {
const { value, bytesRead } = decodeBitcoinVarInt(hexBytes, index);
decodedValues.push(value);
index += bytesRead;
}
return decodedValues;
}
Here is data of tuple [0, 1, 21000000]
after prefix varints Bitcoin-style encode
Copy 0 => 00
1 => 01
21000000 => fe406f4001
[0, 1, 21000000] => 0001fe406f4001
Calculate the first data in protocol message
The second data push is decoded as two integers, SYMBOL
, DECIMALS
SYMBOL
is a base 26-encoded human readable symbol, similar to that used in ordinal number sat names. The only valid characters are A
through Z
.
Copy // Some code
const bb26 = require("base26");
const text = 'rune';
const formatOrdinalBase26 = (text) => {
const result = (2099999997689999 + 1 - bb26.from(text));
return result;
};
Here is data of tuple [RUNE, 18]
after prefix varints Bitcoin-style encode
Copy RUNE => 2099999997359067 => ffdbf3de59dbf3de59
18 => 12
[RUNE, 18] => ffdbf3de59dbf3de5912
Last result of Protocol message
Copy OP_RETURN 52 0001fe406f4001 ffdbf3de59dbf3de5912