Name Service
Name registry
name registry จะมีไว้เก็บข้อมูลเกี่ยวกับ domain name ซึ่งจะแบ่งเป็น 2 ส่วนคือ:
- The header
- The data
ข้อมูลของ domain name จะขึ้นต้นด้วย header ส่วนด้านล่างนี้คือ structure ของ header ใน JS:
import { PublicKey } from "@solana/web3.js";
import { Schema } from "borsh";
export class NameRegistryState {
parentName: PublicKey;
owner: PublicKey;
class: PublicKey;
data: Buffer | undefined;
static HEADER_LEN = 96;
static schema: Schema = new Map([
[
NameRegistryState,
{
kind: "struct",
fields: [
["parentName", [32]],
["owner", [32]],
["class", [32]],
],
},
],
]);
constructor(obj: {
parentName: Uint8Array;
owner: Uint8Array;
class: Uint8Array;
}) {
this.parentName = new PublicKey(obj.parentName);
this.owner = new PublicKey(obj.owner);
this.class = new PublicKey(obj.class);
}
}
export class NameRegistryState {
parentName: PublicKey;
owner: PublicKey;
class: PublicKey;
data: Buffer | undefined;
static HEADER_LEN = 96;
static schema: Schema = new Map([
[
NameRegistryState,
{
kind: "struct",
fields: [
["parentName", [32]],
["owner", [32]],
["class", [32]],
],
},
],
]);
constructor(obj: {
parentName: Uint8Array;
owner: Uint8Array;
class: Uint8Array;
}) {
this.parentName = new PublicKey(obj.parentName);
this.owner = new PublicKey(obj.owner);
this.class = new PublicKey(obj.class);
}
}
Resolving SOL domains
.SOL domains จะไม่ซ้ำ (unique), จดจำได้ง่าย (human-friendly) เป็น domain names ที่ถูกเปลี่ยนเป็น public keys. หลายๆ wallets ใช้มันเป็นทางเลือกในการส่ง tokens หรือ SOL เราสามารถเปลี่ยน .SOL domains เป็น public keys ได้ตามนี้:
import {
getHashedName,
getNameAccountKey,
NameRegistryState,
} from "@bonfida/spl-name-service";
import { Connection, clusterApiUrl, PublicKey } from "@solana/web3.js";
(async () => {
const domain = "levi.sol";
const hashedName = await getHashedName(domain.replace(".sol", ""));
const nameAccountKey = await getNameAccountKey(
hashedName,
undefined,
new PublicKey("58PwtjSDuFHuUkYjH9BYnnQKHfwo9reZhC2zMJv9JPkx") // SOL TLD Authority
);
const owner = await NameRegistryState.retrieve(
new Connection(clusterApiUrl("mainnet-beta")),
nameAccountKey
);
console.log(owner.registry.owner.toBase58());
// JUskoxS2PTiaBpxfGaAPgf3cUNhdeYFGMKdL6mZKKfR
})();
const domain = "levi.sol";
const hashedName = await getHashedName(domain.replace(".sol", ""));
const nameAccountKey = await getNameAccountKey(
hashedName,
undefined,
new PublicKey("58PwtjSDuFHuUkYjH9BYnnQKHfwo9reZhC2zMJv9JPkx") // SOL TLD Authority
);
const owner = await NameRegistryState.retrieve(
new Connection(clusterApiUrl("mainnet-beta")),
nameAccountKey
);
console.log(owner.registry.owner.toBase58());
// JUskoxS2PTiaBpxfGaAPgf3cUNhdeYFGMKdL6mZKKfR
Reverse look up
การทำ Reverse look up จะช่วยทำให้เราหา (resolve) domain name จาก public key ได้
import { performReverseLookup } from "@bonfida/spl-name-service";
import { PublicKey, Connection, clusterApiUrl } from "@solana/web3.js";
async () => {
const connection = new Connection(clusterApiUrl("mainnet-beta"));
// Public key of bonfida.sol
const domainKey = new PublicKey(
"Crf8hzfthWGbGbLTVCiqRqV5MVnbpHB1L9KQMd6gsinb"
);
const domainName = await performReverseLookup(connection, domainKey); // bonfida
};
// Public key of bonfida.sol
const domainKey = new PublicKey("Crf8hzfthWGbGbLTVCiqRqV5MVnbpHB1L9KQMd6gsinb");
const domainName = await performReverseLookup(connection, domainKey); // bonfida
Subdomain look up
ในการ resolve ส่วน subdomain เราจะต้อง:
- หา parent domain key
- หา subdomain key
- ดึงข้อมูล account info
import {
getHashedName,
getNameAccountKey,
NameRegistryState,
getDNSRecordAddress,
} from "@bonfida/spl-name-service";
import { Connection, clusterApiUrl, PublicKey } from "@solana/web3.js";
async () => {
const SOL_TLD_AUTHORITY = new PublicKey(
"58PwtjSDuFHuUkYjH9BYnnQKHfwo9reZhC2zMJv9JPkx"
);
const connection = new Connection(clusterApiUrl("mainnet-beta"));
// Resolution of demo.bonfida.sol
const parentDomain = "bonfida";
const subDomain = "demo";
// Step 1
const hashedParentDomain = await getHashedName(parentDomain);
const parentDomainKey = await getNameAccountKey(
hashedParentDomain,
undefined,
SOL_TLD_AUTHORITY
);
// Step 2
const subDomainKey = await getDNSRecordAddress(parentDomainKey, subDomain);
// Step 3
const registry = await NameRegistryState.retrieve(connection, subDomainKey);
};
const parentDomain = "bonfida";
const subDomain = "demo";
// Step 1
const hashedParentDomain = await getHashedName(mainDomain);
const parentDomainKey = await getNameAccountKey(
hashedParentDomain,
undefined,
SOL_TLD_AUTHORITY
);
// Step 2
const subDomainKey = await getDNSRecordAddress(parentDomainKey, subDomain);
// Step 3
const registry = await NameRegistryState.retrieve(connection, subDomainKey);
หาทุก domain names ที่ public key นี้เป็นเจ้าของ
เราสามารถดึงข้อมูลทุก domain names ของ wallet ใดๆ โดยใช้ getProgramAccounts
และ memcmp
filter
import { Connection, PublicKey } from "@solana/web3.js";
import { NAME_PROGRAM_ID } from "@bonfida/spl-name-service";
export async function findOwnedNameAccountsForUser(
connection: Connection,
userAccount: PublicKey
): Promise<PublicKey[]> {
const filters = [
{
memcmp: {
offset: 32,
bytes: userAccount.toBase58(),
},
},
];
const accounts = await connection.getProgramAccounts(NAME_PROGRAM_ID, {
filters,
});
return accounts.map((a) => a.publicKey);
}
export async function findOwnedNameAccountsForUser(
connection: Connection,
userAccount: PublicKey
): Promise<PublicKey[]> {
const filters = [
{
memcmp: {
offset: 32,
bytes: userAccount.toBase58(),
},
},
];
const accounts = await connection.getProgramAccounts(NAME_PROGRAM_ID, {
filters,
});
return accounts.map((a) => a.publicKey);
}
Resolve a Twitter handle
Twitter handles สามารถจะ ลงทะเบียนบน Solana name service ได้ และสามารถใช้เหมือน .SOL domain names ได้
import { PublicKey, clusterApiUrl, Connection } from "@solana/web3.js";
import { getHandleAndRegistryKey } from "@bonfida/spl-name-service";
async () => {
const connection = new Connection(clusterApiUrl("mainnet-beta"));
// Pubkey of the wallet you want to retrieve the Twitter handle
const pubkey = new PublicKey("FidaeBkZkvDqi1GXNEwB8uWmj9Ngx2HXSS5nyGRuVFcZ");
const [handle, registryKey] = await getHandleAndRegistryKey(
connection,
pubkey
);
};
// Pubkey of the wallet you want to retrieve the Twitter handle
const pubkey = new PublicKey("FidaeBkZkvDqi1GXNEwB8uWmj9Ngx2HXSS5nyGRuVFcZ");
const [handle, registryKey] = await getHandleAndRegistryKey(connection, pubkey);
Reverse look up of a Twitter handle
ในการหา SOL address ที่ associated กับ Twitter handle เราสามารถทำการ reverse look up ได้
import { getTwitterRegistry } from "@bonfida/spl-name-service";
import { Connection, clusterApiUrl } from "@solana/web3.js";
async () => {
const handle = "bonfida";
const connection = new Connection(clusterApiUrl("mainnet-beta"));
const registry = await getTwitterRegistry(connection, handle);
};
const handle = "bonfida";
const registry = await getTwitterRegistry(connection, handle);