@solana/spl-name-service
Version:
SPL Name Service JavaScript API
267 lines (242 loc) • 6.93 kB
text/typescript
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<TransactionInstruction> {
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<TransactionInstruction> {
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<TransactionInstruction> {
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<TransactionInstruction> {
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<TransactionInstruction> {
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;
}