---
title: Strings and StringBuilders
description: "Various String and StringBuilder functions from the Core library of Tact"
---

import { Badge } from '@astrojs/starlight/components';

Strings are immutable sequences of characters, which means that once a [`String{:tact}`][p] is created, it cannot be changed. Strings are useful for storing text, so they can be converted to a [`Cell{:tact}`][cell] type to be used as message bodies.

To concatenate strings use a [`StringBuilder{:tact}`][p].

To use [`String{:tact}`][p] literals directly, see: [String literals](/book/expressions#string-literals).

:::note

  Strings on-chain are represented as [slices][slice], which are expensive for handling Unicode strings and quite costly even for ASCII ones. Prefer not to manipulate strings on-chain.

:::

## beginString

```tact
fun beginString(): StringBuilder;
```

Creates and returns an empty [`StringBuilder{:tact}`][p].

Usage example:

```tact
let fizz: StringBuilder = beginString();
```

## beginComment

```tact
fun beginComment(): StringBuilder;
```

Creates and returns an empty [`StringBuilder{:tact}`][p] for building a comment string, which prefixes the resulting [`String{:tact}`][p] with four null bytes. [This format](https://docs.ton.org/v3/guidelines/dapps/asset-processing/nft-processing/metadata-parsing#snake-data-encoding) is used for passing text comments as message bodies.

Usage example:

```tact
let fizz: StringBuilder = beginComment();
```

## beginTailString

```tact
fun beginTailString(): StringBuilder;
```

Creates and returns an empty [`StringBuilder{:tact}`][p] for building a tail string, which prefixes the resulting [`String{:tact}`][p] with a single null byte. This format is used in various standards such as NFT or Jetton.

Usage example:

```tact
let fizz: StringBuilder = beginTailString();
```

## beginStringFromBuilder

```tact
fun beginStringFromBuilder(b: StringBuilder): StringBuilder;
```

Creates and returns a new [`StringBuilder{:tact}`][p] from an existing [`StringBuilder{:tact}`][p] `b`. Useful when you need to serialize an existing [`String{:tact}`][p] to a [`Cell{:tact}`][cell] along with other data.

Usage example:

```tact
let fizz: StringBuilder = beginStringFromBuilder(beginString());
```

## StringBuilder

### StringBuilder.append

```tact
extends mutates fun append(self: StringBuilder, s: String);
```

Extension mutation function for the [`StringBuilder{:tact}`][p] type.

Appends a [`String{:tact}`][p] `s` to the [`StringBuilder{:tact}`][p].

Usage example:

```tact
let fizz: StringBuilder = beginString();
fizz.append("oh");
fizz.append("my");
fizz.append("Tact!");
```

### StringBuilder.concat

```tact
extends fun concat(self: StringBuilder, s: String): StringBuilder;
```

Extension function for the [`StringBuilder{:tact}`][p] type.

Returns a new [`StringBuilder{:tact}`][p] after concatenating it with a [`String{:tact}`][p] `s`. It can be chained, unlike [`StringBuilder.append(){:tact}`](#stringbuilderappend).

Usage example:

```tact
let fizz: StringBuilder = beginString()
    .concat("oh")
    .concat("my")
    .concat("Tact!");
```

### StringBuilder.toString

<Badge text="500+ gas" title="Uses 500 gas units or more" variant="danger" size="medium"/><p/>

```tact
extends fun toString(self: StringBuilder): String;
```

Extension function for the [`StringBuilder{:tact}`][p] type.

Returns a built [`String{:tact}`][p] from a [`StringBuilder{:tact}`][p].

Usage example:

```tact
let fizz: StringBuilder = beginString();
let buzz: String = fizz.toString();
```

### StringBuilder.toCell

<Badge text="500+ gas" title="Uses 500 gas units or more" variant="danger" size="medium"/><p/>

```tact
extends fun toCell(self: StringBuilder): Cell;
```

Extension function for the [`StringBuilder{:tact}`][p] type.

Returns an assembled [`Cell{:tact}`][cell] from a [`StringBuilder{:tact}`][p].

Usage example:

```tact
let fizz: StringBuilder = beginString();
let buzz: Cell = fizz.toCell();
```

### StringBuilder.toSlice

<Badge text="500+ gas" title="Uses 500 gas units or more" variant="danger" size="medium"/><p/>

```tact
extends fun toSlice(self: StringBuilder): Slice;
```

Extension function for the [`StringBuilder{:tact}`][p] type.

Returns an assembled [`Cell{:tact}`][cell] as a [`Slice{:tact}`][slice] from a [`StringBuilder{:tact}`][p]. An alias to [`self.toCell().asSlice(){:tact}`](/ref/core-cells#cellasslice).

Usage example:

```tact
let s: StringBuilder = beginString();
let fizz: Slice = s.toSlice();
let buzz: Slice = s.toCell().asSlice();

fizz == buzz; // true
```

## String

### String.hashData

<Badge text="Available since Tact 1.6" variant="tip" size="medium"/><p/>

```tact
extends fun hashData(self: String): Int;
```

Extension function for the [`String{:tact}`][p] type.

Calculates and returns an [`Int{:tact}`][int] value of the [SHA-256][sha-2] hash of the data bits from the given [`String{:tact}`][p], which should have a number of bits divisible by 8.

Unlike [`sha256(){:tact}`](/ref/core-crypto#sha256), this function is gas-efficient and **only** hashes up to 127 bytes of the given string. Using longer strings will cause collisions if their first 127 bytes are the same.

Attempts to specify a [`String{:tact}`][p] with a number of bits **not** divisible by 8 throw an exception with [exit code 9](/book/exit-codes#9): `Cell underflow`.

Usage example:

```tact
let roll: Int = "Never gonna give you up!".hashData(); // just the hash of the data
```

### String.asSlice

```tact
extends fun asSlice(self: String): Slice;
```

Extension function for the [`String{:tact}`][p] type.

Casts the [`String{:tact}`][p] back to the underlying [`Slice{:tact}`][slice] and returns it. The inverse of [`Slice.asString(){:tact}`](/ref/core-cells#sliceasstring).

Usage example:

```tact
let s: String = "It's alive! It's alive!!!";
let fizz: Slice = s.asSlice();
let buzz: Slice = s.asSlice().asString().asSlice();

fizz == buzz; // true
```

:::note

  See how the `String.asSlice{:tact}` function can be used in practice: [How to convert a `String` to an `Int`](/cookbook/type-conversion#how-to-convert-a-string-to-an-int).

:::

### String.asComment

<Badge text="500+ gas" title="Uses 500 gas units or more" variant="danger" size="medium"/><p/>

```tact
extends fun asComment(self: String): Cell;
```

Extension function for the [`String{:tact}`][p] type.

Returns a [`Cell{:tact}`][cell] from a [`String{:tact}`][p] by prefixing the latter with four null bytes. This format is used for passing text comments as message bodies.

Usage example:

```tact
let s: String = "When life gives you lemons, call them 'yellow oranges' and sell them for double the price.";
let fizz: Cell = s.asComment();

let b: StringBuilder = beginComment();
b.append(s);
let buzz: Cell = b.toCell();

fizz == buzz; // true
```

### String.fromBase64

<Badge text="500+ gas" title="Uses 500 gas units or more" variant="danger" size="medium"/><p/>

```tact
extends fun fromBase64(self: String): Slice;
```

Extension function for the [`String{:tact}`][p] type.

Returns a [`Slice{:tact}`][slice] from the decoded [Base64](https://en.wikipedia.org/wiki/Base64) [`String{:tact}`][p]. An alias to `self.asSlice().fromBase64(){:tact}`.

Note that this function is limited and only takes the first 1023 bits of data from the given [`String{:tact}`][p], without throwing an exception when the [`String{:tact}`][p] is larger (i.e., contains more than 1023 bits of data).

If the given [`String{:tact}`][p] contains characters not from the Base64 set, an exception with [exit code 134](/book/exit-codes#134) will be thrown: `Invalid argument`.

Usage example:

```tact
let s: String = "SGVyZSdzIEpvaG5ueSE=";
let fizz: Slice = s.fromBase64();
let buzz: Slice = s.asSlice().fromBase64();

fizz == buzz; // true
```

## Int.toString

<Badge text="500+ gas" title="Uses 500 gas units or more" variant="danger" size="medium"/><p/>

```tact
extends fun toString(self: Int): String;
```

Extension function for the [`Int{:tact}`][int] type.

Returns a [`String{:tact}`][p] from an [`Int{:tact}`][int] value.

Usage example:

```tact
let fizz: String = (84 - 42).toString();
```

## Int.toFloatString

<Badge text="500+ gas" title="Uses 500 gas units or more" variant="danger" size="medium"/><p/>

```tact
extends fun toFloatString(self: Int, digits: Int): String;
```

Extension function for the [`Int{:tact}`][int] type.

Returns a [`String{:tact}`][p] from an [`Int{:tact}`][int] value using a [fixed-point representation](https://en.wikipedia.org/wiki/Fixed-point_arithmetic) of a fractional number, where `self` is the significant part of the number and `digits` is the number of digits in the fractional part.

More precisely, `digits` is an exponentiation parameter of the expression $10^{-\mathrm{digits}}$, which gives the represented fractional number when multiplied by the actual [`Int{:tact}`][int] value. Parameter `digits` is required to be in the closed interval: $0 < \mathrm{digits} < 78$. Otherwise, an exception with [exit code 134](/book/exit-codes#134) will be thrown: `Invalid argument`.

Usage example:

```tact
let fizz: String = (42).toFloatString(9); // "0.000000042"
```

## Int.toCoinsString

<Badge text="500+ gas" title="Uses 500 gas units or more" variant="danger" size="medium"/><p/>

```tact
extends fun toCoinsString(self: Int): String;
```

Extension function for the [`Int{:tact}`][int] type.

Returns a [`String{:tact}`][p] from an [`Int{:tact}`][int] value using a [fixed-point representation](https://en.wikipedia.org/wiki/Fixed-point_arithmetic) of a fractional number. An alias to `self.toFloatString(9){:tact}`.

This is used to represent [nanoToncoin](/book/integers#nanotoncoin) [`Int{:tact}`][int] values using strings.

Usage example:

```tact
let nanotons: Int = 42;
let fizz: String = nanotons.toCoinsString();
let buzz: String = nanotons.toFloatString(9);

fizz == buzz; // true, both store "0.000000042"
```

[p]: /book/types#primitive-types
[bool]: /book/types#booleans
[int]: /book/integers
[cell]: /book/cells#cells
[slice]: /book/cells#slices

[sha-2]: https://en.wikipedia.org/wiki/SHA-2#Hash_standard
