Added new contract templates (#31)

This commit is contained in:
Chalith Desaman
2024-03-15 17:16:24 +05:30
committed by GitHub
parent 5838ea7fcc
commit 1face50d32
46 changed files with 3860 additions and 73 deletions

View File

@@ -0,0 +1,6 @@
{
"contract": {
"bin_path": "/usr/bin/node",
"bin_args": "index.js"
}
}

View File

@@ -0,0 +1,14 @@
{
"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": {
"bson": "6.4.0",
"hotpocket-nodejs-contract": "^0.7.3",
"@vercel/ncc": "0.34.0"
}
}

View File

@@ -0,0 +1,98 @@
const fs = require('fs');
const bson = require('bson');
export class _projname_ {
sendOutput; // This function must be wired up by the caller.
async handleRequest(user, msg, isReadOnly) {
// This sample application defines simple file operations.
// It's up to the application to decide the structure and contents of messages.
if (msg.type == "upload") {
// Check already exist.
if (fs.existsSync(msg.fileName)) {
await user.send(bson.serialize({
type: "uploadResult",
status: "already_exists",
fileName: msg.fileName
}));
}
// Error is too large.
else if (msg.content.length > 10 * 1024 * 1024) { // 10MB
await user.send(bson.serialize({
type: "uploadResult",
status: "too_large",
fileName: msg.fileName
}));
}
else {
// Do not write in read only mode.
if (!isReadOnly) {
// Save the file.
fs.writeFileSync(msg.fileName, msg.content.buffer);
await user.send(bson.serialize({
type: "uploadResult",
status: "ok",
fileName: msg.fileName
}));
}
else {
await this.sendOutput(user, {
type: "uploadResult",
status: "error",
error: 'Write is not supported in readonly mode'
})
}
}
}
else if (msg.type == "delete") {
// Delete if exist.
if (fs.existsSync(msg.fileName)) {
// Do not delete in read only mode.
if (!isReadOnly) {
fs.unlinkSync(msg.fileName);
await user.send(bson.serialize({
type: "deleteResult",
status: "ok",
fileName: msg.fileName
}));
}
else {
await this.sendOutput(user, {
type: "deleteResult",
status: "error",
error: 'Delete is not supported in readonly mode'
})
}
}
else {
await user.send(bson.serialize({
type: "deleteResult",
status: "not_found",
fileName: msg.fileName
}));
}
}
// Send file if exist.
else if (msg.type == "download") {
if (fs.existsSync(msg.fileName)) {
const fileContent = fs.readFileSync(msg.fileName);
await user.send(bson.serialize({
type: "downloadResult",
status: "ok",
fileName: msg.fileName,
content: fileContent
}));
}
else {
await user.send(bson.serialize({
type: "downloadResult",
status: "not_found",
fileName: msg.fileName
}));
}
}
}
}

View File

@@ -0,0 +1,48 @@
const HotPocket = require('hotpocket-nodejs-contract');
const bson = require('bson');
const { _projname_ } = require('./_projname_');
// HotPocket smart contract is defined as a function which takes the HotPocket contract context 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 HotPocket.
const app = new _projname_();
// Wire-up output emissions from the application before we pass user inputs to it.
app.sendOutput = async (user, output) => {
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 binary.
// In real-world apps, we need to gracefully filter out invalid data formats for our contract.
const msg = bson.deserialize(buf);
// Pass the JSON message to our application logic component.
await app.handleRequest(user, msg, isReadOnly);
}
}
}
const hpc = new HotPocket.Contract();
hpc.init(contract);