goodrdotfun-sdk
Version:
SDK for interacting with goodr.fun and Sonic on Solana
411 lines (319 loc) • 13 kB
Markdown
# Goodr SDK
JavaScript/TypeScript SDK for interacting with goodr.fun and Sonic on Solana.
## Installation
```bash
npm install goodrdotfun-sdk
```
## Usage
Currently we are supporting Solana and [SonicSVM](https://www.sonic.game/) only
Here's a complete example showing how to create a token, buy, and sell using the SDK:
```typescript
import { Keypair, LAMPORTS_PER_SOL, PublicKey } from '@solana/web3.js';
import {
GoodrFunSDK,
TokenMetadata,
MemeDonationDestinationName,
getMemeDonationDestinationFromName,
ChainType,
} from 'goodrdotfun-sdk';
import { BigNumber } from 'bignumber.js';
const main = async () => {
// Initialize SDK with RPC endpoint
const rpcEndpoint = 'https://api.testnet.sonic.game'; // Use appropriate endpoint (Solana or Sonic SVM)
const sdk = new GoodrFunSDK(ChainType.SONIC, rpcEndpoint);
// Set up your wallet (using environment variables for security)
const walletPublicKey = process.env.WALLET_PUBLIC_KEY;
const walletPrivateKey = process.env.WALLET_PRIVATE_KEY;
if (!walletPublicKey || !walletPrivateKey) {
throw new Error('Wallet public key and private key are required');
}
const wallet = new Keypair({
publicKey: new PublicKey(walletPublicKey).toBytes(),
secretKey: bs58.decode(walletPrivateKey),
});
const mint = Keypair.generate();
const donation = getMemeDonationDestinationFromName(
MemeDonationDestinationName.FarmMeme,
);
const tokenMetadata = new TokenMetadata({
name: 'DONUTS',
ticker: 'DONUTS',
description: 'DONUTS',
donationAmount: donation.donationAmount.toString(),
donationDestinationId: donation.id,
imageUrl: 'https://picsum.photos/200/300',
websiteUrl: 'https://donuts.com',
twitterUrl: 'https://twitter.com/donuts',
telegramUrl: 'https://t.me/donuts',
}).toJSON();
// Update this json to ipfs or any storage then get the url. In this test i will use a fixed url
const metadataUri =
'https://goodr-fun.s3.us-east-1.amazonaws.com/metadata/1745847137445-DONUTS';
const result = await sdk.createAndBuy(wallet, {
mint: mint,
buySolAmount: new BigNumber(0.1).multipliedBy(LAMPORTS_PER_SOL),
slippageBasisPoints: 500,
meme: donation.name,
metadata: {
name: 'DONUTS',
symbol: 'DONUTS',
metadataUri: metadataUri,
},
});
console.log('Token created and bought:', {
signature: result.signature,
tokenAddress: mint.publicKey.toBase58(),
});
// Get token state
const tokenState = await sdk.getCurrentState(mint.publicKey);
console.log('Token state:', {
bondingCurveProgress: `${tokenState.bondingCurveProgress}%`,
price: `${tokenState.priceData.price} SOL`,
totalSupply: `${tokenState.totalSupply} Tokens`,
marketCap: `${tokenState.priceData.marketCap} SOL`,
});
// Buy more tokens
const buyResult = await sdk.buy(wallet, {
mint: mint.publicKey,
solAmount: new BigNumber(0.01).multipliedBy(LAMPORTS_PER_SOL),
slippageBasisPoints: 500,
});
console.log('Additional tokens bought:', {
signature: buyResult.signature,
tokenAddress: mint.publicKey.toBase58(),
});
// Sell tokens
const sellResult = await sdk.sell(wallet, {
mint: mint.publicKey,
tokenAmount: new BigNumber(100000000).multipliedBy(10 ** 6),
slippageBasisPoints: 500,
});
console.log('Tokens sold:', {
signature: sellResult.signature,
tokenAddress: mint.publicKey.toBase58(),
});
};
main().catch(console.error);
```
## SONIC Integration
The SDK supports SONIC token operations with SPL-22 tokens as base currency:
```typescript
import { Keypair, PublicKey } from '@solana/web3.js';
import {
GoodrFunSDK,
TokenMetadata,
MemeDonationDestinationName,
getMemeDonationDestinationFromName,
ChainType,
} from 'goodrdotfun-sdk';
import { BigNumber } from 'bignumber.js';
const main = async () => {
// Initialize SDK for SONIC
const rpcEndpoint = 'https://api.testnet.sonic.game';
const sdk = new GoodrFunSDK(ChainType.SONIC, rpcEndpoint);
const wallet = Keypair.generate(); // Your wallet keypair
const mint = Keypair.generate();
// SONIC token mint address (SPL-22)
const sonicMint = new PublicKey('SONIC_TOKEN_MINT_ADDRESS');
const donation = getMemeDonationDestinationFromName(
MemeDonationDestinationName.FarmMeme,
);
// Create token with SONIC as base currency
const result = await sdk.createAndBuyWithSonic(wallet, {
mint: mint,
baseCurrencyMint: sonicMint,
buySonicAmount: new BigNumber(1.0).multipliedBy(10 ** 9), // 1 SONIC (9 decimals)
slippageBasisPoints: 500,
meme: donation.name,
metadata: {
name: 'SONIC MEME',
symbol: 'SMEME',
metadataUri: 'https://your-metadata-uri.com/metadata.json',
},
});
console.log('SONIC token created:', {
signature: result.signature,
tokenAddress: mint.publicKey.toBase58(),
});
// Buy more tokens with SONIC
const buyResult = await sdk.buyWithSonic(wallet, {
mint: mint.publicKey,
baseCurrencyMint: sonicMint,
sonicAmount: new BigNumber(0.5).multipliedBy(10 ** 9), // 0.5 SONIC
slippageBasisPoints: 500,
});
console.log('Additional tokens bought with SONIC:', {
signature: buyResult.signature,
});
// Sell tokens for SONIC
const sellResult = await sdk.sellWithSonic(wallet, {
mint: mint.publicKey,
baseCurrencyMint: sonicMint,
tokenAmount: new BigNumber(100).multipliedBy(10 ** 6), // 100 tokens
slippageBasisPoints: 500,
});
console.log('Tokens sold for SONIC:', {
signature: sellResult.signature,
});
// Calculate token amounts with SONIC
const buyCalculation = await sdk.calculateBuyTokenAmountWithSonic({
mint: mint.publicKey,
baseCurrencyMint: sonicMint,
amountSonic: new BigNumber(1.0), // 1 SONIC
});
console.log('Tokens you can buy with 1 SONIC:', buyCalculation.amountToken.toString());
const sellCalculation = await sdk.calculateSellTokenAmountWithSonic({
mint: mint.publicKey,
baseCurrencyMint: sonicMint,
amountToken: new BigNumber(100), // 100 tokens
});
console.log('SONIC you can get for 100 tokens:', sellCalculation.amountSonic.toString());
};
main().catch(console.error);
```
## Features
- Create and buy tokens in a single transaction (SOL and SONIC)
- Buy and sell tokens with slippage protection (SOL and SONIC)
- Support for SPL and SPL-22 (Token-2022) tokens
- Get token balances and price data
- Monitor token state and bonding curve progress
- Built-in bonding curve calculations
- Dynamic token program detection
## API Reference
### GoodrFunSDK
The main SDK class for interacting with the GoodrFun program.
#### Constructor
```typescript
constructor(rpcEndpoint: string)
```
- `rpcEndpoint`: Solana RPC endpoint URL
#### Methods
- `createAndBuy(creator: Keypair, params: CreateAndBuyParams): Promise<TransactionResult>`
- Creates a new token and buys initial tokens in a single transaction
- Parameters:
- `mint`: Token mint keypair
- `buySolAmount`: Initial buy amount in SOL
- `slippageBasisPoints`: Slippage tolerance
- `metadata`: Token metadata (name, symbol, URI)
- `buy(creator: Keypair, params: BuyParams): Promise<TransactionResult>`
- Buys tokens with specified SOL amount and slippage protection
- Parameters:
- `mint`: Token mint public key
- `solAmount`: Amount of SOL to spend
- `slippageBasisPoints`: Slippage tolerance
- `sell(creator: Keypair, params: SellParams): Promise<TransactionResult>`
- Sells specified amount of tokens with slippage protection
- Parameters:
- `mint`: Token mint public key
- `tokenAmount`: Amount of tokens to sell
- `slippageBasisPoints`: Slippage tolerance
- `getCurrentState(mint: PublicKey): Promise<TokenState>`
- Gets current token state including:
- Bonding curve progress
- Price data
- Total supply
- Market cap
- `getTokenAccountBalance(mint: PublicKey, authority: PublicKey): Promise<BigNumber>`
- Gets token balance for a specific account
- Parameters:
- `mint`: Token mint public key
- `authority`: Account owner public key
- `getPriceAndMarketcapData(mint: PublicKey): Promise<PriceData>`
- Gets current price and market cap information
- Returns price data including current price and market cap
- `calculateBuyTokenAmount(params: { mint: PublicKey, amountSol: BigNumber }): Promise<{ amountToken: BigNumber }>`
- Calculates the amount of tokens that can be bought with a given SOL amount
- Useful for price impact estimation before trading
#### SONIC-specific Methods
- `createAndBuyWithSonic(creator: Keypair, params: CreateAndBuyWithSonicParams): Promise<TransactionResult>`
- Creates a new token using SONIC as base currency and buys initial tokens
- Parameters:
- `mint`: Token mint keypair
- `baseCurrencyMint`: SONIC token mint (SPL-22)
- `buySonicAmount`: Initial buy amount in SONIC
- `slippageBasisPoints`: Slippage tolerance
- `metadata`: Token metadata (name, symbol, URI)
- `buyWithSonic(creator: Keypair, params: BuyWithSonicParams): Promise<TransactionResult>`
- Buys tokens with specified SONIC amount and slippage protection
- Parameters:
- `mint`: Token mint public key
- `baseCurrencyMint`: SONIC token mint (SPL-22)
- `sonicAmount`: Amount of SONIC to spend
- `slippageBasisPoints`: Slippage tolerance
- `sellWithSonic(creator: Keypair, params: SellWithSonicParams): Promise<TransactionResult>`
- Sells specified amount of tokens for SONIC with slippage protection
- Parameters:
- `mint`: Token mint public key
- `baseCurrencyMint`: SONIC token mint (SPL-22)
- `tokenAmount`: Amount of tokens to sell
- `slippageBasisPoints`: Slippage tolerance
- `calculateBuyTokenAmountWithSonic(params: { mint: PublicKey, baseCurrencyMint: PublicKey, amountSonic: BigNumber }): Promise<{ amountToken: BigNumber }>`
- Calculates the amount of tokens that can be bought with a given SONIC amount
- Useful for price impact estimation before trading with SONIC
- `calculateSellTokenAmountWithSonic(params: { mint: PublicKey, baseCurrencyMint: PublicKey, amountToken: BigNumber }): Promise<{ amountSonic: BigNumber }>`
- Calculates the amount of SONIC that can be received for a given token amount
- Useful for price impact estimation before selling for SONIC
#### Event Listeners
- `addOnCreateEvent(callback: (event: CreateEvent, slot: number, signature: string) => void): number`
- Listen for token creation events
- Returns an event listener ID
- `addOnTradeEvent(callback: (event: TradeEvent, slot: number, signature: string) => void): number`
- Listen for trade events (buys and sells)
- Returns an event listener ID
- `addOnCompleteEvent(callback: (event: CompleteEvent, slot: number, signature: string) => void): number`
- Listen for completion events
- Returns an event listener ID
- `addOnSetParamsEvent(callback: (event: SetParamsEvent, slot: number, signature: string) => void): number`
- Listen for parameter update events
- Returns an event listener ID
- `removeEventListener(...eventIds: number[]): void`
- Remove one or more event listeners by their IDs
#### Event Usage Example
```typescript
// Listen for trade events
const tradeListenerId = sdk.addOnTradeEvent((event, slot, signature) => {
console.log('Trade executed:', {
event,
slot,
signature,
});
});
// Listen for token creation
const createListenerId = sdk.addOnCreateEvent((event, slot, signature) => {
console.log('Token created:', {
event,
slot,
signature,
});
});
// Remove listeners when no longer needed
sdk.removeEventListener(tradeListenerId, createListenerId);
```
## Error Handling Example
When using the SDK, you can catch and handle program errors (such as slippage or authorization errors) using a try/catch block. The SDK will throw a `ProgramError` (extending JavaScript's `Error`) for any known on-chain error, with a `code` and `message` property.
```typescript
import { GoodrFunSDK } from 'goodrdotfun-sdk'; // adjust import as needed
import { ProgramError } from 'goodrdotfun-sdk/src/base/types/common'; // adjust path as needed
async function buyTokens(sdk, buyParams) {
try {
const result = await sdk.buy(wallet, buyParams);
console.log('Buy successful:', result);
} catch (e) {
if (e instanceof ProgramError) {
// This is a program error from the Solana program
console.error('Program error code:', e.code); // e.g., 'TooMuchSolRequired'
console.error('Program error message:', e.message); // e.g., 'slippage: Too much SOL required to buy the given amount of tokens.'
// Handle specific error codes if needed
if (e.code === 'TooMuchSolRequired') {
// Handle slippage error
}
} else {
// This is some other error (network, JS, etc.)
console.error('Other error:', e);
}
}
}
```
You can use this pattern for any SDK method that may throw a program error (e.g., `buy`, `sell`, `buyExactToken`, etc.).
## License
MIT