Commit 11c11597 authored by Andrew Danger Lyon's avatar Andrew Danger Lyon

ripping out basis client stuff and replacing with lib-basis-client! working...

ripping out basis client stuff and replacing with lib-basis-client! working great, tests passing, slimed down packages a ton, and can now more portably talk to basis from other js projects.
parent dd0f98d4
"use strict";
const Promise = require('bluebird');
const config = require('../helpers/config');
const trans = require('../helpers/transactions');
const tx = trans.types;
const Users = require('../models/users');
exports.load = async function() {
const data = {
id: config.bootstrap_user.id,
pubkey: config.bootstrap_user.pub,
roles: ['SuperAdmin'],
email: config.bootstrap_user.email,
name: config.bootstrap_user.name,
meta: '{}',
created: new Date().toISOString(),
};
const params = {
pubkey: config.bootstrap_user.pub,
privkey: config.bootstrap_user.sec,
};
const txid = await trans.send(tx.user.TxCreate, data, params);
const status = await trans.wait(txid);
if(!status.success) {
throw new Error('helpers/bootstrap::load() -- user create failed: '+JSON.stringify(status));
}
return txid;
};
exports.unload = async function() {
const data = {
id: config.bootstrap_user.id,
memo: 'You are *fired* =D!!',
deleted: new Date().toISOString(),
};
const params = {
pubkey: config.bootstrap_user.pub,
privkey: config.bootstrap_user.sec,
message_id: 4,
};
const txid = await trans.send(tx.user.TxDelete, data, params);
const status = await trans.wait(txid);
if(!status.success) {
throw new Error('helpers/bootstrap::unload() -- user delete failed: '+JSON.stringify(status));
}
};
module.exports = Object.assign({}, require('../config/default'), require('../config/local'));
"use strict";
const fs = require('fs');
const path = require('path');
const Promise = require('bluebird');
const protobuf = require('protobufjs');
const Exonum = require('exonum-client');
const config = require('./config');
const Timestamp = {
type: (function() {
const Type = new protobuf.Type('Timestamp');
Type.add(new protobuf.Field('seconds', 1, 'int64'));
Type.add(new protobuf.Field('nanos', 2, 'int32'));
return Type;
})(),
gen: function(datestr) {
const now = new Date(datestr).getTime();
const seconds = Math.floor(now / 1000);
return {
seconds: seconds,
nanos: (now - (seconds * 1000)) * 1000000,
};
},
from: function(date) {
let ts = parseInt((date.seconds * 1000) + (date.nanos / 1000000));
return new Date(ts);
},
};
const Hash = {
type: (function() {
const Type = new protobuf.Type('Hash');
Type.add(new protobuf.Field('data', 1, 'bytes'));
return Type;
})(),
gen: function(pubkey) {
return {data: Exonum.hexadecimalToUint8Array(pubkey)};
},
};
const Pubkey = {
type: (function() {
const Type = new protobuf.Type('PublicKey');
Type.add(new protobuf.Field('data', 1, 'bytes'));
return Type;
})(),
gen: function(pubkey) {
return {data: Exonum.hexadecimalToUint8Array(pubkey)};
},
};
const CompanyType = {
map: {
UNKNOWN: 0,
PUBLIC: 1,
SYNDICATE: 2,
PRIVATE: 3,
},
type: new protobuf.Enum('CompanyType', this.map),
gen: function(val) {
return CompanyType.map[val.toUpperCase()] || 0;
},
};
const Unit = {
map: {
UNKNOWN: 0,
MILLIMETER: 1,
MILLILITER: 2,
WATTHOUR: 3,
},
type: new protobuf.Enum('Unit', this.map),
gen: function(val) {
return Unit.map[val.toUpperCase()] || 0;
},
};
const Time = {
map: {
UNKNOWN: 0,
NANOSECONDS: 1,
MILLISECONDS: 2,
SECONDS: 3,
MINUTES: 4,
HOURS: 5,
DAYS: 6,
WEEKS: 7,
YEARS: 8,
},
type: new protobuf.Enum('Time', this.map),
gen: function(val) {
return Time.map[val.toUpperCase()] || 0;
},
};
const ProcessStatus = {
map: {
UNKNOWN: 0,
NEW: 1,
ACCEPTED: 2,
PROCESSING: 3,
COMPLETED: 4,
PROXYING: 5,
FINALIZED: 6,
CANCELED: 7,
},
type: new protobuf.Enum('ProcessStatus', this.map),
gen: function(val) {
return ProcessStatus.map[val.toUpperCase()] || 0;
},
};
const CostCategory = {
map: {
UNKNOWN: 0,
INVENTORY: 1,
OPERATING: 2,
},
type: new protobuf.Enum('Category', this.map),
gen: function(val) {
return CostCategory.map[val.toUpperCase()] || 0;
},
};
// NOTE: this must usually also be mapped in helpers/transactions::make()
exports.types = {
Timestamp: Timestamp,
Hash: Hash,
Pubkey: Pubkey,
CompanyType: CompanyType,
Unit: Unit,
Time: Time,
ProcessStatus: ProcessStatus,
CostCategory: CostCategory,
};
const protos = new protobuf.Root();
protos.resolvePath = (origin, target) => {
return target;
};
protos.define('exonum').add(Pubkey.type);
protos.define('exonum').add(Hash.type);
exports.root = protos;
function load() {
const files = fs.readdirSync(config.protobuf_dir)
files.forEach(function(protofile) {
if(protofile.match(/^\./) || !protofile.match(/\.proto$/)) return;
const fullpath = fs.realpathSync(config.protobuf_dir+'/'+protofile);
const name = path.basename(fullpath, '.proto');
if(protos[name]) return protos[name];
protos.loadSync(fullpath, {keepCase: true});
});
};
load();
"use strict";
const rp = require('request-promise');
const Exonum = require('exonum-client');
const config = require('../helpers/config');
const protobuf = require('../helpers/protobuf');
const standard_api = require('../helpers/standard-api');
exports.generate = function(path, type) {
function verify(res) {
const Type = Exonum.newType(protobuf.root.lookupType(type));
try {
const obj_proof = new Exonum.MapProof(res.item_proof.object, Exonum.Hash, Type);
const tbl_proof = new Exonum.MapProof(res.item_proof.table, Exonum.Hash, Exonum.Hash);
if(res.item) {
const root_hash = Exonum.uint8ArrayToHexadecimal(new Uint8Array(res.item.history_hash.data));
const len = res.item.history_len;
const tree_proof = Exonum.merkleProof(root_hash, len, res.item_history.proof, [0, len], Type);
}
} catch(e) {
console.log('err proof: ', e);
}
}
return {
list: async function(qs) {
let res = await rp({
url: `${config.endpoint}/services/basis/v1${path}`,
json: true,
qs: qs,
});
return (res && res.items) || [];
},
get: async function(qs, options) {
options || (options = {});
const {extended} = options;
let res = await rp({
url: `${config.endpoint}/services/basis/v1${path}/info`,
json: true,
qs: qs,
});
if(!res) return null;
verify(res);
if(!extended) res = res.item;
return res;
},
};
};
"use strict";
const Exonum = require('exonum-client');
const rp = require('request-promise');
const protobuf = require('./protobuf');
const config = require('./config');
const types = {};
const message_id_map = (function() {
// these MUST be ordered in the same way as basis/src/block/transactions/mod.rs
const transactions = [
'user.TxCreate',
'user.TxUpdate',
'user.TxSetPubkey',
'user.TxSetRoles',
'user.TxDelete',
'company.TxCreatePrivate',
'company.TxUpdate',
'company.TxSetType',
'company.TxDelete',
'company_member.TxCreate',
'company_member.TxSetRoles',
'company_member.TxDelete',
'labor.TxCreate',
'labor.TxSetTime',
'product.TxCreate',
'product.TxUpdate',
'product.TxDelete',
'resource_tag.TxCreate',
'resource_tag.TxDelete',
'order.TxCreate',
'order.TxUpdateStatus',
'order.TxUpdateCostCategory',
];
const map = {};
let i = 0;
transactions.forEach((t) => { map[t] = i++; });
return map;
})();
Object.keys(message_id_map).forEach((key) => {
const [type, tx] = key.split('.');
if(!types[type]) types[type] = {};
types[type][tx] = {
type: `basis.${key}`,
msg_id: message_id_map[key],
}
});
exports.types = types;
exports.make = (type, data, params) => {
const Transaction = protobuf.root.lookupType(type.type);
const map_types = {
'google.protobuf.Timestamp': 'Timestamp',
'exonum.Hash': 'Hash',
'exonum.PublicKey': 'Pubkey',
'CompanyType': 'CompanyType',
'Product.Unit': 'Unit',
'Product.Effort.Time': 'Time',
'Order.ProcessStatus': 'ProcessStatus',
'Order.CostCategory': 'CostCategory',
};
Object.keys(Transaction.fields).forEach((field) => {
if(typeof(data[field]) == 'undefined') return;
const spec = Transaction.fields[field];
const mapping = map_types[spec.type];
if(!mapping) return;
data[field] = protobuf.types[mapping].gen(data[field]);
});
const errmsg = Transaction.verify(data);
if(errmsg) {
throw new Error(`transaction: ${type}: verification error: ${errmsg}`);
}
const trans = Exonum.newTransaction({
schema: Transaction,
author: params.pubkey,
service_id: params.service_id || config.service_id,
message_id: params.message_id || type.msg_id,
});
return trans;
};
exports.send = async (type, data, params) => {
data = JSON.parse(JSON.stringify(data));
const trans = exports.make(type, data, params);
return trans.send(`${config.endpoint}/explorer/v1/transactions`, data, params.privkey);
};
const whoswho = {};
exports.add_user = (who, pubkey, seckey) => {
whoswho[who] = {pub: pubkey, sec: seckey};
};
exports.clear_users = () => {
Object.keys(whoswho).forEach((key) => delete whoswho[key]);
};
exports.send_as = async (who, type, data, params, options) => {
options || (options = {});
const user = whoswho[who];
if(!user) throw new Error(`helpers/transactions::send_as() -- missing user ${who}`);
const newparams = Object.assign({}, {
pubkey: user.pub,
privkey: user.sec,
}, params || {});
let txid = await exports.send(type, data, newparams);
if(options.no_wait) {
return txid;
}
let status = exports.wait(txid, options);
status.txid = txid;
return status;
};
exports.get = async (txid) => {
const res = await rp({
url: `${config.endpoint}/explorer/v1/transactions?hash=${txid}`,
json: true,
});
return res;
};
function extract_status(trans) {
return {
committed: trans.type == 'committed',
success: trans.status.type == 'success',
code: trans.status.code,
description: trans.status.description,
}
}
exports.wait = async (txid, options) => {
options || (options = {});
let timeout = false;
setTimeout(() => timeout = true, options.timeout || 10000);
let trans = null;
while(true) {
const res = await rp({
url: `${config.endpoint}/explorer/v1/transactions?hash=${txid}`,
json: true,
});
if(timeout) {
if(options.raw) {
throw new Error(`helpers/transactions::wait() -- timeout`);
}
return {missing: true};
}
if(res && res.type != 'unknown') {
trans = res;
break;
}
}
if(options.raw) return trans;
return extract_status(trans);
};
exports.status = async (txid) => {
const res = await exports.get(txid);
if(!res || res.type == 'unknown') return {missing: true};
return extract_status(res);
};
"use strict";
const standard_api = require('../helpers/standard-api');
const {list, get} = standard_api.generate('/companies/members', 'basis.company_member.CompanyMember');
exports.list = list;
exports.get = get;
"use strict";
const standard_api = require('../helpers/standard-api');
const {list, get} = standard_api.generate('/companies', 'basis.company.Company');
exports.list = list;
exports.get = get;
"use strict";
const standard_api = require('../helpers/standard-api');
const {list, get} = standard_api.generate('/labor', 'basis.labor.Labor');
exports.list = list;
exports.get = get;
"use strict";
const standard_api = require('../helpers/standard-api');
const {list, get} = standard_api.generate('/orders', 'basis.order.Order');
exports.list = list;
exports.get = get;
"use strict";
const standard_api = require('../helpers/standard-api');
const {list, get} = standard_api.generate('/products', 'basis.product.Product');
exports.list = list;
exports.get = get;
"use strict";
const standard_api = require('../helpers/standard-api');
const {list, get} = standard_api.generate('/resource-tags', 'basis.resource_tag.ResourceTag');
exports.list = list;
exports.get = get;
"use strict";
const standard_api = require('../helpers/standard-api');
const {list, get} = standard_api.generate('/users', 'basis.user.User');
exports.list = list;
exports.get = get;
......@@ -64,9 +64,9 @@
"integrity": "sha512-1w52Nyx4Gq47uuu0EVcsHBxZFJgurQ+rTKS3qMHxR1GY2T8c2AJYd6vZoZ9q1rupaDjU0yT+Jc2XTyXkjeMA+Q=="
},
"@types/node": {
"version": "10.14.13",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.13.tgz",
"integrity": "sha512-yN/FNNW1UYsRR1wwAoyOwqvDuLDtVXnaJTZ898XIw/Q5cCaeVAlVwvsmXLX5PuiScBYwZsZU4JYSHB3TvfdwvQ=="
"version": "10.14.20",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.20.tgz",
"integrity": "sha512-An+MXSV8CGXz/BO9C1KKsoJ/8WDrvlNUaRMsm2h+IHZuSyQkM8U5bJJkb8ItLKA73VePG/nUK+t+EuW2IWuhsQ=="
},
"ajv": {
"version": "6.10.2",
......@@ -125,9 +125,9 @@
}
},
"big-integer": {
"version": "1.6.44",
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.44.tgz",
"integrity": "sha512-7MzElZPTyJ2fNvBkPxtFQ2fWIkVmuzw41+BZHSzpEq3ymB2MfeKp1+yXl/tS75xCx+WnyV+yb0kp+K1C3UNwmQ=="
"version": "1.6.47",
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.47.tgz",
"integrity": "sha512-9t9f7X3as2XGX8b52GqG6ox0GvIdM86LyIXASJnDCFhYNgt+A+MByQZ3W2PyMRZjEvG5f8TEbSPfEotVuMJnQg=="
},
"binary-search": {
"version": "1.3.6",
......@@ -135,9 +135,9 @@
"integrity": "sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA=="
},
"bluebird": {
"version": "3.5.5",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz",
"integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w=="
"version": "3.7.0",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.0.tgz",
"integrity": "sha512-aBQ1FxIa7kSWCcmKHlcHFlT2jt6J/l4FzC7KcPELkOJOsPOb/bccdhmIrKDfXhwFrmc7vDoDrrepFvGqjyXGJg=="
},
"caseless": {
"version": "0.12.0",
......@@ -282,9 +282,9 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"is-buffer": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz",
"integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw=="
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz",
"integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A=="
},
"is-typedarray": {
"version": "1.0.0",
......@@ -327,6 +327,18 @@
"verror": "1.10.0"
}
},
"lib-basis-client": {
"version": "git+ssh://git@gitlab.com/basis-/lib-basis-client.git#80c8d0757a7333aaf37a77041f60f87be26f70f8",
"from": "git+ssh://git@gitlab.com/basis-/lib-basis-client.git#master",
"requires": {
"bluebird": "^3.5.5",
"exonum-client": "^0.17.1",
"protobufjs": "^6.8.8",
"request": "^2.88.0",
"request-promise": "^4.2.4",
"uuid": "^3.3.2"
}
},
"lodash": {
"version": "4.17.15",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
......@@ -386,9 +398,9 @@
}
},
"psl": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.2.0.tgz",
"integrity": "sha512-GEn74ZffufCmkDDLNcl3uuyF/aSD6exEyh1v/ZSdAomB82t6G9hzJVRx0jBmLDW+VfZqks3aScmMw9DszwUalA=="
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.4.0.tgz",
"integrity": "sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw=="
},
"punycode": {
"version": "2.1.1",
......@@ -524,9 +536,9 @@
}
},
"uuid": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz",
"integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ=="
},
"verror": {
"version": "1.10.0",
......
......@@ -6,10 +6,6 @@
"license": "GPLv3",
"dependencies": {
"bluebird": "^3.5.5",
"exonum-client": "^0.17.1",
"protobufjs": "^6.8.8",
"request": "^2.88.0",
"request-promise": "^4.2.4",
"uuid": "^3.3.2"
"lib-basis-client": "git+ssh://git@gitlab.com:basis-/lib-basis-client.git#master"
}
}
"use strict";
const Basis = require('lib-basis-client');
Basis.init(__dirname+'/../config');
const uuid = require('uuid/v4');
const Exonum = require('exonum-client');
const trans = require('../helpers/transactions');
const trans = Basis.transactions
const tx = trans.types;
const bootstrap = require('../helpers/bootstrap');
const config = require('../helpers/config');
const Users = require('../models/users');
const bootstrap = Basis.bootstrap;
const config = Basis.config;
const Users = Basis.models.users;
describe('users', function() {
jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000;
......
"use strict";
const Basis = require('lib-basis-client');
Basis.init(__dirname+'/../config');
const uuid = require('uuid/v4');
const Exonum = require('exonum-client');
const trans = require('../helpers/transactions');
const trans = Basis.transactions
const tx = trans.types;
const bootstrap = require('../helpers/bootstrap');
const config = require('../helpers/config');
const Companies = require('../models/companies');
const bootstrap = Basis.bootstrap;
const config = Basis.config;
const Companies = Basis.models.companies;
describe('companies', function() {
jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000;
......
"use strict";
const Basis = require('lib-basis-client');
Basis.init(__dirname+'/../config');
const uuid = require('uuid/v4');
const Exonum = require('exonum-client');
const trans = require('../helpers/transactions');
const trans = Basis.transactions
const tx = trans.types;
const bootstrap = require('../helpers/bootstrap');
const config = require('../helpers/config');
const Members = require('../models/companies-members');
const bootstrap = Basis.bootstrap;
const config = Basis.config;
const Members = Basis.models.companies_members;
describe('company members', function() {
jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000;
......
"use strict";
const Basis = require('lib-basis-client');
Basis.init(__dirname+'/../config');
const uuid = require('uuid/v4');
const Exonum = require('exonum-client');
const trans = require('../helpers/transactions');
const trans = Basis.transactions
const tx = trans.types;
const bootstrap = require('../helpers/bootstrap');
const config = require('../helpers/config');
const Labor = require('../models/labor');
const Timestamp = require('../helpers/protobuf').types.Timestamp;
const bootstrap = Basis.bootstrap;
const config = Basis.config;
const Labor = Basis.models.labor;
const Timestamp = Basis.protobuf.types.Timestamp;
describe('labor', function() {