@cowprotocol/widget-lib 2.0.0 → 2.0.2

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,10 @@
1
+ import { CowWidgetEventListeners } from '@cowprotocol/events';
2
+ export declare class IframeCowEventEmitter {
3
+ private contentWindow;
4
+ private eventEmitter;
5
+ private listeners;
6
+ private widgetListener;
7
+ constructor(contentWindow: Window, listeners?: CowWidgetEventListeners);
8
+ stopListeningIframe(): void;
9
+ updateListeners(listeners?: CowWidgetEventListeners): void;
10
+ }
@@ -0,0 +1,8 @@
1
+ export declare class IframeSafeSdkBridge {
2
+ private appWindow;
3
+ private iframeWidow;
4
+ forwardSdkMessage: (event: MessageEvent<unknown>) => void;
5
+ constructor(appWindow: Window, iframeWidow: Window);
6
+ private startListening;
7
+ stopListening(): void;
8
+ }
@@ -0,0 +1,18 @@
1
+ import { CowWidgetEventListeners } from '@cowprotocol/events';
2
+ import { CowSwapWidgetParams, CowSwapWidgetProps, EthereumProvider } from './types';
3
+ /**
4
+ * Callback function signature for updating the CoW Swap Widget.
5
+ */
6
+ export interface CowSwapWidgetHandler {
7
+ updateParams: (params: CowSwapWidgetParams) => void;
8
+ updateListeners: (newListeners?: CowWidgetEventListeners) => void;
9
+ updateProvider: (newProvider?: EthereumProvider) => void;
10
+ destroy: () => void;
11
+ }
12
+ /**
13
+ * Generates and injects a CoW Swap Widget into the provided container.
14
+ * @param container - The HTML element to inject the widget into.
15
+ * @param params - Parameters for configuring the widget.
16
+ * @returns A callback function to update the widget with new settings.
17
+ */
18
+ export declare function createCowSwapWidget(container: HTMLElement, props: CowSwapWidgetProps): CowSwapWidgetHandler;
@@ -0,0 +1,5 @@
1
+ import { SupportedChainId } from '@cowprotocol/cow-sdk';
2
+ import { FlexibleConfig, PerNetworkConfig, PerTradeTypeConfig, TradeType } from './types';
3
+ export declare function resolveFlexibleConfig<T>(config: FlexibleConfig<T>, chainId: SupportedChainId, tradeType: TradeType): T | undefined;
4
+ export declare function isPerTradeTypeConfig<T>(config: FlexibleConfig<T>): config is PerTradeTypeConfig<T>;
5
+ export declare function isPerNetworkConfig<T>(config: FlexibleConfig<T>): config is PerNetworkConfig<T>;
package/index.cjs ADDED
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const I=require("@cowprotocol/iframe-transport"),W=require("@cowprotocol/events");var c=(e=>(e.ACTIVATE="ACTIVATE",e.UPDATE_HEIGHT="UPDATE_HEIGHT",e.SET_FULL_HEIGHT="SET_FULL_HEIGHT",e.EMIT_COW_EVENT="EMIT_COW_EVENT",e.PROVIDER_RPC_REQUEST="PROVIDER_RPC_REQUEST",e.INTERCEPT_WINDOW_OPEN="INTERCEPT_WINDOW_OPEN",e))(c||{}),E=(e=>(e.UPDATE_PARAMS="UPDATE_PARAMS",e.UPDATE_APP_DATA="UPDATE_APP_DATA",e.PROVIDER_RPC_RESPONSE="PROVIDER_RPC_RESPONSE",e.PROVIDER_ON_EVENT="PROVIDER_ON_EVENT",e))(E||{}),T=(e=>(e.SWAP="swap",e.LIMIT="limit",e.ADVANCED="advanced",e.YIELD="yield",e))(T||{});const O=["primary","background","paper","text","danger","warning","alert","info","success"],r=new I.IframeTransport("cowSwapWidget");class R{constructor(t,i=[]){this.contentWindow=t,this.updateListeners(i),this.widgetListener=r.listenToMessageFromWindow(this.contentWindow,c.EMIT_COW_EVENT,n=>this.eventEmitter.emit(n.event,n.payload))}eventEmitter=new W.SimpleCowEventEmitter;listeners=[];widgetListener;stopListeningIframe(){r.stopListeningWindowListener(this.contentWindow,this.widgetListener)}updateListeners(t){for(const i of this.listeners)this.eventEmitter.off(i);this.listeners=t||[];for(const i of this.listeners)this.eventEmitter.on(i)}}class D{constructor(t,i){this.appWindow=t,this.iframeWidow=i,this.forwardSdkMessage=n=>{b(n.data)&&(typeof window<"u"&&n.origin===window.location.origin||(y(n.data)?this.appWindow.parent.postMessage(n.data,"*"):M(n.data)&&this.iframeWidow.postMessage(n.data,"*")))},this.startListening()}forwardSdkMessage;startListening(){this.appWindow.addEventListener("message",this.forwardSdkMessage)}stopListening(){this.appWindow.removeEventListener("message",this.forwardSdkMessage)}}function b(e){return typeof e=="object"&&e!==null&&"id"in e&&typeof e.id=="string"}function y(e){return"method"in e&&typeof e.method=="string"&&"params"in e&&"env"in e&&typeof e.env=="object"&&e.env!==null&&"sdkVersion"in e.env}function M(e){return"success"in e&&typeof e.success=="boolean"&&"version"in e&&typeof e.version=="string"}function A(e){return!!(e&&typeof e=="object")}const g="_";function N(e){const t=typeof e.baseUrl=="string"?e.baseUrl:"https://swap.cow.fi",i=v(e);return t+"/#"+i+"?"+C(e)}function v(e){const{chainId:t=1,sell:i,buy:n,tradeType:o=T.SWAP}=e,s=[i?.asset||g,n?.asset||g].map(encodeURIComponent).join("/");return`/${t}/widget/${o}/${s}`}function C(e){const t=new URLSearchParams;return V(H(U(t,e),e),e)}function U(e,t){const{sell:i,buy:n}=t;return i?.amount&&e.append("sellAmount",i.amount),n?.amount&&e.append("buyAmount",n.amount),e}function H(e,t){const i=t.theme;return i?(A(i)?(e.append("palette",encodeURIComponent(JSON.stringify(i))),e.append("theme",i.baseTheme)):(e.append("palette","null"),e.append("theme",i)),e):(e.append("palette","null"),e)}function V(e,t){return t.targetChainId&&e.append("targetChainId",t.targetChainId.toString()),e}const S="640px",F="450px",k=20,j={updateParams:()=>{},updateListeners:()=>{},updateProvider:()=>{},destroy:()=>{}};function G(e,t){const{params:i,provider:n,listeners:o}=t;let s=n,l=i;if(typeof window>"u")return j;const a=x(i);e.innerHTML="",e.appendChild(a);const{contentWindow:u}=a;if(!u)throw console.error("Iframe does not contain a window",a),new Error("Iframe does not contain a window!");const w=[];w.push(Q(u,i.appCode)),w.push(...B(a,i.height,i.maxHeight)),w.push($());const P=new R(window,o);let h=m(u,null,s);a.addEventListener("load",()=>_(u,l,s));const L=new D(window,u);return{updateParams:d=>{l=d,_(u,l,s)},updateListeners:d=>P.updateListeners(d),updateProvider:d=>{s=d,h=m(u,h,d)},destroy:()=>{h.disconnect(),P.stopListeningIframe(),w.forEach(d=>window.removeEventListener("message",d)),L.stopListening(),e.removeChild(a)}}}function m(e,t,i){t&&t.disconnect();const n=t||new I.IframeRpcProviderBridge(e);return i&&n.onConnect(i),n}function x(e){const{width:t=F,height:i=S}=e,n=document.createElement("iframe");return n.src=N(e),n.width=t,n.height=i,n.style.border="0",n.allow="clipboard-read; clipboard-write",n}function _(e,t,i){const n=!!i,o=v(t),s=C(t).toString(),{theme:l,...a}=t;r.postMessageToWindow(e,E.UPDATE_PARAMS,{urlParams:{pathname:o,search:s},appParams:a,hasProvider:n})}function Q(e,t){return r.listenToMessageFromWindow(window,c.ACTIVATE,()=>{r.postMessageToWindow(e,E.UPDATE_APP_DATA,{metaData:t?{appCode:t}:void 0})})}function $(){return r.listenToMessageFromWindow(window,c.INTERCEPT_WINDOW_OPEN,({href:e,rel:t,target:i})=>{const n=e.toString();if(!n.startsWith("http")&&n.match(/^[a-zA-Z0-9]+:\/\//)){window.open(n,i,t);return}})}function B(e,t=S,i){return[r.listenToMessageFromWindow(window,c.UPDATE_HEIGHT,n=>{const o=n.height?n.height+k:void 0;e.style.height=o?`${i?Math.min(o,i):o}px`:t}),r.listenToMessageFromWindow(window,c.SET_FULL_HEIGHT,({isUpToSmall:n})=>{e.style.height=n?t:`${i||document.body.offsetHeight}px`})]}const Y=Object.values(T);function z(e,t,i){if(p(e)){const n=e[i];return f(n)?n[t]:n}if(f(e)){const n=e[t];return p(n)?n[i]:n}return e}function p(e){return typeof e!="object"?!1:Object.keys(e).every(t=>Y.includes(t))}const J=/^\d+$/;function f(e){return typeof e!="object"?!1:Object.keys(e).every(t=>J.test(t))}function K(e){return p(e)?Object.values(e).flatMap(t=>f(t)?Object.values(t):[t]):f(e)?Object.values(e).flatMap(t=>p(t)?Object.values(t):[t]):[e]}exports.TradeType=T;exports.WIDGET_PALETTE_COLORS=O;exports.WidgetMethodsEmit=c;exports.WidgetMethodsListen=E;exports.createCowSwapWidget=G;exports.isCowSwapWidgetPalette=A;exports.isPerNetworkConfig=f;exports.isPerTradeTypeConfig=p;exports.resolveFlexibleConfig=z;exports.resolveFlexibleConfigValues=K;exports.widgetIframeTransport=r;
package/index.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ export { createCowSwapWidget } from './cowSwapWidget';
2
+ export { widgetIframeTransport } from './widgetIframeTransport';
3
+ export type { CowSwapWidgetHandler } from './cowSwapWidget';
4
+ export { resolveFlexibleConfigValues } from './resolveFlexibleConfigValues';
5
+ export * from './types';
6
+ export * from './themeUtils';
7
+ export * from './flexibleConfig';
package/index.js ADDED
@@ -0,0 +1,217 @@
1
+ import { IframeTransport as C, IframeRpcProviderBridge as L } from "@cowprotocol/iframe-transport";
2
+ import { SimpleCowEventEmitter as R } from "@cowprotocol/events";
3
+ var u = /* @__PURE__ */ ((e) => (e.ACTIVATE = "ACTIVATE", e.UPDATE_HEIGHT = "UPDATE_HEIGHT", e.SET_FULL_HEIGHT = "SET_FULL_HEIGHT", e.EMIT_COW_EVENT = "EMIT_COW_EVENT", e.PROVIDER_RPC_REQUEST = "PROVIDER_RPC_REQUEST", e.INTERCEPT_WINDOW_OPEN = "INTERCEPT_WINDOW_OPEN", e))(u || {}), T = /* @__PURE__ */ ((e) => (e.UPDATE_PARAMS = "UPDATE_PARAMS", e.UPDATE_APP_DATA = "UPDATE_APP_DATA", e.PROVIDER_RPC_RESPONSE = "PROVIDER_RPC_RESPONSE", e.PROVIDER_ON_EVENT = "PROVIDER_ON_EVENT", e))(T || {}), h = /* @__PURE__ */ ((e) => (e.SWAP = "swap", e.LIMIT = "limit", e.ADVANCED = "advanced", e.YIELD = "yield", e))(h || {});
4
+ const K = ["primary", "background", "paper", "text", "danger", "warning", "alert", "info", "success"], d = new C("cowSwapWidget");
5
+ class D {
6
+ constructor(t, i = []) {
7
+ this.contentWindow = t, this.updateListeners(i), this.widgetListener = d.listenToMessageFromWindow(this.contentWindow, u.EMIT_COW_EVENT, (n) => this.eventEmitter.emit(n.event, n.payload));
8
+ }
9
+ eventEmitter = new R();
10
+ listeners = [];
11
+ widgetListener;
12
+ stopListeningIframe() {
13
+ d.stopListeningWindowListener(this.contentWindow, this.widgetListener);
14
+ }
15
+ updateListeners(t) {
16
+ for (const i of this.listeners)
17
+ this.eventEmitter.off(i);
18
+ this.listeners = t || [];
19
+ for (const i of this.listeners)
20
+ this.eventEmitter.on(i);
21
+ }
22
+ }
23
+ class O {
24
+ constructor(t, i) {
25
+ this.appWindow = t, this.iframeWidow = i, this.forwardSdkMessage = (n) => {
26
+ W(n.data) && (typeof window < "u" && n.origin === window.location.origin || (b(n.data) ? this.appWindow.parent.postMessage(n.data, "*") : y(n.data) && this.iframeWidow.postMessage(n.data, "*")));
27
+ }, this.startListening();
28
+ }
29
+ forwardSdkMessage;
30
+ startListening() {
31
+ this.appWindow.addEventListener("message", this.forwardSdkMessage);
32
+ }
33
+ stopListening() {
34
+ this.appWindow.removeEventListener("message", this.forwardSdkMessage);
35
+ }
36
+ }
37
+ function W(e) {
38
+ return typeof e == "object" && e !== null && "id" in e && typeof e.id == "string";
39
+ }
40
+ function b(e) {
41
+ return "method" in e && typeof e.method == "string" && "params" in e && "env" in e && typeof e.env == "object" && e.env !== null && "sdkVersion" in e.env;
42
+ }
43
+ function y(e) {
44
+ return "success" in e && typeof e.success == "boolean" && "version" in e && typeof e.version == "string";
45
+ }
46
+ function U(e) {
47
+ return !!(e && typeof e == "object");
48
+ }
49
+ const m = "_";
50
+ function H(e) {
51
+ const t = typeof e.baseUrl == "string" ? e.baseUrl : "https://swap.cow.fi", i = A(e);
52
+ return t + "/#" + i + "?" + g(e);
53
+ }
54
+ function A(e) {
55
+ const {
56
+ chainId: t = 1,
57
+ sell: i,
58
+ buy: n,
59
+ tradeType: o = h.SWAP
60
+ } = e, r = [i?.asset || m, n?.asset || m].map(encodeURIComponent).join("/");
61
+ return `/${t}/widget/${o}/${r}`;
62
+ }
63
+ function g(e) {
64
+ const t = new URLSearchParams();
65
+ return V(M(N(t, e), e), e);
66
+ }
67
+ function N(e, t) {
68
+ const {
69
+ sell: i,
70
+ buy: n
71
+ } = t;
72
+ return i?.amount && e.append("sellAmount", i.amount), n?.amount && e.append("buyAmount", n.amount), e;
73
+ }
74
+ function M(e, t) {
75
+ const i = t.theme;
76
+ return i ? (U(i) ? (e.append("palette", encodeURIComponent(JSON.stringify(i))), e.append("theme", i.baseTheme)) : (e.append("palette", "null"), e.append("theme", i)), e) : (e.append("palette", "null"), e);
77
+ }
78
+ function V(e, t) {
79
+ return t.targetChainId && e.append("targetChainId", t.targetChainId.toString()), e;
80
+ }
81
+ const v = "640px", F = "450px", k = 20, j = {
82
+ updateParams: () => {
83
+ },
84
+ updateListeners: () => {
85
+ },
86
+ updateProvider: () => {
87
+ },
88
+ destroy: () => {
89
+ }
90
+ };
91
+ function X(e, t) {
92
+ const {
93
+ params: i,
94
+ provider: n,
95
+ listeners: o
96
+ } = t;
97
+ let r = n, p = i;
98
+ if (typeof window > "u") return j;
99
+ const s = G(i);
100
+ e.innerHTML = "", e.appendChild(s);
101
+ const {
102
+ contentWindow: c
103
+ } = s;
104
+ if (!c)
105
+ throw console.error("Iframe does not contain a window", s), new Error("Iframe does not contain a window!");
106
+ const f = [];
107
+ f.push(x(c, i.appCode)), f.push(...$(s, i.height, i.maxHeight)), f.push(Q());
108
+ const P = new D(window, o);
109
+ let w = _(c, null, r);
110
+ s.addEventListener("load", () => I(c, p, r));
111
+ const S = new O(window, c);
112
+ return {
113
+ updateParams: (a) => {
114
+ p = a, I(c, p, r);
115
+ },
116
+ updateListeners: (a) => P.updateListeners(a),
117
+ updateProvider: (a) => {
118
+ r = a, w = _(c, w, a);
119
+ },
120
+ destroy: () => {
121
+ w.disconnect(), P.stopListeningIframe(), f.forEach((a) => window.removeEventListener("message", a)), S.stopListening(), e.removeChild(s);
122
+ }
123
+ };
124
+ }
125
+ function _(e, t, i) {
126
+ t && t.disconnect();
127
+ const n = t || new L(e);
128
+ return i && n.onConnect(i), n;
129
+ }
130
+ function G(e) {
131
+ const {
132
+ width: t = F,
133
+ height: i = v
134
+ } = e, n = document.createElement("iframe");
135
+ return n.src = H(e), n.width = t, n.height = i, n.style.border = "0", n.allow = "clipboard-read; clipboard-write", n;
136
+ }
137
+ function I(e, t, i) {
138
+ const n = !!i, o = A(t), r = g(t).toString(), {
139
+ theme: p,
140
+ ...s
141
+ } = t;
142
+ d.postMessageToWindow(e, T.UPDATE_PARAMS, {
143
+ urlParams: {
144
+ pathname: o,
145
+ search: r
146
+ },
147
+ appParams: s,
148
+ hasProvider: n
149
+ });
150
+ }
151
+ function x(e, t) {
152
+ return d.listenToMessageFromWindow(window, u.ACTIVATE, () => {
153
+ d.postMessageToWindow(e, T.UPDATE_APP_DATA, {
154
+ metaData: t ? {
155
+ appCode: t
156
+ } : void 0
157
+ });
158
+ });
159
+ }
160
+ function Q() {
161
+ return d.listenToMessageFromWindow(window, u.INTERCEPT_WINDOW_OPEN, ({
162
+ href: e,
163
+ rel: t,
164
+ target: i
165
+ }) => {
166
+ const n = e.toString();
167
+ if (!n.startsWith("http") && n.match(/^[a-zA-Z0-9]+:\/\//)) {
168
+ window.open(n, i, t);
169
+ return;
170
+ }
171
+ });
172
+ }
173
+ function $(e, t = v, i) {
174
+ return [d.listenToMessageFromWindow(window, u.UPDATE_HEIGHT, (n) => {
175
+ const o = n.height ? n.height + k : void 0;
176
+ e.style.height = o ? `${i ? Math.min(o, i) : o}px` : t;
177
+ }), d.listenToMessageFromWindow(window, u.SET_FULL_HEIGHT, ({
178
+ isUpToSmall: n
179
+ }) => {
180
+ e.style.height = n ? t : `${i || document.body.offsetHeight}px`;
181
+ })];
182
+ }
183
+ const B = Object.values(h);
184
+ function Z(e, t, i) {
185
+ if (l(e)) {
186
+ const n = e[i];
187
+ return E(n) ? n[t] : n;
188
+ }
189
+ if (E(e)) {
190
+ const n = e[t];
191
+ return l(n) ? n[i] : n;
192
+ }
193
+ return e;
194
+ }
195
+ function l(e) {
196
+ return typeof e != "object" ? !1 : Object.keys(e).every((t) => B.includes(t));
197
+ }
198
+ const Y = /^\d+$/;
199
+ function E(e) {
200
+ return typeof e != "object" ? !1 : Object.keys(e).every((t) => Y.test(t));
201
+ }
202
+ function q(e) {
203
+ return l(e) ? Object.values(e).flatMap((t) => E(t) ? Object.values(t) : [t]) : E(e) ? Object.values(e).flatMap((t) => l(t) ? Object.values(t) : [t]) : [e];
204
+ }
205
+ export {
206
+ h as TradeType,
207
+ K as WIDGET_PALETTE_COLORS,
208
+ u as WidgetMethodsEmit,
209
+ T as WidgetMethodsListen,
210
+ X as createCowSwapWidget,
211
+ U as isCowSwapWidgetPalette,
212
+ E as isPerNetworkConfig,
213
+ l as isPerTradeTypeConfig,
214
+ Z as resolveFlexibleConfig,
215
+ q as resolveFlexibleConfigValues,
216
+ d as widgetIframeTransport
217
+ };
package/package.json CHANGED
@@ -1,17 +1,29 @@
1
1
  {
2
2
  "name": "@cowprotocol/widget-lib",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "description": "CoW Swap Widget Library. Allows you to easily embed a CoW Swap widget on your website.",
5
- "type": "commonjs",
6
- "main": "./src/index.ts",
7
- "types": "./src/index.d.ts",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/cowprotocol/cowswap.git",
8
+ "directory": "libs/widget-lib"
9
+ },
10
+ "type": "module",
11
+ "main": "./index.js",
12
+ "types": "./index.d.ts",
8
13
  "license": "ISC",
9
14
  "publishConfig": {
10
15
  "access": "public"
11
16
  },
12
17
  "dependencies": {
13
- "@cowprotocol/cow-sdk": "8.0.0",
14
- "@cowprotocol/events": "4.0.0",
15
- "@cowprotocol/iframe-transport": "2.0.8"
18
+ "@cowprotocol/cow-sdk": "8.0.3",
19
+ "@cowprotocol/events": "^4.0.2",
20
+ "@cowprotocol/iframe-transport": "^2.0.10"
21
+ },
22
+ "exports": {
23
+ ".": {
24
+ "types": "./index.d.ts",
25
+ "import": "./index.js",
26
+ "require": "./index.cjs"
27
+ }
16
28
  }
17
29
  }
@@ -0,0 +1,2 @@
1
+ import { FlexibleConfig } from './types';
2
+ export declare function resolveFlexibleConfigValues<T>(config: FlexibleConfig<T>): T[];
@@ -0,0 +1,2 @@
1
+ import { CowSwapTheme, CowSwapWidgetPalette } from './types';
2
+ export declare function isCowSwapWidgetPalette(palette: CowSwapTheme | CowSwapWidgetPalette | undefined): palette is CowSwapWidgetPalette;