@gorbchain-xyz/chaindecode
Version:
GorbchainSDK V1.3+ - Complete Solana development toolkit with advanced cryptography, messaging, and collaboration features. Build secure applications with blockchain, DeFi, and end-to-end encryption.
573 lines (572 loc) • 23.8 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { getGorbchainConfig } from '../utils/gorbchainConfig.js';
// Get Metaplex program ID from config
function getMetaplexProgramId() {
var _a, _b;
const config = getGorbchainConfig();
return (_b = (_a = config.programIds) === null || _a === void 0 ? void 0 : _a.metaplex) !== null && _b !== void 0 ? _b : 'BvoSmPBF6mBRxBMY9FPguw1zUoUg3xrc5CaWf7y5ACkc';
}
// Metaplex Instruction Types
export var MetaplexInstruction;
(function (MetaplexInstruction) {
MetaplexInstruction[MetaplexInstruction["CreateMetadataAccount"] = 0] = "CreateMetadataAccount";
MetaplexInstruction[MetaplexInstruction["UpdateMetadataAccount"] = 1] = "UpdateMetadataAccount";
MetaplexInstruction[MetaplexInstruction["DeprecatedCreateMasterEdition"] = 2] = "DeprecatedCreateMasterEdition";
MetaplexInstruction[MetaplexInstruction["DeprecatedMintNewEditionFromMasterEditionViaPrintingToken"] = 3] = "DeprecatedMintNewEditionFromMasterEditionViaPrintingToken";
MetaplexInstruction[MetaplexInstruction["UpdatePrimarySaleHappenedViaToken"] = 4] = "UpdatePrimarySaleHappenedViaToken";
MetaplexInstruction[MetaplexInstruction["DeprecatedSetReservationList"] = 5] = "DeprecatedSetReservationList";
MetaplexInstruction[MetaplexInstruction["DeprecatedCreateReservationList"] = 6] = "DeprecatedCreateReservationList";
MetaplexInstruction[MetaplexInstruction["SignMetadata"] = 7] = "SignMetadata";
MetaplexInstruction[MetaplexInstruction["DeprecatedMintPrintingTokensViaToken"] = 8] = "DeprecatedMintPrintingTokensViaToken";
MetaplexInstruction[MetaplexInstruction["DeprecatedMintPrintingTokens"] = 9] = "DeprecatedMintPrintingTokens";
MetaplexInstruction[MetaplexInstruction["CreateMasterEdition"] = 10] = "CreateMasterEdition";
MetaplexInstruction[MetaplexInstruction["MintNewEditionFromMasterEditionViaToken"] = 11] = "MintNewEditionFromMasterEditionViaToken";
MetaplexInstruction[MetaplexInstruction["ConvertMasterEditionV1ToV2"] = 12] = "ConvertMasterEditionV1ToV2";
MetaplexInstruction[MetaplexInstruction["MintNewEditionFromMasterEditionViaVaultProxy"] = 13] = "MintNewEditionFromMasterEditionViaVaultProxy";
MetaplexInstruction[MetaplexInstruction["PuffMetadata"] = 14] = "PuffMetadata";
MetaplexInstruction[MetaplexInstruction["UpdateMetadataAccountV2"] = 15] = "UpdateMetadataAccountV2";
MetaplexInstruction[MetaplexInstruction["CreateMetadataAccountV2"] = 16] = "CreateMetadataAccountV2";
MetaplexInstruction[MetaplexInstruction["CreateMasterEditionV3"] = 17] = "CreateMasterEditionV3";
MetaplexInstruction[MetaplexInstruction["VerifyCollection"] = 18] = "VerifyCollection";
MetaplexInstruction[MetaplexInstruction["Utilize"] = 19] = "Utilize";
MetaplexInstruction[MetaplexInstruction["ApproveUseAuthority"] = 20] = "ApproveUseAuthority";
MetaplexInstruction[MetaplexInstruction["RevokeUseAuthority"] = 21] = "RevokeUseAuthority";
MetaplexInstruction[MetaplexInstruction["UnverifyCollection"] = 22] = "UnverifyCollection";
MetaplexInstruction[MetaplexInstruction["ApproveCollectionAuthority"] = 23] = "ApproveCollectionAuthority";
MetaplexInstruction[MetaplexInstruction["RevokeCollectionAuthority"] = 24] = "RevokeCollectionAuthority";
MetaplexInstruction[MetaplexInstruction["SetAndVerifyCollection"] = 25] = "SetAndVerifyCollection";
MetaplexInstruction[MetaplexInstruction["FreezeDelegatedAccount"] = 26] = "FreezeDelegatedAccount";
MetaplexInstruction[MetaplexInstruction["ThawDelegatedAccount"] = 27] = "ThawDelegatedAccount";
MetaplexInstruction[MetaplexInstruction["RemoveCreatorVerification"] = 28] = "RemoveCreatorVerification";
MetaplexInstruction[MetaplexInstruction["BurnNft"] = 29] = "BurnNft";
MetaplexInstruction[MetaplexInstruction["VerifyCreator"] = 30] = "VerifyCreator";
MetaplexInstruction[MetaplexInstruction["UnverifyCreator"] = 31] = "UnverifyCreator";
MetaplexInstruction[MetaplexInstruction["CreateMetadataAccountV3"] = 32] = "CreateMetadataAccountV3";
MetaplexInstruction[MetaplexInstruction["SetCollectionSize"] = 33] = "SetCollectionSize";
MetaplexInstruction[MetaplexInstruction["SetTokenStandard"] = 34] = "SetTokenStandard";
MetaplexInstruction[MetaplexInstruction["BubblegumSetCollectionSize"] = 35] = "BubblegumSetCollectionSize";
MetaplexInstruction[MetaplexInstruction["BurnEditionNft"] = 36] = "BurnEditionNft";
MetaplexInstruction[MetaplexInstruction["CreateEscrowAccount"] = 37] = "CreateEscrowAccount";
MetaplexInstruction[MetaplexInstruction["CloseEscrowAccount"] = 38] = "CloseEscrowAccount";
MetaplexInstruction[MetaplexInstruction["TransferOutOfEscrow"] = 39] = "TransferOutOfEscrow";
MetaplexInstruction[MetaplexInstruction["Burn"] = 40] = "Burn";
MetaplexInstruction[MetaplexInstruction["Create"] = 41] = "Create";
MetaplexInstruction[MetaplexInstruction["Mint"] = 42] = "Mint";
MetaplexInstruction[MetaplexInstruction["Delegate"] = 43] = "Delegate";
MetaplexInstruction[MetaplexInstruction["Revoke"] = 44] = "Revoke";
MetaplexInstruction[MetaplexInstruction["Lock"] = 45] = "Lock";
MetaplexInstruction[MetaplexInstruction["Unlock"] = 46] = "Unlock";
MetaplexInstruction[MetaplexInstruction["Migrate"] = 47] = "Migrate";
MetaplexInstruction[MetaplexInstruction["Transfer"] = 48] = "Transfer";
MetaplexInstruction[MetaplexInstruction["Update"] = 49] = "Update";
MetaplexInstruction[MetaplexInstruction["Use"] = 50] = "Use";
MetaplexInstruction[MetaplexInstruction["Verify"] = 51] = "Verify";
MetaplexInstruction[MetaplexInstruction["Unverify"] = 52] = "Unverify";
})(MetaplexInstruction || (MetaplexInstruction = {}));
/**
* Main NFT/Metaplex decoder function
*/
export function decodeNFTInstruction(instruction) {
const data = instruction.data;
if (!data || data.length === 0) {
throw new Error('Invalid NFT instruction: no data');
}
const instructionType = data[0];
const programId = getMetaplexProgramId();
switch (instructionType) {
case MetaplexInstruction.CreateMetadataAccount:
return decodeCreateMetadataAccount(instruction, programId);
case MetaplexInstruction.UpdateMetadataAccount:
return decodeUpdateMetadataAccount(instruction, programId);
case MetaplexInstruction.CreateMasterEdition:
return decodeCreateMasterEdition(instruction, programId);
case MetaplexInstruction.MintNewEditionFromMasterEditionViaToken:
return decodeMintNewEdition(instruction, programId);
case MetaplexInstruction.UpdateMetadataAccountV2:
return decodeUpdateMetadataAccountV2(instruction, programId);
case MetaplexInstruction.CreateMetadataAccountV2:
return decodeCreateMetadataAccountV2(instruction, programId);
case MetaplexInstruction.CreateMasterEditionV3:
return decodeCreateMasterEditionV3(instruction, programId);
case MetaplexInstruction.VerifyCollection:
return decodeVerifyCollection(instruction, programId);
case MetaplexInstruction.UnverifyCollection:
return decodeUnverifyCollection(instruction, programId);
case MetaplexInstruction.VerifyCreator:
return decodeVerifyCreator(instruction, programId);
case MetaplexInstruction.UnverifyCreator:
return decodeUnverifyCreator(instruction, programId);
case MetaplexInstruction.BurnNft:
return decodeBurnNft(instruction, programId);
case MetaplexInstruction.CreateMetadataAccountV3:
return decodeCreateMetadataAccountV3(instruction, programId);
case MetaplexInstruction.SetCollectionSize:
return decodeSetCollectionSize(instruction, programId);
case MetaplexInstruction.SetTokenStandard:
return decodeSetTokenStandard(instruction, programId);
case MetaplexInstruction.Transfer:
return decodeNFTTransfer(instruction, programId);
case MetaplexInstruction.Mint:
return decodeNFTMint(instruction, programId);
case MetaplexInstruction.Burn:
return decodeNFTBurn(instruction, programId);
case MetaplexInstruction.Lock:
return decodeNFTLock(instruction, programId);
case MetaplexInstruction.Unlock:
return decodeNFTUnlock(instruction, programId);
default:
return {
type: 'nft-unknown',
programId,
data: {
instructionType,
error: `Unknown NFT instruction type: ${instructionType}`
},
accounts: instruction.accounts,
raw: instruction
};
}
}
/**
* Enhanced NFT instruction decoder with metadata extraction
*/
export function decodeNFTInstructionWithDetails(data) {
if (data.length === 0) {
return {
type: 'nft-unknown',
instruction: 'Unknown NFT instruction',
accounts: []
};
}
const instructionType = data[0];
switch (instructionType) {
case 0: // CreateMetadataAccount
return {
type: 'nft-create-metadata',
instruction: 'Create NFT metadata account',
nftDetails: {
isCollection: false,
isMasterEdition: false
},
accounts: []
};
case 10: // CreateMasterEdition
return {
type: 'nft-create-master-edition',
instruction: 'Create NFT master edition',
nftDetails: {
isMasterEdition: true,
isCollection: false
},
accounts: []
};
case 16: // CreateMetadataAccountV2
return {
type: 'nft-create-metadata-v2',
instruction: 'Create NFT metadata account V2',
nftDetails: {
isCollection: false,
isMasterEdition: false
},
accounts: []
};
case 17: // CreateMasterEditionV3
return {
type: 'nft-create-master-edition-v3',
instruction: 'Create NFT master edition V3',
nftDetails: {
isMasterEdition: true,
isCollection: false
},
accounts: []
};
case 18: // VerifyCollection
return {
type: 'nft-verify-collection',
instruction: 'Verify NFT collection',
nftDetails: {
isCollection: true,
isMasterEdition: false
},
accounts: []
};
case 29: // BurnNft
return {
type: 'nft-burn',
instruction: 'Burn NFT',
accounts: []
};
case 32: // CreateMetadataAccountV3
return {
type: 'nft-create-metadata-v3',
instruction: 'Create NFT metadata account V3',
nftDetails: {
isCollection: false,
isMasterEdition: false
},
accounts: []
};
case 48: // Transfer
return {
type: 'nft-transfer',
instruction: 'Transfer NFT',
accounts: []
};
case 42: // Mint
return {
type: 'nft-mint',
instruction: 'Mint NFT',
accounts: []
};
default:
return {
type: 'nft-unknown',
instruction: `Unknown NFT instruction (type: ${instructionType})`,
accounts: []
};
}
}
/**
* Check if a token is an NFT based on its characteristics
*/
export function isNFTToken(tokenInfo) {
// NFTs typically have:
// - Supply of 1
// - 0 decimals
// Note: We don't require mintAuthority to be null as many custom NFTs
// may still have mint authority but are functionally NFTs
const supply = BigInt(tokenInfo.supply);
return (supply === BigInt(1) &&
tokenInfo.decimals === 0);
}
/**
* Check if a token is a strict standard NFT (following Metaplex standards)
*/
export function isStandardNFT(tokenInfo) {
// Standard NFTs have:
// - Supply of 1
// - 0 decimals
// - No mint authority (supply is fixed)
const supply = BigInt(tokenInfo.supply);
return (supply === BigInt(1) &&
tokenInfo.decimals === 0 &&
tokenInfo.mintAuthority === null);
}
/**
* Get NFT metadata from URI
*/
export function fetchNFTMetadata(uri) {
return __awaiter(this, void 0, void 0, function* () {
var _a, _b, _c, _d, _e;
try {
const response = yield fetch(uri);
if (!response.ok) {
return null;
}
const metadata = yield response.json();
return {
name: (_a = metadata.name) !== null && _a !== void 0 ? _a : 'Unknown NFT',
symbol: (_b = metadata.symbol) !== null && _b !== void 0 ? _b : '',
uri,
sellerFeeBasisPoints: (_c = metadata.seller_fee_basis_points) !== null && _c !== void 0 ? _c : 0,
creators: (_e = (_d = metadata.properties) === null || _d === void 0 ? void 0 : _d.creators) !== null && _e !== void 0 ? _e : [],
collection: metadata.collection,
uses: metadata.uses
};
}
catch (error) {
// eslint-disable-next-line no-console
console.error('Failed to fetch NFT metadata:', error);
return null;
}
});
}
// Individual instruction decoders
function decodeCreateMetadataAccount(instruction, programId) {
var _a, _b, _c, _d, _e;
return {
type: 'nft-create-metadata',
programId,
data: {
metadata: (_a = instruction.accounts[0]) !== null && _a !== void 0 ? _a : '',
mint: (_b = instruction.accounts[1]) !== null && _b !== void 0 ? _b : '',
mintAuthority: (_c = instruction.accounts[2]) !== null && _c !== void 0 ? _c : '',
payer: (_d = instruction.accounts[3]) !== null && _d !== void 0 ? _d : '',
updateAuthority: (_e = instruction.accounts[4]) !== null && _e !== void 0 ? _e : ''
},
accounts: instruction.accounts
};
}
function decodeUpdateMetadataAccount(instruction, programId) {
var _a, _b;
return {
type: 'nft-update-metadata',
programId,
data: {
metadata: (_a = instruction.accounts[0]) !== null && _a !== void 0 ? _a : '',
updateAuthority: (_b = instruction.accounts[1]) !== null && _b !== void 0 ? _b : ''
},
accounts: instruction.accounts
};
}
function decodeCreateMasterEdition(instruction, programId) {
var _a;
return {
type: 'nft-create-master-edition',
programId,
data: {
edition: instruction.accounts[0],
mint: instruction.accounts[1],
updateAuthority: instruction.accounts[2],
mintAuthority: instruction.accounts[3],
payer: instruction.accounts[4],
metadata: instruction.accounts[5]
},
accounts: (_a = instruction.accounts) !== null && _a !== void 0 ? _a : []
};
}
function decodeMintNewEdition(instruction, programId) {
var _a;
return {
type: 'nft-mint-new-edition',
programId,
data: {
metadata: instruction.accounts[0],
edition: instruction.accounts[1],
masterEdition: instruction.accounts[2],
mint: instruction.accounts[3],
mintAuthority: instruction.accounts[4]
},
accounts: (_a = instruction.accounts) !== null && _a !== void 0 ? _a : []
};
}
function decodeUpdateMetadataAccountV2(instruction, programId) {
var _a;
return {
type: 'nft-update-metadata-v2',
programId,
data: {
metadata: instruction.accounts[0],
updateAuthority: instruction.accounts[1]
},
accounts: (_a = instruction.accounts) !== null && _a !== void 0 ? _a : []
};
}
function decodeCreateMetadataAccountV2(instruction, programId) {
var _a;
return {
type: 'nft-create-metadata-v2',
programId,
data: {
metadata: instruction.accounts[0],
mint: instruction.accounts[1],
mintAuthority: instruction.accounts[2],
payer: instruction.accounts[3],
updateAuthority: instruction.accounts[4]
},
accounts: (_a = instruction.accounts) !== null && _a !== void 0 ? _a : []
};
}
function decodeCreateMasterEditionV3(instruction, programId) {
var _a;
return {
type: 'nft-create-master-edition-v3',
programId,
data: {
edition: instruction.accounts[0],
mint: instruction.accounts[1],
updateAuthority: instruction.accounts[2],
mintAuthority: instruction.accounts[3],
payer: instruction.accounts[4],
metadata: instruction.accounts[5]
},
accounts: (_a = instruction.accounts) !== null && _a !== void 0 ? _a : []
};
}
function decodeVerifyCollection(instruction, programId) {
var _a;
return {
type: 'nft-verify-collection',
programId,
data: {
metadata: instruction.accounts[0],
collectionAuthority: instruction.accounts[1],
payer: instruction.accounts[2],
collectionMint: instruction.accounts[3],
collection: instruction.accounts[4]
},
accounts: (_a = instruction.accounts) !== null && _a !== void 0 ? _a : []
};
}
function decodeUnverifyCollection(instruction, programId) {
var _a;
return {
type: 'nft-unverify-collection',
programId,
data: {
metadata: instruction.accounts[0],
collectionAuthority: instruction.accounts[1],
collectionMint: instruction.accounts[2],
collection: instruction.accounts[3]
},
accounts: (_a = instruction.accounts) !== null && _a !== void 0 ? _a : []
};
}
function decodeVerifyCreator(instruction, programId) {
var _a;
return {
type: 'nft-verify-creator',
programId,
data: {
metadata: instruction.accounts[0],
creator: instruction.accounts[1]
},
accounts: (_a = instruction.accounts) !== null && _a !== void 0 ? _a : []
};
}
function decodeUnverifyCreator(instruction, programId) {
var _a;
return {
type: 'nft-unverify-creator',
programId,
data: {
metadata: instruction.accounts[0],
creator: instruction.accounts[1]
},
accounts: (_a = instruction.accounts) !== null && _a !== void 0 ? _a : []
};
}
function decodeBurnNft(instruction, programId) {
var _a;
return {
type: 'nft-burn',
programId,
data: {
metadata: instruction.accounts[0],
owner: instruction.accounts[1],
mint: instruction.accounts[2],
tokenAccount: instruction.accounts[3]
},
accounts: (_a = instruction.accounts) !== null && _a !== void 0 ? _a : []
};
}
function decodeCreateMetadataAccountV3(instruction, programId) {
var _a;
return {
type: 'nft-create-metadata-v3',
programId,
data: {
metadata: instruction.accounts[0],
mint: instruction.accounts[1],
mintAuthority: instruction.accounts[2],
payer: instruction.accounts[3],
updateAuthority: instruction.accounts[4]
},
accounts: (_a = instruction.accounts) !== null && _a !== void 0 ? _a : []
};
}
function decodeSetCollectionSize(instruction, programId) {
var _a;
return {
type: 'nft-set-collection-size',
programId,
data: {
collectionMetadata: instruction.accounts[0],
collectionAuthority: instruction.accounts[1],
collectionMint: instruction.accounts[2]
},
accounts: (_a = instruction.accounts) !== null && _a !== void 0 ? _a : []
};
}
function decodeSetTokenStandard(instruction, programId) {
var _a;
return {
type: 'nft-set-token-standard',
programId,
data: {
metadata: instruction.accounts[0],
updateAuthority: instruction.accounts[1],
mint: instruction.accounts[2]
},
accounts: (_a = instruction.accounts) !== null && _a !== void 0 ? _a : []
};
}
function decodeNFTTransfer(instruction, programId) {
var _a;
return {
type: 'nft-transfer',
programId,
data: {
tokenAccount: instruction.accounts[0],
tokenOwner: instruction.accounts[1],
destinationTokenAccount: instruction.accounts[2],
destinationOwner: instruction.accounts[3],
mint: instruction.accounts[4]
},
accounts: (_a = instruction.accounts) !== null && _a !== void 0 ? _a : []
};
}
function decodeNFTMint(instruction, programId) {
var _a;
return {
type: 'nft-mint',
programId,
data: {
tokenAccount: instruction.accounts[0],
tokenOwner: instruction.accounts[1],
metadata: instruction.accounts[2],
masterEdition: instruction.accounts[3],
mint: instruction.accounts[4]
},
accounts: (_a = instruction.accounts) !== null && _a !== void 0 ? _a : []
};
}
function decodeNFTBurn(instruction, programId) {
var _a;
return {
type: 'nft-burn',
programId,
data: {
tokenAccount: instruction.accounts[0],
mint: instruction.accounts[1],
authority: instruction.accounts[2]
},
accounts: (_a = instruction.accounts) !== null && _a !== void 0 ? _a : []
};
}
function decodeNFTLock(instruction, programId) {
var _a;
return {
type: 'nft-lock',
programId,
data: {
authority: instruction.accounts[0],
tokenOwner: instruction.accounts[1],
tokenAccount: instruction.accounts[2],
mint: instruction.accounts[3]
},
accounts: (_a = instruction.accounts) !== null && _a !== void 0 ? _a : []
};
}
function decodeNFTUnlock(instruction, programId) {
var _a;
return {
type: 'nft-unlock',
programId,
data: {
authority: instruction.accounts[0],
tokenOwner: instruction.accounts[1],
tokenAccount: instruction.accounts[2],
mint: instruction.accounts[3]
},
accounts: (_a = instruction.accounts) !== null && _a !== void 0 ? _a : []
};
}