@shogun-sdk/money-legos
Version:
Shogun Money Legos: clients and types for quotes, memes, prices, balances, fees, validations, etc.
227 lines (196 loc) • 8.07 kB
text/typescript
import { FOUR_MEME_TOKEN_MANAGER_HELPER_3_ABI } from '../config/abis/fourMeme/tokenManagerHelper3.abi.js';
import { FOUR_MEME_TOKEN_MANAGER_LITE_ABI } from '../config/abis/fourMeme/tokenManagerLite.abi.js';
import { BSC_CHAIN_ID } from '../config/index.js';
// import { BSC_CHAIN_ID } from '../config/chains.js';
import {
FOUR_MEME_BSC_TOKEN_MANAGER_HELPER_3_ADDRESS,
FOUR_MEME_TOKEN_MANAGER_2_LITE_ADDRESS,
} from '../constants/index.js';
import { ethers } from 'ethers';
import { getEVMEthersProviderWithFallback } from '../utils/index.js';
// import { getEVMEthersProviderWithFallback } from '../utils/index.js';
export type FourMemeTokenInfo = {
version: bigint; // The TokenManager version. If version returns 1, you should call V1 TokenManager methods for trading. If version returns 2, call V2
tokenManager: string; // The address of the token manager which manages your token. We recommend using this address to call the TokenManager-related interfaces and parameters, replacing the hardcoded TokenManager addresses
quote: string; // The address of the quote token of your token. If quote returns address 0, it means the token is traded by BNB. otherwise traded by BEP20
lastPrice: bigint; // The last price of your token
tradingFeeRate: bigint; // The trading fee rate of your token. The actual usage of the fee rate should be the return value divided by 10,000
minTradingFee: bigint; // The amount of minimum trading fee
launchTime: bigint; // Launch time of the token
offers: bigint; // Amount of tokens that are not sold
maxOffers: bigint; // Maximum amount of tokens that could be sold before creating Pancake pair
funds: bigint; // Amount of paid BNB or BEP20 received
maxFunds: bigint; // Maximum amount of paid BNB or BEP20 that could be received
liquidityAdded: boolean; // True if the Pancake pair has been created
};
export type FourMemeTryBuyResponse = {
tokenManager: string; // The address of the TokenManager associated with the token
quote: string; // The address of the quote currency for the token, where `address(0)` represents ETH or BNB
estimatedAmount: bigint; // The estimated amount of tokens that can be bought
estimatedCost: bigint; // The estimated cost in the quote currency
estimatedFee: bigint; // The estimated fee for the transaction
amountMsgValue: bigint; // The value to be set in `msg.value` when calling `TokenManager.buyToken()` or `TokenManager.buyTokenAMAP()
amountApproval: bigint; // The amount of tokens that need to be pre-approved for `TokenManager.buyToken()` or `TokenManager.buyTokenAMAP()`
amountFunds: bigint; // The value used for the`funds` parameter when calling`TokenManager.buyTokenAMAP()`
};
export type FourMemeTryBuyParams = {
tokenAddress: string;
tokenAmount?: bigint;
nativeAmount?: bigint;
};
export type FourMemeTrySellParams = {
tokenAddress: string;
amount: bigint;
};
export type FourMemeTrySellResponse = {
tokenManager: string; // The address of the token manager which manages your token
quote: string; // The address of the quote token of your token
funds: bigint; // The amount of quote token users will receive for selling a token
fee: bigint; // The amount of quote token users will pay for trading fee
};
export class FourMeme {
public tokenManagerV2Contract!: ethers.Contract;
public tokenManagerHelperV3!: TokenManagerHelperV3;
private _initialized: boolean = false;
private _initializing: Promise<void> | null = null;
// Static factory method to create an instance
public static async create(): Promise<FourMeme> {
const instance = new FourMeme();
await instance.connect();
return instance;
}
public async connect(): Promise<void> {
if (!this._initialized) {
if (!this._initializing) {
this._initializing = this.initialize();
}
await this._initializing;
}
}
private async initialize(): Promise<void> {
if (this._initialized) return;
try {
const provider = await getEVMEthersProviderWithFallback(BSC_CHAIN_ID);
this.tokenManagerHelperV3 = new TokenManagerHelperV3(provider);
this.tokenManagerV2Contract = new ethers.Contract(
FOUR_MEME_TOKEN_MANAGER_2_LITE_ADDRESS,
FOUR_MEME_TOKEN_MANAGER_LITE_ABI,
provider,
);
this._initialized = true;
this._initializing = null;
} catch (error) {
this._initializing = null;
throw error;
}
}
}
export class TokenManagerHelperV3 {
private bscTokenManagerHelper3Contract: ethers.Contract;
constructor(private provider: ethers.JsonRpcProvider) {
this.bscTokenManagerHelper3Contract = new ethers.Contract(
FOUR_MEME_BSC_TOKEN_MANAGER_HELPER_3_ADDRESS,
FOUR_MEME_TOKEN_MANAGER_HELPER_3_ABI,
this.provider,
);
}
/**
* Get information about the token.
*
* @param tokenAddress The address of your token
*/
async getTokenInfo(tokenAddress: string): Promise<FourMemeTokenInfo | null> {
try {
const tokenInfo = await this.bscTokenManagerHelper3Contract.getTokenInfo!(tokenAddress);
if (!tokenInfo.length) {
return null;
}
const response: FourMemeTokenInfo = {
version: tokenInfo[0],
tokenManager: tokenInfo[1],
quote: tokenInfo[2],
lastPrice: tokenInfo[3],
tradingFeeRate: tokenInfo[4],
minTradingFee: tokenInfo[5],
launchTime: tokenInfo[6],
offers: tokenInfo[7],
maxOffers: tokenInfo[8],
funds: tokenInfo[9],
maxFunds: tokenInfo[10],
liquidityAdded: tokenInfo[11],
};
return response;
} catch (error) {
return null;
}
}
/**
* Simulate a buy and get estimated results.
*
* @param tokenAddress The address of the token to purchase
* @param tokenAmount The amount of the token the user wants to purchase
* @param nativeAmount The amount of money the user wants to spend (in the quote currency)
*
* @example
* - If the user wants to buy 10_000 tokens:
* - Call with param 'tokenAmount' set to 10000*1e18
*
* - If the user wants to spend 10 BNB to purchase tokens:
* - Call with param 'nativeAmount' set to 10*1e18
*/
async tryBuy(params: FourMemeTryBuyParams): Promise<FourMemeTryBuyResponse | null> {
try {
const { tokenAddress, tokenAmount, nativeAmount } = params;
let result;
// only one of the two parameters should be provided
if ((tokenAmount && nativeAmount) || (!tokenAmount && !nativeAmount)) {
return null;
}
if (tokenAmount) {
result = await this.bscTokenManagerHelper3Contract.tryBuy!(tokenAddress, tokenAmount, BigInt(0));
} else {
result = await this.bscTokenManagerHelper3Contract.tryBuy!(tokenAddress, BigInt(0), nativeAmount);
}
if (!result.length) {
return null;
}
const response: FourMemeTryBuyResponse = {
tokenManager: result[0],
quote: result[1],
estimatedAmount: result[2],
estimatedCost: result[3],
estimatedFee: result[4],
amountMsgValue: result[5],
amountApproval: result[6],
amountFunds: result[7],
};
return response;
} catch (error) {
return null;
}
}
/**
* Just pre-calculate the result if the user sells a specified amount of tokens if needed.
*
* @param tokenAddress The address of the token to purchase
* @param amount The amount of token that the user wants to sell
*/
async trySell(params: FourMemeTrySellParams): Promise<FourMemeTrySellResponse | null> {
try {
const { tokenAddress, amount } = params;
const result = await this.bscTokenManagerHelper3Contract.trySell!(tokenAddress, amount);
if (!result.length) {
return null;
}
const response: FourMemeTrySellResponse = {
tokenManager: result[0],
quote: result[1],
funds: result[2],
fee: result[3],
};
return response;
} catch (error) {
return null;
}
}
}