Skip to content

Commit

Permalink
Refactored buy/sell
Browse files Browse the repository at this point in the history
  • Loading branch information
Nils Abegg committed Jun 18, 2024
1 parent a2199fd commit 027bd3f
Show file tree
Hide file tree
Showing 7 changed files with 339 additions and 285 deletions.
5 changes: 5 additions & 0 deletions .changeset/refactored.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@degenfrends/solana-pumpfun-trader': patch
---

## @degenfrends/solana-pumpfun-trader: Discord fixes
37 changes: 33 additions & 4 deletions README.MD
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Solana Rugchecker
# Solana Pump.fun Trader

![Static Badge](https://img.shields.io/badge/degen-100%25-pink)
![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/degenfrends/solana-pumpfun-trader/publish.yml)
Expand All @@ -10,10 +10,12 @@

## This project is more or less a copy of https://github.com/bilix-software/solana-pump-fun. I made a npm package out of it and resturctured/refactored the code a little bit.

## If you made some money off of this and you want to contribute to the ongoing development, you can send some SOL to this address: xe18XoG9HpgpmZ6C4GLAfnDtD7xGc6dEjen7NfF3V9g

[Join the discord if you are looking for fellow degen developers!](https://discord.gg/HUVAbet2Dp)

> [!CAUTION]
> Do not use your main wallet with this script! Always use a trading wallet with your trading budget.
> Do not use your main wallet with this script! Always use a trading wallet with your trading budget. Don't be lazy! Create a wallet for this now!
Solan Pump.fun Trader is a library to execute buy and sell orders for SPL tokens that were created on pump.fun.

Expand All @@ -25,6 +27,33 @@ Just install it with npm or yarn or whatever.
npm install "@degenfrends/solana-pumpfun-trader"
```

## Configuration
## Configuration & Usage

```typescript
import PumpFunTrader from '@degenfrends/solana-pumpfun-trader';

const pumpFunTrader = new PumpFunTrader();
this.pumpFunTrader.setSolanaRpcUrl('https://yoursolanarpc.com');

await this.pumpFunTrader.buy(
privateKey: '12123423434234', // your private key
tokenAddress: 'ejddjsldjsdlks', // the address of the token you want to buy
amount: 0.5, // amount in solana
priorityFee: 0, // (optional) you should increase the priority fee when you want to make sure that transactions are always succesfull.
slippage: 0.25, // (optional) 0.25 equals 25% slippage.
isSimulation: false // (optional)
);

await this.pumpFunTrader.sell(
privateKey: '12123423434234', // your private key
tokenAddress: 'ejddjsldjsdlks', // the address of the token you want to sell
tokenBalance: 10000000 // the amounts of token you want to sell, you need to multiply the amount you want to sell by 1000000 since pump.fun tokens have 6 digits,
priorityFee: 0, // (optional) you should increase the priority fee when you want to make sure that transactions are always succesfull.
slippage: 0.25, // (optional) 0.25 equals 25% slippage.
isSimulation: false // (optional)
);
```

There are functions to build sell and buy transaction instructions too, which you can use to bundle transactions.

TBD
If you have any questions or suggestions, [join the discord!](https://discord.gg/HUVAbet2Dp)
2 changes: 2 additions & 0 deletions dist/index.d.mts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ declare class PumpFunTrader {
setLogger(logger: any): this;
buy(privateKey: string, tokenAddress: string, amount: number, priorityFee?: number, slippage?: number, isSimulation?: boolean): Promise<void>;
sell(privateKey: string, tokenAddress: string, tokenBalance: number, priorityFee?: number, slippage?: number, isSimulation?: boolean): Promise<void>;
createAndSendTransaction(txBuilder: Transaction, privateKey: string, priorityFee?: number, isSimulation?: boolean): Promise<void>;
getBuyInstruction(privateKey: string, tokenAddress: string, amount: number, slippage: number | undefined, txBuilder: Transaction): Promise<TransactionInstruction | undefined>;
getSellInstruction(privateKey: string, tokenAddress: string, tokenBalance: number, priorityFee?: number, slippage?: number): Promise<TransactionInstruction | undefined>;
}

export { ASSOC_TOKEN_ACC_PROG, FEE_RECIPIENT, GLOBAL, PUMP_FUN_ACCOUNT, PUMP_FUN_PROGRAM, RENT, SYSTEM_PROGRAM_ID, TOKEN_PROGRAM_ID, PumpFunTrader as default };
2 changes: 2 additions & 0 deletions dist/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ declare class PumpFunTrader {
setLogger(logger: any): this;
buy(privateKey: string, tokenAddress: string, amount: number, priorityFee?: number, slippage?: number, isSimulation?: boolean): Promise<void>;
sell(privateKey: string, tokenAddress: string, tokenBalance: number, priorityFee?: number, slippage?: number, isSimulation?: boolean): Promise<void>;
createAndSendTransaction(txBuilder: Transaction, privateKey: string, priorityFee?: number, isSimulation?: boolean): Promise<void>;
getBuyInstruction(privateKey: string, tokenAddress: string, amount: number, slippage: number | undefined, txBuilder: Transaction): Promise<TransactionInstruction | undefined>;
getSellInstruction(privateKey: string, tokenAddress: string, tokenBalance: number, priorityFee?: number, slippage?: number): Promise<TransactionInstruction | undefined>;
}

export { ASSOC_TOKEN_ACC_PROG, FEE_RECIPIENT, GLOBAL, PUMP_FUN_ACCOUNT, PUMP_FUN_PROGRAM, RENT, SYSTEM_PROGRAM_ID, TOKEN_PROGRAM_ID, PumpFunTrader as default };
224 changes: 114 additions & 110 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,129 +166,39 @@ var PumpFunTrader = class {
return;
}
txBuilder.add(instruction);
const walletPrivateKey = await getKeyPairFromPrivateKey(privateKey);
const transaction = await createTransaction(this.connection, txBuilder.instructions, walletPrivateKey.publicKey, priorityFee);
if (isSimulation == false) {
const signature = await sendTransaction(this.connection, transaction, [
walletPrivateKey
]);
this.logger.log("Buy transaction confirmed:", signature);
} else if (isSimulation == true) {
const simulatedResult = await this.connection.simulateTransaction(transaction);
this.logger.log(simulatedResult);
}
await this.createAndSendTransaction(txBuilder, privateKey, priorityFee, isSimulation);
} catch (error) {
this.logger.log(error);
}
}
async sell(privateKey, tokenAddress, tokenBalance, priorityFee = 0, slippage = 0.25, isSimulation = true) {
try {
const coinData = await getCoinData(tokenAddress);
if (!coinData) {
this.logger.error("Failed to retrieve coin data...");
return;
}
const payer = await getKeyPairFromPrivateKey(privateKey);
const owner = payer.publicKey;
const mint = new import_web34.PublicKey(tokenAddress);
const instruction = await this.getSellInstruction(privateKey, tokenAddress, tokenBalance, priorityFee, slippage);
const txBuilder = new import_web34.Transaction();
const tokenAccountAddress = await (0, import_spl_token.getAssociatedTokenAddress)(mint, owner, false);
const tokenAccountInfo = await this.connection.getAccountInfo(tokenAccountAddress);
let tokenAccount;
if (!tokenAccountInfo) {
txBuilder.add((0, import_spl_token.createAssociatedTokenAccountInstruction)(payer.publicKey, tokenAccountAddress, payer.publicKey, mint));
tokenAccount = tokenAccountAddress;
} else {
tokenAccount = tokenAccountAddress;
if (!instruction) {
this.logger.error("Failed to retrieve sell instruction...");
return;
}
const minSolOutput = Math.floor(tokenBalance * (1 - slippage) * coinData["virtual_sol_reserves"] / coinData["virtual_token_reserves"]);
const keys = [
{
pubkey: GLOBAL,
isSigner: false,
isWritable: false
},
{
pubkey: FEE_RECIPIENT,
isSigner: false,
isWritable: true
},
{
pubkey: mint,
isSigner: false,
isWritable: false
},
{
pubkey: new import_web34.PublicKey(coinData["bonding_curve"]),
isSigner: false,
isWritable: true
},
{
pubkey: new import_web34.PublicKey(coinData["associated_bonding_curve"]),
isSigner: false,
isWritable: true
},
{
pubkey: tokenAccount,
isSigner: false,
isWritable: true
},
{
pubkey: owner,
isSigner: false,
isWritable: true
},
{
pubkey: SYSTEM_PROGRAM_ID,
isSigner: false,
isWritable: false
},
{
pubkey: ASSOC_TOKEN_ACC_PROG,
isSigner: false,
isWritable: false
},
{
pubkey: TOKEN_PROGRAM_ID,
isSigner: false,
isWritable: false
},
{
pubkey: PUMP_FUN_ACCOUNT,
isSigner: false,
isWritable: false
},
{
pubkey: PUMP_FUN_PROGRAM,
isSigner: false,
isWritable: false
}
];
const data = Buffer.concat([
bufferFromUInt64("12502976635542562355"),
bufferFromUInt64(tokenBalance),
bufferFromUInt64(minSolOutput)
]);
const instruction = new import_web34.TransactionInstruction({
keys,
programId: PUMP_FUN_PROGRAM,
data
});
txBuilder.add(instruction);
const transaction = await createTransaction(this.connection, txBuilder.instructions, payer.publicKey, priorityFee);
if (isSimulation == false) {
const signature = await sendTransaction(this.connection, transaction, [
payer
]);
this.logger.log("Sell transaction confirmed:", signature);
} else if (isSimulation == true) {
const simulatedResult = await this.connection.simulateTransaction(transaction);
this.logger.log(simulatedResult);
}
const payer = await getKeyPairFromPrivateKey(privateKey);
await this.createAndSendTransaction(txBuilder, privateKey, priorityFee, isSimulation);
} catch (error) {
this.logger.log(error);
}
}
async createAndSendTransaction(txBuilder, privateKey, priorityFee = 0, isSimulation = true) {
const walletPrivateKey = await getKeyPairFromPrivateKey(privateKey);
const transaction = await createTransaction(this.connection, txBuilder.instructions, walletPrivateKey.publicKey, priorityFee);
if (isSimulation == false) {
const signature = await sendTransaction(this.connection, transaction, [
walletPrivateKey
]);
this.logger.log("Buy transaction confirmed:", signature);
} else if (isSimulation == true) {
const simulatedResult = await this.connection.simulateTransaction(transaction);
this.logger.log(simulatedResult);
}
}
async getBuyInstruction(privateKey, tokenAddress, amount, slippage = 0.25, txBuilder) {
const coinData = await getCoinData(tokenAddress);
if (!coinData) {
Expand Down Expand Up @@ -389,6 +299,100 @@ var PumpFunTrader = class {
});
return instruction;
}
async getSellInstruction(privateKey, tokenAddress, tokenBalance, priorityFee = 0, slippage = 0.25) {
const coinData = await getCoinData(tokenAddress);
if (!coinData) {
this.logger.error("Failed to retrieve coin data...");
return;
}
const payer = await getKeyPairFromPrivateKey(privateKey);
const owner = payer.publicKey;
const mint = new import_web34.PublicKey(tokenAddress);
const txBuilder = new import_web34.Transaction();
const tokenAccountAddress = await (0, import_spl_token.getAssociatedTokenAddress)(mint, owner, false);
const tokenAccountInfo = await this.connection.getAccountInfo(tokenAccountAddress);
let tokenAccount;
if (!tokenAccountInfo) {
txBuilder.add((0, import_spl_token.createAssociatedTokenAccountInstruction)(payer.publicKey, tokenAccountAddress, payer.publicKey, mint));
tokenAccount = tokenAccountAddress;
} else {
tokenAccount = tokenAccountAddress;
}
const minSolOutput = Math.floor(tokenBalance * (1 - slippage) * coinData["virtual_sol_reserves"] / coinData["virtual_token_reserves"]);
const keys = [
{
pubkey: GLOBAL,
isSigner: false,
isWritable: false
},
{
pubkey: FEE_RECIPIENT,
isSigner: false,
isWritable: true
},
{
pubkey: mint,
isSigner: false,
isWritable: false
},
{
pubkey: new import_web34.PublicKey(coinData["bonding_curve"]),
isSigner: false,
isWritable: true
},
{
pubkey: new import_web34.PublicKey(coinData["associated_bonding_curve"]),
isSigner: false,
isWritable: true
},
{
pubkey: tokenAccount,
isSigner: false,
isWritable: true
},
{
pubkey: owner,
isSigner: false,
isWritable: true
},
{
pubkey: SYSTEM_PROGRAM_ID,
isSigner: false,
isWritable: false
},
{
pubkey: ASSOC_TOKEN_ACC_PROG,
isSigner: false,
isWritable: false
},
{
pubkey: TOKEN_PROGRAM_ID,
isSigner: false,
isWritable: false
},
{
pubkey: PUMP_FUN_ACCOUNT,
isSigner: false,
isWritable: false
},
{
pubkey: PUMP_FUN_PROGRAM,
isSigner: false,
isWritable: false
}
];
const data = Buffer.concat([
bufferFromUInt64("12502976635542562355"),
bufferFromUInt64(tokenBalance),
bufferFromUInt64(minSolOutput)
]);
const instruction = new import_web34.TransactionInstruction({
keys,
programId: PUMP_FUN_PROGRAM,
data
});
return instruction;
}
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
Expand Down
Loading

0 comments on commit 027bd3f

Please sign in to comment.