refactoring of Address
This commit is contained in:
parent
ebddafcaa7
commit
a642114fb5
139
Address.js
139
Address.js
|
@ -1,143 +1,22 @@
|
|||
require('classtool');
|
||||
|
||||
function ClassSpec(b) {
|
||||
var base58 = b.base58 || require('base58-native').base58Check;
|
||||
var superclass = b.superclass || require('./util/VersionedData').class();
|
||||
|
||||
// Constructor. Takes the following forms:
|
||||
// new Address();
|
||||
// new Address(<base58_address_string>)
|
||||
// new Address(<21-byte-buffer>)
|
||||
// new Address(<data>, <encoding>)
|
||||
// new Address(<version>, <20-byte-hash>)
|
||||
function Address(arg1, arg2) {
|
||||
if(typeof arg1 == 'number') {
|
||||
this.data = new Buffer(21);
|
||||
this.__proto__ = encodings['binary'];
|
||||
this.version(arg1);
|
||||
this.hash(arg2);
|
||||
} else {
|
||||
this.data = arg1 || new Buffer(21);
|
||||
if(!arg2 && (typeof arg1 == 'string')) {
|
||||
this.__proto__ = encodings['base58'];
|
||||
} else {
|
||||
this.__proto__ = encodings[arg2 || 'binary'];
|
||||
}
|
||||
}
|
||||
function Address() {
|
||||
Address.super(this, arguments);
|
||||
};
|
||||
|
||||
// get or set the bitcoin address version (the first byte of the address)
|
||||
Address.prototype.version = function(num) {
|
||||
if(num || (num === 0)) {
|
||||
this.doAsBinary(function() {this.data.writeUInt8(num, 0);});
|
||||
return num;
|
||||
}
|
||||
return this.as('binary').readUInt8(0);
|
||||
};
|
||||
Address.superclass = superclass;
|
||||
superclass.applyEncodingsTo(Address);
|
||||
|
||||
// get or set the hash data (as a Buffer object)
|
||||
Address.prototype.hash = function(data) {
|
||||
if(data) {
|
||||
this.doAsBinary(function() {data.copy(this.data,1);});
|
||||
return data;
|
||||
}
|
||||
return this.as('binary').slice(1);
|
||||
};
|
||||
|
||||
// get or set the encoding used (transforms data)
|
||||
Address.prototype.encoding = function(encoding) {
|
||||
if(encoding && (encoding != this._encoding)) {
|
||||
this.data = this.as(encoding);
|
||||
this.__proto__ = encodings[encoding];
|
||||
}
|
||||
return this._encoding;
|
||||
};
|
||||
|
||||
// answer a new instance having the given encoding
|
||||
Address.prototype.withEncoding = function(encoding) {
|
||||
return new Address(this.as(encoding), encoding);
|
||||
};
|
||||
|
||||
// answer the data in the given encoding
|
||||
Address.prototype.as = function(encoding) {
|
||||
if(!encodings[encoding]) throw new Error('invalid encoding');
|
||||
return this.converters[encoding].call(this);
|
||||
};
|
||||
|
||||
// validate the address (basically just check that we have 21 bytes)
|
||||
Address.prototype.validate = function() {
|
||||
this.withEncoding('binary').validate();
|
||||
this.doAsBinary(function() {
|
||||
Address.super(this, 'validate', arguments);
|
||||
if(this.data.length != 21) throw new Error('invalid data length');
|
||||
});
|
||||
};
|
||||
|
||||
// convert to a string (in base58 form)
|
||||
Address.prototype.toString = function() {
|
||||
return this.as('base58');
|
||||
};
|
||||
|
||||
// utility
|
||||
Address.prototype.doAsBinary = function(callback) {
|
||||
var oldEncoding = this.encoding();
|
||||
this.encoding('binary');
|
||||
callback.apply(this);
|
||||
this.encoding(oldEncoding);
|
||||
};
|
||||
|
||||
// Setup support for various address encodings. The object for
|
||||
// each encoding inherits from the Address prototype. This
|
||||
// allows any encoding to override any method...changing the encoding
|
||||
// for an instance will change the encoding it inherits from. Note,
|
||||
// this will present some problems for anyone wanting to inherit from
|
||||
// Address (we'll deal with that when needed).
|
||||
var encodings = {
|
||||
'binary': {
|
||||
converters: {
|
||||
'binary': function() {
|
||||
var answer = new Buffer(this.data.length);
|
||||
this.data.copy(answer);
|
||||
return answer;
|
||||
},
|
||||
'base58': function() {
|
||||
return base58.encode(this.data);
|
||||
},
|
||||
'hex': function() {
|
||||
return this.data.toString('hex');
|
||||
},
|
||||
},
|
||||
|
||||
validate: function() {
|
||||
if(this.data.length != 21) throw new Error('invalid data length');
|
||||
},
|
||||
},
|
||||
|
||||
'base58': {
|
||||
converters: {
|
||||
'binary': function() {
|
||||
return base58.decode(this.data);
|
||||
},
|
||||
'hex': function() {
|
||||
return this.withEncoding('binary').as('hex');
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
'hex': {
|
||||
converters: {
|
||||
'binary': function() {
|
||||
return new Buffer(this.data, 'hex');
|
||||
},
|
||||
'base58': function() {
|
||||
return this.withEncoding('binary').as('base58');
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
for(var k in encodings) {
|
||||
if(!encodings[k].converters[k])
|
||||
encodings[k].converters[k] = function() {return this.data;};
|
||||
encodings[k]._encoding = k;
|
||||
encodings[k].__proto__ = Address.prototype;
|
||||
};
|
||||
|
||||
return Address;
|
||||
};
|
||||
module.defineClass(ClassSpec);
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
require('classtool');
|
||||
|
||||
function ClassSpec(b) {
|
||||
var base58 = b.base58 || require('base58-native').base58Check;
|
||||
|
||||
// Constructor. Takes the following forms:
|
||||
// new EncodedData(<base58_address_string>)
|
||||
// new EncodedData(<binary_buffer>)
|
||||
// new EncodedData(<data>, <encoding>)
|
||||
// new EncodedData(<version>, <20-byte-hash>)
|
||||
function EncodedData(data, encoding) {
|
||||
this.data = data;
|
||||
if(!encoding && (typeof data == 'string')) {
|
||||
this.__proto__ = this.encodings['base58'];
|
||||
} else {
|
||||
this.__proto__ = this.encodings[encoding || 'binary'];
|
||||
}
|
||||
};
|
||||
|
||||
// get or set the encoding used (transforms data)
|
||||
EncodedData.prototype.encoding = function(encoding) {
|
||||
if(encoding && (encoding != this._encoding)) {
|
||||
this.data = this.as(encoding);
|
||||
this.__proto__ = this.encodings[encoding];
|
||||
}
|
||||
return this._encoding;
|
||||
};
|
||||
|
||||
// answer a new instance having the given encoding
|
||||
EncodedData.prototype.withEncoding = function(encoding) {
|
||||
return new EncodedData(this.as(encoding), encoding);
|
||||
};
|
||||
|
||||
// answer the data in the given encoding
|
||||
EncodedData.prototype.as = function(encoding) {
|
||||
if(!encodings[encoding]) throw new Error('invalid encoding');
|
||||
return this.converters[encoding].call(this);
|
||||
};
|
||||
|
||||
// validate that we can convert to binary
|
||||
EncodedData.prototype._validate = function() {
|
||||
this.withEncoding('binary');
|
||||
};
|
||||
|
||||
// subclasses can override to do more stuff
|
||||
EncodedData.prototype.validate = function() {
|
||||
this._validate();
|
||||
};
|
||||
|
||||
// convert to a string (in base58 form)
|
||||
EncodedData.prototype.toString = function() {
|
||||
return this.as('base58');
|
||||
};
|
||||
|
||||
// utility
|
||||
EncodedData.prototype.doAsBinary = function(callback) {
|
||||
var oldEncoding = this.encoding();
|
||||
this.encoding('binary');
|
||||
callback.apply(this);
|
||||
this.encoding(oldEncoding);
|
||||
};
|
||||
|
||||
// Setup support for various address encodings. The object for
|
||||
// each encoding inherits from the EncodedData prototype. This
|
||||
// allows any encoding to override any method...changing the encoding
|
||||
// for an instance will change the encoding it inherits from. Note,
|
||||
// this will present some problems for anyone wanting to inherit from
|
||||
// EncodedData (we'll deal with that when needed).
|
||||
var encodings = {
|
||||
'binary': {
|
||||
converters: {
|
||||
'binary': function() {
|
||||
var answer = new Buffer(this.data.length);
|
||||
this.data.copy(answer);
|
||||
return answer;
|
||||
},
|
||||
'base58': function() {
|
||||
return base58.encode(this.data);
|
||||
},
|
||||
'hex': function() {
|
||||
return this.data.toString('hex');
|
||||
},
|
||||
},
|
||||
|
||||
_validate: function() {
|
||||
//nothing to do here...we make no assumptions about the data
|
||||
},
|
||||
},
|
||||
|
||||
'base58': {
|
||||
converters: {
|
||||
'binary': function() {
|
||||
return base58.decode(this.data);
|
||||
},
|
||||
'hex': function() {
|
||||
return this.withEncoding('binary').as('hex');
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
'hex': {
|
||||
converters: {
|
||||
'binary': function() {
|
||||
return new Buffer(this.data, 'hex');
|
||||
},
|
||||
'base58': function() {
|
||||
return this.withEncoding('binary').as('base58');
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
for(var k in encodings) {
|
||||
if(!encodings[k].converters[k])
|
||||
encodings[k].converters[k] = function() {return this.data;};
|
||||
encodings[k]._encoding = k;
|
||||
}
|
||||
|
||||
EncodedData.applyEncodingsTo = function(aClass) {
|
||||
var tmp = {};
|
||||
for(var k in encodings) {
|
||||
var enc = encodings[k];
|
||||
var obj = {};
|
||||
for(var j in enc) {
|
||||
obj[j] = enc[j];
|
||||
}
|
||||
obj.__proto__ = aClass.prototype;
|
||||
tmp[k] = obj;
|
||||
}
|
||||
aClass.prototype.encodings = tmp;
|
||||
};
|
||||
|
||||
EncodedData.applyEncodingsTo(EncodedData);
|
||||
return EncodedData;
|
||||
};
|
||||
module.defineClass(ClassSpec);
|
|
@ -0,0 +1,39 @@
|
|||
require('classtool');
|
||||
|
||||
function ClassSpec(b) {
|
||||
var superclass = b.superclass || require('./EncodedData').class();
|
||||
|
||||
function VersionedData(version, payload) {
|
||||
if(typeof version != 'number') {
|
||||
VersionedData.super(this, arguments);
|
||||
return;
|
||||
};
|
||||
this.data = new Buffer(payload.length + 1);
|
||||
this.__proto__ = this.encodings['binary'];
|
||||
this.version(version);
|
||||
this.payload(payload);
|
||||
};
|
||||
VersionedData.superclass = superclass;
|
||||
superclass.applyEncodingsTo(VersionedData);
|
||||
|
||||
// get or set the version data (the first byte of the address)
|
||||
VersionedData.prototype.version = function(num) {
|
||||
if(num || (num === 0)) {
|
||||
this.doAsBinary(function() {this.data.writeUInt8(num, 0);});
|
||||
return num;
|
||||
}
|
||||
return this.as('binary').readUInt8(0);
|
||||
};
|
||||
|
||||
// get or set the payload data (as a Buffer object)
|
||||
VersionedData.prototype.payload = function(data) {
|
||||
if(data) {
|
||||
this.doAsBinary(function() {data.copy(this.data,1);});
|
||||
return data;
|
||||
}
|
||||
return this.as('binary').slice(1);
|
||||
};
|
||||
|
||||
return VersionedData;
|
||||
};
|
||||
module.defineClass(ClassSpec);
|
Loading…
Reference in New Issue