```
   _  __         __               ___           _          _   __          ____
  / |/ /_ ______/ /__ __ _____   / _ )___  ____(_)__  ___ | | / /__ ___ __/ / /_
 /    / // / __/ / -_) // (_-<  / _  / _ \/ __/ / _ \/ _ `/ |/ / _ `/ // / / __/
/_/|_/\_,_/\__/_/\__/\_,_/___/ /____/\___/_/ /_/_//_/\_, /|___/\_,_/\_,_/_/\__/
   ____              __              __  _______  __/___/
  / __/______  ___  / /____ ___  ___/ / / __/ _ \/ //_/
 / _// __/ _ \/ _ \/ __/ -_) _ \/ _  / _\ \/ // / ,<
/_/ /_/  \___/_//_/\__/\__/_//_/\_,_/ /___/____/_/|_|
```

A TypeScript SDK for interacting with Nucleus BoringVault Smart Contracts, providing helper functions for depositing and withdrawing assets across multiple chains.

## Installation

**npm**

```bash
npm install @molecularlabs/nucleus-frontend
```

**yarn**

```bash
yarn add @molecularlabs/nucleus-frontend
```

**pnpm**

```bash
pnpm add @molecularlabs/nucleus-frontend
```

## Requirements

- Node.js >= 16

**Recommended Dependencies**

- Viem >= 2.0.0
- Wagmi >= 2.0.0

## Features

- Deposit assets into vaults across multiple chains
- Bridge assets between supported networks
- Withdraw assets from vaults
- Calculate rates and fees
- TypeScript support with full type definitions

## Usage

### Setup with Wagmi 2.x

```tsx
import { createConfig, http } from 'wagmi'
import { mainnet, boba } from 'wagmi/chains'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { WagmiProvider } from 'wagmi'

const config = createConfig({
  chains: [mainnet, boba],
  transports: {
    [mainnet.id]: http(),
    [boba.id]: http(),
  },
})

const queryClient = new QueryClient()

function App() {
  return (
    <WagmiProvider config={config}>
      <QueryClientProvider client={queryClient}>
        <YourApp />
      </QueryClientProvider>
    </WagmiProvider>
  )
}
```

### Basic Usage Example

```tsx
import { useAccount, useWriteContract, useWaitForTransactionReceipt } from 'wagmi'
import { 
  prepareDepositTransactionData, 
  prepareApproveDepositToken,
  VaultKeys 
} from '@molecularlabs/nucleus-frontend'

function DepositComponent() {
  const { address } = useAccount()
  const { writeContract, data: hash } = useWriteContract()
  const { isLoading, isSuccess } = useWaitForTransactionReceipt({ hash })

  const handleDeposit = async () => {
    if (!address) return

    try {
      // 1. First, prepare approval transaction
      const approvalData = await prepareApproveDepositToken({
        vaultKey: 'bobaeth',
        depositTokenSymbol: 'WETH',
        depositAmount: '1.0',
        chainId: 1, // Ethereum mainnet
      })

      // 2. Execute approval
      await writeContract(approvalData)

      // 3. Prepare deposit transaction
      const depositData = await prepareDepositTransactionData({
        vaultKey: 'bobaeth',
        userAddress: address,
        depositTokenSymbol: 'WETH',
        depositAmount: '1.0',
        chainId: 1,
        slippage: 0.01, // 1% slippage
      })

      // 4. Execute deposit
      await writeContract(depositData)
    } catch (error) {
      console.error('Deposit failed:', error)
    }
  }

  return (
    <div>
      <button onClick={handleDeposit} disabled={isLoading}>
        {isLoading ? 'Processing...' : 'Deposit 1 WETH'}
      </button>
      {isSuccess && <p>Transaction successful!</p>}
    </div>
  )
}
```

## API Reference

### Transaction Preparation Functions

#### prepareDepositTransactionData

Prepares transaction data for depositing assets into a vault.

```ts
import { prepareDepositTransactionData } from '@molecularlabs/nucleus-frontend'

const depositData = await prepareDepositTransactionData({
  vaultKey: 'bobaeth',
  userAddress: '0x1234...',
  depositTokenSymbol: 'WETH',
  depositAmount: '1.0', // Amount as string
  chainId: 1, // Ethereum mainnet
  slippage: 0.01, // 1% slippage (optional)
})

// Use with Wagmi
const { writeContract } = useWriteContract()
await writeContract(depositData)
```

#### prepareDepositAndBridgeTransactionData

Prepares transaction data for depositing and bridging assets across chains.

```ts
import { prepareDepositAndBridgeTransactionData } from '@molecularlabs/nucleus-frontend'

const bridgeData = await prepareDepositAndBridgeTransactionData({
  vaultKey: 'bobaeth',
  depositTokenSymbol: 'WETH',
  depositAmount: '1.0',
  sourceChainId: 1, // Ethereum mainnet
  destinationChainId: 288, // Boba network
  userAddress: '0x1234...',
  slippage: 0.01,
})

// Use with Wagmi
const { writeContract } = useWriteContract()
await writeContract(bridgeData)
```

#### prepareWithdrawTransactionData

Prepares transaction data for withdrawing assets from a vault.

```ts
import { prepareWithdrawTransactionData } from '@molecularlabs/nucleus-frontend'

const withdrawData = await prepareWithdrawTransactionData({
  vaultKey: 'bobaeth',
  chainId: 1,
  userAddress: '0x1234...',
  wantTokenSymbol: 'WETH',
  offerAmount: '1.0', // Amount of vault shares to redeem
  deadline: Math.floor(Date.now() / 1000) + 3600, // 1 hour from now
  slippage: 0.01,
})

// Use with Wagmi
const { writeContract } = useWriteContract()
await writeContract(withdrawData)
```

#### prepareBridgeAndWithdrawTransactionData

Prepares transaction data for bridging and withdrawing assets across chains.

```ts
import { prepareBridgeAndWithdrawTransactionData } from '@molecularlabs/nucleus-frontend'

const bridgeAndWithdrawData = await prepareBridgeAndWithdrawTransactionData({
  vaultKey: 'bobaeth',
  sourceChainId: 288, // Boba network
  destinationChainId: 1, // Ethereum mainnet
  userAddress: '0x1234...',
  wantTokenSymbol: 'WETH',
  offerAmount: '1.0',
  deadline: Math.floor(Date.now() / 1000) + 3600,
  slippage: 0.01,
})

// Execute bridge transaction first
const { writeContract } = useWriteContract()
await writeContract(bridgeAndWithdrawData.bridgeTransactionData)

// Then execute withdraw transaction on destination chain
await writeContract(bridgeAndWithdrawData.withdrawTransactionData)
```

### Approval Functions

#### prepareApproveDepositToken

Prepares approval transaction for deposit tokens.

```ts
import { prepareApproveDepositToken } from '@molecularlabs/nucleus-frontend'

const approvalData = await prepareApproveDepositToken({
  vaultKey: 'bobaeth',
  depositTokenSymbol: 'WETH',
  depositAmount: '1.0', // Optional: specific amount to approve
  chainId: 1,
})

// Use with Wagmi
const { writeContract } = useWriteContract()
await writeContract(approvalData)
```

#### prepareApproveWithdrawToken

Prepares approval transaction for vault shares.

```ts
import { prepareApproveWithdrawToken } from '@molecularlabs/nucleus-frontend'

const approvalData = await prepareApproveWithdrawToken({
  vaultKey: 'bobaeth',
  withdrawAmount: '1.0', // Optional: specific amount to approve
  chainId: 1,
})

// Use with Wagmi
const { writeContract } = useWriteContract()
await writeContract(approvalData)
```

### Utility Functions

#### getVaultByKey

Retrieves vault configuration by key.

```ts
import { getVaultByKey, VaultKeys } from '@molecularlabs/nucleus-frontend'

const vault = await getVaultByKey('bobaeth')
console.log('Available vaults:', VaultKeys)
```

#### Exchange Rate Functions

```ts
import { 
  getDepositExchangeRate, 
  getWithdrawExchangeRate 
} from '@molecularlabs/nucleus-frontend'

// Get deposit exchange rate
const depositRate = await getDepositExchangeRate({
  vaultKey: 'bobaeth',
  depositTokenSymbol: 'WETH',
  depositAmount: '1.0',
  chainId: 1,
})

// Get withdraw exchange rate
const withdrawRate = await getWithdrawExchangeRate({
  vaultKey: 'bobaeth',
  wantTokenSymbol: 'WETH',
  offerAmount: '1.0',
  chainId: 1,
})
```

#### Bridge Fee Functions

```ts
import { getBridgeFee } from '@molecularlabs/nucleus-frontend'

const bridgeFee = await getBridgeFee({
  vaultKey: 'bobaeth',
  sourceChainId: 1,
  destinationChainId: 288,
  bridgeAmount: '1.0',
})
```

#### Approval Check Functions

```ts
import { 
  isDepositSpendApproved, 
  isWithdrawalSpendApproved 
} from '@molecularlabs/nucleus-frontend'

// Check if deposit token is approved
const isDepositApproved = await isDepositSpendApproved({
  vaultKey: 'bobaeth',
  userAddress: '0x1234...',
  depositTokenSymbol: 'WETH',
  depositAmount: '1.0',
  chainId: 1,
})

// Check if vault shares are approved
const isWithdrawApproved = await isWithdrawalSpendApproved({
  vaultKey: 'bobaeth',
  userAddress: '0x1234...',
  withdrawAmount: '1.0',
  chainId: 1,
})
```

## Complete Example with React Hook

```tsx
import { useState } from 'react'
import { useAccount, useWriteContract, useWaitForTransactionReceipt } from 'wagmi'
import { 
  prepareDepositTransactionData,
  prepareApproveDepositToken,
  isDepositSpendApproved,
  VaultKeys 
} from '@molecularlabs/nucleus-frontend'

function useNucleusDeposit() {
  const { address } = useAccount()
  const { writeContract, data: hash } = useWriteContract()
  const { isLoading, isSuccess } = useWaitForTransactionReceipt({ hash })
  const [error, setError] = useState<string | null>(null)

  const deposit = async (
    vaultKey: string,
    tokenSymbol: string,
    amount: string,
    chainId: number,
    slippage = 0.01
  ) => {
    if (!address) {
      setError('No wallet connected')
      return
    }

    try {
      setError(null)

      // Check if approval is needed
      const isApproved = await isDepositSpendApproved({
        vaultKey,
        userAddress: address,
        depositTokenSymbol: tokenSymbol,
        depositAmount: amount,
        chainId,
      })

      if (!isApproved) {
        // Prepare and execute approval
        const approvalData = await prepareApproveDepositToken({
          vaultKey,
          depositTokenSymbol: tokenSymbol,
          depositAmount: amount,
          chainId,
        })

        await writeContract(approvalData)
      }

      // Prepare and execute deposit
      const depositData = await prepareDepositTransactionData({
        vaultKey,
        userAddress: address,
        depositTokenSymbol: tokenSymbol,
        depositAmount: amount,
        chainId,
        slippage,
      })

      await writeContract(depositData)
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Transaction failed')
    }
  }

  return {
    deposit,
    isLoading,
    isSuccess,
    error,
  }
}

// Usage in component
function DepositForm() {
  const { deposit, isLoading, isSuccess, error } = useNucleusDeposit()
  const [amount, setAmount] = useState('1.0')

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault()
    deposit('bobaeth', 'WETH', amount, 1, 0.01)
  }

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="number"
        value={amount}
        onChange={(e) => setAmount(e.target.value)}
        placeholder="Amount"
        step="0.1"
        min="0"
      />
      <button type="submit" disabled={isLoading}>
        {isLoading ? 'Processing...' : 'Deposit WETH'}
      </button>
      {error && <p style={{ color: 'red' }}>{error}</p>}
      {isSuccess && <p style={{ color: 'green' }}>Deposit successful!</p>}
    </form>
  )
}
```

## TypeScript Support

The SDK provides full TypeScript support with comprehensive type definitions:

```ts
import type { 
  VaultKey, 
  ChainId, 
  DepositTransactionData,
  WithdrawTransactionData 
} from '@molecularlabs/nucleus-frontend'

// All functions are fully typed
const depositData: DepositTransactionData = await prepareDepositTransactionData({
  // TypeScript will provide autocomplete and type checking
})
```

## Error Handling

The SDK includes comprehensive error handling:

```ts
try {
  const depositData = await prepareDepositTransactionData({
    vaultKey: 'bobaeth',
    userAddress: '0x1234...',
    depositTokenSymbol: 'WETH',
    depositAmount: '1.0',
    chainId: 1,
  })
} catch (error) {
  if (error instanceof Error) {
    console.error('Deposit preparation failed:', error.message)
  }
}
```

## Supported Networks

- Ethereum Mainnet (Chain ID: 1)
- Boba Network (Chain ID: 288)
- Sei Network (Chain ID: 713715)
- Plume Mainnet (Chain ID: 98866)

## License

MIT