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

# Solana Contracts

> This guide explains how to interact with the rhino.fi Bridge program on Solana.

## **Contract Overview**

The Bridge program exposes the following function for bridging:

```solidity theme={null}
pub fn deposit_with_id(
    ctx: Context<DepositLiquidity>,
    amount: u64,
    commitment_id: u128,
)
```

## IDL

<AccordionGroup>
  <Accordion title="Bridge Progam IDL">
    ```json idl theme={null}
    {
      version: '0.1.0',
      name: 'bridge',
      constants: [
        {
          name: 'AUTHORITY_SEED',
          type: 'string',
          value: '"authority"',
        },
        {
          name: 'BRIDGE_SEED',
          type: 'string',
          value: '"rhino_bridge"',
        },
      ],
      instructions: [
        {
          name: 'createBridge',
          accounts: [
            {
              name: 'bridge',
              isMut: true,
              isSigner: false,
            },
            {
              name: 'admin',
              isMut: false,
              isSigner: false,
              docs: ['The admin of the Bridge'],
            },
            {
              name: 'payer',
              isMut: true,
              isSigner: true,
              docs: ['The account paying for all rents'],
            },
            {
              name: 'systemProgram',
              isMut: false,
              isSigner: false,
              docs: ['Solana ecosystem accounts'],
            },
          ],
          args: [],
        },
        {
          name: 'deposit',
          accounts: [
            {
              name: 'bridge',
              isMut: false,
              isSigner: false,
            },
            {
              name: 'pool',
              isMut: false,
              isSigner: false,
            },
            {
              name: 'poolAuthority',
              isMut: false,
              isSigner: false,
            },
            {
              name: 'depositor',
              isMut: false,
              isSigner: true,
              docs: ['The account paying for all rents'],
            },
            {
              name: 'mint',
              isMut: false,
              isSigner: false,
            },
            {
              name: 'poolAccount',
              isMut: true,
              isSigner: false,
            },
            {
              name: 'depositorAccount',
              isMut: true,
              isSigner: false,
            },
            {
              name: 'payer',
              isMut: true,
              isSigner: true,
              docs: ['The account paying for all rents'],
            },
            {
              name: 'tokenProgram',
              isMut: false,
              isSigner: false,
              docs: ['Solana ecosystem accounts'],
            },
            {
              name: 'associatedTokenProgram',
              isMut: false,
              isSigner: false,
            },
            {
              name: 'systemProgram',
              isMut: false,
              isSigner: false,
            },
            {
              name: 'eventAuthority',
              isMut: false,
              isSigner: false,
            },
            {
              name: 'program',
              isMut: false,
              isSigner: false,
            },
          ],
          args: [
            {
              name: 'amount',
              type: 'u64',
            },
            {
              name: 'ethAddressUpper',
              type: 'u32',
            },
            {
              name: 'ethAddressLower',
              type: 'u128',
            },
          ],
        },
        {
          name: 'depositWithId',
          accounts: [
            {
              name: 'bridge',
              isMut: false,
              isSigner: false,
            },
            {
              name: 'pool',
              isMut: false,
              isSigner: false,
            },
            {
              name: 'poolAuthority',
              isMut: false,
              isSigner: false,
            },
            {
              name: 'depositor',
              isMut: false,
              isSigner: true,
              docs: ['The account paying for all rents'],
            },
            {
              name: 'mint',
              isMut: false,
              isSigner: false,
            },
            {
              name: 'poolAccount',
              isMut: true,
              isSigner: false,
            },
            {
              name: 'depositorAccount',
              isMut: true,
              isSigner: false,
            },
            {
              name: 'payer',
              isMut: true,
              isSigner: true,
              docs: ['The account paying for all rents'],
            },
            {
              name: 'tokenProgram',
              isMut: false,
              isSigner: false,
              docs: ['Solana ecosystem accounts'],
            },
            {
              name: 'associatedTokenProgram',
              isMut: false,
              isSigner: false,
            },
            {
              name: 'systemProgram',
              isMut: false,
              isSigner: false,
            },
            {
              name: 'eventAuthority',
              isMut: false,
              isSigner: false,
            },
            {
              name: 'program',
              isMut: false,
              isSigner: false,
            },
          ],
          args: [
            {
              name: 'amount',
              type: 'u64',
            },
            {
              name: 'commitmentId',
              type: 'u128',
            },
          ],
        },
        {
          name: 'createPool',
          accounts: [
            {
              name: 'bridge',
              isMut: false,
              isSigner: false,
            },
            {
              name: 'pool',
              isMut: true,
              isSigner: false,
            },
            {
              name: 'poolAuthority',
              isMut: false,
              isSigner: false,
            },
            {
              name: 'mint',
              isMut: false,
              isSigner: false,
            },
            {
              name: 'poolAccount',
              isMut: true,
              isSigner: false,
            },
            {
              name: 'admin',
              isMut: false,
              isSigner: true,
              docs: ['The admin of the Bridge'],
            },
            {
              name: 'payer',
              isMut: true,
              isSigner: true,
              docs: ['The account paying for all rents'],
            },
            {
              name: 'tokenProgram',
              isMut: false,
              isSigner: false,
              docs: ['Solana ecosystem accounts'],
            },
            {
              name: 'associatedTokenProgram',
              isMut: false,
              isSigner: false,
            },
            {
              name: 'systemProgram',
              isMut: false,
              isSigner: false,
            },
          ],
          args: [],
        },
        {
          name: 'allowOperator',
          accounts: [
            {
              name: 'bridge',
              isMut: false,
              isSigner: false,
            },
            {
              name: 'operatorStorage',
              isMut: true,
              isSigner: false,
            },
            {
              name: 'operator',
              isMut: false,
              isSigner: false,
            },
            {
              name: 'admin',
              isMut: false,
              isSigner: true,
              docs: ['The admin of the Bridge'],
            },
            {
              name: 'payer',
              isMut: true,
              isSigner: true,
              docs: ['The account paying for all rents'],
            },
            {
              name: 'systemProgram',
              isMut: false,
              isSigner: false,
              docs: ['Solana ecosystem accounts'],
            },
          ],
          args: [
            {
              name: 'isAllowed',
              type: 'bool',
            },
          ],
        },
        {
          name: 'withdraw',
          accounts: [
            {
              name: 'bridge',
              isMut: false,
              isSigner: false,
            },
            {
              name: 'pool',
              isMut: false,
              isSigner: false,
            },
            {
              name: 'poolAuthority',
              isMut: false,
              isSigner: false,
            },
            {
              name: 'operatorStorage',
              isMut: false,
              isSigner: false,
            },
            {
              name: 'recipient',
              isMut: false,
              isSigner: false,
            },
            {
              name: 'operator',
              isMut: false,
              isSigner: true,
            },
            {
              name: 'mint',
              isMut: false,
              isSigner: false,
            },
            {
              name: 'poolAccount',
              isMut: true,
              isSigner: false,
            },
            {
              name: 'recipientAccount',
              isMut: true,
              isSigner: false,
            },
            {
              name: 'payer',
              isMut: true,
              isSigner: true,
              docs: ['The account paying for all rents'],
            },
            {
              name: 'tokenProgram',
              isMut: false,
              isSigner: false,
              docs: ['Solana ecosystem accounts'],
            },
            {
              name: 'associatedTokenProgram',
              isMut: false,
              isSigner: false,
            },
            {
              name: 'systemProgram',
              isMut: false,
              isSigner: false,
            },
          ],
          args: [
            {
              name: 'amount',
              type: 'u64',
            },
          ],
        },
        {
          name: 'transferAdmin',
          accounts: [
            {
              name: 'bridge',
              isMut: true,
              isSigner: false,
            },
            {
              name: 'newAdmin',
              isMut: false,
              isSigner: false,
              docs: ['The admin of the Bridge'],
            },
            {
              name: 'admin',
              isMut: false,
              isSigner: true,
              docs: ['The admin of the Bridge'],
            },
            {
              name: 'systemProgram',
              isMut: false,
              isSigner: false,
              docs: ['Solana ecosystem accounts'],
            },
          ],
          args: [],
        },
      ],
      accounts: [
        {
          name: 'bridge',
          type: {
            kind: 'struct',
            fields: [
              {
                name: 'admin',
                docs: ['Account that has admin authority over the Bridge'],
                type: 'publicKey',
              },
            ],
          },
        },
        {
          name: 'pool',
          type: {
            kind: 'struct',
            fields: [
              {
                name: 'bridge',
                docs: ['Primary key of the Bridge'],
                type: 'publicKey',
              },
              {
                name: 'mint',
                docs: ['Mint of token A'],
                type: 'publicKey',
              },
            ],
          },
        },
        {
          name: 'operator',
          type: {
            kind: 'struct',
            fields: [
              {
                name: 'operator',
                docs: ['Public key of the operator'],
                type: 'publicKey',
              },
              {
                name: 'isAllowed',
                docs: ['Whether the operator has access'],
                type: 'bool',
              },
            ],
          },
        },
      ],
      events: [
        {
          name: 'BridgedDeposit',
          fields: [
            {
              name: 'from',
              type: 'publicKey',
              index: false,
            },
            {
              name: 'to',
              type: 'publicKey',
              index: false,
            },
            {
              name: 'token',
              type: 'publicKey',
              index: false,
            },
            {
              name: 'amount',
              type: 'u64',
              index: false,
            },
            {
              name: 'ethAddressUpper',
              type: 'u32',
              index: false,
            },
            {
              name: 'ethAddressLower',
              type: 'u128',
              index: false,
            },
          ],
        },
        {
          name: 'BridgedDepositWithId',
          fields: [
            {
              name: 'from',
              type: 'publicKey',
              index: false,
            },
            {
              name: 'to',
              type: 'publicKey',
              index: false,
            },
            {
              name: 'token',
              type: 'publicKey',
              index: false,
            },
            {
              name: 'amount',
              type: 'u64',
              index: false,
            },
            {
              name: 'commitmentId',
              type: 'u128',
              index: false,
            },
          ],
        },
        {
          name: 'BridgeWithdraw',
          fields: [
            {
              name: 'from',
              type: 'publicKey',
              index: false,
            },
            {
              name: 'to',
              type: 'publicKey',
              index: false,
            },
            {
              name: 'amount',
              type: 'u64',
              index: false,
            },
          ],
        },
      ],
      errors: [
        {
          code: 6000,
          name: 'DepositNotAllowed',
          msg: 'DEPOSIT_NOT_ALLOWED',
        },
        {
          code: 6001,
          name: 'Unauthorized',
          msg: 'UNAUTHORIZED',
        },
        {
          code: 6002,
          name: 'NotEnoughLiquidity',
          msg: 'NOT_ENOUGH_LIQUIDITY',
        },
        {
          code: 6003,
          name: 'NotEnoughBalance',
          msg: 'NOT_ENOUGH_BALANCE',
        },
        {
          code: 6004,
          name: 'InvalidAmount',
          msg: 'INVALID_AMOUNT',
        },
      ],
    }
    ```
  </Accordion>
</AccordionGroup>

### Setup

For this example we'll use `@solana/web3.js`, `@solana/spl-token` and `@coral-xyz/anchor` to interact with the contract, but you can replace it with any Solana library of your choice.

Make sure to install it first:

<CodeGroup>
  ```bash yarn theme={null}
  yarn add @solana/web3.js @solana/spl-token @coral-xyz/anchor
  ```

  ```bash npm theme={null}
  npm install @solana/web3.js @solana/spl-token @coral-xyz/anchor
  ```
</CodeGroup>

## Set-up helpers for Solana accounts

```javascript solanaBridgeHelpers.js theme={null}
import { PublicKey } from '@solana/web3.js'
import { getAssociatedTokenAddressSync } from '@solana/spl-token'
import { Buffer } from 'buffer'

export const getSolanaBridgeKey = async (bridgeContractAddress) => {
  const programId = new PublicKey(bridgeContractAddress)
  return PublicKey.findProgramAddressSync([Buffer.from('rhino_bridge')], programId)[0]
}

export const getSolanaPoolKey = async (bridgeContractAddress, mint) => {
  const programId = new PublicKey(bridgeContractAddress)
  const bridgeKey = await getSolanaBridgeKey(bridgeContractAddress)
  const mintId = new PublicKey(mint)
  return PublicKey.findProgramAddressSync([bridgeKey.toBuffer(), mintId.toBuffer()], programId)[0]
}

export const getSolanaPoolAuthority = async (bridgeContractAddress, mint) => {
  const programId = new PublicKey(bridgeContractAddress)
  const bridgeKey = await getSolanaBridgeKey(bridgeContractAddress)
  const mintId = new PublicKey(mint)
  return PublicKey.findProgramAddressSync(
    [bridgeKey.toBuffer(), mintId.toBuffer(), Buffer.from('authority')],
    programId,
  )[0]
}

export const getSolanaPoolTokenAccount = async (bridgeContractAddress, mint) => {
  const poolAuthority = await getSolanaPoolAuthority(bridgeContractAddress, mint)
  const mintId = new PublicKey(mint)
  return getAssociatedTokenAddressSync(mintId, poolAuthority, true)
}

export const getSolanaDepositorAccount = async (secondaryWalletAddress, mint) => {
  const mintId = new PublicKey(mint)
  const depositor = new PublicKey(secondaryWalletAddress)
  return getAssociatedTokenAddressSync(mintId, depositor, true)
}

```

## Interacting with the Contract

To execute a bridge transaction, call the `depositWithId` (ERC20) or `depositNativeWithId` (native) function as follows:

<Info>
  The `commitmentId` required by the contract corresponds to the `quoteId` returned by the API.

  To obtain the `commitmentId`, first request a quote from the API, then commit it. The response will include the `quoteId`, which should be used as the `commitmentId` in the contract call.

  See [the API bridge example](/api-integration/bridge#6-full-example) for details.
</Info>

<CodeGroup>
  ```javascript anchor theme={null}
  import {Connection, PublicKey} from '@solana/web3.js'
  import {AnchorProvider, Program, BN} from '@coral-xyz/anchor'
  import {
    getSolanaBridgeKey,
    getSolanaDepositorAccount,
    getSolanaPoolAuthority,
    getSolanaPoolKey,
    getSolanaPoolTokenAccount,
  } from './solanaBridgeHelpers'
  import {IDL} from "./idl";
  import getBridgeConfigs from './getBridgeConfigs'

  // Import a solana wallet / or use your wallet library
  const secretKey = base58.decode(SOLANA_PRIVATE_KEY)
  const keypair = Keypair.fromSecretKey(new Uint8Array(secretKey))
  const wallet = new Wallet(keypair)

  export const callSolanaBridgeContract = async (
    {
      token,
      chain, // SOLANA
      commitmentId,
      amount,
    }) => {
    // See API Integration -> Fetch Bridge Configs for the full implementation
    const configs = await getBridgeConfigs()
    const chainConfig = configs[chain]

    const solanaWalletAddress = wallet.publicKey.toString()

    const tokenConfig = chainConfig.tokens[token]
    const tokenAmount = +amount * 10 ** tokenConfig.decimals
    const tokenAddress = tokenConfig.address
    const bridgeContractAddress = chainConfig.contractAddress

    const connection = new Connection(chainConfig.rpc)

    const options = AnchorProvider.defaultOptions()
    const anchorProvider = new AnchorProvider(connection, wallet, options)

    const depositor = new PublicKey(solanaWalletAddress)
    const bridgeKey = await getSolanaBridgeKey(bridgeContractAddress)
    const poolKey = await getSolanaPoolKey(bridgeContractAddress, tokenAddress)
    const poolAuthority = await getSolanaPoolAuthority(bridgeContractAddress, tokenAddress)
    const poolAccount = await getSolanaPoolTokenAccount(bridgeContractAddress, tokenAddress)
    const depositorAccount = await getSolanaDepositorAccount(solanaWalletAddress, tokenAddress)

    const program = new Program(IDL, bridgeContractAddress, anchorProvider)

    const accounts = {
    bridge: bridgeKey,
    pool: poolKey,
    poolAuthority,
    poolAccount: poolAccount,
    depositor,
    mint: new PublicKey(tokenAddress),
    depositorAccount: depositorAccount,
  }

    const depositTxHash = await program.methods['depositWithId'](new BN(tokenAmount), new BN(commitmentId, 'hex'))
    .accounts(accounts)
    .signers([])
    .rpc()

    await connection.getSignatureStatus(depositTxHash)

    return depositTxHash
  }
  ```
</CodeGroup>
