Workflow updating files of arbitrumwallet
This commit is contained in:
parent
3102dfe898
commit
11c9aed730
2
arbitrumwallet/README.md
Normal file
2
arbitrumwallet/README.md
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# arbitrum
|
||||||
|
Arbitrum blockchain wallet linked with FLO and BTC network
|
||||||
1291
arbitrumwallet/css/main.css
Normal file
1291
arbitrumwallet/css/main.css
Normal file
File diff suppressed because it is too large
Load Diff
1900
arbitrumwallet/index.html
Normal file
1900
arbitrumwallet/index.html
Normal file
File diff suppressed because it is too large
Load Diff
1499
arbitrumwallet/scripts/btcOperator.js
Normal file
1499
arbitrumwallet/scripts/btcOperator.js
Normal file
File diff suppressed because it is too large
Load Diff
1
arbitrumwallet/scripts/btcOperator.min.js
vendored
Normal file
1
arbitrumwallet/scripts/btcOperator.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
10430
arbitrumwallet/scripts/btcwallet_scripts_lib.js
Normal file
10430
arbitrumwallet/scripts/btcwallet_scripts_lib.js
Normal file
File diff suppressed because it is too large
Load Diff
57
arbitrumwallet/scripts/btcwallet_scripts_lib.min.js
vendored
Normal file
57
arbitrumwallet/scripts/btcwallet_scripts_lib.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
257
arbitrumwallet/scripts/compactIDB.js
Normal file
257
arbitrumwallet/scripts/compactIDB.js
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
(function (EXPORTS) { //compactIDB v2.1.2
|
||||||
|
/* Compact IndexedDB operations */
|
||||||
|
'use strict';
|
||||||
|
const compactIDB = EXPORTS;
|
||||||
|
|
||||||
|
var defaultDB;
|
||||||
|
|
||||||
|
const indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
|
||||||
|
const IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction;
|
||||||
|
const IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange;
|
||||||
|
|
||||||
|
if (!indexedDB) {
|
||||||
|
console.error("Your browser doesn't support a stable version of IndexedDB.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
compactIDB.setDefaultDB = dbName => defaultDB = dbName;
|
||||||
|
|
||||||
|
Object.defineProperty(compactIDB, 'default', {
|
||||||
|
get: () => defaultDB,
|
||||||
|
set: dbName => defaultDB = dbName
|
||||||
|
});
|
||||||
|
|
||||||
|
function getDBversion(dbName = defaultDB) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
openDB(dbName).then(db => {
|
||||||
|
resolve(db.version)
|
||||||
|
db.close()
|
||||||
|
}).catch(error => reject(error))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function upgradeDB(dbName, createList = null, deleteList = null) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
getDBversion(dbName).then(version => {
|
||||||
|
var idb = indexedDB.open(dbName, version + 1);
|
||||||
|
idb.onerror = (event) => reject("Error in opening IndexedDB");
|
||||||
|
idb.onupgradeneeded = (event) => {
|
||||||
|
let db = event.target.result;
|
||||||
|
if (createList instanceof Object) {
|
||||||
|
if (Array.isArray(createList)) {
|
||||||
|
let tmp = {}
|
||||||
|
createList.forEach(o => tmp[o] = {})
|
||||||
|
createList = tmp
|
||||||
|
}
|
||||||
|
for (let o in createList) {
|
||||||
|
let obs = db.createObjectStore(o, createList[o].options || {});
|
||||||
|
if (createList[o].indexes instanceof Object)
|
||||||
|
for (let i in createList[o].indexes)
|
||||||
|
obs.createIndex(i, i, createList[o].indexes || {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Array.isArray(deleteList))
|
||||||
|
deleteList.forEach(o => db.deleteObjectStore(o));
|
||||||
|
resolve('Database upgraded')
|
||||||
|
}
|
||||||
|
idb.onsuccess = (event) => event.target.result.close();
|
||||||
|
}).catch(error => reject(error))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
compactIDB.initDB = function (dbName, objectStores = {}) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (!(objectStores instanceof Object))
|
||||||
|
return reject('ObjectStores must be an object or array')
|
||||||
|
defaultDB = defaultDB || dbName;
|
||||||
|
var idb = indexedDB.open(dbName);
|
||||||
|
idb.onerror = (event) => reject("Error in opening IndexedDB");
|
||||||
|
idb.onsuccess = (event) => {
|
||||||
|
var db = event.target.result;
|
||||||
|
let cList = Object.values(db.objectStoreNames);
|
||||||
|
var obs = {},
|
||||||
|
a_obs = {},
|
||||||
|
d_obs = [];
|
||||||
|
if (!Array.isArray(objectStores))
|
||||||
|
var obs = objectStores
|
||||||
|
else
|
||||||
|
objectStores.forEach(o => obs[o] = {})
|
||||||
|
let nList = Object.keys(obs)
|
||||||
|
for (let o of nList)
|
||||||
|
if (!cList.includes(o))
|
||||||
|
a_obs[o] = obs[o]
|
||||||
|
for (let o of cList)
|
||||||
|
if (!nList.includes(o))
|
||||||
|
d_obs.push(o)
|
||||||
|
if (!Object.keys(a_obs).length && !d_obs.length)
|
||||||
|
resolve("Initiated IndexedDB");
|
||||||
|
else
|
||||||
|
upgradeDB(dbName, a_obs, d_obs)
|
||||||
|
.then(result => resolve(result))
|
||||||
|
.catch(error => reject(error))
|
||||||
|
db.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const openDB = compactIDB.openDB = function (dbName = defaultDB) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
var idb = indexedDB.open(dbName);
|
||||||
|
idb.onerror = (event) => reject("Error in opening IndexedDB");
|
||||||
|
idb.onupgradeneeded = (event) => {
|
||||||
|
event.target.result.close();
|
||||||
|
deleteDB(dbName).then(_ => null).catch(_ => null).finally(_ => reject("Datebase not found"))
|
||||||
|
}
|
||||||
|
idb.onsuccess = (event) => resolve(event.target.result);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteDB = compactIDB.deleteDB = function (dbName = defaultDB) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
var deleteReq = indexedDB.deleteDatabase(dbName);;
|
||||||
|
deleteReq.onerror = (event) => reject("Error deleting database!");
|
||||||
|
deleteReq.onsuccess = (event) => resolve("Database deleted successfully");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
compactIDB.writeData = function (obsName, data, key = false, dbName = defaultDB) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
openDB(dbName).then(db => {
|
||||||
|
var obs = db.transaction(obsName, "readwrite").objectStore(obsName);
|
||||||
|
let writeReq = (key ? obs.put(data, key) : obs.put(data));
|
||||||
|
writeReq.onsuccess = (evt) => resolve(`Write data Successful`);
|
||||||
|
writeReq.onerror = (evt) => reject(
|
||||||
|
`Write data unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`
|
||||||
|
);
|
||||||
|
db.close();
|
||||||
|
}).catch(error => reject(error));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
compactIDB.addData = function (obsName, data, key = false, dbName = defaultDB) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
openDB(dbName).then(db => {
|
||||||
|
var obs = db.transaction(obsName, "readwrite").objectStore(obsName);
|
||||||
|
let addReq = (key ? obs.add(data, key) : obs.add(data));
|
||||||
|
addReq.onsuccess = (evt) => resolve(`Add data successful`);
|
||||||
|
addReq.onerror = (evt) => reject(
|
||||||
|
`Add data unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`
|
||||||
|
);
|
||||||
|
db.close();
|
||||||
|
}).catch(error => reject(error));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
compactIDB.removeData = function (obsName, key, dbName = defaultDB) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
openDB(dbName).then(db => {
|
||||||
|
var obs = db.transaction(obsName, "readwrite").objectStore(obsName);
|
||||||
|
let delReq = obs.delete(key);
|
||||||
|
delReq.onsuccess = (evt) => resolve(`Removed Data ${key}`);
|
||||||
|
delReq.onerror = (evt) => reject(
|
||||||
|
`Remove data unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`
|
||||||
|
);
|
||||||
|
db.close();
|
||||||
|
}).catch(error => reject(error));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
compactIDB.clearData = function (obsName, dbName = defaultDB) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
openDB(dbName).then(db => {
|
||||||
|
var obs = db.transaction(obsName, "readwrite").objectStore(obsName);
|
||||||
|
let clearReq = obs.clear();
|
||||||
|
clearReq.onsuccess = (evt) => resolve(`Clear data Successful`);
|
||||||
|
clearReq.onerror = (evt) => reject(`Clear data Unsuccessful`);
|
||||||
|
db.close();
|
||||||
|
}).catch(error => reject(error));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
compactIDB.readData = function (obsName, key, dbName = defaultDB) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
openDB(dbName).then(db => {
|
||||||
|
var obs = db.transaction(obsName, "readonly").objectStore(obsName);
|
||||||
|
let getReq = obs.get(key);
|
||||||
|
getReq.onsuccess = (evt) => resolve(evt.target.result);
|
||||||
|
getReq.onerror = (evt) => reject(
|
||||||
|
`Read data unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`
|
||||||
|
);
|
||||||
|
db.close();
|
||||||
|
}).catch(error => reject(error));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
compactIDB.readAllData = function (obsName, dbName = defaultDB) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
openDB(dbName).then(db => {
|
||||||
|
var obs = db.transaction(obsName, "readonly").objectStore(obsName);
|
||||||
|
var tmpResult = {}
|
||||||
|
let curReq = obs.openCursor();
|
||||||
|
curReq.onsuccess = (evt) => {
|
||||||
|
var cursor = evt.target.result;
|
||||||
|
if (cursor) {
|
||||||
|
tmpResult[cursor.primaryKey] = cursor.value;
|
||||||
|
cursor.continue();
|
||||||
|
} else
|
||||||
|
resolve(tmpResult);
|
||||||
|
}
|
||||||
|
curReq.onerror = (evt) => reject(
|
||||||
|
`Read-All data unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`
|
||||||
|
);
|
||||||
|
db.close();
|
||||||
|
}).catch(error => reject(error));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* compactIDB.searchData = function (obsName, options = {}, dbName = defaultDB) {
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
openDB(dbName).then(db => {
|
||||||
|
var obs = db.transaction(obsName, "readonly").objectStore(obsName);
|
||||||
|
var filteredResult = {}
|
||||||
|
let keyRange;
|
||||||
|
if(options.lowerKey!==null && options.upperKey!==null)
|
||||||
|
keyRange = IDBKeyRange.bound(options.lowerKey, options.upperKey);
|
||||||
|
else if(options.lowerKey!==null)
|
||||||
|
keyRange = IDBKeyRange.lowerBound(options.lowerKey);
|
||||||
|
else if (options.upperKey!==null)
|
||||||
|
keyRange = IDBKeyRange.upperBound(options.upperBound);
|
||||||
|
else if (options.atKey)
|
||||||
|
let curReq = obs.openCursor(keyRange, )
|
||||||
|
}).catch(error => reject(error))
|
||||||
|
})
|
||||||
|
}*/
|
||||||
|
|
||||||
|
compactIDB.searchData = function (obsName, options = {}, dbName = defaultDB) {
|
||||||
|
options.lowerKey = options.atKey || options.lowerKey || 0
|
||||||
|
options.upperKey = options.atKey || options.upperKey || false
|
||||||
|
options.patternEval = options.patternEval || ((k, v) => true);
|
||||||
|
options.limit = options.limit || false;
|
||||||
|
options.reverse = options.reverse || false;
|
||||||
|
options.lastOnly = options.lastOnly || false
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
openDB(dbName).then(db => {
|
||||||
|
var obs = db.transaction(obsName, "readonly").objectStore(obsName);
|
||||||
|
var filteredResult = {}
|
||||||
|
let curReq = obs.openCursor(
|
||||||
|
options.upperKey ? IDBKeyRange.bound(options.lowerKey, options.upperKey) : IDBKeyRange.lowerBound(options.lowerKey),
|
||||||
|
options.lastOnly || options.reverse ? "prev" : "next");
|
||||||
|
curReq.onsuccess = (evt) => {
|
||||||
|
var cursor = evt.target.result;
|
||||||
|
if (!cursor || (options.limit && options.limit <= Object.keys(filteredResult).length))
|
||||||
|
return resolve(filteredResult); //reached end of key list or limit reached
|
||||||
|
else if (options.patternEval(cursor.primaryKey, cursor.value)) {
|
||||||
|
filteredResult[cursor.primaryKey] = cursor.value;
|
||||||
|
options.lastOnly ? resolve(filteredResult) : cursor.continue();
|
||||||
|
} else
|
||||||
|
cursor.continue();
|
||||||
|
}
|
||||||
|
curReq.onerror = (evt) => reject(`Search unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`);
|
||||||
|
db.close();
|
||||||
|
}).catch(error => reject(error));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
})(window.compactIDB = {});
|
||||||
9
arbitrumwallet/scripts/components.js
Normal file
9
arbitrumwallet/scripts/components.js
Normal file
File diff suppressed because one or more lines are too long
1
arbitrumwallet/scripts/components.min.js
vendored
Normal file
1
arbitrumwallet/scripts/components.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
556
arbitrumwallet/scripts/ethOperator.js
Normal file
556
arbitrumwallet/scripts/ethOperator.js
Normal file
@ -0,0 +1,556 @@
|
|||||||
|
(function (EXPORTS) { // ethOperator v1.0.2
|
||||||
|
/* ETH Crypto and API Operator */
|
||||||
|
if (!window.ethers)
|
||||||
|
return console.error('ethers.js not found')
|
||||||
|
const ethOperator = EXPORTS;
|
||||||
|
const isValidAddress = ethOperator.isValidAddress = (address) => {
|
||||||
|
try {
|
||||||
|
// Check if the address is a valid checksum address
|
||||||
|
const isValidChecksum = ethers.utils.isAddress(address);
|
||||||
|
// Check if the address is a valid non-checksum address
|
||||||
|
const isValidNonChecksum = ethers.utils.getAddress(address) === address.toLowerCase();
|
||||||
|
return isValidChecksum || isValidNonChecksum;
|
||||||
|
} catch (error) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const ERC20ABI = [
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "name",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_spender",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_value",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "approve",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "totalSupply",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_from",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_to",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_value",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "transferFrom",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "decimals",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint8"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_owner",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "balanceOf",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "balance",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "symbol",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_to",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_value",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "transfer",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_owner",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_spender",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "allowance",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"payable": true,
|
||||||
|
"stateMutability": "payable",
|
||||||
|
"type": "fallback"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": true,
|
||||||
|
"name": "owner",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": true,
|
||||||
|
"name": "spender",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"name": "value",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "Approval",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": true,
|
||||||
|
"name": "from",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": true,
|
||||||
|
"name": "to",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"name": "value",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "Transfer",
|
||||||
|
"type": "event"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
const CONTRACT_ADDRESSES = {
|
||||||
|
// Arbitrum One network token addresses
|
||||||
|
usdc: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", // USDC on Arbitrum
|
||||||
|
usdt: "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9", // USDT on Arbitrum
|
||||||
|
weth: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1" // Wrapped ETH on Arbitrum
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get Arbitrum provider (MetaMask or public RPC)
|
||||||
|
* @param {boolean} readOnly - If true, use public RPC; if false, use MetaMask when available
|
||||||
|
* @returns {ethers.providers.Provider} Arbitrum provider instance
|
||||||
|
*/
|
||||||
|
const getProvider = ethOperator.getProvider = (readOnly = false) => {
|
||||||
|
if (!readOnly && window.ethereum) {
|
||||||
|
return new ethers.providers.Web3Provider(window.ethereum);
|
||||||
|
} else {
|
||||||
|
return new ethers.providers.JsonRpcProvider(`https://arb1.arbitrum.io/rpc`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Note: MetaMask connection is handled in the UI layer, not here
|
||||||
|
const getBalance = ethOperator.getBalance = async (address) => {
|
||||||
|
try {
|
||||||
|
if (!address || !isValidAddress(address))
|
||||||
|
return new Error('Invalid address');
|
||||||
|
|
||||||
|
// Use read-only provider (public RPC) for balance checks
|
||||||
|
const provider = getProvider(true);
|
||||||
|
const balanceWei = await provider.getBalance(address);
|
||||||
|
const balanceEth = parseFloat(ethers.utils.formatEther(balanceWei));
|
||||||
|
return balanceEth;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Balance error:', error.message);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const getTokenBalance = ethOperator.getTokenBalance = async (address, token, { contractAddress } = {}) => {
|
||||||
|
try {
|
||||||
|
if (!token)
|
||||||
|
return new Error("Token not specified");
|
||||||
|
if (!CONTRACT_ADDRESSES[token] && !contractAddress)
|
||||||
|
return new Error('Contract address of token not available')
|
||||||
|
|
||||||
|
// Use read-only provider (public RPC) for token balance checks
|
||||||
|
const provider = getProvider(true);
|
||||||
|
const tokenAddress = CONTRACT_ADDRESSES[token] || contractAddress;
|
||||||
|
const tokenContract = new ethers.Contract(tokenAddress, ERC20ABI, provider);
|
||||||
|
let balance = await tokenContract.balanceOf(address);
|
||||||
|
|
||||||
|
// WETH uses 18 decimals (like native ETH), USDC and USDT use 6 decimals
|
||||||
|
const decimals = token === 'weth' ? 18 : 6;
|
||||||
|
balance = parseFloat(ethers.utils.formatUnits(balance, decimals));
|
||||||
|
return balance;
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Token balance error:', e);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const estimateGas = ethOperator.estimateGas = async ({ privateKey, receiver, amount }) => {
|
||||||
|
try {
|
||||||
|
const provider = getProvider();
|
||||||
|
const signer = new ethers.Wallet(privateKey, provider);
|
||||||
|
return provider.estimateGas({
|
||||||
|
from: signer.address,
|
||||||
|
to: receiver,
|
||||||
|
value: ethers.utils.parseUnits(amount, "ether"),
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const sendTransaction = ethOperator.sendTransaction = async ({ privateKey, receiver, amount }) => {
|
||||||
|
try {
|
||||||
|
const provider = getProvider();
|
||||||
|
const signer = new ethers.Wallet(privateKey, provider);
|
||||||
|
const limit = await estimateGas({ privateKey, receiver, amount })
|
||||||
|
|
||||||
|
// Get current fee data from the network
|
||||||
|
const feeData = await provider.getFeeData();
|
||||||
|
|
||||||
|
// Calculate priority fee (tip to miners) - use 1.5 gwei or the network's suggested priority fee, whichever is higher
|
||||||
|
const priorityFee = feeData.maxPriorityFeePerGas || ethers.utils.parseUnits("1.5", "gwei");
|
||||||
|
|
||||||
|
// Calculate max fee per gas (base fee + priority fee)
|
||||||
|
// Use the network's suggested maxFeePerGas or calculate it manually
|
||||||
|
let maxFee = feeData.maxFeePerGas;
|
||||||
|
|
||||||
|
// If maxFeePerGas is not available or is less than priority fee, calculate it
|
||||||
|
if (!maxFee || maxFee.lt(priorityFee)) {
|
||||||
|
// Get the base fee from the latest block and add our priority fee
|
||||||
|
const block = await provider.getBlock("latest");
|
||||||
|
const baseFee = block.baseFeePerGas || ethers.utils.parseUnits("1", "gwei");
|
||||||
|
// maxFee = (baseFee * 2) + priorityFee to account for potential base fee increases
|
||||||
|
maxFee = baseFee.mul(2).add(priorityFee);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure maxFee is at least 1.5x the priority fee for safety
|
||||||
|
const minMaxFee = priorityFee.mul(15).div(10); // 1.5x priority fee
|
||||||
|
if (maxFee.lt(minMaxFee)) {
|
||||||
|
maxFee = minMaxFee;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creating and sending the transaction object
|
||||||
|
return signer.sendTransaction({
|
||||||
|
to: receiver,
|
||||||
|
value: ethers.utils.parseUnits(amount, "ether"),
|
||||||
|
gasLimit: limit,
|
||||||
|
nonce: await signer.getTransactionCount(),
|
||||||
|
maxPriorityFeePerGas: priorityFee,
|
||||||
|
maxFeePerGas: maxFee,
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send ERC20 tokens (USDC, USDT, or WETH)
|
||||||
|
* @param {object} params - Transaction parameters
|
||||||
|
* @param {string} params.token - Token symbol ('usdc', 'usdt', or 'weth')
|
||||||
|
* @param {string} params.privateKey - Sender's private key
|
||||||
|
* @param {string} params.amount - Amount to send
|
||||||
|
* @param {string} params.receiver - Recipient's Arbitrum address
|
||||||
|
* @param {string} params.contractAddress - Optional custom contract address
|
||||||
|
* @returns {Promise} Transaction promise
|
||||||
|
*/
|
||||||
|
const sendToken = ethOperator.sendToken = async ({ token, privateKey, amount, receiver, contractAddress }) => {
|
||||||
|
const wallet = new ethers.Wallet(privateKey, getProvider());
|
||||||
|
const tokenContract = new ethers.Contract(CONTRACT_ADDRESSES[token] || contractAddress, ERC20ABI, wallet);
|
||||||
|
// Convert amount to smallest unit: WETH uses 18 decimals, USDC and USDT use 6 decimals
|
||||||
|
const decimals = token === 'weth' ? 18 : 6;
|
||||||
|
const amountWei = ethers.utils.parseUnits(amount.toString(), decimals);
|
||||||
|
return tokenContract.transfer(receiver, amountWei)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const MORALIS_API_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJub25jZSI6IjNmMjE5NjM5LTQwYmYtNDhkMC1hNDMxLTI5YjA4YzhlYzE5MiIsIm9yZ0lkIjoiNDkwNTU1IiwidXNlcklkIjoiNTA0NzE5IiwidHlwZUlkIjoiYWNiMjQzOWUtMDEzYy00YjhjLWI2N2MtNjRlNGNhMjA4YTlkIiwidHlwZSI6IlBST0pFQ1QiLCJpYXQiOjE3Njg1MDcyNTIsImV4cCI6NDkyNDI2NzI1Mn0.X4Hn3VxLVRJL6HlAGPFQdWvQAdTXO20_Z8CpWhNt5CE';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get transaction history for an Arbitrum address using Moralis API
|
||||||
|
* @param {string} address - Arbitrum address
|
||||||
|
* @param {object} options - Optional parameters
|
||||||
|
* @returns {Promise<Array>} Array of transactions
|
||||||
|
*/
|
||||||
|
const getTransactionHistory = ethOperator.getTransactionHistory = async (address, options = {}) => {
|
||||||
|
try {
|
||||||
|
if (!address || !isValidAddress(address)) {
|
||||||
|
throw new Error('Invalid Arbitrum address');
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
page = 1,
|
||||||
|
offset = 100,
|
||||||
|
} = options;
|
||||||
|
|
||||||
|
// Moralis API endpoint for Arbitrum
|
||||||
|
const chain = '0xa4b1'; // Arbitrum One chain ID in hex
|
||||||
|
|
||||||
|
// Fetch transactions using Moralis API
|
||||||
|
const moralisUrl = `https://deep-index.moralis.io/api/v2.2/${address}?chain=${chain}&limit=${offset}`;
|
||||||
|
|
||||||
|
const response = await fetch(moralisUrl, {
|
||||||
|
headers: {
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'X-API-Key': MORALIS_API_KEY
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
const errorData = await response.json().catch(() => ({}));
|
||||||
|
throw new Error(`Moralis API Error: ${errorData.message || response.statusText}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
if (!data.result || data.result.length === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse and format transactions from Moralis response
|
||||||
|
return data.result.map(tx => {
|
||||||
|
const isReceived = tx.to_address && tx.to_address.toLowerCase() === address.toLowerCase();
|
||||||
|
const value = parseFloat(ethers.utils.formatEther(tx.value || '0'));
|
||||||
|
|
||||||
|
return {
|
||||||
|
hash: tx.hash,
|
||||||
|
from: tx.from_address,
|
||||||
|
to: tx.to_address,
|
||||||
|
value: value,
|
||||||
|
symbol: 'ETH',
|
||||||
|
timestamp: new Date(tx.block_timestamp).getTime() / 1000,
|
||||||
|
blockNumber: parseInt(tx.block_number),
|
||||||
|
isReceived: isReceived,
|
||||||
|
isSent: !isReceived,
|
||||||
|
gasUsed: tx.receipt_gas_used ? parseInt(tx.receipt_gas_used) : 0,
|
||||||
|
gasPrice: tx.gas_price ? parseFloat(ethers.utils.formatUnits(tx.gas_price, 'gwei')) : 0,
|
||||||
|
isError: tx.receipt_status === '0',
|
||||||
|
contractAddress: tx.to_address && tx.input !== '0x' ? tx.to_address : null,
|
||||||
|
tokenName: null,
|
||||||
|
confirmations: 0,
|
||||||
|
nonce: tx.nonce ? parseInt(tx.nonce) : 0,
|
||||||
|
input: tx.input || '0x',
|
||||||
|
isTokenTransfer: false
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching transaction history:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get detailed information about a specific transaction
|
||||||
|
* @param {string} txHash - Transaction hash
|
||||||
|
* @returns {Promise<Object>} Transaction details
|
||||||
|
*/
|
||||||
|
const getTransactionDetails = ethOperator.getTransactionDetails = async (txHash) => {
|
||||||
|
try {
|
||||||
|
if (!txHash || !/^0x([A-Fa-f0-9]{64})$/.test(txHash)) {
|
||||||
|
throw new Error('Invalid transaction hash');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use read-only provider for fetching transaction details
|
||||||
|
const provider = getProvider(true);
|
||||||
|
|
||||||
|
// Get transaction details
|
||||||
|
const tx = await provider.getTransaction(txHash);
|
||||||
|
|
||||||
|
if (!tx) {
|
||||||
|
throw new Error('Transaction not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get transaction receipt for status and gas used
|
||||||
|
const receipt = await provider.getTransactionReceipt(txHash);
|
||||||
|
|
||||||
|
// Get current block number for confirmations
|
||||||
|
const currentBlock = await provider.getBlockNumber();
|
||||||
|
|
||||||
|
// Get block details for timestamp
|
||||||
|
const block = await provider.getBlock(tx.blockNumber);
|
||||||
|
|
||||||
|
// Calculate gas fee
|
||||||
|
const gasUsed = receipt ? receipt.gasUsed : null;
|
||||||
|
const effectiveGasPrice = receipt ? receipt.effectiveGasPrice : tx.gasPrice;
|
||||||
|
const gasFee = gasUsed && effectiveGasPrice ?
|
||||||
|
parseFloat(ethers.utils.formatEther(gasUsed.mul(effectiveGasPrice))) : null;
|
||||||
|
|
||||||
|
// Check if it's a token transfer by examining logs
|
||||||
|
let tokenTransfer = null;
|
||||||
|
if (receipt && receipt.logs.length > 0) {
|
||||||
|
// Try to decode ERC20 Transfer event
|
||||||
|
const transferEventSignature = ethers.utils.id('Transfer(address,address,uint256)');
|
||||||
|
const transferLog = receipt.logs.find(log => log.topics[0] === transferEventSignature);
|
||||||
|
|
||||||
|
if (transferLog) {
|
||||||
|
try {
|
||||||
|
const tokenContract = new ethers.Contract(transferLog.address, ERC20ABI, provider);
|
||||||
|
const [symbol, decimals] = await Promise.all([
|
||||||
|
tokenContract.symbol().catch(() => 'TOKEN'),
|
||||||
|
tokenContract.decimals().catch(() => 18)
|
||||||
|
]);
|
||||||
|
|
||||||
|
const from = ethers.utils.getAddress('0x' + transferLog.topics[1].slice(26));
|
||||||
|
const to = ethers.utils.getAddress('0x' + transferLog.topics[2].slice(26));
|
||||||
|
const value = parseFloat(ethers.utils.formatUnits(transferLog.data, decimals));
|
||||||
|
|
||||||
|
tokenTransfer = {
|
||||||
|
from,
|
||||||
|
to,
|
||||||
|
value,
|
||||||
|
symbol,
|
||||||
|
contractAddress: transferLog.address
|
||||||
|
};
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('Could not decode token transfer:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
hash: tx.hash,
|
||||||
|
from: tx.from,
|
||||||
|
to: tx.to,
|
||||||
|
value: parseFloat(ethers.utils.formatEther(tx.value)),
|
||||||
|
symbol: 'ETH',
|
||||||
|
blockNumber: tx.blockNumber,
|
||||||
|
timestamp: block ? block.timestamp : null,
|
||||||
|
confirmations: currentBlock - tx.blockNumber,
|
||||||
|
gasLimit: tx.gasLimit.toString(),
|
||||||
|
gasUsed: gasUsed ? gasUsed.toString() : null,
|
||||||
|
gasPrice: parseFloat(ethers.utils.formatUnits(tx.gasPrice, 'gwei')),
|
||||||
|
gasFee: gasFee,
|
||||||
|
nonce: tx.nonce,
|
||||||
|
input: tx.data,
|
||||||
|
status: receipt ? (receipt.status === 1 ? 'success' : 'failed') : 'pending',
|
||||||
|
isError: receipt ? receipt.status !== 1 : false,
|
||||||
|
tokenTransfer: tokenTransfer,
|
||||||
|
logs: receipt ? receipt.logs : [],
|
||||||
|
type: tx.type
|
||||||
|
};
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching transaction details:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a string is a valid transaction hash
|
||||||
|
* @param {string} hash - Potential transaction hash
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
const isValidTxHash = ethOperator.isValidTxHash = (hash) => {
|
||||||
|
return /^0x([A-Fa-f0-9]{64})$/.test(hash);
|
||||||
|
};
|
||||||
|
|
||||||
|
})('object' === typeof module ? module.exports : window.ethOperator = {});
|
||||||
1
arbitrumwallet/scripts/ethOperator.min.js
vendored
Normal file
1
arbitrumwallet/scripts/ethOperator.min.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
!function(EXPORTS){if(!window.ethers)return console.error("ethers.js not found");const ethOperator=EXPORTS,isValidAddress=ethOperator.isValidAddress=address=>{try{const isValidChecksum=ethers.utils.isAddress(address),isValidNonChecksum=ethers.utils.getAddress(address)===address.toLowerCase();return isValidChecksum||isValidNonChecksum}catch(error){return!1}},ERC20ABI=[{constant:!0,inputs:[],name:"name",outputs:[{name:"",type:"string"}],payable:!1,stateMutability:"view",type:"function"},{constant:!1,inputs:[{name:"_spender",type:"address"},{name:"_value",type:"uint256"}],name:"approve",outputs:[{name:"",type:"bool"}],payable:!1,stateMutability:"nonpayable",type:"function"},{constant:!0,inputs:[],name:"totalSupply",outputs:[{name:"",type:"uint256"}],payable:!1,stateMutability:"view",type:"function"},{constant:!1,inputs:[{name:"_from",type:"address"},{name:"_to",type:"address"},{name:"_value",type:"uint256"}],name:"transferFrom",outputs:[{name:"",type:"bool"}],payable:!1,stateMutability:"nonpayable",type:"function"},{constant:!0,inputs:[],name:"decimals",outputs:[{name:"",type:"uint8"}],payable:!1,stateMutability:"view",type:"function"},{constant:!0,inputs:[{name:"_owner",type:"address"}],name:"balanceOf",outputs:[{name:"balance",type:"uint256"}],payable:!1,stateMutability:"view",type:"function"},{constant:!0,inputs:[],name:"symbol",outputs:[{name:"",type:"string"}],payable:!1,stateMutability:"view",type:"function"},{constant:!1,inputs:[{name:"_to",type:"address"},{name:"_value",type:"uint256"}],name:"transfer",outputs:[{name:"",type:"bool"}],payable:!1,stateMutability:"nonpayable",type:"function"},{constant:!0,inputs:[{name:"_owner",type:"address"},{name:"_spender",type:"address"}],name:"allowance",outputs:[{name:"",type:"uint256"}],payable:!1,stateMutability:"view",type:"function"},{payable:!0,stateMutability:"payable",type:"fallback"},{anonymous:!1,inputs:[{indexed:!0,name:"owner",type:"address"},{indexed:!0,name:"spender",type:"address"},{indexed:!1,name:"value",type:"uint256"}],name:"Approval",type:"event"},{anonymous:!1,inputs:[{indexed:!0,name:"from",type:"address"},{indexed:!0,name:"to",type:"address"},{indexed:!1,name:"value",type:"uint256"}],name:"Transfer",type:"event"}],CONTRACT_ADDRESSES={usdc:"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",usdt:"0xdac17f958d2ee523a2206206994597c13d831ec7"};function getProvider(){return window.ethereum?new ethers.providers.Web3Provider(window.ethereum):new ethers.providers.JsonRpcProvider("https://mainnet.infura.io/v3/6e12fee52bdd48208f0d82fb345bcb3c")}ethOperator.getBalance=async address=>{try{if(!address||!isValidAddress(address))return new Error("Invalid address");const provider=getProvider(),balanceWei=await provider.getBalance(address);return parseFloat(ethers.utils.formatEther(balanceWei))}catch(error){return console.error("Error:",error.message),error}},ethOperator.getTokenBalance=async(address,token,{contractAddress:contractAddress}={})=>{try{if(!token)return new Error("Token not specified");if(!CONTRACT_ADDRESSES[token]&&contractAddress)return new Error("Contract address of token not available");const usdcContract=new ethers.Contract(CONTRACT_ADDRESSES[token]||contractAddress,ERC20ABI,getProvider());let balance=await usdcContract.balanceOf(address);return balance=parseFloat(ethers.utils.formatUnits(balance,6)),balance}catch(e){console.error(e)}};const estimateGas=ethOperator.estimateGas=async({privateKey:privateKey,receiver:receiver,amount:amount})=>{try{const provider=getProvider(),signer=new ethers.Wallet(privateKey,provider);return provider.estimateGas({from:signer.address,to:receiver,value:ethers.utils.parseUnits(amount,"ether")})}catch(e){throw new Error(e)}};ethOperator.sendTransaction=async({privateKey:privateKey,receiver:receiver,amount:amount})=>{try{const provider=getProvider(),signer=new ethers.Wallet(privateKey,provider),limit=await estimateGas({privateKey:privateKey,receiver:receiver,amount:amount});return signer.sendTransaction({to:receiver,value:ethers.utils.parseUnits(amount,"ether"),gasLimit:limit,nonce:signer.getTransactionCount(),maxPriorityFeePerGas:ethers.utils.parseUnits("2","gwei")})}catch(e){throw new Error(e)}},ethOperator.sendToken=async({token:token,privateKey:privateKey,amount:amount,receiver:receiver,contractAddress:contractAddress})=>{const wallet=new ethers.Wallet(privateKey,getProvider()),tokenContract=new ethers.Contract(CONTRACT_ADDRESSES[token]||contractAddress,ERC20ABI,wallet),amountWei=ethers.utils.parseUnits(amount.toString(),6);return tokenContract.transfer(receiver,amountWei)}}("object"==typeof module?module.exports:window.ethOperator={});
|
||||||
1
arbitrumwallet/scripts/ether.umd.min.js
vendored
Normal file
1
arbitrumwallet/scripts/ether.umd.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
530
arbitrumwallet/scripts/floCrypto.js
Normal file
530
arbitrumwallet/scripts/floCrypto.js
Normal file
@ -0,0 +1,530 @@
|
|||||||
|
(function (EXPORTS) { //floCrypto v2.3.6a
|
||||||
|
/* FLO Crypto Operators */
|
||||||
|
'use strict';
|
||||||
|
const floCrypto = EXPORTS;
|
||||||
|
|
||||||
|
const p = BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16);
|
||||||
|
const ecparams = EllipticCurve.getSECCurveByName("secp256k1");
|
||||||
|
const ascii_alternatives = `‘ '\n’ '\n“ "\n” "\n– --\n— ---\n≥ >=\n≤ <=\n≠ !=\n× *\n÷ /\n← <-\n→ ->\n↔ <->\n⇒ =>\n⇐ <=\n⇔ <=>`;
|
||||||
|
const exponent1 = () => p.add(BigInteger.ONE).divide(BigInteger("4"));
|
||||||
|
coinjs.compressed = true; //defaulting coinjs compressed to true;
|
||||||
|
|
||||||
|
function calculateY(x) {
|
||||||
|
let exp = exponent1();
|
||||||
|
// x is x value of public key in BigInteger format without 02 or 03 or 04 prefix
|
||||||
|
return x.modPow(BigInteger("3"), p).add(BigInteger("7")).mod(p).modPow(exp, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getUncompressedPublicKey(compressedPublicKey) {
|
||||||
|
// Fetch x from compressedPublicKey
|
||||||
|
let pubKeyBytes = Crypto.util.hexToBytes(compressedPublicKey);
|
||||||
|
const prefix = pubKeyBytes.shift() // remove prefix
|
||||||
|
let prefix_modulus = prefix % 2;
|
||||||
|
pubKeyBytes.unshift(0) // add prefix 0
|
||||||
|
let x = new BigInteger(pubKeyBytes)
|
||||||
|
let xDecimalValue = x.toString()
|
||||||
|
// Fetch y
|
||||||
|
let y = calculateY(x);
|
||||||
|
let yDecimalValue = y.toString();
|
||||||
|
// verify y value
|
||||||
|
let resultBigInt = y.mod(BigInteger("2"));
|
||||||
|
let check = resultBigInt.toString() % 2;
|
||||||
|
if (prefix_modulus !== check)
|
||||||
|
yDecimalValue = y.negate().mod(p).toString();
|
||||||
|
return {
|
||||||
|
x: xDecimalValue,
|
||||||
|
y: yDecimalValue
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSenderPublicKeyString() {
|
||||||
|
let privateKey = ellipticCurveEncryption.senderRandom();
|
||||||
|
var senderPublicKeyString = ellipticCurveEncryption.senderPublicString(privateKey);
|
||||||
|
return {
|
||||||
|
privateKey: privateKey,
|
||||||
|
senderPublicKeyString: senderPublicKeyString
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function deriveSharedKeySender(receiverPublicKeyHex, senderPrivateKey) {
|
||||||
|
let receiverPublicKeyString = getUncompressedPublicKey(receiverPublicKeyHex);
|
||||||
|
var senderDerivedKey = ellipticCurveEncryption.senderSharedKeyDerivation(
|
||||||
|
receiverPublicKeyString.x, receiverPublicKeyString.y, senderPrivateKey);
|
||||||
|
return senderDerivedKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
function deriveSharedKeyReceiver(senderPublicKeyString, receiverPrivateKey) {
|
||||||
|
return ellipticCurveEncryption.receiverSharedKeyDerivation(
|
||||||
|
senderPublicKeyString.XValuePublicString, senderPublicKeyString.YValuePublicString, receiverPrivateKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getReceiverPublicKeyString(privateKey) {
|
||||||
|
return ellipticCurveEncryption.receiverPublicString(privateKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function wifToDecimal(pk_wif, isPubKeyCompressed = false) {
|
||||||
|
let pk = Bitcoin.Base58.decode(pk_wif)
|
||||||
|
pk.shift()
|
||||||
|
pk.splice(-4, 4)
|
||||||
|
//If the private key corresponded to a compressed public key, also drop the last byte (it should be 0x01).
|
||||||
|
if (isPubKeyCompressed == true) pk.pop()
|
||||||
|
pk.unshift(0)
|
||||||
|
let privateKeyDecimal = BigInteger(pk).toString()
|
||||||
|
let privateKeyHex = Crypto.util.bytesToHex(pk)
|
||||||
|
return {
|
||||||
|
privateKeyDecimal: privateKeyDecimal,
|
||||||
|
privateKeyHex: privateKeyHex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//generate a random Interger within range
|
||||||
|
floCrypto.randInt = function (min, max) {
|
||||||
|
min = Math.ceil(min);
|
||||||
|
max = Math.floor(max);
|
||||||
|
return Math.floor(securedMathRandom() * (max - min + 1)) + min;
|
||||||
|
}
|
||||||
|
|
||||||
|
//generate a random String within length (options : alphaNumeric chars only)
|
||||||
|
floCrypto.randString = function (length, alphaNumeric = true) {
|
||||||
|
var result = '';
|
||||||
|
var characters = alphaNumeric ? 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' :
|
||||||
|
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_+-./*?@#&$<>=[]{}():';
|
||||||
|
for (var i = 0; i < length; i++)
|
||||||
|
result += characters.charAt(Math.floor(securedMathRandom() * characters.length));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Encrypt Data using public-key
|
||||||
|
floCrypto.encryptData = function (data, receiverPublicKeyHex) {
|
||||||
|
var senderECKeyData = getSenderPublicKeyString();
|
||||||
|
var senderDerivedKey = deriveSharedKeySender(receiverPublicKeyHex, senderECKeyData.privateKey);
|
||||||
|
let senderKey = senderDerivedKey.XValue + senderDerivedKey.YValue;
|
||||||
|
let secret = Crypto.AES.encrypt(data, senderKey);
|
||||||
|
return {
|
||||||
|
secret: secret,
|
||||||
|
senderPublicKeyString: senderECKeyData.senderPublicKeyString
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//Decrypt Data using private-key
|
||||||
|
floCrypto.decryptData = function (data, privateKeyHex) {
|
||||||
|
var receiverECKeyData = {};
|
||||||
|
if (typeof privateKeyHex !== "string") throw new Error("No private key found.");
|
||||||
|
let privateKey = wifToDecimal(privateKeyHex, true);
|
||||||
|
if (typeof privateKey.privateKeyDecimal !== "string") throw new Error("Failed to detremine your private key.");
|
||||||
|
receiverECKeyData.privateKey = privateKey.privateKeyDecimal;
|
||||||
|
var receiverDerivedKey = deriveSharedKeyReceiver(data.senderPublicKeyString, receiverECKeyData.privateKey);
|
||||||
|
let receiverKey = receiverDerivedKey.XValue + receiverDerivedKey.YValue;
|
||||||
|
let decryptMsg = Crypto.AES.decrypt(data.secret, receiverKey);
|
||||||
|
return decryptMsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Sign data using private-key
|
||||||
|
floCrypto.signData = function (data, privateKeyHex) {
|
||||||
|
var key = new Bitcoin.ECKey(privateKeyHex);
|
||||||
|
var messageHash = Crypto.SHA256(data);
|
||||||
|
var messageSign = Bitcoin.ECDSA.sign(messageHash, key.priv);
|
||||||
|
var sighex = Crypto.util.bytesToHex(messageSign);
|
||||||
|
return sighex;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Verify signatue of the data using public-key
|
||||||
|
floCrypto.verifySign = function (data, signatureHex, publicKeyHex) {
|
||||||
|
var msgHash = Crypto.SHA256(data);
|
||||||
|
var sigBytes = Crypto.util.hexToBytes(signatureHex);
|
||||||
|
var publicKeyPoint = ecparams.getCurve().decodePointHex(publicKeyHex);
|
||||||
|
var verify = Bitcoin.ECDSA.verify(msgHash, sigBytes, publicKeyPoint);
|
||||||
|
return verify;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Generates a new flo ID and returns private-key, public-key and floID
|
||||||
|
const generateNewID = floCrypto.generateNewID = function () {
|
||||||
|
var key = new Bitcoin.ECKey(false);
|
||||||
|
key.setCompressed(true);
|
||||||
|
return {
|
||||||
|
floID: key.getBitcoinAddress(),
|
||||||
|
pubKey: key.getPubKeyHex(),
|
||||||
|
privKey: key.getBitcoinWalletImportFormat()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.defineProperties(floCrypto, {
|
||||||
|
newID: {
|
||||||
|
get: () => generateNewID()
|
||||||
|
},
|
||||||
|
hashID: {
|
||||||
|
value: (str) => {
|
||||||
|
let bytes = ripemd160(Crypto.SHA256(str, { asBytes: true }), { asBytes: true });
|
||||||
|
bytes.unshift(bitjs.pub);
|
||||||
|
var hash = Crypto.SHA256(Crypto.SHA256(bytes, {
|
||||||
|
asBytes: true
|
||||||
|
}), {
|
||||||
|
asBytes: true
|
||||||
|
});
|
||||||
|
var checksum = hash.slice(0, 4);
|
||||||
|
return bitjs.Base58.encode(bytes.concat(checksum));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tmpID: {
|
||||||
|
get: () => {
|
||||||
|
let bytes = Crypto.util.randomBytes(20);
|
||||||
|
bytes.unshift(bitjs.pub);
|
||||||
|
var hash = Crypto.SHA256(Crypto.SHA256(bytes, {
|
||||||
|
asBytes: true
|
||||||
|
}), {
|
||||||
|
asBytes: true
|
||||||
|
});
|
||||||
|
var checksum = hash.slice(0, 4);
|
||||||
|
return bitjs.Base58.encode(bytes.concat(checksum));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//Returns public-key from private-key
|
||||||
|
floCrypto.getPubKeyHex = function (privateKeyHex) {
|
||||||
|
if (!privateKeyHex)
|
||||||
|
return null;
|
||||||
|
var key = new Bitcoin.ECKey(privateKeyHex);
|
||||||
|
if (key.priv == null)
|
||||||
|
return null;
|
||||||
|
key.setCompressed(true);
|
||||||
|
return key.getPubKeyHex();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Returns flo-ID from public-key or private-key
|
||||||
|
floCrypto.getFloID = function (keyHex) {
|
||||||
|
if (!keyHex)
|
||||||
|
return null;
|
||||||
|
try {
|
||||||
|
var key = new Bitcoin.ECKey(keyHex);
|
||||||
|
if (key.priv == null)
|
||||||
|
key.setPub(keyHex);
|
||||||
|
return key.getBitcoinAddress();
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
floCrypto.getAddress = function (privateKeyHex, strict = false) {
|
||||||
|
if (!privateKeyHex)
|
||||||
|
return;
|
||||||
|
var key = new Bitcoin.ECKey(privateKeyHex);
|
||||||
|
if (key.priv == null)
|
||||||
|
return null;
|
||||||
|
key.setCompressed(true);
|
||||||
|
let pubKey = key.getPubKeyHex(),
|
||||||
|
version = bitjs.Base58.decode(privateKeyHex)[0];
|
||||||
|
switch (version) {
|
||||||
|
case coinjs.priv: //BTC
|
||||||
|
return coinjs.bech32Address(pubKey).address;
|
||||||
|
case bitjs.priv: //FLO
|
||||||
|
return bitjs.pubkey2address(pubKey);
|
||||||
|
default:
|
||||||
|
return strict ? false : bitjs.pubkey2address(pubKey); //default to FLO address (if strict=false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Verify the private-key for the given public-key or flo-ID
|
||||||
|
floCrypto.verifyPrivKey = function (privateKeyHex, pubKey_floID, isfloID = true) {
|
||||||
|
if (!privateKeyHex || !pubKey_floID)
|
||||||
|
return false;
|
||||||
|
try {
|
||||||
|
var key = new Bitcoin.ECKey(privateKeyHex);
|
||||||
|
if (key.priv == null)
|
||||||
|
return false;
|
||||||
|
key.setCompressed(true);
|
||||||
|
if (isfloID && pubKey_floID == key.getBitcoinAddress())
|
||||||
|
return true;
|
||||||
|
else if (!isfloID && pubKey_floID.toUpperCase() == key.getPubKeyHex().toUpperCase())
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
floCrypto.getMultisigAddress = function (publicKeyList, requiredSignatures) {
|
||||||
|
if (!Array.isArray(publicKeyList) || !publicKeyList.length)
|
||||||
|
return null;
|
||||||
|
if (!Number.isInteger(requiredSignatures) || requiredSignatures < 1 || requiredSignatures > publicKeyList.length)
|
||||||
|
return null;
|
||||||
|
try {
|
||||||
|
var multisig = bitjs.pubkeys2multisig(publicKeyList, requiredSignatures);
|
||||||
|
return multisig;
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
floCrypto.decodeRedeemScript = function (redeemScript) {
|
||||||
|
try {
|
||||||
|
var decoded = bitjs.transaction().decodeRedeemScript(redeemScript);
|
||||||
|
return decoded;
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check if the given flo-id is valid or not
|
||||||
|
floCrypto.validateFloID = function (floID, regularOnly = false) {
|
||||||
|
if (!floID)
|
||||||
|
return false;
|
||||||
|
try {
|
||||||
|
let addr = new Bitcoin.Address(floID);
|
||||||
|
if (regularOnly && addr.version != Bitcoin.Address.standardVersion)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check if the given address (any blockchain) is valid or not
|
||||||
|
floCrypto.validateAddr = function (address, std = true, bech = true) {
|
||||||
|
let raw = decodeAddress(address);
|
||||||
|
if (!raw)
|
||||||
|
return false;
|
||||||
|
if (typeof raw.version !== 'undefined') { //legacy or segwit
|
||||||
|
if (std == false)
|
||||||
|
return false;
|
||||||
|
else if (std === true || (!Array.isArray(std) && std === raw.version) || (Array.isArray(std) && std.includes(raw.version)))
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
} else if (typeof raw.bech_version !== 'undefined') { //bech32
|
||||||
|
if (bech === false)
|
||||||
|
return false;
|
||||||
|
else if (bech === true || (!Array.isArray(bech) && bech === raw.bech_version) || (Array.isArray(bech) && bech.includes(raw.bech_version)))
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
} else //unknown
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check the public-key (or redeem-script) for the address (any blockchain)
|
||||||
|
floCrypto.verifyPubKey = function (pubKeyHex, address) {
|
||||||
|
let raw = decodeAddress(address);
|
||||||
|
if (!raw)
|
||||||
|
return;
|
||||||
|
let pub_hash = Crypto.util.bytesToHex(ripemd160(Crypto.SHA256(Crypto.util.hexToBytes(pubKeyHex), { asBytes: true })));
|
||||||
|
if (typeof raw.bech_version !== 'undefined' && raw.bytes.length == 32) //bech32-multisig
|
||||||
|
raw.hex = Crypto.util.bytesToHex(ripemd160(raw.bytes, { asBytes: true }));
|
||||||
|
return pub_hash === raw.hex;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Convert the given address (any blockchain) to equivalent floID
|
||||||
|
floCrypto.toFloID = function (address, options = null) {
|
||||||
|
if (!address)
|
||||||
|
return;
|
||||||
|
let raw = decodeAddress(address);
|
||||||
|
if (!raw)
|
||||||
|
return;
|
||||||
|
else if (options) { //if (optional) version check is passed
|
||||||
|
if (typeof raw.version !== 'undefined' && (!options.std || !options.std.includes(raw.version)))
|
||||||
|
return;
|
||||||
|
if (typeof raw.bech_version !== 'undefined' && (!options.bech || !options.bech.includes(raw.bech_version)))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
raw.bytes.unshift(bitjs.pub);
|
||||||
|
let hash = Crypto.SHA256(Crypto.SHA256(raw.bytes, {
|
||||||
|
asBytes: true
|
||||||
|
}), {
|
||||||
|
asBytes: true
|
||||||
|
});
|
||||||
|
return bitjs.Base58.encode(raw.bytes.concat(hash.slice(0, 4)));
|
||||||
|
}
|
||||||
|
|
||||||
|
//Convert raw address bytes to floID
|
||||||
|
floCrypto.rawToFloID = function (raw_bytes) {
|
||||||
|
if (typeof raw_bytes === 'string')
|
||||||
|
raw_bytes = Crypto.util.hexToBytes(raw_bytes);
|
||||||
|
if (raw_bytes.length != 20)
|
||||||
|
return null;
|
||||||
|
raw_bytes.unshift(bitjs.pub);
|
||||||
|
let hash = Crypto.SHA256(Crypto.SHA256(raw_bytes, {
|
||||||
|
asBytes: true
|
||||||
|
}), {
|
||||||
|
asBytes: true
|
||||||
|
});
|
||||||
|
return bitjs.Base58.encode(raw_bytes.concat(hash.slice(0, 4)));
|
||||||
|
}
|
||||||
|
|
||||||
|
//Convert the given multisig address (any blockchain) to equivalent multisig floID
|
||||||
|
floCrypto.toMultisigFloID = function (address, options = null) {
|
||||||
|
if (!address)
|
||||||
|
return;
|
||||||
|
let raw = decodeAddress(address);
|
||||||
|
if (!raw)
|
||||||
|
return;
|
||||||
|
else if (options) { //if (optional) version check is passed
|
||||||
|
if (typeof raw.version !== 'undefined' && (!options.std || !options.std.includes(raw.version)))
|
||||||
|
return;
|
||||||
|
if (typeof raw.bech_version !== 'undefined' && (!options.bech || !options.bech.includes(raw.bech_version)))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (typeof raw.bech_version !== 'undefined') {
|
||||||
|
if (raw.bytes.length != 32) return; //multisig bech address have 32 bytes
|
||||||
|
//multisig-bech:hash=SHA256 whereas multisig:hash=r160(SHA265), thus ripemd160 the bytes from multisig-bech
|
||||||
|
raw.bytes = ripemd160(raw.bytes, {
|
||||||
|
asBytes: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
raw.bytes.unshift(bitjs.multisig);
|
||||||
|
let hash = Crypto.SHA256(Crypto.SHA256(raw.bytes, {
|
||||||
|
asBytes: true
|
||||||
|
}), {
|
||||||
|
asBytes: true
|
||||||
|
});
|
||||||
|
return bitjs.Base58.encode(raw.bytes.concat(hash.slice(0, 4)));
|
||||||
|
}
|
||||||
|
|
||||||
|
//Checks if the given addresses (any blockchain) are same (w.r.t keys)
|
||||||
|
floCrypto.isSameAddr = function (addr1, addr2) {
|
||||||
|
if (!addr1 || !addr2)
|
||||||
|
return;
|
||||||
|
let raw1 = decodeAddress(addr1),
|
||||||
|
raw2 = decodeAddress(addr2);
|
||||||
|
if (!raw1 || !raw2)
|
||||||
|
return false;
|
||||||
|
else {
|
||||||
|
if (typeof raw1.bech_version !== 'undefined' && raw1.bytes.length == 32) //bech32-multisig
|
||||||
|
raw1.hex = Crypto.util.bytesToHex(ripemd160(raw1.bytes, { asBytes: true }));
|
||||||
|
if (typeof raw2.bech_version !== 'undefined' && raw2.bytes.length == 32) //bech32-multisig
|
||||||
|
raw2.hex = Crypto.util.bytesToHex(ripemd160(raw2.bytes, { asBytes: true }));
|
||||||
|
return raw1.hex === raw2.hex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const decodeAddress = floCrypto.decodeAddr = function (address) {
|
||||||
|
if (!address)
|
||||||
|
return;
|
||||||
|
else if (address.length == 33 || address.length == 34) { //legacy encoding
|
||||||
|
let decode = bitjs.Base58.decode(address);
|
||||||
|
let bytes = decode.slice(0, decode.length - 4);
|
||||||
|
let checksum = decode.slice(decode.length - 4),
|
||||||
|
hash = Crypto.SHA256(Crypto.SHA256(bytes, {
|
||||||
|
asBytes: true
|
||||||
|
}), {
|
||||||
|
asBytes: true
|
||||||
|
});
|
||||||
|
return (hash[0] != checksum[0] || hash[1] != checksum[1] || hash[2] != checksum[2] || hash[3] != checksum[3]) ? null : {
|
||||||
|
version: bytes.shift(),
|
||||||
|
hex: Crypto.util.bytesToHex(bytes),
|
||||||
|
bytes
|
||||||
|
}
|
||||||
|
} else if (address.length == 42 || address.length == 62) { //bech encoding
|
||||||
|
let decode = coinjs.bech32_decode(address);
|
||||||
|
if (decode) {
|
||||||
|
let bytes = decode.data;
|
||||||
|
let bech_version = bytes.shift();
|
||||||
|
bytes = coinjs.bech32_convert(bytes, 5, 8, false);
|
||||||
|
return {
|
||||||
|
bech_version,
|
||||||
|
hrp: decode.hrp,
|
||||||
|
hex: Crypto.util.bytesToHex(bytes),
|
||||||
|
bytes
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Split the str using shamir's Secret and Returns the shares
|
||||||
|
floCrypto.createShamirsSecretShares = function (str, total_shares, threshold_limit) {
|
||||||
|
try {
|
||||||
|
if (str.length > 0) {
|
||||||
|
var strHex = shamirSecretShare.str2hex(str);
|
||||||
|
var shares = shamirSecretShare.share(strHex, total_shares, threshold_limit);
|
||||||
|
return shares;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Returns the retrived secret by combining the shamirs shares
|
||||||
|
const retrieveShamirSecret = floCrypto.retrieveShamirSecret = function (sharesArray) {
|
||||||
|
try {
|
||||||
|
if (sharesArray.length > 0) {
|
||||||
|
var comb = shamirSecretShare.combine(sharesArray.slice(0, sharesArray.length));
|
||||||
|
comb = shamirSecretShare.hex2str(comb);
|
||||||
|
return comb;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Verifies the shares and str
|
||||||
|
floCrypto.verifyShamirsSecret = function (sharesArray, str) {
|
||||||
|
if (!str)
|
||||||
|
return null;
|
||||||
|
else if (retrieveShamirSecret(sharesArray) === str)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const validateASCII = floCrypto.validateASCII = function (string, bool = true) {
|
||||||
|
if (typeof string !== "string")
|
||||||
|
return null;
|
||||||
|
if (bool) {
|
||||||
|
let x;
|
||||||
|
for (let i = 0; i < string.length; i++) {
|
||||||
|
x = string.charCodeAt(i);
|
||||||
|
if (x < 32 || x > 127)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
let x, invalids = {};
|
||||||
|
for (let i = 0; i < string.length; i++) {
|
||||||
|
x = string.charCodeAt(i);
|
||||||
|
if (x < 32 || x > 127)
|
||||||
|
if (x in invalids)
|
||||||
|
invalids[string[i]].push(i)
|
||||||
|
else
|
||||||
|
invalids[string[i]] = [i];
|
||||||
|
}
|
||||||
|
if (Object.keys(invalids).length)
|
||||||
|
return invalids;
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
floCrypto.convertToASCII = function (string, mode = 'soft-remove') {
|
||||||
|
let chars = validateASCII(string, false);
|
||||||
|
if (chars === true)
|
||||||
|
return string;
|
||||||
|
else if (chars === null)
|
||||||
|
return null;
|
||||||
|
let convertor, result = string,
|
||||||
|
refAlt = {};
|
||||||
|
ascii_alternatives.split('\n').forEach(a => refAlt[a[0]] = a.slice(2));
|
||||||
|
mode = mode.toLowerCase();
|
||||||
|
if (mode === "hard-unicode")
|
||||||
|
convertor = (c) => `\\u${('000' + c.charCodeAt().toString(16)).slice(-4)}`;
|
||||||
|
else if (mode === "soft-unicode")
|
||||||
|
convertor = (c) => refAlt[c] || `\\u${('000' + c.charCodeAt().toString(16)).slice(-4)}`;
|
||||||
|
else if (mode === "hard-remove")
|
||||||
|
convertor = c => "";
|
||||||
|
else if (mode === "soft-remove")
|
||||||
|
convertor = c => refAlt[c] || "";
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
for (let c in chars)
|
||||||
|
result = result.replaceAll(c, convertor(c));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
floCrypto.revertUnicode = function (string) {
|
||||||
|
return string.replace(/\\u[\dA-F]{4}/gi,
|
||||||
|
m => String.fromCharCode(parseInt(m.replace(/\\u/g, ''), 16)));
|
||||||
|
}
|
||||||
|
|
||||||
|
})('object' === typeof module ? module.exports : window.floCrypto = {});
|
||||||
57
arbitrumwallet/scripts/floEthereum.js
Normal file
57
arbitrumwallet/scripts/floEthereum.js
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
(function (EXPORTS) { //floEthereum v1.0.1a
|
||||||
|
/* FLO Ethereum Operators */
|
||||||
|
/* Make sure you added Taproot, Keccak, FLO and BTC Libraries before */
|
||||||
|
'use strict';
|
||||||
|
const floEthereum = EXPORTS;
|
||||||
|
|
||||||
|
const ethAddressFromPrivateKey = floEthereum.ethAddressFromPrivateKey = function (privateKey, onlyEvenY = false) {
|
||||||
|
var t1, t1_x, t1_y, t1_y_BigInt, t2, t3, t4;
|
||||||
|
var groupOrder = BigInt("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F");
|
||||||
|
|
||||||
|
t1 = bitjs.newPubkey(privateKey);
|
||||||
|
t1_x = t1.slice(2, 66); t1_y = t1.slice(-64);
|
||||||
|
if (onlyEvenY) {
|
||||||
|
t1_y_BigInt = BigInt("0x" + t1_y);
|
||||||
|
if (t1_y_BigInt % 2n !== 0n) { t1_y_BigInt = (groupOrder - t1_y_BigInt) % groupOrder; t1_y = t1_y_BigInt.toString(16) }
|
||||||
|
};
|
||||||
|
|
||||||
|
t2 = t1_x.toString(16) + t1_y.toString(16);
|
||||||
|
t3 = keccak.keccak_256(Crypto.util.hexToBytes(t2));
|
||||||
|
t4 = keccak.extractLast20Bytes(t3);
|
||||||
|
return "0x" + t4;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ethAddressFromCompressedPublicKey = floEthereum.ethAddressFromCompressedPublicKey = function (compressedPublicKey) {
|
||||||
|
var t1, t2, t3, t4;
|
||||||
|
t1 = coinjs.compressedToUncompressed(compressedPublicKey);
|
||||||
|
t2 = t1.slice(2);
|
||||||
|
t3 = keccak.keccak_256(Crypto.util.hexToBytes(t2));
|
||||||
|
t4 = keccak.extractLast20Bytes(t3);
|
||||||
|
return "0x" + t4;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ethPrivateKeyFromUntweakedPrivateKey = floEthereum.ethPrivateKeyFromUntweakedPrivateKey = function (untweakedPrivateKey) {
|
||||||
|
var t1;
|
||||||
|
t1 = hex.encode(taproot.taprootTweakPrivKey(hex.decode(untweakedPrivateKey)));
|
||||||
|
return t1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ethAddressFromUntweakedPrivateKey = floEthereum.ethAddressFromUntweakedPrivateKey = function (untweakedPrivateKey) {
|
||||||
|
var t1, t2;
|
||||||
|
t1 = hex.encode(taproot.taprootTweakPrivKey(hex.decode(untweakedPrivateKey)));
|
||||||
|
t2 = ethAddressFromPrivateKey(t1);
|
||||||
|
return t2;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ethAddressFromTaprootAddress = floEthereum.ethAddressFromTaprootAddress = function (taprootAddress) {
|
||||||
|
var t1, t2, t3, t4;
|
||||||
|
t1 = coinjs.addressDecode(taprootAddress);
|
||||||
|
t2 = t1.outstring.slice(4);
|
||||||
|
t3 = "02" + t2;
|
||||||
|
t4 = ethAddressFromCompressedPublicKey(t3);
|
||||||
|
return t4;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
})('object' === typeof module ? module.exports : window.floEthereum = {});
|
||||||
1
arbitrumwallet/scripts/floEthereum.min.js
vendored
Normal file
1
arbitrumwallet/scripts/floEthereum.min.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
!function(EXPORTS){"use strict";const floEthereum="object"===typeof module?module.exports:window.floEthereum={},ethAddressFromPrivateKey=floEthereum.ethAddressFromPrivateKey=function(privateKey,onlyEvenY=!1){var t1,t1_x,t1_y,t1_y_BigInt,t2,t3,groupOrder=BigInt("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F");return t1_x=(t1=bitjs.newPubkey(privateKey)).slice(2,66),t1_y=t1.slice(-64),onlyEvenY&&(t1_y_BigInt=BigInt("0x"+t1_y))%2n!==0n&&(t1_y=(t1_y_BigInt=(groupOrder-t1_y_BigInt)%groupOrder).toString(16)),t2=t1_x.toString(16)+t1_y.toString(16),t3=keccak.keccak_256(Crypto.util.hexToBytes(t2)),"0x"+keccak.extractLast20Bytes(t3)},ethAddressFromCompressedPublicKey=floEthereum.ethAddressFromCompressedPublicKey=function(compressedPublicKey){var t2,t3;return t2=coinjs.compressedToUncompressed(compressedPublicKey).slice(2),t3=keccak.keccak_256(Crypto.util.hexToBytes(t2)),"0x"+keccak.extractLast20Bytes(t3)};floEthereum.ethPrivateKeyFromUntweakedPrivateKey=function(untweakedPrivateKey){return hex.encode(taproot.taprootTweakPrivKey(hex.decode(untweakedPrivateKey)))},floEthereum.ethAddressFromUntweakedPrivateKey=function(untweakedPrivateKey){var t1;return t1=hex.encode(taproot.taprootTweakPrivKey(hex.decode(untweakedPrivateKey))),ethAddressFromPrivateKey(t1)},floEthereum.ethAddressFromTaprootAddress=function(taprootAddress){var t2;return t2=coinjs.addressDecode(taprootAddress).outstring.slice(4),ethAddressFromCompressedPublicKey("02"+t2)}}();
|
||||||
674
arbitrumwallet/scripts/keccak.js
Normal file
674
arbitrumwallet/scripts/keccak.js
Normal file
@ -0,0 +1,674 @@
|
|||||||
|
(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.keccak = window.keccak || {}) : {};
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var isArray = root.JS_SHA3_NO_NODE_JS || !Array.isArray
|
||||||
|
? function (obj) {
|
||||||
|
return Object.prototype.toString.call(obj) === '[object Array]';
|
||||||
|
}
|
||||||
|
: Array.isArray;
|
||||||
|
|
||||||
|
var isView = (ARRAY_BUFFER && (root.JS_SHA3_NO_ARRAY_BUFFER_IS_VIEW || !ArrayBuffer.isView))
|
||||||
|
? function (obj) {
|
||||||
|
return typeof obj === 'object' && obj.buffer && obj.buffer.constructor === ArrayBuffer;
|
||||||
|
}
|
||||||
|
: ArrayBuffer.isView;
|
||||||
|
|
||||||
|
// [message: string, isString: bool]
|
||||||
|
var formatMessage = function (message) {
|
||||||
|
var type = typeof message;
|
||||||
|
if (type === 'string') {
|
||||||
|
return [message, true];
|
||||||
|
}
|
||||||
|
if (type !== 'object' || message === null) {
|
||||||
|
throw new Error(INPUT_ERROR);
|
||||||
|
}
|
||||||
|
if (ARRAY_BUFFER && message.constructor === ArrayBuffer) {
|
||||||
|
return [new Uint8Array(message), false];
|
||||||
|
}
|
||||||
|
if (!isArray(message) && !isView(message)) {
|
||||||
|
throw new Error(INPUT_ERROR);
|
||||||
|
}
|
||||||
|
return [message, false];
|
||||||
|
}
|
||||||
|
|
||||||
|
var empty = function (message) {
|
||||||
|
return formatMessage(message)[0].length === 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
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 (empty(n) && empty(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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
methodNames.push("extractLast20Bytes");
|
||||||
|
methods["extractLast20Bytes"] = extractLast20Bytes;
|
||||||
|
|
||||||
|
|
||||||
|
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 result = formatMessage(message);
|
||||||
|
message = result[0];
|
||||||
|
var isString = result[1];
|
||||||
|
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 (isString) {
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (i = this.start; index < length && i < byteCount; ++index) {
|
||||||
|
blocks[i >> 2] |= message[index] << 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 result = formatMessage(str);
|
||||||
|
str = result[0];
|
||||||
|
var isString = result[1];
|
||||||
|
var bytes = 0, length = str.length;
|
||||||
|
if (isString) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bytes = length;
|
||||||
|
}
|
||||||
|
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) % 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];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function extractLast20Bytes(hexString, addPrefix) {
|
||||||
|
// Ensure the input hexString has '0x' prefix
|
||||||
|
if (!hexString.startsWith('0x')) {
|
||||||
|
hexString = '0x' + hexString;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove '0x' prefix and parse the hex string to a BigInt
|
||||||
|
var bigIntValue = BigInt(hexString);
|
||||||
|
|
||||||
|
// Extract the last 20 bytes (160 bits) from the BigInt
|
||||||
|
var last20Bytes = bigIntValue & BigInt('0x' + 'f'.repeat(40)); // 0xf is 4 bits in hexadecimal, repeated 40 times for 160 bits
|
||||||
|
|
||||||
|
// Convert the result back to a hexadecimal string
|
||||||
|
var result = last20Bytes.toString(16).padStart(40, '0'); // 40 characters for 160 bits
|
||||||
|
|
||||||
|
// Add '0x' prefix if addPrefix is truthy
|
||||||
|
if (addPrefix) {
|
||||||
|
result = '0x' + result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof root.keccak === 'object') {
|
||||||
|
Object.assign(root.keccak, methods);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
8428
arbitrumwallet/scripts/tap_combined.js
Normal file
8428
arbitrumwallet/scripts/tap_combined.js
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user