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,65 @@
export class _projname_ {
sendOutput; // This function must be wired up by the caller.
async handleRequest(user, message, unl, timeout, isReadOnly) {
// This sample application defines a simple messages. 'rnd' and 'set'.
// It's up to the application to decide the structure and contents of messages.
if (message.type == 'rnd') {
// NPL messages are not supported in readonly mode.
if (!isReadOnly) {
// Start listening to incoming NPL messages before we send ours.
const promise = new Promise((resolve, reject) => {
let t = setTimeout(() => {
reject(`NPL messages aren't received withing ${timeout} ms.`);
}, timeout);
let nplRes = [];
unl.onMessage((node, msg) => {
nplRes.push({ pubkey: node.publicKey, number: Number(msg.toString()) });
// Resolve once all are received
if (nplRes.length === unl.count()) {
clearTimeout(t);
resolve(nplRes.sort((a, b) => a.number - b.number));
}
});
});
await unl.send(Math.random().toString());
try {
const receipt = await promise;
await this.sendOutput(user, {
type: 'rndResult',
status: "ok",
nplMessages: receipt,
rnd: receipt[0].number
});
}
catch (e) {
await this.sendOutput(user, {
type: "rndResult",
status: "error",
error: e.toString()
});
}
}
else {
await this.sendOutput(user, {
type: "rndResult",
status: "error",
error: 'NPL messages are not supported in readonly mode'
});
}
}
else {
await this.sendOutput(user, {
type: 'error',
error: 'Unknown message type'
})
}
}
}

View File

@@ -0,0 +1,53 @@
const HotPocket = require('hotpocket-nodejs-contract');
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;
// Access the HotPocket config.
const hpconfig = await ctx.getConfig();
// Wait only for half of roundtime for random number generation.
const timeout = Math.ceil(hpconfig.consensus.roundtime);
// 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 filter out invalid data formats for our contract.
const message = JSON.parse(buf);
// Pass the JSON message to our application logic component.
await app.handleRequest(user, message, ctx.unl, timeout, isReadOnly);
}
}
}
const hpc = new HotPocket.Contract();
hpc.init(contract);