# Bot SDK - EVM

{% hint style="info" %}
Join our [developer TG channel](https://t.me/+dYgiHDL-Z29jZGRk) for important updates.
{% endhint %}

The trading instructions for buy and sell (but not mint) are directly available on-chain via the Moonshot Smart Contract.

### **Overview** <a href="#overview" id="overview"></a>

The Moonshot SDK for EVM provides the following functions for Base and Abstract chains:

* Minting of a token&#x20;
  * Prepare and submit transactions
  * Upload all assets
  * Buy an initial amount of the tokens you minted
* Get price of the token / position on bonding curve
* Calculate collateral/token in and out
* Generate buy and sell transactions (both exact in and out)
* Set the slippage amount

### Installation <a href="#installation" id="installation"></a>

Install the [package](https://www.npmjs.com/package/@wen-moon-ser/moonshot-sdk-evm) using npm or yarn

Copy

```
npm i @wen-moon-ser/moonshot-sdk-evm
# or
yarn add @wen-moon-ser/moonshot-sdk-evm
```

Example in Wen Moon repo : <https://github.com/wen-moon-ser/moonshot-sdk-evm/blob/main/README.md>&#x20;

### Initializing Moonshot <a href="#initializing-moonshot" id="initializing-moonshot"></a>

To initialize the Moonshot SDK, you need to create an instance of the Moonshot class. Before instantiating the Moonshot class, define your rpcUrl and signer.

#### Public endpoints for rpcUrl on Base <a href="#public-endpoints-for-rpcurl" id="public-endpoints-for-rpcurl"></a>

* Mainnet : <https://base.gateway.tenderly.co/>
* Testnet : <https://base-sepolia.gateway.tenderly.co/>

#### Public endpoints for rpcUrl on Abstract <a href="#public-endpoints-for-rpcurl" id="public-endpoints-for-rpcurl"></a>

* Mainnet : <https://api.mainnet.abs.xyz/>
* Testnet : <https://api.testnet.abs.xyz/>

#### Parameters of the Moonshot class <a href="#parameters-of-the-moonshot-class" id="parameters-of-the-moonshot-class"></a>

* environment : You can initialize the environment for either mainnet or devnet
  * For Mainnet, use Environment.MAINNET
  * For Devnet, use Environemnt.TESTNET
* signer : generated through your private key and rpcUrl
* network : For selecting which chain you want to connect on
  * For Base, leave this parameter as empty (as in the example below)
  * For Abstract, use Network.ASBTRACT

```typescript
import { Wallet } from 'ethers';
import { JsonRpcProvider } from 'ethers';
import { Moonshot, Token, FixedSide, Environment } from '@wen-moon-ser/moonshot-sdk-evm';

export const buyTx = async (): Promise<void> => {
  console.log('--- Buying token example ---');

  const rpcUrl = 'https://base-sepolia.gateway.tenderly.co';

  const provider = new JsonRpcProvider(rpcUrl);
  const signer = new Wallet('private key', provider);

  const moonshot = new Moonshot({
      signer: signer,
      env: Environment.TESTNET,
      // Currently supporting Base and Abstract (network :Network.ABSTRACT). Leave it empty for Base
  });
```

### Buy Example <a href="#buy-example" id="buy-example"></a>

```typescript
import {ethers, JsonRpcProvider, Wallet} from "ethers";
import {Environment, FixedSide, Moonshot, Token} from "@wen-moon-ser/moonshot-sdk-evm";

const buyExactIn = async (tokenAddress: string) => {
  const provider = new JsonRpcProvider(process.env.RPC_URL as string);
  const signer = new Wallet('private_key', provider);

  const moonshot = new Moonshot({
    signer,
    env: Environment.TESTNET,
  });

  const token = await Token.create({
    moonshot,
    provider,
    tokenAddress,
  });

  const collateralAmount = ethers.parseEther('0.001');

  const tokenAmountForTransaction = await token.getTokenAmountByCollateral({
    collateralAmount,
    tradeDirection: 'BUY',
  });

  const slippageBps = 1000;

  const buyTx = await token.prepareTx({
    slippageBps,
    tokenAmount: tokenAmountForTransaction,
    collateralAmount: collateralAmount,
    tradeDirection: 'BUY',
    fixedSide: FixedSide.IN,
  });

  const walletAddress = await signer.getAddress();

  const feeData = await provider.getFeeData();

  const nonce = await provider.getTransactionCount(walletAddress, 'latest');

  const enrichedBuyTx = {
    ...buyTx,
    gasPrice: feeData.gasPrice,
    nonce: nonce,
    from: walletAddress,
  };

  const buyTxGasLimit = await provider.estimateGas(enrichedBuyTx);

  const buyTxResponse = await signer.sendTransaction({
    ...buyTx,
    gasLimit: buyTxGasLimit,
  });

  const buyTxReceipt = await buyTxResponse.wait();

  if(buyTxReceipt?.status === 1) {
    const balance = await token.balanceOf(walletAddress);

    console.log(balance);
  }
};
```

### Sell Example <a href="#sell-example" id="sell-example"></a>

```typescript
import {JsonRpcProvider, Wallet} from "ethers";
import {Environment, FixedSide, Moonshot, Token} from "@wen-moon-ser/moonshot-sdk-evm";

const sellExactIn = async (tokenAddress: string) => {
  const provider = new JsonRpcProvider(process.env.RPC_URL as string);
  const signer = new Wallet('private_key', provider);

  const walletAddress = await signer.getAddress();

  const moonshot = new Moonshot({
    signer,
    env: Environment.TESTNET,
  });
  const token = await Token.create({
    moonshot,
    provider,
    tokenAddress,
  });

  const tokenAmount = await token.balanceOf(walletAddress);

  await token.approveForMoonshotSell(tokenAmount);

  const collateralAmountForTransaction =
    await token.getCollateralAmountByTokens({
      tokenAmount,
      tradeDirection: 'BUY',
    });

  const slippageBps = 1000;

  const sellTx = await token.prepareTx({
    slippageBps,
    tokenAmount,
    collateralAmount: collateralAmountForTransaction,
    tradeDirection: 'SELL',
    fixedSide: FixedSide.IN,
  });

  const feeData = await provider.getFeeData();

  const nonce = await provider.getTransactionCount(walletAddress, 'latest');

  const enrichedSellTx = {
    ...sellTx,
    gasPrice: feeData.gasPrice,
    nonce: nonce,
    from: walletAddress,
  };

  const sellTxGasLimit = await provider.estimateGas(enrichedSellTx);

  const sellTxResponse = await signer.sendTransaction({
    ...enrichedSellTx,
    gasLimit: sellTxGasLimit,
  });

  const sellTxReceipt = await sellTxResponse.wait();

  if(sellTxReceipt?.status === 1) {
    const balance = await token.balanceOf(walletAddress);

    console.log(balance);
  }
};
```

### Mint Example

* Image size restrictions - 2 MB for the icon and 5 MB for the banner
* Recommended aspect ratio - 1 : 1 for the icon and 3:1 for the banner
* tokenAmount - Lets you buy an initial amount of tokens that you just minted

```typescript
import {Environment, MigrationDex, MintTokenCurveType, Moonshot} from "@wen-moon-ser/moonshot-sdk-evm";
import {JsonRpcProvider, Transaction, Wallet} from "ethers";

const mintTx = async () => {
  const provider = new JsonRpcProvider(process.env.RPC_URL as string);
  const signer = new Wallet('private_key', provider);

  const moonshot = new Moonshot({
    signer,
    env: Environment.TESTNET,
  });

  const mockImg = '...';

  const prepMint = await moonshot.prepareMintTx({
    name: 'TEST_TOKEN',
    symbol: 'TEST_TOKEN',
    curveType: MintTokenCurveType.CONSTANT_PRODUCT_V1,
    migrationDex: MigrationDex.UNISWAP, // USE MigrationDex.ABSTRACTSWAP for abstract
    icon: mockImg,
    description: 'TEST_TOKEN',
    links: [{ url: 'https://x.com', label: 'x handle' }],
    banner: mockImg,
    creator: await signer.getAddress(),
    tokenAmount: '10000000000000',
  });

  const deserializedTransaction = Transaction.from(
    prepMint.transaction,
  ).toJSON();

  const walletAddress = await signer.getAddress();

  const feeData = await provider.getFeeData();

  const tx = {
    ...deserializedTransaction,
    gasPrice: feeData.gasPrice,
    from: walletAddress,
    nonce: await provider.getTransactionCount(walletAddress, 'latest'),
  };

  const gasLimit = await provider.estimateGas(tx);

  const txResponse = await signer.sendTransaction({
    ...tx,
    gasLimit,
  });

  const receipt = await txResponse.wait();

  if (receipt?.status === 1) {
    const res = await moonshot.submitMintTx({
      token: prepMint.token,
      signedTransaction: JSON.stringify(txResponse),
      tokenId: prepMint.draftTokenId,
    });

    const createdTokenAddress = receipt?.logs[0].address;

    console.log(createdTokenAddress);
  }
}
```


---

# 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.moonshot.cc/developers/bot-sdk-evm.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.
