@cowprotocol/widget-lib 0.4.0 → 0.6.0-RC.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,11 @@
1
+ import { CowEventListeners } from '@cowprotocol/events';
2
+ export declare class IframeCowEventEmitter {
3
+ private contentWindow;
4
+ private eventEmitter;
5
+ private listeners;
6
+ private widgetListener;
7
+ private instanceNumber;
8
+ constructor(contentWindow: Window, listeners?: CowEventListeners);
9
+ stopListeningIframe(): void;
10
+ updateListeners(listeners?: CowEventListeners): void;
11
+ }
@@ -0,0 +1,44 @@
1
+ import { EthereumProvider, JsonRpcRequestMessage } from './types';
2
+ /**
3
+ * Handles JSON-RPC request comming from an iFrame by delegating to a given Ethereum provider.
4
+ * The result will be passed back to the iFrame.
5
+ *
6
+ * Additionally, it will forward some special events from the wallet, to the iFrame window, for example connect/disconnect/chainChanged
7
+ */
8
+ export declare class IframeRpcProviderBridge {
9
+ private iframeWidow;
10
+ /**
11
+ * The Ethereum provider instance.
12
+ * When is null the JSON-RPC bridge is disconnected from the Ethereum provider.
13
+ * */
14
+ private ethereumProvider;
15
+ /** Stored JSON-RPC requests, to queue them when disconnected. */
16
+ private requestWaitingForConnection;
17
+ /**
18
+ * Creates an instance of IframeRpcProviderBridge.
19
+ * @param iframeWidow - The iFrame window that will post up general RPC messages and to which the IframeRpcProviderBridge will forward the RPC result.
20
+ * Also it will receive some special RPC events coming from the wallet, like connect/chainChanged,accountChanged
21
+ */
22
+ constructor(iframeWidow: Window);
23
+ /**
24
+ * Disconnects the JSON-RPC bridge from the Ethereum provider.
25
+ */
26
+ disconnect(): void;
27
+ /**
28
+ * Handles the 'connect' event and sets up event listeners for Ethereum provider events.
29
+ * @param newProvider - The Ethereum provider to connect.
30
+ */
31
+ onConnect(newProvider: EthereumProvider): void;
32
+ private processPendingRequests;
33
+ /**
34
+ * Processes a JSON-RPC request and sends appropriate response or error via the content window.
35
+ * @param request - The JSON-RPC request to be processed.
36
+ */
37
+ processRpcRequest(request: JsonRpcRequestMessage): void;
38
+ private processRpcCallFromWindow;
39
+ private onProviderEvent;
40
+ /**
41
+ * Forward a JSON-RPC message to the content window.
42
+ */
43
+ private forwardRpcResponseToIframe;
44
+ }
package/README.md CHANGED
@@ -6,7 +6,7 @@ look and much more!
6
6
 
7
7
  ## Live example
8
8
 
9
- See the widget in action in the [widget configurator](../../apps/widget-configurator/src/main.tsx)
9
+ See the widget in action in the [widget configurator](https://widget.cow.fi)
10
10
 
11
11
  ## Docs
12
12
 
@@ -1,12 +1,18 @@
1
- import { CowSwapWidgetParams } from './types';
1
+ import { CowEventListeners } from '@cowprotocol/events';
2
+ import { CowSwapWidgetParams, CowSwapWidgetProps, EthereumProvider } from './types';
2
3
  /**
3
4
  * Callback function signature for updating the CoW Swap Widget.
4
5
  */
5
- export type UpdateWidgetCallback = (params: CowSwapWidgetParams) => void;
6
+ export interface CowSwapWidgetHandler {
7
+ updateParams: (params: CowSwapWidgetParams) => void;
8
+ updateListeners: (newListeners?: CowEventListeners) => void;
9
+ updateProvider: (newProvider?: EthereumProvider) => void;
10
+ destroy: () => void;
11
+ }
6
12
  /**
7
13
  * Generates and injects a CoW Swap Widget into the provided container.
8
14
  * @param container - The HTML element to inject the widget into.
9
15
  * @param params - Parameters for configuring the widget.
10
16
  * @returns A callback function to update the widget with new settings.
11
17
  */
12
- export declare function cowSwapWidget(container: HTMLElement, params?: CowSwapWidgetParams): UpdateWidgetCallback;
18
+ export declare function createCowSwapWidget(container: HTMLElement, props: CowSwapWidgetProps): CowSwapWidgetHandler;
package/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- export { cowSwapWidget } from './cowSwapWidget';
2
- export type { UpdateWidgetCallback } from './cowSwapWidget';
1
+ export { createCowSwapWidget } from './cowSwapWidget';
2
+ export type { CowSwapWidgetHandler } from './cowSwapWidget';
3
3
  export { COWSWAP_URLS } from './consts';
4
4
  export * from './types';
5
+ export * from './messages';
package/index.iife.js CHANGED
@@ -1 +1 @@
1
- var cowSwapWidget=function(i){"use strict";const m="2.0",f="*",l=["connect","disconnect","close","chainChanged","accountsChanged"];class E{constructor(t){this.contentWindow=t,this.ethereumProvider=null,this.requests={},this.processEvent=e=>{e.data.jsonrpc==="2.0"&&(this.ethereumProvider?this.processRequest(e.data):this.requests[e.data.id]=e.data)},window.addEventListener("message",this.processEvent)}disconnect(){this.ethereumProvider=null,window.removeEventListener("message",this.processEvent)}onConnect(t){this.ethereumProvider=t,Object.keys(this.requests).forEach(e=>{this.processRequest(this.requests[e])}),this.requests={},l.forEach(e=>{t.on(e,n=>{this.postMessage({method:e,params:[n]})})})}processRequest(t){if(!this.ethereumProvider)return;(t.method==="enable"?this.ethereumProvider.enable():this.ethereumProvider.request(t)).then(n=>{this.postMessage({id:t.id,result:n})}).catch(n=>{this.postMessage({id:t.id,error:n})})}postMessage(t){this.contentWindow.postMessage({jsonrpc:m,...t},f)}}function v(){return typeof window>"u"||!window?"":`https://swap-dev-git-${window.location.hostname.replace("widget-configurator-git-","").replace("-cowswap.vercel.app","")}-cowswap.vercel.app`}const d={local:"http://localhost:3000",prod:"https://swap.cow.fi",dev:"https://dev.swap.cow.fi",pr:v()};var c=(s=>(s.SWAP="swap",s.LIMIT="limit",s.ADVANCED="advanced",s))(c||{});const h="_";function P(s){const t=d[s.env||"prod"],e=u(s),n=p(s);return t+"/#"+e+"?"+n}function u(s){const{chainId:t=1,sell:e,buy:n,tradeType:o=c.SWAP}=s,r=[(e==null?void 0:e.asset)||h,(n==null?void 0:n.asset)||h].map(encodeURIComponent).join("/");return`/${t}/widget/${o}/${r}`}function p(s){const{sell:t,buy:e,theme:n}=s,o=new URLSearchParams;return t!=null&&t.amount&&o.append("sellAmount",t.amount),e!=null&&e.amount&&o.append("buyAmount",e.amount),n&&o.append("theme",typeof n=="string"?n:n.baseTheme),o}const a="cowSwapWidget",w="640px",W="450px",S=20;function y(s,t={}){const{provider:e}=t,n=T(t);s.innerHTML="",s.appendChild(n);const{contentWindow:o}=n;if(!o)throw new Error("Iframe does not contain a window!");return A(o,t.appCode),M(n,t.height),e&&new E(o).onConnect(e),n.addEventListener("load",()=>{g(t,o)}),r=>g(r,o)}function T(s){const{width:t=W,height:e=w}=s,n=document.createElement("iframe");return n.src=P(s),n.width=t,n.height=e,n.style.border="0",n}function g(s,t){const e=u(s),n=p(s).toString();t.postMessage({key:a,method:"update",urlParams:{pathname:e,search:n},appParams:{...s,provider:void 0}},"*")}function A(s,t){window.addEventListener("message",e=>{e.data.key!==a||e.data.method!=="activate"||s.postMessage({key:a,method:"metaData",metaData:t?{appCode:t}:void 0},"*")})}function M(s,t=w){window.addEventListener("message",e=>{e.data.key!==a||e.data.method!=="iframeHeight"||(s.style.height=e.data.height?`${e.data.height+S}px`:t)})}return i.COWSWAP_URLS=d,i.TradeType=c,i.cowSwapWidget=y,Object.defineProperty(i,Symbol.toStringTag,{value:"Module"}),i}({});
1
+ var cowSwapWidget=function(o){"use strict";const P="cowSwapWidget";function p(t,n,e){const s={key:P,method:n,...typeof e=="object"?e:{}};t.postMessage(s,"*")}function E(t,n,e){const i=s=>{!D(s.data)||s.data.key!==P||s.data.method!==n||e(s.data)};return t.addEventListener("message",i),i}function D(t){return typeof t=="object"&&t!==null&&"key"in t&&"method"in t&&typeof t.key=="string"&&typeof t.method=="string"}function l(t,n,e){t.removeEventListener("message",e)}function m(t,n){t.removeEventListener("message",n)}var d=(t=>(t.ACTIVATE="ACTIVATE",t.UPDATE_HEIGHT="UPDATE_HEIGHT",t.EMIT_COW_EVENT="EMIT_COW_EVENT",t.PROVIDER_RPC_REQUEST="PROVIDER_RPC_REQUEST",t))(d||{}),h=(t=>(t.UPDATE_PARAMS="UPDATE_PARAMS",t.UPDATE_APP_DATA="UPDATE_APP_DATA",t.PROVIDER_RPC_RESPONSE="PROVIDER_RPC_RESPONSE",t.PROVIDER_ON_EVENT="PROVIDER_ON_EVENT",t))(h||{}),w=(t=>(t.SWAP="swap",t.LIMIT="limit",t.ADVANCED="advanced",t))(w||{});const S=["connect","disconnect","close","chainChanged","accountsChanged"];class O{constructor(n){this.iframeWidow=n,this.ethereumProvider=null,this.requestWaitingForConnection={},this.processRpcCallFromWindow=({rpcRequest:e})=>{if(!this.ethereumProvider){e.id&&(this.requestWaitingForConnection[e.id]=e);return}this.processRpcRequest(e)}}disconnect(){this.ethereumProvider=null,l(window,d.PROVIDER_RPC_REQUEST,this.processRpcCallFromWindow)}onConnect(n){this.ethereumProvider?this.disconnect():E(window,d.PROVIDER_RPC_REQUEST,this.processRpcCallFromWindow),this.ethereumProvider=n,this.processPendingRequests(),S.forEach(e=>{n.on(e,i=>this.onProviderEvent(e,i))})}processPendingRequests(){Object.keys(this.requestWaitingForConnection).forEach(n=>{this.processRpcRequest(this.requestWaitingForConnection[n])}),this.requestWaitingForConnection={}}processRpcRequest(n){const{id:e,jsonrpc:i,method:s}=n;if(!this.ethereumProvider||!e)return;(s==="enable"?this.ethereumProvider.enable():this.ethereumProvider.request({...n,id:e})).then(r=>this.forwardRpcResponseToIframe({rpcResponse:{jsonrpc:i,id:e,result:r}})).catch(r=>this.forwardRpcResponseToIframe({rpcResponse:{jsonrpc:i,id:e,error:r}}))}onProviderEvent(n,e){p(this.iframeWidow,h.PROVIDER_ON_EVENT,{event:n,params:e})}forwardRpcResponseToIframe(n){p(this.iframeWidow,h.PROVIDER_RPC_RESPONSE,n)}}function L(){return typeof window>"u"||!window?"":`https://swap-dev-git-${window.location.hostname.replace("widget-configurator-git-","").replace("-cowswap.vercel.app","")}-cowswap.vercel.app`}const R={local:"http://localhost:3000",prod:"https://swap.cow.fi",dev:"https://dev.swap.cow.fi",pr:L()},T="_";function V(t){const n=R[t.env||"prod"],e=_(t),i=g(t);return n+"/#"+e+"?"+i}function _(t){const{chainId:n=1,sell:e,buy:i,tradeType:s=w.SWAP}=t,c=[(e==null?void 0:e.asset)||T,(i==null?void 0:i.asset)||T].map(encodeURIComponent).join("/");return`/${n}/widget/${s}/${c}`}function g(t){const{sell:n,buy:e,theme:i}=t,s=new URLSearchParams;return n!=null&&n.amount&&s.append("sellAmount",n.amount),e!=null&&e.amount&&s.append("buyAmount",e.amount),i&&s.append("theme",typeof i=="string"?i:i.baseTheme),s}class y{constructor(){this.subscriptions={}}on(n){const{event:e,handler:i}=n;this.subscriptions[e]||(this.subscriptions[e]=[]),this.subscriptions[e].push(i)}off(n){const{event:e,handler:i}=n;this.subscriptions[e]&&(this.subscriptions[e]=this.subscriptions[e].filter(s=>s!==i))}emit(n,e){this.subscriptions[n]&&this.subscriptions[n].forEach(i=>i(e))}}let U=1;class N{constructor(n,e=[]){this.contentWindow=n,this.eventEmitter=new y,this.listeners=[],this.instanceNumber=U++,this.updateListeners(e),this.widgetListener=E(this.contentWindow,d.EMIT_COW_EVENT,i=>this.eventEmitter.emit(i.event,i.payload))}stopListeningIframe(){m(this.contentWindow,this.widgetListener)}updateListeners(n){for(const e of this.listeners)this.eventEmitter.off(e);this.listeners=n||[];for(const e of this.listeners)this.eventEmitter.on(e)}}const A="640px",F="450px",b=20;function H(t,n){const{params:e,provider:i,listeners:s}=n;let c=i;const r=M(e);t.innerHTML="",t.appendChild(r);const{contentWindow:u}=r;if(!u)throw console.error("Iframe does not contain a window",r),new Error("Iframe does not contain a window!");const f=[];f.push(q(u,e.appCode)),f.push(G(r,e.height));const C=new N(window,s);let I=v(u,null,c);return r.addEventListener("load",()=>W(u,e,c)),{updateParams:a=>W(u,a,c),updateListeners:a=>C.updateListeners(a),updateProvider:a=>{c=a,I=v(u,I,a)},destroy:()=>{C.stopListeningIframe(),f.forEach(a=>window.removeEventListener("message",a)),t.removeChild(r)}}}function v(t,n,e){n&&n.disconnect();const i=n||new O(t);return e&&i.onConnect(e),i}function M(t){const{width:n=F,height:e=A}=t,i=document.createElement("iframe");return i.src=V(t),i.width=n,i.height=e,i.style.border="0",i}function W(t,n,e){const i=!!e,s=_(n),c=g(n).toString();p(t,h.UPDATE_PARAMS,{urlParams:{pathname:s,search:c},appParams:{...n},hasProvider:i})}function q(t,n){const e=E(window,d.ACTIVATE,()=>{m(window,e),p(t,h.UPDATE_APP_DATA,{metaData:n?{appCode:n}:void 0})});return e}function G(t,n=A){return E(window,d.UPDATE_HEIGHT,e=>{t.style.height=e.height?`${e.height+b}px`:n})}return o.COWSWAP_URLS=R,o.TradeType=w,o.WidgetMethodsEmit=d,o.WidgetMethodsListen=h,o.createCowSwapWidget=H,o.listenToMessageFromWindow=E,o.postMessageToWindow=p,o.stopListeningToMessageFromWindow=l,o.stopListeningWindowListener=m,Object.defineProperty(o,Symbol.toStringTag,{value:"Module"}),o}({});
package/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const g="2.0",m="*",f=["connect","disconnect","close","chainChanged","accountsChanged"];class l{constructor(t){this.contentWindow=t,this.ethereumProvider=null,this.requests={},this.processEvent=e=>{e.data.jsonrpc==="2.0"&&(this.ethereumProvider?this.processRequest(e.data):this.requests[e.data.id]=e.data)},window.addEventListener("message",this.processEvent)}disconnect(){this.ethereumProvider=null,window.removeEventListener("message",this.processEvent)}onConnect(t){this.ethereumProvider=t,Object.keys(this.requests).forEach(e=>{this.processRequest(this.requests[e])}),this.requests={},f.forEach(e=>{t.on(e,n=>{this.postMessage({method:e,params:[n]})})})}processRequest(t){if(!this.ethereumProvider)return;(t.method==="enable"?this.ethereumProvider.enable():this.ethereumProvider.request(t)).then(n=>{this.postMessage({id:t.id,result:n})}).catch(n=>{this.postMessage({id:t.id,error:n})})}postMessage(t){this.contentWindow.postMessage({jsonrpc:g,...t},m)}}function E(){return typeof window>"u"||!window?"":`https://swap-dev-git-${window.location.hostname.replace("widget-configurator-git-","").replace("-cowswap.vercel.app","")}-cowswap.vercel.app`}const h={local:"http://localhost:3000",prod:"https://swap.cow.fi",dev:"https://dev.swap.cow.fi",pr:E()};var r=(s=>(s.SWAP="swap",s.LIMIT="limit",s.ADVANCED="advanced",s))(r||{});const c="_";function v(s){const t=h[s.env||"prod"],e=p(s),n=u(s);return t+"/#"+e+"?"+n}function p(s){const{chainId:t=1,sell:e,buy:n,tradeType:o=r.SWAP}=s,i=[(e==null?void 0:e.asset)||c,(n==null?void 0:n.asset)||c].map(encodeURIComponent).join("/");return`/${t}/widget/${o}/${i}`}function u(s){const{sell:t,buy:e,theme:n}=s,o=new URLSearchParams;return t!=null&&t.amount&&o.append("sellAmount",t.amount),e!=null&&e.amount&&o.append("buyAmount",e.amount),n&&o.append("theme",typeof n=="string"?n:n.baseTheme),o}const a="cowSwapWidget",w="640px",P="450px",W=20;function y(s,t={}){const{provider:e}=t,n=S(t);s.innerHTML="",s.appendChild(n);const{contentWindow:o}=n;if(!o)throw new Error("Iframe does not contain a window!");return T(o,t.appCode),A(n,t.height),e&&new l(o).onConnect(e),n.addEventListener("load",()=>{d(t,o)}),i=>d(i,o)}function S(s){const{width:t=P,height:e=w}=s,n=document.createElement("iframe");return n.src=v(s),n.width=t,n.height=e,n.style.border="0",n}function d(s,t){const e=p(s),n=u(s).toString();t.postMessage({key:a,method:"update",urlParams:{pathname:e,search:n},appParams:{...s,provider:void 0}},"*")}function T(s,t){window.addEventListener("message",e=>{e.data.key!==a||e.data.method!=="activate"||s.postMessage({key:a,method:"metaData",metaData:t?{appCode:t}:void 0},"*")})}function A(s,t=w){window.addEventListener("message",e=>{e.data.key!==a||e.data.method!=="iframeHeight"||(s.style.height=e.data.height?`${e.data.height+W}px`:t)})}exports.COWSWAP_URLS=h;exports.TradeType=r;exports.cowSwapWidget=y;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const _="cowSwapWidget";function p(t,n,e){const i={key:_,method:n,...typeof e=="object"?e:{}};t.postMessage(i,"*")}function u(t,n,e){const s=i=>{!I(i.data)||i.data.key!==_||i.data.method!==n||e(i.data)};return t.addEventListener("message",s),s}function I(t){return typeof t=="object"&&t!==null&&"key"in t&&"method"in t&&typeof t.key=="string"&&typeof t.method=="string"}function g(t,n,e){t.removeEventListener("message",e)}function m(t,n){t.removeEventListener("message",n)}var a=(t=>(t.ACTIVATE="ACTIVATE",t.UPDATE_HEIGHT="UPDATE_HEIGHT",t.EMIT_COW_EVENT="EMIT_COW_EVENT",t.PROVIDER_RPC_REQUEST="PROVIDER_RPC_REQUEST",t))(a||{}),h=(t=>(t.UPDATE_PARAMS="UPDATE_PARAMS",t.UPDATE_APP_DATA="UPDATE_APP_DATA",t.PROVIDER_RPC_RESPONSE="PROVIDER_RPC_RESPONSE",t.PROVIDER_ON_EVENT="PROVIDER_ON_EVENT",t))(h||{}),w=(t=>(t.SWAP="swap",t.LIMIT="limit",t.ADVANCED="advanced",t))(w||{});const D=["connect","disconnect","close","chainChanged","accountsChanged"];class O{constructor(n){this.iframeWidow=n,this.ethereumProvider=null,this.requestWaitingForConnection={},this.processRpcCallFromWindow=({rpcRequest:e})=>{if(!this.ethereumProvider){e.id&&(this.requestWaitingForConnection[e.id]=e);return}this.processRpcRequest(e)}}disconnect(){this.ethereumProvider=null,g(window,a.PROVIDER_RPC_REQUEST,this.processRpcCallFromWindow)}onConnect(n){this.ethereumProvider?this.disconnect():u(window,a.PROVIDER_RPC_REQUEST,this.processRpcCallFromWindow),this.ethereumProvider=n,this.processPendingRequests(),D.forEach(e=>{n.on(e,s=>this.onProviderEvent(e,s))})}processPendingRequests(){Object.keys(this.requestWaitingForConnection).forEach(n=>{this.processRpcRequest(this.requestWaitingForConnection[n])}),this.requestWaitingForConnection={}}processRpcRequest(n){const{id:e,jsonrpc:s,method:i}=n;if(!this.ethereumProvider||!e)return;(i==="enable"?this.ethereumProvider.enable():this.ethereumProvider.request({...n,id:e})).then(o=>this.forwardRpcResponseToIframe({rpcResponse:{jsonrpc:s,id:e,result:o}})).catch(o=>this.forwardRpcResponseToIframe({rpcResponse:{jsonrpc:s,id:e,error:o}}))}onProviderEvent(n,e){p(this.iframeWidow,h.PROVIDER_ON_EVENT,{event:n,params:e})}forwardRpcResponseToIframe(n){p(this.iframeWidow,h.PROVIDER_RPC_RESPONSE,n)}}function S(){return typeof window>"u"||!window?"":`https://swap-dev-git-${window.location.hostname.replace("widget-configurator-git-","").replace("-cowswap.vercel.app","")}-cowswap.vercel.app`}const A={local:"http://localhost:3000",prod:"https://swap.cow.fi",dev:"https://dev.swap.cow.fi",pr:S()},l="_";function L(t){const n=A[t.env||"prod"],e=v(t),s=C(t);return n+"/#"+e+"?"+s}function v(t){const{chainId:n=1,sell:e,buy:s,tradeType:i=w.SWAP}=t,r=[(e==null?void 0:e.asset)||l,(s==null?void 0:s.asset)||l].map(encodeURIComponent).join("/");return`/${n}/widget/${i}/${r}`}function C(t){const{sell:n,buy:e,theme:s}=t,i=new URLSearchParams;return n!=null&&n.amount&&i.append("sellAmount",n.amount),e!=null&&e.amount&&i.append("buyAmount",e.amount),s&&i.append("theme",typeof s=="string"?s:s.baseTheme),i}class V{constructor(){this.subscriptions={}}on(n){const{event:e,handler:s}=n;this.subscriptions[e]||(this.subscriptions[e]=[]),this.subscriptions[e].push(s)}off(n){const{event:e,handler:s}=n;this.subscriptions[e]&&(this.subscriptions[e]=this.subscriptions[e].filter(i=>i!==s))}emit(n,e){this.subscriptions[n]&&this.subscriptions[n].forEach(s=>s(e))}}let y=1;class U{constructor(n,e=[]){this.contentWindow=n,this.eventEmitter=new V,this.listeners=[],this.instanceNumber=y++,this.updateListeners(e),this.widgetListener=u(this.contentWindow,a.EMIT_COW_EVENT,s=>this.eventEmitter.emit(s.event,s.payload))}stopListeningIframe(){m(this.contentWindow,this.widgetListener)}updateListeners(n){for(const e of this.listeners)this.eventEmitter.off(e);this.listeners=n||[];for(const e of this.listeners)this.eventEmitter.on(e)}}const W="640px",N="450px",F=20;function b(t,n){const{params:e,provider:s,listeners:i}=n;let r=s;const o=H(e);t.innerHTML="",t.appendChild(o);const{contentWindow:d}=o;if(!d)throw console.error("Iframe does not contain a window",o),new Error("Iframe does not contain a window!");const E=[];E.push(M(d,e.appCode)),E.push(q(o,e.height));const f=new U(window,i);let P=R(d,null,r);return o.addEventListener("load",()=>T(d,e,r)),{updateParams:c=>T(d,c,r),updateListeners:c=>f.updateListeners(c),updateProvider:c=>{r=c,P=R(d,P,c)},destroy:()=>{f.stopListeningIframe(),E.forEach(c=>window.removeEventListener("message",c)),t.removeChild(o)}}}function R(t,n,e){n&&n.disconnect();const s=n||new O(t);return e&&s.onConnect(e),s}function H(t){const{width:n=N,height:e=W}=t,s=document.createElement("iframe");return s.src=L(t),s.width=n,s.height=e,s.style.border="0",s}function T(t,n,e){const s=!!e,i=v(n),r=C(n).toString();p(t,h.UPDATE_PARAMS,{urlParams:{pathname:i,search:r},appParams:{...n},hasProvider:s})}function M(t,n){const e=u(window,a.ACTIVATE,()=>{m(window,e),p(t,h.UPDATE_APP_DATA,{metaData:n?{appCode:n}:void 0})});return e}function q(t,n=W){return u(window,a.UPDATE_HEIGHT,e=>{t.style.height=e.height?`${e.height+F}px`:n})}exports.COWSWAP_URLS=A;exports.TradeType=w;exports.WidgetMethodsEmit=a;exports.WidgetMethodsListen=h;exports.createCowSwapWidget=b;exports.listenToMessageFromWindow=u;exports.postMessageToWindow=p;exports.stopListeningToMessageFromWindow=g;exports.stopListeningWindowListener=m;
package/index.mjs CHANGED
@@ -1,131 +1,223 @@
1
- const w = "2.0", m = "*", g = ["connect", "disconnect", "close", "chainChanged", "accountsChanged"];
2
- class f {
1
+ const R = "cowSwapWidget";
2
+ function p(t, n, e) {
3
+ const i = {
4
+ key: R,
5
+ method: n,
6
+ ...typeof e == "object" ? e : {}
7
+ };
8
+ t.postMessage(
9
+ i,
10
+ "*"
11
+ // TODO: Change to CoW specific origin in production. https://github.com/cowprotocol/cowswap/issues/3828
12
+ );
13
+ }
14
+ function u(t, n, e) {
15
+ const s = (i) => {
16
+ !I(i.data) || i.data.key !== R || i.data.method !== n || e(i.data);
17
+ };
18
+ return t.addEventListener("message", s), s;
19
+ }
20
+ function I(t) {
21
+ return typeof t == "object" && t !== null && "key" in t && "method" in t && typeof t.key == "string" && typeof t.method == "string";
22
+ }
23
+ function C(t, n, e) {
24
+ t.removeEventListener("message", e);
25
+ }
26
+ function T(t, n) {
27
+ t.removeEventListener("message", n);
28
+ }
29
+ var d = /* @__PURE__ */ ((t) => (t.ACTIVATE = "ACTIVATE", t.UPDATE_HEIGHT = "UPDATE_HEIGHT", t.EMIT_COW_EVENT = "EMIT_COW_EVENT", t.PROVIDER_RPC_REQUEST = "PROVIDER_RPC_REQUEST", t))(d || {}), h = /* @__PURE__ */ ((t) => (t.UPDATE_PARAMS = "UPDATE_PARAMS", t.UPDATE_APP_DATA = "UPDATE_APP_DATA", t.PROVIDER_RPC_RESPONSE = "PROVIDER_RPC_RESPONSE", t.PROVIDER_ON_EVENT = "PROVIDER_ON_EVENT", t))(h || {}), _ = /* @__PURE__ */ ((t) => (t.SWAP = "swap", t.LIMIT = "limit", t.ADVANCED = "advanced", t))(_ || {});
30
+ const D = ["connect", "disconnect", "close", "chainChanged", "accountsChanged"];
31
+ class W {
3
32
  /**
4
- * Creates an instance of JsonRpcManager.
5
- * @param contentWindow - The window for handling events.
33
+ * Creates an instance of IframeRpcProviderBridge.
34
+ * @param iframeWidow - The iFrame window that will post up general RPC messages and to which the IframeRpcProviderBridge will forward the RPC result.
35
+ * Also it will receive some special RPC events coming from the wallet, like connect/chainChanged,accountChanged
6
36
  */
7
- constructor(t) {
8
- this.contentWindow = t, this.ethereumProvider = null, this.requests = {}, this.processEvent = (e) => {
9
- e.data.jsonrpc === "2.0" && (this.ethereumProvider ? this.processRequest(e.data) : this.requests[e.data.id] = e.data);
10
- }, window.addEventListener("message", this.processEvent);
37
+ constructor(n) {
38
+ this.iframeWidow = n, this.ethereumProvider = null, this.requestWaitingForConnection = {}, this.processRpcCallFromWindow = ({ rpcRequest: e }) => {
39
+ if (!this.ethereumProvider) {
40
+ e.id && (this.requestWaitingForConnection[e.id] = e);
41
+ return;
42
+ }
43
+ this.processRpcRequest(e);
44
+ };
11
45
  }
12
46
  /**
13
- * Disconnects the JSON-RPC manager from the Ethereum provider.
47
+ * Disconnects the JSON-RPC bridge from the Ethereum provider.
14
48
  */
15
49
  disconnect() {
16
- this.ethereumProvider = null, window.removeEventListener("message", this.processEvent);
50
+ this.ethereumProvider = null, C(window, d.PROVIDER_RPC_REQUEST, this.processRpcCallFromWindow);
17
51
  }
18
52
  /**
19
53
  * Handles the 'connect' event and sets up event listeners for Ethereum provider events.
20
- * @param ethereumProvider - The Ethereum provider to connect.
54
+ * @param newProvider - The Ethereum provider to connect.
21
55
  */
22
- onConnect(t) {
23
- this.ethereumProvider = t, Object.keys(this.requests).forEach((e) => {
24
- this.processRequest(this.requests[e]);
25
- }), this.requests = {}, g.forEach((e) => {
26
- t.on(e, (n) => {
27
- this.postMessage({ method: e, params: [n] });
28
- });
56
+ onConnect(n) {
57
+ this.ethereumProvider ? this.disconnect() : u(window, d.PROVIDER_RPC_REQUEST, this.processRpcCallFromWindow), this.ethereumProvider = n, this.processPendingRequests(), D.forEach((e) => {
58
+ n.on(e, (s) => this.onProviderEvent(e, s));
29
59
  });
30
60
  }
61
+ processPendingRequests() {
62
+ Object.keys(this.requestWaitingForConnection).forEach((n) => {
63
+ this.processRpcRequest(this.requestWaitingForConnection[n]);
64
+ }), this.requestWaitingForConnection = {};
65
+ }
31
66
  /**
32
67
  * Processes a JSON-RPC request and sends appropriate response or error via the content window.
33
68
  * @param request - The JSON-RPC request to be processed.
34
69
  */
35
- processRequest(t) {
36
- if (!this.ethereumProvider)
70
+ processRpcRequest(n) {
71
+ const { id: e, jsonrpc: s, method: i } = n;
72
+ if (!this.ethereumProvider || !e)
37
73
  return;
38
- (t.method === "enable" ? this.ethereumProvider.enable() : this.ethereumProvider.request(t)).then((n) => {
39
- this.postMessage({ id: t.id, result: n });
40
- }).catch((n) => {
41
- this.postMessage({ id: t.id, error: n });
74
+ (i === "enable" ? this.ethereumProvider.enable() : this.ethereumProvider.request({ ...n, id: e })).then(
75
+ (o) => this.forwardRpcResponseToIframe({
76
+ rpcResponse: { jsonrpc: s, id: e, result: o }
77
+ })
78
+ ).catch(
79
+ (o) => this.forwardRpcResponseToIframe({
80
+ rpcResponse: { jsonrpc: s, id: e, error: o }
81
+ })
82
+ );
83
+ }
84
+ onProviderEvent(n, e) {
85
+ p(this.iframeWidow, h.PROVIDER_ON_EVENT, {
86
+ event: n,
87
+ params: e
42
88
  });
43
89
  }
44
- postMessage(t) {
45
- this.contentWindow.postMessage(
46
- {
47
- jsonrpc: w,
48
- ...t
49
- },
50
- m
51
- );
90
+ /**
91
+ * Forward a JSON-RPC message to the content window.
92
+ */
93
+ forwardRpcResponseToIframe(n) {
94
+ p(this.iframeWidow, h.PROVIDER_RPC_RESPONSE, n);
52
95
  }
53
96
  }
54
- function l() {
97
+ function O() {
55
98
  return typeof window > "u" || !window ? "" : `https://swap-dev-git-${window.location.hostname.replace("widget-configurator-git-", "").replace("-cowswap.vercel.app", "")}-cowswap.vercel.app`;
56
99
  }
57
- const E = {
100
+ const S = {
58
101
  local: "http://localhost:3000",
59
102
  prod: "https://swap.cow.fi",
60
103
  dev: "https://dev.swap.cow.fi",
61
- pr: l()
62
- };
63
- var d = /* @__PURE__ */ ((s) => (s.SWAP = "swap", s.LIMIT = "limit", s.ADVANCED = "advanced", s))(d || {});
64
- const r = "_";
65
- function v(s) {
66
- const t = E[s.env || "prod"], e = h(s), n = p(s);
67
- return t + "/#" + e + "?" + n;
68
- }
69
- function h(s) {
70
- const { chainId: t = 1, sell: e, buy: n, tradeType: o = d.SWAP } = s, i = [(e == null ? void 0 : e.asset) || r, (n == null ? void 0 : n.asset) || r].map(encodeURIComponent).join("/");
71
- return `/${t}/widget/${o}/${i}`;
72
- }
73
- function p(s) {
74
- const { sell: t, buy: e, theme: n } = s, o = new URLSearchParams();
75
- return t != null && t.amount && o.append("sellAmount", t.amount), e != null && e.amount && o.append("buyAmount", e.amount), n && o.append("theme", typeof n == "string" ? n : n.baseTheme), o;
76
- }
77
- const a = "cowSwapWidget", u = "640px", P = "450px", W = 20;
78
- function M(s, t = {}) {
79
- const { provider: e } = t, n = y(t);
80
- s.innerHTML = "", s.appendChild(n);
81
- const { contentWindow: o } = n;
82
- if (!o)
83
- throw new Error("Iframe does not contain a window!");
84
- return T(o, t.appCode), A(n, t.height), e && new f(o).onConnect(e), n.addEventListener("load", () => {
85
- c(t, o);
86
- }), (i) => c(i, o);
87
- }
88
- function y(s) {
89
- const { width: t = P, height: e = u } = s, n = document.createElement("iframe");
90
- return n.src = v(s), n.width = t, n.height = e, n.style.border = "0", n;
91
- }
92
- function c(s, t) {
93
- const e = h(s), n = p(s).toString();
94
- t.postMessage(
95
- {
96
- key: a,
97
- method: "update",
98
- urlParams: {
99
- pathname: e,
100
- search: n
101
- },
102
- appParams: {
103
- ...s,
104
- provider: void 0
105
- }
106
- },
107
- "*"
108
- );
104
+ pr: O()
105
+ }, w = "_";
106
+ function V(t) {
107
+ const n = S[t.env || "prod"], e = A(t), s = v(t);
108
+ return n + "/#" + e + "?" + s;
109
109
  }
110
- function T(s, t) {
111
- window.addEventListener("message", (e) => {
112
- e.data.key !== a || e.data.method !== "activate" || s.postMessage(
113
- {
114
- key: a,
115
- method: "metaData",
116
- metaData: t ? { appCode: t } : void 0
117
- },
118
- "*"
110
+ function A(t) {
111
+ const { chainId: n = 1, sell: e, buy: s, tradeType: i = _.SWAP } = t, r = [(e == null ? void 0 : e.asset) || w, (s == null ? void 0 : s.asset) || w].map(encodeURIComponent).join("/");
112
+ return `/${n}/widget/${i}/${r}`;
113
+ }
114
+ function v(t) {
115
+ const { sell: n, buy: e, theme: s } = t, i = new URLSearchParams();
116
+ return n != null && n.amount && i.append("sellAmount", n.amount), e != null && e.amount && i.append("buyAmount", e.amount), s && i.append("theme", typeof s == "string" ? s : s.baseTheme), i;
117
+ }
118
+ class L {
119
+ constructor() {
120
+ this.subscriptions = {};
121
+ }
122
+ on(n) {
123
+ const { event: e, handler: s } = n;
124
+ this.subscriptions[e] || (this.subscriptions[e] = []), this.subscriptions[e].push(s);
125
+ }
126
+ off(n) {
127
+ const { event: e, handler: s } = n;
128
+ this.subscriptions[e] && (this.subscriptions[e] = this.subscriptions[e].filter((i) => i !== s));
129
+ }
130
+ emit(n, e) {
131
+ this.subscriptions[n] && this.subscriptions[n].forEach((s) => s(e));
132
+ }
133
+ }
134
+ let U = 1;
135
+ class y {
136
+ constructor(n, e = []) {
137
+ this.contentWindow = n, this.eventEmitter = new L(), this.listeners = [], this.instanceNumber = U++, this.updateListeners(e), this.widgetListener = u(
138
+ this.contentWindow,
139
+ d.EMIT_COW_EVENT,
140
+ (s) => this.eventEmitter.emit(s.event, s.payload)
119
141
  );
142
+ }
143
+ stopListeningIframe() {
144
+ T(this.contentWindow, this.widgetListener);
145
+ }
146
+ updateListeners(n) {
147
+ for (const e of this.listeners)
148
+ this.eventEmitter.off(e);
149
+ this.listeners = n || [];
150
+ for (const e of this.listeners)
151
+ this.eventEmitter.on(e);
152
+ }
153
+ }
154
+ const g = "640px", N = "450px", H = 20;
155
+ function M(t, n) {
156
+ const { params: e, provider: s, listeners: i } = n;
157
+ let r = s;
158
+ const o = F(e);
159
+ t.innerHTML = "", t.appendChild(o);
160
+ const { contentWindow: a } = o;
161
+ if (!a)
162
+ throw console.error("Iframe does not contain a window", o), new Error("Iframe does not contain a window!");
163
+ const E = [];
164
+ E.push(b(a, e.appCode)), E.push(q(o, e.height));
165
+ const m = new y(window, i);
166
+ let f = P(a, null, r);
167
+ return o.addEventListener("load", () => l(a, e, r)), {
168
+ updateParams: (c) => l(a, c, r),
169
+ updateListeners: (c) => m.updateListeners(c),
170
+ updateProvider: (c) => {
171
+ r = c, f = P(a, f, c);
172
+ },
173
+ destroy: () => {
174
+ m.stopListeningIframe(), E.forEach((c) => window.removeEventListener("message", c)), t.removeChild(o);
175
+ }
176
+ };
177
+ }
178
+ function P(t, n, e) {
179
+ n && n.disconnect();
180
+ const s = n || new W(t);
181
+ return e && s.onConnect(e), s;
182
+ }
183
+ function F(t) {
184
+ const { width: n = N, height: e = g } = t, s = document.createElement("iframe");
185
+ return s.src = V(t), s.width = n, s.height = e, s.style.border = "0", s;
186
+ }
187
+ function l(t, n, e) {
188
+ const s = !!e, i = A(n), r = v(n).toString();
189
+ p(t, h.UPDATE_PARAMS, {
190
+ urlParams: {
191
+ pathname: i,
192
+ search: r
193
+ },
194
+ appParams: {
195
+ ...n
196
+ },
197
+ hasProvider: s
198
+ });
199
+ }
200
+ function b(t, n) {
201
+ const e = u(window, d.ACTIVATE, () => {
202
+ T(window, e), p(t, h.UPDATE_APP_DATA, {
203
+ metaData: n ? { appCode: n } : void 0
204
+ });
120
205
  });
206
+ return e;
121
207
  }
122
- function A(s, t = u) {
123
- window.addEventListener("message", (e) => {
124
- e.data.key !== a || e.data.method !== "iframeHeight" || (s.style.height = e.data.height ? `${e.data.height + W}px` : t);
208
+ function q(t, n = g) {
209
+ return u(window, d.UPDATE_HEIGHT, (e) => {
210
+ t.style.height = e.height ? `${e.height + H}px` : n;
125
211
  });
126
212
  }
127
213
  export {
128
- E as COWSWAP_URLS,
129
- d as TradeType,
130
- M as cowSwapWidget
214
+ S as COWSWAP_URLS,
215
+ _ as TradeType,
216
+ d as WidgetMethodsEmit,
217
+ h as WidgetMethodsListen,
218
+ M as createCowSwapWidget,
219
+ u as listenToMessageFromWindow,
220
+ p as postMessageToWindow,
221
+ C as stopListeningToMessageFromWindow,
222
+ T as stopListeningWindowListener
131
223
  };
package/messages.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ import { WidgetMethodsEmit, WidgetMethodsEmitPayloadMap, WidgetMethodsListen, WidgetMethodsListenPayloadMap } from './types';
2
+ export declare function postMessageToWindow<T extends WidgetMethodsEmit>(contentWindow: Window, method: T, payload: WidgetMethodsEmitPayloadMap[T]): void;
3
+ export declare function postMessageToWindow<T extends WidgetMethodsListen>(contentWindow: Window, method: T, payload: WidgetMethodsListenPayloadMap[T]): void;
4
+ export type WindowListener = (event: MessageEvent<unknown>) => void;
5
+ export declare function listenToMessageFromWindow<T extends WidgetMethodsListen>(contentWindow: Window, method: T, callback: (payload: WidgetMethodsListenPayloadMap[T]) => void): WindowListener;
6
+ export declare function listenToMessageFromWindow<T extends WidgetMethodsEmit>(contentWindow: Window, method: T, callback: (payload: WidgetMethodsEmitPayloadMap[T]) => void): WindowListener;
7
+ export declare function stopListeningToMessageFromWindow<T extends WidgetMethodsListen>(contentWindow: Window, method: T, callback: (payload: WidgetMethodsListenPayloadMap[T]) => void): void;
8
+ export declare function stopListeningToMessageFromWindow<T extends WidgetMethodsEmit>(contentWindow: Window, method: T, callback: (payload: WidgetMethodsEmitPayloadMap[T]) => void): void;
9
+ export declare function stopListeningWindowListener(contentWindow: Window, callback: WindowListener): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cowprotocol/widget-lib",
3
- "version": "0.4.0",
3
+ "version": "0.6.0-RC.0",
4
4
  "type": "commonjs",
5
5
  "description": "CoW Swap Widget Library. Allows you to easily embed a CoW Swap widget on your website.",
6
6
  "main": "index.js",
package/types.d.ts CHANGED
@@ -1,4 +1,23 @@
1
1
  import type { SupportedChainId } from '@cowprotocol/cow-sdk';
2
+ import { CowEventListeners, CowEventPayloadMap, CowEvents } from '@cowprotocol/events';
3
+ export type { SupportedChainId } from '@cowprotocol/cow-sdk';
4
+ export declare enum WidgetMethodsEmit {
5
+ ACTIVATE = "ACTIVATE",
6
+ UPDATE_HEIGHT = "UPDATE_HEIGHT",
7
+ EMIT_COW_EVENT = "EMIT_COW_EVENT",
8
+ PROVIDER_RPC_REQUEST = "PROVIDER_RPC_REQUEST"
9
+ }
10
+ export declare enum WidgetMethodsListen {
11
+ UPDATE_PARAMS = "UPDATE_PARAMS",
12
+ UPDATE_APP_DATA = "UPDATE_APP_DATA",
13
+ PROVIDER_RPC_RESPONSE = "PROVIDER_RPC_RESPONSE",
14
+ PROVIDER_ON_EVENT = "PROVIDER_ON_EVENT"
15
+ }
16
+ export interface CowSwapWidgetProps {
17
+ params: CowSwapWidgetParams;
18
+ provider?: EthereumProvider;
19
+ listeners?: CowEventListeners;
20
+ }
2
21
  export interface JsonRpcRequest {
3
22
  id: number;
4
23
  method: string;
@@ -49,6 +68,21 @@ export declare enum TradeType {
49
68
  */
50
69
  ADVANCED = "advanced"
51
70
  }
71
+ /**
72
+ * The partner fee
73
+ *
74
+ * Please contact https://cowprotocol.typeform.com/to/rONXaxHV
75
+ */
76
+ export interface PartnerFee {
77
+ /**
78
+ * The fee in basis points (BPS). One basis point is equivalent to 0.01% (1/100th of a percent)
79
+ */
80
+ bps: number;
81
+ /**
82
+ * The Ethereum address of the partner to receive the fee.
83
+ */
84
+ recipient: string;
85
+ }
52
86
  export interface CowSwapWidgetPalette {
53
87
  baseTheme: CowSwapTheme;
54
88
  primary: string;
@@ -61,75 +95,184 @@ export interface CowSwapWidgetPalette {
61
95
  info: string;
62
96
  success: string;
63
97
  }
64
- interface CowSwapWidgetConfig {
65
- /**
66
- * The width of the widget in pixels. Default: 400px
67
- */
68
- width: string;
69
- /**
70
- * The height of the widget in pixels. Default: 600px
71
- */
72
- height: string;
98
+ export interface CowSwapWidgetParams {
73
99
  /**
74
100
  * The unique identifier of the widget consumer.
75
101
  * Please fill the for to let us know a little about you: https://cowprotocol.typeform.com/to/rONXaxHV
76
102
  */
77
103
  appCode: string;
78
104
  /**
79
- * The widget might be connected to a custom Ethereum provider.
105
+ * The width of the widget in pixels. Default: 400px
80
106
  */
81
- provider: EthereumProvider;
107
+ width?: string;
108
+ /**
109
+ * The height of the widget in pixels. Default: 600px
110
+ */
111
+ height?: string;
82
112
  /**
83
113
  * Network ID.
84
114
  */
85
- chainId: SupportedChainId;
115
+ chainId?: SupportedChainId;
86
116
  /**
87
117
  * The token lists urls to use in the widget
88
118
  */
89
- tokenLists: string[];
119
+ tokenLists?: string[];
90
120
  /**
91
121
  * Swap, Limit or Advanced (Twap).
92
122
  */
93
- tradeType: TradeType;
123
+ tradeType?: TradeType;
94
124
  /**
95
125
  * The environment of the widget. Default: prod
96
126
  */
97
- env: CowSwapWidgetEnv;
127
+ env?: CowSwapWidgetEnv;
98
128
  /**
99
129
  * Sell token, and optionally the amount.
100
130
  */
101
- sell: TradeAsset;
131
+ sell?: TradeAsset;
102
132
  /**
103
133
  * Buy token, and optionally the amount.
104
134
  */
105
- buy: TradeAsset;
135
+ buy?: TradeAsset;
106
136
  /**
107
- * The theme of the widget UI.
137
+ * Enables the ability to switch between trade types in the widget.
108
138
  */
109
- theme: CowSwapTheme | CowSwapWidgetPalette;
139
+ enabledTradeTypes?: TradeType[];
110
140
  /**
111
- * Allows to set a custom logo for the widget.
141
+ * The partner fee
142
+ *
143
+ * Please contact https://cowprotocol.typeform.com/to/rONXaxHV
144
+ */
145
+ partnerFee?: PartnerFee;
146
+ /**
147
+ * Disables showing the confirmation modal you get after posting an order.
148
+ * Defaults to false.
149
+ */
150
+ disablePostedOrderConfirmationModal?: boolean;
151
+ /**
152
+ * Disables showing the toast messages.
153
+ * Some UI might want to disable it and subscribe to WidgetMethodsEmit.ON_TOAST_MESSAGE event to handle the toast messages itself.
154
+ * Defaults to false.
112
155
  */
113
- logoUrl: string;
156
+ disableToastMessages?: boolean;
114
157
  /**
115
158
  * Option to hide the logo in the widget.
116
159
  */
117
- hideLogo: boolean;
160
+ hideLogo?: boolean;
118
161
  /**
119
162
  * Option to hide the network selector in the widget.
120
163
  */
121
- hideNetworkSelector: boolean;
164
+ hideNetworkSelector?: boolean;
122
165
  /**
123
- * Enables the ability to switch between trade types in the widget.
166
+ * Hides the connect buttons, and the connected account button. Defaults to false.
124
167
  */
125
- enabledTradeTypes: TradeType[];
168
+ hideConnectButton?: boolean;
126
169
  /**
127
- * The interface fee in basis points.
128
- * For example: 1.5% = 150 bips
129
- *
130
- * Please contact https://cowprotocol.typeform.com/to/rONXaxHV
170
+ * The theme of the widget UI.
171
+ */
172
+ theme?: CowSwapTheme | CowSwapWidgetPalette;
173
+ /**
174
+ * Allows to set a custom logo for the widget.
175
+ */
176
+ logoUrl?: string;
177
+ /**
178
+ * Customizable images for the widget.
131
179
  */
132
- interfaceFeeBips: string;
180
+ images?: {
181
+ /**
182
+ * The image to display when the orders table is empty (no orders yet). It defaults to "Yoga CoW" image.
183
+ * Alternatively, you can use a URL to a custom image file, or set to null to disable the image.
184
+ */
185
+ emptyOrders?: string | null;
186
+ };
187
+ /**
188
+ * Sounds configuration for the app.
189
+ */
190
+ sounds?: {
191
+ /**
192
+ * The sound to play when the order is executed. Defaults to world wide famous CoW Swap moooooooooo!
193
+ * Alternatively, you can use a URL to a custom sound file, or set to null to disable the sound.
194
+ */
195
+ postOrder?: string | null;
196
+ /**
197
+ * The sound to play when the order is executed. Defaults to world wide famous CoW Swap happy moooooooooo!
198
+ * Alternatively, you can use a URL to a custom sound file, or set to null to disable the sound.
199
+ */
200
+ orderExecuted?: string | null;
201
+ /**
202
+ * The sound to play when the order is executed. Defaults to world wide famous CoW Swap unhappy moooooooooo!
203
+ * Alternatively, you can use a URL to a custom sound file, or set to null to disable the sound.
204
+ */
205
+ orderError?: string | null;
206
+ };
207
+ }
208
+ export interface WidgetMethodsEmitPayloadMap {
209
+ [WidgetMethodsEmit.ACTIVATE]: void;
210
+ [WidgetMethodsEmit.EMIT_COW_EVENT]: EmitCowEventPayload<CowEvents>;
211
+ [WidgetMethodsEmit.UPDATE_HEIGHT]: UpdateWidgetHeightPayload;
212
+ [WidgetMethodsEmit.PROVIDER_RPC_REQUEST]: ProviderRpcRequestPayload;
213
+ }
214
+ export interface WidgetMethodsListenPayloadMap {
215
+ [WidgetMethodsListen.UPDATE_APP_DATA]: UpdateAppDataPayload;
216
+ [WidgetMethodsListen.UPDATE_PARAMS]: UpdateParamsPayload;
217
+ [WidgetMethodsListen.PROVIDER_RPC_RESPONSE]: ProviderRpcResponsePayload;
218
+ [WidgetMethodsListen.PROVIDER_ON_EVENT]: ProviderOnEventPayload;
219
+ }
220
+ export type WidgetMethodsEmitPayloads = WidgetMethodsEmitPayloadMap[WidgetMethodsEmit];
221
+ export type WidgetMethodsListenPayloads = WidgetMethodsListenPayloadMap[WidgetMethodsListen];
222
+ export interface UpdateParamsPayload {
223
+ urlParams: {
224
+ pathname: string;
225
+ search: string;
226
+ };
227
+ appParams: CowSwapWidgetParams;
228
+ hasProvider: boolean;
229
+ }
230
+ export interface UpdateAppDataPayload {
231
+ metaData?: {
232
+ appCode: string;
233
+ };
234
+ }
235
+ export interface UpdateWidgetHeightPayload {
236
+ height?: number;
237
+ }
238
+ export interface EmitCowEventPayload<T extends CowEvents> {
239
+ event: T;
240
+ payload: CowEventPayloadMap[T];
241
+ }
242
+ export type WidgetMethodsEmitListener<T extends WidgetMethodsEmit> = T extends WidgetMethodsEmit ? {
243
+ event: T;
244
+ handler: WidgetMethodHandler<T>;
245
+ } : never;
246
+ export type WidgetMethodHandler<T extends WidgetMethodsEmit> = (payload: WidgetMethodsEmitPayloadMap[T]) => void;
247
+ export interface ProviderRpcRequestPayload {
248
+ rpcRequest: JsonRpcRequestMessage;
249
+ }
250
+ export interface JsonRpcRequestMessage {
251
+ jsonrpc: '2.0';
252
+ id?: number;
253
+ method: string;
254
+ params: unknown[];
255
+ }
256
+ export interface BaseJsonRpcResponseMessage {
257
+ id: number;
258
+ jsonrpc: '2.0';
259
+ }
260
+ export interface JsonRpcSucessfulResponseMessage<TResult = unknown> extends BaseJsonRpcResponseMessage {
261
+ result: TResult;
262
+ }
263
+ export interface JsonRpcError<TData = unknown> {
264
+ code: number;
265
+ message: string;
266
+ data?: TData;
267
+ }
268
+ export interface JsonRpcErrorResponseMessage<TErrorData = unknown> extends BaseJsonRpcResponseMessage {
269
+ error: JsonRpcError<TErrorData>;
270
+ }
271
+ export type ProviderRpcResponsePayload = {
272
+ rpcResponse: JsonRpcResponse;
273
+ };
274
+ export type JsonRpcResponse = JsonRpcRequestMessage | JsonRpcErrorResponseMessage | JsonRpcSucessfulResponseMessage;
275
+ export interface ProviderOnEventPayload {
276
+ event: string;
277
+ params: unknown;
133
278
  }
134
- export type CowSwapWidgetParams = Partial<CowSwapWidgetConfig>;
135
- export {};
package/urlUtils.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  import { CowSwapWidgetParams } from './types';
2
- export declare function buildWidgetUrl(params: CowSwapWidgetParams): string;
3
- export declare function buildWidgetPath(params: CowSwapWidgetParams): string;
4
- export declare function buildTradeAmountsQuery(params: CowSwapWidgetParams): URLSearchParams;
2
+ export declare function buildWidgetUrl(params: Partial<CowSwapWidgetParams>): string;
3
+ export declare function buildWidgetPath(params: Partial<CowSwapWidgetParams>): string;
4
+ export declare function buildTradeAmountsQuery(params: Partial<CowSwapWidgetParams>): URLSearchParams;
@@ -1,35 +0,0 @@
1
- import { EthereumProvider, JsonRpcRequest } from './types';
2
- /**
3
- * Manages JSON-RPC requests and interactions with an Ethereum provider.
4
- */
5
- export declare class JsonRpcManager {
6
- private contentWindow;
7
- /**
8
- * The Ethereum provider instance.
9
- * When is null the JSON-RPC manager is disconnected from the Ethereum provider.
10
- * */
11
- private ethereumProvider;
12
- /** Stored JSON-RPC requests. */
13
- private requests;
14
- /**
15
- * Creates an instance of JsonRpcManager.
16
- * @param contentWindow - The window for handling events.
17
- */
18
- constructor(contentWindow: Window);
19
- /**
20
- * Disconnects the JSON-RPC manager from the Ethereum provider.
21
- */
22
- disconnect(): void;
23
- /**
24
- * Handles the 'connect' event and sets up event listeners for Ethereum provider events.
25
- * @param ethereumProvider - The Ethereum provider to connect.
26
- */
27
- onConnect(ethereumProvider: EthereumProvider): void;
28
- /**
29
- * Processes a JSON-RPC request and sends appropriate response or error via the content window.
30
- * @param request - The JSON-RPC request to be processed.
31
- */
32
- processRequest(request: JsonRpcRequest): void;
33
- private processEvent;
34
- private postMessage;
35
- }