UNPKG

@solanafm/explorer-kit

Version:
1,752 lines (1,737 loc) 229 kB
// src/types/AnchorTypes.ts function isIdlAccounts(accountItem) { return "accounts" in accountItem; } // src/types/NewAnchorTypes.ts var checkIfIdlDefinedFieldsNamed = (fields) => { const fieldsToCheck = fields; if (!fieldsToCheck[0]) return false; if (fieldsToCheck[0].name !== void 0) return true; return false; }; function isIdlAccounts2(accountItem) { return "accounts" in accountItem; } // src/helpers/idl.ts var isDataWithMappedType = (data) => { return data.type && data.data; }; var mapAccountKeysToName = (accountKeys, idlIxAccounts, mapTypes) => { if (idlIxAccounts && accountKeys) { const names = []; idlIxAccounts.forEach((idlIxAccount) => { names.push( extractIdlIxAccountName(idlIxAccount) ?? { name: "Unknown" } ); }); const flattenedArray = names.flat(5); const nonOptionalFlattenArray = flattenedArray.filter((accountKey) => !accountKey.optional); let translatedAccountKeysObj = {}; if (nonOptionalFlattenArray.length >= accountKeys.length) { accountKeys.forEach((accountKey, index) => { let objectKey = nonOptionalFlattenArray[index] ?? { name: "Unknown" }; const object = { [objectKey.name]: mapTypes ? { data: accountKey, type: "publicKey" } : accountKey }; translatedAccountKeysObj = Object.assign(translatedAccountKeysObj, object); }); } else { let namesIndex = 0; let optionalKeyCounter = 1; accountKeys.forEach((accountKey) => { let objectKey = flattenedArray[namesIndex] ?? { name: "Unknown" }; if (objectKey.optional) { if (accountKeys.length < nonOptionalFlattenArray.length + optionalKeyCounter) { const nonOptionalIdlAccount = getNonOptionalIdlAccount(namesIndex, flattenedArray); if (nonOptionalIdlAccount) { objectKey = nonOptionalIdlAccount.idlAccount ?? { name: "Unknown" }; namesIndex = nonOptionalIdlAccount.index; } } optionalKeyCounter++; } const object = { [objectKey.name]: mapTypes ? { data: accountKey, type: "publicKey" } : accountKey }; translatedAccountKeysObj = Object.assign(translatedAccountKeysObj, object); namesIndex++; }); } return translatedAccountKeysObj; } return {}; }; var getNonOptionalIdlAccount = (nameIndex, idlAccounts) => { let index = nameIndex; let idlAccount = idlAccounts[index] ?? { name: "Unknown" }; if (idlAccount) { if (idlAccount?.optional) { index++; return getNonOptionalIdlAccount(index, idlAccounts); } return { idlAccount, index }; } return void 0; }; var extractIdlIxAccountName = (idlAccount) => { if (idlAccount) { if (isIdlAccounts(idlAccount)) { const idlIxAccounts = []; idlAccount.accounts.forEach((account) => { let extractedName = extractIdlIxAccountName(account); if (extractedName) { if (Array.isArray(extractedName)) { extractedName = extractIdlIxAccountName(account); } else { idlIxAccounts.push({ name: idlAccount.name + "." + extractedName.name, optional: extractedName.optional }); } } }); return idlIxAccounts; } else { return { name: idlAccount.name, optional: idlAccount.isOptional }; } } return void 0; }; var mapDataTypeToName = (data, idlFields, shankDiscriminant) => { const dataKeys = Object.keys(data); const mappedDataType = {}; dataKeys.forEach((keyName) => { if (idlFields && idlFields.length > 0) { const filteredIdlField = idlFields?.find((idlField) => idlField.name === keyName); if (filteredIdlField) { mappedDataType[keyName] = { type: filteredIdlField.type, data: data[keyName] }; } else if (shankDiscriminant) { mappedDataType[keyName] = { type: shankDiscriminant.type, data: data[keyName] }; } else { mappedDataType[keyName] = { data: data[keyName], type: "Unknown Type" }; } } }); return Object.keys(mappedDataType).length > 0 ? mappedDataType : data; }; var mapNewAnchorDataTypeToName = (data, idlFields) => { const dataKeys = Object.keys(data); const mappedDataType = {}; dataKeys.forEach((keyName) => { if (idlFields && idlFields.length > 0) { if (checkIfIdlDefinedFieldsNamed(idlFields)) { const filteredIdlField = idlFields.find((idlField) => idlField.name === keyName); if (filteredIdlField) { mappedDataType[keyName] = { type: filteredIdlField.type, data: data[keyName] }; } else { mappedDataType[keyName] = { data: data[keyName], type: "Unknown Type" }; } } } }); return Object.keys(mappedDataType).length > 0 ? mappedDataType : data; }; // src/parsers/v2/account/anchor.ts import { BorshAccountsCoder } from "@coral-xyz/anchor"; import { convertBNToNumberInObject } from "@solanafm/utils"; // src/types/Parsers.ts var ParserType = /* @__PURE__ */ ((ParserType2) => { ParserType2["ACCOUNT"] = "account"; ParserType2["INSTRUCTION"] = "instruction"; ParserType2["EVENT"] = "event"; ParserType2["ERROR"] = "error"; return ParserType2; })(ParserType || {}); var checkIfInstructionParser = (parser) => { return parser ? "instructionsLayout" in parser && parser.instructionsLayout !== void 0 : false; }; var checkIfEventParser = (parser) => { return parser ? "eventsLayout" in parser && parser.eventsLayout !== void 0 : false; }; var checkIfErrorsParser = (parser) => { return parser ? "errorsLayout" in parser && parser.errorsLayout !== void 0 : false; }; var checkIfAccountParser = (parser) => { return parser ? "accountLayouts" in parser && parser.accountLayouts !== void 0 : false; }; // src/parsers/v2/account/anchor.ts var createAnchorAccountParser = (idlItem) => { const idl = idlItem.idl; const accountLayouts = new BorshAccountsCoder(idl); const parseAccount = (accountData, maptypes) => { const bufferData = Buffer.from(accountData, "base64"); const accountDiscriminator = bufferData.subarray(0, 8); const accountName = Array.from(idl.accounts ?? []).find( (key) => BorshAccountsCoder.accountDiscriminator(key.name).equals(accountDiscriminator) ); try { let decodedAccountData = accountLayouts.decodeAny(bufferData); if (decodedAccountData) { const filteredIdlAccount = idl.accounts?.filter((account) => account.name === accountName?.name) ?? []; if (maptypes) { decodedAccountData = mapDataTypeToName(decodedAccountData, filteredIdlAccount[0]?.type.fields); } return { name: accountName?.name, data: convertBNToNumberInObject(decodedAccountData), type: "account" /* ACCOUNT */ }; } } catch (error) { throw new Error(`Error parsing account data - ${accountData}`, { cause: { decoderError: error, programId: idlItem.programId } }); } return null; }; const getProgramName = () => { return idl.name; }; return { accountLayouts, parseAccount, getProgramName }; }; // src/parsers/v2/account/anchor-v1.ts import { BorshAccountsCoder as BorshAccountsCoder2 } from "@coral-xyz/anchor-new"; import { convertBNToNumberInObject as convertBNToNumberInObject2 } from "@solanafm/utils"; var createAnchorV1AccountParser = (idlItem) => { const idl = idlItem.idl; const accountLayouts = new BorshAccountsCoder2(idl); const parseAccount = (accountData, maptypes) => { try { const bufferData = Buffer.from(accountData, "base64"); const accountDiscriminator = bufferData.subarray(0, 8); const accountName = Array.from(idl.accounts ?? []).find( (key) => accountLayouts.accountDiscriminator(key.name).equals(accountDiscriminator) ); let decodedAccountData = accountLayouts.decodeAny(bufferData); if (decodedAccountData) { const filteredIdlType = idl.types?.filter((type) => type.name === accountName?.name) ?? []; if (maptypes) { if (filteredIdlType[0]?.type.kind === "struct" && filteredIdlType[0]?.type.fields) decodedAccountData = mapNewAnchorDataTypeToName(decodedAccountData, filteredIdlType[0]?.type.fields); } return { name: accountName?.name, data: convertBNToNumberInObject2(decodedAccountData), type: "account" /* ACCOUNT */ }; } } catch (error) { throw new Error(`Error parsing account data - ${accountData}`, { cause: { decoderError: error, programId: idlItem.programId } }); } return null; }; const getProgramName = () => { return idl.metadata.name; }; return { accountLayouts, parseAccount, getProgramName }; }; // src/parsers/v2/account/config.ts import { convertBNToNumberInObject as convertBNToNumberInObject3 } from "@solanafm/utils"; // src/helpers/KinobiTreeGenerator.ts import { array, bool, bytes, dataEnum, f32, f64, i8, i16, i32, i64, i128, map, option, publicKey, set, string, struct, tuple, u8, u16, u32, u64, u128, unit } from "@metaplex-foundation/umi/serializers"; import { splDiscriminate } from "@solana/spl-type-length-value"; import { assertStructFieldTypeNode, bytesTypeNode, createFromIdls, createFromJson, getAllAccounts, getAllDefinedTypes, getAllEvents, getAllInstructions, isStructTypeNode, numberTypeNode, prefixedSize, stringTypeNode, structFieldTypeNode, TransformNodesVisitor } from "@solanafm/kinobi-lite"; import { encodeBase58 } from "@solanafm/utils"; // src/helpers/common.ts var toSnakeCase = (str) => { return str.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g).map((x) => x.toLowerCase()).join("_"); }; // src/helpers/KinobiTreeGenerator.ts var KinobiTreeGenerator = class _KinobiTreeGenerator { rootNode; treeGeneratorType; constructor(idl, treeGeneratorType = 1 /* INSTRUCTIONS */, kinobiJsonString) { const kinobiTree = kinobiJsonString ? createFromJson(kinobiJsonString) : createFromIdls([idl]); if (idl.metadata.address === "Config1111111111111111111111111111111111111") { kinobiTree.update( new TransformNodesVisitor([ { selector: { kind: "structFieldTypeNode", name: "info" }, transformer: (node) => { assertStructFieldTypeNode(node); return structFieldTypeNode({ ...node, child: stringTypeNode({ size: prefixedSize(numberTypeNode("u64")) }) }); } } ]) ); } else if (idl.metadata.address === "BPFLoaderUpgradeab1e11111111111111111111111") { kinobiTree.update( new TransformNodesVisitor([ { selector: { kind: "structFieldTypeNode", name: "data" }, transformer: (node) => { assertStructFieldTypeNode(node); return structFieldTypeNode({ ...node, child: bytesTypeNode({ kind: "remainder" }) }); } } ]) ); } else if (idl.metadata.address === "noopb9bkMVfRPU8AsbpTUg8AQkHtKwMYZiFUjNRtMmV") { kinobiTree.update( new TransformNodesVisitor([ { selector: { kind: "structFieldTypeNode", name: "data" }, transformer: (node) => { assertStructFieldTypeNode(node); return structFieldTypeNode({ ...node, child: bytesTypeNode({ kind: "remainder" }) }); } } ]) ); } else if (idl.metadata.address === "11111111111111111111111111111111") { kinobiTree.update( new TransformNodesVisitor([ { selector: { kind: "structFieldTypeNode", name: "seed" }, transformer: (node) => { assertStructFieldTypeNode(node); return structFieldTypeNode({ ...node, child: stringTypeNode({ size: prefixedSize(numberTypeNode("u64")) }) }); } } ]) ); } this.rootNode = kinobiTree.getRoot(); this.treeGeneratorType = treeGeneratorType; } /** * Constructs a map with the discriminant as the key and the serializer as the value for a single shank-generated IDL * @param treeGeneratorType - The type of tree generator to construct * @param interfaceDiscriminantMode - Uses 8-bytes discriminant for the map key name if true, otherwise uses the discriminant value from the IDL * @param interfacePrefixString - String to prefix the interface name with * @returns A map with the discriminant as the key and the serializer as the value */ constructLayout(treeGeneratorType = 1 /* INSTRUCTIONS */, interfaceDiscriminantMode = false, interfacePrefixString) { return this._constructLayout(treeGeneratorType, interfaceDiscriminantMode, interfacePrefixString); } _constructLayout(treeGeneratorType, interfaceDiscriminantMode, interfacePrefixString) { const typeNodes = getAllDefinedTypes(this.rootNode); switch (treeGeneratorType) { case 1 /* INSTRUCTIONS */: const instructionLayout = /* @__PURE__ */ new Map(); const instructionNodes = getAllInstructions(this.rootNode); instructionNodes.forEach((instructionNode, index) => { if (isStructTypeNode(instructionNode.dataArgs.struct)) { const fields = instructionNode.dataArgs.struct.fields; if (fields[0]) { const ixDiscriminant = fields[0].defaultsTo?.value; if (ixDiscriminant?.kind === "number") { const discriminant = ixDiscriminant.value; const serializer = _KinobiTreeGenerator.createSerializer( instructionNode.dataArgs.struct, typeNodes, instructionNode.name ); const fmShankSerializer = { serializer: serializer[1], instructionName: serializer[0] }; instructionLayout.set(discriminant, fmShankSerializer); } if (!ixDiscriminant) { const serializer = _KinobiTreeGenerator.createSerializer( instructionNode.dataArgs.struct, typeNodes, instructionNode.name ); const fmShankSerializer = { serializer: serializer[1], instructionName: serializer[0] }; if (interfaceDiscriminantMode) { const ixName = toSnakeCase(instructionNode.name); const discriminant = splDiscriminate(`${interfacePrefixString ?? ""}:${ixName}`); instructionLayout.set(encodeBase58(discriminant), fmShankSerializer); } else { instructionLayout.set(index, fmShankSerializer); } } } } }); return instructionLayout; case 0 /* ACCOUNTS */: const accountNodes = getAllAccounts(this.rootNode); const accountLayout = /* @__PURE__ */ new Map(); accountNodes.forEach((account, index) => { if (isStructTypeNode(account.data.struct)) { const fields = account.data.struct.fields; const ixDiscriminant = fields[0]?.defaultsTo?.value; if (ixDiscriminant) { if (ixDiscriminant?.kind === "number") { const discriminant = ixDiscriminant.value; const serializer = _KinobiTreeGenerator.createSerializer( account.data.struct, typeNodes, account.name, treeGeneratorType ); const fmShankSerializer = { serializer: serializer[1], instructionName: serializer[0] }; accountLayout.set(discriminant, fmShankSerializer); } else if (ixDiscriminant?.kind === "list") { const discriminant = ixDiscriminant.values; const array3 = []; discriminant.forEach((value) => { if (value.kind === "number") { array3.push(value.value); } }); const buffer = Buffer.from(array3); const serializer = _KinobiTreeGenerator.createSerializer( account.data.struct, typeNodes, account.name, treeGeneratorType ); const fmShankSerializer = { serializer: serializer[1], instructionName: serializer[0] }; accountLayout.set(buffer.toString("base64"), fmShankSerializer); } } else { const serializer = _KinobiTreeGenerator.createSerializer( account.data.struct, typeNodes, account.name, treeGeneratorType ); const fmShankSerializer = { serializer: serializer[1], instructionName: serializer[0] }; const accountDiscriminator = index; accountLayout.set(accountDiscriminator, fmShankSerializer); } } }); return accountLayout; case 2 /* TYPES */: const parentTypeNodes = getAllDefinedTypes(this.rootNode); const typeLayout = /* @__PURE__ */ new Map(); parentTypeNodes.forEach((typeNode) => { const serializer = _KinobiTreeGenerator.createSerializer( typeNode.data, typeNodes, typeNode.name, treeGeneratorType ); const fmShankSerializer = { serializer: serializer[1], instructionName: serializer[0] }; typeLayout.set(typeNode.idlName, fmShankSerializer); }); return typeLayout; case 3 /* EVENTS */: const eventNodes = getAllEvents(this.rootNode); const eventsLayout = /* @__PURE__ */ new Map(); eventNodes.forEach((eventNode, index) => { if (isStructTypeNode(eventNode.dataArgs.struct)) { const serializer = _KinobiTreeGenerator.createSerializer( eventNode.dataArgs.struct, typeNodes, eventNode.dataArgs.name, treeGeneratorType ); const fmShankSerializer = { serializer: serializer[1], instructionName: serializer[0] }; const eventDiscriminator = index; eventsLayout.set(eventDiscriminator, fmShankSerializer); } }); return eventsLayout; default: return /* @__PURE__ */ new Map(); } } static createSerializer(field, types, keyName, treeGeneratorType = 1 /* INSTRUCTIONS */) { switch (field.kind) { case "arrayTypeNode": const innerArrayLayout = _KinobiTreeGenerator.createSerializer(field.child, types, keyName, treeGeneratorType); if (innerArrayLayout[1] !== null) { let size2 = void 0; switch (field.size.kind) { case "fixed": size2 = field.size.value; break; case "prefixed": size2 = _KinobiTreeGenerator.createNumberSerializer(field.size.prefix.format, "size")[1] ?? void 0; break; case "remainder": return [keyName, array(innerArrayLayout[1], { size: "remainder" })]; } return [keyName, array(innerArrayLayout[1], { size: size2 })]; } return ["typeArrayNodeNull", null]; case "boolTypeNode": return [keyName, bool()]; case "bytesTypeNode": let size = null; switch (field.size.kind) { case "fixed": size = field.size.value; break; case "prefixed": size = _KinobiTreeGenerator.createNumberSerializer(field.size.prefix.format, "bytesPrefixedNumber")[1]; break; case "remainder": size = "variable"; break; default: break; } if (size) { return [ keyName, bytes({ size }) ]; } return [keyName, bytes()]; case "linkTypeNode": const definedType = field.name; const filteredDefinedType = types.filter((type) => { return type.name === definedType; }); const typeManifest = filteredDefinedType[0]; if (typeManifest) { const innerDefinedLinkLayout = _KinobiTreeGenerator.createSerializer( typeManifest.data, types, typeManifest.name, treeGeneratorType ); return innerDefinedLinkLayout; } return ["typeDefinedLinkNodeNull", null]; case "enumTypeNode": const innerEnumLayouts = []; const enumDiscSize = _KinobiTreeGenerator.createNumberSerializer(field.size.format, "size"); field.variants.forEach((variant) => { const layout = _KinobiTreeGenerator.createSerializer(variant, types, variant.name, treeGeneratorType); innerEnumLayouts.push(layout); }); if (enumDiscSize && enumDiscSize[1]) { return [ keyName, dataEnum(innerEnumLayouts, { size: enumDiscSize[1] }) ]; } return [keyName, dataEnum(innerEnumLayouts)]; case "mapTypeNode": const keyLayout = _KinobiTreeGenerator.createSerializer(field.key, types, keyName, treeGeneratorType); const valueLayout = _KinobiTreeGenerator.createSerializer(field.value, types, keyName, treeGeneratorType); if (keyLayout[1] && valueLayout[1]) { let size2 = void 0; switch (field.size.kind) { case "fixed": size2 = field.size.value; break; case "prefixed": size2 = _KinobiTreeGenerator.createNumberSerializer(field.size.prefix.format, "size")[1] ?? void 0; break; case "remainder": return [ keyName, map(keyLayout[1], valueLayout[1], { description: "", size: "remainder" }) ]; } return [ keyName, map(keyLayout[1], valueLayout[1], { description: "", size: size2 }) ]; } return ["typeMapNodeNull", null]; case "numberTypeNode": const serializer = _KinobiTreeGenerator.createNumberSerializer(field.format, keyName); return serializer; case "optionTypeNode": const innerOptionLayout = _KinobiTreeGenerator.createSerializer(field.child, types, keyName, treeGeneratorType); const options = { fixed: field.fixed, prefix: _KinobiTreeGenerator.createNumberSerializer(field.prefix.format, "size")[1] ?? void 0 }; if (innerOptionLayout[1]) { return [keyName, option(innerOptionLayout[1], options)]; } return ["typeOptionNodeNull", null]; case "publicKeyTypeNode": return [keyName, publicKey()]; case "setTypeNode": const innerSetLayout = _KinobiTreeGenerator.createSerializer(field.child, types, keyName, treeGeneratorType); if (innerSetLayout[1]) { return [keyName, set(innerSetLayout[1])]; } return ["typeSetNodeNull", null]; case "stringTypeNode": let stringSize = null; switch (field.size.kind) { case "fixed": stringSize = field.size.value; break; case "prefixed": stringSize = _KinobiTreeGenerator.createNumberSerializer( field.size.prefix.format, "stringPrefixedNumber" )[1]; break; case "remainder": stringSize = "variable"; break; default: break; } if (stringSize) { return [ keyName, string({ size: stringSize }) ]; } return [keyName, string()]; case "structTypeNode": const structLayout = []; field.fields.forEach((innerField) => { const name = innerField.name; const innerStructLayout = _KinobiTreeGenerator.createSerializer( innerField.child, types, name, treeGeneratorType ); if (innerStructLayout[1] !== null) { const innerLayout = innerStructLayout[1]; structLayout.push([innerStructLayout[0], innerLayout]); } }); return [keyName, struct(structLayout)]; case "tupleTypeNode": const innerTupleLayouts = []; field.children.forEach((item) => { const innerItemLayout = _KinobiTreeGenerator.createSerializer(item, types, keyName, treeGeneratorType); if (innerItemLayout[1]) { innerTupleLayouts.push(innerItemLayout[1]); } }); return [keyName, tuple(innerTupleLayouts)]; case "enumEmptyVariantTypeNode": return [field.name, unit()]; case "enumStructVariantTypeNode": const innerEnumLayout = _KinobiTreeGenerator.createSerializer(field.struct, types, keyName, treeGeneratorType); if (innerEnumLayout[1]) { return [keyName, innerEnumLayout[1]]; } return ["typeEnumStructVariantNodeNull", null]; case "enumTupleVariantTypeNode": const innerEnumTupleLayout = _KinobiTreeGenerator.createSerializer( field.tuple, types, keyName, treeGeneratorType ); if (innerEnumTupleLayout[1]) { return [keyName, innerEnumTupleLayout[1]]; } return ["typeEnumStructVariantNodeNull", null]; default: console.error("Unknown node type", field); return ["nullSerializer", null]; } } static createNumberSerializer(field, keyName) { switch (field) { case "u8": return [keyName, u8()]; case "u16": return [keyName, u16()]; case "u32": return [keyName, u32()]; case "u64": return [keyName, u64()]; case "u128": return [keyName, u128()]; case "i8": return [keyName, i8()]; case "i16": return [keyName, i16()]; case "i32": return [keyName, i32()]; case "i64": return [keyName, i64()]; case "i128": return [keyName, i128()]; case "f32": return [keyName, f32()]; case "f64": return [keyName, f64()]; default: console.error("Unidentifiable field of:", field); return ["null", null]; } } }; // src/parsers/v2/account/config.ts var createShankConfigAccount = (idlItem, accountHash) => { const idl = idlItem.idl; const accountLayouts = new KinobiTreeGenerator(idl).constructLayout(0 /* ACCOUNTS */); const parseAccount = (accountData, mapTypes) => { try { const dataBuffer = Buffer.from(accountData, "base64"); let accountSerializer = void 0; if (accountHash === "StakeConfig11111111111111111111111111111111") { accountSerializer = accountLayouts.get(0); } else { accountSerializer = accountLayouts.get(1); } if (accountSerializer && dataBuffer.byteLength > 0) { const decodedAccountData = accountSerializer.serializer?.deserialize(dataBuffer); if (decodedAccountData && decodedAccountData[0]) { const filteredIdlAccount = idl.accounts?.filter( (account) => account.name.toLowerCase() === accountSerializer?.instructionName.toLowerCase() ) ?? []; if (mapTypes) { decodedAccountData[0] = mapDataTypeToName(decodedAccountData[0], filteredIdlAccount[0]?.type.fields); } return { name: accountSerializer.instructionName, data: convertBNToNumberInObject3(decodedAccountData[0]), type: "account" /* ACCOUNT */ }; } } return null; } catch (error) { throw new Error(`Error parsing account data - ${accountData}`, { cause: { decoderError: error, programId: idlItem.programId } }); } }; const getProgramName = () => { return "config"; }; return { accountLayouts, parseAccount, getProgramName }; }; // src/parsers/v2/account/name-service.ts import { convertBNToNumberInObject as convertBNToNumberInObject4 } from "@solanafm/utils"; var createShankNameServiceAccount = (idlItem) => { const idl = idlItem.idl; const accountLayouts = new KinobiTreeGenerator(idl).constructLayout(0 /* ACCOUNTS */); const ACCOUNT_MIN_SIZE = 96; const parseAccount = (accountData, mapTypes) => { try { const dataBuffer = Buffer.from(accountData, "base64"); let accountSerializer = void 0; if (dataBuffer.byteLength < ACCOUNT_MIN_SIZE) { throw new Error(`Account data length is less than the minimum size required for this account`); } if (dataBuffer.byteLength >= ACCOUNT_MIN_SIZE) { accountSerializer = accountLayouts.get(0); } if (accountSerializer && dataBuffer.length > 0) { const decodedAccountData = accountSerializer.serializer?.deserialize(dataBuffer); if (decodedAccountData && decodedAccountData[0]) { const filteredIdlAccount = idl.accounts?.filter( (account) => account.name.toLowerCase() === accountSerializer?.instructionName.toLowerCase() ) ?? []; if (mapTypes) { decodedAccountData[0] = mapDataTypeToName(decodedAccountData[0], filteredIdlAccount[0]?.type.fields); } return { name: accountSerializer.instructionName, data: convertBNToNumberInObject4(decodedAccountData[0]), type: "account" /* ACCOUNT */ }; } } return null; } catch (error) { throw new Error(`Error parsing account data - ${accountData}`, { cause: { decoderError: error, programId: idlItem.programId } }); } }; const getProgramName = () => { return idl.name; }; return { accountLayouts, parseAccount, getProgramName }; }; // src/parsers/v2/account/phoenix.ts import { convertBNToNumberInObject as convertBNToNumberInObject5 } from "@solanafm/utils"; // src/idls/phoenix.ts var PhoenixIDL = { version: "0.2.3", name: "phoenix_v1", accounts: [ { name: "Seat", type: { kind: "struct", fields: [ { name: "market", type: "publicKey" }, { name: "trader", type: "publicKey" }, { name: "approval_status", type: "u64" }, { name: "_padding", type: { array: ["u64", 6] } } ] } }, { name: "MarketHeader", type: { kind: "struct", fields: [ { name: "status", type: "u64" }, { name: "market_size_params", type: { defined: "MarketSizeParams" } }, { name: "base_params", type: { defined: "TokenParams" } }, { name: "base_lot_size", type: "u64" }, { name: "quote_params", type: { defined: "TokenParams" } }, { name: "quote_lot_size", type: "u64" }, { name: "tick_size_in_quote_atoms_per_base_unit", type: "u64" }, { name: "authority", type: "publicKey" }, { name: "fee_recipient", type: "publicKey" }, { name: "market_sequence_number", type: "u64" }, { name: "successor", type: "publicKey" }, { name: "raw_base_units_per_base_unit", type: "u32" } ] } } ], instructions: [ { name: "Swap", accounts: [ { name: "phoenixProgram", isMut: false, isSigner: false, desc: "Phoenix program" }, { name: "logAuthority", isMut: false, isSigner: false, desc: "Phoenix log authority" }, { name: "market", isMut: true, isSigner: false, desc: "This account holds the market state" }, { name: "trader", isMut: false, isSigner: true }, { name: "baseAccount", isMut: true, isSigner: false, desc: "Trader base token account" }, { name: "quoteAccount", isMut: true, isSigner: false, desc: "Trader quote token account" }, { name: "baseVault", isMut: true, isSigner: false, desc: "Base vault PDA, seeds are [b'vault', market_address, base_mint_address]" }, { name: "quoteVault", isMut: true, isSigner: false, desc: "Quote vault PDA, seeds are [b'vault', market_address, quote_mint_address]" }, { name: "tokenProgram", isMut: false, isSigner: false, desc: "Token program" } ], args: [ { name: "orderPacket", type: { defined: "OrderPacket" } } ], discriminant: { type: "u8", value: 0 } }, { name: "SwapWithFreeFunds", accounts: [ { name: "phoenixProgram", isMut: false, isSigner: false, desc: "Phoenix program" }, { name: "logAuthority", isMut: false, isSigner: false, desc: "Phoenix log authority" }, { name: "market", isMut: true, isSigner: false, desc: "This account holds the market state" }, { name: "trader", isMut: false, isSigner: true }, { name: "seat", isMut: false, isSigner: false } ], args: [ { name: "orderPacket", type: { defined: "OrderPacket" } } ], discriminant: { type: "u8", value: 1 } }, { name: "PlaceLimitOrder", accounts: [ { name: "phoenixProgram", isMut: false, isSigner: false, desc: "Phoenix program" }, { name: "logAuthority", isMut: false, isSigner: false, desc: "Phoenix log authority" }, { name: "market", isMut: true, isSigner: false, desc: "This account holds the market state" }, { name: "trader", isMut: false, isSigner: true }, { name: "seat", isMut: false, isSigner: false }, { name: "baseAccount", isMut: true, isSigner: false, desc: "Trader base token account" }, { name: "quoteAccount", isMut: true, isSigner: false, desc: "Trader quote token account" }, { name: "baseVault", isMut: true, isSigner: false, desc: "Base vault PDA, seeds are [b'vault', market_address, base_mint_address]" }, { name: "quoteVault", isMut: true, isSigner: false, desc: "Quote vault PDA, seeds are [b'vault', market_address, quote_mint_address]" }, { name: "tokenProgram", isMut: false, isSigner: false, desc: "Token program" } ], args: [ { name: "orderPacket", type: { defined: "OrderPacket" } } ], discriminant: { type: "u8", value: 2 } }, { name: "PlaceLimitOrderWithFreeFunds", accounts: [ { name: "phoenixProgram", isMut: false, isSigner: false, desc: "Phoenix program" }, { name: "logAuthority", isMut: false, isSigner: false, desc: "Phoenix log authority" }, { name: "market", isMut: true, isSigner: false, desc: "This account holds the market state" }, { name: "trader", isMut: false, isSigner: true }, { name: "seat", isMut: false, isSigner: false } ], args: [ { name: "orderPacket", type: { defined: "OrderPacket" } } ], discriminant: { type: "u8", value: 3 } }, { name: "ReduceOrder", accounts: [ { name: "phoenixProgram", isMut: false, isSigner: false, desc: "Phoenix program" }, { name: "logAuthority", isMut: false, isSigner: false, desc: "Phoenix log authority" }, { name: "market", isMut: true, isSigner: false, desc: "This account holds the market state" }, { name: "trader", isMut: false, isSigner: true }, { name: "baseAccount", isMut: true, isSigner: false, desc: "Trader base token account" }, { name: "quoteAccount", isMut: true, isSigner: false, desc: "Trader quote token account" }, { name: "baseVault", isMut: true, isSigner: false, desc: "Base vault PDA, seeds are [b'vault', market_address, base_mint_address]" }, { name: "quoteVault", isMut: true, isSigner: false, desc: "Quote vault PDA, seeds are [b'vault', market_address, quote_mint_address]" }, { name: "tokenProgram", isMut: false, isSigner: false, desc: "Token program" } ], args: [ { name: "params", type: { defined: "ReduceOrderParams" } } ], discriminant: { type: "u8", value: 4 } }, { name: "ReduceOrderWithFreeFunds", accounts: [ { name: "phoenixProgram", isMut: false, isSigner: false, desc: "Phoenix program" }, { name: "logAuthority", isMut: false, isSigner: false, desc: "Phoenix log authority" }, { name: "market", isMut: true, isSigner: false, desc: "This account holds the market state" }, { name: "trader", isMut: true, isSigner: true } ], args: [ { name: "params", type: { defined: "ReduceOrderParams" } } ], discriminant: { type: "u8", value: 5 } }, { name: "CancelAllOrders", accounts: [ { name: "phoenixProgram", isMut: false, isSigner: false, desc: "Phoenix program" }, { name: "logAuthority", isMut: false, isSigner: false, desc: "Phoenix log authority" }, { name: "market", isMut: true, isSigner: false, desc: "This account holds the market state" }, { name: "trader", isMut: false, isSigner: true }, { name: "baseAccount", isMut: true, isSigner: false, desc: "Trader base token account" }, { name: "quoteAccount", isMut: true, isSigner: false, desc: "Trader quote token account" }, { name: "baseVault", isMut: true, isSigner: false, desc: "Base vault PDA, seeds are [b'vault', market_address, base_mint_address]" }, { name: "quoteVault", isMut: true, isSigner: false, desc: "Quote vault PDA, seeds are [b'vault', market_address, quote_mint_address]" }, { name: "tokenProgram", isMut: false, isSigner: false, desc: "Token program" } ], args: [], discriminant: { type: "u8", value: 6 } }, { name: "CancelAllOrdersWithFreeFunds", accounts: [ { name: "phoenixProgram", isMut: false, isSigner: false, desc: "Phoenix program" }, { name: "logAuthority", isMut: false, isSigner: false, desc: "Phoenix log authority" }, { name: "market", isMut: true, isSigner: false, desc: "This account holds the market state" }, { name: "trader", isMut: false, isSigner: true } ], args: [], discriminant: { type: "u8", value: 7 } }, { name: "CancelUpTo", accounts: [ { name: "phoenixProgram", isMut: false, isSigner: false, desc: "Phoenix program" }, { name: "logAuthority", isMut: false, isSigner: false, desc: "Phoenix log authority" }, { name: "market", isMut: true, isSigner: false, desc: "This account holds the market state" }, { name: "trader", isMut: false, isSigner: true }, { name: "baseAccount", isMut: true, isSigner: false, desc: "Trader base token account" }, { name: "quoteAccount", isMut: true, isSigner: false, desc: "Trader quote token account" }, { name: "baseVault", isMut: true, isSigner: false, desc: "Base vault PDA, seeds are [b'vault', market_address, base_mint_address]" }, { name: "quoteVault", isMut: true, isSigner: false, desc: "Quote vault PDA, seeds are [b'vault', market_address, quote_mint_address]" }, { name: "tokenProgram", isMut: false, isSigner: false, desc: "Token program" } ], args: [ { name: "params", type: { defined: "CancelUpToParams" } } ], discriminant: { type: "u8", value: 8 } }, { name: "CancelUpToWithFreeFunds", accounts: [ { name: "phoenixProgram", isMut: false, isSigner: false, desc: "Phoenix program" }, { name: "logAuthority", isMut: false, isSigner: false, desc: "Phoenix log authority" }, { name: "market", isMut: true, isSigner: false, desc: "This account holds the market state" }, { name: "trader", isMut: false, isSigner: true } ], args: [ { name: "params", type: { defined: "CancelUpToParams" } } ], discriminant: { type: "u8", value: 9 } }, { name: "CancelMultipleOrdersById", accounts: [ { name: "phoenixProgram", isMut: false, isSigner: false, desc: "Phoenix program" }, { name: "logAuthority", isMut: false, isSigner: false, desc: "Phoenix log authority" }, { name: "market", isMut: true, isSigner: false, desc: "This account holds the market state" }, { name: "trader", isMut: false, isSigner: true }, { name: "baseAccount", isMut: true, isSigner: false, desc: "Trader base token account" }, { name: "quoteAccount", isMut: true, isSigner: false, desc: "Trader quote token account" }, { name: "baseVault", isMut: true, isSigner: false, desc: "Base vault PDA, seeds are [b'vault', market_address, base_mint_address]" }, { name: "quoteVault", isMut: true, isSigner: false, desc: "Quote vault PDA, seeds are [b'vault', market_address, quote_mint_address]" }, { name: "tokenProgram", isMut: false, isSigner: false, desc: "Token program" } ], args: [ { name: "params", type: { defined: "CancelMultipleOrdersByIdParams" } } ], discriminant: { type: "u8", value: 10 } }, { name: "CancelMultipleOrdersByIdWithFreeFunds", accounts: [ { name: "phoenixProgram", isMut: false, isSigner: false, desc: "Phoenix program" }, { name: "logAuthority", isMut: false, isSigner: false, desc: "Phoenix log authority" }, { name: "market", isMut: true, isSigner: false, desc: "This account holds the market state" }, { name: "trader", isMut: false, isSigner: true } ], args: [ { name: "params", type: { defined: "CancelMultipleOrdersByIdParams" } } ], discriminant: { type: "u8", value: 11 } }, { name: "WithdrawFunds", accounts: [ { name: "phoenixProgram", isMut: false, isSigner: false, desc: "Phoenix program" }, { name: "logAuthority", isMut: false, isSigner: false, desc: "Phoenix log authority" }, { name: "market", isMut: true, isSigner: false, desc: "This account holds the market state" }, { name: "trader", isMut: false, isSigner: true }, { name: "baseAccount", isMut: true, isSigner: false, desc: "Trader base token account" }, { name: "quoteAccount", isMut: true, isSigner: false, desc: "Trader quote token account" }, { name: "baseVault", isMut: true, isSigner: false, desc: "Base vault PDA, seeds are [b'vault', market_address, base_mint_address]" }, { name: "quoteVault", isMut: true, isSigner: false, desc: "Quote vault PDA, seeds are [b'vault', market_address, quote_mint_address]" }, { name: "tokenProgram", isMut: false, isSigner: false, desc: "Token program" } ], args: [ { name: "withdrawFundsParams", type: { defined: "WithdrawParams" } } ], discriminant: { type: "u8", value: 12 } }, { name: "DepositFunds", accounts: [ { name: "phoenixProgram", isMut: false, isSigner: false, desc: "Phoenix program" }, { name: "logAuthority", isMut: false, isSigner: false,