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

# Quickstart

> Submit your first Tachyon intent, the two-step flow, end to end.

<Warning>
  **The TypeScript SDK is WIP.** This page shows the planned shape alongside the real HTTP + contract calls that work today. Every SDK call maps to a real endpoint documented in the [Relayer API reference](/api/relayer).
</Warning>

A complete Tachyon submission is two artifacts:

1. An **on-chain intent**, public, created by calling `BridgeIntentV2.createIntent` on the source chain (solver-facing offer: token pair, amount, reward, destination)
2. An **encrypted recipient bundle**, off-chain, POSTed to the relayer (who actually receives, encrypted so only the relayer and the winning solver ever see plaintext)

Both are needed. The SDK will wrap them into one call; today you make them yourself.

<Note>
  Tachyon is live on testnet. All transactions use test tokens with no real value.
</Note>

## Prerequisites

* A sender wallet with the source-chain asset + some native gas
* A registered recipient (see step 1)
* The bridge contract approved for `amountIn + reward`

## 1. Register the recipient (once per recipient address)

Generates and stores the recipient's viewing/spending keys on the relayer.

```ts theme={null}
const sig = await recipientWallet.signMessage(`REGISTER_STEALTH:${recipientAddress}`);
await fetch("https://relayer.tachyon.pe/recipient/register", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ recipientAddress, signature: sig }),
});
```

Planned SDK:

```ts theme={null}
await tachyon.user.register(recipientAddress, sig);
```

## 2. Approve the bridge contract

Sender approves `tokenIn` for `amountIn + reward`:

```ts theme={null}
import { Contract } from "ethers";
const token = new Contract(tokenIn, erc20ABI, senderWallet);
await (await token.approve(bridgeAddress, amountIn + reward)).wait();
```

## 3. Call `createIntent` on source chain

Publishes the public offer. Returns an `intentId`.

```ts theme={null}
const bridge = new Contract(bridgeAddress, bridgeIntentABI, senderWallet);
await (await bridge.createIntent(
  tokenIn, tokenOut,
  amountIn, minAmountOut,
  reward,
  destChainId,
  auctionDuration,  // e.g. 120 for 2 minutes
)).wait();

const intentId = (await bridge.getLatestIntentId()).toString();
```

## 4. Encrypt and store the recipient bundle

```ts theme={null}
const { publicKey } = await fetch("https://relayer.tachyon.pe/ecies-pubkey").then(r => r.json());

const plaintext = JSON.stringify({
  recipients: [recipientAddress],
  amounts:    [minAmountOut.toString()],
});
const encrypted = await eciesEncrypt(publicKey, Buffer.from(plaintext));

await fetch("https://relayer.tachyon.pe/store-recipients", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    intentId,
    chainId: destChainId,
    encryptedData: encrypted.toString("hex"),
  }),
});
```

Planned SDK wraps steps 3+4 into:

```ts theme={null}
const { intentId } = await tachyon.intent.submit({
  sourceChain: "base_mainnet",
  destChain:   "horizen_mainnet",
  tokenIn,  tokenOut,
  amountIn, minAmountOut, reward,
  deadline: Math.floor(Date.now() / 1000) + 600,
  recipients: [{ address: recipientAddress, amount: minAmountOut }],
}, senderWallet);
```

## 5. Poll to completion

```ts theme={null}
async function waitForCompletion(intentId) {
  while (true) {
    const { intent } = await fetch(`https://relayer.tachyon.pe/intent-details/${intentId}`).then(r => r.json());
    console.log(intent.status); // pending → solving → settled → completed
    if (intent.status === "completed") {
      console.log("Source settle tx:", intent.settleTxHash);
      console.log("Destination solve tx:", intent.solveTxHash);
      return intent;
    }
    await new Promise(r => setTimeout(r, 3000));
  }
}
```

Planned SDK:

```ts theme={null}
tachyon.intent.subscribe(intentId, (intent) => {
  if (intent.status === "completed") console.log(intent.settleTxHash);
});
```

## What just happened under the hood

```mermaid theme={null}
sequenceDiagram
    autonumber
    participant You
    participant Bridge as BridgeIntent (source)
    participant Relayer
    participant Solvers
    participant Dest as Destination chain

    You->>Bridge: createIntent (public solver-facing offer)
    Bridge-->>Bridge: emit encrypted blob (relayer key, on-chain recovery anchor)
    You->>Relayer: POST /store-recipients (ECIES-encrypted)
    Relayer->>Solvers: batched plaintext broadcast (rate, token, fees)
    Solvers->>Relayer: bid to fill a portion
    Relayer-->>Solvers: re-encrypt recipient bundle to winning solver
    Solvers->>Dest: deliver to stealth address
    Relayer->>Bridge: settle (release reward)
```

The only actor that ever sees the plaintext recipient address, outside of the relayer inside its trusted environment, is the one solver that won the bid for your intent.

## Next steps

<CardGroup cols={2}>
  <Card title="Concepts: mental model" icon="compass" href="/concepts/overview">
    Intents, solvers, stealth addresses, viewing keys, settlement.
  </Card>

  <Card title="Privacy guarantees" icon="shield" href="/concepts/privacy-guarantees">
    What's private, what's public, threat model.
  </Card>

  <Card title="Relayer HTTP API" icon="server" href="/api/relayer">
    Every endpoint used above, with full request/response shapes.
  </Card>

  <Card title="Errors" icon="circle-exclamation" href="/reference/errors">
    Error codes you'll encounter and how to handle them.
  </Card>
</CardGroup>
