# Quickstart

End-to-end recipes for the four things you'll usually want to do: **read**, **buy**, **sell**, and **launch**.

## Setup

```ts
import { TonClient } from "@ton/ton";
import {
  buildBuyTokens, buildSellTransfer, buildLaunchToken, buildOffchainContent,
  getCurveState, getCurveAddress, getJettonWalletAddress, getJettonWalletBalance,
  prepareBuyTx, prepareSellTx, envelopeToTonConnect, sendInternal, pollUntil,
  newRandomQueryId,
  quoteBuyOffchain, quoteSellOffchain, withSlippage,
  tonToNano, nanoToTon, baseUnitsToJettons,
  SELL_FORWARD_TON, SELL_VALUE_TON, TRADE_GAS_BUFFER, LAUNCH_VALUE_TON,
  MAINNET_FACTORY,
} from "@tontonfun/sdk";
import { Address } from "@ton/core";

const client = new TonClient({
  endpoint: "https://toncenter.com/api/v2/jsonRPC",
  apiKey: process.env.TONCENTER_API_KEY, // optional, helps with rate limits
});
```

## Read the curve state

```ts
const curve = Address.parse("EQBM0PUXzH6BAtkGhNo1RKhQLOy1dhuB49EiEtF1AYq6GKR3");
const state = await getCurveState(client, curve);

console.log("Tokens sold:", baseUnitsToJettons(state.tokensSold));
console.log("TON collected:", nanoToTon(state.tonCollected));
console.log("Graduated:", state.graduated);
console.log("Jetton master:", state.jettonMaster.toString());
```

## Off-chain quote

```ts
// What do I get for 1 TON?
const out = quoteBuyOffchain(
  tonToNano(1),
  state.tokensSold,
  state.tonCollected,
);
console.log("1 TON →", baseUnitsToJettons(out), "jettons");

// If I sell 1000 jettons, what TON do I get back?
const back = quoteSellOffchain(
  tonToNano(1000),
  state.tokensSold,
  state.tonCollected,
);
console.log("1000 jettons →", nanoToTon(back), "TON");
```

## Buy

Easiest path — `prepareBuyTx` + your wallet adapter:

```ts
const buyTx = prepareBuyTx({
  curve: "EQBM0PUXzH6BAtkGhNo1RKhQLOy1dhuB49EiEtF1AYq6GKR3",
  tonAmount: tonToNano(1),
  curveState: state,
  slippagePct: 5,
});

// buyTx = { to, value, body, quote: { jettonsOut, minJettonsOut } }
console.log(`You will receive ~${baseUnitsToJettons(buyTx.quote.jettonsOut)} jettons`);

await tonConnectUI.sendTransaction({
  validUntil: Math.floor(Date.now() / 1000) + 360,
  messages: [envelopeToTonConnect(buyTx)],
});
```

If you'd rather build the body manually:

```ts
const minJettonsOut = withSlippage(
  quoteBuyOffchain(tonToNano(1), state.tokensSold, state.tonCollected),
  5, // slippage %
);
const body = buildBuyTokens(newRandomQueryId(), minJettonsOut);

await sendInternal(tonConnectUI.sendTransaction.bind(tonConnectUI), {
  to: "EQBM0PUXzH6BAtkGhNo1RKhQLOy1dhuB49EiEtF1AYq6GKR3",
  valueNano: tonToNano(1) + TRADE_GAS_BUFFER, // +0.2 TON gas reserve
  body,
});
```

## Sell

Sells are TEP-74 `JETTON_TRANSFER` calls to *your* jetton wallet, not the curve. The SDK handles the wire format correctly.

```ts
// 1) Resolve your jetton wallet for this token
const sellerWallet = await getJettonWalletAddress(
  client,
  state.jettonMaster,
  Address.parse(myWalletAddress),
);

// 2) Read your current balance
const balance = await getJettonWalletBalance(client, sellerWallet);

// 3) Build + send
const sellTx = prepareSellTx({
  sellerJettonWallet: sellerWallet,
  curve: "EQBM0PUXzH6BAtkGhNo1RKhQLOy1dhuB49EiEtF1AYq6GKR3",
  seller: myWalletAddress,
  jettonAmount: balance, // sell everything
  curveState: state,
});

await tonConnectUI.sendTransaction({
  validUntil: Math.floor(Date.now() / 1000) + 360,
  messages: [envelopeToTonConnect(sellTx)],
});
```

### ⚠️ If you're rolling your own codec

The curve refunds if the `SELL` op isn't bit-aligned exactly where it expects. Tonton's contracts are Tact-generated and read `forward_payload` as `Slice as remaining` — **no Either-tag bit**. The SDK's `buildSellTransfer` already does this correctly. Don't add `storeBit(false)` before the SELL op.

## Launch

{% stepper %}
{% step %}

### Pin your metadata to IPFS

```ts
// 1) Pin your metadata to IPFS (Pinata, web3.storage, your own gateway).
const imageUri = await pinFile(myImageFile); // returns "ipfs://bafy..."
const metadataUri = await pinJson({
  name: "My Token",
  symbol: "MYT",
  decimals: "9",
  description: "A great token",
  image: imageUri,
  website: "https://example.com",
});
```

{% endstep %}

{% step %}

### Build the content cell

```ts
// 2) Build the content cell
const content = buildOffchainContent(metadataUri);
```

{% endstep %}

{% step %}

### Compute the curve address *before* the tx lands

```ts
// 3) Compute the curve address *before* the tx lands
const curveAddr = await getCurveAddress(
  client,
  Address.parse(MAINNET_FACTORY),
  Address.parse(myWalletAddress),
  content,
);
console.log("Your curve will deploy to:", curveAddr.toString());
```

{% endstep %}

{% step %}

### Build + send

```ts
// 4) Build + send
const body = buildLaunchToken({
  queryId: newRandomQueryId(),
  content,
});

await sendInternal(tonConnectUI.sendTransaction.bind(tonConnectUI), {
  to: MAINNET_FACTORY,
  valueNano: LAUNCH_VALUE_TON, // 0.5 TON
  body,
});
```

{% endstep %}

{% step %}

### (Optional) Poll for the curve to appear

```ts
// 5) (Optional) Poll for the curve to appear
await pollUntil(
  async () => {
    try {
      await getCurveState(client, curveAddr);
      return true;
    } catch {
      return false;
    }
  },
  { intervalMs: 3000, timeoutMs: 120_000 },
);
console.log("Curve is live:", curveAddr.toString());
```

{% endstep %}
{% endstepper %}

## Recovery ops

If a launch's mint into the master bounces (rare network blip), `buildRetryMint` re-triggers it. Send to the curve, value \~0.1 TON, anyone can call.

```ts
const body = buildRetryMint(newRandomQueryId());
// to: the curve address, value: tonToNano(0.1)
```

For graduation deposit recovery (if one half of the LP provide bounced), `buildRetryDeposit` re-emits the missing half. Send to the adapter, value \~0.5 TON, only the creator can call.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.tonton.fun/sdk/quickstart.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
