@@ -10,6 +10,9 @@ import {
1010 isAnchorIdlV01 ,
1111 getInstructionDiscriminatorBytes ,
1212 findInstructionDiscriminatorByName ,
13+ getDiscriminator ,
14+ isRootNode ,
15+ isAnchorIdl ,
1316} from '@subql/common-solana' ;
1417import { getLogger } from '@subql/node-core' ;
1518import {
@@ -21,7 +24,14 @@ import {
2124} from '@subql/types-solana' ;
2225import { isHex } from '@subql/utils' ;
2326import bs58 from 'bs58' ;
24- import { camelCase , DefinedTypeNode , InstructionNode , RootNode } from 'codama' ;
27+ import {
28+ camelCase ,
29+ DefinedTypeNode ,
30+ InstructionNode ,
31+ pascalCase ,
32+ RootNode ,
33+ titleCase ,
34+ } from 'codama' ;
2535import { Memoize } from '../utils/decorators' ;
2636import { allAccounts , getProgramId } from './utils.solana' ;
2737
@@ -99,14 +109,36 @@ export function decodeInstruction(
99109
100110// Codama doesn't support Logs so extra work is required to decode logs
101111export function decodeLog ( idl : Idl , message : string ) : DecodedData | null {
112+ const msgData = message . replace ( 'Program data: ' , '' ) ;
113+ const msgBuffer = basedToBuffer ( msgData ) ;
114+
115+ // Codama IDL, doesn't include events in the IDL but it should decoded to a definedType in the IDL
116+ if ( ! isAnchorIdl ( idl ) ) {
117+ if ( msgBuffer . length < 8 ) {
118+ // Not enough data for a discriminator
119+ return null ;
120+ }
121+
122+ // Split the discriminator and data
123+ const logDisc = msgBuffer . subarray ( 0 , 8 ) ;
124+ const data = msgBuffer . subarray ( 8 ) ;
125+
126+ // Attempt to find the matching type by discriminator and decode the data
127+ return decodeData ( idl , data . toString ( 'base64' ) , ( root ) => {
128+ return root . program . definedTypes . find (
129+ ( t ) =>
130+ // Warning this is fragile as there can be various casings of the type names, but because it requires hashing data we can only go one way
131+ logDisc . indexOf ( getDiscriminator ( t . name ) ) === 0 ||
132+ logDisc . indexOf ( getDiscriminator ( pascalCase ( t . name ) ) ) === 0 ,
133+ ) ;
134+ } ) ;
135+ }
136+
102137 // Older versions don't support events
103138 if ( ! isAnchorIdlV01 ( idl ) ) {
104139 throw new Error ( 'Only Anchor IDL v0.1.0 is supported for decoding logs' ) ;
105140 }
106141
107- const msgData = message . replace ( 'Program data: ' , '' ) as any ;
108- const msgBuffer = basedToBuffer ( msgData ) ;
109-
110142 // Codama doesn't include events so we have to find it manually
111143 const event = idl . events ?. find (
112144 ( e ) => msgBuffer . indexOf ( Buffer . from ( e . discriminator ) ) === 0 ,
@@ -121,7 +153,7 @@ export function decodeLog(idl: Idl, message: string): DecodedData | null {
121153 . subarray ( event . discriminator . length )
122154 . toString ( 'base64' ) ;
123155
124- return decodeData ( idl , input as any , ( root , data ) => {
156+ return decodeData ( idl , input , ( root ) => {
125157 return root . program . definedTypes . find (
126158 ( t ) => t . name === event . name || t . name === camelCase ( event . name ) ,
127159 ) ;
0 commit comments