Compare commits
4 Commits
v0.2.45
...
9454c3f6c7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9454c3f6c7 | ||
|
|
39bfeb085f | ||
|
|
10885d5e08 | ||
|
|
2406f6d087 |
21
codex.md
Normal file
21
codex.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Codex Notes
|
||||
|
||||
## Tx Binary enum synchronization
|
||||
|
||||
When adding or renaming transaction-facing enum values, keep the binary format definitions in sync.
|
||||
|
||||
This includes, but is not limited to:
|
||||
|
||||
- tx events
|
||||
- programs
|
||||
- platforms
|
||||
- MEV agents
|
||||
- swap modes, amount sides, limit types, and fee sides
|
||||
|
||||
Checklist:
|
||||
|
||||
1. Add the public constant in the normal source location, such as `enum.go`.
|
||||
2. Add any address mapping in `consts.go` when the enum is account-derived, such as platform or MEV agent detection.
|
||||
3. Append the new value to the matching versioned enum list in `tx_binary.go` under `txBinaryEnumTables`.
|
||||
4. Do not reorder or insert into existing `tx_binary.go` enum lists unless the binary version is intentionally changed; append to preserve existing numeric IDs.
|
||||
5. Add or update tx-binary round-trip coverage so encoding and decoding the new enum value is exercised.
|
||||
@@ -25,7 +25,7 @@ func main() {
|
||||
// laserstream-mainnet-slc.helius-rpc.com:80
|
||||
|
||||
ch := make(chan example.SubscriptionMessage, 1)
|
||||
go example.RunLoopWithReConnect(context.Background(), "", "", parser.SolProgramPump, ch)
|
||||
go example.RunLoopWithReConnect(context.Background(), "ams.rpc.orbitflare.com:10000", "ORBIT-EPUZGQ-177605-508881", parser.SolProgramPump, ch)
|
||||
// var tokenTxs = make(map[string]*types.Tx)
|
||||
// currentBlock := uint64(0)
|
||||
for msg := range ch {
|
||||
|
||||
4
rawtx.go
4
rawtx.go
@@ -3,6 +3,7 @@ package pump_parser
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -876,6 +877,9 @@ func ConvertYellowstoneGrpcTransactionToSolanaTransaction(y *pb.SubscribeUpdateT
|
||||
//Version: nil,
|
||||
}
|
||||
meta := y.Transaction.GetMeta()
|
||||
if meta == nil {
|
||||
return nil, errors.New("meta can not parser")
|
||||
}
|
||||
yTx := y.Transaction.Transaction
|
||||
|
||||
if meta.Err != nil && len(meta.Err.GetErr()) > 0 {
|
||||
|
||||
31
tx_binary.go
31
tx_binary.go
@@ -1191,7 +1191,7 @@ func (enc *txBinaryEncoder) writeTxBinaryBody(tx *TxBinary, enumTable *txBinaryE
|
||||
func (enc *txBinaryEncoder) writePlatformEntries(entries []PlatformBinary, enumTable *txBinaryEnumTable) error {
|
||||
enc.writeUint32(uint32(len(entries)))
|
||||
for i, entry := range entries {
|
||||
enumID, err := enumTable.platforms.id(entry.Platform)
|
||||
enumID, err := enumTable.platforms.idOrFallback(entry.Platform, PlatformNone)
|
||||
if err != nil {
|
||||
return fmt.Errorf("platform[%d]: %w", i, err)
|
||||
}
|
||||
@@ -1204,7 +1204,7 @@ func (enc *txBinaryEncoder) writePlatformEntries(entries []PlatformBinary, enumT
|
||||
func (enc *txBinaryEncoder) writeMevAgentEntries(entries []MevAgentBinary, enumTable *txBinaryEnumTable) error {
|
||||
enc.writeUint32(uint32(len(entries)))
|
||||
for i, entry := range entries {
|
||||
enumID, err := enumTable.mevAgents.id(entry.MevAgent)
|
||||
enumID, err := enumTable.mevAgents.idOrFallback(entry.MevAgent, MevAgentUnknown)
|
||||
if err != nil {
|
||||
return fmt.Errorf("mev_agent[%d]: %w", i, err)
|
||||
}
|
||||
@@ -1592,7 +1592,7 @@ func txBinaryReadPlatformEntries(dec txBinaryBodyReader, enumTable *txBinaryEnum
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
platform, err := enumTable.platforms.value(enumID)
|
||||
platform, err := enumTable.platforms.valueOrFallback(enumID, PlatformNone)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("platform[%d]: %w", i, err)
|
||||
}
|
||||
@@ -1619,7 +1619,7 @@ func txBinaryReadMevAgentEntries(dec txBinaryBodyReader, enumTable *txBinaryEnum
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mevAgent, err := enumTable.mevAgents.value(enumID)
|
||||
mevAgent, err := enumTable.mevAgents.valueOrFallback(enumID, MevAgentUnknown)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("mev_agent[%d]: %w", i, err)
|
||||
}
|
||||
@@ -2143,6 +2143,8 @@ var txBinaryEnumTables = map[uint16]*txBinaryEnumTable{
|
||||
MevAgentSpeedlanding,
|
||||
MevAgentAllenhark,
|
||||
MevAgentRaiden,
|
||||
MevAgentZan,
|
||||
MevAgentTunneling,
|
||||
},
|
||||
),
|
||||
}
|
||||
@@ -2198,9 +2200,30 @@ func (set txBinaryEnumSet) id(value string) (uint16, error) {
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func (set txBinaryEnumSet) idOrFallback(value string, fallback string) (uint16, error) {
|
||||
if id, ok := set.ids[value]; ok {
|
||||
return id, nil
|
||||
}
|
||||
id, ok := set.ids[fallback]
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("unsupported %s fallback enum value %q for versioned tx binary", set.name, fallback)
|
||||
}
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func (set txBinaryEnumSet) value(id uint16) (string, error) {
|
||||
if int(id) >= len(set.values) {
|
||||
return "", fmt.Errorf("unknown %s enum id %d", set.name, id)
|
||||
}
|
||||
return set.values[id], nil
|
||||
}
|
||||
|
||||
func (set txBinaryEnumSet) valueOrFallback(id uint16, fallback string) (string, error) {
|
||||
if int(id) < len(set.values) {
|
||||
return set.values[id], nil
|
||||
}
|
||||
if _, ok := set.ids[fallback]; !ok {
|
||||
return "", fmt.Errorf("unsupported %s fallback enum value %q for versioned tx binary", set.name, fallback)
|
||||
}
|
||||
return fallback, nil
|
||||
}
|
||||
|
||||
@@ -41,6 +41,14 @@ func TestTxBinaryRoundTrip(t *testing.T) {
|
||||
MevAgent: MevAgentJito,
|
||||
MevAgentFee: decimal.RequireFromString("0.030000000"),
|
||||
},
|
||||
MevAgentZan: {
|
||||
MevAgent: MevAgentZan,
|
||||
MevAgentFee: decimal.RequireFromString("0.040000000"),
|
||||
},
|
||||
MevAgentTunneling: {
|
||||
MevAgent: MevAgentTunneling,
|
||||
MevAgentFee: decimal.RequireFromString("0.050000000"),
|
||||
},
|
||||
},
|
||||
Swaps: []Swap{
|
||||
{
|
||||
@@ -146,6 +154,12 @@ func TestTxBinaryRoundTrip(t *testing.T) {
|
||||
if !decoded.MevAgent[MevAgentJito].MevAgentFee.Equal(original.MevAgent[MevAgentJito].MevAgentFee) {
|
||||
t.Fatalf("MevAgent fee mismatch")
|
||||
}
|
||||
if !decoded.MevAgent[MevAgentZan].MevAgentFee.Equal(original.MevAgent[MevAgentZan].MevAgentFee) {
|
||||
t.Fatalf("Zan MevAgent fee mismatch")
|
||||
}
|
||||
if !decoded.MevAgent[MevAgentTunneling].MevAgentFee.Equal(original.MevAgent[MevAgentTunneling].MevAgentFee) {
|
||||
t.Fatalf("Tunneling MevAgent fee mismatch")
|
||||
}
|
||||
if len(decoded.Swaps) != 1 {
|
||||
t.Fatalf("Swaps len = %d, want 1", len(decoded.Swaps))
|
||||
}
|
||||
@@ -225,6 +239,87 @@ func TestTxBinaryRejectsUnknownProgramEnum(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTxBinaryLabelEnumsFallbackToUnknown(t *testing.T) {
|
||||
original := &Tx{
|
||||
Signer: solana.WrappedSol,
|
||||
Platform: map[string]platformInfo{
|
||||
"future-platform": {
|
||||
Platform: "future-platform",
|
||||
PlatformFee: decimal.RequireFromString("0.010000000"),
|
||||
},
|
||||
},
|
||||
MevAgent: map[string]mevInfo{
|
||||
"future-mev-agent": {
|
||||
MevAgent: "future-mev-agent",
|
||||
MevAgentFee: decimal.RequireFromString("0.020000000"),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
encoded, err := EncodeTxBinary(original)
|
||||
if err != nil {
|
||||
t.Fatalf("EncodeTxBinary() error = %v", err)
|
||||
}
|
||||
decoded, err := DecodeTxBinary(encoded)
|
||||
if err != nil {
|
||||
t.Fatalf("DecodeTxBinary() error = %v", err)
|
||||
}
|
||||
|
||||
if len(decoded.Platform) != 1 {
|
||||
t.Fatalf("Platform len = %d, want 1", len(decoded.Platform))
|
||||
}
|
||||
if _, exists := decoded.Platform["future-platform"]; exists {
|
||||
t.Fatalf("future platform was preserved, want fallback")
|
||||
}
|
||||
if !decoded.Platform[PlatformNone].PlatformFee.Equal(original.Platform["future-platform"].PlatformFee) {
|
||||
t.Fatalf("PlatformNone fee = %s, want %s", decoded.Platform[PlatformNone].PlatformFee, original.Platform["future-platform"].PlatformFee)
|
||||
}
|
||||
|
||||
if len(decoded.MevAgent) != 1 {
|
||||
t.Fatalf("MevAgent len = %d, want 1", len(decoded.MevAgent))
|
||||
}
|
||||
if _, exists := decoded.MevAgent["future-mev-agent"]; exists {
|
||||
t.Fatalf("future mev agent was preserved, want fallback")
|
||||
}
|
||||
if !decoded.MevAgent[MevAgentUnknown].MevAgentFee.Equal(original.MevAgent["future-mev-agent"].MevAgentFee) {
|
||||
t.Fatalf("MevAgentUnknown fee = %s, want %s", decoded.MevAgent[MevAgentUnknown].MevAgentFee, original.MevAgent["future-mev-agent"].MevAgentFee)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTxBinaryReadLabelEnumUnknownIDsFallback(t *testing.T) {
|
||||
enumTable := txBinaryEnumTables[txBinaryEnumVersionV1]
|
||||
|
||||
platformFee := uint64(123)
|
||||
platformEnc := txBinaryEncoder{}
|
||||
platformEnc.writeUint32(1)
|
||||
platformEnc.writeUint16(uint16(len(enumTable.platforms.values) + 10))
|
||||
platformEnc.writeUint64(platformFee)
|
||||
|
||||
platformDec := txBinaryDecoder{reader: bytes.NewReader(platformEnc.bytes())}
|
||||
platforms, err := txBinaryReadPlatformEntries(&platformDec, enumTable)
|
||||
if err != nil {
|
||||
t.Fatalf("txBinaryReadPlatformEntries() error = %v", err)
|
||||
}
|
||||
if len(platforms) != 1 || platforms[0].Platform != PlatformNone || platforms[0].PlatformFee != platformFee {
|
||||
t.Fatalf("platform fallback = %+v, want %s/%d", platforms, PlatformNone, platformFee)
|
||||
}
|
||||
|
||||
mevFee := uint64(456)
|
||||
mevEnc := txBinaryEncoder{}
|
||||
mevEnc.writeUint32(1)
|
||||
mevEnc.writeUint16(uint16(len(enumTable.mevAgents.values) + 10))
|
||||
mevEnc.writeUint64(mevFee)
|
||||
|
||||
mevDec := txBinaryDecoder{reader: bytes.NewReader(mevEnc.bytes())}
|
||||
mevAgents, err := txBinaryReadMevAgentEntries(&mevDec, enumTable)
|
||||
if err != nil {
|
||||
t.Fatalf("txBinaryReadMevAgentEntries() error = %v", err)
|
||||
}
|
||||
if len(mevAgents) != 1 || mevAgents[0].MevAgent != MevAgentUnknown || mevAgents[0].MevAgentFee != mevFee {
|
||||
t.Fatalf("mev agent fallback = %+v, want %s/%d", mevAgents, MevAgentUnknown, mevFee)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTxBinaryAcceptsKnownEventEnums(t *testing.T) {
|
||||
events := []string{
|
||||
TxEventAddLP,
|
||||
|
||||
Reference in New Issue
Block a user