UNPKG

@erc7824/nitrolite

Version:

The Nitrolite SDK empowers developers to build high-performance, scalable web3 applications using state channels. It's designed to provide near-instant transactions and significantly improved user experiences by minimizing direct blockchain interactions.

143 lines (142 loc) 5.16 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.NitroliteRPC = void 0; const types_1 = require("./types"); const utils_1 = require("./utils"); class NitroliteRPC { static createRequest(requestId = (0, utils_1.generateRequestId)(), method, params = [], timestamp = (0, utils_1.getCurrentTimestamp)()) { const requestData = [requestId, method, params, timestamp]; const message = { req: requestData }; return message; } static createAppRequest(requestId = (0, utils_1.generateRequestId)(), method, params = [], timestamp = (0, utils_1.getCurrentTimestamp)(), sid) { const requestData = [requestId, method, params, timestamp]; const message = { req: requestData, sid }; return message; } static parseResponse(rawMessage) { let message; try { message = typeof rawMessage === 'string' ? JSON.parse(rawMessage) : rawMessage; } catch (e) { console.error('Failed to parse incoming message:', e); return { isValid: false, error: 'Message parsing failed', }; } if (!message || typeof message !== 'object' || !message.res || !Array.isArray(message.res) || message.res.length !== 4) { return { isValid: false, error: "Invalid message structure: Missing or invalid 'res' array.", }; } const [requestId, method, dataPayload, timestamp] = message.res; const sid = typeof message.sid === 'string' ? message.sid : undefined; if (typeof requestId !== 'number' || typeof method !== 'string' || !Object.values(types_1.RPCMethod).includes(method) || !Array.isArray(dataPayload) || typeof timestamp !== 'number') { return { isValid: false, requestId, method, sid, timestamp, error: "Invalid 'res' payload structure or types.", }; } let data; let isError = false; if (method === types_1.RPCMethod.Error) { isError = true; if (dataPayload.length === 1 && typeof dataPayload[0] === 'object' && dataPayload[0] !== null && 'error' in dataPayload[0]) { data = dataPayload[0]; } else { return { isValid: false, requestId, method, sid, timestamp, error: 'Malformed error response payload.', }; } } else { data = dataPayload; } return { isValid: true, isError, requestId, method: method, data, sid, timestamp, }; } static isResponseType(response, method) { return response.isValid && !response.isError && response.method === method; } static getMessagePayload(message) { if (message.req) return message.req; if (message.res) return message.res; throw new Error("Message must contain either 'req' or 'res' field"); } static async signRequestMessage(message, signer) { if (!message.req) { throw new Error("signRequestMessage can only sign request messages containing 'req'."); } const payload = this.getMessagePayload(message); const signature = await signer(payload); message.sig = [signature]; return message; } static async verifySingleSignature(message, expectedSigner, verifier) { if (!message.sig || !Array.isArray(message.sig) || message.sig.length === 0) { return false; } const signature = message.sig[0]; if (message.sig.length > 1) { console.error('verifySingleSignature called on message with multiple signatures. Verifying only the first one.'); } try { const payload = this.getMessagePayload(message); if (typeof signature !== 'string' || signature === '') { return false; } return await verifier(payload, signature, expectedSigner); } catch (error) { console.error('Error during single signature verification:', error); return false; } } static async verifyMultipleSignatures(message, expectedSigners, verifier) { if (!message.sig || !Array.isArray(message.sig)) { return false; } try { const payload = this.getMessagePayload(message); return await verifier(payload, message.sig, expectedSigners); } catch (error) { console.error('Error during multiple signature verification:', error); return false; } } } exports.NitroliteRPC = NitroliteRPC;