# Broxus JavaScript Core library

This library provides a comprehensive set of MobX-based models, and utilities for building JavaScript applications
that interact with TVM-based blockchains. It offers reactive state management for smart contracts, tokens,
DEX operations, and more.

## Installation

Install the package as project dependency

```shell
npm install @broxus/js-core
```

```shell
yarn add @broxus/js-core
```

```shell
pnpm add @broxus/js-core
```

```shell
bun add @broxus/js-core
```

## Core

### `AbstractStore`

Base abstract class for creating reactive stores and services with built-in state and data management.

#### Interface

```typescript
abstract class AbstractStore<
    T extends ObjectLiteral = ObjectLiteral,
    U extends ObjectLiteral = ObjectLiteral
> {
    protected _data: T
    protected _state: U
    
    setData<K extends keyof T>(dataOrFn: Pick<T, K> | ((prevData: Readonly<T>) => Pick<T, K>)): this
    setData<K extends keyof T>(key: K, value: T[K]): this
    
    setState<K extends keyof U>(stateOrFn: Pick<U, K> | ((prevState: Readonly<U>) => Pick<U, K>)): this
    setState<K extends keyof U>(key: K, value?: U[K]): this
    
    toJSON(): T
    toJSON(both: true): [T, U]
}
```

#### Example

```typescript
import { AbstractStore } from '@broxus/js-core'
import { makeObservable, observable } from 'mobx'

interface UserData {
    balance: string
    name: string
}

interface UserState {
    error?: string
    isLoading: boolean
}

class UserStore extends AbstractStore<UserData, UserState> {

    constructor() {
        super({
            initialData: { name: '', balance: '0' },
            initialState: { isLoading: false }
        })
        makeObservable(this)
    }
    
    async loadUser(address: string): Promise<void> {
        this.setState('isLoading', true)
        try {
            // Load user data
            this.setData({ balance: '1000', name: 'User' })
        }
        catch (e: any) {
            this.setState('error', e.message)
        }
        finally {
            this.setState('isLoading', false)
        }
    }

}
```

### `SmartContractModel`

Abstract class for creating reactive smart contract wrappers with automatic state synchronization and blockchain event watching.

#### Interface

```typescript
abstract class SmartContractModel<
    T extends SmartContractModelData | ObjectLiteral = SmartContractModelData,
    U extends SmartContractModelState | ObjectLiteral = SmartContractModelState,
> extends AbstractStore<SmartContractModelData & T, SmartContractModelState & U> {
    
    readonly address: Address
    readonly computedStorageData?: {
        accountStatus: 'uninit' | 'frozen' | 'active' | 'nonexist'
        deleteDueLimit: string
        freezeDueLimit: string
        storageFee: string
        storageFeeDebt?: string
    }
    readonly contractState?: FullContractState
    readonly isDeployed?: boolean
    readonly isSyncing?: boolean
    readonly syncedAt?: number
    
    syncContractState(options?: { force?: boolean, ttl?: number }): Promise<FullContractState | undefined>
    watch?(callback?: (data: T, state: U) => void): Promise<Subscriber>
    unwatch?(): Promise<void>
}
```

#### Example

```typescript
import { SmartContractModel } from '@broxus/js-core'
import { ProviderRpcClient } from 'everscale-inpage-provider'

interface CustomContractData {
    owner: Address
    value: string
}

class CustomContract extends SmartContractModel<CustomContractData> {
    constructor(connection: ProviderRpcClient, address: Address) {
        super(connection, address)
    }
    
    async sync() {
        await this.syncContractState({ force: true })
        
        if (!this.isDeployed) {
            throw new Error('Contract not deployed')
        }
        
        // Fetch and set contract data
        this.setData({
            owner: /* ... */,
            value: /* ... */
        })
    }
}
```

### `Endpoint`

Class for creating type-safe HTTP API endpoints with automatic URL generation and request handling.

#### Interface

```typescript
class Endpoint<TParams = undefined, TRequestBody = undefined, TResponse = any> {
    constructor(path: string, basePath?: string)
    
    url(params?: TParams): string
    request(routeParams?: TParams, requestInit?: RequestInit, bodyData?: TRequestBody): Promise<Response>
    fetch<UResponse = TResponse>(routeParams?: TParams, requestInit?: RequestInit, bodyData?: TRequestBody): Promise<UResponse>
    post<UResponse = TResponse>(routeParams?: TParams, requestInit?: RequestInit, bodyData?: TRequestBody): Promise<UResponse>
    put<UResponse = TResponse>(routeParams?: TParams, requestInit?: RequestInit, bodyData?: TRequestBody): Promise<UResponse>
    delete<UResponse = TResponse>(routeParams?: TParams, requestInit?: RequestInit, bodyData?: TRequestBody): Promise<UResponse>
}
```

#### Example

```typescript
import { Endpoint } from '@broxus/js-core'

interface TokenInfo {
    symbol: string
    decimals: number
}

// Create endpoint with route parameters
const tokenEndpoint = new Endpoint<{ address: string }, undefined, TokenInfo>(
    '/tokens/:address',
    'https://api.example.com'
)

// Use the endpoint
const tokenInfo = await tokenEndpoint.fetch({ address: '0:abc...' })
console.log(tokenInfo.symbol) // 'USDT'
```

## Network Configuration

### `MasterChainConfig`

Model for accessing **masterchain** network configuration parameters including gas prices, limits, and message forwarding fees.

#### Features

- Gas prices and limits for masterchain
- Message forwarding prices
- Storage fee parameters
- Real-time configuration updates watching

#### Interface

```typescript
class MasterChainConfig extends SmartContractModel<MasterChainConfigData> {
    readonly gasPrice: string
    readonly gasLimit: string
    readonly gasCredit: string
    readonly blockGasLimit: string
    readonly freezeDueLimit: string
    readonly deleteDueLimit: string
    readonly flatGasLimit: string
    readonly flatGasPrice: string
    readonly specialGasLimit: string
    
    // Message forwarding prices
    readonly lumpPrice: string
    readonly bitPrice: string
    readonly cellPrice: string
    readonly ihrPriceFactor: string
    readonly firstFrac: string
    readonly nextFrac: string
}
```

#### Example

```typescript
import { MasterChainConfig } from '@broxus/js-core'

const masterConfig = await MasterChainConfig.create(
    connection,
    '-1:5555555555555555555555555555555555555555555555555555555555555555',
    { sync: true }
)

console.log(masterConfig.gasPrice) // '1000000'
console.log(masterConfig.gasLimit) // '1000000'
console.log(masterConfig.bitPrice) // '1'
console.log(masterConfig.cellPrice) // '500'

// Watch for configuration updates
await masterConfig.watch((data, state) => {
    console.log('Gas price updated:', data.gasPrice)
})
```

### `ShardChainConfig`

Model for accessing **shardchain** (workchain) network configuration parameters including gas prices, limits, and message forwarding fees.

#### Features

- Gas prices and limits for workchain
- Message forwarding prices
- Storage fee parameters
- Real-time configuration updates watching

#### Interface

```typescript
class ShardChainConfig extends SmartContractModel<ShardChainConfigData> {
    readonly gasPrice: string
    readonly gasLimit: string
    readonly gasCredit: string
    readonly blockGasLimit: string
    readonly freezeDueLimit: string
    readonly deleteDueLimit: string
    readonly flatGasLimit: string
    readonly flatGasPrice: string
    readonly specialGasLimit: string
    
    // Message forwarding prices
    readonly lumpPrice: string
    readonly bitPrice: string
    readonly cellPrice: string
    readonly ihrPriceFactor: string
    readonly firstFrac: string
    readonly nextFrac: string
}
```

#### Example

```typescript
import { ShardChainConfig } from '@broxus/js-core'

const shardConfig = await ShardChainConfig.create(
    connection,
    '-1:5555555555555555555555555555555555555555555555555555555555555555',
    { sync: true }
)

console.log(shardConfig.gasPrice) // '1000000'
console.log(shardConfig.gasLimit) // '10000000'

// Use gas price for transaction calculations
const gasFee = BigInt(shardConfig.gasPrice) * BigInt(estimatedGas)
```

## Models

### `TvmToken`

Model for TVM-based token (TIP-3 standard) with reactive state management and blockchain synchronization.

#### Features

- Automatic token details synchronization (symbol, decimals, totalSupply, etc.)
- Real-time blockchain state watching
- Token wallet management
- Balance queries

#### Interface

```typescript
class TvmToken<T extends TvmTokenData | ObjectLiteral = TvmTokenData>
    extends SmartContractModel<T & TvmTokenData> {
    static Utils: TvmTokenUtils
    static Wallet: typeof TvmTokenWallet
    
    readonly symbol: string
    readonly decimals: number
    readonly name: string
    readonly totalSupply?: string
    readonly rootOwnerAddress?: Address
    readonly verified?: boolean
    
    wallet(ownerAddress: Address | string): Promise<TvmTokenWallet>
    walletOf(ownerAddress: Address | string): Promise<Address>
    balance(ownerAddress: Address | string): Promise<string | undefined>
}
```

#### Example

```typescript
import { TvmToken } from '@broxus/js-core'

const token = await TvmToken.create(
    connection,
    {
        address: '0:a49cd4e158a9a15555e624759e2e4e766d22600b7800d891e46f9291f044a93d',
        symbol: 'WEVER',
        decimals: 9,
        name: 'Wrapped EVER'
    },
    { sync: true, watch: true }
)

console.log(token.symbol) // 'WEVER'
console.log(token.totalSupply) // '1000000000000000'

// Get user wallet
const userWallet = await token.wallet('0:user_address...')
console.log(userWallet.balance) // '100000000'
```

### `TvmTokenWallet`

Model for TVM token wallet with transfer and balance management capabilities.

#### Features

- Balance synchronization
- Token transfers
- Burn operations
- Wallet destruction

#### Interface

```typescript
class TvmTokenWallet extends SmartContractModel<TvmTokenWalletData> {
    static Utils: TvmTokenWalletUtils
    
    readonly balance?: string
    readonly ownerAddress?: Address
    readonly tokenAddress?: Address
    
    transfer(params: TransferParams, args?: SendInternalParams): Promise<DelayedMessageExecution>
    transferToWallet(params: TransferToWalletParams, args?: SendInternalParams): Promise<DelayedMessageExecution>
    burn(params: BurnParams, args?: SendInternalParams): Promise<DelayedMessageExecution>
    destroy(params: DestroyParams, args?: SendInternalParams): Promise<DelayedMessageExecution>
}
```

#### Example

```typescript
import { TvmTokenWallet } from '@broxus/js-core'

const wallet = await TvmTokenWallet.create(
    connection,
    { address: '0:wallet_address...' },
    { sync: true },
    provider
)

// Transfer tokens
await wallet.transfer({
    amount: '1000000000',
    recipient: '0:recipient_address...',
    remainingGasTo: '0:sender_address...'
})
```

### `Dex`

Model for DEX root contract with pair/pool deployment and account management.

#### Features

- DEX account deployment
- Pair creation (constant product AMM)
- Stable pool creation
- Expected address calculation

#### Interface

```typescript
class Dex extends SmartContractModel<DexData> {
    static Utils: DexUtils
    
    readonly manager: Address
    readonly owner: Address
    readonly vault: Address
    
    deployAccount(params: DexDeployAccountParams, args?: SendInternalParams): Promise<Transaction | undefined>
    deployPair(params: DexDeployPairParams, args?: SendInternalParams): Promise<Transaction | undefined>
    deployStablePool(params: DexDeployPoolParams, args?: SendInternalParams): Promise<Transaction | undefined>
    getExpectedAccountAddress(params: { ownerAddress: Address | string }): Promise<Address>
    getExpectedPairAddress(params: { leftRootAddress: Address | string, rightRootAddress: Address | string }): Promise<Address>
    getExpectedPoolAddress(params: { roots: (Address | string)[] }): Promise<Address>
}
```

#### Example

```typescript
import { Dex } from '@broxus/js-core'

const dex = await Dex.create(
    connection,
    '0:dex_root_address...',
    { sync: true }
)

// Deploy user DEX account
await dex.deployAccount({
    ownerAddress: '0:user_address...',
    sendGasTo: '0:user_address...',
    onTransactionSuccess: ({ input }) => {
        console.log('Account deployed:', input.dexAccountAddress)
    }
})
```

### `DexAccount`

Model for user's DEX account with liquidity management capabilities.

#### Features

- Token deposits and withdrawals
- Liquidity provision
- Pool management
- Balance tracking

#### Interface

```typescript
class DexAccount extends SmartContractModel<DexAccountData> {
    static Utils: DexAccountUtils
    
    readonly balances?: Map<string, string>
    readonly ownerAddress: Address
    readonly wallets?: Map<string, Address>
    
    depositToken(params: DepositTokenParams, args?: SendInternalParams): Promise<Transaction | undefined>
    withdrawToken(params: WithdrawTokenParams, args?: SendInternalParams): Promise<Transaction | undefined>
    depositLiquidity(params: DepositLiquidityParams, args?: SendInternalParams): Promise<Transaction | undefined>
    addPool(params: AddPoolParams, args?: SendInternalParams): Promise<Transaction | undefined>
}
```

#### Example

```typescript
import { DexAccount } from '@broxus/js-core'

const account = await DexAccount.create(
    connection,
    { dex, ownerAddress: '0:user_address...' },
    { sync: true }
)

// Deposit tokens to account
await account.depositToken({
    amount: '1000000000',
    tokenAddress: '0:token_address...',
    senderAddress: '0:user_address...',
    recipientTokenWallet: '0:dex_account_wallet...',
    remainingGasTo: '0:user_address...'
})
```

### `DexGasValues`

Model for querying DEX operation gas values and fees.

#### Interface

```typescript
class DexGasValues extends SmartContractModel {
    static Utils: DexGasValuesUtils
    
    getDeployAccountGas(): Promise<string>
    getDepositToAccountGas(): Promise<string>
    getAccountWithdrawGas(params: { deployWalletValue?: string }): Promise<string>
    getAccountDepositGas(params: { autoChange: boolean }): Promise<string>
    getAddPoolGas(params: { N: number }): Promise<string>
    getDeployPoolGas(params: { N: number }): Promise<string>
}
```

### `DexPair`

Model for constant product AMM pair with liquidity operations.

#### Features

- Pair details synchronization
- Balance tracking
- Liquidity withdrawal
- Fee parameters

#### Interface

```typescript
class DexPair extends SmartContractModel<DexPairData> {
    static Utils: DexPairUtils
    
    readonly leftToken: TokenInfo
    readonly rightToken: TokenInfo
    readonly lpToken: TokenInfo
    readonly balances?: Map<string, string>
    readonly feeParams: DexPairFeeParams
    readonly isActive?: boolean
    
    syncBalances(options?: { force?: boolean }): Promise<Map<string, string>>
    withdrawLiquidity(params: WithdrawParams, args?: SendInternalParams): Promise<Transaction | undefined>
}
```

#### Example

```typescript
import { DexPair } from '@broxus/js-core'

const pair = await DexPair.create(
    connection,
    {
        dex,
        leftRootAddress: '0:token1_address...',
        rightRootAddress: '0:token2_address...'
    },
    { sync: true }
)

console.log(pair.leftToken.symbol) // 'USDT'
console.log(pair.rightToken.symbol) // 'WEVER'
console.log(pair.balances) // Map { '0:token1...' => '1000000', ... }
```

### `DexStablePair`

Model for StableSwap pair (2 tokens) with reduced slippage for similar assets.

Similar to `DexPair` but optimized for stable pairs (e.g., USDT-USDC).

### `DexStablePool`

Model for StableSwap pool supporting multiple tokens (N-token pool).

#### Features

- Multi-token pool management
- Virtual price calculation
- Amplification coefficient
- Low slippage swaps for correlated assets

#### Interface

```typescript
class DexStablePool extends SmartContractModel<DexStablePoolData> {
    static Utils: DexStablePoolUtils
    
    readonly tokens: TokenInfo[]
    readonly lpToken: TokenInfo
    readonly balances?: Map<string, string>
    readonly virtualPrice?: string
    readonly feeParams: DexStablePoolFeeParams
    
    withdrawLiquidity(params: WithdrawParams, args?: SendInternalParams): Promise<Transaction | undefined>
}
```

#### Example

```typescript
import { DexStablePool } from '@broxus/js-core'

const pool = await DexStablePool.create(
    connection,
    {
        dex,
        roots: [
            '0:usdt_address...',
            '0:usdc_address...',
            '0:dai_address...'
        ]
    },
    { sync: true }
)

console.log(pool.tokens.length) // 3
console.log(pool.virtualPrice) // '1.002134...'
```

## Other Models

The library also includes the following models:

- **Gauge** - Liquidity mining gauge contract
- **GaugeAccount** - User's gauge account for rewards
- **VoteEscrow** - Vote-escrowed token locking
- **VoteEscrowAccount** - User's vote escrow account
- **VoteEscrowDaoRoot** - DAO governance root
- **VoteEscrowProposal** - Governance proposal
- **TvmTokenFactory** - Token factory contract
- **VaultTokenWallet** - Vault token wallet
- **WrappedCurrencyVault** - Native currency wrapping vault

## Utilities

Each model comes with a static `Utils` class providing low-level ABI interaction methods:

```typescript
// Token utilities
TvmToken.Utils.getDetails(connection, address, state)
TvmToken.Utils.walletOf(connection, { ownerAddress, tokenAddress })
TvmToken.Utils.balance(connection, { walletAddress })

// DEX utilities
Dex.Utils.getExpectedPairAddress(connection, dexAddress, params, state)
DexPair.Utils.getBalances(connection, pairAddress, state)
DexPair.Utils.expectedExchange(connection, pairAddress, amount, state)
```

## License

MIT
