app.js
1 import { config, readConfigs } from './configParser.js' 2 import Kefir from 'kefir' 3 import express from 'express' 4 import cors from 'cors' 5 import path from 'path' 6 import { Server } from 'socket.io' 7 import socketProtector from './safetySocks.js' 8 import chalk from 'chalk' 9 10 import dctrlDb from './dctrlDb.js' 11 import state from './state.js' 12 import reactions from './reactions.js' 13 import auth from './auth.js' 14 import exchangeRate from './exchangeRate.js' 15 import rent from './rent.js' 16 import link from './link.js' 17 import lightning from './lightning.js' 18 import applyRouter from './router.js' 19 //import connector from './connector.js' 20 21 // Okay, what's happening here in callback hell!? 22 // 23 // First, we load the config as defined mostly 24 // in the .ao directory - see configParser 25 // 26 // Next, we apply the router as defined in 27 // 'router.js', which defines some post endpoints 28 // and redirects all GET to the index.html 29 // 30 // Finally, we begin the complex process of 31 // "starting the AO". 32 // 33 // "Starting the AO" first consists of establishing 34 // a connection to the database and reading all of 35 // the logged events to generate the current 36 // application state. 37 // 38 // Afterwards, a few plugins are loaded and then 39 // the db is set up to listen for changes and 40 // apply them to the application state. 41 // 42 // The last step is configuring the server to 43 // listen on the given port (default 8003) and 44 // accept websocket connections. 45 // 46 // Whenever an event is received from the changefeed 47 // (or shadowfeed?), it is both applied to the application 48 // state and sent to all clients via websocket. Finally, 49 // it is sent to the 'reactions' library to see if anything 50 // needs to be done in response to this particular event: 51 // doors opened, payments processed etc. 52 53 54 // ~ Reimplementation with nostr relays ~ 55 // 56 // Read the config. Apply the router. 57 // 58 // For the AO itself, all data will be stored 59 // on the relay. The AO server will maintain 60 // application state, listen for changes from 61 // the relay and process / verify any reactions 62 // 63 // Relay will manage event propagation and clients 64 // will open up a socket directly to the relay 65 // instead of to the AO. A request can be made 66 // to SOLAR for logging in, returning the nsec 67 // to be used for signing, etc. 68 69 70 71 readConfigs(() => { 72 const app = express() 73 app.use(cors()) 74 75 applyRouter(app) 76 startDctrlAo() 77 78 function startDctrlAo(){ 79 dctrlDb.startDb( (err, conn) => { 80 if (err) return console.log(chalk.bold.red('db initialize failed:', err)) 81 82 let start = Date.now() 83 state.initialize( err => { 84 if (err) return console.log(chalk.bold.red('ao state initialization failed:'), err) 85 exchangeRate.watchSpot() 86 lightning.initClient(config) 87 lightning.stormWallet() 88 lightning.recordEveryInvoice(state.serverState.cash.pay_index) 89 lightning.watchOnChain() 90 // rent() 91 // link() 92 93 dctrlDb.changeFeed 94 .onValue( ev => state.applyEvent(state.serverState, ev)) 95 96 /* 97 TODO: The next major change to AO-Z is building it to work with 98 nostr relays. Initially, these means using a relay as the database. 99 The complexity of AO having hardware/lightning interactions means 100 that we will need to maintain a "server". 101 102 futr2 works alright, but strfry is a much better maintained system 103 written in a more robust language. 104 */ 105 106 const server = app.listen(config.port, err => { 107 console.log(chalk.blue.bold("http://localhost:" + config.port)) 108 const io = new Server(server, { 109 cors: { 110 // Only really needed for dev 111 origin: '*' 112 } 113 }) 114 socketProtector(io, { 115 authenticate: auth.socketAuth, 116 timeout: 2345, 117 }) 118 Kefir.merge([ 119 dctrlDb.changeFeed.map(state.removeSensitive), 120 dctrlDb.shadowFeed 121 ]).onValue( ev => { 122 state.applyEvent(state.pubState, ev) 123 io.emit('eventstream', ev) 124 console.log("def happened:", ev) 125 }).onValue(reactions) 126 }) 127 }) 128 }) 129 } 130 }) 131 132 export default readConfigs