Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite web3-eth-iban #3955

Closed
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
354 changes: 178 additions & 176 deletions packages/web3-eth-iban/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@

"use strict";

var utils = require('web3-utils');
var BigNumber = require('bn.js');
const utils = require('web3-utils');
const BigNumber = require('bn.js');


var leftPad = function (string, bytes) {
var result = string;
const leftPad = function (string, bytes) {
let result = string;
while (result.length < bytes * 2) {
result = '0' + result;
}
Expand All @@ -45,16 +45,16 @@ var leftPad = function (string, bytes) {
* @param {String} iban the IBAN
* @returns {String} the prepared IBAN
*/
var iso13616Prepare = function (iban) {
var A = 'A'.charCodeAt(0);
var Z = 'Z'.charCodeAt(0);
const iso13616Prepare = function (iban) {
const A = 'A'.charCodeAt(0);
const Z = 'Z'.charCodeAt(0);

iban = iban.toUpperCase();
iban = iban.substr(4) + iban.substr(0,4);

return iban.split('').map(function(n){
var code = n.charCodeAt(0);
if (code >= A && code <= Z){
return iban.split('').map(function(n) {
const code = n.charCodeAt(0);
if (code >= A && code <= Z) {
// A = 10, B = 11, ... Z = 35
return code - A + 10;
} else {
Expand All @@ -70,9 +70,9 @@ var iso13616Prepare = function (iban) {
* @param {String} iban
* @returns {Number}
*/
var mod9710 = function (iban) {
var remainder = iban,
block;
const mod9710 = function (iban) {
let remainder = iban;
let block;

while (remainder.length > 2){
block = remainder.slice(0, 9);
Expand All @@ -87,181 +87,183 @@ var mod9710 = function (iban) {
*
* @param {String} iban
*/
var Iban = function Iban(iban) {
this._iban = iban;
};

/**
* This method should be used to create an ethereum address from a direct iban address
*
* @method toAddress
* @param {String} iban address
* @return {String} the ethereum address
*/
Iban.toAddress = function (ib) {
ib = new Iban(ib);

if(!ib.isDirect()) {
throw new Error('IBAN is indirect and can\'t be converted');
class Iban {
constructor (iban) {
this._iban = iban;
}

return ib.toAddress();
};

/**
* This method should be used to create iban address from an ethereum address
*
* @method toIban
* @param {String} address
* @return {String} the IBAN address
*/
Iban.toIban = function (address) {
return Iban.fromAddress(address).toString();
};
/**
* This method should be used to create an ethereum address from a direct iban address
*
* @method toAddress
* @param {String} iban address
* @return {String} the ethereum address
*/
static toAddress (ib) {
ib = new Iban(ib);

if(!ib.isDirect()) {
throw new Error('IBAN is indirect and can\'t be converted');
}

/**
* This method should be used to create iban object from an ethereum address
*
* @method fromAddress
* @param {String} address
* @return {Iban} the IBAN object
*/
Iban.fromAddress = function (address) {
if(!utils.isAddress(address)){
throw new Error('Provided address is not a valid address: '+ address);
return ib.toAddress();
}

address = address.replace('0x','').replace('0X','');

var asBn = new BigNumber(address, 16);
var base36 = asBn.toString(36);
var padded = leftPad(base36, 15);
return Iban.fromBban(padded.toUpperCase());
};

/**
* Convert the passed BBAN to an IBAN for this country specification.
* Please note that <i>"generation of the IBAN shall be the exclusive responsibility of the bank/branch servicing the account"</i>.
* This method implements the preferred algorithm described in http://en.wikipedia.org/wiki/International_Bank_Account_Number#Generating_IBAN_check_digits
*
* @method fromBban
* @param {String} bban the BBAN to convert to IBAN
* @returns {Iban} the IBAN object
*/
Iban.fromBban = function (bban) {
var countryCode = 'XE';

var remainder = mod9710(iso13616Prepare(countryCode + '00' + bban));
var checkDigit = ('0' + (98 - remainder)).slice(-2);

return new Iban(countryCode + checkDigit + bban);
};

/**
* Should be used to create IBAN object for given institution and identifier
*
* @method createIndirect
* @param {Object} options, required options are "institution" and "identifier"
* @return {Iban} the IBAN object
*/
Iban.createIndirect = function (options) {
return Iban.fromBban('ETH' + options.institution + options.identifier);
};

/**
* This method should be used to check if given string is valid iban object
*
* @method isValid
* @param {String} iban string
* @return {Boolean} true if it is valid IBAN
*/
Iban.isValid = function (iban) {
var i = new Iban(iban);
return i.isValid();
};

/**
* Should be called to check if iban is correct
*
* @method isValid
* @returns {Boolean} true if it is, otherwise false
*/
Iban.prototype.isValid = function () {
return /^XE[0-9]{2}(ETH[0-9A-Z]{13}|[0-9A-Z]{30,31})$/.test(this._iban) &&
mod9710(iso13616Prepare(this._iban)) === 1;
};

/**
* Should be called to check if iban number is direct
*
* @method isDirect
* @returns {Boolean} true if it is, otherwise false
*/
Iban.prototype.isDirect = function () {
return this._iban.length === 34 || this._iban.length === 35;
};
/**
* This method should be used to create iban address from an ethereum address
*
* @method toIban
* @param {String} address
* @return {String} the IBAN address
*/
static toIban (address) {
return Iban.fromAddress(address).toString();
}

/**
* Should be called to check if iban number if indirect
*
* @method isIndirect
* @returns {Boolean} true if it is, otherwise false
*/
Iban.prototype.isIndirect = function () {
return this._iban.length === 20;
};
/**
* This method should be used to create iban object from an ethereum address
*
* @method fromAddress
* @param {String} address
* @return {Iban} the IBAN object
*/
static fromAddress (address) {
if(!utils.isAddress(address)){
throw new Error('Provided address is not a valid address: '+ address);
}

/**
* Should be called to get iban checksum
* Uses the mod-97-10 checksumming protocol (ISO/IEC 7064:2003)
*
* @method checksum
* @returns {String} checksum
*/
Iban.prototype.checksum = function () {
return this._iban.substr(2, 2);
};
address = address.replace('0x','').replace('0X','');

/**
* Should be called to get institution identifier
* eg. XREG
*
* @method institution
* @returns {String} institution identifier
*/
Iban.prototype.institution = function () {
return this.isIndirect() ? this._iban.substr(7, 4) : '';
};
const asBn = new BigNumber(address, 16);
const base36 = asBn.toString(36);
const padded = leftPad(base36, 15);
return Iban.fromBban(padded.toUpperCase());
}

/**
* Should be called to get client identifier within institution
* eg. GAVOFYORK
*
* @method client
* @returns {String} client identifier
*/
Iban.prototype.client = function () {
return this.isIndirect() ? this._iban.substr(11) : '';
};
/**
* Convert the passed BBAN to an IBAN for this country specification.
* Please note that <i>"generation of the IBAN shall be the exclusive responsibility of the bank/branch servicing the account"</i>.
* This method implements the preferred algorithm described in http://en.wikipedia.org/wiki/International_Bank_Account_Number#Generating_IBAN_check_digits
*
* @method fromBban
* @param {String} bban the BBAN to convert to IBAN
* @returns {Iban} the IBAN object
*/
static fromBban (bban) {
const countryCode = 'XE';

const remainder = mod9710(iso13616Prepare(countryCode + '00' + bban));
const checkDigit = ('0' + (98 - remainder)).slice(-2);

return new Iban(countryCode + checkDigit + bban);
}

/**
* Should be called to get client direct address
*
* @method toAddress
* @returns {String} ethereum address
*/
Iban.prototype.toAddress = function () {
if (this.isDirect()) {
var base36 = this._iban.substr(4);
var asBn = new BigNumber(base36, 36);
return utils.toChecksumAddress(asBn.toString(16, 20));
/**
* Should be used to create IBAN object for given institution and identifier
*
* @method createIndirect
* @param {Object} options, required options are "institution" and "identifier"
* @return {Iban} the IBAN object
*/
static createIndirect (options) {
return Iban.fromBban('ETH' + options.institution + options.identifier);
}

return '';
};
/**
* This method should be used to check if given string is valid iban object
*
* @method isValid
* @param {String} iban string
* @return {Boolean} true if it is valid IBAN
*/
static isValid (iban) {
const i = new Iban(iban);
return i.isValid();
};

/**
* Should be called to check if iban is correct
*
* @method isValid
* @returns {Boolean} true if it is, otherwise false
*/
isValid () {
return /^XE[0-9]{2}(ETH[0-9A-Z]{13}|[0-9A-Z]{30,31})$/.test(this._iban) &&
mod9710(iso13616Prepare(this._iban)) === 1;
};

/**
* Should be called to check if iban number is direct
*
* @method isDirect
* @returns {Boolean} true if it is, otherwise false
*/
isDirect () {
return this._iban.length === 34 || this._iban.length === 35;
};

/**
* Should be called to check if iban number if indirect
*
* @method isIndirect
* @returns {Boolean} true if it is, otherwise false
*/
isIndirect () {
return this._iban.length === 20;
};

/**
* Should be called to get iban checksum
* Uses the mod-97-10 checksumming protocol (ISO/IEC 7064:2003)
*
* @method checksum
* @returns {String} checksum
*/
checksum () {
return this._iban.substr(2, 2);
};

/**
* Should be called to get institution identifier
* eg. XREG
*
* @method institution
* @returns {String} institution identifier
*/
institution () {
return this.isIndirect() ? this._iban.substr(7, 4) : '';
};

/**
* Should be called to get client identifier within institution
* eg. GAVOFYORK
*
* @method client
* @returns {String} client identifier
*/
client () {
return this.isIndirect() ? this._iban.substr(11) : '';
};

/**
* Should be called to get client direct address
*
* @method toAddress
* @returns {String} ethereum address
*/
toAddress () {
if (this.isDirect()) {
const base36 = this._iban.substr(4);
const asBn = new BigNumber(base36, 36);
return utils.toChecksumAddress(asBn.toString(16, 20));
}

Iban.prototype.toString = function () {
return this._iban;
};
return '';
};

toString () {
return this._iban;
};
}

module.exports = Iban;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left module.exports = Iban; instead of export default Iban to avoid breaking changes. What do you suggest?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

module.exports is fine for this