@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.
- package/lib/commonjs/index.js +254 -58
- package/lib/commonjs/mpc/errors/index.js +2 -2
- package/lib/commonjs/mpc/index.js +43 -79
- package/lib/commonjs/provider/index.js +57 -14
- package/lib/esm/index.js +254 -58
- package/lib/esm/mpc/errors/index.js +2 -2
- package/lib/esm/mpc/index.js +43 -79
- package/lib/esm/provider/index.js +57 -14
- package/package.json +4 -1
- package/src/index.ts +323 -67
- package/src/mpc/errors/index.ts +2 -2
- package/src/mpc/index.ts +54 -99
- package/src/provider/index.ts +66 -16
- package/types.d.ts +17 -27
package/src/index.ts
CHANGED
|
@@ -1,24 +1,32 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Connection,
|
|
3
|
+
PublicKey,
|
|
4
|
+
Transaction as SolanaTransaction,
|
|
5
|
+
SystemProgram,
|
|
6
|
+
} from '@solana/web3.js'
|
|
7
|
+
|
|
1
8
|
import type {
|
|
2
9
|
BackupConfigs,
|
|
3
10
|
BackupResponse,
|
|
4
|
-
BackupSharePairMetadata,
|
|
5
11
|
Balance,
|
|
6
12
|
ClientResponse,
|
|
7
13
|
EthereumTransaction,
|
|
8
14
|
FeatureFlags,
|
|
9
15
|
GDriveConfig,
|
|
10
|
-
|
|
16
|
+
RpcConfig,
|
|
11
17
|
NFT,
|
|
12
18
|
PasskeyConfig,
|
|
13
19
|
PortalOptions,
|
|
14
20
|
ProgressCallback,
|
|
15
21
|
QuoteArgs,
|
|
16
22
|
QuoteResponse,
|
|
17
|
-
SigningSharePairMetadata,
|
|
18
23
|
SimulateTransactionParam,
|
|
19
24
|
SimulatedTransaction,
|
|
20
25
|
Transaction,
|
|
21
26
|
TypedData,
|
|
27
|
+
SharesOnDeviceResponse,
|
|
28
|
+
RequestArguments,
|
|
29
|
+
EjectResult,
|
|
22
30
|
} from '../types'
|
|
23
31
|
import Mpc from './mpc'
|
|
24
32
|
import Provider from './provider'
|
|
@@ -29,7 +37,6 @@ class Portal {
|
|
|
29
37
|
public authToken?: string
|
|
30
38
|
public authUrl?: string
|
|
31
39
|
public autoApprove: boolean
|
|
32
|
-
public chainId: number
|
|
33
40
|
public gDriveConfig?: GDriveConfig
|
|
34
41
|
public passkeyConfig?: PasskeyConfig
|
|
35
42
|
public host: string
|
|
@@ -41,19 +48,18 @@ class Portal {
|
|
|
41
48
|
public featureFlags: FeatureFlags
|
|
42
49
|
|
|
43
50
|
private errorCallbacks: ((reason: string) => any | Promise<any>)[] = []
|
|
44
|
-
private
|
|
51
|
+
private rpcConfig: RpcConfig
|
|
45
52
|
private readyCallbacks: (() => any | Promise<any>)[] = []
|
|
46
53
|
|
|
47
54
|
constructor({
|
|
48
55
|
// Required
|
|
49
|
-
|
|
56
|
+
rpcConfig,
|
|
50
57
|
|
|
51
58
|
// Optional
|
|
52
59
|
apiKey,
|
|
53
60
|
authToken,
|
|
54
61
|
authUrl,
|
|
55
62
|
autoApprove = false,
|
|
56
|
-
chainId = 1,
|
|
57
63
|
gdrive,
|
|
58
64
|
passkey,
|
|
59
65
|
host = 'web.portalhq.io',
|
|
@@ -67,8 +73,7 @@ class Portal {
|
|
|
67
73
|
this.authToken = authToken
|
|
68
74
|
this.authUrl = authUrl
|
|
69
75
|
this.autoApprove = autoApprove
|
|
70
|
-
this.
|
|
71
|
-
this.gatewayConfig = gatewayConfig
|
|
76
|
+
this.rpcConfig = rpcConfig
|
|
72
77
|
this.host = host
|
|
73
78
|
this.mpcHost = mpcHost
|
|
74
79
|
this.mpcVersion = mpcVersion
|
|
@@ -220,12 +225,12 @@ class Portal {
|
|
|
220
225
|
return this.recoverWallet(cipherText, backupMethod, backupConfigs, progress)
|
|
221
226
|
}
|
|
222
227
|
|
|
223
|
-
public async
|
|
228
|
+
public async eject(
|
|
224
229
|
clientBackupCipherText: string,
|
|
225
230
|
backupMethod: BackupMethods,
|
|
226
231
|
backupConfigs: BackupConfigs,
|
|
227
232
|
orgBackupShare: string,
|
|
228
|
-
): Promise<
|
|
233
|
+
): Promise<EjectResult> {
|
|
229
234
|
if (clientBackupCipherText === '') {
|
|
230
235
|
throw new Error('clientBackupCipherText cannot be empty string.')
|
|
231
236
|
}
|
|
@@ -234,7 +239,7 @@ class Portal {
|
|
|
234
239
|
throw new Error('orgBackupShare cannot be empty string.')
|
|
235
240
|
}
|
|
236
241
|
|
|
237
|
-
const
|
|
242
|
+
const { SECP256K1, ED25519 } = await this.mpc.eject({
|
|
238
243
|
cipherText: clientBackupCipherText,
|
|
239
244
|
backupMethod,
|
|
240
245
|
backupConfigs,
|
|
@@ -244,17 +249,73 @@ class Portal {
|
|
|
244
249
|
featureFlags: this.featureFlags,
|
|
245
250
|
})
|
|
246
251
|
|
|
247
|
-
return
|
|
252
|
+
return {
|
|
253
|
+
SECP256K1,
|
|
254
|
+
ED25519,
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
public async getEip155Address(): Promise<string> {
|
|
259
|
+
const client = await this.mpc?.getClient()
|
|
260
|
+
const eip155Address = client?.metadata?.namespaces?.eip155?.address || ''
|
|
261
|
+
return eip155Address
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
public async getSolanaAddress(): Promise<string> {
|
|
265
|
+
const client = await this.mpc?.getClient()
|
|
266
|
+
const solAddress = client?.metadata?.namespaces?.solana?.address || ''
|
|
267
|
+
return solAddress
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
public async doesWalletExist(chainId?: string): Promise<boolean> {
|
|
271
|
+
const client = await this.mpc?.getClient()
|
|
272
|
+
|
|
273
|
+
if (chainId) {
|
|
274
|
+
const namespace = chainId?.split(':')?.[0] || ''
|
|
275
|
+
const namespaceInfo = client?.metadata?.namespaces?.[namespace]
|
|
276
|
+
return !!namespaceInfo
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
return client?.wallets?.length > 0
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
public async isWalletOnDevice(chainId?: string): Promise<boolean> {
|
|
283
|
+
const client = await this.mpc?.getClient()
|
|
284
|
+
const sharesOnDevice = await this.mpc?.checkSharesOnDevice()
|
|
285
|
+
|
|
286
|
+
if (chainId) {
|
|
287
|
+
const namespace = chainId?.split(':')?.[0] || ''
|
|
288
|
+
const curve = client?.metadata?.namespaces?.[namespace]?.curve || ''
|
|
289
|
+
return sharesOnDevice[curve as keyof SharesOnDeviceResponse] || false
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
return sharesOnDevice.ED25519 && sharesOnDevice.SECP256K1
|
|
248
293
|
}
|
|
249
294
|
|
|
250
295
|
/****************************
|
|
251
296
|
* Provider Methods
|
|
252
297
|
****************************/
|
|
253
298
|
|
|
299
|
+
public async request(request: RequestArguments): Promise<any> {
|
|
300
|
+
return this.provider.request(request)
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Estimates the amount of gas that will be required to execute an Ethereum transaction.
|
|
305
|
+
*
|
|
306
|
+
* @deprecated This method is deprecated. Use `portal.request` with method 'eth_estimateGas' instead.
|
|
307
|
+
*
|
|
308
|
+
* @param {string} chainId - The chain ID of the Ethereum network.
|
|
309
|
+
* @param {EthereumTransaction} transaction - The transaction object containing the necessary transaction details.
|
|
310
|
+
* @returns {Promise<any>} A Promise that resolves to the gas estimate.
|
|
311
|
+
*/
|
|
254
312
|
public async ethEstimateGas(
|
|
313
|
+
chainId: string,
|
|
255
314
|
transaction: EthereumTransaction,
|
|
256
|
-
chainId?: string,
|
|
257
315
|
): Promise<any> {
|
|
316
|
+
console.warn(
|
|
317
|
+
'"portal.ethEstimateGas" is deprecated. Use "portal.request" instead.',
|
|
318
|
+
)
|
|
258
319
|
return this.provider.request({
|
|
259
320
|
chainId,
|
|
260
321
|
method: 'eth_estimateGas',
|
|
@@ -262,7 +323,18 @@ class Portal {
|
|
|
262
323
|
})
|
|
263
324
|
}
|
|
264
325
|
|
|
265
|
-
|
|
326
|
+
/**
|
|
327
|
+
* Gets the current gas price for the Ethereum network.
|
|
328
|
+
*
|
|
329
|
+
* @deprecated This method is deprecated. Use `portal.request` with method 'eth_gasPrice' instead.
|
|
330
|
+
*
|
|
331
|
+
* @param {string} chainId - The chain ID of the Ethereum network.
|
|
332
|
+
* @returns {Promise<string>} A Promise that resolves to the current gas price.
|
|
333
|
+
*/
|
|
334
|
+
public async ethGasPrice(chainId: string): Promise<string> {
|
|
335
|
+
console.warn(
|
|
336
|
+
'"portal.ethGasPrice" is deprecated. Use "portal.request" instead.',
|
|
337
|
+
)
|
|
266
338
|
return this.provider.request({
|
|
267
339
|
chainId,
|
|
268
340
|
method: 'eth_gasPrice',
|
|
@@ -270,7 +342,18 @@ class Portal {
|
|
|
270
342
|
}) as Promise<string>
|
|
271
343
|
}
|
|
272
344
|
|
|
273
|
-
|
|
345
|
+
/**
|
|
346
|
+
* Gets the balance of the current Ethereum address.
|
|
347
|
+
*
|
|
348
|
+
* @deprecated This method is deprecated. Use `portal.request` with method 'eth_getBalance' instead.
|
|
349
|
+
*
|
|
350
|
+
* @param {string} chainId - The chain ID of the Ethereum network.
|
|
351
|
+
* @returns {Promise<string>} A Promise that resolves to the current balance.
|
|
352
|
+
*/
|
|
353
|
+
public async ethGetBalance(chainId: string): Promise<string> {
|
|
354
|
+
console.warn(
|
|
355
|
+
'"portal.ethGetBalance" is deprecated. Use "portal.request" instead.',
|
|
356
|
+
)
|
|
274
357
|
return this.provider.request({
|
|
275
358
|
chainId,
|
|
276
359
|
method: 'eth_getBalance',
|
|
@@ -278,10 +361,22 @@ class Portal {
|
|
|
278
361
|
}) as Promise<string>
|
|
279
362
|
}
|
|
280
363
|
|
|
364
|
+
/**
|
|
365
|
+
* Sends an Ethereum transaction.
|
|
366
|
+
*
|
|
367
|
+
* @deprecated This method is deprecated. Use `portal.request` with method 'eth_getTransactionCount' instead.
|
|
368
|
+
*
|
|
369
|
+
* @param {string} chainId - The chain ID of the Ethereum network.
|
|
370
|
+
* @param {EthereumTransaction} transaction - The transaction object containing the necessary transaction details.
|
|
371
|
+
* @returns {Promise<string>} A Promise that resolves to the transaction hash.
|
|
372
|
+
*/
|
|
281
373
|
public async ethSendTransaction(
|
|
374
|
+
chainId: string,
|
|
282
375
|
transaction: EthereumTransaction,
|
|
283
|
-
chainId?: string,
|
|
284
376
|
): Promise<string> {
|
|
377
|
+
console.warn(
|
|
378
|
+
'"portal.ethSendTransaction" is deprecated. Use "portal.request" instead.',
|
|
379
|
+
)
|
|
285
380
|
return this.provider.request({
|
|
286
381
|
chainId,
|
|
287
382
|
method: 'eth_sendTransaction',
|
|
@@ -289,18 +384,22 @@ class Portal {
|
|
|
289
384
|
}) as Promise<string>
|
|
290
385
|
}
|
|
291
386
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
387
|
+
/**
|
|
388
|
+
* Signs an Ethereum transaction.
|
|
389
|
+
*
|
|
390
|
+
* @deprecated This method is deprecated. Use `portal.request` with method 'eth_signTransaction' instead.
|
|
391
|
+
*
|
|
392
|
+
* @param {string} chainId - The chain ID of the Ethereum network.
|
|
393
|
+
* @param {EthereumTransaction} transaction - The transaction object containing the necessary transaction details.
|
|
394
|
+
* @returns {Promise<string>} A Promise that resolves to the signed transaction.
|
|
395
|
+
*/
|
|
300
396
|
public async ethSignTransaction(
|
|
397
|
+
chainId: string,
|
|
301
398
|
transaction: EthereumTransaction,
|
|
302
|
-
chainId?: string,
|
|
303
399
|
): Promise<string> {
|
|
400
|
+
console.warn(
|
|
401
|
+
'"portal.ethSignTransaction" is deprecated. Use "portal.request" instead.',
|
|
402
|
+
)
|
|
304
403
|
return this.provider.request({
|
|
305
404
|
chainId,
|
|
306
405
|
method: 'eth_signTransaction',
|
|
@@ -308,10 +407,22 @@ class Portal {
|
|
|
308
407
|
}) as Promise<string>
|
|
309
408
|
}
|
|
310
409
|
|
|
410
|
+
/**
|
|
411
|
+
* Signs an Ethereum message using EIP-712.
|
|
412
|
+
*
|
|
413
|
+
* @deprecated This method is deprecated. Use `portal.request` with method 'eth_signTypedData' instead.
|
|
414
|
+
*
|
|
415
|
+
* @param {string} chainId - The chain ID of the Ethereum network.
|
|
416
|
+
* @param {TypedData} data - The typed data object to sign.
|
|
417
|
+
* @returns {Promise<string>} A Promise that resolves to the signed message.
|
|
418
|
+
*/
|
|
311
419
|
public async ethSignTypedData(
|
|
420
|
+
chainId: string,
|
|
312
421
|
data: TypedData,
|
|
313
|
-
chainId?: string,
|
|
314
422
|
): Promise<string> {
|
|
423
|
+
console.warn(
|
|
424
|
+
'"portal.ethSignTypedData" is deprecated. Use "portal.request" instead.',
|
|
425
|
+
)
|
|
315
426
|
return this.provider.request({
|
|
316
427
|
chainId,
|
|
317
428
|
method: 'eth_signTypedData',
|
|
@@ -319,10 +430,22 @@ class Portal {
|
|
|
319
430
|
}) as Promise<string>
|
|
320
431
|
}
|
|
321
432
|
|
|
433
|
+
/**
|
|
434
|
+
* Signs an Ethereum message using EIP-712 (legacy).
|
|
435
|
+
*
|
|
436
|
+
* @deprecated This method is deprecated. Use `portal.request` with method 'eth_signTypedData_v3' instead.
|
|
437
|
+
*
|
|
438
|
+
* @param {string} chainId - The chain ID of the Ethereum network.
|
|
439
|
+
* @param {TypedData} data - The typed data object to sign.
|
|
440
|
+
* @returns {Promise<string>} A Promise that resolves to the signed message.
|
|
441
|
+
*/
|
|
322
442
|
public async ethSignTypedDataV3(
|
|
443
|
+
chainId: string,
|
|
323
444
|
data: TypedData,
|
|
324
|
-
chainId?: string,
|
|
325
445
|
): Promise<string> {
|
|
446
|
+
console.warn(
|
|
447
|
+
'"portal.ethSignTypedDataV3" is deprecated. Use "portal.request" instead.',
|
|
448
|
+
)
|
|
326
449
|
return this.provider.request({
|
|
327
450
|
chainId,
|
|
328
451
|
method: 'eth_signTypedData_v3',
|
|
@@ -330,10 +453,22 @@ class Portal {
|
|
|
330
453
|
}) as Promise<string>
|
|
331
454
|
}
|
|
332
455
|
|
|
456
|
+
/**
|
|
457
|
+
* Signs an Ethereum message using EIP-712 (v4).
|
|
458
|
+
*
|
|
459
|
+
* @deprecated This method is deprecated. Use `portal.request` with method 'eth_signTypedData_v4' instead.
|
|
460
|
+
*
|
|
461
|
+
* @param {string} chainId - The chain ID of the Ethereum network.
|
|
462
|
+
* @param {TypedData} data - The typed data object to sign.
|
|
463
|
+
* @returns {Promise<string>} A Promise that resolves to the signed message.
|
|
464
|
+
*/
|
|
333
465
|
public async ethSignTypedDataV4(
|
|
466
|
+
chainId: string,
|
|
334
467
|
data: TypedData,
|
|
335
|
-
chainId?: string,
|
|
336
468
|
): Promise<string> {
|
|
469
|
+
console.warn(
|
|
470
|
+
'"portal.ethSignTypedDataV4" is deprecated. Use "portal.request" instead.',
|
|
471
|
+
)
|
|
337
472
|
return this.provider.request({
|
|
338
473
|
chainId,
|
|
339
474
|
method: 'eth_signTypedData_v4',
|
|
@@ -341,10 +476,10 @@ class Portal {
|
|
|
341
476
|
}) as Promise<string>
|
|
342
477
|
}
|
|
343
478
|
|
|
344
|
-
public async personalSign(
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
479
|
+
public async personalSign(chainId: string, message: string): Promise<string> {
|
|
480
|
+
console.warn(
|
|
481
|
+
'"portal.personalSign" is deprecated. Use "portal.request" instead.',
|
|
482
|
+
)
|
|
348
483
|
return (await this.provider.request({
|
|
349
484
|
chainId,
|
|
350
485
|
method: 'personal_sign',
|
|
@@ -352,43 +487,162 @@ class Portal {
|
|
|
352
487
|
})) as Promise<string>
|
|
353
488
|
}
|
|
354
489
|
|
|
490
|
+
public async sendSol({
|
|
491
|
+
chainId,
|
|
492
|
+
to,
|
|
493
|
+
lamports,
|
|
494
|
+
}: {
|
|
495
|
+
chainId: string
|
|
496
|
+
to: string
|
|
497
|
+
lamports: number
|
|
498
|
+
}): Promise<string> {
|
|
499
|
+
// Ensure the chainId is solana.
|
|
500
|
+
if (!chainId.startsWith('solana:')) {
|
|
501
|
+
throw new Error(
|
|
502
|
+
'[Portal] Invalid chainId. Please provide a chainId that starts with "solana:"',
|
|
503
|
+
)
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// Ensure the to address is a valid Solana address.
|
|
507
|
+
if (!to || typeof to !== 'string' || to.length !== 44) {
|
|
508
|
+
throw new Error(
|
|
509
|
+
'[Portal] Invalid "to" Solana address provided, must be 44 characters',
|
|
510
|
+
)
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// Validate the lamports.
|
|
514
|
+
if (typeof lamports !== 'number' || lamports <= 0) {
|
|
515
|
+
throw new Error(
|
|
516
|
+
'[Portal] Invalid lamports amount, must be a positive number greater than 0',
|
|
517
|
+
)
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// Get the most recent blockhash.
|
|
521
|
+
const blockhashResponse = await this.provider.request({
|
|
522
|
+
chainId: chainId,
|
|
523
|
+
method: 'getLatestBlockhash',
|
|
524
|
+
params: [],
|
|
525
|
+
})
|
|
526
|
+
const blockhash = blockhashResponse?.value?.blockhash || ''
|
|
527
|
+
|
|
528
|
+
// If we didn't get a blockhash, throw an error.
|
|
529
|
+
if (!blockhash) {
|
|
530
|
+
throw new Error('[Portal] Failed to get most recent blockhash')
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// Get the Solana address from the client, validate the addresses.
|
|
534
|
+
const solanaAddress = await this.getSolanaAddress()
|
|
535
|
+
if (!solanaAddress) {
|
|
536
|
+
throw new Error('[Portal] Failed to get Solana address')
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// Get the Solana gateway URL.
|
|
540
|
+
const gatewayUrl = this.getRpcUrl(chainId)
|
|
541
|
+
if (!gatewayUrl) {
|
|
542
|
+
throw new Error('[Portal] No RPC endpoint configured for chainId')
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
// Create a new connection to the Solana network.
|
|
546
|
+
new Connection(gatewayUrl, 'confirmed')
|
|
547
|
+
|
|
548
|
+
// The sender's public key.
|
|
549
|
+
const fromPublicKey = new PublicKey(solanaAddress)
|
|
550
|
+
|
|
551
|
+
// The recipient's public key.
|
|
552
|
+
const toPublicKey = new PublicKey(to)
|
|
553
|
+
|
|
554
|
+
// Create a new transaction.
|
|
555
|
+
const transaction = new SolanaTransaction().add(
|
|
556
|
+
SystemProgram.transfer({
|
|
557
|
+
fromPubkey: fromPublicKey,
|
|
558
|
+
toPubkey: toPublicKey,
|
|
559
|
+
lamports,
|
|
560
|
+
}),
|
|
561
|
+
)
|
|
562
|
+
transaction.recentBlockhash = blockhash
|
|
563
|
+
transaction.feePayer = fromPublicKey
|
|
564
|
+
const compiledMessage = transaction.compileMessage()
|
|
565
|
+
|
|
566
|
+
// Build the transaction and its message.
|
|
567
|
+
const message = {
|
|
568
|
+
accountKeys: compiledMessage.accountKeys.map((key) => key.toBase58()),
|
|
569
|
+
header: compiledMessage.header,
|
|
570
|
+
instructions: compiledMessage.instructions,
|
|
571
|
+
recentBlockhash: blockhash,
|
|
572
|
+
}
|
|
573
|
+
const formattedTransaction = {
|
|
574
|
+
signatures: null,
|
|
575
|
+
message,
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
// Attempt to sign and send the transaction
|
|
579
|
+
const transactionResult = await this.provider.request({
|
|
580
|
+
chainId: chainId,
|
|
581
|
+
method: 'sol_signAndSendTransaction',
|
|
582
|
+
params: [formattedTransaction],
|
|
583
|
+
})
|
|
584
|
+
|
|
585
|
+
// If we didn't get a transactionResult, throw an error.
|
|
586
|
+
if (!transactionResult) {
|
|
587
|
+
throw new Error('[Portal] Failed to send Solana transaction')
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
// Return the transactionResult.
|
|
591
|
+
return transactionResult
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
public sendEth = async ({
|
|
595
|
+
chainId,
|
|
596
|
+
to,
|
|
597
|
+
value,
|
|
598
|
+
}: {
|
|
599
|
+
chainId: string
|
|
600
|
+
to: string
|
|
601
|
+
value: string
|
|
602
|
+
}) => {
|
|
603
|
+
return this.provider.request({
|
|
604
|
+
chainId,
|
|
605
|
+
method: 'eth_sendTransaction',
|
|
606
|
+
params: [
|
|
607
|
+
{
|
|
608
|
+
from: this.address,
|
|
609
|
+
to,
|
|
610
|
+
value,
|
|
611
|
+
},
|
|
612
|
+
],
|
|
613
|
+
})
|
|
614
|
+
}
|
|
615
|
+
|
|
355
616
|
/*******************************
|
|
356
617
|
* API Methods
|
|
357
618
|
*******************************/
|
|
358
619
|
|
|
359
|
-
public async getBalances(): Promise<Balance[]> {
|
|
360
|
-
return await this.mpc?.getBalances()
|
|
620
|
+
public async getBalances(chainId: string): Promise<Balance[]> {
|
|
621
|
+
return await this.mpc?.getBalances(chainId)
|
|
361
622
|
}
|
|
362
623
|
|
|
363
624
|
public async getClient(): Promise<ClientResponse> {
|
|
364
625
|
return this.mpc?.getClient()
|
|
365
626
|
}
|
|
366
627
|
|
|
367
|
-
public async getNFTs(): Promise<NFT[]> {
|
|
368
|
-
return this.mpc?.getNFTs()
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
public async getBackupShareMetadata(): Promise<BackupSharePairMetadata[]> {
|
|
372
|
-
return this.mpc?.getBackupShareMetadata()
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
public async getSigningShareMetadata(): Promise<SigningSharePairMetadata[]> {
|
|
376
|
-
return this.mpc?.getSigningShareMetadata()
|
|
628
|
+
public async getNFTs(chainId: string): Promise<NFT[]> {
|
|
629
|
+
return this.mpc?.getNFTs(chainId)
|
|
377
630
|
}
|
|
378
631
|
|
|
379
632
|
public async getTransactions(
|
|
633
|
+
chainId: string,
|
|
380
634
|
limit?: number,
|
|
381
635
|
offset?: number,
|
|
382
636
|
order?: GetTransactionsOrder,
|
|
383
|
-
chainId?: string,
|
|
384
637
|
): Promise<Transaction[]> {
|
|
385
|
-
return this.mpc?.getTransactions(limit, offset, order
|
|
638
|
+
return this.mpc?.getTransactions(chainId, limit, offset, order)
|
|
386
639
|
}
|
|
387
640
|
|
|
388
641
|
public async simulateTransaction(
|
|
642
|
+
chainId: string,
|
|
389
643
|
transaction: SimulateTransactionParam,
|
|
390
644
|
): Promise<SimulatedTransaction> {
|
|
391
|
-
return this.mpc?.simulateTransaction(transaction)
|
|
645
|
+
return this.mpc?.simulateTransaction(transaction, chainId)
|
|
392
646
|
}
|
|
393
647
|
|
|
394
648
|
/*******************************
|
|
@@ -398,14 +652,14 @@ class Portal {
|
|
|
398
652
|
public async getQuote(
|
|
399
653
|
apiKey: string,
|
|
400
654
|
args: QuoteArgs,
|
|
401
|
-
chainId
|
|
655
|
+
chainId: string,
|
|
402
656
|
): Promise<QuoteResponse> {
|
|
403
657
|
return this.mpc?.getQuote(apiKey, args, chainId)
|
|
404
658
|
}
|
|
405
659
|
|
|
406
660
|
public async getSources(
|
|
407
661
|
apiKey: string,
|
|
408
|
-
chainId
|
|
662
|
+
chainId: string,
|
|
409
663
|
): Promise<Record<string, string>> {
|
|
410
664
|
return this.mpc?.getSources(apiKey, chainId)
|
|
411
665
|
}
|
|
@@ -425,31 +679,33 @@ class Portal {
|
|
|
425
679
|
* RPC Methods
|
|
426
680
|
****************************/
|
|
427
681
|
|
|
428
|
-
public getRpcUrl() {
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
682
|
+
public getRpcUrl(chainId?: string) {
|
|
683
|
+
// Ensure a chainId is provided.
|
|
684
|
+
if (!chainId) {
|
|
685
|
+
throw new Error(
|
|
686
|
+
'[Portal] No chainId provided. Please provide a chainId to get the RPC endpoint',
|
|
687
|
+
)
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
// Ensure the chainId is configured in the rpcConfig.
|
|
691
|
+
// eslint-disable-next-line no-prototype-builtins
|
|
692
|
+
if (!this.rpcConfig.hasOwnProperty(chainId)) {
|
|
438
693
|
throw new Error(
|
|
439
|
-
`[
|
|
694
|
+
`[Portal] No RPC endpoint configured for chainId: ${chainId}`,
|
|
440
695
|
)
|
|
441
696
|
}
|
|
442
697
|
|
|
443
|
-
//
|
|
444
|
-
const
|
|
698
|
+
// Derive the RPC endpoint from the rpcConfig.
|
|
699
|
+
const gatewayUrl = this.rpcConfig[chainId]
|
|
445
700
|
|
|
446
|
-
|
|
447
|
-
|
|
701
|
+
// If the RPC endpoint is a string, return it as-is.
|
|
702
|
+
if (typeof gatewayUrl === 'string') {
|
|
703
|
+
return gatewayUrl
|
|
448
704
|
}
|
|
449
705
|
|
|
450
|
-
//
|
|
706
|
+
// Otherwise, something is wrong with the configuration.
|
|
451
707
|
throw new Error(
|
|
452
|
-
`[
|
|
708
|
+
`[Portal] Could not find a valid rpcConfig entry for chainId: ${chainId}`,
|
|
453
709
|
)
|
|
454
710
|
}
|
|
455
711
|
|
package/src/mpc/errors/index.ts
CHANGED
|
@@ -72,7 +72,7 @@ export class MpcError extends Error {
|
|
|
72
72
|
super(error.message(context))
|
|
73
73
|
|
|
74
74
|
// Custom error context
|
|
75
|
-
this.code = error
|
|
75
|
+
this.code = error?.code || 999
|
|
76
76
|
if (context) {
|
|
77
77
|
this.context = context
|
|
78
78
|
}
|
|
@@ -160,7 +160,7 @@ export class PortalMpcError extends Error {
|
|
|
160
160
|
public constructor(error: PortalError) {
|
|
161
161
|
super(error.message)
|
|
162
162
|
|
|
163
|
-
this.code = error
|
|
163
|
+
this.code = error?.code || 999
|
|
164
164
|
}
|
|
165
165
|
}
|
|
166
166
|
|