@portal-hq/web 2.0.1 → 3.0.1

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.
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import { PortalMpcError } from './errors';
11
11
  import { BackupMethods } from '../index';
12
- const WEB_SDK_VERSION = '2.0.1';
12
+ const WEB_SDK_VERSION = '3.0.1';
13
13
  class Mpc {
14
14
  constructor({ portal }) {
15
15
  this.configureIframe = () => {
@@ -18,11 +18,9 @@ class Mpc {
18
18
  authToken: this.portal.authToken,
19
19
  authUrl: this.portal.authUrl,
20
20
  autoApprove: this.portal.autoApprove,
21
- chainId: this.portal.chainId,
22
21
  gdrive: this.portal.gDriveConfig,
23
22
  passkey: this.portal.passkeyConfig,
24
23
  host: this.portal.host,
25
- rpcUrl: this.portal.getRpcUrl(),
26
24
  mpcHost: this.portal.mpcHost,
27
25
  mpcVersion: this.portal.mpcVersion,
28
26
  featureFlags: this.portal.featureFlags,
@@ -258,7 +256,7 @@ class Mpc {
258
256
  return __awaiter(this, void 0, void 0, function* () {
259
257
  return new Promise((resolve, reject) => {
260
258
  const handleEject = (message) => {
261
- const { type, data } = message.data;
259
+ const { type, data: result } = message.data;
262
260
  const { origin } = message;
263
261
  // ignore any broadcast postMessages
264
262
  if (origin !== this.getOrigin()) {
@@ -267,12 +265,12 @@ class Mpc {
267
265
  if (type === 'portal:wasm:ejectError') {
268
266
  // Remove the event listeners
269
267
  window.removeEventListener('message', handleEject);
270
- reject(new PortalMpcError(data));
268
+ reject(new PortalMpcError(result));
271
269
  }
272
270
  else if (type === 'portal:wasm:ejectResult') {
273
271
  // Remove the event listeners
274
272
  window.removeEventListener('message', handleEject);
275
- resolve(data);
273
+ resolve(result);
276
274
  }
277
275
  };
278
276
  window.addEventListener('message', handleEject);
@@ -287,10 +285,6 @@ class Mpc {
287
285
  // Noop
288
286
  }) {
289
287
  return __awaiter(this, void 0, void 0, function* () {
290
- const message = {
291
- type: 'portal:wasm:sign',
292
- data,
293
- };
294
288
  return new Promise((resolve, reject) => {
295
289
  // Create a function to be bound when sign is triggered
296
290
  const handleSign = (event) => {
@@ -330,7 +324,43 @@ class Mpc {
330
324
  window.addEventListener('message', handleSign);
331
325
  window.addEventListener('message', handleProgress);
332
326
  // Send the request to the iframe
333
- this.postMessage(message);
327
+ this.postMessage({
328
+ type: 'portal:wasm:sign',
329
+ data,
330
+ });
331
+ });
332
+ });
333
+ }
334
+ checkSharesOnDevice() {
335
+ return __awaiter(this, void 0, void 0, function* () {
336
+ return new Promise((resolve, reject) => {
337
+ const handleCheckSharesOnDevice = (event) => {
338
+ const { type, data } = event.data;
339
+ const { origin } = event;
340
+ // ignore any broadcast postMessages
341
+ if (origin !== this.getOrigin()) {
342
+ return;
343
+ }
344
+ if (type === 'portal:checkSharesOnDeviceError') {
345
+ // Remove the event listener
346
+ window.removeEventListener('message', handleCheckSharesOnDevice);
347
+ // Reject the promise with the error
348
+ return reject(new PortalMpcError(data));
349
+ }
350
+ else if (type === 'portal:checkSharesOnDeviceResult') {
351
+ // Remove the event listener
352
+ window.removeEventListener('message', handleCheckSharesOnDevice);
353
+ // Resolve the promise with the result
354
+ resolve(data);
355
+ }
356
+ };
357
+ // Bind the function to the message event
358
+ window.addEventListener('message', handleCheckSharesOnDevice);
359
+ // Send the request to the iframe
360
+ this.postMessage({
361
+ type: 'portal:checkSharesOnDevice',
362
+ data: {},
363
+ });
334
364
  });
335
365
  });
336
366
  }
@@ -509,7 +539,7 @@ class Mpc {
509
539
  });
510
540
  });
511
541
  }
512
- getTransactions(limit, offset, order, chainId) {
542
+ getTransactions(chainId, limit, offset, order) {
513
543
  return __awaiter(this, void 0, void 0, function* () {
514
544
  return new Promise((resolve, reject) => {
515
545
  const handleGetTransactions = (event) => {
@@ -538,10 +568,10 @@ class Mpc {
538
568
  this.postMessage({
539
569
  type: 'portal:getTransactions',
540
570
  data: {
571
+ chainId,
541
572
  limit,
542
573
  offset,
543
574
  order,
544
- chainId,
545
575
  },
546
576
  });
547
577
  });
@@ -652,72 +682,6 @@ class Mpc {
652
682
  });
653
683
  });
654
684
  }
655
- getBackupShareMetadata() {
656
- return __awaiter(this, void 0, void 0, function* () {
657
- return new Promise((resolve, reject) => {
658
- const handleGetBackupShareMetadata = (event) => {
659
- const { type, data } = event.data;
660
- const { origin } = event;
661
- // ignore any broadcast postMessages
662
- if (origin !== this.getOrigin()) {
663
- return;
664
- }
665
- if (type === 'portal:getBackupShareMetadataError') {
666
- // Remove the event listener
667
- window.removeEventListener('message', handleGetBackupShareMetadata);
668
- // Reject the promise with the error
669
- return reject(new PortalMpcError(data));
670
- }
671
- else if (type === 'portal:getBackupShareMetadataResult') {
672
- // Remove the event listener
673
- window.removeEventListener('message', handleGetBackupShareMetadata);
674
- // Resolve the promise with the result
675
- resolve(data);
676
- }
677
- };
678
- // Bind the function to the message event
679
- window.addEventListener('message', handleGetBackupShareMetadata);
680
- // Send the request to the iframe
681
- this.postMessage({
682
- type: 'portal:getBackupShareMetadata',
683
- data: {},
684
- });
685
- });
686
- });
687
- }
688
- getSigningShareMetadata() {
689
- return __awaiter(this, void 0, void 0, function* () {
690
- return new Promise((resolve, reject) => {
691
- const handleGetSigningShareMetadata = (event) => {
692
- const { type, data } = event.data;
693
- const { origin } = event;
694
- // ignore any broadcast postMessages
695
- if (origin !== this.getOrigin()) {
696
- return;
697
- }
698
- if (type === 'portal:getSigningShareMetadataError') {
699
- // Remove the event listener
700
- window.removeEventListener('message', handleGetSigningShareMetadata);
701
- // Reject the promise with the error
702
- return reject(new PortalMpcError(data));
703
- }
704
- else if (type === 'portal:getSigningShareMetadataResult') {
705
- // Remove the event listener
706
- window.removeEventListener('message', handleGetSigningShareMetadata);
707
- // Resolve the promise with the result
708
- resolve(data);
709
- }
710
- };
711
- // Bind the function to the message event
712
- window.addEventListener('message', handleGetSigningShareMetadata);
713
- // Send the request to the iframe
714
- this.postMessage({
715
- type: 'portal:getSigningShareMetadata',
716
- data: {},
717
- });
718
- });
719
- });
720
- }
721
685
  /***************************
722
686
  * Private Methods
723
687
  ***************************/
@@ -23,9 +23,29 @@ const signerMethods = [
23
23
  'eth_signTypedData_v3',
24
24
  'eth_signTypedData_v4',
25
25
  'personal_sign',
26
+ 'sol_signAndConfirmTransaction',
27
+ 'sol_signAndSendTransaction',
28
+ 'sol_signMessage',
29
+ 'sol_signTransaction',
26
30
  ];
27
31
  class Provider {
28
32
  constructor({ portal }) {
33
+ this.enforceEip155ChainId = (chainId) => {
34
+ if (!chainId) {
35
+ throw new Error('[PortalProvider] Chain ID is required for the operation');
36
+ }
37
+ if (!chainId.startsWith('eip155:')) {
38
+ throw new Error(`[PortalProvider] Chain ID must be prefixed with "eip155:" for the operation, got ${chainId}`);
39
+ }
40
+ };
41
+ this.enforceSolanaChainId = (chainId) => {
42
+ if (!chainId) {
43
+ throw new Error('[PortalProvider] Chain ID is required for the operation');
44
+ }
45
+ if (!chainId.startsWith('solana:')) {
46
+ throw new Error(`[PortalProvider] Chain ID must be prefixed with "solana:" for the operation, got ${chainId}`);
47
+ }
48
+ };
29
49
  this.buildParams = (method, txParams) => {
30
50
  let params = txParams;
31
51
  switch (method) {
@@ -33,6 +53,10 @@ class Provider {
33
53
  case 'personal_sign':
34
54
  case 'eth_signTypedData_v3':
35
55
  case 'eth_signTypedData_v4':
56
+ case 'sol_signAndConfirmTransaction':
57
+ case 'sol_signAndSendTransaction':
58
+ case 'sol_signMessage':
59
+ case 'sol_signTransaction':
36
60
  if (!Array.isArray(txParams)) {
37
61
  params = [txParams];
38
62
  }
@@ -110,9 +134,6 @@ class Provider {
110
134
  */
111
135
  request({ chainId, method, params, }) {
112
136
  return __awaiter(this, void 0, void 0, function* () {
113
- if (method === 'eth_chainId') {
114
- return chainId ? parseInt(chainId.split(':')[1]) : this.portal.chainId;
115
- }
116
137
  const isSignerMethod = signerMethods.includes(method);
117
138
  if (!isSignerMethod && !method.startsWith('wallet_')) {
118
139
  // Send to Gateway for RPC calls
@@ -223,16 +244,21 @@ class Provider {
223
244
  */
224
245
  handleGatewayRequest({ chainId, method, params, }) {
225
246
  return __awaiter(this, void 0, void 0, function* () {
226
- // Pass request off to the gateway
227
- const result = yield fetch(this.portal.getRpcUrl(), {
247
+ // Prepare the request body
248
+ const requestBody = {
228
249
  body: JSON.stringify({
229
250
  jsonrpc: '2.0',
230
- id: chainId ? parseInt(chainId.split(':')[1]) : this.portal.chainId,
251
+ id: '0',
231
252
  method,
232
253
  params,
233
254
  }),
234
255
  method: 'POST',
235
- });
256
+ headers: {
257
+ 'Content-Type': 'application/json',
258
+ },
259
+ };
260
+ // Pass request off to the gateway
261
+ const result = yield fetch(this.portal.getRpcUrl(chainId), requestBody);
236
262
  return result.json();
237
263
  });
238
264
  }
@@ -252,24 +278,41 @@ class Provider {
252
278
  return;
253
279
  }
254
280
  switch (method) {
255
- case 'eth_chainId':
256
- return `0x${this.portal.chainId.toString(16)}`;
281
+ case 'eth_chainId': {
282
+ this.enforceEip155ChainId(chainId);
283
+ const chainReferenceId = parseInt(chainId.split(':')[1]);
284
+ return `0x${chainReferenceId.toString(16)}`;
285
+ }
257
286
  case 'eth_accounts':
258
- case 'eth_requestAccounts':
287
+ case 'eth_requestAccounts': {
288
+ this.enforceEip155ChainId(chainId);
259
289
  return [this.portal.address];
290
+ }
260
291
  case 'eth_sendTransaction':
261
292
  case 'eth_sign':
262
293
  case 'eth_signTransaction':
263
294
  case 'eth_signTypedData_v3':
264
295
  case 'eth_signTypedData_v4':
265
296
  case 'personal_sign': {
297
+ this.enforceEip155ChainId(chainId);
298
+ const result = yield this.portal.mpc.sign({
299
+ chainId: chainId,
300
+ method,
301
+ params: this.buildParams(method, params),
302
+ rpcUrl: this.portal.getRpcUrl(chainId),
303
+ });
304
+ return result;
305
+ }
306
+ case 'sol_signAndConfirmTransaction':
307
+ case 'sol_signAndSendTransaction':
308
+ case 'sol_signMessage':
309
+ case 'sol_signTransaction': {
310
+ this.enforceSolanaChainId(chainId);
266
311
  const result = yield this.portal.mpc.sign({
267
- chainId: chainId
268
- ? chainId.split(':')[1]
269
- : this.portal.chainId.toString(),
312
+ chainId: chainId,
270
313
  method,
271
314
  params: this.buildParams(method, params),
272
- rpcUrl: this.portal.getRpcUrl(),
315
+ rpcUrl: this.portal.getRpcUrl(chainId),
273
316
  });
274
317
  return result;
275
318
  }
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Portal MPC Support for Web",
4
4
  "author": "Portal Labs, Inc.",
5
5
  "homepage": "https://portalhq.io/",
6
- "version": "2.0.1",
6
+ "version": "3.0.1",
7
7
  "license": "MIT",
8
8
  "main": "lib/commonjs/index",
9
9
  "module": "lib/esm/index",
@@ -45,5 +45,8 @@
45
45
  "typescript": "^4.8.4",
46
46
  "webpack": "^5.87.0",
47
47
  "webpack-cli": "^5.1.4"
48
+ },
49
+ "dependencies": {
50
+ "@solana/web3.js": "^1.91.8"
48
51
  }
49
52
  }