Skip to content

Commit

Permalink
Merge pull request #544 from xmtp/np/multi-wallet-support
Browse files Browse the repository at this point in the history
Mutli Wallet Support
  • Loading branch information
nplasterer authored Nov 22, 2024
2 parents 5c9bf88 + 55b5dfd commit c8ecebb
Show file tree
Hide file tree
Showing 13 changed files with 541 additions and 185 deletions.
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ repositories {
dependencies {
implementation project(':expo-modules-core')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}"
implementation "org.xmtp:android:3.0.6"
implementation "org.xmtp:android:3.0.8"
implementation 'com.google.code.gson:gson:2.10.1'
implementation 'com.facebook.react:react-native:0.71.3'
implementation "com.daveanthonythomas.moshipack:moshipack:1.0.1"
Expand Down
97 changes: 79 additions & 18 deletions android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import expo.modules.xmtpreactnativesdk.wrappers.GroupWrapper
import expo.modules.xmtpreactnativesdk.wrappers.InboxStateWrapper
import expo.modules.xmtpreactnativesdk.wrappers.MemberWrapper
import expo.modules.xmtpreactnativesdk.wrappers.PermissionPolicySetWrapper
import expo.modules.xmtpreactnativesdk.wrappers.WalletParamsWrapper
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
Expand Down Expand Up @@ -253,19 +254,6 @@ class XMTPModule : Module() {
}
}

AsyncFunction("revokeAllOtherInstallations") Coroutine { inboxId: String ->
withContext(Dispatchers.IO) {
logV("revokeAllOtherInstallations")
val client = clients[inboxId] ?: throw XMTPException("No client")
val reactSigner =
ReactNativeSigner(module = this@XMTPModule, address = client.address)
signer = reactSigner

client.revokeAllOtherInstallations(reactSigner)
signer = null
}
}

AsyncFunction("getInboxState") Coroutine { inboxId: String, refreshFromNetwork: Boolean ->
withContext(Dispatchers.IO) {
val client = clients[inboxId] ?: throw XMTPException("No client")
Expand Down Expand Up @@ -317,16 +305,16 @@ class XMTPModule : Module() {
}
}

AsyncFunction("create") Coroutine { address: String, hasAuthInboxCallback: Boolean?, dbEncryptionKey: List<Int>, authParams: String ->
AsyncFunction("create") Coroutine { address: String, hasAuthInboxCallback: Boolean?, dbEncryptionKey: List<Int>, authParams: String, walletParams: String ->
withContext(Dispatchers.IO) {
logV("create")
val authOptions = AuthParamsWrapper.authParamsFromJson(authParams)
val walletOptions = WalletParamsWrapper.walletParamsFromJson(walletParams)
val reactSigner = ReactNativeSigner(
module = this@XMTPModule,
address = address,
type = authOptions.walletType,
chainId = authOptions.chainId,
blockNumber = authOptions.blockNumber
type = walletOptions.walletType,
chainId = walletOptions.chainId,
blockNumber = walletOptions.blockNumber
)
signer = reactSigner
val options = clientOptions(
Expand Down Expand Up @@ -356,6 +344,66 @@ class XMTPModule : Module() {
}
}

AsyncFunction("revokeAllOtherInstallations") Coroutine { inboxId: String, walletParams: String ->
withContext(Dispatchers.IO) {
logV("revokeAllOtherInstallations")
val client = clients[inboxId] ?: throw XMTPException("No client")
val walletOptions = WalletParamsWrapper.walletParamsFromJson(walletParams)
val reactSigner =
ReactNativeSigner(
module = this@XMTPModule,
address = client.address,
type = walletOptions.walletType,
chainId = walletOptions.chainId,
blockNumber = walletOptions.blockNumber
)
signer = reactSigner

client.revokeAllOtherInstallations(reactSigner)
signer = null
}
}

AsyncFunction("addAccount") Coroutine { inboxId: String, newAddress: String, walletParams: String ->
withContext(Dispatchers.IO) {
logV("addAccount")
val client = clients[inboxId] ?: throw XMTPException("No client")
val walletOptions = WalletParamsWrapper.walletParamsFromJson(walletParams)
val reactSigner =
ReactNativeSigner(
module = this@XMTPModule,
address = newAddress,
type = walletOptions.walletType,
chainId = walletOptions.chainId,
blockNumber = walletOptions.blockNumber
)
signer = reactSigner

client.addAccount(reactSigner)
signer = null
}
}

AsyncFunction("removeAccount") Coroutine { inboxId: String, addressToRemove: String, walletParams: String ->
withContext(Dispatchers.IO) {
logV("removeAccount")
val client = clients[inboxId] ?: throw XMTPException("No client")
val walletOptions = WalletParamsWrapper.walletParamsFromJson(walletParams)
val reactSigner =
ReactNativeSigner(
module = this@XMTPModule,
address = client.address,
type = walletOptions.walletType,
chainId = walletOptions.chainId,
blockNumber = walletOptions.blockNumber
)
signer = reactSigner

client.removeAccount(reactSigner, addressToRemove)
signer = null
}
}

AsyncFunction("dropClient") Coroutine { inboxId: String ->
withContext(Dispatchers.IO) {
logV("dropClient")
Expand All @@ -366,13 +414,26 @@ class XMTPModule : Module() {

AsyncFunction("signWithInstallationKey") Coroutine { inboxId: String, message: String ->
withContext(Dispatchers.IO) {
logV("signWithInstallationKey")
val client = clients[inboxId] ?: throw XMTPException("No client")

val signature = client.signWithInstallationKey(message)
signature.map { it.toInt() and 0xFF }
}
}

AsyncFunction("verifySignature") Coroutine { inboxId: String, message: String, signature: List<Int> ->
withContext(Dispatchers.IO) {
logV("verifySignature")
val client = clients[inboxId] ?: throw XMTPException("No client")
val signatureBytes =
signature.foldIndexed(ByteArray(signature.size)) { i, a, v ->
a.apply { set(i, v.toByte()) }
}
client.verifySignature(message, signatureBytes)
}
}

AsyncFunction("canMessage") Coroutine { inboxId: String, peerAddresses: List<String> ->
withContext(Dispatchers.IO) {
logV("canMessage")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ class AuthParamsWrapper(
val appVersion: String?,
val dbDirectory: String?,
val historySyncUrl: String?,
val walletType: WalletType = WalletType.EOA,
val chainId: Long?,
val blockNumber: Long?,
) {
companion object {
fun authParamsFromJson(authParams: String): AuthParamsWrapper {
Expand All @@ -20,6 +17,21 @@ class AuthParamsWrapper(
if (jsonOptions.has("appVersion")) jsonOptions.get("appVersion").asString else null,
if (jsonOptions.has("dbDirectory")) jsonOptions.get("dbDirectory").asString else null,
if (jsonOptions.has("historySyncUrl")) jsonOptions.get("historySyncUrl").asString else null,
)
}
}
}

class WalletParamsWrapper(
val walletType: WalletType = WalletType.EOA,
val chainId: Long?,
val blockNumber: Long?,

) {
companion object {
fun walletParamsFromJson(walletParams: String): WalletParamsWrapper {
val jsonOptions = JsonParser.parseString(walletParams).asJsonObject
return WalletParamsWrapper(
if (jsonOptions.has("walletType")) {
when (jsonOptions.get("walletType").asString) {
"SCW" -> WalletType.SCW
Expand All @@ -30,7 +42,8 @@ class AuthParamsWrapper(
},
if (jsonOptions.has("chainId")) jsonOptions.get("chainId").asLong else null,
if (jsonOptions.has("blockNumber")) jsonOptions.get("blockNumber").asLong else null,
)
)
}
}
}

60 changes: 22 additions & 38 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
PODS:
- BigInt (5.0.0)
- boost (1.76.0)
- CoinbaseWalletSDK/Client (1.0.4)
- CoinbaseWalletSDK/CrossPlatform (1.0.4):
- CoinbaseWalletSDK/Client
- CoinbaseWalletSDKExpo (1.0.10):
- CoinbaseWalletSDK/CrossPlatform (= 1.0.4)
- ExpoModulesCore
- Connect-Swift (0.12.0):
- SwiftProtobuf (~> 1.25.2)
- Connect-Swift (1.0.0):
- SwiftProtobuf (~> 1.28.2)
- CryptoSwift (1.8.3)
- CSecp256k1 (0.2.0)
- DoubleConversion (1.1.6)
- EXApplication (5.4.0):
- ExpoModulesCore
Expand Down Expand Up @@ -49,15 +50,12 @@ PODS:
- React-jsi (= 0.71.14)
- ReactCommon/turbomodule/core (= 0.71.14)
- fmt (6.2.1)
- GenericJSON (2.0.2)
- glog (0.3.5)
- GzipSwift (5.1.1)
- hermes-engine (0.71.14):
- hermes-engine/Pre-built (= 0.71.14)
- hermes-engine/Pre-built (0.71.14)
- libevent (2.1.12)
- LibXMTP (3.0.3)
- Logging (1.0.0)
- LibXMTP (3.0.7)
- MessagePacker (0.4.7)
- MMKV (2.0.0):
- MMKVCore (~> 2.0.0)
Expand Down Expand Up @@ -442,23 +440,17 @@ PODS:
- React-RCTImage
- RNSVG (13.14.0):
- React-Core
- secp256k1.swift (0.1.4)
- SwiftProtobuf (1.25.2)
- web3.swift (1.6.0):
- BigInt (~> 5.0.0)
- GenericJSON (~> 2.0)
- Logging (~> 1.0.0)
- secp256k1.swift (~> 0.1)
- XMTP (3.0.6):
- Connect-Swift (= 0.12.0)
- GzipSwift
- LibXMTP (= 3.0.3)
- web3.swift
- SwiftProtobuf (1.28.2)
- XMTP (3.0.8):
- Connect-Swift (= 1.0.0)
- CryptoSwift (= 1.8.3)
- CSecp256k1 (~> 0.2)
- LibXMTP (= 3.0.7)
- XMTPReactNative (0.1.0):
- CSecp256k1 (~> 0.2)
- ExpoModulesCore
- MessagePacker
- secp256k1.swift
- XMTP (= 3.0.6)
- XMTP (= 3.0.8)
- Yoga (1.14.0)

DEPENDENCIES:
Expand Down Expand Up @@ -533,22 +525,18 @@ DEPENDENCIES:

SPEC REPOS:
trunk:
- BigInt
- CoinbaseWalletSDK
- Connect-Swift
- CryptoSwift
- CSecp256k1
- fmt
- GenericJSON
- GzipSwift
- libevent
- LibXMTP
- Logging
- MessagePacker
- MMKV
- MMKVCore
- OpenSSL-Universal
- secp256k1.swift
- SwiftProtobuf
- web3.swift
- XMTP

EXTERNAL SOURCES:
Expand Down Expand Up @@ -684,11 +672,12 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/yoga"

SPEC CHECKSUMS:
BigInt: 74b4d88367b0e819d9f77393549226d36faeb0d8
boost: 57d2868c099736d80fcd648bf211b4431e51a558
CoinbaseWalletSDK: ea1f37512bbc69ebe07416e3b29bf840f5cc3152
CoinbaseWalletSDKExpo: c79420eb009f482f768c23b6768fc5b2d7c98777
Connect-Swift: 1de2ef4a548c59ecaeb9120812dfe0d6e07a0d47
Connect-Swift: 84e043b904f63dc93a2c01c6c125da25e765b50d
CryptoSwift: 967f37cea5a3294d9cce358f78861652155be483
CSecp256k1: 2a59c03e52637ded98896a33be4b2649392cb843
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
EXApplication: 2a0d9abd4feace9c6faedfe541c1dec02e3702cd
EXConstants: f348da07e21b23d2b085e270d7b74f282df1a7d9
Expand All @@ -706,13 +695,10 @@ SPEC CHECKSUMS:
FBLazyVector: 12ea01e587c9594e7b144e1bfc86ac4d9ac28fde
FBReactNativeSpec: b6ae48e67aaba46442f84d6f9ba598ccfbe2ee66
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
GenericJSON: 79a840eeb77030962e8cf02a62d36bd413b67626
glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b
GzipSwift: 893f3e48e597a1a4f62fafcb6514220fcf8287fa
hermes-engine: d7cc127932c89c53374452d6f93473f1970d8e88
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
LibXMTP: 948d39cf5b978adaa7d0f6ea5c6c0995a0b9e63f
Logging: 9ef4ecb546ad3169398d5a723bc9bea1c46bef26
LibXMTP: 1d9b9514c2b6407a82d72b203288cd5af064d787
MessagePacker: ab2fe250e86ea7aedd1a9ee47a37083edd41fd02
MMKV: f7d1d5945c8765f97f39c3d121f353d46735d801
MMKVCore: c04b296010fcb1d1638f2c69405096aac12f6390
Expand Down Expand Up @@ -760,11 +746,9 @@ SPEC CHECKSUMS:
RNFS: 4ac0f0ea233904cb798630b3c077808c06931688
RNScreens: 218801c16a2782546d30bd2026bb625c0302d70f
RNSVG: d00c8f91c3cbf6d476451313a18f04d220d4f396
secp256k1.swift: a7e7a214f6db6ce5db32cc6b2b45e5c4dd633634
SwiftProtobuf: 407a385e97fd206c4fbe880cc84123989167e0d1
web3.swift: 2263d1e12e121b2c42ffb63a5a7beb1acaf33959
XMTP: 48d0c71ef732ac4d79c2942902a132bf71661029
XMTPReactNative: 406f92e777c9d2891404956309d926e7b2f25c1c
SwiftProtobuf: 4dbaffec76a39a8dc5da23b40af1a5dc01a4c02d
XMTP: f8ee66c4aacc5750ab0f67f5bb86c05cd2513185
XMTPReactNative: 8cda2ca09be81cee8c26d986db65fc6faef57bea
Yoga: e71803b4c1fff832ccf9b92541e00f9b873119b9

PODFILE CHECKSUM: 0e6fe50018f34e575d38dc6a1fdf1f99c9596cdd
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -293,13 +293,17 @@
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-xmtpreactnativesdkexample/Pods-xmtpreactnativesdkexample-resources.sh",
"${PODS_CONFIGURATION_BUILD_DIR}/CryptoSwift/CryptoSwift.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/SwiftProtobuf/SwiftProtobuf.bundle",
);
name = "[CP] Copy Pods Resources";
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/CryptoSwift.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXConstants.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SwiftProtobuf.bundle",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
Expand Down
Loading

0 comments on commit c8ecebb

Please sign in to comment.