UNPKG

@apillon/sdk

Version:

▶◀ Apillon SDK for NodeJS ▶◀

91 lines 4.37 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Identity = void 0; const apillon_1 = require("../../lib/apillon"); const apillon_api_1 = require("../../lib/apillon-api"); const ethereumjs_util_1 = require("ethereumjs-util"); const util_crypto_1 = require("@polkadot/util-crypto"); class Identity extends apillon_1.ApillonModule { constructor() { super(...arguments); /** * Base API url for identity. */ this.API_PREFIX = '/wallet-identity'; } /** * Get a wallet's on-chain identity data, including Subsocial and Polkadot Identity data * @param {string} walletAddress - Wallet address to retreive data for * @returns Identity data fetched from Polkadot Identity and Subsocial */ async getWalletIdentity(walletAddress) { return await apillon_api_1.ApillonApi.get(`${this.API_PREFIX}?address=${walletAddress}`); } /** * Generate a message presented to the user when requested to sign using their wallet * @param {string} [customText='Please sign this message'] * @returns Generated message and timestamp */ generateSigningMessage(customText = 'Please sign this message') { const timestamp = new Date().getTime(); const message = `${customText}\n${timestamp}`; return { message, timestamp }; } /** * Check if a signed message from an EVM wallet address is valid * @param {IValidateWalletSignature} data - The data used to validate the EVM signature * @returns {VerifySignedMessageResult} */ validateEvmWalletSignature(data) { const { walletAddress, message, timestamp } = data; if (timestamp && (message === null || message === void 0 ? void 0 : message.split('\n').at(-1)) !== `${timestamp}`) { throw new Error('Message does not contain a valid timestamp'); } // Check if the timestamp is within the valid time range (default 10 minutes) const isValidTimestamp = timestamp ? new Date().getTime() - timestamp <= (data.signatureValidityMinutes || 10) * 60000 : true; // Prefix the message and hash it using Keccak-256 const prefixedMessage = (0, ethereumjs_util_1.keccak256)(Buffer.from(`\x19Ethereum Signed Message:\n${message.length}${message}`, 'utf-8')); // Split the signature into its components const { v, r, s } = (0, ethereumjs_util_1.fromRpcSig)(data.signature); // Recover the public key const publicKey = (0, ethereumjs_util_1.ecrecover)(prefixedMessage, v, r, s); // Recover the address from the signature and public key const address = (0, ethereumjs_util_1.bufferToHex)((0, ethereumjs_util_1.publicToAddress)(publicKey)); const isValidAddress = walletAddress ? address.toLowerCase() === walletAddress.toLowerCase() : true; return { isValid: isValidTimestamp && isValidAddress, address, }; } /** * Check if a signed message from a Polkadot wallet address is valid * @param {IValidatePolkadotWalletSignature} data - The data used to validate the Polkadot signature * @returns {{isValid: boolean; address: string;}} */ validatePolkadotWalletSignature(data) { const { message, signature, walletAddress, timestamp } = data; const signingMessage = message instanceof Uint8Array ? Buffer.from(message).toString('base64') : message; if (timestamp && (signingMessage === null || signingMessage === void 0 ? void 0 : signingMessage.split('\n').at(-1)) !== `${timestamp}`) { throw new Error('Message does not contain a valid timestamp'); } // Check if the timestamp is within the valid time range (default 10 minutes) const isValidTimestamp = timestamp ? new Date().getTime() - timestamp <= (data.signatureValidityMinutes || 10) * 60000 : true; const { isValid, publicKey } = (0, util_crypto_1.signatureVerify)(message, signature, walletAddress); return { isValid: isValidTimestamp && isValid, address: (0, util_crypto_1.encodeAddress)(publicKey), }; } } exports.Identity = Identity; //# sourceMappingURL=identity.js.map