@ckb-ccc/connector 0.0.5-alpha.0 → 0.0.5-alpha.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.
Files changed (49) hide show
  1. package/dist/advancedBarrel.d.ts +1 -0
  2. package/dist/advancedBarrel.d.ts.map +1 -1
  3. package/dist/advancedBarrel.js +1 -0
  4. package/dist/assets/chains/ckb.sm.svg.d.ts +2 -0
  5. package/dist/assets/chains/ckb.sm.svg.d.ts.map +1 -0
  6. package/dist/assets/chains/ckb.sm.svg.js +2 -0
  7. package/dist/assets/copy.svg.d.ts +2 -0
  8. package/dist/assets/copy.svg.d.ts.map +1 -0
  9. package/dist/assets/copy.svg.js +2 -0
  10. package/dist/assets/diconnect.svg.d.ts +2 -0
  11. package/dist/assets/diconnect.svg.d.ts.map +1 -0
  12. package/dist/assets/diconnect.svg.js +2 -0
  13. package/dist/assets/left.svg.d.ts +2 -0
  14. package/dist/assets/left.svg.d.ts.map +1 -0
  15. package/dist/assets/left.svg.js +2 -0
  16. package/dist/assets/swap.svg.d.ts +2 -0
  17. package/dist/assets/swap.svg.d.ts.map +1 -0
  18. package/dist/assets/swap.svg.js +2 -0
  19. package/dist/connector/index.d.ts +12 -0
  20. package/dist/connector/index.d.ts.map +1 -1
  21. package/dist/connector/index.js +278 -39
  22. package/dist/scenes/connected.d.ts +4 -0
  23. package/dist/scenes/connected.d.ts.map +1 -0
  24. package/dist/scenes/connected.js +71 -0
  25. package/dist/scenes/networks.d.ts +3 -0
  26. package/dist/scenes/networks.d.ts.map +1 -0
  27. package/dist/scenes/networks.js +38 -0
  28. package/dist/scenes/signers.d.ts.map +1 -1
  29. package/dist/scenes/signers.js +5 -2
  30. package/dist/scenes/wallets.d.ts +1 -1
  31. package/dist/scenes/wallets.d.ts.map +1 -1
  32. package/dist/scenes/wallets.js +9 -44
  33. package/dist/signerOpenLink/index.d.ts +13 -0
  34. package/dist/signerOpenLink/index.d.ts.map +1 -0
  35. package/dist/signerOpenLink/index.js +26 -0
  36. package/package.json +3 -3
  37. package/src/advancedBarrel.ts +1 -0
  38. package/src/assets/chains/ckb.sm.svg.ts +5 -0
  39. package/src/assets/copy.svg.ts +5 -0
  40. package/src/assets/diconnect.svg.ts +5 -0
  41. package/src/assets/left.svg.ts +5 -0
  42. package/src/assets/swap.svg.ts +5 -0
  43. package/src/connector/index.ts +331 -56
  44. package/src/scenes/connected.ts +87 -0
  45. package/src/scenes/networks.ts +47 -0
  46. package/src/scenes/signers.ts +5 -2
  47. package/src/scenes/wallets.ts +20 -63
  48. package/src/signerOpenLink/index.ts +35 -0
  49. package/dist.commonjs/tsconfig.commonjs.tsbuildinfo +0 -1
@@ -1,8 +1,11 @@
1
1
  import { ccc } from "@ckb-ccc/ccc";
2
2
  import { LitElement, PropertyValues, css, html } from "lit";
3
3
  import { customElement, property, state } from "lit/decorators.js";
4
+ import { Ref, createRef, ref } from "lit/directives/ref.js";
4
5
  import { CLOSE_SVG } from "../assets/close.svg";
5
6
  import { JOY_ID_SVG } from "../assets/joy-id.svg";
7
+ import { LEFT_SVG } from "../assets/left.svg";
8
+ import { METAMASK_SVG } from "../assets/metamask.svg";
6
9
  import { OKX_SVG } from "../assets/okx.svg";
7
10
  import { UNI_SAT_SVG } from "../assets/uni-sat.svg";
8
11
  import { WillUpdateEvent } from "../events";
@@ -11,6 +14,9 @@ import {
11
14
  generateSignersScene,
12
15
  generateWalletsScene,
13
16
  } from "../scenes";
17
+ import { generateConnectedScene } from "../scenes/connected";
18
+ import { generateNetworksScene } from "../scenes/networks";
19
+ import { SignerOpenLink } from "../signerOpenLink";
14
20
  import { WalletWithSigners } from "../types";
15
21
 
16
22
  enum Scene {
@@ -18,12 +24,18 @@ enum Scene {
18
24
  SelectingSigners = "SelectingSigners",
19
25
  Connecting = "Connecting",
20
26
  Connected = "Connected",
27
+ SwitchingNetworks = "SwitchingNetworks",
21
28
  }
22
29
 
23
30
  @customElement("ccc-connector")
24
31
  export class WebComponentConnector extends LitElement {
25
32
  @state()
26
33
  private wallets: WalletWithSigners[] = [];
34
+ @property()
35
+ public signerFilter?: (
36
+ signerInfo: ccc.SignerInfo,
37
+ wallet: ccc.Wallet,
38
+ ) => Promise<boolean>;
27
39
 
28
40
  private resetListeners: (() => void)[] = [];
29
41
 
@@ -33,6 +45,11 @@ export class WebComponentConnector extends LitElement {
33
45
  this.isOpen = isOpen;
34
46
  }
35
47
 
48
+ @property()
49
+ public name?: string;
50
+ @property()
51
+ public icon?: string;
52
+
36
53
  @property()
37
54
  public client: ccc.Client = new ccc.ClientPublicTestnet();
38
55
  public setClient(client: ccc.Client) {
@@ -54,17 +71,33 @@ export class WebComponentConnector extends LitElement {
54
71
  public wallet?: ccc.Wallet;
55
72
  @state()
56
73
  public signer?: ccc.SignerInfo;
57
- private prepareSigner() {
58
- (async () => {
59
- if (this.signer && (await this.signer.signer.isConnected())) {
60
- this.scene = Scene.Connected;
61
- return;
62
- }
63
74
 
64
- this.wallet = undefined;
65
- this.signer = undefined;
66
- this.scene = Scene.SelectingWallets;
67
- })();
75
+ @state()
76
+ private recommendAddress?: string;
77
+ @state()
78
+ private internalAddress?: string;
79
+ @state()
80
+ private balance?: ccc.Num;
81
+
82
+ private async updateSignerInfo() {
83
+ if (!this.signer) {
84
+ return;
85
+ }
86
+ this.recommendAddress = await this.signer.signer.getRecommendedAddress();
87
+ this.balance = await this.signer.signer.getBalance();
88
+ this.internalAddress = await this.signer.signer.getInternalAddress();
89
+ }
90
+
91
+ private async prepareSigner() {
92
+ if (this.signer && (await this.signer.signer.isConnected())) {
93
+ await this.updateSignerInfo();
94
+ this.scene = Scene.Connected;
95
+ return;
96
+ }
97
+
98
+ this.wallet = undefined;
99
+ this.signer = undefined;
100
+ this.scene = Scene.SelectingWallets;
68
101
  }
69
102
 
70
103
  public disconnect() {
@@ -72,6 +105,7 @@ export class WebComponentConnector extends LitElement {
72
105
  this.walletName = undefined;
73
106
  this.signerName = undefined;
74
107
  this.saveConnection();
108
+ this.closedHandler();
75
109
  }
76
110
 
77
111
  private loadConnection() {
@@ -103,23 +137,33 @@ export class WebComponentConnector extends LitElement {
103
137
  }
104
138
 
105
139
  willUpdate(changedProperties: PropertyValues): void {
106
- if (changedProperties.has("client")) {
107
- this.reloadSigners();
108
- }
109
140
  if (
110
- changedProperties.has("walletName") ||
111
- changedProperties.has("wallets")
141
+ changedProperties.has("client") ||
142
+ changedProperties.has("signerFilter")
112
143
  ) {
113
- this.wallet = this.wallets.find(({ name }) => name === this.walletName);
144
+ this.reloadSigners();
114
145
  }
115
146
  if (
147
+ changedProperties.has("walletName") ||
148
+ changedProperties.has("wallets") ||
116
149
  changedProperties.has("signerName") ||
117
150
  changedProperties.has("wallet")
118
151
  ) {
119
- const wallet = this.wallets.find(({ name }) => name === this.walletName);
120
- this.signer = wallet?.signers.find(
121
- ({ name }) => name === this.signerName,
122
- );
152
+ (async () => {
153
+ const wallet = this.wallets.find(
154
+ ({ name }) => name === this.walletName,
155
+ );
156
+ const signer = wallet?.signers.find(
157
+ ({ name }) => name === this.signerName,
158
+ );
159
+ if (signer && (await signer.signer.isConnected())) {
160
+ this.wallet = wallet;
161
+ this.signer = signer;
162
+ } else {
163
+ this.wallet = undefined;
164
+ this.signer = undefined;
165
+ }
166
+ })();
123
167
  }
124
168
  if (changedProperties.has("signer")) {
125
169
  this.prepareSigner();
@@ -144,31 +188,27 @@ export class WebComponentConnector extends LitElement {
144
188
 
145
189
  this.resetListeners.forEach((listener) => listener());
146
190
  this.resetListeners = [];
147
-
148
- ccc.JoyId.getJoyIdSigners(this.client).forEach(({ signer, type, name }) => {
149
- this.addSigner("JoyID", name, JOY_ID_SVG, type, signer);
150
- });
191
+ const name =
192
+ this.name ??
193
+ (document.querySelector("head title") as HTMLTitleElement).text;
194
+ const icon =
195
+ this.icon ??
196
+ (document.querySelector('link[rel="icon"]') as HTMLLinkElement).href;
197
+
198
+ ccc.JoyId.getJoyIdSigners(this.client, name, icon).forEach(
199
+ ({ signer, name }) => {
200
+ this.addSigner("JoyID", name, JOY_ID_SVG, signer);
201
+ },
202
+ );
151
203
 
152
204
  const uniSatSigner = ccc.UniSat.getUniSatSigner(this.client);
153
205
  if (uniSatSigner) {
154
- this.addSigner(
155
- "UniSat",
156
- "BTC",
157
- UNI_SAT_SVG,
158
- ccc.SignerType.BTC,
159
- uniSatSigner,
160
- );
206
+ this.addSigner("UniSat", "BTC", UNI_SAT_SVG, uniSatSigner);
161
207
  }
162
208
 
163
209
  const okxBitcoinSigner = ccc.Okx.getOKXBitcoinSigner(this.client);
164
210
  if (okxBitcoinSigner) {
165
- this.addSigner(
166
- "OKX Wallet",
167
- "BTC",
168
- OKX_SVG,
169
- ccc.SignerType.BTC,
170
- okxBitcoinSigner,
171
- );
211
+ this.addSigner("OKX Wallet", "BTC", OKX_SVG, okxBitcoinSigner);
172
212
  }
173
213
 
174
214
  const eip6963Manager = new ccc.Eip6963.SignerFactory(this.client);
@@ -178,20 +218,64 @@ export class WebComponentConnector extends LitElement {
178
218
  `${signer.detail.info.name}`,
179
219
  "EVM",
180
220
  signer.detail.info.icon,
181
- ccc.SignerType.EVM,
182
221
  signer,
183
222
  );
184
223
  }),
185
224
  );
225
+
226
+ // === Dummy signers ===
227
+ this.addSigner(
228
+ "MetaMask",
229
+ "EVM",
230
+ METAMASK_SVG,
231
+ new SignerOpenLink(
232
+ this.client,
233
+ `https://metamask.app.link/dapp/${window.location.href}`,
234
+ ccc.SignerType.EVM,
235
+ ),
236
+ );
237
+ [ccc.SignerType.EVM, ccc.SignerType.BTC].forEach((type) => {
238
+ this.addSigner(
239
+ "OKX Wallet",
240
+ type,
241
+ OKX_SVG,
242
+ new SignerOpenLink(
243
+ this.client,
244
+ "https://www.okx.com/download?deeplink=" +
245
+ encodeURIComponent(
246
+ "okx://wallet/dapp/url?dappUrl=" +
247
+ encodeURIComponent(window.location.href),
248
+ ),
249
+ type,
250
+ ),
251
+ );
252
+ });
253
+ this.addSigner(
254
+ "UniSat",
255
+ ccc.SignerType.BTC,
256
+ UNI_SAT_SVG,
257
+ new SignerOpenLink(
258
+ this.client,
259
+ "https://unisat.io/download",
260
+ ccc.SignerType.BTC,
261
+ ),
262
+ );
263
+ // ===
186
264
  }
187
265
 
188
- private addSigner(
266
+ private async addSigner(
189
267
  walletName: string,
190
268
  signerName: string,
191
269
  icon: string,
192
- type: ccc.SignerType,
193
270
  signer: ccc.Signer,
194
271
  ) {
272
+ const signerInfo = { name: signerName, signer };
273
+ if (
274
+ this.signerFilter &&
275
+ !(await this.signerFilter(signerInfo, { name: walletName, icon }))
276
+ ) {
277
+ return;
278
+ }
195
279
  let updated = false;
196
280
  const wallets = this.wallets.map((wallet) => {
197
281
  if (wallet.name !== walletName) {
@@ -199,9 +283,13 @@ export class WebComponentConnector extends LitElement {
199
283
  }
200
284
 
201
285
  updated = true;
286
+ const allSigners = [...wallet.signers, signerInfo];
287
+ const signers = allSigners.filter(
288
+ ({ signer }) => !(signer instanceof SignerOpenLink),
289
+ );
202
290
  return {
203
291
  ...wallet,
204
- signers: [...wallet.signers, { type, name: signerName, signer }],
292
+ signers: signers.length !== 0 ? signers : [signerInfo],
205
293
  };
206
294
  });
207
295
 
@@ -209,15 +297,38 @@ export class WebComponentConnector extends LitElement {
209
297
  wallets.push({
210
298
  name: walletName,
211
299
  icon,
212
- signers: [{ type, name: signerName, signer }],
300
+ signers: [signerInfo],
213
301
  });
214
302
  }
215
303
 
216
304
  this.wallets = wallets;
217
305
  }
218
306
 
307
+ mainRef: Ref<HTMLDivElement> = createRef();
308
+ headerRef: Ref<HTMLDivElement> = createRef();
309
+ bodyRef: Ref<HTMLDivElement> = createRef();
310
+
219
311
  render() {
220
312
  const [title, body] = (() => {
313
+ if (this.scene === Scene.Connected && this.wallet && this.signer) {
314
+ return generateConnectedScene(
315
+ this.wallet,
316
+ this.signer,
317
+ this.recommendAddress,
318
+ this.internalAddress,
319
+ this.balance,
320
+ this.disconnect.bind(this),
321
+ () => {
322
+ this.scene = Scene.SwitchingNetworks;
323
+ },
324
+ );
325
+ }
326
+ if (this.scene === Scene.SwitchingNetworks) {
327
+ return generateNetworksScene(this.client, (client) => {
328
+ this.setClient(client);
329
+ this.closedHandler();
330
+ });
331
+ }
221
332
  if (this.scene === Scene.SelectingWallets || !this.selectedWallet) {
222
333
  return generateWalletsScene(
223
334
  this.wallets,
@@ -241,6 +352,12 @@ export class WebComponentConnector extends LitElement {
241
352
  );
242
353
  })();
243
354
 
355
+ const canBack = [
356
+ Scene.SelectingSigners,
357
+ Scene.Connecting,
358
+ Scene.SwitchingNetworks,
359
+ ].includes(this.scene);
360
+
244
361
  return html`<style>
245
362
  :host {
246
363
  ${this.isOpen ? "" : "display: none;"}
@@ -249,6 +366,7 @@ export class WebComponentConnector extends LitElement {
249
366
  --btn-primary: #f8f8f8;
250
367
  --btn-primary-hover: #efeeee;
251
368
  --btn-secondary: #ddd;
369
+ --btn-secondary-hover: #ccc;
252
370
  color: #1e1e1e;
253
371
  --tip-color: #666;
254
372
  }
@@ -261,17 +379,52 @@ export class WebComponentConnector extends LitElement {
261
379
  }
262
380
  }}
263
381
  >
264
- <div class="main">
265
- <div class="header text-bold fs-big">
266
- <div class="back"></div>
382
+ <div class="main" ${ref(this.mainRef)}>
383
+ <div
384
+ class="header text-bold fs-lg ${title == null
385
+ ? ""
386
+ : "header-divider"}"
387
+ ${ref(this.headerRef)}
388
+ >
389
+ <img
390
+ class="back ${canBack ? "active" : ""}"
391
+ src=${LEFT_SVG}
392
+ @click=${() => {
393
+ if (this.scene === Scene.Connecting) {
394
+ if ((this.selectedWallet?.signers.length ?? 0) <= 1) {
395
+ this.scene = Scene.SelectingWallets;
396
+ } else {
397
+ this.scene = Scene.SelectingSigners;
398
+ }
399
+ } else if (this.scene === Scene.SelectingSigners) {
400
+ this.scene = Scene.SelectingWallets;
401
+ } else if (this.scene === Scene.SwitchingNetworks) {
402
+ this.scene = Scene.Connected;
403
+ }
404
+ }}
405
+ />
267
406
  ${title}
268
- <img class="close" src=${CLOSE_SVG} @click=${this.closedHandler} />
407
+ <img
408
+ class="close active"
409
+ src=${CLOSE_SVG}
410
+ @click=${this.closedHandler}
411
+ />
269
412
  </div>
270
- <div class="body">${body}</div>
413
+ <div class="body" ${ref(this.bodyRef)}>${body}</div>
271
414
  </div>
272
415
  </div>`;
273
416
  }
274
417
 
418
+ updated() {
419
+ if (!this.mainRef.value) {
420
+ return;
421
+ }
422
+ this.mainRef.value.style.height = `${
423
+ (this.bodyRef.value?.clientHeight ?? 0) +
424
+ (this.headerRef.value?.clientHeight ?? 0)
425
+ }px`;
426
+ }
427
+
275
428
  private closedHandler = () => {
276
429
  if (
277
430
  [
@@ -283,7 +436,10 @@ export class WebComponentConnector extends LitElement {
283
436
  this.scene = Scene.SelectingWallets;
284
437
  this.selectedSigner = undefined;
285
438
  this.selectedWallet = undefined;
439
+ } else if ([Scene.SwitchingNetworks].includes(this.scene)) {
440
+ this.scene = Scene.Connected;
286
441
  }
442
+
287
443
  this.isOpen = false;
288
444
  };
289
445
 
@@ -299,6 +455,8 @@ export class WebComponentConnector extends LitElement {
299
455
  if (!(await signer.signer.isConnected())) {
300
456
  return;
301
457
  }
458
+ this.recommendAddress = await signer.signer.getRecommendedAddress();
459
+ this.balance = await signer.signer.getBalance();
302
460
  this.scene = Scene.Connected;
303
461
  this.walletName = wallet.name;
304
462
  this.signerName = signer.name;
@@ -334,9 +492,18 @@ export class WebComponentConnector extends LitElement {
334
492
  color: var(--tip-color);
335
493
  }
336
494
 
337
- .fs-big {
495
+ .fs-sm {
496
+ font-size: 0.8rem;
497
+ }
498
+ .fs-md {
499
+ font-size: 1rem;
500
+ }
501
+ .fs-lg {
338
502
  font-size: 1.2rem;
339
503
  }
504
+ .fs-xl {
505
+ font-size: 1.5rem;
506
+ }
340
507
 
341
508
  .mb-1 {
342
509
  margin-bottom: 0.7rem;
@@ -350,6 +517,18 @@ export class WebComponentConnector extends LitElement {
350
517
  .mt-2 {
351
518
  margin-top: 1rem;
352
519
  }
520
+ .ml-1 {
521
+ margin-left: 0.7rem;
522
+ }
523
+ .ml-2 {
524
+ margin-left: 1em;
525
+ }
526
+ .mr-1 {
527
+ margin-right: 0.7rem;
528
+ }
529
+ .mr-2 {
530
+ margin-right: 1rem;
531
+ }
353
532
 
354
533
  .background {
355
534
  width: 100%;
@@ -364,25 +543,39 @@ export class WebComponentConnector extends LitElement {
364
543
  transform: translate(-50%, -50%);
365
544
  background: var(--background);
366
545
  border-radius: 1.2rem;
546
+ overflow: hidden;
547
+ transition: height 0.15s ease-out;
367
548
  }
368
549
 
369
550
  .header {
370
551
  display: flex;
371
552
  justify-content: space-between;
372
553
  align-items: center;
373
- padding: 1rem 1.3rem;
554
+ padding: 1rem 1.3rem 0.5rem;
555
+ }
556
+
557
+ .header-divider {
558
+ padding-bottom: 1rem;
374
559
  border-bottom: 1px solid var(--divider);
560
+ margin-bottom: 1rem;
375
561
  }
376
562
 
377
563
  .close,
378
564
  .back {
379
565
  width: 0.8rem;
380
566
  height: 0.8rem;
567
+ opacity: 0;
568
+ transition: opacity 0.15s ease-in-out;
569
+ }
570
+
571
+ .close.active,
572
+ .back.active {
573
+ opacity: 1;
381
574
  cursor: pointer;
382
575
  }
383
576
 
384
577
  .body {
385
- padding: 1.4rem 1.3rem;
578
+ padding: 0 1.3rem 1.4rem;
386
579
  min-width: 20rem;
387
580
  display: flex;
388
581
  flex-direction: column;
@@ -397,18 +590,23 @@ export class WebComponentConnector extends LitElement {
397
590
  padding: 0.75rem 1rem;
398
591
  background: var(--btn-primary);
399
592
  border-radius: 0.4rem;
400
- transition: background 0.3s ease-in-out;
593
+ transition: background 0.15s ease-in-out;
401
594
  }
402
-
403
595
  .btn-primary img {
404
596
  width: 2rem;
405
597
  height: 2rem;
406
598
  margin-right: 1rem;
599
+ border-radius: 0.4rem;
407
600
  }
408
-
409
601
  .btn-primary:hover {
410
602
  background: var(--btn-primary-hover);
411
603
  }
604
+ .btn-primary:disabled {
605
+ cursor: not-allowed;
606
+ }
607
+ .btn-primary:disabled:hover {
608
+ background: var(--btn-primary);
609
+ }
412
610
 
413
611
  .btn-secondary {
414
612
  display: flex;
@@ -416,19 +614,28 @@ export class WebComponentConnector extends LitElement {
416
614
  padding: 0.25rem 1rem;
417
615
  background: var(--btn-secondary);
418
616
  border-radius: 9999px;
419
- transition: background 0.3s ease-in-out;
617
+ transition: background 0.15s ease-in-out;
420
618
  }
421
-
422
619
  .btn-secondary img {
423
620
  width: 0.8rem;
424
621
  height: 0.8rem;
425
622
  margin-right: 0.5rem;
426
623
  }
624
+ .btn-secondary:hover {
625
+ background: var(--btn-secondary-hover);
626
+ }
627
+ .btn-secondary:disabled {
628
+ cursor: not-allowed;
629
+ }
630
+ .btn-secondary:disabled:hover {
631
+ background: var(--btn-secondary);
632
+ }
427
633
 
428
634
  .wallet-icon {
429
635
  width: 4rem;
430
636
  height: 4rem;
431
637
  margin-bottom: 0.5rem;
638
+ border-radius: 0.8rem;
432
639
  }
433
640
 
434
641
  .connecting-wallet-icon {
@@ -436,5 +643,73 @@ export class WebComponentConnector extends LitElement {
436
643
  height: 5rem;
437
644
  border-radius: 1rem;
438
645
  }
646
+
647
+ .position-relative {
648
+ position: relative;
649
+ }
650
+ .position-absolute {
651
+ position: absolute;
652
+ }
653
+
654
+ .connected-type-icon {
655
+ position: absolute;
656
+ width: 1.5rem;
657
+ height: 1.5rem;
658
+ right: -0.5rem;
659
+ bottom: -0.5rem;
660
+ }
661
+
662
+ .text-center {
663
+ text-align: center;
664
+ }
665
+
666
+ .cursor-pointer {
667
+ cursor: pointer;
668
+ }
669
+
670
+ .flex {
671
+ display: flex;
672
+ }
673
+ .justify-center {
674
+ justify-content: center;
675
+ }
676
+ .justify-between {
677
+ justify-content: space-between;
678
+ }
679
+ .align-center {
680
+ align-items: center;
681
+ }
682
+
683
+ .switch-btn-container {
684
+ width: 100%;
685
+ padding: 1rem;
686
+ }
687
+
688
+ .switch-line {
689
+ flex: 1;
690
+ height: 1px;
691
+ background-color: var(--divider);
692
+ }
693
+
694
+ .switching-status-dot {
695
+ width: 0.5rem;
696
+ height: 0.5rem;
697
+ background: #0f0;
698
+ border-radius: 50%;
699
+ }
700
+
701
+ .copy-btn {
702
+ width: 1.5rem;
703
+ height: 1.5rem;
704
+ }
705
+
706
+ .copy-btn-sm {
707
+ width: 1rem;
708
+ height: 1rem;
709
+ }
710
+
711
+ .sm-chain-logo {
712
+ width: 1.125rem;
713
+ }
439
714
  `;
440
715
  }
@@ -0,0 +1,87 @@
1
+ import { ccc } from "@ckb-ccc/ccc";
2
+ import { html } from "lit";
3
+ import { CKB_SVG } from "../assets/chains";
4
+ import { COPY_SVG } from "../assets/copy.svg";
5
+ import { DISCONNECT_SVG } from "../assets/diconnect.svg";
6
+ import { SWAP_SVG } from "../assets/swap.svg";
7
+ import { signerTypeToIcon } from "./signers";
8
+
9
+ function copyAddress(address?: string) {
10
+ if (!address) {
11
+ return;
12
+ }
13
+
14
+ return window.navigator.clipboard.writeText(address);
15
+ }
16
+
17
+ export function formatString(
18
+ str: string | undefined,
19
+ l = 7,
20
+ r = 5,
21
+ ): string | undefined {
22
+ if (str && str.length > l + r + 3) {
23
+ return `${str.slice(0, l)}...${str.slice(-r)}`;
24
+ }
25
+ return str;
26
+ }
27
+
28
+ export function generateConnectedScene(
29
+ wallet: ccc.Wallet,
30
+ signer: ccc.SignerInfo,
31
+ recommendedAddress: string | undefined,
32
+ internalAddress: string | undefined,
33
+ balance: ccc.Num | undefined,
34
+ disconnect: () => void,
35
+ handleSwitchClick: () => void,
36
+ ) {
37
+ return [
38
+ undefined,
39
+ html`
40
+ <div class="position-relative">
41
+ <img
42
+ class="connecting-wallet-icon"
43
+ src=${wallet.icon}
44
+ alt=${wallet.name}
45
+ />
46
+ <img
47
+ class="connected-type-icon"
48
+ src=${signerTypeToIcon(signer.signer.type)}
49
+ alt=${signer.signer.type}
50
+ >
51
+ </img>
52
+ </div>
53
+
54
+ <div class="flex align-center mt-2">
55
+ <span class="text-bold fs-xl">${formatString(internalAddress)}</span>
56
+ <img class="cursor-pointer copy-btn" src=${COPY_SVG} alt="copy" @click=${() => copyAddress(internalAddress)}/>
57
+ </div>
58
+ <div class="text-bold fs-md">${ccc.fixedPointToString(balance ?? ccc.Zero)} CKB</div>
59
+ <div class="flex align-center">
60
+ <span class="text-bold text-tip fs-md">${formatString(recommendedAddress, 13, 7)}</span>
61
+ <img class="cursor-pointer copy-btn-sm" src=${COPY_SVG} alt="copy" @click=${() => copyAddress(recommendedAddress)}/>
62
+ </div>
63
+
64
+ <button
65
+ class="btn-primary mt-2"
66
+ @click=${disconnect}
67
+ >
68
+ <img
69
+ src=${DISCONNECT_SVG}
70
+ alt="disconnect"
71
+ />
72
+ Disconnect
73
+ </button>
74
+
75
+ <div class="switch-btn-container align-center flex justify-center mt-1">
76
+ <div class="switch-line"></div>
77
+ <div class="switch-content flex align-center cursor-pointer ml-2 mr-2 fs-sm" @click=${handleSwitchClick}>
78
+ <img class="mr-1 sm-chain-logo" src=${CKB_SVG} alt="Nervos Network">
79
+ ${signer.signer.client.addressPrefix === "ckb" ? "Mainnet" : "Testnet"}
80
+ ${["ckb", "ckt"].includes(signer.signer.client.addressPrefix) ? "" : ` ${signer.signer.client.addressPrefix}`}
81
+ <img class="ml-1" src=${SWAP_SVG} alt="Nervos Network">
82
+ </div>
83
+ <div class="switch-line"></div>
84
+ </div>
85
+ `,
86
+ ];
87
+ }