mirror of
https://github.com/seigler/govobject-proposal
synced 2025-07-27 06:46:10 +00:00
add proposal validation
This commit is contained in:
parent
0bba2e8599
commit
6f6301da48
2 changed files with 152 additions and 31 deletions
|
@ -3207,6 +3207,32 @@ module.exports = [{
|
||||||
'name': 'InvalidRate',
|
'name': 'InvalidRate',
|
||||||
'message': 'Invalid exchange rate: {0}'
|
'message': 'Invalid exchange rate: {0}'
|
||||||
}]
|
}]
|
||||||
|
}, {
|
||||||
|
name: 'GovObject',
|
||||||
|
message: 'Internal Error on GovObject {0}',
|
||||||
|
errors: [{
|
||||||
|
name: 'Proposal',
|
||||||
|
message: 'Internal Error on Proposal {0}',
|
||||||
|
errors: [{
|
||||||
|
name: 'invalidDate',
|
||||||
|
message: 'Invalid Date'
|
||||||
|
}, {
|
||||||
|
name: 'invalidDateWindow',
|
||||||
|
message: 'Invalid Timespan'
|
||||||
|
}, {
|
||||||
|
name: 'invalidAddress',
|
||||||
|
message: 'Invalid Address'
|
||||||
|
}, {
|
||||||
|
name: 'invalidPayment',
|
||||||
|
message: 'Invalid Payment Amount'
|
||||||
|
}, {
|
||||||
|
name: 'invalidUrl',
|
||||||
|
message: 'Invalid URL'
|
||||||
|
}, {
|
||||||
|
name: 'invalidName',
|
||||||
|
message: 'Invalid Name'
|
||||||
|
}]
|
||||||
|
}]
|
||||||
}, {
|
}, {
|
||||||
name: 'Transaction',
|
name: 'Transaction',
|
||||||
message: 'Internal Error on Transaction {0}',
|
message: 'Internal Error on Transaction {0}',
|
||||||
|
@ -3354,6 +3380,8 @@ var JSUtil = require('../util/js');
|
||||||
var BufferReader = require('../encoding/bufferreader');
|
var BufferReader = require('../encoding/bufferreader');
|
||||||
var BufferWriter = require('../encoding/bufferwriter');
|
var BufferWriter = require('../encoding/bufferwriter');
|
||||||
|
|
||||||
|
var Address = require('../address');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a generic Governance Object
|
* Represents a generic Governance Object
|
||||||
*
|
*
|
||||||
|
@ -3422,7 +3450,6 @@ GovObject.prototype.fromString = function(string) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve a hexa string that can be used with dashd's CLI interface
|
* Retrieve a hexa string that can be used with dashd's CLI interface
|
||||||
* (decoderawtransaction, sendrawtransaction)
|
|
||||||
*
|
*
|
||||||
* @param {Object} opts allows to skip certain tests. {@see Transaction#serialize}
|
* @param {Object} opts allows to skip certain tests. {@see Transaction#serialize}
|
||||||
* @return {string}
|
* @return {string}
|
||||||
|
@ -3430,7 +3457,6 @@ GovObject.prototype.fromString = function(string) {
|
||||||
GovObject.prototype.checkedSerialize = function(opts) {
|
GovObject.prototype.checkedSerialize = function(opts) {
|
||||||
var serializationError = this.getSerializationError(opts);
|
var serializationError = this.getSerializationError(opts);
|
||||||
if (serializationError) {
|
if (serializationError) {
|
||||||
serializationError.message += ' Use uncheckedSerialize if you wish to skip security checks.';
|
|
||||||
throw serializationError;
|
throw serializationError;
|
||||||
}
|
}
|
||||||
return this.uncheckedSerialize();
|
return this.uncheckedSerialize();
|
||||||
|
@ -3458,7 +3484,6 @@ GovObject.prototype.toBuffer = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
GovObject.prototype.toBufferWriter = function(writer) {
|
GovObject.prototype.toBufferWriter = function(writer) {
|
||||||
console.log(this.dataHex());
|
|
||||||
writer.write(new Buffer(this.dataHex()));
|
writer.write(new Buffer(this.dataHex()));
|
||||||
return writer;
|
return writer;
|
||||||
};
|
};
|
||||||
|
@ -3479,33 +3504,38 @@ GovObject.shallowCopy = function(GovObject) {
|
||||||
return copy;
|
return copy;
|
||||||
};
|
};
|
||||||
|
|
||||||
GovObject.prototype._toASCII = function(string) {
|
GovObject.prototype._verifyDateFormat = function(date) {
|
||||||
var escapable = /[\\\"\x00-\x1f\x7f-\uffff]/g,
|
var parsedDate = new Date(date * 1000);
|
||||||
meta = { // table of character substitutions
|
return parsedDate;
|
||||||
'\b': '\\b',
|
};
|
||||||
'\t': '\\t',
|
|
||||||
'\n': '\\n',
|
|
||||||
'\f': '\\f',
|
|
||||||
'\r': '\\r',
|
|
||||||
'"' : '\\"',
|
|
||||||
'\\': '\\\\'
|
|
||||||
};
|
|
||||||
|
|
||||||
escapable.lastIndex = 0;
|
GovObject.prototype._verifyPayment = function(payment) {
|
||||||
return escapable.test(string) ?
|
var parsedPayment = parseFloat(payment);
|
||||||
'"' + string.replace(escapable, function (a) {
|
if(isNaN(parsedPayment)) return true;
|
||||||
var c = meta[a];
|
|
||||||
return typeof c === 'string' ? c :
|
return Boolean((parsedPayment <= 0));
|
||||||
'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
};
|
||||||
}) + '"' :
|
|
||||||
'"' + string + '"';
|
GovObject.prototype._verifyAddress = function(address, network) {
|
||||||
|
var validAddress = Address.isValid(address, network);
|
||||||
|
return validAddress;
|
||||||
|
};
|
||||||
|
|
||||||
|
GovObject.prototype._verifyUrl = function(url) {
|
||||||
|
var urlregex = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/;
|
||||||
|
return urlregex.test(url);
|
||||||
|
};
|
||||||
|
|
||||||
|
GovObject.prototype._verifyName = function(name) {
|
||||||
|
var nameregex = /^[-_a-zA-Z0-9]+$/;
|
||||||
|
return nameregex.test(name);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
module.exports = GovObject;
|
module.exports = GovObject;
|
||||||
|
|
||||||
}).call(this,require("buffer").Buffer)
|
}).call(this,require("buffer").Buffer)
|
||||||
},{"../encoding/bufferreader":14,"../encoding/bufferwriter":15,"../errors":17,"../util/buffer":46,"../util/js":47,"../util/preconditions":48,"buffer":115,"buffer-compare":113,"lodash":187}],20:[function(require,module,exports){
|
},{"../address":1,"../encoding/bufferreader":14,"../encoding/bufferwriter":15,"../errors":17,"../util/buffer":46,"../util/js":47,"../util/preconditions":48,"buffer":115,"buffer-compare":113,"lodash":187}],20:[function(require,module,exports){
|
||||||
module.exports = require('./govobject');
|
module.exports = require('./govobject');
|
||||||
|
|
||||||
module.exports.Proposal = require('./types/proposal');
|
module.exports.Proposal = require('./types/proposal');
|
||||||
|
@ -3514,6 +3544,7 @@ module.exports.Proposal = require('./types/proposal');
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var GovObject = require('../govobject');
|
var GovObject = require('../govobject');
|
||||||
|
var errors = require('../../errors');
|
||||||
var inherits = require('util').inherits;
|
var inherits = require('util').inherits;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3548,6 +3579,8 @@ Proposal.prototype.dataHex = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
Proposal.prototype._newGovObject = function() {
|
Proposal.prototype._newGovObject = function() {
|
||||||
|
this.network = "livenet";
|
||||||
|
|
||||||
this.end_epoch = "";
|
this.end_epoch = "";
|
||||||
this.name = "";
|
this.name = "";
|
||||||
this.payment_address = "";
|
this.payment_address = "";
|
||||||
|
@ -3564,15 +3597,52 @@ Proposal.prototype.fromObject = function fromObject(arg) {
|
||||||
};
|
};
|
||||||
|
|
||||||
GovObject.prototype.getSerializationError = function(opts) {
|
GovObject.prototype.getSerializationError = function(opts) {
|
||||||
|
opts = opts || {};
|
||||||
|
|
||||||
// TODO
|
// check date format
|
||||||
|
if(isNaN(this._verifyDateFormat(this.start_epoch))) {
|
||||||
|
return new errors.GovObject.Proposal.invalidDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isNaN(this._verifyDateFormat(this.end_epoch))) {
|
||||||
|
return new errors.GovObject.Proposal.invalidDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.start_epoch >= this.end_epoch) {
|
||||||
|
return new errors.GovObject.Proposal.invalidDateWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
var now = Math.round(new Date().getTime()/1000);
|
||||||
|
if (this.end_epoch < now) {
|
||||||
|
return new errors.GovObject.Proposal.invalidDateWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
// check address
|
||||||
|
if (!this._verifyAddress(this.payment_address,this.network)) {
|
||||||
|
return new errors.GovObject.Proposal.invalidAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
// check payment amount
|
||||||
|
if (this._verifyPayment(this.payment_amount)) {
|
||||||
|
return new errors.GovObject.Proposal.invalidPayment();
|
||||||
|
}
|
||||||
|
|
||||||
|
// check url
|
||||||
|
if(!this._verifyUrl(this.url)) {
|
||||||
|
return new errors.GovObject.Proposal.invalidUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
// check name
|
||||||
|
if(!this._verifyName(this.name)) {
|
||||||
|
return new errors.GovObject.Proposal.invalidName();
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
module.exports = Proposal;
|
module.exports = Proposal;
|
||||||
|
|
||||||
},{"../govobject":19,"util":241}],22:[function(require,module,exports){
|
},{"../../errors":17,"../govobject":19,"util":241}],22:[function(require,module,exports){
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
63
index.html
63
index.html
|
@ -31,6 +31,10 @@
|
||||||
copyToClipboard($(this).attr('id'));
|
copyToClipboard($(this).attr('id'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('.createProposal input').focus(function() {
|
||||||
|
$(this).removeClass('validationError');
|
||||||
|
});
|
||||||
|
|
||||||
$('#btnPrepare').click(function() {
|
$('#btnPrepare').click(function() {
|
||||||
|
|
||||||
var proposal = new ProposalGenerator(gov);
|
var proposal = new ProposalGenerator(gov);
|
||||||
|
@ -43,7 +47,7 @@
|
||||||
|
|
||||||
$('#feeTxid').on('input', function() {
|
$('#feeTxid').on('input', function() {
|
||||||
if ($(this).val().length > 0) {
|
if ($(this).val().length > 0) {
|
||||||
var submitCommand = "gobject submit " + $('#parentHash').val() + " " + $('#revision').val() + " " + $('#time').val() + " " + proposal.gov.uncheckedSerialize() + " " + $(this).val();
|
var submitCommand = "gobject submit " + $('#parentHash').val() + " " + $('#revision').val() + " " + $('#time').val() + " " + proposal.gov.serialize() + " " + $(this).val();
|
||||||
|
|
||||||
$('textarea#submitProposal').val(submitCommand);
|
$('textarea#submitProposal').val(submitCommand);
|
||||||
$('.walletCommands#walletCommandsSubmit').removeClass('hidden');
|
$('.walletCommands#walletCommandsSubmit').removeClass('hidden');
|
||||||
|
@ -69,6 +73,7 @@
|
||||||
var ProposalGenerator = function(gov) {
|
var ProposalGenerator = function(gov) {
|
||||||
this._mode = 'proposal';
|
this._mode = 'proposal';
|
||||||
this.gov = gov;
|
this.gov = gov;
|
||||||
|
this.gov.network = 'testnet';
|
||||||
|
|
||||||
// proposal basic fields
|
// proposal basic fields
|
||||||
this.gov.name = $('#name').val();
|
this.gov.name = $('#name').val();
|
||||||
|
@ -85,18 +90,62 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
ProposalGenerator.prototype.validate = function() {
|
ProposalGenerator.prototype.validate = function() {
|
||||||
var gov = this.gov;
|
try {
|
||||||
|
var gov = this.gov.serialize();
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
|
||||||
|
switch(e.message) {
|
||||||
|
case 'Invalid Timespan':
|
||||||
|
console.log("Error: invalid timespan");
|
||||||
|
$('#start_epoch, #end_epoch').addClass('validationError');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Invalid Start Date':
|
||||||
|
console.log("Error: invalid start date");
|
||||||
|
$('#start_epoch').addClass('validationError');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Invalid End Date':
|
||||||
|
console.log("Error: invalid end date");
|
||||||
|
$('#end_epoch').addClass('validationError');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Invalid Address':
|
||||||
|
console.log("Error: invalid address");
|
||||||
|
$('#payment_address').addClass('validationError');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Invalid Payment Amount':
|
||||||
|
console.log("Error: invalid payment amount");
|
||||||
|
$('#payment_amount').addClass('validationError');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Invalid URL':
|
||||||
|
console.log("Error: invalid url");
|
||||||
|
$('#url').addClass('validationError');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Invalid Name':
|
||||||
|
console.log("error: invalid name");
|
||||||
|
$('#name').addClass('validationError');
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
console.log(e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: perform validation within bitcore-lib-dash
|
|
||||||
// return gov.getSerializationError();
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
ProposalGenerator.prototype.walletCommands = function() {
|
ProposalGenerator.prototype.walletCommands = function() {
|
||||||
var gov = this.gov;
|
var gov = this.gov;
|
||||||
|
|
||||||
|
var propCommand = "gobject prepare "+$('#parentHash').val() + " " + $('#revision').val() +" " + $('#time').val() +" " + gov.serialize();
|
||||||
var propCommand = "gobject prepare "+$('#parentHash').val() + " " + $('#revision').val() +" " + $('#time').val() +" " + gov.uncheckedSerialize();
|
|
||||||
$("textarea#prepareProposal").val(propCommand);
|
$("textarea#prepareProposal").val(propCommand);
|
||||||
|
|
||||||
if(this._mode == 'proposal') {
|
if(this._mode == 'proposal') {
|
||||||
|
@ -177,6 +226,8 @@
|
||||||
#walletCommandsTx { margin-top:2em; }
|
#walletCommandsTx { margin-top:2em; }
|
||||||
#walletCommandsSubmit { margin-top:2em; }
|
#walletCommandsSubmit { margin-top:2em; }
|
||||||
|
|
||||||
|
.validationError { background-color:#ffe6e6; }
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue