wallet-storage-client
Version:
Client only Wallet Storage
325 lines • 14.9 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Wallet = void 0;
const sdk_1 = require("@bsv/sdk");
const index_client_1 = require("./index.client");
const acquireDirectCertificate_1 = require("./signer/methods/acquireDirectCertificate");
const proveCertificate_1 = require("./signer/methods/proveCertificate");
const createAction_1 = require("./signer/methods/createAction");
const signAction_1 = require("./signer/methods/signAction");
const internalizeAction_1 = require("./signer/methods/internalizeAction");
function isWalletSigner(args) {
return args["isWalletSigner"];
}
class Wallet {
constructor(argsOrSigner, services, monitor, privilegedKeyManager) {
const args = !isWalletSigner(argsOrSigner) ? argsOrSigner : {
chain: argsOrSigner.chain,
keyDeriver: argsOrSigner.keyDeriver,
storage: argsOrSigner.storage,
services,
monitor,
privilegedKeyManager
};
if (args.storage._authId.identityKey != args.keyDeriver.identityKey)
throw new index_client_1.sdk.WERR_INVALID_PARAMETER('storage', `authenticated as the same identityKey (${args.storage._authId.identityKey}) as the keyDeriver (${args.keyDeriver.identityKey}).`);
this.chain = args.chain;
this.keyDeriver = args.keyDeriver;
this.storage = args.storage;
this.proto = new sdk_1.ProtoWallet(args.keyDeriver);
this.services = args.services;
this.monitor = args.monitor;
this.privilegedKeyManager = args.privilegedKeyManager;
this.identityKey = this.keyDeriver.identityKey;
this.pendingSignActions = {};
this.userParty = `user ${this.getClientChangeKeyPair().publicKey}`;
this.beef = new sdk_1.BeefParty([this.userParty]);
this.trustSelf = 'known';
if (this.services) {
this.storage.setServices(this.services);
}
}
async destroy() {
await this.storage.destroy();
if (this.privilegedKeyManager)
await this.privilegedKeyManager.destroyKey();
}
getClientChangeKeyPair() {
const kp = {
privateKey: this.keyDeriver.rootKey.toString(),
publicKey: this.keyDeriver.rootKey.toPublicKey().toString()
};
return kp;
}
async getIdentityKey() {
return (await this.getPublicKey({ identityKey: true })).publicKey;
}
getPublicKey(args, originator) {
if (args.privileged) {
if (!this.privilegedKeyManager) {
throw new Error('Privileged operations require the Wallet to be configured with a privileged key manager.');
}
return this.privilegedKeyManager.getPublicKey(args);
}
return this.proto.getPublicKey(args);
}
revealCounterpartyKeyLinkage(args, originator) {
if (args.privileged) {
if (!this.privilegedKeyManager) {
throw new Error('Privileged operations require the Wallet to be configured with a privileged key manager.');
}
return this.privilegedKeyManager.revealCounterpartyKeyLinkage(args);
}
return this.proto.revealCounterpartyKeyLinkage(args);
}
revealSpecificKeyLinkage(args, originator) {
if (args.privileged) {
if (!this.privilegedKeyManager) {
throw new Error('Privileged operations require the Wallet to be configured with a privileged key manager.');
}
return this.privilegedKeyManager.revealSpecificKeyLinkage(args);
}
return this.proto.revealSpecificKeyLinkage(args);
}
encrypt(args, originator) {
if (args.privileged) {
if (!this.privilegedKeyManager) {
throw new Error('Privileged operations require the Wallet to be configured with a privileged key manager.');
}
return this.privilegedKeyManager.encrypt(args);
}
return this.proto.encrypt(args);
}
decrypt(args, originator) {
if (args.privileged) {
if (!this.privilegedKeyManager) {
throw new Error('Privileged operations require the Wallet to be configured with a privileged key manager.');
}
return this.privilegedKeyManager.decrypt(args);
}
return this.proto.decrypt(args);
}
createHmac(args, originator) {
if (args.privileged) {
if (!this.privilegedKeyManager) {
throw new Error('Privileged operations require the Wallet to be configured with a privileged key manager.');
}
return this.privilegedKeyManager.createHmac(args);
}
return this.proto.createHmac(args);
}
verifyHmac(args, originator) {
if (args.privileged) {
if (!this.privilegedKeyManager) {
throw new Error('Privileged operations require the Wallet to be configured with a privileged key manager.');
}
return this.privilegedKeyManager.verifyHmac(args);
}
return this.proto.verifyHmac(args);
}
createSignature(args, originator) {
if (args.privileged) {
if (!this.privilegedKeyManager) {
throw new Error('Privileged operations require the Wallet to be configured with a privileged key manager.');
}
return this.privilegedKeyManager.createSignature(args);
}
return this.proto.createSignature(args);
}
verifySignature(args, originator) {
if (args.privileged) {
if (!this.privilegedKeyManager) {
throw new Error('Privileged operations require the Wallet to be configured with a privileged key manager.');
}
return this.privilegedKeyManager.verifySignature(args);
}
return this.proto.verifySignature(args);
}
getServices() {
if (!this.services)
throw new index_client_1.sdk.WERR_INVALID_PARAMETER('services', 'valid in constructor arguments to be retreived here.');
return this.services;
}
/**
* @returns the full list of txids whose validity this wallet claims to know.
*
* @param newKnownTxids Optional. Additional new txids known to be valid by the caller to be merged.
*/
getKnownTxids(newKnownTxids) {
if (newKnownTxids) {
for (const txid of newKnownTxids)
this.beef.mergeTxidOnly(txid);
}
const r = this.beef.sortTxs();
const knownTxids = r.valid;
return knownTxids;
}
getStorageIdentity() {
const s = this.storage.getSettings();
return { storageIdentityKey: s.storageIdentityKey, storageName: s.storageName };
}
validateAuthAndArgs(args, validate) {
const vargs = validate(args);
const auth = { identityKey: this.identityKey };
return { vargs, auth };
}
//////////////////
// List Methods
//////////////////
async listActions(args, originator) {
index_client_1.sdk.validateOriginator(originator);
const { vargs } = this.validateAuthAndArgs(args, index_client_1.sdk.validateListActionsArgs);
const r = await this.storage.listActions(vargs);
return r;
}
get storageParty() { return `storage ${this.getStorageIdentity().storageIdentityKey}`; }
async listOutputs(args, originator) {
index_client_1.sdk.validateOriginator(originator);
const { vargs } = this.validateAuthAndArgs(args, index_client_1.sdk.validateListOutputsArgs);
vargs.knownTxids = this.getKnownTxids();
const r = await this.storage.listOutputs(vargs);
if (r.BEEF) {
this.beef.mergeBeefFromParty(this.storageParty, r.BEEF);
}
return r;
}
async listCertificates(args, originator) {
index_client_1.sdk.validateOriginator(originator);
const { vargs } = this.validateAuthAndArgs(args, index_client_1.sdk.validateListCertificatesArgs);
const r = await this.storage.listCertificates(vargs);
return r;
}
//////////////////
// Certificates
//////////////////
async acquireCertificate(args, originator) {
index_client_1.sdk.validateOriginator(originator);
if (args.acquisitionProtocol === 'direct') {
const { auth, vargs } = this.validateAuthAndArgs(args, index_client_1.sdk.validateAcquireDirectCertificateArgs);
vargs.subject = (await this.getPublicKey({ identityKey: true, privileged: args.privileged, privilegedReason: args.privilegedReason })).publicKey;
try {
// Confirm that the information received adds up to a usable certificate...
await index_client_1.sdk.CertOps.fromCounterparty(vargs.privileged ? this.privilegedKeyManager : this, {
certificate: { ...vargs },
keyring: vargs.keyringForSubject,
counterparty: vargs.keyringRevealer === 'certifier' ? vargs.certifier : vargs.keyringRevealer
});
}
catch (eu) {
const e = index_client_1.sdk.WalletError.fromUnknown(eu);
throw new index_client_1.sdk.WERR_INVALID_PARAMETER('args', `valid encrypted and signed certificate and keyring from revealer. ${e.name}: ${e.message}`);
}
const r = await (0, acquireDirectCertificate_1.acquireDirectCertificate)(this, auth, vargs);
return r;
}
if (args.acquisitionProtocol === 'issuance') {
throw new index_client_1.sdk.WERR_NOT_IMPLEMENTED();
}
throw new index_client_1.sdk.WERR_INVALID_PARAMETER('acquisitionProtocol', `valid. ${args.acquisitionProtocol} is unrecognized.`);
}
async relinquishCertificate(args, originator) {
index_client_1.sdk.validateOriginator(originator);
this.validateAuthAndArgs(args, index_client_1.sdk.validateRelinquishCertificateArgs);
const r = await this.storage.relinquishCertificate(args);
return { relinquished: true };
}
async proveCertificate(args, originator) {
originator = index_client_1.sdk.validateOriginator(originator);
const { auth, vargs } = this.validateAuthAndArgs(args, index_client_1.sdk.validateProveCertificateArgs);
const r = await (0, proveCertificate_1.proveCertificate)(this, auth, vargs);
return r;
}
async discoverByIdentityKey(args, originator) {
index_client_1.sdk.validateOriginator(originator);
this.validateAuthAndArgs(args, index_client_1.sdk.validateDiscoverByIdentityKeyArgs);
throw new Error("Method not implemented.");
}
async discoverByAttributes(args, originator) {
index_client_1.sdk.validateOriginator(originator);
this.validateAuthAndArgs(args, index_client_1.sdk.validateDiscoverByAttributesArgs);
throw new Error("Method not implemented.");
}
//////////////////
// Actions
//////////////////
async createAction(args, originator) {
var _a;
index_client_1.sdk.validateOriginator(originator);
if (!args.options)
args.options = {};
(_a = args.options).trustSelf || (_a.trustSelf = this.trustSelf);
args.options.knownTxids = this.getKnownTxids(args.options.knownTxids);
const { auth, vargs } = this.validateAuthAndArgs(args, index_client_1.sdk.validateCreateActionArgs);
const r = await (0, createAction_1.createAction)(this, auth, vargs);
if (r.signableTransaction) {
const st = r.signableTransaction;
const ab = sdk_1.Beef.fromBinary(st.tx);
if (!ab.atomicTxid)
throw new index_client_1.sdk.WERR_INTERNAL('Missing atomicTxid in signableTransaction result');
if (ab.txs.length < 1 || ab.txs[ab.txs.length - 1].txid !== ab.atomicTxid)
throw new index_client_1.sdk.WERR_INTERNAL('atomicTxid does not match txid of last AtomicBEEF transaction');
// Remove the new, partially constructed transaction from beef as it will never be a valid transaction.
ab.txs.slice(ab.txs.length - 1);
this.beef.mergeBeefFromParty(this.storageParty, ab);
}
else if (r.tx) {
this.beef.mergeBeefFromParty(this.storageParty, r.tx);
}
return r;
}
async signAction(args, originator) {
index_client_1.sdk.validateOriginator(originator);
const { auth, vargs } = this.validateAuthAndArgs(args, index_client_1.sdk.validateSignActionArgs);
const r = await (0, signAction_1.signAction)(this, auth, vargs);
return r;
}
async abortAction(args, originator) {
index_client_1.sdk.validateOriginator(originator);
const { auth } = this.validateAuthAndArgs(args, index_client_1.sdk.validateAbortActionArgs);
const r = await this.storage.abortAction(args);
return r;
}
async internalizeAction(args, originator) {
index_client_1.sdk.validateOriginator(originator);
const { auth, vargs } = this.validateAuthAndArgs(args, index_client_1.sdk.validateInternalizeActionArgs);
const r = await (0, internalizeAction_1.internalizeAction)(this, auth, args);
return r;
}
async relinquishOutput(args, originator) {
index_client_1.sdk.validateOriginator(originator);
const { vargs } = this.validateAuthAndArgs(args, index_client_1.sdk.validateRelinquishOutputArgs);
const r = await this.storage.relinquishOutput(args);
return { relinquished: true };
}
async isAuthenticated(args, originator) {
index_client_1.sdk.validateOriginator(originator);
const r = {
authenticated: true
};
return r;
}
async waitForAuthentication(args, originator) {
index_client_1.sdk.validateOriginator(originator);
return { authenticated: true };
}
async getHeight(args, originator) {
index_client_1.sdk.validateOriginator(originator);
const height = await this.getServices().getHeight();
return { height };
}
async getHeaderForHeight(args, originator) {
index_client_1.sdk.validateOriginator(originator);
const serializedHeader = await this.getServices().getHeaderForHeight(args.height);
return { header: sdk_1.Utils.toHex(serializedHeader) };
}
async getNetwork(args, originator) {
index_client_1.sdk.validateOriginator(originator);
return { network: (0, index_client_1.toWalletNetwork)(this.chain) };
}
async getVersion(args, originator) {
index_client_1.sdk.validateOriginator(originator);
return { version: 'wallet-brc100-1.0.0' };
}
}
exports.Wallet = Wallet;
//# sourceMappingURL=Wallet.js.map