@@ -23,6 +23,7 @@ import (
2323
2424 bin "github.com/gagliardetto/binary"
2525 "github.com/gagliardetto/treeout"
26+ jsoniter "github.com/json-iterator/go"
2627
2728 "github.com/gagliardetto/solana-go/text"
2829)
@@ -195,42 +196,69 @@ func (mx *Message) NumWritableLookups() int {
195196func (mx Message ) MarshalJSON () ([]byte , error ) {
196197 if mx .version == MessageVersionLegacy {
197198 out := struct {
198- AccountKeys [] string `json:"accountKeys"`
199+ AccountKeys PublicKeySlice `json:"accountKeys"`
199200 Header MessageHeader `json:"header"`
200- RecentBlockhash string `json:"recentBlockhash"`
201+ RecentBlockhash Hash `json:"recentBlockhash"`
201202 Instructions []CompiledInstruction `json:"instructions"`
202203 }{
203- AccountKeys : make ([] string , len ( mx .AccountKeys )) ,
204+ AccountKeys : mx .AccountKeys ,
204205 Header : mx .Header ,
205- RecentBlockhash : mx .RecentBlockhash . String () ,
206+ RecentBlockhash : mx .RecentBlockhash ,
206207 Instructions : mx .Instructions ,
207208 }
208- for i , key := range mx .AccountKeys {
209- out .AccountKeys [i ] = key .String ()
210- }
211209 return json .Marshal (out )
212210 }
213211 // Versioned message:
212+ lookups := mx .AddressTableLookups
213+ if lookups == nil {
214+ lookups = MessageAddressTableLookupSlice {}
215+ }
214216 out := struct {
215- AccountKeys [] string `json:"accountKeys"`
216- Header MessageHeader `json:"header"`
217- RecentBlockhash string `json:"recentBlockhash"`
218- Instructions []CompiledInstruction `json:"instructions"`
219- AddressTableLookups [] MessageAddressTableLookup `json:"addressTableLookups"`
217+ AccountKeys PublicKeySlice `json:"accountKeys"`
218+ Header MessageHeader `json:"header"`
219+ RecentBlockhash Hash `json:"recentBlockhash"`
220+ Instructions []CompiledInstruction `json:"instructions"`
221+ AddressTableLookups MessageAddressTableLookupSlice `json:"addressTableLookups"`
220222 }{
221- AccountKeys : make ([] string , len ( mx .AccountKeys )) ,
223+ AccountKeys : mx .AccountKeys ,
222224 Header : mx .Header ,
223- RecentBlockhash : mx .RecentBlockhash . String () ,
225+ RecentBlockhash : mx .RecentBlockhash ,
224226 Instructions : mx .Instructions ,
225- AddressTableLookups : mx . AddressTableLookups ,
227+ AddressTableLookups : lookups ,
226228 }
227- for i , key := range mx .AccountKeys {
228- out .AccountKeys [i ] = key .String ()
229+ return json .Marshal (out )
230+ }
231+
232+ // UnmarshalJSON decodes the message from JSON and determines its version.
233+ // The Solana RPC emits `addressTableLookups` only for versioned (V0+)
234+ // messages; its presence in the JSON is what distinguishes V0 from legacy,
235+ // since the private `version` field has no wire representation.
236+ func (mx * Message ) UnmarshalJSON (data []byte ) error {
237+ // Decode `addressTableLookups` via a RawMessage pointer so presence of the
238+ // key can be detected in a single parse. A non-nil pointer means the key
239+ // was present in the JSON (even if its value is `null`), which selects V0.
240+ aux := struct {
241+ AccountKeys PublicKeySlice `json:"accountKeys"`
242+ Header MessageHeader `json:"header"`
243+ RecentBlockhash Hash `json:"recentBlockhash"`
244+ Instructions []CompiledInstruction `json:"instructions"`
245+ AddressTableLookups * jsoniter.RawMessage `json:"addressTableLookups"`
246+ }{}
247+ if err := json .Unmarshal (data , & aux ); err != nil {
248+ return err
229249 }
230- if out .AddressTableLookups == nil {
231- out .AddressTableLookups = make ([]MessageAddressTableLookup , 0 )
250+ mx .AccountKeys = aux .AccountKeys
251+ mx .Header = aux .Header
252+ mx .RecentBlockhash = aux .RecentBlockhash
253+ mx .Instructions = aux .Instructions
254+
255+ if aux .AddressTableLookups == nil {
256+ mx .version = MessageVersionLegacy
257+ mx .AddressTableLookups = nil
258+ return nil
232259 }
233- return json .Marshal (out )
260+ mx .version = MessageVersionV0
261+ return json .Unmarshal (* aux .AddressTableLookups , & mx .AddressTableLookups )
234262}
235263
236264func (mx * Message ) EncodeToTree (txTree treeout.Branches ) {
0 commit comments