Compare commits

...

1 Commits

Author SHA1 Message Date
thloyi
51f1511c8f fix EncodeTxBinary 2026-04-20 15:09:42 +08:00
3 changed files with 94 additions and 10 deletions

View File

@@ -62,6 +62,12 @@ func main() {
swap.BaseAmount.Div(decimal.NewFromInt(1e6)), swap.QuoteAmount.Div(decimal.NewFromInt(1e9)), swap.FixedAmount.String(), swap.LimitAmount.String()) swap.BaseAmount.Div(decimal.NewFromInt(1e6)), swap.QuoteAmount.Div(decimal.NewFromInt(1e9)), swap.FixedAmount.String(), swap.LimitAmount.String())
} }
} }
if len(ptx.Swaps) > 0 {
_, err := parser.EncodeTxBinary(ptx)
if err != nil {
fmt.Printf("success tx : %s, , block: %d, tx: %s, err: %s \n", time.Now().Format("2006-01-02 15:04:05"), ptx.Block, ptx.GetTxHash(), err.Error())
}
}
} }
// currentBlock = ptx.Block // currentBlock = ptx.Block

View File

@@ -80,8 +80,8 @@ type SwapBinary struct {
ActualLimitAmountSide SwapAmountSide ActualLimitAmountSide SwapAmountSide
SlippageBps uint64 SlippageBps uint64
BaseReserve uint64 BaseReserve float64
QuoteReserve uint64 QuoteReserve float64
Mayhem bool Mayhem bool
Cashback bool Cashback bool
@@ -777,10 +777,10 @@ func newSwapBinary(swap Swap, index int, addressIndex *txBinaryAddressIndex) (Sw
if out.SlippageBps, err = txBinaryRoundedDecimalToUint64(swap.SlippageBps, fmt.Sprintf("swap[%d].slippage_bps", index)); err != nil { if out.SlippageBps, err = txBinaryRoundedDecimalToUint64(swap.SlippageBps, fmt.Sprintf("swap[%d].slippage_bps", index)); err != nil {
return SwapBinary{}, err return SwapBinary{}, err
} }
if out.BaseReserve, err = txBinaryDecimalToUint64(swap.BaseReserve, fmt.Sprintf("swap[%d].base_reserve", index)); err != nil { if out.BaseReserve, err = txBinaryDecimalToFloat64Raw(swap.BaseReserve, fmt.Sprintf("swap[%d].base_reserve", index)); err != nil {
return SwapBinary{}, err return SwapBinary{}, err
} }
if out.QuoteReserve, err = txBinaryDecimalToUint64(swap.QuoteReserve, fmt.Sprintf("swap[%d].quote_reserve", index)); err != nil { if out.QuoteReserve, err = txBinaryDecimalToFloat64Raw(swap.QuoteReserve, fmt.Sprintf("swap[%d].quote_reserve", index)); err != nil {
return SwapBinary{}, err return SwapBinary{}, err
} }
if out.UserBaseBalance, err = txBinaryDecimalToUint64(swap.UserBaseBalance, fmt.Sprintf("swap[%d].user_base_balance", index)); err != nil { if out.UserBaseBalance, err = txBinaryDecimalToUint64(swap.UserBaseBalance, fmt.Sprintf("swap[%d].user_base_balance", index)); err != nil {
@@ -878,8 +878,8 @@ func (swap SwapBinary) toSwap(addressTable []solana.PublicKey, index int) (Swap,
ActualLimitAmount: decimal.NewFromUint64(swap.ActualLimitAmount), ActualLimitAmount: decimal.NewFromUint64(swap.ActualLimitAmount),
ActualLimitAmountSide: swap.ActualLimitAmountSide, ActualLimitAmountSide: swap.ActualLimitAmountSide,
SlippageBps: decimal.NewFromUint64(swap.SlippageBps), SlippageBps: decimal.NewFromUint64(swap.SlippageBps),
BaseReserve: decimal.NewFromUint64(swap.BaseReserve), BaseReserve: txBinaryFloat64ToDecimalRaw(swap.BaseReserve),
QuoteReserve: decimal.NewFromUint64(swap.QuoteReserve), QuoteReserve: txBinaryFloat64ToDecimalRaw(swap.QuoteReserve),
Mayhem: swap.Mayhem, Mayhem: swap.Mayhem,
Cashback: swap.Cashback, Cashback: swap.Cashback,
UserBaseBalance: decimal.NewFromUint64(swap.UserBaseBalance), UserBaseBalance: decimal.NewFromUint64(swap.UserBaseBalance),
@@ -1063,6 +1063,14 @@ func txBinaryDecimalToFloat64(value decimal.Decimal, scale int32, field string)
return f, nil return f, nil
} }
func txBinaryDecimalToFloat64Raw(value decimal.Decimal, field string) (float64, error) {
f, exact := value.Float64()
if !exact && math.IsInf(f, 0) {
return 0, fmt.Errorf("%s cannot be represented as float64: %s", field, value.String())
}
return f, nil
}
func txBinaryFloat64ToDecimal(value float64, scale int32) decimal.Decimal { func txBinaryFloat64ToDecimal(value float64, scale int32) decimal.Decimal {
formatted := strconv.FormatFloat(value, 'f', int(scale), 64) formatted := strconv.FormatFloat(value, 'f', int(scale), 64)
out, err := decimal.NewFromString(formatted) out, err := decimal.NewFromString(formatted)
@@ -1072,6 +1080,15 @@ func txBinaryFloat64ToDecimal(value float64, scale int32) decimal.Decimal {
return out return out
} }
func txBinaryFloat64ToDecimalRaw(value float64) decimal.Decimal {
formatted := strconv.FormatFloat(value, 'f', -1, 64)
out, err := decimal.NewFromString(formatted)
if err != nil {
return decimal.Zero
}
return out
}
type txBinaryEncoder struct { type txBinaryEncoder struct {
buf bytes.Buffer buf bytes.Buffer
} }
@@ -1224,8 +1241,8 @@ func (enc *txBinaryEncoder) writeSwaps(swaps []SwapBinary, enumTable *txBinaryEn
enc.writeUint64(swap.ActualLimitAmount) enc.writeUint64(swap.ActualLimitAmount)
enc.writeUint8(uint8(swap.ActualLimitAmountSide)) enc.writeUint8(uint8(swap.ActualLimitAmountSide))
enc.writeUint64(swap.SlippageBps) enc.writeUint64(swap.SlippageBps)
enc.writeUint64(swap.BaseReserve) enc.writeFloat64(swap.BaseReserve)
enc.writeUint64(swap.QuoteReserve) enc.writeFloat64(swap.QuoteReserve)
enc.writeBool(swap.Mayhem) enc.writeBool(swap.Mayhem)
enc.writeBool(swap.Cashback) enc.writeBool(swap.Cashback)
enc.writeUint64(swap.UserBaseBalance) enc.writeUint64(swap.UserBaseBalance)
@@ -1720,10 +1737,10 @@ func txBinaryReadSwaps(dec txBinaryBodyReader, enumTable *txBinaryEnumTable) ([]
if swap.SlippageBps, err = dec.readUint64(); err != nil { if swap.SlippageBps, err = dec.readUint64(); err != nil {
return nil, err return nil, err
} }
if swap.BaseReserve, err = dec.readUint64(); err != nil { if swap.BaseReserve, err = dec.readFloat64(); err != nil {
return nil, err return nil, err
} }
if swap.QuoteReserve, err = dec.readUint64(); err != nil { if swap.QuoteReserve, err = dec.readFloat64(); err != nil {
return nil, err return nil, err
} }
if swap.Mayhem, err = dec.readBool(); err != nil { if swap.Mayhem, err = dec.readBool(); err != nil {

View File

@@ -293,6 +293,67 @@ func TestTxBinaryAcceptsKnownEventEnums(t *testing.T) {
} }
} }
func TestTxBinaryPreservesFractionalReserves(t *testing.T) {
tx := &Tx{
Signer: mustPubKey("So11111111111111111111111111111111111111112"),
Block: 1,
BlockIndex: 1,
CuFee: decimal.NewFromInt(1),
CUPrice: decimal.RequireFromString("0.000001"),
BeforeSolBalance: decimal.RequireFromString("1.000000000"),
AfterSOLBalance: decimal.RequireFromString("0.900000000"),
ComputeUnitsConsumed: 1,
CuLimit: 1,
Swaps: []Swap{
{
Program: SolProgramMeteoraPools,
Event: TxEventAddLiquidity,
Pool: mustPubKey("11111111111111111111111111111111"),
BaseMint: mustPubKey("3wyAj7RtG72wM1Wv9DkYfL7RAx9X3Jx1sC6E6mN4jWeL"),
QuoteMint: solana.WrappedSol,
BaseTokenProgram: solana.TokenProgramID,
QuoteTokenProgram: solana.TokenProgramID,
Creator: mustPubKey("BPFLoader1111111111111111111111111111111111"),
BaseMintDecimals: 6,
QuoteMintDecimals: 9,
User: mustPubKey("SysvarRent111111111111111111111111111111111"),
BaseAmount: decimal.NewFromInt(10),
QuoteAmount: decimal.NewFromInt(20),
SwapMode: SwapModeExactIn,
FixedAmount: decimal.NewFromInt(20),
FixedAmountSide: SwapAmountSideQuote,
FixedMint: solana.WrappedSol,
LimitAmountType: SwapLimitTypeMinOut,
LimitAmount: decimal.NewFromInt(9),
LimitAmountSide: SwapAmountSideBase,
LimitMint: mustPubKey("3wyAj7RtG72wM1Wv9DkYfL7RAx9X3Jx1sC6E6mN4jWeL"),
ActualLimitAmount: decimal.NewFromInt(10),
ActualLimitAmountSide: SwapAmountSideBase,
BaseReserve: decimal.RequireFromString("123.4"),
QuoteReserve: decimal.RequireFromString("710079483.625409498"),
AfterSOLBalance: decimal.RequireFromString("0.800000000"),
},
},
}
encoded, err := EncodeTxBinary(tx)
if err != nil {
t.Fatalf("EncodeTxBinary() error = %v", err)
}
decoded, err := DecodeTxBinary(encoded)
if err != nil {
t.Fatalf("DecodeTxBinary() error = %v", err)
}
if got := decoded.Swaps[0].BaseReserve.String(); got != "123.4" {
t.Fatalf("BaseReserve = %s, want 123.4", got)
}
diff := decoded.Swaps[0].QuoteReserve.Sub(decimal.RequireFromString("710079483.625409498")).Abs()
if diff.GreaterThan(decimal.RequireFromString("0.0000001")) {
t.Fatalf("QuoteReserve diff = %s, want <= 0.0000001", diff)
}
}
func TestTxsBinaryRoundTripWithSharedAddressTable(t *testing.T) { func TestTxsBinaryRoundTripWithSharedAddressTable(t *testing.T) {
tx1 := Tx{ tx1 := Tx{
Signer: mustPubKey("So11111111111111111111111111111111111111112"), Signer: mustPubKey("So11111111111111111111111111111111111111112"),