@apillon/sdk
Version:
▶◀ Apillon SDK for NodeJS ▶◀
91 lines • 4.37 kB
JavaScript
;
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