/* eslint-disable @typescript-eslint/no-redeclare */ import { Infer, number, literal, enums, union, boolean, array, type, nullable, size, string, optional, any, } from "superstruct"; import { PublicKeyFromString } from "../validators/pubkey"; // Token2022 extensions guide: https://spl.solana.com/token-2022/extensions export type DefaultTokenAccountState = Infer; export const DefaultAccountState = enums(["initialized", "frozen"]); // token account extensions export type TokenAccountExtensionType = Infer; export const TokenAccountExtensionType = enums([ "transferFeeAmount", "immutableOwner", "memoTransfer", "cpiGuard", "nonTransferableAccount", "confidentialTransferAccount", "confidentialTransferFeeAmount", "transferHookAccount", ]); export type ImmutableOwnerExt = Infer; export const ImmutableOwnerExt = type({ extension: literal("immutableOwner"), }); export type MemoTransferExt = Infer; export type MemoTransferState = Infer; export const MemoTransferState = type({ requireIncomingTransferMemos: boolean(), }); export const MemoTransferExt = type({ extension: literal("memoTransfer"), state: MemoTransferState, }); export type TransferFeeAmountExt = Infer; export type TransferFeeAmountState = Infer; export const TransferFeeAmountState = type({ withheldAmount: number(), }); export const TransferFeeAmountExt = type({ extension: literal("transferFeeAmount"), state: TransferFeeAmountState, }); export type СpiGuardExt = Infer; export type СpiGuardState = Infer; export const СpiGuardState = type({ lockCpi: boolean(), }); export const СpiGuardExt = type({ extension: literal("cpiGuard"), state: СpiGuardState, }); export type NonTransferableAccountExt = Infer; export const NonTransferableAccountExt = type({ extension: literal("nonTransferableAccount"), }); export type ConfidentialTransferAccountExt = Infer; export type ConfidentialTransferAccountState = Infer; export const ConfidentialTransferAccountState = type({ approved: boolean(), elgamalPubkey: string(), pendingBalanceLo: string(), pendingBalanceHi: string(), availableBalance: string(), decryptableAvailableBalance: string(), allowConfidentialCredits: boolean(), allowNonConfidentialCredits: boolean(), pendingBalanceCreditCounter: number(), maximumPendingBalanceCreditCounter: number(), expectedPendingBalanceCreditCounter: number(), actualPendingBalanceCreditCounter: number(), }); export const ConfidentialTransferAccountExt = type({ extension: literal("confidentialTransferAccount"), state: ConfidentialTransferAccountState, }); export type ConfidentialTransferFeeAmountExt = Infer; export type ConfidentialTransferFeeAmountState = Infer; export const ConfidentialTransferFeeAmountState = type({ withheldAmount: string(), }); export const ConfidentialTransferFeeAmountExt = type({ extension: literal("confidentialTransferFeeAmount"), state: ConfidentialTransferFeeAmountState, }); export type TransferHookAccountExt = Infer; export type TransferHookAccountState = Infer; export const TransferHookAccountState = type({ transferring: boolean(), }); export const TransferHookAccountExt = type({ extension: literal("transferHookAccount"), state: TransferHookAccountState, }); export const UnknownExt = type({ extension: string(), state: optional(any()), }); export type TokenAccountExtensions = Infer; export const TokenAccountExtensions = array( union([ ImmutableOwnerExt, MemoTransferExt, TransferFeeAmountExt, СpiGuardExt, NonTransferableAccountExt, ConfidentialTransferFeeAmountExt, TransferHookAccountExt, UnknownExt, ]), ); // mint extensions export type MintExtensionType = Infer; export const MintExtensionType = enums([ "transferFeeConfig", "mintCloseAuthority", "permanentDelegate", "interestBearingConfig", "defaultAccountState", "nonTransferable", "transferHook", "metadataPointer", "tokenMetadata", "confidentialTransferMint", "confidentialTransferFeeConfig", "groupPointer", "groupMemberPointer", "tokenGroup", "tokenGroupMember", ]); const TransferFee = type({ epoch: number(), maximumFee: number(), transferFeeBasisPoints: number(), }); export type TransferFeeConfigExt = Infer; export type TransferFeeConfigState = Infer; export const TransferFeeConfigState = type({ newerTransferFee: TransferFee, olderTransferFee: TransferFee, transferFeeConfigAuthority: nullable(PublicKeyFromString), withdrawWithheldAuthority: nullable(PublicKeyFromString), withheldAmount: number(), }); export const TransferFeeConfigExt = type({ extension: literal("transferFeeConfig"), state: TransferFeeConfigState, }); export type MintCloseAuthorityExt = Infer; export type MintCloseAuthorityState = Infer; export const MintCloseAuthorityState = type({ closeAuthority: nullable(PublicKeyFromString), }); export const MintCloseAuthorityExt = type({ extension: literal("mintCloseAuthority"), state: MintCloseAuthorityState, }); export type PermanentDelegateExt = Infer; export type PermanentDelegateState = Infer; export const PermanentDelegateState = type({ delegate: nullable(PublicKeyFromString), }); export const PermanentDelegateExt = type({ extension: literal("permanentDelegate"), state: PermanentDelegateState, }); export type InterestBearingConfigExt = Infer; export type InterestBearingConfigState = Infer; export const InterestBearingConfigState = type({ rateAuthority: nullable(PublicKeyFromString), initializationTimestamp: number(), preUpdateAverageRate: number(), lastUpdateTimestamp: number(), currentRate: number(), }); export const InterestBearingConfigExt = type({ extension: literal("interestBearingConfig"), state: InterestBearingConfigState, }); export type DefaultAccountStateExt = Infer; export type DefaultAccountStateState = Infer; export const DefaultAccountStateState = type({ state: DefaultAccountState, }); export const DefaultAccountStateExt = type({ extension: literal("defaultAccountState"), state: DefaultAccountStateState, }); export type NonTransferableExt = Infer; export const NonTransferableExt = type({ extension: literal("nonTransferable"), }); export type TransferHookExt = Infer; export type TransferHookState = Infer; export const TransferHookState = type({ authority: nullable(PublicKeyFromString), programId: nullable(PublicKeyFromString), }); export const TransferHookExt = type({ extension: literal("transferHook"), state: TransferHookState, }); export type MetadataPointerExt = Infer; export type MetadataPointerState = Infer; export const MetadataPointerState = type({ authority: nullable(PublicKeyFromString), metadataAddress: nullable(PublicKeyFromString), }); export const MetadataPointerExt = type({ extension: literal("metadataPointer"), state: MetadataPointerState, }); export type TokenMetadataExt = Infer; export type TokenMetadataState = Infer; export const TokenMetadataState = type({ additionalMetadata: array(size(array(string()), 2, 2)), mint: PublicKeyFromString, name: string(), symbol: string(), updateAuthority: nullable(PublicKeyFromString), uri: string(), }); export const TokenMetadataExt = type({ extension: literal("tokenMetadata"), state: TokenMetadataState, }); export type ConfidentialTransferMintExt = Infer; export type ConfidentialTransferMintState = Infer; export const ConfidentialTransferMintState = type({ authority: optional(nullable(PublicKeyFromString)), autoApproveNewAccounts: optional(boolean()), auditorElgamalPubkey: optional(nullable(string())), }); export const ConfidentialTransferMintExt = type({ extension: literal("confidentialTransferMint"), state: ConfidentialTransferMintState, }); export type ConfidentialTransferFeeConfigExt = Infer; export type ConfidentialTransferFeeConfigState = Infer; export const ConfidentialTransferFeeConfigState = type({ authority: optional(nullable(PublicKeyFromString)), harvestToMintEnabled: optional(boolean()), withdrawWithheldAuthorityElgamalPubkey: optional(nullable(string())), withheldAmount: optional(string()), }); export const ConfidentialTransferFeeConfigExt = type({ extension: literal("confidentialTransferFeeConfig"), state: ConfidentialTransferFeeConfigState, }); export type GroupPointerExt = Infer; export type GroupPointerState = Infer; export const GroupPointerState = type({ authority: nullable(PublicKeyFromString), groupAddress: nullable(PublicKeyFromString), }); export const GroupPointerExt = type({ extension: literal("groupPointer"), state: GroupPointerState, }); export type GroupMemberPointerExt = Infer; export type GroupMemberPointerState = Infer; export const GroupMemberPointerState = type({ authority: nullable(PublicKeyFromString), memberAddress: nullable(PublicKeyFromString), }); export const GroupMemberPointerExt = type({ extension: literal("groupMemberPointer"), state: GroupMemberPointerState, }); export type TokenGroupExt = Infer; export type TokenGroupState = Infer; export const TokenGroupState = type({ maxSize: number(), mint: PublicKeyFromString, size: number(), updateAuthority: nullable(PublicKeyFromString), }); export const TokenGroupExt = type({ extension: literal("tokenGroup"), state: TokenGroupState, }); export type TokenGroupMemberExt = Infer; export type TokenGroupMemberState = Infer; export const TokenGroupMemberState = type({ group: PublicKeyFromString, memberNumber: number(), mint: PublicKeyFromString, }); export const TokenGroupMemberExt = type({ extension: literal("tokenGroupMember"), state: TokenGroupMemberState, }); export type MintExt = Infer; export const MintExt = union([ NonTransferableExt, TransferFeeConfigExt, MintCloseAuthorityExt, PermanentDelegateExt, InterestBearingConfigExt, DefaultAccountStateExt, TransferHookExt, MetadataPointerExt, TokenMetadataExt, ConfidentialTransferMintExt, ConfidentialTransferFeeConfigExt, GroupPointerExt, GroupMemberPointerExt, TokenGroupExt, TokenGroupMemberExt, ]); export type MintExtensions = Infer; export const MintExtensions = array( union([ TransferFeeConfigExt, MintCloseAuthorityExt, PermanentDelegateExt, InterestBearingConfigExt, DefaultAccountStateExt, NonTransferableExt, TransferHookExt, MetadataPointerExt, TokenMetadataExt, ConfidentialTransferMintExt, ConfidentialTransferFeeConfigExt, GroupPointerExt, GroupMemberPointerExt, TokenGroupExt, TokenGroupMemberExt, UnknownExt, ]), ); export type ExtensionType = Infer; export const ExtensionType = union([TokenAccountExtensionType, MintExtensionType]);