update amm virtual quotes reserves
This commit is contained in:
127
pumpamm_test.go
127
pumpamm_test.go
@@ -1,11 +1,13 @@
|
||||
package pump_parser
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
|
||||
agbinary "github.com/gagliardetto/binary"
|
||||
"github.com/gagliardetto/solana-go"
|
||||
"github.com/mr-tron/base58"
|
||||
|
||||
"testing"
|
||||
)
|
||||
@@ -40,3 +42,128 @@ func TestAmmBuyEvent(t *testing.T) {
|
||||
fmt.Println(pumpAmmBuyEventDiscriminator)
|
||||
fmt.Println(pumpGetFeesDiscriminator)
|
||||
}
|
||||
|
||||
func TestDecodeAmmBuyEventSuffixCompatibility(t *testing.T) {
|
||||
prefix := ammBuyEventPrefix{TimeStamp: 123, PoolQuoteTokenReserve: 456}
|
||||
|
||||
legacy, err := decodeAmmBuyEvent(encodeAmmEventParts(t, prefix))
|
||||
if err != nil {
|
||||
t.Fatalf("decodeAmmBuyEvent(legacy) error = %v", err)
|
||||
}
|
||||
if legacy.TimeStamp != prefix.TimeStamp || legacy.PoolQuoteTokenReserve != prefix.PoolQuoteTokenReserve {
|
||||
t.Fatalf("legacy prefix mismatch: %+v", legacy.ammBuyEventPrefix)
|
||||
}
|
||||
if legacy.BuybackFeeBasisPoints != 0 || legacy.BuybackFee != 0 || legacy.CanBoost || legacy.BaseSupply != 0 || !pumpAmmVirtualQuoteReserve(legacy.VirtualQuoteReserves).IsZero() {
|
||||
t.Fatalf("legacy suffix is not zero-valued: %+v", legacy)
|
||||
}
|
||||
|
||||
buyback := ammTradeEventBuybackSuffix{BuybackFeeBasisPoints: 1000, BuybackFee: 77}
|
||||
withBuyback, err := decodeAmmBuyEvent(encodeAmmEventParts(t, prefix, buyback))
|
||||
if err != nil {
|
||||
t.Fatalf("decodeAmmBuyEvent(buyback) error = %v", err)
|
||||
}
|
||||
if withBuyback.BuybackFeeBasisPoints != buyback.BuybackFeeBasisPoints || withBuyback.BuybackFee != buyback.BuybackFee {
|
||||
t.Fatalf("buyback suffix mismatch: %+v", withBuyback)
|
||||
}
|
||||
if withBuyback.CanBoost || withBuyback.BaseSupply != 0 || !pumpAmmVirtualQuoteReserve(withBuyback.VirtualQuoteReserves).IsZero() {
|
||||
t.Fatalf("pre-virtual suffix has unexpected virtual fields: %+v", withBuyback)
|
||||
}
|
||||
|
||||
negativeVirtual := agbinary.Int128(agbinary.Uint128{Lo: ^uint64(122), Hi: ^uint64(0)})
|
||||
virtual := ammTradeEventVirtualSuffix{
|
||||
VirtualQuoteReserves: negativeVirtual,
|
||||
CanBoost: true,
|
||||
BaseSupply: 1_000_000,
|
||||
}
|
||||
current, err := decodeAmmBuyEvent(encodeAmmEventParts(t, prefix, buyback, virtual))
|
||||
if err != nil {
|
||||
t.Fatalf("decodeAmmBuyEvent(current) error = %v", err)
|
||||
}
|
||||
if got := pumpAmmVirtualQuoteReserve(current.VirtualQuoteReserves).String(); got != "-123" {
|
||||
t.Fatalf("VirtualQuoteReserves = %s, want -123", got)
|
||||
}
|
||||
if !current.CanBoost || current.BaseSupply != virtual.BaseSupply {
|
||||
t.Fatalf("current suffix mismatch: %+v", current)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeAmmSellEventSuffixCompatibility(t *testing.T) {
|
||||
prefix := ammSellEventPrefix{Timestamp: 321, PoolQuoteTokenReserves: 654, QuoteAmountOut: 54}
|
||||
buyback := ammTradeEventBuybackSuffix{BuybackFeeBasisPoints: 900, BuybackFee: 88}
|
||||
virtual := ammTradeEventVirtualSuffix{
|
||||
VirtualQuoteReserves: agbinary.Int128(agbinary.Uint128{Lo: 987}),
|
||||
CanBoost: true,
|
||||
BaseSupply: 2_000_000,
|
||||
}
|
||||
|
||||
event, err := decodeAmmSellEvent(encodeAmmEventParts(t, prefix, buyback, virtual))
|
||||
if err != nil {
|
||||
t.Fatalf("decodeAmmSellEvent() error = %v", err)
|
||||
}
|
||||
if event.Timestamp != prefix.Timestamp || event.BuybackFee != buyback.BuybackFee || !event.CanBoost || event.BaseSupply != virtual.BaseSupply {
|
||||
t.Fatalf("decoded sell event mismatch: %+v", event)
|
||||
}
|
||||
if got := pumpAmmVirtualQuoteReserve(event.VirtualQuoteReserves).String(); got != "987" {
|
||||
t.Fatalf("VirtualQuoteReserves = %s, want 987", got)
|
||||
}
|
||||
real, effective := pumpAmmSellPostQuoteReserves(event)
|
||||
if real.String() != "600" || effective.String() != "1587" {
|
||||
t.Fatalf("post reserves = real %s effective %s", real, effective)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeAmmTradeEventRejectsTruncatedSuffix(t *testing.T) {
|
||||
prefix := encodeAmmEventParts(t, ammBuyEventPrefix{})
|
||||
for _, suffixLength := range []int{1, 15, 17, 40} {
|
||||
data := append(append([]byte(nil), prefix...), make([]byte, suffixLength)...)
|
||||
if _, err := decodeAmmBuyEvent(data); err == nil {
|
||||
t.Fatalf("decodeAmmBuyEvent() error = nil for %d-byte suffix", suffixLength)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeAmmBuyEventDevnetVirtualReserve(t *testing.T) {
|
||||
const eventDataBase58 = "6MF1ykxMQW5eFmo1ErWgds8V2wfEyqJPjEsoz4yRoKQCktPze5U297neF7huAQQ9DhxEJqHPwezxUh9mcQEsfdmnwW84YVxcfEzDUduRqc1zty2dLQZcFGzFeFC6fmpX75tkvuMvTN89HekHa9TEikGRuXhtWkeacjNoVqfbxXUp3FQxGSFoyeBaSdAfPMvXJ7zN4ALTDtn3a5g7HxJCPPWeUtYGcJig6RpKrC3DzAQ3x5SiiJiVhK1zdocmkkRXuTezt5L5Svrf9pbM4QkkwgvxrYqfUs5YeaLNqWYtNZfimLtENhQJcfrhQh2svCosCJ2Ux5iyyLZwJu7VLZibD41CwxuF6ngmrhde8BmEegmQ9f3L4qYhqgW5RJSiu1JnKMFqmTckuwGydQfTiyA9RsCtFxiazaAVim9SMARU2fqe9zfAPdRjBetAvTGkBxrERmmzhWVhER6g448mV1E1eeQjFWYRhtR33hSUpNUUP6dUF8CWae2BuJxaKexpiY3pyqUwbH7osvexbff8jpfpZGubP5UWjqhwijtF8tdkoEdAnb2TgWXqXMu4by5VDsEzwbgNK1DbkGbxrcXYwFTNskqoUqoNLPRaAcfnjTMA9cVme62HAj5WvxuzpL9Gpw7ZzSE2LYnVvzTa6PnN2bbpuqJpZ3d"
|
||||
data, err := base58.Decode(eventDataBase58)
|
||||
if err != nil {
|
||||
t.Fatalf("base58.Decode() error = %v", err)
|
||||
}
|
||||
if len(data) < 16 || !bytes.Equal(data[:8], pumpAmmEventDiscriminator[:]) || !bytes.Equal(data[8:16], pumpAmmBuyEventDiscriminator[:]) {
|
||||
t.Fatalf("unexpected event discriminator: len=%d", len(data))
|
||||
}
|
||||
|
||||
event, err := decodeAmmBuyEvent(data[16:])
|
||||
if err != nil {
|
||||
t.Fatalf("decodeAmmBuyEvent(devnet) error = %v", err)
|
||||
}
|
||||
if event.TimeStamp != 1784271481 || event.PoolQuoteTokenReserve != 2_213_159_021 || event.QuoteAmountIn != 100_000_000 || event.QuoteAmountInWithLpFee != 98_785_184 {
|
||||
t.Fatalf("devnet buy event core fields mismatch: %+v", event)
|
||||
}
|
||||
if event.BuybackFeeBasisPoints != 1000 || event.BuybackFee != 91_851 {
|
||||
t.Fatalf("devnet buyback fields mismatch: bps=%d fee=%d", event.BuybackFeeBasisPoints, event.BuybackFee)
|
||||
}
|
||||
if got := pumpAmmVirtualQuoteReserve(event.VirtualQuoteReserves).String(); got != "583150126" {
|
||||
t.Fatalf("VirtualQuoteReserves = %s, want 583150126", got)
|
||||
}
|
||||
if !event.CanBoost || event.BaseSupply != 1_000_000_000_000_000 {
|
||||
t.Fatalf("devnet boost metadata mismatch: can_boost=%t base_supply=%d", event.CanBoost, event.BaseSupply)
|
||||
}
|
||||
|
||||
real, effective := pumpAmmBuyPostQuoteReserves(event)
|
||||
if real.String() != "2313159021" || effective.String() != "2896309147" {
|
||||
t.Fatalf("post reserves = real %s effective %s", real, effective)
|
||||
}
|
||||
}
|
||||
|
||||
func encodeAmmEventParts(t *testing.T, parts ...any) []byte {
|
||||
t.Helper()
|
||||
|
||||
var buf bytes.Buffer
|
||||
encoder := agbinary.NewBorshEncoder(&buf)
|
||||
for _, part := range parts {
|
||||
if err := encoder.Encode(part); err != nil {
|
||||
t.Fatalf("borsh encode %T: %v", part, err)
|
||||
}
|
||||
}
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user