feat: add getEntry and update createEntry to use it

This commit is contained in:
Derrick Hammer 2023-12-12 15:48:13 -05:00
parent 6a3eea92b7
commit aea236067e
Signed by: pcfreak30
GPG Key ID: C997C339BE476FF2
2 changed files with 78 additions and 8 deletions

View File

@ -33,6 +33,7 @@ import {
} from "./request.js"; } from "./request.js";
import { import {
createEntry, createEntry,
getEntry,
publishEntry, publishEntry,
subscribeToEntry, subscribeToEntry,
} from "./methods/registry.js"; } from "./methods/registry.js";
@ -143,6 +144,7 @@ export class S5Client {
subscribeToEntry = subscribeToEntry; subscribeToEntry = subscribeToEntry;
publishEntry = publishEntry; publishEntry = publishEntry;
createEntry = createEntry; createEntry = createEntry;
getEntry = getEntry;
/** /**
* The S5 Client which can be used to access S5-net. * The S5 Client which can be used to access S5-net.

View File

@ -1,9 +1,9 @@
import { DEFAULT_BASE_OPTIONS } from "../utils/options.js"; import { DEFAULT_BASE_OPTIONS } from "../utils/options.js";
import { CustomClientOptions, S5Client } from "../client.js"; import { CustomClientOptions, S5Client } from "../client.js";
import { ensureBytes } from "@noble/curves/abstract/utils"; import { ensureBytes, equalBytes } from "@noble/curves/abstract/utils";
import WS from "isomorphic-ws"; import WS from "isomorphic-ws";
import { buildRequestUrl } from "#request.js"; import { buildRequestUrl, ExecuteRequestError } from "#request.js";
import { import {
CID, CID,
createKeyPair, createKeyPair,
@ -19,6 +19,7 @@ import {
import { Buffer } from "buffer"; import { Buffer } from "buffer";
import { throwValidationError } from "../utils/validation.js"; import { throwValidationError } from "../utils/validation.js";
import { base64url } from "multiformats/bases/base64"; import { base64url } from "multiformats/bases/base64";
export const DEFAULT_GET_ENTRY_OPTIONS = { export const DEFAULT_GET_ENTRY_OPTIONS = {
...DEFAULT_BASE_OPTIONS, ...DEFAULT_BASE_OPTIONS,
endpointGetEntry: "/s5/registry", endpointGetEntry: "/s5/registry",
@ -91,6 +92,7 @@ export async function subscribeToEntry(
} }
const base64urlEncode = (d: Uint8Array) => base64url.encode(d).substring(1); const base64urlEncode = (d: Uint8Array) => base64url.encode(d).substring(1);
const base64urlDecode = (d: string) => base64url.decode(`u${d}`);
export async function publishEntry( export async function publishEntry(
this: S5Client, this: S5Client,
@ -135,15 +137,81 @@ export async function createEntry(
sk = createKeyPair(sk); sk = createKeyPair(sk);
} }
const entry = { let entry = await this.getEntry(sk.publicKey);
kp: sk,
data: cid.toRegistryEntry(),
revision,
};
const signedEntry = signRegistryEntry(entry); if (!entry) {
entry = {
pk: sk,
data: cid.toRegistryEntry(),
revision,
} as unknown as SignedRegistryEntry;
} else {
if (!equalBytes(sk.publicKey, entry.pk)) {
throwValidationError(
"entry.pk", // name of the variable
Buffer.from(entry.pk).toString("hex"), // actual value
"result", // valueKind (assuming it's a function parameter)
Buffer.from(sk.publicKey).toString("hex"), // expected description
);
}
entry.revision++;
}
const signedEntry = signRegistryEntry({
kp: sk,
data: entry.data,
revision: entry.revision,
});
await this.publishEntry(signedEntry); await this.publishEntry(signedEntry);
return signedEntry; return signedEntry;
} }
export async function getEntry(
this: S5Client,
publicKey: Uint8Array,
customOptions?: CustomRegistryOptions,
) {
const opts = {
...DEFAULT_GET_ENTRY_OPTIONS,
...this.customOptions,
...customOptions,
};
try {
const ret = await this.executeRequest({
...opts,
endpointPath: opts.endpointGetEntry,
method: "post",
data: {
pk: base64urlEncode(publicKey),
},
});
const signedEntry = {
pk: base64urlDecode(ret.data.pk),
revision: ret.data.revision,
data: base64urlDecode(ret.data.data),
signature: base64urlDecode(ret.data.signature),
} as SignedRegistryEntry;
if (!verifyRegistryEntry(signedEntry)) {
throwValidationError(
"signedEntry", // name of the variable
signedEntry, // actual value
"result", // valueKind (assuming it's a function parameter)
"a valid signed registry entry", // expected description
);
}
return signedEntry;
} catch (e) {
if ((e as ExecuteRequestError).responseStatus === 404) {
return undefined;
}
throw e;
}
}