@portal-hq/connect 2.0.2 → 2.0.3
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.
- package/lib/commonjs/index.js +55 -6
- package/lib/esm/index.js +53 -5
- package/package.json +2 -2
- package/src/index.ts +69 -5
- package/types.d.ts +13 -1
package/lib/commonjs/index.js
CHANGED
|
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.ConnectionStates = void 0;
|
|
12
|
+
exports.ConnectionStates = exports.ConnectError = void 0;
|
|
13
13
|
const provider_1 = require("@portal-hq/provider");
|
|
14
14
|
class PortalConnect {
|
|
15
15
|
constructor({ apiKey, chainId, keychain, gatewayConfig,
|
|
@@ -19,6 +19,7 @@ class PortalConnect {
|
|
|
19
19
|
this.apiKey = apiKey;
|
|
20
20
|
this.events = {};
|
|
21
21
|
this.websocketServer = webSocketServer;
|
|
22
|
+
this.gatewayConfig = gatewayConfig;
|
|
22
23
|
this.provider = new provider_1.Provider({
|
|
23
24
|
apiKey,
|
|
24
25
|
chainId,
|
|
@@ -172,6 +173,36 @@ class PortalConnect {
|
|
|
172
173
|
this.events[event] = this.events[event].filter(filterEventHandlers);
|
|
173
174
|
}
|
|
174
175
|
}
|
|
176
|
+
/**
|
|
177
|
+
* Adds chains from gateway config to the session proposal
|
|
178
|
+
* @param proposal
|
|
179
|
+
* @returns session proposal with chains from gateway config added
|
|
180
|
+
*/
|
|
181
|
+
addChainsToProposal(proposal) {
|
|
182
|
+
if (!('params' in proposal) || !('requiredNamespaces' in proposal.params)) {
|
|
183
|
+
throw new Error('Invalid proposal structure.');
|
|
184
|
+
}
|
|
185
|
+
// Ensure eip155 is present in requiredNamespaces
|
|
186
|
+
if (!proposal.params.requiredNamespaces.eip155) {
|
|
187
|
+
proposal.params.requiredNamespaces.eip155 = {
|
|
188
|
+
chains: [],
|
|
189
|
+
methods: [],
|
|
190
|
+
events: [],
|
|
191
|
+
rpcMap: {},
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
// Get chains from gatewayConfig with 'eip155:' prefix, but only if they're not already in the proposal
|
|
195
|
+
const existingChains = proposal.params.requiredNamespaces.eip155.chains;
|
|
196
|
+
const newChains = Object.keys(this.gatewayConfig)
|
|
197
|
+
.map((chain) => `eip155:${chain}`)
|
|
198
|
+
.filter((chain) => !existingChains.includes(chain));
|
|
199
|
+
// Append new chains to the existing chains
|
|
200
|
+
proposal.params.requiredNamespaces.eip155.chains = [
|
|
201
|
+
...existingChains,
|
|
202
|
+
...newChains,
|
|
203
|
+
];
|
|
204
|
+
return proposal;
|
|
205
|
+
}
|
|
175
206
|
/**
|
|
176
207
|
* Adds event bindings to a websocket connection
|
|
177
208
|
* - on open, a `connect` event is dispatched via the socket to establish a bridge connection
|
|
@@ -185,6 +216,7 @@ class PortalConnect {
|
|
|
185
216
|
* - Fires a subsequent call over the websocket to notify the proxy of the uri to connect to
|
|
186
217
|
*/
|
|
187
218
|
socket.onopen = () => __awaiter(this, void 0, void 0, function* () {
|
|
219
|
+
this.connectionState = ConnectionStates.CONNECTING;
|
|
188
220
|
const address = yield this.address;
|
|
189
221
|
const { chainId } = this.provider;
|
|
190
222
|
// Tell the proxy server where to connect to downstream
|
|
@@ -215,7 +247,12 @@ class PortalConnect {
|
|
|
215
247
|
// Check if the event is an ErrorEvent
|
|
216
248
|
errorMessage = event.message; // Access the error message from the ErrorEvent
|
|
217
249
|
}
|
|
218
|
-
this.emit('portal_connectError',
|
|
250
|
+
this.emit('portal_connectError', {
|
|
251
|
+
id: '0',
|
|
252
|
+
topic: this.topic,
|
|
253
|
+
params: new ConnectError(errorMessage, 500),
|
|
254
|
+
});
|
|
255
|
+
this.connectionState = ConnectionStates.DISCONNECTED;
|
|
219
256
|
});
|
|
220
257
|
/**
|
|
221
258
|
* Handles all incoming messages over the websocket connection
|
|
@@ -244,14 +281,17 @@ class PortalConnect {
|
|
|
244
281
|
const request = message.data;
|
|
245
282
|
const params = request.params;
|
|
246
283
|
// Sign the transaction and get back a transaction hash
|
|
247
|
-
yield this.handleProviderRequest(params.request.method, params.request.params, request);
|
|
284
|
+
yield this.handleProviderRequest(params.request.method, params.request.params, params.chainId, request);
|
|
248
285
|
break;
|
|
249
286
|
case 'portal_dappSessionRequested':
|
|
250
287
|
case 'portal_dappSessionRequestedV1':
|
|
251
288
|
this.handleSessionRequest(message);
|
|
252
289
|
break;
|
|
290
|
+
case 'portal_connectError':
|
|
291
|
+
this.emit('portal_connectError', message.data);
|
|
292
|
+
break;
|
|
253
293
|
default:
|
|
254
|
-
console.log(`
|
|
294
|
+
console.log(`Received unsupported event "${message.event}". Ignoring.`);
|
|
255
295
|
break;
|
|
256
296
|
}
|
|
257
297
|
});
|
|
@@ -264,7 +304,7 @@ class PortalConnect {
|
|
|
264
304
|
*
|
|
265
305
|
* @returns The result of the provider request
|
|
266
306
|
*/
|
|
267
|
-
handleProviderRequest(method, params, request) {
|
|
307
|
+
handleProviderRequest(method, params, chainId, request) {
|
|
268
308
|
return __awaiter(this, void 0, void 0, function* () {
|
|
269
309
|
// Bind to potential signing rejection events
|
|
270
310
|
this.provider.on('portal_signingRejected', this.handleSigningRejected);
|
|
@@ -276,7 +316,7 @@ class PortalConnect {
|
|
|
276
316
|
}
|
|
277
317
|
});
|
|
278
318
|
// Pass the request along to the provider
|
|
279
|
-
yield this.provider.request({ method, params, connect: this });
|
|
319
|
+
yield this.provider.request({ method, params, chainId, connect: this });
|
|
280
320
|
});
|
|
281
321
|
}
|
|
282
322
|
handleSessionApproved(data, request) {
|
|
@@ -371,6 +411,15 @@ class PortalConnect {
|
|
|
371
411
|
}
|
|
372
412
|
}
|
|
373
413
|
}
|
|
414
|
+
class ConnectError extends Error {
|
|
415
|
+
constructor(message, code) {
|
|
416
|
+
super(message);
|
|
417
|
+
this.code = code;
|
|
418
|
+
// Set the prototype explicitly.
|
|
419
|
+
Object.setPrototypeOf(this, ConnectError.prototype);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
exports.ConnectError = ConnectError;
|
|
374
423
|
var ConnectionStates;
|
|
375
424
|
(function (ConnectionStates) {
|
|
376
425
|
ConnectionStates["CONNECTED"] = "CONNECTED";
|
package/lib/esm/index.js
CHANGED
|
@@ -16,6 +16,7 @@ class PortalConnect {
|
|
|
16
16
|
this.apiKey = apiKey;
|
|
17
17
|
this.events = {};
|
|
18
18
|
this.websocketServer = webSocketServer;
|
|
19
|
+
this.gatewayConfig = gatewayConfig;
|
|
19
20
|
this.provider = new Provider({
|
|
20
21
|
apiKey,
|
|
21
22
|
chainId,
|
|
@@ -169,6 +170,36 @@ class PortalConnect {
|
|
|
169
170
|
this.events[event] = this.events[event].filter(filterEventHandlers);
|
|
170
171
|
}
|
|
171
172
|
}
|
|
173
|
+
/**
|
|
174
|
+
* Adds chains from gateway config to the session proposal
|
|
175
|
+
* @param proposal
|
|
176
|
+
* @returns session proposal with chains from gateway config added
|
|
177
|
+
*/
|
|
178
|
+
addChainsToProposal(proposal) {
|
|
179
|
+
if (!('params' in proposal) || !('requiredNamespaces' in proposal.params)) {
|
|
180
|
+
throw new Error('Invalid proposal structure.');
|
|
181
|
+
}
|
|
182
|
+
// Ensure eip155 is present in requiredNamespaces
|
|
183
|
+
if (!proposal.params.requiredNamespaces.eip155) {
|
|
184
|
+
proposal.params.requiredNamespaces.eip155 = {
|
|
185
|
+
chains: [],
|
|
186
|
+
methods: [],
|
|
187
|
+
events: [],
|
|
188
|
+
rpcMap: {},
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
// Get chains from gatewayConfig with 'eip155:' prefix, but only if they're not already in the proposal
|
|
192
|
+
const existingChains = proposal.params.requiredNamespaces.eip155.chains;
|
|
193
|
+
const newChains = Object.keys(this.gatewayConfig)
|
|
194
|
+
.map((chain) => `eip155:${chain}`)
|
|
195
|
+
.filter((chain) => !existingChains.includes(chain));
|
|
196
|
+
// Append new chains to the existing chains
|
|
197
|
+
proposal.params.requiredNamespaces.eip155.chains = [
|
|
198
|
+
...existingChains,
|
|
199
|
+
...newChains,
|
|
200
|
+
];
|
|
201
|
+
return proposal;
|
|
202
|
+
}
|
|
172
203
|
/**
|
|
173
204
|
* Adds event bindings to a websocket connection
|
|
174
205
|
* - on open, a `connect` event is dispatched via the socket to establish a bridge connection
|
|
@@ -182,6 +213,7 @@ class PortalConnect {
|
|
|
182
213
|
* - Fires a subsequent call over the websocket to notify the proxy of the uri to connect to
|
|
183
214
|
*/
|
|
184
215
|
socket.onopen = () => __awaiter(this, void 0, void 0, function* () {
|
|
216
|
+
this.connectionState = ConnectionStates.CONNECTING;
|
|
185
217
|
const address = yield this.address;
|
|
186
218
|
const { chainId } = this.provider;
|
|
187
219
|
// Tell the proxy server where to connect to downstream
|
|
@@ -212,7 +244,12 @@ class PortalConnect {
|
|
|
212
244
|
// Check if the event is an ErrorEvent
|
|
213
245
|
errorMessage = event.message; // Access the error message from the ErrorEvent
|
|
214
246
|
}
|
|
215
|
-
this.emit('portal_connectError',
|
|
247
|
+
this.emit('portal_connectError', {
|
|
248
|
+
id: '0',
|
|
249
|
+
topic: this.topic,
|
|
250
|
+
params: new ConnectError(errorMessage, 500),
|
|
251
|
+
});
|
|
252
|
+
this.connectionState = ConnectionStates.DISCONNECTED;
|
|
216
253
|
});
|
|
217
254
|
/**
|
|
218
255
|
* Handles all incoming messages over the websocket connection
|
|
@@ -241,14 +278,17 @@ class PortalConnect {
|
|
|
241
278
|
const request = message.data;
|
|
242
279
|
const params = request.params;
|
|
243
280
|
// Sign the transaction and get back a transaction hash
|
|
244
|
-
yield this.handleProviderRequest(params.request.method, params.request.params, request);
|
|
281
|
+
yield this.handleProviderRequest(params.request.method, params.request.params, params.chainId, request);
|
|
245
282
|
break;
|
|
246
283
|
case 'portal_dappSessionRequested':
|
|
247
284
|
case 'portal_dappSessionRequestedV1':
|
|
248
285
|
this.handleSessionRequest(message);
|
|
249
286
|
break;
|
|
287
|
+
case 'portal_connectError':
|
|
288
|
+
this.emit('portal_connectError', message.data);
|
|
289
|
+
break;
|
|
250
290
|
default:
|
|
251
|
-
console.log(`
|
|
291
|
+
console.log(`Received unsupported event "${message.event}". Ignoring.`);
|
|
252
292
|
break;
|
|
253
293
|
}
|
|
254
294
|
});
|
|
@@ -261,7 +301,7 @@ class PortalConnect {
|
|
|
261
301
|
*
|
|
262
302
|
* @returns The result of the provider request
|
|
263
303
|
*/
|
|
264
|
-
handleProviderRequest(method, params, request) {
|
|
304
|
+
handleProviderRequest(method, params, chainId, request) {
|
|
265
305
|
return __awaiter(this, void 0, void 0, function* () {
|
|
266
306
|
// Bind to potential signing rejection events
|
|
267
307
|
this.provider.on('portal_signingRejected', this.handleSigningRejected);
|
|
@@ -273,7 +313,7 @@ class PortalConnect {
|
|
|
273
313
|
}
|
|
274
314
|
});
|
|
275
315
|
// Pass the request along to the provider
|
|
276
|
-
yield this.provider.request({ method, params, connect: this });
|
|
316
|
+
yield this.provider.request({ method, params, chainId, connect: this });
|
|
277
317
|
});
|
|
278
318
|
}
|
|
279
319
|
handleSessionApproved(data, request) {
|
|
@@ -368,6 +408,14 @@ class PortalConnect {
|
|
|
368
408
|
}
|
|
369
409
|
}
|
|
370
410
|
}
|
|
411
|
+
export class ConnectError extends Error {
|
|
412
|
+
constructor(message, code) {
|
|
413
|
+
super(message);
|
|
414
|
+
this.code = code;
|
|
415
|
+
// Set the prototype explicitly.
|
|
416
|
+
Object.setPrototypeOf(this, ConnectError.prototype);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
371
419
|
export var ConnectionStates;
|
|
372
420
|
(function (ConnectionStates) {
|
|
373
421
|
ConnectionStates["CONNECTED"] = "CONNECTED";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@portal-hq/connect",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.3",
|
|
4
4
|
"main": "lib/commonjs/index",
|
|
5
5
|
"module": "lib/esm/index",
|
|
6
6
|
"source": "src/index",
|
|
@@ -32,5 +32,5 @@
|
|
|
32
32
|
"react": "*",
|
|
33
33
|
"react-native": "*"
|
|
34
34
|
},
|
|
35
|
-
"gitHead": "
|
|
35
|
+
"gitHead": "c333fe5280f16a5c5f70b7ae768f112baf7156ba"
|
|
36
36
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Provider } from '@portal-hq/provider'
|
|
2
2
|
import type {
|
|
3
|
+
ErrorResult,
|
|
3
4
|
EventHandler,
|
|
4
5
|
PortalConnectOptions,
|
|
5
6
|
ProviderRequestPayload,
|
|
@@ -9,12 +10,16 @@ import type {
|
|
|
9
10
|
WebsocketMessage,
|
|
10
11
|
} from '../types.d'
|
|
11
12
|
import { IPortalProvider } from '@portal-hq/utils'
|
|
12
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
GatewayConfig,
|
|
15
|
+
SwitchEthereumChainParameter,
|
|
16
|
+
} from '@portal-hq/provider/types'
|
|
13
17
|
|
|
14
18
|
class PortalConnect {
|
|
15
19
|
private apiKey: string
|
|
16
20
|
private connectionState: ConnectionStates = ConnectionStates.DISCONNECTED
|
|
17
21
|
private provider: IPortalProvider
|
|
22
|
+
private gatewayConfig: GatewayConfig
|
|
18
23
|
private socket?: WebSocket
|
|
19
24
|
private topic?: string
|
|
20
25
|
private uri?: string
|
|
@@ -54,7 +59,7 @@ class PortalConnect {
|
|
|
54
59
|
this.apiKey = apiKey
|
|
55
60
|
this.events = {}
|
|
56
61
|
this.websocketServer = webSocketServer
|
|
57
|
-
|
|
62
|
+
this.gatewayConfig = gatewayConfig
|
|
58
63
|
this.provider = new Provider({
|
|
59
64
|
apiKey,
|
|
60
65
|
chainId,
|
|
@@ -224,6 +229,43 @@ class PortalConnect {
|
|
|
224
229
|
}
|
|
225
230
|
}
|
|
226
231
|
|
|
232
|
+
/**
|
|
233
|
+
* Adds chains from gateway config to the session proposal
|
|
234
|
+
* @param proposal
|
|
235
|
+
* @returns session proposal with chains from gateway config added
|
|
236
|
+
*/
|
|
237
|
+
public addChainsToProposal(
|
|
238
|
+
proposal: SessionProposalOrMetadata,
|
|
239
|
+
): SessionProposalOrMetadata {
|
|
240
|
+
if (!('params' in proposal) || !('requiredNamespaces' in proposal.params)) {
|
|
241
|
+
throw new Error('Invalid proposal structure.')
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Ensure eip155 is present in requiredNamespaces
|
|
245
|
+
if (!proposal.params.requiredNamespaces.eip155) {
|
|
246
|
+
proposal.params.requiredNamespaces.eip155 = {
|
|
247
|
+
chains: [],
|
|
248
|
+
methods: [],
|
|
249
|
+
events: [],
|
|
250
|
+
rpcMap: {},
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Get chains from gatewayConfig with 'eip155:' prefix, but only if they're not already in the proposal
|
|
255
|
+
const existingChains = proposal.params.requiredNamespaces.eip155.chains
|
|
256
|
+
const newChains = Object.keys(this.gatewayConfig)
|
|
257
|
+
.map((chain) => `eip155:${chain}`)
|
|
258
|
+
.filter((chain) => !existingChains.includes(chain))
|
|
259
|
+
|
|
260
|
+
// Append new chains to the existing chains
|
|
261
|
+
proposal.params.requiredNamespaces.eip155.chains = [
|
|
262
|
+
...existingChains,
|
|
263
|
+
...newChains,
|
|
264
|
+
]
|
|
265
|
+
|
|
266
|
+
return proposal
|
|
267
|
+
}
|
|
268
|
+
|
|
227
269
|
/**
|
|
228
270
|
* Adds event bindings to a websocket connection
|
|
229
271
|
* - on open, a `connect` event is dispatched via the socket to establish a bridge connection
|
|
@@ -237,6 +279,7 @@ class PortalConnect {
|
|
|
237
279
|
* - Fires a subsequent call over the websocket to notify the proxy of the uri to connect to
|
|
238
280
|
*/
|
|
239
281
|
socket.onopen = async () => {
|
|
282
|
+
this.connectionState = ConnectionStates.CONNECTING
|
|
240
283
|
const address = await this.address
|
|
241
284
|
const { chainId } = this.provider
|
|
242
285
|
|
|
@@ -275,7 +318,12 @@ class PortalConnect {
|
|
|
275
318
|
errorMessage = event.message // Access the error message from the ErrorEvent
|
|
276
319
|
}
|
|
277
320
|
|
|
278
|
-
this.emit('portal_connectError',
|
|
321
|
+
this.emit('portal_connectError', {
|
|
322
|
+
id: '0',
|
|
323
|
+
topic: this.topic,
|
|
324
|
+
params: new ConnectError(errorMessage, 500),
|
|
325
|
+
} as ErrorResult)
|
|
326
|
+
this.connectionState = ConnectionStates.DISCONNECTED
|
|
279
327
|
}
|
|
280
328
|
|
|
281
329
|
/**
|
|
@@ -310,6 +358,7 @@ class PortalConnect {
|
|
|
310
358
|
await this.handleProviderRequest(
|
|
311
359
|
params.request.method,
|
|
312
360
|
params.request.params,
|
|
361
|
+
params.chainId,
|
|
313
362
|
request,
|
|
314
363
|
)
|
|
315
364
|
break
|
|
@@ -317,9 +366,12 @@ class PortalConnect {
|
|
|
317
366
|
case 'portal_dappSessionRequestedV1':
|
|
318
367
|
this.handleSessionRequest(message)
|
|
319
368
|
break
|
|
369
|
+
case 'portal_connectError':
|
|
370
|
+
this.emit('portal_connectError', message.data as ErrorResult)
|
|
371
|
+
break
|
|
320
372
|
default:
|
|
321
373
|
console.log(
|
|
322
|
-
`
|
|
374
|
+
`Received unsupported event "${message.event}". Ignoring.`,
|
|
323
375
|
)
|
|
324
376
|
break
|
|
325
377
|
}
|
|
@@ -337,6 +389,7 @@ class PortalConnect {
|
|
|
337
389
|
private async handleProviderRequest(
|
|
338
390
|
method: string,
|
|
339
391
|
params: any,
|
|
392
|
+
chainId: string,
|
|
340
393
|
request: SessionRequest,
|
|
341
394
|
): Promise<void> {
|
|
342
395
|
// Bind to potential signing rejection events
|
|
@@ -356,7 +409,7 @@ class PortalConnect {
|
|
|
356
409
|
)
|
|
357
410
|
|
|
358
411
|
// Pass the request along to the provider
|
|
359
|
-
await this.provider.request({ method, params, connect: this })
|
|
412
|
+
await this.provider.request({ method, params, chainId, connect: this })
|
|
360
413
|
}
|
|
361
414
|
|
|
362
415
|
private async handleSessionApproved(
|
|
@@ -476,6 +529,17 @@ class PortalConnect {
|
|
|
476
529
|
}
|
|
477
530
|
}
|
|
478
531
|
|
|
532
|
+
export class ConnectError extends Error {
|
|
533
|
+
code: number
|
|
534
|
+
|
|
535
|
+
constructor(message: string, code: number) {
|
|
536
|
+
super(message)
|
|
537
|
+
this.code = code
|
|
538
|
+
// Set the prototype explicitly.
|
|
539
|
+
Object.setPrototypeOf(this, ConnectError.prototype)
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
|
|
479
543
|
export enum ConnectionStates {
|
|
480
544
|
CONNECTED = 'CONNECTED',
|
|
481
545
|
CONNECTING = 'CONNECTING',
|
package/types.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import Portal from '@portal-hq/core'
|
|
2
2
|
import { KeychainAdapter } from '@portal-hq/utils'
|
|
3
|
+
import { ConnectError } from 'src'
|
|
3
4
|
|
|
4
5
|
export type EventHandler = (data: any) => void
|
|
5
6
|
export type SessionProposalOrMetadata = SessionProposal | PeerMetadata
|
|
@@ -10,6 +11,12 @@ export interface ConnectRequest {
|
|
|
10
11
|
topic: string
|
|
11
12
|
}
|
|
12
13
|
|
|
14
|
+
export interface ErrorResult {
|
|
15
|
+
id: string
|
|
16
|
+
params: ConnectError
|
|
17
|
+
topic: string
|
|
18
|
+
}
|
|
19
|
+
|
|
13
20
|
export interface ConnectResult {
|
|
14
21
|
active: boolean
|
|
15
22
|
expiry: number
|
|
@@ -114,5 +121,10 @@ export interface SigningResult {
|
|
|
114
121
|
|
|
115
122
|
export interface WebsocketMessage {
|
|
116
123
|
event: string
|
|
117
|
-
data:
|
|
124
|
+
data:
|
|
125
|
+
| ConnectResult
|
|
126
|
+
| DisconnectResult
|
|
127
|
+
| SessionRequest
|
|
128
|
+
| SigningResult
|
|
129
|
+
| ErrorResult
|
|
118
130
|
}
|