diff --git a/Gruntfile.js b/Gruntfile.js index 1245e833a1..8227f9d15a 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -5,14 +5,16 @@ module.exports = function (grunt) { return content .replace(/CLIENT_VERSION\s*=\s*'[^']+'/, grunt.template.process("CLIENT_VERSION = '<%= pkg.version %>a'")) .replace(/NODE_ADDRESS\s*=\s*'[^']+'/, grunt.template.process("NODE_ADDRESS = '<%= meta.configurations.testnet.server %>'")) - .replace(/NETWORK_NAME\s*=\s*'[^']+'/, grunt.template.process("NETWORK_NAME = '<%= meta.configurations.testnet.name %>'")); + .replace(/NETWORK_NAME\s*=\s*'[^']+'/, grunt.template.process("NETWORK_NAME = '<%= meta.configurations.testnet.name %>'")) + .replace(/NETWORK_CODE\s*=\s*'[^']+'/, grunt.template.process("NETWORK_CODE = '<%= meta.configurations.testnet.code %>'")); }; var replaceMainnetVersion = function (content) { return content .replace(/CLIENT_VERSION\s*=\s*'[^']+'/, grunt.template.process("CLIENT_VERSION = '<%= pkg.version %>a'")) .replace(/NODE_ADDRESS\s*=\s*'[^']+'/, grunt.template.process("NODE_ADDRESS = '<%= meta.configurations.mainnet.server %>'")) - .replace(/NETWORK_NAME\s*=\s*'[^']+'/, grunt.template.process("NETWORK_NAME = '<%= meta.configurations.mainnet.name %>'")); + .replace(/NETWORK_NAME\s*=\s*'[^']+'/, grunt.template.process("NETWORK_NAME = '<%= meta.configurations.mainnet.name %>'")) + .replace(/NETWORK_CODE\s*=\s*'[^']+'/, grunt.template.process("NETWORK_CODE = '<%= meta.configurations.mainnet.code %>'")); }; // Project configuration. @@ -24,10 +26,12 @@ module.exports = function (grunt) { configurations: { testnet: { name: 'testnet', + code: 'T', server: 'http://52.30.47.67:6869' }, mainnet: { name: 'mainnet', + code: 'W', server: 'https://nodes.wavesnodes.com' }, chrome: { diff --git a/js/waves.settings.js b/js/waves.settings.js index 37b360309f..fec2315a0a 100644 --- a/js/waves.settings.js +++ b/js/waves.settings.js @@ -26,6 +26,8 @@ var Waves = (function (Waves) { Waves.constants.CLIENT_VERSION = '0.4.1a'; Waves.constants.NODE_ADDRESS = 'http://52.30.47.67:6869'; Waves.constants.NETWORK_NAME = 'devel'; + Waves.constants.ADDRESS_VERSION = 1; + Waves.constants.NETWORK_CODE = 'T'; return Waves; }(Waves || {})); diff --git a/js/waves.ui.functions.js b/js/waves.ui.functions.js index 11c0cd78ec..eb4f5bbe5d 100644 --- a/js/waves.ui.functions.js +++ b/js/waves.ui.functions.js @@ -326,13 +326,11 @@ var Waves = (function(Waves, $, undefined) { // additional address validation var freshKey = Waves.getPublicKey(accountDetails.passphrase); - Waves.apiRequest(Waves.api.waves.address, freshKey, function(response) { - var generated = Waves.Addressing.fromRawAddress(response.address); - var bytes = converters.stringToByteArray(accountDetails.password); - var id = Base58.encode(Waves.blake2bHash(new Uint8Array(bytes))); + var generated = Waves.buildAddress(freshKey); + var bytes = converters.stringToByteArray(accountDetails.password); + var id = Base58.encode(Waves.blake2bHash(new Uint8Array(bytes))); - Waves.apiRequest(Waves.api.address.check(Waves.address, generated, id)); - }); + Waves.apiRequest(Waves.api.address.check(Waves.address, generated, id)); }); } diff --git a/js/waves.ui.js b/js/waves.ui.js index a7ed35fae1..36c91db4bc 100644 --- a/js/waves.ui.js +++ b/js/waves.ui.js @@ -369,13 +369,11 @@ var Waves = (function(Waves, $, undefined) { }); $('#header-wPop-backup').on($.modal.BEFORE_OPEN, function() { - Waves.apiRequest(Waves.api.waves.address, Waves.publicKey, function(response) { - $('#seedBackup').val(Waves.passphrase); - $('#encodedSeedBackup').val(Base58.encode(converters.stringToByteArray(Waves.passphrase))); - $('#privateKeyBackup').val(Waves.privateKey); - $('#publicKeyBackup').val(Waves.publicKey); - $("#addressBackup").val(Waves.Addressing.fromRawAddress(response.address).getDisplayAddress()); - }); + $('#seedBackup').val(Waves.passphrase); + $('#encodedSeedBackup').val(Base58.encode(converters.stringToByteArray(Waves.passphrase))); + $('#privateKeyBackup').val(Waves.privateKey); + $('#publicKeyBackup').val(Waves.publicKey); + $("#addressBackup").val(Waves.buildAddress(Waves.publicKey).getDisplayAddress()); }); $('#header-wPop-backup').on($.modal.AFTER_CLOSE, function() { diff --git a/js/waves.ui.lockscreen.js b/js/waves.ui.lockscreen.js index 3ba6968ca6..3478bb17ce 100644 --- a/js/waves.ui.lockscreen.js +++ b/js/waves.ui.lockscreen.js @@ -97,7 +97,6 @@ var Waves = (function(Waves, $, undefined) { $("#publicKeyLockscreen").html(''); $("#privateKeyLockscreen").html(''); $("#addresLockscreen").html(''); - }); //Create new Waves Acount @@ -125,7 +124,6 @@ var Waves = (function(Waves, $, undefined) { }); $('#login-wPop-new').on($.modal.CLOSE, function(event, modal) { - var passphrase = PassPhraseGenerator.generatePassPhrase(); $("#walletSeed").val(passphrase); @@ -134,11 +132,8 @@ var Waves = (function(Waves, $, undefined) { $("#publicKeyLockscreen").html(publicKey); $("#privateKeyLockscreen").html(privateKey); - - Waves.apiRequest(Waves.api.waves.address, publicKey, function(response) { - $("#addresLockscreen").html(Waves.Addressing.fromRawAddress(response.address).getDisplayAddress()); - NProgress.done(); - }); + $("#addresLockscreen").html(Waves.buildAddress(publicKey).getDisplayAddress()); + NProgress.done(); }); $("#close_create_account_modal").on("click", function(){ @@ -163,10 +158,7 @@ var Waves = (function(Waves, $, undefined) { $("#publicKeyLockscreen").html(publicKey); $("#privateKeyLockscreen").html(privateKey); - - Waves.apiRequest(Waves.api.waves.address, publicKey, function(response) { - $("#addresLockscreen").html(Waves.Addressing.fromRawAddress(response.address).getDisplayAddress()); - }); + $("#addresLockscreen").html(Waves.buildAddress(publicKey).getDisplayAddress()); }); $("#generateRandomSeed").on("click", function(e) { @@ -180,10 +172,7 @@ var Waves = (function(Waves, $, undefined) { $("#publicKeyLockscreen").html(publicKey); $("#privateKeyLockscreen").html(privateKey); - - Waves.apiRequest(Waves.api.waves.address, publicKey, function(response) { - $("#addresLockscreen").html(Waves.Addressing.fromRawAddress(response.address).getDisplayAddress()); - }); + $("#addresLockscreen").html(Waves.buildAddress(publicKey).getDisplayAddress()); }); $(".goBack").on("click", function(e) { @@ -206,84 +195,75 @@ var Waves = (function(Waves, $, undefined) { var name = $("#walletName").val(); var password = $("#walletPassword").val(); + var address = Waves.buildAddress(publicKey); + var cipher = Waves.encryptWalletSeed(passphrase, password).toString(); + var checksum = converters.byteArrayToHexString(Waves.simpleHash(converters.stringToByteArray(passphrase))); - Waves.apiRequest(Waves.api.waves.address, publicKey, function(response) { - - var address = Waves.Addressing.fromRawAddress(response.address); - var cipher = Waves.encryptWalletSeed(passphrase, password).toString(); - var checksum = converters.byteArrayToHexString(Waves.simpleHash(converters.stringToByteArray(passphrase))); - - var accountData = { - name: name, - cipher: cipher, - checksum: checksum, - publicKey: publicKey, - address: address.getRawAddress() - }; + var accountData = { + name: name, + cipher: cipher, + checksum: checksum, + publicKey: publicKey, + address: address.getRawAddress() + }; - if(Waves.hasLocalStorage) { - - var currentAccounts = localStorage.getItem('Waves'+Waves.network); - currentAccounts = JSON.parse(currentAccounts); + if(Waves.hasLocalStorage) { - if(currentAccounts !== undefined && currentAccounts !== null) { + var currentAccounts = localStorage.getItem('Waves'+Waves.network); + currentAccounts = JSON.parse(currentAccounts); - currentAccounts.accounts.push(accountData); - localStorage.setItem('Waves'+Waves.network, JSON.stringify(currentAccounts)); - $("#wavesAccounts").append('
'+accountData.name+' ' + address.getDisplayAddress()); + if(currentAccounts !== undefined && currentAccounts !== null) { - } else { - var accountArray = { accounts: [accountData] }; - localStorage.setItem('Waves'+Waves.network, JSON.stringify(accountArray)); - $("#wavesAccounts").append('
'+accountData.name+'' + address.getDisplayAddress()); - } + currentAccounts.accounts.push(accountData); + localStorage.setItem('Waves'+Waves.network, JSON.stringify(currentAccounts)); + $("#wavesAccounts").append('
'+accountData.name+' ' + address.getDisplayAddress()); } else { + var accountArray = { accounts: [accountData] }; + localStorage.setItem('Waves'+Waves.network, JSON.stringify(accountArray)); + $("#wavesAccounts").append('
'+accountData.name+'' + address.getDisplayAddress()); + } - Waves.getAccounts(function(currentAccounts) { - - var saveData = { - name: name, - cipher: cipher, - checksum: checksum, - publicKey: publicKey, - address: address.getRawAddress() - }; + } else { - if(currentAccounts !== '') { + Waves.getAccounts(function(currentAccounts) { - currentAccounts = currentAccounts['WavesAccounts']; + var saveData = { + name: name, + cipher: cipher, + checksum: checksum, + publicKey: publicKey, + address: address.getRawAddress() + }; - currentAccounts.accounts.push(saveData); - chrome.storage.sync.set({'WavesAccounts': currentAccounts}, function() { - // Notify that we saved. - $.growl.notice({ message: "Added Account!" }); - $("#wavesAccounts").append('
'+saveData.name+' ' + address.getDisplayAddress()); - }); + if(currentAccounts !== '') { - } else { + currentAccounts = currentAccounts['WavesAccounts']; - var accountArray = { accounts: [saveData] }; - chrome.storage.sync.set({'WavesAccounts': accountArray}, function() { - // Notify that we saved. - $.growl.notice({ message: "Added Account!" }); - $("#wavesAccounts").append('
'+saveData.name+' ' + address.getDisplayAddress()); - }); - } + currentAccounts.accounts.push(saveData); + chrome.storage.sync.set({'WavesAccounts': currentAccounts}, function() { + // Notify that we saved. + $.growl.notice({ message: "Added Account!" }); + $("#wavesAccounts").append('
'+saveData.name+' ' + address.getDisplayAddress()); + }); - }); - - } + } else { - accountData.firstTime = true; - accountData.password = password; - accountData.passphrase = passphrase; - passphrase = ''; + var accountArray = { accounts: [saveData] }; + chrome.storage.sync.set({'WavesAccounts': accountArray}, function() { + // Notify that we saved. + $.growl.notice({ message: "Added Account!" }); + $("#wavesAccounts").append('
'+saveData.name+' ' + address.getDisplayAddress()); + }); + } + }); + } - Waves.login(accountData); + accountData.firstTime = true; + accountData.password = password; + accountData.passphrase = passphrase; - }); - + Waves.login(accountData); }); Waves.UI.registerForm.setupValidation(); diff --git a/js/waves.util.js b/js/waves.util.js index d41dd79cb4..54b646051c 100644 --- a/js/waves.util.js +++ b/js/waves.util.js @@ -246,6 +246,10 @@ var Waves = (function (Waves, $, undefined) { }; Waves.MAP = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; + + var getNetworkIdByte = function() { + return Waves.constants.NETWORK_CODE.charCodeAt(0) & 0xFF; + } Waves.getLocalDateFormat = function () { return Waves.LOCALE_DATE_FORMAT; @@ -364,6 +368,24 @@ var Waves = (function (Waves, $, undefined) { return Base58.encode(p.private); } + Waves.buildRawAddress = function (encodedPublicKey) { + var publicKey = Base58.decode(encodedPublicKey); + var publicKeyHash = this.hashChain(publicKey); + + var prefix = new Uint8Array(2); + prefix[0] = Waves.constants.ADDRESS_VERSION; + prefix[1] = getNetworkIdByte(); + + var unhashedAddress = this.appendUint8Arrays(prefix, publicKeyHash.slice(0, 20)); + var addressHash = this.hashChain(unhashedAddress).slice(0, 4); + + return Base58.encode(this.appendUint8Arrays(unhashedAddress, addressHash)); + } + + Waves.buildAddress = function (encodedPublicKey) { + return Waves.Addressing.fromRawAddress(this.buildRawAddress(encodedPublicKey)); + } + //Returns publicKey built from string Waves.getPublicKey = function(secretPhrase) { return this.buildPublicKey(converters.stringToByteArray(secretPhrase)); diff --git a/tests/spec/waves.util.spec.js b/tests/spec/waves.util.spec.js index 05b003271c..f64af10b16 100755 --- a/tests/spec/waves.util.spec.js +++ b/tests/spec/waves.util.spec.js @@ -54,4 +54,32 @@ describe("waves.util", function() { signature = Waves.nonDeterministicSign(privateKey, messageBytes); expect(Waves.verify(publicKey, messageBytes, Base58.decode(signature))).toBe(true); }); + + it("should generate network addresses locally", function() { + // testing testnet address generation + Waves.constants.NETWORK_CODE = 'T'; + expect(Waves.buildRawAddress("5ug8nQ1ubfjAZVJFed4mcXVVEBz53DfV8nBQWuKbt2AJ")) + .toEqual("3Mtkz8KeXUZmTbNH1MFcrMGv4t1av5tmaFL"); + expect(Waves.buildRawAddress("9iDrC31brcunVTRCq69iUngg1S5Ai1rd6iX7vTwAGTvn")) + .toEqual("3N33kaYS3C9pvVsVjLKLApmRQHfzm3UY36N"); + expect(Waves.buildRawAddress("Dq5f76Ro3qQCPWSDrCNrVDCiKwNFKCP2UmnVZzPxVf8")) + .toEqual("3NBmgsTgGv8nfmYzbCiKvTuBJtDpVyyxqKr"); + expect(Waves.buildRawAddress("6tk94Rwij3FXwfaJLWu9PhQAHDY2MUjPLYkHQ28HaRk3")) + .toEqual("3MstHyC4tKtBhzbWdhrJ3jkxPD1hYSJCi77"); + expect(Waves.buildRawAddress("2oGDrLRdBsU9Nb32jgPMh3TrQXm9QifUBLnLijfWqY5e")) + .toEqual("3MzUpwpiNTr32YWoYVmRFyzJQgdDbti3shP"); + expect(Waves.buildRawAddress("71m88eJxbfJnNPW87r4Qtrp9Q2qa1wsLYmrxXRAzLPF6")) + .toEqual("3MwJXUURjZY2BmbMDRMwgGnJ19RZC9Hdg3V"); + expect(Waves.buildRawAddress("7Ftuept6hfNEhSeVA439asPWZQVuteqWQUEPz6RGHsAo")) + .toEqual("3MpETHR7opAMN6dWqJejq1X37YCkq6Nu5hK"); + expect(Waves.buildRawAddress("AEYsMR1171SmhV77rDtBTyfjmFubzirpHqFH4hV1aDt9")) + .toEqual("3MyciTA8STrTWjZ46KdoZ1ASf5GuY7sD8be"); + + // testing mainnet address generation + Waves.constants.NETWORK_CODE = 'W'; + expect(Waves.buildRawAddress("D1vnz91YRXyDM72R6ZsPZfj1woMzL5nZtFrfeGQYjMs6")) + .toEqual("3PKGL4nMz3sMESQXPzmX5GKbiQtCi2Tu9Z5"); + expect(Waves.buildRawAddress("9Emin4uvu2cew67hkpkX2ZKV6NJEjyP7Uvzbf8ARMCc6")) + .toEqual("3P9oRcFxwjW58bqu1oXyk1JrRTy8ADSKvdN"); + }); });