Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

bitski-provider

Package Overview
Dependencies
Maintainers
6
Versions
89
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

bitski-provider - npm Package Compare versions

Comparing version 2.0.0 to 2.1.0-next.0

6

CHANGELOG.md
# bitski-provider
## 2.1.0-next.0
### Minor Changes
- [#347](https://github.com/BitskiCo/bitski-js/pull/347) [`38b66b0`](https://github.com/BitskiCo/bitski-js/commit/38b66b0c5a460a7f28fdb520d5c39d1f795e3d61) Thanks [@pzuraq](https://github.com/pzuraq)! - Add the ability for the SDK to handle multiple sequential signing reuests
## 2.0.0

@@ -4,0 +10,0 @@

2

dist/bitski-provider.js

@@ -43,3 +43,3 @@ import SafeEventEmitter from '@metamask/safe-event-emitter';

this.activeSubs = new Set();
this.config = Object.assign(Object.assign({}, config), { fetch: (_a = config.fetch) !== null && _a !== void 0 ? _a : fetch, additionalHeaders: Object.assign({ 'X-API-KEY': config.clientId, 'X-CLIENT-ID': config.clientId, 'X-CLIENT-VERSION': "bitski-provider-v2.0.0" }, ((_b = config.additionalHeaders) !== null && _b !== void 0 ? _b : {})), apiBaseUrl: (_c = config.apiBaseUrl) !== null && _c !== void 0 ? _c : BITSKI_API_BASE_URL, signerBaseUrl: (_d = config.signerBaseUrl) !== null && _d !== void 0 ? _d : BITSKI_SIGNER_BASE_URL, store: (_e = config.store) !== null && _e !== void 0 ? _e : new LocalStorageStore(), sign: (_f = config.sign) !== null && _f !== void 0 ? _f : createBrowserSigner() });
this.config = Object.assign(Object.assign({}, config), { fetch: (_a = config.fetch) !== null && _a !== void 0 ? _a : fetch, additionalHeaders: Object.assign({ 'X-API-KEY': config.clientId, 'X-CLIENT-ID': config.clientId, 'X-CLIENT-VERSION': "bitski-provider-v2.1.0-next.0" }, ((_b = config.additionalHeaders) !== null && _b !== void 0 ? _b : {})), apiBaseUrl: (_c = config.apiBaseUrl) !== null && _c !== void 0 ? _c : BITSKI_API_BASE_URL, signerBaseUrl: (_d = config.signerBaseUrl) !== null && _d !== void 0 ? _d : BITSKI_SIGNER_BASE_URL, store: (_e = config.store) !== null && _e !== void 0 ? _e : new LocalStorageStore(), sign: (_f = config.sign) !== null && _f !== void 0 ? _f : createBrowserSigner() });
this.store = new BitskiProviderStateStore(this.config.store);

@@ -46,0 +46,0 @@ // Setup the engine

@@ -32,2 +32,3 @@ import css from '../styles/dialog';

constructor(content, dynamicContent = false) {
this.dynamicContent = dynamicContent;
// check for an element passed as content or a selector corresponding to an element

@@ -38,14 +39,2 @@ this.content = this.parseContent(content);

injectStyles();
// Inject dialog content
this.injectTemplate(this.container, this.content);
// Show a spinner if content is dynamic
if (dynamicContent) {
this.setLoading(true);
}
// Add close handlers
this.addCloseHandlers();
// A short delay is required before triggering animations
setTimeout(() => {
this.show();
}, 10);
}

@@ -64,2 +53,16 @@ /**

}
open() {
// Inject dialog content
this.injectTemplate(this.container, this.content);
// Show a spinner if content is dynamic
if (this.dynamicContent) {
this.setLoading(true);
}
// Add close handlers
this.addCloseHandlers();
// A short delay is required before triggering animations
setTimeout(() => {
this.show();
}, 10);
}
/**

@@ -66,0 +69,0 @@ * Dismisses the dialog without triggering the close handler.

@@ -6,6 +6,3 @@ import { ethErrors } from 'eth-rpc-errors';

import { createBitskiTransaction } from '../utils/transaction';
// Global state, this manages the currently open signer popup. There should never
// be more than one, so it's ok for this to be module scoped.
let currentRequestDialog;
let currentRequest;
const SIGN_REQUEST_QUEUE = [];
if (typeof window !== 'undefined') {

@@ -50,35 +47,42 @@ window.addEventListener('message', (event) => {

const showIframe = (transaction, context) => {
return new Promise((fulfill, reject) => {
const url = `${context.config.signerBaseUrl}/transactions/${transaction.id}`;
const iframe = document.createElement('iframe');
iframe.style.position = 'absolute';
iframe.style.top = '0';
iframe.style.left = '0';
iframe.style.width = '100%';
iframe.style.height = '100%';
iframe.frameBorder = '0';
iframe.src = url;
// Dismiss any existing dialogs to prevent UI glitches.
if (currentRequestDialog && currentRequest) {
currentRequestDialog.close();
const [, reject] = currentRequest;
reject(ethErrors.provider.userRejectedRequest('Another signing request was made before this one was completed'));
}
currentRequest = [fulfill, reject];
currentRequestDialog = new Dialog(iframe, true);
let resolve, reject;
const promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
const url = `${context.config.signerBaseUrl}/transactions/${transaction.id}`;
const iframe = document.createElement('iframe');
iframe.style.position = 'absolute';
iframe.style.top = '0';
iframe.style.left = '0';
iframe.style.width = '100%';
iframe.style.height = '100%';
iframe.frameBorder = '0';
iframe.src = url;
const dialog = new Dialog(iframe, true);
if (SIGN_REQUEST_QUEUE.length > 0) {
const lastRequest = SIGN_REQUEST_QUEUE[SIGN_REQUEST_QUEUE.length - 1];
lastRequest.promise.then(() => {
dialog.open();
});
}
else {
dialog.open();
}
SIGN_REQUEST_QUEUE.push({
resolve,
reject,
promise,
dialog,
});
return promise;
};
const handleCallback = (callback) => {
// Ignore messages when we don't have a current request in flight
if (currentRequest === undefined) {
const currentRequest = SIGN_REQUEST_QUEUE.shift();
if (!currentRequest) {
return;
}
const [fulfill, reject] = currentRequest;
const { resolve, reject, dialog } = currentRequest;
// Dismiss current dialog
if (currentRequestDialog) {
currentRequestDialog.close();
}
// Clear state
currentRequest = undefined;
currentRequestDialog = undefined;
dialog.close();
// Call the callback to complete the request

@@ -89,3 +93,3 @@ if (callback.error) {

else {
fulfill(callback.result);
resolve(callback.result);
}

@@ -92,0 +96,0 @@ };

@@ -49,3 +49,3 @@ "use strict";

this.activeSubs = new Set();
this.config = Object.assign(Object.assign({}, config), { fetch: (_a = config.fetch) !== null && _a !== void 0 ? _a : fetch, additionalHeaders: Object.assign({ 'X-API-KEY': config.clientId, 'X-CLIENT-ID': config.clientId, 'X-CLIENT-VERSION': "bitski-provider-v2.0.0" }, ((_b = config.additionalHeaders) !== null && _b !== void 0 ? _b : {})), apiBaseUrl: (_c = config.apiBaseUrl) !== null && _c !== void 0 ? _c : constants_1.BITSKI_API_BASE_URL, signerBaseUrl: (_d = config.signerBaseUrl) !== null && _d !== void 0 ? _d : constants_1.BITSKI_SIGNER_BASE_URL, store: (_e = config.store) !== null && _e !== void 0 ? _e : new store_1.LocalStorageStore(), sign: (_f = config.sign) !== null && _f !== void 0 ? _f : (0, browser_1.default)() });
this.config = Object.assign(Object.assign({}, config), { fetch: (_a = config.fetch) !== null && _a !== void 0 ? _a : fetch, additionalHeaders: Object.assign({ 'X-API-KEY': config.clientId, 'X-CLIENT-ID': config.clientId, 'X-CLIENT-VERSION': "bitski-provider-v2.1.0-next.0" }, ((_b = config.additionalHeaders) !== null && _b !== void 0 ? _b : {})), apiBaseUrl: (_c = config.apiBaseUrl) !== null && _c !== void 0 ? _c : constants_1.BITSKI_API_BASE_URL, signerBaseUrl: (_d = config.signerBaseUrl) !== null && _d !== void 0 ? _d : constants_1.BITSKI_SIGNER_BASE_URL, store: (_e = config.store) !== null && _e !== void 0 ? _e : new store_1.LocalStorageStore(), sign: (_f = config.sign) !== null && _f !== void 0 ? _f : (0, browser_1.default)() });
this.store = new store_1.BitskiProviderStateStore(this.config.store);

@@ -52,0 +52,0 @@ // Setup the engine

@@ -5,2 +5,3 @@ /**

export declare class Dialog {
private dynamicContent;
private content;

@@ -22,2 +23,3 @@ private container;

hide(): void;
open(): void;
/**

@@ -24,0 +26,0 @@ * Dismisses the dialog without triggering the close handler.

@@ -38,2 +38,3 @@ "use strict";

constructor(content, dynamicContent = false) {
this.dynamicContent = dynamicContent;
// check for an element passed as content or a selector corresponding to an element

@@ -44,14 +45,2 @@ this.content = this.parseContent(content);

injectStyles();
// Inject dialog content
this.injectTemplate(this.container, this.content);
// Show a spinner if content is dynamic
if (dynamicContent) {
this.setLoading(true);
}
// Add close handlers
this.addCloseHandlers();
// A short delay is required before triggering animations
setTimeout(() => {
this.show();
}, 10);
}

@@ -70,2 +59,16 @@ /**

}
open() {
// Inject dialog content
this.injectTemplate(this.container, this.content);
// Show a spinner if content is dynamic
if (this.dynamicContent) {
this.setLoading(true);
}
// Add close handlers
this.addCloseHandlers();
// A short delay is required before triggering animations
setTimeout(() => {
this.show();
}, 10);
}
/**

@@ -72,0 +75,0 @@ * Dismisses the dialog without triggering the close handler.

@@ -8,6 +8,3 @@ "use strict";

const transaction_1 = require("../utils/transaction");
// Global state, this manages the currently open signer popup. There should never
// be more than one, so it's ok for this to be module scoped.
let currentRequestDialog;
let currentRequest;
const SIGN_REQUEST_QUEUE = [];
if (typeof window !== 'undefined') {

@@ -52,35 +49,42 @@ window.addEventListener('message', (event) => {

const showIframe = (transaction, context) => {
return new Promise((fulfill, reject) => {
const url = `${context.config.signerBaseUrl}/transactions/${transaction.id}`;
const iframe = document.createElement('iframe');
iframe.style.position = 'absolute';
iframe.style.top = '0';
iframe.style.left = '0';
iframe.style.width = '100%';
iframe.style.height = '100%';
iframe.frameBorder = '0';
iframe.src = url;
// Dismiss any existing dialogs to prevent UI glitches.
if (currentRequestDialog && currentRequest) {
currentRequestDialog.close();
const [, reject] = currentRequest;
reject(eth_rpc_errors_1.ethErrors.provider.userRejectedRequest('Another signing request was made before this one was completed'));
}
currentRequest = [fulfill, reject];
currentRequestDialog = new dialog_1.Dialog(iframe, true);
let resolve, reject;
const promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
const url = `${context.config.signerBaseUrl}/transactions/${transaction.id}`;
const iframe = document.createElement('iframe');
iframe.style.position = 'absolute';
iframe.style.top = '0';
iframe.style.left = '0';
iframe.style.width = '100%';
iframe.style.height = '100%';
iframe.frameBorder = '0';
iframe.src = url;
const dialog = new dialog_1.Dialog(iframe, true);
if (SIGN_REQUEST_QUEUE.length > 0) {
const lastRequest = SIGN_REQUEST_QUEUE[SIGN_REQUEST_QUEUE.length - 1];
lastRequest.promise.then(() => {
dialog.open();
});
}
else {
dialog.open();
}
SIGN_REQUEST_QUEUE.push({
resolve,
reject,
promise,
dialog,
});
return promise;
};
const handleCallback = (callback) => {
// Ignore messages when we don't have a current request in flight
if (currentRequest === undefined) {
const currentRequest = SIGN_REQUEST_QUEUE.shift();
if (!currentRequest) {
return;
}
const [fulfill, reject] = currentRequest;
const { resolve, reject, dialog } = currentRequest;
// Dismiss current dialog
if (currentRequestDialog) {
currentRequestDialog.close();
}
// Clear state
currentRequest = undefined;
currentRequestDialog = undefined;
dialog.close();
// Call the callback to complete the request

@@ -91,3 +95,3 @@ if (callback.error) {

else {
fulfill(callback.result);
resolve(callback.result);
}

@@ -94,0 +98,0 @@ };

@@ -12,3 +12,3 @@ {

},
"version": "2.0.0",
"version": "2.1.0-next.0",
"scripts": {

@@ -15,0 +15,0 @@ "test": "jest",

@@ -37,3 +37,3 @@ import css from '../styles/dialog';

*/
constructor(content: HTMLElement | string, dynamicContent = false) {
constructor(content: HTMLElement | string, private dynamicContent = false) {
// check for an element passed as content or a selector corresponding to an element

@@ -46,2 +46,18 @@ this.content = this.parseContent(content);

injectStyles();
}
/**
* Show the dialog
*/
public show(): void {
this.container.classList.add('bitski-visible', 'bitski-loaded');
}
/**
* Hides the dialog, but does not remove
*/
public hide(): void {
this.container.classList.remove('bitski-visible', 'bitski-loaded');
}
public open(): void {
// Inject dialog content

@@ -51,3 +67,3 @@ this.injectTemplate(this.container, this.content);

// Show a spinner if content is dynamic
if (dynamicContent) {
if (this.dynamicContent) {
this.setLoading(true);

@@ -66,15 +82,2 @@ }

/**
* Show the dialog
*/
public show(): void {
this.container.classList.add('bitski-visible', 'bitski-loaded');
}
/**
* Hides the dialog, but does not remove
*/
public hide(): void {
this.container.classList.remove('bitski-visible', 'bitski-loaded');
}
/**
* Dismisses the dialog without triggering the close handler.

@@ -81,0 +84,0 @@ */

@@ -8,7 +8,12 @@ import { ethErrors } from 'eth-rpc-errors';

// Global state, this manages the currently open signer popup. There should never
// be more than one, so it's ok for this to be module scoped.
let currentRequestDialog: Dialog | undefined;
let currentRequest: [(signed: any) => void, (error: Error) => void] | undefined;
// Global state, this manages the currently open signer popup.
interface SignRequestState {
dialog: Dialog;
promise: Promise<string>;
resolve: (v: string | PromiseLike<string>) => void;
reject: (e: unknown) => void;
}
const SIGN_REQUEST_QUEUE: SignRequestState[] = [];
if (typeof window !== 'undefined') {

@@ -72,47 +77,53 @@ window.addEventListener('message', (event: MessageEvent) => {

): Promise<string> => {
return new Promise((fulfill, reject) => {
const url = `${context.config.signerBaseUrl}/transactions/${transaction.id}`;
let resolve, reject;
const promise = new Promise<string>((res, rej) => {
resolve = res;
reject = rej;
});
const iframe = document.createElement('iframe');
iframe.style.position = 'absolute';
iframe.style.top = '0';
iframe.style.left = '0';
iframe.style.width = '100%';
iframe.style.height = '100%';
iframe.frameBorder = '0';
iframe.src = url;
const url = `${context.config.signerBaseUrl}/transactions/${transaction.id}`;
// Dismiss any existing dialogs to prevent UI glitches.
if (currentRequestDialog && currentRequest) {
currentRequestDialog.close();
const [, reject] = currentRequest;
reject(
ethErrors.provider.userRejectedRequest(
'Another signing request was made before this one was completed',
),
);
}
const iframe = document.createElement('iframe');
iframe.style.position = 'absolute';
iframe.style.top = '0';
iframe.style.left = '0';
iframe.style.width = '100%';
iframe.style.height = '100%';
iframe.frameBorder = '0';
iframe.src = url;
currentRequest = [fulfill, reject];
currentRequestDialog = new Dialog(iframe, true);
const dialog = new Dialog(iframe, true);
if (SIGN_REQUEST_QUEUE.length > 0) {
const lastRequest = SIGN_REQUEST_QUEUE[SIGN_REQUEST_QUEUE.length - 1];
lastRequest.promise.then(() => {
dialog.open();
});
} else {
dialog.open();
}
SIGN_REQUEST_QUEUE.push({
resolve,
reject,
promise,
dialog,
});
return promise;
};
const handleCallback = (callback: any): void => {
// Ignore messages when we don't have a current request in flight
if (currentRequest === undefined) {
const currentRequest = SIGN_REQUEST_QUEUE.shift();
if (!currentRequest) {
return;
}
const [fulfill, reject] = currentRequest;
const { resolve, reject, dialog } = currentRequest;
// Dismiss current dialog
if (currentRequestDialog) {
currentRequestDialog.close();
}
dialog.close();
// Clear state
currentRequest = undefined;
currentRequestDialog = undefined;
// Call the callback to complete the request

@@ -122,3 +133,3 @@ if (callback.error) {

} else {
fulfill(callback.result);
resolve(callback.result);
}

@@ -125,0 +136,0 @@ };

@@ -6,2 +6,3 @@ import { Dialog } from '../src/components/dialog';

const dialog = new Dialog(div);
dialog.open();
expect((dialog as any).content).toBe(div);

@@ -13,2 +14,3 @@ expect((dialog as any).container.contains(div)).toEqual(true);

const dialog = new Dialog('Hello World');
dialog.open();
expect((dialog as any).content).toBeDefined();

@@ -23,2 +25,3 @@ expect((dialog as any).content.innerText).toEqual('Hello World');

const dialog = new Dialog('#test-div');
dialog.open();
expect((dialog as any).content).toBe(div);

@@ -31,2 +34,3 @@ expect((dialog as any).container.contains(div)).toEqual(true);

const spy = jest.spyOn(dialog, 'close');
dialog.open();
(dialog as any).container.dispatchEvent(new Event('click'));

@@ -39,2 +43,3 @@ expect(spy).toHaveBeenCalled();

const spy = jest.spyOn(dialog, 'close');
dialog.open();
document.dispatchEvent(new KeyboardEvent('keyup', { key: 'E' }));

@@ -48,2 +53,3 @@ expect(spy).not.toHaveBeenCalled();

const dialog = new Dialog('foo');
dialog.open();
const removeSpy = jest.spyOn((dialog as any).container, 'remove');

@@ -50,0 +56,0 @@ dialog.close();

@@ -766,3 +766,3 @@ import { EthMethod } from 'eth-provider-types';

test('sign() should close existing dialog if one is already open', async () => {
test('sign() should enqueue multiple sign requests', async () => {
expect.assertions(8);

@@ -802,14 +802,11 @@ const provider = createTestProvider({ sign: createBrowserSigner() });

provider
.request({
method: EthMethod.eth_signTransaction,
params: [txn],
})
.catch((e) =>
expect(e).toMatchObject({
message: 'Another signing request was made before this one was completed',
}),
);
const result1 = provider.request({
method: EthMethod.eth_signTransaction,
params: [txn],
});
await sleep(0);
const result2 = provider.request({
method: EthMethod.eth_signTransaction,
params: [txn],
});

@@ -827,8 +824,19 @@ triggerMessage(

const result = await provider.request({
method: EthMethod.eth_signTransaction,
params: [txn],
});
await sleep(0);
expect(result).toBe('0x123');
triggerMessage(
new MessageEvent('message', {
data: {
id: 0,
jsonrpc: '2.0',
result: '0x456',
},
origin: 'https://sign.bitski.com',
}),
);
const [result1Value, result2Value] = await Promise.all([result1, result2]);
expect(result1Value).toBe('0x123');
expect(result2Value).toBe('0x456');
});

@@ -835,0 +843,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc