Skip to content

Commit

Permalink
js: add registerDomainNameV2 to devnet bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
dr497 committed May 13, 2024
1 parent 099d7ad commit cfc3b1e
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 1 deletion.
1 change: 1 addition & 0 deletions js/src/bindings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ export async function deleteNameRegistry(
}

/**
* @deprecated This function is deprecated and will be removed in future releases. Use `registerDomainNameV2` instead.
* This function can be used to register a .sol domain
* @param connection The Solana RPC connection object
* @param name The domain name to register e.g bonfida if you want to register bonfida.sol
Expand Down
114 changes: 113 additions & 1 deletion js/src/devnet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
createReverseInstruction,
createInstructionV3,
burnInstruction,
createSplitV2Instruction,
} from "./instructions";
import { NameRegistryState } from "./state";
import { Numberu64, Numberu32 } from "./int";
Expand All @@ -24,7 +25,12 @@ import {
createAssociatedTokenAccountIdempotentInstruction,
} from "@solana/spl-token";
import { ErrorType, SNSError } from "./error";
import { deserializeReverse, getHashedNameSync } from "./utils";
import {
deserializeReverse,
getHashedNameSync,
getPythFeedAccountKey,
} from "./utils";
import { PYTH_PULL_FEEDS } from "./constants";

const constants = {
/**
Expand Down Expand Up @@ -395,6 +401,7 @@ async function deleteNameRegistry(
}

/**
* @deprecated This function is deprecated and will be removed in future releases. Use `registerDomainNameV2` instead.
* This function can be used to register a .sol domain
* @param connection The Solana RPC connection object
* @param name The domain name to register e.g bonfida if you want to register bonfida.sol
Expand Down Expand Up @@ -672,6 +679,110 @@ const transferSubdomain = async (
return ix;
};

/**
* This function can be used to register a .sol domain
* @param connection The Solana RPC connection object
* @param name The domain name to register e.g bonfida if you want to register bonfida.sol
* @param space The domain name account size (max 10kB)
* @param buyer The public key of the buyer
* @param buyerTokenAccount The buyer token account (USDC)
* @param mint Optional mint used to purchase the domain, defaults to USDC
* @param referrerKey Optional referrer key
* @returns
*/
const registerDomainNameV2 = async (
connection: Connection,
name: string,
space: number,
buyer: PublicKey,
buyerTokenAccount: PublicKey,
mint = constants.USDC_MINT,
referrerKey?: PublicKey,
) => {
// Basic validation
if (name.includes(".") || name.trim().toLowerCase() !== name) {
throw new SNSError(ErrorType.InvalidDomain);
}
const [cs] = PublicKey.findProgramAddressSync(
[constants.REGISTER_PROGRAM_ID.toBuffer()],
constants.REGISTER_PROGRAM_ID,
);

const hashed = getHashedNameSync(name);
const nameAccount = getNameAccountKeySync(
hashed,
undefined,
constants.ROOT_DOMAIN_ACCOUNT,
);

const hashedReverseLookup = getHashedNameSync(nameAccount.toBase58());
const reverseLookupAccount = getNameAccountKeySync(hashedReverseLookup, cs);

const [derived_state] = PublicKey.findProgramAddressSync(
[nameAccount.toBuffer()],
constants.REGISTER_PROGRAM_ID,
);

const refIdx = constants.REFERRERS.findIndex((e) => referrerKey?.equals(e));
let refTokenAccount: PublicKey | undefined = undefined;

const ixs: TransactionInstruction[] = [];

if (refIdx !== -1 && !!referrerKey) {
refTokenAccount = getAssociatedTokenAddressSync(mint, referrerKey, true);
const acc = await connection.getAccountInfo(refTokenAccount);
if (!acc?.data) {
const ix = createAssociatedTokenAccountIdempotentInstruction(
buyer,
refTokenAccount,
referrerKey,
mint,
);
ixs.push(ix);
}
}

const vault = getAssociatedTokenAddressSync(
mint,
constants.VAULT_OWNER,
true,
);
const pythFeed = PYTH_PULL_FEEDS.get(mint.toBase58());

if (!pythFeed) {
throw new SNSError(ErrorType.PythFeedNotFound);
}

const [pythFeedAccount] = getPythFeedAccountKey(0, pythFeed);

const ix = new createSplitV2Instruction({
name,
space,
referrerIdxOpt: refIdx != -1 ? refIdx : null,
}).getInstruction(
constants.REGISTER_PROGRAM_ID,
constants.NAME_PROGRAM_ID,
constants.ROOT_DOMAIN_ACCOUNT,
nameAccount,
reverseLookupAccount,
SystemProgram.programId,
cs,
buyer,
buyer,
buyer,
buyerTokenAccount,
pythFeedAccount,
vault,
TOKEN_PROGRAM_ID,
SYSVAR_RENT_PUBKEY,
derived_state,
refTokenAccount,
);
ixs.push(ix);

return ixs;
};

export const devnet = {
utils: {
getNameAccountKeySync,
Expand All @@ -691,5 +802,6 @@ export const devnet = {
createSubdomain,
burnDomain,
transferSubdomain,
registerDomainNameV2,
},
};
20 changes: 20 additions & 0 deletions js/tests/devnet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,26 @@ test("Registration", async () => {
expect(res.value.err).toBe(null);
});

test("Registration V2", async () => {
const tx = new Transaction();

const ix = await devnet.bindings.registerDomainNameV2(
connection,
randomBytes(10).toString("hex"),
1_000,
OWNER2,
getAssociatedTokenAddressSync(NATIVE_MINT, OWNER2, true),
NATIVE_MINT,
);
tx.add(...ix);
const { blockhash } = await connection.getLatestBlockhash();
tx.recentBlockhash = blockhash;
tx.feePayer = OWNER2;
const res = await connection.simulateTransaction(tx);
console.log(res.value.logs);
expect(res.value.err).toBe(null);
});

test("Create", async () => {
const tx = new Transaction();

Expand Down

0 comments on commit cfc3b1e

Please sign in to comment.