UNPKG

@krebitdao/reputation-passport

Version:

Krebit SDK for Verified Credentials

200 lines (199 loc) 8.3 kB
import { ethers } from 'ethers'; import { SiweMessage } from 'siwe'; import localStore from 'store2'; import { schemas } from '../schemas/index.js'; import { utils } from '../utils/index.js'; import { config } from '../config/index.js'; export const AUTH_SIGNATURE_BODY = 'I am creating an account to use the private features of Krebit at {{timestamp}}'; const signAuthMessage = async (props) => { const { wallet, resources = [], config } = props; const now = new Date().toISOString(); const statement = AUTH_SIGNATURE_BODY.replace('{{timestamp}}', now); const message = { domain: config.publicUrl.replace('https://', '').replace('http://', ''), address: await wallet.getAddress(), statement, uri: config.publicUrl, version: '1', chainId: Number(schemas.krbToken[config.network].domain.chainId) }; if (resources && resources.length > 0) { message['resources'] = resources; } const siweMessage = new SiweMessage(message); const messageToSign = siweMessage.prepareMessage(); const signature = await wallet.signMessage(messageToSign); console.log('signature: ', signature); const recoveredAddress = ethers.utils.verifyMessage(messageToSign, signature); const authSig = { sig: signature, derivedVia: 'web3.eth.personal.sign', signedMessage: messageToSign, address: recoveredAddress }; localStore.set('lit-auth-signature', authSig); return authSig; }; export function canonicalAccessControlConditionFormatter(cond) { // need to return in the exact format below: /* pub struct JsonAccessControlCondition { pub contract_address: String, pub chain: String, pub standard_contract_type: String, pub method: String, pub parameters: Vec<String>, pub return_value_test: JsonReturnValueTest, } */ if (Array.isArray(cond)) { return cond.map(c => canonicalAccessControlConditionFormatter(c)); } if ('operator' in cond) { return { operator: cond.operator }; } if ('returnValueTest' in cond) { return { contractAddress: cond.contractAddress, chain: cond.chain, standardContractType: cond.standardContractType, method: cond.method, parameters: cond.parameters, returnValueTest: { comparator: cond.returnValueTest.comparator, value: cond.returnValueTest.value } }; } throw new Error(`invalid access control condition: ${cond}`); } export class Lit { constructor() { this.connect = async () => { this.litSdk = this.currentConfig.litSdk; this.litNodeClient = new this.litSdk.LitNodeClient(); await this.litNodeClient.connect(); }; this.getOwnsAddressCondition = (address) => { return [ { conditionType: 'evmBasic', contractAddress: '', standardContractType: '', chain: this.currentConfig.network, method: '', parameters: [':userAddress'], returnValueTest: { comparator: '=', value: address } } ]; }; this.getShareWithCondition = (address) => { return [ { operator: 'or' }, { conditionType: 'evmBasic', contractAddress: '', standardContractType: '', chain: this.currentConfig.network, method: '', parameters: [':userAddress'], returnValueTest: { comparator: '=', value: address } } ]; }; this.encrypt = async (message, accessControlConditions, wallet) => { try { if (!this.litNodeClient) { await this.connect(); } let authSig = localStore.get('lit-auth-signature'); if (!authSig || authSig === 'undefined') { console.log('signing auth message because sig is not in local storage'); await signAuthMessage({ wallet, config: this.currentConfig }); authSig = localStore.get('lit-auth-signature'); } const { encryptedString, symmetricKey } = await this.litSdk.encryptString(message); const encryptedStringBase64 = await utils.base64.blobToBase64(encryptedString); const conds = accessControlConditions.map(c => canonicalAccessControlConditionFormatter(c)); const encryptedSymmetricKey = await this.litNodeClient.saveEncryptionKey({ accessControlConditions: conds, symmetricKey, authSig, chain: this.currentConfig.network, permanent: false }); return { encryptedString: encryptedStringBase64, encryptedSymmetricKey: this.litSdk.uint8arrayToString(encryptedSymmetricKey, 'base16'), unifiedAccessControlConditions: accessControlConditions, chain: this.currentConfig.network }; } catch (error) { console.error('Encrypt error', error); } }; this.updateConditions = async (encryptedSymmetricKey, newAccessControlConditions, wallet, permanent = false) => { if (!this.litNodeClient) { await this.connect(); } let authSig = localStore.get('lit-auth-signature'); if (!authSig || authSig === 'undefined') { console.log('signing auth message because sig is not in local storage'); await signAuthMessage({ wallet, config: this.currentConfig }); authSig = localStore.get('lit-auth-signature'); } const conds = newAccessControlConditions.map(c => canonicalAccessControlConditionFormatter(c)); const decodedKey = this.litSdk.uint8arrayFromString(encryptedSymmetricKey, 'base16'); const newEncryptedSymmetricKey = await this.litNodeClient.saveEncryptionKey({ accessControlConditions: conds, encryptedSymmetricKey: decodedKey, authSig, chain: this.currentConfig.network, permanent }); return this.litSdk.uint8arrayToString(newEncryptedSymmetricKey, 'base16'); }; this.decrypt = async (encryptedString, encryptedSymmetricKey, accessControlConditions, wallet) => { if (!this.litNodeClient) { await this.connect(); } let authSig = localStore.get('lit-auth-signature'); if (!authSig || authSig === 'undefined') { console.log('signing auth message because sig is not in local storage'); await signAuthMessage({ wallet, config: this.currentConfig }); authSig = localStore.get('lit-auth-signature'); } const conds = accessControlConditions.map(c => canonicalAccessControlConditionFormatter(c)); const decryptedSymmKey = await this.litNodeClient.getEncryptionKey({ accessControlConditions: conds, toDecrypt: encryptedSymmetricKey, authSig, chain: this.currentConfig.network }); const decryptedString = await this.litSdk.decryptString(new Blob([utils.base64.decodeb64(encryptedString)]), decryptedSymmKey); return decryptedString; }; const currentConfig = config.get(); this.currentConfig = currentConfig; } }