From 770d5bc7778383b800a0ea4385c34c94a9c58c8b Mon Sep 17 00:00:00 2001 From: Kieran O'Neill Date: Wed, 14 Jun 2023 14:20:41 +0100 Subject: [PATCH 01/12] build(yarn): add @web3modal/sign-react and @walletconnect/types packages --- package.json | 6 +- yarn.lock | 708 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 703 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 2b096685..3772808b 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,9 @@ "@types/zxcvbn": "^4.4.1", "@typescript-eslint/eslint-plugin": "^5.54.0", "@typescript-eslint/parser": "^5.54.0", + "@walletconnect/types": "^2.8.0", + "@web3modal/sign-react": "^2.4.5", + "add": "^2.0.6", "concurrently": "^7.6.0", "copy-webpack-plugin": "^11.0.0", "cross-env": "^7.0.3", @@ -82,7 +85,8 @@ "webpack": "^5.76.3", "webpack-cli": "^5.0.1", "webpack-dev-server": "^4.13.0", - "webpack-merge": "^5.8.0" + "webpack-merge": "^5.8.0", + "yarn": "^1.22.19" }, "dependencies": { "@agoralabs-sh/algorand-provider": "^1.1.0", diff --git a/yarn.lock b/yarn.lock index b9a0cbed..c236d144 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1889,11 +1889,92 @@ resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A== +"@lit-labs/ssr-dom-shim@^1.0.0", "@lit-labs/ssr-dom-shim@^1.1.0": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.1.1.tgz#64df34e2f12e68e78ac57e571d25ec07fa460ca9" + integrity sha512-kXOeFbfCm4fFf2A3WwVEeQj55tMZa8c8/f9AKHMobQMkzNUfUj+antR3fRPaZJawsa1aZiP/Da3ndpZrwEe4rQ== + +"@lit/reactive-element@^1.3.0", "@lit/reactive-element@^1.6.0": + version "1.6.2" + resolved "https://registry.yarnpkg.com/@lit/reactive-element/-/reactive-element-1.6.2.tgz#c256690f82f2d7d0ffb0b1cdf68dcb1ec86cea28" + integrity sha512-rDfl+QnCYjuIGf5xI2sVJWdYIi56CTCwWa+nidKYX6oIuBYwUbT/vX4qbUDlHiZKJ/3FRNQ/tWJui44p6/stSA== + dependencies: + "@lit-labs/ssr-dom-shim" "^1.0.0" + "@mdn/browser-compat-data@5.2.29": version "5.2.29" resolved "https://registry.yarnpkg.com/@mdn/browser-compat-data/-/browser-compat-data-5.2.29.tgz#7f29e9a108aaf789600dd36e8442fe89ab41a815" integrity sha512-bEBrkTWbDAs/PB4IdRg4CtU750oBRytXHK/wC2oIDkgKZqnt76nACSooQQuHF11mK5k43f/IgFUMO5t5quRPVA== +"@motionone/animation@^10.15.1": + version "10.15.1" + resolved "https://registry.yarnpkg.com/@motionone/animation/-/animation-10.15.1.tgz#4a85596c31cbc5100ae8eb8b34c459fb0ccf6807" + integrity sha512-mZcJxLjHor+bhcPuIFErMDNyrdb2vJur8lSfMCsuCB4UyV8ILZLvK+t+pg56erv8ud9xQGK/1OGPt10agPrCyQ== + dependencies: + "@motionone/easing" "^10.15.1" + "@motionone/types" "^10.15.1" + "@motionone/utils" "^10.15.1" + tslib "^2.3.1" + +"@motionone/dom@^10.16.2": + version "10.16.2" + resolved "https://registry.yarnpkg.com/@motionone/dom/-/dom-10.16.2.tgz#0c44df8ee3d1cfc50ee11d27050b27824355a61a" + integrity sha512-bnuHdNbge1FutZXv+k7xub9oPWcF0hsu8y1HTH/qg6av58YI0VufZ3ngfC7p2xhMJMnoh0LXFma2EGTgPeCkeg== + dependencies: + "@motionone/animation" "^10.15.1" + "@motionone/generators" "^10.15.1" + "@motionone/types" "^10.15.1" + "@motionone/utils" "^10.15.1" + hey-listen "^1.0.8" + tslib "^2.3.1" + +"@motionone/easing@^10.15.1": + version "10.15.1" + resolved "https://registry.yarnpkg.com/@motionone/easing/-/easing-10.15.1.tgz#95cf3adaef34da6deebb83940d8143ede3deb693" + integrity sha512-6hIHBSV+ZVehf9dcKZLT7p5PEKHGhDwky2k8RKkmOvUoYP3S+dXsKupyZpqx5apjd9f+php4vXk4LuS+ADsrWw== + dependencies: + "@motionone/utils" "^10.15.1" + tslib "^2.3.1" + +"@motionone/generators@^10.15.1": + version "10.15.1" + resolved "https://registry.yarnpkg.com/@motionone/generators/-/generators-10.15.1.tgz#dc6abb11139d1bafe758a41c134d4c753a9b871c" + integrity sha512-67HLsvHJbw6cIbLA/o+gsm7h+6D4Sn7AUrB/GPxvujse1cGZ38F5H7DzoH7PhX+sjvtDnt2IhFYF2Zp1QTMKWQ== + dependencies: + "@motionone/types" "^10.15.1" + "@motionone/utils" "^10.15.1" + tslib "^2.3.1" + +"@motionone/svelte@^10.16.2": + version "10.16.2" + resolved "https://registry.yarnpkg.com/@motionone/svelte/-/svelte-10.16.2.tgz#0b37c3b12927814d31d24941d1ca0ff49981b444" + integrity sha512-38xsroKrfK+aHYhuQlE6eFcGy0EwrB43Q7RGjF73j/kRUTcLNu/LAaKiLLsN5lyqVzCgTBVt4TMT/ShWbTbc5Q== + dependencies: + "@motionone/dom" "^10.16.2" + tslib "^2.3.1" + +"@motionone/types@^10.15.1": + version "10.15.1" + resolved "https://registry.yarnpkg.com/@motionone/types/-/types-10.15.1.tgz#89441b54285012795cbba8612cbaa0fa420db3eb" + integrity sha512-iIUd/EgUsRZGrvW0jqdst8st7zKTzS9EsKkP+6c6n4MPZoQHwiHuVtTQLD6Kp0bsBLhNzKIBlHXponn/SDT4hA== + +"@motionone/utils@^10.15.1": + version "10.15.1" + resolved "https://registry.yarnpkg.com/@motionone/utils/-/utils-10.15.1.tgz#6b5f51bde75be88b5411e084310299050368a438" + integrity sha512-p0YncgU+iklvYr/Dq4NobTRdAPv9PveRDUXabPEeOjBLSO/1FNB2phNTZxOxpi1/GZwYpAoECEa0Wam+nsmhSw== + dependencies: + "@motionone/types" "^10.15.1" + hey-listen "^1.0.8" + tslib "^2.3.1" + +"@motionone/vue@^10.16.2": + version "10.16.2" + resolved "https://registry.yarnpkg.com/@motionone/vue/-/vue-10.16.2.tgz#faf13afc27620a2df870c71c58a04ee8de8dea65" + integrity sha512-7/dEK/nWQXOkJ70bqb2KyNfSWbNvWqKKq1C8juj+0Mg/AorgD8O5wE3naddK0G+aXuNMqRuc4jlsYHHWHtIzVw== + dependencies: + "@motionone/dom" "^10.16.2" + tslib "^2.3.1" + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -2358,21 +2439,155 @@ dependencies: "@sinonjs/commons" "^2.0.0" +"@stablelib/aead@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/aead/-/aead-1.0.1.tgz#c4b1106df9c23d1b867eb9b276d8f42d5fc4c0c3" + integrity sha512-q39ik6sxGHewqtO0nP4BuSe3db5G1fEJE8ukvngS2gLkBXyy6E7pLubhbYgnkDFv6V8cWaxcE4Xn0t6LWcJkyg== + "@stablelib/base64@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@stablelib/base64/-/base64-1.0.1.tgz#bdfc1c6d3a62d7a3b7bbc65b6cce1bb4561641be" integrity sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ== +"@stablelib/binary@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/binary/-/binary-1.0.1.tgz#c5900b94368baf00f811da5bdb1610963dfddf7f" + integrity sha512-ClJWvmL6UBM/wjkvv/7m5VP3GMr9t0osr4yVgLZsLCOz4hGN9gIAFEqnJ0TsSMAN+n840nf2cHZnA5/KFqHC7Q== + dependencies: + "@stablelib/int" "^1.0.1" + +"@stablelib/bytes@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/bytes/-/bytes-1.0.1.tgz#0f4aa7b03df3080b878c7dea927d01f42d6a20d8" + integrity sha512-Kre4Y4kdwuqL8BR2E9hV/R5sOrUj6NanZaZis0V6lX5yzqC3hBuVSDXUIBqQv/sCpmuWRiHLwqiT1pqqjuBXoQ== + +"@stablelib/chacha20poly1305@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/chacha20poly1305/-/chacha20poly1305-1.0.1.tgz#de6b18e283a9cb9b7530d8767f99cde1fec4c2ee" + integrity sha512-MmViqnqHd1ymwjOQfghRKw2R/jMIGT3wySN7cthjXCBdO+qErNPUBnRzqNpnvIwg7JBCg3LdeCZZO4de/yEhVA== + dependencies: + "@stablelib/aead" "^1.0.1" + "@stablelib/binary" "^1.0.1" + "@stablelib/chacha" "^1.0.1" + "@stablelib/constant-time" "^1.0.1" + "@stablelib/poly1305" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/chacha@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/chacha/-/chacha-1.0.1.tgz#deccfac95083e30600c3f92803a3a1a4fa761371" + integrity sha512-Pmlrswzr0pBzDofdFuVe1q7KdsHKhhU24e8gkEwnTGOmlC7PADzLVxGdn2PoNVBBabdg0l/IfLKg6sHAbTQugg== + dependencies: + "@stablelib/binary" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/constant-time@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/constant-time/-/constant-time-1.0.1.tgz#bde361465e1cf7b9753061b77e376b0ca4c77e35" + integrity sha512-tNOs3uD0vSJcK6z1fvef4Y+buN7DXhzHDPqRLSXUel1UfqMB1PWNsnnAezrKfEwTLpN0cGH2p9NNjs6IqeD0eg== + +"@stablelib/ed25519@^1.0.2": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@stablelib/ed25519/-/ed25519-1.0.3.tgz#f8fdeb6f77114897c887bb6a3138d659d3f35996" + integrity sha512-puIMWaX9QlRsbhxfDc5i+mNPMY+0TmQEskunY1rZEBPi1acBCVQAhnsk/1Hk50DGPtVsZtAWQg4NHGlVaO9Hqg== + dependencies: + "@stablelib/random" "^1.0.2" + "@stablelib/sha512" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/hash@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/hash/-/hash-1.0.1.tgz#3c944403ff2239fad8ebb9015e33e98444058bc5" + integrity sha512-eTPJc/stDkdtOcrNMZ6mcMK1e6yBbqRBaNW55XA1jU8w/7QdnCF0CmMmOD1m7VSkBR44PWrMHU2l6r8YEQHMgg== + "@stablelib/hex@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@stablelib/hex/-/hex-1.0.1.tgz#564bd46d896941c93131d1e1869eabc17cf9bab5" integrity sha512-PQOEChVBjhYGgAD+ehO2ow1gSj1slre3jW4oMD4kV8VrhYhzmtsQDWDZej3BQO8qkVezdczDvISxVSF24PuYNA== +"@stablelib/hkdf@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/hkdf/-/hkdf-1.0.1.tgz#b4efd47fd56fb43c6a13e8775a54b354f028d98d" + integrity sha512-SBEHYE16ZXlHuaW5RcGk533YlBj4grMeg5TooN80W3NpcHRtLZLLXvKyX0qcRFxf+BGDobJLnwkvgEwHIDBR6g== + dependencies: + "@stablelib/hash" "^1.0.1" + "@stablelib/hmac" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/hmac@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/hmac/-/hmac-1.0.1.tgz#3d4c1b8cf194cb05d28155f0eed8a299620a07ec" + integrity sha512-V2APD9NSnhVpV/QMYgCVMIYKiYG6LSqw1S65wxVoirhU/51ACio6D4yDVSwMzuTJXWZoVHbDdINioBwKy5kVmA== + dependencies: + "@stablelib/constant-time" "^1.0.1" + "@stablelib/hash" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/int@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/int/-/int-1.0.1.tgz#75928cc25d59d73d75ae361f02128588c15fd008" + integrity sha512-byr69X/sDtDiIjIV6m4roLVWnNNlRGzsvxw+agj8CIEazqWGOQp2dTYgQhtyVXV9wpO6WyXRQUzLV/JRNumT2w== + +"@stablelib/keyagreement@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/keyagreement/-/keyagreement-1.0.1.tgz#4612efb0a30989deb437cd352cee637ca41fc50f" + integrity sha512-VKL6xBwgJnI6l1jKrBAfn265cspaWBPAPEc62VBQrWHLqVgNRE09gQ/AnOEyKUWrrqfD+xSQ3u42gJjLDdMDQg== + dependencies: + "@stablelib/bytes" "^1.0.1" + +"@stablelib/poly1305@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/poly1305/-/poly1305-1.0.1.tgz#93bfb836c9384685d33d70080718deae4ddef1dc" + integrity sha512-1HlG3oTSuQDOhSnLwJRKeTRSAdFNVB/1djy2ZbS35rBSJ/PFqx9cf9qatinWghC2UbfOYD8AcrtbUQl8WoxabA== + dependencies: + "@stablelib/constant-time" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/random@^1.0.1", "@stablelib/random@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@stablelib/random/-/random-1.0.2.tgz#2dece393636489bf7e19c51229dd7900eddf742c" + integrity sha512-rIsE83Xpb7clHPVRlBj8qNe5L8ISQOzjghYQm/dZ7VaM2KHYwMW5adjQjrzTZCchFnNCNhkwtnOBa9HTMJCI8w== + dependencies: + "@stablelib/binary" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/sha256@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/sha256/-/sha256-1.0.1.tgz#77b6675b67f9b0ea081d2e31bda4866297a3ae4f" + integrity sha512-GIIH3e6KH+91FqGV42Kcj71Uefd/QEe7Dy42sBTeqppXV95ggCcxLTk39bEr+lZfJmp+ghsR07J++ORkRELsBQ== + dependencies: + "@stablelib/binary" "^1.0.1" + "@stablelib/hash" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/sha512@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/sha512/-/sha512-1.0.1.tgz#6da700c901c2c0ceacbd3ae122a38ac57c72145f" + integrity sha512-13gl/iawHV9zvDKciLo1fQ8Bgn2Pvf7OV6amaRVKiq3pjQ3UmEpXxWiAfV8tYjUpeZroBxtyrwtdooQT/i3hzw== + dependencies: + "@stablelib/binary" "^1.0.1" + "@stablelib/hash" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + "@stablelib/utf8@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@stablelib/utf8/-/utf8-1.0.1.tgz#fd5e7ad353b7e3cd1ce85e49099360e57693cfd1" integrity sha512-FrYD1xadah/TtAP6VJ04lDD5h9rdDj/d8wH/jMYTtHqZBv9z2btdvEU8vTxdjdkFmo1b/BH+t3R1wi/mYhCCNg== +"@stablelib/wipe@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/wipe/-/wipe-1.0.1.tgz#d21401f1d59ade56a62e139462a97f104ed19a36" + integrity sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg== + +"@stablelib/x25519@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@stablelib/x25519/-/x25519-1.0.3.tgz#13c8174f774ea9f3e5e42213cbf9fc68a3c7b7fd" + integrity sha512-KnTbKmUhPhHavzobclVJQG5kuivH+qDLpe84iRqX3CLrKp881cF160JvXJ+hjn1aMyCwYOKeIZefIH/P5cJoRw== + dependencies: + "@stablelib/keyagreement" "^1.0.1" + "@stablelib/random" "^1.0.2" + "@stablelib/wipe" "^1.0.1" + "@szmarczak/http-timer@^5.0.1": version "5.0.1" resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-5.0.1.tgz#c7c1bf1141cdd4751b0399c8fc7b8b664cd5be3a" @@ -2756,7 +2971,7 @@ resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.2.tgz#6286b4c7228d58ab7866d19716f3696e03a09397" integrity sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw== -"@types/trusted-types@*": +"@types/trusted-types@*", "@types/trusted-types@^2.0.2": version "2.0.3" resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.3.tgz#a136f83b0758698df454e328759dbd3d44555311" integrity sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g== @@ -2896,6 +3111,243 @@ "@typescript-eslint/types" "5.54.0" eslint-visitor-keys "^3.3.0" +"@walletconnect/core@2.8.0": + version "2.8.0" + resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.8.0.tgz#f694e1562413c4eb700f6b3a83fa7964342100c0" + integrity sha512-pl7x4sq1nuU0ixA9wF2ecjDecUzIauKr7ZwC29rs9qTcmDpxgJbbOdZwaSl+dJlf1bHC87adVLf5KAkwwo9PzQ== + dependencies: + "@walletconnect/heartbeat" "1.2.1" + "@walletconnect/jsonrpc-provider" "1.0.13" + "@walletconnect/jsonrpc-types" "1.0.3" + "@walletconnect/jsonrpc-utils" "1.0.8" + "@walletconnect/jsonrpc-ws-connection" "^1.0.11" + "@walletconnect/keyvaluestorage" "^1.0.2" + "@walletconnect/logger" "^2.0.1" + "@walletconnect/relay-api" "^1.0.9" + "@walletconnect/relay-auth" "^1.0.4" + "@walletconnect/safe-json" "^1.0.2" + "@walletconnect/time" "^1.0.2" + "@walletconnect/types" "2.8.0" + "@walletconnect/utils" "2.8.0" + events "^3.3.0" + lodash.isequal "4.5.0" + uint8arrays "^3.1.0" + +"@walletconnect/environment@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@walletconnect/environment/-/environment-1.0.1.tgz#1d7f82f0009ab821a2ba5ad5e5a7b8ae3b214cd7" + integrity sha512-T426LLZtHj8e8rYnKfzsw1aG6+M0BT1ZxayMdv/p8yM0MU+eJDISqNY3/bccxRr4LrF9csq02Rhqt08Ibl0VRg== + dependencies: + tslib "1.14.1" + +"@walletconnect/events@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@walletconnect/events/-/events-1.0.1.tgz#2b5f9c7202019e229d7ccae1369a9e86bda7816c" + integrity sha512-NPTqaoi0oPBVNuLv7qPaJazmGHs5JGyO8eEAk5VGKmJzDR7AHzD4k6ilox5kxk1iwiOnFopBOOMLs86Oa76HpQ== + dependencies: + keyvaluestorage-interface "^1.0.0" + tslib "1.14.1" + +"@walletconnect/heartbeat@1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@walletconnect/heartbeat/-/heartbeat-1.2.1.tgz#afaa3a53232ae182d7c9cff41c1084472d8f32e9" + integrity sha512-yVzws616xsDLJxuG/28FqtZ5rzrTA4gUjdEMTbWB5Y8V1XHRmqq4efAxCw5ie7WjbXFSUyBHaWlMR+2/CpQC5Q== + dependencies: + "@walletconnect/events" "^1.0.1" + "@walletconnect/time" "^1.0.2" + tslib "1.14.1" + +"@walletconnect/jsonrpc-provider@1.0.13": + version "1.0.13" + resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-provider/-/jsonrpc-provider-1.0.13.tgz#9a74da648d015e1fffc745f0c7d629457f53648b" + integrity sha512-K73EpThqHnSR26gOyNEL+acEex3P7VWZe6KE12ZwKzAt2H4e5gldZHbjsu2QR9cLeJ8AXuO7kEMOIcRv1QEc7g== + dependencies: + "@walletconnect/jsonrpc-utils" "^1.0.8" + "@walletconnect/safe-json" "^1.0.2" + tslib "1.14.1" + +"@walletconnect/jsonrpc-types@1.0.3", "@walletconnect/jsonrpc-types@^1.0.2", "@walletconnect/jsonrpc-types@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-types/-/jsonrpc-types-1.0.3.tgz#65e3b77046f1a7fa8347ae02bc1b841abe6f290c" + integrity sha512-iIQ8hboBl3o5ufmJ8cuduGad0CQm3ZlsHtujv9Eu16xq89q+BG7Nh5VLxxUgmtpnrePgFkTwXirCTkwJH1v+Yw== + dependencies: + keyvaluestorage-interface "^1.0.0" + tslib "1.14.1" + +"@walletconnect/jsonrpc-utils@1.0.8", "@walletconnect/jsonrpc-utils@^1.0.6", "@walletconnect/jsonrpc-utils@^1.0.8": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-utils/-/jsonrpc-utils-1.0.8.tgz#82d0cc6a5d6ff0ecc277cb35f71402c91ad48d72" + integrity sha512-vdeb03bD8VzJUL6ZtzRYsFMq1eZQcM3EAzT0a3st59dyLfJ0wq+tKMpmGH7HlB7waD858UWgfIcudbPFsbzVdw== + dependencies: + "@walletconnect/environment" "^1.0.1" + "@walletconnect/jsonrpc-types" "^1.0.3" + tslib "1.14.1" + +"@walletconnect/jsonrpc-ws-connection@^1.0.11": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-ws-connection/-/jsonrpc-ws-connection-1.0.11.tgz#1ce59d86f273d576ca73385961303ebd44dd923f" + integrity sha512-TiFJ6saasKXD+PwGkm5ZGSw0837nc6EeFmurSPgIT/NofnOV4Tv7CVJqGQN0rQYoJUSYu21cwHNYaFkzNpUN+w== + dependencies: + "@walletconnect/jsonrpc-utils" "^1.0.6" + "@walletconnect/safe-json" "^1.0.2" + events "^3.3.0" + tslib "1.14.1" + ws "^7.5.1" + +"@walletconnect/keyvaluestorage@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@walletconnect/keyvaluestorage/-/keyvaluestorage-1.0.2.tgz#92f5ca0f54c1a88a093778842ce0c874d86369c8" + integrity sha512-U/nNG+VLWoPFdwwKx0oliT4ziKQCEoQ27L5Hhw8YOFGA2Po9A9pULUYNWhDgHkrb0gYDNt//X7wABcEWWBd3FQ== + dependencies: + safe-json-utils "^1.1.1" + tslib "1.14.1" + +"@walletconnect/logger@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@walletconnect/logger/-/logger-2.0.1.tgz#7f489b96e9a1ff6bf3e58f0fbd6d69718bf844a8" + integrity sha512-SsTKdsgWm+oDTBeNE/zHxxr5eJfZmE9/5yp/Ku+zJtcTAjELb3DXueWkDXmE9h8uHIbJzIb5wj5lPdzyrjT6hQ== + dependencies: + pino "7.11.0" + tslib "1.14.1" + +"@walletconnect/modal@2.4.5": + version "2.4.5" + resolved "https://registry.yarnpkg.com/@walletconnect/modal/-/modal-2.4.5.tgz#bfdf6110a7f09c709fc5af19e576a28e6bba1d6e" + integrity sha512-t+sII7GIMsKDr0wvSJxzlpcbxw35WthuVpAqPlzMS7roSPmQZT18KO8Iu4ccLkNZF+ioptRTpBUKtk2eeuaqlQ== + dependencies: + "@web3modal/core" "2.4.5" + "@web3modal/ui" "2.4.5" + +"@walletconnect/relay-api@^1.0.9": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@walletconnect/relay-api/-/relay-api-1.0.9.tgz#f8c2c3993dddaa9f33ed42197fc9bfebd790ecaf" + integrity sha512-Q3+rylJOqRkO1D9Su0DPE3mmznbAalYapJ9qmzDgK28mYF9alcP3UwG/og5V7l7CFOqzCLi7B8BvcBUrpDj0Rg== + dependencies: + "@walletconnect/jsonrpc-types" "^1.0.2" + tslib "1.14.1" + +"@walletconnect/relay-auth@^1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@walletconnect/relay-auth/-/relay-auth-1.0.4.tgz#0b5c55c9aa3b0ef61f526ce679f3ff8a5c4c2c7c" + integrity sha512-kKJcS6+WxYq5kshpPaxGHdwf5y98ZwbfuS4EE/NkQzqrDFm5Cj+dP8LofzWvjrrLkZq7Afy7WrQMXdLy8Sx7HQ== + dependencies: + "@stablelib/ed25519" "^1.0.2" + "@stablelib/random" "^1.0.1" + "@walletconnect/safe-json" "^1.0.1" + "@walletconnect/time" "^1.0.2" + tslib "1.14.1" + uint8arrays "^3.0.0" + +"@walletconnect/safe-json@^1.0.1", "@walletconnect/safe-json@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@walletconnect/safe-json/-/safe-json-1.0.2.tgz#7237e5ca48046e4476154e503c6d3c914126fa77" + integrity sha512-Ogb7I27kZ3LPC3ibn8ldyUr5544t3/STow9+lzz7Sfo808YD7SBWk7SAsdBFlYgP2zDRy2hS3sKRcuSRM0OTmA== + dependencies: + tslib "1.14.1" + +"@walletconnect/sign-client@2.8.0": + version "2.8.0" + resolved "https://registry.yarnpkg.com/@walletconnect/sign-client/-/sign-client-2.8.0.tgz#735dc8bf120242584fb2ff22c6a3d672c1fae1a1" + integrity sha512-+l9qwvVeUGk0fBQsgx6yb6hdGYt8uQ3a9jR9GgsJvm8FjFh1oUzTKqFnG7XdhCBnzFnbSoLr41Xe8PbN8qoUSw== + dependencies: + "@walletconnect/core" "2.8.0" + "@walletconnect/events" "^1.0.1" + "@walletconnect/heartbeat" "1.2.1" + "@walletconnect/jsonrpc-utils" "1.0.8" + "@walletconnect/logger" "^2.0.1" + "@walletconnect/time" "^1.0.2" + "@walletconnect/types" "2.8.0" + "@walletconnect/utils" "2.8.0" + events "^3.3.0" + +"@walletconnect/time@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@walletconnect/time/-/time-1.0.2.tgz#6c5888b835750ecb4299d28eecc5e72c6d336523" + integrity sha512-uzdd9woDcJ1AaBZRhqy5rNC9laqWGErfc4dxA9a87mPdKOgWMD85mcFo9dIYIts/Jwocfwn07EC6EzclKubk/g== + dependencies: + tslib "1.14.1" + +"@walletconnect/types@2.8.0", "@walletconnect/types@^2.8.0": + version "2.8.0" + resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.8.0.tgz#f8a5f09ee2b31abed231966e7e1eebd22be058a2" + integrity sha512-FMeGK3lGXFDwcs5duoN74xL1aLrkgYqnavWE0DnFPt2i1QmSUITU9c8f88EDh8uPXANd2WIYOItm0DVCNxLGGA== + dependencies: + "@walletconnect/events" "^1.0.1" + "@walletconnect/heartbeat" "1.2.1" + "@walletconnect/jsonrpc-types" "1.0.3" + "@walletconnect/keyvaluestorage" "^1.0.2" + "@walletconnect/logger" "^2.0.1" + events "^3.3.0" + +"@walletconnect/utils@2.8.0": + version "2.8.0" + resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.8.0.tgz#c219e78fd2c35062cf3e37f84961afde8da9b9a1" + integrity sha512-Q8OwMtUevIn1+64LXyTMLlhH58k3UOAjU5b3smYZ7CEEmwEGpOTfTDAWrB3v+ZDIhjyqP94+8fuvKIbcVLKLWA== + dependencies: + "@stablelib/chacha20poly1305" "1.0.1" + "@stablelib/hkdf" "1.0.1" + "@stablelib/random" "^1.0.2" + "@stablelib/sha256" "1.0.1" + "@stablelib/x25519" "^1.0.3" + "@walletconnect/relay-api" "^1.0.9" + "@walletconnect/safe-json" "^1.0.2" + "@walletconnect/time" "^1.0.2" + "@walletconnect/types" "2.8.0" + "@walletconnect/window-getters" "^1.0.1" + "@walletconnect/window-metadata" "^1.0.1" + detect-browser "5.3.0" + query-string "7.1.3" + uint8arrays "^3.1.0" + +"@walletconnect/window-getters@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@walletconnect/window-getters/-/window-getters-1.0.1.tgz#f36d1c72558a7f6b87ecc4451fc8bd44f63cbbdc" + integrity sha512-vHp+HqzGxORPAN8gY03qnbTMnhqIwjeRJNOMOAzePRg4xVEEE2WvYsI9G2NMjOknA8hnuYbU3/hwLcKbjhc8+Q== + dependencies: + tslib "1.14.1" + +"@walletconnect/window-metadata@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@walletconnect/window-metadata/-/window-metadata-1.0.1.tgz#2124f75447b7e989e4e4e1581d55d25bc75f7be5" + integrity sha512-9koTqyGrM2cqFRW517BPY/iEtUDx2r1+Pwwu5m7sJ7ka79wi3EyqhqcICk/yDmv6jAS1rjKgTKXlEhanYjijcA== + dependencies: + "@walletconnect/window-getters" "^1.0.1" + tslib "1.14.1" + +"@web3modal/core@2.4.5": + version "2.4.5" + resolved "https://registry.yarnpkg.com/@web3modal/core/-/core-2.4.5.tgz#506161e37b8431fc8d605aed7a73d93e3f8ee7b4" + integrity sha512-iulOIW2irVaq+xWTzzM2xbRI4TCR0yTnV2Yz+ifIFl+r3OF3ZOC1jsy4jJnKL7/6e7p4NmmKJk0/w951KzCF5g== + dependencies: + buffer "6.0.3" + valtio "1.10.5" + +"@web3modal/sign-html@2.4.5": + version "2.4.5" + resolved "https://registry.yarnpkg.com/@web3modal/sign-html/-/sign-html-2.4.5.tgz#185334fa04ea0f8132d74be4a035b4739d06821c" + integrity sha512-16ctFYbGJhf7i6kntJupstr8uLdURku6e+fF3nOXlPpNKYKSdWNuY/dMLz4QvS7jck/Fqky6ksu9ul/uK3TOGg== + dependencies: + "@walletconnect/modal" "2.4.5" + "@walletconnect/sign-client" "2.8.0" + +"@web3modal/sign-react@^2.4.5": + version "2.4.5" + resolved "https://registry.yarnpkg.com/@web3modal/sign-react/-/sign-react-2.4.5.tgz#077a2f8728a43b10d0bc3db65102c830adac480c" + integrity sha512-/rOV8I7QvHjvY2D+mAkrBDwRt14HghSiVFstViYxmc3uKxVNABJZgQuE1HvCravd0HD8E4dLpooqkDoOWHadFA== + dependencies: + "@web3modal/sign-html" "2.4.5" + mitt "3.0.0" + +"@web3modal/ui@2.4.5": + version "2.4.5" + resolved "https://registry.yarnpkg.com/@web3modal/ui/-/ui-2.4.5.tgz#bd388faeafd9abf72abffc85613b3d7038adcf14" + integrity sha512-LvGjGL7vyQrUrrQOtFAK0SyxJs1yozOnJjP7s7gWXJa7wFWCE+kVjrhE8VrKbwx7nHe78IFA1rs7V1ncCirqVQ== + dependencies: + "@web3modal/core" "2.4.5" + lit "2.7.5" + motion "10.16.2" + qrcode "1.5.3" + "@webassemblyjs/ast@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" @@ -3113,6 +3565,11 @@ acorn@^8.1.0, acorn@^8.4.1, acorn@^8.5.0, acorn@^8.7.1, acorn@^8.8.0, acorn@^8.8 resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== +add@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/add/-/add-2.0.6.tgz#248f0a9f6e5a528ef2295dbeec30532130ae2235" + integrity sha512-j5QzrmsokwWWp6kUcJQySpbG+xfOBqqKnup3OIk1pz+kB/80SLorZ9V8zHFLO92Lcd+hbvq8bT+zOGoPkmBV0Q== + addons-linter@5.27.0: version "5.27.0" resolved "https://registry.yarnpkg.com/addons-linter/-/addons-linter-5.27.0.tgz#23ecef4a274c41a96a89ad67cd038c9ab01e42e0" @@ -3744,7 +4201,7 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== -buffer@^6.0.3: +buffer@6.0.3, buffer@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== @@ -4653,6 +5110,11 @@ decode-named-character-reference@^1.0.0: dependencies: character-entities "^2.0.0" +decode-uri-component@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" + integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== + decompress-response@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" @@ -4765,6 +5227,11 @@ destroy@1.2.0: resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== +detect-browser@5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/detect-browser/-/detect-browser-5.3.0.tgz#9705ef2bddf46072d0f7265a1fe300e36fe7ceca" + integrity sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w== + detect-newline@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" @@ -4944,6 +5411,16 @@ duplexer2@~0.1.0: dependencies: readable-stream "^2.0.2" +duplexify@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.2.tgz#18b4f8d28289132fa0b9573c898d9f903f81c7b0" + integrity sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw== + dependencies: + end-of-stream "^1.4.1" + inherits "^2.0.3" + readable-stream "^3.1.1" + stream-shift "^1.0.0" + eastasianwidth@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" @@ -5011,7 +5488,7 @@ encoding@^0.1.13: dependencies: iconv-lite "^0.6.2" -end-of-stream@^1.1.0, end-of-stream@~1.4.1: +end-of-stream@^1.1.0, end-of-stream@^1.4.1, end-of-stream@~1.4.1: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== @@ -5484,6 +5961,11 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== +fast-redact@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.2.0.tgz#b1e2d39bc731376d28bde844454fa23e26919987" + integrity sha512-zaTadChr+NekyzallAMXATXLOR8MNx3zqpZ0MUF2aGf4EathnG0f32VLODNlY8IuGY3HoRO2L6/6fSzNsLaHIw== + fast-redact@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.1.2.tgz#d58e69e9084ce9fa4c1a6fa98a3e1ecf5d7839aa" @@ -5564,6 +6046,11 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" +filter-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b" + integrity sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ== + finalhandler@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" @@ -6104,6 +6591,11 @@ he@^1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== +hey-listen@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/hey-listen/-/hey-listen-1.0.8.tgz#8e59561ff724908de1aa924ed6ecc84a56a9aa68" + integrity sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q== + hi-base32@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/hi-base32/-/hi-base32-0.5.1.tgz#1279f2ddae2673219ea5870c2121d2a33132857e" @@ -7453,6 +7945,11 @@ keyv@^4.5.2: dependencies: json-buffer "3.0.1" +keyvaluestorage-interface@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/keyvaluestorage-interface/-/keyvaluestorage-interface-1.0.0.tgz#13ebdf71f5284ad54be94bd1ad9ed79adad515ff" + integrity sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g== + kind-of@^6.0.2, kind-of@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" @@ -7687,6 +8184,31 @@ listr2@^5.0.5: through "^2.3.8" wrap-ansi "^7.0.0" +lit-element@^3.3.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/lit-element/-/lit-element-3.3.2.tgz#9913bf220b85065f0e5f1bb8878cc44f36b50cfa" + integrity sha512-xXAeVWKGr4/njq0rGC9dethMnYCq5hpKYrgQZYTzawt9YQhMiXfD+T1RgrdY3NamOxwq2aXlb0vOI6e29CKgVQ== + dependencies: + "@lit-labs/ssr-dom-shim" "^1.1.0" + "@lit/reactive-element" "^1.3.0" + lit-html "^2.7.0" + +lit-html@^2.7.0: + version "2.7.4" + resolved "https://registry.yarnpkg.com/lit-html/-/lit-html-2.7.4.tgz#6d75001977c206683685b9d76594a516afda2954" + integrity sha512-/Jw+FBpeEN+z8X6PJva5n7+0MzCVAH2yypN99qHYYkq8bI+j7I39GH+68Z/MZD6rGKDK9RpzBw7CocfmHfq6+g== + dependencies: + "@types/trusted-types" "^2.0.2" + +lit@2.7.5: + version "2.7.5" + resolved "https://registry.yarnpkg.com/lit/-/lit-2.7.5.tgz#60bc82990cfad169d42cd786999356dcf79b035f" + integrity sha512-i/cH7Ye6nBDUASMnfwcictBnsTN91+aBjXoTHF2xARghXScKxpD4F4WYI+VLXg9lqbMinDfvoI7VnZXjyHgdfQ== + dependencies: + "@lit/reactive-element" "^1.6.0" + lit-element "^3.3.0" + lit-html "^2.7.0" + load-json-file@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" @@ -7760,6 +8282,11 @@ lodash.escaperegexp@^4.1.2: resolved "https://registry.yarnpkg.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347" integrity sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw== +lodash.isequal@4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== + lodash.isfunction@^3.0.9: version "3.0.9" resolved "https://registry.yarnpkg.com/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz#06de25df4db327ac931981d1bdb067e5af68d051" @@ -8413,6 +8940,11 @@ minizlib@^2.1.1, minizlib@^2.1.2: minipass "^3.0.0" yallist "^4.0.0" +mitt@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mitt/-/mitt-3.0.0.tgz#69ef9bd5c80ff6f57473e8d89326d01c414be0bd" + integrity sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ== + mkdirp-infer-owner@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/mkdirp-infer-owner/-/mkdirp-infer-owner-2.0.0.tgz#55d3b368e7d89065c38f32fd38e638f0ab61d316" @@ -8454,6 +8986,18 @@ moment@^2.19.3: resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== +motion@10.16.2: + version "10.16.2" + resolved "https://registry.yarnpkg.com/motion/-/motion-10.16.2.tgz#7dc173c6ad62210a7e9916caeeaf22c51e598d21" + integrity sha512-p+PurYqfUdcJZvtnmAqu5fJgV2kR0uLFQuBKtLeFVTrYEVllI99tiOTSefVNYuip9ELTEkepIIDftNdze76NAQ== + dependencies: + "@motionone/animation" "^10.15.1" + "@motionone/dom" "^10.16.2" + "@motionone/svelte" "^10.16.2" + "@motionone/types" "^10.15.1" + "@motionone/utils" "^10.15.1" + "@motionone/vue" "^10.16.2" + mri@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" @@ -8482,6 +9026,11 @@ multicast-dns@^7.2.5: dns-packet "^5.2.2" thunky "^1.0.2" +multiformats@^9.4.2: + version "9.9.0" + resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-9.9.0.tgz#c68354e7d21037a8f1f8833c8ccd68618e8f1d37" + integrity sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg== + multimatch@6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-6.0.0.tgz#c72a9bddbc94baa4727efd613b5d22a1fe4d6ee3" @@ -8934,6 +9483,11 @@ obuf@^1.0.0, obuf@^1.1.2: resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== +on-exit-leak-free@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-0.2.0.tgz#b39c9e3bf7690d890f4861558b0d7b90a442d209" + integrity sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg== + on-exit-leak-free@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz#5c703c968f7e7f851885f6459bf8a8a57edc9cc4" @@ -9358,6 +9912,14 @@ pify@^3.0.0: resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" integrity sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg== +pino-abstract-transport@v0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-0.5.0.tgz#4b54348d8f73713bfd14e3dc44228739aa13d9c0" + integrity sha512-+KAgmVeqXYbTtU2FScx1XS3kNyfZ5TrXY07V96QnUSFqo2gAqlvmaxH67Lj7SWazqsMabf+58ctdTcBgnOLUOQ== + dependencies: + duplexify "^4.1.2" + split2 "^4.0.0" + pino-abstract-transport@v1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.0.0.tgz#cc0d6955fffcadb91b7b49ef220a6cc111d48bb3" @@ -9366,11 +9928,33 @@ pino-abstract-transport@v1.0.0: readable-stream "^4.0.0" split2 "^4.0.0" +pino-std-serializers@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-4.0.0.tgz#1791ccd2539c091ae49ce9993205e2cd5dbba1e2" + integrity sha512-cK0pekc1Kjy5w9V2/n+8MkZwusa6EyyxfeQCB799CQRhRt/CqYKiWs5adeu8Shve2ZNffvfC/7J64A2PJo1W/Q== + pino-std-serializers@^6.0.0: version "6.1.0" resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-6.1.0.tgz#307490fd426eefc95e06067e85d8558603e8e844" integrity sha512-KO0m2f1HkrPe9S0ldjx7za9BJjeHqBku5Ch8JyxETxT8dEFGz1PwgrHaOQupVYitpzbFSYm7nnljxD8dik2c+g== +pino@7.11.0: + version "7.11.0" + resolved "https://registry.yarnpkg.com/pino/-/pino-7.11.0.tgz#0f0ea5c4683dc91388081d44bff10c83125066f6" + integrity sha512-dMACeu63HtRLmCG8VKdy4cShCPKaYDR4youZqoSWLxl5Gu99HUw8bw75thbPv9Nip+H+QYX8o3ZJbTdVZZ2TVg== + dependencies: + atomic-sleep "^1.0.0" + fast-redact "^3.0.0" + on-exit-leak-free "^0.2.0" + pino-abstract-transport v0.5.0 + pino-std-serializers "^4.0.0" + process-warning "^1.0.0" + quick-format-unescaped "^4.0.3" + real-require "^0.1.0" + safe-stable-stringify "^2.1.0" + sonic-boom "^2.2.1" + thread-stream "^0.15.1" + pino@8.8.0: version "8.8.0" resolved "https://registry.yarnpkg.com/pino/-/pino-8.8.0.tgz#1f0d6695a224aa06afc7ad60f2ccc4772d3b9233" @@ -9477,6 +10061,11 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== +process-warning@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-1.0.0.tgz#980a0b25dc38cd6034181be4b7726d89066b4616" + integrity sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q== + process-warning@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-2.1.0.tgz#1e60e3bfe8183033bbc1e702c2da74f099422d1a" @@ -9559,6 +10148,11 @@ proxy-addr@~2.0.7: forwarded "0.2.0" ipaddr.js "1.9.1" +proxy-compare@2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/proxy-compare/-/proxy-compare-2.5.1.tgz#17818e33d1653fbac8c2ec31406bce8a2966f600" + integrity sha512-oyfc0Tx87Cpwva5ZXezSp5V9vht1c7dZBhvuV/y3ctkgMVUmiAGDVeeB0dKhGSyT0v1ZTEQYpe/RXlBVBNuCLA== + psl@^1.1.28, psl@^1.1.33: version "1.9.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" @@ -9594,6 +10188,16 @@ qrcode-terminal@^0.12.0: resolved "https://registry.yarnpkg.com/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz#bb5b699ef7f9f0505092a3748be4464fe71b5819" integrity sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ== +qrcode@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.5.3.tgz#03afa80912c0dccf12bc93f615a535aad1066170" + integrity sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg== + dependencies: + dijkstrajs "^1.0.1" + encode-utf8 "^1.0.3" + pngjs "^5.0.0" + yargs "^15.3.1" + qrcode@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.5.1.tgz#0103f97317409f7bc91772ef30793a54cd59f0cb" @@ -9616,6 +10220,16 @@ qs@~6.5.2: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== +query-string@7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.1.3.tgz#a1cf90e994abb113a325804a972d98276fe02328" + integrity sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg== + dependencies: + decode-uri-component "^0.2.2" + filter-obj "^1.1.0" + split-on-first "^1.0.0" + strict-uri-encode "^2.0.0" + querystringify@^2.1.1: version "2.2.0" resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" @@ -9917,7 +10531,7 @@ readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.0.6: +readable-stream@^3.0.6, readable-stream@^3.1.1: version "3.6.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== @@ -9953,6 +10567,11 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +real-require@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.1.0.tgz#736ac214caa20632847b7ca8c1056a0767df9381" + integrity sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg== + real-require@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78" @@ -10238,6 +10857,16 @@ safe-json-stringify@~1: resolved "https://registry.yarnpkg.com/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz#356e44bc98f1f93ce45df14bcd7c01cda86e0afd" integrity sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg== +safe-json-utils@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/safe-json-utils/-/safe-json-utils-1.1.1.tgz#0e883874467d95ab914c3f511096b89bfb3e63b1" + integrity sha512-SAJWGKDs50tAbiDXLf89PDwt9XYkWyANFWVzn4dTXl5QyI8t2o/bW5/OJl3lvc2WVU4MEpTo9Yz5NVFNsp+OJQ== + +safe-stable-stringify@^2.1.0: + version "2.4.3" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886" + integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g== + safe-stable-stringify@^2.3.1: version "2.4.2" resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.2.tgz#ec7b037768098bf65310d1d64370de0dc02353aa" @@ -10593,6 +11222,13 @@ socks@^2.6.2: ip "^2.0.0" smart-buffer "^4.2.0" +sonic-boom@^2.2.1: + version "2.8.0" + resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-2.8.0.tgz#c1def62a77425090e6ad7516aad8eb402e047611" + integrity sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg== + dependencies: + atomic-sleep "^1.0.0" + sonic-boom@^3.1.0: version "3.2.1" resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-3.2.1.tgz#972ceab831b5840a08a002fa95a672008bda1c38" @@ -10703,6 +11339,11 @@ spdy@^4.0.2: select-hose "^2.0.0" spdy-transport "^3.0.0" +split-on-first@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f" + integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw== + split2@^3.0.0: version "3.2.2" resolved "https://registry.yarnpkg.com/split2/-/split2-3.2.2.tgz#bf2cf2a37d838312c249c89206fd7a17dd12365f" @@ -10781,6 +11422,11 @@ stream-combiner2@~1.1.1: duplexer2 "~0.1.0" readable-stream "^2.0.2" +stream-shift@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" + integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== + stream-to-array@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/stream-to-array/-/stream-to-array-2.3.0.tgz#bbf6b39f5f43ec30bc71babcb37557acecf34353" @@ -10797,6 +11443,11 @@ stream-to-promise@3.0.0: end-of-stream "~1.4.1" stream-to-array "~2.3.0" +strict-uri-encode@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" + integrity sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ== + string-argv@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" @@ -11077,6 +11728,13 @@ thenify-all@^1.0.0: dependencies: any-promise "^1.0.0" +thread-stream@^0.15.1: + version "0.15.2" + resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-0.15.2.tgz#fb95ad87d2f1e28f07116eb23d85aba3bc0425f4" + integrity sha512-UkEhKIg2pD+fjkHQKyJO3yoIvAP3N6RlNFt2dUhcS1FGvCD1cQa1M/PGknCLFIyZdtJOWQjejp7bdNqmN7zwdA== + dependencies: + real-require "^0.1.0" + thread-stream@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-2.3.0.tgz#4fc07fb39eff32ae7bad803cb7dd9598349fed33" @@ -11271,21 +11929,26 @@ tsconfig-paths@^3.14.2: minimist "^1.2.6" strip-bom "^3.0.0" +tslib@1.14.1, tslib@^1.8.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + tslib@2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== -tslib@^1.8.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== +tslib@^2.3.1: + version "2.5.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.3.tgz#24944ba2d990940e6e982c4bea147aba80209913" + integrity sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w== + tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" @@ -11399,6 +12062,13 @@ uglify-js@^3.1.4: resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.4.tgz#61678cf5fa3f5b7eb789bb345df29afb8257c22c" integrity sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g== +uint8arrays@^3.0.0, uint8arrays@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-3.1.1.tgz#2d8762acce159ccd9936057572dade9459f65ae0" + integrity sha512-+QJa8QRnbdXVpHYjLoTpJIdCTiw9Ir62nocClWuXIq2JIh4Uta0cQsTSpFL678p2CN8B+XSApwcU+pQEqVpKWg== + dependencies: + multiformats "^9.4.2" + unified@^10.0.0: version "10.1.2" resolved "https://registry.yarnpkg.com/unified/-/unified-10.1.2.tgz#b1d64e55dafe1f0b98bb6c719881103ecf6c86df" @@ -11576,7 +12246,7 @@ use-sidecar@^1.1.2: detect-node-es "^1.1.0" tslib "^2.0.0" -use-sync-external-store@^1.0.0: +use-sync-external-store@1.2.0, use-sync-external-store@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== @@ -11650,6 +12320,14 @@ validate-npm-package-name@^4.0.0: dependencies: builtins "^5.0.0" +valtio@1.10.5: + version "1.10.5" + resolved "https://registry.yarnpkg.com/valtio/-/valtio-1.10.5.tgz#7852125e3b774b522827d96bd9c76d285c518678" + integrity sha512-jTp0k63VXf4r5hPoaC6a6LCG4POkVSh629WLi1+d5PlajLsbynTMd7qAgEiOSPxzoX5iNvbN7iZ/k/g29wrNiQ== + dependencies: + proxy-compare "2.5.1" + use-sync-external-store "1.2.0" + vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" @@ -12056,6 +12734,11 @@ ws@8.12.0: resolved "https://registry.yarnpkg.com/ws/-/ws-8.12.0.tgz#485074cc392689da78e1828a9ff23585e06cddd8" integrity sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig== +ws@^7.5.1: + version "7.5.9" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" + integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== + ws@^8.11.0: version "8.12.1" resolved "https://registry.yarnpkg.com/ws/-/ws-8.12.1.tgz#c51e583d79140b5e42e39be48c934131942d4a8f" @@ -12190,6 +12873,11 @@ yargs@^17.0.0, yargs@^17.3.1, yargs@^17.5.1: y18n "^5.0.5" yargs-parser "^21.1.1" +yarn@^1.22.19: + version "1.22.19" + resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.22.19.tgz#4ba7fc5c6e704fce2066ecbfb0b0d8976fe62447" + integrity sha512-/0V5q0WbslqnwP91tirOvldvYISzaqhClxzyUKXYxs07yUILIs5jx/k6CFe8bvKSkds5w+eiOqta39Wk3WxdcQ== + yauzl@2.10.0: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" From ba9e037a4e7542fd84addb592e298ec4b8e65812 Mon Sep 17 00:00:00 2001 From: Kieran O'Neill Date: Wed, 14 Jun 2023 14:21:05 +0100 Subject: [PATCH 02/12] feat(dapp): display wallet connect modal --- dapp/App.tsx | 81 ++++++++++++++----- .../WalletConnectIcon/WalletConnectIcon.tsx | 13 +++ .../components/WalletConnectIcon/index.ts | 1 + 3 files changed, 77 insertions(+), 18 deletions(-) create mode 100644 src/extension/components/WalletConnectIcon/WalletConnectIcon.tsx create mode 100644 src/extension/components/WalletConnectIcon/index.ts diff --git a/dapp/App.tsx b/dapp/App.tsx index 5bb73a02..0076c91a 100644 --- a/dapp/App.tsx +++ b/dapp/App.tsx @@ -29,11 +29,14 @@ import { Text, Select, } from '@chakra-ui/react'; +import { SessionTypes } from '@walletconnect/types'; +import { Web3ModalSign, useConnect } from '@web3modal/sign-react'; import { nanoid } from 'nanoid'; import React, { ChangeEvent, FC, useEffect, useState } from 'react'; // Components import Fonts from '@extension/components/Fonts'; +import WalletConnectIcon from '@extension/components/WalletConnectIcon'; // Config import { networks } from '@extension/config'; @@ -59,6 +62,15 @@ import { IAccountInformation } from './types'; import { getAccountInformation } from './utils'; const App: FC = () => { + const { connect } = useConnect({ + requiredNamespaces: { + algorand: { + chains: ['algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDe'], + events: [], + methods: ['algorand_signTransaction', 'algorand_signMessage'], + }, + }, + }); const toast: CreateToastFnReturn = useToast({ duration: 3000, isClosable: true, @@ -130,6 +142,11 @@ const App: FC = () => { }); } }; + const handleWalletConnectClick = async () => { + const data: SessionTypes.Struct = await connect(); + + console.log(data); + }; useEffect(() => { if (enabledAccounts) { @@ -140,6 +157,20 @@ const App: FC = () => { return ( +
{ + {/* Enable CTAs */} - - + + + ); }; diff --git a/src/extension/components/WalletConnectBannerIcon/WalletConnectBannerIcon.tsx b/src/extension/components/WalletConnectBannerIcon/WalletConnectBannerIcon.tsx new file mode 100644 index 00000000..fb094f2c --- /dev/null +++ b/src/extension/components/WalletConnectBannerIcon/WalletConnectBannerIcon.tsx @@ -0,0 +1,66 @@ +import { Icon, IconProps } from '@chakra-ui/react'; +import React, { FC } from 'react'; + +// Hooks +import useColorModeValue from '@extension/hooks/useColorModeValue'; + +const WalletConnectBannerIcon: FC = (props: IconProps) => { + const fillColor: string = useColorModeValue('#3B99FC', '#FFFFFF'); + + return ( + + + + + + + + + + + + + + + + + ); +}; + +export default WalletConnectBannerIcon; diff --git a/src/extension/components/WalletConnectBannerIcon/index.ts b/src/extension/components/WalletConnectBannerIcon/index.ts new file mode 100644 index 00000000..68e40737 --- /dev/null +++ b/src/extension/components/WalletConnectBannerIcon/index.ts @@ -0,0 +1 @@ +export { default } from './WalletConnectBannerIcon'; diff --git a/src/extension/components/WalletConnectModal/WalletConnectModal.tsx b/src/extension/components/WalletConnectModal/WalletConnectModal.tsx new file mode 100644 index 00000000..96b83ba7 --- /dev/null +++ b/src/extension/components/WalletConnectModal/WalletConnectModal.tsx @@ -0,0 +1,386 @@ +import { + Avatar, + Checkbox, + HStack, + Modal, + ModalBody, + ModalContent, + ModalFooter, + ModalHeader, + Skeleton, + SkeletonCircle, + Spacer, + Spinner, + Text, + VStack, +} from '@chakra-ui/react'; +import { generateAccount } from 'algosdk'; +import { nanoid } from 'nanoid'; +import React, { ChangeEvent, FC, ReactNode, useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Rings } from 'react-loader-spinner'; + +// Components +import Button from '@extension/components/Button'; +import EmptyState from '@extension/components/EmptyState'; +import WalletConnectBannerIcon from '@extension/components/WalletConnectBannerIcon'; + +// Constants +import { DEFAULT_GAP } from '@extension/constants'; + +// Hooks +import useColorModeValue from '@extension/hooks/useColorModeValue'; +import useDefaultTextColor from '@extension/hooks/useDefaultTextColor'; +import usePrimaryColorScheme from '@extension/hooks/usePrimaryColorScheme'; +import useSubTextColor from '@extension/hooks/useSubTextColor'; +import useWalletConnect from '@extension/hooks/useWalletConnect'; +import useCaptureQrCode from './hooks/useCaptureQrCode'; + +// Selectors +import { + useSelectAccounts, + useSelectFetchingAccounts, + useSelectInitializingWalletConnect, + useSelectSelectedNetwork, + useSelectWalletConnectModalOpen, +} from '@extension/selectors'; + +// Services +import { AccountService } from '@extension/services'; + +// Theme +import { theme } from '@extension/theme'; + +// Types +import { + IAccount, + IAccountInformation, + IAppThunkDispatch, + INetwork, +} from '@extension/types'; + +// Utils +import { ellipseAddress } from '@extension/utils'; +import SessionRequestHeader from '@extension/components/SessionRequestHeader'; + +interface IProps { + onClose: () => void; +} + +const WalletConnectModal: FC = ({ onClose }: IProps) => { + const { t } = useTranslation(); + // selectors + const accounts: IAccount[] = useSelectAccounts(); + const fetching: boolean = useSelectFetchingAccounts(); + const initializing: boolean = useSelectInitializingWalletConnect(); + const network: INetwork | null = useSelectSelectedNetwork(); + const isOpen: boolean = useSelectWalletConnectModalOpen(); + // hooks + const { captureAction, scanning, url } = useCaptureQrCode(); + const defaultTextColor: string = useDefaultTextColor(); + const primaryColor: string = useColorModeValue( + theme.colors.primaryLight['500'], + theme.colors.primaryDark['500'] + ); + const primaryColorScheme: string = usePrimaryColorScheme(); + const subTextColor: string = useSubTextColor(); + const { + approveSessionProposalAction, + pairing, + rejectSessionProposalAction, + sessionProposal, + } = useWalletConnect(url); + // states + const [authorizedAddresses, setAuthorizedAddresses] = useState([]); + // handlers + const handleApproveClick = async () => { + if (authorizedAddresses.length > 0) { + await approveSessionProposalAction(authorizedAddresses); + + handleClose(); + } + }; + const handleCancelClick = () => handleClose(); + const handleClose = () => { + setAuthorizedAddresses([]); + onClose(); + }; + const handleOnAccountCheckChange = + (address: string) => (event: ChangeEvent) => { + // add if checked and doesn't exist + if (event.target.checked) { + if (!authorizedAddresses.find((value) => value === address)) { + setAuthorizedAddresses([...authorizedAddresses, address]); + } + + return; + } + + // remove if unchecked + setAuthorizedAddresses( + authorizedAddresses.filter((value) => value !== address) + ); + }; + const handleRejectClick = async () => { + await rejectSessionProposalAction(); + + handleClose(); + }; + // misc + const renderContent = () => { + let accountNodes: ReactNode[]; + + if (initializing || scanning) { + return ( + <> + + + + + {t( + scanning + ? 'captions.scanningForQrCode' + : 'captions.initializingWalletConnect' + )} + + + + + + + + ); + } + + if (pairing) { + return ( + <> + + + + + {t('captions.connectingToWalletConnect')} + + + + + + + + ); + } + + if (!network || fetching) { + return ( + <> + + {Array.from({ length: 3 }, () => ( + + + + + {ellipseAddress(generateAccount().addr, { + end: 10, + start: 10, + })} + + + + ))} + + + + + + ); + } + + accountNodes = accounts.reduce( + (acc, account, currentIndex) => { + const accountInformation: IAccountInformation | null = + AccountService.extractAccountInformationForNetwork(account, network); + let address: string; + + if (!accountInformation) { + return acc; + } + + address = AccountService.convertPublicKeyToAlgorandAddress( + account.publicKey + ); + + return [ + ...acc, + + + {accountInformation.name ? ( + + + {accountInformation.name} + + + {ellipseAddress(address, { + end: 10, + start: 10, + })} + + + ) : ( + + {ellipseAddress(address, { + end: 10, + start: 10, + })} + + )} + value === address) + } + onChange={handleOnAccountCheckChange(address)} + /> + , + ]; + }, + [] + ); + + return ( + <> + + + {accountNodes.length > 0 ? ( + accountNodes + ) : ( + <> + {/*empty state*/} + + ('headings.noAccountsFound')} /> + + + )} + + + + + + + + + + ); + }; + + useEffect(() => { + if (isOpen) { + captureAction(); + } + }, [isOpen]); + + return ( + + + + {sessionProposal ? ( + ('captions.enableRequest')} + description={sessionProposal.params.proposer.metadata.description} + host={sessionProposal.params.proposer.metadata.url} + iconUrl={sessionProposal.params.proposer.metadata.icons[0]} + name={sessionProposal.params.proposer.metadata.name} + network={network || undefined} + /> + ) : ( + + )} + + {renderContent()} + + + ); +}; + +export default WalletConnectModal; diff --git a/src/extension/components/WalletConnectModal/hooks/useCaptureQrCode/index.ts b/src/extension/components/WalletConnectModal/hooks/useCaptureQrCode/index.ts new file mode 100644 index 00000000..1fec1fb3 --- /dev/null +++ b/src/extension/components/WalletConnectModal/hooks/useCaptureQrCode/index.ts @@ -0,0 +1,3 @@ +export { default } from './useCaptureQrCode'; +export * from './types'; +export * from './utils'; diff --git a/src/extension/components/WalletConnectModal/hooks/useCaptureQrCode/types/IUseCaptureQrCodeState.ts b/src/extension/components/WalletConnectModal/hooks/useCaptureQrCode/types/IUseCaptureQrCodeState.ts new file mode 100644 index 00000000..72193357 --- /dev/null +++ b/src/extension/components/WalletConnectModal/hooks/useCaptureQrCode/types/IUseCaptureQrCodeState.ts @@ -0,0 +1,7 @@ +interface IUseCaptureQrCodeState { + captureAction: () => void; + scanning: boolean; + url: string | null; +} + +export default IUseCaptureQrCodeState; diff --git a/src/extension/components/WalletConnectModal/hooks/useCaptureQrCode/types/index.ts b/src/extension/components/WalletConnectModal/hooks/useCaptureQrCode/types/index.ts new file mode 100644 index 00000000..89634631 --- /dev/null +++ b/src/extension/components/WalletConnectModal/hooks/useCaptureQrCode/types/index.ts @@ -0,0 +1 @@ +export type { default as IUseCaptureQrCodeState } from './IUseCaptureQrCodeState'; diff --git a/src/extension/components/WalletConnectModal/hooks/useCaptureQrCode/useCaptureQrCode.ts b/src/extension/components/WalletConnectModal/hooks/useCaptureQrCode/useCaptureQrCode.ts new file mode 100644 index 00000000..c6ddfcdf --- /dev/null +++ b/src/extension/components/WalletConnectModal/hooks/useCaptureQrCode/useCaptureQrCode.ts @@ -0,0 +1,60 @@ +import { useState } from 'react'; + +// Selectors +import { useSelectLogger } from '@extension/selectors'; + +// Types +import { ILogger } from '@common/types'; +import { IUseCaptureQrCodeState } from './types'; + +// Utils +import { captureQrCode } from './utils'; + +export default function useCaptureQrCode(): IUseCaptureQrCodeState { + const logger: ILogger = useSelectLogger(); + const [scanning, setScanning] = useState(false); + const [url, setUrl] = useState(null); + const captureAction: () => void = () => { + let capturedUrl: string; + let intervalId: number; + + setScanning(true); + + (async () => { + try { + capturedUrl = await captureQrCode(); + + setUrl(capturedUrl); + setScanning(false); + + return; + } catch (error) { + logger.debug(error.message); + } + + // add a one second interval that attempts to capture a qr code on the screen + intervalId = window.setInterval(async () => { + if (capturedUrl) { + window.clearInterval(intervalId); + + return; + } + + try { + capturedUrl = await captureQrCode(); + + setUrl(capturedUrl); + setScanning(false); + } catch (error) { + logger.debug(error.message); + } + }, 3000); + })(); + }; + + return { + captureAction, + scanning, + url, + }; +} diff --git a/src/extension/components/WalletConnectModal/hooks/useCaptureQrCode/utils/captureQrCode.ts b/src/extension/components/WalletConnectModal/hooks/useCaptureQrCode/utils/captureQrCode.ts new file mode 100644 index 00000000..5afead21 --- /dev/null +++ b/src/extension/components/WalletConnectModal/hooks/useCaptureQrCode/utils/captureQrCode.ts @@ -0,0 +1,37 @@ +import jsQR, { QRCode } from 'jsqr'; +import browser, { Windows } from 'webextension-polyfill'; + +// Utils +import { convertDataUriToImageData } from '@extension/utils'; + +export default async function captureQrCode(): Promise { + let dataImageUrl: string; + let imageData: ImageData | null; + let result: QRCode | null; + let windows: Windows.Window[]; + let window: Windows.Window | null; + + windows = await browser.windows.getAll(); + window = windows.find((value) => value.type !== 'popup') || null; // get windows that are not popups, i.e. the extension + + if (!window) { + throw new Error('unable to find browser window'); + } + + dataImageUrl = await browser.tabs.captureVisibleTab(window.id, { + format: 'png', + }); + imageData = await convertDataUriToImageData(dataImageUrl); + + if (!imageData) { + throw new Error('unable to get image data for current window'); + } + + result = jsQR(imageData.data, imageData.width, imageData.height); + + if (!result) { + throw new Error('no qr code found'); + } + + return result.data; +} diff --git a/src/extension/components/WalletConnectModal/hooks/useCaptureQrCode/utils/index.ts b/src/extension/components/WalletConnectModal/hooks/useCaptureQrCode/utils/index.ts new file mode 100644 index 00000000..000c1f05 --- /dev/null +++ b/src/extension/components/WalletConnectModal/hooks/useCaptureQrCode/utils/index.ts @@ -0,0 +1 @@ +export { default as captureQrCode } from './captureQrCode'; diff --git a/src/extension/components/WalletConnectModal/index.ts b/src/extension/components/WalletConnectModal/index.ts new file mode 100644 index 00000000..3f509724 --- /dev/null +++ b/src/extension/components/WalletConnectModal/index.ts @@ -0,0 +1 @@ +export { default } from './WalletConnectModal'; diff --git a/src/extension/config/index.ts b/src/extension/config/index.ts index 1a250d9f..82d79d0f 100644 --- a/src/extension/config/index.ts +++ b/src/extension/config/index.ts @@ -1 +1,3 @@ export { default as networks } from './networks'; +export { default as walletConnectSupportedChains } from './walletConnectSupportedChains'; +export { default as walletConnectSupportedMethods } from './walletConnectSupportedMethods'; diff --git a/src/extension/config/walletConnectSupportedChains.ts b/src/extension/config/walletConnectSupportedChains.ts new file mode 100644 index 00000000..1eed7cc1 --- /dev/null +++ b/src/extension/config/walletConnectSupportedChains.ts @@ -0,0 +1,10 @@ +// Enums +import { WalletConnectChainsEnum } from '@extension/enums'; + +const walletConnectSupportedChains: string[] = [ + WalletConnectChainsEnum.AlgorandMainNet, + WalletConnectChainsEnum.AlgorandTestNet, + WalletConnectChainsEnum.AlgorandBetaNet, +]; + +export default walletConnectSupportedChains; diff --git a/src/extension/config/walletConnectSupportedMethods.ts b/src/extension/config/walletConnectSupportedMethods.ts new file mode 100644 index 00000000..55080de1 --- /dev/null +++ b/src/extension/config/walletConnectSupportedMethods.ts @@ -0,0 +1,6 @@ +const walletConnectSupportedMethods: string[] = [ + 'algorand_signTransaction', + 'algorand_signMessage', +]; + +export default walletConnectSupportedMethods; diff --git a/src/extension/constants/Links.ts b/src/extension/constants/Links.ts index de2495d0..21b519c9 100644 --- a/src/extension/constants/Links.ts +++ b/src/extension/constants/Links.ts @@ -1,2 +1,3 @@ export const AGORA_LABS_LINK: string = 'https://agoralabs.sh'; +export const KIBISIS_LINK: string = 'https://kibisi.is'; export const SUPPORT_MAIL_TO_LINK: string = 'mailto:support@agoralabs.sh'; diff --git a/src/extension/enums/SessionsThunkEnum.ts b/src/extension/enums/SessionsThunkEnum.ts index d5de4e58..f57c8e8e 100644 --- a/src/extension/enums/SessionsThunkEnum.ts +++ b/src/extension/enums/SessionsThunkEnum.ts @@ -1,6 +1,7 @@ enum SessionsThunkEnum { ClearSessions = 'sessions/clearSessions', FetchSessions = 'sessions/fetchSessions', + InitializeWalletConnect = 'sessions/initializeWalletConnect', RemoveAuthorizedAddress = 'sessions/removeAuthorizedAddress', RemoveSession = 'sessions/removeSession', SetSession = 'sessions/setSession', diff --git a/src/extension/enums/WalletConnectChainsEnum.ts b/src/extension/enums/WalletConnectChainsEnum.ts new file mode 100644 index 00000000..2aa6af7c --- /dev/null +++ b/src/extension/enums/WalletConnectChainsEnum.ts @@ -0,0 +1,7 @@ +enum WalletConnectChainsEnum { + AlgorandBetaNet = 'algorand:mFgazF-2uRS1tMiL9dsj01hJGySEmPN2', + AlgorandMainNet = 'algorand:wGHE2Pwdvd7S12BL5FaOP20EGYesN73k', + AlgorandTestNet = 'algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDe', +} + +export default WalletConnectChainsEnum; diff --git a/src/extension/enums/index.ts b/src/extension/enums/index.ts index 8e170d6c..1ba65f9c 100644 --- a/src/extension/enums/index.ts +++ b/src/extension/enums/index.ts @@ -9,3 +9,4 @@ export { default as SettingsThunkEnum } from './SettingsThunkEnum'; export { default as StoreNameEnum } from './StoreNameEnum'; export { default as TransactionsThunkEnum } from './TransactionsThunkEnum'; export { default as TransactionTypeEnum } from './TransactionTypeEnum'; +export { default as WalletConnectChainsEnum } from './WalletConnectChainsEnum'; diff --git a/src/extension/features/sessions/slice.ts b/src/extension/features/sessions/slice.ts index b795e0ba..07360a65 100644 --- a/src/extension/features/sessions/slice.ts +++ b/src/extension/features/sessions/slice.ts @@ -1,4 +1,5 @@ -import { createSlice, PayloadAction, Reducer } from '@reduxjs/toolkit'; +import { createSlice, Draft, PayloadAction, Reducer } from '@reduxjs/toolkit'; +import { IWeb3Wallet } from '@walletconnect/web3wallet/dist/types'; // Enums import { StoreNameEnum } from '@extension/enums'; @@ -7,6 +8,7 @@ import { StoreNameEnum } from '@extension/enums'; import { clearSessionsThunk, fetchSessionsThunk, + initializeWalletConnectThunk, removeAuthorizedAddressThunk, removeSessionThunk, setSessionThunk, @@ -46,6 +48,26 @@ const slice = createSlice({ builder.addCase(fetchSessionsThunk.rejected, (state: ISessionsState) => { state.fetching = false; }); + /** Initialize WalletConnect **/ + builder.addCase( + initializeWalletConnectThunk.fulfilled, + (state: ISessionsState, action: PayloadAction) => { + state.web3Wallet = action.payload; + state.initializingWalletConnect = false; + } + ); + builder.addCase( + initializeWalletConnectThunk.pending, + (state: ISessionsState) => { + state.initializingWalletConnect = true; + } + ); + builder.addCase( + initializeWalletConnectThunk.rejected, + (state: ISessionsState) => { + state.initializingWalletConnect = false; + } + ); /** Remove authorized address **/ builder.addCase( removeAuthorizedAddressThunk.fulfilled, @@ -107,10 +129,15 @@ const slice = createSlice({ initialState: getInitialState(), name: StoreNameEnum.Sessions, reducers: { - noop: () => { - return; + closeWalletConnectModal: (state: Draft) => { + state.walletConnectModalOpen = false; + }, + openWalletConnectModal: (state: Draft) => { + state.walletConnectModalOpen = true; }, }, }); export const reducer: Reducer = slice.reducer; +export const { closeWalletConnectModal, openWalletConnectModal } = + slice.actions; diff --git a/src/extension/features/sessions/thunks/index.ts b/src/extension/features/sessions/thunks/index.ts index d80236b6..d392123a 100644 --- a/src/extension/features/sessions/thunks/index.ts +++ b/src/extension/features/sessions/thunks/index.ts @@ -1,5 +1,6 @@ export { default as clearSessionsThunk } from './clearSessionsThunk'; export { default as fetchSessionsThunk } from './fetchSessionsThunk'; +export { default as initializeWalletConnectThunk } from './initializeWalletConnectThunk'; export { default as removeAuthorizedAddressThunk } from './removeAuthorizedAddressThunk'; export { default as removeSessionThunk } from './removeSessionThunk'; export { default as setSessionThunk } from './setSessionThunk'; diff --git a/src/extension/features/sessions/thunks/initializeWalletConnectThunk.ts b/src/extension/features/sessions/thunks/initializeWalletConnectThunk.ts new file mode 100644 index 00000000..971bab28 --- /dev/null +++ b/src/extension/features/sessions/thunks/initializeWalletConnectThunk.ts @@ -0,0 +1,46 @@ +import { AsyncThunk, createAsyncThunk } from '@reduxjs/toolkit'; +import { Core } from '@walletconnect/core'; +import { Web3Wallet } from '@walletconnect/web3wallet'; +import { IWeb3Wallet } from '@walletconnect/web3wallet/dist/types'; + +// Constants +import { KIBISIS_LINK } from '@extension/constants'; + +// Enums +import { SessionsThunkEnum } from '@extension/enums'; + +// Types +import { IMainRootState } from '@extension/types'; +import { ILogger } from '@common/types'; + +const initializeWalletConnectThunk: AsyncThunk< + IWeb3Wallet, // return + undefined, // args + Record +> = createAsyncThunk( + SessionsThunkEnum.InitializeWalletConnect, + async (_, { getState }) => { + const logger: ILogger = getState().system.logger; + const web3Wallet: IWeb3Wallet = await Web3Wallet.init({ + core: new Core({ + projectId: '86eaff455340651e0ee12c8572c2d228', + }), + metadata: { + name: __APP_TITLE__, + description: 'Demo Client as Wallet/Peer', + url: KIBISIS_LINK, + icons: [], + }, + }); + + // add event listeners + web3Wallet.on('session_delete', (event) => { + // TODO: handle session disconnected + console.log(event); + }); + + return web3Wallet; + } +); + +export default initializeWalletConnectThunk; diff --git a/src/extension/features/sessions/types/ISessionsState.ts b/src/extension/features/sessions/types/ISessionsState.ts index 528f6264..ee01acff 100644 --- a/src/extension/features/sessions/types/ISessionsState.ts +++ b/src/extension/features/sessions/types/ISessionsState.ts @@ -1,15 +1,23 @@ +import { IWeb3Wallet } from '@walletconnect/web3wallet/dist/types'; + // Types import { ISession } from '@extension/types'; /** * @property {boolean} fetching - true fetching the sessions from storage. + * @property {boolean} initializingWalletConnect - true if the Web3Wallet (WalletConnect) instance is initializing. * @property {ISession[]} items - the session items. * @property {boolean} saving - true saving the sessions from storage. + * @property {IWeb3Wallet | null} web3Wallet - an initialized instance of Web3Wallet (WalletConnect). + * @property {boolean} walletConnectModalOpen - true if the wallet connect modal is open. */ interface ISessionsState { fetching: boolean; + initializingWalletConnect: boolean; items: ISession[]; saving: boolean; + web3Wallet: IWeb3Wallet | null; + walletConnectModalOpen: boolean; } export default ISessionsState; diff --git a/src/extension/features/sessions/utils/getInitialState.ts b/src/extension/features/sessions/utils/getInitialState.ts index bda03dc8..915b2426 100644 --- a/src/extension/features/sessions/utils/getInitialState.ts +++ b/src/extension/features/sessions/utils/getInitialState.ts @@ -4,7 +4,10 @@ import { ISessionsState } from '../types'; export default function getInitialState(): ISessionsState { return { fetching: false, + initializingWalletConnect: false, items: [], saving: false, + web3Wallet: null, + walletConnectModalOpen: false, }; } diff --git a/src/extension/hooks/useWalletConnect/index.ts b/src/extension/hooks/useWalletConnect/index.ts new file mode 100644 index 00000000..54969107 --- /dev/null +++ b/src/extension/hooks/useWalletConnect/index.ts @@ -0,0 +1,3 @@ +export { default } from './useWalletConnect'; +export * from './types'; +export * from './utils'; diff --git a/src/extension/hooks/useWalletConnect/types/IUseWalletConnectState.ts b/src/extension/hooks/useWalletConnect/types/IUseWalletConnectState.ts new file mode 100644 index 00000000..3ca7d518 --- /dev/null +++ b/src/extension/hooks/useWalletConnect/types/IUseWalletConnectState.ts @@ -0,0 +1,10 @@ +import { Web3WalletTypes } from '@walletconnect/web3wallet'; + +interface IUseWalletConnectState { + approveSessionProposalAction: (addresses: string[]) => Promise; + pairing: boolean; + rejectSessionProposalAction: () => Promise; + sessionProposal: Web3WalletTypes.SessionProposal | null; +} + +export default IUseWalletConnectState; diff --git a/src/extension/hooks/useWalletConnect/types/index.ts b/src/extension/hooks/useWalletConnect/types/index.ts new file mode 100644 index 00000000..b763dd11 --- /dev/null +++ b/src/extension/hooks/useWalletConnect/types/index.ts @@ -0,0 +1 @@ +export type { default as IUseWalletConnectState } from './IUseWalletConnectState'; diff --git a/src/extension/hooks/useWalletConnect/useWalletConnect.ts b/src/extension/hooks/useWalletConnect/useWalletConnect.ts new file mode 100644 index 00000000..e69f6886 --- /dev/null +++ b/src/extension/hooks/useWalletConnect/useWalletConnect.ts @@ -0,0 +1,108 @@ +import { SessionTypes } from '@walletconnect/types'; +import { getSdkError } from '@walletconnect/utils'; +import { Web3WalletTypes } from '@walletconnect/web3wallet'; +import { IWeb3Wallet } from '@walletconnect/web3wallet/dist/types'; +import { useEffect, useState } from 'react'; + +// Selectors +import { useSelectLogger, useSelectWeb3Wallet } from '@extension/selectors'; + +// Types +import { ILogger } from '@common/types'; +import { IUseWalletConnectState } from './types'; + +// Utils +import { createSessionNamespaces } from './utils'; + +export default function useWalletConnect( + uri: string | null +): IUseWalletConnectState { + // selectors + const logger: ILogger = useSelectLogger(); + const web3Wallet: IWeb3Wallet | null = useSelectWeb3Wallet(); + // states + const [pairing, setPairing] = useState(false); + const [sessionProposal, setSessionProposal] = + useState(null); + const approveSessionProposalAction: ( + addresses: string[] + ) => Promise = async (addresses: string[]) => { + let session: SessionTypes.Struct; + + if (web3Wallet && sessionProposal) { + logger.debug( + `${useWalletConnect.name}#${handleSessionProposal.name}(): approving session proposal "${sessionProposal.id}"` + ); + + session = await web3Wallet.approveSession({ + id: sessionProposal.id, + namespaces: createSessionNamespaces({ + addresses, + proposalParams: sessionProposal.params, + }), + }); + + // TODO: add session to sessions + + console.log(JSON.stringify(session)); + console.log(JSON.stringify(sessionProposal)); + + // clean up + setPairing(false); + setSessionProposal(null); + } + }; + const handleSessionProposal: ( + proposal: Web3WalletTypes.SessionProposal + ) => void = (proposal: Web3WalletTypes.SessionProposal) => { + logger.debug( + `${useWalletConnect.name}#${handleSessionProposal.name}(): received session proposal "${proposal.id}"` + ); + + setSessionProposal(proposal); + setPairing(false); + }; + const rejectSessionProposalAction: () => Promise = async () => { + if (web3Wallet && sessionProposal) { + logger.debug( + `${useWalletConnect.name}#${rejectSessionProposalAction.name}(): rejecting session proposal "${sessionProposal.id}"` + ); + + await web3Wallet.rejectSession({ + id: sessionProposal.id, + reason: getSdkError('USER_REJECTED'), + }); + + // clean up + setPairing(false); + setSessionProposal(null); + } + }; + + useEffect(() => { + if (web3Wallet && uri) { + (async () => { + web3Wallet.on('session_proposal', handleSessionProposal); + + setPairing(true); + + await web3Wallet.core.pairing.pair({ + uri, + }); + })(); + } + + return function cleanup() { + if (web3Wallet) { + web3Wallet.removeListener('session_proposal', handleSessionProposal); + } + }; + }, [uri]); + + return { + approveSessionProposalAction, + pairing, + rejectSessionProposalAction, + sessionProposal, + }; +} diff --git a/src/extension/hooks/useWalletConnect/utils/createSessionNamespaces.ts b/src/extension/hooks/useWalletConnect/utils/createSessionNamespaces.ts new file mode 100644 index 00000000..a83f022f --- /dev/null +++ b/src/extension/hooks/useWalletConnect/utils/createSessionNamespaces.ts @@ -0,0 +1,36 @@ +import { ProposalTypes, SessionTypes } from '@walletconnect/types'; +import { buildApprovedNamespaces } from '@walletconnect/utils'; + +// Config +import { + walletConnectSupportedChains as chains, + walletConnectSupportedMethods as methods, +} from '@extension/config'; + +interface IOptions { + addresses: string[]; + proposalParams: ProposalTypes.Struct; +} + +export default function createSessionNamespaces({ + addresses, + proposalParams, +}: IOptions): SessionTypes.Namespaces { + return buildApprovedNamespaces({ + proposal: proposalParams, + supportedNamespaces: { + algorand: { + accounts: chains.reduce( + (acc, chain) => [ + ...acc, + ...addresses.map((address) => `${chain}:${address}`), + ], + [] + ), // accounts that comply with the CAIP-10 format e.g. ['algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDe:ULDXF5B7ZJFIKUY25RFE7EIBV3CS47FZLZDCJHUHQFRSX74L5S6V75M4NE'] + chains, + events: [], + methods, + }, + }, + }); +} diff --git a/src/extension/hooks/useWalletConnect/utils/index.ts b/src/extension/hooks/useWalletConnect/utils/index.ts new file mode 100644 index 00000000..13184a44 --- /dev/null +++ b/src/extension/hooks/useWalletConnect/utils/index.ts @@ -0,0 +1 @@ +export { default as createSessionNamespaces } from './createSessionNamespaces'; diff --git a/src/extension/selectors/index.ts b/src/extension/selectors/index.ts index 4fc760aa..e74d3ffb 100644 --- a/src/extension/selectors/index.ts +++ b/src/extension/selectors/index.ts @@ -15,6 +15,7 @@ export { default as useSelectFetchingAssets } from './useSelectFetchingAssets'; export { default as useSelectFetchingSessions } from './useSelectFetchingSessions'; export { default as useSelectFetchingSettings } from './useSelectFetchingSettings'; export { default as useSelectFetchingTransactionsByAccountId } from './useSelectFetchingTransactionsByAccountId'; +export { default as useSelectInitializingWalletConnect } from './useSelectInitializingWalletConnect'; export { default as useSelectIsOnline } from './useSelectIsOnline'; export { default as useSelectLogger } from './useSelectLogger'; export { default as useSelectNetworkByGenesisHash } from './useSelectNetworkByGenesisHash'; @@ -33,3 +34,5 @@ export { default as useSelectSignTxnsRequest } from './useSelectSignTxnsRequest' export { default as useSelectToast } from './useSelectToast'; export { default as useSelectUpdatingAccounts } from './useSelectUpdatingAccounts'; export { default as useSelectUpdatingAssets } from './useSelectUpdatingAssets'; +export { default as useSelectWalletConnectModalOpen } from './useSelectWalletConnectModalOpen'; +export { default as useSelectWeb3Wallet } from './useSelectWeb3Wallet'; diff --git a/src/extension/selectors/useSelectInitializingWalletConnect.ts b/src/extension/selectors/useSelectInitializingWalletConnect.ts new file mode 100644 index 00000000..ce311667 --- /dev/null +++ b/src/extension/selectors/useSelectInitializingWalletConnect.ts @@ -0,0 +1,9 @@ +import { useSelector } from 'react-redux'; + +// Types +import { IMainRootState } from '@extension/types'; +export default function useSelectInitializingWalletConnect(): boolean { + return useSelector( + (state) => state.sessions.initializingWalletConnect + ); +} diff --git a/src/extension/selectors/useSelectWalletConnectModalOpen.ts b/src/extension/selectors/useSelectWalletConnectModalOpen.ts new file mode 100644 index 00000000..6a53c69a --- /dev/null +++ b/src/extension/selectors/useSelectWalletConnectModalOpen.ts @@ -0,0 +1,9 @@ +import { useSelector } from 'react-redux'; + +// Types +import { IMainRootState } from '@extension/types'; +export default function useSelectWalletConnectModalOpen(): boolean { + return useSelector( + (state) => state.sessions.walletConnectModalOpen + ); +} diff --git a/src/extension/selectors/useSelectWeb3Wallet.ts b/src/extension/selectors/useSelectWeb3Wallet.ts new file mode 100644 index 00000000..c8a8404a --- /dev/null +++ b/src/extension/selectors/useSelectWeb3Wallet.ts @@ -0,0 +1,10 @@ +import { IWeb3Wallet } from '@walletconnect/web3wallet/dist/types'; +import { useSelector } from 'react-redux'; + +// Types +import { IMainRootState } from '@extension/types'; +export default function useSelectWeb3Wallet(): IWeb3Wallet | null { + return useSelector( + (state) => state.sessions.web3Wallet + ); +} diff --git a/src/extension/translations/en.ts b/src/extension/translations/en.ts index 413c9d53..8cff6fbe 100644 --- a/src/extension/translations/en.ts +++ b/src/extension/translations/en.ts @@ -9,10 +9,12 @@ const translation: IResourceLanguage = { addAccount: 'Add Account', addAsset: 'Add Asset', allow: 'Allow', + approve: 'Approve', cancel: 'Cancel', changePassword: 'Change Password', clearAllData: 'Clear All Data', confirm: 'Confirm', + connect: 'Connect', copySeedPhrase: 'Copy Seed Phrase', create: 'Create', dismiss: 'Dismiss', @@ -23,6 +25,7 @@ const translation: IResourceLanguage = { ok: 'OK', previous: 'Previous', receive: 'Receive', + reject: 'Reject', removeAllSessions: 'Remove All Sessions', save: 'Save', send: 'Send', @@ -57,6 +60,7 @@ const translation: IResourceLanguage = { clearAllData: 'Are you sure you want to clear all your data?', clearAllDataWarning: 'Once this has been completed, it cannot be reversed. All your settings and accounts will be removed', + connectingToWalletConnect: 'Attempting to connect to WalletConnect.', copied: 'Copied!', createNewAccount: 'Create a new account. You will be prompted to save a mnemonic seed phrase.', @@ -74,6 +78,8 @@ const translation: IResourceLanguage = { importExistingAccount: `Import an existing account using you mnemonic seed phrase.`, importExistingAccountComplete: `To finalize we will encrypt your account keys with your password and you will be able to start using this account.`, importRekeyedAccount: `Import an existing account that has been rekeyed. You will need the mnemonic seed phrase of the authorized account and the address of the rekeyed account.`, + initializingWalletConnect: + 'Putting the final touches into your WalletConnect interface.', invalidAlgorithm: `The suggested signing method does not match the method that will be used to sign this token`, managerAddressDoesNotMatch: 'This account does not have the authority to alter this asset. This transaction will likely fail.', @@ -109,6 +115,8 @@ const translation: IResourceLanguage = { saveMnemonicPhrase1: 'Here is your 25 word mnemonic seed phrase; it is the key to your account.', saveMnemonicPhrase2: `Make sure you save this in a secure place.`, + scanningForQrCode: + 'Scanning for a WalletConnect QR Code. Make sure the WalletConnect QR code is visible in the background.', securityTokenExpired: 'This token has expired', signJwtRequest: 'An application is requesting to sign a security token.', signMessageRequest: 'An application is requesting to sign a message.', @@ -212,6 +220,7 @@ const translation: IResourceLanguage = { authorizedAddresses: 'Authorized Addresses', balance: 'Balance', clawbackAccount: 'Clawback Account', + connectWallet: 'Connect Wallet', copySeedPhraseConfirm: 'I confirm I have copied my seed phrase to a secure place.', creatorAccount: 'Creator Account', diff --git a/src/extension/types/IWalletConnectSupportedNamespace.ts b/src/extension/types/IWalletConnectSupportedNamespace.ts new file mode 100644 index 00000000..57b38e62 --- /dev/null +++ b/src/extension/types/IWalletConnectSupportedNamespace.ts @@ -0,0 +1,8 @@ +interface IWalletConnectSupportedNamespace { + accounts: string[]; + chains: string[]; + events: string[]; + methods: string[]; +} + +export default IWalletConnectSupportedNamespace; diff --git a/src/extension/types/index.ts b/src/extension/types/index.ts index 5a7d914b..f67d813a 100644 --- a/src/extension/types/index.ts +++ b/src/extension/types/index.ts @@ -62,3 +62,4 @@ export type { default as ITinyManAssetResponse } from './ITinyManAssetResponse'; export type { default as ITransactions } from './ITransactions'; export type { default as IVestigeFiAssetResponse } from './IVestigeFiAssetResponse'; export type { default as IUnknownTransaction } from './IUnknownTransaction'; +export type { default as IWalletConnectSupportedNamespace } from './IWalletConnectSupportedNamespace'; diff --git a/src/extension/utils/convertDataUriToImageData.ts b/src/extension/utils/convertDataUriToImageData.ts new file mode 100644 index 00000000..fd62b8b1 --- /dev/null +++ b/src/extension/utils/convertDataUriToImageData.ts @@ -0,0 +1,31 @@ +/** + * Converts an image data URI to image data. + * @param {string} datUri - the image data URI. + * @returns {Promise} the image data or null if no image could be found in the URI. + */ +export default function convertDataUriToImageData( + datUri: string +): Promise { + return new Promise((resolve) => { + const canvas: HTMLCanvasElement = document.createElement('canvas'); + const context: CanvasRenderingContext2D | null = canvas.getContext('2d'); + const image: HTMLImageElement = new Image(); + + // add an event listener for when the image has been loaded. + image.addEventListener('load', () => { + canvas.width = image.width; + canvas.height = image.height; + + if (!context) { + return resolve(null); + } + + // update the canvas with the image + context.drawImage(image, 0, 0, canvas.width, canvas.height); + + return resolve(context.getImageData(0, 0, canvas.width, canvas.height)); + }); + + image.src = datUri; + }); +} diff --git a/src/extension/utils/index.ts b/src/extension/utils/index.ts index 32a1c966..f95b3853 100644 --- a/src/extension/utils/index.ts +++ b/src/extension/utils/index.ts @@ -1,4 +1,5 @@ export { default as bootstrapApp } from './bootstrapApp'; +export { default as convertDataUriToImageData } from './convertDataUriToImageData'; export { default as convertGenesisHashToHex } from './convertGenesisHashToHex'; export { default as createIconFromDataUri } from './createIconFromDataUri'; export { default as decodeJwt } from './decodeJwt'; diff --git a/src/extension/utils/makeStore.ts b/src/extension/utils/makeStore.ts index 753f1d6f..bbf0f594 100644 --- a/src/extension/utils/makeStore.ts +++ b/src/extension/utils/makeStore.ts @@ -7,6 +7,7 @@ import { setNavigate, setToast, } from '@extension/features/system'; +import { initializeWalletConnectThunk } from '@extension/features/sessions'; // Types import { IBaseRootState } from '@extension/types'; @@ -19,12 +20,14 @@ export default function makeStore( getDefaultMiddleware({ serializableCheck: { ignoredActions: [ + initializeWalletConnectThunk.fulfilled.type, setConfirm.type, setError.type, setNavigate.type, setToast.type, ], ignoredPaths: [ + 'sessions.web3Wallet', 'system.confirm.onCancel', 'system.confirm.onConfirm', 'system.error', diff --git a/src/manifest.json b/src/manifest.json index 82f8b0cd..7b1e7fda 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -13,6 +13,7 @@ "*://algosigner.api.purestake.io/*", "*://*.algonode.cloud/*", "*://*.algorpc.pro/*", + "", "downloads", "storage" ], @@ -25,22 +26,14 @@ "default_title": "Kibisis" }, "background": { - "scripts": [ - "background.js" - ], + "scripts": ["background.js"], "persistent": true }, "content_scripts": [ { - "matches": [ - "" - ], - "js": [ - "content-script.js" - ] + "matches": [""], + "js": ["content-script.js"] } ], - "web_accessible_resources": [ - "wallet-initializer.js" - ] + "web_accessible_resources": ["wallet-initializer.js"] } From dfe3033fb3c33c1d6e807280cfd1a287959ab3f5 Mon Sep 17 00:00:00 2001 From: Kieran O'Neill Date: Thu, 15 Jun 2023 20:07:15 +0100 Subject: [PATCH 07/12] feat: add chain agnostic namespaces to the network --- src/extension/config/networks.ts | 20 +++++++++++++++++++ ...sionThunk.ts => removeSessionByIdThunk.ts} | 11 +++++----- src/extension/types/IChainNamespace.ts | 7 +++++++ src/extension/types/INetwork.ts | 2 ++ .../types/IWalletConnectSupportedNamespace.ts | 8 -------- src/extension/types/index.ts | 3 ++- 6 files changed, 36 insertions(+), 15 deletions(-) rename src/extension/features/sessions/thunks/{removeSessionThunk.ts => removeSessionByIdThunk.ts} (72%) create mode 100644 src/extension/types/IChainNamespace.ts delete mode 100644 src/extension/types/IWalletConnectSupportedNamespace.ts diff --git a/src/extension/config/networks.ts b/src/extension/config/networks.ts index 1d9310d3..85bd64be 100644 --- a/src/extension/config/networks.ts +++ b/src/extension/config/networks.ts @@ -63,6 +63,11 @@ const networks: INetwork[] = [ url: 'https://mainnet-idx.algonode.cloud', }, ], + namespace: { + key: 'algorand', + methods: ['signTransaction', 'signMessage'], + reference: 'wGHE2Pwdvd7S12BL5FaOP20EGYesN73k', + }, nativeCurrency: { code: 'ALGO', decimals: 6, @@ -125,6 +130,11 @@ const networks: INetwork[] = [ url: 'https://betanet-idx.algonode.cloud', }, ], + namespace: { + key: 'algorand', + methods: ['signTransaction', 'signMessage'], + reference: 'mFgazF-2uRS1tMiL9dsj01hJGySEmPN2', + }, nativeCurrency: { code: 'ALGO', decimals: 6, @@ -192,6 +202,11 @@ const networks: INetwork[] = [ url: 'https://testnet-idx.algonode.cloud', }, ], + namespace: { + key: 'algorand', + methods: ['signTransaction', 'signMessage'], + reference: 'SGO1GKSzyE7IEPItTxCByw9x8FmnrCDe', + }, nativeCurrency: { code: 'ALGO', decimals: 6, @@ -220,6 +235,11 @@ const networks: INetwork[] = [ url: 'https://voitest-idx.algorpc.pro', }, ], + namespace: { + key: 'voi', + methods: ['signTransaction', 'signMessage'], + reference: 'xK6y2kD4Rnq9EYD1Ta1JTf56TBQTu2_z', + }, nativeCurrency: { code: 'VOI', decimals: 6, diff --git a/src/extension/features/sessions/thunks/removeSessionThunk.ts b/src/extension/features/sessions/thunks/removeSessionByIdThunk.ts similarity index 72% rename from src/extension/features/sessions/thunks/removeSessionThunk.ts rename to src/extension/features/sessions/thunks/removeSessionByIdThunk.ts index dc77f329..3347d6f4 100644 --- a/src/extension/features/sessions/thunks/removeSessionThunk.ts +++ b/src/extension/features/sessions/thunks/removeSessionByIdThunk.ts @@ -1,13 +1,10 @@ import { AsyncThunk, createAsyncThunk } from '@reduxjs/toolkit'; -// Constants -import { SESSION_ITEM_KEY_PREFIX } from '@extension/constants'; - // Enums import { SessionsThunkEnum } from '@extension/enums'; // Services -import { StorageManager } from '@extension/services'; +import { SessionService } from '@extension/services'; // Types import { ILogger } from '@common/types'; @@ -21,13 +18,15 @@ const removeSessionThunk: AsyncThunk< SessionsThunkEnum.RemoveSession, async (id, { getState }) => { const logger: ILogger = getState().system.logger; - const storageManager: StorageManager = new StorageManager(); + const sessionService: SessionService = new SessionService({ + logger, + }); logger.debug( `${removeSessionThunk.name}: removing session "${id}" from storage` ); - await storageManager.remove(`${SESSION_ITEM_KEY_PREFIX}${id}`); + await sessionService.removeById(id); return id; } diff --git a/src/extension/types/IChainNamespace.ts b/src/extension/types/IChainNamespace.ts new file mode 100644 index 00000000..8185371c --- /dev/null +++ b/src/extension/types/IChainNamespace.ts @@ -0,0 +1,7 @@ +interface IChainNamespace { + key: string; + reference: string; + methods: string[]; +} + +export default IChainNamespace; diff --git a/src/extension/types/INetwork.ts b/src/extension/types/INetwork.ts index ab113e86..dc014ec4 100644 --- a/src/extension/types/INetwork.ts +++ b/src/extension/types/INetwork.ts @@ -2,6 +2,7 @@ import { NetworkTypeEnum } from '../enums'; // Types +import IChainNamespace from './IChainNamespace'; import IExplorer from './IExplorer'; import INativeCurrency from './INativeCurrency'; import INode from './INode'; @@ -12,6 +13,7 @@ interface INetwork { explorers: IExplorer[]; genesisHash: string; genesisId: string; + namespace: IChainNamespace; nativeCurrency: INativeCurrency; indexers: INode[]; algods: INode[]; diff --git a/src/extension/types/IWalletConnectSupportedNamespace.ts b/src/extension/types/IWalletConnectSupportedNamespace.ts deleted file mode 100644 index 57b38e62..00000000 --- a/src/extension/types/IWalletConnectSupportedNamespace.ts +++ /dev/null @@ -1,8 +0,0 @@ -interface IWalletConnectSupportedNamespace { - accounts: string[]; - chains: string[]; - events: string[]; - methods: string[]; -} - -export default IWalletConnectSupportedNamespace; diff --git a/src/extension/types/index.ts b/src/extension/types/index.ts index f67d813a..b794c1f4 100644 --- a/src/extension/types/index.ts +++ b/src/extension/types/index.ts @@ -62,4 +62,5 @@ export type { default as ITinyManAssetResponse } from './ITinyManAssetResponse'; export type { default as ITransactions } from './ITransactions'; export type { default as IVestigeFiAssetResponse } from './IVestigeFiAssetResponse'; export type { default as IUnknownTransaction } from './IUnknownTransaction'; -export type { default as IWalletConnectSupportedNamespace } from './IWalletConnectSupportedNamespace'; +export type { default as IChainNamespace } from './IChainNamespace'; +export type { default as IWalletConnectSessionMetadata } from './IWalletConnectSessionMetadata'; From b09c958d2acfe46cbbfd0996dbab24fea8f2b668 Mon Sep 17 00:00:00 2001 From: Kieran O'Neill Date: Thu, 15 Jun 2023 20:07:59 +0100 Subject: [PATCH 08/12] feat: add wallet connect to the session store --- dapp/App.tsx | 18 ++++---- .../ManageSessionModal/ManageSessionModal.tsx | 4 +- .../WalletConnectModal/WalletConnectModal.tsx | 15 +++---- src/extension/enums/SessionsThunkEnum.ts | 3 +- src/extension/features/sessions/slice.ts | 43 ++++++++++++++++--- .../sessions/thunks/fetchSessionsThunk.ts | 25 ++++------- .../features/sessions/thunks/index.ts | 3 +- .../thunks/initializeWalletConnectThunk.ts | 12 +++--- .../sessions/thunks/removeSessionByIdThunk.ts | 8 ++-- .../thunks/removeSessionByTopicThunk.ts | 40 +++++++++++++++++ .../sessions/thunks/setSessionThunk.ts | 15 +++---- .../features/sessions/types/ISessionsState.ts | 2 +- .../types/IUseWalletConnectState.ts | 6 ++- .../useWalletConnect/useWalletConnect.ts | 32 +++++++++++--- .../utils/createSessionNamespaces.ts | 29 ++++++------- .../SessionsSettingsPage.tsx | 5 ++- src/extension/services/SessionService.ts | 14 ++++++ src/extension/types/ISession.ts | 5 +++ .../types/IWalletConnectSessionMetadata.ts | 14 ++++++ src/extension/utils/index.ts | 1 + .../utils/mapSessionFromEnableRequest.ts | 1 + .../mapSessionFromWalletConnectSession.ts | 38 ++++++++++++++++ 22 files changed, 241 insertions(+), 92 deletions(-) create mode 100644 src/extension/features/sessions/thunks/removeSessionByTopicThunk.ts create mode 100644 src/extension/types/IWalletConnectSessionMetadata.ts create mode 100644 src/extension/utils/mapSessionFromWalletConnectSession.ts diff --git a/dapp/App.tsx b/dapp/App.tsx index 0ca7f556..8ed59ebe 100644 --- a/dapp/App.tsx +++ b/dapp/App.tsx @@ -66,15 +66,6 @@ import { IAccountInformation } from './types'; import { getAccountInformation } from './utils'; const App: FC = () => { - const { connect } = useConnect({ - requiredNamespaces: { - algorand: { - chains: walletConnectSupportedChains, - events: [], - methods: walletConnectSupportedMethods, - }, - }, - }); const toast: CreateToastFnReturn = useToast({ duration: 3000, isClosable: true, @@ -86,6 +77,15 @@ const App: FC = () => { const [selectedAccount, setSelectedAccount] = useState(null); const [selectedNetwork, setSelectedNetwork] = useState(null); + const { connect } = useConnect({ + requiredNamespaces: { + algorand: { + chains: walletConnectSupportedChains, + events: [], + methods: walletConnectSupportedMethods, + }, + }, + }); const handleAddressSelect = (event: ChangeEvent) => { const account: IAccountInformation | null = enabledAccounts.find((value) => value.address === event.target.value) || diff --git a/src/extension/components/ManageSessionModal/ManageSessionModal.tsx b/src/extension/components/ManageSessionModal/ManageSessionModal.tsx index 91ffe54a..98f9f9bb 100644 --- a/src/extension/components/ManageSessionModal/ManageSessionModal.tsx +++ b/src/extension/components/ManageSessionModal/ManageSessionModal.tsx @@ -33,7 +33,7 @@ import { DEFAULT_GAP } from '@extension/constants'; // Features import { - removeSessionThunk, + removeSessionByIdThunk, setSessionThunk, } from '@extension/features/sessions'; @@ -98,7 +98,7 @@ const ManageSessionModal: FC = ({ onClose, session }: IProps) => { // if all authorized accounts are removed, remove the session if (authorizedAddresses.length <= 0) { - dispatch(removeSessionThunk(session.id)); + dispatch(removeSessionByIdThunk(session.id)); onClose(); diff --git a/src/extension/components/WalletConnectModal/WalletConnectModal.tsx b/src/extension/components/WalletConnectModal/WalletConnectModal.tsx index 96b83ba7..02109d7c 100644 --- a/src/extension/components/WalletConnectModal/WalletConnectModal.tsx +++ b/src/extension/components/WalletConnectModal/WalletConnectModal.tsx @@ -52,12 +52,7 @@ import { AccountService } from '@extension/services'; import { theme } from '@extension/theme'; // Types -import { - IAccount, - IAccountInformation, - IAppThunkDispatch, - INetwork, -} from '@extension/types'; +import { IAccount, IAccountInformation, INetwork } from '@extension/types'; // Utils import { ellipseAddress } from '@extension/utils'; @@ -94,11 +89,11 @@ const WalletConnectModal: FC = ({ onClose }: IProps) => { const [authorizedAddresses, setAuthorizedAddresses] = useState([]); // handlers const handleApproveClick = async () => { - if (authorizedAddresses.length > 0) { - await approveSessionProposalAction(authorizedAddresses); - - handleClose(); + if (authorizedAddresses.length > 0 && network) { + await approveSessionProposalAction(authorizedAddresses, network); } + + handleClose(); }; const handleCancelClick = () => handleClose(); const handleClose = () => { diff --git a/src/extension/enums/SessionsThunkEnum.ts b/src/extension/enums/SessionsThunkEnum.ts index f57c8e8e..9c9bb3be 100644 --- a/src/extension/enums/SessionsThunkEnum.ts +++ b/src/extension/enums/SessionsThunkEnum.ts @@ -3,7 +3,8 @@ enum SessionsThunkEnum { FetchSessions = 'sessions/fetchSessions', InitializeWalletConnect = 'sessions/initializeWalletConnect', RemoveAuthorizedAddress = 'sessions/removeAuthorizedAddress', - RemoveSession = 'sessions/removeSession', + RemoveSessionById = 'sessions/removeSessionById', + RemoveSessionByTopic = 'sessions/removeSessionByTopic', SetSession = 'sessions/setSession', } diff --git a/src/extension/features/sessions/slice.ts b/src/extension/features/sessions/slice.ts index 07360a65..e24c7a19 100644 --- a/src/extension/features/sessions/slice.ts +++ b/src/extension/features/sessions/slice.ts @@ -10,7 +10,8 @@ import { fetchSessionsThunk, initializeWalletConnectThunk, removeAuthorizedAddressThunk, - removeSessionThunk, + removeSessionByIdThunk, + removeSessionByTopicThunk, setSessionThunk, } from './thunks'; @@ -95,9 +96,9 @@ const slice = createSlice({ state.saving = false; } ); - /** Remove session **/ + /** Remove session by id **/ builder.addCase( - removeSessionThunk.fulfilled, + removeSessionByIdThunk.fulfilled, (state: ISessionsState, action: PayloadAction) => { state.items = state.items.filter( (value) => value.id !== action.payload @@ -105,12 +106,40 @@ const slice = createSlice({ state.saving = false; } ); - builder.addCase(removeSessionThunk.pending, (state: ISessionsState) => { + builder.addCase(removeSessionByIdThunk.pending, (state: ISessionsState) => { state.saving = true; }); - builder.addCase(removeSessionThunk.rejected, (state: ISessionsState) => { - state.saving = false; - }); + builder.addCase( + removeSessionByIdThunk.rejected, + (state: ISessionsState) => { + state.saving = false; + } + ); + /** Remove session by topic **/ + builder.addCase( + removeSessionByTopicThunk.fulfilled, + (state: ISessionsState, action: PayloadAction) => { + if (action.payload) { + state.items = state.items.filter( + (value) => value.id !== action.payload + ); + } + + state.saving = false; + } + ); + builder.addCase( + removeSessionByTopicThunk.pending, + (state: ISessionsState) => { + state.saving = true; + } + ); + builder.addCase( + removeSessionByTopicThunk.rejected, + (state: ISessionsState) => { + state.saving = false; + } + ); /** Set session **/ builder.addCase( setSessionThunk.fulfilled, diff --git a/src/extension/features/sessions/thunks/fetchSessionsThunk.ts b/src/extension/features/sessions/thunks/fetchSessionsThunk.ts index 6143742a..96646fab 100644 --- a/src/extension/features/sessions/thunks/fetchSessionsThunk.ts +++ b/src/extension/features/sessions/thunks/fetchSessionsThunk.ts @@ -1,16 +1,14 @@ import { AsyncThunk, createAsyncThunk } from '@reduxjs/toolkit'; -// Constants -import { SESSION_ITEM_KEY_PREFIX } from '@extension/constants'; - // Enums import { SessionsThunkEnum } from '@extension/enums'; // Services -import { StorageManager } from '@extension/services'; +import { SessionService } from '@extension/services'; // Types -import { IMainRootState, ISession, IStorageItemTypes } from '@extension/types'; +import { ILogger } from '@common/types'; +import { IMainRootState, ISession } from '@extension/types'; const fetchSessionsThunk: AsyncThunk< ISession[], // return @@ -18,18 +16,13 @@ const fetchSessionsThunk: AsyncThunk< Record > = createAsyncThunk( SessionsThunkEnum.FetchSessions, - async () => { - const storageManager: StorageManager = new StorageManager(); - const storageItems: Record = - await storageManager.getAllItems(); + async (_, { getState }) => { + const logger: ILogger = getState().system.logger; + const sessionService: SessionService = new SessionService({ + logger, + }); - return Object.keys(storageItems).reduce( - (acc, key) => - key.startsWith(SESSION_ITEM_KEY_PREFIX) - ? [...acc, storageItems[key] as ISession] - : acc, - [] - ); + return await sessionService.getAll(); } ); diff --git a/src/extension/features/sessions/thunks/index.ts b/src/extension/features/sessions/thunks/index.ts index d392123a..86eafdd4 100644 --- a/src/extension/features/sessions/thunks/index.ts +++ b/src/extension/features/sessions/thunks/index.ts @@ -2,5 +2,6 @@ export { default as clearSessionsThunk } from './clearSessionsThunk'; export { default as fetchSessionsThunk } from './fetchSessionsThunk'; export { default as initializeWalletConnectThunk } from './initializeWalletConnectThunk'; export { default as removeAuthorizedAddressThunk } from './removeAuthorizedAddressThunk'; -export { default as removeSessionThunk } from './removeSessionThunk'; +export { default as removeSessionByIdThunk } from './removeSessionByIdThunk'; +export { default as removeSessionByTopicThunk } from './removeSessionByTopicThunk'; export { default as setSessionThunk } from './setSessionThunk'; diff --git a/src/extension/features/sessions/thunks/initializeWalletConnectThunk.ts b/src/extension/features/sessions/thunks/initializeWalletConnectThunk.ts index 971bab28..d67078ec 100644 --- a/src/extension/features/sessions/thunks/initializeWalletConnectThunk.ts +++ b/src/extension/features/sessions/thunks/initializeWalletConnectThunk.ts @@ -9,6 +9,9 @@ import { KIBISIS_LINK } from '@extension/constants'; // Enums import { SessionsThunkEnum } from '@extension/enums'; +// Thunks +import removeSessionByTopicThunk from './removeSessionByTopicThunk'; + // Types import { IMainRootState } from '@extension/types'; import { ILogger } from '@common/types'; @@ -19,7 +22,7 @@ const initializeWalletConnectThunk: AsyncThunk< Record > = createAsyncThunk( SessionsThunkEnum.InitializeWalletConnect, - async (_, { getState }) => { + async (_, { dispatch, getState }) => { const logger: ILogger = getState().system.logger; const web3Wallet: IWeb3Wallet = await Web3Wallet.init({ core: new Core({ @@ -34,10 +37,9 @@ const initializeWalletConnectThunk: AsyncThunk< }); // add event listeners - web3Wallet.on('session_delete', (event) => { - // TODO: handle session disconnected - console.log(event); - }); + web3Wallet.on('session_delete', (event) => + dispatch(removeSessionByTopicThunk(event.topic)) + ); return web3Wallet; } diff --git a/src/extension/features/sessions/thunks/removeSessionByIdThunk.ts b/src/extension/features/sessions/thunks/removeSessionByIdThunk.ts index 3347d6f4..e1698660 100644 --- a/src/extension/features/sessions/thunks/removeSessionByIdThunk.ts +++ b/src/extension/features/sessions/thunks/removeSessionByIdThunk.ts @@ -10,12 +10,12 @@ import { SessionService } from '@extension/services'; import { ILogger } from '@common/types'; import { IMainRootState } from '@extension/types'; -const removeSessionThunk: AsyncThunk< +const removeSessionByIdThunk: AsyncThunk< string, // return string, // args Record > = createAsyncThunk( - SessionsThunkEnum.RemoveSession, + SessionsThunkEnum.RemoveSessionById, async (id, { getState }) => { const logger: ILogger = getState().system.logger; const sessionService: SessionService = new SessionService({ @@ -23,7 +23,7 @@ const removeSessionThunk: AsyncThunk< }); logger.debug( - `${removeSessionThunk.name}: removing session "${id}" from storage` + `${removeSessionByIdThunk.name}: removing session "${id}" from storage` ); await sessionService.removeById(id); @@ -32,4 +32,4 @@ const removeSessionThunk: AsyncThunk< } ); -export default removeSessionThunk; +export default removeSessionByIdThunk; diff --git a/src/extension/features/sessions/thunks/removeSessionByTopicThunk.ts b/src/extension/features/sessions/thunks/removeSessionByTopicThunk.ts new file mode 100644 index 00000000..84dc49d0 --- /dev/null +++ b/src/extension/features/sessions/thunks/removeSessionByTopicThunk.ts @@ -0,0 +1,40 @@ +import { AsyncThunk, createAsyncThunk } from '@reduxjs/toolkit'; + +// Enums +import { SessionsThunkEnum } from '@extension/enums'; + +// Services +import { SessionService } from '@extension/services'; + +// Types +import { ILogger } from '@common/types'; +import { IMainRootState, ISession } from '@extension/types'; + +const removeSessionByTopicThunk: AsyncThunk< + string | null, // return + string, // args + Record +> = createAsyncThunk( + SessionsThunkEnum.RemoveSessionByTopic, + async (topic, { getState }) => { + const logger: ILogger = getState().system.logger; + const sessionService: SessionService = new SessionService({ + logger, + }); + const session: ISession | null = await sessionService.getByTopic(topic); + + if (!session) { + return null; + } + + logger.debug( + `${removeSessionByTopicThunk.name}: removing session "${session.id}" from storage` + ); + + await sessionService.removeById(session.id); + + return session.id; + } +); + +export default removeSessionByTopicThunk; diff --git a/src/extension/features/sessions/thunks/setSessionThunk.ts b/src/extension/features/sessions/thunks/setSessionThunk.ts index 3e72239a..44b8156c 100644 --- a/src/extension/features/sessions/thunks/setSessionThunk.ts +++ b/src/extension/features/sessions/thunks/setSessionThunk.ts @@ -1,13 +1,10 @@ import { AsyncThunk, createAsyncThunk } from '@reduxjs/toolkit'; -// Constants -import { SESSION_ITEM_KEY_PREFIX } from '@extension/constants'; - // Enums import { SessionsThunkEnum } from '@extension/enums'; // Services -import { StorageManager } from '@extension/services'; +import { SessionService } from '@extension/services'; // Types import { ILogger } from '@common/types'; @@ -21,17 +18,15 @@ const setSessionThunk: AsyncThunk< SessionsThunkEnum.SetSession, async (session, { getState }) => { const logger: ILogger = getState().system.logger; - const storageManager: StorageManager = new StorageManager(); + const sessionService: SessionService = new SessionService({ + logger, + }); logger.debug( `${SessionsThunkEnum.SetSession}: saving session "${session.id}" to storage` ); - await storageManager.setItems({ - [`${SESSION_ITEM_KEY_PREFIX}${session.id}`]: session, - }); - - return session; + return await sessionService.save(session); } ); diff --git a/src/extension/features/sessions/types/ISessionsState.ts b/src/extension/features/sessions/types/ISessionsState.ts index ee01acff..8ee2872e 100644 --- a/src/extension/features/sessions/types/ISessionsState.ts +++ b/src/extension/features/sessions/types/ISessionsState.ts @@ -6,7 +6,7 @@ import { ISession } from '@extension/types'; /** * @property {boolean} fetching - true fetching the sessions from storage. * @property {boolean} initializingWalletConnect - true if the Web3Wallet (WalletConnect) instance is initializing. - * @property {ISession[]} items - the session items. + * @property {Array} items - the session items. * @property {boolean} saving - true saving the sessions from storage. * @property {IWeb3Wallet | null} web3Wallet - an initialized instance of Web3Wallet (WalletConnect). * @property {boolean} walletConnectModalOpen - true if the wallet connect modal is open. diff --git a/src/extension/hooks/useWalletConnect/types/IUseWalletConnectState.ts b/src/extension/hooks/useWalletConnect/types/IUseWalletConnectState.ts index 3ca7d518..1f70f4d2 100644 --- a/src/extension/hooks/useWalletConnect/types/IUseWalletConnectState.ts +++ b/src/extension/hooks/useWalletConnect/types/IUseWalletConnectState.ts @@ -1,7 +1,11 @@ import { Web3WalletTypes } from '@walletconnect/web3wallet'; +import { INetwork } from '@extension/types'; interface IUseWalletConnectState { - approveSessionProposalAction: (addresses: string[]) => Promise; + approveSessionProposalAction: ( + authorizedAddresses: string[], + network: INetwork + ) => Promise; pairing: boolean; rejectSessionProposalAction: () => Promise; sessionProposal: Web3WalletTypes.SessionProposal | null; diff --git a/src/extension/hooks/useWalletConnect/useWalletConnect.ts b/src/extension/hooks/useWalletConnect/useWalletConnect.ts index e69f6886..11ff868e 100644 --- a/src/extension/hooks/useWalletConnect/useWalletConnect.ts +++ b/src/extension/hooks/useWalletConnect/useWalletConnect.ts @@ -3,20 +3,27 @@ import { getSdkError } from '@walletconnect/utils'; import { Web3WalletTypes } from '@walletconnect/web3wallet'; import { IWeb3Wallet } from '@walletconnect/web3wallet/dist/types'; import { useEffect, useState } from 'react'; +import { useDispatch } from 'react-redux'; + +// Features +import { setSessionThunk } from '@extension/features/sessions'; // Selectors import { useSelectLogger, useSelectWeb3Wallet } from '@extension/selectors'; // Types import { ILogger } from '@common/types'; +import { IAppThunkDispatch, INetwork } from '@extension/types'; import { IUseWalletConnectState } from './types'; // Utils +import { mapSessionFromWalletConnectSession } from '@extension/utils'; import { createSessionNamespaces } from './utils'; export default function useWalletConnect( uri: string | null ): IUseWalletConnectState { + const dispatch: IAppThunkDispatch = useDispatch(); // selectors const logger: ILogger = useSelectLogger(); const web3Wallet: IWeb3Wallet | null = useSelectWeb3Wallet(); @@ -25,8 +32,12 @@ export default function useWalletConnect( const [sessionProposal, setSessionProposal] = useState(null); const approveSessionProposalAction: ( - addresses: string[] - ) => Promise = async (addresses: string[]) => { + authorizedAddresses: string[], + network: INetwork + ) => Promise = async ( + authorizedAddresses: string[], + network: INetwork + ) => { let session: SessionTypes.Struct; if (web3Wallet && sessionProposal) { @@ -37,15 +48,22 @@ export default function useWalletConnect( session = await web3Wallet.approveSession({ id: sessionProposal.id, namespaces: createSessionNamespaces({ - addresses, + authorizedAddresses, + network, proposalParams: sessionProposal.params, }), }); - // TODO: add session to sessions - - console.log(JSON.stringify(session)); - console.log(JSON.stringify(sessionProposal)); + // add the session to the store + dispatch( + setSessionThunk( + mapSessionFromWalletConnectSession({ + authorizedAddresses, + network, + walletConnectSession: session, + }) + ) + ); // clean up setPairing(false); diff --git a/src/extension/hooks/useWalletConnect/utils/createSessionNamespaces.ts b/src/extension/hooks/useWalletConnect/utils/createSessionNamespaces.ts index a83f022f..d98f5bf9 100644 --- a/src/extension/hooks/useWalletConnect/utils/createSessionNamespaces.ts +++ b/src/extension/hooks/useWalletConnect/utils/createSessionNamespaces.ts @@ -1,35 +1,32 @@ import { ProposalTypes, SessionTypes } from '@walletconnect/types'; import { buildApprovedNamespaces } from '@walletconnect/utils'; -// Config -import { - walletConnectSupportedChains as chains, - walletConnectSupportedMethods as methods, -} from '@extension/config'; +// Types +import { INetwork } from '@extension/types'; interface IOptions { - addresses: string[]; + authorizedAddresses: string[]; + network: INetwork; proposalParams: ProposalTypes.Struct; } export default function createSessionNamespaces({ - addresses, + authorizedAddresses, + network, proposalParams, }: IOptions): SessionTypes.Namespaces { + const chainId: string = `${network.namespace.key}:${network.namespace.reference}`; // in CAIP-2 format e.g. ['algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDe'] + return buildApprovedNamespaces({ proposal: proposalParams, supportedNamespaces: { algorand: { - accounts: chains.reduce( - (acc, chain) => [ - ...acc, - ...addresses.map((address) => `${chain}:${address}`), - ], - [] - ), // accounts that comply with the CAIP-10 format e.g. ['algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDe:ULDXF5B7ZJFIKUY25RFE7EIBV3CS47FZLZDCJHUHQFRSX74L5S6V75M4NE'] - chains, + accounts: authorizedAddresses.map((value) => `${chainId}:${value}`), // accounts that comply with the CAIP-10 format e.g. ['algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDe:ULDXF5B7ZJFIKUY25RFE7EIBV3CS47FZLZDCJHUHQFRSX74L5S6V75M4NE'] + chains: [chainId], events: [], - methods, + methods: network.namespace.methods.map( + (value) => `${network.namespace.key}_${value}` + ), }, }, }); diff --git a/src/extension/pages/SessionsSettingsPage/SessionsSettingsPage.tsx b/src/extension/pages/SessionsSettingsPage/SessionsSettingsPage.tsx index b229d470..ea053f45 100644 --- a/src/extension/pages/SessionsSettingsPage/SessionsSettingsPage.tsx +++ b/src/extension/pages/SessionsSettingsPage/SessionsSettingsPage.tsx @@ -26,7 +26,7 @@ import SettingsSessionItem from '@extension/components/SettingsSessionItem'; import { setConfirm } from '@extension/features/system'; import { clearSessionsThunk, - removeSessionThunk, + removeSessionByIdThunk, } from '@extension/features/sessions'; // Hooks @@ -62,7 +62,8 @@ const SessionsSettingsPage: FC = () => { title: t('headings.removeAllSessions'), }) ); - const handleRemoveSession = (id: string) => dispatch(removeSessionThunk(id)); + const handleRemoveSession = (id: string) => + dispatch(removeSessionByIdThunk(id)); const renderContent = () => { if (fetching) { return ( diff --git a/src/extension/services/SessionService.ts b/src/extension/services/SessionService.ts index 58d02181..e3d9ad35 100644 --- a/src/extension/services/SessionService.ts +++ b/src/extension/services/SessionService.ts @@ -61,6 +61,20 @@ export default class SessionService { return await this.storageManager.getItem(this.createItemKey(id)); } + /** + * Gets the session for a given WalletConnect topic. + * @param {string} topic - the WalletConnect topic to search for. + * @returns {Promise} the session or null. + */ + public async getByTopic(topic: string): Promise { + const sessions: ISession[] = await this.getAll(); + + return ( + sessions.find((value) => value.walletConnectMetadata?.topic === topic) || + null + ); + } + /** * Removes a session by its ID. * @param {string} id - the session ID. diff --git a/src/extension/types/ISession.ts b/src/extension/types/ISession.ts index 75a6484a..48c333fd 100644 --- a/src/extension/types/ISession.ts +++ b/src/extension/types/ISession.ts @@ -1,3 +1,6 @@ +// Tyoes +import IWalletConnectSessionMetadata from './IWalletConnectSessionMetadata'; + /** * @property {string} appName - the name of the dApp. * @property {string[]} authorizedAddresses - a list of authorized addresses. @@ -9,6 +12,7 @@ * @property {string | null} iconUrl - an icon url for the app. * @property {string} id - a unique identifier for this session as a UUID v4. * @property {number} usedAt - a timestamp (in milliseconds) for when this session was last used. + * @property {IWalletConnectSessionMetadata | null} walletConnectMetadata - extra data if this is a WalletConnect session. */ interface ISession { appName: string; @@ -21,6 +25,7 @@ interface ISession { iconUrl: string | null; id: string; usedAt: number; + walletConnectMetadata: IWalletConnectSessionMetadata | null; } export default ISession; diff --git a/src/extension/types/IWalletConnectSessionMetadata.ts b/src/extension/types/IWalletConnectSessionMetadata.ts new file mode 100644 index 00000000..6cbcc756 --- /dev/null +++ b/src/extension/types/IWalletConnectSessionMetadata.ts @@ -0,0 +1,14 @@ +import { SessionTypes } from '@walletconnect/types'; + +/** + * @property {number} expiresAt - a timestamp (in milliseconds) for when this session was expires. + * @property {SessionTypes.Namespaces} namespaces - the namespaces available for this session. + * @property {string} topic - the WalletConnect topic for this session. + */ +interface IWalletConnectSessionMetadata { + expiresAt: number; + namespaces: SessionTypes.Namespaces; + topic: string; +} + +export default IWalletConnectSessionMetadata; diff --git a/src/extension/utils/index.ts b/src/extension/utils/index.ts index f95b3853..31245d25 100644 --- a/src/extension/utils/index.ts +++ b/src/extension/utils/index.ts @@ -20,6 +20,7 @@ export { default as mapAddressToWalletAccount } from './mapAddressToWalletAccoun export { default as mapAlgorandAccountInformationToAccount } from './mapAlgorandAccountInformationToAccount'; export { default as mapAlgorandTransactionToTransaction } from './mapAlgorandTransactionToTransaction'; export { default as mapSessionFromEnableRequest } from './mapSessionFromEnableRequest'; +export { default as mapSessionFromWalletConnectSession } from './mapSessionFromWalletConnectSession'; export { default as parseTransactionType } from './parseTransactionType'; export { default as selectDefaultNetwork } from './selectDefaultNetwork'; export { default as upsertItemsById } from './upsertItemsById'; diff --git a/src/extension/utils/mapSessionFromEnableRequest.ts b/src/extension/utils/mapSessionFromEnableRequest.ts index 78bd5290..44a3b142 100644 --- a/src/extension/utils/mapSessionFromEnableRequest.ts +++ b/src/extension/utils/mapSessionFromEnableRequest.ts @@ -25,5 +25,6 @@ export default function mapSessionFromEnableRequest({ iconUrl, id, usedAt: now.getTime(), + walletConnectMetadata: null, }; } diff --git a/src/extension/utils/mapSessionFromWalletConnectSession.ts b/src/extension/utils/mapSessionFromWalletConnectSession.ts new file mode 100644 index 00000000..e9f72162 --- /dev/null +++ b/src/extension/utils/mapSessionFromWalletConnectSession.ts @@ -0,0 +1,38 @@ +import { SessionTypes } from '@walletconnect/types'; +import { v4 as uuid } from 'uuid'; + +// Types +import { INetwork, ISession } from '@extension/types'; + +interface IOptions { + authorizedAddresses: string[]; + network: INetwork; + walletConnectSession: SessionTypes.Struct; +} + +export default function mapSessionFromWalletConnectSession({ + authorizedAddresses, + network, + walletConnectSession, +}: IOptions): ISession { + const id: string = uuid(); + const now: Date = new Date(); + + return { + appName: walletConnectSession.peer.metadata.name, + authorizedAddresses, + createdAt: now.getTime(), + description: walletConnectSession.peer.metadata.description, + genesisHash: network.genesisHash, + genesisId: network.genesisId, + host: walletConnectSession.peer.metadata.url, + iconUrl: walletConnectSession.peer.metadata.icons[0] || null, + id, + usedAt: now.getTime(), + walletConnectMetadata: { + expiresAt: walletConnectSession.expiry, + namespaces: walletConnectSession.namespaces, + topic: walletConnectSession.topic, + }, + }; +} From 26bd48d831f1cadc999c428066c1dec18285de42 Mon Sep 17 00:00:00 2001 From: Kieran O'Neill Date: Thu, 15 Jun 2023 20:13:18 +0100 Subject: [PATCH 09/12] refactor: removed unused configs --- dapp/App.tsx | 23 ++++++++----------- .../WalletConnectModal/WalletConnectModal.tsx | 2 +- src/extension/config/index.ts | 2 -- .../config/walletConnectSupportedChains.ts | 10 -------- .../config/walletConnectSupportedMethods.ts | 6 ----- .../enums/WalletConnectChainsEnum.ts | 7 ------ src/extension/enums/index.ts | 1 - 7 files changed, 11 insertions(+), 40 deletions(-) delete mode 100644 src/extension/config/walletConnectSupportedChains.ts delete mode 100644 src/extension/config/walletConnectSupportedMethods.ts delete mode 100644 src/extension/enums/WalletConnectChainsEnum.ts diff --git a/dapp/App.tsx b/dapp/App.tsx index 8ed59ebe..4857aaad 100644 --- a/dapp/App.tsx +++ b/dapp/App.tsx @@ -39,11 +39,7 @@ import Fonts from '@extension/components/Fonts'; import WalletConnectIcon from '@extension/components/WalletConnectIcon'; // Config -import { - networks, - walletConnectSupportedChains, - walletConnectSupportedMethods, -} from '@extension/config'; +import { networks } from '@extension/config'; // Tabs import ApplicationActionsTab from './ApplicationActionsTab'; @@ -71,21 +67,22 @@ const App: FC = () => { isClosable: true, position: 'top', }); - const [enabledAccounts, setEnabledAccounts] = useState( - [] - ); - const [selectedAccount, setSelectedAccount] = - useState(null); - const [selectedNetwork, setSelectedNetwork] = useState(null); const { connect } = useConnect({ requiredNamespaces: { algorand: { - chains: walletConnectSupportedChains, + chains: ['algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDe'], // testnet events: [], - methods: walletConnectSupportedMethods, + methods: ['algorand_signTransaction', 'algorand_signMessage'], }, }, }); + // states + const [enabledAccounts, setEnabledAccounts] = useState( + [] + ); + const [selectedAccount, setSelectedAccount] = + useState(null); + const [selectedNetwork, setSelectedNetwork] = useState(null); const handleAddressSelect = (event: ChangeEvent) => { const account: IAccountInformation | null = enabledAccounts.find((value) => value.address === event.target.value) || diff --git a/src/extension/components/WalletConnectModal/WalletConnectModal.tsx b/src/extension/components/WalletConnectModal/WalletConnectModal.tsx index 02109d7c..8c415ffc 100644 --- a/src/extension/components/WalletConnectModal/WalletConnectModal.tsx +++ b/src/extension/components/WalletConnectModal/WalletConnectModal.tsx @@ -23,6 +23,7 @@ import { Rings } from 'react-loader-spinner'; // Components import Button from '@extension/components/Button'; import EmptyState from '@extension/components/EmptyState'; +import SessionRequestHeader from '@extension/components/SessionRequestHeader'; import WalletConnectBannerIcon from '@extension/components/WalletConnectBannerIcon'; // Constants @@ -56,7 +57,6 @@ import { IAccount, IAccountInformation, INetwork } from '@extension/types'; // Utils import { ellipseAddress } from '@extension/utils'; -import SessionRequestHeader from '@extension/components/SessionRequestHeader'; interface IProps { onClose: () => void; diff --git a/src/extension/config/index.ts b/src/extension/config/index.ts index 82d79d0f..1a250d9f 100644 --- a/src/extension/config/index.ts +++ b/src/extension/config/index.ts @@ -1,3 +1 @@ export { default as networks } from './networks'; -export { default as walletConnectSupportedChains } from './walletConnectSupportedChains'; -export { default as walletConnectSupportedMethods } from './walletConnectSupportedMethods'; diff --git a/src/extension/config/walletConnectSupportedChains.ts b/src/extension/config/walletConnectSupportedChains.ts deleted file mode 100644 index 1eed7cc1..00000000 --- a/src/extension/config/walletConnectSupportedChains.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Enums -import { WalletConnectChainsEnum } from '@extension/enums'; - -const walletConnectSupportedChains: string[] = [ - WalletConnectChainsEnum.AlgorandMainNet, - WalletConnectChainsEnum.AlgorandTestNet, - WalletConnectChainsEnum.AlgorandBetaNet, -]; - -export default walletConnectSupportedChains; diff --git a/src/extension/config/walletConnectSupportedMethods.ts b/src/extension/config/walletConnectSupportedMethods.ts deleted file mode 100644 index 55080de1..00000000 --- a/src/extension/config/walletConnectSupportedMethods.ts +++ /dev/null @@ -1,6 +0,0 @@ -const walletConnectSupportedMethods: string[] = [ - 'algorand_signTransaction', - 'algorand_signMessage', -]; - -export default walletConnectSupportedMethods; diff --git a/src/extension/enums/WalletConnectChainsEnum.ts b/src/extension/enums/WalletConnectChainsEnum.ts deleted file mode 100644 index 2aa6af7c..00000000 --- a/src/extension/enums/WalletConnectChainsEnum.ts +++ /dev/null @@ -1,7 +0,0 @@ -enum WalletConnectChainsEnum { - AlgorandBetaNet = 'algorand:mFgazF-2uRS1tMiL9dsj01hJGySEmPN2', - AlgorandMainNet = 'algorand:wGHE2Pwdvd7S12BL5FaOP20EGYesN73k', - AlgorandTestNet = 'algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDe', -} - -export default WalletConnectChainsEnum; diff --git a/src/extension/enums/index.ts b/src/extension/enums/index.ts index 1ba65f9c..8e170d6c 100644 --- a/src/extension/enums/index.ts +++ b/src/extension/enums/index.ts @@ -9,4 +9,3 @@ export { default as SettingsThunkEnum } from './SettingsThunkEnum'; export { default as StoreNameEnum } from './StoreNameEnum'; export { default as TransactionsThunkEnum } from './TransactionsThunkEnum'; export { default as TransactionTypeEnum } from './TransactionTypeEnum'; -export { default as WalletConnectChainsEnum } from './WalletConnectChainsEnum'; From c719ec3218308659e3096d9f3c3fccc5a6014e65 Mon Sep 17 00:00:00 2001 From: Kieran O'Neill Date: Thu, 15 Jun 2023 20:31:30 +0100 Subject: [PATCH 10/12] feat: disconnect walletconnect session when removing --- .../thunks/removeSessionByTopicThunk.ts | 15 ++++++++++ .../SessionsSettingsPage.tsx | 28 ++++++++++++++++--- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/extension/features/sessions/thunks/removeSessionByTopicThunk.ts b/src/extension/features/sessions/thunks/removeSessionByTopicThunk.ts index 84dc49d0..76ce3417 100644 --- a/src/extension/features/sessions/thunks/removeSessionByTopicThunk.ts +++ b/src/extension/features/sessions/thunks/removeSessionByTopicThunk.ts @@ -1,4 +1,6 @@ import { AsyncThunk, createAsyncThunk } from '@reduxjs/toolkit'; +import { IWeb3Wallet } from '@walletconnect/web3wallet/dist/types'; +import { getSdkError } from '@walletconnect/utils'; // Enums import { SessionsThunkEnum } from '@extension/enums'; @@ -18,6 +20,7 @@ const removeSessionByTopicThunk: AsyncThunk< SessionsThunkEnum.RemoveSessionByTopic, async (topic, { getState }) => { const logger: ILogger = getState().system.logger; + const web3Wallet: IWeb3Wallet | null = getState().sessions.web3Wallet; const sessionService: SessionService = new SessionService({ logger, }); @@ -33,6 +36,18 @@ const removeSessionByTopicThunk: AsyncThunk< await sessionService.removeById(session.id); + // disconnect the session with walletconnect + if (web3Wallet) { + logger.debug( + `${removeSessionByTopicThunk.name}: disconnecting walletconnect session for topic "${topic}"` + ); + + await web3Wallet.disconnectSession({ + topic, + reason: getSdkError('USER_DISCONNECTED'), + }); + } + return session.id; } ); diff --git a/src/extension/pages/SessionsSettingsPage/SessionsSettingsPage.tsx b/src/extension/pages/SessionsSettingsPage/SessionsSettingsPage.tsx index ea053f45..c785c6b0 100644 --- a/src/extension/pages/SessionsSettingsPage/SessionsSettingsPage.tsx +++ b/src/extension/pages/SessionsSettingsPage/SessionsSettingsPage.tsx @@ -13,11 +13,11 @@ import { faker } from '@faker-js/faker'; import { nanoid } from 'nanoid'; import React, { FC, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { IoAdd, IoLinkOutline } from 'react-icons/io5'; import { useDispatch } from 'react-redux'; // Components import Button from '@extension/components/Button'; +import EmptyState from '@extension/components/EmptyState'; import ManageSessionModal from '@extension/components/ManageSessionModal'; import PageHeader from '@extension/components/PageHeader'; import SettingsSessionItem from '@extension/components/SettingsSessionItem'; @@ -27,6 +27,7 @@ import { setConfirm } from '@extension/features/system'; import { clearSessionsThunk, removeSessionByIdThunk, + removeSessionByTopicThunk, } from '@extension/features/sessions'; // Hooks @@ -41,16 +42,19 @@ import { // Types import { IAppThunkDispatch, ISession } from '@extension/types'; -import EmptyState from '@extension/components/EmptyState'; const SessionsSettingsPage: FC = () => { const { t } = useTranslation(); const dispatch: IAppThunkDispatch = useDispatch(); + // selectors const fetching: boolean = useSelectFetchingSessions(); const sessions: ISession[] = useSelectSessions(); + // hooks const defaultSubTextColor: string = useSubTextColor(); const defaultTextColor: string = useDefaultTextColor(); + // states const [managedSession, setManagedSession] = useState(null); + // handlers const handleManageSessionClose = () => setManagedSession(null); const handleManageSession = (id: string) => setManagedSession(sessions.find((value) => value.id === id) || null); @@ -62,8 +66,24 @@ const SessionsSettingsPage: FC = () => { title: t('headings.removeAllSessions'), }) ); - const handleRemoveSession = (id: string) => - dispatch(removeSessionByIdThunk(id)); + const handleRemoveSession = (id: string) => { + const session: ISession | null = + sessions.find((value) => value.id === id) || null; + + if (session) { + // if this is a walletconnect session, remove by topic + if (session.walletConnectMetadata) { + dispatch( + removeSessionByTopicThunk(session.walletConnectMetadata.topic) + ); + + return; + } + + dispatch(removeSessionByIdThunk(id)); + } + }; + // misc const renderContent = () => { if (fetching) { return ( From bac4e983b351f0a86f91b664336c511302ce35bb Mon Sep 17 00:00:00 2001 From: Kieran O'Neill Date: Wed, 11 Oct 2023 10:21:15 +0300 Subject: [PATCH 11/12] refactor: remove use of nanoid --- dapp/App.tsx | 9 +- dapp/ApplicationActionsTab.tsx | 7 +- dapp/AssetActionsTab.tsx | 11 +- dapp/AtomicTransactionActionsTab.tsx | 15 ++- package.json | 1 - .../AccountActivityTab/AccountActivityTab.tsx | 14 ++- .../AccountAssetsTab/AccountAssetsTab.tsx | 9 +- .../AccountSelect/AccountSelect.tsx | 5 +- .../components/EnableModal/EnableModal.tsx | 17 ++- .../EnterMnemonicPhraseInput.tsx | 17 ++- .../ManageSessionModal/ManageSessionModal.tsx | 116 ++++++++++-------- .../NetworkSelect/NetworkSelect.tsx | 9 +- .../components/PillSwitch/PillSwitch.tsx | 5 +- .../SettingsSelectItem/SettingsSelectItem.tsx | 8 +- src/extension/components/SideBar/SideBar.tsx | 9 +- .../SignBytesModal/SignBytesModal.tsx | 5 +- .../MultipleTransactionsContent.tsx | 3 +- .../WalletConnectModal/WalletConnectModal.tsx | 17 ++- .../CreateNewAccountPage.tsx | 11 +- .../SessionsSettingsPage.tsx | 16 ++- .../ApplicationTransactionContent.tsx | 3 +- .../LoadingTransactionContent.tsx | 5 +- yarn.lock | 5 - 23 files changed, 184 insertions(+), 133 deletions(-) diff --git a/dapp/App.tsx b/dapp/App.tsx index 4857aaad..645e0d04 100644 --- a/dapp/App.tsx +++ b/dapp/App.tsx @@ -31,7 +31,6 @@ import { } from '@chakra-ui/react'; import { SessionTypes } from '@walletconnect/types'; import { Web3ModalSign, useConnect } from '@web3modal/sign-react'; -import { nanoid } from 'nanoid'; import React, { ChangeEvent, FC, useEffect, useState } from 'react'; // Components @@ -206,8 +205,8 @@ const App: FC = () => { - {enabledAccounts.map((value) => ( - + {enabledAccounts.map((value, index) => ( + {value.address} {value.name || '-'} @@ -262,8 +261,8 @@ const App: FC = () => { placeholder="Select an address" value={selectedAccount?.address || undefined} > - {enabledAccounts.map((value) => ( - ))} diff --git a/dapp/ApplicationActionsTab.tsx b/dapp/ApplicationActionsTab.tsx index 2f09f28c..ffddbfb8 100644 --- a/dapp/ApplicationActionsTab.tsx +++ b/dapp/ApplicationActionsTab.tsx @@ -28,7 +28,6 @@ import { SignedTransaction, Transaction, } from 'algosdk'; -import { nanoid } from 'nanoid'; import React, { ChangeEvent, FC, useState } from 'react'; // Enums @@ -211,8 +210,10 @@ const ApplicationActionsTab: FC = ({ type: TransactionTypeEnum.ApplicationUpdate, label: 'Send Update App Transaction', }, - ].map(({ label, type }) => ( - + ].map(({ label, type }, index) => ( +