@signumjs/wallets
Version:
Wallets communication package for DApps in the Signum Network
164 lines • 6.52 kB
JavaScript
;
/**
* Original work Copyright (c) 2020 Madfish Solutions
* Modified work Copyright (c) 2022 Signum Network
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.BrowserExtensionAdapter = void 0;
const nanoid_1 = require("nanoid");
const messaging_1 = require("./messaging");
const errors_1 = require("./errors");
/**
* Extension Adapter for Browser based wallet access, to use with {@link GenericExtensionWallet}
*
* This adapter is automatically chosen in browser environments - Usually, you won't use this adapter directly.
*/
class BrowserExtensionAdapter {
static send(msg) {
window.postMessage(msg, '*');
}
static assertResponse(condition) {
if (!condition) {
throw new Error('Invalid response received');
}
}
/**
* Asserts that a compatible extension wallet is available
* @throws Exception if no wallet was found
*/
async assertWalletAvailable() {
return new Promise((resolve, reject) => {
const handleMessage = (evt) => {
if (evt.source === window &&
evt.data?.type === messaging_1.PageMessageType.Response &&
evt.data?.payload === 'PONG') {
done(true);
}
};
const done = (result) => {
window.removeEventListener('message', handleMessage);
clearTimeout(t);
if (result) {
resolve();
}
else {
reject((0, errors_1.createError)(messaging_1.ExtensionErrorType.NotFound));
}
};
window.addEventListener('message', handleMessage);
BrowserExtensionAdapter.send({
type: messaging_1.PageMessageType.Request,
payload: 'PING',
});
const t = setTimeout(() => done(false), 1_000);
});
}
/**
* Informs about extension wallet events, like network/node changes, permission and/or account removals
* @param callback The callback object with the event handler
* @return The listener object, that can/should be used to unsubscribe if not needed anymore
*/
onNotification(callback) {
let listener;
function handleMessage(evt) {
if (evt.source === window
&& evt.origin === location.origin
&& typeof (evt.data.type) === 'string'
&& evt.data.type.startsWith('XT_DAPP_')) {
callback(evt.data);
}
}
window.addEventListener('message', handleMessage);
listener = {
unlisten: () => { window.removeEventListener('message', handleMessage); }
};
return listener;
}
/**
* Gets the current permission
* @return The extensions permission object
*/
async getCurrentPermission() {
const res = await this.request({
type: messaging_1.ExtensionMessageType.GetCurrentPermissionRequest,
});
BrowserExtensionAdapter.assertResponse(res.type === messaging_1.ExtensionMessageType.GetCurrentPermissionResponse);
return res.permission;
}
/**
* Generic request method, to request various operations
* @param payload The payload object for the respective operation
* @return The response from the wallet in case of success
* @throws An error object in case of failures, see also {@link ExtensionWalletError}
*/
request(payload) {
return new Promise((resolve, reject) => {
const reqId = (0, nanoid_1.nanoid)();
const handleMessage = (evt) => {
const res = evt.data;
if (evt.source !== window || res?.reqId !== reqId) {
return;
}
else if (res?.type === messaging_1.PageMessageType.Response) {
resolve(res.payload);
window.removeEventListener('message', handleMessage);
}
else if (res?.type === messaging_1.PageMessageType.ErrorResponse) {
reject((0, errors_1.createError)(res.payload));
window.removeEventListener('message', handleMessage);
}
};
BrowserExtensionAdapter.send({
type: messaging_1.PageMessageType.Request,
payload,
reqId,
});
window.addEventListener('message', handleMessage);
});
}
/**
* Requests the permission of a compatible wallet.
* A permission is based on _one_ network, e.g. Signum, Signum-TESTNET, etc. and the url of the requesting application.
* The wallet should have selected a node of the required network, otherwise permission request fails with {@link InvalidNetworkError}
* @param args The argument object
*/
async requestPermission(args) {
const res = await this.request({
type: messaging_1.ExtensionMessageType.PermissionRequest,
network: args.network,
appMeta: args.appMeta,
});
BrowserExtensionAdapter.assertResponse(res.type === messaging_1.ExtensionMessageType.PermissionResponse);
return {
currentNodeHost: res.currentNodeHost,
availableNodeHosts: res.availableNodeHosts,
accountId: res.accountId,
publicKey: res.publicKey,
watchOnly: res.watchOnly
};
}
async requestSign(args) {
const res = await this.request({
type: messaging_1.ExtensionMessageType.SignRequest,
payload: args.unsignedTransaction,
});
BrowserExtensionAdapter.assertResponse(res.type === messaging_1.ExtensionMessageType.SignResponse);
return {
transactionId: res.transactionId,
fullHash: res.fullHash
};
}
async requestSendEncryptedMessage(args) {
const res = await this.request({
type: messaging_1.ExtensionMessageType.SendEncryptedMessageRequest,
...args
});
BrowserExtensionAdapter.assertResponse(res.type === messaging_1.ExtensionMessageType.SendEncryptedMessageResponse);
return {
transactionId: res.transactionId,
fullHash: res.fullHash
};
}
}
exports.BrowserExtensionAdapter = BrowserExtensionAdapter;
//# sourceMappingURL=browserExtensionAdapter.js.map