Skip to content

Commit

Permalink
Reference guide (#45)
Browse files Browse the repository at this point in the history
* fix incorrect function name

* keep variable name consistent

* security quick reference

* add missing word

* change image to text, remove spheron

* secrets quick reference

* remove reference to image

* remove redundant code

* fix incorrect import

* fix task id

* update functions to better match description of what they're doing

* switch from image to text

* networking quick reference

* storage quick reference

* configuration scaffolding

* improve instructions for staking wallet

* deployment quick reference

* add note about hidden folder

* testing quick reference

* kpl token quick reference

* add links to quick reference sections

* clarify IPFS
  • Loading branch information
labrocadabro authored Jun 28, 2024
1 parent 5f241fc commit 281008e
Show file tree
Hide file tree
Showing 21 changed files with 501 additions and 69 deletions.
13 changes: 13 additions & 0 deletions Get Started - Quick Intro/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,16 @@
That's it! you can make changes to your task and it will update live in your node. You can add `process.env.TEST_KEYWORD` to your console logs to see them in your console, or you can view the entire task output in the task log file.

![View task log](../Lesson%201/imgs/my-node-open-logs.png)

## Going Further

Check out our quick reference guides:

- [Networking](./networking.md)
- [Storage](./storage.md)
- [Secrets](./secrets.md)
- [Security](./security.md)
- [KPL Tokens](./kpl-tokens.md)
- [Testing](./testing.md)
<!-- - [Configuration](./configuration.md) -->
- [Deployment](./deployment.md)
27 changes: 27 additions & 0 deletions Get Started - Quick Intro/configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Configuration Quick Reference

## Task Metadata

The `task_name`, `author`, `description`, `repositoryUrl` and `imageUrl` will be displayed in the desktop node.

<!-- Screenshot highlighting various areas -->

## Task Details

`task_executable_network`?
`task_audit_program`?
`round_time`, `audit_window`, `submission_window` - How do people know what to set for these?
`minimum_stake_amount` - any guidelines?
`total_bounty_amount`, `bounty_amount_per_round`
`allowed_failed_distributions`
`space` - what should this be?

## Requirements Tags

<!-- List of possible options? -->

## Updating a Task

`task_id`, `migrationDescription`

<!-- what can't be updated? -->
39 changes: 39 additions & 0 deletions Get Started - Quick Intro/deployment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Deployment Quick Reference

Before deploying your task, you can apply for our [grant program](https://www.koii.network/founders) that can help you out with initial funding.

1. Make sure all dependencies are installed:

```sh
yarn
```

2. Build the executable:

```sh
yarn webpack
```

3. Run the create task CLI:

```sh
npx @_koii/create-task-cli@latest
```

4. Choose "Deploy a New Task".

5. At this point you will be asked how you'd like to configure your task, via the CLI or the config YML. We recommend using the YML file.

6. Enter the path to your staking wallet. If you have installed the desktop node, visit `<OS-specific path>/KOII-Desktop-Node/namespace/` and you should see a file with the name `<name>stakingWallet.json`. Enter the full path to this file (`<OS-specific path>/KOII-Desktop-Node/namespace/<name>stakingWallet.json`).

The OS-specific paths are as follows:

**Windows**: `/Users/<username>/AppData/Roaming`

**Mac**: `/Users/<username>/Library/Application Support`

**Linux**: `/home/<username>/.config`

7. Press 'y' to confirm you would like to deploy the task.

Once your task is deployed, you will have to apply to have it [whitelisted](https://docs.koii.network/develop/write-a-koii-task/task-development-guide/task-development-flow/whitelist-task) if you would like your task to be listed in the desktop node's Add Task list.
34 changes: 34 additions & 0 deletions Get Started - Quick Intro/kpl-tokens.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# KPL Tokens Quick Reference

## Creating KPL Tokens

Visit [this site](https://dev-blue-spl-token-creator.vercel.app/) to create a KPL token.

You will be asked to enter the following information:

1. **Wallet.json**
If you have deployed your own tasks in previous lessons, you should already know how to obtain your `wallet.json`.

> [!NOTE]
>
> `Wallet.json` is handled through the front-end JavaScript, so rest assured, your `wallet.json` file will never be uploaded anywhere and will always remain on your local machine.
>
2. **PNG/ICO/JPEG**
This is your icon. It is best if it is square; otherwise, it may be cropped.

3. **Token Name/Token Symbol/Token Description**
These are the details of your token. The symbol represents the unit, such as FIRE and KOII.

> [!IMPORTANT]
>
> Please remember your token's Token Public Key, as it will be needed in the next step for minting.
>
## Minting Tokens

Enter the amount of tokens you'd like to mint, your `wallet.json` file, and your Token Public Key.

## Checking Token Balance

You can check the token balance by choosing "Connect Finnie" to link your [Finnie Wallet](https://docs.koii.network/concepts/finnie-wallet/introduction), and then clicking "Fetch Tokens".
86 changes: 86 additions & 0 deletions Get Started - Quick Intro/networking.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Networking Quick Reference

## Configuration

Koii nodes use UPnP for node-to-node communication. This is disabled by default and must be activated by the user, so fewer nodes will be available for these tasks. In order to identify users that can perform these tasks, add `REQUIRE_INTERNET` to your `requirementTags` in `config-task.yml`:

```yml
requirementsTags:
- type: ADDON
value: 'REQUIRE_INTERNET'
```
## Serving Endpoints
Endpoint routes can be added to index.js. Two are already defined in the task template:
```js
if (app) {
// Write your Express Endpoints here.
// Ex. app.post('/accept-cid', async (req, res) => {})

// Sample API that return your task state
app.get('/taskState', async (req, res) => {
const state = await namespaceWrapper.getTaskState({
is_stake_list_required: true,
});
console.log('TASK STATE', state);
res.status(200).json({ taskState: state });
});

// Sample API that return the value stored in NeDB
app.get('/value', async (req, res) => {
const value = await namespaceWrapper.storeGet('value');
console.log('value', value);
res.status(200).json({ value: value });
});
}
```

You can access endpoints like so when you are running `prod-debug`: `http://localhost:30017/task/<taskID>/<endpoint>`

## Accessing Endpoints from Other Nodes

To access other nodes' endpoints, you can access the list of IP addresses currently running the task, then choose which nodes you will access. In this example, we're selecting a single random node:

```javascript
async function getAddressArray() {
try {
// get the task state from K2 (the Koii blockchain)
const taskState = await namespaceWrapper.getTaskState();

// get the list of available IP addresses from the task state
// nodeList is an object with key-value pairs in the form stakingKey: ipAddress
const nodeList = taskState.ip_address_list;

// return just the IP addresses
return Object.values(IPAddressObj);
} catch (e) {
console.log('ERROR GETTING TASK STATE', e);
}
}

async function getRandomNodeEndpoint(IPAddressArray) {
// choose a random index
const randomIndex = Math.floor(Math.random() * IPAddressArray.length);
// Return the IP address stored at the random index position
return IPAddressArray[randomIndex];
}
```

You can access the endpoint(s) you've chosen during the task or audit phases

```javascript
// Get a random node from the list
const IPAddressObj = getAddressArray();
const randomNode = getRandomNodeEndpoint(IPAddressObj);

// Fetch the data from the node
const response = await axios.get(`${randomNode}/task/${TASK_ID}/<endpoint>`);

if (response.status === 200) {
const data = response.data;
} else {
return null;
}
```
20 changes: 20 additions & 0 deletions Get Started - Quick Intro/secrets.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Secrets Quick Reference

Secrets (referred to as task extensions in the desktop node) are environment variables stored by node users. These can be accessed just as you would any other environment variable, using `process.env`. During development, these should be added to your .env file.

You can specify which environment variables a user must define in the `requirementsTags` section of your `config-task.yml` file, using the `TASK_VARIABLE` type.

Example:

```yml
requirementsTags:
- type: TASK_VARIABLE
value: 'TWITTER_USERNAME'
description: 'The username of your volunteer Twitter account.'
- type: TASK_VARIABLE
value: 'TWITTER_PASSWORD'
description: 'The password of your volunteer Twitter account.'
- type: TASK_VARIABLE
value: 'TWITTER_PHONE'
description: 'If verification is required, will use your phone number to login.'
```
29 changes: 29 additions & 0 deletions Get Started - Quick Intro/security.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Security Quick Reference

A message can be signed like so, using `namespaceWrapper.payloadSigning()`:

```javascript
const message = "Hello World!";

// Sign payload
const signedMessage = await namespaceWrapper.payloadSigning(message);
```

The `payloadSigning()` function will take care of accessing the node's private key for the signing.

When you want to send this signature to another node, you'll also need to include the current node's public key. You can get this from `namespaceWrapper.getSubmitterAccount()`:

```javascript
// get current node's keypair
const keypair = await namespaceWrapper.getSubmitterAccount(message);

// get the public key from the keypair
const publicKey = keypair.publicKey;
```

You can then send the signed message and the public key to another node to be verified and decoded. This can be done with `namespaceWrapper.verifySignature()`:

```javascript
// Assuming you've already retrieved the signed message and the public key
const message = namespaceWrapper.verifySignature(signedMessage, publicKey);
```
78 changes: 78 additions & 0 deletions Get Started - Quick Intro/storage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Storage Quick Reference

## Local Database

Koii tasks use a local key-value store that can be used to pass data between functions.

### Setting a value

```js
const value = await namespaceWrapper.storeSet('value', '<your_value>');
```

### Getting a value

```js
const value = await namespaceWrapper.storeGet('value');
```

## IPFS

You can use IPFS in a Koii task to pass files between nodes.

### Uploading a file

```js
const { KoiiStorageClient } = require('@_koii/storage-task-sdk');
const fs = require('fs');

async function storeFile(data, filename = 'value.json') {
try {
// Create a new instance of the Koii Storage Client
const client = new KoiiStorageClient();
const basePath = await namespaceWrapper.getBasePath();

// Write the data to a temp file
fs.writeFileSync(`${basePath}/${filename}`, JSON.stringify(data));

// Get the user staking account, to be used for signing the upload request
const userStaking = await namespaceWrapper.getSubmitterAccount();

// Upload the file to IPFS and get the CID
const { cid } = await client.uploadFile(`${basePath}/${filename}`, userStaking);

// Delete the temp file
fs.unlinkSync(`${basePath}/${filename}`);

return cid;
} catch (error) {
console.error('Failed to upload file to IPFS:', error);
fs.unlinkSync(`${basePath}/${filename}`);
throw error;
}
}
```

The CID can then be sent as part of the submission to be used by other nodes.

## Retrieving a file

```js
const { KoiiStorageClient } = require('@_koii/storage-task-sdk');

// Create a new instance of the Koii Storage Client
const client = new KoiiStorageClient();

try {
// get file from IPFS
const fileBlob = await client.getFile(cid, filename);
if (!fileBlob) return false;

// if it's a text file, you can read the contents
const fileContent = await fileBlob.text();

} catch (error) {
console.error('Failed to download or validate file from IPFS:', error);
throw error;
}
```
Loading

0 comments on commit 281008e

Please sign in to comment.