Skip to content

Commit 69e9b31

Browse files
committed
feat: events
1 parent b682672 commit 69e9b31

File tree

8 files changed

+158
-37
lines changed

8 files changed

+158
-37
lines changed

packages/neuron-ui/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
"@nervosnetwork/ckb-sdk-core": "0.109.0",
5454
"@nervosnetwork/ckb-sdk-utils": "0.109.0",
5555
"canvg": "2.0.0",
56-
"ckb-walletconnect-wallet-sdk": "0.0.1-alpha.9",
56+
"ckb-walletconnect-wallet-sdk": "0.0.1-alpha.10",
5757
"i18next": "21.10.0",
5858
"immer": "9.0.21",
5959
"jsqr": "1.4.0",

packages/neuron-ui/src/components/CameraScanDialog/index.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React, { useEffect, useRef, useCallback, useState } from 'react'
22
import { useTranslation } from 'react-i18next'
33
import { askForCameraAccess } from 'services/remote'
44
import Dialog from 'widgets/Dialog'
5+
import LoadingDialog from 'widgets/LoadingDialog'
56
import AlertDialog from 'widgets/AlertDialog'
67
import { isSuccessResponse } from 'utils'
78
import jsQR from 'jsqr'
@@ -20,7 +21,7 @@ const CameraScanDialog = ({ close, onConfirm }: { close: () => void; onConfirm:
2021
const videoRef = useRef<HTMLVideoElement>()
2122
const canvasRef = useRef<HTMLCanvasElement>(null)
2223
const canvas2dRef = useRef<CanvasRenderingContext2D>()
23-
const [dialogType, setDialogType] = useState<'' | 'no-camera' | 'access-fail' | 'scan'>('')
24+
const [dialogType, setDialogType] = useState<'' | 'opening' | 'access-fail' | 'scan'>('')
2425

2526
const drawLine = (begin: Point, end: Point) => {
2627
if (!canvas2dRef.current) return
@@ -60,6 +61,7 @@ const CameraScanDialog = ({ close, onConfirm }: { close: () => void; onConfirm:
6061

6162
askForCameraAccess().then(accessRes => {
6263
if (isSuccessResponse(accessRes)) {
64+
setDialogType('opening')
6365
navigator.mediaDevices
6466
.getUserMedia({
6567
audio: false,
@@ -105,6 +107,8 @@ const CameraScanDialog = ({ close, onConfirm }: { close: () => void; onConfirm:
105107
</div>
106108
</Dialog>
107109

110+
<LoadingDialog show={dialogType === 'opening'} message={t('wallet-connect.camera-connecting')} />
111+
108112
<AlertDialog
109113
show={dialogType === 'access-fail'}
110114
title={t('wallet-connect.camera-fail')}

packages/neuron-ui/src/components/WalletConnect/hooks.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useCallback } from 'react'
1+
import { useCallback, useMemo } from 'react'
22
import { useState as useGlobalState } from 'states'
33
import { connect, disconnect, approveSession, rejectSession, approveRequest, rejectRequest } from 'services/remote'
44
import { ControllerResponse } from 'services/remote/remoteApiWrapper'
@@ -53,7 +53,7 @@ export const useWalletConnect = () => {
5353
[requests]
5454
)
5555

56-
const userName = `${identity.slice(0, 6)}...${identity.slice(-6)}`
56+
const userName = useMemo(() => `${identity.slice(0, 6)}...${identity.slice(-6)}`, [identity])
5757

5858
return {
5959
proposals,

packages/neuron-ui/src/locales/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,6 +1146,7 @@
11461146
"scan-qrcode": "Scan the QR code in the screen",
11471147
"no-camera-tip": "Don't have a camera? Use the uri to connect",
11481148
"camera-fail": "Unable to acquire camera data",
1149+
"camera-connecting": "Connecting Camera...",
11491150
"camera-msg": "Please check that the settings allow Neuron to access the camera",
11501151
"screen-fail": "Unable to get screen data",
11511152
"screen-msg": "Please check that the settings allow Neuron to access the screen",

packages/neuron-ui/src/locales/zh-tw.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,6 +1117,7 @@
11171117
"scan-qrcode": "掃描屏幕二維碼",
11181118
"no-camera-tip": "沒有攝像頭?使用連結碼連結",
11191119
"camera-fail": "無法獲取攝像頭數據",
1120+
"camera-connecting": "正在連結攝像頭",
11201121
"camera-msg": "請檢查設置是否允許Neuron訪問攝像頭",
11211122
"screen-fail": "無法獲取屏幕數據",
11221123
"screen-msg": "請檢查設置是否允許Neuron訪問屏幕",

packages/neuron-ui/src/locales/zh.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,6 +1138,7 @@
11381138
"scan-qrcode": "扫描屏幕二维码",
11391139
"no-camera-tip": "没有摄像头?使用连接码连接",
11401140
"camera-fail": "无法获取摄像头数据",
1141+
"camera-connecting": "正在连接摄像头",
11411142
"camera-msg": "请检查设置是否允许Neuron访问摄像头",
11421143
"screen-fail": "无法获取屏幕数据",
11431144
"screen-msg": "请检查设置是否允许Neuron访问屏幕",

packages/neuron-wallet/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
"async": "3.2.4",
5858
"bn.js": "4.12.0",
5959
"chalk": "3.0.0",
60-
"ckb-walletconnect-wallet-sdk": "0.0.1-alpha.9",
60+
"ckb-walletconnect-wallet-sdk": "0.0.1-alpha.10",
6161
"dotenv": "8.6.0",
6262
"electron-log": "4.4.8",
6363
"electron-updater": "4.6.5",

packages/neuron-wallet/src/controllers/wallet-connect.ts

Lines changed: 146 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@ import {
1313
Session,
1414
SessionRequest,
1515
SignedTransaction,
16-
Chain,
1716
} from 'ckb-walletconnect-wallet-sdk'
1817
import WalletConnectSubject from '../models/subjects/wallet-connect-subject'
1918
import { CurrentWalletSubject } from '../models/subjects/wallets'
2019
import { CurrentNetworkIDSubject } from '../models/subjects/networks'
2120
import { AccountExtendedPublicKey } from '../models/keys/key'
21+
import { Address as AddressInterface } from '../models/address'
2222
import { AddressType } from '../models/keys/address'
23+
import TxDbChangedSubject from '../models/subjects/tx-db-changed-subject'
24+
import AddressDbChangedSubject from '../models/subjects/address-db-changed-subject'
2325
import logger from '../utils/logger'
2426
import { ResponseCode } from '../utils/const'
2527
import WalletsService from '../services/wallets'
@@ -28,25 +30,57 @@ import AddressService from '../services/addresses'
2830

2931
class Adapter implements CKBWalletAdapter {
3032
private walletID: string = ''
33+
private extendedKey: AccountExtendedPublicKey
3134

32-
constructor(props: { walletID: string }) {
35+
constructor(props: { walletID: string; extendedKey: string }) {
3336
this.walletID = props.walletID
37+
this.extendedKey = AccountExtendedPublicKey.parse(props.extendedKey)
3438
}
3539

3640
public async ckb_getAddresses(params: GetAddressesParams): Promise<{
3741
[scriptBase: string]: Address[]
3842
}> {
3943
const scriptBaseList = Object.keys(params)
4044
if (scriptBaseList.length) {
41-
const addresses = (await AddressService.getAddressesByWalletId(this.walletID))
42-
.filter(item => item.addressType === AddressType.Receiving)
43-
.map(({ address, blake160: identifier, balance, description = '', addressIndex: index = '' }) => ({
45+
const { page, type } = params[scriptBaseList[0]]
46+
const { size = 10, before, after } = page
47+
let resList = [] as AddressInterface[]
48+
if (type === 'generate') {
49+
resList =
50+
(await AddressService.generateAndSaveForExtendedKey({
51+
walletId: this.walletID,
52+
extendedKey: this.extendedKey,
53+
receivingAddressCount: size,
54+
})) || []
55+
} else {
56+
const list = (await AddressService.getAddressesWithBalancesByWalletId(this.walletID)).filter(
57+
item => item.addressType === AddressType.Receiving
58+
)
59+
60+
if (before) {
61+
const beforeItem = list.find(item => item.address === before)
62+
if (beforeItem) {
63+
resList = list.filter(item => item.addressIndex < beforeItem.addressIndex).slice(-size)
64+
}
65+
} else if (after) {
66+
const afterItem = list.find(item => item.address === after)
67+
if (afterItem) {
68+
resList = list.filter(item => item.addressIndex > afterItem.addressIndex).slice(size)
69+
}
70+
} else {
71+
resList = list.slice(0, size)
72+
}
73+
}
74+
75+
const addresses = resList.map(
76+
({ address, blake160: identifier, balance, description = '', addressIndex: index = '' }) => ({
4477
address,
4578
identifier,
4679
description,
4780
balance: balance!,
4881
index,
49-
}))
82+
})
83+
)
5084
return Promise.resolve({
5185
[scriptBaseList[0]]: addresses,
5286
})
@@ -81,33 +115,45 @@ export default class WalletConnectController {
81115
private sessions: Session[] = []
82116
private requests: SessionRequest[] = []
83117

84-
private identity: string = ''
85-
private chain: Chain = 'devnet'
118+
private addresses: AddressInterface[] = []
86119

87-
private async init() {
120+
private getWallet() {
88121
const currentWallet = WalletsService.getInstance().getCurrent()
89-
const network = NetworksService.getInstance().getCurrent()
122+
if (currentWallet) {
123+
const { extendedKey, id } = currentWallet.toJSON()
124+
const identity = AccountExtendedPublicKey.parse(extendedKey).addressPublicKey(AddressType.Receiving, 0)
90125

91-
if (!currentWallet) {
92-
return
126+
return {
127+
identity,
128+
id,
129+
extendedKey,
130+
}
93131
}
132+
return {
133+
identity: '',
134+
}
135+
}
94136

95-
const { extendedKey, id } = currentWallet.toJSON()
96-
this.identity = AccountExtendedPublicKey.parse(extendedKey).addressPublicKey(AddressType.Receiving, 0)
97-
137+
private getNetwork() {
138+
const network = NetworksService.getInstance().getCurrent()
98139
switch (network?.chain) {
99140
case 'ckb':
100-
this.chain = 'mainnet'
101-
break
141+
return 'mainnet'
102142
case 'ckb_testnet':
103-
this.chain = 'testnet'
104-
break
143+
case 'light_client_testnet':
144+
return 'testnet'
105145
case 'ckb_dev':
106-
this.chain = 'devnet'
107-
break
146+
return 'devnet'
108147
default:
109-
this.chain = 'devnet'
110-
break
148+
return 'devnet'
149+
}
150+
}
151+
152+
private async init() {
153+
const wallet = this.getWallet()
154+
155+
if (!wallet.id) {
156+
return
111157
}
112158

113159
const core = new Core({
@@ -124,7 +170,8 @@ export default class WalletConnectController {
124170
description: 'Neuron Wallet is a CKB wallet produced by Nervos Foundation. ',
125171
},
126172
adapter: new Adapter({
127-
walletID: id,
173+
walletID: wallet.id,
174+
extendedKey: wallet.extendedKey,
128175
}),
129176
})
130177

@@ -143,23 +190,89 @@ export default class WalletConnectController {
143190
})
144191
}
145192

193+
private async updateAddresses(emitEvent: boolean = true) {
194+
const { id } = this.getWallet()
195+
if (id) {
196+
const list = await AddressService.getAddressesWithBalancesByWalletId(id)
197+
const receriveList = list.filter(item => item.addressType === AddressType.Receiving)
198+
199+
if (!this.addresses.length) {
200+
this.addresses = receriveList
201+
return
202+
}
203+
204+
if (receriveList.length > this.addresses.length) {
205+
const addresses = receriveList
206+
.slice(this.addresses.length)
207+
.map(({ address, blake160: identifier, balance, description = '', addressIndex: index = '' }) => ({
208+
address,
209+
identifier,
210+
description,
211+
balance: balance!,
212+
index,
213+
}))
214+
if (emitEvent) {
215+
WalletConnectController.client?.changeAddresses({
216+
addresses,
217+
changeType: 'add',
218+
})
219+
}
220+
} else if (receriveList.length === this.addresses.length) {
221+
const addresses = [] as Address[]
222+
receriveList.forEach((item, index) => {
223+
if (item.txCount && (this.addresses[index]?.txCount || 0) < item.txCount)
224+
addresses.push({
225+
address: item.address,
226+
identifier: item.blake160,
227+
description: item.description || '',
228+
balance: item.balance!,
229+
index,
230+
})
231+
})
232+
if (emitEvent) {
233+
WalletConnectController.client?.changeAddresses({
234+
addresses,
235+
changeType: 'consume',
236+
})
237+
}
238+
}
239+
this.addresses = receriveList
240+
}
241+
}
242+
146243
constructor() {
147244
this.init()
148245

149246
CurrentWalletSubject.pipe(debounceTime(50)).subscribe(async params => {
150247
if (params.currentWallet && WalletConnectController.client) {
151-
WalletConnectController.client.disconnectAllSessions()
152-
this.init()
248+
const { identity, id, extendedKey } = this.getWallet()
249+
if (id) {
250+
WalletConnectController.client.updateAdapter(new Adapter({ walletID: id, extendedKey }))
251+
WalletConnectController.client.changeAccount(identity)
252+
this.updateAddresses(false)
253+
this.notify()
254+
}
153255
}
154256
})
155257

156-
CurrentNetworkIDSubject.subscribe(async ({ currentNetworkID }) => {
157-
const currentNetwork = NetworksService.getInstance().get(currentNetworkID)
158-
if (currentNetwork && WalletConnectController.client) {
258+
CurrentNetworkIDSubject.subscribe(() => {
259+
if (WalletConnectController.client) {
159260
WalletConnectController.client.disconnectAllSessions()
160261
this.init()
161262
}
162263
})
264+
265+
TxDbChangedSubject.getSubject()
266+
.pipe(debounceTime(500))
267+
.subscribe(async () => {
268+
this.updateAddresses()
269+
})
270+
271+
AddressDbChangedSubject.getSubject()
272+
.pipe(debounceTime(200))
273+
.subscribe(async () => {
274+
this.updateAddresses()
275+
})
163276
}
164277

165278
public async connect(uri: string) {
@@ -183,10 +296,11 @@ export default class WalletConnectController {
183296
public async approveSession(params: { id: number; scriptBases: string[] }) {
184297
await WalletConnectController.client?.approve({
185298
id: params.id,
186-
chain: this.chain,
187-
identity: this.identity,
299+
network: this.getNetwork(),
300+
identity: this.getWallet().identity,
188301
scriptBases: params.scriptBases,
189302
} as ApproveParams)
303+
this.updateAddresses(false)
190304
return {
191305
status: ResponseCode.Success,
192306
}
@@ -218,7 +332,7 @@ export default class WalletConnectController {
218332
proposals: this.proposals,
219333
sessions: this.sessions,
220334
requests: this.requests,
221-
identity: this.identity,
335+
identity: this.getWallet().identity,
222336
})
223337
}
224338
}

0 commit comments

Comments
 (0)