Simple BlockChain program - javascript

I am trying to build this simple code of "BlockChain" I found it online to give me a better understanding of the blockchain technique.
But when I run it it gives me an error when it runs.
This is the error that I got:-
import {BlockChain} from 'BlockChain';
^
SyntaxError: Unexpected token
class Block
export class Block{
constructor(timestamp, data, previousHash = '') {
this.timestamp = timestamp;
this.data = data;
this.previousHash = previousHash;
// The calculation of the hash must be at the end so to ensure that all data is assigned correctly before calculation
this.hash = this.calculateHash(); }
calculateHash() {
return SHA256(this.previousHash + this.timestamp + JSON.stringify(this.data)).toString();
}
}
class BlockChain
import {Block} from 'Block';
export class BlockChain {
constructor() {
this.chain = [this.createGenesisBlock()];
}
createGenesisBlock(){
return new Block("2018-11-11 00:00:00", "Genesis block of simple chain", "");
}
getLatestBlock() {
return this.chain[this.chain.length - 1];
}
addBlock(newBlock) {
// The previous hash value of the new block is the hash value of the last block of the existing blockchain;
newBlock.previousHash = this.getLatestBlock().hash;
// Recalculate the hash value of the new block (because the previousHash is specified);
newBlock.hash = newBlock.calculateHash();
//Add new blocks to the chain;
this.chain.push(newBlock);
}
isChainValid() {
//Traverse all the blocks
for (let i = 1; i < this.chain.length; i++) {
const currentBlock = this.chain[i];
const previousBlock = this.chain[i - 1];
//Recalculate the has value of the current block. If the hash value is not matched, it indicates that data of the block was changed without permission, and therefore the has value is not recalculated.
if (currentBlock.hash !== currentBlock.calculateHash()) {
console.error("hash not equal: " + JSON.stringify(currentBlock));
return false;
}
// Determine whether the previousHash of the current block is equal to the hash of the previous block. If they are not equal to each other, this means that the previous block was changed without permission. Although the hash value is recalculated correctly, the hash value of the subsequent block is not recalculated, resulting the the whole chain breaking.
if (currentBlock.previousHash !== previousBlock.calculateHash) {
console.error("previous hash not right: " + JSON.stringify(currentBlock));
return false;
}
}
return true;
}
}
Class Test
import {BlockChain} from 'BlockChain';
import {Block} from 'Block';
let simpleChain = new BlockChain();
simpleChain.addBlock(new Block("2018-11-11 00:00:01", {amount: 10}));
simpleChain.addBlock(new Block("2018-11-11 00:00:02", {amount: 20}));
console.log(JSON.stringify(simpleChain, null, 4));
console.log("is the chain valid? " + simpleChain.isChainValid());

The code is fine. You can run the code as follows:
Install crypto-js using Node:
npm install crypto-js
Open a Node prompt from the Command window/Terminal:
Node
Open the Editor in Node:
Require the sha256 module. Paste the following code in the editor:
const SHA256 = require('crypto-js/sha256');
Paste the Block, BlockChain and Test classes, in the editor:
Class Block
class Block{
constructor(timestamp, data, previousHash = '') {
this.timestamp = timestamp;
this.data = data;
this.previousHash = previousHash;
// The calculation of the hash must be at the end so to ensure that all data is assigned correctly before calculation
this.hash = this.calculateHash(); }
calculateHash() {
return SHA256(this.previousHash + this.timestamp + JSON.stringify(this.data)).toString();
}
}
Class BlockChain
class BlockChain {
constructor() {
this.chain = [this.createGenesisBlock()];
}
createGenesisBlock(){
return new Block("2018-11-11 00:00:00", "Genesis block of simple chain", "");
}
getLatestBlock() {
return this.chain[this.chain.length - 1];
}
addBlock(newBlock) {
// The previous hash value of the new block is the hash value of the last block of the existing blockchain;
newBlock.previousHash = this.getLatestBlock().hash;
// Recalculate the hash value of the new block (because the previousHash is specified);
newBlock.hash = newBlock.calculateHash();
//Add new blocks to the chain;
this.chain.push(newBlock);
}
isChainValid() {
//Traverse all the blocks
for (let i = 1; i < this.chain.length; i++) {
const currentBlock = this.chain[i];
const previousBlock = this.chain[i - 1];
//Recalculate the has value of the current block. If the hash value is not matched, it indicates that data of the block was changed without permission, and therefore the has value is not recalculated.
if (currentBlock.hash !== currentBlock.calculateHash()) {
console.error("hash not equal: " + JSON.stringify(currentBlock));
return false;
}
// Determine whether the previousHash of the current block is equal to the hash of the previous block. If they are not equal to each other, this means that the previous block was changed without permission. Although the hash value is recalculated correctly, the hash value of the subsequent block is not recalculated, resulting the the whole chain breaking.
if (currentBlock.previousHash !== previousBlock.calculateHash) {
console.error("previous hash not right: " + JSON.stringify(currentBlock));
return false;
}
}
return true;
}
}
Class Test
let simpleChain = new BlockChain();
simpleChain.addBlock(new Block("2018-11-11 00:00:01", {amount: 10}));
simpleChain.addBlock(new Block("2018-11-11 00:00:02", {amount: 20}));
console.log(JSON.stringify(simpleChain, null, 4));
console.log("is the chain valid? " + simpleChain.isChainValid());
Press ^D to finish
This will give you the following output:

Related

How to use quills setSelection?

I am writing a custom module for quilljs. It is a simple text macro replacement tool.
ie type ".hi", it will replace it with "hello".
Originally I was calling quill.setSelection(...) within the text-change event. It wasn't working Codepen Original. Eventually I found this in the docs
Changes to text may cause changes to the selection (ex. typing advances the cursor), however during the text-change handler, the selection is not yet updated, and native browser behavior may place it in an inconsistent state. Use selection-change or editor-change for reliable selection updates." Quill setSelection API docs
So I reworked the code Codepen Revised. It works, but it sure is ugly and cursor updating after the text insertion looks weird. I cannot believe there isn't a better/idiomatic way to do this.
Quill.register("modules/quicktext", function (quill, options) {
let cache = "";
let finalcaret = null;
quill.on("editor-change", (eventName, ...args) => {
if (eventName === "text-change" && args[2] === "user") {
let [delta, oldDelta, source] = args;
console.log(source, delta);
let lastkey = delta.ops[delta.ops.length - 1]?.insert || "";
if (delta.ops[delta.ops.length - 1]?.delete) {
// handle delete key
cache = cache.slice(0, -1);
return;
}
if (lastkey && lastkey !== " ") {
cache += lastkey;
console.log("cache", cache, "lastkey", lastkey);
} else if (cache) {
// avoid initial call
console.log("cache", cache, "lastkey", lastkey);
reps.forEach((rep) => {
console.log("rep check", cache, rep[cache]);
if (rep[cache]) {
console.log("triggered");
let caret = quill.getSelection().index;
let start = caret - cache.length - 1;
quill.deleteText(start, cache.length, "api");
quill.insertText(start, rep[cache], "api");
//quill.update("api");
finalcaret = caret + rep[cache].length - cache.length;
console.log(
`caret at ${caret}, moving forward ${
rep[cache].length - cache.length
} spaces, to position ${
caret + rep[cache].length - cache.length
}.`
);
console.log("done trigger");
}
});
cache = "";
}
} else if (eventName === "selection-change") {
if (finalcaret) {
quill.setSelection(finalcaret);
finalcaret = "";
}
}
});
});
let reps = [
{ ".hi": "hello" },
{ ".bye": "goodbye" },
{ ".brb": "be right back" }
];
// We can now initialize Quill with something like this:
var quill = new Quill("#editor", {
modules: {
quicktext: {
reps: reps
}
}
});
I was able to figure out a solution based upon this issue. Not sure why this is necessary, but works but it does.
// quill.setSelection(finalcaret, 0) // this fails
setTimeout(() => quill.setSelection(finalcaret, 0), 1); // this works
Codepen FINAL

Using a string interpolation in a string template undefined object attribute value

I'm having this weird error:
testObject.ts
import { OobjectA } from './OobjectA';
import { OobjectB } from './OobjectB';
import { OobjectC } from './OobjectC';
export class TestObject{
private _atrrA: number=0;
private _atrr1: string="";
private _atrr2: number = 0;
private _atrr3: number = 0;
private _atrrBt: Date = new Date();
private _atrrC: number =0;
private _atrrD: Date = new Date();
private _atrrError: number = 0;
private _atrr4: number = 0;
private _atrr5: number = 0;
constructor(
oobjectA: OobjectA,
oobjectB: OobjectB,
oobjectC: OobjectC
) {
if (oobjectA !== undefined &&
oobjectB !== undefined &&
oobjectC !== undefined ) {
this._atrrError = oobjectA.atrrError;
this._atrr4 = oobjectB.atrr4;
this._atrr5 = oobjectC.atrr5;
}
}
set atrrA(atrrA){
this._atrrA =atrrA
}
set atrr1(atrr1){
this._atrr1 =atrr1
}
set atrr2(atrr2){
this._atrr2 = atrr2
}
set atrr3(atrr3){
this._atrr3 =atrr3
}
set atrrBt(atrrBt){
this._atrrBt = atrrBt
}
set atrrC(atrrC){
this._atrrC = atrrC
}
set atrrD(atrrD){
this._atrrD = atrrD
}
set atrrError(atrrError){
this._atrrError = atrrError
}
set atrr4(_atrr4){
this._atrr4 = _atrr4
}
set atrr5(atrr5){
this._atrr5 = atrr5
}
get atrrA(){
return this._atrrA
}
get atrr1(){
return this._atrr1
}
get atrr2(){
return this._atrr2
}
get atrr3(){
return this._atrr3
}
get atrrBt(){
return this._atrrBt
}
get atrrC(){
return this._atrrC
}
get atrrD(){
return this._atrrD
}
get atrrError(){
return this._atrrError
}
get atrr4(){
return this._atrr4
}
get atrr5(){
return this._atrr5
}
}
Controller.ts
try{
// ...more code
const oobjectA : OobjectA = new OobjectA ()
oobjectA.atrrError = otherObject[0].atrrError
oobjectB.atrr4 = otherObject2[0].subObject[0].atrr4
const testObject: TestObject = new TestObject(oobjectA, oobjectB, oobjectC)
testObject.atrr1 = "string"
testObject.atrr2 = 1
testObject.atrr3 = 1;
const testObject_id: any = await create_user_function_ejecution_order[5].functionCU(testObject).catch(error => {
create_user_function_ejecution_order[5].status=false
create_user_function_ejecution_order[5].error = error
console.log(error)
})
console.log("testObject",testObject.atrrA?.atrrA)
}catch(e){
// ... more code
}
// ... more code
file.ts
import {db} from "../../connection";
export const insert_data = async(testObject) => {
console.log(testObject)
console.log(testObject._atrrError)
console.log(testObject.atrrError)
console.log(`${testObject.atrrError}`)
console.log(`${testObject._atrrError}`)
const queryString = `
INSERT INTO table (column1, column2, column3, columnError, column4, column5)
VALUES ('${testObject.atrr1}', ${testObject.atrr2}, ${testObject.atrr3}, ${testObject.atrrError} , ${testObject.atrr4}, ${testObject.atr5})
`
console.log(queryString)
const result = await db.query(queryString)
return result[0]
};
output
testObject{
_atrrA: 0,
_atrr1: 'string',
_atrr2: 1,
_atrr3: 1,
_atrrB: 2021-11-24T23:37:42.394Z,
_atrrC: 0,
_atrrD: 2021-11-24T23:37:42.394Z,
_atrrError: 1,
_atrr4: 1,
_atrr5: 1
}
1
1
undefined
undefined
INSERT INTO table (INSERT INTO table (column1, column2, column3, columnError, column4, column5)
VALUES ('string', 1, 1, undefined, 1, 1)
Error: Unknown column 'undefined' in 'field list'
Why it is defined with the value 1 in the cosole.log but in the 3rd console.log it is not defined.
My thought was because some asynchronous thing, but it is in the same file. My second thought was it is taking ownership, but is not a low level language. So my new hypothesis is that the string interpolation have an inside error.
Any other case were it can be other error like this?
devDependencies:
"ts-node": "^10.4.0",
"typescript": "^4.4.4"
nodejs version: v16.13.0
Putting this in an answer just because I need to communicate multiple lines of code which won't be legible in a comment.
When I put this into a file and run that file with nodejs:
const testObject = {
atrr: 1
};
console.log(testObject)
console.log(testObject.atrr)
console.log(`${testObject.atrr}`)
I get this output in the console:
{ atrr: 1 }
1
1
Which is exactly what we would expect. So, apparently there's something different around your object or your environment. The only way I would expect undefined is if the value of the attrr property was something that does not have a .toString() method or if that method returned undefined.
Keep in mind that the template is going to check the type of the value you passed it and, if it isn't a string, it's going to try to convert it to a string. Apparently that string conversion is resulting in undefined.
For any further help, please show exactly how testObject is declared and edit your question to show a minimal, reproducible example.

Greedy Promise resolve for a semantic parser

I'm trying to create a semantic parser, that parses elements and try to resolve a type for each element (types are also elements itself).
I tried to create the following minimal working example to specify my problem:
// Elements are defined with a name and an typeID:
class Element{
name = "";
typeID = "";
type = null;
waitPromise = null;
constructor(name, typeID){
this.name = name;
this.typeID = typeID;
}
}
// some generic event listener for resolving/waiting for types
class Events{
waitForTypes = {};
waitForType(typeName, cb){
if(!this.waitForTypes[typeName]){
this.waitForTypes[typeName] = [];
}
this.waitForTypes[typeName].push(cb);
}
triggerTypeFound(typeName){
if(this.waitForTypes[typeName] && this.waitForTypes[typeName].length > 0){
for(let cb of this.waitForTypes[typeName]){
cb()
}
delete this.waitForTypes[typeName]
}
}
}
// the parser itself
class Parser extends Events{
registredTypes = [];
typePromises = [];
resolveType(element){
console.log("resolve type: "+ element.name)
this.registredTypes[element.name] = element;
this.triggerTypeFound(element.name)
}
async getType(typeId){
if(this.registredTypes[typeId]){
return Promise.resolve(this.registredTypes[typeId]);
} else {
return new Promise((resolve, reject) => {
this.waitForType(typeId, () => {
resolve(this.registredTypes[typeId])
})
});
}
}
parseElement(element){
console.log("parse Element " + element.name);
this.resolveType(element);
// getType needs to be unblocking, because it might never finish
let typePromise = this.getType(element.typeID).then(type => {
console.log("set Type for " + element.name);
element.type = type
});
this.typePromises.push(typePromise)
}
parseElements(elements){
for(let element of elements){
this.parseElement(element);
}
console.log("parsing finished", this.waitForTypes);
}
}
let elements = [
new Element("A", "B"), // Element "A" with the Type "B"
new Element("B", "B"), // Element "B" with the Type "B"
new Element("C", "B"), // Element "C" with the Type "B"
];
let parser = new Parser()
parser.parseElements(elements)
Promise.all(parser.typePromises).then(() => {
console.log("all types are resolved");
})
If you execute the above script you will see that all elements are parsed and all types are registered within the parser.
If you parse Element("A", "B") the Element A is parsed → type A is registered. The Element A has the Type B, which is not a registered type, so the parser is waiting for it to resolve.
At the end all elements are parsed and all types could be resolved so all types are resolved is printed.
So my actual Problem is: if not all types could be resolved I want to trigger a message parsing finished, not all types are resolved. But set Type .. is triggered after parsing finished. The Promises for getType are added at the end of the event loop.
Is there a way to resolve them with higher priority ? Or is the architecture of the parser badly designed ?
The parser might never resolve all types so:
let elements = [
new Element("A", "B")
];
let parser = new Parser()
parser.parseElements(elements)
should trigger a message that the parser is finished but was not able to resolve everything.

Call variable value in another .js file

I have 2 soy.js and lib-dialogs.js files.
I need to make lib-dialogs pass the value of the lineCount variable to soy.js.
I was able to do this with localStorage but because it saves in a cookie it does not update the values correctly.
In lib-dialogs there is a function called BlocklyDialogs.congratulations that calls the necessary data.
FIle:lib-dialogs.js
BlocklyDialogs.congratulations = function() {
// Add the user's code.
if (BlocklyGames.workspace) {
var linesText = document.getElementById('dialogLinesText');
linesText.textContent = '';
// Line produces warning when compiling Puzzle since there is no JavaScript
// generator. But this function is never called in Puzzle, so no matter.
var code = Blockly.JavaScript.workspaceToCode(BlocklyGames.workspace);
code = BlocklyInterface.stripCode(code);
var noComments = code.replace(/\/\/[^\n]*/g, ''); // Inline comments.
noComments = noComments.replace(/\/\*.*\*\//g, ''); /* Block comments. */
noComments = noComments.replace(/[ \t]+\n/g, '\n'); // Trailing spaces.
noComments = noComments.replace(/\n+/g, '\n'); // Blank lines.
noComments = noComments.trim();
var lineCount = noComments.split('\n').length;
var pre = document.getElementById('containerCode');
pre.textContent = code;
if (typeof prettyPrintOne == 'function') {
code = pre.innerHTML;
code = prettyPrintOne(code, 'js');
pre.innerHTML = code;
}
if (lineCount == 1) {
var text = BlocklyGames.getMsg('Games_linesOfCode1');
} else {
var text = BlocklyGames.getMsg('Games_linesOfCode2')
.replace('%1', String(lineCount));
}
linesText.appendChild(document.createTextNode(text));
}
FIle:soy.js
example "var count = BlocklyDialogs.congratulations(lineCount);"
In soy.js I need to receive the values of lineCount. I've already managed to do this using localStorage but I needed to do something more direct.
In testing I verified that the problem is in the lineCount variable because it is not passing a value to any variable even within the file itself.
I created a variable outside the blocklyDialogs.congratulations function and entered a value of 5.
I called the variable in the soy.js file and got it normally.
I need to make the lineCount pass its value.
You can use event driven programming, pub-sub model.
class EventManager {
constructor(...listeners) {
this.listeners = listeners;
}
register(fn) {
const id = this.listeners.push(fn);
return () => {
this.listeners.splice(id - 1, 1);
};
}
emit(data) {
this.listeners.forEach(fn => fn(data));
}
}
const pushEvents = new EventManager();
// JS 1
const unsubscribe1 = pushEvents.register(x => {
console.log("event:", x);
});
pushEvents.register(x => {
console.log("event:", x);
});
// JS 2
pushEvents.emit("Tets data");
//Output
// event: Tets data
// event: Tets data
unsubscribe1();
pushEvents.emit("Tets data2");
//Output
// event: Tets data2
.as-console-row {color: red!important}

Why is previousHash not showing when I console.log my test blockchain?

I am trying learn more about blockchain by building a small project using JavaScript. Can anyone explain to me why the previousHash does not show when I console.log the test blockchain?
(npm install --save crypto-js if you need SHA256)
const SHA256 = require('crypto-js/sha256');
class Block{
//Index: (Optional) tells us where the block is in the chain
//Timestamp: tells us when the block was created
//Data: Can include any kind of data; for a currency you could store details of the transaction(transfer amount, sender id, receiver id)
//previousHash: String which contains the hash of the block which came before it (Ensures data integrity)
constructor(index, timestamp, data, previousHash = ''){
this.index = index;
this.timestamp = timestamp;
this.data = data;
this.previousHash = previousHash;
//Hash of this block
this.hash = this.calculateHash();
}
//Runs values from block through a hashing function to create a hash
calculateHash(){
return SHA256(this.index + this.previousHash + this.timestamp + JSON.stringify(this.data)).toString();
}
}
//8.44
class Blockchain{
//Initializes blockchain
constructor(){
this.chain = [this.createGenesisBlock];
}
// first block needs to be created manually
//index, timeStamp, data, previousHash(there is none in this case)
createGenesisBlock(){
return new Block(0, "01/01/2017", "Genesis block", "0");
}
//Returns most recently added block
getLatestBlock(){
return this.chain[this.chain.length -1];
}
//adds a new block to the chain
addBlock(newBlock){
newBlock.previousHash = this.getLatestBlock().hash;
newBlock.hash = newBlock.calculateHash
//The chain is just an array so you can use regular array methods
this.chain.push(newBlock);
}
}
//create instance of blockchhain
let Coin = new Blockchain();
Coin.addBlock(new Block(1, "10/07/2017", {amount: 4}));
Coin.addBlock(new Block(2, "12/07/2017", {amount: 10}));
console.log(JSON.stringify(Coin, null, 4));
I expect the console.logged JSON file to contain the previousHash as well as the index, timestamp and data. It contains all except previousHash.
Thanks for the help have been scratching my head for a while trying to figure this out...
You forgot the paranthesis in the line with: this.chain = [this.createGenesisBlock()]; line, thus the first element of the chain will be a reference to a function, instead of an instance of a Block. Add the paranthesis, and it should work.
Additionally, you also forgot the paranthesis at another function call: when you are trying to call the function newBlock.hash = newBlock.calculateHash()
You also don't have hash in your console. This is the line with the error:
newBlock.hash = newBlock.calculateHash
calculateHash is a function
newBlock.hash = newBlock.calculateHash()
Now it is working:
{
"chain": [
null,
{
"index": 1,
"timestamp": "10/07/2017",
"data": {
"amount": 4
},
"hash": "8f84adcf036e9aa052a4d7e689c7b8b06070b851eff535870f5cb8f7d53ab05a"
},
{
"index": 2,
"timestamp": "12/07/2017",
"data": {
"amount": 10
},
"previousHash": "8f84adcf036e9aa052a4d7e689c7b8b06070b851eff535870f5cb8f7d53ab05a",
"hash": "a2479e7df8f2a61f97f3ae4830aff93c0d43041b4a7cbb8079c2309a915d8945"
}
]
}

Categories