@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
JavaScript
;
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