const NeoBlocks = require("neoblocks-common");
const config = {
request: {
node: "http://127.0.0.1:10332",
timeout: 30000
}
};
let service = new NeoBlocks.Service(config);
let blockchain = new NeoBlocks.Blockchain(config);
service.log(["NeoBlocks Agent"]);
const init = async () => {
let block, height;
try {
height = await service.fetch("getblockcount", []);
} catch (error) {
service.exit(error)
};
try {
service.log(["Requesting block from node:", (height-1)], "debug");
block = await service.fetch("getblock", [(height-1), 1]);
} catch (error) {
service.exit(error)
};
let Block;
try {
Block = new blockchain.Block(block);
} catch (error) {
service.exit(error);
};
if (!service.is.array(block.tx)) { service.exit("Unable to retrieve transactions from block"); };
for (let index in block.tx) {
let transaction = block.tx[index];
try {
let Transaction = new blockchain.Transaction(transaction);
for (let index in transaction["vin"]) {
let Input = new blockchain.Input(transaction["vin"][index]);
Transaction.vin.push(Input);
};
for (let index in transaction["vout"]) {
let Output = new blockchain.Output(transaction["vout"][index]);
Transaction.vout.push(Output);
};
switch (transaction["type"]) {
case "MinerTransaction":
service.validate(transaction, {nonce:0});
break;
case "ClaimTransaction":
service.validate(transaction, {claims:[]});
Transaction.assign({
claims: []
});
for (let index in transaction["claims"]) {
let Claim = new blockchain.Claim(transaction["claims"][index]);
Transaction.claims.push(Claim);
};
break;
case "EnrollmentTransaction":
service.validate(transaction, {pubkey:""});
Transaction.assign({
pubkey: transaction["pubkey"]
});
break;
case "RegisterTransaction":
service.validate(transaction, {asset:{type:"",name:[],amount:"",precision:0,admin:""}});
Transaction.assign({
asset: {
type: transaction["asset"]["type"],
name: transaction["asset"]["name"],
amount: transaction["asset"]["amount"],
precision: transaction["asset"]["precision"],
admin: transaction["asset"]["admin"]
}
});
break;
case "StateTransaction":
service.validate(transaction, {descriptors:[]});
Transaction.assign({
descriptors: []
});
for (let index in transaction["descriptors"]) {
let Descriptor = new blockchain.Descriptor(transaction["descriptors"][index]);
Transaction.descriptors.push(Descriptor);
};
break;
case "PublishTransaction":
service.validate(transaction, {contract:{code:{hash:"",script:"",parameters:[],returntype:""},needstorage:true,name:"",version:"",author:"",email:"",description:""}});
Transaction.assign({
contract: {
code: {
hash: transaction["contract"]["code"]["hash"],
script: transaction["contract"]["code"]["script"],
parameters: transaction["contract"]["code"]["parameters"],
returntype: transaction["contract"]["code"]["returntype"]
},
needstorage: transaction["contract"]["needstorage"],
name: transaction["contract"]["name"],
version: transaction["contract"]["version"],
author: transaction["contract"]["author"],
email: transaction["contract"]["email"],
description: transaction["contract"]["description"]
}
});
break;
case "InvocationTransaction":
service.validate(transaction, {gas:"",script:""});
Transaction.assign({
gas: transaction["gas"],
script: transaction["script"],
executions: []
});
try {
service.log(["Fetching events for transaction:",transaction["txid"]], "debug");
let data = await service.fetch("geteventlog", [transaction["txid"]]);
service.validate(data, {txid:"",executions:[]});
for (let index in data["executions"]) {
let execution = data["executions"][index];
let Execution = new blockchain.Execution(execution);
let transfers = function (event) {
let from, to, amount, integer = false;
if (event["type"] != "Runtime.Notify") { return; };
if (event["state"]["type"] != "Array") { return; };
if (event["state"]["value"].length != 4) { return; };
if (event["state"]["value"][0]["type"] == "ByteArray" && event["state"]["value"][0]["value"] == "7472616e73666572") {
if (event["state"]["value"][1]["type"] != "ByteArray") { return; }
if (event["state"]["value"][2]["type"] != "ByteArray") { return; }
if (event["state"]["value"][3]["type"] != "ByteArray" && event["state"]["value"][3]["type"] != "Integer") { return; }
try {
if (event["state"]["value"][1]["value"] == "") {
from = "";
} else {
from = service.neon.wallet.getAddressFromScriptHash(service.neon.u.reverseHex(event["state"]["value"][1]["value"]));
if (!service.neon.wallet.isAddress(from)) { from = ""; };
};
if (event["state"]["value"][2]["value"] == "") {
to = "";
} else {
to = service.neon.wallet.getAddressFromScriptHash(service.neon.u.reverseHex(event["state"]["value"][2]["value"]));
if (!service.neon.wallet.isAddress(to)) { to = ""; };
};
if (event["state"]["value"][3]["value"] == "") {
amount = 0;
} else {
if (event["state"]["value"][3]["type"] == "ByteArray") {
amount = service.neon.u.Fixed8.fromReverseHex(event["state"]["value"][3]["value"]).toString();
} else if (event["state"]["value"][3]["type"] == "Integer") {
amount = event["state"]["value"][3]["value"];
integer = true;
};
};
return { contract: event["contract"], from: from, to: to, amount: amount, integer: integer };
} catch (error) {
return;
};
} else {
return;
};
};
for (let index in execution["events"]) {
let Event = new blockchain.Event(execution["events"][index]);
let transfer = transfers(execution["events"][index]);
Execution.events.push(Event);
if (transfer) {
service.log(['Pushing transfer:', transfer])
Execution.transfers.push(transfer);
};
};
Transaction.executions.push(Execution);
};
} catch (error) {
service.exit(error)
};
break;
};
Block.transactions.push(Transaction);
} catch (error) {
service.exit(error);
};
}
service.log(JSON.stringify(Block));
};
init();