@ckb-ccc/connector 0.0.4 → 0.0.5-alpha.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.
Files changed (42) hide show
  1. package/README.md +6 -0
  2. package/dist/assets/chains/ckb.svg.d.ts +2 -0
  3. package/dist/assets/chains/ckb.svg.d.ts.map +1 -0
  4. package/dist/assets/chains/ckb.svg.js +2 -0
  5. package/dist/assets/chains/index.d.ts +1 -0
  6. package/dist/assets/chains/index.d.ts.map +1 -1
  7. package/dist/assets/chains/index.js +1 -0
  8. package/dist/assets/joy-id.svg.d.ts +2 -0
  9. package/dist/assets/joy-id.svg.d.ts.map +1 -0
  10. package/dist/assets/joy-id.svg.js +2 -0
  11. package/dist/assets/left.svg.d.ts +2 -0
  12. package/dist/assets/left.svg.d.ts.map +1 -0
  13. package/dist/assets/left.svg.js +2 -0
  14. package/dist/assets/metamask.svg.d.ts +2 -0
  15. package/dist/assets/metamask.svg.d.ts.map +1 -0
  16. package/dist/assets/metamask.svg.js +2 -0
  17. package/dist/connector/index.d.ts +11 -7
  18. package/dist/connector/index.d.ts.map +1 -1
  19. package/dist/connector/index.js +130 -73
  20. package/dist/scenes/connecting.d.ts +2 -1
  21. package/dist/scenes/connecting.d.ts.map +1 -1
  22. package/dist/scenes/signers.d.ts +1 -1
  23. package/dist/scenes/signers.d.ts.map +1 -1
  24. package/dist/scenes/signers.js +3 -2
  25. package/dist/scenes/wallets.d.ts +1 -1
  26. package/dist/scenes/wallets.d.ts.map +1 -1
  27. package/dist/scenes/wallets.js +44 -9
  28. package/dist/types/index.d.ts +5 -0
  29. package/dist/types/index.d.ts.map +1 -1
  30. package/package.json +3 -3
  31. package/src/assets/chains/ckb.svg.ts +5 -0
  32. package/src/assets/chains/index.ts +1 -0
  33. package/src/assets/joy-id.svg.ts +5 -0
  34. package/src/assets/left.svg.ts +5 -0
  35. package/src/assets/metamask.svg.ts +5 -0
  36. package/src/connector/index.ts +153 -80
  37. package/src/scenes/connecting.ts +3 -2
  38. package/src/scenes/signers.ts +4 -3
  39. package/src/scenes/wallets.ts +68 -22
  40. package/src/types/index.ts +6 -0
  41. package/tsconfig.base.json +0 -21
  42. package/tsconfig.commonjs.json +0 -8
@@ -2,4 +2,9 @@ import { ccc } from "@ckb-ccc/ccc";
2
2
  export type WalletWithSigners = ccc.Wallet & {
3
3
  signers: ccc.SignerInfo[];
4
4
  };
5
+ export interface WalletInfo {
6
+ name: string;
7
+ icon: string;
8
+ downloadLink: string;
9
+ }
5
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEnC,MAAM,MAAM,iBAAiB,GAAG,GAAG,CAAC,MAAM,GAAG;IAC3C,OAAO,EAAE,GAAG,CAAC,UAAU,EAAE,CAAC;CAC3B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEnC,MAAM,MAAM,iBAAiB,GAAG,GAAG,CAAC,MAAM,GAAG;IAC3C,OAAO,EAAE,GAAG,CAAC,UAAU,EAAE,CAAC;CAC3B,CAAC;AAEF,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;CACtB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ckb-ccc/connector",
3
- "version": "0.0.4",
3
+ "version": "0.0.5-alpha.1",
4
4
  "description": "Common Chains Connector UI",
5
5
  "author": "Hanssen0 <hanssen0@hanssen0.com>",
6
6
  "license": "MIT",
@@ -37,8 +37,8 @@
37
37
  "access": "public"
38
38
  },
39
39
  "dependencies": {
40
- "@ckb-ccc/ccc": "0.0.4",
40
+ "@ckb-ccc/ccc": "0.0.5-alpha.1",
41
41
  "lit": "^3.1.3"
42
42
  },
43
- "gitHead": "76485b6b76ce3c97d5acebd42decbafd546aa433"
43
+ "gitHead": "98d6d902fff0cc3d65f536cb85b32c867045d15d"
44
44
  }
@@ -0,0 +1,5 @@
1
+ import { encodeSvgToImgSrc } from "../utils";
2
+
3
+ export const CKB_SVG = encodeSvgToImgSrc(
4
+ '<svg width="668" height="666.66669" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"><polygon points="170.265,206.318 223.416,206.318 223.416,93.897 264.161,93.897 170.265,0 " transform="matrix(1.8256046,0,0,1.8256046,-166.4037,144.47964)" /><polygon points="324.79,112.422 284.046,112.422 377.941,206.318 377.941,0 324.79,0 " transform="matrix(1.8256046,0,0,1.8256046,-166.4037,144.47964)" /></svg>',
5
+ );
@@ -1,2 +1,3 @@
1
1
  export * from "./btc.svg";
2
+ export * from "./ckb.svg";
2
3
  export * from "./eth.svg";
@@ -0,0 +1,5 @@
1
+ import { encodeSvgToImgSrc } from "./utils";
2
+
3
+ export const JOY_ID_SVG = encodeSvgToImgSrc(
4
+ '<svg xmlns="http://www.w3.org/2000/svg" width="420" height="420" viewBox="0 0 420 420" fill="none"><circle cx="210" cy="210" r="210" fill="#333333"/><path d="M271.127 204.419C279.096 204.419 285.555 197.959 285.555 189.991C285.555 182.022 279.096 175.562 271.127 175.562C263.159 175.562 256.699 182.022 256.699 189.991C256.699 197.959 263.159 204.419 271.127 204.419Z" fill="#8CDD00"/><path d="M173.995 175.562C166.773 175.562 160.91 181.425 160.91 188.648C160.91 195.87 166.773 201.733 173.995 201.733C181.218 201.733 187.081 195.87 187.081 188.648C187.064 181.425 181.218 175.562 173.995 175.562Z" fill="#8CDD00"/><path d="M213.43 164.836L198.969 233.586C197.626 240.006 191.878 244.657 185.327 244.657C181.086 244.657 177.139 242.757 174.47 239.465C172.39 236.894 171.342 233.734 171.391 230.491L145.27 237.238C146.383 244.084 149.2 250.618 153.687 256.203C161.434 265.816 172.963 271.335 185.311 271.335C204.407 271.335 221.111 257.775 225.041 239.089L240.665 164.852H213.43V164.836Z" fill="#C1C1C1"/><path d="M335.83 115.983C327.068 105.19 314.065 99 300.161 99H267.981L262.363 125.662H300.161C305.991 125.662 311.445 128.249 315.113 132.786C318.782 137.306 320.207 143.185 319.011 148.884L313.394 175.562H340.645L345.116 154.387C347.965 140.778 344.592 126.775 335.83 115.983Z" fill="#8CDD00"/><path d="M295.216 261.999C291.285 280.669 274.597 294.212 255.518 294.212H226.875L221.258 320.874H255.518C287.126 320.874 314.803 298.421 321.304 267.485L326.021 245.049H298.77L295.216 261.999Z" fill="#8CDD00"/><path d="M98.8061 152.39L93.9258 175.58H121.177L124.894 157.892C128.825 139.223 145.513 125.679 164.592 125.679H192.04L197.657 99.0176H164.592C132.985 99.0012 105.308 121.454 98.8061 152.39Z" fill="#8CDD00"/><path d="M104.998 287.072C101.33 282.552 99.9049 276.673 101.1 270.974L106.079 247.342L77.2555 254.777L74.9956 265.487C72.1296 279.097 75.5196 293.099 84.2813 303.891C93.0429 314.684 106.046 320.874 119.95 320.874H150.935L156.553 294.212H119.95C114.12 294.196 108.666 291.608 104.998 287.072Z" fill="#8CDD00"/></svg>',
5
+ );
@@ -0,0 +1,5 @@
1
+ import { encodeSvgToImgSrc } from "./utils";
2
+
3
+ export const LEFT_SVG = encodeSvgToImgSrc(
4
+ '<svg width="8" height="14" viewBox="0 0 8 14" xmlns="http://www.w3.org/2000/svg"><path d="M6.74554 13.5C6.54646 13.5 6.35454 13.4177 6.21275 13.2695L0.720203 7.55253C0.426599 7.24573 0.426599 6.75035 0.720203 6.44355L6.21275 0.725059C6.50779 0.422747 6.98185 0.42574 7.27402 0.729549C7.5662 1.03485 7.56763 1.52723 7.27832 1.83404L2.31999 6.99729L7.27975 12.162C7.49459 12.3865 7.55904 12.7233 7.44303 13.0166C7.32415 13.3084 7.0506 13.5 6.74554 13.5Z" stroke="#1E1E1E" stroke-width="1"/></svg>',
5
+ );
@@ -0,0 +1,5 @@
1
+ import { encodeSvgToImgSrc } from "./utils";
2
+
3
+ export const METAMASK_SVG = encodeSvgToImgSrc(
4
+ `<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" id="Layer_1" x="0" y="0" version="1.1" viewBox="0 0 318.6 318.6"><style>.st1,.st6{fill:#e4761b;stroke:#e4761b;stroke-linecap:round;stroke-linejoin:round}.st6{fill:#f6851b;stroke:#f6851b}</style><path fill="#e2761b" stroke="#e2761b" stroke-linecap="round" stroke-linejoin="round" d="m274.1 35.5-99.5 73.9L193 65.8z"/><path d="m44.4 35.5 98.7 74.6-17.5-44.3zm193.9 171.3-26.5 40.6 56.7 15.6 16.3-55.3zm-204.4.9L50.1 263l56.7-15.6-26.5-40.6z" class="st1"/><path d="m103.6 138.2-15.8 23.9 56.3 2.5-2-60.5zm111.3 0-39-34.8-1.3 61.2 56.2-2.5zM106.8 247.4l33.8-16.5-29.2-22.8zm71.1-16.5 33.9 16.5-4.7-39.3z" class="st1"/><path fill="#d7c1b3" stroke="#d7c1b3" stroke-linecap="round" stroke-linejoin="round" d="m211.8 247.4-33.9-16.5 2.7 22.1-.3 9.3zm-105 0 31.5 14.9-.2-9.3 2.5-22.1z"/><path fill="#233447" stroke="#233447" stroke-linecap="round" stroke-linejoin="round" d="m138.8 193.5-28.2-8.3 19.9-9.1zm40.9 0 8.3-17.4 20 9.1z"/><path fill="#cd6116" stroke="#cd6116" stroke-linecap="round" stroke-linejoin="round" d="m106.8 247.4 4.8-40.6-31.3.9zM207 206.8l4.8 40.6 26.5-39.7zm23.8-44.7-56.2 2.5 5.2 28.9 8.3-17.4 20 9.1zm-120.2 23.1 20-9.1 8.2 17.4 5.3-28.9-56.3-2.5z"/><path fill="#e4751f" stroke="#e4751f" stroke-linecap="round" stroke-linejoin="round" d="m87.8 162.1 23.6 46-.8-22.9zm120.3 23.1-1 22.9 23.7-46zm-64-20.6-5.3 28.9 6.6 34.1 1.5-44.9zm30.5 0-2.7 18 1.2 45 6.7-34.1z"/><path d="m179.8 193.5-6.7 34.1 4.8 3.3 29.2-22.8 1-22.9zm-69.2-8.3.8 22.9 29.2 22.8 4.8-3.3-6.6-34.1z" class="st6"/><path fill="#c0ad9e" stroke="#c0ad9e" stroke-linecap="round" stroke-linejoin="round" d="m180.3 262.3.3-9.3-2.5-2.2h-37.7l-2.3 2.2.2 9.3-31.5-14.9 11 9 22.3 15.5h38.3l22.4-15.5 11-9z"/><path fill="#161616" stroke="#161616" stroke-linecap="round" stroke-linejoin="round" d="m177.9 230.9-4.8-3.3h-27.7l-4.8 3.3-2.5 22.1 2.3-2.2h37.7l2.5 2.2z"/><path fill="#763d16" stroke="#763d16" stroke-linecap="round" stroke-linejoin="round" d="m278.3 114.2 8.5-40.8-12.7-37.9-96.2 71.4 37 31.3 52.3 15.3 11.6-13.5-5-3.6 8-7.3-6.2-4.8 8-6.1zM31.8 73.4l8.5 40.8-5.4 4 8 6.1-6.1 4.8 8 7.3-5 3.6 11.5 13.5 52.3-15.3 37-31.3-96.2-71.4z"/><path d="m267.2 153.5-52.3-15.3 15.9 23.9-23.7 46 31.2-.4h46.5zm-163.6-15.3-52.3 15.3-17.4 54.2h46.4l31.1.4-23.6-46zm71 26.4 3.3-57.7 15.2-41.1h-67.5l15 41.1 3.5 57.7 1.2 18.2.1 44.8h27.7l.2-44.8z" class="st6"/><script xmlns=""/></svg>`,
5
+ );
@@ -1,7 +1,10 @@
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";
6
+ import { JOY_ID_SVG } from "../assets/joy-id.svg";
7
+ import { LEFT_SVG } from "../assets/left.svg";
5
8
  import { OKX_SVG } from "../assets/okx.svg";
6
9
  import { UNI_SAT_SVG } from "../assets/uni-sat.svg";
7
10
  import { WillUpdateEvent } from "../events";
@@ -12,6 +15,13 @@ import {
12
15
  } from "../scenes";
13
16
  import { WalletWithSigners } from "../types";
14
17
 
18
+ enum Scene {
19
+ SelectingWallets = "SelectingWallets",
20
+ SelectingSigners = "SelectingSigners",
21
+ Connecting = "Connecting",
22
+ Connected = "Connected",
23
+ }
24
+
15
25
  @customElement("ccc-connector")
16
26
  export class WebComponentConnector extends LitElement {
17
27
  @state()
@@ -25,6 +35,11 @@ export class WebComponentConnector extends LitElement {
25
35
  this.isOpen = isOpen;
26
36
  }
27
37
 
38
+ @property()
39
+ public name?: string;
40
+ @property()
41
+ public icon?: string;
42
+
28
43
  @property()
29
44
  public client: ccc.Client = new ccc.ClientPublicTestnet();
30
45
  public setClient(client: ccc.Client) {
@@ -32,68 +47,49 @@ export class WebComponentConnector extends LitElement {
32
47
  }
33
48
 
34
49
  @state()
35
- private walletName?: string;
36
- @state()
37
- private signerType?: ccc.SignerType;
50
+ private scene: Scene = Scene.SelectingWallets;
38
51
  @state()
39
52
  private selectedWallet?: WalletWithSigners;
40
- private updateWallet() {
41
- this.selectedWallet = this.wallets.find(
42
- (wallet) => this.walletName === wallet.name,
43
- );
44
- }
45
53
  @state()
46
54
  private selectedSigner?: ccc.SignerInfo;
47
- private updateSigner() {
48
- this.selectedSigner = this.selectedWallet?.signers.find(
49
- ({ type }) => type === this.signerType,
50
- );
51
- }
55
+
52
56
  @state()
53
- public wallet?: WalletWithSigners;
57
+ private walletName?: string;
58
+ @state()
59
+ private signerName?: string;
60
+ @state()
61
+ public wallet?: ccc.Wallet;
54
62
  @state()
55
63
  public signer?: ccc.SignerInfo;
56
- private canConnect = false;
57
64
  private prepareSigner() {
58
65
  (async () => {
59
- if (!this.selectedSigner) {
60
- this.wallet = undefined;
61
- this.signer = undefined;
66
+ if (this.signer && (await this.signer.signer.isConnected())) {
67
+ this.scene = Scene.Connected;
62
68
  return;
63
69
  }
64
70
 
65
- if (!(await this.selectedSigner.signer.isConnected())) {
66
- if (!this.canConnect) {
67
- this.disconnect();
68
- return;
69
- }
70
- await this.selectedSigner.signer.connect();
71
- }
72
-
73
- this.saveConnection();
74
- this.wallet = this.selectedWallet;
75
- this.signer = this.selectedSigner;
76
- this.closedHandler();
71
+ this.wallet = undefined;
72
+ this.signer = undefined;
73
+ this.scene = Scene.SelectingWallets;
77
74
  })();
78
75
  }
79
76
 
80
77
  public disconnect() {
78
+ this.signer?.signer?.disconnect();
81
79
  this.walletName = undefined;
82
- this.wallet = undefined;
83
- this.signerType = undefined;
84
- this.signer = undefined;
80
+ this.signerName = undefined;
85
81
  this.saveConnection();
86
82
  }
87
83
 
88
84
  private loadConnection() {
89
85
  const {
90
- signerType,
86
+ signerName,
91
87
  walletName,
92
- }: { signerType?: ccc.SignerType; walletName?: string } = JSON.parse(
88
+ }: { signerName?: string; walletName?: string } = JSON.parse(
93
89
  window.localStorage.getItem("ccc-connection-info") ?? "{}",
94
90
  );
95
91
 
96
- this.signerType = signerType;
92
+ this.signerName = signerName;
97
93
  this.walletName = walletName;
98
94
  }
99
95
 
@@ -101,7 +97,7 @@ export class WebComponentConnector extends LitElement {
101
97
  window.localStorage.setItem(
102
98
  "ccc-connection-info",
103
99
  JSON.stringify({
104
- signerType: this.signerType,
100
+ signerName: this.signerName,
105
101
  walletName: this.walletName,
106
102
  }),
107
103
  );
@@ -121,15 +117,18 @@ export class WebComponentConnector extends LitElement {
121
117
  changedProperties.has("walletName") ||
122
118
  changedProperties.has("wallets")
123
119
  ) {
124
- this.updateWallet();
120
+ this.wallet = this.wallets.find(({ name }) => name === this.walletName);
125
121
  }
126
122
  if (
127
- changedProperties.has("signerType") ||
128
- changedProperties.has("selectedWallet")
123
+ changedProperties.has("signerName") ||
124
+ changedProperties.has("wallet")
129
125
  ) {
130
- this.updateSigner();
126
+ const wallet = this.wallets.find(({ name }) => name === this.walletName);
127
+ this.signer = wallet?.signers.find(
128
+ ({ name }) => name === this.signerName,
129
+ );
131
130
  }
132
- if (changedProperties.has("selectedSigner")) {
131
+ if (changedProperties.has("signer")) {
133
132
  this.prepareSigner();
134
133
  }
135
134
 
@@ -140,35 +139,47 @@ export class WebComponentConnector extends LitElement {
140
139
  this.wallets = [];
141
140
 
142
141
  (async () => {
143
- if (!this.selectedSigner) {
142
+ if (!this.signer) {
144
143
  return;
145
144
  }
146
145
 
147
- const newSigner = await this.selectedSigner.signer.replaceClient(
148
- this.client,
149
- );
150
- if (newSigner) {
151
- this.selectedSigner = {
152
- ...this.selectedSigner,
153
- signer: newSigner,
154
- };
155
- } else {
156
- this.disconnect();
157
- }
146
+ this.signer = {
147
+ ...this.signer,
148
+ signer: await this.signer.signer.replaceClient(this.client),
149
+ };
158
150
  })();
159
151
 
160
152
  this.resetListeners.forEach((listener) => listener());
161
153
  this.resetListeners = [];
154
+ const name =
155
+ this.name ??
156
+ (document.querySelector("head title") as HTMLTitleElement).text;
157
+ const icon =
158
+ this.icon ??
159
+ (document.querySelector('link[rel="icon"]') as HTMLLinkElement).href;
160
+
161
+ ccc.JoyId.getJoyIdSigners(this.client, name, icon).forEach(
162
+ ({ signer, type, name }) => {
163
+ this.addSigner("JoyID", name, JOY_ID_SVG, type, signer);
164
+ },
165
+ );
162
166
 
163
167
  const uniSatSigner = ccc.UniSat.getUniSatSigner(this.client);
164
168
  if (uniSatSigner) {
165
- this.addSigner("UniSat", UNI_SAT_SVG, ccc.SignerType.BTC, uniSatSigner);
169
+ this.addSigner(
170
+ "UniSat",
171
+ "BTC",
172
+ UNI_SAT_SVG,
173
+ ccc.SignerType.BTC,
174
+ uniSatSigner,
175
+ );
166
176
  }
167
177
 
168
178
  const okxBitcoinSigner = ccc.Okx.getOKXBitcoinSigner(this.client);
169
179
  if (okxBitcoinSigner) {
170
180
  this.addSigner(
171
181
  "OKX Wallet",
182
+ "BTC",
172
183
  OKX_SVG,
173
184
  ccc.SignerType.BTC,
174
185
  okxBitcoinSigner,
@@ -180,6 +191,7 @@ export class WebComponentConnector extends LitElement {
180
191
  eip6963Manager.subscribeSigners((signer) => {
181
192
  this.addSigner(
182
193
  `${signer.detail.info.name}`,
194
+ "EVM",
183
195
  signer.detail.info.icon,
184
196
  ccc.SignerType.EVM,
185
197
  signer,
@@ -189,45 +201,53 @@ export class WebComponentConnector extends LitElement {
189
201
  }
190
202
 
191
203
  private addSigner(
192
- name: string,
204
+ walletName: string,
205
+ signerName: string,
193
206
  icon: string,
194
207
  type: ccc.SignerType,
195
208
  signer: ccc.Signer,
196
209
  ) {
197
210
  let updated = false;
198
211
  const wallets = this.wallets.map((wallet) => {
199
- if (wallet.name !== name) {
212
+ if (wallet.name !== walletName) {
200
213
  return wallet;
201
214
  }
202
215
 
203
216
  updated = true;
204
217
  return {
205
218
  ...wallet,
206
- signers: [...wallet.signers, { type, signer }],
219
+ signers: [...wallet.signers, { type, name: signerName, signer }],
207
220
  };
208
221
  });
209
222
 
210
223
  if (!updated) {
211
224
  wallets.push({
212
- name,
225
+ name: walletName,
213
226
  icon,
214
- signers: [{ type, signer }],
227
+ signers: [{ type, name: signerName, signer }],
215
228
  });
216
229
  }
217
230
 
218
231
  this.wallets = wallets;
219
232
  }
220
233
 
234
+ mainRef: Ref<HTMLDivElement> = createRef();
235
+ headerRef: Ref<HTMLDivElement> = createRef();
236
+ bodyRef: Ref<HTMLDivElement> = createRef();
237
+
221
238
  render() {
222
239
  const [title, body] = (() => {
223
- if (!this.selectedWallet) {
240
+ if (this.scene === Scene.SelectingWallets || !this.selectedWallet) {
224
241
  return generateWalletsScene(
225
242
  this.wallets,
226
- this.signerSelectedHandler,
243
+ (wallet) => {
244
+ this.selectedWallet = wallet;
245
+ this.scene = Scene.SelectingSigners;
246
+ },
227
247
  this.signerSelectedHandler,
228
248
  );
229
249
  }
230
- if (!this.selectedSigner) {
250
+ if (this.scene === Scene.SelectingSigners || !this.selectedSigner) {
231
251
  return generateSignersScene(
232
252
  this.selectedWallet,
233
253
  this.signerSelectedHandler,
@@ -240,6 +260,10 @@ export class WebComponentConnector extends LitElement {
240
260
  );
241
261
  })();
242
262
 
263
+ const canBack = [Scene.SelectingSigners, Scene.Connecting].includes(
264
+ this.scene,
265
+ );
266
+
243
267
  return html`<style>
244
268
  :host {
245
269
  ${this.isOpen ? "" : "display: none;"}
@@ -248,7 +272,6 @@ export class WebComponentConnector extends LitElement {
248
272
  --btn-primary: #f8f8f8;
249
273
  --btn-primary-hover: #efeeee;
250
274
  --btn-secondary: #ddd;
251
- --btn-icon: #e9e4de;
252
275
  color: #1e1e1e;
253
276
  --tip-color: #666;
254
277
  }
@@ -261,31 +284,74 @@ export class WebComponentConnector extends LitElement {
261
284
  }
262
285
  }}
263
286
  >
264
- <div class="main">
265
- <div class="header text-bold fs-big">
266
- <div class="back"></div>
287
+ <div class="main" ${ref(this.mainRef)}>
288
+ <div class="header text-bold fs-big" ${ref(this.headerRef)}>
289
+ <img
290
+ class="back ${canBack ? "active" : ""}"
291
+ src=${LEFT_SVG}
292
+ @click=${() => {
293
+ if (this.scene === Scene.Connecting) {
294
+ this.scene = Scene.SelectingSigners;
295
+ } else if (this.scene === Scene.SelectingSigners) {
296
+ this.scene = Scene.SelectingWallets;
297
+ }
298
+ }}
299
+ />
267
300
  ${title}
268
- <img class="close" src=${CLOSE_SVG} @click=${this.closedHandler} />
301
+ <img
302
+ class="close active"
303
+ src=${CLOSE_SVG}
304
+ @click=${this.closedHandler}
305
+ />
269
306
  </div>
270
- <div class="body">${body}</div>
307
+ <div class="body" ${ref(this.bodyRef)}>${body}</div>
271
308
  </div>
272
309
  </div>`;
273
310
  }
274
311
 
312
+ updated() {
313
+ if (!this.mainRef.value) {
314
+ return;
315
+ }
316
+ this.mainRef.value.style.height = `${
317
+ (this.bodyRef.value?.clientHeight ?? 0) +
318
+ (this.headerRef.value?.clientHeight ?? 0)
319
+ }px`;
320
+ }
321
+
275
322
  private closedHandler = () => {
276
- if (this.signer === undefined) {
277
- this.disconnect();
323
+ if (
324
+ [
325
+ Scene.SelectingSigners,
326
+ Scene.SelectingWallets,
327
+ Scene.Connecting,
328
+ ].includes(this.scene)
329
+ ) {
330
+ this.scene = Scene.SelectingWallets;
331
+ this.selectedSigner = undefined;
332
+ this.selectedWallet = undefined;
278
333
  }
279
334
  this.isOpen = false;
280
335
  };
281
336
 
282
337
  private signerSelectedHandler = (
283
- wallet?: ccc.Wallet,
284
- signer?: ccc.SignerInfo,
338
+ wallet: WalletWithSigners,
339
+ signer: ccc.SignerInfo,
285
340
  ) => {
286
- this.walletName = wallet?.name;
287
- this.signerType = signer?.type;
288
- this.canConnect = true;
341
+ this.scene = Scene.Connecting;
342
+ this.selectedWallet = wallet;
343
+ this.selectedSigner = signer;
344
+ (async () => {
345
+ await signer.signer.connect();
346
+ if (!(await signer.signer.isConnected())) {
347
+ return;
348
+ }
349
+ this.scene = Scene.Connected;
350
+ this.walletName = wallet.name;
351
+ this.signerName = signer.name;
352
+ this.saveConnection();
353
+ this.closedHandler();
354
+ })();
289
355
  };
290
356
 
291
357
  static styles = css`
@@ -345,6 +411,8 @@ export class WebComponentConnector extends LitElement {
345
411
  transform: translate(-50%, -50%);
346
412
  background: var(--background);
347
413
  border-radius: 1.2rem;
414
+ overflow: hidden;
415
+ transition: height 0.15s ease-out;
348
416
  }
349
417
 
350
418
  .header {
@@ -359,6 +427,13 @@ export class WebComponentConnector extends LitElement {
359
427
  .back {
360
428
  width: 0.8rem;
361
429
  height: 0.8rem;
430
+ opacity: 0;
431
+ transition: opacity 0.15s ease-in-out;
432
+ }
433
+
434
+ .close.active,
435
+ .back.active {
436
+ opacity: 1;
362
437
  cursor: pointer;
363
438
  }
364
439
 
@@ -378,7 +453,7 @@ export class WebComponentConnector extends LitElement {
378
453
  padding: 0.75rem 1rem;
379
454
  background: var(--btn-primary);
380
455
  border-radius: 0.4rem;
381
- transition: background 0.3s ease-in-out;
456
+ transition: background 0.15s ease-in-out;
382
457
  }
383
458
 
384
459
  .btn-primary img {
@@ -386,7 +461,6 @@ export class WebComponentConnector extends LitElement {
386
461
  height: 2rem;
387
462
  margin-right: 1rem;
388
463
  border-radius: 0.4rem;
389
- background: var(--btn-icon);
390
464
  }
391
465
 
392
466
  .btn-primary:hover {
@@ -399,7 +473,7 @@ export class WebComponentConnector extends LitElement {
399
473
  padding: 0.25rem 1rem;
400
474
  background: var(--btn-secondary);
401
475
  border-radius: 9999px;
402
- transition: background 0.3s ease-in-out;
476
+ transition: background 0.15s ease-in-out;
403
477
  }
404
478
 
405
479
  .btn-secondary img {
@@ -413,7 +487,6 @@ export class WebComponentConnector extends LitElement {
413
487
  height: 4rem;
414
488
  margin-bottom: 0.5rem;
415
489
  border-radius: 0.8rem;
416
- background: var(--btn-icon);
417
490
  }
418
491
 
419
492
  .connecting-wallet-icon {
@@ -1,12 +1,13 @@
1
1
  import { ccc } from "@ckb-ccc/ccc";
2
2
  import { html } from "lit";
3
3
  import { RETRY_SVG } from "../assets/retry.svg";
4
+ import { WalletWithSigners } from "../types";
4
5
 
5
6
  export function generateConnectingScene(
6
- wallet: ccc.Wallet,
7
+ wallet: WalletWithSigners,
7
8
  signer: ccc.SignerInfo,
8
9
  onSignerSelected: (
9
- wallet: ccc.Wallet | undefined,
10
+ wallet: WalletWithSigners,
10
11
  signer: ccc.SignerInfo,
11
12
  ) => unknown,
12
13
  ) {
@@ -1,20 +1,21 @@
1
1
  import { ccc } from "@ckb-ccc/ccc";
2
2
  import { html } from "lit";
3
3
  import { repeat } from "lit/directives/repeat.js";
4
- import { BTC_SVG, ETH_SVG } from "../assets/chains";
4
+ import { BTC_SVG, CKB_SVG, ETH_SVG } from "../assets/chains";
5
5
  import { WalletWithSigners } from "../types";
6
6
 
7
7
  export function signerTypeToIcon(type: ccc.SignerType): string {
8
8
  return {
9
9
  [ccc.SignerType.BTC]: BTC_SVG,
10
10
  [ccc.SignerType.EVM]: ETH_SVG,
11
+ [ccc.SignerType.CKB]: CKB_SVG,
11
12
  }[type];
12
13
  }
13
14
 
14
15
  export function generateSignersScene(
15
16
  wallet: WalletWithSigners,
16
17
  onSignerSelected: (
17
- wallet: ccc.Wallet | undefined,
18
+ wallet: WalletWithSigners,
18
19
  signer: ccc.SignerInfo,
19
20
  ) => unknown,
20
21
  ) {
@@ -35,7 +36,7 @@ export function generateSignersScene(
35
36
  }}
36
37
  >
37
38
  <img src=${signerTypeToIcon(signer.type)} alt=${signer.type} />
38
- ${signer.type}
39
+ ${signer.name}
39
40
  </button>
40
41
  `,
41
42
  )}
@@ -1,33 +1,79 @@
1
1
  import { ccc } from "@ckb-ccc/ccc";
2
2
  import { html } from "lit";
3
3
  import { repeat } from "lit/directives/repeat.js";
4
- import { WalletWithSigners } from "../types";
4
+ import { METAMASK_SVG } from "../assets/metamask.svg";
5
+ import { OKX_SVG } from "../assets/okx.svg";
6
+ import { UNI_SAT_SVG } from "../assets/uni-sat.svg";
7
+ import { WalletInfo, WalletWithSigners } from "../types";
5
8
 
6
9
  export function generateWalletsScene(
7
10
  wallets: WalletWithSigners[],
8
- onWalletSelected: (wallet: ccc.Wallet) => unknown,
9
- onSignerSelected: (wallet: ccc.Wallet, signer: ccc.SignerInfo) => unknown,
11
+ onWalletSelected: (wallet: WalletWithSigners) => unknown,
12
+ onSignerSelected: (
13
+ wallet: WalletWithSigners,
14
+ signer: ccc.SignerInfo,
15
+ ) => unknown,
10
16
  ) {
17
+ const recommendedWallets = [
18
+ {
19
+ name: "MetaMask",
20
+ icon: METAMASK_SVG,
21
+ downloadLink: `https://metamask.app.link/dapp/${window.location.href}`,
22
+ },
23
+ {
24
+ name: "OKX Wallet",
25
+ icon: OKX_SVG,
26
+ downloadLink: "https://www.okx.com/zh-hans/download",
27
+ },
28
+ {
29
+ name: "UniSat",
30
+ icon: UNI_SAT_SVG,
31
+ downloadLink: "https://unisat.io/",
32
+ },
33
+ ];
34
+
35
+ const missingWallets = recommendedWallets.filter(
36
+ (recommendedWallet) =>
37
+ !wallets.some((wallet) => wallet.name === recommendedWallet.name),
38
+ );
39
+
40
+ const additionalButtons = missingWallets.map(
41
+ (wallet: WalletInfo) => html`
42
+ <button
43
+ class="btn-primary mb-1"
44
+ @click=${() => {
45
+ window.open(wallet.downloadLink, "_blank");
46
+ }}
47
+ >
48
+ <img src=${wallet.icon} alt=${wallet.name} />
49
+ ${wallet.name}
50
+ </button>
51
+ `,
52
+ );
53
+
11
54
  return [
12
55
  "Connect Wallet",
13
- repeat(
14
- wallets,
15
- (wallet) => wallet.name,
16
- (wallet) => html`
17
- <button
18
- class="btn-primary mb-1"
19
- @click=${async () => {
20
- if (wallet.signers.length === 1) {
21
- onSignerSelected(wallet, wallet.signers[0]);
22
- } else {
23
- onWalletSelected(wallet);
24
- }
25
- }}
26
- >
27
- <img src=${wallet.icon} alt=${wallet.name} />
28
- ${wallet.name}
29
- </button>
30
- `,
31
- ),
56
+ html`
57
+ ${repeat(
58
+ wallets,
59
+ (wallet) => wallet.name,
60
+ (wallet) => html`
61
+ <button
62
+ class="btn-primary mb-1"
63
+ @click=${async () => {
64
+ if (wallet.signers.length === 1) {
65
+ onSignerSelected(wallet, wallet.signers[0]);
66
+ } else {
67
+ onWalletSelected(wallet);
68
+ }
69
+ }}
70
+ >
71
+ <img src=${wallet.icon} alt=${wallet.name} />
72
+ ${wallet.name}
73
+ </button>
74
+ `,
75
+ )}
76
+ ${additionalButtons}
77
+ `,
32
78
  ];
33
79
  }