nebulouslabs / skynet-js Goto Github PK
View Code? Open in Web Editor NEWA Javascript module made to simplify communication with Sia Skynet portals from the browser.
Home Page: https://nebulouslabs.github.io/skynet-js/
License: MIT License
A Javascript module made to simplify communication with Sia Skynet portals from the browser.
Home Page: https://nebulouslabs.github.io/skynet-js/
License: MIT License
bug recreated in test case #94
Improve skylink
param handling:
[a-zA-Z0-9_-]{46}
sia://<skylink>
(strip sia://
)https://siasky.net/docs/?javascript--browser#uploading-a-directory
async function uploadDirectoryExample() {
try {
var files = []
var f1 = document.getElementById('profilePicture').files[0]
f1.webkitRelativePath = '1.jpg'
files.push(f1)
const directory = files.reduce((accumulator, file) => {
const path = skyid.getRelativeFilePath(file);
return { ...accumulator, [path]: file };
}, {});
console.log('directory', directory)
const { skylink } = await skyid.skynetClient.uploadDirectory(directory, 'asd');
console.log('skylink', skylink)
} catch (error) {
console.log(error);
}
}
We should set maxBodyLength
and maxContentLength
to Infinity
when making axios calls. See NebulousLabs/nodejs-skynet#49
Using the code from the SDK documentation
async function uploadExample() {
try {
const { skylink } = await client.uploadFile(file);
} catch (error) {
console.log(error)
}
}
return undefined on successful upload
dataKey
is passed twice into skynetClient.registry.setEntry(...)
example from https://siasky.net/docs/#setting-data-on-the-registry
import { SkynetClient, keyPairFromSeed } from "skynet-js";
const client = new SkynetClient();
const { publicKey, privateKey } = keyPairFromSeed("this seed should be fairly long for security");
const dataKey = "foo";
const data = "bar";
const revision = 0;
const entry = { datakey, data, revision };
async function setEntryExample() {
try {
await client.registry.setEntry(privateKey, dataKey, entry);
} catch (error) {
console.log(error);
}
}
Variable dataKey
is passed once to create entry
const entry = { datakey, data, revision };
and then also as a second parameter to setEntry
client.registry.setEntry(privateKey, dataKey, entry);
Solution proposals
// (my choice)
const entry = { datakey, data, revision };
client.registry.setEntry(privateKey, entry);
or
const entry = { data, revision };
client.registry.setEntry(privateKey, dataKey, entry);
or
client.registry.setEntry(privateKey, dataKey, data, revision);
Inspired by #319 I looked into mime-db
-- it seems like the original usage was prompted by an issue with react-dropzone
on the web portal homepage.
This dependency is just a large JSON file of all known MIME-types. It seems like this would be a developer's responsibility to manage, and at 200kb unpacked, it's almost 20% of the space in our code.
Option 1: Fix react-dropzone
and drop dependency.
Option 2: Follow their documentation's advice:
If you're crazy enough to use this in the browser, you can just grab the JSON file using jsDelivr. It is recommended to replace master with a release tag as the JSON format may change in the future.
We could host the file on skynet and have the client load it from the current portal if an upload of unknown MIME-type ever occurs.
Option 3: Consider a library like mime. It's a self-contained module bundled with a pre-optimized version of the mime-db dataset, and intended for browser use. mime-db
, when minified and compressed, is 18KB, mime
is 8KB, mime/lite
is 2KB.
Functions keyPairFromSeed
and generateKeyPairAndSeed
should return keys as strings, not buffers, otherwise if I want to print the publickey to user, I need to install a buffer package and use toString("hex") myself which is an extra step and I think totally unnecessary.
closes #165
The utils.ts
file is stuffed with a bunch of different functions by this point. I think it would be itneresting to organize them into a utils
directory with different files (for example, theres a few functions for manipulating URLs that can go into utils/url.ts
).
We could add support for production build that would allow people to use https://unpkg.com/
Right now, we consider any rejected response from api to be "empty record" for both getEntry and getJSON due to the fact that we had to reject it ourselves on timeout and couldn't rely on a specific error code from siad. Now that #218 implements timeout properly, we should be returning empty records only in an event when siad rejects with the not found error, otherwise we should be rethrowing the original api error.
Pending either a response header or an API endpoint on Web Portal:
https://github.com/NebulousLabs/skynet-webportal/issues/657
Skapps that expect their storage to be "long-term" may want to indicate to users that they are not logged into the portal using an account. Even "free" should be fine.
GET and POST calls need cookies sent with Accounts.
fetch("https://siasky.xyz/AACU3d_HIQ8jkSPdQwn415O0AVvvP6jo9RALPXWUltwcfQ", { credentials: 'include'})
For axios:
https://stackoverflow.com/a/43178070
functions like HashAll
, HashDataKey
, NewHash
, HashRegistryEntry
should have first letter lowercase
I think the required skykeyName is just ignored when uploading encrypted file.
https://siasky.net/docs/?javascript--browser#uploading-with-encryption
(Would be great to be able to encrypt SkyDB JSON files also)
We need a way for Skapps to reliably know what web portal they're being accessed through.
This will need to use headers the portal passes or an endpoint accessible even when at an HNS subdomain. The first seems far preferable.
generateKeyPairAndSeed
and keyPairFromSeed
One starts with a verb generate
, the other doesn't. Since we're doing some breaking changes anyway, let's change keyPairFromSeed
to generateKeyPairFromSeed
.
Add typescript support.
We introduced 2 new features recently:
You can reencode skylink with Base32 and use it as a subdomain to access your content on siasky.net:
Converter: https://convert-skylink.hns.siasky.net/ (conversion explained and documented on GitHub)
We should add support to either return regular skylink url or the subdomain skylink url when returning skylink url in SDK. preferably regular skylink url by default and subdomain skylink url if some optional param is set to true
.
We should also add a utility function that converts Base64 (regular) skylink (46 chars) to Base32 skylink. There are already decoder and encoder functions here https://github.com/kwypchlo/base32/blob/master/src/crypto.ts and usage example is https://github.com/kwypchlo/base32/blob/master/src/App.tsx#L24-L25 but I guess it could be one function in the SDK (instead of two).
You can access your content bound to the hns domain using *.hns.siasky.net subdomain:
Regular hns: https://siasky.net/hns/convert-skylink/
New hns subdomain: https://convert-skylink.hns.siasky.net/
We should add a param to function that return hns url to either return regular one (default) or the one in subdomain (optional param set to true
).
Current db.setJSON
does the following in series:
Option 1: The first 2 calls are very expensive and can be done in parallel.
https://siasky.net/IADUtc2kNnhgWVISPvel9H_Lazb8RjOghSYFgn_mIkqcTg
Finished in #305
Option 2: Idea needs tested, but providing a "skylink" instead of a JSON object to setJSON and getJSON. Then "initial value" skylinks can be used to try to initialize the SkyDB entry at registry rev0 without checking if the registry entry already exists or not. Also, this bypasses the first skyfile upload to save time early in the user experience and ensures that any subsequent visit to the site will not result in the registry read having to timeout.
I need to print a url after creating the registry entry. Currently I do it like this:
const encodedPublicKey = encodeURIComponent(`ed25519:${publicKey}`);
const encodedDataKey = encodeURIComponent(Buffer.from(HashDataKey(dataKey)).toString("hex"));
console.log(`https://siasky.net/skynet/registry?publickey=${encodedPublicKey}&datakey=${encodedDataKey}`);
I would like a function called getRegistryEntryUrl
that would allow me to modify the above code to be
console.log(skynetClient.registry.getEntryUrl(publicKey, dataKey));
From #239 (comment):
What happens if we don't specify the content type? Would it be detected?
No need to cover this now but it might be interesting to verify the behaviour.
Function keyPairFromSeed
should also include specifier
in the response object, set to "ed25519"
(it wouldn't be needed if private key and public key would be strings in the response so close this one if #162 is accepted).
Function skynetClient.registry.getEntry
now returns null
if entry is not found so we need to write
const entry = skynetClient.registry.getEntry(...);
if(entry) {
console.log(entry.entry.data);
}
and it works fine (not even mentioning weird entry.entry
chain) but I think usually people would write
const { entry } = skynetClient.registry.getEntry(...);
but it will throw an error if getEntry
returns null
.
I think we should return { entry: null }
if the entry is not found instead of just null
so it's easier for people to destructure the result and saves us weird accessing entry.entry
.
From #141 (comment).
It is easy to obscure the otherwise explicit definition of the portal if we make our portal a default. This could cause bad user experience if people start relying on https://siasky.net free service as a de facto way to use the library and our portal starts having problems or we take it down for updates or sth. We should include it in the examples but the actual library should stay portal agnostic.
@m-cat FLW: the same should apply to all our SDKs
Originally posted by @kwypchlo in #37 (comment)
FLW: We should include the new functions in README.md examples
Originally posted by @kwypchlo in #37 (comment)
genKeyPairFromSeed() returns something weird bytearray instead of HEX
Solution: Use this function instead of .toString('hex')
When a skapp imports skynet-js
and builds with Webpack (what we recommend in tutorials), the resulting bundle pulls in the entire SDK, even if the skapp only used a single function from skynet-js
(e.g. defaultPortalUrl()
).
Currently build
runs babel and then tsc to generate .js
files. tsc actually overwrites the babel generated files, meaning we should either:
"emitDeclarationOnly": true,
to tsconfig.build.json
as addressed here.Example:
My skapp https://vg4hm678pvjltuh5nmmfimdi9jud7tggoda3eo4651uioqrii5oali0.siasky.net
calls getSkylinkUrl("_AkeLeS84huwnOKEdP9o36dE1qJkmwHCVpzyFcMhv5d33A", { subdomain: true })
The result is https://vg4o10vtuj8j5np6rm4ujohmpaoksi9f9ei5ecnkguch74qgepbiobg.vg4hm678pvjltuh5nmmfimdi9jud7tggoda3eo4651uioqrii5oali0.siasky.net/
.
The expected result is https://vg4o10vtuj8j5np6rm4ujohmpaoksi9f9ei5ecnkguch74qgepbiobg.siasky.net/
.
This is probably impossible until https://github.com/NebulousLabs/skynet-webportal/issues/423 is implemented.
Currently, the SDK uses very similar ways of directing the browser to "download" or "open" files, both by calling the window object.
As I work more with skynet-js, I'm wondering if "requesting" a file and returning the data of the Axios response (and perhaps skylink metadata) makes sense, especially for txt, json or other filetypes.
I'd propose getFile
for this, but that overlaps with SkyDB function names, so perhaps client.requestFile(skylink)
?
I'd be happy to do the initial implementation.
The default options are being exported for compatibility with Go, but they shouldn't be because the user has no use for them and they only clutter the API
The download options object should be expanded with a new option to pass the no-response-metadata
HTTP parameter
When running app in a browser from an url with a skylink (for example when your app is uploaded to skynet), parseSkylink
returns that skylink from the browser url even if the argument passed to parseSkylink
should throw an error (ex parseSkylink("foo")
).
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.