mirror of
https://github.com/EvernodeXRPL/hp-devkit.git
synced 2026-04-29 15:37:58 +00:00
Added nodejs code generator. (#1)
This commit is contained in:
6
docker/code-templates/nodejs/starter/dist/hp.cfg.override
vendored
Normal file
6
docker/code-templates/nodejs/starter/dist/hp.cfg.override
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"contract": {
|
||||
"bin_path": "/usr/bin/node",
|
||||
"bin_args": "index.js"
|
||||
}
|
||||
}
|
||||
13
docker/code-templates/nodejs/starter/package.json
Normal file
13
docker/code-templates/nodejs/starter/package.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "_projname_",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"build": "npx ncc build src/contract.js -o dist",
|
||||
"build:prod": "npx ncc build src/contract.js --minify -o dist",
|
||||
"start": "npm run build && hpdevkit deploy dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"hotpocket-nodejs-contract": "0.5.3",
|
||||
"@vercel/ncc": "0.34.0"
|
||||
}
|
||||
}
|
||||
60
docker/code-templates/nodejs/starter/src/_projname_.js
Normal file
60
docker/code-templates/nodejs/starter/src/_projname_.js
Normal file
@@ -0,0 +1,60 @@
|
||||
const fs = require('fs').promises;
|
||||
|
||||
// This sample application writes and reads from a simple text file to serve user requests.
|
||||
// Real-world applications may use a proper local database like sqlite.
|
||||
const dataFile = 'datafile.txt'
|
||||
|
||||
export class _projname_ {
|
||||
sendOutput; // This function must be wired up by the caller.
|
||||
|
||||
async handleRequest(userPubKey, message, isReadOnly) {
|
||||
|
||||
// This sample application defines two simple messages. 'get' and 'set'.
|
||||
// It's up to the application to decide the structure and contents of messages.
|
||||
|
||||
if (message.type == 'get') {
|
||||
|
||||
// Retrieved previously saved data and return to the user.
|
||||
const data = await this.getData();
|
||||
await this.sendOutput(userPubKey, {
|
||||
type: 'data_result',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
else if (message.type == 'set') {
|
||||
|
||||
if (!isReadOnly) {
|
||||
// Save the provided data into storage.
|
||||
await this.setData(message.data);
|
||||
}
|
||||
else {
|
||||
await this.sendOutput(userPubKey, {
|
||||
type: 'error',
|
||||
error: 'Set data not supported in readonly mode'
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
await this.sendOutput(userPubKey, {
|
||||
type: 'error',
|
||||
error: 'Unknown message type'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async setData(data) {
|
||||
// Hot Pocket subjects data on-disk to consensus.
|
||||
await fs.writeFile(dataFile, data);
|
||||
}
|
||||
|
||||
async getData() {
|
||||
try {
|
||||
return (await fs.readFile(dataFile)).toString();
|
||||
}
|
||||
catch {
|
||||
console.log('Data file not created yet. Returning empty data.');
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
49
docker/code-templates/nodejs/starter/src/contract.js
Normal file
49
docker/code-templates/nodejs/starter/src/contract.js
Normal file
@@ -0,0 +1,49 @@
|
||||
const HotPocket = require('hotpocket-nodejs-contract');
|
||||
const { _projname_ } = require('./_projname_');
|
||||
|
||||
// Hot Pocket smart contract is defined as a function which takes the Hot Pocket ExecutionContext as an argument.
|
||||
// This function gets invoked every consensus round and whenever a user sends a out-of-concensus read-request.
|
||||
async function contract(ctx) {
|
||||
|
||||
// Create our application logic component.
|
||||
// This pattern allows us to test the application logic independently of Hot Pocket.
|
||||
const app = new _projname_();
|
||||
|
||||
// Wire-up output emissions from the application before we pass user inputs to it.
|
||||
app.sendOutput = async (userPubKey, output) => {
|
||||
// In Hot Pocket, each user is represented by their Ed25519 public key.
|
||||
const user = ctx.users.find(userPubKey);
|
||||
await user.send(output)
|
||||
}
|
||||
|
||||
// In 'readonly' mode, nothing our contract does will get persisted on the ledger. The benefit is
|
||||
// readonly messages gets processed much faster due to not being subjected to consensus.
|
||||
// We should only use readonly mode for returning/replying data for the requesting user.
|
||||
//
|
||||
// In consensus mode (NOT read-only), we can do anything like persisting to data storage and/or
|
||||
// sending data to any connected user at the time. Everything will get subjected to consensus so
|
||||
// there is a time-penalty.
|
||||
const isReadOnly = ctx.readonly;
|
||||
|
||||
// Process user inputs.
|
||||
// Loop through list of users who have sent us inputs.
|
||||
for (const user of ctx.users.list()) {
|
||||
|
||||
// Loop through inputs sent by each user.
|
||||
for (const input of user.inputs) {
|
||||
|
||||
// Read the data buffer sent by user (this can be any kind of data like string, json or binary data).
|
||||
const buf = await ctx.users.read(input);
|
||||
|
||||
// Let's assume all data buffers for this contract are JSON.
|
||||
// In real-world apps, we need to gracefully fitler out invalid data formats for our contract.
|
||||
const message = JSON.parse(buf);
|
||||
|
||||
// Pass the JSON message to our application logic component.
|
||||
await app.handleRequest(userPubKey, message, isReadOnly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const hpc = new HotPocket.Contract();
|
||||
hpc.init(contract);
|
||||
Reference in New Issue
Block a user