Skip to content

Commit

Permalink
Merge pull request #4 from wakumo/dapp-support
Browse files Browse the repository at this point in the history
DApp support
  • Loading branch information
ludowkm authored Mar 1, 2023
2 parents ff88b02 + 5c4effc commit 8bc4e38
Show file tree
Hide file tree
Showing 18 changed files with 720 additions and 169 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@
## 0.1.1

* Upgrade to the latest SDKs Android Bom 1.4.1, iOS 1.3.0

## 1.0.0

* Official support for DApps by creating Pairing, connect with Wallet, send Request and receive Response
85 changes: 62 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
# wallet_connect_v2

WalletConnect V2 for Flutter
WalletConnect V2 for Flutter, available for both Wallet and DApp!

This lib came from the demand of our project [Avacus](https://avacus.cc)
Fully support at [Avacus](https://avacus.cc), you can experience both Mainnet and Testnet as it supports network customization.

We used to try to make in pure Dart but it cost much time to build and test so we decide to make an wrapper to consume SDKs from WalletConnect team!
Feel free to use and don't hesitate to raise issue if there are.

## Getting Started

We make very detail in example so you can follow it.
We make very detail in example so you can follow it for both Wallet and Dapp.

The connection is kept stable follow app lifecycle.

Import and create instance
```dart
Expand All @@ -24,61 +26,98 @@ _client.init(projectId: projectId, appMetadata: walletMetadata);

Listen needed events from our export
```dart
typedef OnConnectionStatus = Function(bool isConnected);
typedef OnSessionProposal = Function(SessionProposal proposal);
typedef OnSessionSettle = Function(Session session);
typedef OnSessionUpdate = Function(String topic);
typedef OnSessionDelete = Function(String topic);
typedef OnSessionRequest = Function(SessionRequest request);
typedef OnEventError = Function(String code, String message);
// example of listen to session proposal
// Wallet & DApp, listen to socket connection change
_client.onConnectionStatus = (isConnected) {
// do something, for e.g update UI
}
// Wallet only, listen to session proposal from DApp
_client.onSessionProposal = (proposal) {
// do approve and reject session here
// proposal request, handle to approve or reject
}
// Wallet & DApp, listen to new session which has been established
_client.onSessionSettle = (session) {
// we have detail information of session
}
// Wallet & DApp
_client.onSessionUpdate = (topic) {
// the session of topic has been updated
}
// Wallet & DApp
_client.onSessionDelete = (topic) {
// the session of topic has been deleted
}
// Wallet & DApp
_client.onSessionRequest = (request) {
// session request, handle to approve or reject
}
// DApp only, when Wallet reject the proposal
_client.onSessionRejection = (topic) {
// handle rejection here, for e.g hide the uri popup
}
// DApp only, when Wallet approve and reject session request
_client.onSessionResponse = (topic) {
// handle response here, for e.g update UI
}
```

Connect to listen event
Connect to listen event, for Wallet & DApp to connect to Relay service
```dart
_client.connect();
```

Disconnect
Disconnect, for Wallet & DApp to disconnect with Relay service
```dart
_client.disconnect();
```

Pair with DApps
Pair with DApps for Wallet only
```dart
_client.pair(uri: uri);
```

Approve session
Approve session for Wallet only
```dart
_client.approveSession(approval: approval);
```

Reject session
Reject session for Wallet only
```dart
_client.rejectSession(proposalId: proposal.id);
```

Disconnect session
Disconnect session for Wallet & DApp
```dart
_client.disconnectSession(topic: topic);
```

Update session
Update session for Wallet & DApp
```dart
_client.updateSession(approval: updateApproval);
```

Approve request
Approve request for Wallet only
```dart
_client.approveRequest(topic: topic, requestId: requestId, result: result);
```

Reject request
Reject request for Wallet only
```dart
_client.rejectRequest(topic: topic, requestId: requestId);
```

Create pair for DApp only
```dart
_client.createPair(namespaces: namespaces);
```

Send request for DApp only
```dart
_client.sendRequest(request: request);
```
5 changes: 3 additions & 2 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ android {
}

dependencies {
implementation("com.walletconnect:sign:2.7.1")
implementation("com.walletconnect:android-core:1.9.1")
implementation 'com.google.code.gson:gson:2.10'
implementation(platform("com.walletconnect:android-bom:1.4.1"))
implementation("com.walletconnect:android-core")
implementation("com.walletconnect:sign")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,58 @@ class WalletConnectV2Plugin : FlutterPlugin, MethodCallHandler, ActivityAware,
}
SignClient.setWalletDelegate(walletDelegate)

val dappDelegate = object : SignClient.DappDelegate {
override fun onSessionApproved(approvedSession: Sign.Model.ApprovedSession) {
val session = SignClient.getActiveSessionByTopic(approvedSession.topic)
if (session != null) {
onEvent(
name = "session_settle", data = session.toFlutterValue()
)
}
}

override fun onSessionRejected(rejectedSession: Sign.Model.RejectedSession) {
onEvent(
name = "session_rejection", data = rejectedSession.toFlutterValue()
)
}

override fun onSessionUpdate(updatedSession: Sign.Model.UpdatedSession) {
// Unused
}

override fun onSessionExtend(session: Sign.Model.Session) {
// Unused
}

override fun onSessionEvent(sessionEvent: Sign.Model.SessionEvent) {
// Unused
}

override fun onSessionDelete(deletedSession: Sign.Model.DeletedSession) {
// Handled by Wallet Delegate
}

override fun onSessionRequestResponse(response: Sign.Model.SessionRequestResponse) {
onEvent(
name = "session_response", data = response.toFlutterValue()
)
}

override fun onConnectionStateChange(state: Sign.Model.ConnectionState) {
// Handled by Wallet Delegate
}

override fun onError(error: Sign.Model.Error) {
onError(
"delegate_error",
errorMessage = error.throwable.message ?: ""
)
}
}

SignClient.setDappDelegate(dappDelegate)

result.success(null)
}
"connect" -> {
Expand Down Expand Up @@ -187,7 +239,7 @@ class WalletConnectV2Plugin : FlutterPlugin, MethodCallHandler, ActivityAware,
result.success(null)
}
"getActivatedSessions" -> {
val sessions = SignClient.getListOfSettledSessions()
val sessions = SignClient.getListOfActiveSessions()
result.success(sessions.map { it.toFlutterValue() })
}
"disconnectSession" -> {
Expand Down Expand Up @@ -249,6 +301,45 @@ class WalletConnectV2Plugin : FlutterPlugin, MethodCallHandler, ActivityAware,
})
result.success(null)
}
"createPair" -> {
val arguments = call.arguments<Map<String, Any>>()!!
val gson = Gson()
val namespaces = arguments.mapValues {
gson.fromJson(
gson.toJson(it.value), Sign.Model.Namespace.Proposal::class.java
)
}
val pairing: Core.Model.Pairing? = CoreClient.Pairing.create {
onError("create_pair_error", errorMessage = it.throwable.message ?: "")
}
if (pairing == null) {
result.success(null)
return
}
val connectParams = Sign.Params.Connect(namespaces = namespaces, pairing = pairing)
SignClient.connect(connectParams, {
result.success(pairing.uri)
}, {
result.success(null)
onError("create_pair_error", errorMessage = it.throwable.message ?: "")
})
}
"sendRequest" -> {
val arguments = call.arguments<Map<String, Any>>()!!
val gson = Gson()
val requestParams = Sign.Params.Request(
sessionTopic = arguments["topic"] as String,
method = arguments["method"] as String,
chainId = arguments["chainId"] as String,
params = gson.toJson(arguments["params"])
)
SignClient.request(requestParams, onError = {
result.success(null)
onError("send_request_error", errorMessage = it.throwable.message ?: "")
}, onSuccess = {
result.success(null)
})
}
else -> {
result.notImplemented()
}
Expand Down Expand Up @@ -365,4 +456,28 @@ fun Sign.Model.SessionRequest.toFlutterValue(): Map<String, String?> {
fun Date.toUtcIsoDateString(): String {
val dateFormat: DateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
return dateFormat.format(this)
}
}

fun Sign.Model.RejectedSession.toFlutterValue(): Map<String, String> {
return mapOf(
"topic" to this.topic
)
}

fun Sign.Model.SessionRequestResponse.toFlutterValue(): Map<String, Any> {
val results: Any = if (this.result is Sign.Model.JsonRpcResponse.JsonRpcResult) {
Gson().toJson((this.result as Sign.Model.JsonRpcResponse.JsonRpcResult).result)
} else {
Gson().toJson(
mapOf(
"code" to (this.result as Sign.Model.JsonRpcResponse.JsonRpcError).code,
"message" to (this.result as Sign.Model.JsonRpcResponse.JsonRpcError).message
)
)
}
return mapOf(
"id" to this.result.id.toString(),
"topic" to this.topic,
"results" to results
)
}
Loading

0 comments on commit 8bc4e38

Please sign in to comment.