UNPKG

@skalenetwork/bite

Version:

TS Library to interact with BITE protocol

1 lines 20.6 kB
{"version":3,"sources":["../src/core/encrypt.ts","../src/utils/constants.ts","../src/utils/helper.ts","../src/utils/logger.ts","../src/core/biteRpc.ts","../src/core/bite.ts"],"sourcesContent":["/**\n * @license\n * SKALE bite.ts\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this program. If not, see <https://www.gnu.org/licenses/>.\n */\n\n/**\n * @file encrypt.ts\n * @copyright SKALE Labs 2025-Present\n */\n\nimport {\n encryptMessage as encryptRawMessage,\n encryptMessageMockup as encryptRawMessageMockup\n} from '@skalenetwork/t-encrypt';\nimport {getCommonPublicKey} from './biteRpc';\nimport {logger} from \"../utils/logger\";\nimport * as utils from '../utils/helper';\nimport * as constants from '../utils/constants';\n\n\nexport interface Transaction {\n to: string;\n data: string;\n}\n\n/**\n * Encrypts a transaction using the real BLS key.\n *\n * @param {Transaction} tx - The transaction object.\n * @param {string} endpoint - BITE URL provider.\n * @returns {Promise<Transaction>} - A promise with encrypted transaction.\n *\n */\nexport async function encryptTransaction(\n tx: Transaction,\n endpoint: string\n): Promise<Transaction> {\n try {\n const validatedTx = validateAndExtractTransactionFields(tx);\n const txTo = validatedTx.to;\n let txData = validatedTx.data;\n\n // append 'to' field to end of data\n txData += txTo;\n\n tx.data = await encryptMessage(txData, endpoint);\n tx.to = constants.BITE_ADDRESS;\n\n return tx;\n } catch (error) {\n logger.error('Error encrypting transaction:', error);\n throw error;\n }\n}\n\n/**\n * Encrypts a transaction using mock encryption.\n *\n * @param {Transaction} tx - The transaction object.\n * @returns {Promise<Transaction>} - A promise with encrypted transaction.\n *\n */\nexport async function encryptTransactionMockup(tx: Transaction): Promise<Transaction> {\n try {\n const validatedTx = validateAndExtractTransactionFields(tx);\n const txTo = validatedTx.to;\n let txData = validatedTx.data;\n\n // append 'to' field to end of data\n txData += txTo;\n\n tx.data = await encryptMessageMockup(txData);\n tx.to = constants.BITE_ADDRESS;\n\n return tx;\n } catch (error) {\n logger.error('Error encrypting transaction (mockup):', error);\n throw error;\n }\n}\n\n/**\n * Encrypts a raw hex-encoded message using the real BLS key.\n *\n * @param {string} message - The message to encrypt, as a hex string (with or without 0x prefix).\n * @param {string} endpoint - BITE URL provider.\n * @returns {Promise<string>} - The encrypted message.\n */\nexport async function encryptMessage(\n message: string,\n endpoint: string\n): Promise<string> {\n try {\n const data = utils.remove0xPrefixIfNeeded(message);\n utils.validateHexString(data);\n\n const BLS_PUBLIC_KEY = await getCommonPublicKey(endpoint);\n const encryptedRawMessage = await encryptRawMessage(data, BLS_PUBLIC_KEY);\n const epochIDHex = utils.intTo8BytesHex(0);\n\n return `0x${epochIDHex}${encryptedRawMessage}`;\n } catch (error) {\n logger.error('Error encrypting message:', error);\n throw error;\n }\n}\n\n/**\n * Encrypts a raw hex-encoded message using mock encryption.\n *\n * @param {string} message - The message to encrypt, as a hex string (with or without 0x prefix).\n * @returns {Promise<string>} - The encrypted message.\n */\nexport async function encryptMessageMockup(\n message: string\n): Promise<string> {\n try {\n const data = utils.remove0xPrefixIfNeeded(message);\n\n if (!/^[0-9a-fA-F]*$/.test(data) || data.length % 2 !== 0) {\n throw new Error(\"Invalid input: message must be valid hex and even length\");\n }\n\n const encryptedRawMessage = await encryptRawMessageMockup(data);\n const epochIDHex = utils.intTo8BytesHex(0);\n\n return `0x${epochIDHex}${encryptedRawMessage}`;\n } catch (error) {\n logger.error('Error encrypting message:', error);\n throw error;\n }\n}\n\n\n\n/**\n * Validates a transaction object for encryption and extracts the fields to be encrypted.\n * @param {object} tx - The transaction object containing a 'data' and 'to' fields (hex string).\n * @returns {{ data: string, to: string}} An object with the 'data' and 'to' fields properly validated\n * and formatted as hexadecimal strings without the '0x' prefix.\n */\nfunction validateAndExtractTransactionFields(tx: Transaction): Transaction {\n const isValid = tx && typeof tx === 'object' && \n tx.data && tx.to && \n typeof tx.data === 'string' && \n typeof tx.to === 'string';\n \n if (!isValid) {\n throw new Error(\"Invalid input: Must be an object with 'data' and 'to' fields of type string\");\n }\n\n const txData = utils.remove0xPrefixIfNeeded(tx.data);\n const txTo = utils.remove0xPrefixIfNeeded(tx.to);\n\n // Validate that the data and to fields contain only hex characters and are of even length\n utils.validateHexString(txData);\n utils.validateHexString(txTo);\n\n if (txTo.length !== 40) {\n throw new Error(\"Invalid input: 'to' field must be exactly 20 bytes (40 hex characters) long\");\n }\n\n return { data: txData, to: txTo };\n}","/**\n * @license\n * SKALE bite.ts\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this program. If not, see <https://www.gnu.org/licenses/>.\n */\n\n/**\n * @file constants.ts\n * @copyright SKALE Labs 2025-Present\n */\n\nexport const EPOCH_ID_SIZE_BYTES = 8;\nexport const BITE_ADDRESS = '0x42495445204D452049274d20454e435259505444';\nexport const NODE_ENV = process.env.NODE_ENV","/**\n * @license\n * SKALE libte-ts\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this program. If not, see <https://www.gnu.org/licenses/>.\n */\n\n/**\n * @file helper.ts\n * @copyright SKALE Labs 2025-Present\n */\n\nimport * as constants from \"./constants\";\n\nexport function remove0xPrefixIfNeeded(str: string): string {\n return str.startsWith('0x') ? str.slice(2) : str;\n}\n\nexport function intTo8BytesHex(num: number | bigint): string {\n if (typeof num !== 'number' && typeof num !== 'bigint') {\n throw new TypeError('Input must be a number or bigint');\n }\n return BigInt(num).toString(16).padStart(2 * constants.EPOCH_ID_SIZE_BYTES, '0');\n}\n\nexport function validateUrl(url: string): void {\n try {\n new URL(url);\n } catch {\n throw new Error(`Invalid provider URL: ${url}`);\n }\n}\n\nexport function validateHexString(str: string): void {\n if (!/^[0-9a-fA-F]*$/.test(str)) {\n throw new Error(\"Invalid input: Must contain only hexadecimal characters\");\n }\n if (str.length % 2 !== 0) {\n throw new Error(\"Invalid input: Must have an even length\");\n }\n}","/**\n * @license\n * SKALE bite.ts\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this program. If not, see <https://www.gnu.org/licenses/>.\n */\n\n/**\n * @file logger.ts\n * @copyright SKALE Labs 2025-Present\n */\n\nimport { Logger, type ILogObj } from 'tslog';\nimport { NODE_ENV } from './constants';\n\nconst isDev = NODE_ENV === 'development';\n\nconst logger = new Logger<ILogObj>({\n name: 'bite',\n minLevel: isDev ? 'info' : 9,\n});\n\nexport { logger };\n","/**\n * @license\n * SKALE libte-ts\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this program. If not, see <https://www.gnu.org/licenses/>.\n */\n\n/**\n * @file biteRpc.ts\n * @copyright SKALE Labs 2025-Present\n */\n\nimport * as utils from '../utils/helper';\nimport {logger} from \"../utils/logger\";\n\ninterface JsonRpcRequest {\n jsonrpc: '2.0';\n method: string;\n params: unknown[];\n id: number;\n}\n\ninterface JsonRpcSuccess<T> {\n jsonrpc: '2.0';\n result: T;\n id: number;\n}\n\ninterface JsonRpcError<E> {\n jsonrpc: '2.0';\n error: {\n code: number;\n message: string;\n data?: E;\n };\n id: number;\n}\n\ntype JsonRpcResponse<T = unknown, E = unknown> = JsonRpcSuccess<T> | JsonRpcError<E>;\n\n/**\n * Fetch decrypted transaction data via JSON-RPC endpoint.\n *\n * @param endpoint - BITE URL provider.\n * @param transactionHash - The hash of the transaction to decrypt.\n * @returns The decrypted transaction data.\n */\nexport async function getDecryptedTransactionData(\n endpoint: string,\n transactionHash: string\n): Promise<string> {\n try {\n utils.validateUrl(endpoint);\n\n const requestBody: JsonRpcRequest = {\n jsonrpc: '2.0',\n method: 'bite_getDecryptedTransactionData',\n params: [transactionHash],\n id: 1,\n };\n\n const result = await sendRpcRequest<string>(endpoint, requestBody);\n\n return result;\n } catch (error) {\n logger.error('Error fetching decrypted transaction data:', error);\n throw error;\n }\n}\n\n/**\n * Requests the common public key via JSON-RPC.\n *\n * @param endpoint - BITE URL provider.\n * @returns A 256-character hexadecimal public key string.\n * @throws If the response is invalid or the key format is incorrect.\n */\nexport async function getCommonPublicKey(endpoint: string): Promise<string> {\n try {\n const requestBody: JsonRpcRequest = {\n jsonrpc: '2.0',\n method: 'bite_getCommonPublicKey',\n params: [],\n id: 1,\n };\n \n const result = await sendRpcRequest<string>(endpoint, requestBody);\n\n if (typeof result !== 'string') {\n throw new Error('Result is not a string');\n }\n\n if (!/^[0-9a-fA-F]{256}$/.test(result)) {\n throw new Error('Result is not a valid 256-character hexadecimal string');\n }\n\n return result;\n } catch (error) {\n logger.error('Error fetching BITE common public key:', error);\n throw error;\n }\n}\n\nasync function sendRpcRequest<ResponseType>(endpoint: string, requestBody: JsonRpcRequest): Promise<ResponseType> {\n try {\n utils.validateUrl(endpoint);\n\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(requestBody),\n });\n\n if (response.status !== 200) {\n throw new Error(`Received status code: ${response.status}`);\n }\n\n const data = await response.json() as JsonRpcResponse<ResponseType>;\n\n if ('error' in data) {\n throw new Error(`Error from server: ${data.error.message}`);\n }\n\n return data.result;\n } catch (error) {\n logger.error('Error sending RPC request:', error);\n throw error;\n }\n}\n","/**\n * @license\n * SKALE libte-ts\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this program. If not, see <https://www.gnu.org/licenses/>.\n */\n\n/**\n * @file bite.ts\n * @copyright SKALE Labs 2025-Present\n */\n\nimport * as encrypt from './encrypt';\nimport * as biteRpc from './biteRpc';\n\nexport class BITE {\n private readonly providerURL: string;\n\n constructor(providerURL: string) {\n this.providerURL = providerURL;\n }\n\n /**\n * Encrypt a hex-encoded message using BLS public key.\n * @param message - Hex string (with or without 0x).\n */\n async encryptMessage(message: string): Promise<string> {\n return encrypt.encryptMessage(message, this.providerURL);\n }\n\n /**\n * Encrypt a transaction object using BLS public key.\n * @param tx - The transaction to encrypt.\n */\n async encryptTransaction(tx: encrypt.Transaction): Promise<encrypt.Transaction> {\n return encrypt.encryptTransaction(tx, this.providerURL);\n }\n\n /**\n * Fetch the common BLS public key from the configured endpoint.\n */\n async getCommonPublicKey(): Promise<string> {\n return biteRpc.getCommonPublicKey(this.providerURL);\n }\n\n /**\n * Get decrypted transaction data using the configured endpoint.\n * @param transactionHash - The hash of the transaction.\n */\n async getDecryptedTransactionData(transactionHash: string): Promise<string> {\n return biteRpc.getDecryptedTransactionData(this.providerURL, transactionHash);\n }\n}\n\n\nexport class BITEMockup {\n /**\n * Simulates encryption of a hex-encoded message\n *\n * @param message - Hex string (with or without 0x).\n */\n async encryptMessage(message: string): Promise<string> {\n return encrypt.encryptMessageMockup(message);\n }\n\n /**\n * Simulates encryption of a transaction object\n *\n * @param tx - The transaction to encrypt.\n */\n async encryptTransaction(tx: encrypt.Transaction): Promise<encrypt.Transaction> {\n return encrypt.encryptTransactionMockup(tx);\n }\n}"],"mappings":"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","names":[]}