@bringweb3/chrome-extension-kit 1.0.0 → 1.0.1

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bringweb3/chrome-extension-kit",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.mjs",
6
6
  "types": "dist/index.d.ts",
@@ -16,6 +16,10 @@
16
16
  "test": "vitest --coverage",
17
17
  "release": "yarn build & changeset publish"
18
18
  },
19
+ "files": [
20
+ "dist",
21
+ "README.md"
22
+ ],
19
23
  "devDependencies": {
20
24
  "@changesets/cli": "^2.27.7",
21
25
  "@types/chrome": "^0.0.268",
@@ -1,8 +0,0 @@
1
- # Changesets
2
-
3
- Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
4
- with multi-package repos, or single-package repos to help you version and publish your code. You can
5
- find the full documentation for it [in our repository](https://github.com/changesets/changesets)
6
-
7
- We have a quick list of common questions to get you started engaging with this project in
8
- [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
@@ -1,11 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/@changesets/config@3.0.2/schema.json",
3
- "changelog": "@changesets/cli/changelog",
4
- "commit": false,
5
- "fixed": [],
6
- "linked": [],
7
- "access": "restricted",
8
- "baseBranch": "main",
9
- "updateInternalDependencies": "patch",
10
- "ignore": []
11
- }
package/CHANGELOG.md DELETED
@@ -1,7 +0,0 @@
1
- # @bringweb3/chrome-extension-kit
2
-
3
- ## 1.0.0
4
-
5
- ### Major Changes
6
-
7
- - fb4c76e: Initial release of @bringweb3/chrome-extension-kit - Chrome Extension Kit from Bringweb3
@@ -1,301 +0,0 @@
1
- import fetchDomains from "./utils/api/fetchDomains.js"
2
- import validateDomain from "./utils/api/validateDomain.js"
3
- import checkEvents from "./utils/api/checkEvents.js"
4
- import { ApiEndpoint } from "./utils/apiEndpoint.js"
5
-
6
- import { UPDATE_CACHE_ALARM_NAME } from './utils/constants.js'
7
- import storage from "./utils/storage.js"
8
-
9
- const quietTime = 30 * 60 * 1000
10
-
11
- const getWalletAddress = async (tabId?: number): Promise<WalletAddress> => {
12
- let walletAddress: WalletAddress = await storage.get('walletAddress')
13
-
14
- try {
15
- if (!tabId) {
16
- const tabs = await chrome.tabs.query({ active: true, currentWindow: true })
17
- if (!tabs || !tabs[0] || !tabs[0].id) return walletAddress;
18
- tabId = tabs[0].id
19
- }
20
-
21
- const res = await sendMessage(tabId, { action: 'GET_WALLET_ADDRESS' });
22
-
23
- if (res?.walletAddress && walletAddress !== res?.walletAddress) {
24
- walletAddress = res?.walletAddress
25
- await storage.set('walletAddress', walletAddress as string)
26
- }
27
- } catch (error) {
28
- // console.log("Can't update wallet address");
29
- }
30
-
31
- return walletAddress
32
- }
33
-
34
- const calcDelay = (timestamp: number) => {
35
- const now = Date.now()
36
- return (timestamp - now) / 1000 / 60 // milliseconds to minutes
37
- }
38
-
39
- const updateCache = async (apiKey: string) => {
40
- const res = await fetchDomains(apiKey)
41
-
42
- storage.set('relevantDomains', res.relevantDomains)
43
-
44
- const { nextUpdateTimestamp } = res
45
-
46
- const delay = calcDelay(nextUpdateTimestamp)
47
-
48
- chrome.alarms.create(UPDATE_CACHE_ALARM_NAME, {
49
- delayInMinutes: delay
50
- })
51
- }
52
-
53
- const checkNotifications = async (apiKey: string, tabId: number, cashbackUrl: string | undefined, isAfterActivation?: boolean) => {
54
- const falseReturn = { showNotification: false, token: '' };
55
-
56
- const nextNotificationCheck = await storage.get('notificationCheck');
57
-
58
- if (nextNotificationCheck?.check && Date.now() < nextNotificationCheck.check) return falseReturn;
59
-
60
- const walletAddress = await getWalletAddress(tabId)
61
-
62
- if (!walletAddress) return falseReturn;
63
-
64
- const res = await checkEvents({ apiKey, walletAddress, cashbackUrl });
65
- const notifications = {
66
- check: isAfterActivation ? res.nextRequestTimestampActivated : res.nextRequestTimestampRegular,
67
- nextRequestTimestampActivated: res.nextRequestTimestampActivated,
68
- nextRequestTimestampRegular: res.nextRequestTimestampRegular
69
- }
70
- storage.set('notificationCheck', notifications);
71
-
72
- return {
73
- showNotification: res.showNotification as boolean,
74
- token: res.token as string
75
- };
76
- }
77
-
78
- const getDomain = (url: string) => {
79
- return url.replace(/^(https?:\/\/)?(www\.)?/, '');
80
- }
81
-
82
- const getRelevantDomain = async (url: string | undefined) => {
83
- const relevantDomains = await storage.get('relevantDomains')
84
- if (!url || !relevantDomains || !relevantDomains.length) return ''
85
- const domain = getDomain(url)
86
- for (const relevantDomain of relevantDomains) {
87
- if (domain.startsWith(relevantDomain)) {
88
-
89
- const quietDomains = await storage.get('quietDomains')
90
- if (quietDomains && quietDomains[relevantDomain] && Date.now() < quietDomains[relevantDomain]) {
91
- return ''
92
- }
93
- return relevantDomain
94
- }
95
- }
96
- return ''
97
- }
98
-
99
- const addQuietDomain = async (domain: string, time?: number) => {
100
- if (!time) time = quietTime
101
-
102
- let quietDomains = await storage.get('quietDomains')
103
-
104
- if (typeof quietDomains === 'object') {
105
- quietDomains[domain] = Date.now() + time
106
- } else {
107
- quietDomains = { [domain]: Date.now() + quietTime }
108
- }
109
- storage.set('quietDomains', quietDomains)
110
- }
111
-
112
- const getCashbackUrl = (cashbackUrl: string | undefined): string | undefined => {
113
- return cashbackUrl ? chrome.runtime.getURL(cashbackUrl) : undefined;
114
- }
115
-
116
- interface Message {
117
- action: 'INJECT' | 'GET_WALLET_ADDRESS'
118
- domain?: string
119
- token?: string
120
- page?: string
121
- }
122
-
123
- const sendMessage = async (tabId: number, message: Message) => {
124
- const maxRetries = 5;
125
- const baseDelay = 1000; // 1 second
126
-
127
- for (let attempt = 0; attempt < maxRetries; attempt++) {
128
- try {
129
- // Check if tab still exists
130
- const tabInfo = await chrome.tabs.get(tabId);
131
- if (chrome.runtime.lastError) {
132
- // console.warn("Tab no longer exists:", chrome.runtime.lastError);
133
- return;
134
- }
135
-
136
- const res = await chrome.tabs.sendMessage(tabId, message);
137
- // console.log("Message sent successfully");
138
- return res;
139
- } catch (error) {
140
- // console.warn(`Attempt ${attempt + 1} failed:`, error);
141
- if (attempt < maxRetries - 1) {
142
- await new Promise(resolve => setTimeout(resolve, baseDelay * Math.pow(2, attempt)));
143
- }
144
- }
145
- }
146
- }
147
-
148
- const showNotification = async (identifier: string, tabId: number, cashbackPagePath: string | undefined): Promise<void> => {
149
- const notification = await checkNotifications(identifier, tabId, getCashbackUrl(cashbackPagePath))
150
-
151
- if (!notification.showNotification) return;
152
- await sendMessage(tabId, {
153
- action: 'INJECT',
154
- token: notification.token,
155
- page: 'notification',
156
- })
157
- }
158
-
159
- interface UrlDict {
160
- [key: string]: string
161
- }
162
-
163
- const urlsDict: UrlDict = {}
164
-
165
- interface Configuration {
166
- identifier: string
167
- apiEndpoint: string
168
- cashbackPagePath?: string
169
- }
170
- /**
171
- * Initializes the background script for the Bring extension.
172
- *
173
- * @async
174
- * @function bringInitBackground
175
- * @param {Object} configuration - The configuration object.
176
- * @param {string} configuration.identifier - The identifier for the extension.
177
- * @param {string} configuration.apiEndpoint - The API endpoint ('prod' or 'sandbox').
178
- * @param {string} [configuration.cashbackPagePath] - Optional path to the cashback page.
179
- * @throws {Error} Throws an error if identifier or apiEndpoint is missing, or if apiEndpoint is invalid.
180
- * @returns {Promise<void>}
181
- *
182
- * @description
183
- * This function sets up the background processes for the Bring extension. It initializes
184
- * the API endpoint, sets up listeners for alarms, runtime messages, and tab updates.
185
- * It handles various actions such as opting out, closing notifications, injecting content
186
- * based on URL changes, and managing quiet domains.
187
- *
188
- * The function performs the following tasks:
189
- * - Validates and sets the API endpoint
190
- * - Updates the cache
191
- * - Sets up listeners for alarms to update cache periodically
192
- * - Handles runtime messages for opting out and closing notifications
193
- * - Monitors tab updates to inject content or show notifications based on URL changes
194
- * - Validates domains and manages quiet domains
195
- *
196
- * @example
197
- * bringInitBackground({
198
- * identifier: 'my-extension-id',
199
- * apiEndpoint: 'sandbox',
200
- * cashbackPagePath: '/cashback.html'
201
- * });
202
- */
203
- const bringInitBackground = async ({ identifier, apiEndpoint, cashbackPagePath }: Configuration) => {
204
- if (!identifier || !apiEndpoint) throw new Error('Missing configuration')
205
- if (!['prod', 'sandbox'].includes(apiEndpoint)) throw new Error('unknown apiEndpoint')
206
-
207
- ApiEndpoint.getInstance().setApiEndpoint(apiEndpoint)
208
-
209
-
210
- updateCache(identifier)
211
-
212
- chrome.alarms.onAlarm.addListener(async (alarm) => {
213
- const { name } = alarm
214
-
215
- switch (name) {
216
- case UPDATE_CACHE_ALARM_NAME:
217
- updateCache(identifier)
218
- break;
219
- default:
220
- console.error('alarm with no use case:', name);
221
- break;
222
- }
223
- })
224
-
225
- chrome.runtime.onMessage.addListener(async (request, sender) => {
226
- const { action, time } = request
227
-
228
- switch (action) {
229
- case 'ACTIVATE':
230
- const notificationCheck = await storage.get('notificationCheck')
231
- if (!notificationCheck.check || !notificationCheck.nextRequestTimestampActivated) break;
232
- notificationCheck.check = notificationCheck.nextRequestTimestampActivated;
233
- storage.set('notificationCheck', notificationCheck)
234
- break;
235
- case 'OPT_OUT':
236
- storage.set('optOut', Date.now() + time)
237
- break;
238
- case 'CLOSE':
239
- const domain = await getRelevantDomain(sender.tab?.url || sender.origin)
240
- if (!domain) break;
241
- addQuietDomain(domain, time)
242
- break;
243
- default:
244
- console.warn(`Bring unknown action: ${action}`);
245
- break;
246
- }
247
- })
248
-
249
- chrome.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => {
250
- const optOut = await storage.get('optOut');
251
-
252
- if (optOut && optOut > Date.now()) {
253
- await showNotification(identifier, tabId, cashbackPagePath);
254
- return;
255
- }
256
-
257
- if (!tab.url) return;
258
-
259
- const urlObj = new URL(tab.url)
260
- const url = `${urlObj.hostname.replace('www.', '')}${urlObj.pathname}`
261
-
262
- const previousUrl = urlsDict[tabId];
263
-
264
- if (changeInfo.status !== 'complete' || url === previousUrl) return;
265
-
266
- urlsDict[tabId] = url
267
-
268
- const match = await getRelevantDomain(tab.url);
269
-
270
- if (!match || !match.length) {
271
- await showNotification(identifier, tabId, cashbackPagePath)
272
- return;
273
- };
274
-
275
- const address = await getWalletAddress(tabId);
276
-
277
- const { token, isValid } = await validateDomain({
278
- apiKey: identifier,
279
- query: {
280
- domain: match,
281
- url: tab.url,
282
- address
283
- }
284
- });
285
-
286
- if (!isValid) {
287
- addQuietDomain(match);
288
- return;
289
- }
290
-
291
- sendMessage(tabId, {
292
- action: 'INJECT',
293
- token,
294
- domain: url
295
- });
296
- })
297
-
298
- chrome.tabs.onRemoved.addListener(tabId => delete urlsDict[tabId])
299
- }
300
-
301
- export default bringInitBackground
@@ -1,101 +0,0 @@
1
- import injectIFrame from "./utils/contentScript/injectIFrame.js";
2
- import handleIframeMessages from "./utils/contentScript/handleIframeMessages.js";
3
- import startListenersForWalletAddress from "./utils/contentScript/startLIstenersForWalletAddress.js";
4
-
5
- let iframeEl: IFrame = null
6
- let isIframeOpen = false
7
-
8
- interface Configuration {
9
- iframeEndpoint: string
10
- getWalletAddress: () => Promise<WalletAddress>
11
- promptLogin: () => Promise<WalletAddress>
12
- walletAddressListeners: string[]
13
- customTheme?: Style
14
- }
15
-
16
- /**
17
- * Initializes the content script for the Bring extension.
18
- *
19
- * @async
20
- * @function bringInitContentScript
21
- * @param {Object} configuration - The configuration object.
22
- * @param {Function} configuration.getWalletAddress - A function that returns a Promise resolving to the wallet address.
23
- * @param {Function} configuration.promptLogin - A function to prompt the user to login.
24
- * @param {string[]} configuration.walletAddressListeners - An array of strings representing wallet address listeners.
25
- * @param {Object} [configuration.customTheme] - Optional custom theme settings.
26
- * @param {string} configuration.iframeEndpoint - The endpoint URL for the iframe.
27
- * @throws {Error} Throws an error if any required configuration is missing.
28
- * @returns {Promise<void>}
29
- *
30
- * @description
31
- * This function sets up event listeners for wallet address changes, iframe messages,
32
- * and Chrome runtime messages. It handles actions such as getting the wallet address
33
- * and injecting iframes based on received messages.
34
- *
35
- * @example
36
- * bringInitContentScript({
37
- * getWalletAddress: async () => '0x1234...',
38
- * promptLogin: () => { ... },
39
- * walletAddressListeners: ["listener1", "listener2"],
40
- * iframeEndpoint: 'https://example.com/iframe'
41
- * });
42
- */
43
- const bringInitContentScript = async ({
44
- getWalletAddress,
45
- promptLogin,
46
- walletAddressListeners,
47
- customTheme,
48
- iframeEndpoint
49
- }: Configuration) => {
50
- if (!getWalletAddress || !promptLogin || !walletAddressListeners?.length || !iframeEndpoint) throw new Error('Missing configuration')
51
-
52
- startListenersForWalletAddress({
53
- walletAddressListeners,
54
- getWalletAddress,
55
- iframeEl
56
- })
57
-
58
- window.addEventListener('message', (e) => handleIframeMessages({
59
- event: e,
60
- iframeEl,
61
- promptLogin
62
- }))
63
-
64
- // Listen for message
65
- chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
66
-
67
- const { action } = request
68
-
69
- switch (action) {
70
-
71
- case 'GET_WALLET_ADDRESS':
72
- getWalletAddress()
73
- .then(walletAddress => sendResponse({ status: 'success', walletAddress }))
74
- .catch(err => sendResponse({ status: 'success', walletAddress: undefined }))
75
- return true
76
-
77
- case 'INJECT':
78
- if (isIframeOpen) {
79
- return
80
- }
81
- const { token, page } = request;
82
- // console.log(`injecting to: ${request.domain}`);
83
-
84
- iframeEl = injectIFrame({
85
- query: { token },
86
- iframeSrc: page === 'notification' ?
87
- `${iframeEndpoint}notification` : iframeEndpoint,
88
- theme: customTheme
89
- });
90
- isIframeOpen = true
91
- sendResponse({ status: 'success' });
92
- return true
93
-
94
- default:
95
- console.error(`Unknown action: ${action}`);
96
- break;
97
- }
98
- });
99
- }
100
-
101
- export default bringInitContentScript;
package/config.ts DELETED
@@ -1 +0,0 @@
1
- export const API_URL = 'https://sandbox-api.bringweb3.io/v1/extension'
package/dist/index.d.mts DELETED
@@ -1,77 +0,0 @@
1
- interface Configuration$1 {
2
- iframeEndpoint: string;
3
- getWalletAddress: () => Promise<WalletAddress>;
4
- promptLogin: () => Promise<WalletAddress>;
5
- walletAddressListeners: string[];
6
- customTheme?: Style;
7
- }
8
- /**
9
- * Initializes the content script for the Bring extension.
10
- *
11
- * @async
12
- * @function bringInitContentScript
13
- * @param {Object} configuration - The configuration object.
14
- * @param {Function} configuration.getWalletAddress - A function that returns a Promise resolving to the wallet address.
15
- * @param {Function} configuration.promptLogin - A function to prompt the user to login.
16
- * @param {string[]} configuration.walletAddressListeners - An array of strings representing wallet address listeners.
17
- * @param {Object} [configuration.customTheme] - Optional custom theme settings.
18
- * @param {string} configuration.iframeEndpoint - The endpoint URL for the iframe.
19
- * @throws {Error} Throws an error if any required configuration is missing.
20
- * @returns {Promise<void>}
21
- *
22
- * @description
23
- * This function sets up event listeners for wallet address changes, iframe messages,
24
- * and Chrome runtime messages. It handles actions such as getting the wallet address
25
- * and injecting iframes based on received messages.
26
- *
27
- * @example
28
- * bringInitContentScript({
29
- * getWalletAddress: async () => '0x1234...',
30
- * promptLogin: () => { ... },
31
- * walletAddressListeners: ["listener1", "listener2"],
32
- * iframeEndpoint: 'https://example.com/iframe'
33
- * });
34
- */
35
- declare const bringInitContentScript: ({ getWalletAddress, promptLogin, walletAddressListeners, customTheme, iframeEndpoint }: Configuration$1) => Promise<void>;
36
-
37
- interface Configuration {
38
- identifier: string;
39
- apiEndpoint: string;
40
- cashbackPagePath?: string;
41
- }
42
- /**
43
- * Initializes the background script for the Bring extension.
44
- *
45
- * @async
46
- * @function bringInitBackground
47
- * @param {Object} configuration - The configuration object.
48
- * @param {string} configuration.identifier - The identifier for the extension.
49
- * @param {string} configuration.apiEndpoint - The API endpoint ('prod' or 'sandbox').
50
- * @param {string} [configuration.cashbackPagePath] - Optional path to the cashback page.
51
- * @throws {Error} Throws an error if identifier or apiEndpoint is missing, or if apiEndpoint is invalid.
52
- * @returns {Promise<void>}
53
- *
54
- * @description
55
- * This function sets up the background processes for the Bring extension. It initializes
56
- * the API endpoint, sets up listeners for alarms, runtime messages, and tab updates.
57
- * It handles various actions such as opting out, closing notifications, injecting content
58
- * based on URL changes, and managing quiet domains.
59
- *
60
- * The function performs the following tasks:
61
- * - Validates and sets the API endpoint
62
- * - Updates the cache
63
- * - Sets up listeners for alarms to update cache periodically
64
- * - Handles runtime messages for opting out and closing notifications
65
- * - Monitors tab updates to inject content or show notifications based on URL changes
66
- * - Validates domains and manages quiet domains
67
- *
68
- * @example
69
- * bringInitBackground({
70
- * identifier: 'my-extension-id',
71
- * apiEndpoint: 'sandbox',
72
- * cashbackPagePath: '/cashback.html'
73
- * });
74
- */
75
- declare const bringInitBackground: ({ identifier, apiEndpoint, cashbackPagePath }: Configuration) => Promise<void>;
76
-
77
- export { bringInitBackground, bringInitContentScript };
package/dist/index.d.ts DELETED
@@ -1,77 +0,0 @@
1
- interface Configuration$1 {
2
- iframeEndpoint: string;
3
- getWalletAddress: () => Promise<WalletAddress>;
4
- promptLogin: () => Promise<WalletAddress>;
5
- walletAddressListeners: string[];
6
- customTheme?: Style;
7
- }
8
- /**
9
- * Initializes the content script for the Bring extension.
10
- *
11
- * @async
12
- * @function bringInitContentScript
13
- * @param {Object} configuration - The configuration object.
14
- * @param {Function} configuration.getWalletAddress - A function that returns a Promise resolving to the wallet address.
15
- * @param {Function} configuration.promptLogin - A function to prompt the user to login.
16
- * @param {string[]} configuration.walletAddressListeners - An array of strings representing wallet address listeners.
17
- * @param {Object} [configuration.customTheme] - Optional custom theme settings.
18
- * @param {string} configuration.iframeEndpoint - The endpoint URL for the iframe.
19
- * @throws {Error} Throws an error if any required configuration is missing.
20
- * @returns {Promise<void>}
21
- *
22
- * @description
23
- * This function sets up event listeners for wallet address changes, iframe messages,
24
- * and Chrome runtime messages. It handles actions such as getting the wallet address
25
- * and injecting iframes based on received messages.
26
- *
27
- * @example
28
- * bringInitContentScript({
29
- * getWalletAddress: async () => '0x1234...',
30
- * promptLogin: () => { ... },
31
- * walletAddressListeners: ["listener1", "listener2"],
32
- * iframeEndpoint: 'https://example.com/iframe'
33
- * });
34
- */
35
- declare const bringInitContentScript: ({ getWalletAddress, promptLogin, walletAddressListeners, customTheme, iframeEndpoint }: Configuration$1) => Promise<void>;
36
-
37
- interface Configuration {
38
- identifier: string;
39
- apiEndpoint: string;
40
- cashbackPagePath?: string;
41
- }
42
- /**
43
- * Initializes the background script for the Bring extension.
44
- *
45
- * @async
46
- * @function bringInitBackground
47
- * @param {Object} configuration - The configuration object.
48
- * @param {string} configuration.identifier - The identifier for the extension.
49
- * @param {string} configuration.apiEndpoint - The API endpoint ('prod' or 'sandbox').
50
- * @param {string} [configuration.cashbackPagePath] - Optional path to the cashback page.
51
- * @throws {Error} Throws an error if identifier or apiEndpoint is missing, or if apiEndpoint is invalid.
52
- * @returns {Promise<void>}
53
- *
54
- * @description
55
- * This function sets up the background processes for the Bring extension. It initializes
56
- * the API endpoint, sets up listeners for alarms, runtime messages, and tab updates.
57
- * It handles various actions such as opting out, closing notifications, injecting content
58
- * based on URL changes, and managing quiet domains.
59
- *
60
- * The function performs the following tasks:
61
- * - Validates and sets the API endpoint
62
- * - Updates the cache
63
- * - Sets up listeners for alarms to update cache periodically
64
- * - Handles runtime messages for opting out and closing notifications
65
- * - Monitors tab updates to inject content or show notifications based on URL changes
66
- * - Validates domains and manages quiet domains
67
- *
68
- * @example
69
- * bringInitBackground({
70
- * identifier: 'my-extension-id',
71
- * apiEndpoint: 'sandbox',
72
- * cashbackPagePath: '/cashback.html'
73
- * });
74
- */
75
- declare const bringInitBackground: ({ identifier, apiEndpoint, cashbackPagePath }: Configuration) => Promise<void>;
76
-
77
- export { bringInitBackground, bringInitContentScript };
package/index.ts DELETED
@@ -1,7 +0,0 @@
1
- import bringInitContentScript from "./bringInitContentScript.js"
2
- import bringInitBackground from "./bringInitBackground.js"
3
-
4
- export {
5
- bringInitBackground,
6
- bringInitContentScript
7
- }
@@ -1,23 +0,0 @@
1
- import getQueryParams from '../utils/getQueryParams'
2
- import { describe, it, expect } from 'vitest'
3
-
4
- describe('getQueryParams', () => {
5
- it('return params', () => {
6
-
7
- const query = { param1: 'value1', param2: 'value2' }
8
- const params = getQueryParams({ query })
9
-
10
- expect(params).toEqual('param1=value1&param2=value2')
11
- })
12
- it('return empty string', () => {
13
- const params = getQueryParams({ query: {} })
14
-
15
- expect(params).toEqual('')
16
- })
17
- it('adds prefix', () => {
18
- const query = { param1: 'value1', param2: 'value2' }
19
- const params = getQueryParams({ query, prefix: 't' })
20
-
21
- expect(params).toEqual('t_param1=value1&t_param2=value2')
22
- })
23
- })
package/tsconfig.json DELETED
@@ -1,12 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "module": "commonjs", /* Specify what module code is generated. */
4
- "target": "es2023", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
5
- "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
6
- "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
7
- "strict": true, /* Enable all strict type-checking options. */
8
- "skipLibCheck": true, /* Skip type checking all .d.ts files. */
9
- "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
10
- "noEmit": true, /* Disable emitting files from a compilation. */
11
- }
12
- }
package/types.d.ts DELETED
@@ -1,25 +0,0 @@
1
- type WalletAddress = string | undefined
2
-
3
- type Endpoint = 'sandbox' | 'prod';
4
-
5
- type IFrame = HTMLIFrameElement | null
6
-
7
- interface Style {
8
- [key: string]: string
9
- }
10
-
11
- interface KeyFrame {
12
- name: string
13
- rules: string
14
- }
15
-
16
- interface BringEvent {
17
- data: {
18
- from: string
19
- action: string
20
- style?: Style[]
21
- keyFrames?: KeyFrame[]
22
- extensionId: string
23
- time?: number
24
- }
25
- }
@@ -1,33 +0,0 @@
1
- import { ApiEndpoint } from "../apiEndpoint";
2
-
3
- interface CheckEventsProps {
4
- apiKey: string;
5
- walletAddress: string
6
- cashbackUrl: string | undefined;
7
- }
8
-
9
- interface Body {
10
- walletAddress: string;
11
- cashbackUrl?: string;
12
- test?: boolean
13
- }
14
-
15
- const checkEvents = async ({ apiKey, walletAddress, cashbackUrl }: CheckEventsProps) => {
16
- const endpoint = ApiEndpoint.getInstance().getApiEndpoint()
17
- const body: Body = { walletAddress, test: true }
18
- if (cashbackUrl) body.cashbackUrl = cashbackUrl;
19
-
20
- const res = await fetch(`${endpoint}/check-events`, {
21
- method: 'POST',
22
- headers: {
23
- 'Content-Type': 'application/json',
24
- 'x-api-key': apiKey
25
- },
26
- body: JSON.stringify(body)
27
- })
28
- const json = await res.json()
29
-
30
- return json
31
- }
32
-
33
- export default checkEvents;
@@ -1,16 +0,0 @@
1
- import { ApiEndpoint } from "../apiEndpoint"
2
-
3
- const fetchDomains = async (apiKey: string) => {
4
- const endpoint = ApiEndpoint.getInstance().getApiEndpoint()
5
-
6
- const res = await fetch(`${endpoint}/domains?country=us`, {
7
- headers: {
8
- 'x-api-key': apiKey
9
- }
10
- })
11
- const json = await res.json()
12
- // console.log({ json });
13
- return json
14
- }
15
-
16
- export default fetchDomains
@@ -1,28 +0,0 @@
1
- import { ApiEndpoint } from "../apiEndpoint";
2
- import getQueryParams from "../getQueryParams";
3
-
4
- interface ValidateDomainProps {
5
- apiKey: string,
6
- query: {
7
- url: string,
8
- domain: string,
9
- address: WalletAddress,
10
- country?: string
11
- }
12
- }
13
-
14
- const validateDomain = async ({ apiKey, query }: ValidateDomainProps) => {
15
- const endpoint = ApiEndpoint.getInstance().getApiEndpoint()
16
- const params = getQueryParams({ query: { ...query, country: 'us' } })
17
-
18
- const res = await fetch(`${endpoint}/token?${params.toString()}`, {
19
- headers: {
20
- 'x-api-key': apiKey
21
- }
22
- })
23
- const json = await res.json()
24
- // console.log({ json });
25
- return json
26
- }
27
-
28
- export default validateDomain;
@@ -1,28 +0,0 @@
1
-
2
- export class ApiEndpoint {
3
- private static instance: ApiEndpoint | null = null;
4
- private apiEndpoint: string = '';
5
-
6
- private constructor() {
7
- }
8
-
9
- public static getInstance(): ApiEndpoint {
10
- if (!ApiEndpoint.instance) {
11
- ApiEndpoint.instance = new ApiEndpoint();
12
- }
13
- return ApiEndpoint.instance;
14
- }
15
-
16
- public setApiEndpoint(endpoint: string): void {
17
- this.apiEndpoint = endpoint === 'prod'
18
- ? 'https://api.bringweb3.io/v1/extension'
19
- : 'https://sandbox-api.bringweb3.io/v1/extension';
20
- }
21
-
22
- public getApiEndpoint(): string {
23
- if (!this.apiEndpoint) {
24
- throw new Error('API endpoint not set. Call setApiEndpoint first.');
25
- }
26
- return this.apiEndpoint;
27
- }
28
- }
@@ -1,2 +0,0 @@
1
- export const UPDATE_CACHE_ALARM_NAME = 'updateCache'
2
- export const CHECK_EVENTS_ALARM_NAME = 'checkEvents'
@@ -1,20 +0,0 @@
1
- const addKeyframes = (keyFrames: KeyFrame[] | undefined): void => {
2
-
3
- if (!keyFrames || !keyFrames.length) return
4
-
5
- const style = document.createElement('style');
6
-
7
- document.head.appendChild(style);
8
-
9
- const sheet = style.sheet;
10
-
11
- if (sheet) {
12
- keyFrames.forEach(({ name, rules }) => {
13
- sheet.insertRule(`@keyframes ${name} { ${rules} }`, sheet.cssRules.length);
14
- })
15
- } else {
16
- console.error('Failed to create stylesheet');
17
- }
18
- }
19
-
20
- export default addKeyframes;
@@ -1,11 +0,0 @@
1
- const applyStyles = (element: IFrame, style: Style[] | undefined) => {
2
- if (!element || !style || !Object.keys(style).length) return;
3
-
4
- Object.entries(style).forEach(([key, value]) => {
5
- if (key in element.style) {
6
- (element.style as any)[key] = value;
7
- }
8
- });
9
- }
10
-
11
- export default applyStyles;
@@ -1,56 +0,0 @@
1
- import applyStyles from "./applyStyles"
2
- import addKeyframes from "./addKeyFrames"
3
-
4
- interface Props {
5
- event: BringEvent
6
- iframeEl: IFrame
7
- promptLogin: () => Promise<WalletAddress>
8
- }
9
-
10
- const ACTIONS = {
11
- OPEN: 'OPEN',
12
- CLOSE: 'CLOSE',
13
- ACTIVATE: 'ACTIVATE',
14
- PROMPT_LOGIN: 'PROMPT_LOGIN',
15
- OPT_OUT: 'OPT_OUT',
16
- ADD_KEYFRAMES: 'ADD_KEYFRAMES'
17
- }
18
-
19
- const UNION_ACTIONS = [ACTIONS.ACTIVATE]
20
-
21
- const handleIframeMessages = ({ event, iframeEl, promptLogin }: Props) => {
22
- const { data } = event
23
- const { from, action, style, keyFrames, time, extensionId } = data
24
-
25
- if (from !== 'bringweb3') return
26
-
27
- // If the event comes from another extension that installed our package, ignore it (unless it ACTIVATE action)
28
- if (extensionId !== chrome.runtime.id && !UNION_ACTIONS.includes(action)) return
29
-
30
- switch (action) {
31
- case ACTIONS.OPEN:
32
- applyStyles(iframeEl, style)
33
- break;
34
- case ACTIONS.CLOSE:
35
- if (iframeEl) iframeEl.parentNode?.removeChild(iframeEl)
36
- if (time) chrome.runtime.sendMessage({ action, time })
37
- break;
38
- case ACTIONS.PROMPT_LOGIN:
39
- promptLogin()
40
- break;
41
- case ACTIONS.ACTIVATE:
42
- chrome.runtime.sendMessage({ action })
43
- break;
44
- case ACTIONS.OPT_OUT:
45
- chrome.runtime.sendMessage({ action, time })
46
- break;
47
- case ACTIONS.ADD_KEYFRAMES:
48
- addKeyframes(keyFrames)
49
- break;
50
- default:
51
- // console.log('Non exist ACTION:', action);
52
- break;
53
- }
54
- }
55
-
56
- export default handleIframeMessages;
@@ -1,36 +0,0 @@
1
- import getQueryParams from "../getQueryParams";
2
-
3
- interface Query {
4
- [key: string]: string
5
-
6
- }
7
-
8
- interface Props {
9
- query: Query
10
- theme?: Style
11
- iframeSrc: string
12
- }
13
-
14
- const injectIFrame = ({ query, theme, iframeSrc }: Props): HTMLIFrameElement => {
15
- const extensionId = chrome.runtime.id;
16
- const params = getQueryParams({ query: { ...query, extensionId } })
17
- const customStyles = theme ? `&${getQueryParams({ query: theme, prefix: 't' })}` : ''
18
- const iframe = document.createElement('iframe');
19
- iframe.id = `bringweb3-iframe:${extensionId}`;
20
- iframe.src = `${iframeSrc}?${params}${customStyles}`;
21
- iframe.setAttribute('sandbox', "allow-popups allow-scripts allow-same-origin allow-top-navigation-by-user-activation")
22
- iframe.style.position = "fixed";
23
- iframe.scrolling = "no";
24
- iframe.style.overflow = "hidden";
25
- iframe.style.width = "1px";
26
- iframe.style.height = "1px";
27
- iframe.style.right = "8px";
28
- iframe.style.borderRadius = "10px";
29
- iframe.style.border = "none";
30
- iframe.style.cssText += `z-index: 99999999999999 !important;`;
31
- if (theme?.popupShadow) iframe.style.boxShadow = theme.popupShadow;
32
- document.documentElement.appendChild(iframe);
33
- return iframe
34
- }
35
-
36
- export default injectIFrame;
@@ -1,30 +0,0 @@
1
- interface Props {
2
- walletAddressListeners: string[],
3
- getWalletAddress: () => Promise<WalletAddress>
4
- iframeEl: IFrame
5
- }
6
-
7
- const startListenersForWalletAddress = ({ walletAddressListeners, getWalletAddress, iframeEl }: Props) => {
8
- for (let i = 0; i < walletAddressListeners.length; i++) {
9
- const eventName = walletAddressListeners[i]
10
- if (!eventName) continue
11
- window.addEventListener(eventName, async (e) => {
12
- // console.log('NEW EVENT');
13
- // console.log(e.detail);
14
-
15
-
16
- if (!iframeEl) {
17
- iframeEl = document.querySelector(`#bringweb3-iframe:${chrome.runtime.id}`)
18
- if (!iframeEl) return
19
- }
20
- if (!iframeEl.contentWindow) {
21
- return
22
- }
23
- const address = await getWalletAddress()
24
-
25
- iframeEl.contentWindow.postMessage({ action: 'WALLET_ADDRESS_UPDATE', walletAddress: address }, '*')
26
- });
27
- }
28
- }
29
-
30
- export default startListenersForWalletAddress;
@@ -1,27 +0,0 @@
1
- interface Query {
2
- [key: string]: string | undefined
3
-
4
- }
5
-
6
- interface props {
7
- query: Query
8
- prefix?: string
9
- }
10
-
11
- const getQueryParams = (props: props) => {
12
- const params = new URLSearchParams()
13
- const { query, prefix } = props
14
-
15
- Object.entries(query).forEach(([key, value]) => {
16
- if (!value) return
17
- if (prefix) key = `${prefix}_${key}`
18
- if (key === 'url') {
19
- params.append(key, encodeURIComponent(value))
20
- } else {
21
- params.append(key, value)
22
- }
23
- })
24
- return params.toString()
25
- }
26
-
27
- export default getQueryParams
package/utils/storage.ts DELETED
@@ -1,25 +0,0 @@
1
- const set = async (key: string, value: any) => {
2
- chrome.storage.local.set({ [key]: value });
3
- }
4
-
5
- const get = async (key: string) => {
6
- const data = await chrome.storage.local.get(key)
7
- return data[key]
8
- }
9
-
10
- const remove = async (key: string) => {
11
- chrome.storage.local.remove(key)
12
- }
13
-
14
- // const clear = async () => {
15
- // chrome.storage.local.clear(() => {
16
- // console.log('Cache cleared successfully')
17
- // })
18
- // }
19
-
20
- export default {
21
- set,
22
- get,
23
- remove,
24
- // clear
25
- }