@bsv/sdk
Version:
BSV Blockchain Software Development Kit
218 lines • 9.49 kB
JavaScript
import WindowCWISubstrate from './substrates/window.CWI.js';
import XDMSubstrate from './substrates/XDM.js';
import WalletWireTransceiver from './substrates/WalletWireTransceiver.js';
import HTTPWalletWire from './substrates/HTTPWalletWire.js';
import HTTPWalletJSON from './substrates/HTTPWalletJSON.js';
import ReactNativeWebView from './substrates/ReactNativeWebView.js';
import { validateAbortActionArgs, validateAcquireDirectCertificateArgs, validateAcquireIssuanceCertificateArgs, validateCreateActionArgs, validateDiscoverByAttributesArgs, validateDiscoverByIdentityKeyArgs, validateInternalizeActionArgs, validateListActionsArgs, validateListCertificatesArgs, validateListOutputsArgs, validateProveCertificateArgs, validateRelinquishCertificateArgs, validateRelinquishOutputArgs, validateSignActionArgs } from './validationHelpers.js';
import { WERR_INVALID_PARAMETER } from './WERR_INVALID_PARAMETER.js';
const MAX_XDM_RESPONSE_WAIT = 200;
/**
* The SDK is how applications communicate with wallets over a communications substrate.
*/
export default class WalletClient {
substrate;
originator;
constructor(substrate = 'auto', originator) {
if (substrate === 'Cicada') {
substrate = new WalletWireTransceiver(new HTTPWalletWire(originator));
}
if (substrate === 'window.CWI')
substrate = new WindowCWISubstrate();
if (substrate === 'XDM')
substrate = new XDMSubstrate();
if (substrate === 'json-api')
substrate = new HTTPWalletJSON(originator);
if (substrate === 'react-native')
substrate = new ReactNativeWebView(originator);
if (substrate === 'secure-json-api')
substrate = new HTTPWalletJSON(originator, 'https://localhost:2121');
this.substrate = substrate;
this.originator = originator;
}
async connectToSubstrate() {
if (typeof this.substrate === 'object') {
return; // substrate is already connected
}
const attemptSubstrate = async (factory, timeout) => {
try {
const sub = factory();
let result;
if (typeof timeout === 'number') {
result = await Promise.race([
sub.getVersion({}),
new Promise((_resolve, reject) => setTimeout(() => reject(new Error('Timed out.')), timeout))
]);
}
else {
result = await sub.getVersion({});
}
if (typeof result !== 'object' || typeof result.version !== 'string') {
return { success: false };
}
return { success: true, sub };
}
catch {
return { success: false };
}
};
// Try fast substrates first
const fastAttempts = [
attemptSubstrate(() => new WindowCWISubstrate()),
attemptSubstrate(() => new HTTPWalletJSON(this.originator, 'https://localhost:2121')),
attemptSubstrate(() => new HTTPWalletJSON(this.originator)),
attemptSubstrate(() => new ReactNativeWebView(this.originator)),
attemptSubstrate(() => new WalletWireTransceiver(new HTTPWalletWire(this.originator)))
];
const fastResults = await Promise.allSettled(fastAttempts);
const fastSuccessful = fastResults
.filter((r) => r.status === 'fulfilled' && r.value.success && r.value.sub !== undefined)
.map(r => r.value.sub);
if (fastSuccessful.length > 0) {
this.substrate = fastSuccessful[0];
return;
}
// Fall back to slower XDM substrate
const xdmResult = await attemptSubstrate(() => new XDMSubstrate(), MAX_XDM_RESPONSE_WAIT);
if (xdmResult.success && xdmResult.sub !== undefined) {
this.substrate = xdmResult.sub;
}
else {
throw new Error('No wallet available over any communication substrate. Install a BSV wallet today!');
}
}
async createAction(args) {
validateCreateActionArgs(args);
await this.connectToSubstrate();
return await this.substrate.createAction(args, this.originator);
}
async signAction(args) {
validateSignActionArgs(args);
await this.connectToSubstrate();
return await this.substrate.signAction(args, this.originator);
}
async abortAction(args) {
validateAbortActionArgs(args);
await this.connectToSubstrate();
return await this.substrate.abortAction(args, this.originator);
}
async listActions(args) {
validateListActionsArgs(args);
await this.connectToSubstrate();
return await this.substrate.listActions(args, this.originator);
}
async internalizeAction(args) {
validateInternalizeActionArgs(args);
await this.connectToSubstrate();
return await this.substrate.internalizeAction(args, this.originator);
}
async listOutputs(args) {
validateListOutputsArgs(args);
await this.connectToSubstrate();
return await this.substrate.listOutputs(args, this.originator);
}
async relinquishOutput(args) {
validateRelinquishOutputArgs(args);
await this.connectToSubstrate();
return await this.substrate.relinquishOutput(args, this.originator);
}
async getPublicKey(args) {
await this.connectToSubstrate();
return await this.substrate.getPublicKey(args, this.originator);
}
async revealCounterpartyKeyLinkage(args) {
await this.connectToSubstrate();
return await this.substrate.revealCounterpartyKeyLinkage(args, this.originator);
}
async revealSpecificKeyLinkage(args) {
await this.connectToSubstrate();
return await this.substrate.revealSpecificKeyLinkage(args, this.originator);
}
async encrypt(args) {
await this.connectToSubstrate();
return await this.substrate.encrypt(args, this.originator);
}
async decrypt(args) {
await this.connectToSubstrate();
return await this.substrate.decrypt(args, this.originator);
}
async createHmac(args) {
await this.connectToSubstrate();
return await this.substrate.createHmac(args, this.originator);
}
async verifyHmac(args) {
await this.connectToSubstrate();
return await this.substrate.verifyHmac(args, this.originator);
}
async createSignature(args) {
await this.connectToSubstrate();
return await this.substrate.createSignature(args, this.originator);
}
async verifySignature(args) {
await this.connectToSubstrate();
return await this.substrate.verifySignature(args, this.originator);
}
async acquireCertificate(args) {
if (args.acquisitionProtocol === 'direct') {
validateAcquireDirectCertificateArgs(args);
}
else if (args.acquisitionProtocol === 'issuance') {
validateAcquireIssuanceCertificateArgs(args);
}
else {
throw new WERR_INVALID_PARAMETER('acquisitionProtocol', `valid. ${String(args.acquisitionProtocol)} is unrecognized.`);
}
await this.connectToSubstrate();
return await this.substrate.acquireCertificate(args, this.originator);
}
async listCertificates(args) {
validateListCertificatesArgs(args);
await this.connectToSubstrate();
return await this.substrate.listCertificates(args, this.originator);
}
async proveCertificate(args) {
validateProveCertificateArgs(args);
await this.connectToSubstrate();
return await this.substrate.proveCertificate(args, this.originator);
}
async relinquishCertificate(args) {
validateRelinquishCertificateArgs(args);
await this.connectToSubstrate();
return await this.substrate.relinquishCertificate(args, this.originator);
}
async discoverByIdentityKey(args) {
validateDiscoverByIdentityKeyArgs(args);
await this.connectToSubstrate();
return await this.substrate.discoverByIdentityKey(args, this.originator);
}
async discoverByAttributes(args) {
validateDiscoverByAttributesArgs(args);
await this.connectToSubstrate();
return await this.substrate.discoverByAttributes(args, this.originator);
}
async isAuthenticated(args = {}) {
await this.connectToSubstrate();
return await this.substrate.isAuthenticated(args, this.originator);
}
async waitForAuthentication(args = {}) {
await this.connectToSubstrate();
return await this.substrate.waitForAuthentication(args, this.originator);
}
async getHeight(args = {}) {
await this.connectToSubstrate();
return await this.substrate.getHeight(args, this.originator);
}
async getHeaderForHeight(args) {
await this.connectToSubstrate();
return await this.substrate.getHeaderForHeight(args, this.originator);
}
async getNetwork(args = {}) {
await this.connectToSubstrate();
return await this.substrate.getNetwork(args, this.originator);
}
async getVersion(args = {}) {
await this.connectToSubstrate();
return await this.substrate.getVersion(args, this.originator);
}
}
//# sourceMappingURL=WalletClient.js.map