UNPKG

@veramo/kms-web3

Version:

Veramo KMS implementation backed by web3 wallets

115 lines 4.5 kB
import { toUtf8String } from 'ethers'; import { AbstractKeyManagementSystem } from '@veramo/key-manager'; /** * This is a {@link @veramo/key-manager#AbstractKeyManagementSystem | KMS} implementation that uses the addresses of a * web3 wallet as key identifiers, and calls the respective wallet for signing operations. * @beta */ export class Web3KeyManagementSystem extends AbstractKeyManagementSystem { providers; /** * * @param providers - the key can be any unique name. * Example `{ metamask: metamaskProvider, walletConnect: walletConnectProvider }` */ constructor(providers) { super(); this.providers = providers; } createKey({ type }) { throw Error('not_supported: Web3KeyManagementSystem cannot create new keys'); } async importKey(args) { // throw Error('Not implemented') return args; } async listKeys() { const keys = []; for (const provider in this.providers) { const accounts = await this.providers[provider].listAccounts(); for (const account of accounts) { const key = { kid: `${provider}-${account}`, type: 'Secp256k1', publicKeyHex: '', kms: '', meta: { account, provider, algorithms: ['eth_signMessage', 'eth_signTypedData'], }, }; keys.push(key); } } return keys; } async sharedSecret(args) { throw Error('not_implemented: Web3KeyManagementSystem sharedSecret'); } async deleteKey(args) { // this kms doesn't need to delete keys return true; } // keyRef should be in this format '{providerName-account} // example: 'metamask-0xf3beac30c498d9e26865f34fcaa57dbb935b0d74' async getAccountAndSignerByKeyRef(keyRef) { const [providerName, account] = keyRef.kid.split('-'); if (!this.providers[providerName]) { throw Error(`not_available: provider ${providerName}`); } const signer = await this.providers[providerName].getSigner(account); return { account, signer }; } async sign({ keyRef, algorithm, data, }) { if (algorithm) { if (algorithm === 'eth_signMessage') { return await this.eth_signMessage(keyRef, data); } else if (['eth_signTypedData', 'EthereumEip712Signature2021'].includes(algorithm)) { return await this.eth_signTypedData(keyRef, data); } } throw Error(`not_supported: Cannot sign ${algorithm} `); } /** * @returns a `0x` prefixed hex string representing the signed EIP712 data */ async eth_signTypedData(keyRef, data) { let msg, msgDomain, msgTypes, msgPrimaryType; const serializedData = toUtf8String(data); try { const jsonData = JSON.parse(serializedData); if (typeof jsonData.domain === 'object' && typeof jsonData.types === 'object') { const { domain, types, message, primaryType } = jsonData; msg = message; msgDomain = domain; msgTypes = types; msgPrimaryType = primaryType; } else { // next check will throw since the data couldn't be parsed } } catch (e) { // next check will throw since the data couldn't be parsed } if (typeof msgDomain !== 'object' || typeof msgTypes !== 'object' || typeof msg !== 'object') { throw Error(`invalid_arguments: Cannot sign typed data. 'domain', 'types', and 'message' must be provided`); } delete msgTypes.EIP712Domain; const { signer } = await this.getAccountAndSignerByKeyRef(keyRef); const signature = await signer.signTypedData(msgDomain, msgTypes, msg); return signature; } /** * @returns a `0x` prefixed hex string representing the signed message */ async eth_signMessage(keyRef, rawMessageBytes) { const { signer } = await this.getAccountAndSignerByKeyRef(keyRef); const signature = await signer.signMessage(rawMessageBytes); // HEX encoded string, 0x prefixed return signature; } } //# sourceMappingURL=web3-key-management-system.js.map