@subql/node-solana 6.1.2 → 6.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/solana/decoder.js
CHANGED
|
@@ -76,12 +76,29 @@ function decodeInstruction(idl, data) {
|
|
|
76
76
|
}
|
|
77
77
|
// Codama doesn't support Logs so extra work is required to decode logs
|
|
78
78
|
function decodeLog(idl, message) {
|
|
79
|
+
const msgData = message.replace('Program data: ', '');
|
|
80
|
+
const msgBuffer = basedToBuffer(msgData);
|
|
81
|
+
// Codama IDL, doesn't include events in the IDL but it should decoded to a definedType in the IDL
|
|
82
|
+
if (!(0, common_solana_1.isAnchorIdl)(idl)) {
|
|
83
|
+
if (msgBuffer.length < 8) {
|
|
84
|
+
// Not enough data for a discriminator
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
// Split the discriminator and data
|
|
88
|
+
const logDisc = msgBuffer.subarray(0, 8);
|
|
89
|
+
const data = msgBuffer.subarray(8);
|
|
90
|
+
// Attempt to find the matching type by discriminator and decode the data
|
|
91
|
+
return decodeData(idl, data.toString('base64'), (root) => {
|
|
92
|
+
return root.program.definedTypes.find((t) =>
|
|
93
|
+
// 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
|
|
94
|
+
logDisc.indexOf((0, common_solana_1.getDiscriminator)(t.name)) === 0 ||
|
|
95
|
+
logDisc.indexOf((0, common_solana_1.getDiscriminator)((0, codama_1.pascalCase)(t.name))) === 0);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
79
98
|
// Older versions don't support events
|
|
80
99
|
if (!(0, common_solana_1.isAnchorIdlV01)(idl)) {
|
|
81
100
|
throw new Error('Only Anchor IDL v0.1.0 is supported for decoding logs');
|
|
82
101
|
}
|
|
83
|
-
const msgData = message.replace('Program data: ', '');
|
|
84
|
-
const msgBuffer = basedToBuffer(msgData);
|
|
85
102
|
// Codama doesn't include events so we have to find it manually
|
|
86
103
|
const event = idl.events?.find((e) => msgBuffer.indexOf(Buffer.from(e.discriminator)) === 0);
|
|
87
104
|
if (!event) {
|
|
@@ -91,7 +108,7 @@ function decodeLog(idl, message) {
|
|
|
91
108
|
const input = msgBuffer
|
|
92
109
|
.subarray(event.discriminator.length)
|
|
93
110
|
.toString('base64');
|
|
94
|
-
return decodeData(idl, input, (root
|
|
111
|
+
return decodeData(idl, input, (root) => {
|
|
95
112
|
return root.program.definedTypes.find((t) => t.name === event.name || t.name === (0, codama_1.camelCase)(event.name));
|
|
96
113
|
});
|
|
97
114
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decoder.js","sourceRoot":"","sources":["../../src/solana/decoder.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport fs from 'node:fs';\nimport { getNodeCodec } from '@codama/dynamic-codecs';\nimport { Base58EncodedBytes, TransactionForFullJson } from '@solana/kit';\nimport {\n parseIdl,\n Idl,\n isAnchorIdlV01,\n getInstructionDiscriminatorBytes,\n findInstructionDiscriminatorByName,\n} from '@subql/common-solana';\nimport { getLogger } from '@subql/node-core';\nimport {\n DecodedData,\n Decoder,\n SolanaInstruction,\n SolanaLogMessage,\n SubqlDatasource,\n} from '@subql/types-solana';\nimport { isHex } from '@subql/utils';\nimport bs58 from 'bs58';\nimport { camelCase, DefinedTypeNode, InstructionNode, RootNode } from 'codama';\nimport { Memoize } from '../utils/decorators';\nimport { allAccounts, getProgramId } from './utils.solana';\n\nconst logger = getLogger('SolanaDecoder');\n\nfunction findInstructionForData(\n rootNode: RootNode,\n data: Buffer,\n): InstructionNode | undefined {\n return rootNode.program.instructions.find((inst) => {\n try {\n const bytes = getInstructionDiscriminatorBytes(inst);\n return data.indexOf(bytes) === 0;\n } catch (e) {\n logger.debug(\n `Failed to get discriminator for instruction ${inst.name}: ${e}`,\n );\n return false;\n }\n });\n}\n\n// Converts a base58 or base64 string to Buffer\nfunction basedToBuffer(input: string | Base58EncodedBytes): Buffer {\n try {\n return Buffer.from(bs58.decode(input));\n } catch (e) {\n return Buffer.from(input, 'base64');\n }\n}\n\nfunction decodeData(\n idl: Idl,\n data: Base58EncodedBytes | string,\n getEncodableNode: (\n rootNode: RootNode,\n data: Buffer,\n ) => InstructionNode | DefinedTypeNode | undefined,\n): DecodedData | null {\n const root = parseIdl(idl).getRoot();\n\n const buffer = basedToBuffer(data);\n\n const node = getEncodableNode(root, buffer);\n if (!node) {\n logger.warn(\n `Failed to find instruction with discriminator in ${root.program.name}`,\n );\n return null;\n }\n\n try {\n // Path is required to find other defined structs\n const codec = getNodeCodec([root, root.program, node as any]);\n\n // Strip the discriminator\n const { discriminator, ...decoded } = codec.decode(buffer) as any;\n\n return {\n data: decoded,\n name: node.name,\n };\n } catch (e) {\n logger.warn(`Failed to decode data name: ${node.name}, error: ${e}`);\n return null;\n }\n}\n\nexport function decodeInstruction(\n idl: Idl,\n data: Base58EncodedBytes,\n): DecodedData | null {\n return decodeData(idl, data, findInstructionForData);\n}\n\n// Codama doesn't support Logs so extra work is required to decode logs\nexport function decodeLog(idl: Idl, message: string): DecodedData | null {\n // Older versions don't support events\n if (!isAnchorIdlV01(idl)) {\n throw new Error('Only Anchor IDL v0.1.0 is supported for decoding logs');\n }\n\n const msgData = message.replace('Program data: ', '') as any;\n const msgBuffer = basedToBuffer(msgData);\n\n // Codama doesn't include events so we have to find it manually\n const event = idl.events?.find(\n (e) => msgBuffer.indexOf(Buffer.from(e.discriminator)) === 0,\n );\n\n if (!event) {\n throw new Error('Unable to find event for log data');\n }\n\n // Input needs to be without the discriminator because we're just going to decode a type\n const input = msgBuffer\n .subarray(event.discriminator.length)\n .toString('base64');\n\n return decodeData(idl, input as any, (root, data) => {\n return root.program.definedTypes.find(\n (t) => t.name === event.name || t.name === camelCase(event.name),\n );\n });\n}\n\nexport class SolanaDecoder {\n idls: Record<string, Idl | null> = {};\n\n async loadIdls(ds: SubqlDatasource): Promise<void> {\n if (!ds.assets) {\n return;\n }\n\n for (const [name, { file }] of ds.assets.entries()) {\n try {\n if (this.idls[name]) {\n continue;\n }\n const raw = await fs.promises.readFile(file, { encoding: 'utf8' });\n this.idls[name] = JSON.parse(raw);\n logger.info(`Loaded IDL for ${name}`);\n } catch (e) {\n throw new Error(`Failed to load datasource IDL ${name}:${file}`);\n }\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/require-await\n async getIdlFromChain(programId: string): Promise<Idl | null> {\n throw new Error('Not implemented: getIdlFromChain');\n // this.idls[programId] ??= await Program.fetchIdl(programId, {\n // connection: this.api as any,\n // });\n\n // return this.idls[programId];\n }\n\n @Memoize()\n parseDiscriminator(input: string, programId: string): Buffer {\n if (isHex(input)) {\n return Buffer.from(input.replace('0x', ''), 'hex');\n }\n\n const idl = this.idls[programId];\n if (!idl) {\n throw new Error(`Unable to find IDL for program ${programId}`);\n }\n\n const root = parseIdl(idl).getRoot();\n\n const discriminator = findInstructionDiscriminatorByName(root, input);\n if (!discriminator) {\n return Buffer.from(bs58.decode(input));\n }\n\n return discriminator;\n }\n\n async decodeInstructionRaw(\n instruction: TransactionForFullJson<0>['transaction']['message']['instructions'][number],\n transaction: TransactionForFullJson<0>,\n ): Promise<DecodedData | null> {\n try {\n const programId = allAccounts(transaction)[instruction.programIdIndex];\n\n const idl =\n this.idls[programId] ?? (await this.getIdlFromChain(programId));\n\n if (!idl) {\n logger.warn(\n `Unable to decode instruction for program: ${programId}. No IDL.`,\n );\n return null;\n }\n\n return decodeInstruction(idl, instruction.data);\n } catch (e) {\n logger.warn(`Failed to decode instruction: ${e}`);\n }\n\n return null;\n }\n\n async decodeInstruction(\n instruction: SolanaInstruction,\n ): Promise<DecodedData | null> {\n return this.decodeInstructionRaw(instruction, instruction.transaction);\n }\n\n async decodeLog(log: SolanaLogMessage): Promise<DecodedData | null> {\n try {\n const programId = log.programId;\n\n const idl =\n this.idls[programId] ?? (await this.getIdlFromChain(programId));\n\n if (!idl) {\n logger.warn(`Unable to decode log for program: ${programId}. No IDL.`);\n return null;\n }\n\n return decodeLog(idl, log.message);\n } catch (e) {\n logger.warn(`Failed to decode log: ${e}`);\n }\n return null;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"decoder.js","sourceRoot":"","sources":["../../src/solana/decoder.ts"],"names":[],"mappings":";AAAA,8DAA8D;AAC9D,mCAAmC;;;;;;;;;;;;;;;AAqGnC,8CAKC;AAGD,8BAkDC;AA7JD,sDAAyB;AACzB,2DAAsD;AAEtD,wDAS8B;AAC9B,gDAA6C;AAQ7C,wCAAqC;AACrC,gDAAwB;AACxB,mCAOgB;AAChB,oDAA8C;AAC9C,iDAA2D;AAE3D,MAAM,MAAM,GAAG,IAAA,qBAAS,EAAC,eAAe,CAAC,CAAC;AAE1C,SAAS,sBAAsB,CAC7B,QAAkB,EAClB,IAAY;IAEZ,OAAO,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;QACjD,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,IAAA,gDAAgC,EAAC,IAAI,CAAC,CAAC;YACrD,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,CAAC,KAAK,CACV,+CAA+C,IAAI,CAAC,IAAI,KAAK,CAAC,EAAE,CACjE,CAAC;YACF,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,+CAA+C;AAC/C,SAAS,aAAa,CAAC,KAAkC;IACvD,IAAI,CAAC;QACH,OAAO,MAAM,CAAC,IAAI,CAAC,cAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACzC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACtC,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CACjB,GAAQ,EACR,IAAiC,EACjC,gBAGkD;IAElD,MAAM,IAAI,GAAG,IAAA,wBAAQ,EAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;IAErC,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IAEnC,MAAM,IAAI,GAAG,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC5C,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,CAAC,IAAI,CACT,oDAAoD,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CACxE,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,iDAAiD;QACjD,MAAM,KAAK,GAAG,IAAA,6BAAY,EAAC,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,IAAW,CAAC,CAAC,CAAC;QAE9D,0BAA0B;QAC1B,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAQ,CAAC;QAElE,OAAO;YACL,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,IAAI,CAAC,IAAI;SAChB,CAAC;IACJ,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,CAAC,IAAI,CAAC,+BAA+B,IAAI,CAAC,IAAI,YAAY,CAAC,EAAE,CAAC,CAAC;QACrE,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAgB,iBAAiB,CAC/B,GAAQ,EACR,IAAwB;IAExB,OAAO,UAAU,CAAC,GAAG,EAAE,IAAI,EAAE,sBAAsB,CAAC,CAAC;AACvD,CAAC;AAED,uEAAuE;AACvE,SAAgB,SAAS,CAAC,GAAQ,EAAE,OAAe;IACjD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC;IACtD,MAAM,SAAS,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IAEzC,kGAAkG;IAClG,IAAI,CAAC,IAAA,2BAAW,EAAC,GAAG,CAAC,EAAE,CAAC;QACtB,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzB,sCAAsC;YACtC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,mCAAmC;QACnC,MAAM,OAAO,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACzC,MAAM,IAAI,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAEnC,yEAAyE;QACzE,OAAO,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE;YACvD,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,CACnC,CAAC,CAAC,EAAE,EAAE;YACJ,yIAAyI;YACzI,OAAO,CAAC,OAAO,CAAC,IAAA,gCAAgB,EAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC;gBAC/C,OAAO,CAAC,OAAO,CAAC,IAAA,gCAAgB,EAAC,IAAA,mBAAU,EAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAC9D,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAED,sCAAsC;IACtC,IAAI,CAAC,IAAA,8BAAc,EAAC,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;IAC3E,CAAC;IAED,+DAA+D;IAC/D,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,EAAE,IAAI,CAC5B,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,KAAK,CAAC,CAC7D,CAAC;IAEF,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACvD,CAAC;IAED,wFAAwF;IACxF,MAAM,KAAK,GAAG,SAAS;SACpB,QAAQ,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC;SACpC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAEtB,OAAO,UAAU,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE;QACrC,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,CACnC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,KAAK,IAAA,kBAAS,EAAC,KAAK,CAAC,IAAI,CAAC,CACjE,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAa,aAAa;IACxB,IAAI,GAA+B,EAAE,CAAC;IAEtC,KAAK,CAAC,QAAQ,CAAC,EAAmB;QAChC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC;YACf,OAAO;QACT,CAAC;QAED,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC;YACnD,IAAI,CAAC;gBACH,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;oBACpB,SAAS;gBACX,CAAC;gBACD,MAAM,GAAG,GAAG,MAAM,iBAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;gBACnE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAClC,MAAM,CAAC,IAAI,CAAC,kBAAkB,IAAI,EAAE,CAAC,CAAC;YACxC,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,MAAM,IAAI,KAAK,CAAC,iCAAiC,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC;YACnE,CAAC;QACH,CAAC;IACH,CAAC;IAED,4DAA4D;IAC5D,KAAK,CAAC,eAAe,CAAC,SAAiB;QACrC,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACpD,+DAA+D;QAC/D,iCAAiC;QACjC,MAAM;QAEN,+BAA+B;IACjC,CAAC;IAGD,kBAAkB,CAAC,KAAa,EAAE,SAAiB;QACjD,IAAI,IAAA,aAAK,EAAC,KAAK,CAAC,EAAE,CAAC;YACjB,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;QACrD,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACjC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,KAAK,CAAC,kCAAkC,SAAS,EAAE,CAAC,CAAC;QACjE,CAAC;QAED,MAAM,IAAI,GAAG,IAAA,wBAAQ,EAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;QAErC,MAAM,aAAa,GAAG,IAAA,kDAAkC,EAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACtE,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,OAAO,MAAM,CAAC,IAAI,CAAC,cAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACzC,CAAC;QAED,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,oBAAoB,CACxB,WAAwF,EACxF,WAAsC;QAEtC,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,IAAA,0BAAW,EAAC,WAAW,CAAC,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;YAEvE,MAAM,GAAG,GACP,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,CAAC;YAElE,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,MAAM,CAAC,IAAI,CACT,6CAA6C,SAAS,WAAW,CAClE,CAAC;gBACF,OAAO,IAAI,CAAC;YACd,CAAC;YAED,OAAO,iBAAiB,CAAC,GAAG,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC;QAClD,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,CAAC,IAAI,CAAC,iCAAiC,CAAC,EAAE,CAAC,CAAC;QACpD,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,iBAAiB,CACrB,WAA8B;QAE9B,OAAO,IAAI,CAAC,oBAAoB,CAAC,WAAW,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC;IACzE,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,GAAqB;QACnC,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,CAAC;YAEhC,MAAM,GAAG,GACP,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,CAAC;YAElE,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,MAAM,CAAC,IAAI,CAAC,qCAAqC,SAAS,WAAW,CAAC,CAAC;gBACvE,OAAO,IAAI,CAAC;YACd,CAAC;YAED,OAAO,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QACrC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,CAAC,IAAI,CAAC,yBAAyB,CAAC,EAAE,CAAC,CAAC;QAC5C,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAtGD,sCAsGC;AArEC;IADC,IAAA,oBAAO,GAAE;;;oCAC4C,MAAM;uDAkB3D","sourcesContent":["// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport fs from 'node:fs';\nimport { getNodeCodec } from '@codama/dynamic-codecs';\nimport { Base58EncodedBytes, TransactionForFullJson } from '@solana/kit';\nimport {\n parseIdl,\n Idl,\n isAnchorIdlV01,\n getInstructionDiscriminatorBytes,\n findInstructionDiscriminatorByName,\n getDiscriminator,\n isRootNode,\n isAnchorIdl,\n} from '@subql/common-solana';\nimport { getLogger } from '@subql/node-core';\nimport {\n DecodedData,\n Decoder,\n SolanaInstruction,\n SolanaLogMessage,\n SubqlDatasource,\n} from '@subql/types-solana';\nimport { isHex } from '@subql/utils';\nimport bs58 from 'bs58';\nimport {\n camelCase,\n DefinedTypeNode,\n InstructionNode,\n pascalCase,\n RootNode,\n titleCase,\n} from 'codama';\nimport { Memoize } from '../utils/decorators';\nimport { allAccounts, getProgramId } from './utils.solana';\n\nconst logger = getLogger('SolanaDecoder');\n\nfunction findInstructionForData(\n rootNode: RootNode,\n data: Buffer,\n): InstructionNode | undefined {\n return rootNode.program.instructions.find((inst) => {\n try {\n const bytes = getInstructionDiscriminatorBytes(inst);\n return data.indexOf(bytes) === 0;\n } catch (e) {\n logger.debug(\n `Failed to get discriminator for instruction ${inst.name}: ${e}`,\n );\n return false;\n }\n });\n}\n\n// Converts a base58 or base64 string to Buffer\nfunction basedToBuffer(input: string | Base58EncodedBytes): Buffer {\n try {\n return Buffer.from(bs58.decode(input));\n } catch (e) {\n return Buffer.from(input, 'base64');\n }\n}\n\nfunction decodeData(\n idl: Idl,\n data: Base58EncodedBytes | string,\n getEncodableNode: (\n rootNode: RootNode,\n data: Buffer,\n ) => InstructionNode | DefinedTypeNode | undefined,\n): DecodedData | null {\n const root = parseIdl(idl).getRoot();\n\n const buffer = basedToBuffer(data);\n\n const node = getEncodableNode(root, buffer);\n if (!node) {\n logger.warn(\n `Failed to find instruction with discriminator in ${root.program.name}`,\n );\n return null;\n }\n\n try {\n // Path is required to find other defined structs\n const codec = getNodeCodec([root, root.program, node as any]);\n\n // Strip the discriminator\n const { discriminator, ...decoded } = codec.decode(buffer) as any;\n\n return {\n data: decoded,\n name: node.name,\n };\n } catch (e) {\n logger.warn(`Failed to decode data name: ${node.name}, error: ${e}`);\n return null;\n }\n}\n\nexport function decodeInstruction(\n idl: Idl,\n data: Base58EncodedBytes,\n): DecodedData | null {\n return decodeData(idl, data, findInstructionForData);\n}\n\n// Codama doesn't support Logs so extra work is required to decode logs\nexport function decodeLog(idl: Idl, message: string): DecodedData | null {\n const msgData = message.replace('Program data: ', '');\n const msgBuffer = basedToBuffer(msgData);\n\n // Codama IDL, doesn't include events in the IDL but it should decoded to a definedType in the IDL\n if (!isAnchorIdl(idl)) {\n if (msgBuffer.length < 8) {\n // Not enough data for a discriminator\n return null;\n }\n\n // Split the discriminator and data\n const logDisc = msgBuffer.subarray(0, 8);\n const data = msgBuffer.subarray(8);\n\n // Attempt to find the matching type by discriminator and decode the data\n return decodeData(idl, data.toString('base64'), (root) => {\n return root.program.definedTypes.find(\n (t) =>\n // 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\n logDisc.indexOf(getDiscriminator(t.name)) === 0 ||\n logDisc.indexOf(getDiscriminator(pascalCase(t.name))) === 0,\n );\n });\n }\n\n // Older versions don't support events\n if (!isAnchorIdlV01(idl)) {\n throw new Error('Only Anchor IDL v0.1.0 is supported for decoding logs');\n }\n\n // Codama doesn't include events so we have to find it manually\n const event = idl.events?.find(\n (e) => msgBuffer.indexOf(Buffer.from(e.discriminator)) === 0,\n );\n\n if (!event) {\n throw new Error('Unable to find event for log data');\n }\n\n // Input needs to be without the discriminator because we're just going to decode a type\n const input = msgBuffer\n .subarray(event.discriminator.length)\n .toString('base64');\n\n return decodeData(idl, input, (root) => {\n return root.program.definedTypes.find(\n (t) => t.name === event.name || t.name === camelCase(event.name),\n );\n });\n}\n\nexport class SolanaDecoder {\n idls: Record<string, Idl | null> = {};\n\n async loadIdls(ds: SubqlDatasource): Promise<void> {\n if (!ds.assets) {\n return;\n }\n\n for (const [name, { file }] of ds.assets.entries()) {\n try {\n if (this.idls[name]) {\n continue;\n }\n const raw = await fs.promises.readFile(file, { encoding: 'utf8' });\n this.idls[name] = JSON.parse(raw);\n logger.info(`Loaded IDL for ${name}`);\n } catch (e) {\n throw new Error(`Failed to load datasource IDL ${name}:${file}`);\n }\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/require-await\n async getIdlFromChain(programId: string): Promise<Idl | null> {\n throw new Error('Not implemented: getIdlFromChain');\n // this.idls[programId] ??= await Program.fetchIdl(programId, {\n // connection: this.api as any,\n // });\n\n // return this.idls[programId];\n }\n\n @Memoize()\n parseDiscriminator(input: string, programId: string): Buffer {\n if (isHex(input)) {\n return Buffer.from(input.replace('0x', ''), 'hex');\n }\n\n const idl = this.idls[programId];\n if (!idl) {\n throw new Error(`Unable to find IDL for program ${programId}`);\n }\n\n const root = parseIdl(idl).getRoot();\n\n const discriminator = findInstructionDiscriminatorByName(root, input);\n if (!discriminator) {\n return Buffer.from(bs58.decode(input));\n }\n\n return discriminator;\n }\n\n async decodeInstructionRaw(\n instruction: TransactionForFullJson<0>['transaction']['message']['instructions'][number],\n transaction: TransactionForFullJson<0>,\n ): Promise<DecodedData | null> {\n try {\n const programId = allAccounts(transaction)[instruction.programIdIndex];\n\n const idl =\n this.idls[programId] ?? (await this.getIdlFromChain(programId));\n\n if (!idl) {\n logger.warn(\n `Unable to decode instruction for program: ${programId}. No IDL.`,\n );\n return null;\n }\n\n return decodeInstruction(idl, instruction.data);\n } catch (e) {\n logger.warn(`Failed to decode instruction: ${e}`);\n }\n\n return null;\n }\n\n async decodeInstruction(\n instruction: SolanaInstruction,\n ): Promise<DecodedData | null> {\n return this.decodeInstructionRaw(instruction, instruction.transaction);\n }\n\n async decodeLog(log: SolanaLogMessage): Promise<DecodedData | null> {\n try {\n const programId = log.programId;\n\n const idl =\n this.idls[programId] ?? (await this.getIdlFromChain(programId));\n\n if (!idl) {\n logger.warn(`Unable to decode log for program: ${programId}. No IDL.`);\n return null;\n }\n\n return decodeLog(idl, log.message);\n } catch (e) {\n logger.warn(`Failed to decode log: ${e}`);\n }\n return null;\n }\n}\n"]}
|
|
@@ -10,7 +10,10 @@ const bs58_1 = __importDefault(require("bs58"));
|
|
|
10
10
|
const api_solana_1 = require("./api.solana");
|
|
11
11
|
const decoder_1 = require("./decoder");
|
|
12
12
|
const utils_solana_1 = require("./utils.solana");
|
|
13
|
-
const HTTP_ENDPOINT = process.env.HTTP_ENDPOINT ??
|
|
13
|
+
const HTTP_ENDPOINT = process.env.HTTP_ENDPOINT ??
|
|
14
|
+
'https://api.mainnet-beta.solana.com' ??
|
|
15
|
+
'https://solana.api.onfinality.io/public';
|
|
16
|
+
const IDL_codama_0_1_0 = require('../../test/8t2R21V3vjS1ucZzmX2memtGptjYZi2yGY3cYVa8dak7.idl.json');
|
|
14
17
|
const IDL_Jupiter = require('../../test/JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4.idl.json');
|
|
15
18
|
const IDL_swap = require('../../test/swapFpHZwjELNnjvThjajtiVmkz3yPQEHjLtka2fwHW.idl.json');
|
|
16
19
|
const IDL_token = require('../../test/TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA.idl.json');
|
|
@@ -32,6 +35,9 @@ describe('SolanaDecoder', () => {
|
|
|
32
35
|
decoder.idls['swapFpHZwjELNnjvThjajtiVmkz3yPQEHjLtka2fwHW'] = IDL_swap;
|
|
33
36
|
// eslint-disable-next-line @typescript-eslint/dot-notation
|
|
34
37
|
decoder.idls['TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'] = IDL_token;
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/dot-notation
|
|
39
|
+
decoder.idls['8t2R21V3vjS1ucZzmX2memtGptjYZi2yGY3cYVa8dak7'] =
|
|
40
|
+
IDL_codama_0_1_0;
|
|
35
41
|
};
|
|
36
42
|
describe('caching IDLs', () => {
|
|
37
43
|
// Fetching IDLs from the network is not currently supported
|
|
@@ -171,6 +177,30 @@ describe('SolanaDecoder', () => {
|
|
|
171
177
|
expect(decoded.name).toBe('poolBalanceUpdatedEvent');
|
|
172
178
|
expect(decoded.data).toEqual(logData);
|
|
173
179
|
});
|
|
180
|
+
it('can decode codama 0.1.0 spec idl events', async () => {
|
|
181
|
+
const solanaApi = await api_solana_1.SolanaApi.create('https://api.devnet.solana.com', new event_emitter_1.EventEmitter2(), decoder);
|
|
182
|
+
const block = await solanaApi.fetchBlock(405402294);
|
|
183
|
+
const tx = findTx(block.block, '4xHLJtomvuF2DAwtDoHgGqABv47kmqMCvd691bRe9XhiAP99grjvpAdvNQGnA4PETZSvhXdfHvvHUNWu2SNM3aqE');
|
|
184
|
+
expect(tx).toBeDefined();
|
|
185
|
+
const programLogs = tx.meta.logs?.filter((l) => l.message.startsWith('Program data:'));
|
|
186
|
+
expect(programLogs).toBeDefined();
|
|
187
|
+
const decoded = await programLogs[0].decodedMessage;
|
|
188
|
+
expect(decoded).not.toBeNull();
|
|
189
|
+
expect(decoded.name).toEqual('createCampaign');
|
|
190
|
+
expect(decoded.data).toMatchObject({
|
|
191
|
+
aggregateAmount: 10000n,
|
|
192
|
+
campaign: 'BjYpCVaiksvD8Dw4LixUJVNaCptefKk86nDtw419b7Y5',
|
|
193
|
+
campaignName: 'HODL or Nothing',
|
|
194
|
+
campaignStartTime: 1754142441n,
|
|
195
|
+
creator: 'HTtnrJ5iq9HVVypJZxFKMCcR6JDiUqT6yaE7c6BvfeTp',
|
|
196
|
+
expirationTime: 1757776469n,
|
|
197
|
+
ipfsCid: 'bafkreiecpwdhvkmw4y6iihfndk7jhwjas3m5htm7nczovt6m37mucwgsrq',
|
|
198
|
+
merkleRoot: ['base64', '1SVJywcqH80FJBL8gPZ47/6Sru7czRyuYyxcbh3ok3k='],
|
|
199
|
+
recipientCount: 100,
|
|
200
|
+
tokenDecimals: 6,
|
|
201
|
+
tokenMint: '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU',
|
|
202
|
+
});
|
|
203
|
+
});
|
|
174
204
|
});
|
|
175
205
|
});
|
|
176
206
|
//# sourceMappingURL=decoder.spec.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decoder.spec.js","sourceRoot":"","sources":["../../src/solana/decoder.spec.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { IdlV01 } from '@codama/nodes-from-anchor';\nimport { EventEmitter2 } from '@nestjs/event-emitter';\nimport { SolanaBlock, SolanaTransaction } from '@subql/types-solana';\nimport bs58 from 'bs58';\nimport { RootNode } from 'codama';\nimport { SolanaApi } from './api.solana';\nimport { SolanaDecoder } from './decoder';\nimport { getProgramId, filterInstructionsProcessor } from './utils.solana';\n\nconst HTTP_ENDPOINT =\n process.env.HTTP_ENDPOINT ?? 'https://solana.api.onfinality.io/public';\n\nconst IDL_Jupiter: IdlV01 = require('../../test/JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4.idl.json');\nconst IDL_swap: IdlV01 = require('../../test/swapFpHZwjELNnjvThjajtiVmkz3yPQEHjLtka2fwHW.idl.json');\nconst IDL_token: RootNode = require('../../test/TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA.idl.json');\n\nfunction findTx(\n block: SolanaBlock,\n sig: string,\n): SolanaTransaction | undefined {\n return block.transactions.find((tx) =>\n tx.transaction.signatures.find((s) => s === sig),\n );\n}\n\ndescribe('SolanaDecoder', () => {\n let solanaApi: SolanaApi;\n let decoder: SolanaDecoder;\n let blockData: SolanaBlock;\n\n beforeAll(async () => {\n decoder = new SolanaDecoder();\n solanaApi = await SolanaApi.create(\n HTTP_ENDPOINT,\n new EventEmitter2(),\n decoder,\n );\n });\n\n const loadDecoderIdls = () => {\n // eslint-disable-next-line @typescript-eslint/dot-notation\n decoder.idls['JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4'] = IDL_Jupiter;\n // eslint-disable-next-line @typescript-eslint/dot-notation\n decoder.idls['swapFpHZwjELNnjvThjajtiVmkz3yPQEHjLtka2fwHW'] = IDL_swap;\n // eslint-disable-next-line @typescript-eslint/dot-notation\n decoder.idls['TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'] = IDL_token;\n };\n\n describe('caching IDLs', () => {\n // Fetching IDLs from the network is not currently supported\n it.skip('caches IDLs from the network', async () => {\n const spy = jest.spyOn(solanaApi, 'getAccountInfo');\n\n const mockInst = {\n transaction: {\n transaction: {\n message: {\n accountKeys: ['JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4'],\n },\n },\n },\n data: '',\n programIdIndex: 0,\n };\n\n await decoder.decodeInstruction(mockInst as any);\n await decoder.decodeInstruction(mockInst as any);\n\n expect(spy).toHaveBeenCalledTimes(1);\n\n await decoder.decodeLog({\n programId: 'JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4',\n message: '',\n } as any);\n\n expect(spy).toHaveBeenCalledTimes(1);\n });\n });\n\n describe('parsing instruction discriminators', () => {\n beforeAll(() => {\n loadDecoderIdls();\n });\n\n it('correctly parses Anchor program discriminators', () => {\n for (const inst of IDL_Jupiter.instructions) {\n expect(\n decoder.parseDiscriminator(\n inst.name,\n 'JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4',\n ),\n ).toEqual(Buffer.from(inst.discriminator));\n }\n });\n\n it('correctly parses SPL program discriminators', () => {\n for (let i = 0; i < IDL_token.program.instructions.length; i++) {\n const inst = IDL_token.program.instructions[i];\n expect(\n decoder.parseDiscriminator(\n inst.name,\n 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',\n ),\n ).toEqual(Buffer.from([i]));\n }\n });\n\n it('correctly parses hex discriminators', () => {\n for (let i = 0; i < IDL_token.program.instructions.length; i++) {\n expect(\n decoder.parseDiscriminator(\n `0x${Buffer.from([i]).toString('hex')}`,\n 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',\n ),\n ).toEqual(Buffer.from([i]));\n }\n\n for (const inst of IDL_Jupiter.instructions) {\n expect(\n decoder.parseDiscriminator(\n `0x${Buffer.from(inst.discriminator).toString('hex')}`,\n 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',\n ),\n ).toEqual(Buffer.from(inst.discriminator));\n }\n });\n\n it('correctly parses base58 discriminators', () => {\n for (let i = 0; i < IDL_token.program.instructions.length; i++) {\n expect(\n decoder.parseDiscriminator(\n bs58.encode(Buffer.from([i])),\n 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',\n ),\n ).toEqual(Buffer.from([i]));\n }\n\n for (const inst of IDL_Jupiter.instructions) {\n expect(\n decoder.parseDiscriminator(\n bs58.encode(Buffer.from(inst.discriminator)),\n 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',\n ),\n ).toEqual(Buffer.from(inst.discriminator));\n }\n });\n });\n\n describe('decode instrutions', () => {\n beforeAll(async () => {\n // https://solscan.io/block/330469167\n const { block } = await solanaApi.fetchBlock(330_469_167);\n blockData = block;\n\n loadDecoderIdls();\n }, 30_000);\n\n const instructionData = {\n routePlan: [\n {\n swap: {\n __kind: 'MeteoraDlmm',\n },\n percent: 100,\n inputIndex: 0,\n outputIndex: 1,\n },\n ],\n inAmount: BigInt(16000),\n quotedOutAmount: BigInt(126754),\n slippageBps: 200,\n platformFeeBps: 98,\n };\n\n it('can decode an instruction with an IDL file', async () => {\n //https://solscan.io/tx/3rf2sSMeJC1dd4t4TDvYPfvQjpL6DG6qdDcMnruDtATPbwjqt3xDnNvddtiTBESL8AWiFt2zENghqAh1h252bKQi\n const tx = findTx(\n blockData,\n '3rf2sSMeJC1dd4t4TDvYPfvQjpL6DG6qdDcMnruDtATPbwjqt3xDnNvddtiTBESL8AWiFt2zENghqAh1h252bKQi',\n );\n const instruction = tx!.transaction.message.instructions[3];\n\n const decoded = await decoder.decodeInstruction(instruction);\n\n expect(decoded).toBeDefined();\n expect(decoded!.name).toEqual('route');\n expect(decoded!.data).toEqual(instructionData);\n });\n\n // Since removing anchor we don't have a way of fetching IDLS\n it.skip('can decode an instruction with an IDL found on chain', async () => {\n // https://solscan.io/tx/3rf2sSMeJC1dd4t4TDvYPfvQjpL6DG6qdDcMnruDtATPbwjqt3xDnNvddtiTBESL8AWiFt2zENghqAh1h252bKQi\n const tx = findTx(\n blockData,\n '3rf2sSMeJC1dd4t4TDvYPfvQjpL6DG6qdDcMnruDtATPbwjqt3xDnNvddtiTBESL8AWiFt2zENghqAh1h252bKQi',\n );\n\n const instruction = tx!.transaction.message.instructions[3];\n const decoded = await decoder.decodeInstruction(instruction);\n\n expect(decoded).toBeDefined();\n expect(decoded!.name).toEqual('route');\n expect(decoded!.data).toEqual(instructionData);\n });\n\n it('can decode SPL token program instructions', async () => {\n const tx = findTx(\n blockData,\n '61vjnjBfvU3e2BqmatPd3uYi37woXS44oqcQ3gD1XoS4demqXSmT32vGpdYdXTHW5niePACTKQaDxipn6jhbTWDL',\n );\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain\n const instruction = tx!.meta?.innerInstructions.find(\n (inner) => inner.index === 0,\n )?.instructions[1]!;\n\n const program = getProgramId(instruction);\n expect(program).toBe('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA');\n\n const decoded = await decoder.decodeInstruction(instruction);\n\n expect(decoded).toEqual({\n name: 'transferChecked',\n data: {\n amount: BigInt('5904646875'),\n decimals: 6,\n },\n });\n });\n });\n\n describe('decode log', () => {\n beforeAll(async () => {\n //https://solscan.io/block/327347682\n const { block } = await solanaApi.fetchBlock(327_347_682);\n loadDecoderIdls();\n blockData = block;\n }, 30_000);\n\n const logData = {\n pubkey: 'BQR6JJFyMWxnUERqbCRCCy1ietW2yq8RTKDx9odzruha',\n data: {\n balances: [BigInt('16648442361'), BigInt('4003645427000')],\n },\n };\n\n it('can decode a log with an Anchor IDL file', async () => {\n // https://solscan.io/tx/5Z18NZWUiDmxmVYncvuyACB9HRRYyzZfRPE9pfT2yaTpAveDTUwghWaYMPRk9Df5HsJy9yd6dBrndrmHz1zfsAig\n const tx = findTx(\n blockData,\n '5Z18NZWUiDmxmVYncvuyACB9HRRYyzZfRPE9pfT2yaTpAveDTUwghWaYMPRk9Df5HsJy9yd6dBrndrmHz1zfsAig',\n );\n\n const programLogs = tx!.meta!.logs?.filter((l) =>\n l.message.startsWith('Program data:'),\n );\n expect(programLogs?.length).toBe(1);\n\n const decoded = await decoder.decodeLog(programLogs![0]);\n\n expect(decoded).not.toBeNull();\n expect(decoded!.name).toBe('poolBalanceUpdatedEvent');\n expect(decoded!.data).toEqual(logData);\n });\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"decoder.spec.js","sourceRoot":"","sources":["../../src/solana/decoder.spec.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2020-2025 SubQuery Pte Ltd authors & contributors\n// SPDX-License-Identifier: GPL-3.0\n\nimport { IdlV01 } from '@codama/nodes-from-anchor';\nimport { EventEmitter2 } from '@nestjs/event-emitter';\nimport { SolanaBlock, SolanaTransaction } from '@subql/types-solana';\nimport bs58 from 'bs58';\nimport { RootNode } from 'codama';\nimport { SolanaApi } from './api.solana';\nimport { SolanaDecoder } from './decoder';\nimport { getProgramId, filterInstructionsProcessor } from './utils.solana';\n\nconst HTTP_ENDPOINT =\n process.env.HTTP_ENDPOINT ??\n 'https://api.mainnet-beta.solana.com' ??\n 'https://solana.api.onfinality.io/public';\n\nconst IDL_codama_0_1_0: IdlV01 = require('../../test/8t2R21V3vjS1ucZzmX2memtGptjYZi2yGY3cYVa8dak7.idl.json');\nconst IDL_Jupiter: IdlV01 = require('../../test/JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4.idl.json');\nconst IDL_swap: IdlV01 = require('../../test/swapFpHZwjELNnjvThjajtiVmkz3yPQEHjLtka2fwHW.idl.json');\nconst IDL_token: RootNode = require('../../test/TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA.idl.json');\n\nfunction findTx(\n block: SolanaBlock,\n sig: string,\n): SolanaTransaction | undefined {\n return block.transactions.find((tx) =>\n tx.transaction.signatures.find((s) => s === sig),\n );\n}\n\ndescribe('SolanaDecoder', () => {\n let solanaApi: SolanaApi;\n let decoder: SolanaDecoder;\n let blockData: SolanaBlock;\n\n beforeAll(async () => {\n decoder = new SolanaDecoder();\n solanaApi = await SolanaApi.create(\n HTTP_ENDPOINT,\n new EventEmitter2(),\n decoder,\n );\n });\n\n const loadDecoderIdls = () => {\n // eslint-disable-next-line @typescript-eslint/dot-notation\n decoder.idls['JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4'] = IDL_Jupiter;\n // eslint-disable-next-line @typescript-eslint/dot-notation\n decoder.idls['swapFpHZwjELNnjvThjajtiVmkz3yPQEHjLtka2fwHW'] = IDL_swap;\n // eslint-disable-next-line @typescript-eslint/dot-notation\n decoder.idls['TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'] = IDL_token;\n // eslint-disable-next-line @typescript-eslint/dot-notation\n decoder.idls['8t2R21V3vjS1ucZzmX2memtGptjYZi2yGY3cYVa8dak7'] =\n IDL_codama_0_1_0;\n };\n\n describe('caching IDLs', () => {\n // Fetching IDLs from the network is not currently supported\n it.skip('caches IDLs from the network', async () => {\n const spy = jest.spyOn(solanaApi, 'getAccountInfo');\n\n const mockInst = {\n transaction: {\n transaction: {\n message: {\n accountKeys: ['JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4'],\n },\n },\n },\n data: '',\n programIdIndex: 0,\n };\n\n await decoder.decodeInstruction(mockInst as any);\n await decoder.decodeInstruction(mockInst as any);\n\n expect(spy).toHaveBeenCalledTimes(1);\n\n await decoder.decodeLog({\n programId: 'JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4',\n message: '',\n } as any);\n\n expect(spy).toHaveBeenCalledTimes(1);\n });\n });\n\n describe('parsing instruction discriminators', () => {\n beforeAll(() => {\n loadDecoderIdls();\n });\n\n it('correctly parses Anchor program discriminators', () => {\n for (const inst of IDL_Jupiter.instructions) {\n expect(\n decoder.parseDiscriminator(\n inst.name,\n 'JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4',\n ),\n ).toEqual(Buffer.from(inst.discriminator));\n }\n });\n\n it('correctly parses SPL program discriminators', () => {\n for (let i = 0; i < IDL_token.program.instructions.length; i++) {\n const inst = IDL_token.program.instructions[i];\n expect(\n decoder.parseDiscriminator(\n inst.name,\n 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',\n ),\n ).toEqual(Buffer.from([i]));\n }\n });\n\n it('correctly parses hex discriminators', () => {\n for (let i = 0; i < IDL_token.program.instructions.length; i++) {\n expect(\n decoder.parseDiscriminator(\n `0x${Buffer.from([i]).toString('hex')}`,\n 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',\n ),\n ).toEqual(Buffer.from([i]));\n }\n\n for (const inst of IDL_Jupiter.instructions) {\n expect(\n decoder.parseDiscriminator(\n `0x${Buffer.from(inst.discriminator).toString('hex')}`,\n 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',\n ),\n ).toEqual(Buffer.from(inst.discriminator));\n }\n });\n\n it('correctly parses base58 discriminators', () => {\n for (let i = 0; i < IDL_token.program.instructions.length; i++) {\n expect(\n decoder.parseDiscriminator(\n bs58.encode(Buffer.from([i])),\n 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',\n ),\n ).toEqual(Buffer.from([i]));\n }\n\n for (const inst of IDL_Jupiter.instructions) {\n expect(\n decoder.parseDiscriminator(\n bs58.encode(Buffer.from(inst.discriminator)),\n 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',\n ),\n ).toEqual(Buffer.from(inst.discriminator));\n }\n });\n });\n\n describe('decode instrutions', () => {\n beforeAll(async () => {\n // https://solscan.io/block/330469167\n const { block } = await solanaApi.fetchBlock(330_469_167);\n blockData = block;\n\n loadDecoderIdls();\n }, 30_000);\n\n const instructionData = {\n routePlan: [\n {\n swap: {\n __kind: 'MeteoraDlmm',\n },\n percent: 100,\n inputIndex: 0,\n outputIndex: 1,\n },\n ],\n inAmount: BigInt(16000),\n quotedOutAmount: BigInt(126754),\n slippageBps: 200,\n platformFeeBps: 98,\n };\n\n it('can decode an instruction with an IDL file', async () => {\n //https://solscan.io/tx/3rf2sSMeJC1dd4t4TDvYPfvQjpL6DG6qdDcMnruDtATPbwjqt3xDnNvddtiTBESL8AWiFt2zENghqAh1h252bKQi\n const tx = findTx(\n blockData,\n '3rf2sSMeJC1dd4t4TDvYPfvQjpL6DG6qdDcMnruDtATPbwjqt3xDnNvddtiTBESL8AWiFt2zENghqAh1h252bKQi',\n );\n const instruction = tx!.transaction.message.instructions[3];\n\n const decoded = await decoder.decodeInstruction(instruction);\n\n expect(decoded).toBeDefined();\n expect(decoded!.name).toEqual('route');\n expect(decoded!.data).toEqual(instructionData);\n });\n\n // Since removing anchor we don't have a way of fetching IDLS\n it.skip('can decode an instruction with an IDL found on chain', async () => {\n // https://solscan.io/tx/3rf2sSMeJC1dd4t4TDvYPfvQjpL6DG6qdDcMnruDtATPbwjqt3xDnNvddtiTBESL8AWiFt2zENghqAh1h252bKQi\n const tx = findTx(\n blockData,\n '3rf2sSMeJC1dd4t4TDvYPfvQjpL6DG6qdDcMnruDtATPbwjqt3xDnNvddtiTBESL8AWiFt2zENghqAh1h252bKQi',\n );\n\n const instruction = tx!.transaction.message.instructions[3];\n const decoded = await decoder.decodeInstruction(instruction);\n\n expect(decoded).toBeDefined();\n expect(decoded!.name).toEqual('route');\n expect(decoded!.data).toEqual(instructionData);\n });\n\n it('can decode SPL token program instructions', async () => {\n const tx = findTx(\n blockData,\n '61vjnjBfvU3e2BqmatPd3uYi37woXS44oqcQ3gD1XoS4demqXSmT32vGpdYdXTHW5niePACTKQaDxipn6jhbTWDL',\n );\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain\n const instruction = tx!.meta?.innerInstructions.find(\n (inner) => inner.index === 0,\n )?.instructions[1]!;\n\n const program = getProgramId(instruction);\n expect(program).toBe('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA');\n\n const decoded = await decoder.decodeInstruction(instruction);\n\n expect(decoded).toEqual({\n name: 'transferChecked',\n data: {\n amount: BigInt('5904646875'),\n decimals: 6,\n },\n });\n });\n });\n\n describe('decode log', () => {\n beforeAll(async () => {\n //https://solscan.io/block/327347682\n const { block } = await solanaApi.fetchBlock(327_347_682);\n loadDecoderIdls();\n blockData = block;\n }, 30_000);\n\n const logData = {\n pubkey: 'BQR6JJFyMWxnUERqbCRCCy1ietW2yq8RTKDx9odzruha',\n data: {\n balances: [BigInt('16648442361'), BigInt('4003645427000')],\n },\n };\n\n it('can decode a log with an Anchor IDL file', async () => {\n // https://solscan.io/tx/5Z18NZWUiDmxmVYncvuyACB9HRRYyzZfRPE9pfT2yaTpAveDTUwghWaYMPRk9Df5HsJy9yd6dBrndrmHz1zfsAig\n const tx = findTx(\n blockData,\n '5Z18NZWUiDmxmVYncvuyACB9HRRYyzZfRPE9pfT2yaTpAveDTUwghWaYMPRk9Df5HsJy9yd6dBrndrmHz1zfsAig',\n );\n\n const programLogs = tx!.meta!.logs?.filter((l) =>\n l.message.startsWith('Program data:'),\n );\n expect(programLogs?.length).toBe(1);\n\n const decoded = await decoder.decodeLog(programLogs![0]);\n\n expect(decoded).not.toBeNull();\n expect(decoded!.name).toBe('poolBalanceUpdatedEvent');\n expect(decoded!.data).toEqual(logData);\n });\n\n it('can decode codama 0.1.0 spec idl events', async () => {\n const solanaApi = await SolanaApi.create(\n 'https://api.devnet.solana.com',\n new EventEmitter2(),\n decoder,\n );\n\n const block = await solanaApi.fetchBlock(405402294);\n\n const tx = findTx(\n block.block,\n '4xHLJtomvuF2DAwtDoHgGqABv47kmqMCvd691bRe9XhiAP99grjvpAdvNQGnA4PETZSvhXdfHvvHUNWu2SNM3aqE',\n );\n\n expect(tx).toBeDefined();\n\n const programLogs = tx!.meta!.logs?.filter((l) =>\n l.message.startsWith('Program data:'),\n );\n expect(programLogs).toBeDefined();\n const decoded = await programLogs![0].decodedMessage;\n expect(decoded).not.toBeNull();\n expect(decoded!.name).toEqual('createCampaign');\n expect(decoded!.data).toMatchObject({\n aggregateAmount: 10000n,\n campaign: 'BjYpCVaiksvD8Dw4LixUJVNaCptefKk86nDtw419b7Y5',\n campaignName: 'HODL or Nothing',\n campaignStartTime: 1754142441n,\n creator: 'HTtnrJ5iq9HVVypJZxFKMCcR6JDiUqT6yaE7c6BvfeTp',\n expirationTime: 1757776469n,\n ipfsCid: 'bafkreiecpwdhvkmw4y6iihfndk7jhwjas3m5htm7nczovt6m37mucwgsrq',\n merkleRoot: ['base64', '1SVJywcqH80FJBL8gPZ47/6Sru7czRyuYyxcbh3ok3k='],\n recipientCount: 100,\n tokenDecimals: 6,\n tokenMint: '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU',\n });\n });\n });\n});\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@subql/node-solana",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.2.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"author": "Ian He",
|
|
6
6
|
"license": "GPL-3.0",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"@nestjs/platform-express": "^11.0.8",
|
|
27
27
|
"@nestjs/schedule": "^5.0.1",
|
|
28
28
|
"@solana/kit": "^3.0.2",
|
|
29
|
-
"@subql/common-solana": "1.
|
|
29
|
+
"@subql/common-solana": "1.2.0",
|
|
30
30
|
"@subql/node-core": "^18.3.3",
|
|
31
31
|
"@subql/testing": "^2.2.1",
|
|
32
32
|
"@subql/types-solana": "1.1.0",
|