From 957aea09d9b2037a64e6a8a52e9fde9a8b497425 Mon Sep 17 00:00:00 2001 From: Alexandr Kazachenko Date: Fri, 27 Dec 2024 16:30:46 +0500 Subject: [PATCH 1/3] chore: add reown packages --- package.json | 5 +- ...letconnect+universal-provider+2.10.2.patch | 11 - yarn.lock | 429 ++++++++++++++++-- 3 files changed, 399 insertions(+), 46 deletions(-) delete mode 100644 patches/@walletconnect+universal-provider+2.10.2.patch diff --git a/package.json b/package.json index 6d26d07d41..e97ff9f62c 100644 --- a/package.json +++ b/package.json @@ -107,6 +107,8 @@ "@react-hook/window-scroll": "^1.3.0", "@react-spring/web": "^9.6.1", "@reduxjs/toolkit": "^1.8.0", + "@reown/appkit": "^1.6.2", + "@reown/appkit-adapter-ethers5": "^1.6.2", "@rjsf/core": "^4.2.2", "@safe-global/api-kit": "^1.3.0", "@safe-global/protocol-kit": "^1.2.0", @@ -129,7 +131,6 @@ "@visx/glyph": "^3.3.0", "@visx/responsive": "^3.10.2", "@visx/shape": "^3.5.0", - "@walletconnect/ethereum-provider": "^2.10.2", "@web3-react/coinbase-wallet": "^8.2.3", "@web3-react/core": "^8.2.3", "@web3-react/eip1193": "^8.2.3", @@ -343,4 +344,4 @@ "vite-tsconfig-paths": "~4.3.2", "vitest": "~0.32.0" } -} \ No newline at end of file +} diff --git a/patches/@walletconnect+universal-provider+2.10.2.patch b/patches/@walletconnect+universal-provider+2.10.2.patch deleted file mode 100644 index c387a1fad7..0000000000 --- a/patches/@walletconnect+universal-provider+2.10.2.patch +++ /dev/null @@ -1,11 +0,0 @@ -diff --git a/node_modules/@walletconnect/universal-provider/dist/index.cjs.js b/node_modules/@walletconnect/universal-provider/dist/index.cjs.js -index d4fc0f5..7384e91 100644 ---- a/node_modules/@walletconnect/universal-provider/dist/index.cjs.js -+++ b/node_modules/@walletconnect/universal-provider/dist/index.cjs.js -@@ -24,5 +24,5 @@ __p += '`),H&&(m+=`' + - function print() { __p += __j.call(arguments, '') } - `:`; - `)+m+`return __p --}`;var b=_a(function(){return U(o,I+"return "+m).apply(i,f)});if(b.source=m,Ei(b))throw b;return b}function $d(n){return q(n).toLowerCase()}function Ud(n){return q(n).toUpperCase()}function qd(n,t,e){if(n=q(n),n&&(e||t===i))return ys(n);if(!n||!(t=pn(t)))return n;var r=On(n),s=On(t),o=Ss(r,s),f=Rs(r,s)+1;return at(r,o,f).join("")}function Wd(n,t,e){if(n=q(n),n&&(e||t===i))return n.slice(0,bs(n)+1);if(!n||!(t=pn(t)))return n;var r=On(n),s=Rs(r,On(t))+1;return at(r,0,s).join("")}function Fd(n,t,e){if(n=q(n),n&&(e||t===i))return n.replace(Er,"");if(!n||!(t=pn(t)))return n;var r=On(n),s=Ss(r,On(t));return at(r,s).join("")}function Md(n,t){var e=La,r=Da;if(z(t)){var s="separator"in t?t.separator:s;e="length"in t?O(t.length):e,r="omission"in t?pn(t.omission):r}n=q(n);var o=n.length;if(Dt(n)){var f=On(n);o=f.length}if(e>=o)return n;var c=e-Nt(r);if(c<1)return r;var l=f?at(f,0,c).join(""):n.slice(0,c);if(s===i)return l+r;if(f&&(c+=l.length-c),yi(s)){if(n.slice(c).search(s)){var v,_=l;for(s.global||(s=Br(s.source,q(Zi.exec(s))+"g")),s.lastIndex=0;v=s.exec(_);)var m=v.index;l=l.slice(0,m===i?c:m)}}else if(n.indexOf(pn(s),c)!=c){var P=l.lastIndexOf(s);P>-1&&(l=l.slice(0,P))}return l+r}function Bd(n){return n=q(n),n&&Va.test(n)?n.replace(zi,_f):n}var Gd=Mt(function(n,t,e){return n+(e?" ":"")+t.toUpperCase()}),Oi=mu("toUpperCase");function va(n,t,e){return n=q(n),t=e?i:t,t===i?lf(n)?Pf(n):ef(n):n.match(t)||[]}var _a=L(function(n,t){try{return hn(n,i,t)}catch(e){return Ei(e)?e:new S(e)}}),Kd=Yn(function(n,t){return wn(t,function(e){e=Wn(e),zn(n,e,Ii(n[e],n))}),n});function zd(n){var t=n==null?0:n.length,e=x();return n=t?G(n,function(r){if(typeof r[1]!="function")throw new Pn($);return[e(r[0]),r[1]]}):[],L(function(r){for(var s=-1;++sjn)return[];var e=$n,r=nn(n,$n);t=x(t),n-=$n;for(var s=Wr(r,t);++e0||t<0)?new N(e):(n<0?e=e.takeRight(-n):n&&(e=e.drop(n)),t!==i&&(t=O(t),e=t<0?e.dropRight(-t):e.take(t-n)),e)},N.prototype.takeRightWhile=function(n){return this.reverse().takeWhile(n).reverse()},N.prototype.toArray=function(){return this.take($n)},Un(N.prototype,function(n,t){var e=/^(?:filter|find|map|reject)|While$/.test(t),r=/^(?:head|last)$/.test(t),s=a[r?"take"+(t=="last"?"Right":""):t],o=r||/^find/.test(t);s&&(a.prototype[t]=function(){var f=this.__wrapped__,c=r?[1]:arguments,l=f instanceof N,v=c[0],_=l||R(f),m=function(D){var H=s.apply(a,tt([D],c));return r&&P?H[0]:H};_&&e&&typeof v=="function"&&v.length!=1&&(l=_=!1);var P=this.__chain__,I=!!this.__actions__.length,E=o&&!P,b=l&&!I;if(!o&&_){f=b?f:new N(this);var y=n.apply(f,c);return y.__actions__.push({func:er,args:[m],thisArg:i}),new An(y,P)}return E&&b?n.apply(this,c):(y=this.thru(m),E?r?y.value()[0]:y.value():y)})}),wn(["pop","push","shift","sort","splice","unshift"],function(n){var t=Re[n],e=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",r=/^(?:pop|shift)$/.test(n);a.prototype[n]=function(){var s=arguments;if(r&&!this.__chain__){var o=this.value();return t.apply(R(o)?o:[],s)}return this[e](function(f){return t.apply(R(f)?f:[],s)})}}),Un(N.prototype,function(n,t){var e=a[t];if(e){var r=e.name+"";W.call(qt,r)||(qt[r]=[]),qt[r].push({name:t,func:e})}}),qt[Xe(i,ht).name]=[{name:"wrapper",func:i}],N.prototype.clone=Bf,N.prototype.reverse=Gf,N.prototype.value=Kf,a.prototype.at=wl,a.prototype.chain=Pl,a.prototype.commit=Al,a.prototype.next=Cl,a.prototype.plant=xl,a.prototype.reverse=El,a.prototype.toJSON=a.prototype.valueOf=a.prototype.value=yl,a.prototype.first=a.prototype.head,te&&(a.prototype[te]=Il),a},Ht=Af();pt?((pt.exports=Ht)._=Ht,Tr._=Ht):k._=Ht}).call(ge)})(Ui,Ui.exports);var $g=Object.defineProperty,Ug=Object.defineProperties,qg=Object.getOwnPropertyDescriptors,Ea=Object.getOwnPropertySymbols,Wg=Object.prototype.hasOwnProperty,Fg=Object.prototype.propertyIsEnumerable,ya=(A,u,i)=>u in A?$g(A,u,{enumerable:!0,configurable:!0,writable:!0,value:i}):A[u]=i,cr=(A,u)=>{for(var i in u||(u={}))Wg.call(u,i)&&ya(A,i,u[i]);if(Ea)for(var i of Ea(u))Fg.call(u,i)&&ya(A,i,u[i]);return A},Mg=(A,u)=>Ug(A,qg(u));function ct(A,u,i){var d;const w=en.parseChainId(A);return((d=u.rpcMap)==null?void 0:d[w.reference])||`${Hg}?chainId=${w.namespace}:${w.reference}&projectId=${i}`}function It(A){return A.includes(":")?A.split(":")[1]:A}function Sa(A){return A.map(u=>`${u.split(":")[0]}:${u.split(":")[1]}`)}function Bg(A,u){const i=Object.keys(u.namespaces).filter(w=>w.includes(A));if(!i.length)return[];const d=[];return i.forEach(w=>{const T=u.namespaces[w].accounts;d.push(...T)}),d}function Gg(A={},u={}){const i=Ra(A),d=Ra(u);return Ui.exports.merge(i,d)}function Ra(A){var u,i,d,w;const T={};if(!en.isValidObject(A))return T;for(const[$,yn]of Object.entries(A)){const zt=en.isCaipNamespace($)?[$]:yn.chains,pr=yn.methods||[],xt=yn.events||[],Dn=yn.rpcMap||{},Fn=en.parseNamespaceKey($);T[Fn]=Mg(cr(cr({},T[Fn]),yn),{chains:en.mergeArrays(zt,(u=T[Fn])==null?void 0:u.chains),methods:en.mergeArrays(pr,(i=T[Fn])==null?void 0:i.methods),events:en.mergeArrays(xt,(d=T[Fn])==null?void 0:d.events),rpcMap:cr(cr({},Dn),(w=T[Fn])==null?void 0:w.rpcMap)})}return T}function Kg(A){return A.includes(":")?A.split(":")[2]:A}function zg(A){const u={};for(const[i,d]of Object.entries(A)){const w=d.methods||[],T=d.events||[],$=d.accounts||[],yn=en.isCaipNamespace(i)?[i]:d.chains?d.chains:Sa(d.accounts);u[i]={chains:yn,methods:w,events:T,accounts:$}}return u}function qi(A){return typeof A=="number"?A:A.includes("0x")?parseInt(A,16):A.includes(":")?Number(A.split(":")[1]):Number(A)}const Oa={},K=A=>Oa[A],Wi=(A,u)=>{Oa[A]=u};class Jg{constructor(u){this.name="polkadot",this.namespace=u.namespace,this.events=K("events"),this.client=K("client"),this.chainId=this.getDefaultChain(),this.httpProviders=this.createHttpProviders()}updateNamespace(u){this.namespace=Object.assign(this.namespace,u)}requestAccounts(){return this.getAccounts()}getDefaultChain(){if(this.chainId)return this.chainId;if(this.namespace.defaultChain)return this.namespace.defaultChain;const u=this.namespace.chains[0];if(!u)throw new Error("ChainId not found");return u.split(":")[1]}request(u){return this.namespace.methods.includes(u.request.method)?this.client.request(u):this.getHttpProvider().request(u.request)}setDefaultChain(u,i){this.httpProviders[u]||this.setHttpProvider(u,i),this.chainId=u,this.events.emit(kn.DEFAULT_CHAIN_CHANGED,`${this.name}:${u}`)}getAccounts(){const u=this.namespace.accounts;return u?u.filter(i=>i.split(":")[1]===this.chainId.toString()).map(i=>i.split(":")[2])||[]:[]}createHttpProviders(){const u={};return this.namespace.chains.forEach(i=>{var d;const w=It(i);u[w]=this.createHttpProvider(w,(d=this.namespace.rpcMap)==null?void 0:d[i])}),u}getHttpProvider(){const u=`${this.name}:${this.chainId}`,i=this.httpProviders[u];if(typeof i>"u")throw new Error(`JSON-RPC provider for ${u} not found`);return i}setHttpProvider(u,i){const d=this.createHttpProvider(u,i);d&&(this.httpProviders[u]=d)}createHttpProvider(u,i){const d=i||ct(u,this.namespace,this.client.core.projectId);if(!d)throw new Error(`No RPC url provided for chainId: ${u}`);return new ft.JsonRpcProvider(new Ct.default(d,K("disableProviderPing")))}}class Yg{constructor(u){this.name="eip155",this.namespace=u.namespace,this.events=K("events"),this.client=K("client"),this.httpProviders=this.createHttpProviders(),this.chainId=parseInt(this.getDefaultChain())}async request(u){switch(u.request.method){case"eth_requestAccounts":return this.getAccounts();case"eth_accounts":return this.getAccounts();case"wallet_switchEthereumChain":return await this.handleSwitchChain(u);case"eth_chainId":return parseInt(this.getDefaultChain())}return this.namespace.methods.includes(u.request.method)?await this.client.request(u):this.getHttpProvider().request(u.request)}updateNamespace(u){this.namespace=Object.assign(this.namespace,u)}setDefaultChain(u,i){this.httpProviders[u]||this.setHttpProvider(parseInt(u),i),this.chainId=parseInt(u),this.events.emit(kn.DEFAULT_CHAIN_CHANGED,`${this.name}:${u}`)}requestAccounts(){return this.getAccounts()}getDefaultChain(){if(this.chainId)return this.chainId.toString();if(this.namespace.defaultChain)return this.namespace.defaultChain;const u=this.namespace.chains[0];if(!u)throw new Error("ChainId not found");return u.split(":")[1]}createHttpProvider(u,i){const d=i||ct(`${this.name}:${u}`,this.namespace,this.client.core.projectId);if(!d)throw new Error(`No RPC url provided for chainId: ${u}`);return new ft.JsonRpcProvider(new Ca.HttpConnection(d,K("disableProviderPing")))}setHttpProvider(u,i){const d=this.createHttpProvider(u,i);d&&(this.httpProviders[u]=d)}createHttpProviders(){const u={};return this.namespace.chains.forEach(i=>{var d;const w=parseInt(It(i));u[w]=this.createHttpProvider(w,(d=this.namespace.rpcMap)==null?void 0:d[i])}),u}getAccounts(){const u=this.namespace.accounts;return u?[...new Set(u.filter(i=>i.split(":")[1]===this.chainId.toString()).map(i=>i.split(":")[2]))]:[]}getHttpProvider(){const u=this.chainId,i=this.httpProviders[u];if(typeof i>"u")throw new Error(`JSON-RPC provider for ${u} not found`);return i}async handleSwitchChain(u){var i,d;let w=u.request.params?(i=u.request.params[0])==null?void 0:i.chainId:"0x0";w=w.startsWith("0x")?w:`0x${w}`;const T=parseInt(w,16);if(this.isChainApproved(T))this.setDefaultChain(`${T}`);else if(this.namespace.methods.includes("wallet_switchEthereumChain"))await this.client.request({topic:u.topic,request:{method:u.request.method,params:[{chainId:w}]},chainId:(d=this.namespace.chains)==null?void 0:d[0]}),this.setDefaultChain(`${T}`);else throw new Error(`Failed to switch to chain 'eip155:${T}'. The chain is not approved or the wallet does not support 'wallet_switchEthereumChain' method.`);return null}isChainApproved(u){return this.namespace.chains.includes(`${this.name}:${u}`)}}class Zg{constructor(u){this.name="solana",this.namespace=u.namespace,this.events=K("events"),this.client=K("client"),this.chainId=this.getDefaultChain(),this.httpProviders=this.createHttpProviders()}updateNamespace(u){this.namespace=Object.assign(this.namespace,u)}requestAccounts(){return this.getAccounts()}request(u){return this.namespace.methods.includes(u.request.method)?this.client.request(u):this.getHttpProvider().request(u.request)}setDefaultChain(u,i){this.httpProviders[u]||this.setHttpProvider(u,i),this.chainId=u,this.events.emit(kn.DEFAULT_CHAIN_CHANGED,`${this.name}:${u}`)}getDefaultChain(){if(this.chainId)return this.chainId;if(this.namespace.defaultChain)return this.namespace.defaultChain;const u=this.namespace.chains[0];if(!u)throw new Error("ChainId not found");return u.split(":")[1]}getAccounts(){const u=this.namespace.accounts;return u?[...new Set(u.filter(i=>i.split(":")[1]===this.chainId.toString()).map(i=>i.split(":")[2]))]:[]}createHttpProviders(){const u={};return this.namespace.chains.forEach(i=>{var d;const w=It(i);u[w]=this.createHttpProvider(w,(d=this.namespace.rpcMap)==null?void 0:d[i])}),u}getHttpProvider(){const u=`${this.name}:${this.chainId}`,i=this.httpProviders[u];if(typeof i>"u")throw new Error(`JSON-RPC provider for ${u} not found`);return i}setHttpProvider(u,i){const d=this.createHttpProvider(u,i);d&&(this.httpProviders[u]=d)}createHttpProvider(u,i){const d=i||ct(u,this.namespace,this.client.core.projectId);if(!d)throw new Error(`No RPC url provided for chainId: ${u}`);return new ft.JsonRpcProvider(new Ct.default(d,K("disableProviderPing")))}}class Xg{constructor(u){this.name="cosmos",this.namespace=u.namespace,this.events=K("events"),this.client=K("client"),this.chainId=this.getDefaultChain(),this.httpProviders=this.createHttpProviders()}updateNamespace(u){this.namespace=Object.assign(this.namespace,u)}requestAccounts(){return this.getAccounts()}getDefaultChain(){if(this.chainId)return this.chainId;if(this.namespace.defaultChain)return this.namespace.defaultChain;const u=this.namespace.chains[0];if(!u)throw new Error("ChainId not found");return u.split(":")[1]}request(u){return this.namespace.methods.includes(u.request.method)?this.client.request(u):this.getHttpProvider().request(u.request)}setDefaultChain(u,i){this.httpProviders[u]||this.setHttpProvider(u,i),this.chainId=u,this.events.emit(kn.DEFAULT_CHAIN_CHANGED,`${this.name}:${this.chainId}`)}getAccounts(){const u=this.namespace.accounts;return u?[...new Set(u.filter(i=>i.split(":")[1]===this.chainId.toString()).map(i=>i.split(":")[2]))]:[]}createHttpProviders(){const u={};return this.namespace.chains.forEach(i=>{var d;const w=It(i);u[w]=this.createHttpProvider(w,(d=this.namespace.rpcMap)==null?void 0:d[i])}),u}getHttpProvider(){const u=`${this.name}:${this.chainId}`,i=this.httpProviders[u];if(typeof i>"u")throw new Error(`JSON-RPC provider for ${u} not found`);return i}setHttpProvider(u,i){const d=this.createHttpProvider(u,i);d&&(this.httpProviders[u]=d)}createHttpProvider(u,i){const d=i||ct(u,this.namespace,this.client.core.projectId);if(!d)throw new Error(`No RPC url provided for chainId: ${u}`);return new ft.JsonRpcProvider(new Ct.default(d,K("disableProviderPing")))}}class Qg{constructor(u){this.name="cip34",this.namespace=u.namespace,this.events=K("events"),this.client=K("client"),this.chainId=this.getDefaultChain(),this.httpProviders=this.createHttpProviders()}updateNamespace(u){this.namespace=Object.assign(this.namespace,u)}requestAccounts(){return this.getAccounts()}getDefaultChain(){if(this.chainId)return this.chainId;if(this.namespace.defaultChain)return this.namespace.defaultChain;const u=this.namespace.chains[0];if(!u)throw new Error("ChainId not found");return u.split(":")[1]}request(u){return this.namespace.methods.includes(u.request.method)?this.client.request(u):this.getHttpProvider().request(u.request)}setDefaultChain(u,i){this.httpProviders[u]||this.setHttpProvider(u,i),this.chainId=u,this.events.emit(kn.DEFAULT_CHAIN_CHANGED,`${this.name}:${this.chainId}`)}getAccounts(){const u=this.namespace.accounts;return u?[...new Set(u.filter(i=>i.split(":")[1]===this.chainId.toString()).map(i=>i.split(":")[2]))]:[]}createHttpProviders(){const u={};return this.namespace.chains.forEach(i=>{const d=this.getCardanoRPCUrl(i),w=It(i);u[w]=this.createHttpProvider(w,d)}),u}getHttpProvider(){const u=`${this.name}:${this.chainId}`,i=this.httpProviders[u];if(typeof i>"u")throw new Error(`JSON-RPC provider for ${u} not found`);return i}getCardanoRPCUrl(u){const i=this.namespace.rpcMap;if(i)return i[u]}setHttpProvider(u,i){const d=this.createHttpProvider(u,i);d&&(this.httpProviders[u]=d)}createHttpProvider(u,i){const d=i||this.getCardanoRPCUrl(u);if(!d)throw new Error(`No RPC url provided for chainId: ${u}`);return new ft.JsonRpcProvider(new Ct.default(d,K("disableProviderPing")))}}class Vg{constructor(u){this.name="elrond",this.namespace=u.namespace,this.events=K("events"),this.client=K("client"),this.chainId=this.getDefaultChain(),this.httpProviders=this.createHttpProviders()}updateNamespace(u){this.namespace=Object.assign(this.namespace,u)}requestAccounts(){return this.getAccounts()}request(u){return this.namespace.methods.includes(u.request.method)?this.client.request(u):this.getHttpProvider().request(u.request)}setDefaultChain(u,i){this.httpProviders[u]||this.setHttpProvider(u,i),this.chainId=u,this.events.emit(kn.DEFAULT_CHAIN_CHANGED,`${this.name}:${u}`)}getDefaultChain(){if(this.chainId)return this.chainId;if(this.namespace.defaultChain)return this.namespace.defaultChain;const u=this.namespace.chains[0];if(!u)throw new Error("ChainId not found");return u.split(":")[1]}getAccounts(){const u=this.namespace.accounts;return u?[...new Set(u.filter(i=>i.split(":")[1]===this.chainId.toString()).map(i=>i.split(":")[2]))]:[]}createHttpProviders(){const u={};return this.namespace.chains.forEach(i=>{var d;const w=It(i);u[w]=this.createHttpProvider(w,(d=this.namespace.rpcMap)==null?void 0:d[i])}),u}getHttpProvider(){const u=`${this.name}:${this.chainId}`,i=this.httpProviders[u];if(typeof i>"u")throw new Error(`JSON-RPC provider for ${u} not found`);return i}setHttpProvider(u,i){const d=this.createHttpProvider(u,i);d&&(this.httpProviders[u]=d)}createHttpProvider(u,i){const d=i||ct(u,this.namespace,this.client.core.projectId);if(!d)throw new Error(`No RPC url provided for chainId: ${u}`);return new ft.JsonRpcProvider(new Ct.default(d,K("disableProviderPing")))}}class kg{constructor(u){this.name="multiversx",this.namespace=u.namespace,this.events=K("events"),this.client=K("client"),this.chainId=this.getDefaultChain(),this.httpProviders=this.createHttpProviders()}updateNamespace(u){this.namespace=Object.assign(this.namespace,u)}requestAccounts(){return this.getAccounts()}request(u){return this.namespace.methods.includes(u.request.method)?this.client.request(u):this.getHttpProvider().request(u.request)}setDefaultChain(u,i){this.httpProviders[u]||this.setHttpProvider(u,i),this.chainId=u,this.events.emit(kn.DEFAULT_CHAIN_CHANGED,`${this.name}:${u}`)}getDefaultChain(){if(this.chainId)return this.chainId;if(this.namespace.defaultChain)return this.namespace.defaultChain;const u=this.namespace.chains[0];if(!u)throw new Error("ChainId not found");return u.split(":")[1]}getAccounts(){const u=this.namespace.accounts;return u?[...new Set(u.filter(i=>i.split(":")[1]===this.chainId.toString()).map(i=>i.split(":")[2]))]:[]}createHttpProviders(){const u={};return this.namespace.chains.forEach(i=>{var d;const w=It(i);u[w]=this.createHttpProvider(w,(d=this.namespace.rpcMap)==null?void 0:d[i])}),u}getHttpProvider(){const u=`${this.name}:${this.chainId}`,i=this.httpProviders[u];if(typeof i>"u")throw new Error(`JSON-RPC provider for ${u} not found`);return i}setHttpProvider(u,i){const d=this.createHttpProvider(u,i);d&&(this.httpProviders[u]=d)}createHttpProvider(u,i){const d=i||ct(u,this.namespace,this.client.core.projectId);if(!d)throw new Error(`No RPC url provided for chainId: ${u}`);return new ft.JsonRpcProvider(new Ct.default(d,K("disableProviderPing")))}}class jg{constructor(u){this.name="near",this.namespace=u.namespace,this.events=K("events"),this.client=K("client"),this.chainId=this.getDefaultChain(),this.httpProviders=this.createHttpProviders()}updateNamespace(u){this.namespace=Object.assign(this.namespace,u)}requestAccounts(){return this.getAccounts()}getDefaultChain(){if(this.chainId)return this.chainId;if(this.namespace.defaultChain)return this.namespace.defaultChain;const u=this.namespace.chains[0];if(!u)throw new Error("ChainId not found");return u.split(":")[1]}request(u){return this.namespace.methods.includes(u.request.method)?this.client.request(u):this.getHttpProvider().request(u.request)}setDefaultChain(u,i){if(this.chainId=u,!this.httpProviders[u]){const d=i||ct(`${this.name}:${u}`,this.namespace);if(!d)throw new Error(`No RPC url provided for chainId: ${u}`);this.setHttpProvider(u,d)}this.events.emit(kn.DEFAULT_CHAIN_CHANGED,`${this.name}:${this.chainId}`)}getAccounts(){const u=this.namespace.accounts;return u?u.filter(i=>i.split(":")[1]===this.chainId.toString()).map(i=>i.split(":")[2])||[]:[]}createHttpProviders(){const u={};return this.namespace.chains.forEach(i=>{var d;u[i]=this.createHttpProvider(i,(d=this.namespace.rpcMap)==null?void 0:d[i])}),u}getHttpProvider(){const u=`${this.name}:${this.chainId}`,i=this.httpProviders[u];if(typeof i>"u")throw new Error(`JSON-RPC provider for ${u} not found`);return i}setHttpProvider(u,i){const d=this.createHttpProvider(u,i);d&&(this.httpProviders[u]=d)}createHttpProvider(u,i){const d=i||ct(u,this.namespace);return typeof d>"u"?void 0:new ft.JsonRpcProvider(new Ct.default(d,K("disableProviderPing")))}}var nv=Object.defineProperty,tv=Object.defineProperties,ev=Object.getOwnPropertyDescriptors,ba=Object.getOwnPropertySymbols,rv=Object.prototype.hasOwnProperty,iv=Object.prototype.propertyIsEnumerable,Ta=(A,u,i)=>u in A?nv(A,u,{enumerable:!0,configurable:!0,writable:!0,value:i}):A[u]=i,hr=(A,u)=>{for(var i in u||(u={}))rv.call(u,i)&&Ta(A,i,u[i]);if(ba)for(var i of ba(u))iv.call(u,i)&&Ta(A,i,u[i]);return A},Fi=(A,u)=>tv(A,ev(u));class lr{constructor(u){this.events=new Tg.default,this.rpcProviders={},this.shouldAbortPairingAttempt=!1,this.maxPairingAttempts=10,this.disableProviderPing=!1,this.providerOpts=u,this.logger=typeof u?.logger<"u"&&typeof u?.logger!="string"?u.logger:Aa.pino(Aa.getDefaultLoggerOptions({level:u?.logger||Ia})),this.disableProviderPing=u?.disableProviderPing||!1}static async init(u){const i=new lr(u);return await i.initialize(),i}async request(u,i){const[d,w]=this.validateChain(i);if(!this.session)throw new Error("Please call connect() before request()");return await this.getProvider(d).request({request:hr({},u),chainId:`${d}:${w}`,topic:this.session.topic})}sendAsync(u,i,d){this.request(u,d).then(w=>i(null,w)).catch(w=>i(w,void 0))}async enable(){if(!this.client)throw new Error("Sign Client not initialized");return this.session||await this.connect({namespaces:this.namespaces,optionalNamespaces:this.optionalNamespaces,sessionProperties:this.sessionProperties}),await this.requestAccounts()}async disconnect(){var u;if(!this.session)throw new Error("Please call connect() before enable()");await this.client.disconnect({topic:(u=this.session)==null?void 0:u.topic,reason:en.getSdkError("USER_DISCONNECTED")}),await this.cleanup()}async connect(u){if(!this.client)throw new Error("Sign Client not initialized");if(this.setNamespaces(u),await this.cleanupPendingPairings(),!u.skipPairing)return await this.pair(u.pairingTopic)}on(u,i){this.events.on(u,i)}once(u,i){this.events.once(u,i)}removeListener(u,i){this.events.removeListener(u,i)}off(u,i){this.events.off(u,i)}get isWalletConnect(){return!0}async pair(u){this.shouldAbortPairingAttempt=!1;let i=0;do{if(this.shouldAbortPairingAttempt)throw new Error("Pairing aborted");if(i>=this.maxPairingAttempts)throw new Error("Max auto pairing attempts reached");const{uri:d,approval:w}=await this.client.connect({pairingTopic:u,requiredNamespaces:this.namespaces,optionalNamespaces:this.optionalNamespaces,sessionProperties:this.sessionProperties});d&&(this.uri=d,this.events.emit("display_uri",d)),await w().then(T=>{this.session=T,this.namespaces||(this.namespaces=zg(T.namespaces),this.persist("namespaces",this.namespaces))}).catch(T=>{if(T.message!==Pa.PROPOSAL_EXPIRY_MESSAGE)throw T;i++})}while(!this.session);return this.onConnect(),this.session}setDefaultChain(u,i){try{if(!this.session)return;const[d,w]=this.validateChain(u);this.getProvider(d).setDefaultChain(w,i)}catch(d){if(!/Please call connect/.test(d.message))throw d}}async cleanupPendingPairings(u={}){this.logger.info("Cleaning up inactive pairings...");const i=this.client.pairing.getAll();if(en.isValidArray(i)){for(const d of i)u.deletePairings?this.client.core.expirer.set(d.topic,0):await this.client.core.relayer.subscriber.unsubscribe(d.topic);this.logger.info(`Inactive pairings cleared: ${i.length}`)}}abortPairingAttempt(){this.shouldAbortPairingAttempt=!0}async checkStorage(){if(this.namespaces=await this.getFromStore("namespaces"),this.optionalNamespaces=await this.getFromStore("optionalNamespaces")||{},this.client.session.length){const u=this.client.session.keys.length-1;this.session=this.client.session.get(this.client.session.keys[u]),this.createProviders()}}async initialize(){this.logger.trace("Initialized"),await this.createClient(),await this.checkStorage(),this.registerEventListeners()}async createClient(){this.client=this.providerOpts.client||await bg.default.init({logger:this.providerOpts.logger||Ia,relayUrl:this.providerOpts.relayUrl||Lg,projectId:this.providerOpts.projectId,metadata:this.providerOpts.metadata,storageOptions:this.providerOpts.storageOptions,storage:this.providerOpts.storage,name:this.providerOpts.name}),this.logger.trace("SignClient Initialized")}createProviders(){if(!this.client)throw new Error("Sign Client not initialized");if(!this.session)throw new Error("Session not initialized. Please call connect() before enable()");const u=[...new Set(Object.keys(this.session.namespaces).map(i=>en.parseNamespaceKey(i)))];Wi("client",this.client),Wi("events",this.events),Wi("disableProviderPing",this.disableProviderPing),u.forEach(i=>{if(!this.session)return;const d=Bg(i,this.session),w=Sa(d),T=Gg(this.namespaces,this.optionalNamespaces),$=Fi(hr({},T[i]),{accounts:d,chains:w});switch(i){case"eip155":this.rpcProviders[i]=new Yg({namespace:$});break;case"solana":this.rpcProviders[i]=new Zg({namespace:$});break;case"cosmos":this.rpcProviders[i]=new Xg({namespace:$});break;case"polkadot":this.rpcProviders[i]=new Jg({namespace:$});break;case"cip34":this.rpcProviders[i]=new Qg({namespace:$});break;case"elrond":this.rpcProviders[i]=new Vg({namespace:$});break;case"multiversx":this.rpcProviders[i]=new kg({namespace:$});break;case"near":this.rpcProviders[i]=new jg({namespace:$});break}})}registerEventListeners(){if(typeof this.client>"u")throw new Error("Sign Client is not initialized");this.client.on("session_ping",u=>{this.events.emit("session_ping",u)}),this.client.on("session_event",u=>{const{params:i}=u,{event:d}=i;if(d.name==="accountsChanged"){const w=d.data;w&&en.isValidArray(w)&&this.events.emit("accountsChanged",w.map(Kg))}else if(d.name==="chainChanged"){const w=i.chainId,T=i.event.data,$=en.parseNamespaceKey(w),yn=qi(w)!==qi(T)?`${$}:${qi(T)}`:w;this.onChainChanged(yn)}else this.events.emit(d.name,d.data);this.events.emit("session_event",u)}),this.client.on("session_update",({topic:u,params:i})=>{var d;const{namespaces:w}=i,T=(d=this.client)==null?void 0:d.session.get(u);this.session=Fi(hr({},T),{namespaces:w}),this.onSessionUpdate(),this.events.emit("session_update",{topic:u,params:i})}),this.client.on("session_delete",async u=>{await this.cleanup(),this.events.emit("session_delete",u),this.events.emit("disconnect",Fi(hr({},en.getSdkError("USER_DISCONNECTED")),{data:u.topic}))}),this.on(kn.DEFAULT_CHAIN_CHANGED,u=>{this.onChainChanged(u,!0)})}getProvider(u){if(!this.rpcProviders[u])throw new Error(`Provider not found: ${u}`);return this.rpcProviders[u]}onSessionUpdate(){Object.keys(this.rpcProviders).forEach(u=>{var i;this.getProvider(u).updateNamespace((i=this.session)==null?void 0:i.namespaces[u])})}setNamespaces(u){const{namespaces:i,optionalNamespaces:d,sessionProperties:w}=u;i&&Object.keys(i).length&&(this.namespaces=i),d&&Object.keys(d).length&&(this.optionalNamespaces=d),this.sessionProperties=w,this.persist("namespaces",i),this.persist("optionalNamespaces",d)}validateChain(u){const[i,d]=u?.split(":")||["",""];if(!this.namespaces||!Object.keys(this.namespaces).length)return[i,d];if(i&&!Object.keys(this.namespaces||{}).map($=>en.parseNamespaceKey($)).includes(i))throw new Error(`Namespace '${i}' is not configured. Please call connect() first with namespace config.`);if(i&&d)return[i,d];const w=en.parseNamespaceKey(Object.keys(this.namespaces)[0]),T=this.rpcProviders[w].getDefaultChain();return[w,T]}async requestAccounts(){const[u]=this.validateChain();return await this.getProvider(u).requestAccounts()}onChainChanged(u,i=!1){var d;if(!this.namespaces)return;const[w,T]=this.validateChain(u);i||this.getProvider(w).setDefaultChain(T),((d=this.namespaces[w])!=null?d:this.namespaces[`${w}:${T}`]).defaultChain=T,this.persist("namespaces",this.namespaces),this.events.emit("chainChanged",T)}onConnect(){this.createProviders(),this.events.emit("connect",{session:this.session})}async cleanup(){this.session=void 0,this.namespaces=void 0,this.optionalNamespaces=void 0,this.sessionProperties=void 0,this.persist("namespaces",void 0),this.persist("optionalNamespaces",void 0),this.persist("sessionProperties",void 0),await this.cleanupPendingPairings({deletePairings:!0})}persist(u,i){this.client.core.storage.setItem(`${xa}/${u}`,i)}async getFromStore(u){return await this.client.core.storage.getItem(`${xa}/${u}`)}}const sv=lr;exports.UniversalProvider=sv,exports.default=lr; -+}`;var b=_a(function(){return U(o,I+"return "+m).apply(i,f)});if(b.source=m,Ei(b))throw b;return b}function $d(n){return q(n).toLowerCase()}function Ud(n){return q(n).toUpperCase()}function qd(n,t,e){if(n=q(n),n&&(e||t===i))return ys(n);if(!n||!(t=pn(t)))return n;var r=On(n),s=On(t),o=Ss(r,s),f=Rs(r,s)+1;return at(r,o,f).join("")}function Wd(n,t,e){if(n=q(n),n&&(e||t===i))return n.slice(0,bs(n)+1);if(!n||!(t=pn(t)))return n;var r=On(n),s=Rs(r,On(t))+1;return at(r,0,s).join("")}function Fd(n,t,e){if(n=q(n),n&&(e||t===i))return n.replace(Er,"");if(!n||!(t=pn(t)))return n;var r=On(n),s=Ss(r,On(t));return at(r,s).join("")}function Md(n,t){var e=La,r=Da;if(z(t)){var s="separator"in t?t.separator:s;e="length"in t?O(t.length):e,r="omission"in t?pn(t.omission):r}n=q(n);var o=n.length;if(Dt(n)){var f=On(n);o=f.length}if(e>=o)return n;var c=e-Nt(r);if(c<1)return r;var l=f?at(f,0,c).join(""):n.slice(0,c);if(s===i)return l+r;if(f&&(c+=l.length-c),yi(s)){if(n.slice(c).search(s)){var v,_=l;for(s.global||(s=Br(s.source,q(Zi.exec(s))+"g")),s.lastIndex=0;v=s.exec(_);)var m=v.index;l=l.slice(0,m===i?c:m)}}else if(n.indexOf(pn(s),c)!=c){var P=l.lastIndexOf(s);P>-1&&(l=l.slice(0,P))}return l+r}function Bd(n){return n=q(n),n&&Va.test(n)?n.replace(zi,_f):n}var Gd=Mt(function(n,t,e){return n+(e?" ":"")+t.toUpperCase()}),Oi=mu("toUpperCase");function va(n,t,e){return n=q(n),t=e?i:t,t===i?lf(n)?Pf(n):ef(n):n.match(t)||[]}var _a=L(function(n,t){try{return hn(n,i,t)}catch(e){return Ei(e)?e:new S(e)}}),Kd=Yn(function(n,t){return wn(t,function(e){e=Wn(e),zn(n,e,Ii(n[e],n))}),n});function zd(n){var t=n==null?0:n.length,e=x();return n=t?G(n,function(r){if(typeof r[1]!="function")throw new Pn($);return[e(r[0]),r[1]]}):[],L(function(r){for(var s=-1;++sjn)return[];var e=$n,r=nn(n,$n);t=x(t),n-=$n;for(var s=Wr(r,t);++e0||t<0)?new N(e):(n<0?e=e.takeRight(-n):n&&(e=e.drop(n)),t!==i&&(t=O(t),e=t<0?e.dropRight(-t):e.take(t-n)),e)},N.prototype.takeRightWhile=function(n){return this.reverse().takeWhile(n).reverse()},N.prototype.toArray=function(){return this.take($n)},Un(N.prototype,function(n,t){var e=/^(?:filter|find|map|reject)|While$/.test(t),r=/^(?:head|last)$/.test(t),s=a[r?"take"+(t=="last"?"Right":""):t],o=r||/^find/.test(t);s&&(a.prototype[t]=function(){var f=this.__wrapped__,c=r?[1]:arguments,l=f instanceof N,v=c[0],_=l||R(f),m=function(D){var H=s.apply(a,tt([D],c));return r&&P?H[0]:H};_&&e&&typeof v=="function"&&v.length!=1&&(l=_=!1);var P=this.__chain__,I=!!this.__actions__.length,E=o&&!P,b=l&&!I;if(!o&&_){f=b?f:new N(this);var y=n.apply(f,c);return y.__actions__.push({func:er,args:[m],thisArg:i}),new An(y,P)}return E&&b?n.apply(this,c):(y=this.thru(m),E?r?y.value()[0]:y.value():y)})}),wn(["pop","push","shift","sort","splice","unshift"],function(n){var t=Re[n],e=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",r=/^(?:pop|shift)$/.test(n);a.prototype[n]=function(){var s=arguments;if(r&&!this.__chain__){var o=this.value();return t.apply(R(o)?o:[],s)}return this[e](function(f){return t.apply(R(f)?f:[],s)})}}),Un(N.prototype,function(n,t){var e=a[t];if(e){var r=e.name+"";W.call(qt,r)||(qt[r]=[]),qt[r].push({name:t,func:e})}}),qt[Xe(i,ht).name]=[{name:"wrapper",func:i}],N.prototype.clone=Bf,N.prototype.reverse=Gf,N.prototype.value=Kf,a.prototype.at=wl,a.prototype.chain=Pl,a.prototype.commit=Al,a.prototype.next=Cl,a.prototype.plant=xl,a.prototype.reverse=El,a.prototype.toJSON=a.prototype.valueOf=a.prototype.value=yl,a.prototype.first=a.prototype.head,te&&(a.prototype[te]=Il),a},Ht=Af();pt?((pt.exports=Ht)._=Ht,Tr._=Ht):k._=Ht}).call(ge)})(Ui,Ui.exports);var $g=Object.defineProperty,Ug=Object.defineProperties,qg=Object.getOwnPropertyDescriptors,Ea=Object.getOwnPropertySymbols,Wg=Object.prototype.hasOwnProperty,Fg=Object.prototype.propertyIsEnumerable,ya=(A,u,i)=>u in A?$g(A,u,{enumerable:!0,configurable:!0,writable:!0,value:i}):A[u]=i,cr=(A,u)=>{for(var i in u||(u={}))Wg.call(u,i)&&ya(A,i,u[i]);if(Ea)for(var i of Ea(u))Fg.call(u,i)&&ya(A,i,u[i]);return A},Mg=(A,u)=>Ug(A,qg(u));function ct(A,u,i){var d;const w=en.parseChainId(A);return((d=u.rpcMap)==null?void 0:d[w.reference])||`${Hg}?chainId=${w.namespace}:${w.reference}&projectId=${i}`}function It(A){return A.includes(":")?A.split(":")[1]:A}function Sa(A){return A.map(u=>`${u.split(":")[0]}:${u.split(":")[1]}`)}function Bg(A,u){const i=Object.keys(u.namespaces).filter(w=>w.includes(A));if(!i.length)return[];const d=[];return i.forEach(w=>{const T=u.namespaces[w].accounts;d.push(...T)}),d}function Gg(A={},u={}){const i=Ra(A),d=Ra(u);return Ui.exports.merge(i,d)}function Ra(A){var u,i,d,w;const T={};if(!en.isValidObject(A))return T;for(const[$,yn]of Object.entries(A)){const zt=en.isCaipNamespace($)?[$]:yn.chains,pr=yn.methods||[],xt=yn.events||[],Dn=yn.rpcMap||{},Fn=en.parseNamespaceKey($);T[Fn]=Mg(cr(cr({},T[Fn]),yn),{chains:en.mergeArrays(zt,(u=T[Fn])==null?void 0:u.chains),methods:en.mergeArrays(pr,(i=T[Fn])==null?void 0:i.methods),events:en.mergeArrays(xt,(d=T[Fn])==null?void 0:d.events),rpcMap:cr(cr({},Dn),(w=T[Fn])==null?void 0:w.rpcMap)})}return T}function Kg(A){return A.includes(":")?A.split(":")[2]:A}function zg(A){const u={};for(const[i,d]of Object.entries(A)){const w=d.methods||[],T=d.events||[],$=d.accounts||[],yn=en.isCaipNamespace(i)?[i]:d.chains?d.chains:Sa(d.accounts);u[i]={chains:yn,methods:w,events:T,accounts:$}}return u}function qi(A){return typeof A=="number"?A:A.includes("0x")?parseInt(A,16):A.includes(":")?Number(A.split(":")[1]):Number(A)}const Oa={},K=A=>Oa[A],Wi=(A,u)=>{Oa[A]=u};class Jg{constructor(u){this.name="polkadot",this.namespace=u.namespace,this.events=K("events"),this.client=K("client"),this.chainId=this.getDefaultChain(),this.httpProviders=this.createHttpProviders()}updateNamespace(u){this.namespace=Object.assign(this.namespace,u)}requestAccounts(){return this.getAccounts()}getDefaultChain(){if(this.chainId)return this.chainId;if(this.namespace.defaultChain)return this.namespace.defaultChain;const u=this.namespace.chains[0];if(!u)throw new Error("ChainId not found");return u.split(":")[1]}request(u){return this.namespace.methods.includes(u.request.method)?this.client.request(u):this.getHttpProvider().request(u.request)}setDefaultChain(u,i){this.httpProviders[u]||this.setHttpProvider(u,i),this.chainId=u,this.events.emit(kn.DEFAULT_CHAIN_CHANGED,`${this.name}:${u}`)}getAccounts(){const u=this.namespace.accounts;return u?u.filter(i=>i.split(":")[1]===this.chainId.toString()).map(i=>i.split(":")[2])||[]:[]}createHttpProviders(){const u={};return this.namespace.chains.forEach(i=>{var d;const w=It(i);u[w]=this.createHttpProvider(w,(d=this.namespace.rpcMap)==null?void 0:d[i])}),u}getHttpProvider(){const u=`${this.name}:${this.chainId}`,i=this.httpProviders[u];if(typeof i>"u")throw new Error(`JSON-RPC provider for ${u} not found`);return i}setHttpProvider(u,i){const d=this.createHttpProvider(u,i);d&&(this.httpProviders[u]=d)}createHttpProvider(u,i){const d=i||ct(u,this.namespace,this.client.core.projectId);if(!d)throw new Error(`No RPC url provided for chainId: ${u}`);return new ft.JsonRpcProvider(new Ct.default(d,K("disableProviderPing")))}}class Yg{constructor(u){this.name="eip155",this.namespace=u.namespace,this.events=K("events"),this.client=K("client"),this.httpProviders=this.createHttpProviders(),this.chainId=parseInt(this.getDefaultChain())}async request(u){switch(u.request.method){case"eth_requestAccounts":return this.getAccounts();case"eth_accounts":return this.getAccounts();case"wallet_switchEthereumChain":return await this.handleSwitchChain(u);case"eth_chainId":return parseInt(this.getDefaultChain())}return this.namespace.methods.includes(u.request.method)?await this.client.request(u):this.getHttpProvider().request(u.request)}updateNamespace(u){this.namespace=Object.assign(this.namespace,u)}setDefaultChain(u,i){this.httpProviders[u]||this.setHttpProvider(parseInt(u),i),this.chainId=parseInt(u),this.events.emit(kn.DEFAULT_CHAIN_CHANGED,`${this.name}:${u}`)}requestAccounts(){return this.getAccounts()}getDefaultChain(){if(this.chainId)return this.chainId.toString();if(this.namespace.defaultChain)return this.namespace.defaultChain;const u=this.namespace.chains[0];if(!u)throw new Error("ChainId not found");return u.split(":")[1]}createHttpProvider(u,i){const d=i||ct(`${this.name}:${u}`,this.namespace,this.client.core.projectId);if(!d)throw new Error(`No RPC url provided for chainId: ${u}`);return new ft.JsonRpcProvider(new Ca.HttpConnection(d,K("disableProviderPing")))}setHttpProvider(u,i){const d=this.createHttpProvider(u,i);d&&(this.httpProviders[u]=d)}createHttpProviders(){const u={};return this.namespace.chains.forEach(i=>{var d;const w=parseInt(It(i));u[w]=this.createHttpProvider(w,(d=this.namespace.rpcMap)==null?void 0:d[i])}),u}getAccounts(){const u=this.namespace.accounts;return u?[...new Set(u.filter(i=>i.split(":")[1]===this.chainId.toString()).map(i=>i.split(":")[2]))]:[]}getHttpProvider(){const u=this.chainId,i=this.httpProviders[u];if(typeof i>"u")throw new Error(`JSON-RPC provider for ${u} not found`);return i}async handleSwitchChain(u){var i,d;let w=u.request.params?(i=u.request.params[0])==null?void 0:i.chainId:"0x0";w=w.startsWith("0x")?w:`0x${w}`;const T=parseInt(w,16);if(this.isChainApproved(T))this.setDefaultChain(`${T}`);else if(this.namespace.methods.includes("wallet_switchEthereumChain"))await this.client.request({topic:u.topic,request:{method:u.request.method,params:[{chainId:w}]},chainId:(d=this.namespace.chains)==null?void 0:d[0]}),this.setDefaultChain(`${T}`);else throw new Error(`Failed to switch to chain 'eip155:${T}'. The chain is not approved or the wallet does not support 'wallet_switchEthereumChain' method.`);return null}isChainApproved(u){return this.namespace.chains.includes(`${this.name}:${u}`)}}class Zg{constructor(u){this.name="solana",this.namespace=u.namespace,this.events=K("events"),this.client=K("client"),this.chainId=this.getDefaultChain(),this.httpProviders=this.createHttpProviders()}updateNamespace(u){this.namespace=Object.assign(this.namespace,u)}requestAccounts(){return this.getAccounts()}request(u){return this.namespace.methods.includes(u.request.method)?this.client.request(u):this.getHttpProvider().request(u.request)}setDefaultChain(u,i){this.httpProviders[u]||this.setHttpProvider(u,i),this.chainId=u,this.events.emit(kn.DEFAULT_CHAIN_CHANGED,`${this.name}:${u}`)}getDefaultChain(){if(this.chainId)return this.chainId;if(this.namespace.defaultChain)return this.namespace.defaultChain;const u=this.namespace.chains[0];if(!u)throw new Error("ChainId not found");return u.split(":")[1]}getAccounts(){const u=this.namespace.accounts;return u?[...new Set(u.filter(i=>i.split(":")[1]===this.chainId.toString()).map(i=>i.split(":")[2]))]:[]}createHttpProviders(){const u={};return this.namespace.chains.forEach(i=>{var d;const w=It(i);u[w]=this.createHttpProvider(w,(d=this.namespace.rpcMap)==null?void 0:d[i])}),u}getHttpProvider(){const u=`${this.name}:${this.chainId}`,i=this.httpProviders[u];if(typeof i>"u")throw new Error(`JSON-RPC provider for ${u} not found`);return i}setHttpProvider(u,i){const d=this.createHttpProvider(u,i);d&&(this.httpProviders[u]=d)}createHttpProvider(u,i){const d=i||ct(u,this.namespace,this.client.core.projectId);if(!d)throw new Error(`No RPC url provided for chainId: ${u}`);return new ft.JsonRpcProvider(new Ct.default(d,K("disableProviderPing")))}}class Xg{constructor(u){this.name="cosmos",this.namespace=u.namespace,this.events=K("events"),this.client=K("client"),this.chainId=this.getDefaultChain(),this.httpProviders=this.createHttpProviders()}updateNamespace(u){this.namespace=Object.assign(this.namespace,u)}requestAccounts(){return this.getAccounts()}getDefaultChain(){if(this.chainId)return this.chainId;if(this.namespace.defaultChain)return this.namespace.defaultChain;const u=this.namespace.chains[0];if(!u)throw new Error("ChainId not found");return u.split(":")[1]}request(u){return this.namespace.methods.includes(u.request.method)?this.client.request(u):this.getHttpProvider().request(u.request)}setDefaultChain(u,i){this.httpProviders[u]||this.setHttpProvider(u,i),this.chainId=u,this.events.emit(kn.DEFAULT_CHAIN_CHANGED,`${this.name}:${this.chainId}`)}getAccounts(){const u=this.namespace.accounts;return u?[...new Set(u.filter(i=>i.split(":")[1]===this.chainId.toString()).map(i=>i.split(":")[2]))]:[]}createHttpProviders(){const u={};return this.namespace.chains.forEach(i=>{var d;const w=It(i);u[w]=this.createHttpProvider(w,(d=this.namespace.rpcMap)==null?void 0:d[i])}),u}getHttpProvider(){const u=`${this.name}:${this.chainId}`,i=this.httpProviders[u];if(typeof i>"u")throw new Error(`JSON-RPC provider for ${u} not found`);return i}setHttpProvider(u,i){const d=this.createHttpProvider(u,i);d&&(this.httpProviders[u]=d)}createHttpProvider(u,i){const d=i||ct(u,this.namespace,this.client.core.projectId);if(!d)throw new Error(`No RPC url provided for chainId: ${u}`);return new ft.JsonRpcProvider(new Ct.default(d,K("disableProviderPing")))}}class Qg{constructor(u){this.name="cip34",this.namespace=u.namespace,this.events=K("events"),this.client=K("client"),this.chainId=this.getDefaultChain(),this.httpProviders=this.createHttpProviders()}updateNamespace(u){this.namespace=Object.assign(this.namespace,u)}requestAccounts(){return this.getAccounts()}getDefaultChain(){if(this.chainId)return this.chainId;if(this.namespace.defaultChain)return this.namespace.defaultChain;const u=this.namespace.chains[0];if(!u)throw new Error("ChainId not found");return u.split(":")[1]}request(u){return this.namespace.methods.includes(u.request.method)?this.client.request(u):this.getHttpProvider().request(u.request)}setDefaultChain(u,i){this.httpProviders[u]||this.setHttpProvider(u,i),this.chainId=u,this.events.emit(kn.DEFAULT_CHAIN_CHANGED,`${this.name}:${this.chainId}`)}getAccounts(){const u=this.namespace.accounts;return u?[...new Set(u.filter(i=>i.split(":")[1]===this.chainId.toString()).map(i=>i.split(":")[2]))]:[]}createHttpProviders(){const u={};return this.namespace.chains.forEach(i=>{const d=this.getCardanoRPCUrl(i),w=It(i);u[w]=this.createHttpProvider(w,d)}),u}getHttpProvider(){const u=`${this.name}:${this.chainId}`,i=this.httpProviders[u];if(typeof i>"u")throw new Error(`JSON-RPC provider for ${u} not found`);return i}getCardanoRPCUrl(u){const i=this.namespace.rpcMap;if(i)return i[u]}setHttpProvider(u,i){const d=this.createHttpProvider(u,i);d&&(this.httpProviders[u]=d)}createHttpProvider(u,i){const d=i||this.getCardanoRPCUrl(u);if(!d)throw new Error(`No RPC url provided for chainId: ${u}`);return new ft.JsonRpcProvider(new Ct.default(d,K("disableProviderPing")))}}class Vg{constructor(u){this.name="elrond",this.namespace=u.namespace,this.events=K("events"),this.client=K("client"),this.chainId=this.getDefaultChain(),this.httpProviders=this.createHttpProviders()}updateNamespace(u){this.namespace=Object.assign(this.namespace,u)}requestAccounts(){return this.getAccounts()}request(u){return this.namespace.methods.includes(u.request.method)?this.client.request(u):this.getHttpProvider().request(u.request)}setDefaultChain(u,i){this.httpProviders[u]||this.setHttpProvider(u,i),this.chainId=u,this.events.emit(kn.DEFAULT_CHAIN_CHANGED,`${this.name}:${u}`)}getDefaultChain(){if(this.chainId)return this.chainId;if(this.namespace.defaultChain)return this.namespace.defaultChain;const u=this.namespace.chains[0];if(!u)throw new Error("ChainId not found");return u.split(":")[1]}getAccounts(){const u=this.namespace.accounts;return u?[...new Set(u.filter(i=>i.split(":")[1]===this.chainId.toString()).map(i=>i.split(":")[2]))]:[]}createHttpProviders(){const u={};return this.namespace.chains.forEach(i=>{var d;const w=It(i);u[w]=this.createHttpProvider(w,(d=this.namespace.rpcMap)==null?void 0:d[i])}),u}getHttpProvider(){const u=`${this.name}:${this.chainId}`,i=this.httpProviders[u];if(typeof i>"u")throw new Error(`JSON-RPC provider for ${u} not found`);return i}setHttpProvider(u,i){const d=this.createHttpProvider(u,i);d&&(this.httpProviders[u]=d)}createHttpProvider(u,i){const d=i||ct(u,this.namespace,this.client.core.projectId);if(!d)throw new Error(`No RPC url provided for chainId: ${u}`);return new ft.JsonRpcProvider(new Ct.default(d,K("disableProviderPing")))}}class kg{constructor(u){this.name="multiversx",this.namespace=u.namespace,this.events=K("events"),this.client=K("client"),this.chainId=this.getDefaultChain(),this.httpProviders=this.createHttpProviders()}updateNamespace(u){this.namespace=Object.assign(this.namespace,u)}requestAccounts(){return this.getAccounts()}request(u){return this.namespace.methods.includes(u.request.method)?this.client.request(u):this.getHttpProvider().request(u.request)}setDefaultChain(u,i){this.httpProviders[u]||this.setHttpProvider(u,i),this.chainId=u,this.events.emit(kn.DEFAULT_CHAIN_CHANGED,`${this.name}:${u}`)}getDefaultChain(){if(this.chainId)return this.chainId;if(this.namespace.defaultChain)return this.namespace.defaultChain;const u=this.namespace.chains[0];if(!u)throw new Error("ChainId not found");return u.split(":")[1]}getAccounts(){const u=this.namespace.accounts;return u?[...new Set(u.filter(i=>i.split(":")[1]===this.chainId.toString()).map(i=>i.split(":")[2]))]:[]}createHttpProviders(){const u={};return this.namespace.chains.forEach(i=>{var d;const w=It(i);u[w]=this.createHttpProvider(w,(d=this.namespace.rpcMap)==null?void 0:d[i])}),u}getHttpProvider(){const u=`${this.name}:${this.chainId}`,i=this.httpProviders[u];if(typeof i>"u")throw new Error(`JSON-RPC provider for ${u} not found`);return i}setHttpProvider(u,i){const d=this.createHttpProvider(u,i);d&&(this.httpProviders[u]=d)}createHttpProvider(u,i){const d=i||ct(u,this.namespace,this.client.core.projectId);if(!d)throw new Error(`No RPC url provided for chainId: ${u}`);return new ft.JsonRpcProvider(new Ct.default(d,K("disableProviderPing")))}}class jg{constructor(u){this.name="near",this.namespace=u.namespace,this.events=K("events"),this.client=K("client"),this.chainId=this.getDefaultChain(),this.httpProviders=this.createHttpProviders()}updateNamespace(u){this.namespace=Object.assign(this.namespace,u)}requestAccounts(){return this.getAccounts()}getDefaultChain(){if(this.chainId)return this.chainId;if(this.namespace.defaultChain)return this.namespace.defaultChain;const u=this.namespace.chains[0];if(!u)throw new Error("ChainId not found");return u.split(":")[1]}request(u){return this.namespace.methods.includes(u.request.method)?this.client.request(u):this.getHttpProvider().request(u.request)}setDefaultChain(u,i){if(this.chainId=u,!this.httpProviders[u]){const d=i||ct(`${this.name}:${u}`,this.namespace);if(!d)throw new Error(`No RPC url provided for chainId: ${u}`);this.setHttpProvider(u,d)}this.events.emit(kn.DEFAULT_CHAIN_CHANGED,`${this.name}:${this.chainId}`)}getAccounts(){const u=this.namespace.accounts;return u?u.filter(i=>i.split(":")[1]===this.chainId.toString()).map(i=>i.split(":")[2])||[]:[]}createHttpProviders(){const u={};return this.namespace.chains.forEach(i=>{var d;u[i]=this.createHttpProvider(i,(d=this.namespace.rpcMap)==null?void 0:d[i])}),u}getHttpProvider(){const u=`${this.name}:${this.chainId}`,i=this.httpProviders[u];if(typeof i>"u")throw new Error(`JSON-RPC provider for ${u} not found`);return i}setHttpProvider(u,i){const d=this.createHttpProvider(u,i);d&&(this.httpProviders[u]=d)}createHttpProvider(u,i){const d=i||ct(u,this.namespace);return typeof d>"u"?void 0:new ft.JsonRpcProvider(new Ct.default(d,K("disableProviderPing")))}}var nv=Object.defineProperty,tv=Object.defineProperties,ev=Object.getOwnPropertyDescriptors,ba=Object.getOwnPropertySymbols,rv=Object.prototype.hasOwnProperty,iv=Object.prototype.propertyIsEnumerable,Ta=(A,u,i)=>u in A?nv(A,u,{enumerable:!0,configurable:!0,writable:!0,value:i}):A[u]=i,hr=(A,u)=>{for(var i in u||(u={}))rv.call(u,i)&&Ta(A,i,u[i]);if(ba)for(var i of ba(u))iv.call(u,i)&&Ta(A,i,u[i]);return A},Fi=(A,u)=>tv(A,ev(u));class lr{constructor(u){this.events=new Tg.default,this.rpcProviders={},this.shouldAbortPairingAttempt=!1,this.maxPairingAttempts=10,this.disableProviderPing=!1,this.providerOpts=u,this.logger=typeof u?.logger<"u"&&typeof u?.logger!="string"?u.logger:Aa.pino(Aa.getDefaultLoggerOptions({level:u?.logger||Ia})),this.disableProviderPing=u?.disableProviderPing||!1}static async init(u){const i=new lr(u);return await i.initialize(),i}async request(u,i){const[d,w]=this.validateChain(i);if(!this.session)throw new Error("Please call connect() before request()");return await this.getProvider(d).request({request:hr({},u),chainId:`${d}:${w}`,topic:this.session.topic})}sendAsync(u,i,d){this.request(u,d).then(w=>i(null,w)).catch(w=>i(w,void 0))}async enable(){if(!this.client)throw new Error("Sign Client not initialized");return this.session||await this.connect({namespaces:this.namespaces,optionalNamespaces:this.optionalNamespaces,sessionProperties:this.sessionProperties}),await this.requestAccounts()}async disconnect(){var u;if(!this.session)throw new Error("Please call connect() before enable()");await this.client.disconnect({topic:(u=this.session)==null?void 0:u.topic,reason:en.getSdkError("USER_DISCONNECTED")}),await this.cleanup()}async connect(u){if(!this.client)throw new Error("Sign Client not initialized");if(this.setNamespaces(u),await this.cleanupPendingPairings(),!u.skipPairing)return await this.pair(u.pairingTopic)}on(u,i){this.events.on(u,i)}once(u,i){this.events.once(u,i)}removeListener(u,i){this.events.removeListener(u,i)}off(u,i){this.events.off(u,i)}get isWalletConnect(){return!0}async pair(u){this.shouldAbortPairingAttempt=!1;let i=0;do{if(this.shouldAbortPairingAttempt)throw new Error("Pairing aborted");if(i>=this.maxPairingAttempts)throw new Error("Max auto pairing attempts reached");const{uri:d,approval:w}=await this.client.connect({pairingTopic:u,requiredNamespaces:this.namespaces,optionalNamespaces:this.optionalNamespaces,sessionProperties:this.sessionProperties});d&&(this.uri=d,this.events.emit("display_uri",d)),await w().then(T=>{this.session=T,this.namespaces||(this.namespaces=zg(T.namespaces),this.persist("namespaces",this.namespaces))}).catch(T=>{if(T.message!==Pa.PROPOSAL_EXPIRY_MESSAGE)throw T;i++})}while(!this.session);return this.onConnect(),this.session}setDefaultChain(u,i){try{if(!this.session)return;const[d,w]=this.validateChain(u);this.getProvider(d).setDefaultChain(w,i)}catch(d){if(!/Please call connect/.test(d.message))throw d}}async cleanupPendingPairings(u={}){this.logger.info("Cleaning up inactive pairings...");const i=this.client.pairing.getAll();if(en.isValidArray(i)){for(const d of i)u.deletePairings?this.client.core.expirer.set(d.topic,0):await this.client.core.relayer.subscriber.unsubscribe(d.topic);this.logger.info(`Inactive pairings cleared: ${i.length}`)}}abortPairingAttempt(){this.shouldAbortPairingAttempt=!0}async checkStorage(){if(this.namespaces=await this.getFromStore("namespaces"),this.optionalNamespaces=await this.getFromStore("optionalNamespaces")||{},this.client.session.length){const u=this.client.session.keys.length-1;this.session=this.client.session.get(this.client.session.keys[u]),this.createProviders()}}async initialize(){this.logger.trace("Initialized"),await this.createClient(),await this.checkStorage(),this.registerEventListeners()}async createClient(){this.client=this.providerOpts.client||await (bg.default.init || bg.default.default.init)({logger:this.providerOpts.logger||Ia,relayUrl:this.providerOpts.relayUrl||Lg,projectId:this.providerOpts.projectId,metadata:this.providerOpts.metadata,storageOptions:this.providerOpts.storageOptions,storage:this.providerOpts.storage,name:this.providerOpts.name}),this.logger.trace("SignClient Initialized")}createProviders(){if(!this.client)throw new Error("Sign Client not initialized");if(!this.session)throw new Error("Session not initialized. Please call connect() before enable()");const u=[...new Set(Object.keys(this.session.namespaces).map(i=>en.parseNamespaceKey(i)))];Wi("client",this.client),Wi("events",this.events),Wi("disableProviderPing",this.disableProviderPing),u.forEach(i=>{if(!this.session)return;const d=Bg(i,this.session),w=Sa(d),T=Gg(this.namespaces,this.optionalNamespaces),$=Fi(hr({},T[i]),{accounts:d,chains:w});switch(i){case"eip155":this.rpcProviders[i]=new Yg({namespace:$});break;case"solana":this.rpcProviders[i]=new Zg({namespace:$});break;case"cosmos":this.rpcProviders[i]=new Xg({namespace:$});break;case"polkadot":this.rpcProviders[i]=new Jg({namespace:$});break;case"cip34":this.rpcProviders[i]=new Qg({namespace:$});break;case"elrond":this.rpcProviders[i]=new Vg({namespace:$});break;case"multiversx":this.rpcProviders[i]=new kg({namespace:$});break;case"near":this.rpcProviders[i]=new jg({namespace:$});break}})}registerEventListeners(){if(typeof this.client>"u")throw new Error("Sign Client is not initialized");this.client.on("session_ping",u=>{this.events.emit("session_ping",u)}),this.client.on("session_event",u=>{const{params:i}=u,{event:d}=i;if(d.name==="accountsChanged"){const w=d.data;w&&en.isValidArray(w)&&this.events.emit("accountsChanged",w.map(Kg))}else if(d.name==="chainChanged"){const w=i.chainId,T=i.event.data,$=en.parseNamespaceKey(w),yn=qi(w)!==qi(T)?`${$}:${qi(T)}`:w;this.onChainChanged(yn)}else this.events.emit(d.name,d.data);this.events.emit("session_event",u)}),this.client.on("session_update",({topic:u,params:i})=>{var d;const{namespaces:w}=i,T=(d=this.client)==null?void 0:d.session.get(u);this.session=Fi(hr({},T),{namespaces:w}),this.onSessionUpdate(),this.events.emit("session_update",{topic:u,params:i})}),this.client.on("session_delete",async u=>{await this.cleanup(),this.events.emit("session_delete",u),this.events.emit("disconnect",Fi(hr({},en.getSdkError("USER_DISCONNECTED")),{data:u.topic}))}),this.on(kn.DEFAULT_CHAIN_CHANGED,u=>{this.onChainChanged(u,!0)})}getProvider(u){if(!this.rpcProviders[u])throw new Error(`Provider not found: ${u}`);return this.rpcProviders[u]}onSessionUpdate(){Object.keys(this.rpcProviders).forEach(u=>{var i;this.getProvider(u).updateNamespace((i=this.session)==null?void 0:i.namespaces[u])})}setNamespaces(u){const{namespaces:i,optionalNamespaces:d,sessionProperties:w}=u;i&&Object.keys(i).length&&(this.namespaces=i),d&&Object.keys(d).length&&(this.optionalNamespaces=d),this.sessionProperties=w,this.persist("namespaces",i),this.persist("optionalNamespaces",d)}validateChain(u){const[i,d]=u?.split(":")||["",""];if(!this.namespaces||!Object.keys(this.namespaces).length)return[i,d];if(i&&!Object.keys(this.namespaces||{}).map($=>en.parseNamespaceKey($)).includes(i))throw new Error(`Namespace '${i}' is not configured. Please call connect() first with namespace config.`);if(i&&d)return[i,d];const w=en.parseNamespaceKey(Object.keys(this.namespaces)[0]),T=this.rpcProviders[w].getDefaultChain();return[w,T]}async requestAccounts(){const[u]=this.validateChain();return await this.getProvider(u).requestAccounts()}onChainChanged(u,i=!1){var d;if(!this.namespaces)return;const[w,T]=this.validateChain(u);i||this.getProvider(w).setDefaultChain(T),((d=this.namespaces[w])!=null?d:this.namespaces[`${w}:${T}`]).defaultChain=T,this.persist("namespaces",this.namespaces),this.events.emit("chainChanged",T)}onConnect(){this.createProviders(),this.events.emit("connect",{session:this.session})}async cleanup(){this.session=void 0,this.namespaces=void 0,this.optionalNamespaces=void 0,this.sessionProperties=void 0,this.persist("namespaces",void 0),this.persist("optionalNamespaces",void 0),this.persist("sessionProperties",void 0),await this.cleanupPendingPairings({deletePairings:!0})}persist(u,i){this.client.core.storage.setItem(`${xa}/${u}`,i)}async getFromStore(u){return await this.client.core.storage.getItem(`${xa}/${u}`)}}const sv=lr;exports.UniversalProvider=sv,exports.default=lr; - //# sourceMappingURL=index.cjs.js.map diff --git a/yarn.lock b/yarn.lock index cd5acc9218..6c9ad4688d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -21,6 +21,11 @@ resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz#d2a39395c587e092d77cbbc80acf956a54f38bf7" integrity sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q== +"@adraffy/ens-normalize@^1.10.1": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.11.0.tgz#42cc67c5baa407ac25059fcd7d405cc5ecdb0c33" + integrity sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg== + "@alloc/quick-lru@^5.2.0": version "5.2.0" resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30" @@ -5383,7 +5388,7 @@ dependencies: "@noble/hashes" "1.3.2" -"@noble/curves@^1.6.0": +"@noble/curves@1.7.0", "@noble/curves@^1.4.0", "@noble/curves@^1.6.0", "@noble/curves@~1.7.0": version "1.7.0" resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.7.0.tgz#0512360622439256df892f21d25b388f52505e45" integrity sha512-UTMhXK9SeDhFJVrHeUJ5uZlI6ajXg10O6Ddocf9S6GjbSBVZsJo88HzKwXznNfGpMTRDyJkqMjNDPYgf0qFWnw== @@ -5410,16 +5415,16 @@ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.6.0.tgz#d4bfb516ad6e7b5111c216a5cc7075f4cf19e6c5" integrity sha512-YUULf0Uk4/mAA89w+k3+yUYh6NrEvxZa5T6SY3wlMvE2chHkxFUUIDI8/XW1QSC357iA5pSnqt7XEhvFOqmDyQ== +"@noble/hashes@1.6.1", "@noble/hashes@^1.4.0", "@noble/hashes@^1.5.0", "@noble/hashes@~1.6.0": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.6.1.tgz#df6e5943edcea504bac61395926d6fd67869a0d5" + integrity sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w== + "@noble/hashes@^1.3.1": version "1.4.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== -"@noble/hashes@^1.5.0": - version "1.6.1" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.6.1.tgz#df6e5943edcea504bac61395926d6fd67869a0d5" - integrity sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w== - "@noble/hashes@~1.3.2": version "1.3.3" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699" @@ -6210,6 +6215,128 @@ resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.17.0.tgz#fbb0add487478ef42247d5942e7a5d8a2e20095f" integrity sha512-2D6XaHEVvkCn682XBnipbJjgZUU7xjLtA4dGJRBVUKpEaDYOZMENZoZjAOSb7qirxt5RupjzZxz4fK2FO+EFPw== +"@reown/appkit-adapter-ethers5@^1.6.2": + version "1.6.2" + resolved "https://registry.yarnpkg.com/@reown/appkit-adapter-ethers5/-/appkit-adapter-ethers5-1.6.2.tgz#82929fac902b21eed7d5b4bd4fd7903af8cd7389" + integrity sha512-ORnQXWKFjtwj0KEpgutbH+z+MrraCryhuLRZctFvwOWERK4BaNvkjRBK8L2lrJ/oqbtPLaz4f84wyMgLr3a14A== + dependencies: + "@reown/appkit" "1.6.2" + "@reown/appkit-common" "1.6.2" + "@reown/appkit-core" "1.6.2" + "@reown/appkit-polyfills" "1.6.2" + "@reown/appkit-scaffold-ui" "1.6.2" + "@reown/appkit-ui" "1.6.2" + "@reown/appkit-utils" "1.6.2" + "@reown/appkit-wallet" "1.6.2" + "@walletconnect/universal-provider" "2.17.2" + "@walletconnect/utils" "2.17.2" + valtio "1.11.2" + +"@reown/appkit-common@1.6.2": + version "1.6.2" + resolved "https://registry.yarnpkg.com/@reown/appkit-common/-/appkit-common-1.6.2.tgz#a2d556981ef2bd175cf3c0d975eaf7278b89cbb9" + integrity sha512-m+zbL1gqdCcCxXYq3tFiN3T7SATKuC3w1kXUvsaq0vrNio85AAQJaF0WXGgQkIwmrmg38pi6ZPFuG81SK5Zuzg== + dependencies: + bignumber.js "9.1.2" + dayjs "1.11.10" + viem "2.x" + +"@reown/appkit-core@1.6.2": + version "1.6.2" + resolved "https://registry.yarnpkg.com/@reown/appkit-core/-/appkit-core-1.6.2.tgz#5afafc4fc47044ea398e8dce39fe211c79881a03" + integrity sha512-bVSa/v/8PmcQIb1sNLAjhVzAxH8xwFF11JEtktLiwk3kqWh33U/S1ZplmG3dq6yX4QoA3AqUQy8pwcbzCUYQVg== + dependencies: + "@reown/appkit-common" "1.6.2" + "@reown/appkit-wallet" "1.6.2" + "@walletconnect/universal-provider" "2.17.2" + valtio "1.11.2" + viem "2.x" + +"@reown/appkit-polyfills@1.6.2": + version "1.6.2" + resolved "https://registry.yarnpkg.com/@reown/appkit-polyfills/-/appkit-polyfills-1.6.2.tgz#15dc1f98b7e6f63569ccdaa5b7829bcd7685e90c" + integrity sha512-DV1ReOHnNDsSmI+3oi55M0IWEW48HXML2pUSEr+oJOLLPd8sjar9NNEW/v1hXnl/ddgep2gYsptn8GIPhkCd2g== + dependencies: + buffer "6.0.3" + +"@reown/appkit-scaffold-ui@1.6.2": + version "1.6.2" + resolved "https://registry.yarnpkg.com/@reown/appkit-scaffold-ui/-/appkit-scaffold-ui-1.6.2.tgz#1d6dc681edbd305e45133d3e5e3efecf74b829b0" + integrity sha512-crhCDFNQJ6d6iZkC3TXRoN4utj3Dwl9aW3H1y8kt2g6XFVICBG0cjl0o/9uqRHFkYbKPr7drj9mTrPgTkZ7JNA== + dependencies: + "@reown/appkit-common" "1.6.2" + "@reown/appkit-core" "1.6.2" + "@reown/appkit-ui" "1.6.2" + "@reown/appkit-utils" "1.6.2" + "@reown/appkit-wallet" "1.6.2" + lit "3.1.0" + +"@reown/appkit-siwe@1.6.2": + version "1.6.2" + resolved "https://registry.yarnpkg.com/@reown/appkit-siwe/-/appkit-siwe-1.6.2.tgz#6fa7faa18a46d42c42fefe0c1db202c49750741c" + integrity sha512-pNUjEjOjrrvrOoeX9uYCbcpSsehxTWIrkTp28VUJkeIEPw+1eDRP+YnECRD1uWUHfD2UOyYaE1X73jmcGw41/Q== + dependencies: + "@reown/appkit-common" "1.6.2" + "@reown/appkit-core" "1.6.2" + "@reown/appkit-ui" "1.6.2" + "@reown/appkit-utils" "1.6.2" + "@reown/appkit-wallet" "1.6.2" + "@walletconnect/utils" "2.17.2" + lit "3.1.0" + valtio "1.11.2" + +"@reown/appkit-ui@1.6.2": + version "1.6.2" + resolved "https://registry.yarnpkg.com/@reown/appkit-ui/-/appkit-ui-1.6.2.tgz#a05763837d6e3f92302b5e187d8d4d8675280859" + integrity sha512-cav7ntEH4c3zW6q3CWxqwN8OPqwU1RA9k1ococUAD1299+xOb58zNbdjMaNyUTj/xC4MvNGgGuFNfXXLikzXrg== + dependencies: + lit "3.1.0" + qrcode "1.5.3" + +"@reown/appkit-utils@1.6.2": + version "1.6.2" + resolved "https://registry.yarnpkg.com/@reown/appkit-utils/-/appkit-utils-1.6.2.tgz#8b4cde4abc0c2af181c8b8b78ef50583e2405c66" + integrity sha512-rxocR2pnPgkfasn7LbQMuZt7EkhmF4BBQc1znBJx6UueHtySyR7I5xclBs4FtRNbZAwDoBO9N3Vo8xzDTyKd2Q== + dependencies: + "@reown/appkit-common" "1.6.2" + "@reown/appkit-core" "1.6.2" + "@reown/appkit-polyfills" "1.6.2" + "@reown/appkit-wallet" "1.6.2" + "@walletconnect/logger" "2.1.2" + "@walletconnect/universal-provider" "2.17.2" + valtio "1.11.2" + viem "2.x" + +"@reown/appkit-wallet@1.6.2": + version "1.6.2" + resolved "https://registry.yarnpkg.com/@reown/appkit-wallet/-/appkit-wallet-1.6.2.tgz#d85824c2de8566f7a1179b3331ded3d01a767188" + integrity sha512-hOJngi4Q7vdUEVBDnGY6sHBZH46KWFJkqjREbyPIUyGFKb+KkjyzOzUGOIsi+HNuLVkanlJAKTYt9vMBgkehOQ== + dependencies: + "@reown/appkit-common" "1.6.2" + "@reown/appkit-polyfills" "1.6.2" + "@walletconnect/logger" "2.1.2" + zod "3.22.4" + +"@reown/appkit@1.6.2", "@reown/appkit@^1.6.2": + version "1.6.2" + resolved "https://registry.yarnpkg.com/@reown/appkit/-/appkit-1.6.2.tgz#fc2be7c79e73f546347df48383bc9b0c39b86822" + integrity sha512-xnmkE2nrh/hYph4i4lVUTB1h/aWhhu2Genb/fzERvs7s16R01CEZyz8MAuksyuDkLbvv8VZcitVf4Q5Myel3eA== + dependencies: + "@reown/appkit-common" "1.6.2" + "@reown/appkit-core" "1.6.2" + "@reown/appkit-polyfills" "1.6.2" + "@reown/appkit-scaffold-ui" "1.6.2" + "@reown/appkit-siwe" "1.6.2" + "@reown/appkit-ui" "1.6.2" + "@reown/appkit-utils" "1.6.2" + "@reown/appkit-wallet" "1.6.2" + "@walletconnect/types" "2.17.2" + "@walletconnect/universal-provider" "2.17.2" + "@walletconnect/utils" "2.17.2" + bs58 "6.0.0" + valtio "1.11.2" + viem "2.x" + "@rjsf/core@^4.2.2": version "4.2.3" resolved "https://registry.yarnpkg.com/@rjsf/core/-/core-4.2.3.tgz#7ff2fb593f0af20485dc267391a8971378eec655" @@ -6545,6 +6672,11 @@ resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938" integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA== +"@scure/base@~1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.2.1.tgz#dd0b2a533063ca612c17aa9ad26424a2ff5aa865" + integrity sha512-DGmGtC8Tt63J5GfHgfl5CuAXh96VF/LD8K9Hr/Gv0J2lAoRGlPOMpqMpMbCTOoOJMZCk2Xt+DskdDyn6dEFdzQ== + "@scure/bip32@1.1.5": version "1.1.5" resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.1.5.tgz#d2ccae16dcc2e75bc1d75f5ef3c66a338d1ba300" @@ -6572,6 +6704,15 @@ "@noble/hashes" "~1.3.2" "@scure/base" "~1.1.2" +"@scure/bip32@1.6.0", "@scure/bip32@^1.5.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.6.0.tgz#6dbc6b4af7c9101b351f41231a879d8da47e0891" + integrity sha512-82q1QfklrUUdXJzjuRU7iG7D7XiFx5PHYVS0+oeNKhyDLT7WPqs6pBcM2W5ZdwOwKCwoE1Vy1se+DHjcXwCYnA== + dependencies: + "@noble/curves" "~1.7.0" + "@noble/hashes" "~1.6.0" + "@scure/base" "~1.2.1" + "@scure/bip39@1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.1.tgz#b54557b2e86214319405db819c4b6a370cf340c5" @@ -6588,6 +6729,14 @@ "@noble/hashes" "~1.3.0" "@scure/base" "~1.1.0" +"@scure/bip39@1.5.0", "@scure/bip39@^1.4.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.5.0.tgz#c8f9533dbd787641b047984356531d84485f19be" + integrity sha512-Dop+ASYhnrwm9+HA/HwXg7j2ZqM6yk2fyLWb5znexjctFY3+E+eU8cIWI0Pql0Qx4hPZCijlGq4OL71g+Uz30A== + dependencies: + "@noble/hashes" "~1.6.0" + "@scure/base" "~1.2.1" + "@sentry-internal/tracing@7.64.0": version "7.64.0" resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.64.0.tgz#3e110473b8edf805b799cc91d6ee592830237bb4" @@ -6951,7 +7100,7 @@ "@stablelib/constant-time" "^1.0.1" "@stablelib/wipe" "^1.0.1" -"@stablelib/random@^1.0.1", "@stablelib/random@^1.0.2": +"@stablelib/random@1.0.2", "@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== @@ -6982,7 +7131,7 @@ 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": +"@stablelib/x25519@1.0.3", "@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== @@ -9676,6 +9825,29 @@ lodash.isequal "4.5.0" uint8arrays "^3.1.0" +"@walletconnect/core@2.17.2": + version "2.17.2" + resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.17.2.tgz#877dc03f190d7b262bff8ce346330fdf1019cd83" + integrity sha512-O9VUsFg78CbvIaxfQuZMsHcJ4a2Z16DRz/O4S+uOAcGKhH/i/ln8hp864Tb+xRvifWSzaZ6CeAVxk657F+pscA== + dependencies: + "@walletconnect/heartbeat" "1.2.2" + "@walletconnect/jsonrpc-provider" "1.0.14" + "@walletconnect/jsonrpc-types" "1.0.4" + "@walletconnect/jsonrpc-utils" "1.0.8" + "@walletconnect/jsonrpc-ws-connection" "1.0.14" + "@walletconnect/keyvaluestorage" "1.1.1" + "@walletconnect/logger" "2.1.2" + "@walletconnect/relay-api" "1.0.11" + "@walletconnect/relay-auth" "1.0.4" + "@walletconnect/safe-json" "1.0.2" + "@walletconnect/time" "1.0.2" + "@walletconnect/types" "2.17.2" + "@walletconnect/utils" "2.17.2" + "@walletconnect/window-getters" "1.0.1" + events "3.3.0" + lodash.isequal "4.5.0" + uint8arrays "3.1.0" + "@walletconnect/crypto@^1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@walletconnect/crypto/-/crypto-1.0.3.tgz#7b8dd4d7e2884fe3543c7c07aea425eef5ef9dd4" @@ -9736,7 +9908,7 @@ "@walletconnect/utils" "2.11.1" events "^3.3.0" -"@walletconnect/ethereum-provider@^2.10.1", "@walletconnect/ethereum-provider@^2.10.2": +"@walletconnect/ethereum-provider@^2.10.1": version "2.10.2" resolved "https://registry.yarnpkg.com/@walletconnect/ethereum-provider/-/ethereum-provider-2.10.2.tgz#d5aca538fbcbbf7dd771bceb2430de30f06411de" integrity sha512-QMYFZ6+rVq2CJLdIPdKK0j1Qm66UA27oQU5V2SrL8EVwl7wFfm0Bq7fnL+qAWeDpn612dNeNErpk/ROa1zWlWg== @@ -9751,7 +9923,7 @@ "@walletconnect/utils" "2.10.2" events "^3.3.0" -"@walletconnect/events@^1.0.1": +"@walletconnect/events@1.0.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== @@ -9768,7 +9940,16 @@ "@walletconnect/time" "^1.0.2" tslib "1.14.1" -"@walletconnect/jsonrpc-http-connection@^1.0.4": +"@walletconnect/heartbeat@1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@walletconnect/heartbeat/-/heartbeat-1.2.2.tgz#e8dc5179db7769950c6f9cf59b23516d9b95227d" + integrity sha512-uASiRmC5MwhuRuf05vq4AT48Pq8RMi876zV8rr8cV969uTOzWdB/k+Lj5yI2PBtB1bGQisGen7MM1GcZlQTBXw== + dependencies: + "@walletconnect/events" "^1.0.1" + "@walletconnect/time" "^1.0.2" + events "^3.3.0" + +"@walletconnect/jsonrpc-http-connection@1.0.8", "@walletconnect/jsonrpc-http-connection@^1.0.4": version "1.0.8" resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-http-connection/-/jsonrpc-http-connection-1.0.8.tgz#2f4c3948f074960a3edd07909560f3be13e2c7ae" integrity sha512-+B7cRuaxijLeFDJUq5hAzNyef3e3tBDIxyaCNmFtjwnod5AGis3RToNqzFU33vpVcxFhofkpE7Cx+5MYejbMGw== @@ -9797,7 +9978,7 @@ "@walletconnect/safe-json" "^1.0.2" tslib "1.14.1" -"@walletconnect/jsonrpc-provider@^1.0.6": +"@walletconnect/jsonrpc-provider@1.0.14", "@walletconnect/jsonrpc-provider@^1.0.6": version "1.0.14" resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-provider/-/jsonrpc-provider-1.0.14.tgz#696f3e3b6d728b361f2e8b853cfc6afbdf2e4e3e" integrity sha512-rtsNY1XqHvWj0EtITNeuf8PHMvlCLiS3EjQL+WOkxEOA4KPxsohFnBDeyPYiNm4ZvkQdLnece36opYidmtbmow== @@ -9814,6 +9995,14 @@ keyvaluestorage-interface "^1.0.0" tslib "1.14.1" +"@walletconnect/jsonrpc-types@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-types/-/jsonrpc-types-1.0.4.tgz#ce1a667d79eadf2a2d9d002c152ceb68739c230c" + integrity sha512-P6679fG/M+wuWg9TY8mh6xFSdYnFyFjwFelxyISxMDrlbXokorEVXYOxiqEbrU3x1BmBoCAJJ+vtEaEoMlpCBQ== + dependencies: + events "^3.3.0" + keyvaluestorage-interface "^1.0.0" + "@walletconnect/jsonrpc-utils@1.0.8", "@walletconnect/jsonrpc-utils@^1.0.4", "@walletconnect/jsonrpc-utils@^1.0.6", "@walletconnect/jsonrpc-utils@^1.0.7", "@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" @@ -9844,15 +10033,7 @@ events "^3.3.0" 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/keyvaluestorage@^1.1.1": +"@walletconnect/keyvaluestorage@1.1.1", "@walletconnect/keyvaluestorage@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@walletconnect/keyvaluestorage/-/keyvaluestorage-1.1.1.tgz#dd2caddabfbaf80f6b8993a0704d8b83115a1842" integrity sha512-V7ZQq2+mSxAq7MrRqDxanTzu2RcElfK1PfNYiaVnJgJ7Q7G7hTVwF8voIBx92qsRyGHZihrwNPHuZd1aKkd0rA== @@ -9861,6 +10042,14 @@ idb-keyval "^6.2.1" unstorage "^1.9.0" +"@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/legacy-client@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@walletconnect/legacy-client/-/legacy-client-2.0.0.tgz#9f2c09694789fd4b6c5d68d6423b44bac55aed30" @@ -9921,6 +10110,14 @@ detect-browser "^5.3.0" query-string "^6.13.5" +"@walletconnect/logger@2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@walletconnect/logger/-/logger-2.1.2.tgz#813c9af61b96323a99f16c10089bfeb525e2a272" + integrity sha512-aAb28I3S6pYXZHQm5ESB+V6rDqIYfsnHaQyzFbwUUBFY4H0OXx/YtTl8lvhUNhMMfb9UxbwEBS253TlXUYJWSw== + dependencies: + "@walletconnect/safe-json" "^1.0.2" + pino "7.11.0" + "@walletconnect/logger@^2.0.1": version "2.0.1" resolved "https://registry.yarnpkg.com/@walletconnect/logger/-/logger-2.0.1.tgz#7f489b96e9a1ff6bf3e58f0fbd6d69718bf844a8" @@ -9964,6 +10161,13 @@ randombytes "^2.1.0" tslib "1.14.1" +"@walletconnect/relay-api@1.0.11": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@walletconnect/relay-api/-/relay-api-1.0.11.tgz#80ab7ef2e83c6c173be1a59756f95e515fb63224" + integrity sha512-tLPErkze/HmC9aCmdZOhtVmYZq1wKfWTJtygQHoWtgg722Jd4homo54Cs4ak2RUFUZIGO2RsOpIcWipaua5D5Q== + dependencies: + "@walletconnect/jsonrpc-types" "^1.0.2" + "@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" @@ -9972,7 +10176,7 @@ "@walletconnect/jsonrpc-types" "^1.0.2" tslib "1.14.1" -"@walletconnect/relay-auth@^1.0.4": +"@walletconnect/relay-auth@1.0.4", "@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== @@ -9984,7 +10188,7 @@ tslib "1.14.1" uint8arrays "^3.0.0" -"@walletconnect/safe-json@^1.0.1", "@walletconnect/safe-json@^1.0.2": +"@walletconnect/safe-json@1.0.2", "@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== @@ -10036,7 +10240,22 @@ "@walletconnect/utils" "2.11.1" events "^3.3.0" -"@walletconnect/time@^1.0.2": +"@walletconnect/sign-client@2.17.2": + version "2.17.2" + resolved "https://registry.yarnpkg.com/@walletconnect/sign-client/-/sign-client-2.17.2.tgz#b8bd125d7c34a67916745ebbdbbc834db5518c8b" + integrity sha512-/wigdCIQjlBXSWY43Id0IPvZ5biq4HiiQZti8Ljvx408UYjmqcxcBitbj2UJXMYkid7704JWAB2mw32I1HgshQ== + dependencies: + "@walletconnect/core" "2.17.2" + "@walletconnect/events" "1.0.1" + "@walletconnect/heartbeat" "1.2.2" + "@walletconnect/jsonrpc-utils" "1.0.8" + "@walletconnect/logger" "2.1.2" + "@walletconnect/time" "1.0.2" + "@walletconnect/types" "2.17.2" + "@walletconnect/utils" "2.17.2" + events "3.3.0" + +"@walletconnect/time@1.0.2", "@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== @@ -10079,6 +10298,18 @@ "@walletconnect/logger" "^2.0.1" events "^3.3.0" +"@walletconnect/types@2.17.2": + version "2.17.2" + resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.17.2.tgz#f9afff242563be33f377de689b03b482f5b20aee" + integrity sha512-j/+0WuO00lR8ntu7b1+MKe/r59hNwYLFzW0tTmozzhfAlDL+dYwWasDBNq4AH8NbVd7vlPCQWmncH7/6FVtOfQ== + dependencies: + "@walletconnect/events" "1.0.1" + "@walletconnect/heartbeat" "1.2.2" + "@walletconnect/jsonrpc-types" "1.0.4" + "@walletconnect/keyvaluestorage" "1.1.1" + "@walletconnect/logger" "2.1.2" + events "3.3.0" + "@walletconnect/universal-provider@2.10.2": version "2.10.2" resolved "https://registry.yarnpkg.com/@walletconnect/universal-provider/-/universal-provider-2.10.2.tgz#85c8da39f65da8fe33f65f62689e703607b5ddc5" @@ -10124,6 +10355,24 @@ "@walletconnect/utils" "2.11.1" events "^3.3.0" +"@walletconnect/universal-provider@2.17.2": + version "2.17.2" + resolved "https://registry.yarnpkg.com/@walletconnect/universal-provider/-/universal-provider-2.17.2.tgz#f4627dd9b66db3bacc31864584112868be23bf08" + integrity sha512-yIWDhBODRa9J349d/i1sObzon0vy4n+7R3MvGQQYaU1EVrV+WfoGSRsu8U7rYsL067/MAUu9t/QrpPblaSbz7g== + dependencies: + "@walletconnect/events" "1.0.1" + "@walletconnect/jsonrpc-http-connection" "1.0.8" + "@walletconnect/jsonrpc-provider" "1.0.14" + "@walletconnect/jsonrpc-types" "1.0.4" + "@walletconnect/jsonrpc-utils" "1.0.8" + "@walletconnect/keyvaluestorage" "1.1.1" + "@walletconnect/logger" "2.1.2" + "@walletconnect/sign-client" "2.17.2" + "@walletconnect/types" "2.17.2" + "@walletconnect/utils" "2.17.2" + events "3.3.0" + lodash "4.17.21" + "@walletconnect/utils@2.10.2": version "2.10.2" resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.10.2.tgz#1f2c6a2f1bb95bcc4517b1e94aa7164c9286eb46" @@ -10184,14 +10433,40 @@ query-string "7.1.3" uint8arrays "^3.1.0" -"@walletconnect/window-getters@^1.0.1": +"@walletconnect/utils@2.17.2": + version "2.17.2" + resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.17.2.tgz#b4b12e3f5ebbfd883b2a5c87fb818e53501dc7ea" + integrity sha512-T7eLRiuw96fgwUy2A5NZB5Eu87ukX8RCVoO9lji34RFV4o2IGU9FhTEWyd4QQKI8OuQRjSknhbJs0tU0r0faPw== + dependencies: + "@ethersproject/hash" "5.7.0" + "@ethersproject/transactions" "5.7.0" + "@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/jsonrpc-utils" "1.0.8" + "@walletconnect/keyvaluestorage" "1.1.1" + "@walletconnect/relay-api" "1.0.11" + "@walletconnect/relay-auth" "1.0.4" + "@walletconnect/safe-json" "1.0.2" + "@walletconnect/time" "1.0.2" + "@walletconnect/types" "2.17.2" + "@walletconnect/window-getters" "1.0.1" + "@walletconnect/window-metadata" "1.0.1" + detect-browser "5.3.0" + elliptic "6.6.0" + query-string "7.1.3" + uint8arrays "3.1.0" + +"@walletconnect/window-getters@1.0.1", "@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": +"@walletconnect/window-metadata@1.0.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== @@ -10683,6 +10958,16 @@ abitype@1.0.0: resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.0.tgz#237176dace81d90d018bebf3a45cb42f2a2d9e97" integrity sha512-NMeMah//6bJ56H5XRj8QCV4AwuW6hB6zqz2LnhhLdcWVQOsXki6/Pn3APeqxCma62nXIcmZWdu1DlHWS74umVQ== +abitype@1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.7.tgz#876a0005d211e1c9132825d45bcee7b46416b284" + integrity sha512-ZfYYSktDQUwc2eduYu8C4wOs+RDPmnRYMh7zNfzeMtGGgb0U+6tLGjixUic6mXf5xKKCcgT5Qp6cv39tOARVFw== + +abitype@^1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.8.tgz#3554f28b2e9d6e9f35eb59878193eabd1b9f46ba" + integrity sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg== + abort-controller@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" @@ -11759,6 +12044,11 @@ base-x@^4.0.0: resolved "https://registry.yarnpkg.com/base-x/-/base-x-4.0.0.tgz#d0e3b7753450c73f8ad2389b5c018a4af7b2224a" integrity sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw== +base-x@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-5.0.0.tgz#6d835ceae379130e1a4cb846a70ac4746f28ea9b" + integrity sha512-sMW3VGSX1QWVFA6l8U62MLKz29rRfpTlYdCqLdpLo1/Yd4zZwSbnUaDfciIAowAqvq7YFnWq9hrhdg1KYgc1lQ== + base64-js@^1.3.0, base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" @@ -12219,6 +12509,13 @@ bs-logger@0.x: dependencies: fast-json-stable-stringify "2.x" +bs58@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-6.0.0.tgz#a2cda0130558535dd281a2f8697df79caaf425d8" + integrity sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw== + dependencies: + base-x "^5.0.0" + bs58@^4.0.0, bs58@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" @@ -15123,6 +15420,19 @@ elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3, elliptic@^6.5 minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" +elliptic@6.6.0: + version "6.6.0" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.0.tgz#5919ec723286c1edf28685aa89261d4761afa210" + integrity sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + emittery@^0.10.2: version "0.10.2" resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.10.2.tgz#902eec8aedb8c41938c46e9385e9db7e03182933" @@ -16610,22 +16920,22 @@ eventemitter3@4.0.4: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== +eventemitter3@5.0.1, eventemitter3@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" + integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== + eventemitter3@^4.0.0, eventemitter3@^4.0.7: version "4.0.7" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== -eventemitter3@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" - integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== - events.once@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/events.once/-/events.once-2.0.2.tgz#9e84ac14ef238c070ebc0f44556c24225fa9c7a4" integrity sha512-yt0HxZ3PPiOVsyo9b74bQ07mSKyNeoVHzyakCBFJzSC8WhMUYomvq/naaJNks+wWJ1jv8JYTxO5vaw8wLnmZxw== -events@^3.0.0, events@^3.2.0, events@^3.3.0: +events@3.3.0, events@^3.0.0, events@^3.2.0, events@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== @@ -19753,6 +20063,11 @@ isows@1.0.4: resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.4.tgz#810cd0d90cc4995c26395d2aa4cfa4037ebdf061" integrity sha512-hEzjY+x9u9hPmBom9IIAqdJCwNLax+xrPb51vEPpERoFlIxgmZcHzsT5jKG06nvInKOBGvReAVz80Umed5CczQ== +isows@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.6.tgz#0da29d706fa51551c663c627ace42769850f86e7" + integrity sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw== + isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" @@ -22112,7 +22427,7 @@ lodash.upperfirst@^4.3.1: resolved "https://registry.yarnpkg.com/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz#1365edf431480481ef0d1c68957a5ed99d49f7ce" integrity sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg== -lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.7.0, lodash@~4.17.15: +lodash@4.17.21, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.7.0, lodash@~4.17.15: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -24271,6 +24586,19 @@ outdent@^0.8.0: resolved "https://registry.yarnpkg.com/outdent/-/outdent-0.8.0.tgz#2ebc3e77bf49912543f1008100ff8e7f44428eb0" integrity sha512-KiOAIsdpUTcAXuykya5fnVVT+/5uS0Q1mrkRHcF89tpieSmY33O/tmc54CqwA+bfhbtEfZUNLHaPUiB9X3jt1A== +ox@0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ox/-/ox-0.1.2.tgz#0f791be2ccabeaf4928e6d423498fe1c8094e560" + integrity sha512-ak/8K0Rtphg9vnRJlbOdaX9R7cmxD2MiSthjWGaQdMk3D7hrAlDoM+6Lxn7hN52Za3vrXfZ7enfke/5WjolDww== + dependencies: + "@adraffy/ens-normalize" "^1.10.1" + "@noble/curves" "^1.6.0" + "@noble/hashes" "^1.5.0" + "@scure/bip32" "^1.5.0" + "@scure/bip39" "^1.4.0" + abitype "^1.0.6" + eventemitter3 "5.0.1" + p-cancelable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" @@ -29894,6 +30222,13 @@ ufo@^1.3.0, ufo@^1.3.1, ufo@^1.3.2: resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.3.2.tgz#c7d719d0628a1c80c006d2240e0d169f6e3c0496" integrity sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA== +uint8arrays@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-3.1.0.tgz#8186b8eafce68f28bd29bd29d683a311778901e2" + integrity sha512-ei5rfKtoRO8OyOIor2Rz5fhzjThwIHJZ3uyDPnDHTXbP0aMQ1RN/6AI5B5d9dBxJOU+BvOAk7ZQ1xphsX8Lrog== + dependencies: + multiformats "^9.4.2" + uint8arrays@^2.0.5, uint8arrays@^2.1.2: version "2.1.10" resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-2.1.10.tgz#34d023c843a327c676e48576295ca373c56e286a" @@ -30452,6 +30787,21 @@ vfile@^6.0.0: unist-util-stringify-position "^4.0.0" vfile-message "^4.0.0" +viem@2.x: + version "2.21.57" + resolved "https://registry.yarnpkg.com/viem/-/viem-2.21.57.tgz#bedbb444bb42e07ccc2264a9a0441903a113aab8" + integrity sha512-Mw4f4Dw0+Y/wSHdynVmP4uh+Cw15HEoj8BOKvKH5nGA6oFZYRxSy9Ruu7ZG8jexeAVCZ57aIuXb0gNg6Vb1x0g== + dependencies: + "@noble/curves" "1.7.0" + "@noble/hashes" "1.6.1" + "@scure/bip32" "1.6.0" + "@scure/bip39" "1.5.0" + abitype "1.0.7" + isows "1.0.6" + ox "0.1.2" + webauthn-p256 "0.0.10" + ws "8.18.0" + viem@^1.0.0, viem@^1.16.6: version "1.21.4" resolved "https://registry.yarnpkg.com/viem/-/viem-1.21.4.tgz#883760e9222540a5a7e0339809202b45fe6a842d" @@ -31185,6 +31535,14 @@ web3modal@1.9.0: styled-components "^5.1.1" tslib "^1.10.0" +webauthn-p256@0.0.10: + version "0.0.10" + resolved "https://registry.yarnpkg.com/webauthn-p256/-/webauthn-p256-0.0.10.tgz#877e75abe8348d3e14485932968edf3325fd2fdd" + integrity sha512-EeYD+gmIT80YkSIDb2iWq0lq2zbHo1CxHlQTeJ+KkCILWpVy3zASH3ByD4bopzfk0uCwXxLqKGLqp2W4O28VFA== + dependencies: + "@noble/curves" "^1.4.0" + "@noble/hashes" "^1.4.0" + "webextension-polyfill@>=0.10.0 <1.0": version "0.12.0" resolved "https://registry.yarnpkg.com/webextension-polyfill/-/webextension-polyfill-0.12.0.tgz#f62c57d2cd42524e9fbdcee494c034cae34a3d69" @@ -32061,6 +32419,11 @@ ws@8.16.0: resolved "https://registry.yarnpkg.com/ws/-/ws-8.16.0.tgz#d1cd774f36fbc07165066a60e40323eab6446fd4" integrity sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ== +ws@8.18.0: + version "8.18.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" + integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== + ws@^3.0.0: version "3.3.3" resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" From 0fbeb083b9f24c6084f305e53542b910c2bc687b Mon Sep 17 00:00:00 2001 From: Alexandr Kazachenko Date: Fri, 27 Dec 2024 16:32:56 +0500 Subject: [PATCH 2/3] refactor: remove web3-react usage from useGasLimit --- .../hooksStore/dapps/AirdropHookApp/index.tsx | 4 +++- libs/common-hooks/src/useGasLimitHooks.ts | 19 +++++++------------ 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/apps/cowswap-frontend/src/modules/hooksStore/dapps/AirdropHookApp/index.tsx b/apps/cowswap-frontend/src/modules/hooksStore/dapps/AirdropHookApp/index.tsx index 2225379cbb..69fe3cc599 100644 --- a/apps/cowswap-frontend/src/modules/hooksStore/dapps/AirdropHookApp/index.tsx +++ b/apps/cowswap-frontend/src/modules/hooksStore/dapps/AirdropHookApp/index.tsx @@ -5,6 +5,7 @@ import { TokenWithLogo } from '@cowprotocol/common-const' import { useGasLimit } from '@cowprotocol/common-hooks' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { ButtonPrimary } from '@cowprotocol/ui' +import { useWalletProvider } from '@cowprotocol/wallet-provider' import { Token } from '@uniswap/sdk-core' import { HookDappProps } from 'modules/hooksStore/types/hooks' @@ -27,7 +28,8 @@ const COW_AIRDROP = { export function AirdropHookApp({ context }: HookDappProps) { const { data: claimData, isValidating, error } = useClaimData(COW_AIRDROP) - const { data: gasLimit } = useGasLimit({ to: claimData?.contract.address, data: claimData?.callData }) + const provider = useWalletProvider() + const { data: gasLimit } = useGasLimit(provider, { to: claimData?.contract.address, data: claimData?.callData }) const clickOnAddHook = useCallback(async () => { if (!context || !claimData || !gasLimit) return diff --git a/libs/common-hooks/src/useGasLimitHooks.ts b/libs/common-hooks/src/useGasLimitHooks.ts index 3beaa705cb..6159da5888 100644 --- a/libs/common-hooks/src/useGasLimitHooks.ts +++ b/libs/common-hooks/src/useGasLimitHooks.ts @@ -2,7 +2,6 @@ import { calculateGasMargin } from '@cowprotocol/common-utils' import type { TransactionRequest } from '@ethersproject/abstract-provider' import type { Deferrable } from '@ethersproject/properties' import type { Web3Provider } from '@ethersproject/providers' -import { useWeb3React } from '@web3-react/core' import useSWR from 'swr' @@ -12,15 +11,7 @@ type ITransactionData = Deferrable type IHookGasCalculator = (transactionData: ITransactionData) => Promise -export function useWalletProvider(): Web3Provider | undefined { - const { provider } = useWeb3React() - - return provider -} - -export const useHookGasLimitCalculator = (): IHookGasCalculator => { - const provider = useWalletProvider() - +const useHookGasLimitCalculator = (provider: Web3Provider | undefined): IHookGasCalculator => { return async (transactionData) => { if (!provider) throw new Error('Provider is not defined') const gasEstimation = await provider.estimateGas(transactionData) @@ -28,8 +19,12 @@ export const useHookGasLimitCalculator = (): IHookGasCalculator => { } } -export const useGasLimit = (transactionData: ITransactionData, swrConfig?: SWRConfiguration) => { - const gasCalculator = useHookGasLimitCalculator() +export const useGasLimit = ( + provider: Web3Provider | undefined, + transactionData: ITransactionData, + swrConfig?: SWRConfiguration, +) => { + const gasCalculator = useHookGasLimitCalculator(provider) return useSWR(transactionData, gasCalculator, swrConfig) } From 06d07311d178ea3958619e8d2f0259ad0e0876f8 Mon Sep 17 00:00:00 2001 From: Alexandr Kazachenko Date: Fri, 27 Dec 2024 19:58:27 +0500 Subject: [PATCH 3/3] feat(wallet): replace web3-react by reown --- .../cowswap-frontend/src/cosmos.decorator.tsx | 10 +- apps/cowswap-frontend/src/cow-react/index.tsx | 30 +- .../src/legacy/components/Copy/CopyMod.tsx | 8 - .../Header/NetworkSelector/index.tsx | 4 +- .../legacy/components/Tokens/TokensTable.tsx | 56 ++-- .../src/legacy/state/application/hooks.ts | 4 - .../src/legacy/state/user/hooks.tsx | 4 - .../src/legacy/state/user/reducer.ts | 12 - .../legacy/state/user/userWalletMigration.ts | 28 -- .../containers/AccountDetails/AccountIcon.tsx | 7 +- .../AccountDetails/index.cosmos.tsx | 9 +- .../containers/AccountDetails/index.tsx | 31 +- .../containers/AccountDetails/styled.ts | 48 +-- .../account/containers/OrdersPanel/index.tsx | 6 - .../application/containers/App/Updaters.tsx | 7 +- .../swap/hooks/useSwapButtonContext.ts | 4 +- .../setupTradeState/useSetupTradeState.ts | 7 +- .../hooks/useTradeFormButtonContext.ts | 8 +- .../containers/AccountSelectorModal/index.tsx | 104 ------ .../containers/AccountSelectorModal/state.ts | 11 - .../AccountSelectorModal/styled.tsx | 39 --- .../containers/ConnectWalletOptions.tsx | 84 ----- .../wallet/containers/WalletModal/index.tsx | 90 ----- .../wallet/containers/Web3Status/index.tsx | 12 +- .../modules/wallet/pure/StatusIcon/index.tsx | 19 +- .../modules/wallet/pure/WalletModal/index.tsx | 94 ------ .../wallet/pure/WalletModal/styled.tsx | 121 ------- .../wallet/pure/Web3StatusInner/index.tsx | 6 +- apps/cowswap-frontend/src/test-utils.tsx | 26 +- libs/wallet-provider/README.md | 3 - .../src/hooks/useWalletChainId.ts | 6 +- .../src/hooks/useWalletProvider.ts | 18 +- .../api/container/WalletProvider/index.tsx | 16 + libs/wallet/src/api/eip6963-types.ts | 29 -- libs/wallet/src/api/hooks.ts | 45 +-- .../api/hooks/useOpenWalletConnectionModal.ts | 7 + .../api/state/multiInjectedProvidersAtom.ts | 37 --- libs/wallet/src/api/types.ts | 20 +- libs/wallet/src/api/utils.ts | 9 + libs/wallet/src/api/utils/accountsLoaders.ts | 19 -- libs/wallet/src/api/utils/connection.ts | 45 --- libs/wallet/src/api/utils/getHwAccount.ts | 12 - libs/wallet/src/api/utils/getWalletType.ts | 16 - .../src/api/utils/getWalletTypeLabel.ts | 11 - libs/wallet/src/constants.ts | 9 - libs/wallet/src/index.ts | 58 +--- libs/wallet/src/reown/consts.ts | 5 + .../src/reown/hooks/useDisconnectWallet.ts | 10 + .../hooks/useIsSmartContractWallet.ts | 6 +- .../src/reown/hooks/useIsWalletConnect.ts | 7 + libs/wallet/src/reown/hooks/useSafeAppsSdk.ts | 7 + .../src/reown/hooks/useSwitchNetwork.ts | 19 ++ .../src/reown/hooks/useWalletMetadata.ts | 56 ++++ libs/wallet/src/reown/init.ts | 34 ++ .../updaters/WalletUpdater/index.ts} | 43 +-- .../Web3Provider/hooks/useEagerlyConnect.ts | 96 ------ .../hooks/useOrderedConnections.ts | 45 --- .../src/web3-react/Web3Provider/index.tsx | 37 --- .../web3-react/connection/asyncConnector.ts | 55 ---- .../src/web3-react/connection/coinbase.tsx | 61 ---- .../web3-react/connection/injectedOptions.tsx | 89 ----- .../web3-react/connection/injectedWallet.tsx | 19 -- .../src/web3-react/connection/metaMaskSdk.tsx | 54 --- .../src/web3-react/connection/network.tsx | 18 - .../src/web3-react/connection/onError.ts | 3 - .../wallet/src/web3-react/connection/safe.tsx | 16 - .../src/web3-react/connection/trezor.tsx | 36 -- .../web3-react/connection/walletConnectV2.tsx | 146 --------- .../web3-react/connectors/Injected/index.tsx | 270 --------------- .../TrezorConnector/TrezorProvider.ts | 49 --- .../TrezorConnector/getAccountsList.ts | 110 ------- .../connectors/TrezorConnector/index.ts | 159 --------- .../TrezorConnector/sendTransactionHandler.ts | 53 --- .../TrezorConnector/signTypedDataHandler.ts | 41 --- .../WalletConnectV2Connector/index.tsx | 18 - .../connectors/metaMaskSdk/index.ts | 307 ------------------ .../web3-react/hooks/useActivateConnector.ts | 67 ---- .../src/web3-react/hooks/useConnectionType.ts | 11 - .../web3-react/hooks/useDisconnectWallet.ts | 18 - .../web3-react/hooks/useIsActiveConnection.ts | 17 - .../web3-react/hooks/useIsWalletConnect.ts | 21 -- .../src/web3-react/hooks/useSafeAppsSdk.ts | 20 -- .../src/web3-react/hooks/useSwitchNetwork.ts | 17 - .../src/web3-react/hooks/useWalletMetadata.ts | 139 -------- .../pure/AccountIndexSelect/index.cosmos.tsx | 49 --- .../pure/AccountIndexSelect/index.tsx | 88 ----- .../pure/AccountIndexSelect/styled.tsx | 63 ---- libs/wallet/src/web3-react/types.ts | 20 -- .../updaters/HwAccountIndexUpdater.tsx | 49 --- .../web3-react/utils/getIsHardWareWallet.ts | 9 - .../utils/getWeb3ReactConnection.ts | 40 --- .../src/web3-react/utils/isChainAllowed.ts | 22 -- .../src/web3-react/utils/switchChain.ts | 47 --- package.json | 11 - 94 files changed, 310 insertions(+), 3516 deletions(-) delete mode 100644 apps/cowswap-frontend/src/legacy/state/user/userWalletMigration.ts delete mode 100644 apps/cowswap-frontend/src/modules/wallet/containers/AccountSelectorModal/index.tsx delete mode 100644 apps/cowswap-frontend/src/modules/wallet/containers/AccountSelectorModal/state.ts delete mode 100644 apps/cowswap-frontend/src/modules/wallet/containers/AccountSelectorModal/styled.tsx delete mode 100644 apps/cowswap-frontend/src/modules/wallet/containers/ConnectWalletOptions.tsx delete mode 100644 apps/cowswap-frontend/src/modules/wallet/containers/WalletModal/index.tsx delete mode 100644 apps/cowswap-frontend/src/modules/wallet/pure/WalletModal/index.tsx delete mode 100644 apps/cowswap-frontend/src/modules/wallet/pure/WalletModal/styled.tsx create mode 100644 libs/wallet/src/api/container/WalletProvider/index.tsx delete mode 100644 libs/wallet/src/api/eip6963-types.ts create mode 100644 libs/wallet/src/api/hooks/useOpenWalletConnectionModal.ts delete mode 100644 libs/wallet/src/api/state/multiInjectedProvidersAtom.ts create mode 100644 libs/wallet/src/api/utils.ts delete mode 100644 libs/wallet/src/api/utils/accountsLoaders.ts delete mode 100644 libs/wallet/src/api/utils/connection.ts delete mode 100644 libs/wallet/src/api/utils/getHwAccount.ts delete mode 100644 libs/wallet/src/api/utils/getWalletType.ts delete mode 100644 libs/wallet/src/api/utils/getWalletTypeLabel.ts create mode 100644 libs/wallet/src/reown/consts.ts create mode 100644 libs/wallet/src/reown/hooks/useDisconnectWallet.ts rename libs/wallet/src/{web3-react => reown}/hooks/useIsSmartContractWallet.ts (87%) create mode 100644 libs/wallet/src/reown/hooks/useIsWalletConnect.ts create mode 100644 libs/wallet/src/reown/hooks/useSafeAppsSdk.ts create mode 100644 libs/wallet/src/reown/hooks/useSwitchNetwork.ts create mode 100644 libs/wallet/src/reown/hooks/useWalletMetadata.ts create mode 100644 libs/wallet/src/reown/init.ts rename libs/wallet/src/{web3-react/updater.ts => reown/updaters/WalletUpdater/index.ts} (80%) delete mode 100644 libs/wallet/src/web3-react/Web3Provider/hooks/useEagerlyConnect.ts delete mode 100644 libs/wallet/src/web3-react/Web3Provider/hooks/useOrderedConnections.ts delete mode 100644 libs/wallet/src/web3-react/Web3Provider/index.tsx delete mode 100644 libs/wallet/src/web3-react/connection/asyncConnector.ts delete mode 100644 libs/wallet/src/web3-react/connection/coinbase.tsx delete mode 100644 libs/wallet/src/web3-react/connection/injectedOptions.tsx delete mode 100644 libs/wallet/src/web3-react/connection/injectedWallet.tsx delete mode 100644 libs/wallet/src/web3-react/connection/metaMaskSdk.tsx delete mode 100644 libs/wallet/src/web3-react/connection/network.tsx delete mode 100644 libs/wallet/src/web3-react/connection/onError.ts delete mode 100644 libs/wallet/src/web3-react/connection/safe.tsx delete mode 100644 libs/wallet/src/web3-react/connection/trezor.tsx delete mode 100644 libs/wallet/src/web3-react/connection/walletConnectV2.tsx delete mode 100644 libs/wallet/src/web3-react/connectors/Injected/index.tsx delete mode 100644 libs/wallet/src/web3-react/connectors/TrezorConnector/TrezorProvider.ts delete mode 100644 libs/wallet/src/web3-react/connectors/TrezorConnector/getAccountsList.ts delete mode 100644 libs/wallet/src/web3-react/connectors/TrezorConnector/index.ts delete mode 100644 libs/wallet/src/web3-react/connectors/TrezorConnector/sendTransactionHandler.ts delete mode 100644 libs/wallet/src/web3-react/connectors/TrezorConnector/signTypedDataHandler.ts delete mode 100644 libs/wallet/src/web3-react/connectors/WalletConnectV2Connector/index.tsx delete mode 100644 libs/wallet/src/web3-react/connectors/metaMaskSdk/index.ts delete mode 100644 libs/wallet/src/web3-react/hooks/useActivateConnector.ts delete mode 100644 libs/wallet/src/web3-react/hooks/useConnectionType.ts delete mode 100644 libs/wallet/src/web3-react/hooks/useDisconnectWallet.ts delete mode 100644 libs/wallet/src/web3-react/hooks/useIsActiveConnection.ts delete mode 100644 libs/wallet/src/web3-react/hooks/useIsWalletConnect.ts delete mode 100644 libs/wallet/src/web3-react/hooks/useSafeAppsSdk.ts delete mode 100644 libs/wallet/src/web3-react/hooks/useSwitchNetwork.ts delete mode 100644 libs/wallet/src/web3-react/hooks/useWalletMetadata.ts delete mode 100644 libs/wallet/src/web3-react/pure/AccountIndexSelect/index.cosmos.tsx delete mode 100644 libs/wallet/src/web3-react/pure/AccountIndexSelect/index.tsx delete mode 100644 libs/wallet/src/web3-react/pure/AccountIndexSelect/styled.tsx delete mode 100644 libs/wallet/src/web3-react/types.ts delete mode 100644 libs/wallet/src/web3-react/updaters/HwAccountIndexUpdater.tsx delete mode 100644 libs/wallet/src/web3-react/utils/getIsHardWareWallet.ts delete mode 100644 libs/wallet/src/web3-react/utils/getWeb3ReactConnection.ts delete mode 100644 libs/wallet/src/web3-react/utils/isChainAllowed.ts delete mode 100644 libs/wallet/src/web3-react/utils/switchChain.ts diff --git a/apps/cowswap-frontend/src/cosmos.decorator.tsx b/apps/cowswap-frontend/src/cosmos.decorator.tsx index 7fe7c98e80..5d8ca06a9a 100644 --- a/apps/cowswap-frontend/src/cosmos.decorator.tsx +++ b/apps/cowswap-frontend/src/cosmos.decorator.tsx @@ -6,8 +6,7 @@ import { ReactNode, StrictMode, useCallback, useContext } from 'react' import { CowAnalyticsProvider } from '@cowprotocol/analytics' import IMAGE_MOON from '@cowprotocol/assets/cow-swap/moon.svg' import IMAGE_SUN from '@cowprotocol/assets/cow-swap/sun.svg' -import { injectedWalletConnection, WalletUpdater } from '@cowprotocol/wallet' -import { Web3ReactProvider } from '@web3-react/core' +import { WalletProvider, WalletUpdater } from '@cowprotocol/wallet' import { LanguageProvider } from 'i18n' import SVG from 'react-inlinesvg' @@ -88,9 +87,6 @@ export const DemoContainer = styled.div` const chainId = 5 -const { connector, hooks } = injectedWalletConnection -connector.activate(chainId) - const Fixture = ({ children }: { children: ReactNode }) => { return ( @@ -99,7 +95,7 @@ const Fixture = ({ children }: { children: ReactNode }) => { - + @@ -110,7 +106,7 @@ const Fixture = ({ children }: { children: ReactNode }) => { - + diff --git a/apps/cowswap-frontend/src/cow-react/index.tsx b/apps/cowswap-frontend/src/cow-react/index.tsx index 0074fbdef9..5f0bc8c6c0 100644 --- a/apps/cowswap-frontend/src/cow-react/index.tsx +++ b/apps/cowswap-frontend/src/cow-react/index.tsx @@ -2,13 +2,13 @@ import '@reach/dialog/styles.css' import 'inter-ui' import './sentry' import { Provider as AtomProvider } from 'jotai' -import { ReactNode, StrictMode } from 'react' +import { StrictMode } from 'react' import { CowAnalyticsProvider } from '@cowprotocol/analytics' import { nodeRemoveChildFix } from '@cowprotocol/common-utils' import { jotaiStore } from '@cowprotocol/core' import { SnackbarsWidget } from '@cowprotocol/snackbars' -import { Web3Provider } from '@cowprotocol/wallet' +import { WalletProvider } from '@cowprotocol/wallet' import { LanguageProvider } from 'i18n' import { createRoot } from 'react-dom/client' @@ -19,7 +19,6 @@ import * as serviceWorkerRegistration from 'serviceWorkerRegistration' import { ThemedGlobalStyle, ThemeProvider } from 'theme' import { cowSwapStore } from 'legacy/state' -import { useAppSelector } from 'legacy/state/hooks' import { cowAnalytics } from 'modules/analytics' import { App } from 'modules/application/containers/App' @@ -47,10 +46,10 @@ function Main() { - - - - + + + + @@ -60,9 +59,9 @@ function Main() { - - - + + + @@ -72,17 +71,6 @@ function Main() { ) } -function Web3ProviderInstance({ children }: { children: ReactNode }) { - const selectedWallet = useAppSelector((state) => state.user.selectedWallet) - const { standaloneMode } = useInjectedWidgetParams() - - return ( - - {children} - - ) -} - function Toasts() { const { disableToastMessages = false } = useInjectedWidgetParams() diff --git a/apps/cowswap-frontend/src/legacy/components/Copy/CopyMod.tsx b/apps/cowswap-frontend/src/legacy/components/Copy/CopyMod.tsx index f3ed1a3528..b6d3c8032b 100644 --- a/apps/cowswap-frontend/src/legacy/components/Copy/CopyMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Copy/CopyMod.tsx @@ -10,7 +10,6 @@ import { LinkStyledButton } from 'theme' import { TransactionStatusText } from 'legacy/components/Copy/index' -// MOD imports export const CopyIcon = styled(LinkStyledButton)` --iconSize: var(${UI.ICON_SIZE_NORMAL}); color: inherit; @@ -33,13 +32,6 @@ export const CopyIcon = styled(LinkStyledButton)` } ` -/* const TransactionStatusText = styled.span` - margin-left: 0.25rem; - font-size: 0.825rem; - ${({ theme }) => theme.flexRowNoWrap}; - align-items: center; -` */ - export default function CopyHelper(props: { toCopy: string; children?: React.ReactNode; clickableLink?: boolean }) { const { toCopy, children, clickableLink } = props const [isCopied, setCopied] = useCopyClipboard() diff --git a/apps/cowswap-frontend/src/legacy/components/Header/NetworkSelector/index.tsx b/apps/cowswap-frontend/src/legacy/components/Header/NetworkSelector/index.tsx index e356a36b3c..73a5bee200 100644 --- a/apps/cowswap-frontend/src/legacy/components/Header/NetworkSelector/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Header/NetworkSelector/index.tsx @@ -7,7 +7,6 @@ import { useMediaQuery } from '@cowprotocol/common-hooks' import { UI } from '@cowprotocol/ui' import { Media } from '@cowprotocol/ui' import { useIsRabbyWallet, useIsSmartContractWallet, useWalletInfo } from '@cowprotocol/wallet' -import { useWalletProvider } from '@cowprotocol/wallet-provider' import { Trans } from '@lingui/macro' import { darken, transparentize } from 'color2k' @@ -155,7 +154,6 @@ const NetworkAlertLabel = styled.div` ` export function NetworkSelector() { - const provider = useWalletProvider() const { chainId } = useWalletInfo() const node = useRef(null) const nodeMobile = useRef(null) @@ -180,7 +178,7 @@ export function NetworkSelector() { const availableChains = useAvailableChains() - if (!provider || (isSmartContractWallet && !isRabbyWallet)) { + if (isSmartContractWallet && !isRabbyWallet) { return null } diff --git a/apps/cowswap-frontend/src/legacy/components/Tokens/TokensTable.tsx b/apps/cowswap-frontend/src/legacy/components/Tokens/TokensTable.tsx index 6dec034efc..4535bccbc5 100644 --- a/apps/cowswap-frontend/src/legacy/components/Tokens/TokensTable.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Tokens/TokensTable.tsx @@ -3,12 +3,12 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { BalancesState } from '@cowprotocol/balances-and-allowances' import { TokenWithLogo } from '@cowprotocol/common-const' import { useFilterTokens, usePrevious } from '@cowprotocol/common-hooks' +import { useOpenWalletConnectionModal } from '@cowprotocol/wallet' import { CurrencyAmount } from '@uniswap/sdk-core' import { Trans } from '@lingui/macro' import { useErrorModal } from 'legacy/hooks/useErrorMessageAndModal' -import { useToggleWalletModal } from 'legacy/state/application/hooks' import { usePendingApprovalModal } from 'common/hooks/usePendingApprovalModal' import { CowModal } from 'common/pure/Modal' @@ -58,7 +58,7 @@ export default function TokenTable({ prevQuery, debouncedQuery, }: TokenTableParams) { - const toggleWalletModal = useToggleWalletModal() + const toggleWalletModal = useOpenWalletConnectionModal() const tableRef = useRef(null) // reset pagination when user is in a page > 1, searching and deletes query @@ -104,30 +104,30 @@ export default function TokenTable({ const sortedTokens = useMemo(() => { return tokensData ? tokensData - .filter((x) => !!x) - .sort((tokenA, tokenB) => { - if (!sortField) { - // If there is no sort field selected (default) - return tokenComparator(tokenA, tokenB) - } else if (sortField === SORT_FIELD.BALANCE) { - // If the sort field is Balance - if (!balances) return 0 - - const balanceA = balances[tokenA.address.toLowerCase()] - const balanceB = balances[tokenB.address.toLowerCase()] - const balanceComp = balanceComparator(balanceA, balanceB) - - return applyDirection(balanceComp > 0, sortDirection) - } else { - // If the sort field is something else - const sortA = tokenA[sortField] - const sortB = tokenB[sortField] - - if (!sortA || !sortB) return 0 - return applyDirection(sortA > sortB, sortDirection) - } - }) - .slice(maxItems * (page - 1), page * maxItems) + .filter((x) => !!x) + .sort((tokenA, tokenB) => { + if (!sortField) { + // If there is no sort field selected (default) + return tokenComparator(tokenA, tokenB) + } else if (sortField === SORT_FIELD.BALANCE) { + // If the sort field is Balance + if (!balances) return 0 + + const balanceA = balances[tokenA.address.toLowerCase()] + const balanceB = balances[tokenB.address.toLowerCase()] + const balanceComp = balanceComparator(balanceA, balanceB) + + return applyDirection(balanceComp > 0, sortDirection) + } else { + // If the sort field is something else + const sortA = tokenA[sortField] + const sortB = tokenB[sortField] + + if (!sortA || !sortB) return 0 + return applyDirection(sortA > sortB, sortDirection) + } + }) + .slice(maxItems * (page - 1), page * maxItems) : [] }, [tokensData, maxItems, page, sortField, tokenComparator, balances, applyDirection, sortDirection]) @@ -154,14 +154,14 @@ export default function TokenTable({ setSortField(newField) setSortDirection(newDirection) }, - [sortDirection, sortField] + [sortDirection, sortField], ) const arrow = useCallback( (field: SORT_FIELD) => { return sortField === field ? (!sortDirection ? '↑' : '↓') : '' }, - [sortDirection, sortField] + [sortDirection, sortField], ) useEffect(() => { diff --git a/apps/cowswap-frontend/src/legacy/state/application/hooks.ts b/apps/cowswap-frontend/src/legacy/state/application/hooks.ts index ca72c2b086..ea31e61a18 100644 --- a/apps/cowswap-frontend/src/legacy/state/application/hooks.ts +++ b/apps/cowswap-frontend/src/legacy/state/application/hooks.ts @@ -27,10 +27,6 @@ export function useCloseModal(_modal: ApplicationModal): Command { return useCallback(() => dispatch(setOpenModal(null)), [dispatch]) } -export function useToggleWalletModal(): Command { - return useToggleModal(ApplicationModal.WALLET) -} - // TODO: These two seem to be gone from original. Check whether they have been replaced export function useOpenModal(modal: ApplicationModal): Command { const dispatch = useAppDispatch() diff --git a/apps/cowswap-frontend/src/legacy/state/user/hooks.tsx b/apps/cowswap-frontend/src/legacy/state/user/hooks.tsx index 2f86b41a32..aeb2a1becd 100644 --- a/apps/cowswap-frontend/src/legacy/state/user/hooks.tsx +++ b/apps/cowswap-frontend/src/legacy/state/user/hooks.tsx @@ -118,10 +118,6 @@ export function useUserTransactionTTL(): [number, (slippage: number) => void] { return [deadline, setUserDeadline] } -export function useSelectedWallet(): string | undefined { - return useAppSelector(({ user: { selectedWallet } }) => selectedWallet) -} - export function serializeToken(token: Currency | TokenWithLogo): SerializedToken { const address = getIsNativeToken(token) ? NATIVE_CURRENCIES[token.chainId as SupportedChainId].address : token.address diff --git a/apps/cowswap-frontend/src/legacy/state/user/reducer.ts b/apps/cowswap-frontend/src/legacy/state/user/reducer.ts index a9470d45b3..ab557234bf 100644 --- a/apps/cowswap-frontend/src/legacy/state/user/reducer.ts +++ b/apps/cowswap-frontend/src/legacy/state/user/reducer.ts @@ -1,15 +1,8 @@ import { DEFAULT_DEADLINE_FROM_NOW, SupportedLocale } from '@cowprotocol/common-const' -import { ConnectionType } from '@cowprotocol/wallet' import { createSlice } from '@reduxjs/toolkit' -import { userWalletMigration } from './userWalletMigration' - -userWalletMigration() - export interface UserState { - selectedWallet?: ConnectionType - matchesDarkMode: boolean // whether the dark mode media query matches userDarkMode: boolean | null // the user's choice for dark mode or light mode @@ -24,7 +17,6 @@ export interface UserState { } export const initialState: UserState = { - selectedWallet: undefined, matchesDarkMode: false, userDarkMode: null, // TODO: mod, shouldn't be here @@ -38,9 +30,6 @@ const userSlice = createSlice({ name: 'user', initialState, reducers: { - updateSelectedWallet(state, { payload: { wallet } }) { - state.selectedWallet = wallet - }, updateUserDarkMode(state, action) { state.userDarkMode = action.payload.userDarkMode }, @@ -63,7 +52,6 @@ const userSlice = createSlice({ }) export const { - updateSelectedWallet, updateMatchesDarkMode, updateUserDarkMode, updateHooksEnabled, diff --git a/apps/cowswap-frontend/src/legacy/state/user/userWalletMigration.ts b/apps/cowswap-frontend/src/legacy/state/user/userWalletMigration.ts deleted file mode 100644 index 876dc60b6f..0000000000 --- a/apps/cowswap-frontend/src/legacy/state/user/userWalletMigration.ts +++ /dev/null @@ -1,28 +0,0 @@ -const MIGRATION_FLAG = 'redux-user-wallet-migrated-2024-05-13' - -/** - * Along with EIP-6963 support, we are migrating the user wallet state to a new structure. - * Actually, we removed ConnectionType.INJECTED_WIDGET and unified ConnectionType.INJECTED - * TODO: Remove after 2024-07-20 - */ -export function userWalletMigration() { - if (localStorage.getItem(MIGRATION_FLAG)) return - - const storeName = 'redux_localstorage_simple_user' - - const store = localStorage.getItem(storeName) - - if (!store) return - - try { - const parsedStore = JSON.parse(store) - - delete parsedStore['selectedWallet'] - - localStorage.setItem(storeName, JSON.stringify(parsedStore)) - } catch (e) { - console.error('Could not parse user wallet store to migrate', e) - } - - localStorage.setItem(MIGRATION_FLAG, '1') -} diff --git a/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/AccountIcon.tsx b/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/AccountIcon.tsx index f765698373..74120cafac 100644 --- a/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/AccountIcon.tsx +++ b/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/AccountIcon.tsx @@ -1,7 +1,7 @@ import { useState } from 'react' import { HoverTooltip } from '@cowprotocol/ui' -import { useConnectionType, useWalletDetails } from '@cowprotocol/wallet' +import { useWalletDetails } from '@cowprotocol/wallet' import { StatusIcon } from 'modules/wallet/pure/StatusIcon' @@ -14,7 +14,6 @@ interface AccountIconProps { export const AccountIcon = ({ size = 16, account }: AccountIconProps) => { const walletDetails = useWalletDetails() - const connectionType = useConnectionType() const [imageLoadError, setImageLoadError] = useState(false) const { icon, walletName } = walletDetails @@ -23,7 +22,7 @@ export const AccountIcon = ({ size = 16, account }: AccountIconProps) => { if (imageLoadError || isIdenticon || !icon) { return ( - + ) } @@ -40,7 +39,7 @@ export const AccountIcon = ({ size = 16, account }: AccountIconProps) => { return ( - {walletName setImageLoadError(true)} /> + {walletName} setImageLoadError(true)} /> ) } diff --git a/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/index.cosmos.tsx index c2dc28ad00..2dff66a276 100644 --- a/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/index.cosmos.tsx @@ -1,4 +1,3 @@ -import { useSelect } from 'react-cosmos/client' import styled from 'styled-components/macro' import { AccountDetails } from './index' @@ -6,7 +5,6 @@ import { AccountDetails } from './index' const defaultProps = { pendingTransactions: [], confirmedTransactions: [], - toggleAccountSelectorModal: () => void 0, handleCloseOrdersPanel: () => void 0, } @@ -19,14 +17,9 @@ const Wrapper = styled.div` // const chainId = 5 function Host() { - const [isHardWare] = useSelect('Is hardware wallet', { - options: ['true', 'false'], - defaultValue: 'false', - }) - return ( - + ) } diff --git a/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/index.tsx b/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/index.tsx index 393a73bbd5..b903ec0615 100644 --- a/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/index.tsx +++ b/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/index.tsx @@ -1,18 +1,16 @@ import { Fragment } from 'react' import { CHAIN_INFO } from '@cowprotocol/common-const' -import { getEtherscanLink, getExplorerLabel, shortenAddress, getExplorerAddressLink } from '@cowprotocol/common-utils' +import { getEtherscanLink, getExplorerLabel, getExplorerAddressLink, shortenAddress } from '@cowprotocol/common-utils' import { Command } from '@cowprotocol/types' import { ExternalLink } from '@cowprotocol/ui' import { useWalletInfo, useWalletDetails, useIsWalletConnect, - getIsHardWareWallet, useDisconnectWallet, - useConnectionType, getIsInjectedMobileBrowser, - ConnectionType, + useIsSafeApp, } from '@cowprotocol/wallet' import { Trans } from '@lingui/macro' @@ -23,8 +21,6 @@ import { groupActivitiesByDay, useMultipleActivityDescriptors, } from 'legacy/hooks/useRecentActivity' -import { useAppDispatch } from 'legacy/state/hooks' -import { updateSelectedWallet } from 'legacy/state/user/reducer' import Activity from 'modules/account/containers/Transaction' import { useInjectedWidgetParams } from 'modules/injectedWidget' @@ -47,7 +43,6 @@ import { WalletActions, WalletName, WalletNameAddress, - WalletSelector, WalletSecondaryActions, WalletWrapper, Wrapper, @@ -74,8 +69,6 @@ export interface AccountDetailsProps { pendingTransactions: string[] confirmedTransactions: string[] ENSName?: string - forceHardwareWallet?: boolean - toggleAccountSelectorModal: Command handleCloseOrdersPanel: Command } @@ -83,14 +76,11 @@ export function AccountDetails({ pendingTransactions = [], confirmedTransactions = [], ENSName, - toggleAccountSelectorModal, handleCloseOrdersPanel, - forceHardwareWallet, }: AccountDetailsProps) { const { account, chainId } = useWalletInfo() - const connectionType = useConnectionType() + const isSafeApp = useIsSafeApp() const walletDetails = useWalletDetails() - const dispatch = useAppDispatch() const disconnectWallet = useDisconnectWallet() const isChainIdUnsupported = useIsProviderNetworkUnsupported() const { standaloneMode } = useInjectedWidgetParams() @@ -125,11 +115,9 @@ export function AccountDetails({ const handleDisconnectClick = () => { disconnectWallet() handleCloseOrdersPanel() - dispatch(updateSelectedWallet({ wallet: undefined })) } const networkLabel = CHAIN_INFO[chainId].label - const isHardWareWallet = forceHardwareWallet || getIsHardWareWallet(connectionType) return ( @@ -137,20 +125,13 @@ export function AccountDetails({ - { - if (isHardWareWallet) { - toggleAccountSelectorModal() - } - }} - > +
{(ENSName || account) && ( {ENSName ? ENSName : account && shortenAddress(account)} )} - +
{(ENSName || account) && }
@@ -177,7 +158,7 @@ export function AccountDetails({ )} - {standaloneMode !== false && connectionType !== ConnectionType.GNOSIS_SAFE && ( + {standaloneMode !== false && !isSafeApp && ( Disconnect diff --git a/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/styled.ts b/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/styled.ts index eb1c592a09..7c88f8e67b 100644 --- a/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/styled.ts +++ b/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/styled.ts @@ -1,4 +1,3 @@ -import { Command } from '@cowprotocol/types' import { ButtonSecondary, Media } from '@cowprotocol/ui' import { ExternalLink, StyledLink } from '@cowprotocol/ui' import { UI } from '@cowprotocol/ui' @@ -147,7 +146,9 @@ export const Wrapper = styled.div` ${WalletAction} { color: inherit; opacity: 0.85; - transition: color var(${UI.ANIMATION_DURATION}) ease-in-out, opacity var(${UI.ANIMATION_DURATION}) ease-in-out; + transition: + color var(${UI.ANIMATION_DURATION}) ease-in-out, + opacity var(${UI.ANIMATION_DURATION}) ease-in-out; margin: auto; padding: 0; border: 0; @@ -441,46 +442,3 @@ export const NetworkCard = styled(NetworkCardUni)` margin: 0 auto 12px; } ` - -interface WalletSelectorProps { - isHardWareWallet?: boolean - onClick?: Command -} - -export const WalletSelector = styled.div` - display: flex; - border-radius: 16px; - align-items: center; - justify-content: center; - transition: background var(${UI.ANIMATION_DURATION}) ease-in-out; - - ${({ isHardWareWallet }) => - isHardWareWallet && - ` - cursor: pointer; - border: 1px solid var(${UI.COLOR_TEXT_OPACITY_25}); - background: transparent; - padding: 6px 10px; - - &:after { - content: ''; - display: block; - width: 0; - height: 0; - border-left: 4px solid transparent; - border-right: 4px solid transparent; - border-top: 4px solid var(${UI.COLOR_TEXT}); - margin-left: 8px; - opacity: 0.5; - transition: opacity var(${UI.ANIMATION_DURATION}) ease-in-out; - } - - &:hover { - background: var(${UI.COLOR_TEXT_OPACITY_25}); - } - - &:hover::after { - opacity: 1; - } - `} -` diff --git a/apps/cowswap-frontend/src/modules/account/containers/OrdersPanel/index.tsx b/apps/cowswap-frontend/src/modules/account/containers/OrdersPanel/index.tsx index 80d6263434..c87eaf3064 100644 --- a/apps/cowswap-frontend/src/modules/account/containers/OrdersPanel/index.tsx +++ b/apps/cowswap-frontend/src/modules/account/containers/OrdersPanel/index.tsx @@ -1,5 +1,3 @@ -import { useSetAtom } from 'jotai' - import Close from '@cowprotocol/assets/images/x.svg?react' import { Media, UI } from '@cowprotocol/ui' import { useWalletDetails, useWalletInfo } from '@cowprotocol/wallet' @@ -7,8 +5,6 @@ import { useWalletDetails, useWalletInfo } from '@cowprotocol/wallet' import { transparentize } from 'color2k' import styled from 'styled-components/macro' -import { toggleAccountSelectorModalAtom } from 'modules/wallet/containers/AccountSelectorModal/state' - import { useCategorizeRecentActivity } from 'common/hooks/useCategorizeRecentActivity' import { useAccountModalState } from '../../hooks/useAccountModalState' @@ -134,7 +130,6 @@ const Wrapper = styled.div` export function OrdersPanel() { const { active, account } = useWalletInfo() const { ensName } = useWalletDetails() - const toggleAccountSelectorModal = useSetAtom(toggleAccountSelectorModalAtom) const { isOpen } = useAccountModalState() const { pendingActivity, confirmedActivity } = useCategorizeRecentActivity() @@ -160,7 +155,6 @@ export function OrdersPanel() { ENSName={ensName} pendingTransactions={pendingActivity} confirmedTransactions={confirmedActivity} - toggleAccountSelectorModal={toggleAccountSelectorModal} handleCloseOrdersPanel={handleCloseOrdersPanel} />
diff --git a/apps/cowswap-frontend/src/modules/application/containers/App/Updaters.tsx b/apps/cowswap-frontend/src/modules/application/containers/App/Updaters.tsx index 25d04938cd..421b5f7e45 100644 --- a/apps/cowswap-frontend/src/modules/application/containers/App/Updaters.tsx +++ b/apps/cowswap-frontend/src/modules/application/containers/App/Updaters.tsx @@ -1,7 +1,7 @@ import { BalancesAndAllowancesUpdater } from '@cowprotocol/balances-and-allowances' import { useFeatureFlags } from '@cowprotocol/common-hooks' import { TokensListsUpdater, UnsupportedTokensUpdater, WidgetTokensListsUpdater } from '@cowprotocol/tokens' -import { HwAccountIndexUpdater, useWalletInfo, WalletUpdater } from '@cowprotocol/wallet' +import { useWalletInfo, WalletUpdater } from '@cowprotocol/wallet' import { GasPriceStrategyUpdater } from 'legacy/state/gas/gas-price-strategy-updater' @@ -39,7 +39,7 @@ import { UserUpdater } from 'common/updaters/UserUpdater' export function Updaters() { const { chainId, account } = useWalletInfo() - const { tokenLists, appCode, customTokens, standaloneMode } = useInjectedWidgetParams() + const { tokenLists, appCode, customTokens } = useInjectedWidgetParams() const onTokenListAddingError = useOnTokenListAddingError() const { isGeoBlockEnabled, isYieldEnabled } = useFeatureFlags() const tradeTypeInfo = useTradeTypeInfo() @@ -48,8 +48,7 @@ export function Updaters() { return ( <> - - + {/**/} diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts index 91fe6ec473..5c219d1e21 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts @@ -6,12 +6,12 @@ import { useGnosisSafeInfo, useIsBundlingSupported, useIsSmartContractWallet, + useOpenWalletConnectionModal, useWalletDetails, useWalletInfo, } from '@cowprotocol/wallet' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' -import { useToggleWalletModal } from 'legacy/state/application/hooks' import { useGetQuoteAndStatus, useIsBestQuoteLoading } from 'legacy/state/price/hooks' import { Field } from 'legacy/state/types' @@ -57,7 +57,7 @@ export function useSwapButtonContext(input: SwapButtonInput, actions: TradeWidge currenciesIds, inputError: swapInputError, } = useDerivedSwapInfo() - const toggleWalletModal = useToggleWalletModal() + const toggleWalletModal = useOpenWalletConnectionModal() const { onCurrencySelection } = useSwapActionHandlers() const isBestQuoteLoading = useIsBestQuoteLoading() const tradeConfirmActions = useTradeConfirmActions() diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useSetupTradeState.ts b/apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useSetupTradeState.ts index 97bbd1cece..d0722f6394 100644 --- a/apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useSetupTradeState.ts +++ b/apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useSetupTradeState.ts @@ -46,13 +46,16 @@ export function useSetupTradeState(): void { const switchNetworkInWallet = useCallback( (targetChainId: SupportedChainId) => { - switchNetwork(targetChainId).catch((error: Error) => { + try { + switchNetwork(targetChainId) + } catch (error) { + // TODO: check the case // We are ignoring Gnosis safe context error // Because it's a normal situation when we are not in Gnosis safe App if (error.name === 'NoSafeContext') return console.error('Network switching error: ', error) - }) + } }, [switchNetwork], ) diff --git a/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormButtonContext.ts b/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormButtonContext.ts index 191924f82b..fa6dde0472 100644 --- a/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormButtonContext.ts +++ b/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormButtonContext.ts @@ -1,8 +1,6 @@ import { useMemo } from 'react' -import { useWalletDetails } from '@cowprotocol/wallet' - -import { useToggleWalletModal } from 'legacy/state/application/hooks' +import { useOpenWalletConnectionModal, useWalletDetails } from '@cowprotocol/wallet' import { useInjectedWidgetParams } from 'modules/injectedWidget' import { useWrapNativeFlow } from 'modules/trade' @@ -13,13 +11,13 @@ import { TradeFormButtonContext } from '../types' export function useTradeFormButtonContext( defaultText: string, - confirmTrade: () => void + confirmTrade: () => void, ): TradeFormButtonContext | null { const derivedState = useDerivedTradeState() const wrapNativeFlow = useWrapNativeFlow() const { isSupportedWallet } = useWalletDetails() const quote = useTradeQuote() - const toggleWalletModal = useToggleWalletModal() + const toggleWalletModal = useOpenWalletConnectionModal() const { standaloneMode } = useInjectedWidgetParams() return useMemo(() => { diff --git a/apps/cowswap-frontend/src/modules/wallet/containers/AccountSelectorModal/index.tsx b/apps/cowswap-frontend/src/modules/wallet/containers/AccountSelectorModal/index.tsx deleted file mode 100644 index b9deedced4..0000000000 --- a/apps/cowswap-frontend/src/modules/wallet/containers/AccountSelectorModal/index.tsx +++ /dev/null @@ -1,104 +0,0 @@ -import { useAtom, useAtomValue, useSetAtom } from 'jotai' -import React, { useCallback, useEffect, useMemo, useState } from 'react' - -import { useNativeTokensBalances } from '@cowprotocol/balances-and-allowances' -import { NATIVE_CURRENCIES } from '@cowprotocol/common-const' -import { useAddSnackbar } from '@cowprotocol/snackbars' -import { - accountsLoaders, - hwAccountIndexAtom, - AccountIndexSelect, - HardWareWallet, - useWalletInfo, - useConnectionType, - useWalletDetails, -} from '@cowprotocol/wallet' -import { Currency, CurrencyAmount } from '@uniswap/sdk-core' - -import { Trans } from '@lingui/macro' - -import { CowModal } from 'common/pure/Modal' - -import { accountSelectorModalAtom, toggleAccountSelectorModalAtom } from './state' -import * as styledEl from './styled' - -const EMPTY_BALANCES = {} - -export function AccountSelectorModal() { - const { chainId } = useWalletInfo() - const { isOpen } = useAtomValue(accountSelectorModalAtom) - const closeModal = useSetAtom(toggleAccountSelectorModalAtom) - - const [hwAccountIndex, setHwAccountIndex] = useAtom(hwAccountIndexAtom) - const connectionType = useConnectionType() - const addSnackbar = useAddSnackbar() - const { walletName, icon: walletIcon } = useWalletDetails() - - const nativeToken = NATIVE_CURRENCIES[chainId] - - const accountsLoader = useMemo(() => accountsLoaders[connectionType as HardWareWallet], [connectionType]) - - const [accountsList, setAccountsList] = useState(null) - - const nativeTokensBalances = useNativeTokensBalances(accountsList || undefined) - - const balances = useMemo(() => { - if (!nativeTokensBalances) return EMPTY_BALANCES - - return Object.keys(nativeTokensBalances).reduce<{ [account: string]: CurrencyAmount | undefined }>( - (acc, key) => { - const balance = nativeTokensBalances[key] - - if (balance) { - acc[key] = CurrencyAmount.fromRawAmount(nativeToken, balance.toString()) - } - return acc - }, - {} - ) - }, [nativeTokensBalances, nativeToken]) - - const loadMoreAccounts = useCallback(async () => { - if (!accountsLoader) return - - return accountsLoader.loadMoreAccounts().then(() => { - setAccountsList(accountsLoader.getAccounts()) - }) - }, [accountsLoader]) - - const onAccountIndexChange = useCallback( - (index: number) => { - setHwAccountIndex(index) - closeModal() - - addSnackbar({ content: {walletName} account changed, id: 'account-changed', icon: 'success' }) - }, - [walletName, addSnackbar, setHwAccountIndex, closeModal] - ) - - useEffect(() => { - setAccountsList(accountsLoader?.getAccounts() || null) - }, [accountsLoader]) - - if (!accountsList || !accountsLoader) return null - - return ( - - - -

- Select {walletName} Account -

- -
- -
-
- ) -} diff --git a/apps/cowswap-frontend/src/modules/wallet/containers/AccountSelectorModal/state.ts b/apps/cowswap-frontend/src/modules/wallet/containers/AccountSelectorModal/state.ts deleted file mode 100644 index 6a2bae21f5..0000000000 --- a/apps/cowswap-frontend/src/modules/wallet/containers/AccountSelectorModal/state.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { atom } from 'jotai' - -export interface AccountSelectorModalState { - isOpen: boolean -} - -export const accountSelectorModalAtom = atom({ isOpen: false }) - -export const toggleAccountSelectorModalAtom = atom(null, (get, set) => { - set(accountSelectorModalAtom, { isOpen: !get(accountSelectorModalAtom).isOpen }) -}) diff --git a/apps/cowswap-frontend/src/modules/wallet/containers/AccountSelectorModal/styled.tsx b/apps/cowswap-frontend/src/modules/wallet/containers/AccountSelectorModal/styled.tsx deleted file mode 100644 index 78499edcab..0000000000 --- a/apps/cowswap-frontend/src/modules/wallet/containers/AccountSelectorModal/styled.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import Close from '@cowprotocol/assets/images/x.svg?react' -import { UI } from '@cowprotocol/ui' - -import styled from 'styled-components/macro' - -export const CloseIcon = styled((props) => )` - opacity: 0.6; - transition: opacity var(${UI.ANIMATION_DURATION}) ease-in-out; - stroke: var(${UI.COLOR_TEXT}); - width: 24px; - height: 24px; - cursor: pointer; - - &:hover { - opacity: 1; - } -` - -export const Header = styled.div` - display: flex; - justify-content: space-between; - margin-bottom: 20px; - - h3 { - display: flex; - gap: 10px; - margin: 0; - } -` - -export const Wrapper = styled.div` - padding: 20px; - width: 100%; -` - -export const WalletIcon = styled.img` - width: 24px; - height: 24px; -` diff --git a/apps/cowswap-frontend/src/modules/wallet/containers/ConnectWalletOptions.tsx b/apps/cowswap-frontend/src/modules/wallet/containers/ConnectWalletOptions.tsx deleted file mode 100644 index 9885ea144e..0000000000 --- a/apps/cowswap-frontend/src/modules/wallet/containers/ConnectWalletOptions.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import { useTheme } from '@cowprotocol/common-hooks' -import { isMobile, isInjectedWidget } from '@cowprotocol/common-utils' -import { - CoinbaseWalletOption, - InjectedOption as DefaultInjectedOption, - MetaMaskSdkOption, - TrezorOption, - WalletConnectV2Option, - getIsInjected, - TryActivation, - useMultiInjectedProviders, - Eip6963Option, - COINBASE_WALLET_RDNS, - getIsInjectedMobileBrowser, - EIP6963ProviderDetail, -} from '@cowprotocol/wallet' - -import { useSelectedWallet } from 'legacy/state/user/hooks' - - -export function ConnectWalletOptions({ tryActivation }: { tryActivation: TryActivation }) { - const selectedWallet = useSelectedWallet() - const multiInjectedProviders = useMultiInjectedProviders() - const { darkMode } = useTheme() - - const hasCoinbaseEip6963 = multiInjectedProviders.some((provider) => provider.info.rdns === COINBASE_WALLET_RDNS) - - const isWidget = isInjectedWidget() - const isInjectedMobileBrowser = getIsInjectedMobileBrowser() - - const connectionProps = { darkMode, selectedWallet, tryActivation } - - const metaMaskSdkOption = - const coinbaseWalletOption = (!hasCoinbaseEip6963 && ) ?? null - const walletConnectionV2Option = - ((!isInjectedMobileBrowser || isWidget) && ) ?? null - const trezorOption = (!isInjectedMobileBrowser && !isMobile && ) ?? null - const injectedOption = (getIsInjected() && ) ?? null - - return ( - <> - {injectedOption} - {metaMaskSdkOption} - {walletConnectionV2Option} - {coinbaseWalletOption} - {trezorOption} - - ) -} - -interface InjectedOptionsProps { - multiInjectedProviders: EIP6963ProviderDetail[] - - connectionProps: { - darkMode: boolean - tryActivation: TryActivation - selectedWallet: string | undefined - } -} - -function InjectedOptions({ connectionProps, multiInjectedProviders }: InjectedOptionsProps) { - if (multiInjectedProviders.length) { - return ( - <> - {multiInjectedProviders - // Even if we detect the MetaMask Extension, we prefer to use the MetaMask SDK - .filter((providerInfo) => !providerInfo.info.rdns.startsWith('io.metamask')) - .map((providerInfo) => { - return ( - - ) - })} - - ) - } - - return -} diff --git a/apps/cowswap-frontend/src/modules/wallet/containers/WalletModal/index.tsx b/apps/cowswap-frontend/src/modules/wallet/containers/WalletModal/index.tsx deleted file mode 100644 index 1a9e4e3394..0000000000 --- a/apps/cowswap-frontend/src/modules/wallet/containers/WalletModal/index.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import { useSetAtom } from 'jotai' -import { useCallback, useEffect, useMemo, useState } from 'react' - -import { errorToString } from '@cowprotocol/common-utils' -import { useWalletInfo, useActivateConnector, ConnectionType } from '@cowprotocol/wallet' - -import { useCloseModal, useModalIsOpen } from 'legacy/state/application/hooks' -import { ApplicationModal } from 'legacy/state/application/reducer' -import { useAppDispatch } from 'legacy/state/hooks' -import { updateSelectedWallet } from 'legacy/state/user/reducer' - -import { useAccountModalState } from 'modules/account' - -import { useSetWalletConnectionError } from '../../hooks/useSetWalletConnectionError' -import { useWalletConnectionError } from '../../hooks/useWalletConnectionError' -import { WalletModal as WalletModalPure, WalletModalView } from '../../pure/WalletModal' -import { toggleAccountSelectorModalAtom } from '../AccountSelectorModal/state' - -export function WalletModal() { - const dispatch = useAppDispatch() - const { account } = useWalletInfo() - const setWalletConnectionError = useSetWalletConnectionError() - - const [walletView, setWalletView] = useState('options') - const isPendingView = walletView === 'pending' - - const pendingError = useWalletConnectionError() - - const walletModalOpen = useModalIsOpen(ApplicationModal.WALLET) - const closeWalletModal = useCloseModal(ApplicationModal.WALLET) - const toggleAccountSelectorModal = useSetAtom(toggleAccountSelectorModalAtom) - - const openOptions = useCallback(() => setWalletView('options'), [setWalletView]) - - const { isOpen: isAccountModalOpen } = useAccountModalState() - // Wallet changing currently is only possible through the account modal - const isWalletChangingFlow = isAccountModalOpen - - useEffect(() => { - if (walletModalOpen) { - setWalletView(account ? 'account' : 'options') - } - }, [walletModalOpen, setWalletView, account]) - - useEffect(() => { - if (!isPendingView) { - setWalletConnectionError(undefined) - } - }, [isPendingView, setWalletConnectionError]) - - const { tryActivation, retryPendingActivation } = useActivateConnector( - useMemo( - () => ({ - skipNetworkChanging: isWalletChangingFlow, - beforeActivation() { - setWalletView('pending') - setWalletConnectionError(undefined) - }, - afterActivation(isHardWareWallet: boolean, connectionType: ConnectionType) { - dispatch(updateSelectedWallet({ wallet: connectionType })) - - if (isHardWareWallet) { - toggleAccountSelectorModal() - } - - closeWalletModal() - setWalletView('account') - }, - onActivationError(error: any) { - dispatch(updateSelectedWallet({ wallet: undefined })) - setWalletConnectionError(errorToString(error)) - }, - }), - [isWalletChangingFlow, closeWalletModal, dispatch, setWalletConnectionError, toggleAccountSelectorModal] - ) - ) - - return ( - - ) -} diff --git a/apps/cowswap-frontend/src/modules/wallet/containers/Web3Status/index.tsx b/apps/cowswap-frontend/src/modules/wallet/containers/Web3Status/index.tsx index 73df792457..cbc1740e32 100644 --- a/apps/cowswap-frontend/src/modules/wallet/containers/Web3Status/index.tsx +++ b/apps/cowswap-frontend/src/modules/wallet/containers/Web3Status/index.tsx @@ -1,11 +1,7 @@ -import { useConnectionType, useWalletDetails, useWalletInfo } from '@cowprotocol/wallet' - -import { useToggleWalletModal } from 'legacy/state/application/hooks' +import { useOpenWalletConnectionModal, useWalletDetails, useWalletInfo } from '@cowprotocol/wallet' import { Web3StatusInner } from '../../pure/Web3StatusInner' import { Wrapper } from '../../pure/Web3StatusInner/styled' -import { AccountSelectorModal } from '../AccountSelectorModal' -import { WalletModal } from '../WalletModal' export interface Web3StatusProps { pendingActivities: string[] @@ -14,11 +10,10 @@ export interface Web3StatusProps { } export function Web3Status({ pendingActivities, className, onClick }: Web3StatusProps) { - const connectionType = useConnectionType() const { account } = useWalletInfo() const { ensName } = useWalletDetails() - const toggleWalletModal = useToggleWalletModal() + const toggleWalletModal = useOpenWalletConnectionModal() return ( @@ -27,10 +22,7 @@ export function Web3Status({ pendingActivities, className, onClick }: Web3Status account={account} ensName={ensName} connectWallet={toggleWalletModal} - connectionType={connectionType} /> - - ) } diff --git a/apps/cowswap-frontend/src/modules/wallet/pure/StatusIcon/index.tsx b/apps/cowswap-frontend/src/modules/wallet/pure/StatusIcon/index.tsx index 211c15bbb6..710174cb32 100644 --- a/apps/cowswap-frontend/src/modules/wallet/pure/StatusIcon/index.tsx +++ b/apps/cowswap-frontend/src/modules/wallet/pure/StatusIcon/index.tsx @@ -1,5 +1,4 @@ -import { Identicon, ConnectionType } from '@cowprotocol/wallet' -import { CoinbaseWalletIcon, WalletConnectIcon } from '@cowprotocol/wallet' +import { Identicon } from '@cowprotocol/wallet' import styled from 'styled-components/macro' @@ -16,24 +15,12 @@ const IconWrapper = styled.div<{ size?: number }>` ` export interface StatusIconProps { - connectionType: ConnectionType account?: string size?: number } -export function StatusIcon({ connectionType, account, size = 16 }: StatusIconProps) { - let image - switch (connectionType) { - case ConnectionType.INJECTED: - image = - break - case ConnectionType.WALLET_CONNECT_V2: - image = WalletConnect - break - case ConnectionType.COINBASE_WALLET: - image = Coinbase Wallet - break - } +export function StatusIcon({ account, size = 16 }: StatusIconProps) { + const image = return {image} } diff --git a/apps/cowswap-frontend/src/modules/wallet/pure/WalletModal/index.tsx b/apps/cowswap-frontend/src/modules/wallet/pure/WalletModal/index.tsx deleted file mode 100644 index b8c0851412..0000000000 --- a/apps/cowswap-frontend/src/modules/wallet/pure/WalletModal/index.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import { Command } from '@cowprotocol/types' -import { AutoRow } from '@cowprotocol/ui' -import { TryActivation } from '@cowprotocol/wallet' - -import { Trans } from '@lingui/macro' -import { ThemedText } from 'theme' - -import { LightCard } from 'legacy/components/Card' -import { AutoColumn } from 'legacy/components/Column' - -import { CloseIcon, ContentWrapper, CowModal, HeaderRow, HoverText } from 'common/pure/Modal' - -import { CloseColor, OptionGrid, TermsWrapper, UpperSection, Wrapper } from './styled' - -import { ConnectWalletOptions } from '../../containers/ConnectWalletOptions' -import { PendingView } from '../PendingView' - -export type WalletModalView = 'options' | 'account' | 'pending' - -interface WalletModalProps { - isOpen: boolean - onDismiss: Command - view: WalletModalView - openOptions: Command - tryConnection: Command - pendingError: string | undefined - tryActivation: TryActivation - account: string | undefined -} - -export function WalletModal(props: Readonly) { - const { isOpen, onDismiss, view, openOptions, pendingError, tryActivation, tryConnection } = props - - const isPending = view === 'pending' - - return ( - - - - {!isPending && ( - - - Connect a wallet - - - - - - - )} - - - {isPending && ( - - )} - {!isPending && ( - - - - )} - {!pendingError && ( - - - - - - - - )} - - - - - - ) -} - -function CustomTerms() { - return ( - - - By connecting a wallet, you acknowledge that you have read, understood and agree to the interface’s{' '} - - Terms & Conditions - - . - - - ) -} diff --git a/apps/cowswap-frontend/src/modules/wallet/pure/WalletModal/styled.tsx b/apps/cowswap-frontend/src/modules/wallet/pure/WalletModal/styled.tsx deleted file mode 100644 index b0a4090f5b..0000000000 --- a/apps/cowswap-frontend/src/modules/wallet/pure/WalletModal/styled.tsx +++ /dev/null @@ -1,121 +0,0 @@ -import Close from '@cowprotocol/assets/images/x.svg?react' -import { ExternalLink, Media } from '@cowprotocol/ui' -import { UI } from '@cowprotocol/ui' - -import styled from 'styled-components/macro' - -export const TermsWrapper = styled.div` - color: inherit; - font-size: 13px; - line-height: 1.5; - text-align: center; - padding: 0 32px; - - > a { - color: inherit; - text-decoration: underline; - } - - > a:hover { - color: var(${UI.COLOR_PRIMARY}); - } -` - -export const Blurb = styled.div` - width: 100%; - margin: 16px 0 0; - text-align: center; - font-size: smaller; - line-height: 1.5; -` - -export const NewToEthereum = () => ( - -
New to decentralised applications?
{' '} - Learn more about wallets -
-) - -export const CloseColor = styled((props) => )` - --size: 16px; - color: inherit; - width: var(--size); - height: var(--size); - - path { - stroke: currentColor; - } -` - -export const Wrapper = styled.div` - ${({ theme }) => theme.flexColumnNoWrap} - margin: 0; - padding: 0; - width: 100%; - color: inherit; - overflow-y: auto; // fallback for 'overlay' - overflow-y: overlay; -` - -export const UpperSection = styled.div` - position: relative; - color: inherit; - - h5 { - margin: 0; - margin-bottom: 0.5rem; - font-size: 1rem; - font-weight: 400; - } - - h5:last-child { - margin-bottom: 0px; - } - - h4 { - margin-top: 0; - font-weight: 500; - } -` - -export const OptionGrid = styled.div` - display: grid; - grid-gap: 10px; - grid-template-columns: repeat(4, 1fr); - grid-template-rows: max-content; - color: inherit; - - ${Media.upToSmall()} { - grid-template-columns: repeat(3, 1fr); - } - ${Media.upToExtraSmall()} { - grid-template-columns: repeat(2, 1fr); - } -` - -export const IconWrapper = styled.div` - --size: 42px; - display: flex; - width: var(--size); - height: var(--size); - border-radius: var(--size); - align-items: center; - justify-content: center; - background: transparent; - border: 1px solid var(${UI.COLOR_BORDER}); - color: inherit; - padding: 8px; - margin: 0 12px 0 0; - - > svg { - width: 100%; - height: 100%; - color: inherit; - } - - > svg > path { - color: currentColor; - fill: var(--color); - stroke: var(--color); - } -` diff --git a/apps/cowswap-frontend/src/modules/wallet/pure/Web3StatusInner/index.tsx b/apps/cowswap-frontend/src/modules/wallet/pure/Web3StatusInner/index.tsx index f73b7c5f94..ffd256d438 100644 --- a/apps/cowswap-frontend/src/modules/wallet/pure/Web3StatusInner/index.tsx +++ b/apps/cowswap-frontend/src/modules/wallet/pure/Web3StatusInner/index.tsx @@ -1,7 +1,6 @@ import { shortenAddress } from '@cowprotocol/common-utils' import { Command } from '@cowprotocol/types' import { Loader, RowBetween } from '@cowprotocol/ui' -import { ConnectionType } from '@cowprotocol/wallet' import { Trans } from '@lingui/macro' import ICON_WALLET from 'assets/icon/wallet.svg' @@ -17,12 +16,11 @@ export interface Web3StatusInnerProps { account?: string pendingCount: number connectWallet: Command - connectionType: ConnectionType ensName?: string | null } export function Web3StatusInner(props: Web3StatusInnerProps) { - const { account, pendingCount, ensName, connectionType, connectWallet } = props + const { account, pendingCount, ensName, connectWallet } = props const hasPendingTransactions = !!pendingCount const isUpToExtraSmall = useMediaQuery(upToExtraSmall) @@ -41,7 +39,7 @@ export function Web3StatusInner(props: Web3StatusInnerProps) { ) : ( {ensName || shortenAddress(account, isUpToTiny ? 4 : isUpToExtraSmall ? 3 : 4)} )} - {!hasPendingTransactions && } + {!hasPendingTransactions && } ) } diff --git a/apps/cowswap-frontend/src/test-utils.tsx b/apps/cowswap-frontend/src/test-utils.tsx index c88711b988..4cc576ae41 100644 --- a/apps/cowswap-frontend/src/test-utils.tsx +++ b/apps/cowswap-frontend/src/test-utils.tsx @@ -4,9 +4,7 @@ import { createStore } from 'jotai/vanilla' import { ReactElement, ReactNode, useMemo } from 'react' import { isInjectedWidget } from '@cowprotocol/common-utils' -import { Web3Provider } from '@cowprotocol/wallet' -import { initializeConnector, Web3ReactHooks, Web3ReactProvider } from '@web3-react/core' -import { Connector } from '@web3-react/types' +import { WalletProvider } from '@cowprotocol/wallet' import { i18n } from '@lingui/core' import { I18nProvider } from '@lingui/react' @@ -40,9 +38,9 @@ const WithProviders = ({ children }: { children?: ReactNode }) => { - + {children} - + @@ -54,27 +52,11 @@ const customRender = (ui: ReactElement) => render(ui, { wrapper: WithProviders } export * from '@testing-library/react' export { customRender as render } -class MockedConnector extends Connector { - activate(): Promise { - return Promise.resolve() - } - - getActions() { - return this.actions - } -} - -export const [mockedConnector, mockedConnectorHooks] = initializeConnector( - (actions) => new MockedConnector(actions) -) - export function WithMockedWeb3({ children, location }: { children?: ReactNode; location?: LocationDescriptorObject }) { - const connectors: [Connector, Web3ReactHooks][] = [[mockedConnector, mockedConnectorHooks]] - return ( - {children} + {children} ) diff --git a/libs/wallet-provider/README.md b/libs/wallet-provider/README.md index 7188387883..9e2fc0beb2 100644 --- a/libs/wallet-provider/README.md +++ b/libs/wallet-provider/README.md @@ -4,9 +4,6 @@ The library contains only two hooks: - `useWalletChainId()` returns actual wallet chainId. In 99% cases we use chainId from `useWalletInfo()` which returns always valid and supported chainId, but in some cases we need a real chainId from the wallet. - `useWalletProvider()` returns ethers `Web3Provider`. -Those hooks are actually wrappers around `useWeb3React()` from `@web3-react/core`. -Once we decide to use other library, we can easily replace it. - ## Developers #### Test diff --git a/libs/wallet-provider/src/hooks/useWalletChainId.ts b/libs/wallet-provider/src/hooks/useWalletChainId.ts index 8e6a770641..389c676077 100644 --- a/libs/wallet-provider/src/hooks/useWalletChainId.ts +++ b/libs/wallet-provider/src/hooks/useWalletChainId.ts @@ -1,7 +1,7 @@ -import { useWeb3React } from '@web3-react/core' +import { useAppKitNetwork } from '@reown/appkit/react' export function useWalletChainId(): number | undefined { - const { chainId } = useWeb3React() + const { chainId } = useAppKitNetwork() - return chainId + return chainId ? +chainId : undefined } diff --git a/libs/wallet-provider/src/hooks/useWalletProvider.ts b/libs/wallet-provider/src/hooks/useWalletProvider.ts index 7c337cf7f7..0dc5674117 100644 --- a/libs/wallet-provider/src/hooks/useWalletProvider.ts +++ b/libs/wallet-provider/src/hooks/useWalletProvider.ts @@ -1,8 +1,18 @@ -import type { Web3Provider } from '@ethersproject/providers' -import { useWeb3React } from '@web3-react/core' +import { SWR_NO_REFRESH_OPTIONS } from '@cowprotocol/common-const' +import { Web3Provider, ExternalProvider } from '@ethersproject/providers' + +import { useAppKitNetwork, useAppKitProvider } from '@reown/appkit/react' +import useSWR from 'swr' export function useWalletProvider(): Web3Provider | undefined { - const { provider } = useWeb3React() + const { walletProvider } = useAppKitProvider('eip155') + const { chainId } = useAppKitNetwork() - return provider + return useSWR( + walletProvider ? [walletProvider, chainId] : null, + ([walletProvider, chainId]) => { + return new Web3Provider(walletProvider as ExternalProvider, chainId) + }, + SWR_NO_REFRESH_OPTIONS, + ).data } diff --git a/libs/wallet/src/api/container/WalletProvider/index.tsx b/libs/wallet/src/api/container/WalletProvider/index.tsx new file mode 100644 index 0000000000..b5df83c0ec --- /dev/null +++ b/libs/wallet/src/api/container/WalletProvider/index.tsx @@ -0,0 +1,16 @@ +import { ReactNode, useEffect } from 'react' + +import { useTheme } from '@cowprotocol/common-hooks' + +import { reownAppKit } from '../../../reown/init' + +export function WalletProvider({ children }: { children: ReactNode }) { + const { darkMode } = useTheme() + + useEffect(() => { + // TODO: configure setThemeVariables() + reownAppKit.setThemeMode(darkMode ? 'dark' : 'light') + }, [darkMode]) + + return children +} diff --git a/libs/wallet/src/api/eip6963-types.ts b/libs/wallet/src/api/eip6963-types.ts deleted file mode 100644 index b65529fb0a..0000000000 --- a/libs/wallet/src/api/eip6963-types.ts +++ /dev/null @@ -1,29 +0,0 @@ -import type { Command } from '@cowprotocol/types' -import type { RequestArguments } from '@web3-react/types' - -import type EventEmitter from 'eventemitter3' - -export interface EIP6963ProviderInfo { - uuid: string - name: string - icon: string - rdns: string -} - -// https://eips.ethereum.org/EIPS/eip-6963 -export interface EIP6963ProviderDetail { - info: EIP6963ProviderInfo - provider: EIP1193Provider -} - -// https://eips.ethereum.org/EIPS/eip-1193 -export type EIP1193Provider = EventEmitter & { - isConnected?: () => boolean - request(args: RequestArguments): Promise - enable?: Command -} - -export interface EIP6963AnnounceProviderEvent extends CustomEvent { - type: 'eip6963:announceProvider' - detail: EIP6963ProviderDetail -} diff --git a/libs/wallet/src/api/hooks.ts b/libs/wallet/src/api/hooks.ts index 29762530a6..518c532c39 100644 --- a/libs/wallet/src/api/hooks.ts +++ b/libs/wallet/src/api/hooks.ts @@ -1,16 +1,12 @@ -import { useAtomValue, useSetAtom } from 'jotai' +import { useAtomValue } from 'jotai' + +import { useWalletInfo as useReOwnWalletInfo } from '@reown/appkit/react' import { gnosisSafeInfoAtom, walletDetailsAtom, walletDisplayedAddress, walletInfoAtom } from './state' -import { - multiInjectedProvidersAtom, - selectedEip6963ProviderAtom, - selectedEip6963ProviderRdnsAtom, -} from './state/multiInjectedProvidersAtom' -import { ConnectionType, GnosisSafeInfo, WalletDetails, WalletInfo } from './types' +import { GnosisSafeInfo, WalletDetails, WalletInfo } from './types' import { RABBY_RDNS, WATCH_ASSET_SUPPORED_WALLETS } from '../constants' -import { useConnectionType } from '../web3-react/hooks/useConnectionType' -import { useIsSafeApp } from '../web3-react/hooks/useWalletMetadata' +import { useIsSafeApp } from '../reown/hooks/useWalletMetadata' export function useWalletInfo(): WalletInfo { return useAtomValue(walletInfoAtom) @@ -35,37 +31,16 @@ export function useIsBundlingSupported(): boolean { return useIsSafeApp() } -export function useMultiInjectedProviders() { - return useAtomValue(multiInjectedProvidersAtom) -} - -export function useSetEip6963Provider() { - return useSetAtom(selectedEip6963ProviderRdnsAtom) -} - -export function useSelectedEip6963ProviderRdns() { - return useAtomValue(selectedEip6963ProviderRdnsAtom) -} - -export function useSelectedEip6963ProviderInfo() { - return useAtomValue(selectedEip6963ProviderAtom) -} - export function useIsAssetWatchingSupported(): boolean { - const connectionType = useConnectionType() - const info = useSelectedEip6963ProviderInfo() + const { walletInfo } = useReOwnWalletInfo() - if (!info || connectionType !== ConnectionType.INJECTED) return false + if (!walletInfo?.rdns) return false - // TODO: check other wallets and extend the array - return WATCH_ASSET_SUPPORED_WALLETS.includes(info.info.rdns) + return WATCH_ASSET_SUPPORED_WALLETS.includes(walletInfo.rdns as string) } export function useIsRabbyWallet(): boolean { - const connectionType = useConnectionType() - const info = useSelectedEip6963ProviderInfo() - - if (!info || connectionType !== ConnectionType.INJECTED) return false + const { walletInfo } = useReOwnWalletInfo() - return RABBY_RDNS === info.info.rdns + return walletInfo?.rdns === RABBY_RDNS } diff --git a/libs/wallet/src/api/hooks/useOpenWalletConnectionModal.ts b/libs/wallet/src/api/hooks/useOpenWalletConnectionModal.ts new file mode 100644 index 0000000000..321f556e61 --- /dev/null +++ b/libs/wallet/src/api/hooks/useOpenWalletConnectionModal.ts @@ -0,0 +1,7 @@ +import { useAppKit } from '@reown/appkit/react' + +export function useOpenWalletConnectionModal() { + const { open } = useAppKit() + + return open +} diff --git a/libs/wallet/src/api/state/multiInjectedProvidersAtom.ts b/libs/wallet/src/api/state/multiInjectedProvidersAtom.ts deleted file mode 100644 index c5a1a9b9f3..0000000000 --- a/libs/wallet/src/api/state/multiInjectedProvidersAtom.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { atom } from 'jotai' -import { atomWithStorage } from 'jotai/utils' - -import { getJotaiIsolatedStorage, jotaiStore } from '@cowprotocol/core' - -import { EIP6963AnnounceProviderEvent, EIP6963ProviderDetail } from '../eip6963-types' - -export const multiInjectedProvidersAtom = atom([]) - -// RDNS of the selected EIP-6963 provider -export const selectedEip6963ProviderRdnsAtom = atomWithStorage( - 'selectedEip6963ProviderAtom:v0', - null, - getJotaiIsolatedStorage() -) - -export const selectedEip6963ProviderAtom = atom((get) => { - const providers = get(multiInjectedProvidersAtom) - const selectedProviderId = get(selectedEip6963ProviderRdnsAtom) - - return selectedProviderId ? providers.find((p) => p.info.rdns === selectedProviderId) : null -}) - -window.addEventListener('eip6963:announceProvider', (event: Event) => { - const providerEvent = event as EIP6963AnnounceProviderEvent - - jotaiStore.set(multiInjectedProvidersAtom, (prev: EIP6963ProviderDetail[]) => { - const newProvider = providerEvent.detail - const existingProvider = prev.find((p) => p.info.rdns === newProvider.info.rdns) - - if (existingProvider) return prev - - return [newProvider, ...prev] - }) -}) - -window.dispatchEvent(new Event('eip6963:requestProvider')) diff --git a/libs/wallet/src/api/types.ts b/libs/wallet/src/api/types.ts index c43a7721e9..cfcb916aeb 100644 --- a/libs/wallet/src/api/types.ts +++ b/libs/wallet/src/api/types.ts @@ -1,17 +1,5 @@ import { SupportedChainId } from '@cowprotocol/cow-sdk' -import { SafeInfoResponse } from '@safe-global/api-kit' - -export * from './eip6963-types' - -export enum ConnectionType { - NETWORK = 'NETWORK', - INJECTED = 'INJECTED', - WALLET_CONNECT_V2 = 'WALLET_CONNECT_V2', - COINBASE_WALLET = 'COINBASE_WALLET', - METAMASK = 'METAMASK', - GNOSIS_SAFE = 'GNOSIS_SAFE', - TREZOR = 'TREZOR', -} +import type { SafeInfoResponse } from '@safe-global/api-kit' export interface WalletInfo { chainId: SupportedChainId @@ -38,9 +26,3 @@ export type GnosisSafeInfo = Pick -} - -export const accountsLoaders: Record = { - [ConnectionType.TREZOR]: { - getAccounts() { - return trezorConnection.connector.getAccounts() - }, - loadMoreAccounts() { - return trezorConnection.connector.loadMoreAccounts() - }, - }, -} diff --git a/libs/wallet/src/api/utils/connection.ts b/libs/wallet/src/api/utils/connection.ts deleted file mode 100644 index 318a20404e..0000000000 --- a/libs/wallet/src/api/utils/connection.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { isMobile } from '@cowprotocol/common-utils' - -import { default as MetamaskImage } from '../../api/assets/metamask.png' -import CoinbaseWalletIcon from '../assets/coinbase.svg' -import TrezorIcon from '../assets/trezor.svg' -import WalletConnectIcon from '../assets/walletConnectIcon.svg' -import { ConnectionType } from '../types' - -const connectionTypeToName: Record = { - [ConnectionType.INJECTED]: 'Injected', - [ConnectionType.METAMASK]: 'MetaMask', - [ConnectionType.COINBASE_WALLET]: 'Coinbase Wallet', - [ConnectionType.WALLET_CONNECT_V2]: 'WalletConnect', - [ConnectionType.NETWORK]: 'Network', - [ConnectionType.GNOSIS_SAFE]: 'Safe', - [ConnectionType.TREZOR]: 'Trezor', -} - -const IDENTICON_KEY = 'Identicon' - -const connectionTypeToIcon: Record = { - [ConnectionType.INJECTED]: IDENTICON_KEY, - [ConnectionType.METAMASK]: MetamaskImage, - [ConnectionType.GNOSIS_SAFE]: IDENTICON_KEY, - [ConnectionType.NETWORK]: IDENTICON_KEY, - [ConnectionType.COINBASE_WALLET]: CoinbaseWalletIcon, - [ConnectionType.TREZOR]: TrezorIcon, - [ConnectionType.WALLET_CONNECT_V2]: WalletConnectIcon, -} - -export function getConnectionIcon(connectionType: ConnectionType): string { - return connectionTypeToIcon[connectionType] -} - -export function getConnectionName(connectionType: ConnectionType): string { - return connectionTypeToName[connectionType] -} - -export function getIsInjected(): boolean { - return Boolean(window.ethereum) -} - -export function getIsInjectedMobileBrowser(): boolean { - return getIsInjected() && isMobile -} diff --git a/libs/wallet/src/api/utils/getHwAccount.ts b/libs/wallet/src/api/utils/getHwAccount.ts deleted file mode 100644 index 37780bfa50..0000000000 --- a/libs/wallet/src/api/utils/getHwAccount.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { jotaiStore } from '@cowprotocol/core' - -import { hwAccountIndexAtom } from '../state' - -export const TREZOR_DERIVATION_PATH = `m/44'/60'/0'/0` - -export function getHwAccount(): { index: number; path: string } { - const index = jotaiStore.get(hwAccountIndexAtom) - const path = `${TREZOR_DERIVATION_PATH}/${index}` - - return { index, path } -} diff --git a/libs/wallet/src/api/utils/getWalletType.ts b/libs/wallet/src/api/utils/getWalletType.ts deleted file mode 100644 index e0fb2f766e..0000000000 --- a/libs/wallet/src/api/utils/getWalletType.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { GnosisSafeInfo, WalletType } from '../types' - -interface GetWalletTypeParams { - gnosisSafeInfo?: GnosisSafeInfo - isSmartContractWallet: boolean | undefined -} - -export function getWalletType({ gnosisSafeInfo, isSmartContractWallet }: GetWalletTypeParams): WalletType { - if (gnosisSafeInfo) { - return WalletType.SAFE - } else if (isSmartContractWallet === true) { - return WalletType.SC - } else { - return WalletType.EOA - } -} diff --git a/libs/wallet/src/api/utils/getWalletTypeLabel.ts b/libs/wallet/src/api/utils/getWalletTypeLabel.ts deleted file mode 100644 index 873e533bc2..0000000000 --- a/libs/wallet/src/api/utils/getWalletTypeLabel.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { WalletType } from '../types' - -const WALLET_TYPE_LABELS: Record = { - [WalletType.SAFE]: 'Safe', - [WalletType.SC]: 'smart contract wallet', - [WalletType.EOA]: 'wallet', -} - -export function getWalletTypeLabel(walletType: WalletType): string { - return WALLET_TYPE_LABELS[walletType] -} diff --git a/libs/wallet/src/constants.ts b/libs/wallet/src/constants.ts index 211f1ca25c..7918e7f4e2 100644 --- a/libs/wallet/src/constants.ts +++ b/libs/wallet/src/constants.ts @@ -1,12 +1,3 @@ -export const WC_DISABLED_TEXT = - 'Wallet-connect based wallet is already in use. Please disconnect it to connect to this wallet.' - -export const WC_PROJECT_ID = process.env.REACT_APP_WC_PROJECT_ID || 'a6cc11517a10f6f12953fd67b1eb67e7' - -export const COINBASE_WALLET_RDNS = 'com.coinbase.wallet' - -export const TRUST_WALLET_RDNS = 'com.trustwallet.app' - export const METAMASK_RDNS = 'io.metamask' export const RABBY_RDNS = 'io.rabby' diff --git a/libs/wallet/src/index.ts b/libs/wallet/src/index.ts index a781aa93ad..ecf8d63e02 100644 --- a/libs/wallet/src/index.ts +++ b/libs/wallet/src/index.ts @@ -1,57 +1,25 @@ import './types.d.ts' - +export { reownAppKit } from './reown/init' export * from './api/types' -export * from './web3-react/types' +export * from './api/utils' export * from './assets' -export * from './constants' // Hooks export * from './api/hooks' -export * from './web3-react/hooks/useWalletMetadata' -export * from './web3-react/hooks/useIsWalletConnect' -export * from './web3-react/hooks/useSafeAppsSdk' -export * from './web3-react/hooks/useIsSmartContractWallet' -export * from './web3-react/hooks/useActivateConnector' -export * from './web3-react/hooks/useDisconnectWallet' -export * from './web3-react/hooks/useSwitchNetwork' -export * from './web3-react/hooks/useConnectionType' - -// Updater -export * from './web3-react/updater' -export * from './web3-react/updaters/HwAccountIndexUpdater' +export { useOpenWalletConnectionModal } from './api/hooks/useOpenWalletConnectionModal' +export * from './reown/hooks/useWalletMetadata' +export * from './reown/hooks/useIsWalletConnect' +export * from './reown/hooks/useSafeAppsSdk' +export * from './reown/hooks/useIsSmartContractWallet' +export * from './reown/hooks/useDisconnectWallet' +export * from './reown/hooks/useSwitchNetwork' + +// Updaters and Providers +export * from './reown/updaters/WalletUpdater' +export { WalletProvider } from './api/container/WalletProvider' // Components export * from './api/container/Identicon' -export * from './web3-react/pure/AccountIndexSelect' - -// Utils -export * from './api/utils/connection' -export * from './web3-react/utils/getIsHardWareWallet' -export { accountsLoaders } from './api/utils/accountsLoaders' -export { isChainAllowed } from './web3-react/utils/isChainAllowed' -export { getWeb3ReactConnection } from './web3-react/utils/getWeb3ReactConnection' -export { switchChain } from './web3-react/utils/switchChain' - -// Connectors -export { Web3Provider } from './web3-react/Web3Provider' -export { injectedWalletConnection } from './web3-react/connection/injectedWallet' -export { networkConnection } from './web3-react/connection/network' -export { gnosisSafeConnection } from './web3-react/connection/safe' -export { walletConnectConnectionV2 } from './web3-react/connection/walletConnectV2' - -// Connect options -export { - InjectedOption, - Eip6963Option, -} from './web3-react/connection/injectedOptions' - -export { ConnectWalletOption } from './api/pure/ConnectWalletOption' -export { TrezorOption } from './web3-react/connection/trezor' -export { WalletConnectV2Option } from './web3-react/connection/walletConnectV2' -export { CoinbaseWalletOption } from './web3-react/connection/coinbase' -export { MetaMaskSdkOption } from './web3-react/connection/metaMaskSdk' // State -// TODO: this export is discussable, however it's already used outside -export * from './api/state' export * from './api/state' diff --git a/libs/wallet/src/reown/consts.ts b/libs/wallet/src/reown/consts.ts new file mode 100644 index 0000000000..35f252264a --- /dev/null +++ b/libs/wallet/src/reown/consts.ts @@ -0,0 +1,5 @@ +import { mainnet, arbitrum, gnosis, sepolia, base } from '@reown/appkit/networks' + +import type { AppKitOptions } from '@reown/appkit/react' + +export const SUPPORTED_REOWN_NETWORKS: AppKitOptions['networks'] = [mainnet, arbitrum, gnosis, sepolia, base] diff --git a/libs/wallet/src/reown/hooks/useDisconnectWallet.ts b/libs/wallet/src/reown/hooks/useDisconnectWallet.ts new file mode 100644 index 0000000000..57094f3a9c --- /dev/null +++ b/libs/wallet/src/reown/hooks/useDisconnectWallet.ts @@ -0,0 +1,10 @@ +import { Command } from '@cowprotocol/types' +import { useDisconnect } from '@reown/appkit/react' + +const { disconnect } = useDisconnect() + +export function useDisconnectWallet(onDisconnect?: Command) { + return () => { + disconnect().then(onDisconnect) + } +} diff --git a/libs/wallet/src/web3-react/hooks/useIsSmartContractWallet.ts b/libs/wallet/src/reown/hooks/useIsSmartContractWallet.ts similarity index 87% rename from libs/wallet/src/web3-react/hooks/useIsSmartContractWallet.ts rename to libs/wallet/src/reown/hooks/useIsSmartContractWallet.ts index a9e1b016b8..cc7d47b2e5 100644 --- a/libs/wallet/src/web3-react/hooks/useIsSmartContractWallet.ts +++ b/libs/wallet/src/reown/hooks/useIsSmartContractWallet.ts @@ -1,5 +1,5 @@ import { SWR_NO_REFRESH_OPTIONS } from '@cowprotocol/common-const' -import { useWeb3React } from '@web3-react/core' +import { useWalletProvider } from '@cowprotocol/wallet-provider' import useSWR from 'swr' @@ -15,7 +15,7 @@ export function useIsSmartContractWallet(): boolean | undefined { } function useHasContractAtAddress(): boolean | undefined { - const { provider } = useWeb3React() + const provider = useWalletProvider() const { account } = useWalletInfo() const { data } = useSWR( @@ -29,7 +29,7 @@ function useHasContractAtAddress(): boolean | undefined { return false } }, - SWR_NO_REFRESH_OPTIONS + SWR_NO_REFRESH_OPTIONS, ) return data diff --git a/libs/wallet/src/reown/hooks/useIsWalletConnect.ts b/libs/wallet/src/reown/hooks/useIsWalletConnect.ts new file mode 100644 index 0000000000..2ce0906ed1 --- /dev/null +++ b/libs/wallet/src/reown/hooks/useIsWalletConnect.ts @@ -0,0 +1,7 @@ +import { useAppKitProvider } from '@reown/appkit/react' + +export function useIsWalletConnect(): boolean { + const { walletProviderType } = useAppKitProvider('eip155') + + return walletProviderType === 'WALLET_CONNECT' +} diff --git a/libs/wallet/src/reown/hooks/useSafeAppsSdk.ts b/libs/wallet/src/reown/hooks/useSafeAppsSdk.ts new file mode 100644 index 0000000000..8cb12ffe67 --- /dev/null +++ b/libs/wallet/src/reown/hooks/useSafeAppsSdk.ts @@ -0,0 +1,7 @@ +import SafeAppsSDK from '@safe-global/safe-apps-sdk' + +const safeAppsSDK = new SafeAppsSDK() + +export function useSafeAppsSdk(): SafeAppsSDK | null { + return safeAppsSDK +} diff --git a/libs/wallet/src/reown/hooks/useSwitchNetwork.ts b/libs/wallet/src/reown/hooks/useSwitchNetwork.ts new file mode 100644 index 0000000000..46ba098f01 --- /dev/null +++ b/libs/wallet/src/reown/hooks/useSwitchNetwork.ts @@ -0,0 +1,19 @@ +import { SupportedChainId } from '@cowprotocol/cow-sdk' + +import { useAppKitNetwork } from '@reown/appkit/react' + +import { SUPPORTED_REOWN_NETWORKS } from '../consts' + +export function useSwitchNetwork() { + const { switchNetwork } = useAppKitNetwork() + + return (chainId: SupportedChainId) => { + const network = SUPPORTED_REOWN_NETWORKS.find((network) => +network.id === +chainId) + + if (!network) { + throw new Error(`Network nod found while switching: ${chainId}`) + } + + switchNetwork(network) + } +} diff --git a/libs/wallet/src/reown/hooks/useWalletMetadata.ts b/libs/wallet/src/reown/hooks/useWalletMetadata.ts new file mode 100644 index 0000000000..12cc45f536 --- /dev/null +++ b/libs/wallet/src/reown/hooks/useWalletMetadata.ts @@ -0,0 +1,56 @@ +import { useWalletInfo } from '@reown/appkit/react' + +import { useSafeAppsSdk } from './useSafeAppsSdk' + +import { useGnosisSafeInfo } from '../../api/hooks' + +export interface WalletMetaData { + walletName?: string + icon?: string +} + +export function useWalletMetaData(): WalletMetaData { + const { walletInfo } = useWalletInfo() + + return { + walletName: walletInfo?.name, + icon: walletInfo?.icon, + } +} + +/** + * Detects whether the currently connected wallet is a Safe App + * It'll be false if connected to Safe wallet via WalletConnect + */ +export function useIsSafeApp(): boolean { + const isSafeWallet = useIsSafeWallet() + const sdk = useSafeAppsSdk() + + // If the wallet is not a Safe, or we don't have access to the SafeAppsSDK, we know is not a Safe App + if (!isSafeWallet || !sdk) { + return false + } + + // Will only be a SafeApp if within an iframe + // Which means, window.parent is different than window + return window?.parent !== window +} + +/** + * Detects whether the currently connected wallet is a Safe wallet + * regardless of the connection method (WalletConnect or inside Safe as an App) + */ +export function useIsSafeWallet(): boolean { + return !!useGnosisSafeInfo() +} + +/** + * Detects whether the currently connected wallet is a Safe wallet + * but NOT loaded as a Safe App + */ +export function useIsSafeViaWc(): boolean { + const isSafeApp = useIsSafeApp() + const isSafeWallet = useIsSafeWallet() + + return isSafeWallet && !isSafeApp +} diff --git a/libs/wallet/src/reown/init.ts b/libs/wallet/src/reown/init.ts new file mode 100644 index 0000000000..cde66b603c --- /dev/null +++ b/libs/wallet/src/reown/init.ts @@ -0,0 +1,34 @@ +import { createAppKit } from '@reown/appkit/react' +import { Ethers5Adapter } from '@reown/appkit-adapter-ethers5' + +import { SUPPORTED_REOWN_NETWORKS } from './consts' + +// TODO: change +const projectId = 'be9f19dedc14dc05c554d97f92aed71d' + +const metadata = { + name: 'CoW Swap', + description: + 'CoW Swap finds the lowest prices from all decentralized exchanges and DEX aggregators & saves you more with p2p trading and protection from MEV', + url: 'https://swap.cow.fi', + icons: ['https://swap.cow.fi/favicon-light-mode.png'], +} + +export const reownAppKit = createAppKit({ + adapters: [new Ethers5Adapter()], + metadata: metadata, + networks: SUPPORTED_REOWN_NETWORKS, + defaultNetwork: SUPPORTED_REOWN_NETWORKS[0], + projectId, + features: { + analytics: false, + email: false, + socials: false, + }, + enableEIP6963: true, + enableWalletGuide: false, + allowUnsupportedChain: false, + featuredWalletIds: ['fd20dc426fb37566d803205b19bbc1d4096b248ac04548e3cfb6b3a38bd033aa'], + termsConditionsUrl: + 'https://cow.fi/legal/cowswap-terms?utm_source=swap.cow.fi&utm_medium=web&utm_content=wallet-modal-terms-link', +}) diff --git a/libs/wallet/src/web3-react/updater.ts b/libs/wallet/src/reown/updaters/WalletUpdater/index.ts similarity index 80% rename from libs/wallet/src/web3-react/updater.ts rename to libs/wallet/src/reown/updaters/WalletUpdater/index.ts index 9c9a3270f9..78d4a27c1d 100644 --- a/libs/wallet/src/web3-react/updater.ts +++ b/libs/wallet/src/reown/updaters/WalletUpdater/index.ts @@ -5,18 +5,16 @@ import { getCurrentChainIdFromUrl } from '@cowprotocol/common-utils' import { getSafeInfo } from '@cowprotocol/core' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { useENSName } from '@cowprotocol/ens' -import { useWeb3React } from '@web3-react/core' +import { useWalletProvider } from '@cowprotocol/wallet-provider' +import { useAppKitNetwork, useAppKitAccount } from '@reown/appkit/react' import ms from 'ms.macro' -import { useIsSmartContractWallet } from './hooks/useIsSmartContractWallet' -import { useSafeAppsSdk } from './hooks/useSafeAppsSdk' -import { useIsSafeApp, useWalletMetaData } from './hooks/useWalletMetadata' - -import { gnosisSafeInfoAtom, walletDetailsAtom, walletInfoAtom } from '../api/state' -import { GnosisSafeInfo, WalletDetails, WalletInfo } from '../api/types' -import { getWalletType } from '../api/utils/getWalletType' -import { getWalletTypeLabel } from '../api/utils/getWalletTypeLabel' +import { gnosisSafeInfoAtom, walletDetailsAtom, walletInfoAtom } from '../../../api/state' +import { GnosisSafeInfo, WalletDetails, WalletInfo } from '../../../api/types' +import { useIsSmartContractWallet } from '../../hooks/useIsSmartContractWallet' +import { useSafeAppsSdk } from '../../hooks/useSafeAppsSdk' +import { useIsSafeApp, useWalletMetaData } from '../../hooks/useWalletMetadata' // used for on-chain calls const SAFE_INFO_LONG_INTERVAL = ms`30s` @@ -33,7 +31,10 @@ function _checkIsSupportedWallet(walletName?: string): boolean { } function _useWalletInfo(): WalletInfo { - const { account, chainId, isActive: active } = useWeb3React() + const { address: account, isConnected: active } = useAppKitAccount() + const { chainId: reownChainId } = useAppKitNetwork() + + const chainId = reownChainId ? +reownChainId : undefined const isChainIdUnsupported = !!chainId && !(chainId in SupportedChainId) return useMemo( @@ -46,10 +47,10 @@ function _useWalletInfo(): WalletInfo { ) } -function _useWalletDetails(account?: string, standaloneMode?: boolean): WalletDetails { +function _useWalletDetails(account?: string): WalletDetails { const { ENSName: ensName } = useENSName(account ?? undefined) const isSmartContractWallet = useIsSmartContractWallet() - const { walletName, icon } = useWalletMetaData(standaloneMode) + const { walletName, icon } = useWalletMetaData() const isSafeApp = useIsSafeApp() return useMemo(() => { @@ -69,7 +70,7 @@ function _useWalletDetails(account?: string, standaloneMode?: boolean): WalletDe } function _useSafeInfo(walletInfo: WalletInfo): GnosisSafeInfo | undefined { - const { provider } = useWeb3React() + const provider = useWalletProvider() const { account, chainId } = walletInfo const [safeInfo, setSafeInfo] = useState() const safeAppsSdk = useSafeAppsSdk() @@ -146,13 +147,9 @@ function _useSafeInfo(walletInfo: WalletInfo): GnosisSafeInfo | undefined { return safeInfo } -interface WalletUpdaterProps { - standaloneMode?: boolean -} - -export function WalletUpdater({ standaloneMode }: WalletUpdaterProps) { +export function WalletUpdater() { const walletInfo = _useWalletInfo() - const walletDetails = _useWalletDetails(walletInfo.account, standaloneMode) + const walletDetails = _useWalletDetails(walletInfo.account) const gnosisSafeInfo = _useSafeInfo(walletInfo) const setWalletInfo = useSetAtom(walletInfoAtom) @@ -166,12 +163,8 @@ export function WalletUpdater({ standaloneMode }: WalletUpdaterProps) { // Update wallet details useEffect(() => { - const walletType = getWalletType({ gnosisSafeInfo, isSmartContractWallet: walletDetails.isSmartContractWallet }) - setWalletDetails({ - walletName: getWalletTypeLabel(walletType), // Fallback wallet name, will be overridden by below line if something exists. - ...walletDetails, - }) - }, [walletDetails, setWalletDetails, gnosisSafeInfo]) + setWalletDetails(walletDetails) + }, [walletDetails, setWalletDetails]) // Update Gnosis Safe info useEffect(() => { diff --git a/libs/wallet/src/web3-react/Web3Provider/hooks/useEagerlyConnect.ts b/libs/wallet/src/web3-react/Web3Provider/hooks/useEagerlyConnect.ts deleted file mode 100644 index 22ac501bef..0000000000 --- a/libs/wallet/src/web3-react/Web3Provider/hooks/useEagerlyConnect.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { useEffect, useRef, useState } from 'react' - -import { getCurrentChainIdFromUrl, isInjectedWidget } from '@cowprotocol/common-utils' -import { jotaiStore } from '@cowprotocol/core' -import { Connector } from '@web3-react/types' - -import { useSelectedEip6963ProviderInfo, useSetEip6963Provider } from '../../../api/hooks' -import { selectedEip6963ProviderRdnsAtom } from '../../../api/state/multiInjectedProvidersAtom' -import { ConnectionType } from '../../../api/types' -import { getIsInjectedMobileBrowser } from '../../../api/utils/connection' -import { injectedWalletConnection } from '../../connection/injectedWallet' -import { networkConnection } from '../../connection/network' -import { gnosisSafeConnection } from '../../connection/safe' -import { getWeb3ReactConnection } from '../../utils/getWeb3ReactConnection' - -async function connect(connector: Connector) { - const chainId = getCurrentChainIdFromUrl() - - try { - if (connector.connectEagerly) { - await connector.connectEagerly(chainId) - } else { - await connector.activate(chainId) - } - } catch (error: any) { - console.debug(`web3-react eager connection error: ${error}`) - } -} - -export function useEagerlyConnect(selectedWallet: ConnectionType | undefined, standaloneMode?: boolean) { - const [tryConnectEip6963Provider, setTryConnectEip6963Provider] = useState(false) - const eagerlyConnectInitRef = useRef(false) - const selectedEip6963ProviderInfo = useSelectedEip6963ProviderInfo() - const setEip6963Provider = useSetEip6963Provider() - - useEffect(() => { - // Initialize EagerlyConnect once - if (eagerlyConnectInitRef.current) return - - const isIframe = window.top !== window.self - - // autoConnect is set to true in the e2e tests - if (isInjectedWidget() || getIsInjectedMobileBrowser() || window.ethereum?.autoConnect) { - connect(injectedWalletConnection.connector) - } - - // Try to connect to Gnosis Safe only when the app is opened in an iframe - if (isIframe) { - connect(gnosisSafeConnection.connector) - } - - connect(networkConnection.connector) - - if (selectedWallet) { - const connection = getWeb3ReactConnection(selectedWallet) - const cachedProviderRdns = jotaiStore.get(selectedEip6963ProviderRdnsAtom) - - /** - * Skip activation if an injected eip6963 provider was previously selected - * Because it will be activated in the next useEffect() block - */ - if (connection.type === ConnectionType.INJECTED && cachedProviderRdns) { - setTryConnectEip6963Provider(true) - return - } - - connect(connection.connector) - } - - eagerlyConnectInitRef.current = true - // The dependency list is empty so this is only run once on mount - }, [selectedWallet]) - - /** - * Activate the selected eip6963 provider - */ - useEffect(() => { - // Ignore remembered eip6963 provider if the app is in widget dapp mode - if (isInjectedWidget() && !standaloneMode) return - if (!selectedWallet || !tryConnectEip6963Provider) return - - const connection = getWeb3ReactConnection(selectedWallet) - - if (connection.type === ConnectionType.INJECTED && selectedEip6963ProviderInfo) { - const { provider, info } = selectedEip6963ProviderInfo - const { connector } = injectedWalletConnection - - connector.provider = provider - connector.onConnect = () => setEip6963Provider(info.rdns) - connector.onDisconnect = () => setEip6963Provider(null) - - setTryConnectEip6963Provider(false) - connect(connector) - } - }, [standaloneMode, selectedEip6963ProviderInfo, selectedWallet, setEip6963Provider, tryConnectEip6963Provider]) -} diff --git a/libs/wallet/src/web3-react/Web3Provider/hooks/useOrderedConnections.ts b/libs/wallet/src/web3-react/Web3Provider/hooks/useOrderedConnections.ts deleted file mode 100644 index 303a9c40ef..0000000000 --- a/libs/wallet/src/web3-react/Web3Provider/hooks/useOrderedConnections.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { useMemo } from 'react' - -import { isInjectedWidget } from '@cowprotocol/common-utils' - -import { ConnectionType } from '../../../api/types' -import { getIsInjected } from '../../../api/utils/connection' -import { getWeb3ReactConnection } from '../../utils/getWeb3ReactConnection' - -const isIframe = window.top !== window.self - -/** - * `web3-react` library gives us concept of "connectors" which are react-wrappers on top of eip1193 providers. - * `Web3ReactProvider` has a context which stores state of all active connectors. - * It is very important! There might be more than one active connector! - * Because of that, we need to prioritize them on this hook. - * `web3-react` will take the first active connector from the list and use it. - */ -export function useOrderedConnections(selectedWallet: ConnectionType | undefined) { - return useMemo(() => { - const orderedConnectionTypes: ConnectionType[] = [] - - if (isInjectedWidget()) { - orderedConnectionTypes.push(ConnectionType.INJECTED) - } - - // Always attempt to use to Gnosis Safe first in iframe, as we can't know if we're in a SafeContext. - if (isIframe) { - orderedConnectionTypes.push(ConnectionType.GNOSIS_SAFE) - } - - // Add the `selectedWallet` to the top so it's prioritized, then add the other selectable wallets. - if (selectedWallet && !orderedConnectionTypes.includes(selectedWallet)) { - orderedConnectionTypes.push(selectedWallet) - } - - if (getIsInjected() && !orderedConnectionTypes.includes(ConnectionType.INJECTED)) { - orderedConnectionTypes.push(ConnectionType.INJECTED) - } - - // Add network connection last as it should be the fallback. - orderedConnectionTypes.push(ConnectionType.NETWORK) - - return orderedConnectionTypes.map(getWeb3ReactConnection) - }, [selectedWallet]) -} diff --git a/libs/wallet/src/web3-react/Web3Provider/index.tsx b/libs/wallet/src/web3-react/Web3Provider/index.tsx deleted file mode 100644 index 97cc1dc8df..0000000000 --- a/libs/wallet/src/web3-react/Web3Provider/index.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { ReactNode, useMemo } from 'react' - -import { Web3ReactHooks, Web3ReactProvider } from '@web3-react/core' -import { Connector } from '@web3-react/types' - -import { useEagerlyConnect } from './hooks/useEagerlyConnect' -import { useOrderedConnections } from './hooks/useOrderedConnections' - -import { ConnectionType } from '../../api/types' -import { getConnectionName } from '../../api/utils/connection' -import { Web3ReactConnection } from '../types' - -interface Web3ProviderProps { - children: ReactNode - selectedWallet: ConnectionType | undefined - standaloneMode?: boolean -} - -export function Web3Provider({ children, selectedWallet, standaloneMode }: Web3ProviderProps) { - useEagerlyConnect(selectedWallet, standaloneMode) - - const connections = useOrderedConnections(selectedWallet) - const connectors: [Connector, Web3ReactHooks][] = connections - .filter(Boolean) - .map(({ hooks, connector }) => [connector, hooks]) - - const key = useMemo( - () => connections.map(({ type }: Web3ReactConnection) => getConnectionName(type)).join('-'), - [connections], - ) - - return ( - - {children} - - ) -} diff --git a/libs/wallet/src/web3-react/connection/asyncConnector.ts b/libs/wallet/src/web3-react/connection/asyncConnector.ts deleted file mode 100644 index d8e2a3059a..0000000000 --- a/libs/wallet/src/web3-react/connection/asyncConnector.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { Web3Provider } from '@ethersproject/providers' -import { Actions, Connector } from '@web3-react/types' - -import EventEmitter from 'events' - -export const ASYNC_CUSTOM_PROVIDER_EVENT = 'customProvider' - -function initCustomProvider(self: AsyncConnector, connector: Connector, chainId: number) { - if (connector.provider && !connector.customProvider) { - self.customProvider = new Web3Provider(connector.provider, chainId) - } - - self.events.emit(ASYNC_CUSTOM_PROVIDER_EVENT, self.customProvider) - - // Update provider when network is changed on wallet side - connector.provider?.on('chainChanged', (chainIdHex: string) => { - initCustomProvider(self, connector, +chainIdHex) - }) -} - -/** - * To avoid including external libs for wallet connection in the bundle - * We load them in runtime by demand - */ -export class AsyncConnector extends Connector { - readonly events = new EventEmitter() - - constructor(private loader: () => Promise, actions: Actions, onError?: (error: Error) => void) { - super(actions, onError) - } - - activate(chainId: number): Promise | void { - return this.loader().then((connector) => { - // There is a magic - we change async-connector prototype to the loaded connector - ;(this as any).__proto__ = connector - - return (connector.activate(chainId) || Promise.resolve()).then(() => { - initCustomProvider(this, connector, chainId) - }) - }) - } - - async connectEagerly(chainId: number) { - return this.loader().then((connector) => { - // There is a magic - we change async-connector prototype to the loaded connector - ;(this as any).__proto__ = connector - - const activation = connector.connectEagerly?.(chainId) || Promise.resolve() - - return activation.then(() => { - initCustomProvider(this, connector, chainId) - }) - }) - } -} diff --git a/libs/wallet/src/web3-react/connection/coinbase.tsx b/libs/wallet/src/web3-react/connection/coinbase.tsx deleted file mode 100644 index 34dc5557fb..0000000000 --- a/libs/wallet/src/web3-react/connection/coinbase.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import CowImage from '@cowprotocol/assets/cow-swap/cow_token.svg' -import { RPC_URLS } from '@cowprotocol/common-const' -import { SupportedChainId } from '@cowprotocol/cow-sdk' -import { initializeConnector } from '@web3-react/core' - -import { AsyncConnector } from './asyncConnector' -import { onError } from './onError' - -import { default as CoinbaseImage } from '../../api/assets/coinbase.svg' -import { ConnectWalletOption } from '../../api/pure/ConnectWalletOption' -import { ConnectionType } from '../../api/types' -import { getConnectionName } from '../../api/utils/connection' -import { useIsActiveConnection } from '../hooks/useIsActiveConnection' -import { ConnectionOptionProps, Web3ReactConnection } from '../types' - -const coinbaseInjectedOption = { - color: '#315CF5', - icon: CoinbaseImage, - id: 'coinbase-wallet', -} - -const [web3CoinbaseWallet, web3CoinbaseWalletHooks] = initializeConnector( - (actions) => - new AsyncConnector( - () => - import('@web3-react/coinbase-wallet').then( - (m) => - new m.CoinbaseWallet({ - actions, - options: { - url: RPC_URLS[SupportedChainId.MAINNET], - appName: 'CoW Swap', - appLogoUrl: CowImage, - reloadOnDisconnect: false, - }, - onError, - }) - ), - actions, - onError - ) -) - -export const coinbaseWalletConnection: Web3ReactConnection = { - connector: web3CoinbaseWallet, - hooks: web3CoinbaseWalletHooks, - type: ConnectionType.COINBASE_WALLET, -} - -export function CoinbaseWalletOption({ tryActivation, selectedWallet }: ConnectionOptionProps) { - const isActive = useIsActiveConnection(selectedWallet, coinbaseWalletConnection) - - return ( - tryActivation(coinbaseWalletConnection.connector)} - header={getConnectionName(ConnectionType.COINBASE_WALLET)} - /> - ) -} diff --git a/libs/wallet/src/web3-react/connection/injectedOptions.tsx b/libs/wallet/src/web3-react/connection/injectedOptions.tsx deleted file mode 100644 index e4d8c16451..0000000000 --- a/libs/wallet/src/web3-react/connection/injectedOptions.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import { useCallback } from 'react' - -import { injectedWalletConnection } from './injectedWallet' - -import { default as InjectedImage, default as InjectedImageDark } from '../../api/assets/arrow-right.svg' -import { useSelectedEip6963ProviderRdns, useSetEip6963Provider } from '../../api/hooks' -import { ConnectWalletOption } from '../../api/pure/ConnectWalletOption' -import { ConnectionType, type EIP1193Provider, EIP6963ProviderDetail } from '../../api/types' -import { getConnectionName } from '../../api/utils/connection' -import { useIsActiveConnection } from '../hooks/useIsActiveConnection' -import { ConnectionOptionProps, TryActivation } from '../types' - -const injectedCommon = { - color: '#010101', - id: 'injected', -} -export const injectedOption = { - ...injectedCommon, - icon: InjectedImage, -} - -export const injectedOptionDark = { - ...injectedCommon, - icon: InjectedImageDark, -} - -export function InjectedOption({ darkMode, tryActivation, selectedWallet }: ConnectionOptionProps) { - const options = darkMode ? injectedOptionDark : injectedOption - - const isActive = useIsActiveConnection(selectedWallet, injectedWalletConnection) - - return ( - tryActivation(injectedWalletConnection.connector)} - /> - ) -} - -interface Eip6963OptionProps { - selectedWallet: string | undefined - tryActivation: TryActivation - providerDetails: EIP6963ProviderDetail - providers: EIP6963ProviderDetail[] -} - -export function Eip6963Option({ - tryActivation, - selectedWallet, - providerDetails: { provider, info }, - providers, -}: Eip6963OptionProps) { - const setEip6963Provider = useSetEip6963Provider() - const selectedRdns = useSelectedEip6963ProviderRdns() - const isActive = - useIsActiveConnection(selectedWallet, injectedWalletConnection) && !!selectedWallet && selectedRdns === info.rdns - - const onClick = useCallback(() => { - // Save the previous provider in case the user disconnects to switch back to it - if (injectedWalletConnection.connector.provider) { - injectedWalletConnection.connector.prevProvider = injectedWalletConnection.connector.provider - } - - injectedWalletConnection.connector.provider = provider - injectedWalletConnection.connector.onConnect = (_provider: EIP1193Provider) => { - const connected = providers.find((p) => p.provider === _provider) - - if (connected) { - setEip6963Provider(connected.info.rdns) - } - } - injectedWalletConnection.connector.onDisconnect = () => setEip6963Provider(null) - - tryActivation(injectedWalletConnection.connector) - }, [provider, tryActivation, setEip6963Provider, providers]) - - return ( - - ) -} diff --git a/libs/wallet/src/web3-react/connection/injectedWallet.tsx b/libs/wallet/src/web3-react/connection/injectedWallet.tsx deleted file mode 100644 index 7f314cda04..0000000000 --- a/libs/wallet/src/web3-react/connection/injectedWallet.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { initializeConnector } from '@web3-react/core' - -import { ConnectionType } from '../../api/types' -import { InjectedWallet } from '../connectors/Injected' -import { Web3ReactConnection } from '../types' - -const [web3Injected, web3InjectedHooks] = initializeConnector( - (actions) => - new InjectedWallet({ - actions, - walletUrl: '', - searchKeywords: [], - }) -) -export const injectedWalletConnection: Web3ReactConnection = { - connector: web3Injected, - hooks: web3InjectedHooks, - type: ConnectionType.INJECTED, -} diff --git a/libs/wallet/src/web3-react/connection/metaMaskSdk.tsx b/libs/wallet/src/web3-react/connection/metaMaskSdk.tsx deleted file mode 100644 index 01f63209c2..0000000000 --- a/libs/wallet/src/web3-react/connection/metaMaskSdk.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { RPC_URLS } from '@cowprotocol/common-const' -import { initializeConnector } from '@web3-react/core' - -import { onError } from './onError' - -import { default as MetamaskImage } from '../../api/assets/metamask.png' -import { ConnectWalletOption } from '../../api/pure/ConnectWalletOption' -import { ConnectionType } from '../../api/types' -import { getConnectionName } from '../../api/utils/connection' -import { MetaMaskSDK } from '../connectors/metaMaskSdk' -import { useIsActiveConnection } from '../hooks/useIsActiveConnection' -import { ConnectionOptionProps, Web3ReactConnection } from '../types' - -const metaMaskOption = { - color: '#E8831D', - icon: MetamaskImage, - id: 'metamask', -} - -const [web3MetaMask, web3MetaMaskHooks] = initializeConnector( - (actions) => - new MetaMaskSDK({ - actions, - options: { - dappMetadata: { - name: 'CoW Swap', - url: 'https://swap.cow.fi', - }, - readonlyRPCMap: Object.fromEntries( - Object.entries(RPC_URLS).map(([chainId, url]) => [`0x${Number(chainId).toString(16)}`, url]), - ), - }, - onError, - }), -) - -export const metaMaskSdkConnection: Web3ReactConnection = { - connector: web3MetaMask, - hooks: web3MetaMaskHooks, - type: ConnectionType.METAMASK, -} - -export function MetaMaskSdkOption({ tryActivation, selectedWallet }: ConnectionOptionProps) { - const isActive = useIsActiveConnection(selectedWallet, metaMaskSdkConnection) - - return ( - tryActivation(metaMaskSdkConnection.connector)} - header={getConnectionName(ConnectionType.METAMASK)} - /> - ) -} diff --git a/libs/wallet/src/web3-react/connection/network.tsx b/libs/wallet/src/web3-react/connection/network.tsx deleted file mode 100644 index 3901edc3bb..0000000000 --- a/libs/wallet/src/web3-react/connection/network.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { RPC_URLS } from '@cowprotocol/common-const' -import { getCurrentChainIdFromUrl } from '@cowprotocol/common-utils' -import { initializeConnector } from '@web3-react/core' -import { Network } from '@web3-react/network' - -import { ConnectionType } from '../../api/types' -import { Web3ReactConnection } from '../types' - -const defaultChainId = getCurrentChainIdFromUrl() - -const [web3Network, web3NetworkHooks] = initializeConnector( - (actions) => new Network({ actions, urlMap: RPC_URLS, defaultChainId }) -) -export const networkConnection: Web3ReactConnection = { - connector: web3Network, - hooks: web3NetworkHooks, - type: ConnectionType.NETWORK, -} diff --git a/libs/wallet/src/web3-react/connection/onError.ts b/libs/wallet/src/web3-react/connection/onError.ts deleted file mode 100644 index b3a7b08d18..0000000000 --- a/libs/wallet/src/web3-react/connection/onError.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function onError(error: Error) { - console.debug(`[web3-react] Error: ${error}`) -} diff --git a/libs/wallet/src/web3-react/connection/safe.tsx b/libs/wallet/src/web3-react/connection/safe.tsx deleted file mode 100644 index c200bb82d6..0000000000 --- a/libs/wallet/src/web3-react/connection/safe.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { initializeConnector } from '@web3-react/core' - -import { AsyncConnector } from './asyncConnector' - -import { ConnectionType } from '../../api/types' -import { Web3ReactConnection } from '../types' - -const [web3GnosisSafe, web3GnosisSafeHooks] = initializeConnector( - (actions) => - new AsyncConnector(() => import('@web3-react/gnosis-safe').then((m) => new m.GnosisSafe({ actions })), actions), -) -export const gnosisSafeConnection: Web3ReactConnection = { - connector: web3GnosisSafe, - hooks: web3GnosisSafeHooks, - type: ConnectionType.GNOSIS_SAFE, -} diff --git a/libs/wallet/src/web3-react/connection/trezor.tsx b/libs/wallet/src/web3-react/connection/trezor.tsx deleted file mode 100644 index 8f65aa4ec8..0000000000 --- a/libs/wallet/src/web3-react/connection/trezor.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { initializeConnector } from '@web3-react/core' - -import { default as TrezorImage } from '../../api/assets/trezor.svg' -import { ConnectWalletOption } from '../../api/pure/ConnectWalletOption' -import { ConnectionType } from '../../api/types' -import { getConnectionName } from '../../api/utils/connection' -import { TrezorConnector } from '../connectors/TrezorConnector' -import { useIsActiveConnection } from '../hooks/useIsActiveConnection' -import { ConnectionOptionProps, Web3ReactConnection } from '../types' - -const BASE_PROPS = { - color: '#4196FC', - icon: TrezorImage, - id: 'trezor', -} - -const [trezor, trezorHooks] = initializeConnector((actions) => new TrezorConnector(actions)) - -export const trezorConnection: Web3ReactConnection = { - connector: trezor, - hooks: trezorHooks, - type: ConnectionType.TREZOR, -} - -export function TrezorOption({ selectedWallet, tryActivation }: ConnectionOptionProps) { - const isActive = useIsActiveConnection(selectedWallet, trezorConnection) - - return ( - tryActivation(trezorConnection.connector)} - header={getConnectionName(ConnectionType.TREZOR)} - /> - ) -} diff --git a/libs/wallet/src/web3-react/connection/walletConnectV2.tsx b/libs/wallet/src/web3-react/connection/walletConnectV2.tsx deleted file mode 100644 index 75ce969378..0000000000 --- a/libs/wallet/src/web3-react/connection/walletConnectV2.tsx +++ /dev/null @@ -1,146 +0,0 @@ -import { useState, useSyncExternalStore } from 'react' - -import { RPC_URLS } from '@cowprotocol/common-const' -import { getCurrentChainIdFromUrl } from '@cowprotocol/common-utils' -import { ALL_SUPPORTED_CHAIN_IDS, SupportedChainId } from '@cowprotocol/cow-sdk' -import { Command } from '@cowprotocol/types' -import { initializeConnector, Web3ReactHooks } from '@web3-react/core' -import { Web3ReactStore } from '@web3-react/types' - -import { ASYNC_CUSTOM_PROVIDER_EVENT, AsyncConnector } from './asyncConnector' -import { onError } from './onError' - -import { default as WalletConnectV2Image } from '../../api/assets/walletConnectIcon.svg' -import { ConnectWalletOption } from '../../api/pure/ConnectWalletOption' -import { ConnectionType } from '../../api/types' -import { getConnectionName } from '../../api/utils/connection' -import { WC_PROJECT_ID } from '../../constants' -import { useIsActiveConnection } from '../hooks/useIsActiveConnection' -import { ConnectionOptionProps, Web3ReactConnection } from '../types' - -export const walletConnectV2Option = { - color: '#4196FC', - icon: WalletConnectV2Image, - id: 'wallet-connect-v2', -} - -function createWalletConnectV2Connector(chainId: SupportedChainId): [AsyncConnector, Web3ReactHooks, Web3ReactStore] { - return initializeConnector( - (actions) => - new AsyncConnector( - () => - import('../connectors/WalletConnectV2Connector').then( - (m) => - new m.WalletConnectV2Connector({ - actions, - onError(error) { - console.error('WalletConnect2 ERROR:', error) - }, - options: { - projectId: WC_PROJECT_ID, - chains: [chainId], - optionalChains: ALL_SUPPORTED_CHAIN_IDS, - showQrModal: true, - rpcMap: RPC_URLS, - }, - }) - ), - actions, - onError - ) - ) -} - -/** - * Copy-pasted solution from https://github.com/Uniswap/interface/blob/main/src/connection/index.ts#L85 - * - * Why do we need this: - * WC2 connector can be created once per network - * - * Let's consider the case: - * - * - Connect via WC2 to Mainnet - * - Disconnect - * - Try to connect to Gnosis Chain via WC2 - * - * In this case, the connection won't be established, because at step 1 the WC2 connector was created for chainId=1. - * To overcome this problem we proxy WC2 connection and change it's implementation on flight on network changes. - */ -function createWc2Connection(chainId = getCurrentChainIdFromUrl()): Web3ReactConnection { - let [web3WalletConnectV2, web3WalletConnectV2Hooks] = createWalletConnectV2Connector(chainId) - - web3WalletConnectV2Hooks.useProvider = function useProvider() { - const [customProvider, setCustomProvider] = useState(undefined) - - web3WalletConnectV2.events.on(ASYNC_CUSTOM_PROVIDER_EVENT, setCustomProvider) - - return customProvider - } - - let onActivate: Command | undefined - - const proxyConnector = new Proxy( - {}, - { - get: (target, p, receiver) => Reflect.get(web3WalletConnectV2, p, receiver), - getOwnPropertyDescriptor: (target, p) => Reflect.getOwnPropertyDescriptor(web3WalletConnectV2, p), - getPrototypeOf: () => AsyncConnector.prototype, - set: (target, p, receiver) => Reflect.set(web3WalletConnectV2, p, receiver), - } - ) as typeof web3WalletConnectV2 - - const proxyHooks = new Proxy( - {}, - { - get: (target, p, receiver) => { - return () => { - // Because our connectors are referentially stable (through proxying), we need a way to trigger React renders - // from outside of the React lifecycle when our connector is re-initialized. This is done via 'change' events - // with `useSyncExternalStore`: - const hooks = useSyncExternalStore( - (onChange) => { - onActivate = onChange - return () => (onActivate = undefined) - }, - () => web3WalletConnectV2Hooks - ) - return Reflect.get(hooks, p, receiver)() - } - }, - } - ) as typeof web3WalletConnectV2Hooks - - return { - get connector() { - return proxyConnector - }, - get hooks() { - return proxyHooks - }, - type: ConnectionType.WALLET_CONNECT_V2, - overrideActivate(chainId: SupportedChainId) { - const update = createWalletConnectV2Connector(chainId) - web3WalletConnectV2 = update[0] - web3WalletConnectV2Hooks = update[1] - - onActivate?.() - return false - }, - } -} - -export const walletConnectConnectionV2 = createWc2Connection() - -export function WalletConnectV2Option({ selectedWallet, tryActivation }: ConnectionOptionProps) { - const isActive = useIsActiveConnection(selectedWallet, walletConnectConnectionV2) - - return ( - tryActivation(walletConnectConnectionV2.connector)} - header={getConnectionName(ConnectionType.WALLET_CONNECT_V2)} - /> - ) -} diff --git a/libs/wallet/src/web3-react/connectors/Injected/index.tsx b/libs/wallet/src/web3-react/connectors/Injected/index.tsx deleted file mode 100644 index 62e3b746dc..0000000000 --- a/libs/wallet/src/web3-react/connectors/Injected/index.tsx +++ /dev/null @@ -1,270 +0,0 @@ -import { isInjectedWidget, isRejectRequestProviderError } from '@cowprotocol/common-utils' -import { WidgetEthereumProvider } from '@cowprotocol/iframe-transport' -import { Command } from '@cowprotocol/types' -import { Actions, AddEthereumChainParameter, Connector, ProviderConnectInfo, ProviderRpcError } from '@web3-react/types' - -import type { EIP1193Provider } from '../../../api/eip6963-types' - -interface injectedWalletConstructorArgs { - actions: Actions - onError?: Command - walletUrl: string - searchKeywords: string[] -} - -export class InjectedWallet extends Connector { - provider?: EIP1193Provider = undefined - prevProvider?: EIP1193Provider = undefined - walletUrl: string - searchKeywords: string[] - eagerConnection?: boolean - - onConnect?(provider: EIP1193Provider): void - - onDisconnect?: Command - - constructor({ actions, onError, walletUrl, searchKeywords }: injectedWalletConstructorArgs) { - super(actions, onError) - - // Mod: we are passing these 2 custom props - this.walletUrl = walletUrl - this.searchKeywords = searchKeywords - } - - /** - * When desiredChainIdOrChainParameters is set it means this is a network switching request - * We have to call startActivation() for switching between wallets, but we mustn't do it on network switch - */ - async activate(desiredChainIdOrChainParameters?: number | AddEthereumChainParameter): Promise { - let cancelActivation: Command - - if (!desiredChainIdOrChainParameters || !this.provider?.isConnected?.()) { - cancelActivation = this.actions.startActivation() - } - - return this.isomorphicInitialize() - .then(async () => { - // Mod: If we can't find the specific provider we want, open the passed URL in new tab - if (!this.provider) { - window.open(this.walletUrl, '_blank') - return - } - - // Try to get accounts, if no accounts is returned (user rejected) throw error - const accounts = await this.getAccounts() - if (!accounts.length) throw new Error('No accounts returned') - - // Get chain ID from the wallet - const chainId = (await this.provider.request({ method: 'eth_chainId' })) as string - const receivedChainId = parseChainId(chainId) - const desiredChainId = - typeof desiredChainIdOrChainParameters === 'number' ? undefined : desiredChainIdOrChainParameters?.chainId - - // if there's no desired chain, or it's equal to the received, update - if (!desiredChainId || receivedChainId === desiredChainId) { - this.onConnect?.(this.provider) - - return this.actions.update({ chainId: receivedChainId, accounts }) - } - - const desiredChainIdHex = `0x${desiredChainId.toString(16)}` - - return this.provider - .request({ - method: 'wallet_switchEthereumChain', - params: [{ chainId: desiredChainIdHex }], - }) - .catch((error: ProviderRpcError) => { - if (error.code === 4902 && typeof desiredChainIdOrChainParameters !== 'number') { - if (!this.provider) throw new Error('No provider') - // if we're here, we can try to add a new network - return this.provider.request({ - method: 'wallet_addEthereumChain', - params: [{ ...desiredChainIdOrChainParameters, chainId: desiredChainIdHex }], - }) - } - - throw error - }) - .then(() => { - if (this.provider) { - this.onConnect?.(this.provider) - } - }) - }) - .catch((error: Error) => { - cancelActivation?.() - throw error - }) - } - - // Copied from https://github.com/Uniswap/web3-react/blob/de97c00c378b7909dfbd8a06558ed12e1f796caa/packages/metamask/src/index.ts#L98 - /** {@inheritdoc Connector.connectEagerly} */ - async connectEagerly(): Promise { - const cancelActivation = this.actions.startActivation() - - try { - await this.isomorphicInitialize() - - if (!this.provider || this.eagerConnection) return cancelActivation() - - // Fix to call this only once - this.eagerConnection = true - - await this.provider.enable?.() - - // Wallets may resolve eth_chainId and hang on eth_accounts pending user interaction, which may include changing - // chains; they should be requested serially, with accounts first, so that the chainId can settle. - const accounts = await this.getAccounts() - if (!accounts.length) throw new Error('No accounts returned') - const chainId = (await this.provider.request({ method: 'eth_chainId' })) as string - this.actions.update({ chainId: parseChainId(chainId), accounts }) - } catch (error) { - console.debug('Could not connect eagerly', error) - // we should be able to use `cancelActivation` here, but on mobile, metamask emits a 'connect' - // event, meaning that chainId is updated, and cancelActivation doesn't work because an intermediary - // update has occurred, so we reset state instead - this.actions.resetState() - } - } - - // Based on https://github.com/Uniswap/web3-react/blob/de97c00c378b7909dfbd8a06558ed12e1f796caa/packages/metamask/src/index.ts#L54 with some changes - private async isomorphicInitialize(): Promise { - // We have a custom method to detect Injected provider based on passed keywords array - const provider = this.detectProvider() - - if (provider) { - const doesProviderMatches = () => this.provider === provider - - provider.on('connect', (data: ProviderConnectInfo): void => { - if (!data || !doesProviderMatches()) return - - const { chainId } = data - this.actions.update({ chainId: parseChainId(chainId) }) - }) - - const onDisconnect = (error: ProviderRpcError): void => { - if (!doesProviderMatches()) return - - this.provider - ?.request({ method: 'PUBLIC_disconnectSite' }) - .catch(() => console.log('Failed to call "PUBLIC_disconnectSite", ignoring')) - - this.deactivate() - this.onError?.(error) - } - - provider.on('disconnect', onDisconnect) - provider.on('close', onDisconnect) - - provider.on('chainChanged', (chainId: string): void => { - if (!doesProviderMatches()) return - - this.actions.update({ chainId: parseChainId(chainId) }) - }) - - provider.on('accountsChanged', (accounts: string[]): void => { - if (!doesProviderMatches()) return - - if (accounts.length === 0) { - // When one of EIP6963 providers is disconnected try to switch to the previous one - if (this.prevProvider && this.provider !== this.prevProvider) { - this.provider = this.prevProvider - this.prevProvider = undefined - - this.activate() - } else { - this.actions.resetState() - } - } else { - this.actions.update({ accounts }) - } - }) - } - } - - async deactivate(): Promise { - if (this.provider) { - this.provider.removeAllListeners('connect') - this.provider.removeAllListeners('disconnect') - this.provider.removeAllListeners('close') - this.provider.removeAllListeners('chainChanged') - this.provider.removeAllListeners('accountsChanged') - } - - this.provider = undefined - this.onDisconnect?.() - this.actions.resetState() - } - - // Mod: Added custom method - // Method to target a specific provider on window.ethereum or window.ethereum.providers if it exists - private detectProvider(): EIP1193Provider | void { - if (this.provider) return this.provider - - if (isInjectedWidget()) { - this.provider = new WidgetEthereumProvider() as EIP1193Provider - } else { - this.provider = - this.detectOnEthereum(window.ethereum) || this.detectOnProvider(window.ethereum?.providers) || null - } - - return this.provider - } - - // Mod: Added custom method - // Some wallets such as Tally will inject custom providers array on window.ethereum - // This array will contain all injected providers and we can select the one we want based on keywords passed to constructor - // For example to select tally we would search for isTally or isTallyWallet property keys - private detectOnProvider(providers: any) { - if (!providers) return null - return providers.find((provider: any) => this.searchKeywords.some((keyword) => provider[keyword])) - } - - // Mod: Added custom method - // Here we check for specific provider directly on window.ethereum - private detectOnEthereum(ethereum?: any) { - if (!ethereum) return null - - if (this.searchKeywords.length === 0) return ethereum - - const provider = this.searchKeywords.some((keyword) => ethereum[keyword]) - return provider ? ethereum : null - } - - // Mod: Added custom method - // Try 2 different RPC methods to get accounts first with eth_requestAccounts and if it fails, try eth_accounts - public async getAccounts() { - const { provider } = this - - if (!provider) { - throw new Error('No provider') - } - - try { - const accounts = await provider.request({ method: 'eth_requestAccounts' }) - return accounts as string[] - } catch (error) { - if (isRejectRequestProviderError(error)) { - throw error - } - - console.debug(` - Failed to get account with eth_requestAccounts method - Trying with eth_accounts method - `) - - return provider.request({ method: 'eth_accounts' }) as Promise - } - } -} - -function parseChainId(chainId: string | number): number { - if (typeof chainId === 'number') return chainId - - if (!chainId.startsWith('0x')) { - return Number(chainId) - } - - return Number.parseInt(chainId, 16) -} diff --git a/libs/wallet/src/web3-react/connectors/TrezorConnector/TrezorProvider.ts b/libs/wallet/src/web3-react/connectors/TrezorConnector/TrezorProvider.ts deleted file mode 100644 index 36ccbc8c69..0000000000 --- a/libs/wallet/src/web3-react/connectors/TrezorConnector/TrezorProvider.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { JsonRpcProvider } from '@ethersproject/providers' - -import { sendTransactionHandler } from './sendTransactionHandler' -import { signTypedDataHandler } from './signTypedDataHandler' - -import { getHwAccount } from '../../../api/utils/getHwAccount' - -import type transformTypedData from '@trezor/connect-plugin-ethereum' -import type { TrezorConnect } from '@trezor/connect-web' - -export class TrezorProvider extends JsonRpcProvider { - constructor( - url: string, - public readonly accounts: string[], - public readonly trezorConnect: TrezorConnect, - public readonly _transformTypedData: typeof transformTypedData - ) { - super(url) - } - - async send(method: string, params: Array): Promise { - if (method === 'eth_accounts') { - return [this.getCurrentAccount()] - } - - if (method.startsWith('eth_signTypedData')) { - const { domain, types, message, primaryType } = JSON.parse(params[1]) - - return signTypedDataHandler(domain, types, message, primaryType, this.trezorConnect, this._transformTypedData) - } - - if (method === 'eth_sendTransaction') { - return sendTransactionHandler( - params as Parameters[0], - this.getCurrentAccount(), - this, - this.trezorConnect - ) - } - - return super.send(method, params) - } - - private getCurrentAccount(): string { - const currentAccountIndex = getHwAccount().index - - return this.accounts[currentAccountIndex] - } -} diff --git a/libs/wallet/src/web3-react/connectors/TrezorConnector/getAccountsList.ts b/libs/wallet/src/web3-react/connectors/TrezorConnector/getAccountsList.ts deleted file mode 100644 index be5123c9a3..0000000000 --- a/libs/wallet/src/web3-react/connectors/TrezorConnector/getAccountsList.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { publicToAddress } from 'ethereumjs-util' -import HDNode from 'hdkey' - -import { TREZOR_DERIVATION_PATH } from '../../../api/utils/getHwAccount' - -import type { TrezorConnect } from '@trezor/connect-web' - -/** - * This file contains cherry-picked code from import { TrezorSubprovider } from '@0x/subproviders' - */ - -export async function getAccountsList(trezorConnect: TrezorConnect, offset = 0, limit = 100): Promise { - const initialDerivedKeyInfo = await initialDerivedKeyInfoAsync(trezorConnect) - - if (!initialDerivedKeyInfo) return null - - const derivedKeyInfos = calculateDerivedHDKeyInfos(initialDerivedKeyInfo, offset, limit) - - return derivedKeyInfos.map((k) => k.address) -} - -interface DerivedHDKeyInfo { - hdKey: HDNode - address: string - derivationPath: string - baseDerivationPath: string -} - -class DerivedHDKeyInfoIterator { - private index = 0 - - constructor(private parentDerivedKeyInfo: DerivedHDKeyInfo, private offset = 0, private limit = 100) {} - next() { - const baseDerivationPath = this.parentDerivedKeyInfo.baseDerivationPath - const derivationIndex = this.offset + this.index - const fullDerivationPath = `m/${baseDerivationPath}/${derivationIndex}` - const path = `m/${derivationIndex}` - const hdKey = this.parentDerivedKeyInfo.hdKey.derive(path) - const address = addressOfHDKey(hdKey) - const derivedKey = { - address, - hdKey, - baseDerivationPath, - derivationPath: fullDerivationPath, - } - const isDone = this.index === this.limit - this.index++ - return { - done: isDone, - value: derivedKey, - } - } - [Symbol.iterator]() { - return this - } -} - -const derivedKeyInfoCache = new Map() - -async function initialDerivedKeyInfoAsync(trezorConnect: TrezorConnect): Promise { - if (derivedKeyInfoCache.has(trezorConnect)) { - return derivedKeyInfoCache.get(trezorConnect) || null - } - - const response = await trezorConnect.getPublicKey({ - path: TREZOR_DERIVATION_PATH, - }) - - if (!response.success) return null - - const payload = response.payload - const hdKey = new HDNode() - hdKey.publicKey = new Buffer(payload.publicKey, 'hex') - hdKey.chainCode = new Buffer(payload.chainCode, 'hex') - const address = addressOfHDKey(hdKey) - - const info: DerivedHDKeyInfo = { - hdKey, - address, - derivationPath: TREZOR_DERIVATION_PATH, - baseDerivationPath: TREZOR_DERIVATION_PATH.slice(2), - } - - derivedKeyInfoCache.set(trezorConnect, info) - - return info -} - -function calculateDerivedHDKeyInfos( - parentDerivedKeyInfo: DerivedHDKeyInfo, - offset: number, - limit: number -): DerivedHDKeyInfo[] { - const derivedKeys: DerivedHDKeyInfo[] = [] - const derivedKeyIterator = new DerivedHDKeyInfoIterator(parentDerivedKeyInfo, offset, limit) - - for (const key of derivedKeyIterator) { - derivedKeys.push(key) - } - - return derivedKeys -} - -function addressOfHDKey(hdKey: HDNode): string { - const shouldSanitizePublicKey = true - const derivedPublicKey = hdKey.publicKey - const ethereumAddressUnprefixed = publicToAddress(derivedPublicKey, shouldSanitizePublicKey).toString('hex') - - return '0x' + ethereumAddressUnprefixed.toLowerCase() -} diff --git a/libs/wallet/src/web3-react/connectors/TrezorConnector/index.ts b/libs/wallet/src/web3-react/connectors/TrezorConnector/index.ts deleted file mode 100644 index 8a399fbc60..0000000000 --- a/libs/wallet/src/web3-react/connectors/TrezorConnector/index.ts +++ /dev/null @@ -1,159 +0,0 @@ -import { RPC_URLS } from '@cowprotocol/common-const' -import { getCurrentChainIdFromUrl } from '@cowprotocol/common-utils' -import { SupportedChainId } from '@cowprotocol/cow-sdk' -import { Command } from '@cowprotocol/types' -import { Connector } from '@web3-react/types' - -import { TrezorProvider } from './TrezorProvider' - -import { getHwAccount } from '../../../api/utils/getHwAccount' - -import type transformTypedData from '@trezor/connect-plugin-ethereum' -import type { TrezorConnect } from '@trezor/connect-web' - -const defaultChainId = getCurrentChainIdFromUrl() - -const trezorConfig: Parameters[0] = { - env: 'web', - manifest: { - email: 'dev@cow.fi', - appUrl: 'https://cow.fi', - }, -} - -const ACCOUNTS_LIMIT = 100 - -export class TrezorConnector extends Connector { - public customProvider?: TrezorProvider = undefined - - private currentAccountIndex = 0 - - private activatedNetwork: SupportedChainId | null = null - - private trezorConnect: TrezorConnect | null = null - - private accounts: string[] | null = null - - private accountsOffset = 0 - - private cancelActivation: Command = () => void 0 - - connectEagerly(...args: unknown[]) { - return this.activate(args[0] as SupportedChainId) - } - - getAccounts(): string[] | null { - return this.accounts - } - - async activate( - chainId: SupportedChainId | { chainId: SupportedChainId } = defaultChainId, - indexChanged = false - ): Promise { - const desiredChainId = typeof chainId === 'object' ? chainId.chainId : chainId - - // Skip when wallet already has the index set - if (indexChanged) { - if (this.currentAccountIndex === getHwAccount().index) { - return - } - - const account = this.getCurrentAccount() - this.actions.update({ accounts: [account] }) - return - } - - // Skip when wallet is already on the requested network - if (this.activatedNetwork === desiredChainId && !indexChanged) { - return - } - - const url = RPC_URLS[desiredChainId] - const initialConnect = this.activatedNetwork === null - - try { - this.activatedNetwork = desiredChainId - - const { default: trezorConnect } = await import('@trezor/connect-web') - const { default: transformTypedData } = await import('@trezor/connect-plugin-ethereum') - - this.trezorConnect = trezorConnect - - if (initialConnect) { - this.cancelActivation = this.actions.startActivation() - await trezorConnect.init(trezorConfig) - } - - await this.installProvider(url, trezorConnect, transformTypedData) - } catch (error) { - await this.deactivate() - - console.error('Trezor activation error:', error) - - throw error - } - } - - deactivate(): Promise | void { - this.activatedNetwork = null - this.accountsOffset = 0 - this.cancelActivation() - - return this.trezorConnect?.dispose() - } - - async loadMoreAccounts(): Promise { - await this.loadAccounts(this.accountsOffset + ACCOUNTS_LIMIT) - } - - async loadAccounts(offset: number): Promise { - this.accountsOffset = offset - - const accounts = await import('./getAccountsList').then((module) => - module.getAccountsList(this.trezorConnect!, offset, ACCOUNTS_LIMIT) - ) - - this.accounts = (this.accounts || []).concat(accounts || []) - } - - private getCurrentAccount(): string { - if (!this.accounts || this.accounts.length === 0) { - throw new Error('Cannot load Trezor accounts. Make sure that the Trezor device is connected.') - } - - const currentAccountIndex = getHwAccount().index - const account = this.accounts[currentAccountIndex] - - if (!account) { - throw new Error('Current Trezor account index is out of bounds.') - } - - return account - } - - private async installProvider( - url: string, - trezorConnect: TrezorConnect, - _transformTypedData: typeof transformTypedData - ) { - await this.loadAccounts(0) - - const account = this.getCurrentAccount() - const customProvider = new TrezorProvider(url, this.accounts!, trezorConnect, _transformTypedData) - - this.customProvider = customProvider - - const network = await customProvider.getNetwork() - const { chainId } = network - - trezorConnect.on('DEVICE_EVENT', (event) => { - if (event.type === 'device-disconnect') { - this.actions.resetState() - this.deactivate() - } - }) - - this.currentAccountIndex = getHwAccount().index - this.actions.update({ accounts: [account], chainId }) - } -} diff --git a/libs/wallet/src/web3-react/connectors/TrezorConnector/sendTransactionHandler.ts b/libs/wallet/src/web3-react/connectors/TrezorConnector/sendTransactionHandler.ts deleted file mode 100644 index f033692228..0000000000 --- a/libs/wallet/src/web3-react/connectors/TrezorConnector/sendTransactionHandler.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { gasPriceAtom, jotaiStore } from '@cowprotocol/core' -import { JsonRpcProvider } from '@ethersproject/providers' -import { serialize } from '@ethersproject/transactions' - -import { EthereumTransaction } from '@trezor/connect' - -import { getHwAccount } from '../../../api/utils/getHwAccount' - -import type { TrezorConnect } from '@trezor/connect-web' - -export async function sendTransactionHandler( - params: [{ to: string; value: string | undefined; data: string | undefined }], - account: string, - provider: JsonRpcProvider, - trezorConnect: TrezorConnect -) { - const { chainId } = await provider.getNetwork() - const nonce = await provider.send('eth_getTransactionCount', [account, 'latest']) - - const originalTx = params[0] - const estimation = await provider.estimateGas(originalTx) - const gasPrice = jotaiStore.get(gasPriceAtom)?.fast - - const transaction: EthereumTransaction = { - to: originalTx.to, - value: originalTx.value || '0x0', - data: originalTx.data || '0x', - gasPrice: gasPrice ? `0x${BigInt(gasPrice).toString(16)}` : '0x0', - gasLimit: estimation.toHexString(), - nonce, - chainId, - } - - const { success, payload } = await trezorConnect.ethereumSignTransaction({ - path: getHwAccount().path, - transaction, - }) - - if (!success) { - console.error('Trezor tx signing error: ', payload) - throw new Error(payload.error) - } - - const serialized = serialize( - { ...transaction, nonce: +transaction.nonce }, - { - ...payload, - v: +payload.v, - } - ) - - return provider.send('eth_sendRawTransaction', [serialized]) -} diff --git a/libs/wallet/src/web3-react/connectors/TrezorConnector/signTypedDataHandler.ts b/libs/wallet/src/web3-react/connectors/TrezorConnector/signTypedDataHandler.ts deleted file mode 100644 index c285dfb496..0000000000 --- a/libs/wallet/src/web3-react/connectors/TrezorConnector/signTypedDataHandler.ts +++ /dev/null @@ -1,41 +0,0 @@ -import type { TypedDataDomain, TypedDataField } from '@ethersproject/abstract-signer' - -import { getHwAccount } from '../../../api/utils/getHwAccount' - -import type transformTypedData from '@trezor/connect-plugin-ethereum' -import type { TrezorConnect } from '@trezor/connect-web' - -export async function signTypedDataHandler( - domain: TypedDataDomain, - types: Record>, - message: Record, - primaryType: string, - trezorConnect: TrezorConnect, - _transformTypedData: typeof transformTypedData -): Promise { - const eip712Data = { - domain, - types, - message, - primaryType, - } as Parameters[0] - - const { domain_separator_hash, message_hash } = _transformTypedData(eip712Data, true) - - if (!message_hash) throw new Error('Trezor sign typed data no message hash: ' + JSON.stringify(eip712Data)) - - const result = await trezorConnect.ethereumSignTypedData({ - path: getHwAccount().path, - data: eip712Data, - metamask_v4_compat: true, - // These are optional, but required for T1 compatibility - domain_separator_hash, - message_hash, - }) - - if (!result.success) throw new Error(result.payload.error) - - const { signature } = result.payload - - return signature -} diff --git a/libs/wallet/src/web3-react/connectors/WalletConnectV2Connector/index.tsx b/libs/wallet/src/web3-react/connectors/WalletConnectV2Connector/index.tsx deleted file mode 100644 index 9db9922707..0000000000 --- a/libs/wallet/src/web3-react/connectors/WalletConnectV2Connector/index.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { WalletConnect } from '@web3-react/walletconnect-v2' - -export class WalletConnectV2Connector extends WalletConnect { - async activate(desiredChainId?: number): Promise { - const isNetworkSwitching = !!this.provider?.session - - await super.activate(isNetworkSwitching ? desiredChainId : undefined) - - /** - * In CoW Swap we have "change wallet" functionality. - * When user changes wallet from WC to another one and back to WC, we need to update the state. - * Because in `WalletConnect.activate()` they don't update the state if the session is the same. - */ - if (this.provider) { - this.actions.update({ chainId: this.provider.chainId, accounts: this.provider.accounts }) - } - } -} diff --git a/libs/wallet/src/web3-react/connectors/metaMaskSdk/index.ts b/libs/wallet/src/web3-react/connectors/metaMaskSdk/index.ts deleted file mode 100644 index 69c4f15698..0000000000 --- a/libs/wallet/src/web3-react/connectors/metaMaskSdk/index.ts +++ /dev/null @@ -1,307 +0,0 @@ -import type { - Actions, - AddEthereumChainParameter, - Provider, - ProviderConnectInfo, - ProviderRpcError, - WatchAssetParameters, -} from '@web3-react/types' -import { Connector } from '@web3-react/types' - -import type { MetaMaskSDK as _MetaMaskSDK, MetaMaskSDKOptions as _MetaMaskSDKOptions, SDKProvider } from '@metamask/sdk' - -/** - * MetaMaskSDK options. - */ -type MetaMaskSDKOptions = Pick<_MetaMaskSDKOptions, 'infuraAPIKey' | 'readonlyRPCMap'> & { - dappMetadata: Pick<_MetaMaskSDKOptions['dappMetadata'], 'name' | 'url' | 'iconUrl'> -} - -/** - * Listener type for MetaMaskSDK events. - */ -type Listener = Parameters[1] - -/** - * Error thrown when the MetaMaskSDK is not installed. - */ -export class NoMetaMaskSDKError extends Error { - public constructor() { - super('MetaMaskSDK not installed') - this.name = NoMetaMaskSDKError.name - Object.setPrototypeOf(this, NoMetaMaskSDKError.prototype) - } -} - -/** - * Parses a chainId from a string or number. - */ -function parseChainId(chainId: string | number) { - return typeof chainId === 'number' ? chainId : Number.parseInt(chainId, chainId.startsWith('0x') ? 16 : 10) -} - -/** - * @param options - Options to pass to `@metamask/sdk` - * @param onError - Handler to report errors thrown from eventListeners. - */ -export interface MetaMaskSDKConstructorArgs { - actions: Actions - options?: MetaMaskSDKOptions - onError?: (error: Error) => void -} - -/** - * Connector for the MetaMaskSDK. - */ -export class MetaMaskSDK extends Connector { - private sdk?: _MetaMaskSDK - provider?: SDKProvider = undefined - private readonly options: MetaMaskSDKOptions - private eagerConnection?: Promise - - /** - * @inheritdoc Connector.constructor - */ - constructor({ actions, options, onError }: MetaMaskSDKConstructorArgs) { - super(actions, onError) - - const defaultUrl = typeof window !== 'undefined' ? `${window.location.protocol}//${window.location.host}` : '' - - this.options = { - ...options, - dappMetadata: options?.dappMetadata ?? { - url: defaultUrl, - name: defaultUrl !== '' ? undefined : 'wagmi', - }, - } - } - - /** - * Indicates whether the user is connected to the MetaMaskSDK. - */ - private async isConnected() { - try { - if (this.provider?.isConnected?.() === true) { - if (this.sdk?.isExtensionActive() === true) { - const accounts = ((await this.provider?.request({ method: 'eth_accounts' })) ?? []) as string[] - return accounts.length > 0 - } - - return true - } - } catch { - // ignore - } - - return false - } - - /** - * @inheritdoc Connector.isomorphicInitialize - */ - private async isomorphicInitialize(): Promise { - if (this.eagerConnection) return - - return (this.eagerConnection = import('@metamask/sdk').then(async (m) => { - if (!this.sdk) { - this.sdk = new m.default({ - _source: 'web3React', - useDeeplink: true, - injectProvider: false, - forceInjectProvider: false, - forceDeleteProvider: false, - ...this.options, - }) - await this.sdk.init() - } - - this.provider = this.sdk.getProvider()! - - this.provider.on('connect', (({ chainId }: ProviderConnectInfo): void => { - this.actions.update({ chainId: parseChainId(chainId) }) - }) as Listener) - - this.provider.on('disconnect', (async (error: ProviderRpcError): Promise => { - const originalError = ((error.data as any)?.originalError ?? error) as ProviderRpcError - - // If MetaMask emits a `code: 1013` error, wait for reconnection before disconnecting - // https://github.com/MetaMask/providers/pull/120 - if (error && originalError.code === 1013 && this.provider) { - const accounts = (await this.provider.request({ method: 'eth_accounts' })) as string[] - if (accounts.length > 0) return - } - - this.clearCache() - - this.actions.resetState() - this.onError?.(error) - }) as Listener) - - this.provider.on('chainChanged', ((chainId: string): void => { - this.actions.update({ chainId: parseChainId(chainId) }) - }) as Listener) - - this.provider.on('accountsChanged', ((accounts: string[]): void => { - // Disconnect if there are no accounts - if (accounts.length === 0) { - // ... and using browser extension - if (this.sdk?.isExtensionActive()) { - this.clearCache() - this.actions.resetState() - } - // FIXME(upstream): Mobile app sometimes emits invalid `accountsChanged` event with empty accounts array - else return - } else { - this.actions.update({ accounts }) - } - }) as Listener) - })) - } - - /** - * @inheritdoc Connector.connectEagerly - */ - public async connectEagerly(): Promise { - const cancelActivation = this.actions.startActivation() - - try { - await this.isomorphicInitialize() - if (!this.provider) return cancelActivation() - - // Wallets may resolve eth_chainId and hang on eth_accounts pending user interaction, which may include changing - // chains; they should be requested serially, with accounts first, so that the chainId can settle. - const accounts = (await this.provider.request({ method: 'eth_accounts' })) as string[] - if (!accounts.length) throw new Error('No accounts returned') - const chainId = (await this.provider.request({ method: 'eth_chainId' })) as string - this.actions.update({ chainId: parseChainId(chainId), accounts }) - } catch { - // we should be able to use `cancelActivation` here, but on mobile, metamask emits a 'connect' - // event, meaning that chainId is updated, and cancelActivation doesn't work because an intermediary - // update has occurred, so we reset state instead - this.actions.resetState() - } - } - - /** - * Initiates a connection. - * - * @param desiredChainIdOrChainParameters - If defined, indicates the desired chain to connect to. If the user is - * already connected to this chain, no additional steps will be taken. Otherwise, the user will be prompted to switch - * to the chain, if one of two conditions is met: either they already have it added in their extension, or the - * argument is of type AddEthereumChainParameter, in which case the user will be prompted to add the chain with the - * specified parameters first, before being prompted to switch. - */ - public async activate(desiredChainIdOrChainParameters?: number | AddEthereumChainParameter): Promise { - const [desiredChainId, desiredChain] = - typeof desiredChainIdOrChainParameters === 'number' - ? [desiredChainIdOrChainParameters, undefined] - : [desiredChainIdOrChainParameters?.chainId, desiredChainIdOrChainParameters] - - // If user already connected, only switch chain - if (this.provider && (await this.isConnected())) { - await this.switchChain(desiredChainId, desiredChain) - return - } - - // If user not connected, connect eagerly - // Then switch chain - const cancelActivation = this.actions.startActivation() - return this.isomorphicInitialize() - .then(async () => { - if (!this.provider || !this.sdk) throw new NoMetaMaskSDKError() - - const accounts = await this.sdk.connect() - const currentChainIdHex = (await this.provider.request({ method: 'eth_chainId' })) as string - const currentChainId = parseChainId(currentChainIdHex) - - await this.actions.update({ chainId: currentChainId, accounts }) - }) - .catch((error) => { - cancelActivation?.() - throw error - }) - } - - /** - * @inheritdoc Connector.deactivate - */ - public deactivate(): void { - this.sdk?.terminate() - } - - /** - * Watches an asset in the MetaMask wallet. - */ - public async watchAsset({ address, symbol, decimals, image }: WatchAssetParameters): Promise { - if (!this.provider) throw new NoMetaMaskSDKError() - - return this.provider - .request({ - method: 'wallet_watchAsset', - params: { - type: 'ERC20', // Initially only supports ERC20, but eventually more! - options: { - address, // The address that the token is at. - symbol, // A ticker symbol or shorthand, up to 5 chars. - decimals, // The number of decimals in the token - image, // A string url of the token logo - }, - }, - }) - .then((success) => { - if (!success) throw new Error('Rejected') - return true - }) - } - - /** - * Switches the chain of the MetaMask wallet. - * - * Only switches the chain if the desired chain is different from the current chain. - * Else returns the current chain id. - */ - private async switchChain(desiredChainId?: number, desiredChain?: AddEthereumChainParameter): Promise { - if (!this.provider) throw new NoMetaMaskSDKError() - - const currentChainIdHex = (await this.provider.request({ method: 'eth_chainId' })) as string - const currentChainId = parseChainId(currentChainIdHex) - - if (!desiredChainId || currentChainId === desiredChainId) return currentChainId - - const chainIdHex = `0x${desiredChainId.toString(16)}` - this.provider - .request({ - method: 'wallet_switchEthereumChain', - params: [{ chainId: chainIdHex }], - }) - .catch(async (error: ProviderRpcError) => { - const originalError = ((error.data as any)?.originalError ?? error) as ProviderRpcError - - if (originalError.code === 4902 && desiredChain !== undefined) { - if (!this.provider) throw new NoMetaMaskSDKError() - // if we're here, we can try to add a new network - return this.provider.request({ - method: 'wallet_addEthereumChain', - params: [{ ...desiredChain, chainId: chainIdHex }], - }) - } - - throw error - }) - - const newChainIdHex = (await this.provider.request({ method: 'eth_chainId' })) as string - const newChainId = parseChainId(newChainIdHex) - - return newChainId - } - - /** - * Clears the cache. - */ - private clearCache() { - localStorage.removeItem('.MMSDK_cached_address') - localStorage.removeItem('.MMSDK_cached_chainId') - localStorage.removeItem('.sdk-comm') - localStorage.removeItem('.MetaMaskSDKLng') - } -} diff --git a/libs/wallet/src/web3-react/hooks/useActivateConnector.ts b/libs/wallet/src/web3-react/hooks/useActivateConnector.ts deleted file mode 100644 index 9a3fb0b12e..0000000000 --- a/libs/wallet/src/web3-react/hooks/useActivateConnector.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { useCallback, useMemo, useState } from 'react' - -import { getCurrentChainIdFromUrl } from '@cowprotocol/common-utils' -import { Connector } from '@web3-react/types' - -import { useWalletInfo } from '../../api/hooks' -import { ConnectionType } from '../../api/types' -import { getIsHardWareWallet } from '../utils/getIsHardWareWallet' -import { getWeb3ReactConnection } from '../utils/getWeb3ReactConnection' - -export interface ConnectorActivationContext { - skipNetworkChanging?: boolean - - beforeActivation(): void - - afterActivation(isHardWareWallet: boolean, connectionType: ConnectionType): void - - onActivationError(error: any): void -} - -export function useActivateConnector({ - skipNetworkChanging, - beforeActivation, - afterActivation, - onActivationError, -}: ConnectorActivationContext) { - const { chainId } = useWalletInfo() - const [pendingConnector, setPendingConnector] = useState() - - const tryActivation = useCallback( - async (connector: Connector) => { - const connection = getWeb3ReactConnection(connector) - const connectionType = connection.type - const isHardWareWallet = getIsHardWareWallet(connectionType) - - // Skips wallet connection if the connection should override the default - // behavior, i.e. install MetaMask or launch Coinbase app - if (connection.overrideActivate?.(chainId)) return - - try { - setPendingConnector(connector) - beforeActivation() - - await connector.activate(skipNetworkChanging ? undefined : getCurrentChainIdFromUrl()) - - afterActivation(isHardWareWallet, connectionType) - } catch (error: any) { - console.error(`[tryActivation] web3-react connection error`, error) - - onActivationError(error) - } - }, - [chainId, skipNetworkChanging, afterActivation, beforeActivation, onActivationError], - ) - - return useMemo( - () => ({ - tryActivation, - retryPendingActivation: () => { - if (pendingConnector) { - tryActivation(pendingConnector) - } - }, - }), - [tryActivation, pendingConnector], - ) -} diff --git a/libs/wallet/src/web3-react/hooks/useConnectionType.ts b/libs/wallet/src/web3-react/hooks/useConnectionType.ts deleted file mode 100644 index 377ea1777a..0000000000 --- a/libs/wallet/src/web3-react/hooks/useConnectionType.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { useMemo } from 'react' - -import { useWeb3React } from '@web3-react/core' - -import { getWeb3ReactConnection } from '../utils/getWeb3ReactConnection' - -export function useConnectionType() { - const { connector } = useWeb3React() - - return useMemo(() => getWeb3ReactConnection(connector).type, [connector]) -} diff --git a/libs/wallet/src/web3-react/hooks/useDisconnectWallet.ts b/libs/wallet/src/web3-react/hooks/useDisconnectWallet.ts deleted file mode 100644 index b0aefec82a..0000000000 --- a/libs/wallet/src/web3-react/hooks/useDisconnectWallet.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { useCallback } from 'react' - -import { Command } from '@cowprotocol/types' -import { useWeb3React } from '@web3-react/core' - -export function useDisconnectWallet(onDisconnect?: Command) { - const { connector } = useWeb3React() - - return useCallback(() => { - if (connector.deactivate) { - connector.deactivate() - } else { - connector.resetState() - } - - onDisconnect?.() - }, [onDisconnect, connector]) -} diff --git a/libs/wallet/src/web3-react/hooks/useIsActiveConnection.ts b/libs/wallet/src/web3-react/hooks/useIsActiveConnection.ts deleted file mode 100644 index 89786ff4f0..0000000000 --- a/libs/wallet/src/web3-react/hooks/useIsActiveConnection.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { useWeb3React } from '@web3-react/core' - -import { Web3ReactConnection } from '../types' - -export const useIsActiveConnection = (selectedWallet: string | undefined, connection: Web3ReactConnection) => { - const { account } = useWeb3React() - - const isActive = connection.hooks.useIsActive() - - if (!isActive) { - return false - } else if (isActive && !selectedWallet && account) { - return true - } else { - return selectedWallet === connection.type - } -} diff --git a/libs/wallet/src/web3-react/hooks/useIsWalletConnect.ts b/libs/wallet/src/web3-react/hooks/useIsWalletConnect.ts deleted file mode 100644 index 2c35dd1e52..0000000000 --- a/libs/wallet/src/web3-react/hooks/useIsWalletConnect.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { useMemo } from 'react' - -import { useWeb3React } from '@web3-react/core' -import { Connector } from '@web3-react/types' - -import { ConnectionType } from '../../api/types' -import { getWeb3ReactConnection } from '../utils/getWeb3ReactConnection' - -export function useIsWalletConnect(): boolean { - const { connector } = useWeb3React() - - return useMemo(() => { - return getIsWalletConnect(connector) - }, [connector]) -} - -export function getIsWalletConnect(connector: Connector): boolean { - const connection = getWeb3ReactConnection(connector) - - return ConnectionType.WALLET_CONNECT_V2 === connection.type -} diff --git a/libs/wallet/src/web3-react/hooks/useSafeAppsSdk.ts b/libs/wallet/src/web3-react/hooks/useSafeAppsSdk.ts deleted file mode 100644 index 76d05ba214..0000000000 --- a/libs/wallet/src/web3-react/hooks/useSafeAppsSdk.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { useEffect, useState } from 'react' - -import SafeAppsSDK from '@safe-global/safe-apps-sdk' -import { useWeb3React } from '@web3-react/core' -import { GnosisSafe } from '@web3-react/gnosis-safe' - -export function useSafeAppsSdk(): SafeAppsSDK | null { - const [safeAppsSdk, setSafeAppsSdk] = useState(null) - const { connector, isActive } = useWeb3React() - - useEffect(() => { - if (!isActive || !(connector instanceof GnosisSafe) || !connector.sdk) { - setSafeAppsSdk(null) - } else { - setSafeAppsSdk(connector.sdk) - } - }, [isActive, connector]) - - return safeAppsSdk -} diff --git a/libs/wallet/src/web3-react/hooks/useSwitchNetwork.ts b/libs/wallet/src/web3-react/hooks/useSwitchNetwork.ts deleted file mode 100644 index ff7d38ae45..0000000000 --- a/libs/wallet/src/web3-react/hooks/useSwitchNetwork.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { useCallback } from 'react' - -import { SupportedChainId } from '@cowprotocol/cow-sdk' -import { useWeb3React } from '@web3-react/core' - -import { switchChain } from '../utils/switchChain' - -export function useSwitchNetwork() { - const { connector } = useWeb3React() - - return useCallback( - (targetChain: SupportedChainId) => { - return switchChain(connector, targetChain) - }, - [connector] - ) -} diff --git a/libs/wallet/src/web3-react/hooks/useWalletMetadata.ts b/libs/wallet/src/web3-react/hooks/useWalletMetadata.ts deleted file mode 100644 index 6ba8f2e103..0000000000 --- a/libs/wallet/src/web3-react/hooks/useWalletMetadata.ts +++ /dev/null @@ -1,139 +0,0 @@ -import { useMemo } from 'react' - -import { useWeb3React } from '@web3-react/core' - -import { useSafeAppsSdk } from './useSafeAppsSdk' - -import { useGnosisSafeInfo, useSelectedEip6963ProviderInfo } from '../../api/hooks' -import { ConnectionType } from '../../api/types' -import { getConnectionIcon, getConnectionName } from '../../api/utils/connection' -import { getWeb3ReactConnection } from '../utils/getWeb3ReactConnection' - -const SAFE_APP_NAME = 'Safe App' - -const SAFE_ICON_URL = 'https://app.safe.global/favicon.ico' - -const METADATA_DISCONNECTED: WalletMetaData = { - walletName: undefined, - icon: undefined, -} - -const METADATA_SAFE: WalletMetaData = { - walletName: SAFE_APP_NAME, - icon: SAFE_ICON_URL, -} - -export interface WalletMetaData { - walletName?: string - icon?: string -} - -function getWcWalletIcon(meta: any) { - return meta.icons?.length > 0 ? meta.icons[0] : undefined -} - -function getWcPeerMetadata(provider: any | undefined): WalletMetaData { - // fix for this https://github.com/gnosis/cowswap/issues/1929 - const defaultOutput = { walletName: undefined, icon: undefined } - - if (!provider) { - return defaultOutput - } - - const v1MetaData = provider?.connector?.peerMeta - const v2MetaData = provider?.signer?.session?.peer?.metadata - const meta = v1MetaData || v2MetaData - - if (meta) { - return { - walletName: meta.name, - icon: getWcWalletIcon(meta), - } - } - - return defaultOutput -} - -// FIXME: I notice this function is not calculating always correctly the walletName. Out of scope of this PR to fix. "getConnnectionName" might help -export function useWalletMetaData(standaloneMode?: boolean): WalletMetaData { - const { connector, provider, account } = useWeb3React() - const selectedEip6963Provider = useSelectedEip6963ProviderInfo() - const connectionType = getWeb3ReactConnection(connector).type - - return useMemo(() => { - if (!account) { - return METADATA_DISCONNECTED - } - - if (connectionType === ConnectionType.INJECTED) { - if (standaloneMode === false) { - return { - walletName: 'CoW Swap widget', - icon: 'Identicon', - } - } - - if (selectedEip6963Provider) { - return { - icon: selectedEip6963Provider.info.icon, - walletName: selectedEip6963Provider.info.name, - } - } - } - - if (connectionType === ConnectionType.WALLET_CONNECT_V2) { - const wc = provider?.provider - - if ((wc as any)?.isWalletConnect) { - return getWcPeerMetadata(wc) - } - } - - if (connectionType === ConnectionType.GNOSIS_SAFE) { - // TODO: potentially here is where we'll need to work to show the multiple flavours of Safe wallets - return METADATA_SAFE - } - - return { - icon: getConnectionIcon(connectionType), - walletName: getConnectionName(connectionType), - } - }, [connectionType, provider, account, selectedEip6963Provider, standaloneMode]) -} - -/** - * Detects whether the currently connected wallet is a Safe App - * It'll be false if connected to Safe wallet via WalletConnect - */ -export function useIsSafeApp(): boolean { - const isSafeWallet = useIsSafeWallet() - const sdk = useSafeAppsSdk() - - // If the wallet is not a Safe, or we don't have access to the SafeAppsSDK, we know is not a Safe App - if (!isSafeWallet || !sdk) { - return false - } - - // Will only be a SafeApp if within an iframe - // Which means, window.parent is different than window - return window?.parent !== window -} - -/** - * Detects whether the currently connected wallet is a Safe wallet - * regardless of the connection method (WalletConnect or inside Safe as an App) - */ -export function useIsSafeWallet(): boolean { - return !!useGnosisSafeInfo() -} - -/** - * Detects whether the currently connected wallet is a Safe wallet - * but NOT loaded as a Safe App - */ -export function useIsSafeViaWc(): boolean { - const isSafeApp = useIsSafeApp() - const isSafeWallet = useIsSafeWallet() - - return isSafeWallet && !isSafeApp -} diff --git a/libs/wallet/src/web3-react/pure/AccountIndexSelect/index.cosmos.tsx b/libs/wallet/src/web3-react/pure/AccountIndexSelect/index.cosmos.tsx deleted file mode 100644 index 08a055de26..0000000000 --- a/libs/wallet/src/web3-react/pure/AccountIndexSelect/index.cosmos.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { WETH_SEPOLIA } from '@cowprotocol/common-const' -import { CurrencyAmount } from '@uniswap/sdk-core' - -import styled from 'styled-components/macro' - -import { AccountIndexSelect } from './index' - -const accountsList = [ - '0x95222290dd7278aa3ddd389cc1e1d165cc4bafe5', - '0x4675c7e5baafbffbca748158becba61ef3b0a263', - '0x8e501693b6197d85fd26b93bbf5c0911f79f0979', - '0xefcce23bfbef24cc4fb2dcb2bbc4f6f83c6bda98', -] - -const balances = { - '0x95222290dd7278aa3ddd389cc1e1d165cc4bafe5': CurrencyAmount.fromRawAmount(WETH_SEPOLIA, 10_000_000), - '0x4675c7e5baafbffbca748158becba61ef3b0a263': CurrencyAmount.fromRawAmount(WETH_SEPOLIA, 20_000_000), - '0x8e501693b6197d85fd26b93bbf5c0911f79f0979': CurrencyAmount.fromRawAmount(WETH_SEPOLIA, 30_000_000), - '0xefcce23bfbef24cc4fb2dcb2bbc4f6f83c6bda98': CurrencyAmount.fromRawAmount(WETH_SEPOLIA, 40_000_000), -} - -const Wrapper = styled.div` - width: 500px; - margin: 100px auto; - padding: 20px; - - background: var(--cow-container-bg-01); -` - -const Fixtures = { - default: ( - - console.log('onAccountIndexChange', index)} - loadMoreAccounts={() => { - return new Promise((resolve) => { - console.log('loadMoreAccounts') - setTimeout(resolve, 2000) - }) - }} - /> - - ), -} - -export default Fixtures diff --git a/libs/wallet/src/web3-react/pure/AccountIndexSelect/index.tsx b/libs/wallet/src/web3-react/pure/AccountIndexSelect/index.tsx deleted file mode 100644 index 77068a4864..0000000000 --- a/libs/wallet/src/web3-react/pure/AccountIndexSelect/index.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import { useCallback, useRef, useState } from 'react' - -import { shortenAddress } from '@cowprotocol/common-utils' -import { ButtonPrimary, Loader, SelectDropdown, TokenAmount } from '@cowprotocol/ui' -import { Currency, CurrencyAmount } from '@uniswap/sdk-core' - - -import * as styledEl from './styled' - -export interface AccountIndexSelectProps { - accountsList: string[] - currentIndex: number - balances: { [account: string]: CurrencyAmount | undefined } - onAccountIndexChange(index: number): void - loadMoreAccounts(): Promise -} - -export function AccountIndexSelect(props: AccountIndexSelectProps) { - const { currentIndex, accountsList, balances, onAccountIndexChange, loadMoreAccounts } = props - const selectRef = useRef(null) - const [loadingAccounts, setLoadingAccounts] = useState(false) - - const onAccountIndexChangeCallback = useCallback(() => { - const index = +(selectRef.current?.value || 0) - - onAccountIndexChange(index) - }, [onAccountIndexChange]) - - const loadMoreAccountsCallback = useCallback(async () => { - setLoadingAccounts(true) - - try { - await loadMoreAccounts() - } catch (e) { - console.error('Loading more accounts error:', e) - } - - setLoadingAccounts(false) - }, [loadMoreAccounts]) - - return ( - - - - <> - - Please select which account you would like to use: - - - {accountsList.map((address, index) => { - const balance = balances[address] - - return ( - - ) - })} - - - - {loadingAccounts ? ( - <> - - Loading... - - ) : ( - 'Load more' - )} - - - - - - Connect selected account - - - - - - ) -} diff --git a/libs/wallet/src/web3-react/pure/AccountIndexSelect/styled.tsx b/libs/wallet/src/web3-react/pure/AccountIndexSelect/styled.tsx deleted file mode 100644 index e2a16b4942..0000000000 --- a/libs/wallet/src/web3-react/pure/AccountIndexSelect/styled.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import { ButtonSecondary, Media } from '@cowprotocol/ui' - -import styled from 'styled-components/macro' - -export const Wrapper = styled.div` - ${({ theme }) => theme.flexColumnNoWrap}; - align-items: center; - justify-content: center; - width: 100%; -` - -export const LoaderContainer = styled(ButtonSecondary)` - display: flex; - gap: 8px; - align-items: center; - justify-content: center; - - &[disabled] { - cursor: default; - background: var(--cow-color-lightBlue-opacity-90); - } -` - -export const LoadingMessage = styled.div` - ${({ theme }) => theme.flexRowNoWrap}; - width: 100%; - align-items: center; - justify-content: center; - border-radius: 12px; -` - -export const LoadingWrapper = styled.div` - ${({ theme }) => theme.flexColumnNoWrap}; - width: 100%; - align-items: center; - justify-content: center; -` - -export const SelectWrapper = styled.div` - ${({ theme }) => theme.flexRowNoWrap}; - align-items: center; - justify-content: center; - width: 100%; - margin: 8px 0 0; - gap: 8px; - - ${Media.upToSmall()} { - flex-flow: column wrap; - - ${ButtonSecondary} { - width: 100%; - } - } -` - -export const TextWrapper = styled.div` - ${({ theme }) => theme.flexColumnNoWrap}; - align-items: flex-start; - justify-content: flex-start; - width: 100%; - margin: 0 0 24px; - font-size: 14px; -` diff --git a/libs/wallet/src/web3-react/types.ts b/libs/wallet/src/web3-react/types.ts deleted file mode 100644 index 0f92a8de1e..0000000000 --- a/libs/wallet/src/web3-react/types.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { SupportedChainId } from '@cowprotocol/cow-sdk' -import { Web3ReactHooks } from '@web3-react/core' -import { Connector } from '@web3-react/types' - -import { ConnectionType } from '../api/types' - -export interface Web3ReactConnection { - connector: T - hooks: Web3ReactHooks - type: ConnectionType - overrideActivate?: (chainId: SupportedChainId) => boolean -} - -export type TryActivation = (connector: Connector) => void - -export interface ConnectionOptionProps { - darkMode: boolean - selectedWallet: string | undefined - tryActivation: TryActivation -} diff --git a/libs/wallet/src/web3-react/updaters/HwAccountIndexUpdater.tsx b/libs/wallet/src/web3-react/updaters/HwAccountIndexUpdater.tsx deleted file mode 100644 index 49becd18df..0000000000 --- a/libs/wallet/src/web3-react/updaters/HwAccountIndexUpdater.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { useAtom } from 'jotai' -import { useEffect, useMemo, useRef } from 'react' - -import { useWeb3React } from '@web3-react/core' - -import { useWalletInfo } from '../../api/hooks' -import { hwAccountIndexAtom } from '../../api/state' -import { getIsHardWareWallet } from '../utils/getIsHardWareWallet' -import { getWeb3ReactConnection } from '../utils/getWeb3ReactConnection' - -const indexChanged = true - -export function HwAccountIndexUpdater() { - const [hwAccountIndex, setHwAccountIndex] = useAtom(hwAccountIndexAtom) - const { chainId, account } = useWalletInfo() - const { connector, isActive } = useWeb3React() - const connectorRef = useRef(connector) - - connectorRef.current = connector - - const connectionType = useMemo(() => { - const connection = getWeb3ReactConnection(connector) - - return connection.type - }, [connector]) - - /** - * Reactivate connector each time when account index is changed from HwAccountIndexSelector - * A hardware wallet connector should take into account the second parameter (indexChanged = true) for activate() method - */ - useEffect(() => { - if (!isActive) return - - const isHardWare = getIsHardWareWallet(connectionType) - - if (!isHardWare) return - - console.debug('[Hardware wallet] account index changed', hwAccountIndex) - connectorRef.current?.activate(chainId, indexChanged) - }, [isActive, hwAccountIndex, connectionType, chainId]) - - useEffect(() => { - if (account) return - - setHwAccountIndex(0) - }, [setHwAccountIndex, account]) - - return null -} diff --git a/libs/wallet/src/web3-react/utils/getIsHardWareWallet.ts b/libs/wallet/src/web3-react/utils/getIsHardWareWallet.ts deleted file mode 100644 index ec20354da7..0000000000 --- a/libs/wallet/src/web3-react/utils/getIsHardWareWallet.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { ConnectionType } from '../../api/types' - -// TODO: add others -export const HARDWARE_WALLETS = [ConnectionType.TREZOR] as const - -export type HardWareWallet = (typeof HARDWARE_WALLETS)[number] - -export const getIsHardWareWallet = (connectionType: ConnectionType) => - HARDWARE_WALLETS.includes(connectionType as HardWareWallet) diff --git a/libs/wallet/src/web3-react/utils/getWeb3ReactConnection.ts b/libs/wallet/src/web3-react/utils/getWeb3ReactConnection.ts deleted file mode 100644 index 2b8f7fb69a..0000000000 --- a/libs/wallet/src/web3-react/utils/getWeb3ReactConnection.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Connector } from '@web3-react/types' - -import { ConnectionType } from '../../api/types' -import { coinbaseWalletConnection } from '../connection/coinbase' -import { injectedWalletConnection } from '../connection/injectedWallet' -import { metaMaskSdkConnection } from '../connection/metaMaskSdk' -import { networkConnection } from '../connection/network' -import { gnosisSafeConnection } from '../connection/safe' -import { trezorConnection } from '../connection/trezor' -import { walletConnectConnectionV2 } from '../connection/walletConnectV2' -import { Web3ReactConnection } from '../types' - -const connectionTypeToConnection: Record = { - [ConnectionType.INJECTED]: injectedWalletConnection, - [ConnectionType.METAMASK]: metaMaskSdkConnection, - [ConnectionType.COINBASE_WALLET]: coinbaseWalletConnection, - [ConnectionType.WALLET_CONNECT_V2]: walletConnectConnectionV2, - [ConnectionType.NETWORK]: networkConnection, - [ConnectionType.GNOSIS_SAFE]: gnosisSafeConnection, - [ConnectionType.TREZOR]: trezorConnection, -} -const CONNECTIONS: Web3ReactConnection[] = Object.values(connectionTypeToConnection) - -export function getWeb3ReactConnection(c: Connector | ConnectionType): Web3ReactConnection { - if (c instanceof Connector) { - const connection = CONNECTIONS.find((connection) => connection.connector === c) - if (!connection) { - throw Error('unsupported connector') - } - return connection - } - - const connection = connectionTypeToConnection[c] - - if (!connection) { - throw Error('unsupported connector') - } - - return connection -} diff --git a/libs/wallet/src/web3-react/utils/isChainAllowed.ts b/libs/wallet/src/web3-react/utils/isChainAllowed.ts deleted file mode 100644 index 86c19de13c..0000000000 --- a/libs/wallet/src/web3-react/utils/isChainAllowed.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { ALL_SUPPORTED_CHAIN_IDS, SupportedChainId } from '@cowprotocol/cow-sdk' -import { Connector } from '@web3-react/types' - -import { getWeb3ReactConnection } from './getWeb3ReactConnection' - -import { ConnectionType } from '../../api/types' - -const allowedChainsByWallet: Record = { - [ConnectionType.INJECTED]: ALL_SUPPORTED_CHAIN_IDS, - [ConnectionType.METAMASK]: ALL_SUPPORTED_CHAIN_IDS, - [ConnectionType.COINBASE_WALLET]: ALL_SUPPORTED_CHAIN_IDS, - [ConnectionType.WALLET_CONNECT_V2]: ALL_SUPPORTED_CHAIN_IDS, - [ConnectionType.NETWORK]: ALL_SUPPORTED_CHAIN_IDS, - [ConnectionType.GNOSIS_SAFE]: ALL_SUPPORTED_CHAIN_IDS, - [ConnectionType.TREZOR]: ALL_SUPPORTED_CHAIN_IDS, -} - -export function isChainAllowed(connector: Connector, chainId: number): boolean { - const connection = getWeb3ReactConnection(connector) - - return allowedChainsByWallet[connection.type].includes(chainId) -} diff --git a/libs/wallet/src/web3-react/utils/switchChain.ts b/libs/wallet/src/web3-react/utils/switchChain.ts deleted file mode 100644 index dbbadbe820..0000000000 --- a/libs/wallet/src/web3-react/utils/switchChain.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { getChainInfo, RPC_URLS } from '@cowprotocol/common-const' -import { SupportedChainId } from '@cowprotocol/cow-sdk' -import { Connector } from '@web3-react/types' - -import { getWeb3ReactConnection } from './getWeb3ReactConnection' -import { isChainAllowed } from './isChainAllowed' - -import { ConnectionType } from '../../api/types' -import { getIsWalletConnect } from '../hooks/useIsWalletConnect' - -function getRpcUrls(chainId: SupportedChainId): [string] { - const rpcUrl = WALLET_RPC_SUGGESTION[chainId] || RPC_URLS[chainId] - - return [rpcUrl] -} - -const WALLET_RPC_SUGGESTION: Record = { - [SupportedChainId.MAINNET]: null, - [SupportedChainId.GNOSIS_CHAIN]: 'https://rpc.gnosischain.com/', - [SupportedChainId.ARBITRUM_ONE]: 'https://arb1.arbitrum.io/rpc', - [SupportedChainId.BASE]: 'https://mainnet.base.org', - [SupportedChainId.SEPOLIA]: null, -} - -export const switchChain = async (connector: Connector, chainId: SupportedChainId) => { - if (!isChainAllowed(connector, chainId)) { - throw new Error(`Chain ${chainId} not supported for connector (${typeof connector})`) - } - - const connection = getWeb3ReactConnection(connector) - const isNetworkConnection = connection.type === ConnectionType.NETWORK - const isWalletConnect = getIsWalletConnect(connector) - - if (isNetworkConnection || isWalletConnect) { - await connector.activate(chainId) - } else { - const info = getChainInfo(chainId) - const addChainParameter = { - chainId, - chainName: info.label, - rpcUrls: getRpcUrls(chainId), - nativeCurrency: info.nativeCurrency, - blockExplorerUrls: [info.explorer], - } - await connector.activate(addChainParameter) - } -} diff --git a/package.json b/package.json index e97ff9f62c..9ee2316b4d 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,6 @@ }, "resolutions": { "@safe-global/safe-apps-provider/**/@safe-global/safe-apps-sdk": "^9.1.0", - "@web3-react/gnosis-safe/**/@safe-global/safe-apps-sdk": "^9.1.0", "@types/react": "18.2.22", "@types/react-dom": "npm:types-react-dom@19.0.0-rc.1" }, @@ -131,15 +130,6 @@ "@visx/glyph": "^3.3.0", "@visx/responsive": "^3.10.2", "@visx/shape": "^3.5.0", - "@web3-react/coinbase-wallet": "^8.2.3", - "@web3-react/core": "^8.2.3", - "@web3-react/eip1193": "^8.2.3", - "@web3-react/empty": "^8.2.3", - "@web3-react/gnosis-safe": "^8.2.4", - "@web3-react/metamask": "^8.2.4", - "@web3-react/network": "^8.2.3", - "@web3-react/url": "^8.2.3", - "@web3-react/walletconnect-v2": "^8.5.1", "@web3modal/ethers5": "^4.1.9", "bnc-sdk": "^4.6.0", "buffer": "^6.0.3", @@ -298,7 +288,6 @@ "@vitejs/plugin-react-swc": "^3.6.0", "@vitest/coverage-c8": "~0.33.0", "@vitest/ui": "~1.5.2", - "@web3-react/types": "^8.2.3", "babel-jest": "^29.6.2", "babel-plugin-styled-components": "2.1.4", "babel-plugin-transform-import-meta": "^2.2.0",