@bajetech/digitalbits-wallet-sdk
Version:
A library to make it easier to write wallets that interact with the DigitalBits blockchain
191 lines (151 loc) • 4.75 kB
text/typescript
import DigitalBitsSdk from "xdb-digitalbits-sdk";
import { KeyType } from "./constants/keys";
import { generateEncryptedKey } from "./fixtures/keys";
import { getKeyMetadata } from "./helpers/getKeyMetadata";
import { EncryptedKey, Encrypter, Key, KeyMetadata, KeyStore } from "./types";
function isKey(obj: any): obj is Key {
return obj.privateKey !== undefined;
}
function isEncryptedKey(obj: any): obj is EncryptedKey {
return obj.encryptedBlob !== undefined;
}
/**
* Validates an `Encrypter` object. Resolves to true if valid.
*/
export async function testEncrypter(encrypter: any = 0): Promise<boolean> {
const account = DigitalBitsSdk.Keypair.random();
if (!encrypter) {
return Promise.reject(new Error("[Encrypter] Encrypter not defined"));
}
if (typeof encrypter.name !== "string") {
return Promise.reject(new Error("[Encrypter.name] Name not defined"));
}
if (typeof encrypter.encryptKey !== "function") {
return Promise.reject(
new Error("[Encrypter.encryptKey] Function not found")
);
}
if (typeof encrypter.decryptKey !== "function") {
return Promise.reject(
new Error("[Encrypter.decryptKey] Function not found")
);
}
const publicKey = account.publicKey();
const privateKey = account.secret();
const key: Key = {
id: "test id",
type: KeyType.plaintextKey,
publicKey,
privateKey,
};
const password = "kh2fu0b939uvdkj";
const encryptedKey = await (encrypter as Encrypter).encryptKey({
key,
password,
});
if (!isEncryptedKey(encryptedKey)) {
return Promise.reject(
new Error("[Encrypter.encryptKey] Encrypted key not valid")
);
}
const decryptedKey = await (encrypter as Encrypter).decryptKey({
encryptedKey,
password,
});
if (!isKey(decryptedKey)) {
return Promise.reject(
new Error("[Encrypter.decryptKey] Decrypted key not valid")
);
}
if (decryptedKey.privateKey !== key.privateKey) {
return Promise.reject(
new Error(
"[Encrypter.decryptKey] Decrypted key doesn't match original key"
)
);
}
return Promise.resolve(true);
}
/**
* Validates a `KeyStore` object. Resolves to true if valid.
*/
export async function testKeyStore(
keyStoreCandidate: any = null
): Promise<boolean> {
if (!keyStoreCandidate) {
return Promise.reject(new Error("[KeyStore] KeyStore not defined"));
}
if (!keyStoreCandidate.name) {
return Promise.reject(new Error("[KeyStore.name] Name not defined"));
}
const functions = [
"configure",
"storeKeys",
"updateKeys",
"loadKey",
"removeKey",
"loadAllKeys",
];
for (const functionName of functions) {
if (typeof keyStoreCandidate[functionName] !== "function") {
return Promise.reject(
new Error(`[KeyStore.${functionName}] Invalid function`)
);
}
}
const keyStore: KeyStore = keyStoreCandidate as KeyStore;
const encryptedKey: EncryptedKey = generateEncryptedKey(keyStore.name);
const keyMetadata: KeyMetadata = getKeyMetadata(encryptedKey);
// make sure we can't update a key that doesn't exist
try {
await keyStore.updateKeys([encryptedKey]);
return Promise.reject(
new Error(
"[KeyStore.updateKeys] Doesn't error when updating a nonexistent key"
)
);
} catch (e) {
// good!
}
// KeyStore.storeKeys
const testMetadata = await keyStore.storeKeys([encryptedKey]);
if (keyMetadata.id !== (testMetadata[0] as KeyMetadata).id) {
return Promise.reject(
new Error("[KeyStore.storeKeys] Key metadata doesn't match")
);
}
try {
await keyStore.storeKeys([encryptedKey]);
return Promise.reject(
new Error("[KeyStore.updateKeys] Doesn't error when storing a stored key")
);
} catch (e) {
// good!
}
// make sure we can't store a key that exists
const allKeys = await keyStore.loadAllKeys();
if (
allKeys.length !== 1 ||
encryptedKey.encryptedBlob !== (allKeys[0] as EncryptedKey).encryptedBlob
) {
return Promise.reject(
new Error("[KeyStore.loadAllKeys] loadAllKeys doesn't match")
);
}
const removalMetadata = await keyStore.removeKey(encryptedKey.id);
if (!removalMetadata || keyMetadata.id !== removalMetadata.id) {
return Promise.reject(
new Error("[KeyStore.removeKey] Removed metadata doesn't match")
);
}
if (!removalMetadata || keyMetadata.id !== removalMetadata.id) {
return Promise.reject(
new Error("[KeyStore.removeKey] Removed metadata doesn't match")
);
}
const noKeys = await keyStore.loadAllKeys();
if (noKeys.length) {
return Promise.reject(new Error("[KeyStore.removeKey] Key not removed"));
}
return Promise.resolve(true);
}