Browse Source

missing files

qdn-metadata
AlphaX-Projects 3 years ago committed by GitHub
parent
commit
e9cb8a5be8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 101
      qortal-ui-plugins/plugins/core/streams/AddressWatcher.js
  2. 65
      qortal-ui-plugins/plugins/core/streams/UnconfirmedTransactionWatcher.js
  3. 336
      qortal-ui-plugins/plugins/core/streams/onNewBlock.js
  4. 241
      qortal-ui-plugins/plugins/core/streams/streams.js

101
qortal-ui-plugins/plugins/core/streams/AddressWatcher.js

@ -0,0 +1,101 @@
import { parentEpml } from '../connect.js'
// Tests to see if a block or transaction should trigger an address reload...but we're not doing that yet, because of no time for good testing
const transactionTests = []
const blockTests = []
const DEFAULT_ADDRESS_INFO = {}
transactionTests.push((tx, addr) => {
return tx.recipient === addr || tx.sender === addr
})
blockTests.push((block, addr) => {
return block.generator === addr
})
export class AddressWatcher {
constructor (addresses) {
addresses = addresses || []
this.reset()
addresses.forEach(addr => this.addAddress(addr))
}
reset () {
this._addresses = {}
this._addressStreams = {}
}
// Adds an address to watch
addAddress (address) {
const addr = address.address
this._addresses[addr] = address
this._addressStreams[addr] = new EpmlStream(`address/${addr}`, () => this._addresses[addr])
this.updateAddress(addr)
}
async testBlock (block) {
// console.log('TESTING BLOCK')
const pendingUpdateAddresses = []
// blockTests.forEach(fn => {
// })
// transactionTests.forEach(fn => {
//
const transactions = await parentEpml.request('apiCall', { url: `/transactions/block/${block.signature}` })
transactions.forEach(transaction => {
// console.log(this)
// fn(transaction, Object.keys(this._addresses))
// Guess the block needs transactions
for (const addr of Object.keys(this._addresses)) {
// const addrChanged = transactionTests.some(fn => {
// return fn(transaction, addr)
// })
// console.log('checking ' + addr)
const addrChanged = true // Just update it every block...for now
if (!addrChanged) return
if (!(addr in pendingUpdateAddresses)) pendingUpdateAddresses.push(addr)
/**
* In the future transactions are potentially stored from here...and address is updated excluding transactions...and also somehow manage tx pages...
* Probably will just make wallet etc. listen for address change and then do the api call itself. If tx. page is on, say, page 3...and there's a new transaction...
* it will refresh, changing the "page" to have 1 extra transaction at the top and losing 1 at the bottom (pushed to next page)
*/
}
})
pendingUpdateAddresses.forEach(addr => this.updateAddress(addr))
}
async updateAddress (addr) {
// console.log('UPPPDDAAATTTINGGG AADDDRRR', addr)
let addressRequest = await parentEpml.request('apiCall', {
type: 'explorer',
data: {
addr: addr,
txOnPage: 10
}
})
// addressRequest = JSON.parse(addressRequest)
// console.log(addressRequest, 'AAADDDREESS REQQUEESTT')
// console.log('response: ', addressRequest)
const addressInfo = addressRequest.success ? addressRequest.data : DEFAULT_ADDRESS_INFO
// const addressInfo = addressRequest.success ? addressRequest.data : DEFAULT_ADDRESS_INFO
addressInfo.transactions = []
for (let i = addressInfo.start; i >= addressInfo.end; i--) {
addressInfo.transactions.push(addressInfo[i])
delete addressInfo[i]
}
// console.log('ADDRESS INFO', addressInfo)
if (!(addr in this._addresses)) return
this._addresses[addr] = addressInfo
// console.log('---------------------------Emitting-----------------------------', this._addresses[addr], this._addressStreams[addr])
this._addressStreams[addr].emit(addressInfo)
}
}

65
qortal-ui-plugins/plugins/core/streams/UnconfirmedTransactionWatcher.js

@ -0,0 +1,65 @@
import { parentEpml } from '../connect.js'
// import { EpmlStream } from 'epml' maybe not needed...loaded for me
export class UnconfirmedTransactionWatcher {
constructor () {
this._unconfirmedTransactionStreams = {}
this.reset() // Sets defaults
setInterval(() => {
Object.entries(this._addresses).forEach((addr) => this._addressTransactionCheck(addr[0]))
}, 10 * 1000)
}
reset () {
this._addresses = {}
this._addressesUnconfirmedTransactions = {}
}
// Adds an address to watch
addAddress (address) {
// console.log("Added address", address)
const addr = address.address
this._addresses[addr] = address
this._addressesUnconfirmedTransactions[addr] = []
if (this._unconfirmedTransactionStreams[addr]) return
// console.log("CREATING A STRTRREEAAAMMMM")
this._unconfirmedTransactionStreams[addr] = new EpmlStream(`unconfirmedOfAddress/${addr}`, () => this._addressesUnconfirmedTransactions[addr])
// this.updateAddress(address.address)
}
check () {
// console.log("checkin for unconfirmed")
const c = this._addressTransactionCheck()
.then(() => setTimeout(() => this.check(), 5000))
.catch(() => setTimeout(() => this.check(), 5000))
// console.log(c)
}
async _addressTransactionCheck () {
// console.log("Checking for unconfirmed transactions")
// console.log(this._addresses, Object.keys(this._addresses))
return Promise.all(Object.keys(this._addresses).map(addr => {
// console.log(`checking ${addr}`)
return parentEpml.request('apiCall', {
type: 'api',
// url: `transactions/unconfirmedof/${addr}`
url: `/transactions/unconfirmed`
}).then(unconfirmedTransactions => {
// unconfirmedTransactions = JSON.parse(unconfirmedTransactions)
// console.log(unconfirmedTransactions)
unconfirmedTransactions.filter(tx => {
tx.creatorAddress === addr || tx.recipient === addr
})
// console.log(unconfirmedTransactions, unconfirmedTransactions.length)
// if(unconfirmedTransactions.length === 0) {
// return
// }
this._unconfirmedTransactionStreams[addr].emit(unconfirmedTransactions)
// console.log(this._unconfirmedTransactionStreams[addr])
})
}))
}
}

336
qortal-ui-plugins/plugins/core/streams/onNewBlock.js

@ -0,0 +1,336 @@
import { parentEpml } from '../connect.js'
let socketObject
let activeBlockSocketTimeout
let initial = 0
let closeGracefully = false
let isCalled = false
let retryOnClose = false
let blockFirstCall = true
let nodeStatusSocketObject
let nodeStatusSocketTimeout
let nodeStatusSocketcloseGracefully = false
let nodeStatusCount = 0
let nodeStatusRetryOnClose = false
let nodeStateCall = false
let isLoggedIn = false
let oldAccountInfo
parentEpml.subscribe('logged_in', loggedIn => {
if (loggedIn === 'true') {
isLoggedIn = true
} else {
isLoggedIn = false
}
})
const setAccountInfo = async (addr) => {
const names = await parentEpml.request('apiCall', {
url: `/names/address/${addr}`
})
const addressInfo = await parentEpml.request('apiCall', {
url: `/addresses/${addr}`
})
let accountInfo = {
names: names,
addressInfo: addressInfo
}
if (window.parent._.isEqual(oldAccountInfo, accountInfo) === true) {
return
} else {
parentEpml.request('setAccountInfo', accountInfo)
oldAccountInfo = accountInfo
}
}
const doNodeInfo = async () => {
const nodeInfo = await parentEpml.request('apiCall', {
url: '/admin/info'
})
parentEpml.request('updateNodeInfo', nodeInfo)
}
let initStateCount = 0
let oldState
const closeSockets = () => {
socketObject.close();
closeGracefully = true
nodeStatusSocketObject.close();
nodeStatusSocketcloseGracefully = true
}
export const startConfigWatcher = () => {
parentEpml.ready().then(() => {
parentEpml.subscribe('node_config', c => {
if (initStateCount === 0) {
let _oldState = JSON.parse(c)
oldState = { node: _oldState.node, knownNodes: _oldState.knownNodes }
initStateCount = initStateCount + 1
nodeStateCall = true
isCalled = true
socketObject !== undefined ? closeSockets() : undefined;
nodeStatusSocketObject !== undefined ? closeSockets() : undefined;
initNodeStatusCall(oldState)
pingactiveBlockSocket()
// Call doNodeInfo
doNodeInfo()
}
let _newState = JSON.parse(c);
let newState = { node: _newState.node, knownNodes: _newState.knownNodes }
if (window.parent._.isEqual(oldState, newState) === true) {
return
} else {
oldState = newState
nodeStateCall = true
isCalled = true
socketObject !== undefined ? closeSockets() : undefined;
nodeStatusSocketObject !== undefined ? closeSockets() : undefined;
initNodeStatusCall(newState)
pingactiveBlockSocket()
// Call doNodeInfo
doNodeInfo()
}
})
})
parentEpml.imReady()
}
const processBlock = (blockObject) => {
parentEpml.request('updateBlockInfo', blockObject)
}
const doNodeStatus = async (nodeStatusObject) => {
parentEpml.request('updateNodeStatus', nodeStatusObject)
}
const initNodeStatusCall = (nodeConfig) => {
if (nodeConfig.node == 0) {
pingNodeStatusSocket()
} else if (nodeConfig.node == 1) {
pingNodeStatusSocket()
} else if (nodeStatusSocketObject !== undefined) {
nodeStatusSocketObject.close()
nodeStatusSocketcloseGracefully = true
} else {
// ...
}
}
const initBlockSocket = () => {
let myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
let nodeUrl = myNode.domain + ":" + myNode.port
let activeBlockSocketLink
if (window.parent.location.protocol === "https:") {
activeBlockSocketLink = `wss://${nodeUrl}/websockets/blocks`;
} else {
activeBlockSocketLink = `ws://${nodeUrl}/websockets/blocks`;
}
const activeBlockSocket = new WebSocket(activeBlockSocketLink);
// Open Connection
activeBlockSocket.onopen = (e) => {
console.log(`[SOCKET-BLOCKS]: Connected.`);
closeGracefully = false
socketObject = activeBlockSocket
initial = initial + 1
}
// Message Event
activeBlockSocket.onmessage = (e) => {
processBlock(JSON.parse(e.data));
if (isLoggedIn) {
// Call Set Account Info...
setAccountInfo(window.parent.reduxStore.getState().app.selectedAddress.address)
}
}
// Closed Event
activeBlockSocket.onclose = () => {
console.log(`[SOCKET-BLOCKS]: CLOSED`);
processBlock({});
blockFirstCall = true
clearInterval(activeBlockSocketTimeout)
if (closeGracefully === false && initial <= 52) {
if (initial <= 52) {
retryOnClose = true
setTimeout(pingactiveBlockSocket, 10000)
initial = initial + 1
} else {
// ... Stop retrying...
retryOnClose = false
}
}
}
// Error Event
activeBlockSocket.onerror = (e) => {
console.log(`[SOCKET-BLOCKS]: ${e.type}`);
blockFirstCall = true
processBlock({});
}
if (blockFirstCall) {
parentEpml.request('apiCall', {
url: '/blocks/last'
}).then(res => {
processBlock(res)
blockFirstCall = false
})
}
}
const pingactiveBlockSocket = () => {
if (isCalled) {
isCalled = false
initBlockSocket()
activeBlockSocketTimeout = setTimeout(pingactiveBlockSocket, 295000)
} else if (retryOnClose) {
retryOnClose = false
clearTimeout(activeBlockSocketTimeout)
initBlockSocket()
isCalled = true
activeBlockSocketTimeout = setTimeout(pingactiveBlockSocket, 295000)
} else {
socketObject.send("non-integer ping")
activeBlockSocketTimeout = setTimeout(pingactiveBlockSocket, 295000)
}
}
const initNodeStatusSocket = () => {
let myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
let nodeUrl = myNode.domain + ":" + myNode.port
let activeNodeStatusSocketLink
if (window.parent.location.protocol === "https:") {
activeNodeStatusSocketLink = `wss://${nodeUrl}/websockets/admin/status`;
} else {
activeNodeStatusSocketLink = `ws://${nodeUrl}/websockets/admin/status`;
}
const activeNodeStatusSocket = new WebSocket(activeNodeStatusSocketLink);
// Open Connection
activeNodeStatusSocket.onopen = (e) => {
console.log(`[SOCKET-NODE-STATUS]: Connected.`);
nodeStatusSocketcloseGracefully = false
nodeStatusSocketObject = activeNodeStatusSocket
nodeStatusCount = nodeStatusCount + 1
}
// Message Event
activeNodeStatusSocket.onmessage = (e) => {
doNodeStatus(JSON.parse(e.data))
}
// Closed Event
activeNodeStatusSocket.onclose = () => {
console.log(`[SOCKET-NODE-STATUS]: CLOSED`);
doNodeStatus({});
clearInterval(nodeStatusSocketTimeout)
if (nodeStatusSocketcloseGracefully === false && nodeStatusCount <= 52) {
if (nodeStatusCount <= 52) {
nodeStatusRetryOnClose = true
setTimeout(pingNodeStatusSocket, 10000)
nodeStatusCount = nodeStatusCount + 1
} else {
// ... Stop retrying...
nodeStatusRetryOnClose = false
}
}
}
// Error Event
activeNodeStatusSocket.onerror = (e) => {
console.log(`[SOCKET-NODE-STATUS]: ${e.type}`);
doNodeStatus({});
}
}
const pingNodeStatusSocket = () => {
if (nodeStateCall) {
clearTimeout(nodeStatusSocketTimeout)
initNodeStatusSocket()
nodeStateCall = false
nodeStatusSocketTimeout = setTimeout(pingNodeStatusSocket, 295000)
} else if (nodeStatusRetryOnClose) {
nodeStatusRetryOnClose = false
clearTimeout(nodeStatusSocketTimeout)
initNodeStatusSocket()
nodeStatusSocketTimeout = setTimeout(pingNodeStatusSocket, 295000)
} else {
nodeStatusSocketObject.send("non-integer ping")
nodeStatusSocketTimeout = setTimeout(pingNodeStatusSocket, 295000)
}
}

241
qortal-ui-plugins/plugins/core/streams/streams.js

@ -0,0 +1,241 @@
import { parentEpml } from '../connect.js'
import { startConfigWatcher } from './onNewBlock.js'
const setAccountInfo = async (addr) => {
const names = await parentEpml.request('apiCall', {
url: `/names/address/${addr}`
})
const addressInfo = await parentEpml.request('apiCall', {
url: `/addresses/${addr}`
})
let accountInfo = {
names: names,
addressInfo: addressInfo
}
parentEpml.request('setAccountInfo', accountInfo)
}
const objectToArray = (object) => {
let groupList = object.groups.map(group => group.groupId === 0 ? { groupId: group.groupId, url: `group/${group.groupId}`, groupName: "Qortal General Chat", sender: group.sender, senderName: group.senderName, timestamp: group.timestamp === undefined ? 1 : group.timestamp } : { ...group, url: `group/${group.groupId}` })
let directList = object.direct.map(dc => {
return { ...dc, url: `direct/${dc.address}` }
})
let chatHeadMasterList = [...groupList, ...directList]
return chatHeadMasterList
}
const sortActiveChat = (activeChatObject, localChatHeads) => {
let oldChatHeads = JSON.parse(localChatHeads)
if (window.parent._.isEqual(oldChatHeads, activeChatObject) === true) {
return
} else {
let oldActiveChats = objectToArray(oldChatHeads)
let newActiveChats = objectToArray(activeChatObject)
let results = newActiveChats.filter(newChat => {
let value = oldActiveChats.some(oldChat => newChat.timestamp === oldChat.timestamp)
return !value
});
results.forEach(chat => {
if (chat.sender !== window.parent.reduxStore.getState().app.selectedAddress.address) {
if (chat.sender !== undefined) parentEpml.request('showNotification', chat)
} else {
// ...
}
})
}
}
let initialChatWatch = 0
const chatHeadWatcher = (activeChats) => {
let addr = window.parent.reduxStore.getState().app.selectedAddress.address
let key = `${addr.substr(0, 10)}_chat-heads`
try {
let localChatHeads = localStorage.getItem(key)
if (localChatHeads === null) {
parentEpml.request('setLocalStorage', {
key: key,
dataObj: activeChats
}).then(ms => {
parentEpml.request('setChatHeads', activeChats).then(ret => {
// ...
})
})
} else {
parentEpml.request('setLocalStorage', {
key: key,
dataObj: activeChats
}).then(ms => {
parentEpml.request('setChatHeads', activeChats).then(ret => {
// ...
})
})
if (initialChatWatch >= 1) {
sortActiveChat(activeChats, localChatHeads)
} else {
initialChatWatch = initialChatWatch + 1
}
}
} catch (e) {
console.error(e)
}
}
let socketObject
let activeChatSocketTimeout
let initial = 0
let closeGracefully = false
let onceLoggedIn = false
let retryOnClose = false
let canPing = false
parentEpml.subscribe('logged_in', async isLoggedIn => {
const initChatHeadSocket = () => {
let myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
let nodeUrl = myNode.domain + ":" + myNode.port
let activeChatSocketLink
if (window.parent.location.protocol === "https:") {
activeChatSocketLink = `wss://${nodeUrl}/websockets/chat/active/${window.parent.reduxStore.getState().app.selectedAddress.address}`;
} else {
activeChatSocketLink = `ws://${nodeUrl}/websockets/chat/active/${window.parent.reduxStore.getState().app.selectedAddress.address}`;
}
const activeChatSocket = new WebSocket(activeChatSocketLink);
// Open Connection
activeChatSocket.onopen = () => {
console.log(`[SOCKET]: Connected.`);
socketObject = activeChatSocket
initial = initial + 1
canPing = true
}
// Message Event
activeChatSocket.onmessage = (e) => {
chatHeadWatcher(JSON.parse(e.data))
}
// Closed Event
activeChatSocket.onclose = () => {
console.log(`[SOCKET]: CLOSED`);
clearInterval(activeChatSocketTimeout)
if (closeGracefully === false && initial <= 52) {
if (initial <= 52) {
parentEpml.request('showSnackBar', "Connection to the Qortal Core was lost, is your Core running ?")
retryOnClose = true
setTimeout(pingActiveChatSocket, 10000)
initial = initial + 1
} else {
parentEpml.request('showSnackBar', "Cannot connect to the Qortal Core, restart UI and Core!")
}
}
}
// Error Event
activeChatSocket.onerror = (e) => {
console.log(`[SOCKET]: ${e.type}`);
}
}
const pingActiveChatSocket = () => {
if (window.parent.reduxStore.getState().app.loggedIn === true) {
if (!onceLoggedIn) {
initChatHeadSocket()
onceLoggedIn = true
activeChatSocketTimeout = setTimeout(pingActiveChatSocket, 295000)
} else if (retryOnClose) {
retryOnClose = false
clearTimeout(activeChatSocketTimeout)
initChatHeadSocket()
onceLoggedIn = true
activeChatSocketTimeout = setTimeout(pingActiveChatSocket, 295000)
} else if (canPing) {
socketObject.send('ping')
activeChatSocketTimeout = setTimeout(pingActiveChatSocket, 295000)
}
} else {
if (onceLoggedIn && !closeGracefully) {
closeGracefully = true
socketObject.close()
clearTimeout(activeChatSocketTimeout)
onceLoggedIn = false
canPing = false
}
}
}
if (isLoggedIn === 'true') {
// Call Set Account Info...
setAccountInfo(window.parent.reduxStore.getState().app.selectedAddress.address)
// Start Chat Watcher Socket
pingActiveChatSocket()
} else {
if (onceLoggedIn) {
closeGracefully = true
socketObject.close()
clearTimeout(activeChatSocketTimeout)
onceLoggedIn = false
canPing = false
}
initialChatWatch = 0
}
})
startConfigWatcher()
Loading…
Cancel
Save