@@ -32,54 +32,6 @@ export const CipMethodsMapping: Record<number, WalletMethod[]> = {
32
32
} ;
33
33
export const WalletApiMethodNames : WalletMethod [ ] = Object . values ( CipMethodsMapping ) . flat ( ) ;
34
34
35
- /**
36
- * Wrap the proxy API object with a regular javascript object to avoid interop issues with some dApps.
37
- *
38
- * Only return the allowed API methods.
39
- */
40
- const wrapAndEnableApi = (
41
- walletApi : WalletApi ,
42
- enabledExtensions ?: WalletApiExtension [ ]
43
- ) : Cip30WalletApiWithPossibleExtensions => {
44
- const baseApi : Cip30WalletApiWithPossibleExtensions = {
45
- // Add experimental.getCollateral to CIP-30 API
46
- experimental : {
47
- getCollateral : ( params ?: { amount ?: Cbor } ) => walletApi . getCollateral ( params )
48
- } ,
49
- getBalance : ( ) => walletApi . getBalance ( ) ,
50
- getChangeAddress : ( ) => walletApi . getChangeAddress ( ) ,
51
- getCollateral : ( params ?: { amount ?: Cbor } ) => walletApi . getCollateral ( params ) ,
52
- getExtensions : ( ) => Promise . resolve ( enabledExtensions || [ ] ) ,
53
- getNetworkId : ( ) => walletApi . getNetworkId ( ) ,
54
- getRewardAddresses : ( ) => walletApi . getRewardAddresses ( ) ,
55
- getUnusedAddresses : ( ) => walletApi . getUnusedAddresses ( ) ,
56
- getUsedAddresses : ( paginate ?: Paginate ) => walletApi . getUsedAddresses ( paginate ) ,
57
- getUtxos : ( amount ?: Cbor , paginate ?: Paginate ) => walletApi . getUtxos ( amount , paginate ) ,
58
- signData : ( addr : Cardano . PaymentAddress | Bytes , payload : Bytes ) => walletApi . signData ( addr , payload ) ,
59
- signTx : ( tx : Cbor , partialSign ?: Boolean ) => walletApi . signTx ( tx , partialSign ) ,
60
- submitTx : ( tx : Cbor ) => walletApi . submitTx ( tx )
61
- } ;
62
-
63
- const additionalCipApis : CipExtensionApis = {
64
- cip95 : {
65
- getPubDRepKey : ( ) => walletApi . getPubDRepKey ( ) ,
66
- getRegisteredPubStakeKeys : ( ) => walletApi . getRegisteredPubStakeKeys ( ) ,
67
- getUnregisteredPubStakeKeys : ( ) => walletApi . getUnregisteredPubStakeKeys ( )
68
- }
69
- } ;
70
-
71
- if ( enabledExtensions ) {
72
- for ( const extension of enabledExtensions ) {
73
- const cipName = `cip${ extension . cip } ` as keyof CipExtensionApis ;
74
- if ( additionalCipApis [ cipName ] ) {
75
- baseApi [ cipName ] = additionalCipApis [ cipName ] ;
76
- }
77
- }
78
- }
79
-
80
- return baseApi ;
81
- } ;
82
-
83
35
/** CIP30 API version */
84
36
export type ApiVersion = string ;
85
37
@@ -93,7 +45,19 @@ export type WalletName = string;
93
45
*/
94
46
export type WalletIcon = string ;
95
47
96
- export type WalletProperties = { icon : WalletIcon ; walletName : WalletName } ;
48
+ export type WalletProperties = {
49
+ icon : WalletIcon ;
50
+ walletName : WalletName ;
51
+ supportedExtensions ?: WalletApiExtension [ ] ;
52
+ /** Deviations from the CIP30 spec */
53
+ cip30ApiDeviations ?: {
54
+ /**
55
+ * Instead of throwing an error when no collateral is found, return empty array.
56
+ * This is the way the Nami wallet works and some DApps rely on it (i.e. https://app.indigoprotocol.io/)
57
+ */
58
+ getCollateralEmptyArray ?: boolean ;
59
+ } ;
60
+ } ;
97
61
98
62
export type WalletDependencies = {
99
63
logger : Logger ;
@@ -108,20 +72,26 @@ export class Cip30Wallet {
108
72
readonly apiVersion : ApiVersion = '0.1.0' ;
109
73
readonly name : WalletName ;
110
74
readonly icon : WalletIcon ;
75
+ /** Support the full api by default */
111
76
readonly supportedExtensions : WalletApiExtension [ ] = [ { cip : 95 } ] ;
112
77
113
78
readonly #logger: Logger ;
114
79
readonly #api: WalletApi ;
115
80
readonly #authenticator: RemoteAuthenticator ;
81
+ readonly #deviations: WalletProperties [ 'cip30ApiDeviations' ] ;
116
82
117
83
constructor ( properties : WalletProperties , { api, authenticator, logger } : WalletDependencies ) {
118
84
this . icon = properties . icon ;
119
85
this . name = properties . walletName ;
120
86
this . #api = api ;
121
87
this . #logger = logger ;
122
88
this . #authenticator = authenticator ;
89
+ this . #deviations = properties . cip30ApiDeviations ;
123
90
this . enable = this . enable . bind ( this ) ;
124
91
this . isEnabled = this . isEnabled . bind ( this ) ;
92
+ if ( properties . supportedExtensions ) {
93
+ this . supportedExtensions = properties . supportedExtensions ;
94
+ }
125
95
}
126
96
127
97
#validateExtensions( extensions : WalletApiExtension [ ] = [ ] ) : void {
@@ -173,9 +143,60 @@ export class Cip30Wallet {
173
143
const extensions = options ?. extensions ?. filter ( ( { cip : requestedCip } ) =>
174
144
this . supportedExtensions . some ( ( { cip : supportedCip } ) => supportedCip === requestedCip )
175
145
) ;
176
- return wrapAndEnableApi ( this . #api , extensions ) ;
146
+ return this . #wrapAndEnableApi ( extensions ) ;
177
147
}
178
148
this . #logger. debug ( `${ location . origin } not authorized to access wallet api` ) ;
179
149
throw new ApiError ( APIErrorCode . Refused , 'wallet not authorized.' ) ;
180
150
}
151
+
152
+ async #wrapGetCollateral( params ?: { amount ?: Cbor } ) {
153
+ const collateral = await this . #api. getCollateral ( params ) ;
154
+ return this . #deviations?. getCollateralEmptyArray ? collateral ?? [ ] : collateral ;
155
+ }
156
+
157
+ /**
158
+ * Wrap the proxy API object with a regular javascript object to avoid interop issues with some dApps.
159
+ *
160
+ * Only return the allowed API methods.
161
+ */
162
+ #wrapAndEnableApi( enabledExtensions ?: WalletApiExtension [ ] ) : Cip30WalletApiWithPossibleExtensions {
163
+ const walletApi = this . #api;
164
+ const baseApi : Cip30WalletApiWithPossibleExtensions = {
165
+ // Add experimental.getCollateral to CIP-30 API
166
+ experimental : {
167
+ getCollateral : async ( params ?: { amount ?: Cbor } ) => this . #wrapGetCollateral( params )
168
+ } ,
169
+ getBalance : ( ) => walletApi . getBalance ( ) ,
170
+ getChangeAddress : ( ) => walletApi . getChangeAddress ( ) ,
171
+ getCollateral : ( params ?: { amount ?: Cbor } ) => this . #wrapGetCollateral( params ) ,
172
+ getExtensions : ( ) => Promise . resolve ( enabledExtensions || [ ] ) ,
173
+ getNetworkId : ( ) => walletApi . getNetworkId ( ) ,
174
+ getRewardAddresses : ( ) => walletApi . getRewardAddresses ( ) ,
175
+ getUnusedAddresses : ( ) => walletApi . getUnusedAddresses ( ) ,
176
+ getUsedAddresses : ( paginate ?: Paginate ) => walletApi . getUsedAddresses ( paginate ) ,
177
+ getUtxos : ( amount ?: Cbor , paginate ?: Paginate ) => walletApi . getUtxos ( amount , paginate ) ,
178
+ signData : ( addr : Cardano . PaymentAddress | Bytes , payload : Bytes ) => walletApi . signData ( addr , payload ) ,
179
+ signTx : ( tx : Cbor , partialSign ?: Boolean ) => walletApi . signTx ( tx , partialSign ) ,
180
+ submitTx : ( tx : Cbor ) => walletApi . submitTx ( tx )
181
+ } ;
182
+
183
+ const additionalCipApis : CipExtensionApis = {
184
+ cip95 : {
185
+ getPubDRepKey : ( ) => walletApi . getPubDRepKey ( ) ,
186
+ getRegisteredPubStakeKeys : ( ) => walletApi . getRegisteredPubStakeKeys ( ) ,
187
+ getUnregisteredPubStakeKeys : ( ) => walletApi . getUnregisteredPubStakeKeys ( )
188
+ }
189
+ } ;
190
+
191
+ if ( enabledExtensions ) {
192
+ for ( const extension of enabledExtensions ) {
193
+ const cipName = `cip${ extension . cip } ` as keyof CipExtensionApis ;
194
+ if ( additionalCipApis [ cipName ] ) {
195
+ baseApi [ cipName ] = additionalCipApis [ cipName ] ;
196
+ }
197
+ }
198
+ }
199
+
200
+ return baseApi ;
201
+ }
181
202
}
0 commit comments