# 🤝🏻 Cooperation-API:🕹Integrate GMGN Solana Trading API

✅ Approved: API Key sent to your email\
❌ Rejected: No notification sent

#### Authentication

* GMGN provides professional users with SOL/BSC/Base/ETH Trading API. Access is granted solely based on sufficient **Trading Volume** on GMGN. Review will be completed within 24 hours after submission
* To access the GMGN Trade API, apply for permission by filling out the following Google Form: <https://forms.gle/CWABDLRe8twvygvy5>
* Upon approval, GMGN will issue an API Key to your email. Include the API Key in the request header with the name: `x-route-key`
* Each API Key is rate-limited to one call every 5 seconds

## 1. **Query Router Endpoint (Anti-MEV Supported):**

```jsx
<https://gmgn.ai/defi/router/v1/sol/tx/get_swap_route?token_in_address=${inputToken}&token_out_address=${outputToken}&in_amount=${amount}&from_address=${fromAddress}&slippage=${slippage}>
```

**Request Method: GET**

**API Key: Upon approval, GMGN will issue it to your email**

**Input Parameters:**

| Parameter           | Type   | Description                                                                                                                                                                                                         |
| ------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| token\_in\_address  | string | The address of the token to spend, e.g., So11111111111111111111111111111111111111112                                                                                                                                |
| token\_out\_address | string | The address of the target token, e.g., 7EYnhQoR9YM3N7UoaKRoA44Uy8JeaZV3qyouov87awMs                                                                                                                                 |
| in\_amount          | string | Amount in lamports, 100000000=0.1SOL                                                                                                                                                                                |
| from\_address       | string | The wallet address initiating the transaction, e.g., 2kpJ5QRh16aRQ4oLZ5LnucHFDAZtEFz6omqWWMzDSNrx                                                                                                                   |
| slippage            | float  | Slippage percentage, e.g., 10 for 10%                                                                                                                                                                               |
| swap\_mode          | string | ExactIn or ExactOut, default is ExactIn                                                                                                                                                                             |
| fee                 | float  | Network priority fees and PRC node tip fees. For example, 0.006, unit SOL. GMGN will automatically allocate node tip tips and network priority fees. If 'is\_anti\_mev' is 'true', 'fee' needs to be at least 0.002 |
| is\_anti\_mev       | bool   | Optional, set 'true' when swap with JITO Anti-MEV                                                                                                                                                                   |
| partner             | string | (optional) partner source name                                                                                                                                                                                      |

Return Parameters:

<table><thead><tr><th width="148">Parameter</th><th width="101">Type</th><th>Description</th></tr></thead><tbody><tr><td>code</td><td>int</td><td>Error code, 0</td></tr><tr><td>msg</td><td>string</td><td>Result description, success</td></tr><tr><td>data</td><td>Object</td><td><p>{</p><p>     quote: {</p><p>       inputMint: 'So11111111111111111111111111111111111111112',</p><p>       inAmount: '50000000',</p><p>       outputMint: '7EYnhQoR9YM3N7UoaKRoA44Uy8JeaZV3qyouov87awMs',</p><p>       outAmount: '77920478752',</p><p>       otherAmountThreshold: '77530876359',</p><p>       swapMode: 'ExactIn',</p><p>       slippageBps: 50,</p><p>       platformFee: null,</p><p>       priceImpactPct: '0',</p><p>       routePlan: [Array],</p><p>       contextSlot: 240893434,</p><p>       timeTaken: 0.04250061</p><p>     },</p><p>     raw_tx: {</p><p>       swapTransaction: 'AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAIDxoVIz70VFGJdL5OoCKmFca4NP2MXOcNEiFO6y6JoFUNGWxA6mmc96B1sKHdcYHTM1M1QYNOOSahRPMddzM8XdRsp8RcOMdvjkujt1otIW/R6tIhAHlyC8kUDXj133RK+Ye1I/p3Gy551653GdDPX3KX0D4dWPXyZvsBemb3XlwHyQ+0ezK8pEPmQbXwZ8Tz3O52/YACoT20v0iE4A7D1bTgIWD7ScmJ4Koq6/mSOQVxqfFkoUZ5qTF4TbXDFfH1U+qMakgEp96ZVF6SJaXlGdV6w0mXkHJVedqOxh5rfjqMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADBkZv5SEXMv/srbpyw5vnvIzlu8X3EmssQ5s6QAAAAAR51VvyMcBu7nTFbs5oFQf9sbLeo/SOUQKxzaJWvBOPBt324ddloZPZy+FGzut5rBy0he1fWzeROoz1hX7/AKlcnp1fowmGSs19gRjTJjE83nuG3xjhl5JKAxhv/p89eoKX5UT/REBqE7f6ZMLP+j7G4V34k14Ax0Fw3q7wE/N9jJclj04kifG7PRApFI4NgwtaE5na/xCEBI572Nvp+Fm0P/on9df2SnTAmx8pWHneSwmrNt/J3VFLMhqns4zl6PSRqslFk9OGKukg94vbePj7SOGor/mX5COZhlMmlOYbCAgABQI6UwcACAAJAyBOAAAAAAAADQYABQAnBwoBAQcCAAUMAgAAAIDw+gIAAAAACgEFARENBgACAAsHCgEBCTMKDAAFAwYCJwsJCQ4JIAoMHAMdAR4aHxsoIiMYDAEEFxkWFQokJiUgCgwSBhMEFBAPESEuwSCbM0HWnIEGAwAAABEBZAABGWQBAhEAZAIDgPD6AgAAAAAgJmwkEgAAADIAAAoDBQAAAQkDegmW2ZAMszm+4Eneq5orFPHiSoriEDigyGyG9FUTd+oGpqilp6GiAp+jq4YFkrWa2UlUnmJKVsvmeovDYVI3GhRB1TB5/repN9MFSEVDREcFQkxGSUuC/JDNwibla4b9UHQsSYKI/HmR9edfsxbKg36RCgUpKAaNi5CGiogCkY4=',</p><p>       lastValidBlockHeight: 221852977,</p><p>       prioritizationFeeLamports: 9601,</p><p>       recentBlockhash: 'HThJomQ74BKBYYfFewg9m5MrRwAsHjrpuTwEcohxpAEW'</p><p>     }</p><p>   }</p></td></tr></tbody></table>

Explanation of data.quote Fields:

| Parameter            | Type   | Description                                                              |
| -------------------- | ------ | ------------------------------------------------------------------------ |
| inputMint            | string | Input token address, e.g., So11111111111111111111111111111111111111112   |
| inAmount             | string | Input token amount in lamports                                           |
| outputMint           | string | Output token address, e.g., 7EYnhQoR9YM3N7UoaKRoA44Uy8JeaZV3qyouov87awMs |
| outputAmount         | string | Expected output amount in lamports                                       |
| otherAmountThreshold | string | Slippage-adjusted value in lamports                                      |
| swapMode             | string | ExactIn or ExactOut                                                      |
| slippageBps          | 50     | Slippage Bps value, with 10000 as the denominator.                       |
| platformFee          | string | Platform fee, null if none                                               |
| priceImpact          | string | Price impact percentage, 0                                               |
| routePlan            | Array  | Routing steps                                                            |
| contextSlot          | int    | Slot number                                                              |
| timeTaken            | float  | Time taken for routing in seconds                                        |

Explanation of routePlan Type:

<figure><img src="https://3168316658-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FcwvUtvEIyqrWZx7sPliY%2Fuploads%2FvN6wHAkyPc411xwnn6bR%2FUntitled.png?alt=media&#x26;token=6a3b0da1-17ad-46ad-be0e-c9b6f6005c42" alt=""><figcaption></figcaption></figure>

Explanation of data.raw\_tx Fields:

| Parameter                 | Type   | Description                                                                                               |
| ------------------------- | ------ | --------------------------------------------------------------------------------------------------------- |
| swapTransaction           | string | Base64-encoded unsigned transaction                                                                       |
| lastValidBlockHeight      | int    | Block height at the time of transaction creation, e.g., 221852977                                         |
| recentBlockhash           | string | Recent block hash at the time of transaction creation, e.g., HThJomQ74BKBYYfFewg9m5MrRwAsHjrpuTwEcohxpAEW |
| prioritizationFeeLamports | int    | Suggested prioritization fee in lamports, e.g., 9601                                                      |

## 2. Submit Transaction Endpoint

```javascript
https://gmgn.ai/txproxy/v1/send_transaction
```

**Request Method: POST**

**After receiving the routing interface response, decode the base64 string and deserialize using `VersionedTransaction`, sign with the local wallet, and then encode the signed transaction in base64 and post to the endpoint:**

{% code overflow="wrap" %}

```javascript
  const swapTransactionBuf = Buffer.from(route.data.raw_tx.swapTransaction, 'base64')
  const transaction = VersionedTransaction.deserialize(swapTransactionBuf)
  transaction.sign([wallet.payer])
  const signedTx = Buffer.from(transaction.serialize()).toString("base64")
```

{% endcode %}

Request Parameters:

| chain     | string | only suport sol so far                            |
| --------- | ------ | ------------------------------------------------- |
| signedTx  | string | Signed transaction, base64-encoded string         |
| isAntiMev | bool   | Optional, set 'true' when swap with JITO Anti-MEV |

Return Parameters:

| code | int    | Error code, 0                                                                                                                                                                                                                                                                                                                                                                                             |
| ---- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| msg  | string | Error code, success                                                                                                                                                                                                                                                                                                                                                                                       |
| data | Object | <p>{<br>"hash": "2WN388zpPEy5zZR1uDGRqYbWotHFWo2Y6atAwfLGwUvDEi8LGk93X9S5pimNMv4uQgpJNf6SFQbZF83XbvgTuikj"<br>"resArr": \[<br>{<br>"hash": "2WN388zpPEy5zZR1uDGRqYbWotHFWo2Y6atAwfLGwUvDEi8LGk93X9S5pimNMv4uQgpJNf6SFQbZF83XbvgTuikj",<br>"err": null<br>},<br>{<br>"hash": "2WN388zpPEy5zZR1uDGRqYbWotHFWo2Y6atAwfLGwUvDEi8LGk93X9S5pimNMv4uQgpJNf6SFQbZF83XbvgTuikj",<br>"err": null<br>}<br>]<br>}</p> |

## 3. Transaction Status Query Endpoint:

```javascript
https://gmgn.ai/defi/router/v1/sol/tx/get_transaction_status?hash=${hash}&last_valid_height=${lastValidBlockHeight}
```

**Request Method: GET**

Request Parameters:

| Parameter           | Type   | Description                                                                                                                                |
| ------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------ |
| hash                | string | Transaction hash returned after submission, e.g., 3Qr9Kb8XfQiTa2E4butFRdVgWb9jTorcQaCPx3zx9fETyZhnffVdjagGU7PkwJVX8X9Js4xvUjybCaNjvFGozoLR |
| last\_valid\_height | int    | Block height at the time of transaction creation, e.g., 221852977                                                                          |

Return Fields:

<table><thead><tr><th>Parameter</th><th width="232">Type</th><th>Description</th></tr></thead><tbody><tr><td>code</td><td>int</td><td>0</td></tr><tr><td>msg</td><td>string</td><td>success</td></tr><tr><td>data</td><td>Object</td><td>{ success: true, expired: false }</td></tr></tbody></table>

**Explanation of `data` Fields:**

* **`success`**: Whether the transaction was successfully added to the blockchain, true if successful.
* **`failed`**: Whether the transaction was added to the blockchain but failed, true if it failed.
* **`expired`**: Whether the transaction has expired. If **`expired=true`** and **`success=false`**, the transaction has expired and needs to be resubmitted. Generally, a transaction expires after 60 seconds.
* If **`success=true`**, the transaction has been successfully added to the blockchain.

**Example code:**

```
import { Wallet } from '@project-serum/anchor'
import { Connection, Keypair, VersionedTransaction,LAMPORTS_PER_SOL } from '@solana/web3.js'
import bs58 from 'bs58';
import fetch from 'node-fetch'
import sleep from './util/sleep.js'
const inputToken = 'So11111111111111111111111111111111111111112'
const outputToken = '7EYnhQoR9YM3N7UoaKRoA44Uy8JeaZV3qyouov87awMs'
const amount = '50000000'
const fromAddress = '2kpJ5QRh16aRQ4oLZ5LnucHFDAZtEFz6omqWWMzDSNrx'
const slippage = 0.5
// GMGN API domain
const API_HOST = 'https://gmgn.ai'
async function main() {
  // Wallet initialization, skip this step if using Phantom
  const wallet = new Wallet(Keypair.fromSecretKey(bs58.decode(process.env.PRIVATE_KEY || '')))
  console.log(`wallet address: ${wallet.publicKey.toString()}`)
  // Get quote and unsigned transaction
  const quoteUrl = `${AdPI_HOST}/defi/router/v1/sol/tx/get_swap_route?token_in_address=${inputToken}&token_out_address=${outputToken}&in_amount=${amount}&from_address=${fromAddress}&slippage=${slippage}`
  let route = await fetch(quoteUrl)
  route = await route.json()
  console.log(route)
  // Sign transaction
  const swapTransactionBuf = Buffer.from(route.data.raw_tx.swapTransaction, 'base64')
  const transaction = VersionedTransaction.deserialize(swapTransactionBuf)
  transaction.sign([wallet.payer])
  const signedTx = Buffer.from(transaction.serialize()).toString('base64')
  console.log(signedTx)
  // Submit transaction
  let res = await fetch(`${API_HOST}/txproxy/v1/send_transaction`,
    {
      method: 'POST',
      headers: {'content-type': 'application/json'},
      body: JSON.stringify(
        {
          "chain": "sol",
          "signedTx": signedTx
        }
      )
    })
  res = await res.json()
  console.log(res)
  // Check transaction status
  // If the transaction is successful, success returns true
  // If is does not go through，expired=true will be returned after 60 seconds
  while (true) {
    const hash =  res.data.hash
    const lastValidBlockHeight = route.data.raw_tx.lastValidBlockHeight
    const statusUrl = `${API_HOST}/defi/router/v1/sol/tx/get_transaction_status?hash=${hash}&last_valid_height=${lastValidBlockHeight}`
    let status = await fetch(statusUrl)
    status = await status.json()
    console.log(status)
    if (status && (status.data.success === true || status.data.expired === true))
      break
    await sleep(1000)
  }
}
main()

```
