UNPKG

@j0nnyboi/amman

Version:

A modern mandatory toolbelt to help test solana SDK libraries and apps on a locally running validator.

226 lines 10.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Relay = exports.RelayServer = void 0; const amman_client_1 = require("@j0nnyboi/amman-client"); const http_1 = require("http"); const socket_io_1 = require("socket.io"); const providers_1 = require("../accounts/providers"); const state_1 = require("../accounts/state"); const assets_1 = require("../assets"); const utils_1 = require("../utils"); const http_2 = require("../utils/http"); const handler_1 = require("./handler"); const rest_server_1 = require("./rest-server"); const { logDebug, logTrace } = (0, utils_1.scopedLog)('relay'); /** * A simple socket.io server which communicates to the Amman Explorere as well as accepting connections * from other clients, i.e. via an {@link AmmanClient} which tests can use to communicate via the amman API. * * @private */ class RelayServer { constructor(io, handler) { this.io = io; this.handler = handler; this.hookConnectionEvents(); } get accountStates() { return this.handler.accountStates; } hookConnectionEvents() { this.io.on('connection', (socket) => { const client = `${socket.id} from ${socket.client.conn.remoteAddress}`; socket.on('disconnect', () => logTrace(`socket.io ${client} disconnected`)); logTrace(`socket.io ${client} connected`); this.hookMessages(socket); }); } hookMessages(socket) { const subscribedAccountStates = new Set(); socket // ----------------- // Amman Version // ----------------- .on(amman_client_1.MSG_REQUEST_AMMAN_VERSION, () => { logTrace(amman_client_1.MSG_REQUEST_AMMAN_VERSION); const reply = this.handler.requestAmmanVersion(); socket.emit(amman_client_1.MSG_RESPOND_AMMAN_VERSION, reply); }) // ----------------- // Validator Pid // ----------------- .on(amman_client_1.MSG_REQUEST_VALIDATOR_PID, () => { logTrace(amman_client_1.MSG_REQUEST_VALIDATOR_PID); const reply = this.handler.requestValidatorPid(); socket.emit(amman_client_1.MSG_RESPOND_VALIDATOR_PID, reply); }) // ----------------- // Kill Amman // ----------------- .on(amman_client_1.MSG_REQUEST_KILL_AMMAN, async () => { logTrace(amman_client_1.MSG_REQUEST_KILL_AMMAN); const reply = await this.handler.requestKillAmman(); socket.emit(amman_client_1.MSG_RESPOND_KILL_AMMAN, reply); }) // ----------------- // Address Labels // ----------------- .on(amman_client_1.MSG_UPDATE_ADDRESS_LABELS, (reply) => { if (logTrace.enabled) { logTrace(amman_client_1.MSG_UPDATE_ADDRESS_LABELS); if ((0, amman_client_1.isReplyWithResult)(reply)) { const labelCount = Object.keys(reply.result.labels).length; logTrace(`Got ${labelCount} labels, broadcasting ...`); } else { (0, utils_1.logError)(reply.err); } } if ((0, amman_client_1.isReplyWithResult)(reply)) { this.handler.updateAddressLabels(reply.result.labels); } socket.broadcast.emit(amman_client_1.MSG_UPDATE_ADDRESS_LABELS, reply); socket.emit(amman_client_1.ACK_UPDATE_ADDRESS_LABELS); }) .on(amman_client_1.MSG_GET_KNOWN_ADDRESS_LABELS, () => { if (logTrace.enabled) { logTrace(amman_client_1.MSG_GET_KNOWN_ADDRESS_LABELS); const labelCount = Object.keys(this.handler.allKnownLabels).length; logTrace(`Sending ${labelCount} known labels to requesting client.`); } const reply = { result: { labels: this.handler.allKnownLabels }, }; socket.emit(amman_client_1.MSG_UPDATE_ADDRESS_LABELS, reply); }) // ----------------- // Restart Validator // ----------------- .on(amman_client_1.MSG_REQUEST_RESTART_VALIDATOR, async (label) => { logTrace(amman_client_1.MSG_REQUEST_RESTART_VALIDATOR, label); const reply = await this.handler.requestRestartValidator(); socket.emit(amman_client_1.MSG_RESPOND_RESTART_VALIDATOR, reply); }) // ----------------- // Account States // ----------------- .on(amman_client_1.MSG_REQUEST_ACCOUNT_STATES, (pubkeyArg) => { logTrace(amman_client_1.MSG_REQUEST_ACCOUNT_STATES, pubkeyArg); const reply = this.handler.requestAccountStates(pubkeyArg); if ((0, amman_client_1.isReplyWithResult)(reply)) { const { pubkey } = reply.result; if (!subscribedAccountStates.has(pubkey)) { subscribedAccountStates.add(pubkey); this.handler.accountStates.on(`account-changed:${pubkey}`, (states) => { const reply = { result: { pubkey, states, }, }; socket.emit(amman_client_1.MSG_UPDATE_ACCOUNT_STATES, reply); logTrace(amman_client_1.MSG_UPDATE_ACCOUNT_STATES); }); } } socket.emit(amman_client_1.MSG_RESPOND_ACCOUNT_STATES, reply); }) // ----------------- // Save Account // ----------------- .on(amman_client_1.MSG_REQUEST_ACCOUNT_SAVE, async (pubkeyArg, slot) => { logTrace(amman_client_1.MSG_REQUEST_ACCOUNT_SAVE, pubkeyArg); const reply = await this.handler.requestAccountSave(pubkeyArg, slot); socket.emit(amman_client_1.MSG_RESPOND_ACCOUNT_SAVE, reply); }) // ----------------- // Snapshot // ----------------- .on(amman_client_1.MSG_REQUEST_SNAPSHOT_SAVE, async (label) => { logTrace(amman_client_1.MSG_REQUEST_SNAPSHOT_SAVE, label); const reply = await this.handler.requestSnapshotSave(label); socket.emit(amman_client_1.MSG_RESPOND_SNAPSHOT_SAVE, reply); }) .on(amman_client_1.MSG_REQUEST_LOAD_SNAPSHOT, async (label) => { logTrace(amman_client_1.MSG_REQUEST_LOAD_SNAPSHOT, label); const reply = await this.handler.requestLoadSnapshot(label); socket.emit(amman_client_1.MSG_RESPOND_LOAD_SNAPSHOT, reply); }) // ----------------- // Keypair // ----------------- .on(amman_client_1.MSG_REQUEST_STORE_KEYPAIR, (id, secretKey) => { logTrace(amman_client_1.MSG_REQUEST_STORE_KEYPAIR, id); const reply = this.handler.requestStoreKeypair(id, secretKey); socket.emit(amman_client_1.MSG_RESPOND_STORE_KEYPAIR, reply); }) .on(amman_client_1.MSG_REQUEST_LOAD_KEYPAIR, (idArg) => { logTrace(amman_client_1.MSG_REQUEST_LOAD_KEYPAIR, idArg); const reply = this.handler.requestLoadKeypair(idArg); socket.emit(amman_client_1.MSG_RESPOND_LOAD_KEYPAIR, reply); }) // ----------------- // Set Account // ----------------- .on(amman_client_1.MSG_REQUEST_SET_ACCOUNT, async (account) => { logTrace(amman_client_1.MSG_REQUEST_SET_ACCOUNT); const reply = await this.handler.requestSetAccount(account); socket.emit(amman_client_1.MSG_RESPOND_SET_ACCOUNT, reply); }); } close() { return new Promise((resolve, reject) => this.io.close((err) => (err ? reject(err) : resolve()))); } } exports.RelayServer = RelayServer; /** * Sets up the Amman Relay which uses the given account provider to resolve account data. * @private * */ class Relay { static createApp(handler) { const server = (0, http_1.createServer)(); const io = new socket_io_1.Server(server, { cors: { origin: '*', }, }); const relayServer = new RelayServer(io, handler); return { app: server, io, relayServer }; } static async startServer(ammanState, accountProviders, accountRenderers, programs, accounts, loadedAccountInfos, loadedKeypairs, accountsFolder, snapshotRoot, killRunning = true) { if (killRunning) { await (0, http_2.killRunningServer)(amman_client_1.AMMAN_RELAY_PORT); } const accountProvider = providers_1.AccountProvider.fromRecord(accountProviders, accountRenderers); state_1.AccountStates.createInstance(accountProvider.connection, accountProvider, loadedAccountInfos, loadedKeypairs); const accountPersister = new assets_1.AccountPersister(accountsFolder, accountProvider.connection); const snapshotPersister = new assets_1.AccountPersister(snapshotRoot, accountProvider.connection); const programLabels = programs .filter((x) => x.label != null) .reduce((acc, x) => { acc[x.programId] = x.label; return acc; }, {}); const accountLabels = accounts .filter((x) => x.label != null) .reduce((acc, x) => { acc[x.accountId] = x.label; return acc; }, {}); const knownLabels = { ...programLabels, ...accountLabels }; const handler = new handler_1.RelayHandler(accountProvider, accountPersister, snapshotPersister, ammanState, state_1.AccountStates.instance, knownLabels); const { app, io, relayServer } = Relay.createApp(handler); rest_server_1.RestServer.init(app, handler); return new Promise((resolve, reject) => { app.on('error', reject).listen(amman_client_1.AMMAN_RELAY_PORT, () => { const addr = app.address(); const msg = `Amman Relay listening on ${addr.address}:${addr.port}`; logDebug(msg); resolve({ app, io, relayServer }); }); }); } } exports.Relay = Relay; //# sourceMappingURL=server.js.map