@dynamic-labs/global-wallet-client 4.9.8 → 4.9.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/package.cjs +1 -1
  3. package/package.js +1 -1
  4. package/package.json +7 -6
  5. package/src/core.d.ts +4 -0
  6. package/src/lib/actions/connectAction/createConnectAction.cjs +3 -1
  7. package/src/lib/actions/connectAction/createConnectAction.js +4 -2
  8. package/src/lib/createGlobalWalletClient.cjs +10 -4
  9. package/src/lib/createGlobalWalletClient.js +10 -4
  10. package/src/lib/errors/DisconnectError.cjs +19 -0
  11. package/src/lib/errors/DisconnectError.d.ts +5 -0
  12. package/src/lib/errors/DisconnectError.js +15 -0
  13. package/src/lib/errors/PopupClosedError.cjs +12 -0
  14. package/src/lib/errors/PopupClosedError.d.ts +3 -0
  15. package/src/lib/errors/PopupClosedError.js +8 -0
  16. package/src/lib/errors/UnknownError.cjs +12 -0
  17. package/src/lib/errors/UnknownError.d.ts +3 -0
  18. package/src/lib/errors/UnknownError.js +8 -0
  19. package/src/lib/ethereum/functions/eip1193Provider/createEIP1193Provider.cjs +13 -7
  20. package/src/lib/ethereum/functions/eip1193Provider/createEIP1193Provider.js +13 -7
  21. package/src/lib/functions/createEncryptedMessageEncoder/createEncryptedMessageEncoder.cjs +19 -0
  22. package/src/lib/functions/createEncryptedMessageEncoder/createEncryptedMessageEncoder.d.ts +3 -0
  23. package/src/lib/functions/createEncryptedMessageEncoder/createEncryptedMessageEncoder.js +15 -0
  24. package/src/lib/functions/createEncryptedMessageEncoder/index.d.ts +1 -0
  25. package/src/lib/functions/createPopupMessageClient/createPopupMessageClient.cjs +74 -0
  26. package/src/lib/functions/createPopupMessageClient/createPopupMessageClient.d.ts +14 -0
  27. package/src/lib/functions/createPopupMessageClient/createPopupMessageClient.js +70 -0
  28. package/src/lib/functions/createPopupMessageClient/index.d.ts +1 -0
  29. package/src/lib/functions/createPopupOpener/createPopupOpener.cjs +110 -42
  30. package/src/lib/functions/createPopupOpener/createPopupOpener.d.ts +2 -1
  31. package/src/lib/functions/createPopupOpener/createPopupOpener.js +111 -43
  32. package/src/lib/functions/createPopupOpener/utils/mapErrorFromPopup.cjs +25 -0
  33. package/src/lib/functions/createPopupOpener/utils/mapErrorFromPopup.d.ts +4 -0
  34. package/src/lib/functions/createPopupOpener/utils/mapErrorFromPopup.js +21 -0
  35. package/src/lib/solana/errors/UserRejectedRequestError.cjs +13 -0
  36. package/src/lib/solana/errors/UserRejectedRequestError.d.ts +4 -0
  37. package/src/lib/solana/errors/UserRejectedRequestError.js +9 -0
  38. package/src/lib/solana/functions/convertErrorToStandard/convertErrorToStandard.cjs +17 -0
  39. package/src/lib/solana/functions/convertErrorToStandard/convertErrorToStandard.d.ts +1 -0
  40. package/src/lib/solana/functions/convertErrorToStandard/convertErrorToStandard.js +13 -0
  41. package/src/lib/solana/functions/convertErrorToStandard/index.d.ts +1 -0
  42. package/src/lib/solana/functions/createSolanaSignAndSendTransactionFeature/createSolanaSignAndSendTransactionFeature.cjs +5 -2
  43. package/src/lib/solana/functions/createSolanaSignAndSendTransactionFeature/createSolanaSignAndSendTransactionFeature.js +5 -2
  44. package/src/lib/solana/functions/createSolanaSignMessageFeature/createSolanaSignMessageFeature.cjs +5 -2
  45. package/src/lib/solana/functions/createSolanaSignMessageFeature/createSolanaSignMessageFeature.js +5 -2
  46. package/src/lib/solana/functions/createSolanaSignTransactionFeature/createSolanaSignTransactionFeature.cjs +5 -2
  47. package/src/lib/solana/functions/createSolanaSignTransactionFeature/createSolanaSignTransactionFeature.js +5 -2
  48. package/src/lib/solana/functions/createStandardConnectFeature/createStandardConnectFeature.cjs +2 -1
  49. package/src/lib/solana/functions/createStandardConnectFeature/createStandardConnectFeature.js +2 -1
  50. package/src/lib/store/createClientStore.cjs +23 -1
  51. package/src/lib/store/createClientStore.d.ts +14 -0
  52. package/src/lib/store/createClientStore.js +23 -1
  53. package/src/lib/types/GlobalWalletPopupMessages.d.ts +16 -0
  54. package/src/lib/constants/logger.cjs +0 -10
  55. package/src/lib/constants/logger.js +0 -6
  56. package/src/lib/functions/mergeAndEncryptParams/index.d.ts +0 -1
  57. package/src/lib/functions/mergeAndEncryptParams/mergeAndEncryptParams.cjs +0 -23
  58. package/src/lib/functions/mergeAndEncryptParams/mergeAndEncryptParams.d.ts +0 -2
  59. package/src/lib/functions/mergeAndEncryptParams/mergeAndEncryptParams.js +0 -19
  60. package/src/lib/functions/mergeURLSearchParams/index.d.ts +0 -1
  61. package/src/lib/functions/mergeURLSearchParams/mergeURLSearchParams.cjs +0 -17
  62. package/src/lib/functions/mergeURLSearchParams/mergeURLSearchParams.d.ts +0 -6
  63. package/src/lib/functions/mergeURLSearchParams/mergeURLSearchParams.js +0 -13
  64. package/src/lib/functions/waitForPopupResponse/index.d.ts +0 -1
  65. package/src/lib/functions/waitForPopupResponse/waitForPopupResponse.cjs +0 -55
  66. package/src/lib/functions/waitForPopupResponse/waitForPopupResponse.d.ts +0 -9
  67. package/src/lib/functions/waitForPopupResponse/waitForPopupResponse.js +0 -51
@@ -5,80 +5,148 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
 
6
6
  var _tslib = require('../../../../_virtual/_tslib.cjs');
7
7
  var utils = require('@dynamic-labs/utils');
8
- var waitForPopupResponse = require('../waitForPopupResponse/waitForPopupResponse.cjs');
9
8
  var onPopupClose = require('../onPopupClose/onPopupClose.cjs');
10
- var mergeAndEncryptParams = require('../mergeAndEncryptParams/mergeAndEncryptParams.cjs');
11
9
  var getCenteredPopupFeatures = require('../getCenteredPopupFeatures/getCenteredPopupFeatures.cjs');
10
+ var createPopupMessageClient = require('../createPopupMessageClient/createPopupMessageClient.cjs');
11
+ var createEncryptedMessageEncoder = require('../createEncryptedMessageEncoder/createEncryptedMessageEncoder.cjs');
12
+ var PopupClosedError = require('../../errors/PopupClosedError.cjs');
13
+ var mapErrorFromPopup = require('./utils/mapErrorFromPopup.cjs');
12
14
 
13
15
  const createPopupOpener = ({ environmentId, popupUrl, popupWidth = 420, popupHeight = 640, store, popupActionTimeout = 1000, // Wait page up to 1 second for new actions before closing
14
- }) => {
16
+ onError, }) => {
15
17
  let popup = null;
16
- let didOpenPopup = false;
17
18
  let lastActionId = null;
19
+ let clientSessionKeyPair = null;
18
20
  const closePopup = () => {
19
21
  popup === null || popup === void 0 ? void 0 : popup.close();
20
22
  popup = null;
21
- didOpenPopup = false;
22
23
  lastActionId = null;
23
24
  };
25
+ // TODO update definition here to use name and args
24
26
  return (_a) => _tslib.__awaiter(void 0, [_a], void 0, function* ({ params, pathname, }) {
27
+ clientSessionKeyPair = clientSessionKeyPair !== null && clientSessionKeyPair !== void 0 ? clientSessionKeyPair : (yield utils.createKeyPair());
25
28
  // Used as a unique identifier for the action
26
- const actionId = new Date().getTime();
29
+ const actionId = new Date().getTime().toString();
27
30
  lastActionId = actionId;
28
31
  const popupFinalUrl = new URL(popupUrl);
29
32
  const activeConnection = store.getActiveConnection();
30
- const resultDeferredPromise = new utils.DeferredPromise();
31
33
  // Setup popup URL and data
32
- popupFinalUrl.hash = `/${pathname}`;
33
34
  popupFinalUrl.searchParams.set('provider_env_id', environmentId);
34
- // TODO: use PlatformService
35
35
  popupFinalUrl.searchParams.set('requester_origin', window.location.origin);
36
- if (popup === null) {
36
+ popupFinalUrl.searchParams.set('client_session_public_key', yield utils.convertPublicKeyCryptoKeyToHex(clientSessionKeyPair.publicKey));
37
+ /**
38
+ * Open a new popup centered on the screen
39
+ */
40
+ const initializePopup = () => {
37
41
  const features = getCenteredPopupFeatures.getCenteredPopupFeatures({
38
42
  height: popupHeight,
39
43
  width: popupWidth,
40
44
  });
41
45
  // Open popup
42
- popup = window.open('', '_blank', features);
43
- }
44
- // Encrypt params if active connection is present
45
- if (params) {
46
- yield mergeAndEncryptParams.mergeAndEncryptParams(popupFinalUrl, params, activeConnection);
47
- }
48
- if (popup === null) {
49
- throw new Error('Failed to open popup');
50
- }
51
- waitForPopupResponse.waitForPopupResponse({
52
- decode: (data) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
53
- if (activeConnection && utils.isEncryptedMessage(data)) {
54
- const decryptedData = yield utils.decryptMessage(activeConnection.sharedSecret, data.encryptedMessage, data.iv);
55
- return JSON.parse(decryptedData);
56
- }
57
- return data;
58
- }),
59
- onError: (error) => resultDeferredPromise.reject(error),
60
- onResponse: (response) => resultDeferredPromise.resolve(response.data),
61
- popupUrl: popupFinalUrl.toString(),
46
+ const popup = window.open('', '_blank', features);
47
+ if (popup === null) {
48
+ throw new Error('Failed to open popup');
49
+ }
50
+ popup.location = popupFinalUrl.href;
51
+ return popup;
52
+ };
53
+ /**
54
+ * Perform the initial handshake with the popup to get the session public key and nonce
55
+ */
56
+ const popupHandshake = () => _tslib.__awaiter(void 0, void 0, void 0, function* () {
57
+ utils.assertDefined(clientSessionKeyPair, 'Client session key pair is not set');
58
+ utils.assertDefined(popup, 'Popup is not defined');
59
+ const popupMessageClient = createPopupMessageClient.createPopupMessageClient(popup, popupFinalUrl.origin);
60
+ const [[popupSessionPublicKey], [nonce]] = yield Promise.all([
61
+ popupMessageClient.waitForMessage('sendPopupSessionPublicKey', 20000),
62
+ popupMessageClient.waitForMessage('sendPopupNonce', 20000),
63
+ ]);
64
+ const sessionSharedSecret = yield utils.deriveSharedSecret(clientSessionKeyPair.privateKey, yield utils.convertPublicKeyHexToCryptoKey(popupSessionPublicKey));
65
+ store.setSessionAuthCode(new TextEncoder().encode(yield utils.generateHMAC(sessionSharedSecret, nonce)));
62
66
  });
63
- onPopupClose.onPopupClose(popup, () => {
64
- resultDeferredPromise.reject(new Error('Popup closed'));
67
+ /**
68
+ * Watch for the popup to close
69
+ */
70
+ const watchForPopupClose = () => _tslib.__awaiter(void 0, void 0, void 0, function* () {
71
+ utils.assertDefined(popup, 'Popup is not defined');
72
+ return new Promise((_, reject) => {
73
+ utils.assertDefined(popup, 'Popup is not defined');
74
+ onPopupClose.onPopupClose(popup, () => {
75
+ reject(new PopupClosedError.PopupClosedError());
76
+ });
77
+ });
78
+ });
79
+ /**
80
+ * Wait for the action response from the popup
81
+ */
82
+ const waitForActionResponse = () => _tslib.__awaiter(void 0, void 0, void 0, function* () {
83
+ utils.assertDefined(popup, 'Popup is not defined');
84
+ utils.assertDefined(store.sessionAuthCode, 'Session auth code is not set');
85
+ const resultDeferredPromise = new utils.DeferredPromise();
86
+ /**
87
+ * Recreate the popup message if the encryption is available
88
+ */
89
+ const encoder = activeConnection
90
+ ? createEncryptedMessageEncoder.createEncryptedMessageEncoder(activeConnection, store.sessionAuthCode)
91
+ : undefined;
92
+ const popupMessageClient = createPopupMessageClient.createPopupMessageClient(popup, popupFinalUrl.origin, encoder);
93
+ void popupMessageClient.postMessage('sendAction', {
94
+ id: actionId,
95
+ name: pathname,
96
+ params,
97
+ });
98
+ /**
99
+ * Listen for action resolved
100
+ */
101
+ const cleanUpActionResolvedListener = popupMessageClient.listenForMessage('actionResolved', ({ data, id }) => {
102
+ if (id === actionId) {
103
+ resultDeferredPromise.resolve(data);
104
+ }
105
+ });
106
+ /**
107
+ * Listen for action rejected
108
+ */
109
+ const cleanUpActionRejectedListener = popupMessageClient.listenForMessage('actionRejected', ({ serializedError, id }) => {
110
+ if (id !== actionId)
111
+ return;
112
+ resultDeferredPromise.reject(mapErrorFromPopup.mapErrorFromPopup(serializedError));
113
+ });
114
+ /**
115
+ * Listen for a global error
116
+ */
117
+ const cleanUpSendErrorListener = popupMessageClient.listenForMessage('sendError', (serializedError) => resultDeferredPromise.reject(mapErrorFromPopup.mapErrorFromPopup(serializedError)));
118
+ return resultDeferredPromise.promise.finally(() => {
119
+ cleanUpActionResolvedListener();
120
+ cleanUpActionRejectedListener();
121
+ cleanUpSendErrorListener();
122
+ });
65
123
  });
124
+ // This array will contain all parallel promises
125
+ const promises = [];
66
126
  /**
67
- * Assign action to popup
127
+ * If no popup is present, it means this is a fresh new popup
128
+ * This block will create a new popup, perform the handshake and wait for the action response
68
129
  */
69
- if (didOpenPopup) {
70
- popup === null || popup === void 0 ? void 0 : popup.postMessage({
71
- actionPath: popupFinalUrl.search + popupFinalUrl.hash,
72
- event: 'new-action',
73
- }, popupFinalUrl.origin);
130
+ if (popup === null) {
131
+ popup = initializePopup();
132
+ promises.push(watchForPopupClose());
133
+ promises.push(popupHandshake().then(waitForActionResponse));
74
134
  }
75
135
  else {
76
- // Load popup
77
- popup.location = popupFinalUrl.href;
136
+ /**
137
+ * If a popup is present, it means this is a re-use of the same popup
138
+ * This block will watch for the popup to close and wait for the action response
139
+ */
140
+ promises.push(watchForPopupClose());
141
+ promises.push(waitForActionResponse());
78
142
  }
79
- didOpenPopup = true;
80
- return resultDeferredPromise.promise
143
+ /**
144
+ * Return the promise and setup the popup cleanup
145
+ * and error handling
146
+ */
147
+ return Promise.race(promises)
81
148
  .catch((err) => {
149
+ onError === null || onError === void 0 ? void 0 : onError(err);
82
150
  closePopup();
83
151
  throw err;
84
152
  })
@@ -7,11 +7,12 @@ type CreatePopupOpenerProps = {
7
7
  popupHeight?: number;
8
8
  store: ClientStore;
9
9
  popupActionTimeout?: number;
10
+ onError?: (error: Error) => void;
10
11
  };
11
12
  type OpenPopupProps<TAction extends IPopupAction> = {
12
13
  params: GetPopupActionFuncArgs<TAction>;
13
14
  pathname: GetPopupActionName<TAction>;
14
15
  };
15
- export declare const createPopupOpener: ({ environmentId, popupUrl, popupWidth, popupHeight, store, popupActionTimeout, }: CreatePopupOpenerProps) => <TPopupAction extends IPopupAction>({ params, pathname, }: OpenPopupProps<TPopupAction>) => Promise<GetPopupActionResult<TPopupAction>>;
16
+ export declare const createPopupOpener: ({ environmentId, popupUrl, popupWidth, popupHeight, store, popupActionTimeout, onError, }: CreatePopupOpenerProps) => <TPopupAction extends IPopupAction>({ params, pathname, }: OpenPopupProps<TPopupAction>) => Promise<GetPopupActionResult<TPopupAction>>;
16
17
  export type OpenPopup = ReturnType<typeof createPopupOpener>;
17
18
  export {};
@@ -1,80 +1,148 @@
1
1
  'use client'
2
2
  import { __awaiter } from '../../../../_virtual/_tslib.js';
3
- import { DeferredPromise, isEncryptedMessage, decryptMessage } from '@dynamic-labs/utils';
4
- import { waitForPopupResponse } from '../waitForPopupResponse/waitForPopupResponse.js';
3
+ import { createKeyPair, convertPublicKeyCryptoKeyToHex, assertDefined, deriveSharedSecret, convertPublicKeyHexToCryptoKey, generateHMAC, DeferredPromise } from '@dynamic-labs/utils';
5
4
  import { onPopupClose } from '../onPopupClose/onPopupClose.js';
6
- import { mergeAndEncryptParams } from '../mergeAndEncryptParams/mergeAndEncryptParams.js';
7
5
  import { getCenteredPopupFeatures } from '../getCenteredPopupFeatures/getCenteredPopupFeatures.js';
6
+ import { createPopupMessageClient } from '../createPopupMessageClient/createPopupMessageClient.js';
7
+ import { createEncryptedMessageEncoder } from '../createEncryptedMessageEncoder/createEncryptedMessageEncoder.js';
8
+ import { PopupClosedError } from '../../errors/PopupClosedError.js';
9
+ import { mapErrorFromPopup } from './utils/mapErrorFromPopup.js';
8
10
 
9
11
  const createPopupOpener = ({ environmentId, popupUrl, popupWidth = 420, popupHeight = 640, store, popupActionTimeout = 1000, // Wait page up to 1 second for new actions before closing
10
- }) => {
12
+ onError, }) => {
11
13
  let popup = null;
12
- let didOpenPopup = false;
13
14
  let lastActionId = null;
15
+ let clientSessionKeyPair = null;
14
16
  const closePopup = () => {
15
17
  popup === null || popup === void 0 ? void 0 : popup.close();
16
18
  popup = null;
17
- didOpenPopup = false;
18
19
  lastActionId = null;
19
20
  };
21
+ // TODO update definition here to use name and args
20
22
  return (_a) => __awaiter(void 0, [_a], void 0, function* ({ params, pathname, }) {
23
+ clientSessionKeyPair = clientSessionKeyPair !== null && clientSessionKeyPair !== void 0 ? clientSessionKeyPair : (yield createKeyPair());
21
24
  // Used as a unique identifier for the action
22
- const actionId = new Date().getTime();
25
+ const actionId = new Date().getTime().toString();
23
26
  lastActionId = actionId;
24
27
  const popupFinalUrl = new URL(popupUrl);
25
28
  const activeConnection = store.getActiveConnection();
26
- const resultDeferredPromise = new DeferredPromise();
27
29
  // Setup popup URL and data
28
- popupFinalUrl.hash = `/${pathname}`;
29
30
  popupFinalUrl.searchParams.set('provider_env_id', environmentId);
30
- // TODO: use PlatformService
31
31
  popupFinalUrl.searchParams.set('requester_origin', window.location.origin);
32
- if (popup === null) {
32
+ popupFinalUrl.searchParams.set('client_session_public_key', yield convertPublicKeyCryptoKeyToHex(clientSessionKeyPair.publicKey));
33
+ /**
34
+ * Open a new popup centered on the screen
35
+ */
36
+ const initializePopup = () => {
33
37
  const features = getCenteredPopupFeatures({
34
38
  height: popupHeight,
35
39
  width: popupWidth,
36
40
  });
37
41
  // Open popup
38
- popup = window.open('', '_blank', features);
39
- }
40
- // Encrypt params if active connection is present
41
- if (params) {
42
- yield mergeAndEncryptParams(popupFinalUrl, params, activeConnection);
43
- }
44
- if (popup === null) {
45
- throw new Error('Failed to open popup');
46
- }
47
- waitForPopupResponse({
48
- decode: (data) => __awaiter(void 0, void 0, void 0, function* () {
49
- if (activeConnection && isEncryptedMessage(data)) {
50
- const decryptedData = yield decryptMessage(activeConnection.sharedSecret, data.encryptedMessage, data.iv);
51
- return JSON.parse(decryptedData);
52
- }
53
- return data;
54
- }),
55
- onError: (error) => resultDeferredPromise.reject(error),
56
- onResponse: (response) => resultDeferredPromise.resolve(response.data),
57
- popupUrl: popupFinalUrl.toString(),
42
+ const popup = window.open('', '_blank', features);
43
+ if (popup === null) {
44
+ throw new Error('Failed to open popup');
45
+ }
46
+ popup.location = popupFinalUrl.href;
47
+ return popup;
48
+ };
49
+ /**
50
+ * Perform the initial handshake with the popup to get the session public key and nonce
51
+ */
52
+ const popupHandshake = () => __awaiter(void 0, void 0, void 0, function* () {
53
+ assertDefined(clientSessionKeyPair, 'Client session key pair is not set');
54
+ assertDefined(popup, 'Popup is not defined');
55
+ const popupMessageClient = createPopupMessageClient(popup, popupFinalUrl.origin);
56
+ const [[popupSessionPublicKey], [nonce]] = yield Promise.all([
57
+ popupMessageClient.waitForMessage('sendPopupSessionPublicKey', 20000),
58
+ popupMessageClient.waitForMessage('sendPopupNonce', 20000),
59
+ ]);
60
+ const sessionSharedSecret = yield deriveSharedSecret(clientSessionKeyPair.privateKey, yield convertPublicKeyHexToCryptoKey(popupSessionPublicKey));
61
+ store.setSessionAuthCode(new TextEncoder().encode(yield generateHMAC(sessionSharedSecret, nonce)));
58
62
  });
59
- onPopupClose(popup, () => {
60
- resultDeferredPromise.reject(new Error('Popup closed'));
63
+ /**
64
+ * Watch for the popup to close
65
+ */
66
+ const watchForPopupClose = () => __awaiter(void 0, void 0, void 0, function* () {
67
+ assertDefined(popup, 'Popup is not defined');
68
+ return new Promise((_, reject) => {
69
+ assertDefined(popup, 'Popup is not defined');
70
+ onPopupClose(popup, () => {
71
+ reject(new PopupClosedError());
72
+ });
73
+ });
74
+ });
75
+ /**
76
+ * Wait for the action response from the popup
77
+ */
78
+ const waitForActionResponse = () => __awaiter(void 0, void 0, void 0, function* () {
79
+ assertDefined(popup, 'Popup is not defined');
80
+ assertDefined(store.sessionAuthCode, 'Session auth code is not set');
81
+ const resultDeferredPromise = new DeferredPromise();
82
+ /**
83
+ * Recreate the popup message if the encryption is available
84
+ */
85
+ const encoder = activeConnection
86
+ ? createEncryptedMessageEncoder(activeConnection, store.sessionAuthCode)
87
+ : undefined;
88
+ const popupMessageClient = createPopupMessageClient(popup, popupFinalUrl.origin, encoder);
89
+ void popupMessageClient.postMessage('sendAction', {
90
+ id: actionId,
91
+ name: pathname,
92
+ params,
93
+ });
94
+ /**
95
+ * Listen for action resolved
96
+ */
97
+ const cleanUpActionResolvedListener = popupMessageClient.listenForMessage('actionResolved', ({ data, id }) => {
98
+ if (id === actionId) {
99
+ resultDeferredPromise.resolve(data);
100
+ }
101
+ });
102
+ /**
103
+ * Listen for action rejected
104
+ */
105
+ const cleanUpActionRejectedListener = popupMessageClient.listenForMessage('actionRejected', ({ serializedError, id }) => {
106
+ if (id !== actionId)
107
+ return;
108
+ resultDeferredPromise.reject(mapErrorFromPopup(serializedError));
109
+ });
110
+ /**
111
+ * Listen for a global error
112
+ */
113
+ const cleanUpSendErrorListener = popupMessageClient.listenForMessage('sendError', (serializedError) => resultDeferredPromise.reject(mapErrorFromPopup(serializedError)));
114
+ return resultDeferredPromise.promise.finally(() => {
115
+ cleanUpActionResolvedListener();
116
+ cleanUpActionRejectedListener();
117
+ cleanUpSendErrorListener();
118
+ });
61
119
  });
120
+ // This array will contain all parallel promises
121
+ const promises = [];
62
122
  /**
63
- * Assign action to popup
123
+ * If no popup is present, it means this is a fresh new popup
124
+ * This block will create a new popup, perform the handshake and wait for the action response
64
125
  */
65
- if (didOpenPopup) {
66
- popup === null || popup === void 0 ? void 0 : popup.postMessage({
67
- actionPath: popupFinalUrl.search + popupFinalUrl.hash,
68
- event: 'new-action',
69
- }, popupFinalUrl.origin);
126
+ if (popup === null) {
127
+ popup = initializePopup();
128
+ promises.push(watchForPopupClose());
129
+ promises.push(popupHandshake().then(waitForActionResponse));
70
130
  }
71
131
  else {
72
- // Load popup
73
- popup.location = popupFinalUrl.href;
132
+ /**
133
+ * If a popup is present, it means this is a re-use of the same popup
134
+ * This block will watch for the popup to close and wait for the action response
135
+ */
136
+ promises.push(watchForPopupClose());
137
+ promises.push(waitForActionResponse());
74
138
  }
75
- didOpenPopup = true;
76
- return resultDeferredPromise.promise
139
+ /**
140
+ * Return the promise and setup the popup cleanup
141
+ * and error handling
142
+ */
143
+ return Promise.race(promises)
77
144
  .catch((err) => {
145
+ onError === null || onError === void 0 ? void 0 : onError(err);
78
146
  closePopup();
79
147
  throw err;
80
148
  })
@@ -0,0 +1,25 @@
1
+ 'use client'
2
+ 'use strict';
3
+
4
+ Object.defineProperty(exports, '__esModule', { value: true });
5
+
6
+ var messageTransport = require('@dynamic-labs/message-transport');
7
+ var DisconnectError = require('../../../errors/DisconnectError.cjs');
8
+ var UnknownError = require('../../../errors/UnknownError.cjs');
9
+
10
+ const mapErrorFromPopup = (serializedError) => {
11
+ if (messageTransport.isSerializedError(serializedError)) {
12
+ const error = messageTransport.parseErrorFromTransport(serializedError);
13
+ if (DisconnectError.DisconnectError.isDisconnectError(error)) {
14
+ return new DisconnectError.DisconnectError();
15
+ }
16
+ else {
17
+ return error;
18
+ }
19
+ }
20
+ else {
21
+ return new UnknownError.UnknownError();
22
+ }
23
+ };
24
+
25
+ exports.mapErrorFromPopup = mapErrorFromPopup;
@@ -0,0 +1,4 @@
1
+ import { SerializedError } from '@dynamic-labs/message-transport';
2
+ import { DisconnectError } from '../../../errors/DisconnectError';
3
+ import { UnknownError } from '../../../errors/UnknownError';
4
+ export declare const mapErrorFromPopup: (serializedError: SerializedError) => DisconnectError | unknown[] | UnknownError;
@@ -0,0 +1,21 @@
1
+ 'use client'
2
+ import { isSerializedError, parseErrorFromTransport } from '@dynamic-labs/message-transport';
3
+ import { DisconnectError } from '../../../errors/DisconnectError.js';
4
+ import { UnknownError } from '../../../errors/UnknownError.js';
5
+
6
+ const mapErrorFromPopup = (serializedError) => {
7
+ if (isSerializedError(serializedError)) {
8
+ const error = parseErrorFromTransport(serializedError);
9
+ if (DisconnectError.isDisconnectError(error)) {
10
+ return new DisconnectError();
11
+ }
12
+ else {
13
+ return error;
14
+ }
15
+ }
16
+ else {
17
+ return new UnknownError();
18
+ }
19
+ };
20
+
21
+ export { mapErrorFromPopup };
@@ -0,0 +1,13 @@
1
+ 'use client'
2
+ 'use strict';
3
+
4
+ Object.defineProperty(exports, '__esModule', { value: true });
5
+
6
+ class UserRejectedRequestError extends Error {
7
+ constructor() {
8
+ super('User rejected the request.');
9
+ this.code = 4001;
10
+ }
11
+ }
12
+
13
+ exports.UserRejectedRequestError = UserRejectedRequestError;
@@ -0,0 +1,4 @@
1
+ export declare class UserRejectedRequestError extends Error {
2
+ code: number;
3
+ constructor();
4
+ }
@@ -0,0 +1,9 @@
1
+ 'use client'
2
+ class UserRejectedRequestError extends Error {
3
+ constructor() {
4
+ super('User rejected the request.');
5
+ this.code = 4001;
6
+ }
7
+ }
8
+
9
+ export { UserRejectedRequestError };
@@ -0,0 +1,17 @@
1
+ 'use client'
2
+ 'use strict';
3
+
4
+ Object.defineProperty(exports, '__esModule', { value: true });
5
+
6
+ var DisconnectError = require('../../../errors/DisconnectError.cjs');
7
+ var PopupClosedError = require('../../../errors/PopupClosedError.cjs');
8
+ var UserRejectedRequestError = require('../../errors/UserRejectedRequestError.cjs');
9
+
10
+ const convertErrorToStandard = (error) => {
11
+ if (error instanceof PopupClosedError.PopupClosedError || error instanceof DisconnectError.DisconnectError) {
12
+ throw new UserRejectedRequestError.UserRejectedRequestError();
13
+ }
14
+ throw error;
15
+ };
16
+
17
+ exports.convertErrorToStandard = convertErrorToStandard;
@@ -0,0 +1 @@
1
+ export declare const convertErrorToStandard: (error: unknown) => never;
@@ -0,0 +1,13 @@
1
+ 'use client'
2
+ import { DisconnectError } from '../../../errors/DisconnectError.js';
3
+ import { PopupClosedError } from '../../../errors/PopupClosedError.js';
4
+ import { UserRejectedRequestError } from '../../errors/UserRejectedRequestError.js';
5
+
6
+ const convertErrorToStandard = (error) => {
7
+ if (error instanceof PopupClosedError || error instanceof DisconnectError) {
8
+ throw new UserRejectedRequestError();
9
+ }
10
+ throw error;
11
+ };
12
+
13
+ export { convertErrorToStandard };
@@ -0,0 +1 @@
1
+ export { convertErrorToStandard } from './convertErrorToStandard';
@@ -5,17 +5,20 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
 
6
6
  var _tslib = require('../../../../../_virtual/_tslib.cjs');
7
7
  var utils = require('@dynamic-labs/utils');
8
+ var convertErrorToStandard = require('../convertErrorToStandard/convertErrorToStandard.cjs');
8
9
 
9
10
  const createSolanaSignAndSendTransactionFeature = (client) => ({
10
11
  signAndSendTransaction: (_a) => _tslib.__awaiter(void 0, [_a], void 0, function* ({ account, transaction, chain }) {
11
- const { signature } = yield client.invoke({
12
+ const { signature } = yield client
13
+ .invoke({
12
14
  params: {
13
15
  address: account.address,
14
16
  chain: chain,
15
17
  transaction: utils.uint8ArrayToBase64(transaction),
16
18
  },
17
19
  pathname: 'solana_signAndSendTransaction',
18
- });
20
+ })
21
+ .catch(convertErrorToStandard.convertErrorToStandard);
19
22
  return [
20
23
  {
21
24
  signature: new TextEncoder().encode(signature),
@@ -1,17 +1,20 @@
1
1
  'use client'
2
2
  import { __awaiter } from '../../../../../_virtual/_tslib.js';
3
3
  import { uint8ArrayToBase64 } from '@dynamic-labs/utils';
4
+ import { convertErrorToStandard } from '../convertErrorToStandard/convertErrorToStandard.js';
4
5
 
5
6
  const createSolanaSignAndSendTransactionFeature = (client) => ({
6
7
  signAndSendTransaction: (_a) => __awaiter(void 0, [_a], void 0, function* ({ account, transaction, chain }) {
7
- const { signature } = yield client.invoke({
8
+ const { signature } = yield client
9
+ .invoke({
8
10
  params: {
9
11
  address: account.address,
10
12
  chain: chain,
11
13
  transaction: uint8ArrayToBase64(transaction),
12
14
  },
13
15
  pathname: 'solana_signAndSendTransaction',
14
- });
16
+ })
17
+ .catch(convertErrorToStandard);
15
18
  return [
16
19
  {
17
20
  signature: new TextEncoder().encode(signature),
@@ -5,6 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
 
6
6
  var _tslib = require('../../../../../_virtual/_tslib.cjs');
7
7
  var utils = require('@dynamic-labs/utils');
8
+ var convertErrorToStandard = require('../convertErrorToStandard/convertErrorToStandard.cjs');
8
9
 
9
10
  const createSolanaSignMessageFeature = (client) => ({
10
11
  signMessage: (_a) => _tslib.__awaiter(void 0, [_a], void 0, function* ({ account, message }) {
@@ -12,10 +13,12 @@ const createSolanaSignMessageFeature = (client) => ({
12
13
  address: account.address,
13
14
  message: utils.uint8ArrayToBase64(message),
14
15
  };
15
- const { signature, signedMessage } = yield client.invoke({
16
+ const { signature, signedMessage } = yield client
17
+ .invoke({
16
18
  params,
17
19
  pathname: 'solana_signMessage',
18
- });
20
+ })
21
+ .catch(convertErrorToStandard.convertErrorToStandard);
19
22
  return [
20
23
  {
21
24
  signature: utils.uint8ArrayFromBase64(signature),
@@ -1,6 +1,7 @@
1
1
  'use client'
2
2
  import { __awaiter } from '../../../../../_virtual/_tslib.js';
3
3
  import { uint8ArrayToBase64, uint8ArrayFromBase64 } from '@dynamic-labs/utils';
4
+ import { convertErrorToStandard } from '../convertErrorToStandard/convertErrorToStandard.js';
4
5
 
5
6
  const createSolanaSignMessageFeature = (client) => ({
6
7
  signMessage: (_a) => __awaiter(void 0, [_a], void 0, function* ({ account, message }) {
@@ -8,10 +9,12 @@ const createSolanaSignMessageFeature = (client) => ({
8
9
  address: account.address,
9
10
  message: uint8ArrayToBase64(message),
10
11
  };
11
- const { signature, signedMessage } = yield client.invoke({
12
+ const { signature, signedMessage } = yield client
13
+ .invoke({
12
14
  params,
13
15
  pathname: 'solana_signMessage',
14
- });
16
+ })
17
+ .catch(convertErrorToStandard);
15
18
  return [
16
19
  {
17
20
  signature: uint8ArrayFromBase64(signature),
@@ -5,17 +5,20 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
 
6
6
  var _tslib = require('../../../../../_virtual/_tslib.cjs');
7
7
  var utils = require('@dynamic-labs/utils');
8
+ var convertErrorToStandard = require('../convertErrorToStandard/convertErrorToStandard.cjs');
8
9
 
9
10
  const createSolanaSignTransactionFeature = (client) => ({
10
11
  signTransaction: (_a) => _tslib.__awaiter(void 0, [_a], void 0, function* ({ account, transaction, chain }) {
11
- const { signedTransaction } = yield client.invoke({
12
+ const { signedTransaction } = yield client
13
+ .invoke({
12
14
  params: {
13
15
  address: account.address,
14
16
  chain: chain,
15
17
  transaction: utils.uint8ArrayToBase64(transaction),
16
18
  },
17
19
  pathname: 'solana_signTransaction',
18
- });
20
+ })
21
+ .catch(convertErrorToStandard.convertErrorToStandard);
19
22
  return [
20
23
  {
21
24
  signedTransaction: utils.uint8ArrayFromBase64(signedTransaction),