Genesis commit
This commit is contained in:
parent
9258d6f234
commit
db36cb33cf
18
config/default.json
Normal file
18
config/default.json
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"bcrypt" : {
|
||||||
|
"salt" : 11
|
||||||
|
},
|
||||||
|
"database" : {
|
||||||
|
"dialect" : "sqlite",
|
||||||
|
"host" : "localhost",
|
||||||
|
"database" : "databases",
|
||||||
|
"username" : "databases",
|
||||||
|
"password" : "thisisfortheotherdbtypes",
|
||||||
|
"storage" : "database.sqlite",
|
||||||
|
"logging": false
|
||||||
|
// Encryption on database...
|
||||||
|
// "dialectOptions": {
|
||||||
|
// "encrypt": true
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
75
lib/commands/add-lock.js
Normal file
75
lib/commands/add-lock.js
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
const persistence = require("../core/persistence/persistence");
|
||||||
|
const cryptoUtil = require("../core/cryptoUtil");
|
||||||
|
|
||||||
|
module.exports.description = "Add lock which we will use our keys on."
|
||||||
|
|
||||||
|
module.exports.builder = (yargs) => {
|
||||||
|
return yargs
|
||||||
|
.usage(`Usage: $0 add-lock [options]`)
|
||||||
|
.help(false)
|
||||||
|
.version(false)
|
||||||
|
.option('lock-definition', {
|
||||||
|
describe: 'New lock to add to our system',
|
||||||
|
type: 'string'
|
||||||
|
})
|
||||||
|
.demandOption(['lock-definition'])
|
||||||
|
.argv;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.handler = (argv) => {
|
||||||
|
console.log("Add lock which we will use our keys on.");
|
||||||
|
console.log("Lock Definition: ", argv["lock-definition"]);
|
||||||
|
|
||||||
|
const lockDefintion = argv["lock-definition"] || argv["lock-definition"].js;
|
||||||
|
const challenge = JSON.parse(lockDefintion);
|
||||||
|
const registerationMessage = JSON.parse(challenge.message);
|
||||||
|
|
||||||
|
// TODO: Validate lock-definition is of the correct format...
|
||||||
|
persistence().LoadDB()
|
||||||
|
.then(db => {
|
||||||
|
// TODO validate lock definition has all the parameters we need
|
||||||
|
// TODO: Verify challenge comes from a service we know...
|
||||||
|
return db.ExtendedPublicKey.findOne({
|
||||||
|
where: {
|
||||||
|
xpub: challenge.xpub
|
||||||
|
},
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
association: db.ExtendedPublicKey.Key // TODO: update this to wallet
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}).then(extendedPublicKey => {
|
||||||
|
if (extendedPublicKey) {
|
||||||
|
const encryptedKey = extendedPublicKey.key.encryptedPrivateKey;
|
||||||
|
const password = "vanished";
|
||||||
|
const walletXpriv = cryptoUtil.decrypt(encryptedKey, password);
|
||||||
|
|
||||||
|
var challengeDerivationPath = `${extendedPublicKey.derivationPath}/${challenge.derivationPath.split("c/")[1]}`;
|
||||||
|
|
||||||
|
const signature = cryptoUtil.signMessage(walletXpriv, challengeDerivationPath, challenge.message)
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: save lock
|
||||||
|
return db.Lock.create({
|
||||||
|
userIdentifier: registerationMessage.userIdentifier,
|
||||||
|
url: registerationMessage.url,
|
||||||
|
signature: signature.toString('hex'),
|
||||||
|
message: challenge.message,
|
||||||
|
extendedPublicKeyId: extendedPublicKey.id
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
console.error("Sorry we can't create a lock with xpub: ", challenge.xpub);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}).then(lock => {
|
||||||
|
if(lock) {
|
||||||
|
console.log("Lock: ", lock.id);
|
||||||
|
console.log("Signature: ", lock.signature);
|
||||||
|
} else {
|
||||||
|
console.error("Failed to create the lock.");
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
73
lib/commands/authenticate-challenge.js
Normal file
73
lib/commands/authenticate-challenge.js
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
const persistence = require("../core/persistence/persistence");
|
||||||
|
const cryptoUtil = require("../core/cryptoUtil");
|
||||||
|
|
||||||
|
module.exports.description = "Sign a challenge to authenticate papao"
|
||||||
|
|
||||||
|
module.exports.builder = (yargs) => {
|
||||||
|
return yargs
|
||||||
|
// .usage(`Usage: $0 add-lock [options]`)
|
||||||
|
.help(false)
|
||||||
|
.version(false)
|
||||||
|
.option('challenge', {
|
||||||
|
describe: 'challenge that needs to be signed',
|
||||||
|
type: 'string'
|
||||||
|
})
|
||||||
|
.option('domain-url', {
|
||||||
|
describe: 'override domain url belong to the service making the challenge',
|
||||||
|
type: 'string'
|
||||||
|
})
|
||||||
|
.option('user-identifier', {
|
||||||
|
describe: 'override user identifier which will be used to sign this challenge',
|
||||||
|
type: 'string'
|
||||||
|
})
|
||||||
|
.demandOption(['challenge'])
|
||||||
|
.argv;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.handler = (argv) => {
|
||||||
|
const challenge = JSON.parse(argv.challenge);
|
||||||
|
// TODO get userIdentifier and domainUrl from challenge
|
||||||
|
const loginRequest = JSON.parse(challenge.message);
|
||||||
|
const domainUrl = argv.domainUrl || loginRequest.domainUrl;
|
||||||
|
const userIdentifier = argv.userIdentifier || loginRequest.userIdentifier;
|
||||||
|
persistence().LoadDB()
|
||||||
|
.then(db => {
|
||||||
|
console.log("Looking for");
|
||||||
|
console.log("url: ", domainUrl);
|
||||||
|
console.log("userIdentifier: ", userIdentifier);
|
||||||
|
|
||||||
|
return db.Lock.findOne({
|
||||||
|
where: {
|
||||||
|
url: domainUrl,
|
||||||
|
userIdentifier: userIdentifier
|
||||||
|
},
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
association: db.Lock.ExtendedPublicKey,
|
||||||
|
require: true,
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
association: db.ExtendedPublicKey.Key, // TODO rename key to wallet
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
.then(lock => {
|
||||||
|
if(lock) {
|
||||||
|
// Sign the message with the key that corresponds with this lock...
|
||||||
|
const encryptedKey = lock.extendedPublicKey.key.encryptedPrivateKey;
|
||||||
|
const password = "vanished";
|
||||||
|
const walletXpriv = cryptoUtil.decrypt(encryptedKey, password);
|
||||||
|
|
||||||
|
var challengeDerivationPath = `${lock.extendedPublicKey.derivationPath}/${challenge.derivationPath.split("c/")[1]}`;
|
||||||
|
|
||||||
|
const signature = cryptoUtil.signMessage(walletXpriv, challengeDerivationPath, challenge.message)
|
||||||
|
console.log("Signature: ", signature.toString('hex'));
|
||||||
|
} else {
|
||||||
|
console.error("Failed to find a lock with these parameters");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
41
lib/commands/create-keys.js
Normal file
41
lib/commands/create-keys.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
const persistence = require("../core/persistence/persistence");
|
||||||
|
const cryptoUtil = require("../core/cryptoUtil");
|
||||||
|
|
||||||
|
const bip39 = require('bip39');
|
||||||
|
const bip32 = require('bip32');
|
||||||
|
|
||||||
|
module.exports.description = "Create keys using a randomly generated seed";
|
||||||
|
|
||||||
|
module.exports.builder = (yargs) => {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.handler = (argv) => {
|
||||||
|
console.log("Create keys using a randomly generated seed");
|
||||||
|
persistence().LoadDB()
|
||||||
|
.then(db => {
|
||||||
|
const mnemonic = bip39.generateMnemonic();
|
||||||
|
console.log("Backup generated Mnemonic: ", mnemonic);
|
||||||
|
|
||||||
|
// TODO: validate user backed up mnemonic
|
||||||
|
const seed = bip39.mnemonicToSeedSync(mnemonic);
|
||||||
|
console.log("Seed: ", seed.toString('hex'))
|
||||||
|
const node = bip32.fromSeed(seed);
|
||||||
|
console.log("xpriv: ", node.toBase58());
|
||||||
|
|
||||||
|
// TODO: Get user key password
|
||||||
|
const password = "vanished";
|
||||||
|
// TODO: Encrypt text securely...
|
||||||
|
const encryptedPrivateKey = cryptoUtil.encrypt(node.toBase58(), password);
|
||||||
|
|
||||||
|
console.log("Encrypted Private Key: ", encryptedPrivateKey);
|
||||||
|
|
||||||
|
// Check if a key exist...
|
||||||
|
db.Key.create({
|
||||||
|
encryptedPrivateKey: encryptedPrivateKey,
|
||||||
|
name: "FirstKey"
|
||||||
|
}).then(key => {
|
||||||
|
console.log("Successfully created: ", key.name)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
9
lib/commands/drop-keys.js
Normal file
9
lib/commands/drop-keys.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
module.exports.description = "Drop the keys we have instantiated"
|
||||||
|
|
||||||
|
module.exports.builder = (yargs) => {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.handler = (argv) => {
|
||||||
|
console.log("Drop the keys we have instantiated");
|
||||||
|
}
|
59
lib/commands/random-xpub.js
Normal file
59
lib/commands/random-xpub.js
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
const persistence = require("../core/persistence/persistence");
|
||||||
|
const cryptoUtil = require("../core/cryptoUtil");
|
||||||
|
|
||||||
|
const bip32 = require('bip32');
|
||||||
|
|
||||||
|
module.exports.description = "Get random xpub to use on a service"
|
||||||
|
|
||||||
|
module.exports.builder = (yargs) => {
|
||||||
|
return yargs.argv;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.handler = (argv) => {
|
||||||
|
console.log("Get random xpub to use on a service");
|
||||||
|
persistence().LoadDB()
|
||||||
|
.then(db => {
|
||||||
|
db.Key.findOne({
|
||||||
|
where: {
|
||||||
|
name: "FirstKey"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(key => {
|
||||||
|
// TODO: Load password from config...
|
||||||
|
if(key) {
|
||||||
|
const password = "vanished";
|
||||||
|
|
||||||
|
console.log("Encrypted: ", key.encryptedPrivateKey);
|
||||||
|
|
||||||
|
const decryptedPrivateKey = cryptoUtil.decrypt(key.encryptedPrivateKey, password);
|
||||||
|
console.log("Decrypted: ", decryptedPrivateKey);
|
||||||
|
const masterNode = bip32.fromBase58(decryptedPrivateKey);
|
||||||
|
|
||||||
|
console.log("Node: ", masterNode.toBase58());
|
||||||
|
|
||||||
|
const derivationPath = `m/${cryptoUtil.randomDerivationPath(true)}`
|
||||||
|
|
||||||
|
const xpubNode = masterNode.derivePath(derivationPath);
|
||||||
|
console.log("Xpub: ", xpubNode.neutered().toBase58());
|
||||||
|
|
||||||
|
// TODO save xpub and derivation path in db...
|
||||||
|
return db.ExtendedPublicKey.create({
|
||||||
|
xpub: xpubNode.neutered().toBase58(),
|
||||||
|
derivationPath: derivationPath,
|
||||||
|
keyId: key.id // TODO rename this to walletID
|
||||||
|
// TODO add name if availabe...
|
||||||
|
}).catch(error => {
|
||||||
|
console.error("Failed to create extended public key: ", error);
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
console.error("Couldn't create xpub without key")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(extendedPublicKey => {
|
||||||
|
console.log("Extened public key: ", extendedPublicKey.xpub);
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error("Failed to find key: ", error);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
9
lib/commands/restore-keys.js
Normal file
9
lib/commands/restore-keys.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
module.exports.description = "Restore keys using a seed if keys haven't been in"
|
||||||
|
|
||||||
|
module.exports.builder = (yargs) => {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.handler = (argv) => {
|
||||||
|
console.log("Restore keys using a seed if keys haven't been in");
|
||||||
|
}
|
18
lib/commands/show-keys.js
Normal file
18
lib/commands/show-keys.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
const persistence = require("../core/persistence/persistence");
|
||||||
|
|
||||||
|
module.exports.description = "Show the keys we have instantiate"
|
||||||
|
|
||||||
|
module.exports.builder = (yargs) => {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.handler = (argv) => {
|
||||||
|
console.log("Show the keys we have instantiate");
|
||||||
|
persistence().LoadDB()
|
||||||
|
.then(db => {
|
||||||
|
db.Key.findAll()
|
||||||
|
.then(keys => {
|
||||||
|
console.log("Keys: ", keys.map(k => k.name));
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
19
lib/commands/show-locks.js
Normal file
19
lib/commands/show-locks.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
const persistence = require("../core/persistence/persistence");
|
||||||
|
|
||||||
|
module.exports.description = "Show all locks our keys have access to"
|
||||||
|
module.exports.builder = (yargs) => {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.handler = (argv) => {
|
||||||
|
console.log("Show all locks our keys have access to.");
|
||||||
|
persistence().LoadDB()
|
||||||
|
.then(db => {
|
||||||
|
db.Lock.findAll()
|
||||||
|
.then(locks => {
|
||||||
|
console.log("locks: ", locks.map(l => {
|
||||||
|
return l
|
||||||
|
}));
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
25
lib/commands/show-xpubs.js
Normal file
25
lib/commands/show-xpubs.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
const persistence = require("../core/persistence/persistence");
|
||||||
|
|
||||||
|
module.exports.description = "Show the ExtendedPublicKeys we have created"
|
||||||
|
|
||||||
|
module.exports.builder = (yargs) => {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.handler = (argv) => {
|
||||||
|
console.log("Show the ExtendedPublicKeys we have created");
|
||||||
|
persistence().LoadDB()
|
||||||
|
.then(db => {
|
||||||
|
db.ExtendedPublicKey.findAll()
|
||||||
|
.then(extendedPublicKey => {
|
||||||
|
console.log("Keys: ", extendedPublicKey.map(k => {
|
||||||
|
return {
|
||||||
|
id: k.id,
|
||||||
|
name: k.name,
|
||||||
|
xpub: k.xpub,
|
||||||
|
derivationPath: k.derivationPath
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
9
lib/commands/verify-message.js
Normal file
9
lib/commands/verify-message.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
module.exports.description = "Verify a message was signed by a specific key"
|
||||||
|
|
||||||
|
module.exports.builder = (yargs) => {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.handler = (argv) => {
|
||||||
|
console.log("Verify message using one of the keys");
|
||||||
|
}
|
58
lib/core/cryptoUtil.js
Normal file
58
lib/core/cryptoUtil.js
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
const crypto = require('crypto');
|
||||||
|
const algorithm = 'aes-256-ctr';
|
||||||
|
const bip32 = require('bip32');
|
||||||
|
|
||||||
|
module.exports.encrypt = (plainText, password) => {
|
||||||
|
// TODO encrypt text
|
||||||
|
// const cipher = crypto.createCipheriv(algorithm, password);
|
||||||
|
|
||||||
|
// var cipherText = cipher.update(plainText, 'utf8', 'hex');
|
||||||
|
// cipher += cipher.final('hex');
|
||||||
|
|
||||||
|
// console.log("CipherText: ", cipherText);
|
||||||
|
return plainText;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.decrypt = (cipherText, password) => {
|
||||||
|
// TODO decrypt cipherText
|
||||||
|
// const decipher = crypto.createDecipheriv(algorithm, password)
|
||||||
|
|
||||||
|
// var plainText = decipher.update(cipherText, 'hex', 'utf8');
|
||||||
|
// plainText += decipher.final('utf8');
|
||||||
|
|
||||||
|
return cipherText;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.randomDerivationPath = function(hardenedDerivation) {
|
||||||
|
// TODO harden derivation path
|
||||||
|
var randomNumbers = [];
|
||||||
|
|
||||||
|
for(var i = 0; i < 3; i++) {
|
||||||
|
randomNumbers.push(parseInt(crypto.randomBytes(3).toString('hex'), 16))
|
||||||
|
}
|
||||||
|
|
||||||
|
return randomNumbers.join('/')
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.verifyMessage = function(base58Key, derivationPath, message, signature) {
|
||||||
|
if(derivationPath.startsWith("a/")) {
|
||||||
|
derivationPath = derivationPath.split("a/")[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(derivationPath.startsWith("c/")) {
|
||||||
|
derivationPath = derivationPath.split("c/")[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
const verificationNode = bip32.fromBase58(base58Key).derivePath(derivationPath);
|
||||||
|
const hash = crypto.createHash('sha256').update(message, 'utf8').digest();
|
||||||
|
|
||||||
|
return verificationNode.verify(hash, Buffer.from(signature, 'hex'));
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.signMessage = function(base58Key, derivationPath, message) {
|
||||||
|
let signingNode = bip32.fromBase58(base58Key).derivePath(derivationPath);
|
||||||
|
|
||||||
|
var hash = crypto.createHash('sha256').update(message, 'utf8').digest();
|
||||||
|
|
||||||
|
return signingNode.sign(hash);
|
||||||
|
}
|
37
lib/core/persistence/models/extendedPublicKey.js
Normal file
37
lib/core/persistence/models/extendedPublicKey.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
module.exports = function (sequelize, DataTypes, options) {
|
||||||
|
const model = sequelize.define("extendedPublicKey", {
|
||||||
|
id: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
defaultValue: function() {
|
||||||
|
return options.generateUniqueId()
|
||||||
|
},
|
||||||
|
primaryKey: true,
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
xpub: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
// TODO add validation
|
||||||
|
allowNull: false,
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
derivationPath: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
// TODO add validation...
|
||||||
|
allowNull: false,
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
unique: true
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
comment: "Exteneded public keys."
|
||||||
|
});
|
||||||
|
|
||||||
|
model.associate = (db) => {
|
||||||
|
// TODO Update key to wallet...
|
||||||
|
model.Key = model.belongsTo(db.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return model;
|
||||||
|
};
|
30
lib/core/persistence/models/key.js
Normal file
30
lib/core/persistence/models/key.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
module.exports = function (sequelize, DataTypes, options) {
|
||||||
|
const model = sequelize.define("key", { // TODO: Rename to wallet
|
||||||
|
id: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
defaultValue: function() {
|
||||||
|
return options.generateUniqueId()
|
||||||
|
},
|
||||||
|
primaryKey: true,
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
encryptedPrivateKey: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: false
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
unique: true
|
||||||
|
}
|
||||||
|
// TODO: Add order to allow for user to set default keys
|
||||||
|
}, {
|
||||||
|
comment: "The keys we are using in our system (seedphrase)."
|
||||||
|
});
|
||||||
|
|
||||||
|
model.associate = (db) => {
|
||||||
|
model.Locks = model.hasMany(db.Lock);
|
||||||
|
model.ExtendedPublicKeys = model.hasMany(db.ExtendedPublicKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
return model;
|
||||||
|
};
|
39
lib/core/persistence/models/lock.js
Normal file
39
lib/core/persistence/models/lock.js
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
module.exports = function (sequelize, DataTypes, options) {
|
||||||
|
const model = sequelize.define("lock", {
|
||||||
|
id: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
defaultValue: function() {
|
||||||
|
return options.generateUniqueId()
|
||||||
|
},
|
||||||
|
primaryKey: true,
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
userIdentifier: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: false
|
||||||
|
},
|
||||||
|
url: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: false
|
||||||
|
},
|
||||||
|
signature: {
|
||||||
|
// Derivation from the master key...
|
||||||
|
// TODO: Add validation...
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: false,
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
message: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: false
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
comment: "lock which our keys has access to"
|
||||||
|
});
|
||||||
|
|
||||||
|
model.associate = (db) => {
|
||||||
|
model.ExtendedPublicKey = model.belongsTo(db.ExtendedPublicKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
return model;
|
||||||
|
};
|
82
lib/core/persistence/persistence.js
Normal file
82
lib/core/persistence/persistence.js
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = function () {
|
||||||
|
var db = {};
|
||||||
|
|
||||||
|
const config = require('config');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const nanoid = require('nanoid');
|
||||||
|
|
||||||
|
var dbOptions = {
|
||||||
|
db: db,
|
||||||
|
generateUniqueId: (customIdSize) => {
|
||||||
|
var idSize = customIdSize || 11;
|
||||||
|
return nanoid(idSize); //=> "hsCc0ocrXkc"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
dbOptions.Sequelize = require('sequelize');
|
||||||
|
|
||||||
|
dbOptions.sequelize = new dbOptions.Sequelize(config.get('database'));
|
||||||
|
|
||||||
|
// Load all the models...
|
||||||
|
var modelDir = path.join(__dirname, './models/');
|
||||||
|
fs.readdirSync(modelDir)
|
||||||
|
.filter(file => {
|
||||||
|
return (file.indexOf('.') !== 0) && (file !== "index.js") && (file.slice(-3) === '.js');
|
||||||
|
})
|
||||||
|
.forEach(file => {
|
||||||
|
// const model = sequelize['import'](path.join(modelDir, file));
|
||||||
|
const model = require(path.join(modelDir, file))(dbOptions.sequelize, dbOptions.Sequelize, dbOptions);
|
||||||
|
|
||||||
|
// Format the Model Name like we have for this project...
|
||||||
|
var modelName = model.name;
|
||||||
|
modelName = modelName.replace(modelName[0], modelName[0].toUpperCase());
|
||||||
|
|
||||||
|
// Add model to the db...
|
||||||
|
db[modelName] = model;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Time for the associations...
|
||||||
|
Object.keys(db).forEach(modelName => {
|
||||||
|
if (db[modelName].associate) {
|
||||||
|
db[modelName].associate(db);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
db.LoadDB = () => {
|
||||||
|
db.Sequelize = dbOptions.Sequelize;
|
||||||
|
db.sequelize = dbOptions.sequelize;
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
dbOptions.sequelize.sync()
|
||||||
|
.then(() => {
|
||||||
|
resolve(db);
|
||||||
|
}).catch(error => {
|
||||||
|
// Do the things...
|
||||||
|
reject(error);
|
||||||
|
console.error('Unable to connect to the database:', error);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
db.updateDatabaseFromModels = () => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
dbOptions.sequelize.sync({
|
||||||
|
alter: true
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
resolve(true);
|
||||||
|
console.log("DB update successful.");
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
// Do the things...
|
||||||
|
reject(error);
|
||||||
|
console.error('Unable to connect to the database:', error);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return db;
|
||||||
|
};
|
||||||
|
|
31
lib/hd-auth-wallet.js
Normal file
31
lib/hd-auth-wallet.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
const bip32 = require("bip32");
|
||||||
|
|
||||||
|
const yargs = require('yargs');
|
||||||
|
const path = require('path');
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
const cli = yargs
|
||||||
|
.help()
|
||||||
|
.version()
|
||||||
|
.strict();
|
||||||
|
|
||||||
|
// Lets load up all the commands written in the commands directory
|
||||||
|
var commandsDirectory = path.join(__dirname, './commands/');
|
||||||
|
fs.readdirSync(commandsDirectory)
|
||||||
|
.filter(file => {
|
||||||
|
return (file.indexOf('.') !== 0) && (file !== "index.js") && (file.slice(-3) === '.js');
|
||||||
|
})
|
||||||
|
.forEach(file => {
|
||||||
|
const command = require(path.join(commandsDirectory, file));
|
||||||
|
|
||||||
|
cli.command(file, command.description, command);
|
||||||
|
});
|
||||||
|
|
||||||
|
const args = cli.argv;
|
||||||
|
|
||||||
|
// show help if no command provided
|
||||||
|
if (!args._[0]) {
|
||||||
|
cli.showHelp();
|
||||||
|
}
|
1529
package-lock.json
generated
Normal file
1529
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
23
package.json
Normal file
23
package.json
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"name": "hd-auth-wallet",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "example wallet features for hd-auth use.",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"bip32": "^2.0.4",
|
||||||
|
"bip38": "^3.0.0",
|
||||||
|
"bip39": "^3.0.2",
|
||||||
|
"config": "^3.2.4",
|
||||||
|
"nanoid": "^2.1.7",
|
||||||
|
"sequelize": "^5.21.2",
|
||||||
|
"sqlite3": "^4.1.0",
|
||||||
|
"yargs": "^15.0.2"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"hd-auth-wallet": "./lib/index.js"
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user