Skip to content

Instantly share code, notes, and snippets.

@webdeb
Created April 23, 2024 00:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save webdeb/be254c6fec31bd0e9a2f5e6a950c817a to your computer and use it in GitHub Desktop.
Save webdeb/be254c6fec31bd0e9a2f5e6a950c817a to your computer and use it in GitHub Desktop.
To `encode` / `decode` offChainContent for TON (see https://docs.ton.org/develop/dapps/asset-processing/metadata#snake-data-encoding)
import { BitBuilder, BitReader, Cell, beginCell } from "@ton/ton";
const OFFCHAIN_CONTENT_PREFIX = 0x01;
export function encodeOffChainContent(content: string) {
let data = Buffer.from(content);
let offChainPrefix = Buffer.from([OFFCHAIN_CONTENT_PREFIX]);
data = Buffer.concat([offChainPrefix, data]);
return makeSnakeCell(data);
}
export function decodeOffChainContent(content: Cell) {
let data = flattenSnakeCell(content);
let prefix = data[0];
if (prefix !== OFFCHAIN_CONTENT_PREFIX) {
throw new Error(`Unknown content prefix: ${prefix.toString(16)}`);
}
return data.subarray(1).toString();
}
export function makeSnakeCell(data: Buffer): Cell {
const chunks = bufferToChunks(data, 127);
if (chunks.length === 0) {
return beginCell().endCell();
}
if (chunks.length === 1) {
return beginCell().storeBuffer(chunks[0]).endCell();
}
let curCell = beginCell();
for (let i = chunks.length - 1; i >= 0; i--) {
const chunk = chunks[i];
curCell.storeBuffer(chunk);
if (i - 1 >= 0) {
const nextCell = beginCell();
nextCell.storeRef(curCell);
curCell = nextCell;
}
}
return curCell.endCell();
}
export function flattenSnakeCell(cell: Cell): Buffer {
let c: Cell | null = cell;
const bitResult = new BitBuilder();
while (c) {
const cs = c.beginParse();
if (cs.remainingBits === 0) {
break;
}
const data = cs.loadBits(cs.remainingBits);
bitResult.writeBits(data);
c = c.refs && c.refs[0];
}
const endBits = bitResult.build();
const reader = new BitReader(endBits);
return reader.loadBuffer(reader.remaining / 8);
}
function bufferToChunks(buff: Buffer, chunkSize: number) {
let chunks: Buffer[] = [];
while (buff.byteLength > 0) {
chunks.push(buff.subarray(0, chunkSize));
buff = buff.subarray(chunkSize);
}
return chunks;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment