@layerswap/wallet-fuel 1.0.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.
Files changed (81) hide show
  1. package/dist/esm/FuelProvider.js +27 -0
  2. package/dist/esm/connectors/bako-safe/Bako.js +29 -0
  3. package/dist/esm/connectors/bako-safe/BakoSafeConnector.js +268 -0
  4. package/dist/esm/connectors/bako-safe/BakoSafeStorage.js +20 -0
  5. package/dist/esm/connectors/bako-safe/DAPPWindow.js +130 -0
  6. package/dist/esm/connectors/bako-safe/SocketClient.js +74 -0
  7. package/dist/esm/connectors/bako-safe/constants.js +16 -0
  8. package/dist/esm/connectors/bako-safe/index.js +1 -0
  9. package/dist/esm/connectors/bako-safe/request.js +15 -0
  10. package/dist/esm/connectors/bako-safe/types.js +25 -0
  11. package/dist/esm/connectors/fuel-wallet/FuelWalletConnector.js +234 -0
  12. package/dist/esm/connectors/fuel-wallet/constants.js +4 -0
  13. package/dist/esm/connectors/fuel-wallet/index.js +3 -0
  14. package/dist/esm/connectors/fuel-wallet/types.js +9 -0
  15. package/dist/esm/connectors/fuelet-wallet/FueletWalletConnector.js +19 -0
  16. package/dist/esm/connectors/fuelet-wallet/constants.js +2 -0
  17. package/dist/esm/connectors/fuelet-wallet/index.js +1 -0
  18. package/dist/esm/fuelAddressUtilsProvider.js +19 -0
  19. package/dist/esm/fuelBalanceProvider.js +61 -0
  20. package/dist/esm/fuelGasProvider.js +38 -0
  21. package/dist/esm/index.js +13 -0
  22. package/dist/esm/jsons/FUELWATCHDOG.json +96 -0
  23. package/dist/esm/services/transferService/transactionBuilder.js +11 -0
  24. package/dist/esm/useFuelConnection.js +232 -0
  25. package/dist/esm/utils/KnownFuelConnectors.js +24 -0
  26. package/dist/esm/utils/index.js +2 -0
  27. package/dist/esm/utils/resolveIcon.js +9 -0
  28. package/dist/tsconfig.tsbuildinfo +1 -0
  29. package/dist/types/FuelProvider.d.ts +5 -0
  30. package/dist/types/FuelProvider.d.ts.map +1 -0
  31. package/dist/types/connectors/bako-safe/Bako.d.ts +16 -0
  32. package/dist/types/connectors/bako-safe/Bako.d.ts.map +1 -0
  33. package/dist/types/connectors/bako-safe/BakoSafeConnector.d.ts +65 -0
  34. package/dist/types/connectors/bako-safe/BakoSafeConnector.d.ts.map +1 -0
  35. package/dist/types/connectors/bako-safe/BakoSafeStorage.d.ts +11 -0
  36. package/dist/types/connectors/bako-safe/BakoSafeStorage.d.ts.map +1 -0
  37. package/dist/types/connectors/bako-safe/DAPPWindow.d.ts +26 -0
  38. package/dist/types/connectors/bako-safe/DAPPWindow.d.ts.map +1 -0
  39. package/dist/types/connectors/bako-safe/SocketClient.d.ts +17 -0
  40. package/dist/types/connectors/bako-safe/SocketClient.d.ts.map +1 -0
  41. package/dist/types/connectors/bako-safe/constants.d.ts +14 -0
  42. package/dist/types/connectors/bako-safe/constants.d.ts.map +1 -0
  43. package/dist/types/connectors/bako-safe/index.d.ts +2 -0
  44. package/dist/types/connectors/bako-safe/index.d.ts.map +1 -0
  45. package/dist/types/connectors/bako-safe/request.d.ts +7 -0
  46. package/dist/types/connectors/bako-safe/request.d.ts.map +1 -0
  47. package/dist/types/connectors/bako-safe/types.d.ts +55 -0
  48. package/dist/types/connectors/bako-safe/types.d.ts.map +1 -0
  49. package/dist/types/connectors/fuel-wallet/FuelWalletConnector.d.ts +52 -0
  50. package/dist/types/connectors/fuel-wallet/FuelWalletConnector.d.ts.map +1 -0
  51. package/dist/types/connectors/fuel-wallet/constants.d.ts +5 -0
  52. package/dist/types/connectors/fuel-wallet/constants.d.ts.map +1 -0
  53. package/dist/types/connectors/fuel-wallet/index.d.ts +4 -0
  54. package/dist/types/connectors/fuel-wallet/index.d.ts.map +1 -0
  55. package/dist/types/connectors/fuel-wallet/types.d.ts +51 -0
  56. package/dist/types/connectors/fuel-wallet/types.d.ts.map +1 -0
  57. package/dist/types/connectors/fuelet-wallet/FueletWalletConnector.d.ts +8 -0
  58. package/dist/types/connectors/fuelet-wallet/FueletWalletConnector.d.ts.map +1 -0
  59. package/dist/types/connectors/fuelet-wallet/constants.d.ts +3 -0
  60. package/dist/types/connectors/fuelet-wallet/constants.d.ts.map +1 -0
  61. package/dist/types/connectors/fuelet-wallet/index.d.ts +2 -0
  62. package/dist/types/connectors/fuelet-wallet/index.d.ts.map +1 -0
  63. package/dist/types/fuelAddressUtilsProvider.d.ts +6 -0
  64. package/dist/types/fuelAddressUtilsProvider.d.ts.map +1 -0
  65. package/dist/types/fuelBalanceProvider.d.ts +6 -0
  66. package/dist/types/fuelBalanceProvider.d.ts.map +1 -0
  67. package/dist/types/fuelGasProvider.d.ts +6 -0
  68. package/dist/types/fuelGasProvider.d.ts.map +1 -0
  69. package/dist/types/index.d.ts +3 -0
  70. package/dist/types/index.d.ts.map +1 -0
  71. package/dist/types/services/transferService/transactionBuilder.d.ts +7 -0
  72. package/dist/types/services/transferService/transactionBuilder.d.ts.map +1 -0
  73. package/dist/types/useFuelConnection.d.ts +3 -0
  74. package/dist/types/useFuelConnection.d.ts.map +1 -0
  75. package/dist/types/utils/KnownFuelConnectors.d.ts +6 -0
  76. package/dist/types/utils/KnownFuelConnectors.d.ts.map +1 -0
  77. package/dist/types/utils/index.d.ts +3 -0
  78. package/dist/types/utils/index.d.ts.map +1 -0
  79. package/dist/types/utils/resolveIcon.d.ts +6 -0
  80. package/dist/types/utils/resolveIcon.d.ts.map +1 -0
  81. package/package.json +72 -0
@@ -0,0 +1,27 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { BakoRequestAPI } from './connectors/bako-safe/Bako';
3
+ import { BakoSafeConnector } from './connectors/bako-safe';
4
+ import { FuelProvider } from '@fuels/react';
5
+ import { FueletWalletConnector } from './connectors/fuelet-wallet';
6
+ import { FuelWalletConnector } from './connectors/fuel-wallet';
7
+ import { useSettingsState } from '@layerswap/widget/internal';
8
+ import { NetworkType } from '@layerswap/widget/types';
9
+ import { useMemo } from 'react';
10
+ const HOST_URL = 'https://api.bako.global';
11
+ const FuelProviderWrapper = ({ children }) => {
12
+ const { networks } = useSettingsState();
13
+ const fuelConfig = {
14
+ connectors: [
15
+ new FuelWalletConnector(),
16
+ new BakoSafeConnector({
17
+ api: new BakoRequestAPI(HOST_URL)
18
+ }),
19
+ new FueletWalletConnector(),
20
+ ]
21
+ };
22
+ const fuelNetworks = useMemo(() => networks.filter(n => n.type == NetworkType.Fuel).map((network) => ({
23
+ chainId: Number(network.chain_id)
24
+ })), [networks]);
25
+ return (_jsx(FuelProvider, { uiConfig: { suggestBridge: false }, theme: 'dark', fuelConfig: fuelConfig, networks: fuelNetworks, children: children }));
26
+ };
27
+ export default FuelProviderWrapper;
@@ -0,0 +1,29 @@
1
+ import { urlJoin } from "@fuel-ts/account";
2
+ export class BAKO_STATE {
3
+ }
4
+ BAKO_STATE.state = { data: false, req_count: 0 };
5
+ BAKO_STATE.period_durtion = 10000;
6
+ export class BakoRequestAPI {
7
+ constructor(baseUrl) {
8
+ this.baseUrl = baseUrl;
9
+ }
10
+ async get(pathname) {
11
+ if (!pathname.includes('/state')) {
12
+ const data = await fetch(urlJoin(this.baseUrl, pathname)).then((res) => res.json());
13
+ return data;
14
+ }
15
+ const period_elapsed = BAKO_STATE.state?.period_start && new Date().getTime() - BAKO_STATE.state?.period_start?.getTime() > BAKO_STATE.period_durtion;
16
+ const skip = BAKO_STATE.state?.last_req && new Date().getTime() - BAKO_STATE.state?.last_req?.getTime() < 1000 * 60 * 2 && period_elapsed;
17
+ if (skip)
18
+ return BAKO_STATE.state?.data;
19
+ const data = await fetch(urlJoin(this.baseUrl, pathname)).then((res) => res.json());
20
+ const count = BAKO_STATE.state?.req_count || 0;
21
+ BAKO_STATE.state = { last_req: new Date(), data, req_count: count + 1, period_start: period_elapsed ? new Date() : BAKO_STATE.state?.period_start || new Date() };
22
+ return data;
23
+ }
24
+ async delete(pathname) {
25
+ await fetch(urlJoin(this.baseUrl, pathname), {
26
+ method: 'DELETE',
27
+ });
28
+ }
29
+ }
@@ -0,0 +1,268 @@
1
+ import { FuelConnector, FuelConnectorEventTypes, Provider, } from 'fuels';
2
+ import { BakoStorage } from './BakoSafeStorage';
3
+ import { DAppWindow } from './DAPPWindow';
4
+ import { SocketClient } from './SocketClient';
5
+ import { APP_DESCRIPTION, APP_IMAGE_DARK, APP_IMAGE_LIGHT, APP_NAME, APP_NETWORK, APP_URL, APP_VERSION, HAS_WINDOW, HOST_URL, IS_SAFARI, SESSION_ID, WINDOW, } from './constants';
6
+ import { RequestAPI } from './request';
7
+ import { BakoSafeConnectorEvents, } from './types';
8
+ export class BakoSafeConnector extends FuelConnector {
9
+ constructor(config) {
10
+ super();
11
+ this.name = APP_NAME;
12
+ this.metadata = {
13
+ image: {
14
+ light: APP_IMAGE_LIGHT,
15
+ dark: APP_IMAGE_DARK,
16
+ },
17
+ install: {
18
+ action: APP_URL,
19
+ link: APP_URL,
20
+ description: APP_DESCRIPTION,
21
+ },
22
+ };
23
+ this.installed = !IS_SAFARI;
24
+ this.connected = false;
25
+ this.external = false;
26
+ this.host = config?.host ?? HOST_URL;
27
+ this.appUrl = config?.appUrl ?? APP_URL;
28
+ this.api = config?.api ?? new RequestAPI(this.host);
29
+ this.storage = this.getStorage(config?.storage);
30
+ this.setupReady = false;
31
+ }
32
+ // ============================================================
33
+ // Bako Safe application specific methods
34
+ // ============================================================
35
+ getStorage(storage) {
36
+ const _storage = storage ?? WINDOW.localStorage ?? new BakoStorage();
37
+ if (!_storage) {
38
+ throw new Error('No storage provided');
39
+ }
40
+ return _storage;
41
+ }
42
+ async getSessionId() {
43
+ let sessionId = (await this.storage?.getItem(SESSION_ID)) || '';
44
+ if (!sessionId) {
45
+ sessionId = crypto.randomUUID();
46
+ await this.storage?.setItem(SESSION_ID, sessionId);
47
+ }
48
+ return sessionId;
49
+ }
50
+ checkWindow() {
51
+ // timeout to open
52
+ const openInterval = setInterval(() => {
53
+ const isOpen = this.dAppWindow?.isOpen;
54
+ if (!isOpen) {
55
+ this.emit(BakoSafeConnectorEvents.CLIENT_DISCONNECTED, {});
56
+ clearInterval(openInterval);
57
+ }
58
+ }, 2000);
59
+ // timeout to close
60
+ const interval = setInterval(() => {
61
+ const isOpen = this.dAppWindow?.opned?.closed;
62
+ if (isOpen) {
63
+ this.emit(BakoSafeConnectorEvents.CLIENT_DISCONNECTED, {});
64
+ clearInterval(interval);
65
+ }
66
+ }, 300);
67
+ }
68
+ /**
69
+ * [important]
70
+ * this.socket.emit -> emit message to the server
71
+ * this.emit -> emit message to the dApp client
72
+ */
73
+ async setup() {
74
+ if (!HAS_WINDOW)
75
+ return;
76
+ if (this.socket)
77
+ this.socket.checkConnection();
78
+ if (this.setupReady)
79
+ return;
80
+ this.setupReady = true;
81
+ const sessionId = await this.getSessionId();
82
+ this.sessionId = sessionId;
83
+ this.socket = SocketClient.create({
84
+ sessionId,
85
+ events: this,
86
+ });
87
+ this.dAppWindow = new DAppWindow({
88
+ sessionId,
89
+ height: 800,
90
+ width: 450,
91
+ appUrl: this.appUrl,
92
+ request_id: this.socket.request_id,
93
+ });
94
+ await this.requestConnectionState();
95
+ }
96
+ async requestConnectionState() {
97
+ return new Promise((resolve) => {
98
+ if (!this.socket)
99
+ return;
100
+ this.socket.server.emit(BakoSafeConnectorEvents.CONNECTION_STATE);
101
+ this.socket.server.once(BakoSafeConnectorEvents.CONNECTION_STATE, async ({ data }) => {
102
+ this.connected = data;
103
+ this.emit(this.events.connection, data);
104
+ resolve();
105
+ });
106
+ });
107
+ }
108
+ // ============================================================
109
+ // Connector methods
110
+ // ============================================================
111
+ async connect() {
112
+ await this.setup();
113
+ return new Promise((resolve, reject) => {
114
+ if (this.connected) {
115
+ resolve(true);
116
+ return;
117
+ }
118
+ this.dAppWindow?.open('/', reject);
119
+ this.checkWindow();
120
+ this.once(BakoSafeConnectorEvents.CLIENT_DISCONNECTED, () => {
121
+ this.dAppWindow?.close();
122
+ reject(false);
123
+ });
124
+ this.once(BakoSafeConnectorEvents.AUTH_CONFIRMED, async ({ data }) => {
125
+ await this.requestConnectionState();
126
+ this.emit(this.events.accounts, await this.accounts());
127
+ this.emit(this.events.currentAccount, await this.currentAccount());
128
+ this.dAppWindow?.close();
129
+ resolve(data.connected);
130
+ });
131
+ });
132
+ }
133
+ /*
134
+ * @param {string} address - The address to sign the transaction
135
+ * @param {Transaction} transaction - The transaction to send
136
+ *
137
+ * @returns {string} - The transaction id
138
+ */
139
+ async sendTransaction(_address, _transaction) {
140
+ return new Promise((resolve, reject) => {
141
+ this.dAppWindow?.open('/dapp/transaction', reject);
142
+ this.checkWindow();
143
+ const onClientConnected = () => {
144
+ this.socket?.server.emit(BakoSafeConnectorEvents.TX_PENDING, {
145
+ _transaction,
146
+ _address,
147
+ });
148
+ };
149
+ // @ts-ignore
150
+ this.on(BakoSafeConnectorEvents.CLIENT_CONNECTED, onClientConnected);
151
+ this.once(BakoSafeConnectorEvents.CLIENT_DISCONNECTED, () => {
152
+ this.dAppWindow?.close();
153
+ this.removeListener(BakoSafeConnectorEvents.CLIENT_CONNECTED, onClientConnected);
154
+ reject(new Error('Client disconnected'));
155
+ });
156
+ this.once(BakoSafeConnectorEvents.TX_TIMEOUT, () => {
157
+ this.dAppWindow?.close();
158
+ this.removeListener(BakoSafeConnectorEvents.CLIENT_CONNECTED, onClientConnected);
159
+ reject(new Error('Transaction timeout'));
160
+ });
161
+ this.once(BakoSafeConnectorEvents.TX_CONFIRMED, ({ data }) => {
162
+ this.removeListener(BakoSafeConnectorEvents.CLIENT_CONNECTED, onClientConnected);
163
+ resolve(`0x${data.id}`);
164
+ });
165
+ });
166
+ }
167
+ async selectNetwork(_network) {
168
+ return new Promise((resolve, reject) => {
169
+ this.dAppWindow?.open('/dapp/network', reject);
170
+ this.checkWindow();
171
+ const onClientConnected = () => {
172
+ this.socket?.server.emit(BakoSafeConnectorEvents.CHANGE_NETWORK, {
173
+ _network,
174
+ });
175
+ };
176
+ // @ts-ignore
177
+ this.on(BakoSafeConnectorEvents.CLIENT_CONNECTED, onClientConnected);
178
+ this.once(BakoSafeConnectorEvents.CLIENT_DISCONNECTED, () => {
179
+ this.dAppWindow?.close();
180
+ this.removeListener(BakoSafeConnectorEvents.CLIENT_CONNECTED, onClientConnected);
181
+ reject(new Error('Client disconnected'));
182
+ });
183
+ this.once(BakoSafeConnectorEvents.NETWORK_CHANGED, async () => {
184
+ const network = await this.currentNetwork();
185
+ this.emit(this.events.networks, [network]);
186
+ this.emit(this.events.currentNetwork, network);
187
+ this.dAppWindow?.close();
188
+ this.removeListener(BakoSafeConnectorEvents.CLIENT_CONNECTED, onClientConnected);
189
+ resolve(true);
190
+ });
191
+ });
192
+ }
193
+ async ping() {
194
+ if (IS_SAFARI) {
195
+ return false;
196
+ }
197
+ await this.setup();
198
+ return this.setupReady ?? false;
199
+ }
200
+ async version() {
201
+ return {
202
+ app: APP_VERSION,
203
+ network: APP_NETWORK,
204
+ };
205
+ }
206
+ async isConnected() {
207
+ await this.setup();
208
+ return this.connected;
209
+ }
210
+ async accounts() {
211
+ const data = await this.api.get(`/connections/${this.sessionId}/accounts`);
212
+ const acc = Array.isArray(data) ? data : [];
213
+ return acc;
214
+ }
215
+ async currentAccount() {
216
+ const data = await this.api.get(`/connections/${this.sessionId}/currentAccount`);
217
+ const isInvalid = data && JSON.stringify(data) === JSON.stringify({});
218
+ return isInvalid ? null : data;
219
+ }
220
+ async disconnect() {
221
+ await this.api.delete(`/connections/${this.sessionId}`);
222
+ await this.requestConnectionState();
223
+ this.emit(this.events.accounts, []);
224
+ this.emit(this.events.currentAccount, null);
225
+ return false;
226
+ }
227
+ async currentNetwork() {
228
+ const data = await this.api.get(`/connections/${this.sessionId}/currentNetwork`);
229
+ const provider = new Provider(data);
230
+ return {
231
+ url: provider.url,
232
+ chainId: await provider.getChainId(),
233
+ };
234
+ }
235
+ async networks() {
236
+ return [await this.currentNetwork()];
237
+ }
238
+ async assets() {
239
+ return [];
240
+ }
241
+ async signMessage(_address, _message) {
242
+ throw new Error('Method not implemented.');
243
+ }
244
+ async addAssets(_assets) {
245
+ throw new Error('Method not implemented.');
246
+ }
247
+ async addAsset(_assets) {
248
+ throw new Error('Method not implemented.');
249
+ }
250
+ async addNetwork(_networkUrl) {
251
+ throw new Error('Method not implemented.');
252
+ }
253
+ async addABI(_contractId, _abi) {
254
+ throw new Error('Method not implemented.');
255
+ }
256
+ async getABI(_id) {
257
+ throw new Error('Method not implemented.');
258
+ }
259
+ async hasABI(_id) {
260
+ throw new Error('Method not implemented.');
261
+ }
262
+ /**
263
+ * @inheritdoc
264
+ */
265
+ async startConsolidation(opts) {
266
+ this.emit(FuelConnectorEventTypes.consolidateCoins, opts);
267
+ }
268
+ }
@@ -0,0 +1,20 @@
1
+ import { StorageAbstract } from 'fuels';
2
+ export class BakoStorage extends StorageAbstract {
3
+ constructor() {
4
+ super(...arguments);
5
+ this.data = {};
6
+ }
7
+ async getItem(key) {
8
+ return this.data[key];
9
+ }
10
+ async setItem(key, value) {
11
+ this.data[key] = value;
12
+ return;
13
+ }
14
+ async removeItem(key) {
15
+ delete this.data[key];
16
+ }
17
+ async clear() {
18
+ this.data = {};
19
+ }
20
+ }
@@ -0,0 +1,130 @@
1
+ import { WINDOW } from './constants';
2
+ export class DAppWindow {
3
+ constructor(config) {
4
+ this.config = config;
5
+ this.isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
6
+ this.isSafariBrowser = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
7
+ this.isOpen = false;
8
+ this.opned = null;
9
+ this.request_id = config.request_id;
10
+ }
11
+ get popupConfig() {
12
+ const { height, width } = this.config;
13
+ return {
14
+ top: WINDOW.innerHeight / 2 - height / 2,
15
+ left: WINDOW.innerWidth / 2 - width / 2,
16
+ width,
17
+ height: !this.isMobile && WINDOW.innerHeight >= height
18
+ ? height
19
+ : WINDOW.innerHeight,
20
+ };
21
+ }
22
+ open(method, reject) {
23
+ if (this.isOpen)
24
+ reject(new Error('Window is already open'));
25
+ if (!this.isSafariBrowser) {
26
+ // if is not safari, we can use popup for both cases
27
+ this.makePopup(method);
28
+ }
29
+ // if (this.isSafariBrowser && isConnection) {
30
+ // // to use webauthn, we need a new WINDOW
31
+ // this.makeLink(method);
32
+ // }
33
+ if (this.isSafariBrowser) {
34
+ // && !isConnection) {
35
+ // to confirm tx, we need a new popup
36
+ this.makeFrame(method, true);
37
+ }
38
+ return;
39
+ }
40
+ close() {
41
+ const frame = document.getElementById(`${this.config.sessionId}-iframe`);
42
+ const backdrop = document.getElementById(`${this.config.sessionId}-backdrop`);
43
+ if (frame)
44
+ document.body.removeChild(frame);
45
+ if (backdrop)
46
+ document.body.removeChild(backdrop);
47
+ if (this.opned)
48
+ this.opned.close();
49
+ this.isOpen = false;
50
+ }
51
+ makeLink(method) {
52
+ const link = `${this.config.appUrl}${method}${this.queryString}`;
53
+ const a = document.createElement('a');
54
+ a.setAttribute('href', link);
55
+ a.setAttribute('target', '_blank');
56
+ a.click();
57
+ this.isOpen = true;
58
+ }
59
+ makeFrame(method, isSafari = false) {
60
+ const w = this.small;
61
+ //bako frame
62
+ const frame = document.createElement('iframe');
63
+ frame.id = `${this.config.sessionId}-iframe`;
64
+ frame.src = `${this.config.appUrl}${method}${this.queryString}${isSafari ? '&byConnector=true' : ''}`;
65
+ frame.style.position = 'fixed';
66
+ frame.style.zIndex = '99999999';
67
+ frame.style.top = `${w.top}`;
68
+ frame.style.left = `${w.left}`;
69
+ frame.style.width = w.width;
70
+ frame.style.height = w.height;
71
+ frame.style.borderRadius = '16px';
72
+ //backdrop
73
+ const backdrop = document.createElement('div');
74
+ backdrop.id = `${this.config.sessionId}-backdrop`;
75
+ backdrop.style.position = 'fixed';
76
+ backdrop.style.top = '0';
77
+ backdrop.style.left = '0';
78
+ backdrop.style.width = '100%';
79
+ backdrop.style.height = '100%';
80
+ backdrop.style.backgroundColor = 'rgba(0,0,0,0.5)';
81
+ backdrop.style.zIndex = '99999998';
82
+ backdrop.addEventListener('click', () => this.close()); // if user click on backdrop, close the frame
83
+ document.body.appendChild(backdrop);
84
+ document.body.appendChild(frame);
85
+ this.isOpen = true;
86
+ }
87
+ makePopup(method) {
88
+ const link = `${this.config.appUrl}${method}${this.queryString}`;
89
+ const popup = WINDOW.open(link, 'popup', `width=${this.popupConfig.width}, height=${this.popupConfig.height}, top=${this.popupConfig.top}, left=${this.popupConfig.left}`);
90
+ if (popup)
91
+ this.opned = popup;
92
+ this.isOpen = true;
93
+ return popup;
94
+ }
95
+ get queryString() {
96
+ const { sessionId } = this.config;
97
+ return `?sessionId=${sessionId}&origin=${WINDOW.location.origin}&name=${WINDOW.document.title}&request_id=${this.request_id}`;
98
+ }
99
+ get small() {
100
+ // todo: update this to calculate by screen size changes
101
+ const breakponint = {
102
+ md: {
103
+ top: 0,
104
+ left: 0,
105
+ limit: 650,
106
+ width: '100%',
107
+ height: '100%',
108
+ }, // 100%
109
+ lg: {
110
+ top: `${(WINDOW.innerHeight - WINDOW.innerHeight * 0.7) / 2}px`,
111
+ left: `${(WINDOW.innerWidth - WINDOW.innerWidth * 0.5) / 2}px`,
112
+ limit: 1024,
113
+ width: '50%',
114
+ height: '70%',
115
+ }, // 75%
116
+ xl: {
117
+ top: `${(WINDOW.innerHeight - 650) / 2}px`,
118
+ left: `${(WINDOW.innerWidth - 500) / 2}px`,
119
+ limit: 1440,
120
+ height: '650px',
121
+ width: '500px',
122
+ }, // 400px
123
+ };
124
+ return WINDOW.innerWidth < breakponint.md.limit
125
+ ? breakponint.md
126
+ : WINDOW.innerWidth < breakponint.lg.limit
127
+ ? breakponint.lg
128
+ : breakponint.xl;
129
+ }
130
+ }
@@ -0,0 +1,74 @@
1
+ import { io } from 'socket.io-client';
2
+ import { APP_URL, SOCKET_URL } from './constants';
3
+ import { WINDOW } from './constants';
4
+ import { BakoSafeConnectorEvents, BakoSafeUsernames, } from './types';
5
+ const DEFAULT_SOCKET_AUTH = {
6
+ username: BakoSafeUsernames.CONNECTOR,
7
+ data: new Date(),
8
+ origin: WINDOW.origin ?? APP_URL,
9
+ };
10
+ export class SocketClient {
11
+ constructor({ sessionId, events }) {
12
+ this.connecting = false;
13
+ this.request_id = crypto.randomUUID();
14
+ this.server = io(SOCKET_URL, {
15
+ auth: {
16
+ ...DEFAULT_SOCKET_AUTH,
17
+ sessionId,
18
+ request_id: this.request_id,
19
+ },
20
+ autoConnect: false,
21
+ reconnection: true,
22
+ reconnectionAttempts: 5,
23
+ reconnectionDelay: 1000,
24
+ });
25
+ this.server?.on(BakoSafeConnectorEvents.DEFAULT, (data) => {
26
+ if (data.to === DEFAULT_SOCKET_AUTH.username) {
27
+ this.events.emit(data.type, {
28
+ from: data.username,
29
+ data: data.data,
30
+ });
31
+ }
32
+ });
33
+ this.events = events;
34
+ this.setupEventListeners();
35
+ this.connect();
36
+ }
37
+ setupEventListeners() {
38
+ this.server.on('connect', () => {
39
+ this.connecting = false;
40
+ });
41
+ this.server.on('connect_error', () => {
42
+ this.connecting = false;
43
+ });
44
+ this.server.on(BakoSafeConnectorEvents.DEFAULT, (data) => {
45
+ if (data.to === DEFAULT_SOCKET_AUTH.username) {
46
+ this.events.emit(data.type, {
47
+ from: data.username,
48
+ data: data.data,
49
+ });
50
+ }
51
+ });
52
+ }
53
+ static create(options) {
54
+ if (!SocketClient.instance) {
55
+ SocketClient.instance = new SocketClient(options);
56
+ }
57
+ return SocketClient.instance;
58
+ }
59
+ connect() {
60
+ if (this.isConnected || this.connecting)
61
+ return;
62
+ this.connecting = true;
63
+ this.server.connect();
64
+ }
65
+ get isConnected() {
66
+ return this.server.connected;
67
+ }
68
+ checkConnection() {
69
+ if (this.isConnected || this.connecting)
70
+ return;
71
+ this.connect();
72
+ }
73
+ }
74
+ SocketClient.instance = null;
@@ -0,0 +1,16 @@
1
+ export const APP_VERSION = '0.0.0';
2
+ export const APP_NETWORK = '0.0.0';
3
+ export const APP_NAME = 'Bako Safe';
4
+ export const APP_DESCRIPTION = 'Bako Safe is a connector to safe.bako.global, a non-custodial vault for your crypto assets.';
5
+ export const APP_IMAGE_DARK = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTAiIGhlaWdodD0iNTAiIHZpZXdCb3g9IjAgMCA1MCA1MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjUwIiBoZWlnaHQ9IjUwIiByeD0iOCIgZmlsbD0idXJsKCNwYWludDBfbGluZWFyXzEzMjQ5XzE2MjI4MCkiLz4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzEzMjQ5XzE2MjI4MCkiPgo8cGF0aCBkPSJNMTMgMjUuOTE2N0wzNyAzNy44NjcxTDI1LjAwMjQgMTguOTg5M0wxMyAyNS45MTY3WiIgZmlsbD0iI0Y1RjVGNSIvPgo8cGF0aCBkPSJNMzMuODg2NCAyMi4yMTgyTDI0Ljk5NzYgMTcuMDg2NVY1LjEzNTc0TDEzIDEyLjA2MjhWMjUuOTE2TDI0Ljk5NzYgMTguOTg4OVYzMC45Mzk2TDEzIDM3Ljg2NjhMMjQuOTk3NiA0NC43OTM4TDM2Ljk5NTIgMzcuODY2OFYyNy42MDMzQzM2Ljk5NTIgMjUuMzgxNiAzNS44MDk4IDIzLjMyOTEgMzMuODg2NCAyMi4yMTgyWiIgZmlsbD0iIzFFMUYyMiIvPgo8L2c+CjxkZWZzPgo8bGluZWFyR3JhZGllbnQgaWQ9InBhaW50MF9saW5lYXJfMTMyNDlfMTYyMjgwIiB4MT0iMCIgeTE9IjAiIHgyPSI1Mi4zMjg1IiB5Mj0iNDcuNDMxIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+CjxzdG9wIHN0b3AtY29sb3I9IiNGRkMwMTAiLz4KPHN0b3Agb2Zmc2V0PSIwLjQ4IiBzdG9wLWNvbG9yPSIjRUJBMzEyIi8+CjxzdG9wIG9mZnNldD0iMC43MSIgc3RvcC1jb2xvcj0iI0QzODAxNSIvPgo8c3RvcCBvZmZzZXQ9IjAuOTkiIHN0b3AtY29sb3I9IiNCMjRGMTgiLz4KPC9saW5lYXJHcmFkaWVudD4KPGNsaXBQYXRoIGlkPSJjbGlwMF8xMzI0OV8xNjIyODAiPgo8cmVjdCB3aWR0aD0iMjQiIGhlaWdodD0iNDAiIGZpbGw9IndoaXRlIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMyA1KSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo=';
6
+ export const APP_IMAGE_LIGHT = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTAiIGhlaWdodD0iNTAiIHZpZXdCb3g9IjAgMCA1MCA1MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjUwIiBoZWlnaHQ9IjUwIiByeD0iOCIgZmlsbD0idXJsKCNwYWludDBfbGluZWFyXzEzMjQ5XzE2MjI4MCkiLz4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzEzMjQ5XzE2MjI4MCkiPgo8cGF0aCBkPSJNMTMgMjUuOTE2N0wzNyAzNy44NjcxTDI1LjAwMjQgMTguOTg5M0wxMyAyNS45MTY3WiIgZmlsbD0iI0Y1RjVGNSIvPgo8cGF0aCBkPSJNMzMuODg2NCAyMi4yMTgyTDI0Ljk5NzYgMTcuMDg2NVY1LjEzNTc0TDEzIDEyLjA2MjhWMjUuOTE2TDI0Ljk5NzYgMTguOTg4OVYzMC45Mzk2TDEzIDM3Ljg2NjhMMjQuOTk3NiA0NC43OTM4TDM2Ljk5NTIgMzcuODY2OFYyNy42MDMzQzM2Ljk5NTIgMjUuMzgxNiAzNS44MDk4IDIzLjMyOTEgMzMuODg2NCAyMi4yMTgyWiIgZmlsbD0iIzFFMUYyMiIvPgo8L2c+CjxkZWZzPgo8bGluZWFyR3JhZGllbnQgaWQ9InBhaW50MF9saW5lYXJfMTMyNDlfMTYyMjgwIiB4MT0iMCIgeTE9IjAiIHgyPSI1Mi4zMjg1IiB5Mj0iNDcuNDMxIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+CjxzdG9wIHN0b3AtY29sb3I9IiNGRkMwMTAiLz4KPHN0b3Agb2Zmc2V0PSIwLjQ4IiBzdG9wLWNvbG9yPSIjRUJBMzEyIi8+CjxzdG9wIG9mZnNldD0iMC43MSIgc3RvcC1jb2xvcj0iI0QzODAxNSIvPgo8c3RvcCBvZmZzZXQ9IjAuOTkiIHN0b3AtY29sb3I9IiNCMjRGMTgiLz4KPC9saW5lYXJHcmFkaWVudD4KPGNsaXBQYXRoIGlkPSJjbGlwMF8xMzI0OV8xNjIyODAiPgo8cmVjdCB3aWR0aD0iMjQiIGhlaWdodD0iNDAiIGZpbGw9IndoaXRlIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMyA1KSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo=';
7
+ export const APP_URL = 'https://safe.bako.global';
8
+ export const HOST_URL = 'https://api.bako.global';
9
+ export const SOCKET_URL = 'https://api.bako.global';
10
+ // Window object
11
+ export const HAS_WINDOW = typeof window !== 'undefined';
12
+ // biome-ignore lint/suspicious/noExplicitAny: <explanation>
13
+ export const WINDOW = HAS_WINDOW ? window : {};
14
+ export const IS_SAFARI = /^((?!chrome|android).)*safari/i.test(WINDOW.navigator?.userAgent ?? '');
15
+ //storage
16
+ export const SESSION_ID = 'sessionId';
@@ -0,0 +1 @@
1
+ export * from './BakoSafeConnector';
@@ -0,0 +1,15 @@
1
+ import { urlJoin } from 'fuels';
2
+ export class RequestAPI {
3
+ constructor(baseUrl) {
4
+ this.baseUrl = baseUrl;
5
+ }
6
+ async get(pathname) {
7
+ const data = await fetch(urlJoin(this.baseUrl, pathname)).then((res) => res.json());
8
+ return data;
9
+ }
10
+ async delete(pathname) {
11
+ await fetch(urlJoin(this.baseUrl, pathname), {
12
+ method: 'DELETE',
13
+ });
14
+ }
15
+ }
@@ -0,0 +1,25 @@
1
+ export var BakoSafeConnectorEvents;
2
+ (function (BakoSafeConnectorEvents) {
3
+ //default
4
+ BakoSafeConnectorEvents["DEFAULT"] = "message";
5
+ //client
6
+ BakoSafeConnectorEvents["CLIENT_DISCONNECTED"] = "[CLIENT_DISCONNECTED]";
7
+ BakoSafeConnectorEvents["CLIENT_CONNECTED"] = "[CONNECTED]";
8
+ //transactions
9
+ BakoSafeConnectorEvents["TX_PENDING"] = "[TX_EVENT_REQUESTED]";
10
+ BakoSafeConnectorEvents["TX_CONFIRMED"] = "[TX_EVENT_CONFIRMED]";
11
+ BakoSafeConnectorEvents["TX_TIMEOUT"] = "[TX_EVENT_TIMEOUT]";
12
+ //switchNetwork
13
+ BakoSafeConnectorEvents["CHANGE_NETWORK"] = "[CHANGE_NETWORK]";
14
+ BakoSafeConnectorEvents["NETWORK_CHANGED"] = "[NETWORK_CHANGED]";
15
+ //auth
16
+ BakoSafeConnectorEvents["AUTH_CONFIRMED"] = "[AUTH_CONFIRMED]";
17
+ BakoSafeConnectorEvents["CONNECTION_STATE"] = "[CONNECTION_STATE]";
18
+ BakoSafeConnectorEvents["DISCONNECT"] = "[DISCONNECT]";
19
+ })(BakoSafeConnectorEvents || (BakoSafeConnectorEvents = {}));
20
+ export var BakoSafeUsernames;
21
+ (function (BakoSafeUsernames) {
22
+ BakoSafeUsernames["CONNECTOR"] = "[CONNECTOR]";
23
+ BakoSafeUsernames["CLIENT"] = "[UI]";
24
+ BakoSafeUsernames["SERVER"] = "[API]";
25
+ })(BakoSafeUsernames || (BakoSafeUsernames = {}));