:warning: This repo has been archived and moved under the new SkynetLabs repo here
Welcome!
In this repo you will find a basic Skynet app online to help you start developing on Skynet!
The goal of this workshop is to provide developers with examples of the important concepts of developing an app on Skynet.
Create React App is used for structuring the project and simplifying deployment, but you don't need any knowledge of React to follow the workshop.
yarn install
to
install the project's dependencies.yarn start
to see our app's starting layout. If your browser doesn't
launch, visit localhost:3000. Create React App will
auto-reload when you save files. (Use Ctrl+C in the
terminal to stop your app.)We'll first cover the most basic functionality of Skynet, uploading data.
Follow the steps below to update this app to allow the user to upload a file to Skynet. For this sample app, we'll ask the user to upload a picture.
skynet-js
by running yarn add skynet-js
src/App.js
, look for where Step 1.2 code goes, and paste the
following code.// Import the SkynetClient and a helper
import { SkynetClient } from 'skynet-js';
// We'll define a portal to allow for developing on localhost.
// When hosted on a skynet portal, SkynetClient doesn't need any arguments.
const portal = 'https://siasky.net/';
// Initiate the SkynetClient
const client = new SkynetClient(portal);
handleSubmit
function
(called for when form is submitted), paste the code that will upload a file
below the Step 1.3 mark.// Upload user's file and get backs descriptor for our Skyfile
const { skylink } = await client.uploadFile(file);
// skylinks start with `sia://` and don't specify a portal URL
// we can generate URLs for our current portal though.
const skylinkUrl = client.getSkylinkUrl(skylink);
console.log('File Uploaded:', skylinkUrl);
// To use this later in our React app, save the URL to the state.
setFileSkylink(skylinkUrl);
Above this code, uncomment console.log('Uploading file...');
Test it out! If you aren't still running the app, run yarn start
again and try uploading a file. If you open your Developer Console (by
pressing F12), the console show helpful messages.
In Part 1, our app successfully uploaded a file to Skynet, now we'll build on that code to upload a web page.
In addition to files, Skynet can receive directory uploads. Once uploaded to
Skynet, any directory with an index.html
will load in your browser just
like any website. This enables developers to write and deploy their web app,
just by uploading the project's build folder.
handleSubmit
inside src/App.js
, paste this code in the area for Step 2.1.// Create the text of an html file what will be uploaded to Skynet
// We'll use the skylink from Part 1 in the file to load our Skynet-hosted image.
const webPage = generateWebPage(name, skylinkUrl);
// Build our directory object, we're just including the file for our webpage.
const webDirectory = {
'index.html': webPage,
// 'couldList.jpg': moreFiles,
};
// Upload user's webpage
const { skylink: dirSkylink } = await client.uploadDirectory(
webDirectory,
'certificate'
);
// generate a URL for our current portal
const dirSkylinkUrl = client.getSkylinkUrl(dirSkylink);
console.log('Web Page Uploaded:', dirSkylinkUrl);
// To use this later in our React app, save the URL to the state.
setWebPageSkylink(dirSkylinkUrl);
Above this code, uncomment console.log('Uploading web page...');
Test it out! Now the user can submit their name and photo to generate their very own web page on Skynet!
In parts 1 and 2, you uploaded files onto Skynet. The files at these Skylinks are immutable, that is, they cannot be modified (or else their URL would also change). In this section, we'll use SkyDB to store editable data on Skynet that we can come back to and update.
Right now, if you hover over your image in the certificate, you get a nice green halo effect. But, we may want to change this later without changing our skylink. We can do this by saving some editable JSON data to Skynet and having our web page read the info directly from Skynet.
The first step is hooking up our app to SkyDB
, but you'll need a little theory here.
SkyDB users Public / Private key pairs for read / write access. If you want to write to SkyDB, you can use a private key and whatever name you want to give it (the "data key"), and a JSON object to write. So the key combinations are associated with a value. Then, anyone can read this value with your public key and the data key. This kind of database is called a "key-value store."
To get this public/private key pair, you'll use a "seed" which will always generate the same pair based off the same text input.
genKeyPariFromSeed
method from
skynet-js
. Add the code to src/Add.js
for Step 3.1
.import { genKeyPairFromSeed } from 'skynet-js';
SkyDB
. Add the
following code to src/App.js
for Step 3.2
.// Generate the user's private and public keys
const { privateKey, publicKey } = genKeyPairFromSeed(seed);
// Create an object to write to SkyDB
// Conversion to JSON happens automatically.
const jsonData = {
name,
skylinkUrl,
dirSkylinkUrl,
color: userColor,
};
// Use setJSON to save the user's information to SkyDB
try {
await client.db.setJSON(privateKey, dataKey, jsonData);
} catch (error) {
console.log(`error with setJSON: ${error.message}`);
}
// Let's get see info on our SkyDB entry
console.log('SkyDB Entry Written--');
console.log('Public Key: ', publicKey);
console.log('Data Key: ', dataKey);
Above this code, uncomment console.log('Saving user data to SkyDB...');
Next, we want the certificate web page to read this data. The code to fetch the SkyDB entry is already in the generated page, but you'll need to tell it the public key and data key before uploading it to Skynet. Find the code from Step 2.1 that says
const webPage = generateWebPage(name, skylinkUrl);
and replace it with
const webPage = generateWebPage(name, skylinkUrl, seed, dataKey);
loadData
function in our app. Put the following code in the below Step
3.5.// Generate the user's public key again from the seed.
const { publicKey } = genKeyPairFromSeed(seed);
// Use getJSON to load the user's information from SkyDB
const { data } = await client.db.getJSON(publicKey, dataKey);
// To use this elsewhere in our React app, save the data to the state.
if (data) {
setName(data.name);
setFileSkylink(data.skylinkUrl);
setWebPageSkylink(data.dirSkylinkUrl);
setUserColor(data.color);
console.log('User data loaded from SkyDB!');
} else {
console.error('There was a problem with getJSON');
}
Congratulations! You have a fully functioning Skapp! Let's deploy it and let the world see its wonder! As we mentioned before, deploying an application is as easy as uploading a directory.
For Create React App projects, we need to add "homepage": ".",
to the package.json
.
Next, we'll return to where we initialized the SkynetClient
in Step 1.2. When deployed to Skynet, we don't want our App to only communicate with siasky.net, instead we want it to communicate with the portal the app is being served from. Find the line that says
// Initiate the SkynetClient
const client = new SkynetClient(portal);
and replace it with
// Initiate the SkynetClient
const client = new SkynetClient();
Build the application with yarn build
Upload the newly created build
folder to https://siasky.net. (Make sure you select 'Do you want to upload an entire directory?')
Now any of your friends can make their own certificates!
Now that you've deployed a Skynet app, there's many things to keep learning!
You can learn how to use Handshake for a decentralized human-readable URL like skyfeed.hns.siasky.net.
You can integrate cross-application identity with SkyID (or the soon-to-be-released mySky, available April 2021).
You can automate deployment of your site using a Github Action.
We're always improving our Skynet Developer Resources, so check that out and join our Discord to share ideas with other devs.
In the project directory, you can run:
yarn start
Runs the app in the development mode.\ Open http://localhost:3000 to view it in the browser.
The page will reload if you make edits.\ You will also see any lint errors in the console.
yarn build
Builds the app for production to the build
folder.\
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.\ Your app is ready to be deployed!
See the section about deployment for more information.