Compare commits

...

3 Commits

Author SHA1 Message Date
semantic-release-bot 236bae5a90 chore(release): 0.1.0-develop.16 [skip ci]
# [0.1.0-develop.16](https://git.lumeweb.com/LumeWeb/s5-js/compare/v0.1.0-develop.15...v0.1.0-develop.16) (2023-12-12)

### Features

* add getEntry and update createEntry to use it ([aea2360](aea236067e))
2023-12-12 20:49:17 +00:00
Derrick Hammer 68f9c91c62
Merge remote-tracking branch 'origin/develop' into develop 2023-12-12 15:48:19 -05:00
Derrick Hammer aea236067e
feat: add getEntry and update createEntry to use it 2023-12-12 15:48:13 -05:00
5 changed files with 88 additions and 11 deletions

View File

@ -1,3 +1,10 @@
# [0.1.0-develop.16](https://git.lumeweb.com/LumeWeb/s5-js/compare/v0.1.0-develop.15...v0.1.0-develop.16) (2023-12-12)
### Features
* add getEntry and update createEntry to use it ([aea2360](https://git.lumeweb.com/LumeWeb/s5-js/commit/aea236067e6011502f6df2ec9856597b9fe5b1a9))
# [0.1.0-develop.15](https://git.lumeweb.com/LumeWeb/s5-js/compare/v0.1.0-develop.14...v0.1.0-develop.15) (2023-12-12) # [0.1.0-develop.15](https://git.lumeweb.com/LumeWeb/s5-js/compare/v0.1.0-develop.14...v0.1.0-develop.15) (2023-12-12)

4
npm-shrinkwrap.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "@lumeweb/s5-js", "name": "@lumeweb/s5-js",
"version": "0.1.0-develop.15", "version": "0.1.0-develop.16",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@lumeweb/s5-js", "name": "@lumeweb/s5-js",
"version": "0.1.0-develop.15", "version": "0.1.0-develop.16",
"dependencies": { "dependencies": {
"@lumeweb/libs5": "^0.1.0-develop.81", "@lumeweb/libs5": "^0.1.0-develop.81",
"@noble/hashes": "^1.3.2", "@noble/hashes": "^1.3.2",

View File

@ -1,6 +1,6 @@
{ {
"name": "@lumeweb/s5-js", "name": "@lumeweb/s5-js",
"version": "0.1.0-develop.15", "version": "0.1.0-develop.16",
"type": "module", "type": "module",
"module": "lib/index.js", "module": "lib/index.js",
"main": "lib/index.js", "main": "lib/index.js",

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;
}
}