update amm virtual quotes reserves
This commit is contained in:
211
pumpamm.go
211
pumpamm.go
@@ -9,7 +9,7 @@ import (
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
type ammBuyEvent struct {
|
||||
type ammBuyEventPrefix struct {
|
||||
TimeStamp int64
|
||||
BaseAmountOut uint64
|
||||
MaxQuoteAmountIn uint64
|
||||
@@ -45,6 +45,38 @@ type ammBuyEvent struct {
|
||||
Cashback uint64
|
||||
}
|
||||
|
||||
type ammBuyEvent struct {
|
||||
ammBuyEventPrefix
|
||||
BuybackFeeBasisPoints uint64
|
||||
BuybackFee uint64
|
||||
VirtualQuoteReserves agbinary.Int128
|
||||
CanBoost bool
|
||||
BaseSupply uint64
|
||||
}
|
||||
|
||||
type ammTradeEventBuybackSuffix struct {
|
||||
BuybackFeeBasisPoints uint64
|
||||
BuybackFee uint64
|
||||
}
|
||||
|
||||
type ammTradeEventVirtualSuffix struct {
|
||||
VirtualQuoteReserves agbinary.Int128
|
||||
CanBoost bool
|
||||
BaseSupply uint64
|
||||
}
|
||||
|
||||
func decodeAmmBuyEvent(data []byte) (ammBuyEvent, error) {
|
||||
var event ammBuyEvent
|
||||
decoder := agbinary.NewBorshDecoder(data)
|
||||
if err := decoder.Decode(&event.ammBuyEventPrefix); err != nil {
|
||||
return ammBuyEvent{}, err
|
||||
}
|
||||
if err := decodeAmmTradeEventSuffix(decoder, &event.BuybackFeeBasisPoints, &event.BuybackFee, &event.VirtualQuoteReserves, &event.CanBoost, &event.BaseSupply); err != nil {
|
||||
return ammBuyEvent{}, err
|
||||
}
|
||||
return event, nil
|
||||
}
|
||||
|
||||
type ammCreatePoolEvent struct {
|
||||
TimeStamp int64
|
||||
Index uint16
|
||||
@@ -90,7 +122,7 @@ type ammDepositEvent struct {
|
||||
UserPoolTokenAccount solana.PublicKey
|
||||
}
|
||||
|
||||
type ammSellEvent struct {
|
||||
type ammSellEventPrefix struct {
|
||||
Timestamp int64
|
||||
BaseAmountIn uint64
|
||||
MinQuoteAmountOut uint64
|
||||
@@ -119,6 +151,86 @@ type ammSellEvent struct {
|
||||
Cashback uint64
|
||||
}
|
||||
|
||||
type ammSellEvent struct {
|
||||
ammSellEventPrefix
|
||||
BuybackFeeBasisPoints uint64
|
||||
BuybackFee uint64
|
||||
VirtualQuoteReserves agbinary.Int128
|
||||
CanBoost bool
|
||||
BaseSupply uint64
|
||||
}
|
||||
|
||||
func decodeAmmSellEvent(data []byte) (ammSellEvent, error) {
|
||||
var event ammSellEvent
|
||||
decoder := agbinary.NewBorshDecoder(data)
|
||||
if err := decoder.Decode(&event.ammSellEventPrefix); err != nil {
|
||||
return ammSellEvent{}, err
|
||||
}
|
||||
if err := decodeAmmTradeEventSuffix(decoder, &event.BuybackFeeBasisPoints, &event.BuybackFee, &event.VirtualQuoteReserves, &event.CanBoost, &event.BaseSupply); err != nil {
|
||||
return ammSellEvent{}, err
|
||||
}
|
||||
return event, nil
|
||||
}
|
||||
|
||||
func decodeAmmTradeEventSuffix(
|
||||
decoder *agbinary.Decoder,
|
||||
buybackFeeBasisPoints *uint64,
|
||||
buybackFee *uint64,
|
||||
virtualQuoteReserves *agbinary.Int128,
|
||||
canBoost *bool,
|
||||
baseSupply *uint64,
|
||||
) error {
|
||||
remaining := decoder.Remaining()
|
||||
if remaining == 0 {
|
||||
return nil
|
||||
}
|
||||
if remaining < 16 {
|
||||
return fmt.Errorf("pump amm trade event buyback suffix truncated: %d bytes", remaining)
|
||||
}
|
||||
|
||||
var buyback ammTradeEventBuybackSuffix
|
||||
if err := decoder.Decode(&buyback); err != nil {
|
||||
return err
|
||||
}
|
||||
*buybackFeeBasisPoints = buyback.BuybackFeeBasisPoints
|
||||
*buybackFee = buyback.BuybackFee
|
||||
|
||||
remaining = decoder.Remaining()
|
||||
if remaining == 0 {
|
||||
return nil
|
||||
}
|
||||
if remaining < 25 {
|
||||
return fmt.Errorf("pump amm trade event virtual reserve suffix truncated: %d bytes", remaining)
|
||||
}
|
||||
|
||||
var virtual ammTradeEventVirtualSuffix
|
||||
if err := decoder.Decode(&virtual); err != nil {
|
||||
return err
|
||||
}
|
||||
*virtualQuoteReserves = virtual.VirtualQuoteReserves
|
||||
*canBoost = virtual.CanBoost
|
||||
*baseSupply = virtual.BaseSupply
|
||||
return nil
|
||||
}
|
||||
|
||||
func pumpAmmVirtualQuoteReserve(value agbinary.Int128) decimal.Decimal {
|
||||
return decimal.NewFromBigInt(value.BigInt(), 0)
|
||||
}
|
||||
|
||||
func pumpAmmBuyPostQuoteReserves(event ammBuyEvent) (real, effective decimal.Decimal) {
|
||||
// The event reserve is the pre-trade real vault balance. Keep the
|
||||
// parser's existing LP-fee treatment by applying QuoteAmountIn here.
|
||||
real = decimal.NewFromUint64(event.PoolQuoteTokenReserve).Add(decimal.NewFromUint64(event.QuoteAmountIn))
|
||||
return real, real.Add(pumpAmmVirtualQuoteReserve(event.VirtualQuoteReserves))
|
||||
}
|
||||
|
||||
func pumpAmmSellPostQuoteReserves(event ammSellEvent) (real, effective decimal.Decimal) {
|
||||
// The event reserve is the pre-trade real vault balance. Keep the
|
||||
// parser's existing LP-fee treatment by applying QuoteAmountOut here.
|
||||
real = decimal.NewFromUint64(event.PoolQuoteTokenReserves).Sub(decimal.NewFromUint64(event.QuoteAmountOut))
|
||||
return real, real.Add(pumpAmmVirtualQuoteReserve(event.VirtualQuoteReserves))
|
||||
}
|
||||
|
||||
type ammWithdrawEvent struct {
|
||||
Timestamp int64
|
||||
LpTokenAmountIn uint64
|
||||
@@ -249,6 +361,7 @@ func ammCreatePoolParser(tx *Tx, instruction Instruction, innerInstructions Inne
|
||||
QuoteAmount: decimal.NewFromUint64(createEvent.QuoteAmountIn),
|
||||
BaseReserve: decimal.NewFromUint64(createEvent.PoolBaseAmount),
|
||||
QuoteReserve: decimal.NewFromUint64(createEvent.PoolQuoteAmount),
|
||||
RealQuoteReserve: decimal.NewFromUint64(createEvent.PoolQuoteAmount),
|
||||
UserBaseBalance: decimal.Decimal{},
|
||||
UserQuoteBalance: decimal.Decimal{},
|
||||
EntryContract: entryContract,
|
||||
@@ -395,6 +508,7 @@ func failedTxAmmBuyParser(tx *Tx, instruction Instruction, innerInstructions Inn
|
||||
QuoteAmount: decimal.NewFromUint64(quoteAmount),
|
||||
BaseReserve: baseReserve,
|
||||
QuoteReserve: quoteReserve,
|
||||
RealQuoteReserve: quoteReserve,
|
||||
Mayhem: isMayhemPump(result.accountList[instruction.Accounts[9]]),
|
||||
UserBaseBalance: userBase,
|
||||
UserQuoteBalance: userQuote,
|
||||
@@ -518,6 +632,7 @@ func failedTxAmmSellParser(tx *Tx, instruction Instruction, innerInstructions In
|
||||
QuoteAmount: decimal.NewFromUint64(quoteAmount),
|
||||
BaseReserve: baseReserve,
|
||||
QuoteReserve: quoteReserve,
|
||||
RealQuoteReserve: quoteReserve,
|
||||
Mayhem: isMayhemPump(result.accountList[instruction.Accounts[9]]),
|
||||
UserBaseBalance: userBase,
|
||||
UserQuoteBalance: userQuote,
|
||||
@@ -557,7 +672,7 @@ func ammBuyParser(tx *Tx, instruction Instruction, innerInstructions InnerInstru
|
||||
if innerInstr.ProgramIDIndex == instruction.ProgramIDIndex &&
|
||||
bytes.Equal(innerInstr.Data[:8], pumpAmmEventDiscriminator[:]) &&
|
||||
bytes.Equal(innerInstr.Data[8:16], pumpAmmBuyEventDiscriminator[:]) {
|
||||
err = agbinary.NewBorshDecoder(innerInstr.Data[16:]).Decode(&event)
|
||||
event, err = decodeAmmBuyEvent(innerInstr.Data[16:])
|
||||
if offset[1] == 0 {
|
||||
offset[0] += 1
|
||||
} else {
|
||||
@@ -632,27 +747,30 @@ func ammBuyParser(tx *Tx, instruction Instruction, innerInstructions InnerInstru
|
||||
if event.IxName == "buy" {
|
||||
quoteAmount = decimal.NewFromUint64(event.QuoteAmountIn)
|
||||
}
|
||||
realQuoteReserve, effectiveQuoteReserve := pumpAmmBuyPostQuoteReserves(event)
|
||||
swap := Swap{
|
||||
Program: SolProgramPumpAMM,
|
||||
Event: "buy",
|
||||
Pool: event.Pool,
|
||||
BaseMint: baseMint,
|
||||
QuoteMint: quoteMint,
|
||||
BaseTokenProgram: baseTokenProgram,
|
||||
QuoteTokenProgram: quoteTokenProgram,
|
||||
Creator: event.CoinCreator,
|
||||
BaseMintDecimals: baseMintDecimals,
|
||||
QuoteMintDecimals: quoteMintDecimals,
|
||||
User: eventUser,
|
||||
BaseAmount: decimal.NewFromUint64(event.BaseAmountOut),
|
||||
QuoteAmount: quoteAmount,
|
||||
BaseReserve: decimal.NewFromUint64(event.PoolBaseTokenReserve - event.BaseAmountOut),
|
||||
QuoteReserve: decimal.NewFromUint64(event.PoolQuoteTokenReserve + event.QuoteAmountIn),
|
||||
Mayhem: isMayhemPump(result.accountList[instruction.Accounts[9]]),
|
||||
Cashback: isCashbackCoin,
|
||||
UserBaseBalance: userBase,
|
||||
UserQuoteBalance: userQuote,
|
||||
EntryContract: entryContract,
|
||||
Program: SolProgramPumpAMM,
|
||||
Event: "buy",
|
||||
Pool: event.Pool,
|
||||
BaseMint: baseMint,
|
||||
QuoteMint: quoteMint,
|
||||
BaseTokenProgram: baseTokenProgram,
|
||||
QuoteTokenProgram: quoteTokenProgram,
|
||||
Creator: event.CoinCreator,
|
||||
BaseMintDecimals: baseMintDecimals,
|
||||
QuoteMintDecimals: quoteMintDecimals,
|
||||
User: eventUser,
|
||||
BaseAmount: decimal.NewFromUint64(event.BaseAmountOut),
|
||||
QuoteAmount: quoteAmount,
|
||||
BaseReserve: decimal.NewFromUint64(event.PoolBaseTokenReserve - event.BaseAmountOut),
|
||||
QuoteReserve: effectiveQuoteReserve,
|
||||
RealQuoteReserve: realQuoteReserve,
|
||||
VirtualQuoteReserve: pumpAmmVirtualQuoteReserve(event.VirtualQuoteReserves),
|
||||
Mayhem: isMayhemPump(result.accountList[instruction.Accounts[9]]),
|
||||
Cashback: isCashbackCoin,
|
||||
UserBaseBalance: userBase,
|
||||
UserQuoteBalance: userQuote,
|
||||
EntryContract: entryContract,
|
||||
}
|
||||
if bytes.Equal(instruction.Data[:8], pumpAmmBuyV2Discriminator[:]) {
|
||||
swap.SetSwapAmountInfo(
|
||||
@@ -699,7 +817,7 @@ func ammSellParser(tx *Tx, instruction Instruction, innerInstructions InnerInstr
|
||||
if innerInstr.ProgramIDIndex == instruction.ProgramIDIndex &&
|
||||
bytes.Equal(innerInstr.Data[:8], pumpAmmEventDiscriminator[:]) &&
|
||||
bytes.Equal(innerInstr.Data[8:16], pumpAmmSellEventDiscriminator[:]) {
|
||||
err = agbinary.NewBorshDecoder(innerInstr.Data[16:]).Decode(&event)
|
||||
event, err = decodeAmmSellEvent(innerInstr.Data[16:])
|
||||
if offset[1] == 0 {
|
||||
offset[0] += 1
|
||||
} else {
|
||||
@@ -770,27 +888,30 @@ func ammSellParser(tx *Tx, instruction Instruction, innerInstructions InnerInstr
|
||||
userQuote = userQuote.Add(decimal.NewFromUint64(userBalance))
|
||||
}
|
||||
isCashbackCoin := event.CashbackFeeBasisPoints > 0 || event.Cashback > 0
|
||||
realQuoteReserve, effectiveQuoteReserve := pumpAmmSellPostQuoteReserves(event)
|
||||
swap := Swap{
|
||||
Program: SolProgramPumpAMM,
|
||||
Event: "sell",
|
||||
Pool: event.Pool,
|
||||
BaseMint: baseMint,
|
||||
QuoteMint: quoteMint,
|
||||
BaseTokenProgram: baseTokenProgram,
|
||||
QuoteTokenProgram: quoteTokenProgram,
|
||||
Creator: event.CoinCreator,
|
||||
BaseMintDecimals: baseMintDecimals,
|
||||
QuoteMintDecimals: quoteMintDecimals,
|
||||
User: eventUser,
|
||||
BaseAmount: decimal.NewFromUint64(event.BaseAmountIn),
|
||||
QuoteAmount: decimal.NewFromUint64(event.UserQuoteAmountOut),
|
||||
BaseReserve: decimal.NewFromUint64(event.PoolBaseTokenReserves + event.BaseAmountIn),
|
||||
QuoteReserve: decimal.NewFromUint64(event.PoolQuoteTokenReserves - event.QuoteAmountOut),
|
||||
Mayhem: isMayhemPump(result.accountList[instruction.Accounts[9]]),
|
||||
Cashback: isCashbackCoin,
|
||||
UserBaseBalance: userBase,
|
||||
UserQuoteBalance: userQuote,
|
||||
EntryContract: entryContract,
|
||||
Program: SolProgramPumpAMM,
|
||||
Event: "sell",
|
||||
Pool: event.Pool,
|
||||
BaseMint: baseMint,
|
||||
QuoteMint: quoteMint,
|
||||
BaseTokenProgram: baseTokenProgram,
|
||||
QuoteTokenProgram: quoteTokenProgram,
|
||||
Creator: event.CoinCreator,
|
||||
BaseMintDecimals: baseMintDecimals,
|
||||
QuoteMintDecimals: quoteMintDecimals,
|
||||
User: eventUser,
|
||||
BaseAmount: decimal.NewFromUint64(event.BaseAmountIn),
|
||||
QuoteAmount: decimal.NewFromUint64(event.UserQuoteAmountOut),
|
||||
BaseReserve: decimal.NewFromUint64(event.PoolBaseTokenReserves + event.BaseAmountIn),
|
||||
QuoteReserve: effectiveQuoteReserve,
|
||||
RealQuoteReserve: realQuoteReserve,
|
||||
VirtualQuoteReserve: pumpAmmVirtualQuoteReserve(event.VirtualQuoteReserves),
|
||||
Mayhem: isMayhemPump(result.accountList[instruction.Accounts[9]]),
|
||||
Cashback: isCashbackCoin,
|
||||
UserBaseBalance: userBase,
|
||||
UserQuoteBalance: userQuote,
|
||||
EntryContract: entryContract,
|
||||
}
|
||||
swap.SetSwapAmountInfo(
|
||||
SwapModeExactIn,
|
||||
@@ -893,6 +1014,7 @@ func depositParse(tx *Tx, instruction Instruction, innerInstructions InnerInstru
|
||||
QuoteAmount: decimal.NewFromUint64(event.QuoteAmountIn),
|
||||
BaseReserve: decimal.NewFromUint64(event.PoolBaseTokenReserves + event.BaseAmountIn),
|
||||
QuoteReserve: decimal.NewFromUint64(event.PoolQuoteTokenReserves + event.QuoteAmountIn),
|
||||
RealQuoteReserve: decimal.NewFromUint64(event.PoolQuoteTokenReserves + event.QuoteAmountIn),
|
||||
//Mayhem: false,
|
||||
UserBaseBalance: decimal.NewFromUint64(event.UserBaseTokenReserves - event.BaseAmountIn),
|
||||
UserQuoteBalance: decimal.NewFromUint64(event.UserQuoteTokenReserves - event.QuoteAmountIn),
|
||||
@@ -994,6 +1116,7 @@ func withdrawParse(tx *Tx, instruction Instruction, innerInstructions InnerInstr
|
||||
QuoteAmount: decimal.NewFromUint64(event.QuoteAmountOut),
|
||||
BaseReserve: decimal.NewFromUint64(event.PoolBaseTokenReserves - event.BaseAmountOut),
|
||||
QuoteReserve: decimal.NewFromUint64(event.PoolQuoteTokenReserves - event.QuoteAmountOut),
|
||||
RealQuoteReserve: decimal.NewFromUint64(event.PoolQuoteTokenReserves - event.QuoteAmountOut),
|
||||
//Mayhem: false,
|
||||
UserBaseBalance: decimal.NewFromUint64(event.UserBaseTokenReserves + event.BaseAmountOut),
|
||||
UserQuoteBalance: decimal.NewFromUint64(event.UserQuoteTokenReserves + event.QuoteAmountOut),
|
||||
|
||||
Reference in New Issue
Block a user