Skip to content

Commit

Permalink
js: split nft bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
dr497 committed May 30, 2024
1 parent c93754e commit 57c35d2
Show file tree
Hide file tree
Showing 17 changed files with 257 additions and 229 deletions.
7 changes: 4 additions & 3 deletions js/rollup.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { nodeResolve } from "@rollup/plugin-node-resolve";
import replace from "@rollup/plugin-replace";
import babel from "@rollup/plugin-babel";
import { visualizer } from "rollup-plugin-visualizer";
import multiInput from 'rollup-plugin-multi-input';
import multiInput from "rollup-plugin-multi-input";

/**
* @type {import('rollup').RollupOptions}
Expand All @@ -19,6 +19,7 @@ export default {
"src/twitter/**/*.ts",
"src/resolve/**/*.ts",
"src/record/**/*.ts",
"src/nft/**/*.ts",
"src/bindings/**/*.ts",
"src/instructions/**/*.ts",
],
Expand All @@ -28,8 +29,8 @@ export default {
dir: "dist/",
format: "esm",
sourcemap: true,
entryFileNames: '[name].mjs',
exports: "named"
entryFileNames: "[name].mjs",
exports: "named",
},
{ dir: "dist/", format: "cjs", sourcemap: true },
],
Expand Down
2 changes: 1 addition & 1 deletion js/src/favorite-domain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { deserializeReverse } from "./utils/deserializeReverse";
import { getReverseKeyFromDomainKey } from "./utils/getReverseKeyFromDomainKey";
import { reverseLookup } from "./utils/reverseLookup";
import { FavouriteDomainNotFoundError } from "./error";
import { getDomainMint } from "./nft/name-tokenizer";
import { getDomainMint } from "./nft/getDomainMint";
import { NameRegistryState } from "./state";

export const NAME_OFFERS_ID = new PublicKey(
Expand Down
11 changes: 9 additions & 2 deletions js/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,15 @@ export * from "./instructions/transferInstruction";
export * from "./instructions/updateInstruction";
export * from "./instructions/types";

export * from "./nft";
export { getDomainMint } from "./nft/name-tokenizer";
export * from "./nft/getDomainMint";
export * from "./nft/retrieveNftOwnerV2";
export * from "./nft/retrieveNftOwner";
export * from "./nft/retrieveNfts";
export * from "./nft/getRecordFromMint";
export * from "./nft/retrieveRecords";
export * from "./nft/const";
export * from "./nft/state";

export * from "./favorite-domain";
export * from "./constants";
export * from "./int";
Expand Down
8 changes: 8 additions & 0 deletions js/src/nft/const.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { PublicKey } from "@solana/web3.js";
import { Buffer } from "buffer";

export const NAME_TOKENIZER_ID = new PublicKey(
"nftD3vbNkNqfj2Sd3HZwbpw4BxxKWr4AjGb9X38JeZk",
);

export const MINT_PREFIX = Buffer.from("tokenized_name");
10 changes: 10 additions & 0 deletions js/src/nft/getDomainMint.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { PublicKey } from "@solana/web3.js";
import { MINT_PREFIX, NAME_TOKENIZER_ID } from "./const";

export const getDomainMint = (domain: PublicKey) => {
const [mint] = PublicKey.findProgramAddressSync(
[MINT_PREFIX, domain.toBuffer()],
NAME_TOKENIZER_ID,
);
return mint;
};
41 changes: 41 additions & 0 deletions js/src/nft/getRecordFromMint.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import {
Connection,
PublicKey,
GetProgramAccountsFilter,
} from "@solana/web3.js";
import { NAME_TOKENIZER_ID } from "./const";
import { NftRecord } from "./state";

/**
* This function can be used to retrieve a NFT Record given a mint
*
* @param connection A solana RPC connection
* @param mint The mint of the NFT Record
* @returns
*/
export const getRecordFromMint = async (
connection: Connection,
mint: PublicKey,
) => {
const filters: GetProgramAccountsFilter[] = [
{ dataSize: NftRecord.LEN },
{
memcmp: {
offset: 0,
bytes: "3",
},
},
{
memcmp: {
offset: 1 + 1 + 32 + 32,
bytes: mint.toBase58(),
},
},
];

const result = await connection.getProgramAccounts(NAME_TOKENIZER_ID, {
filters,
});

return result;
};
165 changes: 0 additions & 165 deletions js/src/nft/index.ts

This file was deleted.

56 changes: 56 additions & 0 deletions js/src/nft/retrieveNftOwner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import {
Connection,
GetProgramAccountsFilter,
PublicKey,
} from "@solana/web3.js";
import { getDomainMint } from "./getDomainMint";
import { TOKEN_PROGRAM_ID, getMint } from "@solana/spl-token";

/**
* This function can be used to retrieve the owner of a tokenized domain name
*
* @param connection The solana connection object to the RPC node
* @param nameAccount The key of the domain name
* @returns
*/
export const retrieveNftOwner = async (
connection: Connection,
nameAccount: PublicKey,
) => {
try {
const mint = getDomainMint(nameAccount);

const mintInfo = await getMint(connection, mint);
if (mintInfo.supply.toString() === "0") {
return undefined;
}

const filters: GetProgramAccountsFilter[] = [
{
memcmp: {
offset: 0,
bytes: mint.toBase58(),
},
},
{
memcmp: {
offset: 64,
bytes: "2",
},
},
{ dataSize: 165 },
];

const result = await connection.getProgramAccounts(TOKEN_PROGRAM_ID, {
filters,
});

if (result.length != 1) {
return undefined;
}

return new PublicKey(result[0].account.data.slice(32, 64));
} catch {
return undefined;
}
};
37 changes: 37 additions & 0 deletions js/src/nft/retrieveNftOwnerV2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { PublicKey, Connection, SolanaJSONRPCError } from "@solana/web3.js";
import { getDomainMint } from "./getDomainMint";
import { AccountLayout } from "@solana/spl-token";

export const retrieveNftOwnerV2 = async (
connection: Connection,
nameAccount: PublicKey,
) => {
try {
const mint = getDomainMint(nameAccount);

const largestAccounts = await connection.getTokenLargestAccounts(mint);
if (largestAccounts.value.length === 0) {
return null;
}

const largestAccountInfo = await connection.getAccountInfo(
largestAccounts.value[0].address,
);

if (!largestAccountInfo) {
return null;
}

const decoded = AccountLayout.decode(largestAccountInfo.data);
if (decoded.amount.toString() === "1") {
return decoded.owner;
}
return null;
} catch (err) {
if (err instanceof SolanaJSONRPCError && err.code === -32602) {
// Mint does not exist
return null;
}
throw err;
}
};
Loading

0 comments on commit 57c35d2

Please sign in to comment.