@solanafm/explorer-kit
Version:
Public Solana Data Parsers
1,645 lines (1,628 loc) • 232 kB
JavaScript
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var src_exports = {};
__export(src_exports, {
ParserType: () => ParserType,
SolanaFMParser: () => SolanaFMParser,
checkIfAccountParser: () => checkIfAccountParser,
checkIfErrorsParser: () => checkIfErrorsParser,
checkIfEventParser: () => checkIfEventParser,
checkIfInstructionParser: () => checkIfInstructionParser,
isDataWithMappedType: () => isDataWithMappedType,
isIdlAccounts: () => isIdlAccounts
});
module.exports = __toCommonJS(src_exports);
// 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
var import_anchor = require("@coral-xyz/anchor");
var import_utils = require("@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 import_anchor.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) => import_anchor.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: (0, import_utils.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
var import_anchor_new = require("@coral-xyz/anchor-new");
var import_utils2 = require("@solanafm/utils");
var createAnchorV1AccountParser = (idlItem) => {
const idl = idlItem.idl;
const accountLayouts = new import_anchor_new.BorshAccountsCoder(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: (0, import_utils2.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.metadata.name;
};
return {
accountLayouts,
parseAccount,
getProgramName
};
};
// src/parsers/v2/account/config.ts
var import_utils4 = require("@solanafm/utils");
// src/helpers/KinobiTreeGenerator.ts
var import_serializers = require("@metaplex-foundation/umi/serializers");
var import_spl_type_length_value = require("@solana/spl-type-length-value");
var import_kinobi_lite = require("@solanafm/kinobi-lite");
var import_utils3 = require("@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 ? (0, import_kinobi_lite.createFromJson)(kinobiJsonString) : (0, import_kinobi_lite.createFromIdls)([idl]);
if (idl.metadata.address === "Config1111111111111111111111111111111111111") {
kinobiTree.update(
new import_kinobi_lite.TransformNodesVisitor([
{
selector: { kind: "structFieldTypeNode", name: "info" },
transformer: (node) => {
(0, import_kinobi_lite.assertStructFieldTypeNode)(node);
return (0, import_kinobi_lite.structFieldTypeNode)({
...node,
child: (0, import_kinobi_lite.stringTypeNode)({
size: (0, import_kinobi_lite.prefixedSize)((0, import_kinobi_lite.numberTypeNode)("u64"))
})
});
}
}
])
);
} else if (idl.metadata.address === "BPFLoaderUpgradeab1e11111111111111111111111") {
kinobiTree.update(
new import_kinobi_lite.TransformNodesVisitor([
{
selector: { kind: "structFieldTypeNode", name: "data" },
transformer: (node) => {
(0, import_kinobi_lite.assertStructFieldTypeNode)(node);
return (0, import_kinobi_lite.structFieldTypeNode)({
...node,
child: (0, import_kinobi_lite.bytesTypeNode)({
kind: "remainder"
})
});
}
}
])
);
} else if (idl.metadata.address === "noopb9bkMVfRPU8AsbpTUg8AQkHtKwMYZiFUjNRtMmV") {
kinobiTree.update(
new import_kinobi_lite.TransformNodesVisitor([
{
selector: { kind: "structFieldTypeNode", name: "data" },
transformer: (node) => {
(0, import_kinobi_lite.assertStructFieldTypeNode)(node);
return (0, import_kinobi_lite.structFieldTypeNode)({
...node,
child: (0, import_kinobi_lite.bytesTypeNode)({
kind: "remainder"
})
});
}
}
])
);
} else if (idl.metadata.address === "11111111111111111111111111111111") {
kinobiTree.update(
new import_kinobi_lite.TransformNodesVisitor([
{
selector: { kind: "structFieldTypeNode", name: "seed" },
transformer: (node) => {
(0, import_kinobi_lite.assertStructFieldTypeNode)(node);
return (0, import_kinobi_lite.structFieldTypeNode)({
...node,
child: (0, import_kinobi_lite.stringTypeNode)({
size: (0, import_kinobi_lite.prefixedSize)((0, import_kinobi_lite.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 = (0, import_kinobi_lite.getAllDefinedTypes)(this.rootNode);
switch (treeGeneratorType) {
case 1 /* INSTRUCTIONS */:
const instructionLayout = /* @__PURE__ */ new Map();
const instructionNodes = (0, import_kinobi_lite.getAllInstructions)(this.rootNode);
instructionNodes.forEach((instructionNode, index) => {
if ((0, import_kinobi_lite.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 = (0, import_spl_type_length_value.splDiscriminate)(`${interfacePrefixString ?? ""}:${ixName}`);
instructionLayout.set((0, import_utils3.encodeBase58)(discriminant), fmShankSerializer);
} else {
instructionLayout.set(index, fmShankSerializer);
}
}
}
}
});
return instructionLayout;
case 0 /* ACCOUNTS */:
const accountNodes = (0, import_kinobi_lite.getAllAccounts)(this.rootNode);
const accountLayout = /* @__PURE__ */ new Map();
accountNodes.forEach((account, index) => {
if ((0, import_kinobi_lite.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 = (0, import_kinobi_lite.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 = (0, import_kinobi_lite.getAllEvents)(this.rootNode);
const eventsLayout = /* @__PURE__ */ new Map();
eventNodes.forEach((eventNode, index) => {
if ((0, import_kinobi_lite.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, (0, import_serializers.array)(innerArrayLayout[1], { size: "remainder" })];
}
return [keyName, (0, import_serializers.array)(innerArrayLayout[1], { size: size2 })];
}
return ["typeArrayNodeNull", null];
case "boolTypeNode":
return [keyName, (0, import_serializers.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,
(0, import_serializers.bytes)({
size
})
];
}
return [keyName, (0, import_serializers.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,
(0, import_serializers.dataEnum)(innerEnumLayouts, {
size: enumDiscSize[1]
})
];
}
return [keyName, (0, import_serializers.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,
(0, import_serializers.map)(keyLayout[1], valueLayout[1], {
description: "",
size: "remainder"
})
];
}
return [
keyName,
(0, import_serializers.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, (0, import_serializers.option)(innerOptionLayout[1], options)];
}
return ["typeOptionNodeNull", null];
case "publicKeyTypeNode":
return [keyName, (0, import_serializers.publicKey)()];
case "setTypeNode":
const innerSetLayout = _KinobiTreeGenerator.createSerializer(field.child, types, keyName, treeGeneratorType);
if (innerSetLayout[1]) {
return [keyName, (0, import_serializers.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,
(0, import_serializers.string)({
size: stringSize
})
];
}
return [keyName, (0, import_serializers.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, (0, import_serializers.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, (0, import_serializers.tuple)(innerTupleLayouts)];
case "enumEmptyVariantTypeNode":
return [field.name, (0, import_serializers.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, (0, import_serializers.u8)()];
case "u16":
return [keyName, (0, import_serializers.u16)()];
case "u32":
return [keyName, (0, import_serializers.u32)()];
case "u64":
return [keyName, (0, import_serializers.u64)()];
case "u128":
return [keyName, (0, import_serializers.u128)()];
case "i8":
return [keyName, (0, import_serializers.i8)()];
case "i16":
return [keyName, (0, import_serializers.i16)()];
case "i32":
return [keyName, (0, import_serializers.i32)()];
case "i64":
return [keyName, (0, import_serializers.i64)()];
case "i128":
return [keyName, (0, import_serializers.i128)()];
case "f32":
return [keyName, (0, import_serializers.f32)()];
case "f64":
return [keyName, (0, import_serializers.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: (0, import_utils4.convertBNToNumberInObject)(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
var import_utils5 = require("@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: (0, import_utils5.convertBNToNumberInObject)(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
var import_utils6 = require("@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",