import { Connection, PublicKey, SystemProgram, TransactionInstruction, } from '@solana/web3.js'; import { createInstruction, deleteInstruction, reallocInstruction, transferInstruction, updateInstruction, } from './instructions'; import { NameRegistryState } from './state'; import { Numberu64 } from './utils'; import { getHashedName, getNameAccountKey, getNameOwner, Numberu32, } from './utils'; //////////////////////////////////////////////////////////// export const NAME_PROGRAM_ID = new PublicKey( 'namesLPneVptA9Z5rqUDD9tMTWEJwofgaYwp8cawRkX', ); export const HASH_PREFIX = 'SPL Name Service'; //////////////////////////////////////////////////////////// /** * Creates a name account with the given rent budget, allocated space, owner and class. * * @param connection The solana connection object to the RPC node * @param name The name of the new account * @param space The space in bytes allocated to the account * @param payerKey The allocation cost payer * @param nameOwner The pubkey to be set as owner of the new name account * @param lamports The budget to be set for the name account. If not specified, it'll be the minimum for rent exemption * @param nameClass The class of this new name * @param parentName The parent name of the new name. If specified its owner needs to sign * @returns */ export async function createNameRegistry( connection: Connection, name: string, space: number, payerKey: PublicKey, nameOwner: PublicKey, lamports?: number, nameClass?: PublicKey, parentName?: PublicKey, ): Promise { const hashed_name = await getHashedName(name); const nameAccountKey = await getNameAccountKey( hashed_name, nameClass, parentName, ); const balance = lamports ? lamports : await connection.getMinimumBalanceForRentExemption(space); let nameParentOwner: PublicKey | undefined; if (parentName) { const parentAccount = await getNameOwner(connection, parentName); nameParentOwner = parentAccount.owner; } const createNameInstr = createInstruction( NAME_PROGRAM_ID, SystemProgram.programId, nameAccountKey, nameOwner, payerKey, hashed_name, new Numberu64(balance), new Numberu32(space), nameClass, parentName, nameParentOwner, ); return createNameInstr; } /** * Overwrite the data of the given name registry. * * @param connection The solana connection object to the RPC node * @param name The name of the name registry to update * @param offset The offset to which the data should be written into the registry * @param input_data The data to be written * @param nameClass The class of this name, if it exsists * @param nameParent The parent name of this name, if it exists */ export async function updateNameRegistryData( connection: Connection, name: string, offset: number, input_data: Buffer, nameClass?: PublicKey, nameParent?: PublicKey, ): Promise { const hashed_name = await getHashedName(name); const nameAccountKey = await getNameAccountKey( hashed_name, nameClass, nameParent, ); let signer: PublicKey; if (nameClass) { signer = nameClass; } else { signer = (await NameRegistryState.retrieve(connection, nameAccountKey)) .owner; } const updateInstr = updateInstruction( NAME_PROGRAM_ID, nameAccountKey, new Numberu32(offset), input_data, signer, nameParent, ); return updateInstr; } /** * Change the owner of a given name account. * * @param connection The solana connection object to the RPC node * @param name The name of the name account * @param newOwner The new owner to be set * @param curentNameOwner the current name Owner * @param nameClass The class of this name, if it exsists * @param nameParent The parent name of this name, if it exists * @returns */ export async function transferNameOwnership( connection: Connection, name: string, newOwner: PublicKey, nameClass?: PublicKey, nameParent?: PublicKey, ): Promise { const hashed_name = await getHashedName(name); const nameAccountKey = await getNameAccountKey( hashed_name, nameClass, nameParent, ); let curentNameOwner: PublicKey; if (nameClass) { curentNameOwner = nameClass; } else { curentNameOwner = ( await NameRegistryState.retrieve(connection, nameAccountKey) ).owner; } const transferInstr = transferInstruction( NAME_PROGRAM_ID, nameAccountKey, newOwner, curentNameOwner, nameClass, nameParent, ); return transferInstr; } /** * Delete the name account and transfer the rent to the target. * * @param connection The solana connection object to the RPC node * @param name The name of the name account * @param refundTargetKey The refund destination address * @param nameClass The class of this name, if it exsists * @param nameParent The parent name of this name, if it exists * @returns */ export async function deleteNameRegistry( connection: Connection, name: string, refundTargetKey: PublicKey, nameClass?: PublicKey, nameParent?: PublicKey, ): Promise { const hashed_name = await getHashedName(name); const nameAccountKey = await getNameAccountKey( hashed_name, nameClass, nameParent, ); let nameOwner: PublicKey; if (nameClass) { nameOwner = nameClass; } else { nameOwner = (await NameRegistryState.retrieve(connection, nameAccountKey)) .owner; } const changeAuthoritiesInstr = deleteInstruction( NAME_PROGRAM_ID, nameAccountKey, refundTargetKey, nameOwner, ); return changeAuthoritiesInstr; } /** * Realloc the name account space. * * @param connection The solana connection object to the RPC node * @param name The name of the name account * @param space The new space to be allocated * @param payerKey The allocation cost payer if new space is larger than current or the refund destination if smaller * @param nameClass The class of this name, if it exsists * @param nameParent The parent name of this name, if it exists * @returns */ export async function reallocNameAccount( connection: Connection, name: string, space: number, payerKey: PublicKey, nameClass?: PublicKey, nameParent?: PublicKey, ): Promise { const hashedName = await getHashedName(name); const nameAccountKey = await getNameAccountKey( hashedName, nameClass, nameParent, ); let nameOwner: PublicKey; if (nameClass) { nameOwner = nameClass; } else { nameOwner = (await NameRegistryState.retrieve(connection, nameAccountKey)) .owner; } const reallocInstr = reallocInstruction( NAME_PROGRAM_ID, SystemProgram.programId, payerKey, nameAccountKey, nameOwner, new Numberu32(space), ); return reallocInstr; }