327 lines
13 KiB
HTML
327 lines
13 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|
<title>Handling Cash Payments For Localbitcoinplusplus</title>
|
|
</head>
|
|
<body>
|
|
|
|
<script>
|
|
|
|
(function payments_handler() {
|
|
|
|
|
|
/* CODE_JUNCTION: Indexed DB */
|
|
|
|
//prefixes of implementation that we want to test
|
|
const indexedDB = window.indexedDB || window.mozIndexedDB ||
|
|
window.webkitIndexedDB || window.msIndexedDB;
|
|
|
|
//prefixes of window.IDB objects
|
|
const IDBTransaction = window.IDBTransaction ||
|
|
window.webkitIDBTransaction || window.msIDBTransaction;
|
|
|
|
const IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange ||
|
|
window.msIDBKeyRange
|
|
|
|
if (!indexedDB) {
|
|
alert("Your browser doesn't support a stable version of IndexedDB.")
|
|
}
|
|
|
|
let db;
|
|
const DBName = "paymentsHandlerDB";
|
|
const request = window.indexedDB.open(DBName, 1);
|
|
|
|
request.onerror = function (event) {
|
|
//https://stackoverflow.com/questions/13972385/invalidstateerror-while-opening-indexeddb-in-firefox
|
|
event.preventDefault();
|
|
var error = event.target.error;
|
|
console.log("IndexedDB database open error:", error.name, error.message);
|
|
};
|
|
|
|
request.onsuccess = function (event) {
|
|
db = request.result;
|
|
};
|
|
|
|
request.onupgradeneeded = function (event) {
|
|
const db = event.target.result;
|
|
if (!db.objectStoreNames.contains('paymentsHandlerDetails')) {
|
|
var objectStore = db.createObjectStore("paymentsHandlerDetails", {
|
|
keyPath: "id"
|
|
});
|
|
objectStore.createIndex('myLocalFLOAddress', 'myLocalFLOAddress', {
|
|
unique: true
|
|
});
|
|
objectStore.put({
|
|
myLocalFLOPublicKey: "",
|
|
upiID: "",
|
|
last_tx_time: "",
|
|
last_active_time: ""
|
|
});
|
|
}
|
|
if (!db.objectStoreNames.contains('cash_deposits')) {
|
|
var objectStore = db.createObjectStore("deposits", {
|
|
keyPath: 'id'
|
|
});
|
|
objectStore.createIndex('trader_supernode', 'trader_supernode', {
|
|
unique: false
|
|
});
|
|
objectStore.createIndex('trader_flo_address', 'trader_flo_address', {
|
|
unique: false
|
|
});
|
|
objectStore.createIndex('currency', 'currency', {
|
|
unique: false
|
|
});
|
|
objectStore.createIndex('amount', 'amount', {
|
|
unique: false
|
|
});
|
|
}
|
|
if (!db.objectStoreNames.contains('cash_withdraws')) {
|
|
var objectStore = db.createObjectStore("withdraws", {
|
|
keyPath: 'id'
|
|
});
|
|
objectStore.createIndex('trader_supernode', 'trader_supernode', {
|
|
unique: false
|
|
});
|
|
objectStore.createIndex('trader_flo_address', 'trader_flo_address', {
|
|
unique: false
|
|
});
|
|
objectStore.createIndex('currency', 'currency', {
|
|
unique: false
|
|
});
|
|
objectStore.createIndex('amount', 'amount', {
|
|
unique: false
|
|
});
|
|
}
|
|
if (!db.objectStoreNames.contains('supernodesList')) {
|
|
var objectStore = db.createObjectStore("supernodesList", {
|
|
keyPath: 'id'
|
|
});
|
|
objectStore.createIndex('trader_flo_address', 'trader_flo_address', {
|
|
unique: true
|
|
});
|
|
objectStore.createIndex('ip', 'ip', {
|
|
unique: false
|
|
});
|
|
}
|
|
|
|
}
|
|
|
|
function readDB(tablename, id) {
|
|
return new Promise((resolve, reject) => {
|
|
var transaction = db.transaction([tablename]);
|
|
var objectStore = transaction.objectStore(tablename);
|
|
var request = objectStore.get(id);
|
|
|
|
request.onerror = function (event) {
|
|
reject("Unable to retrieve data from database!");
|
|
};
|
|
|
|
request.onsuccess = function (event) {
|
|
if (request.result) {
|
|
resolve(request.result);
|
|
} else {
|
|
resolve();
|
|
}
|
|
};
|
|
});
|
|
}
|
|
|
|
function readDBbyIndex(tablename, index, indexValue) {
|
|
return new Promise((resolve, reject) => {
|
|
var transaction = db.transaction([tablename]);
|
|
var objectStore = transaction.objectStore(tablename);
|
|
let response = [];
|
|
objectStore.openCursor().onerror = function (event) {
|
|
console.error("Error fetching data");
|
|
reject(event);
|
|
};
|
|
objectStore.openCursor().onsuccess = function (event) {
|
|
let cursor = event.target.result;
|
|
if (cursor) {
|
|
if (cursor.value[index] == indexValue) {
|
|
response.push(cursor.value);
|
|
}
|
|
cursor.continue();
|
|
} else {
|
|
resolve(response);
|
|
}
|
|
};
|
|
});
|
|
}
|
|
|
|
function readAllDB(tablename, limit=0) {
|
|
return new Promise((resolve, reject) => {
|
|
let response = [];
|
|
var objectStore = db.transaction(tablename).objectStore(tablename);
|
|
objectStore.openCursor().onsuccess = function (event) {
|
|
let cursor = event.target.result;
|
|
if (cursor) {
|
|
response.push(cursor.value);
|
|
cursor.continue();
|
|
} else {
|
|
resolve(response);
|
|
}
|
|
};
|
|
});
|
|
}
|
|
|
|
async function addDB(tablename, dbObject) {
|
|
try {
|
|
if(typeof dbObject.vectorClock == "undefined") dbObject.vectorClock = 0;
|
|
dbObject.timestamp = + new Date();
|
|
let request = db.transaction([tablename], "readwrite")
|
|
let store = request.objectStore(tablename)
|
|
await store.add(dbObject);
|
|
await request.complete;
|
|
console.info("Data added in " + tablename);
|
|
return dbObject;
|
|
} catch (error) {
|
|
return new Error(error);
|
|
}
|
|
}
|
|
|
|
async function updateinDB(tablename, Obj, key, updateByVectorClock=false, increaseVectorClock=true) {
|
|
// updateByVectorClock==true will not return Obj back.
|
|
// Return value will be undefined
|
|
try {
|
|
if(typeof Obj.vectorClock == "undefined") {
|
|
Obj.vectorClock = 0;
|
|
} else if(increaseVectorClock === false) {
|
|
// leave the vector clock field unchanged
|
|
} else {
|
|
Obj.vectorClock += 1;
|
|
}
|
|
if (typeof Obj.timestamp !== "number") {
|
|
Obj.timestamp = + new Date();
|
|
}
|
|
var request = db.transaction([tablename], "readwrite")
|
|
let store = request.objectStore(tablename)
|
|
if (updateByVectorClock===true) {
|
|
if (typeof key=="undefined") {
|
|
key = Obj[store.keyPath];
|
|
}
|
|
let objectStoreRequest = store.get(key);
|
|
objectStoreRequest.onsuccess =
|
|
async function(event) {
|
|
var myRecord = objectStoreRequest.result;
|
|
if(typeof myRecord !=="object") {
|
|
Obj.vectorClock = 1;
|
|
await store.put(Obj);
|
|
await request.complete;
|
|
} else if (myRecord.vectorClock+1 < Obj.vectorClock) {
|
|
await store.put(Obj);
|
|
await request.complete;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
await store.put(Obj);
|
|
await request.complete;
|
|
}
|
|
return Obj;
|
|
|
|
} catch (error) {
|
|
return new Error(error);
|
|
}
|
|
}
|
|
|
|
async function removeinDB(tablename, id) {
|
|
try {
|
|
var request = db.transaction([tablename], "readwrite")
|
|
let store = request.objectStore(tablename)
|
|
await store.delete(id);
|
|
await request.complete;
|
|
return id;
|
|
} catch (error) {
|
|
return new Error(error);
|
|
}
|
|
}
|
|
|
|
function removeByIndex(tablename, indexName, indexValue) {
|
|
return new Promise((resolve, reject) => {
|
|
var request = db.transaction([tablename], "readwrite")
|
|
.objectStore(tablename);
|
|
var index = request.index(indexName);
|
|
var request = index.openCursor(IDBKeyRange.only(indexValue));
|
|
request.onsuccess = function () {
|
|
var cursor = request.result;
|
|
if (cursor) {
|
|
cursor.delete();
|
|
cursor.continue();
|
|
} else {
|
|
resolve(true);
|
|
}
|
|
};
|
|
request.onerror = function (e) {
|
|
reject(e);
|
|
}
|
|
})
|
|
}
|
|
|
|
async function removeAllinDB(tablename) {
|
|
try {
|
|
var request = db.transaction([tablename], "readwrite")
|
|
var objectStore = request.objectStore(tablename);
|
|
var objectStoreRequest = await objectStore.clear();
|
|
await request.complete;
|
|
console.info("All the data entry has been removed from your database " + tablename);
|
|
return tablename;
|
|
} catch (error) {
|
|
return new Error(error);
|
|
}
|
|
}
|
|
|
|
/* CODE_JUNCTION: Websockets */
|
|
|
|
function startWebSocket(wsUri) {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
websocket = new WebSocket(wsUri);
|
|
websocket.onopen = function (evt) {
|
|
resolve(onOpen(evt))
|
|
};
|
|
websocket.onclose = function (evt) {
|
|
reject(onClose(evt))
|
|
};
|
|
websocket.onmessage = function (evt) {
|
|
resolve(onMessage(evt))
|
|
};
|
|
websocket.onerror = function (evt) {
|
|
reject(onError(evt))
|
|
};
|
|
})
|
|
}
|
|
|
|
function onOpen(evt) {
|
|
console.info(`INFO: Connected succesfully to ${evt.srcElement.url}.`)
|
|
}
|
|
|
|
function onClose(event) {
|
|
if (event.wasClean) {
|
|
console.info(`[close] Connection to ${event.srcElement.url} closed cleanly, code=${event.code} reason=${event.reason}`);
|
|
} else {
|
|
// e.g. server process killed or network down
|
|
// event.code is usually 1006 in this case
|
|
console.warn(`[close] Connection to ${event.srcElement.url} died unexpectedly, code=${event.code} reason=${event.reason}`);
|
|
}
|
|
}
|
|
|
|
function onMessage(evt) {
|
|
console.log(evt);
|
|
}
|
|
|
|
function onError(evt) {
|
|
console.error(`ERROR: Websocket Connection to ${evt.srcElement.url} returned error.`);
|
|
}
|
|
|
|
})();
|
|
|
|
|
|
|
|
</script>
|
|
|
|
</body>
|
|
</html> |