@solana-mobile/mobile-wallet-adapter-protocol 0.0.1-alpha.0 → 0.0.1-alpha.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/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # `@solana-mobile/mobile-wallet-adapter-protocol`
2
+
3
+ This is a reference implementation of the [Mobile Wallet Adapter specification](https://github.com/solana-mobile/mobile-wallet-adapter/blob/main/spec/spec.md) in JavaScript. Use this to start a session with a mobile wallet in which you can issue API calls to it (eg. `sign_message`) as per the spec.
4
+
5
+ If you are simply looking to integrate a JavaScript application with mobile wallets, see [`@solana-mobile/wallet-adapter-mobile`](https://www.npmjs.com/package/@solana-mobile/wallet-adapter-mobile) instead.
6
+
7
+ ## Quick start
8
+
9
+ Use this API to start a session:
10
+
11
+ ```typescript
12
+ import {withLocalWallet} from '@solana-mobile/mobile-wallet-adapter-protocol';
13
+
14
+ await withLocalWallet(async (wallet) => {
15
+ /* ... */
16
+ });
17
+ ```
18
+
19
+ The callback you provide will be called once a session has been established with a wallet. It will recieve the `MobileWallet` API as an argument. You can call protocol-specified methods using this function. Whatever you return from this callback will be returned by `withLocalWallet`.
20
+
21
+ ```typescript
22
+ const signedPayloads = await withLocalWallet(async (wallet) => {
23
+ const {signed_payloads} = await wallet('sign_message', {
24
+ auth_token,
25
+ payloads: [/* ... */],
26
+ });
27
+ return signed_payloads;
28
+ });
29
+ ```
30
+
31
+ The wallet session will stay active until your callback returns. Typically, wallets will redirect back to your app once the session ends.
32
+
33
+ ## Exception handling
34
+
35
+ You can catch exceptions at any level. See `errors.ts` for a list of exceptions that might be thrown.
36
+
37
+ ```typescript
38
+ try {
39
+ await withLocalWallet(async (wallet) => {
40
+ try {
41
+ await wallet('sign_transaction', /* ... */);
42
+ } catch (e) {
43
+ if (e instanceof SolanaMobileWalletAdapterProtocolReauthorizeError) {
44
+ console.error('The auth token has gone stale');
45
+ await wallet('reauthorize', {auth_token});
46
+ // Retry...
47
+ }
48
+ throw e;
49
+ }
50
+ });
51
+ } catch(e) {
52
+ if (e instanceof SolanaMobileWalletAdapterWalletNotInstalledError) {
53
+ /* ... */
54
+ }
55
+ throw e;
56
+ }
57
+ ```
@@ -0,0 +1,146 @@
1
+ buildscript {
2
+ // Buildscript is evaluated before everything else so we can't use getExtOrDefault
3
+ def kotlin_version = rootProject.ext.has('kotlinVersion') ? rootProject.ext.get('kotlinVersion') : project.properties['SolanaMobileWalletAdapterModule_kotlinVersion']
4
+
5
+ repositories {
6
+ google()
7
+ mavenCentral()
8
+ }
9
+
10
+ dependencies {
11
+ classpath 'com.android.tools.build:gradle:3.5.4'
12
+ // noinspection DifferentKotlinGradleVersion
13
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
14
+ }
15
+ }
16
+
17
+ def isNewArchitectureEnabled() {
18
+ return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
19
+ }
20
+
21
+ apply plugin: 'com.android.library'
22
+ apply plugin: 'kotlin-android'
23
+
24
+ if (isNewArchitectureEnabled()) {
25
+ apply plugin: 'com.facebook.react'
26
+ }
27
+
28
+ def getExtOrDefault(name) {
29
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['SolanaMobileWalletAdapterModule_' + name]
30
+ }
31
+
32
+ def getExtOrIntegerDefault(name) {
33
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties['SolanaMobileWalletAdapterModule_' + name]).toInteger()
34
+ }
35
+
36
+ android {
37
+ compileSdkVersion getExtOrIntegerDefault('compileSdkVersion')
38
+
39
+ defaultConfig {
40
+ minSdkVersion getExtOrIntegerDefault('minSdkVersion')
41
+ targetSdkVersion getExtOrIntegerDefault('targetSdkVersion')
42
+ buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
43
+ }
44
+ buildTypes {
45
+ release {
46
+ minifyEnabled false
47
+ }
48
+ }
49
+
50
+ lintOptions {
51
+ disable 'GradleCompatible'
52
+ }
53
+
54
+ compileOptions {
55
+ sourceCompatibility JavaVersion.VERSION_1_8
56
+ targetCompatibility JavaVersion.VERSION_1_8
57
+ }
58
+ }
59
+
60
+ repositories {
61
+ mavenCentral()
62
+ google()
63
+
64
+ def found = false
65
+ def defaultDir = null
66
+ def androidSourcesName = 'React Native sources'
67
+
68
+ if (rootProject.ext.has('reactNativeAndroidRoot')) {
69
+ defaultDir = rootProject.ext.get('reactNativeAndroidRoot')
70
+ } else {
71
+ defaultDir = new File(
72
+ projectDir,
73
+ '/../../../node_modules/react-native/android'
74
+ )
75
+ }
76
+
77
+ if (defaultDir.exists()) {
78
+ maven {
79
+ url defaultDir.toString()
80
+ name androidSourcesName
81
+ }
82
+
83
+ logger.info(":${project.name}:reactNativeAndroidRoot ${defaultDir.canonicalPath}")
84
+ found = true
85
+ } else {
86
+ def parentDir = rootProject.projectDir
87
+
88
+ 1.upto(5, {
89
+ if (found) return true
90
+ parentDir = parentDir.parentFile
91
+
92
+ def androidSourcesDir = new File(
93
+ parentDir,
94
+ 'node_modules/react-native'
95
+ )
96
+
97
+ def androidPrebuiltBinaryDir = new File(
98
+ parentDir,
99
+ 'node_modules/react-native/android'
100
+ )
101
+
102
+ if (androidPrebuiltBinaryDir.exists()) {
103
+ maven {
104
+ url androidPrebuiltBinaryDir.toString()
105
+ name androidSourcesName
106
+ }
107
+
108
+ logger.info(":${project.name}:reactNativeAndroidRoot ${androidPrebuiltBinaryDir.canonicalPath}")
109
+ found = true
110
+ } else if (androidSourcesDir.exists()) {
111
+ maven {
112
+ url androidSourcesDir.toString()
113
+ name androidSourcesName
114
+ }
115
+
116
+ logger.info(":${project.name}:reactNativeAndroidRoot ${androidSourcesDir.canonicalPath}")
117
+ found = true
118
+ }
119
+ })
120
+ }
121
+
122
+ if (!found) {
123
+ throw new GradleException(
124
+ "${project.name}: unable to locate React Native android sources. " +
125
+ "Ensure you have you installed React Native as a dependency in your project and try again."
126
+ )
127
+ }
128
+ }
129
+
130
+ def kotlin_version = getExtOrDefault('kotlinVersion')
131
+
132
+ dependencies {
133
+ //noinspection GradleDynamicVersion
134
+ implementation "com.facebook.react:react-native:+" // From node_modules
135
+ implementation "com.solanamobile:mobile-wallet-adapter-clientlib:0.1.2"
136
+ implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
137
+ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.2"
138
+ }
139
+
140
+ if (isNewArchitectureEnabled()) {
141
+ react {
142
+ jsRootDir = file("../src/")
143
+ libraryName = "SolanaMobileWalletAdapterModule"
144
+ codegenJavaPackageName = "com.solanamobile.mobilewalletadapter.reactnative"
145
+ }
146
+ }
@@ -0,0 +1,5 @@
1
+ distributionBase=GRADLE_USER_HOME
2
+ distributionPath=wrapper/dists
3
+ distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip
4
+ zipStoreBase=GRADLE_USER_HOME
5
+ zipStorePath=wrapper/dists
@@ -0,0 +1,5 @@
1
+ SolanaMobileWalletAdapterModule_kotlinVersion=1.7.0
2
+ SolanaMobileWalletAdapterModule_minSdkVersion=21
3
+ SolanaMobileWalletAdapterModule_targetSdkVersion=31
4
+ SolanaMobileWalletAdapterModule_compileSdkVersion=31
5
+ SolanaMobileWalletAdapterModule_ndkversion=21.4.7075529
@@ -0,0 +1,185 @@
1
+ #!/usr/bin/env sh
2
+
3
+ #
4
+ # Copyright 2015 the original author or authors.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # https://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ ##############################################################################
20
+ ##
21
+ ## Gradle start up script for UN*X
22
+ ##
23
+ ##############################################################################
24
+
25
+ # Attempt to set APP_HOME
26
+ # Resolve links: $0 may be a link
27
+ PRG="$0"
28
+ # Need this for relative symlinks.
29
+ while [ -h "$PRG" ] ; do
30
+ ls=`ls -ld "$PRG"`
31
+ link=`expr "$ls" : '.*-> \(.*\)$'`
32
+ if expr "$link" : '/.*' > /dev/null; then
33
+ PRG="$link"
34
+ else
35
+ PRG=`dirname "$PRG"`"/$link"
36
+ fi
37
+ done
38
+ SAVED="`pwd`"
39
+ cd "`dirname \"$PRG\"`/" >/dev/null
40
+ APP_HOME="`pwd -P`"
41
+ cd "$SAVED" >/dev/null
42
+
43
+ APP_NAME="Gradle"
44
+ APP_BASE_NAME=`basename "$0"`
45
+
46
+ # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47
+ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48
+
49
+ # Use the maximum available, or set MAX_FD != -1 to use that value.
50
+ MAX_FD="maximum"
51
+
52
+ warn () {
53
+ echo "$*"
54
+ }
55
+
56
+ die () {
57
+ echo
58
+ echo "$*"
59
+ echo
60
+ exit 1
61
+ }
62
+
63
+ # OS specific support (must be 'true' or 'false').
64
+ cygwin=false
65
+ msys=false
66
+ darwin=false
67
+ nonstop=false
68
+ case "`uname`" in
69
+ CYGWIN* )
70
+ cygwin=true
71
+ ;;
72
+ Darwin* )
73
+ darwin=true
74
+ ;;
75
+ MSYS* | MINGW* )
76
+ msys=true
77
+ ;;
78
+ NONSTOP* )
79
+ nonstop=true
80
+ ;;
81
+ esac
82
+
83
+ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84
+
85
+
86
+ # Determine the Java command to use to start the JVM.
87
+ if [ -n "$JAVA_HOME" ] ; then
88
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89
+ # IBM's JDK on AIX uses strange locations for the executables
90
+ JAVACMD="$JAVA_HOME/jre/sh/java"
91
+ else
92
+ JAVACMD="$JAVA_HOME/bin/java"
93
+ fi
94
+ if [ ! -x "$JAVACMD" ] ; then
95
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96
+
97
+ Please set the JAVA_HOME variable in your environment to match the
98
+ location of your Java installation."
99
+ fi
100
+ else
101
+ JAVACMD="java"
102
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103
+
104
+ Please set the JAVA_HOME variable in your environment to match the
105
+ location of your Java installation."
106
+ fi
107
+
108
+ # Increase the maximum file descriptors if we can.
109
+ if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110
+ MAX_FD_LIMIT=`ulimit -H -n`
111
+ if [ $? -eq 0 ] ; then
112
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113
+ MAX_FD="$MAX_FD_LIMIT"
114
+ fi
115
+ ulimit -n $MAX_FD
116
+ if [ $? -ne 0 ] ; then
117
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
118
+ fi
119
+ else
120
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121
+ fi
122
+ fi
123
+
124
+ # For Darwin, add options to specify how the application appears in the dock
125
+ if $darwin; then
126
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127
+ fi
128
+
129
+ # For Cygwin or MSYS, switch paths to Windows format before running java
130
+ if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133
+
134
+ JAVACMD=`cygpath --unix "$JAVACMD"`
135
+
136
+ # We build the pattern for arguments to be converted via cygpath
137
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138
+ SEP=""
139
+ for dir in $ROOTDIRSRAW ; do
140
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
141
+ SEP="|"
142
+ done
143
+ OURCYGPATTERN="(^($ROOTDIRS))"
144
+ # Add a user-defined pattern to the cygpath arguments
145
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147
+ fi
148
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
149
+ i=0
150
+ for arg in "$@" ; do
151
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153
+
154
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156
+ else
157
+ eval `echo args$i`="\"$arg\""
158
+ fi
159
+ i=`expr $i + 1`
160
+ done
161
+ case $i in
162
+ 0) set -- ;;
163
+ 1) set -- "$args0" ;;
164
+ 2) set -- "$args0" "$args1" ;;
165
+ 3) set -- "$args0" "$args1" "$args2" ;;
166
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172
+ esac
173
+ fi
174
+
175
+ # Escape application args
176
+ save () {
177
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178
+ echo " "
179
+ }
180
+ APP_ARGS=`save "$@"`
181
+
182
+ # Collect all arguments for the java command, following the shell quoting and substitution rules
183
+ eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184
+
185
+ exec "$JAVACMD" "$@"
@@ -0,0 +1,89 @@
1
+ @rem
2
+ @rem Copyright 2015 the original author or authors.
3
+ @rem
4
+ @rem Licensed under the Apache License, Version 2.0 (the "License");
5
+ @rem you may not use this file except in compliance with the License.
6
+ @rem You may obtain a copy of the License at
7
+ @rem
8
+ @rem https://www.apache.org/licenses/LICENSE-2.0
9
+ @rem
10
+ @rem Unless required by applicable law or agreed to in writing, software
11
+ @rem distributed under the License is distributed on an "AS IS" BASIS,
12
+ @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ @rem See the License for the specific language governing permissions and
14
+ @rem limitations under the License.
15
+ @rem
16
+
17
+ @if "%DEBUG%" == "" @echo off
18
+ @rem ##########################################################################
19
+ @rem
20
+ @rem Gradle startup script for Windows
21
+ @rem
22
+ @rem ##########################################################################
23
+
24
+ @rem Set local scope for the variables with windows NT shell
25
+ if "%OS%"=="Windows_NT" setlocal
26
+
27
+ set DIRNAME=%~dp0
28
+ if "%DIRNAME%" == "" set DIRNAME=.
29
+ set APP_BASE_NAME=%~n0
30
+ set APP_HOME=%DIRNAME%
31
+
32
+ @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33
+ for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34
+
35
+ @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36
+ set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37
+
38
+ @rem Find java.exe
39
+ if defined JAVA_HOME goto findJavaFromJavaHome
40
+
41
+ set JAVA_EXE=java.exe
42
+ %JAVA_EXE% -version >NUL 2>&1
43
+ if "%ERRORLEVEL%" == "0" goto execute
44
+
45
+ echo.
46
+ echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47
+ echo.
48
+ echo Please set the JAVA_HOME variable in your environment to match the
49
+ echo location of your Java installation.
50
+
51
+ goto fail
52
+
53
+ :findJavaFromJavaHome
54
+ set JAVA_HOME=%JAVA_HOME:"=%
55
+ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56
+
57
+ if exist "%JAVA_EXE%" goto execute
58
+
59
+ echo.
60
+ echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61
+ echo.
62
+ echo Please set the JAVA_HOME variable in your environment to match the
63
+ echo location of your Java installation.
64
+
65
+ goto fail
66
+
67
+ :execute
68
+ @rem Setup the command line
69
+
70
+ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71
+
72
+
73
+ @rem Execute Gradle
74
+ "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75
+
76
+ :end
77
+ @rem End local scope for the variables with windows NT shell
78
+ if "%ERRORLEVEL%"=="0" goto mainEnd
79
+
80
+ :fail
81
+ rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82
+ rem the _cmd.exe /c_ return code!
83
+ if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84
+ exit /b 1
85
+
86
+ :mainEnd
87
+ if "%OS%"=="Windows_NT" endlocal
88
+
89
+ :omega
@@ -0,0 +1,4 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
+ package="com.solanamobile.mobilewalletadapter.reactnative">
3
+
4
+ </manifest>
@@ -0,0 +1,82 @@
1
+ package com.solanamobile.mobilewalletadapter.reactnative
2
+
3
+ import com.facebook.react.bridge.*
4
+ import org.json.JSONArray
5
+ import org.json.JSONException
6
+ import org.json.JSONObject
7
+
8
+ object JSONSerializationUtils {
9
+ @Throws(JSONException::class)
10
+ fun convertMapToJson(readableMap: ReadableMap?): JSONObject {
11
+ val json = JSONObject()
12
+ readableMap?.keySetIterator()?.let { iterator ->
13
+ while (iterator.hasNextKey()) {
14
+ val key = iterator.nextKey()
15
+ when (readableMap.getType(key)) {
16
+ ReadableType.Array -> json.put(
17
+ key,
18
+ readableMap.getArray(key)?.let { convertArrayToJson(it) }
19
+ )
20
+ ReadableType.Boolean -> json.put(key, readableMap.getBoolean(key))
21
+ ReadableType.Map -> json.put(key, convertMapToJson(readableMap.getMap(key)))
22
+ ReadableType.Null -> json.put(key, JSONObject.NULL)
23
+ ReadableType.Number -> json.put(key, readableMap.getDouble(key))
24
+ ReadableType.String -> json.put(key, readableMap.getString(key))
25
+ }
26
+ }
27
+ }
28
+ return json
29
+ }
30
+
31
+ @Throws(JSONException::class)
32
+ private fun convertArrayToJson(readableArray: ReadableArray): JSONArray {
33
+ val array = JSONArray()
34
+ for (i in 0 until readableArray.size()) {
35
+ when (readableArray.getType(i)) {
36
+ ReadableType.Array -> array.put(convertArrayToJson(readableArray.getArray(i)))
37
+ ReadableType.Boolean -> array.put(readableArray.getBoolean(i))
38
+ ReadableType.Map -> array.put(convertMapToJson(readableArray.getMap(i)))
39
+ ReadableType.Null -> {}
40
+ ReadableType.Number -> array.put(readableArray.getDouble(i))
41
+ ReadableType.String -> array.put(readableArray.getString(i))
42
+ }
43
+ }
44
+ return array
45
+ }
46
+
47
+ @Throws(JSONException::class)
48
+ fun convertJsonToMap(jsonObject: JSONObject): ReadableMap {
49
+ val map: WritableMap = WritableNativeMap()
50
+ val iterator = jsonObject.keys()
51
+ while (iterator.hasNext()) {
52
+ val key = iterator.next()
53
+ when (val value = jsonObject[key]) {
54
+ is Boolean -> map.putBoolean(key, value)
55
+ is Double -> map.putDouble(key, value)
56
+ is Int -> map.putInt(key, value)
57
+ is JSONArray -> map.putArray(key, convertJsonToArray(value))
58
+ is JSONObject -> map.putMap(key, convertJsonToMap(value))
59
+ is String -> map.putString(key, value)
60
+ else -> map.putString(key, value.toString())
61
+ }
62
+ }
63
+ return map
64
+ }
65
+
66
+ @Throws(JSONException::class)
67
+ private fun convertJsonToArray(jsonArray: JSONArray): ReadableArray {
68
+ val array: WritableArray = WritableNativeArray()
69
+ for (i in 0 until jsonArray.length()) {
70
+ when (val value = jsonArray[i]) {
71
+ is Boolean -> array.pushBoolean(value)
72
+ is Double -> array.pushDouble(value)
73
+ is Int -> array.pushInt(value)
74
+ is JSONArray -> array.pushArray(convertJsonToArray(value))
75
+ is JSONObject -> array.pushMap(convertJsonToMap(value))
76
+ is String -> array.pushString(value)
77
+ else -> array.pushString(value.toString())
78
+ }
79
+ }
80
+ return array
81
+ }
82
+ }
@@ -0,0 +1,142 @@
1
+ package com.solanamobile.mobilewalletadapter.reactnative
2
+
3
+ import android.net.Uri
4
+ import android.os.Looper
5
+ import android.util.Log
6
+ import com.facebook.react.bridge.*
7
+ import com.solana.mobilewalletadapter.clientlib.protocol.JsonRpc20Client
8
+ import com.solana.mobilewalletadapter.clientlib.protocol.MobileWalletAdapterClient
9
+ import com.solana.mobilewalletadapter.clientlib.scenario.LocalAssociationScenario
10
+ import com.solana.mobilewalletadapter.clientlib.scenario.Scenario
11
+ import com.solanamobile.mobilewalletadapter.reactnative.JSONSerializationUtils.convertJsonToMap
12
+ import com.solanamobile.mobilewalletadapter.reactnative.JSONSerializationUtils.convertMapToJson
13
+ import kotlinx.coroutines.*
14
+ import kotlinx.coroutines.sync.Mutex
15
+ import kotlinx.coroutines.sync.Semaphore
16
+ import org.json.JSONObject
17
+ import java.util.concurrent.ExecutionException
18
+
19
+ class SolanaMobileWalletAdapterModule(reactContext: ReactApplicationContext) :
20
+ ReactContextBaseJavaModule(reactContext), CoroutineScope {
21
+
22
+ data class SessionState(
23
+ val client: MobileWalletAdapterClient,
24
+ val localAssociation: LocalAssociationScenario,
25
+ val semSessionTermination: Semaphore,
26
+ )
27
+
28
+ override val coroutineContext =
29
+ Dispatchers.IO + CoroutineName("SolanaMobileWalletAdapterModuleScope") + SupervisorJob()
30
+
31
+ companion object {
32
+ private const val ASSOCIATION_TIMEOUT_MS = 10000
33
+ private const val CLIENT_TIMEOUT_MS = 90000
34
+
35
+ // Used to ensure that you can't start more than one session at a time.
36
+ private val mutex: Mutex = Mutex()
37
+ private var sessionState: SessionState? = null
38
+ }
39
+
40
+ override fun getName(): String {
41
+ return "SolanaMobileWalletAdapter"
42
+ }
43
+
44
+ @ReactMethod
45
+ fun startSession(config: ReadableMap?, promise: Promise) = launch {
46
+ mutex.lock()
47
+ Log.d(name, "startSession with config $config")
48
+ try {
49
+ val semConnectedOrFailed = Semaphore(1, 1)
50
+ val semTerminated = Semaphore(1, 1)
51
+ val uriPrefix = config?.getString("baseUri")?.let { Uri.parse(it) }
52
+ lateinit var localAssociation: LocalAssociationScenario
53
+ val scenarioCallbacks = object : Scenario.Callbacks {
54
+ override fun onScenarioReady(client: MobileWalletAdapterClient) {
55
+ sessionState = SessionState(client, localAssociation, semTerminated)
56
+ semConnectedOrFailed.release()
57
+ }
58
+
59
+ override fun onScenarioError() = semConnectedOrFailed.release()
60
+ override fun onScenarioComplete() = semConnectedOrFailed.release()
61
+ override fun onScenarioTeardownComplete() = semTerminated.release()
62
+ }
63
+ localAssociation = LocalAssociationScenario(
64
+ Looper.getMainLooper(),
65
+ ASSOCIATION_TIMEOUT_MS,
66
+ scenarioCallbacks,
67
+ uriPrefix
68
+ )
69
+ val intent = localAssociation.createAssociationIntent()
70
+ currentActivity?.startActivityForResult(intent, 0)
71
+ ?: throw NullPointerException("Could not find a current activity from which to launch a local association")
72
+ localAssociation.start()
73
+ withTimeout(ASSOCIATION_TIMEOUT_MS.toLong()) {
74
+ semConnectedOrFailed.acquire()
75
+ }
76
+ promise.resolve(true)
77
+ } catch (e: TimeoutCancellationException) {
78
+ Log.e(name, "Timed out waiting for local association to be ready", e)
79
+ cleanup()
80
+ promise.reject("Timed out waiting for local association to be ready", e)
81
+ } catch (e: Throwable) {
82
+ Log.e(name, "Failed to start session", e)
83
+ cleanup()
84
+ promise.reject(e)
85
+ }
86
+ }
87
+
88
+ @ReactMethod
89
+ fun invoke(method: String, params: ReadableMap, promise: Promise) = sessionState?.let {
90
+ Log.d(name, "invoke `$method` with params $params")
91
+ try {
92
+ val result = it.client.methodCall(
93
+ method,
94
+ convertMapToJson(params),
95
+ CLIENT_TIMEOUT_MS
96
+ ).get() as JSONObject
97
+ promise.resolve(convertJsonToMap(result))
98
+ } catch (e: ExecutionException) {
99
+ val cause = e.cause
100
+ if (cause is JsonRpc20Client.JsonRpc20RemoteException) {
101
+ val userInfo = Arguments.createMap()
102
+ userInfo.putInt("jsonRpcErrorCode", cause.code)
103
+ promise.reject("JSON_RPC_ERROR", cause, userInfo)
104
+ } else {
105
+ throw e
106
+ }
107
+ } catch (e: Throwable) {
108
+ Log.e(name, "Failed to invoke `$method` with params $params", e)
109
+ promise.reject(e)
110
+ }
111
+ } ?: throw NullPointerException("Tried to invoke `$method` without an active session")
112
+
113
+ @ReactMethod
114
+ fun endSession(promise: Promise) = sessionState?.let {
115
+ launch {
116
+ Log.d(name, "endSession")
117
+ try {
118
+ it.localAssociation.close()
119
+ withTimeout(ASSOCIATION_TIMEOUT_MS.toLong()) {
120
+ it.semSessionTermination.acquire()
121
+ }
122
+ cleanup()
123
+ promise.resolve(true)
124
+ } catch (e: TimeoutCancellationException) {
125
+ Log.e(name, "Timed out waiting for local association to close", e)
126
+ cleanup()
127
+ promise.reject("Failed to end session", e)
128
+ } catch (e: Throwable) {
129
+ Log.e(name, "Failed to end session", e)
130
+ cleanup()
131
+ promise.reject("Failed to end session", e)
132
+ }
133
+ }
134
+ } ?: throw NullPointerException("Tried to end a session without an active session")
135
+
136
+ private fun cleanup() {
137
+ sessionState = null
138
+ if (mutex.isLocked) {
139
+ mutex.unlock()
140
+ }
141
+ }
142
+ }
@@ -0,0 +1,16 @@
1
+ package com.solanamobile.mobilewalletadapter.reactnative
2
+
3
+ import com.facebook.react.ReactPackage
4
+ import com.facebook.react.bridge.NativeModule
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.uimanager.ViewManager
7
+
8
+ class SolanaMobileWalletAdapterPackage : ReactPackage {
9
+ override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
10
+ return listOf(SolanaMobileWalletAdapterModule(reactContext))
11
+ }
12
+
13
+ override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
14
+ return emptyList()
15
+ }
16
+ }
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- /*! *****************************************************************************
5
+ /******************************************************************************
6
6
  Copyright (c) Microsoft Corporation.
7
7
 
8
8
  Permission to use, copy, modify, and/or distribute this software for any
package/lib/cjs/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- /*! *****************************************************************************
5
+ /******************************************************************************
6
6
  Copyright (c) Microsoft Corporation.
7
7
 
8
8
  Permission to use, copy, modify, and/or distribute this software for any
@@ -0,0 +1,141 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var reactNative = require('react-native');
6
+
7
+ /******************************************************************************
8
+ Copyright (c) Microsoft Corporation.
9
+
10
+ Permission to use, copy, modify, and/or distribute this software for any
11
+ purpose with or without fee is hereby granted.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
14
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
15
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
16
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
17
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
18
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19
+ PERFORMANCE OF THIS SOFTWARE.
20
+ ***************************************************************************** */
21
+
22
+ function __awaiter(thisArg, _arguments, P, generator) {
23
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
24
+ return new (P || (P = Promise))(function (resolve, reject) {
25
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
26
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
27
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
28
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
29
+ });
30
+ }
31
+
32
+ class SolanaMobileWalletAdapterSecureContextRequiredError extends Error {
33
+ constructor() {
34
+ super('The mobile wallet adapter protocol must be used in a secure context (`https`).');
35
+ this.name = 'SolanaMobileWalletAdapterSecureContextRequiredError';
36
+ }
37
+ }
38
+ class SolanaMobileWalletAdapterForbiddenWalletBaseURLError extends Error {
39
+ constructor() {
40
+ super('Base URLs supplied by wallets must be valid `https` URLs');
41
+ this.name = 'SolanaMobileWalletAdapterForbiddenWalletBaseURLError';
42
+ }
43
+ }
44
+ class SolanaMobileWalletAdapterWalletNotInstalledError extends Error {
45
+ constructor() {
46
+ super(`Found no installed wallet that supports the mobile wallet protocol.`);
47
+ this.name = 'SolanaMobileWalletAdapterWalletNotInstalledError';
48
+ }
49
+ }
50
+ class SolanaMobileWalletAdapterProtocolSessionEstablishmentError extends Error {
51
+ constructor(port) {
52
+ super(`Failed to connect to the wallet websocket on port ${port}.`);
53
+ this.name = 'SolanaMobileWalletAdapterProtocolSessionEstablishmentError';
54
+ }
55
+ }
56
+ class SolanaMobileWalletAdapterProtocolAssociationPortOutOfRangeError extends Error {
57
+ constructor(port) {
58
+ super(`Association port number must be between 49152 and 65535. ${port} given.`);
59
+ this.name = 'SolanaMobileWalletAdapterProtocolAssociationPortOutOfRangeError';
60
+ }
61
+ }
62
+ class SolanaMobileWalletAdapterProtocolSessionClosedError extends Error {
63
+ constructor(code, reason) {
64
+ super(`The wallet session dropped unexpectedly (${code}: ${reason}).`);
65
+ this.name = 'SolanaMobileWalletAdapterProtocolSessionClosedError';
66
+ }
67
+ }
68
+ class SolanaMobileWalletAdapterProtocolReauthorizeError extends Error {
69
+ constructor() {
70
+ super('The auth token provided has gone stale and needs reauthorization.');
71
+ this.name = 'SolanaMobileWalletAdapterProtocolReauthorizeError';
72
+ }
73
+ }
74
+ // Typescript `enums` thwart tree-shaking. See https://bargsten.org/jsts/enums/
75
+ const SolanaMobileWalletAdapterProtocolError = {
76
+ ERROR_REAUTHORIZE: -1,
77
+ ERROR_AUTHORIZATION_FAILED: -2,
78
+ ERROR_INVALID_PAYLOAD: -3,
79
+ ERROR_NOT_SIGNED: -4,
80
+ ERROR_NOT_COMMITTED: -5,
81
+ ERROR_ATTEST_ORIGIN_ANDROID: -100,
82
+ };
83
+ class SolanaMobileWalletAdapterProtocolJsonRpcError extends Error {
84
+ constructor(...args) {
85
+ const [jsonRpcMessageId, code, message, data] = args;
86
+ super(message);
87
+ this.code = code;
88
+ this.data = data;
89
+ this.jsonRpcMessageId = jsonRpcMessageId;
90
+ this.name = 'SolanaNativeWalletAdapterJsonRpcError';
91
+ }
92
+ }
93
+
94
+ const LINKING_ERROR = `The package 'solana-mobile-wallet-adapter-protocol' doesn't seem to be linked. Make sure: \n\n` +
95
+ '- You rebuilt the app after installing the package\n' +
96
+ '- If you are using Lerna workspaces\n' +
97
+ ' - You have added `@solana-mobile/mobile-wallet-adapter-protocol` as an explicit dependency, and\n' +
98
+ ' - You have added `@solana-mobile/mobile-wallet-adapter-protocol` to the `nohoist` section of your package.json\n' +
99
+ '- You are not using Expo managed workflow\n';
100
+ const SolanaMobileWalletAdapter = reactNative.Platform.OS === 'android' && reactNative.NativeModules.SolanaMobileWalletAdapter
101
+ ? reactNative.NativeModules.SolanaMobileWalletAdapter
102
+ : new Proxy({}, {
103
+ get() {
104
+ throw new Error(reactNative.Platform.OS !== 'android'
105
+ ? 'The package `solana-mobile-wallet-adapter-protocol` is only compatible with React Native Android'
106
+ : LINKING_ERROR);
107
+ },
108
+ });
109
+ function withLocalWallet(callback, config) {
110
+ return __awaiter(this, void 0, void 0, function* () {
111
+ try {
112
+ yield SolanaMobileWalletAdapter.startSession(config);
113
+ return yield callback((method, params) => __awaiter(this, void 0, void 0, function* () {
114
+ try {
115
+ return yield SolanaMobileWalletAdapter.invoke(method, params);
116
+ }
117
+ catch (e) {
118
+ if (e instanceof Error && e.code === 'JSON_RPC_ERROR') {
119
+ const details = e.userInfo;
120
+ throw new SolanaMobileWalletAdapterProtocolJsonRpcError(0 /* jsonRpcMessageId */, details.jsonRpcErrorCode, e.message);
121
+ }
122
+ throw e;
123
+ }
124
+ }));
125
+ }
126
+ finally {
127
+ yield SolanaMobileWalletAdapter.endSession();
128
+ }
129
+ });
130
+ }
131
+
132
+ exports.SolanaMobileWalletAdapterForbiddenWalletBaseURLError = SolanaMobileWalletAdapterForbiddenWalletBaseURLError;
133
+ exports.SolanaMobileWalletAdapterProtocolAssociationPortOutOfRangeError = SolanaMobileWalletAdapterProtocolAssociationPortOutOfRangeError;
134
+ exports.SolanaMobileWalletAdapterProtocolError = SolanaMobileWalletAdapterProtocolError;
135
+ exports.SolanaMobileWalletAdapterProtocolJsonRpcError = SolanaMobileWalletAdapterProtocolJsonRpcError;
136
+ exports.SolanaMobileWalletAdapterProtocolReauthorizeError = SolanaMobileWalletAdapterProtocolReauthorizeError;
137
+ exports.SolanaMobileWalletAdapterProtocolSessionClosedError = SolanaMobileWalletAdapterProtocolSessionClosedError;
138
+ exports.SolanaMobileWalletAdapterProtocolSessionEstablishmentError = SolanaMobileWalletAdapterProtocolSessionEstablishmentError;
139
+ exports.SolanaMobileWalletAdapterSecureContextRequiredError = SolanaMobileWalletAdapterSecureContextRequiredError;
140
+ exports.SolanaMobileWalletAdapterWalletNotInstalledError = SolanaMobileWalletAdapterWalletNotInstalledError;
141
+ exports.withLocalWallet = withLocalWallet;
@@ -1,4 +1,4 @@
1
- /*! *****************************************************************************
1
+ /******************************************************************************
2
2
  Copyright (c) Microsoft Corporation.
3
3
 
4
4
  Permission to use, copy, modify, and/or distribute this software for any
package/lib/esm/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! *****************************************************************************
1
+ /******************************************************************************
2
2
  Copyright (c) Microsoft Corporation.
3
3
 
4
4
  Permission to use, copy, modify, and/or distribute this software for any
@@ -30,6 +30,9 @@ type Base64EncodedMessage = string;
30
30
  type Base64EncodedSignedMessage = string;
31
31
  type Base64EncodedSignedTransaction = string;
32
32
  type Base64EncodedTransaction = string;
33
+ type WalletAssociationConfig = Readonly<{
34
+ baseUri?: string;
35
+ }>;
33
36
  interface MobileWallet {
34
37
  (method: "authorize", params: {
35
38
  identity: AppIdentity;
@@ -71,10 +74,7 @@ interface MobileWallet {
71
74
  signatures: Base58EncodedSignature[];
72
75
  }>>;
73
76
  }
74
- type Config = Readonly<{
75
- baseUri?: string;
76
- }>;
77
- declare function withLocalWallet<TReturn>(callback: (wallet: MobileWallet) => TReturn, config?: Config): Promise<TReturn>;
77
+ declare function withLocalWallet<TReturn>(callback: (wallet: MobileWallet) => TReturn, config?: WalletAssociationConfig): Promise<TReturn>;
78
78
  declare class SolanaMobileWalletAdapterSecureContextRequiredError extends Error {
79
79
  constructor();
80
80
  }
@@ -129,5 +129,5 @@ declare class SolanaMobileWalletAdapterProtocolJsonRpcError<TErrorCode extends k
129
129
  message: string
130
130
  ]);
131
131
  }
132
- export { withLocalWallet, SolanaMobileWalletAdapterSecureContextRequiredError, SolanaMobileWalletAdapterForbiddenWalletBaseURLError, SolanaMobileWalletAdapterWalletNotInstalledError, SolanaMobileWalletAdapterProtocolSessionEstablishmentError, SolanaMobileWalletAdapterProtocolAssociationPortOutOfRangeError, SolanaMobileWalletAdapterProtocolSessionClosedError, SolanaMobileWalletAdapterProtocolReauthorizeError, SolanaMobileWalletAdapterProtocolError, SolanaMobileWalletAdapterProtocolJsonRpcError, AppIdentity, AssociationKeypair, AuthorizationResult, AuthToken, MobileWallet };
132
+ export { withLocalWallet, SolanaMobileWalletAdapterSecureContextRequiredError, SolanaMobileWalletAdapterForbiddenWalletBaseURLError, SolanaMobileWalletAdapterWalletNotInstalledError, SolanaMobileWalletAdapterProtocolSessionEstablishmentError, SolanaMobileWalletAdapterProtocolAssociationPortOutOfRangeError, SolanaMobileWalletAdapterProtocolSessionClosedError, SolanaMobileWalletAdapterProtocolReauthorizeError, SolanaMobileWalletAdapterProtocolError, SolanaMobileWalletAdapterProtocolJsonRpcError, AppIdentity, AssociationKeypair, AuthorizationResult, AuthToken, WalletAssociationConfig, MobileWallet };
133
133
  //# sourceMappingURL=index.browser.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.browser.d.mts","sourceRoot":"","sources":["../../src/index.ts","../../src/createHelloReq.ts","../../src/errors.ts","../../src/generateAssociationKeypair.ts","../../src/generateECDHKeypair.ts","../../src/parseHelloRsp.ts","../../src/jsonRpcMessage.ts","../../src/associationPort.ts","../../src/arrayBufferToBase64String.ts","../../src/getStringWithURLUnsafeBase64CharactersReplaced.ts","../../src/getAssociateAndroidIntentURL.ts","../../src/startSession.ts","../../src/types.ts","../../src/withLocalWallet.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,2jBAA8B,CAA0B"}
1
+ {"version":3,"file":"index.browser.d.mts","sourceRoot":"","sources":["../../src/index.ts","../../src/createHelloReq.ts","../../src/errors.ts","../../src/generateAssociationKeypair.ts","../../src/generateECDHKeypair.ts","../../src/parseHelloRsp.ts","../../src/jsonRpcMessage.ts","../../src/associationPort.ts","../../src/arrayBufferToBase64String.ts","../../src/getStringWithURLUnsafeBase64CharactersReplaced.ts","../../src/getAssociateAndroidIntentURL.ts","../../src/startSession.ts","../../src/types.ts","../../src/withLocalWallet.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,olBAA8B,CAA0B"}
@@ -30,6 +30,9 @@ type Base64EncodedMessage = string;
30
30
  type Base64EncodedSignedMessage = string;
31
31
  type Base64EncodedSignedTransaction = string;
32
32
  type Base64EncodedTransaction = string;
33
+ type WalletAssociationConfig = Readonly<{
34
+ baseUri?: string;
35
+ }>;
33
36
  interface MobileWallet {
34
37
  (method: "authorize", params: {
35
38
  identity: AppIdentity;
@@ -71,10 +74,7 @@ interface MobileWallet {
71
74
  signatures: Base58EncodedSignature[];
72
75
  }>>;
73
76
  }
74
- type Config = Readonly<{
75
- baseUri?: string;
76
- }>;
77
- declare function withLocalWallet<TReturn>(callback: (wallet: MobileWallet) => TReturn, config?: Config): Promise<TReturn>;
77
+ declare function withLocalWallet<TReturn>(callback: (wallet: MobileWallet) => TReturn, config?: WalletAssociationConfig): Promise<TReturn>;
78
78
  declare class SolanaMobileWalletAdapterSecureContextRequiredError extends Error {
79
79
  constructor();
80
80
  }
@@ -129,5 +129,5 @@ declare class SolanaMobileWalletAdapterProtocolJsonRpcError<TErrorCode extends k
129
129
  message: string
130
130
  ]);
131
131
  }
132
- export { withLocalWallet, SolanaMobileWalletAdapterSecureContextRequiredError, SolanaMobileWalletAdapterForbiddenWalletBaseURLError, SolanaMobileWalletAdapterWalletNotInstalledError, SolanaMobileWalletAdapterProtocolSessionEstablishmentError, SolanaMobileWalletAdapterProtocolAssociationPortOutOfRangeError, SolanaMobileWalletAdapterProtocolSessionClosedError, SolanaMobileWalletAdapterProtocolReauthorizeError, SolanaMobileWalletAdapterProtocolError, SolanaMobileWalletAdapterProtocolJsonRpcError, AppIdentity, AssociationKeypair, AuthorizationResult, AuthToken, MobileWallet };
132
+ export { withLocalWallet, SolanaMobileWalletAdapterSecureContextRequiredError, SolanaMobileWalletAdapterForbiddenWalletBaseURLError, SolanaMobileWalletAdapterWalletNotInstalledError, SolanaMobileWalletAdapterProtocolSessionEstablishmentError, SolanaMobileWalletAdapterProtocolAssociationPortOutOfRangeError, SolanaMobileWalletAdapterProtocolSessionClosedError, SolanaMobileWalletAdapterProtocolReauthorizeError, SolanaMobileWalletAdapterProtocolError, SolanaMobileWalletAdapterProtocolJsonRpcError, AppIdentity, AssociationKeypair, AuthorizationResult, AuthToken, WalletAssociationConfig, MobileWallet };
133
133
  //# sourceMappingURL=index.browser.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.browser.d.ts","sourceRoot":"","sources":["../../src/index.ts","../../src/createHelloReq.ts","../../src/errors.ts","../../src/generateAssociationKeypair.ts","../../src/generateECDHKeypair.ts","../../src/parseHelloRsp.ts","../../src/jsonRpcMessage.ts","../../src/associationPort.ts","../../src/arrayBufferToBase64String.ts","../../src/getStringWithURLUnsafeBase64CharactersReplaced.ts","../../src/getAssociateAndroidIntentURL.ts","../../src/startSession.ts","../../src/types.ts","../../src/withLocalWallet.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,2jBAA8B,CAA0B"}
1
+ {"version":3,"file":"index.browser.d.ts","sourceRoot":"","sources":["../../src/index.ts","../../src/createHelloReq.ts","../../src/errors.ts","../../src/generateAssociationKeypair.ts","../../src/generateECDHKeypair.ts","../../src/parseHelloRsp.ts","../../src/jsonRpcMessage.ts","../../src/associationPort.ts","../../src/arrayBufferToBase64String.ts","../../src/getStringWithURLUnsafeBase64CharactersReplaced.ts","../../src/getAssociateAndroidIntentURL.ts","../../src/startSession.ts","../../src/types.ts","../../src/withLocalWallet.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,olBAA8B,CAA0B"}
@@ -30,6 +30,9 @@ type Base64EncodedMessage = string;
30
30
  type Base64EncodedSignedMessage = string;
31
31
  type Base64EncodedSignedTransaction = string;
32
32
  type Base64EncodedTransaction = string;
33
+ type WalletAssociationConfig = Readonly<{
34
+ baseUri?: string;
35
+ }>;
33
36
  interface MobileWallet {
34
37
  (method: "authorize", params: {
35
38
  identity: AppIdentity;
@@ -71,10 +74,7 @@ interface MobileWallet {
71
74
  signatures: Base58EncodedSignature[];
72
75
  }>>;
73
76
  }
74
- type Config = Readonly<{
75
- baseUri?: string;
76
- }>;
77
- declare function withLocalWallet<TReturn>(callback: (wallet: MobileWallet) => TReturn, config?: Config): Promise<TReturn>;
77
+ declare function withLocalWallet<TReturn>(callback: (wallet: MobileWallet) => TReturn, config?: WalletAssociationConfig): Promise<TReturn>;
78
78
  declare class SolanaMobileWalletAdapterSecureContextRequiredError extends Error {
79
79
  constructor();
80
80
  }
@@ -129,5 +129,5 @@ declare class SolanaMobileWalletAdapterProtocolJsonRpcError<TErrorCode extends k
129
129
  message: string
130
130
  ]);
131
131
  }
132
- export { withLocalWallet, SolanaMobileWalletAdapterSecureContextRequiredError, SolanaMobileWalletAdapterForbiddenWalletBaseURLError, SolanaMobileWalletAdapterWalletNotInstalledError, SolanaMobileWalletAdapterProtocolSessionEstablishmentError, SolanaMobileWalletAdapterProtocolAssociationPortOutOfRangeError, SolanaMobileWalletAdapterProtocolSessionClosedError, SolanaMobileWalletAdapterProtocolReauthorizeError, SolanaMobileWalletAdapterProtocolError, SolanaMobileWalletAdapterProtocolJsonRpcError, AppIdentity, AssociationKeypair, AuthorizationResult, AuthToken, MobileWallet };
132
+ export { withLocalWallet, SolanaMobileWalletAdapterSecureContextRequiredError, SolanaMobileWalletAdapterForbiddenWalletBaseURLError, SolanaMobileWalletAdapterWalletNotInstalledError, SolanaMobileWalletAdapterProtocolSessionEstablishmentError, SolanaMobileWalletAdapterProtocolAssociationPortOutOfRangeError, SolanaMobileWalletAdapterProtocolSessionClosedError, SolanaMobileWalletAdapterProtocolReauthorizeError, SolanaMobileWalletAdapterProtocolError, SolanaMobileWalletAdapterProtocolJsonRpcError, AppIdentity, AssociationKeypair, AuthorizationResult, AuthToken, WalletAssociationConfig, MobileWallet };
133
133
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../src/index.ts","../../src/createHelloReq.ts","../../src/errors.ts","../../src/generateAssociationKeypair.ts","../../src/generateECDHKeypair.ts","../../src/parseHelloRsp.ts","../../src/jsonRpcMessage.ts","../../src/associationPort.ts","../../src/arrayBufferToBase64String.ts","../../src/getStringWithURLUnsafeBase64CharactersReplaced.ts","../../src/getAssociateAndroidIntentURL.ts","../../src/startSession.ts","../../src/types.ts","../../src/withLocalWallet.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,2jBAA8B,CAA0B"}
1
+ {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../src/index.ts","../../src/createHelloReq.ts","../../src/errors.ts","../../src/generateAssociationKeypair.ts","../../src/generateECDHKeypair.ts","../../src/parseHelloRsp.ts","../../src/jsonRpcMessage.ts","../../src/associationPort.ts","../../src/arrayBufferToBase64String.ts","../../src/getStringWithURLUnsafeBase64CharactersReplaced.ts","../../src/getAssociateAndroidIntentURL.ts","../../src/startSession.ts","../../src/types.ts","../../src/withLocalWallet.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,olBAA8B,CAA0B"}
@@ -30,6 +30,9 @@ type Base64EncodedMessage = string;
30
30
  type Base64EncodedSignedMessage = string;
31
31
  type Base64EncodedSignedTransaction = string;
32
32
  type Base64EncodedTransaction = string;
33
+ type WalletAssociationConfig = Readonly<{
34
+ baseUri?: string;
35
+ }>;
33
36
  interface MobileWallet {
34
37
  (method: "authorize", params: {
35
38
  identity: AppIdentity;
@@ -71,10 +74,7 @@ interface MobileWallet {
71
74
  signatures: Base58EncodedSignature[];
72
75
  }>>;
73
76
  }
74
- type Config = Readonly<{
75
- baseUri?: string;
76
- }>;
77
- declare function withLocalWallet<TReturn>(callback: (wallet: MobileWallet) => TReturn, config?: Config): Promise<TReturn>;
77
+ declare function withLocalWallet<TReturn>(callback: (wallet: MobileWallet) => TReturn, config?: WalletAssociationConfig): Promise<TReturn>;
78
78
  declare class SolanaMobileWalletAdapterSecureContextRequiredError extends Error {
79
79
  constructor();
80
80
  }
@@ -129,5 +129,5 @@ declare class SolanaMobileWalletAdapterProtocolJsonRpcError<TErrorCode extends k
129
129
  message: string
130
130
  ]);
131
131
  }
132
- export { withLocalWallet, SolanaMobileWalletAdapterSecureContextRequiredError, SolanaMobileWalletAdapterForbiddenWalletBaseURLError, SolanaMobileWalletAdapterWalletNotInstalledError, SolanaMobileWalletAdapterProtocolSessionEstablishmentError, SolanaMobileWalletAdapterProtocolAssociationPortOutOfRangeError, SolanaMobileWalletAdapterProtocolSessionClosedError, SolanaMobileWalletAdapterProtocolReauthorizeError, SolanaMobileWalletAdapterProtocolError, SolanaMobileWalletAdapterProtocolJsonRpcError, AppIdentity, AssociationKeypair, AuthorizationResult, AuthToken, MobileWallet };
132
+ export { withLocalWallet, SolanaMobileWalletAdapterSecureContextRequiredError, SolanaMobileWalletAdapterForbiddenWalletBaseURLError, SolanaMobileWalletAdapterWalletNotInstalledError, SolanaMobileWalletAdapterProtocolSessionEstablishmentError, SolanaMobileWalletAdapterProtocolAssociationPortOutOfRangeError, SolanaMobileWalletAdapterProtocolSessionClosedError, SolanaMobileWalletAdapterProtocolReauthorizeError, SolanaMobileWalletAdapterProtocolError, SolanaMobileWalletAdapterProtocolJsonRpcError, AppIdentity, AssociationKeypair, AuthorizationResult, AuthToken, WalletAssociationConfig, MobileWallet };
133
133
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts","../../src/createHelloReq.ts","../../src/errors.ts","../../src/generateAssociationKeypair.ts","../../src/generateECDHKeypair.ts","../../src/parseHelloRsp.ts","../../src/jsonRpcMessage.ts","../../src/associationPort.ts","../../src/arrayBufferToBase64String.ts","../../src/getStringWithURLUnsafeBase64CharactersReplaced.ts","../../src/getAssociateAndroidIntentURL.ts","../../src/startSession.ts","../../src/types.ts","../../src/withLocalWallet.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,2jBAA8B,CAA0B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts","../../src/createHelloReq.ts","../../src/errors.ts","../../src/generateAssociationKeypair.ts","../../src/generateECDHKeypair.ts","../../src/parseHelloRsp.ts","../../src/jsonRpcMessage.ts","../../src/associationPort.ts","../../src/arrayBufferToBase64String.ts","../../src/getStringWithURLUnsafeBase64CharactersReplaced.ts","../../src/getAssociateAndroidIntentURL.ts","../../src/startSession.ts","../../src/types.ts","../../src/withLocalWallet.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,olBAA8B,CAA0B"}
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Properties that wallets may present to users when an app
3
+ * asks for authorization to execute privileged methods (see
4
+ * {@link PrivilegedMethods}).
5
+ */
6
+ type AppIdentity = Readonly<{
7
+ uri?: string;
8
+ icon?: string;
9
+ name?: string;
10
+ }>;
11
+ /**
12
+ * An ephemeral elliptic-curve keypair on the P-256 curve.
13
+ * This public key is used to create the association token.
14
+ * The private key is used during session establishment.
15
+ */
16
+ type AssociationKeypair = CryptoKeyPair;
17
+ /**
18
+ * The context returned from a wallet after having authorized a given
19
+ * account for use with a given application. You can cache this and
20
+ * use it later to invoke privileged methods.
21
+ */
22
+ type AuthorizationResult = Readonly<{
23
+ authToken: string;
24
+ publicKey: string;
25
+ walletUriBase: string;
26
+ }>;
27
+ type AuthToken = string;
28
+ type Base58EncodedSignature = string;
29
+ type Base64EncodedMessage = string;
30
+ type Base64EncodedSignedMessage = string;
31
+ type Base64EncodedSignedTransaction = string;
32
+ type Base64EncodedTransaction = string;
33
+ type WalletAssociationConfig = Readonly<{
34
+ baseUri?: string;
35
+ }>;
36
+ interface MobileWallet {
37
+ (method: "authorize", params: {
38
+ identity: AppIdentity;
39
+ }): Promise<Readonly<{
40
+ auth_token: AuthToken;
41
+ pub_key: string;
42
+ wallet_uri_base: string;
43
+ }>>;
44
+ (method: "clone_authorization", params: {
45
+ auth_token: AuthToken;
46
+ }): Promise<Readonly<{
47
+ auth_token: AuthToken;
48
+ }>>;
49
+ (method: "deauthorize", params: {
50
+ auth_token: AuthToken;
51
+ }): Promise<Readonly<Record<string, never>>>;
52
+ (method: "reauthorize", params: {
53
+ auth_token: AuthToken;
54
+ }): Promise<Readonly<{
55
+ auth_token: AuthToken;
56
+ }>>;
57
+ (method: "sign_message", params: {
58
+ auth_token: AuthToken;
59
+ payloads: Base64EncodedMessage[];
60
+ }): Promise<Readonly<{
61
+ signed_payloads: Base64EncodedSignedMessage[];
62
+ }>>;
63
+ (method: "sign_transaction", params: {
64
+ auth_token: AuthToken;
65
+ payloads: Base64EncodedTransaction[];
66
+ }): Promise<Readonly<{
67
+ signed_payloads: Base64EncodedSignedTransaction[];
68
+ }>>;
69
+ (method: "sign_and_send_transaction", params: {
70
+ auth_token: AuthToken;
71
+ commitment: "confirmed" | "finalized" | "processed";
72
+ payloads: Base64EncodedTransaction[];
73
+ }): Promise<Readonly<{
74
+ signatures: Base58EncodedSignature[];
75
+ }>>;
76
+ }
77
+ declare function withLocalWallet<TReturn>(callback: (wallet: MobileWallet) => TReturn, config?: WalletAssociationConfig): Promise<TReturn>;
78
+ declare class SolanaMobileWalletAdapterSecureContextRequiredError extends Error {
79
+ constructor();
80
+ }
81
+ declare class SolanaMobileWalletAdapterForbiddenWalletBaseURLError extends Error {
82
+ constructor();
83
+ }
84
+ declare class SolanaMobileWalletAdapterWalletNotInstalledError extends Error {
85
+ constructor();
86
+ }
87
+ declare class SolanaMobileWalletAdapterProtocolSessionEstablishmentError extends Error {
88
+ constructor(port: number);
89
+ }
90
+ declare class SolanaMobileWalletAdapterProtocolAssociationPortOutOfRangeError extends Error {
91
+ constructor(port: number);
92
+ }
93
+ declare class SolanaMobileWalletAdapterProtocolSessionClosedError extends Error {
94
+ constructor(code: number, reason: string);
95
+ }
96
+ declare class SolanaMobileWalletAdapterProtocolReauthorizeError extends Error {
97
+ constructor();
98
+ }
99
+ type JSONRPCErrorCode = number;
100
+ // Typescript `enums` thwart tree-shaking. See https://bargsten.org/jsts/enums/
101
+ declare const SolanaMobileWalletAdapterProtocolError: {
102
+ readonly ERROR_REAUTHORIZE: -1;
103
+ readonly ERROR_AUTHORIZATION_FAILED: -2;
104
+ readonly ERROR_INVALID_PAYLOAD: -3;
105
+ readonly ERROR_NOT_SIGNED: -4;
106
+ readonly ERROR_NOT_COMMITTED: -5;
107
+ readonly ERROR_ATTEST_ORIGIN_ANDROID: -100;
108
+ };
109
+ type SolanaMobileWalletAdapterProtocolErrorEnum = (typeof SolanaMobileWalletAdapterProtocolError)[keyof typeof SolanaMobileWalletAdapterProtocolError];
110
+ type ErrorDataTypeMap = {
111
+ [SolanaMobileWalletAdapterProtocolError.ERROR_ATTEST_ORIGIN_ANDROID]: {
112
+ attest_origin_uri: string;
113
+ challenge: string;
114
+ context: string;
115
+ };
116
+ };
117
+ declare class SolanaMobileWalletAdapterProtocolJsonRpcError<TErrorCode extends keyof ErrorDataTypeMap> extends Error {
118
+ data: ErrorDataTypeMap[TErrorCode] extends Record<string, unknown> ? ErrorDataTypeMap[TErrorCode] : undefined;
119
+ code: SolanaMobileWalletAdapterProtocolErrorEnum | JSONRPCErrorCode;
120
+ jsonRpcMessageId: number;
121
+ constructor(...args: ErrorDataTypeMap[TErrorCode] extends Record<string, unknown> ? [
122
+ jsonRpcMessageId: number,
123
+ code: SolanaMobileWalletAdapterProtocolErrorEnum | JSONRPCErrorCode,
124
+ message: string,
125
+ data: ErrorDataTypeMap[TErrorCode]
126
+ ] : [
127
+ jsonRpcMessageId: number,
128
+ code: SolanaMobileWalletAdapterProtocolErrorEnum | JSONRPCErrorCode,
129
+ message: string
130
+ ]);
131
+ }
132
+ export { withLocalWallet, SolanaMobileWalletAdapterSecureContextRequiredError, SolanaMobileWalletAdapterForbiddenWalletBaseURLError, SolanaMobileWalletAdapterWalletNotInstalledError, SolanaMobileWalletAdapterProtocolSessionEstablishmentError, SolanaMobileWalletAdapterProtocolAssociationPortOutOfRangeError, SolanaMobileWalletAdapterProtocolSessionClosedError, SolanaMobileWalletAdapterProtocolReauthorizeError, SolanaMobileWalletAdapterProtocolError, SolanaMobileWalletAdapterProtocolJsonRpcError, AppIdentity, AssociationKeypair, AuthorizationResult, AuthToken, WalletAssociationConfig, MobileWallet };
133
+ //# sourceMappingURL=index.native.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.native.d.ts","sourceRoot":"","sources":["../../src/index.ts","../../src/createHelloReq.ts","../../src/errors.ts","../../src/generateAssociationKeypair.ts","../../src/generateECDHKeypair.ts","../../src/parseHelloRsp.ts","../../src/jsonRpcMessage.ts","../../src/associationPort.ts","../../src/arrayBufferToBase64String.ts","../../src/getStringWithURLUnsafeBase64CharactersReplaced.ts","../../src/getAssociateAndroidIntentURL.ts","../../src/startSession.ts","../../src/types.ts","../../src/withLocalWallet.ts","../../src/__forks__/react-native/withLocalWallet.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,olBAA8B,CAA0B"}
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "@solana-mobile/mobile-wallet-adapter-protocol",
3
3
  "description": "An implementation of the Solana Mobile Mobile Wallet Adapter protocol. Use this to open a session with a mobile wallet app, and to issue API calls to it.",
4
- "version": "0.0.1-alpha.0",
4
+ "version": "0.0.1-alpha.1",
5
5
  "author": "Steven Luscher <steven.luscher@solanamobile.com>",
6
6
  "repository": "https://github.com/solana-mobile/mobile-wallet-adapter",
7
7
  "license": "Apache-2.0",
8
8
  "type": "module",
9
9
  "sideEffects": false,
10
10
  "main": "lib/cjs/index.js",
11
+ "react-native": "lib/cjs/index.native.js",
11
12
  "module": "lib/esm/index.mjs",
12
13
  "types": "lib/types/index.d.ts",
13
14
  "browser": {
@@ -15,10 +16,15 @@
15
16
  "./lib/esm/index.mjs": "./lib/esm/index.browser.mjs"
16
17
  },
17
18
  "exports": {
18
- "import": "./lib/esm/index.mjs",
19
- "require": "./lib/cjs/index.js"
19
+ "./package.json": "./package.json",
20
+ ".": {
21
+ "import": "./lib/esm/index.mjs",
22
+ "require": "./lib/esm/index.cjs"
23
+ }
20
24
  },
21
25
  "files": [
26
+ "android",
27
+ "!android/build",
22
28
  "lib",
23
29
  "LICENSE"
24
30
  ],
@@ -32,7 +38,12 @@
32
38
  "postbuild": "echo '{\"type\":\"commonjs\"}' | npx json > lib/cjs/package.json && echo '{\"type\":\"module\"} ' | npx json > lib/esm/package.json",
33
39
  "prepublishOnly": "agadoo"
34
40
  },
41
+ "dependencies": {
42
+ "react-native": "^0.69.1"
43
+ },
35
44
  "devDependencies": {
45
+ "@types/react-native": "^0.69.3",
36
46
  "agadoo": "^2.0.0"
37
- }
47
+ },
48
+ "gitHead": "56c859fc81d1dc009d9b49d93af440a5a3e600a9"
38
49
  }