@portal-hq/provider 1.0.5 → 1.1.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.
@@ -29,10 +29,10 @@ const signerMethods = [
29
29
  ];
30
30
  class Provider {
31
31
  constructor({
32
- // Required options
33
- apiKey, chainId, keychain,
34
- // Optional options
35
- apiUrl = 'api.portalhq.io', autoApprove = false, mpcUrl = 'mpc.portalhq.io', mpcVersion = 'v4', gatewayConfig = {}, }) {
32
+ // Required
33
+ apiKey, chainId, keychain, gatewayConfig,
34
+ // Optional
35
+ isSimulator = false, autoApprove = false, apiHost = 'api.portalhq.io', mpcHost = 'mpc.portalhq.io', version = 'v4', }) {
36
36
  // Handle required fields
37
37
  if (!apiKey || apiKey.length === 0) {
38
38
  throw new utils_1.InvalidApiKeyError();
@@ -45,39 +45,37 @@ class Provider {
45
45
  }
46
46
  // Handle the stuff we can auto-set
47
47
  this.apiKey = apiKey;
48
- this.apiUrl = apiUrl;
49
48
  this.autoApprove = autoApprove;
50
49
  this.chainId = chainId;
51
- this.connected = false;
52
50
  this.events = {};
53
51
  this.gatewayConfig = gatewayConfig;
54
- this.isMPC = true;
52
+ this.isSimulator = isSimulator;
55
53
  this.keychain = keychain;
56
- this.mpcUrl = mpcUrl;
57
- this.rpcUrl = this.getRpcUrl();
58
- this.mpcVersion = mpcVersion;
59
54
  // Add a logger
60
55
  this.log = console;
61
56
  // Initialize Portal API HttpRequester
62
- this.portal = new utils_1.HttpRequester({
63
- baseUrl: this.apiUrl,
57
+ this.portalApi = new utils_1.HttpRequester({
58
+ baseUrl: apiHost.startsWith('localhost')
59
+ ? `http://${apiHost}`
60
+ : `https://${apiHost}`,
64
61
  });
65
62
  // Initialize Gateway HttpRequester
66
- this.rpc = new utils_1.HttpRequester({
67
- baseUrl: this.rpcUrl,
63
+ this.gateway = new utils_1.HttpRequester({
64
+ baseUrl: this.getGatewayUrl(),
68
65
  });
69
66
  // Initialize an MpcSigner
70
67
  this.signer = new signers_1.MpcSigner({
71
- mpcUrl: this.mpcUrl,
72
- keychain: this.keychain,
73
- mpcVersion: mpcVersion,
74
- });
75
- this.signer.getAddress().then((address) => {
76
- if (typeof address !== 'undefined' && address.length) {
77
- this.address = address;
78
- }
68
+ mpcHost: mpcHost,
69
+ keychain: keychain,
70
+ version: version,
79
71
  });
80
72
  }
73
+ get address() {
74
+ return this.keychain.getAddress(this.isSimulator);
75
+ }
76
+ get gatewayUrl() {
77
+ return this.getGatewayUrl();
78
+ }
81
79
  /**
82
80
  * Invokes all registered event handlers with the data provided
83
81
  * - If any `once` handlers exist, they are removed after all handlers are invoked
@@ -102,7 +100,7 @@ class Provider {
102
100
  *
103
101
  * @returns string
104
102
  */
105
- getRpcUrl() {
103
+ getGatewayUrl() {
106
104
  if (typeof this.gatewayConfig === 'string') {
107
105
  // If the gatewayConfig is just a static URL, return that
108
106
  return this.gatewayConfig;
@@ -183,7 +181,7 @@ class Provider {
183
181
  * @param args The arguments of the request being made
184
182
  * @returns Promise<any>
185
183
  */
186
- request({ method, params }) {
184
+ request({ method, params, connect, }) {
187
185
  return __awaiter(this, void 0, void 0, function* () {
188
186
  if (method === 'eth_chainId') {
189
187
  return this.chainId;
@@ -208,6 +206,7 @@ class Provider {
208
206
  const transactionHash = yield this.handleSigningRequests({
209
207
  method,
210
208
  params,
209
+ connect,
211
210
  });
212
211
  if (transactionHash) {
213
212
  this.emit('portal_signatureReceived', {
@@ -231,33 +230,30 @@ class Provider {
231
230
  return result;
232
231
  });
233
232
  }
234
- _setAddress(address) {
235
- this.address = address;
236
- if (!this.connected) {
237
- this.dispatchConnect();
238
- }
239
- }
240
233
  /**
241
234
  * Updates the chainId of this instance and builds a new RPC HttpRequester for
242
235
  * the gateway used for the new chain
243
236
  *
244
- * @param chainId A hex string of the chainId to use for this connection
237
+ * @param chainId The numerical ID of the chain to switch to
245
238
  * @returns BaseProvider
246
239
  */
247
- setChainId(chainId) {
240
+ setChainId(chainId, connect) {
248
241
  return __awaiter(this, void 0, void 0, function* () {
249
- // Disconnect from the current chain
250
- this.connected = false;
251
242
  // Update the chainId
252
- this.chainId = Number(`${chainId}`);
243
+ this.chainId = chainId;
253
244
  // Re-initialize the Gateway HttpRequester
254
- this.rpc = new utils_1.HttpRequester({
255
- baseUrl: this.getRpcUrl(),
245
+ this.gateway = new utils_1.HttpRequester({
246
+ baseUrl: this.getGatewayUrl(),
256
247
  });
257
248
  // Emit event for update
258
249
  this.emit('chainChanged', {
259
250
  chainId: this.chainId,
260
251
  });
252
+ if (connect) {
253
+ connect.emit('portalConnect_chainChanged', {
254
+ chainId: this.chainId,
255
+ });
256
+ }
261
257
  // Dispatch 'connect' event
262
258
  this.dispatchConnect();
263
259
  return this;
@@ -268,15 +264,15 @@ class Provider {
268
264
  *
269
265
  * @param args The arguments of the request being made
270
266
  */
271
- getApproval({ method, params, }) {
267
+ getApproval({ method, params, connect, }) {
272
268
  return __awaiter(this, void 0, void 0, function* () {
273
269
  // If autoApprove is enabled, just resolve to true
274
270
  if (this.autoApprove) {
275
271
  return true;
276
272
  }
277
273
  const signingHandlers = this.events['portal_signingRequested'];
278
- if (!signingHandlers || signingHandlers.length === 0) {
279
- throw new Error(`[PortalProvider] Auto-approve is disabled. Cannot perform signing requests without an event handler for the 'portal_signingRequested' event.`);
274
+ if (!connect && (!signingHandlers || signingHandlers.length === 0)) {
275
+ throw new Error(`[PortalProvider] Auto-approve is disabled. Cannot perform Provider signing requests without an event handler for the 'portal_signingRequested' event.`);
280
276
  }
281
277
  return new Promise((resolve) => {
282
278
  // Remove already used listeners
@@ -305,16 +301,23 @@ class Provider {
305
301
  }
306
302
  });
307
303
  // Tell any listening clients that signing has been requested
308
- this.emit('portal_signingRequested', {
309
- method,
310
- params,
311
- });
304
+ if (connect) {
305
+ connect.emit('portalConnect_signingRequested', {
306
+ method,
307
+ params,
308
+ });
309
+ }
310
+ else {
311
+ this.emit('portal_signingRequested', {
312
+ method,
313
+ params,
314
+ });
315
+ }
312
316
  });
313
317
  });
314
318
  }
315
319
  dispatchConnect() {
316
320
  return __awaiter(this, void 0, void 0, function* () {
317
- this.connected = true;
318
321
  this.emit('connect', {
319
322
  chainId: `0x${this.chainId.toString(16)}`,
320
323
  });
@@ -329,7 +332,7 @@ class Provider {
329
332
  handleGatewayRequests({ method, params, }) {
330
333
  return __awaiter(this, void 0, void 0, function* () {
331
334
  // Pass request off to the gateway
332
- return yield this.rpc.post('', {
335
+ return yield this.gateway.post('', {
333
336
  body: {
334
337
  jsonrpc: '2.0',
335
338
  id: this.chainId,
@@ -345,12 +348,12 @@ class Provider {
345
348
  * @param args The arguments of the request being made
346
349
  * @returns Promise<any>
347
350
  */
348
- handleSigningRequests({ method, params, }) {
351
+ handleSigningRequests({ method, params, connect, }) {
349
352
  var _a;
350
353
  return __awaiter(this, void 0, void 0, function* () {
351
354
  const isApproved = passiveSignerMethods.includes(method)
352
355
  ? true
353
- : yield this.getApproval({ method, params });
356
+ : yield this.getApproval({ method, params, connect });
354
357
  if (!isApproved) {
355
358
  this.log.info(`[PortalProvider] Request for signing method '${method}' could not be completed because it was not approved by the user.`);
356
359
  return;
@@ -369,7 +372,7 @@ class Provider {
369
372
  const result = yield ((_a = this.signer) === null || _a === void 0 ? void 0 : _a.sign({ chainId: this.chainId, method, params }, this));
370
373
  if (result) {
371
374
  try {
372
- yield this.portal.post('/api/v1/analytics/track', {
375
+ yield this.portalApi.post('/api/v1/analytics/track', {
373
376
  headers: {
374
377
  Authentication: `Bearer ${this.apiKey}`,
375
378
  },
@@ -10,11 +10,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  class Signer {
13
- getAddress() {
14
- return __awaiter(this, void 0, void 0, function* () {
15
- throw new Error(`[Portal] getAddress() method must be implemented as a subclass of Signer`);
16
- });
17
- }
18
13
  sign(_, __) {
19
14
  return __awaiter(this, void 0, void 0, function* () {
20
15
  throw new Error('[Portal] sign() method must be implemented in a subclass of Signer');
@@ -12,8 +12,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  const react_native_1 = require("react-native");
13
13
  const utils_1 = require("@portal-hq/utils");
14
14
  class MpcSigner {
15
- constructor({ keychain, mpcUrl, mpcVersion = 'v4' }) {
16
- this.mpcVersion = 'v4';
15
+ constructor({ keychain, isSimulator = false, mpcHost = 'mpc.portalhq.io', version = 'v4', }) {
16
+ this.version = 'v4';
17
17
  this.buildParams = (method, txParams) => {
18
18
  let params = txParams;
19
19
  switch (method) {
@@ -32,29 +32,24 @@ class MpcSigner {
32
32
  }
33
33
  return params;
34
34
  };
35
+ this.isSimulator = isSimulator;
35
36
  this.keychain = keychain;
36
37
  this.mpc = react_native_1.NativeModules.PortalMobileMpc;
37
- this.mpcUrl = mpcUrl;
38
- this.mpcVersion = mpcVersion;
38
+ this.mpcHost = mpcHost;
39
+ this.version = version;
39
40
  if (!this.mpc) {
40
41
  throw new Error(`[Portal.Provider.MpcSigner] The MPC module could not be found by the signer. This is usually an issue with React Native linking. Please verify that the 'PortalReactNative' module is properly linked to this project.`);
41
42
  }
42
43
  }
43
- getAddress() {
44
- return __awaiter(this, void 0, void 0, function* () {
45
- if (this.address) {
46
- return this.address;
47
- }
48
- const address = yield this.keychain.getAddress();
49
- if (typeof address !== 'undefined' && address.length) {
50
- this.address = address;
51
- }
52
- return address;
53
- });
44
+ get address() {
45
+ return this.keychain.getAddress(this.isSimulator);
46
+ }
47
+ get signingShare() {
48
+ return this.keychain.getDkgResult(this.isSimulator);
54
49
  }
55
50
  sign(message, provider) {
56
51
  return __awaiter(this, void 0, void 0, function* () {
57
- const address = yield this.keychain.getAddress();
52
+ const address = yield this.address;
58
53
  const apiKey = provider.apiKey;
59
54
  const { method, params } = message;
60
55
  switch (method) {
@@ -65,8 +60,8 @@ class MpcSigner {
65
60
  default:
66
61
  break;
67
62
  }
68
- const dkg = yield this.keychain.getDkgResult();
69
- const result = yield this.mpc.sign(apiKey, this.mpcUrl, dkg, message.method, JSON.stringify(this.buildParams(method, params)), provider.rpcUrl, provider.chainId.toString(), this.mpcVersion);
63
+ const signingShare = yield this.signingShare;
64
+ const result = yield this.mpc.sign(apiKey, this.mpcHost, signingShare, message.method, JSON.stringify(this.buildParams(method, params)), provider.gatewayUrl, provider.chainId.toString(), this.version);
70
65
  const { data, error } = JSON.parse(String(result));
71
66
  if (error && error.code > 0) {
72
67
  throw new utils_1.PortalMpcError(error);
@@ -27,10 +27,10 @@ const signerMethods = [
27
27
  ];
28
28
  class Provider {
29
29
  constructor({
30
- // Required options
31
- apiKey, chainId, keychain,
32
- // Optional options
33
- apiUrl = 'api.portalhq.io', autoApprove = false, mpcUrl = 'mpc.portalhq.io', mpcVersion = 'v4', gatewayConfig = {}, }) {
30
+ // Required
31
+ apiKey, chainId, keychain, gatewayConfig,
32
+ // Optional
33
+ isSimulator = false, autoApprove = false, apiHost = 'api.portalhq.io', mpcHost = 'mpc.portalhq.io', version = 'v4', }) {
34
34
  // Handle required fields
35
35
  if (!apiKey || apiKey.length === 0) {
36
36
  throw new InvalidApiKeyError();
@@ -43,39 +43,37 @@ class Provider {
43
43
  }
44
44
  // Handle the stuff we can auto-set
45
45
  this.apiKey = apiKey;
46
- this.apiUrl = apiUrl;
47
46
  this.autoApprove = autoApprove;
48
47
  this.chainId = chainId;
49
- this.connected = false;
50
48
  this.events = {};
51
49
  this.gatewayConfig = gatewayConfig;
52
- this.isMPC = true;
50
+ this.isSimulator = isSimulator;
53
51
  this.keychain = keychain;
54
- this.mpcUrl = mpcUrl;
55
- this.rpcUrl = this.getRpcUrl();
56
- this.mpcVersion = mpcVersion;
57
52
  // Add a logger
58
53
  this.log = console;
59
54
  // Initialize Portal API HttpRequester
60
- this.portal = new HttpRequester({
61
- baseUrl: this.apiUrl,
55
+ this.portalApi = new HttpRequester({
56
+ baseUrl: apiHost.startsWith('localhost')
57
+ ? `http://${apiHost}`
58
+ : `https://${apiHost}`,
62
59
  });
63
60
  // Initialize Gateway HttpRequester
64
- this.rpc = new HttpRequester({
65
- baseUrl: this.rpcUrl,
61
+ this.gateway = new HttpRequester({
62
+ baseUrl: this.getGatewayUrl(),
66
63
  });
67
64
  // Initialize an MpcSigner
68
65
  this.signer = new MpcSigner({
69
- mpcUrl: this.mpcUrl,
70
- keychain: this.keychain,
71
- mpcVersion: mpcVersion,
72
- });
73
- this.signer.getAddress().then((address) => {
74
- if (typeof address !== 'undefined' && address.length) {
75
- this.address = address;
76
- }
66
+ mpcHost: mpcHost,
67
+ keychain: keychain,
68
+ version: version,
77
69
  });
78
70
  }
71
+ get address() {
72
+ return this.keychain.getAddress(this.isSimulator);
73
+ }
74
+ get gatewayUrl() {
75
+ return this.getGatewayUrl();
76
+ }
79
77
  /**
80
78
  * Invokes all registered event handlers with the data provided
81
79
  * - If any `once` handlers exist, they are removed after all handlers are invoked
@@ -100,7 +98,7 @@ class Provider {
100
98
  *
101
99
  * @returns string
102
100
  */
103
- getRpcUrl() {
101
+ getGatewayUrl() {
104
102
  if (typeof this.gatewayConfig === 'string') {
105
103
  // If the gatewayConfig is just a static URL, return that
106
104
  return this.gatewayConfig;
@@ -181,7 +179,7 @@ class Provider {
181
179
  * @param args The arguments of the request being made
182
180
  * @returns Promise<any>
183
181
  */
184
- request({ method, params }) {
182
+ request({ method, params, connect, }) {
185
183
  return __awaiter(this, void 0, void 0, function* () {
186
184
  if (method === 'eth_chainId') {
187
185
  return this.chainId;
@@ -206,6 +204,7 @@ class Provider {
206
204
  const transactionHash = yield this.handleSigningRequests({
207
205
  method,
208
206
  params,
207
+ connect,
209
208
  });
210
209
  if (transactionHash) {
211
210
  this.emit('portal_signatureReceived', {
@@ -229,33 +228,30 @@ class Provider {
229
228
  return result;
230
229
  });
231
230
  }
232
- _setAddress(address) {
233
- this.address = address;
234
- if (!this.connected) {
235
- this.dispatchConnect();
236
- }
237
- }
238
231
  /**
239
232
  * Updates the chainId of this instance and builds a new RPC HttpRequester for
240
233
  * the gateway used for the new chain
241
234
  *
242
- * @param chainId A hex string of the chainId to use for this connection
235
+ * @param chainId The numerical ID of the chain to switch to
243
236
  * @returns BaseProvider
244
237
  */
245
- setChainId(chainId) {
238
+ setChainId(chainId, connect) {
246
239
  return __awaiter(this, void 0, void 0, function* () {
247
- // Disconnect from the current chain
248
- this.connected = false;
249
240
  // Update the chainId
250
- this.chainId = Number(`${chainId}`);
241
+ this.chainId = chainId;
251
242
  // Re-initialize the Gateway HttpRequester
252
- this.rpc = new HttpRequester({
253
- baseUrl: this.getRpcUrl(),
243
+ this.gateway = new HttpRequester({
244
+ baseUrl: this.getGatewayUrl(),
254
245
  });
255
246
  // Emit event for update
256
247
  this.emit('chainChanged', {
257
248
  chainId: this.chainId,
258
249
  });
250
+ if (connect) {
251
+ connect.emit('portalConnect_chainChanged', {
252
+ chainId: this.chainId,
253
+ });
254
+ }
259
255
  // Dispatch 'connect' event
260
256
  this.dispatchConnect();
261
257
  return this;
@@ -266,15 +262,15 @@ class Provider {
266
262
  *
267
263
  * @param args The arguments of the request being made
268
264
  */
269
- getApproval({ method, params, }) {
265
+ getApproval({ method, params, connect, }) {
270
266
  return __awaiter(this, void 0, void 0, function* () {
271
267
  // If autoApprove is enabled, just resolve to true
272
268
  if (this.autoApprove) {
273
269
  return true;
274
270
  }
275
271
  const signingHandlers = this.events['portal_signingRequested'];
276
- if (!signingHandlers || signingHandlers.length === 0) {
277
- throw new Error(`[PortalProvider] Auto-approve is disabled. Cannot perform signing requests without an event handler for the 'portal_signingRequested' event.`);
272
+ if (!connect && (!signingHandlers || signingHandlers.length === 0)) {
273
+ throw new Error(`[PortalProvider] Auto-approve is disabled. Cannot perform Provider signing requests without an event handler for the 'portal_signingRequested' event.`);
278
274
  }
279
275
  return new Promise((resolve) => {
280
276
  // Remove already used listeners
@@ -303,16 +299,23 @@ class Provider {
303
299
  }
304
300
  });
305
301
  // Tell any listening clients that signing has been requested
306
- this.emit('portal_signingRequested', {
307
- method,
308
- params,
309
- });
302
+ if (connect) {
303
+ connect.emit('portalConnect_signingRequested', {
304
+ method,
305
+ params,
306
+ });
307
+ }
308
+ else {
309
+ this.emit('portal_signingRequested', {
310
+ method,
311
+ params,
312
+ });
313
+ }
310
314
  });
311
315
  });
312
316
  }
313
317
  dispatchConnect() {
314
318
  return __awaiter(this, void 0, void 0, function* () {
315
- this.connected = true;
316
319
  this.emit('connect', {
317
320
  chainId: `0x${this.chainId.toString(16)}`,
318
321
  });
@@ -327,7 +330,7 @@ class Provider {
327
330
  handleGatewayRequests({ method, params, }) {
328
331
  return __awaiter(this, void 0, void 0, function* () {
329
332
  // Pass request off to the gateway
330
- return yield this.rpc.post('', {
333
+ return yield this.gateway.post('', {
331
334
  body: {
332
335
  jsonrpc: '2.0',
333
336
  id: this.chainId,
@@ -343,12 +346,12 @@ class Provider {
343
346
  * @param args The arguments of the request being made
344
347
  * @returns Promise<any>
345
348
  */
346
- handleSigningRequests({ method, params, }) {
349
+ handleSigningRequests({ method, params, connect, }) {
347
350
  var _a;
348
351
  return __awaiter(this, void 0, void 0, function* () {
349
352
  const isApproved = passiveSignerMethods.includes(method)
350
353
  ? true
351
- : yield this.getApproval({ method, params });
354
+ : yield this.getApproval({ method, params, connect });
352
355
  if (!isApproved) {
353
356
  this.log.info(`[PortalProvider] Request for signing method '${method}' could not be completed because it was not approved by the user.`);
354
357
  return;
@@ -367,7 +370,7 @@ class Provider {
367
370
  const result = yield ((_a = this.signer) === null || _a === void 0 ? void 0 : _a.sign({ chainId: this.chainId, method, params }, this));
368
371
  if (result) {
369
372
  try {
370
- yield this.portal.post('/api/v1/analytics/track', {
373
+ yield this.portalApi.post('/api/v1/analytics/track', {
371
374
  headers: {
372
375
  Authentication: `Bearer ${this.apiKey}`,
373
376
  },
@@ -8,11 +8,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  class Signer {
11
- getAddress() {
12
- return __awaiter(this, void 0, void 0, function* () {
13
- throw new Error(`[Portal] getAddress() method must be implemented as a subclass of Signer`);
14
- });
15
- }
16
11
  sign(_, __) {
17
12
  return __awaiter(this, void 0, void 0, function* () {
18
13
  throw new Error('[Portal] sign() method must be implemented in a subclass of Signer');
@@ -10,8 +10,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  import { NativeModules } from 'react-native';
11
11
  import { PortalMpcError, } from '@portal-hq/utils';
12
12
  class MpcSigner {
13
- constructor({ keychain, mpcUrl, mpcVersion = 'v4' }) {
14
- this.mpcVersion = 'v4';
13
+ constructor({ keychain, isSimulator = false, mpcHost = 'mpc.portalhq.io', version = 'v4', }) {
14
+ this.version = 'v4';
15
15
  this.buildParams = (method, txParams) => {
16
16
  let params = txParams;
17
17
  switch (method) {
@@ -30,29 +30,24 @@ class MpcSigner {
30
30
  }
31
31
  return params;
32
32
  };
33
+ this.isSimulator = isSimulator;
33
34
  this.keychain = keychain;
34
35
  this.mpc = NativeModules.PortalMobileMpc;
35
- this.mpcUrl = mpcUrl;
36
- this.mpcVersion = mpcVersion;
36
+ this.mpcHost = mpcHost;
37
+ this.version = version;
37
38
  if (!this.mpc) {
38
39
  throw new Error(`[Portal.Provider.MpcSigner] The MPC module could not be found by the signer. This is usually an issue with React Native linking. Please verify that the 'PortalReactNative' module is properly linked to this project.`);
39
40
  }
40
41
  }
41
- getAddress() {
42
- return __awaiter(this, void 0, void 0, function* () {
43
- if (this.address) {
44
- return this.address;
45
- }
46
- const address = yield this.keychain.getAddress();
47
- if (typeof address !== 'undefined' && address.length) {
48
- this.address = address;
49
- }
50
- return address;
51
- });
42
+ get address() {
43
+ return this.keychain.getAddress(this.isSimulator);
44
+ }
45
+ get signingShare() {
46
+ return this.keychain.getDkgResult(this.isSimulator);
52
47
  }
53
48
  sign(message, provider) {
54
49
  return __awaiter(this, void 0, void 0, function* () {
55
- const address = yield this.keychain.getAddress();
50
+ const address = yield this.address;
56
51
  const apiKey = provider.apiKey;
57
52
  const { method, params } = message;
58
53
  switch (method) {
@@ -63,8 +58,8 @@ class MpcSigner {
63
58
  default:
64
59
  break;
65
60
  }
66
- const dkg = yield this.keychain.getDkgResult();
67
- const result = yield this.mpc.sign(apiKey, this.mpcUrl, dkg, message.method, JSON.stringify(this.buildParams(method, params)), provider.rpcUrl, provider.chainId.toString(), this.mpcVersion);
61
+ const signingShare = yield this.signingShare;
62
+ const result = yield this.mpc.sign(apiKey, this.mpcHost, signingShare, message.method, JSON.stringify(this.buildParams(method, params)), provider.gatewayUrl, provider.chainId.toString(), this.version);
68
63
  const { data, error } = JSON.parse(String(result));
69
64
  if (error && error.code > 0) {
70
65
  throw new PortalMpcError(error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@portal-hq/provider",
3
- "version": "1.0.5",
3
+ "version": "1.1.1",
4
4
  "license": "MIT",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/esm/index",
@@ -19,7 +19,8 @@
19
19
  "test": "jest"
20
20
  },
21
21
  "dependencies": {
22
- "@portal-hq/utils": "^1.0.5"
22
+ "@portal-hq/connect": "^1.1.1",
23
+ "@portal-hq/utils": "^1.1.1"
23
24
  },
24
25
  "devDependencies": {
25
26
  "@babel/preset-typescript": "^7.18.6",
@@ -29,5 +30,5 @@
29
30
  "ts-jest": "^29.0.3",
30
31
  "typescript": "^4.8.4"
31
32
  },
32
- "gitHead": "acac6640bcad15621912376d95c0bd09509387e1"
33
+ "gitHead": "2ba5caccbaae676a2b207bab294bbd59cfc136ca"
33
34
  }
@@ -18,6 +18,7 @@ import {
18
18
  type RequestArguments,
19
19
  type SwitchEthereumChainParameter,
20
20
  } from '../../types'
21
+ import PortalConnect from '@portal-hq/connect'
21
22
 
22
23
  const passiveSignerMethods = [
23
24
  'eth_accounts',
@@ -38,37 +39,40 @@ const signerMethods = [
38
39
  ]
39
40
 
40
41
  class Provider {
41
- public readonly mpcUrl: string
42
- public readonly portal: HttpRequester
43
-
44
- public address?: string
45
42
  public apiKey: string
46
- public apiUrl: string
47
- public autoApprove?: boolean
43
+ public autoApprove: boolean
48
44
  public chainId: number
49
- public connected: boolean
50
- public events: Record<string, RegisteredEventHandler[]>
51
- public gatewayConfig: GatewayLike
52
- public isMPC: boolean
53
- public keychain: KeychainAdapter
54
45
  public log: Console
55
- public rpc: HttpRequester
56
- public rpcUrl: string
57
- public signer: Signer
58
- public mpcVersion: string
46
+ public gateway: HttpRequester
47
+
48
+ private events: Record<string, RegisteredEventHandler[]>
49
+ private gatewayConfig: GatewayLike
50
+ private isSimulator: boolean
51
+ private keychain: KeychainAdapter
52
+ private readonly portalApi: HttpRequester
53
+ private signer: Signer
54
+
55
+ public get address(): Promise<string | undefined> {
56
+ return this.keychain.getAddress(this.isSimulator)
57
+ }
58
+
59
+ public get gatewayUrl(): string {
60
+ return this.getGatewayUrl()
61
+ }
59
62
 
60
63
  constructor({
61
- // Required options
64
+ // Required
62
65
  apiKey,
63
66
  chainId,
64
67
  keychain,
68
+ gatewayConfig,
65
69
 
66
- // Optional options
67
- apiUrl = 'api.portalhq.io',
70
+ // Optional
71
+ isSimulator = false,
68
72
  autoApprove = false,
69
- mpcUrl = 'mpc.portalhq.io',
70
- mpcVersion = 'v4',
71
- gatewayConfig = {},
73
+ apiHost = 'api.portalhq.io',
74
+ mpcHost = 'mpc.portalhq.io',
75
+ version = 'v4',
72
76
  }: ProviderOptions) {
73
77
  // Handle required fields
74
78
  if (!apiKey || apiKey.length === 0) {
@@ -83,41 +87,33 @@ class Provider {
83
87
 
84
88
  // Handle the stuff we can auto-set
85
89
  this.apiKey = apiKey
86
- this.apiUrl = apiUrl
87
90
  this.autoApprove = autoApprove
88
91
  this.chainId = chainId
89
- this.connected = false
90
92
  this.events = {}
91
93
  this.gatewayConfig = gatewayConfig
92
- this.isMPC = true
94
+ this.isSimulator = isSimulator
93
95
  this.keychain = keychain
94
- this.mpcUrl = mpcUrl
95
- this.rpcUrl = this.getRpcUrl()
96
- this.mpcVersion = mpcVersion
96
+
97
97
  // Add a logger
98
98
  this.log = console
99
99
 
100
100
  // Initialize Portal API HttpRequester
101
- this.portal = new HttpRequester({
102
- baseUrl: this.apiUrl,
101
+ this.portalApi = new HttpRequester({
102
+ baseUrl: apiHost.startsWith('localhost')
103
+ ? `http://${apiHost}`
104
+ : `https://${apiHost}`,
103
105
  })
104
106
 
105
107
  // Initialize Gateway HttpRequester
106
- this.rpc = new HttpRequester({
107
- baseUrl: this.rpcUrl,
108
+ this.gateway = new HttpRequester({
109
+ baseUrl: this.getGatewayUrl(),
108
110
  })
109
111
 
110
112
  // Initialize an MpcSigner
111
113
  this.signer = new MpcSigner({
112
- mpcUrl: this.mpcUrl,
113
- keychain: this.keychain,
114
- mpcVersion: mpcVersion,
115
- })
116
-
117
- this.signer.getAddress().then((address) => {
118
- if (typeof address !== 'undefined' && address.length) {
119
- this.address = address
120
- }
114
+ mpcHost: mpcHost,
115
+ keychain: keychain,
116
+ version: version,
121
117
  })
122
118
  }
123
119
 
@@ -149,7 +145,7 @@ class Provider {
149
145
  *
150
146
  * @returns string
151
147
  */
152
- public getRpcUrl(): string {
148
+ public getGatewayUrl(): string {
153
149
  if (typeof this.gatewayConfig === 'string') {
154
150
  // If the gatewayConfig is just a static URL, return that
155
151
  return this.gatewayConfig
@@ -252,7 +248,11 @@ class Provider {
252
248
  * @param args The arguments of the request being made
253
249
  * @returns Promise<any>
254
250
  */
255
- public async request({ method, params }: RequestArguments): Promise<any> {
251
+ public async request({
252
+ method,
253
+ params,
254
+ connect,
255
+ }: RequestArguments): Promise<any> {
256
256
  if (method === 'eth_chainId') {
257
257
  return this.chainId
258
258
  }
@@ -280,6 +280,7 @@ class Provider {
280
280
  const transactionHash = await this.handleSigningRequests({
281
281
  method,
282
282
  params,
283
+ connect,
283
284
  })
284
285
 
285
286
  if (transactionHash) {
@@ -305,31 +306,20 @@ class Provider {
305
306
  return result
306
307
  }
307
308
 
308
- public _setAddress(address: string): void {
309
- this.address = address
310
-
311
- if (!this.connected) {
312
- this.dispatchConnect()
313
- }
314
- }
315
-
316
309
  /**
317
310
  * Updates the chainId of this instance and builds a new RPC HttpRequester for
318
311
  * the gateway used for the new chain
319
312
  *
320
- * @param chainId A hex string of the chainId to use for this connection
313
+ * @param chainId The numerical ID of the chain to switch to
321
314
  * @returns BaseProvider
322
315
  */
323
- public async setChainId(chainId: string): Promise<Provider> {
324
- // Disconnect from the current chain
325
- this.connected = false
326
-
316
+ public async setChainId(chainId: number, connect?: PortalConnect): Promise<Provider> {
327
317
  // Update the chainId
328
- this.chainId = Number(`${chainId}`)
318
+ this.chainId = chainId
329
319
 
330
320
  // Re-initialize the Gateway HttpRequester
331
- this.rpc = new HttpRequester({
332
- baseUrl: this.getRpcUrl(),
321
+ this.gateway = new HttpRequester({
322
+ baseUrl: this.getGatewayUrl(),
333
323
  })
334
324
 
335
325
  // Emit event for update
@@ -337,6 +327,12 @@ class Provider {
337
327
  chainId: this.chainId,
338
328
  } as SwitchEthereumChainParameter)
339
329
 
330
+
331
+ if (connect) {
332
+ connect.emit('portalConnect_chainChanged', {
333
+ chainId: this.chainId,
334
+ } as SwitchEthereumChainParameter)
335
+ }
340
336
  // Dispatch 'connect' event
341
337
  this.dispatchConnect()
342
338
 
@@ -351,6 +347,7 @@ class Provider {
351
347
  protected async getApproval({
352
348
  method,
353
349
  params,
350
+ connect,
354
351
  }: RequestArguments): Promise<boolean> {
355
352
  // If autoApprove is enabled, just resolve to true
356
353
  if (this.autoApprove) {
@@ -359,9 +356,9 @@ class Provider {
359
356
 
360
357
  const signingHandlers = this.events['portal_signingRequested']
361
358
 
362
- if (!signingHandlers || signingHandlers.length === 0) {
359
+ if (!connect && (!signingHandlers || signingHandlers.length === 0)) {
363
360
  throw new Error(
364
- `[PortalProvider] Auto-approve is disabled. Cannot perform signing requests without an event handler for the 'portal_signingRequested' event.`,
361
+ `[PortalProvider] Auto-approve is disabled. Cannot perform Provider signing requests without an event handler for the 'portal_signingRequested' event.`,
365
362
  )
366
363
  }
367
364
 
@@ -407,15 +404,21 @@ class Provider {
407
404
  )
408
405
 
409
406
  // Tell any listening clients that signing has been requested
410
- this.emit('portal_signingRequested', {
411
- method,
412
- params,
413
- })
407
+ if (connect) {
408
+ connect.emit('portalConnect_signingRequested', {
409
+ method,
410
+ params,
411
+ })
412
+ } else {
413
+ this.emit('portal_signingRequested', {
414
+ method,
415
+ params,
416
+ })
417
+ }
414
418
  })
415
419
  }
416
420
 
417
421
  private async dispatchConnect(): Promise<void> {
418
- this.connected = true
419
422
  this.emit('connect', {
420
423
  chainId: `0x${this.chainId.toString(16)}`,
421
424
  })
@@ -432,7 +435,7 @@ class Provider {
432
435
  params,
433
436
  }: RequestArguments): Promise<any> {
434
437
  // Pass request off to the gateway
435
- return await this.rpc.post<any>('', {
438
+ return await this.gateway.post<any>('', {
436
439
  body: {
437
440
  jsonrpc: '2.0',
438
441
  id: this.chainId,
@@ -451,10 +454,11 @@ class Provider {
451
454
  private async handleSigningRequests({
452
455
  method,
453
456
  params,
457
+ connect,
454
458
  }: RequestArguments): Promise<any> {
455
459
  const isApproved = passiveSignerMethods.includes(method)
456
460
  ? true
457
- : await this.getApproval({ method, params })
461
+ : await this.getApproval({ method, params, connect })
458
462
 
459
463
  if (!isApproved) {
460
464
  this.log.info(
@@ -481,7 +485,7 @@ class Provider {
481
485
 
482
486
  if (result) {
483
487
  try {
484
- await this.portal.post('/api/v1/analytics/track', {
488
+ await this.portalApi.post('/api/v1/analytics/track', {
485
489
  headers: {
486
490
  Authentication: `Bearer ${this.apiKey}`,
487
491
  },
@@ -2,11 +2,6 @@ import { SigningRequestArguments } from '@portal-hq/utils'
2
2
  import { type SignResult } from '../../types'
3
3
 
4
4
  abstract class Signer {
5
- public async getAddress(): Promise<string> {
6
- throw new Error(
7
- `[Portal] getAddress() method must be implemented as a subclass of Signer`,
8
- )
9
- }
10
5
  public async sign(_: SigningRequestArguments, __?: any): Promise<SignResult> {
11
6
  throw new Error(
12
7
  '[Portal] sign() method must be implemented in a subclass of Signer',
@@ -15,18 +15,31 @@ import {
15
15
  } from '../../types'
16
16
 
17
17
  class MpcSigner implements Signer {
18
+ private isSimulator: boolean
19
+ private keychain: KeychainAdapter
18
20
  private mpc: PortalMobileMpc
21
+ private mpcHost: string // should we add a default here mpc.portalhq.io
22
+ private version: string = 'v4'
19
23
 
20
- public address?: string
21
- public keychain: KeychainAdapter
22
- public mpcUrl: string // should we add a default here mpc.portalhq.io
23
- public mpcVersion: string = 'v4'
24
+ private get address(): Promise<string | undefined> {
25
+ return this.keychain.getAddress(this.isSimulator)
26
+ }
27
+
28
+ private get signingShare(): Promise<string> {
29
+ return this.keychain.getDkgResult(this.isSimulator)
30
+ }
24
31
 
25
- constructor({ keychain, mpcUrl, mpcVersion = 'v4' }: MpcSignerOptions) {
32
+ constructor({
33
+ keychain,
34
+ isSimulator = false,
35
+ mpcHost = 'mpc.portalhq.io',
36
+ version = 'v4',
37
+ }: MpcSignerOptions) {
38
+ this.isSimulator = isSimulator
26
39
  this.keychain = keychain
27
40
  this.mpc = NativeModules.PortalMobileMpc
28
- this.mpcUrl = mpcUrl
29
- this.mpcVersion = mpcVersion
41
+ this.mpcHost = mpcHost
42
+ this.version = version
30
43
 
31
44
  if (!this.mpc) {
32
45
  throw new Error(
@@ -35,25 +48,11 @@ class MpcSigner implements Signer {
35
48
  }
36
49
  }
37
50
 
38
- public async getAddress(): Promise<string> {
39
- if (this.address) {
40
- return this.address
41
- }
42
-
43
- const address = await this.keychain.getAddress()
44
-
45
- if (typeof address !== 'undefined' && address.length) {
46
- this.address = address
47
- }
48
-
49
- return address
50
- }
51
-
52
51
  public async sign(
53
52
  message: SigningRequestArguments,
54
53
  provider: Provider,
55
54
  ): Promise<any> {
56
- const address = await this.keychain.getAddress()
55
+ const address = await this.address
57
56
  const apiKey = provider.apiKey
58
57
 
59
58
  const { method, params } = message
@@ -67,17 +66,17 @@ class MpcSigner implements Signer {
67
66
  break
68
67
  }
69
68
 
70
- const dkg = await this.keychain.getDkgResult()
69
+ const signingShare = await this.signingShare
71
70
 
72
71
  const result = await this.mpc.sign(
73
72
  apiKey,
74
- this.mpcUrl,
75
- dkg,
73
+ this.mpcHost,
74
+ signingShare,
76
75
  message.method,
77
76
  JSON.stringify(this.buildParams(method, params)),
78
- provider.rpcUrl,
77
+ provider.gatewayUrl,
79
78
  provider.chainId.toString(),
80
- this.mpcVersion,
79
+ this.version,
81
80
  )
82
81
 
83
82
  const { data, error } = JSON.parse(String(result)) as SigningResponse
package/types.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  // Types
2
2
 
3
+ import PortalConnect from '@portal-hq/connect'
3
4
  import { KeychainAdapter, type PortalError } from '@portal-hq/utils'
4
5
 
5
6
  export type EventHandler = (data: any) => void
@@ -16,8 +17,11 @@ export interface GatewayConfig {
16
17
 
17
18
  export interface MpcSignerOptions extends SignerOptions {
18
19
  keychain: KeychainAdapter
19
- mpcUrl: string
20
- mpcVersion?: string
20
+
21
+ // Optional
22
+ isSimulator?: boolean
23
+ mpcHost?: string
24
+ version?: string
21
25
  }
22
26
 
23
27
  export interface PortalMobileMpc {
@@ -46,18 +50,18 @@ export interface PortalMobileMpc {
46
50
  }
47
51
 
48
52
  export interface ProviderOptions {
49
- // Required options
53
+ // Required
50
54
  apiKey: string
51
55
  chainId: number
52
56
  keychain: KeychainAdapter
53
57
  gatewayConfig: GatewayLike
54
58
 
55
- // Optional options
56
- apiUrl?: string
59
+ // Optional
60
+ isSimulator?: boolean
57
61
  autoApprove?: boolean
58
- enableMpc?: boolean
59
- mpcUrl?: string
60
- mpcVersion?: string
62
+ apiHost?: string
63
+ mpcHost?: string
64
+ version?: string
61
65
  }
62
66
 
63
67
  export interface RegisteredEventHandler {
@@ -68,6 +72,7 @@ export interface RegisteredEventHandler {
68
72
  export interface RequestArguments {
69
73
  method: string
70
74
  params?: unknown[] | SigningRequestParams
75
+ connect?: PortalConnect
71
76
  }
72
77
 
73
78
  export interface SignResult {