# 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);
  }
}
```
