diff --git a/wallets/react-wallet-v2/package.json b/wallets/react-wallet-v2/package.json
index 7b36952..a3846b9 100644
--- a/wallets/react-wallet-v2/package.json
+++ b/wallets/react-wallet-v2/package.json
@@ -21,7 +21,8 @@
"framer-motion": "6.2.8",
"ethers": "5.5.4",
"valtio": "1.3.1",
- "react-code-blocks": "0.0.9-0"
+ "react-code-blocks": "0.0.9-0",
+ "@cosmjs/proto-signing": "0.27.1"
},
"devDependencies": {
"@walletconnect/types": "2.0.0-beta.22",
@@ -31,6 +32,6 @@
"eslint-config-next": "12.1.0",
"eslint-config-prettier": "8.4.0",
"prettier": "2.5.1",
- "typescript": "4.5.5"
+ "typescript": "4.6.2"
}
}
diff --git a/wallets/react-wallet-v2/src/components/Modal.tsx b/wallets/react-wallet-v2/src/components/Modal.tsx
index ff2fdc9..7a2990c 100644
--- a/wallets/react-wallet-v2/src/components/Modal.tsx
+++ b/wallets/react-wallet-v2/src/components/Modal.tsx
@@ -1,6 +1,7 @@
import ModalStore from '@/store/ModalStore'
import SessionProposalModal from '@/views/SessionProposalModal'
import SessionSendTransactionModal from '@/views/SessionSendTransactionModal'
+import SessionSignCosmosModal from '@/views/SessionSignCosmosModal'
import SessionRequestModal from '@/views/SessionSignModal'
import SessionSignTypedDataModal from '@/views/SessionSignTypedDataModal'
import SessionUnsuportedMethodModal from '@/views/SessionUnsuportedMethodModal'
@@ -17,6 +18,7 @@ export default function Modal() {
{view === 'SessionSignTypedDataModal' && }
{view === 'SessionSendTransactionModal' && }
{view === 'SessionUnsuportedMethodModal' && }
+ {view === 'SessionSignCosmosModal' && }
)
}
diff --git a/wallets/react-wallet-v2/src/data/COSMOSData.ts b/wallets/react-wallet-v2/src/data/COSMOSData.ts
index ae0d4aa..9d7bd87 100644
--- a/wallets/react-wallet-v2/src/data/COSMOSData.ts
+++ b/wallets/react-wallet-v2/src/data/COSMOSData.ts
@@ -15,3 +15,11 @@ export const COSMOS_MAINNET_CHAINS = {
rpc: ''
}
}
+
+/**
+ * Methods
+ */
+export const COSMOS_SIGNING_METHODS = {
+ COSMOS_SIGN_DIRECT: 'cosmos_signDirect',
+ COSMOS_SIGN_AMINO: 'cosmos_signAmino'
+}
diff --git a/wallets/react-wallet-v2/src/hooks/useWalletConnectEventsManager.ts b/wallets/react-wallet-v2/src/hooks/useWalletConnectEventsManager.ts
index 8c4358e..0d31254 100644
--- a/wallets/react-wallet-v2/src/hooks/useWalletConnectEventsManager.ts
+++ b/wallets/react-wallet-v2/src/hooks/useWalletConnectEventsManager.ts
@@ -1,3 +1,4 @@
+import { COSMOS_SIGNING_METHODS } from '@/data/COSMOSData'
import { EIP155_SIGNING_METHODS } from '@/data/EIP155Data'
import ModalStore from '@/store/ModalStore'
import { walletConnectClient } from '@/utils/WalletConnectUtil'
@@ -40,6 +41,10 @@ export default function useWalletConnectEventsManager(initialized: boolean) {
case EIP155_SIGNING_METHODS.ETH_SIGN_TRANSACTION:
return ModalStore.open('SessionSendTransactionModal', { requestEvent, requestSession })
+ case COSMOS_SIGNING_METHODS.COSMOS_SIGN_DIRECT:
+ case COSMOS_SIGNING_METHODS.COSMOS_SIGN_AMINO:
+ return ModalStore.open('SessionSignCosmosModal', { requestEvent, requestSession })
+
default:
return ModalStore.open('SessionUnsuportedMethodModal', { requestEvent, requestSession })
}
diff --git a/wallets/react-wallet-v2/src/store/ModalStore.ts b/wallets/react-wallet-v2/src/store/ModalStore.ts
index 656d1ba..1225f19 100644
--- a/wallets/react-wallet-v2/src/store/ModalStore.ts
+++ b/wallets/react-wallet-v2/src/store/ModalStore.ts
@@ -19,6 +19,7 @@ interface State {
| 'SessionSignTypedDataModal'
| 'SessionSendTransactionModal'
| 'SessionUnsuportedMethodModal'
+ | 'SessionSignCosmosModal'
data?: ModalData
}
diff --git a/wallets/react-wallet-v2/src/utils/CosmosRequestHandler.ts b/wallets/react-wallet-v2/src/utils/CosmosRequestHandler.ts
new file mode 100644
index 0000000..a15c496
--- /dev/null
+++ b/wallets/react-wallet-v2/src/utils/CosmosRequestHandler.ts
@@ -0,0 +1,30 @@
+import { COSMOS_SIGNING_METHODS } from '@/data/COSMOSData'
+import { cosmosAddresses, cosmosWallets } from '@/utils/CosmosWalletUtil'
+import { getWalletAddressFromParams } from '@/utils/HelperUtil'
+import { formatJsonRpcError, formatJsonRpcResult } from '@json-rpc-tools/utils'
+import { RequestEvent } from '@walletconnect/types'
+import { ERROR } from '@walletconnect/utils'
+
+export async function approveCosmosRequest(requestEvent: RequestEvent) {
+ const { method, params, id } = requestEvent.request
+ const wallet = cosmosWallets[getWalletAddressFromParams(cosmosAddresses, params)]
+
+ switch (method) {
+ case COSMOS_SIGNING_METHODS.COSMOS_SIGN_DIRECT:
+ const signedDirect = await wallet.signDirect(params.signerAddress, params.signDoc)
+ return formatJsonRpcResult(id, signedDirect.signature)
+
+ case COSMOS_SIGNING_METHODS.COSMOS_SIGN_AMINO:
+ const signedAmino = await wallet.signAmino(params.signerAddress, params.signDoc)
+ return formatJsonRpcResult(id, signedAmino.signature)
+
+ default:
+ throw new Error(ERROR.UNKNOWN_JSONRPC_METHOD.format().message)
+ }
+}
+
+export function rejectCosmosRequest(request: RequestEvent['request']) {
+ const { id } = request
+
+ return formatJsonRpcError(id, ERROR.JSONRPC_REQUEST_METHOD_REJECTED.format().message)
+}
diff --git a/wallets/react-wallet-v2/src/utils/CosmosUtil.ts b/wallets/react-wallet-v2/src/utils/CosmosUtil.ts
index 4a4ce0c..912b6f0 100644
--- a/wallets/react-wallet-v2/src/utils/CosmosUtil.ts
+++ b/wallets/react-wallet-v2/src/utils/CosmosUtil.ts
@@ -1,3 +1,5 @@
+// @ts-expect-error
+import { SignDoc } from '@cosmjs/proto-signing/build/codec/cosmos/tx/v1beta1/tx'
import CosmosWallet from 'cosmos-wallet'
import MnemonicKeyring from 'mnemonic-keyring'
@@ -42,4 +44,12 @@ export class Cosmos {
public getMnemonic() {
return this.keyring.mnemonic
}
+
+ public signDirect(address: string, signDoc: SignDoc) {
+ return this.wallet.signDirect(address, signDoc)
+ }
+
+ public signAmino(address: string, signDoc: SignDoc) {
+ return this.wallet.signAmino(address, signDoc)
+ }
}
diff --git a/wallets/react-wallet-v2/src/utils/HelperUtil.ts b/wallets/react-wallet-v2/src/utils/HelperUtil.ts
index 8c7b3a1..64a4bcf 100644
--- a/wallets/react-wallet-v2/src/utils/HelperUtil.ts
+++ b/wallets/react-wallet-v2/src/utils/HelperUtil.ts
@@ -70,10 +70,16 @@ export function getWalletAddressFromParams(addresses: string[], params: any) {
return address
}
+/**
+ * Check if chain is part of EIP155 standard
+ */
export function isEIP155Chain(chain: string) {
return chain.includes('eip155')
}
+/**
+ * Check if chain is part of COSMOS standard
+ */
export function isCosmosChain(chain: string) {
return chain.includes('cosmos')
}
diff --git a/wallets/react-wallet-v2/src/views/SessionSignCosmosModal.tsx b/wallets/react-wallet-v2/src/views/SessionSignCosmosModal.tsx
new file mode 100644
index 0000000..412e228
--- /dev/null
+++ b/wallets/react-wallet-v2/src/views/SessionSignCosmosModal.tsx
@@ -0,0 +1,125 @@
+import { COSMOS_MAINNET_CHAINS, TCosmosChain } from '@/data/COSMOSData'
+import ModalStore from '@/store/ModalStore'
+import { approveCosmosRequest, rejectCosmosRequest } from '@/utils/CosmosRequestHandler'
+import { walletConnectClient } from '@/utils/WalletConnectUtil'
+import { Avatar, Button, Col, Container, Divider, Link, Modal, Row, Text } from '@nextui-org/react'
+import { Fragment } from 'react'
+
+export default function SessionSignCosmosModal() {
+ // Get request and wallet data from store
+ const requestEvent = ModalStore.state.data?.requestEvent
+ const requestSession = ModalStore.state.data?.requestSession
+
+ // Ensure request and wallet are defined
+ if (!requestEvent || !requestSession) {
+ return Missing request data
+ }
+
+ // Get required request data
+ const { chainId } = requestEvent
+ const { method, params } = requestEvent.request
+ const { protocol } = requestSession.relay
+ const { name, icons, url } = requestSession.peer.metadata
+
+ // Handle approve action (logic varies based on request method)
+ async function onApprove() {
+ if (requestEvent) {
+ const response = await approveCosmosRequest(requestEvent)
+ await walletConnectClient.respond({
+ topic: requestEvent.topic,
+ response
+ })
+ ModalStore.close()
+ }
+ }
+
+ // Handle reject action
+ async function onReject() {
+ if (requestEvent) {
+ const response = rejectCosmosRequest(requestEvent.request)
+ await walletConnectClient.respond({
+ topic: requestEvent.topic,
+ response
+ })
+ ModalStore.close()
+ }
+ }
+
+ return (
+
+
+ Sign Message
+
+
+
+
+
+
+
+
+
+ {name}
+ {url}
+
+
+
+
+
+
+
+ Blockchain
+
+ {COSMOS_MAINNET_CHAINS[chainId as TCosmosChain]?.name ?? chainId}
+
+
+
+
+
+
+
+
+ Message
+ {JSON.stringify(params.signDoc.msgs) ?? 'No Message'}
+
+
+
+
+
+
+
+ Memo
+ {JSON.stringify(params.signDoc.memo)}
+
+
+
+
+
+
+
+ Method
+ {method}
+
+
+
+
+
+
+
+ Relay Protocol
+ {protocol}
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/wallets/react-wallet-v2/yarn.lock b/wallets/react-wallet-v2/yarn.lock
index 645bf4f..8f5c634 100644
--- a/wallets/react-wallet-v2/yarn.lock
+++ b/wallets/react-wallet-v2/yarn.lock
@@ -143,6 +143,16 @@
"@babel/helper-validator-identifier" "^7.16.7"
to-fast-properties "^2.0.0"
+"@cosmjs/amino@0.27.1":
+ version "0.27.1"
+ resolved "https://registry.yarnpkg.com/@cosmjs/amino/-/amino-0.27.1.tgz#0910256b5aecd794420bb5f7319d98fc63252fa1"
+ integrity sha512-w56ar/nK9+qlvWDpBPRmD0Blk2wfkkLqRi1COs1x7Ll1LF0AtkIBUjbRKplENLbNovK0T3h+w8bHiFm+GBGQOA==
+ dependencies:
+ "@cosmjs/crypto" "0.27.1"
+ "@cosmjs/encoding" "0.27.1"
+ "@cosmjs/math" "0.27.1"
+ "@cosmjs/utils" "0.27.1"
+
"@cosmjs/amino@^0.25.4", "@cosmjs/amino@^0.25.6":
version "0.25.6"
resolved "https://registry.yarnpkg.com/@cosmjs/amino/-/amino-0.25.6.tgz#cdf9632253bfab7b1d2ef967124953d7bf16351f"
@@ -153,6 +163,22 @@
"@cosmjs/math" "^0.25.6"
"@cosmjs/utils" "^0.25.6"
+"@cosmjs/crypto@0.27.1":
+ version "0.27.1"
+ resolved "https://registry.yarnpkg.com/@cosmjs/crypto/-/crypto-0.27.1.tgz#271c853089a3baf3acd6cf0b2122fd49f8815743"
+ integrity sha512-vbcxwSt99tIYJg8Spp00wc3zx72qx+pY3ozGuBN8gAvySnagK9dQ/jHwtWQWdammmdD6oW+75WfIHZ+gNa+Ybg==
+ dependencies:
+ "@cosmjs/encoding" "0.27.1"
+ "@cosmjs/math" "0.27.1"
+ "@cosmjs/utils" "0.27.1"
+ bip39 "^3.0.2"
+ bn.js "^5.2.0"
+ elliptic "^6.5.3"
+ js-sha3 "^0.8.0"
+ libsodium-wrappers "^0.7.6"
+ ripemd160 "^2.0.2"
+ sha.js "^2.4.11"
+
"@cosmjs/crypto@^0.25.6":
version "0.25.6"
resolved "https://registry.yarnpkg.com/@cosmjs/crypto/-/crypto-0.25.6.tgz#695d2d0d2195bdbdd5825d415385646244900bbb"
@@ -169,6 +195,15 @@
ripemd160 "^2.0.2"
sha.js "^2.4.11"
+"@cosmjs/encoding@0.27.1":
+ version "0.27.1"
+ resolved "https://registry.yarnpkg.com/@cosmjs/encoding/-/encoding-0.27.1.tgz#3cd5bc0af743485eb2578cdb08cfa84c86d610e1"
+ integrity sha512-rayLsA0ojHeniaRfWWcqSsrE/T1rl1gl0OXVNtXlPwLJifKBeLEefGbOUiAQaT0wgJ8VNGBazVtAZBpJidfDhw==
+ dependencies:
+ base64-js "^1.3.0"
+ bech32 "^1.1.4"
+ readonly-date "^1.0.0"
+
"@cosmjs/encoding@^0.25.6":
version "0.25.6"
resolved "https://registry.yarnpkg.com/@cosmjs/encoding/-/encoding-0.25.6.tgz#da741a33eaf063a6d3611d7d68db5ca3938e0ef5"
@@ -178,6 +213,13 @@
bech32 "^1.1.4"
readonly-date "^1.0.0"
+"@cosmjs/math@0.27.1":
+ version "0.27.1"
+ resolved "https://registry.yarnpkg.com/@cosmjs/math/-/math-0.27.1.tgz#be78857b008ffc6b1ed6fecaa1c4cd5bc38c07d7"
+ integrity sha512-cHWVjmfIjtRc7f80n7x+J5k8pe+vTVTQ0lA82tIxUgqUvgS6rogPP/TmGtTiZ4+NxWxd11DUISY6gVpr18/VNQ==
+ dependencies:
+ bn.js "^5.2.0"
+
"@cosmjs/math@^0.25.6":
version "0.25.6"
resolved "https://registry.yarnpkg.com/@cosmjs/math/-/math-0.25.6.tgz#25c7b106aaded889a5b80784693caa9e654b0c28"
@@ -185,6 +227,18 @@
dependencies:
bn.js "^4.11.8"
+"@cosmjs/proto-signing@0.27.1":
+ version "0.27.1"
+ resolved "https://registry.yarnpkg.com/@cosmjs/proto-signing/-/proto-signing-0.27.1.tgz#1f8f662550aab012d957d02f43c77d914c2ae0db"
+ integrity sha512-t7/VvQivMdM1KgKWai/9ZCEcGFXJtr9Xo0hGcPLTn9wGkh9tmOsUXINYVMsf5D/jWIm1MDPbGCYfdb9V1Od4hw==
+ dependencies:
+ "@cosmjs/amino" "0.27.1"
+ "@cosmjs/crypto" "0.27.1"
+ "@cosmjs/math" "0.27.1"
+ cosmjs-types "^0.4.0"
+ long "^4.0.0"
+ protobufjs "~6.10.2"
+
"@cosmjs/proto-signing@^0.25.4":
version "0.25.6"
resolved "https://registry.yarnpkg.com/@cosmjs/proto-signing/-/proto-signing-0.25.6.tgz#d9fc57b8e0a46cda97e192bd0435157b24949ff8"
@@ -194,6 +248,11 @@
long "^4.0.0"
protobufjs "~6.10.2"
+"@cosmjs/utils@0.27.1":
+ version "0.27.1"
+ resolved "https://registry.yarnpkg.com/@cosmjs/utils/-/utils-0.27.1.tgz#1c8efde17256346ef142a3bd15158ee4055470e2"
+ integrity sha512-VG7QPDiMUzVPxRdJahDV8PXxVdnuAHiIuG56hldV4yPnOz/si/DLNd7VAUUA5923b6jS1Hhev0Hr6AhEkcxBMg==
+
"@cosmjs/utils@^0.25.6":
version "0.25.6"
resolved "https://registry.yarnpkg.com/@cosmjs/utils/-/utils-0.25.6.tgz#934d9a967180baa66163847616a74358732227ca"
@@ -938,7 +997,7 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-11.11.6.tgz#df929d1bb2eee5afdda598a41930fe50b43eaa6a"
integrity sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==
-"@types/node@17.0.21":
+"@types/node@17.0.21", "@types/node@>=13.7.0":
version "17.0.21"
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.21.tgz#864b987c0c68d07b4345845c3e63b75edd143644"
integrity sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==
@@ -1427,6 +1486,11 @@ bn.js@^4.11.8, bn.js@^4.11.9:
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88"
integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==
+bn.js@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002"
+ integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==
+
brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
@@ -1617,6 +1681,14 @@ core-util-is@~1.0.0:
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85"
integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==
+cosmjs-types@^0.4.0:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/cosmjs-types/-/cosmjs-types-0.4.1.tgz#3b2a53ba60d33159dd075596ce8267cfa7027063"
+ integrity sha512-I7E/cHkIgoJzMNQdFF0YVqPlaTqrqKHrskuSTIqlEyxfB5Lf3WKCajSXVK2yHOfOFfSux/RxEdpMzw/eO4DIog==
+ dependencies:
+ long "^4.0.0"
+ protobufjs "~6.11.2"
+
cosmos-wallet@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/cosmos-wallet/-/cosmos-wallet-1.1.0.tgz#ca554d19fda1a1a7a8ee21fef4e0ef8f7fa9ef7b"
@@ -3285,6 +3357,25 @@ protobufjs@~6.10.2:
"@types/node" "^13.7.0"
long "^4.0.0"
+protobufjs@~6.11.2:
+ version "6.11.2"
+ resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.2.tgz#de39fabd4ed32beaa08e9bb1e30d08544c1edf8b"
+ integrity sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==
+ dependencies:
+ "@protobufjs/aspromise" "^1.1.2"
+ "@protobufjs/base64" "^1.1.2"
+ "@protobufjs/codegen" "^2.0.4"
+ "@protobufjs/eventemitter" "^1.1.0"
+ "@protobufjs/fetch" "^1.1.0"
+ "@protobufjs/float" "^1.0.2"
+ "@protobufjs/inquire" "^1.1.0"
+ "@protobufjs/path" "^1.1.2"
+ "@protobufjs/pool" "^1.1.0"
+ "@protobufjs/utf8" "^1.1.0"
+ "@types/long" "^4.0.1"
+ "@types/node" ">=13.7.0"
+ long "^4.0.0"
+
proxy-compare@2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/proxy-compare/-/proxy-compare-2.0.3.tgz#13fac7a72ca186a3f4a5e99bdff4863f2ced85c1"
@@ -3898,10 +3989,10 @@ typeforce@^1.11.5:
resolved "https://registry.yarnpkg.com/typeforce/-/typeforce-1.18.0.tgz#d7416a2c5845e085034d70fcc5b6cc4a90edbfdc"
integrity sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==
-typescript@4.5.5:
- version "4.5.5"
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3"
- integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==
+typescript@4.6.2:
+ version "4.6.2"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.2.tgz#fe12d2727b708f4eef40f51598b3398baa9611d4"
+ integrity sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==
unbox-primitive@^1.0.1:
version "1.0.1"