@solanafm/explorer-kit
Version:
Public Solana Data Parsers
1,752 lines (1,737 loc) • 229 kB
JavaScript
// 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,