> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ton.org/llms.txt
> Use this file to discover all available pages before exploring further.

<AgentInstructions>

## Submitting Feedback

If you encounter incorrect, outdated, or confusing documentation on this page, submit feedback:

POST https://docs.ton.org/feedback

```json
{
  "path": "/foundations/addresses/serialize",
  "feedback": "Description of the issue"
}
```

Only submit feedback when you have something specific and actionable to report.

</AgentInstructions>

# Reading and writing addresses

export const Image = ({src, darkSrc, alt = '', darkAlt, href, target, height = 342, width = 608, noZoom = false, center = false}) => {
  const isSVG = src.match(/\.svg(?:[#?].*?)?$/i) !== null;
  const shouldInvert = isSVG && !darkSrc;
  const shouldCreateLink = href !== undefined;
  const minPx = 9;
  const maxPx = 608;
  const expectedPx = `a number or a string with a number that is greater than ${minPx - 1} and less than or equal to ${maxPx}`;
  const createInvalidPropCallout = (title, received, expected) => {
    return <Danger>
        <span className="font-bold">
          Invalid <code>{title.toString()}</code> passed!
        </span>
        <br />
        <span className="font-bold">Received: </span>
        {received.toString()}
        <br />
        <span className="font-bold">Expected: </span>
        {expected.toString()}
        {}
      </Danger>;
  };
  const checkValidDimensionValue = value => {
    switch (typeof value) {
      case "string":
      case "number":
        const num = Number(value);
        return Number.isSafeInteger(num) && num >= minPx && num <= maxPx;
      default:
        return false;
    }
  };
  let callouts = [];
  if (height && !checkValidDimensionValue(height)) {
    callouts.push(createInvalidPropCallout("height", height, expectedPx));
  }
  if (width && !checkValidDimensionValue(width)) {
    callouts.push(createInvalidPropCallout("width", width, expectedPx));
  }
  if (callouts.length !== 0) {
    return callouts;
  }
  const heightPx = Number(height);
  const widthPx = Number(width);
  const shouldCenter = center === "true" || center === true ? true : false;
  const shouldNotZoom = noZoom === "true" || noZoom === true ? true : false;
  const images = <>
      <img className="block dark:hidden" src={src} alt={alt} {...height && ({
    height: heightPx
  })} {...width && ({
    width: widthPx
  })} {...(shouldCreateLink || shouldInvert || shouldNotZoom) && ({
    noZoom: "true"
  })} />
      <img className={`hidden dark:block ${shouldInvert ? "invert" : ""}`} src={darkSrc ?? src} alt={darkAlt ?? alt} {...height && ({
    height: heightPx
  })} {...width && ({
    width: widthPx
  })} {...(shouldCreateLink || shouldInvert || shouldNotZoom) && ({
    noZoom: "true"
  })} />
    </>;
  if (shouldCreateLink) {
    if (shouldCenter) {
      return <div style={{
        display: "flex",
        justifyContent: "center"
      }}>
          <a href={href} target={target ?? "_self"}>
            {images}
          </a>
        </div>;
    }
    return <a href={href} target={target ?? "_self"}>
        {images}
      </a>;
  }
  if (shouldCenter) {
    return <div style={{
      display: "flex",
      justifyContent: "center"
    }}>{images}</div>;
  }
  return images;
};

On this page, the main issues of interaction with the addresses are described:

* **how to create and parse**;
* **how to check the validity**;
* **how to convert from one format to another**.

## Using online converter

The best user-friendly online parser and address converter in TON blockchain is [TON Address tool](https://ton.org/address).
If the address is entered in any format, the system will provide all possible formats for the address, provided that it is entered correctly.
Otherwise, a warning will be displayed indicating that the address is invalid.

<Image src="/resources/images/ton-addresses.png" darkSrc="/resources/images/ton-addresses.png" alt="example of query to the tool" />

## Using SDK

There are at least four SDKs for interacting with TON blockchain, written in

* [TypeScript](https://github.com/ton-org/ton);
* [Java](https://github.com/neodix42/ton4j);
* [Go](https://github.com/xssnick/tonutils-go);
* [Python](https://github.com/nessshon/tonutils).

You can use any of them, including for working with addresses. However, we focus here on the most used one: the one written in TypeScript.
Namely, we examine [ton-core address module](https://github.com/ton-org/ton-core/tree/main/src/address).

The internal addresses are represented as instances of the `Address` class. You can access it in your favorite IDE using the following import.

```typescript theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
import { Address } from "@ton/core";

readonly workChain: number;
readonly hash: Buffer;
```

As for the external addresses, they are represented as instances of the `ExternalAddress` class. Similarly, you can access it as follows.

```typescript theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
import { ExternalAddress } from "@ton/core";

readonly value: bigint;
readonly bits: number;
```

### Create, parse, and convert addresses

The creation is simple.

```typescript theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
// There is a hash validation check inside the Address constructor.
const internalAddress = new Address(some_wc, some_valid_hash);

const externalAddress = new ExternalAddress(some_value, some_bits);
```

You can parse the internal addresses string and then convert from one format to another as follows.

```typescript theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
const address1 = Address.parse('EQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPrHF');
const address2 = Address.parse('0:ca6e321c7cce9ecedf0a8ca2492ec8592494aa5fb5ce0387dff96ef6af982a3e');
// or via its convenient wrapper
// const address1 = address('EQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPrHF');

// const address2 = address('0:ca6e321c7cce9ecedf0a8ca2492ec8592494aa5fb5ce0387dff96ef6af982a3e');

// these two addresses are equal
console.log(address1.equals(address2)); // true

// toString arguments: urlSafe    {true means using '-' and '_' instead of '+' and '/'; false means the opposite};
//                     bounceable {true means the address is bounceable; false means non-bounceable};
//                     testOnly   {true means the address is for Testnet; false means for Mainnet}.
// default values: true, true, false.

console.log(address1.toString()); // EQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPrHF
console.log(address1.toString({urlSafe: false})) // EQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff+W72r5gqPrHF
console.log(address1.toString({bounceable: false})) // UQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPuwA
console.log(address1.toString({testOnly: true})) // kQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPgpP
console.log(address1.toString({bounceable: false, testOnly: true})) // 0QDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPleK

// output the address in raw format
console.log(address1.toRawString()); // 0:ca6e321c7cce9ecedf0a8ca2492ec8592494aa5fb5ce0387dff96ef6af982a3e

// returns a Buffer with the user‑friendly format address
address1.toStringBuffer();

// the same for address2
console.log(address2.toString()); // EQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPrHF
console.log(address2.toRawString()); // 0:ca6e321c7cce9ecedf0a8ca2492ec8592494aa5fb5ce0387dff96ef6af982a3e

// returns a Buffer with the raw format address
address2.toStringBuffer();

```

If you are sure that your string accurately represents the address in raw or user-friendly format, you can also use the following methods.

```typescript theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
const address1 = Address.parseFriendly('EQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPrHF');
const address2 = Address.parseRaw('0:ca6e321c7cce9ecedf0a8ca2492ec8592494aa5fb5ce0387dff96ef6af982a3e');
```

**However, there is no separate method for parsing external addresses from a string.**

### Validate addresses

The validity of the address is checked at the time of its parsing. An attempt to parse an invalid address will result in an error.
However, you can check separately whether a string is a valid address in raw or user-friendly formats.

```typescript theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
console.log(Address.isFriendly('EQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPrHF')) // true
console.log(Address.isRaw('EQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPrHF')) // false

console.log(Address.isFriendly('0:ca6e321c7cce9ecedf0a8ca2492ec8592494aa5fb5ce0387dff96ef6af982a3e')) // false
console.log(Address.isRaw('0:ca6e321c7cce9ecedf0a8ca2492ec8592494aa5fb5ce0387dff96ef6af982a3e')) // true
```
