# Developer guide

## API Documentation

The Genius Bridge Protocol provides a comprehensive REST API for developers to integrate cross-chain functionality into their applications. Our API is designed for simplicity, reliability, and performance.

#### Base URLs

* Production: `https://api.geniusbridge.com/v1`
* Staging: `https://genius-bridge-staging-894762848.us-east-2.elb.amazonaws.com/quoting`&#x20;

### Endpoints

TODO: add correct link here

The details of the various available endpoints are present at [here](http://genius-bridge-staging-894762848.us-east-2.elb.amazonaws.com/api/v1/docs)

## SDK integration

#### Installation

```bash
# JavaScript/TypeScript
npm install genius-bridge-sdk
```

#### Basic Setup

TODO: to add

## Executing Solana transactions

When executing cross-chain swaps involving Solana, the GBP API returns an array of base58-encoded Solana transactions that must be executed in a specific sequence. These transactions are designed to work atomically using Jito bundles for optimal execution.

**Transaction Types**

1. **Swap Transactions** (all except last): Convert user's desired token to USDC via aggregators
2. **Order Creation** (last transaction): Creates an order on the Genius Solana Pool

Transactions must be executed in the exact order received:

```
// ❌ Don't execute in parallel
await Promise.all(transactions.map(tx => connection.sendTransaction(tx)));

// ⚠️ Execute sequentially, but not recommended
for (const transaction of transactions) {
  await connection.sendTransaction(transaction);
}
```

**Atomic Execution with Jito Bundles**

For optimal execution, use Jito bundles to ensure atomicity. Details on using jito can be found [here](https://www.quicknode.com/guides/solana-development/transactions/jito-bundles).

Here is a sample implementation of the transaction execution via jito

```
import {
  Connection,
  Keypair,
  PublicKey,
  SystemProgram,
  TransactionMessage,
  VersionedTransaction,
} from '@solana/web3.js';
import bs58 from 'bs58';

export class JitoService {
  private readonly DEFAULT_JITO_FEE = 200000;
  private readonly jitoTipAccounts = [
    'ADuUkR4vqLUMWXxW9gh6D6L8pMSawimctcNZ5pGwDcEt',
    'DfXygSm4jCyNCybVYYK6DwvWqjKee8pbDmJGcLWNDXjh',
  ];
  private readonly jitoEndpoints = [
    'https://ny.mainnet.block-engine.jito.wtf/api/v1/bundles',
    'https://tokyo.mainnet.block-engine.jito.wtf/api/v1/bundles',
  ];

  constructor() {}

  /**
   * Gets a random validator key from the validator list
   */
  private getRandomValidatorKey(): PublicKey {
    const randomValidator =
      this.jitoTipAccounts[
        Math.floor(Math.random() * this.jitoTipAccounts.length)
      ];
    return new PublicKey(randomValidator);
  }

  /**
   * Bundles transactions for Jito processing
   */
  public async bundle(
    txs: VersionedTransaction[],
    keypair: Keypair,
    connection: Connection,
    additionalSigners: Keypair[] = [],
  ): Promise<string[]> {
    const abortController = new AbortController();

    try {
      const txNum = Math.ceil(txs.length / 3);
      let successNum = 0;
      const results = [];

      const latestBlockhash = await connection.getLatestBlockhash('confirmed');
      for (let i = 0; i < txNum; i++) {
        const upperIndex = (i + 1) * 3;
        const downIndex = i * 3;
        const newTxs = [];

        for (let j = downIndex; j < upperIndex; j++) {
          if (txs[j]) {
            const message = txs[j].message;
            message.recentBlockhash = latestBlockhash.blockhash;
            const txn = new VersionedTransaction(message);
            txn.sign([keypair]);
            try {
              additionalSigners.forEach((signer) => {
                txn.sign([signer]);
              });
            } catch (error) {
              console.log(
                `Failed to sign transaction for index ${j}: `,
                error,
              );
            }
            newTxs.push(txn);
          }
        }

        const success = await this.bulldozer(
          newTxs,
          keypair,
          connection,
          abortController.signal,
        );
        const { success: successValue } = success;
        console.log('successfully finished bulldozer', success);

        if (success && successValue > 0) successNum += 1;
        results.push(success);
      }
      if (successNum == 0) {
        throw new Error('No successful responses received from Jito');
      }
      const successResults = results?.[0]?.signatures?.map((signature) => {
        return signature;
      });
      if (!successResults || successResults.length == 0) {
        throw new Error(
          'Executing Order SOLANA No successful responses received from Jito - transactions failed',
        );
      }
      return successResults;
    } catch (error) {
      console.log(
        'Executing Order SOLANA JITO Error during transaction execution',
        error,
      );
      return [];
    } finally {
      abortController.abort();
    }
  }

  /**
   * Send transactions to Jito block engine
   */
  public async bulldozer(
    txs: VersionedTransaction[],
    payer: Keypair,
    connection: Connection,
    abortSignal: AbortSignal,
  ) {
    try {
      // Get dynamic JITO fee instead of using constant
      const jitoFee = this.DEFAULT_JITO_FEE;

      const jitoFeeWallet = this.getRandomValidatorKey();
      const latestBlockhash = await connection.getLatestBlockhash('confirmed');
      const jitTipTxFeeMessage = new TransactionMessage({
        payerKey: payer.publicKey,
        recentBlockhash: latestBlockhash.blockhash,
        instructions: [
          SystemProgram.transfer({
            fromPubkey: payer.publicKey,
            toPubkey: jitoFeeWallet,
            lamports: jitoFee,
          }),
        ],
      }).compileToV0Message();

      const jitoFeeTx = new VersionedTransaction(jitTipTxFeeMessage);
      jitoFeeTx.sign([payer]);

      const serializedJitoFeeTx = bs58.encode(jitoFeeTx.serialize());
      const serializedTransactions = [
        serializedJitoFeeTx,
        ...txs.map((tx: VersionedTransaction) => bs58.encode(tx.serialize())),
      ];

      const requests = this.jitoEndpoints.map(async (url) => {
        const response = await fetch(url, {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            jsonrpc: '2.0',
            id: 1,
            method: 'sendBundle',
            params: [serializedTransactions],
          }),
          signal: abortSignal,
        });

        if (!response.ok) {
          console.log('not okay response for url', url);
          return null;
        }

        return response.json();
      });
      const results = await Promise.all(requests.map((p) => p.catch((e) => e)));
      console.log('Executing Order SOLANA jitoresults', { results });

      const successfulResults = results
        .filter((result) => result !== null)
        .filter((result) => !(result instanceof Error));

      if (successfulResults.length > 0) {
        txs.map((tx) =>
          console.log(
            `TX Confirmed: https://solscan.io/tx/${bs58.encode(
              tx.signatures[0],
            )}`,
          ),
        );

        return {
          success: 1,
          signatures: txs.map((tx) => bs58.encode(tx.signatures[0])),
          links: txs.map(
            (tx) => `https://solscan.io/tx/${bs58.encode(tx.signatures[0])}`,
          ),
        };
      } else {
        console.log(`No successful responses received for jito`);
      }

      return {
        success: 0,
        error: 'No successful responses received for jito',
      };
    } catch (error) {
      console.log(
        'Executing Order SOLANA JITO Error during transaction execution',
        error,
      );
      return {
        success: 0,
        error,
      };
    }
  }
}

```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.bridgesmarter.com/getting-started/developer-guide.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
