Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

skynet-js

Package Overview
Dependencies
Maintainers
2
Versions
68
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

skynet-js - npm Package Compare versions

Comparing version 2.1.1 to 2.2.0

13

CHANGELOG.md
# Changelog
## [2.2.0]
### Changed
- Change SkyDB and Registry APIs.
## [2.1.1]
### Changed
- Improve timeout handling for SkyDB

@@ -10,3 +18,8 @@ - Extend end-to-end tests

### Added
- Add SkyDB support
### Changed
- Move to Typescript

@@ -13,0 +26,0 @@

39

dist/client.d.ts

@@ -5,22 +5,19 @@ import { AxiosResponse } from "axios";

import { downloadFile, downloadFileHns, getSkylinkUrl, getHnsUrl, getHnsresUrl, getMetadata, openFile, openFileHns, resolveHns } from "./download";
import { getFile, setFile } from "./skydb";
import { lookupRegistry, updateRegistry } from "./registry";
export declare type CustomClientOptions = {
/** authentication password to use */
APIKey?: string;
/** custom user agent header to set */
customUserAgent?: string;
/** optional callback to track upload progress */
onUploadProgress?: (progress: number, event: ProgressEvent) => void;
};
export declare class SkynetClient {
portalUrl: string;
customOptions: Record<string, unknown>;
customOptions: CustomClientOptions;
/**
* The Skynet Client which can be used to access Skynet.
* @constructor
* @param {string} [portalUrl="https://siasky.net"] - The portal URL to use to access Skynet, if specified. To use the default portal while passing custom options, use "".
* @param {Object} [customOptions={}] - Configuration for the client.
* @param {string} [customOptions.method] - HTTP method to use.
* @param {string} [customOptions.APIKey] - Authentication password to use.
* @param {string} [customOptions.customUserAgent=""] - Custom user agent header to set.
* @param {Object} [customOptions.data=null] - Data to send in a POST.
* @param {string} [customOptions.endpointPath=""] - The relative URL path of the portal endpoint to contact.
* @param {string} [customOptions.extraPath=""] - Extra path element to append to the URL.
* @param {Function} [customOptions.onUploadProgress] - Optional callback to track progress.
* @param {Object} [customOptions.query={}] - Query parameters to include in the URl.
* @param [portalUrl] The portal URL to use to access Skynet, if specified. To use the default portal while passing custom options, use ""
* @param [customOptions] Configuration for the client
*/
constructor(portalUrl?: string, customOptions?: {});
constructor(portalUrl?: string, customOptions?: CustomClientOptions);
uploadFile: typeof uploadFile;

@@ -44,6 +41,10 @@ uploadDirectory: typeof uploadDirectory;

resolveHns: typeof resolveHns;
getFile: typeof getFile;
setFile: typeof setFile;
lookupRegistry: typeof lookupRegistry;
updateRegistry: typeof updateRegistry;
db: {
getJSON: any;
setJSON: any;
};
registry: {
getEntry: any;
setEntry: any;
};
/**

@@ -50,0 +51,0 @@ * Creates and executes a request.

@@ -11,19 +11,10 @@ "use strict";

var download_1 = require("./download");
var utils_1 = require("./utils");
var skydb_1 = require("./skydb");
var registry_1 = require("./registry");
var utils_1 = require("./utils");
var SkynetClient = /** @class */ (function () {
/**
* The Skynet Client which can be used to access Skynet.
* @constructor
* @param {string} [portalUrl="https://siasky.net"] - The portal URL to use to access Skynet, if specified. To use the default portal while passing custom options, use "".
* @param {Object} [customOptions={}] - Configuration for the client.
* @param {string} [customOptions.method] - HTTP method to use.
* @param {string} [customOptions.APIKey] - Authentication password to use.
* @param {string} [customOptions.customUserAgent=""] - Custom user agent header to set.
* @param {Object} [customOptions.data=null] - Data to send in a POST.
* @param {string} [customOptions.endpointPath=""] - The relative URL path of the portal endpoint to contact.
* @param {string} [customOptions.extraPath=""] - Extra path element to append to the URL.
* @param {Function} [customOptions.onUploadProgress] - Optional callback to track progress.
* @param {Object} [customOptions.query={}] - Query parameters to include in the URl.
* @param [portalUrl] The portal URL to use to access Skynet, if specified. To use the default portal while passing custom options, use ""
* @param [customOptions] Configuration for the client
*/

@@ -52,7 +43,11 @@ function SkynetClient(portalUrl, customOptions) {

// SkyDB
this.getFile = skydb_1.getFile;
this.setFile = skydb_1.setFile;
this.db = {
getJSON: skydb_1.getJSON.bind(this),
setJSON: skydb_1.setJSON.bind(this)
};
// SkyDB helpers
this.lookupRegistry = registry_1.lookupRegistry;
this.updateRegistry = registry_1.updateRegistry;
this.registry = {
getEntry: registry_1.getEntry.bind(this),
setEntry: registry_1.setEntry.bind(this)
};
this.portalUrl = portalUrl;

@@ -81,7 +76,7 @@ this.customOptions = customOptions;

onUploadProgress: config.onUploadProgress &&
function (_a) {
var loaded = _a.loaded, total = _a.total;
var progress = loaded / total;
config.onUploadProgress(progress, { loaded: loaded, total: total });
}
function (event) {
var progress = event.loaded / event.total;
config.onUploadProgress(progress, event);
},
timeout: config.timeout
});

@@ -88,0 +83,0 @@ };

@@ -1,6 +0,9 @@

import { RegistryValue } from "./registry";
import { FileID } from "./skydb";
import { RegistryEntry } from "./registry";
import { pki } from "node-forge";
export declare type PublicKey = pki.ed25519.NativeBuffer;
export declare type SecretKey = pki.ed25519.NativeBuffer;
export declare type Signature = pki.ed25519.NativeBuffer;
export declare function HashAll(...args: any[]): Uint8Array;
export declare function HashRegistryValue(registryValue: RegistryValue): Uint8Array;
export declare function HashFileID(fileID: FileID): Uint8Array;
export declare function HashDataKey(datakey: string): Uint8Array;
export declare function HashRegistryEntry(registryEntry: RegistryEntry): Uint8Array;
//# sourceMappingURL=crypto.d.ts.map

@@ -6,3 +6,3 @@ "use strict";

exports.__esModule = true;
exports.HashFileID = exports.HashRegistryValue = exports.HashAll = void 0;
exports.HashRegistryEntry = exports.HashDataKey = exports.HashAll = void 0;
var blakejs_1 = __importDefault(require("blakejs"));

@@ -27,27 +27,28 @@ var utils_1 = require("./utils");

exports.HashAll = HashAll;
// HashRegistryValue hashes the given registry value
function HashRegistryValue(registryValue) {
return HashAll(registryValue.tweak, encodeString(registryValue.data), encodeUint8(registryValue.revision));
// Hash the given data key.
function HashDataKey(datakey) {
return HashAll(encodeString(datakey));
}
exports.HashRegistryValue = HashRegistryValue;
// HashFileID hashes the given fileID
function HashFileID(fileID) {
return HashAll(encodeUint8(fileID.version), encodeString(fileID.applicationID), encodeUint8(fileID.fileType), encodeString(fileID.filename));
exports.HashDataKey = HashDataKey;
// Hashes the given registry entry.
function HashRegistryEntry(registryEntry) {
return HashAll(HashDataKey(registryEntry.datakey), encodeString(registryEntry.data), encodeNumber(registryEntry.revision));
}
exports.HashFileID = HashFileID;
// encodeUint8 converts the given number into a uint8 array
function encodeUint8(num) {
if (num > 255) {
throw new Error("overflow");
exports.HashRegistryEntry = HashRegistryEntry;
// encodeNumber converts the given number into a uint8 array
function encodeNumber(num) {
var encoded = new Uint8Array(8);
for (var index = 0; index < encoded.length; index++) {
var byte = num & 0xff;
encoded[index] = byte;
num = num >> 8;
}
var encoded = new Uint8Array(8);
encoded[0] = num;
return encoded;
}
// encodeUint8 converts the given string into a uint8 array
// encodeString converts the given string into a uint8 array
function encodeString(str) {
var encoded = new Uint8Array(8 + str.length);
encoded.set(encodeUint8(str.length));
encoded.set(encodeNumber(str.length));
encoded.set(utils_1.stringToUint8Array(str), 8);
return encoded;
}

@@ -0,1 +1,2 @@

import { SkynetClient } from "./client";
/**

@@ -7,3 +8,3 @@ * Initiates a download of the content of the skylink within the browser.

*/
export declare function downloadFile(skylink: string, customOptions?: {}): void;
export declare function downloadFile(this: SkynetClient, skylink: string, customOptions?: any): void;
/**

@@ -15,7 +16,7 @@ * Initiates a download of the content of the skylink at the Handshake domain.

*/
export declare function downloadFileHns(domain: string, customOptions?: {}): Promise<void>;
export declare function getSkylinkUrl(skylink: string, customOptions?: {}): string;
export declare function getHnsUrl(domain: string, customOptions?: {}): string;
export declare function getHnsresUrl(domain: string, customOptions?: {}): string;
export declare function getMetadata(skylink: string, customOptions?: {}): Promise<void>;
export declare function downloadFileHns(this: SkynetClient, domain: string, customOptions?: any): Promise<void>;
export declare function getSkylinkUrl(this: SkynetClient, skylink: string, customOptions?: any): string;
export declare function getHnsUrl(this: SkynetClient, domain: string, customOptions?: any): string;
export declare function getHnsresUrl(this: SkynetClient, domain: string, customOptions?: any): string;
export declare function getMetadata(this: SkynetClient, skylink: string, customOptions?: any): Promise<any>;
/**

@@ -27,3 +28,3 @@ * Opens the content of the skylink within the browser.

*/
export declare function openFile(skylink: string, customOptions?: {}): void;
export declare function openFile(this: SkynetClient, skylink: string, customOptions?: {}): void;
/**

@@ -35,3 +36,3 @@ * Opens the content of the skylink from the given Handshake domain within the browser.

*/
export declare function openFileHns(domain: string, customOptions?: {}): Promise<void>;
export declare function openFileHns(this: SkynetClient, domain: string, customOptions?: {}): Promise<void>;
/**

@@ -42,3 +43,3 @@ * @param {string} domain - Handshake resolver domain.

*/
export declare function resolveHns(domain: string, customOptions?: {}): Promise<any>;
export declare function resolveHns(this: SkynetClient, domain: string, customOptions?: {}): Promise<any>;
//# sourceMappingURL=download.d.ts.map

@@ -66,3 +66,3 @@ "use strict";

// Download the url.
window.location = url;
window.location.assign(url);
}

@@ -84,3 +84,3 @@ exports.downloadFile = downloadFile;

// Download the url.
window.location = url;
window.location.assign(url);
return [2 /*return*/];

@@ -116,6 +116,20 @@ });

return __awaiter(this, void 0, void 0, function () {
var opts;
var opts, url, response, error_1;
return __generator(this, function (_a) {
opts = __assign(__assign(__assign({}, defaultDownloadOptions), this.customOptions), customOptions);
throw new Error("Unimplemented");
switch (_a.label) {
case 0:
opts = __assign(__assign(__assign({}, defaultDownloadOptions), this.customOptions), customOptions);
url = this.getSkylinkUrl(skylink, opts);
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, this.executeRequest(__assign(__assign({}, opts), { method: "head", url: url }))];
case 2:
response = _a.sent();
return [2 /*return*/, response.headers["skynet-file-metadata"] ? JSON.parse(response.headers["skynet-file-metadata"]) : {}];
case 3:
error_1 = _a.sent();
throw new Error("Error getting skynet-file-metadata from skylink");
case 4: return [2 /*return*/];
}
});

@@ -122,0 +136,0 @@ });

@@ -1,6 +0,7 @@

export declare function addSkykey(skykey: string, customOptions?: {}): Promise<void>;
export declare function createSkykey(skykeyName: string, skykeyType: string, customOptions?: {}): Promise<void>;
export declare function getSkykeyById(skykeyId: string, customOptions?: {}): Promise<void>;
export declare function getSkykeyByName(skykeyName: string, customOptions?: {}): Promise<void>;
export declare function getSkykeys(customOptions?: {}): Promise<void>;
import { SkynetClient } from "./client";
export declare function addSkykey(this: SkynetClient, skykey: string, customOptions?: {}): Promise<void>;
export declare function createSkykey(this: SkynetClient, skykeyName: string, skykeyType: string, customOptions?: {}): Promise<void>;
export declare function getSkykeyById(this: SkynetClient, skykeyId: string, customOptions?: {}): Promise<void>;
export declare function getSkykeyByName(this: SkynetClient, skykeyName: string, customOptions?: {}): Promise<void>;
export declare function getSkykeys(this: SkynetClient, customOptions?: {}): Promise<void>;
//# sourceMappingURL=encryption.d.ts.map
export { SkynetClient } from "./client";
export {} from "./download";
export {} from "./encryption";
export {} from "./upload";
export { FILEID_V1, FileType, FileID, User, SkyFile } from "./skydb";
export type { SignedRegistryValue, RegistryValue } from "./registry";
export { defaultPortalUrl, defaultSkynetPortalUrl, getRelativeFilePath, getRootDirectory, parseSkylink, uriHandshakePrefix, uriHandshakeResolverPrefix, uriSkynetPrefix, } from "./utils";
export type { PublicKey, SecretKey, Signature } from "./crypto";
export type { SignedRegistryEntry, RegistryEntry } from "./registry";
export { defaultPortalUrl, defaultSkynetPortalUrl, getRelativeFilePath, getRootDirectory, keyPairFromSeed, parseSkylink, uriHandshakePrefix, uriHandshakeResolverPrefix, uriSkynetPrefix, } from "./utils";
//# sourceMappingURL=index.d.ts.map

@@ -10,11 +10,5 @@ "use strict";

exports.__esModule = true;
exports.uriSkynetPrefix = exports.uriHandshakeResolverPrefix = exports.uriHandshakePrefix = exports.parseSkylink = exports.getRootDirectory = exports.getRelativeFilePath = exports.defaultSkynetPortalUrl = exports.defaultPortalUrl = exports.SkyFile = exports.User = exports.FileID = exports.FileType = exports.FILEID_V1 = exports.SkynetClient = void 0;
exports.uriSkynetPrefix = exports.uriHandshakeResolverPrefix = exports.uriHandshakePrefix = exports.parseSkylink = exports.keyPairFromSeed = exports.getRootDirectory = exports.getRelativeFilePath = exports.defaultSkynetPortalUrl = exports.defaultPortalUrl = exports.SkynetClient = void 0;
var client_1 = require("./client");
__createBinding(exports, client_1, "SkynetClient");
var skydb_1 = require("./skydb");
__createBinding(exports, skydb_1, "FILEID_V1");
__createBinding(exports, skydb_1, "FileType");
__createBinding(exports, skydb_1, "FileID");
__createBinding(exports, skydb_1, "User");
__createBinding(exports, skydb_1, "SkyFile");
var utils_1 = require("./utils");

@@ -25,2 +19,3 @@ __createBinding(exports, utils_1, "defaultPortalUrl");

__createBinding(exports, utils_1, "getRootDirectory");
__createBinding(exports, utils_1, "keyPairFromSeed");
__createBinding(exports, utils_1, "parseSkylink");

@@ -27,0 +22,0 @@ __createBinding(exports, utils_1, "uriHandshakePrefix");

@@ -1,14 +0,21 @@

import { pki } from "node-forge";
import { FileID, User } from "./skydb";
export declare type RegistryValue = {
tweak: Uint8Array;
import { SkynetClient } from "./client";
import { PublicKey, Signature } from "./crypto";
export declare type RegistryEntry = {
datakey: string;
data: string;
revision: number;
};
export declare type SignedRegistryValue = {
value: RegistryValue;
signature: pki.ed25519.NativeBuffer;
export declare type SignedRegistryEntry = {
entry: RegistryEntry;
signature: Signature;
};
export declare function lookupRegistry(user: User, fileID: FileID, customOptions?: {}): Promise<SignedRegistryValue | null>;
export declare function updateRegistry(user: User, fileID: FileID, srv: SignedRegistryValue, customOptions?: {}): Promise<boolean>;
/**
* Gets the registry entry corresponding to the publicKey and dataKey.
* @param publicKey - The user public key.
* @param dataKey - The key of the data to fetch for the given user.
* @param [customOptions={}] - Additional settings that can optionally be set.
* @param [customOptions.timeout=5000] - Timeout in ms for the registry lookup.
*/
export declare function getEntry(this: SkynetClient, publickey: PublicKey, datakey: string, customOptions?: {}): Promise<SignedRegistryEntry | null>;
export declare function setEntry(this: SkynetClient, publickey: PublicKey, datakey: string, entry: RegistryEntry, signature: Signature, customOptions?: {}): Promise<void>;
//# sourceMappingURL=registry.d.ts.map

@@ -50,7 +50,15 @@ "use strict";

exports.__esModule = true;
exports.updateRegistry = exports.lookupRegistry = void 0;
exports.setEntry = exports.getEntry = void 0;
var utils_1 = require("./utils");
var buffer_1 = require("buffer");
var defaultRegistryOptions = __assign({}, utils_1.defaultOptions("/skynet/registry"));
function lookupRegistry(user, fileID, customOptions) {
var crypto_1 = require("./crypto");
var defaultRegistryOptions = __assign(__assign({}, utils_1.defaultOptions("/skynet/registry")), { timeout: 5000 });
/**
* Gets the registry entry corresponding to the publicKey and dataKey.
* @param publicKey - The user public key.
* @param dataKey - The key of the data to fetch for the given user.
* @param [customOptions={}] - Additional settings that can optionally be set.
* @param [customOptions.timeout=5000] - Timeout in ms for the registry lookup.
*/
function getEntry(publickey, datakey, customOptions) {
if (customOptions === void 0) { customOptions = {}; }

@@ -67,10 +75,5 @@ return __awaiter(this, void 0, void 0, function () {

return [4 /*yield*/, this.executeRequest(__assign(__assign({}, opts), { method: "get", query: {
publickey: "ed25519:" + user.id,
fileid: buffer_1.Buffer.from(JSON.stringify({
version: fileID.version,
applicationid: fileID.applicationID,
filetype: fileID.fileType,
filename: fileID.filename
})).toString("hex")
} }))];
publickey: "ed25519:" + publickey.toString("hex"),
datakey: buffer_1.Buffer.from(crypto_1.HashDataKey(datakey)).toString("hex")
}, timeout: opts.timeout }))];
case 2:

@@ -86,11 +89,12 @@ response = _a.sent();

return [2 /*return*/, {
value: {
tweak: Uint8Array.from(buffer_1.Buffer.from(response.data.tweak)),
entry: {
datakey: datakey,
data: buffer_1.Buffer.from(utils_1.hexToUint8Array(response.data.data)).toString(),
// TODO: Handle uint64 properly.
revision: parseInt(response.data.revision, 10)
},
signature: response.data.signature
signature: buffer_1.Buffer.from(utils_1.hexToUint8Array(response.data.signature))
}];
}
throw new Error("unexpected response status code " + response.status);
return [2 /*return*/, null];
}

@@ -100,7 +104,7 @@ });

}
exports.lookupRegistry = lookupRegistry;
function updateRegistry(user, fileID, srv, customOptions) {
exports.getEntry = getEntry;
function setEntry(publickey, datakey, entry, signature, customOptions) {
if (customOptions === void 0) { customOptions = {}; }
return __awaiter(this, void 0, void 0, function () {
var opts, response, err_2;
var opts, data;
return __generator(this, function (_a) {

@@ -110,32 +114,16 @@ switch (_a.label) {

opts = __assign(__assign(__assign({}, defaultRegistryOptions), this.customOptions), customOptions);
_a.label = 1;
data = {
publickey: {
algorithm: "ed25519",
key: Array.from(publickey)
},
datakey: buffer_1.Buffer.from(crypto_1.HashDataKey(datakey)).toString("hex"),
revision: entry.revision,
data: Array.from(buffer_1.Buffer.from(entry.data)),
signature: Array.from(signature)
};
return [4 /*yield*/, this.executeRequest(__assign(__assign({}, opts), { method: "post", data: data }))];
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, this.executeRequest(__assign(__assign({}, opts), { method: "post", data: {
publickey: {
algorithm: "ed25519",
key: Array.from(user.publicKey)
},
fileid: {
version: fileID.version,
applicationid: fileID.applicationID,
filetype: fileID.fileType,
filename: fileID.filename
},
revision: srv.value.revision,
data: Array.from(Uint8Array.from(buffer_1.Buffer.from(srv.value.data))),
signature: Array.from(Uint8Array.from(srv.signature))
} }))];
case 2:
response = _a.sent();
return [3 /*break*/, 4];
case 3:
err_2 = _a.sent();
// unfortunately axios rejects anything that's not >= 200 and < 300
return [2 /*return*/, false];
case 4:
if (response.status === 204) {
return [2 /*return*/, true];
}
throw new Error("unexpected response status code " + response.status);
_a.sent();
return [2 /*return*/];
}

@@ -145,2 +133,2 @@ });

}
exports.updateRegistry = updateRegistry;
exports.setEntry = setEntry;

@@ -1,27 +0,15 @@

import { pki } from "node-forge";
export declare const FILEID_V1 = 1;
export declare enum FileType {
Invalid = 0,
PublicUnencrypted = 1
}
export declare function getFile(user: User, fileID: FileID): Promise<SkyFile>;
export declare function setFile(user: User, fileID: FileID, file: SkyFile): Promise<boolean>;
export declare class FileID {
applicationID: string;
fileType: FileType;
filename: string;
version: number;
constructor(applicationID: string, fileType: FileType, filename: string);
}
export declare class User {
id: string;
publicKey: pki.ed25519.NativeBuffer;
protected secretKey: pki.ed25519.NativeBuffer;
constructor(username: string, password: string);
sign(options: pki.ed25519.ToNativeBufferParameters): pki.ed25519.NativeBuffer;
}
export declare class SkyFile {
file: File;
constructor(file: File);
}
import { SkynetClient } from "./client";
import { PublicKey, SecretKey } from "./crypto";
/**
* Gets the JSON object corresponding to the publicKey and dataKey.
* @param publicKey - The user public key.
* @param dataKey - The key of the data to fetch for the given user.
* @param [customOptions={}] - Additional settings that can optionally be set.
* @param [customOptions.timeout=5000] - Timeout in ms for the registry lookup.
*/
export declare function getJSON(this: SkynetClient, publicKey: PublicKey, dataKey: string, customOptions?: {}): Promise<{
data: Record<string, unknown>;
revision: number;
} | null>;
export declare function setJSON(this: SkynetClient, privateKey: SecretKey, dataKey: string, json: Record<string, unknown>, revision?: number, customOptions?: {}): Promise<void>;
//# sourceMappingURL=skydb.d.ts.map

@@ -50,34 +50,32 @@ "use strict";

exports.__esModule = true;
exports.SkyFile = exports.User = exports.FileID = exports.setFile = exports.getFile = exports.FileType = exports.FILEID_V1 = void 0;
exports.setJSON = exports.getJSON = void 0;
var node_forge_1 = require("node-forge");
var crypto_1 = require("./crypto");
var utils_1 = require("./utils");
// FILEID_V1 represents version 1 of the FileID object
exports.FILEID_V1 = 1;
// FileType is the type of the file
var FileType;
(function (FileType) {
FileType[FileType["Invalid"] = 0] = "Invalid";
FileType[FileType["PublicUnencrypted"] = 1] = "PublicUnencrypted";
})(FileType = exports.FileType || (exports.FileType = {}));
// getFile will lookup the entry for given skappID and filename, if it exists it
// will try and download the file behind the skylink it has found in the entry.
function getFile(user, fileID) {
/**
* Gets the JSON object corresponding to the publicKey and dataKey.
* @param publicKey - The user public key.
* @param dataKey - The key of the data to fetch for the given user.
* @param [customOptions={}] - Additional settings that can optionally be set.
* @param [customOptions.timeout=5000] - Timeout in ms for the registry lookup.
*/
function getJSON(publicKey, dataKey, customOptions) {
if (customOptions === void 0) { customOptions = {}; }
return __awaiter(this, void 0, void 0, function () {
var existing, skylink, response, metadata, file;
var opts, entry, skylink, response;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.lookupRegistry(user, fileID)];
case 0:
opts = __assign(__assign({}, this.customOptions), customOptions);
return [4 /*yield*/, this.registry.getEntry(publicKey, dataKey, opts)];
case 1:
existing = _a.sent();
if (!existing) {
throw new Error("not found");
entry = _a.sent();
if (entry === null) {
return [2 /*return*/, null];
}
skylink = existing.value.data;
return [4 /*yield*/, this.executeRequest(__assign(__assign({}, this.customOptions), { method: "get", url: this.getSkylinkUrl(skylink) }))];
skylink = utils_1.parseSkylink(entry.entry.data);
return [4 /*yield*/, this.executeRequest(__assign(__assign({}, opts), { method: "get", url: this.getSkylinkUrl(skylink) }))];
case 2:
response = _a.sent();
metadata = JSON.parse(response.headers["skynet-file-metadata"]);
file = new SkyFile(new File([response.data], metadata.filename, { type: response.headers["content-type"] }));
return [2 /*return*/, file];
return [2 /*return*/, { data: response.data, revision: entry.entry.revision }];
}

@@ -87,36 +85,56 @@ });

}
exports.getFile = getFile;
// setFile uploads a file and sets updates the registry
function setFile(user, fileID, file) {
exports.getJSON = getJSON;
function setJSON(privateKey, dataKey, json, revision, customOptions) {
if (customOptions === void 0) { customOptions = {}; }
return __awaiter(this, void 0, void 0, function () {
var customFilename, skylink, existing, error_1, value, signature, updated;
var opts, file, skylink, publicKey, entry_1, err_1, entry, signature;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
customFilename = fileID.filename;
return [4 /*yield*/, this.uploadFile(file.file, { customFilename: customFilename })];
opts = __assign(__assign({}, this.customOptions), customOptions);
file = new File([JSON.stringify(json)], dataKey, { type: "application/json" });
return [4 /*yield*/, this.uploadFileRequest(file, opts)];
case 1:
skylink = _a.sent();
skylink = (_a.sent()).skylink;
publicKey = node_forge_1.pki.ed25519.publicKeyFromPrivateKey({ privateKey: privateKey });
if (!!revision) return [3 /*break*/, 6];
_a.label = 2;
case 2:
_a.trys.push([2, 4, , 5]);
return [4 /*yield*/, utils_1.promiseTimeout(this.lookupRegistry(user, fileID), 2000)];
return [4 /*yield*/, this.registry.getEntry(publicKey, dataKey, opts)];
case 3:
existing = _a.sent();
entry_1 = _a.sent();
revision = entry_1.entry.revision + 1;
return [3 /*break*/, 5];
case 4:
error_1 = _a.sent();
existing = null;
err_1 = _a.sent();
revision = 0;
return [3 /*break*/, 5];
case 5:
value = {
tweak: crypto_1.HashFileID(fileID),
// Verify here if we fetched the entry earlier.
if (entry_1 &&
!node_forge_1.pki.ed25519.verify({
message: crypto_1.HashRegistryEntry(entry_1.entry),
signature: entry_1.signature,
publicKey: publicKey
})) {
throw new Error("could not verify signature from retrieved, signed registry entry -- possible corrupted entry");
}
_a.label = 6;
case 6:
entry = {
datakey: dataKey,
data: utils_1.trimUriPrefix(skylink, utils_1.uriSkynetPrefix),
revision: existing ? existing.value.revision + 1 : 0
revision: revision
};
signature = user.sign({ message: crypto_1.HashRegistryValue(value) });
return [4 /*yield*/, this.updateRegistry(user, fileID, { value: value, signature: signature })];
case 6:
updated = _a.sent();
return [2 /*return*/, updated];
signature = node_forge_1.pki.ed25519.sign({
message: crypto_1.HashRegistryEntry(entry),
privateKey: privateKey
});
// update the registry
return [4 /*yield*/, this.registry.setEntry(publicKey, dataKey, entry, signature)];
case 7:
// update the registry
_a.sent();
return [2 /*return*/];
}

@@ -126,41 +144,2 @@ });

}
exports.setFile = setFile;
// FileID represents a File
var FileID = /** @class */ (function () {
function FileID(applicationID, fileType, filename) {
this.applicationID = applicationID;
this.fileType = fileType;
this.filename = filename;
this.version = exports.FILEID_V1;
// validate file type
if (fileType !== FileType.PublicUnencrypted) {
throw new Error("invalid file type");
}
}
return FileID;
}());
exports.FileID = FileID;
// User represents a user entity and can be used to sign.
var User = /** @class */ (function () {
// NOTE: username should be the user's email address as ideally it's unique
function User(username, password) {
var seed = node_forge_1.pkcs5.pbkdf2(password, username, 1000, 32);
var _a = node_forge_1.pki.ed25519.generateKeyPair({ seed: seed }), publicKey = _a.publicKey, privateKey = _a.privateKey;
this.publicKey = publicKey;
this.secretKey = privateKey;
this.id = publicKey.toString("hex");
}
User.prototype.sign = function (options) {
return node_forge_1.pki.ed25519.sign(__assign(__assign({}, options), { privateKey: this.secretKey }));
};
return User;
}());
exports.User = User;
// SkyFile wraps a File.
var SkyFile = /** @class */ (function () {
function SkyFile(file) {
this.file = file;
}
return SkyFile;
}());
exports.SkyFile = SkyFile;
exports.setJSON = setJSON;

@@ -1,3 +0,9 @@

export declare function uploadFile(file: File, customOptions?: {}): Promise<string>;
export declare function uploadFileRequest(file: File, customOptions?: {}): Promise<any>;
import { SkynetClient, CustomClientOptions } from "./client";
declare type CustomUploadOptions = {
portalFileFieldname?: string;
portalDirectoryFileFieldname?: string;
customFilename?: string;
} & CustomClientOptions;
export declare function uploadFile(this: SkynetClient, file: File, customOptions?: CustomUploadOptions): Promise<string>;
export declare function uploadFileRequest(this: SkynetClient, file: File, customOptions?: CustomUploadOptions): Promise<any>;
/**

@@ -18,4 +24,5 @@ * Uploads a local directory to Skynet.

*/
export declare function uploadDirectory(directory: any, filename: string, customOptions?: {}): Promise<string>;
export declare function uploadDirectoryRequest(directory: any, filename: string, customOptions?: {}): Promise<any>;
export declare function uploadDirectory(this: SkynetClient, directory: any, filename: string, customOptions?: CustomUploadOptions): Promise<string>;
export declare function uploadDirectoryRequest(this: SkynetClient, directory: any, filename: string, customOptions?: CustomUploadOptions): Promise<any>;
export {};
//# sourceMappingURL=upload.d.ts.map

@@ -54,3 +54,2 @@ "use strict";

function uploadFile(file, customOptions) {
if (customOptions === void 0) { customOptions = {}; }
return __awaiter(this, void 0, void 0, function () {

@@ -70,3 +69,2 @@ var response;

function uploadFileRequest(file, customOptions) {
if (customOptions === void 0) { customOptions = {}; }
return __awaiter(this, void 0, void 0, function () {

@@ -111,3 +109,2 @@ var opts, formData, data;

function uploadDirectory(directory, filename, customOptions) {
if (customOptions === void 0) { customOptions = {}; }
return __awaiter(this, void 0, void 0, function () {

@@ -127,3 +124,2 @@ var response;

function uploadDirectoryRequest(directory, filename, customOptions) {
if (customOptions === void 0) { customOptions = {}; }
return __awaiter(this, void 0, void 0, function () {

@@ -159,3 +155,3 @@ var opts, formData, data;

function ensureFileObjectConsistency(file) {
return new File([file], file.name, { type: file.type });
return new File([file], file.name, { type: utils_1.getFileMimeType(file) });
}

@@ -0,1 +1,2 @@

import { PublicKey, SecretKey } from "./crypto";
export declare const defaultSkynetPortalUrl = "https://siasky.net";

@@ -6,3 +7,7 @@ export declare const uriHandshakePrefix = "hns:";

export declare function addUrlQuery(url: string, query: Record<string, unknown>): string;
export declare function defaultOptions(endpointPath: string): Record<string, unknown>;
export declare function defaultOptions(endpointPath: string): {
endpointPath: string;
APIKey: string;
customUserAgent: string;
};
export declare function defaultPortalUrl(): string;

@@ -12,2 +17,10 @@ export declare function getRelativeFilePath(file: File): string;

/**
* Generates a public and private key from a provided, secure seed.
* @param seed - A secure seed.
*/
export declare function keyPairFromSeed(seed: string): {
publicKey: PublicKey;
privateKey: SecretKey;
};
/**
* Properly joins paths together to create a URL. Takes a variable number of

@@ -20,6 +33,10 @@ * arguments.

export declare function randomNumber(low: number, high: number): number;
export declare function promiseTimeout(promise: any, ms: number): Promise<any>;
export declare function stringToUint8Array(str: string): Uint8Array;
export declare function hexToUint8Array(str: string): Uint8Array;
export declare function readData(file: File): Promise<string | ArrayBuffer>;
/**
* Get the file mime type. In case the type is not provided, use mime-db and try
* to guess the file type based on the extension.
*/
export declare function getFileMimeType(file: File): string;
//# sourceMappingURL=utils.d.ts.map
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __spreadArrays = (this && this.__spreadArrays) || function () {

@@ -49,3 +13,5 @@ for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;

exports.__esModule = true;
exports.readData = exports.hexToUint8Array = exports.stringToUint8Array = exports.promiseTimeout = exports.randomNumber = exports.trimUriPrefix = exports.parseSkylink = exports.makeUrl = exports.getRootDirectory = exports.getRelativeFilePath = exports.defaultPortalUrl = exports.defaultOptions = exports.addUrlQuery = exports.uriSkynetPrefix = exports.uriHandshakeResolverPrefix = exports.uriHandshakePrefix = exports.defaultSkynetPortalUrl = void 0;
exports.getFileMimeType = exports.readData = exports.hexToUint8Array = exports.stringToUint8Array = exports.randomNumber = exports.trimUriPrefix = exports.parseSkylink = exports.makeUrl = exports.keyPairFromSeed = exports.getRootDirectory = exports.getRelativeFilePath = exports.defaultPortalUrl = exports.defaultOptions = exports.addUrlQuery = exports.uriSkynetPrefix = exports.uriHandshakeResolverPrefix = exports.uriHandshakePrefix = exports.defaultSkynetPortalUrl = void 0;
var node_forge_1 = require("node-forge");
var mime_db_1 = __importDefault(require("mime-db"));
var path_browserify_1 = __importDefault(require("path-browserify"));

@@ -98,2 +64,12 @@ var url_parse_1 = __importDefault(require("url-parse"));

/**
* Generates a public and private key from a provided, secure seed.
* @param seed - A secure seed.
*/
function keyPairFromSeed(seed) {
// Get a 32-byte seed.
seed = node_forge_1.pkcs5.pbkdf2(seed, "", 1000, 32, node_forge_1.md.sha256.create());
return node_forge_1.pki.ed25519.generateKeyPair({ seed: seed });
}
exports.keyPairFromSeed = keyPairFromSeed;
/**
* Properly joins paths together to create a URL. Takes a variable number of

@@ -152,16 +128,2 @@ * arguments.

exports.randomNumber = randomNumber;
function promiseTimeout(promise, ms) {
return __awaiter(this, void 0, void 0, function () {
var timeout;
return __generator(this, function (_a) {
timeout = new Promise(function (resolve, reject) {
setTimeout(function () {
reject("Timed out after " + ms + "ms");
}, ms);
});
return [2 /*return*/, Promise.race([promise, timeout])];
});
});
}
exports.promiseTimeout = promiseTimeout;
// stringToUint8Array converts a string to a uint8 array

@@ -188,1 +150,20 @@ function stringToUint8Array(str) {

exports.readData = readData;
/**
* Get the file mime type. In case the type is not provided, use mime-db and try
* to guess the file type based on the extension.
*/
function getFileMimeType(file) {
var _a, _b;
if (file.type)
return file.type;
var extension = file.name.slice(file.name.lastIndexOf(".") + 1);
if (extension) {
for (var type in mime_db_1["default"]) {
if ((_b = (_a = mime_db_1["default"][type]) === null || _a === void 0 ? void 0 : _a.extensions) === null || _b === void 0 ? void 0 : _b.includes(extension)) {
return type;
}
}
}
return "";
}
exports.getFileMimeType = getFileMimeType;
{
"name": "skynet-js",
"version": "2.1.1",
"version": "2.2.0",
"description": "Sia Skynet Javascript Client",

@@ -9,2 +9,7 @@ "main": "dist/index.js",

],
"browserslist": [
"defaults",
"not IE 11",
"not OperaMini all"
],
"scripts": {

@@ -50,9 +55,9 @@ "test": "jest",

},
"homepage": "https://nebulouslabs.github.io/skynet-js/",
"homepage": "https://github.com/NebulousLabs/skynet-js",
"dependencies": {
"@babel/runtime": "^7.11.2",
"@types/node-forge": "^0.9.5",
"axios": "^0.20.0",
"axios": "^0.21.0",
"blakejs": "^1.1.0",
"buffer": "^5.6.0",
"mime-db": "^1.45.0",
"node-forge": "^0.10.0",

@@ -71,3 +76,5 @@ "path-browserify": "^1.0.1",

"@types/jest": "^26.0.14",
"@types/mime-db": "^1.43.0",
"@types/node": "^14.11.2",
"@types/node-forge": "^0.9.5",
"@types/url-join": "^4.0.0",

@@ -79,3 +86,4 @@ "@types/url-parse": "^1.4.3",

"babel-plugin-transform-class-properties": "^6.24.1",
"eslint": "^7.8.1",
"eslint": "^7.11.0",
"eslint-plugin-compat": "^3.8.0",
"husky": "^4.3.0",

@@ -82,0 +90,0 @@ "jest": "^26.4.2",

@@ -10,16 +10,37 @@ # skynet-js - Javascript Sia Skynet Client

## Installing
## Documentation
Using npm
For documentation complete with examples, please see [the Skynet SDK docs](https://siasky.net/docs/?javascript--browser#introduction).
```sh
npm install skynet-js
```
We also have an [example tutorial about creating your first web app on Skynet](https://blog.sia.tech/creating-your-first-web-app-on-skynet-ec6f4fff405f)
Using yarn
## How To Use skynet-js In Your Project
```sh
yarn add skynet-js
If you're thinking, "wait, how can I `import()` in the browser," then here is the answer:
While `skynet-js` is built with Node.js, you can easily compile it to one minified javascript file that is compatible with browsers.
Webpack will compile only the used functions (unused code will be removed automatically), so it is recommended to build your whole project in Node.js and compile it with webpack ([click here for detailed tutorial](https://blog.sia.tech/creating-your-first-web-app-on-skynet-ec6f4fff405f)):
`cd your_project`
`npm install skynet-js`
`npm install webpack webpack-cli --save-dev`
Update your `package.json` file.
```
remove - "main": "index.js",
add - "private": true,
```
Create folders `mkdir dist src`. Make sure you have your javascript files in `src` and the main (entry) javascript is named `index.js`.
Compile with `npx webpack`! You will find the minified `main.js` in the `dist` folder.
### Browser Utility Functions
`skynet-js` provides functions that only make sense in the browser, and are covered in the special section [Browser JS API](https://siasky.net/docs/?javascript--browser#browser-js-api).
## Development

@@ -30,9 +51,1 @@

- Run `yarn test` to run the tests
## Documentation
For documentation complete with examples, please see [the Skynet SDK docs](https://nebulouslabs.github.io/skynet-docs/?javascript--browser#introduction).
### Browser Utility Functions
`skynet-js` provides functions that only make sense in the browser, and are covered in the special section [Browser JS Utilities](https://nebulouslabs.github.io/skynet-docs/?javascript--browser#browser-js-utilities).

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc