# Tolk-TLB Transpiler

A powerful tool for transpiling Tolk structs to TLB (Type Language Binary) definitions and generating TypeScript wrappers for TON blockchain smart contracts.

## Features

-   🔄 **TLB Transpilation**: Convert Tolk structs to TLB schema definitions
-   🎯 **TypeScript Wrapper Generation**: Generate complete smart contract wrappers
-   🔍 **Constants Extraction**: Extract constants from Tolk code with filtering support
-   🛠️ **CLI & API**: Use via command line or programmatic API
-   📦 **Type Safety**: Full TypeScript support with type definitions

## Installation

```bash
npm install -g @ston-fi/tolk-tlb-transpiler
```

Or use directly:

```bash
npx tolk-tlb-transpiler --help
```

## CLI Usage

### Basic TLB Transpilation (supports imports)

```bash
# Transpile Tolk structs to TLB definitions (imports supported)
tolk-tlb transpile input.tolk

# Custom output directory
tolk-tlb transpile input.tolk -o ./output

# Skip TypeScript generation
tolk-tlb transpile input.tolk --no-ts

# Verbose output
tolk-tlb transpile input.tolk -v
```

### Smart Contract Wrapper Generation (supports imports)

```bash
# Generate TypeScript wrapper for smart contract (imports supported in both files)
tolk-tlb wrapper structures.tolk get-methods.tolk MyContract

# Custom output directory
tolk-tlb wrapper structures.tolk get-methods.tolk MyContract -o ./output

# Custom file name
tolk-tlb wrapper structures.tolk get-methods.tolk MyContract -n contract-wrapper

# Verbose output
tolk-tlb wrapper structures.tolk get-methods.tolk MyContract -v
```

## Programmatic API

### Basic Transpilation

```typescript
import {
    transpileTolkToTlb,
    transpileTolkToTlbDefinitions,
    transpileTolkFileToTlbDefinitions,
} from 'tolk-tlb-transpiler';

const tolkCode = `
struct User {
    id: uint64;
    name: bytes;
    active: bool;
}
`;

// Get formatted TLB string from code string
const tlbString = await transpileTolkToTlb(tolkCode);

// Get TLB definitions array from code string
const tlbDefinitions = await transpileTolkToTlbDefinitions(tolkCode);

// Preferred when working with files that may include imports
const tlbFromFile = await transpileTolkFileToTlbDefinitions('path/to/file.tolk');
```

### Smart Contract Wrapper Generation

```typescript
import { generateContractWrapperFromFiles, generateContractWrapper } from 'tolk-tlb-transpiler';

const structuresCode = `
struct MinterStorage {
    counter: uint64;
    owner: address;
}

struct IncrementMessage {
    amount: uint32;
}

type MinterInternalMessage = IncrementMessage;
`;

const getMethodsCode = `
get counter(): uint64;
get owner(): address;
`;

// Preferred: from files (supports imports in both files)
const result = await generateContractWrapperFromFiles(
    'path/to/structures.tolk',
    'path/to/get-methods.tolk',
    'Minter'
);

// Also available: from raw source strings (no cross-file import resolution)
// const result = await generateContractWrapper(structuresCode, getMethodsCode, 'Minter');

// Access generated code
console.log(result.tlbString); // TLB definitions
console.log(result.typescriptCode); // TypeScript types
console.log(result.wrapperCode); // Contract wrapper class
console.log(result.fullCode); // Complete combined code

// Generated wrapper includes:
// - Static opcodes map for all messages (InternalMessage union)
// - Send methods only for incoming messages (IncomingMessage union)
// - Static body creation methods for each message type
```

### Constants Extraction

```typescript
import { extractConstants, extractErrorConstants } from 'tolk-tlb-transpiler';

const tolkCode = `
const ERROR_INVALID_SIGNATURE = 123;
const ERROR_INSUFFICIENT_BALANCE: int = 456;
const ERROR_UNAUTHORIZED: int = 0x789;
const MAX_SUPPLY = 1000000;
const DEFAULT_DECIMALS: int = 9;
`;

// Extract all constants
const allConstants = await extractConstants(tolkCode);
// {
//   "ERROR_INVALID_SIGNATURE": 123,
//   "ERROR_INSUFFICIENT_BALANCE": 456,
//   "ERROR_UNAUTHORIZED": 1929,
//   "MAX_SUPPLY": 1000000,
//   "DEFAULT_DECIMALS": 9
// }

// Extract only ERROR_ constants
const errorConstants = await extractErrorConstants(tolkCode);
// {
//   "ERROR_INVALID_SIGNATURE": 123,
//   "ERROR_INSUFFICIENT_BALANCE": 456,
//   "ERROR_UNAUTHORIZED": 1929
// }

// Custom filtering with predicate
const largeConstants = await extractConstants(tolkCode, (constant) => constant.value > 500);
// {
//   "ERROR_UNAUTHORIZED": 1929,
//   "MAX_SUPPLY": 1000000
// }
```

#### Supported Number Formats

-   Decimal: `123`
-   Hexadecimal: `0x789`
-   Binary: `0b1010`

#### Available Predicates

```typescript
import { isErrorConstant } from 'tolk-tlb-transpiler';

// Check if constant is an error constant
isErrorConstant(constant); // boolean
```

## Input/Output Examples

### TLB Transpilation

**Input (`user.tolk`):**

```tolk
struct User {
    id: uint64;
    data: cell;
    active: bool;
}
```

**Output (`user.tlb`):**

```tlb
// User
user#_ id:uint64 data:^Cell name:bytes active:bool = User;
```

### Wrapper Generation

**Input Files:**

`structures.tolk`:

```tolk
struct CounterStorage {
    counter: uint64;
    owner: address;
}

struct IncrementMessage {
    amount: uint32;
}

type CounterIncomingMessage = IncrementMessage;

type CounterInternalMessage = IncrementMessage | IncrementResponse;
```

`get-methods.tolk`:

```tolk
get counter(): uint64;
get owner(): address;
```

**Generated Wrapper:**

```typescript
export class Counter implements Contract {
    constructor(readonly address: Address, readonly init?: { code: Cell; data: Cell }) {}

    // Static opcodes map for all messages (incoming + outgoing)
    static readonly opcodes = {
        IncrementMessage: 927538991,
        IncrementResponse: 2135924527,
    } as const;

    static createFromAddress(address: Address) {
        return new Counter(address);
    }

    static createFromConfig(storage: CounterStorage, code: Cell, workchain = 0) {
        const data = beginCell().store(storeCounterStorage(storage)).endCell();
        const init = { code, data };
        return new Counter(contractAddress(workchain, init), init);
    }

    // Send methods generated only from IncomingMessage types
    async sendIncrement(
        provider: ContractProvider,
        via: Sender,
        value: bigint,
        params: IncrementMessageBody
    ) {
        await provider.internal(via, {
            value,
            sendMode: SendMode.PAY_GAS_SEPARATELY,
            body: Counter.createIncrementMessageBody(params),
        });
    }

    async getCounter(provider: ContractProvider): Promise<bigint> {
        const { stack } = await provider.get('counter', []);
        return stack.readBigNumber();
    }

    async getOwner(provider: ContractProvider): Promise<Address> {
        const { stack } = await provider.get('owner', []);
        return stack.readAddress();
    }
}
```

## Command Reference

```bash
# Show help
tolk-tlb --help

# Show version
tolk-tlb --version

# Transpile command help
tolk-tlb transpile --help

# Wrapper command help
tolk-tlb wrapper --help
```
