@solana-mobile/mobile-wallet-adapter-walletlib 1.3.0 → 1.4.0-beta2
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/README.md +90 -53
- package/android/src/main/java/com/solanamobile/mobilewalletadapterwalletlib/reactnative/SolanaMobileWalletAdapterWalletLibModule.kt +453 -171
- package/lib/esm/index.js +83 -52
- package/lib/esm/index.native.js +83 -52
- package/lib/types/index.d.ts +16 -5
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.native.d.ts +16 -5
- package/lib/types/index.native.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -4,31 +4,36 @@ import android.net.Uri
|
|
|
4
4
|
import android.util.Log
|
|
5
5
|
import com.facebook.react.bridge.*
|
|
6
6
|
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
7
|
-
import com.solana.mobilewalletadapter.common.
|
|
7
|
+
import com.solana.mobilewalletadapter.common.ProtocolContract
|
|
8
8
|
import com.solana.mobilewalletadapter.walletlib.association.AssociationUri
|
|
9
9
|
import com.solana.mobilewalletadapter.walletlib.association.LocalAssociationUri
|
|
10
10
|
import com.solana.mobilewalletadapter.walletlib.authorization.AuthIssuerConfig
|
|
11
|
-
import com.solana.mobilewalletadapter.walletlib.protocol.MobileWalletAdapterConfig
|
|
12
11
|
import com.solana.mobilewalletadapter.walletlib.scenario.*
|
|
13
12
|
import com.solana.mobilewalletadapter.walletlib.scenario.AuthorizedAccount
|
|
14
|
-
import com.solana.mobilewalletadapter.common.ProtocolContract
|
|
15
|
-
import com.solanamobile.mobilewalletadapterwalletlib.reactnative.BuildConfig
|
|
16
13
|
import com.solanamobile.mobilewalletadapterwalletlib.reactnative.model.*
|
|
14
|
+
import java.util.UUID
|
|
17
15
|
import kotlinx.coroutines.*
|
|
18
16
|
import kotlinx.serialization.json.Json
|
|
19
17
|
import kotlinx.serialization.json.JsonObject
|
|
20
18
|
import kotlinx.serialization.json.JsonPrimitive
|
|
21
19
|
import kotlinx.serialization.json.jsonObject
|
|
22
|
-
|
|
20
|
+
|
|
21
|
+
enum class ErrorCode(val code: String) {
|
|
22
|
+
ERROR_INTENT_DATA_NOT_FOUND("ERROR_INTENT_DATA_NOT_FOUND"),
|
|
23
|
+
ERROR_SESSION_ALREADY_CREATED("ERROR_SESSION_ALREADY_CREATED"),
|
|
24
|
+
ERROR_UNSUPPORTED_ASSOCIATION_URI("ERROR_UNSUPPORTED_ASSOCIATION_URI"),
|
|
25
|
+
ERROR_UNSUPPORTED_ASSOCIATION_TYPE("ERROR_UNSUPPORTED_ASSOCIATION_TYPE")
|
|
26
|
+
}
|
|
23
27
|
|
|
24
28
|
class SolanaMobileWalletAdapterWalletLibModule(val reactContext: ReactApplicationContext) :
|
|
25
29
|
ReactContextBaseJavaModule(reactContext), CoroutineScope {
|
|
26
30
|
|
|
27
31
|
private val json = Json { ignoreUnknownKeys = true }
|
|
28
32
|
|
|
29
|
-
// Sets the name of the module in React, accessible at
|
|
33
|
+
// Sets the name of the module in React, accessible at
|
|
34
|
+
// ReactNative.NativeModules.SolanaMobileWalletAdapterWalletLib
|
|
30
35
|
override fun getName() = "SolanaMobileWalletAdapterWalletLib"
|
|
31
|
-
|
|
36
|
+
|
|
32
37
|
override val coroutineContext =
|
|
33
38
|
Dispatchers.IO + CoroutineName("SolanaMobileWalletAdapterWalletLibModuleScope") + SupervisorJob()
|
|
34
39
|
|
|
@@ -65,16 +70,30 @@ class SolanaMobileWalletAdapterWalletLibModule(val reactContext: ReactApplicatio
|
|
|
65
70
|
}
|
|
66
71
|
}
|
|
67
72
|
|
|
68
|
-
// Service requests that come from the dApp for Authorization, Signing, Sending, hence
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
73
|
+
// Service requests that come from the dApp for Authorization, Signing, Sending, hence
|
|
74
|
+
// "RemoteRequest".
|
|
75
|
+
sealed class MobileWalletAdapterRemoteRequest(
|
|
76
|
+
open val request: ScenarioRequest,
|
|
77
|
+
val id: String = UUID.randomUUID().toString()
|
|
78
|
+
) {
|
|
79
|
+
data class AuthorizeDapp(override val request: AuthorizeRequest) :
|
|
80
|
+
MobileWalletAdapterRemoteRequest(request)
|
|
81
|
+
|
|
82
|
+
data class ReauthorizeDapp(override val request: ReauthorizeRequest) :
|
|
83
|
+
MobileWalletAdapterRemoteRequest(request)
|
|
84
|
+
|
|
85
|
+
data class DeauthorizeDapp(override val request: DeauthorizedEvent) :
|
|
86
|
+
MobileWalletAdapterRemoteRequest(request)
|
|
87
|
+
|
|
88
|
+
sealed class SignPayloads(override val request: SignPayloadsRequest) :
|
|
89
|
+
MobileWalletAdapterRemoteRequest(request)
|
|
90
|
+
|
|
91
|
+
data class SignTransactions(override val request: SignTransactionsRequest) :
|
|
92
|
+
SignPayloads(request)
|
|
93
|
+
|
|
94
|
+
data class SignMessages(override val request: SignMessagesRequest) :
|
|
95
|
+
SignPayloads(request)
|
|
74
96
|
|
|
75
|
-
sealed class SignPayloads(override val request: SignPayloadsRequest) : MobileWalletAdapterRemoteRequest(request)
|
|
76
|
-
data class SignTransactions(override val request: SignTransactionsRequest) : SignPayloads(request)
|
|
77
|
-
data class SignMessages(override val request: SignMessagesRequest) : SignPayloads(request)
|
|
78
97
|
data class SignAndSendTransactions(
|
|
79
98
|
override val request: SignAndSendTransactionsRequest,
|
|
80
99
|
val endpointUri: Uri,
|
|
@@ -86,67 +105,93 @@ class SolanaMobileWalletAdapterWalletLibModule(val reactContext: ReactApplicatio
|
|
|
86
105
|
private var scenarioUri: Uri? = null
|
|
87
106
|
private var scenario: Scenario? = null
|
|
88
107
|
set(value) {
|
|
89
|
-
value?.let { scenarioId = UUID.randomUUID().toString() }
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
108
|
+
value?.let { scenarioId = UUID.randomUUID().toString() }
|
|
109
|
+
?: run {
|
|
110
|
+
scenarioUri = null
|
|
111
|
+
scenarioId = null
|
|
112
|
+
scenario?.close()
|
|
113
|
+
}
|
|
93
114
|
pendingRequests.clear()
|
|
94
115
|
field = value
|
|
95
116
|
}
|
|
96
117
|
|
|
97
|
-
// very basic/naive implememtion of request cache.
|
|
98
|
-
// we could replace this with an abstraction that has expiration, persistance, etc.
|
|
118
|
+
// very basic/naive implememtion of request cache.
|
|
119
|
+
// we could replace this with an abstraction that has expiration, persistance, etc.
|
|
99
120
|
private val pendingRequests = mutableMapOf<String, MobileWalletAdapterRemoteRequest>()
|
|
100
121
|
|
|
101
122
|
private fun clusterToRpcUri(cluster: String?): Uri {
|
|
102
123
|
return when (cluster) {
|
|
103
124
|
ProtocolContract.CLUSTER_MAINNET_BETA ->
|
|
104
125
|
Uri.parse("https://api.mainnet-beta.solana.com")
|
|
126
|
+
|
|
105
127
|
ProtocolContract.CLUSTER_DEVNET ->
|
|
106
128
|
Uri.parse("https://api.devnet.solana.com")
|
|
107
|
-
|
|
108
|
-
|
|
129
|
+
|
|
130
|
+
else -> Uri.parse("https://api.testnet.solana.com")
|
|
109
131
|
}
|
|
110
132
|
}
|
|
111
|
-
|
|
112
133
|
@ReactMethod
|
|
113
134
|
fun createScenario(
|
|
114
135
|
walletName: String,
|
|
115
|
-
uriStr: String,
|
|
116
136
|
config: String,
|
|
137
|
+
promise: Promise,
|
|
117
138
|
) = launch {
|
|
118
|
-
|
|
139
|
+
// Get the intent that started this activity
|
|
140
|
+
val intent = reactContext.getCurrentActivity()?.intent
|
|
141
|
+
if (intent == null) {
|
|
142
|
+
Log.e(TAG, "Unable to get intent in current context")
|
|
143
|
+
promise.reject(ErrorCode.ERROR_INTENT_DATA_NOT_FOUND.code, "Unable to get intent in current context")
|
|
144
|
+
return@launch
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Get the data from the intent and parse into URI
|
|
148
|
+
val data = intent.data
|
|
149
|
+
if (data == null) {
|
|
150
|
+
Log.e(TAG, "Unable to get intent data in current context")
|
|
151
|
+
promise.reject(ErrorCode.ERROR_INTENT_DATA_NOT_FOUND.code, "Unable to get intent data in current context")
|
|
152
|
+
return@launch
|
|
153
|
+
}
|
|
154
|
+
val uri = Uri.parse(data.toString())
|
|
119
155
|
|
|
120
156
|
// TODO: this is dirty, need some stateful object/data to know what state we are in.
|
|
121
|
-
// also, should we
|
|
157
|
+
// also, should we support multiple simultaneous scenarios?
|
|
122
158
|
if (uri == scenarioUri && scenario != null) {
|
|
123
159
|
Log.w(TAG, "Session already created for uri: $uri")
|
|
160
|
+
promise.reject(ErrorCode.ERROR_SESSION_ALREADY_CREATED.code, "Session already created for uri: $uri")
|
|
124
161
|
return@launch
|
|
125
162
|
}
|
|
126
163
|
|
|
127
164
|
val associationUri = AssociationUri.parse(uri)
|
|
128
165
|
if (associationUri == null) {
|
|
129
166
|
Log.e(TAG, "Unsupported association URI: $uri")
|
|
167
|
+
promise.reject(ErrorCode.ERROR_UNSUPPORTED_ASSOCIATION_URI.code, "Unsupported association URI: $uri")
|
|
130
168
|
return@launch
|
|
131
169
|
} else if (associationUri !is LocalAssociationUri) {
|
|
132
170
|
Log.e(TAG, "Current implementation of fakewallet does not support remote clients")
|
|
171
|
+
promise.reject(ErrorCode.ERROR_UNSUPPORTED_ASSOCIATION_TYPE.code, "Current implementation of fakewallet does not support remote clients")
|
|
133
172
|
return@launch
|
|
134
173
|
}
|
|
135
174
|
|
|
136
175
|
scenarioUri = uri
|
|
137
176
|
|
|
138
|
-
val kotlinConfig =
|
|
177
|
+
val kotlinConfig =
|
|
178
|
+
json.decodeFromString(MobileWalletAdapterConfigSerializer, config)
|
|
139
179
|
|
|
140
180
|
// created a scenario, told it to start (kicks off some threads in the background)
|
|
141
181
|
// we've kept a reference to it in the global state of this module (scenario)
|
|
142
|
-
// this won't be garbage collected and will just run, sit & wait for an incoming
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
182
|
+
// this won't be garbage collected and will just run, sit & wait for an incoming
|
|
183
|
+
// connection
|
|
184
|
+
scenario =
|
|
185
|
+
associationUri.createScenario(
|
|
186
|
+
reactContext,
|
|
187
|
+
kotlinConfig,
|
|
188
|
+
AuthIssuerConfig(walletName),
|
|
189
|
+
MobileWalletAdapterScenarioCallbacks()
|
|
190
|
+
).also {
|
|
191
|
+
it.start()
|
|
192
|
+
}
|
|
149
193
|
|
|
194
|
+
promise.resolve(scenarioId)
|
|
150
195
|
Log.d(TAG, "scenario created: $walletName")
|
|
151
196
|
}
|
|
152
197
|
|
|
@@ -161,170 +206,395 @@ class SolanaMobileWalletAdapterWalletLibModule(val reactContext: ReactApplicatio
|
|
|
161
206
|
|
|
162
207
|
@ReactMethod
|
|
163
208
|
fun resolve(requestJson: String, responseJson: String) = launch {
|
|
164
|
-
val completedRequest =
|
|
165
|
-
|
|
209
|
+
val completedRequest =
|
|
210
|
+
json.decodeFromString(
|
|
211
|
+
MobileWalletAdapterRequestSerializer,
|
|
212
|
+
requestJson
|
|
213
|
+
)
|
|
214
|
+
val response =
|
|
215
|
+
json.decodeFromString(
|
|
216
|
+
MobileWalletAdapterResponseSerializer,
|
|
217
|
+
responseJson
|
|
218
|
+
)
|
|
166
219
|
val pendingRequest = pendingRequests[completedRequest.requestId]
|
|
167
220
|
|
|
168
221
|
if (completedRequest.sessionId != scenarioId) {
|
|
169
|
-
sendSessionEventToReact(
|
|
170
|
-
|
|
171
|
-
|
|
222
|
+
sendSessionEventToReact(
|
|
223
|
+
MobileWalletAdapterSessionEvent.ScenarioError(
|
|
224
|
+
"Invalid session (${completedRequest.sessionId}). This session does not exist/is no longer active."
|
|
225
|
+
)
|
|
226
|
+
)
|
|
172
227
|
return@launch
|
|
173
228
|
}
|
|
174
229
|
|
|
175
230
|
fun completeWithInvalidResponse() {
|
|
176
|
-
pendingRequest?.request?.completeWithInternalError(
|
|
231
|
+
pendingRequest?.request?.completeWithInternalError(
|
|
232
|
+
Exception("Invalid Response For Request: response = $responseJson")
|
|
233
|
+
)
|
|
177
234
|
}
|
|
178
235
|
|
|
179
236
|
when (completedRequest) {
|
|
180
|
-
is AuthorizeDapp ->
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
237
|
+
is AuthorizeDapp ->
|
|
238
|
+
when (response) {
|
|
239
|
+
is MobileWalletAdapterFailureResponse -> {
|
|
240
|
+
when (response) {
|
|
241
|
+
is UserDeclinedResponse ->
|
|
242
|
+
(pendingRequest as?
|
|
243
|
+
MobileWalletAdapterRemoteRequest.AuthorizeDapp)
|
|
244
|
+
?.request
|
|
245
|
+
?.completeWithDecline()
|
|
246
|
+
|
|
247
|
+
else ->
|
|
248
|
+
completeWithInvalidResponse()
|
|
249
|
+
}
|
|
186
250
|
}
|
|
251
|
+
|
|
252
|
+
is AuthorizeDappResponse ->
|
|
253
|
+
(pendingRequest as?
|
|
254
|
+
MobileWalletAdapterRemoteRequest.AuthorizeDapp)
|
|
255
|
+
?.request
|
|
256
|
+
?.completeWithAuthorize(
|
|
257
|
+
response.accounts
|
|
258
|
+
.first()
|
|
259
|
+
.let { account
|
|
260
|
+
->
|
|
261
|
+
AuthorizedAccount(
|
|
262
|
+
account.publicKey,
|
|
263
|
+
account.accountLabel,
|
|
264
|
+
account.icon
|
|
265
|
+
?.let {
|
|
266
|
+
Uri.parse(
|
|
267
|
+
it
|
|
268
|
+
)
|
|
269
|
+
},
|
|
270
|
+
account.chains
|
|
271
|
+
?.toTypedArray(),
|
|
272
|
+
account.features
|
|
273
|
+
?.toTypedArray()
|
|
274
|
+
)
|
|
275
|
+
},
|
|
276
|
+
response.walletUriBase
|
|
277
|
+
?.let {
|
|
278
|
+
Uri.parse(
|
|
279
|
+
response.walletUriBase
|
|
280
|
+
)
|
|
281
|
+
},
|
|
282
|
+
response.authorizationScope,
|
|
283
|
+
response.signInResult
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
else -> completeWithInvalidResponse()
|
|
187
287
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
is MobileWalletAdapterFailureResponse -> {
|
|
203
|
-
when (response) {
|
|
204
|
-
is AuthorizationNotValidResponse ->
|
|
205
|
-
(pendingRequest as? MobileWalletAdapterRemoteRequest.ReauthorizeDapp)?.request?.completeWithDecline()
|
|
206
|
-
else -> completeWithInvalidResponse()
|
|
288
|
+
|
|
289
|
+
is ReauthorizeDapp ->
|
|
290
|
+
when (response) {
|
|
291
|
+
is MobileWalletAdapterFailureResponse -> {
|
|
292
|
+
when (response) {
|
|
293
|
+
is AuthorizationNotValidResponse ->
|
|
294
|
+
(pendingRequest as?
|
|
295
|
+
MobileWalletAdapterRemoteRequest.ReauthorizeDapp)
|
|
296
|
+
?.request
|
|
297
|
+
?.completeWithDecline()
|
|
298
|
+
|
|
299
|
+
else ->
|
|
300
|
+
completeWithInvalidResponse()
|
|
301
|
+
}
|
|
207
302
|
}
|
|
303
|
+
|
|
304
|
+
is ReauthorizeDappResponse ->
|
|
305
|
+
(pendingRequest as?
|
|
306
|
+
MobileWalletAdapterRemoteRequest.ReauthorizeDapp)
|
|
307
|
+
?.request
|
|
308
|
+
?.completeWithReauthorize()
|
|
309
|
+
|
|
310
|
+
else -> completeWithInvalidResponse()
|
|
208
311
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
312
|
+
|
|
313
|
+
is DeauthorizeDapp ->
|
|
314
|
+
when (response) {
|
|
315
|
+
is DeauthorizeDappResponse ->
|
|
316
|
+
(pendingRequest as?
|
|
317
|
+
MobileWalletAdapterRemoteRequest.DeauthorizeDapp)
|
|
318
|
+
?.request
|
|
319
|
+
?.complete()
|
|
320
|
+
|
|
321
|
+
else -> completeWithInvalidResponse()
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
is SignAndSendTransactions ->
|
|
325
|
+
when (response) {
|
|
326
|
+
is MobileWalletAdapterFailureResponse -> {
|
|
327
|
+
when (response) {
|
|
328
|
+
is UserDeclinedResponse ->
|
|
329
|
+
(pendingRequest as?
|
|
330
|
+
MobileWalletAdapterRemoteRequest.SignAndSendTransactions)
|
|
331
|
+
?.request
|
|
332
|
+
?.completeWithDecline()
|
|
333
|
+
|
|
334
|
+
is TooManyPayloadsResponse ->
|
|
335
|
+
(pendingRequest as?
|
|
336
|
+
MobileWalletAdapterRemoteRequest.SignAndSendTransactions)
|
|
337
|
+
?.request
|
|
338
|
+
?.completeWithTooManyPayloads()
|
|
339
|
+
|
|
340
|
+
is AuthorizationNotValidResponse ->
|
|
341
|
+
(pendingRequest as?
|
|
342
|
+
MobileWalletAdapterRemoteRequest.SignAndSendTransactions)
|
|
343
|
+
?.request
|
|
344
|
+
?.completeWithAuthorizationNotValid()
|
|
345
|
+
|
|
346
|
+
is InvalidSignaturesResponse ->
|
|
347
|
+
(pendingRequest as?
|
|
348
|
+
MobileWalletAdapterRemoteRequest.SignAndSendTransactions)
|
|
349
|
+
?.request
|
|
350
|
+
?.completeWithInvalidSignatures(
|
|
351
|
+
response.valid
|
|
352
|
+
)
|
|
353
|
+
}
|
|
229
354
|
}
|
|
355
|
+
|
|
356
|
+
is SignedAndSentTransactions ->
|
|
357
|
+
(pendingRequest as?
|
|
358
|
+
MobileWalletAdapterRemoteRequest.SignAndSendTransactions)
|
|
359
|
+
?.request
|
|
360
|
+
?.completeWithSignatures(
|
|
361
|
+
response.signedTransactions
|
|
362
|
+
.toTypedArray()
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
else -> completeWithInvalidResponse()
|
|
230
366
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
367
|
+
|
|
368
|
+
is SignPayloads ->
|
|
369
|
+
when (response) {
|
|
370
|
+
is MobileWalletAdapterFailureResponse -> {
|
|
371
|
+
when (response) {
|
|
372
|
+
is UserDeclinedResponse ->
|
|
373
|
+
(pendingRequest as?
|
|
374
|
+
MobileWalletAdapterRemoteRequest.SignPayloads)
|
|
375
|
+
?.request
|
|
376
|
+
?.completeWithDecline()
|
|
377
|
+
|
|
378
|
+
is TooManyPayloadsResponse ->
|
|
379
|
+
(pendingRequest as?
|
|
380
|
+
MobileWalletAdapterRemoteRequest.SignPayloads)
|
|
381
|
+
?.request
|
|
382
|
+
?.completeWithTooManyPayloads()
|
|
383
|
+
|
|
384
|
+
is AuthorizationNotValidResponse ->
|
|
385
|
+
(pendingRequest as?
|
|
386
|
+
MobileWalletAdapterRemoteRequest.SignPayloads)
|
|
387
|
+
?.request
|
|
388
|
+
?.completeWithAuthorizationNotValid()
|
|
389
|
+
|
|
390
|
+
is InvalidSignaturesResponse ->
|
|
391
|
+
(pendingRequest as?
|
|
392
|
+
MobileWalletAdapterRemoteRequest.SignPayloads)
|
|
393
|
+
?.request
|
|
394
|
+
?.completeWithInvalidPayloads(
|
|
395
|
+
response.valid
|
|
396
|
+
)
|
|
397
|
+
}
|
|
246
398
|
}
|
|
399
|
+
|
|
400
|
+
is SignedPayloads ->
|
|
401
|
+
(pendingRequest as?
|
|
402
|
+
MobileWalletAdapterRemoteRequest.SignPayloads)
|
|
403
|
+
?.request
|
|
404
|
+
?.completeWithSignedPayloads(
|
|
405
|
+
response.signedPayloads
|
|
406
|
+
.toTypedArray()
|
|
407
|
+
)
|
|
408
|
+
|
|
409
|
+
else -> completeWithInvalidResponse()
|
|
247
410
|
}
|
|
248
|
-
is SignedPayloads ->
|
|
249
|
-
(pendingRequest as? MobileWalletAdapterRemoteRequest.SignPayloads)?.request?.completeWithSignedPayloads(response.signedPayloads.toTypedArray())
|
|
250
|
-
else -> completeWithInvalidResponse()
|
|
251
|
-
}
|
|
252
411
|
}
|
|
253
412
|
}
|
|
254
413
|
|
|
255
|
-
private fun checkSessionId(sessionId: String, doIfValid: (() -> Unit)) =
|
|
256
|
-
if (sessionId == scenarioId) doIfValid()
|
|
257
|
-
else
|
|
258
|
-
|
|
259
|
-
|
|
414
|
+
private fun checkSessionId(sessionId: String, doIfValid: (() -> Unit)) =
|
|
415
|
+
if (sessionId == scenarioId) doIfValid()
|
|
416
|
+
else
|
|
417
|
+
sendSessionEventToReact(
|
|
418
|
+
MobileWalletAdapterSessionEvent
|
|
419
|
+
.ScenarioError(
|
|
420
|
+
"Invalid session ($sessionId). This session does not exist/is no longer active."
|
|
421
|
+
)
|
|
422
|
+
)
|
|
260
423
|
|
|
261
424
|
private fun sendSessionEventToReact(sessionEvent: MobileWalletAdapterSessionEvent) {
|
|
262
|
-
val eventInfo =
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
425
|
+
val eventInfo =
|
|
426
|
+
when (sessionEvent) {
|
|
427
|
+
is MobileWalletAdapterSessionEvent.None -> null
|
|
428
|
+
is MobileWalletAdapterSessionEvent.ScenarioError ->
|
|
429
|
+
Arguments.createMap().apply {
|
|
430
|
+
putString(
|
|
431
|
+
"__type",
|
|
432
|
+
sessionEvent.type
|
|
433
|
+
)
|
|
434
|
+
putString(
|
|
435
|
+
"error",
|
|
436
|
+
sessionEvent.message
|
|
437
|
+
)
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
else ->
|
|
441
|
+
Arguments.createMap().apply {
|
|
442
|
+
putString(
|
|
443
|
+
"__type",
|
|
444
|
+
sessionEvent.type
|
|
445
|
+
)
|
|
446
|
+
}
|
|
270
447
|
}
|
|
271
|
-
}
|
|
272
448
|
|
|
273
449
|
eventInfo?.putString("sessionId", scenarioId)
|
|
274
450
|
|
|
275
|
-
eventInfo?.let {
|
|
276
|
-
|
|
451
|
+
eventInfo?.let {
|
|
452
|
+
sendEvent(
|
|
453
|
+
reactContext,
|
|
454
|
+
Companion.MOBILE_WALLET_ADAPTER_SERVICE_REQUEST_BRIDGE_NAME,
|
|
455
|
+
it
|
|
456
|
+
)
|
|
457
|
+
}
|
|
277
458
|
}
|
|
278
459
|
|
|
279
460
|
private fun sendWalletServiceRequestToReact(request: MobileWalletAdapterRemoteRequest) {
|
|
280
|
-
val surrogate =
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
461
|
+
val surrogate =
|
|
462
|
+
when (request) {
|
|
463
|
+
is MobileWalletAdapterRemoteRequest.AuthorizeDapp ->
|
|
464
|
+
AuthorizeDapp(
|
|
465
|
+
scenarioId!!,
|
|
466
|
+
request.request.chain,
|
|
467
|
+
request.request
|
|
468
|
+
.identityName,
|
|
469
|
+
request.request.identityUri
|
|
470
|
+
.toString(),
|
|
471
|
+
request.request
|
|
472
|
+
.iconRelativeUri
|
|
473
|
+
.toString(),
|
|
474
|
+
request.request.features
|
|
475
|
+
?.asList(),
|
|
476
|
+
request.request.addresses
|
|
477
|
+
?.asList(),
|
|
478
|
+
request.request
|
|
479
|
+
.signInPayload
|
|
480
|
+
)
|
|
481
|
+
|
|
482
|
+
is MobileWalletAdapterRemoteRequest.ReauthorizeDapp ->
|
|
483
|
+
ReauthorizeDapp(
|
|
484
|
+
scenarioId!!,
|
|
485
|
+
request.request.chain,
|
|
486
|
+
request.request
|
|
487
|
+
.identityName,
|
|
488
|
+
request.request.identityUri
|
|
489
|
+
.toString(),
|
|
490
|
+
request.request
|
|
491
|
+
.iconRelativeUri
|
|
492
|
+
.toString(),
|
|
493
|
+
request.request
|
|
494
|
+
.authorizationScope
|
|
495
|
+
)
|
|
496
|
+
|
|
497
|
+
is MobileWalletAdapterRemoteRequest.DeauthorizeDapp ->
|
|
498
|
+
DeauthorizeDapp(
|
|
499
|
+
scenarioId!!,
|
|
500
|
+
request.request.chain,
|
|
501
|
+
request.request
|
|
502
|
+
.identityName,
|
|
503
|
+
request.request.identityUri
|
|
504
|
+
.toString(),
|
|
505
|
+
request.request
|
|
506
|
+
.iconRelativeUri
|
|
507
|
+
.toString(),
|
|
508
|
+
request.request
|
|
509
|
+
.authorizationScope
|
|
510
|
+
)
|
|
511
|
+
|
|
512
|
+
is MobileWalletAdapterRemoteRequest.SignMessages ->
|
|
513
|
+
SignMessages(
|
|
514
|
+
scenarioId!!,
|
|
515
|
+
request.request.chain,
|
|
516
|
+
request.request
|
|
517
|
+
.identityName,
|
|
518
|
+
request.request.identityUri
|
|
519
|
+
.toString(),
|
|
520
|
+
request.request
|
|
521
|
+
.iconRelativeUri
|
|
522
|
+
.toString(),
|
|
523
|
+
request.request
|
|
524
|
+
.authorizationScope,
|
|
525
|
+
request.request.payloads
|
|
526
|
+
.toList()
|
|
527
|
+
)
|
|
528
|
+
|
|
529
|
+
is MobileWalletAdapterRemoteRequest.SignTransactions ->
|
|
530
|
+
SignTransactions(
|
|
531
|
+
scenarioId!!,
|
|
532
|
+
request.request.chain,
|
|
533
|
+
request.request
|
|
534
|
+
.identityName,
|
|
535
|
+
request.request.identityUri
|
|
536
|
+
.toString(),
|
|
537
|
+
request.request
|
|
538
|
+
.iconRelativeUri
|
|
539
|
+
.toString(),
|
|
540
|
+
request.request
|
|
541
|
+
.authorizationScope,
|
|
542
|
+
request.request.payloads
|
|
543
|
+
.toList()
|
|
544
|
+
)
|
|
545
|
+
|
|
546
|
+
is MobileWalletAdapterRemoteRequest.SignAndSendTransactions ->
|
|
547
|
+
SignAndSendTransactions(
|
|
548
|
+
scenarioId!!,
|
|
549
|
+
request.request.chain,
|
|
550
|
+
request.request
|
|
551
|
+
.identityName,
|
|
552
|
+
request.request.identityUri
|
|
553
|
+
.toString(),
|
|
554
|
+
request.request
|
|
555
|
+
.iconRelativeUri
|
|
556
|
+
.toString(),
|
|
557
|
+
request.request
|
|
558
|
+
.authorizationScope,
|
|
559
|
+
request.request.payloads
|
|
560
|
+
.toList()
|
|
561
|
+
)
|
|
562
|
+
}
|
|
313
563
|
|
|
314
564
|
// this is dirty, the requestId needs to line up so have to manually overwrite here
|
|
315
565
|
// should we change javascript side to accept json?
|
|
316
|
-
val eventInfo =
|
|
317
|
-
JsonObject(
|
|
318
|
-
.
|
|
319
|
-
|
|
320
|
-
|
|
566
|
+
val eventInfo =
|
|
567
|
+
JsonObject(
|
|
568
|
+
json.encodeToJsonElement(
|
|
569
|
+
MobileWalletAdapterRequestSerializer,
|
|
570
|
+
surrogate
|
|
571
|
+
)
|
|
572
|
+
.jsonObject
|
|
573
|
+
.toMutableMap()
|
|
574
|
+
.apply {
|
|
575
|
+
put(
|
|
576
|
+
"requestId",
|
|
577
|
+
JsonPrimitive(
|
|
578
|
+
request.id
|
|
579
|
+
)
|
|
580
|
+
)
|
|
581
|
+
}
|
|
582
|
+
)
|
|
583
|
+
.toReadableMap()
|
|
321
584
|
|
|
322
|
-
sendEvent(
|
|
585
|
+
sendEvent(
|
|
586
|
+
reactContext,
|
|
587
|
+
Companion.MOBILE_WALLET_ADAPTER_SERVICE_REQUEST_BRIDGE_NAME,
|
|
588
|
+
eventInfo
|
|
589
|
+
)
|
|
323
590
|
}
|
|
324
591
|
|
|
325
|
-
private fun sendEvent(
|
|
326
|
-
reactContext
|
|
327
|
-
|
|
592
|
+
private fun sendEvent(
|
|
593
|
+
reactContext: ReactContext,
|
|
594
|
+
eventName: String,
|
|
595
|
+
params: ReadableMap? = null
|
|
596
|
+
) {
|
|
597
|
+
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
328
598
|
.emit(eventName, params)
|
|
329
599
|
}
|
|
330
600
|
|
|
@@ -335,7 +605,9 @@ class SolanaMobileWalletAdapterWalletLibModule(val reactContext: ReactApplicatio
|
|
|
335
605
|
}
|
|
336
606
|
|
|
337
607
|
override fun onScenarioServingClients() {
|
|
338
|
-
sendSessionEventToReact(
|
|
608
|
+
sendSessionEventToReact(
|
|
609
|
+
MobileWalletAdapterSessionEvent.ScenarioServingClients
|
|
610
|
+
)
|
|
339
611
|
}
|
|
340
612
|
|
|
341
613
|
override fun onScenarioServingComplete() {
|
|
@@ -359,7 +631,9 @@ class SolanaMobileWalletAdapterWalletLibModule(val reactContext: ReactApplicatio
|
|
|
359
631
|
}
|
|
360
632
|
|
|
361
633
|
override fun onLowPowerAndNoConnection() {
|
|
362
|
-
sendSessionEventToReact(
|
|
634
|
+
sendSessionEventToReact(
|
|
635
|
+
MobileWalletAdapterSessionEvent.LowPowerNoConnection
|
|
636
|
+
)
|
|
363
637
|
}
|
|
364
638
|
|
|
365
639
|
/* Remote Requests */
|
|
@@ -387,9 +661,15 @@ class SolanaMobileWalletAdapterWalletLibModule(val reactContext: ReactApplicatio
|
|
|
387
661
|
sendWalletServiceRequestToReact(request)
|
|
388
662
|
}
|
|
389
663
|
|
|
390
|
-
override fun onSignAndSendTransactionsRequest(
|
|
664
|
+
override fun onSignAndSendTransactionsRequest(
|
|
665
|
+
request: SignAndSendTransactionsRequest
|
|
666
|
+
) {
|
|
391
667
|
val endpointUri = clusterToRpcUri(request.cluster)
|
|
392
|
-
val request =
|
|
668
|
+
val request =
|
|
669
|
+
MobileWalletAdapterRemoteRequest.SignAndSendTransactions(
|
|
670
|
+
request,
|
|
671
|
+
endpointUri
|
|
672
|
+
)
|
|
393
673
|
pendingRequests.put(request.id, request)
|
|
394
674
|
sendWalletServiceRequestToReact(request)
|
|
395
675
|
}
|
|
@@ -403,7 +683,9 @@ class SolanaMobileWalletAdapterWalletLibModule(val reactContext: ReactApplicatio
|
|
|
403
683
|
|
|
404
684
|
companion object {
|
|
405
685
|
private val TAG = SolanaMobileWalletAdapterWalletLibModule::class.simpleName
|
|
406
|
-
const val MOBILE_WALLET_ADAPTER_SERVICE_REQUEST_BRIDGE_NAME =
|
|
407
|
-
|
|
686
|
+
const val MOBILE_WALLET_ADAPTER_SERVICE_REQUEST_BRIDGE_NAME =
|
|
687
|
+
"MobileWalletAdapterServiceRequestBridge"
|
|
688
|
+
const val MOBILE_WALLET_ADAPTER_SESSION_EVENT_BRIDGE_NAME =
|
|
689
|
+
"MobileWalletAdapterSessionEventBridge"
|
|
408
690
|
}
|
|
409
|
-
}
|
|
691
|
+
}
|