UNPKG

sui-direct

Version:

Decentralized version control system on SUI blockchain

142 lines (141 loc) 6.18 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const os_1 = require("os"); const prompts_1 = __importDefault(require("prompts")); const utils_1 = require("@mysten/sui/utils"); const fs_1 = require("fs"); const p2p_1 = __importDefault(require("./p2p")); const colors_1 = require("../utils/colors"); class Auth extends p2p_1.default { constructor(_) { super(); this.connection = _.connection; this.nodePeerID = _.nodePeerID; this.peerID = _.peerID; } static async waitUntilAuthenticated(stream, token) { // Send token message await stream.sink(JSON.stringify({ token })); // Wait for server to acknowledge token validation const ackChunk = await stream.source.next(); const ack = JSON.parse(ackChunk.value.toString()); if (ack.status !== true) { throw new Error(ack.message || "Token validation failed on server."); } } async getUser() { return new Promise(async (resolve, reject) => { const unauthenticated = () => { console.log(colors_1.colorize.errorIcon("You must be logged in to perform this action.")); return reject(); }; const tokenDir = `${(0, os_1.homedir)()}/.sui-direct/TOKEN`; if (!(0, fs_1.existsSync)(tokenDir)) return unauthenticated(); const token = (0, fs_1.readFileSync)(tokenDir, "utf-8"); if (!token) return unauthenticated(); const stream = await this.connection.newStream(this.VALIDATE_PROTOCOL); const message = JSON.stringify({ token, peerID: this.peerID.toString(), }); await this.sink(stream, message); const response = await this.parseChunk(stream); if (response === null || response === void 0 ? void 0 : response.expired) { this.logout(); console.log(colors_1.colorize.errorIcon("Session is expired. Please login again.")); return reject(response.error); } if ((response === null || response === void 0 ? void 0 : response.status) !== "ok") { return unauthenticated(); } return resolve({ data: response.decoded.data, token, }); }); } async login(publicKey) { // Get nonce from node const nonceStream = await this.connection.newStream(this.NONCE_PROTOCOL); const nonceMessage = JSON.stringify({ peerID: this.peerID.toString(), }); await this.sink(nonceStream, nonceMessage); const response = await this.parseChunk(nonceStream); if (!(response === null || response === void 0 ? void 0 : response.nonce)) { console.error(colors_1.colorize.errorIcon("Failed to get nonce from node.")); return; } // Get public key if (!publicKey) { const publicKeyInput = await (0, prompts_1.default)({ type: "text", name: "publicKey", message: "Please enter your SUI wallet address", validate: (value) => (0, utils_1.isValidSuiAddress)(value) && value.trim() ? true : "Invalid SUI address", }); publicKey = publicKeyInput.publicKey; if (!publicKey) { console.error(colors_1.colorize.errorIcon("Public key is required to authenticate.")); return; } } // Instructions console.log("\n"); console.log("Please go to the following URL to sign a message:"); console.log(`${colors_1.colorize.warning(`https://sui.direct/sign?nonce=${response.nonce}`)}${colors_1.colorize.reset()}\n\n`); console.log("If you are using CLI wallet, please sign the message below:\n"); console.log(`${colors_1.colorize.highlight(`Welcome to sui.direct!\n\nSign this message to authenticate in the CLI.\n\nNonce: ${response.nonce}`)}${colors_1.colorize.reset()}`); let validated = false; let token; while (!validated) { const signatureInput = await (0, prompts_1.default)({ type: "text", name: "signature", message: "Paste the signature here", validate: (value) => (value.length > 0 ? true : "Signature cannot be empty"), }); const signature = signatureInput.signature; if (signature === "exit" || signature === "quit") { console.log(colors_1.colorize.error("Good bye!")); return; } // Send the signature to the node for validation const signatureStream = await this.connection.newStream(this.SIGNATURE_PROTOCOL); const signatureMessage = JSON.stringify({ peerID: this.peerID.toString(), publicKey: publicKey, signature: signature, }); await this.sink(signatureStream, signatureMessage); const signatureResponse = await this.parseChunk(signatureStream); if (signatureResponse === null || signatureResponse === void 0 ? void 0 : signatureResponse.error) { console.log(colors_1.colorize.errorIcon(signatureResponse.error)); } else { token = signatureResponse.token; validated = true; } } // Store the token (0, fs_1.writeFileSync)(`${(0, os_1.homedir)()}/.sui-direct/TOKEN`, token, { encoding: "utf-8", flag: "w+", }); console.log(colors_1.colorize.successIcon("Successfully authenticated.")); } logout() { try { (0, fs_1.rmSync)(`${(0, os_1.homedir)()}/.sui-direct/TOKEN`); } catch (e) { // Ignore errors } } } exports.default = Auth;