Skip to content

Commit

Permalink
js: add getRecordV2 and getMultipleRecordsV2
Browse files Browse the repository at this point in the history
  • Loading branch information
dr497 committed Dec 13, 2023
1 parent d02dbb8 commit eae6054
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 7 deletions.
4 changes: 2 additions & 2 deletions js/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion js/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@bonfida/spl-name-service",
"version": "2.0.3",
"version": "2.0.4",
"license": "MIT",
"files": [
"dist"
Expand Down
88 changes: 84 additions & 4 deletions js/src/record_v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export const ETH_ROA_RECORDS = new Set<Record>([
export const verifyStaleness = async (
connection: Connection,
record: Record,
domain: string
domain: string,
) => {
const recordKey = getRecordV2Key(domain, record);
const owner = await resolve(connection, domain);
Expand Down Expand Up @@ -76,7 +76,7 @@ export const verifyRightOfAssociation = async (
connection: Connection,
record: Record,
domain: string,
verifier?: Buffer
verifier?: Buffer,
) => {
const recordKey = getRecordV2Key(domain, record);
const recordObj = await SnsRecord.retrieve(connection, recordKey);
Expand Down Expand Up @@ -139,7 +139,7 @@ export const SELF_SIGNED = new Set<Record>([
*/
export const deserializeRecordV2Content = (
content: Buffer,
record: Record
record: Record,
): string => {
const utf8Encoded = UTF8_ENCODED.has(record);

Expand Down Expand Up @@ -171,7 +171,7 @@ export const deserializeRecordV2Content = (
*/
export const serializeRecordV2Content = (
content: string,
record: Record
record: Record,
): Buffer => {
const utf8Encoded = UTF8_ENCODED.has(record);
if (utf8Encoded) {
Expand Down Expand Up @@ -213,3 +213,83 @@ export const getRecordV2Key = (domain: string, record: Record): PublicKey => {
const hashed = getHashedNameSync(`\x02`.concat(record as string));
return getNameAccountKeySync(hashed, CENTRAL_STATE_SNS_RECORDS, pubkey);
};

export interface GetRecordV2Options {
deserialize?: boolean;
}

export interface RecordResult {
retrievedRecord: SnsRecord;
record: Record;
deserializedContent?: string;
}

export type SingleRecordResult = Omit<RecordResult, "record">;

/**
* This function can be used to retrieve a specified record V2 for the given domain name
* @param connection The Solana RPC connection object
* @param domain The .sol domain name
* @param record The record to search for
* @returns
*/
export async function getRecordV2(
connection: Connection,
domain: string,
record: Record,
options: GetRecordV2Options = {},
): Promise<SingleRecordResult> {
const pubkey = getRecordV2Key(domain, record);
const retrievedRecord = await SnsRecord.retrieve(connection, pubkey);

if (options.deserialize) {
return {
retrievedRecord,
deserializedContent: deserializeRecordV2Content(
retrievedRecord.getContent(),
record,
),
};
}

return { retrievedRecord };
}

/**
* This function can be used to retrieve multiple records V2 for a given domain
* @param connection The Solana RPC connection object
* @param domain The .sol domain name
* @param record The record to search for
* @returns
*/
export async function getMultipleRecordsV2(
connection: Connection,
domain: string,
records: Record[],
options: GetRecordV2Options = {},
): Promise<(RecordResult | undefined)[]> {
const pubkeys = records.map((record) => getRecordV2Key(domain, record));
const retrievedRecords = await SnsRecord.retrieveBatch(connection, pubkeys);

if (options.deserialize) {
return retrievedRecords.map((e, idx) => {
if (!e) return undefined;
return {
retrievedRecord: e,
record: records[idx],
deserializedContent: deserializeRecordV2Content(
e.getContent(),
records[idx],
),
};
});
}

return retrievedRecords.map((e, idx) => {
if (!e) return undefined;
return {
retrievedRecord: e,
record: records[idx],
};
});
}
38 changes: 38 additions & 0 deletions js/tests/records-v2.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ require("dotenv").config();
import { test, expect } from "@jest/globals";
import {
deserializeRecordV2Content,
getMultipleRecordsV2,
getRecordV2,
serializeRecordV2Content,
} from "../src/record_v2";
import { Record } from "../src/types/record";
Expand Down Expand Up @@ -263,3 +265,39 @@ test("Create record for sub & update & verify staleness & delete", async () => {
const { value } = await connection.simulateTransaction(tx);
expect(value.err).toBe(null);
});

test("getRecordV2", async () => {
const domain = "wallet-guide-9.sol";
const items = [
{ record: Record.IPFS, value: "ipfs://test" },
{ record: Record.Email, value: "[email protected]" },
{ record: Record.Url, value: "https://google.com" },
];
for (let item of items) {
const res = await getRecordV2(connection, domain, item.record, {
deserialize: true,
});
expect(res.deserializedContent).toBe(item.value);
}
});

test("getMultipleRecordsV2", async () => {
const domain = "wallet-guide-9.sol";
const items = [
{ record: Record.IPFS, value: "ipfs://test" },
{ record: Record.Email, value: "[email protected]" },
{ record: Record.Url, value: "https://google.com" },
];
const res = await getMultipleRecordsV2(
connection,
domain,
items.map((e) => e.record),
{
deserialize: true,
},
);
for (let i = 0; i < items.length; i++) {
expect(items[i].value).toBe(res[i]?.deserializedContent);
expect(items[i].record).toBe(res[i]?.record);
}
});

0 comments on commit eae6054

Please sign in to comment.