151 lines
4.5 KiB
Go
151 lines
4.5 KiB
Go
|
|
package pump_parser
|
||
|
|
|
||
|
|
import (
|
||
|
|
"testing"
|
||
|
|
|
||
|
|
"github.com/gagliardetto/solana-go"
|
||
|
|
"github.com/shopspring/decimal"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestSetSwapAmountInfoExactInBuy(t *testing.T) {
|
||
|
|
swap := Swap{
|
||
|
|
Event: TxEventBuy,
|
||
|
|
BaseMint: solana.MustPublicKeyFromBase58("11111111111111111111111111111111"),
|
||
|
|
QuoteMint: solana.MustPublicKeyFromBase58("So11111111111111111111111111111111111111112"),
|
||
|
|
BaseAmount: decimal.NewFromInt(120),
|
||
|
|
QuoteAmount: decimal.NewFromInt(100),
|
||
|
|
}
|
||
|
|
|
||
|
|
swap.SetSwapAmountInfo(SwapModeExactIn, decimal.NewFromInt(100), decimal.NewFromInt(110))
|
||
|
|
|
||
|
|
if swap.FixedAmountSide != SwapAmountSideQuote {
|
||
|
|
t.Fatalf("fixed side = %s, want quote", swap.FixedAmountSide.String())
|
||
|
|
}
|
||
|
|
if swap.LimitAmountType != SwapLimitTypeMinOut {
|
||
|
|
t.Fatalf("limit type = %s, want min_out", swap.LimitAmountType.String())
|
||
|
|
}
|
||
|
|
if swap.LimitAmountSide != SwapAmountSideBase {
|
||
|
|
t.Fatalf("limit side = %s, want base", swap.LimitAmountSide.String())
|
||
|
|
}
|
||
|
|
if !swap.ActualLimitAmount.Equal(decimal.NewFromInt(120)) {
|
||
|
|
t.Fatalf("actual limit amount = %s, want 120", swap.ActualLimitAmount)
|
||
|
|
}
|
||
|
|
if got := swap.SlippageBps.StringFixed(4); got != "833.3333" {
|
||
|
|
t.Fatalf("slippage bps = %s, want 833.3333", got)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestSetSwapAmountInfoExactOutSell(t *testing.T) {
|
||
|
|
swap := Swap{
|
||
|
|
Event: TxEventSell,
|
||
|
|
BaseMint: solana.MustPublicKeyFromBase58("11111111111111111111111111111111"),
|
||
|
|
QuoteMint: solana.MustPublicKeyFromBase58("So11111111111111111111111111111111111111112"),
|
||
|
|
BaseAmount: decimal.NewFromInt(95),
|
||
|
|
QuoteAmount: decimal.NewFromInt(100),
|
||
|
|
}
|
||
|
|
|
||
|
|
swap.SetSwapAmountInfo(SwapModeExactOut, decimal.NewFromInt(100), decimal.NewFromInt(105))
|
||
|
|
|
||
|
|
if swap.FixedAmountSide != SwapAmountSideQuote {
|
||
|
|
t.Fatalf("fixed side = %s, want quote", swap.FixedAmountSide.String())
|
||
|
|
}
|
||
|
|
if swap.LimitAmountType != SwapLimitTypeMaxIn {
|
||
|
|
t.Fatalf("limit type = %s, want max_in", swap.LimitAmountType.String())
|
||
|
|
}
|
||
|
|
if swap.LimitAmountSide != SwapAmountSideBase {
|
||
|
|
t.Fatalf("limit side = %s, want base", swap.LimitAmountSide.String())
|
||
|
|
}
|
||
|
|
if !swap.ActualLimitAmount.Equal(decimal.NewFromInt(95)) {
|
||
|
|
t.Fatalf("actual limit amount = %s, want 95", swap.ActualLimitAmount)
|
||
|
|
}
|
||
|
|
if got := swap.SlippageBps.StringFixed(4); got != "952.3810" {
|
||
|
|
t.Fatalf("slippage bps = %s, want 952.3810", got)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestSetSwapAmountInfoExactInZeroLimitUsesMaxSlippage(t *testing.T) {
|
||
|
|
swap := Swap{
|
||
|
|
Event: TxEventSell,
|
||
|
|
BaseMint: solana.MustPublicKeyFromBase58("11111111111111111111111111111111"),
|
||
|
|
QuoteMint: solana.MustPublicKeyFromBase58("So11111111111111111111111111111111111111112"),
|
||
|
|
BaseAmount: decimal.NewFromInt(50),
|
||
|
|
QuoteAmount: decimal.NewFromInt(25),
|
||
|
|
}
|
||
|
|
|
||
|
|
swap.SetSwapAmountInfo(SwapModeExactIn, decimal.NewFromInt(50), decimal.Zero)
|
||
|
|
|
||
|
|
if got := swap.SlippageBps.String(); got != "10000" {
|
||
|
|
t.Fatalf("slippage bps = %s, want 10000", got)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestMeteoraDammSwapAmountInfo(t *testing.T) {
|
||
|
|
tests := []struct {
|
||
|
|
name string
|
||
|
|
event string
|
||
|
|
params *struct {
|
||
|
|
Amount0 uint64
|
||
|
|
Amount1 uint64
|
||
|
|
SwapMode uint8
|
||
|
|
}
|
||
|
|
wantMode SwapMode
|
||
|
|
wantFixed int64
|
||
|
|
wantLimit int64
|
||
|
|
}{
|
||
|
|
{
|
||
|
|
name: "sell exact in uses amount0 as input and amount1 as min out",
|
||
|
|
event: TxEventSell,
|
||
|
|
params: &struct {
|
||
|
|
Amount0 uint64
|
||
|
|
Amount1 uint64
|
||
|
|
SwapMode uint8
|
||
|
|
}{Amount0: 100, Amount1: 95, SwapMode: 0},
|
||
|
|
wantMode: SwapModeExactIn,
|
||
|
|
wantFixed: 100,
|
||
|
|
wantLimit: 95,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "sell partial fill follows exact in semantics",
|
||
|
|
event: TxEventSell,
|
||
|
|
params: &struct {
|
||
|
|
Amount0 uint64
|
||
|
|
Amount1 uint64
|
||
|
|
SwapMode uint8
|
||
|
|
}{Amount0: 101, Amount1: 96, SwapMode: 1},
|
||
|
|
wantMode: SwapModeExactIn,
|
||
|
|
wantFixed: 101,
|
||
|
|
wantLimit: 96,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "buy exact out uses amount0 as target output and amount1 as max input",
|
||
|
|
event: TxEventBuy,
|
||
|
|
params: &struct {
|
||
|
|
Amount0 uint64
|
||
|
|
Amount1 uint64
|
||
|
|
SwapMode uint8
|
||
|
|
}{Amount0: 120, Amount1: 130, SwapMode: 2},
|
||
|
|
wantMode: SwapModeExactOut,
|
||
|
|
wantFixed: 120,
|
||
|
|
wantLimit: 130,
|
||
|
|
},
|
||
|
|
}
|
||
|
|
|
||
|
|
for _, tt := range tests {
|
||
|
|
t.Run(tt.name, func(t *testing.T) {
|
||
|
|
gotMode, gotFixed, gotLimit, ok := meteoraDammSwapAmountInfo(tt.event, tt.params)
|
||
|
|
if !ok {
|
||
|
|
t.Fatal("ok = false, want true")
|
||
|
|
}
|
||
|
|
if gotMode != tt.wantMode {
|
||
|
|
t.Fatalf("mode = %s, want %s", gotMode.String(), tt.wantMode.String())
|
||
|
|
}
|
||
|
|
if !gotFixed.Equal(decimal.NewFromInt(tt.wantFixed)) {
|
||
|
|
t.Fatalf("fixed = %s, want %d", gotFixed, tt.wantFixed)
|
||
|
|
}
|
||
|
|
if !gotLimit.Equal(decimal.NewFromInt(tt.wantLimit)) {
|
||
|
|
t.Fatalf("limit = %s, want %d", gotLimit, tt.wantLimit)
|
||
|
|
}
|
||
|
|
})
|
||
|
|
}
|
||
|
|
}
|