@@ -37,7 +37,7 @@ import {
37
37
TokenInfoResponse ,
38
38
TransferListResponse
39
39
} from '@safe-global/api-kit/types/safeTransactionServiceTypes'
40
- import { HttpMethod , sendRequest } from '@safe-global/api-kit/utils/httpRequests'
40
+ import { HttpMethod , HttpRequest , sendRequest } from '@safe-global/api-kit/utils/httpRequests'
41
41
import { signDelegate } from '@safe-global/api-kit/utils/signDelegate'
42
42
import { validateEip3770Address , validateEthereumAddress } from '@safe-global/protocol-kit'
43
43
import {
@@ -50,7 +50,7 @@ import {
50
50
SafeOperationResponse ,
51
51
UserOperationV06
52
52
} from '@safe-global/types-kit'
53
- import { TRANSACTION_SERVICE_URLS } from './utils/config'
53
+ import { getTransactionServiceUrl } from './utils/config'
54
54
import { isEmptyData } from './utils'
55
55
import { getAddSafeOperationProps , isSafeOperation } from './utils/safeOperation'
56
56
import { QUERY_PARAMS_MAP } from './utils/queryParamsMap'
@@ -60,19 +60,43 @@ export interface SafeApiKitConfig {
60
60
chainId : bigint
61
61
/** txServiceUrl - Safe Transaction Service URL */
62
62
txServiceUrl ?: string
63
+ /**
64
+ * apiKey - The API key to access the Safe Transaction Service.
65
+ * - Required if txServiceUrl is undefined
66
+ * - Required if txServiceUrl contains "safe.global" or "5afe.dev"
67
+ * - Optional otherwise
68
+ */
69
+ apiKey ?: string
63
70
}
64
71
65
72
class SafeApiKit {
66
73
#chainId: bigint
74
+ #apiKey?: string
67
75
#txServiceBaseUrl: string
68
76
69
- constructor ( { chainId, txServiceUrl } : SafeApiKitConfig ) {
77
+ constructor ( { chainId, txServiceUrl, apiKey } : SafeApiKitConfig ) {
70
78
this . #chainId = chainId
71
79
72
80
if ( txServiceUrl ) {
81
+ // If txServiceUrl contains safe.global or 5afe.dev, apiKey is mandatory
82
+ if (
83
+ ( txServiceUrl . includes ( 'api.safe.global' ) || txServiceUrl . includes ( 'api.5afe.dev' ) ) &&
84
+ ! apiKey
85
+ ) {
86
+ throw new Error (
87
+ 'apiKey is mandatory when using api.safe.global or api.5afe.dev domains. Please obtain your API key at https://developer.safe.global.'
88
+ )
89
+ }
73
90
this . #txServiceBaseUrl = txServiceUrl
74
91
} else {
75
- const url = TRANSACTION_SERVICE_URLS [ chainId . toString ( ) ]
92
+ // If txServiceUrl is not defined, apiKey is mandatory
93
+ if ( ! apiKey ) {
94
+ throw new Error (
95
+ 'apiKey is mandatory when txServiceUrl is not defined. Please obtain your API key at https://developer.safe.global.'
96
+ )
97
+ }
98
+
99
+ const url = getTransactionServiceUrl ( chainId )
76
100
if ( ! url ) {
77
101
throw new TypeError (
78
102
`There is no transaction service available for chainId ${ chainId } . Please set the txServiceUrl property to use a custom transaction service.`
@@ -81,6 +105,8 @@ class SafeApiKit {
81
105
82
106
this . #txServiceBaseUrl = url
83
107
}
108
+
109
+ this . #apiKey = apiKey
84
110
}
85
111
86
112
#isValidAddress( address : string ) {
@@ -119,13 +145,17 @@ class SafeApiKit {
119
145
} )
120
146
}
121
147
148
+ async #api< T > ( request : HttpRequest ) : Promise < T > {
149
+ return sendRequest ( request , this . #apiKey)
150
+ }
151
+
122
152
/**
123
153
* Returns the information and configuration of the service.
124
154
*
125
155
* @returns The information and configuration of the service
126
156
*/
127
157
async getServiceInfo ( ) : Promise < SafeServiceInfoResponse > {
128
- return sendRequest ( {
158
+ return this . #api ( {
129
159
url : `${ this . #txServiceBaseUrl} /v1/about` ,
130
160
method : HttpMethod . Get
131
161
} )
@@ -137,7 +167,7 @@ class SafeApiKit {
137
167
* @returns The list of Safe singletons
138
168
*/
139
169
async getServiceSingletonsInfo ( ) : Promise < SafeSingletonResponse [ ] > {
140
- return sendRequest ( {
170
+ return this . #api ( {
141
171
url : `${ this . #txServiceBaseUrl} /v1/about/singletons` ,
142
172
method : HttpMethod . Get
143
173
} )
@@ -164,7 +194,7 @@ class SafeApiKit {
164
194
dataDecoderRequest . to = to
165
195
}
166
196
167
- return sendRequest ( {
197
+ return this . #api ( {
168
198
url : `${ this . #txServiceBaseUrl} /v1/data-decoder/` ,
169
199
method : HttpMethod . Post ,
170
200
body : dataDecoderRequest
@@ -210,7 +240,7 @@ class SafeApiKit {
210
240
url . searchParams . set ( 'offset' , offset . toString ( ) )
211
241
}
212
242
213
- return sendRequest ( {
243
+ return this . #api ( {
214
244
url : url . toString ( ) ,
215
245
method : HttpMethod . Get
216
246
} )
@@ -256,7 +286,7 @@ class SafeApiKit {
256
286
label,
257
287
signature
258
288
}
259
- return sendRequest ( {
289
+ return this . #api ( {
260
290
url : `${ this . #txServiceBaseUrl} /v2/delegates/` ,
261
291
method : HttpMethod . Post ,
262
292
body
@@ -289,7 +319,7 @@ class SafeApiKit {
289
319
const { address : delegator } = this . #getEip3770Address( delegatorAddress )
290
320
const signature = await signDelegate ( signer , delegate , this . #chainId)
291
321
292
- return sendRequest ( {
322
+ return this . #api ( {
293
323
url : `${ this . #txServiceBaseUrl} /v2/delegates/${ delegate } ` ,
294
324
method : HttpMethod . Delete ,
295
325
body : {
@@ -309,7 +339,7 @@ class SafeApiKit {
309
339
throw new Error ( 'Invalid messageHash' )
310
340
}
311
341
312
- return sendRequest ( {
342
+ return this . #api ( {
313
343
url : `${ this . #txServiceBaseUrl} /v1/messages/${ messageHash } /` ,
314
344
method : HttpMethod . Get
315
345
} )
@@ -334,7 +364,7 @@ class SafeApiKit {
334
364
// Check if options are given and add query parameters
335
365
this . #addUrlQueryParams< GetSafeMessageListOptions > ( url , options )
336
366
337
- return sendRequest ( {
367
+ return this . #api ( {
338
368
url : url . toString ( ) ,
339
369
method : HttpMethod . Get
340
370
} )
@@ -351,7 +381,7 @@ class SafeApiKit {
351
381
throw new Error ( 'Invalid safeAddress' )
352
382
}
353
383
354
- return sendRequest ( {
384
+ return this . #api ( {
355
385
url : `${ this . #txServiceBaseUrl} /v1/safes/${ safeAddress } /messages/` ,
356
386
method : HttpMethod . Post ,
357
387
body : addMessageOptions
@@ -368,7 +398,7 @@ class SafeApiKit {
368
398
throw new Error ( 'Invalid messageHash or signature' )
369
399
}
370
400
371
- return sendRequest ( {
401
+ return this . #api ( {
372
402
url : `${ this . #txServiceBaseUrl} /v1/messages/${ messageHash } /signatures/` ,
373
403
method : HttpMethod . Post ,
374
404
body : {
@@ -390,7 +420,7 @@ class SafeApiKit {
390
420
throw new Error ( 'Invalid owner address' )
391
421
}
392
422
const { address } = this . #getEip3770Address( ownerAddress )
393
- return sendRequest ( {
423
+ return this . #api ( {
394
424
url : `${ this . #txServiceBaseUrl} /v1/owners/${ address } /safes/` ,
395
425
method : HttpMethod . Get
396
426
} )
@@ -409,7 +439,7 @@ class SafeApiKit {
409
439
throw new Error ( 'Invalid module address' )
410
440
}
411
441
const { address } = this . #getEip3770Address( moduleAddress )
412
- return sendRequest ( {
442
+ return this . #api ( {
413
443
url : `${ this . #txServiceBaseUrl} /v1/modules/${ address } /safes/` ,
414
444
method : HttpMethod . Get
415
445
} )
@@ -427,7 +457,7 @@ class SafeApiKit {
427
457
if ( safeTxHash === '' ) {
428
458
throw new Error ( 'Invalid safeTxHash' )
429
459
}
430
- return sendRequest ( {
460
+ return this . #api ( {
431
461
url : `${ this . #txServiceBaseUrl} /v2/multisig-transactions/${ safeTxHash } /` ,
432
462
method : HttpMethod . Get
433
463
} )
@@ -446,7 +476,7 @@ class SafeApiKit {
446
476
if ( safeTxHash === '' ) {
447
477
throw new Error ( 'Invalid safeTxHash' )
448
478
}
449
- return sendRequest ( {
479
+ return this . #api ( {
450
480
url : `${ this . #txServiceBaseUrl} /v1/multisig-transactions/${ safeTxHash } /confirmations/` ,
451
481
method : HttpMethod . Get
452
482
} )
@@ -470,7 +500,7 @@ class SafeApiKit {
470
500
if ( signature === '' ) {
471
501
throw new Error ( 'Invalid signature' )
472
502
}
473
- return sendRequest ( {
503
+ return this . #api ( {
474
504
url : `${ this . #txServiceBaseUrl} /v1/multisig-transactions/${ safeTxHash } /confirmations/` ,
475
505
method : HttpMethod . Post ,
476
506
body : {
@@ -492,7 +522,7 @@ class SafeApiKit {
492
522
throw new Error ( 'Invalid Safe address' )
493
523
}
494
524
const { address } = this . #getEip3770Address( safeAddress )
495
- return sendRequest ( {
525
+ return this . #api ( {
496
526
url : `${ this . #txServiceBaseUrl} /v1/safes/${ address } /` ,
497
527
method : HttpMethod . Get
498
528
} ) . then ( ( response : any ) => {
@@ -521,7 +551,7 @@ class SafeApiKit {
521
551
throw new Error ( 'Invalid Safe address' )
522
552
}
523
553
const { address } = this . #getEip3770Address( safeAddress )
524
- return sendRequest ( {
554
+ return this . #api ( {
525
555
url : `${ this . #txServiceBaseUrl} /v1/safes/${ address } /creation/` ,
526
556
method : HttpMethod . Get
527
557
} ) . then ( ( response : any ) => {
@@ -554,7 +584,7 @@ class SafeApiKit {
554
584
throw new Error ( 'Invalid Safe address' )
555
585
}
556
586
const { address } = this . #getEip3770Address( safeAddress )
557
- return sendRequest ( {
587
+ return this . #api ( {
558
588
url : `${ this . #txServiceBaseUrl} /v1/safes/${ address } /multisig-transactions/estimations/` ,
559
589
method : HttpMethod . Post ,
560
590
body : safeTransaction
@@ -587,7 +617,7 @@ class SafeApiKit {
587
617
if ( safeTxHash === '' ) {
588
618
throw new Error ( 'Invalid safeTxHash' )
589
619
}
590
- return sendRequest ( {
620
+ return this . #api ( {
591
621
url : `${ this . #txServiceBaseUrl} /v2/safes/${ safe } /multisig-transactions/` ,
592
622
method : HttpMethod . Post ,
593
623
body : {
@@ -622,7 +652,7 @@ class SafeApiKit {
622
652
// Check if options are given and add query parameters
623
653
this . #addUrlQueryParams< GetIncomingTransactionsOptions > ( url , options )
624
654
625
- return sendRequest ( {
655
+ return this . #api ( {
626
656
url : url . toString ( ) ,
627
657
method : HttpMethod . Get
628
658
} )
@@ -651,7 +681,7 @@ class SafeApiKit {
651
681
// Check if options are given and add query parameters
652
682
this . #addUrlQueryParams< GetModuleTransactionsOptions > ( url , options )
653
683
654
- return sendRequest ( {
684
+ return this . #api ( {
655
685
url : url . toString ( ) ,
656
686
method : HttpMethod . Get
657
687
} )
@@ -680,7 +710,7 @@ class SafeApiKit {
680
710
// Check if options are given and add query parameters
681
711
this . #addUrlQueryParams< GetMultisigTransactionsOptions > ( url , options )
682
712
683
- return sendRequest ( {
713
+ return this . #api ( {
684
714
url : url . toString ( ) ,
685
715
method : HttpMethod . Get
686
716
} )
@@ -728,7 +758,7 @@ class SafeApiKit {
728
758
url . searchParams . set ( 'offset' , offset . toString ( ) )
729
759
}
730
760
731
- return sendRequest ( {
761
+ return this . #api ( {
732
762
url : url . toString ( ) ,
733
763
method : HttpMethod . Get
734
764
} )
@@ -757,7 +787,7 @@ class SafeApiKit {
757
787
// Check if options are given and add query parameters
758
788
this . #addUrlQueryParams< AllTransactionsOptions > ( url , options )
759
789
760
- return sendRequest ( {
790
+ return this . #api ( {
761
791
url : url . toString ( ) ,
762
792
method : HttpMethod . Get
763
793
} )
@@ -802,7 +832,7 @@ class SafeApiKit {
802
832
// Check if options are given and add query parameters
803
833
this . #addUrlQueryParams< TokenInfoListOptions > ( url , options )
804
834
805
- return sendRequest ( {
835
+ return this . #api ( {
806
836
url : url . toString ( ) ,
807
837
method : HttpMethod . Get
808
838
} )
@@ -821,7 +851,7 @@ class SafeApiKit {
821
851
throw new Error ( 'Invalid token address' )
822
852
}
823
853
const { address } = this . #getEip3770Address( tokenAddress )
824
- return sendRequest ( {
854
+ return this . #api ( {
825
855
url : `${ this . #txServiceBaseUrl} /v1/tokens/${ address } /` ,
826
856
method : HttpMethod . Get
827
857
} )
@@ -850,7 +880,7 @@ class SafeApiKit {
850
880
// Check if options are given and add query parameters
851
881
this . #addUrlQueryParams< TokenInfoListOptions > ( url , options )
852
882
853
- return sendRequest ( {
883
+ return this . #api ( {
854
884
url : url . toString ( ) ,
855
885
method : HttpMethod . Get
856
886
} )
@@ -886,7 +916,7 @@ class SafeApiKit {
886
916
throw new Error ( 'SafeOperation hash must not be empty' )
887
917
}
888
918
889
- return sendRequest ( {
919
+ return this . #api ( {
890
920
url : `${ this . #txServiceBaseUrl} /v1/safe-operations/${ safeOperationHash } /` ,
891
921
method : HttpMethod . Get
892
922
} )
@@ -947,7 +977,7 @@ class SafeApiKit {
947
977
948
978
const userOperationV06 = userOperation as UserOperationV06
949
979
950
- return sendRequest ( {
980
+ return this . #api ( {
951
981
url : `${ this . #txServiceBaseUrl} /v1/safes/${ safeAddress } /safe-operations/` ,
952
982
method : HttpMethod . Post ,
953
983
body : {
@@ -1000,7 +1030,7 @@ class SafeApiKit {
1000
1030
url . searchParams . set ( 'offset' , offset . toString ( ) )
1001
1031
}
1002
1032
1003
- return sendRequest ( {
1033
+ return this . #api ( {
1004
1034
url : url . toString ( ) ,
1005
1035
method : HttpMethod . Get
1006
1036
} )
@@ -1024,7 +1054,7 @@ class SafeApiKit {
1024
1054
if ( ! signature ) {
1025
1055
throw new Error ( 'Invalid signature' )
1026
1056
}
1027
- return sendRequest ( {
1057
+ return this . #api ( {
1028
1058
url : `${ this . #txServiceBaseUrl} /v1/safe-operations/${ safeOperationHash } /confirmations/` ,
1029
1059
method : HttpMethod . Post ,
1030
1060
body : { signature }
0 commit comments