contents of zip

This commit is contained in:
transatoshi
2024-12-20 18:08:44 -08:00
parent aeb2b99db7
commit f03ed73d2b
261 changed files with 208197 additions and 0 deletions

21
scripts/BLAKE2b license.txt Executable file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Nicolas Flamel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

181
scripts/BLAKE2b-0.0.2.js Executable file
View File

@@ -0,0 +1,181 @@
var blake2b = (() => {
var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;
return (
function(blake2b) {
blake2b = blake2b || {};
var a;a||(a=typeof blake2b !== 'undefined' ? blake2b : {});var g,h;a.ready=new Promise(function(b,d){g=b;h=d});var k=Object.assign({},a),m="";"undefined"!=typeof document&&document.currentScript&&(m=document.currentScript.src);_scriptDir&&(m=_scriptDir);0!==m.indexOf("blob:")?m=m.substr(0,m.replace(/[?#].*/,"").lastIndexOf("/")+1):m="";var n=a.printErr||console.warn.bind(console);Object.assign(a,k);k=null;var p;a.wasmBinary&&(p=a.wasmBinary);var noExitRuntime=a.noExitRuntime||!0;
"object"!=typeof WebAssembly&&q("no native wasm support detected");var r,t=!1,u,v;function w(){var b=r.buffer;u=b;a.HEAP8=new Int8Array(b);a.HEAP16=new Int16Array(b);a.HEAP32=new Int32Array(b);a.HEAPU8=v=new Uint8Array(b);a.HEAPU16=new Uint16Array(b);a.HEAPU32=new Uint32Array(b);a.HEAPF32=new Float32Array(b);a.HEAPF64=new Float64Array(b)}var x=[],y=[],z=[];function A(){var b=a.preRun.shift();x.unshift(b)}var B=0,C=null,D=null;
function q(b){if(a.onAbort)a.onAbort(b);b="Aborted("+b+")";n(b);t=!0;b=new WebAssembly.RuntimeError(b+". Build with -sASSERTIONS for more info.");h(b);throw b;}function E(){return F.startsWith("data:application/octet-stream;base64,")}var F;F="." + getResource("./scripts/BLAKE2b-0.0.2.wasm");if(!E()){var G=F;F=a.locateFile?a.locateFile(G,m):m+G}function H(){var b=F;try{if(b==F&&p)return new Uint8Array(p);throw"both async and sync fetching of the wasm failed";}catch(d){q(d)}}
function I(){return p||"function"!=typeof fetch?Promise.resolve().then(function(){return H()}):fetch(F,{credentials:"same-origin"}).then(function(b){if(!b.ok)throw"failed to load wasm binary file at '"+F+"'";return b.arrayBuffer()}).catch(function(){return H()})}function J(b){for(;0<b.length;)b.shift()(a)}
var K={a:function(b){var d=v.length;b>>>=0;if(2147483648<b)return!1;for(var l=1;4>=l;l*=2){var f=d*(1+.2/l);f=Math.min(f,b+100663296);var c=Math;f=Math.max(b,f);c=c.min.call(c,2147483648,f+(65536-f%65536)%65536);a:{try{r.grow(c-u.byteLength+65535>>>16);w();var e=1;break a}catch(O){}e=void 0}if(e)return!0}return!1}};
(function(){function b(c){a.asm=c.exports;r=a.asm.b;w();y.unshift(a.asm.c);B--;a.monitorRunDependencies&&a.monitorRunDependencies(B);0==B&&(null!==C&&(clearInterval(C),C=null),D&&(c=D,D=null,c()))}function d(c){b(c.instance)}function l(c){return I().then(function(e){return WebAssembly.instantiate(e,f)}).then(function(e){return e}).then(c,function(e){n("failed to asynchronously prepare wasm: "+e);q(e)})}var f={a:K};B++;a.monitorRunDependencies&&a.monitorRunDependencies(B);if(a.instantiateWasm)try{return a.instantiateWasm(f,
b)}catch(c){return n("Module.instantiateWasm callback failed with error: "+c),!1}(function(){return p||"function"!=typeof WebAssembly.instantiateStreaming||E()||"function"!=typeof fetch?l(d):fetch(F,{credentials:"same-origin"}).then(function(c){return WebAssembly.instantiateStreaming(c,f).then(d,function(e){n("wasm streaming compile failed: "+e);n("falling back to ArrayBuffer instantiation");return l(d)})})})().catch(h);return{}})();
a.___wasm_call_ctors=function(){return(a.___wasm_call_ctors=a.asm.c).apply(null,arguments)};a._compute=function(){return(a._compute=a.asm.d).apply(null,arguments)};a._malloc=function(){return(a._malloc=a.asm.e).apply(null,arguments)};a._free=function(){return(a._free=a.asm.f).apply(null,arguments)};var L;D=function M(){L||N();L||(D=M)};
function N(){function b(){if(!L&&(L=!0,a.calledRun=!0,!t)){J(y);g(a);if(a.onRuntimeInitialized)a.onRuntimeInitialized();if(a.postRun)for("function"==typeof a.postRun&&(a.postRun=[a.postRun]);a.postRun.length;){var d=a.postRun.shift();z.unshift(d)}J(z)}}if(!(0<B)){if(a.preRun)for("function"==typeof a.preRun&&(a.preRun=[a.preRun]);a.preRun.length;)A();J(x);0<B||(a.setStatus?(a.setStatus("Running..."),setTimeout(function(){setTimeout(function(){a.setStatus("")},1);b()},1)):b())}}
if(a.preInit)for("function"==typeof a.preInit&&(a.preInit=[a.preInit]);0<a.preInit.length;)a.preInit.pop()();N();
return blake2b.ready
}
);
})();
if (typeof exports === 'object' && typeof module === 'object')
module.exports = blake2b;
else if (typeof define === 'function' && define['amd'])
define([], function() { return blake2b; });
else if (typeof exports === 'object')
exports["blake2b"] = blake2b;
// Use strict
"use strict";
// Classes
// BLAKE2b class
class Blake2b {
// Public
// Initialize
static initialize() {
// Set instance to invalid
Blake2b.instance = Blake2b.INVALID;
// Return promise
return new Promise(function(resolve, reject) {
// Set settings
var settings = {
// On abort
"onAbort": function(error) {
// Prevent on abort from being called again
delete settings["onAbort"];
// Reject error
reject("Failed to download resource");
}
};
// Create BLAKE2b instance
blake2b(settings).then(function(instance) {
// Prevent on abort from being called
delete settings["onAbort"];
// Set instance
Blake2b.instance = instance;
// Resolve
resolve();
});
});
}
// Compute
static compute(resultSize, input, key) {
// Check if instance doesn't exist
if(typeof Blake2b.instance === "undefined")
// Set instance
Blake2b.instance = blake2b();
// Check if instance is invalid
if(Blake2b.instance === Blake2b.INVALID)
// Return operation failed
return Blake2b.OPERATION_FAILED;
// Initialize result to result size
var result = new Uint8Array(resultSize);
// Allocate and fill memory
var resultBuffer = Blake2b.instance._malloc(result["length"] * result["BYTES_PER_ELEMENT"]);
var inputBuffer = Blake2b.instance._malloc(input["length"] * input["BYTES_PER_ELEMENT"]);
Blake2b.instance["HEAPU8"].set(input, inputBuffer / input["BYTES_PER_ELEMENT"]);
var keyBuffer = Blake2b.instance._malloc(key["length"] * key["BYTES_PER_ELEMENT"]);
Blake2b.instance["HEAPU8"].set(key, keyBuffer / key["BYTES_PER_ELEMENT"]);
// Check if computing BLAKE2b failed
if(Blake2b.instance._compute(resultBuffer, result["length"] * result["BYTES_PER_ELEMENT"], inputBuffer, input["length"] * input["BYTES_PER_ELEMENT"], keyBuffer, key["length"] * key["BYTES_PER_ELEMENT"]) === Blake2b.C_FALSE) {
// Clear memory
Blake2b.instance["HEAPU8"].fill(0, resultBuffer / result["BYTES_PER_ELEMENT"], resultBuffer / result["BYTES_PER_ELEMENT"] + result["length"]);
Blake2b.instance["HEAPU8"].fill(0, inputBuffer / input["BYTES_PER_ELEMENT"], inputBuffer / input["BYTES_PER_ELEMENT"] + input["length"]);
Blake2b.instance["HEAPU8"].fill(0, keyBuffer / key["BYTES_PER_ELEMENT"], keyBuffer / key["BYTES_PER_ELEMENT"] + key["length"]);
// Free memory
Blake2b.instance._free(resultBuffer);
Blake2b.instance._free(inputBuffer);
Blake2b.instance._free(keyBuffer);
// Return operation failed
return Blake2b.OPERATION_FAILED;
}
// Get result
result = new Uint8Array(Blake2b.instance["HEAPU8"].subarray(resultBuffer, resultBuffer + result["length"]));
// Clear memory
Blake2b.instance["HEAPU8"].fill(0, resultBuffer / result["BYTES_PER_ELEMENT"], resultBuffer / result["BYTES_PER_ELEMENT"] + result["length"]);
Blake2b.instance["HEAPU8"].fill(0, inputBuffer / input["BYTES_PER_ELEMENT"], inputBuffer / input["BYTES_PER_ELEMENT"] + input["length"]);
Blake2b.instance["HEAPU8"].fill(0, keyBuffer / key["BYTES_PER_ELEMENT"], keyBuffer / key["BYTES_PER_ELEMENT"] + key["length"]);
// Free memory
Blake2b.instance._free(resultBuffer);
Blake2b.instance._free(inputBuffer);
Blake2b.instance._free(keyBuffer);
// Return result
return result;
}
// Operation failed
static get OPERATION_FAILED() {
// Return operation failed
return null;
}
// Private
// Invalid
static get INVALID() {
// Return invalid
return null;
}
// C false
static get C_FALSE() {
// Return C false
return 0;
}
}
// Supporting fuction implementation
// Check if document doesn't exist
if(typeof document === "undefined") {
// Create document
var document = {};
}
// Check if module exports exists
if(typeof module === "object" && module !== null && "exports" in module === true) {
// Exports
module["exports"] = Blake2b;
}

BIN
scripts/BLAKE2b-0.0.2.wasm Executable file

Binary file not shown.

19
scripts/ChaCha license.txt Executable file
View File

@@ -0,0 +1,19 @@
Copyright (c) 2014-2015 Calvin Metcalf
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

6373
scripts/ChaCha-2.1.0.js Executable file

File diff suppressed because it is too large Load Diff

21
scripts/Ed25519 license.txt Executable file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Nicolas Flamel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

292
scripts/Ed25519-0.0.22.js Executable file
View File

@@ -0,0 +1,292 @@
var ed25519 = (() => {
var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;
return (
function(ed25519) {
ed25519 = ed25519 || {};
var a;a||(a=typeof ed25519 !== 'undefined' ? ed25519 : {});var g,h;a.ready=new Promise(function(b,d){g=b;h=d});var k=Object.assign({},a),m="";"undefined"!=typeof document&&document.currentScript&&(m=document.currentScript.src);_scriptDir&&(m=_scriptDir);0!==m.indexOf("blob:")?m=m.substr(0,m.replace(/[?#].*/,"").lastIndexOf("/")+1):m="";var n=a.printErr||console.warn.bind(console);Object.assign(a,k);k=null;var p;a.wasmBinary&&(p=a.wasmBinary);var noExitRuntime=a.noExitRuntime||!0;
"object"!=typeof WebAssembly&&q("no native wasm support detected");var r,t=!1,u,v;function w(){var b=r.buffer;u=b;a.HEAP8=new Int8Array(b);a.HEAP16=new Int16Array(b);a.HEAP32=new Int32Array(b);a.HEAPU8=v=new Uint8Array(b);a.HEAPU16=new Uint16Array(b);a.HEAPU32=new Uint32Array(b);a.HEAPF32=new Float32Array(b);a.HEAPF64=new Float64Array(b)}var x=[],y=[],z=[];function A(){var b=a.preRun.shift();x.unshift(b)}var B=0,C=null,D=null;
function q(b){if(a.onAbort)a.onAbort(b);b="Aborted("+b+")";n(b);t=!0;b=new WebAssembly.RuntimeError(b+". Build with -sASSERTIONS for more info.");h(b);throw b;}function E(){return F.startsWith("data:application/octet-stream;base64,")}var F;F="." + getResource("./scripts/Ed25519-0.0.22.wasm");if(!E()){var G=F;F=a.locateFile?a.locateFile(G,m):m+G}function H(){var b=F;try{if(b==F&&p)return new Uint8Array(p);throw"both async and sync fetching of the wasm failed";}catch(d){q(d)}}
function I(){return p||"function"!=typeof fetch?Promise.resolve().then(function(){return H()}):fetch(F,{credentials:"same-origin"}).then(function(b){if(!b.ok)throw"failed to load wasm binary file at '"+F+"'";return b.arrayBuffer()}).catch(function(){return H()})}function J(b){for(;0<b.length;)b.shift()(a)}
var K={b:function(){q("")},a:function(b){var d=v.length;b>>>=0;if(2147483648<b)return!1;for(var l=1;4>=l;l*=2){var f=d*(1+.2/l);f=Math.min(f,b+100663296);var c=Math;f=Math.max(b,f);c=c.min.call(c,2147483648,f+(65536-f%65536)%65536);a:{try{r.grow(c-u.byteLength+65535>>>16);w();var e=1;break a}catch(O){}e=void 0}if(e)return!0}return!1}};
(function(){function b(c){a.asm=c.exports;r=a.asm.c;w();y.unshift(a.asm.d);B--;a.monitorRunDependencies&&a.monitorRunDependencies(B);0==B&&(null!==C&&(clearInterval(C),C=null),D&&(c=D,D=null,c()))}function d(c){b(c.instance)}function l(c){return I().then(function(e){return WebAssembly.instantiate(e,f)}).then(function(e){return e}).then(c,function(e){n("failed to asynchronously prepare wasm: "+e);q(e)})}var f={a:K};B++;a.monitorRunDependencies&&a.monitorRunDependencies(B);if(a.instantiateWasm)try{return a.instantiateWasm(f,
b)}catch(c){return n("Module.instantiateWasm callback failed with error: "+c),!1}(function(){return p||"function"!=typeof WebAssembly.instantiateStreaming||E()||"function"!=typeof fetch?l(d):fetch(F,{credentials:"same-origin"}).then(function(c){return WebAssembly.instantiateStreaming(c,f).then(d,function(e){n("wasm streaming compile failed: "+e);n("falling back to ArrayBuffer instantiation");return l(d)})})})().catch(h);return{}})();
a.___wasm_call_ctors=function(){return(a.___wasm_call_ctors=a.asm.d).apply(null,arguments)};a._publicKeySize=function(){return(a._publicKeySize=a.asm.e).apply(null,arguments)};a._publicKeyFromSecretKey=function(){return(a._publicKeyFromSecretKey=a.asm.f).apply(null,arguments)};a._signatureSize=function(){return(a._signatureSize=a.asm.g).apply(null,arguments)};a._sign=function(){return(a._sign=a.asm.h).apply(null,arguments)};a._verify=function(){return(a._verify=a.asm.i).apply(null,arguments)};
a._malloc=function(){return(a._malloc=a.asm.j).apply(null,arguments)};a._free=function(){return(a._free=a.asm.k).apply(null,arguments)};var L;D=function M(){L||N();L||(D=M)};
function N(){function b(){if(!L&&(L=!0,a.calledRun=!0,!t)){J(y);g(a);if(a.onRuntimeInitialized)a.onRuntimeInitialized();if(a.postRun)for("function"==typeof a.postRun&&(a.postRun=[a.postRun]);a.postRun.length;){var d=a.postRun.shift();z.unshift(d)}J(z)}}if(!(0<B)){if(a.preRun)for("function"==typeof a.preRun&&(a.preRun=[a.preRun]);a.preRun.length;)A();J(x);0<B||(a.setStatus?(a.setStatus("Running..."),setTimeout(function(){setTimeout(function(){a.setStatus("")},1);b()},1)):b())}}
if(a.preInit)for("function"==typeof a.preInit&&(a.preInit=[a.preInit]);0<a.preInit.length;)a.preInit.pop()();N();
return ed25519.ready
}
);
})();
if (typeof exports === 'object' && typeof module === 'object')
module.exports = ed25519;
else if (typeof define === 'function' && define['amd'])
define([], function() { return ed25519; });
else if (typeof exports === 'object')
exports["ed25519"] = ed25519;
// Use strict
"use strict";
// Classes
// Ed25519 class
class Ed25519 {
// Public
// Initialize
static initialize() {
// Set instance to invalid
Ed25519.instance = Ed25519.INVALID;
// Return promise
return new Promise(function(resolve, reject) {
// Set settings
var settings = {
// On abort
"onAbort": function(error) {
// Prevent on abort from being called again
delete settings["onAbort"];
// Reject error
reject("Failed to download resource");
}
};
// Create Ed25519 instance
ed25519(settings).then(function(instance) {
// Prevent on abort from being called
delete settings["onAbort"];
// Set instance
Ed25519.instance = instance;
// Resolve
resolve();
});
});
}
// Public key from secret key
static publicKeyFromSecretKey(secretKey) {
// Check if instance doesn't exist
if(typeof Ed25519.instance === "undefined")
// Set instance
Ed25519.instance = ed25519();
// Check if instance is invalid
if(Ed25519.instance === Ed25519.INVALID)
// Return operation failed
return Ed25519.OPERATION_FAILED;
// Initialize public key to size of public key
var publicKey = new Uint8Array(Ed25519.instance._publicKeySize());
// Allocate and fill memory
var publicKeyBuffer = Ed25519.instance._malloc(publicKey["length"] * publicKey["BYTES_PER_ELEMENT"]);
var secretKeyBuffer = Ed25519.instance._malloc(secretKey["length"] * secretKey["BYTES_PER_ELEMENT"]);
Ed25519.instance["HEAPU8"].set(secretKey, secretKeyBuffer / secretKey["BYTES_PER_ELEMENT"]);
// Check if getting public key from secret key failed
if(Ed25519.instance._publicKeyFromSecretKey(publicKeyBuffer, secretKeyBuffer, secretKey["length"] * secretKey["BYTES_PER_ELEMENT"]) === Ed25519.C_FALSE) {
// Clear memory
Ed25519.instance["HEAPU8"].fill(0, publicKeyBuffer / publicKey["BYTES_PER_ELEMENT"], publicKeyBuffer / publicKey["BYTES_PER_ELEMENT"] + publicKey["length"]);
Ed25519.instance["HEAPU8"].fill(0, secretKeyBuffer / secretKey["BYTES_PER_ELEMENT"], secretKeyBuffer / secretKey["BYTES_PER_ELEMENT"] + secretKey["length"]);
// Free memory
Ed25519.instance._free(publicKeyBuffer);
Ed25519.instance._free(secretKeyBuffer);
// Return operation failed
return Ed25519.OPERATION_FAILED;
}
// Get public key
publicKey = new Uint8Array(Ed25519.instance["HEAPU8"].subarray(publicKeyBuffer, publicKeyBuffer + publicKey["length"]));
// Clear memory
Ed25519.instance["HEAPU8"].fill(0, publicKeyBuffer / publicKey["BYTES_PER_ELEMENT"], publicKeyBuffer / publicKey["BYTES_PER_ELEMENT"] + publicKey["length"]);
Ed25519.instance["HEAPU8"].fill(0, secretKeyBuffer / secretKey["BYTES_PER_ELEMENT"], secretKeyBuffer / secretKey["BYTES_PER_ELEMENT"] + secretKey["length"]);
// Free memory
Ed25519.instance._free(publicKeyBuffer);
Ed25519.instance._free(secretKeyBuffer);
// Return public key
return publicKey;
}
// Sign
static sign(message, secretKey) {
// Check if instance doesn't exist
if(typeof Ed25519.instance === "undefined")
// Set instance
Ed25519.instance = ed25519();
// Check if instance is invalid
if(Ed25519.instance === Ed25519.INVALID)
// Return operation failed
return Ed25519.OPERATION_FAILED;
// Initialize signature to size of signature
var signature = new Uint8Array(Ed25519.instance._signatureSize());
// Allocate and fill memory
var signatureBuffer = Ed25519.instance._malloc(signature["length"] * signature["BYTES_PER_ELEMENT"]);
var messageBuffer = Ed25519.instance._malloc(message["length"] * message["BYTES_PER_ELEMENT"]);
Ed25519.instance["HEAPU8"].set(message, messageBuffer / message["BYTES_PER_ELEMENT"]);
var secretKeyBuffer = Ed25519.instance._malloc(secretKey["length"] * secretKey["BYTES_PER_ELEMENT"]);
Ed25519.instance["HEAPU8"].set(secretKey, secretKeyBuffer / secretKey["BYTES_PER_ELEMENT"]);
// Check if signing message failed
if(Ed25519.instance._sign(signatureBuffer, messageBuffer, message["length"] * message["BYTES_PER_ELEMENT"], secretKeyBuffer, secretKey["length"] * secretKey["BYTES_PER_ELEMENT"]) === Ed25519.C_FALSE) {
// Clear memory
Ed25519.instance["HEAPU8"].fill(0, signatureBuffer / signature["BYTES_PER_ELEMENT"], signatureBuffer / signature["BYTES_PER_ELEMENT"] + signature["length"]);
Ed25519.instance["HEAPU8"].fill(0, messageBuffer / message["BYTES_PER_ELEMENT"], messageBuffer / message["BYTES_PER_ELEMENT"] + message["length"]);
Ed25519.instance["HEAPU8"].fill(0, secretKeyBuffer / secretKey["BYTES_PER_ELEMENT"], secretKeyBuffer / secretKey["BYTES_PER_ELEMENT"] + secretKey["length"]);
// Free memory
Ed25519.instance._free(signatureBuffer);
Ed25519.instance._free(messageBuffer);
Ed25519.instance._free(secretKeyBuffer);
// Return operation failed
return Ed25519.OPERATION_FAILED;
}
// Get signature
signature = new Uint8Array(Ed25519.instance["HEAPU8"].subarray(signatureBuffer, signatureBuffer + signature["length"]));
// Clear memory
Ed25519.instance["HEAPU8"].fill(0, signatureBuffer / signature["BYTES_PER_ELEMENT"], signatureBuffer / signature["BYTES_PER_ELEMENT"] + signature["length"]);
Ed25519.instance["HEAPU8"].fill(0, messageBuffer / message["BYTES_PER_ELEMENT"], messageBuffer / message["BYTES_PER_ELEMENT"] + message["length"]);
Ed25519.instance["HEAPU8"].fill(0, secretKeyBuffer / secretKey["BYTES_PER_ELEMENT"], secretKeyBuffer / secretKey["BYTES_PER_ELEMENT"] + secretKey["length"]);
// Free memory
Ed25519.instance._free(signatureBuffer);
Ed25519.instance._free(messageBuffer);
Ed25519.instance._free(secretKeyBuffer);
// Return signature
return signature;
}
// Verify
static verify(message, signature, publicKey) {
// Check if instance doesn't exist
if(typeof Ed25519.instance === "undefined")
// Set instance
Ed25519.instance = ed25519();
// Check if instance is invalid
if(Ed25519.instance === Ed25519.INVALID)
// Return operation failed
return Ed25519.OPERATION_FAILED;
// Allocate and fill memory
var messageBuffer = Ed25519.instance._malloc(message["length"] * message["BYTES_PER_ELEMENT"]);
Ed25519.instance["HEAPU8"].set(message, messageBuffer / message["BYTES_PER_ELEMENT"]);
var signatureBuffer = Ed25519.instance._malloc(signature["length"] * signature["BYTES_PER_ELEMENT"]);
Ed25519.instance["HEAPU8"].set(signature, signatureBuffer / signature["BYTES_PER_ELEMENT"]);
var publicKeyBuffer = Ed25519.instance._malloc(publicKey["length"] * publicKey["BYTES_PER_ELEMENT"]);
Ed25519.instance["HEAPU8"].set(publicKey, publicKeyBuffer / publicKey["BYTES_PER_ELEMENT"]);
// Check if performing verify failed
if(Ed25519.instance._verify(messageBuffer, message["length"] * message["BYTES_PER_ELEMENT"], signatureBuffer, signature["length"] * signature["BYTES_PER_ELEMENT"], publicKeyBuffer, publicKey["length"] * publicKey["BYTES_PER_ELEMENT"]) === Ed25519.C_FALSE) {
// Clear memory
Ed25519.instance["HEAPU8"].fill(0, messageBuffer / message["BYTES_PER_ELEMENT"], messageBuffer / message["BYTES_PER_ELEMENT"] + message["length"]);
Ed25519.instance["HEAPU8"].fill(0, signatureBuffer / signature["BYTES_PER_ELEMENT"], signatureBuffer / signature["BYTES_PER_ELEMENT"] + signature["length"]);
Ed25519.instance["HEAPU8"].fill(0, publicKeyBuffer / publicKey["BYTES_PER_ELEMENT"], publicKeyBuffer / publicKey["BYTES_PER_ELEMENT"] + publicKey["length"]);
// Free memory
Ed25519.instance._free(messageBuffer);
Ed25519.instance._free(signatureBuffer);
Ed25519.instance._free(publicKeyBuffer);
// Return false
return false;
}
// Clear memory
Ed25519.instance["HEAPU8"].fill(0, messageBuffer / message["BYTES_PER_ELEMENT"], messageBuffer / message["BYTES_PER_ELEMENT"] + message["length"]);
Ed25519.instance["HEAPU8"].fill(0, signatureBuffer / signature["BYTES_PER_ELEMENT"], signatureBuffer / signature["BYTES_PER_ELEMENT"] + signature["length"]);
Ed25519.instance["HEAPU8"].fill(0, publicKeyBuffer / publicKey["BYTES_PER_ELEMENT"], publicKeyBuffer / publicKey["BYTES_PER_ELEMENT"] + publicKey["length"]);
// Free memory
Ed25519.instance._free(messageBuffer);
Ed25519.instance._free(signatureBuffer);
Ed25519.instance._free(publicKeyBuffer);
// Return true
return true;
}
// Operation failed
static get OPERATION_FAILED() {
// Return operation failed
return null;
}
// Private
// Invalid
static get INVALID() {
// Return invalid
return null;
}
// C false
static get C_FALSE() {
// Return C false
return 0;
}
}
// Supporting fuction implementation
// Check if document doesn't exist
if(typeof document === "undefined") {
// Create document
var document = {};
}
// Check if module exports exists
if(typeof module === "object" && module !== null && "exports" in module === true) {
// Exports
module["exports"] = Ed25519;
}

BIN
scripts/Ed25519-0.0.22.wasm Executable file

Binary file not shown.

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2017 William Buss
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

815
scripts/JSONBigNumber-1.1.1.js Executable file
View File

@@ -0,0 +1,815 @@
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory(require("bignumber.js"));
else if(typeof define === 'function' && define.amd)
define(["bignumber.js"], factory);
else if(typeof exports === 'object')
exports["JSONBigNumber"] = factory(require("bignumber.js"));
else
root["JSONBigNumber"] = factory(root["BigNumber"]);
})(this, function(__WEBPACK_EXTERNAL_MODULE__332__) {
return /******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({
/***/ 332:
/***/ ((module) => {
module.exports = __WEBPACK_EXTERNAL_MODULE__332__;
/***/ })
/******/ });
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
/******/ /* webpack/runtime/compat get default export */
/******/ (() => {
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = (module) => {
/******/ var getter = module && module.__esModule ?
/******/ () => (module['default']) :
/******/ () => (module);
/******/ __webpack_require__.d(getter, { a: getter });
/******/ return getter;
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ (() => {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = (exports) => {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ })();
/******/
/************************************************************************/
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
(() => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "stringify": () => (/* binding */ stringify),
/* harmony export */ "parse": () => (/* binding */ parse),
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var bignumber_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(332);
/* harmony import */ var bignumber_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(bignumber_js__WEBPACK_IMPORTED_MODULE_0__);
// JSONBigNumber.js
// 2017-02-14
// Public Domain.
// NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
// See http://www.JSON.org/js.html
// This code should be minified before deployment.
// USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
// NOT CONTROL.
// This file creates a global JSONBigNumber object containing two methods: stringify
// and parse.
// JSONBigNumber.stringify(value, replacer, space)
// value any JavaScript value, usually an object or array.
// replacer an optional parameter that determines how object
// values are stringified for objects. It can be a
// function or an array of strings.
// space an optional parameter that specifies the indentation
// of nested structures. If it is omitted, the text will
// be packed without extra whitespace. If it is a number,
// it will specify the number of spaces to indent at each
// level. If it is a string (such as "\t" or "&nbsp;"),
// it contains the characters used to indent at each level.
// This method produces a JSON text from a JavaScript value.
// When an object value is found, if the object contains a toJSON
// method, its toJSON method will be called and the result will be
// stringified. A toJSON method does not serialize: it returns the
// value represented by the name/value pair that should be serialized,
// or undefined if nothing should be serialized. The toJSON method
// will be passed the key associated with the value, and this will be
// bound to the value.
// For example, this would serialize Dates as ISO strings.
// Date.prototype.toJSON = function (key) {
// function f(n) {
// // Format integers to have at least two digits.
// return (n < 10)
// ? "0" + n
// : n;
// }
// return this.getUTCFullYear() + "-" +
// f(this.getUTCMonth() + 1) + "-" +
// f(this.getUTCDate()) + "T" +
// f(this.getUTCHours()) + ":" +
// f(this.getUTCMinutes()) + ":" +
// f(this.getUTCSeconds()) + "Z";
// };
// You can provide an optional replacer method. It will be passed the
// key and value of each member, with this bound to the containing
// object. The value that is returned from your method will be
// serialized. If your method returns undefined, then the member will
// be excluded from the serialization.
// If the replacer parameter is an array of strings, then it will be
// used to select the members to be serialized. It filters the results
// such that only members with keys listed in the replacer array are
// stringified.
// Values that do not have JSON representations, such as undefined or
// functions, will not be serialized. Such values in objects will be
// dropped; in arrays they will be replaced with null. You can use
// a replacer function to replace those with JSON values.
// JSONBigNumber.stringify(undefined) returns undefined.
// The optional space parameter produces a stringification of the
// value that is filled with line breaks and indentation to make it
// easier to read.
// If the space parameter is a non-empty string, then that string will
// be used for indentation. If the space parameter is a number, then
// the indentation will be that many spaces.
// Example:
// text = JSONBigNumber.stringify(["e", {pluribus: "unum"}]);
// // text is '["e",{"pluribus":"unum"}]'
// text = JSONBigNumber.stringify(["e", {pluribus: "unum"}], null, "\t");
// // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
// text = JSONBigNumber.stringify([new Date()], function (key, value) {
// return this[key] instanceof Date
// ? "Date(" + this[key] + ")"
// : value;
// });
// // text is '["Date(---current time---)"]'
// JSONBigNumber.parse(text, reviver)
// This method parses a JSON text to produce an object or array.
// It can throw a SyntaxError exception.
// The optional reviver parameter is a function that can filter and
// transform the results. It receives each of the keys and values,
// and its return value is used instead of the original value.
// If it returns what it received, then the structure is not modified.
// If it returns undefined then the member is deleted.
// Example:
// // Parse the text. Values that look like ISO date strings will
// // be converted to Date objects.
// myData = JSONBigNumber.parse(text, function (key, value) {
// var a;
// if (typeof value === "string") {
// a =
// /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
// if (a) {
// return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
// +a[5], +a[6]));
// }
// }
// return value;
// });
// myData = JSONBigNumber.parse('["Date(09/09/2001)"]', function (key, value) {
// var d;
// if (typeof value === "string" &&
// value.slice(0, 5) === "Date(" &&
// value.slice(-1) === ")") {
// d = new Date(value.slice(5, -1));
// if (d) {
// return d;
// }
// }
// return value;
// });
// This is a reference implementation. You are free to copy, modify, or
// redistribute.
/*jslint
eval, for, this
*/
/*property
JSONBigNumber, apply, call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
lastIndex, length, parse, prototype, push, replace, slice, stringify,
test, toJSON, toString, valueOf
*/
var rx_escapable = /[\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
function f(n) {
// Format integers to have at least two digits.
return n < 10 ?
"0" + n :
n;
}
function this_value() {
return this.valueOf();
}
if (typeof Date.prototype.toJSON !== "function") {
Date.prototype.toJSON = function () {
return isFinite(this.valueOf()) ?
this.getUTCFullYear() + "-" +
f(this.getUTCMonth() + 1) + "-" +
f(this.getUTCDate()) + "T" +
f(this.getUTCHours()) + ":" +
f(this.getUTCMinutes()) + ":" +
f(this.getUTCSeconds()) + "Z" :
null;
};
Boolean.prototype.toJSON = this_value;
Number.prototype.toJSON = this_value;
String.prototype.toJSON = this_value;
}
var gap;
var indent;
var meta;
var rep;
function quote(string) {
// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.
rx_escapable.lastIndex = 0;
return rx_escapable.test(string) ?
"\"" + string.replace(rx_escapable, function (a) {
var c = meta[a];
return typeof c === "string" ?
c :
"\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4);
}) + "\"" :
"\"" + string + "\"";
}
function str(key, holder) {
// Produce a string from holder[key].
var i; // The loop counter.
var k; // The member key.
var v; // The member value.
var length;
var mind = gap;
var partial;
var value = holder[key];
var isBigNumber = value != null && (value instanceof (bignumber_js__WEBPACK_IMPORTED_MODULE_0___default()) || bignumber_js__WEBPACK_IMPORTED_MODULE_0___default().isBigNumber(value));
// Check for NaN and Infinity
if (isBigNumber && !value.isFinite()) {
value = null;
}
// If the value has a toJSON method, call it to obtain a replacement value.
if (value && typeof value === "object" &&
typeof value.toJSON === "function") {
value = value.toJSON(key);
}
// If we were called with a replacer function, then call the replacer to
// obtain a replacement value.
if (typeof rep === "function") {
value = rep.call(holder, key, value);
}
// What happens next depends on the value's type.
switch (typeof value) {
case "string":
if (isBigNumber) {
return value;
} else {
return quote(value);
}
case "number":
// JSON numbers must be finite. Encode non-finite numbers as null.
return isFinite(value) ?
String(value) :
"null";
case "boolean":
case "null":
// If the value is a boolean or null, convert it to a string. Note:
// typeof null does not produce "null". The case is included here in
// the remote chance that this gets fixed someday.
return String(value);
// If the type is "object", we might be dealing with an object or an array or
// null.
case "object":
// Due to a specification blunder in ECMAScript, typeof null is "object",
// so watch out for that case.
if (!value) {
return "null";
}
// Make an array to hold the partial results of stringifying this object value.
gap += indent;
partial = [];
// Is the value an array?
if (Object.prototype.toString.apply(value) === "[object Array]") {
// The value is an array. Stringify every element. Use null as a placeholder
// for non-JSON values.
length = value.length;
for (i = 0; i < length; i += 1) {
partial[i] = str(i, value) || "null";
}
// Join all of the elements together, separated with commas, and wrap them in
// brackets.
v = partial.length === 0 ?
"[]" :
gap ?
"[\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "]" :
"[" + partial.join(",") + "]";
gap = mind;
return v;
}
// If the replacer is an array, use it to select the members to be stringified.
if (rep && typeof rep === "object") {
length = rep.length;
for (i = 0; i < length; i += 1) {
if (typeof rep[i] === "string") {
k = rep[i];
v = str(k, value);
if (v) {
partial.push(quote(k) + (
gap ?
": " :
":"
) + v);
}
}
}
} else {
// Otherwise, iterate through all of the keys in the object.
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = str(k, value);
if (v) {
partial.push(quote(k) + (
gap ?
": " :
":"
) + v);
}
}
}
}
// Join all of the member texts together, separated with commas,
// and wrap them in braces.
v = partial.length === 0 ?
"{}" :
gap ?
"{\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "}" :
"{" + partial.join(",") + "}";
gap = mind;
return v;
}
}
// If the JSON object does not yet have a stringify method, give it one.
meta = { // table of character substitutions
"\b": "\\b",
"\t": "\\t",
"\n": "\\n",
"\f": "\\f",
"\r": "\\r",
"\"": "\\\"",
"\\": "\\\\"
};
function stringify(value, replacer, space) {
// The stringify method takes a value and an optional replacer, and an optional
// space parameter, and returns a JSON text. The replacer can be a function
// that can replace values, or an array of strings that will select the keys.
// A default replacer method can be provided. Use of the space parameter can
// produce text that is more easily readable.
var i;
gap = "";
indent = "";
// If the space parameter is a number, make an indent string containing that
// many spaces.
if (typeof space === "number") {
for (i = 0; i < space; i += 1) {
indent += " ";
}
// If the space parameter is a string, it will be used as the indent string.
} else if (typeof space === "string") {
indent = space;
}
// If there is a replacer, it must be a function or an array.
// Otherwise, throw an error.
rep = replacer;
if (replacer && typeof replacer !== "function" &&
(typeof replacer !== "object" ||
typeof replacer.length !== "number")) {
throw new Error("JSON.stringify");
}
// Make a fake root object containing our value under the key of "".
// Return the result of stringifying the value.
return str("", {
"": value
});
}
// We are defining the function inside of another function to avoid creating
// global variables.
var at; // The index of the current character
var ch; // The current character
var escapee = {
"\"": "\"",
"\\": "\\",
"/": "/",
b: "\b",
f: "\f",
n: "\n",
r: "\r",
t: "\t"
};
var text;
var error = function (m) {
// Call error when something is wrong.
throw {
name: "SyntaxError",
message: m,
at: at,
text: text
};
};
var next = function (c) {
// If a c parameter is provided, verify that it matches the current character.
if (c && c !== ch) {
error("Expected '" + c + "' instead of '" + ch + "'");
}
// Get the next character. When there are no more characters,
// return the empty string.
ch = text.charAt(at);
at += 1;
return ch;
};
var number = function () {
// Parse a number value to a BigNumber.
var number;
var string = "";
if (ch === "-") {
string = "-";
next("-");
}
while (ch >= "0" && ch <= "9") {
string += ch;
next();
}
if (ch === ".") {
string += ".";
while (next() && ch >= "0" && ch <= "9") {
string += ch;
}
}
if (ch === "e" || ch === "E") {
string += ch;
next();
if (ch === "-" || ch === "+") {
string += ch;
next();
}
while (ch >= "0" && ch <= "9") {
string += ch;
next();
}
}
number = new (bignumber_js__WEBPACK_IMPORTED_MODULE_0___default())(string);
if (!number.isFinite()) {
error("Bad number");
} else {
return number;
}
};
var string = function () {
// Parse a string value.
var hex;
var i;
var value = "";
var uffff;
// When parsing for string values, we must look for " and \ characters.
if (ch === "\"") {
while (next()) {
if (ch === "\"") {
next();
return value;
}
if (ch === "\\") {
next();
if (ch === "u") {
uffff = 0;
for (i = 0; i < 4; i += 1) {
hex = parseInt(next(), 16);
if (!isFinite(hex)) {
break;
}
uffff = uffff * 16 + hex;
}
value += String.fromCharCode(uffff);
} else if (typeof escapee[ch] === "string") {
value += escapee[ch];
} else {
break;
}
} else {
value += ch;
}
}
}
error("Bad string");
};
var white = function () {
// Skip whitespace.
while (ch && ch <= " ") {
next();
}
};
var word = function () {
// true, false, or null.
switch (ch) {
case "t":
next("t");
next("r");
next("u");
next("e");
return true;
case "f":
next("f");
next("a");
next("l");
next("s");
next("e");
return false;
case "n":
next("n");
next("u");
next("l");
next("l");
return null;
}
error("Unexpected '" + ch + "'");
};
var value; // Place holder for the value function.
var array = function () {
// Parse an array value.
var arr = [];
if (ch === "[") {
next("[");
white();
if (ch === "]") {
next("]");
return arr; // empty array
}
while (ch) {
arr.push(value());
white();
if (ch === "]") {
next("]");
return arr;
}
next(",");
white();
}
}
error("Bad array");
};
var object = function () {
// Parse an object value.
var key;
var obj = {};
if (ch === "{") {
next("{");
white();
if (ch === "}") {
next("}");
return obj; // empty object
}
while (ch) {
key = string();
white();
next(":");
if (Object.hasOwnProperty.call(obj, key)) {
error("Duplicate key '" + key + "'");
}
obj[key] = value();
white();
if (ch === "}") {
next("}");
return obj;
}
next(",");
white();
}
}
error("Bad object");
};
value = function () {
// Parse a JSON value. It could be an object, an array, a string, a number,
// or a word.
white();
switch (ch) {
case "{":
return object();
case "[":
return array();
case "\"":
return string();
case "-":
return number();
default:
return (ch >= "0" && ch <= "9") ?
number() :
word();
}
};
// Set the New JSONBigNumber.parse function It will have access to all of the above
// functions and variables.
function parse(source, reviver) {
var result;
text = source;
at = 0;
ch = " ";
result = value();
white();
if (ch) {
error("Syntax error");
}
// If there is a reviver function, we recursively walk the new structure,
// passing each name/value pair to the reviver function for possible
// transformation, starting with a temporary root object that holds the result
// in an empty key. If there is not a reviver function, we simply return the
// result.
return (typeof reviver === "function") ? (function walk(holder, key) {
var k;
var v;
var val = holder[key];
if (val && typeof val === "object") {
for (k in val) {
if (Object.prototype.hasOwnProperty.call(val, k)) {
v = walk(val, k);
if (v !== undefined) {
val[k] = v;
} else {
delete val[k];
}
}
}
}
return reviver.call(holder, key, val);
}({
"": result
}, "")) :
result;
}
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({
parse: parse,
stringify: stringify
});
})();
/******/ return __webpack_exports__;
/******/ })()
;
});

21
scripts/SMAZ license.txt Executable file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022-2023 Nicolas Flamel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

261
scripts/SMAZ-0.0.31.js Executable file
View File

@@ -0,0 +1,261 @@
var smaz = (() => {
var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;
return (
function(smaz) {
smaz = smaz || {};
var a;a||(a=typeof smaz !== 'undefined' ? smaz : {});var g,h;a.ready=new Promise(function(b,d){g=b;h=d});var k=Object.assign({},a),m="";"undefined"!=typeof document&&document.currentScript&&(m=document.currentScript.src);_scriptDir&&(m=_scriptDir);0!==m.indexOf("blob:")?m=m.substr(0,m.replace(/[?#].*/,"").lastIndexOf("/")+1):m="";var n=a.printErr||console.warn.bind(console);Object.assign(a,k);k=null;var p;a.wasmBinary&&(p=a.wasmBinary);var noExitRuntime=a.noExitRuntime||!0;
"object"!=typeof WebAssembly&&q("no native wasm support detected");var r,t=!1,u,v;function w(){var b=r.buffer;u=b;a.HEAP8=new Int8Array(b);a.HEAP16=new Int16Array(b);a.HEAP32=new Int32Array(b);a.HEAPU8=v=new Uint8Array(b);a.HEAPU16=new Uint16Array(b);a.HEAPU32=new Uint32Array(b);a.HEAPF32=new Float32Array(b);a.HEAPF64=new Float64Array(b)}var x=[],y=[],z=[];function A(){var b=a.preRun.shift();x.unshift(b)}var B=0,C=null,D=null;
function q(b){if(a.onAbort)a.onAbort(b);b="Aborted("+b+")";n(b);t=!0;b=new WebAssembly.RuntimeError(b+". Build with -sASSERTIONS for more info.");h(b);throw b;}function E(){return F.startsWith("data:application/octet-stream;base64,")}var F;F="." + getResource("./scripts/SMAZ-0.0.31.wasm");if(!E()){var G=F;F=a.locateFile?a.locateFile(G,m):m+G}function H(){var b=F;try{if(b==F&&p)return new Uint8Array(p);throw"both async and sync fetching of the wasm failed";}catch(d){q(d)}}
function I(){return p||"function"!=typeof fetch?Promise.resolve().then(function(){return H()}):fetch(F,{credentials:"same-origin"}).then(function(b){if(!b.ok)throw"failed to load wasm binary file at '"+F+"'";return b.arrayBuffer()}).catch(function(){return H()})}function J(b){for(;0<b.length;)b.shift()(a)}
var K={b:function(){q("")},a:function(b){var d=v.length;b>>>=0;if(2147483648<b)return!1;for(var l=1;4>=l;l*=2){var f=d*(1+.2/l);f=Math.min(f,b+100663296);var c=Math;f=Math.max(b,f);c=c.min.call(c,2147483648,f+(65536-f%65536)%65536);a:{try{r.grow(c-u.byteLength+65535>>>16);w();var e=1;break a}catch(O){}e=void 0}if(e)return!0}return!1}};
(function(){function b(c){a.asm=c.exports;r=a.asm.c;w();y.unshift(a.asm.d);B--;a.monitorRunDependencies&&a.monitorRunDependencies(B);0==B&&(null!==C&&(clearInterval(C),C=null),D&&(c=D,D=null,c()))}function d(c){b(c.instance)}function l(c){return I().then(function(e){return WebAssembly.instantiate(e,f)}).then(function(e){return e}).then(c,function(e){n("failed to asynchronously prepare wasm: "+e);q(e)})}var f={a:K};B++;a.monitorRunDependencies&&a.monitorRunDependencies(B);if(a.instantiateWasm)try{return a.instantiateWasm(f,
b)}catch(c){return n("Module.instantiateWasm callback failed with error: "+c),!1}(function(){return p||"function"!=typeof WebAssembly.instantiateStreaming||E()||"function"!=typeof fetch?l(d):fetch(F,{credentials:"same-origin"}).then(function(c){return WebAssembly.instantiateStreaming(c,f).then(d,function(e){n("wasm streaming compile failed: "+e);n("falling back to ArrayBuffer instantiation");return l(d)})})})().catch(h);return{}})();
a.___wasm_call_ctors=function(){return(a.___wasm_call_ctors=a.asm.d).apply(null,arguments)};a._invalidSize=function(){return(a._invalidSize=a.asm.e).apply(null,arguments)};a._compressSize=function(){return(a._compressSize=a.asm.f).apply(null,arguments)};a._compress=function(){return(a._compress=a.asm.g).apply(null,arguments)};a._decompressSize=function(){return(a._decompressSize=a.asm.h).apply(null,arguments)};a._decompress=function(){return(a._decompress=a.asm.i).apply(null,arguments)};
a._malloc=function(){return(a._malloc=a.asm.j).apply(null,arguments)};a._free=function(){return(a._free=a.asm.k).apply(null,arguments)};var L;D=function M(){L||N();L||(D=M)};
function N(){function b(){if(!L&&(L=!0,a.calledRun=!0,!t)){J(y);g(a);if(a.onRuntimeInitialized)a.onRuntimeInitialized();if(a.postRun)for("function"==typeof a.postRun&&(a.postRun=[a.postRun]);a.postRun.length;){var d=a.postRun.shift();z.unshift(d)}J(z)}}if(!(0<B)){if(a.preRun)for("function"==typeof a.preRun&&(a.preRun=[a.preRun]);a.preRun.length;)A();J(x);0<B||(a.setStatus?(a.setStatus("Running..."),setTimeout(function(){setTimeout(function(){a.setStatus("")},1);b()},1)):b())}}
if(a.preInit)for("function"==typeof a.preInit&&(a.preInit=[a.preInit]);0<a.preInit.length;)a.preInit.pop()();N();
return smaz.ready
}
);
})();
if (typeof exports === 'object' && typeof module === 'object')
module.exports = smaz;
else if (typeof define === 'function' && define['amd'])
define([], function() { return smaz; });
else if (typeof exports === 'object')
exports["smaz"] = smaz;
// Use strict
"use strict";
// Classes
// SMAZ class
class Smaz {
// Public
// Initialize
static initialize() {
// Set instance to invalid
Smaz.instance = Smaz.INVALID;
// Return promise
return new Promise(function(resolve, reject) {
// Set settings
var settings = {
// On abort
"onAbort": function(error) {
// Prevent on abort from being called again
delete settings["onAbort"];
// Reject error
reject("Failed to download resource");
}
};
// Create SMAZ instance
smaz(settings).then(function(instance) {
// Prevent on abort from being called
delete settings["onAbort"];
// Set instance
Smaz.instance = instance;
// Resolve
resolve();
});
});
}
// Compress
static compress(input) {
// Check if instance doesn't exist
if(typeof Smaz.instance === "undefined")
// Set instance
Smaz.instance = smaz();
// Check if instance is invalid
if(Smaz.instance === Smaz.INVALID)
// Return operation failed
return Smaz.OPERATION_FAILED;
// Allocate and fill memory
var inputBuffer = Smaz.instance._malloc(input["length"] * input["BYTES_PER_ELEMENT"]);
Smaz.instance["HEAPU8"].set(input, inputBuffer / input["BYTES_PER_ELEMENT"]);
// Check if getting compress size failed
var compressSize = Smaz.instance._compressSize(inputBuffer, input["length"] * input["BYTES_PER_ELEMENT"]);
if(compressSize === Smaz.instance._invalidSize()) {
// Clear memory
Smaz.instance["HEAPU8"].fill(0, inputBuffer / input["BYTES_PER_ELEMENT"], inputBuffer / input["BYTES_PER_ELEMENT"] + input["length"]);
// Free memory
Smaz.instance._free(inputBuffer);
// Return operation failed
return Smaz.OPERATION_FAILED;
}
// Initialize result to compress size
var result = new Uint8Array(compressSize);
// Allocate and fill memory
var resultBuffer = Smaz.instance._malloc(result["length"] * result["BYTES_PER_ELEMENT"]);
// Check if compressing failed
if(Smaz.instance._compress(resultBuffer, result["length"] * result["BYTES_PER_ELEMENT"], inputBuffer, input["length"] * input["BYTES_PER_ELEMENT"]) === Smaz.C_FALSE) {
// Clear memory
Smaz.instance["HEAPU8"].fill(0, resultBuffer / result["BYTES_PER_ELEMENT"], resultBuffer / result["BYTES_PER_ELEMENT"] + result["length"]);
Smaz.instance["HEAPU8"].fill(0, inputBuffer / input["BYTES_PER_ELEMENT"], inputBuffer / input["BYTES_PER_ELEMENT"] + input["length"]);
// Free memory
Smaz.instance._free(resultBuffer);
Smaz.instance._free(inputBuffer);
// Return operation failed
return Smaz.OPERATION_FAILED;
}
// Get result
result = new Uint8Array(Smaz.instance["HEAPU8"].subarray(resultBuffer, resultBuffer + result["length"]));
// Clear memory
Smaz.instance["HEAPU8"].fill(0, resultBuffer / result["BYTES_PER_ELEMENT"], resultBuffer / result["BYTES_PER_ELEMENT"] + result["length"]);
Smaz.instance["HEAPU8"].fill(0, inputBuffer / input["BYTES_PER_ELEMENT"], inputBuffer / input["BYTES_PER_ELEMENT"] + input["length"]);
// Free memory
Smaz.instance._free(resultBuffer);
Smaz.instance._free(inputBuffer);
// Return result
return result;
}
// Decompress
static decompress(input) {
// Check if instance doesn't exist
if(typeof Smaz.instance === "undefined")
// Set instance
Smaz.instance = smaz();
// Check if instance is invalid
if(Smaz.instance === Smaz.INVALID)
// Return operation failed
return Smaz.OPERATION_FAILED;
// Allocate and fill memory
var inputBuffer = Smaz.instance._malloc(input["length"] * input["BYTES_PER_ELEMENT"]);
Smaz.instance["HEAPU8"].set(input, inputBuffer / input["BYTES_PER_ELEMENT"]);
// Check if getting decompress size failed
var decompressSize = Smaz.instance._decompressSize(inputBuffer, input["length"] * input["BYTES_PER_ELEMENT"]);
if(decompressSize === Smaz.instance._invalidSize()) {
// Clear memory
Smaz.instance["HEAPU8"].fill(0, inputBuffer / input["BYTES_PER_ELEMENT"], inputBuffer / input["BYTES_PER_ELEMENT"] + input["length"]);
// Free memory
Smaz.instance._free(inputBuffer);
// Return operation failed
return Smaz.OPERATION_FAILED;
}
// Initialize result to decompress size
var result = new Uint8Array(decompressSize);
// Allocate and fill memory
var resultBuffer = Smaz.instance._malloc(result["length"] * result["BYTES_PER_ELEMENT"]);
// Check if decompressing failed
if(Smaz.instance._decompress(resultBuffer, result["length"] * result["BYTES_PER_ELEMENT"], inputBuffer, input["length"] * input["BYTES_PER_ELEMENT"]) === Smaz.C_FALSE) {
// Clear memory
Smaz.instance["HEAPU8"].fill(0, resultBuffer / result["BYTES_PER_ELEMENT"], resultBuffer / result["BYTES_PER_ELEMENT"] + result["length"]);
Smaz.instance["HEAPU8"].fill(0, inputBuffer / input["BYTES_PER_ELEMENT"], inputBuffer / input["BYTES_PER_ELEMENT"] + input["length"]);
// Free memory
Smaz.instance._free(resultBuffer);
Smaz.instance._free(inputBuffer);
// Return operation failed
return Smaz.OPERATION_FAILED;
}
// Get result
result = new Uint8Array(Smaz.instance["HEAPU8"].subarray(resultBuffer, resultBuffer + result["length"]));
// Clear memory
Smaz.instance["HEAPU8"].fill(0, resultBuffer / result["BYTES_PER_ELEMENT"], resultBuffer / result["BYTES_PER_ELEMENT"] + result["length"]);
Smaz.instance["HEAPU8"].fill(0, inputBuffer / input["BYTES_PER_ELEMENT"], inputBuffer / input["BYTES_PER_ELEMENT"] + input["length"]);
// Free memory
Smaz.instance._free(resultBuffer);
Smaz.instance._free(inputBuffer);
// Return result
return result;
}
// Operation failed
static get OPERATION_FAILED() {
// Return operation failed
return null;
}
// Private
// Invalid
static get INVALID() {
// Return invalid
return null;
}
// C false
static get C_FALSE() {
// Return C false
return 0;
}
}
// Supporting fuction implementation
// Check if document doesn't exist
if(typeof document === "undefined") {
// Create document
var document = {};
}
// Check if module exports exists
if(typeof module === "object" && module !== null && "exports" in module === true) {
// Exports
module["exports"] = Smaz;
}

BIN
scripts/SMAZ-0.0.31.wasm Executable file

Binary file not shown.

21
scripts/X25519 license.txt Executable file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022-2023 Nicolas Flamel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

290
scripts/X25519-0.0.23.js Executable file
View File

@@ -0,0 +1,290 @@
var x25519 = (() => {
var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;
return (
function(x25519) {
x25519 = x25519 || {};
var a;a||(a=typeof x25519 !== 'undefined' ? x25519 : {});var g,h;a.ready=new Promise(function(b,d){g=b;h=d});var k=Object.assign({},a),m="";"undefined"!=typeof document&&document.currentScript&&(m=document.currentScript.src);_scriptDir&&(m=_scriptDir);0!==m.indexOf("blob:")?m=m.substr(0,m.replace(/[?#].*/,"").lastIndexOf("/")+1):m="";var n=a.printErr||console.warn.bind(console);Object.assign(a,k);k=null;var p;a.wasmBinary&&(p=a.wasmBinary);var noExitRuntime=a.noExitRuntime||!0;
"object"!=typeof WebAssembly&&q("no native wasm support detected");var r,t=!1,u,v;function w(){var b=r.buffer;u=b;a.HEAP8=new Int8Array(b);a.HEAP16=new Int16Array(b);a.HEAP32=new Int32Array(b);a.HEAPU8=v=new Uint8Array(b);a.HEAPU16=new Uint16Array(b);a.HEAPU32=new Uint32Array(b);a.HEAPF32=new Float32Array(b);a.HEAPF64=new Float64Array(b)}var x=[],y=[],z=[];function A(){var b=a.preRun.shift();x.unshift(b)}var B=0,C=null,D=null;
function q(b){if(a.onAbort)a.onAbort(b);b="Aborted("+b+")";n(b);t=!0;b=new WebAssembly.RuntimeError(b+". Build with -sASSERTIONS for more info.");h(b);throw b;}function E(){return F.startsWith("data:application/octet-stream;base64,")}var F;F="." + getResource("./scripts/X25519-0.0.23.wasm");if(!E()){var G=F;F=a.locateFile?a.locateFile(G,m):m+G}function H(){var b=F;try{if(b==F&&p)return new Uint8Array(p);throw"both async and sync fetching of the wasm failed";}catch(d){q(d)}}
function I(){return p||"function"!=typeof fetch?Promise.resolve().then(function(){return H()}):fetch(F,{credentials:"same-origin"}).then(function(b){if(!b.ok)throw"failed to load wasm binary file at '"+F+"'";return b.arrayBuffer()}).catch(function(){return H()})}function J(b){for(;0<b.length;)b.shift()(a)}
var K={b:function(){q("")},a:function(b){var d=v.length;b>>>=0;if(2147483648<b)return!1;for(var l=1;4>=l;l*=2){var f=d*(1+.2/l);f=Math.min(f,b+100663296);var c=Math;f=Math.max(b,f);c=c.min.call(c,2147483648,f+(65536-f%65536)%65536);a:{try{r.grow(c-u.byteLength+65535>>>16);w();var e=1;break a}catch(O){}e=void 0}if(e)return!0}return!1}};
(function(){function b(c){a.asm=c.exports;r=a.asm.c;w();y.unshift(a.asm.d);B--;a.monitorRunDependencies&&a.monitorRunDependencies(B);0==B&&(null!==C&&(clearInterval(C),C=null),D&&(c=D,D=null,c()))}function d(c){b(c.instance)}function l(c){return I().then(function(e){return WebAssembly.instantiate(e,f)}).then(function(e){return e}).then(c,function(e){n("failed to asynchronously prepare wasm: "+e);q(e)})}var f={a:K};B++;a.monitorRunDependencies&&a.monitorRunDependencies(B);if(a.instantiateWasm)try{return a.instantiateWasm(f,
b)}catch(c){return n("Module.instantiateWasm callback failed with error: "+c),!1}(function(){return p||"function"!=typeof WebAssembly.instantiateStreaming||E()||"function"!=typeof fetch?l(d):fetch(F,{credentials:"same-origin"}).then(function(c){return WebAssembly.instantiateStreaming(c,f).then(d,function(e){n("wasm streaming compile failed: "+e);n("falling back to ArrayBuffer instantiation");return l(d)})})})().catch(h);return{}})();
a.___wasm_call_ctors=function(){return(a.___wasm_call_ctors=a.asm.d).apply(null,arguments)};a._secretKeySize=function(){return(a._secretKeySize=a.asm.e).apply(null,arguments)};a._secretKeyFromEd25519SecretKey=function(){return(a._secretKeyFromEd25519SecretKey=a.asm.f).apply(null,arguments)};a._publicKeySize=function(){return(a._publicKeySize=a.asm.g).apply(null,arguments)};a._publicKeyFromEd25519PublicKey=function(){return(a._publicKeyFromEd25519PublicKey=a.asm.h).apply(null,arguments)};
a._sharedSecretKeySize=function(){return(a._sharedSecretKeySize=a.asm.i).apply(null,arguments)};a._sharedSecretKeyFromSecretKeyAndPublicKey=function(){return(a._sharedSecretKeyFromSecretKeyAndPublicKey=a.asm.j).apply(null,arguments)};a._malloc=function(){return(a._malloc=a.asm.k).apply(null,arguments)};a._free=function(){return(a._free=a.asm.l).apply(null,arguments)};var L;D=function M(){L||N();L||(D=M)};
function N(){function b(){if(!L&&(L=!0,a.calledRun=!0,!t)){J(y);g(a);if(a.onRuntimeInitialized)a.onRuntimeInitialized();if(a.postRun)for("function"==typeof a.postRun&&(a.postRun=[a.postRun]);a.postRun.length;){var d=a.postRun.shift();z.unshift(d)}J(z)}}if(!(0<B)){if(a.preRun)for("function"==typeof a.preRun&&(a.preRun=[a.preRun]);a.preRun.length;)A();J(x);0<B||(a.setStatus?(a.setStatus("Running..."),setTimeout(function(){setTimeout(function(){a.setStatus("")},1);b()},1)):b())}}
if(a.preInit)for("function"==typeof a.preInit&&(a.preInit=[a.preInit]);0<a.preInit.length;)a.preInit.pop()();N();
return x25519.ready
}
);
})();
if (typeof exports === 'object' && typeof module === 'object')
module.exports = x25519;
else if (typeof define === 'function' && define['amd'])
define([], function() { return x25519; });
else if (typeof exports === 'object')
exports["x25519"] = x25519;
// Use strict
"use strict";
// Classes
// X25519 class
class X25519 {
// Public
// Initialize
static initialize() {
// Set instance to invalid
X25519.instance = X25519.INVALID;
// Return promise
return new Promise(function(resolve, reject) {
// Set settings
var settings = {
// On abort
"onAbort": function(error) {
// Prevent on abort from being called again
delete settings["onAbort"];
// Reject error
reject("Failed to download resource");
}
};
// Create X25519 instance
x25519(settings).then(function(instance) {
// Prevent on abort from being called
delete settings["onAbort"];
// Set instance
X25519.instance = instance;
// Resolve
resolve();
});
});
}
// Secret key from Ed25519 secret key
static secretKeyFromEd25519SecretKey(ed25519SecretKey) {
// Check if instance doesn't exist
if(typeof X25519.instance === "undefined")
// Set instance
X25519.instance = x25519();
// Check if instance is invalid
if(X25519.instance === X25519.INVALID)
// Return operation failed
return X25519.OPERATION_FAILED;
// Initialize secret key to size of secret key
var secretKey = new Uint8Array(X25519.instance._secretKeySize());
// Allocate and fill memory
var secretKeyBuffer = X25519.instance._malloc(secretKey["length"] * secretKey["BYTES_PER_ELEMENT"]);
var ed25519SecretKeyBuffer = X25519.instance._malloc(ed25519SecretKey["length"] * ed25519SecretKey["BYTES_PER_ELEMENT"]);
X25519.instance["HEAPU8"].set(ed25519SecretKey, ed25519SecretKeyBuffer / ed25519SecretKey["BYTES_PER_ELEMENT"]);
// Check if getting secret key from Ed25519 secret key failed
if(X25519.instance._secretKeyFromEd25519SecretKey(secretKeyBuffer, ed25519SecretKeyBuffer, ed25519SecretKey["length"] * ed25519SecretKey["BYTES_PER_ELEMENT"]) === X25519.C_FALSE) {
// Clear memory
X25519.instance["HEAPU8"].fill(0, secretKeyBuffer / secretKey["BYTES_PER_ELEMENT"], secretKeyBuffer / secretKey["BYTES_PER_ELEMENT"] + secretKey["length"]);
X25519.instance["HEAPU8"].fill(0, ed25519SecretKeyBuffer / ed25519SecretKey["BYTES_PER_ELEMENT"], ed25519SecretKeyBuffer / ed25519SecretKey["BYTES_PER_ELEMENT"] + ed25519SecretKey["length"]);
// Free memory
X25519.instance._free(secretKeyBuffer);
X25519.instance._free(ed25519SecretKeyBuffer);
// Return operation failed
return X25519.OPERATION_FAILED;
}
// Get secret key
secretKey = new Uint8Array(X25519.instance["HEAPU8"].subarray(secretKeyBuffer, secretKeyBuffer + secretKey["length"]));
// Clear memory
X25519.instance["HEAPU8"].fill(0, secretKeyBuffer / secretKey["BYTES_PER_ELEMENT"], secretKeyBuffer / secretKey["BYTES_PER_ELEMENT"] + secretKey["length"]);
X25519.instance["HEAPU8"].fill(0, ed25519SecretKeyBuffer / ed25519SecretKey["BYTES_PER_ELEMENT"], ed25519SecretKeyBuffer / ed25519SecretKey["BYTES_PER_ELEMENT"] + ed25519SecretKey["length"]);
// Free memory
X25519.instance._free(secretKeyBuffer);
X25519.instance._free(ed25519SecretKeyBuffer);
// Return secret key
return secretKey;
}
// Public key from Ed25519 public key
static publicKeyFromEd25519PublicKey(ed25519PublicKey) {
// Check if instance doesn't exist
if(typeof X25519.instance === "undefined")
// Set instance
X25519.instance = x25519();
// Check if instance is invalid
if(X25519.instance === X25519.INVALID)
// Return operation failed
return X25519.OPERATION_FAILED;
// Initialize public key to size of public key
var publicKey = new Uint8Array(X25519.instance._publicKeySize());
// Allocate and fill memory
var publicKeyBuffer = X25519.instance._malloc(publicKey["length"] * publicKey["BYTES_PER_ELEMENT"]);
var ed25519PublicKeyBuffer = X25519.instance._malloc(ed25519PublicKey["length"] * ed25519PublicKey["BYTES_PER_ELEMENT"]);
X25519.instance["HEAPU8"].set(ed25519PublicKey, ed25519PublicKeyBuffer / ed25519PublicKey["BYTES_PER_ELEMENT"]);
// Check if getting public key from Ed25519 public key failed
if(X25519.instance._publicKeyFromEd25519PublicKey(publicKeyBuffer, ed25519PublicKeyBuffer, ed25519PublicKey["length"] * ed25519PublicKey["BYTES_PER_ELEMENT"]) === X25519.C_FALSE) {
// Clear memory
X25519.instance["HEAPU8"].fill(0, publicKeyBuffer / publicKey["BYTES_PER_ELEMENT"], publicKeyBuffer / publicKey["BYTES_PER_ELEMENT"] + publicKey["length"]);
X25519.instance["HEAPU8"].fill(0, ed25519PublicKeyBuffer / ed25519PublicKey["BYTES_PER_ELEMENT"], ed25519PublicKeyBuffer / ed25519PublicKey["BYTES_PER_ELEMENT"] + ed25519PublicKey["length"]);
// Free memory
X25519.instance._free(publicKeyBuffer);
X25519.instance._free(ed25519PublicKeyBuffer);
// Return operation failed
return X25519.OPERATION_FAILED;
}
// Get public key
publicKey = new Uint8Array(X25519.instance["HEAPU8"].subarray(publicKeyBuffer, publicKeyBuffer + publicKey["length"]));
// Clear memory
X25519.instance["HEAPU8"].fill(0, publicKeyBuffer / publicKey["BYTES_PER_ELEMENT"], publicKeyBuffer / publicKey["BYTES_PER_ELEMENT"] + publicKey["length"]);
X25519.instance["HEAPU8"].fill(0, ed25519PublicKeyBuffer / ed25519PublicKey["BYTES_PER_ELEMENT"], ed25519PublicKeyBuffer / ed25519PublicKey["BYTES_PER_ELEMENT"] + ed25519PublicKey["length"]);
// Free memory
X25519.instance._free(publicKeyBuffer);
X25519.instance._free(ed25519PublicKeyBuffer);
// Return public key
return publicKey;
}
// Shared secret key from secret key and public key
static sharedSecretKeyFromSecretKeyAndPublicKey(secretKey, publicKey) {
// Check if instance doesn't exist
if(typeof X25519.instance === "undefined")
// Set instance
X25519.instance = x25519();
// Check if instance is invalid
if(X25519.instance === X25519.INVALID)
// Return operation failed
return X25519.OPERATION_FAILED;
// Initialize shared secret key to size of shared secret key
var sharedSecretKey = new Uint8Array(X25519.instance._sharedSecretKeySize());
// Allocate and fill memory
var sharedSecretKeyBuffer = X25519.instance._malloc(sharedSecretKey["length"] * sharedSecretKey["BYTES_PER_ELEMENT"]);
var secretKeyBuffer = X25519.instance._malloc(secretKey["length"] * secretKey["BYTES_PER_ELEMENT"]);
X25519.instance["HEAPU8"].set(secretKey, secretKeyBuffer / secretKey["BYTES_PER_ELEMENT"]);
var publicKeyBuffer = X25519.instance._malloc(publicKey["length"] * publicKey["BYTES_PER_ELEMENT"]);
X25519.instance["HEAPU8"].set(publicKey, publicKeyBuffer / publicKey["BYTES_PER_ELEMENT"]);
// Check if getting shared secret key from secret key and public key failed
if(X25519.instance._sharedSecretKeyFromSecretKeyAndPublicKey(sharedSecretKeyBuffer, secretKeyBuffer, secretKey["length"] * secretKey["BYTES_PER_ELEMENT"], publicKeyBuffer, publicKey["length"] * publicKey["BYTES_PER_ELEMENT"]) === X25519.C_FALSE) {
// Clear memory
X25519.instance["HEAPU8"].fill(0, sharedSecretKeyBuffer / sharedSecretKey["BYTES_PER_ELEMENT"], sharedSecretKeyBuffer / sharedSecretKey["BYTES_PER_ELEMENT"] + sharedSecretKey["length"]);
X25519.instance["HEAPU8"].fill(0, secretKeyBuffer / secretKey["BYTES_PER_ELEMENT"], secretKeyBuffer / secretKey["BYTES_PER_ELEMENT"] + secretKey["length"]);
X25519.instance["HEAPU8"].fill(0, publicKeyBuffer / publicKey["BYTES_PER_ELEMENT"], publicKeyBuffer / publicKey["BYTES_PER_ELEMENT"] + publicKey["length"]);
// Free memory
X25519.instance._free(sharedSecretKeyBuffer);
X25519.instance._free(secretKeyBuffer);
X25519.instance._free(publicKeyBuffer);
// Return operation failed
return X25519.OPERATION_FAILED;
}
// Get shared secret key
sharedSecretKey = new Uint8Array(X25519.instance["HEAPU8"].subarray(sharedSecretKeyBuffer, sharedSecretKeyBuffer + sharedSecretKey["length"]));
// Clear memory
X25519.instance["HEAPU8"].fill(0, sharedSecretKeyBuffer / sharedSecretKey["BYTES_PER_ELEMENT"], sharedSecretKeyBuffer / sharedSecretKey["BYTES_PER_ELEMENT"] + sharedSecretKey["length"]);
X25519.instance["HEAPU8"].fill(0, secretKeyBuffer / secretKey["BYTES_PER_ELEMENT"], secretKeyBuffer / secretKey["BYTES_PER_ELEMENT"] + secretKey["length"]);
X25519.instance["HEAPU8"].fill(0, publicKeyBuffer / publicKey["BYTES_PER_ELEMENT"], publicKeyBuffer / publicKey["BYTES_PER_ELEMENT"] + publicKey["length"]);
// Free memory
X25519.instance._free(sharedSecretKeyBuffer);
X25519.instance._free(secretKeyBuffer);
X25519.instance._free(publicKeyBuffer);
// Return shared secret key
return sharedSecretKey;
}
// Operation failed
static get OPERATION_FAILED() {
// Return operation failed
return null;
}
// Private
// Invalid
static get INVALID() {
// Return invalid
return null;
}
// C false
static get C_FALSE() {
// Return C false
return 0;
}
}
// Supporting fuction implementation
// Check if document doesn't exist
if(typeof document === "undefined") {
// Create document
var document = {};
}
// Check if module exports exists
if(typeof module === "object" && module !== null && "exports" in module === true) {
// Exports
module["exports"] = X25519;
}

BIN
scripts/X25519-0.0.23.wasm Executable file

Binary file not shown.

523
scripts/about_section.js Executable file
View File

@@ -0,0 +1,523 @@
// Use strict
"use strict";
// Classes
// About section class
class AboutSection extends Section {
// Public
// Constructor
constructor(display, sections, settings, message, focus, application, unlocked, automaticLock, scroll, wallets, node, wakeLock, transactions, prices, clipboard) {
// Delegate constructor
super(display, sections, settings, message, focus, application, unlocked, automaticLock, scroll, wallets, node, wakeLock, transactions, prices, clipboard);
// Add version information
this.addVersionInformation();
// Add donate information
this.addDonateInformation();
// Update copyright
this.updateCopyright();
// Add disclaimer
this.addDisclaimer();
// Add translation contribution message
this.addTranslationContributionMessage();
// Add attributions
this.addAttributions();
// Set self
var self = this;
// Donate address copy click and touch end event
this.getDisplay().find("div.donate span.copy").on("click touchend", function(event) {
// Check if event is touch end
if("type" in event["originalEvent"] === true && event["originalEvent"]["type"] === "touchend") {
// Check if address copy isn't under the touch area
var changedTouch = event["originalEvent"]["changedTouches"][0];
if(this !== document.elementFromPoint(changedTouch["clientX"], changedTouch["clientY"])) {
// Return
return;
}
}
// Stop propagation
event.stopPropagation();
// Prevent showing messages
self.getMessage().prevent();
// Blur focus
$(":focus").blur();
// Disable unlocked
self.getUnlocked().disable();
// Get copy button
var copyButton = $(this);
// Show loading
self.getApplication().showLoading();
// Set that copy button is clicked
copyButton.addClass("clicked");
// Set timeout
setTimeout(function() {
// Blur copy button
copyButton.blur();
}, 0);
// Set timeout
setTimeout(function() {
// Get address
var address = copyButton.prev().text();
// Copy address to clipboard
self.getClipboard().copy(address).then(function() {
// Show message and allow showing messages
self.getMessage().show(Language.getDefaultTranslation('Address Copied'), Message.createText(Language.getDefaultTranslation('The address was successfully copied to your clipboard.')) + Message.createText(Language.getDefaultTranslation('(?<=.) ')) + Message.createText(Language.getDefaultTranslation('Verify that the pasted address matches the following address when you paste it.')) + Message.createLineBreak() + Message.createLineBreak() + "<span class=\"messageContainer\"><span class=\"message contextMenu rawData\">" + Common.htmlEncode(address) + "</span>" + Language.createTranslatableContainer("<span>", Language.getDefaultTranslation('Copy'), [], "copy", true) + "</span>" + Message.createLineBreak(), false, function() {
// Hide loading
self.getApplication().hideLoading();
}, Language.getDefaultTranslation('OK'), Message.NO_BUTTON, true, Message.VISIBLE_STATE_UNLOCKED).then(function(messageResult) {
// Check if message was displayed
if(messageResult !== Message.NOT_DISPLAYED_RESULT) {
// Enable unlocked
self.getUnlocked().enable();
// Set that copy button isn't clicked
copyButton.removeClass("clicked");
// Hide message
self.getMessage().hide();
}
});
// Catch errors
}).catch(function(error) {
// Show message and allow showing messages
self.getMessage().show(Language.getDefaultTranslation('Copy Address Error'), Message.createText(Language.getDefaultTranslation('Copying the address to your clipboard failed.')), false, function() {
// Hide loading
self.getApplication().hideLoading();
}, Language.getDefaultTranslation('OK'), Message.NO_BUTTON, true, Message.VISIBLE_STATE_UNLOCKED).then(function(messageResult) {
// Check if message was displayed
if(messageResult !== Message.NOT_DISPLAYED_RESULT) {
// Enable unlocked
self.getUnlocked().enable();
// Set that copy button isn't clicked
copyButton.removeClass("clicked");
// Hide message
self.getMessage().hide();
}
});
});
}, ("type" in event["originalEvent"] === true && event["originalEvent"]["type"] === "touchend") ? 0 : AboutSection.COPY_ADDRESS_TO_CLIPBOARD_DELAY_MILLISECONDS);
});
}
// Get name
getName() {
// Return name
return AboutSection.NAME;
}
// Reset
reset() {
// Reset
super.reset();
}
// Name
static get NAME() {
// Return name
return "About";
}
// Private
// Initialize
initialize(state) {
// Set base class initialize
var baseClassInitialize = super.initialize(state);
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Return initializing base class
return baseClassInitialize.then(function() {
// Resolve
resolve();
// Reject error
}).catch(function(error) {
// Reject error
reject(error);
});
});
}
// Get initialize error header
getInitializeErrorHeader() {
// Return initialize error header
return Language.getDefaultTranslation('About Error');
}
// Add version information
addVersionInformation() {
// Get version information display
var versionInformationDisplay = this.getDisplay().find("div.versionInformation");
// Get version release timestamp
var versionReleaseTimestamp = Date.parse(VERSION_RELEASE_DATE) / Common.MILLISECONDS_IN_A_SECOND;
// Add version number to version information display
versionInformationDisplay.append("<p>" + Language.createTranslatableContainer("<span>", Language.getDefaultTranslation('Version number:')) + Language.createTranslatableContainer("<span>", Language.getDefaultTranslation('(?<=:) ')) + Language.createTranslatableContainer("<span>", "%1$v", [VERSION_NUMBER], "contextMenu") + "</p>");
// Add release date to version information display
versionInformationDisplay.append("<p>" + Language.createTranslatableContainer("<span>", Language.getDefaultTranslation('Release date:')) + Language.createTranslatableContainer("<span>", Language.getDefaultTranslation('(?<=:) ')) + Language.createTranslatableContainer("<span>", "%1$d", [versionReleaseTimestamp.toFixed()], "contextMenu") + "</p>");
// Check if is an extension
if(Common.isExtension() === true) {
// Set source code
var sourceCode = "https://github.com/NicolasFlamel1/MWC-Wallet-Browser-Extension";
}
// Otherwise check if loading from file
else if(location["protocol"] === Common.FILE_PROTOCOL) {
// Set source code
var sourceCode = "https://github.com/NicolasFlamel1/MWC-Wallet-Standalone";
}
// Otherwise
else {
// Set source code
var sourceCode = "https://github.com/NicolasFlamel1/mwcwallet.com";
}
// Add source code to version information display
versionInformationDisplay.append("<p>" + Language.createTranslatableContainer("<span>", Language.getDefaultTranslation('Source code:')) + Language.createTranslatableContainer("<span>", Language.getDefaultTranslation('(?<=:) ')) + Language.createTranslatableContainer("<span>", "%1$m", [
[
// Text
sourceCode,
// URL
sourceCode,
// Is external
true,
// Is blob
false
]
]) + "</p>");
// Add wallet type to version information display
versionInformationDisplay.append("<p>" + Language.createTranslatableContainer("<span>", Language.getDefaultTranslation('Wallet type:')) + Language.createTranslatableContainer("<span>", Language.getDefaultTranslation('(?<=:) ')) + Language.createTranslatableContainer("<span>", "%1$x", [Consensus.walletTypeToText(Consensus.getWalletType())], "contextMenu") + "</p>");
// Add network type to version information display
versionInformationDisplay.append("<p>" + Language.createTranslatableContainer("<span>", Language.getDefaultTranslation('Network type:')) + Language.createTranslatableContainer("<span>", Language.getDefaultTranslation('(?<=:) ')) + Language.createTranslatableContainer("<span>", "%1$x", [Consensus.networkTypeToText(Consensus.getNetworkType())], "contextMenu") + "</p>");
}
// Add donate information
addDonateInformation() {
// Get donate display
var donateDisplay = this.getDisplay().find("div.donate");
// Check if is an extension
if(Common.isExtension() === true) {
// Set message
var message = Language.getDefaultTranslation('Donations are greatly appreciated and help fund the development of this extension.');
}
// Otherwise check if is an app
else if(Common.isApp() === true) {
// Set message
var message = Language.getDefaultTranslation('Donations are greatly appreciated and help fund the development of this app.');
}
// Otherwise
else {
// Set message
var message = Language.getDefaultTranslation('Donations are greatly appreciated and help fund the development of this site.');
}
// Add message to donate display
donateDisplay.prepend(Language.createTranslatableContainer("<p>", message));
}
// Update copyright
updateCopyright() {
// Get current timestamp
var currentTimestamp = new Date();
// Get current year
var currentYear = currentTimestamp.getFullYear();
// Check if the current year is greater than the copyright year
if(currentYear > COPYRIGHT_YEAR) {
// Get new copyright
var newCopyright = Language.createTranslatableContainer("<p>", Language.getDefaultTranslation('© %1$s%2$s Nicolas Flamel.'), [COPYRIGHT_YEAR.toFixed(), currentYear.toFixed()], "copyright");
}
// Otherwise
else {
// Get new copyright
var newCopyright = Language.createTranslatableContainer("<p>", Language.getDefaultTranslation('© %1$s Nicolas Flamel.'), [COPYRIGHT_YEAR.toFixed()], "copyright");
}
// Replace copyright with the new copyright
this.getDisplay().find("p.copyright").replaceWith(newCopyright);
// Get next year timestamp
var nextYearTimestamp = new Date(currentYear + 1, Common.JANUARY_MONTH_INDEX);
// Set self
var self = this;
// Set timeout
setTimeout(function() {
// Update copyright
self.updateCopyright();
}, Math.min(nextYearTimestamp - currentTimestamp, Common.INT32_MAX_VALUE));
}
// Add disclaimer
addDisclaimer() {
// Get disclaimer display
var disclaimerDisplay = this.getDisplay().find("div.disclaimer");
// Check if is an extension
if(Common.isExtension() === true) {
// Set message
var message = Language.getDefaultTranslation('This extension is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with this extension or the use or other dealings in this extension.');
}
// Otherwise check if is an app
else if(Common.isApp() === true) {
// Set message
var message = Language.getDefaultTranslation('This app is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with this app or the use or other dealings in this app.');
}
// Otherwise
else {
// Set message
var message = Language.getDefaultTranslation('This site is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with this site or the use or other dealings in this site.');
}
// Add disclaimer message to disclaimer display
disclaimerDisplay.append(Language.createTranslatableContainer("<p>", message));
}
// Add translation contribution message
addTranslationContributionMessage() {
// Get translation contributors display
var translationContributorsDisplay = this.getDisplay().find("div.translationContributors");
// Check if is an extension
if(Common.isExtension() === true) {
// Set message
var message = Language.getDefaultTranslation('The following people created the translations for this extension. You can email %1$m if you\'re interested in translating this extension into another language.');
}
// Otherwise check if is an app
else if(Common.isApp() === true) {
// Set message
var message = Language.getDefaultTranslation('The following people created the translations for this app. You can email %1$m if you\'re interested in translating this app into another language.');
}
// Otherwise
else {
// Set message
var message = Language.getDefaultTranslation('The following people created the translations for this site. You can email %1$m if you\'re interested in translating this site into another language.');
}
// Add translation contribution message to translation contributors display
translationContributorsDisplay.prepend(Language.createTranslatableContainer("<p>", message, [
[
// Text
"nicolasflamel@mwcwallet.com",
// URL
"mailto:nicolasflamel@mwcwallet.com",
// Is external
true,
// Is blob
false
]
]));
}
// Add attributions
addAttributions() {
// Get attributions display
var attributionsDisplay = this.getDisplay().find("div.attributions");
// Check if is an extension
if(Common.isExtension() === true) {
// Set message
var message = Language.getDefaultTranslation('This extension utilizes code and assets from the following sources.');
}
// Otherwise check if is an app
else if(Common.isApp() === true) {
// Set message
var message = Language.getDefaultTranslation('This app utilizes code and assets from the following sources.');
}
// Otherwise
else {
// Set message
var message = Language.getDefaultTranslation('This site utilizes code and assets from the following sources.');
}
// Add attributions message to attributions display
attributionsDisplay.prepend(Language.createTranslatableContainer("<p>", message));
// Go through all attributions
for(var name in ATTRIBUTIONS) {
if(ATTRIBUTIONS.hasOwnProperty(name) === true) {
// Check if attribution has a license
if("License Type" in ATTRIBUTIONS[name] === true && "License Path" in ATTRIBUTIONS[name] === true) {
// Add attribution to attributions display
attributionsDisplay.find("ul").append("<li>" + Language.createTranslatableContainer("<span>", Language.getDefaultTranslation('%1$y: %2$m, License: %3$m'), [
// Name
name,
[
// Text
ATTRIBUTIONS[name]["URL"],
// URL
ATTRIBUTIONS[name]["URL"],
// Is external
true,
// Is blob
false
],
[
// Text
ATTRIBUTIONS[name]["License Type"],
// URL
ATTRIBUTIONS[name]["License Path"],
// Is external
true,
// Is blob
false
]
], "contextMenu") + "</li>");
}
// Otherwise
else {
// Add attribution to attributions display
attributionsDisplay.find("ul").append("<li>" + Language.createTranslatableContainer("<span>", Language.getDefaultTranslation('%1$y: %2$m'), [
// Name
name,
[
// Text
ATTRIBUTIONS[name]["URL"],
// URL
ATTRIBUTIONS[name]["URL"],
// Is external
true,
// Is blob
false
]
], "contextMenu") + "</li>");
}
}
}
}
// Copy address to clipboard delay milliseconds
static get COPY_ADDRESS_TO_CLIPBOARD_DELAY_MILLISECONDS() {
// Return copy address to clipboard delay milliseconds
return 175;
}
}
// Main function
// Set global object's about section
globalThis["AboutSection"] = AboutSection;

622
scripts/account_section.js Executable file
View File

@@ -0,0 +1,622 @@
// Use strict
"use strict";
// Classes
// Account section class
class AccountSection extends Section {
// Public
// Constructor
constructor(display, sections, settings, message, focus, application, unlocked, automaticLock, scroll, wallets, node, wakeLock, transactions, prices, clipboard) {
// Delegate constructor
super(display, sections, settings, message, focus, application, unlocked, automaticLock, scroll, wallets, node, wakeLock, transactions, prices, clipboard);
// Set self
var self = this;
// Change password button click event
this.getDisplay().find("button.changePassword").on("click", function() {
// Get button
var button = $(this);
// Prevent showing messages
self.getMessage().prevent();
// Save focus, blur, and get focused element
var focusedElement = self.getFocus().save(true);
// Check if focused element is the button
if(focusedElement !== Focus.NO_FOCUS && focusedElement.is(button) === true) {
// Set that button is clicked
button.addClass("clicked");
}
// Disable unlocked
self.getUnlocked().disable();
// Show loading
self.getApplication().showLoading();
// Set that button is loading
button.addClass("loading");
// Get current password
var currentPassword = self.getDisplay().find("input.currentPassword").val();
// Get new password
var newPassword = self.getDisplay().find("input.newPassword").val();
// Get confirm new password
var confirmNewPassword = self.getDisplay().find("input.confirmNewPassword").val();
// Show change password error
var showChangePasswordError = function(error) {
// TODO Securely clear the currentPassword, newPassword, and confirmNewPassword
// Show message and allow showing messages
self.getMessage().show(Language.getDefaultTranslation('Change Password Error'), Message.createText(error), false, function() {
// Hide loading
self.getApplication().hideLoading();
}, Language.getDefaultTranslation('OK'), Message.NO_BUTTON, true, Message.VISIBLE_STATE_UNLOCKED).then(function(messageResult) {
// Check if message was displayed
if(messageResult !== Message.NOT_DISPLAYED_RESULT) {
// Set that button isn't loading
button.removeClass("loading");
// Enable unlocked
self.getUnlocked().enable();
// Set that button isn't clicked
button.removeClass("clicked");
// Restore focus and don't blur
self.getFocus().restore(false);
// Hide message
self.getMessage().hide();
}
});
};
// Check if current password is invalid
if(currentPassword["length"] === 0) {
// Show change password error
showChangePasswordError(Language.getDefaultTranslation('Current password is empty.'));
}
// Otherwise check if current password is incorrect
else if(self.getWallets().isPassword(currentPassword) === false) {
// Show change password error
showChangePasswordError(Language.getDefaultTranslation('Current password is incorrect.'));
}
// Otherwise check if new password is invalid
else if(newPassword["length"] === 0) {
// Show change password error
showChangePasswordError(Language.getDefaultTranslation('New password is empty.'));
}
// Otherwise check if confirm new password is invalid
else if(confirmNewPassword["length"] === 0) {
// Show change password error
showChangePasswordError(Language.getDefaultTranslation('Confirm new password is empty.'));
}
// Otherwise check if new passwords don't match match
else if(newPassword !== confirmNewPassword) {
// Show change password error
showChangePasswordError(Language.getDefaultTranslation('New passwords don\'t match.'));
}
// Otherwise
else {
// Prevent automatic lock
self.getAutomaticLock().prevent();
// Set timeout
setTimeout(function() {
// Change password
self.getWallets().changePassword(currentPassword, newPassword).then(function() {
// Log message
Log.logMessage(Language.getDefaultTranslation('Changed password.'));
// TODO Securely clear the currentPassword, newPassword, and confirmNewPassword
// Allow automatic lock
self.getAutomaticLock().allow();
// Check if automatic lock isn't locking
if(self.getAutomaticLock().isLocking() === false) {
// Show message and allow showing messages
self.getMessage().show(Language.getDefaultTranslation('Password Changed'), Message.createText(Language.getDefaultTranslation('Your password was successfully changed.')), false, function() {
// Hide loading
self.getApplication().hideLoading();
}, Language.getDefaultTranslation('OK'), Message.NO_BUTTON, true, Message.VISIBLE_STATE_UNLOCKED).then(function(messageResult) {
// Check if message was displayed
if(messageResult !== Message.NOT_DISPLAYED_RESULT) {
// Clear current password, new password, and confirm new password values
self.getDisplay().find("input.currentPassword, input.newPassword, input.confirmNewPassword").val("").closest("div").parent().closest("div").removeClass("error");
// Set that button isn't loading
button.removeClass("loading");
// Enable unlocked
self.getUnlocked().enable();
// Set that button isn't clicked
button.removeClass("clicked");
// Delete focus
self.getFocus().delete();
// Hide message
self.getMessage().hide();
}
// Otherwise
else {
// Clear current password, new password, and confirm new password values
self.getDisplay().find("input.currentPassword, input.newPassword, input.confirmNewPassword").val("").closest("div").parent().closest("div").removeClass("error");
}
});
}
// Otherwise
else {
// Clear current password, new password, and confirm new password values
self.getDisplay().find("input.currentPassword, input.newPassword, input.confirmNewPassword").val("").closest("div").parent().closest("div").removeClass("error");
// Update state and catch errors
self.updateState().catch(function(error) {
});
}
// Catch errors
}).catch(function(error) {
// Allow automatic lock
self.getAutomaticLock().allow();
// Check if automatic lock isn't locking
if(self.getAutomaticLock().isLocking() === false) {
// Show change password error
showChangePasswordError(error);
}
});
}, AccountSection.CHANGE_PASSWORD_DELAY_MILLISECONDS);
}
});
// Current password, new password, or confirm new password key down event
this.getDisplay().find("input.currentPassword, input.newPassword, input.confirmNewPassword").on("keydown", function(event) {
// Check if enter was pressed
if(event["which"] === "\r".charCodeAt(0)) {
// Get input
var input = $(this);
// Get input's display
var display = input.closest("div").parent().closest("div");
// Check if display doesn't show an error
if(display.hasClass("error") === false) {
// Trigger click on change password button
self.getDisplay().find("button.changePassword").trigger("click");
}
}
// Current password, new password, or confirm new password input event
}).on("input", function() {
// Get input
var input = $(this);
// Check if input has focus
if(input.is(":focus") === true) {
// Get input's display
var display = input.closest("div").parent().closest("div");
// Get input's value
var value = input.val();
// Check if value doesn't exist
if(value["length"] === 0) {
// Set that display shows an error
display.addClass("error");
// Return
return;
}
// Check if input is current password
if(input.hasClass("currentPassword") === true) {
// Check if value isn't the current password
if(self.getWallets().isPassword(value) === false) {
// Set that display shows an error
display.addClass("error");
// Return
return;
}
}
// Otherwise check if input is the new password
else if(input.hasClass("newPassword") === true) {
// Check if value isn't the confirm new password
if(value === self.getDisplay().find("input.confirmNewPassword").val()) {
// Set that confirm new password's display doesn't show an error
self.getDisplay().find("input.confirmNewPassword").closest("div").parent().closest("div").removeClass("error");
}
// Otherwise check if confirm new password exists
else if(self.getDisplay().find("input.confirmNewPassword").val()["length"] !== 0) {
// Set that confirm new password's display doesn't shows an error
self.getDisplay().find("input.confirmNewPassword").closest("div").parent().closest("div").addClass("error");
}
}
// Otherwise check if input is the confirm new password
else if(input.hasClass("confirmNewPassword") === true) {
// Check if value isn't the new password
if(value !== self.getDisplay().find("input.newPassword").val()) {
// Set that display shows an error
display.addClass("error");
// Return
return;
}
}
// Set that display doesn't shows an error
display.removeClass("error");
}
// Current password, new password, or confirm new password focus event
}).on("focus", function() {
// Get input
var input = $(this);
// Get input's display
var display = input.closest("div").parent().closest("div");
// Check if display isn't disabled
if(display.hasClass("disabled") === false) {
// Trigger input event
input.trigger("input");
}
// Current password, new password, or confirm new password blur event
}).on("blur", function() {
// Check if automatic lock isn't locking
if(self.getAutomaticLock().isLocking() === false) {
// Get input
var input = $(this);
// Get input's display
var display = input.closest("div").parent().closest("div");
// Check if value is empty
if(input.val()["length"] === 0) {
// Set that display doesn't shows an error
display.removeClass("error");
}
}
});
// Show click event
this.getDisplay().find("span.show").on("click", function(event) {
// Get target
var target = $(this);
// Get input
var input = target.siblings("input");
// Check if input isn't disabled
if(input.is(":disabled") === false) {
// Save input selection
var savedSelectionStart = input.get(0)["selectionStart"];
var savedSelectionEnd = input.get(0)["selectionEnd"];
var savedSelectionDirection = input.get(0)["selectionDirection"];
// Check if concealing password
if(target.hasClass("conceal") === true) {
// Set title
var title = Language.getDefaultTranslation('Show');
// Show reveal icon and set title
target.removeClass("conceal").attr(Common.DATA_ATTRIBUTE_PREFIX + "text", title).attr("title", Language.getTranslation(title));
// Change password input type
input.attr("type", "password");
}
// Otherwise
else {
// Set title
var title = Language.getDefaultTranslation('Hide');
// Show conceal icon and set title
target.addClass("conceal").attr(Common.DATA_ATTRIBUTE_PREFIX + "text", title).attr("title", Language.getTranslation(title));
// Change password input type
input.attr("type", "text");
}
// Request animation frame
requestAnimationFrame(function() {
// Save focus and don't blur
self.getFocus().save(false);
// Restore input selection
input.get(0).setSelectionRange(savedSelectionStart, savedSelectionEnd, savedSelectionDirection);
// Restore focus and blur if it doesn't exist
self.getFocus().restore(true);
});
}
// Show mouse down event
}).on("mousedown", function(event) {
// Get target
var target = $(this);
// Check if target's input has focus
if(target.siblings("input").is(":focus") === true) {
// Prevent stealing focus
event.preventDefault();
// Trigger focus change event
target.trigger(Common.FOCUS_CHANGE_EVENT);
}
});
// Delete all wallets button click event
this.getDisplay().find("button.deleteAllWallets").on("click", function() {
// Get button
var button = $(this);
// Set that button is clicked
button.addClass("clicked");
// Show message
self.getMessage().show(Language.getDefaultTranslation('Delete All Wallets'), Message.createText(Language.getDefaultTranslation('Are you sure you want to delete all your wallets?')) + Message.createLineBreak() + "<b>" + Message.createText(Language.getDefaultTranslation('Each wallet can only be recovered by using its passphrase or hardware wallet once it\'s been deleted.')) + "</b>", false, function() {
// Save focus and blur
self.getFocus().save(true);
// Disable unlocked
self.getUnlocked().disable();
}, Language.getDefaultTranslation('No'), Language.getDefaultTranslation('Yes'), false, Message.VISIBLE_STATE_UNLOCKED, true).then(function(messageResult) {
// Check if message was displayed
if(messageResult !== Message.NOT_DISPLAYED_RESULT) {
// Check if deleting all wallets
if(messageResult === Message.SECOND_BUTTON_CLICKED_RESULT) {
// Prevent showing messages
self.getMessage().prevent();
// Show loading
self.getApplication().showLoading();
// Set that message second button is loading
self.getMessage().setButtonLoading(Message.SECOND_BUTTON);
// Prevent automatic lock
self.getAutomaticLock().prevent();
// Set timeout
setTimeout(function() {
// Remove all wallets
self.getWallets().removeAllWallets().then(function() {
// Set that button isn't clicked
button.removeClass("clicked");
// Delete focus
self.getFocus().delete();
// Show create display
self.getApplication().showCreateDisplay();
// Catch errors
}).catch(function(error) {
// Allow automatic lock
self.getAutomaticLock().allow();
// Check if automatic lock isn't locking
if(self.getAutomaticLock().isLocking() === false) {
// Show message and allow showing messages
self.getMessage().show(Language.getDefaultTranslation('Delete All Wallets Error'), Message.createText(error), true, function() {
// Hide loading
self.getApplication().hideLoading();
}, Language.getDefaultTranslation('OK'), Message.NO_BUTTON, true, Message.VISIBLE_STATE_UNLOCKED).then(function(messageResult) {
// Check if message was displayed
if(messageResult !== Message.NOT_DISPLAYED_RESULT) {
// Enable unlocked
self.getUnlocked().enable();
// Set that button isn't clicked
button.removeClass("clicked");
// Restore focus and don't blur
self.getFocus().restore(false);
// Hide message
self.getMessage().hide();
}
});
}
});
}, Application.DELETE_ALL_WALLETS_DELAY_MILLISECONDS);
}
// Otherwise
else {
// Enable unlocked
self.getUnlocked().enable();
// Set that button isn't clicked
button.removeClass("clicked");
// Restore focus and don't blur
self.getFocus().restore(false);
// Hide message
self.getMessage().hide();
}
}
});
});
}
// Get name
getName() {
// Return name
return AccountSection.NAME;
}
// Reset
reset() {
// Reset
super.reset();
// Clear change password's current password, new password, and confirm new password an set their type to password and make them not showing errors
this.getDisplay().find("input.currentPassword, input.newPassword, input.confirmNewPassword").val("").attr("type", "password").closest("div").parent().closest("div").removeClass("error");
// Set that buttons aren't clicked or loading
this.getDisplay().find("button").removeClass("clicked loading");
}
// Name
static get NAME() {
// Return name
return "Account";
}
// Private
// Initialize
initialize(state) {
// Set base class initialize
var baseClassInitialize = super.initialize(state);
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Return initializing base class
return baseClassInitialize.then(function() {
// Set title
var title = Language.getDefaultTranslation('Show');
// Show current password show icon, set its title, and change password input type
self.getDisplay().find("input.currentPassword").siblings("span.show").removeClass("conceal").attr(Common.DATA_ATTRIBUTE_PREFIX + "text", title).attr("title", Language.getTranslation(title)).siblings("input").attr("type", "password");
// Show new password show icon, set its title, and change password input type
self.getDisplay().find("input.newPassword").siblings("span.show").removeClass("conceal").attr(Common.DATA_ATTRIBUTE_PREFIX + "text", title).attr("title", Language.getTranslation(title)).siblings("input").attr("type", "password");
// Show confirm new password show icon, set its title, and change password input type
self.getDisplay().find("input.confirmNewPassword").siblings("span.show").removeClass("conceal").attr(Common.DATA_ATTRIBUTE_PREFIX + "text", title).attr("title", Language.getTranslation(title)).siblings("input").attr("type", "password");
// Resolve
resolve();
// Reject error
}).catch(function(error) {
// Reject error
reject(error);
});
});
}
// Get initialize error header
getInitializeErrorHeader() {
// Return initialize error header
return Language.getDefaultTranslation('Account Error');
}
// Change password delay milliseconds
static get CHANGE_PASSWORD_DELAY_MILLISECONDS() {
// Return change password delay milliseconds
return 300;
}
}
// Main function
// Set global object's account section
globalThis["AccountSection"] = AccountSection;

17297
scripts/api.js Executable file

File diff suppressed because it is too large Load Diff

7566
scripts/application.js Executable file

File diff suppressed because it is too large Load Diff

539
scripts/automatic_lock.js Executable file
View File

@@ -0,0 +1,539 @@
// Use strict
"use strict";
// Classes
// Automatic lock class
class AutomaticLock {
// Public
// Constructor
constructor(application, message, settings) {
// Set application
this.application = application;
// Set message
this.message = message;
// Set settings
this.settings = settings;
// Set lock timeout to no timeout
this.lockTimeout = AutomaticLock.NO_TIMEOUT;
// Set allow no interaction lock to false
this.allowNoInteractionLock = false;
// Set allow inactive lock to false
this.allowInactiveLock = false;
// Set locking to false
this.locking = false;
// Set enable automatic lock to setting's default value
this.enableAutomaticLock = AutomaticLock.SETTINGS_ENABLE_AUTOMATIC_LOCK_DEFAULT_VALUE;
// Set no interaction lock timeout minutes to setting's default value
this.noInteractionLockTimeoutMinutes = AutomaticLock.SETTINGS_NO_INTERACTION_LOCK_TIMEOUT_MINUTES_DEFAULT_VALUE;
// Set lock on inactive to setting's default value
this.enableLockOnInactive = AutomaticLock.SETTINGS_ENABLE_LOCK_ON_INACTIVE_DEFAULT_VALUE;
// Update last interaction timestamp
this.updateLastInteractionTimestamp();
// Set self
var self = this;
// Once database is initialized
Database.onceInitialized(function() {
// Return promise
return new Promise(function(resolve, reject) {
// Return creating settings
return Promise.all([
// Create enable automatic lock setting
self.settings.createValue(AutomaticLock.SETTINGS_ENABLE_AUTOMATIC_LOCK_NAME, AutomaticLock.SETTINGS_ENABLE_AUTOMATIC_LOCK_DEFAULT_VALUE),
// Create no interaction lock timeout minutes setting
self.settings.createValue(AutomaticLock.SETTINGS_NO_INTERACTION_LOCK_TIMEOUT_MINUTES_NAME, AutomaticLock.SETTINGS_NO_INTERACTION_LOCK_TIMEOUT_MINUTES_DEFAULT_VALUE),
// Create enable lock on inactive setting
self.settings.createValue(AutomaticLock.SETTINGS_ENABLE_LOCK_ON_INACTIVE_NAME, AutomaticLock.SETTINGS_ENABLE_LOCK_ON_INACTIVE_DEFAULT_VALUE)
]).then(function() {
// Initialize settings
var settings = [
// Enable automatic lock setting
AutomaticLock.SETTINGS_ENABLE_AUTOMATIC_LOCK_NAME,
// No interaction lock timeout minutes setting
AutomaticLock.SETTINGS_NO_INTERACTION_LOCK_TIMEOUT_MINUTES_NAME,
// Enable lock on inactive setting
AutomaticLock.SETTINGS_ENABLE_LOCK_ON_INACTIVE_NAME
];
// Return getting settings' values
return Promise.all(settings.map(function(setting) {
// Return getting setting's value
return self.settings.getValue(setting);
})).then(function(settingValues) {
// Set enable automatic lock to setting's value
self.enableAutomaticLock = settingValues[settings.indexOf(AutomaticLock.SETTINGS_ENABLE_AUTOMATIC_LOCK_NAME)];
// Set no interaction lock timeout minutes to setting's value
self.noInteractionLockTimeoutMinutes = settingValues[settings.indexOf(AutomaticLock.SETTINGS_NO_INTERACTION_LOCK_TIMEOUT_MINUTES_NAME)];
// Set enable lock on inactive to setting's value
self.enableLockOnInactive = settingValues[settings.indexOf(AutomaticLock.SETTINGS_ENABLE_LOCK_ON_INACTIVE_NAME)];
// Update last interaction timestamp
self.updateLastInteractionTimestamp();
// Resolve
resolve();
// Catch errors
}).catch(function(error) {
// Reject
reject();
});
// Catch errors
}).catch(function(error) {
// Reject
reject();
});
});
});
// Settings change event
$(this.settings).on(Settings.CHANGE_EVENT, function(event, setting) {
// Check what setting was changes
switch(setting[Settings.DATABASE_SETTING_NAME]) {
// Enable automatic lock setting
case AutomaticLock.SETTINGS_ENABLE_AUTOMATIC_LOCK_NAME:
// Set enable automatic lock to setting's value
self.enableAutomaticLock = setting[Settings.DATABASE_VALUE_NAME];
// Update last interaction timestamp
self.updateLastInteractionTimestamp();
// Break
break;
// No interaction lock timeout minutes setting
case AutomaticLock.SETTINGS_NO_INTERACTION_LOCK_TIMEOUT_MINUTES_NAME:
// Set no interaction lock timeout minutes to setting's value
self.noInteractionLockTimeoutMinutes = setting[Settings.DATABASE_VALUE_NAME];
// Update last interaction timestamp
self.updateLastInteractionTimestamp();
// Break
break;
// Enable lock on inactive setting
case AutomaticLock.SETTINGS_ENABLE_LOCK_ON_INACTIVE_NAME:
// Set enable lock on inactive to setting's value
self.enableLockOnInactive = setting[Settings.DATABASE_VALUE_NAME];
// Break
break;
}
});
// Window blur event
$(window).on("blur", function() {
// Update last interaction timestamp
self.updateLastInteractionTimestamp();
// Check if lock on inactive is enabled and allowed
if(self.enableLockOnInactive === true && self.allowInactiveLock === true) {
// Reset lock timeout
self.resetLockTimeout();
// Check if application's unlocked display is shown
if(self.application.isUnlockedDisplayShown() === true) {
// Log message
Log.logMessage(Language.getDefaultTranslation('Inactive lock activated.'));
}
// Lock
self.lock();
}
// Window focus event
}).on("focus", function() {
// Check if no interaction lock timeout minutes exist
if(self.noInteractionLockTimeoutMinutes !== AutomaticLock.NO_NO_INTERACTION_LOCK_TIMEOUT_MINUTES) {
// Check if application hasn't been interacted with in too long
if(self.lastInteractionTimestamp <= Common.getCurrentTimestamp() - self.noInteractionLockTimeoutMinutes * Common.SECONDS_IN_A_MINUTE) {
// Reset lock timeout
self.resetLockTimeout();
// Check if automatic lock is enabled and allowed
if(self.enableAutomaticLock === true && self.allowNoInteractionLock === true) {
// Check if application's unlocked display is shown
if(self.application.isUnlockedDisplayShown() === true) {
// Log message
Log.logMessage(Language.getDefaultTranslation('Automatic lock activated.'));
}
// Lock
self.lock();
}
}
}
// Update last interaction timestamp
self.updateLastInteractionTimestamp();
// Window page hide event
}).on("pagehide", function() {
// Check if lock on inactive is enabled and allowed
if(self.enableLockOnInactive === true && self.allowInactiveLock === true) {
// Reset lock timeout
self.resetLockTimeout();
// Check if application's unlocked display is shown
if(self.application.isUnlockedDisplayShown() === true) {
// Log message
Log.logMessage(Language.getDefaultTranslation('Inactive lock activated.'));
}
// Lock
self.lock();
}
});
// Document mouse move, mouse down, mouse up, key down, key up, touch start, touch move, touch end, and focus change event
$(document).on("mousemove mousedown mouseup keydown keyup touchstart touchmove touchend" + Common.FOCUS_CHANGE_EVENT, function(event) {
// Check if has focus
if(document.hasFocus() === true)
// Update last interaction timestamp
self.updateLastInteractionTimestamp();
// Document visibility change event
}).on("visibilitychange", function() {
// Check if page is hidden
if(document["visibilityState"] === Common.VISIBILITY_STATE_HIDDEN) {
// Check if lock on inactive is enabled and allowed
if(self.enableLockOnInactive === true && self.allowInactiveLock === true) {
// Reset lock timeout
self.resetLockTimeout();
// Check if application's unlocked display is shown
if(self.application.isUnlockedDisplayShown() === true) {
// Log message
Log.logMessage(Language.getDefaultTranslation('Inactive lock activated.'));
}
// Lock
self.lock();
}
}
});
}
// Allow
allow(lockType = AutomaticLock.NO_INTERACTION_LOCK_TYPE | AutomaticLock.INACTIVE_LOCK_TYPE) {
// Check if allowing the no interaction lock
if((lockType & AutomaticLock.NO_INTERACTION_LOCK_TYPE) !== 0)
// Set allow no interaction lock
this.allowNoInteractionLock = true;
// Check if allowing the inactive lock
if((lockType & AutomaticLock.INACTIVE_LOCK_TYPE) !== 0)
// Set allow inactive lock
this.allowInactiveLock = true;
// Check if no interaction lock timeout minutes exist
if(this.noInteractionLockTimeoutMinutes !== AutomaticLock.NO_NO_INTERACTION_LOCK_TIMEOUT_MINUTES) {
// Check if application hasn't been interacted with in too long
if(this.lastInteractionTimestamp <= Common.getCurrentTimestamp() - this.noInteractionLockTimeoutMinutes * Common.SECONDS_IN_A_MINUTE) {
// Reset lock timeout
this.resetLockTimeout();
// Check if automatic lock is enabled and allowed
if(this.enableAutomaticLock === true && this.allowNoInteractionLock === true) {
// Check if application's unlocked display is shown
if(this.application.isUnlockedDisplayShown() === true) {
// Log message
Log.logMessage(Language.getDefaultTranslation('Automatic lock activated.'));
}
// Lock
this.lock();
}
}
}
// Check if lock on inactive is enabled and allowed and the document doesn't have focus or is hidden
if(this.enableLockOnInactive === true && this.allowInactiveLock === true && (document.hasFocus() === false || document["visibilityState"] === Common.VISIBILITY_STATE_HIDDEN)) {
// Reset lock timeout
this.resetLockTimeout();
// Check if application's unlocked display is shown
if(this.application.isUnlockedDisplayShown() === true) {
// Log message
Log.logMessage(Language.getDefaultTranslation('Inactive lock activated.'));
}
// Lock
this.lock();
}
}
// Get allowed
getAllowed() {
// Initialize result
var result = 0;
// Check if allow no interaction lock
if(this.allowNoInteractionLock === true) {
// Set no interaction lock type in the result
result |= AutomaticLock.NO_INTERACTION_LOCK_TYPE;
}
// Check if allow inactive lock
if(this.allowInactiveLock === true) {
// Set inactive lock type in the result
result |= AutomaticLock.INACTIVE_LOCK_TYPE;
}
// Return result
return result;
}
// Prevent
prevent(lockType = AutomaticLock.NO_INTERACTION_LOCK_TYPE | AutomaticLock.INACTIVE_LOCK_TYPE) {
// Check if preventing the no interaction lock
if((lockType & AutomaticLock.NO_INTERACTION_LOCK_TYPE) !== 0)
// Clear allow no interaction lock
this.allowNoInteractionLock = false;
// Check if preventing the inactive lock
if((lockType & AutomaticLock.INACTIVE_LOCK_TYPE) !== 0)
// Clear allow inactive lock
this.allowInactiveLock = false;
}
// Is locking
isLocking() {
// Return if locking
return this.locking === true;
}
// No interaction lock type
static get NO_INTERACTION_LOCK_TYPE() {
// Return no interaction lock type
return 1 << 0;
}
// Inactive lock type
static get INACTIVE_LOCK_TYPE() {
// Return inactive lock type
return 1 << 1;
}
// Private
// Update last interaction timestamp
updateLastInteractionTimestamp() {
// Set last interaction timestamp to current timestamp
this.lastInteractionTimestamp = Common.getCurrentTimestamp();
// Reset lock timeout
this.resetLockTimeout();
}
// Reset lock timeout
resetLockTimeout() {
// Check if lock timeout exists
if(this.lockTimeout !== AutomaticLock.NO_TIMEOUT) {
// Clear lock timeout
clearTimeout(this.lockTimeout);
// Set lock timeout to no timeout
this.lockTimeout = AutomaticLock.NO_TIMEOUT;
}
// Check if no interaction lock timeout minutes exist
if(this.noInteractionLockTimeoutMinutes !== AutomaticLock.NO_NO_INTERACTION_LOCK_TIMEOUT_MINUTES) {
// Set self
var self = this;
// Set lock timeout
this.lockTimeout = setTimeout(function() {
// Reset lock timeout
self.resetLockTimeout();
// Check if automatic lock is enabled and allowed
if(self.enableAutomaticLock === true && self.allowNoInteractionLock === true) {
// Check if application's unlocked display is shown
if(self.application.isUnlockedDisplayShown() === true) {
// Log message
Log.logMessage(Language.getDefaultTranslation('Automatic lock activated.'));
}
// Lock
self.lock();
}
}, this.noInteractionLockTimeoutMinutes * Common.SECONDS_IN_A_MINUTE * Common.MILLISECONDS_IN_A_SECOND);
}
}
// Lock
lock() {
// Check if application's unlocked display is shown, not already locking, and not currently showing a minimal display
if(this.application.isUnlockedDisplayShown() === true && this.isLocking() === false && $("div.unlocked").hasClass("minimal") === false) {
// Set locking
this.locking = true;
// Prevent showing messages
this.message.prevent();
// Show loading
this.application.showLoading();
// Show lock display
this.application.showLockDisplay();
// Set self
var self = this;
// Set timeout
setTimeout(function() {
// Clear locking
self.locking = false;
}, 0);
}
}
// No timeout
static get NO_TIMEOUT() {
// Return no timeout
return null;
}
// No no interaction lock timeout minutes
static get NO_NO_INTERACTION_LOCK_TIMEOUT_MINUTES() {
// Return no no interaction lock timeout minutes
return null;
}
// Settings enable automatic lock name
static get SETTINGS_ENABLE_AUTOMATIC_LOCK_NAME() {
// Return settings enable automatic lock name
return "Enable Automatic Lock";
}
// Settings enable automatic lock default value
static get SETTINGS_ENABLE_AUTOMATIC_LOCK_DEFAULT_VALUE() {
// Return settings enable automatic lock default value
return true;
}
// Settings no interaction lock timeout minutes name
static get SETTINGS_NO_INTERACTION_LOCK_TIMEOUT_MINUTES_NAME() {
// Return settings no interaction lock timeout minutes name
return "No Interaction Lock Timeout Minutes";
}
// Settings no interaction lock timeout minutes default value
static get SETTINGS_NO_INTERACTION_LOCK_TIMEOUT_MINUTES_DEFAULT_VALUE() {
// Return settings no interaction lock timeout minutes default value
return 5;
}
// Settings enable lock on inactive name
static get SETTINGS_ENABLE_LOCK_ON_INACTIVE_NAME() {
// Return settings enable lock on inactive name
return "Enable Lock On Inactive";
}
// Settings enable lock on inactive default value
static get SETTINGS_ENABLE_LOCK_ON_INACTIVE_DEFAULT_VALUE() {
// Return settings enable lock on inactive default value
return false;
}
}
// Main function
// Set global object's automatic lock
globalThis["AutomaticLock"] = AutomaticLock;

266
scripts/base58.js Executable file
View File

@@ -0,0 +1,266 @@
// Use strict
"use strict";
// Classes
// Base58 class
class Base58 {
// Public
// Encode
static encode(byteArray) {
// Go through all leading zeros in the byte array
var numberOfLeadingZeros = 0;
while(numberOfLeadingZeros < byteArray["length"] && byteArray[numberOfLeadingZeros] === 0) {
// Increment number of leading zeros
++numberOfLeadingZeros;
}
// Get buffer size
var bufferSize = Math.ceil((byteArray["length"] - numberOfLeadingZeros) * Base58.BYTES_PER_LENGTH_IN_NEW_BASE);
// Create buffer
var buffer = (new Uint8Array(bufferSize)).fill(0);
// Go through all bytes in the byte array after the leading zeros
var length = 0;
for(var i = numberOfLeadingZeros; i < byteArray["length"]; ++i) {
// Get byte
var byte = byteArray[i];
// Go through all base 58 components of the byte
for(var j = 0, k = bufferSize - 1; (byte !== 0 || j < length) && k >= 0; ++j, --k) {
// Include the current buffer value in the byte
byte += (Common.BYTE_MAX_VALUE + 1) * buffer[k];
// Set value in the buffer
buffer[k] = byte % Base58.NUMBER_BASE;
// Update the byte
byte = Math.floor(byte / Base58.NUMBER_BASE);
}
// Update length
length = j;
}
// Go through all leading zeros in the buffer
var bufferIndex = bufferSize - length;
while(bufferIndex < buffer["length"] && buffer[bufferIndex] === 0) {
// Increment buffer index
++bufferIndex;
}
// Set result to start with the number of leading zeros in base58
var result = Base58.CHARACTERS[0].repeat(numberOfLeadingZeros);
// Go through all bytes in the buffer after the leading zeros
for(; bufferIndex < buffer["length"]; ++bufferIndex) {
// Append buffer's value in base58 to the result
result += Base58.CHARACTERS[buffer[bufferIndex]];
}
// Return result
return result;
}
// Encode with checksum
static encodeWithChecksum(byteArray) {
// Get the checksum of the byte array
var checksum = Base58.getChecksum(byteArray);
// Return encoding the byte array with the checksum
return Base58.encode(Common.mergeArrays([
// Byte array
byteArray,
// Checksum
checksum
]));
}
// Decode
static decode(base58String) {
// Go through all leading zeros in base58 in the string
var numberOfLeadingZeros = 0;
while(numberOfLeadingZeros < base58String["length"] && base58String[numberOfLeadingZeros] === Base58.CHARACTERS[0]) {
// Increment number of leading zeros
++numberOfLeadingZeros;
}
// Get buffer size
var bufferSize = Math.ceil((base58String["length"] - numberOfLeadingZeros) * Base58.BYTES_PER_LENGTH_IN_OLD_BASE);
// Crete buffer
var buffer = (new Uint8Array(bufferSize)).fill(0);
// Go through all characters in the string after the leading zeros in base58
var length = 0;
for(var i = numberOfLeadingZeros; i < base58String["length"]; ++i) {
// Get character as byte
var byte = Base58.CHARACTERS.indexOf(base58String[i]);
// Check if byte is invalid
if(byte === Common.INDEX_NOT_FOUND) {
// Throw error
throw "Invalid base58 string.";
}
// Go through all base 58 components of the byte
for(var j = 0, k = bufferSize - 1; (byte !== 0 || j < length) && k >= 0; ++j, --k) {
// Include the current buffer value in the byte
byte += Base58.NUMBER_BASE * buffer[k];
// Set value in the buffer
buffer[k] = byte % (Common.BYTE_MAX_VALUE + 1);
// Update the byte
byte = Math.floor(byte / (Common.BYTE_MAX_VALUE + 1));
}
// Update length
length = j;
}
// Go through all leading zeros in the buffer
var bufferIndex = bufferSize - length;
while(bufferIndex < buffer["length"] && buffer[bufferIndex] === 0) {
// Increment buffer index
++bufferIndex;
}
// Set result to start with the number of leading zeros
var result = (new Uint8Array(numberOfLeadingZeros + bufferSize - bufferIndex)).fill(0);
// Go through all bytes in the buffer after the leading zeros
for(var i = 0; bufferIndex < buffer["length"]; ++i, ++bufferIndex) {
// Append buffer's value to the result
result[i + numberOfLeadingZeros] += buffer[bufferIndex];
}
// Return result
return result;
}
// Decode with checksum
static decodeWithChecksum(base58String) {
// Try
try {
// Decode the string
var byteArray = Base58.decode(base58String);
}
// Catch errors
catch(error) {
// Throw error
throw error;
}
// Check if the byte array doesn't include a checksum
if(byteArray["length"] < Base58.CHECKSUM_LENGTH) {
// Throw error
throw "No checksum exists.";
}
// Otherwise
else {
// Get the checksum of the byte array without its checksum
var checksum = Base58.getChecksum(byteArray.subarray(0, byteArray["length"] - Base58.CHECKSUM_LENGTH));
// Get the provided checksum from the byte array
var providedChecksum = byteArray.subarray(byteArray["length"] - Base58.CHECKSUM_LENGTH);
// Check if checksums don't match
if(Common.arraysAreEqual(checksum, providedChecksum) === false) {
// Throw error
throw "Invalid checksum.";
}
// Otherwise
else {
// Return byte array without the checksum
return byteArray.subarray(0, byteArray["length"] - Base58.CHECKSUM_LENGTH);
}
}
}
// Private
// Get checksum
static getChecksum(byteArray) {
// Get a hash of the hash of the byte array
var hash = new Uint8Array(sha256.arrayBuffer(new Uint8Array(sha256.arrayBuffer(byteArray))));
// Get the checksum from the hash
var checksum = hash.subarray(0, Base58.CHECKSUM_LENGTH);
// Return checksum
return checksum;
}
// Characters
static get CHARACTERS() {
// Return characters
return "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
}
// Number base
static get NUMBER_BASE() {
// Return number base
return 58;
}
// Bytes per length in new base
static get BYTES_PER_LENGTH_IN_NEW_BASE() {
// Return bytes per length in new base
return Math.log(Common.BYTE_MAX_VALUE + 1) / Math.log(Base58.NUMBER_BASE);
}
// Bytes per length in old base
static get BYTES_PER_LENGTH_IN_OLD_BASE() {
// Return bytes per length in old base
return Math.log(Base58.NUMBER_BASE) / Math.log(Common.BYTE_MAX_VALUE + 1);
}
// Checksum length
static get CHECKSUM_LENGTH() {
// Return checksum length
return 4;
}
}
// Main function
// Set global object's base58
globalThis["Base58"] = Base58;

27
scripts/base64.js license.txt Executable file
View File

@@ -0,0 +1,27 @@
Copyright (c) 2014, Dan Kogai
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of {{{project}}} nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

316
scripts/base64.js-3.7.5.js Executable file
View File

@@ -0,0 +1,316 @@
//
// THIS FILE IS AUTOMATICALLY GENERATED! DO NOT EDIT BY HAND!
//
;
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined'
? module.exports = factory()
: typeof define === 'function' && define.amd
? define(factory) :
// cf. https://github.com/dankogai/js-base64/issues/119
(function () {
// existing version for noConflict()
var _Base64 = global.Base64;
var gBase64 = factory();
gBase64.noConflict = function () {
global.Base64 = _Base64;
return gBase64;
};
if (global.Meteor) { // Meteor.js
Base64 = gBase64;
}
global.Base64 = gBase64;
})();
}((typeof self !== 'undefined' ? self
: typeof window !== 'undefined' ? window
: typeof global !== 'undefined' ? global
: this), function () {
'use strict';
/**
* base64.ts
*
* Licensed under the BSD 3-Clause License.
* http://opensource.org/licenses/BSD-3-Clause
*
* References:
* http://en.wikipedia.org/wiki/Base64
*
* @author Dan Kogai (https://github.com/dankogai)
*/
var version = '3.7.5';
/**
* @deprecated use lowercase `version`.
*/
var VERSION = version;
var _hasatob = typeof atob === 'function';
var _hasbtoa = typeof btoa === 'function';
var _hasBuffer = typeof Buffer === 'function';
var _TD = typeof TextDecoder === 'function' ? new TextDecoder() : undefined;
var _TE = typeof TextEncoder === 'function' ? new TextEncoder() : undefined;
var b64ch = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
var b64chs = Array.prototype.slice.call(b64ch);
var b64tab = (function (a) {
var tab = {};
a.forEach(function (c, i) { return tab[c] = i; });
return tab;
})(b64chs);
var b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/;
var _fromCC = String.fromCharCode.bind(String);
var _U8Afrom = typeof Uint8Array.from === 'function'
? Uint8Array.from.bind(Uint8Array)
: function (it) { return new Uint8Array(Array.prototype.slice.call(it, 0)); };
var _mkUriSafe = function (src) { return src
.replace(/=/g, '').replace(/[+\/]/g, function (m0) { return m0 == '+' ? '-' : '_'; }); };
var _tidyB64 = function (s) { return s.replace(/[^A-Za-z0-9\+\/]/g, ''); };
/**
* polyfill version of `btoa`
*/
var btoaPolyfill = function (bin) {
// console.log('polyfilled');
var u32, c0, c1, c2, asc = '';
var pad = bin.length % 3;
for (var i = 0; i < bin.length;) {
if ((c0 = bin.charCodeAt(i++)) > 255 ||
(c1 = bin.charCodeAt(i++)) > 255 ||
(c2 = bin.charCodeAt(i++)) > 255)
throw new TypeError('invalid character found');
u32 = (c0 << 16) | (c1 << 8) | c2;
asc += b64chs[u32 >> 18 & 63]
+ b64chs[u32 >> 12 & 63]
+ b64chs[u32 >> 6 & 63]
+ b64chs[u32 & 63];
}
return pad ? asc.slice(0, pad - 3) + "===".substring(pad) : asc;
};
/**
* does what `window.btoa` of web browsers do.
* @param {String} bin binary string
* @returns {string} Base64-encoded string
*/
var _btoa = _hasbtoa ? function (bin) { return btoa(bin); }
: _hasBuffer ? function (bin) { return Buffer.from(bin, 'binary').toString('base64'); }
: btoaPolyfill;
var _fromUint8Array = _hasBuffer
? function (u8a) { return Buffer.from(u8a).toString('base64'); }
: function (u8a) {
// cf. https://stackoverflow.com/questions/12710001/how-to-convert-uint8-array-to-base64-encoded-string/12713326#12713326
var maxargs = 0x1000;
var strs = [];
for (var i = 0, l = u8a.length; i < l; i += maxargs) {
strs.push(_fromCC.apply(null, u8a.subarray(i, i + maxargs)));
}
return _btoa(strs.join(''));
};
/**
* converts a Uint8Array to a Base64 string.
* @param {boolean} [urlsafe] URL-and-filename-safe a la RFC4648 §5
* @returns {string} Base64 string
*/
var fromUint8Array = function (u8a, urlsafe) {
if (urlsafe === void 0) { urlsafe = false; }
return urlsafe ? _mkUriSafe(_fromUint8Array(u8a)) : _fromUint8Array(u8a);
};
// This trick is found broken https://github.com/dankogai/js-base64/issues/130
// const utob = (src: string) => unescape(encodeURIComponent(src));
// reverting good old fationed regexp
var cb_utob = function (c) {
if (c.length < 2) {
var cc = c.charCodeAt(0);
return cc < 0x80 ? c
: cc < 0x800 ? (_fromCC(0xc0 | (cc >>> 6))
+ _fromCC(0x80 | (cc & 0x3f)))
: (_fromCC(0xe0 | ((cc >>> 12) & 0x0f))
+ _fromCC(0x80 | ((cc >>> 6) & 0x3f))
+ _fromCC(0x80 | (cc & 0x3f)));
}
else {
var cc = 0x10000
+ (c.charCodeAt(0) - 0xD800) * 0x400
+ (c.charCodeAt(1) - 0xDC00);
return (_fromCC(0xf0 | ((cc >>> 18) & 0x07))
+ _fromCC(0x80 | ((cc >>> 12) & 0x3f))
+ _fromCC(0x80 | ((cc >>> 6) & 0x3f))
+ _fromCC(0x80 | (cc & 0x3f)));
}
};
var re_utob = /[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g;
/**
* @deprecated should have been internal use only.
* @param {string} src UTF-8 string
* @returns {string} UTF-16 string
*/
var utob = function (u) { return u.replace(re_utob, cb_utob); };
//
var _encode = _hasBuffer
? function (s) { return Buffer.from(s, 'utf8').toString('base64'); }
: _TE
? function (s) { return _fromUint8Array(_TE.encode(s)); }
: function (s) { return _btoa(utob(s)); };
/**
* converts a UTF-8-encoded string to a Base64 string.
* @param {boolean} [urlsafe] if `true` make the result URL-safe
* @returns {string} Base64 string
*/
var encode = function (src, urlsafe) {
if (urlsafe === void 0) { urlsafe = false; }
return urlsafe
? _mkUriSafe(_encode(src))
: _encode(src);
};
/**
* converts a UTF-8-encoded string to URL-safe Base64 RFC4648 §5.
* @returns {string} Base64 string
*/
var encodeURI = function (src) { return encode(src, true); };
// This trick is found broken https://github.com/dankogai/js-base64/issues/130
// const btou = (src: string) => decodeURIComponent(escape(src));
// reverting good old fationed regexp
var re_btou = /[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g;
var cb_btou = function (cccc) {
switch (cccc.length) {
case 4:
var cp = ((0x07 & cccc.charCodeAt(0)) << 18)
| ((0x3f & cccc.charCodeAt(1)) << 12)
| ((0x3f & cccc.charCodeAt(2)) << 6)
| (0x3f & cccc.charCodeAt(3)), offset = cp - 0x10000;
return (_fromCC((offset >>> 10) + 0xD800)
+ _fromCC((offset & 0x3FF) + 0xDC00));
case 3:
return _fromCC(((0x0f & cccc.charCodeAt(0)) << 12)
| ((0x3f & cccc.charCodeAt(1)) << 6)
| (0x3f & cccc.charCodeAt(2)));
default:
return _fromCC(((0x1f & cccc.charCodeAt(0)) << 6)
| (0x3f & cccc.charCodeAt(1)));
}
};
/**
* @deprecated should have been internal use only.
* @param {string} src UTF-16 string
* @returns {string} UTF-8 string
*/
var btou = function (b) { return b.replace(re_btou, cb_btou); };
/**
* polyfill version of `atob`
*/
var atobPolyfill = function (asc) {
// console.log('polyfilled');
asc = asc.replace(/\s+/g, '');
if (!b64re.test(asc))
throw new TypeError('malformed base64.');
asc += '=='.slice(2 - (asc.length & 3));
var u24, bin = '', r1, r2;
for (var i = 0; i < asc.length;) {
u24 = b64tab[asc.charAt(i++)] << 18
| b64tab[asc.charAt(i++)] << 12
| (r1 = b64tab[asc.charAt(i++)]) << 6
| (r2 = b64tab[asc.charAt(i++)]);
bin += r1 === 64 ? _fromCC(u24 >> 16 & 255)
: r2 === 64 ? _fromCC(u24 >> 16 & 255, u24 >> 8 & 255)
: _fromCC(u24 >> 16 & 255, u24 >> 8 & 255, u24 & 255);
}
return bin;
};
/**
* does what `window.atob` of web browsers do.
* @param {String} asc Base64-encoded string
* @returns {string} binary string
*/
var _atob = _hasatob ? function (asc) { return atob(_tidyB64(asc)); }
: _hasBuffer ? function (asc) { return Buffer.from(asc, 'base64').toString('binary'); }
: atobPolyfill;
//
var _toUint8Array = _hasBuffer
? function (a) { return _U8Afrom(Buffer.from(a, 'base64')); }
: function (a) { return _U8Afrom(_atob(a).split('').map(function (c) { return c.charCodeAt(0); })); };
/**
* converts a Base64 string to a Uint8Array.
*/
var toUint8Array = function (a) { return _toUint8Array(_unURI(a)); };
//
var _decode = _hasBuffer
? function (a) { return Buffer.from(a, 'base64').toString('utf8'); }
: _TD
? function (a) { return _TD.decode(_toUint8Array(a)); }
: function (a) { return btou(_atob(a)); };
var _unURI = function (a) { return _tidyB64(a.replace(/[-_]/g, function (m0) { return m0 == '-' ? '+' : '/'; })); };
/**
* converts a Base64 string to a UTF-8 string.
* @param {String} src Base64 string. Both normal and URL-safe are supported
* @returns {string} UTF-8 string
*/
var decode = function (src) { return _decode(_unURI(src)); };
/**
* check if a value is a valid Base64 string
* @param {String} src a value to check
*/
var isValid = function (src) {
if (typeof src !== 'string')
return false;
var s = src.replace(/\s+/g, '').replace(/={0,2}$/, '');
return !/[^\s0-9a-zA-Z\+/]/.test(s) || !/[^\s0-9a-zA-Z\-_]/.test(s);
};
//
var _noEnum = function (v) {
return {
value: v, enumerable: false, writable: true, configurable: true
};
};
/**
* extend String.prototype with relevant methods
*/
var extendString = function () {
var _add = function (name, body) { return Object.defineProperty(String.prototype, name, _noEnum(body)); };
_add('fromBase64', function () { return decode(this); });
_add('toBase64', function (urlsafe) { return encode(this, urlsafe); });
_add('toBase64URI', function () { return encode(this, true); });
_add('toBase64URL', function () { return encode(this, true); });
_add('toUint8Array', function () { return toUint8Array(this); });
};
/**
* extend Uint8Array.prototype with relevant methods
*/
var extendUint8Array = function () {
var _add = function (name, body) { return Object.defineProperty(Uint8Array.prototype, name, _noEnum(body)); };
_add('toBase64', function (urlsafe) { return fromUint8Array(this, urlsafe); });
_add('toBase64URI', function () { return fromUint8Array(this, true); });
_add('toBase64URL', function () { return fromUint8Array(this, true); });
};
/**
* extend Builtin prototypes with relevant methods
*/
var extendBuiltins = function () {
extendString();
extendUint8Array();
};
var gBase64 = {
version: version,
VERSION: VERSION,
atob: _atob,
atobPolyfill: atobPolyfill,
btoa: _btoa,
btoaPolyfill: btoaPolyfill,
fromBase64: decode,
toBase64: encode,
encode: encode,
encodeURI: encodeURI,
encodeURL: encodeURI,
utob: utob,
btou: btou,
decode: decode,
isValid: isValid,
fromUint8Array: fromUint8Array,
toUint8Array: toUint8Array,
extendString: extendString,
extendUint8Array: extendUint8Array,
extendBuiltins: extendBuiltins
};
//
// export Base64 to the namespace
//
// ES5 is yet to have Object.assign() that may make transpilers unhappy.
// gBase64.Base64 = Object.assign({}, gBase64);
gBase64.Base64 = {};
Object.keys(gBase64).forEach(function (k) { return gBase64.Base64[k] = gBase64[k]; });
return gBase64;
}));

22
scripts/bech32 license.txt Executable file
View File

@@ -0,0 +1,22 @@
MIT License
Copyright (c) 2017 Pieter Wuille
Copyright (c) 2018 bitcoinjs contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

170
scripts/bech32-2.0.0.js Executable file
View File

@@ -0,0 +1,170 @@
'use strict';
//Object.defineProperty(globalThis, "__esModule", { value: true });
globalThis.bech32m = globalThis.bech32 = void 0;
const ALPHABET = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l';
const ALPHABET_MAP = {};
for (let z = 0; z < ALPHABET.length; z++) {
const x = ALPHABET.charAt(z);
ALPHABET_MAP[x] = z;
}
function polymodStep(pre) {
const b = pre >> 25;
return (((pre & 0x1ffffff) << 5) ^
(-((b >> 0) & 1) & 0x3b6a57b2) ^
(-((b >> 1) & 1) & 0x26508e6d) ^
(-((b >> 2) & 1) & 0x1ea119fa) ^
(-((b >> 3) & 1) & 0x3d4233dd) ^
(-((b >> 4) & 1) & 0x2a1462b3));
}
function prefixChk(prefix) {
let chk = 1;
for (let i = 0; i < prefix.length; ++i) {
const c = prefix.charCodeAt(i);
if (c < 33 || c > 126)
return 'Invalid prefix (' + prefix + ')';
chk = polymodStep(chk) ^ (c >> 5);
}
chk = polymodStep(chk);
for (let i = 0; i < prefix.length; ++i) {
const v = prefix.charCodeAt(i);
chk = polymodStep(chk) ^ (v & 0x1f);
}
return chk;
}
function convert(data, inBits, outBits, pad) {
let value = 0;
let bits = 0;
const maxV = (1 << outBits) - 1;
const result = [];
for (let i = 0; i < data.length; ++i) {
value = (value << inBits) | data[i];
bits += inBits;
while (bits >= outBits) {
bits -= outBits;
result.push((value >> bits) & maxV);
}
}
if (pad) {
if (bits > 0) {
result.push((value << (outBits - bits)) & maxV);
}
}
else {
if (bits >= inBits)
return 'Excess padding';
if ((value << (outBits - bits)) & maxV)
return 'Non-zero padding';
}
return result;
}
function toWords(bytes) {
return convert(bytes, 8, 5, true);
}
function fromWordsUnsafe(words) {
const res = convert(words, 5, 8, false);
if (Array.isArray(res))
return res;
}
function fromWords(words) {
const res = convert(words, 5, 8, false);
if (Array.isArray(res))
return res;
throw new Error(res);
}
function getLibraryFromEncoding(encoding) {
let ENCODING_CONST;
if (encoding === 'bech32') {
ENCODING_CONST = 1;
}
else {
ENCODING_CONST = 0x2bc830a3;
}
function encode(prefix, words, LIMIT) {
LIMIT = LIMIT || 90;
if (prefix.length + 7 + words.length > LIMIT)
throw new TypeError('Exceeds length limit');
prefix = prefix.toLowerCase();
// determine chk mod
let chk = prefixChk(prefix);
if (typeof chk === 'string')
throw new Error(chk);
let result = prefix + '1';
for (let i = 0; i < words.length; ++i) {
const x = words[i];
if (x >> 5 !== 0)
throw new Error('Non 5-bit word');
chk = polymodStep(chk) ^ x;
result += ALPHABET.charAt(x);
}
for (let i = 0; i < 6; ++i) {
chk = polymodStep(chk);
}
chk ^= ENCODING_CONST;
for (let i = 0; i < 6; ++i) {
const v = (chk >> ((5 - i) * 5)) & 0x1f;
result += ALPHABET.charAt(v);
}
return result;
}
function __decode(str, LIMIT) {
LIMIT = LIMIT || 90;
if (str.length < 8)
return str + ' too short';
if (str.length > LIMIT)
return 'Exceeds length limit';
// don't allow mixed case
const lowered = str.toLowerCase();
const uppered = str.toUpperCase();
if (str !== lowered && str !== uppered)
return 'Mixed-case string ' + str;
str = lowered;
const split = str.lastIndexOf('1');
if (split === -1)
return 'No separator character for ' + str;
if (split === 0)
return 'Missing prefix for ' + str;
const prefix = str.slice(0, split);
const wordChars = str.slice(split + 1);
if (wordChars.length < 6)
return 'Data too short';
let chk = prefixChk(prefix);
if (typeof chk === 'string')
return chk;
const words = [];
for (let i = 0; i < wordChars.length; ++i) {
const c = wordChars.charAt(i);
const v = ALPHABET_MAP[c];
if (v === undefined)
return 'Unknown character ' + c;
chk = polymodStep(chk) ^ v;
// not in the checksum?
if (i + 6 >= wordChars.length)
continue;
words.push(v);
}
if (chk !== ENCODING_CONST)
return 'Invalid checksum for ' + str;
return { prefix, words };
}
function decodeUnsafe(str, LIMIT) {
const res = __decode(str, LIMIT);
if (typeof res === 'object')
return res;
}
function decode(str, LIMIT) {
const res = __decode(str, LIMIT);
if (typeof res === 'object')
return res;
throw new Error(res);
}
return {
decodeUnsafe,
decode,
encode,
toWords,
fromWordsUnsafe,
fromWords,
};
}
globalThis.bech32 = getLibraryFromEncoding('bech32');
globalThis.bech32m = getLibraryFromEncoding('bech32m');

View File

@@ -0,0 +1,26 @@
The MIT License (MIT)
=====================
Copyright © `<2022>` `Michael Mclaughlin`
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the “Software”), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

2926
scripts/bignumber.js-9.1.1.js Executable file

File diff suppressed because it is too large Load Diff

124
scripts/bit_reader.js Executable file
View File

@@ -0,0 +1,124 @@
// Use strict
"use strict";
// Classes
// Bit reader class
class BitReader {
// Public
// Constructor
constructor(data) {
// Set data
this.data = data;
// Initialize byte index
this.byteIndex = 0;
// Initialize bit index
this.bitIndex = 0;
}
// Get bits
getBits(numberOfBits) {
// Check if more than one byte is requested
if(numberOfBits > Common.BITS_IN_A_BYTE) {
// Initialize result
var result = 0;
// Go through all bytes
while(numberOfBits > 0) {
// Update result to make space for more bits
result <<= Math.min(numberOfBits, Common.BITS_IN_A_BYTE);
// Include bits in result
result |= this.getBits(Math.min(numberOfBits, Common.BITS_IN_A_BYTE));
// Update number of bits
numberOfBits -= Common.BITS_IN_A_BYTE;
}
// Return result
return result;
}
// Otherwise
else {
// Check if no bits requested
if(numberOfBits === 0) {
// Return zero
return 0;
}
// Check if number of bits is invalid
if(this.byteIndex === this.data["length"] || (this.byteIndex === this.data["length"] - 1 && this.bitIndex + numberOfBits > Common.BITS_IN_A_BYTE)) {
// Throw error
throw "Invalid number of bits.";
}
// Initialize result to data at the byte index
var result = this.data[this.byteIndex] << Common.BITS_IN_A_BYTE;
// Check if more data is needed
if(this.bitIndex + numberOfBits > Common.BITS_IN_A_BYTE) {
// Append next byte to the result
result |= this.data[this.byteIndex + 1];
}
// Remove upper bits from result
result &= (1 << (Common.BITS_IN_A_BYTE * 2 - this.bitIndex)) - 1;
// Remove lower bits from result
result >>>= (Common.BITS_IN_A_BYTE * 2 - (this.bitIndex + numberOfBits));
// Update bit index
this.bitIndex += numberOfBits;
// Check if bit index overflowed into the next byte
if(this.bitIndex >= Common.BITS_IN_A_BYTE) {
// Increment byte index
++this.byteIndex;
// Correct bit index
this.bitIndex %= Common.BITS_IN_A_BYTE;
}
// Return result
return result;
}
}
// Get bytes
getBytes(numberOfBytes) {
// Initialize result
var result = new Uint8Array(numberOfBytes);
// Go through all bytes
for(var i = 0; i < numberOfBytes; ++i) {
// Set byte in the result
result[i] = this.getBits(Common.BITS_IN_A_BYTE);
}
// Return result
return result;
}
}
// Main function
// Set global object's bit reader
globalThis["BitReader"] = BitReader;

110
scripts/bit_writer.js Executable file
View File

@@ -0,0 +1,110 @@
// Use strict
"use strict";
// Classes
// Bit writer class
class BitWriter {
// Public
// Constructor
constructor() {
// Set data
this.data = new Uint8Array([]);
// Initialize byte index
this.byteIndex = 0;
// Initialize bit index
this.bitIndex = 0;
}
// Set bits
setBits(value, numberOfBits) {
// Go through all bytes past one byte
while(numberOfBits > Common.BITS_IN_A_BYTE) {
// Set byte
this.setBits(value >>> (Common.BITS_IN_A_BYTE * (Math.floor(numberOfBits / Common.BITS_IN_A_BYTE) - 1) + numberOfBits % Common.BITS_IN_A_BYTE), Math.min(numberOfBits, Common.BITS_IN_A_BYTE));
// Update number of bits
numberOfBits -= Common.BITS_IN_A_BYTE;
}
// Check if no bits requested
if(numberOfBits === 0) {
// Return
return;
}
// Check if more data is needed
if(this.bitIndex === 0 || this.bitIndex + numberOfBits > Common.BITS_IN_A_BYTE) {
// Increase data's size by one
var temp = new Uint8Array(this.data["length"] + 1);
temp.set(this.data);
this.data = temp;
}
// Check if value will overflow into the next byte
if(this.bitIndex + numberOfBits > Common.BITS_IN_A_BYTE) {
// Include data in value at byte index
this.data[this.byteIndex] |= value >>> ((this.bitIndex + numberOfBits) - Common.BITS_IN_A_BYTE);
// Include data in value at next byte index
this.data[this.byteIndex + 1] |= value << (Common.BITS_IN_A_BYTE * 2 - (this.bitIndex + numberOfBits));
}
// Otherwise
else {
// Include data in value at byte index
this.data[this.byteIndex] |= value << (Common.BITS_IN_A_BYTE - (this.bitIndex + numberOfBits));
}
// Update bit index
this.bitIndex += numberOfBits;
// Check if bit index overflowed into the next byte
if(this.bitIndex >= Common.BITS_IN_A_BYTE) {
// Increment byte index
++this.byteIndex;
// Correct bit index
this.bitIndex %= Common.BITS_IN_A_BYTE;
}
}
// Set bytes
setBytes(bytes) {
// Go through all bytes
for(var i = 0; i < bytes["length"]; ++i) {
// Set byte in the data
this.setBits(bytes[i], Common.BITS_IN_A_BYTE);
}
}
// Get bytes
getBytes() {
// Return data
return this.data;
}
}
// Main function
// Set global object's bit writer
globalThis["BitWriter"] = BitWriter;

434
scripts/camera.js Executable file
View File

@@ -0,0 +1,434 @@
// Use strict
"use strict";
// Classes
// Camera class
class Camera {
// Public
// Initialize
static initialize() {
// Initialize request index
Camera.requestIndex = 0;
// Create worker
Camera.worker = new Worker(Camera.WORKER_FILE_LOCATION);
// Window before unload event
$(window).on("beforeunload", function() {
// Get current request index
var currentRequestIndex = Camera.requestIndex++;
// Check if current request index is at the max safe integer
if(currentRequestIndex === Number.MAX_SAFE_INTEGER)
// Reset request index
Camera.requestIndex = 0;
// Send worker an uninitialize request
Camera.worker.postMessage([
// Request index
currentRequestIndex,
// Type
Camera.UNINITIALIZE_REQUEST_TYPE
]);
// Terminate worker
Camera.worker.terminate();
});
// Return promise
return new Promise(function(resolve, reject) {
// Worker on error
Camera.worker["onerror"] = function() {
// Reject error
reject("Failed to create camera worker.");
};
// Worker on message
Camera.worker["onmessage"] = function(event) {
// Get message
var message = event["data"];
// Get message's request index
var requestIndex = message[Camera.MESSAGE_REQUEST_INDEX_OFFSET];
// Check message's type
switch(message[Camera.MESSAGE_TYPE_OFFSET]) {
// Initialize request type
case Camera.INITIALIZE_REQUEST_TYPE:
// Get message's status
var status = message[Camera.MESSAGE_STATUS_OFFSET];
// Check if worker initialized successfully
if(status === Camera.STATUS_SUCCESS_VALUE)
// Resolve
resolve();
// Otherwise
else
// Reject error
reject("Failed to initialize camera worker.");
// Break
break;
// Default
default:
// Get message's response
var response = message[Camera.MESSAGE_RESPONSE_OFFSET];
// Trigger response request index event
$(document).trigger(Camera.RESPONSE_EVENT + requestIndex.toFixed(), [
// Response
response
]);
// Break
break;
}
};
// Get current request index
var currentRequestIndex = Camera.requestIndex++;
// Check if current request index is at the max safe integer
if(currentRequestIndex === Number.MAX_SAFE_INTEGER)
// Reset request index
Camera.requestIndex = 0;
// Send worker an initialize request
Camera.worker.postMessage([
// Request index
currentRequestIndex,
// Type
Camera.INITIALIZE_REQUEST_TYPE,
// URL query string
Common.URL_QUERY_STRING_SEPARATOR + encodeURIComponent(Consensus.OVERRIDE_WALLET_TYPE_URL_PARAMETER_NAME).replace(/%20/ug, "+") + Common.URL_QUERY_STRING_PARAMETER_VALUE_SEPARATOR + encodeURIComponent(Consensus.walletTypeToText(Consensus.getWalletType())).replace(/%20/ug, "+") + Common.URL_QUERY_STRING_PARAMETER_SEPARATOR + encodeURIComponent(Consensus.OVERRIDE_NETWORK_TYPE_URL_PARAMETER_NAME).replace(/%20/ug, "+") + Common.URL_QUERY_STRING_PARAMETER_VALUE_SEPARATOR + encodeURIComponent(Consensus.networkTypeToText(Consensus.getNetworkType())).replace(/%20/ug, "+")
]);
});
}
// Get value
static getValue(image, width, height) {
// Create canvas
var canvas = document.createElement("canvas");
// Set canvas's dimensions
canvas["width"] = width;
canvas["height"] = height;
// Draw image on canvas
var context = canvas.getContext("2d");
context.drawImage(image, 0, 0, width, height);
// Get image's data from the canvas
var imageData = context.getImageData(0, 0, width, height)["data"]["buffer"];
// Return promise
return new Promise(function(resolve, reject) {
// Return sending decode request
return Camera.sendRequest([
// Type
Camera.DECODE_REQUEST_TYPE,
// Width
width,
// Height
height,
// Image data
imageData
], [
// Image data
imageData
]).then(function(response) {
// Check if response is no value
if(response === Camera.NO_VALUE)
// Resolve no value
resolve(Camera.NO_VALUE);
// Otherwise
else {
// Get data from response
var data = response[Camera.RESPONSE_DATA_INDEX];
// Get top left corner X from response
var topLeftCornerX = response[Camera.RESPONSE_TOP_LEFT_CORNER_X_INDEX];
// Get top left corner Y from response
var topLeftCornerY = response[Camera.RESPONSE_TOP_LEFT_CORNER_Y_INDEX];
// Get top right corner X from response
var topRightCornerX = response[Camera.RESPONSE_TOP_RIGHT_CORNER_X_INDEX];
// Get top right corner Y from response
var topRightCornerY = response[Camera.RESPONSE_TOP_RIGHT_CORNER_Y_INDEX];
// Get bottom left corner X from response
var bottomLeftCornerX = response[Camera.RESPONSE_BOTTOM_LEFT_CORNER_X_INDEX];
// Get bottom left corner Y from response
var bottomLeftCornerY = response[Camera.RESPONSE_BOTTOM_LEFT_CORNER_Y_INDEX];
// Get bottom right corner X from response
var bottomRightCornerX = response[Camera.RESPONSE_BOTTOM_RIGHT_CORNER_X_INDEX];
// Get bottom right corner Y from response
var bottomRightCornerY = response[Camera.RESPONSE_BOTTOM_RIGHT_CORNER_Y_INDEX];
// Resolve data
resolve(data);
}
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
});
}
// Initialize request type
static get INITIALIZE_REQUEST_TYPE() {
// Return initialize request type
return 0;
}
// Uninitialize request type
static get UNINITIALIZE_REQUEST_TYPE() {
// Return uninitialize request type
return Camera.INITIALIZE_REQUEST_TYPE + 1;
}
// Decode request type
static get DECODE_REQUEST_TYPE() {
// Return decode request type
return Camera.UNINITIALIZE_REQUEST_TYPE + 1;
}
// Message request index offset
static get MESSAGE_REQUEST_INDEX_OFFSET() {
// Return message request index offset
return 0;
}
// Message type offset
static get MESSAGE_TYPE_OFFSET() {
// Return message type offset
return Camera.MESSAGE_REQUEST_INDEX_OFFSET + 1;
}
// Message initialize URL query string offset
static get MESSAGE_INITIALIZE_URL_QUERY_STRING_OFFSET() {
// Return message initialize URL query string offset
return Camera.MESSAGE_TYPE_OFFSET + 1;
}
// Message width offset
static get MESSAGE_WIDTH_OFFSET() {
// Return message width offset
return Camera.MESSAGE_TYPE_OFFSET + 1;
}
// Message height offset
static get MESSAGE_HEIGHT_OFFSET() {
// Return message height offset
return Camera.MESSAGE_WIDTH_OFFSET + 1;
}
// Message image data offset
static get MESSAGE_IMAGE_DATA_OFFSET() {
// Return message image data offset
return Camera.MESSAGE_HEIGHT_OFFSET + 1;
}
// Status success value
static get STATUS_SUCCESS_VALUE() {
// Return status success value
return true;
}
// Status failed value
static get STATUS_FAILED_VALUE() {
// Return status failed value
return false;
}
// No value
static get NO_VALUE() {
// Return no value
return null;
}
// Private
// Send request
static sendRequest(request, transfer) {
// Get current request index
var currentRequestIndex = Camera.requestIndex++;
// Check if current request index is at the max safe integer
if(currentRequestIndex === Number.MAX_SAFE_INTEGER)
// Reset request index
Camera.requestIndex = 0;
// Add current request index to request
request.unshift(currentRequestIndex);
// Return promise
return new Promise(function(resolve, reject) {
// Response current request index event
$(document).one(Camera.RESPONSE_EVENT + currentRequestIndex.toFixed(), function(event, response) {
// Resolve response
resolve(response);
});
// Send worker the request
Camera.worker.postMessage(request, transfer);
});
}
// Message status offset
static get MESSAGE_STATUS_OFFSET() {
// Return message status offset
return Camera.MESSAGE_TYPE_OFFSET + 1;
}
// Message response offset
static get MESSAGE_RESPONSE_OFFSET() {
// Return message response offset
return Camera.MESSAGE_TYPE_OFFSET + 1;
}
// Response event
static get RESPONSE_EVENT() {
// Return response event
return "CameraResponseEvent";
}
// Response data index
static get RESPONSE_DATA_INDEX() {
// Return response data index
return 0;
}
// Response top left corner X index
static get RESPONSE_TOP_LEFT_CORNER_X_INDEX() {
// Return response top left corner X index
return Camera.RESPONSE_DATA_INDEX + 1;
}
// Response top left corner Y index
static get RESPONSE_TOP_LEFT_CORNER_Y_INDEX() {
// Return response top left corner Y index
return Camera.RESPONSE_TOP_LEFT_CORNER_X_INDEX + 1;
}
// Response top right corner X index
static get RESPONSE_TOP_RIGHT_CORNER_X_INDEX() {
// Return response top right corner X index
return Camera.RESPONSE_TOP_LEFT_CORNER_Y_INDEX + 1;
}
// Response top right corner Y index
static get RESPONSE_TOP_RIGHT_CORNER_Y_INDEX() {
// Return response top right corner Y index
return Camera.RESPONSE_TOP_RIGHT_CORNER_X_INDEX + 1;
}
// Response bottom left corner X index
static get RESPONSE_BOTTOM_LEFT_CORNER_X_INDEX() {
// Return response bottom left corner X index
return Camera.RESPONSE_TOP_RIGHT_CORNER_Y_INDEX + 1;
}
// Response bottom left corner Y index
static get RESPONSE_BOTTOM_LEFT_CORNER_Y_INDEX() {
// Return response bottom left corner Y index
return Camera.RESPONSE_BOTTOM_LEFT_CORNER_X_INDEX + 1;
}
// Response bottom right corner X index
static get RESPONSE_BOTTOM_RIGHT_CORNER_X_INDEX() {
// Return response bottom right corner X index
return Camera.RESPONSE_BOTTOM_LEFT_CORNER_Y_INDEX + 1;
}
// Response bottom right corner Y index
static get RESPONSE_BOTTOM_RIGHT_CORNER_Y_INDEX() {
// Return response bottom right corner Y index
return Camera.RESPONSE_BOTTOM_RIGHT_CORNER_X_INDEX + 1;
}
// Worker file location
static get WORKER_FILE_LOCATION() {
// Return worker file location
return "." + getResource("./scripts/camera_worker.js");
}
}
// Main function
// Set global object's camera
globalThis["Camera"] = Camera;

176
scripts/camera_worker.js Executable file
View File

@@ -0,0 +1,176 @@
<?php
// Included files
require_once __DIR__ . "/../backend/common.php";
require_once __DIR__ . "/../backend/resources.php";
// Main function
// Set content type header
header("Content-Type: application/javascript; charset=" . mb_internal_encoding());
?>// Use strict
"use strict";
// Import scripts
importScripts(".<?= escapeString(getResource("./scripts/camera.js")); ?>");
importScripts(".<?= escapeString(getResource("./scripts/jsQR-1.4.0.js")); ?>");
// Constants
// No QR code
const NO_QR_CODE = null;
// Global variables
// URL query string
var URL_QUERY_STRING;
// Events
// Message event
self.addEventListener("message", function(event) {
// Get message
var message = event["data"];
// Get message's request index
var requestIndex = message[Camera.MESSAGE_REQUEST_INDEX_OFFSET];
// Get message's type
var type = message[Camera.MESSAGE_TYPE_OFFSET];
// Check type
switch(type) {
// Initialize request type
case Camera.INITIALIZE_REQUEST_TYPE:
// Get message's URL query string
URL_QUERY_STRING = message[Camera.MESSAGE_INITIALIZE_URL_QUERY_STRING_OFFSET];
// Respond with success status
postMessage([
// Request index
requestIndex,
// Type
type,
// Status
Camera.STATUS_SUCCESS_VALUE
]);
// Break
break;
// Uninitialize request type
case Camera.UNINITIALIZE_REQUEST_TYPE:
// Respond with success status
postMessage([
// Request index
requestIndex,
// Type
type,
// Status
Camera.STATUS_SUCCESS_VALUE
]);
// Break
break;
// Decode request type
case Camera.DECODE_REQUEST_TYPE:
// Get message's width
var width = message[Camera.MESSAGE_WIDTH_OFFSET];
// Get message's height
var height = message[Camera.MESSAGE_HEIGHT_OFFSET];
// Get message's image data
var imageData = new Uint8Array(message[Camera.MESSAGE_IMAGE_DATA_OFFSET]);
// Get QR code from image data, width, and height
var qrCode = jsQR(imageData, width, height, {
// Inversion attempts
"inversionAttempts": "attemptBoth"
});
// Check if getting QR code failed
if(qrCode === NO_QR_CODE) {
// Respond with no value
postMessage([
// Request index
requestIndex,
// Type
type,
// Value
Camera.NO_VALUE
]);
}
// Otherwise
else {
// Respond with value
postMessage([
// Request index
requestIndex,
// Type
type,
// Value
[
// Data
qrCode["data"],
// Top left corner X
qrCode["location"]["topLeftCorner"]["x"],
// Top left corner Y
qrCode["location"]["topLeftCorner"]["y"],
// Top right corner X
qrCode["location"]["topRightCorner"]["x"],
// Top right corner Y
qrCode["location"]["topRightCorner"]["y"],
// Bottom left corner X
qrCode["location"]["bottomLeftCorner"]["x"],
// Bottom left corner Y
qrCode["location"]["bottomLeftCorner"]["y"],
// Bottom right corner X
qrCode["location"]["bottomRightCorner"]["x"],
// Bottom right corner Y
qrCode["location"]["bottomRightCorner"]["y"]
]
]);
}
// Break;
break;
}
});

135
scripts/caps_lock.js Executable file
View File

@@ -0,0 +1,135 @@
// Use strict
"use strict";
// Classes
// Caps lock class
class CapsLock {
// Public
// Constructor
constructor() {
// Set state
this.state = false;
// Get is linux
this.isLinux = (typeof navigator === "object" && navigator !== null) ? (("userAgentData" in navigator === true && "platform" in navigator["userAgentData"] === true) ? navigator["userAgentData"]["platform"] : navigator["platform"]).toLowerCase().indexOf("linux") !== Common.INDEX_NOT_FOUND : false;
// Turning off
this.turningOff = false;
// Get body display
this.bodyDisplay = $("body");
// Set self
var self = this;
// Document key down, key up, mouse down, mouse up, and mousemove event
$(document).on("keydown keyup mousedown mouseup mousemove", function(event) {
// Check if Linux, event is key up or key down, and caps lock is the key
if(self.isLinux === true && (event["type"] === "keyup" || event["type"] === "keydown") && event["originalEvent"]["code"] === "CapsLock") {
// Check if event is key down
if(event["type"] === "keydown") {
// Check if caps lock is off
if(event["originalEvent"].getModifierState("CapsLock") === false) {
// Check if state is off
if(self.state === false) {
// Set state
self.state = true;
// Set that body display has caps lock
self.bodyDisplay.addClass("capsLock");
}
}
// Otherwise
else
// Set turning off
self.turningOff = true;
}
// Otherwise assume event is key up
else {
// Check if turning off
if(self.turningOff === true) {
// Clear turning off
self.turningOff = false;
// Check if state is on
if(self.state === true) {
// Clear state
self.state = false;
// Set that body display doesn't have caps lock
self.bodyDisplay.removeClass("capsLock");
}
}
}
}
// Otherwise check if event includes the ability to get the modifier state
else if(typeof event === "object" && event !== null && "originalEvent" in event === true && typeof event["originalEvent"] === "object" && event["originalEvent"] !== null && "getModifierState" in event["originalEvent"] === true) {
// Check if caps lock is on
if(event["originalEvent"].getModifierState("CapsLock") === true) {
// Check if state is off
if(self.state === false) {
// Set state
self.state = true;
// Set that body display has caps lock
self.bodyDisplay.addClass("capsLock");
}
}
// Otherwise check if caps lock is off
else if(event["originalEvent"].getModifierState("CapsLock") === false) {
// Check if state is on
if(self.state === true) {
// Clear state
self.state = false;
// Set that body display doesn't have caps lock
self.bodyDisplay.removeClass("capsLock");
}
}
}
});
}
// Is on
isOn() {
// Return if caps lock is on
return this.state === true;
}
// Is off
isOff() {
// Return if not on
return this.isOn() === false;
}
}
// Main function
// Set global object's caps lock
globalThis["CapsLock"] = CapsLock;

48
scripts/clipboard.js Executable file
View File

@@ -0,0 +1,48 @@
// Use strict
"use strict";
// Classes
// Clipboard class
class Clipboard {
// Public
// Copy
copy(text) {
// Return promise
return new Promise(function(resolve, reject) {
// Check if clipboard API is supported
if(typeof navigator === "object" && navigator !== null && "clipboard" in navigator === true) {
// Return writing text to clipboard
return navigator["clipboard"].writeText(text).then(function() {
// Resolve
resolve();
// Catch errors
}).catch(function(error) {
// Reject error
reject("Writing to clipboard failed.");
});
}
// Otherwise
else
// Reject error
reject("Clipboard not supported.");
});
}
}
// Main function
// Set global object's clipboard
globalThis["Clipboard"] = Clipboard;

1951
scripts/common.js Executable file

File diff suppressed because it is too large Load Diff

1587
scripts/consensus.js Executable file

File diff suppressed because it is too large Load Diff

180
scripts/cookie_acceptance.js Executable file
View File

@@ -0,0 +1,180 @@
// Use strict
"use strict";
// Classes
// Cookie acceptance class
class CookieAcceptance {
// Public
// Constructor
constructor() {
// Get cookie acceptance display
this.cookieAcceptanceDisplay = $("section.cookieAcceptance");
// Get acknowledge button
this.acknowledgeButton = this.cookieAcceptanceDisplay.find("button");
// Set can show
this.canShow = false;
// Set self
var self = this;
// Cookie acceptance display transaition end event
this.cookieAcceptanceDisplay.on("transitionend", function() {
// Check if cookie acceptance display is hiding
if(self.cookieAcceptanceDisplay.hasClass("hide") === true) {
// Prevent focus on cookie acceptance display's elements
self.cookieAcceptanceDisplay.addClass("noFocus");
// Trigger is hidden event
$(self).trigger(CookieAcceptance.IS_HIDDEN_EVENT);
}
});
// Window storage event
$(window).on("storage", function(event) {
// Check if cookie acceptance message acknowledged was changed
if(event["originalEvent"]["key"] === CookieAcceptance.COOKIE_ACCEPTANCE_MESSAGE_ACKNOWLEDGED_LOCAL_STORAGE_NAME) {
// Hide
self.hide();
// Clear can show
self.canShow = false;
}
});
// Acknowledged button click event
this.acknowledgeButton.on("click", function() {
// Hide
self.hide();
// Clear can show
self.canShow = false;
// Try
try {
// Save cookie acceptance message acknowledged
localStorage.setItem(CookieAcceptance.COOKIE_ACCEPTANCE_MESSAGE_ACKNOWLEDGED_LOCAL_STORAGE_NAME, CookieAcceptance.COOKIE_ACCEPTANCE_MESSAGE_ACKNOWLEDGED_TRUE_VALUE);
}
// Catch errors
catch(error) {
// Trigger a fatal error
new FatalError(FatalError.LOCAL_STORAGE_ERROR);
}
});
}
// Show
show(canShow = true) {
// Check if can show
if(canShow === true || this.canShow === true) {
// Set can show
this.canShow = true;
// Check if not an app or extension and not loading from file
if(Common.isApp() === false && Common.isExtension() === false && location["protocol"] !== Common.FILE_PROTOCOL) {
// Get cookie acceptance message acknowledged
var cookieAcceptanceMessageAcknowledged = localStorage.getItem(CookieAcceptance.COOKIE_ACCEPTANCE_MESSAGE_ACKNOWLEDGED_LOCAL_STORAGE_NAME);
// Check if cookie acceptance message hasn't been acknowledged
if(cookieAcceptanceMessageAcknowledged === Common.INVALID_LOCAL_STORAGE_ITEM || cookieAcceptanceMessageAcknowledged !== CookieAcceptance.COOKIE_ACCEPTANCE_MESSAGE_ACKNOWLEDGED_TRUE_VALUE) {
// Show cookie acceptance display and make it so that its elements can be focused
this.cookieAcceptanceDisplay.removeClass("hide noFocus");
// Set self
var self = this;
// Windows resize cookie acceptance event
$(window).on("resize.cookieAcceptance", function() {
// Check if is an app
if(Common.isApp() === true) {
// Turn off window resize cookie acceptance event
$(window).off("resize.cookieAcceptance");
// Hide
self.hide();
// Clear can show
self.canShow = false;
}
});
// Return true
return true;
}
// Otherwise
else {
// Trigger is hidden event
$(this).trigger(CookieAcceptance.IS_HIDDEN_EVENT);
}
}
// Otherwise
else {
// Trigger is hidden event
$(this).trigger(CookieAcceptance.IS_HIDDEN_EVENT);
}
}
// Return false
return false;
}
// Is hidden event
static get IS_HIDDEN_EVENT() {
// Return is hidden event
return "CookieAcceptanceIsHiddenEvent";
}
// Private
// Hide
hide() {
// Hide cookie acceptance display
this.cookieAcceptanceDisplay.addClass("hide");
}
// Cookie acceptance message acknowledged local storage name
static get COOKIE_ACCEPTANCE_MESSAGE_ACKNOWLEDGED_LOCAL_STORAGE_NAME() {
// Return cookie acceptance message acknowledged local storage name
return "Cookie Acceptance Message Acknowledged";
}
// Cookie acceptance message acknowledged true value
static get COOKIE_ACCEPTANCE_MESSAGE_ACKNOWLEDGED_TRUE_VALUE() {
// Return cookie acceptance message acknowledged true value
return "true";
}
}
// Main function
// Set global object's cookie acceptance
globalThis["CookieAcceptance"] = CookieAcceptance;

100
scripts/copyright.js Executable file
View File

@@ -0,0 +1,100 @@
// Use strict
"use strict";
// Classes
// Copyright class
class Copyright {
// Public
// Initialize
static initialize() {
// Update
Copyright.update();
}
// Private
// Update
static update() {
// Get current timestamp
var currentTimestamp = new Date();
// Get current year
var currentYear = currentTimestamp.getFullYear();
// Check if the current year is greater than the copyright year
if(currentYear > COPYRIGHT_YEAR) {
// Get new date copyright
var newDateCopyright = $(Language.createTranslatableContainer("<meta>", Language.getDefaultTranslation('%1$s%2$s'), [COPYRIGHT_YEAR.toFixed(), currentYear.toFixed()]));
// Get new rights
var newRights = $(Language.createTranslatableContainer("<meta>", Language.getDefaultTranslation('© %1$s%2$s Nicolas Flamel.'), [COPYRIGHT_YEAR.toFixed(), currentYear.toFixed()]));
}
// Otherwise
else {
// Get new date copyright
var newDateCopyright = $(Language.createTranslatableContainer("<meta>", "%1$s", [COPYRIGHT_YEAR.toFixed()]));
// Get new rights
var newRights = $(Language.createTranslatableContainer("<meta>", Language.getDefaultTranslation('© %1$s Nicolas Flamel.'), [COPYRIGHT_YEAR.toFixed()]));
}
// Set new date copyright's name
newDateCopyright.attr("name", Copyright.DATE_COPYRIGHT_NAME);
// Set new rights's name
newRights.attr("name", Copyright.RIGHTS_NAME);
// Replace date copyright with the new date copyright
$("meta[name=\"" + Copyright.DATE_COPYRIGHT_NAME + "\"]").replaceWith(newDateCopyright);
// Replace rights with the new rights
$("meta[name=\"" + Copyright.RIGHTS_NAME + "\"]").replaceWith(newRights);
// Get next year timestamp
var nextYearTimestamp = new Date(currentYear + 1, Common.JANUARY_MONTH_INDEX);
// Set timeout
setTimeout(function() {
// Update
Copyright.update();
}, Math.min(nextYearTimestamp - currentTimestamp, Common.INT32_MAX_VALUE));
}
// Date copyright name
static get DATE_COPYRIGHT_NAME() {
// Return date copyright name
return "dcterms.dateCopyrighted";
}
// Rights name
static get RIGHTS_NAME() {
// Return rights name
return "dcterms.rights";
}
}
// Main function
// Set global object's copyright
globalThis["Copyright"] = Copyright;
// Ready event
$(function() {
// Initialize copyright
Copyright.initialize();
});

14
scripts/crc32 license.txt Executable file
View File

@@ -0,0 +1,14 @@
Copyright (C) 2014-present SheetJS
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

118
scripts/crc32-1.2.0.js Executable file
View File

@@ -0,0 +1,118 @@
/* crc32.js (C) 2014-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
/*exported CRC32 */
var CRC32;
(function (factory) {
/*jshint ignore:start */
/*eslint-disable */
if(typeof DO_NOT_EXPORT_CRC === 'undefined') {
if('object' === typeof exports) {
factory(exports);
} else if ('function' === typeof define && define.amd) {
define(function () {
var module = {};
factory(module);
return module;
});
} else {
factory(CRC32 = {});
}
} else {
factory(CRC32 = {});
}
/*eslint-enable */
/*jshint ignore:end */
}(function(CRC32) {
CRC32.version = '1.2.0';
/* see perf/crc32table.js */
/*global Int32Array */
function signed_crc_table() {
var c = 0, table = new Array(256);
for(var n =0; n != 256; ++n){
c = n;
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
table[n] = c;
}
return typeof Int32Array !== 'undefined' ? new Int32Array(table) : table;
}
var T = signed_crc_table();
function crc32_bstr(bstr, seed) {
var C = seed ^ -1, L = bstr.length - 1;
for(var i = 0; i < L;) {
C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
}
if(i === L) C = (C>>>8) ^ T[(C ^ bstr.charCodeAt(i))&0xFF];
return C ^ -1;
}
function crc32_buf(buf, seed) {
if(buf.length > 10000) return crc32_buf_8(buf, seed);
var C = seed ^ -1, L = buf.length - 3;
for(var i = 0; i < L;) {
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
}
while(i < L+3) C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
return C ^ -1;
}
function crc32_buf_8(buf, seed) {
var C = seed ^ -1, L = buf.length - 7;
for(var i = 0; i < L;) {
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
}
while(i < L+7) C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
return C ^ -1;
}
function crc32_str(str, seed) {
var C = seed ^ -1;
for(var i = 0, L=str.length, c, d; i < L;) {
c = str.charCodeAt(i++);
if(c < 0x80) {
C = (C>>>8) ^ T[(C ^ c)&0xFF];
} else if(c < 0x800) {
C = (C>>>8) ^ T[(C ^ (192|((c>>6)&31)))&0xFF];
C = (C>>>8) ^ T[(C ^ (128|(c&63)))&0xFF];
} else if(c >= 0xD800 && c < 0xE000) {
c = (c&1023)+64; d = str.charCodeAt(i++)&1023;
C = (C>>>8) ^ T[(C ^ (240|((c>>8)&7)))&0xFF];
C = (C>>>8) ^ T[(C ^ (128|((c>>2)&63)))&0xFF];
C = (C>>>8) ^ T[(C ^ (128|((d>>6)&15)|((c&3)<<4)))&0xFF];
C = (C>>>8) ^ T[(C ^ (128|(d&63)))&0xFF];
} else {
C = (C>>>8) ^ T[(C ^ (224|((c>>12)&15)))&0xFF];
C = (C>>>8) ^ T[(C ^ (128|((c>>6)&63)))&0xFF];
C = (C>>>8) ^ T[(C ^ (128|(c&63)))&0xFF];
}
}
return C ^ -1;
}
CRC32.table = T;
// $FlowIgnore
CRC32.bstr = crc32_bstr;
// $FlowIgnore
CRC32.buf = crc32_buf;
// $FlowIgnore
CRC32.str = crc32_str;
}));

1194
scripts/crypto.js Executable file

File diff suppressed because it is too large Load Diff

1758
scripts/database.js Executable file

File diff suppressed because it is too large Load Diff

87
scripts/database_transaction.js Executable file
View File

@@ -0,0 +1,87 @@
// Use strict
"use strict";
// Classes
// Database transaction class
class DatabaseTransaction {
// Public
// Constructor
constructor(transaction, objectStoreNames, autocomplete = true) {
// Set transaction
this.transaction = transaction;
// Set object store names
this.objectStoreNames = objectStoreNames;
// Set autocomplete
this.autocomplete = autocomplete;
// Set completed
this.completed = false;
// Set aborted
this.aborted = false;
// Set self
var self = this;
// Transaction complete event
$(this.transaction).on("complete", function() {
// Set completed
self.completed = true;
// Transaction abort event
}).on("abort", function() {
// Set aborted
self.aborted = true;
});
}
// Get transaction
getTransaction() {
// Return transaction
return this.transaction;
}
// Get object store names
getObjectStoreNames() {
// Return object store names
return this.objectStoreNames;
}
// Get autocomplete
getAutocomplete() {
// Return autocomplete
return this.autocomplete;
}
// Is completed
isCompleted() {
// Return if completed
return this.completed === true;
}
// Is aborted
isAborted() {
// Return if aborted
return this.aborted === true;
}
}
// Main function
// Set global object's database transaction
globalThis["DatabaseTransaction"] = DatabaseTransaction;

1207
scripts/emoji.js Executable file

File diff suppressed because it is too large Load Diff

410
scripts/extension.js Executable file
View File

@@ -0,0 +1,410 @@
// Use strict
"use strict";
// Classes
// Extension class
class Extension {
// Public
// Initialize
static initialize() {
// Get URL parameters
var urlParameters = Common.getUrlParameters();
// Return promise
return new Promise(function(resolve, reject) {
// Check if URL parameters contains a request
if("Request" in urlParameters === true) {
// Set close when done
Extension.closeWhenDone = true;
// Try
try {
// Process URL parameters as a request
Extension.processRequest(urlParameters, true);
}
// Catch errors
catch(error) {
// Reject error
reject(error);
// Return
return;
}
}
// Otherwise
else {
// Clear close when done
Extension.closeWhenDone = false;
}
// Resolve
resolve();
});
}
// Get requests
static getRequests() {
// Return requests
return Extension.requests;
}
// Allow interrupt on close
static allowInterruptOnClose() {
// Set can interrupt close
Extension.canInterruptClose = true;
}
// Prevent interrupt on close
static preventInterruptOnClose() {
// Clear can interrupt close
Extension.canInterruptClose = false;
}
// Get close when done
static getCloseWhenDone() {
// Return close when done
return Extension.closeWhenDone;
}
// No transaction amount
static get NO_TRANSACTION_AMOUNT() {
// Return no transaction amount
return null;
}
// No transaction message
static get NO_TRANSACTION_MESSAGE() {
// Return no transation message
return null;
}
// Private
// Process request
static processRequest(request, makeFirstRequest = false) {
// Check request
switch(request["Request"]) {
// Start transaction
case "Start Transaction":
// Check if recipient address isn't valid
if("Recipient Address" in request === false || typeof request["Recipient Address"] !== "string" || request["Recipient Address"]["length"] === 0) {
// Throw error
throw Language.getDefaultTranslation('Invalid recipient address.');
}
// Otherwise check if amount isn't valid
else if("Amount" in request === true && request["Amount"] !== Extension.NO_TRANSACTION_AMOUNT && (Common.isNumberString(request["Amount"]) === false || Common.getNumberStringPrecision(request["Amount"]) > Extension.MAXIMUM_AMOUNT_PRECISION || parseFloat(Common.removeTrailingZeros(request["Amount"])) < Extension.MINIMUM_AMOUNT)) {
// Throw error
throw Language.getDefaultTranslation('Invalid amount.');
}
// Otherwise check if message isn't valid
else if("Message" in request === true && request["Message"] !== Extension.NO_TRANSACTION_MESSAGE && typeof request["Message"] !== "string") {
// Throw error
throw Language.getDefaultTranslation('Invalid message.');
}
// Otherwise
else {
// Get request information
var requestInformation = {
// Name
"Name": SendPaymentSection.NAME,
// State
"State": {
// Elements states
[Section.STATE_ELEMENTS_STATES_NAME]: [
// Back
{
"Tag": "BUTTON",
"Focused": false,
"Value": Section.NO_VALUE
},
// Forward
{
"Tag": "BUTTON",
"Focused": false,
"Value": Section.NO_VALUE
},
// Recipient address
{
"Tag": "INPUT",
"Focused": false,
"Value": ProtocolHandler.standardizeUrlProtocol(request["Recipient Address"]),
"Selection Start": Section.NO_VALUE,
"Selection End": Section.NO_VALUE,
"Selection Direction": Section.NO_VALUE
},
// Scan
{
"Tag": "BUTTON",
"Focused": false,
"Value": Section.NO_VALUE
},
// Wallet
{
"Tag": "SELECT",
"Focused": false,
"Value": Section.NO_VALUE
},
// Amount
{
"Tag": "INPUT",
"Focused": false,
"Value": ("Amount" in request === true && request["Amount"] !== Extension.NO_TRANSACTION_AMOUNT) ? (new BigNumber(request["Amount"])).toFixed() : Section.NO_VALUE,
"Selection Start": Section.NO_VALUE,
"Selection End": Section.NO_VALUE,
"Selection Direction": Section.NO_VALUE
},
// All
{
"Tag": "BUTTON",
"Focused": false,
"Value": Section.NO_VALUE
},
// Value
{
"Tag": "INPUT",
"Focused": false,
"Value": Section.NO_VALUE,
"Selection Start": Section.NO_VALUE,
"Selection End": Section.NO_VALUE,
"Selection Direction": Section.NO_VALUE
},
// Base fee
{
"Tag": "INPUT",
"Focused": false,
"Value": Section.NO_VALUE,
"Selection Start": Section.NO_VALUE,
"Selection End": Section.NO_VALUE,
"Selection Direction": Section.NO_VALUE
},
// Default base fee
{
"Tag": "BUTTON",
"Focused": false,
"Value": Section.NO_VALUE
},
// Message
{
"Tag": "INPUT",
"Focused": false,
"Value": ("Message" in request === true && request["Message"] !== Extension.NO_TRANSACTION_MESSAGE) ? request["Message"] : Section.NO_VALUE,
"Selection Start": Section.NO_VALUE,
"Selection End": Section.NO_VALUE,
"Selection Direction": Section.NO_VALUE
},
// Send
{
"Tag": "BUTTON",
"Focused": false,
"Value": Section.NO_VALUE
},
// Cancel
{
"Tag": "BUTTON",
"Focused": false,
"Value": Section.NO_VALUE
}
]
}
};
// Check if making first request
if(makeFirstRequest === true) {
// Add request information to beginning of list
Extension.requests.unshift(requestInformation);
}
// Otherwise
else {
// Append request information to list
Extension.requests.push(requestInformation);
}
// Trigger extension request receive event
$(document).trigger(Extension.REQUEST_RECEIVE_EVENT);
}
// Break
break;
// Default
default:
// Throw error
throw Language.getDefaultTranslation('Invalid request.');
}
}
// Maximum amount precision
static get MAXIMUM_AMOUNT_PRECISION() {
// Return maximum amount precision
return Math.log10(Consensus.VALUE_NUMBER_BASE);
}
// Minimum amount
static get MINIMUM_AMOUNT() {
// Return minimum amount
return 1 / Consensus.VALUE_NUMBER_BASE;
}
// Request receive event
static get REQUEST_RECEIVE_EVENT() {
// Return request receive event
return "ExtensionRequestReceiveEvent";
}
}
// Main function
// Set global object's extension
globalThis["Extension"] = Extension;
// Initialize extension requests
Extension.requests = [];
// Initialize extension can interrupt close
Extension.canInterruptClose = false;
// Window before unload event
$(window).on("beforeunload", function(event) {
// Check if extension can interrupt close and extension requests exist
if(Extension.canInterruptClose === true && Extension.getRequests()["length"] !== 0) {
// Try
try {
// Prevent default
event.preventDefault();
// Stop propagation
event.stopPropagation();
event.stopImmediatePropagation();
// Check if one extension request exists
if(Extension.getRequests()["length"] === 1) {
// Return message
return event["originalEvent"]["returnValue"] = Language.getTranslation('Are you sure you want to exit? There\'s a remaining transaction.');
}
// Otherwise
else {
// Return message
return event["originalEvent"]["returnValue"] = Language.getTranslation('Are you sure you want to exit? There\'s remaining transactions.');
}
}
// Catch errors
catch(error) {
}
}
});
// Check if is a Firefox or Safari extension
if(Common.isExtension() === true && typeof browser !== "undefined") {
// Message event
browser["runtime"]["onMessage"].addListener(function(request, sender, sendResponse) {
// Check if request is from the content script
if(sender["id"] === browser["runtime"]["id"] && "frameId" in sender === true && typeof request === "object" && request !== null && "Wallet Type" in request === true && "Network Type" in request === true && "Request" in request === true) {
// Check if request's wallet type is the current wallet type and network type is the current network type
if(request["Wallet Type"] === Consensus.walletTypeToText(Consensus.getWalletType()) && request["Network Type"] === Consensus.networkTypeToText(Consensus.getNetworkType())) {
// Try
try {
// Process extension request
Extension.processRequest(request);
}
// Catch errors
catch(error) {
}
}
}
});
}
// Otherwise check if is a Chrome extension
else if(Common.isExtension() === true && typeof chrome !== "undefined") {
// Message event
chrome["runtime"]["onMessage"].addListener(function(request, sender, sendResponse) {
// Check if request is from the content script
if(sender["id"] === chrome["runtime"]["id"] && "frameId" in sender === true && typeof request === "object" && request !== null && "Wallet Type" in request === true && "Network Type" in request === true && "Request" in request === true) {
// Check if request's wallet type is the current wallet type and network type is the current network type
if(request["Wallet Type"] === Consensus.walletTypeToText(Consensus.getWalletType()) && request["Network Type"] === Consensus.networkTypeToText(Consensus.getNetworkType())) {
// Try
try {
// Process extension request
Extension.processRequest(request);
}
// Catch errors
catch(error) {
}
}
}
});
}

123
scripts/fatal_error.js Executable file
View File

@@ -0,0 +1,123 @@
// Use strict
"use strict";
// Classes
// Fatal error class
class FatalError {
// Public
// Constructor
constructor(errorType = FatalError.UNKNOWN_ERROR) {
// Check if a fatal error hasn't occurred
if(FatalError.errorOccurred === false) {
// Set that a fatal error occurred
FatalError.errorOccurred = true;
// Check error type
switch(errorType) {
// Local storage error
case FatalError.LOCAL_STORAGE_ERROR:
// Log error
console.log("A local storage error occurred.");
// Break
break;
// Database error
case FatalError.DATABASE_ERROR:
// Log error
console.log("A database error occurred.");
// Break
break;
// Unknown error and default
case FatalError.UNKNOWN_ERROR:
default:
// Log error
console.log("An unknown error occurred.");
// Break
break;
}
// Log stack trace
console.trace();
// Prevent extension from interrupting on close
Extension.preventInterruptOnClose();
// Check if not an extension and not loading from file
if(Common.isExtension() === false && location["protocol"] !== Common.FILE_PROTOCOL) {
// Go to error page
location.replace(((location["protocol"] === Common.HTTPS_PROTOCOL) ? Common.HTTPS_PROTOCOL : Common.HTTP_PROTOCOL) + "//" + location["hostname"] + FatalError.ERROR_PAGE_URL);
}
// Otherwise
else {
// Close
window.close();
}
}
}
// Local storage error
static get LOCAL_STORAGE_ERROR() {
// Return local storage error
return 0;
}
// Database error
static get DATABASE_ERROR() {
// Return database error
return FatalError.LOCAL_STORAGE_ERROR + 1;
}
// Unknown error
static get UNKNOWN_ERROR() {
// Return unknown error
return FatalError.DATABASE_ERROR + 1;
}
// Private
// Error page URL
static get ERROR_PAGE_URL() {
// Return error page URL
return "/errors/error.html";
}
}
// Main function
// Set global object's fatal error
globalThis["FatalError"] = FatalError;
// Set fatal error error occurred
FatalError.errorOccurred = false;
// Window error event
$(window).on("error", function() {
// Check if using application error handler
if(usingApplicationErrorHandler() === true)
// Trigger a fatal error
new FatalError(FatalError.UNKNOWN_ERROR);
});

240
scripts/focus.js Executable file
View File

@@ -0,0 +1,240 @@
// Use strict
"use strict";
// Classes
// Focus class
class Focus {
// Public
// Constructor
constructor() {
// Set focus stack to empty array
this.focusStack = [];
// Set self
var self = this;
// Document input focus event
$(document).on("focus", "input", function() {
// Get input
var input = $(this);
// Check if input isn't having its focus restored
if(input.hasClass("focused") === false) {
// Select input
input.select();
}
});
// Document key down event
$(document).on("keydown", function(event) {
// Check if is an extension and a popup or is an app
if((Common.isExtension() === true && Common.isPopup() === true) || Common.isApp() === true) {
// Check if key tab is pressed
if(event["which"] === "\t".charCodeAt(0)) {
// Get all focusable elements
var focusableElements = $("button:not([tabindex=\"-1\"]):not(:disabled):visible, input:not([tabindex=\"-1\"]):not(:disabled):visible, select:not([tabindex=\"-1\"]):not(:disabled):visible, a:not([tabindex=\"-1\"]):not(:disabled):visible").filter(function() {
// Return if not hidden
return $(this).closest(".hide")["length"] === 0;
});
// Check if elements are focusable
if(focusableElements["length"] !== 0) {
// Check if no element is focused
if($(":focus")["length"] === 0) {
// Check if tabbing forward
if(event["shiftKey"] === false) {
// Focus on first focusable element
focusableElements.first().focus();
}
// Otherwise
else {
// Focus on last first focusable element
focusableElements.last().focus();
}
// Prevent default;
event.preventDefault();
}
// Otherwise check if tabbing forward and focused on the last focusable element
else if(event["shiftKey"] === false && focusableElements.last().is(":focus") === true) {
// Check if other elements are focusable
if(focusableElements["length"] > 1) {
// Focus on first focusable element
focusableElements.first().focus();
}
// Prevent default;
event.preventDefault();
}
// Otherwise check if tabbing backward and focused on the first focusable element
else if(event["shiftKey"] === true && focusableElements.first().is(":focus") === true) {
// Check if other elements are focusable
if(focusableElements["length"] > 1) {
// Focus on last first focusable element
focusableElements.last().focus();
}
// Prevent default;
event.preventDefault();
}
}
// Otherwise
else {
// Prevent default;
event.preventDefault();
}
}
}
});
}
// Save
save(blur) {
// Get focused element
var focusedElement = $(":focus");
// Check if no elements are focused
if(focusedElement["length"] === 0) {
// Add no focus element to focus stack
this.focusStack.push(Focus.NO_FOCUS);
// Return no focus
return Focus.NO_FOCUS;
}
// Otherwise
else {
// Add focused element to the focus stack
this.focusStack.push(focusedElement.first());
// Check if blurring
if(blur === true) {
// Remove focus from element
focusedElement.blur();
// Remove selection
Focus.removeSelection();
}
// Return focused element
return focusedElement;
}
}
// Restore
restore(blurIfNoState) {
// Check if focus stack isn't empty
if(this.focusStack["length"] > 0) {
// Get focused element from the focus stack and remove it from the focus stack
var focusedElement = this.focusStack.pop();
// Check if focused element isn't no focus
if(focusedElement !== Focus.NO_FOCUS) {
// Set that focused element is having its focus restored
focusedElement.addClass("focused");
// Focus on focused element
focusedElement.focus();
// Set that focused element isn't having its focus restored
focusedElement.removeClass("focused");
}
// Otherwise check if blurring if no state
else if(blurIfNoState === true)
// Blur focused element
$(":focus").blur();
}
}
// Delete
delete() {
// Check if focus stack isn't empty
if(this.focusStack["length"] > 0)
// Remove next focused element from the focus stack
this.focusStack.pop();
}
// Delete all
deleteAll() {
// Set focus stack to empty array
this.focusStack = [];
}
// Remove selection
static removeSelection() {
// Check if get selection is supported
if(typeof getSelection !== "undefined") {
// Get current selection
var currentSelection = getSelection();
// Check if current selection empty is supported
if(typeof currentSelection.empty !== "undefined")
// Empty current selection
currentSelection.empty();
// Otherwise check if current selection remove all ranges is supported
else if(typeof currentSelection.removeAllRanges !== "undefined")
// Remove all ranges from the current selection
currentSelection.removeAllRanges();
}
// Otherwise check if selection is supported and selection empty is supported
else if(typeof document["selection"] !== "undefined" && typeof document["selection"].empty !== "undefined")
// Empty selection
document["selection"].empty();
}
// No focus
static get NO_FOCUS() {
// Return no focus
return null;
}
}
// Main function
// Set global object's focus
globalThis["Focus"] = Focus;

19
scripts/glMatrix license.txt Executable file
View File

@@ -0,0 +1,19 @@
Copyright (c) 2015-2021, Brandon Jones, Colin MacKenzie IV.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

7860
scripts/glMatrix-3.4.1.js Executable file

File diff suppressed because it is too large Load Diff

7062
scripts/hardware_wallet.js Executable file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

80
scripts/hash.js Executable file
View File

@@ -0,0 +1,80 @@
// Use strict
"use strict";
// Classes
// Hash class
class Hash {
// Public
// Constructor
constructor(data) {
// Check if creating hash from data was successful
this.bytes = Blake2b.compute(Hash.HASH_LENGTH, Common.mergeArrays(data), new Uint8Array([]));
if(this.bytes === Blake2b.OPERATION_FAILED) {
// Throw error
throw "Creating hash failed.";
}
}
// Compare
compare(hash) {
// Go through all bytes in the hash
for(var i = 0; i < Hash.HASH_LENGTH; ++i) {
// Get bytes
var byte = this.getBytes()[i];
var otherByte = hash.getBytes()[i];
// Check if byte is greater than the other
if(byte > otherByte)
// Return sort greater than
return Common.SORT_GREATER_THAN;
// Otherwise check if byte is less than the other
else if(byte < otherByte)
// Return sort less than
return Common.SORT_LESS_THAN;
}
// Return sort equal
return Common.SORT_EQUAL;
}
// Serialize
serialize() {
// Return serialized hash
return Common.toHexString(this.getBytes());
}
// Private
// Get bytes
getBytes() {
// Return bytes
return this.bytes;
}
// Hash length
static get HASH_LENGTH() {
// Return hash length
return 32;
}
}
// Main function
// Set global object's hash
globalThis["Hash"] = Hash;

64
scripts/height.js Executable file
View File

@@ -0,0 +1,64 @@
// Use strict
"use strict";
// Classes
// Height class
class Height {
// Public
// Constructor
constructor(height, hash = Height.NO_HASH) {
// Set height
this.setHeight(height);
// Set hash
this.setHash(hash);
}
// Set height
setHeight(height) {
// Set height
this.height = height;
}
// Get height
getHeight() {
// Return height
return this.height;
}
// Set hash
setHash(hash) {
// Set hash
this.hash = hash;
}
// Get hash
getHash() {
// Return hash
return this.hash;
}
// Private
// No hash
static get NO_HASH() {
// Return no hash
return "";
}
}
// Main function
// Set global object's height
globalThis["Height"] = Height;

22
scripts/hi-base32 license.txt Executable file
View File

@@ -0,0 +1,22 @@
Copyright (c) 2015-2021 Chen, Yi-Cyuan
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

458
scripts/hi-base32-0.5.1.js Executable file
View File

@@ -0,0 +1,458 @@
/*
* [hi-base32]{@link https://github.com/emn178/hi-base32}
*
* @version 0.5.0
* @author Chen, Yi-Cyuan [emn178@gmail.com]
* @copyright Chen, Yi-Cyuan 2015-2018
* @license MIT
*/
/*jslint bitwise: true */
(function () {
'use strict';
var root = typeof window === 'object' ? window : self;
var NODE_JS = !root.HI_BASE32_NO_NODE_JS && typeof process === 'object' && process.versions && process.versions.node;
if (NODE_JS) {
root = global;
}
var COMMON_JS = !root.HI_BASE32_NO_COMMON_JS && typeof module === 'object' && module.exports;
var AMD = typeof define === 'function' && define.amd;
var BASE32_ENCODE_CHAR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'.split('');
var BASE32_DECODE_CHAR = {
'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': 4, 'F': 5, 'G': 6, 'H': 7, 'I': 8,
'J': 9, 'K': 10, 'L': 11, 'M': 12, 'N': 13, 'O': 14, 'P': 15, 'Q': 16,
'R': 17, 'S': 18, 'T': 19, 'U': 20, 'V': 21, 'W': 22, 'X': 23, 'Y': 24,
'Z': 25, '2': 26, '3': 27, '4': 28, '5': 29, '6': 30, '7': 31
};
var blocks = [0, 0, 0, 0, 0, 0, 0, 0];
var throwInvalidUtf8 = function (position, partial) {
if (partial.length > 10) {
partial = '...' + partial.substr(-10);
}
var err = new Error('Decoded data is not valid UTF-8.'
+ ' Maybe try base32.decode.asBytes()?'
+ ' Partial data after reading ' + position + ' bytes: ' + partial + ' <-');
err.position = position;
throw err;
};
var toUtf8String = function (bytes) {
var str = '', length = bytes.length, i = 0, followingChars = 0, b, c;
while (i < length) {
b = bytes[i++];
if (b <= 0x7F) {
str += String.fromCharCode(b);
continue;
} else if (b > 0xBF && b <= 0xDF) {
c = b & 0x1F;
followingChars = 1;
} else if (b <= 0xEF) {
c = b & 0x0F;
followingChars = 2;
} else if (b <= 0xF7) {
c = b & 0x07;
followingChars = 3;
} else {
throwInvalidUtf8(i, str);
}
for (var j = 0; j < followingChars; ++j) {
b = bytes[i++];
if (b < 0x80 || b > 0xBF) {
throwInvalidUtf8(i, str);
}
c <<= 6;
c += b & 0x3F;
}
if (c >= 0xD800 && c <= 0xDFFF) {
throwInvalidUtf8(i, str);
}
if (c > 0x10FFFF) {
throwInvalidUtf8(i, str);
}
if (c <= 0xFFFF) {
str += String.fromCharCode(c);
} else {
c -= 0x10000;
str += String.fromCharCode((c >> 10) + 0xD800);
str += String.fromCharCode((c & 0x3FF) + 0xDC00);
}
}
return str;
};
var decodeAsBytes = function (base32Str) {
if (base32Str === '') {
return [];
} else if (!/^[A-Z2-7=]+$/.test(base32Str)) {
throw new Error('Invalid base32 characters');
}
base32Str = base32Str.replace(/=/g, '');
var v1, v2, v3, v4, v5, v6, v7, v8, bytes = [], index = 0, length = base32Str.length;
// 4 char to 3 bytes
for (var i = 0, count = length >> 3 << 3; i < count;) {
v1 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v2 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v3 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v4 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v5 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v6 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v7 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v8 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
bytes[index++] = (v1 << 3 | v2 >>> 2) & 255;
bytes[index++] = (v2 << 6 | v3 << 1 | v4 >>> 4) & 255;
bytes[index++] = (v4 << 4 | v5 >>> 1) & 255;
bytes[index++] = (v5 << 7 | v6 << 2 | v7 >>> 3) & 255;
bytes[index++] = (v7 << 5 | v8) & 255;
}
// remain bytes
var remain = length - count;
if (remain === 2) {
v1 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v2 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
bytes[index++] = (v1 << 3 | v2 >>> 2) & 255;
} else if (remain === 4) {
v1 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v2 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v3 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v4 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
bytes[index++] = (v1 << 3 | v2 >>> 2) & 255;
bytes[index++] = (v2 << 6 | v3 << 1 | v4 >>> 4) & 255;
} else if (remain === 5) {
v1 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v2 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v3 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v4 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v5 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
bytes[index++] = (v1 << 3 | v2 >>> 2) & 255;
bytes[index++] = (v2 << 6 | v3 << 1 | v4 >>> 4) & 255;
bytes[index++] = (v4 << 4 | v5 >>> 1) & 255;
} else if (remain === 7) {
v1 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v2 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v3 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v4 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v5 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v6 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v7 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
bytes[index++] = (v1 << 3 | v2 >>> 2) & 255;
bytes[index++] = (v2 << 6 | v3 << 1 | v4 >>> 4) & 255;
bytes[index++] = (v4 << 4 | v5 >>> 1) & 255;
bytes[index++] = (v5 << 7 | v6 << 2 | v7 >>> 3) & 255;
}
return bytes;
};
var encodeAscii = function (str) {
var v1, v2, v3, v4, v5, base32Str = '', length = str.length;
for (var i = 0, count = parseInt(length / 5) * 5; i < count;) {
v1 = str.charCodeAt(i++);
v2 = str.charCodeAt(i++);
v3 = str.charCodeAt(i++);
v4 = str.charCodeAt(i++);
v5 = str.charCodeAt(i++);
base32Str += BASE32_ENCODE_CHAR[v1 >>> 3] +
BASE32_ENCODE_CHAR[(v1 << 2 | v2 >>> 6) & 31] +
BASE32_ENCODE_CHAR[(v2 >>> 1) & 31] +
BASE32_ENCODE_CHAR[(v2 << 4 | v3 >>> 4) & 31] +
BASE32_ENCODE_CHAR[(v3 << 1 | v4 >>> 7) & 31] +
BASE32_ENCODE_CHAR[(v4 >>> 2) & 31] +
BASE32_ENCODE_CHAR[(v4 << 3 | v5 >>> 5) & 31] +
BASE32_ENCODE_CHAR[v5 & 31];
}
// remain char
var remain = length - count;
if (remain === 1) {
v1 = str.charCodeAt(i);
base32Str += BASE32_ENCODE_CHAR[v1 >>> 3] +
BASE32_ENCODE_CHAR[(v1 << 2) & 31] +
'======';
} else if (remain === 2) {
v1 = str.charCodeAt(i++);
v2 = str.charCodeAt(i);
base32Str += BASE32_ENCODE_CHAR[v1 >>> 3] +
BASE32_ENCODE_CHAR[(v1 << 2 | v2 >>> 6) & 31] +
BASE32_ENCODE_CHAR[(v2 >>> 1) & 31] +
BASE32_ENCODE_CHAR[(v2 << 4) & 31] +
'====';
} else if (remain === 3) {
v1 = str.charCodeAt(i++);
v2 = str.charCodeAt(i++);
v3 = str.charCodeAt(i);
base32Str += BASE32_ENCODE_CHAR[v1 >>> 3] +
BASE32_ENCODE_CHAR[(v1 << 2 | v2 >>> 6) & 31] +
BASE32_ENCODE_CHAR[(v2 >>> 1) & 31] +
BASE32_ENCODE_CHAR[(v2 << 4 | v3 >>> 4) & 31] +
BASE32_ENCODE_CHAR[(v3 << 1) & 31] +
'===';
} else if (remain === 4) {
v1 = str.charCodeAt(i++);
v2 = str.charCodeAt(i++);
v3 = str.charCodeAt(i++);
v4 = str.charCodeAt(i);
base32Str += BASE32_ENCODE_CHAR[v1 >>> 3] +
BASE32_ENCODE_CHAR[(v1 << 2 | v2 >>> 6) & 31] +
BASE32_ENCODE_CHAR[(v2 >>> 1) & 31] +
BASE32_ENCODE_CHAR[(v2 << 4 | v3 >>> 4) & 31] +
BASE32_ENCODE_CHAR[(v3 << 1 | v4 >>> 7) & 31] +
BASE32_ENCODE_CHAR[(v4 >>> 2) & 31] +
BASE32_ENCODE_CHAR[(v4 << 3) & 31] +
'=';
}
return base32Str;
};
var encodeUtf8 = function (str) {
var v1, v2, v3, v4, v5, code, end = false, base32Str = '',
index = 0, i, start = 0, bytes = 0, length = str.length;
if (str === '') {
return base32Str;
}
do {
blocks[0] = blocks[5];
blocks[1] = blocks[6];
blocks[2] = blocks[7];
for (i = start; index < length && i < 5; ++index) {
code = str.charCodeAt(index);
if (code < 0x80) {
blocks[i++] = code;
} else if (code < 0x800) {
blocks[i++] = 0xc0 | (code >> 6);
blocks[i++] = 0x80 | (code & 0x3f);
} else if (code < 0xd800 || code >= 0xe000) {
blocks[i++] = 0xe0 | (code >> 12);
blocks[i++] = 0x80 | ((code >> 6) & 0x3f);
blocks[i++] = 0x80 | (code & 0x3f);
} else {
code = 0x10000 + (((code & 0x3ff) << 10) | (str.charCodeAt(++index) & 0x3ff));
blocks[i++] = 0xf0 | (code >> 18);
blocks[i++] = 0x80 | ((code >> 12) & 0x3f);
blocks[i++] = 0x80 | ((code >> 6) & 0x3f);
blocks[i++] = 0x80 | (code & 0x3f);
}
}
bytes += i - start;
start = i - 5;
if (index === length) {
++index;
}
if (index > length && i < 6) {
end = true;
}
v1 = blocks[0];
if (i > 4) {
v2 = blocks[1];
v3 = blocks[2];
v4 = blocks[3];
v5 = blocks[4];
base32Str += BASE32_ENCODE_CHAR[v1 >>> 3] +
BASE32_ENCODE_CHAR[(v1 << 2 | v2 >>> 6) & 31] +
BASE32_ENCODE_CHAR[(v2 >>> 1) & 31] +
BASE32_ENCODE_CHAR[(v2 << 4 | v3 >>> 4) & 31] +
BASE32_ENCODE_CHAR[(v3 << 1 | v4 >>> 7) & 31] +
BASE32_ENCODE_CHAR[(v4 >>> 2) & 31] +
BASE32_ENCODE_CHAR[(v4 << 3 | v5 >>> 5) & 31] +
BASE32_ENCODE_CHAR[v5 & 31];
} else if (i === 1) {
base32Str += BASE32_ENCODE_CHAR[v1 >>> 3] +
BASE32_ENCODE_CHAR[(v1 << 2) & 31] +
'======';
} else if (i === 2) {
v2 = blocks[1];
base32Str += BASE32_ENCODE_CHAR[v1 >>> 3] +
BASE32_ENCODE_CHAR[(v1 << 2 | v2 >>> 6) & 31] +
BASE32_ENCODE_CHAR[(v2 >>> 1) & 31] +
BASE32_ENCODE_CHAR[(v2 << 4) & 31] +
'====';
} else if (i === 3) {
v2 = blocks[1];
v3 = blocks[2];
base32Str += BASE32_ENCODE_CHAR[v1 >>> 3] +
BASE32_ENCODE_CHAR[(v1 << 2 | v2 >>> 6) & 31] +
BASE32_ENCODE_CHAR[(v2 >>> 1) & 31] +
BASE32_ENCODE_CHAR[(v2 << 4 | v3 >>> 4) & 31] +
BASE32_ENCODE_CHAR[(v3 << 1) & 31] +
'===';
} else {
v2 = blocks[1];
v3 = blocks[2];
v4 = blocks[3];
base32Str += BASE32_ENCODE_CHAR[v1 >>> 3] +
BASE32_ENCODE_CHAR[(v1 << 2 | v2 >>> 6) & 31] +
BASE32_ENCODE_CHAR[(v2 >>> 1) & 31] +
BASE32_ENCODE_CHAR[(v2 << 4 | v3 >>> 4) & 31] +
BASE32_ENCODE_CHAR[(v3 << 1 | v4 >>> 7) & 31] +
BASE32_ENCODE_CHAR[(v4 >>> 2) & 31] +
BASE32_ENCODE_CHAR[(v4 << 3) & 31] +
'=';
}
} while (!end);
return base32Str;
};
var encodeBytes = function (bytes) {
var v1, v2, v3, v4, v5, base32Str = '', length = bytes.length;
for (var i = 0, count = parseInt(length / 5) * 5; i < count;) {
v1 = bytes[i++];
v2 = bytes[i++];
v3 = bytes[i++];
v4 = bytes[i++];
v5 = bytes[i++];
base32Str += BASE32_ENCODE_CHAR[v1 >>> 3] +
BASE32_ENCODE_CHAR[(v1 << 2 | v2 >>> 6) & 31] +
BASE32_ENCODE_CHAR[(v2 >>> 1) & 31] +
BASE32_ENCODE_CHAR[(v2 << 4 | v3 >>> 4) & 31] +
BASE32_ENCODE_CHAR[(v3 << 1 | v4 >>> 7) & 31] +
BASE32_ENCODE_CHAR[(v4 >>> 2) & 31] +
BASE32_ENCODE_CHAR[(v4 << 3 | v5 >>> 5) & 31] +
BASE32_ENCODE_CHAR[v5 & 31];
}
// remain char
var remain = length - count;
if (remain === 1) {
v1 = bytes[i];
base32Str += BASE32_ENCODE_CHAR[v1 >>> 3] +
BASE32_ENCODE_CHAR[(v1 << 2) & 31] +
'======';
} else if (remain === 2) {
v1 = bytes[i++];
v2 = bytes[i];
base32Str += BASE32_ENCODE_CHAR[v1 >>> 3] +
BASE32_ENCODE_CHAR[(v1 << 2 | v2 >>> 6) & 31] +
BASE32_ENCODE_CHAR[(v2 >>> 1) & 31] +
BASE32_ENCODE_CHAR[(v2 << 4) & 31] +
'====';
} else if (remain === 3) {
v1 = bytes[i++];
v2 = bytes[i++];
v3 = bytes[i];
base32Str += BASE32_ENCODE_CHAR[v1 >>> 3] +
BASE32_ENCODE_CHAR[(v1 << 2 | v2 >>> 6) & 31] +
BASE32_ENCODE_CHAR[(v2 >>> 1) & 31] +
BASE32_ENCODE_CHAR[(v2 << 4 | v3 >>> 4) & 31] +
BASE32_ENCODE_CHAR[(v3 << 1) & 31] +
'===';
} else if (remain === 4) {
v1 = bytes[i++];
v2 = bytes[i++];
v3 = bytes[i++];
v4 = bytes[i];
base32Str += BASE32_ENCODE_CHAR[v1 >>> 3] +
BASE32_ENCODE_CHAR[(v1 << 2 | v2 >>> 6) & 31] +
BASE32_ENCODE_CHAR[(v2 >>> 1) & 31] +
BASE32_ENCODE_CHAR[(v2 << 4 | v3 >>> 4) & 31] +
BASE32_ENCODE_CHAR[(v3 << 1 | v4 >>> 7) & 31] +
BASE32_ENCODE_CHAR[(v4 >>> 2) & 31] +
BASE32_ENCODE_CHAR[(v4 << 3) & 31] +
'=';
}
return base32Str;
};
var encode = function (input, asciiOnly) {
var notString = typeof(input) !== 'string';
if (notString && input.constructor === ArrayBuffer) {
input = new Uint8Array(input);
}
if (notString) {
return encodeBytes(input);
} else if (asciiOnly) {
return encodeAscii(input);
} else {
return encodeUtf8(input);
}
};
var decode = function (base32Str, asciiOnly) {
if (!asciiOnly) {
return toUtf8String(decodeAsBytes(base32Str));
}
if (base32Str === '') {
return '';
} else if (!/^[A-Z2-7=]+$/.test(base32Str)) {
throw new Error('Invalid base32 characters');
}
var v1, v2, v3, v4, v5, v6, v7, v8, str = '', length = base32Str.indexOf('=');
if (length === -1) {
length = base32Str.length;
}
// 8 char to 5 bytes
for (var i = 0, count = length >> 3 << 3; i < count;) {
v1 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v2 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v3 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v4 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v5 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v6 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v7 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v8 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
str += String.fromCharCode((v1 << 3 | v2 >>> 2) & 255) +
String.fromCharCode((v2 << 6 | v3 << 1 | v4 >>> 4) & 255) +
String.fromCharCode((v4 << 4 | v5 >>> 1) & 255) +
String.fromCharCode((v5 << 7 | v6 << 2 | v7 >>> 3) & 255) +
String.fromCharCode((v7 << 5 | v8) & 255);
}
// remain bytes
var remain = length - count;
if (remain === 2) {
v1 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v2 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
str += String.fromCharCode((v1 << 3 | v2 >>> 2) & 255);
} else if (remain === 4) {
v1 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v2 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v3 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v4 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
str += String.fromCharCode((v1 << 3 | v2 >>> 2) & 255) +
String.fromCharCode((v2 << 6 | v3 << 1 | v4 >>> 4) & 255);
} else if (remain === 5) {
v1 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v2 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v3 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v4 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v5 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
str += String.fromCharCode((v1 << 3 | v2 >>> 2) & 255) +
String.fromCharCode((v2 << 6 | v3 << 1 | v4 >>> 4) & 255) +
String.fromCharCode((v4 << 4 | v5 >>> 1) & 255);
} else if (remain === 7) {
v1 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v2 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v3 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v4 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v5 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v6 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
v7 = BASE32_DECODE_CHAR[base32Str.charAt(i++)];
str += String.fromCharCode((v1 << 3 | v2 >>> 2) & 255) +
String.fromCharCode((v2 << 6 | v3 << 1 | v4 >>> 4) & 255) +
String.fromCharCode((v4 << 4 | v5 >>> 1) & 255) +
String.fromCharCode((v5 << 7 | v6 << 2 | v7 >>> 3) & 255);
}
return str;
};
var exports = {
encode: encode,
decode: decode
};
decode.asBytes = decodeAsBytes;
if (COMMON_JS) {
module.exports = exports;
} else {
root.base32 = exports;
if (AMD) {
define(function() {
return exports;
});
}
}
})();

437
scripts/identifier.js Executable file
View File

@@ -0,0 +1,437 @@
// Use strict
"use strict";
// Classes
// Identifier class
class Identifier {
// Public
// Constructor
constructor(serializedIdentifier = Identifier.DEFAULT_SERIALIZED_IDENTIFIER) {
// Set depth
this.depth = 0;
// Set paths
this.paths = new Uint32Array(Identifier.MAX_DEPTH);
// Set value to serialized identifier
this.setValue(serializedIdentifier);
}
// Get depth
getDepth() {
// Return depth
return this.depth;
}
// Get paths
getPaths() {
// Return paths
return this.paths;
}
// Set value
setValue(serializedIdentifierOrDepth, firstValue, secondValue, thirdValue, fourthValue) {
// Check if value is provided in a serialized format
if(typeof serializedIdentifierOrDepth === "string") {
// Get serialized identifier
var serializedIdentifier = serializedIdentifierOrDepth;
// Check if serialized identifier ia a hex string
if(Common.isHexString(serializedIdentifier) === true) {
// Get serialized value
var serializedValue = Common.fromHexString(serializedIdentifier);
// Check if serialized value is valid
if(serializedValue["length"] === Identifier.LENGTH) {
// Set depth
this.depth = Math.min(serializedValue[Identifier.DEPTH_INDEX], Identifier.MAX_DEPTH);
// Go through all paths
var serializedValueDataView = new DataView(serializedValue["buffer"]);
for(var i = 0; i < this.getPaths()["length"]; ++i)
// Set path
this.paths[i] = serializedValueDataView.getUint32(Identifier.PATHS_INDEX + i * Uint32Array["BYTES_PER_ELEMENT"], false);
}
// Otherwise
else {
// Throw error
throw "Invalid identifier.";
}
}
// Otherwise
else {
// Throw error
throw "Invalid identifier.";
}
}
// Otherwise
else {
// Get depth
var depth = serializedIdentifierOrDepth;
// Check if depth is valid
if(depth <= Identifier.MAX_DEPTH) {
// Set depth
this.depth = depth;
// Check if paths are provided as an array
if(firstValue instanceof Uint32Array === true) {
// Get paths
var paths = firstValue;
// Check if paths are valid
if(paths["length"] === this.getPaths()["length"]) {
// Go through all paths
for(var i = 0; i < this.getPaths()["length"]; ++i) {
// Set path to path
this.paths[i] = paths[i];
}
}
// Otherwise
else {
// Throw error
throw "Invalid identifier.";
}
}
// Otherwise
else {
// Set paths
this.paths[0] = firstValue;
this.paths[1] = secondValue;
this.paths[2] = thirdValue;
this.paths[3] = fourthValue;
}
}
// Otherwise
else {
// Throw error
throw "Invalid identifier.";
}
}
}
// Get value
getValue() {
// Initialize buffer
var buffer = new Uint8Array(Identifier.LENGTH);
// Set buffer's depth
buffer[Identifier.DEPTH_INDEX] = this.getDepth();
// Go through all paths
var bufferView = new DataView(buffer["buffer"]);
for(var i = 0; i < this.getPaths()["length"]; ++i)
// Set buffer's path
bufferView.setUint32(Identifier.PATHS_INDEX + i * Uint32Array["BYTES_PER_ELEMENT"], this.getPaths()[i], false);
// Return buffer
return buffer;
}
// Equals value
equalsValue(identifier) {
// Check if depths differ
if(this.getDepth() !== identifier.getDepth())
// Return false
return false;
// Return if paths are equal
return Common.arraysAreEqual(this.getPaths(), identifier.getPaths() === true);
}
// Includes value
includesValue(identifier) {
// Check if depths differ
if(this.getDepth() !== identifier.getDepth())
// Return false
return false;
// Return if last path is greater than or equal to the value's last path
return this.getLastPath() >= identifier.getLastPath();
}
// Get last path index
getLastPath() {
// Return last path
return (this.getDepth() === 0) ? 0 : this.getPaths()[this.getDepth() - 1];
}
// Get next
getNext(height = Identifier.NO_HEIGHT) {
// Create next as a clone of self
var next = this.clone();
// Increment next's last path to value
++next.paths[next.getDepth() - 1];
// Check if height exists
if(height !== Identifier.NO_HEIGHT) {
// Check wallet type
switch(Consensus.getWalletType()) {
// MWC wallet
case Consensus.MWC_WALLET_TYPE:
// Set next's height path as the height limited by its maximum value
next.paths[Identifier.HEIGHT_PATH_INDEX] = Math.max(height.modulo(Identifier.MAXIMUM_HEIGHT + 1).toNumber(), 1);
// Break
break;
}
}
// Return next
return next;
}
// Get parent
getParent() {
// Create parent as a clone of self
var parent = this.clone();
// Check if previous depth exists
if(this.getDepth() > 0) {
// Clear parent's last path
parent.paths[parent.getDepth() - 1] = 0;
// Decrement parent's depth
--parent.depth;
}
// Return parent
return parent;
}
// Get child
getChild(height = Identifier.NO_HEIGHT) {
// Create child as a clone of self
var child = this.clone();
// Check if next depth exists
if(this.getDepth() < Identifier.MAX_DEPTH) {
// Increment child's depth
++child.depth;
}
// Check if height exists
if(height !== Identifier.NO_HEIGHT) {
// Check wallet type
switch(Consensus.getWalletType()) {
// MWC wallet
case Consensus.MWC_WALLET_TYPE:
// Set child's height path as the height limited by its maximum value
child.paths[Identifier.HEIGHT_PATH_INDEX] = Math.max(height.modulo(Identifier.MAXIMUM_HEIGHT + 1).toNumber(), 1);
// Break
break;
}
}
// Return child
return child;
}
// Get height
getHeight() {
// Check wallet type
switch(Consensus.getWalletType()) {
// MWC wallet
case Consensus.MWC_WALLET_TYPE:
// Get height from height path
var height = this.getPaths()[Identifier.HEIGHT_PATH_INDEX];
// Check if height exists
if(height !== Consensus.FIRST_BLOCK_HEIGHT) {
// Return height
return new BigNumber(height);
}
// Otherwise
else {
// Return no height
return Identifier.NO_HEIGHT;
}
}
// Return no height
return Identifier.NO_HEIGHT;
}
// Remove extras
removeExtras() {
// Create copy as a clone of self
var copy = this.clone();
// Check wallet type
switch(Consensus.getWalletType()) {
// MWC wallet
case Consensus.MWC_WALLET_TYPE:
// Set copy's height path to not exist
copy.paths[Identifier.HEIGHT_PATH_INDEX] = Consensus.FIRST_BLOCK_HEIGHT;
// Break
break;
}
// Return copy
return copy;
}
// Is path hardened
static isPathHardened(path) {
// Return if path is hardened
return (path & Identifier.PATH_HARDENED_MASK) !== 0;
}
// Length
static get LENGTH() {
// Return length
return 1 * Uint8Array["BYTES_PER_ELEMENT"] + Identifier.MAX_DEPTH * Uint32Array["BYTES_PER_ELEMENT"];
}
// Max depth
static get MAX_DEPTH() {
// Return max depth
return 4;
}
// Root serialized identifier
static get ROOT_SERIALIZED_IDENTIFIER() {
// Return root serialized identifier
return "0000000000000000000000000000000000";
}
// Paths index
static get PATHS_INDEX() {
// Return paths index
return Identifier.DEPTH_INDEX + 1;
}
// No identifier
static get NO_IDENTIFIER() {
// Return no identifier
return null;
}
// No heights
static get NO_HEIGHT() {
// Return no height
return null;
}
// Maximum height
static get MAXIMUM_HEIGHT() {
// Return maximum height
return Common.UINT32_MAX_VALUE;
}
// Private
// Clone
clone() {
// Create a copy of self
var copy = new Identifier();
copy.setValue(this.getDepth(), this.getPaths());
// Return copy
return copy;
}
// Default serialized identifier
static get DEFAULT_SERIALIZED_IDENTIFIER() {
// Return default serialized identifier
return "0200000000000000000000000000000000";
}
// Depth index
static get DEPTH_INDEX() {
// Return depth index
return 0;
}
// Path hardened mask
static get PATH_HARDENED_MASK() {
// Return path hardened mask
return 0x80000000;
}
// Height path index
static get HEIGHT_PATH_INDEX() {
// Return height path index
return Identifier.MAX_DEPTH - 1;
}
}
// Main function
// Set global object's identifier
globalThis["Identifier"] = Identifier;

View File

@@ -0,0 +1,132 @@
// Use strict
"use strict";
// Classes
// Initial heights obtained class
class InitialHeightsObtained {
// Public
// Constructor
constructor(node) {
// Create database
Database.createDatabase(function(database, currentVersion, databaseTransaction) {
// Create or get initial heights obtained object store
var initialHeightsObtainedObjectStore = (currentVersion === Database.NO_CURRENT_VERSION) ? database.createObjectStore(InitialHeightsObtained.OBJECT_STORE_NAME, {
// Key path
"keyPath": [
// Wallet type
Database.toKeyPath(InitialHeightsObtained.DATABASE_WALLET_TYPE_NAME),
// Network type
Database.toKeyPath(InitialHeightsObtained.DATABASE_NETWORK_TYPE_NAME)
]
}) : databaseTransaction.objectStore(InitialHeightsObtained.OBJECT_STORE_NAME);
});
}
// Get obtained
getObtained() {
// Return promise
return new Promise(function(resolve, reject) {
// Return getting the initial heights obtained with the wallet type and network type in the database
return Database.getResults(InitialHeightsObtained.OBJECT_STORE_NAME, 0, 1, Database.NO_INDEX, IDBKeyRange.only([
// Wallet type
Consensus.getWalletType(),
// Network type
Consensus.getNetworkType(),
])).then(function(results) {
// Check if initial heights were obtained
if(results["length"] !== 0) {
// Resolve true
resolve(true);
}
// Otherwise
else {
// Resolve false
resolve(false);
}
// Catch errors
}).catch(function(error) {
// Reject error
reject("The database failed.");
});
});
}
// Set obtained
setObtained() {
// Return promise
return new Promise(function(resolve, reject) {
// Save initial heights obtained for the wallet type and network type in the database
Database.saveResults(InitialHeightsObtained.OBJECT_STORE_NAME, [{
// Wallet type
[Database.toKeyPath(InitialHeightsObtained.DATABASE_WALLET_TYPE_NAME)]: Consensus.getWalletType(),
// Network type
[Database.toKeyPath(InitialHeightsObtained.DATABASE_NETWORK_TYPE_NAME)]: Consensus.getNetworkType()
}], [], Database.CREATE_NEW_TRANSACTION, Database.STRICT_DURABILITY).then(function() {
// Resolve
resolve();
// Catch errors
}).catch(function(error) {
// Reject error
reject("The database failed.");
});
});
}
// Private
// Object store name
static get OBJECT_STORE_NAME() {
// Return object store name
return "Initial Heights Obtained";
}
// Database wallet type name
static get DATABASE_WALLET_TYPE_NAME() {
// Return database wallet type name
return "Wallet Type";
}
// Database network type name
static get DATABASE_NETWORK_TYPE_NAME() {
// Return database network type name
return "Network Type";
}
}
// Main function
// Set global object's initial heights obtained
globalThis["InitialHeightsObtained"] = InitialHeightsObtained;

353
scripts/install_app.js Executable file
View File

@@ -0,0 +1,353 @@
// Use strict
"use strict";
// Classes
// Install app class
class InstallApp {
// Public
// Constructor
constructor(cookieAcceptance, automaticLock) {
// Set automatic lock
this.automaticLock = automaticLock;
// Get install app display
this.installAppDisplay = $("section.installApp");
// Get install now button
this.installNowButton = this.installAppDisplay.find("button.installNow");
// Get remind me later button
this.remindMeLaterButton = this.installAppDisplay.find("button.remindMeLater");
// Set can show
this.canShow = false;
// Set was installed
this.wasInstalled = false;
// Set cookie acceptance is hidden
this.cookieAcceptanceIsHidden = false;
// Set self
var self = this;
// Cookie acceptance is hidden event
$(cookieAcceptance).one(CookieAcceptance.IS_HIDDEN_EVENT, function() {
// Set timeout
setTimeout(function() {
// Set cookie acceptance is hidden
self.cookieAcceptanceIsHidden = true;
// Can if can show
if(self.canShow === true)
// Show
self.show();
}, InstallApp.COOKIE_ACCEPTANCE_HIDE_BEFORE_SHOW_DELAY_MILLISECONDS);
});
// Window before install prompt event
$(window).on("beforeinstallprompt", function(event) {
// Prevent default
event.preventDefault();
// Store install app prompt
installAppPrompt = event["originalEvent"];
// Can if can show
if(self.canShow === true)
// Show
self.show();
});
// Install app display transaition end event
this.installAppDisplay.on("transitionend", function() {
// Check if install app display is hiding
if(self.installAppDisplay.hasClass("hide") === true)
// Prevent focus on install app display's elements
self.installAppDisplay.addClass("noFocus");
});
// Window app installed event
$(window).on("appinstalled", function(event) {
// Hide
self.hide();
});
// Window storage event
$(window).on("storage", function(event) {
// Check if remind me later timestamp was changed
if(event["originalEvent"]["key"] === InstallApp.INSTALL_APP_REMIND_ME_LATER_TIMESTAMP_LOCAL_STORAGE_NAME)
// Hide
self.hide();
});
// Install now button click event
this.installNowButton.on("click", function() {
// Check if the install app prompt exists
if(installAppPrompt !== InstallApp.NO_INSTALL_APP_PROMPT) {
// Get if automatic lock is enabled
var automaticLockEnabled = self.automaticLock.getAllowed() !== 0;
// Check if automatic lock is enabled
if(automaticLockEnabled === true) {
// Prevent automatic lock
self.automaticLock.prevent();
}
// Prompt to install app
installAppPrompt.prompt();
// Get if app was installed
installAppPrompt["userChoice"].then(function(result) {
// Check if automatic lock is enabled
if(automaticLockEnabled === true) {
// Allow automatic lock
self.automaticLock.allow();
}
// Check if app was installed
if(result["outcome"] === InstallApp.APP_INSTALLED_OUTCOME) {
// Set was installed
self.wasInstalled = true;
// Hide
self.hide();
}
// Catch errors
}).catch(function(error) {
// Check if automatic lock is enabled
if(automaticLockEnabled === true) {
// Allow automatic lock
self.automaticLock.allow();
}
});
}
});
// Remind me later button click event
this.remindMeLaterButton.on("click", function() {
// Hide
self.hide();
// Try
try {
// Save current timestamp as the remind me later timestamp
localStorage.setItem(InstallApp.INSTALL_APP_REMIND_ME_LATER_TIMESTAMP_LOCAL_STORAGE_NAME, Common.getCurrentTimestamp().toFixed());
}
// Catch errors
catch(error) {
// Trigger a fatal error
new FatalError(FatalError.LOCAL_STORAGE_ERROR);
}
// Remind me later hover in event
}).hover(function() {
// Check if can hover
if(typeof matchMedia === "function" && matchMedia("(any-hover: hover)")["matches"] === true) {
// Get element
var element = $(this);
// Check if element's text is shown
if(element.children().is(":visible") === true) {
// Save element's title
element.attr(Common.DATA_ATTRIBUTE_PREFIX + "title", element.attr("title"));
// Remove element's title
element.removeAttr("title");
}
}
// Remind me later hover out event
}, function() {
// Check if can hover
if(typeof matchMedia === "function" && matchMedia("(any-hover: hover)")["matches"] === true) {
// Get element
var element = $(this);
// Check if element isn't focused
if(element.is(":focus") === false) {
// Check if element's title is saved
if(element.attr(Common.DATA_ATTRIBUTE_PREFIX + "title") !== Common.NO_ATTRIBUTE) {
// Restore element's title
element.attr("title", element.attr(Common.DATA_ATTRIBUTE_PREFIX + "title"));
// Remove element's saved title
element.removeAttr(Common.DATA_ATTRIBUTE_PREFIX + "title");
}
}
}
// Remind me later focus event
}).on("focus", function() {
// Get element
var element = $(this);
// Check if element's text is shown
if(element.children().is(":visible") === true) {
// Save element's title
element.attr(Common.DATA_ATTRIBUTE_PREFIX + "title", element.attr("title"));
// Remove element's title
element.removeAttr("title");
}
// Remind me later blur event
}).on("blur", function() {
// Get element
var element = $(this);
// Check if can't hover or element isn't hovered
if((typeof matchMedia !== "function" || matchMedia("(any-hover: hover)")["matches"] === false) || element.is(":hover") === false) {
// Check if element's title is saved
if(element.attr(Common.DATA_ATTRIBUTE_PREFIX + "title") !== Common.NO_ATTRIBUTE) {
// Restore element's title
element.attr("title", element.attr(Common.DATA_ATTRIBUTE_PREFIX + "title"));
// Remove element's saved title
element.removeAttr(Common.DATA_ATTRIBUTE_PREFIX + "title");
}
}
});
}
// Show
show() {
// Set can show
this.canShow = true;
// Check if not an app or extension and not loading from file
if(Common.isApp() === false && Common.isExtension() === false && location["protocol"] !== Common.FILE_PROTOCOL) {
// Check if the install app prompt exists, cookie acceptance is hidden, and wasn't installed
if(installAppPrompt !== InstallApp.NO_INSTALL_APP_PROMPT && this.cookieAcceptanceIsHidden === true && this.wasInstalled === false) {
// Get remind me later timestamp
var remindMeLaterTimestamp = localStorage.getItem(InstallApp.INSTALL_APP_REMIND_ME_LATER_TIMESTAMP_LOCAL_STORAGE_NAME);
// Check if it's time to remind about installing the app
if(remindMeLaterTimestamp === Common.INVALID_LOCAL_STORAGE_ITEM || parseInt(remindMeLaterTimestamp, Common.DECIMAL_NUMBER_BASE) <= Common.getCurrentTimestamp() - InstallApp.REMIND_ME_LATER_DURATION_SECONDS) {
// Show install app display and make it so that its elements can be focused
this.installAppDisplay.removeClass("hide noFocus");
// Return true
return true;
}
}
}
// Return false
return false;
}
// No install app prompt
static get NO_INSTALL_APP_PROMPT() {
// Return no install app prompt
return null;
}
// Private
// Hide
hide() {
// Set install app prompt to no install app prompt
this.installAppPrompt = InstallApp.NO_INSTALL_APP_PROMPT;
// Hide install app display
this.installAppDisplay.addClass("hide");
}
// Remind me later duration seconds
static get REMIND_ME_LATER_DURATION_SECONDS() {
// Return remind me later duration seconds
return 90 * Common.HOURS_IN_A_DAY * Common.MINUTES_IN_AN_HOUR * Common.SECONDS_IN_A_MINUTE;
}
// Install app remind me later timestamp local storage name
static get INSTALL_APP_REMIND_ME_LATER_TIMESTAMP_LOCAL_STORAGE_NAME() {
// Return install app remind me later timestamp local storage name
return "Install App Remind Me Later Timestamp";
}
// App install outcome
static get APP_INSTALLED_OUTCOME() {
// Return app installed outcome
return "accepted";
}
// Return cookie acceptance hide before show delay milliseconds
static get COOKIE_ACCEPTANCE_HIDE_BEFORE_SHOW_DELAY_MILLISECONDS() {
// Return cookie acceptance hide before show delay milliseconds
return 100;
}
}
// Global variables
// Install app prompt
var installAppPrompt = InstallApp.NO_INSTALL_APP_PROMPT;
// Main function
// Set global object's install app
globalThis["InstallApp"] = InstallApp;
// Window before install prompt event
$(window).on("beforeinstallprompt", function(event) {
// Prevent default
event.preventDefault();
// Store install app prompt
installAppPrompt = event["originalEvent"];
});

268
scripts/instance.js Executable file
View File

@@ -0,0 +1,268 @@
// Use strict
"use strict";
// Classes
// Instance class
class Instance {
// Public
// Constructor
constructor() {
// Set current instance ID to random value
this.currentInstanceId = Math.random().toFixed(Instance.MAX_FIXED_NUMBER_OF_DECIMAL_PLACES);
// Set primary instance ID to stored value
this.primaryInstanceId = localStorage.getItem(Instance.PRIMARY_INSTANCE_ID_LOCAL_STORAGE_NAME);
// Set check primary instance timeout
this.checkPrimaryInstanceTimeout = Instance.NO_TIMEOUT;
// Set self
var self = this;
// Try
try {
// Save current instance ID as the primary instance ID
localStorage.setItem(Instance.PRIMARY_INSTANCE_ID_LOCAL_STORAGE_NAME, this.currentInstanceId);
}
// Catch errors
catch(error) {
// Throw error
throw "Local storage failed.";
}
// Set check primary instance timeout
this.checkPrimaryInstanceTimeout = setTimeout(function() {
// Check if primary instance
self.checkIfPrimaryInstance();
}, Instance.CHECK_IF_PRIMARY_INSTANCE_DELAY_MILLISECONDS);
// Window storage instance event
$(window).on("storage.instance", function(event) {
// Check if primary instance ID was changed
if(event["originalEvent"]["key"] === Instance.PRIMARY_INSTANCE_ID_LOCAL_STORAGE_NAME) {
// Check if primary instance was closed
if(event["originalEvent"]["newValue"] === null || event["originalEvent"]["newValue"] === "") {
// Try
try {
// Save current instance ID as the primary instance ID
localStorage.setItem(Instance.PRIMARY_INSTANCE_ID_LOCAL_STORAGE_NAME, self.currentInstanceId);
}
// Catch errors
catch(error) {
// Return
return;
}
// Check if check primary instance timeout exists
if(self.checkPrimaryInstanceTimeout !== Instance.NO_TIMEOUT) {
// Clear check primary instance timeout
clearTimeout(self.checkPrimaryInstanceTimeout);
// Clear check primary instance timeout
self.checkPrimaryInstanceTimeout = Instance.NO_TIMEOUT;
}
// Set check primary instance timeout
self.checkPrimaryInstanceTimeout = setTimeout(function() {
// Check if primary instance
self.checkIfPrimaryInstance();
}, Instance.CHECK_IF_PRIMARY_INSTANCE_DELAY_MILLISECONDS);
}
// Otherwise check if current instance ID is the primary instance ID and a new instance is trying to become the primary instance
else if(self.currentInstanceId === self.primaryInstanceId && event["originalEvent"]["newValue"] !== self.currentInstanceId) {
// Try
try {
// Save current instance ID as the primary instance ID
localStorage.setItem(Instance.PRIMARY_INSTANCE_ID_LOCAL_STORAGE_NAME, self.currentInstanceId);
}
// Catch errors
catch(error) {
// Trigger a fatal error
new FatalError(FatalError.LOCAL_STORAGE_ERROR);
}
}
// Otherwise check if new instance isn't the current instance ID
else if(event["originalEvent"]["newValue"] !== self.currentInstanceId)
// Update primary instance ID
self.primaryInstanceId = event["originalEvent"]["newValue"];
}
// Window focus instance event
}).on("focus.instance", function() {
// Check if current instance ID isn't the primary instance ID
if(self.currentInstanceId !== self.primaryInstanceId) {
// Set timeout
setTimeout(function() {
// Try
try {
// Save current instance ID as the primary instance ID
localStorage.setItem(Instance.PRIMARY_INSTANCE_ID_LOCAL_STORAGE_NAME, self.currentInstanceId);
}
// Catch errors
catch(error) {
// Return
return;
}
// Check if check primary instance timeout exists
if(self.checkPrimaryInstanceTimeout !== Instance.NO_TIMEOUT) {
// Clear check primary instance timeout
clearTimeout(self.checkPrimaryInstanceTimeout);
// Clear check primary instance timeout
self.checkPrimaryInstanceTimeout = Instance.NO_TIMEOUT;
}
// Set check primary instance timeout
self.checkPrimaryInstanceTimeout = setTimeout(function() {
// Check if primary instance
self.checkIfPrimaryInstance();
}, Instance.CHECK_IF_PRIMARY_INSTANCE_DELAY_MILLISECONDS);
}, Instance.FOCUS_DELAY_MILLISECONDS);
}
// Window before unload instance and unload instance event
}).on("beforeunload.instance unload.instance", function() {
// Turn off window before unload instance and unload instance event
$(window).off("beforeunload.instance unload.instance");
// Turn off window storage instance event
$(window).off("storage.instance");
// Turn off window focus instance event
$(window).off("focus.instance");
// Check if current instance ID is the primary instance ID
if(self.currentInstanceId === self.primaryInstanceId)
// Remove saved primary instance ID
localStorage.removeItem(Instance.PRIMARY_INSTANCE_ID_LOCAL_STORAGE_NAME);
});
}
// Is primary instance
isPrimaryInstance() {
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Set timeout
setTimeout(function() {
// Resolve if current instance ID is the primary instance ID
resolve(self.currentInstanceId === self.primaryInstanceId);
}, Instance.CHECK_IF_PRIMARY_INSTANCE_DELAY_MILLISECONDS);
});
}
// Is primary instance event
static get IS_PRIMARY_INSTANCE_EVENT() {
// Return is primary instance event
return "InstanceIsPrimaryInstanceEvent";
}
// Private
// Check if primary instance
checkIfPrimaryInstance() {
// Clear check primary instance timeout
this.checkPrimaryInstanceTimeout = Instance.NO_TIMEOUT;
// Get the saved primary instance ID
var savedPrimaryInstanceId = localStorage.getItem(Instance.PRIMARY_INSTANCE_ID_LOCAL_STORAGE_NAME);
// Check if current instance ID is the saved primary instance ID
if(savedPrimaryInstanceId !== Common.INVALID_LOCAL_STORAGE_ITEM && this.currentInstanceId === savedPrimaryInstanceId) {
// Set primary instance ID to current instance ID
this.primaryInstanceId = this.currentInstanceId;
// Trigger is primary instance event
$(this).trigger(Instance.IS_PRIMARY_INSTANCE_EVENT);
}
}
// Primary instance ID local storage name
static get PRIMARY_INSTANCE_ID_LOCAL_STORAGE_NAME() {
// Return primary instance ID local storage name
return "Primary Instance ID";
}
// Check if primary instance delay milliseconds
static get CHECK_IF_PRIMARY_INSTANCE_DELAY_MILLISECONDS() {
// Return check if primary instance delay milliseconds
return 600;
}
// Focus delay milliseconds
static get FOCUS_DELAY_MILLISECONDS() {
// Return focus delay milliseconds
return 100;
}
// No timeout
static get NO_TIMEOUT() {
// Return no timeout
return null;
}
// Max fixed number of decimal places
static get MAX_FIXED_NUMBER_OF_DECIMAL_PLACES() {
// Return max fixed number of decimal places
return 20;
}
}
// Main function
// Set global object's instance
globalThis["Instance"] = Instance;

226
scripts/interaction.js Executable file
View File

@@ -0,0 +1,226 @@
// Use strict
"use strict";
// Classes
// Interaction class
class Interaction {
// Public
// Constructor
constructor(index, urlOrWalletKeyPath, api, type, data, listener = Interaction.NO_LISTENER) {
// Check if a URL is provided
if(typeof urlOrWalletKeyPath === "string") {
// Set URL
var url = urlOrWalletKeyPath;
// Set wallet key path
var walletKeyPath = Interaction.NO_WALLET_KEY_PATH;
}
// Otherwise
else {
// Set URL
var url = Interaction.NO_URL;
// Set wallet key path
var walletKeyPath = urlOrWalletKeyPath;
}
// Set index
this.index = index;
// Set URL
this.url = url;
// Set wallet key path
this.walletKeyPath = walletKeyPath;
// Set API
this.api = api;
// Set type
this.type = type;
// Set data
this.data = data;
// Set listener
this.listener = listener;
// Set canceled
this.canceled = false;
}
// Get URL
getUrl() {
// Return URL
return this.url;
}
// Get wallet key path
getWalletKeyPath() {
// Return wallet key path
return this.walletKeyPath;
}
// Get API
getApi() {
// Return API
return this.api;
}
// Get type
getType() {
// Return type
return this.type;
}
// Get data
getData() {
// Return data
return this.data;
}
// Set canceled
setCanceled() {
// Set canceled
this.canceled = true;
}
// Is canceled
isCanceled() {
// Return if canceled
return this.canceled === true;
}
// Respond
respond(response) {
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Check if canceled
if(self.isCanceled() === true) {
// Reject error
reject("Interaction canceled.");
}
// Otherwise check if a listener is used
else if(self.listener !== Interaction.NO_LISTENER) {
// Return responding with data to listener
return self.listener.respondWithData(self.index, response).then(function(status) {
// Resolve status
resolve(status);
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
}
// Otherwise
else {
// Resolve
resolve();
}
});
}
// Cancel
cancel(response) {
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Check if canceled
if(self.isCanceled() === true) {
// Reject error
reject("Interaction canceled.");
}
// Otherwise check if a listener is used
else if(self.listener !== Interaction.NO_LISTENER) {
// Return responding with error to listener
return self.listener.respondWithError(self.index, response).then(function(status) {
// Resolve status
resolve(status);
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
}
// Otherwise
else {
// Resolve
resolve();
}
});
}
// No index
static get NO_INDEX() {
// Return no index
return null;
}
// No listener
static get NO_LISTENER() {
// Return no listener
return null;
}
// No URL
static get NO_URL() {
// Return no URL
return null;
}
// No wallet key path
static get NO_WALLET_KEY_PATH() {
// Return no wallet key path
return null;
}
}
// Main function
// Set global object's interaction
globalThis["Interaction"] = Interaction;

20
scripts/jQuery license.txt Executable file
View File

@@ -0,0 +1,20 @@
Copyright OpenJS Foundation and other contributors, https://openjsf.org/
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

10965
scripts/jQuery-3.6.4.js Executable file

File diff suppressed because it is too large Load Diff

22
scripts/js-sha256 license.txt Executable file
View File

@@ -0,0 +1,22 @@
Copyright (c) 2014-2017 Chen, Yi-Cyuan
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

527
scripts/js-sha256-0.10.0.js Executable file
View File

@@ -0,0 +1,527 @@
/**
* [js-sha256]{@link https://github.com/emn178/js-sha256}
*
* @version 0.10.0
* @author Chen, Yi-Cyuan [emn178@gmail.com]
* @copyright Chen, Yi-Cyuan 2014-2023
* @license MIT
*/
/*jslint bitwise: true */
(function () {
'use strict';
var ERROR = 'input is invalid type';
var WINDOW = typeof window === 'object';
var root = WINDOW ? window : {};
if (root.JS_SHA256_NO_WINDOW) {
WINDOW = false;
}
var WEB_WORKER = !WINDOW && typeof self === 'object';
var NODE_JS = !root.JS_SHA256_NO_NODE_JS && typeof process === 'object' && process.versions && process.versions.node;
if (NODE_JS) {
root = global;
} else if (WEB_WORKER) {
root = self;
}
var COMMON_JS = !root.JS_SHA256_NO_COMMON_JS && typeof module === 'object' && module.exports;
var AMD = typeof define === 'function' && define.amd;
var ARRAY_BUFFER = !root.JS_SHA256_NO_ARRAY_BUFFER && typeof ArrayBuffer !== 'undefined';
var HEX_CHARS = '0123456789abcdef'.split('');
var EXTRA = [-2147483648, 8388608, 32768, 128];
var SHIFT = [24, 16, 8, 0];
var K = [
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
];
var OUTPUT_TYPES = ['hex', 'array', 'digest', 'arrayBuffer'];
var blocks = [];
if (root.JS_SHA256_NO_NODE_JS || !Array.isArray) {
Array.isArray = function (obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
};
}
if (ARRAY_BUFFER && (root.JS_SHA256_NO_ARRAY_BUFFER_IS_VIEW || !ArrayBuffer.isView)) {
ArrayBuffer.isView = function (obj) {
return typeof obj === 'object' && obj.buffer && obj.buffer.constructor === ArrayBuffer;
};
}
var createOutputMethod = function (outputType, is224) {
return function (message) {
return new Sha256(is224, true).update(message)[outputType]();
};
};
var createMethod = function (is224) {
var method = createOutputMethod('hex', is224);
if (NODE_JS) {
method = nodeWrap(method, is224);
}
method.create = function () {
return new Sha256(is224);
};
method.update = function (message) {
return method.create().update(message);
};
for (var i = 0; i < OUTPUT_TYPES.length; ++i) {
var type = OUTPUT_TYPES[i];
method[type] = createOutputMethod(type, is224);
}
return method;
};
var nodeWrap = function (method, is224) {
var crypto = require('crypto')
var Buffer = require('buffer').Buffer;
var algorithm = is224 ? 'sha224' : 'sha256';
var bufferFrom;
if (Buffer.from && !root.JS_SHA256_NO_BUFFER_FROM) {
bufferFrom = Buffer.from;
} else {
bufferFrom = function (message) {
return new Buffer(message);
};
}
var nodeMethod = function (message) {
if (typeof message === 'string') {
return crypto.createHash(algorithm).update(message, 'utf8').digest('hex');
} else {
if (message === null || message === undefined) {
throw new Error(ERROR);
} else if (message.constructor === ArrayBuffer) {
message = new Uint8Array(message);
}
}
if (Array.isArray(message) || ArrayBuffer.isView(message) ||
message.constructor === Buffer) {
return crypto.createHash(algorithm).update(bufferFrom(message)).digest('hex');
} else {
return method(message);
}
};
return nodeMethod;
};
var createHmacOutputMethod = function (outputType, is224) {
return function (key, message) {
return new HmacSha256(key, is224, true).update(message)[outputType]();
};
};
var createHmacMethod = function (is224) {
var method = createHmacOutputMethod('hex', is224);
method.create = function (key) {
return new HmacSha256(key, is224);
};
method.update = function (key, message) {
return method.create(key).update(message);
};
for (var i = 0; i < OUTPUT_TYPES.length; ++i) {
var type = OUTPUT_TYPES[i];
method[type] = createHmacOutputMethod(type, is224);
}
return method;
};
function Sha256(is224, sharedMemory) {
if (sharedMemory) {
blocks[0] = blocks[16] = blocks[1] = blocks[2] = blocks[3] =
blocks[4] = blocks[5] = blocks[6] = blocks[7] =
blocks[8] = blocks[9] = blocks[10] = blocks[11] =
blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
this.blocks = blocks;
} else {
this.blocks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
}
if (is224) {
this.h0 = 0xc1059ed8;
this.h1 = 0x367cd507;
this.h2 = 0x3070dd17;
this.h3 = 0xf70e5939;
this.h4 = 0xffc00b31;
this.h5 = 0x68581511;
this.h6 = 0x64f98fa7;
this.h7 = 0xbefa4fa4;
} else { // 256
this.h0 = 0x6a09e667;
this.h1 = 0xbb67ae85;
this.h2 = 0x3c6ef372;
this.h3 = 0xa54ff53a;
this.h4 = 0x510e527f;
this.h5 = 0x9b05688c;
this.h6 = 0x1f83d9ab;
this.h7 = 0x5be0cd19;
}
this.block = this.start = this.bytes = this.hBytes = 0;
this.finalized = this.hashed = false;
this.first = true;
this.is224 = is224;
}
Sha256.prototype.update = function (message) {
if (this.finalized) {
return;
}
var notString, type = typeof message;
if (type !== 'string') {
if (type === 'object') {
if (message === null) {
throw new Error(ERROR);
} else if (ARRAY_BUFFER && message.constructor === ArrayBuffer) {
message = new Uint8Array(message);
} else if (!Array.isArray(message)) {
if (!ARRAY_BUFFER || !ArrayBuffer.isView(message)) {
throw new Error(ERROR);
}
}
} else {
throw new Error(ERROR);
}
notString = true;
}
var code, index = 0, i, length = message.length, blocks = this.blocks;
while (index < length) {
if (this.hashed) {
this.hashed = false;
blocks[0] = this.block;
blocks[16] = blocks[1] = blocks[2] = blocks[3] =
blocks[4] = blocks[5] = blocks[6] = blocks[7] =
blocks[8] = blocks[9] = blocks[10] = blocks[11] =
blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
}
if (notString) {
for (i = this.start; index < length && i < 64; ++index) {
blocks[i >> 2] |= message[index] << SHIFT[i++ & 3];
}
} else {
for (i = this.start; index < length && i < 64; ++index) {
code = message.charCodeAt(index);
if (code < 0x80) {
blocks[i >> 2] |= code << SHIFT[i++ & 3];
} else if (code < 0x800) {
blocks[i >> 2] |= (0xc0 | (code >> 6)) << SHIFT[i++ & 3];
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
} else if (code < 0xd800 || code >= 0xe000) {
blocks[i >> 2] |= (0xe0 | (code >> 12)) << SHIFT[i++ & 3];
blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
} else {
code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));
blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3];
blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3];
blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
}
}
}
this.lastByteIndex = i;
this.bytes += i - this.start;
if (i >= 64) {
this.block = blocks[16];
this.start = i - 64;
this.hash();
this.hashed = true;
} else {
this.start = i;
}
}
if (this.bytes > 4294967295) {
this.hBytes += this.bytes / 4294967296 << 0;
this.bytes = this.bytes % 4294967296;
}
return this;
};
Sha256.prototype.finalize = function () {
if (this.finalized) {
return;
}
this.finalized = true;
var blocks = this.blocks, i = this.lastByteIndex;
blocks[16] = this.block;
blocks[i >> 2] |= EXTRA[i & 3];
this.block = blocks[16];
if (i >= 56) {
if (!this.hashed) {
this.hash();
}
blocks[0] = this.block;
blocks[16] = blocks[1] = blocks[2] = blocks[3] =
blocks[4] = blocks[5] = blocks[6] = blocks[7] =
blocks[8] = blocks[9] = blocks[10] = blocks[11] =
blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
}
blocks[14] = this.hBytes << 3 | this.bytes >>> 29;
blocks[15] = this.bytes << 3;
this.hash();
};
Sha256.prototype.hash = function () {
var a = this.h0, b = this.h1, c = this.h2, d = this.h3, e = this.h4, f = this.h5, g = this.h6,
h = this.h7, blocks = this.blocks, j, s0, s1, maj, t1, t2, ch, ab, da, cd, bc;
for (j = 16; j < 64; ++j) {
// rightrotate
t1 = blocks[j - 15];
s0 = ((t1 >>> 7) | (t1 << 25)) ^ ((t1 >>> 18) | (t1 << 14)) ^ (t1 >>> 3);
t1 = blocks[j - 2];
s1 = ((t1 >>> 17) | (t1 << 15)) ^ ((t1 >>> 19) | (t1 << 13)) ^ (t1 >>> 10);
blocks[j] = blocks[j - 16] + s0 + blocks[j - 7] + s1 << 0;
}
bc = b & c;
for (j = 0; j < 64; j += 4) {
if (this.first) {
if (this.is224) {
ab = 300032;
t1 = blocks[0] - 1413257819;
h = t1 - 150054599 << 0;
d = t1 + 24177077 << 0;
} else {
ab = 704751109;
t1 = blocks[0] - 210244248;
h = t1 - 1521486534 << 0;
d = t1 + 143694565 << 0;
}
this.first = false;
} else {
s0 = ((a >>> 2) | (a << 30)) ^ ((a >>> 13) | (a << 19)) ^ ((a >>> 22) | (a << 10));
s1 = ((e >>> 6) | (e << 26)) ^ ((e >>> 11) | (e << 21)) ^ ((e >>> 25) | (e << 7));
ab = a & b;
maj = ab ^ (a & c) ^ bc;
ch = (e & f) ^ (~e & g);
t1 = h + s1 + ch + K[j] + blocks[j];
t2 = s0 + maj;
h = d + t1 << 0;
d = t1 + t2 << 0;
}
s0 = ((d >>> 2) | (d << 30)) ^ ((d >>> 13) | (d << 19)) ^ ((d >>> 22) | (d << 10));
s1 = ((h >>> 6) | (h << 26)) ^ ((h >>> 11) | (h << 21)) ^ ((h >>> 25) | (h << 7));
da = d & a;
maj = da ^ (d & b) ^ ab;
ch = (h & e) ^ (~h & f);
t1 = g + s1 + ch + K[j + 1] + blocks[j + 1];
t2 = s0 + maj;
g = c + t1 << 0;
c = t1 + t2 << 0;
s0 = ((c >>> 2) | (c << 30)) ^ ((c >>> 13) | (c << 19)) ^ ((c >>> 22) | (c << 10));
s1 = ((g >>> 6) | (g << 26)) ^ ((g >>> 11) | (g << 21)) ^ ((g >>> 25) | (g << 7));
cd = c & d;
maj = cd ^ (c & a) ^ da;
ch = (g & h) ^ (~g & e);
t1 = f + s1 + ch + K[j + 2] + blocks[j + 2];
t2 = s0 + maj;
f = b + t1 << 0;
b = t1 + t2 << 0;
s0 = ((b >>> 2) | (b << 30)) ^ ((b >>> 13) | (b << 19)) ^ ((b >>> 22) | (b << 10));
s1 = ((f >>> 6) | (f << 26)) ^ ((f >>> 11) | (f << 21)) ^ ((f >>> 25) | (f << 7));
bc = b & c;
maj = bc ^ (b & d) ^ cd;
ch = (f & g) ^ (~f & h);
t1 = e + s1 + ch + K[j + 3] + blocks[j + 3];
t2 = s0 + maj;
e = a + t1 << 0;
a = t1 + t2 << 0;
this.chromeBugWorkAround = true;
}
this.h0 = this.h0 + a << 0;
this.h1 = this.h1 + b << 0;
this.h2 = this.h2 + c << 0;
this.h3 = this.h3 + d << 0;
this.h4 = this.h4 + e << 0;
this.h5 = this.h5 + f << 0;
this.h6 = this.h6 + g << 0;
this.h7 = this.h7 + h << 0;
};
Sha256.prototype.hex = function () {
this.finalize();
var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3, h4 = this.h4, h5 = this.h5,
h6 = this.h6, h7 = this.h7;
var hex = HEX_CHARS[(h0 >> 28) & 0x0F] + HEX_CHARS[(h0 >> 24) & 0x0F] +
HEX_CHARS[(h0 >> 20) & 0x0F] + HEX_CHARS[(h0 >> 16) & 0x0F] +
HEX_CHARS[(h0 >> 12) & 0x0F] + HEX_CHARS[(h0 >> 8) & 0x0F] +
HEX_CHARS[(h0 >> 4) & 0x0F] + HEX_CHARS[h0 & 0x0F] +
HEX_CHARS[(h1 >> 28) & 0x0F] + HEX_CHARS[(h1 >> 24) & 0x0F] +
HEX_CHARS[(h1 >> 20) & 0x0F] + HEX_CHARS[(h1 >> 16) & 0x0F] +
HEX_CHARS[(h1 >> 12) & 0x0F] + HEX_CHARS[(h1 >> 8) & 0x0F] +
HEX_CHARS[(h1 >> 4) & 0x0F] + HEX_CHARS[h1 & 0x0F] +
HEX_CHARS[(h2 >> 28) & 0x0F] + HEX_CHARS[(h2 >> 24) & 0x0F] +
HEX_CHARS[(h2 >> 20) & 0x0F] + HEX_CHARS[(h2 >> 16) & 0x0F] +
HEX_CHARS[(h2 >> 12) & 0x0F] + HEX_CHARS[(h2 >> 8) & 0x0F] +
HEX_CHARS[(h2 >> 4) & 0x0F] + HEX_CHARS[h2 & 0x0F] +
HEX_CHARS[(h3 >> 28) & 0x0F] + HEX_CHARS[(h3 >> 24) & 0x0F] +
HEX_CHARS[(h3 >> 20) & 0x0F] + HEX_CHARS[(h3 >> 16) & 0x0F] +
HEX_CHARS[(h3 >> 12) & 0x0F] + HEX_CHARS[(h3 >> 8) & 0x0F] +
HEX_CHARS[(h3 >> 4) & 0x0F] + HEX_CHARS[h3 & 0x0F] +
HEX_CHARS[(h4 >> 28) & 0x0F] + HEX_CHARS[(h4 >> 24) & 0x0F] +
HEX_CHARS[(h4 >> 20) & 0x0F] + HEX_CHARS[(h4 >> 16) & 0x0F] +
HEX_CHARS[(h4 >> 12) & 0x0F] + HEX_CHARS[(h4 >> 8) & 0x0F] +
HEX_CHARS[(h4 >> 4) & 0x0F] + HEX_CHARS[h4 & 0x0F] +
HEX_CHARS[(h5 >> 28) & 0x0F] + HEX_CHARS[(h5 >> 24) & 0x0F] +
HEX_CHARS[(h5 >> 20) & 0x0F] + HEX_CHARS[(h5 >> 16) & 0x0F] +
HEX_CHARS[(h5 >> 12) & 0x0F] + HEX_CHARS[(h5 >> 8) & 0x0F] +
HEX_CHARS[(h5 >> 4) & 0x0F] + HEX_CHARS[h5 & 0x0F] +
HEX_CHARS[(h6 >> 28) & 0x0F] + HEX_CHARS[(h6 >> 24) & 0x0F] +
HEX_CHARS[(h6 >> 20) & 0x0F] + HEX_CHARS[(h6 >> 16) & 0x0F] +
HEX_CHARS[(h6 >> 12) & 0x0F] + HEX_CHARS[(h6 >> 8) & 0x0F] +
HEX_CHARS[(h6 >> 4) & 0x0F] + HEX_CHARS[h6 & 0x0F];
if (!this.is224) {
hex += HEX_CHARS[(h7 >> 28) & 0x0F] + HEX_CHARS[(h7 >> 24) & 0x0F] +
HEX_CHARS[(h7 >> 20) & 0x0F] + HEX_CHARS[(h7 >> 16) & 0x0F] +
HEX_CHARS[(h7 >> 12) & 0x0F] + HEX_CHARS[(h7 >> 8) & 0x0F] +
HEX_CHARS[(h7 >> 4) & 0x0F] + HEX_CHARS[h7 & 0x0F];
}
return hex;
};
Sha256.prototype.toString = Sha256.prototype.hex;
Sha256.prototype.digest = function () {
this.finalize();
var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3, h4 = this.h4, h5 = this.h5,
h6 = this.h6, h7 = this.h7;
var arr = [
(h0 >> 24) & 0xFF, (h0 >> 16) & 0xFF, (h0 >> 8) & 0xFF, h0 & 0xFF,
(h1 >> 24) & 0xFF, (h1 >> 16) & 0xFF, (h1 >> 8) & 0xFF, h1 & 0xFF,
(h2 >> 24) & 0xFF, (h2 >> 16) & 0xFF, (h2 >> 8) & 0xFF, h2 & 0xFF,
(h3 >> 24) & 0xFF, (h3 >> 16) & 0xFF, (h3 >> 8) & 0xFF, h3 & 0xFF,
(h4 >> 24) & 0xFF, (h4 >> 16) & 0xFF, (h4 >> 8) & 0xFF, h4 & 0xFF,
(h5 >> 24) & 0xFF, (h5 >> 16) & 0xFF, (h5 >> 8) & 0xFF, h5 & 0xFF,
(h6 >> 24) & 0xFF, (h6 >> 16) & 0xFF, (h6 >> 8) & 0xFF, h6 & 0xFF
];
if (!this.is224) {
arr.push((h7 >> 24) & 0xFF, (h7 >> 16) & 0xFF, (h7 >> 8) & 0xFF, h7 & 0xFF);
}
return arr;
};
Sha256.prototype.array = Sha256.prototype.digest;
Sha256.prototype.arrayBuffer = function () {
this.finalize();
var buffer = new ArrayBuffer(this.is224 ? 28 : 32);
var dataView = new DataView(buffer);
dataView.setUint32(0, this.h0);
dataView.setUint32(4, this.h1);
dataView.setUint32(8, this.h2);
dataView.setUint32(12, this.h3);
dataView.setUint32(16, this.h4);
dataView.setUint32(20, this.h5);
dataView.setUint32(24, this.h6);
if (!this.is224) {
dataView.setUint32(28, this.h7);
}
return buffer;
};
function HmacSha256(key, is224, sharedMemory) {
var i, type = typeof key;
if (type === 'string') {
var bytes = [], length = key.length, index = 0, code;
for (i = 0; i < length; ++i) {
code = key.charCodeAt(i);
if (code < 0x80) {
bytes[index++] = code;
} else if (code < 0x800) {
bytes[index++] = (0xc0 | (code >> 6));
bytes[index++] = (0x80 | (code & 0x3f));
} else if (code < 0xd800 || code >= 0xe000) {
bytes[index++] = (0xe0 | (code >> 12));
bytes[index++] = (0x80 | ((code >> 6) & 0x3f));
bytes[index++] = (0x80 | (code & 0x3f));
} else {
code = 0x10000 + (((code & 0x3ff) << 10) | (key.charCodeAt(++i) & 0x3ff));
bytes[index++] = (0xf0 | (code >> 18));
bytes[index++] = (0x80 | ((code >> 12) & 0x3f));
bytes[index++] = (0x80 | ((code >> 6) & 0x3f));
bytes[index++] = (0x80 | (code & 0x3f));
}
}
key = bytes;
} else {
if (type === 'object') {
if (key === null) {
throw new Error(ERROR);
} else if (ARRAY_BUFFER && key.constructor === ArrayBuffer) {
key = new Uint8Array(key);
} else if (!Array.isArray(key)) {
if (!ARRAY_BUFFER || !ArrayBuffer.isView(key)) {
throw new Error(ERROR);
}
}
} else {
throw new Error(ERROR);
}
}
if (key.length > 64) {
key = (new Sha256(is224, true)).update(key).array();
}
var oKeyPad = [], iKeyPad = [];
for (i = 0; i < 64; ++i) {
var b = key[i] || 0;
oKeyPad[i] = 0x5c ^ b;
iKeyPad[i] = 0x36 ^ b;
}
Sha256.call(this, is224, sharedMemory);
this.update(iKeyPad);
this.oKeyPad = oKeyPad;
this.inner = true;
this.sharedMemory = sharedMemory;
}
HmacSha256.prototype = new Sha256();
HmacSha256.prototype.finalize = function () {
Sha256.prototype.finalize.call(this);
if (this.inner) {
this.inner = false;
var innerHash = this.array();
Sha256.call(this, this.is224, this.sharedMemory);
this.update(this.oKeyPad);
this.update(innerHash);
Sha256.prototype.finalize.call(this);
}
};
var exports = createMethod();
exports.sha256 = exports;
exports.sha224 = createMethod(true);
exports.sha256.hmac = createHmacMethod();
exports.sha224.hmac = createHmacMethod(true);
if (COMMON_JS) {
module.exports = exports;
} else {
root.sha256 = exports.sha256;
root.sha224 = exports.sha224;
if (AMD) {
define(function () {
return exports;
});
}
}
})();

20
scripts/js-sha3 license.txt Executable file
View File

@@ -0,0 +1,20 @@
Copyright 2015-2018 Chen, Yi-Cyuan
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

656
scripts/js-sha3-0.8.0.js Executable file
View File

@@ -0,0 +1,656 @@
/**
* [js-sha3]{@link https://github.com/emn178/js-sha3}
*
* @version 0.8.0
* @author Chen, Yi-Cyuan [emn178@gmail.com]
* @copyright Chen, Yi-Cyuan 2015-2018
* @license MIT
*/
/*jslint bitwise: true */
(function () {
'use strict';
var INPUT_ERROR = 'input is invalid type';
var FINALIZE_ERROR = 'finalize already called';
var WINDOW = typeof window === 'object';
var root = WINDOW ? window : {};
if (root.JS_SHA3_NO_WINDOW) {
WINDOW = false;
}
var WEB_WORKER = !WINDOW && typeof self === 'object';
var NODE_JS = !root.JS_SHA3_NO_NODE_JS && typeof process === 'object' && process.versions && process.versions.node;
if (NODE_JS) {
root = global;
} else if (WEB_WORKER) {
root = self;
}
var COMMON_JS = !root.JS_SHA3_NO_COMMON_JS && typeof module === 'object' && module.exports;
var AMD = typeof define === 'function' && define.amd;
var ARRAY_BUFFER = !root.JS_SHA3_NO_ARRAY_BUFFER && typeof ArrayBuffer !== 'undefined';
var HEX_CHARS = '0123456789abcdef'.split('');
var SHAKE_PADDING = [31, 7936, 2031616, 520093696];
var CSHAKE_PADDING = [4, 1024, 262144, 67108864];
var KECCAK_PADDING = [1, 256, 65536, 16777216];
var PADDING = [6, 1536, 393216, 100663296];
var SHIFT = [0, 8, 16, 24];
var RC = [1, 0, 32898, 0, 32906, 2147483648, 2147516416, 2147483648, 32907, 0, 2147483649,
0, 2147516545, 2147483648, 32777, 2147483648, 138, 0, 136, 0, 2147516425, 0,
2147483658, 0, 2147516555, 0, 139, 2147483648, 32905, 2147483648, 32771,
2147483648, 32770, 2147483648, 128, 2147483648, 32778, 0, 2147483658, 2147483648,
2147516545, 2147483648, 32896, 2147483648, 2147483649, 0, 2147516424, 2147483648];
var BITS = [224, 256, 384, 512];
var SHAKE_BITS = [128, 256];
var OUTPUT_TYPES = ['hex', 'buffer', 'arrayBuffer', 'array', 'digest'];
var CSHAKE_BYTEPAD = {
'128': 168,
'256': 136
};
if (root.JS_SHA3_NO_NODE_JS || !Array.isArray) {
Array.isArray = function (obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
};
}
if (ARRAY_BUFFER && (root.JS_SHA3_NO_ARRAY_BUFFER_IS_VIEW || !ArrayBuffer.isView)) {
ArrayBuffer.isView = function (obj) {
return typeof obj === 'object' && obj.buffer && obj.buffer.constructor === ArrayBuffer;
};
}
var createOutputMethod = function (bits, padding, outputType) {
return function (message) {
return new Keccak(bits, padding, bits).update(message)[outputType]();
};
};
var createShakeOutputMethod = function (bits, padding, outputType) {
return function (message, outputBits) {
return new Keccak(bits, padding, outputBits).update(message)[outputType]();
};
};
var createCshakeOutputMethod = function (bits, padding, outputType) {
return function (message, outputBits, n, s) {
return methods['cshake' + bits].update(message, outputBits, n, s)[outputType]();
};
};
var createKmacOutputMethod = function (bits, padding, outputType) {
return function (key, message, outputBits, s) {
return methods['kmac' + bits].update(key, message, outputBits, s)[outputType]();
};
};
var createOutputMethods = function (method, createMethod, bits, padding) {
for (var i = 0; i < OUTPUT_TYPES.length; ++i) {
var type = OUTPUT_TYPES[i];
method[type] = createMethod(bits, padding, type);
}
return method;
};
var createMethod = function (bits, padding) {
var method = createOutputMethod(bits, padding, 'hex');
method.create = function () {
return new Keccak(bits, padding, bits);
};
method.update = function (message) {
return method.create().update(message);
};
return createOutputMethods(method, createOutputMethod, bits, padding);
};
var createShakeMethod = function (bits, padding) {
var method = createShakeOutputMethod(bits, padding, 'hex');
method.create = function (outputBits) {
return new Keccak(bits, padding, outputBits);
};
method.update = function (message, outputBits) {
return method.create(outputBits).update(message);
};
return createOutputMethods(method, createShakeOutputMethod, bits, padding);
};
var createCshakeMethod = function (bits, padding) {
var w = CSHAKE_BYTEPAD[bits];
var method = createCshakeOutputMethod(bits, padding, 'hex');
method.create = function (outputBits, n, s) {
if (!n && !s) {
return methods['shake' + bits].create(outputBits);
} else {
return new Keccak(bits, padding, outputBits).bytepad([n, s], w);
}
};
method.update = function (message, outputBits, n, s) {
return method.create(outputBits, n, s).update(message);
};
return createOutputMethods(method, createCshakeOutputMethod, bits, padding);
};
var createKmacMethod = function (bits, padding) {
var w = CSHAKE_BYTEPAD[bits];
var method = createKmacOutputMethod(bits, padding, 'hex');
method.create = function (key, outputBits, s) {
return new Kmac(bits, padding, outputBits).bytepad(['KMAC', s], w).bytepad([key], w);
};
method.update = function (key, message, outputBits, s) {
return method.create(key, outputBits, s).update(message);
};
return createOutputMethods(method, createKmacOutputMethod, bits, padding);
};
var algorithms = [
{ name: 'keccak', padding: KECCAK_PADDING, bits: BITS, createMethod: createMethod },
{ name: 'sha3', padding: PADDING, bits: BITS, createMethod: createMethod },
{ name: 'shake', padding: SHAKE_PADDING, bits: SHAKE_BITS, createMethod: createShakeMethod },
{ name: 'cshake', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: createCshakeMethod },
{ name: 'kmac', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: createKmacMethod }
];
var methods = {}, methodNames = [];
for (var i = 0; i < algorithms.length; ++i) {
var algorithm = algorithms[i];
var bits = algorithm.bits;
for (var j = 0; j < bits.length; ++j) {
var methodName = algorithm.name + '_' + bits[j];
methodNames.push(methodName);
methods[methodName] = algorithm.createMethod(bits[j], algorithm.padding);
if (algorithm.name !== 'sha3') {
var newMethodName = algorithm.name + bits[j];
methodNames.push(newMethodName);
methods[newMethodName] = methods[methodName];
}
}
}
function Keccak(bits, padding, outputBits) {
this.blocks = [];
this.s = [];
this.padding = padding;
this.outputBits = outputBits;
this.reset = true;
this.finalized = false;
this.block = 0;
this.start = 0;
this.blockCount = (1600 - (bits << 1)) >> 5;
this.byteCount = this.blockCount << 2;
this.outputBlocks = outputBits >> 5;
this.extraBytes = (outputBits & 31) >> 3;
for (var i = 0; i < 50; ++i) {
this.s[i] = 0;
}
}
Keccak.prototype.update = function (message) {
if (this.finalized) {
throw new Error(FINALIZE_ERROR);
}
var notString, type = typeof message;
if (type !== 'string') {
if (type === 'object') {
if (message === null) {
throw new Error(INPUT_ERROR);
} else if (ARRAY_BUFFER && message.constructor === ArrayBuffer) {
message = new Uint8Array(message);
} else if (!Array.isArray(message)) {
if (!ARRAY_BUFFER || !ArrayBuffer.isView(message)) {
throw new Error(INPUT_ERROR);
}
}
} else {
throw new Error(INPUT_ERROR);
}
notString = true;
}
var blocks = this.blocks, byteCount = this.byteCount, length = message.length,
blockCount = this.blockCount, index = 0, s = this.s, i, code;
while (index < length) {
if (this.reset) {
this.reset = false;
blocks[0] = this.block;
for (i = 1; i < blockCount + 1; ++i) {
blocks[i] = 0;
}
}
if (notString) {
for (i = this.start; index < length && i < byteCount; ++index) {
blocks[i >> 2] |= message[index] << SHIFT[i++ & 3];
}
} else {
for (i = this.start; index < length && i < byteCount; ++index) {
code = message.charCodeAt(index);
if (code < 0x80) {
blocks[i >> 2] |= code << SHIFT[i++ & 3];
} else if (code < 0x800) {
blocks[i >> 2] |= (0xc0 | (code >> 6)) << SHIFT[i++ & 3];
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
} else if (code < 0xd800 || code >= 0xe000) {
blocks[i >> 2] |= (0xe0 | (code >> 12)) << SHIFT[i++ & 3];
blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
} else {
code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));
blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3];
blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3];
blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
}
}
}
this.lastByteIndex = i;
if (i >= byteCount) {
this.start = i - byteCount;
this.block = blocks[blockCount];
for (i = 0; i < blockCount; ++i) {
s[i] ^= blocks[i];
}
f(s);
this.reset = true;
} else {
this.start = i;
}
}
return this;
};
Keccak.prototype.encode = function (x, right) {
var o = x & 255, n = 1;
var bytes = [o];
x = x >> 8;
o = x & 255;
while (o > 0) {
bytes.unshift(o);
x = x >> 8;
o = x & 255;
++n;
}
if (right) {
bytes.push(n);
} else {
bytes.unshift(n);
}
this.update(bytes);
return bytes.length;
};
Keccak.prototype.encodeString = function (str) {
var notString, type = typeof str;
if (type !== 'string') {
if (type === 'object') {
if (str === null) {
throw new Error(INPUT_ERROR);
} else if (ARRAY_BUFFER && str.constructor === ArrayBuffer) {
str = new Uint8Array(str);
} else if (!Array.isArray(str)) {
if (!ARRAY_BUFFER || !ArrayBuffer.isView(str)) {
throw new Error(INPUT_ERROR);
}
}
} else {
throw new Error(INPUT_ERROR);
}
notString = true;
}
var bytes = 0, length = str.length;
if (notString) {
bytes = length;
} else {
for (var i = 0; i < str.length; ++i) {
var code = str.charCodeAt(i);
if (code < 0x80) {
bytes += 1;
} else if (code < 0x800) {
bytes += 2;
} else if (code < 0xd800 || code >= 0xe000) {
bytes += 3;
} else {
code = 0x10000 + (((code & 0x3ff) << 10) | (str.charCodeAt(++i) & 0x3ff));
bytes += 4;
}
}
}
bytes += this.encode(bytes * 8);
this.update(str);
return bytes;
};
Keccak.prototype.bytepad = function (strs, w) {
var bytes = this.encode(w);
for (var i = 0; i < strs.length; ++i) {
bytes += this.encodeString(strs[i]);
}
var paddingBytes = w - bytes % w;
var zeros = [];
zeros.length = paddingBytes;
this.update(zeros);
return this;
};
Keccak.prototype.finalize = function () {
if (this.finalized) {
return;
}
this.finalized = true;
var blocks = this.blocks, i = this.lastByteIndex, blockCount = this.blockCount, s = this.s;
blocks[i >> 2] |= this.padding[i & 3];
if (this.lastByteIndex === this.byteCount) {
blocks[0] = blocks[blockCount];
for (i = 1; i < blockCount + 1; ++i) {
blocks[i] = 0;
}
}
blocks[blockCount - 1] |= 0x80000000;
for (i = 0; i < blockCount; ++i) {
s[i] ^= blocks[i];
}
f(s);
};
Keccak.prototype.toString = Keccak.prototype.hex = function () {
this.finalize();
var blockCount = this.blockCount, s = this.s, outputBlocks = this.outputBlocks,
extraBytes = this.extraBytes, i = 0, j = 0;
var hex = '', block;
while (j < outputBlocks) {
for (i = 0; i < blockCount && j < outputBlocks; ++i, ++j) {
block = s[i];
hex += HEX_CHARS[(block >> 4) & 0x0F] + HEX_CHARS[block & 0x0F] +
HEX_CHARS[(block >> 12) & 0x0F] + HEX_CHARS[(block >> 8) & 0x0F] +
HEX_CHARS[(block >> 20) & 0x0F] + HEX_CHARS[(block >> 16) & 0x0F] +
HEX_CHARS[(block >> 28) & 0x0F] + HEX_CHARS[(block >> 24) & 0x0F];
}
if (j % blockCount === 0) {
f(s);
i = 0;
}
}
if (extraBytes) {
block = s[i];
hex += HEX_CHARS[(block >> 4) & 0x0F] + HEX_CHARS[block & 0x0F];
if (extraBytes > 1) {
hex += HEX_CHARS[(block >> 12) & 0x0F] + HEX_CHARS[(block >> 8) & 0x0F];
}
if (extraBytes > 2) {
hex += HEX_CHARS[(block >> 20) & 0x0F] + HEX_CHARS[(block >> 16) & 0x0F];
}
}
return hex;
};
Keccak.prototype.arrayBuffer = function () {
this.finalize();
var blockCount = this.blockCount, s = this.s, outputBlocks = this.outputBlocks,
extraBytes = this.extraBytes, i = 0, j = 0;
var bytes = this.outputBits >> 3;
var buffer;
if (extraBytes) {
buffer = new ArrayBuffer((outputBlocks + 1) << 2);
} else {
buffer = new ArrayBuffer(bytes);
}
var array = new Uint32Array(buffer);
while (j < outputBlocks) {
for (i = 0; i < blockCount && j < outputBlocks; ++i, ++j) {
array[j] = s[i];
}
if (j % blockCount === 0) {
f(s);
}
}
if (extraBytes) {
array[i] = s[i];
buffer = buffer.slice(0, bytes);
}
return buffer;
};
Keccak.prototype.buffer = Keccak.prototype.arrayBuffer;
Keccak.prototype.digest = Keccak.prototype.array = function () {
this.finalize();
var blockCount = this.blockCount, s = this.s, outputBlocks = this.outputBlocks,
extraBytes = this.extraBytes, i = 0, j = 0;
var array = [], offset, block;
while (j < outputBlocks) {
for (i = 0; i < blockCount && j < outputBlocks; ++i, ++j) {
offset = j << 2;
block = s[i];
array[offset] = block & 0xFF;
array[offset + 1] = (block >> 8) & 0xFF;
array[offset + 2] = (block >> 16) & 0xFF;
array[offset + 3] = (block >> 24) & 0xFF;
}
if (j % blockCount === 0) {
f(s);
}
}
if (extraBytes) {
offset = j << 2;
block = s[i];
array[offset] = block & 0xFF;
if (extraBytes > 1) {
array[offset + 1] = (block >> 8) & 0xFF;
}
if (extraBytes > 2) {
array[offset + 2] = (block >> 16) & 0xFF;
}
}
return array;
};
function Kmac(bits, padding, outputBits) {
Keccak.call(this, bits, padding, outputBits);
}
Kmac.prototype = new Keccak();
Kmac.prototype.finalize = function () {
this.encode(this.outputBits, true);
return Keccak.prototype.finalize.call(this);
};
var f = function (s) {
var h, l, n, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9,
b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15, b16, b17,
b18, b19, b20, b21, b22, b23, b24, b25, b26, b27, b28, b29, b30, b31, b32, b33,
b34, b35, b36, b37, b38, b39, b40, b41, b42, b43, b44, b45, b46, b47, b48, b49;
for (n = 0; n < 48; n += 2) {
c0 = s[0] ^ s[10] ^ s[20] ^ s[30] ^ s[40];
c1 = s[1] ^ s[11] ^ s[21] ^ s[31] ^ s[41];
c2 = s[2] ^ s[12] ^ s[22] ^ s[32] ^ s[42];
c3 = s[3] ^ s[13] ^ s[23] ^ s[33] ^ s[43];
c4 = s[4] ^ s[14] ^ s[24] ^ s[34] ^ s[44];
c5 = s[5] ^ s[15] ^ s[25] ^ s[35] ^ s[45];
c6 = s[6] ^ s[16] ^ s[26] ^ s[36] ^ s[46];
c7 = s[7] ^ s[17] ^ s[27] ^ s[37] ^ s[47];
c8 = s[8] ^ s[18] ^ s[28] ^ s[38] ^ s[48];
c9 = s[9] ^ s[19] ^ s[29] ^ s[39] ^ s[49];
h = c8 ^ ((c2 << 1) | (c3 >>> 31));
l = c9 ^ ((c3 << 1) | (c2 >>> 31));
s[0] ^= h;
s[1] ^= l;
s[10] ^= h;
s[11] ^= l;
s[20] ^= h;
s[21] ^= l;
s[30] ^= h;
s[31] ^= l;
s[40] ^= h;
s[41] ^= l;
h = c0 ^ ((c4 << 1) | (c5 >>> 31));
l = c1 ^ ((c5 << 1) | (c4 >>> 31));
s[2] ^= h;
s[3] ^= l;
s[12] ^= h;
s[13] ^= l;
s[22] ^= h;
s[23] ^= l;
s[32] ^= h;
s[33] ^= l;
s[42] ^= h;
s[43] ^= l;
h = c2 ^ ((c6 << 1) | (c7 >>> 31));
l = c3 ^ ((c7 << 1) | (c6 >>> 31));
s[4] ^= h;
s[5] ^= l;
s[14] ^= h;
s[15] ^= l;
s[24] ^= h;
s[25] ^= l;
s[34] ^= h;
s[35] ^= l;
s[44] ^= h;
s[45] ^= l;
h = c4 ^ ((c8 << 1) | (c9 >>> 31));
l = c5 ^ ((c9 << 1) | (c8 >>> 31));
s[6] ^= h;
s[7] ^= l;
s[16] ^= h;
s[17] ^= l;
s[26] ^= h;
s[27] ^= l;
s[36] ^= h;
s[37] ^= l;
s[46] ^= h;
s[47] ^= l;
h = c6 ^ ((c0 << 1) | (c1 >>> 31));
l = c7 ^ ((c1 << 1) | (c0 >>> 31));
s[8] ^= h;
s[9] ^= l;
s[18] ^= h;
s[19] ^= l;
s[28] ^= h;
s[29] ^= l;
s[38] ^= h;
s[39] ^= l;
s[48] ^= h;
s[49] ^= l;
b0 = s[0];
b1 = s[1];
b32 = (s[11] << 4) | (s[10] >>> 28);
b33 = (s[10] << 4) | (s[11] >>> 28);
b14 = (s[20] << 3) | (s[21] >>> 29);
b15 = (s[21] << 3) | (s[20] >>> 29);
b46 = (s[31] << 9) | (s[30] >>> 23);
b47 = (s[30] << 9) | (s[31] >>> 23);
b28 = (s[40] << 18) | (s[41] >>> 14);
b29 = (s[41] << 18) | (s[40] >>> 14);
b20 = (s[2] << 1) | (s[3] >>> 31);
b21 = (s[3] << 1) | (s[2] >>> 31);
b2 = (s[13] << 12) | (s[12] >>> 20);
b3 = (s[12] << 12) | (s[13] >>> 20);
b34 = (s[22] << 10) | (s[23] >>> 22);
b35 = (s[23] << 10) | (s[22] >>> 22);
b16 = (s[33] << 13) | (s[32] >>> 19);
b17 = (s[32] << 13) | (s[33] >>> 19);
b48 = (s[42] << 2) | (s[43] >>> 30);
b49 = (s[43] << 2) | (s[42] >>> 30);
b40 = (s[5] << 30) | (s[4] >>> 2);
b41 = (s[4] << 30) | (s[5] >>> 2);
b22 = (s[14] << 6) | (s[15] >>> 26);
b23 = (s[15] << 6) | (s[14] >>> 26);
b4 = (s[25] << 11) | (s[24] >>> 21);
b5 = (s[24] << 11) | (s[25] >>> 21);
b36 = (s[34] << 15) | (s[35] >>> 17);
b37 = (s[35] << 15) | (s[34] >>> 17);
b18 = (s[45] << 29) | (s[44] >>> 3);
b19 = (s[44] << 29) | (s[45] >>> 3);
b10 = (s[6] << 28) | (s[7] >>> 4);
b11 = (s[7] << 28) | (s[6] >>> 4);
b42 = (s[17] << 23) | (s[16] >>> 9);
b43 = (s[16] << 23) | (s[17] >>> 9);
b24 = (s[26] << 25) | (s[27] >>> 7);
b25 = (s[27] << 25) | (s[26] >>> 7);
b6 = (s[36] << 21) | (s[37] >>> 11);
b7 = (s[37] << 21) | (s[36] >>> 11);
b38 = (s[47] << 24) | (s[46] >>> 8);
b39 = (s[46] << 24) | (s[47] >>> 8);
b30 = (s[8] << 27) | (s[9] >>> 5);
b31 = (s[9] << 27) | (s[8] >>> 5);
b12 = (s[18] << 20) | (s[19] >>> 12);
b13 = (s[19] << 20) | (s[18] >>> 12);
b44 = (s[29] << 7) | (s[28] >>> 25);
b45 = (s[28] << 7) | (s[29] >>> 25);
b26 = (s[38] << 8) | (s[39] >>> 24);
b27 = (s[39] << 8) | (s[38] >>> 24);
b8 = (s[48] << 14) | (s[49] >>> 18);
b9 = (s[49] << 14) | (s[48] >>> 18);
s[0] = b0 ^ (~b2 & b4);
s[1] = b1 ^ (~b3 & b5);
s[10] = b10 ^ (~b12 & b14);
s[11] = b11 ^ (~b13 & b15);
s[20] = b20 ^ (~b22 & b24);
s[21] = b21 ^ (~b23 & b25);
s[30] = b30 ^ (~b32 & b34);
s[31] = b31 ^ (~b33 & b35);
s[40] = b40 ^ (~b42 & b44);
s[41] = b41 ^ (~b43 & b45);
s[2] = b2 ^ (~b4 & b6);
s[3] = b3 ^ (~b5 & b7);
s[12] = b12 ^ (~b14 & b16);
s[13] = b13 ^ (~b15 & b17);
s[22] = b22 ^ (~b24 & b26);
s[23] = b23 ^ (~b25 & b27);
s[32] = b32 ^ (~b34 & b36);
s[33] = b33 ^ (~b35 & b37);
s[42] = b42 ^ (~b44 & b46);
s[43] = b43 ^ (~b45 & b47);
s[4] = b4 ^ (~b6 & b8);
s[5] = b5 ^ (~b7 & b9);
s[14] = b14 ^ (~b16 & b18);
s[15] = b15 ^ (~b17 & b19);
s[24] = b24 ^ (~b26 & b28);
s[25] = b25 ^ (~b27 & b29);
s[34] = b34 ^ (~b36 & b38);
s[35] = b35 ^ (~b37 & b39);
s[44] = b44 ^ (~b46 & b48);
s[45] = b45 ^ (~b47 & b49);
s[6] = b6 ^ (~b8 & b0);
s[7] = b7 ^ (~b9 & b1);
s[16] = b16 ^ (~b18 & b10);
s[17] = b17 ^ (~b19 & b11);
s[26] = b26 ^ (~b28 & b20);
s[27] = b27 ^ (~b29 & b21);
s[36] = b36 ^ (~b38 & b30);
s[37] = b37 ^ (~b39 & b31);
s[46] = b46 ^ (~b48 & b40);
s[47] = b47 ^ (~b49 & b41);
s[8] = b8 ^ (~b0 & b2);
s[9] = b9 ^ (~b1 & b3);
s[18] = b18 ^ (~b10 & b12);
s[19] = b19 ^ (~b11 & b13);
s[28] = b28 ^ (~b20 & b22);
s[29] = b29 ^ (~b21 & b23);
s[38] = b38 ^ (~b30 & b32);
s[39] = b39 ^ (~b31 & b33);
s[48] = b48 ^ (~b40 & b42);
s[49] = b49 ^ (~b41 & b43);
s[0] ^= RC[n];
s[1] ^= RC[n + 1];
}
};
if (COMMON_JS) {
module.exports = methods;
} else {
for (i = 0; i < methodNames.length; ++i) {
root[methodNames[i]] = methods[methodNames[i]];
}
if (AMD) {
define(function () {
return methods;
});
}
}
})();

202
scripts/jsQR license.txt Executable file
View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

10100
scripts/jsQR-1.4.0.js Executable file

File diff suppressed because it is too large Load Diff

593
scripts/json_rpc.js Executable file
View File

@@ -0,0 +1,593 @@
// Use strict
"use strict";
// Classes
// JSON-RPC class
class JsonRpc {
// Public
// Send request
static sendRequest(urlOrUrls, method, parameters = [], headers = {}, numberOfAttempts = JsonRpc.DEFAULT_NUMBER_OF_ATTEMPTS, cancelOccurred = Common.NO_CANCEL_OCCURRED) {
// Return promise
return new Promise(function(resolve, reject) {
// Set current attempt
var currentAttempt = new Promise(function(resolve, reject) {
// Resolve invalid response
resolve(JsonRpc.INVALID_RESPONSE);
});
// Initiaize attempts
var attempts = [currentAttempt];
// Go through all attempts or URLs
for(let i = 0; i < Math.max(numberOfAttempts, (Array.isArray(urlOrUrls) === true) ? urlOrUrls["length"] : [urlOrUrls]["length"]); ++i) {
// Set attempt that runs after the current attempt
currentAttempt = currentAttempt.then(function(response) {
// Return promise
return new Promise(function(resolve, reject) {
// Check if response isn't invalid
if(response !== JsonRpc.INVALID_RESPONSE) {
// Resolve response
resolve(response);
}
// Otherwise
else {
// Get current URL
var currentUrl = (Array.isArray(urlOrUrls) === true) ? urlOrUrls[i % urlOrUrls["length"]] : urlOrUrls;
// Return sending data
return JsonRpc.sendData(currentUrl, method, parameters, headers, JsonRpc.DEFAULT_ID, cancelOccurred).then(function(currentResponse) {
// Resolve current response
resolve(currentResponse);
// Catch errors
}).catch(function(error) {
// Check if at the last attempt, the error's response had an ok, bad request, unauthorized, forbidden, not found, unsupported media type, or payload too large status, or the response is a JSON-RPC error
if(i === Math.max(numberOfAttempts, (Array.isArray(urlOrUrls) === true) ? urlOrUrls["length"] : [urlOrUrls]["length"]) - 1 || error === Common.HTTP_OK_STATUS || error === Common.HTTP_BAD_REQUEST_STATUS || error === Common.HTTP_UNAUTHORIZED_STATUS || error === Common.HTTP_FORBIDDEN_STATUS || error === Common.HTTP_NOT_FOUND_STATUS || error === Common.HTTP_UNSUPPORTED_MEDIA_TYPE_STATUS || error === Common.HTTP_PAYLOAD_TOO_LARGE_STATUS || Object.isObject(error) === true) {
// Reject error
reject(error);
}
// Otherwise
else {
// Resolve invalid response
resolve(JsonRpc.INVALID_RESPONSE);
}
});
}
});
// Catch errors
}).catch(function(error) {
// Return promise
return new Promise(function(resolve, reject) {
// Reject error
reject(error);
});
});
// Append current attempt to list
attempts.push(currentAttempt);
}
// Return trying all attempts
return Promise.all(attempts).then(function(responses) {
// Resolve response
resolve(responses[responses["length"] - 1]);
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
});
}
// Send notification
static sendNotification(urlOrUrls, method, parameters = [], headers = {}, numberOfAttempts = JsonRpc.DEFAULT_NUMBER_OF_ATTEMPTS, cancelOccurred = Common.NO_CANCEL_OCCURRED) {
// Return promise
return new Promise(function(resolve, reject) {
// Set current attempt
var currentAttempt = new Promise(function(resolve, reject) {
// Resolve invalid response
resolve(JsonRpc.INVALID_RESPONSE);
});
// Initiaize attempts
var attempts = [currentAttempt];
// Go through all attempts or URLs
for(let i = 0; i < Math.max(numberOfAttempts, (Array.isArray(urlOrUrls) === true) ? urlOrUrls["length"] : [urlOrUrls]["length"]); ++i) {
// Set attempt that runs after the current attempt
currentAttempt = currentAttempt.then(function(response) {
// Return promise
return new Promise(function(resolve, reject) {
// Check if response isn't invalid
if(response !== JsonRpc.INVALID_RESPONSE) {
// Resolve response
resolve(response);
}
// Otherwise
else {
// Get current URL
var currentUrl = (Array.isArray(urlOrUrls) === true) ? urlOrUrls[i % urlOrUrls["length"]] : urlOrUrls;
// Return sending data
return JsonRpc.sendData(currentUrl, method, parameters, headers, JsonRpc.NO_ID, cancelOccurred).then(function(currentResponse) {
// Resolve current response
resolve(currentResponse);
// Catch errors
}).catch(function(error) {
// Check if at the last attempt, the error's response had an ok, bad request, unauthorized, forbidden, not found, unsupported media type, or payload too large status, or the response is a JSON-RPC error
if(i === Math.max(numberOfAttempts, (Array.isArray(urlOrUrls) === true) ? urlOrUrls["length"] : [urlOrUrls]["length"]) - 1 || error === Common.HTTP_OK_STATUS || error === Common.HTTP_BAD_REQUEST_STATUS || error === Common.HTTP_UNAUTHORIZED_STATUS || error === Common.HTTP_FORBIDDEN_STATUS || error === Common.HTTP_NOT_FOUND_STATUS || error === Common.HTTP_UNSUPPORTED_MEDIA_TYPE_STATUS || error === Common.HTTP_PAYLOAD_TOO_LARGE_STATUS || Object.isObject(error) === true) {
// Reject error
reject(error);
}
// Otherwise
else {
// Resolve invalid response
resolve(JsonRpc.INVALID_RESPONSE);
}
});
}
});
// Catch errors
}).catch(function(error) {
// Return promise
return new Promise(function(resolve, reject) {
// Reject error
reject(error);
});
});
// Append current attempt to list
attempts.push(currentAttempt);
}
// Return trying all attempts
return Promise.all(attempts).then(function(responses) {
// Resolve response
resolve(responses[responses["length"] - 1]);
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
});
}
// Create response
static createResponse(response, requestOrNotification, isError = false) {
// Check if a request is provided
if(Object.isObject(requestOrNotification) === true && "id" in requestOrNotification === true) {
// Check if not error
if(isError === false) {
// Return response
return {
// Version
"jsonrpc": JsonRpc.VERSION,
// ID
"id": requestOrNotification["id"],
// Result
"result": response
};
}
// Otherwise
else {
// Return response
return {
// Version
"jsonrpc": JsonRpc.VERSION,
// ID
"id": requestOrNotification["id"],
// Error
"error": response
};
}
}
// Otherwise
else {
// Return no response
return JsonRpc.NO_RESPONSE;
}
}
// Create error response
static createErrorResponse(error, requestOrNotification, message = JsonRpc.DEFAULT_MESSAGE) {
// Check if message is default message
if(message === JsonRpc.DEFAULT_MESSAGE) {
// Check error
switch(error) {
// Invalid request error
case JsonRpc.INVALID_REQUEST_ERROR:
// Set message
message = Language.getDefaultTranslation('Invalid request');
// Break
break;
// Method not found error
case JsonRpc.METHOD_NOT_FOUND_ERROR:
// Set message
message = Language.getDefaultTranslation('Method not found');
// Break
break;
// Invalid parameters error
case JsonRpc.INVALID_PARAMETERS_ERROR:
// Set message
message = Language.getDefaultTranslation('Invalid parameters');
// Break
break;
// Internal error error
case JsonRpc.INTERNAL_ERROR_ERROR:
// Set message
message = Language.getDefaultTranslation('Internal error');
// Break
break;
}
}
// Return create response
return JsonRpc.createResponse({
// Code
"code": error,
// Message
"message": message
}, requestOrNotification, true);
}
// Is request
static isRequest(data) {
// Return if data is a request
return Object.isObject(data) === true && "jsonrpc" in data === true && data["jsonrpc"] === JsonRpc.VERSION && "id" in data === true && data["id"] instanceof BigNumber === true && data["id"].isInteger() === true && data["id"].isPositive() === true && "method" in data === true && "params" in data === true;
}
// Is notification
static isNotification(data) {
// Return if data is a notification
return Object.isObject(data) === true && "jsonrpc" in data === true && data["jsonrpc"] === JsonRpc.VERSION && "id" in data === false && "method" in data === true && "params" in data === true;
}
// Is error response
static isErrorResponse(response) {
// Return if response is an error
return Object.isObject(response) === true && "jsonrpc" in response === true && response["jsonrpc"] === JsonRpc.VERSION && "id" in response === true && response["id"] instanceof BigNumber === true && response["id"].isInteger() === true && response["id"].isPositive() === true && "error" in response === true && Object.isObject(response["error"]) === true && "code" in response["error"] === true;
}
// No response
static get NO_RESPONSE() {
// Return no response
return null;
}
// Invalid request error
static get INVALID_REQUEST_ERROR() {
// Return invalid request error
return -32600;
}
// Method not found error
static get METHOD_NOT_FOUND_ERROR() {
// Return method not found error
return -32601;
}
// Invalid parameters error
static get INVALID_PARAMETERS_ERROR() {
// Return invalid parameters error
return -32602;
}
// Internal error error
static get INTERNAL_ERROR_ERROR() {
// Return internal error error
return -32603;
}
// Default message
static get DEFAULT_MESSAGE() {
// Return default message
return null;
}
// Private
// Send data
static sendData(url, method, parameters, headers, id, cancelOccurred = Common.NO_CANCEL_OCCURRED) {
// Return promise
return new Promise(function(resolve, reject) {
// Check if cancel didn't occur
if(cancelOccurred === Common.NO_CANCEL_OCCURRED || cancelOccurred() === false) {
// Set data
var data = {
// Version
"jsonrpc": JsonRpc.VERSION,
// Method
"method": method,
// Parameters
"params": parameters
};
// Check if an ID is provided
if(id !== JsonRpc.NO_ID)
// Set data's ID
data["id"] = id;
// Get AJAX request
var ajaxRequest = $.ajax(url, {
// Data
"data": JSONBigNumber.stringify(data),
// Content type
"contentType": "application/json",
// Data type
"dataType": "text",
// Type
"type": "POST",
// Headers
"headers": headers
});
// Initialize cancel allowed
var cancelAllowed = true;
// Abort if canceled
var abortIfCanceled = function() {
// Check if cancel is allowed
if(cancelAllowed === true) {
// Check if cancel occurred
if(cancelOccurred !== Common.NO_CANCEL_OCCURRED && cancelOccurred() === true) {
// Abort AJAX request
ajaxRequest.abort();
}
// Otherwise
else {
// Set timeout
setTimeout(function() {
// Abort if canceled
abortIfCanceled();
}, JsonRpc.AJAX_REQUEST_CANCELED_CHECK_INTERVAL_MILLISECONDS);
}
}
};
// Abort if canceled
abortIfCanceled();
// Return sending AJAX request
return ajaxRequest.then(function(response, status, request) {
// Clear cancel allowed
cancelAllowed = false;
// Check if a response was expected
if(id !== JsonRpc.NO_ID) {
// Try
try {
// Parse response as JSON
response = JSONBigNumber.parse(response);
}
// Catch errors
catch(error) {
// Reject request's status
reject(request["status"]);
// Return
return;
}
// Check if response is invalid
if(Object.isObject(response) === false)
// Reject request's status
reject(request["status"]);
// Otherwise check if response contains an invalid version
else if("jsonrpc" in response === false || response["jsonrpc"] !== JsonRpc.VERSION)
// Reject request's status
reject(request["status"]);
// Otherwise check if response contains an invalid ID
else if("id" in response === false || response["id"] instanceof BigNumber === false || response["id"].isInteger() === false || response["id"].isPositive() === false)
// Reject request's status
reject(request["status"]);
// Otherwise check if response contains an invalid result
else if("error" in response === true || "result" in response === false)
// Reject response's error or request's status
reject(("error" in response === true) ? response["error"] : request["status"]);
// Otherwise
else
// Resolve response's result
resolve(response["result"]);
}
// Otherwise
else {
// Check if a response exists
if(response["length"] !== 0)
// Reject request's status
reject(request["status"]);
// Otherwise
else
// Resolve
resolve();
}
// Catch errors
}).catch(function(request) {
// Clear cancel allowed
cancelAllowed = false;
// Reject request's status
reject(request["status"]);
});
}
// Otherwise
else {
// Reject HTTP no response status
reject(Common.HTTP_NO_RESPONSE_STATUS);
}
});
}
// Version
static get VERSION() {
// Return version
return "2.0";
}
// Default ID
static get DEFAULT_ID() {
// Return default ID
return 1;
}
// Default number of attempts
static get DEFAULT_NUMBER_OF_ATTEMPTS() {
// Return default number of attempts
return 5;
}
// Invalid response
static get INVALID_RESPONSE() {
// Return invalid response
return undefined;
}
// No ID
static get NO_ID() {
// Return no ID
return null;
}
// AJAX request canceled check interval milliseconds
static get AJAX_REQUEST_CANCELED_CHECK_INTERVAL_MILLISECONDS() {
// Return AJAX request canceled check interval milliseconds
return 50;
}
}
// Main function
// Set global object's JSON-RPC
globalThis["JsonRpc"] = JsonRpc;

2021
scripts/language.js Executable file

File diff suppressed because it is too large Load Diff

20
scripts/languages.js Executable file
View File

@@ -0,0 +1,20 @@
<?php
// Included files
require_once __DIR__ . "/../backend/common.php";
require_once __DIR__ . "/../backend/language.php";
// Main function
// Set content type header
header("Content-Type: application/javascript; charset=" . mb_internal_encoding());
?>// Use strict
"use strict";
// Constants
// Available languages
var AVAILABLE_LANGUAGES = <?= json_encode(getAvailableLanguages()); ?>;

229
scripts/legacy_proof_builder.js Executable file
View File

@@ -0,0 +1,229 @@
// Use strict
"use strict";
// Classes
// Legacy proof builder class
class LegacyProofBuilder extends ProofBuilder {
// Public
// Initialize
initialize(extendedPrivateKey) {
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Return deriving root hash from extended private key and root identifier
return Crypto.deriveSecretKey(extendedPrivateKey, new BigNumber(0), new Identifier(Identifier.ROOT_SERIALIZED_IDENTIFIER), Crypto.SWITCH_TYPE_REGULAR).then(function(rootHash) {
// Set root hash
self.rootHash = rootHash;
// Resolve
resolve();
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
});
}
// Uninitialize
uninitialize() {
// Securely clear root hash
this.rootHash.fill(0);
}
// Rewind nonce
rewindNonce(commit) {
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Check if getting nonce from root hash and commit was successful
var nonce = Blake2b.compute(Crypto.NONCE_LENGTH, self.rootHash, commit);
if(nonce !== Blake2b.OPERATION_FAILED) {
// Check if nonce is a valid secret key
if(Secp256k1Zkp.isValidSecretKey(nonce) === true) {
// Resolve nonce
resolve(nonce);
}
// Otherwise
else {
// Securely clear nonce
nonce.fill(0);
// Reject error
reject("Nonce is not a valid secret key.");
}
}
// Otherwise
else {
// Reject error
reject("Getting nonce failed.");
}
});
}
// Private nonce
privateNonce(commit) {
// Return rewind nonce
return this.rewindNonce(commit);
}
// Proof message
proofMessage(identifier, switchType) {
// Create message
var message = new Uint8Array(LegacyProofBuilder.MESSAGE_LENGTH).fill(0);
// Set everything after message's header to the identifier's path value
message = Common.mergeArrays([
// Message header
message.subarray(0, LegacyProofBuilder.MESSAGE_HEADER_LENGTH),
// Identifier's path value
identifier.getValue().subarray(Identifier.PATHS_INDEX)
]);
// Return message
return message;
}
// Get output
getOutput(extendedPrivateKey, amount, commit, message) {
// Return promise
return new Promise(function(resolve, reject) {
// Check if message is valid
if(message["length"] === LegacyProofBuilder.MESSAGE_LENGTH && Common.arraysAreEqual(message.subarray(0, LegacyProofBuilder.MESSAGE_HEADER_START["length"]), LegacyProofBuilder.MESSAGE_HEADER_START) === true) {
// Set switch type
var switchType = LegacyProofBuilder.MESSAGE_SWITCH_TYPE;
// Set depth
var depth = LegacyProofBuilder.MESSAGE_DEPTH;
// Try
try {
// Create identifier from depth and message
var identifier = new Identifier(depth.toString(Common.HEX_NUMBER_BASE).padStart(Common.HEX_NUMBER_LENGTH, Common.HEX_NUMBER_PADDING) + Common.toHexString(message.subarray(LegacyProofBuilder.MESSAGE_HEADER_LENGTH)));
}
// Catch errors
catch(error) {
// Reject error
reject("Identifier isn't valid.");
// Return
return;
}
// Return getting commit from extended private key, amount, identifier, and switch type
return Crypto.commit(extendedPrivateKey, amount, identifier, switchType).then(function(computedCommit) {
// Check if commit matches the computed commit
if(Common.arraysAreEqual(commit, computedCommit) === true) {
// Resolve
resolve([
// Identifier
identifier,
// Switch type
switchType
]);
}
// Otherwise
else {
// Reject error
reject("Output isn't valid.");
}
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
}
// Otherwise
else {
// Reject error
reject("Message isn't valid.");
}
});
}
// Private
// Message header start
static get MESSAGE_HEADER_START() {
// Return message header start
return new Uint8Array([0, 0, 0, 0]);
}
// Message switch type
static get MESSAGE_SWITCH_TYPE() {
// Return message switch type
return Crypto.SWITCH_TYPE_REGULAR;
}
// Message depth
static get MESSAGE_DEPTH() {
// Return message depth
return 3;
}
// Message header length
static get MESSAGE_HEADER_LENGTH() {
// Return message header length
return LegacyProofBuilder.MESSAGE_HEADER_START["length"];
}
// Message length
static get MESSAGE_LENGTH() {
// Return message length
return LegacyProofBuilder.MESSAGE_HEADER_LENGTH + Identifier.MAX_DEPTH * Uint32Array["BYTES_PER_ELEMENT"];
}
}
// Main function
// Set global object's legacy proof builder
globalThis["LegacyProofBuilder"] = LegacyProofBuilder;

1901
scripts/listener.js Executable file

File diff suppressed because it is too large Load Diff

142
scripts/log.js Executable file
View File

@@ -0,0 +1,142 @@
// Use strict
"use strict";
// Classes
// Log class
class Log {
// Public
// Initialize
static initialize() {
// Get log display
Log.logDisplay = $("div.unlocked").find("div.sections").find("div.log");
// Check if log display exists
if(Log.logDisplay["length"] !== 0) {
// Get message display
Log.messageDisplay = Log.logDisplay.find("div.messages");
// Log message
Log.logMessage(Language.getDefaultTranslation('Log initialized.'), [], ACCESS_TIMESTAMP);
// Check if messages exist
if(typeof Log.messages !== "undefined") {
// Go through all messages
for(var i = 0; i < Log.messages["length"]; ++i) {
// Get message
var message = Log.messages[i];
// Log message
Log.logMessage(message[Log.MESSAGE_TEXT_INDEX], message[Log.MESSAGE_TEXT_ARGUMENTS_INDEX], message[Log.MESSAGE_TIMESTAMP_INDEX]);
}
}
}
}
// Log message
static logMessage(text, textArguments = [], timestamp = Date.now()) {
// Check if log has been initialized and the log display exists
if(typeof Log.logDisplay !== "undefined" && Log.logDisplay["length"] !== 0) {
// Get if log display is scrolled to the bottom
var scrollToBottom = Math.abs(Log.logDisplay.get(0)["scrollHeight"] - Log.logDisplay.get(0)["clientHeight"] - Log.logDisplay.get(0)["scrollTop"]) <= Scroll.TOLERANCE || Log.logDisplay.get(0)["scrollHeight"] - Log.logDisplay.get(0)["scrollTop"] <= Log.logDisplay.get(0)["clientHeight"];
// Append message to message display
Log.messageDisplay.append("<p class=\"contextMenu\">" + Language.createTranslatableContainer("<span>", Language.getDefaultTranslation('%1$u:'), [
// Timestamp
timestamp.toFixed()
], "timestamp") + Language.createTranslatableContainer("<span>", Language.getDefaultTranslation('(?<=:) ')) + Language.createTranslatableContainer("<span>", text, textArguments) + "</p>");
// Check if log display was scrolled to the bottom
if(scrollToBottom === true) {
// Request animation frame
requestAnimationFrame(function() {
// Scroll log display to the bottom
Log.logDisplay.get(0)["scrollTop"] = Log.logDisplay.get(0)["scrollHeight"] - Log.logDisplay.get(0)["clientHeight"] + Scroll.TOLERANCE;
});
}
// Trigger message event
$(document).trigger(Log.MESSAGE_EVENT);
}
// Otherwise
else {
// Check if messages doesn't exist
if(typeof Log.messages === "undefined") {
// Create messages
Log.messages = [];
}
// Append message to list
Log.messages.push([
// Text
text,
// Text arguments
textArguments,
// Timestamp
timestamp
]);
}
}
// Message event
static get MESSAGE_EVENT() {
// Return message event
return "LogMessageEvent";
}
// Private
// Message text index
static get MESSAGE_TEXT_INDEX() {
// Return message text index
return 0;
}
// Message text arguments index
static get MESSAGE_TEXT_ARGUMENTS_INDEX() {
// Return message text arguments index
return Log.MESSAGE_TEXT_INDEX + 1;
}
// Message timestamp index
static get MESSAGE_TIMESTAMP_INDEX() {
// Return message timestamp index
return Log.MESSAGE_TEXT_ARGUMENTS_INDEX + 1;
}
}
// Main function
// Set global object's log
globalThis["Log"] = Log;
// Ready event
$(function() {
// Initialize log
Log.initialize();
});

273
scripts/log_section.js Executable file
View File

@@ -0,0 +1,273 @@
// Use strict
"use strict";
// Classes
// Log section class
class LogSection extends Section {
// Public
// Constructor
constructor(display, sections, settings, message, focus, application, unlocked, automaticLock, scroll, wallets, node, wakeLock, transactions, prices, clipboard) {
// Delegate constructor
super(display, sections, settings, message, focus, application, unlocked, automaticLock, scroll, wallets, node, wakeLock, transactions, prices, clipboard);
// Get message display
this.messageDisplay = this.getDisplay().find("div.messages");
// Set message counter
this.messageCounter = 1;
// Set maximum number of messages to setting's default value
this.maximumNumberOfMessages = LogSection.SETTINGS_MAXIMUM_NUMBER_OF_MESSAGES_DEFAULT_VALUE;
// Set scroll to bottom
this.scrollToBottom = true;
// Set self
var self = this;
// Once database is initialized
Database.onceInitialized(function() {
// Return promise
return new Promise(function(resolve, reject) {
// Return creating settings
return Promise.all([
// Maximum number of messages setting
self.getSettings().createValue(LogSection.SETTINGS_MAXIMUM_NUMBER_OF_MESSAGES_NAME, LogSection.SETTINGS_MAXIMUM_NUMBER_OF_MESSAGES_DEFAULT_VALUE)
]).then(function() {
// Initialize settings
var settings = [
// Maximum number of messages setting
LogSection.SETTINGS_MAXIMUM_NUMBER_OF_MESSAGES_NAME,
];
// Return getting settings' values
return Promise.all(settings.map(function(setting) {
// Return getting setting's value
return self.getSettings().getValue(setting);
})).then(function(settingValues) {
// Set maximum number of messages to setting's value
self.maximumNumberOfMessages = settingValues[settings.indexOf(LogSection.SETTINGS_MAXIMUM_NUMBER_OF_MESSAGES_NAME)];
// Resolve
resolve();
// Catch errors
}).catch(function(error) {
// Reject
reject();
});
// Catch errors
}).catch(function(error) {
// Reject
reject();
});
});
});
// Settings change event
$(this.getSettings()).on(Settings.CHANGE_EVENT, function(event, setting) {
// Check what setting was changes
switch(setting[Settings.DATABASE_SETTING_NAME]) {
// Maximum number of messages setting
case LogSection.SETTINGS_MAXIMUM_NUMBER_OF_MESSAGES_NAME:
// Set maximum number of messages to setting's value
self.maximumNumberOfMessages = setting[Settings.DATABASE_VALUE_NAME];
// Truncate messages
self.truncateMessages();
// Break
break;
}
});
// Check if get selection is supported
if(typeof getSelection !== "undefined") {
// Main copy event
$("main").on("copy", function(event) {
// Check if shown
if(self.isShown() === true) {
// Prevent default
event.preventDefault();
// Get selection without duplicate newlines
var selection = Common.removeDuplicateNewlines(getSelection().toString());
// Set clipboard data to the new selection
event["originalEvent"]["clipboardData"].setData("text/plain", selection);
}
});
}
// Display scroll event
this.getDisplay().on("scroll", function(event) {
// Check if shown
if(self.isShown() === true) {
// Update scroll to bottom
self.scrollToBottom = Math.abs(self.getDisplay().get(0)["scrollHeight"] - self.getDisplay().get(0)["clientHeight"] - self.getDisplay().get(0)["scrollTop"]) <= Scroll.TOLERANCE || self.getDisplay().get(0)["scrollHeight"] - self.getDisplay().get(0)["scrollTop"] <= self.getDisplay().get(0)["clientHeight"];
}
// Display language change event
}).on(Language.CHANGE_EVENT, function() {
// Check if scroll to bottom
if(self.scrollToBottom === true) {
// Scroll display to the bottom
self.getDisplay().get(0)["scrollTop"] = self.getDisplay().get(0)["scrollHeight"] - self.getDisplay().get(0)["clientHeight"] + Scroll.TOLERANCE;
}
});
// Document log message event
$(document).on(Log.MESSAGE_EVENT, function() {
// Increment message counter
++self.messageCounter;
// Truncate messages
self.truncateMessages();
});
// Section shown event
$(this).on(Section.SHOWN_EVENT, function() {
// Check if scroll to bottom
if(self.scrollToBottom === true) {
// Request animation frame
requestAnimationFrame(function() {
// Scroll display to the bottom
self.getDisplay().get(0)["scrollTop"] = self.getDisplay().get(0)["scrollHeight"] - self.getDisplay().get(0)["clientHeight"] + Scroll.TOLERANCE;
});
}
});
// Window resize event
$(window).on("resize", function() {
// Check if scroll to bottom
if(self.scrollToBottom === true) {
// Scroll display to the bottom
self.getDisplay().get(0)["scrollTop"] = self.getDisplay().get(0)["scrollHeight"] - self.getDisplay().get(0)["clientHeight"] + Scroll.TOLERANCE;
}
});
}
// Get name
getName() {
// Return name
return LogSection.NAME;
}
// Reset
reset() {
// Reset
super.reset();
}
// Name
static get NAME() {
// Return name
return "Log";
}
// Private
// Initialize
initialize(state) {
// Set base class initialize
var baseClassInitialize = super.initialize(state);
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Return initializing base class
return baseClassInitialize.then(function() {
// Resolve
resolve();
// Reject error
}).catch(function(error) {
// Reject error
reject(error);
});
});
}
// Get initialize error header
getInitializeErrorHeader() {
// Return initialize error header
return Language.getDefaultTranslation('Log Error');
}
// Truncate messages
truncateMessages() {
// Check if too many messages exist
if(this.messageCounter > this.maximumNumberOfMessages) {
// Remove earlier messages
this.messageDisplay.children("p:lt(" + (this.messageCounter - this.maximumNumberOfMessages).toFixed() + ")").remove();
// Update message counter
this.messageCounter = this.maximumNumberOfMessages;
}
}
// Settings maximum number of messages name
static get SETTINGS_MAXIMUM_NUMBER_OF_MESSAGES_NAME() {
// Return settings maximum number of messages name
return "Maximum Number Of Messages";
}
// Settings maximum number of messages default value
static get SETTINGS_MAXIMUM_NUMBER_OF_MESSAGES_DEFAULT_VALUE() {
// Return settings maximum number of messages default value
return 1000;
}
}
// Main function
// Set global object's log section
globalThis["LogSection"] = LogSection;

1931
scripts/logo.js Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,185 @@
// Use strict
"use strict";
// Classes
// Maintenance notification class
class MaintenanceNotification {
// Public
// Constructor
constructor() {
// Get maintenance notification display
this.maintenanceNotificationDisplay = $("section.maintenanceNotification");
// Get acknowledge button
this.acknowledgeButton = this.maintenanceNotificationDisplay.find("button");
// Get start timestamp
this.startTimestamp = (MAINTENANCE_START_TIME["length"] !== 0) ? Date.parse(MAINTENANCE_START_TIME) / Common.MILLISECONDS_IN_A_SECOND : 0;
// Set can show
this.canShow = true;
// Set self
var self = this;
// Maintenance notification display transaition end event
this.maintenanceNotificationDisplay.on("transitionend", function() {
// Check if maintenance notification display is hiding
if(self.maintenanceNotificationDisplay.hasClass("hide") === true)
// Prevent focus on maintenance notification display's elements
self.maintenanceNotificationDisplay.addClass("noFocus");
});
// Window storage event
$(window).on("storage", function(event) {
// Check if maintenance notification message acknowledged timestamp was changed and it's as recent or newer than the start timestamp
if(event["originalEvent"]["key"] === MaintenanceNotification.MAINTENANCE_NOTIFICATION_MESSAGE_ACKNOWLEDGED_TIMESTAMP_LOCAL_STORAGE_NAME && parseInt(event["originalEvent"]["newValue"], Common.DECIMAL_NUMBER_BASE) >= self.startTimestamp) {
// Hide
self.hide();
// Clear can show
self.canShow = false;
}
});
// Acknowledged button click event
this.acknowledgeButton.on("click", function() {
// Hide
self.hide();
// Clear can show
self.canShow = false;
// Try
try {
// Save maintenance notification message acknowledged timestamp
localStorage.setItem(MaintenanceNotification.MAINTENANCE_NOTIFICATION_MESSAGE_ACKNOWLEDGED_TIMESTAMP_LOCAL_STORAGE_NAME, self.startTimestamp.toFixed());
}
// Catch errors
catch(error) {
// Trigger a fatal error
new FatalError(FatalError.LOCAL_STORAGE_ERROR);
}
});
}
// Show
show() {
// Check if can show
if(this.canShow === true) {
// Check if not an extension and not loading from file
if(Common.isExtension() === false && location["protocol"] !== Common.FILE_PROTOCOL) {
// Get the current timestamp
var currentTimestamp = Common.getCurrentTimestamp();
// Check if current timestamp is older than the start timestamp
if(currentTimestamp <= this.startTimestamp) {
// Get maintenance notification message acknowledged timestamp
var maintenanceNotificationMessageAcknowledgedTimestamp = localStorage.getItem(MaintenanceNotification.MAINTENANCE_NOTIFICATION_MESSAGE_ACKNOWLEDGED_TIMESTAMP_LOCAL_STORAGE_NAME);
// Check if maintenance notification message hasn't been acknowledged or it was acknowledged as an older timestamp
if(maintenanceNotificationMessageAcknowledgedTimestamp === Common.INVALID_LOCAL_STORAGE_ITEM || parseInt(maintenanceNotificationMessageAcknowledgedTimestamp, Common.DECIMAL_NUMBER_BASE) < this.startTimestamp) {
// Check if is an app
if(Common.isApp() === true) {
// Set message
var message = Language.getDefaultTranslation('This app will be down for scheduled maintenance starting on %1$d at %2$t.');
}
// Otherwise
else {
// Set message
var message = Language.getDefaultTranslation('This site will be down for scheduled maintenance starting on %1$d at %2$t.');
}
// Add maintenance notification display text to maintenance notification display
this.maintenanceNotificationDisplay.find("button").before(Language.createTranslatableContainer("<p>", message, [
// Start timestamp
this.startTimestamp.toFixed(),
// Start timestamp
this.startTimestamp.toFixed()
]));
// Show maintenance notification display and make it so that its elements can be focused
this.maintenanceNotificationDisplay.removeClass("hide noFocus");
// Check if a timeout can be set for the start timestamp
if((this.startTimestamp - currentTimestamp) * Common.MILLISECONDS_IN_A_SECOND <= Common.INT32_MAX_VALUE) {
// Check if not closing when done processing extension requests
if(Extension.getCloseWhenDone() === false) {
// Set timeout
setTimeout(function() {
// Prevent extension from interrupting on close
Extension.preventInterruptOnClose();
// Go to maintenance page
location.replace(((location["protocol"] === Common.HTTPS_PROTOCOL) ? Common.HTTPS_PROTOCOL : Common.HTTP_PROTOCOL) + "//" + location["hostname"] + MaintenanceNotification.MAINTENANCE_PAGE_URL);
}, (this.startTimestamp - currentTimestamp) * Common.MILLISECONDS_IN_A_SECOND);
}
}
// Return true
return true;
}
}
}
}
// Return false
return false;
}
// Private
// Hide
hide() {
// Hide maintenance notification display
this.maintenanceNotificationDisplay.addClass("hide");
}
// Maintenance notification message acknowledged local storage name
static get MAINTENANCE_NOTIFICATION_MESSAGE_ACKNOWLEDGED_TIMESTAMP_LOCAL_STORAGE_NAME() {
// Return maintenance notification message acknowledged timestamp local storage name
return "Maintenance Notification Message Acknowledged Timestamp";
}
// Maintenance page URL
static get MAINTENANCE_PAGE_URL() {
// Return maintenance page URL
return "/errors/503.html";
}
}
// Main function
// Set global object's maintenance notification
globalThis["MaintenanceNotification"] = MaintenanceNotification;

1785
scripts/message.js Executable file

File diff suppressed because it is too large Load Diff

1414
scripts/mqs.js Executable file

File diff suppressed because it is too large Load Diff

331
scripts/new_proof_builder.js Executable file
View File

@@ -0,0 +1,331 @@
// Use strict
"use strict";
// Classes
// New proof builder class
class NewProofBuilder extends ProofBuilder {
// Public
// Initialize
initialize(extendedPrivateKey) {
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Return deriving secret key from extended private key and root identifier
return Crypto.deriveSecretKey(extendedPrivateKey, new BigNumber(0), new Identifier(Identifier.ROOT_SERIALIZED_IDENTIFIER), Crypto.SWITCH_TYPE_NONE).then(function(secretKey) {
// Check if getting private hash from secret key was successful
self.privateHash = Blake2b.compute(Crypto.NONCE_LENGTH, secretKey, new Uint8Array([]));
if(self.privateHash !== Blake2b.OPERATION_FAILED) {
// Securely clear secret key
secretKey.fill(0);
// Return getting root public key from extended private key
return Crypto.rootPublicKey(extendedPrivateKey).then(function(publicKey) {
// Check if getting rewind hash from public key was successful
self.rewindHash = Blake2b.compute(Crypto.NONCE_LENGTH, publicKey, new Uint8Array([]));
if(self.rewindHash !== Blake2b.OPERATION_FAILED) {
// Securely clear public key
publicKey.fill(0);
// Resolve
resolve();
}
// Otherwise
else {
// Securely clear private hash
self.privateHash.fill(0);
// Securely clear public key
publicKey.fill(0);
// Reject error
reject("Getting Rewind hash failed.");
}
// Catch errors
}).catch(function(error) {
// Securely clear private hash
self.privateHash.fill(0);
// Reject error
reject(error);
});
}
// Otherwise
else {
// Securely clear secret key
secretKey.fill(0);
// Reject error
reject("Getting private hash failed.");
}
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
});
}
// Uninitialize
uninitialize() {
// Securely clear private hash
this.privateHash.fill(0);
// Securely clear rewind hash
this.rewindHash.fill(0);
}
// Rewind nonce
rewindNonce(commit) {
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Check if getting nonce from rewind hash and commit was successful
var nonce = Blake2b.compute(Crypto.NONCE_LENGTH, self.rewindHash, commit);
if(nonce !== Blake2b.OPERATION_FAILED) {
// Check if nonce is a valid secret key
if(Secp256k1Zkp.isValidSecretKey(nonce) === true) {
// Resolve nonce
resolve(nonce);
}
// Otherwise
else {
// Securely clear nonce
nonce.fill(0);
// Reject error
reject("Nonce is not a valid secret key.");
}
}
// Otherwise
else {
// Reject error
reject("Getting nonce failed.");
}
});
}
// Private nonce
privateNonce(commit) {
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Check if getting nonce from private hash and commit was successful
var nonce = Blake2b.compute(Crypto.NONCE_LENGTH, self.privateHash, commit);
if(nonce !== Blake2b.OPERATION_FAILED) {
// Check if nonce is a valid secret key
if(Secp256k1Zkp.isValidSecretKey(nonce) === true) {
// Resolve nonce
resolve(nonce);
}
// Otherwise
else {
// Securely clear nonce
nonce.fill(0);
// Reject error
reject("Nonce is not a valid secret key.");
}
}
// Otherwise
else {
// Reject error
reject("Getting nonce failed.");
}
});
}
// Proof message
proofMessage(identifier, switchType) {
// Create message
var message = new Uint8Array(NewProofBuilder.MESSAGE_LENGTH).fill(0);
// Set message's switch type
message[NewProofBuilder.MESSAGE_SWITCH_TYPE_INDEX] = switchType;
// Set everything after message's switch type to the identifier's value
message = Common.mergeArrays([
// Message switch type
message.subarray(0, NewProofBuilder.MESSAGE_SWITCH_TYPE_INDEX + 1),
// Identifier's value
identifier.getValue().subarray(0, NewProofBuilder.MESSAGE_LENGTH - (NewProofBuilder.MESSAGE_SWITCH_TYPE_INDEX + 1))
]);
// Return message
return message;
}
// Get output
getOutput(extendedPrivateKey, amount, commit, message) {
// Return promise
return new Promise(function(resolve, reject) {
// Check if message is valid
if(message["length"] === NewProofBuilder.MESSAGE_LENGTH && Common.arraysAreEqual(message.subarray(0, NewProofBuilder.MESSAGE_HEADER_START["length"]), NewProofBuilder.MESSAGE_HEADER_START) === true) {
// Get switch type from message
var switchType = message[NewProofBuilder.MESSAGE_SWITCH_TYPE_INDEX];
// Check if switch type is valid
if(switchType === Crypto.SWITCH_TYPE_NONE || switchType === Crypto.SWITCH_TYPE_REGULAR) {
// Get depth from message
var depth = message[NewProofBuilder.MESSAGE_DEPTH_INDEX];
// Try
try {
// Create identifier from depth and message
var identifier = new Identifier(depth.toString(Common.HEX_NUMBER_BASE).padStart(Common.HEX_NUMBER_LENGTH, Common.HEX_NUMBER_PADDING) + Common.toHexString(message.subarray(NewProofBuilder.MESSAGE_HEADER_LENGTH)));
}
// Catch errors
catch(error) {
// Reject error
reject("Identifier isn't valid.");
// Return
return;
}
// Return getting commit from extended private key, amount, identifier, and switch type
return Crypto.commit(extendedPrivateKey, amount, identifier, switchType).then(function(computedCommit) {
// Check if commit matches the computed commit
if(Common.arraysAreEqual(commit, computedCommit) === true) {
// Resolve output
resolve([
// Identifier
identifier,
// Switch type
switchType
]);
}
// Otherwise
else {
// Reject error
reject("Output isn't valid.");
}
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
}
// Otherwise
else {
// Reject error
reject("Switch type isn't valid.");
}
}
// Otherwise
else {
// Reject error
reject("Message isn't valid.");
}
});
}
// Private
// Message header start
static get MESSAGE_HEADER_START() {
// Return message header start
return new Uint8Array([0, 0]);
}
// Message switch type index
static get MESSAGE_SWITCH_TYPE_INDEX() {
// Return message switch type index
return NewProofBuilder.MESSAGE_HEADER_START["length"];
}
// Message depth index
static get MESSAGE_DEPTH_INDEX() {
// Return message depth index
return NewProofBuilder.MESSAGE_SWITCH_TYPE_INDEX + 1;
}
// Message header length
static get MESSAGE_HEADER_LENGTH() {
// Return message header length
return NewProofBuilder.MESSAGE_DEPTH_INDEX + 1;
}
// Message length
static get MESSAGE_LENGTH() {
// Return message length
return NewProofBuilder.MESSAGE_HEADER_LENGTH + Identifier.MAX_DEPTH * Uint32Array["BYTES_PER_ELEMENT"];
}
}
// Main function
// Set global object's new proof builder
globalThis["NewProofBuilder"] = NewProofBuilder;

3156
scripts/node.js Executable file

File diff suppressed because it is too large Load Diff

762
scripts/output.js Executable file
View File

@@ -0,0 +1,762 @@
// Use strict
"use strict";
// Classes
// Output class
class Output {
// Public
// Initialize
static initialize() {
// Initialize request index
Output.requestIndex = 0;
// Initialize worker index
Output.workerIndex = 0;
// Initialize workers
Output.workers = [];
// Get the number of processors or the default number of processors if not available
var numberOfProcessors = ("hardwareConcurrency" in navigator === true) ? navigator["hardwareConcurrency"] : Output.DEFAULT_NUMBER_OF_PROCESSORS;
// Check if device has low memory
if(Common.isLowMemoryDevice() === true)
// Only create one worker to reduce memory usage
numberOfProcessors = 1;
// Go through all of the processors
for(var i = 0; i < numberOfProcessors; ++i)
// Create worker and append it to list of workers
Output.workers.push(new Worker(Output.WORKER_FILE_LOCATION));
// Window before unload event
$(window).on("beforeunload", function() {
// Go through all of the workers
for(var i = 0; i < Output.workers["length"]; ++i) {
// Get worker
var worker = Output.workers[i];
// Get current request index
var currentRequestIndex = Output.requestIndex++;
// Check if current request index is at the max safe integer
if(currentRequestIndex === Number.MAX_SAFE_INTEGER)
// Reset request index
Output.requestIndex = 0;
// Send worker an uninitialize request
worker.postMessage([
// Request index
currentRequestIndex,
// Type
Output.UNINITIALIZE_REQUEST_TYPE
]);
// Terminate worker
worker.terminate();
}
});
// Return promise
return new Promise(function(resolve, reject) {
// Initialize initialize workers
var initializeWorkers = [];
// Go through all of the workers
for(var i = 0; i < Output.workers["length"]; ++i) {
// Get worker
let worker = Output.workers[i];
// Append initializing worker to list
initializeWorkers.push(new Promise(function(resolve, reject) {
// Worker on error
worker["onerror"] = function() {
// Reject error
reject("Failed to create output worker.");
};
// Worker on message
worker["onmessage"] = function(event) {
// Get message
var message = event["data"];
// Get message's request index
var requestIndex = message[Output.MESSAGE_REQUEST_INDEX_OFFSET];
// Check message's type
switch(message[Output.MESSAGE_TYPE_OFFSET]) {
// Initialize request type
case Output.INITIALIZE_REQUEST_TYPE:
// Get message's status
var status = message[Output.MESSAGE_STATUS_OFFSET];
// Check if worker initialized successfully
if(status === Output.STATUS_SUCCESS_VALUE)
// Resolve
resolve();
// Otherwise
else
// Reject error
reject("Failed to initialize output worker.");
// Break
break;
// Default
default:
// Get message's response
var response = message[Output.MESSAGE_RESPONSE_OFFSET];
// Trigger response request index event
$(document).trigger(Output.RESPONSE_EVENT + requestIndex.toFixed(), [
// Response
response
]);
// Break
break;
}
};
}));
// Get current request index
var currentRequestIndex = Output.requestIndex++;
// Check if current request index is at the max safe integer
if(currentRequestIndex === Number.MAX_SAFE_INTEGER)
// Reset request index
Output.requestIndex = 0;
// Send worker an initialize request
worker.postMessage([
// Request index
currentRequestIndex,
// Type
Output.INITIALIZE_REQUEST_TYPE,
// URL query string
Common.URL_QUERY_STRING_SEPARATOR + encodeURIComponent(Consensus.OVERRIDE_WALLET_TYPE_URL_PARAMETER_NAME).replace(/%20/ug, "+") + Common.URL_QUERY_STRING_PARAMETER_VALUE_SEPARATOR + encodeURIComponent(Consensus.walletTypeToText(Consensus.getWalletType())).replace(/%20/ug, "+") + Common.URL_QUERY_STRING_PARAMETER_SEPARATOR + encodeURIComponent(Consensus.OVERRIDE_NETWORK_TYPE_URL_PARAMETER_NAME).replace(/%20/ug, "+") + Common.URL_QUERY_STRING_PARAMETER_VALUE_SEPARATOR + encodeURIComponent(Consensus.networkTypeToText(Consensus.getNetworkType())).replace(/%20/ug, "+")
]);
}
// Return initializing all workers
return Promise.all(initializeWorkers).then(function() {
// Resolve
resolve();
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
});
}
// Constructor
constructor(commit, proof, type, height) {
// Set commit
this.commit = commit;
// Set proof
this.proof = proof;
// Set type
this.type = type;
// Set height
this.height = height;
// Set maturity height
this.maturityHeight = (this.isCoinbase() === true) ? this.getHeight().plus(Consensus.COINBASE_MATURITY - 1) : this.getHeight();
}
// Get commit
getCommit() {
// Return commit
return this.commit;
}
// Get proof
getProof() {
// Return proof
return this.proof;
}
// Is coinbase
isCoinbase() {
// Return if type is coinbase type
return this.type === Output.COINBASE_TYPE;
}
// Is transaction
isTransaction() {
// Return is type is transaction type
return this.type === Output.TRANSACTION_TYPE;
}
// Get height
getHeight() {
// Return height
return this.height;
}
// Get maturity height
getMaturityHeight() {
// Return maturity height
return this.maturityHeight;
}
// Get information
getInformation(extendedPrivateKeyOrRootPublicKey, isMainnet) {
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Check if an extended private key is provided
if(extendedPrivateKeyOrRootPublicKey["length"] !== Crypto.SECP256K1_PUBLIC_KEY_LENGTH) {
// Get extended private key
var extendedPrivateKey = extendedPrivateKeyOrRootPublicKey;
// Return getting output legacy information
return self.getLegacyOutputInformation(extendedPrivateKey, isMainnet).then(function(legacyOutputInformation) {
// Check if legacy output information is no information
if(legacyOutputInformation === Output.NO_INFORMATION) {
// Return getting new output infromation
return self.getNewOutputInformation(extendedPrivateKey).then(function(newOutputInformation) {
// Resolve new output information
resolve(newOutputInformation);
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
}
// Otherwise
else {
// Resolve legacy output information
resolve(legacyOutputInformation);
}
// Catch errors
}).catch(function(error) {
// Return getting new output infromation
return self.getNewOutputInformation(extendedPrivateKey).then(function(newOutputInformation) {
// Resolve new output information
resolve(newOutputInformation);
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
});
}
// Otherwise
else {
// Get root public key
var rootPublicKey = extendedPrivateKeyOrRootPublicKey;
// Return getting view output infromation
return self.getViewOutputInformation(rootPublicKey).then(function(viewOutputInformation) {
// Resolve view output information
resolve(viewOutputInformation);
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
}
});
}
// No information
static get NO_INFORMATION() {
// Return no information
return null;
}
// Coinbase type
static get COINBASE_TYPE() {
// Return coinbase type
return "Coinbase";
}
// Transaction type
static get TRANSACTION_TYPE() {
// Return transaction type
return "Transaction";
}
// Initialize request type
static get INITIALIZE_REQUEST_TYPE() {
// Return initialize request type
return 0;
}
// Uninitialize request type
static get UNINITIALIZE_REQUEST_TYPE() {
// Return uninitialize request type
return Output.INITIALIZE_REQUEST_TYPE + 1;
}
// Legacy information request type
static get LEGACY_INFORMATION_REQUEST_TYPE() {
// Return legacy information request type
return Output.UNINITIALIZE_REQUEST_TYPE + 1;
}
// New information request type
static get NEW_INFORMATION_REQUEST_TYPE() {
// Return new information request type
return Output.LEGACY_INFORMATION_REQUEST_TYPE + 1;
}
// View information request type
static get VIEW_INFORMATION_REQUEST_TYPE() {
// Return view information request type
return Output.NEW_INFORMATION_REQUEST_TYPE + 1;
}
// Message request index offset
static get MESSAGE_REQUEST_INDEX_OFFSET() {
// Return message request index offset
return 0;
}
// Message type offset
static get MESSAGE_TYPE_OFFSET() {
// Return message type offset
return Output.MESSAGE_REQUEST_INDEX_OFFSET + 1;
}
// Message initialize URL query string offset
static get MESSAGE_INITIALIZE_URL_QUERY_STRING_OFFSET() {
// Return message initialize URL query string offset
return Output.MESSAGE_TYPE_OFFSET + 1;
}
// Message proof offset
static get MESSAGE_PROOF_OFFSET() {
// Return message proof offset
return Output.MESSAGE_TYPE_OFFSET + 1;
}
// Message commit offset
static get MESSAGE_COMMIT_OFFSET() {
// Return message commit offset
return Output.MESSAGE_PROOF_OFFSET + 1;
}
// Message extended private key or root public key offset
static get MESSAGE_EXTENDED_PRIVATE_KEY_OR_ROOT_PUBLIC_KEY_OFFSET() {
// Return message extended private key or root public key offset
return Output.MESSAGE_COMMIT_OFFSET + 1;
}
// Status success value
static get STATUS_SUCCESS_VALUE() {
// Return status success value
return true;
}
// Status failed value
static get STATUS_FAILED_VALUE() {
// Return status failed value
return false;
}
// Private
// Send request
static sendRequest(request) {
// Get current request index
var currentRequestIndex = Output.requestIndex++;
// Check if current request index is at the max safe integer
if(currentRequestIndex === Number.MAX_SAFE_INTEGER)
// Reset request index
Output.requestIndex = 0;
// Add current request index to request
request.unshift(currentRequestIndex);
// Return promise
return new Promise(function(resolve, reject) {
// Response current request index event
$(document).one(Output.RESPONSE_EVENT + currentRequestIndex.toFixed(), function(event, response) {
// Resolve response
resolve(response);
});
// Send worker at worker index the request
Output.workers[Output.workerIndex].postMessage(request);
// Increment worker index
Output.workerIndex = (Output.workerIndex + 1) % Output.workers["length"];
});
}
// Get legacy output information
getLegacyOutputInformation(extendedPrivateKey, isMainnet) {
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Check wallet type
switch(Consensus.getWalletType()) {
// MWC or GRIN wallet
case Consensus.MWC_WALLET_TYPE:
case Consensus.GRIN_WALLET_TYPE:
// Get legacy previous weeks ago
var legacyPreviousWeeksAgo = self.getHeight().minus(Output.LEGACY_PREVIOUS_BLOCKS_CHECK_DURATION);
if(legacyPreviousWeeksAgo.isLessThan(0) === true)
legacyPreviousWeeksAgo = new BigNumber(0);
// Set perform legacy check to if the output could be legacy
var performLegacyCheck = Consensus.isValidHeaderVersion(isMainnet, legacyPreviousWeeksAgo, Consensus.LEGACY_HEADER_VERSION) === true;
// Break
break;
// EPIC wallet
case Consensus.EPIC_WALLET_TYPE:
// Set perform legacy check
var performLegacyCheck = true;
// Break
break;
}
// Check if performing legacy check
if(performLegacyCheck === true) {
// Return sending legacy information request
return Output.sendRequest([
// Type
Output.LEGACY_INFORMATION_REQUEST_TYPE,
// Proof
self.getProof(),
// Commit
self.getCommit(),
// Extended private key
extendedPrivateKey
]).then(function(response) {
// Check if response is no information
if(response === Output.NO_INFORMATION)
// Resolve no information
resolve(Output.NO_INFORMATION);
// Otherwise
else {
// Get amount from response
var amount = Common.unserializeObject(response[Output.RESPONSE_AMOUNT_INDEX]);
// Get identifier from response
var identifier = Common.unserializeObject(response[Output.RESPONSE_IDENTIFIER_INDEX]);
// Get switch type from response
var switchType = response[Output.RESPONSE_SWITCH_TYPE_INDEX];
// Create legacy output information
var legacyOutputInformation = new OutputInformation(self, amount, identifier, switchType);
// Resolve legacy output information
resolve(legacyOutputInformation);
}
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
}
// Otherwise
else {
// Resolve no information
resolve(Output.NO_INFORMATION);
}
});
}
// Get new output information
getNewOutputInformation(extendedPrivateKey) {
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Return sending new information request
return Output.sendRequest([
// Type
Output.NEW_INFORMATION_REQUEST_TYPE,
// Proof
self.getProof(),
// Commit
self.getCommit(),
// Extended private key
extendedPrivateKey
]).then(function(response) {
// Check if response is no information
if(response === Output.NO_INFORMATION)
// Resolve no information
resolve(Output.NO_INFORMATION);
// Otherwise
else {
// Get amount from response
var amount = Common.unserializeObject(response[Output.RESPONSE_AMOUNT_INDEX]);
// Get identifier from response
var identifier = Common.unserializeObject(response[Output.RESPONSE_IDENTIFIER_INDEX]);
// Get switch type from response
var switchType = response[Output.RESPONSE_SWITCH_TYPE_INDEX];
// Create new output information
var newOutputInformation = new OutputInformation(self, amount, identifier, switchType);
// Resolve new output information
resolve(newOutputInformation);
}
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
});
}
// Get view output information
getViewOutputInformation(extendedPrivateKeyOrRootPublicKey) {
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Return sending view information request
return Output.sendRequest([
// Type
Output.VIEW_INFORMATION_REQUEST_TYPE,
// Proof
self.getProof(),
// Commit
self.getCommit(),
// Extended private key or root public key
extendedPrivateKeyOrRootPublicKey
]).then(function(response) {
// Check if response is no information
if(response === Output.NO_INFORMATION)
// Resolve no information
resolve(Output.NO_INFORMATION);
// Otherwise
else {
// Get amount from response
var amount = Common.unserializeObject(response[Output.RESPONSE_AMOUNT_INDEX]);
// Get identifier from response
var identifier = Common.unserializeObject(response[Output.RESPONSE_IDENTIFIER_INDEX]);
// Get switch type from response
var switchType = response[Output.RESPONSE_SWITCH_TYPE_INDEX];
// Create view output information
var viewOutputInformation = new OutputInformation(self, amount, identifier, switchType);
// Resolve view output information
resolve(viewOutputInformation);
}
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
});
}
// Message status offset
static get MESSAGE_STATUS_OFFSET() {
// Return message status offset
return Output.MESSAGE_TYPE_OFFSET + 1;
}
// Message response offset
static get MESSAGE_RESPONSE_OFFSET() {
// Return message response offset
return Output.MESSAGE_TYPE_OFFSET + 1;
}
// Response event
static get RESPONSE_EVENT() {
// Return response event
return "OutputResponseEvent";
}
// Response amount index
static get RESPONSE_AMOUNT_INDEX() {
// Return response amount index
return 0;
}
// Response identifier index
static get RESPONSE_IDENTIFIER_INDEX() {
// Return response identifier index
return Output.RESPONSE_AMOUNT_INDEX + 1;
}
// Response switch type index
static get RESPONSE_SWITCH_TYPE_INDEX() {
// Return response switch type index
return Output.RESPONSE_IDENTIFIER_INDEX + 1;
}
// Default number of processors
static get DEFAULT_NUMBER_OF_PROCESSORS() {
// Return default number of processors
return 1;
}
// Legacy previous blocks check duration
static get LEGACY_PREVIOUS_BLOCKS_CHECK_DURATION() {
// Return legacy previous blocks check duration
return 2 * Consensus.BLOCK_HEIGHT_WEEK;
}
// Worker file location
static get WORKER_FILE_LOCATION() {
// Return worker file location
return "." + getResource("./scripts/output_worker.js");
}
}
// Main function
// Set global object's output
globalThis["Output"] = Output;

61
scripts/output_information.js Executable file
View File

@@ -0,0 +1,61 @@
// Use strict
"use strict";
// Classes
// Output information class
class OutputInformation {
// Public
// Constructor
constructor(output, amount, identifier, switchType) {
// Set output
this.output = output;
// Set amount
this.amount = amount;
// Set identifier
this.identifier = identifier;
// Set switch type
this.switchType = switchType;
}
// Get output
getOutput() {
// Return output
return this.output;
}
// Get amount
getAmount() {
// Return amount
return this.amount;
}
// Get identifier
getIdentifier() {
// Return identifier
return this.identifier;
}
// Get switch type
getSwitchType() {
// Return switch type
return this.switchType;
}
}
// Main function
// Set global object's output information
globalThis["OutputInformation"] = OutputInformation;

392
scripts/output_worker.js Executable file
View File

@@ -0,0 +1,392 @@
<?php
// Included files
require_once __DIR__ . "/../backend/common.php";
require_once __DIR__ . "/../backend/resources.php";
// Main function
// Set content type header
header("Content-Type: application/javascript; charset=" . mb_internal_encoding());
?>// Use strict
"use strict";
// Import scripts
importScripts(".<?= escapeString(getResource("./scripts/BLAKE2b-0.0.2.js")); ?>");
importScripts(".<?= escapeString(getResource("./scripts/secp256k1-zkp-0.0.29.js")); ?>");
importScripts(".<?= escapeString(getResource("./scripts/bignumber.js-9.1.1.js")); ?>");
importScripts(".<?= escapeString(getResource("./scripts/common.js")); ?>");
importScripts(".<?= escapeString(getResource("./scripts/crypto.js")); ?>");
importScripts(".<?= escapeString(getResource("./scripts/identifier.js")); ?>");
importScripts(".<?= escapeString(getResource("./scripts/proof_builder.js")); ?>");
importScripts(".<?= escapeString(getResource("./scripts/legacy_proof_builder.js")); ?>");
importScripts(".<?= escapeString(getResource("./scripts/new_proof_builder.js")); ?>");
importScripts(".<?= escapeString(getResource("./scripts/view_proof_builder.js")); ?>");
importScripts(".<?= escapeString(getResource("./scripts/output.js")); ?>");
// Constants
// Files
const FILES = <?= json_encode($files); ?>;
// Dependencies initializations
const DEPENDENCIES_INITIALIZATIONS = [
// BLAKE2b initialize
Blake2b.initialize,
// Secp256k1-zkp initialize
Secp256k1Zkp.initialize
];
// Dependencies uninitializations
const DEPENDENCIES_UNINITIALIZATIONS = [
// Secp256k1-zkp uninitialize
Secp256k1Zkp.uninitialize
];
// Global variables
// URL query string
var URL_QUERY_STRING;
// Events
// Message event
self.addEventListener("message", function(event) {
// Get message
var message = event["data"];
// Get message's request index
var requestIndex = message[Output.MESSAGE_REQUEST_INDEX_OFFSET];
// Get message's type
var type = message[Output.MESSAGE_TYPE_OFFSET];
// Check type
switch(type) {
// Initialize request type
case Output.INITIALIZE_REQUEST_TYPE:
// Get message's URL query string
URL_QUERY_STRING = message[Output.MESSAGE_INITIALIZE_URL_QUERY_STRING_OFFSET];
// Perform dependencies initializations
Promise.all(DEPENDENCIES_INITIALIZATIONS.map(function(dependencyInitialization) {
// Return performing dependency initialization
return dependencyInitialization();
})).then(function() {
// Respond with success status
postMessage([
// Request index
requestIndex,
// Type
type,
// Status
Output.STATUS_SUCCESS_VALUE
]);
// Catch errors
}).catch(function(error) {
// Respond with failed status
postMessage([
// Request index
requestIndex,
// Type
type,
// Status
Output.STATUS_FAILED_VALUE
]);
});
// Break
break;
// Uninitialize request type
case Output.UNINITIALIZE_REQUEST_TYPE:
// Go through all dependencies uninitializations
for(var i = 0; i < DEPENDENCIES_UNINITIALIZATIONS["length"]; ++i) {
// Get dependency's uninitialization
var dependencyUninitialization = DEPENDENCIES_UNINITIALIZATIONS[i];
// Perform dependency's uninitialization
dependencyUninitialization();
}
// Respond with success status
postMessage([
// Request index
requestIndex,
// Type
type,
// Status
Output.STATUS_SUCCESS_VALUE
]);
// Break
break;
// Legacy information request type, new information request type, or view information request type
case Output.LEGACY_INFORMATION_REQUEST_TYPE:
case Output.NEW_INFORMATION_REQUEST_TYPE:
case Output.VIEW_INFORMATION_REQUEST_TYPE:
// Get message's proof
var proof = message[Output.MESSAGE_PROOF_OFFSET];
// Get message's commit
var commit = message[Output.MESSAGE_COMMIT_OFFSET];
// Get message's extended private key or root public key
var extendedPrivateKeyOrRootPublicKey = message[Output.MESSAGE_EXTENDED_PRIVATE_KEY_OR_ROOT_PUBLIC_KEY_OFFSET];
// Check type
switch(type) {
// Legacy information request type
case Output.LEGACY_INFORMATION_REQUEST_TYPE:
// Create legacy proof builder
var proofBuilder = new LegacyProofBuilder();
// Break
break;
// New information request type
case Output.NEW_INFORMATION_REQUEST_TYPE:
// Create new proof builder
var proofBuilder = new NewProofBuilder();
// Break
break;
// View information request type
case Output.VIEW_INFORMATION_REQUEST_TYPE:
// Create view proof builder
var proofBuilder = new ViewProofBuilder();
// Break
break;
}
// Initialize proof builder
proofBuilder.initialize(extendedPrivateKeyOrRootPublicKey).then(function() {
// Get information
getInformation(proof, commit, extendedPrivateKeyOrRootPublicKey, proofBuilder).then(function(information) {
// Uninitialize proof builder
proofBuilder.uninitialize();
// Securely clear extended private key or root public key
extendedPrivateKeyOrRootPublicKey.fill(0);
// Respond with information
postMessage([
// Request index
requestIndex,
// Type
type,
// Information
information
]);
// Catch errors
}).catch(function(error) {
// Uninitialize proof builder
proofBuilder.uninitialize();
// Securely clear extended private key or root public key
extendedPrivateKeyOrRootPublicKey.fill(0);
// Respond with no information
postMessage([
// Request index
requestIndex,
// Type
type,
// Information
Output.NO_INFORMATION
]);
});
// Catch errors
}).catch(function(error) {
// Securely clear extended private key or root public key
extendedPrivateKeyOrRootPublicKey.fill(0);
// Respond with no information
postMessage([
// Request index
requestIndex,
// Type
type,
// Information
Output.NO_INFORMATION
]);
});
// Break;
break;
}
});
// Supporting function implementation
// Add minified suffix
function addMinifiedSuffix(file) {
// Get file's suffix offset
var suffixOffset = file.lastIndexOf(".");
// Check if file contains no suffix
if(suffixOffset === Common.INDEX_NOT_FOUND || suffixOffset < "./"["length"])
// Return file with minified suffix at the end
return file + ".min";
// Otherwise
else
// Return file with minified suffix insert before its suffix
return file.substring(0, suffixOffset) + ".min" + file.substring(suffixOffset);
}
// Get resource
function getResource(file) {
// Return resource with version
return ((file in FILES === true && FILES[file]["Minified"] === true) ? addMinifiedSuffix(file) : file) + ((file in FILES === true && FILES[file]["Version"] !== 0) ? "?" + FILES[file]["Version"] : "");
}
// Get information
function getInformation(proof, commit, extendedPrivateKeyOrRootPublicKey, proofBuilder) {
// Return promise
return new Promise(function(resolve, reject) {
// Check if commit is valid
if(Secp256k1Zkp.isValidCommit(commit) === true) {
// Return getting rewind nonce from the proof builder
return proofBuilder.rewindNonce(commit).then(function(rewindNonce) {
// Check if rewinding bulletproof was successful
var bulletproof = Secp256k1Zkp.rewindBulletproof(proof, commit, rewindNonce);
if(bulletproof !== Secp256k1Zkp.OPERATION_FAILED) {
// Securely clear rewind nonce
rewindNonce.fill(0);
// Get amount from bulletproof
var amount = new BigNumber(bulletproof["Value"]);
// Get message from bulletproof
var message = bulletproof["Message"];
// Return having the proof builder get the output
return proofBuilder.getOutput(extendedPrivateKeyOrRootPublicKey, amount, commit, message).then(function(output) {
// Get identifier from output
var identifier = output[ProofBuilder.OUTPUT_IDENTIFIER_INDEX];
// Get switch type from output
var switchType = output[ProofBuilder.OUTPUT_SWITCH_TYPE_INDEX];
// Check if output's proof verifies the output's commit
if(Secp256k1Zkp.verifyBulletproof(proof, commit, new Uint8Array([])) === true) {
// Resolve information
resolve([
// Amount
Common.serializeObject(amount),
// Identifier
Common.serializeObject(identifier),
// Switch type
switchType
]);
}
// Otherwise
else {
// Resolve no information
resolve(Output.NO_INFORMATION);
}
// Catch errors
}).catch(function(error) {
// Resolve no information
resolve(Output.NO_INFORMATION);
});
}
// Otherwise
else {
// Securely clear rewind nonce
rewindNonce.fill(0);
// Resolve no information
resolve(Output.NO_INFORMATION);
}
// Catch errors
}).catch(function(error) {
// Resolve no information
resolve(Output.NO_INFORMATION);
});
}
// Otherwise
else {
// Resolve no information
resolve(Output.NO_INFORMATION);
}
});
}

761
scripts/prices.js Executable file
View File

@@ -0,0 +1,761 @@
// Use strict
"use strict";
// Classes
// Prices class
class Prices {
// Public
// Constructor
constructor(settings) {
// Set settings
this.settings = settings;
// Set prices obtained
this.pricesObtained = false;
// Set update prices timeout to no timeout
this.updatePricesTimeout = Prices.NO_TIMEOUT;
// Set prices
this.prices = {};
// Set enable price to setting's default value
this.enablePrice = Prices.SETTINGS_ENABLE_PRICE_DEFAULT_VALUE;
// Set update price interval minutes to setting's default value
this.updatePriceIntervalMinutes = Prices.SETTINGS_UPDATE_PRICE_INTERVAL_MINUTES_DEFAULT_VALUE;
// Can get prices
this.canGetPrices = false;
// Create database
Database.createDatabase(function(database, currentVersion, databaseTransaction) {
// Create or get prices object store
var pricesObjectStore = (currentVersion === Database.NO_CURRENT_VERSION) ? database.createObjectStore(Prices.OBJECT_STORE_NAME, {
// Key path
"keyPath": [
// Wallet type
Database.toKeyPath(Prices.DATABASE_WALLET_TYPE_NAME),
// Currency
Database.toKeyPath(Prices.DATABASE_CURRENCY_NAME)
]
}) : databaseTransaction.objectStore(Prices.OBJECT_STORE_NAME);
// Check if no database version exists
if(currentVersion === Database.NO_CURRENT_VERSION) {
// Create index to search prices object store by wallet type
pricesObjectStore.createIndex(Prices.DATABASE_WALLET_TYPE_NAME, Database.toKeyPath(Prices.DATABASE_WALLET_TYPE_NAME), {
// Unique
"unique": false
});
}
});
// Set self
var self = this;
// Once database is initialized
Database.onceInitialized(function() {
// Return promise
return new Promise(function(resolve, reject) {
// Return creating settings
return Promise.all([
// Create enable price setting
self.settings.createValue(Prices.SETTINGS_ENABLE_PRICE_NAME, Prices.SETTINGS_ENABLE_PRICE_DEFAULT_VALUE),
// Create update price interval minutes setting
self.settings.createValue(Prices.SETTINGS_UPDATE_PRICE_INTERVAL_MINUTES_NAME, Prices.SETTINGS_UPDATE_PRICE_INTERVAL_MINUTES_DEFAULT_VALUE)
]).then(function() {
// Initialize settings
var settings = [
// Enable price setting
Prices.SETTINGS_ENABLE_PRICE_NAME,
// Update price interval minutes setting
Prices.SETTINGS_UPDATE_PRICE_INTERVAL_MINUTES_NAME
];
// Return getting settings' values
return Promise.all(settings.map(function(setting) {
// Return getting setting's value
return self.settings.getValue(setting);
})).then(function(settingValues) {
// Set enable price to setting's value
self.enablePrice = settingValues[settings.indexOf(Prices.SETTINGS_ENABLE_PRICE_NAME)];
// Set update price interval minutes to setting's value
self.updatePriceIntervalMinutes = settingValues[settings.indexOf(Prices.SETTINGS_UPDATE_PRICE_INTERVAL_MINUTES_NAME)];
// Return getting all prices with the wallet type in the database
return Database.getResults(Prices.OBJECT_STORE_NAME, Database.GET_ALL_RESULTS, Database.GET_ALL_RESULTS, Prices.DATABASE_WALLET_TYPE_NAME, Consensus.getWalletType()).then(function(results) {
// Set can get prices
self.canGetPrices = true;
// Go through all prices
for(var i = 0; i < results["length"]; ++i) {
// Get price's currency
var currency = results[i][Database.toKeyPath(Prices.DATABASE_CURRENCY_NAME)];
// Get price's price or zero if network type isn't mainnet
var price = new BigNumber((Consensus.getNetworkType() === Consensus.MAINNET_NETWORK_TYPE) ? results[i][Database.toKeyPath(Prices.DATABASE_PRICE_NAME)] : 0);
// Add price to list of prices
self.prices[currency] = price;
}
// Check if price is enabled and network type is mainnet
if(self.enablePrice === true && Consensus.getNetworkType() === Consensus.MAINNET_NETWORK_TYPE) {
// Check if update prices timeout exists
if(self.updatePricesTimeout !== Prices.NO_TIMEOUT) {
// Clear update prices timeout
clearTimeout(self.updatePricesTimeout);
// Set updates prices timeout to no timeout
self.updatePricesTimeout = Prices.NO_TIMEOUT;
}
// Update prices
self.updatePrices();
}
// Otherwise
else {
// Refresh prices timeout
self.refreshPricesTimeout();
}
// Resolve
resolve();
// Catch errors
}).catch(function(error) {
// Reject
reject();
});
// Catch errors
}).catch(function(error) {
// Reject
reject();
});
// Catch errors
}).catch(function(error) {
// Reject
reject();
});
});
});
// Settings change event
$(this.settings).on(Settings.CHANGE_EVENT, function(event, setting) {
// Check what setting was changes
switch(setting[Settings.DATABASE_SETTING_NAME]) {
// Enable price setting
case Prices.SETTINGS_ENABLE_PRICE_NAME:
// Set enable price to setting's value
self.enablePrice = setting[Settings.DATABASE_VALUE_NAME];
// Check if price is enabled and network type is mainnet
if(self.enablePrice === true && Consensus.getNetworkType() === Consensus.MAINNET_NETWORK_TYPE) {
// Check if update prices timeout exists
if(self.updatePricesTimeout !== Prices.NO_TIMEOUT) {
// Clear update prices timeout
clearTimeout(self.updatePricesTimeout);
// Set updates prices timeout to no timeout
self.updatePricesTimeout = Prices.NO_TIMEOUT;
}
// Trigger change event
$(self).trigger(Prices.CHANGE_EVENT, self.prices);
// Update prices
self.updatePrices();
}
// Otherwise
else {
// Refresh prices timeout
self.refreshPricesTimeout();
// Trigger change event
$(self).trigger(Prices.CHANGE_EVENT, self.prices);
}
// Break
break;
// Update price interval minutes setting
case Prices.SETTINGS_UPDATE_PRICE_INTERVAL_MINUTES_NAME:
// Set update price interval minutes to setting's value
self.updatePriceIntervalMinutes = setting[Settings.DATABASE_VALUE_NAME];
// Refresh prices timeout
self.refreshPricesTimeout();
// Break
break;
}
});
// Window online event
$(window).on("online", function() {
// Check if prices haven't been obtained, the price is enabled, and network type is mainnet
if(self.pricesObtained === false && self.enablePrice === true && Consensus.getNetworkType() === Consensus.MAINNET_NETWORK_TYPE) {
// Check if update prices timeout exists
if(self.updatePricesTimeout !== Prices.NO_TIMEOUT) {
// Clear update prices timeout
clearTimeout(self.updatePricesTimeout);
// Set updates prices timeout to no timeout
self.updatePricesTimeout = Prices.NO_TIMEOUT;
}
// Update prices
self.updatePrices();
}
});
}
// Get prices
getPrices() {
// Check if price is enabled and prices exist
if(this.enablePrice === true && Object.keys(this.prices)["length"] !== 0) {
// Return copy of prices
return JSONBigNumber.parse(JSONBigNumber.stringify(this.prices));
}
// Otherwise
else {
// Return no prices found
return Prices.NO_PRICES_FOUND;
}
}
// Get price
getPrice(currency = Prices.CURRENT_LANGUAGE_CURRENCY, prices = Prices.CURRENT_PRICES) {
// Check if using current prices
if(prices === Prices.CURRENT_PRICES) {
// Set prices to the current prices
prices = this.prices;
}
// Check if price is enabled
if(this.enablePrice === true) {
// Check if network type is mainnet
if(Consensus.getNetworkType() === Consensus.MAINNET_NETWORK_TYPE) {
// Check if currency is the current language's currency
if(currency === Prices.CURRENT_LANGUAGE_CURRENCY)
// Set currency to current language's currency
currency = Prices.getCurrentLanguageCurrency();
// Return price for currency if found or no price found otherwise
return (currency.toUpperCase() in prices === true) ? prices[currency.toUpperCase()] : Prices.NO_PRICE_FOUND;
}
// Otherwise
else {
// Return zero
return new BigNumber(0);
}
}
// Otherwise
else {
// Return no price found
return Prices.NO_PRICE_FOUND;
}
}
// Refresh
refresh() {
// Check if price is enabled and network type is mainnet
if(this.enablePrice === true && Consensus.getNetworkType() === Consensus.MAINNET_NETWORK_TYPE) {
// Check if update prices timeout exists
if(this.updatePricesTimeout !== Prices.NO_TIMEOUT) {
// Clear update prices timeout
clearTimeout(this.updatePricesTimeout);
// Set updates prices timeout to no timeout
this.updatePricesTimeout = Prices.NO_TIMEOUT;
}
// Update prices
this.updatePrices();
}
}
// Bitcoin currency name
static get BITCOIN_CURRENCY_NAME() {
// Return Bitcoin currency name
return "BTC";
}
// Bitcoin number base
static get BITCOIN_NUMBER_BASE() {
// Return Bitcoin number base
return 1E8;
}
// Ethereum currency name
static get ETHEREUM_CURRENCY_NAME() {
// Return Ethereum currency name
return "ETH";
}
// Ethereum number base
static get ETHEREUM_NUMBER_BASE() {
// Return Ethereum number base
return 1E18;
}
// No price found
static get NO_PRICE_FOUND() {
// Return no price found
return null;
}
// No prices found
static get NO_PRICES_FOUND() {
// Return no prices found
return null;
}
// Change event
static get CHANGE_EVENT() {
// Return change event
return "PricesChangeEvent";
}
// Currency language currency
static get CURRENT_LANGUAGE_CURRENCY() {
// Return currency language currency
return null;
}
// Current prices
static get CURRENT_PRICES() {
// Return current prices
return null;
}
// Private
// Update prices
updatePrices() {
// Check if can get prices
if(this.canGetPrices === true) {
// Log message
Log.logMessage(Language.getDefaultTranslation('Trying to connect to the prices server at %1$y.'), [
[
// Text
Prices.API_URL,
// Is raw data
true
]
]);
// Initialize unique currencies to include default currencies
var uniqueCurrencies = new Set(Prices.DEFAULT_CURRENCIES);
// Go through all currencies
var allCurrencies = Prices.getAllCurrencies();
Object.keys(allCurrencies).forEach(function(language) {
// Append currency to list of unique currencies
uniqueCurrencies.add(allCurrencies[language].toUpperCase());
});
// Set self
var self = this;
// Get price for each currency
$.ajax({
// URL
"url": Prices.getApiRequest(uniqueCurrencies),
// Data type
"dataType": "text"
// Done
}).done(function(response) {
// Log message
Log.logMessage(Language.getDefaultTranslation('Successfully connected to the prices server.'));
// Try
try {
// Parse response as JSON
response = JSONBigNumber.parse(response);
}
// Catch errors
catch(error) {
// Log message
Log.logMessage(Language.getDefaultTranslation('Received an invalid response from the prices server.'));
// Return
return;
}
// Initialize new prices
var newPrices = [];
// Check if response is valid
if(Object.isObject(response) === true && Prices.API_CURRENCY_ID in response === true && Object.isObject(response[Prices.API_CURRENCY_ID]) === true) {
// Go through price for each currency
Object.keys(response[Prices.API_CURRENCY_ID]).forEach(function(currency) {
// Check if currency and price are valid
if(typeof currency === "string" && uniqueCurrencies.has(currency.toUpperCase()) === true && response[Prices.API_CURRENCY_ID][currency] instanceof BigNumber === true && response[Prices.API_CURRENCY_ID][currency].isPositive() === true && response[Prices.API_CURRENCY_ID][currency].isFinite() === true) {
// Append new price to list
newPrices.push({
// Wallet type
[Database.toKeyPath(Prices.DATABASE_WALLET_TYPE_NAME)]: Consensus.getWalletType(),
// Currency
[Database.toKeyPath(Prices.DATABASE_CURRENCY_NAME)]: currency.toUpperCase(),
// Price
[Database.toKeyPath(Prices.DATABASE_PRICE_NAME)]: response[Prices.API_CURRENCY_ID][currency].toFixed()
});
// Update prices in list
self.prices[currency.toUpperCase()] = response[Prices.API_CURRENCY_ID][currency];
}
});
}
// Check if new prices exist
if(newPrices["length"] !== 0) {
// Set prices obtained
self.pricesObtained = true;
// Save new prices in the database
Database.saveResults(Prices.OBJECT_STORE_NAME, newPrices, [], Database.CREATE_NEW_TRANSACTION, Database.STRICT_DURABILITY).then(function() {
// Log message
Log.logMessage(Language.getDefaultTranslation('Successfully updated the prices.'));
// Trigger change event
$(self).trigger(Prices.CHANGE_EVENT, self.prices);
// Catch errors
}).catch(function(error) {
// Log message
Log.logMessage(Language.getDefaultTranslation('Updating the prices failed.'));
});
}
// Otherwise
else {
// Log message
Log.logMessage(Language.getDefaultTranslation('Received an invalid response from the prices server.'));
}
// Catch errors
}).fail(function(request) {
// Check if connecting to the prices server failed
if(request["status"] === Common.HTTP_NO_RESPONSE_STATUS) {
// Log message
Log.logMessage(Language.getDefaultTranslation('Connecting to the prices server failed.'));
}
// Otherwise
else {
// Log message
Log.logMessage(Language.getDefaultTranslation('Successfully connected to the prices server.'));
// Log message
Log.logMessage(Language.getDefaultTranslation('Received an invalid response from the prices server.'));
}
// Always
}).always(function() {
// Refresh prices timeout
self.refreshPricesTimeout();
});
}
// Otherwise
else {
// Refresh prices timeout
this.refreshPricesTimeout();
}
}
// Refresh prices timeout
refreshPricesTimeout() {
// Check if update prices timeout exists
if(this.updatePricesTimeout !== Prices.NO_TIMEOUT) {
// Clear update prices timeout
clearTimeout(this.updatePricesTimeout);
// Set updates prices timeout to no timeout
this.updatePricesTimeout = Prices.NO_TIMEOUT;
}
// Check if enable price and network type is mainnet
if(this.enablePrice === true && Consensus.getNetworkType() === Consensus.MAINNET_NETWORK_TYPE) {
// Set self
var self = this;
// Set update prices timeout
this.updatePricesTimeout = setTimeout(function() {
// Update prices again
self.updatePrices();
}, this.updatePriceIntervalMinutes * Common.SECONDS_IN_A_MINUTE * Common.MILLISECONDS_IN_A_SECOND);
}
}
// Get current language currency
static getCurrentLanguageCurrency() {
// Return currency for the current language
return Language.getConstant(Language.CURRENCY_CONSTANT);
}
// Get all currencies
static getAllCurrencies() {
// Initialize currencies
var currencies = {};
// Check if available languages exist
if(typeof AVAILABLE_LANGUAGES !== "undefined") {
// Go through all available languages
Object.keys(AVAILABLE_LANGUAGES).forEach(function(availableLanguage) {
// Append currency for the available language to list of currencies
currencies[availableLanguage] = Language.getConstant(Language.CURRENCY_CONSTANT, availableLanguage);
});
}
// Return currencies
return currencies;
}
// Get API request
static getApiRequest(currencies) {
// Return API query string
return Prices.API_URL + Common.URL_QUERY_STRING_SEPARATOR + $.param({
// IDs
"ids": Prices.API_CURRENCY_ID,
// VS currencies
"vs_currencies": Array.from(currencies).join(Prices.API_CURRENCIES_SEPARATOR)
});
}
// Object store name
static get OBJECT_STORE_NAME() {
// Return object store name
return "Prices";
}
// Database wallet type name
static get DATABASE_WALLET_TYPE_NAME() {
// Return database wallet type name
return "Wallet Type";
}
// Database currency name
static get DATABASE_CURRENCY_NAME() {
// Return database currency name
return "Currency";
}
// Database price name
static get DATABASE_PRICE_NAME() {
// Return database price name
return "Price";
}
// Default currencies
static get DEFAULT_CURRENCIES() {
// Return default currencies
return [
// Bitcoin currency name
Prices.BITCOIN_CURRENCY_NAME.toUpperCase(),
// Ethereum currency name
Prices.ETHEREUM_CURRENCY_NAME.toUpperCase()
];
}
// API URL
static get API_URL() {
// Return API URL
return "https://api.coingecko.com/api/v3/simple/price";
}
// API currency ID
static get API_CURRENCY_ID() {
// Check wallet type
switch(Consensus.getWalletType()) {
// MWC wallet
case Consensus.MWC_WALLET_TYPE:
// Return API currency ID
return "mimblewimblecoin";
// GRIN wallet
case Consensus.GRIN_WALLET_TYPE:
// Return API currency ID
return "grin";
// EPIC wallet
case Consensus.EPIC_WALLET_TYPE:
// Return API currency ID
return "epic-cash";
}
}
// API currencies separator
static get API_CURRENCIES_SEPARATOR() {
// Return API currencies separator
return ",";
}
// No timeout
static get NO_TIMEOUT() {
// Return no timeout
return null;
}
// Settings enable price name
static get SETTINGS_ENABLE_PRICE_NAME() {
// Return settings enable price name
return "Enable Price";
}
// Settings enable price default value
static get SETTINGS_ENABLE_PRICE_DEFAULT_VALUE() {
// Return settings enable price default value
return true;
}
// Settings update price interval minutes name
static get SETTINGS_UPDATE_PRICE_INTERVAL_MINUTES_NAME() {
// Return settings update price interval minutes name
return "Update Price Interval Minutes";
}
// Settings update price interval minutes default value
static get SETTINGS_UPDATE_PRICE_INTERVAL_MINUTES_DEFAULT_VALUE() {
// Return settings update price interval minutes default value
return 10;
}
}
// Main function
// Set global object's prices
globalThis["Prices"] = Prices;

89
scripts/proof_builder.js Executable file
View File

@@ -0,0 +1,89 @@
// Use strict
"use strict";
// Classes
// Proof builder class
class ProofBuilder {
// Public
// Initialize
initialize(extendedPrivateKey) {
// Return promise
return new Promise(function(resolve, reject) {
// Reject error
reject("Not implemented.");
});
}
// Uninitialize
uninitialize() {
// Throw error
throw "Not implemented.";
}
// Rewind nonce
rewindNonce(commit) {
// Return promise
return new Promise(function(resolve, reject) {
// Reject error
reject("Not implemented.");
});
}
// Private nonce
privateNonce(commit) {
// Return promise
return new Promise(function(resolve, reject) {
// Reject error
reject("Not implemented.");
});
}
// Proof message
proofMessage(identifier, switchType) {
// Throw error
throw "Not implemented.";
}
// Get output
getOutput(extendedPrivateKey, amount, commit, message) {
// Return promise
return new Promise(function(resolve, reject) {
// Reject error
reject("Not implemented.");
});
}
// Output identifier index
static get OUTPUT_IDENTIFIER_INDEX() {
// Return output identifier index
return 0;
}
// Output switch type index
static get OUTPUT_SWITCH_TYPE_INDEX() {
// Return output switch type index
return ProofBuilder.OUTPUT_IDENTIFIER_INDEX + 1;
}
}
// Main function
// Set global object's proof builder
globalThis["ProofBuilder"] = ProofBuilder;

702
scripts/protocol_buffers.js Executable file
View File

@@ -0,0 +1,702 @@
// Use strict
"use strict";
// Classes
// Protocol Buffers class
class ProtocolBuffers {
// Public
// Decode
static decode(messageType, data, schema) {
// Check if schema for message type isn't known
if(messageType.toFixed() in schema === false) {
// Throw error
throw "Schema for message type isn't known.";
}
// Get message schema
var messageSchema = schema[messageType.toFixed()];
// Initialize result
var result = {};
// Go through all fields in the data
for(var i = 0; i < data["length"];) {
// Get field tag
var fieldTag = ProtocolBuffers.decodeVarint(data, i);
// Go to start of the field payload
i += ProtocolBuffers.getVarintLength(data, i);
// Check if field tag is too big
if(fieldTag > Number.MAX_SAFE_INTEGER) {
// Throw error
throw "Field tag is too big.";
}
// Get field number
var fieldNumber = fieldTag.toNumber() >>> 3;
// Get field wire type
var fieldWireType = fieldTag.toNumber() & 0b111;
// Check if field is known in the message schema
if(fieldNumber.toFixed() in messageSchema === true) {
// Check field's expected type
switch(messageSchema[fieldNumber.toFixed()]["Type"]) {
// Uint, bool, enum, or sint
case ProtocolBuffers.UINT_SCHEMA_DATA_TYPE:
case ProtocolBuffers.BOOL_SCHEMA_DATA_TYPE:
case ProtocolBuffers.ENUM_SCHEMA_DATA_TYPE:
case ProtocolBuffers.SINT_SCHEMA_DATA_TYPE:
// Check if field wire type isn't correct
if(fieldWireType !== ProtocolBuffers.VARINT_WIRE_TYPE) {
// Throw error
throw "Field wire type isn't correct.";
}
// Break
break;
// String or bytes
case ProtocolBuffers.STRING_SCHEMA_DATA_TYPE:
case ProtocolBuffers.BYTES_SCHEMA_DATA_TYPE:
// Check if field wire type isn't correct
if(fieldWireType !== ProtocolBuffers.LEN_WIRE_TYPE) {
// Throw error
throw "Field wire type isn't correct.";
}
// Break
break;
}
// Check if field doesn't exist in the result
if(messageSchema[fieldNumber.toFixed()]["Name"] in result === false) {
// Create field in result
result[messageSchema[fieldNumber.toFixed()]["Name"]] = [];
}
}
// Check field wire type
switch(fieldWireType) {
// Varint
case ProtocolBuffers.VARINT_WIRE_TYPE:
// Check if field is known in the message schema
if(fieldNumber.toFixed() in messageSchema === true) {
// Get value from the field payload
var value = ProtocolBuffers.decodeVarint(data, i);
// Check field's expected type
switch(messageSchema[fieldNumber.toFixed()]["Type"]) {
// Uint
case ProtocolBuffers.UINT_SCHEMA_DATA_TYPE:
// Append value to result
result[messageSchema[fieldNumber.toFixed()]["Name"]].push(value);
// Break
break;
// Bool
case ProtocolBuffers.BOOL_SCHEMA_DATA_TYPE:
// Append value as a boolean to result
result[messageSchema[fieldNumber.toFixed()]["Name"]].push(value.isZero() === false);
// Break
break;
// Enum
case ProtocolBuffers.ENUM_SCHEMA_DATA_TYPE:
// Check if value is too big
if(value > Number.MAX_SAFE_INTEGER) {
// Throw error
throw "Value is too big.";
}
// Append value as an enum to result
result[messageSchema[fieldNumber.toFixed()]["Name"]].push(value.toNumber());
// Break
break;
// Sint
case ProtocolBuffers.SINT_SCHEMA_DATA_TYPE:
// Get if value is even
if(value.modulo(2).isZero() === true) {
// Append value as a positive number to result
result[messageSchema[fieldNumber.toFixed()]["Name"]].push(value.dividedToIntegerBy(2));
}
// Otherwise
else {
// Append value as a negative number to result
result[messageSchema[fieldNumber.toFixed()]["Name"]].push(value.plus(1).dividedToIntegerBy(-2));
}
// Break
break;
}
}
// Go to next field
i += ProtocolBuffers.getVarintLength(data, i);
// Break
break;
// I64
case ProtocolBuffers.I64_WIRE_TYPE:
// Check if field payload doesn't contain data
if(i + Common.BYTES_IN_A_UINT64 > data["length"]) {
// Throw error
throw "Field payload doesn't contain data.";
}
// Go to next field
i += Common.BYTES_IN_A_UINT64;
// Break
break;
// Len
case ProtocolBuffers.LEN_WIRE_TYPE:
// Get length from the field payload
var length = ProtocolBuffers.decodeVarint(data, i);
// Go to the field payload's data
i += ProtocolBuffers.getVarintLength(data, i);
// Check if length is too big
if(length > Number.MAX_SAFE_INTEGER) {
// Throw error
throw "Length is too big.";
}
// Check if field payload doesn't contain data
if(i + length.toNumber() > data["length"]) {
// Throw error
throw "Field payload doesn't contain data.";
}
// Check if field is known in the message schema
if(fieldNumber.toFixed() in messageSchema === true) {
// Get value from the field payload's data
var value = data.subarray(i, i + length.toNumber());
// Check field's expected type
switch(messageSchema[fieldNumber.toFixed()]["Type"]) {
// String
case ProtocolBuffers.STRING_SCHEMA_DATA_TYPE:
// Append value as a string to result
result[messageSchema[fieldNumber.toFixed()]["Name"]].push((new TextDecoder("utf-8", {"fatal": true})).decode(value));
// Break
break;
// Bytes
case ProtocolBuffers.BYTES_SCHEMA_DATA_TYPE:
// Append value to result
result[messageSchema[fieldNumber.toFixed()]["Name"]].push(value);
// Break
break;
}
}
// Go to next field
i += length.toNumber();
// Break
break;
// I32
case ProtocolBuffers.I32_WIRE_TYPE:
// Check if field payload doesn't contain data
if(i + Common.BYTES_IN_A_UINT32 > data["length"]) {
// Throw error
throw "Field payload doesn't contain data.";
}
// Go to next field
i += Common.BYTES_IN_A_UINT32;
// Break
break;
// Default
default:
// Throw error
throw "Field wire type isn't known.";
}
}
// Return result
return result;
}
// Encode
static encode(messageType, data, schema) {
// Check if schema for message type isn't known
if(messageType.toFixed() in schema === false) {
// Throw error
throw "Schema for message type isn't known.";
}
// Get message schema
var messageSchema = schema[messageType.toFixed()];
// Initialize result
var result = new Uint8Array([]);
// Go through all values in the data
for(var name in data) {
if(data.hasOwnProperty(name) === true) {
// Initialize value found
var valueFound = false;
// Go through all fields in the message schema
for(var fieldNumber in messageSchema) {
if(messageSchema.hasOwnProperty(fieldNumber) === true) {
// Check if field is for the value
if(messageSchema[fieldNumber]["Name"] === name) {
// Set value found
valueFound = true;
// Check field's type
switch(messageSchema[fieldNumber]["Type"]) {
// Uint
case ProtocolBuffers.UINT_SCHEMA_DATA_TYPE:
// Check if value type isn't correct
if(data[name] instanceof BigNumber === false) {
// Throw error
throw "Value's type isn't correct.";
}
// Set field wire type
var fieldWireType = ProtocolBuffers.VARINT_WIRE_TYPE;
// Set field payload
var fieldPayload = ProtocolBuffers.encodeVarint(data[name]);
// Break
break;
// Bool
case ProtocolBuffers.BOOL_SCHEMA_DATA_TYPE:
// Check if value type isn't correct
if(typeof data[name] !== "boolean") {
// Throw error
throw "Value's type isn't correct.";
}
// Set field wire type
var fieldWireType = ProtocolBuffers.VARINT_WIRE_TYPE;
// Set field payload
var fieldPayload = ProtocolBuffers.encodeVarint(new BigNumber((data[name] === true) ? 1 : 0));
// Break
break;
// Enum
case ProtocolBuffers.ENUM_SCHEMA_DATA_TYPE:
// Check if value type isn't correct
if(typeof data[name] !== "number") {
// Throw error
throw "Value's type isn't correct.";
}
// Set field wire type
var fieldWireType = ProtocolBuffers.VARINT_WIRE_TYPE;
// Set field payload
var fieldPayload = ProtocolBuffers.encodeVarint(new BigNumber(data[name]));
// Break
break;
// String
case ProtocolBuffers.STRING_SCHEMA_DATA_TYPE:
// Check if value's type isn't correct
if(typeof data[name] !== "string") {
// Throw error
throw "Value's type isn't correct.";
}
// Set field wire type
var fieldWireType = ProtocolBuffers.LEN_WIRE_TYPE;
// Set field payload
var fieldPayload = Common.mergeArrays([
// Length
ProtocolBuffers.encodeVarint(new BigNumber(data[name]["length"])),
// Data
(new TextEncoder()).encode(data[name])
]);
// Break
break;
// Bytes
case ProtocolBuffers.BYTES_SCHEMA_DATA_TYPE:
// Check if value's type isn't correct
if(data[name] instanceof Uint8Array === false) {
// Throw error
throw "Value's type isn't correct.";
}
// Check if no data exists and data is optional
if(data[name]["length"] === 0 && "Optional" in messageSchema[fieldNumber] === true && messageSchema[fieldNumber]["Optional"] === true) {
// Clear value found
valueFound = false;
}
// Otherwise
else {
// Set field wire type
var fieldWireType = ProtocolBuffers.LEN_WIRE_TYPE;
// Set field payload
var fieldPayload = Common.mergeArrays([
// Length
ProtocolBuffers.encodeVarint(new BigNumber(data[name]["length"])),
// Data
data[name]
]);
}
// Break
break;
// Sint
case ProtocolBuffers.SINT_SCHEMA_DATA_TYPE:
// Check if value type isn't correct
if(data[name] instanceof BigNumber === false) {
// Throw error
throw "Value's type isn't correct.";
}
// Set field wire type
var fieldWireType = ProtocolBuffers.VARINT_WIRE_TYPE;
// Check if value is positive
if(data[name].isPositive() === true) {
// Set field payload
var fieldPayload = ProtocolBuffers.encodeVarint(data[name].multipliedBy(2));
}
// Otherwise
else {
// Set field payload
var fieldPayload = ProtocolBuffers.encodeVarint(data[name].multipliedBy(-2).minus(1));
}
// Break
break;
}
// Break
break;
}
}
}
// Check if value was found in message schema
if(valueFound === true) {
// Set field tag
var fieldTag = ProtocolBuffers.encodeVarint(new BigNumber((fieldNumber << 3) | fieldWireType));
// Append field tag and field payload to the result
result = Common.mergeArrays([
// Result
result,
// Field tag
fieldTag,
// Field payload
fieldPayload
]);
}
}
}
// Return result
return result;
}
// Uint schema data type
static get UINT_SCHEMA_DATA_TYPE() {
// Return uint data type
return 0;
}
// Bool schema data type
static get BOOL_SCHEMA_DATA_TYPE() {
// Return bool data type
return ProtocolBuffers.UINT_SCHEMA_DATA_TYPE + 1;
}
// Enum schema data type
static get ENUM_SCHEMA_DATA_TYPE() {
// Return enum data type
return ProtocolBuffers.BOOL_SCHEMA_DATA_TYPE + 1;
}
// String schema data type
static get STRING_SCHEMA_DATA_TYPE() {
// Return string data type
return ProtocolBuffers.ENUM_SCHEMA_DATA_TYPE + 1;
}
// Bytes schema data type
static get BYTES_SCHEMA_DATA_TYPE() {
// Return bytes data type
return ProtocolBuffers.STRING_SCHEMA_DATA_TYPE + 1;
}
// Sint schema data type
static get SINT_SCHEMA_DATA_TYPE() {
// Return sint data type
return ProtocolBuffers.BYTES_SCHEMA_DATA_TYPE + 1;
}
// Private
// Decode varint
static decodeVarint(data, offset) {
// Initialize payloads
var payloads = [];
// Loop through all bytes in the varint
do {
// Check if data doesn't contain a varint
if(offset >= data["length"]) {
// Throw error
throw "Data doesn't contain a varint.";
}
// Get if continuation bit is set
var continuationBitSet = (data[offset] & 0b10000000) !== 0;
// Append payload to list
payloads.unshift(data[offset] & 0b01111111);
// Increment offset
++offset;
} while(continuationBitSet === true);
// Create bit writer
var bitWriter = new BitWriter();
// Add padding bits to bit writer
bitWriter.setBits(0, payloads["length"] % Common.BITS_IN_A_BYTE);
// Go through all payloads
for(var i = 0; i < payloads["length"]; ++i) {
// Add payload to the bit writer
bitWriter.setBits(payloads[i], 7);
}
// Return number value of the bit writer's bytes
return new BigNumber(Common.HEX_PREFIX + Common.toHexString(bitWriter.getBytes()));
}
// Get varint length
static getVarintLength(data, offset) {
// Initialize length
var length = 0;
// Loop through all bytes in the varint
do {
// Check if data doesn't contain a varint
if(offset + length >= data["length"]) {
// Throw error
throw "Data doesn't contain a varint.";
}
// Get if continuation bit is set
var continuationBitSet = (data[offset + length] & 0b10000000) !== 0;
// Increment length
++length;
} while(continuationBitSet === true);
// Return length
return length;
}
// Encode varint
static encodeVarint(value) {
// Get value as bytes
var bytes = value.toBytes(BigNumber.BIG_ENDIAN);
// Initialize result
var result = (new Uint8Array((bytes["length"] > 1 || bytes[0] >= 0b10000000) ? Math.ceil(bytes["length"] * Common.BITS_IN_A_BYTE / 7) : bytes["length"])).fill(0);
// Initialize bit reader with the bytes
var bitReader = new BitReader(bytes);
// Go through all bytes in the result
for(var i = result["length"] - 1; i >= 0; --i) {
// Set byte's continuation bit
result[i] |= (i === result["length"] - 1) ? 0b00000000 : 0b10000000;
// Check if bytes can be encoded in one payload
if(bytes["length"] === 1 && bytes[0] < 0b10000000) {
// Set byte's payload
result[i] |= bitReader.getBits(8);
}
// Otherwise check at the ending byte and a fewer than seven bits remain
else if(i === result["length"] - 1 && bytes["length"] * Common.BITS_IN_A_BYTE % 7 !== 0) {
// Set byte's payload
result[i] |= bitReader.getBits(bytes["length"] * Common.BITS_IN_A_BYTE % 7);
}
// Otherwise
else {
// Set byte's payload
result[i] |= bitReader.getBits(7);
}
}
// Return result
return result;
}
// Varint wire type
static get VARINT_WIRE_TYPE() {
// Return varint wire type
return 0;
}
// I64 wire type
static get I64_WIRE_TYPE() {
// Return i64 wire type
return ProtocolBuffers.VARINT_WIRE_TYPE + 1;
}
// Len wire type
static get LEN_WIRE_TYPE() {
// Return len wire type
return ProtocolBuffers.I64_WIRE_TYPE + 1;
}
// Sgroup wire type
static get SGROUP_WIRE_TYPE() {
// Return sgroup wire type
return ProtocolBuffers.LEN_WIRE_TYPE + 1;
}
// Egroup wire type
static get EGROUP_WIRE_TYPE() {
// Return egroup wire type
return ProtocolBuffers.SGROUP_WIRE_TYPE + 1;
}
// I32 wire type
static get I32_WIRE_TYPE() {
// Return i32 wire type
return ProtocolBuffers.EGROUP_WIRE_TYPE + 1;
}
}
// Main function
// Set global object's Protocol Buffers
globalThis["ProtocolBuffers"] = ProtocolBuffers;

182
scripts/protocol_handler.js Executable file
View File

@@ -0,0 +1,182 @@
// Use strict
"use strict";
// Classes
// ProtocolHandler class
class ProtocolHandler {
// Public
// Register
static register() {
// Check if not an app and not loading from a file
if(Common.isApp() === false && location["protocol"] !== Common.FILE_PROTOCOL) {
// Check if can register protocol handler
if(typeof navigator === "object" && navigator !== null && "registerProtocolHandler" in navigator === true) {
// Go through all protocols
for(var i = 0; i < ProtocolHandler.PROTOCOLS["length"]; ++i) {
// Get protocol
var protocol = ProtocolHandler.PROTOCOLS[i];
// Try
try {
// Register protocol handler
navigator.registerProtocolHandler(protocol, ProtocolHandler.HANDLER_URL, Language.getTranslation('MWC Wallet'));
}
// Catch errors
catch(error) {
}
}
}
}
}
// Standardize URL protocol
static standardizeUrlProtocol(url) {
// Try
try {
// Parse URL
var parsedUrl = new URL(url);
}
// Catch errors
catch(error) {
// Return URL
return url;
}
// Check if URL's protocol is being handled
if(ProtocolHandler.PROTOCOLS.map(function(protocol) {
// Return protocol
return protocol + ":";
}).indexOf(parsedUrl["protocol"]) !== Common.INDEX_NOT_FOUND) {
// Return standard URL
return Common.ltrim(url).substring(ProtocolHandler.PROTOCOLS_PREFIX["length"]);
}
// Otherwise
else {
// Return URL
return url;
}
}
// Private
// Protocols prefix
static get PROTOCOLS_PREFIX() {
// Check wallet type
switch(Consensus.getWalletType()) {
// MWC wallet
case Consensus.MWC_WALLET_TYPE:
// Check network type
switch(Consensus.getNetworkType()) {
// Mainnet network
case Consensus.MAINNET_NETWORK_TYPE:
// Return protocols prefix
return "web+mwc";
// Testnet network
case Consensus.TESTNET_NETWORK_TYPE:
// Return protocols prefix
return "web+mwcfloonet";
}
// Break
break;
// GRIN wallet
case Consensus.GRIN_WALLET_TYPE:
// Check network type
switch(Consensus.getNetworkType()) {
// Mainnet network
case Consensus.MAINNET_NETWORK_TYPE:
// Return protocols prefix
return "web+grin";
// Testnet network
case Consensus.TESTNET_NETWORK_TYPE:
// Return protocols prefix
return "web+grintestnet";
}
// Break
break;
// EPIC wallet
case Consensus.EPIC_WALLET_TYPE:
// Check network type
switch(Consensus.getNetworkType()) {
// Mainnet network
case Consensus.MAINNET_NETWORK_TYPE:
// Return protocols prefix
return "web+epic";
// Testnet network
case Consensus.TESTNET_NETWORK_TYPE:
// Return protocols prefix
return "web+epicfloonet";
}
// Break
break;
}
}
// Protocols
static get PROTOCOLS() {
// Return protocols
return [
// HTTP
ProtocolHandler.PROTOCOLS_PREFIX + "http",
// HTTPS
ProtocolHandler.PROTOCOLS_PREFIX + "https"
];
}
// Handler URL
static get HANDLER_URL() {
// Return handler URL
return "/index.html" + Common.URL_QUERY_STRING_SEPARATOR + encodeURIComponent(Consensus.OVERRIDE_WALLET_TYPE_URL_PARAMETER_NAME).replace(/%20/ug, "+") + Common.URL_QUERY_STRING_PARAMETER_VALUE_SEPARATOR + encodeURIComponent(Consensus.walletTypeToText(Consensus.getWalletType())).replace(/%20/ug, "+") + Common.URL_QUERY_STRING_PARAMETER_SEPARATOR + encodeURIComponent(Consensus.OVERRIDE_NETWORK_TYPE_URL_PARAMETER_NAME).replace(/%20/ug, "+") + Common.URL_QUERY_STRING_PARAMETER_VALUE_SEPARATOR + encodeURIComponent(Consensus.networkTypeToText(Consensus.getNetworkType())).replace(/%20/ug, "+") + Common.URL_QUERY_STRING_PARAMETER_SEPARATOR + encodeURIComponent("Request").replace(/%20/ug, "+") + Common.URL_QUERY_STRING_PARAMETER_VALUE_SEPARATOR + encodeURIComponent("Start Transaction").replace(/%20/ug, "+") + Common.URL_QUERY_STRING_PARAMETER_SEPARATOR + encodeURIComponent("Recipient Address").replace(/%20/ug, "+") + Common.URL_QUERY_STRING_PARAMETER_VALUE_SEPARATOR + "%s";
}
}
// Main function
// Set global object's protocol handler
globalThis["ProtocolHandler"] = ProtocolHandler;

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2009 Kazuhiko Arase
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

2297
scripts/qrcode-generator-1.4.4.js Executable file

File diff suppressed because it is too large Load Diff

977
scripts/recent_heights.js Executable file
View File

@@ -0,0 +1,977 @@
// Use strict
"use strict";
// Classes
// Recent heights class
class RecentHeights {
// Public
// Constructor
constructor(node) {
// Set node
this.node = node;
// Set heights
this.heights = [];
// Set current heights
this.currentHeights = [];
// Set heights changed
this.heightsChanged = false;
// Set initial heights obtained
this.initialHeightsObtained = new InitialHeightsObtained();
// Create database
Database.createDatabase(function(database, currentVersion, databaseTransaction) {
// Create or get recent heights object store
var recentHeightsObjectStore = (currentVersion === Database.NO_CURRENT_VERSION) ? database.createObjectStore(RecentHeights.OBJECT_STORE_NAME, {
// Key path
"keyPath": [
// Wallet type
Database.toKeyPath(RecentHeights.DATABASE_WALLET_TYPE_NAME),
// Network type
Database.toKeyPath(RecentHeights.DATABASE_NETWORK_TYPE_NAME),
// Height
Database.toKeyPath(RecentHeights.DATABASE_HEIGHT_NAME)
]
}) : databaseTransaction.objectStore(RecentHeights.OBJECT_STORE_NAME);
// Check if no database version exists
if(currentVersion === Database.NO_CURRENT_VERSION) {
// Create index to search recent heights object store by wallet type and network type
recentHeightsObjectStore.createIndex(RecentHeights.DATABASE_WALLET_TYPE_AND_NETWORK_TYPE_NAME, [
// Wallet Type
Database.toKeyPath(RecentHeights.DATABASE_WALLET_TYPE_NAME),
// Network Type
Database.toKeyPath(RecentHeights.DATABASE_NETWORK_TYPE_NAME)
], {
// Unique
"unique": false
});
}
});
// Set self
var self = this;
// Once database is initialized
Database.onceInitialized(function() {
// Return promise
return new Promise(function(resolve, reject) {
// Return getting the recent heights with the wallet type and network type in the database
return Database.getResults(RecentHeights.OBJECT_STORE_NAME, Database.GET_ALL_RESULTS, Database.GET_ALL_RESULTS, RecentHeights.DATABASE_WALLET_TYPE_AND_NETWORK_TYPE_NAME, IDBKeyRange.only([
// Wallet type
Consensus.getWalletType(),
// Network type
Consensus.getNetworkType()
])).then(function(results) {
// Go through all recent heights while not exceeding the max number of recent heights
for(var i = 0; i < results["length"] && self.heights["length"] < RecentHeights.MAXIMUM_NUMBER_OF_RECENT_HEIGHTS; ++i) {
// Get height from result
var height = RecentHeights.getHeightFromResult(results[i]);
// Check if height is valid
if(height.getHeight().isGreaterThanOrEqualTo(Consensus.FIRST_BLOCK_HEIGHT) === true)
// Append height to list of heights
self.heights.push(height);
}
// Sort heights in descending order
self.heights.sort(function(firstHeight, secondHeight) {
// Check if first height is less than the second height
if(firstHeight.getHeight().isLessThan(secondHeight.getHeight()) === true)
// Return sort greater than
return Common.SORT_GREATER_THAN;
// Check if first height is greater than the second height
if(firstHeight.getHeight().isGreaterThan(secondHeight.getHeight()) === true)
// Return sort less than
return Common.SORT_LESS_THAN;
// Return sort equal
return Common.SORT_EQUAL;
});
// Store current heights
self.storeCurrentHeights();
// Resolve
resolve();
// Catch errors
}).catch(function(error) {
// Reject
reject();
});
});
});
}
// Get highest verified height
getHighestVerifiedHeight(tipHeight) {
// Retore current heights
this.restoreCurrentHeights();
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Set get initial heights
var getInitialHeights = new Promise(function(resolve, reject) {
// Return getting if initial heights were obtained
return self.initialHeightsObtained.getObtained().then(function(obtained) {
// Check if initial heights weren't obtained
if(obtained === false) {
// Clear heights
self.heights = [];
// Return saving heights
return self.saveHeights(tipHeight).then(function() {
// Return setting that initial heights were obtained
return self.initialHeightsObtained.setObtained().then(function() {
// Resolve
resolve();
// Catch errors
}).catch(function(error) {
// Clear heights
self.heights = [];
// Return deleting recent heights with the wallet type and network type in the database
return Database.deleteResultsWithValue(RecentHeights.OBJECT_STORE_NAME, RecentHeights.DATABASE_WALLET_TYPE_AND_NETWORK_TYPE_NAME, IDBKeyRange.only([
// Wallet type
Consensus.getWalletType(),
// Network type
Consensus.getNetworkType()
]), Database.CREATE_NEW_TRANSACTION, Database.STRICT_DURABILITY).catch(function(error) {
// Finally
}).finally(function() {
// Reject error
reject(error);
});
});
// Catch errors
}).catch(function(error) {
// Clear heights
self.heights = [];
// Return deleting recent heights with the wallet type and network type in the database
return Database.deleteResultsWithValue(RecentHeights.OBJECT_STORE_NAME, RecentHeights.DATABASE_WALLET_TYPE_AND_NETWORK_TYPE_NAME, IDBKeyRange.only([
// Wallet type
Consensus.getWalletType(),
// Network type
Consensus.getNetworkType()
]), Database.CREATE_NEW_TRANSACTION, Database.STRICT_DURABILITY).catch(function(error) {
// Finally
}).finally(function() {
// Reject error
reject(error);
});
});
}
// Otherwise
else {
// Resolve
resolve();
}
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
});
// Return getting initial heights
return getInitialHeights.then(function() {
// Set highest verified height to no verified height
var highestVerifiedHeight = RecentHeights.NO_VERIFIED_HEIGHT;
// Set reorg occurred to true if heights exist
var reorgOccurred = self.heights["length"] !== 0;
// Set verifying height to promise
var verifyingHeight = new Promise(function(resolve, reject) {
// Resolve
resolve();
});
// Initialize verifying heights
var verifyingHeights = [verifyingHeight];
// Go through all heights from highest to lowest
var verifiedHeightFound = false;
for(let i = 0; i < self.heights["length"]; ++i) {
// Get height
let height = self.heights[i];
// Set verifying height to verify current height after previous height is done being verified
verifyingHeight = verifyingHeight.then(function() {
// Return promise
return new Promise(function(resolve, reject) {
// Check if a verified height was already found
if(verifiedHeightFound === true)
// Resolve
resolve();
// Otherwise
else {
// Return verifying height
return self.verifyHeight(height, tipHeight).then(function(verified) {
// Check if height is verified
if(verified === true) {
// Set highest verified height to height
highestVerifiedHeight = height.getHeight();
// Remove invalid heights
self.heights.splice(0, i);
// Set that a verified height was found
verifiedHeightFound = true;
// Check if highest height is verified
if(i === 0)
// Clear reorg occurred
reorgOccurred = false;
}
// Otherwise check if no saved heights are valid
else if(i === self.heights["length"] - 1)
// Clear all heights
self.heights = [];
// Resolve
resolve();
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
}
});
// Catch errors
}).catch(function(error) {
// Return promise
return new Promise(function(resolve, reject) {
// Reject error
reject(error);
});
});
// Append verifying height to list
verifyingHeights.push(verifyingHeight);
}
// Wait until a verified height has been found
return Promise.all(verifyingHeights).then(function() {
// Resolve highest verified height
resolve([
// Highest verified height
highestVerifiedHeight,
// Reorg occurred
reorgOccurred
]);
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
});
}
// Get highest height
getHighestHeight() {
// Return highest current height without verifying it again or no height if not available
return (this.currentHeights["length"] !== 0) ? this.currentHeights[0].getHeight() : RecentHeights.NO_HEIGHT;
}
// Save heights
saveHeights(tipHeight) {
// Store current heights
this.storeCurrentHeights();
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Return updating heights
return self.updateHeights(tipHeight).then(function() {
// Store current heights
self.storeCurrentHeights();
// Check if heights changed
if(self.heightsChanged === true) {
// Clear heights changed
self.heightsChanged = false;
// Return creating database transaction
return Database.createTransaction(RecentHeights.OBJECT_STORE_NAME, Database.READ_AND_WRITE_MODE, Database.STRICT_DURABILITY).then(function(transaction) {
// Return deleting recent heights with the wallet type and network type in the database
return Database.deleteResultsWithValue(RecentHeights.OBJECT_STORE_NAME, RecentHeights.DATABASE_WALLET_TYPE_AND_NETWORK_TYPE_NAME, IDBKeyRange.only([
// Wallet type
Consensus.getWalletType(),
// Network type
Consensus.getNetworkType()
]), transaction, Database.STRICT_DURABILITY).then(function() {
// Return saving all recent heights in the database
return Database.saveResults(RecentHeights.OBJECT_STORE_NAME, self.heights.map(function(height) {
// Return height as result
return {
// Wallet Type
[Database.toKeyPath(RecentHeights.DATABASE_WALLET_TYPE_NAME)]: Consensus.getWalletType(),
// Network type
[Database.toKeyPath(RecentHeights.DATABASE_NETWORK_TYPE_NAME)]: Consensus.getNetworkType(),
// Height
[Database.toKeyPath(RecentHeights.DATABASE_HEIGHT_NAME)]: height.getHeight().toFixed(),
// Hash
[Database.toKeyPath(RecentHeights.DATABASE_HASH_NAME)]: height.getHash()
};
}), [], transaction, Database.STRICT_DURABILITY).then(function() {
// Return committing database transaction
return Database.commitTransaction(transaction).then(function() {
// Resolve
resolve();
// Catch errors
}).catch(function(error) {
// Return aborting database transaction
return Database.abortTransaction(transaction).then(function() {
// Reject error
reject("The database failed.");
// Catch errors
}).catch(function(error) {
// Trigger a fatal error
new FatalError(FatalError.DATABASE_ERROR);
});
});
// Catch errors
}).catch(function(error) {
// Return aborting database transaction
return Database.abortTransaction(transaction).then(function() {
// Reject error
reject("The database failed.");
// Catch errors
}).catch(function(error) {
// Trigger a fatal error
new FatalError(FatalError.DATABASE_ERROR);
});
});
// Catch errors
}).catch(function(error) {
// Return aborting database transaction
return Database.abortTransaction(transaction).then(function() {
// Reject error
reject("The database failed.");
// Catch errors
}).catch(function(error) {
// Trigger a fatal error
new FatalError(FatalError.DATABASE_ERROR);
});
});
// Catch errors
}).catch(function(error) {
// Reject error
reject("The database failed.");
});
}
// Otherwise
else
// Resolve
resolve();
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
});
}
// No verified height
static get NO_VERIFIED_HEIGHT() {
// Return no verified height
return null;
}
// No height
static get NO_HEIGHT() {
// Return no height
return null;
}
// Highest verified height index
static get HIGHEST_VERIFIED_HEIGHT_INDEX() {
// Return highest verified hight index
return 0;
}
// Reorg occurred index
static get REORG_OCCURRED_INDEX() {
// Return reorg occurred index
return RecentHeights.HIGHEST_VERIFIED_HEIGHT_INDEX + 1;
}
// Header hash length
static get HEADER_HASH_LENGTH() {
// Return header hash length
return 32;
}
// Private
// Verify height
verifyHeight(height, tipHeight) {
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Check if tip height is greater than or equal to the height
if(tipHeight.getHeight().isGreaterThanOrEqualTo(height.getHeight()) === true) {
// Set get hash
var getHash = new Promise(function(resolve, reject) {
// Check if height is equal to the tip height
if(height.getHeight().isEqualTo(tipHeight.getHeight()) === true) {
// Set hash to tip height's hash
var hash = tipHeight.getHash();
// Resolve hash
resolve(hash);
}
// Otherwise
else {
// Return getting node's header at height
return self.node.getHeader(height.getHeight()).then(function(header) {
// Resolve header
resolve((header !== Node.NO_HEADER_FOUND) ? header["hash"] : header);
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
}
});
// Return getting hash
return getHash.then(function(hash) {
// Check if no header for the height
if(hash === Node.NO_HEADER_FOUND)
// Resolve false
resolve(false);
// Otherwise
else
// Resolve if height's hash didn't change
resolve(Common.arraysAreEqual(hash, height.getHash()) === true);
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
}
// Otherwise
else
// Resolve false
resolve(false);
});
}
// Update heights
updateHeights(tipHeight) {
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Initialize new heights
var newHeights = [];
// Initialize get heights
var getHeights = [];
// Go through the max number of recent heights or until a first block height is used
var firstBlockHeightUsed = false;
for(let i = 0; i < RecentHeights.MAXIMUM_NUMBER_OF_RECENT_HEIGHTS && firstBlockHeightUsed === false; ++i) {
// Get minimum and maximum age in seconds for the height at this index
var minimumAgeInSeconds = (i !== 0) ? RecentHeights.getMinimumAgeAtIndex(i - 1) : 0;
var maximumAgeInSeconds = RecentHeights.getMinimumAgeAtIndex(i) - 1;
// Get ideal height from minimum age
let idealHeight = tipHeight.getHeight().minus(Math.ceil(minimumAgeInSeconds / Consensus.BLOCK_TIME_SECONDS));
// Check if heights exist
if(self.heights["length"] !== 0) {
// Go through all heights
for(var j = 0; j < self.heights["length"]; ++j) {
// Get height
var height = self.heights[j];
// Get height's age in seconds
var ageInSeconds = tipHeight.getHeight().minus(height.getHeight()).multipliedBy(Consensus.BLOCK_TIME_SECONDS);
// Check if height isn't too new or old for this index or height and ideal height are both the first block height
if((ageInSeconds.isGreaterThanOrEqualTo(minimumAgeInSeconds) === true && ageInSeconds.isLessThanOrEqualTo(maximumAgeInSeconds) === true) || (idealHeight.isLessThanOrEqualTo(Consensus.FIRST_BLOCK_HEIGHT) === true && height.getHeight().isEqualTo(Consensus.FIRST_BLOCK_HEIGHT) === true)) {
// Check if indexes differ
if(i !== j)
// Set heights changed
self.heightsChanged = true;
// Check if height is equal to the first block height
if(height.getHeight().isEqualTo(Consensus.FIRST_BLOCK_HEIGHT) === true)
// Set first block height used
firstBlockHeightUsed = true;
// Set height in new heights at index
newHeights[i] = height;
// Break
break;
}
// Otherwise check if no heights have the correct age for this index
else if(j === self.heights["length"] - 1) {
// Check if ideal height is less than or equal to the first block height
if(idealHeight.isLessThanOrEqualTo(Consensus.FIRST_BLOCK_HEIGHT) === true) {
// Check if first block height isn't used
if(firstBlockHeightUsed === false) {
// Set first block height used
firstBlockHeightUsed = true;
// Set ideal height to the first block height
idealHeight = new BigNumber(Consensus.FIRST_BLOCK_HEIGHT);
// Set heights changed
self.heightsChanged = true;
}
// Otherwise
else
// Break
break;
}
// Otherwise
else
// Set heights changed
self.heightsChanged = true;
// Append get height to list
getHeights.push(new Promise(function(resolve, reject) {
// Check if the ideal height is equal to the tip height
if(idealHeight.isEqualTo(tipHeight.getHeight()) === true) {
// Set new height at index to the tip height
newHeights[i] = new Height(tipHeight.getHeight(), tipHeight.getHash());
// Resolve
resolve();
}
// Otherwise
else {
// Return getting node's header for the ideal height
return self.node.getHeader(idealHeight).then(function(header) {
// Check if no header exists for the height
if(header === Node.NO_HEADER_FOUND)
// Reject error
reject("Height not found.");
// Otherwise
else {
// Set height in new heights at index
newHeights[i] = new Height(idealHeight, header["hash"]);
// Resolve
resolve();
}
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
}
}));
}
}
}
// Otherwise
else {
// Check if ideal height is less than or equal to the first block height
if(idealHeight.isLessThanOrEqualTo(Consensus.FIRST_BLOCK_HEIGHT) === true) {
// Check if first block height isn't used
if(firstBlockHeightUsed === false) {
// Set first block height used
firstBlockHeightUsed = true;
// Set ideal height to the first block height
idealHeight = new BigNumber(Consensus.FIRST_BLOCK_HEIGHT);
// Set heights changed
self.heightsChanged = true;
}
// Otherwise
else
// Break
break;
}
// Otherwise
else
// Set heights changed
self.heightsChanged = true;
// Append getting height to list
getHeights.push(new Promise(function(resolve, reject) {
// Check if the ideal height is equal to the tip height
if(idealHeight.isEqualTo(tipHeight.getHeight()) === true) {
// Set new height at index to the tip height
newHeights[i] = new Height(tipHeight.getHeight(), tipHeight.getHash());
// Resolve
resolve();
}
// Otherwise
else {
// Return getting node's header for the ideal height
return self.node.getHeader(idealHeight).then(function(header) {
// Check if no header exists for the height
if(header === Node.NO_HEADER_FOUND)
// Reject
reject("Height not found.");
// Otherwise
else {
// Set height in new heights at index
newHeights[i] = new Height(idealHeight, header["hash"]);
// Resolve
resolve();
}
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
}
}));
}
}
// Return waiting for all heights to be obtained
return Promise.all(getHeights).then(function() {
// Get tip of new heights
var tipNewHeight = newHeights[0];
// Check if the tip of the new heights isn't equal to the tip height
if(tipNewHeight.getHeight().isEqualTo(tipHeight.getHeight()) === false || Common.arraysAreEqual(tipNewHeight.getHash(), tipHeight.getHash()) === false) {
// Set tip of new heights to tip height
newHeights[0] = new Height(tipHeight.getHeight(), tipHeight.getHash());
// Set heights changed
self.heightsChanged = true;
}
// Set heights to new heights
self.heights = newHeights;
// Resolve
resolve();
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
});
}
// Store current heights
storeCurrentHeights() {
// Clear current heights
this.currentHeights = [];
// Go through all heights
for(var i = 0; i < this.heights["length"]; ++i) {
// Get height
var height = this.heights[i];
// Copy height to current heights
this.currentHeights.push(new Height(height.getHeight(), height.getHash()));
}
}
// Retore current heights
restoreCurrentHeights() {
// Clear heights
this.heights = [];
// Go through all current heights
for(var i = 0; i < this.currentHeights["length"]; ++i) {
// Get current height
var currentHeight = this.currentHeights[i];
// Copy current height to heights
this.heights.push(new Height(currentHeight.getHeight(), currentHeight.getHash()));
}
}
// Get minimum age at index
static getMinimumAgeAtIndex(index) {
// Return minimum age at index in seconds
return Math.pow((index > 2) ? 3 : 2, (index > 2) ? index - 1 : index) * Consensus.BLOCK_TIME_SECONDS;
}
// Get height from result
static getHeightFromResult(result) {
// Return height from result
return new Height(
// Height
new BigNumber(result[Database.toKeyPath(RecentHeights.DATABASE_HEIGHT_NAME)]),
// Hash
result[Database.toKeyPath(RecentHeights.DATABASE_HASH_NAME)]
);
}
// Object store name
static get OBJECT_STORE_NAME() {
// Return object store name
return "Recent Heights";
}
// Database wallet type name
static get DATABASE_WALLET_TYPE_NAME() {
// Return database wallet type name
return "Wallet Type";
}
// Database network type name
static get DATABASE_NETWORK_TYPE_NAME() {
// Return database network type name
return "Network Type";
}
// Database height name
static get DATABASE_HEIGHT_NAME() {
// Return database height name
return "Height";
}
// Database hash name
static get DATABASE_HASH_NAME() {
// Return database hash name
return "Hash";
}
// Database wallet type and network type name
static get DATABASE_WALLET_TYPE_AND_NETWORK_TYPE_NAME() {
// Return database wallet type and network type name
return "Wallet Type And Network Type";
}
// Maximum number of recent heights
static get MAXIMUM_NUMBER_OF_RECENT_HEIGHTS() {
// Return the maximum number of recent heights
return 13;
}
}
// Main function
// Set global object's recent heights
globalThis["RecentHeights"] = RecentHeights;

187
scripts/scroll.js Executable file
View File

@@ -0,0 +1,187 @@
// Use strict
"use strict";
// Classes
// Scroll class
class Scroll {
// Public
// Constructor
constructor() {
// Set prevent scrolling keys to false
this.preventScrollingKeys = false;
// Set self
var self = this;
// Document key down event
$(document).on("keydown", function(event) {
// Check if preventing scrolling keys and a scroll key was pressed
if(self.preventScrollingKeys === true && Scroll.isScrollKey(event["which"]) === true) {
// Prevent default
event.preventDefault();
}
// Input blur or mouse out event
}).on("blur mouseout", "input", function() {
// Get input
var input = $(this);
// Check if input doesn't have focus
if(input.is(":focus") === false) {
// Scroll input back to start
input.scrollLeft(0);
}
});
// Check if browser isn't Firefox
if(typeof navigator !== "object" || navigator === null || "userAgent" in navigator === false || navigator["userAgent"].toLowerCase().indexOf("firefox") === Common.INDEX_NOT_FOUND) {
// Scroll event
document.addEventListener("scroll", function(event) {
// Get element
var element = $(event["target"]);
// Check if element is an input and it doesn't have focus
if(element.is("input") === true && element.is(":focus") === false) {
// Prevent scrolling
element.scrollLeft(0);
}
}, true);
}
}
// Prevent keys
preventKeys() {
// Set prevent scrolling keys
this.preventScrollingKeys = true;
}
// Allow keys
allowKeys() {
// Clear prevent scrolling keys
this.preventScrollingKeys = false;
}
// Tolerance
static get TOLERANCE() {
// Return tolerance
return 2;
}
// Private
// Is scroll key
static isScrollKey(key) {
// Return is key is a scroll key
return Scroll.SCROLL_KEYS.indexOf(key) !== Common.INDEX_NOT_FOUND;
}
// Scroll keys
static get SCROLL_KEYS() {
// Return scroll keys
return [
// Page up
Scroll.PAGE_UP_KEY_CODE,
// Page down
Scroll.PAGE_DOWN_KEY_CODE,
// End
Scroll.END_KEY_CODE,
// Home
Scroll.HOME_KEY_CODE,
// Left arrow
Scroll.LEFT_ARROW_KEY_CODE,
// Up arrow
Scroll.UP_ARROW_KEY_CODE,
// Right arrow
Scroll.RIGHT_ARROW_KEY_CODE,
// Down arrow
Scroll.DOWN_ARROW_KEY_CODE
];
}
// Page up key code
static get PAGE_UP_KEY_CODE() {
// Return page up key code
return 33;
}
// Page down key code
static get PAGE_DOWN_KEY_CODE() {
// Return page down key code
return 34;
}
// End key code
static get END_KEY_CODE() {
// Return end key code
return 35;
}
// Home key code
static get HOME_KEY_CODE() {
// Return home key code
return 36;
}
// Left arrow key code
static get LEFT_ARROW_KEY_CODE() {
// Return left arrow key code
return 37;
}
// Up arrow key code
static get UP_ARROW_KEY_CODE() {
// Return up arrow key code
return 38;
}
// Right arrow key code
static get RIGHT_ARROW_KEY_CODE() {
// Return right arrow key code
return 39;
}
// Down arrow key code
static get DOWN_ARROW_KEY_CODE() {
// Return down arrow key code
return 40;
}
}
// Main function
// Set global object's scroll
globalThis["Scroll"] = Scroll;

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022-2023 Nicolas Flamel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

3762
scripts/secp256k1-zkp-0.0.29.js Executable file

File diff suppressed because it is too large Load Diff

BIN
scripts/secp256k1-zkp-0.0.29.wasm Executable file

Binary file not shown.

1632
scripts/section.js Executable file

File diff suppressed because it is too large Load Diff

931
scripts/sections.js Executable file
View File

@@ -0,0 +1,931 @@
// Use strict
"use strict";
// Classes
// Sections class
class Sections {
// Public
// Constructor
constructor(settings, message, version) {
// Set settings
this.settings = settings;
// Set message
this.message = message;
// Set version
this.version = version;
// Set sections
this.sections = {};
// Set stack to setting's default value
this.stack = JSON.parse(Sections.SETTINGS_SECTIONS_STACK_DEFAULT_VALUE);
// Set stack index to setting's default value
this.stackIndex = Sections.SETTINGS_SECTIONS_STACK_INDEX_DEFAULT_VALUE;
// Set stack version
this.stackVersion = version.getVersion();
// Set self
var self = this;
// Once database is initialized
Database.onceInitialized(function() {
// Return promise
return new Promise(function(resolve, reject) {
// Return creating settings
return Promise.all([
// Sections stack setting
self.settings.createValue(Sections.SETTINGS_SECTIONS_STACK_NAME, Sections.SETTINGS_SECTIONS_STACK_DEFAULT_VALUE),
// Sections stack index setting
self.settings.createValue(Sections.SETTINGS_SECTIONS_STACK_INDEX_NAME, Sections.SETTINGS_SECTIONS_STACK_INDEX_DEFAULT_VALUE),
// Sections stack version setting
self.settings.createValue(Sections.SETTINGS_SECTIONS_STACK_VERSION_NAME, self.stackVersion)
]).then(function() {
// Initialize settings
var settings = [
// Sections stack setting
Sections.SETTINGS_SECTIONS_STACK_NAME,
// Sections stack index setting
Sections.SETTINGS_SECTIONS_STACK_INDEX_NAME,
// Sections stack version setting
Sections.SETTINGS_SECTIONS_STACK_VERSION_NAME
];
// Return getting settings' values
return Promise.all(settings.map(function(setting) {
// Return getting setting's value
return self.settings.getValue(setting);
})).then(function(settingValues) {
// Check if stack version changed
if(settingValues[settings.indexOf(Sections.SETTINGS_SECTIONS_STACK_VERSION_NAME)] !== self.stackVersion) {
// Return setting settings to their default values
return Promise.all([
// Sections stack setting
self.settings.setValue(Sections.SETTINGS_SECTIONS_STACK_NAME, Sections.SETTINGS_SECTIONS_STACK_DEFAULT_VALUE),
// Sections stack index setting
self.settings.setValue(Sections.SETTINGS_SECTIONS_STACK_INDEX_NAME, Sections.SETTINGS_SECTIONS_STACK_INDEX_DEFAULT_VALUE)
]).then(function() {
// Return setting sections stack version setting to the current version
return self.settings.setValue(Sections.SETTINGS_SECTIONS_STACK_VERSION_NAME, self.stackVersion).then(function() {
// Set stack to setting's default value
self.stack = JSON.parse(Sections.SETTINGS_SECTIONS_STACK_DEFAULT_VALUE);
// Set stack index to setting's default value
self.stackIndex = Sections.SETTINGS_SECTIONS_STACK_INDEX_DEFAULT_VALUE;
// Resolve
resolve();
// Catch errors
}).catch(function(error) {
// Reject
reject();
});
// Catch errors
}).catch(function(error) {
// Reject
reject();
});
}
// Otherwise
else {
// Set stack to setting's value
self.stack = JSON.parse(settingValues[settings.indexOf(Sections.SETTINGS_SECTIONS_STACK_NAME)]);
// Set stack index to setting's value
self.stackIndex = settingValues[settings.indexOf(Sections.SETTINGS_SECTIONS_STACK_INDEX_NAME)];
// Resolve
resolve();
}
// Catch errors
}).catch(function(error) {
// Reject
reject();
});
// Catch errors
}).catch(function(error) {
// Reject
reject();
});
});
});
}
// Register section
registerSection(section) {
// Append section to list
this.sections[section.getName()] = section;
}
// Get stack length
getStackLength() {
// Return stack length
return this.stack["length"];
}
// Get stack index
getStackIndex() {
// Return stack index
return this.stackIndex;
}
// Set stack index
setStackIndex(stackIndex) {
// Set stack index
this.stackIndex = stackIndex;
}
// Get stack
getStack() {
// Return stack
return this.stack;
}
// Set stack
setStack(stack) {
// Set stack
this.stack = stack;
}
// Push state to stack
pushStateToStack(section) {
// Check if state isn't going to the end of the stack
if(this.stackIndex !== this.stack["length"]) {
// Remove everything in stack after current index
this.stack.splice(this.stackIndex);
}
// Otherwise check if a state exists in the stack
else if(this.stackIndex !== 0) {
// Get current section
var currentSection = this.sections[this.stack[this.stackIndex - 1]["Name"]];
// Update current section's state in the stack
this.stack[this.stackIndex - 1] = {
// Name
"Name": currentSection.getName(),
// State
"State": currentSection.getState()
};
}
// Increment stack index
++this.stackIndex;
// Append section's state to the stack
this.stack.push({
// Name
"Name": section.getName(),
// State
"State": section.getState()
});
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Return saving stack
return self.saveStack().then(function() {
// Resolve
resolve();
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
});
}
// Insert state in stack
insertStateInStack(sectionName, state, isTemporary = false) {
// Check if no states exists in the stack
if(this.stackIndex === 0) {
// Increment stack index
++this.stackIndex;
}
// Insert section name and state in the stack
this.stack.splice(this.stackIndex - 1, 0, {
// Name
"Name": sectionName,
// State
"State": state
});
// Check if is temporary
if(isTemporary === true) {
// Set that value in stack is temporary
this.stack[this.stackIndex - 1]["Temporary"] = true;
}
// Otherwise
else {
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Return saving stack
return self.saveStack().then(function() {
// Resolve
resolve();
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
});
}
}
// Update state in stack
updateStateInStack(section, state = Sections.NO_STATE) {
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Check if current state in the stack is for the section
if(self.stackIndex !== 0 && self.stack[self.stackIndex - 1]["Name"] === section.getName()) {
// Get if state is temporary
var isTemporary = "Temporary" in self.stack[self.stackIndex - 1] === true && self.stack[self.stackIndex - 1]["Temporary"] === true;
// Check if not temporary and unlocked display is showing a minimal display
if(isTemporary === false && $("div.unlocked").hasClass("minimal") === true) {
// Resolve
resolve();
}
// Otherwise
else {
// Update section's state in the stack
self.stack[self.stackIndex - 1] = {
// Name
"Name": section.getName(),
// State
"State": (state === Sections.NO_STATE) ? section.getState() : state
};
// Check if is temporary
if(isTemporary === true) {
// Set that value in stack is temporary
self.stack[self.stackIndex - 1]["Temporary"] = true;
}
// Return saving stack
return self.saveStack().then(function() {
// Resolve
resolve();
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
}
}
// Otherwise
else {
// Reject
reject();
}
});
}
// Update stack
updateStack() {
// Set current state to no state
var currentState = Sections.NO_STATE;
// Check if a state exists in the stack
if(this.stackIndex !== 0) {
// Get current section
var currentSection = this.sections[this.stack[this.stackIndex - 1]["Name"]];
// Check if current state in the stack is for the current section
if(this.stack[this.stackIndex - 1]["Name"] === currentSection.getName()) {
// Get current section's state
currentState = currentSection.getState();
}
}
// Otherwise
else {
// Set current section to no section
var currentSection = Sections.NO_SECTION;
}
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Check if a current section exists
if(currentSection !== Sections.NO_SECTION) {
// Update current section's state in the stack
self.updateStateInStack(currentSection, currentState).then(function() {
// Resolve
resolve();
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
}
// Otherwise
else {
// Reject
reject();
}
});
}
// Clear stack
clearStack(saveStack = false) {
// Set stack to setting's default value
this.stack = JSON.parse(Sections.SETTINGS_SECTIONS_STACK_DEFAULT_VALUE);
// Set stack index to setting's default value
this.stackIndex = Sections.SETTINGS_SECTIONS_STACK_INDEX_DEFAULT_VALUE;
// Check if saving stack
if(saveStack === true) {
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Return saving stack
return self.saveStack().then(function() {
// Resolve
resolve();
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
});
}
}
// Get current section
getCurrentSection() {
// Return current section or no section if it doesn't exist
return (this.stackIndex !== 0) ? this.sections[this.stack[this.stackIndex - 1]["Name"]] : Sections.NO_SECTION;
}
// Get current section name
getCurrentSectionName() {
// Return current section's name or the default section name if there is no current section
return (this.stackIndex !== 0) ? this.stack[this.stackIndex - 1]["Name"] : Sections.DEFAULT_SECTION_NAME;
}
// Get current section state
getCurrentSectionState() {
// Return current section's state or no state if there is no current section
return (this.stackIndex !== 0) ? this.stack[this.stackIndex - 1]["State"] : Section.NO_STATE;
}
// Is current section temporary
isCurrentSectionTemporary() {
// Return if current section is temporary
return this.stackIndex !== 0 && "Temporary" in this.stack[this.stackIndex - 1] === true && this.stack[this.stackIndex - 1]["Temporary"] === true;
}
// Show current section
showCurrentSection(minimal = true) {
// Check if not minimal
if(minimal === false) {
// Prevent showing messages
this.message.prevent();
// Check if a current section exists
if(this.stackIndex !== 0) {
// Check if current section is temporary
if("Temporary" in this.stack[this.stackIndex - 1] === true && this.stack[this.stackIndex - 1]["Temporary"] === true) {
// Remove current section from the stack
this.stack.splice(this.stackIndex - 1, 1);
// Check if there's no more sections
if(this.stack["length"] === 0) {
// Decrement stack index
--this.stackIndex;
}
}
}
// Check if an extension request exists
if(Extension.getRequests()["length"] !== 0) {
// Get request
var request = Extension.getRequests().shift();
// Insert request into sections
this.insertStateInStack(request["Name"], request["State"], true);
}
// Otherwise check if closing when done processing extension requests
else if(Extension.getCloseWhenDone() === true) {
// Prevent extension from interrupting on close
Extension.preventInterruptOnClose();
// Close
window.close();
// Return promise
return new Promise(function(resolve, reject) {
});
}
}
// Initialize first stack value
var firstStackValue = false;
// Check if no current sections exists
if(this.stackIndex === 0) {
// Set current state to no state
var currentState = Section.NO_STATE;
// Set current section to the default section
var currentSection = this.sections[Sections.DEFAULT_SECTION_NAME];
// Set first stack value
firstStackValue = true;
}
// Otherwise
else {
// Get current state from stack
var currentState = this.stack[this.stackIndex - 1];
// Get current section from state
var currentSection = this.sections[currentState["Name"]];
}
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Check if minimal
if(minimal === true) {
// Return showing current section with the current state
return currentSection.show(true, false, false, (currentState !== Section.NO_STATE) ? currentState["State"] : Section.NO_STATE, firstStackValue, true, currentState !== Section.NO_STATE && "Temporary" in currentState === true && currentState["Temporary"] === true).then(function() {
// Resolve
resolve();
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
}
// Otherwise
else {
// Return showing current section with the current state
return currentSection.show(false, true, true, (currentState !== Section.NO_STATE) ? currentState["State"] : Section.NO_STATE, firstStackValue, false, currentState !== Section.NO_STATE && "Temporary" in currentState === true && currentState["Temporary"] === true).then(function() {
// Allow showing messages
self.message.allow();
// Resolve
resolve();
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
}
});
}
// Show section
showSection(sectionName, saveCurrentDisplay = false, state = Section.NO_STATE) {
// Prevent showing messages
this.message.prevent();
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Return showing section
return self.sections[sectionName].show(false, true, true, state, true, saveCurrentDisplay).then(function() {
// Allow showing messages
self.message.allow();
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
});
}
// Show previous section
showPreviousSection() {
// Get previous state
var previousState = this.getPreviousStateFromStack();
// Get previous section
var previousSection = this.sections[previousState["Name"]];
// Prevent showing messages
this.message.prevent();
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Return showing previous section
return previousSection.show(false, true, true, previousState["State"], false, true).then(function() {
// Allow showing messages
self.message.allow();
// Resolve
resolve();
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
});
}
// Show next section
showNextSection() {
// Get next state
var nextState = this.getNextStateFromStack();
// Get next section
var nextSection = this.sections[nextState["Name"]];
// Prevent showing messages
this.message.prevent();
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Return showing next section
return nextSection.show(false, true, true, nextState["State"], false, true).then(function() {
// Allow showing messages
self.message.allow();
// Resolve
resolve();
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
});
}
// Reset
reset() {
// Go through all sections
for(var sectionName in this.sections) {
if(this.sections.hasOwnProperty(sectionName) === true) {
// Get section
var section = this.sections[sectionName];
// Reset section
section.reset();
}
}
}
// Get section
getSection(display) {
// Go through all sections
for(var sectionName in this.sections) {
if(this.sections.hasOwnProperty(sectionName) === true) {
// Get section
var section = this.sections[sectionName];
// Check if section has the display
if(section.getDisplay().is(display) === true) {
// Return section
return section;
}
}
}
// Return no section
return Sections.NO_SECTION;
}
// Is section in stack
isSectionInStack(sectionName) {
// Go through the stack
for(var i = 0; i < this.stack["length"]; ++i) {
// Check if section in the stack has the same name
if(this.stack[i]["Name"] === sectionName) {
// Return true
return true;
}
}
// Return false
return false;
}
// No section
static get NO_SECTION() {
// Return no section
return null;
}
// Private
// Save stack
saveStack() {
// Set self
var self = this;
// Return promise
return new Promise(function(resolve, reject) {
// Get current stack
var currentStack = [];
// Get current stack index
var currentStackIndex = self.stackIndex;
// Go through all values in the stack
for(var i = 0; i < self.stack["length"]; ++i) {
// Get value
var value = self.stack[i];
// Check if value is temporary
if("Temporary" in value === true && value["Temporary"] === true) {
// Check if value being removed affects the current stack index
if(currentStackIndex - 1 > i || i === currentStack["length"] - 1) {
// Decrement current stack index
--currentStackIndex;
}
}
// Otherwise
else {
// Add value to current stack
currentStack.push(value);
}
}
// Check if nothing is in the current stack
if(currentStack["length"] === 0) {
// Set current stack index to zero
currentStackIndex = 0;
}
// Return saving sections stack version setting
return self.settings.setValue(Sections.SETTINGS_SECTIONS_STACK_VERSION_NAME, self.stackVersion).then(function() {
// Return saving settings
return Promise.all([
// Save sections stack setting
self.settings.setValue(Sections.SETTINGS_SECTIONS_STACK_NAME, JSON.stringify(currentStack)),
// Save sections stack index setting
self.settings.setValue(Sections.SETTINGS_SECTIONS_STACK_INDEX_NAME, currentStackIndex)
]).then(function() {
// Resolve
resolve();
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
});
}
// Get previous state from stack
getPreviousStateFromStack() {
// Decrement stack index
--this.stackIndex;
// Return state at stack index
return this.stack[this.stackIndex - 1];
}
// Get next state from stack
getNextStateFromStack() {
// Increment stack index
++this.stackIndex;
// Return state at stack index
return this.stack[this.stackIndex - 1];
}
// Settings sections stack name
static get SETTINGS_SECTIONS_STACK_NAME() {
// Return settings sections stack name
return "Sections Stack";
}
// Settings sections stack default value
static get SETTINGS_SECTIONS_STACK_DEFAULT_VALUE() {
// Return settings sections stack default value
return JSON.stringify([]);
}
// Settings sections stack index name
static get SETTINGS_SECTIONS_STACK_INDEX_NAME() {
// Return settings sections stack index name
return "Sections Stack Index";
}
// Settings sections stack index default value
static get SETTINGS_SECTIONS_STACK_INDEX_DEFAULT_VALUE() {
// Return settings sections stack index default value
return 0;
}
// Settings sections stackversion name
static get SETTINGS_SECTIONS_STACK_VERSION_NAME() {
// Return settings sections stack version name
return "Sections Stack Version";
}
// Default section name
static get DEFAULT_SECTION_NAME() {
// Return default section name
return WalletSection.NAME;
}
}
// Main function
// Set global object's sections
globalThis["Sections"] = Sections;

2979
scripts/seed.js Executable file

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More