@portal-hq/provider 4.1.2 → 4.1.4
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/providers/index.js +22 -11
- package/lib/commonjs/signers/enclave.js +316 -0
- package/lib/commonjs/signers/index.js +3 -1
- package/lib/commonjs/signers/mpc.js +32 -8
- package/lib/esm/providers/index.js +23 -12
- package/lib/esm/signers/enclave.js +311 -0
- package/lib/esm/signers/index.js +1 -0
- package/lib/esm/signers/mpc.js +29 -8
- package/package.json +6 -4
- package/src/providers/index.ts +22 -12
- package/src/signers/enclave.ts +414 -0
- package/src/signers/index.ts +1 -0
- package/src/signers/mpc.ts +28 -7
- package/types.d.ts +51 -0
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
import { PortalCurve } from '@portal-hq/core'
|
|
2
|
+
import { FeatureFlags } from '@portal-hq/core/types'
|
|
3
|
+
import {
|
|
4
|
+
HttpRequester,
|
|
5
|
+
IPortalProvider,
|
|
6
|
+
KeychainAdapter,
|
|
7
|
+
type SigningRequestArguments,
|
|
8
|
+
getClientPlatformVersion,
|
|
9
|
+
} from '@portal-hq/utils'
|
|
10
|
+
import UUID from 'react-native-uuid'
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
type MpcSignerOptions,
|
|
14
|
+
PortalMobileMpcMetadata,
|
|
15
|
+
type EnclaveSignRequest,
|
|
16
|
+
type EnclaveSignResponse,
|
|
17
|
+
type EnclaveSignResult,
|
|
18
|
+
} from '../../types'
|
|
19
|
+
import Signer from './abstract'
|
|
20
|
+
|
|
21
|
+
enum Operation {
|
|
22
|
+
SIGN = 'sign',
|
|
23
|
+
RAW_SIGN = 'raw_sign',
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
class EnclaveSigner implements Signer {
|
|
27
|
+
private featureFlags: FeatureFlags
|
|
28
|
+
private keychain: KeychainAdapter
|
|
29
|
+
private enclaveMPCHost: string
|
|
30
|
+
private version = 'v6'
|
|
31
|
+
private portalApi?: HttpRequester
|
|
32
|
+
private requests: HttpRequester
|
|
33
|
+
|
|
34
|
+
constructor({
|
|
35
|
+
keychain,
|
|
36
|
+
enclaveMPCHost = 'mpc-client.portalhq.io',
|
|
37
|
+
version = 'v6',
|
|
38
|
+
portalApi,
|
|
39
|
+
featureFlags = {},
|
|
40
|
+
}: MpcSignerOptions & { enclaveMPCHost?: string }) {
|
|
41
|
+
this.featureFlags = featureFlags
|
|
42
|
+
this.keychain = keychain
|
|
43
|
+
this.enclaveMPCHost = enclaveMPCHost
|
|
44
|
+
this.version = version
|
|
45
|
+
this.portalApi = portalApi
|
|
46
|
+
this.requests = new HttpRequester({
|
|
47
|
+
baseUrl: `https://${this.enclaveMPCHost}`,
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public async sign(
|
|
52
|
+
message: SigningRequestArguments,
|
|
53
|
+
provider: IPortalProvider,
|
|
54
|
+
): Promise<any> {
|
|
55
|
+
// Always track metrics, but only send if feature flag is enabled
|
|
56
|
+
const shouldSendMetrics =
|
|
57
|
+
this.featureFlags.enableSdkPerformanceMetrics === true
|
|
58
|
+
const signStartTime = performance.now()
|
|
59
|
+
const preOperationStartTime = performance.now()
|
|
60
|
+
|
|
61
|
+
// Generate a traceId for this operation
|
|
62
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
|
|
63
|
+
const traceId = (UUID as any).v4() as string
|
|
64
|
+
const metrics: Record<string, number | string | boolean> = {
|
|
65
|
+
hasError: false,
|
|
66
|
+
operation: Operation.SIGN,
|
|
67
|
+
signingMethod: message.method,
|
|
68
|
+
traceId,
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
const eip155Address = await this.keychain.getEip155Address()
|
|
73
|
+
const apiKey = provider.apiKey
|
|
74
|
+
const { method, chainId, curve, isRaw } = message
|
|
75
|
+
|
|
76
|
+
// Add chainId to metrics
|
|
77
|
+
if (chainId) {
|
|
78
|
+
metrics.chainId = chainId
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
switch (method) {
|
|
82
|
+
case 'eth_requestAccounts':
|
|
83
|
+
return [eip155Address]
|
|
84
|
+
case 'eth_accounts':
|
|
85
|
+
return [eip155Address]
|
|
86
|
+
default:
|
|
87
|
+
break
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const shares = await this.keychain.getShares()
|
|
91
|
+
let signingShare = shares.secp256k1.share
|
|
92
|
+
|
|
93
|
+
if (curve === PortalCurve.ED25519) {
|
|
94
|
+
if (!shares.ed25519) {
|
|
95
|
+
throw new Error(
|
|
96
|
+
'[Portal.Provider.EnclaveSigner] The ED25519 share is missing from the keychain.',
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
signingShare = shares.ed25519.share
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const metadata: PortalMobileMpcMetadata = {
|
|
103
|
+
clientPlatform: 'REACT_NATIVE',
|
|
104
|
+
clientPlatformVersion: getClientPlatformVersion(),
|
|
105
|
+
isMultiBackupEnabled: this.featureFlags.isMultiBackupEnabled,
|
|
106
|
+
mpcServerVersion: this.version,
|
|
107
|
+
optimized: true,
|
|
108
|
+
curve,
|
|
109
|
+
chainId,
|
|
110
|
+
isRaw,
|
|
111
|
+
reqId: traceId,
|
|
112
|
+
connectionTracingEnabled: shouldSendMetrics,
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
let formattedParams: string
|
|
116
|
+
let rpcUrl: string
|
|
117
|
+
|
|
118
|
+
if (isRaw) {
|
|
119
|
+
formattedParams = JSON.stringify(
|
|
120
|
+
this.buildParams(method, message.params),
|
|
121
|
+
)
|
|
122
|
+
rpcUrl = ''
|
|
123
|
+
metrics.operation = Operation.RAW_SIGN
|
|
124
|
+
} else {
|
|
125
|
+
formattedParams = JSON.stringify(
|
|
126
|
+
this.buildParams(method, message.params),
|
|
127
|
+
)
|
|
128
|
+
rpcUrl = provider.getGatewayUrl(chainId)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (typeof formattedParams !== 'string') {
|
|
132
|
+
throw new Error(
|
|
133
|
+
`[Portal.Provider.EnclaveSigner] The formatted params for the signing request could not be converted to a string. The params were: ${formattedParams}`,
|
|
134
|
+
)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Record pre-operation time
|
|
138
|
+
metrics.sdkPreOperationMs = performance.now() - preOperationStartTime
|
|
139
|
+
|
|
140
|
+
// Measure enclave signing operation time
|
|
141
|
+
const enclaveSignStartTime = performance.now()
|
|
142
|
+
|
|
143
|
+
const result = isRaw
|
|
144
|
+
? await this.enclaveRawSign(
|
|
145
|
+
apiKey,
|
|
146
|
+
JSON.stringify(signingShare),
|
|
147
|
+
formattedParams,
|
|
148
|
+
curve || 'SECP256K1',
|
|
149
|
+
)
|
|
150
|
+
: await this.enclaveSign(
|
|
151
|
+
apiKey,
|
|
152
|
+
JSON.stringify(signingShare),
|
|
153
|
+
message.method,
|
|
154
|
+
formattedParams,
|
|
155
|
+
rpcUrl,
|
|
156
|
+
chainId || '',
|
|
157
|
+
JSON.stringify(metadata),
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
// Post-operation processing time starts
|
|
161
|
+
const postOperationStartTime = performance.now()
|
|
162
|
+
|
|
163
|
+
// Record HTTP call time
|
|
164
|
+
metrics.enclaveHttpCallMs = performance.now() - enclaveSignStartTime
|
|
165
|
+
|
|
166
|
+
// Record post-operation time
|
|
167
|
+
metrics.sdkPostOperationMs = performance.now() - postOperationStartTime
|
|
168
|
+
|
|
169
|
+
// Calculate total SDK signing time
|
|
170
|
+
metrics.sdkOperationMs = performance.now() - signStartTime
|
|
171
|
+
|
|
172
|
+
// Log performance timing to console
|
|
173
|
+
const timingMetrics: Record<string, number> = {}
|
|
174
|
+
if (typeof metrics.sdkPreOperationMs === 'number') {
|
|
175
|
+
timingMetrics['Pre-operation'] = metrics.sdkPreOperationMs
|
|
176
|
+
}
|
|
177
|
+
if (typeof metrics.enclaveHttpCallMs === 'number') {
|
|
178
|
+
timingMetrics['Enclave HTTP Call'] = metrics.enclaveHttpCallMs
|
|
179
|
+
}
|
|
180
|
+
if (typeof metrics.sdkPostOperationMs === 'number') {
|
|
181
|
+
timingMetrics['Post-operation'] = metrics.sdkPostOperationMs
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Only send metrics if the feature flag is enabled
|
|
185
|
+
if (shouldSendMetrics && this.portalApi) {
|
|
186
|
+
try {
|
|
187
|
+
await this.sendMetrics(metrics, apiKey)
|
|
188
|
+
} catch (err) {
|
|
189
|
+
// No-op
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return result
|
|
194
|
+
} catch (error) {
|
|
195
|
+
// Calculate total time even in error case
|
|
196
|
+
metrics.sdkOperationMs = performance.now() - signStartTime
|
|
197
|
+
|
|
198
|
+
// Log performance timing to console even in error case
|
|
199
|
+
const errorTimingMetrics: Record<string, number> = {}
|
|
200
|
+
if (typeof metrics.sdkPreOperationMs === 'number') {
|
|
201
|
+
errorTimingMetrics['Pre-operation'] = metrics.sdkPreOperationMs
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Only send metrics if the feature flag is enabled
|
|
205
|
+
if (shouldSendMetrics) {
|
|
206
|
+
const apiKey = provider.apiKey
|
|
207
|
+
metrics.hasError = true
|
|
208
|
+
try {
|
|
209
|
+
await this.sendMetrics(metrics, apiKey)
|
|
210
|
+
} catch {
|
|
211
|
+
// No-op
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
throw error
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
private async enclaveRawSign(
|
|
220
|
+
apiKey: string,
|
|
221
|
+
signingShare: string,
|
|
222
|
+
params: string,
|
|
223
|
+
curve: string,
|
|
224
|
+
): Promise<string> {
|
|
225
|
+
if (!apiKey || !signingShare || !params || !curve) {
|
|
226
|
+
return this.encodeErrorResult(
|
|
227
|
+
'INVALID_PARAMETERS',
|
|
228
|
+
'Invalid parameters provided for raw signing',
|
|
229
|
+
)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const requestBody = {
|
|
233
|
+
params: params,
|
|
234
|
+
share: signingShare,
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const endpoint = `/v1/raw/sign/${curve}`
|
|
238
|
+
|
|
239
|
+
try {
|
|
240
|
+
const response = await this.requests.post<EnclaveSignResponse>(endpoint, {
|
|
241
|
+
headers: {
|
|
242
|
+
Authorization: `Bearer ${apiKey}`,
|
|
243
|
+
'Content-Type': 'application/json',
|
|
244
|
+
},
|
|
245
|
+
body: requestBody,
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
return this.encodeSuccessResult(response.data)
|
|
249
|
+
} catch (error: any) {
|
|
250
|
+
if (error?.response?.data) {
|
|
251
|
+
const portalError = this.decodePortalError(
|
|
252
|
+
JSON.stringify(error.response.data),
|
|
253
|
+
)
|
|
254
|
+
return this.encodeErrorResult(portalError?.id, portalError?.message)
|
|
255
|
+
}
|
|
256
|
+
return this.encodeErrorResult(
|
|
257
|
+
'SIGNING_NETWORK_ERROR',
|
|
258
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument
|
|
259
|
+
error.message || 'Network error occurred',
|
|
260
|
+
)
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
private async enclaveSign(
|
|
265
|
+
apiKey: string,
|
|
266
|
+
signingShare: string,
|
|
267
|
+
method: string,
|
|
268
|
+
params: string,
|
|
269
|
+
rpcURL: string,
|
|
270
|
+
chainId: string,
|
|
271
|
+
metadata: string,
|
|
272
|
+
): Promise<string> {
|
|
273
|
+
if (
|
|
274
|
+
!apiKey ||
|
|
275
|
+
!signingShare ||
|
|
276
|
+
!method ||
|
|
277
|
+
!params ||
|
|
278
|
+
!chainId ||
|
|
279
|
+
!metadata
|
|
280
|
+
) {
|
|
281
|
+
return this.encodeErrorResult(
|
|
282
|
+
'INVALID_PARAMETERS',
|
|
283
|
+
'Invalid parameters provided',
|
|
284
|
+
)
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const requestBody: EnclaveSignRequest = {
|
|
288
|
+
method: method,
|
|
289
|
+
params: params,
|
|
290
|
+
share: signingShare,
|
|
291
|
+
chainId: chainId,
|
|
292
|
+
rpcUrl: rpcURL,
|
|
293
|
+
metadataStr: metadata,
|
|
294
|
+
clientPlatform: 'REACT_NATIVE',
|
|
295
|
+
clientPlatformVersion: getClientPlatformVersion(),
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
try {
|
|
299
|
+
const response = await this.requests.post<EnclaveSignResponse>(
|
|
300
|
+
'/v1/sign',
|
|
301
|
+
{
|
|
302
|
+
headers: {
|
|
303
|
+
Authorization: `Bearer ${apiKey}`,
|
|
304
|
+
'Content-Type': 'application/json',
|
|
305
|
+
},
|
|
306
|
+
body: requestBody,
|
|
307
|
+
},
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
return this.encodeSuccessResult(response.data)
|
|
311
|
+
} catch (error: any) {
|
|
312
|
+
if (error?.response?.data) {
|
|
313
|
+
const portalError = this.decodePortalError(
|
|
314
|
+
JSON.stringify(error.response.data),
|
|
315
|
+
)
|
|
316
|
+
return this.encodeErrorResult(portalError?.id, portalError?.message)
|
|
317
|
+
}
|
|
318
|
+
return this.encodeErrorResult(
|
|
319
|
+
'SIGNING_NETWORK_ERROR',
|
|
320
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument
|
|
321
|
+
error.message || 'Network error occurred',
|
|
322
|
+
)
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Helper function to encode success results
|
|
327
|
+
private encodeSuccessResult(data: string): string {
|
|
328
|
+
const successResult: EnclaveSignResult = { data: data, error: undefined }
|
|
329
|
+
return this.encodeJSON(successResult)
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Helper function to decode Portal errors
|
|
333
|
+
private decodePortalError(
|
|
334
|
+
errorStr?: string,
|
|
335
|
+
): { id?: string; message?: string } | null {
|
|
336
|
+
if (!errorStr) return null
|
|
337
|
+
try {
|
|
338
|
+
return JSON.parse(errorStr)
|
|
339
|
+
} catch {
|
|
340
|
+
return null
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Helper function to encode error results
|
|
345
|
+
private encodeErrorResult(id?: string, message?: string): string {
|
|
346
|
+
const errorResult: EnclaveSignResult = {
|
|
347
|
+
data: undefined,
|
|
348
|
+
error: { id, message },
|
|
349
|
+
}
|
|
350
|
+
return this.encodeJSON(errorResult)
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Helper function to encode any object to JSON string
|
|
354
|
+
private encodeJSON<T>(value: T): string {
|
|
355
|
+
try {
|
|
356
|
+
const jsonString = JSON.stringify(value)
|
|
357
|
+
return jsonString
|
|
358
|
+
} catch (error: any) {
|
|
359
|
+
return JSON.stringify({
|
|
360
|
+
error: {
|
|
361
|
+
id: 'ENCODING_ERROR',
|
|
362
|
+
message: `Failed to encode JSON: ${error.message}`,
|
|
363
|
+
},
|
|
364
|
+
})
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
private async sendMetrics(
|
|
369
|
+
metrics: Record<string, number | string | boolean>,
|
|
370
|
+
apiKey: string,
|
|
371
|
+
): Promise<void> {
|
|
372
|
+
try {
|
|
373
|
+
if (this.portalApi) {
|
|
374
|
+
await this.portalApi.post('/api/v3/clients/me/sdk/metrics', {
|
|
375
|
+
headers: {
|
|
376
|
+
Authorization: `Bearer ${apiKey}`,
|
|
377
|
+
'Content-Type': 'application/json',
|
|
378
|
+
},
|
|
379
|
+
body: metrics,
|
|
380
|
+
})
|
|
381
|
+
}
|
|
382
|
+
} catch {
|
|
383
|
+
// No-op
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
private buildParams = (method: string, txParams: any) => {
|
|
388
|
+
let params = txParams
|
|
389
|
+
|
|
390
|
+
switch (method) {
|
|
391
|
+
case 'eth_sign':
|
|
392
|
+
case 'personal_sign':
|
|
393
|
+
case 'eth_signTypedData_v3':
|
|
394
|
+
case 'eth_signTypedData_v4':
|
|
395
|
+
case 'sol_signMessage':
|
|
396
|
+
case 'sol_signTransaction':
|
|
397
|
+
case 'sol_signAndSendTransaction':
|
|
398
|
+
case 'sol_signAndConfirmTransaction':
|
|
399
|
+
if (!Array.isArray(txParams)) {
|
|
400
|
+
params = [txParams]
|
|
401
|
+
}
|
|
402
|
+
break
|
|
403
|
+
default:
|
|
404
|
+
if (Array.isArray(txParams)) {
|
|
405
|
+
if (txParams.length === 1) {
|
|
406
|
+
params = txParams[0]
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
return params
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
export default EnclaveSigner
|
package/src/signers/index.ts
CHANGED
package/src/signers/mpc.ts
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
getClientPlatformVersion,
|
|
10
10
|
} from '@portal-hq/utils'
|
|
11
11
|
import { NativeModules } from 'react-native'
|
|
12
|
+
import UUID from 'react-native-uuid'
|
|
12
13
|
|
|
13
14
|
import {
|
|
14
15
|
type MpcSignerOptions,
|
|
@@ -61,9 +62,14 @@ class MpcSigner implements Signer {
|
|
|
61
62
|
this.featureFlags.enableSdkPerformanceMetrics === true
|
|
62
63
|
const signStartTime = performance.now()
|
|
63
64
|
const preOperationStartTime = performance.now()
|
|
65
|
+
// Generate a traceId for this operation
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
67
|
+
const traceId = (UUID as any).v4() as string
|
|
64
68
|
const metrics: Record<string, number | string | boolean> = {
|
|
65
|
-
operation: Operation.SIGN,
|
|
66
69
|
hasError: false,
|
|
70
|
+
operation: Operation.SIGN,
|
|
71
|
+
signingMethod: message.method,
|
|
72
|
+
traceId,
|
|
67
73
|
}
|
|
68
74
|
try {
|
|
69
75
|
const eip155Address = await this.keychain.getEip155Address()
|
|
@@ -107,6 +113,8 @@ class MpcSigner implements Signer {
|
|
|
107
113
|
curve,
|
|
108
114
|
chainId,
|
|
109
115
|
isRaw,
|
|
116
|
+
reqId: traceId,
|
|
117
|
+
connectionTracingEnabled: shouldSendMetrics,
|
|
110
118
|
}
|
|
111
119
|
|
|
112
120
|
const stringifiedMetadata = JSON.stringify(metadata)
|
|
@@ -160,15 +168,28 @@ class MpcSigner implements Signer {
|
|
|
160
168
|
|
|
161
169
|
// Add binary metrics to our metrics object
|
|
162
170
|
if (meta?.metrics) {
|
|
163
|
-
|
|
164
|
-
|
|
171
|
+
const binaryMetrics = meta.metrics
|
|
172
|
+
if (binaryMetrics.wsConnectDurationMs) {
|
|
173
|
+
metrics.sdkBinaryWSConnectMs = binaryMetrics.wsConnectDurationMs
|
|
174
|
+
}
|
|
175
|
+
if (binaryMetrics.operationDurationMs) {
|
|
176
|
+
metrics.sdkBinaryOperationMs = binaryMetrics.operationDurationMs
|
|
177
|
+
}
|
|
178
|
+
if (binaryMetrics.tlsHandshakeMs) {
|
|
179
|
+
metrics.sdkBinaryTlsHandshakeMs = binaryMetrics.tlsHandshakeMs
|
|
165
180
|
}
|
|
166
|
-
if (
|
|
167
|
-
metrics.
|
|
181
|
+
if (binaryMetrics.firstResponseMs) {
|
|
182
|
+
metrics.sdkBinaryFirstResponseMs = binaryMetrics.firstResponseMs
|
|
183
|
+
}
|
|
184
|
+
if (binaryMetrics.dnsLookupMs) {
|
|
185
|
+
metrics.sdkBinaryDnsLookupMs = binaryMetrics.dnsLookupMs
|
|
186
|
+
}
|
|
187
|
+
if (binaryMetrics.connectMs) {
|
|
188
|
+
metrics.sdkBinaryConnectMs = binaryMetrics.connectMs
|
|
168
189
|
}
|
|
169
190
|
}
|
|
170
191
|
|
|
171
|
-
if (error?.
|
|
192
|
+
if (error?.id) {
|
|
172
193
|
throw new PortalMpcError(error)
|
|
173
194
|
}
|
|
174
195
|
|
|
@@ -182,7 +203,7 @@ class MpcSigner implements Signer {
|
|
|
182
203
|
if (shouldSendMetrics && this.portalApi) {
|
|
183
204
|
try {
|
|
184
205
|
await this.sendMetrics(metrics, apiKey)
|
|
185
|
-
} catch {
|
|
206
|
+
} catch (err) {
|
|
186
207
|
// No-op
|
|
187
208
|
}
|
|
188
209
|
}
|
package/types.d.ts
CHANGED
|
@@ -25,6 +25,7 @@ export interface MpcSignerOptions extends SignerOptions {
|
|
|
25
25
|
isSimulator?: boolean
|
|
26
26
|
mpcHost?: string
|
|
27
27
|
portalApi?: HttpRequester
|
|
28
|
+
enclaveMPCHost?: string
|
|
28
29
|
version?: string
|
|
29
30
|
featureFlags?: FeatureFlags
|
|
30
31
|
}
|
|
@@ -45,6 +46,8 @@ export interface PortalMobileMpcMetadata {
|
|
|
45
46
|
mpcServerVersion: string
|
|
46
47
|
optimized: true
|
|
47
48
|
isRaw?: boolean
|
|
49
|
+
reqId?: string
|
|
50
|
+
connectionTracingEnabled?: boolean
|
|
48
51
|
}
|
|
49
52
|
|
|
50
53
|
export interface PortalMobileMpc {
|
|
@@ -84,6 +87,7 @@ export interface ProviderOptions {
|
|
|
84
87
|
autoApprove?: boolean
|
|
85
88
|
apiHost?: string
|
|
86
89
|
mpcHost?: string
|
|
90
|
+
enclaveMPCHost?: string
|
|
87
91
|
version?: string
|
|
88
92
|
featureFlags?: FeatureFlags
|
|
89
93
|
}
|
|
@@ -104,6 +108,30 @@ export interface SignResult {
|
|
|
104
108
|
S: string
|
|
105
109
|
}
|
|
106
110
|
|
|
111
|
+
export interface EnclaveSignResult {
|
|
112
|
+
data?: string
|
|
113
|
+
error?: {
|
|
114
|
+
id?: string
|
|
115
|
+
message?: string
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export interface ProviderOptions {
|
|
120
|
+
// Required
|
|
121
|
+
apiKey: string
|
|
122
|
+
keychain: KeychainAdapter
|
|
123
|
+
gatewayConfig: GatewayLike
|
|
124
|
+
|
|
125
|
+
// Optional
|
|
126
|
+
autoApprove?: boolean
|
|
127
|
+
apiHost?: string
|
|
128
|
+
mpcHost?: string
|
|
129
|
+
enclaveMPCHost?: string
|
|
130
|
+
version?: string
|
|
131
|
+
chainId?: string
|
|
132
|
+
featureFlags?: FeatureFlags
|
|
133
|
+
}
|
|
134
|
+
|
|
107
135
|
export interface SignerOptions {}
|
|
108
136
|
|
|
109
137
|
export interface Eip1559 {
|
|
@@ -128,6 +156,10 @@ export interface SigningResponse {
|
|
|
128
156
|
metrics?: {
|
|
129
157
|
wsConnectDurationMs?: number
|
|
130
158
|
operationDurationMs?: number
|
|
159
|
+
tlsHandshakeMs?: number
|
|
160
|
+
firstResponseMs?: number
|
|
161
|
+
dnsLookupMs?: number
|
|
162
|
+
connectMs?: number
|
|
131
163
|
}
|
|
132
164
|
}
|
|
133
165
|
}
|
|
@@ -135,3 +167,22 @@ export interface SigningResponse {
|
|
|
135
167
|
export interface SwitchEthereumChainParameter {
|
|
136
168
|
chainId: number
|
|
137
169
|
}
|
|
170
|
+
|
|
171
|
+
export interface EnclaveSignRequest {
|
|
172
|
+
method: string
|
|
173
|
+
params: string
|
|
174
|
+
share: string
|
|
175
|
+
chainId: string
|
|
176
|
+
rpcUrl: string
|
|
177
|
+
metadataStr: string
|
|
178
|
+
clientPlatform: string
|
|
179
|
+
clientPlatformVersion: string
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export interface EnclaveSignResponse {
|
|
183
|
+
data: string
|
|
184
|
+
error?: {
|
|
185
|
+
id: string
|
|
186
|
+
message: string
|
|
187
|
+
}
|
|
188
|
+
}
|