update amm virtual quotes reserves
This commit is contained in:
102
tx_binary.go
102
tx_binary.go
@@ -8,6 +8,7 @@ import (
|
||||
"io"
|
||||
"iter"
|
||||
"math"
|
||||
"math/big"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
||||
@@ -18,7 +19,9 @@ import (
|
||||
|
||||
const (
|
||||
txBinarySchemaVersionV3 uint16 = 3
|
||||
txBinarySchemaVersionCurrent uint16 = 4
|
||||
txBinarySchemaVersionV4 uint16 = 4
|
||||
txBinarySchemaVersionV5 uint16 = 5
|
||||
txBinarySchemaVersionCurrent = txBinarySchemaVersionV5
|
||||
txBinaryEnumVersionV1 uint16 = 1
|
||||
|
||||
txBinarySOLScale int32 = 9
|
||||
@@ -102,6 +105,9 @@ type SwapBinary struct {
|
||||
LpMint uint32
|
||||
|
||||
AfterSOLBalance float64
|
||||
|
||||
RealQuoteReserve uint64
|
||||
VirtualQuoteReserve [16]byte
|
||||
}
|
||||
|
||||
type TxsBinary struct {
|
||||
@@ -659,7 +665,7 @@ func (tx *TxBinary) ToTx() (*Tx, error) {
|
||||
if len(tx.Swaps) > 0 {
|
||||
out.Swaps = make([]Swap, 0, len(tx.Swaps))
|
||||
for i, swap := range tx.Swaps {
|
||||
decodedSwap, err := swap.toSwap(tx.AddressTable, i)
|
||||
decodedSwap, err := swap.toSwap(tx.AddressTable, i, tx.SchemaVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -797,6 +803,12 @@ func newSwapBinary(swap Swap, index int, addressIndex *txBinaryAddressIndex) (Sw
|
||||
if out.QuoteReserve, err = txBinaryDecimalToFloat64Raw(swap.QuoteReserve, fmt.Sprintf("swap[%d].quote_reserve", index)); err != nil {
|
||||
return SwapBinary{}, err
|
||||
}
|
||||
if out.RealQuoteReserve, err = txBinaryDecimalToUint64(swap.RealQuoteReserve, fmt.Sprintf("swap[%d].real_quote_reserve", index)); err != nil {
|
||||
return SwapBinary{}, err
|
||||
}
|
||||
if out.VirtualQuoteReserve, err = txBinaryDecimalToInt128(swap.VirtualQuoteReserve, fmt.Sprintf("swap[%d].virtual_quote_reserve", index)); err != nil {
|
||||
return SwapBinary{}, err
|
||||
}
|
||||
if out.UserBaseBalance, err = txBinaryDecimalToUint64(swap.UserBaseBalance, fmt.Sprintf("swap[%d].user_base_balance", index)); err != nil {
|
||||
return SwapBinary{}, err
|
||||
}
|
||||
@@ -810,7 +822,7 @@ func newSwapBinary(swap Swap, index int, addressIndex *txBinaryAddressIndex) (Sw
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (swap SwapBinary) toSwap(addressTable []solana.PublicKey, index int) (Swap, error) {
|
||||
func (swap SwapBinary) toSwap(addressTable []solana.PublicKey, index int, schemaVersion uint16) (Swap, error) {
|
||||
pool, err := txBinaryAddressAt(addressTable, swap.Pool, fmt.Sprintf("swap[%d].pool", index))
|
||||
if err != nil {
|
||||
return Swap{}, err
|
||||
@@ -864,6 +876,20 @@ func (swap SwapBinary) toSwap(addressTable []solana.PublicKey, index int) (Swap,
|
||||
return Swap{}, err
|
||||
}
|
||||
|
||||
quoteReserve := txBinaryFloat64ToDecimalRaw(swap.QuoteReserve)
|
||||
realQuoteReserve := quoteReserve
|
||||
virtualQuoteReserve := decimal.Zero
|
||||
if schemaVersion >= txBinarySchemaVersionV5 {
|
||||
realQuoteReserve = decimal.NewFromUint64(swap.RealQuoteReserve)
|
||||
virtualQuoteReserve = txBinaryInt128ToDecimal(swap.VirtualQuoteReserve)
|
||||
// A v3/v4 batch upgraded by the streaming merger has no component
|
||||
// bytes to carry forward. Preserve its legacy meaning after the
|
||||
// merged output is written as v5.
|
||||
if realQuoteReserve.IsZero() && virtualQuoteReserve.IsZero() && !quoteReserve.IsZero() {
|
||||
realQuoteReserve = quoteReserve
|
||||
}
|
||||
}
|
||||
|
||||
return Swap{
|
||||
Program: swap.Program,
|
||||
Event: swap.Event,
|
||||
@@ -893,7 +919,9 @@ func (swap SwapBinary) toSwap(addressTable []solana.PublicKey, index int) (Swap,
|
||||
ActualLimitAmountSide: swap.ActualLimitAmountSide,
|
||||
SlippageBps: decimal.NewFromUint64(swap.SlippageBps),
|
||||
BaseReserve: txBinaryFloat64ToDecimalRaw(swap.BaseReserve),
|
||||
QuoteReserve: txBinaryFloat64ToDecimalRaw(swap.QuoteReserve),
|
||||
QuoteReserve: quoteReserve,
|
||||
RealQuoteReserve: realQuoteReserve,
|
||||
VirtualQuoteReserve: virtualQuoteReserve,
|
||||
Mayhem: swap.Mayhem,
|
||||
Cashback: swap.Cashback,
|
||||
UserBaseBalance: decimal.NewFromUint64(swap.UserBaseBalance),
|
||||
@@ -1071,6 +1099,44 @@ func txBinaryDecimalToUint64(value decimal.Decimal, field string) (uint64, error
|
||||
return bigInt.Uint64(), nil
|
||||
}
|
||||
|
||||
func txBinaryDecimalToInt128(value decimal.Decimal, field string) ([16]byte, error) {
|
||||
var out [16]byte
|
||||
if !value.Equal(value.Truncate(0)) {
|
||||
return out, fmt.Errorf("%s must be an integer, got %s", field, value.String())
|
||||
}
|
||||
|
||||
integer := value.BigInt()
|
||||
limit := new(big.Int).Lsh(big.NewInt(1), 127)
|
||||
minimum := new(big.Int).Neg(new(big.Int).Set(limit))
|
||||
maximum := new(big.Int).Sub(new(big.Int).Set(limit), big.NewInt(1))
|
||||
if integer.Cmp(minimum) < 0 || integer.Cmp(maximum) > 0 {
|
||||
return out, fmt.Errorf("%s overflows int128: %s", field, value.String())
|
||||
}
|
||||
|
||||
unsigned := new(big.Int).Set(integer)
|
||||
if unsigned.Sign() < 0 {
|
||||
unsigned.Add(unsigned, new(big.Int).Lsh(big.NewInt(1), 128))
|
||||
}
|
||||
var bigEndian [16]byte
|
||||
unsigned.FillBytes(bigEndian[:])
|
||||
for i := range out {
|
||||
out[i] = bigEndian[len(bigEndian)-1-i]
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func txBinaryInt128ToDecimal(raw [16]byte) decimal.Decimal {
|
||||
var bigEndian [16]byte
|
||||
for i := range raw {
|
||||
bigEndian[i] = raw[len(raw)-1-i]
|
||||
}
|
||||
integer := new(big.Int).SetBytes(bigEndian[:])
|
||||
if raw[len(raw)-1]&0x80 != 0 {
|
||||
integer.Sub(integer, new(big.Int).Lsh(big.NewInt(1), 128))
|
||||
}
|
||||
return decimal.NewFromBigInt(integer, 0)
|
||||
}
|
||||
|
||||
func txBinaryScaledDecimalToUint64(value decimal.Decimal, scale int32, field string) (uint64, error) {
|
||||
return txBinaryDecimalToUint64(value.Shift(scale), field)
|
||||
}
|
||||
@@ -1179,7 +1245,7 @@ func (enc *txBinaryEncoder) writeTxBinaryBody(tx *TxBinary, enumTable *txBinaryE
|
||||
enc.writeUint32(tx.Signer)
|
||||
enc.writeUint64(tx.Block)
|
||||
enc.writeUint64(tx.BlockIndex)
|
||||
if tx.SchemaVersion >= txBinarySchemaVersionCurrent {
|
||||
if tx.SchemaVersion >= txBinarySchemaVersionV4 {
|
||||
enc.writeUint64(uint64(tx.BlockAt))
|
||||
}
|
||||
enc.writeBool(tx.TxHash != nil)
|
||||
@@ -1198,7 +1264,7 @@ func (enc *txBinaryEncoder) writeTxBinaryBody(tx *TxBinary, enumTable *txBinaryE
|
||||
if err := enc.writeMevAgentEntries(tx.MevAgent, enumTable); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := enc.writeSwaps(tx.Swaps, enumTable); err != nil {
|
||||
if err := enc.writeSwaps(tx.Swaps, enumTable, tx.SchemaVersion); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -1230,7 +1296,7 @@ func (enc *txBinaryEncoder) writeMevAgentEntries(entries []MevAgentBinary, enumT
|
||||
return nil
|
||||
}
|
||||
|
||||
func (enc *txBinaryEncoder) writeSwaps(swaps []SwapBinary, enumTable *txBinaryEnumTable) error {
|
||||
func (enc *txBinaryEncoder) writeSwaps(swaps []SwapBinary, enumTable *txBinaryEnumTable, schemaVersion uint16) error {
|
||||
enc.writeUint32(uint32(len(swaps)))
|
||||
for i, swap := range swaps {
|
||||
programID, err := enumTable.programs.id(swap.Program)
|
||||
@@ -1280,6 +1346,10 @@ func (enc *txBinaryEncoder) writeSwaps(swaps []SwapBinary, enumTable *txBinaryEn
|
||||
enc.writeUint32(swap.MigrateTopProgram)
|
||||
enc.writeUint32(swap.LpMint)
|
||||
enc.writeFloat64(swap.AfterSOLBalance)
|
||||
if schemaVersion >= txBinarySchemaVersionV5 {
|
||||
enc.writeUint64(swap.RealQuoteReserve)
|
||||
enc.writeBytes(swap.VirtualQuoteReserve[:])
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1395,7 +1465,7 @@ func (dec *txBinaryDecoder) readMevAgentEntries(enumTable *txBinaryEnumTable) ([
|
||||
}
|
||||
|
||||
func (dec *txBinaryDecoder) readSwaps(enumTable *txBinaryEnumTable, _ []solana.PublicKey) ([]SwapBinary, error) {
|
||||
return txBinaryReadSwaps(dec, enumTable)
|
||||
return txBinaryReadSwaps(dec, enumTable, txBinarySchemaVersionCurrent)
|
||||
}
|
||||
|
||||
func (dec *txBinaryDecoder) readTxBinaryBody(tx *TxBinary, enumTable *txBinaryEnumTable, addressTable []solana.PublicKey) error {
|
||||
@@ -1651,7 +1721,7 @@ func txBinaryReadMevAgentEntries(dec txBinaryBodyReader, enumTable *txBinaryEnum
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func txBinaryReadSwaps(dec txBinaryBodyReader, enumTable *txBinaryEnumTable) ([]SwapBinary, error) {
|
||||
func txBinaryReadSwaps(dec txBinaryBodyReader, enumTable *txBinaryEnumTable, schemaVersion uint16) ([]SwapBinary, error) {
|
||||
count, err := dec.readUint32()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1798,6 +1868,16 @@ func txBinaryReadSwaps(dec txBinaryBodyReader, enumTable *txBinaryEnumTable) ([]
|
||||
if swap.AfterSOLBalance, err = dec.readFloat64(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if schemaVersion >= txBinarySchemaVersionV5 {
|
||||
if swap.RealQuoteReserve, err = dec.readUint64(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rawVirtualQuoteReserve, err := dec.readN(len(swap.VirtualQuoteReserve))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy(swap.VirtualQuoteReserve[:], rawVirtualQuoteReserve)
|
||||
}
|
||||
out = append(out, swap)
|
||||
}
|
||||
return out, nil
|
||||
@@ -1815,7 +1895,7 @@ func txBinaryReadTxBody(dec txBinaryBodyReader, tx *TxBinary, enumTable *txBinar
|
||||
if tx.BlockIndex, err = dec.readUint64(); err != nil {
|
||||
return err
|
||||
}
|
||||
if tx.SchemaVersion >= txBinarySchemaVersionCurrent {
|
||||
if tx.SchemaVersion >= txBinarySchemaVersionV4 {
|
||||
blockAt, err := dec.readUint64()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -1863,7 +1943,7 @@ func txBinaryReadTxBody(dec txBinaryBodyReader, tx *TxBinary, enumTable *txBinar
|
||||
if tx.MevAgent, err = txBinaryReadMevAgentEntries(dec, enumTable); err != nil {
|
||||
return err
|
||||
}
|
||||
if tx.Swaps, err = txBinaryReadSwaps(dec, enumTable); err != nil {
|
||||
if tx.Swaps, err = txBinaryReadSwaps(dec, enumTable, tx.SchemaVersion); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user