From ddaa84e3baf0f3c25b3c5381469fec3449002a89 Mon Sep 17 00:00:00 2001 From: yanguoyu <841185308@qq.com> Date: Tue, 13 Dec 2022 19:55:26 +0800 Subject: [PATCH 01/52] feat: Upgrade electron to 22.0.0 --- packages/neuron-ui/package.json | 6 +- .../neuron-ui/src/components/Send/hooks.ts | 41 ---- .../neuron-ui/src/components/Send/index.tsx | 2 - .../src/components/SendFieldset/index.tsx | 15 -- packages/neuron-ui/src/electron-modules.tsx | 1 - .../neuron-ui/src/services/remote/index.ts | 84 +------ .../neuron-ui/src/types/global/index.d.ts | 1 - packages/neuron-wallet/package.json | 4 +- .../src/controllers/app/index.ts | 1 + .../src/controllers/app/preload.ts | 6 +- .../src/controllers/app/show-window.ts | 1 + yarn.lock | 226 +++++++++++++----- 12 files changed, 181 insertions(+), 207 deletions(-) diff --git a/packages/neuron-ui/package.json b/packages/neuron-ui/package.json index e5b12cb51e..5889b69342 100644 --- a/packages/neuron-ui/package.json +++ b/packages/neuron-ui/package.json @@ -53,8 +53,8 @@ "qr.js": "0.0.0", "react": "17.0.2", "react-dom": "17.0.2", - "react-router-dom": "5.1.2", "react-i18next": "11.15.3", + "react-router-dom": "5.1.2", "sass": "1.47.0" }, "devDependencies": { @@ -73,12 +73,12 @@ "@types/react": "17.0.39", "@types/react-dom": "17.0.11", "@types/react-router-dom": "5.3.3", - "@types/storybook__addon-storyshots": "5.1.2", "@types/storybook-react-router": "1.0.1", + "@types/storybook__addon-storyshots": "5.1.2", "@types/styled-components": "4.4.3", "@wojtekmaj/enzyme-adapter-react-17": "0.8.0", "babel-jest": "25.5.1", - "electron": "16.2.8", + "electron": "22.0.0", "enzyme": "3.11.0", "eslint-config-airbnb": "19.0.4", "eslint-config-prettier": "8.5.0", diff --git a/packages/neuron-ui/src/components/Send/hooks.ts b/packages/neuron-ui/src/components/Send/hooks.ts index a7f43d3d3d..aa8daf4219 100644 --- a/packages/neuron-ui/src/components/Send/hooks.ts +++ b/packages/neuron-ui/src/components/Send/hooks.ts @@ -1,9 +1,6 @@ import React, { useState, useCallback, useEffect, useMemo } from 'react' import { TFunction } from 'i18next' -import jsQR from 'jsqr' - import { AppActions, StateDispatch } from 'states/stateProvider/reducer' -import { captureScreenshot, showErrorMessage } from 'services/remote' import { generateTx, generateSendingAllTx } from 'services/remote/wallets' import { @@ -12,11 +9,7 @@ import { shannonToCKBFormatter, calculateFee, validateOutputs, - validateAddress, } from 'utils' -import i18n from 'utils/i18n' - -import styles from './send.module.scss' let generateTxTimer: ReturnType @@ -332,39 +325,6 @@ export const useInitialize = ( } }, [updateSendingAllTransaction, setIsSendMax, isSendMax, outputs.length, updateTransactionOutput, items]) - const onScan = useCallback( - (e: React.SyntheticEvent) => { - const { - dataset: { idx }, - } = e.target as HTMLButtonElement - if (idx !== undefined && !(e.target as HTMLButtonElement).classList.contains(styles.busy)) { - ;[...document.querySelectorAll(`.${styles.scanBtn}`)].forEach(b => b.classList.add(styles.busy)) - setTimeout(async () => { - const codes = await captureScreenshot().then(imageDataList => - imageDataList.map(imageData => - jsQR(imageData.data, imageData.width, imageData.height, { - inversionAttempts: 'dontInvert', - }) - ) - ) - for (let i = 0; i < codes.length; i++) { - try { - validateAddress(codes[i]?.data ?? '', isMainnet) - updateTransactionOutput('address')(+idx)(codes[i]!.data) - ;[...document.querySelectorAll(`.${styles.scanBtn}`)].forEach(b => b.classList.remove(styles.busy)) - return - } catch { - // ignore - } - } - showErrorMessage(i18n.t('messages.error'), i18n.t('messages.no-valid-addresses-found')) - ;[...document.querySelectorAll(`.${styles.scanBtn}`)].forEach(b => b.classList.remove(styles.busy)) - }, 100) - } - }, - [updateTransactionOutput, isMainnet] - ) - useEffect(() => { if (isSendMax) { updateSendingAllTransaction() @@ -393,7 +353,6 @@ export const useInitialize = ( setErrorMessage, isSendMax, onSendMaxClick, - onScan, } } diff --git a/packages/neuron-ui/src/components/Send/index.tsx b/packages/neuron-ui/src/components/Send/index.tsx index b5e9e4a532..8127d2ae24 100644 --- a/packages/neuron-ui/src/components/Send/index.tsx +++ b/packages/neuron-ui/src/components/Send/index.tsx @@ -62,7 +62,6 @@ const Send = () => { setErrorMessage, isSendMax, onSendMaxClick: handleSendMaxClick, - onScan: handleScan, } = useInitialize(walletID, send.outputs, send.generatedTx, send.price, sending, isMainnet, dispatch, t) const [locktimeIndex, setLocktimeIndex] = useState(-1) @@ -175,7 +174,6 @@ const Send = () => { onOutputAdd={handleOutputAdd} onOutputRemove={handleOutputRemove} onItemChange={handleItemChange} - onScan={handleScan} onSendMaxClick={handleSendMaxClick} onLocktimeClick={handleLocktimeClick} isTimeLockable={!device} diff --git a/packages/neuron-ui/src/components/SendFieldset/index.tsx b/packages/neuron-ui/src/components/SendFieldset/index.tsx index e0814baa0e..a7e85df255 100644 --- a/packages/neuron-ui/src/components/SendFieldset/index.tsx +++ b/packages/neuron-ui/src/components/SendFieldset/index.tsx @@ -4,7 +4,6 @@ import { useTranslation } from 'react-i18next' import TextField from 'widgets/TextField' import Button from 'widgets/Button' -import { ReactComponent as Scan } from 'widgets/Icons/Scan.svg' import AddOutput from 'widgets/Icons/AddOutput.png' import RemoveOutput from 'widgets/Icons/RemoveOutput.png' import Edit from 'widgets/Icons/Edit.png' @@ -35,7 +34,6 @@ interface SendSubformProps { onOutputAdd: () => void onOutputRemove: React.EventHandler> onLocktimeClick?: React.EventHandler> - onScan?: React.EventHandler> onSendMaxClick?: React.EventHandler> onItemChange: React.EventHandler> } @@ -53,7 +51,6 @@ const SendFieldset = ({ onOutputAdd, onOutputRemove, onLocktimeClick, - onScan, onSendMaxClick, onItemChange, isTimeLockable = true, @@ -104,18 +101,6 @@ const SendFieldset = ({ error={amountErrorMsg} /> - - {isMaxBtnShow ? ( + ) +} + +interface Option { + value: number + title: string + label: string + selectable: boolean +} +export const useSelectorFocusControl = (value: number, options: Option[], onChange: (option: Option) => void) => { + const [focusIndex, setFocusIndex] = useState(-1) + + useEffect(() => { + setFocusIndex(options.findIndex(option => option.value === value)) + }, [value, options]) + + function moveBackward() { + const index = focusIndex - 1 + if (options[index].selectable) { + setFocusIndex(index) + } + } + function moveForward() { + const index = focusIndex + 1 + if (options[index].selectable) { + setFocusIndex(index) + } + } + + const onKeyDown = (e: KeyboardEvent) => { + const keyEventMap = { + Enter: () => onChange(options[focusIndex]), + ' ': () => onChange(options[focusIndex]), + + ArrowLeft: () => moveBackward(), + ArrowRight: () => moveForward(), + ArrowUp: () => moveBackward(), + ArrowDown: () => moveForward(), + } + if (Object.keys(keyEventMap).includes(e.key)) { + e.preventDefault() + e.stopPropagation() + + keyEventMap[e.key as keyof typeof keyEventMap]() + } + } + + return { focusIndex, onKeyDown } +} + +export const useTableFocusControl = ( + value: Date | undefined, + minDate: Date | undefined, + maxDate: Date | undefined, + calendarYear: number, + calendarMonth: number, + setYear: (month: number) => void, + setMonth: (month: number) => void, + onChange: (value: Date) => void +) => { + const [focusDate, setFocusDate] = useState(value || new Date()) + const curFocusYear = focusDate.getFullYear() + const curFocusMonth = focusDate.getMonth() + 1 + const curFocusDate = focusDate.getDate() + + function moveDate(year: number, month: number, date: number) { + if (!isMonthInRange(year, month, { minDate, maxDate })) { + return + } + setYear(year) + setMonth(month) + + const daysInMonth = new Date(year, month, 0).getDate() + const instance = new Date(year, month - 1, daysInMonth < date ? daysInMonth : date) + + if (!isDayInRange(instance, { minDate, maxDate })) { + if (isDayInRange(instance, { minDate })) { + setFocusDate(maxDate as Date) + } else { + setFocusDate(minDate as Date) + } + } else { + setFocusDate(instance) + } + } + + function moveDateDiff(diff: number) { + const instance = new Date(focusDate) + instance.setDate(instance.getDate() + diff) + moveDate(instance.getFullYear(), instance.getMonth() + 1, instance.getDate()) + } + + useEffect(() => { + const instance = value || new Date() + moveDate(instance.getFullYear(), instance.getMonth() + 1, instance.getDate()) + }, [value?.toDateString(), minDate?.toDateString(), maxDate?.toDateString()]) + + useEffect(() => { + moveDate(calendarYear, calendarMonth, focusDate.getDate()) + }, [calendarYear, calendarMonth, minDate?.toDateString(), maxDate?.toDateString()]) + + const onKeyDown = (e: KeyboardEvent) => { + const keyEventMap = { + Enter: () => onChange(focusDate), + ' ': () => onChange(focusDate), + + ArrowLeft: () => moveDateDiff(-1), + ArrowRight: () => moveDateDiff(1), + ArrowUp: () => moveDateDiff(-7), + ArrowDown: () => moveDateDiff(7), + + PageUp() { + if (curFocusMonth <= 1) { + moveDate(curFocusYear - 1, 12, curFocusDate) + } else { + moveDate(curFocusYear, curFocusMonth - 1, curFocusDate) + } + }, + PageDown() { + if (curFocusMonth >= 12) { + moveDate(curFocusYear + 1, 1, curFocusDate) + } else { + moveDate(curFocusYear, curFocusMonth + 1, curFocusDate) + } + }, + Home() { + moveDate(curFocusYear, curFocusMonth, 1) + }, + End() { + moveDate(curFocusYear, curFocusMonth, 100) + }, + } + + if (Object.keys(keyEventMap).includes(e.key)) { + e.preventDefault() + e.stopPropagation() + + keyEventMap[e.key as keyof typeof keyEventMap]() + } + } + + return { focusDate, onKeyDown } +} + +export const useFocusObserve = () => { + const [isComponetFocused, setIsComponetFocused] = useState(false) + + const onFocus = () => setIsComponetFocused(true) + const onBlur = () => setIsComponetFocused(false) + + return { isComponetFocused, onFocus, onBlur } +} diff --git a/packages/neuron-ui/src/widgets/Calendar/index.tsx b/packages/neuron-ui/src/widgets/Calendar/index.tsx new file mode 100644 index 0000000000..e7c6b71b2d --- /dev/null +++ b/packages/neuron-ui/src/widgets/Calendar/index.tsx @@ -0,0 +1,264 @@ +import React, { useState, useEffect, useMemo, useCallback } from 'react' +import { useTranslation } from 'react-i18next' +import { + getMonthCalendar, + getLocalMonthNames, + getLocalMonthShortNames, + getLocalWeekNames, + isMonthInRange, + isYearInRange, + isDateEqual, + isDayInRange, + WeekDayRange, +} from './utils' +import { ButtonHasFocus, useTableFocusControl, useSelectorFocusControl, useFocusObserve } from './focusControl' +import styles from './calendar.module.scss' + +interface Option { + value: number + title: string + label: string + selectable: boolean +} +interface SelectorProps { + value: number + options: Option[] + onChange: (option: Option) => void +} +const Selector = ({ value, options, onChange }: SelectorProps) => { + const { focusIndex, onKeyDown } = useSelectorFocusControl(value, options, onChange) + return ( +
    + {options.map((option, idx) => ( +
  1. + onChange(option)} + disabled={!option.selectable} + > + {option.title} + +
  2. + ))} +
+ ) +} + +export interface CalendarProps { + value: Date | undefined + onChange: (value: Date) => void + minDate?: Date + maxDate?: Date + firstDayOfWeek?: WeekDayRange + className?: string +} +const Calendar: React.FC = ({ + value, + onChange, + minDate, + maxDate, + firstDayOfWeek = 0, + className = '', +}) => { + const [year, setYear] = useState(new Date().getFullYear()) + const [month, setMonth] = useState(new Date().getMonth() + 1) + const [status, setStatus] = useState<'year' | 'month' | 'date'>('date') + + useEffect(() => { + setYear(value?.getFullYear() ?? new Date().getFullYear()) + setMonth((value?.getMonth() ?? new Date().getMonth()) + 1) + }, [value?.toDateString()]) + + const [uId] = useState(() => (+new Date()).toString(16).slice(-4)) + + const [t, { language }] = useTranslation() + const monthNames = useMemo(() => getLocalMonthNames(language), [language]) + const monthShortNames = useMemo(() => getLocalMonthShortNames(language), [language]) + const weekNames = useMemo(() => getLocalWeekNames(language), [language]) + + const weekTitle = useMemo(() => Array.from({ length: 7 }, (_, i) => weekNames[(i + firstDayOfWeek) % 7]), [weekNames]) + const monthName = monthNames[month - 1] + const monthShortName = monthShortNames[month - 1] + + const calendar = useMemo(() => getMonthCalendar(year, month, firstDayOfWeek, language), [ + year, + month, + firstDayOfWeek, + language, + ]) + function isDisabledTime(date: Date): boolean { + return !isDayInRange(date, { minDate, maxDate }) + } + const prevMonth = () => { + if (month > 1) { + setMonth(m => m - 1) + } else { + setYear(y => y - 1) + setMonth(12) + } + } + const nextMonth = () => { + if (month < 12) { + setMonth(m => m + 1) + } else { + setYear(y => y + 1) + setMonth(1) + } + } + const { focusDate, onKeyDown } = useTableFocusControl( + value, + minDate, + maxDate, + year, + month, + setYear, + setMonth, + onChange + ) + const { isComponetFocused, ...focusListeners } = useFocusObserve() + const calendarTable = ( + + + + {weekTitle.map(weekname => ( + + ))} + + + + {calendar.map(week => ( + + {week.map(date => ( + + ))} + + ))} + +
+ onChange(date.instance)} + > + {date.date} + +
+ ) + + const calendarHeader = ( +
+

+ + +

+
+ ) + + const monthOptions: Option[] = Array.from({ length: 12 }, (_, index) => ({ + value: index + 1, + title: monthShortNames[index], + label: monthNames[index], + selectable: isMonthInRange(year, index + 1, { minDate, maxDate }), + })) + const yearOptions: Option[] = Array.from({ length: 12 }, (_, index) => ({ + value: year - 6 + index, + title: `${year - 6 + index}`, + label: `${year - 6 + index}`, + selectable: isYearInRange(year - 6 + index, { minDate, maxDate }), + })) + const onChangeMonth = useCallback((monthOptionItem: Option) => { + setMonth(monthOptionItem.value) + setStatus('date') + }, []) + const onChangeYear = useCallback( + (yearOptionItem: Option) => { + setYear(yearOptionItem.value) + if (!isMonthInRange(yearOptionItem.value, month, { minDate, maxDate })) { + setMonth((minDate?.getMonth() || 0) + 1) + } + setStatus('month') + }, + [month, minDate?.toDateString(), maxDate?.toDateString()] + ) + + return ( +
+ {calendarHeader} + {status === 'date' && calendarTable} + {status === 'year' && } + {status === 'month' && } +
+ ) +} + +export default React.memo( + Calendar, + (prevProps, nextProps) => + prevProps.value?.toDateString() === nextProps.value?.toDateString() && + prevProps.minDate?.toDateString() === nextProps.minDate?.toDateString() && + prevProps.maxDate?.toDateString() === nextProps.maxDate?.toDateString() && + prevProps.className === nextProps.className && + prevProps.firstDayOfWeek === nextProps.firstDayOfWeek && + prevProps.onChange === nextProps.onChange +) diff --git a/packages/neuron-ui/src/widgets/Calendar/utils.ts b/packages/neuron-ui/src/widgets/Calendar/utils.ts new file mode 100644 index 0000000000..15d8033c32 --- /dev/null +++ b/packages/neuron-ui/src/widgets/Calendar/utils.ts @@ -0,0 +1,115 @@ +export interface Day { + instance: Date + year: number + month: number + date: number + weekday: number + isCurMonth: boolean + isToday: boolean + label: string +} + +interface DateRange { + minDate?: Date + maxDate?: Date +} + +export type WeekDayRange = 0 | 1 | 2 | 3 | 4 | 5 | 6 + +export function isDayInRange(date: Date, range: DateRange): boolean { + const dayBegin = new Date(date.getFullYear(), date.getMonth(), date.getDate()) + const dayEnd = new Date(date.getFullYear(), date.getMonth(), date.getDate() + 1) + + if (range.minDate !== undefined && dayEnd <= range.minDate) { + return false + } + if (range.maxDate !== undefined && dayBegin > range.maxDate) { + return false + } + return true +} + +export function isMonthInRange(year: number, month: number, range: DateRange): boolean { + const monthBegin = new Date(year, month - 1, 1) + const monthEnd = new Date(year, month, 1) + + if (range.minDate !== undefined && monthEnd <= range.minDate) { + return false + } + if (range.maxDate !== undefined && monthBegin > range.maxDate) { + return false + } + return true +} + +export function isYearInRange(year: number, range: DateRange): boolean { + if (range.minDate !== undefined && year < range.minDate.getFullYear()) { + return false + } + if (range.maxDate !== undefined && year > range.maxDate.getFullYear()) { + return false + } + return true +} + +export function isDateEqual(a: Date | undefined, b: Date | undefined): boolean { + if (a === undefined || b === undefined) { + return false + } + return a?.toDateString() === b?.toDateString() +} + +/** + * @description Generate monthly calendar 2D table data + */ +export function getMonthCalendar(year: number, month: number, firstDayOfWeek: WeekDayRange = 0, lang = 'en'): Day[][] { + const today = new Date() + const weekdayOfFirstDay = new Date(year, month - 1, 1).getDay() + const DAYS_IN_WEEK = 7 + const ROWS_IN_CALENDAR = 6 + const numOfDaysInCalendar = DAYS_IN_WEEK * ROWS_IN_CALENDAR + + const dateList: Day[] = [] + const formater = new Intl.DateTimeFormat(lang, { dateStyle: 'full' }) + + for (let i = 1; i <= numOfDaysInCalendar; i++) { + const instance = new Date(year, month - 1, ((firstDayOfWeek - weekdayOfFirstDay - 7) % 7) + i) + const day: Day = { + instance, + year: instance.getFullYear(), + month: instance.getMonth() + 1, + date: instance.getDate(), + weekday: instance.getDay(), + isCurMonth: instance.getMonth() + 1 === month, + isToday: instance.toDateString() === today.toDateString(), + label: formater.format(instance), + } + dateList.push(day) + } + + const calendarData: Day[][] = [] + + for (let i = 0; i < dateList.length; i += 7) { + calendarData.push(dateList.slice(i, i + 7)) + } + + return calendarData +} + +export const getLocalMonthShortNames = (lang: string) => { + const formater = new Intl.DateTimeFormat(lang, { month: 'short' }) + return Array.from( + { length: 12 }, + (_, i) => `${formater.format(new Date(Date.UTC(2023, i, 1)))}${lang.startsWith('en') ? '.' : ''}` + ) +} + +export const getLocalMonthNames = (lang: string) => { + const formater = new Intl.DateTimeFormat(lang, { month: 'long' }) + return Array.from({ length: 12 }, (_, i) => formater.format(new Date(Date.UTC(2023, i, 1)))) +} + +export const getLocalWeekNames = (lang: string) => { + const formater = new Intl.DateTimeFormat(lang, { weekday: 'short' }) + return Array.from({ length: 7 }, (_, i) => formater.format(new Date(Date.UTC(2023, 0, 1 + i)))) +} diff --git a/packages/neuron-ui/src/widgets/DatetimePicker/datetimePicker.module.scss b/packages/neuron-ui/src/widgets/DatetimePicker/datetimePicker.module.scss index bf9be01d42..dc0ab87ccd 100644 --- a/packages/neuron-ui/src/widgets/DatetimePicker/datetimePicker.module.scss +++ b/packages/neuron-ui/src/widgets/DatetimePicker/datetimePicker.module.scss @@ -1,128 +1,8 @@ @import '../../styles/mixin.scss'; $width: 374px; -:global { - .p-calendar { - @include regular-text; - - width: $width; - padding: 20px 0; - border: 1px solid #eee; - border-color: #eee transparent; - display: flex; - justify-content: center; - align-items: center; - - .p-datepicker-today span { - color: var(--nervos-green); - pointer-events: none; - } - - .p-datepicker-header { - display: flex; - justify-content: space-between; - padding: 0 10px; - margin-bottom: 16px; - - .p-datepicker-next.p-link { - order: 1; - } - - @mixin chevron-line { - display: block; - content: ''; - width: 8px; - height: 2px; - background: #000; - position: absolute; - } - - button { - background-color: transparent; - border: none; - font-weight: bolder; - position: relative; - padding: 0; - width: 10px; - } - - .pi-chevron-left { - &::before { - @include chevron-line; - left: 0; - top: 50%; - transform-origin: left center; - position: absolute; - transform: rotate(-45deg) translateY(50%); - } - - &::after { - @include chevron-line; - left: 0; - top: 50%; - transform-origin: left center; - transform: rotate(45deg) translateY(-50%); - } - } - - .pi-chevron-right { - &::before { - @include chevron-line; - right: 0; - top: 50%; - transform-origin: right center; - position: absolute; - transform: rotate(-45deg) translateY(-50%); - } - - &::after { - @include chevron-line; - right: 0; - top: 50%; - transform-origin: right center; - transform: rotate(45deg) translateY(50%); - } - } - - .p-datepicker-month { - margin-right: 5px; - } - } - - .p-highlight { - background: var(--nervos-green); - color: #fff !important; - } - - .p-disabled { - opacity: 0.2; - } - - th { - color: rgba(0, 0, 0, 0.38); - font-size: 12px; - } - - td { - span { - display: flex; - justify-content: center; - align-items: center; - width: 30px; - height: 30px; - border-radius: 50%; - color: #000; - - font-size: 12px; - margin: auto 10px; - - &:not(.p-disabled):hover { - color: #fff; - background-color: var(--nervos-green); - } - } - } - } +.calendar { + width: $width; } .container { diff --git a/packages/neuron-ui/src/widgets/DatetimePicker/index.tsx b/packages/neuron-ui/src/widgets/DatetimePicker/index.tsx index dc09f7e562..7833442376 100644 --- a/packages/neuron-ui/src/widgets/DatetimePicker/index.tsx +++ b/packages/neuron-ui/src/widgets/DatetimePicker/index.tsx @@ -1,8 +1,7 @@ import React, { useState, useCallback, useRef, useEffect } from 'react' -import { Calendar, CalendarChangeParams } from 'primereact/calendar' +import Calendar from 'widgets/Calendar' import Button from 'widgets/Button' import { useTranslation } from 'react-i18next' -import { addLocale } from 'primereact/api' import styles from './datetimePicker.module.scss' const SECONDS_PER_DAY = 24 * 3600 * 1000 @@ -42,32 +41,6 @@ const DatetimePicker = ({ const [display, setDisplay] = useState(preset ? formatDate(new Date(+preset)) : '') const inputRef = useRef(null) - const locale: any = { - firstDayOfWeek: 0, - dayNames: ['sun', 'mon', 'tues', 'wed', 'thur', 'fri', 'sat'].map(dayname => t(`datetime.${dayname}.full`)), - dayNamesShort: ['sun', 'mon', 'tue', 'wed', 'thur', 'fri', 'sat'].map(dayname => t(`datetime.${dayname}.short`)), - dayNamesMin: ['sun', 'mon', 'tue', 'wed', 'thur', 'fri', 'sat'].map(dayname => t(`datetime.${dayname}.tag`)), - monthNames: ['jan', 'feb', 'mar', 'apr', 'may', 'june', 'july', 'aug', 'sept', 'oct', 'nov', 'dec'].map(monname => - t(`datetime.${monname}.short`) - ), - monthNamesShort: [ - 'jan', - 'feb', - 'mar', - 'apr', - 'may', - 'june', - 'july', - 'aug', - 'sept', - 'oct', - 'nov', - 'dec', - ].map(monname => t(`datetime.${monname}.short`)), - } - - addLocale('es', locale) - let selected: Date | undefined = display ? new Date(display) : undefined if (selected?.toString() === 'Invalid Date') { selected = undefined @@ -100,8 +73,8 @@ const DatetimePicker = ({ ) const onCalendarChange = useCallback( - (e: CalendarChangeParams) => { - setDisplay(formatDate(new Date(+e.value!))) + (date: Date) => { + setDisplay(formatDate(date)) setStatus('done') }, [setDisplay, setStatus] @@ -155,14 +128,7 @@ const DatetimePicker = ({ onKeyPress={onKeyPress} /> )} - + {isSinceTomorrow ? null : {t('datetime.start-tomorrow')}} {notice ? (
From e8f56e16e711f4f54d4c8190a5dbc624925a8dd0 Mon Sep 17 00:00:00 2001 From: Keith Date: Fri, 31 Mar 2023 23:47:29 +0800 Subject: [PATCH 23/52] fix: fix error on multisig dialog Use optional chaining to avoid non-null assertion --- packages/neuron-ui/src/widgets/InputSelect/index.tsx | 2 +- packages/neuron-ui/src/widgets/Select/index.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/neuron-ui/src/widgets/InputSelect/index.tsx b/packages/neuron-ui/src/widgets/InputSelect/index.tsx index 5d924b64d1..bc7728a98e 100644 --- a/packages/neuron-ui/src/widgets/InputSelect/index.tsx +++ b/packages/neuron-ui/src/widgets/InputSelect/index.tsx @@ -34,7 +34,7 @@ const Select = ({ value, options, placeholder, disabled, onChange, className }: const onDocumentClick = useCallback( (e: any) => { - if (mounted.current && !root.current!.contains(e.target) && openRef.current) { + if (mounted.current && !root.current?.contains(e.target) && openRef.current) { setOpen(false) } }, diff --git a/packages/neuron-ui/src/widgets/Select/index.tsx b/packages/neuron-ui/src/widgets/Select/index.tsx index 150bf47d20..5a2ca05cac 100644 --- a/packages/neuron-ui/src/widgets/Select/index.tsx +++ b/packages/neuron-ui/src/widgets/Select/index.tsx @@ -35,7 +35,7 @@ const Select = ({ value, options, placeholder, disabled, onChange }: SelectProps const onDocumentClick = useCallback( (e: any) => { - if (mounted.current && !root.current!.contains(e.target) && isOpen) { + if (mounted.current && !root.current?.contains(e.target) && isOpen) { setOpen(false) } }, From 8d7e27027401041c47d22b34cdcf2926ff3c1ff3 Mon Sep 17 00:00:00 2001 From: Chen Yu Date: Tue, 4 Apr 2023 14:16:14 +0800 Subject: [PATCH 24/52] Update dependencies (#2585) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/package.yml | 2 +- .github/workflows/package_for_test.yml | 2 +- package.json | 8 +- packages/ckb-indexer/package.json | 2 +- packages/neuron-ui/package.json | 28 +- packages/neuron-wallet/package.json | 16 +- yarn.lock | 615 ++++++++++--------------- 7 files changed, 261 insertions(+), 412 deletions(-) diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 8ffe4f2b7b..c14e893e89 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -47,7 +47,7 @@ jobs: - name: Add msbuild to PATH if: matrix.os == 'windows-2019' - uses: microsoft/setup-msbuild@v1.1.3 + uses: microsoft/setup-msbuild@v1.3.1 env: ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true' diff --git a/.github/workflows/package_for_test.yml b/.github/workflows/package_for_test.yml index 81622cc921..7daf40df09 100644 --- a/.github/workflows/package_for_test.yml +++ b/.github/workflows/package_for_test.yml @@ -42,7 +42,7 @@ jobs: - name: Add msbuild to PATH if: matrix.os == 'windows-2019' - uses: microsoft/setup-msbuild@v1.1.3 + uses: microsoft/setup-msbuild@v1.3.1 env: ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true' diff --git a/package.json b/package.json index 9fee71108c..71f17571ea 100644 --- a/package.json +++ b/package.json @@ -44,12 +44,12 @@ } }, "devDependencies": { - "@babel/core": "7.20.5", + "@babel/core": "7.21.0", "@types/jest": "27.5.2", - "@types/node": "18.11.17", + "@types/node": "18.14.6", "@types/npmlog": "4.1.4", - "@typescript-eslint/eslint-plugin": "5.47.0", - "@typescript-eslint/parser": "5.47.0", + "@typescript-eslint/eslint-plugin": "5.54.1", + "@typescript-eslint/parser": "5.54.1", "concurrently": "7.6.0", "cross-env": "7.0.3", "husky": "3.1.0", diff --git a/packages/ckb-indexer/package.json b/packages/ckb-indexer/package.json index b40fb007b2..10b6624d17 100644 --- a/packages/ckb-indexer/package.json +++ b/packages/ckb-indexer/package.json @@ -22,7 +22,7 @@ }, "devDependencies": { "events": "3.3.0", - "eslint": "8.31.0" + "eslint": "8.35.0" }, "scripts": { "build": "tsc", diff --git a/packages/neuron-ui/package.json b/packages/neuron-ui/package.json index c2a91a5715..e38ead95af 100644 --- a/packages/neuron-ui/package.json +++ b/packages/neuron-ui/package.json @@ -48,16 +48,16 @@ "i18next": "21.10.0", "immer": "9.0.16", "jsqr": "1.4.0", - "office-ui-fabric-react": "7.199.6", + "office-ui-fabric-react": "7.204.0", "qr.js": "0.0.0", "react": "17.0.2", "react-dom": "17.0.2", - "react-i18next": "11.18.6", + "react-i18next": "12.1.5", "react-router-dom": "5.1.2", - "sass": "1.56.1" + "sass": "1.58.3" }, "devDependencies": { - "@babel/plugin-proposal-private-property-in-object": "7.20.5", + "@babel/plugin-proposal-private-property-in-object": "7.21.0", "@storybook/addon-actions": "5.3.18", "@storybook/addon-knobs": "5.3.21", "@storybook/addon-links": "5.3.18", @@ -68,33 +68,33 @@ "@storybook/react": "5.3.18", "@types/enzyme": "3.10.12", "@types/enzyme-adapter-react-16": "1.0.6", - "@types/node": "18.11.17", + "@types/node": "18.14.6", "@types/react": "17.0.53", - "@types/react-dom": "17.0.11", + "@types/react-dom": "17.0.19", "@types/react-router-dom": "5.3.3", "@types/storybook-react-router": "1.0.1", "@types/storybook__addon-storyshots": "5.1.2", - "@types/styled-components": "4.4.3", + "@types/styled-components": "5.1.26", "@wojtekmaj/enzyme-adapter-react-17": "0.8.0", "babel-jest": "25.5.1", - "electron": "22.2.0", + "electron": "23.1.2", "enzyme": "3.11.0", "enzyme-adapter-react-16": "1.15.7", "eslint-config-airbnb": "19.0.4", - "eslint-config-prettier": "8.5.0", - "eslint-plugin-import": "2.26.0", - "eslint-plugin-jsx-a11y": "6.6.1", + "eslint-config-prettier": "8.7.0", + "eslint-plugin-import": "2.27.5", + "eslint-plugin-jsx-a11y": "6.7.1", "eslint-plugin-prettier": "4.0.0", - "eslint-plugin-react": "7.31.10", + "eslint-plugin-react": "7.32.2", "jest-styled-components": "7.1.1", "lint-staged": "9.5.0", "prettier": "1.19.1", "react-app-rewired": "2.2.1", "react-scripts": "5.0.1", - "react-test-renderer": "16.12.0", + "react-test-renderer": "16.14.0", "storybook-react-router": "1.0.8" }, "resolutions": { - "react-i18next": ">=11.16.4" + "react-i18next": "12.1.5" } } diff --git a/packages/neuron-wallet/package.json b/packages/neuron-wallet/package.json index 32ad2bec8b..d23073a6aa 100644 --- a/packages/neuron-wallet/package.json +++ b/packages/neuron-wallet/package.json @@ -39,7 +39,7 @@ "@ckb-lumos/base": "0.18.0-rc2", "@ckb-lumos/rpc": "0.18.0-rc2", "@iarna/toml": "2.2.5", - "@ledgerhq/hw-transport-node-hid": "6.27.11", + "@ledgerhq/hw-transport-node-hid": "6.27.12", "@nervina-labs/ckb-indexer": "0.1.1", "@nervosnetwork/ckb-sdk-core": "0.103.1", "@nervosnetwork/ckb-sdk-utils": "0.103.1", @@ -59,7 +59,7 @@ "reflect-metadata": "0.1.13", "rxjs": "6.6.7", "sha3": "2.1.4", - "sqlite3": "5.1.2", + "sqlite3": "5.1.4", "subleveldown": "4.1.4", "typeorm": "0.2.25", "undici": "5.19.1", @@ -69,7 +69,7 @@ "@electron/notarize": "1.2.3", "@nervosnetwork/ckb-types": "0.103.1", "@types/archiver": "3.1.1", - "@types/async": "3.2.16", + "@types/async": "3.2.18", "@types/electron-devtools-installer": "2.2.2", "@types/elliptic": "6.4.14", "@types/iarna__toml": "2.0.2", @@ -82,18 +82,18 @@ "@types/uuid": "8.3.4", "@zerollup/ts-transform-paths": "1.7.18", "devtron": "1.4.0", - "electron": "22.2.0", + "electron": "23.1.2", "electron-build-env": "0.2.0", "electron-builder": "23.6.0", - "electron-devtools-installer": "2.2.4", - "eslint": "8.27.0", - "eslint-config-prettier": "6.15.0", + "electron-devtools-installer": "3.2.0", + "eslint": "8.35.0", + "eslint-config-prettier": "8.7.0", "eslint-plugin-prettier": "3.4.1", "jest-when": "2.8.1", "lint-staged": "9.5.0", "neuron-ui": "0.106.0", "prettier": "1.19.1", - "ttypescript": "1.5.13", + "ttypescript": "1.5.15", "typescript": "4.2.3" } } diff --git a/yarn.lock b/yarn.lock index e4c652269f..36bffa0c0c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,17 +7,12 @@ resolved "https://registry.yarnpkg.com/7zip-bin/-/7zip-bin-5.1.1.tgz#9274ec7460652f9c632c59addf24efb1684ef876" integrity sha512-sAP4LldeWNz0lNzmTird3uWfFDWWTeg6V/MsmyyLR9X1idwKBWIgt/ZvinqQldJm3LecKEs1emkbquO6PCiLVQ== -"7zip@0.0.6": - version "0.0.6" - resolved "https://registry.yarnpkg.com/7zip/-/7zip-0.0.6.tgz#9cafb171af82329490353b4816f03347aa150a30" - integrity sha512-ns8vKbKhIQm338AeWo/YdDSWil3pldwCMoyR2npoM2qDAzF8Vuko8BtDxpNt/wE15SXOh5K5WbjSLR4kTOAHLA== - "@adobe/css-tools@^4.0.1": version "4.2.0" resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.2.0.tgz#e1a84fca468f4b337816fcb7f0964beb620ba855" integrity sha512-E09FiIft46CmH5Qnjb0wsW54/YQd69LsxeKUOWawmws1XWvyFGURnAChH0mlr7YPFR1ofwvUQfcL0J3lMxXqPA== -"@ampproject/remapping@^2.1.0", "@ampproject/remapping@^2.2.0": +"@ampproject/remapping@^2.2.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== @@ -75,25 +70,25 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@7.20.5": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.5.tgz#45e2114dc6cd4ab167f81daf7820e8fa1250d113" - integrity sha512-UdOWmk4pNWTm/4DlPUl/Pt4Gz4rcEMb7CY0Y3eJl5Yz1vI8ZJGmHWaVE55LoxRjdpx0z259GE9U5STA9atUinQ== +"@babel/core@7.21.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.21.0.tgz#1341aefdcc14ccc7553fcc688dd8986a2daffc13" + integrity sha512-PuxUbxcW6ZYe656yL3EAhpy7qXKq0DmYsrJLpbB8XrsCP9Nm+XCg9XFMb5vIDliPD7+U/+M+QJlH17XOcB7eXA== dependencies: - "@ampproject/remapping" "^2.1.0" + "@ampproject/remapping" "^2.2.0" "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.20.5" - "@babel/helper-compilation-targets" "^7.20.0" - "@babel/helper-module-transforms" "^7.20.2" - "@babel/helpers" "^7.20.5" - "@babel/parser" "^7.20.5" - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.20.5" - "@babel/types" "^7.20.5" + "@babel/generator" "^7.21.0" + "@babel/helper-compilation-targets" "^7.20.7" + "@babel/helper-module-transforms" "^7.21.0" + "@babel/helpers" "^7.21.0" + "@babel/parser" "^7.21.0" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.21.0" + "@babel/types" "^7.21.0" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" - json5 "^2.2.1" + json5 "^2.2.2" semver "^6.3.0" "@babel/core@^7.1.0", "@babel/core@^7.1.6", "@babel/core@^7.11.1", "@babel/core@^7.12.3", "@babel/core@^7.16.0", "@babel/core@^7.4.5", "@babel/core@^7.7.2", "@babel/core@^7.7.5", "@babel/core@^7.8.0": @@ -126,7 +121,7 @@ eslint-visitor-keys "^2.1.0" semver "^6.3.0" -"@babel/generator@^7.12.11", "@babel/generator@^7.12.5", "@babel/generator@^7.20.5", "@babel/generator@^7.21.3", "@babel/generator@^7.4.0", "@babel/generator@^7.7.2": +"@babel/generator@^7.12.11", "@babel/generator@^7.12.5", "@babel/generator@^7.21.3", "@babel/generator@^7.4.0", "@babel/generator@^7.7.2": version "7.21.3" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.21.3.tgz#232359d0874b392df04045d72ce2fd9bb5045fce" integrity sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA== @@ -136,6 +131,16 @@ "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" +"@babel/generator@^7.21.0": + version "7.21.1" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.21.1.tgz#951cc626057bc0af2c35cd23e9c64d384dea83dd" + integrity sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA== + dependencies: + "@babel/types" "^7.21.0" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + "@babel/helper-annotate-as-pure@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" @@ -162,7 +167,7 @@ lru-cache "^5.1.1" semver "^6.3.0" -"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.20.5", "@babel/helper-create-class-features-plugin@^7.21.0": +"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.21.0": version "7.21.0" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.21.0.tgz#64f49ecb0020532f19b1d014b03bccaa1ab85fb9" integrity sha512-Q8wNiMIdwsv5la5SPxNYzzkPnjgC0Sy0i7jLkVOCdllu/xcVNkr3TeZzbHBJrj+XXRqzX5uCyCoV9eu6xUG7KQ== @@ -237,7 +242,7 @@ dependencies: "@babel/types" "^7.18.6" -"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.20.11", "@babel/helper-module-transforms@^7.20.2", "@babel/helper-module-transforms@^7.21.2": +"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.20.11", "@babel/helper-module-transforms@^7.21.0", "@babel/helper-module-transforms@^7.21.2": version "7.21.2" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz#160caafa4978ac8c00ac66636cb0fa37b024e2d2" integrity sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ== @@ -336,7 +341,7 @@ "@babel/traverse" "^7.20.5" "@babel/types" "^7.20.5" -"@babel/helpers@^7.12.5", "@babel/helpers@^7.20.5", "@babel/helpers@^7.21.0": +"@babel/helpers@^7.12.5", "@babel/helpers@^7.21.0": version "7.21.0" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.21.0.tgz#9dd184fb5599862037917cdc9eecb84577dc4e7e" integrity sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA== @@ -354,11 +359,16 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.1.6", "@babel/parser@^7.12.7", "@babel/parser@^7.14.7", "@babel/parser@^7.20.5", "@babel/parser@^7.20.7", "@babel/parser@^7.21.3", "@babel/parser@^7.4.3": +"@babel/parser@^7.1.0", "@babel/parser@^7.1.6", "@babel/parser@^7.12.7", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.21.3", "@babel/parser@^7.4.3": version "7.21.3" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.3.tgz#1d285d67a19162ff9daa358d4cb41d50c06220b3" integrity sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ== +"@babel/parser@^7.21.0": + version "7.21.2" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.2.tgz#dacafadfc6d7654c3051a66d6fe55b6cb2f2a0b3" + integrity sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ== + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz#da5b8f9a580acdfbe53494dba45ea389fb09a4d2" @@ -506,17 +516,7 @@ "@babel/helper-create-class-features-plugin" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-proposal-private-property-in-object@7.20.5": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.20.5.tgz#309c7668f2263f1c711aa399b5a9a6291eef6135" - integrity sha512-Vq7b9dUA12ByzB4EjQTPo25sFhY+08pQDBSZRtUAkj7lb7jahaHR5igera16QZ+3my1nYR4dKsNdYj5IjPHilQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-create-class-features-plugin" "^7.20.5" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/plugin-syntax-private-property-in-object" "^7.14.5" - -"@babel/plugin-proposal-private-property-in-object@^7.18.6": +"@babel/plugin-proposal-private-property-in-object@7.21.0", "@babel/plugin-proposal-private-property-in-object@^7.18.6": version "7.21.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0.tgz#19496bd9883dd83c23c7d7fc45dcd9ad02dfa1dc" integrity sha512-ha4zfehbJjc5MmXBlHec1igel5TJXXLDDRbuJ4+XT2TJcyD9/V1919BA8gMvsdHcNMBy4WBUBiRb3nw/EQUtBw== @@ -1147,15 +1147,7 @@ resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== -"@babel/runtime-corejs3@^7.10.2": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.21.0.tgz#6e4939d9d9789ff63e2dc58e88f13a3913a24eba" - integrity sha512-TDD4UJzos3JJtM+tHX+w2Uc+KWj7GV+VKKFdMVd2Rx8sdA19hcc3P3AHFYd5LVOw+pYuSd5lICC3gm52B6Rwxw== - dependencies: - core-js-pure "^3.25.1" - regenerator-runtime "^0.13.11" - -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.3", "@babel/runtime@^7.17.2", "@babel/runtime@^7.18.9", "@babel/runtime@^7.20.6", "@babel/runtime@^7.20.7", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.3", "@babel/runtime@^7.17.2", "@babel/runtime@^7.20.6", "@babel/runtime@^7.20.7", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": version "7.21.0" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.0.tgz#5b55c9d394e5fcf304909a8b00c07dc217b56673" integrity sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw== @@ -1187,7 +1179,7 @@ debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.12.6", "@babel/types@^7.12.7", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.2.0", "@babel/types@^7.20.0", "@babel/types@^7.20.2", "@babel/types@^7.20.5", "@babel/types@^7.20.7", "@babel/types@^7.21.0", "@babel/types@^7.21.2", "@babel/types@^7.21.3", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.0", "@babel/types@^7.4.4": +"@babel/types@^7.0.0", "@babel/types@^7.12.6", "@babel/types@^7.12.7", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.2.0", "@babel/types@^7.20.0", "@babel/types@^7.20.2", "@babel/types@^7.20.5", "@babel/types@^7.20.7", "@babel/types@^7.21.3", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.0", "@babel/types@^7.4.4": version "7.21.3" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.3.tgz#4865a5357ce40f64e3400b0f3b737dc6d4f64d05" integrity sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg== @@ -1196,6 +1188,15 @@ "@babel/helper-validator-identifier" "^7.19.1" to-fast-properties "^2.0.0" +"@babel/types@^7.21.0", "@babel/types@^7.21.2": + version "7.21.2" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.2.tgz#92246f6e00f91755893c2876ad653db70c8310d1" + integrity sha512-3wRZSs7jiFaB8AjxiiD+VqN5DTG2iRvJGQ+qYFrs/654lg6kGTQWIOFjlBo5RaXuAZjBmP3+OQH4dmhqiiyYxw== + dependencies: + "@babel/helper-string-parser" "^7.19.4" + "@babel/helper-validator-identifier" "^7.19.1" + to-fast-properties "^2.0.0" + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" @@ -1529,10 +1530,10 @@ resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.4.0.tgz#3e61c564fcd6b921cb789838631c5ee44df09403" integrity sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ== -"@eslint/eslintrc@^1.3.3", "@eslint/eslintrc@^1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.4.1.tgz#af58772019a2d271b7e2d4c23ff4ddcba3ccfb3e" - integrity sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA== +"@eslint/eslintrc@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.0.0.tgz#943309d8697c52fc82c076e90c1c74fbbe69dbff" + integrity sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A== dependencies: ajv "^6.12.4" debug "^4.3.2" @@ -1559,6 +1560,11 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" +"@eslint/js@8.35.0": + version "8.35.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.35.0.tgz#b7569632b0b788a0ca0e438235154e45d42813a7" + integrity sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw== + "@eslint/js@8.36.0": version "8.36.0" resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.36.0.tgz#9837f768c03a1e4a30bd304a64fb8844f0e72efe" @@ -1669,7 +1675,7 @@ dependencies: "@hapi/hoek" "^9.0.0" -"@humanwhocodes/config-array@^0.11.6", "@humanwhocodes/config-array@^0.11.8": +"@humanwhocodes/config-array@^0.11.8": version "0.11.8" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz#03595ac2075a4dc0f191cc2131de14fbd7d410b9" integrity sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g== @@ -2133,16 +2139,6 @@ rxjs "6" semver "^7.3.5" -"@ledgerhq/devices@^7.0.7": - version "7.0.7" - resolved "https://registry.yarnpkg.com/@ledgerhq/devices/-/devices-7.0.7.tgz#3499304a1c9d3aa7399de2ad390719bef5d1e89c" - integrity sha512-PZ9TtaTGBYUm/g0qNKPbECZt7DDNvqM3ILS5wAtOMna2cBR+mrywUGXrkjuOWlHpuqZ8wenaAKveQBbzF2ba8w== - dependencies: - "@ledgerhq/errors" "^6.12.3" - "@ledgerhq/logs" "^6.10.1" - rxjs "6" - semver "^7.3.5" - "@ledgerhq/devices@^8.0.0": version "8.0.0" resolved "https://registry.yarnpkg.com/@ledgerhq/devices/-/devices-8.0.0.tgz#8fe9f9e442e28b7a20bcdf4c2eed06ce7b8f76ae" @@ -2163,7 +2159,7 @@ resolved "https://registry.yarnpkg.com/@ledgerhq/errors/-/errors-6.12.3.tgz#a610caae1eeeb7cb038525e5212fe03217dda683" integrity sha512-djiMSgB/7hnK3aLR/c5ZMMivxjcI7o2+y3VKcsZZpydPoVf9+FXqeJPRfOwmJ0JxbQ//LinUfWpIfHew8LkaVw== -"@ledgerhq/hw-transport-node-hid-noevents@^6.27.11": +"@ledgerhq/hw-transport-node-hid-noevents@^6.27.12": version "6.27.12" resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid-noevents/-/hw-transport-node-hid-noevents-6.27.12.tgz#5dacbaf7e146018a73d18d16ce975925b5795732" integrity sha512-f99lIcdEz78jHVfr57Vl9sgP/WpAuM3X26lLDSTKmNHDxLSx7IQaK/eJOcFG4XLk5K7dK/zoyXqq13zcLL2tPg== @@ -2174,15 +2170,15 @@ "@ledgerhq/logs" "^6.10.1" node-hid "^2.1.2" -"@ledgerhq/hw-transport-node-hid@6.27.11": - version "6.27.11" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-6.27.11.tgz#b41ba626e32a8d44930de9f7d5ba9025554386af" - integrity sha512-vAiLhj0zmh9irSlZylDA8AzHbxj5rHVRNcWqSMbXDMPZJECl1Rjj3oNe6Rx6kday1NJMY06Ssxo2cv4ONsyEDQ== +"@ledgerhq/hw-transport-node-hid@6.27.12": + version "6.27.12" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-6.27.12.tgz#8a628ea574c51bd727aa1d7b7a4ddaf9a5042df1" + integrity sha512-Y3GGgZK27K587P3671bCF4pbbfFYq6eVECnxoxtVwt0kdquRfpt3mxWlU51LIL+XgDEwBwt2QdB+6eyLHmWKQA== dependencies: - "@ledgerhq/devices" "^7.0.7" + "@ledgerhq/devices" "^8.0.0" "@ledgerhq/errors" "^6.12.3" - "@ledgerhq/hw-transport" "^6.28.0" - "@ledgerhq/hw-transport-node-hid-noevents" "^6.27.11" + "@ledgerhq/hw-transport" "^6.28.1" + "@ledgerhq/hw-transport-node-hid-noevents" "^6.27.12" "@ledgerhq/logs" "^6.10.1" lodash "^4.17.21" node-hid "^2.1.2" @@ -2197,7 +2193,7 @@ "@ledgerhq/errors" "^5.50.0" events "^3.3.0" -"@ledgerhq/hw-transport@^6.28.0", "@ledgerhq/hw-transport@^6.28.1": +"@ledgerhq/hw-transport@^6.28.1": version "6.28.1" resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-6.28.1.tgz#cb22fe9bc23af4682c30f2aac7fe6f7ab13ed65a" integrity sha512-RaZe+abn0zBIz82cE9tp7Y7aZkHWWbEaE2yJpfxT8AhFz3fx+BU0kLYzuRN9fmA7vKueNJ1MTVUCY+Ex9/CHSQ== @@ -4638,10 +4634,10 @@ dependencies: "@types/glob" "*" -"@types/async@3.2.16": - version "3.2.16" - resolved "https://registry.yarnpkg.com/@types/async/-/async-3.2.16.tgz#7473aa015cf8a60584a94dc79b9203d465c32b41" - integrity sha512-jnlGp5Z/cAZ7JVYyLnSDuYJ+YyYm0o2yzL8Odv6ckWmGMow3j/P/wgfziybB044cXXA93lEuymJyxVR8Iz2amQ== +"@types/async@3.2.18": + version "3.2.18" + resolved "https://registry.yarnpkg.com/@types/async/-/async-3.2.18.tgz#3d93dde6eab654f7bc23e549d9af5d3fa4a5bdc5" + integrity sha512-/IsuXp3B9R//uRLi40VlIYoMp7OzhkunPe2fDu7jGfQXI9y3CDCx6FC4juRLSqrpmLst3vgsiK536AAGJFl4Ww== "@types/babel__core@^7.0.0", "@types/babel__core@^7.1.14", "@types/babel__core@^7.1.7": version "7.20.0" @@ -5080,10 +5076,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.3.tgz#f0b991c32cfc6a4e7f3399d6cb4b8cf9a0315014" integrity sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw== -"@types/node@18.11.17": - version "18.11.17" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.17.tgz#5c009e1d9c38f4a2a9d45c0b0c493fe6cdb4bcb5" - integrity sha512-HJSUJmni4BeDHhfzn6nF0sVmd1SMezP7/4F0Lq+aXzmp2xm9O7WXrUtHW/CHlYVtZUbByEvWidHqRtcJXGF2Ng== +"@types/node@18.14.6": + version "18.14.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.14.6.tgz#ae1973dd2b1eeb1825695bb11ebfb746d27e3e93" + integrity sha512-93+VvleD3mXwlLI/xASjw0FzKcwzl3OdTCzm1LaRfqgS21gfFtK3zDXM5Op9TeeMsJVOaJ2VRDpT9q4Y3d0AvA== "@types/node@^16.11.26": version "16.18.16" @@ -5158,19 +5154,12 @@ "@types/react" "*" "@types/reactcss" "*" -"@types/react-dom@17.0.11": - version "17.0.11" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.11.tgz#e1eadc3c5e86bdb5f7684e00274ae228e7bcc466" - integrity sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q== - dependencies: - "@types/react" "*" - -"@types/react-native@*": - version "0.71.3" - resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.71.3.tgz#537f669ed6b38b5ae47444bd9d253c4cff23bed7" - integrity sha512-0Uqw1YZ0qbVla0MMWFTANFm6W8KYWNvGQmYfucdecbXivLMcQ2v4PovuYFKr7bE6Bc5nDCUEaga962Y8gcDF7A== +"@types/react-dom@17.0.19": + version "17.0.19" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.19.tgz#36feef3aa35d045cacd5ed60fe0eef5272f19492" + integrity sha512-PiYG40pnQRdPHnlf7tZnp0aQ6q9tspYr72vD61saO6zFCybLfMqwUCN0va1/P+86DXn18ZWeW30Bk7xlC5eEAQ== dependencies: - "@types/react" "*" + "@types/react" "^17" "@types/react-router-dom@5.3.3": version "5.3.3" @@ -5316,15 +5305,14 @@ dependencies: "@storybook/react" "^5.2.0" -"@types/styled-components@4.4.3": - version "4.4.3" - resolved "https://registry.yarnpkg.com/@types/styled-components/-/styled-components-4.4.3.tgz#74dd00ad760845a98890a8539361d8afc32059de" - integrity sha512-U0udeNOZBfUkJycmGJwmzun0FBt11rZy08weVQmE2xfUNAbX8AGOEWxWna2d+qAUKxKgMlcG+TZT0+K2FfDcnQ== +"@types/styled-components@5.1.26": + version "5.1.26" + resolved "https://registry.yarnpkg.com/@types/styled-components/-/styled-components-5.1.26.tgz#5627e6812ee96d755028a98dae61d28e57c233af" + integrity sha512-KuKJ9Z6xb93uJiIyxo/+ksS7yLjS1KzG6iv5i78dhVg/X3u5t1H7juRWqVmodIdz6wGVaIApo1u01kmFRdJHVw== dependencies: "@types/hoist-non-react-statics" "*" "@types/react" "*" - "@types/react-native" "*" - csstype "^2.2.0" + csstype "^3.0.2" "@types/tapable@^1", "@types/tapable@^1.0.5": version "1.0.8" @@ -5431,15 +5419,16 @@ dependencies: "@types/node" "*" -"@typescript-eslint/eslint-plugin@5.47.0": - version "5.47.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.47.0.tgz#dadb79df3b0499699b155839fd6792f16897d910" - integrity sha512-AHZtlXAMGkDmyLuLZsRpH3p4G/1iARIwc/T0vIem2YB+xW6pZaXYXzCBnZSF/5fdM97R9QqZWZ+h3iW10XgevQ== +"@typescript-eslint/eslint-plugin@5.54.1": + version "5.54.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.54.1.tgz#0c5091289ce28372e38ab8d28e861d2dbe1ab29e" + integrity sha512-a2RQAkosH3d3ZIV08s3DcL/mcGc2M/UC528VkPULFxR9VnVPT8pBu0IyBAJJmVsCmhVfwQX1v6q+QGnmSe1bew== dependencies: - "@typescript-eslint/scope-manager" "5.47.0" - "@typescript-eslint/type-utils" "5.47.0" - "@typescript-eslint/utils" "5.47.0" + "@typescript-eslint/scope-manager" "5.54.1" + "@typescript-eslint/type-utils" "5.54.1" + "@typescript-eslint/utils" "5.54.1" debug "^4.3.4" + grapheme-splitter "^1.0.4" ignore "^5.2.0" natural-compare-lite "^1.4.0" regexpp "^3.2.0" @@ -5469,14 +5458,14 @@ dependencies: "@typescript-eslint/utils" "5.55.0" -"@typescript-eslint/parser@5.47.0": - version "5.47.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.47.0.tgz#62e83de93499bf4b500528f74bf2e0554e3a6c8d" - integrity sha512-udPU4ckK+R1JWCGdQC4Qa27NtBg7w020ffHqGyAK8pAgOVuNw7YaKXGChk+udh+iiGIJf6/E/0xhVXyPAbsczw== +"@typescript-eslint/parser@5.54.1": + version "5.54.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.54.1.tgz#05761d7f777ef1c37c971d3af6631715099b084c" + integrity sha512-8zaIXJp/nG9Ff9vQNh7TI+C3nA6q6iIsGJ4B4L6MhZ7mHnTMR4YP5vp2xydmFXIy8rpyIVbNAG44871LMt6ujg== dependencies: - "@typescript-eslint/scope-manager" "5.47.0" - "@typescript-eslint/types" "5.47.0" - "@typescript-eslint/typescript-estree" "5.47.0" + "@typescript-eslint/scope-manager" "5.54.1" + "@typescript-eslint/types" "5.54.1" + "@typescript-eslint/typescript-estree" "5.54.1" debug "^4.3.4" "@typescript-eslint/parser@^5.5.0": @@ -5489,13 +5478,13 @@ "@typescript-eslint/typescript-estree" "5.55.0" debug "^4.3.4" -"@typescript-eslint/scope-manager@5.47.0": - version "5.47.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.47.0.tgz#f58144a6b0ff58b996f92172c488813aee9b09df" - integrity sha512-dvJab4bFf7JVvjPuh3sfBUWsiD73aiftKBpWSfi3sUkysDQ4W8x+ZcFpNp7Kgv0weldhpmMOZBjx1wKN8uWvAw== +"@typescript-eslint/scope-manager@5.54.1": + version "5.54.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.54.1.tgz#6d864b4915741c608a58ce9912edf5a02bb58735" + integrity sha512-zWKuGliXxvuxyM71UA/EcPxaviw39dB2504LqAmFDjmkpO8qNLHcmzlh6pbHs1h/7YQ9bnsO8CCcYCSA8sykUg== dependencies: - "@typescript-eslint/types" "5.47.0" - "@typescript-eslint/visitor-keys" "5.47.0" + "@typescript-eslint/types" "5.54.1" + "@typescript-eslint/visitor-keys" "5.54.1" "@typescript-eslint/scope-manager@5.55.0": version "5.55.0" @@ -5505,13 +5494,13 @@ "@typescript-eslint/types" "5.55.0" "@typescript-eslint/visitor-keys" "5.55.0" -"@typescript-eslint/type-utils@5.47.0": - version "5.47.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.47.0.tgz#2b440979c574e317d3473225ae781f292c99e55d" - integrity sha512-1J+DFFrYoDUXQE1b7QjrNGARZE6uVhBqIvdaXTe5IN+NmEyD68qXR1qX1g2u4voA+nCaelQyG8w30SAOihhEYg== +"@typescript-eslint/type-utils@5.54.1": + version "5.54.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.54.1.tgz#4825918ec27e55da8bb99cd07ec2a8e5f50ab748" + integrity sha512-WREHsTz0GqVYLIbzIZYbmUUr95DKEKIXZNH57W3s+4bVnuF1TKe2jH8ZNH8rO1CeMY3U4j4UQeqPNkHMiGem3g== dependencies: - "@typescript-eslint/typescript-estree" "5.47.0" - "@typescript-eslint/utils" "5.47.0" + "@typescript-eslint/typescript-estree" "5.54.1" + "@typescript-eslint/utils" "5.54.1" debug "^4.3.4" tsutils "^3.21.0" @@ -5525,23 +5514,23 @@ debug "^4.3.4" tsutils "^3.21.0" -"@typescript-eslint/types@5.47.0": - version "5.47.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.47.0.tgz#67490def406eaa023dbbd8da42ee0d0c9b5229d3" - integrity sha512-eslFG0Qy8wpGzDdYKu58CEr3WLkjwC5Usa6XbuV89ce/yN5RITLe1O8e+WFEuxnfftHiJImkkOBADj58ahRxSg== +"@typescript-eslint/types@5.54.1": + version "5.54.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.54.1.tgz#29fbac29a716d0f08c62fe5de70c9b6735de215c" + integrity sha512-G9+1vVazrfAfbtmCapJX8jRo2E4MDXxgm/IMOF4oGh3kq7XuK3JRkOg6y2Qu1VsTRmWETyTkWt1wxy7X7/yLkw== "@typescript-eslint/types@5.55.0": version "5.55.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.55.0.tgz#9830f8d3bcbecf59d12f821e5bc6960baaed41fd" integrity sha512-M4iRh4AG1ChrOL6Y+mETEKGeDnT7Sparn6fhZ5LtVJF1909D5O4uqK+C5NPbLmpfZ0XIIxCdwzKiijpZUOvOug== -"@typescript-eslint/typescript-estree@5.47.0": - version "5.47.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.47.0.tgz#ed971a11c5c928646d6ba7fc9dfdd6e997649aca" - integrity sha512-LxfKCG4bsRGq60Sqqu+34QT5qT2TEAHvSCCJ321uBWywgE2dS0LKcu5u+3sMGo+Vy9UmLOhdTw5JHzePV/1y4Q== +"@typescript-eslint/typescript-estree@5.54.1": + version "5.54.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.1.tgz#df7b6ae05fd8fef724a87afa7e2f57fa4a599be1" + integrity sha512-bjK5t+S6ffHnVwA0qRPTZrxKSaFYocwFIkZx5k7pvWfsB1I57pO/0M0Skatzzw1sCkjJ83AfGTL0oFIFiDX3bg== dependencies: - "@typescript-eslint/types" "5.47.0" - "@typescript-eslint/visitor-keys" "5.47.0" + "@typescript-eslint/types" "5.54.1" + "@typescript-eslint/visitor-keys" "5.54.1" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" @@ -5561,16 +5550,16 @@ semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/utils@5.47.0": - version "5.47.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.47.0.tgz#b5005f7d2696769a1fdc1e00897005a25b3a0ec7" - integrity sha512-U9xcc0N7xINrCdGVPwABjbAKqx4GK67xuMV87toI+HUqgXj26m6RBp9UshEXcTrgCkdGYFzgKLt8kxu49RilDw== +"@typescript-eslint/utils@5.54.1": + version "5.54.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.54.1.tgz#7a3ee47409285387b9d4609ea7e1020d1797ec34" + integrity sha512-IY5dyQM8XD1zfDe5X8jegX6r2EVU5o/WJnLu/znLPWCBF7KNGC+adacXnt5jEYS9JixDcoccI6CvE4RCjHMzCQ== dependencies: "@types/json-schema" "^7.0.9" "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.47.0" - "@typescript-eslint/types" "5.47.0" - "@typescript-eslint/typescript-estree" "5.47.0" + "@typescript-eslint/scope-manager" "5.54.1" + "@typescript-eslint/types" "5.54.1" + "@typescript-eslint/typescript-estree" "5.54.1" eslint-scope "^5.1.1" eslint-utils "^3.0.0" semver "^7.3.7" @@ -5589,12 +5578,12 @@ eslint-scope "^5.1.1" semver "^7.3.7" -"@typescript-eslint/visitor-keys@5.47.0": - version "5.47.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.47.0.tgz#4aca4efbdf6209c154df1f7599852d571b80bb45" - integrity sha512-ByPi5iMa6QqDXe/GmT/hR6MZtVPi0SqMQPDx15FczCBXJo/7M8T88xReOALAfpBLm+zxpPfmhuEvPb577JRAEg== +"@typescript-eslint/visitor-keys@5.54.1": + version "5.54.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.1.tgz#d7a8a0f7181d6ac748f4d47b2306e0513b98bf8b" + integrity sha512-q8iSoHTgwCfgcRJ2l2x+xCbu8nBlRAlsQ33k24Adj8eoVBE0f8dUeI+bAa8F84Mv05UGbAx57g2zrRsYIooqQg== dependencies: - "@typescript-eslint/types" "5.47.0" + "@typescript-eslint/types" "5.54.1" eslint-visitor-keys "^3.3.0" "@typescript-eslint/visitor-keys@5.55.0": @@ -6596,14 +6585,6 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== -aria-query@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b" - integrity sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA== - dependencies: - "@babel/runtime" "^7.10.2" - "@babel/runtime-corejs3" "^7.10.2" - aria-query@^5.1.3: version "5.1.3" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.1.3.tgz#19db27cd101152773631396f7a95a3b58c22c35e" @@ -6654,7 +6635,7 @@ array-ify@^1.0.0: resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece" integrity sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng== -array-includes@^3.0.3, array-includes@^3.1.4, array-includes@^3.1.5, array-includes@^3.1.6: +array-includes@^3.0.3, array-includes@^3.1.5, array-includes@^3.1.6: version "3.1.6" resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.6.tgz#9e9e720e194f198266ba9e18c29e6a9b0e4b225f" integrity sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw== @@ -6708,7 +6689,7 @@ array.prototype.find@^2.1.1: es-abstract "^1.20.4" es-shim-unscopables "^1.0.0" -array.prototype.flat@^1.2.1, array.prototype.flat@^1.2.3, array.prototype.flat@^1.2.5, array.prototype.flat@^1.3.1: +array.prototype.flat@^1.2.1, array.prototype.flat@^1.2.3, array.prototype.flat@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz#ffc6576a7ca3efc2f46a143b9d1dda9b4b3cf5e2" integrity sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA== @@ -6718,7 +6699,7 @@ array.prototype.flat@^1.2.1, array.prototype.flat@^1.2.3, array.prototype.flat@^ es-abstract "^1.20.4" es-shim-unscopables "^1.0.0" -array.prototype.flatmap@^1.2.1, array.prototype.flatmap@^1.3.0, array.prototype.flatmap@^1.3.1: +array.prototype.flatmap@^1.2.1, array.prototype.flatmap@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz#1aae7903c2100433cb8261cd4ed310aab5c4a183" integrity sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ== @@ -6920,7 +6901,7 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3" integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg== -axe-core@^4.4.3, axe-core@^4.6.2: +axe-core@^4.6.2: version "4.6.3" resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.6.3.tgz#fc0db6fdb65cc7a80ccf85286d91d64ababa3ece" integrity sha512-/BQzOX780JhsxDnPpH4ZiyrJAzcd8AfzFPkv+89veFSr1rcMjuq2JDCwypKaPeB6ljHp9KjXhPpjgCvQlWYuqg== @@ -6948,11 +6929,6 @@ axios@^1.0.0: form-data "^4.0.0" proxy-from-env "^1.1.0" -axobject-query@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" - integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA== - axobject-query@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-3.1.1.tgz#3b6e5c6d4e43ca7ba51c5babf99d22a9c68485e1" @@ -9099,7 +9075,7 @@ core-js-compat@^3.25.1: dependencies: browserslist "^4.21.5" -core-js-pure@^3.0.1, core-js-pure@^3.23.3, core-js-pure@^3.25.1: +core-js-pure@^3.0.1, core-js-pure@^3.23.3: version "3.29.1" resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.29.1.tgz#1be6ca2b8772f6b4df7fc4621743286e676c6162" integrity sha512-4En6zYVi0i0XlXHVz/bi6l1XDjCqkKRq765NXuX+SnaIatlE96Odt5lMLjdxUiNI1v9OXI5DSLWYPlmTfkTktg== @@ -9261,11 +9237,6 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" -cross-unzip@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/cross-unzip/-/cross-unzip-0.0.2.tgz#5183bc47a09559befcf98cc4657964999359372f" - integrity sha512-nRJ5c+aqHz0OJVU4V1bqoaDggydfauK/Gha/H/ScBvuIjhZvl8YIpdWVzSR3vUhzCloqB1tvBdQ4V7J8qK7HzQ== - crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" @@ -9508,7 +9479,7 @@ cssstyle@^2.3.0: dependencies: cssom "~0.3.6" -csstype@^2.2.0, csstype@^2.5.7: +csstype@^2.5.7: version "2.6.21" resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.21.tgz#2efb85b7cc55c80017c66a5ad7cbd931fda3a90e" integrity sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w== @@ -9564,7 +9535,7 @@ dateformat@^3.0.0: resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== -debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8, debug@^2.6.9: +debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -10286,15 +10257,15 @@ electron-builder@23.6.0: simple-update-notifier "^1.0.7" yargs "^17.5.1" -electron-devtools-installer@2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/electron-devtools-installer/-/electron-devtools-installer-2.2.4.tgz#261a50337e37121d338b966f07922eb4939a8763" - integrity sha512-b5kcM3hmUqn64+RUcHjjr8ZMpHS2WJ5YO0pnG9+P/RTdx46of/JrEjuciHWux6pE+On6ynWhHJF53j/EDJN0PA== +electron-devtools-installer@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/electron-devtools-installer/-/electron-devtools-installer-3.2.0.tgz#acc48d24eb7033fe5af284a19667e73b78d406d0" + integrity sha512-t3UczsYugm4OAbqvdImMCImIMVdFzJAHgbwHpkl5jmfu1izVgUcP/mnrPqJIpEeCK1uZGpt+yHgWEN+9EwoYhQ== dependencies: - "7zip" "0.0.6" - cross-unzip "0.0.2" - rimraf "^2.5.2" - semver "^5.3.0" + rimraf "^3.0.2" + semver "^7.2.1" + tslib "^2.1.0" + unzip-crx-3 "^0.2.0" electron-log@4.4.8: version "4.4.8" @@ -10353,10 +10324,10 @@ electron-window-state@5.0.3: jsonfile "^4.0.0" mkdirp "^0.5.1" -electron@22.2.0: - version "22.2.0" - resolved "https://registry.yarnpkg.com/electron/-/electron-22.2.0.tgz#1aa321415d8b8021a4b0807641f0ad56028feaf5" - integrity sha512-puRZSF2vWJ4pz3oetL5Td8LcuivTWz3MoAk/gjImHSN1B/2VJNEQlw1jGdkte+ppid2craOswE2lmCOZ7SwF1g== +electron@23.1.2: + version "23.1.2" + resolved "https://registry.yarnpkg.com/electron/-/electron-23.1.2.tgz#f03e361c94f8dd2407963b5461d19aadea335316" + integrity sha512-ajE6xzIwH7swf8TlTU5WklDqpI3mPj4Am6690YrpCXzcp+E+dmMBXIajUUNt4joDrFhJC/lC6ZqDS2Q1BApKgQ== dependencies: "@electron/get" "^2.0.0" "@types/node" "^16.11.26" @@ -10772,17 +10743,10 @@ eslint-config-airbnb@19.0.4: object.assign "^4.1.2" object.entries "^1.1.5" -eslint-config-prettier@6.15.0: - version "6.15.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.15.0.tgz#7f93f6cb7d45a92f1537a70ecc06366e1ac6fed9" - integrity sha512-a1+kOYLR8wMGustcgAjdydMsQ2A/2ipRPwRKUmfYaSxc9ZPcrku080Ctl6zrZzZNs/U82MjSv+qKREkoq3bJaw== - dependencies: - get-stdin "^6.0.0" - -eslint-config-prettier@8.5.0: - version "8.5.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz#5a81680ec934beca02c7b1a61cf8ca34b66feab1" - integrity sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q== +eslint-config-prettier@8.7.0: + version "8.7.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.7.0.tgz#f1cc58a8afebc50980bd53475451df146c13182d" + integrity sha512-HHVXLSlVUhMSmyW4ZzEuvjpwqamgmlfkutD53cYXLikh4pt/modINRcCIApJ84czDxM4GZInwUrromsDdTImTA== eslint-config-react-app@^7.0.1: version "7.0.1" @@ -10804,7 +10768,7 @@ eslint-config-react-app@^7.0.1: eslint-plugin-react-hooks "^4.3.0" eslint-plugin-testing-library "^5.0.1" -eslint-import-resolver-node@^0.3.6, eslint-import-resolver-node@^0.3.7: +eslint-import-resolver-node@^0.3.7: version "0.3.7" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz#83b375187d412324a1963d84fa664377a23eb4d7" integrity sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA== @@ -10813,7 +10777,7 @@ eslint-import-resolver-node@^0.3.6, eslint-import-resolver-node@^0.3.7: is-core-module "^2.11.0" resolve "^1.22.1" -eslint-module-utils@^2.7.3, eslint-module-utils@^2.7.4: +eslint-module-utils@^2.7.4: version "2.7.4" resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz#4f3e41116aaf13a20792261e61d3a2e7e0583974" integrity sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA== @@ -10828,26 +10792,7 @@ eslint-plugin-flowtype@^8.0.3: lodash "^4.17.21" string-natural-compare "^3.0.1" -eslint-plugin-import@2.26.0: - version "2.26.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz#f812dc47be4f2b72b478a021605a59fc6fe8b88b" - integrity sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA== - dependencies: - array-includes "^3.1.4" - array.prototype.flat "^1.2.5" - debug "^2.6.9" - doctrine "^2.1.0" - eslint-import-resolver-node "^0.3.6" - eslint-module-utils "^2.7.3" - has "^1.0.3" - is-core-module "^2.8.1" - is-glob "^4.0.3" - minimatch "^3.1.2" - object.values "^1.1.5" - resolve "^1.22.0" - tsconfig-paths "^3.14.1" - -eslint-plugin-import@^2.25.3: +eslint-plugin-import@2.27.5, eslint-plugin-import@^2.25.3: version "2.27.5" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz#876a6d03f52608a3e5bb439c2550588e51dd6c65" integrity sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow== @@ -10875,26 +10820,7 @@ eslint-plugin-jest@^25.3.0: dependencies: "@typescript-eslint/experimental-utils" "^5.0.0" -eslint-plugin-jsx-a11y@6.6.1: - version "6.6.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.6.1.tgz#93736fc91b83fdc38cc8d115deedfc3091aef1ff" - integrity sha512-sXgFVNHiWffBq23uiS/JaP6eVR622DqwB4yTzKvGZGcPq6/yZ3WmOZfuBks/vHWo9GaFOqC2ZK4i6+C35knx7Q== - dependencies: - "@babel/runtime" "^7.18.9" - aria-query "^4.2.2" - array-includes "^3.1.5" - ast-types-flow "^0.0.7" - axe-core "^4.4.3" - axobject-query "^2.2.0" - damerau-levenshtein "^1.0.8" - emoji-regex "^9.2.2" - has "^1.0.3" - jsx-ast-utils "^3.3.2" - language-tags "^1.0.5" - minimatch "^3.1.2" - semver "^6.3.0" - -eslint-plugin-jsx-a11y@^6.5.1: +eslint-plugin-jsx-a11y@6.7.1, eslint-plugin-jsx-a11y@^6.5.1: version "6.7.1" resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz#fca5e02d115f48c9a597a6894d5bcec2f7a76976" integrity sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA== @@ -10935,27 +10861,7 @@ eslint-plugin-react-hooks@^4.3.0: resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3" integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g== -eslint-plugin-react@7.31.10: - version "7.31.10" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.31.10.tgz#6782c2c7fe91c09e715d536067644bbb9491419a" - integrity sha512-e4N/nc6AAlg4UKW/mXeYWd3R++qUano5/o+t+wnWxIf+bLsOaH3a4q74kX3nDjYym3VBN4HyO9nEn1GcAqgQOA== - dependencies: - array-includes "^3.1.5" - array.prototype.flatmap "^1.3.0" - doctrine "^2.1.0" - estraverse "^5.3.0" - jsx-ast-utils "^2.4.1 || ^3.0.0" - minimatch "^3.1.2" - object.entries "^1.1.5" - object.fromentries "^2.0.5" - object.hasown "^1.1.1" - object.values "^1.1.5" - prop-types "^15.8.1" - resolve "^2.0.0-next.3" - semver "^6.3.0" - string.prototype.matchall "^4.0.7" - -eslint-plugin-react@^7.27.1: +eslint-plugin-react@7.32.2, eslint-plugin-react@^7.27.1: version "7.32.2" resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz#e71f21c7c265ebce01bcbc9d0955170c55571f10" integrity sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg== @@ -11035,57 +10941,13 @@ eslint-webpack-plugin@^3.1.1: normalize-path "^3.0.0" schema-utils "^4.0.0" -eslint@8.27.0: - version "8.27.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.27.0.tgz#d547e2f7239994ad1faa4bb5d84e5d809db7cf64" - integrity sha512-0y1bfG2ho7mty+SiILVf9PfuRA49ek4Nc60Wmmu62QlobNR+CeXa4xXIJgcuwSQgZiWaPH+5BDsctpIW0PR/wQ== - dependencies: - "@eslint/eslintrc" "^1.3.3" - "@humanwhocodes/config-array" "^0.11.6" - "@humanwhocodes/module-importer" "^1.0.1" - "@nodelib/fs.walk" "^1.2.8" - ajv "^6.10.0" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.3.2" - doctrine "^3.0.0" - escape-string-regexp "^4.0.0" - eslint-scope "^7.1.1" - eslint-utils "^3.0.0" - eslint-visitor-keys "^3.3.0" - espree "^9.4.0" - esquery "^1.4.0" - esutils "^2.0.2" - fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" - find-up "^5.0.0" - glob-parent "^6.0.2" - globals "^13.15.0" - grapheme-splitter "^1.0.4" - ignore "^5.2.0" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - is-path-inside "^3.0.3" - js-sdsl "^4.1.4" - js-yaml "^4.1.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash.merge "^4.6.2" - minimatch "^3.1.2" - natural-compare "^1.4.0" - optionator "^0.9.1" - regexpp "^3.2.0" - strip-ansi "^6.0.1" - strip-json-comments "^3.1.0" - text-table "^0.2.0" - -eslint@8.31.0: - version "8.31.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.31.0.tgz#75028e77cbcff102a9feae1d718135931532d524" - integrity sha512-0tQQEVdmPZ1UtUKXjX7EMm9BlgJ08G90IhWh0PKDCb3ZLsgAOHI8fYSIzYVZej92zsgq+ft0FGsxhJ3xo2tbuA== +eslint@8.35.0: + version "8.35.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.35.0.tgz#fffad7c7e326bae606f0e8f436a6158566d42323" + integrity sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw== dependencies: - "@eslint/eslintrc" "^1.4.1" + "@eslint/eslintrc" "^2.0.0" + "@eslint/js" "8.35.0" "@humanwhocodes/config-array" "^0.11.8" "@humanwhocodes/module-importer" "^1.0.1" "@nodelib/fs.walk" "^1.2.8" @@ -11099,7 +10961,7 @@ eslint@8.31.0: eslint-utils "^3.0.0" eslint-visitor-keys "^3.3.0" espree "^9.4.0" - esquery "^1.4.0" + esquery "^1.4.2" esutils "^2.0.2" fast-deep-equal "^3.1.3" file-entry-cache "^6.0.1" @@ -11190,7 +11052,7 @@ esprima@^4.0.0, esprima@^4.0.1, esprima@~4.0.0: resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.0.1, esquery@^1.4.0, esquery@^1.4.2: +esquery@^1.0.1, esquery@^1.4.2: version "1.5.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== @@ -12153,11 +12015,6 @@ get-port@^5.1.1: resolved "https://registry.yarnpkg.com/get-port/-/get-port-5.1.1.tgz#0469ed07563479de6efb986baf053dcd7d4e3193" integrity sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ== -get-stdin@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" - integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== - get-stdin@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-7.0.0.tgz#8d5de98f15171a125c5e516643c7a6d0ea8a96f6" @@ -12402,7 +12259,7 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -globals@^13.15.0, globals@^13.19.0: +globals@^13.19.0: version "13.20.0" resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82" integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ== @@ -13233,6 +13090,11 @@ immediate@^3.2.3: resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.3.0.tgz#1aef225517836bcdf7f2a2de2600c79ff0269266" integrity sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q== +immediate@~3.0.5: + version "3.0.6" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" + integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ== + immer@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/immer/-/immer-1.10.0.tgz#bad67605ba9c810275d91e1c2a47d4582e98286d" @@ -15099,7 +14961,7 @@ json3@^3.3.2: resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81" integrity sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA== -json5@2.x, json5@^2.1.1, json5@^2.1.2, json5@^2.2.0, json5@^2.2.1, json5@^2.2.2: +json5@2.x, json5@^2.1.1, json5@^2.1.2, json5@^2.2.0, json5@^2.2.2: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== @@ -15157,7 +15019,7 @@ jsqr@1.4.0: resolved "https://registry.yarnpkg.com/jsqr/-/jsqr-1.4.0.tgz#8efb8d0a7cc6863cb6d95116b9069123ce9eb2d1" integrity sha512-dxLob7q65Xg2DvstYkRpkYtmKm2sPJ9oFhrhmudT1dZvNFFTlroai3AWSpLey/w5vMcLBXRgOJsbXpdN9HzU/A== -"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.2, jsx-ast-utils@^3.3.3: +"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.3: version "3.3.3" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz#76b3e6e6cece5c69d49a5792c3d01bd1a0cdc7ea" integrity sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw== @@ -15165,6 +15027,16 @@ jsqr@1.4.0: array-includes "^3.1.5" object.assign "^4.1.3" +jszip@^3.1.0: + version "3.10.1" + resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.10.1.tgz#34aee70eb18ea1faec2f589208a157d1feb091c2" + integrity sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g== + dependencies: + lie "~3.3.0" + pako "~1.0.2" + readable-stream "~2.3.6" + setimmediate "^1.0.5" + just-diff-apply@^5.2.0: version "5.5.0" resolved "https://registry.yarnpkg.com/just-diff-apply/-/just-diff-apply-5.5.0.tgz#771c2ca9fa69f3d2b54e7c3f5c1dfcbcc47f9f0f" @@ -15230,7 +15102,7 @@ klona@^2.0.4, klona@^2.0.5: resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.6.tgz#85bffbf819c03b2f53270412420a4555ef882e22" integrity sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA== -language-subtag-registry@^0.3.20, language-subtag-registry@~0.3.2: +language-subtag-registry@~0.3.2: version "0.3.22" resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz#2e1500861b2e457eba7e7ae86877cbd08fa1fd1d" integrity sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w== @@ -15242,13 +15114,6 @@ language-tags@=1.0.5: dependencies: language-subtag-registry "~0.3.2" -language-tags@^1.0.5: - version "1.0.8" - resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.8.tgz#042b4bdb0d4e771a9f8cc2fdc9bb26a52a367312" - integrity sha512-aWAZwgPLS8hJ20lNPm9HNVs4inexz6S2sQa3wx/+ycuutMNE5/IfYxiWYBbi+9UWCQVaXYCOPUl6gFrPR7+jGg== - dependencies: - language-subtag-registry "^0.3.20" - latest-version@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" @@ -15541,6 +15406,13 @@ libnpmteam@^1.0.1: get-stream "^4.0.0" npm-registry-fetch "^4.0.0" +lie@~3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a" + integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ== + dependencies: + immediate "~3.0.5" + lilconfig@^2.0.3, lilconfig@^2.0.5, lilconfig@^2.0.6: version "2.1.0" resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" @@ -17360,7 +17232,7 @@ object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.0 define-properties "^1.1.4" es-abstract "^1.20.4" -object.hasown@^1.1.1, object.hasown@^1.1.2: +object.hasown@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.2.tgz#f919e21fad4eb38a57bc6345b3afd496515c3f92" integrity sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw== @@ -17389,26 +17261,7 @@ obuf@^1.0.0, obuf@^1.1.2: resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== -office-ui-fabric-react@7.199.6: - version "7.199.6" - resolved "https://registry.yarnpkg.com/office-ui-fabric-react/-/office-ui-fabric-react-7.199.6.tgz#68113e773e000fed95a390b0b158906bc390db85" - integrity sha512-Nxs3bmTpPeoUlDdk1pld26HornxhK9DCig74Y390fcprQc/9Y6zEDaCPqXxOCybqluNQLKoteF1Pc4kpsseofw== - dependencies: - "@fluentui/date-time-utilities" "^7.9.1" - "@fluentui/react-focus" "^7.18.17" - "@fluentui/react-window-provider" "^1.0.6" - "@microsoft/load-themed-styles" "^1.10.26" - "@uifabric/foundation" "^7.10.16" - "@uifabric/icons" "^7.9.5" - "@uifabric/merge-styles" "^7.20.2" - "@uifabric/react-hooks" "^7.16.4" - "@uifabric/set-version" "^7.0.24" - "@uifabric/styling" "^7.25.1" - "@uifabric/utilities" "^7.38.2" - prop-types "^15.7.2" - tslib "^1.10.0" - -office-ui-fabric-react@^7.199.6, office-ui-fabric-react@^7.204.0: +office-ui-fabric-react@7.204.0, office-ui-fabric-react@^7.199.6, office-ui-fabric-react@^7.204.0: version "7.204.0" resolved "https://registry.yarnpkg.com/office-ui-fabric-react/-/office-ui-fabric-react-7.204.0.tgz#1bec4d14f91bee8fddf2fc05bdc1a8af462211fa" integrity sha512-W1xIsYEwxPrGYojvVtGTGvSfdnUoPEm8w6hhMlW/uFr5YwIB1isG/dVk4IZxWbcbea7612u059p+jRf+RjPW0w== @@ -17769,7 +17622,7 @@ pacote@^9.2.3, pacote@^9.5.0: unique-filename "^1.1.1" which "^1.3.1" -pako@~1.0.5: +pako@~1.0.2, pako@~1.0.5: version "1.0.11" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== @@ -19429,7 +19282,7 @@ react-hotkeys@2.0.0: dependencies: prop-types "^15.6.1" -react-i18next@11.18.6, react-i18next@>=11.16.4: +react-i18next@12.1.5, react-i18next@>=11.16.4: version "12.2.0" resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-12.2.0.tgz#010e3f6070b8d700442947233352ebe4b252d7a1" integrity sha512-5XeVgSygaGfyFmDd2WcXvINRw2WEC1XviW1LXY/xLOEMzsCFRwKqfnHN+hUjla8ZipbVJR27GCMSuTr0BhBBBQ== @@ -19626,17 +19479,7 @@ react-syntax-highlighter@^11.0.2: prismjs "^1.8.4" refractor "^2.4.1" -react-test-renderer@16.12.0: - version "16.12.0" - resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.12.0.tgz#11417ffda579306d4e841a794d32140f3da1b43f" - integrity sha512-Vj/teSqt2oayaWxkbhQ6gKis+t5JrknXfPVo+aIJ8QwYAqMPH77uptOdrlphyxl8eQI/rtkOYg86i/UWkpFu0w== - dependencies: - object-assign "^4.1.1" - prop-types "^15.6.2" - react-is "^16.8.6" - scheduler "^0.18.0" - -react-test-renderer@^16.0.0-0: +react-test-renderer@16.14.0, react-test-renderer@^16.0.0-0: version "16.14.0" resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.14.0.tgz#e98360087348e260c56d4fe2315e970480c228ae" integrity sha512-L8yPjqPE5CZO6rKsKXRO/rVPiaCOy0tQQJbC+UjPNlobl5mad59lvPjwFsQHTvL03caVDIVr9x9/OSgDe6I5Eg== @@ -20225,7 +20068,7 @@ resolve@1.1.7: resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" integrity sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg== -resolve@>=1.9.0, resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.11.0, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.0, resolve@^1.22.1, resolve@^1.3.2: +resolve@>=1.9.0, resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.11.0, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.1, resolve@^1.3.2: version "1.22.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== @@ -20234,7 +20077,7 @@ resolve@>=1.9.0, resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.11. path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -resolve@^2.0.0-next.3, resolve@^2.0.0-next.4: +resolve@^2.0.0-next.4: version "2.0.0-next.4" resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.4.tgz#3d37a113d6429f496ec4752d2a2e58efb1fd4660" integrity sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ== @@ -20495,10 +20338,10 @@ sass-loader@^12.3.0: klona "^2.0.4" neo-async "^2.6.2" -sass@1.56.1: - version "1.56.1" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.56.1.tgz#94d3910cd468fd075fa87f5bb17437a0b617d8a7" - integrity sha512-VpEyKpyBPCxE7qGDtOcdJ6fFbcpOM+Emu7uZLxVrkX8KVU/Dp5UF7WLvzqRuUhB6mqqQt1xffLoG+AndxTZrCQ== +sass@1.58.3: + version "1.58.3" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.58.3.tgz#2348cc052061ba4f00243a208b09c40e031f270d" + integrity sha512-Q7RaEtYf6BflYrQ+buPudKR26/lH+10EmO9bBqbmPh/KeLqv8bjpTNqxe71ocONqXq+jYiCbpPUmQMS+JJPk4A== dependencies: chokidar ">=3.0.0 <4.0.0" immutable "^4.0.0" @@ -20516,14 +20359,6 @@ saxes@^5.0.1: dependencies: xmlchars "^2.2.0" -scheduler@^0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.18.0.tgz#5901ad6659bc1d8f3fdaf36eb7a67b0d6746b1c4" - integrity sha512-agTSHR1Nbfi6ulI0kYNK0203joW2Y5W4po4l+v03tOoiJKpTBbxpNhWDvqc/4IcOw+KLmSiQLTasZ4cab2/UWQ== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - scheduler@^0.19.1: version "0.19.1" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196" @@ -20615,7 +20450,7 @@ semver-diff@^2.0.0: dependencies: semver "^5.0.3" -"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1: +"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -20627,7 +20462,7 @@ semver@7.3.4: dependencies: lru-cache "^6.0.0" -semver@7.x, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8: +semver@7.x, semver@^7.0.0, semver@^7.1.1, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8: version "7.3.8" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== @@ -20738,7 +20573,7 @@ set-value@^2.0.0, set-value@^2.0.1: is-plain-object "^2.0.3" split-string "^3.0.1" -setimmediate@^1.0.4: +setimmediate@^1.0.4, setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== @@ -21216,10 +21051,10 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== -sqlite3@5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/sqlite3/-/sqlite3-5.1.2.tgz#f50d5b1482b6972fb650daf6f718e6507c6cfb0f" - integrity sha512-D0Reg6pRWAFXFUnZKsszCI67tthFD8fGPewRddDCX6w4cYwz3MbvuwRICbL+YQjBAh9zbw+lJ/V9oC8nG5j6eg== +sqlite3@5.1.4: + version "5.1.4" + resolved "https://registry.yarnpkg.com/sqlite3/-/sqlite3-5.1.4.tgz#35f83d368963168b324ad2f0fffce09f3b8723a7" + integrity sha512-i0UlWAzPlzX3B5XP2cYuhWQJsTtlMD6obOa1PgeEQ4DHEXUuyJkgv50I3isqZAP5oFc2T8OFvakmDh2W6I+YpA== dependencies: "@mapbox/node-pre-gyp" "^1.0.0" node-addon-api "^4.2.0" @@ -21450,7 +21285,7 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -"string.prototype.matchall@^4.0.0 || ^3.0.1", string.prototype.matchall@^4.0.6, string.prototype.matchall@^4.0.7, string.prototype.matchall@^4.0.8: +"string.prototype.matchall@^4.0.0 || ^3.0.1", string.prototype.matchall@^4.0.6, string.prototype.matchall@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz#3bf85722021816dcd1bf38bb714915887ca79fd3" integrity sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg== @@ -22324,10 +22159,10 @@ tty-browserify@0.0.0: resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" integrity sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw== -ttypescript@1.5.13: - version "1.5.13" - resolved "https://registry.yarnpkg.com/ttypescript/-/ttypescript-1.5.13.tgz#c3bcb760599fe49157d30c5d5895a0023cbb7f30" - integrity sha512-KT/RBfGGlVJFqEI8cVvI3nMsmYcFvPSZh8bU0qX+pAwbi7/ABmYkzn7l/K8skw0xmYjVCoyaV6WLsBQxdadybQ== +ttypescript@1.5.15: + version "1.5.15" + resolved "https://registry.yarnpkg.com/ttypescript/-/ttypescript-1.5.15.tgz#e45550ad69289d06d3bc3fd4a3c87e7c1ef3eba7" + integrity sha512-48ykDNHzFnPMnv4hYX1P8Q84TvCZyL1QlFxeuxsuZ48X2+ameBgPenvmCkHJtoOSxpoWTWi8NcgNrRnVDOmfSg== dependencies: resolve ">=1.9.0" @@ -22705,6 +22540,15 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" +unzip-crx-3@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/unzip-crx-3/-/unzip-crx-3-0.2.0.tgz#d5324147b104a8aed9ae8639c95521f6f7cda292" + integrity sha512-0+JiUq/z7faJ6oifVB5nSwt589v1KCduqIJupNVDoWSXZtWDmjDGO3RAEOvwJ07w90aoXoP4enKsR7ecMrJtWQ== + dependencies: + jszip "^3.1.0" + mkdirp "^0.5.1" + yaku "^0.16.6" + upath@^1.1.1, upath@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" @@ -23752,6 +23596,11 @@ y18n@^5.0.5: resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== +yaku@^0.16.6: + version "0.16.7" + resolved "https://registry.yarnpkg.com/yaku/-/yaku-0.16.7.tgz#1d195c78aa9b5bf8479c895b9504fd4f0847984e" + integrity sha512-Syu3IB3rZvKvYk7yTiyl1bo/jiEFaaStrgv1V2TIJTqYPStSMQVO8EQjg/z+DRzLq/4LIIharNT3iH1hylEIRw== + yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" From 085e1f21c26edebacf681e2c6cefefb985e0ba20 Mon Sep 17 00:00:00 2001 From: Chen Yu Date: Thu, 6 Apr 2023 14:41:20 +0800 Subject: [PATCH 25/52] feat: download ckb_aarch64 for neuron-arm64 (#2627) --- .ckb-version | 2 +- .github/workflows/package_for_test.yml | 12 ++++----- packages/neuron-wallet/electron-builder.yml | 2 +- scripts/download-ckb.sh | 30 ++++++++++++++++----- 4 files changed, 32 insertions(+), 14 deletions(-) diff --git a/.ckb-version b/.ckb-version index f6e84c7e2f..78519a718c 100644 --- a/.ckb-version +++ b/.ckb-version @@ -1 +1 @@ -v0.107.0 +v0.108.1 diff --git a/.github/workflows/package_for_test.yml b/.github/workflows/package_for_test.yml index 7daf40df09..d3f1217d84 100644 --- a/.github/workflows/package_for_test.yml +++ b/.github/workflows/package_for_test.yml @@ -97,28 +97,28 @@ jobs: if: matrix.os == 'macos-11' uses: actions/upload-artifact@v3 with: - name: Neuron-Mac + name: Neuron-Mac-x64 path: release/Neuron-*-mac-x64.zip - name: Upload Neuron App Zip(arm64) - if: matrix.os == 'macos-latest' + if: matrix.os == 'macos-11' uses: actions/upload-artifact@v3 with: - name: Neuron-Mac + name: Neuron-Mac-arm64 path: release/Neuron-*-mac-arm64.zip - name: Upload Neuron Dmg if: matrix.os == 'macos-11' uses: actions/upload-artifact@v3 with: - name: Neuron-Dmg + name: Neuron-Dmg-x64 path: release/Neuron-*-x64.dmg - name: Upload Neuron Dmg(arm64) - if: matrix.os == 'macos-latest' + if: matrix.os == 'macos-11' uses: actions/upload-artifact@v3 with: - name: Neuron-Dmg + name: Neuron-Dmg-arm64 path: release/Neuron-*-arm64.dmg - name: Upload Neuron Win diff --git a/packages/neuron-wallet/electron-builder.yml b/packages/neuron-wallet/electron-builder.yml index 78c65c631b..8125c6b0da 100644 --- a/packages/neuron-wallet/electron-builder.yml +++ b/packages/neuron-wallet/electron-builder.yml @@ -51,7 +51,7 @@ mac: category: public.app-category.finance icon: assets/icons/icon.icns extraFiles: - - from: "bin/mac/ckb" + - from: "bin/mac/ckb-${arch}" to: "bin/ckb" hardenedRuntime: true gatekeeperAssess: false diff --git a/scripts/download-ckb.sh b/scripts/download-ckb.sh index 87ecae43e2..20474ec7c2 100755 --- a/scripts/download-ckb.sh +++ b/scripts/download-ckb.sh @@ -2,15 +2,33 @@ CKB_VERSION=$(cat .ckb-version) ROOT_DIR=$(pwd) # Be sure to run this from root directory! +GITHUB_RELEASE_URL="https://github.com/nervosnetwork/ckb/releases/download" function download_macos() { - # macOS - CKB_FILENAME="ckb_${CKB_VERSION}_x86_64-apple-darwin-portable" + download_macos_x86_64 + download_macos_aarch64 +} + +function download_macos_x86_64() { + # for macOS x64 + CKB_FILENAME="ckb_${CKB_VERSION}_x86_64-apple-darwin" cd $ROOT_DIR/packages/neuron-wallet/bin/mac - curl -O -L "https://github.com/nervosnetwork/ckb/releases/download/${CKB_VERSION}/${CKB_FILENAME}.zip" + curl -O -L "${GITHUB_RELEASE_URL}/${CKB_VERSION}/${CKB_FILENAME}.zip" unzip ${CKB_FILENAME}.zip - cp ${CKB_FILENAME}/ckb ./ + cp ${CKB_FILENAME}/ckb ./ckb-x64 + rm -rf $CKB_FILENAME + rm ${CKB_FILENAME}.zip +} + +function download_macos_aarch64() { + # for macOS arm64 + CKB_FILENAME="ckb_${CKB_VERSION}_aarch64-apple-darwin" + cd $ROOT_DIR/packages/neuron-wallet/bin/mac + + curl -O -L "${GITHUB_RELEASE_URL}/${CKB_VERSION}/${CKB_FILENAME}.zip" + unzip ${CKB_FILENAME}.zip + cp ${CKB_FILENAME}/ckb ./ckb-arm64 rm -rf $CKB_FILENAME rm ${CKB_FILENAME}.zip } @@ -20,7 +38,7 @@ function download_linux() { CKB_FILENAME="ckb_${CKB_VERSION}_x86_64-unknown-linux-gnu-portable" cd $ROOT_DIR/packages/neuron-wallet/bin/linux - curl -O -L "https://github.com/nervosnetwork/ckb/releases/download/${CKB_VERSION}/${CKB_FILENAME}.tar.gz" + curl -O -L "${GITHUB_RELEASE_URL}/${CKB_VERSION}/${CKB_FILENAME}.tar.gz" tar xvzf ${CKB_FILENAME}.tar.gz cp ${CKB_FILENAME}/ckb ./ rm -rf $CKB_FILENAME @@ -32,7 +50,7 @@ function download_windows() { CKB_FILENAME="ckb_${CKB_VERSION}_x86_64-pc-windows-msvc" cd $ROOT_DIR/packages/neuron-wallet/bin/win - curl -O -L "https://github.com/nervosnetwork/ckb/releases/download/${CKB_VERSION}/${CKB_FILENAME}.zip" + curl -O -L "${GITHUB_RELEASE_URL}/${CKB_VERSION}/${CKB_FILENAME}.zip" unzip ${CKB_FILENAME}.zip cp ${CKB_FILENAME}/ckb.exe ./ rm -rf $CKB_FILENAME From 1cf76c1e27149842b81d51fe7bc1e903ac18d1d1 Mon Sep 17 00:00:00 2001 From: Jun Ma Date: Fri, 14 Apr 2023 14:24:57 +0800 Subject: [PATCH 26/52] Feat/implement dynamic fee rate based on fee rate statistics (#2599) --- packages/neuron-ui/package.json | 4 +- .../src/components/NFTSend/index.tsx | 8 +- .../src/components/NervosDAO/hooks.ts | 25 ++- .../src/components/NervosDAO/index.tsx | 33 +++- .../src/components/PricePanel/index.tsx | 175 ++++++++++++++++++ .../PricePanel/pricePanel.module.scss | 93 ++++++++++ .../src/components/SUDTSend/index.tsx | 3 +- .../neuron-ui/src/components/Send/hooks.ts | 50 ++++- .../src/components/SendMetaInfo/index.tsx | 4 +- .../src/components/SpecialAssetList/index.tsx | 6 +- .../components/TransactionFeePanel/index.tsx | 69 +------ packages/neuron-ui/src/locales/en.json | 16 ++ packages/neuron-ui/src/locales/zh-tw.json | 16 ++ packages/neuron-ui/src/locales/zh.json | 16 ++ packages/neuron-ui/src/services/chain.ts | 3 +- .../src/states/stateProvider/reducer.ts | 6 + .../src/stories/SendMetaInfo.stories.tsx | 2 +- packages/neuron-ui/src/styles/color.scss | 4 + packages/neuron-ui/src/types/App/index.d.ts | 3 + packages/neuron-ui/src/utils/calculateFee.ts | 2 +- .../src/utils/hooks/createSUDTAccount.ts | 14 +- .../hooks/useGetCountDownAndFeeRateStats.ts | 62 +++++++ .../index.module.scss | 94 ++++++++++ .../DropdownWithCustomRender/index.tsx | 171 +++++++++++++++++ .../src/widgets/Icons/LineDownArrow.svg | 4 + .../neuron-ui/src/widgets/Icons/Transfer.svg | 5 + packages/neuron-ui/src/widgets/Icons/icon.tsx | 4 + .../widgets/TextField/textField.module.scss | 4 +- packages/neuron-wallet/package.json | 4 +- yarn.lock | 60 +++--- 30 files changed, 830 insertions(+), 130 deletions(-) create mode 100644 packages/neuron-ui/src/components/PricePanel/index.tsx create mode 100644 packages/neuron-ui/src/components/PricePanel/pricePanel.module.scss create mode 100644 packages/neuron-ui/src/utils/hooks/useGetCountDownAndFeeRateStats.ts create mode 100644 packages/neuron-ui/src/widgets/DropdownWithCustomRender/index.module.scss create mode 100644 packages/neuron-ui/src/widgets/DropdownWithCustomRender/index.tsx create mode 100644 packages/neuron-ui/src/widgets/Icons/LineDownArrow.svg create mode 100644 packages/neuron-ui/src/widgets/Icons/Transfer.svg diff --git a/packages/neuron-ui/package.json b/packages/neuron-ui/package.json index e38ead95af..43ed8b4eef 100644 --- a/packages/neuron-ui/package.json +++ b/packages/neuron-ui/package.json @@ -40,8 +40,8 @@ "last 2 chrome versions" ], "dependencies": { - "@nervosnetwork/ckb-sdk-core": "0.103.1", - "@nervosnetwork/ckb-sdk-utils": "0.103.1", + "@nervosnetwork/ckb-sdk-core": "0.107.0", + "@nervosnetwork/ckb-sdk-utils": "0.107.0", "@uifabric/experiments": "7.45.14", "@uifabric/styling": "7.25.1", "canvg": "2.0.0", diff --git a/packages/neuron-ui/src/components/NFTSend/index.tsx b/packages/neuron-ui/src/components/NFTSend/index.tsx index 8baef82697..8202c7b11a 100644 --- a/packages/neuron-ui/src/components/NFTSend/index.tsx +++ b/packages/neuron-ui/src/components/NFTSend/index.tsx @@ -3,10 +3,10 @@ import { useTranslation } from 'react-i18next' import { useLocation, useParams } from 'react-router-dom' import { useState as useGlobalState, useDispatch, AppActions } from 'states' import { isMainnet as isMainnetUtil, isSuccessResponse, validateAddress } from 'utils' +import useGetCountDownAndFeeRateStats from 'utils/hooks/useGetCountDownAndFeeRateStats' import TextField from 'widgets/TextField' import { generateNFTSendTransaction } from 'services/remote' import Button from 'widgets/Button' -import { MEDIUM_FEE_RATE } from 'utils/const' import { ReactComponent as Attention } from 'widgets/Icons/Attention.svg' import { isErrorWithI18n } from 'exceptions' import styles from './NFTSend.module.scss' @@ -48,8 +48,8 @@ const NFTSend = () => { } = useGlobalState() const [t] = useTranslation() const globalDispatch = useDispatch() + const { suggestFeeRate } = useGetCountDownAndFeeRateStats() const timerRef = useRef(null) - const [sendState, dispatch] = useReducer(reducer, initState) const [remoteError, setRemoteError] = useState('') @@ -122,7 +122,7 @@ const NFTSend = () => { receiveAddress: sendState.address, outPoint, description: sendState.description, - feeRate: `${MEDIUM_FEE_RATE}`, + feeRate: `${suggestFeeRate}`, } generateNFTSendTransaction(params) @@ -141,7 +141,7 @@ const NFTSend = () => { }) }, TIMER_DELAY) return clearTimer - }, [isSubmittable, globalDispatch, sendState, walletId, outPoint]) + }, [isSubmittable, globalDispatch, sendState, walletId, outPoint, suggestFeeRate]) return (
diff --git a/packages/neuron-ui/src/components/NervosDAO/hooks.ts b/packages/neuron-ui/src/components/NervosDAO/hooks.ts index 58a66ea222..3a70110bad 100644 --- a/packages/neuron-ui/src/components/NervosDAO/hooks.ts +++ b/packages/neuron-ui/src/components/NervosDAO/hooks.ts @@ -44,17 +44,19 @@ export const useUpdateMaxDeposit = ({ setMaxDepositTx, setMaxDepositErrorMessage, isBalanceReserved, + suggestFeeRate, }: { wallet: State.Wallet setMaxDepositAmount: React.Dispatch> setMaxDepositTx: React.Dispatch> setMaxDepositErrorMessage: React.Dispatch> isBalanceReserved: boolean + suggestFeeRate: number | string }) => { useEffect(() => { generateDaoDepositAllTx({ walletID: wallet.id, - feeRate: `${MEDIUM_FEE_RATE}`, + feeRate: `${suggestFeeRate}`, isBalanceReserved, }) .then((res: any) => { @@ -72,7 +74,15 @@ export const useUpdateMaxDeposit = ({ setMaxDepositTx(undefined) setMaxDepositErrorMessage(err.message) }) - }, [wallet.id, wallet.balance, setMaxDepositAmount, setMaxDepositErrorMessage, setMaxDepositTx, isBalanceReserved]) + }, [ + wallet.id, + wallet.balance, + setMaxDepositAmount, + setMaxDepositErrorMessage, + setMaxDepositTx, + isBalanceReserved, + suggestFeeRate, + ]) } export const useInitData = ({ @@ -129,6 +139,7 @@ export const useUpdateDepositValue = ({ maxDepositErrorMessage, isBalanceReserved, t, + suggestFeeRate, }: { setDepositValue: React.Dispatch> setErrorMessage: React.Dispatch> @@ -140,6 +151,7 @@ export const useUpdateDepositValue = ({ maxDepositErrorMessage: string isBalanceReserved: boolean t: TFunction + suggestFeeRate: number | string }) => useCallback( (value: string) => { @@ -171,7 +183,7 @@ export const useUpdateDepositValue = ({ const capacity = CKBToShannonFormatter(amount, CapacityUnit.CKB) if (BigInt(capacity) < maxDepositAmount) { generateDaoDepositTx({ - feeRate: `${MEDIUM_FEE_RATE}`, + feeRate: `${suggestFeeRate}`, capacity, walletID, }).then(res => { @@ -213,6 +225,7 @@ export const useUpdateDepositValue = ({ setDepositValue, setErrorMessage, isBalanceReserved, + suggestFeeRate, ] ) @@ -298,19 +311,21 @@ export const useOnWithdrawDialogSubmit = ({ clearGeneratedTx, walletID, dispatch, + suggestFeeRate, }: { activeRecord: State.NervosDAORecord | null setActiveRecord: React.Dispatch clearGeneratedTx: () => void walletID: string dispatch: React.Dispatch + suggestFeeRate: number | string }) => useCallback(() => { if (activeRecord) { generateDaoWithdrawTx({ walletID, outPoint: activeRecord.outPoint, - feeRate: `${MEDIUM_FEE_RATE}`, + feeRate: `${suggestFeeRate}`, }) .then(res => { if (isSuccessResponse(res)) { @@ -342,7 +357,7 @@ export const useOnWithdrawDialogSubmit = ({ }) } setActiveRecord(null) - }, [activeRecord, setActiveRecord, clearGeneratedTx, walletID, dispatch]) + }, [activeRecord, setActiveRecord, clearGeneratedTx, walletID, dispatch, suggestFeeRate]) export const useOnActionClick = ({ records, diff --git a/packages/neuron-ui/src/components/NervosDAO/index.tsx b/packages/neuron-ui/src/components/NervosDAO/index.tsx index 635300d2d3..2fef820a42 100644 --- a/packages/neuron-ui/src/components/NervosDAO/index.tsx +++ b/packages/neuron-ui/src/components/NervosDAO/index.tsx @@ -1,9 +1,9 @@ import React, { useEffect, useState, useMemo, useCallback } from 'react' +import { useState as useGlobalState, useDispatch, AppActions } from 'states' import { useTranslation } from 'react-i18next' import { ReactComponent as TooltipIcon } from 'widgets/Icons/Tooltip.svg' import appState from 'states/init/app' -import { useState as useGlobalState, useDispatch } from 'states' import { CONSTANTS, @@ -15,9 +15,12 @@ import { getCurrentUrl, getSyncStatus, CKBToShannonFormatter, + ErrorCode, + CapacityUnit, + isSuccessResponse, } from 'utils' -import { openExternal } from 'services/remote' +import { generateDaoDepositTx, openExternal } from 'services/remote' import DepositDialog from 'components/DepositDialog' import WithdrawDialog from 'components/WithdrawDialog' @@ -26,6 +29,7 @@ import BalanceSyncIcon from 'components/BalanceSyncingIcon' import Button from 'widgets/Button' import CopyZone from 'widgets/CopyZone' +import useGetCountDownAndFeeRateStats from 'utils/hooks/useGetCountDownAndFeeRateStats' import hooks from './hooks' import styles from './nervosDAO.module.scss' @@ -55,6 +59,7 @@ const NervosDAO = () => { } = useGlobalState() const dispatch = useDispatch() const [t, { language }] = useTranslation() + const { suggestFeeRate } = useGetCountDownAndFeeRateStats() const [depositValue, setDepositValue] = useState(`${MIN_DEPOSIT_AMOUNT}`) const [showDepositDialog, setShowDepositDialog] = useState(false) const [activeRecord, setActiveRecord] = useState(null) @@ -79,6 +84,7 @@ const NervosDAO = () => { maxDepositErrorMessage, isBalanceReserved, t, + suggestFeeRate, }) const onDepositValueChange = hooks.useOnDepositValueChange({ updateDepositValue }) @@ -102,6 +108,7 @@ const NervosDAO = () => { setMaxDepositTx, setMaxDepositErrorMessage, isBalanceReserved, + suggestFeeRate, }) hooks.useInitData({ clearGeneratedTx, dispatch, updateDepositValue, wallet, setGenesisBlockTimestamp }) hooks.useUpdateGlobalAPC({ bestKnownBlockTimestamp, genesisBlockTimestamp, setGlobalAPC }) @@ -111,6 +118,7 @@ const NervosDAO = () => { clearGeneratedTx, walletID: wallet.id, dispatch, + suggestFeeRate, }) const onActionClick = hooks.useOnActionClick({ @@ -244,6 +252,27 @@ const NervosDAO = () => { } }, [maxDepositAmount, depositValue, setDepositValue]) + useEffect(() => { + generateDaoDepositTx({ + feeRate: `${suggestFeeRate}`, + capacity: CKBToShannonFormatter(depositValue, CapacityUnit.CKB), + walletID: wallet.id, + }).then(res => { + if (isSuccessResponse(res)) { + dispatch({ + type: AppActions.UpdateGeneratedTx, + payload: res.result, + }) + } else if (res.status === 0) { + setErrorMessage(`${typeof res.message === 'string' ? res.message : res.message.content}`) + } else if (res.status === ErrorCode.CapacityNotEnoughForChange) { + setErrorMessage(t(`messages.codes.106`)) + } else { + setErrorMessage(t(`messages.codes.${res.status}`)) + } + }) + }, [suggestFeeRate, depositValue]) + const MemoizedDepositDialog = useMemo(() => { return ( void +} +enum PriceTypeEnum { + Custom = 'custom', + Standard = 'standard', +} +const DEFAULT_PRICE_ARRAY = ['1000', '2000', '3000'] +const DEFAULT_COUNT_DOWN = 30 + +const PricePanel: React.FunctionComponent = ({ price, field, onPriceChange }: PricePanelProps) => { + const [t] = useTranslation() + const [type, setType] = useState(PriceTypeEnum.Standard) + const [feeRateValueArray, setFeeRateValueArray] = useState([]) + const [priceArray, setPriceArray] = useState(DEFAULT_PRICE_ARRAY) + const [currentModeIdx, setCurrentModeIdx] = useState(1) + + const { + app: { send = appState.send }, + wallet: { id: walletID = '' }, + } = useGlobalState() + const { countDown, suggestFeeRate } = useGetCountDownAndFeeRateStats({ seconds: DEFAULT_COUNT_DOWN }) + + const isStandard = type === PriceTypeEnum.Standard + const label = isStandard ? t('price-switch.price') : t('price-switch.customPrice') + const percent = (countDown / DEFAULT_COUNT_DOWN) * 100 + + const handleDropdownChange = useCallback( + (e: { value: string; index?: number }) => { + const { value: dropdownChangedValue, index = 1 } = e + setCurrentModeIdx(index) + + onPriceChange?.(dropdownChangedValue) + }, + [setCurrentModeIdx, onPriceChange] + ) + + const dropdownValue = useMemo(() => priceArray[currentModeIdx], [priceArray, currentModeIdx]) + + const handleInputChange = useCallback( + (e: React.SyntheticEvent) => { + const { value: inputChangedValue } = e.currentTarget + + onPriceChange?.(inputChangedValue) + }, + [onPriceChange] + ) + + const inputError = useMemo(() => (Number(price) < 1000 ? t('price-switch.errorTip', { minPrice: 1000 }) : null), [ + price, + ]) + + const feeValuesArray = useMemo( + () => + feeRateValueArray?.map((item: FeeRateValueArrayItemType) => ({ + feeRateValue: item.feeRateValue, + value: shannonToCKBFormatter(item.feeValue), + })), + [feeRateValueArray] + ) + + useEffect(() => { + if (isStandard) { + handleDropdownChange({ value: priceArray[currentModeIdx], index: currentModeIdx }) + } + }, [isStandard, handleDropdownChange, priceArray]) + + const options = useMemo( + () => + ['slow', 'standard', 'fast'].map((mode, idx) => ({ + idx, + value: priceArray[idx], + label: ( +
+ {t(`price-switch.${mode}`)} + + {t('price-switch.priceColumn', { + priceValue: feeValuesArray?.[idx]?.feeRateValue || priceArray[idx], + feeValue: feeValuesArray?.[idx]?.value || 0, + })} + +
+ ), + })), + [priceArray, feeValuesArray] + ) + + useEffect(() => { + useGetBatchGeneratedTx({ walletID, items: send.outputs, priceArray }).then(res => { + setFeeRateValueArray(res) + }) + }, [send.outputs, priceArray]) + + useEffect(() => { + if (suggestFeeRate === 0) { + setPriceArray(['1000', '2000', '3000']) + } else { + setPriceArray(['1000', `${suggestFeeRate}`, `${Number(suggestFeeRate) * 2 - 1000}`]) + } + }, [suggestFeeRate]) + + const inputHint = t('price-switch.hintTip', { suggestFeeRate }) + + return ( +
+
+
+ + +
+ {isStandard ? ( +
+ + {t('price-switch.countDownTip', { countDown })} +
+ ) : null} +
+ + {isStandard ? ( +
+ +
+ ) : ( + + )} +
+ ) +} + +PricePanel.displayName = 'PricePanel' + +export default React.memo(PricePanel) diff --git a/packages/neuron-ui/src/components/PricePanel/pricePanel.module.scss b/packages/neuron-ui/src/components/PricePanel/pricePanel.module.scss new file mode 100644 index 0000000000..23939161ee --- /dev/null +++ b/packages/neuron-ui/src/components/PricePanel/pricePanel.module.scss @@ -0,0 +1,93 @@ +@import '../../styles/mixin.scss'; + +.pricePanel { + display: flex; + justify-content: space-between; + font-size: 0.875rem; + line-height: 1.125rem; + + .transferSwitch { + display: flex; + } +} + +.transferWrap { + display: flex; + align-items: center; + position: relative; + border: none; + background: none; + + &:hover { + font-size: 14px; + + svg > path { + fill: var(--active-color); + } + + &::after { + position: absolute; + display: inline-block; + left: 50%; + transform: translate(-50%, -99%); + padding: 12px; + border-radius: 8px; + overflow-wrap: break-word; + background-color: var(--tooltip-background-color); + color: var(--tooltip-font-color); + user-select: text; + white-space: nowrap; + text-align: center; + content: attr(data-content); + } + &::before { + content: ''; + user-select: text; + border-width: 9px; + border-style: solid; + border-color: transparent; + display: inline-block; + border-top-color: var(--tooltip-background-color); + transform: translate(-50%, -70%); + left: 50%; + position: absolute; + } + } +} + +.dropdownBox { + margin: 4px 0px 19px 0px; +} +.suffix { + font-family: inherit; + display: flex; + justify-content: center; + align-items: center; + color: #434343; + padding: 0 10px; + font-size: 0.75rem; + max-width: 200px; +} +.timeoutWrap { + display: flex; + align-items: center; + font-size: 14px; + gap: 4px; +} +.labelWrap { + color: #333; + font-weight: 500; + font-size: 12px; + + .labelComment { + display: inline-block; + font-weight: 400; + background-color: #effaf7; + color: #00c891; + padding: 2px 8px; + border-radius: 24px; + margin-left: 8px; + font-size: 10px; + line-height: 14px; + } +} diff --git a/packages/neuron-ui/src/components/SUDTSend/index.tsx b/packages/neuron-ui/src/components/SUDTSend/index.tsx index fbb80a63e7..34afa7c3ec 100644 --- a/packages/neuron-ui/src/components/SUDTSend/index.tsx +++ b/packages/neuron-ui/src/components/SUDTSend/index.tsx @@ -280,8 +280,7 @@ const SUDTSend = () => { }, [dispatch, sendState.sendAll]) const onPriceChange = useCallback( - (e: React.SyntheticEvent) => { - const { value } = e.target as HTMLInputElement + (value: string) => { const price = value.split('.')[0].replace(/[^\d]/, '') dispatch({ type: Fields.Price, payload: price }) }, diff --git a/packages/neuron-ui/src/components/Send/hooks.ts b/packages/neuron-ui/src/components/Send/hooks.ts index aa8daf4219..55b1141b45 100644 --- a/packages/neuron-ui/src/components/Send/hooks.ts +++ b/packages/neuron-ui/src/components/Send/hooks.ts @@ -2,6 +2,7 @@ import React, { useState, useCallback, useEffect, useMemo } from 'react' import { TFunction } from 'i18next' import { AppActions, StateDispatch } from 'states/stateProvider/reducer' import { generateTx, generateSendingAllTx } from 'services/remote/wallets' +import { ControllerResponse, SuccessFromController } from 'services/remote/remoteApiWrapper' import { outputsToTotalAmount, @@ -168,6 +169,7 @@ const useOnTransactionChange = ( type: AppActions.UpdateGeneratedTx, payload: null, }) + updateTransactionWith(generateTx)({ walletID, items, @@ -233,9 +235,9 @@ const useOnItemChange = (updateTransactionOutput: Function) => const useUpdateTransactionPrice = (dispatch: StateDispatch) => useCallback( - (e: React.SyntheticEvent) => { - const { value } = e.target as HTMLInputElement + (value: string) => { const price = value.split('.')[0].replace(/[^\d]/g, '') + dispatch({ type: AppActions.UpdateSendPrice, payload: price.replace(/,/g, ''), @@ -264,6 +266,50 @@ const clear = (dispatch: StateDispatch) => { const useClear = (dispatch: StateDispatch) => useCallback(() => clear(dispatch), [dispatch]) +export type FeeRateValueArrayItemType = { + feeRateValue: string + feeValue: string +} + +export const useGetBatchGeneratedTx = async ({ + walletID, + priceArray = [], + items, +}: { + walletID: string + priceArray?: string[] + items: Readonly +}) => { + const getUpdateGeneratedTx = (params: Controller.GenerateTransactionParams) => + generateTx(params).then((res: ControllerResponse) => { + if (res.status === 1) { + return (res as SuccessFromController).result + } + return res + }) + + const realParams = { + walletID, + items: items.map(item => ({ + address: item.address!, + capacity: CKBToShannonFormatter(item.amount, item.unit), + date: item.date, + })), + } + + const requestArray = priceArray.map(itemPrice => getUpdateGeneratedTx({ ...realParams, feeRate: itemPrice })) + const allPromiseResult = await Promise.allSettled(requestArray) + + const feeRateValueArray: FeeRateValueArrayItemType[] = allPromiseResult?.map( + (batchItem: PromiseSettledResult, index: number) => ({ + feeRateValue: priceArray[index], + feeValue: batchItem.status === 'fulfilled' ? calculateFee(batchItem.value) : '', + }) + ) + + return feeRateValueArray +} + export const useInitialize = ( walletID: string, items: Readonly, diff --git a/packages/neuron-ui/src/components/SendMetaInfo/index.tsx b/packages/neuron-ui/src/components/SendMetaInfo/index.tsx index 0d41481f26..5e4bd5aa33 100644 --- a/packages/neuron-ui/src/components/SendMetaInfo/index.tsx +++ b/packages/neuron-ui/src/components/SendMetaInfo/index.tsx @@ -15,7 +15,7 @@ interface SendMetaInfoProps { fee: string price: string handleDescriptionChange: React.EventHandler - handlePriceChange: React.EventHandler + handlePriceChange: (value: string) => void } const SendMetaInfo = ({ @@ -41,6 +41,7 @@ const SendMetaInfo = ({ error={errorMessage} /> ) : null} + - ) } diff --git a/packages/neuron-ui/src/components/SpecialAssetList/index.tsx b/packages/neuron-ui/src/components/SpecialAssetList/index.tsx index fa97067e1e..43e170ac89 100644 --- a/packages/neuron-ui/src/components/SpecialAssetList/index.tsx +++ b/packages/neuron-ui/src/components/SpecialAssetList/index.tsx @@ -27,6 +27,7 @@ import { TokenInfo } from 'components/SUDTCreateDialog' import SUDTMigrateDialog from 'components/SUDTMigrateDialog' import SUDTMigrateToNewAccountDialog from 'components/SUDTMigrateToNewAccountDialog' import SUDTMigrateToExistAccountDialog from 'components/SUDTMigrateToExistAccountDialog' +import useGetCountDownAndFeeRateStats from 'utils/hooks/useGetCountDownAndFeeRateStats' import { useMigrate, useClickMigrate, @@ -36,7 +37,7 @@ import { } from './hooks' import styles from './specialAssetList.module.scss' -const { PAGE_SIZE, MEDIUM_FEE_RATE } = CONSTANTS +const { PAGE_SIZE } = CONSTANTS export interface SpecialAssetCell { blockHash: string @@ -110,6 +111,7 @@ const SpecialAssetList = () => { }, sUDTAccounts, } = useGlobalState() + const { suggestFeeRate } = useGetCountDownAndFeeRateStats() const isMainnet = isMainnetUtil(networks, networkID) const foundTokenInfo = tokenInfoList.find(token => token.tokenID === accountToClaim?.account.tokenID) const accountNames = useMemo(() => sUDTAccounts.filter(v => !!v.accountName).map(v => v.accountName!), [sUDTAccounts]) @@ -248,7 +250,7 @@ const SpecialAssetList = () => { unlockSpecialAsset({ walletID: id, outPoint: cell.outPoint, - feeRate: `${MEDIUM_FEE_RATE}`, + feeRate: `${suggestFeeRate}`, customizedAssetInfo: cell.customizedAssetInfo, }).then(handleRes('unlock')) return diff --git a/packages/neuron-ui/src/components/TransactionFeePanel/index.tsx b/packages/neuron-ui/src/components/TransactionFeePanel/index.tsx index e1b8f2ad13..052d8f0127 100644 --- a/packages/neuron-ui/src/components/TransactionFeePanel/index.tsx +++ b/packages/neuron-ui/src/components/TransactionFeePanel/index.tsx @@ -1,85 +1,32 @@ -import React, { useState } from 'react' -import { Stack, Toggle, IDropdownOption } from 'office-ui-fabric-react' -import Dropdown from 'widgets/Dropdown' +import React from 'react' +import { Stack } from 'office-ui-fabric-react' import TextField from 'widgets/TextField' +import PricePanel from 'components/PricePanel' import { useTranslation } from 'react-i18next' -import { Price, localNumberFormatter } from 'utils' interface TransactionFeeProps { fee: string price: string - onPriceChange: any + onPriceChange: (value: string) => void } -const TransactionFee: React.FunctionComponent = ({ +const TransactionFeePanel: React.FunctionComponent = ({ price, fee, onPriceChange, }: TransactionFeeProps) => { const [t] = useTranslation() - const [showDetail, setShowDetail] = useState(false) return ( - - { - setShowDetail(!showDetail) - }} - label={t('send.advanced-fee-settings')} - inlineLabel - onText=" " - offText=" " - styles={{ - label: { - fontSize: 14, - fontWeight: 500, - }, - }} - /> - - - - - - { - if (item) { - e.target.value = item.key - onPriceChange(e) - } - }} - aria-label="expected speed" - /> + ) } -TransactionFee.displayName = 'TransactionFee' +TransactionFeePanel.displayName = 'TransactionFeePanel' -export default TransactionFee +export default TransactionFeePanel diff --git a/packages/neuron-ui/src/locales/en.json b/packages/neuron-ui/src/locales/en.json index 1b5edfdd61..7f0fecd41f 100644 --- a/packages/neuron-ui/src/locales/en.json +++ b/packages/neuron-ui/src/locales/en.json @@ -991,6 +991,22 @@ "view-concise-data": "View concise data", "view-raw-data": "View raw data" } + }, + "dropdown": { + "placeholder": "Please select..." + }, + "price-switch": { + "price": "Price", + "customPrice": "Custom Price", + "errorTip": "Price cannot be less than {{minPrice}} shannons/KB, please re-enter", + "hintTip": "Suggested price is {{suggestFeeRate}} shannons/KB", + "priceColumn": "Price {{priceValue}} shannons/KB | Fee {{feeValue}} CKB", + "fast": "Fast", + "standard": "Standard", + "slow": "Slow", + "countDownTip": "The price will refresh after {{countDown}} seconds", + "switchToCustomPrice": "Switch to custom price", + "switchToPrice": "Switch to price" } } } diff --git a/packages/neuron-ui/src/locales/zh-tw.json b/packages/neuron-ui/src/locales/zh-tw.json index e980435550..d45a4fe26f 100644 --- a/packages/neuron-ui/src/locales/zh-tw.json +++ b/packages/neuron-ui/src/locales/zh-tw.json @@ -983,6 +983,22 @@ "view-concise-data": "查看概要", "view-raw-data": "查看原始數據" } + }, + "dropdown": { + "placeholder": "請選擇 ..." + }, + "price-switch": { + "price": "單價", + "customPrice": "自定義價格", + "errorTip": "價格設定最少不得少於 {{minPrice}} shannons/byte,請重新輸入", + "hintTip": "建議價格 {{suggestFeeRate}} shannons/KB", + "priceColumn": "單價 {{priceValue}} shannons/KB | 費用 {{feeValue}} CKB", + "fast": "快速", + "standard": "標準", + "slow": "慢速", + "countDownTip": "單價將在{{countDown}}秒後刷新", + "switchToCustomPrice": "切換到自定義價格", + "switchToPrice": "切換到單價" } } } diff --git a/packages/neuron-ui/src/locales/zh.json b/packages/neuron-ui/src/locales/zh.json index 316a253421..aa817d5a31 100644 --- a/packages/neuron-ui/src/locales/zh.json +++ b/packages/neuron-ui/src/locales/zh.json @@ -983,6 +983,22 @@ "view-concise-data": "查看概要", "view-raw-data": "查看原始数据" } + }, + "dropdown": { + "placeholder": "请选择 ..." + }, + "price-switch": { + "price": "单价", + "customPrice": "自定义价格", + "errorTip": "价格设定最少不得少于 {{minPrice}} shannons/KB,请重新输入", + "hintTip": "建议价格 {{suggestFeeRate}} shannons/KB", + "priceColumn": "单价 {{priceValue}} shannons/KB | 费用 {{feeValue}} CKB", + "fast": "快速", + "standard": "标准", + "slow": "慢速", + "countDownTip": "单价将在{{countDown}}秒后刷新", + "switchToCustomPrice": "切换到自定义价格", + "switchToPrice": "切换到单价" } } } diff --git a/packages/neuron-ui/src/services/chain.ts b/packages/neuron-ui/src/services/chain.ts index ecda9466ea..e83b569cbf 100644 --- a/packages/neuron-ui/src/services/chain.ts +++ b/packages/neuron-ui/src/services/chain.ts @@ -1,7 +1,7 @@ import CKBCore from '@nervosnetwork/ckb-sdk-core' export const ckbCore = new CKBCore('') -export const { getHeader, getBlock, getBlockchainInfo, getTipHeader, getHeaderByNumber } = ckbCore.rpc +export const { getHeader, getBlock, getBlockchainInfo, getTipHeader, getHeaderByNumber, getFeeRateStats } = ckbCore.rpc export const { calculateDaoMaximumWithdraw } = ckbCore @@ -15,4 +15,5 @@ export default { getHeaderByNumber, calculateDaoMaximumWithdraw, toUint64Le, + getFeeRateStats, } diff --git a/packages/neuron-ui/src/states/stateProvider/reducer.ts b/packages/neuron-ui/src/states/stateProvider/reducer.ts index 7b41290369..bd0db0a3e7 100644 --- a/packages/neuron-ui/src/states/stateProvider/reducer.ts +++ b/packages/neuron-ui/src/states/stateProvider/reducer.ts @@ -58,6 +58,9 @@ export enum AppActions { UpdateExperimentalParams = 'updateExperimentalParams', // offline sign UpdateLoadedTransaction = 'updateLoadedTransaction', + + GetFeeRateStats = 'getFeeRateStats', + UpdateCountDown = 'updateCountDown', } export type StateAction = @@ -89,6 +92,8 @@ export type StateAction = | { type: AppActions.Ignore; payload?: any } | { type: AppActions.UpdateExperimentalParams; payload: { tx: any; assetAccount?: any } | null } | { type: AppActions.UpdateLoadedTransaction; payload: { filePath?: string; json: OfflineSignJSON } } + | { type: AppActions.GetFeeRateStats; payload: State.FeeRateStatsType } + | { type: AppActions.UpdateCountDown; payload: number } | { type: NeuronWalletActions.InitAppState; payload: any } | { type: NeuronWalletActions.UpdateCurrentWallet; payload: Partial } | { type: NeuronWalletActions.UpdateWalletList; payload: State.WalletIdentity[] } @@ -365,6 +370,7 @@ export const reducer = produce((state: Draft, action: } break } + default: { break } diff --git a/packages/neuron-ui/src/stories/SendMetaInfo.stories.tsx b/packages/neuron-ui/src/stories/SendMetaInfo.stories.tsx index c4909c7098..d1a0f3889c 100644 --- a/packages/neuron-ui/src/stories/SendMetaInfo.stories.tsx +++ b/packages/neuron-ui/src/stories/SendMetaInfo.stories.tsx @@ -15,7 +15,7 @@ stories.add('Common', () => { fee: text('Fee', ''), price: text('Price', ''), handleDescriptionChange: (e: React.ChangeEvent) => action('Update Description')(e.target.value), - handlePriceChange: (e: React.ChangeEvent) => action('Update Price')(e.target.value), + handlePriceChange: (value: string) => action('Update Price')(value), } return }) diff --git a/packages/neuron-ui/src/styles/color.scss b/packages/neuron-ui/src/styles/color.scss index e6d4962cd6..6cfb27bc6a 100644 --- a/packages/neuron-ui/src/styles/color.scss +++ b/packages/neuron-ui/src/styles/color.scss @@ -1,4 +1,8 @@ :root { --nervos-green: #3cc68a; --nervos-green-light: #31a572; // most recent color to nervos green that pairs with white background + + --active-color: #00c891; + --tooltip-background-color: rgba(0, 0, 0, 0.8); + --tooltip-font-color: #ffffff; } diff --git a/packages/neuron-ui/src/types/App/index.d.ts b/packages/neuron-ui/src/types/App/index.d.ts index 9994a955ea..f3cd426448 100644 --- a/packages/neuron-ui/src/types/App/index.d.ts +++ b/packages/neuron-ui/src/types/App/index.d.ts @@ -61,6 +61,7 @@ declare namespace State { content?: string meta?: Meta } + interface Send { txID: string outputs: Output[] @@ -120,6 +121,8 @@ declare namespace State { type AlertDialog = Record<'title' | 'message', string> | null type GlobalDialogType = 'unlock-success' | 'rebuild-sync' | null + type FeeRateStatsType = { mean: string | number; median: string | number; suggestFeeRate: string | number } + interface App { tipBlockNumber: string tipBlockHash: string diff --git a/packages/neuron-ui/src/utils/calculateFee.ts b/packages/neuron-ui/src/utils/calculateFee.ts index 709c2a0390..2c7103f747 100644 --- a/packages/neuron-ui/src/utils/calculateFee.ts +++ b/packages/neuron-ui/src/utils/calculateFee.ts @@ -1,5 +1,5 @@ export const calculateFee = (tx: any) => { - if (!tx) { + if (!tx?.inputs || !tx?.outputs) { return '0' } const inputCapacities = tx.inputs.reduce( diff --git a/packages/neuron-ui/src/utils/hooks/createSUDTAccount.ts b/packages/neuron-ui/src/utils/hooks/createSUDTAccount.ts index a4136869a1..ddca3b5290 100644 --- a/packages/neuron-ui/src/utils/hooks/createSUDTAccount.ts +++ b/packages/neuron-ui/src/utils/hooks/createSUDTAccount.ts @@ -10,6 +10,7 @@ import { invokeShowErrorMessage, } from 'services/remote' import { getExplorerUrl } from 'utils' +import useGetCountDownAndFeeRateStats from './useGetCountDownAndFeeRateStats' import { ErrorCode } from '../enums' import { isSuccessResponse } from '../is' import { @@ -29,8 +30,10 @@ export const useIsInsufficientToCreateSUDTAccount = ({ walletId, balance, setInsufficient, -}: IsInsufficientToCreateSudtAccountProps) => - useEffect(() => { +}: IsInsufficientToCreateSudtAccountProps) => { + const { suggestFeeRate } = useGetCountDownAndFeeRateStats() + + return useEffect(() => { const createDummySUDTAccount = () => { if (balance <= BigInt(MIN_CKB_REQUIRED_BY_NORMAL_SUDT) * BigInt(SHANNON_CKB_RATIO)) { return true @@ -42,7 +45,7 @@ export const useIsInsufficientToCreateSUDTAccount = ({ accountName: DEFAULT_SUDT_FIELDS.accountName, symbol: DEFAULT_SUDT_FIELDS.symbol, decimal: '0', - feeRate: `${MEDIUM_FEE_RATE}`, + feeRate: `${suggestFeeRate}`, } return generateCreateSUDTAccountTransaction(params).catch(() => false) } @@ -57,7 +60,7 @@ export const useIsInsufficientToCreateSUDTAccount = ({ accountName: DEFAULT_SUDT_FIELDS.accountName, symbol: DEFAULT_SUDT_FIELDS.CKBSymbol, decimal: DEFAULT_SUDT_FIELDS.CKBDecimal, - feeRate: `${MEDIUM_FEE_RATE}`, + feeRate: `${suggestFeeRate}`, } return generateCreateSUDTAccountTransaction(params).catch(() => false) } @@ -76,7 +79,8 @@ export const useIsInsufficientToCreateSUDTAccount = ({ [AccountType.SUDT]: insufficientToCreateSUDTAccount, }) }) - }, [walletId, balance, setInsufficient]) + }, [walletId, balance, setInsufficient, suggestFeeRate]) +} export const useOnGenerateNewAccountTransaction = ({ walletId, diff --git a/packages/neuron-ui/src/utils/hooks/useGetCountDownAndFeeRateStats.ts b/packages/neuron-ui/src/utils/hooks/useGetCountDownAndFeeRateStats.ts new file mode 100644 index 0000000000..43d6b15f0f --- /dev/null +++ b/packages/neuron-ui/src/utils/hooks/useGetCountDownAndFeeRateStats.ts @@ -0,0 +1,62 @@ +import { useState, useEffect, useCallback } from 'react' +import { getFeeRateStats } from 'services/chain' +import { AppActions, StateDispatch, useDispatch } from 'states' +import { MEDIUM_FEE_RATE } from 'utils/const' + +type CountdownOptions = { + seconds?: number + interval?: number +} + +const useGetCountDownAndFeeRateStats = ({ seconds = 30, interval = 1000 }: CountdownOptions = {}) => { + const [countDown, setCountDown] = useState(seconds) + const [feeFatestatsData, setFeeFatestatsData] = useState<{ + mean?: string + median?: string + suggestFeeRate: number + }>({ suggestFeeRate: MEDIUM_FEE_RATE }) + const dispatch = useDispatch() + + const handleGetFeeRateStatis = useCallback( + (stateDispatch: StateDispatch) => { + getFeeRateStats() + .then(res => { + const { mean, median } = res + const suggested = mean && median ? Math.max(1000, Number(mean), Number(median)) : MEDIUM_FEE_RATE + + setFeeFatestatsData(states => ({ ...states, ...res, suggestFeeRate: suggested })) + }) + .catch((err: Error) => { + stateDispatch({ + type: AppActions.AddNotification, + payload: { + type: 'alert', + timestamp: +new Date(), + content: err.message, + }, + }) + }) + }, + [getFeeRateStats, setFeeFatestatsData] + ) + + useEffect(() => { + const countInterval = setInterval(() => { + setCountDown(count => (count <= 0 ? seconds : count - 1)) + }, interval) + + return () => { + clearInterval(countInterval) + } + }, []) + + useEffect(() => { + if (countDown === seconds) { + handleGetFeeRateStatis(dispatch) + } + }, [countDown, seconds, dispatch]) + + return { countDown, ...feeFatestatsData } +} + +export default useGetCountDownAndFeeRateStats diff --git a/packages/neuron-ui/src/widgets/DropdownWithCustomRender/index.module.scss b/packages/neuron-ui/src/widgets/DropdownWithCustomRender/index.module.scss new file mode 100644 index 0000000000..73ed79612d --- /dev/null +++ b/packages/neuron-ui/src/widgets/DropdownWithCustomRender/index.module.scss @@ -0,0 +1,94 @@ +:root { + --dropdown-base-font-color: rgb(50, 49, 48); + --selected-color: rgb(227, 227, 227); +} + +.dropdown-root { + position: relative; +} + +.dropdown-control { + position: relative; + overflow: hidden; + background-color: white; + border: 1px solid rgb(96, 94, 92); + box-sizing: border-box; + cursor: pointer; + outline: none; + transition: all 200ms ease; + font-size: 0.75rem; + font-weight: 400; + color: var(--dropdown-base-font-color); + border-color: rgb(96, 94, 92); + display: flex; + justify-content: space-between; + align-items: center; + padding: 3px 10px; + padding-bottom: 3.5px; +} + +.dropdown-control:hover { + box-shadow: 0 1px 0 rgba(0, 0, 0, 0.06); +} + +.dropdown-arrow { + transition: 0.2s; +} + +.is-open .dropdown-arrow { + transform: rotate(180deg); +} + +.dropdown-menu { + background-color: white; + box-shadow: rgb(0 0 0 / 13%) 0px 3.2px 7.2px 0px, + rgb(0 0 0 / 11%) 0px 0.6px 1.8px 0px; + box-sizing: border-box; + margin-top: 0px; + max-height: 200px; + overflow-y: auto; + position: absolute; + top: 100%; + width: 100%; + z-index: 1000; + -webkit-overflow-scrolling: touch; +} + +.dropdown-option { + box-sizing: border-box; + color: var(--dropdown-base-font-color); + cursor: pointer; + display: block; + padding: 6px 10px; + font-size: 0.75rem; +} + +.dropdown-option:last-child { + border-bottom-right-radius: 2px; + border-bottom-left-radius: 2px; +} + +.dropdown-option:hover { + background-color: rgba(0, 0, 0, 0.06); + color: var(--dropdown-base-font-color); +} + +.dropdown-option.is-selected { + color: var(--dropdown-base-font-color); +} + +.dropdown-disabled { + background-color: var(--selected-color); +} + +.dropdown-placeholder { + font-size: 12px; +} + +.dropdown-noresults { + box-sizing: border-box; + color: #ccc; + cursor: default; + display: block; + padding: 8px 10px; +} diff --git a/packages/neuron-ui/src/widgets/DropdownWithCustomRender/index.tsx b/packages/neuron-ui/src/widgets/DropdownWithCustomRender/index.tsx new file mode 100644 index 0000000000..fedf9e2743 --- /dev/null +++ b/packages/neuron-ui/src/widgets/DropdownWithCustomRender/index.tsx @@ -0,0 +1,171 @@ +import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' +import { useTranslation } from 'react-i18next' +import { LineDownArrow } from 'widgets/Icons/icon' + +import styles from './index.module.scss' + +export interface OptionProps { + label: string | React.ReactNode + value: string + className?: string + index?: number +} + +interface DropdownWithCustomRenderProps { + onChange: (changeValue: OptionProps) => void + options: OptionProps[] + value?: string + placeholder?: string + onFocus?: (isOpen: boolean) => void + disabled?: boolean + className?: string +} + +const DropdownWithCustomRender = ({ + options: optionsFromProps, + onChange, + value: valueFromProps = '', + placeholder, + onFocus, + disabled, + className, +}: DropdownWithCustomRenderProps) => { + const [t] = useTranslation() + const [isOpen, setIsOpen] = useState(false) + const dropdownRef = useRef(null) + + const DEFAULT_PLACEHOLDER_STRING = t('dropdown.placeholder') + + // render selected value in options + const parseValue = (value: string, options: OptionProps[]) => { + const option = options.find(v => v?.value === value) + + return ( + option || { + label: placeholder ?? DEFAULT_PLACEHOLDER_STRING, + value: '', + } + ) + } + + const selectedOption = useMemo(() => parseValue(valueFromProps, optionsFromProps), [valueFromProps, optionsFromProps]) + + const setValue = useCallback( + ({ value, label, index }: OptionProps) => { + const newState = { + value, + label, + index, + } + onChange?.(newState) + setIsOpen(false) + }, + [onChange, setIsOpen] + ) + + const handleDocumentClick = (event: MouseEvent | TouchEvent) => { + if (!dropdownRef.current?.contains(event.target as HTMLElement)) { + setIsOpen(false) + } + } + + const handleMouseDown = (event: React.MouseEvent | React.TouchEvent) => { + if (typeof onFocus === 'function') { + onFocus(isOpen) + } + if (event.type === 'mousedown' && (event as React.MouseEvent).button !== 0) { + return + } + event.stopPropagation() + event.preventDefault() + + if (!disabled) { + setIsOpen(openState => !openState) + } + } + + const isValueSelected = selectedOption.value !== '' + const dropdownLabelOrPlaceholder = selectedOption.label || DEFAULT_PLACEHOLDER_STRING + + const disabledClass = disabled ? `${styles['dropdown-disabled']}` : '' + const dropdownClass = `${styles['dropdown-root']} ${className} ${isOpen ? styles['is-open'] : ''}` + const controlClass = `${styles['dropdown-control']} ${disabledClass}` + const placeholderClass = `${styles['dropdown-placeholder']} ${isValueSelected ? styles['is-selected'] : ''}` + const arrowClass = `${styles['dropdown-arrow']}` + const menuClass = `${styles['dropdown-menu']}` + + const renderOption = useCallback( + (option: OptionProps) => { + const { value, label, className: optionClassName, index } = option + const isSelected = value === selectedOption.value + const optionClass = `${styles['dropdown-option']} ${optionClassName} ${isSelected ? styles['is-selected'] : ''}` + + const renderedValue = { + value, + label, + index, + } + + return ( +
setValue(renderedValue)} + onClick={() => setValue(renderedValue)} + onKeyDown={() => setValue(renderedValue)} + role="option" + tabIndex={0} + aria-selected={isSelected ? 'true' : 'false'} + > + {label} +
+ ) + }, + [selectedOption, setValue] + ) + + const menu = useMemo(() => { + const buildMenu = () => { + const ops = optionsFromProps.map((option, index) => renderOption({ ...option, index })) + + return ops.length ? ops :
No options found
+ } + + return isOpen ? ( +
+ {buildMenu()} +
+ ) : null + }, [isOpen, optionsFromProps, renderOption]) + + useEffect(() => { + document.addEventListener('click', handleDocumentClick, false) + document.addEventListener('touchend', handleDocumentClick, false) + + return () => { + document.removeEventListener('click', handleDocumentClick, false) + document.removeEventListener('touchend', handleDocumentClick, false) + } + }, []) + + return ( +
+
+
{dropdownLabelOrPlaceholder}
+ +
+ {menu} +
+ ) +} + +DropdownWithCustomRender.displayName = 'DropdownWithCustomRender' + +export default React.memo(DropdownWithCustomRender) diff --git a/packages/neuron-ui/src/widgets/Icons/LineDownArrow.svg b/packages/neuron-ui/src/widgets/Icons/LineDownArrow.svg new file mode 100644 index 0000000000..5f7b069fac --- /dev/null +++ b/packages/neuron-ui/src/widgets/Icons/LineDownArrow.svg @@ -0,0 +1,4 @@ + + + diff --git a/packages/neuron-ui/src/widgets/Icons/Transfer.svg b/packages/neuron-ui/src/widgets/Icons/Transfer.svg new file mode 100644 index 0000000000..8b92c924a8 --- /dev/null +++ b/packages/neuron-ui/src/widgets/Icons/Transfer.svg @@ -0,0 +1,5 @@ + + + diff --git a/packages/neuron-ui/src/widgets/Icons/icon.tsx b/packages/neuron-ui/src/widgets/Icons/icon.tsx index 5bae71d5ce..a2de766d62 100644 --- a/packages/neuron-ui/src/widgets/Icons/icon.tsx +++ b/packages/neuron-ui/src/widgets/Icons/icon.tsx @@ -25,6 +25,8 @@ import { ReactComponent as PendingIconSvg } from './PendingIcon.svg' import { ReactComponent as NewTabSvg } from './new_tab.svg' import { ReactComponent as TooltipSvg } from './Tooltip.svg' import { ReactComponent as OpenFolderSvg } from './OpenFolder.svg' +import { ReactComponent as TransferSvg } from './Transfer.svg' +import { ReactComponent as LineDownArrowSvg } from './LineDownArrow.svg' import styles from './icon.module.scss' @@ -64,3 +66,5 @@ export const PendingIcon = WrapSvg(PendingIconSvg) export const NewTab = WrapSvg(NewTabSvg) export const Tooltip = WrapSvg(TooltipSvg) export const OpenFolder = WrapSvg(OpenFolderSvg) +export const Transfer = WrapSvg(TransferSvg) +export const LineDownArrow = WrapSvg(LineDownArrowSvg) diff --git a/packages/neuron-ui/src/widgets/TextField/textField.module.scss b/packages/neuron-ui/src/widgets/TextField/textField.module.scss index a1c503f923..3f0ef823b4 100644 --- a/packages/neuron-ui/src/widgets/TextField/textField.module.scss +++ b/packages/neuron-ui/src/widgets/TextField/textField.module.scss @@ -94,14 +94,12 @@ $secondary-font-size: 0.63rem; grid-area: message; color: $error-red; font-size: $secondary-font-size; - line-height: 0.6875rem; word-break: break-all; svg { width: 8px; - height: 8px; + height: 1rem; margin-right: 5px; - margin-top: 0.125rem; } } diff --git a/packages/neuron-wallet/package.json b/packages/neuron-wallet/package.json index d23073a6aa..70a0789f3b 100644 --- a/packages/neuron-wallet/package.json +++ b/packages/neuron-wallet/package.json @@ -41,8 +41,8 @@ "@iarna/toml": "2.2.5", "@ledgerhq/hw-transport-node-hid": "6.27.12", "@nervina-labs/ckb-indexer": "0.1.1", - "@nervosnetwork/ckb-sdk-core": "0.103.1", - "@nervosnetwork/ckb-sdk-utils": "0.103.1", + "@nervosnetwork/ckb-sdk-core": "0.107.0", + "@nervosnetwork/ckb-sdk-utils": "0.107.0", "archiver": "5.3.0", "async": "3.2.4", "bn.js": "4.12.0", diff --git a/yarn.lock b/yarn.lock index 36bffa0c0c..3c9e8244e5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2976,31 +2976,31 @@ call-me-maybe "^1.0.1" glob-to-regexp "^0.3.0" -"@nervosnetwork/ckb-sdk-core@0.103.1": - version "0.103.1" - resolved "https://registry.yarnpkg.com/@nervosnetwork/ckb-sdk-core/-/ckb-sdk-core-0.103.1.tgz#136d616ec53af96d3b93dcbce593e6db484c802d" - integrity sha512-LeNwId3GaQILVpnY1zfNBY897XQJPODKeP6d7w6tww9anu0jSxrvXVxGMDTTn3Yz5mixzBgpFGo4SXRrH0eiaQ== - dependencies: - "@nervosnetwork/ckb-sdk-rpc" "0.103.1" - "@nervosnetwork/ckb-sdk-utils" "0.103.1" - "@nervosnetwork/ckb-types" "0.103.1" +"@nervosnetwork/ckb-sdk-core@0.107.0": + version "0.107.0" + resolved "https://registry.yarnpkg.com/@nervosnetwork/ckb-sdk-core/-/ckb-sdk-core-0.107.0.tgz#3baba0ed96d4cc48a34dc984bcc0bee0f1729aa9" + integrity sha512-2Tmt1bDjgX9FDrH+1MThjs8N33X/QGRsln/ldaN9vfzXEhXWCcru9KZR9gBQNIiyLjXOb8sv1aUH8Ma9y8QMZQ== + dependencies: + "@nervosnetwork/ckb-sdk-rpc" "0.107.0" + "@nervosnetwork/ckb-sdk-utils" "0.107.0" + "@nervosnetwork/ckb-types" "0.107.0" tslib "2.3.1" -"@nervosnetwork/ckb-sdk-rpc@0.103.1": - version "0.103.1" - resolved "https://registry.yarnpkg.com/@nervosnetwork/ckb-sdk-rpc/-/ckb-sdk-rpc-0.103.1.tgz#6c0d0bad8a05a9280ddc34adf973bf55e0725e06" - integrity sha512-n3V/5Be7PilyHXUcR6yAiwanMcuZNLfslu9A84OpfB22hlkwIv7OFG/JvFNack/cANPfChRAWB+VWiYGwSON/A== +"@nervosnetwork/ckb-sdk-rpc@0.107.0": + version "0.107.0" + resolved "https://registry.yarnpkg.com/@nervosnetwork/ckb-sdk-rpc/-/ckb-sdk-rpc-0.107.0.tgz#c0ed51ae96f237c6140945c1b8408cdf64ffa4e1" + integrity sha512-zLUrvjQuYqkX08POB4Q8Szws+c6XcX4iyhu+evYllrdvd9XF20GF/B62mMIQpnos3phu9ySs4H58VTxWp7aiag== dependencies: - "@nervosnetwork/ckb-sdk-utils" "0.103.1" + "@nervosnetwork/ckb-sdk-utils" "0.107.0" axios "0.21.4" tslib "2.3.1" -"@nervosnetwork/ckb-sdk-utils@0.103.1": - version "0.103.1" - resolved "https://registry.yarnpkg.com/@nervosnetwork/ckb-sdk-utils/-/ckb-sdk-utils-0.103.1.tgz#8356f88027a4054835fee0648617cc7020c8db1b" - integrity sha512-OzpFNKkOOqYWDHDjPf11uOfOf8EQOEstOBxVtyFjrGEx3B9FwsGxItlHYeuTfpFkHF2Ut+G9M3X71w8h/IApdQ== +"@nervosnetwork/ckb-sdk-utils@0.107.0": + version "0.107.0" + resolved "https://registry.yarnpkg.com/@nervosnetwork/ckb-sdk-utils/-/ckb-sdk-utils-0.107.0.tgz#36bc402c60c8174c24092e21211351e8fbd4f9f6" + integrity sha512-CPos2k3S9YI/MSUWv1D85KDwkvYBQcyl9YoYvsBN+AsMqqSUb8h1D3oectaJ2hN37o4Z2hrSDewEA6dXIWFLAg== dependencies: - "@nervosnetwork/ckb-types" "0.103.1" + "@nervosnetwork/ckb-types" "0.107.0" bech32 "2.0.0" elliptic "6.5.4" jsbi "3.1.3" @@ -3011,6 +3011,11 @@ resolved "https://registry.yarnpkg.com/@nervosnetwork/ckb-types/-/ckb-types-0.103.1.tgz#b5626ce905353e70136bfaccf9def0819b76ca27" integrity sha512-gGRR1VvUS/KRq2ChhXHPiHpgyLYazPM2R8lK87shQI82Gp2/m6k1HVDeNR5XOYwQ3YmBbxHGQtQr/kMq7DUlZA== +"@nervosnetwork/ckb-types@0.107.0": + version "0.107.0" + resolved "https://registry.yarnpkg.com/@nervosnetwork/ckb-types/-/ckb-types-0.107.0.tgz#980947e20d17edd145ff3805e7312bbeb38be2f6" + integrity sha512-vaPQXzfbwVJnSqPtGFbdH8/WrL6YQmNQz1Tf1dRBIZbIEIXjVGO5DUHwAiU6pjC6j1QsrlBrvv/P622vM4Q1sA== + "@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1": version "5.1.1-v1" resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz#dbf733a965ca47b1973177dc0bb6c889edcfb129" @@ -5192,14 +5197,7 @@ dependencies: "@types/react" "*" -"@types/react-transition-group@^4.4.1": - version "4.4.5" - resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.5.tgz#aae20dcf773c5aa275d5b9f7cdbca638abc5e416" - integrity sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA== - dependencies: - "@types/react" "*" - -"@types/react@*", "@types/react@17.0.53": +"@types/react@*", "@types/react@17.0.53", "@types/react@^17": version "17.0.53" resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.53.tgz#10d4d5999b8af3d6bc6a9369d7eb953da82442ab" integrity sha512-1yIpQR2zdYu1Z/dc1OxC+MA6GR240u3gcnP4l6mvj/PJiVaqHsQPmWttsvHsfnhfPbU2FuGmo0wSITPygjBmsw== @@ -18713,14 +18711,6 @@ pretty-hrtime@^1.0.3: resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" integrity sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A== -primereact@8.7.1: - version "8.7.1" - resolved "https://registry.yarnpkg.com/primereact/-/primereact-8.7.1.tgz#2206ba4db54cbea44ebb0d0b9df8bd1ce0fbf5ef" - integrity sha512-2uv3t9LjcT9f4j2DgDIK0xa+lP8ysmQuD9DbBJwnfuyz362P0w2mmcDfp4UksiD1ld6oF0u3XAWVNZclaPJUjg== - dependencies: - "@types/react-transition-group" "^4.4.1" - react-transition-group "^4.4.1" - prismjs@^1.8.4: version "1.29.0" resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12" @@ -19507,7 +19497,7 @@ react-textarea-autosize@^7.1.0: "@babel/runtime" "^7.1.2" prop-types "^15.6.0" -react-transition-group@^4.3.0, react-transition-group@^4.4.1: +react-transition-group@^4.3.0: version "4.4.5" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1" integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g== From f568124d79267cc0b2a3d934003110c2b2bf38b5 Mon Sep 17 00:00:00 2001 From: Keith Date: Fri, 14 Apr 2023 16:03:59 +0800 Subject: [PATCH 27/52] ci: update reviewers and action versions 1. set 'merge released to develop' reviewers to keith-cy 2. upgrade peter-evans/commit-comment to v2 --- .github/workflows/check_checksums.yml | 2 +- .github/workflows/merge_released_into_develop.yml | 2 +- .github/workflows/package_for_test.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/check_checksums.yml b/.github/workflows/check_checksums.yml index 86ff926b1e..3a8558ffd7 100644 --- a/.github/workflows/check_checksums.yml +++ b/.github/workflows/check_checksums.yml @@ -33,7 +33,7 @@ jobs: body="${body//$'\r'/'%0D'}" echo ::set-output name=body::$body - - uses: peter-evans/commit-comment@v1 + - uses: peter-evans/commit-comment@v2 with: body: ${{ steps.comment_body.outputs.body }} diff --git a/.github/workflows/merge_released_into_develop.yml b/.github/workflows/merge_released_into_develop.yml index 8747fad3f0..aaffa45742 100644 --- a/.github/workflows/merge_released_into_develop.yml +++ b/.github/workflows/merge_released_into_develop.yml @@ -17,6 +17,6 @@ jobs: source_branch: 'master' destination_branch: 'develop' pr_title: 'Merge released ${{ github.ref }} into develop' - pr_reviewer: 'keith-cy,yuche,kellyshang' + pr_reviewer: 'keith-cy' pr_label: 'auto-pr' github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/package_for_test.yml b/.github/workflows/package_for_test.yml index d3f1217d84..3a9c7fa94a 100644 --- a/.github/workflows/package_for_test.yml +++ b/.github/workflows/package_for_test.yml @@ -140,7 +140,7 @@ jobs: name: Append links to the Pull Request runs-on: ubuntu-latest steps: - - uses: peter-evans/commit-comment@v1 + - uses: peter-evans/commit-comment@v2 with: body: | Packaging for test is done in [${{ github.run_id }}](https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}) From e28ddd619d7dab42434d1f1813adac9f028d4456 Mon Sep 17 00:00:00 2001 From: Keith Date: Sat, 15 Apr 2023 02:02:37 +0800 Subject: [PATCH 28/52] fix: fix parsing deposit time in nervos dao 0 in the condition hits the negative branch but it should be treated as a positive one because 0 is a valid index of an array --- packages/neuron-ui/src/components/NervosDAO/hooks.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/neuron-ui/src/components/NervosDAO/hooks.ts b/packages/neuron-ui/src/components/NervosDAO/hooks.ts index 58a66ea222..71abdffdb1 100644 --- a/packages/neuron-ui/src/components/NervosDAO/hooks.ts +++ b/packages/neuron-ui/src/components/NervosDAO/hooks.ts @@ -539,7 +539,7 @@ export const useUpdateDepositEpochList = ({ const epochList = new Map() records.forEach(record => { const key = getRecordKey(record) - epochList.set(key, recordKeyIdxMap.get(key) ? res[recordKeyIdxMap.get(key)!]?.epoch : null) + epochList.set(key, recordKeyIdxMap.get(key) !== undefined ? res[recordKeyIdxMap.get(key)!]?.epoch : null) }) setDepositEpochList(epochList) }) From 277aa7c75099cbb28ed656c09ccdc567dea76edc Mon Sep 17 00:00:00 2001 From: Keith Date: Sun, 16 Apr 2023 14:51:09 +0800 Subject: [PATCH 29/52] ci: add an action to add "replied" label automatically The "replied" label will be added if an issue has been replied by a user who has write access. It's expected to work with the update-issue-status action to manage issues automatically. --- .github/workflows/add-replied-label.yml | 32 +++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .github/workflows/add-replied-label.yml diff --git a/.github/workflows/add-replied-label.yml b/.github/workflows/add-replied-label.yml new file mode 100644 index 0000000000..0dc24712f5 --- /dev/null +++ b/.github/workflows/add-replied-label.yml @@ -0,0 +1,32 @@ +name: Add 'replied' label + +on: + issue_comment: + types: [created] + +jobs: + add-label: + runs-on: ubuntu-latest + steps: + - id: check-access + name: Check if the commenter has write access + uses: actions/github-script@v4 + with: + script: | + const response = await github.repos.checkCollaborator({ + owner: context.repo.owner, + repo: context.repo.repo, + username: context.payload.comment.user.login, + }) + return { hasWriteAccess: response.data.permission === 'write' } + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - id: add-label + name: Add 'replied' label + if: steps.check-access.outputs.hasWriteAccess + uses: actions-ecosystem/action-add-label@v1 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + issue-number: ${{ github.event.issue.number }} + label: replied From 7806e7add0e0d3096034356939e063460d73c1a8 Mon Sep 17 00:00:00 2001 From: Chen Yu Date: Mon, 17 Apr 2023 18:07:58 +0800 Subject: [PATCH 30/52] Update dependencies (#2628) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/update-issue-status.yml | 2 +- package.json | 14 +- packages/ckb-indexer/package.json | 2 +- packages/neuron-ui/package.json | 18 +- packages/neuron-wallet/package.json | 18 +- renovate.json | 2 +- yarn.lock | 946 +++++++++++----------- 7 files changed, 483 insertions(+), 519 deletions(-) diff --git a/.github/workflows/update-issue-status.yml b/.github/workflows/update-issue-status.yml index 030096019b..cff334fbfd 100644 --- a/.github/workflows/update-issue-status.yml +++ b/.github/workflows/update-issue-status.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Update stale issues - uses: actions/stale@v7 + uses: actions/stale@v8 with: any-of-issue-labels: replied stale-issue-label: stale diff --git a/package.json b/package.json index 71f17571ea..0b81528a5f 100644 --- a/package.json +++ b/package.json @@ -44,15 +44,15 @@ } }, "devDependencies": { - "@babel/core": "7.21.0", + "@babel/core": "7.21.4", "@types/jest": "27.5.2", - "@types/node": "18.14.6", + "@types/node": "18.15.11", "@types/npmlog": "4.1.4", - "@typescript-eslint/eslint-plugin": "5.54.1", - "@typescript-eslint/parser": "5.54.1", - "concurrently": "7.6.0", + "@typescript-eslint/eslint-plugin": "5.58.0", + "@typescript-eslint/parser": "5.58.0", + "concurrently": "8.0.1", "cross-env": "7.0.3", - "husky": "3.1.0", + "husky": "8.0.3", "lerna": "5.6.2", "ncp": "2.0.0", "ts-jest": "27.1.5", @@ -61,7 +61,7 @@ }, "dependencies": {}, "resolutions": { - "@types/react": "17.0.53", + "@types/react": "17.0.58", "react-i18next": ">=11.16.4", "usb": "1.8.8" } diff --git a/packages/ckb-indexer/package.json b/packages/ckb-indexer/package.json index 10b6624d17..44351435cc 100644 --- a/packages/ckb-indexer/package.json +++ b/packages/ckb-indexer/package.json @@ -22,7 +22,7 @@ }, "devDependencies": { "events": "3.3.0", - "eslint": "8.35.0" + "eslint": "8.38.0" }, "scripts": { "build": "tsc", diff --git a/packages/neuron-ui/package.json b/packages/neuron-ui/package.json index 43ed8b4eef..57f0d62686 100644 --- a/packages/neuron-ui/package.json +++ b/packages/neuron-ui/package.json @@ -46,7 +46,7 @@ "@uifabric/styling": "7.25.1", "canvg": "2.0.0", "i18next": "21.10.0", - "immer": "9.0.16", + "immer": "9.0.21", "jsqr": "1.4.0", "office-ui-fabric-react": "7.204.0", "qr.js": "0.0.0", @@ -54,7 +54,7 @@ "react-dom": "17.0.2", "react-i18next": "12.1.5", "react-router-dom": "5.1.2", - "sass": "1.58.3" + "sass": "1.62.0" }, "devDependencies": { "@babel/plugin-proposal-private-property-in-object": "7.21.0", @@ -68,8 +68,8 @@ "@storybook/react": "5.3.18", "@types/enzyme": "3.10.12", "@types/enzyme-adapter-react-16": "1.0.6", - "@types/node": "18.14.6", - "@types/react": "17.0.53", + "@types/node": "18.15.11", + "@types/react": "17.0.58", "@types/react-dom": "17.0.19", "@types/react-router-dom": "5.3.3", "@types/storybook-react-router": "1.0.1", @@ -77,18 +77,18 @@ "@types/styled-components": "5.1.26", "@wojtekmaj/enzyme-adapter-react-17": "0.8.0", "babel-jest": "25.5.1", - "electron": "23.1.2", + "electron": "24.1.1", "enzyme": "3.11.0", "enzyme-adapter-react-16": "1.15.7", "eslint-config-airbnb": "19.0.4", - "eslint-config-prettier": "8.7.0", + "eslint-config-prettier": "8.8.0", "eslint-plugin-import": "2.27.5", "eslint-plugin-jsx-a11y": "6.7.1", - "eslint-plugin-prettier": "4.0.0", + "eslint-plugin-prettier": "4.2.1", "eslint-plugin-react": "7.32.2", "jest-styled-components": "7.1.1", - "lint-staged": "9.5.0", - "prettier": "1.19.1", + "lint-staged": "13.2.1", + "prettier": "2.8.7", "react-app-rewired": "2.2.1", "react-scripts": "5.0.1", "react-test-renderer": "16.14.0", diff --git a/packages/neuron-wallet/package.json b/packages/neuron-wallet/package.json index 70a0789f3b..937be7321e 100644 --- a/packages/neuron-wallet/package.json +++ b/packages/neuron-wallet/package.json @@ -39,7 +39,7 @@ "@ckb-lumos/base": "0.18.0-rc2", "@ckb-lumos/rpc": "0.18.0-rc2", "@iarna/toml": "2.2.5", - "@ledgerhq/hw-transport-node-hid": "6.27.12", + "@ledgerhq/hw-transport-node-hid": "6.27.13", "@nervina-labs/ckb-indexer": "0.1.1", "@nervosnetwork/ckb-sdk-core": "0.107.0", "@nervosnetwork/ckb-sdk-utils": "0.107.0", @@ -62,12 +62,12 @@ "sqlite3": "5.1.4", "subleveldown": "4.1.4", "typeorm": "0.2.25", - "undici": "5.19.1", + "undici": "5.21.2", "uuid": "8.3.2" }, "devDependencies": { "@electron/notarize": "1.2.3", - "@nervosnetwork/ckb-types": "0.103.1", + "@nervosnetwork/ckb-types": "0.107.0", "@types/archiver": "3.1.1", "@types/async": "3.2.18", "@types/electron-devtools-installer": "2.2.2", @@ -82,17 +82,17 @@ "@types/uuid": "8.3.4", "@zerollup/ts-transform-paths": "1.7.18", "devtron": "1.4.0", - "electron": "23.1.2", + "electron": "24.1.1", "electron-build-env": "0.2.0", "electron-builder": "23.6.0", "electron-devtools-installer": "3.2.0", - "eslint": "8.35.0", - "eslint-config-prettier": "8.7.0", - "eslint-plugin-prettier": "3.4.1", + "eslint": "8.38.0", + "eslint-config-prettier": "8.8.0", + "eslint-plugin-prettier": "4.2.1", "jest-when": "2.8.1", - "lint-staged": "9.5.0", + "lint-staged": "13.2.1", "neuron-ui": "0.106.0", - "prettier": "1.19.1", + "prettier": "2.8.7", "ttypescript": "1.5.15", "typescript": "4.2.3" } diff --git a/renovate.json b/renovate.json index f3cafad313..44ba1e0835 100644 --- a/renovate.json +++ b/renovate.json @@ -8,5 +8,5 @@ "addLabels": ["types"] } ], - "reviewers": ["keith-cy", "yanguoyu", "cedar67", "jeffreyma597"] + "reviewers": ["keith-cy", "yanguoyu", "jeffreyma597", "devchenyan", "WhiteMinds"] } diff --git a/yarn.lock b/yarn.lock index 3c9e8244e5..72745e06c0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -43,11 +43,23 @@ dependencies: "@babel/highlight" "^7.18.6" +"@babel/code-frame@^7.21.4": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.21.4.tgz#d0fa9e4413aca81f2b23b9442797bda1826edb39" + integrity sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g== + dependencies: + "@babel/highlight" "^7.18.6" + "@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.1", "@babel/compat-data@^7.20.5": version "7.21.0" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.21.0.tgz#c241dc454e5b5917e40d37e525e2f4530c399298" integrity sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g== +"@babel/compat-data@^7.21.4": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.21.4.tgz#457ffe647c480dff59c2be092fc3acf71195c87f" + integrity sha512-/DYyDpeCfaVinT40FPGdkkb+lYSKvsVuMjDAG7jPOWWiM1ibOaB9CXJAlc4d1QpP/U2q2P9jbrSlClKSErd55g== + "@babel/core@7.12.9": version "7.12.9" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.9.tgz#fd450c4ec10cdbb980e2928b7aa7a28484593fc8" @@ -70,21 +82,21 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@7.21.0": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.21.0.tgz#1341aefdcc14ccc7553fcc688dd8986a2daffc13" - integrity sha512-PuxUbxcW6ZYe656yL3EAhpy7qXKq0DmYsrJLpbB8XrsCP9Nm+XCg9XFMb5vIDliPD7+U/+M+QJlH17XOcB7eXA== +"@babel/core@7.21.4": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.21.4.tgz#c6dc73242507b8e2a27fd13a9c1814f9fa34a659" + integrity sha512-qt/YV149Jman/6AfmlxJ04LMIu8bMoyl3RB91yTFrxQmgbrSvQMy7cI8Q62FHx1t8wJ8B5fu0UDoLwHAhUo1QA== dependencies: "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.21.0" - "@babel/helper-compilation-targets" "^7.20.7" - "@babel/helper-module-transforms" "^7.21.0" + "@babel/code-frame" "^7.21.4" + "@babel/generator" "^7.21.4" + "@babel/helper-compilation-targets" "^7.21.4" + "@babel/helper-module-transforms" "^7.21.2" "@babel/helpers" "^7.21.0" - "@babel/parser" "^7.21.0" + "@babel/parser" "^7.21.4" "@babel/template" "^7.20.7" - "@babel/traverse" "^7.21.0" - "@babel/types" "^7.21.0" + "@babel/traverse" "^7.21.4" + "@babel/types" "^7.21.4" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" @@ -131,12 +143,12 @@ "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" -"@babel/generator@^7.21.0": - version "7.21.1" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.21.1.tgz#951cc626057bc0af2c35cd23e9c64d384dea83dd" - integrity sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA== +"@babel/generator@^7.21.4": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.21.4.tgz#64a94b7448989f421f919d5239ef553b37bb26bc" + integrity sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA== dependencies: - "@babel/types" "^7.21.0" + "@babel/types" "^7.21.4" "@jridgewell/gen-mapping" "^0.3.2" "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" @@ -167,6 +179,17 @@ lru-cache "^5.1.1" semver "^6.3.0" +"@babel/helper-compilation-targets@^7.21.4": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.4.tgz#770cd1ce0889097ceacb99418ee6934ef0572656" + integrity sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg== + dependencies: + "@babel/compat-data" "^7.21.4" + "@babel/helper-validator-option" "^7.21.0" + browserslist "^4.21.3" + lru-cache "^5.1.1" + semver "^6.3.0" + "@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.21.0": version "7.21.0" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.21.0.tgz#64f49ecb0020532f19b1d014b03bccaa1ab85fb9" @@ -242,7 +265,7 @@ dependencies: "@babel/types" "^7.18.6" -"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.20.11", "@babel/helper-module-transforms@^7.21.0", "@babel/helper-module-transforms@^7.21.2": +"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.20.11", "@babel/helper-module-transforms@^7.21.2": version "7.21.2" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz#160caafa4978ac8c00ac66636cb0fa37b024e2d2" integrity sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ== @@ -364,10 +387,10 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.3.tgz#1d285d67a19162ff9daa358d4cb41d50c06220b3" integrity sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ== -"@babel/parser@^7.21.0": - version "7.21.2" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.2.tgz#dacafadfc6d7654c3051a66d6fe55b6cb2f2a0b3" - integrity sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ== +"@babel/parser@^7.21.4": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.4.tgz#94003fdfc520bbe2875d4ae557b43ddb6d880f17" + integrity sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw== "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": version "7.18.6" @@ -1179,6 +1202,22 @@ debug "^4.1.0" globals "^11.1.0" +"@babel/traverse@^7.21.4": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.21.4.tgz#a836aca7b116634e97a6ed99976236b3282c9d36" + integrity sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q== + dependencies: + "@babel/code-frame" "^7.21.4" + "@babel/generator" "^7.21.4" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.21.0" + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/parser" "^7.21.4" + "@babel/types" "^7.21.4" + debug "^4.1.0" + globals "^11.1.0" + "@babel/types@^7.0.0", "@babel/types@^7.12.6", "@babel/types@^7.12.7", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.2.0", "@babel/types@^7.20.0", "@babel/types@^7.20.2", "@babel/types@^7.20.5", "@babel/types@^7.20.7", "@babel/types@^7.21.3", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.0", "@babel/types@^7.4.4": version "7.21.3" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.3.tgz#4865a5357ce40f64e3400b0f3b737dc6d4f64d05" @@ -1197,6 +1236,15 @@ "@babel/helper-validator-identifier" "^7.19.1" to-fast-properties "^2.0.0" +"@babel/types@^7.21.4": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.4.tgz#2d5d6bb7908699b3b416409ffd3b5daa25b030d4" + integrity sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA== + dependencies: + "@babel/helper-string-parser" "^7.19.4" + "@babel/helper-validator-identifier" "^7.19.1" + to-fast-properties "^2.0.0" + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" @@ -1530,14 +1578,14 @@ resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.4.0.tgz#3e61c564fcd6b921cb789838631c5ee44df09403" integrity sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ== -"@eslint/eslintrc@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.0.0.tgz#943309d8697c52fc82c076e90c1c74fbbe69dbff" - integrity sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A== +"@eslint/eslintrc@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.0.1.tgz#7888fe7ec8f21bc26d646dbd2c11cd776e21192d" + integrity sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw== dependencies: ajv "^6.12.4" debug "^4.3.2" - espree "^9.4.0" + espree "^9.5.0" globals "^13.19.0" ignore "^5.2.0" import-fresh "^3.2.1" @@ -1545,14 +1593,14 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/eslintrc@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.0.1.tgz#7888fe7ec8f21bc26d646dbd2c11cd776e21192d" - integrity sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw== +"@eslint/eslintrc@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.0.2.tgz#01575e38707add677cf73ca1589abba8da899a02" + integrity sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ== dependencies: ajv "^6.12.4" debug "^4.3.2" - espree "^9.5.0" + espree "^9.5.1" globals "^13.19.0" ignore "^5.2.0" import-fresh "^3.2.1" @@ -1560,16 +1608,16 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@8.35.0": - version "8.35.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.35.0.tgz#b7569632b0b788a0ca0e438235154e45d42813a7" - integrity sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw== - "@eslint/js@8.36.0": version "8.36.0" resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.36.0.tgz#9837f768c03a1e4a30bd304a64fb8844f0e72efe" integrity sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg== +"@eslint/js@8.38.0": + version "8.38.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.38.0.tgz#73a8a0d8aa8a8e6fe270431c5e72ae91b5337892" + integrity sha512-IoD2MfUnOV58ghIHCiil01PcohxjbYR/qCxsoC+xNgUwh1EY8jOOrYmu3d3a71+tJJ23uscEV4X2HJWMsPJu4g== + "@fluentui/date-time-utilities@^7.9.1": version "7.9.1" resolved "https://registry.yarnpkg.com/@fluentui/date-time-utilities/-/date-time-utilities-7.9.1.tgz#bb486dc0a0fff33ef5803adabbf95e2cbf4be7be" @@ -2139,12 +2187,12 @@ rxjs "6" semver "^7.3.5" -"@ledgerhq/devices@^8.0.0": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/devices/-/devices-8.0.0.tgz#8fe9f9e442e28b7a20bcdf4c2eed06ce7b8f76ae" - integrity sha512-gSnRT0KPca+LIpaC6D/WZQjOAlSI5uCvK1dmxXtKhODLAj735rX5Z3SnGnLUavRCHNbUi44FzgvloF5BKTkh7A== +"@ledgerhq/devices@^8.0.1": + version "8.0.1" + resolved "https://registry.yarnpkg.com/@ledgerhq/devices/-/devices-8.0.1.tgz#4c475f6ae249daf00ef08f5098924206233f3179" + integrity sha512-8uuyR8DGowYBLatur+MyJtRJ8RYDWSFFqGnNmgBBdlRG6VPf9vjhrFZlmYqukWesPwkZNZstP475W4TS+j6EFw== dependencies: - "@ledgerhq/errors" "^6.12.3" + "@ledgerhq/errors" "^6.12.4" "@ledgerhq/logs" "^6.10.1" rxjs "6" semver "^7.3.5" @@ -2154,31 +2202,31 @@ resolved "https://registry.yarnpkg.com/@ledgerhq/errors/-/errors-5.50.0.tgz#e3a6834cb8c19346efca214c1af84ed28e69dad9" integrity sha512-gu6aJ/BHuRlpU7kgVpy2vcYk6atjB4iauP2ymF7Gk0ez0Y/6VSMVSJvubeEQN+IV60+OBK0JgeIZG7OiHaw8ow== -"@ledgerhq/errors@^6.12.3": - version "6.12.3" - resolved "https://registry.yarnpkg.com/@ledgerhq/errors/-/errors-6.12.3.tgz#a610caae1eeeb7cb038525e5212fe03217dda683" - integrity sha512-djiMSgB/7hnK3aLR/c5ZMMivxjcI7o2+y3VKcsZZpydPoVf9+FXqeJPRfOwmJ0JxbQ//LinUfWpIfHew8LkaVw== +"@ledgerhq/errors@^6.12.4": + version "6.12.4" + resolved "https://registry.yarnpkg.com/@ledgerhq/errors/-/errors-6.12.4.tgz#1c2f75dc3dee91b069f3446be484fa28676d1b45" + integrity sha512-qi5poMrcIuFuivdzRjjQsNp7rRwUA5v3eo6D4yEy+l+w8wT4d4JtQ5u1TbrlGfFHfgLq7Lv6dsvh2ooLyWTyfg== -"@ledgerhq/hw-transport-node-hid-noevents@^6.27.12": - version "6.27.12" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid-noevents/-/hw-transport-node-hid-noevents-6.27.12.tgz#5dacbaf7e146018a73d18d16ce975925b5795732" - integrity sha512-f99lIcdEz78jHVfr57Vl9sgP/WpAuM3X26lLDSTKmNHDxLSx7IQaK/eJOcFG4XLk5K7dK/zoyXqq13zcLL2tPg== +"@ledgerhq/hw-transport-node-hid-noevents@^6.27.13": + version "6.27.13" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid-noevents/-/hw-transport-node-hid-noevents-6.27.13.tgz#96f3667a18ea3602160af5d08db677ae0b8e3bb7" + integrity sha512-Lq85zoc95eb5npudlgTARVrB57jbk8oZ8KuyVOovNm1AjR0OrYfl0iCqw49h+SL/UFWWVyBisLg6IOYCpj1SNQ== dependencies: - "@ledgerhq/devices" "^8.0.0" - "@ledgerhq/errors" "^6.12.3" - "@ledgerhq/hw-transport" "^6.28.1" + "@ledgerhq/devices" "^8.0.1" + "@ledgerhq/errors" "^6.12.4" + "@ledgerhq/hw-transport" "^6.28.2" "@ledgerhq/logs" "^6.10.1" node-hid "^2.1.2" -"@ledgerhq/hw-transport-node-hid@6.27.12": - version "6.27.12" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-6.27.12.tgz#8a628ea574c51bd727aa1d7b7a4ddaf9a5042df1" - integrity sha512-Y3GGgZK27K587P3671bCF4pbbfFYq6eVECnxoxtVwt0kdquRfpt3mxWlU51LIL+XgDEwBwt2QdB+6eyLHmWKQA== +"@ledgerhq/hw-transport-node-hid@6.27.13": + version "6.27.13" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-6.27.13.tgz#741644d7b8761f682b36eda36e1bf7876357efda" + integrity sha512-j4c1UOMylX9cE9ebTh+qqMfzZDJpK8WZ7/kalxdY/MHWQcO+F2XAMvEqdZOaMjSIhI0vbgL/OoEvO2nxGFhObA== dependencies: - "@ledgerhq/devices" "^8.0.0" - "@ledgerhq/errors" "^6.12.3" - "@ledgerhq/hw-transport" "^6.28.1" - "@ledgerhq/hw-transport-node-hid-noevents" "^6.27.12" + "@ledgerhq/devices" "^8.0.1" + "@ledgerhq/errors" "^6.12.4" + "@ledgerhq/hw-transport" "^6.28.2" + "@ledgerhq/hw-transport-node-hid-noevents" "^6.27.13" "@ledgerhq/logs" "^6.10.1" lodash "^4.17.21" node-hid "^2.1.2" @@ -2193,13 +2241,13 @@ "@ledgerhq/errors" "^5.50.0" events "^3.3.0" -"@ledgerhq/hw-transport@^6.28.1": - version "6.28.1" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-6.28.1.tgz#cb22fe9bc23af4682c30f2aac7fe6f7ab13ed65a" - integrity sha512-RaZe+abn0zBIz82cE9tp7Y7aZkHWWbEaE2yJpfxT8AhFz3fx+BU0kLYzuRN9fmA7vKueNJ1MTVUCY+Ex9/CHSQ== +"@ledgerhq/hw-transport@^6.28.2": + version "6.28.2" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-6.28.2.tgz#483f9a39403ee63b03d452e30bfe8189dcca5785" + integrity sha512-2LxQdZnhSzu394brKuUZIWfuT2YAyNI3glRMf8+yHx3wUFqi10v8NzII99SHDyT8tN3Ovzmq+hbGHvrR2PqYRA== dependencies: - "@ledgerhq/devices" "^8.0.0" - "@ledgerhq/errors" "^6.12.3" + "@ledgerhq/devices" "^8.0.1" + "@ledgerhq/errors" "^6.12.4" events "^3.3.0" "@ledgerhq/logs@^5.50.0": @@ -3006,11 +3054,6 @@ jsbi "3.1.3" tslib "2.3.1" -"@nervosnetwork/ckb-types@0.103.1": - version "0.103.1" - resolved "https://registry.yarnpkg.com/@nervosnetwork/ckb-types/-/ckb-types-0.103.1.tgz#b5626ce905353e70136bfaccf9def0819b76ca27" - integrity sha512-gGRR1VvUS/KRq2ChhXHPiHpgyLYazPM2R8lK87shQI82Gp2/m6k1HVDeNR5XOYwQ3YmBbxHGQtQr/kMq7DUlZA== - "@nervosnetwork/ckb-types@0.107.0": version "0.107.0" resolved "https://registry.yarnpkg.com/@nervosnetwork/ckb-types/-/ckb-types-0.107.0.tgz#980947e20d17edd145ff3805e7312bbeb38be2f6" @@ -3458,13 +3501,6 @@ resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz#8be36a1f66f3265389e90b5f9c9962146758f728" integrity sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg== -"@samverschueren/stream-to-observable@^0.3.0": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.1.tgz#a21117b19ee9be70c379ec1877537ef2e1c63301" - integrity sha512-c/qwwcHyafOQuVQJj0IlBjf5yYgBI7YPJ77k4fOJYesb41jio65eaJODRUmfYKhTOFBrIZ66kgvGPlNbjuoRdQ== - dependencies: - any-observable "^0.3.0" - "@sideway/address@^4.1.3": version "4.1.4" resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0" @@ -5081,15 +5117,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.3.tgz#f0b991c32cfc6a4e7f3399d6cb4b8cf9a0315014" integrity sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw== -"@types/node@18.14.6": - version "18.14.6" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.14.6.tgz#ae1973dd2b1eeb1825695bb11ebfb746d27e3e93" - integrity sha512-93+VvleD3mXwlLI/xASjw0FzKcwzl3OdTCzm1LaRfqgS21gfFtK3zDXM5Op9TeeMsJVOaJ2VRDpT9q4Y3d0AvA== - -"@types/node@^16.11.26": - version "16.18.16" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.16.tgz#09ff98b144abae2d7cce3e9fe9040ab2bf73222c" - integrity sha512-ZOzvDRWp8dCVBmgnkIqYCArgdFOO9YzocZp8Ra25N/RStKiWvMOXHMz+GjSeVNe5TstaTmTWPucGJkDw0XXJWA== +"@types/node@18.15.11", "@types/node@^18.11.18": + version "18.15.11" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.11.tgz#b3b790f09cb1696cffcec605de025b088fa4225f" + integrity sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q== "@types/normalize-package-data@^2.4.0": version "2.4.1" @@ -5197,10 +5228,10 @@ dependencies: "@types/react" "*" -"@types/react@*", "@types/react@17.0.53", "@types/react@^17": - version "17.0.53" - resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.53.tgz#10d4d5999b8af3d6bc6a9369d7eb953da82442ab" - integrity sha512-1yIpQR2zdYu1Z/dc1OxC+MA6GR240u3gcnP4l6mvj/PJiVaqHsQPmWttsvHsfnhfPbU2FuGmo0wSITPygjBmsw== +"@types/react@*", "@types/react@17.0.58", "@types/react@^17": + version "17.0.58" + resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.58.tgz#c8bbc82114e5c29001548ebe8ed6c4ba4d3c9fb0" + integrity sha512-c1GzVY97P0fGxwGxhYq989j4XwlcHQoto6wQISOC2v6wm3h0PORRWJFHlkRjfGsiG3y1609WdQ+J+tKxvrEd6A== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" @@ -5417,19 +5448,19 @@ dependencies: "@types/node" "*" -"@typescript-eslint/eslint-plugin@5.54.1": - version "5.54.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.54.1.tgz#0c5091289ce28372e38ab8d28e861d2dbe1ab29e" - integrity sha512-a2RQAkosH3d3ZIV08s3DcL/mcGc2M/UC528VkPULFxR9VnVPT8pBu0IyBAJJmVsCmhVfwQX1v6q+QGnmSe1bew== +"@typescript-eslint/eslint-plugin@5.58.0": + version "5.58.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.58.0.tgz#b1d4b0ad20243269d020ef9bbb036a40b0849829" + integrity sha512-vxHvLhH0qgBd3/tW6/VccptSfc8FxPQIkmNTVLWcCOVqSBvqpnKkBTYrhcGlXfSnd78azwe+PsjYFj0X34/njA== dependencies: - "@typescript-eslint/scope-manager" "5.54.1" - "@typescript-eslint/type-utils" "5.54.1" - "@typescript-eslint/utils" "5.54.1" + "@eslint-community/regexpp" "^4.4.0" + "@typescript-eslint/scope-manager" "5.58.0" + "@typescript-eslint/type-utils" "5.58.0" + "@typescript-eslint/utils" "5.58.0" debug "^4.3.4" grapheme-splitter "^1.0.4" ignore "^5.2.0" natural-compare-lite "^1.4.0" - regexpp "^3.2.0" semver "^7.3.7" tsutils "^3.21.0" @@ -5456,14 +5487,14 @@ dependencies: "@typescript-eslint/utils" "5.55.0" -"@typescript-eslint/parser@5.54.1": - version "5.54.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.54.1.tgz#05761d7f777ef1c37c971d3af6631715099b084c" - integrity sha512-8zaIXJp/nG9Ff9vQNh7TI+C3nA6q6iIsGJ4B4L6MhZ7mHnTMR4YP5vp2xydmFXIy8rpyIVbNAG44871LMt6ujg== +"@typescript-eslint/parser@5.58.0": + version "5.58.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.58.0.tgz#2ac4464cf48bef2e3234cb178ede5af352dddbc6" + integrity sha512-ixaM3gRtlfrKzP8N6lRhBbjTow1t6ztfBvQNGuRM8qH1bjFFXIJ35XY+FC0RRBKn3C6cT+7VW1y8tNm7DwPHDQ== dependencies: - "@typescript-eslint/scope-manager" "5.54.1" - "@typescript-eslint/types" "5.54.1" - "@typescript-eslint/typescript-estree" "5.54.1" + "@typescript-eslint/scope-manager" "5.58.0" + "@typescript-eslint/types" "5.58.0" + "@typescript-eslint/typescript-estree" "5.58.0" debug "^4.3.4" "@typescript-eslint/parser@^5.5.0": @@ -5476,14 +5507,6 @@ "@typescript-eslint/typescript-estree" "5.55.0" debug "^4.3.4" -"@typescript-eslint/scope-manager@5.54.1": - version "5.54.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.54.1.tgz#6d864b4915741c608a58ce9912edf5a02bb58735" - integrity sha512-zWKuGliXxvuxyM71UA/EcPxaviw39dB2504LqAmFDjmkpO8qNLHcmzlh6pbHs1h/7YQ9bnsO8CCcYCSA8sykUg== - dependencies: - "@typescript-eslint/types" "5.54.1" - "@typescript-eslint/visitor-keys" "5.54.1" - "@typescript-eslint/scope-manager@5.55.0": version "5.55.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.55.0.tgz#e863bab4d4183ddce79967fe10ceb6c829791210" @@ -5492,15 +5515,13 @@ "@typescript-eslint/types" "5.55.0" "@typescript-eslint/visitor-keys" "5.55.0" -"@typescript-eslint/type-utils@5.54.1": - version "5.54.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.54.1.tgz#4825918ec27e55da8bb99cd07ec2a8e5f50ab748" - integrity sha512-WREHsTz0GqVYLIbzIZYbmUUr95DKEKIXZNH57W3s+4bVnuF1TKe2jH8ZNH8rO1CeMY3U4j4UQeqPNkHMiGem3g== +"@typescript-eslint/scope-manager@5.58.0": + version "5.58.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.58.0.tgz#5e023a48352afc6a87be6ce3c8e763bc9e2f0bc8" + integrity sha512-b+w8ypN5CFvrXWQb9Ow9T4/6LC2MikNf1viLkYTiTbkQl46CnR69w7lajz1icW0TBsYmlpg+mRzFJ4LEJ8X9NA== dependencies: - "@typescript-eslint/typescript-estree" "5.54.1" - "@typescript-eslint/utils" "5.54.1" - debug "^4.3.4" - tsutils "^3.21.0" + "@typescript-eslint/types" "5.58.0" + "@typescript-eslint/visitor-keys" "5.58.0" "@typescript-eslint/type-utils@5.55.0": version "5.55.0" @@ -5512,28 +5533,25 @@ debug "^4.3.4" tsutils "^3.21.0" -"@typescript-eslint/types@5.54.1": - version "5.54.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.54.1.tgz#29fbac29a716d0f08c62fe5de70c9b6735de215c" - integrity sha512-G9+1vVazrfAfbtmCapJX8jRo2E4MDXxgm/IMOF4oGh3kq7XuK3JRkOg6y2Qu1VsTRmWETyTkWt1wxy7X7/yLkw== +"@typescript-eslint/type-utils@5.58.0": + version "5.58.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.58.0.tgz#f7d5b3971483d4015a470d8a9e5b8a7d10066e52" + integrity sha512-FF5vP/SKAFJ+LmR9PENql7fQVVgGDOS+dq3j+cKl9iW/9VuZC/8CFmzIP0DLKXfWKpRHawJiG70rVH+xZZbp8w== + dependencies: + "@typescript-eslint/typescript-estree" "5.58.0" + "@typescript-eslint/utils" "5.58.0" + debug "^4.3.4" + tsutils "^3.21.0" "@typescript-eslint/types@5.55.0": version "5.55.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.55.0.tgz#9830f8d3bcbecf59d12f821e5bc6960baaed41fd" integrity sha512-M4iRh4AG1ChrOL6Y+mETEKGeDnT7Sparn6fhZ5LtVJF1909D5O4uqK+C5NPbLmpfZ0XIIxCdwzKiijpZUOvOug== -"@typescript-eslint/typescript-estree@5.54.1": - version "5.54.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.1.tgz#df7b6ae05fd8fef724a87afa7e2f57fa4a599be1" - integrity sha512-bjK5t+S6ffHnVwA0qRPTZrxKSaFYocwFIkZx5k7pvWfsB1I57pO/0M0Skatzzw1sCkjJ83AfGTL0oFIFiDX3bg== - dependencies: - "@typescript-eslint/types" "5.54.1" - "@typescript-eslint/visitor-keys" "5.54.1" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - semver "^7.3.7" - tsutils "^3.21.0" +"@typescript-eslint/types@5.58.0": + version "5.58.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.58.0.tgz#54c490b8522c18986004df7674c644ffe2ed77d8" + integrity sha512-JYV4eITHPzVQMnHZcYJXl2ZloC7thuUHrcUmxtzvItyKPvQ50kb9QXBkgNAt90OYMqwaodQh2kHutWZl1fc+1g== "@typescript-eslint/typescript-estree@5.55.0": version "5.55.0" @@ -5548,19 +5566,18 @@ semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/utils@5.54.1": - version "5.54.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.54.1.tgz#7a3ee47409285387b9d4609ea7e1020d1797ec34" - integrity sha512-IY5dyQM8XD1zfDe5X8jegX6r2EVU5o/WJnLu/znLPWCBF7KNGC+adacXnt5jEYS9JixDcoccI6CvE4RCjHMzCQ== +"@typescript-eslint/typescript-estree@5.58.0": + version "5.58.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.58.0.tgz#4966e6ff57eaf6e0fce2586497edc097e2ab3e61" + integrity sha512-cRACvGTodA+UxnYM2uwA2KCwRL7VAzo45syNysqlMyNyjw0Z35Icc9ihPJZjIYuA5bXJYiJ2YGUB59BqlOZT1Q== dependencies: - "@types/json-schema" "^7.0.9" - "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.54.1" - "@typescript-eslint/types" "5.54.1" - "@typescript-eslint/typescript-estree" "5.54.1" - eslint-scope "^5.1.1" - eslint-utils "^3.0.0" + "@typescript-eslint/types" "5.58.0" + "@typescript-eslint/visitor-keys" "5.58.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" semver "^7.3.7" + tsutils "^3.21.0" "@typescript-eslint/utils@5.55.0", "@typescript-eslint/utils@^5.43.0": version "5.55.0" @@ -5576,13 +5593,19 @@ eslint-scope "^5.1.1" semver "^7.3.7" -"@typescript-eslint/visitor-keys@5.54.1": - version "5.54.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.1.tgz#d7a8a0f7181d6ac748f4d47b2306e0513b98bf8b" - integrity sha512-q8iSoHTgwCfgcRJ2l2x+xCbu8nBlRAlsQ33k24Adj8eoVBE0f8dUeI+bAa8F84Mv05UGbAx57g2zrRsYIooqQg== +"@typescript-eslint/utils@5.58.0": + version "5.58.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.58.0.tgz#430d7c95f23ec457b05be5520c1700a0dfd559d5" + integrity sha512-gAmLOTFXMXOC+zP1fsqm3VceKSBQJNzV385Ok3+yzlavNHZoedajjS4UyS21gabJYcobuigQPs/z71A9MdJFqQ== dependencies: - "@typescript-eslint/types" "5.54.1" - eslint-visitor-keys "^3.3.0" + "@eslint-community/eslint-utils" "^4.2.0" + "@types/json-schema" "^7.0.9" + "@types/semver" "^7.3.12" + "@typescript-eslint/scope-manager" "5.58.0" + "@typescript-eslint/types" "5.58.0" + "@typescript-eslint/typescript-estree" "5.58.0" + eslint-scope "^5.1.1" + semver "^7.3.7" "@typescript-eslint/visitor-keys@5.55.0": version "5.55.0" @@ -5592,6 +5615,14 @@ "@typescript-eslint/types" "5.55.0" eslint-visitor-keys "^3.3.0" +"@typescript-eslint/visitor-keys@5.58.0": + version "5.58.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.58.0.tgz#eb9de3a61d2331829e6761ce7fd13061781168b4" + integrity sha512-/fBraTlPj0jwdyTwLyrRTxv/3lnU2H96pNTVM6z3esTWLtA5MZ9ghSMJ7Rb+TtUAdtEw9EyJzJ0EydIMKxQ9gA== + dependencies: + "@typescript-eslint/types" "5.58.0" + eslint-visitor-keys "^3.3.0" + "@uifabric/azure-themes@^7.10.27": version "7.10.35" resolved "https://registry.yarnpkg.com/@uifabric/azure-themes/-/azure-themes-7.10.35.tgz#f758153ec2082d5a716a5b45761d23c6ab4a53e5" @@ -6357,12 +6388,12 @@ ansi-colors@^4.1.1: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== -ansi-escapes@^3.0.0, ansi-escapes@^3.2.0: +ansi-escapes@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== -ansi-escapes@^4.2.1, ansi-escapes@^4.3.1: +ansi-escapes@^4.2.1, ansi-escapes@^4.3.0, ansi-escapes@^4.3.1: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== @@ -6423,6 +6454,11 @@ ansi-styles@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== +ansi-styles@^6.0.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + ansi-to-html@^0.6.11: version "0.6.15" resolved "https://registry.yarnpkg.com/ansi-to-html/-/ansi-to-html-0.6.15.tgz#ac6ad4798a00f6aa045535d7f6a9cb9294eebea7" @@ -6430,11 +6466,6 @@ ansi-to-html@^0.6.11: dependencies: entities "^2.0.0" -any-observable@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.3.0.tgz#af933475e5806a67d0d7df090dd5e8bef65d119b" - integrity sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog== - any-promise@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" @@ -8279,7 +8310,12 @@ chalk@3.0.0, chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: +chalk@5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.2.0.tgz#249623b7d66869c673699fb66d65723e54dfcfb3" + integrity sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA== + +chalk@^1.1.1, chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A== @@ -8489,7 +8525,7 @@ cli-cursor@3.1.0, cli-cursor@^3.1.0: dependencies: restore-cursor "^3.1.0" -cli-cursor@^2.0.0, cli-cursor@^2.1.0: +cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" integrity sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw== @@ -8528,14 +8564,6 @@ cli-table3@0.5.1: optionalDependencies: colors "^1.1.2" -cli-truncate@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574" - integrity sha512-f4r4yJnbT++qUPI9NR4XLDLq41gQ+uqnPItWG0F5ZkehuNiTTa3EY0S4AqTSUOeJ7/zU41oWPQSNkW5BqPL9bg== - dependencies: - slice-ansi "0.0.4" - string-width "^1.0.1" - cli-truncate@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" @@ -8544,6 +8572,14 @@ cli-truncate@^2.1.0: slice-ansi "^3.0.0" string-width "^4.2.0" +cli-truncate@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-3.1.0.tgz#3f23ab12535e3d73e839bb43e73c9de487db1389" + integrity sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA== + dependencies: + slice-ansi "^5.0.0" + string-width "^5.0.0" + cli-width@^2.0.0: version "2.2.1" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" @@ -8713,7 +8749,7 @@ colord@^2.9.1: resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.3.tgz#4f8ce919de456f1d5c1c368c307fe20f3e59fb43" integrity sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw== -colorette@^2.0.10: +colorette@^2.0.10, colorette@^2.0.19: version "2.0.19" resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== @@ -8755,6 +8791,11 @@ commander@2.9.0: dependencies: graceful-readlink ">= 1.0.0" +commander@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.0.tgz#71797971162cd3cf65f0b9d24eb28f8d303acdf1" + integrity sha512-zS5PnTI22FIRM6ylNW8G4Ap0IEOyk62fhLSD0+uHRT9McRCLGpkVNvao4bjimpK/GShynyQkFFxHhwMcETmduA== + commander@^2.19.0, commander@^2.20.0, commander@^2.9.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -8873,20 +8914,20 @@ concat-stream@^2.0.0: readable-stream "^3.0.2" typedarray "^0.0.6" -concurrently@7.6.0: - version "7.6.0" - resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-7.6.0.tgz#531a6f5f30cf616f355a4afb8f8fcb2bba65a49a" - integrity sha512-BKtRgvcJGeZ4XttiDiNcFiRlxoAeZOseqUvyYRUp/Vtd+9p1ULmeoSqGsDA+2ivdeDFpqrJvGvmI+StKfKl5hw== +concurrently@8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-8.0.1.tgz#80c0591920a9fa3e68ba0dd8aa6eac8487eb904c" + integrity sha512-Sh8bGQMEL0TAmAm2meAXMjcASHZa7V0xXQVDBLknCPa9TPtkY9yYs+0cnGGgfdkW0SV1Mlg+hVGfXcoI8d3MJA== dependencies: - chalk "^4.1.0" - date-fns "^2.29.1" + chalk "^4.1.2" + date-fns "^2.29.3" lodash "^4.17.21" - rxjs "^7.0.0" - shell-quote "^1.7.3" - spawn-command "^0.0.2-1" - supports-color "^8.1.0" + rxjs "^7.8.0" + shell-quote "^1.8.0" + spawn-command "0.0.2-1" + supports-color "^8.1.1" tree-kill "^1.2.2" - yargs "^17.3.1" + yargs "^17.7.1" config-chain@^1.1.12: version "1.1.13" @@ -9518,12 +9559,7 @@ data-urls@^2.0.0: whatwg-mimetype "^2.3.0" whatwg-url "^8.0.0" -date-fns@^1.27.2: - version "1.30.1" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" - integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw== - -date-fns@^2.29.1: +date-fns@^2.29.3: version "2.29.3" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.3.tgz#27402d2fc67eb442b511b70bbdf98e6411cd68a8" integrity sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA== @@ -9747,20 +9783,6 @@ defined@~0.0.0: resolved "https://registry.yarnpkg.com/defined/-/defined-0.0.0.tgz#f35eea7d705e933baf13b2f03b3f83d921403b3e" integrity sha512-zpqiCT8bODLu3QSmLLic8xJnYWBFjOSu/fBCm189oAiTtPq/PSanNACKZDS7kgSyCJY7P+IcODzlIogBK/9RBg== -del@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/del/-/del-5.1.0.tgz#d9487c94e367410e6eff2925ee58c0c84a75b3a7" - integrity sha512-wH9xOVHnczo9jN2IW68BabcecVPxacIA3g/7z6vhSU/4stOKQzeCRK0yD0A24WiAAUJmmVpWqrERcTxnLo3AnA== - dependencies: - globby "^10.0.1" - graceful-fs "^4.2.2" - is-glob "^4.0.1" - is-path-cwd "^2.2.0" - is-path-inside "^3.0.1" - p-map "^3.0.0" - rimraf "^3.0.0" - slash "^3.0.0" - delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -10204,6 +10226,11 @@ duplexify@^3.4.2, duplexify@^3.6.0: readable-stream "^2.0.0" stream-shift "^1.0.0" +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" @@ -10322,20 +10349,15 @@ electron-window-state@5.0.3: jsonfile "^4.0.0" mkdirp "^0.5.1" -electron@23.1.2: - version "23.1.2" - resolved "https://registry.yarnpkg.com/electron/-/electron-23.1.2.tgz#f03e361c94f8dd2407963b5461d19aadea335316" - integrity sha512-ajE6xzIwH7swf8TlTU5WklDqpI3mPj4Am6690YrpCXzcp+E+dmMBXIajUUNt4joDrFhJC/lC6ZqDS2Q1BApKgQ== +electron@24.1.1: + version "24.1.1" + resolved "https://registry.yarnpkg.com/electron/-/electron-24.1.1.tgz#05fa6269b1ee303fed7a05de9eb4be56c46660b8" + integrity sha512-ymjUMe6Pvh9ytpM4lOvr+Qxd6NG5AELRtR6tw54bK3FXfKtTTKKAtZw/NbwHwkRAlWu8FNAGOuvCoap6/bm9LQ== dependencies: "@electron/get" "^2.0.0" - "@types/node" "^16.11.26" + "@types/node" "^18.11.18" extract-zip "^2.0.1" -elegant-spinner@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" - integrity sha512-B+ZM+RXvRqQaAmkMlO/oSe5nMUOaUnyfGYCEHoR8wrXsZR2mA0XVibsxV1bvTwxdRWah1PkQqso2EzhILGHtEQ== - element-resize-detector@^1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/element-resize-detector/-/element-resize-detector-1.2.4.tgz#3e6c5982dd77508b5fa7e6d5c02170e26325c9b1" @@ -10741,10 +10763,10 @@ eslint-config-airbnb@19.0.4: object.assign "^4.1.2" object.entries "^1.1.5" -eslint-config-prettier@8.7.0: - version "8.7.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.7.0.tgz#f1cc58a8afebc50980bd53475451df146c13182d" - integrity sha512-HHVXLSlVUhMSmyW4ZzEuvjpwqamgmlfkutD53cYXLikh4pt/modINRcCIApJ84czDxM4GZInwUrromsDdTImTA== +eslint-config-prettier@8.8.0: + version "8.8.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz#bfda738d412adc917fd7b038857110efe98c9348" + integrity sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA== eslint-config-react-app@^7.0.1: version "7.0.1" @@ -10840,17 +10862,10 @@ eslint-plugin-jsx-a11y@6.7.1, eslint-plugin-jsx-a11y@^6.5.1: object.fromentries "^2.0.6" semver "^6.3.0" -eslint-plugin-prettier@3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz#e9ddb200efb6f3d05ffe83b1665a716af4a387e5" - integrity sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g== - dependencies: - prettier-linter-helpers "^1.0.0" - -eslint-plugin-prettier@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz#8b99d1e4b8b24a762472b4567992023619cb98e0" - integrity sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ== +eslint-plugin-prettier@4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz#651cbb88b1dab98bfd42f017a12fa6b2d993f94b" + integrity sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ== dependencies: prettier-linter-helpers "^1.0.0" @@ -10911,14 +10926,7 @@ eslint-scope@^7.1.1: esrecurse "^4.3.0" estraverse "^5.2.0" -eslint-utils@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" - integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== - dependencies: - eslint-visitor-keys "^2.0.0" - -eslint-visitor-keys@^2.0.0, eslint-visitor-keys@^2.1.0: +eslint-visitor-keys@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== @@ -10928,6 +10936,11 @@ eslint-visitor-keys@^3.3.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== +eslint-visitor-keys@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz#c7f0f956124ce677047ddbc192a68f999454dedc" + integrity sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ== + eslint-webpack-plugin@^3.1.1: version "3.2.0" resolved "https://registry.yarnpkg.com/eslint-webpack-plugin/-/eslint-webpack-plugin-3.2.0.tgz#1978cdb9edc461e4b0195a20da950cf57988347c" @@ -10939,13 +10952,15 @@ eslint-webpack-plugin@^3.1.1: normalize-path "^3.0.0" schema-utils "^4.0.0" -eslint@8.35.0: - version "8.35.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.35.0.tgz#fffad7c7e326bae606f0e8f436a6158566d42323" - integrity sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw== +eslint@8.38.0: + version "8.38.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.38.0.tgz#a62c6f36e548a5574dd35728ac3c6209bd1e2f1a" + integrity sha512-pIdsD2jwlUGf/U38Jv97t8lq6HpaU/G9NKbYmpWpZGw3LdTNhZLbJePqxOXGB5+JEKfOPU/XLxYxFh03nr1KTg== dependencies: - "@eslint/eslintrc" "^2.0.0" - "@eslint/js" "8.35.0" + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.4.0" + "@eslint/eslintrc" "^2.0.2" + "@eslint/js" "8.38.0" "@humanwhocodes/config-array" "^0.11.8" "@humanwhocodes/module-importer" "^1.0.1" "@nodelib/fs.walk" "^1.2.8" @@ -10956,9 +10971,8 @@ eslint@8.35.0: doctrine "^3.0.0" escape-string-regexp "^4.0.0" eslint-scope "^7.1.1" - eslint-utils "^3.0.0" - eslint-visitor-keys "^3.3.0" - espree "^9.4.0" + eslint-visitor-keys "^3.4.0" + espree "^9.5.1" esquery "^1.4.2" esutils "^2.0.2" fast-deep-equal "^3.1.3" @@ -10980,7 +10994,6 @@ eslint@8.35.0: minimatch "^3.1.2" natural-compare "^1.4.0" optionator "^0.9.1" - regexpp "^3.2.0" strip-ansi "^6.0.1" strip-json-comments "^3.1.0" text-table "^0.2.0" @@ -11036,7 +11049,7 @@ esm@3.2.25: resolved "https://registry.yarnpkg.com/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10" integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA== -espree@^9.4.0, espree@^9.5.0: +espree@^9.5.0: version "9.5.0" resolved "https://registry.yarnpkg.com/espree/-/espree-9.5.0.tgz#3646d4e3f58907464edba852fa047e6a27bdf113" integrity sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw== @@ -11045,6 +11058,15 @@ espree@^9.4.0, espree@^9.5.0: acorn-jsx "^5.3.2" eslint-visitor-keys "^3.3.0" +espree@^9.5.1: + version "9.5.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.5.1.tgz#4f26a4d5f18905bf4f2e0bd99002aab807e96dd4" + integrity sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg== + dependencies: + acorn "^8.8.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.0" + esprima@^4.0.0, esprima@^4.0.1, esprima@~4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" @@ -11152,21 +11174,6 @@ execa@^1.0.0: signal-exit "^3.0.0" strip-eof "^1.0.0" -execa@^2.0.3: - version "2.1.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-2.1.0.tgz#e5d3ecd837d2a60ec50f3da78fd39767747bbe99" - integrity sha512-Y/URAVapfbYy2Xp/gb6A0E7iR8xeqOCXsuuaoMn7A5PzrXUK84E1gyiEfq0wQd/GHA6GsoHWwhNq8anb0mleIw== - dependencies: - cross-spawn "^7.0.0" - get-stream "^5.0.0" - is-stream "^2.0.0" - merge-stream "^2.0.0" - npm-run-path "^3.0.0" - onetime "^5.1.0" - p-finally "^2.0.0" - signal-exit "^3.0.2" - strip-final-newline "^2.0.0" - execa@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" @@ -11182,6 +11189,21 @@ execa@^5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" +execa@^7.0.0: + version "7.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-7.1.1.tgz#3eb3c83d239488e7b409d48e8813b76bb55c9c43" + integrity sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.1" + human-signals "^4.3.0" + is-stream "^3.0.0" + merge-stream "^2.0.0" + npm-run-path "^5.1.0" + onetime "^6.0.0" + signal-exit "^3.0.7" + strip-final-newline "^3.0.0" + exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" @@ -11377,7 +11399,7 @@ fast-glob@^2.0.2: merge2 "^1.2.3" micromatch "^3.1.10" -fast-glob@^3.0.3, fast-glob@^3.2.12, fast-glob@^3.2.9: +fast-glob@^3.2.12, fast-glob@^3.2.9: version "3.2.12" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== @@ -11450,14 +11472,6 @@ figures@3.2.0, figures@^3.0.0: dependencies: escape-string-regexp "^1.0.5" -figures@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" - integrity sha512-UxKlfCRuCBxSXU4C6t9scbDyWZ4VlaFFdojKtzJuSkuOBQ5CNFum+zZXFwHjo+CxBC1t6zlYPgHIgFjL8ggoEQ== - dependencies: - escape-string-regexp "^1.0.5" - object-assign "^4.1.0" - figures@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" @@ -12013,11 +12027,6 @@ get-port@^5.1.1: resolved "https://registry.yarnpkg.com/get-port/-/get-port-5.1.1.tgz#0469ed07563479de6efb986baf053dcd7d4e3193" integrity sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ== -get-stdin@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-7.0.0.tgz#8d5de98f15171a125c5e516643c7a6d0ea8a96f6" - integrity sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ== - get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" @@ -12030,14 +12039,14 @@ get-stream@^4.0.0, get-stream@^4.1.0: dependencies: pump "^3.0.0" -get-stream@^5.0.0, get-stream@^5.1.0: +get-stream@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== dependencies: pump "^3.0.0" -get-stream@^6.0.0: +get-stream@^6.0.0, get-stream@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== @@ -12284,20 +12293,6 @@ globby@8.0.2: pify "^3.0.0" slash "^1.0.0" -globby@^10.0.1: - version "10.0.2" - resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.2.tgz#277593e745acaa4646c3ab411289ec47a0392543" - integrity sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg== - dependencies: - "@types/glob" "^7.1.1" - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.0.3" - glob "^7.1.3" - ignore "^5.1.1" - merge2 "^1.2.3" - slash "^3.0.0" - globby@^11.0.0, globby@^11.0.2, globby@^11.0.4, globby@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" @@ -12950,6 +12945,11 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== +human-signals@^4.3.0: + version "4.3.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-4.3.1.tgz#ab7f811e851fca97ffbd2c1fe9a958964de321b2" + integrity sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ== + humanize-ms@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" @@ -12962,22 +12962,10 @@ humanize-plus@^1.8.1: resolved "https://registry.yarnpkg.com/humanize-plus/-/humanize-plus-1.8.2.tgz#a65b34459ad6367adbb3707a82a3c9f916167030" integrity sha512-jaLeQyyzjjINGv7O9JJegjsaUcWjSj/1dcXvLEgU3pGdqCdP1PiC/uwr+saJXhTNBHZtmKnmpXyazgh+eceRxA== -husky@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/husky/-/husky-3.1.0.tgz#5faad520ab860582ed94f0c1a77f0f04c90b57c0" - integrity sha512-FJkPoHHB+6s4a+jwPqBudBDvYZsoQW5/HBuMSehC8qDiCe50kpcxeqFoDSlow+9I6wg47YxBoT3WxaURlrDIIQ== - dependencies: - chalk "^2.4.2" - ci-info "^2.0.0" - cosmiconfig "^5.2.1" - execa "^1.0.0" - get-stdin "^7.0.0" - opencollective-postinstall "^2.0.2" - pkg-dir "^4.2.0" - please-upgrade-node "^3.2.0" - read-pkg "^5.2.0" - run-node "^1.0.0" - slash "^3.0.0" +husky@8.0.3: + version "8.0.3" + resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184" + integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg== hw-app-ckb@0.1.2: version "0.1.2" @@ -13078,7 +13066,7 @@ ignore@^3.3.5: resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== -ignore@^5.0.4, ignore@^5.1.1, ignore@^5.2.0: +ignore@^5.0.4, ignore@^5.2.0: version "5.2.4" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== @@ -13098,10 +13086,10 @@ immer@1.10.0: resolved "https://registry.yarnpkg.com/immer/-/immer-1.10.0.tgz#bad67605ba9c810275d91e1c2a47d4582e98286d" integrity sha512-O3sR1/opvCDGLEVcvrGTMtLac8GJ5IwZC4puPrLuRj3l7ICKvkmA0vGuU9OW8mV9WIBRnaxp5GJh9IEAaNOoYg== -immer@9.0.16: - version "9.0.16" - resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.16.tgz#8e7caab80118c2b54b37ad43e05758cdefad0198" - integrity sha512-qenGE7CstVm1NrHQbMh8YaSzTZTFNP3zPqr3YU0S0UY441j4bJTg4A2Hh5KAhwgaiU6ZZ1Ar6y/2f4TblnMReQ== +immer@9.0.21: + version "9.0.21" + resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.21.tgz#1e025ea31a40f24fb064f1fef23e931496330176" + integrity sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA== immer@^9.0.7: version "9.0.19" @@ -13161,11 +13149,6 @@ imurmurhash@^0.1.4: resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== -indent-string@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" - integrity sha512-BYqTHXTGUIvg7t1r4sJNKcbDZkL92nkXA8YtRpbjFHRHGDL/NtUeiBJMeE60kIFN/Mg8ESaWQvftaYMGJzQZCQ== - indent-string@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" @@ -13547,6 +13530,11 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== +is-fullwidth-code-point@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz#fae3167c729e7463f8461ce512b080a49268aa88" + integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ== + is-function@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.2.tgz#4f097f30abf6efadac9833b17ca5dc03f8144e08" @@ -13655,18 +13643,6 @@ is-object@^1.0.1: resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.2.tgz#a56552e1c665c9e950b4a025461da87e72f86fcf" integrity sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA== -is-observable@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-observable/-/is-observable-1.1.0.tgz#b3e986c8f44de950867cab5403f5a3465005975e" - integrity sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA== - dependencies: - symbol-observable "^1.1.0" - -is-path-cwd@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" - integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== - is-path-inside@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" @@ -13674,7 +13650,7 @@ is-path-inside@^1.0.0: dependencies: path-is-inside "^1.0.1" -is-path-inside@^3.0.1, is-path-inside@^3.0.3: +is-path-inside@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== @@ -13716,11 +13692,6 @@ is-potential-custom-element-name@^1.0.1: resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== -is-promise@^2.1.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" - integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== - is-regex@^1.0.4, is-regex@^1.0.5, is-regex@^1.1.0, is-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" @@ -13768,6 +13739,11 @@ is-stream@^2.0.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== +is-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" + integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== + is-string@^1.0.5, is-string@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" @@ -15411,7 +15387,7 @@ lie@~3.3.0: dependencies: immediate "~3.0.5" -lilconfig@^2.0.3, lilconfig@^2.0.5, lilconfig@^2.0.6: +lilconfig@2.1.0, lilconfig@^2.0.3, lilconfig@^2.0.5, lilconfig@^2.0.6: version "2.1.0" resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== @@ -15426,69 +15402,38 @@ lines-and-columns@~2.0.3: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-2.0.3.tgz#b2f0badedb556b747020ab8ea7f0373e22efac1b" integrity sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w== -lint-staged@9.5.0: - version "9.5.0" - resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-9.5.0.tgz#290ec605252af646d9b74d73a0fa118362b05a33" - integrity sha512-nawMob9cb/G1J98nb8v3VC/E8rcX1rryUYXVZ69aT9kde6YWX+uvNOEHY5yf2gcWcTJGiD0kqXmCnS3oD75GIA== +lint-staged@13.2.1: + version "13.2.1" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-13.2.1.tgz#9d30a14e3e42897ef417bc98556fb757f75cae87" + integrity sha512-8gfzinVXoPfga5Dz/ZOn8I2GOhf81Wvs+KwbEXQn/oWZAvCVS2PivrXfVbFJc93zD16uC0neS47RXHIjXKYZQw== dependencies: - chalk "^2.4.2" - commander "^2.20.0" - cosmiconfig "^5.2.1" - debug "^4.1.1" - dedent "^0.7.0" - del "^5.0.0" - execa "^2.0.3" - listr "^0.14.3" - log-symbols "^3.0.0" - micromatch "^4.0.2" + chalk "5.2.0" + cli-truncate "^3.1.0" + commander "^10.0.0" + debug "^4.3.4" + execa "^7.0.0" + lilconfig "2.1.0" + listr2 "^5.0.7" + micromatch "^4.0.5" normalize-path "^3.0.0" - please-upgrade-node "^3.1.1" - string-argv "^0.3.0" - stringify-object "^3.3.0" - -listr-silent-renderer@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e" - integrity sha512-L26cIFm7/oZeSNVhWB6faeorXhMg4HNlb/dS/7jHhr708jxlXrtrBWo4YUxZQkc6dGoxEAe6J/D3juTRBUzjtA== - -listr-update-renderer@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz#4ea8368548a7b8aecb7e06d8c95cb45ae2ede6a2" - integrity sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA== - dependencies: - chalk "^1.1.3" - cli-truncate "^0.2.1" - elegant-spinner "^1.0.1" - figures "^1.7.0" - indent-string "^3.0.0" - log-symbols "^1.0.2" - log-update "^2.3.0" - strip-ansi "^3.0.1" - -listr-verbose-renderer@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz#f1132167535ea4c1261102b9f28dac7cba1e03db" - integrity sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw== - dependencies: - chalk "^2.4.1" - cli-cursor "^2.1.0" - date-fns "^1.27.2" - figures "^2.0.0" + object-inspect "^1.12.3" + pidtree "^0.6.0" + string-argv "^0.3.1" + yaml "^2.2.1" -listr@^0.14.3: - version "0.14.3" - resolved "https://registry.yarnpkg.com/listr/-/listr-0.14.3.tgz#2fea909604e434be464c50bddba0d496928fa586" - integrity sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA== +listr2@^5.0.7: + version "5.0.8" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-5.0.8.tgz#a9379ffeb4bd83a68931a65fb223a11510d6ba23" + integrity sha512-mC73LitKHj9w6v30nLNGPetZIlfpUniNSsxxrbaPcWOjDb92SHPzJPi/t+v1YC/lxKz/AJ9egOjww0qUuFxBpA== dependencies: - "@samverschueren/stream-to-observable" "^0.3.0" - is-observable "^1.1.0" - is-promise "^2.1.0" - is-stream "^1.1.0" - listr-silent-renderer "^1.1.1" - listr-update-renderer "^0.5.0" - listr-verbose-renderer "^0.5.0" - p-map "^2.0.0" - rxjs "^6.3.3" + cli-truncate "^2.1.0" + colorette "^2.0.19" + log-update "^4.0.0" + p-map "^4.0.0" + rfdc "^1.3.0" + rxjs "^7.8.0" + through "^2.3.8" + wrap-ansi "^7.0.0" load-json-file@^4.0.0: version "4.0.0" @@ -15686,20 +15631,6 @@ lodash@^4.0.1, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.15, lodash@^4.17.1 resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -log-symbols@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18" - integrity sha512-mmPrW0Fh2fxOzdBbFv4g1m6pR72haFLPJ2G5SJEELf1y+iaQrDG6cWCPjy54RHYbZAt7X+ls690Kw62AdWXBzQ== - dependencies: - chalk "^1.0.0" - -log-symbols@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" - integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== - dependencies: - chalk "^2.4.2" - log-symbols@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" @@ -15708,14 +15639,15 @@ log-symbols@^4.1.0: chalk "^4.1.0" is-unicode-supported "^0.1.0" -log-update@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/log-update/-/log-update-2.3.0.tgz#88328fd7d1ce7938b29283746f0b1bc126b24708" - integrity sha512-vlP11XfFGyeNQlmEn9tJ66rEW1coA/79m5z6BCkudjbAGE83uhAcGYrBFwfs3AdLiLzGRusRPAbSPK9xZteCmg== +log-update@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1" + integrity sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg== dependencies: - ansi-escapes "^3.0.0" - cli-cursor "^2.0.0" - wrap-ansi "^3.0.1" + ansi-escapes "^4.3.0" + cli-cursor "^3.1.0" + slice-ansi "^4.0.0" + wrap-ansi "^6.2.0" loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0: version "1.4.0" @@ -16157,6 +16089,11 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== +mimic-fn@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" + integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== + mimic-response@^1.0.0, mimic-response@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" @@ -17019,13 +16956,6 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" -npm-run-path@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-3.1.0.tgz#7f91be317f6a466efed3c9f2980ad8a4ee8b0fa5" - integrity sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg== - dependencies: - path-key "^3.0.0" - npm-run-path@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" @@ -17033,6 +16963,13 @@ npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" +npm-run-path@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.1.0.tgz#bc62f7f3f6952d9894bd08944ba011a6ee7b7e00" + integrity sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q== + dependencies: + path-key "^4.0.0" + "npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" @@ -17313,6 +17250,13 @@ onetime@^5.1.0, onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" +onetime@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4" + integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ== + dependencies: + mimic-fn "^4.0.0" + open@^6.3.0: version "6.4.0" resolved "https://registry.yarnpkg.com/open/-/open-6.4.0.tgz#5c13e96d0dc894686164f18965ecfe889ecfc8a9" @@ -17337,11 +17281,6 @@ open@^8.0.9, open@^8.4.0: is-docker "^2.1.1" is-wsl "^2.2.0" -opencollective-postinstall@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259" - integrity sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q== - optionator@^0.8.1: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" @@ -17419,11 +17358,6 @@ p-finally@^1.0.0: resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== -p-finally@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-2.0.1.tgz#bd6fcaa9c559a096b680806f4d657b3f0f240561" - integrity sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw== - p-limit@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" @@ -17478,11 +17412,6 @@ p-map-series@^2.1.0: resolved "https://registry.yarnpkg.com/p-map-series/-/p-map-series-2.1.0.tgz#7560d4c452d9da0c07e692fdbfe6e2c81a2a91f2" integrity sha512-RpYIIK1zXSNEOdwxcfe7FdvGcs7+y5n8rifMhMNWvaxRNMPINJHF5GDeuVxWqnfrcHPSCnp7Oo5yNXHId9Av2Q== -p-map@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" - integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== - p-map@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d" @@ -17820,6 +17749,11 @@ path-key@^3.0.0, path-key@^3.1.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== +path-key@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" + integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== + path-parse@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" @@ -17885,6 +17819,11 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3, picomatc resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +pidtree@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.6.0.tgz#90ad7b6d42d5841e69e0a2419ef38f8883aa057c" + integrity sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g== + pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -17948,13 +17887,6 @@ pkg-up@^3.1.0: dependencies: find-up "^3.0.0" -please-upgrade-node@^3.1.1, please-upgrade-node@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942" - integrity sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg== - dependencies: - semver-compare "^1.0.0" - plist@^3.0.1, plist@^3.0.4: version "3.0.6" resolved "https://registry.yarnpkg.com/plist/-/plist-3.0.6.tgz#7cfb68a856a7834bca6dbfe3218eb9c7740145d3" @@ -18642,7 +18574,12 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier@1.19.1, prettier@^1.16.4: +prettier@2.8.7: + version "2.8.7" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.7.tgz#bb79fc8729308549d28fe3a98fce73d2c0656450" + integrity sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw== + +prettier@^1.16.4: version "1.19.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== @@ -19821,11 +19758,6 @@ regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.4.3: define-properties "^1.1.3" functions-have-names "^1.2.2" -regexpp@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" - integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== - regexpu-core@^5.3.1: version "5.3.2" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.3.2.tgz#11a2b06884f3527aec3e93dbbf4a3b958a95546b" @@ -20131,6 +20063,11 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== +rfdc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" + integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== + rgbcolor@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/rgbcolor/-/rgbcolor-1.0.1.tgz#d6505ecdb304a6595da26fa4b43307306775945d" @@ -20219,11 +20156,6 @@ run-async@^2.2.0, run-async@^2.4.0: resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== -run-node@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/run-node/-/run-node-1.0.0.tgz#46b50b946a2aa2d4947ae1d886e9856fd9cabe5e" - integrity sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A== - run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -20238,14 +20170,14 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" -rxjs@6, rxjs@6.6.7, rxjs@^6.3.3, rxjs@^6.4.0, rxjs@^6.6.0: +rxjs@6, rxjs@6.6.7, rxjs@^6.4.0, rxjs@^6.6.0: version "6.6.7" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== dependencies: tslib "^1.9.0" -rxjs@^7.0.0, rxjs@^7.5.4, rxjs@^7.5.5: +rxjs@^7.5.4, rxjs@^7.5.5, rxjs@^7.8.0: version "7.8.0" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.0.tgz#90a938862a82888ff4c7359811a595e14e1e09a4" integrity sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg== @@ -20328,10 +20260,10 @@ sass-loader@^12.3.0: klona "^2.0.4" neo-async "^2.6.2" -sass@1.58.3: - version "1.58.3" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.58.3.tgz#2348cc052061ba4f00243a208b09c40e031f270d" - integrity sha512-Q7RaEtYf6BflYrQ+buPudKR26/lH+10EmO9bBqbmPh/KeLqv8bjpTNqxe71ocONqXq+jYiCbpPUmQMS+JJPk4A== +sass@1.62.0: + version "1.62.0" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.62.0.tgz#3686b2195b93295d20765135e562366b33ece37d" + integrity sha512-Q4USplo4pLYgCi+XlipZCWUQz5pkg/ruSSgJ0WRDSb/+3z9tXUOkQ7QPYn4XrhZKYAK4HlpaQecRwKLJX6+DBg== dependencies: chokidar ">=3.0.0 <4.0.0" immutable "^4.0.0" @@ -20654,6 +20586,11 @@ shell-quote@^1.7.3: resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.0.tgz#20d078d0eaf71d54f43bd2ba14a1b5b9bfa5c8ba" integrity sha512-QHsz8GgQIGKlRi24yFc6a6lN69Idnx634w49ay6+jA5yFh7a1UY+4Rp6HPx/L/1zcEDPEij8cIsiqR6bQsE5VQ== +shell-quote@^1.8.0: + version "1.8.1" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.1.tgz#6dbf4db75515ad5bac63b4f1894c3a154c766680" + integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA== + shelljs@^0.8.3: version "0.8.5" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c" @@ -20743,11 +20680,6 @@ slash@^4.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== -slice-ansi@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" - integrity sha512-up04hB2hR92PgjpyU3y/eg91yIBILyjVY26NvvciY3EVVPjybkMszMpXQ9QAkcS3I5rtJBDLoTxxg+qvW8c7rw== - slice-ansi@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" @@ -20757,6 +20689,23 @@ slice-ansi@^3.0.0: astral-regex "^2.0.0" is-fullwidth-code-point "^3.0.0" +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +slice-ansi@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-5.0.0.tgz#b73063c57aa96f9cd881654b15294d95d285c42a" + integrity sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ== + dependencies: + ansi-styles "^6.0.0" + is-fullwidth-code-point "^4.0.0" + slide@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" @@ -20956,7 +20905,7 @@ space-separated-tokens@^1.0.0: resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz#85f32c3d10d9682007e917414ddc5c26d1aa6899" integrity sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA== -spawn-command@^0.0.2-1: +spawn-command@0.0.2-1: version "0.0.2-1" resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0" integrity sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg== @@ -21214,7 +21163,7 @@ strict-uri-encode@^1.0.0: resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" integrity sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ== -string-argv@^0.3.0: +string-argv@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg== @@ -21275,6 +21224,15 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" +string-width@^5.0.0: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + "string.prototype.matchall@^4.0.0 || ^3.0.1", string.prototype.matchall@^4.0.6, string.prototype.matchall@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz#3bf85722021816dcd1bf38bb714915887ca79fd3" @@ -21422,6 +21380,11 @@ strip-final-newline@^2.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== +strip-final-newline@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" + integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== + strip-indent@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" @@ -21521,7 +21484,7 @@ supports-color@^7.0.0, supports-color@^7.1.0: dependencies: has-flag "^4.0.0" -supports-color@^8.0.0, supports-color@^8.1.0: +supports-color@^8.0.0, supports-color@^8.1.1: version "8.1.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== @@ -21578,11 +21541,6 @@ svgo@^2.7.0: picocolors "^1.0.0" stable "^0.1.8" -symbol-observable@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" - integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== - symbol-tree@^3.2.4: version "3.2.4" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" @@ -21880,7 +21838,7 @@ through2@^4.0.0: dependencies: readable-stream "3" -through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6: +through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6, through@^2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== @@ -22327,10 +22285,10 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" -undici@5.19.1: - version "5.19.1" - resolved "https://registry.yarnpkg.com/undici/-/undici-5.19.1.tgz#92b1fd3ab2c089b5a6bd3e579dcda8f1934ebf6d" - integrity sha512-YiZ61LPIgY73E7syxCDxxa3LV2yl3sN8spnIuTct60boiiRaE1J8mNWHO8Im2Zi/sFrPusjLlmRPrsyraSqX6A== +undici@5.21.2: + version "5.21.2" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.21.2.tgz#329f628aaea3f1539a28b9325dccc72097d29acd" + integrity sha512-f6pTQ9RF4DQtwoWSaC42P/NKlUjvezVvd9r155ohqkwFNRyBKM3f3pcty3ouusefNRyM25XhIQEbeQ46sZDJfQ== dependencies: busboy "^1.6.0" @@ -23428,14 +23386,6 @@ worker-rpc@^0.1.0: dependencies: microevent.ts "~0.1.1" -wrap-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-3.0.1.tgz#288a04d87eda5c286e060dfe8f135ce8d007f8ba" - integrity sha512-iXR3tDXpbnTpzjKSylUJRkLuOrEC7hwEB221cgn6wtF8wpmz28puFXAEfPT5zrjM3wahygB//VuWEr1vTkDcNQ== - dependencies: - string-width "^2.1.1" - strip-ansi "^4.0.0" - wrap-ansi@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" @@ -23445,6 +23395,15 @@ wrap-ansi@^5.1.0: string-width "^3.0.0" strip-ansi "^5.0.0" +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -23611,6 +23570,11 @@ yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2: resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== +yaml@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.2.1.tgz#3014bf0482dcd15147aa8e56109ce8632cd60ce4" + integrity sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw== + yargonaut@^1.1.2: version "1.1.4" resolved "https://registry.yarnpkg.com/yargonaut/-/yargonaut-1.1.4.tgz#c64f56432c7465271221f53f5cc517890c3d6e0c" @@ -23672,7 +23636,7 @@ yargs@^16.0.0, yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@^17.3.1, yargs@^17.5.1, yargs@^17.6.2: +yargs@^17.5.1, yargs@^17.6.2, yargs@^17.7.1: version "17.7.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.1.tgz#34a77645201d1a8fc5213ace787c220eabbd0967" integrity sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw== From 4c6ef294dbca328d5660f77d4a31d6c9fb50135a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=A5=E5=9B=BD=E5=AE=87?= <841185308@qq.com> Date: Mon, 17 Apr 2023 20:42:43 +0800 Subject: [PATCH 31/52] fix: Fix when enter over 8 decimal crash. (#2629) --- packages/neuron-ui/src/components/NervosDAO/index.tsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/neuron-ui/src/components/NervosDAO/index.tsx b/packages/neuron-ui/src/components/NervosDAO/index.tsx index 2fef820a42..3bb9cc88cd 100644 --- a/packages/neuron-ui/src/components/NervosDAO/index.tsx +++ b/packages/neuron-ui/src/components/NervosDAO/index.tsx @@ -247,8 +247,14 @@ const NervosDAO = () => { }, []) useEffect(() => { - if (BigInt(CKBToShannonFormatter(depositValue)) > maxDepositAmount) { - setDepositValue(shannonToCKBFormatter(`${maxDepositAmount}`, false, '')) + try { + if (BigInt(CKBToShannonFormatter(depositValue)) > maxDepositAmount) { + setDepositValue(shannonToCKBFormatter(`${maxDepositAmount}`, false, '')) + } + } catch (error) { + // ignore error + // When the depositValue is invalid, it displays the error in the textField, but it will throw an exception when valid wheater it's big than the max deposit value + // and when the depositValue is invalid, it's no need to set max depositValue. } }, [maxDepositAmount, depositValue, setDepositValue]) From 678ff830023350c043ce66f3ebf17f7e0111c338 Mon Sep 17 00:00:00 2001 From: Chen Yu Date: Sun, 23 Apr 2023 10:22:03 +0800 Subject: [PATCH 32/52] ci: fix the add-label action (#2643) * ci: fix the add-label action Ref: https://github.com/actions-ecosystem/action-add-labels * ci: filter pull request out in issue management This commit adds a step to filter pull requests out because pull request is also regarded as an issue in GitHub Ref: action triggered by comment in pr: https://github.com/nervosnetwork/neuron/actions/runs/4760813903 --- .github/workflows/add-replied-label.yml | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/.github/workflows/add-replied-label.yml b/.github/workflows/add-replied-label.yml index 0dc24712f5..9dfb292006 100644 --- a/.github/workflows/add-replied-label.yml +++ b/.github/workflows/add-replied-label.yml @@ -22,10 +22,24 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - id: check-issue + name: Check if the comment is replied in an issue + uses: actions/github-script@v4 + with: + script: | + const response = await github.repos.issues.get({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + }) + return { isIssue: !response.data.pull_request } + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - id: add-label name: Add 'replied' label - if: steps.check-access.outputs.hasWriteAccess - uses: actions-ecosystem/action-add-label@v1 + if: ${{ steps.check-access.outputs.hasWriteAccess && steps.check-issue.outputs.isIssue }} + uses: actions-ecosystem/action-add-labels@v1 with: repo-token: ${{ secrets.GITHUB_TOKEN }} issue-number: ${{ github.event.issue.number }} From 03b40ee085d7292024c750f0cc72f83d57ac9b0e Mon Sep 17 00:00:00 2001 From: Keith Date: Sun, 23 Apr 2023 15:15:36 +0800 Subject: [PATCH 33/52] refactor: use github rest api to update labels The external action is out-of-date on permission management in github action, so the label action is re-written in github rest api for maintenance. Ref: https://github.com/actions-ecosystem/action-add-labels/issues/444 --- .github/workflows/add-replied-label.yml | 27 ++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/.github/workflows/add-replied-label.yml b/.github/workflows/add-replied-label.yml index 9dfb292006..9ba991676f 100644 --- a/.github/workflows/add-replied-label.yml +++ b/.github/workflows/add-replied-label.yml @@ -7,9 +7,11 @@ on: jobs: add-label: runs-on: ubuntu-latest + permissions: + issues: write steps: - id: check-access - name: Check if the commenter has write access + name: Check if the commenter is a collaborator uses: actions/github-script@v4 with: script: | @@ -18,7 +20,7 @@ jobs: repo: context.repo.repo, username: context.payload.comment.user.login, }) - return { hasWriteAccess: response.data.permission === 'write' } + return response.status === 204 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -27,20 +29,27 @@ jobs: uses: actions/github-script@v4 with: script: | - const response = await github.repos.issues.get({ + const response = await github.issues.get({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, }) - return { isIssue: !response.data.pull_request } + return response.data.pull_request === undefined env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - id: add-label name: Add 'replied' label - if: ${{ steps.check-access.outputs.hasWriteAccess && steps.check-issue.outputs.isIssue }} - uses: actions-ecosystem/action-add-labels@v1 + if: ${{ steps.check-access.outputs.result == 'true' && steps.check-issue.outputs.result == 'true' }} + uses: actions/github-script@v4 with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - issue-number: ${{ github.event.issue.number }} - label: replied + script: | + await github.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + labels: process.env.labels.split(', '), + }) + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + labels: 'replied' From dd06df33e000e50b37eaa40e6bfe1114ed14277a Mon Sep 17 00:00:00 2001 From: Keith Date: Tue, 25 Apr 2023 11:02:18 +0800 Subject: [PATCH 34/52] refactor: fallback to false instead of throw in label action This commit catches '404' response of github rest api and return 'false' instead of throwing it out which makes the action look like failed. --- .github/workflows/add-replied-label.yml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/.github/workflows/add-replied-label.yml b/.github/workflows/add-replied-label.yml index 9ba991676f..5e596dd725 100644 --- a/.github/workflows/add-replied-label.yml +++ b/.github/workflows/add-replied-label.yml @@ -15,12 +15,16 @@ jobs: uses: actions/github-script@v4 with: script: | - const response = await github.repos.checkCollaborator({ - owner: context.repo.owner, - repo: context.repo.repo, - username: context.payload.comment.user.login, - }) - return response.status === 204 + try{ + const response = await github.repos.checkCollaborator({ + owner: context.repo.owner, + repo: context.repo.repo, + username: context.payload.comment.user.login, + }) + return response.status === 204 + } catch { + return false + } env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 4a9e1dc53c85a4118b46f8f3943339cf0215773b Mon Sep 17 00:00:00 2001 From: Keith Date: Tue, 25 Apr 2023 13:59:06 +0800 Subject: [PATCH 35/52] fix: fix typo --- packages/neuron-wallet/src/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/neuron-wallet/src/main.ts b/packages/neuron-wallet/src/main.ts index d9f8c57179..e358754995 100644 --- a/packages/neuron-wallet/src/main.ts +++ b/packages/neuron-wallet/src/main.ts @@ -17,7 +17,7 @@ if (singleInstanceLock) { }) app.on('before-quit', async () => { - logger.info('App:\tNeuron will exist') + logger.info('App:\tNeuron will exit') await appController.end() }) From 6bee124e329b0dc33cda0a2059815ed0546dc476 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=A5=E5=9B=BD=E5=AE=87?= <841185308@qq.com> Date: Wed, 26 Apr 2023 18:14:11 +0800 Subject: [PATCH 36/52] feat: Add dialog warn for migrate date to 0.108 (#2651) --- .../src/containers/Notification/index.tsx | 35 +++++++++++++++---- packages/neuron-ui/src/locales/en.json | 1 + packages/neuron-ui/src/locales/zh-tw.json | 1 + packages/neuron-ui/src/locales/zh.json | 1 + packages/neuron-ui/src/services/subjects.ts | 2 +- .../src/stories/GlobalDialog.stories.tsx | 2 +- packages/neuron-ui/src/utils/const.ts | 2 +- packages/neuron-ui/src/utils/hooks/index.ts | 21 ++++++----- .../src/widgets/GlobalDialog/index.tsx | 9 +++-- 9 files changed, 52 insertions(+), 22 deletions(-) diff --git a/packages/neuron-ui/src/containers/Notification/index.tsx b/packages/neuron-ui/src/containers/Notification/index.tsx index f23cbb0588..8efab67577 100644 --- a/packages/neuron-ui/src/containers/Notification/index.tsx +++ b/packages/neuron-ui/src/containers/Notification/index.tsx @@ -1,4 +1,4 @@ -import React, { useMemo, useCallback, MouseEventHandler } from 'react' +import React, { useMemo, useCallback, MouseEventHandler, useState } from 'react' import { createPortal } from 'react-dom' import { useTranslation } from 'react-i18next' import { Stack, MessageBar, MessageBarType, IconButton, Panel, PanelType, Text } from 'office-ui-fabric-react' @@ -11,12 +11,13 @@ import { dismissNotification, dismissGlobalDialog, } from 'states' -import { useOnLocaleChange, useGlobalNotifications, isSuccessResponse } from 'utils' +import { useOnLocaleChange, useGlobalNotifications, isSuccessResponse, useDidMount } from 'utils' +import { shell } from 'electron' import GlobalDialog from 'widgets/GlobalDialog' import AlertDialog from 'widgets/AlertDialog' import { syncRebuildNotification } from 'services/localCache' -import { migrateData } from 'services/remote' +import { getCkbNodeDataPath, migrateData } from 'services/remote' import styles from './Notification.module.scss' const notificationType = (type: 'success' | 'warning' | 'alert') => { @@ -79,7 +80,8 @@ export const NoticeContent = () => { const dispatch = useDispatch() const [t, i18n] = useTranslation() useOnLocaleChange(i18n) - useGlobalNotifications(dispatch) + const [hasDismissMigrate, setHasDismissMigrate] = useState(false) + useGlobalNotifications(dispatch, hasDismissMigrate) const notificationsInDesc = useMemo(() => [...notifications].reverse(), [notifications]) const notification: State.Message | undefined = notificationsInDesc[0] @@ -101,17 +103,36 @@ export const NoticeContent = () => { const onGlobalDialogDismiss = useCallback(() => { dismissGlobalDialog()(dispatch) - }, [dispatch]) + if (globalDialog === 'rebuild-sync') { + setHasDismissMigrate(true) + } + }, [dispatch, globalDialog]) const onOk = useCallback(() => { migrateData().then(res => { if (isSuccessResponse(res)) { dismissGlobalDialog()(dispatch) - syncRebuildNotification.save() } + }).finally(() => { + syncRebuildNotification.save() }) }, [dispatch]) + const [ckbDataPath, setCkbDataPath] = useState() + useDidMount(() => { + getCkbNodeDataPath().then(res => { + if (isSuccessResponse(res) && res.result) { + setCkbDataPath(res.result) + } + }) + }) + + const onOpenDataDir = useCallback(() => { + if (ckbDataPath) { + shell.openPath(ckbDataPath) + } + }, [ckbDataPath]) + return (
{showTopAlert && notification ? ( @@ -197,7 +218,7 @@ export const NoticeContent = () => { ) })} - +
) diff --git a/packages/neuron-ui/src/locales/en.json b/packages/neuron-ui/src/locales/en.json index 7f0fecd41f..be611a6196 100644 --- a/packages/neuron-ui/src/locales/en.json +++ b/packages/neuron-ui/src/locales/en.json @@ -506,6 +506,7 @@ "experimental-message-hardware": "This is an experimental feature. Please pay attention to the risk and use with caution.", "experimental-message": "This is an experimental feature, it could change at any time. Please use with caution.", "rebuild-sync": "For better user experience, Neuron has adopted a new storage, which requires a migrating of data (estimated 20 ~ 60min).\nSorry for the inconvenience.", + "migrate-warning": "Warning: The migration process may fail for unknown reasons resulting in resynchronization, please back up manually and start the migration!", "migrate": "Migrate", "secp256k1/blake160-address-required": "Secp256k1/blake160 address is required", "fields": { diff --git a/packages/neuron-ui/src/locales/zh-tw.json b/packages/neuron-ui/src/locales/zh-tw.json index d45a4fe26f..ad2508617b 100644 --- a/packages/neuron-ui/src/locales/zh-tw.json +++ b/packages/neuron-ui/src/locales/zh-tw.json @@ -499,6 +499,7 @@ "experimental-message-hardware": "本功能為實驗性功能,請註意風險,謹慎使用。", "experimental-message": "本頁面為實驗性功能,可能隨時變更。請謹慎使用。", "rebuild-sync": "為了提供更好的用戶體驗,Neuron 採取了新的存儲方案,該方案需要壹次性遷移數據(預期同步時間為 20~60 分鐘)。\n抱歉給您帶來不便。", + "migrate-warning": "註意:遷移過程中可能由於未知原因失敗導致需要重新同步,請備份完成後開始遷移!", "migrate": "遷移", "secp256k1/blake160-address-required": "請輸入 secp256k1/blake160 地址", "fields": { diff --git a/packages/neuron-ui/src/locales/zh.json b/packages/neuron-ui/src/locales/zh.json index aa817d5a31..5cd4ba3825 100644 --- a/packages/neuron-ui/src/locales/zh.json +++ b/packages/neuron-ui/src/locales/zh.json @@ -499,6 +499,7 @@ "experimental-message-hardware": "本功能为实验性功能,请注意风险,谨慎使用。", "experimental-message": "本页面为实验性功能,可能随时变更。请谨慎使用。", "rebuild-sync": "为了提供更好的用户体验,Neuron 採取了新的存储方案,该方案需要一次性迁移数据(预期同步时间为 20~60 分钟)。\n抱歉给您带来不便。", + "migrate-warning": "注意:迁移过程中可能由于未知原因失败导致需要重新同步,请备份完成后开始迁移!", "migrate": "迁移", "secp256k1/blake160-address-required": "请输入 secp256k1/blake160 地址", "fields": { diff --git a/packages/neuron-ui/src/services/subjects.ts b/packages/neuron-ui/src/services/subjects.ts index 6a486a420b..628d367feb 100644 --- a/packages/neuron-ui/src/services/subjects.ts +++ b/packages/neuron-ui/src/services/subjects.ts @@ -65,7 +65,7 @@ export const Navigation = SubjectConstructor('navigation') export const SetLocale = SubjectConstructor('set-locale') export const DeviceSignIndex = SubjectConstructor('device-sign-index') export const MultisigOutputUpdate = SubjectConstructor('multisig-output-update') -export const Migrate = SubjectConstructor<'need-migrate' | 'migrating' | 'failed' | 'finish'>('migrate', true) +export const Migrate = SubjectConstructor<'need-migrate' | 'migrating' | 'failed' | 'finish'>('migrate') export default { DataUpdate, diff --git a/packages/neuron-ui/src/stories/GlobalDialog.stories.tsx b/packages/neuron-ui/src/stories/GlobalDialog.stories.tsx index 561f9ea6c4..7d1e9d8750 100644 --- a/packages/neuron-ui/src/stories/GlobalDialog.stories.tsx +++ b/packages/neuron-ui/src/stories/GlobalDialog.stories.tsx @@ -9,6 +9,6 @@ const types: State.GlobalDialogType[] = ['unlock-success', 'rebuild-sync', null] types.forEach(type => { stories.add(type || 'Null', () => { - return + return }) }) diff --git a/packages/neuron-ui/src/utils/const.ts b/packages/neuron-ui/src/utils/const.ts index 419adb3478..69d33c9b2f 100644 --- a/packages/neuron-ui/src/utils/const.ts +++ b/packages/neuron-ui/src/utils/const.ts @@ -57,7 +57,7 @@ export const LONG_DATA_PREFIX = '0x02' export const LONG_TYPE_PREFIX = '0x04' // times -export const SYNC_REBUILD_SINCE_VERSION = '0.105' +export const SYNC_REBUILD_SINCE_VERSION = '0.108' export const DEPRECATED_CODE_HASH: Record = { AcpOnLina: '0x0fb343953ee78c9986b091defb6252154e0bb51044fd2879fde5b27314506111', diff --git a/packages/neuron-ui/src/utils/hooks/index.ts b/packages/neuron-ui/src/utils/hooks/index.ts index f30eeb3d0d..47576ee7f5 100644 --- a/packages/neuron-ui/src/utils/hooks/index.ts +++ b/packages/neuron-ui/src/utils/hooks/index.ts @@ -433,27 +433,30 @@ export const useOnHandleNetwork = ({ history }: { history: ReturnType + dispatch: React.Dispatch<{ type: AppActions.SetGlobalDialog; payload: State.GlobalDialogType }>, + hasDismissMigrate: boolean ) => { useEffect(() => { const lastVersion = syncRebuildNotification.load() const isVersionUpdate = isReadyByVersion(CONSTANTS.SYNC_REBUILD_SINCE_VERSION, lastVersion) - if (isVersionUpdate) { - dispatch({ - type: AppActions.SetGlobalDialog, - payload: 'rebuild-sync', - }) - } const migrateSubscription = Migrate.subscribe(migrateStatus => { - if (!isVersionUpdate && migrateStatus === 'need-migrate') { + if (migrateStatus !== 'need-migrate') return + if (lastVersion && !isVersionUpdate) { + // means has click migrate for current version, so migrate silent migrateData() migrateSubscription.unsubscribe() + } else if (!hasDismissMigrate) { + // means need click ok to migrate + dispatch({ + type: AppActions.SetGlobalDialog, + payload: 'rebuild-sync', + }) } }) return () => { migrateSubscription.unsubscribe() } - }, [dispatch]) + }, [dispatch, hasDismissMigrate]) } export const useDidMount = (cb: () => void) => { diff --git a/packages/neuron-ui/src/widgets/GlobalDialog/index.tsx b/packages/neuron-ui/src/widgets/GlobalDialog/index.tsx index 4c9796b20c..1201039e74 100644 --- a/packages/neuron-ui/src/widgets/GlobalDialog/index.tsx +++ b/packages/neuron-ui/src/widgets/GlobalDialog/index.tsx @@ -14,7 +14,7 @@ const UnlockSuccess = () => { ) } -const RebuildSync = ({ onDismiss, onOk }: { onDismiss: React.MouseEventHandler; onOk: React.MouseEventHandler }) => { +const RebuildSync = ({ onDismiss, onBackUp, onOk }: { onDismiss: React.MouseEventHandler; onBackUp: React.MouseEventHandler; onOk: React.MouseEventHandler }) => { const [t] = useTranslation() return (
@@ -23,8 +23,10 @@ const RebuildSync = ({ onDismiss, onOk }: { onDismiss: React.MouseEventHandler; .map((s: string) => (

{s}

))} +

{t('messages.migrate-warning')}

@@ -34,10 +36,11 @@ const RebuildSync = ({ onDismiss, onOk }: { onDismiss: React.MouseEventHandler; interface GlobalDialogProps { onDismiss: React.MouseEventHandler onOk: React.MouseEventHandler + onBackUp: React.MouseEventHandler type: State.GlobalDialogType } -const GlobalDialog = ({ onDismiss, type, onOk }: GlobalDialogProps) => { +const GlobalDialog = ({ onDismiss, type, onOk, onBackUp }: GlobalDialogProps) => { let content = null let maskClosable = true switch (type) { @@ -47,7 +50,7 @@ const GlobalDialog = ({ onDismiss, type, onOk }: GlobalDialogProps) => { } case 'rebuild-sync': { maskClosable = false - content = + content = break } default: { From 20da0808ad0237a8eab0e6bd0a883249de34dfaf Mon Sep 17 00:00:00 2001 From: WhiteMind Date: Thu, 27 Apr 2023 15:45:06 +0800 Subject: [PATCH 37/52] fix: failed to connect to ckb rpc after upgrading electron to v23 --- .../src/components/NetworkEditor/index.tsx | 2 +- .../src/stories/NetworkSetting.stories.tsx | 6 ++--- .../src/stories/NetworkStatus.stories.tsx | 4 ++-- .../src/tests/is/isMainnet/fixtures.ts | 6 ++--- .../neuron-wallet/src/services/networks.ts | 23 ++++++++++++++++++- packages/neuron-wallet/src/utils/const.ts | 2 +- .../tests/controllers/export-debug.test.ts | 2 +- .../tests/services/networks.test.ts | 19 +++++++++++---- .../neuron-wallet/tests/services/node.test.ts | 2 +- 9 files changed, 48 insertions(+), 18 deletions(-) diff --git a/packages/neuron-ui/src/components/NetworkEditor/index.tsx b/packages/neuron-ui/src/components/NetworkEditor/index.tsx index 62d22e76e3..4105007a81 100644 --- a/packages/neuron-ui/src/components/NetworkEditor/index.tsx +++ b/packages/neuron-ui/src/components/NetworkEditor/index.tsx @@ -105,7 +105,7 @@ const NetworkEditor = () => { onChange={onChange} label={t('settings.network.edit-network.rpc-url')} error={editor.urlError} - placeholder="http://localhost:8114" + placeholder="http://127.0.0.1:8114" required autoFocus /> diff --git a/packages/neuron-ui/src/stories/NetworkSetting.stories.tsx b/packages/neuron-ui/src/stories/NetworkSetting.stories.tsx index ce7cda1263..1fa4e8a932 100644 --- a/packages/neuron-ui/src/stories/NetworkSetting.stories.tsx +++ b/packages/neuron-ui/src/stories/NetworkSetting.stories.tsx @@ -10,21 +10,21 @@ const states: { [title: string]: State.Network[] } = { { id: 'Mainnet', name: 'Mainnet', - remote: 'http://localhost:8114', + remote: 'http://127.0.0.1:8114', chain: 'ckb', type: 0, }, { id: 'Testnet', name: 'Testnet', - remote: 'http://localhost:8114', + remote: 'http://127.0.0.1:8114', chain: 'ckb_testnet', type: 1, }, { id: 'Local', name: 'Local', - remote: 'http://localhost:8114', + remote: 'http://127.0.0.1:8114', chain: 'ckb_devnet', type: 1, }, diff --git a/packages/neuron-ui/src/stories/NetworkStatus.stories.tsx b/packages/neuron-ui/src/stories/NetworkStatus.stories.tsx index 48d16ef422..4f9572404e 100644 --- a/packages/neuron-ui/src/stories/NetworkStatus.stories.tsx +++ b/packages/neuron-ui/src/stories/NetworkStatus.stories.tsx @@ -6,7 +6,7 @@ import NetworkStatus, { NetworkStatusProps } from 'components/NetworkStatus' const defaultProps: Omit = { network: { name: 'network', - remote: 'http://localhost:3000', + remote: 'http://127.0.0.1:3000', type: 0, id: 'd', chain: 'ckb', @@ -67,7 +67,7 @@ stories.add('With knobs', () => { const props = { network: { name: text('Network name', 'network name'), - remote: text('Remote', 'http://localhost:3000'), + remote: text('Remote', 'http://127.0.0.1:3000'), type: select('Type', [0, 1], 0) as any, id: text('id', 'd'), chain: select('Chain', ['ckb', 'ckb_testnet', 'ckb_dev'], 'ckb'), diff --git a/packages/neuron-ui/src/tests/is/isMainnet/fixtures.ts b/packages/neuron-ui/src/tests/is/isMainnet/fixtures.ts index 739207c1dd..9749009a15 100644 --- a/packages/neuron-ui/src/tests/is/isMainnet/fixtures.ts +++ b/packages/neuron-ui/src/tests/is/isMainnet/fixtures.ts @@ -16,7 +16,7 @@ const fixtures = { 'Should return false when network id cannot be found in network list': { params: { networkID: 'testnet', - networks: [{ id: 'mainnet', chain: 'ckb', type: 0 as 0 | 1, name: 'Mainnet', remote: 'http://localhost:8114' }], + networks: [{ id: 'mainnet', chain: 'ckb', type: 0 as 0 | 1, name: 'Mainnet', remote: 'http://127.0.0.1:8114' }], }, expected: false, }, @@ -24,7 +24,7 @@ const fixtures = { params: { networkID: 'testnet', networks: [ - { id: 'testnet', chain: 'ckb_testnet', type: 0 as 0 | 1, name: 'Mainnet', remote: 'http://localhost:8114' }, + { id: 'testnet', chain: 'ckb_testnet', type: 0 as 0 | 1, name: 'Mainnet', remote: 'http://127.0.0.1:8114' }, ], }, expected: false, @@ -32,7 +32,7 @@ const fixtures = { "Should return true when network id can be found in network list and it's Mainnet": { params: { networkID: 'mainnet', - networks: [{ id: 'mainnet', chain: 'ckb', type: 0 as 0 | 1, name: 'Mainnet', remote: 'http://localhost:8114' }], + networks: [{ id: 'mainnet', chain: 'ckb', type: 0 as 0 | 1, name: 'Mainnet', remote: 'http://127.0.0.1:8114' }], }, expected: true, }, diff --git a/packages/neuron-wallet/src/services/networks.ts b/packages/neuron-wallet/src/services/networks.ts index 24be2b4bb4..cb5071b8dd 100644 --- a/packages/neuron-wallet/src/services/networks.ts +++ b/packages/neuron-wallet/src/services/networks.ts @@ -8,6 +8,7 @@ import { Validate, Required } from 'utils/validators' import { UsedName, NetworkNotFound, InvalidFormat } from 'exceptions' import { MAINNET_GENESIS_HASH, EMPTY_GENESIS_HASH, NetworkType, Network } from 'models/network' import CommonUtils from 'utils/common' +import { BUNDLED_CKB_URL } from 'utils/const' const presetNetworks: { selected: string; networks: Network[] } = { selected: 'mainnet', @@ -15,7 +16,7 @@ const presetNetworks: { selected: string; networks: Network[] } = { { id: 'mainnet', name: 'Default', - remote: 'http://localhost:8114', + remote: BUNDLED_CKB_URL, genesisHash: MAINNET_GENESIS_HASH, type: NetworkType.Default, chain: 'ckb' @@ -47,6 +48,12 @@ export default class NetworksService extends Store { public getAll = () => { const networks = this.readSync(NetworksKey.List) || presetNetworks.networks + networks.forEach((network) => { + // Currently, the RPC interface of the CKB node is bound to IPv4 by default. + // Starting from node17, its DNS resolution is no longer `ipv4first`. + // Therefore, to ensure normal connection to the ckb node, manual resolution needs to be done here. + network.remote = applyLocalhostIPv4Resolve(network.remote) + }) const defaultNetwork = networks[0] const isOldDefaultName = ['Default', 'Mainnet'].includes(networks[0].name) defaultNetwork.name = isOldDefaultName ? 'default node' : defaultNetwork.name @@ -176,3 +183,17 @@ export default class NetworksService extends Store { return network } } + +function applyLocalhostIPv4Resolve(url: string): string { + let urlObj + try { + urlObj = new URL(url) + } catch (err) { + return url + } + + if (urlObj.hostname !== 'localhost') return url + + urlObj.hostname = '127.0.0.1' + return urlObj.href +} diff --git a/packages/neuron-wallet/src/utils/const.ts b/packages/neuron-wallet/src/utils/const.ts index 0fe3ff2f81..9d1e694f9c 100644 --- a/packages/neuron-wallet/src/utils/const.ts +++ b/packages/neuron-wallet/src/utils/const.ts @@ -1,6 +1,6 @@ export const MIN_PASSWORD_LENGTH = 8 export const MAX_PASSWORD_LENGTH = 50 -export const BUNDLED_CKB_URL = 'http://localhost:8114' +export const BUNDLED_CKB_URL = 'http://127.0.0.1:8114' export const SETTINGS_WINDOW_TITLE = process.platform === 'darwin' ? 'settings.title.mac' : 'settings.title.normal' export const SETTINGS_WINDOW_WIDTH = 900 export const DEFAULT_UDT_SYMBOL = 'Unknown' diff --git a/packages/neuron-wallet/tests/controllers/export-debug.test.ts b/packages/neuron-wallet/tests/controllers/export-debug.test.ts index 9ab2b6b6d6..60458c3ea6 100644 --- a/packages/neuron-wallet/tests/controllers/export-debug.test.ts +++ b/packages/neuron-wallet/tests/controllers/export-debug.test.ts @@ -55,7 +55,7 @@ jest.mock('../../src/services/networks', () => { return { getCurrent() { return { - remote: 'http://localhost:8114' + remote: 'http://127.0.0.1:8114' } } } diff --git a/packages/neuron-wallet/tests/services/networks.test.ts b/packages/neuron-wallet/tests/services/networks.test.ts index ca0fd752dd..fb6e3ae19c 100644 --- a/packages/neuron-wallet/tests/services/networks.test.ts +++ b/packages/neuron-wallet/tests/services/networks.test.ts @@ -11,7 +11,7 @@ const ERROR_MESSAGE = { describe(`Unit tests of networks service`, () => { const newNetwork: Network = { name: `new network`, - remote: `http://localhost:8114`, + remote: `http://127.0.0.1:8114`, type: 0, genesisHash: '0x', id: '', @@ -20,7 +20,7 @@ describe(`Unit tests of networks service`, () => { const newNetworkWithDefaultTypeOf1 = { name: `new network with the default type of 1`, - remote: `http://localhost:8114`, + remote: `http://127.0.0.1:8114`, id: '', } @@ -82,12 +82,21 @@ describe(`Unit tests of networks service`, () => { it(`update the network' address`, async () => { const network = await service.create(newNetworkWithDefaultTypeOf1.name, newNetworkWithDefaultTypeOf1.remote) - const address = `http://localhost:8115` + const address = `http://127.0.0.1:8115` await service.update(network.id, { remote: address }) const updated = service.get(network.id) expect(updated && updated.remote).toBe(address) }) + it(`use ipv4 to resolve the localhost in network' remote`, async () => { + const network = await service.create(newNetworkWithDefaultTypeOf1.name, 'http://localhost:8114/') + const created = service.get(network.id) + expect(created && created.remote).toBe('http://127.0.0.1:8114/') + await service.update(network.id, { remote: 'http://localhost:8114/' }) + const updated = service.get(network.id) + expect(updated && updated.remote).toBe('http://127.0.0.1:8114/') + }) + it(`set the network to be the current one`, async () => { const network = await service.create(newNetworkWithDefaultTypeOf1.name, newNetworkWithDefaultTypeOf1.remote) await service.activate(network.id) @@ -151,11 +160,11 @@ describe(`Unit tests of networks service`, () => { describe(`validation on network existence`, () => { beforeEach(async () => { - await service.create('Default', 'http://localhost:8114') + await service.create('Default', 'http://127.0.0.1:8114') }); it(`create network with existing name of Default`, () => { - expect(service.create('Default', 'http://localhost:8114')).rejects.toThrowError(t(ERROR_MESSAGE.NAME_USED)) + expect(service.create('Default', 'http://127.0.0.1:8114')).rejects.toThrowError(t(ERROR_MESSAGE.NAME_USED)) }) it(`update network which is not existing`, () => { diff --git a/packages/neuron-wallet/tests/services/node.test.ts b/packages/neuron-wallet/tests/services/node.test.ts index 5f89450b9d..54edad3da4 100644 --- a/packages/neuron-wallet/tests/services/node.test.ts +++ b/packages/neuron-wallet/tests/services/node.test.ts @@ -322,7 +322,7 @@ describe('NodeService', () => { expect(stubbedTipNumberSubjectCallback).toHaveBeenCalledWith('0') }) describe('targets to bundled node', () => { - const bundledNodeUrl = 'http://localhost:8114' + const bundledNodeUrl = 'http://127.0.0.1:8114' beforeEach(async () => { stubbedCKBSetNode.mockImplementation(() => { nodeService.ckb.node.url = bundledNodeUrl From 5b7f4cdd02294883d110f65a0426b6073674777a Mon Sep 17 00:00:00 2001 From: WhiteMind Date: Fri, 5 May 2023 17:41:13 +0800 Subject: [PATCH 38/52] chore: use macos-latest for package --- .github/workflows/package.yml | 8 ++++---- .github/workflows/package_for_test.yml | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index c14e893e89..cdddaf7d4e 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -14,7 +14,7 @@ jobs: node: - 18.12.0 os: - - macos-11 + - macos-latest - ubuntu-20.04 - windows-2019 @@ -67,7 +67,7 @@ jobs: CI: false - name: Package for MacOS - if: matrix.os == 'macos-11' + if: matrix.os == 'macos-latest' run: | ./scripts/download-ckb.sh mac yarn release mac @@ -99,7 +99,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Upload Neuron App Zip - if: matrix.os == 'macos-11' + if: matrix.os == 'macos-latest' uses: actions/upload-artifact@v3 with: name: Neuron-Mac @@ -113,7 +113,7 @@ jobs: path: release/Neuron-*-mac-arm64.zip - name: Upload Neuron Dmg - if: matrix.os == 'macos-11' + if: matrix.os == 'macos-latest' uses: actions/upload-artifact@v3 with: name: Neuron-Dmg diff --git a/.github/workflows/package_for_test.yml b/.github/workflows/package_for_test.yml index 3a9c7fa94a..4bd4850407 100644 --- a/.github/workflows/package_for_test.yml +++ b/.github/workflows/package_for_test.yml @@ -9,7 +9,7 @@ jobs: node: - 18.12.0 os: - - macos-11 + - macos-latest - ubuntu-20.04 - windows-2019 @@ -62,7 +62,7 @@ jobs: CI: false - name: Package for MacOS - if: matrix.os == 'macos-11' + if: matrix.os == 'macos-latest' run: | ./scripts/download-ckb.sh mac yarn package:test mac @@ -94,28 +94,28 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Upload Neuron App Zip - if: matrix.os == 'macos-11' + if: matrix.os == 'macos-latest' uses: actions/upload-artifact@v3 with: name: Neuron-Mac-x64 path: release/Neuron-*-mac-x64.zip - name: Upload Neuron App Zip(arm64) - if: matrix.os == 'macos-11' + if: matrix.os == 'macos-latest' uses: actions/upload-artifact@v3 with: name: Neuron-Mac-arm64 path: release/Neuron-*-mac-arm64.zip - name: Upload Neuron Dmg - if: matrix.os == 'macos-11' + if: matrix.os == 'macos-latest' uses: actions/upload-artifact@v3 with: name: Neuron-Dmg-x64 path: release/Neuron-*-x64.dmg - name: Upload Neuron Dmg(arm64) - if: matrix.os == 'macos-11' + if: matrix.os == 'macos-latest' uses: actions/upload-artifact@v3 with: name: Neuron-Dmg-arm64 From e0a2fdc3d926b86f16e41142d123899ba4110372 Mon Sep 17 00:00:00 2001 From: WhiteMind Date: Sat, 6 May 2023 13:46:54 +0800 Subject: [PATCH 39/52] fix: applyLocalhostIPv4Resolve caused additional impact --- packages/neuron-wallet/src/services/networks.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/neuron-wallet/src/services/networks.ts b/packages/neuron-wallet/src/services/networks.ts index cb5071b8dd..0400f70402 100644 --- a/packages/neuron-wallet/src/services/networks.ts +++ b/packages/neuron-wallet/src/services/networks.ts @@ -195,5 +195,8 @@ function applyLocalhostIPv4Resolve(url: string): string { if (urlObj.hostname !== 'localhost') return url urlObj.hostname = '127.0.0.1' - return urlObj.href + // When the pathname is empty, the URL constructor automatically sets the pathname + // to '/' and this needs to be handled. + const hasExtraPathSeparator = urlObj.pathname === '/' && !url.endsWith('/') + return hasExtraPathSeparator ? urlObj.href.slice(0, -1) : urlObj.href } From 70c604b8aae6731129ae73c869ffea7f55331421 Mon Sep 17 00:00:00 2001 From: WhiteMind Date: Sat, 6 May 2023 17:25:42 +0800 Subject: [PATCH 40/52] feat: provide loading for the detail button on the history page --- .../src/components/TransactionList/index.tsx | 7 +++++-- .../transactionList.module.scss | 4 ++++ packages/neuron-ui/src/locales/en.json | 1 + packages/neuron-ui/src/locales/zh-tw.json | 1 + packages/neuron-ui/src/locales/zh.json | 1 + packages/neuron-wallet/src/controllers/api.ts | 20 +++++++++++++++++-- .../src/controllers/app/show-window.ts | 5 +++-- 7 files changed, 33 insertions(+), 6 deletions(-) diff --git a/packages/neuron-ui/src/components/TransactionList/index.tsx b/packages/neuron-ui/src/components/TransactionList/index.tsx index 6099fe9182..090aefd7ec 100644 --- a/packages/neuron-ui/src/components/TransactionList/index.tsx +++ b/packages/neuron-ui/src/components/TransactionList/index.tsx @@ -48,6 +48,7 @@ const TransactionList = ({ dispatch, }: TransactionListProps) => { const [txHash, setTxHash] = useState('') + const [isDetailOpening, setIsDetailOpening] = useState(false) const [t] = useTranslation() const { @@ -115,7 +116,8 @@ const TransactionList = ({ break } case 'detail': { - showTransactionDetails(btn.dataset.hash) + setIsDetailOpening(true) + showTransactionDetails(btn.dataset.hash).finally(() => setIsDetailOpening(false)) break } default: { @@ -279,9 +281,10 @@ const TransactionList = ({ onClick={onActionBtnClick} data-hash={tx.hash} data-action="detail" + disabled={isDetailOpening} > - {t('history.view-detail')} + {isDetailOpening ? t('history.opening') : t('history.view-detail')}
diff --git a/packages/neuron-ui/src/utils/hooks/useGetCountDownAndFeeRateStats.ts b/packages/neuron-ui/src/utils/hooks/useGetCountDownAndFeeRateStats.ts index 43d6b15f0f..a1a97221fa 100644 --- a/packages/neuron-ui/src/utils/hooks/useGetCountDownAndFeeRateStats.ts +++ b/packages/neuron-ui/src/utils/hooks/useGetCountDownAndFeeRateStats.ts @@ -21,20 +21,24 @@ const useGetCountDownAndFeeRateStats = ({ seconds = 30, interval = 1000 }: Count (stateDispatch: StateDispatch) => { getFeeRateStats() .then(res => { - const { mean, median } = res + const { mean, median } = res ?? {} const suggested = mean && median ? Math.max(1000, Number(mean), Number(median)) : MEDIUM_FEE_RATE setFeeFatestatsData(states => ({ ...states, ...res, suggestFeeRate: suggested })) }) - .catch((err: Error) => { - stateDispatch({ - type: AppActions.AddNotification, - payload: { - type: 'alert', - timestamp: +new Date(), - content: err.message, - }, - }) + .catch((err: Error & { response?: { status: number } }) => { + if (err?.response?.status === 404) { + setFeeFatestatsData(states => ({ ...states, suggestFeeRate: MEDIUM_FEE_RATE })) + } else { + stateDispatch({ + type: AppActions.AddNotification, + payload: { + type: 'alert', + timestamp: +new Date(), + content: err.message, + }, + }) + } }) }, [getFeeRateStats, setFeeFatestatsData] From 03678574eb17629626bc6470c93cf5f0758a9755 Mon Sep 17 00:00:00 2001 From: WhiteMind Date: Tue, 16 May 2023 15:54:58 +0800 Subject: [PATCH 45/52] Fix the current problematic ESLint and Prettier workflow (#2662) --- .husky/pre-commit | 4 + .prettierignore | 2 + .vscode/extensions.json | 3 + .vscode/settings.json | 1 + package.json | 11 +- packages/neuron-ui/.eslintrc.js | 167 +++---- packages/neuron-ui/.prettierrc | 5 - packages/neuron-ui/.prettierrc.js | 11 + packages/neuron-ui/config-overrides.js | 1 + packages/neuron-ui/package.json | 4 - .../neuron-ui/src/components/History/hooks.ts | 2 +- .../src/components/NervosDAO/hooks.ts | 150 +++---- .../src/components/NervosDAORecord/index.tsx | 4 +- .../neuron-ui/src/components/Send/hooks.ts | 189 ++++---- .../SendFromMultisigDialog/hooks.ts | 102 ++--- .../src/components/WalletEditor/hooks.ts | 6 +- packages/neuron-ui/src/services/remote/app.ts | 2 +- .../neuron-ui/src/services/remote/index.ts | 1 + .../neuron-ui/src/services/remote/multisig.ts | 14 +- .../src/services/remote/remoteApiWrapper.ts | 46 +- .../neuron-ui/src/services/remote/sudt.ts | 5 +- .../neuron-ui/src/services/remote/wallets.ts | 10 +- packages/neuron-ui/src/services/subjects.ts | 2 +- .../stateProvider/actionCreators/app.ts | 31 +- .../stateProvider/actionCreators/sudt.ts | 6 +- .../actionCreators/transactions.ts | 43 +- .../stateProvider/actionCreators/wallets.ts | 70 ++- .../src/states/stateProvider/provider.tsx | 6 +- .../calculation/calculateAPC/index.test.ts | 6 +- .../src/tests/getPageNoList/index.test.ts | 6 +- .../src/tests/getSyncLeftTime/index.test.ts | 6 +- .../src/tests/is/isMainnet/index.test.ts | 6 +- .../tests/is/isReadyByVersion/index.test.ts | 6 +- .../tests/is/isSuccessResponse/index.test.ts | 6 +- .../src/tests/sortAccounts/index.test.ts | 6 +- .../tests/validators/address/index.test.ts | 6 +- .../src/tests/validators/amount/index.test.ts | 6 +- .../validators/amountRange/index.test.ts | 6 +- .../assetAccountAddress/index.test.ts | 6 +- .../validators/assetAccountName/index.test.ts | 6 +- .../tests/validators/decimal/index.test.ts | 6 +- .../validators/networkName/index.test.ts | 6 +- .../tests/validators/outputs/index.test.ts | 6 +- .../passwordComplexity/index.test.ts | 6 +- .../tests/validators/sudtAmount/index.test.ts | 6 +- .../src/tests/validators/symbol/index.test.ts | 6 +- .../tests/validators/tokenId/index.test.ts | 6 +- .../tests/validators/tokenName/index.test.ts | 6 +- .../validators/totalAmount/index.test.ts | 6 +- .../src/tests/validators/url/index.test.ts | 6 +- packages/neuron-ui/src/types/App/index.d.ts | 2 +- .../neuron-ui/src/types/global/index.d.ts | 8 +- packages/neuron-ui/src/utils/formatters.ts | 2 +- .../neuron-ui/src/utils/generateWalletName.ts | 2 +- packages/neuron-ui/src/utils/hooks/index.ts | 4 +- .../src/widgets/DatetimePicker/index.tsx | 2 +- .../src/widgets/Pagination/index.tsx | 4 +- .../neuron-ui/src/widgets/QRCode/index.tsx | 2 + .../neuron-ui/src/widgets/TextField/index.tsx | 2 +- packages/neuron-wallet/.eslintrc.js | 124 ++---- packages/neuron-wallet/.prettierrc | 5 - packages/neuron-wallet/.prettierrc.js | 11 + packages/neuron-wallet/package.json | 5 - .../src/block-sync-renderer/index.ts | 12 +- .../sync/indexer-cache-service.ts | 46 +- .../sync/indexer-connector.ts | 29 +- .../src/block-sync-renderer/sync/queue.ts | 31 +- .../sync/tx-address-finder.ts | 16 +- .../src/block-sync-renderer/task-wrapper.ts | 6 +- .../src/block-sync-renderer/task.ts | 41 +- .../block-sync-renderer/tx-status-listener.ts | 8 +- .../src/controllers/anyone-can-pay.ts | 10 +- packages/neuron-wallet/src/controllers/api.ts | 305 ++++++++----- .../src/controllers/app/index.ts | 4 +- .../neuron-wallet/src/controllers/app/menu.ts | 130 +++--- .../src/controllers/app/preload.ts | 6 +- .../src/controllers/app/show-window.ts | 6 +- .../src/controllers/app/subscribe.ts | 4 +- .../src/controllers/asset-account.ts | 48 +- .../src/controllers/customized-assets.ts | 6 +- packages/neuron-wallet/src/controllers/dao.ts | 10 +- .../src/controllers/export-debug.ts | 47 +- .../neuron-wallet/src/controllers/hardware.ts | 12 +- .../neuron-wallet/src/controllers/mercury.ts | 2 +- .../neuron-wallet/src/controllers/multisig.ts | 134 +++--- .../src/controllers/networks/index.ts | 20 +- .../src/controllers/offline-sign.ts | 30 +- .../src/controllers/sign-message.ts | 4 +- .../neuron-wallet/src/controllers/sudt.ts | 10 +- .../neuron-wallet/src/controllers/sync-api.ts | 42 +- .../src/controllers/transactions.ts | 16 +- .../neuron-wallet/src/controllers/update.ts | 6 +- .../neuron-wallet/src/controllers/wallets.ts | 100 ++--- .../src/database/address/AddressVersion.ts | 2 +- .../chain/entities/address-description.ts | 6 +- .../database/chain/entities/asset-account.ts | 14 +- .../chain/entities/hd-public-key-info.ts | 6 +- .../chain/entities/indexer-tx-hash-cache.ts | 16 +- .../src/database/chain/entities/input.ts | 38 +- .../chain/entities/multisig-output.ts | 20 +- .../src/database/chain/entities/output.ts | 44 +- .../chain/entities/sudt-token-info.ts | 15 +- .../src/database/chain/entities/sync-info.ts | 4 +- .../database/chain/entities/transaction.ts | 40 +- .../database/chain/entities/tx-description.ts | 6 +- .../neuron-wallet/src/database/chain/index.ts | 10 +- .../src/database/chain/ormconfig.ts | 6 +- packages/neuron-wallet/src/env.ts | 4 +- .../neuron-wallet/src/exceptions/address.ts | 4 +- .../src/exceptions/anyone-can-pay.ts | 2 +- .../neuron-wallet/src/exceptions/common.ts | 2 +- packages/neuron-wallet/src/exceptions/file.ts | 2 +- .../neuron-wallet/src/exceptions/helper.ts | 2 +- packages/neuron-wallet/src/exceptions/key.ts | 2 +- .../neuron-wallet/src/exceptions/network.ts | 2 +- .../src/exceptions/transaction.ts | 2 +- .../neuron-wallet/src/exceptions/wallet.ts | 2 +- packages/neuron-wallet/src/locales/en.ts | 100 ++--- packages/neuron-wallet/src/locales/i18n.ts | 8 +- packages/neuron-wallet/src/locales/zh-tw.ts | 100 ++--- packages/neuron-wallet/src/locales/zh.ts | 100 ++--- packages/neuron-wallet/src/models/address.ts | 2 +- .../src/models/asset-account-info.ts | 38 +- .../src/models/chain/cell-dep.ts | 4 +- .../neuron-wallet/src/models/chain/input.ts | 4 +- .../src/models/chain/live-cell.ts | 2 +- .../src/models/chain/out-point.ts | 2 +- .../neuron-wallet/src/models/chain/output.ts | 6 +- .../neuron-wallet/src/models/chain/script.ts | 6 +- .../src/models/chain/transaction.ts | 12 +- .../src/models/chain/tx-status.ts | 4 +- .../src/models/chain/witness-args.ts | 6 +- .../neuron-wallet/src/models/keys/address.ts | 2 +- .../src/models/keys/hd-public-key-info.ts | 2 +- packages/neuron-wallet/src/models/keys/key.ts | 2 +- .../neuron-wallet/src/models/keys/keychain.ts | 31 +- .../neuron-wallet/src/models/keys/keystore.ts | 16 +- .../src/models/keys/mnemonic/index.ts | 7 +- .../src/models/keys/mnemonic/word-list.ts | 2 +- .../src/models/multisig-config.ts | 2 +- packages/neuron-wallet/src/models/multisig.ts | 2 +- packages/neuron-wallet/src/models/network.ts | 2 +- .../neuron-wallet/src/models/offline-sign.ts | 8 +- .../src/models/subjects/networks.ts | 4 +- .../neuron-wallet/src/models/subjects/node.ts | 2 +- .../src/models/subjects/sync-state-subject.ts | 2 +- .../src/models/subjects/wallets.ts | 2 +- .../src/models/synced-block-number.ts | 7 +- .../src/models/transaction-size.ts | 6 +- .../neuron-wallet/src/services/addresses.ts | 34 +- .../src/services/anyone-can-pay.ts | 12 +- .../src/services/asset-account-service.ts | 20 +- packages/neuron-wallet/src/services/cells.ts | 107 +++-- packages/neuron-wallet/src/services/file.ts | 2 +- .../src/services/hardware/common.ts | 2 +- .../src/services/hardware/hardware.ts | 51 ++- .../src/services/hardware/index.ts | 2 +- .../src/services/hardware/ledger.ts | 73 +-- .../neuron-wallet/src/services/multisig.ts | 55 +-- .../neuron-wallet/src/services/networks.ts | 12 +- packages/neuron-wallet/src/services/node.ts | 17 +- .../src/services/offline-sign.ts | 19 +- .../neuron-wallet/src/services/sdk-core.ts | 2 +- .../neuron-wallet/src/services/settings.ts | 20 +- .../src/services/sign-message.ts | 2 +- .../src/services/transaction-sender.ts | 35 +- .../src/services/tx/failed-transaction.ts | 6 +- .../services/tx/transaction-description.ts | 6 +- .../src/services/tx/transaction-generator.ts | 96 ++-- .../src/services/tx/transaction-persistor.ts | 24 +- .../src/services/tx/transaction-service.ts | 44 +- .../neuron-wallet/src/services/wallets.ts | 10 +- .../neuron-wallet/src/types/controller.d.ts | 2 +- packages/neuron-wallet/src/utils/common.ts | 2 +- packages/neuron-wallet/src/utils/const.ts | 4 +- .../neuron-wallet/src/utils/export-history.ts | 4 +- packages/neuron-wallet/src/utils/multisig.ts | 2 +- .../src/utils/parse_sudt_token_info.ts | 4 +- packages/neuron-wallet/src/utils/queue.ts | 2 +- .../neuron-wallet/src/utils/rpc-request.ts | 14 +- .../neuron-wallet/src/utils/to-csv-row.ts | 2 +- .../neuron-wallet/src/utils/validators.ts | 6 +- .../index/createBlockSyncTask.test.ts | 15 +- .../index/hasSideEffect.test.ts | 8 +- .../index/killBlockSyncTask.test.ts | 10 +- .../index/queryIndexer.test.ts | 24 +- .../index/resetSyncTask.test.ts | 8 +- .../index/switchNetwork.test.ts | 4 +- .../indexer-cache-service.intg.test.ts | 420 +++++++++--------- .../indexer-connector.test.ts | 92 ++-- .../tests/block-sync-renderer/queue.test.ts | 39 +- .../tests/block-sync-renderer/task.test.ts | 18 +- .../tx-status-listener.intg.test.ts | 66 ++- .../tests/controllers/anyone-can-pay.test.ts | 34 +- .../tests/controllers/asset-account.test.ts | 95 ++-- .../tests/controllers/export-debug.test.ts | 32 +- .../tests/controllers/hardware.test.ts | 38 +- .../tests/controllers/multisig.test.ts | 277 ++++++------ .../tests/controllers/offline-sign.test.ts | 241 +++++----- .../tests/controllers/sudt.test.ts | 26 +- .../tests/controllers/sync-api.test.ts | 98 ++-- .../tests/database/address/meta.test.ts | 13 +- packages/neuron-wallet/tests/mock/electron.ts | 4 +- packages/neuron-wallet/tests/mock/hardware.ts | 40 +- packages/neuron-wallet/tests/mock/logger.ts | 7 +- .../tests/models/address-parser.test.ts | 19 +- .../tests/models/asset-account-info.test.ts | 90 ++-- .../tests/models/chain/block-header.test.ts | 29 +- .../tests/models/chain/live-cell.test.ts | 15 +- .../tests/models/chain/out-point.test.ts | 2 +- .../tests/models/chain/output.test.ts | 6 +- .../tests/models/chain/script.test.ts | 4 +- .../tests/models/chain/transaction.test.ts | 99 ++--- .../tests/models/chain/witness-args.test.ts | 4 +- .../tests/models/keys/address.test.ts | 12 +- .../models/keys/hd-public-key-info.test.ts | 40 +- .../tests/models/keys/keychain.test.ts | 31 +- .../tests/models/keys/keystore.test.ts | 20 +- .../tests/models/migrate-subject.test.ts | 14 +- .../tests/models/multi-sign.test.ts | 8 +- .../tests/models/offline-sign.test.ts | 8 +- .../models/synced-block-number.intg.test.ts | 37 +- .../tests/models/system-script-info.test.ts | 15 +- .../tests/models/transaction-fee.test.ts | 8 +- .../tests/models/transaction-size.test.ts | 114 ++--- .../tests/services/address.test.ts | 24 +- .../tests/services/anyone-can-pay.test.ts | 195 ++++++-- .../services/asset-account-service.test.ts | 194 ++++---- .../tests/services/cells.test.ts | 393 +++++++++------- .../tests/services/ckb-runner.test.ts | 37 +- .../tests/services/hardware.test.ts | 2 +- .../tests/services/indexer.test.ts | 18 +- .../tests/services/monitor.test.ts | 12 +- .../tests/services/multisig.test.ts | 129 +++--- .../tests/services/networks.test.ts | 19 +- .../neuron-wallet/tests/services/node.test.ts | 166 +++---- .../tests/services/offline-sign.test.ts | 17 +- .../tests/services/setting.test.ts | 16 +- .../tests/services/sign-message.test.ts | 31 +- .../tests/services/transactions.test.ts | 22 +- .../tests/services/tx-wallet.test.ts | 12 +- .../services/tx/transaction-generator.test.ts | 270 +++++------ .../services/tx/transaction-persistor.test.ts | 20 +- .../services/tx/transaction-sender.test.ts | 257 ++++++----- .../services/tx/transaction-service.test.ts | 26 +- .../tx/transaction.description.intg.test.ts | 43 +- .../tests/services/wallets.test.ts | 100 ++--- packages/neuron-wallet/tests/setup.ts | 4 +- .../setupAndTeardown/accounts.fixture.ts | 4 +- .../tests/setupAndTeardown/index.ts | 8 +- .../tests/setupAndTeardown/keys.ts | 2 +- .../public-key-info.fixture.ts | 22 +- .../setupAndTeardown/transactions.fixture.ts | 106 ++--- .../neuron-wallet/tests/utils/array.test.ts | 5 +- .../neuron-wallet/tests/utils/buffer.test.ts | 20 +- .../tests/utils/export-history/index.test.ts | 2 +- .../tests/utils/multisig.test.ts | 41 +- .../utils/parse_sudt_token_info/index.test.ts | 8 +- .../neuron-wallet/tests/utils/queue.test.ts | 6 +- .../tests/utils/redist-check/index.test.ts | 18 +- .../tests/utils/rpc-request.test.ts | 39 +- .../tests/utils/shannonToCKB.test.ts | 15 +- yarn.lock | 19 - 263 files changed, 4177 insertions(+), 4110 deletions(-) create mode 100755 .husky/pre-commit create mode 100644 .prettierignore create mode 100644 .vscode/extensions.json delete mode 100644 packages/neuron-ui/.prettierrc create mode 100644 packages/neuron-ui/.prettierrc.js delete mode 100644 packages/neuron-wallet/.prettierrc create mode 100644 packages/neuron-wallet/.prettierrc.js diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000000..14ce4f87fc --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +lerna run --no-bail --stream precommit diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000000..8b167d9296 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,2 @@ +# These files are generated by tools and may be edited again by the tools, so we are temporarily not formatting them. +**/packages/neuron-wallet/src/database/chain/migrations/**/*.ts diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000000..1d7ac851ea --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"] +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 9ce0d17b29..ae55f121aa 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,5 @@ { + "editor.rulers": [120], "eslint.workingDirectories": [ { "directory": "packages/neuron-wallet", diff --git a/package.json b/package.json index 6ace9f1558..06a7830d4a 100644 --- a/package.json +++ b/package.json @@ -35,14 +35,9 @@ "test": "cross-env NODE_OPTIONS=--openssl-legacy-provider lerna run --parallel test", "test:ci": "yarn build:main && yarn test", "lint": "lerna run --stream lint", - "postinstall": "lerna run build --scope=@nervina-labs/ckb-indexer", + "postinstall": "husky install && lerna run build --scope=@nervina-labs/ckb-indexer", "db:chain": "node ./node_modules/.bin/typeorm" }, - "husky": { - "hooks": { - "pre-commit": "lerna run --no-bail --stream precommit" - } - }, "devDependencies": { "@babel/core": "7.21.4", "@types/jest": "27.5.2", @@ -52,9 +47,13 @@ "@typescript-eslint/parser": "5.58.0", "concurrently": "8.0.1", "cross-env": "7.0.3", + "eslint": "8.38.0", + "eslint-config-prettier": "8.8.0", "husky": "8.0.3", "lerna": "5.6.2", + "lint-staged": "13.2.1", "ncp": "2.0.0", + "prettier": "2.8.7", "ts-jest": "27.1.5", "typescript": "5.0.4", "wait-on": "6.0.1" diff --git a/packages/neuron-ui/.eslintrc.js b/packages/neuron-ui/.eslintrc.js index e82516a083..318286afee 100644 --- a/packages/neuron-ui/.eslintrc.js +++ b/packages/neuron-ui/.eslintrc.js @@ -1,8 +1,8 @@ module.exports = { - extends: ['airbnb', 'plugin:prettier/recommended'], - parser: '@typescript-eslint/parser', - plugins: ['@typescript-eslint'], + extends: ['airbnb', 'plugin:@typescript-eslint/recommended', 'prettier'], settings: { + // https://github.com/SimulatedGREG/electron-vue/issues/423#issuecomment-464807973 + 'import/core-modules': ['electron'], 'import/resolver': { node: { paths: ['src'], @@ -13,92 +13,61 @@ module.exports = { version: 'detect', }, }, + env: { + jest: true, + node: true, + browser: true, + }, + globals: { + BigInt: 'readonly', + }, rules: { - 'prettier/prettier': [ - 2, - { - printWidth: 120, - endOfLine: 'auto', - }, - ], - semi: [2, 'never'], - curly: [2, 'all'], - 'comma-dangle': [ - 2, - { - arrays: 'always-multiline', - objects: 'always-multiline', - imports: 'always-multiline', - exports: 'always-multiline', - functions: 'ignore', - }, - ], - 'import/no-extraneous-dependencies': [ - 2, - { - devDependencies: true, - }, - ], - 'no-unused-vars': 'off', - 'implicit-arrow-linebreak': 'off', + // TODO: Some temporarily disabled rules will be re-enabled later, considering that many files are affected and will be addressed in the future. + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-non-null-assertion': 'off', + + // This is the configuration that was set when using eslint-plugin-prettier + // https://github.com/prettier/eslint-plugin-prettier#arrow-body-style-and-prefer-arrow-callback-issue + 'arrow-body-style': 'off', + 'prefer-arrow-callback': 'off', + + // https://github.com/jsx-eslint/eslint-plugin-react/issues/498 + 'react/prop-types': 'off', + + // TypeScript support '@typescript-eslint/no-unused-vars': [ 'error', { - vars: 'local', - args: 'after-used', - ignoreRestSiblings: false, + argsIgnorePattern: '^_', }, ], - 'arrow-parens': [2, 'as-needed'], - 'max-len': [ - 2, - { - code: 120, - ignoreComments: true, - ignoreTrailingComments: true, - ignoreUrls: true, - ignoreStrings: true, - ignoreTemplateLiterals: true, - ignoreRegExpLiterals: true, - }, - ], - 'object-curly-newline': [ + // Avoid duplicating @typescript-eslint/no-shadow + 'no-shadow': 'off', + '@typescript-eslint/no-shadow': 'error', + + // Unnecessary rules + 'no-plusplus': 'off', + 'max-classes-per-file': 'off', + '@typescript-eslint/no-inferrable-types': 'off', + '@typescript-eslint/no-empty-function': 'off', + '@typescript-eslint/ban-ts-comment': 'warn', + 'react/require-default-props': 'off', + 'react/jsx-props-no-spreading': 'off', + + // Adjusted rules + 'no-console': [ 'error', { - ObjectExpression: { - consistent: true, - }, - ObjectPattern: { - consistent: true, - }, - ImportDeclaration: { - consistent: true, - }, - ExportDeclaration: { - multiline: true, - minProperties: 3, - }, + allow: ['info', 'warn', 'error', 'group', 'groupEnd'], }, ], - 'no-plusplus': [0], 'lines-between-class-members': ['error', 'always', { exceptAfterSingleLine: true }], - 'max-classes-per-file': [0], - 'react/jsx-filename-extension': [ - 1, - { - extensions: ['.ts', '.tsx'], - }, - ], - 'react/jsx-props-no-spreading': [0], - 'typescript-eslint/no-angle-bracket-type-assertion': [0], - 'no-alert': [0], - 'no-console': [ - 2, + 'import/no-extraneous-dependencies': [ + 'error', { - allow: ['info', 'warn', 'error', 'group', 'groupEnd'], + devDependencies: ['**/*.stories.*', 'src/setupTests.ts'], }, ], - 'no-bitwise': [0], 'import/extensions': [ 'error', 'ignorePackages', @@ -107,53 +76,25 @@ module.exports = { tsx: 'never', }, ], - 'no-shadow': 'off', - '@typescript-eslint/no-shadow': ['error'], - '@typescript-eslint/no-var-requires': 'off', - 'react/prop-types': 'off', + 'react/no-unstable-nested-components': ['error', { allowAsProps: true }], + 'react/jsx-filename-extension': [ + 'warn', + { + extensions: ['.jsx', '.tsx'], + }, + ], 'react/function-component-definition': [ - 2, + 'error', { namedComponents: 'arrow-function', unnamedComponents: 'arrow-function', }, ], - 'react/require-default-props': 'off', - '@typescript-eslint/ban-types': [ + 'react/jsx-no-useless-fragment': [ 'error', { - extendDefaults: true, - types: { - '{}': false, - Function: false, - }, + allowExpressions: true, }, ], - 'no-unsafe-optional-chaining': ['warn', { disallowArithmeticOperators: false }], - 'react/no-unstable-nested-components': ['warn', { allowAsProps: true }], - 'default-param-last': 'off', - 'react/jsx-no-useless-fragment': 'off', - }, - overrides: [ - { - files: ['*.ts', '*.tsx'], - rules: { - 'no-undef': 'off', - }, - }, - { - files: ['*.ts', '*.tsx'], - rules: { - 'react/jsx-no-constructed-context-values': 0, - }, - }, - ], - env: { - jest: true, - node: true, - browser: true, - }, - globals: { - BigInt: 'readonly', }, } diff --git a/packages/neuron-ui/.prettierrc b/packages/neuron-ui/.prettierrc deleted file mode 100644 index 5149b1b773..0000000000 --- a/packages/neuron-ui/.prettierrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "trailingComma": "es5", - "semi": false, - "singleQuote": true -} diff --git a/packages/neuron-ui/.prettierrc.js b/packages/neuron-ui/.prettierrc.js new file mode 100644 index 0000000000..4cba56a93f --- /dev/null +++ b/packages/neuron-ui/.prettierrc.js @@ -0,0 +1,11 @@ +module.exports = { + tabWidth: 2, + useTabs: false, + printWidth: 120, + trailingComma: 'es5', + semi: false, + singleQuote: true, + // TODO: This is the previous legacy configuration, should use the default settings, considering that more files are affected, and will be dealt with later. + // https://prettier.io/blog/2020/03/21/2.0.0.html#change-default-value-for-arrowparens-to-always-7430httpsgithubcomprettierprettierpull7430-by-kachkaevhttpsgithubcomkachkaev + arrowParens: 'avoid', +} diff --git a/packages/neuron-ui/config-overrides.js b/packages/neuron-ui/config-overrides.js index 0fdac05ff9..aa4d60f53b 100644 --- a/packages/neuron-ui/config-overrides.js +++ b/packages/neuron-ui/config-overrides.js @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ const path = require('path') module.exports = function override(config) { diff --git a/packages/neuron-ui/package.json b/packages/neuron-ui/package.json index 57f0d62686..5cca4a9e76 100644 --- a/packages/neuron-ui/package.json +++ b/packages/neuron-ui/package.json @@ -81,14 +81,10 @@ "enzyme": "3.11.0", "enzyme-adapter-react-16": "1.15.7", "eslint-config-airbnb": "19.0.4", - "eslint-config-prettier": "8.8.0", "eslint-plugin-import": "2.27.5", "eslint-plugin-jsx-a11y": "6.7.1", - "eslint-plugin-prettier": "4.2.1", "eslint-plugin-react": "7.32.2", "jest-styled-components": "7.1.1", - "lint-staged": "13.2.1", - "prettier": "2.8.7", "react-app-rewired": "2.2.1", "react-scripts": "5.0.1", "react-test-renderer": "16.14.0", diff --git a/packages/neuron-ui/src/components/History/hooks.ts b/packages/neuron-ui/src/components/History/hooks.ts index a30448be71..94ba80e0e7 100644 --- a/packages/neuron-ui/src/components/History/hooks.ts +++ b/packages/neuron-ui/src/components/History/hooks.ts @@ -2,7 +2,7 @@ import { useState, useEffect } from 'react' import { updateTransactionList } from 'states/stateProvider/actionCreators/transactions' import { listParams, backToTop } from 'utils' -export const useSearch = (search: string = '', walletID: string = '', dispatch: React.Dispatch) => { +export const useSearch = (search: string, walletID: string, dispatch: React.Dispatch) => { const [keywords, setKeywords] = useState('') const onKeywordsChange = (_e?: React.FormEvent, newValue?: string) => { diff --git a/packages/neuron-ui/src/components/NervosDAO/hooks.ts b/packages/neuron-ui/src/components/NervosDAO/hooks.ts index cd65926072..23a32d989d 100644 --- a/packages/neuron-ui/src/components/NervosDAO/hooks.ts +++ b/packages/neuron-ui/src/components/NervosDAO/hooks.ts @@ -24,14 +24,8 @@ import { ckbCore, getHeaderByNumber } from 'services/chain' import { isErrorWithI18n } from 'exceptions' import { calculateMaximumWithdraw } from '@nervosnetwork/ckb-sdk-utils' -const { - MIN_AMOUNT, - MILLISECONDS_IN_YEAR, - MIN_DEPOSIT_AMOUNT, - MEDIUM_FEE_RATE, - SHANNON_CKB_RATIO, - MAX_DECIMAL_DIGITS, -} = CONSTANTS +const { MIN_AMOUNT, MILLISECONDS_IN_YEAR, MIN_DEPOSIT_AMOUNT, MEDIUM_FEE_RATE, SHANNON_CKB_RATIO, MAX_DECIMAL_DIGITS } = + CONSTANTS const getRecordKey = ({ depositOutPoint, outPoint }: State.NervosDAORecord) => { return depositOutPoint ? `${depositOutPoint.txHash}-${depositOutPoint.index}` : `${outPoint.txHash}-${outPoint.index}` @@ -127,7 +121,6 @@ export const useClearGeneratedTx = (dispatch: React.Dispatch) => }) }, [dispatch]) - export const useGenerateDaoDepositTx = ({ setErrorMessage, clearGeneratedTx, @@ -154,76 +147,77 @@ export const useGenerateDaoDepositTx = ({ suggestFeeRate: string | number }) => { const timer = useRef>() - useEffect( - () => { - clearTimeout(timer.current) - timer.current = setTimeout(() => { - setErrorMessage('') - clearGeneratedTx() - - try { - validateAmount(depositValue) - } catch (err) { - if (isErrorWithI18n(err)) { - setErrorMessage( - t(`messages.codes.${err.code}`, { fieldName: 'deposit', fieldValue: depositValue, length: MAX_DECIMAL_DIGITS }) - ) - } - return - } - - if (BigInt(CKBToShannonFormatter(depositValue)) < BigInt(MIN_DEPOSIT_AMOUNT * SHANNON_CKB_RATIO)) { - setErrorMessage(t('nervos-dao.minimal-fee-required', { minimal: MIN_DEPOSIT_AMOUNT })) - return + useEffect(() => { + clearTimeout(timer.current) + timer.current = setTimeout(() => { + setErrorMessage('') + clearGeneratedTx() + + try { + validateAmount(depositValue) + } catch (err) { + if (isErrorWithI18n(err)) { + setErrorMessage( + t(`messages.codes.${err.code}`, { + fieldName: 'deposit', + fieldValue: depositValue, + length: MAX_DECIMAL_DIGITS, + }) + ) } - - const capacity = CKBToShannonFormatter(depositValue, CapacityUnit.CKB) - if (BigInt(capacity) < maxDepositAmount) { - generateDaoDepositTx({ - feeRate: `${suggestFeeRate}`, - capacity, - walletID, - }).then(res => { - if (isSuccessResponse(res)) { - dispatch({ - type: AppActions.UpdateGeneratedTx, - payload: res.result, - }) - } else if (res.status === 0) { - setErrorMessage(`${typeof res.message === 'string' ? res.message : res.message.content}`) - } else if (res.status === ErrorCode.CapacityNotEnoughForChange) { - setErrorMessage(t(`messages.codes.106`)) - } else { - setErrorMessage(t(`messages.codes.${res.status}`)) - } - }) - } else if (BigInt(capacity) === maxDepositAmount) { - dispatch({ - type: AppActions.UpdateGeneratedTx, - payload: maxDepositTx, - }) - if (!isBalanceReserved) { - setErrorMessage(maxDepositErrorMessage || t('messages.remain-ckb-for-withdraw')) + return + } + + if (BigInt(CKBToShannonFormatter(depositValue)) < BigInt(MIN_DEPOSIT_AMOUNT * SHANNON_CKB_RATIO)) { + setErrorMessage(t('nervos-dao.minimal-fee-required', { minimal: MIN_DEPOSIT_AMOUNT })) + return + } + + const capacity = CKBToShannonFormatter(depositValue, CapacityUnit.CKB) + if (BigInt(capacity) < maxDepositAmount) { + generateDaoDepositTx({ + feeRate: `${suggestFeeRate}`, + capacity, + walletID, + }).then(res => { + if (isSuccessResponse(res)) { + dispatch({ + type: AppActions.UpdateGeneratedTx, + payload: res.result, + }) + } else if (res.status === 0) { + setErrorMessage(`${typeof res.message === 'string' ? res.message : res.message.content}`) + } else if (res.status === ErrorCode.CapacityNotEnoughForChange) { + setErrorMessage(t(`messages.codes.106`)) + } else { + setErrorMessage(t(`messages.codes.${res.status}`)) } - } else { - setErrorMessage(t(`messages.codes.${ErrorCode.AmountNotEnough}`)) + }) + } else if (BigInt(capacity) === maxDepositAmount) { + dispatch({ + type: AppActions.UpdateGeneratedTx, + payload: maxDepositTx, + }) + if (!isBalanceReserved) { + setErrorMessage(maxDepositErrorMessage || t('messages.remain-ckb-for-withdraw')) } - }) - }, - [ - clearGeneratedTx, - maxDepositAmount, - maxDepositTx, - dispatch, - walletID, - maxDepositErrorMessage, - t, - setErrorMessage, - isBalanceReserved, - depositValue, - suggestFeeRate, - ] - ) + } else { + setErrorMessage(t(`messages.codes.${ErrorCode.AmountNotEnough}`)) + } + }) + }, [ + clearGeneratedTx, + maxDepositAmount, + maxDepositTx, + dispatch, + walletID, + maxDepositErrorMessage, + t, + setErrorMessage, + isBalanceReserved, + depositValue, + suggestFeeRate, + ]) } export const useUpdateDepositValue = ({ @@ -239,9 +233,7 @@ export const useUpdateDepositValue = ({ } setDepositValue(amount) }, - [ - setDepositValue, - ] + [setDepositValue] ) export const useOnDepositValueChange = ({ updateDepositValue }: { updateDepositValue: (value: string) => void }) => diff --git a/packages/neuron-ui/src/components/NervosDAORecord/index.tsx b/packages/neuron-ui/src/components/NervosDAORecord/index.tsx index ed41668389..10e77c709a 100644 --- a/packages/neuron-ui/src/components/NervosDAORecord/index.tsx +++ b/packages/neuron-ui/src/components/NervosDAORecord/index.tsx @@ -136,9 +136,9 @@ export const DAORecord = ({ } const lockedPeriod = - unlockInfo?.timestamp && depositInfo?.timestamp ? +unlockInfo?.timestamp - +depositInfo?.timestamp : undefined + unlockInfo?.timestamp && depositInfo?.timestamp ? +unlockInfo.timestamp - +depositInfo.timestamp : undefined const compensatedPeriod = - withdrawInfo?.timestamp && depositInfo?.timestamp ? +withdrawInfo?.timestamp - +depositInfo?.timestamp : undefined + withdrawInfo?.timestamp && depositInfo?.timestamp ? +withdrawInfo.timestamp - +depositInfo.timestamp : undefined const isActionAvailable = connectionStatus === 'online' && [CellStatus.Deposited, CellStatus.Unlockable].includes(cellStatus) diff --git a/packages/neuron-ui/src/components/Send/hooks.ts b/packages/neuron-ui/src/components/Send/hooks.ts index 55b1141b45..e1fe712f1d 100644 --- a/packages/neuron-ui/src/components/Send/hooks.ts +++ b/packages/neuron-ui/src/components/Send/hooks.ts @@ -21,92 +21,6 @@ Object.defineProperty(generateSendingAllTx, 'type', { value: 'all', }) -const updateTransactionWith = (generator: typeof generateTx | typeof generateSendingAllTx) => ({ - walletID, - price, - items, - setTotalAmount, - setErrorMessage, - updateTransactionOutput, - isMainnet, - dispatch, - t, -}: { - walletID: string - price: string - items: Readonly - setTotalAmount: Function - setErrorMessage: Function - updateTransactionOutput?: Function - isMainnet: boolean - dispatch: StateDispatch - t: TFunction -}) => { - const { value: type } = Object.getOwnPropertyDescriptor(generator, 'type')! - if (items.length === 1 && items[0].amount === undefined) { - setTotalAmount('0') - } else if (type === 'common') { - try { - const totalAmount = outputsToTotalAmount(items) - setTotalAmount(totalAmount) - } catch (err) { - console.warn(err) - } - } - try { - validateOutputs(items, isMainnet, type === 'all') - const realParams = { - walletID, - items: items.map(item => ({ - address: item.address || '', - capacity: CKBToShannonFormatter(item.amount, item.unit), - date: item.date, - })), - feeRate: price, - } - return generator(realParams) - .then((res: any) => { - if (res.status === 1) { - dispatch({ - type: AppActions.UpdateGeneratedTx, - payload: res.result, - }) - if (type === 'all') { - const fmtItems = items.map((item, i) => ({ - ...item, - amount: shannonToCKBFormatter(res.result.outputs[i].capacity, false, ''), - })) - const totalAmount = outputsToTotalAmount(fmtItems) - setTotalAmount(totalAmount) - if (updateTransactionOutput) { - updateTransactionOutput('amount')(items.length - 1)(fmtItems[fmtItems.length - 1].amount) - } - } - return res.result - } - if (res.status === 0 || res.status === 114) { - throw new Error(res.message.content) - } - throw new Error(t(`messages.codes.${res.status}`)) - }) - .catch((err: Error) => { - dispatch({ - type: AppActions.UpdateGeneratedTx, - payload: '', - }) - setErrorMessage(err.message) - return undefined - }) - } catch { - // ignore - } - dispatch({ - type: AppActions.UpdateGeneratedTx, - payload: '', - }) - return Promise.resolve(undefined) -} - const useUpdateTransactionOutput = (dispatch: StateDispatch) => useCallback( (field: string) => (idx: number) => (value: string | undefined) => { @@ -123,6 +37,94 @@ const useUpdateTransactionOutput = (dispatch: StateDispatch) => [dispatch] ) +const updateTransactionWith = + (generator: typeof generateTx | typeof generateSendingAllTx) => + ({ + walletID, + price, + items, + setTotalAmount, + setErrorMessage, + updateTransactionOutput, + isMainnet, + dispatch, + t, + }: { + walletID: string + price: string + items: Readonly + setTotalAmount: (val: string) => void + setErrorMessage: (val: string) => void + updateTransactionOutput?: ReturnType + isMainnet: boolean + dispatch: StateDispatch + t: TFunction + }) => { + const { value: type } = Object.getOwnPropertyDescriptor(generator, 'type')! + if (items.length === 1 && items[0].amount === undefined) { + setTotalAmount('0') + } else if (type === 'common') { + try { + const totalAmount = outputsToTotalAmount(items) + setTotalAmount(totalAmount) + } catch (err) { + console.warn(err) + } + } + try { + validateOutputs(items, isMainnet, type === 'all') + const realParams = { + walletID, + items: items.map(item => ({ + address: item.address || '', + capacity: CKBToShannonFormatter(item.amount, item.unit), + date: item.date, + })), + feeRate: price, + } + return generator(realParams) + .then((res: any) => { + if (res.status === 1) { + dispatch({ + type: AppActions.UpdateGeneratedTx, + payload: res.result, + }) + if (type === 'all') { + const fmtItems = items.map((item, i) => ({ + ...item, + amount: shannonToCKBFormatter(res.result.outputs[i].capacity, false, ''), + })) + const totalAmount = outputsToTotalAmount(fmtItems) + setTotalAmount(totalAmount) + if (updateTransactionOutput) { + updateTransactionOutput('amount')(items.length - 1)(fmtItems[fmtItems.length - 1].amount) + } + } + return res.result + } + if (res.status === 0 || res.status === 114) { + throw new Error(res.message.content) + } + throw new Error(t(`messages.codes.${res.status}`)) + }) + .catch((err: Error) => { + dispatch({ + type: AppActions.UpdateGeneratedTx, + payload: '', + }) + setErrorMessage(err.message) + return undefined + }) + } catch { + // ignore + } + dispatch({ + type: AppActions.UpdateGeneratedTx, + payload: '', + }) + return Promise.resolve(undefined) + } + const useAddTransactionOutput = (dispatch: StateDispatch) => useCallback(() => { dispatch({ @@ -154,8 +156,8 @@ const useOnTransactionChange = ( isMainnet: boolean, dispatch: StateDispatch, isSendMax: boolean, - setTotalAmount: Function, - setErrorMessage: Function, + setTotalAmount: (val: string) => void, + setErrorMessage: (val: string) => void, t: TFunction ) => { useEffect(() => { @@ -210,7 +212,7 @@ const useOnSubmit = (items: Readonly, isMainnet: boolean, dispat [dispatch, items, isMainnet] ) -const useOnItemChange = (updateTransactionOutput: Function) => +const useOnItemChange = (updateTransactionOutput: ReturnType) => useCallback( (e: any) => { const { @@ -326,11 +328,10 @@ export const useInitialize = ( const [errorMessage, setErrorMessage] = useState('') const [isSendMax, setIsSendMax] = useState(false) - const outputs = useMemo(() => items.map(item => ({ ...item, disabled: isSendMax || sending })), [ - items, - isSendMax, - sending, - ]) + const outputs = useMemo( + () => items.map(item => ({ ...item, disabled: isSendMax || sending })), + [items, isSendMax, sending] + ) const updateTransactionOutput = useUpdateTransactionOutput(dispatch) const onItemChange = useOnItemChange(updateTransactionOutput) diff --git a/packages/neuron-ui/src/components/SendFromMultisigDialog/hooks.ts b/packages/neuron-ui/src/components/SendFromMultisigDialog/hooks.ts index d069a6aaec..acbdf088f8 100644 --- a/packages/neuron-ui/src/components/SendFromMultisigDialog/hooks.ts +++ b/packages/neuron-ui/src/components/SendFromMultisigDialog/hooks.ts @@ -28,61 +28,63 @@ Object.defineProperty(generateMultisigSendAllTx, 'type', { value: 'all', }) -const generateMultisigTxWith = (generator: typeof generateMultisigTx | typeof generateMultisigSendAllTx) => ({ - sendInfoList, - multisigConfig, - dispatch, - setErrorMessage, - t, - isMainnet, -}: { - sendInfoList: { address: string | undefined; amount: string | undefined; unit: CapacityUnit }[] - multisigConfig: MultisigConfig - dispatch: StateDispatch - setErrorMessage: React.Dispatch> - t: TFunction - isMainnet: boolean -}) => { - try { - const { value: type } = Object.getOwnPropertyDescriptor(generator, 'type')! - validateOutputs(sendInfoList, isMainnet, type === 'all') - const realParams = { - items: sendInfoList.map(item => ({ - address: item.address || '', - capacity: CKBToShannonFormatter(item.amount, item.unit), - })), - multisigConfig, - } - return generator(realParams) - .then((res: any) => { - if (res.status === 1) { +const generateMultisigTxWith = + (generator: typeof generateMultisigTx | typeof generateMultisigSendAllTx) => + ({ + sendInfoList, + multisigConfig, + dispatch, + setErrorMessage, + t, + isMainnet, + }: { + sendInfoList: { address: string | undefined; amount: string | undefined; unit: CapacityUnit }[] + multisigConfig: MultisigConfig + dispatch: StateDispatch + setErrorMessage: React.Dispatch> + t: TFunction + isMainnet: boolean + }) => { + try { + const { value: type } = Object.getOwnPropertyDescriptor(generator, 'type')! + validateOutputs(sendInfoList, isMainnet, type === 'all') + const realParams = { + items: sendInfoList.map(item => ({ + address: item.address || '', + capacity: CKBToShannonFormatter(item.amount, item.unit), + })), + multisigConfig, + } + return generator(realParams) + .then((res: any) => { + if (res.status === 1) { + dispatch({ + type: AppActions.UpdateGeneratedTx, + payload: res.result, + }) + return res.result + } + if (res.status === 0 || res.status === 114) { + throw new Error(res.message.content) + } + throw new Error(t(`messages.codes.${res.status}`)) + }) + .catch((err: Error) => { dispatch({ type: AppActions.UpdateGeneratedTx, - payload: res.result, + payload: '', }) - return res.result - } - if (res.status === 0 || res.status === 114) { - throw new Error(res.message.content) - } - throw new Error(t(`messages.codes.${res.status}`)) - }) - .catch((err: Error) => { - dispatch({ - type: AppActions.UpdateGeneratedTx, - payload: '', + setErrorMessage(err.message) }) - setErrorMessage(err.message) - }) - } catch { - // ignore catch + } catch { + // ignore catch + } + dispatch({ + type: AppActions.UpdateGeneratedTx, + payload: '', + }) + return Promise.resolve(undefined) } - dispatch({ - type: AppActions.UpdateGeneratedTx, - payload: '', - }) - return Promise.resolve(undefined) -} export const useSendInfo = ({ isMainnet, balance, diff --git a/packages/neuron-ui/src/components/WalletEditor/hooks.ts b/packages/neuron-ui/src/components/WalletEditor/hooks.ts index 7cdf103e46..fb3996b160 100644 --- a/packages/neuron-ui/src/components/WalletEditor/hooks.ts +++ b/packages/neuron-ui/src/components/WalletEditor/hooks.ts @@ -41,8 +41,8 @@ export const useInputs = ({ name }: ReturnType) => { } export const useOnSubmit = ( - name: string = '', - id: string = '', + name: string, + id: string, history: ReturnType, dispatch: StateDispatch, disabled: boolean @@ -66,7 +66,7 @@ export const useOnSubmit = ( ) } -export const useHint = (name: string, usedNames: string[], t: Function): string | null => { +export const useHint = (name: string, usedNames: string[], t: (key: string, opts: object) => string): string | null => { return useMemo(() => { if (name === '') { return t(`messages.codes.${ErrorCode.FieldRequired}`, { fieldName: 'name' }) diff --git a/packages/neuron-ui/src/services/remote/app.ts b/packages/neuron-ui/src/services/remote/app.ts index 2c2881a410..fb4ee8c706 100644 --- a/packages/neuron-ui/src/services/remote/app.ts +++ b/packages/neuron-ui/src/services/remote/app.ts @@ -16,7 +16,7 @@ export const openInWindow = remoteApi('open-in-wi export const requestOpenInExplorer = remoteApi('request-open-in-explorer') export const handleViewError = remoteApi('handle-view-error') export const showSettings = remoteApi('show-settings') -export const setLocale = remoteApi('set-locale') +export const setLocale = remoteApi<(typeof LOCALES)[number]>('set-locale') export const getCkbNodeDataPath = remoteApi('get-ckb-node-data-path') export const setCkbNodeDataPath = remoteApi<{ dataPath: string; clearCache?: boolean }, string>( 'set-ckb-node-data-path' diff --git a/packages/neuron-ui/src/services/remote/index.ts b/packages/neuron-ui/src/services/remote/index.ts index 272b675ea9..a52afbbd8a 100644 --- a/packages/neuron-ui/src/services/remote/index.ts +++ b/packages/neuron-ui/src/services/remote/index.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-alert */ import { ipcRenderer, shell, OpenDialogOptions, MenuItemConstructorOptions, MenuItem } from 'electron' import { invokeShowErrorMessage, invokeShowOpenDialog, invokeShowOpenDialogModal, invokeOpenContextMenu } from './app' diff --git a/packages/neuron-ui/src/services/remote/multisig.ts b/packages/neuron-ui/src/services/remote/multisig.ts index 89ac83f02e..7c853a2994 100644 --- a/packages/neuron-ui/src/services/remote/multisig.ts +++ b/packages/neuron-ui/src/services/remote/multisig.ts @@ -1,15 +1,13 @@ import { remoteApi } from './remoteApiWrapper' import { OfflineSignJSON } from './offline' -type PartialSome = Omit & - { - [P in R]?: T[P] - } +type PartialSome = Omit & { + [P in R]?: T[P] +} -type RequiredSome = Omit & - { - [P in R]-?: T[P] - } +type RequiredSome = Omit & { + [P in R]-?: T[P] +} type MultisigParams = { id: number diff --git a/packages/neuron-ui/src/services/remote/remoteApiWrapper.ts b/packages/neuron-ui/src/services/remote/remoteApiWrapper.ts index 97d54dd7b6..54729f60a2 100644 --- a/packages/neuron-ui/src/services/remote/remoteApiWrapper.ts +++ b/packages/neuron-ui/src/services/remote/remoteApiWrapper.ts @@ -148,32 +148,36 @@ type Action = | 'get-hold-sudt-cell-capacity' | 'start-migrate' -export const remoteApi =

(action: Action) => async (params: P): Promise> => { - const res: SuccessFromController | FailureFromController = await ipcRenderer.invoke(action, params).catch(() => ({ - status: ResponseCode.FAILURE, - message: { - content: 'Invalid response format', - }, - })) +export const remoteApi = +

(action: Action) => + async (params: P): Promise> => { + const res: SuccessFromController | FailureFromController = await ipcRenderer + .invoke(action, params) + .catch(() => ({ + status: ResponseCode.FAILURE, + message: { + content: 'Invalid response format', + }, + })) - if (!res) { - return { - status: ResponseCode.SUCCESS, - result: null, + if (!res) { + return { + status: ResponseCode.SUCCESS, + result: null, + } } - } - if (isSuccessResponse(res)) { - return { - status: ResponseCode.SUCCESS, - result: res.result ?? null, + if (isSuccessResponse(res)) { + return { + status: ResponseCode.SUCCESS, + result: res.result ?? null, + } } - } - return { - status: res.status ?? ResponseCode.FAILURE, - message: typeof res.message === 'string' ? { content: res.message } : res.message ?? '', + return { + status: res.status ?? ResponseCode.FAILURE, + message: typeof res.message === 'string' ? { content: res.message } : res.message ?? '', + } } -} export default { remoteApi } diff --git a/packages/neuron-ui/src/services/remote/sudt.ts b/packages/neuron-ui/src/services/remote/sudt.ts index 036c4a4549..ace0358d7c 100644 --- a/packages/neuron-ui/src/services/remote/sudt.ts +++ b/packages/neuron-ui/src/services/remote/sudt.ts @@ -12,9 +12,8 @@ export const generateCreateSUDTAccountTransaction = remoteApi( - 'send-create-asset-account-tx' -) +export const sendCreateSUDTAccountTransaction = + remoteApi('send-create-asset-account-tx') export const updateSUDTAccount = remoteApi('update-asset-account') diff --git a/packages/neuron-ui/src/services/remote/wallets.ts b/packages/neuron-ui/src/services/remote/wallets.ts index b5e22f73d0..bbbd508afa 100644 --- a/packages/neuron-ui/src/services/remote/wallets.ts +++ b/packages/neuron-ui/src/services/remote/wallets.ts @@ -10,9 +10,8 @@ export const updateWallet = remoteApi('update-wal export const deleteWallet = remoteApi('delete-wallet') export const backupWallet = remoteApi('backup-wallet') export const getAddressesByWalletID = remoteApi('get-all-addresses') -export const updateAddressDescription = remoteApi( - 'update-address-description' -) +export const updateAddressDescription = + remoteApi('update-address-description') export const requestPassword = remoteApi('request-password') export const sendTx = remoteApi('send-tx') export const generateTx = remoteApi('generate-tx') @@ -23,9 +22,8 @@ export const validateMnemonic = remoteApi('validate-mnemonic') // Dao export const getDaoData = remoteApi('get-dao-data') export const generateDaoDepositTx = remoteApi('generate-dao-deposit-tx') -export const generateDaoDepositAllTx = remoteApi( - 'generate-dao-deposit-all-tx' -) +export const generateDaoDepositAllTx = + remoteApi('generate-dao-deposit-all-tx') export const generateDaoWithdrawTx = remoteApi('start-withdraw-from-dao') export const generateDaoClaimTx = remoteApi('withdraw-from-dao') diff --git a/packages/neuron-ui/src/services/subjects.ts b/packages/neuron-ui/src/services/subjects.ts index 628d367feb..1ef4fa26a8 100644 --- a/packages/neuron-ui/src/services/subjects.ts +++ b/packages/neuron-ui/src/services/subjects.ts @@ -62,7 +62,7 @@ export const SyncState = SubjectConstructor('sync-estimate-up export const AppUpdater = SubjectConstructor('app-updater-updated') export const Command = SubjectConstructor('command') export const Navigation = SubjectConstructor('navigation') -export const SetLocale = SubjectConstructor('set-locale') +export const SetLocale = SubjectConstructor<(typeof LOCALES)[number]>('set-locale') export const DeviceSignIndex = SubjectConstructor('device-sign-index') export const MultisigOutputUpdate = SubjectConstructor('multisig-output-update') export const Migrate = SubjectConstructor<'need-migrate' | 'migrating' | 'failed' | 'finish'>('migrate') diff --git a/packages/neuron-ui/src/states/stateProvider/actionCreators/app.ts b/packages/neuron-ui/src/states/stateProvider/actionCreators/app.ts index 569d966e86..0dac471d40 100644 --- a/packages/neuron-ui/src/states/stateProvider/actionCreators/app.ts +++ b/packages/neuron-ui/src/states/stateProvider/actionCreators/app.ts @@ -91,23 +91,22 @@ export const dismissGlobalDialog = () => (dispatch: StateDispatch) => { }) } -export const showAlertDialog = (content: { title: string; message: string }) => ( - dispatch: React.Dispatch<{ type: AppActions.UpdateAlertDialog; payload: { title: string; message: string } }> -) => { - dispatch({ - type: AppActions.UpdateAlertDialog, - payload: content, - }) -} +export const showAlertDialog = + (content: { title: string; message: string }) => + (dispatch: React.Dispatch<{ type: AppActions.UpdateAlertDialog; payload: { title: string; message: string } }>) => { + dispatch({ + type: AppActions.UpdateAlertDialog, + payload: content, + }) + } -export const dismissAlertDialog = () => ( - dispatch: React.Dispatch<{ type: AppActions.UpdateAlertDialog; payload: null }> -) => { - dispatch({ - type: AppActions.UpdateAlertDialog, - payload: null, - }) -} +export const dismissAlertDialog = + () => (dispatch: React.Dispatch<{ type: AppActions.UpdateAlertDialog; payload: null }>) => { + dispatch({ + type: AppActions.UpdateAlertDialog, + payload: null, + }) + } export const toggleTopAlertVisibility = (show?: boolean) => (dispatch: StateDispatch) => { dispatch({ diff --git a/packages/neuron-ui/src/states/stateProvider/actionCreators/sudt.ts b/packages/neuron-ui/src/states/stateProvider/actionCreators/sudt.ts index 2cc1a18ebb..235b910e32 100644 --- a/packages/neuron-ui/src/states/stateProvider/actionCreators/sudt.ts +++ b/packages/neuron-ui/src/states/stateProvider/actionCreators/sudt.ts @@ -7,9 +7,9 @@ import { import { AppActions, StateDispatch } from '../reducer' import { addNotification } from './app' -export const sendCreateSUDTAccountTransaction = (params: Controller.SendCreateSUDTAccountTransaction.Params) => async ( - dispatch: StateDispatch -) => sendTxBaseAction(sendCreateAccountTx, params, dispatch, addNotification) +export const sendCreateSUDTAccountTransaction = + (params: Controller.SendCreateSUDTAccountTransaction.Params) => async (dispatch: StateDispatch) => + sendTxBaseAction(sendCreateAccountTx, params, dispatch, addNotification) export const sendSUDTTransaction = (params: Controller.SendSUDTTransaction.Params) => async (dispatch: StateDispatch) => sendTxBaseAction(sendSUDTTx, params, dispatch, addNotification) diff --git a/packages/neuron-ui/src/states/stateProvider/actionCreators/transactions.ts b/packages/neuron-ui/src/states/stateProvider/actionCreators/transactions.ts index a3082716a7..cfb9915e4d 100644 --- a/packages/neuron-ui/src/states/stateProvider/actionCreators/transactions.ts +++ b/packages/neuron-ui/src/states/stateProvider/actionCreators/transactions.ts @@ -20,26 +20,25 @@ export const updateTransactionList = (params: GetTransactionListParams) => (disp }) } -export const updateTransactionDescription = (params: Controller.UpdateTransactionDescriptionParams) => ( - dispatch: StateDispatch -) => { - const descriptionParams = { - walletID: params.walletID, - hash: params.hash, - description: params.description, - } - dispatch({ - type: NeuronWalletActions.UpdateTransactionDescription, - payload: descriptionParams, - }) // update local description before remote description to avoid the flicker on the field - updateRemoteTransactionDescription(params).then(res => { - if (res.status === 1) { - dispatch({ - type: NeuronWalletActions.UpdateTransactionDescription, - payload: descriptionParams, - }) - } else { - addNotification(failureResToNotification(res))(dispatch) +export const updateTransactionDescription = + (params: Controller.UpdateTransactionDescriptionParams) => (dispatch: StateDispatch) => { + const descriptionParams = { + walletID: params.walletID, + hash: params.hash, + description: params.description, } - }) -} + dispatch({ + type: NeuronWalletActions.UpdateTransactionDescription, + payload: descriptionParams, + }) // update local description before remote description to avoid the flicker on the field + updateRemoteTransactionDescription(params).then(res => { + if (res.status === 1) { + dispatch({ + type: NeuronWalletActions.UpdateTransactionDescription, + payload: descriptionParams, + }) + } else { + addNotification(failureResToNotification(res))(dispatch) + } + }) + } diff --git a/packages/neuron-ui/src/states/stateProvider/actionCreators/wallets.ts b/packages/neuron-ui/src/states/stateProvider/actionCreators/wallets.ts index 1e3bcd0228..944828d9c7 100644 --- a/packages/neuron-ui/src/states/stateProvider/actionCreators/wallets.ts +++ b/packages/neuron-ui/src/states/stateProvider/actionCreators/wallets.ts @@ -76,43 +76,41 @@ export const setCurrentWallet = (id: string) => (dispatch: StateDispatch) => { export const sendTransaction = (params: Controller.SendTransactionParams) => async (dispatch: StateDispatch) => sendTxBaseAction(sendTx, params, dispatch, addNotification) -export const updateAddressListAndBalance = (params: Controller.GetAddressesByWalletIDParams) => ( - dispatch: StateDispatch -) => { - getAddressesByWalletID(params).then(res => { - if (isSuccessResponse(res)) { - const addresses = res.result || [] - const balance = addressesToBalance(addresses) - dispatch({ - type: NeuronWalletActions.UpdateAddressListAndBalance, - payload: { addresses, balance }, - }) - addressesCache.save(addresses) - } else { - addNotification(failureResToNotification(res))(dispatch) - } - }) -} +export const updateAddressListAndBalance = + (params: Controller.GetAddressesByWalletIDParams) => (dispatch: StateDispatch) => { + getAddressesByWalletID(params).then(res => { + if (isSuccessResponse(res)) { + const addresses = res.result || [] + const balance = addressesToBalance(addresses) + dispatch({ + type: NeuronWalletActions.UpdateAddressListAndBalance, + payload: { addresses, balance }, + }) + addressesCache.save(addresses) + } else { + addNotification(failureResToNotification(res))(dispatch) + } + }) + } -export const updateAddressDescription = (params: Controller.UpdateAddressDescriptionParams) => ( - dispatch: StateDispatch -) => { - const descriptionParams = { address: params.address, description: params.description } - dispatch({ - type: NeuronWalletActions.UpdateAddressDescription, - payload: descriptionParams, - }) - updateRemoteAddressDescription(params).then(res => { - if (isSuccessResponse(res)) { - dispatch({ - type: NeuronWalletActions.UpdateAddressDescription, - payload: descriptionParams, - }) - } else { - addNotification(failureResToNotification(res))(dispatch) - } - }) -} +export const updateAddressDescription = + (params: Controller.UpdateAddressDescriptionParams) => (dispatch: StateDispatch) => { + const descriptionParams = { address: params.address, description: params.description } + dispatch({ + type: NeuronWalletActions.UpdateAddressDescription, + payload: descriptionParams, + }) + updateRemoteAddressDescription(params).then(res => { + if (isSuccessResponse(res)) { + dispatch({ + type: NeuronWalletActions.UpdateAddressDescription, + payload: descriptionParams, + }) + } else { + addNotification(failureResToNotification(res))(dispatch) + } + }) + } export const deleteWallet = (params: Controller.DeleteWalletParams) => async (dispatch: StateDispatch) => { dispatch({ diff --git a/packages/neuron-ui/src/states/stateProvider/provider.tsx b/packages/neuron-ui/src/states/stateProvider/provider.tsx index 1d3d1c24cd..a9a54c1cd1 100644 --- a/packages/neuron-ui/src/states/stateProvider/provider.tsx +++ b/packages/neuron-ui/src/states/stateProvider/provider.tsx @@ -1,4 +1,4 @@ -import React, { createContext, useReducer, useContext } from 'react' +import React, { createContext, useReducer, useContext, useMemo } from 'react' import initStates from 'states/init' import { StateDispatch, reducer } from './reducer' @@ -16,8 +16,10 @@ export const withProvider = (Comp: React.ComponentType) => (props: JSX.Intrinsic value: 'ComponentWithNeuronWallet', }) + const value = useMemo(() => ({ state: providers, dispatch }), [providers, dispatch]) + return ( - + ) diff --git a/packages/neuron-ui/src/tests/calculation/calculateAPC/index.test.ts b/packages/neuron-ui/src/tests/calculation/calculateAPC/index.test.ts index b111a7d8dd..8066d4badd 100644 --- a/packages/neuron-ui/src/tests/calculation/calculateAPC/index.test.ts +++ b/packages/neuron-ui/src/tests/calculation/calculateAPC/index.test.ts @@ -2,9 +2,9 @@ import calculateAPC from 'utils/calculateAPC' import fixtures from './fixtures.json' describe('calculate the apc', () => { - const fixtureTable: [string, number, number, number][] = Object.entries( - fixtures - ).map(([title, { startYearNumber, endYearNumber, expected }]) => [title, startYearNumber, endYearNumber, expected]) + const fixtureTable: [string, number, number, number][] = Object.entries(fixtures).map( + ([title, { startYearNumber, endYearNumber, expected }]) => [title, startYearNumber, endYearNumber, expected] + ) test.each(fixtureTable)(`%s`, (_title, startYearNumber, endYearNumber, expected) => { const apc = calculateAPC({ diff --git a/packages/neuron-ui/src/tests/getPageNoList/index.test.ts b/packages/neuron-ui/src/tests/getPageNoList/index.test.ts index 74aa69afc7..e8336515d5 100644 --- a/packages/neuron-ui/src/tests/getPageNoList/index.test.ts +++ b/packages/neuron-ui/src/tests/getPageNoList/index.test.ts @@ -2,9 +2,9 @@ import getPageNoList from 'utils/getPageNoList' import fixtures from './fixtures' describe('Test getPageNoList', () => { - const fixtureTable: [string, [number, number], number[]][] = Object.entries( - fixtures - ).map(([name, { params, expected }]) => [name, [params.pageNo, params.count], expected]) + const fixtureTable: [string, [number, number], number[]][] = Object.entries(fixtures).map( + ([name, { params, expected }]) => [name, [params.pageNo, params.count], expected] + ) test.each(fixtureTable)('%s', (_name: string, [pageNo, count], expected) => { expect.assertions(1) diff --git a/packages/neuron-ui/src/tests/getSyncLeftTime/index.test.ts b/packages/neuron-ui/src/tests/getSyncLeftTime/index.test.ts index cf784a8dda..4447e320e4 100644 --- a/packages/neuron-ui/src/tests/getSyncLeftTime/index.test.ts +++ b/packages/neuron-ui/src/tests/getSyncLeftTime/index.test.ts @@ -2,9 +2,9 @@ import getSyncLeftTime from 'utils/getSyncLeftTime' import fixtures from './fixtures.json' describe('Test getCompensatedTime', () => { - const fixtureTable: [string, number | null, string][] = Object.entries( - fixtures - ).map(([title, { estimate, expected }]) => [title, estimate, expected]) + const fixtureTable: [string, number | null, string][] = Object.entries(fixtures).map( + ([title, { estimate, expected }]) => [title, estimate, expected] + ) test.each(fixtureTable)(`%s`, (_title, estimate, expected) => { expect.assertions(1) diff --git a/packages/neuron-ui/src/tests/is/isMainnet/index.test.ts b/packages/neuron-ui/src/tests/is/isMainnet/index.test.ts index 8b4483ca37..10d8af1da9 100644 --- a/packages/neuron-ui/src/tests/is/isMainnet/index.test.ts +++ b/packages/neuron-ui/src/tests/is/isMainnet/index.test.ts @@ -1,9 +1,9 @@ import { isMainnet } from 'utils/is' import fixtures from './fixtures' -const fixtureTable: [string, Parameters, boolean][] = Object.entries( - fixtures -).map(([title, { params, expected }]) => [title, [params.networks, params.networkID], expected]) +const fixtureTable: [string, Parameters, boolean][] = Object.entries(fixtures).map( + ([title, { params, expected }]) => [title, [params.networks, params.networkID], expected] +) describe('Test isMainnet', () => { test.each(fixtureTable)(`%s`, (_title, [networks, networkID], expected) => { diff --git a/packages/neuron-ui/src/tests/is/isReadyByVersion/index.test.ts b/packages/neuron-ui/src/tests/is/isReadyByVersion/index.test.ts index 4541c61942..c37977d95c 100644 --- a/packages/neuron-ui/src/tests/is/isReadyByVersion/index.test.ts +++ b/packages/neuron-ui/src/tests/is/isReadyByVersion/index.test.ts @@ -1,9 +1,9 @@ import { isReadyByVersion } from 'utils/is' import fixtures from './fixtures' -const fixtureTable: [string, Parameters, boolean][] = Object.entries( - fixtures -).map(([title, { params, expected }]) => [title, [params.targetVersion, params.lastVersion], expected]) +const fixtureTable: [string, Parameters, boolean][] = Object.entries(fixtures).map( + ([title, { params, expected }]) => [title, [params.targetVersion, params.lastVersion], expected] +) describe('Test isReadyByVersion', () => { test.each(fixtureTable)(`%s`, (_title, [targetVersion, lastVersion], expected) => { diff --git a/packages/neuron-ui/src/tests/is/isSuccessResponse/index.test.ts b/packages/neuron-ui/src/tests/is/isSuccessResponse/index.test.ts index 2c3bfee57e..1d0a50f7dc 100644 --- a/packages/neuron-ui/src/tests/is/isSuccessResponse/index.test.ts +++ b/packages/neuron-ui/src/tests/is/isSuccessResponse/index.test.ts @@ -1,9 +1,9 @@ import { isSuccessResponse } from 'utils/is' import fixtures from './fixtures' -const fixtureTable: [string, Parameters, boolean][] = Object.entries( - fixtures -).map(([title, { params, expected }]) => [title, [params.res], expected]) +const fixtureTable: [string, Parameters, boolean][] = Object.entries(fixtures).map( + ([title, { params, expected }]) => [title, [params.res], expected] +) describe('Test isSuccessResponse', () => { test.each(fixtureTable)(`%s`, (_title, [res], expected) => { diff --git a/packages/neuron-ui/src/tests/sortAccounts/index.test.ts b/packages/neuron-ui/src/tests/sortAccounts/index.test.ts index 6d1c8086ed..53249f3579 100644 --- a/packages/neuron-ui/src/tests/sortAccounts/index.test.ts +++ b/packages/neuron-ui/src/tests/sortAccounts/index.test.ts @@ -2,9 +2,9 @@ import sortAccounts, { Account } from 'utils/sortAccounts' import fixtures from './fixtures.json' describe('Test sortAccounts', () => { - const fixtureTable: [string, { accounts: Account[]; expected: Account[] }][] = Object.entries( - fixtures - ).map(([name, fixture]) => [name, fixture]) + const fixtureTable: [string, { accounts: Account[]; expected: Account[] }][] = Object.entries(fixtures).map( + ([name, fixture]) => [name, fixture] + ) test.each(fixtureTable)('%s', (_name: string, { accounts, expected }: any) => { const actual = accounts.sort(sortAccounts) diff --git a/packages/neuron-ui/src/tests/validators/address/index.test.ts b/packages/neuron-ui/src/tests/validators/address/index.test.ts index d5bba86ec2..59a8c1a58e 100644 --- a/packages/neuron-ui/src/tests/validators/address/index.test.ts +++ b/packages/neuron-ui/src/tests/validators/address/index.test.ts @@ -2,9 +2,9 @@ import { isErrorWithI18n } from 'exceptions' import { validateAddress } from 'utils/validators' import fixtures from './fixtures' -const fixtureTable: Fixture.Validator[] = Object.entries( - fixtures -).map(([title, { params, exception }]) => [title, [params.address, params.isMainnet], exception]) +const fixtureTable: Fixture.Validator[] = Object.entries(fixtures).map( + ([title, { params, exception }]) => [title, [params.address, params.isMainnet], exception] +) describe(`Test address validator`, () => { test.each(fixtureTable)(`%s`, (_title, [address, isMainnet], exception) => { diff --git a/packages/neuron-ui/src/tests/validators/amount/index.test.ts b/packages/neuron-ui/src/tests/validators/amount/index.test.ts index 20d277ebd4..9c1ac74e69 100644 --- a/packages/neuron-ui/src/tests/validators/amount/index.test.ts +++ b/packages/neuron-ui/src/tests/validators/amount/index.test.ts @@ -2,9 +2,9 @@ import { isErrorWithI18n } from 'exceptions' import { validateAmount } from 'utils/validators' import fixtures from './fixtures' -const fixtureTable: Fixture.Validator[] = Object.entries( - fixtures -).map(([title, { params, exception }]) => [title, [params.amount], exception]) +const fixtureTable: Fixture.Validator[] = Object.entries(fixtures).map( + ([title, { params, exception }]) => [title, [params.amount], exception] +) describe(`Test amount validator`, () => { test.each(fixtureTable)(`%s`, (_title, [amount], exception) => { diff --git a/packages/neuron-ui/src/tests/validators/amountRange/index.test.ts b/packages/neuron-ui/src/tests/validators/amountRange/index.test.ts index b0c7a6b9f9..2061364ab8 100644 --- a/packages/neuron-ui/src/tests/validators/amountRange/index.test.ts +++ b/packages/neuron-ui/src/tests/validators/amountRange/index.test.ts @@ -2,9 +2,9 @@ import { isErrorWithI18n } from 'exceptions' import { validateAmountRange } from 'utils/validators' import fixtures from './fixtures' -const fixtureTable: Fixture.Validator[] = Object.entries( - fixtures -).map(([title, { params, exception }]) => [title, [params.amount, params.extraSize], exception]) +const fixtureTable: Fixture.Validator[] = Object.entries(fixtures).map( + ([title, { params, exception }]) => [title, [params.amount, params.extraSize], exception] +) describe('Verify amount range', () => { test.each(fixtureTable)(`%s`, (_title, [amount, extraSize], exception) => { diff --git a/packages/neuron-ui/src/tests/validators/assetAccountAddress/index.test.ts b/packages/neuron-ui/src/tests/validators/assetAccountAddress/index.test.ts index 062a7e6749..b09b6775f9 100644 --- a/packages/neuron-ui/src/tests/validators/assetAccountAddress/index.test.ts +++ b/packages/neuron-ui/src/tests/validators/assetAccountAddress/index.test.ts @@ -2,9 +2,9 @@ import { isErrorWithI18n } from 'exceptions' import { validateAssetAccountAddress } from 'utils/validators' import fixtures from './fixtures' -const fixtureTable: Fixture.Validator[] = Object.entries( - fixtures -).map(([title, { params, exception }]) => [title, [params], exception]) +const fixtureTable: Fixture.Validator[] = Object.entries(fixtures).map( + ([title, { params, exception }]) => [title, [params], exception] +) describe(`Test sudt address validator`, () => { test.each(fixtureTable)(`%s`, (_title, [params], exception) => { diff --git a/packages/neuron-ui/src/tests/validators/assetAccountName/index.test.ts b/packages/neuron-ui/src/tests/validators/assetAccountName/index.test.ts index 26bfe93318..4bbe8169f4 100644 --- a/packages/neuron-ui/src/tests/validators/assetAccountName/index.test.ts +++ b/packages/neuron-ui/src/tests/validators/assetAccountName/index.test.ts @@ -2,9 +2,9 @@ import { isErrorWithI18n } from 'exceptions' import { validateAssetAccountName } from 'utils/validators' import fixtures from './fixtures' -const fixtureTable: Fixture.Validator[] = Object.entries( - fixtures -).map(([title, { params, exception }]) => [title, [params], exception]) +const fixtureTable: Fixture.Validator[] = Object.entries(fixtures).map( + ([title, { params, exception }]) => [title, [params], exception] +) describe('Test sudt account name validator', () => { test.each(fixtureTable)(`%s`, (_title, [params], exception) => { diff --git a/packages/neuron-ui/src/tests/validators/decimal/index.test.ts b/packages/neuron-ui/src/tests/validators/decimal/index.test.ts index 7a7ea3f822..a579546928 100644 --- a/packages/neuron-ui/src/tests/validators/decimal/index.test.ts +++ b/packages/neuron-ui/src/tests/validators/decimal/index.test.ts @@ -2,9 +2,9 @@ import { isErrorWithI18n } from 'exceptions' import { validateDecimal } from 'utils/validators' import fixtures from './fixtures' -const fixtureTable: Fixture.Validator[] = Object.entries( - fixtures -).map(([title, { params, exception }]) => [title, [params], exception]) +const fixtureTable: Fixture.Validator[] = Object.entries(fixtures).map( + ([title, { params, exception }]) => [title, [params], exception] +) describe('Test decimal validator', () => { test.each(fixtureTable)(`%s`, (_title, [params], exception) => { diff --git a/packages/neuron-ui/src/tests/validators/networkName/index.test.ts b/packages/neuron-ui/src/tests/validators/networkName/index.test.ts index 0c73f1f183..ad39dd7cb2 100644 --- a/packages/neuron-ui/src/tests/validators/networkName/index.test.ts +++ b/packages/neuron-ui/src/tests/validators/networkName/index.test.ts @@ -2,9 +2,9 @@ import { isErrorWithI18n } from 'exceptions' import { validateNetworkName } from 'utils/validators' import fixtures from './fixtures' -const fixtureTable: Fixture.Validator[] = Object.entries( - fixtures -).map(([title, { params, exception }]) => [title, [params.name, params.usedNames], exception]) +const fixtureTable: Fixture.Validator[] = Object.entries(fixtures).map( + ([title, { params, exception }]) => [title, [params.name, params.usedNames], exception] +) describe(`Test network name validator`, () => { test.each(fixtureTable)(`%s`, (_title, [name, usedNames], exception) => { diff --git a/packages/neuron-ui/src/tests/validators/outputs/index.test.ts b/packages/neuron-ui/src/tests/validators/outputs/index.test.ts index 603ab71474..90c56798a0 100644 --- a/packages/neuron-ui/src/tests/validators/outputs/index.test.ts +++ b/packages/neuron-ui/src/tests/validators/outputs/index.test.ts @@ -1,9 +1,9 @@ import { validateOutputs } from 'utils/validators' import fixtures from './fixtures' -const fixtureTable: Fixture.Validator[] = Object.entries( - fixtures -).map(([title, { params, exception }]) => [title, [params.outputs, params.ignoreLastAmount], exception]) +const fixtureTable: Fixture.Validator[] = Object.entries(fixtures).map( + ([title, { params, exception }]) => [title, [params.outputs, params.ignoreLastAmount], exception] +) describe(`Test outputs validator`, () => { test.each(fixtureTable)(`%s`, (_title, [outputs, ignoreLastAmount], exception) => { diff --git a/packages/neuron-ui/src/tests/validators/passwordComplexity/index.test.ts b/packages/neuron-ui/src/tests/validators/passwordComplexity/index.test.ts index 073e5245f4..85c7fc4b78 100644 --- a/packages/neuron-ui/src/tests/validators/passwordComplexity/index.test.ts +++ b/packages/neuron-ui/src/tests/validators/passwordComplexity/index.test.ts @@ -2,9 +2,9 @@ import { isErrorWithI18n } from 'exceptions' import { validatePasswordComplexity } from 'utils/validators' import fixtures from './fixtures' -const fixtureTable: Fixture.Validator[] = Object.entries( - fixtures -).map(([title, { params, exception }]) => [title, [params.password], exception]) +const fixtureTable: Fixture.Validator[] = Object.entries(fixtures).map( + ([title, { params, exception }]) => [title, [params.password], exception] +) describe('Test password complexity validator', () => { test.each(fixtureTable)(`%s`, (_title, [password], exception) => { diff --git a/packages/neuron-ui/src/tests/validators/sudtAmount/index.test.ts b/packages/neuron-ui/src/tests/validators/sudtAmount/index.test.ts index a4aba63a71..e04f191a21 100644 --- a/packages/neuron-ui/src/tests/validators/sudtAmount/index.test.ts +++ b/packages/neuron-ui/src/tests/validators/sudtAmount/index.test.ts @@ -3,9 +3,9 @@ import { validateAssetAccountAmount } from 'utils/validators' import fixtures from './fixtures' -const fixtureTable: Fixture.Validator[] = Object.entries( - fixtures -).map(([title, { params, exception }]) => [title, [params], exception]) +const fixtureTable: Fixture.Validator[] = Object.entries(fixtures).map( + ([title, { params, exception }]) => [title, [params], exception] +) describe(`Test sudt amount validator`, () => { test.each(fixtureTable)(`%s`, (_title, [params], exception) => { diff --git a/packages/neuron-ui/src/tests/validators/symbol/index.test.ts b/packages/neuron-ui/src/tests/validators/symbol/index.test.ts index 3aadd95753..f20fcf651c 100644 --- a/packages/neuron-ui/src/tests/validators/symbol/index.test.ts +++ b/packages/neuron-ui/src/tests/validators/symbol/index.test.ts @@ -2,9 +2,9 @@ import { isErrorWithI18n } from 'exceptions' import { validateSymbol } from 'utils/validators' import fixtures from './fixtures' -const fixtureTable: Fixture.Validator[] = Object.entries( - fixtures -).map(([title, { params, exception }]) => [title, [params], exception]) +const fixtureTable: Fixture.Validator[] = Object.entries(fixtures).map( + ([title, { params, exception }]) => [title, [params], exception] +) describe('Test symbol validator', () => { test.each(fixtureTable)(`%s`, (_title, [params], exception) => { diff --git a/packages/neuron-ui/src/tests/validators/tokenId/index.test.ts b/packages/neuron-ui/src/tests/validators/tokenId/index.test.ts index e2af8e5aa8..4110535426 100644 --- a/packages/neuron-ui/src/tests/validators/tokenId/index.test.ts +++ b/packages/neuron-ui/src/tests/validators/tokenId/index.test.ts @@ -2,9 +2,9 @@ import { isErrorWithI18n } from 'exceptions' import { validateTokenId } from 'utils/validators' import fixtures from './fixtures' -const fixtureTable: Fixture.Validator[] = Object.entries( - fixtures -).map(([title, { params, exception }]) => [title, [params], exception]) +const fixtureTable: Fixture.Validator[] = Object.entries(fixtures).map( + ([title, { params, exception }]) => [title, [params], exception] +) describe('Test token validator', () => { test.each(fixtureTable)(`%s`, (_title, [tokenId], exception) => { diff --git a/packages/neuron-ui/src/tests/validators/tokenName/index.test.ts b/packages/neuron-ui/src/tests/validators/tokenName/index.test.ts index 8650b3a5c9..c981928028 100644 --- a/packages/neuron-ui/src/tests/validators/tokenName/index.test.ts +++ b/packages/neuron-ui/src/tests/validators/tokenName/index.test.ts @@ -2,9 +2,9 @@ import { isErrorWithI18n } from 'exceptions' import { validateTokenName } from 'utils/validators' import fixtures from './fixtures' -const fixtureTable: Fixture.Validator[] = Object.entries( - fixtures -).map(([title, { params, exception }]) => [title, [params], exception]) +const fixtureTable: Fixture.Validator[] = Object.entries(fixtures).map( + ([title, { params, exception }]) => [title, [params], exception] +) describe('Test token name validator', () => { test.each(fixtureTable)(`%s`, (_title, [params], exception) => { diff --git a/packages/neuron-ui/src/tests/validators/totalAmount/index.test.ts b/packages/neuron-ui/src/tests/validators/totalAmount/index.test.ts index 39a2989ab4..f31ec17fbe 100644 --- a/packages/neuron-ui/src/tests/validators/totalAmount/index.test.ts +++ b/packages/neuron-ui/src/tests/validators/totalAmount/index.test.ts @@ -3,9 +3,9 @@ import { validateTotalAmount } from 'utils/validators' import fixtures from './fixtures' -const fixtureTable: Fixture.Validator[] = Object.entries( - fixtures -).map(([title, { params, exception }]) => [title, [params.totalAmount, params.fee, params.balance], exception]) +const fixtureTable: Fixture.Validator[] = Object.entries(fixtures).map( + ([title, { params, exception }]) => [title, [params.totalAmount, params.fee, params.balance], exception] +) describe(`Test total amount validator`, () => { test.each(fixtureTable)(`%s`, (_title, [totalAmount, fee, balance], exception) => { diff --git a/packages/neuron-ui/src/tests/validators/url/index.test.ts b/packages/neuron-ui/src/tests/validators/url/index.test.ts index 941d070256..be3af6e4a4 100644 --- a/packages/neuron-ui/src/tests/validators/url/index.test.ts +++ b/packages/neuron-ui/src/tests/validators/url/index.test.ts @@ -2,9 +2,9 @@ import { isErrorWithI18n } from 'exceptions' import { validateURL } from 'utils/validators' import fixtures from './fixtures' -const fixtureTable: Fixture.Validator[] = Object.entries( - fixtures -).map(([title, { params, exception }]) => [title, [params.url], exception]) +const fixtureTable: Fixture.Validator[] = Object.entries(fixtures).map( + ([title, { params, exception }]) => [title, [params.url], exception] +) describe('Test URL validator', () => { test.each(fixtureTable)(`%s`, (_title, [url], exception) => { diff --git a/packages/neuron-ui/src/types/App/index.d.ts b/packages/neuron-ui/src/types/App/index.d.ts index f3cd426448..458c724171 100644 --- a/packages/neuron-ui/src/types/App/index.d.ts +++ b/packages/neuron-ui/src/types/App/index.d.ts @@ -221,7 +221,7 @@ declare namespace State { } } interface Settings { - general: {} + general: object networks: Network[] wallets: WalletIdentity[] } diff --git a/packages/neuron-ui/src/types/global/index.d.ts b/packages/neuron-ui/src/types/global/index.d.ts index 07d6616a04..3955ee84ae 100644 --- a/packages/neuron-ui/src/types/global/index.d.ts +++ b/packages/neuron-ui/src/types/global/index.d.ts @@ -4,13 +4,7 @@ declare interface Window { shell: any require: any nativeImage: any - ipcRenderer: { - invoke(channel: string, ...args: any[]): Promise - on(channel: string, listener: Function) - removeListener(channel: string, listener: Function) - removeAllListeners(channel: string) - sendSync(channel: string, ...args: any[]): any - } + ipcRenderer: import('electron').IpcRenderer } neuron: { role: 'main' | 'settings' diff --git a/packages/neuron-ui/src/utils/formatters.ts b/packages/neuron-ui/src/utils/formatters.ts index f3592ee066..e9828fc725 100644 --- a/packages/neuron-ui/src/utils/formatters.ts +++ b/packages/neuron-ui/src/utils/formatters.ts @@ -101,7 +101,7 @@ export const CKBToShannonFormatter = (amount: string = '0', unit: CapacityUnit = } } -export const shannonToCKBFormatter = (shannon: string = '0', showPositiveSign?: boolean, delimiter: string = ',') => { +export const shannonToCKBFormatter = (shannon: string, showPositiveSign?: boolean, delimiter: string = ',') => { if (Number.isNaN(+shannon)) { console.warn(`Shannon is not a valid number`) return shannon diff --git a/packages/neuron-ui/src/utils/generateWalletName.ts b/packages/neuron-ui/src/utils/generateWalletName.ts index 1a36c3251a..717a24def3 100644 --- a/packages/neuron-ui/src/utils/generateWalletName.ts +++ b/packages/neuron-ui/src/utils/generateWalletName.ts @@ -1,4 +1,4 @@ -export const generateWalletName = (wallets: Readonly, baseNum: number = 0, t: any): string => { +export const generateWalletName = (wallets: Readonly, baseNum: number, t: any): string => { const walletName = t('wizard.wallet-suffix', { suffix: baseNum }) if (wallets.some(wallet => wallet.name === walletName)) { return generateWalletName(wallets, baseNum + 1, t) diff --git a/packages/neuron-ui/src/utils/hooks/index.ts b/packages/neuron-ui/src/utils/hooks/index.ts index 47576ee7f5..389afd2409 100644 --- a/packages/neuron-ui/src/utils/hooks/index.ts +++ b/packages/neuron-ui/src/utils/hooks/index.ts @@ -463,8 +463,8 @@ export const useDidMount = (cb: () => void) => { useEffect(cb, []) } -export const useForceUpdate = (cb: T) => { - const [, update] = useState<{}>(Object.create(null)) +export const useForceUpdate = void>(cb: T) => { + const [, update] = useState(Object.create(null)) const memoizedDispatch = useCallback( (...args: any) => { diff --git a/packages/neuron-ui/src/widgets/DatetimePicker/index.tsx b/packages/neuron-ui/src/widgets/DatetimePicker/index.tsx index 7833442376..1e0bd99252 100644 --- a/packages/neuron-ui/src/widgets/DatetimePicker/index.tsx +++ b/packages/neuron-ui/src/widgets/DatetimePicker/index.tsx @@ -26,7 +26,7 @@ export interface DatetimePickerProps { title?: string preset?: Date | string | number | null notice?: string - onConfirm: Function + onConfirm: (time: number) => void onCancel: (e: React.MouseEvent) => void } const DatetimePicker = ({ diff --git a/packages/neuron-ui/src/widgets/Pagination/index.tsx b/packages/neuron-ui/src/widgets/Pagination/index.tsx index 3759b3c1a5..458dcadb5e 100644 --- a/packages/neuron-ui/src/widgets/Pagination/index.tsx +++ b/packages/neuron-ui/src/widgets/Pagination/index.tsx @@ -12,7 +12,7 @@ export interface PaginationProps { count: number pageNo: number pageSize: number - onChange: Function + onChange: (page: number) => void } const Pagination = ({ count, pageNo, onChange, pageSize }: PaginationProps) => { @@ -45,7 +45,7 @@ const Pagination = ({ count, pageNo, onChange, pageSize }: PaginationProps) => { return (

{range}
-
+
>() +let requests = new Map unknown>>() export const killBlockSyncTask = async () => { const _child = child @@ -45,7 +45,7 @@ const waitForChildClose = (c: ChildProcess) => type: 'call', id: requestId++, channel: 'unmount', - message: null + message: null, } c.send(msg, err => { if (err) { @@ -91,7 +91,7 @@ export const queryIndexer = async (query: LumosCellQuery): Promise type: 'call', id: requestId++, channel: 'queryIndexer', - message: query + message: query, } return registerRequest(_child, msg).catch(err => { logger.error(`Sync:\tfailed to register query indexer task`, err) @@ -105,7 +105,7 @@ export const createBlockSyncTask = async () => { // prevents the sync task from being started repeatedly if fork does not finish executing. child = fork(path.join(__dirname, 'task-wrapper.js'), [], { env: { fileBasePath: env.fileBasePath }, - stdio: ['ipc', process.stdout, 'pipe'] + stdio: ['ipc', process.stdout, 'pipe'], }) child.on('message', ({ id, message, channel }: WorkerMessage) => { @@ -159,7 +159,7 @@ export const createBlockSyncTask = async () => { DataUpdateSubject.next({ dataType: 'transaction', - actionType: 'update' + actionType: 'update', }) const _child = child @@ -170,7 +170,7 @@ export const createBlockSyncTask = async () => { genesisHash: network.genesisHash, url: network.remote, addressMetas, - indexerUrl: network.remote + indexerUrl: network.remote, } const msg: Required> = { type: 'call', channel: 'start', id: requestId++, message } return registerRequest(_child, msg).catch(err => { diff --git a/packages/neuron-wallet/src/block-sync-renderer/sync/indexer-cache-service.ts b/packages/neuron-wallet/src/block-sync-renderer/sync/indexer-cache-service.ts index e36745206e..72bcf1f5e5 100644 --- a/packages/neuron-wallet/src/block-sync-renderer/sync/indexer-cache-service.ts +++ b/packages/neuron-wallet/src/block-sync-renderer/sync/indexer-cache-service.ts @@ -30,7 +30,7 @@ export default class IndexerCacheService { .getRepository(IndexerTxHashCache) .createQueryBuilder() .where({ - walletId: this.walletId + walletId: this.walletId, }) .getCount() } @@ -40,7 +40,7 @@ export default class IndexerCacheService { .getRepository(IndexerTxHashCache) .createQueryBuilder() .where({ - walletId: this.walletId + walletId: this.walletId, }) .getMany() } @@ -61,7 +61,7 @@ export default class IndexerCacheService { return { blockNumber: result.blockNumber.toString(), - blockHash: result.blockHash + blockHash: result.blockHash, } } @@ -70,10 +70,10 @@ export default class IndexerCacheService { .createQueryBuilder() .update(IndexerTxHashCache) .set({ - isProcessed: true + isProcessed: true, }) .where({ - txHash + txHash, }) .execute() } @@ -84,7 +84,7 @@ export default class IndexerCacheService { const lockScripts = [ addressMeta.generateDefaultLockScript(), addressMeta.generateACPLockScript(), - addressMeta.generateLegacyACPLockScript() + addressMeta.generateLegacyACPLockScript(), ] for (const lockScript of lockScripts) { @@ -94,12 +94,12 @@ export default class IndexerCacheService { lock: { code_hash: lockScript.codeHash, hash_type: lockScript.hashType, - args: lockScript.args - } + args: lockScript.args, + }, }, this.indexer.ckbRpcUrl, { - includeStatus: false + includeStatus: false, } ) @@ -113,8 +113,8 @@ export default class IndexerCacheService { mappingsByTxHash.set(txHash, [ { address: addressMeta.address, - lockHash: lockScript.computeHash() - } + lockHash: lockScript.computeHash(), + }, ]) } } @@ -122,12 +122,12 @@ export default class IndexerCacheService { const lockScriptsForCellCollection = [ { lockScript: addressMeta.generateSingleMultiSignLockScript(), - argsLen: 28 + argsLen: 28, }, { lockScript: addressMeta.generateChequeLockScriptWithReceiverLockHash(), - argsLen: 40 - } + argsLen: 40, + }, ] for (const { lockScript, argsLen } of lockScriptsForCellCollection) { @@ -135,9 +135,9 @@ export default class IndexerCacheService { lock: { code_hash: lockScript.codeHash, hash_type: lockScript.hashType, - args: lockScript.args.slice(0, 42) + args: lockScript.args.slice(0, 42), }, - argsLen + argsLen, }) for await (const cell of cellCollector.collect()) { @@ -145,8 +145,8 @@ export default class IndexerCacheService { mappingsByTxHash.set(txHash, [ { address: addressMeta.address, - lockHash: lockScript.computeHash() - } + lockHash: lockScript.computeHash(), + }, ]) } } @@ -214,7 +214,7 @@ export default class IndexerCacheService { lockHash, address, walletId: this.walletId, - isProcessed: false + isProcessed: false, }) .execute() } @@ -228,11 +228,11 @@ export default class IndexerCacheService { .createQueryBuilder() .update(IndexerTxHashCache) .set({ - isProcessed: true + isProcessed: true, }) .where({ blockNumber: blockNumber, - walletId: this.walletId + walletId: this.walletId, }) .execute() } @@ -243,7 +243,7 @@ export default class IndexerCacheService { .createQueryBuilder() .where({ isProcessed: false, - walletId: this.walletId + walletId: this.walletId, }) .orderBy('blockNumber', 'ASC') .getOne() @@ -259,7 +259,7 @@ export default class IndexerCacheService { .where({ blockNumber, isProcessed: false, - walletId: this.walletId + walletId: this.walletId, }) .getMany() } diff --git a/packages/neuron-wallet/src/block-sync-renderer/sync/indexer-connector.ts b/packages/neuron-wallet/src/block-sync-renderer/sync/indexer-connector.ts index 0da3dbcbdd..de363b600e 100644 --- a/packages/neuron-wallet/src/block-sync-renderer/sync/indexer-connector.ts +++ b/packages/neuron-wallet/src/block-sync-renderer/sync/indexer-connector.ts @@ -1,4 +1,3 @@ -// eslint-disable-next-line prettier/prettier import type { ScriptHashType } from '../../models/chain/script' import { Subject } from 'rxjs' import { queue, AsyncQueue } from 'async' @@ -14,8 +13,8 @@ import IndexerTxHashCache from '../../database/chain/entities/indexer-tx-hash-ca import IndexerCacheService from './indexer-cache-service' export interface LumosCellQuery { - lock: { codeHash: string, hashType: ScriptHashType, args: string } | null, - type: { codeHash: string, hashType: ScriptHashType, args: string } | null, + lock: { codeHash: string; hashType: ScriptHashType; args: string } | null + type: { codeHash: string; hashType: ScriptHashType; args: string } | null data: string | null } @@ -56,13 +55,11 @@ export default class IndexerConnector { private processingBlockNumber: string | undefined public pollingIndexer: boolean = false public readonly blockTipsSubject: Subject = new Subject() - public readonly transactionsSubject: Subject> = new Subject>() + public readonly transactionsSubject: Subject> = new Subject< + Array + >() - constructor( - addresses: Address[], - nodeUrl: string, - indexerUrl: string - ) { + constructor(addresses: Address[], nodeUrl: string, indexerUrl: string) { this.indexer = new CkbIndexer(nodeUrl, indexerUrl) this.rpcService = new RpcService(nodeUrl) @@ -107,8 +104,7 @@ export default class IndexerConnector { if (!this.processingBlockNumber) { await this.processNextBlockNumber() } - } - else { + } else { this.blockTipsSubject.next({ cacheTipNumber: indexerTipNumber, indexerTipNumber, @@ -159,14 +155,14 @@ export default class IndexerConnector { queries.lock = { code_hash: lock.codeHash, hash_type: lock.hashType, - args: lock.args + args: lock.args, } } if (type) { queries.type = { code_hash: type.codeHash, hash_type: type.hashType, - args: type.args + args: type.args, } } queries.data = data || 'any' @@ -207,9 +203,7 @@ export default class IndexerConnector { return grouped }, new Map>()) - const nextUnprocessedBlockNumber = [...groupedTxHashCaches.keys()] - .sort((a, b) => parseInt(a) - parseInt(b)) - .shift() + const nextUnprocessedBlockNumber = [...groupedTxHashCaches.keys()].sort((a, b) => parseInt(a) - parseInt(b)).shift() if (!nextUnprocessedBlockNumber) { return [] @@ -267,8 +261,7 @@ export default class IndexerConnector { public notifyCurrentBlockNumberProcessed(blockNumber: string) { if (blockNumber === this.processingBlockNumber) { delete this.processingBlockNumber - } - else { + } else { return } this.processNextBlockNumber() diff --git a/packages/neuron-wallet/src/block-sync-renderer/sync/queue.ts b/packages/neuron-wallet/src/block-sync-renderer/sync/queue.ts index c1ad3ef332..4b3903e29c 100644 --- a/packages/neuron-wallet/src/block-sync-renderer/sync/queue.ts +++ b/packages/neuron-wallet/src/block-sync-renderer/sync/queue.ts @@ -18,7 +18,6 @@ import CommonUtils from '../../utils/common' import { ShouldInChildProcess } from '../../exceptions' export default class Queue { - // eslint-disable-next-line prettier/prettier #lockHashes: string[] #url: string // ckb node #indexerUrl: string @@ -41,11 +40,13 @@ export default class Queue { const blake160s = this.#addresses.map(meta => meta.blake160) this.#multiSignBlake160s = blake160s.map(blake160 => Multisig.hash([blake160])) - this.#anyoneCanPayLockHashes = blake160s.map(b => this.#assetAccountInfo.generateAnyoneCanPayScript(b).computeHash()) + this.#anyoneCanPayLockHashes = blake160s.map(b => + this.#assetAccountInfo.generateAnyoneCanPayScript(b).computeHash() + ) } start = async () => { - logger.info("Queue:\tstart") + logger.info('Queue:\tstart') try { this.#indexerConnector = new IndexerConnector(this.#addresses, this.#url, this.#indexerUrl) @@ -82,16 +83,15 @@ export default class Queue { logger.error(err, JSON.stringify(task, undefined, 2)) }) - this.#indexerConnector.transactionsSubject - .subscribe(transactions => { - const task = { transactions: transactions.map(t => t.transaction) } - this.#checkAndSaveQueue!.push(task) - }) + this.#indexerConnector.transactionsSubject.subscribe(transactions => { + const task = { transactions: transactions.map(t => t.transaction) } + this.#checkAndSaveQueue!.push(task) + }) } getIndexerConnector = (): IndexerConnector => this.#indexerConnector! - stop = () => this.#indexerConnector!.pollingIndexer = false + stop = () => (this.#indexerConnector!.pollingIndexer = false) stopAndWait = async () => { this.stop() @@ -120,11 +120,11 @@ export default class Queue { for (const [, input] of tx.inputs.entries()) { const previousTxHash = input.previousOutput!.txHash if (previousTxHash === `0x${'0'.repeat(64)}`) { - continue; + continue } if (txHashSet.has(previousTxHash)) { - continue; + continue } fetchTxQueue.push({ txHash: previousTxHash }) @@ -165,10 +165,7 @@ export default class Queue { ) { const output = tx.outputs![inputIndex] if (output) { - output.setDepositOutPoint(new OutPoint( - input.previousOutput!.txHash, - input.previousOutput!.index, - )) + output.setDepositOutPoint(new OutPoint(input.previousOutput!.txHash, input.previousOutput!.index)) } } } @@ -206,8 +203,8 @@ export default class Queue { message: { indexerTipNumber: tip.indexerTipNumber, cacheTipNumber: tip.cacheTipNumber, - timestamp: Date.now() - } + timestamp: Date.now(), + }, }) } else { throw new ShouldInChildProcess() diff --git a/packages/neuron-wallet/src/block-sync-renderer/sync/tx-address-finder.ts b/packages/neuron-wallet/src/block-sync-renderer/sync/tx-address-finder.ts index 37e32d262c..e82b5700d5 100644 --- a/packages/neuron-wallet/src/block-sync-renderer/sync/tx-address-finder.ts +++ b/packages/neuron-wallet/src/block-sync-renderer/sync/tx-address-finder.ts @@ -38,7 +38,7 @@ export default class TxAddressFinder { return [ inputAddressesResult[0] || outputsResult[0], inputAddressesResult[1].concat(outputAddresses), - inputAddressesResult[2].concat(outputsResult[2]) + inputAddressesResult[2].concat(outputsResult[2]), ] } @@ -61,7 +61,7 @@ export default class TxAddressFinder { // anyoneCanPayBlake160s.push(output.lock.args) anyoneCanPayInfos.push({ blake160: output.lock.args, - tokenID: output.type?.args || 'CKBytes' + tokenID: output.type?.args || 'CKBytes', }) } if (this.lockHashes.has(output.lockHash!)) { @@ -90,18 +90,16 @@ export default class TxAddressFinder { let shouldSync = false for (const input of inputs) { const outPoint: OutPoint = input.previousOutput! - const output = await getConnection() - .getRepository(OutputEntity) - .findOne({ - outPointTxHash: outPoint.txHash, - outPointIndex: outPoint.index - }) + const output = await getConnection().getRepository(OutputEntity).findOne({ + outPointTxHash: outPoint.txHash, + outPointIndex: outPoint.index, + }) if (output && this.anyoneCanPayLockHashes.has(output.lockHash)) { shouldSync = true // anyoneCanPayBlake160s.push(output.lockArgs) anyoneCanPayInfos.push({ blake160: output.lockArgs, - tokenID: output.typeArgs || 'CKBytes' + tokenID: output.typeArgs || 'CKBytes', }) } if (output && this.lockHashes.has(output.lockHash)) { diff --git a/packages/neuron-wallet/src/block-sync-renderer/task-wrapper.ts b/packages/neuron-wallet/src/block-sync-renderer/task-wrapper.ts index 00e10d20da..427f9b714a 100644 --- a/packages/neuron-wallet/src/block-sync-renderer/task-wrapper.ts +++ b/packages/neuron-wallet/src/block-sync-renderer/task-wrapper.ts @@ -3,12 +3,12 @@ import Module from 'module' const originalLoad = Module._load -Module._load = function(request: string) { - if (request === 'electron') { +Module._load = function (...args: unknown[]) { + if (args[0] === 'electron') { return {} } - return originalLoad.apply(this, arguments) + return originalLoad.apply(this, args) } export * from './task' diff --git a/packages/neuron-wallet/src/block-sync-renderer/task.ts b/packages/neuron-wallet/src/block-sync-renderer/task.ts index 475aea45c5..ff33424118 100644 --- a/packages/neuron-wallet/src/block-sync-renderer/task.ts +++ b/packages/neuron-wallet/src/block-sync-renderer/task.ts @@ -1,7 +1,6 @@ -// eslint-disable-next-line prettier/prettier import type { LumosCellQuery } from './sync/indexer-connector' import initConnection from '../database/chain/ormconfig' -import { register as registerTxStatusListener, } from './tx-status-listener' +import { register as registerTxStatusListener } from './tx-status-listener' import SyncQueue from './sync/queue' import logger from '../utils/logger' import { ShouldInChildProcess } from '../exceptions' @@ -10,9 +9,18 @@ import env from '../env' let syncQueue: SyncQueue | null export interface WorkerMessage { - type: 'call' | 'response' | 'kill', - id?: number, - channel: 'start' | 'queryIndexer' | 'unmount' | 'cache-tip-block-updated' | 'tx-db-changed' | 'wallet-deleted' | 'address-created' | 'indexer-error' | 'check-and-save-wallet-address' + type: 'call' | 'response' | 'kill' + id?: number + channel: + | 'start' + | 'queryIndexer' + | 'unmount' + | 'cache-tip-block-updated' + | 'tx-db-changed' + | 'wallet-deleted' + | 'address-created' + | 'indexer-error' + | 'check-and-save-wallet-address' message: T } @@ -28,7 +36,6 @@ export interface StartParams { export type QueryIndexerParams = LumosCellQuery export const listener = async ({ type, id, channel, message }: WorkerMessage) => { - if (type === 'kill') { process.exit(0) } @@ -37,13 +44,17 @@ export const listener = async ({ type, id, channel, message }: WorkerMessage) => throw new ShouldInChildProcess() } - if (type !== 'call') { return } + if (type !== 'call') { + return + } let res = null switch (channel) { case 'start': { - if (syncQueue) { return } + if (syncQueue) { + return + } env.fileBasePath = process.env['fileBasePath'] ?? env.fileBasePath @@ -52,20 +63,22 @@ export const listener = async ({ type, id, channel, message }: WorkerMessage) => syncQueue = new SyncQueue(message.url, message.addressMetas, message.indexerUrl) syncQueue.start() - } catch (err) { - logger.error(`Block Sync Task:\t`, err,) + logger.error(`Block Sync Task:\t`, err) } break } case 'unmount': { - if (!syncQueue) { process.exit(0); return } - logger.debug("Sync:\tstopping") + if (!syncQueue) { + process.exit(0) + return + } + logger.debug('Sync:\tstopping') await syncQueue.stopAndWait() syncQueue = null - logger.debug("Sync:\tstopped") + logger.debug('Sync:\tstopped') process.exit(0) break } @@ -77,7 +90,6 @@ export const listener = async ({ type, id, channel, message }: WorkerMessage) => default: { // ignore } - } process.send({ id, type: `response`, channel, message: res }) } @@ -85,4 +97,3 @@ export const listener = async ({ type, id, channel, message }: WorkerMessage) => process.on('message', listener) registerTxStatusListener() - diff --git a/packages/neuron-wallet/src/block-sync-renderer/tx-status-listener.ts b/packages/neuron-wallet/src/block-sync-renderer/tx-status-listener.ts index cb412f3591..7bb9d8dbc9 100644 --- a/packages/neuron-wallet/src/block-sync-renderer/tx-status-listener.ts +++ b/packages/neuron-wallet/src/block-sync-renderer/tx-status-listener.ts @@ -17,20 +17,20 @@ const getTransactionStatus = async (hash: string) => { return { tx: txWithStatus, status: TransactionStatus.Failed, - blockHash: null + blockHash: null, } } if (txWithStatus.txStatus.isCommitted()) { return { tx: txWithStatus.transaction, status: TransactionStatus.Success, - blockHash: txWithStatus.txStatus.blockHash + blockHash: txWithStatus.txStatus.blockHash, } } return { tx: txWithStatus.transaction, status: TransactionStatus.Pending, - blockHash: null + blockHash: null, } } @@ -48,7 +48,7 @@ const trackingStatus = async () => { hash, tx: txWithStatus.tx, status: txWithStatus.status, - blockHash: txWithStatus.blockHash + blockHash: txWithStatus.blockHash, } }) ) diff --git a/packages/neuron-wallet/src/controllers/anyone-can-pay.ts b/packages/neuron-wallet/src/controllers/anyone-can-pay.ts index 1016d8bdb4..b74267ea19 100644 --- a/packages/neuron-wallet/src/controllers/anyone-can-pay.ts +++ b/packages/neuron-wallet/src/controllers/anyone-can-pay.ts @@ -42,7 +42,7 @@ export default class AnyoneCanPayController { return { status: ResponseCode.Success, - result: tx + result: tx, } } @@ -54,7 +54,7 @@ export default class AnyoneCanPayController { const extraCKB = await AnyoneCanPayService.getHoldSUDTCellCapacity(lockScript, tokenID) return { status: ResponseCode.Success, - result: extraCKB + result: extraCKB, } } @@ -79,14 +79,14 @@ export default class AnyoneCanPayController { return { status: ResponseCode.Success, - result: txHash + result: txHash, } } public getScript() { return { status: ResponseCode.Success, - result: new AssetAccountInfo().infos.anyoneCanPay + result: new AssetAccountInfo().infos.anyoneCanPay, } } @@ -94,7 +94,7 @@ export default class AnyoneCanPayController { const tx = await AnyoneCanPayService.generateSudtMigrateAcpTx(params.outPoint, params.acpAddress) return { status: ResponseCode.Success, - result: tx + result: tx, } } } diff --git a/packages/neuron-wallet/src/controllers/api.ts b/packages/neuron-wallet/src/controllers/api.ts index e731218eee..82acd734a2 100644 --- a/packages/neuron-wallet/src/controllers/api.ts +++ b/packages/neuron-wallet/src/controllers/api.ts @@ -10,7 +10,7 @@ import { MenuItem, Menu, screen, - BrowserWindow + BrowserWindow, } from 'electron' import { t } from 'i18next' import path from 'path' @@ -51,7 +51,7 @@ import { GenerateAnyoneCanPayTxParams, SendAnyoneCanPayTxParams } from './anyone import { DeviceInfo, ExtendedPublicKey } from '../services/hardware/common' import HardwareController from './hardware' import OfflineSignController from './offline-sign' -import SUDTController from "./sudt" +import SUDTController from './sudt' import SyncedBlockNumber from '../models/synced-block-number' import IndexerService from '../services/indexer' import MultisigConfigModel from '../models/multisig-config' @@ -62,7 +62,6 @@ import NodeService from '../services/node' export type Command = 'export-xpubkey' | 'import-xpubkey' | 'delete-wallet' | 'backup-wallet' | 'migrate-acp' // Handle channel messages from renderer process and user actions. export default class ApiController { - // eslint-disable-next-line prettier/prettier #walletsController = new WalletsController() #transactionsController = new TransactionsController() #daoController = new DaoController() @@ -90,8 +89,9 @@ export default class ApiController { break } case 'import-xpubkey': { - this.#walletsController.importXPubkey() - .catch(error => { dialog.showMessageBox({ type: 'error', buttons: [], message: error.message }) }) + this.#walletsController.importXPubkey().catch(error => { + dialog.showMessageBox({ type: 'error', buttons: [], message: error.message }) + }) break } case 'delete-wallet': @@ -99,7 +99,6 @@ export default class ApiController { // delete/backup wallet with wallet id this.#walletsController.requestPassword(params, command) break - } case 'migrate-acp': { this.#assetAccountController.showACPMigrationDialog(false) @@ -135,7 +134,7 @@ export default class ApiController { handle('get-system-codehash', async () => { return { status: ResponseCode.Success, - result: SystemScriptInfo.SECP_CODE_HASH + result: SystemScriptInfo.SECP_CODE_HASH, } }) @@ -147,7 +146,7 @@ export default class ApiController { const result = await dialog.showOpenDialog(params) return { status: ResponseCode.Success, - result + result, } }) @@ -156,7 +155,7 @@ export default class ApiController { const result = await dialog.showOpenDialog(win, params) return { status: ResponseCode.Success, - result + result, } }) @@ -168,7 +167,7 @@ export default class ApiController { const result = screen.getAllDisplays().map(d => d.size) return { status: ResponseCode.Success, - result + result, } }) @@ -179,37 +178,42 @@ export default class ApiController { const currentWallet = this.#walletsController.getCurrent().result const wallets = walletsService.getAll() - const [ - currentNetworkID = '', - networks = [], - syncedBlockNumber = '0', - connectionStatus = false, - ] = await Promise.all([ - networksService.getCurrentID(), - networksService.getAll(), - new SyncedBlockNumber().getNextBlock().then( - blockNumber => blockNumber.toString() - ).catch(() => '0'), - new Promise(resolve => { - ConnectionStatusSubject.pipe(take(1)).subscribe( - status => { resolve(status) }, - () => { resolve(false) }, - () => { resolve(false) } - ) - }), - ]) + const [currentNetworkID = '', networks = [], syncedBlockNumber = '0', connectionStatus = false] = + await Promise.all([ + networksService.getCurrentID(), + networksService.getAll(), + new SyncedBlockNumber() + .getNextBlock() + .then(blockNumber => blockNumber.toString()) + .catch(() => '0'), + new Promise(resolve => { + ConnectionStatusSubject.pipe(take(1)).subscribe( + status => { + resolve(status) + }, + () => { + resolve(false) + }, + () => { + resolve(false) + } + ) + }), + ]) const addresses: Controller.Address[] = await (currentWallet ? this.#walletsController.getAllAddresses(currentWallet.id).then(res => res.result) : []) const transactions = currentWallet - ? await this.#transactionsController.getAll({ - pageNo: 1, - pageSize: 15, - keywords: '', - walletID: currentWallet.id, - }).then(res => res.result) + ? await this.#transactionsController + .getAll({ + pageNo: 1, + pageSize: 15, + keywords: '', + walletID: currentWallet.id, + }) + .then(res => res.result) : [] const initState = { @@ -226,26 +230,28 @@ export default class ApiController { return { status: ResponseCode.Success, result: initState } }) - handle('open-in-window', async (_, { url, title }: { url: string, title: string }) => { + handle('open-in-window', async (_, { url, title }: { url: string; title: string }) => { showWindow(url, title) }) - handle('request-open-in-explorer', (_, { key, type }: { key: string, type: 'transaction' }) => { + handle('request-open-in-explorer', (_, { key, type }: { key: string; type: 'transaction' }) => { if (type !== 'transaction' || !key) { return } - dialog.showMessageBox({ - type: 'question', - title: t(`open-in-explorer.title`), - message: t(`open-in-explorer.message`, { type: t(`open-in-explorer.${type}`), key }), - defaultId: 0, - buttons: [t('common.ok'), t('common.cancel'),] - }).then(({ response }) => { - if (response === 0) { - const base = NetworksService.getInstance().explorerUrl() - shell.openExternal(`${base}/${type}/${key}`) - } - }) + dialog + .showMessageBox({ + type: 'question', + title: t(`open-in-explorer.title`), + message: t(`open-in-explorer.message`, { type: t(`open-in-explorer.${type}`), key }), + defaultId: 0, + buttons: [t('common.ok'), t('common.cancel')], + }) + .then(({ response }) => { + if (response === 0) { + const base = NetworksService.getInstance().explorerUrl() + shell.openExternal(`${base}/${type}/${key}`) + } + }) }) handle('handle-view-error', async (_, error: string) => { @@ -255,13 +261,13 @@ export default class ApiController { }) handle('set-locale', async (_, locale: Locale) => { - return SettingsService.getInstance().locale = locale + return (SettingsService.getInstance().locale = locale) }) handle('is-ckb-run-external', () => { return { status: ResponseCode.Success, - result: NodeService.getInstance().isCkbNodeExternal + result: NodeService.getInstance().isCkbNodeExternal, } }) // Wallets @@ -310,42 +316,78 @@ export default class ApiController { return this.#walletsController.getAllAddresses(id) }) - handle('update-address-description', async (_, params: { walletID: string, address: string, description: string }) => { - return this.#walletsController.updateAddressDescription(params) - }) - - handle('request-password', async (_, { walletID, action }: { walletID: string, action: 'delete-wallet' | 'backup-wallet' }) => { - this.#walletsController.requestPassword(walletID, action) - }) - - handle('send-tx', async (_, params: { walletID: string, tx: Transaction, password: string, description?: string, multisigConfig?: MultisigConfigModel }) => { - return this.#walletsController.sendTx({ - ...params, - multisigConfig: params.multisigConfig ? MultisigConfigModel.fromObject(params.multisigConfig) : undefined - }) - }) - - handle('generate-tx', async (_, params: { walletID: string, items: { address: string, capacity: string }[], fee: string, feeRate: string }) => { - return this.#walletsController.generateTx(params) - }) - - handle('generate-send-all-tx', async (_, params: { walletID: string, items: { address: string, capacity: string }[], fee: string, feeRate: string }) => { - return this.#walletsController.generateSendingAllTx(params) - }) - - handle('generate-multisig-tx', async (_, params: { items: { address: string, capacity: string }[], multisigConfig: MultisigConfigModel }) => { - return this.#walletsController.generateMultisigTx({ - items: params.items, - multisigConfig: MultisigConfigModel.fromObject(params.multisigConfig) - }) - }) + handle( + 'update-address-description', + async (_, params: { walletID: string; address: string; description: string }) => { + return this.#walletsController.updateAddressDescription(params) + } + ) - handle('generate-multisig-send-all-tx', async (_, params: { items: { address: string, capacity: string }[], multisigConfig: MultisigConfigModel }) => { - return this.#walletsController.generateMultisigSendAllTx({ - items: params.items, - multisigConfig: MultisigConfigModel.fromObject(params.multisigConfig) - }) - }) + handle( + 'request-password', + async (_, { walletID, action }: { walletID: string; action: 'delete-wallet' | 'backup-wallet' }) => { + this.#walletsController.requestPassword(walletID, action) + } + ) + + handle( + 'send-tx', + async ( + _, + params: { + walletID: string + tx: Transaction + password: string + description?: string + multisigConfig?: MultisigConfigModel + } + ) => { + return this.#walletsController.sendTx({ + ...params, + multisigConfig: params.multisigConfig ? MultisigConfigModel.fromObject(params.multisigConfig) : undefined, + }) + } + ) + + handle( + 'generate-tx', + async ( + _, + params: { walletID: string; items: { address: string; capacity: string }[]; fee: string; feeRate: string } + ) => { + return this.#walletsController.generateTx(params) + } + ) + + handle( + 'generate-send-all-tx', + async ( + _, + params: { walletID: string; items: { address: string; capacity: string }[]; fee: string; feeRate: string } + ) => { + return this.#walletsController.generateSendingAllTx(params) + } + ) + + handle( + 'generate-multisig-tx', + async (_, params: { items: { address: string; capacity: string }[]; multisigConfig: MultisigConfigModel }) => { + return this.#walletsController.generateMultisigTx({ + items: params.items, + multisigConfig: MultisigConfigModel.fromObject(params.multisigConfig), + }) + } + ) + + handle( + 'generate-multisig-send-all-tx', + async (_, params: { items: { address: string; capacity: string }[]; multisigConfig: MultisigConfigModel }) => { + return this.#walletsController.generateMultisigSendAllTx({ + items: params.items, + multisigConfig: MultisigConfigModel.fromObject(params.multisigConfig), + }) + } + ) handle('generate-mnemonic', async () => { return this.#walletsController.generateMnemonic() @@ -361,23 +403,26 @@ export default class ApiController { return this.#transactionsController.getAll(params) }) - handle('get-transaction', async (_, { walletID, hash }: { walletID: string, hash: string }) => { + handle('get-transaction', async (_, { walletID, hash }: { walletID: string; hash: string }) => { return this.#transactionsController.get(walletID, hash) }) - handle('update-transaction-description', async (_, params: { walletID: string; hash: string; description: string }) => { - return this.#transactionsController.updateDescription(params) - }) + handle( + 'update-transaction-description', + async (_, params: { walletID: string; hash: string; description: string }) => { + return this.#transactionsController.updateDescription(params) + } + ) handle('show-transaction-details', async (_, hash: string) => { const win = showWindow( `#/transaction/${hash}`, t(`messageBox.transaction.title`, { hash }), { - height: 750 + height: 750, }, undefined, - (win) => win.webContents.getURL().endsWith(`#/transaction/${hash}`) + win => win.webContents.getURL().endsWith(`#/transaction/${hash}`) ) if (win.isVisible()) return @@ -401,30 +446,54 @@ export default class ApiController { return this.#daoController.getDaoCells(params) }) - handle('generate-dao-deposit-tx', async (_, params: { walletID: string, capacity: string, fee: string, feeRate: string }) => { - return this.#daoController.generateDepositTx(params) - }) - - handle('generate-dao-deposit-all-tx', async (_, params: { walletID: string, isBalanceReserved: boolean, fee: string, feeRate: string }) => { - return this.#daoController.generateDepositAllTx(params) - }) + handle( + 'generate-dao-deposit-tx', + async (_, params: { walletID: string; capacity: string; fee: string; feeRate: string }) => { + return this.#daoController.generateDepositTx(params) + } + ) - handle('start-withdraw-from-dao', async (_, params: { walletID: string, outPoint: OutPoint, fee: string, feeRate: string }) => { - return this.#daoController.startWithdrawFromDao(params) - }) + handle( + 'generate-dao-deposit-all-tx', + async (_, params: { walletID: string; isBalanceReserved: boolean; fee: string; feeRate: string }) => { + return this.#daoController.generateDepositAllTx(params) + } + ) - handle('withdraw-from-dao', async (_, params: { walletID: string, depositOutPoint: OutPoint, withdrawingOutPoint: OutPoint, fee: string, feeRate: string }) => { - return this.#daoController.withdrawFromDao(params) - }); + handle( + 'start-withdraw-from-dao', + async (_, params: { walletID: string; outPoint: OutPoint; fee: string; feeRate: string }) => { + return this.#daoController.startWithdrawFromDao(params) + } + ) + + handle( + 'withdraw-from-dao', + async ( + _, + params: { + walletID: string + depositOutPoint: OutPoint + withdrawingOutPoint: OutPoint + fee: string + feeRate: string + } + ) => { + return this.#daoController.withdrawFromDao(params) + } + ) // Customized Asset handle('get-customized-asset-cells', async (_, params: Controller.Params.GetCustomizedAssetCellsParams) => { return this.#customizedAssetsController.getCustomizedAssetCells(params) }) - handle('generate-withdraw-customized-cell-tx', async (_, params: Controller.Params.GenerateWithdrawCustomizedCellTxParams) => { - return this.#customizedAssetsController.generateWithdrawCustomizedCellTx(params) - }) + handle( + 'generate-withdraw-customized-cell-tx', + async (_, params: Controller.Params.GenerateWithdrawCustomizedCellTxParams) => { + return this.#customizedAssetsController.generateWithdrawCustomizedCellTx(params) + } + ) handle('generate-transfer-nft-tx', async (_, params: Controller.Params.GenerateTransferNftTxParams) => { return this.#customizedAssetsController.generateTransferNftTx(params) @@ -440,7 +509,7 @@ export default class ApiController { return this.#networksController.create({ name, remote, type, genesisHash: '0x', chain: 'ckb', id: '' }) }) - handle('update-network', async (_, { networkID, options }: { networkID: string, options: Partial }) => { + handle('update-network', async (_, { networkID, options }: { networkID: string; options: Partial }) => { return this.#networksController.update(networkID, options) }) @@ -484,7 +553,7 @@ export default class ApiController { handle('get-ckb-node-data-path', () => { return { status: ResponseCode.Success, - result: SettingsService.getInstance().ckbDataPath + result: SettingsService.getInstance().ckbDataPath, } }) @@ -493,7 +562,7 @@ export default class ApiController { const { response } = await dialog.showMessageBox(BrowserWindow.getFocusedWindow()!, { type: 'info', message: t('messages.no-exist-ckb-node-data', { path: dataPath }), - buttons: [t('common.ok'), t('common.cancel')] + buttons: [t('common.ok'), t('common.cancel')], }) if (response === 1) { return { @@ -506,7 +575,7 @@ export default class ApiController { await startMonitor('ckb', true) return { status: ResponseCode.Success, - result: SettingsService.getInstance().ckbDataPath + result: SettingsService.getInstance().ckbDataPath, } }) @@ -559,7 +628,7 @@ export default class ApiController { return this.#assetAccountController.getAll(params) }) - handle("get-asset-account", async (_, params: { walletID: string, id: number }) => { + handle('get-asset-account', async (_, params: { walletID: string; id: number }) => { return this.#assetAccountController.getAccount(params) }) @@ -588,7 +657,7 @@ export default class ApiController { return this.#anyoneCanPayController.generateTx(params) }) - handle('get-hold-sudt-cell-capacity', async (_, params: { address: string, tokenID: string }) => { + handle('get-hold-sudt-cell-capacity', async (_, params: { address: string; tokenID: string }) => { return this.#anyoneCanPayController.getHoldSudtCellCapacity(params.address, params.tokenID) }) @@ -608,7 +677,7 @@ export default class ApiController { return this.#sudtController.getSUDTTypeScriptHash(params) }) - handle('generate-destroy-asset-account-tx', async (_, params: { walletID: string, id: number }) => { + handle('generate-destroy-asset-account-tx', async (_, params: { walletID: string; id: number }) => { return this.#assetAccountController.destoryAssetAccount(params) }) @@ -657,14 +726,14 @@ export default class ApiController { handle('sign-and-export-transaction', async (_, params) => { return this.#offlineSignController.signAndExportTransaction({ ...params, - multisigConfig: params?.multisigConfig ? MultisigConfigModel.fromObject(params?.multisigConfig) : undefined + multisigConfig: params?.multisigConfig ? MultisigConfigModel.fromObject(params?.multisigConfig) : undefined, }) }) handle('sign-and-broadcast-transaction', async (_, params) => { return this.#offlineSignController.signAndBroadcastTransaction({ ...params, - multisigConfig: params?.multisigConfig ? MultisigConfigModel.fromObject(params?.multisigConfig) : undefined + multisigConfig: params?.multisigConfig ? MultisigConfigModel.fromObject(params?.multisigConfig) : undefined, }) }) @@ -712,7 +781,7 @@ export default class ApiController { } // Register handler, warp and serialize API response - #handleChannel = (channel: string, listener: (event: IpcMainInvokeEvent, ...args: any[]) => (Promise) | (any)) => { + #handleChannel = (channel: string, listener: (event: IpcMainInvokeEvent, ...args: any[]) => Promise | any) => { ipcMain.handle(channel, async (event, args) => { try { const res = await listener(event, args) diff --git a/packages/neuron-wallet/src/controllers/app/index.ts b/packages/neuron-wallet/src/controllers/app/index.ts index 377247c796..ac95e2847d 100644 --- a/packages/neuron-wallet/src/controllers/app/index.ts +++ b/packages/neuron-wallet/src/controllers/app/index.ts @@ -130,8 +130,8 @@ export default class AppController { nodeIntegration: true, devTools: env.isDevMode, contextIsolation: false, - preload: path.join(__dirname, './preload.js') - } + preload: path.join(__dirname, './preload.js'), + }, }) windowState.manage(this.mainWindow) diff --git a/packages/neuron-wallet/src/controllers/app/menu.ts b/packages/neuron-wallet/src/controllers/app/menu.ts index 588e8c7001..426c01e940 100644 --- a/packages/neuron-wallet/src/controllers/app/menu.ts +++ b/packages/neuron-wallet/src/controllers/app/menu.ts @@ -23,7 +23,7 @@ enum URL { ImportMnemonic = '/wizard/mnemonic/import', ImportKeystore = '/keystore/import', ImportHardware = '/import-hardware', - OfflineSign = '/offline-sign' + OfflineSign = '/offline-sign', } enum ExternalURL { @@ -31,11 +31,11 @@ enum ExternalURL { Repository = 'https://github.com/nervosnetwork/neuron', Issues = 'https://github.com/nervosnetwork/neuron/issues', Doc = 'https://docs.nervos.org/docs/basics/tools#neuron-wallet', - MailUs = 'neuron@magickbase.com' + MailUs = 'neuron@magickbase.com', } const separator: MenuItemConstructorOptions = { - type: 'separator' + type: 'separator', } const showAbout = () => { @@ -61,7 +61,7 @@ const showAbout = () => { message: app.name, detail: applicationVersion, buttons: ['OK'], - cancelId: 0 + cancelId: 0, } dialog.showMessageBox(options) return @@ -130,11 +130,11 @@ const updateApplicationMenu = (mainWindow: BrowserWindow | null) => { { id: 'about', label: t('application-menu.neuron.about', { - app: app.name + app: app.name, }), click: () => { showAbout() - } + }, }, { label: t('application-menu.neuron.check-updates'), @@ -142,7 +142,7 @@ const updateApplicationMenu = (mainWindow: BrowserWindow | null) => { click: () => { new UpdateController().checkUpdates() showSettings() - } + }, }, separator, { @@ -150,16 +150,16 @@ const updateApplicationMenu = (mainWindow: BrowserWindow | null) => { enabled: isMainWindow, label: t('application-menu.neuron.preferences'), accelerator: 'CmdOrCtrl+,', - click: showSettings + click: showSettings, }, separator, { label: t('application-menu.neuron.quit', { - app: app.name + app: app.name, }), - role: 'quit' - } - ] + role: 'quit', + }, + ], } const selectWalletMenu: MenuItemConstructorOptions[] = wallets.map(wallet => { @@ -170,7 +170,7 @@ const updateApplicationMenu = (mainWindow: BrowserWindow | null) => { checked: currentWallet && wallet.id === currentWallet.id, click: () => { WalletsService.getInstance().setCurrent(wallet.id) - } + }, } }) @@ -185,7 +185,7 @@ const updateApplicationMenu = (mainWindow: BrowserWindow | null) => { label: t('application-menu.wallet.create-new'), click: () => { navigateTo(URL.CreateWallet) - } + }, }, { id: 'import', @@ -196,14 +196,14 @@ const updateApplicationMenu = (mainWindow: BrowserWindow | null) => { label: t('application-menu.wallet.import-mnemonic'), click: () => { navigateTo(URL.ImportMnemonic) - } + }, }, { id: 'import-with-keystore', label: t('application-menu.wallet.import-keystore'), click: () => { navigateTo(URL.ImportKeystore) - } + }, }, { id: 'import-with-xpubkey', @@ -213,16 +213,16 @@ const updateApplicationMenu = (mainWindow: BrowserWindow | null) => { if (window) { CommandSubject.next({ winID: window.id, type: 'import-xpubkey', payload: null, dispatchToUI: false }) } - } + }, }, { id: 'import-with-hardware', label: t('application-menu.wallet.import-hardware'), click: () => { importHardware(URL.ImportHardware) - } - } - ] + }, + }, + ], }, separator, { @@ -234,7 +234,7 @@ const updateApplicationMenu = (mainWindow: BrowserWindow | null) => { return } requestPassword(currentWallet.id, 'backup-wallet') - } + }, }, { id: 'export-xpubkey', @@ -250,10 +250,10 @@ const updateApplicationMenu = (mainWindow: BrowserWindow | null) => { winID: window.id, type: 'export-xpubkey', payload: currentWallet.id, - dispatchToUI: false + dispatchToUI: false, }) } - } + }, }, { id: 'delete', @@ -264,9 +264,9 @@ const updateApplicationMenu = (mainWindow: BrowserWindow | null) => { return } requestPassword(currentWallet.id, 'delete-wallet') - } - } - ] + }, + }, + ], } const editMenuItem: MenuItemConstructorOptions = { @@ -275,22 +275,22 @@ const updateApplicationMenu = (mainWindow: BrowserWindow | null) => { submenu: [ { label: t('application-menu.edit.cut'), - role: 'cut' + role: 'cut', }, { label: t('application-menu.edit.copy'), - role: 'copy' + role: 'copy', }, { label: t('application-menu.edit.paste'), - role: 'paste' + role: 'paste', }, separator, { label: t('application-menu.edit.selectall'), - role: 'selectAll' - } - ] + role: 'selectAll', + }, + ], } const toolsMenuItem: MenuItemConstructorOptions = { @@ -303,9 +303,9 @@ const updateApplicationMenu = (mainWindow: BrowserWindow | null) => { click: () => { const currentWallet = walletsService.getCurrent() showWindow(`#/sign-verify/${currentWallet!.id}`, t(`messageBox.sign-and-verify.title`), { - width: 900 + width: 900, }) - } + }, }, { label: t('application-menu.tools.multisig-address'), @@ -319,11 +319,11 @@ const updateApplicationMenu = (mainWindow: BrowserWindow | null) => { width: 900, maxWidth: 900, minWidth: 900, - resizable: true + resizable: true, }, ['multisig-output-update'] ) - } + }, }, { label: t('application-menu.tools.clear-sync-data'), @@ -335,12 +335,12 @@ const updateApplicationMenu = (mainWindow: BrowserWindow | null) => { message: t('messageBox.clear-sync-data.message'), buttons: [t('messageBox.button.confirm'), t('messageBox.button.discard')], defaultId: 0, - cancelId: 1 + cancelId: 1, }) if (res.response === 0) { await clearCkbNodeCache() } - } + }, }, { label: t('application-menu.tools.offline-sign'), @@ -352,9 +352,9 @@ const updateApplicationMenu = (mainWindow: BrowserWindow | null) => { } const { json, filePath } = result loadTransaction(URL.OfflineSign, json, filePath) - } - } - ] + }, + }, + ], } const windowMenuItem: MenuItemConstructorOptions = { @@ -364,13 +364,13 @@ const updateApplicationMenu = (mainWindow: BrowserWindow | null) => { submenu: [ { label: t('application-menu.window.minimize'), - role: 'minimize' + role: 'minimize', }, { label: t('application-menu.window.close'), - role: 'close' - } - ] + role: 'close', + }, + ], } const helpSubmenu: MenuItemConstructorOptions[] = [ @@ -378,26 +378,26 @@ const updateApplicationMenu = (mainWindow: BrowserWindow | null) => { label: t('application-menu.help.documentation'), click: () => { shell.openExternal(ExternalURL.Doc) - } + }, }, separator, { label: t('application-menu.help.nervos-website'), click: () => { shell.openExternal(ExternalURL.Website) - } + }, }, { label: t('application-menu.help.source-code'), click: () => { shell.openExternal(ExternalURL.Repository) - } + }, }, { label: t('application-menu.help.report-issue'), click: () => { shell.openExternal(ExternalURL.Issues) - } + }, }, { label: t('application-menu.help.contact-us'), @@ -408,10 +408,10 @@ const updateApplicationMenu = (mainWindow: BrowserWindow | null) => { buttons: [ t(`messageBox.button.discard`), t(`messageBox.mail-us.copy-mail-addr`), - t(`messageBox.mail-us.open-client`) + t(`messageBox.mail-us.open-client`), ], defaultId: 1, - cancelId: 0 + cancelId: 0, }) switch (methodId) { @@ -432,7 +432,7 @@ const updateApplicationMenu = (mainWindow: BrowserWindow | null) => { message: t(`messageBox.mail-us.fail-message`), buttons: [t(`messageBox.button.discard`), t(`messageBox.mail-us.copy-mail-addr`)], defaultId: 1, - cancelId: 0 + cancelId: 0, }) if (subMethodId === 1) { clipboard.writeText(ExternalURL.MailUs) @@ -444,21 +444,21 @@ const updateApplicationMenu = (mainWindow: BrowserWindow | null) => { return } } - } + }, }, { label: t('application-menu.help.export-debug-info'), click: () => { new ExportDebugController().export() - } - } + }, + }, ] if (!isMac) { helpSubmenu.push(separator) helpSubmenu.push({ id: 'preference', label: t(SETTINGS_WINDOW_TITLE), - click: showSettings + click: showSettings, }) helpSubmenu.push({ label: t('application-menu.neuron.check-updates'), @@ -466,16 +466,16 @@ const updateApplicationMenu = (mainWindow: BrowserWindow | null) => { click: () => { new UpdateController().checkUpdates() showSettings() - } + }, }) helpSubmenu.push({ id: 'about', label: t('application-menu.neuron.about', { - app: app.name + app: app.name, }), click: () => { showAbout() - } + }, }) } @@ -483,7 +483,7 @@ const updateApplicationMenu = (mainWindow: BrowserWindow | null) => { id: 'help', label: t('application-menu.help.label'), role: 'help', - submenu: helpSubmenu + submenu: helpSubmenu, } const developMenuItem: MenuItemConstructorOptions = { @@ -492,17 +492,17 @@ const updateApplicationMenu = (mainWindow: BrowserWindow | null) => { submenu: [ { label: t('application-menu.develop.reload'), - role: 'reload' + role: 'reload', }, { label: t('application-menu.develop.force-reload'), - role: 'forceReload' + role: 'forceReload', }, { label: t('application-menu.develop.toggle-dev-tools'), - role: 'toggleDevTools' - } - ] + role: 'toggleDevTools', + }, + ], } const applicationMenuTemplate = env.isDevMode diff --git a/packages/neuron-wallet/src/controllers/app/preload.ts b/packages/neuron-wallet/src/controllers/app/preload.ts index 45d0a3e900..fe11b5062f 100644 --- a/packages/neuron-wallet/src/controllers/app/preload.ts +++ b/packages/neuron-wallet/src/controllers/app/preload.ts @@ -15,8 +15,8 @@ if (process.env.NODE_ENV === 'development') { Object.defineProperty(window, '__devtron', { value: { require, - process - } + process, + }, }) } @@ -24,5 +24,5 @@ window.electron = { clipboard, nativeImage, ipcRenderer, - shell + shell, } diff --git a/packages/neuron-wallet/src/controllers/app/show-window.ts b/packages/neuron-wallet/src/controllers/app/show-window.ts index fe5c917a94..6f436b3b67 100644 --- a/packages/neuron-wallet/src/controllers/app/show-window.ts +++ b/packages/neuron-wallet/src/controllers/app/show-window.ts @@ -8,7 +8,7 @@ const showWindow = ( title: string, options?: Electron.BrowserWindowConstructorOptions, channels?: string[], - comparator: (win: BrowserWindow) => boolean = (win) => win.getTitle() === title + comparator: (win: BrowserWindow) => boolean = win => win.getTitle() === title ): BrowserWindow => { const opened = BrowserWindow.getAllWindows().find(comparator) if (opened) { @@ -31,9 +31,9 @@ const showWindow = ( nodeIntegration: true, devTools: env.isDevMode, contextIsolation: false, - preload: path.join(__dirname, './preload.js') + preload: path.join(__dirname, './preload.js'), }, - ...options + ...options, }) if (channels) { AppController.getInstance().registerChannels(win, channels) diff --git a/packages/neuron-wallet/src/controllers/app/subscribe.ts b/packages/neuron-wallet/src/controllers/app/subscribe.ts index 048395a1c6..ea189ca28f 100644 --- a/packages/neuron-wallet/src/controllers/app/subscribe.ts +++ b/packages/neuron-wallet/src/controllers/app/subscribe.ts @@ -89,7 +89,7 @@ export const subscribe = (dispatcher: AppResponder) => { }) MultisigOutputChangedSubject.getSubject().subscribe(params => [ - dispatcher.sendMessage('multisig-output-update', params) + dispatcher.sendMessage('multisig-output-update', params), ]) MigrateSubject.getSubject().subscribe(async message => { @@ -111,7 +111,7 @@ export const subscribe = (dispatcher: AppResponder) => { title: t('messageBox.migrate-failed.title'), message: t('messageBox.migrate-failed.message', { reason: message.reason }), cancelId: 0, - noLink: true + noLink: true, }) if (dialogResponse.response === 0) { await clearCkbNodeCache() diff --git a/packages/neuron-wallet/src/controllers/asset-account.ts b/packages/neuron-wallet/src/controllers/asset-account.ts index 4854e41052..36e6e1fda0 100644 --- a/packages/neuron-wallet/src/controllers/asset-account.ts +++ b/packages/neuron-wallet/src/controllers/asset-account.ts @@ -85,13 +85,13 @@ export default class AssetAccountController { const result = assetAccounts.map(aa => { return { ...aa, - address: scriptToAddress(assetAccountInfo.generateAnyoneCanPayScript(aa.blake160), isMainnet) + address: scriptToAddress(assetAccountInfo.generateAnyoneCanPayScript(aa.blake160), isMainnet), } }) return { status: ResponseCode.Success, - result + result, } } @@ -109,7 +109,7 @@ export default class AssetAccountController { return { status: ResponseCode.Success, - result: tx + result: tx, } } @@ -130,14 +130,12 @@ export default class AssetAccountController { status: ResponseCode.Success, result: { ...account, - address: scriptToAddress(assetAccountInfo.generateAnyoneCanPayScript(account.blake160), isMainnet) - } + address: scriptToAddress(assetAccountInfo.generateAnyoneCanPayScript(account.blake160), isMainnet), + }, } } - public async generateCreateTx( - params: GenerateCreateAssetAccountTxParams - ): Promise< + public async generateCreateTx(params: GenerateCreateAssetAccountTxParams): Promise< Controller.Response<{ assetAccount: AssetAccount tx: Transaction @@ -160,7 +158,7 @@ export default class AssetAccountController { return { status: ResponseCode.Success, - result + result, } } @@ -178,7 +176,7 @@ export default class AssetAccountController { return { status: ResponseCode.Success, - result: txHash + result: txHash, } } @@ -187,7 +185,7 @@ export default class AssetAccountController { return { status: ResponseCode.Success, - result: undefined + result: undefined, } } @@ -195,7 +193,7 @@ export default class AssetAccountController { const result = await AssetAccountService.getTokenInfoList() return { status: ResponseCode.Success, - result + result, } } @@ -213,12 +211,12 @@ export default class AssetAccountController { title: t(`${I18N_PATH}.title`), message: t(`${I18N_PATH}.message`), cancelId: 0, - noLink: true + noLink: true, }) return { status: ResponseCode.Success, - result: txHash + result: txHash, } } @@ -229,14 +227,14 @@ export default class AssetAccountController { const currentWallet = walletsService.getCurrent() if (!currentWallet) { return { - status: ResponseCode.Success + status: ResponseCode.Success, } } const walletId = currentWallet.id if (!allowMultipleOpen && this.displayedACPMigrationDialogByWalletIds.has(walletId)) { return { - status: ResponseCode.Success + status: ResponseCode.Success, } } @@ -244,21 +242,21 @@ export default class AssetAccountController { if (syncStatus !== SyncStatus.SyncCompleted || BrowserWindow.getAllWindows().length !== 1) { return { - status: ResponseCode.Success + status: ResponseCode.Success, } } const window = BrowserWindow.getFocusedWindow() if (!window) { return { - status: ResponseCode.Success + status: ResponseCode.Success, } } const tx = await TransactionGenerator.generateMigrateLegacyACPTx(walletId) if (!tx) { return { - status: ResponseCode.Success + status: ResponseCode.Success, } } @@ -274,7 +272,7 @@ export default class AssetAccountController { message: t(`${I18N_PATH}.message`), detail: t(`${I18N_PATH}.detail`), cancelId: 0, - noLink: true + noLink: true, }) .then(({ response }) => { switch (response) { @@ -283,7 +281,7 @@ export default class AssetAccountController { winID: window.id, type: 'migrate-acp', payload: walletId, - dispatchToUI: true + dispatchToUI: true, }) return true } @@ -294,7 +292,7 @@ export default class AssetAccountController { }) .then(result => ({ status: ResponseCode.Success, - result + result, })) } @@ -310,7 +308,7 @@ export default class AssetAccountController { ) return { status: ResponseCode.Success, - result: tx + result: tx, } } @@ -321,7 +319,7 @@ export default class AssetAccountController { const { tx, assetAccount } = await AssetAccountService.generateClaimChequeTx(walletID, chequeCellOutPoint) return { status: ResponseCode.Success, - result: { tx, assetAccount } + result: { tx, assetAccount }, } } @@ -332,7 +330,7 @@ export default class AssetAccountController { const tx = await AssetAccountService.generateWithdrawChequeTx(chequeCellOutPoint) return { status: ResponseCode.Success, - result: { tx } + result: { tx }, } } } diff --git a/packages/neuron-wallet/src/controllers/customized-assets.ts b/packages/neuron-wallet/src/controllers/customized-assets.ts index 291e922fff..e2a63db5a8 100644 --- a/packages/neuron-wallet/src/controllers/customized-assets.ts +++ b/packages/neuron-wallet/src/controllers/customized-assets.ts @@ -22,7 +22,7 @@ export default class CustomizedAssetsController { return { status: ResponseCode.Success, - result + result, } } @@ -47,7 +47,7 @@ export default class CustomizedAssetsController { return { status: ResponseCode.Success, - result: tx + result: tx, } } @@ -81,7 +81,7 @@ export default class CustomizedAssetsController { return { status: ResponseCode.Success, - result: tx + result: tx, } } } diff --git a/packages/neuron-wallet/src/controllers/dao.ts b/packages/neuron-wallet/src/controllers/dao.ts index 991ede2eea..e460b0b13a 100644 --- a/packages/neuron-wallet/src/controllers/dao.ts +++ b/packages/neuron-wallet/src/controllers/dao.ts @@ -17,7 +17,7 @@ export default class DaoController { return { status: ResponseCode.Success, - result: cells + result: cells, } } @@ -39,7 +39,7 @@ export default class DaoController { ) return { status: ResponseCode.Success, - result: tx + result: tx, } } @@ -61,7 +61,7 @@ export default class DaoController { ) return { status: ResponseCode.Success, - result: tx + result: tx, } } @@ -83,7 +83,7 @@ export default class DaoController { ) return { status: ResponseCode.Success, - result: tx + result: tx, } } @@ -107,7 +107,7 @@ export default class DaoController { ) return { status: ResponseCode.Success, - result: tx + result: tx, } } } diff --git a/packages/neuron-wallet/src/controllers/export-debug.ts b/packages/neuron-wallet/src/controllers/export-debug.ts index a32cd4d738..0d3d36a267 100644 --- a/packages/neuron-wallet/src/controllers/export-debug.ts +++ b/packages/neuron-wallet/src/controllers/export-debug.ts @@ -13,14 +13,13 @@ import redistCheck from '../utils/redist-check' import SettingsService from '../services/settings' export default class ExportDebugController { - // eslint-disable-next-line prettier/prettier #I18N_PATH = 'export-debug-info' #ANONYMOUS_ADDRESS = 'http://****:port' private archive: archiver.Archiver constructor() { this.archive = archiver('zip', { - zlib: { level: 9 } + zlib: { level: 9 }, }) this.archive.on('error', err => { dialog.showErrorBox(t('common.error'), err.message) @@ -31,17 +30,22 @@ export default class ExportDebugController { try { const { canceled, filePath } = await dialog.showSaveDialog({ title: t(`${this.#I18N_PATH}.export-debug-info`), - defaultPath: `neuron_debug_${Date.now()}.zip` + defaultPath: `neuron_debug_${Date.now()}.zip`, }) if (canceled || !filePath) { return } this.archive.pipe(fs.createWriteStream(filePath)) - await Promise.all([this.addStatusFile(), this.addBundledCKBLog(), this.addLogFiles(), this.addHdPublicKeyInfoCsv()]) + await Promise.all([ + this.addStatusFile(), + this.addBundledCKBLog(), + this.addLogFiles(), + this.addHdPublicKeyInfoCsv(), + ]) await this.archive.finalize() dialog.showMessageBox({ type: 'info', - message: t(`${this.#I18N_PATH}.debug-info-exported`, { file: filePath }) + message: t(`${this.#I18N_PATH}.debug-info-exported`, { file: filePath }), }) } catch (err) { dialog.showErrorBox(t('common.error'), err.message) @@ -66,17 +70,15 @@ export default class ExportDebugController { .getTipBlockNumber() .then(n => BigInt(n).toString()) .catch(() => ''), - ckb.rpc - .getPeers() - .catch(() => []), - redistCheck() + ckb.rpc.getPeers().catch(() => []), + redistCheck(), ]) const { platform, arch } = process const release = os.release() const status = { neuron: { version: neuronVersion, - blockNumber: syncedBlockNumber + blockNumber: syncedBlockNumber, }, ckb: { url: /https?:\/\/(localhost|127.0.0.1)/.test(url) ? url : this.#ANONYMOUS_ADDRESS, @@ -88,11 +90,11 @@ export default class ExportDebugController { platform, arch, release, - vcredist - } + vcredist, + }, } this.archive.append(JSON.stringify(status), { - name: 'status.json' + name: 'status.json', }) } @@ -102,13 +104,17 @@ export default class ExportDebugController { return new Promise((resolve, reject) => { const logPath = path.resolve(SettingsService.getInstance().ckbDataPath, 'data', 'logs', 'run.log') - if (!fs.existsSync(logPath)) { return reject(new Error("File not found")) } + if (!fs.existsSync(logPath)) { + return reject(new Error('File not found')) + } const fileStats = fs.statSync(logPath) const position = fileStats.size - SIZE_TO_READ fs.open(logPath, 'r', (openErr, fd) => { - if (openErr) { return reject(openErr) } + if (openErr) { + return reject(openErr) + } fs.read(fd, Buffer.alloc(SIZE_TO_READ), 0, SIZE_TO_READ, position, (readErr, _, buffer) => { fs.close(fd, closeErr => { const err = closeErr || readErr @@ -119,12 +125,13 @@ export default class ExportDebugController { }) }) }) - - }).then((log: string) => { - this.archive.append(log, { name }) - }).catch(err => { - this.archive.append(err.message, { name }) }) + .then((log: string) => { + this.archive.append(log, { name }) + }) + .catch(err => { + this.archive.append(err.message, { name }) + }) } private async addHdPublicKeyInfoCsv() { diff --git a/packages/neuron-wallet/src/controllers/hardware.ts b/packages/neuron-wallet/src/controllers/hardware.ts index b831c57818..41cd9f0d8a 100644 --- a/packages/neuron-wallet/src/controllers/hardware.ts +++ b/packages/neuron-wallet/src/controllers/hardware.ts @@ -14,7 +14,7 @@ export default class HardwareController { } return { - status: ResponseCode.Success + status: ResponseCode.Success, } } @@ -24,7 +24,7 @@ export default class HardwareController { const devices = await HardwareWalletService.findDevices(model) return { status: ResponseCode.Success, - result: devices + result: devices, } } @@ -34,7 +34,7 @@ export default class HardwareController { return { status: ResponseCode.Success, - result: version + result: version, } } @@ -44,7 +44,7 @@ export default class HardwareController { return { status: ResponseCode.Success, - result: version + result: version, } } @@ -54,7 +54,7 @@ export default class HardwareController { return { status: ResponseCode.Success, - result: pubkey + result: pubkey, } } @@ -65,7 +65,7 @@ export default class HardwareController { return { status: ResponseCode.Success, - result: pubkey + result: pubkey, } } } diff --git a/packages/neuron-wallet/src/controllers/mercury.ts b/packages/neuron-wallet/src/controllers/mercury.ts index 513d7fa863..007a45190d 100644 --- a/packages/neuron-wallet/src/controllers/mercury.ts +++ b/packages/neuron-wallet/src/controllers/mercury.ts @@ -36,6 +36,6 @@ const openMigrateDialog = (type: 'hard-fork' | 'mercury') => { defaultId: 1, message: t(`${I18N_PATH}.message`), cancelId: 0, - noLink: true + noLink: true, }) } diff --git a/packages/neuron-wallet/src/controllers/multisig.ts b/packages/neuron-wallet/src/controllers/multisig.ts index 34b02cee09..43dd200504 100644 --- a/packages/neuron-wallet/src/controllers/multisig.ts +++ b/packages/neuron-wallet/src/controllers/multisig.ts @@ -14,55 +14,45 @@ import SystemScriptInfo from '../models/system-script-info' import NetworksService from '../services/networks' interface MultisigConfigOutput { - multisig_configs: Record + multisig_configs: Record< + string, + { + sighash_addresses: string[] + require_first_n: number + threshold: number + alias?: string + } + > } const validateImportConfig = (configOutput: MultisigConfigOutput) => { - return configOutput.multisig_configs && + return ( + configOutput.multisig_configs && Object.values(configOutput.multisig_configs).length && Object.values(configOutput.multisig_configs).every( - config => config.sighash_addresses?.length >= Math.max(+config.require_first_n, +config.threshold + config => config.sighash_addresses?.length >= Math.max(+config.require_first_n, +config.threshold) ) ) } export default class MultisigController { - // eslint-disable-next-line prettier/prettier - #multisigService: MultisigService; + #multisigService: MultisigService constructor() { - this.#multisigService = new MultisigService(); + this.#multisigService = new MultisigService() } - async saveConfig(params: { - walletId: string - r: number - m: number - n: number - blake160s: string[] - alias?: string - }) { - const multiSignConfig = MultisigConfig.fromModel(new MultisigConfigModel( - params.walletId, - params.r, - params.m, - params.n, - params.blake160s, - params.alias - )) + async saveConfig(params: { walletId: string; r: number; m: number; n: number; blake160s: string[]; alias?: string }) { + const multiSignConfig = MultisigConfig.fromModel( + new MultisigConfigModel(params.walletId, params.r, params.m, params.n, params.blake160s, params.alias) + ) const result = await this.#multisigService.saveMultisigConfig(multiSignConfig) return { status: ResponseCode.Success, - result + result, } } - async updateConfig(params: { id: number walletId?: string @@ -75,7 +65,7 @@ export default class MultisigController { const result = await this.#multisigService.updateMultisigConfig(params) return { status: ResponseCode.Success, - result + result, } } @@ -83,21 +73,18 @@ export default class MultisigController { const { response } = await dialog.showMessageBox(BrowserWindow.getFocusedWindow()!, { message: t('multisig-config.confirm-delete'), type: 'question', - buttons: [ - t('multisig-config.delete-actions.ok'), - t('multisig-config.delete-actions.cancel') - ] + buttons: [t('multisig-config.delete-actions.ok'), t('multisig-config.delete-actions.cancel')], }) if (response === 0) { await this.#multisigService.deleteConfig(id) return { status: ResponseCode.Success, - result: true + result: true, } } return { status: ResponseCode.Success, - result: false + result: false, } } @@ -105,18 +92,20 @@ export default class MultisigController { const result = await this.#multisigService.getMultisigConfig(walletId) return { status: ResponseCode.Success, - result + result, } } async importConfig(walletId: string) { const { canceled, filePaths } = await dialog.showOpenDialog(BrowserWindow.getFocusedWindow()!, { title: t('multisig-config.import-config'), - filters: [{ - name: 'json', - extensions: ['json'] - }], - properties: ['openFile'] + filters: [ + { + name: 'json', + extensions: ['json'], + }, + ], + properties: ['openFile'], }) if (canceled || !filePaths || !filePaths[0]) { @@ -135,7 +124,7 @@ export default class MultisigController { n: config.sighash_addresses.length, blake160s: config.sighash_addresses.map(v => addressToScript(v).args), walletId, - alias: config.alias + alias: config.alias, })) const savedResult = await Promise.allSettled(saveConfigs.map(config => this.saveConfig(config))) const saveSuccessConfigs: MultisigConfig[] = [] @@ -147,35 +136,35 @@ export default class MultisigController { } dialog.showMessageBox({ type: 'info', - message: t( - 'multisig-config.import-result', - { - success: saveSuccessConfigs.length, - fail: savedResult.length - saveSuccessConfigs.length, - failCheck: savedResult.length > saveSuccessConfigs.length ? t('multisig-config.import-duplicate') : undefined, - }) + message: t('multisig-config.import-result', { + success: saveSuccessConfigs.length, + fail: savedResult.length - saveSuccessConfigs.length, + failCheck: savedResult.length > saveSuccessConfigs.length ? t('multisig-config.import-duplicate') : undefined, + }), }) return { status: ResponseCode.Success, - result: saveSuccessConfigs + result: saveSuccessConfigs, } } catch { dialog.showErrorBox(t('common.error'), t('messages.invalid-json')) } } - async exportConfig(configs: { - id: string - walletId: string - r: number - m: number - n: number - blake160s: string[] - alias?: string - }[]) { + async exportConfig( + configs: { + id: string + walletId: string + r: number + m: number + n: number + blake160s: string[] + alias?: string + }[] + ) { const { canceled, filePath } = await dialog.showSaveDialog(BrowserWindow.getFocusedWindow()!, { title: t('multisig-config.export-config'), - defaultPath: `multisig-config_${Date.now()}.json` + defaultPath: `multisig-config_${Date.now()}.json`, }) if (canceled || !filePath) { return @@ -184,35 +173,36 @@ export default class MultisigController { const output: MultisigConfigOutput = { multisig_configs: {} } configs.forEach(v => { output.multisig_configs[Multisig.hash(v.blake160s, v.r, v.m, v.n)] = { - sighash_addresses: v.blake160s.map(args => scriptToAddress(SystemScriptInfo.generateSecpScript(args), isMainnet)), + sighash_addresses: v.blake160s.map(args => + scriptToAddress(SystemScriptInfo.generateSecpScript(args), isMainnet) + ), require_first_n: v.r, threshold: v.m, - alias: v.alias + alias: v.alias, } }) - fs.writeFileSync(filePath, JSON.stringify(output, undefined, 2)) dialog.showMessageBox({ type: 'info', - message: t('multisig-config.config-exported', { filePath }) + message: t('multisig-config.config-exported', { filePath }), }) return { status: ResponseCode.Success, result: { filePath: path.basename(filePath), - configs - } + configs, + }, } } - async getMultisigBalances({ isMainnet, multisigAddresses}: { isMainnet: boolean , multisigAddresses: string[] }) { + async getMultisigBalances({ isMainnet, multisigAddresses }: { isMainnet: boolean; multisigAddresses: string[] }) { const balances = await CellsService.getMultisigBalances(isMainnet, multisigAddresses) return { status: ResponseCode.Success, - result: balances + result: balances, } } @@ -228,12 +218,12 @@ export default class MultisigController { if (tx.transaction.inputs.every(v => v.lockHash !== lockHash)) { dialog.showErrorBox(t('common.error'), t('messages.multisig-lock-hash-mismatch')) return { - status: ResponseCode.Fail + status: ResponseCode.Fail, } } return { status: ResponseCode.Success, - result: result?.json + result: result?.json, } } -} \ No newline at end of file +} diff --git a/packages/neuron-wallet/src/controllers/networks/index.ts b/packages/neuron-wallet/src/controllers/networks/index.ts index adc430da12..b25d31e06c 100644 --- a/packages/neuron-wallet/src/controllers/networks/index.ts +++ b/packages/neuron-wallet/src/controllers/networks/index.ts @@ -37,7 +37,7 @@ export default class NetworksController { const networks = networksService.getAll() return { status: ResponseCode.Success, - result: networks + result: networks, } } @@ -53,7 +53,7 @@ export default class NetworksController { return { status: ResponseCode.Success, - result: network + result: network, } } @@ -71,7 +71,7 @@ export default class NetworksController { return { status: ResponseCode.Success, - result: created + result: created, } } @@ -91,7 +91,7 @@ export default class NetworksController { return { status: ResponseCode.Success, - result: true + result: true, } } @@ -107,12 +107,12 @@ export default class NetworksController { title: t(`messageBox.remove-network.title`), message: t(`messageBox.remove-network.message`, { name: network.name, - address: network.remote + address: network.remote, }), detail: currentID === id ? t('messageBox.remove-network.alert') : '', buttons: [t('messageBox.button.confirm'), t('messageBox.button.discard')], defaultId: 0, - cancelId: 1 + cancelId: 1, }) if (messageValue.response === 0) { @@ -128,13 +128,13 @@ export default class NetworksController { return { status: ResponseCode.Success, - result: true + result: true, } } catch (err) { logger.warn(`connect network error: ${err}`) dialog.showMessageBox({ type: 'error', - message: err.message + message: err.message, }) } } @@ -145,7 +145,7 @@ export default class NetworksController { if (currentID) { return { status: ResponseCode.Success, - result: currentID + result: currentID, } } throw new CurrentNetworkNotSet() @@ -163,7 +163,7 @@ export default class NetworksController { return { status: ResponseCode.Success, - result: true + result: true, } } diff --git a/packages/neuron-wallet/src/controllers/offline-sign.ts b/packages/neuron-wallet/src/controllers/offline-sign.ts index 92f0431bda..5899beb4c8 100644 --- a/packages/neuron-wallet/src/controllers/offline-sign.ts +++ b/packages/neuron-wallet/src/controllers/offline-sign.ts @@ -21,16 +21,16 @@ export default class OfflineSignController { status, asset_account, description, - context + context, }: OfflineSignJSON) { const { canceled, filePath } = await dialog.showSaveDialog({ title: t('offline-signature.export-transaction'), - defaultPath: `transaction_${Date.now()}.json` + defaultPath: `transaction_${Date.now()}.json`, }) if (canceled || !filePath) { return { - status: ResponseCode.Success + status: ResponseCode.Success, } } @@ -49,7 +49,7 @@ export default class OfflineSignController { status, asset_account, context, - description + description, }) const json = signer.toJSON() @@ -58,15 +58,15 @@ export default class OfflineSignController { dialog.showMessageBox({ type: 'info', - message: t('offline-signature.transaction-exported', { filePath }) + message: t('offline-signature.transaction-exported', { filePath }), }) return { status: ResponseCode.Success, result: { filePath: path.basename(filePath), - json - } + json, + }, } } @@ -101,7 +101,7 @@ export default class OfflineSignController { const signer = OfflineSign.fromJSON({ ...params, - transaction: tx + transaction: tx, }) let signStatus = SignStatus.Signed @@ -112,7 +112,7 @@ export default class OfflineSignController { return { status: ResponseCode.Success, - result: signer.toJSON() + result: signer.toJSON(), } } catch (err) { if (err.code) { @@ -129,7 +129,7 @@ export default class OfflineSignController { const signer = OfflineSign.fromJSON({ ...params, - ...res.result + ...res.result, }) return await this.exportTransactionAsJSON(signer.toJSON()) @@ -145,7 +145,7 @@ export default class OfflineSignController { return await this.broadcastTransaction({ ...res.result, - walletID: params.walletID + walletID: params.walletID, }) } @@ -154,7 +154,7 @@ export default class OfflineSignController { type, asset_account: assetAccount, walletID, - description + description, }: OfflineSignJSON & { walletID: string }) { const tx = Transaction.fromObject(transaction) switch (type) { @@ -164,7 +164,7 @@ export default class OfflineSignController { walletID, assetAccount: assetAccount!, tx, - password: '' + password: '', }, true ) @@ -174,7 +174,7 @@ export default class OfflineSignController { { walletID, tx, - password: '' + password: '', }, true ) @@ -185,7 +185,7 @@ export default class OfflineSignController { walletID, tx, password: '', - description + description, }, true ) diff --git a/packages/neuron-wallet/src/controllers/sign-message.ts b/packages/neuron-wallet/src/controllers/sign-message.ts index aff6f77929..a81916b7f6 100644 --- a/packages/neuron-wallet/src/controllers/sign-message.ts +++ b/packages/neuron-wallet/src/controllers/sign-message.ts @@ -16,7 +16,7 @@ export default class SignMessageController { return { status: ResponseCode.Success, - result: signature + result: signature, } } @@ -28,7 +28,7 @@ export default class SignMessageController { return { status: ResponseCode.Success, - result + result, } } } diff --git a/packages/neuron-wallet/src/controllers/sudt.ts b/packages/neuron-wallet/src/controllers/sudt.ts index d7e067360a..a2191a26e0 100644 --- a/packages/neuron-wallet/src/controllers/sudt.ts +++ b/packages/neuron-wallet/src/controllers/sudt.ts @@ -14,25 +14,25 @@ export default class SUDTController { if (sudtInfo) { return { status: ResponseCode.Success, - result: { ...sudtInfo, tokenID: params.tokenID } + result: { ...sudtInfo, tokenID: params.tokenID }, } } const typeScript = Script.fromObject({ codeHash: new AssetAccountInfo().sudtInfoCodeHash, args: params.tokenID, - hashType: ScriptHashType.Type + hashType: ScriptHashType.Type, }) const liveCell = await LiveCellService.getInstance().getOneByLockScriptAndTypeScript(null, typeScript) if (!liveCell) { return { - status: ResponseCode.Fail + status: ResponseCode.Fail, } } const { decimal, name, symbol } = parseSUDTTokenInfo(liveCell.data) return { status: ResponseCode.Success, - result: { tokenID: params.tokenID, symbol: symbol, tokenName: name, decimal: decimal } + result: { tokenID: params.tokenID, symbol: symbol, tokenName: name, decimal: decimal }, } } @@ -41,7 +41,7 @@ export default class SUDTController { const script = new Script(assetAcount.infos.sudt.codeHash, params.tokenID, assetAcount.infos.sudt.hashType) return { status: ResponseCode.Success, - result: scriptToHash(script.toSDK()) + result: scriptToHash(script.toSDK()), } } } diff --git a/packages/neuron-wallet/src/controllers/sync-api.ts b/packages/neuron-wallet/src/controllers/sync-api.ts index e35bf2051b..b21b199386 100644 --- a/packages/neuron-wallet/src/controllers/sync-api.ts +++ b/packages/neuron-wallet/src/controllers/sync-api.ts @@ -15,26 +15,25 @@ export enum SyncStatus { SyncNotStart, SyncPending, Syncing, - SyncCompleted + SyncCompleted, } interface SyncState { - nodeUrl: string, - timestamp: number, - indexerTipNumber: number, - cacheTipNumber: number, - bestKnownBlockNumber: number, - bestKnownBlockTimestamp: number, - indexRate: number | undefined, - cacheRate: number | undefined, - estimate: number | undefined, + nodeUrl: string + timestamp: number + indexerTipNumber: number + cacheTipNumber: number + bestKnownBlockNumber: number + bestKnownBlockTimestamp: number + indexRate: number | undefined + cacheRate: number | undefined + estimate: number | undefined status: SyncStatus - isLookingValidTarget?: boolean, + isLookingValidTarget?: boolean validTarget?: string } export default class SyncApiController { - // eslint-disable-next-line prettier/prettier #syncedBlockNumber = new SyncedBlockNumber() static emiter = new EventEmiter() private static instance: SyncApiController @@ -61,8 +60,7 @@ export default class SyncApiController { #getEstimatesByCurrentNode = () => { const nodeUrl = this.#getCurrentNodeUrl() return this.#estimates.filter( - state => state.nodeUrl === nodeUrl && - Date.now() - state.timestamp <= this.#sampleTime + state => state.nodeUrl === nodeUrl && Date.now() - state.timestamp <= this.#sampleTime ) } @@ -105,7 +103,7 @@ export default class SyncApiController { return newSyncState } - #fetchBestKnownBlockInfo = async (): Promise<{ bestKnownBlockNumber: number, bestKnownBlockTimestamp: number }> => { + #fetchBestKnownBlockInfo = async (): Promise<{ bestKnownBlockNumber: number; bestKnownBlockTimestamp: number }> => { const nodeUrl = this.#getCurrentNodeUrl() const rpcService = new RpcService(nodeUrl) try { @@ -155,7 +153,7 @@ export default class SyncApiController { estimate: undefined, status: SyncStatus.Syncing, isLookingValidTarget: getLookingValidTargetStatus(), - validTarget: process.env.CKB_NODE_ASSUME_VALID_TARGET + validTarget: process.env.CKB_NODE_ASSUME_VALID_TARGET, } if (foundBestKnownBlockNumber) { @@ -199,7 +197,8 @@ export default class SyncApiController { return this.#cachedEstimation } - if (this.#estimates.length > 1 && + if ( + this.#estimates.length > 1 && this.#estimates[this.#estimates.length - 2].cacheTipNumber === lastEstimation.cacheTipNumber ) { this.#cachedEstimation = lastEstimation @@ -208,7 +207,8 @@ export default class SyncApiController { const nodeUrl = this.#getCurrentNodeUrl() - if (this.#cachedEstimation.nodeUrl !== nodeUrl || + if ( + this.#cachedEstimation.nodeUrl !== nodeUrl || this.#cachedEstimation.timestamp + this.#sampleTime <= Date.now() ) { this.#cachedEstimation = lastEstimation @@ -218,14 +218,13 @@ export default class SyncApiController { } #registerHandlers = () => { - // FIX: remove listener when sync task stopped // Export handler to devtools SyncApiController.emiter.on('cache-tip-block-updated', async states => { const newSyncState = await this.#estimate(states) this.#syncedBlockNumber.setNextBlock(BigInt(newSyncState.cacheTipNumber)) SyncStateSubject.next(newSyncState) - await MultisigService.syncMultisigOutput(`0x${(BigInt(newSyncState.cacheTipNumber)).toString(16)}`) + await MultisigService.syncMultisigOutput(`0x${BigInt(newSyncState.cacheTipNumber).toString(16)}`) }) CurrentNetworkIDSubject.pipe(debounceTime(500)).subscribe(() => { @@ -241,12 +240,11 @@ export default class SyncApiController { cacheRate: undefined, estimate: undefined, status: SyncStatus.SyncNotStart, - validTarget: process.env.CKB_NODE_ASSUME_VALID_TARGET + validTarget: process.env.CKB_NODE_ASSUME_VALID_TARGET, } this.#estimates = [newSyncState] SyncStateSubject.next(newSyncState) }) } - } diff --git a/packages/neuron-wallet/src/controllers/transactions.ts b/packages/neuron-wallet/src/controllers/transactions.ts index 3a1b42295f..26f6624ac5 100644 --- a/packages/neuron-wallet/src/controllers/transactions.ts +++ b/packages/neuron-wallet/src/controllers/transactions.ts @@ -24,7 +24,7 @@ export default class TransactionsController { keywords.trim() ).catch(() => ({ totalCount: 0, - items: [] as Transaction[] + items: [] as Transaction[], })) transactions.items = await Promise.all( transactions.items.map(async tx => { @@ -41,7 +41,7 @@ export default class TransactionsController { return { status: ResponseCode.Success, - result: { ...params, ...transactions, keywords, walletID } + result: { ...params, ...transactions, keywords, walletID }, } } @@ -96,14 +96,14 @@ export default class TransactionsController { result: { ...transaction, outputsCount, inputsCount } as Transaction & { outputsCount: string inputsCount: string - } + }, } } public async updateDescription({ walletID, hash, - description + description, }: { walletID: string hash: string @@ -113,7 +113,7 @@ export default class TransactionsController { return { status: ResponseCode.Success, - result: { hash, description } + result: { hash, description }, } } @@ -127,7 +127,7 @@ export default class TransactionsController { try { const { canceled, filePath } = await dialog.showSaveDialog({ title: t('export-transactions.export-transactions'), - defaultPath: `transactions_${Date.now()}.csv` + defaultPath: `transactions_${Date.now()}.csv`, }) if (canceled || !filePath) { return @@ -135,11 +135,11 @@ export default class TransactionsController { const total = await TransactionsService.exportTransactions({ walletID, filePath }) dialog.showMessageBox({ type: 'info', - message: t('export-transactions.transactions-exported', { file: filePath, total }) + message: t('export-transactions.transactions-exported', { file: filePath, total }), }) return { status: ResponseCode.Success, - result: total + result: total, } } catch (err) { dialog.showErrorBox(t('common.error'), err.message) diff --git a/packages/neuron-wallet/src/controllers/update.ts b/packages/neuron-wallet/src/controllers/update.ts index 0153090421..f5f306084b 100644 --- a/packages/neuron-wallet/src/controllers/update.ts +++ b/packages/neuron-wallet/src/controllers/update.ts @@ -22,7 +22,7 @@ export default class UpdateController { checking: true, downloadProgress: -1, version: '', - releaseNotes: '' + releaseNotes: '', }) } @@ -59,7 +59,7 @@ export default class UpdateController { dialog.showMessageBox(BrowserWindow.getFocusedWindow()!, { type: 'info', message: t('updater.update-not-available'), - buttons: [t('common.ok')] + buttons: [t('common.ok')], }) }) @@ -81,7 +81,7 @@ export default class UpdateController { checking: UpdateController.isChecking, downloadProgress, version, - releaseNotes + releaseNotes, }) } } diff --git a/packages/neuron-wallet/src/controllers/wallets.ts b/packages/neuron-wallet/src/controllers/wallets.ts index 44ed72b8f6..37afcf66d2 100644 --- a/packages/neuron-wallet/src/controllers/wallets.ts +++ b/packages/neuron-wallet/src/controllers/wallets.ts @@ -19,7 +19,7 @@ import { IncorrectPassword, InvalidJSON, InvalidAddress, - UsedName + UsedName, } from '../exceptions' import AddressService from '../services/addresses' import { MainnetAddressRequired, TestnetAddressRequired } from '../exceptions/address' @@ -40,7 +40,7 @@ export default class WalletsController { } return { status: ResponseCode.Success, - result: wallets.map(({ name, id, device }) => ({ name, id, device })) + result: wallets.map(({ name, id, device }) => ({ name, id, device })), } } @@ -55,14 +55,14 @@ export default class WalletsController { } return { status: ResponseCode.Success, - result: wallet + result: wallet, } } public async importMnemonic({ name, password, - mnemonic + mnemonic, }: { name: string password: string @@ -74,7 +74,7 @@ export default class WalletsController { public async create({ name, password, - mnemonic + mnemonic, }: { name: string password: string @@ -87,7 +87,7 @@ export default class WalletsController { name, password, mnemonic, - isImporting + isImporting, }: { name: string password: string @@ -120,7 +120,7 @@ export default class WalletsController { id: '', name, extendedKey: accountExtendedPublicKey.serialize(), - keystore + keystore, }) wallet.checkAndGenerateAddresses(isImporting) @@ -129,15 +129,15 @@ export default class WalletsController { status: ResponseCode.Success, result: { id: wallet.id, - name: wallet.name - } + name: wallet.name, + }, } } public async importKeystore({ name, password, - keystorePath + keystorePath, }: { name: string password: string @@ -169,14 +169,14 @@ export default class WalletsController { id: '', name, extendedKey: accountExtendedPublicKey.serialize(), - keystore: keystoreObject + keystore: keystoreObject, }) wallet.checkAndGenerateAddresses(true) return { status: ResponseCode.Success, - result: wallet + result: wallet, } } @@ -185,7 +185,7 @@ export default class WalletsController { name, password, newPassword, - device + device, }: { id: string password: string @@ -200,7 +200,7 @@ export default class WalletsController { } const props: { name: string; keystore?: Keystore; device?: DeviceInfo } = { - name: name || wallet.name + name: name || wallet.name, } if (!wallet.isHardware()) { @@ -219,7 +219,7 @@ export default class WalletsController { walletsService.update(id, props) return { status: ResponseCode.Success, - result: walletsService.get(id) + result: walletsService.get(id), } } @@ -237,7 +237,7 @@ export default class WalletsController { public async backup({ id = '', - password = '' + password = '', }: Controller.Params.BackupWallet): Promise> { const walletsService = WalletsService.getInstance() @@ -251,7 +251,7 @@ export default class WalletsController { public async importHardwareWallet({ publicKey, chainCode, - walletName + walletName, }: ExtendedPublicKey & { walletName: string }): Promise> { const device = HardwareWalletService.getInstance().getCurrent()! const accountExtendedPublicKey = new AccountExtendedPublicKey(publicKey, chainCode) @@ -261,14 +261,14 @@ export default class WalletsController { id: '', name: walletName, extendedKey: accountExtendedPublicKey.serialize(), - keystore: Keystore.createEmpty() + keystore: Keystore.createEmpty(), }) wallet.checkAndGenerateAddresses(true) return { status: ResponseCode.Success, - result: wallet + result: wallet, } } @@ -276,17 +276,13 @@ export default class WalletsController { return dialog .showOpenDialog(BrowserWindow.getFocusedWindow()!, { title: t('messages.import-extended-public-key'), - filters: [{ name: 'JSON File', extensions: ['json'] }] + filters: [{ name: 'JSON File', extensions: ['json'] }], }) .then((value: OpenDialogReturnValue) => { const filePath = value.filePaths[0] if (filePath) { try { - const name = - filePath - .split(/[\\/]/) - .pop()! - .split('.')[0] + '-Watch Only' // File name (without extension) + const name = filePath.split(/[\\/]/).pop()!.split('.')[0] + '-Watch Only' // File name (without extension) const content = fs.readFileSync(filePath, 'utf8') const json: { xpubkey: string } = JSON.parse(content) const accountExtendedPublicKey = AccountExtendedPublicKey.parse(json.xpubkey) @@ -296,13 +292,13 @@ export default class WalletsController { id: '', name, extendedKey: accountExtendedPublicKey.serialize(), - keystore: Keystore.createEmpty() + keystore: Keystore.createEmpty(), }) wallet.checkAndGenerateAddresses(true) return { status: ResponseCode.Success, - result: wallet + result: wallet, } } catch (e) { if (e instanceof UsedName) { @@ -324,19 +320,19 @@ export default class WalletsController { return dialog .showSaveDialog(BrowserWindow.getFocusedWindow()!, { title: t('messages.save-extended-public-key'), - defaultPath: wallet.name + '-xpubkey.json' + defaultPath: wallet.name + '-xpubkey.json', }) .then((returnValue: SaveDialogReturnValue) => { if (returnValue.filePath) { fs.writeFileSync(returnValue.filePath, JSON.stringify({ xpubkey: xpubkey.serialize() })) return { status: ResponseCode.Success, - result: true + result: true, } } else { return { status: ResponseCode.Fail, - result: false + result: false, } } }) @@ -349,9 +345,9 @@ export default class WalletsController { result: currentWallet ? { ...currentWallet.toJSON(), - isWatchOnly: currentWallet.isHDWallet() && currentWallet.loadKeystore().isEmpty() + isWatchOnly: currentWallet.isHDWallet() && currentWallet.loadKeystore().isEmpty(), } - : null + : null, } } @@ -364,7 +360,7 @@ export default class WalletsController { } return { status: ResponseCode.Success, - result: currentWallet.toJSON() + result: currentWallet.toJSON(), } } @@ -377,7 +373,7 @@ export default class WalletsController { txCount, balance, description = '', - addressIndex: index = '' + addressIndex: index = '', }) => ({ address, identifier, @@ -385,12 +381,12 @@ export default class WalletsController { txCount: txCount!, description, balance: balance!, - index + index, }) ) return { status: ResponseCode.Success, - result: addresses + result: addresses, } } @@ -433,7 +429,7 @@ export default class WalletsController { return { status: ResponseCode.Success, - result: hash + result: hash, } } @@ -457,7 +453,7 @@ export default class WalletsController { ) return { status: ResponseCode.Success, - result: tx + result: tx, } } @@ -481,7 +477,7 @@ export default class WalletsController { ) return { status: ResponseCode.Success, - result: tx + result: tx, } } @@ -498,7 +494,7 @@ export default class WalletsController { const tx: Transaction = await new TransactionSender().generateMultisigTx(params.items, params.multisigConfig) return { status: ResponseCode.Success, - result: tx + result: tx, } } @@ -515,14 +511,14 @@ export default class WalletsController { const tx: Transaction = await new TransactionSender().generateMultisigSendAllTx(params.items, params.multisigConfig) return { status: ResponseCode.Success, - result: tx + result: tx, } } public async updateAddressDescription({ walletID, address, - description + description, }: { walletID: string address: string @@ -536,8 +532,8 @@ export default class WalletsController { result: { walletID, address, - description - } + description, + }, } } @@ -566,7 +562,7 @@ export default class WalletsController { winID: window.id, type: action, payload: walletID, - dispatchToUI: true + dispatchToUI: true, }) } } @@ -575,14 +571,14 @@ export default class WalletsController { public validateMnemonic(mnemonic: string) { return { status: ResponseCode.Success, - result: validateMnemonic(mnemonic) + result: validateMnemonic(mnemonic), } } public generateMnemonic() { return { status: ResponseCode.Success, - result: generateMnemonic() + result: generateMnemonic(), } } @@ -619,7 +615,7 @@ export default class WalletsController { await walletsService.delete(id) return { - status: ResponseCode.Success + status: ResponseCode.Success, } } @@ -632,24 +628,24 @@ export default class WalletsController { return dialog .showSaveDialog(BrowserWindow.getFocusedWindow()!, { title: t('messages.save-keystore'), - defaultPath: wallet.name + '.json' + defaultPath: wallet.name + '.json', }) .then((returnValue: SaveDialogReturnValue) => { if (returnValue.canceled) { return { status: ResponseCode.Success, - result: true + result: true, } } else if (returnValue.filePath) { fs.writeFileSync(returnValue.filePath, JSON.stringify(keystore)) return { status: ResponseCode.Success, - result: true + result: true, } } else { return { status: ResponseCode.Fail, - result: false + result: false, } } }) diff --git a/packages/neuron-wallet/src/database/address/AddressVersion.ts b/packages/neuron-wallet/src/database/address/AddressVersion.ts index 4d3e539718..e7219aa190 100644 --- a/packages/neuron-wallet/src/database/address/AddressVersion.ts +++ b/packages/neuron-wallet/src/database/address/AddressVersion.ts @@ -1,4 +1,4 @@ export enum AddressVersion { Testnet = 'testnet', - Mainnet = 'mainnet' + Mainnet = 'mainnet', } diff --git a/packages/neuron-wallet/src/database/chain/entities/address-description.ts b/packages/neuron-wallet/src/database/chain/entities/address-description.ts index 5fd750962c..5ae3855aa8 100644 --- a/packages/neuron-wallet/src/database/chain/entities/address-description.ts +++ b/packages/neuron-wallet/src/database/chain/entities/address-description.ts @@ -6,19 +6,19 @@ export default class AddressDescription { id!: number @Column({ - type: 'varchar' + type: 'varchar', }) @Index() walletId!: string @Column({ - type: 'varchar' + type: 'varchar', }) @Index() address!: string @Column({ - type: 'varchar' + type: 'varchar', }) description!: string } diff --git a/packages/neuron-wallet/src/database/chain/entities/asset-account.ts b/packages/neuron-wallet/src/database/chain/entities/asset-account.ts index 8280ded5e4..d59d67ecd4 100644 --- a/packages/neuron-wallet/src/database/chain/entities/asset-account.ts +++ b/packages/neuron-wallet/src/database/chain/entities/asset-account.ts @@ -9,31 +9,27 @@ export default class AssetAccount { id!: number @Column({ - type: 'varchar' + type: 'varchar', }) tokenID!: string @Column({ type: 'varchar', - default: '' + default: '', }) accountName!: string @Column({ - type: 'varchar' + type: 'varchar', }) balance!: string @Column({ - type: 'varchar' + type: 'varchar', }) blake160!: string - @ManyToOne( - _type => SudtTokenInfo, - sudtTokenInfo => sudtTokenInfo.assetAccounts, - { onDelete: 'CASCADE' } - ) + @ManyToOne(_type => SudtTokenInfo, sudtTokenInfo => sudtTokenInfo.assetAccounts, { onDelete: 'CASCADE' }) @JoinColumn([{ name: 'tokenID', referencedColumnName: 'tokenID' }]) sudtTokenInfo!: SudtTokenInfo diff --git a/packages/neuron-wallet/src/database/chain/entities/hd-public-key-info.ts b/packages/neuron-wallet/src/database/chain/entities/hd-public-key-info.ts index 4162a80ad5..e06e3d5632 100644 --- a/packages/neuron-wallet/src/database/chain/entities/hd-public-key-info.ts +++ b/packages/neuron-wallet/src/database/chain/entities/hd-public-key-info.ts @@ -8,7 +8,7 @@ export default class HdPublicKeyInfo { id!: number @Column({ - type: 'varchar' + type: 'varchar', }) @Index() walletId!: string @@ -21,13 +21,13 @@ export default class HdPublicKeyInfo { addressIndex!: number @Column({ - type: 'varchar' + type: 'varchar', }) publicKeyInBlake160!: string @CreateDateColumn({ type: 'varchar', - default: () => 'CURRENT_TIMESTAMP' + default: () => 'CURRENT_TIMESTAMP', }) createdAt!: Date diff --git a/packages/neuron-wallet/src/database/chain/entities/indexer-tx-hash-cache.ts b/packages/neuron-wallet/src/database/chain/entities/indexer-tx-hash-cache.ts index c6c5cd571d..3aaf054b5b 100644 --- a/packages/neuron-wallet/src/database/chain/entities/indexer-tx-hash-cache.ts +++ b/packages/neuron-wallet/src/database/chain/entities/indexer-tx-hash-cache.ts @@ -7,28 +7,28 @@ export default class IndexerTxHashCache extends BaseEntity { @Column({ type: 'character', - length: 32 + length: 32, }) @Index() txHash!: string @Column({ type: 'character', - length: 32 + length: 32, }) @Index() lockHash!: string @Column({ type: 'character', - length: 32 + length: 32, }) @Index() address!: string @Column({ type: 'character', - length: 32 + length: 32, }) @Index() walletId!: string @@ -39,13 +39,13 @@ export default class IndexerTxHashCache extends BaseEntity { @Column({ type: 'character', - length: 32 + length: 32, }) @Index() blockHash!: string @Column({ - type: 'varchar' + type: 'varchar', }) @Index() blockTimestamp!: string @@ -56,14 +56,14 @@ export default class IndexerTxHashCache extends BaseEntity { @CreateDateColumn({ type: 'varchar', - default: () => 'CURRENT_TIMESTAMP' + default: () => 'CURRENT_TIMESTAMP', }) createdAt!: Date @UpdateDateColumn({ type: 'varchar', default: () => 'CURRENT_TIMESTAMP', - onUpdate: 'CURRENT_TIMESTAMP' + onUpdate: 'CURRENT_TIMESTAMP', }) updatedAt!: Date } diff --git a/packages/neuron-wallet/src/database/chain/entities/input.ts b/packages/neuron-wallet/src/database/chain/entities/input.ts index 9586013367..2aa7c1532b 100644 --- a/packages/neuron-wallet/src/database/chain/entities/input.ts +++ b/packages/neuron-wallet/src/database/chain/entities/input.ts @@ -13,104 +13,100 @@ export default class Input extends BaseEntity { // cellbase input has empty cell { txHash, index } @Column({ type: 'varchar', - nullable: true + nullable: true, }) outPointTxHash: string | null = null @Column({ type: 'varchar', - nullable: true + nullable: true, }) outPointIndex: string | null = null @Column({ - type: 'varchar' + type: 'varchar', }) since!: string @Column({ type: 'varchar', - nullable: true + nullable: true, }) lockHash: string | null = null // cellbase input has no previous output lock script @Column({ type: 'varchar', - nullable: true + nullable: true, }) lockCodeHash: string | null = null @Column({ type: 'varchar', - nullable: true + nullable: true, }) lockArgs: string | null = null @Column({ type: 'varchar', - nullable: true + nullable: true, }) lockHashType: ScriptHashType | null = null @Column({ type: 'varchar', - nullable: true + nullable: true, }) typeCodeHash: string | null = null @Column({ type: 'varchar', - nullable: true + nullable: true, }) typeArgs: string | null = null @Column({ type: 'varchar', - nullable: true + nullable: true, }) typeHashType: ScriptHashType | null = null @Column({ type: 'varchar', - nullable: true + nullable: true, }) typeHash: string | null = null // only first 130 chars @Column({ type: 'varchar', - default: '0x' + default: '0x', }) data: string = '0x' @Column({ - type: 'varchar' + type: 'varchar', }) transactionHash!: string - @ManyToOne( - _type => Transaction, - transaction => transaction.inputs, - { onDelete: 'CASCADE' } - ) + @ManyToOne(_type => Transaction, transaction => transaction.inputs, { onDelete: 'CASCADE' }) transaction!: Transaction @Column({ type: 'varchar', - nullable: true + nullable: true, }) capacity: string | null = null @Column({ type: 'varchar', - nullable: true + nullable: true, }) inputIndex: string | null = null @Column({ type: 'varchar', - nullable: true + nullable: true, }) multiSignBlake160: string | null = null diff --git a/packages/neuron-wallet/src/database/chain/entities/multisig-output.ts b/packages/neuron-wallet/src/database/chain/entities/multisig-output.ts index 9b4683246d..deeaf9f9ba 100644 --- a/packages/neuron-wallet/src/database/chain/entities/multisig-output.ts +++ b/packages/neuron-wallet/src/database/chain/entities/multisig-output.ts @@ -7,47 +7,47 @@ import { OutputStatus } from '../../../models/chain/output' @Entity() export default class MultisigOutput extends BaseEntity { @PrimaryColumn({ - type: 'varchar' + type: 'varchar', }) outPointTxHash!: string @PrimaryColumn({ - type: 'varchar' + type: 'varchar', }) outPointIndex!: string @PrimaryColumn({ - type: 'varchar' + type: 'varchar', }) outPointTxHashAddIndex!: string @Column({ - type: 'varchar' + type: 'varchar', }) capacity!: string @Column({ - type: 'varchar' + type: 'varchar', }) lockCodeHash!: string @Column({ - type: 'varchar' + type: 'varchar', }) lockArgs!: string @Column({ - type: 'varchar' + type: 'varchar', }) lockHashType!: ScriptHashType @Column({ - type: 'varchar' + type: 'varchar', }) lockHash!: string @Column({ - type: 'varchar' + type: 'varchar', }) status!: string @@ -74,7 +74,7 @@ export default class MultisigOutput extends BaseEntity { entity.lockHash = scriptToHash({ args: entity.lockArgs, codeHash: entity.lockCodeHash, - hashType: entity.lockHashType + hashType: entity.lockHashType, }) entity.status = OutputStatus.Live return entity diff --git a/packages/neuron-wallet/src/database/chain/entities/output.ts b/packages/neuron-wallet/src/database/chain/entities/output.ts index 0db351f331..d05af4ce0f 100644 --- a/packages/neuron-wallet/src/database/chain/entities/output.ts +++ b/packages/neuron-wallet/src/database/chain/entities/output.ts @@ -7,102 +7,102 @@ import OutputModel, { OutputStatus } from '../../../models/chain/output' @Entity() export default class Output extends BaseEntity { @PrimaryColumn({ - type: 'varchar' + type: 'varchar', }) outPointTxHash!: string @PrimaryColumn({ - type: 'varchar' + type: 'varchar', }) outPointIndex!: string @Column({ - type: 'varchar' + type: 'varchar', }) capacity!: string @Column({ - type: 'varchar' + type: 'varchar', }) lockCodeHash!: string @Column({ - type: 'varchar' + type: 'varchar', }) lockArgs!: string @Column({ - type: 'varchar' + type: 'varchar', }) lockHashType!: ScriptHashType @Column({ - type: 'varchar' + type: 'varchar', }) lockHash!: string @Column({ - type: 'varchar' + type: 'varchar', }) status!: string @Column({ type: 'varchar', - nullable: true + nullable: true, }) typeCodeHash: string | null = null @Column({ type: 'varchar', - nullable: true + nullable: true, }) typeArgs: string | null = null @Column({ type: 'varchar', - nullable: true + nullable: true, }) typeHashType: ScriptHashType | null = null @Column({ type: 'varchar', - nullable: true + nullable: true, }) typeHash: string | null = null // only first 130 chars @Column({ type: 'varchar', - default: '0x' + default: '0x', }) data: string = '0x' @Column({ type: 'varchar', - nullable: true + nullable: true, }) daoData: string | null = null @Column({ - type: 'boolean' + type: 'boolean', }) hasData!: boolean @Column({ type: 'varchar', - nullable: true + nullable: true, }) depositTxHash: string | null = null @Column({ type: 'varchar', - nullable: true + nullable: true, }) depositIndex: string | null = null @Column({ type: 'varchar', - nullable: true + nullable: true, }) multiSignBlake160: string | null = null @@ -128,11 +128,7 @@ export default class Output extends BaseEntity { return undefined } - @ManyToOne( - _type => TransactionEntity, - transaction => transaction.outputs, - { onDelete: 'CASCADE' } - ) + @ManyToOne(_type => TransactionEntity, transaction => transaction.outputs, { onDelete: 'CASCADE' }) transaction!: TransactionEntity public toModel(): OutputModel { @@ -152,7 +148,7 @@ export default class Output extends BaseEntity { blockNumber: this.transaction?.blockNumber, blockHash: this.transaction?.blockHash, depositOutPoint: this.depositOutPoint(), - multiSignBlake160: this.multiSignBlake160 + multiSignBlake160: this.multiSignBlake160, }) } } diff --git a/packages/neuron-wallet/src/database/chain/entities/sudt-token-info.ts b/packages/neuron-wallet/src/database/chain/entities/sudt-token-info.ts index 5f409a42d6..ec0614395b 100644 --- a/packages/neuron-wallet/src/database/chain/entities/sudt-token-info.ts +++ b/packages/neuron-wallet/src/database/chain/entities/sudt-token-info.ts @@ -5,29 +5,26 @@ import AssetAccount from './asset-account' @Index(['tokenID'], { unique: true }) export default class SudtTokenInfo { @PrimaryColumn({ - type: 'varchar' + type: 'varchar', }) tokenID!: string @Column({ - type: 'varchar' + type: 'varchar', }) symbol!: string @Column({ - type: 'varchar' + type: 'varchar', }) tokenName!: string @Column({ - type: 'varchar' + type: 'varchar', }) decimal!: string - @OneToMany( - _type => AssetAccount, - assetAccount => assetAccount.sudtTokenInfo - ) + @OneToMany(_type => AssetAccount, assetAccount => assetAccount.sudtTokenInfo) assetAccounts!: AssetAccount[] public toModel() { @@ -35,7 +32,7 @@ export default class SudtTokenInfo { tokenID: this.tokenID, tokenName: this.tokenName, symbol: this.symbol, - decimal: this.decimal + decimal: this.decimal, } } } diff --git a/packages/neuron-wallet/src/database/chain/entities/sync-info.ts b/packages/neuron-wallet/src/database/chain/entities/sync-info.ts index c181c27036..5b8e93bed0 100644 --- a/packages/neuron-wallet/src/database/chain/entities/sync-info.ts +++ b/packages/neuron-wallet/src/database/chain/entities/sync-info.ts @@ -5,12 +5,12 @@ export default class SyncInfo { public static CURRENT_BLOCK_NUMBER = 'currentBlockNumber' @PrimaryColumn({ - type: 'varchar' + type: 'varchar', }) name!: string @Column({ - type: 'varchar' + type: 'varchar', }) value!: string } diff --git a/packages/neuron-wallet/src/database/chain/entities/transaction.ts b/packages/neuron-wallet/src/database/chain/entities/transaction.ts index 13586ca451..b40216ae91 100644 --- a/packages/neuron-wallet/src/database/chain/entities/transaction.ts +++ b/packages/neuron-wallet/src/database/chain/entities/transaction.ts @@ -8,7 +8,7 @@ import { BeforeUpdate, AfterInsert, AfterUpdate, - AfterRemove + AfterRemove, } from 'typeorm' import TxDbChangedSubject from '../../../models/subjects/tx-db-changed-subject' import InputEntity from './input' @@ -22,85 +22,79 @@ import Output from '../../../models/chain/output' @Entity() export default class Transaction extends BaseEntity { @PrimaryColumn({ - type: 'varchar' + type: 'varchar', }) hash!: string @Column({ - type: 'varchar' + type: 'varchar', }) version!: string @Column({ - type: 'simple-json' + type: 'simple-json', }) cellDeps: CellDep[] = [] @Column({ - type: 'simple-json' + type: 'simple-json', }) headerDeps: string[] = [] @Column({ - type: 'simple-json' + type: 'simple-json', }) witnesses!: string[] @Column({ type: 'varchar', - nullable: true + nullable: true, }) timestamp: string | undefined = undefined @Column({ type: 'varchar', - nullable: true + nullable: true, }) blockNumber: string | undefined = undefined @Column({ type: 'varchar', - nullable: true + nullable: true, }) blockHash: string | undefined = undefined @Column({ type: 'varchar', - nullable: true + nullable: true, }) description?: string @Column({ - type: 'varchar' + type: 'varchar', }) status!: TransactionStatus @Column({ - type: 'varchar' + type: 'varchar', }) createdAt!: string @Column({ - type: 'varchar' + type: 'varchar', }) updatedAt!: string // only used for check fork in indexer mode @Column({ - type: 'boolean' + type: 'boolean', }) confirmed: boolean = false - @OneToMany( - _type => InputEntity, - input => input.transaction - ) + @OneToMany(_type => InputEntity, input => input.transaction) inputs!: InputEntity[] - @OneToMany( - _type => OutputEntity, - output => output.transaction - ) + @OneToMany(_type => OutputEntity, output => output.transaction) outputs!: OutputEntity[] public toModel(): TransactionModel { @@ -128,7 +122,7 @@ export default class Transaction extends BaseEntity { createdAt: this.createdAt, updatedAt: this.updatedAt, outputsData: [], - nervosDao: false + nervosDao: false, }) } diff --git a/packages/neuron-wallet/src/database/chain/entities/tx-description.ts b/packages/neuron-wallet/src/database/chain/entities/tx-description.ts index ad63dc847d..f5bb6d73ea 100644 --- a/packages/neuron-wallet/src/database/chain/entities/tx-description.ts +++ b/packages/neuron-wallet/src/database/chain/entities/tx-description.ts @@ -6,18 +6,18 @@ export default class TxDescription { id!: number @Column({ - type: 'varchar' + type: 'varchar', }) walletId!: string @Column({ - type: 'varchar' + type: 'varchar', }) @Index() txHash!: string @Column({ - type: 'varchar' + type: 'varchar', }) description!: string } diff --git a/packages/neuron-wallet/src/database/chain/index.ts b/packages/neuron-wallet/src/database/chain/index.ts index be614f57cf..3ad38d7498 100644 --- a/packages/neuron-wallet/src/database/chain/index.ts +++ b/packages/neuron-wallet/src/database/chain/index.ts @@ -13,16 +13,10 @@ import MultisigOutput from './entities/multisig-output' export const clean = async () => { await Promise.all( [InputEntity, OutputEntity, TransactionEntity, IndexerTxHashCache, MultisigOutput].map(entity => { - return getConnection() - .getRepository(entity) - .clear() + return getConnection().getRepository(entity).clear() }) ) MultisigOutputChangedSubject.getSubject().next('reset') - await getConnection() - .createQueryBuilder() - .delete() - .from(SyncInfoEntity) - .execute() + await getConnection().createQueryBuilder().delete().from(SyncInfoEntity).execute() } diff --git a/packages/neuron-wallet/src/database/chain/ormconfig.ts b/packages/neuron-wallet/src/database/chain/ormconfig.ts index 145599e566..e3910ceff3 100644 --- a/packages/neuron-wallet/src/database/chain/ormconfig.ts +++ b/packages/neuron-wallet/src/database/chain/ormconfig.ts @@ -79,7 +79,7 @@ const connectOptions = async (genesisBlockHash: string): Promise Please append debug information exported by "Menu" -> "Help" -> "Export Debug Information".', documentation: 'Documentation', settings: 'Settings', - 'export-debug-info': 'Export Debug Information' + 'export-debug-info': 'Export Debug Information', }, develop: { develop: 'Develop', 'force-reload': 'Force Reload', reload: 'Reload', - 'toggle-dev-tools': 'Toggle Developer Tools' - } + 'toggle-dev-tools': 'Toggle Developer Tools', + }, }, services: { transactions: 'Transactions', - wallets: 'Wallets' + wallets: 'Wallets', }, messages: { 'failed-to-load-networks': 'Failed to load networks.', @@ -134,50 +134,50 @@ export default { 'sudt-acp-have-data': 'The destroying sUDT acp account have amount', 'no-match-address-for-sign': 'Not found matched address', 'target-lock-error': 'CKB asset account can only transfer to sepe256k1 or acp address', - 'no-exist-ckb-node-data': '{{path}} has no CKB Node config and storage, press ok to synchronize from scratch' + 'no-exist-ckb-node-data': '{{path}} has no CKB Node config and storage, press ok to synchronize from scratch', }, messageBox: { button: { confirm: 'OK', - discard: 'Cancel' + discard: 'Cancel', }, 'clear-sync-data': { title: 'Clear all synchronized data', message: - 'Clear all synchronized data will delete all local synchronized data and resynchronize the data on the chain, the whole synchronization may take a long time.' + 'Clear all synchronized data will delete all local synchronized data and resynchronize the data on the chain, the whole synchronization may take a long time.', }, 'send-capacity': { - title: 'Send Transaction' + title: 'Send Transaction', }, 'remove-network': { title: 'Remove Network', message: 'Network {{name}} (address: {{address}}) will be removed.', - alert: 'This is the current network, by removing it, the connection will be switched to the default network' + alert: 'This is the current network, by removing it, the connection will be switched to the default network', }, 'remove-wallet': { title: 'Delete the wallet', - password: 'Password' + password: 'Password', }, 'backup-keystore': { title: 'Backup the Keystore', - password: 'Password' + password: 'Password', }, transaction: { - title: 'Transaction: {{hash}}' + title: 'Transaction: {{hash}}', }, 'sign-and-verify': { - title: 'Sign/verify message' + title: 'Sign/verify message', }, 'multisig-address': { - title: 'Multisig Addresses' + title: 'Multisig Addresses', }, 'ckb-dependency': { title: 'Bundled CKB Node', message: 'Dependency Required', detail: `The embedded CKB node in Neuron requires x64 version of Microsoft Visual C++ Redistributable component to be installed to work properly. You have to install it to enable the internal node.`, buttons: { - 'install-and-exit': 'Install and Exit' - } + 'install-and-exit': 'Install and Exit', + }, }, 'acp-migration': { title: 'Upgrade Asset Account', @@ -186,26 +186,26 @@ export default { 'Recently our security team identified a potential vulnerability in the experimental Asset Account script. We have deployed a new Asset Account script with a fix on mainnet and all future Asset Account will use the new version. We suggest you to upgrade them to use the new script.', buttons: { migrate: 'Secure upgrade now', - skip: 'I know the risk, will upgrade later' - } + skip: 'I know the risk, will upgrade later', + }, }, 'acp-migration-completed': { title: 'Congratulations! You have completed the secure upgrade.', message: 'Congratulations! You have completed the secure upgrade.', buttons: { - ok: 'OK' - } + ok: 'OK', + }, }, 'hard-fork-migrate': { message: - 'In order to adapt to the latest version of CKB, Neuron will resynchronize the data on the chain, and the whole synchronization may take a long time.' + 'In order to adapt to the latest version of CKB, Neuron will resynchronize the data on the chain, and the whole synchronization may take a long time.', }, 'mail-us': { message: 'Please mail us with debug information exported by "Menu" -> "Help" -> "Export Debug Information".', 'open-client': 'Open Mail Client', 'fail-message': 'Unable to launch mail client, please copy the mail address, append debug information exported by "Menu" -> "Help" -> "Export Debug Information" and send us.', - 'copy-mail-addr': 'Copy mail address' + 'copy-mail-addr': 'Copy mail address', }, 'migrate-failed': { title: 'Migrate failed', @@ -213,46 +213,46 @@ export default { 'Migrate failed, press ok to delete old data and synchronize from scratch, or click cancel to migrate later by relanuch Neuron. Migrate fail reason: {{ reason }}', buttons: { ok: 'OK', - cancel: 'Cancel' - } + cancel: 'Cancel', + }, }, 'node-version-different': { - message: 'The node version is inconsistent with Neuron(v {{ version }}), please use after confirmation' + message: 'The node version is inconsistent with Neuron(v {{ version }}), please use after confirmation', }, 'ckb-without-indexer': { - message: "Please add '--indexer' option to start local node" - } + message: "Please add '--indexer' option to start local node", + }, }, prompt: { password: { label: 'Input your password', submit: 'Submit', - cancel: 'Cancel' - } + cancel: 'Cancel', + }, }, updater: { - 'update-not-available': 'There are currently no updates available.' + 'update-not-available': 'There are currently no updates available.', }, common: { yes: 'Yes', no: 'No', ok: 'OK', cancel: 'Cancel', - error: 'Error' + error: 'Error', }, 'export-debug-info': { 'export-debug-info': 'Export Debug Information', - 'debug-info-exported': 'Debug information has been exported to {{ file }}' + 'debug-info-exported': 'Debug information has been exported to {{ file }}', }, about: { 'app-version': '{{name}} Version: {{version}}', - 'ckb-client-version': 'CKB Client Version: {{version}}' + 'ckb-client-version': 'CKB Client Version: {{version}}', }, settings: { title: { normal: 'Settings', - mac: 'Preference' - } + mac: 'Preference', + }, }, 'export-transactions': { 'export-transactions': 'Export Transaction History', @@ -264,19 +264,19 @@ export default { 'tx-type': 'Transaction Type', amount: 'CKB Amount', 'udt-amount': 'UDT Amount', - description: 'Description' + description: 'Description', }, 'tx-type': { send: 'Send', receive: 'Receive', 'create-asset-account': 'Create {{name}} Asset Account', - 'destroy-asset-account': 'Destroy {{name}} Asset Account' - } + 'destroy-asset-account': 'Destroy {{name}} Asset Account', + }, }, 'offline-signature': { 'export-transaction': 'Export Transaction as JSON', 'transaction-exported': 'The transaction have beed exported to {{filePath}}.', - 'load-transaction': 'Load Transaction file' + 'load-transaction': 'Load Transaction file', }, 'multisig-config': { 'import-config': 'Import multisig config', @@ -288,13 +288,13 @@ export default { 'approve-tx': 'Confirm multisig transaction', 'delete-actions': { ok: 'Confirm', - cancel: 'Cancel' - } + cancel: 'Cancel', + }, }, 'open-in-explorer': { title: 'View in CKB Explorer', transaction: 'transaction', - message: 'View {{type}} {{key}} in CKB Explorer' - } - } + message: 'View {{type}} {{key}} in CKB Explorer', + }, + }, } diff --git a/packages/neuron-wallet/src/locales/i18n.ts b/packages/neuron-wallet/src/locales/i18n.ts index 4788e15396..a7a9a69335 100644 --- a/packages/neuron-wallet/src/locales/i18n.ts +++ b/packages/neuron-wallet/src/locales/i18n.ts @@ -7,15 +7,15 @@ i18n.init({ resources: { en, zh, - 'zh-TW': zhTW + 'zh-TW': zhTW, }, fallbackLng: { 'zh-CN': ['zh'], - default: ['en'] + default: ['en'], }, interpolation: { - escapeValue: false - } + escapeValue: false, + }, }) export const changeLanguage = (lng = 'en') => { diff --git a/packages/neuron-wallet/src/locales/zh-tw.ts b/packages/neuron-wallet/src/locales/zh-tw.ts index f2d0a7f90f..d03db44bef 100644 --- a/packages/neuron-wallet/src/locales/zh-tw.ts +++ b/packages/neuron-wallet/src/locales/zh-tw.ts @@ -3,14 +3,14 @@ export default { keywords: { wallet: '錢包', password: '密碼', - 'wallet-name': '錢包名稱' + 'wallet-name': '錢包名稱', }, 'application-menu': { neuron: { about: '關於{{app}}', preferences: '偏好設定...', 'check-updates': '檢查更新...', - quit: '退出{{app}}' + quit: '退出{{app}}', }, wallet: { label: '錢包', @@ -24,26 +24,26 @@ export default { 'import-mnemonic': '導入助記詞', 'import-keystore': '導入 Keystore 檔案', 'import-xpubkey': '導入 Extended Public Key', - 'import-hardware': '導入硬體錢包' + 'import-hardware': '導入硬體錢包', }, edit: { label: '編輯', cut: '剪下', copy: '複製', paste: '貼上', - selectall: '全選' + selectall: '全選', }, tools: { label: '工具', 'sign-and-verify': '簽名/驗簽信息', 'multisig-address': '多簽地址', 'offline-sign': '離線簽名', - 'clear-sync-data': '清除所有同步數據' + 'clear-sync-data': '清除所有同步數據', }, window: { label: '視窗', minimize: '最小化', - close: '關閉視窗' + close: '關閉視窗', }, help: { label: '幫助', @@ -54,18 +54,18 @@ export default { 'contact-us-message': '> 請通過 "菜單" -> "幫助" -> "導出調試信息" 獲得 Neuron 的調試信息並附在郵件中.', documentation: '使用說明', settings: '設定', - 'export-debug-info': '導出除錯信息' + 'export-debug-info': '導出除錯信息', }, develop: { develop: '開發', 'force-reload': '強制重新載入', reload: '重新載入', - 'toggle-dev-tools': '開發者工具' - } + 'toggle-dev-tools': '開發者工具', + }, }, services: { transactions: '交易', - wallets: '錢包' + wallets: '錢包', }, messages: { 'failed-to-load-networks': '載入節點失敗。', @@ -124,41 +124,41 @@ export default { 'sudt-acp-have-data': '待銷毀的 sUDT 賬戶資產不為 0', 'no-match-address-for-sign': '没有找到匹配的地址', 'target-lock-error': 'CKB 資產只能轉賬到 secp256k1 或者 acp 地址', - 'no-exist-ckb-node-data': '{{path}} 目錄下沒有找到 CKB Node 配置和數據, 點擊繼續重新同步' + 'no-exist-ckb-node-data': '{{path}} 目錄下沒有找到 CKB Node 配置和數據, 點擊繼續重新同步', }, messageBox: { button: { confirm: '確定', - discard: '放棄' + discard: '放棄', }, 'send-capacity': { - title: '發送交易' + title: '發送交易', }, 'clear-sync-data': { title: '清除同步數據', - message: '清除所有同步數據會重置所有本地節點數據並重新同步,整個過程可能會消耗較長時間。' + message: '清除所有同步數據會重置所有本地節點數據並重新同步,整個過程可能會消耗較長時間。', }, 'remove-network': { title: '删除網路', message: '將删除網路 {{name}}(地址: {{address}})的設定.', - alert: '這是當前連接網路,删除後會連接到默認網路' + alert: '這是當前連接網路,删除後會連接到默認網路', }, 'remove-wallet': { title: '删除錢包', - password: '密碼' + password: '密碼', }, 'backup-keystore': { title: '備份 Keystore 檔案', - password: '密碼' + password: '密碼', }, transaction: { - title: '交易: {{hash}}' + title: '交易: {{hash}}', }, 'sign-and-verify': { - title: '簽名/驗簽信息' + title: '簽名/驗簽信息', }, 'multisig-address': { - title: '多簽地址' + title: '多簽地址', }, 'ckb-dependency': { title: '內置 CKB 節點', @@ -166,8 +166,8 @@ export default { detail: 'Neuron 內置的 CKB 節點需要安裝 x64 版本的 Microsoft Visual C++ Redistributable 才能正常運行。您需要安裝該組件來啟動內置節點。', buttons: { - 'install-and-exit': '安裝並退出' - } + 'install-and-exit': '安裝並退出', + }, }, 'acp-migration': { title: '升級資產賬戶', @@ -176,71 +176,71 @@ export default { '我們的安全團隊在近期在實驗性的資產賬戶腳本中定位了壹個潛在的安全性問題。我們已經部署了新的資產賬戶腳本來替換舊腳本,未來的資產賬戶也會采納新的腳本。建議您立即升級以使用新的賬戶腳本。', buttons: { migrate: '安全升級', - skip: '已知風險,稍後升級' - } + skip: '已知風險,稍後升級', + }, }, 'acp-migration-completed': { title: '恭喜!您已經完成安全升級。', message: '恭喜!您已經完成安全升級。', buttons: { - ok: 'OK' - } + ok: 'OK', + }, }, 'hard-fork-migrate': { - message: '為適配最新版本的 CKB 節點,Neuron 將會重新同步鏈上數據,整個同步可能時間較長' + message: '為適配最新版本的 CKB 節點,Neuron 將會重新同步鏈上數據,整個同步可能時間較長', }, 'mail-us': { message: '請將問題及調試信息通過郵件發給我們, 調試信息可以通過 "菜單" -> "幫助" -> "導出調試信息" 獲得', 'open-client': '打開郵件客戶端', 'fail-message': '未能打開郵件客戶端, 請複製郵件地址, 並通過 "菜單" -> "幫助" -> "導出調試信息" 獲得 Neuron 的調試信息附在郵件中發送給我們', - 'copy-mail-addr': '複製郵件地址' + 'copy-mail-addr': '複製郵件地址', }, 'migrate-failed': { title: '數據遷移失敗', message: '數據遷移失敗, 點擊確認刪除數據並重新同步, 點擊取消稍後重啟後再次嘗試。失敗原因: {{ reason }}', buttons: { ok: '確認', - cancel: '取消' - } + cancel: '取消', + }, }, 'node-version-different': { - message: '節點版本與 Neuron(v {{ version }}) 不壹致,請確認後使用' + message: '節點版本與 Neuron(v {{ version }}) 不壹致,請確認後使用', }, 'ckb-without-indexer': { - message: "請添加 '--indexer' 參數來啟動本地節點" - } + message: "請添加 '--indexer' 參數來啟動本地節點", + }, }, prompt: { password: { label: '請輸入密碼', submit: '提交', - cancel: '取消' - } + cancel: '取消', + }, }, updater: { - 'update-not-available': '沒有可供升級的新版本。' + 'update-not-available': '沒有可供升級的新版本。', }, common: { yes: '是', no: '否', ok: '確定', cancel: '取消', - error: '錯誤' + error: '錯誤', }, 'export-debug-info': { 'export-debug-info': '導出除錯信息', - 'debug-info-exported': '除錯信息已被導出至 {{ file }}' + 'debug-info-exported': '除錯信息已被導出至 {{ file }}', }, about: { 'app-version': '{{name}} 版本: {{version}}', - 'ckb-client-version': 'CKB 節點版本: {{version}}' + 'ckb-client-version': 'CKB 節點版本: {{version}}', }, settings: { title: { normal: '設置', - mac: '偏好設置' - } + mac: '偏好設置', + }, }, 'export-transactions': { 'export-transactions': '導出交易歷史', @@ -252,19 +252,19 @@ export default { 'tx-type': '交易類型', amount: 'CKB 金額', 'udt-amount': 'UDT 金額', - description: '備註' + description: '備註', }, 'tx-type': { send: '轉賬', receive: '收款', 'create-asset-account': '創建 {{name}} 資產賬戶', - 'destroy-asset-account': '銷毀 {{name}} 資產賬戶' - } + 'destroy-asset-account': '銷毀 {{name}} 資產賬戶', + }, }, 'offline-signature': { 'export-transaction': '導出交易為 JSON 檔案', 'transaction-exported': '交易已被導出至 {{filePath}}.', - 'load-transaction': '加載交易檔案' + 'load-transaction': '加載交易檔案', }, 'multisig-config': { 'import-config': '導入多簽配置', @@ -276,13 +276,13 @@ export default { 'approve-tx': '確認多簽交易', 'delete-actions': { ok: '確認', - cancel: '取消' - } + cancel: '取消', + }, }, 'open-in-explorer': { title: '在 CKB 瀏覽器中查看', transaction: '交易', - message: '在 CKB 瀏覽器中查看 {{type}} {{key}}' - } - } + message: '在 CKB 瀏覽器中查看 {{type}} {{key}}', + }, + }, } diff --git a/packages/neuron-wallet/src/locales/zh.ts b/packages/neuron-wallet/src/locales/zh.ts index 708e03bfa8..a9b432473b 100644 --- a/packages/neuron-wallet/src/locales/zh.ts +++ b/packages/neuron-wallet/src/locales/zh.ts @@ -3,14 +3,14 @@ export default { keywords: { wallet: '钱包', password: '密码', - 'wallet-name': '钱包名称' + 'wallet-name': '钱包名称', }, 'application-menu': { neuron: { about: '关于{{app}}', preferences: '偏好设置...', 'check-updates': '检查更新...', - quit: '退出{{app}}' + quit: '退出{{app}}', }, wallet: { label: '钱包', @@ -24,26 +24,26 @@ export default { 'import-mnemonic': '导入助记词', 'import-keystore': '导入 Keystore 文件', 'import-xpubkey': '导入 Extended Public Key', - 'import-hardware': '导入硬件钱包' + 'import-hardware': '导入硬件钱包', }, edit: { label: '编辑', cut: '剪切', copy: '复制', paste: '粘贴', - selectall: '全部选中' + selectall: '全部选中', }, tools: { label: '工具', 'sign-and-verify': '签名/验签信息', 'multisig-address': '多签地址', 'offline-sign': '离线签名', - 'clear-sync-data': '清除所有同步数据' + 'clear-sync-data': '清除所有同步数据', }, window: { label: '窗口', minimize: '最小化', - close: '关闭窗口' + close: '关闭窗口', }, help: { label: '帮助', @@ -54,18 +54,18 @@ export default { 'contact-us-message': '> 请通过 "菜单" -> "帮助" -> "导出调试信息" 获得 Neuron 的调试信息并附在邮件中.', documentation: '使用文档', settings: '设置', - 'export-debug-info': '导出调试信息' + 'export-debug-info': '导出调试信息', }, develop: { develop: '开发', 'force-reload': '强制刷新', reload: '刷新', - 'toggle-dev-tools': '开发者工具' - } + 'toggle-dev-tools': '开发者工具', + }, }, services: { transactions: '交易', - wallets: '钱包' + wallets: '钱包', }, messages: { 'failed-to-load-networks': '加载节点失败。', @@ -125,41 +125,41 @@ export default { 'sudt-acp-have-data': '待销毁的 sUDT 账户资产不为 0', 'no-match-address-for-sign': '没有找到匹配的地址', 'target-lock-error': 'CKB 资产只能转账到 secp256k1 或者 acp 地址', - 'no-exist-ckb-node-data': '{{path}} 目录下没有找到 CKB Node 配置和数据, 点击继续重新同步' + 'no-exist-ckb-node-data': '{{path}} 目录下没有找到 CKB Node 配置和数据, 点击继续重新同步', }, messageBox: { button: { confirm: '确定', - discard: '放弃' + discard: '放弃', }, 'send-capacity': { - title: '发送交易' + title: '发送交易', }, 'clear-sync-data': { title: '清除同步数据', - message: '清除所有同步数据会重置所有本地节点数据并重新同步,整个过程可能会消耗较长时间。' + message: '清除所有同步数据会重置所有本地节点数据并重新同步,整个过程可能会消耗较长时间。', }, 'remove-network': { title: '删除网络', message: '将删除网络 {{name}}(地址: {{address}})的设置.', - alert: '这是当前连接网络, 删除后会连接到默认网络' + alert: '这是当前连接网络, 删除后会连接到默认网络', }, 'remove-wallet': { title: '删除钱包', - password: '密码' + password: '密码', }, 'backup-keystore': { title: '备份 Keystore 文件', - password: '密码' + password: '密码', }, transaction: { - title: '交易: {{hash}}' + title: '交易: {{hash}}', }, 'sign-and-verify': { - title: '签名/验签信息' + title: '签名/验签信息', }, 'multisig-address': { - title: '多签地址' + title: '多签地址', }, 'ckb-dependency': { title: '内置 CKB 节点', @@ -167,8 +167,8 @@ export default { detail: 'Neuron 内置的 CKB 节点需要安装 x64 版本的 Microsoft Visual C++ Redistributable 才能正常运行。您需要安装该组件来启用内置节点。', buttons: { - 'install-and-exit': '安装并退出' - } + 'install-and-exit': '安装并退出', + }, }, 'acp-migration': { title: '升级资产账户', @@ -177,71 +177,71 @@ export default { '我们的安全团队在近期在实验性的资产账户脚本中定位了一个潜在的安全性问题。我们已经部署了新的资产账户脚本来替换旧脚本,未来的资产账户也会采纳新的脚本。建议您立即升级以使用新的账户脚本。', buttons: { migrate: '安全升级', - skip: '已知风险,稍后升级' - } + skip: '已知风险,稍后升级', + }, }, 'acp-migration-completed': { title: '恭喜!您已经完成安全升级。', message: '恭喜!您已经完成安全升级。', buttons: { - ok: 'OK' - } + ok: 'OK', + }, }, 'hard-fork-migrate': { - message: '为适配最新版本的 CKB 节点,Neuron 将会重新同步链上数据,整个同步可能时间较长' + message: '为适配最新版本的 CKB 节点,Neuron 将会重新同步链上数据,整个同步可能时间较长', }, 'mail-us': { message: '请将问题及调试信息通过邮件发给我们, 调试信息可以通过 "菜单" -> "帮助" -> "导出调试信息" 获得', 'open-client': '打开邮件客户端', 'fail-message': '未能打开邮件客户端, 请复制邮件地址, 并通过 "菜单" -> "帮助" -> "导出调试信息" 获得 Neuron 的调试信息附在邮件中发送给我们', - 'copy-mail-addr': '复制邮件地址' + 'copy-mail-addr': '复制邮件地址', }, 'migrate-failed': { title: '数据迁移失败', message: '数据迁移失败, 点击确认删除数据并重新同步, 点击取消稍后重启后再次尝试。失败原因: {{ reason }}', buttons: { ok: '确认', - cancel: '取消' - } + cancel: '取消', + }, }, 'node-version-different': { - message: '节点版本与 Neuron(v {{ version }}) 不一致,请确认后使用' + message: '节点版本与 Neuron(v {{ version }}) 不一致,请确认后使用', }, 'ckb-without-indexer': { - message: "请添加 '--indexer' 参数来启动本地节点" - } + message: "请添加 '--indexer' 参数来启动本地节点", + }, }, prompt: { password: { label: '请输入密码', submit: '提交', - cancel: '取消' - } + cancel: '取消', + }, }, updater: { - 'update-not-available': '没有可供升级的新版本。' + 'update-not-available': '没有可供升级的新版本。', }, common: { yes: '是', no: '否', ok: '确定', cancel: '取消', - error: '错误' + error: '错误', }, 'export-debug-info': { 'export-debug-info': '导出调试信息', - 'debug-info-exported': '调试信息已被导出至 {{ file }}' + 'debug-info-exported': '调试信息已被导出至 {{ file }}', }, about: { 'app-version': '{{name}} 版本: {{version}}', - 'ckb-client-version': 'CKB 节点版本: {{version}}' + 'ckb-client-version': 'CKB 节点版本: {{version}}', }, settings: { title: { normal: '设置', - mac: '偏好设置' - } + mac: '偏好设置', + }, }, 'export-transactions': { 'export-transactions': '导出交易历史', @@ -253,19 +253,19 @@ export default { 'tx-type': '交易类型', amount: 'CKB 金额', 'udt-amount': 'UDT 金额', - description: '备注' + description: '备注', }, 'tx-type': { send: '转账', receive: '收款', 'create-asset-account': '创建 {{name}} 资产账户', - 'destroy-asset-account': '销毁 {{name}} 资产账户' - } + 'destroy-asset-account': '销毁 {{name}} 资产账户', + }, }, 'offline-signature': { 'export-transaction': '导出交易为 JSON 文件', 'transaction-exported': '交易已被导出至 {{filePath}}.', - 'load-transaction': '加载交易文件' + 'load-transaction': '加载交易文件', }, 'multisig-config': { 'import-config': '导入多签配置', @@ -277,13 +277,13 @@ export default { 'approve-tx': '确认多签交易', 'delete-actions': { ok: '确认', - cancel: '取消' - } + cancel: '取消', + }, }, 'open-in-explorer': { title: '在 CKB 浏览器中查看', transaction: '交易', - message: '在 CKB 浏览器中查看 {{type}} {{key}}' - } - } + message: '在 CKB 浏览器中查看 {{type}} {{key}}', + }, + }, } diff --git a/packages/neuron-wallet/src/models/address.ts b/packages/neuron-wallet/src/models/address.ts index 00aaa87662..7b3940cb95 100644 --- a/packages/neuron-wallet/src/models/address.ts +++ b/packages/neuron-wallet/src/models/address.ts @@ -2,7 +2,7 @@ import { AddressType } from '../models/keys/address' export enum AddressVersion { Testnet = 'testnet', - Mainnet = 'mainnet' + Mainnet = 'mainnet', } export interface Address { diff --git a/packages/neuron-wallet/src/models/asset-account-info.ts b/packages/neuron-wallet/src/models/asset-account-info.ts index a6646d2886..dac6d3722a 100644 --- a/packages/neuron-wallet/src/models/asset-account-info.ts +++ b/packages/neuron-wallet/src/models/asset-account-info.ts @@ -31,7 +31,7 @@ export default class AssetAccountInfo { return { sudt: this.sudt, sudtInfo: this.sudtInfo, - anyoneCanPay: this.anyoneCanPayInfo + anyoneCanPay: this.anyoneCanPayInfo, } } @@ -43,7 +43,7 @@ export default class AssetAccountInfo { process.env.MAINNET_SUDT_DEP_TYPE! as DepType ), codeHash: process.env.MAINNET_SUDT_SCRIPT_CODEHASH!, - hashType: process.env.MAINNET_SUDT_SCRIPT_HASHTYPE! as ScriptHashType + hashType: process.env.MAINNET_SUDT_SCRIPT_HASHTYPE! as ScriptHashType, } this.sudtInfo = { cellDep: new CellDep( @@ -51,7 +51,7 @@ export default class AssetAccountInfo { process.env.MAINNET_SUDT_INFO_DEP_TYPE! as DepType ), codeHash: process.env.MAINNET_SUDT_INFO_SCRIPT_CODEHASH!, - hashType: process.env.MAINNET_SUDT_INFO_SCRIPT_HASHTYPE! as ScriptHashType + hashType: process.env.MAINNET_SUDT_INFO_SCRIPT_HASHTYPE! as ScriptHashType, } this.anyoneCanPayInfo = { cellDep: new CellDep( @@ -59,7 +59,7 @@ export default class AssetAccountInfo { process.env.MAINNET_ACP_DEP_TYPE! as DepType ), codeHash: process.env.MAINNET_ACP_SCRIPT_CODEHASH!, - hashType: process.env.MAINNET_ACP_SCRIPT_HASHTYPE! as ScriptHashType + hashType: process.env.MAINNET_ACP_SCRIPT_HASHTYPE! as ScriptHashType, } this.legacyAnyoneCanPayInfo = { cellDep: new CellDep( @@ -67,7 +67,7 @@ export default class AssetAccountInfo { process.env.LEGACY_MAINNET_ACP_DEP_TYPE! as DepType ), codeHash: process.env.LEGACY_MAINNET_ACP_SCRIPT_CODEHASH!, - hashType: process.env.LEGACY_MAINNET_ACP_SCRIPT_HASHTYPE! as ScriptHashType + hashType: process.env.LEGACY_MAINNET_ACP_SCRIPT_HASHTYPE! as ScriptHashType, } this.pwAnyoneCanPayInfo = { cellDep: new CellDep( @@ -75,7 +75,7 @@ export default class AssetAccountInfo { process.env.MAINNET_PW_ACP_DEP_TYPE! as DepType ), codeHash: process.env.MAINNET_PW_ACP_SCRIPT_CODEHASH!, - hashType: process.env.MAINNET_PW_ACP_SCRIPT_HASHTYPE! as ScriptHashType + hashType: process.env.MAINNET_PW_ACP_SCRIPT_HASHTYPE! as ScriptHashType, } this.chequeInfo = { cellDep: new CellDep( @@ -83,7 +83,7 @@ export default class AssetAccountInfo { process.env.MAINNET_CHEQUE_DEP_TYPE! as DepType ), codeHash: process.env.MAINNET_CHEQUE_SCRIPT_CODEHASH!, - hashType: process.env.MAINNET_CHEQUE_SCRIPT_HASHTYPE! as ScriptHashType + hashType: process.env.MAINNET_CHEQUE_SCRIPT_HASHTYPE! as ScriptHashType, } this.nftIssuerInfo = { cellDep: new CellDep( @@ -91,7 +91,7 @@ export default class AssetAccountInfo { process.env.MAINNET_NFT_ISSUER_DEP_TYPE as DepType ), codeHash: process.env.MAINNET_NFT_ISSUER_SCRIPT_CODEHASH!, - hashType: process.env.MAINNET_NFT_ISSUER_SCRIPT_HASH_TYPE! as ScriptHashType + hashType: process.env.MAINNET_NFT_ISSUER_SCRIPT_HASH_TYPE! as ScriptHashType, } this.nftClassInfo = { cellDep: new CellDep( @@ -99,7 +99,7 @@ export default class AssetAccountInfo { process.env.MAINNET_NFT_CLASS_DEP_TYPE as DepType ), codeHash: process.env.MAINNET_NFT_CLASS_SCRIPT_CODEHASH!, - hashType: process.env.MAINNET_NFT_CLASS_SCRIPT_HASH_TYPE! as ScriptHashType + hashType: process.env.MAINNET_NFT_CLASS_SCRIPT_HASH_TYPE! as ScriptHashType, } this.nftInfo = { cellDep: new CellDep( @@ -107,7 +107,7 @@ export default class AssetAccountInfo { process.env.MAINNET_NFT_DEP_TYPE as DepType ), codeHash: process.env.MAINNET_NFT_SCRIPT_CODEHASH!, - hashType: process.env.MAINNET_NFT_SCRIPT_HASH_TYPE! as ScriptHashType + hashType: process.env.MAINNET_NFT_SCRIPT_HASH_TYPE! as ScriptHashType, } } else { this.sudt = { @@ -116,7 +116,7 @@ export default class AssetAccountInfo { process.env.TESTNET_SUDT_DEP_TYPE! as DepType ), codeHash: process.env.TESTNET_SUDT_SCRIPT_CODEHASH!, - hashType: process.env.TESTNET_SUDT_SCRIPT_HASHTYPE! as ScriptHashType + hashType: process.env.TESTNET_SUDT_SCRIPT_HASHTYPE! as ScriptHashType, } this.sudtInfo = { cellDep: new CellDep( @@ -124,7 +124,7 @@ export default class AssetAccountInfo { process.env.TESTNET_SUDT_INFO_DEP_TYPE! as DepType ), codeHash: process.env.TESTNET_SUDT_INFO_SCRIPT_CODEHASH!, - hashType: process.env.TESTNET_SUDT_INFO_SCRIPT_HASHTYPE! as ScriptHashType + hashType: process.env.TESTNET_SUDT_INFO_SCRIPT_HASHTYPE! as ScriptHashType, } this.anyoneCanPayInfo = { cellDep: new CellDep( @@ -132,7 +132,7 @@ export default class AssetAccountInfo { process.env.TESTNET_ACP_DEP_TYPE! as DepType ), codeHash: process.env.TESTNET_ACP_SCRIPT_CODEHASH!, - hashType: process.env.TESTNET_ACP_SCRIPT_HASHTYPE! as ScriptHashType + hashType: process.env.TESTNET_ACP_SCRIPT_HASHTYPE! as ScriptHashType, } this.legacyAnyoneCanPayInfo = { cellDep: new CellDep( @@ -140,7 +140,7 @@ export default class AssetAccountInfo { process.env.LEGACY_TESTNET_ACP_DEP_TYPE! as DepType ), codeHash: process.env.LEGACY_TESTNET_ACP_SCRIPT_CODEHASH!, - hashType: process.env.LEGACY_TESTNET_ACP_SCRIPT_HASHTYPE! as ScriptHashType + hashType: process.env.LEGACY_TESTNET_ACP_SCRIPT_HASHTYPE! as ScriptHashType, } this.pwAnyoneCanPayInfo = { cellDep: new CellDep( @@ -148,7 +148,7 @@ export default class AssetAccountInfo { process.env.TESTNET_PW_ACP_DEP_TYPE! as DepType ), codeHash: process.env.TESTNET_PW_ACP_SCRIPT_CODEHASH!, - hashType: process.env.TESTNET_PW_ACP_SCRIPT_HASHTYPE! as ScriptHashType + hashType: process.env.TESTNET_PW_ACP_SCRIPT_HASHTYPE! as ScriptHashType, } this.chequeInfo = { cellDep: new CellDep( @@ -156,7 +156,7 @@ export default class AssetAccountInfo { process.env.TESTNET_CHEQUE_DEP_TYPE! as DepType ), codeHash: process.env.TESTNET_CHEQUE_SCRIPT_CODEHASH!, - hashType: process.env.TESTNET_CHEQUE_SCRIPT_HASHTYPE! as ScriptHashType + hashType: process.env.TESTNET_CHEQUE_SCRIPT_HASHTYPE! as ScriptHashType, } this.nftIssuerInfo = { cellDep: new CellDep( @@ -164,7 +164,7 @@ export default class AssetAccountInfo { process.env.TESTNET_NFT_ISSUER_DEP_TYPE as DepType ), codeHash: process.env.TESTNET_NFT_ISSUER_SCRIPT_CODEHASH!, - hashType: process.env.TESTNET_NFT_ISSUER_SCRIPT_HASH_TYPE! as ScriptHashType + hashType: process.env.TESTNET_NFT_ISSUER_SCRIPT_HASH_TYPE! as ScriptHashType, } this.nftClassInfo = { cellDep: new CellDep( @@ -172,7 +172,7 @@ export default class AssetAccountInfo { process.env.TESTNET_NFT_CLASS_DEP_TYPE as DepType ), codeHash: process.env.TESTNET_NFT_CLASS_SCRIPT_CODEHASH!, - hashType: process.env.TESTNET_NFT_CLASS_SCRIPT_HASH_TYPE! as ScriptHashType + hashType: process.env.TESTNET_NFT_CLASS_SCRIPT_HASH_TYPE! as ScriptHashType, } this.nftInfo = { cellDep: new CellDep( @@ -180,7 +180,7 @@ export default class AssetAccountInfo { process.env.TESTNET_NFT_DEP_TYPE as DepType ), codeHash: process.env.TESTNET_NFT_SCRIPT_CODEHASH!, - hashType: process.env.TESTNET_NFT_SCRIPT_HASH_TYPE! as ScriptHashType + hashType: process.env.TESTNET_NFT_SCRIPT_HASH_TYPE! as ScriptHashType, } } } diff --git a/packages/neuron-wallet/src/models/chain/cell-dep.ts b/packages/neuron-wallet/src/models/chain/cell-dep.ts index a34ec89cd4..c8830809ed 100644 --- a/packages/neuron-wallet/src/models/chain/cell-dep.ts +++ b/packages/neuron-wallet/src/models/chain/cell-dep.ts @@ -2,7 +2,7 @@ import OutPoint from './out-point' export enum DepType { Code = 'code', - DepGroup = 'depGroup' + DepGroup = 'depGroup', } export default class CellDep { @@ -21,7 +21,7 @@ export default class CellDep { public toSDK(): CKBComponents.CellDep { return { outPoint: this.outPoint.toSDK(), - depType: this.depType + depType: this.depType, } } diff --git a/packages/neuron-wallet/src/models/chain/input.ts b/packages/neuron-wallet/src/models/chain/input.ts index 6b6afe0e1c..ec3dacece7 100644 --- a/packages/neuron-wallet/src/models/chain/input.ts +++ b/packages/neuron-wallet/src/models/chain/input.ts @@ -57,7 +57,7 @@ export default class Input { multiSignBlake160, type, typeHash, - data + data, }: { previousOutput: OutPoint | null since?: string @@ -113,7 +113,7 @@ export default class Input { public toSDK(): CKBComponents.CellInput { return { since: HexUtils.toHex(this.since!), - previousOutput: this.previousOutput?.toSDK() || null + previousOutput: this.previousOutput?.toSDK() || null, } } diff --git a/packages/neuron-wallet/src/models/chain/live-cell.ts b/packages/neuron-wallet/src/models/chain/live-cell.ts index 6cd68eb9c4..e72fa4b57b 100644 --- a/packages/neuron-wallet/src/models/chain/live-cell.ts +++ b/packages/neuron-wallet/src/models/chain/live-cell.ts @@ -5,7 +5,7 @@ import { LumosCell } from '../../block-sync-renderer/sync/indexer-connector' const LUMOS_HASH_TYPE_MAP: Record = { type: ScriptHashType.Type, data1: ScriptHashType.Data1, - data: ScriptHashType.Data + data: ScriptHashType.Data, } export default class LiveCell { diff --git a/packages/neuron-wallet/src/models/chain/out-point.ts b/packages/neuron-wallet/src/models/chain/out-point.ts index a5c54ef31d..1f889e7f16 100644 --- a/packages/neuron-wallet/src/models/chain/out-point.ts +++ b/packages/neuron-wallet/src/models/chain/out-point.ts @@ -21,7 +21,7 @@ export default class OutPoint { public toSDK(): CKBComponents.OutPoint { return { txHash: this.txHash, - index: HexUtils.toHex(this.index) + index: HexUtils.toHex(this.index), } } diff --git a/packages/neuron-wallet/src/models/chain/output.ts b/packages/neuron-wallet/src/models/chain/output.ts index a1700c776d..071a3f24e3 100644 --- a/packages/neuron-wallet/src/models/chain/output.ts +++ b/packages/neuron-wallet/src/models/chain/output.ts @@ -10,7 +10,7 @@ export enum OutputStatus { Live = 'live', Pending = 'pending', Dead = 'dead', - Failed = 'failed' + Failed = 'failed', } // empty string '' means not customized lock / type / data @@ -105,7 +105,7 @@ export default class Output { blockHash, depositOutPoint, depositTimestamp, - multiSignBlake160 + multiSignBlake160, }: { capacity: string data?: string @@ -214,7 +214,7 @@ export default class Output { return { capacity: HexUtils.toHex(this.capacity), lock: this.lock.toSDK(), - type: this.type ? this.type.toSDK() : this.type + type: this.type ? this.type.toSDK() : this.type, } } diff --git a/packages/neuron-wallet/src/models/chain/script.ts b/packages/neuron-wallet/src/models/chain/script.ts index 66901f573e..09a341e039 100644 --- a/packages/neuron-wallet/src/models/chain/script.ts +++ b/packages/neuron-wallet/src/models/chain/script.ts @@ -5,7 +5,7 @@ import TypeChecker from '../../utils/type-checker' export enum ScriptHashType { Data = 'data', Type = 'type', - Data1 = 'data1' + Data1 = 'data1', } export default class Script { @@ -24,7 +24,7 @@ export default class Script { public static fromObject({ codeHash, args, - hashType + hashType, }: { codeHash: string args: string @@ -46,7 +46,7 @@ export default class Script { return { args: this.args, codeHash: this.codeHash, - hashType: this.hashType + hashType: this.hashType, } } diff --git a/packages/neuron-wallet/src/models/chain/transaction.ts b/packages/neuron-wallet/src/models/chain/transaction.ts index 26bd196cbd..d128270a8f 100644 --- a/packages/neuron-wallet/src/models/chain/transaction.ts +++ b/packages/neuron-wallet/src/models/chain/transaction.ts @@ -12,7 +12,7 @@ import { Signatures } from '../../models/offline-sign' export enum TransactionStatus { Pending = 'pending', Success = 'success', - Failed = 'failed' + Failed = 'failed', } export interface SudtTokenInfo { @@ -29,7 +29,7 @@ export interface SudtInfo { export enum NFTType { Send = 'send', - Receive = 'receive' + Receive = 'receive', } export interface NFTInfo { @@ -39,7 +39,7 @@ export interface NFTInfo { export enum AssetAccountType { CKB = 'CKB', - SUDT = 'sUDT' + SUDT = 'sUDT', } export default class Transaction { @@ -167,7 +167,7 @@ export default class Transaction { sudtInfo, nftInfo, signatures = {}, - assetAccountType + assetAccountType, }: { version: string cellDeps?: CellDep[] @@ -279,7 +279,7 @@ export default class Transaction { cellDeps: this.cellDeps.map(cd => cd.toSDK()), headerDeps: this.headerDeps, outputsData: this.outputsData, - witnesses: this.witnessesAsString() + witnesses: this.witnessesAsString(), } } @@ -288,7 +288,7 @@ export default class Transaction { const hash = this.hash || this.computeHash() return { ...this.toSDKRawTransaction(), - hash + hash, } } diff --git a/packages/neuron-wallet/src/models/chain/tx-status.ts b/packages/neuron-wallet/src/models/chain/tx-status.ts index 0dc10193ce..a2c54c553a 100644 --- a/packages/neuron-wallet/src/models/chain/tx-status.ts +++ b/packages/neuron-wallet/src/models/chain/tx-status.ts @@ -3,7 +3,7 @@ import TypeCheckerUtils from '../../utils/type-checker' export enum TxStatusType { Pending = 'pending', Proposed = 'proposed', - Committed = 'committed' + Committed = 'committed', } export default class TxStatus { @@ -31,7 +31,7 @@ export default class TxStatus { public toSDK() { return { blockHash: this.blockHash, - status: this.status + status: this.status, } } diff --git a/packages/neuron-wallet/src/models/chain/witness-args.ts b/packages/neuron-wallet/src/models/chain/witness-args.ts index cef340a92f..c177ec4e4f 100644 --- a/packages/neuron-wallet/src/models/chain/witness-args.ts +++ b/packages/neuron-wallet/src/models/chain/witness-args.ts @@ -14,7 +14,7 @@ export default class WitnessArgs { public static fromObject({ lock, inputType, - outputType + outputType, }: { lock?: string inputType?: string @@ -53,7 +53,7 @@ export default class WitnessArgs { return WitnessArgs.fromObject({ lock: '0x' + buffer.slice(offset0 + 4, offset1).toString('hex'), inputType: inputType === '0x' ? undefined : inputType, - outputType: outputType === '0x' ? undefined : outputType + outputType: outputType === '0x' ? undefined : outputType, }) } @@ -73,7 +73,7 @@ export default class WitnessArgs { return { lock: this.lock, inputType: this.inputType, - outputType: this.outputType + outputType: this.outputType, } } } diff --git a/packages/neuron-wallet/src/models/keys/address.ts b/packages/neuron-wallet/src/models/keys/address.ts index deb60b913a..52f14b79f9 100644 --- a/packages/neuron-wallet/src/models/keys/address.ts +++ b/packages/neuron-wallet/src/models/keys/address.ts @@ -6,7 +6,7 @@ export { AddressPrefix } export enum AddressType { Receiving = 0, // External chain - Change = 1 // Internal chain + Change = 1, // Internal chain } export const publicKeyToAddress = (publicKey: string, isMainnet = false) => { diff --git a/packages/neuron-wallet/src/models/keys/hd-public-key-info.ts b/packages/neuron-wallet/src/models/keys/hd-public-key-info.ts index 73db4fba9c..de0b070121 100644 --- a/packages/neuron-wallet/src/models/keys/hd-public-key-info.ts +++ b/packages/neuron-wallet/src/models/keys/hd-public-key-info.ts @@ -15,7 +15,7 @@ export default class HdPublicKeyInfoModel { { codeHash: SystemScriptInfo.SECP_CODE_HASH, hashType: SystemScriptInfo.SECP_HASH_TYPE, - args: this.publicKeyInBlake160 + args: this.publicKeyInBlake160, }, NetworksService.getInstance().isMainnet() ) diff --git a/packages/neuron-wallet/src/models/keys/key.ts b/packages/neuron-wallet/src/models/keys/key.ts index 1bee2254f8..5e5ae9c939 100644 --- a/packages/neuron-wallet/src/models/keys/key.ts +++ b/packages/neuron-wallet/src/models/keys/key.ts @@ -98,7 +98,7 @@ export class ExtendedPrivateKey { export enum DefaultAddressNumber { Receiving = 20, - Change = 10 + Change = 10, } export interface Addresses { diff --git a/packages/neuron-wallet/src/models/keys/keychain.ts b/packages/neuron-wallet/src/models/keys/keychain.ts index 0663ad00fe..c7a0872e5f 100644 --- a/packages/neuron-wallet/src/models/keys/keychain.ts +++ b/packages/neuron-wallet/src/models/keys/keychain.ts @@ -40,10 +40,7 @@ export default class Keychain { } public static fromSeed = (seed: Buffer): Keychain => { - const i = crypto - .createHmac('sha512', Buffer.from('Bitcoin seed', 'utf8')) - .update(seed) - .digest() + const i = crypto.createHmac('sha512', Buffer.from('Bitcoin seed', 'utf8')).update(seed).digest() const keychain = new Keychain(i.slice(0, 32), i.slice(32)) keychain.calculateFingerprint() return keychain @@ -51,7 +48,7 @@ export default class Keychain { // Create a child keychain with extended public key and path. // Children of this keychain should not have any hardened paths. - public static fromPublicKey = (publicKey: Buffer, chainCode: Buffer, path: String): Keychain => { + public static fromPublicKey = (publicKey: Buffer, chainCode: Buffer, path: string): Keychain => { const keychain = new Keychain(EMPTY_BUFFER, chainCode) keychain.publicKey = publicKey keychain.calculateFingerprint() @@ -77,10 +74,7 @@ export default class Keychain { data = Buffer.concat([this.publicKey, indexBuffer]) } - const i = crypto - .createHmac('sha512', this.chainCode) - .update(data) - .digest() + const i = crypto.createHmac('sha512', this.chainCode).update(data).digest() const il = i.slice(0, 32) const ir = i.slice(32) @@ -108,6 +102,7 @@ export default class Keychain { return this } + // eslint-disable-next-line @typescript-eslint/no-this-alias let bip32: Keychain = this let entries = path.split('/') @@ -123,19 +118,13 @@ export default class Keychain { return bip32 } - isNeutered = (): Boolean => { + isNeutered = (): boolean => { return this.privateKey === EMPTY_BUFFER } hash160 = (data: Buffer): Buffer => { - const sha256 = crypto - .createHash('sha256') - .update(data) - .digest() - return crypto - .createHash('ripemd160') - .update(sha256) - .digest() + const sha256 = crypto.createHash('sha256').update(data).digest() + return crypto.createHash('ripemd160').update(sha256).digest() } private static privateKeyAdd = (privateKey: Buffer, factor: Buffer): Buffer => { @@ -150,11 +139,7 @@ export default class Keychain { private static publicKeyAdd = (publicKey: Buffer, factor: Buffer): Buffer => { const x = new BN(publicKey.slice(1)).toRed(ec.curve.red) - let y = x - .redSqr() - .redIMul(x) - .redIAdd(ec.curve.b) - .redSqrt() + let y = x.redSqr().redIMul(x).redIAdd(ec.curve.b).redSqrt() if ((publicKey[0] === 0x03) !== y.isOdd()) { y = y.redNeg() } diff --git a/packages/neuron-wallet/src/models/keys/keystore.ts b/packages/neuron-wallet/src/models/keys/keystore.ts index 7bbf65050d..3072052764 100644 --- a/packages/neuron-wallet/src/models/keys/keystore.ts +++ b/packages/neuron-wallet/src/models/keys/keystore.ts @@ -61,18 +61,18 @@ export default class Keystore { salt: salt.toString('hex'), n: 2 ** 18, r: 8, - p: 1 + p: 1, } return new Keystore( { ciphertext: '', cipherparams: { - iv: iv.toString('hex') + iv: iv.toString('hex'), }, cipher: CIPHER, kdf: 'scrypt', kdfparams, - mac: '' + mac: '', }, uuid() ) @@ -90,7 +90,7 @@ export default class Keystore { salt: salt.toString('hex'), n: 2 ** 18, r: 8, - p: 1 + p: 1, } const derivedKey = crypto.scryptSync(password, salt, kdfparams.dklen, Keystore.scryptOptions(kdfparams)) @@ -100,19 +100,19 @@ export default class Keystore { } const ciphertext = Buffer.concat([ cipher.update(Buffer.from(extendedPrivateKey.serialize(), 'hex')), - cipher.final() + cipher.final(), ]) return new Keystore( { ciphertext: ciphertext.toString('hex'), cipherparams: { - iv: iv.toString('hex') + iv: iv.toString('hex'), }, cipher: CIPHER, kdf: 'scrypt', kdfparams, - mac: Keystore.mac(derivedKey, ciphertext) + mac: Keystore.mac(derivedKey, ciphertext), }, uuid() ) @@ -167,7 +167,7 @@ export default class Keystore { N: kdfparams.n, r: kdfparams.r, p: kdfparams.p, - maxmem: 128 * (kdfparams.n + kdfparams.p + 2) * kdfparams.r + maxmem: 128 * (kdfparams.n + kdfparams.p + 2) * kdfparams.r, } } } diff --git a/packages/neuron-wallet/src/models/keys/mnemonic/index.ts b/packages/neuron-wallet/src/models/keys/mnemonic/index.ts index 5cfda9ac1f..178d4204ca 100644 --- a/packages/neuron-wallet/src/models/keys/mnemonic/index.ts +++ b/packages/neuron-wallet/src/models/keys/mnemonic/index.ts @@ -30,10 +30,7 @@ const bytesToBinary = (bytes: Buffer): string => { const deriveChecksumBits = (entropyBuffer: Buffer): string => { const ENT = entropyBuffer.length * 8 const CS = ENT / 32 - const hash = crypto - .createHash('sha256') - .update(entropyBuffer) - .digest() + const hash = crypto.createHash('sha256').update(entropyBuffer).digest() return bytesToBinary(hash).slice(0, CS) } @@ -149,5 +146,5 @@ export default { mnemonicToEntropy, mnemonicToSeed, mnemonicToSeedSync, - validateMnemonic + validateMnemonic, } diff --git a/packages/neuron-wallet/src/models/keys/mnemonic/word-list.ts b/packages/neuron-wallet/src/models/keys/mnemonic/word-list.ts index ae7c97e4c9..f5d81d3377 100644 --- a/packages/neuron-wallet/src/models/keys/mnemonic/word-list.ts +++ b/packages/neuron-wallet/src/models/keys/mnemonic/word-list.ts @@ -2046,5 +2046,5 @@ export default [ 'zebra', 'zero', 'zone', - 'zoo' + 'zoo', ] diff --git a/packages/neuron-wallet/src/models/multisig-config.ts b/packages/neuron-wallet/src/models/multisig-config.ts index c830649995..69cbfd9fa2 100644 --- a/packages/neuron-wallet/src/models/multisig-config.ts +++ b/packages/neuron-wallet/src/models/multisig-config.ts @@ -46,7 +46,7 @@ export default class MultisigConfigModel { n: this.n, r: this.r, blake160s: this.blake160s, - alias: this.alias + alias: this.alias, } } diff --git a/packages/neuron-wallet/src/models/multisig.ts b/packages/neuron-wallet/src/models/multisig.ts index 95e4ef73b2..39f2153d41 100644 --- a/packages/neuron-wallet/src/models/multisig.ts +++ b/packages/neuron-wallet/src/models/multisig.ts @@ -72,7 +72,7 @@ export default class Multisig { return { length: (epoch >> BigInt(40)) & BigInt(0xffff), index: (epoch >> BigInt(24)) & BigInt(0xffff), - number: epoch & BigInt(0xffffff) + number: epoch & BigInt(0xffffff), } } diff --git a/packages/neuron-wallet/src/models/network.ts b/packages/neuron-wallet/src/models/network.ts index 68d185fdb4..739be27e9a 100644 --- a/packages/neuron-wallet/src/models/network.ts +++ b/packages/neuron-wallet/src/models/network.ts @@ -1,6 +1,6 @@ export enum NetworkType { Default, // Preset mainnet node - Normal + Normal, } export const MAINNET_GENESIS_HASH = '0x92b197aa1fba0f63633922c61c92375c9c074a93e85963554f5499fe1450d0e5' diff --git a/packages/neuron-wallet/src/models/offline-sign.ts b/packages/neuron-wallet/src/models/offline-sign.ts index 6a74e91bd1..a77182550d 100644 --- a/packages/neuron-wallet/src/models/offline-sign.ts +++ b/packages/neuron-wallet/src/models/offline-sign.ts @@ -4,14 +4,14 @@ import Transaction from './chain/transaction' export enum SignStatus { Signed = 'Signed', Unsigned = 'Unsigned', - PartiallySigned = 'PartiallySigned' + PartiallySigned = 'PartiallySigned', } export enum SignType { Regular = 'Regular', UnlockDAO = 'UnlockDAO', CreateSUDTAccount = 'CreateSUDTAccount', - SendSUDT = 'SendSUDT' + SendSUDT = 'SendSUDT', } interface MultisigConfigs { @@ -75,7 +75,7 @@ export default class OfflineSign implements OfflineSignProps { transaction: this.transaction, type: this.type, status: this.status, - context: this.context + context: this.context, } if (this.assetAccount) { @@ -95,7 +95,7 @@ export default class OfflineSign implements OfflineSignProps { asset_account: assetAcount, status, context, - description + description, }: OfflineSignJSON) { return new OfflineSign(transaction, signType, status, context, assetAcount, description) } diff --git a/packages/neuron-wallet/src/models/subjects/networks.ts b/packages/neuron-wallet/src/models/subjects/networks.ts index a6f7780120..3e53b21f13 100644 --- a/packages/neuron-wallet/src/models/subjects/networks.ts +++ b/packages/neuron-wallet/src/models/subjects/networks.ts @@ -4,10 +4,10 @@ export const NetworkListSubject = new BehaviorSubject<{ currentNetworkList: Controller.Network[] }>({ currentNetworkList: [] }) export const CurrentNetworkIDSubject = new BehaviorSubject<{ currentNetworkID: Controller.NetworkID }>({ - currentNetworkID: '' + currentNetworkID: '', }) export default { NetworkListSubject, - CurrentNetworkIDSubject + CurrentNetworkIDSubject, } diff --git a/packages/neuron-wallet/src/models/subjects/node.ts b/packages/neuron-wallet/src/models/subjects/node.ts index 04427324fd..209e871cba 100644 --- a/packages/neuron-wallet/src/models/subjects/node.ts +++ b/packages/neuron-wallet/src/models/subjects/node.ts @@ -12,7 +12,7 @@ export const ConnectionStatusSubject = new BehaviorSubject({ url: '', connected: false, isBundledNode: true, - startedBundledNode: false + startedBundledNode: false, }) export const getLatestConnectionStatus = async () => { diff --git a/packages/neuron-wallet/src/models/subjects/sync-state-subject.ts b/packages/neuron-wallet/src/models/subjects/sync-state-subject.ts index c60511099c..30222dcbbf 100644 --- a/packages/neuron-wallet/src/models/subjects/sync-state-subject.ts +++ b/packages/neuron-wallet/src/models/subjects/sync-state-subject.ts @@ -15,7 +15,7 @@ const SyncStateSubject = new BehaviorSubject<{ indexRate: undefined, cacheRate: undefined, estimate: undefined, - status: 0 + status: 0, }) export default SyncStateSubject diff --git a/packages/neuron-wallet/src/models/subjects/wallets.ts b/packages/neuron-wallet/src/models/subjects/wallets.ts index 4e348bfbdd..8c01e9780c 100644 --- a/packages/neuron-wallet/src/models/subjects/wallets.ts +++ b/packages/neuron-wallet/src/models/subjects/wallets.ts @@ -13,5 +13,5 @@ export const CurrentWalletSubject = new Subject<{ export default { WalletListSubject, - CurrentWalletSubject + CurrentWalletSubject, } diff --git a/packages/neuron-wallet/src/models/synced-block-number.ts b/packages/neuron-wallet/src/models/synced-block-number.ts index 50562d6dc0..50d9145611 100644 --- a/packages/neuron-wallet/src/models/synced-block-number.ts +++ b/packages/neuron-wallet/src/models/synced-block-number.ts @@ -4,7 +4,6 @@ import logger from '../utils/logger' // Keep track of synced block number. export default class SyncedBlockNumber { - // eslint-disable-next-line prettier/prettier #blockNumberEntity?: SyncInfoEntity #lastSavedBlock: bigint = BigInt(-1) @@ -21,13 +20,15 @@ export default class SyncedBlockNumber { blockNumberEntity.value = current.toString() await getConnection().manager.save(blockNumberEntity) - logger.info("Database:\tsaved synced block #" + current.toString()) + logger.info('Database:\tsaved synced block #' + current.toString()) } } #blockNumber = async (): Promise => { if (!this.#blockNumberEntity) { - let blockNumber = await getConnection().getRepository(SyncInfoEntity).findOne({ name: SyncInfoEntity.CURRENT_BLOCK_NUMBER }) + let blockNumber = await getConnection() + .getRepository(SyncInfoEntity) + .findOne({ name: SyncInfoEntity.CURRENT_BLOCK_NUMBER }) if (!blockNumber) { blockNumber = new SyncInfoEntity() diff --git a/packages/neuron-wallet/src/models/transaction-size.ts b/packages/neuron-wallet/src/models/transaction-size.ts index 887b8315c1..4bdca0deb3 100644 --- a/packages/neuron-wallet/src/models/transaction-size.ts +++ b/packages/neuron-wallet/src/models/transaction-size.ts @@ -37,7 +37,7 @@ export default class TransactionSize { const hash20 = '0x' + '0'.repeat(40) const sudtOutput = Output.fromObject({ capacity: '61', - lock: new Script(hash32, hash20, ScriptHashType.Type) + lock: new Script(hash32, hash20, ScriptHashType.Type), }) return TransactionSize.output(sudtOutput) } @@ -49,7 +49,7 @@ export default class TransactionSize { const sudtOutput = Output.fromObject({ capacity: '142', lock: new Script(hash32, hash20, ScriptHashType.Type), - type: new Script(hash32, hash32, ScriptHashType.Type) + type: new Script(hash32, hash32, ScriptHashType.Type), }) return TransactionSize.output(sudtOutput) } @@ -101,7 +101,7 @@ export default class TransactionSize { this.input() * tx.inputs.length, ...tx.outputs.map(o => this.output(o)), ...tx.outputsData.map(data => this.outputData(data)), - ...tx.witnesses.map(wit => this.witness(wit)) + ...tx.witnesses.map(wit => this.witness(wit)), ].reduce((result, c) => result + c, 0) } } diff --git a/packages/neuron-wallet/src/services/addresses.ts b/packages/neuron-wallet/src/services/addresses.ts index a3ae9e870c..a7b731a301 100644 --- a/packages/neuron-wallet/src/services/addresses.ts +++ b/packages/neuron-wallet/src/services/addresses.ts @@ -47,7 +47,7 @@ export default class AddressService { .map(addr => { return HdPublicKeyInfo.fromObject({ ...addr, - publicKeyInBlake160: addr.blake160 + publicKeyInBlake160: addr.blake160, }) }) if (publicKeyInfos.length) { @@ -167,7 +167,7 @@ export default class AddressService { walletId, publicKey, addressType, - addressIndex + addressIndex, }: { walletId: string publicKey: string @@ -183,7 +183,7 @@ export default class AddressService { .createQueryBuilder() .where({ walletId, - publicKeyInBlake160: publicKeyHash + publicKeyInBlake160: publicKeyHash, }) .getRawOne() @@ -195,7 +195,7 @@ export default class AddressService { walletId, addressType, addressIndex, - publicKeyInBlake160: publicKeyHash + publicKeyInBlake160: publicKeyHash, }) await getConnection().manager.save(publicKeyInfo) @@ -224,7 +224,7 @@ export default class AddressService { walletId, addressType: AddressType.Receiving, addressIndex: idx + receivingStartIndex, - accountExtendedPublicKey: extendedKey + accountExtendedPublicKey: extendedKey, } return AddressService.toAddress(addressMetaInfo) }) @@ -233,13 +233,13 @@ export default class AddressService { walletId, addressType: AddressType.Change, addressIndex: idx + changeStartIndex, - accountExtendedPublicKey: extendedKey + accountExtendedPublicKey: extendedKey, } return AddressService.toAddress(addressMetaInfo) }) return { receiving, - change + change, } } @@ -259,7 +259,7 @@ export default class AddressService { path, addressType: addressMetaInfo.addressType, addressIndex: addressMetaInfo.addressIndex, - blake160 + blake160, } return addressInfo @@ -345,10 +345,7 @@ export default class AddressService { } public static getAddressesByAllWallets = async (): Promise => { - const publicKeyInfos = await getConnection() - .getRepository(HdPublicKeyInfo) - .createQueryBuilder() - .getMany() + const publicKeyInfos = await getConnection().getRepository(HdPublicKeyInfo).createQueryBuilder().getMany() return publicKeyInfos.map(publicKeyInfo => AddressMeta.fromHdPublicKeyInfoModel(publicKeyInfo.toModel())) } @@ -383,13 +380,13 @@ export default class AddressService { const { liveBalances, sentBalances, pendingBalances } = await CellsService.getBalancesByWalletId(walletId) const txCountsByLock = await TransactionsService.getTxCountsByWalletId(walletId, { codeHash: SystemScriptInfo.SECP_CODE_HASH, - hashType: SystemScriptInfo.SECP_HASH_TYPE + hashType: SystemScriptInfo.SECP_HASH_TYPE, }) const allAddressesWithBalances = addresses.map(address => { const script = Script.fromObject({ codeHash: SystemScriptInfo.SECP_CODE_HASH, hashType: SystemScriptInfo.SECP_HASH_TYPE, - args: address.blake160 + args: address.blake160, }) const lockHash = script.computeHash() const liveBalance = liveBalances.get(lockHash) || '0' @@ -405,7 +402,7 @@ export default class AddressService { sentBalance, pendingBalance, balance, - txCount + txCount, } }) return allAddressesWithBalances @@ -434,11 +431,6 @@ export default class AddressService { } public static async deleteByWalletId(walletId: string): Promise { - await getConnection() - .createQueryBuilder() - .delete() - .from(HdPublicKeyInfo) - .where({ walletId }) - .execute() + await getConnection().createQueryBuilder().delete().from(HdPublicKeyInfo).where({ walletId }).execute() } } diff --git a/packages/neuron-wallet/src/services/anyone-can-pay.ts b/packages/neuron-wallet/src/services/anyone-can-pay.ts index f41ae2db85..5d68a50097 100644 --- a/packages/neuron-wallet/src/services/anyone-can-pay.ts +++ b/packages/neuron-wallet/src/services/anyone-can-pay.ts @@ -30,7 +30,7 @@ export default class AnyoneCanPayService { .getRepository(AssetAccountEntity) .createQueryBuilder('aa') .where({ - id: assetAccountID + id: assetAccountID, }) .getOne() if (!assetAccount) { @@ -80,7 +80,7 @@ export default class AnyoneCanPayService { return Output.fromObject({ capacity: '0', lock: lockScript, - type: null + type: null, }) } const liveCellService = LiveCellService.getInstance() @@ -97,7 +97,7 @@ export default class AnyoneCanPayService { lock: targetOutputLiveCell.lock(), type: targetOutputLiveCell.type(), data: targetOutputLiveCell.data, - outPoint: targetOutputLiveCell.outPoint() + outPoint: targetOutputLiveCell.outPoint(), }) } throw new TargetLockError() @@ -108,7 +108,7 @@ export default class AnyoneCanPayService { return Output.fromObject({ capacity: BigInt(MIN_SUDT_CAPACITY).toString(), lock: lockScript, - type: new AssetAccountInfo().generateSudtScript(tokenID) + type: new AssetAccountInfo().generateSudtScript(tokenID), }) } const liveCellService = LiveCellService.getInstance() @@ -122,14 +122,14 @@ export default class AnyoneCanPayService { lock: targetOutputLiveCell.lock(), type: targetOutputLiveCell.type(), data: targetOutputLiveCell.data, - outPoint: targetOutputLiveCell.outPoint() + outPoint: targetOutputLiveCell.outPoint(), }) } return Output.fromObject({ capacity: AnyoneCanPayService.getSUDTAddCapacity(lockScript.args), lock: lockScript, - type: new AssetAccountInfo().generateSudtScript(tokenID) + type: new AssetAccountInfo().generateSudtScript(tokenID), }) } diff --git a/packages/neuron-wallet/src/services/asset-account-service.ts b/packages/neuron-wallet/src/services/asset-account-service.ts index 3dbcb05226..d7c9522519 100644 --- a/packages/neuron-wallet/src/services/asset-account-service.ts +++ b/packages/neuron-wallet/src/services/asset-account-service.ts @@ -31,7 +31,7 @@ export default class AssetAccountService { .where({ status: In([OutputStatus.Live, OutputStatus.Sent]), lockHash: anyoneCanPayLockHash, - typeHash + typeHash, }) .getMany() @@ -64,7 +64,7 @@ export default class AssetAccountService { .where({ status: In([OutputStatus.Live, OutputStatus.Sent]), lockHash: anyoneCanPayLockHash, - typeHash + typeHash, }) .getMany() @@ -86,7 +86,7 @@ export default class AssetAccountService { lockHash: cell.lockHash, typeHash: cell.typeHash, data: cell.data, - since: '0' + since: '0', }) }) // 1. find next unused address @@ -103,7 +103,7 @@ export default class AssetAccountService { return { assetAccount, - tx + tx, } } @@ -237,7 +237,7 @@ export default class AssetAccountService { return { assetAccount, - tx + tx, } } @@ -284,7 +284,7 @@ export default class AssetAccountService { { lockHashes: anyoneCanPayLockHashes, sudtCodeHash: assetAccountInfo.infos.sudt.codeHash, - sudtHashType: assetAccountInfo.infos.sudt.hashType + sudtHashType: assetAccountInfo.infos.sudt.hashType, } ) .groupBy('output.lockHash') @@ -314,7 +314,7 @@ export default class AssetAccountService { .from(AssetAccountEntity) .where('tokenID = :tokenID AND blake160 = :blake160', { tokenID: output.typeArgs || 'CKBytes', - blake160: output.lockArgs + blake160: output.lockArgs, }) .execute() } @@ -362,7 +362,7 @@ export default class AssetAccountService { .from(AssetAccountEntity) .where('tokenID = :tokenID AND blake160 = :blake160', { tokenID: assetAccount.tokenID, - blake160: assetAccount.blake160 + blake160: assetAccount.blake160, }) .execute() } @@ -421,8 +421,8 @@ export default class AssetAccountService { tokenID: Not(''), tokenName: Not(''), symbol: Not(''), - decimal: Not('') - } + decimal: Not(''), + }, }) .then(list => list.map(item => item.toModel())) } diff --git a/packages/neuron-wallet/src/services/cells.ts b/packages/neuron-wallet/src/services/cells.ts index 16a8f3fbd7..88b0666aea 100644 --- a/packages/neuron-wallet/src/services/cells.ts +++ b/packages/neuron-wallet/src/services/cells.ts @@ -5,7 +5,7 @@ import { CapacityNotEnoughForChange, LiveCapacityNotEnough, MultisigConfigNeedError, - TransactionInputParamterMiss + TransactionInputParamterMiss, } from '../exceptions' import FeeMode from '../models/fee-mode' import OutputEntity from '../database/chain/entities/output' @@ -39,7 +39,7 @@ export interface PaginationResult { export enum CustomizedLock { SingleMultiSign = 'SingleMultiSign', Cheque = 'Cheque', - SUDT = 'SUDT' + SUDT = 'SUDT', } export enum CustomizedType { @@ -47,16 +47,14 @@ export enum CustomizedType { NFTClass = 'NFTClass', NFTIssuer = 'NFTIssuer', SUDT = 'SUDT', - Unknown = 'Unknown' + Unknown = 'Unknown', } export default class CellsService { private static ANYONE_CAN_PAY_CKB_CELL_MIN = BigInt(61 * 10 ** 8) private static ANYONE_CAN_PAY_SUDT_CELL_MIN = BigInt(142 * 10 ** 8) - public static async getBalancesByWalletId( - walletId: string - ): Promise<{ + public static async getBalancesByWalletId(walletId: string): Promise<{ liveBalances: Map sentBalances: Map pendingBalances: Map @@ -108,7 +106,7 @@ export default class CellsService { return { liveBalances, sentBalances, - pendingBalances + pendingBalances, } } @@ -121,7 +119,7 @@ export default class CellsService { .getRepository(OutputEntity) .createQueryBuilder('output') .where({ - lockHash: In(anyoneCanPayLockHashes) + lockHash: In(anyoneCanPayLockHashes), }) .getMany() @@ -141,7 +139,7 @@ export default class CellsService { .createQueryBuilder('input') .leftJoinAndSelect('input.transaction', 'tx') .where({ - outPointTxHash: In(unlockTxHashes) + outPointTxHash: In(unlockTxHashes), }) .getMany() const unlockTxMap = new Map() @@ -156,7 +154,7 @@ export default class CellsService { if (unlockTx && (cell.status === OutputStatus.Dead || cell.status === OutputStatus.Pending)) { cell.setUnlockInfo({ txHash: unlockTx.hash, - timestamp: unlockTx.timestamp! + timestamp: unlockTx.timestamp!, }) } }) @@ -170,7 +168,7 @@ export default class CellsService { .getRepository(TransactionEntity) .createQueryBuilder('tx') .where({ - hash: In(depositTxHashes) + hash: In(depositTxHashes), }) .getMany() const depositTxMap = new Map() @@ -183,7 +181,7 @@ export default class CellsService { cell.setDepositTimestamp(depositTx.timestamp!) cell.setDepositInfo({ txHash: depositTx.hash, - timestamp: depositTx.timestamp! + timestamp: depositTx.timestamp!, }) } }) @@ -221,7 +219,7 @@ export default class CellsService { sentStatus: OutputStatus.Sent, failedStatus: TransactionStatus.Failed, deadStatus: OutputStatus.Dead, - pendingStatus: OutputStatus.Pending + pendingStatus: OutputStatus.Pending, } ) .orderBy(`CASE output.daoData WHEN '0x0000000000000000' THEN 1 ELSE 0 END`, 'ASC') @@ -234,14 +232,14 @@ export default class CellsService { // if deposit cell, set depositInfo cell.setDepositInfo({ txHash: output.transaction!.hash, - timestamp: output.transaction!.timestamp! + timestamp: output.transaction!.timestamp!, }) } else { // if not deposit cell, set withdrawInfo const withdrawTx = output.transaction cell.setWithdrawInfo({ txHash: withdrawTx!.hash, - timestamp: withdrawTx!.timestamp! + timestamp: withdrawTx!.timestamp!, }) } return cell @@ -320,7 +318,7 @@ export default class CellsService { chequeLockCodeHash, nftIssuerCodehash, nftClassCodehash, - nftCodehash + nftCodehash, } ) .orderBy('tx.timestamp', 'ASC') @@ -361,20 +359,20 @@ export default class CellsService { cell.setCustomizedAssetInfo({ lock: '', type: CustomizedType.NFTIssuer, - data: '' + data: '', }) } else if (o.typeCodeHash === nftClassCodehash) { cell.setCustomizedAssetInfo({ lock: '', type: CustomizedType.NFTClass, - data: '' + data: '', }) } else if (o.typeCodeHash === nftCodehash) { const isTransferable = NFT.fromString(o.data).isTransferable() cell.setCustomizedAssetInfo({ lock: '', type: CustomizedType.NFT, - data: isTransferable ? 'transferable' : '' + data: isTransferable ? 'transferable' : '', }) } else if (o.lockCodeHash === chequeLockCodeHash) { const receiverLockHash = o.lockArgs.slice(0, 42) @@ -382,32 +380,32 @@ export default class CellsService { cell.setCustomizedAssetInfo({ lock: CustomizedLock.Cheque, type: '', - data: 'claimable' + data: 'claimable', }) } else { cell.setCustomizedAssetInfo({ lock: CustomizedLock.Cheque, type: '', - data: 'withdraw-able' + data: 'withdraw-able', }) } } else if (o.lockCodeHash === SystemScriptInfo.MULTI_SIGN_CODE_HASH) { cell.setCustomizedAssetInfo({ lock: CustomizedLock.SingleMultiSign, type: '', - data: '' + data: '', }) } else if (o.typeCodeHash === sudtCodehash) { cell.setCustomizedAssetInfo({ lock: CustomizedLock.SUDT, type: CustomizedType.SUDT, - data: '' + data: '', }) } else { cell.setCustomizedAssetInfo({ lock: '', type: CustomizedType.Unknown, - data: '' + data: '', }) } return cell @@ -415,7 +413,7 @@ export default class CellsService { return { totalCount: totalCount, - items: cells + items: cells, } } @@ -430,13 +428,11 @@ export default class CellsService { } private static getLiveCellEntity = async (outPoint: OutPoint): Promise => { - const cellEntity: OutputEntity | undefined = await getConnection() - .getRepository(OutputEntity) - .findOne({ - outPointTxHash: outPoint.txHash, - outPointIndex: outPoint.index, - status: 'live' - }) + const cellEntity: OutputEntity | undefined = await getConnection().getRepository(OutputEntity).findOne({ + outPointTxHash: outPoint.txHash, + outPointIndex: outPoint.index, + status: 'live', + }) return cellEntity } @@ -468,7 +464,7 @@ export default class CellsService { walletId, lockCodeHash: lockClass.codeHash, lockHashType: lockClass.hashType, - statuses: [OutputStatus.Live, OutputStatus.Sent] + statuses: [OutputStatus.Live, OutputStatus.Sent], } ) .getMany() @@ -493,7 +489,7 @@ export default class CellsService { lockArgs: lockClass.lockArgs, lockCodeHash: lockClass.codeHash, lockHashType: lockClass.hashType, - statuses: [OutputStatus.Live, OutputStatus.Sent] + statuses: [OutputStatus.Live, OutputStatus.Sent], } ) .getMany() @@ -595,7 +591,7 @@ export default class CellsService { const multisigConfigMap: Record = multisigConfigs.reduce( (pre, cur) => ({ ...pre, - [cur.getLockHash()]: cur + [cur.getLockHash()]: cur, }), {} ) @@ -667,7 +663,7 @@ export default class CellsService { inputs, capacities: inputCapacities.toString(), finalFee: finalFee.toString(), - hasChangeOutput + hasChangeOutput, } } @@ -684,7 +680,7 @@ export default class CellsService { : CellsService.getLiveOrSentCellByLockArgsMultisigOutput({ codeHash: lockClass.codeHash, hashType: lockClass.hashType, - lockArgs: [lockClass.args] + lockArgs: [lockClass.args], })) const inputs: Input[] = cellEntities @@ -773,7 +769,7 @@ export default class CellsService { capacity: this.ANYONE_CAN_PAY_CKB_CELL_MIN.toString(), lock: cell.lock(), type: cell.type(), - data: cell.data + data: cell.data, }) return output }) @@ -805,7 +801,7 @@ export default class CellsService { changeOutput = Output.fromObject({ capacity: changeCapacity.toString(), - lock: SystemScriptInfo.generateSecpScript(changeBlake160) + lock: SystemScriptInfo.generateSecpScript(changeBlake160), }) } @@ -818,7 +814,7 @@ export default class CellsService { anyoneCanPayOutputs, changeOutput, finalFee: finalFee.toString(), - sendCapacity: capacityInt.toString() + sendCapacity: capacityInt.toString(), } } @@ -875,7 +871,7 @@ export default class CellsService { capacity: this.ANYONE_CAN_PAY_CKB_CELL_MIN.toString(), lock: cell.lock(), type: cell.type(), - data: cell.data + data: cell.data, }) return output }) @@ -886,7 +882,7 @@ export default class CellsService { finalFee: needFee.toString(), sendCapacity: capacityInt.toString(), changeInputs: [], - changeOutput: undefined + changeOutput: undefined, } } @@ -938,7 +934,7 @@ export default class CellsService { lockHash: cell.lockHash, type: cell.type(), typeHash: cell.typeHash, - data: cell.data + data: cell.data, }) inputCapacities += BigInt(cell.capacity) totalSize += TransactionSize.input() @@ -986,7 +982,7 @@ export default class CellsService { capacity: capacity.toString(), lock: cell.lock(), type: cell.type(), - data: BufferUtils.writeBigUInt128LE(BigInt(0)) + data: BufferUtils.writeBigUInt128LE(BigInt(0)), }) return output }) @@ -1018,7 +1014,7 @@ export default class CellsService { changeOutput = Output.fromObject({ capacity: changeCapacity.toString(), - lock: SystemScriptInfo.generateSecpScript(changeBlake160) + lock: SystemScriptInfo.generateSecpScript(changeBlake160), }) } @@ -1031,15 +1027,12 @@ export default class CellsService { anyoneCanPayOutputs, changeOutput, finalFee: finalFee.toString(), - amount: amountInt.toString() + amount: amountInt.toString(), } } public static allBlake160s = async (): Promise => { - const outputEntities = await getConnection() - .getRepository(OutputEntity) - .createQueryBuilder('output') - .getMany() + const outputEntities = await getConnection().getRepository(OutputEntity).createQueryBuilder('output').getMany() const blake160s: string[] = outputEntities .map(output => { const lock = output.lockScript() @@ -1068,7 +1061,7 @@ export default class CellsService { .where({ status: OutputStatus.Live, lockCodeHash: legacyACPScriptInfo.codeHash, - lockHashType: legacyACPScriptInfo.hashType + lockHashType: legacyACPScriptInfo.hashType, }) .andWhere( ` @@ -1095,7 +1088,7 @@ export default class CellsService { lockArgs: lock.args, typeCodeHash: type.codeHash, typeHashType: type.hashType, - typeArgs: type.args + typeArgs: type.args, }) .getMany() @@ -1107,7 +1100,7 @@ export default class CellsService { .getRepository(InputEntity) .createQueryBuilder('input') .where('input.lockHash like :lockHash', { - lockHash: `%${lockHash}%` + lockHash: `%${lockHash}%`, }) .getMany() @@ -1125,7 +1118,7 @@ export default class CellsService { `, { status: OutputStatus.Live, - lockHash: lockHash + lockHash: lockHash, } ) .getMany() @@ -1138,7 +1131,7 @@ export default class CellsService { .getRepository(OutputEntity) .createQueryBuilder('output') .where({ - outPointTxHash: hash + outPointTxHash: hash, }) .getMany() @@ -1165,7 +1158,7 @@ export default class CellsService { `, { lockHashes, - statuses: [OutputStatus.Live, OutputStatus.Sent] + statuses: [OutputStatus.Live, OutputStatus.Sent], }, {} ) @@ -1182,7 +1175,7 @@ export default class CellsService { { args: c.lockArgs, codeHash: SystemScriptInfo.MULTI_SIGN_CODE_HASH, - hashType: SystemScriptInfo.MULTI_SIGN_HASH_TYPE + hashType: SystemScriptInfo.MULTI_SIGN_HASH_TYPE, }, isMainnet ) diff --git a/packages/neuron-wallet/src/services/file.ts b/packages/neuron-wallet/src/services/file.ts index 4361c1c918..7b20f59725 100644 --- a/packages/neuron-wallet/src/services/file.ts +++ b/packages/neuron-wallet/src/services/file.ts @@ -18,7 +18,7 @@ export default class FileService { public basePath = process.env['fileBasePath'] ?? env.fileBasePath public config: fs.WriteFileOptions = { - encoding: 'utf8' + encoding: 'utf8', } constructor() { diff --git a/packages/neuron-wallet/src/services/hardware/common.ts b/packages/neuron-wallet/src/services/hardware/common.ts index a343a6871a..2cf52ae82c 100644 --- a/packages/neuron-wallet/src/services/hardware/common.ts +++ b/packages/neuron-wallet/src/services/hardware/common.ts @@ -1,7 +1,7 @@ import { AddressType } from '../../models/keys/address' export enum Manufacturer { - Ledger = 'Ledger' + Ledger = 'Ledger', } export interface DeviceInfo { diff --git a/packages/neuron-wallet/src/services/hardware/hardware.ts b/packages/neuron-wallet/src/services/hardware/hardware.ts index 2a9270d7cc..002f379c94 100644 --- a/packages/neuron-wallet/src/services/hardware/hardware.ts +++ b/packages/neuron-wallet/src/services/hardware/hardware.ts @@ -1,4 +1,3 @@ -// eslint-disable-next-line prettier/prettier import type Transaction from '../../models/chain/transaction' import WitnessArgs from '../../models/chain/witness-args' import { serializeWitnessArgs } from '@nervosnetwork/ckb-sdk-utils' @@ -22,13 +21,19 @@ export abstract class Hardware { } // @TODO: After multi-signature feature is complete, refactor this function into `TransactionSender#sign`. - public async signTx (walletID: string, tx: Transaction, txHash: string, skipLastInputs: boolean = true, context?: RPC.RawTransaction[]) { + public async signTx( + walletID: string, + tx: Transaction, + txHash: string, + skipLastInputs: boolean = true, + context?: RPC.RawTransaction[] + ) { const wallet = WalletService.getInstance().get(walletID) const addressInfos = await AddressService.getAddressesByWalletId(walletID) const witnessSigningEntries = tx.inputs.slice(0, skipLastInputs ? -1 : tx.inputs.length).map((input, index) => { const lockArgs: string = input.lock!.args! const wit: WitnessArgs | string = tx.witnesses[index] - const witnessArgs: WitnessArgs = (wit instanceof WitnessArgs) ? wit : WitnessArgs.generateEmpty() + const witnessArgs: WitnessArgs = wit instanceof WitnessArgs ? wit : WitnessArgs.generateEmpty() return { witnessArgs, lockHash: input.lockHash!, @@ -37,24 +42,24 @@ export abstract class Hardware { } }) - const isMultisig = tx.inputs.length === 1 && - tx.inputs[0].lock!.args.length === TransactionSender.MULTI_SIGN_ARGS_LENGTH + const isMultisig = + tx.inputs.length === 1 && tx.inputs[0].lock!.args.length === TransactionSender.MULTI_SIGN_ARGS_LENGTH - const multiSignBlake160s = isMultisig ? addressInfos.map(i => { - return { - multiSignBlake160: Multisig.hash([i.blake160]), - path: i.path - } - }) : [] + const multiSignBlake160s = isMultisig + ? addressInfos.map(i => { + return { + multiSignBlake160: Multisig.hash([i.blake160]), + path: i.path, + } + }) + : [] const findPath = (args: string) => { if (args.length === TransactionSender.MULTI_SIGN_ARGS_LENGTH) { return multiSignBlake160s.find(i => args.slice(0, 42) === i.multiSignBlake160)!.path - } - else if (args.length === 42) { + } else if (args.length === 42) { return addressInfos.find(i => i.blake160 === args)!.path - } - else { + } else { const addressInfo = AssetAccountInfo.findSignPathForCheque(addressInfos, args) return addressInfo!.path } @@ -81,13 +86,21 @@ export abstract class Hardware { } return serializeWitnessArgs(args.toSDK()) }) - const blake160 = addressInfos.find(i => witnessesArgs[0].lockArgs.slice(0, 42) === Multisig.hash([i.blake160]))!.blake160 + const blake160 = addressInfos.find( + i => witnessesArgs[0].lockArgs.slice(0, 42) === Multisig.hash([i.blake160]) + )!.blake160 const serializedMultiSign: string = Multisig.serialize([blake160]) - const witnesses = await TransactionSender.signSingleMultiSignScript(path, serializedWitnesses, txHash, serializedMultiSign, wallet) + const witnesses = await TransactionSender.signSingleMultiSignScript( + path, + serializedWitnesses, + txHash, + serializedMultiSign, + wallet + ) const signature = await this.signTransaction( walletID, tx, - witnesses.map(w => typeof w === 'string' ? w : serializeWitnessArgs(w.toSDK())), + witnesses.map(w => (typeof w === 'string' ? w : serializeWitnessArgs(w.toSDK()))), path ) const wit = witnesses[0] as WitnessArgs @@ -110,7 +123,7 @@ export abstract class Hardware { witnessEntry.witness = serializeWitnessArgs({ lock: '0x' + signture, inputType: witnessEntry.witnessArgs.inputType ?? '', - outputType: '' + outputType: '', }) } } diff --git a/packages/neuron-wallet/src/services/hardware/index.ts b/packages/neuron-wallet/src/services/hardware/index.ts index 25ebd9af29..d5da221bf3 100644 --- a/packages/neuron-wallet/src/services/hardware/index.ts +++ b/packages/neuron-wallet/src/services/hardware/index.ts @@ -42,7 +42,7 @@ export default class HardwareWalletService { public static async findDevices(device?: Pick): Promise { const devices = await Promise.all([ - Ledger.findDevices() + Ledger.findDevices(), // add new brand `findDevices()` here ]) diff --git a/packages/neuron-wallet/src/services/hardware/ledger.ts b/packages/neuron-wallet/src/services/hardware/ledger.ts index 8933649308..b12b554a6d 100644 --- a/packages/neuron-wallet/src/services/hardware/ledger.ts +++ b/packages/neuron-wallet/src/services/hardware/ledger.ts @@ -2,7 +2,6 @@ import { DeviceInfo, ExtendedPublicKey } from './common' import { Hardware } from './hardware' import HID from '@ledgerhq/hw-transport-node-hid' import LedgerCKB from 'hw-app-ckb' -// eslint-disable-next-line prettier/prettier import type { DescriptorEvent, Subscription, Observer } from '@ledgerhq/hw-transport' import type Transport from '@ledgerhq/hw-transport' import { Observable, timer } from 'rxjs' @@ -18,12 +17,12 @@ export default class Ledger extends Hardware { private ledgerCKB: LedgerCKB | null = null private transport: Transport | null = null - public async connect (deviceInfo?: DeviceInfo) { + public async connect(deviceInfo?: DeviceInfo) { if (this.isConnected) { return } - logger.info("Connect device:\t", deviceInfo ?? this.deviceInfo) + logger.info('Connect device:\t', deviceInfo ?? this.deviceInfo) this.deviceInfo = deviceInfo ?? this.deviceInfo this.transport = await HID.open(this.deviceInfo.descriptor) @@ -32,7 +31,7 @@ export default class Ledger extends Hardware { this.isConnected = true } - public async disconnect () { + public async disconnect() { if (!this.isConnected) { return } @@ -41,15 +40,21 @@ export default class Ledger extends Hardware { this.isConnected = false } - public async getExtendedPublicKey (): Promise { + public async getExtendedPublicKey(): Promise { const { public_key, chain_code } = await this.ledgerCKB!.getWalletExtendedPublicKey(this.defaultPath) return { publicKey: public_key, - chainCode: chain_code + chainCode: chain_code, } } - public async signTransaction (_: string, tx: Transaction, witnesses: string[], path: string, context?: RPC.RawTransaction[]) { + public async signTransaction( + _: string, + tx: Transaction, + witnesses: string[], + path: string, + context?: RPC.RawTransaction[] + ) { const { ckb } = NodeService.getInstance() const rawTx = ckb.rpc.paramsFormatter.toRawTransaction(tx.toSDKRawTransaction()) @@ -63,24 +68,28 @@ export default class Ledger extends Hardware { rawTx, witnesses, context, - this.defaultPath, + this.defaultPath ) return signature } - async signMessage (path: string, messageHex: string) { + async signMessage(path: string, messageHex: string) { const message = HexUtils.removePrefix(messageHex) - const signed = await this.ledgerCKB!.signMessage(path === Address.pathForReceiving(0) ? this.defaultPath : path, message, false) + const signed = await this.ledgerCKB!.signMessage( + path === Address.pathForReceiving(0) ? this.defaultPath : path, + message, + false + ) return HexUtils.addPrefix(signed) } - async getAppVersion (): Promise { + async getAppVersion(): Promise { const conf = await this.ledgerCKB?.getAppConfiguration() return conf!.version } - async getFirmwareVersion (): Promise { + async getFirmwareVersion(): Promise { const res: Buffer = await this.transport!.send(0xe0, 0x01, 0x00, 0x00)! const byteArray = [...res] const data = byteArray.slice(0, byteArray.length - 2) @@ -90,14 +99,17 @@ export default class Ledger extends Hardware { return version } - async getPublicKey (path: string) { + async getPublicKey(path: string) { const networkService = NetworksService.getInstance() const isTestnet = !networkService.isMainnet() - const result = await this.ledgerCKB!.getWalletPublicKey(path === Address.pathForReceiving(0) ? this.defaultPath : path, isTestnet) + const result = await this.ledgerCKB!.getWalletPublicKey( + path === Address.pathForReceiving(0) ? this.defaultPath : path, + isTestnet + ) return result } - public static async findDevices () { + public static async findDevices() { const devices = await Promise.all([ Ledger.searchDevices(HID.listen, false), // Ledger.searchDevices(Bluetooth.listen, true) @@ -106,13 +118,17 @@ export default class Ledger extends Hardware { return devices.flat() } - private static async searchDevices (listener: (observer: Observer>) => Subscription, isBluetooth: boolean) { - return new Observable(listener) - .pipe( - // searching for 2 seconds - takeUntil(timer(2000)), - filter>(e => e.type === 'add'), - scan, DeviceInfo[]>((acc, e) => { + private static async searchDevices( + listener: (observer: Observer>) => Subscription, + isBluetooth: boolean + ) { + return ( + new Observable(listener) + .pipe( + // searching for 2 seconds + takeUntil(timer(2000)), + filter>(e => e.type === 'add'), + scan, DeviceInfo[]>((acc, e) => { return [ ...acc, { @@ -122,13 +138,14 @@ export default class Ledger extends Hardware { manufacturer: e.device.manufacturer, product: e.device.product, addressIndex: 0, - addressType: AddressType.Receiving - } + addressType: AddressType.Receiving, + }, ] - }, []), + }, []) ) - .toPromise() - // If the computer does not have Bluetooth support, ledgerjs may throw an error. - .catch(() => [] as DeviceInfo[]) + .toPromise() + // If the computer does not have Bluetooth support, ledgerjs may throw an error. + .catch(() => [] as DeviceInfo[]) + ) } } diff --git a/packages/neuron-wallet/src/services/multisig.ts b/packages/neuron-wallet/src/services/multisig.ts index 96c432821c..5aa129fadb 100644 --- a/packages/neuron-wallet/src/services/multisig.ts +++ b/packages/neuron-wallet/src/services/multisig.ts @@ -21,7 +21,7 @@ export default class MultisigService { r: multisigConfig.r, m: multisigConfig.m, n: multisigConfig.n, - blake160s: multisigConfig.blake160s + blake160s: multisigConfig.blake160s, }) .getCount() if (result > 0) { @@ -43,7 +43,7 @@ export default class MultisigService { .getRepository(MultisigConfig) .createQueryBuilder() .where({ - id: params.id + id: params.id, }) .getOne() if (!result) { @@ -58,7 +58,7 @@ export default class MultisigService { r: params.r ?? result.r, m: params.m ?? result.m, n: params.n ?? result.n, - blake160s: params.blake160s ?? result.blake160s + blake160s: params.blake160s ?? result.blake160s, }) .where('id = :id', { id: params.id }) .execute() @@ -70,7 +70,7 @@ export default class MultisigService { .getRepository(MultisigConfig) .createQueryBuilder() .where({ - walletId + walletId, }) .orderBy('id', 'DESC') .getMany() @@ -82,7 +82,7 @@ export default class MultisigService { .getRepository(MultisigConfig) .createQueryBuilder() .where({ - id + id, }) .getOne() await getConnection().manager.remove(config) @@ -105,17 +105,17 @@ export default class MultisigService { script: { code_hash: script.codeHash, hash_type: script.hashType, - args: script.args + args: script.args, }, script_type: 'lock', filter: { - block_range: v.lastestBlockNumber ? [v.lastestBlockNumber, max64Int] : undefined - } + block_range: v.lastestBlockNumber ? [v.lastestBlockNumber, max64Int] : undefined, + }, }, 'desc', '0x64', - addressCursorMap.get(script.args) - ] + addressCursorMap.get(script.args), + ], } }) ) @@ -139,10 +139,7 @@ export default class MultisigService { } static async saveLiveMultisigOutput() { - const multisigConfigs = await getConnection() - .getRepository(MultisigConfig) - .createQueryBuilder() - .getMany() + const multisigConfigs = await getConnection().getRepository(MultisigConfig).createQueryBuilder().getMany() const liveCells = await MultisigService.getLiveCells(multisigConfigs) if (liveCells.length) { await getConnection().manager.save(liveCells) @@ -167,17 +164,17 @@ export default class MultisigService { script: { code_hash: script.codeHash, hash_type: script.hashType, - args: script.args + args: script.args, }, script_type: 'lock', filter: { - block_range: v.lastestBlockNumber ? [v.lastestBlockNumber, max64Int] : undefined - } + block_range: v.lastestBlockNumber ? [v.lastestBlockNumber, max64Int] : undefined, + }, }, 'desc', '0x64', - addressCursorMap.get(script.args) - ] + addressCursorMap.get(script.args), + ], } }) ) @@ -206,7 +203,7 @@ export default class MultisigService { network.remote, [...multisigOutputTxHashList].map(v => ({ method: 'get_transaction', - params: [v] + params: [v], })) ) const removeOutputTxHashList: string[] = [] @@ -230,10 +227,7 @@ export default class MultisigService { } static async deleteRemovedMultisigOutput() { - const multisigConfigs = await getConnection() - .getRepository(MultisigConfig) - .createQueryBuilder() - .getMany() + const multisigConfigs = await getConnection().getRepository(MultisigConfig).createQueryBuilder().getMany() const multisigLockHashList = multisigConfigs.map(v => scriptToHash(Multisig.getMultisigScript(v.blake160s, v.r, v.m, v.n)) ) @@ -242,7 +236,7 @@ export default class MultisigService { .delete() .from(MultisigOutput) .where({ - lockHash: Not(In(multisigLockHashList)) + lockHash: Not(In(multisigLockHashList)), }) .execute() MultisigOutputChangedSubject.getSubject().next('delete') @@ -250,10 +244,7 @@ export default class MultisigService { static async syncMultisigOutput(lastestBlockNumber: string) { try { - const multisigConfigs = await getConnection() - .getRepository(MultisigConfig) - .createQueryBuilder() - .getMany() + const multisigConfigs = await getConnection().getRepository(MultisigConfig).createQueryBuilder().getMany() await MultisigService.saveLiveMultisigOutput() await MultisigService.deleteDeadMultisigOutput(multisigConfigs) await getConnection() @@ -261,7 +252,7 @@ export default class MultisigService { .save( multisigConfigs.map(v => ({ ...v, - lastestBlockNumber + lastestBlockNumber, })) ) } catch (error) { @@ -291,10 +282,10 @@ export default class MultisigService { .createQueryBuilder() .update(MultisigOutput) .set({ - status: OutputStatus.Pending + status: OutputStatus.Pending, }) .where({ - outPointTxHashAddIndex: In(inputsOutpointList) + outPointTxHashAddIndex: In(inputsOutpointList), }) .execute() MultisigOutputChangedSubject.getSubject().next('update') diff --git a/packages/neuron-wallet/src/services/networks.ts b/packages/neuron-wallet/src/services/networks.ts index 14ed8a9542..888b6d67cf 100644 --- a/packages/neuron-wallet/src/services/networks.ts +++ b/packages/neuron-wallet/src/services/networks.ts @@ -19,14 +19,14 @@ const presetNetworks: { selected: string; networks: Network[] } = { remote: BUNDLED_CKB_URL, genesisHash: MAINNET_GENESIS_HASH, type: NetworkType.Default, - chain: 'ckb' - } - ] + chain: 'ckb', + }, + ], } enum NetworksKey { List = 'networks', - Current = 'selected' + Current = 'selected', } export default class NetworksService extends Store { @@ -48,7 +48,7 @@ export default class NetworksService extends Store { public getAll = () => { const networks = this.readSync(NetworksKey.List) || presetNetworks.networks - networks.forEach((network) => { + networks.forEach(network => { // Currently, the RPC interface of the CKB node is bound to IPv4 by default. // Starting from node17, its DNS resolution is no longer `ipv4first`. // Therefore, to ensure normal connection to the ckb node, manual resolution needs to be done here. @@ -89,7 +89,7 @@ export default class NetworksService extends Store { remote, type, genesisHash: EMPTY_GENESIS_HASH, - chain: 'ckb_dev' + chain: 'ckb_dev', } const network = await CommonUtils.timeout(2000, this.refreshChainInfo(properties), properties).catch( () => properties diff --git a/packages/neuron-wallet/src/services/node.ts b/packages/neuron-wallet/src/services/node.ts index 3e5ca37030..4c6dc3b3b3 100644 --- a/packages/neuron-wallet/src/services/node.ts +++ b/packages/neuron-wallet/src/services/node.ts @@ -68,7 +68,7 @@ class NodeService { url: this.ckb.node.url, connected, isBundledNode, - startedBundledNode: isBundledNode ? this.startedBundledNode : false + startedBundledNode: isBundledNode ? this.startedBundledNode : false, }) }) } @@ -97,7 +97,7 @@ class NodeService { this.stop = unsubscribe } - public stop: Function | null = null + public stop: (() => void) | null = null public tipNumber = () => { return interval(this.intervalTime) @@ -191,7 +191,7 @@ class NodeService { message: t(`${I18N_PATH}.message`), detail: t(`${I18N_PATH}.detail`), cancelId: 0, - noLink: true + noLink: true, }) .then(() => { const VC_REDIST_URL = `https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads` @@ -206,10 +206,7 @@ class NodeService { const ckbVersionPath = path.join(appPath, '.ckb-version') if (fs.existsSync(ckbVersionPath)) { try { - return fs - .readFileSync(ckbVersionPath, 'utf8') - ?.split('\n')?.[0] - ?.slice(1) + return fs.readFileSync(ckbVersionPath, 'utf8')?.split('\n')?.[0]?.slice(1) } catch (err) { logger.error('App\t: get ckb node version failed') } @@ -226,7 +223,7 @@ class NodeService { if (internalMajor !== externalMajor || (externalMajor === '0' && internalMinor !== externalMinor)) { dialog.showMessageBox({ type: 'warning', - message: t('messageBox.node-version-different.message', { version: internalNodeVersion }) + message: t('messageBox.node-version-different.message', { version: internalNodeVersion }), }) } } @@ -239,14 +236,14 @@ class NodeService { logger.info('Node:\tthe ckb node does not start with --indexer') dialog.showMessageBox({ type: 'warning', - message: t('messageBox.ckb-without-indexer.message') + message: t('messageBox.ckb-without-indexer.message'), }) } } catch (error) { logger.info('Node:\tcalling get_indexer_tip failed') dialog.showMessageBox({ type: 'warning', - message: t('messageBox.ckb-without-indexer.message') + message: t('messageBox.ckb-without-indexer.message'), }) } } diff --git a/packages/neuron-wallet/src/services/offline-sign.ts b/packages/neuron-wallet/src/services/offline-sign.ts index c4fdf8a7e3..e55b0aa36d 100644 --- a/packages/neuron-wallet/src/services/offline-sign.ts +++ b/packages/neuron-wallet/src/services/offline-sign.ts @@ -2,18 +2,19 @@ import fs from 'fs' import path from 'path' import { dialog } from 'electron' import { t } from 'i18next' -// eslint-disable-next-line prettier/prettier import type { OfflineSignJSON } from '../models/offline-sign' -export default class OfflineSignService { - public static async loadTransactionJSON () { +export default class OfflineSignService { + public static async loadTransactionJSON() { const { canceled, filePaths } = await dialog.showOpenDialog({ title: t('offline-signature.load-transaction'), - filters: [{ - name: 'json', - extensions: ['json'] - }], - properties: ['openFile'] + filters: [ + { + name: 'json', + extensions: ['json'], + }, + ], + properties: ['openFile'], }) if (canceled || !filePaths || !filePaths[0]) { @@ -32,7 +33,7 @@ export default class OfflineSignService { } return { json, - filePath: path.basename(filePath) + filePath: path.basename(filePath), } } catch (err) { dialog.showErrorBox(t('common.error'), t('messages.invalid-json')) diff --git a/packages/neuron-wallet/src/services/sdk-core.ts b/packages/neuron-wallet/src/services/sdk-core.ts index 915c8a6d70..ad93376d7f 100644 --- a/packages/neuron-wallet/src/services/sdk-core.ts +++ b/packages/neuron-wallet/src/services/sdk-core.ts @@ -30,5 +30,5 @@ export const generateCKB = (url: string): CKB => { } export default { - generateCKB + generateCKB, } diff --git a/packages/neuron-wallet/src/services/settings.ts b/packages/neuron-wallet/src/services/settings.ts index 8369637e57..52c068db7b 100644 --- a/packages/neuron-wallet/src/services/settings.ts +++ b/packages/neuron-wallet/src/services/settings.ts @@ -8,7 +8,7 @@ import path from 'path' const { app } = env export const locales = ['zh', 'zh-TW', 'en', 'en-US'] as const -export type Locale = typeof locales[number] +export type Locale = (typeof locales)[number] export default class SettingsService extends Store { private static instance: SettingsService | null = null @@ -24,14 +24,6 @@ export default class SettingsService extends Store { return this.readSync('locale') } - get indexerDataPath(): string { - return this.readSync('indexerDataPath') - } - - set indexerDataPath(dataPath: string) { - this.writeSync('indexerDataPath', dataPath) - } - set locale(lng: Locale) { if (locales.includes(lng)) { this.writeSync('locale', lng) @@ -42,6 +34,14 @@ export default class SettingsService extends Store { } } + get indexerDataPath(): string { + return this.readSync('indexerDataPath') + } + + set indexerDataPath(dataPath: string) { + this.writeSync('indexerDataPath', dataPath) + } + get ckbDataPath() { return this.readSync('ckbDataPath') } @@ -56,7 +56,7 @@ export default class SettingsService extends Store { 'settings.json', JSON.stringify({ locale: app.getLocale(), - ckbDataPath: path.resolve(app.getPath('userData'), 'chains/mainnet') + ckbDataPath: path.resolve(app.getPath('userData'), 'chains/mainnet'), }) ) if (!this.ckbDataPath) { diff --git a/packages/neuron-wallet/src/services/sign-message.ts b/packages/neuron-wallet/src/services/sign-message.ts index b6851cadcc..eb186cc0c6 100644 --- a/packages/neuron-wallet/src/services/sign-message.ts +++ b/packages/neuron-wallet/src/services/sign-message.ts @@ -70,7 +70,7 @@ export default class SignMessage { const options = { r: signature.slice(2, 66), s: signature.slice(66, 130), - recoveryParam: parseInt(signature.slice(-1)) + recoveryParam: parseInt(signature.slice(-1)), } const msgBuffer = Buffer.from(digest.slice(2), 'hex') const publicKey = diff --git a/packages/neuron-wallet/src/services/transaction-sender.ts b/packages/neuron-wallet/src/services/transaction-sender.ts index 707f164764..c328efe724 100644 --- a/packages/neuron-wallet/src/services/transaction-sender.ts +++ b/packages/neuron-wallet/src/services/transaction-sender.ts @@ -31,7 +31,7 @@ import { CapacityNotEnoughForChangeByTransfer, MultisigConfigNeedError, NoMatchAddressForSign, - SignTransactionFailed + SignTransactionFailed, } from '../exceptions' import AssetAccountInfo from '../models/asset-account-info' import MultisigConfigModel from '../models/multisig-config' @@ -136,7 +136,7 @@ export default class TransactionSender { ? addressInfos.map(i => { return { multiSignBlake160: Multisig.hash([i.blake160]), - path: i.path + path: i.path, } }) : [] @@ -171,7 +171,7 @@ export default class TransactionSender { witnessArgs, lockHash: input.lockHash!, witness: '', - lockArgs + lockArgs, } }) @@ -197,8 +197,9 @@ export default class TransactionSender { let signed: (string | CKBComponents.WitnessArgs | WitnessArgs)[] = [] if (isMultisig) { - const blake160 = addressInfos.find(i => witnessesArgs[0].lockArgs.slice(0, 42) === Multisig.hash([i.blake160]))! - .blake160 + const blake160 = addressInfos.find( + i => witnessesArgs[0].lockArgs.slice(0, 42) === Multisig.hash([i.blake160]) + )!.blake160 const serializedMultisig: string = Multisig.serialize([blake160]) signed = await TransactionSender.signSingleMultiSignScript( privateKey, @@ -218,7 +219,7 @@ export default class TransactionSender { return wit } return wit.toSDK() - }) + }), }) } @@ -297,7 +298,7 @@ export default class TransactionSender { witnessArgs, lockHash: input.lockHash!, witness: '', - lockArgs + lockArgs, } }) @@ -305,7 +306,7 @@ export default class TransactionSender { const multisigConfigMap: Record = multisigConfigs.reduce( (pre, cur) => ({ ...pre, - [cur.getLockHash()]: cur + [cur.getLockHash()]: cur, }), {} ) @@ -393,7 +394,7 @@ export default class TransactionSender { const emptyWitness = WitnessArgs.fromObject({ ...firstWitness, - lock: `0x` + serializedMultiSign.slice(2) + '0'.repeat(130 * m) + lock: `0x` + serializedMultiSign.slice(2) + '0'.repeat(130 * m), }) const serializedEmptyWitness = serializeWitnessArgs(emptyWitness.toSDK()) const serialziedEmptyWitnessSize = HexUtils.byteLength(serializedEmptyWitness) @@ -427,7 +428,7 @@ export default class TransactionSender { ): Promise => { const targetOutputs = items.map(item => ({ ...item, - capacity: BigInt(item.capacity).toString() + capacity: BigInt(item.capacity).toString(), })) const changeAddress: string = await this.getChangeAddress() @@ -458,7 +459,7 @@ export default class TransactionSender { ): Promise => { const targetOutputs = items.map(item => ({ ...item, - capacity: BigInt(item.capacity).toString() + capacity: BigInt(item.capacity).toString(), })) const tx: Transaction = await TransactionGenerator.generateSendingAllTx(walletID, targetOutputs, fee, feeRate) @@ -472,7 +473,7 @@ export default class TransactionSender { ): Promise => { const targetOutputs = items.map(item => ({ ...item, - capacity: BigInt(item.capacity).toString() + capacity: BigInt(item.capacity).toString(), })) const tx: Transaction = await TransactionGenerator.generateSendingAllTx( @@ -492,7 +493,7 @@ export default class TransactionSender { ): Promise { const targetOutputs = items.map(item => ({ ...item, - capacity: BigInt(item.capacity).toString() + capacity: BigInt(item.capacity).toString(), })) try { @@ -512,7 +513,7 @@ export default class TransactionSender { { lockArgs: [lockScript.args], codeHash: SystemScriptInfo.MULTI_SIGN_CODE_HASH, - hashType: SystemScriptInfo.MULTI_SIGN_HASH_TYPE + hashType: SystemScriptInfo.MULTI_SIGN_HASH_TYPE, }, multisigConfig ) @@ -702,7 +703,7 @@ export default class TransactionSender { outputs, outputsData: outputs.map(o => o.data || '0x'), witnesses: [withdrawWitnessArgs], - interest: (BigInt(outputCapacity) - depositCapacity).toString() + interest: (BigInt(outputCapacity) - depositCapacity).toString(), }) if (mode.isFeeRateMode()) { const txSize: number = TransactionSize.tx(tx) @@ -791,7 +792,7 @@ export default class TransactionSender { return { length: (epoch >> BigInt(40)) & BigInt(0xffff), index: (epoch >> BigInt(24)) & BigInt(0xffff), - number: epoch & BigInt(0xffffff) + number: epoch & BigInt(0xffffff), } } @@ -825,7 +826,7 @@ export default class TransactionSender { const uniquePaths = paths.filter((value, idx, a) => a.indexOf(value) === idx) return uniquePaths.map(path => ({ path, - privateKey: `0x${masterKeychain.derivePath(path).privateKey.toString('hex')}` + privateKey: `0x${masterKeychain.derivePath(path).privateKey.toString('hex')}`, })) } } diff --git a/packages/neuron-wallet/src/services/tx/failed-transaction.ts b/packages/neuron-wallet/src/services/tx/failed-transaction.ts index 0cefaef89f..dc3c89cfb4 100644 --- a/packages/neuron-wallet/src/services/tx/failed-transaction.ts +++ b/packages/neuron-wallet/src/services/tx/failed-transaction.ts @@ -11,7 +11,7 @@ export class FailedTransaction { .getRepository(TransactionEntity) .createQueryBuilder('tx') .where({ - status: TransactionStatus.Pending + status: TransactionStatus.Pending, }) .getMany() @@ -29,7 +29,7 @@ export class FailedTransaction { .leftJoinAndSelect('tx.outputs', 'output') .where({ hash: In(hashes), - status: TransactionStatus.Pending + status: TransactionStatus.Pending, }) .getMany() @@ -54,7 +54,7 @@ export class FailedTransaction { .createQueryBuilder('output') .where({ outPointTxHash: input.outPointTxHash, - outPointIndex: input.outPointIndex + outPointIndex: input.outPointIndex, }) .getOne() if (output) { diff --git a/packages/neuron-wallet/src/services/tx/transaction-description.ts b/packages/neuron-wallet/src/services/tx/transaction-description.ts index d0902d2e14..3d6d06a6a4 100644 --- a/packages/neuron-wallet/src/services/tx/transaction-description.ts +++ b/packages/neuron-wallet/src/services/tx/transaction-description.ts @@ -2,11 +2,7 @@ import { getConnection } from 'typeorm' import TxDescription from '../../database/chain/entities/tx-description' const getEntity = async (walletId: string, txHash: string) => { - return await getConnection() - .getRepository(TxDescription) - .createQueryBuilder() - .where({ walletId, txHash }) - .getOne() + return await getConnection().getRepository(TxDescription).createQueryBuilder().where({ walletId, txHash }).getOne() } export const get = async (walletId: string, txHash: string) => { diff --git a/packages/neuron-wallet/src/services/tx/transaction-generator.ts b/packages/neuron-wallet/src/services/tx/transaction-generator.ts index b00a48a7dd..9d0f9cdabb 100644 --- a/packages/neuron-wallet/src/services/tx/transaction-generator.ts +++ b/packages/neuron-wallet/src/services/tx/transaction-generator.ts @@ -3,7 +3,7 @@ import { CapacityTooSmall, MigrateSudtCellNoTypeError, SudtAcpHaveDataError, - TargetOutputNotFoundError + TargetOutputNotFoundError, } from '../../exceptions' import FeeMode from '../../models/fee-mode' import TransactionSize from '../../models/transaction-size' @@ -77,14 +77,14 @@ export class TransactionGenerator { previousOutput: op, capacity: nftCell.capacity, lock: outputLock, - type: new Script(nftCell.type?.codeHash!, nftCell.type?.args!, nftCell.type?.hashType!), + type: nftCell.type ? new Script(nftCell.type.codeHash, nftCell.type.args, nftCell.type.hashType) : null, data: nftCell.data, - since: '0' + since: '0', }) const append = { input: nftInput, - witness: WitnessArgs.emptyLock() + witness: WitnessArgs.emptyLock(), } nftCell.setLock(receiverLockScript) @@ -96,7 +96,7 @@ export class TransactionGenerator { inputs: [nftInput], outputs, outputsData: outputs.map(output => output.data || '0x'), - witnesses: [] + witnesses: [], }) const txSize = TransactionSize.tx(tx) @@ -199,7 +199,7 @@ export class TransactionGenerator { inputs: [], outputs, outputsData: outputs.map(output => output.data || '0x'), - witnesses: [] + witnesses: [], }) const baseSize: number = TransactionSize.tx(tx) @@ -304,7 +304,7 @@ export class TransactionGenerator { headerDeps: [], inputs: allInputs, outputs, - witnesses: [] + witnesses: [], }) // change @@ -375,7 +375,7 @@ export class TransactionGenerator { inputs: [], outputs, outputsData: outputs.map(output => output.data || '0x'), - witnesses: [] + witnesses: [], }) const baseSize: number = TransactionSize.tx(tx) @@ -455,7 +455,7 @@ export class TransactionGenerator { inputs: allInputs, outputs, outputsData: outputs.map(output => output.data || '0x'), - witnesses: [] + witnesses: [], }) // change @@ -504,7 +504,7 @@ export class TransactionGenerator { inputs: [], outputs, outputsData: outputs.map(o => o.data || '0x'), - witnesses: [] + witnesses: [], }) const baseSize: number = TransactionSize.tx(tx) @@ -513,7 +513,7 @@ export class TransactionGenerator { const append = { input, - witness: WitnessArgs.emptyLock() + witness: WitnessArgs.emptyLock(), } const { inputs, capacities, finalFee, hasChangeOutput } = await CellsService.gatherInputs( @@ -565,7 +565,7 @@ export class TransactionGenerator { // const outputs: Output[] = [output] const output = Output.fromObject({ capacity: prevOutput.capacity, - lock: lockScript + lock: lockScript, }) const since = new Multisig().parseSince(prevOutput.lock.args) @@ -577,7 +577,7 @@ export class TransactionGenerator { headerDeps: [], inputs: [input], outputs: [output], - witnesses: [] + witnesses: [], }) if (mode.isFeeRateMode()) { @@ -613,7 +613,7 @@ export class TransactionGenerator { capacity: needCapacities.toString(), lock: assetAccountInfo.generateAnyoneCanPayScript(blake160), type: isCKB ? null : assetAccountInfo.generateSudtScript(tokenID), - data: isCKB ? '0x' : BufferUtils.writeBigUInt128LE(BigInt(0)) + data: isCKB ? '0x' : BufferUtils.writeBigUInt128LE(BigInt(0)), }) const tx = Transaction.fromObject({ version: '0', @@ -622,7 +622,7 @@ export class TransactionGenerator { inputs: [], outputs: [output], outputsData: [output.data], - witnesses: [] + witnesses: [], }) const baseSize: number = TransactionSize.tx(tx) const { inputs, capacities, finalFee, hasChangeOutput } = await CellsService.gatherInputs( @@ -644,7 +644,7 @@ export class TransactionGenerator { const output = Output.fromObject({ capacity: changeCapacity.toString(), - lock: SystemScriptInfo.generateSecpScript(changeBlake160) + lock: SystemScriptInfo.generateSecpScript(changeBlake160), }) tx.addOutput(output) @@ -685,7 +685,7 @@ export class TransactionGenerator { capacity: totalCapacity.toString(), lock: assetAccountInfo.generateAnyoneCanPayScript(blake160), type: isCKB ? null : assetAccountInfo.generateSudtScript(tokenID), - data: isCKB ? '0x' : BufferUtils.writeBigUInt128LE(BigInt(0)) + data: isCKB ? '0x' : BufferUtils.writeBigUInt128LE(BigInt(0)), }) const tx = Transaction.fromObject({ @@ -695,7 +695,7 @@ export class TransactionGenerator { inputs: allInputs, outputs: [output], outputsData: [output.data], - witnesses: [] + witnesses: [], }) const keyCount = new Set(allInputs.map(i => i.lockHash!)).size const txSize: number = @@ -730,7 +730,7 @@ export class TransactionGenerator { const output = Output.fromObject({ capacity: '0', - lock: SystemScriptInfo.generateSecpScript(changeBlake160) + lock: SystemScriptInfo.generateSecpScript(changeBlake160), }) const tx = Transaction.fromObject({ @@ -740,7 +740,7 @@ export class TransactionGenerator { inputs: asssetAccountInputs, outputs: [output], outputsData: [output.data], - witnesses: [] + witnesses: [], }) let allCapacities = asssetAccountInputs.reduce((a, b) => { @@ -788,14 +788,14 @@ export class TransactionGenerator { capacity === 'all' ? BigInt(targetOutput.capacity) : BigInt(targetOutput.capacity) + BigInt(capacity) const output = Output.fromObject({ ...targetOutput, - capacity: needCapacities.toString() + capacity: needCapacities.toString(), }) const targetInput = Input.fromObject({ previousOutput: targetOutput.outPoint!, since: '0', capacity: targetOutput.capacity, lock: targetOutput.lock, - lockHash: targetOutput.lockHash + lockHash: targetOutput.lockHash, }) if (output.type) { @@ -809,7 +809,7 @@ export class TransactionGenerator { inputs: [targetInput], outputs: [output], outputsData: [output.data], - witnesses: [] + witnesses: [], }) const deps = assetAccountInfo.determineAdditionalACPCellDepsByTx(tx) @@ -870,7 +870,7 @@ export class TransactionGenerator { amount === 'all' ? BigInt(0) : BufferUtils.parseAmountFromSUDTData(targetOutput.data) + BigInt(amount) const output = Output.fromObject({ ...targetOutput, - data: BufferUtils.writeBigUInt128LE(targetAmount) + data: BufferUtils.writeBigUInt128LE(targetAmount), }) const targetInput = targetOutput.outPoint ? Input.fromObject({ @@ -880,7 +880,7 @@ export class TransactionGenerator { lock: targetOutput.lock, lockHash: targetOutput.lockHash, type: targetOutput.type, - data: targetOutput.data + data: targetOutput.data, }) : undefined const tx = Transaction.fromObject({ @@ -890,7 +890,7 @@ export class TransactionGenerator { inputs: targetInput ? [targetInput] : [], outputs: [output], outputsData: [output.data], - witnesses: [] + witnesses: [], }) const deps = assetAccountInfo.determineAdditionalACPCellDepsByTx(tx) @@ -968,7 +968,7 @@ export class TransactionGenerator { inputs: legacyACPInputs, outputs: ACPOutputs, outputsData: ACPCells.map(o => o.data || '0x'), - witnesses: [] + witnesses: [], }) const baseSize = TransactionSize.tx(tx) + TransactionSize.secpLockWitness() * tx.inputs.length @@ -1027,7 +1027,7 @@ export class TransactionGenerator { const chequeCellTmp = Output.fromObject({ capacity: BigInt(162 * 10 ** 8).toString(), lock: assetAccountInfo.generateChequeScript('0'.repeat(40), '0'.repeat(40)), - type: assetAccountInfo.generateSudtScript(assetAccount.tokenID) + type: assetAccountInfo.generateSudtScript(assetAccount.tokenID), }) const tx = Transaction.fromObject({ @@ -1038,7 +1038,7 @@ export class TransactionGenerator { outputs: [], outputsData: [], witnesses: [], - description + description, }) const changeBlake160: string = AddressParser.toBlake160(changeAddress) @@ -1094,7 +1094,7 @@ export class TransactionGenerator { lock: assetAccountInfo.generateChequeScript( receiverLockScript.computeHash(), senderDefaultCell.lock!.computeHash() - ) + ), }) tx.outputs.unshift(chequeCell) tx.outputsData.unshift(chequeCell.data) @@ -1162,12 +1162,12 @@ export class TransactionGenerator { lock: chequeCell.lock, type: chequeCell.type, lockHash: chequeCell.lockHash, - data: chequeCell.data + data: chequeCell.data, }) const senderOutput = Output.fromObject({ capacity: chequeCell.capacity, - lock: chequeSenderLock! + lock: chequeSenderLock!, }) const tx = Transaction.fromObject({ @@ -1177,7 +1177,7 @@ export class TransactionGenerator { inputs: [chequeInput], outputs: [senderOutput], outputsData: [senderOutput.data], - witnesses: [] + witnesses: [], }) const receiverAcpScript = assetAccountInfo.generateAnyoneCanPayScript(receiverLockArgs) @@ -1195,7 +1195,7 @@ export class TransactionGenerator { capacity: originalReceiverAcpOutput.capacity, lock: originalReceiverAcpOutput.lockScript(), type: originalReceiverAcpOutput.typeScript(), - data: BufferUtils.writeBigUInt128LE(receiverAcpOutputAmount) + data: BufferUtils.writeBigUInt128LE(receiverAcpOutputAmount), }) const receiverAcpInput = Input.fromObject({ @@ -1204,7 +1204,7 @@ export class TransactionGenerator { capacity: originalReceiverAcpOutput.capacity, lock: originalReceiverAcpOutput.lockScript(), type: originalReceiverAcpOutput.typeScript(), - data: originalReceiverAcpOutput.data + data: originalReceiverAcpOutput.data, }) tx.inputs.push(receiverAcpInput) tx.outputs.push(newReceiverAcpOutput) @@ -1215,7 +1215,7 @@ export class TransactionGenerator { capacity: acpCellCapacity.toString(), lock: receiverAcpScript, type: chequeCell.type, - data: chequeCell.data + data: chequeCell.data, }) tx.outputs.push(receiverAcpOutput) @@ -1285,7 +1285,7 @@ export class TransactionGenerator { lock: chequeCell.lock, type: chequeCell.type, lockHash: chequeCell.lockHash, - data: chequeCell.data + data: chequeCell.data, }) const chequeSenderAcpInput = Input.fromObject({ @@ -1294,7 +1294,7 @@ export class TransactionGenerator { capacity: chequeSenderLiveAcpCell.capacity, lock: chequeSenderLiveAcpCell.lockScript(), type: chequeSenderLiveAcpCell.typeScript(), - data: chequeSenderLiveAcpCell.data + data: chequeSenderLiveAcpCell.data, }) const senderInputsByLockHash = await CellsService.searchInputsByLockHash(senderLockHash) @@ -1305,7 +1305,7 @@ export class TransactionGenerator { const senderDefaultLockOutput = Output.fromObject({ capacity: chequeCell.capacity, - lock: senderDefaultLockInput.lockScript()! + lock: senderDefaultLockInput.lockScript()!, }) const senderAcpInputAmount = BufferUtils.readBigUInt128LE(chequeSenderAcpInput.data!) @@ -1316,7 +1316,7 @@ export class TransactionGenerator { capacity: chequeSenderAcpInput.capacity!, lock: chequeSenderAcpInput.lock!, type: chequeSenderAcpInput.type!, - data: BufferUtils.writeBigUInt128LE(senderAcpOutputAmount) + data: BufferUtils.writeBigUInt128LE(senderAcpOutputAmount), }) const secpCellDep = await SystemScriptInfo.getInstance().getSecpCellDep() @@ -1331,7 +1331,7 @@ export class TransactionGenerator { inputs: [chequeSenderAcpInput, chequeInput], outputs: [senderAcpOutput], outputsData: [], - witnesses: [] + witnesses: [], }) tx.outputsData = tx.outputs.map(output => output.data || '0x') @@ -1394,8 +1394,8 @@ export class TransactionGenerator { type: inputSudtCell.type, lockHash: inputSudtCell.lockHash, data: inputSudtCell.data, - since: '0' - }) + since: '0', + }), ] const secpCellDep = await SystemScriptInfo.getInstance().getSecpCellDep() @@ -1425,8 +1425,8 @@ export class TransactionGenerator { capacity: receiverAcpCell.capacity, lock: receiverAcpCell.lock(), type: receiverAcpCell.type(), - data: BufferUtils.writeBigUInt128LE(receiverAcpOutputAmount) - }) + data: BufferUtils.writeBigUInt128LE(receiverAcpOutputAmount), + }), ] acpInputCell = Input.fromObject({ previousOutput: receiverAcpCell.outPoint(), @@ -1435,7 +1435,7 @@ export class TransactionGenerator { type: receiverAcpCell.type(), lockHash: receiverAcpCell.lockHash, data: receiverAcpCell.data, - since: '0' + since: '0', }) sudtMigrateAcpInputs.push(acpInputCell) } else { @@ -1455,7 +1455,7 @@ export class TransactionGenerator { inputs: sudtMigrateAcpInputs, outputs: outputs, outputsData: outputs.map(v => v.data || '0x'), - witnesses: [] + witnesses: [], }) const txSize = TransactionSize.tx(tx) + TransactionSize.secpLockWitness() * tx.inputs.length @@ -1478,7 +1478,7 @@ export class TransactionGenerator { TransactionGenerator.CHANGE_OUTPUT_DATA_SIZE, sudtMigrateAcpInputs.map(v => ({ input: v, - witness: WitnessArgs.emptyLock() + witness: WitnessArgs.emptyLock(), })) ) const finalFeeInt = BigInt(finalFee) diff --git a/packages/neuron-wallet/src/services/tx/transaction-persistor.ts b/packages/neuron-wallet/src/services/tx/transaction-persistor.ts index 12bc64c49a..7586377543 100644 --- a/packages/neuron-wallet/src/services/tx/transaction-persistor.ts +++ b/packages/neuron-wallet/src/services/tx/transaction-persistor.ts @@ -12,7 +12,7 @@ import Input from '../../models/chain/input' export enum TxSaveType { Sent = 'sent', - Fetch = 'fetch' + Fetch = 'fetch', } export class TransactionPersistor { @@ -68,11 +68,11 @@ export class TransactionPersistor { .update(OutputEntity) .set({ multiSignBlake160: o.multiSignBlake160, - data + data, }) .where({ outPointTxHash: o.outPoint!.txHash, - outPointIndex: o.outPoint!.index + outPointIndex: o.outPoint!.index, }) .execute() @@ -81,11 +81,11 @@ export class TransactionPersistor { .update(InputEntity) .set({ multiSignBlake160: o.multiSignBlake160, - data + data, }) .where({ outPointTxHash: o.outPoint!.txHash, - outPointIndex: o.outPoint!.index + outPointIndex: o.outPoint!.index, }) .execute() } @@ -100,11 +100,11 @@ export class TransactionPersistor { typeCodeHash: i.type?.codeHash, typeArgs: i.type?.args, typeHashType: i.type?.hashType, - typeHash: i.typeHash + typeHash: i.typeHash, }) .where({ outPointTxHash: i.previousOutput!.txHash, - outPointIndex: i.previousOutput!.index + outPointIndex: i.previousOutput!.index, }) .execute() } @@ -116,7 +116,7 @@ export class TransactionPersistor { .getRepository(InputEntity) .createQueryBuilder('input') .where({ - transaction: txEntity + transaction: txEntity, }) .getMany() @@ -124,7 +124,7 @@ export class TransactionPersistor { .getRepository(OutputEntity) .createQueryBuilder('output') .where({ - transaction: txEntity + transaction: txEntity, }) .andWhere('status != :status', { status: OutputStatus.Dead }) .getMany() @@ -146,7 +146,7 @@ export class TransactionPersistor { if (outPoint) { const outputEntity: OutputEntity | undefined = await connection.getRepository(OutputEntity).findOne({ outPointTxHash: outPoint.txHash, - outPointIndex: outPoint.index + outPointIndex: outPoint.index, }) if (outputEntity && outputEntity.status !== OutputStatus.Dead) { outputEntity.status = OutputStatus.Dead @@ -251,7 +251,7 @@ export class TransactionPersistor { if (outPoint) { const previousOutput: OutputEntity | undefined = await connection.getRepository(OutputEntity).findOne({ outPointTxHash: outPoint.txHash, - outPointIndex: outPoint.index + outPointIndex: outPoint.index, }) if (previousOutput && previousOutput.status !== inputStatus) { @@ -368,7 +368,7 @@ export class TransactionPersistor { public static saveSentTx = async (transaction: Transaction, txHash: string): Promise => { const tx = Transaction.fromObject({ ...transaction, - hash: txHash + hash: txHash, }) const txEntity: TransactionEntity = await TransactionPersistor.convertTransactionAndSave(tx, TxSaveType.Sent) return txEntity diff --git a/packages/neuron-wallet/src/services/tx/transaction-service.ts b/packages/neuron-wallet/src/services/tx/transaction-service.ts index 331548a679..43bb93392e 100644 --- a/packages/neuron-wallet/src/services/tx/transaction-service.ts +++ b/packages/neuron-wallet/src/services/tx/transaction-service.ts @@ -1,7 +1,13 @@ import { getConnection } from 'typeorm' import TransactionEntity from '../../database/chain/entities/transaction' import OutputEntity from '../../database/chain/entities/output' -import Transaction, { TransactionStatus, SudtInfo, NFTType, NFTInfo, AssetAccountType } from '../../models/chain/transaction' +import Transaction, { + TransactionStatus, + SudtInfo, + NFTType, + NFTInfo, + AssetAccountType, +} from '../../models/chain/transaction' import InputEntity from '../../database/chain/entities/input' import AddressParser from '../../models/address-parser' import AssetAccountInfo from '../../models/asset-account-info' @@ -28,7 +34,7 @@ export enum SearchType { Date = 'date', Empty = 'empty', TokenInfo = 'tokenInfo', - Unknown = 'unknown' + Unknown = 'unknown', } export class TransactionsService { @@ -145,14 +151,14 @@ export class TransactionsService { .createQueryBuilder('aa') .leftJoinAndSelect('aa.sudtTokenInfo', 'info') .where(`info.symbol = :searchValue OR info.tokenName = :searchValue OR aa.accountName = :searchValue`, { - searchValue + searchValue, }) .getOne() if (!assetAccount) { return { totalCount: 0, - items: [] + items: [], } } @@ -178,7 +184,7 @@ export class TransactionsService { { walletId: params.walletID, lockCodeHash: assetAccountInfo.anyoneCanPayCodeHash, - tokenID + tokenID, } ) .orderBy('tx.timestamp', 'DESC') @@ -226,7 +232,7 @@ export class TransactionsService { `, { txHashes, - walletId: params.walletID + walletId: params.walletID, } ) .getRawMany() @@ -244,7 +250,7 @@ export class TransactionsService { `, { txHashes, - walletId: params.walletID + walletId: params.walletID, } ) .getRawMany() @@ -260,7 +266,7 @@ export class TransactionsService { { txHashes, walletId: params.walletID, - lockCodeHash: assetAccountInfo.anyoneCanPayCodeHash + lockCodeHash: assetAccountInfo.anyoneCanPayCodeHash, } ) .getMany() @@ -276,7 +282,7 @@ export class TransactionsService { { txHashes, walletId: params.walletID, - lockCodeHash: assetAccountInfo.anyoneCanPayCodeHash + lockCodeHash: assetAccountInfo.anyoneCanPayCodeHash, } ) .getMany() @@ -293,7 +299,7 @@ export class TransactionsService { { txHashes, walletId: params.walletID, - nftCodehash + nftCodehash, } ) .getMany() @@ -310,7 +316,7 @@ export class TransactionsService { { txHashes, walletId: params.walletID, - nftCodehash + nftCodehash, } ) .getMany() @@ -428,7 +434,7 @@ export class TransactionsService { `info.tokenID = :typeArgs AND aa.blake160 IN (select publicKeyInBlake160 from hd_public_key_info where walletId = :walletId)`, { typeArgs, - walletId: params.walletID + walletId: params.walletID, } ) .getOne() @@ -436,7 +442,7 @@ export class TransactionsService { if (tokenInfo) { sudtInfo = { sUDT: tokenInfo, - amount: amount.toString() + amount: amount.toString(), } } } @@ -465,7 +471,7 @@ export class TransactionsService { updatedAt: tx.updatedAt, blockNumber: tx.blockNumber, sudtInfo: sudtInfo, - nftInfo: nftInfo + nftInfo: nftInfo, }) }) ) @@ -474,7 +480,7 @@ export class TransactionsService { return { totalCount, - items: txs + items: txs, } } @@ -485,14 +491,14 @@ export class TransactionsService { .where('transaction.hash is :hash', { hash }) .leftJoinAndSelect('transaction.inputs', 'input') .orderBy({ - 'input.id': 'ASC' + 'input.id': 'ASC', }) .getOne() const txOutputs = await getConnection() .getRepository(OutputEntity) .createQueryBuilder() .where({ - outPointTxHash: hash + outPointTxHash: hash, }) .getMany() @@ -575,7 +581,7 @@ export class TransactionsService { { walletId, lockCodeHash: lock?.codeHash, - lockHashType: lock?.hashType + lockHashType: lock?.hashType, }, {} ) @@ -615,7 +621,7 @@ export class TransactionsService { .getRepository(TransactionEntity) .createQueryBuilder('tx') .where({ - hash + hash, }) .getOne() diff --git a/packages/neuron-wallet/src/services/wallets.ts b/packages/neuron-wallet/src/services/wallets.ts index f61a646943..09bb0fc47a 100644 --- a/packages/neuron-wallet/src/services/wallets.ts +++ b/packages/neuron-wallet/src/services/wallets.ts @@ -59,7 +59,7 @@ export abstract class Wallet { name: this.name, extendedKey: this.extendedKey, device: this.device, - isHD: this.isHD + isHD: this.isHD, }) public fromJSON = () => { @@ -138,7 +138,7 @@ export class FileKeystoreWallet extends Wallet { name: this.name, extendedKey: this.extendedKey, device: this.device, - isHD: this.isHD + isHD: this.isHD, } } @@ -227,7 +227,7 @@ export class HardwareWallet extends Wallet { walletId: this.id, publicKey, addressType, - addressIndex + addressIndex, }) if (address) { @@ -291,7 +291,7 @@ export default class WalletService { const walletList = this.getAll() CurrentWalletSubject.next({ currentWallet, - walletList + walletList, }) } }) @@ -309,7 +309,7 @@ export default class WalletService { await getConnection() .getRepository(HdPublicKeyInfo) .delete({ - walletId: Not(In(allWallets.map(w => w.id))) + walletId: Not(In(allWallets.map(w => w.id))), }) } diff --git a/packages/neuron-wallet/src/types/controller.d.ts b/packages/neuron-wallet/src/types/controller.d.ts index 932015d1e0..20cdba3b2e 100644 --- a/packages/neuron-wallet/src/types/controller.d.ts +++ b/packages/neuron-wallet/src/types/controller.d.ts @@ -1,4 +1,4 @@ -declare module Controller { +declare namespace Controller { interface Response { status: number message?: diff --git a/packages/neuron-wallet/src/utils/common.ts b/packages/neuron-wallet/src/utils/common.ts index c260ae2287..cdf789e01f 100644 --- a/packages/neuron-wallet/src/utils/common.ts +++ b/packages/neuron-wallet/src/utils/common.ts @@ -24,7 +24,7 @@ export default class CommonUtils { promise, new Promise((resolve, _) => { setTimeout(() => resolve(value), time) - }) + }), ]) } diff --git a/packages/neuron-wallet/src/utils/const.ts b/packages/neuron-wallet/src/utils/const.ts index 9d1e694f9c..1b84c7ef41 100644 --- a/packages/neuron-wallet/src/utils/const.ts +++ b/packages/neuron-wallet/src/utils/const.ts @@ -10,9 +10,9 @@ export const START_WITHOUT_INDEXER = -4 export enum ResponseCode { Fail, - Success + Success, } export default { - ResponseCode + ResponseCode, } diff --git a/packages/neuron-wallet/src/utils/export-history.ts b/packages/neuron-wallet/src/utils/export-history.ts index 0fe86bc56b..acaee4e100 100644 --- a/packages/neuron-wallet/src/utils/export-history.ts +++ b/packages/neuron-wallet/src/utils/export-history.ts @@ -30,7 +30,7 @@ const exportHistory = async ({ walletID, filePath }: { walletID: string; filePat return promisify(meta).bind(target) } return meta - } + }, }) await wsPromises.write(`${headers.map(label => t(`export-transactions.column.${label}`))}\n`) @@ -47,7 +47,7 @@ const exportHistory = async ({ walletID, filePath }: { walletID: string; filePat pageNo, pageSize: PAGE_SIZE, addresses, - walletID + walletID, }) count = totalCount txs.push(...items.filter(item => item.status === 'success')) diff --git a/packages/neuron-wallet/src/utils/multisig.ts b/packages/neuron-wallet/src/utils/multisig.ts index 8a457a2b31..a31c710219 100644 --- a/packages/neuron-wallet/src/utils/multisig.ts +++ b/packages/neuron-wallet/src/utils/multisig.ts @@ -28,5 +28,5 @@ export const getMultisigStatus = (multisigConfig: MultisigConfigModel, signature } export default { - getMultisigStatus + getMultisigStatus, } diff --git a/packages/neuron-wallet/src/utils/parse_sudt_token_info.ts b/packages/neuron-wallet/src/utils/parse_sudt_token_info.ts index 346249f455..87bcf1ebb8 100644 --- a/packages/neuron-wallet/src/utils/parse_sudt_token_info.ts +++ b/packages/neuron-wallet/src/utils/parse_sudt_token_info.ts @@ -1,8 +1,6 @@ const parseSUDTTokenInfo = (hexData: string) => { const decimal = (+hexData.substr(0, 4)).toString() - const [, name = '', symbol = ''] = Buffer.from(hexData.slice(4), 'hex') - .toString('utf-8') - .split(`\n`) + const [, name = '', symbol = ''] = Buffer.from(hexData.slice(4), 'hex').toString('utf-8').split(`\n`) return { decimal, name, symbol } } diff --git a/packages/neuron-wallet/src/utils/queue.ts b/packages/neuron-wallet/src/utils/queue.ts index c0119f63ef..5868adca2d 100644 --- a/packages/neuron-wallet/src/utils/queue.ts +++ b/packages/neuron-wallet/src/utils/queue.ts @@ -44,6 +44,6 @@ export default function queueWrapper( ) return promiseList[promiseList.length - 1] }, - writable: false + writable: false, }) as AsyncQueue & { asyncPush: (item: T) => Promise } } diff --git a/packages/neuron-wallet/src/utils/rpc-request.ts b/packages/neuron-wallet/src/utils/rpc-request.ts index aaa04cce07..2793c7377e 100644 --- a/packages/neuron-wallet/src/utils/rpc-request.ts +++ b/packages/neuron-wallet/src/utils/rpc-request.ts @@ -13,11 +13,11 @@ export const rpcRequest = async ( id: 0, jsonrpc: '2.0', method: options.method, - params: options.params + params: options.params, }), headers: { - 'content-type': 'application/json' - } + 'content-type': 'application/json', + }, }) if (res.statusCode !== 200) { throw new Error(`indexer request failed with HTTP code ${res.statusCode}`) @@ -34,7 +34,7 @@ export const rpcBatchRequest = async ( ): Promise => { const res = await request(url, { headers: { - 'content-type': 'application/json' + 'content-type': 'application/json', }, method: 'POST', body: JSON.stringify( @@ -42,9 +42,9 @@ export const rpcBatchRequest = async ( id: idx, jsonrpc: '2.0', method: v.method, - params: v.params + params: v.params, })) - ) + ), }) if (res.statusCode !== 200) { throw new Error(`indexer request failed with HTTP code ${res.statusCode}`) @@ -55,5 +55,5 @@ export const rpcBatchRequest = async ( export default { rpcBatchRequest, - rpcRequest + rpcRequest, } diff --git a/packages/neuron-wallet/src/utils/to-csv-row.ts b/packages/neuron-wallet/src/utils/to-csv-row.ts index 31eff7f950..7b7a01ee22 100644 --- a/packages/neuron-wallet/src/utils/to-csv-row.ts +++ b/packages/neuron-wallet/src/utils/to-csv-row.ts @@ -34,7 +34,7 @@ const toCSVRow = ( if (['create', 'destroy'].includes(tx.type || '')) { // create/destroy an account txType = t(`export-transactions.tx-type.${tx.type}-asset-account`, { - name: tx.sudtInfo.sUDT.tokenName || 'Unknown' + name: tx.sudtInfo.sUDT.tokenName || 'Unknown', }) } else { // transfer of an account diff --git a/packages/neuron-wallet/src/utils/validators.ts b/packages/neuron-wallet/src/utils/validators.ts index 1f3ea21d6a..c0b2827963 100644 --- a/packages/neuron-wallet/src/utils/validators.ts +++ b/packages/neuron-wallet/src/utils/validators.ts @@ -36,13 +36,13 @@ export const verifyPasswordComplexity = (password: string) => { } } -export const Required = (target: Object, propertyKey: string | symbol, index: number) => { +export const Required = (target: object, propertyKey: string | symbol, index: number) => { const indices: number[] = Reflect.getOwnMetadata(requiredMetadataKey, target, propertyKey) || [] indices.push(index) Reflect.defineMetadata(requiredMetadataKey, indices, target, propertyKey) } -export const Password = (target: Object, propertyKey: string | symbol, parameterIndex: number) => { +export const Password = (target: object, propertyKey: string | symbol, parameterIndex: number) => { Reflect.defineMetadata(passwordMetadataKey, parameterIndex, target, propertyKey) } @@ -65,6 +65,6 @@ export const Validate = (target: any, propertyKey: string, descriptor: PropertyD verifyPasswordComplexity(args[passwordIndex]) } return originalMethod.apply(this, args) - } + }, } } diff --git a/packages/neuron-wallet/tests/block-sync-renderer/index/createBlockSyncTask.test.ts b/packages/neuron-wallet/tests/block-sync-renderer/index/createBlockSyncTask.test.ts index 73f6b2b09a..9fda25fbc2 100644 --- a/packages/neuron-wallet/tests/block-sync-renderer/index/createBlockSyncTask.test.ts +++ b/packages/neuron-wallet/tests/block-sync-renderer/index/createBlockSyncTask.test.ts @@ -1,4 +1,3 @@ - describe(`Create block sync task`, () => { const STUB_ADDRESS_METAS = 'address metas' const STUB_NETWORK = { id: 'id', genesisHash: '0x1', remote: 'stub_network_url' } @@ -16,12 +15,12 @@ describe(`Create block sync task`, () => { once: jest.fn(), send: stubbedChildProcessSend, stderr: { - setEncoding: childProcessStdErrEncoding - } + setEncoding: childProcessStdErrEncoding, + }, })) jest.doMock('child_process', () => ({ - fork: stubbedChildProcessFork + fork: stubbedChildProcessFork, })) jest.doMock('models/subjects/data-update', () => ({ @@ -30,7 +29,9 @@ describe(`Create block sync task`, () => { jest.doMock(`utils/logger`, () => ({ info: stubbedLoggerInfo })) jest.doMock('services/addresses', () => ({ getAddressesByAllWallets: stubbedGetAddressesByAllWallets })) - jest.doMock('services/networks', () => ({ getInstance: jest.fn().mockReturnValue({ getCurrent: () => STUB_NETWORK }) })) + jest.doMock('services/networks', () => ({ + getInstance: jest.fn().mockReturnValue({ getCurrent: () => STUB_NETWORK }), + })) const blockSyncRenderer = require('block-sync-renderer') const spyRegisterRequest = jest.spyOn(blockSyncRenderer, 'registerRequest').mockResolvedValue(0) @@ -73,8 +74,8 @@ describe(`Create block sync task`, () => { addressMetas: STUB_ADDRESS_METAS, genesisHash: STUB_NETWORK.genesisHash, indexerUrl: STUB_NETWORK.remote, - url: STUB_NETWORK.remote - } + url: STUB_NETWORK.remote, + }, }) }) }) diff --git a/packages/neuron-wallet/tests/block-sync-renderer/index/hasSideEffect.test.ts b/packages/neuron-wallet/tests/block-sync-renderer/index/hasSideEffect.test.ts index b868129472..54160aeb33 100644 --- a/packages/neuron-wallet/tests/block-sync-renderer/index/hasSideEffect.test.ts +++ b/packages/neuron-wallet/tests/block-sync-renderer/index/hasSideEffect.test.ts @@ -1,8 +1,12 @@ describe(`Should subscribe to 2 subjects on importing`, () => { const stubbedAddressCreatedSubjectSubscribe = jest.fn() const stubbedWalletDeletedSubjectSubscribe = jest.fn() - jest.doMock('models/subjects/address-created-subject', () => ({ getSubject: () => ({ subscribe: stubbedAddressCreatedSubjectSubscribe }) })) - jest.doMock('models/subjects/wallet-deleted-subject', () => ({ getSubject: () => ({ subscribe: stubbedWalletDeletedSubjectSubscribe }) })) + jest.doMock('models/subjects/address-created-subject', () => ({ + getSubject: () => ({ subscribe: stubbedAddressCreatedSubjectSubscribe }), + })) + jest.doMock('models/subjects/wallet-deleted-subject', () => ({ + getSubject: () => ({ subscribe: stubbedWalletDeletedSubjectSubscribe }), + })) require('block-sync-renderer') diff --git a/packages/neuron-wallet/tests/block-sync-renderer/index/killBlockSyncTask.test.ts b/packages/neuron-wallet/tests/block-sync-renderer/index/killBlockSyncTask.test.ts index 231486ffc4..9e103f5d62 100644 --- a/packages/neuron-wallet/tests/block-sync-renderer/index/killBlockSyncTask.test.ts +++ b/packages/neuron-wallet/tests/block-sync-renderer/index/killBlockSyncTask.test.ts @@ -21,16 +21,16 @@ describe(`Kill block sync task`, () => { send: stubbedChildProcessSend, stderr: { setEncoding: jest.fn().mockImplementation(() => ({ - on: jest.fn() - })) - } - })) + on: jest.fn(), + })), + }, + })), })) jest.doMock('services/indexer', () => ({ getInstance: () => ({ start: jest.fn(), stop: jest.fn() }) })) jest.doMock('services/addresses', () => ({ updateTxCountAndBalances: jest.fn(), updateUsedByAnyoneCanPayByBlake160s: jest.fn(), - getAddressesByAllWallets: () => [{}] + getAddressesByAllWallets: () => [{}], })) jest.doMock('services/networks', () => ({ getInstance: () => ({ getCurrent: stubbedGetCurrentNetwork }) })) jest.doMock('block-sync-renderer/task', () => stubbedSyncTaskCtor) diff --git a/packages/neuron-wallet/tests/block-sync-renderer/index/queryIndexer.test.ts b/packages/neuron-wallet/tests/block-sync-renderer/index/queryIndexer.test.ts index d0688eb49c..f12bb96a55 100644 --- a/packages/neuron-wallet/tests/block-sync-renderer/index/queryIndexer.test.ts +++ b/packages/neuron-wallet/tests/block-sync-renderer/index/queryIndexer.test.ts @@ -14,12 +14,12 @@ const stubbedChildProcessFork = jest.fn().mockImplementation(() => ({ once: jest.fn(), send: stubbedChildProcessSend, stderr: { - setEncoding: childProcessStdErrEncoding - } + setEncoding: childProcessStdErrEncoding, + }, })) jest.doMock('child_process', () => ({ - fork: stubbedChildProcessFork + fork: stubbedChildProcessFork, })) jest.doMock('models/subjects/data-update', () => ({ @@ -27,9 +27,16 @@ jest.doMock('models/subjects/data-update', () => ({ })) jest.doMock(`utils/logger`, () => ({ info: stubbedLoggerInfo })) -jest.doMock('services/indexer', () => ({ LISTEN_URI: 'stub_listen_uri', getInstance: () => ({ start: stubbedIndexerServiceStart }) })) +jest.doMock('services/indexer', () => ({ + LISTEN_URI: 'stub_listen_uri', + getInstance: () => ({ start: stubbedIndexerServiceStart }), +})) jest.doMock('services/addresses', () => ({ getAddressesByAllWallets: stubbedGetAddressesByAllWallets })) -jest.doMock('services/networks', () => ({ getInstance: jest.fn().mockReturnValue({ getCurrent: () => ({ id: 'id', genesisHash: '0x1', remote: 'stub_network_url' }) }) })) +jest.doMock('services/networks', () => ({ + getInstance: jest + .fn() + .mockReturnValue({ getCurrent: () => ({ id: 'id', genesisHash: '0x1', remote: 'stub_network_url' }) }), +})) const blockSyncRenderer = require('block-sync-renderer') const spyRegisterRequest = jest.spyOn(blockSyncRenderer, 'registerRequest').mockResolvedValue(`returned cells`) @@ -49,14 +56,11 @@ describe(``, () => { it(`should register a request`, async () => { const res = await blockSyncRenderer.queryIndexer(STUB_QUERY) expect(spyRegisterRequest).toHaveBeenNthCalledWith(2, expect.any(Object), { - channel: "queryIndexer", + channel: 'queryIndexer', id: 1, message: STUB_QUERY, - type: 'call' + type: 'call', }) expect(res).toBe('returned cells') }) - - - }) diff --git a/packages/neuron-wallet/tests/block-sync-renderer/index/resetSyncTask.test.ts b/packages/neuron-wallet/tests/block-sync-renderer/index/resetSyncTask.test.ts index 5639bd7cb6..ac88946a9e 100644 --- a/packages/neuron-wallet/tests/block-sync-renderer/index/resetSyncTask.test.ts +++ b/packages/neuron-wallet/tests/block-sync-renderer/index/resetSyncTask.test.ts @@ -2,11 +2,15 @@ describe(`Reset sync task`, () => { const stubbedmaintainAddressesIfNecessary = jest.fn() const stubbedSleep = jest.fn() const stubbedTimeout = jest.fn().mockReturnValue(Promise.resolve(10)) - jest.doMock('services/wallets', () => ({ getInstance: () => ({ maintainAddressesIfNecessary: stubbedmaintainAddressesIfNecessary }) })) + jest.doMock('services/wallets', () => ({ + getInstance: () => ({ maintainAddressesIfNecessary: stubbedmaintainAddressesIfNecessary }), + })) jest.doMock('utils/common', () => ({ sleep: stubbedSleep, timeout: stubbedTimeout })) const blockSyncRenderer = require('block-sync-renderer') - const spyCreateBlockSyncTask = jest.spyOn(blockSyncRenderer, 'createBlockSyncTask').mockImplementation(() => jest.fn()) + const spyCreateBlockSyncTask = jest + .spyOn(blockSyncRenderer, 'createBlockSyncTask') + .mockImplementation(() => jest.fn()) const spyKillBlockSyncTask = jest.spyOn(blockSyncRenderer, 'killBlockSyncTask').mockImplementation(() => jest.fn()) describe(`with (startTask = false)`, () => { diff --git a/packages/neuron-wallet/tests/block-sync-renderer/index/switchNetwork.test.ts b/packages/neuron-wallet/tests/block-sync-renderer/index/switchNetwork.test.ts index 7c0725d557..8765bedfd7 100644 --- a/packages/neuron-wallet/tests/block-sync-renderer/index/switchNetwork.test.ts +++ b/packages/neuron-wallet/tests/block-sync-renderer/index/switchNetwork.test.ts @@ -7,7 +7,7 @@ describe(`switch to network`, () => { jest.doMock('utils/logger', () => ({ info: stubbedLoggerInfo })) jest.doMock('utils/queue', () => ({ __esModule: true, - default: jest.fn().mockReturnValue({ asyncPush: asyncPushMock }) + default: jest.fn().mockReturnValue({ asyncPush: asyncPushMock }), })) const blockSyncRenderer = require('block-sync-renderer') @@ -15,7 +15,6 @@ describe(`switch to network`, () => { stubbedLoggerInfo.mockClear() }) - it(`should do nothing when reconnected is false and network is not changed`, () => { blockSyncRenderer.switchToNetwork({ ...STUB_NETWOKR, id: undefined, genesisHash: undefined }, false) expect(stubbedLoggerInfo).not.toHaveBeenCalled() @@ -40,5 +39,4 @@ describe(`switch to network`, () => { await blockSyncRenderer.switchToNetwork(STUB_NETWOKR, true) expect(asyncPushMock).toHaveBeenCalledWith(true) }) - }) diff --git a/packages/neuron-wallet/tests/block-sync-renderer/indexer-cache-service.intg.test.ts b/packages/neuron-wallet/tests/block-sync-renderer/indexer-cache-service.intg.test.ts index 96fe8d42e9..f0f3710251 100644 --- a/packages/neuron-wallet/tests/block-sync-renderer/indexer-cache-service.intg.test.ts +++ b/packages/neuron-wallet/tests/block-sync-renderer/indexer-cache-service.intg.test.ts @@ -1,28 +1,24 @@ import { when } from 'jest-when' import { getConnection } from 'typeorm' import { initConnection } from '../../src/database/chain/ormconfig' -import AddressMeta from '../../src/database/address/meta'; -import { AddressType } from '../../src/models/keys/address'; -import { AddressVersion } from '../../src/models/address'; -import IndexerTxHashCache from '../../src/database/chain/entities/indexer-tx-hash-cache'; -import RpcService from '../../src/services/rpc-service'; +import AddressMeta from '../../src/database/address/meta' +import { AddressType } from '../../src/models/keys/address' +import { AddressVersion } from '../../src/models/address' +import IndexerTxHashCache from '../../src/database/chain/entities/indexer-tx-hash-cache' +import RpcService from '../../src/services/rpc-service' const stubbedGetTransactionFn = jest.fn() const stubbedGetHeaderFn = jest.fn() const stubbedGetTransactionsByLockScriptFn = jest.fn() -const stubbedRPCServiceConstructor = jest.fn().mockImplementation( - () => ({ - getTransaction: stubbedGetTransactionFn, - getHeader: stubbedGetHeaderFn - }) -) +const stubbedRPCServiceConstructor = jest.fn().mockImplementation(() => ({ + getTransaction: stubbedGetTransactionFn, + getHeader: stubbedGetHeaderFn, +})) -const stubbedIndexerConstructor = jest.fn().mockImplementation( - () => ({ - getTransactionsByLockScript: stubbedGetTransactionsByLockScriptFn - }) -) +const stubbedIndexerConstructor = jest.fn().mockImplementation(() => ({ + getTransactionsByLockScript: stubbedGetTransactionsByLockScriptFn, +})) const stubbedTransactionCollectorConstructor = jest.fn() const stubbedCellCollectorConstructor = jest.fn() @@ -64,52 +60,55 @@ const legacyAcpLockScript = addressMeta.generateLegacyACPLockScript() const formattedDefaultLockScript = { code_hash: defaultLockScript.codeHash, hash_type: defaultLockScript.hashType, - args: defaultLockScript.args + args: defaultLockScript.args, } const formattedSingleMultiSignLockScript = { code_hash: singleMultiSignLockScript.codeHash, hash_type: singleMultiSignLockScript.hashType, - args: singleMultiSignLockScript.args + '0'.repeat(14) + args: singleMultiSignLockScript.args + '0'.repeat(14), } const formattedChequeLockScript = { code_hash: chequeLockScript.codeHash, hash_type: chequeLockScript.hashType, - args: chequeLockScript.args + args: chequeLockScript.args, } const formattedAcpLockScript = { code_hash: acpLockScript.codeHash, hash_type: acpLockScript.hashType, - args: acpLockScript.args + args: acpLockScript.args, } const formattedLegacyAcpLockScript = { code_hash: legacyAcpLockScript.codeHash, hash_type: legacyAcpLockScript.hashType, - args: legacyAcpLockScript.args + args: legacyAcpLockScript.args, } const mockGetTransactionHashes = (mocks: any[] = []) => { const stubbedConstructor = when(stubbedTransactionCollectorConstructor) - for (const lock of [ - formattedDefaultLockScript, - formattedAcpLockScript, - formattedLegacyAcpLockScript, - ]) { - const {hashes} = mocks.find(mock => mock.lock === lock) || {hashes: []} - stubbedConstructor - .calledWith(expect.anything(), {lock}).mockReturnValue({ - getTransactionHashes: jest.fn().mockReturnValue(hashes), - }) + for (const lock of [formattedDefaultLockScript, formattedAcpLockScript, formattedLegacyAcpLockScript]) { + const { hashes } = mocks.find(mock => mock.lock === lock) || { hashes: [] } + stubbedConstructor.calledWith(expect.anything(), { lock }).mockReturnValue({ + getTransactionHashes: jest.fn().mockReturnValue(hashes), + }) } } -const fakeBlock1 = {number: '1', hash: '1', timestamp: '1'} -const fakeBlock2 = {number: '2', hash: '2', timestamp: '2'} -const fakeTx1 = {transaction: {hash: 'hash1', blockNumber: fakeBlock1.number}, txStatus: {status: 'committed', blockHash: fakeBlock1.hash}} -const fakeTx2 = {transaction: {hash: 'hash2', blockNumber: fakeBlock2.number}, txStatus: {status: 'committed', blockHash: fakeBlock2.hash}} -const fakeTx3 = {transaction: {hash: 'hash3', blockNumber: fakeBlock2.number}, txStatus: {status: 'committed', blockHash: fakeBlock2.hash}} +const fakeBlock1 = { number: '1', hash: '1', timestamp: '1' } +const fakeBlock2 = { number: '2', hash: '2', timestamp: '2' } +const fakeTx1 = { + transaction: { hash: 'hash1', blockNumber: fakeBlock1.number }, + txStatus: { status: 'committed', blockHash: fakeBlock1.hash }, +} +const fakeTx2 = { + transaction: { hash: 'hash2', blockNumber: fakeBlock2.number }, + txStatus: { status: 'committed', blockHash: fakeBlock2.hash }, +} +const fakeTx3 = { + transaction: { hash: 'hash3', blockNumber: fakeBlock2.number }, + txStatus: { status: 'committed', blockHash: fakeBlock2.hash }, +} describe('indexer cache service', () => { - beforeAll(async () => { await initConnection('') }) @@ -126,11 +125,11 @@ describe('indexer cache service', () => { jest.doMock('@nervina-labs/ckb-indexer', () => { return { - CkbIndexer : stubbedIndexerConstructor, - TransactionCollector : stubbedTransactionCollectorConstructor, - CellCollector : stubbedCellCollectorConstructor + CkbIndexer: stubbedIndexerConstructor, + TransactionCollector: stubbedTransactionCollectorConstructor, + CellCollector: stubbedCellCollectorConstructor, } - }); + }) when(stubbedCellCollectorConstructor) .calledWith(expect.anything()) @@ -140,12 +139,12 @@ describe('indexer cache service', () => { [Symbol.asyncIterator]: () => { return { next: async () => { - return {done: true} - } + return { done: true } + }, } - } + }, } - } + }, }) rpcService = new stubbedRPCServiceConstructor() @@ -158,95 +157,88 @@ describe('indexer cache service', () => { it('throws error', () => { expect(() => { new IndexerCacheService('walletId', addressMetas, rpcService, stubbedIndexerConstructor()) - }).toThrow(new Error('address ckt1qyqrdsefa43s6m882pcj53m4gdnj4k440axqswmu83 does not belong to wallet id walletId')) - }); - }); - }); + }).toThrow( + new Error('address ckt1qyqrdsefa43s6m882pcj53m4gdnj4k440axqswmu83 does not belong to wallet id walletId') + ) + }) + }) + }) describe('#upsertTxHashes', () => { describe('with existing tx hashes from indexer', () => { let newTxHashes: any - const initHashes = [ - fakeTx1.transaction.hash, - fakeTx3.transaction.hash, - ] + const initHashes = [fakeTx1.transaction.hash, fakeTx3.transaction.hash] beforeEach(async () => { mockGetTransactionHashes([ { lock: formattedDefaultLockScript, - hashes: initHashes + hashes: initHashes, }, ]) when(stubbedGetTransactionFn) - .calledWith(fakeTx1.transaction.hash).mockReturnValueOnce(fakeTx1) - .calledWith(fakeTx3.transaction.hash).mockReturnValueOnce(fakeTx3) + .calledWith(fakeTx1.transaction.hash) + .mockReturnValueOnce(fakeTx1) + .calledWith(fakeTx3.transaction.hash) + .mockReturnValueOnce(fakeTx3) when(stubbedGetHeaderFn) - .calledWith(fakeBlock1.hash).mockReturnValueOnce(fakeBlock1) - .calledWith(fakeBlock2.hash).mockReturnValueOnce(fakeBlock2) + .calledWith(fakeBlock1.hash) + .mockReturnValueOnce(fakeBlock1) + .calledWith(fakeBlock2.hash) + .mockReturnValueOnce(fakeBlock2) newTxHashes = await indexerCacheService.upsertTxHashes() - }); + }) it('returns newly cached tx hashes', () => { expect(newTxHashes).toEqual([fakeTx1.transaction.hash, fakeTx3.transaction.hash]) }) it('persists tx hashes', async () => { - const caches = await getConnection() - .getRepository(IndexerTxHashCache) - .find() + const caches = await getConnection().getRepository(IndexerTxHashCache).find() expect(caches).toHaveLength(2) expect(caches.filter(cache => cache.txHash === fakeTx1.transaction.hash)).toHaveLength(1) expect(caches.filter(cache => cache.txHash === fakeTx3.transaction.hash)).toHaveLength(1) - }); + }) describe('when new tx hash available', () => { beforeEach(async () => { mockGetTransactionHashes([ { lock: formattedDefaultLockScript, - hashes: [...initHashes, fakeTx2.transaction.hash] + hashes: [...initHashes, fakeTx2.transaction.hash], }, ]) - when(stubbedGetTransactionFn) - .calledWith(fakeTx2.transaction.hash) - .mockReturnValueOnce(fakeTx2) - when(stubbedGetHeaderFn) - .calledWith(fakeBlock2.hash) - .mockReturnValueOnce(fakeBlock2) + when(stubbedGetTransactionFn).calledWith(fakeTx2.transaction.hash).mockReturnValueOnce(fakeTx2) + when(stubbedGetHeaderFn).calledWith(fakeBlock2.hash).mockReturnValueOnce(fakeBlock2) await indexerCacheService.upsertTxHashes() - }); + }) it('saves the new ones', async () => { - const caches = await getConnection() - .getRepository(IndexerTxHashCache) - .find() + const caches = await getConnection().getRepository(IndexerTxHashCache).find() expect(caches).toHaveLength(3) expect(caches.filter(cache => cache.txHash === fakeTx1.transaction.hash)).toHaveLength(1) expect(caches.filter(cache => cache.txHash === fakeTx2.transaction.hash)).toHaveLength(1) expect(caches.filter(cache => cache.txHash === fakeTx3.transaction.hash)).toHaveLength(1) - }); - }); + }) + }) describe('when all of tx hashes cache exists', () => { beforeEach(async () => { resetMocks() mockGetTransactionHashes([ { lock: formattedDefaultLockScript, - hashes: initHashes + hashes: initHashes, }, ]) await indexerCacheService.upsertTxHashes() - }); + }) it('should not do any new inserts', async () => { - const caches = await getConnection() - .getRepository(IndexerTxHashCache) - .find() + const caches = await getConnection().getRepository(IndexerTxHashCache).find() expect(caches).toHaveLength(2) expect(stubbedGetTransactionFn).toHaveBeenCalledTimes(0) expect(stubbedGetHeaderFn).toHaveBeenCalledTimes(0) - }); - }); - }); + }) + }) + }) describe('when found cells using cell collector', () => { let newTxHashes: any const fakeCollectorObj = { @@ -261,130 +253,122 @@ describe('indexer cache service', () => { done: false, value: { out_point: { - tx_hash: fakeTx2.transaction.hash - } - } + tx_hash: fakeTx2.transaction.hash, + }, + }, } } - return {done: true} - } + return { done: true } + }, } - } + }, } - } + }, } beforeEach(async () => { - when(stubbedGetTransactionFn) - .calledWith(fakeTx2.transaction.hash) - .mockReturnValueOnce(fakeTx2) - when(stubbedGetHeaderFn) - .calledWith(fakeBlock2.hash) - .mockReturnValueOnce(fakeBlock2) + when(stubbedGetTransactionFn).calledWith(fakeTx2.transaction.hash).mockReturnValueOnce(fakeTx2) + when(stubbedGetHeaderFn).calledWith(fakeBlock2.hash).mockReturnValueOnce(fakeBlock2) stubbedCellCollectorConstructor.mockReset() when(stubbedCellCollectorConstructor) - .calledWith( - expect.anything(), - { - lock: { - ...formattedSingleMultiSignLockScript, - args: formattedSingleMultiSignLockScript.args.slice(0, 42) - }, - argsLen: 28 - } - ) + .calledWith(expect.anything(), { + lock: { + ...formattedSingleMultiSignLockScript, + args: formattedSingleMultiSignLockScript.args.slice(0, 42), + }, + argsLen: 28, + }) .mockReturnValue(fakeCollectorObj) - .calledWith( - expect.anything(), - { - lock: { - ...formattedChequeLockScript, - args: formattedChequeLockScript.args.slice(0, 42) - }, - argsLen: 40 - } - ) + .calledWith(expect.anything(), { + lock: { + ...formattedChequeLockScript, + args: formattedChequeLockScript.args.slice(0, 42), + }, + argsLen: 40, + }) .mockReturnValue(fakeCollectorObj) newTxHashes = await indexerCacheService.upsertTxHashes() - }); + }) it('saves related tx cache', async () => { expect(newTxHashes).toEqual([fakeTx2.transaction.hash]) - }); - }); - }); + }) + }) + }) describe('#updateProcessedTxHashes', () => { beforeEach(async () => { mockGetTransactionHashes([ { lock: formattedDefaultLockScript, - hashes: [ - fakeTx1.transaction.hash, - fakeTx2.transaction.hash, - fakeTx3.transaction.hash, - ] + hashes: [fakeTx1.transaction.hash, fakeTx2.transaction.hash, fakeTx3.transaction.hash], }, ]) when(stubbedGetTransactionFn) - .calledWith(fakeTx1.transaction.hash).mockReturnValueOnce(fakeTx1) - .calledWith(fakeTx2.transaction.hash).mockReturnValueOnce(fakeTx2) - .calledWith(fakeTx3.transaction.hash).mockReturnValueOnce(fakeTx3) + .calledWith(fakeTx1.transaction.hash) + .mockReturnValueOnce(fakeTx1) + .calledWith(fakeTx2.transaction.hash) + .mockReturnValueOnce(fakeTx2) + .calledWith(fakeTx3.transaction.hash) + .mockReturnValueOnce(fakeTx3) when(stubbedGetHeaderFn) - .calledWith(fakeBlock1.hash).mockReturnValueOnce(fakeBlock1) - .calledWith(fakeBlock2.hash).mockReturnValue(fakeBlock2) + .calledWith(fakeBlock1.hash) + .mockReturnValueOnce(fakeBlock1) + .calledWith(fakeBlock2.hash) + .mockReturnValue(fakeBlock2) await indexerCacheService.upsertTxHashes() await indexerCacheService.updateProcessedTxHashes(fakeBlock2.number) - }); + }) it('updates isProcessed by block number', async () => { - const caches = await getConnection() - .getRepository(IndexerTxHashCache) - .find() - const cachesByBlock2 = caches.filter(cache => cache.isProcessed && cache.blockNumber === parseInt(fakeBlock2.number)) + const caches = await getConnection().getRepository(IndexerTxHashCache).find() + const cachesByBlock2 = caches.filter( + cache => cache.isProcessed && cache.blockNumber === parseInt(fakeBlock2.number) + ) expect(cachesByBlock2).toHaveLength(2) }) - }); + }) describe('#nextUnprocessedTxsGroupedByBlockNumber', () => { describe('when there are caches', () => { beforeEach(async () => { mockGetTransactionHashes([ { lock: formattedDefaultLockScript, - hashes: [ - fakeTx1.transaction.hash, - fakeTx2.transaction.hash, - fakeTx3.transaction.hash, - ] + hashes: [fakeTx1.transaction.hash, fakeTx2.transaction.hash, fakeTx3.transaction.hash], }, ]) when(stubbedGetTransactionFn) - .calledWith(fakeTx1.transaction.hash).mockReturnValueOnce(fakeTx1) - .calledWith(fakeTx2.transaction.hash).mockReturnValueOnce(fakeTx2) - .calledWith(fakeTx3.transaction.hash).mockReturnValueOnce(fakeTx3) + .calledWith(fakeTx1.transaction.hash) + .mockReturnValueOnce(fakeTx1) + .calledWith(fakeTx2.transaction.hash) + .mockReturnValueOnce(fakeTx2) + .calledWith(fakeTx3.transaction.hash) + .mockReturnValueOnce(fakeTx3) when(stubbedGetHeaderFn) - .calledWith(fakeBlock1.hash).mockReturnValueOnce(fakeBlock1) - .calledWith(fakeBlock2.hash).mockReturnValue(fakeBlock2) + .calledWith(fakeBlock1.hash) + .mockReturnValueOnce(fakeBlock1) + .calledWith(fakeBlock2.hash) + .mockReturnValue(fakeBlock2) await indexerCacheService.upsertTxHashes() - }); + }) describe('with all unprocessed transactions', () => { it('returns the tx hashes for the next block number', async () => { const txHashes = await indexerCacheService.nextUnprocessedTxsGroupedByBlockNumber() expect(txHashes).toHaveLength(1) expect(txHashes![0].blockNumber).toEqual(parseInt(fakeBlock1.number)) - }); - }); + }) + }) describe('with some blocks has been fully processed', () => { beforeEach(async () => { await getConnection() .createQueryBuilder() .update(IndexerTxHashCache) .where({ - blockNumber: fakeBlock1.number + blockNumber: fakeBlock1.number, }) .set({ - isProcessed: true + isProcessed: true, }) .execute() }) @@ -392,17 +376,17 @@ describe('indexer cache service', () => { const txHashes = await indexerCacheService.nextUnprocessedTxsGroupedByBlockNumber() expect(txHashes).toHaveLength(2) expect(txHashes![0].blockNumber).toEqual(parseInt(fakeBlock2.number)) - }); + }) describe('when some transactions has been partially processed in a block', () => { beforeEach(async () => { await getConnection() .createQueryBuilder() .update(IndexerTxHashCache) .where({ - txHash: fakeTx2.transaction.hash + txHash: fakeTx2.transaction.hash, }) .set({ - isProcessed: true + isProcessed: true, }) .execute() }) @@ -411,152 +395,144 @@ describe('indexer cache service', () => { expect(txHashes).toHaveLength(1) expect(txHashes![0].blockNumber).toEqual(parseInt(fakeBlock2.number)) expect(txHashes![0].txHash).toEqual(fakeTx3.transaction.hash) - }); - }); - }); - }); + }) + }) + }) + }) describe('when all transactions are processed', () => { beforeEach(async () => { mockGetTransactionHashes([ { lock: formattedDefaultLockScript, - hashes: [ - fakeTx1.transaction.hash, - fakeTx2.transaction.hash, - fakeTx3.transaction.hash, - ] + hashes: [fakeTx1.transaction.hash, fakeTx2.transaction.hash, fakeTx3.transaction.hash], }, ]) when(stubbedGetTransactionFn) - .calledWith(fakeTx1.transaction.hash).mockReturnValueOnce(fakeTx1) - .calledWith(fakeTx2.transaction.hash).mockReturnValueOnce(fakeTx2) - .calledWith(fakeTx3.transaction.hash).mockReturnValueOnce(fakeTx3) + .calledWith(fakeTx1.transaction.hash) + .mockReturnValueOnce(fakeTx1) + .calledWith(fakeTx2.transaction.hash) + .mockReturnValueOnce(fakeTx2) + .calledWith(fakeTx3.transaction.hash) + .mockReturnValueOnce(fakeTx3) when(stubbedGetHeaderFn) - .calledWith(fakeBlock1.hash).mockReturnValueOnce(fakeBlock1) - .calledWith(fakeBlock2.hash).mockReturnValue(fakeBlock2) + .calledWith(fakeBlock1.hash) + .mockReturnValueOnce(fakeBlock1) + .calledWith(fakeBlock2.hash) + .mockReturnValue(fakeBlock2) await indexerCacheService.upsertTxHashes() await getConnection() .createQueryBuilder() .update(IndexerTxHashCache) .set({ - isProcessed: true + isProcessed: true, }) .execute() - }); + }) it('returns empty array when no unprocessed transactions', async () => { const txHashes = await indexerCacheService.nextUnprocessedTxsGroupedByBlockNumber() expect(txHashes).toEqual([]) - }); - }); - }); + }) + }) + }) describe('#nextUnprocessedBlock', () => { beforeEach(async () => { mockGetTransactionHashes([ { lock: formattedDefaultLockScript, - hashes: [ - fakeTx1.transaction.hash, - ] + hashes: [fakeTx1.transaction.hash], }, ]) - when(stubbedGetTransactionFn) - .calledWith(fakeTx1.transaction.hash).mockReturnValueOnce(fakeTx1) - when(stubbedGetHeaderFn) - .calledWith(fakeBlock1.hash).mockReturnValueOnce(fakeBlock1) + when(stubbedGetTransactionFn).calledWith(fakeTx1.transaction.hash).mockReturnValueOnce(fakeTx1) + when(stubbedGetHeaderFn).calledWith(fakeBlock1.hash).mockReturnValueOnce(fakeBlock1) await indexerCacheService.upsertTxHashes() - }); + }) describe('when has unprocessed blocks', () => { let nextUnprocessedBlock: any describe('check with walletId having tx hash caches', () => { beforeEach(async () => { nextUnprocessedBlock = await IndexerCacheService.nextUnprocessedBlock([walletId]) - }); + }) it('returns next unprocessed block number', async () => { expect(nextUnprocessedBlock).toEqual({ - blockNumber: fakeBlock1.number, blockHash: fakeBlock1.hash + blockNumber: fakeBlock1.number, + blockHash: fakeBlock1.hash, }) - }); - }); + }) + }) describe('check with walletId that does not have hash caches', () => { beforeEach(async () => { nextUnprocessedBlock = await IndexerCacheService.nextUnprocessedBlock(['w1']) - }); + }) it('returns undefined', async () => { expect(nextUnprocessedBlock).toEqual(undefined) - }); - }); + }) + }) describe('check with empty walletIds array', () => { beforeEach(async () => { nextUnprocessedBlock = await IndexerCacheService.nextUnprocessedBlock([]) - }); + }) it('returns undefined', async () => { expect(nextUnprocessedBlock).toEqual(undefined) - }); - }); - }); + }) + }) + }) describe('when has no unprocessed blocks', () => { beforeEach(async () => { await getConnection() .createQueryBuilder() .update(IndexerTxHashCache) .set({ - isProcessed: true + isProcessed: true, }) .execute() - }); + }) it('returns undefined', async () => { const nextUnprocessedBlock = await IndexerCacheService.nextUnprocessedBlock([walletId]) expect(nextUnprocessedBlock).toEqual(undefined) - }); - }); - }); + }) + }) + }) describe('#updateCacheProcessed', () => { describe('when there are unprocessed tx hash cache', () => { beforeEach(async () => { mockGetTransactionHashes([ { lock: formattedDefaultLockScript, - hashes: [ - fakeTx1.transaction.hash, - fakeTx2.transaction.hash, - fakeTx3.transaction.hash, - ] + hashes: [fakeTx1.transaction.hash, fakeTx2.transaction.hash, fakeTx3.transaction.hash], }, ]) when(stubbedGetTransactionFn) - .calledWith(fakeTx1.transaction.hash).mockReturnValueOnce(fakeTx1) - .calledWith(fakeTx2.transaction.hash).mockReturnValueOnce(fakeTx2) - .calledWith(fakeTx3.transaction.hash).mockReturnValueOnce(fakeTx3) + .calledWith(fakeTx1.transaction.hash) + .mockReturnValueOnce(fakeTx1) + .calledWith(fakeTx2.transaction.hash) + .mockReturnValueOnce(fakeTx2) + .calledWith(fakeTx3.transaction.hash) + .mockReturnValueOnce(fakeTx3) when(stubbedGetHeaderFn) - .calledWith(fakeBlock1.hash).mockReturnValueOnce(fakeBlock1) - .calledWith(fakeBlock2.hash).mockReturnValue(fakeBlock2) + .calledWith(fakeBlock1.hash) + .mockReturnValueOnce(fakeBlock1) + .calledWith(fakeBlock2.hash) + .mockReturnValue(fakeBlock2) await indexerCacheService.upsertTxHashes() - const caches = await getConnection() - .getRepository(IndexerTxHashCache) - .find() + const caches = await getConnection().getRepository(IndexerTxHashCache).find() const processedCaches = caches.filter(cache => !cache.isProcessed) expect(processedCaches).toHaveLength(3) - for (const hash of [ - fakeTx1.transaction.hash, - fakeTx3.transaction.hash, - ]) { + for (const hash of [fakeTx1.transaction.hash, fakeTx3.transaction.hash]) { await IndexerCacheService.updateCacheProcessed(hash) } - }); + }) it('updates isProcessed to be true', async () => { - const caches = await getConnection() - .getRepository(IndexerTxHashCache) - .find() + const caches = await getConnection().getRepository(IndexerTxHashCache).find() const processedCaches = caches.filter(cache => cache.isProcessed) expect(processedCaches).toHaveLength(2) expect(processedCaches.filter(cache => cache.txHash === fakeTx1.transaction.hash)).toHaveLength(1) expect(processedCaches.filter(cache => cache.txHash === fakeTx3.transaction.hash)).toHaveLength(1) - }); - }); - }); + }) + }) + }) }) diff --git a/packages/neuron-wallet/tests/block-sync-renderer/indexer-connector.test.ts b/packages/neuron-wallet/tests/block-sync-renderer/indexer-connector.test.ts index 3f47d3dbc9..a73f7c392f 100644 --- a/packages/neuron-wallet/tests/block-sync-renderer/indexer-connector.test.ts +++ b/packages/neuron-wallet/tests/block-sync-renderer/indexer-connector.test.ts @@ -55,17 +55,17 @@ describe('unit tests for IndexerConnector', () => { jest.doMock('@nervina-labs/ckb-indexer', () => { return { CkbIndexer: stubbedIndexerConstructor.mockImplementation(() => ({ - tip: stubbedTipFn + tip: stubbedTipFn, })), CellCollector: stubbedCellCollectorConstructor.mockImplementation(() => ({ - collect: stubbedCellCellectFn - })) + collect: stubbedCellCellectFn, + })), } }) jest.doMock('services/rpc-service', () => { return stubbedRPCServiceConstructor.mockImplementation(() => ({ getTransaction: stubbedGetTransactionFn, - getHeader: stubbedGetHeaderFn + getHeader: stubbedGetHeaderFn, })) }) jest.doMock('utils/logger', () => { @@ -74,7 +74,7 @@ describe('unit tests for IndexerConnector', () => { jest.doMock('../../src/block-sync-renderer/sync/indexer-cache-service', () => { return stubbedIndexerCacheService.mockImplementation(() => ({ upsertTxHashes: stubbedUpsertTxHashesFn, - nextUnprocessedTxsGroupedByBlockNumber: stubbedNextUnprocessedTxsGroupedByBlockNumberFn + nextUnprocessedTxsGroupedByBlockNumber: stubbedNextUnprocessedTxsGroupedByBlockNumberFn, })) }) stubbedIndexerConnector = require('../../src/block-sync-renderer/sync/indexer-connector').default @@ -115,36 +115,36 @@ describe('unit tests for IndexerConnector', () => { const fakeBlock3 = { number: '3', hash: '3', timestamp: '3' } const fakeTx1 = { transaction: { hash: 'hash1', blockNumber: fakeBlock1.number, blockTimestamp: new Date(1) }, - txStatus: { status: 'committed', blockHash: fakeBlock1.hash } + txStatus: { status: 'committed', blockHash: fakeBlock1.hash }, } const fakeTx2 = { transaction: { hash: 'hash2', blockNumber: fakeBlock2.number, blockTimestamp: new Date(2) }, - txStatus: { status: 'committed', blockHash: fakeBlock2.hash } + txStatus: { status: 'committed', blockHash: fakeBlock2.hash }, } const fakeTx3 = { transaction: { hash: 'hash3', blockNumber: fakeBlock2.number, blockTimestamp: new Date(3) }, - txStatus: { status: 'committed', blockHash: fakeBlock2.hash } + txStatus: { status: 'committed', blockHash: fakeBlock2.hash }, } const fakeTxHashCache1 = { txHash: fakeTx1.transaction.hash, blockNumber: fakeTx1.transaction.blockNumber, - blockTimestamp: fakeTx1.transaction.blockTimestamp + blockTimestamp: fakeTx1.transaction.blockTimestamp, } const fakeTxHashCache2 = { txHash: fakeTx2.transaction.hash, blockNumber: fakeTx2.transaction.blockNumber, - blockTimestamp: fakeTx2.transaction.blockTimestamp + blockTimestamp: fakeTx2.transaction.blockTimestamp, } const fakeTxHashCache3 = { txHash: fakeTx3.transaction.hash, blockNumber: fakeTx3.transaction.blockNumber, - blockTimestamp: fakeTx3.transaction.blockTimestamp + blockTimestamp: fakeTx3.transaction.blockTimestamp, } let indexerConnector: IndexerConnector const shortAddressInfo = { - lock: SystemScriptInfo.generateSecpScript('0x36c329ed630d6ce750712a477543672adab57f4c') + lock: SystemScriptInfo.generateSecpScript('0x36c329ed630d6ce750712a477543672adab57f4c'), } const address = scriptToAddress(shortAddressInfo.lock, false) const walletId1 = 'walletid1' @@ -161,7 +161,7 @@ describe('unit tests for IndexerConnector', () => { sentBalance: '', pendingBalance: '', balance: '', - version: AddressVersion.Testnet + version: AddressVersion.Testnet, } const addressObj2: Address = { address, @@ -175,7 +175,7 @@ describe('unit tests for IndexerConnector', () => { sentBalance: '', pendingBalance: '', balance: '', - version: AddressVersion.Testnet + version: AddressVersion.Testnet, } const addressesToWatch = [addressObj1, addressObj2] @@ -327,9 +327,7 @@ describe('unit tests for IndexerConnector', () => { beforeEach(async () => { stubbedUpsertTxHashesFn.mockReturnValueOnce([fakeTx3.transaction.hash]) stubbedNextUnprocessedTxsGroupedByBlockNumberFn.mockResolvedValue([fakeTxHashCache3]) - when(stubbedGetTransactionFn) - .calledWith(fakeTxHashCache3.txHash) - .mockResolvedValueOnce(undefined) + when(stubbedGetTransactionFn).calledWith(fakeTxHashCache3.txHash).mockResolvedValueOnce(undefined) txObserver = jest.fn() transactionsSubject.subscribe((transactions: any) => txObserver(transactions)) @@ -363,7 +361,7 @@ describe('unit tests for IndexerConnector', () => { expect(tipObserver).toHaveBeenCalledTimes(1) expect(tipObserver).toHaveBeenCalledWith({ cacheTipNumber: parseInt(fakeTip1.block_number), - indexerTipNumber: parseInt(fakeTip1.block_number) + indexerTipNumber: parseInt(fakeTip1.block_number), }) }) describe('fast forward the interval time', () => { @@ -377,7 +375,7 @@ describe('unit tests for IndexerConnector', () => { expect(tipObserver).toHaveBeenCalledTimes(2) expect(tipObserver).toHaveBeenCalledWith({ cacheTipNumber: parseInt(fakeTip2.block_number), - indexerTipNumber: parseInt(fakeTip2.block_number) + indexerTipNumber: parseInt(fakeTip2.block_number), }) }) }) @@ -385,7 +383,7 @@ describe('unit tests for IndexerConnector', () => { beforeEach(async () => { stubbedNextUnprocessedBlock.mockResolvedValue({ blockNumber: fakeBlock3.number, - blockHash: fakeBlock3.hash + blockHash: fakeBlock3.hash, }) jest.advanceTimersByTime(5000) await flushPromises() @@ -394,7 +392,7 @@ describe('unit tests for IndexerConnector', () => { expect(tipObserver).toHaveBeenCalledTimes(2) expect(tipObserver).toHaveBeenCalledWith({ cacheTipNumber: parseInt(fakeBlock3.number), - indexerTipNumber: parseInt(fakeTip2.block_number) + indexerTipNumber: parseInt(fakeTip2.block_number), }) }) }) @@ -410,28 +408,28 @@ describe('unit tests for IndexerConnector', () => { lock: { hash_type: 'type', code_hash: '0xcode', - args: '0x1' + args: '0x1', }, type: { hash_type: 'data', code_hash: '0xcode', - args: '0x1' - } - } + args: '0x1', + }, + }, } fakeCell2 = { cell_output: { lock: { hash_type: 'type', code_hash: '0xcode', - args: '0x2' + args: '0x2', }, type: { hash_type: 'lock', code_hash: '0xcode', - args: '0x2' - } - } + args: '0x2', + }, + }, } const fakeCells = [fakeCell1, fakeCell2] @@ -440,22 +438,22 @@ describe('unit tests for IndexerConnector', () => { lock: { hashType: ScriptHashType.Data, codeHash: '0xcode', - args: '0x' + args: '0x', }, type: { //test the workaround for this lumos data issue //@ts-ignore hashType: 'lock', codeHash: '0xcode', - args: '0x' + args: '0x', }, - data: null + data: null, } beforeEach(async () => { stubbedCellCellectFn.mockReturnValueOnce([ new Promise(resolve => resolve(JSON.parse(JSON.stringify(fakeCells[0])))), - new Promise(resolve => resolve(JSON.parse(JSON.stringify(fakeCells[1])))) + new Promise(resolve => resolve(JSON.parse(JSON.stringify(fakeCells[1])))), ]) cells = await indexerConnector.getLiveCellsByScript(query) @@ -465,14 +463,14 @@ describe('unit tests for IndexerConnector', () => { lock: { hash_type: query.lock!.hashType, code_hash: query.lock!.codeHash, - args: query.lock!.args + args: query.lock!.args, }, type: { hash_type: query.type!.hashType, code_hash: query.type!.codeHash, - args: query.type!.args + args: query.type!.args, }, - data: 'any' + data: 'any', }) }) it('returns live cells with property value fix', async () => { @@ -485,27 +483,27 @@ describe('unit tests for IndexerConnector', () => { lock: { hashType: ScriptHashType.Data, codeHash: '0xcode', - args: '0x1' + args: '0x1', }, type: { hashType: ScriptHashType.Data, codeHash: '0xcode', - args: '0x1' + args: '0x1', }, - data: null + data: null, } const query2: LumosCellQuery = { lock: { hashType: ScriptHashType.Type, codeHash: '0xcode', - args: '0x2' + args: '0x2', }, type: { hashType: ScriptHashType.Type, codeHash: '0xcode', - args: '0x2' + args: '0x2', }, - data: null + data: null, } const results: unknown[] = [] @@ -517,23 +515,23 @@ describe('unit tests for IndexerConnector', () => { setTimeout(() => { resolve(JSON.parse(JSON.stringify(fakeCells[0]))) }, 500) - }) + }), ]) const stubbedCellCellect2 = jest.fn() stubbedCellCellect2.mockReturnValueOnce([ - new Promise(resolve => resolve(JSON.parse(JSON.stringify(fakeCells[1])))) + new Promise(resolve => resolve(JSON.parse(JSON.stringify(fakeCells[1])))), ]) stubbedCellCollectorConstructor.mockImplementation((_indexer: any, query: any) => { if (query.lock.args === '0x1') { return { - collect: stubbedCellCellect1 + collect: stubbedCellCellect1, } } if (query.lock.args === '0x2') { return { - collect: stubbedCellCellect2 + collect: stubbedCellCellect2, } } }) @@ -550,7 +548,7 @@ describe('unit tests for IndexerConnector', () => { results.push(cells) resolve() }) - }) + }), ]) jest.advanceTimersByTime(500) diff --git a/packages/neuron-wallet/tests/block-sync-renderer/queue.test.ts b/packages/neuron-wallet/tests/block-sync-renderer/queue.test.ts index 9076888921..f441c0cf27 100644 --- a/packages/neuron-wallet/tests/block-sync-renderer/queue.test.ts +++ b/packages/neuron-wallet/tests/block-sync-renderer/queue.test.ts @@ -34,14 +34,14 @@ const stubbedLoggerErrorFn = jest.fn() const stubbedTxAddressFinder = jest.fn().mockImplementation((...args) => { stubbedTxAddressFinderConstructor(...args) return { - addresses: stubbedAddressesFn + addresses: stubbedAddressesFn, } }) const stubbedRPCServiceConstructor = jest.fn().mockImplementation(() => ({ getChain: stubbedGetChainFn, getTransaction: stubbedGetTransactionFn, - genesisBlockHash: stubbedGenesisBlockHashFn + genesisBlockHash: stubbedGenesisBlockHashFn, })) const stubbedProcessSend = jest.spyOn(process, 'send') @@ -69,13 +69,13 @@ const generateFakeTx = (id: string, publicKeyHash: string = '0x') => { fakeTx.outputs = [ Output.fromObject({ capacity: '1', - lock: Script.fromObject({ hashType: ScriptHashType.Type, codeHash: '0x' + id.repeat(64), args: publicKeyHash }) - }) + lock: Script.fromObject({ hashType: ScriptHashType.Type, codeHash: '0x' + id.repeat(64), args: publicKeyHash }), + }), ] fakeTx.blockNumber = '1' const fakeTxWithStatus = { transaction: fakeTx, - txStatus: new TxStatus('0x' + id.repeat(64), TxStatusType.Committed) + txStatus: new TxStatus('0x' + id.repeat(64), TxStatusType.Committed), } return fakeTxWithStatus } @@ -85,7 +85,7 @@ describe('queue', () => { const fakeNodeUrl = 'http://fakenode:8114' const fakeChain = 'ckb_test' const shortAddressInfo = { - lock: SystemScriptInfo.generateSecpScript('0x36c329ed630d6ce750712a477543672adab57f4c') + lock: SystemScriptInfo.generateSecpScript('0x36c329ed630d6ce750712a477543672adab57f4c'), } const address = scriptToAddress(shortAddressInfo.lock, false) const fakeWalletId = 'w1' @@ -101,7 +101,7 @@ describe('queue', () => { sentBalance: '', pendingBalance: '', balance: '', - version: AddressVersion.Testnet + version: AddressVersion.Testnet, } const addresses = [addressInfo] @@ -120,14 +120,14 @@ describe('queue', () => { connect: stubbedConnectFn, blockTipsSubject: stubbedBlockTipsSubject, transactionsSubject: stubbedTransactionsSubject, - notifyCurrentBlockNumberProcessed: stubbedNotifyCurrentBlockNumberProcessedFn + notifyCurrentBlockNumberProcessed: stubbedNotifyCurrentBlockNumberProcessedFn, } }) jest.doMock('controllers/sync-api', () => { return { emiter: { - emit: stubbedEmiterInvokeFn - } + emit: stubbedEmiterInvokeFn, + }, } }) jest.doMock('services/rpc-service', () => { @@ -136,16 +136,16 @@ describe('queue', () => { jest.doMock('services/tx', () => { return { TransactionPersistor: { - saveFetchTx: stubbedSaveFetchFn - } + saveFetchTx: stubbedSaveFetchFn, + }, } }) jest.doMock('services/wallets', () => ({ getInstance: () => ({ get: () => ({ - checkAndGenerateAddresses: stubbedCheckAndGenerateAddressesFn - }) - }) + checkAndGenerateAddresses: stubbedCheckAndGenerateAddressesFn, + }), + }), })) jest.doMock('utils/logger', () => { return { error: stubbedLoggerErrorFn, info: jest.fn() } @@ -186,7 +186,7 @@ describe('queue', () => { stubbedBlockTipsSubject.next({ cacheTipNumber: 3, indexerTipNumber: 3 }) expect(stubbedProcessSend).toHaveBeenCalledWith({ channel: 'cache-tip-block-updated', - message: { cacheTipNumber: 3, indexerTipNumber: 3, timestamp: expect.anything() } + message: { cacheTipNumber: 3, indexerTipNumber: 3, timestamp: expect.anything() }, }) }) }) @@ -220,7 +220,10 @@ describe('queue', () => { } }) it('checks and generate new addresses', () => { - expect(stubbedProcessSend).toHaveBeenCalledWith({ channel: "check-and-save-wallet-address", message: [fakeWalletId]}) + expect(stubbedProcessSend).toHaveBeenCalledWith({ + channel: 'check-and-save-wallet-address', + message: [fakeWalletId], + }) }) it('notify indexer connector of processed block number', () => { expect(stubbedNotifyCurrentBlockNumberProcessedFn).toHaveBeenCalledWith( @@ -256,7 +259,7 @@ describe('queue', () => { }) it('emit event indexer-error', () => { expect(stubbedProcessSend).toHaveBeenCalledWith({ - channel: 'indexer-error' + channel: 'indexer-error', }) }) }) diff --git a/packages/neuron-wallet/tests/block-sync-renderer/task.test.ts b/packages/neuron-wallet/tests/block-sync-renderer/task.test.ts index ccfd8b45b3..9926b46f20 100644 --- a/packages/neuron-wallet/tests/block-sync-renderer/task.test.ts +++ b/packages/neuron-wallet/tests/block-sync-renderer/task.test.ts @@ -6,20 +6,20 @@ const STUB_START_MESSAGE = { genesisHash: 'stub_genesis_hash', url: 'stub_url', addressMetas: 'stub_address_metas', - indexerUrl: 'stub_indexer_url' - } + indexerUrl: 'stub_indexer_url', + }, } const STUB_QUERY_INDEXER_MESSAGE = { type: 'call', id: 1, channel: 'queryIndexer', - message: 'stub_query_indexer_message' + message: 'stub_query_indexer_message', } const STUB_UNMOUNT_MESSAGE = { type: 'call', id: 2, - channel: 'unmount' + channel: 'unmount', } const STUB_LIVE_CELLS = ['stub_live_cells'] @@ -32,8 +32,8 @@ describe(`Block Sync Task`, () => { start: stubbedSyncQueueStart, stopAndWait: stubbedSyncQueueStopAndWait, getIndexerConnector: jest.fn().mockImplementation(() => ({ - getLiveCellsByScript: stubbedGetLiveCellsByScript - })) + getLiveCellsByScript: stubbedGetLiveCellsByScript, + })), })) const stubbedInitConnection = jest.fn() const stubbedLoggerError = jest.fn() @@ -80,7 +80,7 @@ describe(`Block Sync Task`, () => { id: STUB_START_MESSAGE.id, type: 'response', channel: STUB_START_MESSAGE.channel, - message: null + message: null, }) }) }) @@ -96,7 +96,7 @@ describe(`Block Sync Task`, () => { id: STUB_QUERY_INDEXER_MESSAGE.id, type: 'response', channel: STUB_QUERY_INDEXER_MESSAGE.channel, - message: [] + message: [], }) }) @@ -106,7 +106,7 @@ describe(`Block Sync Task`, () => { id: STUB_QUERY_INDEXER_MESSAGE.id, type: 'response', channel: STUB_QUERY_INDEXER_MESSAGE.channel, - message: STUB_LIVE_CELLS + message: STUB_LIVE_CELLS, }) }) }) diff --git a/packages/neuron-wallet/tests/block-sync-renderer/tx-status-listener.intg.test.ts b/packages/neuron-wallet/tests/block-sync-renderer/tx-status-listener.intg.test.ts index b2386e6f3b..9178b1a4ea 100644 --- a/packages/neuron-wallet/tests/block-sync-renderer/tx-status-listener.intg.test.ts +++ b/packages/neuron-wallet/tests/block-sync-renderer/tx-status-listener.intg.test.ts @@ -13,10 +13,10 @@ const stubbedGetHeaderFn = jest.fn() const stubbedRxJsIntervalFn = jest.fn() jest.doMock('models/subjects/address-created-subject', () => ({ - getSubject: jest.fn().mockImplementation(() => ({ subscribe: jest.fn })) + getSubject: jest.fn().mockImplementation(() => ({ subscribe: jest.fn })), })) jest.doMock('models/subjects/wallet-deleted-subject', () => ({ - getSubject: jest.fn().mockImplementation(() => ({ subscribe: jest.fn() })) + getSubject: jest.fn().mockImplementation(() => ({ subscribe: jest.fn() })), })) const resetMocks = () => { @@ -24,27 +24,25 @@ const resetMocks = () => { stubbedRxJsIntervalFn.mockReset() } -stubbedRPCServiceConstructor.mockImplementation( - () => ({ - getTransaction: stubbedGetTransactionFn, - getHeader: stubbedGetHeaderFn, - }) -) +stubbedRPCServiceConstructor.mockImplementation(() => ({ + getTransaction: stubbedGetTransactionFn, + getHeader: stubbedGetHeaderFn, +})) jest.doMock('services/rpc-service', () => { return stubbedRPCServiceConstructor -}); +}) jest.doMock('rxjs', () => { return { __esModule: true, interval: stubbedRxJsIntervalFn, ReplaySubject: jest.fn(), Subject: jest.fn().mockReturnValue({ - pipe: jest.fn().mockReturnValue({ subscribe: jest.fn() }) + pipe: jest.fn().mockReturnValue({ subscribe: jest.fn() }), }), BehaviorSubject: jest.fn(), } -}); +}) const { register } = require('../../src/block-sync-renderer/tx-status-listener') @@ -73,9 +71,9 @@ describe('', () => { stubbedRxJsIntervalFn.mockReturnValue({ subscribe: (_callback: any) => { trackingStatus = _callback - } + }, }) - }); + }) describe('when there are pending txs', () => { beforeEach(async () => { @@ -89,58 +87,52 @@ describe('', () => { const txStatus = new TxStatus('', TxStatusType.Committed) stubbedGetTransactionFn.mockResolvedValue({ transaction: tx1, - txStatus + txStatus, }) register() await trackingStatus() - }); + }) it('updates tx status to success', async () => { - const txs = await getConnection() - .getRepository(TransactionEntity) - .find() + const txs = await getConnection().getRepository(TransactionEntity).find() expect(txs[0].status).toEqual('success') - }); - }); + }) + }) describe('with pending status', () => { beforeEach(async () => { const txStatus = new TxStatus('', TxStatusType.Pending) stubbedGetTransactionFn.mockResolvedValue({ transaction: tx1, - txStatus + txStatus, }) register() await trackingStatus() - }); + }) it('tx status remains pending', async () => { - const txs = await getConnection() - .getRepository(TransactionEntity) - .find() + const txs = await getConnection().getRepository(TransactionEntity).find() expect(txs[0].status).toEqual('pending') - }); - }); + }) + }) describe('with no transaction returned from rpc', () => { beforeEach(async () => { register() await trackingStatus() - }); + }) it('updates tx status to failed', async () => { - const txs = await getConnection() - .getRepository(TransactionEntity) - .find() + const txs = await getConnection().getRepository(TransactionEntity).find() expect(txs[0].status).toEqual('failed') - }); - }); - }); + }) + }) + }) describe('when there are no pending txs', () => { beforeEach(async () => { register() await trackingStatus() - }); + }) it('should not proceed', () => { expect(stubbedGetTransactionFn).toHaveBeenCalledTimes(0) }) }) - }); -}); + }) +}) diff --git a/packages/neuron-wallet/tests/controllers/anyone-can-pay.test.ts b/packages/neuron-wallet/tests/controllers/anyone-can-pay.test.ts index d516f3ac0a..58fb1fc3f1 100644 --- a/packages/neuron-wallet/tests/controllers/anyone-can-pay.test.ts +++ b/packages/neuron-wallet/tests/controllers/anyone-can-pay.test.ts @@ -18,9 +18,7 @@ jest.mock('../../src/services/anyone-can-pay', () => ({ const fromObjectMock = jest.fn() jest.mock('../../src/models/chain/transaction', () => { - function mockClass() { - - } + function mockClass() {} mockClass.fromObject = () => fromObjectMock() return mockClass }) @@ -29,19 +27,19 @@ const sendTxMock = jest.fn() jest.mock('../../src/services/transaction-sender', () => { return function () { return { - sendTx: sendTxMock + sendTx: sendTxMock, } } }) const setDescriptionMock = jest.fn() jest.mock('../../src/services/tx/transaction-description', () => { - const originalModule = jest.requireActual('../../src/services/tx/transaction-description'); + const originalModule = jest.requireActual('../../src/services/tx/transaction-description') return { __esModule: true, ...originalModule, - set: (a: any, b: any, c: any) => setDescriptionMock(a, b, c) + set: (a: any, b: any, c: any) => setDescriptionMock(a, b, c), } }) @@ -54,7 +52,7 @@ describe('anyone-can-pay-controller', () => { amount: 'string', assetAccountID: 1, feeRate: '0', - fee: '1000' + fee: '1000', } it('throw exception ServiceHasNoResponse', async () => { generateAnyoneCanPayTxMock.mockResolvedValueOnce(undefined) @@ -66,7 +64,7 @@ describe('anyone-can-pay-controller', () => { const res = await anyoneCanPayController.generateTx(params) expect(res).toEqual({ status: ResponseCode.Success, - result: {} + result: {}, }) }) }) @@ -78,7 +76,7 @@ describe('anyone-can-pay-controller', () => { amount: 'all', assetAccountID: 1, feeRate: '0', - fee: '1000' + fee: '1000', } generateAnyoneCanPayTxMock.mockResolvedValueOnce({}) await anyoneCanPayController.generateTx(params) @@ -98,7 +96,7 @@ describe('anyone-can-pay-controller', () => { walletID: 'string', tx: new Transaction('', [], [], [], [], []), password: 'string', - skipLastInputs: false + skipLastInputs: false, } it('throw exception', async () => { sendTxMock.mockResolvedValueOnce(undefined) @@ -127,22 +125,22 @@ describe('anyone-can-pay-controller', () => { }) it('generateSudtMigrateAcpTx', async () => { - await anyoneCanPayController.generateSudtMigrateAcpTx({ outPoint: { txHash: 'txHash', index: '1' }}) + await anyoneCanPayController.generateSudtMigrateAcpTx({ outPoint: { txHash: 'txHash', index: '1' } }) expect(generateSudtMigrateAcpTxMock).toHaveBeenCalled() }) describe('getHoldSudtCellExtraCkb', () => { it('correct address', async () => { - const address = 'ckt1qq6pngwqn6e9vlm92th84rk0l4jp2h8lurchjmnwv8kq3rt5psf4vqvyxgyfu4z8yq4t790um8jef7lpm40h2csv4cv7m' + const address = + 'ckt1qq6pngwqn6e9vlm92th84rk0l4jp2h8lurchjmnwv8kq3rt5psf4vqvyxgyfu4z8yq4t790um8jef7lpm40h2csv4cv7m' await anyoneCanPayController.getHoldSudtCellCapacity(address, 'tokenID') - expect(getHoldSUDTCellCapacityMock).toHaveBeenCalledWith( - addressToScript(address), - 'tokenID' - ) + expect(getHoldSUDTCellCapacityMock).toHaveBeenCalledWith(addressToScript(address), 'tokenID') }) it('error address', async () => { const address = 'ct1qq6pngwqn6e9vlm92th84rk0l4jp2h8lurchjmnwv8kq3rt5psf4vqvyxgyfu4z8yq4t790um8jef7lpm40h2csv4cv7m' - await expect(anyoneCanPayController.getHoldSudtCellCapacity(address, 'tokenID')).rejects.toThrow(new Error('Address format error')) + await expect(anyoneCanPayController.getHoldSudtCellCapacity(address, 'tokenID')).rejects.toThrow( + new Error('Address format error') + ) }) }) -}) \ No newline at end of file +}) diff --git a/packages/neuron-wallet/tests/controllers/asset-account.test.ts b/packages/neuron-wallet/tests/controllers/asset-account.test.ts index b0d8a6027d..b74c6d63c3 100644 --- a/packages/neuron-wallet/tests/controllers/asset-account.test.ts +++ b/packages/neuron-wallet/tests/controllers/asset-account.test.ts @@ -1,5 +1,4 @@ - -import {SyncStatus} from '../../src/controllers/sync-api' +import { SyncStatus } from '../../src/controllers/sync-api' import { ServiceHasNoResponse } from '../../src/exceptions' const stubbedGetSyncStatus = jest.fn() @@ -26,83 +25,86 @@ jest.mock('../../src/services/settings', () => { return { getInstance() { return {} - } + }, } }) describe('AssetAccountController', () => { - let assetAccountController: any; - let AssetAccountController: any; + let assetAccountController: any + let AssetAccountController: any const walletId = 'w1' jest.doMock('electron', () => { return { - BrowserWindow : { + BrowserWindow: { getAllWindows: stubbedGetAllWindows, - getFocusedWindow: stubbedGetFocusedWindow + getFocusedWindow: stubbedGetFocusedWindow, }, dialog: { - showMessageBox: stubbedShowMessageBox - } + showMessageBox: stubbedShowMessageBox, + }, } - }); + }) jest.doMock('../../src/services/wallets', () => { return { - getInstance : () => ({ - getCurrent: () => ({id: walletId}) - }) + getInstance: () => ({ + getCurrent: () => ({ id: walletId }), + }), } - }); + }) jest.doMock('../../src/controllers/sync-api', () => ({ __esModule: true, default: { getInstance: () => ({ - getSyncStatus: stubbedGetSyncStatus + getSyncStatus: stubbedGetSyncStatus, }), }, - SyncStatus: SyncStatus - })); + SyncStatus: SyncStatus, + })) jest.doMock('../../src/services/tx', () => ({ TransactionGenerator: { - generateMigrateLegacyACPTx: stubbedGenerateMigrateLegacyACPTx - } - })); + generateMigrateLegacyACPTx: stubbedGenerateMigrateLegacyACPTx, + }, + })) jest.doMock('../../src/models/subjects/command', () => ({ - next: stubbedCommandSubjectNext - })); + next: stubbedCommandSubjectNext, + })) jest.doMock('../../src/services/asset-account-service.ts', () => ({ getAccount: stubbedAssetAccountServiceGetAccount, - destoryAssetAccount: stubbedAssetAccountServiceDestoryAssetAccount + destoryAssetAccount: stubbedAssetAccountServiceDestoryAssetAccount, })) beforeEach(() => { resetMocks() AssetAccountController = require('../../src/controllers/asset-account').default assetAccountController = new AssetAccountController() - }); + }) describe('#showACPMigrationDialog', () => { const mockStates = (syncStatus: any, windowsCount: any, hasFocusedWindow: any, hasTx: any) => { stubbedGetSyncStatus.mockResolvedValue(syncStatus) stubbedGetAllWindows.mockReturnValue(Array(windowsCount)) - stubbedGetFocusedWindow.mockReturnValue(hasFocusedWindow ? {id: '1'} : undefined) + stubbedGetFocusedWindow.mockReturnValue(hasFocusedWindow ? { id: '1' } : undefined) stubbedGenerateMigrateLegacyACPTx.mockResolvedValue(hasTx ? {} : null) } beforeEach(() => { - stubbedShowMessageBox.mockResolvedValue({response: 1}) - }); + stubbedShowMessageBox.mockResolvedValue({ response: 1 }) + }) describe('when all conditions met to display dialog', () => { beforeEach(async () => { mockStates(SyncStatus.SyncCompleted, 1, true, true) await assetAccountController.showACPMigrationDialog() - }); + }) it('broadcast migrate-acp command', () => { expect(stubbedCommandSubjectNext).toHaveBeenCalledWith({ - dispatchToUI: true, payload: "w1", type: "migrate-acp", winID: "1" + dispatchToUI: true, + payload: 'w1', + type: 'migrate-acp', + winID: '1', }) }) describe('attempts to open dialog again', () => { @@ -110,26 +112,29 @@ describe('AssetAccountController', () => { stubbedCommandSubjectNext.mockReset() mockStates(SyncStatus.SyncCompleted, 1, true, true) await assetAccountController.showACPMigrationDialog() - }); + }) it('should not broadcast migrate-acp command', () => { expect(stubbedCommandSubjectNext).not.toHaveBeenCalled() }) - }); + }) describe('force to open dialog again', () => { beforeEach(async () => { stubbedCommandSubjectNext.mockReset() mockStates(SyncStatus.SyncCompleted, 1, true, true) await assetAccountController.showACPMigrationDialog(true) - }); + }) it('broadcast migrate-acp command', () => { expect(stubbedCommandSubjectNext).toHaveBeenCalledWith({ - dispatchToUI: true, payload: "w1", type: "migrate-acp", winID: "1" + dispatchToUI: true, + payload: 'w1', + type: 'migrate-acp', + winID: '1', }) }) - }); - }); + }) + }) describe('when one of the conditions not met', () => { - [ + ;[ [SyncStatus.SyncNotStart, 1, true, true], [SyncStatus.SyncPending, 1, true, true], [SyncStatus.Syncing, 1, true, true], @@ -143,22 +148,24 @@ describe('AssetAccountController', () => { assetAccountController = new AssetAccountController() mockStates(syncStatus, winCount, hasFocusedWindow, hasTx) await assetAccountController.showACPMigrationDialog() - }); + }) it('should not display again in the application session', () => { expect(stubbedCommandSubjectNext).not.toHaveBeenCalled() - }); - }); + }) + }) }) - }); - }); + }) + }) describe('destoryAssetAccount', () => { const params = { walletID: 'walletID', - id: 1 + id: 1, } it('no AssetAccount', async () => { stubbedAssetAccountServiceGetAccount.mockResolvedValueOnce(undefined) - await expect(assetAccountController.destoryAssetAccount(params)).rejects.toThrow(new ServiceHasNoResponse('AssetAccount')) + await expect(assetAccountController.destoryAssetAccount(params)).rejects.toThrow( + new ServiceHasNoResponse('AssetAccount') + ) }) it('excute success', async () => { stubbedAssetAccountServiceGetAccount.mockResolvedValueOnce({}) @@ -167,4 +174,4 @@ describe('AssetAccountController', () => { expect(stubbedAssetAccountServiceDestoryAssetAccount).toHaveBeenCalledWith(params.walletID, {}) }) }) -}); +}) diff --git a/packages/neuron-wallet/tests/controllers/export-debug.test.ts b/packages/neuron-wallet/tests/controllers/export-debug.test.ts index 60458c3ea6..a6839c03f8 100644 --- a/packages/neuron-wallet/tests/controllers/export-debug.test.ts +++ b/packages/neuron-wallet/tests/controllers/export-debug.test.ts @@ -2,14 +2,14 @@ jest.mock('electron', () => ({ dialog: { showSaveDialog: jest.fn(), showMessageBox: jest.fn(), - showErrorBox: jest.fn() + showErrorBox: jest.fn(), }, app: { getVersion: jest.fn().mockReturnValue('mock_version'), getPath: jest.fn().mockReturnValue('mock_path'), - getName: jest.fn().mockReturnValue('mock_name') - } + getName: jest.fn().mockReturnValue('mock_name'), + }, })) jest.mock('../../src/services/addresses', () => { @@ -19,15 +19,15 @@ jest.mock('../../src/services/addresses', () => { walletId: '0', addressType: '0', addressIndex: '0', - blake160: 'hash1' + blake160: 'hash1', }, { walletId: '1', addressType: '1', addressIndex: '1', - blake160: 'hash2' - } - ] + blake160: 'hash2', + }, + ], } }) @@ -36,7 +36,7 @@ jest.mock('fs', () => { createWriteStream: () => null, readFileSync: () => JSON.stringify({}), writeFileSync: () => jest.fn(), - existsSync: () => jest.fn() + existsSync: () => jest.fn(), } }) @@ -44,9 +44,9 @@ jest.mock('../../src/utils/logger', () => ({ error: console.error, transports: { file: { - getFile: jest.fn() - } - } + getFile: jest.fn(), + }, + }, })) jest.mock('../../src/services/networks', () => { @@ -55,11 +55,11 @@ jest.mock('../../src/services/networks', () => { return { getCurrent() { return { - remote: 'http://127.0.0.1:8114' + remote: 'http://127.0.0.1:8114', } - } + }, } - } + }, } }) @@ -67,9 +67,9 @@ jest.mock('../../src/services/settings', () => { return { getInstance() { return { - ckbDataPath: '' + ckbDataPath: '', } - } + }, } }) diff --git a/packages/neuron-wallet/tests/controllers/hardware.test.ts b/packages/neuron-wallet/tests/controllers/hardware.test.ts index 0d6a06eded..4e66ef6d9e 100644 --- a/packages/neuron-wallet/tests/controllers/hardware.test.ts +++ b/packages/neuron-wallet/tests/controllers/hardware.test.ts @@ -23,7 +23,7 @@ describe('hardware controller', () => { try { await hardwareControler.connectDevice({ ...ledgerNanoS, - descriptor: '@throw me a error' + descriptor: '@throw me a error', }) } catch (error) { expect(error).toEqual(new connectDeviceFailed()) @@ -34,26 +34,26 @@ describe('hardware controller', () => { it('#getCkbAppVersion', async () => { const { result } = await hardwareControler.getCkbAppVersion() expect(result).toBe(LedgerCkbApp.version) - }) - - it('#getPublicKey', async () => { - const { result } = await hardwareControler.getPublicKey() - expect(result!.publicKey).toBe(LedgerCkbApp.publicKey) - expect(result!.lockArg).toBe(LedgerCkbApp.lockArg) - expect(result!.address).toBe(LedgerCkbApp.address) - }) - - it('#getExtendedPublicKey', async () => { - const { result } = await hardwareControler.getExtendedPublicKey() - expect(result!.publicKey).toBe(LedgerCkbApp.publicKey) - expect(result!.chainCode).toBe(LedgerCkbApp.chainCode) - }) - - it('#detectDevice', async () => { + }) + + it('#getPublicKey', async () => { + const { result } = await hardwareControler.getPublicKey() + expect(result!.publicKey).toBe(LedgerCkbApp.publicKey) + expect(result!.lockArg).toBe(LedgerCkbApp.lockArg) + expect(result!.address).toBe(LedgerCkbApp.address) + }) + + it('#getExtendedPublicKey', async () => { + const { result } = await hardwareControler.getExtendedPublicKey() + expect(result!.publicKey).toBe(LedgerCkbApp.publicKey) + expect(result!.chainCode).toBe(LedgerCkbApp.chainCode) + }) + + it('#detectDevice', async () => { const { result } = await hardwareControler.detectDevice({ manufacturer: Manufacturer.Ledger, - product: 'Nano S' + product: 'Nano S', }) expect(result).toEqual([ledgerNanoS]) - }) + }) }) diff --git a/packages/neuron-wallet/tests/controllers/multisig.test.ts b/packages/neuron-wallet/tests/controllers/multisig.test.ts index 6a135ee333..fbc830c0dc 100644 --- a/packages/neuron-wallet/tests/controllers/multisig.test.ts +++ b/packages/neuron-wallet/tests/controllers/multisig.test.ts @@ -12,11 +12,11 @@ jest.mock('electron', () => ({ showMessageBox: jest.fn().mockImplementation(() => ({ response })), showOpenDialog: jest.fn().mockImplementation(() => dialogRes), showSaveDialog: jest.fn().mockImplementation(() => dialogRes), - showErrorBox: () => showErrorBoxMock() + showErrorBox: () => showErrorBoxMock(), }, BrowserWindow: { - getFocusedWindow: jest.fn() - } + getFocusedWindow: jest.fn(), + }, })) jest.mock('../../src/services/multisig') @@ -27,7 +27,7 @@ jest.mock('fs', () => { return { readFileSync: () => readFileSyncMock(), writeFileSync: () => jest.fn(), - existsSync: () => jest.fn() + existsSync: () => jest.fn(), } }) @@ -35,9 +35,9 @@ jest.mock('../../src/utils/logger', () => ({ error: console.error, transports: { file: { - getFile: jest.fn() - } - } + getFile: jest.fn(), + }, + }, })) jest.mock('../../src/services/cells', () => ({ @@ -48,52 +48,62 @@ const isMainnetMock = jest.fn().mockReturnValue(false) jest.mock('../../src/services/networks', () => ({ getInstance: () => ({ - isMainnet: () => isMainnetMock() - }) + isMainnet: () => isMainnetMock(), + }), })) const loadTransactionJSONMock = jest.fn() jest.mock('../../src/services/offline-sign', () => ({ - loadTransactionJSON: () => loadTransactionJSONMock() + loadTransactionJSON: () => loadTransactionJSONMock(), })) const multisigArgs = '0x40518821915b81de0614d8c45dbef77151a22ad1' const multisigBlake160s = [ '0xcdef55dcb787257236bbe8d8c338951b4290ca69', '0x3403fcbbd9e20fa31e722eb9981b2203ad475904', - '0xc75e25d1a08c03617fd7211607a0a7479ad2ec31' + '0xc75e25d1a08c03617fd7211607a0a7479ad2ec31', ] const multisigConfig = { testnet: { params: { multisig_configs: { - sighash_addresses: multisigBlake160s.map(args => scriptToAddress({ - args, - codeHash: systemScripts.SECP256K1_BLAKE160.codeHash, - hashType: systemScripts.SECP256K1_BLAKE160.hashType - }, false)), + sighash_addresses: multisigBlake160s.map(args => + scriptToAddress( + { + args, + codeHash: systemScripts.SECP256K1_BLAKE160.codeHash, + hashType: systemScripts.SECP256K1_BLAKE160.hashType, + }, + false + ) + ), require_first_n: 1, - threshold: 2 + threshold: 2, }, - isMainnet: false + isMainnet: false, }, - result: 'ckt1qpw9q60tppt7l3j7r09qcp7lxnp3vcanvgha8pmvsa3jplykxn32sq2q2xyzry2ms80qv9xcc3wmaam32x3z45gut5d40' + result: 'ckt1qpw9q60tppt7l3j7r09qcp7lxnp3vcanvgha8pmvsa3jplykxn32sq2q2xyzry2ms80qv9xcc3wmaam32x3z45gut5d40', }, mainnet: { params: { multisig_configs: { - sighash_addresses: multisigBlake160s.map(args => scriptToAddress({ - args, - codeHash: systemScripts.SECP256K1_BLAKE160.codeHash, - hashType: systemScripts.SECP256K1_BLAKE160.hashType - }, true)), + sighash_addresses: multisigBlake160s.map(args => + scriptToAddress( + { + args, + codeHash: systemScripts.SECP256K1_BLAKE160.codeHash, + hashType: systemScripts.SECP256K1_BLAKE160.hashType, + }, + true + ) + ), require_first_n: 1, - threshold: 2 + threshold: 2, }, - isMainnet: true + isMainnet: true, }, - result: 'ckb1qpw9q60tppt7l3j7r09qcp7lxnp3vcanvgha8pmvsa3jplykxn32sq2q2xyzry2ms80qv9xcc3wmaam32x3z45gjelzlh' - } + result: 'ckb1qpw9q60tppt7l3j7r09qcp7lxnp3vcanvgha8pmvsa3jplykxn32sq2q2xyzry2ms80qv9xcc3wmaam32x3z45gjelzlh', + }, } describe('test for multisig controller', () => { @@ -111,7 +121,7 @@ describe('test for multisig controller', () => { n: 1, blake160s: [], alias: 'string', - changed: expect.any(Function) + changed: expect.any(Function), } await multisigController.saveConfig(params) expect(MultiSigServiceMock.prototype.saveMultisigConfig).toHaveBeenCalledWith(params) @@ -120,7 +130,7 @@ describe('test for multisig controller', () => { it('test update config', async () => { const params = { id: 1, - alias: '2' + alias: '2', } await multisigController.updateConfig(params) expect(MultiSigServiceMock.prototype.updateMultisigConfig).toHaveBeenCalledWith(params) @@ -159,126 +169,144 @@ describe('test for multisig controller', () => { await multisigController.importConfig('1234') expect(showErrorBoxMock).toHaveBeenCalledWith() }), - it('multisig_configs is empty', async () => { - readFileSyncMock.mockReturnValue(JSON.stringify({ multisig_configs: {} })) - await multisigController.importConfig('1234') - expect(showErrorBoxMock).toHaveBeenCalledWith() - }), - it('import data is error no require_first_n', async () => { - readFileSyncMock.mockReturnValue(JSON.stringify({ - multisig_configs: { - [multisigArgs]: { - ...multisigConfig.testnet.params.multisig_configs, - require_first_n: undefined - } - } - })) - const res = await multisigController.importConfig('1234') - expect(res).toBeUndefined() - expect(showErrorBoxMock).toHaveBeenCalledWith() - }) + it('multisig_configs is empty', async () => { + readFileSyncMock.mockReturnValue(JSON.stringify({ multisig_configs: {} })) + await multisigController.importConfig('1234') + expect(showErrorBoxMock).toHaveBeenCalledWith() + }), + it('import data is error no require_first_n', async () => { + readFileSyncMock.mockReturnValue( + JSON.stringify({ + multisig_configs: { + [multisigArgs]: { + ...multisigConfig.testnet.params.multisig_configs, + require_first_n: undefined, + }, + }, + }) + ) + const res = await multisigController.importConfig('1234') + expect(res).toBeUndefined() + expect(showErrorBoxMock).toHaveBeenCalledWith() + }) it('import data is error no threshold', async () => { - readFileSyncMock.mockReturnValue(JSON.stringify({ - multisig_configs: { - [multisigArgs]: { - ...multisigConfig.testnet.params.multisig_configs, - threshold: undefined - } - } - })) + readFileSyncMock.mockReturnValue( + JSON.stringify({ + multisig_configs: { + [multisigArgs]: { + ...multisigConfig.testnet.params.multisig_configs, + threshold: undefined, + }, + }, + }) + ) const res = await multisigController.importConfig('1234') expect(res).toBeUndefined() expect(showErrorBoxMock).toHaveBeenCalledWith() }) it('import data is error require_first_n is not number', async () => { - readFileSyncMock.mockReturnValue(JSON.stringify({ - multisig_configs: { - [multisigArgs]: { - ...multisigConfig.testnet.params.multisig_configs, - require_first_n: 'dd' - } - } - })) + readFileSyncMock.mockReturnValue( + JSON.stringify({ + multisig_configs: { + [multisigArgs]: { + ...multisigConfig.testnet.params.multisig_configs, + require_first_n: 'dd', + }, + }, + }) + ) const res = await multisigController.importConfig('1234') expect(res).toBeUndefined() expect(showErrorBoxMock).toHaveBeenCalledWith() }) it('import data is error threshold is not number', async () => { - readFileSyncMock.mockReturnValue(JSON.stringify({ - multisig_configs: { - [multisigArgs]: { - ...multisigConfig.testnet.params.multisig_configs, - threshold: 'undefined' - } - } - })) + readFileSyncMock.mockReturnValue( + JSON.stringify({ + multisig_configs: { + [multisigArgs]: { + ...multisigConfig.testnet.params.multisig_configs, + threshold: 'undefined', + }, + }, + }) + ) const res = await multisigController.importConfig('1234') expect(res).toBeUndefined() expect(showErrorBoxMock).toHaveBeenCalledWith() }) it('import data is invalidation r > n', async () => { - readFileSyncMock.mockReturnValue(JSON.stringify({ - multisig_configs: { - [multisigArgs]: { - ...multisigConfig.testnet.params.multisig_configs, - require_first_n: 4 - } - } - })) + readFileSyncMock.mockReturnValue( + JSON.stringify({ + multisig_configs: { + [multisigArgs]: { + ...multisigConfig.testnet.params.multisig_configs, + require_first_n: 4, + }, + }, + }) + ) const res = await multisigController.importConfig('1234') expect(res).toBeUndefined() expect(showErrorBoxMock).toHaveBeenCalledWith() }) it('import data is invalidation m > n', async () => { - readFileSyncMock.mockReturnValue(JSON.stringify({ - multisig_configs: { - [multisigArgs]: { - ...multisigConfig.testnet.params.multisig_configs, - threshold: 4 - } - } - })) + readFileSyncMock.mockReturnValue( + JSON.stringify({ + multisig_configs: { + [multisigArgs]: { + ...multisigConfig.testnet.params.multisig_configs, + threshold: 4, + }, + }, + }) + ) const res = await multisigController.importConfig('1234') expect(res).toBeUndefined() expect(showErrorBoxMock).toHaveBeenCalledWith() }) it('import data is invalidation blake160s empty', async () => { - readFileSyncMock.mockReturnValue(JSON.stringify({ - multisig_configs: { - [multisigArgs]: { - ...multisigConfig.testnet.params.multisig_configs, - sighash_addresses: [] - } - } - })) + readFileSyncMock.mockReturnValue( + JSON.stringify({ + multisig_configs: { + [multisigArgs]: { + ...multisigConfig.testnet.params.multisig_configs, + sighash_addresses: [], + }, + }, + }) + ) const res = await multisigController.importConfig('1234') expect(res).toBeUndefined() expect(showErrorBoxMock).toHaveBeenCalledWith() }) it('import data is invalidation blake160 length not 42', async () => { - readFileSyncMock.mockReturnValue(JSON.stringify({ - multisig_configs: { - [multisigArgs]: { - ...multisigConfig.testnet.params.multisig_configs, - sighash_addresses: [multisigConfig.testnet.params.multisig_configs.sighash_addresses[0]] - } - } - })) + readFileSyncMock.mockReturnValue( + JSON.stringify({ + multisig_configs: { + [multisigArgs]: { + ...multisigConfig.testnet.params.multisig_configs, + sighash_addresses: [multisigConfig.testnet.params.multisig_configs.sighash_addresses[0]], + }, + }, + }) + ) const res = await multisigController.importConfig('1234') expect(res).toBeUndefined() expect(showErrorBoxMock).toHaveBeenCalledWith() }) it('import object success', async () => { - readFileSyncMock.mockReturnValue(JSON.stringify({ - multisig_configs: { - [multisigArgs]: multisigConfig.testnet.params.multisig_configs - } - })) + readFileSyncMock.mockReturnValue( + JSON.stringify({ + multisig_configs: { + [multisigArgs]: multisigConfig.testnet.params.multisig_configs, + }, + }) + ) MultiSigServiceMock.prototype.saveMultisigConfig.mockResolvedValueOnce({ blake160s: multisigBlake160s, id: 1, walletId: '1234', - alias: '' + alias: '', } as any) const res = await multisigController.importConfig('1234') expect(res?.result[0].blake160s).toBe(multisigBlake160s) @@ -302,9 +330,10 @@ describe('test for multisig controller', () => { expect(CellsService.getMultisigBalances).toHaveBeenCalled() expect(res.status).toBe(ResponseCode.Success) }) - + describe('loadMultisigTxJson', () => { - const fullPayload = 'ckt1qpw9q60tppt7l3j7r09qcp7lxnp3vcanvgha8pmvsa3jplykxn32sq2yu88cl4mwf0jc05q38gu237qd753c4jcan9jch' + const fullPayload = + 'ckt1qpw9q60tppt7l3j7r09qcp7lxnp3vcanvgha8pmvsa3jplykxn32sq2yu88cl4mwf0jc05q38gu237qd753c4jcan9jch' const lockHash = '0xd121829f9c355496ab54c8b570dd7b0d0f4958dcba6967c241a0ca49a55a8e38' it('load failed', async () => { loadTransactionJSONMock.mockResolvedValueOnce(undefined) @@ -315,14 +344,14 @@ describe('test for multisig controller', () => { it('fullpayload not matched', async () => { loadTransactionJSONMock.mockResolvedValueOnce({ json: { - transaction: { - inputs: [ - { lockHash } - ] - } - } + transaction: { + inputs: [{ lockHash }], + }, + }, }) - const res = await multisigController.loadMultisigTxJson('ckt1qpw9q60tppt7l3j7r09qcp7lxnp3vcanvgha8pmvsa3jplykxn32sqdr04fsz70xn6kl7c54cj0ap93qlvf0cacdhulch') + const res = await multisigController.loadMultisigTxJson( + 'ckt1qpw9q60tppt7l3j7r09qcp7lxnp3vcanvgha8pmvsa3jplykxn32sqdr04fsz70xn6kl7c54cj0ap93qlvf0cacdhulch' + ) expect(res.status).toBe(ResponseCode.Fail) }) @@ -330,14 +359,12 @@ describe('test for multisig controller', () => { loadTransactionJSONMock.mockResolvedValueOnce({ json: { transaction: { - inputs: [ - { lockHash } - ] - } - } + inputs: [{ lockHash }], + }, + }, }) const res = await multisigController.loadMultisigTxJson(fullPayload) expect(res.status).toBe(ResponseCode.Success) }) }) -}) \ No newline at end of file +}) diff --git a/packages/neuron-wallet/tests/controllers/offline-sign.test.ts b/packages/neuron-wallet/tests/controllers/offline-sign.test.ts index fa110c9a91..6cee3aabdc 100644 --- a/packages/neuron-wallet/tests/controllers/offline-sign.test.ts +++ b/packages/neuron-wallet/tests/controllers/offline-sign.test.ts @@ -27,103 +27,98 @@ function resetMocks() { signMultisigMock.mockReset() } - describe('OfflineSignController', () => { let offlineSignController: OfflineSignController const mockTransaction = { - "cellDeps": [ + cellDeps: [ { - "outPoint": { - "txHash": "0xf8de3bb47d055cdf460d93a2a6e1b05f7432f9777c8c474abf4eec1d4aee5d37", - "index": "0" + outPoint: { + txHash: '0xf8de3bb47d055cdf460d93a2a6e1b05f7432f9777c8c474abf4eec1d4aee5d37', + index: '0', }, - "depType": "depGroup" + depType: 'depGroup', }, { - "outPoint": { - "txHash": "0xc1b2ae129fad7465aaa9acc9785f842ba3e6e8b8051d899defa89f5508a77958", - "index": "0" + outPoint: { + txHash: '0xc1b2ae129fad7465aaa9acc9785f842ba3e6e8b8051d899defa89f5508a77958', + index: '0', }, - "depType": "code" + depType: 'code', }, { - "outPoint": { - "txHash": "0x4f32b3e39bd1b6350d326fdfafdfe05e5221865c3098ae323096f0bfc69e0a8c", - "index": "0" + outPoint: { + txHash: '0x4f32b3e39bd1b6350d326fdfafdfe05e5221865c3098ae323096f0bfc69e0a8c', + index: '0', }, - "depType": "depGroup" - } + depType: 'depGroup', + }, ], - "headerDeps": [], - "inputs": [], - "outputs": [ + headerDeps: [], + inputs: [], + outputs: [ { - "capacity": "14200000000", - "lock": { - "args": "0x8830a6e1db602cf8d37f5fd825c6a11c1ccd53a9", - "codeHash": "0x86a1c6987a4acbe1a887cca4c9dd2ac9fcb07405bbeda51b861b18bbf7492c4b", - "hashType": "type" + capacity: '14200000000', + lock: { + args: '0x8830a6e1db602cf8d37f5fd825c6a11c1ccd53a9', + codeHash: '0x86a1c6987a4acbe1a887cca4c9dd2ac9fcb07405bbeda51b861b18bbf7492c4b', + hashType: 'type', }, - "type": { - "args": "0xb58a6fa6f2c57ed45fbdfc7fcebd5c79575590ecf190b72fa6e6a767d57cb105", - "codeHash": "0x48dbf59b4c7ee1547238021b4869bceedf4eea6b43772e5d66ef8865b6ae7212", - "hashType": "data" + type: { + args: '0xb58a6fa6f2c57ed45fbdfc7fcebd5c79575590ecf190b72fa6e6a767d57cb105', + codeHash: '0x48dbf59b4c7ee1547238021b4869bceedf4eea6b43772e5d66ef8865b6ae7212', + hashType: 'data', }, - "lockHash": "0xe3f6ab9a880a87ea44b10ebb6d70bac1e08ac7dfb36b754d68d15d986cf54823", - "typeHash": "0x7be5dd445f388c5f58b06b90cec6db09f70e47e2c6fc9c7547f2826066ba25e3", - "data": "0x2c420f00000000000000000000000000" + lockHash: '0xe3f6ab9a880a87ea44b10ebb6d70bac1e08ac7dfb36b754d68d15d986cf54823', + typeHash: '0x7be5dd445f388c5f58b06b90cec6db09f70e47e2c6fc9c7547f2826066ba25e3', + data: '0x2c420f00000000000000000000000000', }, { - "capacity": "14200000000", - "lock": { - "args": "0x913c4f626f96b01c039a650819b0fb718ef5ad42", - "codeHash": "0x86a1c6987a4acbe1a887cca4c9dd2ac9fcb07405bbeda51b861b18bbf7492c4b", - "hashType": "type" + capacity: '14200000000', + lock: { + args: '0x913c4f626f96b01c039a650819b0fb718ef5ad42', + codeHash: '0x86a1c6987a4acbe1a887cca4c9dd2ac9fcb07405bbeda51b861b18bbf7492c4b', + hashType: 'type', }, - "type": { - "args": "0xb58a6fa6f2c57ed45fbdfc7fcebd5c79575590ecf190b72fa6e6a767d57cb105", - "codeHash": "0x48dbf59b4c7ee1547238021b4869bceedf4eea6b43772e5d66ef8865b6ae7212", - "hashType": "data" + type: { + args: '0xb58a6fa6f2c57ed45fbdfc7fcebd5c79575590ecf190b72fa6e6a767d57cb105', + codeHash: '0x48dbf59b4c7ee1547238021b4869bceedf4eea6b43772e5d66ef8865b6ae7212', + hashType: 'data', }, - "lockHash": "0x1a729562de95cf74255da6d4a0fcf173b6d7d293452903a7290b4c0122fdd2a6", - "typeHash": "0x7be5dd445f388c5f58b06b90cec6db09f70e47e2c6fc9c7547f2826066ba25e3", - "outPoint": { - "txHash": "0x156ac1ddf502f121790ba316889dfb89f2c4b99f37b1af3afadc121187f87070", - "index": "1" + lockHash: '0x1a729562de95cf74255da6d4a0fcf173b6d7d293452903a7290b4c0122fdd2a6', + typeHash: '0x7be5dd445f388c5f58b06b90cec6db09f70e47e2c6fc9c7547f2826066ba25e3', + outPoint: { + txHash: '0x156ac1ddf502f121790ba316889dfb89f2c4b99f37b1af3afadc121187f87070', + index: '1', }, - "data": "0x94841e00000000000000000000000000" + data: '0x94841e00000000000000000000000000', }, { - "capacity": "19999998970", - "lock": { - "args": "0x8830a6e1db602cf8d37f5fd825c6a11c1ccd53a9", - "codeHash": "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8", - "hashType": "type" + capacity: '19999998970', + lock: { + args: '0x8830a6e1db602cf8d37f5fd825c6a11c1ccd53a9', + codeHash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8', + hashType: 'type', }, - "lockHash": "0x0986ec9d96d5bfc7a98c9f064c684e09d9afad4952f720a7e47cda73a1389c1c", - "data": "0x" - } - ], - "witnesses": [], - "description": "", - "nervosDao": false, - "hash": "0x0213376e870aed74969a3f64d1e71eba88e9c0185d371e0f1ad5e6319a3fdaf4", - "version": "0", - "fee": "1030", - "outputsData": [ - "0x2c420f00000000000000000000000000", - "0x94841e00000000000000000000000000", - "0x" + lockHash: '0x0986ec9d96d5bfc7a98c9f064c684e09d9afad4952f720a7e47cda73a1389c1c', + data: '0x', + }, ], - "sudtInfo": { - "amount": "20" - } + witnesses: [], + description: '', + nervosDao: false, + hash: '0x0213376e870aed74969a3f64d1e71eba88e9c0185d371e0f1ad5e6319a3fdaf4', + version: '0', + fee: '1030', + outputsData: ['0x2c420f00000000000000000000000000', '0x94841e00000000000000000000000000', '0x'], + sudtInfo: { + amount: '20', + }, } const mockTxInstance = { toSDKRawTransaction() { return mockTransaction - } + }, } beforeEach(() => { @@ -134,14 +129,14 @@ describe('OfflineSignController', () => { dialog: { showSaveDialog: stubbedElectronShowSaveDialog, showErrorBox: stubbedElectronShowErrorBox, - showMessageBox: stubbedElectronShowMessageBox - } + showMessageBox: stubbedElectronShowMessageBox, + }, } }) jest.doMock('fs', () => { return { - writeFileSync: jest.fn() + writeFileSync: jest.fn(), } }) @@ -160,50 +155,42 @@ describe('OfflineSignController', () => { ckb: { rpc: { paramsFormatter: { - toRawTransaction: (tx: any) => tx - } - } - } + toRawTransaction: (tx: any) => tx, + }, + }, + }, } } } }) jest.doMock('services/transaction-sender', () => { - return jest.fn().mockImplementation( - () => ({ - sign: stubbedTransactionSenderSign, - signMultisig: signMultisigMock - }) - ) + return jest.fn().mockImplementation(() => ({ + sign: stubbedTransactionSenderSign, + signMultisig: signMultisigMock, + })) }) jest.doMock('../../src/controllers/asset-account', () => { - return jest.fn().mockImplementation( - () => ({ - sendCreateTx: stubbedAssetAccountControllerSend - }) - ) + return jest.fn().mockImplementation(() => ({ + sendCreateTx: stubbedAssetAccountControllerSend, + })) }) jest.doMock('../../src/controllers/anyone-can-pay', () => { - return jest.fn().mockImplementation( - () => ({ - sendTx: stubbedAnyoneCanPayControllerSend - }) - ) + return jest.fn().mockImplementation(() => ({ + sendTx: stubbedAnyoneCanPayControllerSend, + })) }) jest.doMock('../../src/controllers/wallets', () => { - return jest.fn().mockImplementation( - () => ({ - sendTx: stubbedWalletsControllerSend - }) - ) + return jest.fn().mockImplementation(() => ({ + sendTx: stubbedWalletsControllerSend, + })) }) jest.doMock('../../src/utils/multisig', () => ({ - getMultisigStatus: getMultisigStatusMock + getMultisigStatus: getMultisigStatusMock, })) const OfflineSignController = require('../../src/controllers/offline-sign').default @@ -222,23 +209,23 @@ describe('OfflineSignController', () => { it('if user cancel', async () => { stubbedElectronShowSaveDialog.mockReturnValue({ - canceled: true + canceled: true, }) const res = await offlineSignController.exportTransactionAsJSON({} as any) expect(res).toEqual({ - status: ResponseCode.Success + status: ResponseCode.Success, }) }) it('if file path is not provider', async () => { stubbedElectronShowSaveDialog.mockReturnValue({ - canceled: false + canceled: false, }) const res = await offlineSignController.exportTransactionAsJSON({} as any) expect(res).toEqual({ - status: ResponseCode.Success + status: ResponseCode.Success, }) }) }) @@ -285,7 +272,7 @@ describe('OfflineSignController', () => { transaction: mockTransaction, status: SignStatus.Unsigned, type: SignType.Regular, - context: [] + context: [], }) }) }) @@ -302,7 +289,7 @@ describe('OfflineSignController', () => { stubbedElectronShowSaveDialog.mockReturnValue({ canceled: false, - filePath: 'filePath.json' + filePath: 'filePath.json', }) }) @@ -311,11 +298,13 @@ describe('OfflineSignController', () => { throw new connectDeviceFailed() }) - expect(offlineSignController.signTransaction({ - transaction: mockTransaction, - status: SignStatus.Unsigned, - type: SignType.Regular, - } as any)).rejects.toThrowError(new connectDeviceFailed()) + expect( + offlineSignController.signTransaction({ + transaction: mockTransaction, + status: SignStatus.Unsigned, + type: SignType.Regular, + } as any) + ).rejects.toThrowError(new connectDeviceFailed()) }) it('throws OfflineSignFailed error if error code is not provide', () => { @@ -323,11 +312,13 @@ describe('OfflineSignController', () => { throw new Error('') }) - expect(offlineSignController.signTransaction({ - transaction: mockTransaction, - status: SignStatus.Unsigned, - type: SignType.Regular, - } as any)).rejects.toThrowError(new OfflineSignFailed()) + expect( + offlineSignController.signTransaction({ + transaction: mockTransaction, + status: SignStatus.Unsigned, + type: SignType.Regular, + } as any) + ).rejects.toThrowError(new OfflineSignFailed()) }) }) @@ -337,7 +328,7 @@ describe('OfflineSignController', () => { stubbedElectronShowSaveDialog.mockReturnValue({ canceled: false, - filePath: 'filePath.json' + filePath: 'filePath.json', }) stubbedTransactionSenderSign.mockReturnValue(mockTransaction) @@ -388,15 +379,9 @@ describe('OfflineSignController', () => { transaction: mockTransaction, status: SignStatus.Unsigned, type: SignType.SendSUDT, - multisigConfig: {} + multisigConfig: {}, } as any) - expect(signMultisigMock).toHaveBeenCalledWith( - undefined, - mockTxInstance, - undefined, - [{}], - undefined - ) + expect(signMultisigMock).toHaveBeenCalledWith(undefined, mockTxInstance, undefined, [{}], undefined) expect(res.result.status).toBe(SignStatus.PartiallySigned) }) }) @@ -409,7 +394,7 @@ describe('OfflineSignController', () => { stubbedElectronShowSaveDialog.mockReturnValue({ canceled: false, - filePath: 'filePath.json' + filePath: 'filePath.json', }) stubbedTransactionSenderSign.mockReturnValue(mockTransaction) @@ -489,11 +474,17 @@ describe('OfflineSignController', () => { }) it('throw exception', async () => { getMultisigStatusMock.mockReturnValueOnce(SignStatus.PartiallySigned) - await expect(offlineSignController.signAndBroadcastTransaction({ transaction: mockTransaction, multisigConfig: {}} as any)).rejects.toThrow(new MultisigNotSignedNeedError()) + await expect( + offlineSignController.signAndBroadcastTransaction({ transaction: mockTransaction, multisigConfig: {} } as any) + ).rejects.toThrow(new MultisigNotSignedNeedError()) }) it('success', async () => { getMultisigStatusMock.mockReturnValueOnce(SignStatus.Signed) - await offlineSignController.signAndBroadcastTransaction({ transaction: mockTransaction, multisigConfig: {}, type: SignType.CreateSUDTAccount } as any) + await offlineSignController.signAndBroadcastTransaction({ + transaction: mockTransaction, + multisigConfig: {}, + type: SignType.CreateSUDTAccount, + } as any) expect(stubbedAssetAccountControllerSend).toHaveBeenCalled() }) }) diff --git a/packages/neuron-wallet/tests/controllers/sudt.test.ts b/packages/neuron-wallet/tests/controllers/sudt.test.ts index c24a1f232f..44ab0f3347 100644 --- a/packages/neuron-wallet/tests/controllers/sudt.test.ts +++ b/packages/neuron-wallet/tests/controllers/sudt.test.ts @@ -1,6 +1,6 @@ -import LiveCell from "../../src/models/chain/live-cell"; -import Script, { ScriptHashType } from "../../src/models/chain/script"; -import {ResponseCode} from "../../src/utils/const"; +import LiveCell from '../../src/models/chain/live-cell' +import Script, { ScriptHashType } from '../../src/models/chain/script' +import { ResponseCode } from '../../src/utils/const' describe('SUDTController', () => { const stubbedGetOneByLockScriptAndTypeScript = jest.fn() @@ -23,7 +23,7 @@ describe('SUDTController', () => { getTokenInfoList: stubbedGetTokenInfoList, } }) - const SUDTController = require("../../src/controllers/sudt").default + const SUDTController = require('../../src/controllers/sudt').default beforeEach(async () => { resetMocks() @@ -43,7 +43,7 @@ describe('SUDTController', () => { it('getSUDTTokenInfo from token list success', async () => { const sudtController = new SUDTController() - const tokenInfo = await sudtController.getSUDTTokenInfo({tokenID:testTokenID}) + const tokenInfo = await sudtController.getSUDTTokenInfo({ tokenID: testTokenID }) expect(tokenInfo).toEqual({ status: ResponseCode.Success, result: testTokenInfo, @@ -59,10 +59,14 @@ describe('SUDTController', () => { symbol: 'ET2', decimal: '8', } - const testLiveCell = new LiveCell('txHash', '0', '10000', - Script.fromObject({codeHash:'',args:'',hashType:ScriptHashType.Type}), - Script.fromObject({codeHash:'',args:'',hashType:ScriptHashType.Type}), - '0x080a456972632d320a455432') + const testLiveCell = new LiveCell( + 'txHash', + '0', + '10000', + Script.fromObject({ codeHash: '', args: '', hashType: ScriptHashType.Type }), + Script.fromObject({ codeHash: '', args: '', hashType: ScriptHashType.Type }), + '0x080a456972632d320a455432' + ) beforeEach(async () => { stubbedGetTokenInfoList.mockReturnValue([]) stubbedGetOneByLockScriptAndTypeScript.mockReturnValue(testLiveCell) @@ -70,7 +74,7 @@ describe('SUDTController', () => { it('getSUDTTokenInfo from live cell data parse', async () => { const sudtController = new SUDTController() - const tokenInfo = await sudtController.getSUDTTokenInfo({tokenID:testTokenID}) + const tokenInfo = await sudtController.getSUDTTokenInfo({ tokenID: testTokenID }) expect(tokenInfo).toEqual({ status: ResponseCode.Success, result: testTokenInfo, @@ -85,7 +89,7 @@ describe('SUDTController', () => { }) it('getSUDTTokenInfo from live cell data parse', async () => { const sudtController = new SUDTController() - const tokenInfo = await sudtController.getSUDTTokenInfo({tokenID:testTokenID}) + const tokenInfo = await sudtController.getSUDTTokenInfo({ tokenID: testTokenID }) expect(tokenInfo).toEqual({ status: ResponseCode.Fail, }) diff --git a/packages/neuron-wallet/tests/controllers/sync-api.test.ts b/packages/neuron-wallet/tests/controllers/sync-api.test.ts index ca5d268b5c..69ec939811 100644 --- a/packages/neuron-wallet/tests/controllers/sync-api.test.ts +++ b/packages/neuron-wallet/tests/controllers/sync-api.test.ts @@ -36,16 +36,16 @@ jest.doMock('models/subjects/networks', () => { pipe: () => ({ subscribe: (callback: any) => { networkChangedCallback = callback - } - }) - } + }, + }), + }, } }) jest.doMock('services/ckb-runner', () => ({ - getLookingValidTargetStatus: jest.fn() + getLookingValidTargetStatus: jest.fn(), })) jest.mock('undici', () => ({ - request: () => jest.fn()() + request: () => jest.fn()(), })) describe('SyncApiController', () => { @@ -82,20 +82,20 @@ describe('SyncApiController', () => { }) jest.doMock('services/node', () => { return { - getInstance: stubbedNodeGetInstance + getInstance: stubbedNodeGetInstance, } }) jest.doMock('services/networks', () => { return { getInstance: () => ({ - getCurrent: () => ({ remote: '' }) - }) + getCurrent: () => ({ remote: '' }), + }), } }) jest.doMock('../../src/models/subjects/node', () => { return { - getLatestConnectionStatus: stubbedGetLatestConnectionStatus + getLatestConnectionStatus: stubbedGetLatestConnectionStatus, } }) jest.doMock('../../src/services/rpc-service', () => { @@ -103,8 +103,8 @@ describe('SyncApiController', () => { __esModule: true, default: stubbedRpcServiceConstructor.mockImplementation(() => ({ getTipHeader: stubbedGetTipHeader, - getSyncState: stubbedGetSyncState - })) + getSyncState: stubbedGetSyncState, + })), } }) @@ -129,14 +129,14 @@ describe('SyncApiController', () => { stubbedDateNow.mockReturnValue(246000) stubbedGetSyncState.mockResolvedValue({ bestKnownBlockNumber: bestKnownBlockNumber.toString(16), - bestKnownBlockTimestamp: `0x${bestKnownBlockTimestamp.toString(16)}` + bestKnownBlockTimestamp: `0x${bestKnownBlockTimestamp.toString(16)}`, }) stubbedNodeGetInstance.mockReturnValue({ ckb: { node: { - url: fakeNodeUrl - } - } + url: fakeNodeUrl, + }, + }, }) stubbedGetTipHeader.mockResolvedValue({ timestamp: '180000' }) }) @@ -146,12 +146,12 @@ describe('SyncApiController', () => { const fakeState1 = { cacheTipNumber, indexerTipNumber: bestKnownBlockNumber.toString(), - timestamp: '186000' + timestamp: '186000', } const fakeState2 = { cacheTipNumber, indexerTipNumber: bestKnownBlockNumber.toString(), - timestamp: '187000' + timestamp: '187000', } beforeEach(async () => { await sendFakeCacheBlockTipEvent(fakeState1) @@ -168,7 +168,7 @@ describe('SyncApiController', () => { indexRate: undefined, cacheRate: undefined, estimate: undefined, - status: 3 + status: 3, }) }) it('#getSyncStatus returns synced', async () => { @@ -185,12 +185,12 @@ describe('SyncApiController', () => { const fakeState1 = { cacheTipNumber, indexerTipNumber: bestKnownBlockNumber.toString(), - timestamp: '186000' + timestamp: '186000', } const fakeState2 = { cacheTipNumber, indexerTipNumber: bestKnownBlockNumber.toString(), - timestamp: '187000' + timestamp: '187000', } beforeEach(async () => { await sendFakeCacheBlockTipEvent(fakeState1) @@ -208,7 +208,7 @@ describe('SyncApiController', () => { indexRate: undefined, cacheRate: undefined, estimate: undefined, - status: 2 + status: 2, }) }) it('#getSyncStatus returns syncing', async () => { @@ -222,12 +222,12 @@ describe('SyncApiController', () => { const fakeState1 = { cacheTipNumber, indexerTipNumber: bestKnownBlockNumber.toString(), - timestamp: '606000' + timestamp: '606000', } const fakeState2 = { cacheTipNumber, indexerTipNumber: bestKnownBlockNumber.toString(), - timestamp: '607000' + timestamp: '607000', } beforeEach(async () => { await sendFakeCacheBlockTipEvent(fakeState1) @@ -245,7 +245,7 @@ describe('SyncApiController', () => { indexRate: undefined, cacheRate: undefined, estimate: undefined, - status: 1 + status: 1, }) }) it('#getSyncStatus returns sync pending', async () => { @@ -260,7 +260,7 @@ describe('SyncApiController', () => { const fakeState1 = { cacheTipNumber, indexerTipNumber: bestKnownBlockNumber.toString(), - timestamp: '186000' + timestamp: '186000', } beforeEach(async () => { await sendFakeCacheBlockTipEvent(fakeState1) @@ -276,7 +276,7 @@ describe('SyncApiController', () => { indexRate: undefined, cacheRate: undefined, estimate: undefined, - status: 2 + status: 2, }) }) it('stores next block number', () => { @@ -291,12 +291,12 @@ describe('SyncApiController', () => { const fakeState1 = { cacheTipNumber, indexerTipNumber: (bestKnownBlockNumber - 102).toString(), - timestamp: '186000' + timestamp: '186000', } const fakeState2 = { cacheTipNumber, indexerTipNumber: (bestKnownBlockNumber - 51).toString(), - timestamp: '187000' + timestamp: '187000', } const indexRate = 51 / (parseInt(fakeState2.timestamp) - parseInt(fakeState1.timestamp)) const expectedEstimation = { @@ -309,7 +309,7 @@ describe('SyncApiController', () => { indexRate, cacheRate: undefined, estimate: Math.round((bestKnownBlockNumber - parseInt(fakeState2.indexerTipNumber)) / indexRate), - status: 2 + status: 2, } beforeEach(async () => { await sendFakeCacheBlockTipEvent(fakeState1) @@ -330,7 +330,7 @@ describe('SyncApiController', () => { const newFakeState = { ...fakeState2, cacheTipNumber: (Number(fakeState2.cacheTipNumber) + 1).toString(), - timestamp: '196000' + timestamp: '196000', } beforeEach(() => { cachedEstimate = controller.getCachedEstimation() @@ -360,9 +360,9 @@ describe('SyncApiController', () => { stubbedNodeGetInstance.mockReturnValue({ ckb: { node: { - url: 'anotherfakeurl' - } - } + url: 'anotherfakeurl', + }, + }, }) await sendFakeCacheBlockTipEvent(newFakeState) @@ -388,12 +388,12 @@ describe('SyncApiController', () => { const fakeState1 = { cacheTipNumber, indexerTipNumber: (bestKnownBlockNumber - 50).toString(), - timestamp: '186000' + timestamp: '186000', } const fakeState2 = { cacheTipNumber, indexerTipNumber: (bestKnownBlockNumber - 1).toString(), - timestamp: '187000' + timestamp: '187000', } beforeEach(async () => { await sendFakeCacheBlockTipEvent(fakeState1) @@ -410,7 +410,7 @@ describe('SyncApiController', () => { indexRate: undefined, cacheRate: undefined, estimate: undefined, - status: 2 + status: 2, }) }) it('stores next block number', () => { @@ -425,17 +425,17 @@ describe('SyncApiController', () => { const fakeState1 = { cacheTipNumber, indexerTipNumber: '100', - timestamp: '181000' + timestamp: '181000', } const fakeState2 = { cacheTipNumber, indexerTipNumber: '200', - timestamp: '186000' + timestamp: '186000', } const fakeState3 = { cacheTipNumber, indexerTipNumber: '6201', - timestamp: '246000' + timestamp: '246000', } beforeEach(async () => { stubbedSyncStateSubjectNext.mockReset() @@ -457,7 +457,7 @@ describe('SyncApiController', () => { cacheTipNumber: parseInt(fakeState3.cacheTipNumber), indexerTipNumber: parseInt(fakeState3.indexerTipNumber), estimate: Math.round((bestKnownBlockNumber - parseInt(fakeState3.indexerTipNumber)) / indexRate), - status: 2 + status: 2, }) }) it('stores next block number', () => { @@ -472,9 +472,9 @@ describe('SyncApiController', () => { stubbedNodeGetInstance.mockImplementation(() => ({ ckb: { node: { - url: 'http://diffurl' - } - } + url: 'http://diffurl', + }, + }, })) await sendFakeCacheBlockTipEvent(fakeState3) }) @@ -489,7 +489,7 @@ describe('SyncApiController', () => { cacheTipNumber: parseInt(fakeState3.cacheTipNumber), indexerTipNumber: parseInt(fakeState3.indexerTipNumber), estimate: undefined, - status: 2 + status: 2, }) }) it('#getSyncStatus returns syncing', async () => { @@ -505,20 +505,20 @@ describe('SyncApiController', () => { const fakeState1 = { cacheTipNumber, indexerTipNumber: (bestKnownBlockNumber - 101).toString(), - timestamp: '186000' + timestamp: '186000', } const nextBestKnownBlockNumber = bestKnownBlockNumber + 50 const fakeState2 = { cacheTipNumber: nextBestKnownBlockNumber.toString(), indexerTipNumber: (bestKnownBlockNumber - 50).toString(), - timestamp: '187000' + timestamp: '187000', } beforeEach(async () => { await sendFakeCacheBlockTipEvent(fakeState1) stubbedGetSyncState.mockResolvedValue({ bestKnownBlockNumber: nextBestKnownBlockNumber.toString(16), - bestKnownBlockTimestamp: bestKnownBlockTimestamp + bestKnownBlockTimestamp: bestKnownBlockTimestamp, }) await sendFakeCacheBlockTipEvent(fakeState2) }) @@ -533,7 +533,7 @@ describe('SyncApiController', () => { indexRate: undefined, cacheRate: undefined, estimate: undefined, - status: 2 + status: 2, }) }) it('#getSyncStatus returns syncing', async () => { @@ -558,7 +558,7 @@ describe('SyncApiController', () => { indexRate: undefined, cacheRate: undefined, estimate: undefined, - status: 0 + status: 0, }) }) it('#getSyncStatus returns not started', async () => { diff --git a/packages/neuron-wallet/tests/database/address/meta.test.ts b/packages/neuron-wallet/tests/database/address/meta.test.ts index 2dc8814701..eb37c459e8 100644 --- a/packages/neuron-wallet/tests/database/address/meta.test.ts +++ b/packages/neuron-wallet/tests/database/address/meta.test.ts @@ -1,7 +1,7 @@ import { Address, AddressVersion } from '../../../src/models/address' import { AddressType } from '../../../src/models/keys/address' import AddressMeta from '../../../src/database/address/meta' -import Multisig from "../../../src/models/multisig"; +import Multisig from '../../../src/models/multisig' import AssetAccountInfo from '../../../src/models/asset-account-info' describe('Address Dao tests', () => { @@ -29,14 +29,14 @@ describe('Address Dao tests', () => { let addressMeta: AddressMeta beforeEach(() => { addressMeta = AddressMeta.fromObject(address) - }); + }) it('#generateDefaultLockScript', () => { const script = addressMeta.generateDefaultLockScript() expect(script).toEqual({ args: address.blake160, codeHash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8', - hashType: 'type' + hashType: 'type', }) }) @@ -45,7 +45,7 @@ describe('Address Dao tests', () => { expect(script).toEqual({ args: Multisig.hash([address.blake160]), codeHash: '0x5c5069eb0857efc65e1bca0c07df34c31663b3622fd3876c876320fc9634e2a8', - hashType: 'type' + hashType: 'type', }) }) @@ -55,9 +55,8 @@ describe('Address Dao tests', () => { expect(script).toEqual({ args: address.blake160, codeHash: assetAccountInfo.anyoneCanPayCodeHash, - hashType: 'type' + hashType: 'type', }) }) - }); - + }) }) diff --git a/packages/neuron-wallet/tests/mock/electron.ts b/packages/neuron-wallet/tests/mock/electron.ts index b565778daf..b603f6718d 100644 --- a/packages/neuron-wallet/tests/mock/electron.ts +++ b/packages/neuron-wallet/tests/mock/electron.ts @@ -4,10 +4,10 @@ import path from 'path' export const dialog = { showSaveDialog: jest.fn(), showMessageBox: jest.fn(), - showErrorBox: jest.fn() + showErrorBox: jest.fn(), } export const app = { getVersion: jest.fn().mockReturnValue('mock_version'), - getPath: jest.fn((p: string) => path.join(os.tmpdir(), p)) + getPath: jest.fn((p: string) => path.join(os.tmpdir(), p)), } diff --git a/packages/neuron-wallet/tests/mock/hardware.ts b/packages/neuron-wallet/tests/mock/hardware.ts index 166feaf459..67e9c500eb 100644 --- a/packages/neuron-wallet/tests/mock/hardware.ts +++ b/packages/neuron-wallet/tests/mock/hardware.ts @@ -3,7 +3,7 @@ import { AddressType } from '../../src/models/keys/address' import type { Subscriber } from 'rxjs' enum Manufacturer { - Ledger = 'Ledger' + Ledger = 'Ledger', } export const ledgerNanoS: DeviceInfo = { @@ -13,7 +13,7 @@ export const ledgerNanoS: DeviceInfo = { isBluetooth: false, manufacturer: Manufacturer.Ledger, addressType: AddressType.Receiving, - addressIndex: 0 + addressIndex: 0, } export const LedgerNanoX: DeviceInfo = { @@ -23,29 +23,25 @@ export const LedgerNanoX: DeviceInfo = { isBluetooth: true, manufacturer: Manufacturer.Ledger, addressType: AddressType.Receiving, - addressIndex: 0 + addressIndex: 0, } class LedgerTransport { - send () { + send() {} - } - - close () { - - } + close() {} } export class LedgerHID { - static async open (descriptor: string) { + static async open(descriptor: string) { if (descriptor !== ledgerNanoS.descriptor && descriptor !== LedgerNanoX.descriptor) { - throw new Error("") + throw new Error('') } return new LedgerTransport() } - static listen (subscriber: Subscriber) { + static listen(subscriber: Subscriber) { subscriber.next({ type: 'add', descriptor: ledgerNanoS.descriptor, @@ -53,13 +49,13 @@ export class LedgerHID { manufacturer: ledgerNanoS.manufacturer, product: ledgerNanoS.product, vendorId: ledgerNanoS.vendorId, - } + }, }) } } export class LedgerBLE { - static async open (descriptor: string) { + static async open(descriptor: string) { if (descriptor !== ledgerNanoS.descriptor || descriptor !== LedgerNanoX.descriptor) { throw new Error('') } @@ -67,7 +63,7 @@ export class LedgerBLE { return new LedgerTransport() } - static listen (subscriber: Subscriber) { + static listen(subscriber: Subscriber) { subscriber.next({ type: 'add', descriptor: LedgerNanoX.descriptor, @@ -75,7 +71,7 @@ export class LedgerBLE { manufacturer: LedgerNanoX.manufacturer, product: LedgerNanoX.product, vendorId: LedgerNanoX.vendorId, - } + }, }) } } @@ -87,24 +83,24 @@ export class LedgerCkbApp { public static lockArg = 'args' public static address = 'address' - async getWalletPublicKey () { + async getWalletPublicKey() { return { publicKey: LedgerCkbApp.publicKey, lockArg: LedgerCkbApp.lockArg, - address: LedgerCkbApp.address + address: LedgerCkbApp.address, } } - async getWalletExtendedPublicKey () { + async getWalletExtendedPublicKey() { return { public_key: LedgerCkbApp.publicKey, - chain_code: LedgerCkbApp.chainCode + chain_code: LedgerCkbApp.chainCode, } } - async getAppConfiguration () { + async getAppConfiguration() { return { - version: LedgerCkbApp.version + version: LedgerCkbApp.version, } } } diff --git a/packages/neuron-wallet/tests/mock/logger.ts b/packages/neuron-wallet/tests/mock/logger.ts index da876aff90..3e36051e09 100644 --- a/packages/neuron-wallet/tests/mock/logger.ts +++ b/packages/neuron-wallet/tests/mock/logger.ts @@ -1,10 +1,11 @@ export const error = console.error export const transports = { file: { - getFile: jest.fn() - } + getFile: jest.fn(), + }, } export default { - error, transports, + error, + transports, } diff --git a/packages/neuron-wallet/tests/models/address-parser.test.ts b/packages/neuron-wallet/tests/models/address-parser.test.ts index 8f6334516b..74890eb1a2 100644 --- a/packages/neuron-wallet/tests/models/address-parser.test.ts +++ b/packages/neuron-wallet/tests/models/address-parser.test.ts @@ -1,13 +1,13 @@ -import AddressParser from "../../src/models/address-parser" -import AssetAccountInfo from "../../src/models/asset-account-info" -import { ScriptHashType } from "../../src/models/chain/script" +import AddressParser from '../../src/models/address-parser' +import AssetAccountInfo from '../../src/models/asset-account-info' +import { ScriptHashType } from '../../src/models/chain/script' describe('AddressParser', () => { const fullAddressInfo = { address: 'ckb1qjda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xw3vumhs9nvu786dj9p0q5elx66t24n3kxgj53qks', codeHash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8', args: '0xb39bbc0b3673c7d36450bc14cfcdad2d559c6c64', - hashType: ScriptHashType.Type + hashType: ScriptHashType.Type, } const shortAddressInfo = { @@ -21,7 +21,7 @@ describe('AddressParser', () => { address: 'ckb1qyq5lv479ewscx3ms620sv34pgeuz6zagaaqklhtgg', hashType: ScriptHashType.Type, args: '0x4fb2be2e5d0c1a3b8694f832350a33c1685d477a', - codeHash: '0x5c5069eb0857efc65e1bca0c07df34c31663b3622fd3876c876320fc9634e2a8' + codeHash: '0x5c5069eb0857efc65e1bca0c07df34c31663b3622fd3876c876320fc9634e2a8', } const shortACPAddressInfo = { @@ -34,7 +34,7 @@ describe('AddressParser', () => { codeHash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8', args: '0xb39bbc0b3673c7d36450bc14cfcdad2d559c6c64', hashType: ScriptHashType.Type, - address: 'ckb1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsqdnnw7qkdnnclfkg59uzn8umtfd2kwxceqxwquc4' + address: 'ckb1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsqdnnw7qkdnnclfkg59uzn8umtfd2kwxceqxwquc4', } // @ts-ignore private property const assetAccount = new AssetAccountInfo(AssetAccountInfo.MAINNET_GENESIS_BLOCK_HASH) @@ -54,14 +54,14 @@ describe('AddressParser', () => { expect(script.hashType).toEqual(shortAddressInfo.hashType) }) - it ('multi sign short address', () => { + it('multi sign short address', () => { const script = AddressParser.parse(multiSignAddressInfo.address) expect(script.codeHash).toEqual(multiSignAddressInfo.codeHash) expect(script.args).toEqual(multiSignAddressInfo.args) expect(script.hashType).toEqual(multiSignAddressInfo.hashType) }) - it ('acp short address', () => { + it('acp short address', () => { const script = AddressParser.parse(shortACPAddressInfo.address) expect(script.codeHash).toEqual(assetAccount.anyoneCanPayCodeHash) expect(script.args).toEqual(shortACPAddressInfo.args) @@ -80,7 +80,7 @@ describe('AddressParser', () => { const result = AddressParser.batchParse([ shortAddressInfo.address, fullAddressInfo.address, - shortACPAddressInfo.address + shortACPAddressInfo.address, ]) expect(result.length).toEqual(3) expect(result[0].codeHash).toEqual(shortAddressInfo.codeHash) @@ -93,5 +93,4 @@ describe('AddressParser', () => { expect(result[2].args).toEqual(shortACPAddressInfo.args) expect(result[2].hashType).toEqual(shortACPAddressInfo.hashType) }) - }) diff --git a/packages/neuron-wallet/tests/models/asset-account-info.test.ts b/packages/neuron-wallet/tests/models/asset-account-info.test.ts index fbe3eecb28..9a35c45a2b 100644 --- a/packages/neuron-wallet/tests/models/asset-account-info.test.ts +++ b/packages/neuron-wallet/tests/models/asset-account-info.test.ts @@ -1,48 +1,48 @@ -import AssetAccountInfo from "../../src/models/asset-account-info" -import CellDep, { DepType } from "../../src/models/chain/cell-dep" -import OutPoint from "../../src/models/chain/out-point" -import { ScriptHashType } from "../../src/models/chain/script" -import { AddressType } from "../../src/models/keys/address" +import AssetAccountInfo from '../../src/models/asset-account-info' +import CellDep, { DepType } from '../../src/models/chain/cell-dep' +import OutPoint from '../../src/models/chain/out-point' +import { ScriptHashType } from '../../src/models/chain/script' +import { AddressType } from '../../src/models/keys/address' import AddressMeta from '../../src/database/address/meta' describe('AssetAccountInfo', () => { const testnetSudtInfo = { - cellDep: new CellDep(new OutPoint('0xc1b2ae129fad7465aaa9acc9785f842ba3e6e8b8051d899defa89f5508a77958', '0'), DepType.Code), + cellDep: new CellDep( + new OutPoint('0xc1b2ae129fad7465aaa9acc9785f842ba3e6e8b8051d899defa89f5508a77958', '0'), + DepType.Code + ), codeHash: '0x48dbf59b4c7ee1547238021b4869bceedf4eea6b43772e5d66ef8865b6ae7212', - hashType: ScriptHashType.Data + hashType: ScriptHashType.Data, } const testnetAnyoneCanPayInfo = { - cellDep: new CellDep(new OutPoint('0x4f32b3e39bd1b6350d326fdfafdfe05e5221865c3098ae323096f0bfc69e0a8c', '0'), DepType.DepGroup), + cellDep: new CellDep( + new OutPoint('0x4f32b3e39bd1b6350d326fdfafdfe05e5221865c3098ae323096f0bfc69e0a8c', '0'), + DepType.DepGroup + ), codeHash: process.env.TESTNET_ACP_SCRIPT_CODEHASH, - hashType: process.env.TESTNET_ACP_SCRIPT_HASHTYPE + hashType: process.env.TESTNET_ACP_SCRIPT_HASHTYPE, } describe('testnet', () => { const genesisBlockHash = '0x63547ecf6fc22d1325980c524b268b4a044d49cda3efbd584c0a8c8b9faaf9e1' it('getSudtCellDep', () => { - expect( - new AssetAccountInfo(genesisBlockHash).sudtCellDep - ).toEqual(testnetSudtInfo.cellDep) + expect(new AssetAccountInfo(genesisBlockHash).sudtCellDep).toEqual(testnetSudtInfo.cellDep) }) it('getAnyoneCanPayCellDep', () => { - expect( - new AssetAccountInfo(genesisBlockHash).anyoneCanPayCellDep - ).toEqual(testnetAnyoneCanPayInfo.cellDep) + expect(new AssetAccountInfo(genesisBlockHash).anyoneCanPayCellDep).toEqual(testnetAnyoneCanPayInfo.cellDep) }) it('generateSudtScript', () => { - expect( - new AssetAccountInfo(genesisBlockHash).generateSudtScript('0x').codeHash - ).toEqual(testnetSudtInfo.codeHash) + expect(new AssetAccountInfo(genesisBlockHash).generateSudtScript('0x').codeHash).toEqual(testnetSudtInfo.codeHash) }) it('generateAnyoneCanPayScript', () => { - expect( - new AssetAccountInfo(genesisBlockHash).generateAnyoneCanPayScript('0x').codeHash - ).toEqual(testnetAnyoneCanPayInfo.codeHash) + expect(new AssetAccountInfo(genesisBlockHash).generateAnyoneCanPayScript('0x').codeHash).toEqual( + testnetAnyoneCanPayInfo.codeHash + ) }) describe('#findSignPathForCheque', () => { @@ -53,7 +53,7 @@ describe('AssetAccountInfo', () => { path: 'p1', addressType: AddressType.Change, addressIndex: 0, - blake160: '0xe2193df51d78411601796b35b17b4f8f2cd85bd0' + blake160: '0xe2193df51d78411601796b35b17b4f8f2cd85bd0', }) const senderAddressInfo = AddressMeta.fromObject({ walletId: '1', @@ -61,76 +61,62 @@ describe('AssetAccountInfo', () => { path: 'p2', addressType: AddressType.Change, addressIndex: 1, - blake160: '0xe2193df51d78411601796b35b17b4f8f2cd85bd1' + blake160: '0xe2193df51d78411601796b35b17b4f8f2cd85bd1', }) const chequeScript = assetAccountInfo.generateChequeScript( receiverAddressInfo.generateDefaultLockScript().computeHash(), - senderAddressInfo.generateDefaultLockScript().computeHash(), + senderAddressInfo.generateDefaultLockScript().computeHash() ) describe('receiver address is ordered first', () => { - const addressInfos = [ - receiverAddressInfo, - senderAddressInfo - ] + const addressInfos = [receiverAddressInfo, senderAddressInfo] it('found receiver path', async () => { const addressInfo = await AssetAccountInfo.findSignPathForCheque(addressInfos, chequeScript.args) expect(addressInfo!.blake160).toEqual(receiverAddressInfo.blake160) }) - }); + }) describe('sender address is ordered first and receiver later', () => { - const addressInfos = [ - senderAddressInfo, - receiverAddressInfo, - ] + const addressInfos = [senderAddressInfo, receiverAddressInfo] it('found receiver path', async () => { const addressInfo = await AssetAccountInfo.findSignPathForCheque(addressInfos, chequeScript.args) expect(addressInfo!.blake160).toEqual(receiverAddressInfo.blake160) }) - }); + }) describe('only sender exists in the address info candidates', () => { - const addressInfos = [ - senderAddressInfo, - ] + const addressInfos = [senderAddressInfo] it('found sender path', async () => { const addressInfo = await AssetAccountInfo.findSignPathForCheque(addressInfos, chequeScript.args) expect(addressInfo!.blake160).toEqual(senderAddressInfo.blake160) }) - }); + }) describe('neither sender address nor receiver address found', () => { const addressInfos: any = [] it('return null', async () => { const addressInfo = await AssetAccountInfo.findSignPathForCheque(addressInfos, chequeScript.args) expect(addressInfo).toEqual(null) }) - }); - }); + }) + }) }) describe('other net', () => { const genesisBlockHash = '0x' + '0'.repeat(64) it('getSudtCellDep', () => { - expect( - new AssetAccountInfo(genesisBlockHash).sudtCellDep - ).toEqual(testnetSudtInfo.cellDep) + expect(new AssetAccountInfo(genesisBlockHash).sudtCellDep).toEqual(testnetSudtInfo.cellDep) }) it('getAnyoneCanPayCellDep', () => { - expect( - new AssetAccountInfo(genesisBlockHash).anyoneCanPayCellDep - ).toEqual(testnetAnyoneCanPayInfo.cellDep) + expect(new AssetAccountInfo(genesisBlockHash).anyoneCanPayCellDep).toEqual(testnetAnyoneCanPayInfo.cellDep) }) it('generateSudtScript', () => { - expect( - new AssetAccountInfo(genesisBlockHash).generateSudtScript('0x').codeHash - ).toEqual(testnetSudtInfo.codeHash) + expect(new AssetAccountInfo(genesisBlockHash).generateSudtScript('0x').codeHash).toEqual(testnetSudtInfo.codeHash) }) it('generateAnyoneCanPayScript', () => { - expect( - new AssetAccountInfo(genesisBlockHash).generateAnyoneCanPayScript('0x').codeHash - ).toEqual(testnetAnyoneCanPayInfo.codeHash) + expect(new AssetAccountInfo(genesisBlockHash).generateAnyoneCanPayScript('0x').codeHash).toEqual( + testnetAnyoneCanPayInfo.codeHash + ) }) }) }) diff --git a/packages/neuron-wallet/tests/models/chain/block-header.test.ts b/packages/neuron-wallet/tests/models/chain/block-header.test.ts index f7f199956d..a6b1680124 100644 --- a/packages/neuron-wallet/tests/models/chain/block-header.test.ts +++ b/packages/neuron-wallet/tests/models/chain/block-header.test.ts @@ -1,20 +1,20 @@ -import BlockHeader from "../../../src/models/chain/block-header" -import HexUtils from "../../../src/utils/hex" +import BlockHeader from '../../../src/models/chain/block-header' +import HexUtils from '../../../src/utils/hex' describe('BlockHeader', () => { const sdkHeader: CKBComponents.BlockHeader = { - "compactTarget": "0x1e083126", - "dao": "0xb5a3e047474401001bc476b9ee573000c0c387962a38000000febffacf030000", - "epoch": "0x7080018000001", - "hash": "0xa5f5c85987a15de25661e5a214f2c1449cd803f071acc7999820f25246471f40", - "nonce": "0x0", - "number": "0x400", - "parentHash": "0xae003585fa15309b30b31aed3dcf385e9472c3c3e93746a6c4540629a6a1ed2d", - "proposalsHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "timestamp": "0x5cd2b117", - "transactionsRoot": "0xc47d5b78b3c4c4c853e2a32810818940d0ee403423bea9ec7b8e566d9595206c", - "extraHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "version": "0x0" + compactTarget: '0x1e083126', + dao: '0xb5a3e047474401001bc476b9ee573000c0c387962a38000000febffacf030000', + epoch: '0x7080018000001', + hash: '0xa5f5c85987a15de25661e5a214f2c1449cd803f071acc7999820f25246471f40', + nonce: '0x0', + number: '0x400', + parentHash: '0xae003585fa15309b30b31aed3dcf385e9472c3c3e93746a6c4540629a6a1ed2d', + proposalsHash: '0x0000000000000000000000000000000000000000000000000000000000000000', + timestamp: '0x5cd2b117', + transactionsRoot: '0xc47d5b78b3c4c4c853e2a32810818940d0ee403423bea9ec7b8e566d9595206c', + extraHash: '0x0000000000000000000000000000000000000000000000000000000000000000', + version: '0x0', } it('fromSDK', () => { @@ -26,5 +26,4 @@ describe('BlockHeader', () => { expect(result.number).toEqual(HexUtils.toDecimal(sdkHeader.number)) expect(result.epoch).toEqual(HexUtils.toDecimal(sdkHeader.epoch)) }) - }) diff --git a/packages/neuron-wallet/tests/models/chain/live-cell.test.ts b/packages/neuron-wallet/tests/models/chain/live-cell.test.ts index c05c58a80a..f60398acc5 100644 --- a/packages/neuron-wallet/tests/models/chain/live-cell.test.ts +++ b/packages/neuron-wallet/tests/models/chain/live-cell.test.ts @@ -1,6 +1,6 @@ import Script, { ScriptHashType } from '../../../src/models/chain/script' import { LumosCell } from '../../../src/block-sync-renderer/sync/indexer-connector' -import LiveCell from "../../../src/models/chain/live-cell" +import LiveCell from '../../../src/models/chain/live-cell' describe('LiveCell Test', () => { const INITIAL_DATA = { @@ -10,14 +10,14 @@ describe('LiveCell Test', () => { lock: { codeHash: '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', hashType: ScriptHashType.Data, - args: '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' + args: '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', }, type: { codeHash: '0xcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', hashType: ScriptHashType.Data1, - args: '0xdddddddddddddddddddddddddddddddddddddddd' + args: '0xdddddddddddddddddddddddddddddddddddddddd', }, - data: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + data: '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', } let liveCell: LiveCell @@ -29,7 +29,7 @@ describe('LiveCell Test', () => { INITIAL_DATA.capacity, new Script(INITIAL_DATA.lock.codeHash, INITIAL_DATA.lock.args, INITIAL_DATA.lock.hashType), new Script(INITIAL_DATA.type.codeHash, INITIAL_DATA.type.args, INITIAL_DATA.type.hashType), - INITIAL_DATA.data, + INITIAL_DATA.data ) }) @@ -53,7 +53,7 @@ describe('LiveCell Test', () => { it('should have outpoint', () => { expect(liveCell.outPoint()).toMatchObject({ txHash: INITIAL_DATA.txHash, - index: '1' + index: '1', }) }) @@ -81,7 +81,7 @@ describe('LiveCell Test', () => { INITIAL_DATA.capacity, new Script(INITIAL_DATA.lock.codeHash, INITIAL_DATA.lock.args, INITIAL_DATA.lock.hashType), null, - INITIAL_DATA.data, + INITIAL_DATA.data ) expect(cell.type()).toBe(undefined) }) @@ -140,7 +140,6 @@ describe('LiveCell Test', () => { lockArgs: INITIAL_DATA.lock.args, data: INITIAL_DATA.data, }) - }) }) }) diff --git a/packages/neuron-wallet/tests/models/chain/out-point.test.ts b/packages/neuron-wallet/tests/models/chain/out-point.test.ts index fa14979bdf..8d04ead142 100644 --- a/packages/neuron-wallet/tests/models/chain/out-point.test.ts +++ b/packages/neuron-wallet/tests/models/chain/out-point.test.ts @@ -20,7 +20,7 @@ describe('OutPoint', () => { it('fromSDK', () => { const o = OutPoint.fromSDK({ txHash: outPoint.txHash, - index: '0x0' + index: '0x0', }) expect(o.txHash).toEqual(outPoint.txHash) expect(o.index).toEqual(outPoint.index) diff --git a/packages/neuron-wallet/tests/models/chain/output.test.ts b/packages/neuron-wallet/tests/models/chain/output.test.ts index 755084cc5d..16444eaf06 100644 --- a/packages/neuron-wallet/tests/models/chain/output.test.ts +++ b/packages/neuron-wallet/tests/models/chain/output.test.ts @@ -2,7 +2,11 @@ import Output from '../../../src/models/chain/output' import Script, { ScriptHashType } from '../../../src/models/chain/script' describe('Output', () => { - const lockScript = new Script('0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8', '0x36c329ed630d6ce750712a477543672adab57f4c', ScriptHashType.Type) + const lockScript = new Script( + '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8', + '0x36c329ed630d6ce750712a477543672adab57f4c', + ScriptHashType.Type + ) const output = new Output('1000', lockScript, undefined, '0x') const outputWithType = new Output('1000', lockScript, lockScript, '0x') const outputWithData = new Output('1000', lockScript, undefined, '0x1234') diff --git a/packages/neuron-wallet/tests/models/chain/script.test.ts b/packages/neuron-wallet/tests/models/chain/script.test.ts index 17761327d4..86c6db9af7 100644 --- a/packages/neuron-wallet/tests/models/chain/script.test.ts +++ b/packages/neuron-wallet/tests/models/chain/script.test.ts @@ -14,7 +14,7 @@ describe('Script', () => { expect(script.hashType).toEqual(hashType) }) - it("computeHash", () => { + it('computeHash', () => { const hash = script.computeHash() expect(hash).toEqual(expectedLockHash) }) @@ -34,7 +34,7 @@ describe('Script', () => { const s = Script.fromSDK({ codeHash, args, - hashType + hashType, }) expect(s.codeHash).toEqual(script.codeHash) expect(s.args).toEqual(script.args) diff --git a/packages/neuron-wallet/tests/models/chain/transaction.test.ts b/packages/neuron-wallet/tests/models/chain/transaction.test.ts index e60a64b9ce..6d92ccdfdb 100644 --- a/packages/neuron-wallet/tests/models/chain/transaction.test.ts +++ b/packages/neuron-wallet/tests/models/chain/transaction.test.ts @@ -12,13 +12,9 @@ describe('Transaction', () => { const transactionInterface = { hash, version: '0', - cellDeps: [ - new CellDep(new OutPoint(hash, '0'), DepType.DepGroup) - ], + cellDeps: [new CellDep(new OutPoint(hash, '0'), DepType.DepGroup)], headerDeps: [hash], - inputs: [ - new Input(new OutPoint(hash, '0'), '0') - ], + inputs: [new Input(new OutPoint(hash, '0'), '0')], outputs: [ Output.fromObject({ capacity: '1000', @@ -28,12 +24,9 @@ describe('Transaction', () => { outPoint: new OutPoint(hash, '0'), status: OutputStatus.Live, daoData: '0x', - }) - ], - witnesses: [ - '0x', - new WitnessArgs(WitnessArgs.EMPTY_LOCK), + }), ], + witnesses: ['0x', new WitnessArgs(WitnessArgs.EMPTY_LOCK)], value: '100', fee: '1', type: 'send', @@ -52,7 +45,7 @@ describe('Transaction', () => { }) it('computeHash', () => { - expect(tx.computeHash()).toEqual("0xf09ef3072ec48a89ed772abd98feb1dd0f3c5074fcc00628c1a82e697aca92e4") + expect(tx.computeHash()).toEqual('0xf09ef3072ec48a89ed772abd98feb1dd0f3c5074fcc00628c1a82e697aca92e4') }) it('toSDK / fromSDK', () => { @@ -63,62 +56,62 @@ describe('Transaction', () => { describe('setSignatures', () => { const sdkTx: CKBComponents.Transaction = { - "hash": '', - "version": "0x0", - "cellDeps": [ + hash: '', + version: '0x0', + cellDeps: [ { - "outPoint": { - "txHash": "0xc12386705b5cbb312b693874f3edf45c43a274482e27b8df0fd80c8d3f5feb8b", - "index": "0x0" + outPoint: { + txHash: '0xc12386705b5cbb312b693874f3edf45c43a274482e27b8df0fd80c8d3f5feb8b', + index: '0x0', }, - "depType": "depGroup" + depType: 'depGroup', }, { - "outPoint": { - "txHash": "0x0fb4945d52baf91e0dee2a686cdd9d84cad95b566a1d7409b970ee0a0f364f60", - "index": "0x2" + outPoint: { + txHash: '0x0fb4945d52baf91e0dee2a686cdd9d84cad95b566a1d7409b970ee0a0f364f60', + index: '0x2', }, - "depType": "code" - } + depType: 'code', + }, ], - "headerDeps": [], - "inputs": [ + headerDeps: [], + inputs: [ { - "previousOutput": { - "txHash": "0x31f695263423a4b05045dd25ce6692bb55d7bba2965d8be16b036e138e72cc65", - "index": "0x1" + previousOutput: { + txHash: '0x31f695263423a4b05045dd25ce6692bb55d7bba2965d8be16b036e138e72cc65', + index: '0x1', }, - "since": "0x0" - } + since: '0x0', + }, ], - "outputs": [ + outputs: [ { - "capacity": "0x174876e800", - "lock": { - "codeHash": "0x68d5438ac952d2f584abf879527946a537e82c7f3c1cbf6d8ebf9767437d8e88", - "args": "0x59a27ef3ba84f061517d13f42cf44ed020610061", - "hashType": "type" + capacity: '0x174876e800', + lock: { + codeHash: '0x68d5438ac952d2f584abf879527946a537e82c7f3c1cbf6d8ebf9767437d8e88', + args: '0x59a27ef3ba84f061517d13f42cf44ed020610061', + hashType: 'type', + }, + type: { + codeHash: '0xece45e0979030e2f8909f76258631c42333b1e906fd9701ec3600a464a90b8f6', + args: '0x', + hashType: 'data', }, - "type": { - "codeHash": "0xece45e0979030e2f8909f76258631c42333b1e906fd9701ec3600a464a90b8f6", - "args": "0x", - "hashType": "data" - } }, { - "capacity": "0x59e1416a5000", - "lock": { - "codeHash": "0x68d5438ac952d2f584abf879527946a537e82c7f3c1cbf6d8ebf9767437d8e88", - "args": "0x59a27ef3ba84f061517d13f42cf44ed020610061", - "hashType": "type" + capacity: '0x59e1416a5000', + lock: { + codeHash: '0x68d5438ac952d2f584abf879527946a537e82c7f3c1cbf6d8ebf9767437d8e88', + args: '0x59a27ef3ba84f061517d13f42cf44ed020610061', + hashType: 'type', }, - "type": null - } + type: null, + }, + ], + outputsData: ['0x1234', '0x'], + witnesses: [ + '0x82df73581bcd08cb9aa270128d15e79996229ce8ea9e4f985b49fbf36762c5c37936caf3ea3784ee326f60b8992924fcf496f9503c907982525a3436f01ab32900', ], - "outputsData": ["0x1234", "0x"], - "witnesses": [ - "0x82df73581bcd08cb9aa270128d15e79996229ce8ea9e4f985b49fbf36762c5c37936caf3ea3784ee326f60b8992924fcf496f9503c907982525a3436f01ab32900" - ] } const tx = Transaction.fromSDK(sdkTx) diff --git a/packages/neuron-wallet/tests/models/chain/witness-args.test.ts b/packages/neuron-wallet/tests/models/chain/witness-args.test.ts index fab6dbaac2..9a62ba7d9b 100644 --- a/packages/neuron-wallet/tests/models/chain/witness-args.test.ts +++ b/packages/neuron-wallet/tests/models/chain/witness-args.test.ts @@ -1,5 +1,5 @@ -import WitnessArgs from "../../../src/models/chain/witness-args" -import { serializeWitnessArgs } from "@nervosnetwork/ckb-sdk-utils" +import WitnessArgs from '../../../src/models/chain/witness-args' +import { serializeWitnessArgs } from '@nervosnetwork/ckb-sdk-utils' describe('WitnessArgs', () => { describe('deserialize', () => { diff --git a/packages/neuron-wallet/tests/models/keys/address.test.ts b/packages/neuron-wallet/tests/models/keys/address.test.ts index 6ba4b13691..c0ec834827 100644 --- a/packages/neuron-wallet/tests/models/keys/address.test.ts +++ b/packages/neuron-wallet/tests/models/keys/address.test.ts @@ -17,19 +17,25 @@ describe('address', () => { const publicKey = '0x024a501efd328e062c8675f2365970728c859c592beeefd6be8ead3d901330bc01' const path = `m/44'/309'/0'/0/0` const address = Address.fromPublicKey(publicKey, `m/44'/309'/0'/0/0`) - expect(address.address).toEqual('ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsqfkcv576ccddnn4quf2ga65xee2m26h7nq4sds0r') + expect(address.address).toEqual( + 'ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsqfkcv576ccddnn4quf2ga65xee2m26h7nq4sds0r' + ) expect(address.path).toEqual(path) }) it('Generate testnet address from public key', () => { const publicKey = '0x024a501efd328e062c8675f2365970728c859c592beeefd6be8ead3d901330bc01' const address = publicKeyToAddress(publicKey) - expect(address).toEqual('ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsqfkcv576ccddnn4quf2ga65xee2m26h7nq4sds0r') + expect(address).toEqual( + 'ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsqfkcv576ccddnn4quf2ga65xee2m26h7nq4sds0r' + ) }) it('Generate mainnet address from public key', () => { const publicKey = '0x024a501efd328e062c8675f2365970728c859c592beeefd6be8ead3d901330bc01' const address = publicKeyToAddress(publicKey, true) - expect(address).toEqual('ckb1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsqfkcv576ccddnn4quf2ga65xee2m26h7nqmzxl9m') + expect(address).toEqual( + 'ckb1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsqfkcv576ccddnn4quf2ga65xee2m26h7nqmzxl9m' + ) }) }) diff --git a/packages/neuron-wallet/tests/models/keys/hd-public-key-info.test.ts b/packages/neuron-wallet/tests/models/keys/hd-public-key-info.test.ts index 9cca1f1370..12b42e4090 100644 --- a/packages/neuron-wallet/tests/models/keys/hd-public-key-info.test.ts +++ b/packages/neuron-wallet/tests/models/keys/hd-public-key-info.test.ts @@ -7,7 +7,7 @@ const stubbedIsMainnet = jest.fn() jest.doMock('services/networks', () => { return { getInstance: () => ({ - isMainnet: stubbedIsMainnet + isMainnet: stubbedIsMainnet, }), } }) @@ -24,7 +24,7 @@ describe('HdPublicKeyInfoModel', () => { beforeEach(() => { resetMocks() - }); + }) describe('#address', () => { describe('with mainnet', () => { @@ -33,48 +33,54 @@ describe('HdPublicKeyInfoModel', () => { keyInfoModel = HdPublicKeyInfoModel.fromObject({ publicKeyInBlake160: keyInfo.publicKeyInBlake160, }) - }); + }) it('generates mainnet address by property', () => { - const address = scriptToAddress({ ...systemScripts.SECP256K1_BLAKE160, args: keyInfo.publicKeyInBlake160 }, true) + const address = scriptToAddress( + { ...systemScripts.SECP256K1_BLAKE160, args: keyInfo.publicKeyInBlake160 }, + true + ) expect(keyInfoModel.address).toEqual(address) }) - }); + }) describe('with testnet', () => { beforeEach(() => { stubbedIsMainnet.mockReturnValue(false) keyInfoModel = HdPublicKeyInfoModel.fromObject({ publicKeyInBlake160: keyInfo.publicKeyInBlake160, }) - }); + }) it('generates testnet address by property', () => { - const address = scriptToAddress({ ...systemScripts.SECP256K1_BLAKE160, args: keyInfo.publicKeyInBlake160 }, false) + const address = scriptToAddress( + { ...systemScripts.SECP256K1_BLAKE160, args: keyInfo.publicKeyInBlake160 }, + false + ) expect(keyInfoModel.address).toEqual(address) }) - }); - }); + }) + }) describe('#path', () => { describe('with change address type', () => { beforeEach(() => { keyInfoModel = HdPublicKeyInfoModel.fromObject({ addressType: AddressType.Change, - addressIndex: 1 + addressIndex: 1, }) - }); + }) it('generates path by property', () => { expect(keyInfoModel.path).toEqual("m/44'/309'/0'/1/1") }) - }); + }) describe('with receive address type', () => { beforeEach(() => { keyInfoModel = HdPublicKeyInfoModel.fromObject({ addressType: AddressType.Receiving, - addressIndex: 1 + addressIndex: 1, }) - }); + }) it('generates path by property', () => { expect(keyInfoModel.path).toEqual("m/44'/309'/0'/0/1") }) - }); - }); -}); + }) + }) +}) diff --git a/packages/neuron-wallet/tests/models/keys/keychain.test.ts b/packages/neuron-wallet/tests/models/keys/keychain.test.ts index 0d65fb72d7..d7b88e3831 100644 --- a/packages/neuron-wallet/tests/models/keys/keychain.test.ts +++ b/packages/neuron-wallet/tests/models/keys/keychain.test.ts @@ -167,23 +167,16 @@ describe('BIP32 Keychain tests', () => { '2925f5dfcbee3b6ad29100a37ed36cbe92d51069779cc96164182c779c5dc20e' ) - expect( - master - .derivePath(`m/44'/309'/0'`) - .deriveChild(0, false) - .privateKey.toString('hex') - ).toEqual('047fae4f38b3204f93a6b39d6dbcfbf5901f2b09f6afec21cbef6033d01801f1') + expect(master.derivePath(`m/44'/309'/0'`).deriveChild(0, false).privateKey.toString('hex')).toEqual( + '047fae4f38b3204f93a6b39d6dbcfbf5901f2b09f6afec21cbef6033d01801f1' + ) expect(master.derivePath(`m/44'/309'/0'/0`).privateKey.toString('hex')).toEqual( '047fae4f38b3204f93a6b39d6dbcfbf5901f2b09f6afec21cbef6033d01801f1' ) expect( - master - .derivePath(`m/44'/309'/0'`) - .deriveChild(0, false) - .deriveChild(0, false) - .privateKey.toString('hex') + master.derivePath(`m/44'/309'/0'`).deriveChild(0, false).deriveChild(0, false).privateKey.toString('hex') ).toEqual('848422863825f69e66dc7f48a3302459ec845395370c23578817456ad6b04b14') expect(master.derivePath(`m/44'/309'/0'/0/0`).privateKey.toString('hex')).toEqual( @@ -203,23 +196,16 @@ describe('BIP32 Keychain tests', () => { '2925f5dfcbee3b6ad29100a37ed36cbe92d51069779cc96164182c779c5dc20e' ) - expect( - master - .derivePath(`m/44'/309'/0'`) - .deriveChild(0, false) - .privateKey.toString('hex') - ).toEqual('047fae4f38b3204f93a6b39d6dbcfbf5901f2b09f6afec21cbef6033d01801f1') + expect(master.derivePath(`m/44'/309'/0'`).deriveChild(0, false).privateKey.toString('hex')).toEqual( + '047fae4f38b3204f93a6b39d6dbcfbf5901f2b09f6afec21cbef6033d01801f1' + ) expect(master.derivePath(`m/44'/309'/0'/0`).privateKey.toString('hex')).toEqual( '047fae4f38b3204f93a6b39d6dbcfbf5901f2b09f6afec21cbef6033d01801f1' ) expect( - master - .derivePath(`m/44'/309'/0'`) - .deriveChild(0, false) - .deriveChild(0, false) - .privateKey.toString('hex') + master.derivePath(`m/44'/309'/0'`).deriveChild(0, false).deriveChild(0, false).privateKey.toString('hex') ).toEqual('848422863825f69e66dc7f48a3302459ec845395370c23578817456ad6b04b14') expect(master.derivePath(`m/44'/309'/0'/0/0`).privateKey.toString('hex')).toEqual( @@ -227,7 +213,6 @@ describe('BIP32 Keychain tests', () => { ) }) - it('private key add', () => { const privateKey = Buffer.from('9e919c96ac5a4caea7ba0ea1f7dd7bca5dca8a11e66ed633690c71e483a6e3c9', 'hex') const toAdd = Buffer.from('36e92e33659808bf06c3e4302b657f39ca285f6bb5393019bb4e2f7b96e3f914', 'hex') diff --git a/packages/neuron-wallet/tests/models/keys/keystore.test.ts b/packages/neuron-wallet/tests/models/keys/keystore.test.ts index 54f6ee1fd6..ade22729cf 100644 --- a/packages/neuron-wallet/tests/models/keys/keystore.test.ts +++ b/packages/neuron-wallet/tests/models/keys/keystore.test.ts @@ -66,26 +66,24 @@ describe('load ckb cli origin keystore', () => { '{"origin":"ckb-cli", "address":"ea22142fa5be326e834681144ca30326f99a6d5a","crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"29304e5bcbb1885ef5cdcb40b5312b58"},"ciphertext":"93054530a8fbe5b11995acda856585d7362ac7d2b1e4f268c633d997be2d6532c4962501d0835bf52a4693ae7a091ac9bac9297793f4116ef7c123edb00dbc85","kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"724327e67ca321ccf15035bb78a0a05c816bebbe218a0840abdc26da8453c1f4"},"mac":"1d0e5660ffbfc1f9ff4da97aefcfc2153c0ec1b411e35ffee26ee92815cc06f9"},"id":"43c1116e-efd5-4c9e-a86a-3ec0ab163122","version":3}' it('does not load', () => { - expect( - () => Keystore.fromJson(keystoreString) - ).toThrowError() + expect(() => Keystore.fromJson(keystoreString)).toThrowError() }) }) -describe("create empty keystore", () => { +describe('create empty keystore', () => { const keystore = Keystore.createEmpty() - it("has empty cipertext and mac", () => { - expect(keystore.crypto.ciphertext).toEqual("") - expect(keystore.crypto.mac).toEqual("") + it('has empty cipertext and mac', () => { + expect(keystore.crypto.ciphertext).toEqual('') + expect(keystore.crypto.mac).toEqual('') }) it("won't verify password", () => { - expect(keystore.checkPassword("")).toBeFalsy() - expect(keystore.checkPassword("anypassword")).toBeFalsy() + expect(keystore.checkPassword('')).toBeFalsy() + expect(keystore.checkPassword('anypassword')).toBeFalsy() }) - it("cannot decrypt", () => { - expect(() => keystore.decrypt("")).toThrowError(new IncorrectPassword()) + it('cannot decrypt', () => { + expect(() => keystore.decrypt('')).toThrowError(new IncorrectPassword()) }) }) diff --git a/packages/neuron-wallet/tests/models/migrate-subject.test.ts b/packages/neuron-wallet/tests/models/migrate-subject.test.ts index be9952e62e..60db05e365 100644 --- a/packages/neuron-wallet/tests/models/migrate-subject.test.ts +++ b/packages/neuron-wallet/tests/models/migrate-subject.test.ts @@ -2,17 +2,17 @@ import CommonUtils from '../../src/utils/common' const nextMock = jest.fn() jest.doMock('rxjs', () => { - const rxjs = jest.requireActual('rxjs'); + const rxjs = jest.requireActual('rxjs') return { __esModule: true, ...rxjs, - Subject: function() { + Subject: function () { const res = new rxjs.Subject() res.next = nextMock return res - } + }, } -}); +}) import MigrateSubject from '../../src/models/subjects/migrate-subject' @@ -58,10 +58,10 @@ describe('migrate subject test', () => { it('migrate end with failed', async () => { MigrateSubject.next({ type: 'need-migrate' }) MigrateSubject.next({ type: 'migrating' }) - MigrateSubject.next({ type: 'failed', reason: 'failed'}) + MigrateSubject.next({ type: 'failed', reason: 'failed' }) await CommonUtils.sleep(3000) MigrateSubject.getSubject().unsubscribe() - expect(nextMock).toHaveBeenLastCalledWith({ type: 'failed', reason: 'failed'}) + expect(nextMock).toHaveBeenLastCalledWith({ type: 'failed', reason: 'failed' }) expect(nextMock).toBeCalledTimes(3) }) -}) \ No newline at end of file +}) diff --git a/packages/neuron-wallet/tests/models/multi-sign.test.ts b/packages/neuron-wallet/tests/models/multi-sign.test.ts index 346809be77..bf9416a94b 100644 --- a/packages/neuron-wallet/tests/models/multi-sign.test.ts +++ b/packages/neuron-wallet/tests/models/multi-sign.test.ts @@ -1,18 +1,18 @@ -import Multisig from "../../src/models/multisig" +import Multisig from '../../src/models/multisig' describe('MultiSign Test', () => { const minutes = 360 - const headerEpoch = "0x7080018000001" + const headerEpoch = '0x7080018000001' const expectedSince = '0x0200007b00f00020' const bob = { privateKey: '0xe79f3207ea4980b7fed79956d5934249ceac4751a4fae01a0f7c4a96884bc4e3', publicKey: '0x024a501efd328e062c8675f2365970728c859c592beeefd6be8ead3d901330bc01', blake160: '0x36c329ed630d6ce750712a477543672adab57f4c', - hash: "0x56f281b3d4bb5fc73c751714af0bf78eb8aba0d8" + hash: '0x56f281b3d4bb5fc73c751714af0bf78eb8aba0d8', } const expectedArgs = '0x56f281b3d4bb5fc73c751714af0bf78eb8aba0d80200007b00f00020' - const serialized = "0x0000010136c329ed630d6ce750712a477543672adab57f4c" + const serialized = '0x0000010136c329ed630d6ce750712a477543672adab57f4c' it('since', () => { const since = new Multisig().since(minutes, headerEpoch) diff --git a/packages/neuron-wallet/tests/models/offline-sign.test.ts b/packages/neuron-wallet/tests/models/offline-sign.test.ts index bf14a76934..bae1350ee5 100644 --- a/packages/neuron-wallet/tests/models/offline-sign.test.ts +++ b/packages/neuron-wallet/tests/models/offline-sign.test.ts @@ -5,19 +5,19 @@ describe('OfflineSign', () => { transaction: {} as any, type: SignType.Regular, status: SignStatus.Unsigned, - context: [] + context: [], } const jsonWithAssetAccount = { ...json, asset_account: { - tokenID: 'tokenID' - } as any + tokenID: 'tokenID', + } as any, } const allPropsJSON = { ...jsonWithAssetAccount, - description: 'description' + description: 'description', } describe('fromJSON', () => { diff --git a/packages/neuron-wallet/tests/models/synced-block-number.intg.test.ts b/packages/neuron-wallet/tests/models/synced-block-number.intg.test.ts index a3ea0ece65..47d1e8b7fc 100644 --- a/packages/neuron-wallet/tests/models/synced-block-number.intg.test.ts +++ b/packages/neuron-wallet/tests/models/synced-block-number.intg.test.ts @@ -28,15 +28,15 @@ describe('SyncedBlockNumber model', () => { jest.doMock('models/subjects/node', () => { return { getSubject: () => ({ - next: stubbedSyncedBlockNumberSubjectNext - }) + next: stubbedSyncedBlockNumberSubjectNext, + }), } - }); + }) jest.doMock('utils/logger', () => { return { - info: stubbedLoggerInfo + info: stubbedLoggerInfo, } - }); + }) SyncedBlockNumber = require('../../src/models/synced-block-number').default }) @@ -53,19 +53,19 @@ describe('SyncedBlockNumber model', () => { let nextBlock: bigint beforeEach(async () => { nextBlock = await syncedBlockNumber.getNextBlock() - }); + }) it('returns block number 0', () => { expect(nextBlock).toEqual(BigInt(0)) }) - }); + }) describe('#setNextBlock', () => { beforeEach(() => { resetMocks() - }); + }) describe('when setting to a block number having absolute difference with the previous one by less than 10', () => { beforeEach(async () => { await syncedBlockNumber.setNextBlock(BigInt(9)) - }); + }) it('should not update logs', () => { expect(stubbedLoggerInfo).not.toHaveBeenCalled() }) @@ -73,16 +73,16 @@ describe('SyncedBlockNumber model', () => { let nextBlock: bigint beforeEach(async () => { nextBlock = await syncedBlockNumber.getNextBlock() - }); + }) it('returns previous block number', () => { expect(nextBlock).toEqual(BigInt(0)) }) - }); - }); + }) + }) describe('when setting to a block number having absolute difference with the previous one by greater or equals to 10', () => { beforeEach(async () => { await syncedBlockNumber.setNextBlock(BigInt(10)) - }); + }) it('updates logs', () => { expect(stubbedLoggerInfo).toHaveBeenCalled() }) @@ -90,13 +90,12 @@ describe('SyncedBlockNumber model', () => { let nextBlock: bigint beforeEach(async () => { nextBlock = await syncedBlockNumber.getNextBlock() - }); + }) it('returns current block number', () => { expect(nextBlock).toEqual(BigInt(10)) }) - }); - }); - }); - }); - + }) + }) + }) + }) }) diff --git a/packages/neuron-wallet/tests/models/system-script-info.test.ts b/packages/neuron-wallet/tests/models/system-script-info.test.ts index d0d5670162..3ac55ff8f7 100644 --- a/packages/neuron-wallet/tests/models/system-script-info.test.ts +++ b/packages/neuron-wallet/tests/models/system-script-info.test.ts @@ -1,25 +1,24 @@ -import SystemScriptInfo from "../../src/models/system-script-info" +import SystemScriptInfo from '../../src/models/system-script-info' // for regression tests describe('SystemScriptInfo', () => { - const SECP_CODE_HASH = "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8" - const DAO_CODE_HASH = "0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e" - const MULTI_SIGN_CODE_HASH = "0x5c5069eb0857efc65e1bca0c07df34c31663b3622fd3876c876320fc9634e2a8" - + const SECP_CODE_HASH = '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8' + const DAO_CODE_HASH = '0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e' + const MULTI_SIGN_CODE_HASH = '0x5c5069eb0857efc65e1bca0c07df34c31663b3622fd3876c876320fc9634e2a8' const secpScript = SystemScriptInfo.generateSecpScript('0x' + '0'.repeat(40)) const multiSignScript = SystemScriptInfo.generateMultiSignScript('0x' + '0'.repeat(40)) const daoScript = SystemScriptInfo.generateDaoScript('0x') - it("secp code hash", () => { + it('secp code hash', () => { expect(SystemScriptInfo.SECP_CODE_HASH).toEqual(SECP_CODE_HASH) }) - it("dao code hash", () => { + it('dao code hash', () => { expect(SystemScriptInfo.DAO_CODE_HASH).toEqual(DAO_CODE_HASH) }) - it("multi sign code hash", () => { + it('multi sign code hash', () => { expect(SystemScriptInfo.MULTI_SIGN_CODE_HASH).toEqual(MULTI_SIGN_CODE_HASH) }) diff --git a/packages/neuron-wallet/tests/models/transaction-fee.test.ts b/packages/neuron-wallet/tests/models/transaction-fee.test.ts index 3170991c6c..1c15d8a7eb 100644 --- a/packages/neuron-wallet/tests/models/transaction-fee.test.ts +++ b/packages/neuron-wallet/tests/models/transaction-fee.test.ts @@ -2,14 +2,10 @@ import TransactionFee from '../../src/models/transaction-fee' describe('TransactionFee', () => { it('txFee without carry', () => { - expect( - TransactionFee.fee(1035, BigInt(1000)) - ).toEqual(BigInt(1035)) + expect(TransactionFee.fee(1035, BigInt(1000))).toEqual(BigInt(1035)) }) it('txFee with carry', () => { - expect( - TransactionFee.fee(1035, BigInt(900)) - ).toEqual(BigInt(932)) + expect(TransactionFee.fee(1035, BigInt(900))).toEqual(BigInt(932)) }) }) diff --git a/packages/neuron-wallet/tests/models/transaction-size.test.ts b/packages/neuron-wallet/tests/models/transaction-size.test.ts index 18473c1186..de105ce411 100644 --- a/packages/neuron-wallet/tests/models/transaction-size.test.ts +++ b/packages/neuron-wallet/tests/models/transaction-size.test.ts @@ -7,9 +7,13 @@ import Output from '../../src/models/chain/output' describe('TransactionSize', () => { const output = Output.fromObject({ - "capacity": "0x174876e800", - "lock": new Script("0x68d5438ac952d2f584abf879527946a537e82c7f3c1cbf6d8ebf9767437d8e88", "0x59a27ef3ba84f061517d13f42cf44ed020610061", ScriptHashType.Type), - "type": new Script("0xece45e0979030e2f8909f76258631c42333b1e906fd9701ec3600a464a90b8f6", "0x", ScriptHashType.Data), + capacity: '0x174876e800', + lock: new Script( + '0x68d5438ac952d2f584abf879527946a537e82c7f3c1cbf6d8ebf9767437d8e88', + '0x59a27ef3ba84f061517d13f42cf44ed020610061', + ScriptHashType.Type + ), + type: new Script('0xece45e0979030e2f8909f76258631c42333b1e906fd9701ec3600a464a90b8f6', '0x', ScriptHashType.Data), }) const witnessArgs = new WitnessArgs('', '0x', '') @@ -21,7 +25,7 @@ describe('TransactionSize', () => { it('witnessArgs', () => { const result = TransactionSize.witness(witnessArgs) - expect(result).toEqual(HexUtils.byteLength("0x10000000100000001000000010000000") + 4 + 4) + expect(result).toEqual(HexUtils.byteLength('0x10000000100000001000000010000000') + 4 + 4) }) it('witnessArgs only lock', () => { @@ -37,93 +41,87 @@ describe('TransactionSize', () => { }) it('secpLockWitness', () => { - expect( - TransactionSize.secpLockWitness() - ).toEqual(85 + 4 + 4) + expect(TransactionSize.secpLockWitness()).toEqual(85 + 4 + 4) }) it('emptyWitness', () => { - expect( - TransactionSize.emptyWitness() - ).toEqual(4 + 4) + expect(TransactionSize.emptyWitness()).toEqual(4 + 4) }) it('singleMultiSignWitness', () => { // 24 bytes larger than secp, for serialized multi sign script - expect( - TransactionSize.singleMultiSignWitness() - ).toEqual(85 + 20 + 4 + 4 + 4) + expect(TransactionSize.singleMultiSignWitness()).toEqual(85 + 20 + 4 + 4 + 4) }) it('empty outputData', () => { - const data = "0x" + const data = '0x' const length = TransactionSize.outputData(data) expect(length).toEqual(8) }) it('outputData with 0x1234abcd', () => { - const data = "0x1234abcd" + const data = '0x1234abcd' const length = TransactionSize.outputData(data) expect(length).toEqual(12) }) const sdkTx: CKBComponents.Transaction = { - "hash": '', - "version": "0x0", - "cellDeps": [ + hash: '', + version: '0x0', + cellDeps: [ { - "outPoint": { - "txHash": "0xc12386705b5cbb312b693874f3edf45c43a274482e27b8df0fd80c8d3f5feb8b", - "index": "0x0" + outPoint: { + txHash: '0xc12386705b5cbb312b693874f3edf45c43a274482e27b8df0fd80c8d3f5feb8b', + index: '0x0', }, - "depType": "depGroup" + depType: 'depGroup', }, { - "outPoint": { - "txHash": "0x0fb4945d52baf91e0dee2a686cdd9d84cad95b566a1d7409b970ee0a0f364f60", - "index": "0x2" + outPoint: { + txHash: '0x0fb4945d52baf91e0dee2a686cdd9d84cad95b566a1d7409b970ee0a0f364f60', + index: '0x2', }, - "depType": "code" - } + depType: 'code', + }, ], - "headerDeps": [], - "inputs": [ + headerDeps: [], + inputs: [ { - "previousOutput": { - "txHash": "0x31f695263423a4b05045dd25ce6692bb55d7bba2965d8be16b036e138e72cc65", - "index": "0x1" + previousOutput: { + txHash: '0x31f695263423a4b05045dd25ce6692bb55d7bba2965d8be16b036e138e72cc65', + index: '0x1', }, - "since": "0x0" - } + since: '0x0', + }, ], - "outputs": [ + outputs: [ { - "capacity": "0x174876e800", - "lock": { - "codeHash": "0x68d5438ac952d2f584abf879527946a537e82c7f3c1cbf6d8ebf9767437d8e88", - "args": "0x59a27ef3ba84f061517d13f42cf44ed020610061", - "hashType": "type" + capacity: '0x174876e800', + lock: { + codeHash: '0x68d5438ac952d2f584abf879527946a537e82c7f3c1cbf6d8ebf9767437d8e88', + args: '0x59a27ef3ba84f061517d13f42cf44ed020610061', + hashType: 'type', + }, + type: { + codeHash: '0xece45e0979030e2f8909f76258631c42333b1e906fd9701ec3600a464a90b8f6', + args: '0x', + hashType: 'data', }, - "type": { - "codeHash": "0xece45e0979030e2f8909f76258631c42333b1e906fd9701ec3600a464a90b8f6", - "args": "0x", - "hashType": "data" - } }, { - "capacity": "0x59e1416a5000", - "lock": { - "codeHash": "0x68d5438ac952d2f584abf879527946a537e82c7f3c1cbf6d8ebf9767437d8e88", - "args": "0x59a27ef3ba84f061517d13f42cf44ed020610061", - "hashType": "type" + capacity: '0x59e1416a5000', + lock: { + codeHash: '0x68d5438ac952d2f584abf879527946a537e82c7f3c1cbf6d8ebf9767437d8e88', + args: '0x59a27ef3ba84f061517d13f42cf44ed020610061', + hashType: 'type', }, - "type": null - } + type: null, + }, + ], + outputsData: ['0x1234', '0x'], + witnesses: [ + '0x82df73581bcd08cb9aa270128d15e79996229ce8ea9e4f985b49fbf36762c5c37936caf3ea3784ee326f60b8992924fcf496f9503c907982525a3436f01ab32900', ], - "outputsData": ["0x1234", "0x"], - "witnesses": [ - "0x82df73581bcd08cb9aa270128d15e79996229ce8ea9e4f985b49fbf36762c5c37936caf3ea3784ee326f60b8992924fcf496f9503c907982525a3436f01ab32900" - ] } const tx = Transaction.fromSDK(sdkTx) @@ -136,7 +134,9 @@ describe('TransactionSize', () => { const witness = TransactionSize.witness TransactionSize.witness = jest.fn() TransactionSize.multiSignWitness(1, 1, 2) - expect(TransactionSize.witness).toHaveBeenCalledWith(new WitnessArgs('0x00010102' + '0'.repeat(80) + '0'.repeat(130))) + expect(TransactionSize.witness).toHaveBeenCalledWith( + new WitnessArgs('0x00010102' + '0'.repeat(80) + '0'.repeat(130)) + ) TransactionSize.witness = witness }) }) diff --git a/packages/neuron-wallet/tests/services/address.test.ts b/packages/neuron-wallet/tests/services/address.test.ts index 4c5e5a37da..67b2d59fc4 100644 --- a/packages/neuron-wallet/tests/services/address.test.ts +++ b/packages/neuron-wallet/tests/services/address.test.ts @@ -70,18 +70,18 @@ const linkNewCell = async ( jest.mock('services/networks', () => ({ getInstance() { return { - isMainnet: () => true + isMainnet: () => true, } - } + }, })) const stubbedAddressDbChangedSubjectNext = jest.fn() jest.mock('models/subjects/address-db-changed-subject', () => ({ getSubject() { return { - next: stubbedAddressDbChangedSubjectNext + next: stubbedAddressDbChangedSubjectNext, } - } + }, })) describe('integration tests for AddressService', () => { @@ -97,7 +97,7 @@ describe('integration tests for AddressService', () => { address, addressType, addressIndex, - publicKeyHash: AddressParser.toBlake160(address.address) + publicKeyHash: AddressParser.toBlake160(address.address), }) } } @@ -318,7 +318,7 @@ describe('integration tests for AddressService', () => { walletId, publicKey, addressType, - addressIndex + addressIndex, }) generatedAddresses = await AddressService.getAddressesByWalletId(walletId) }) @@ -337,7 +337,7 @@ describe('integration tests for AddressService', () => { walletId, publicKey, addressType, - addressIndex + addressIndex, }) generatedAddresses = await AddressService.getAddressesByWalletId(walletId) }) @@ -401,7 +401,7 @@ describe('integration tests for AddressService', () => { expect.objectContaining({ walletId, addressIndex: 0, - addressType: 0 + addressType: 0, }) ) }) @@ -674,7 +674,7 @@ describe('integration tests for AddressService', () => { receiving.map((addr: any) => { return HdPublicKeyInfo.fromObject({ ...addr, - publicKeyInBlake160: addr.blake160 + publicKeyInBlake160: addr.blake160, }) }) ) @@ -684,7 +684,7 @@ describe('integration tests for AddressService', () => { it('create with more than one wallet', async () => { await expect( AddressService.create({ - addresses: [{ walletId: '1' }, { walletId: '2' }] + addresses: [{ walletId: '1' }, { walletId: '2' }], }) ).rejects.toThrow(new Error('Addresses can only be created for one wallet at a time')) }) @@ -694,12 +694,12 @@ describe('integration tests for AddressService', () => { receiving.map((addr: any) => { return HdPublicKeyInfo.fromObject({ ...addr, - publicKeyInBlake160: addr.blake160 + publicKeyInBlake160: addr.blake160, }) }) ) await AddressService.create({ - addresses: [...receiving, ...change] + addresses: [...receiving, ...change], }) expect(stubbedAddressDbChangedSubjectNext).toHaveBeenCalledTimes(1) }) diff --git a/packages/neuron-wallet/tests/services/anyone-can-pay.test.ts b/packages/neuron-wallet/tests/services/anyone-can-pay.test.ts index ddcb258ef2..bf0b9fe69e 100644 --- a/packages/neuron-wallet/tests/services/anyone-can-pay.test.ts +++ b/packages/neuron-wallet/tests/services/anyone-can-pay.test.ts @@ -1,7 +1,7 @@ import { getConnection } from 'typeorm' import AnyoneCanPayServece from '../../src/services/anyone-can-pay' -import AssetAccountEntity from "../../src/database/chain/entities/asset-account" -import AssetAccount from "../../src/models/asset-account" +import AssetAccountEntity from '../../src/database/chain/entities/asset-account' +import AssetAccount from '../../src/models/asset-account' import { initConnection, closeConnection } from '../setupAndTeardown' import { AcpSendSameAccountError, TargetLockError, TargetOutputNotFoundError } from '../../src/exceptions' import AssetAccountInfo from '../../src/models/asset-account-info' @@ -12,16 +12,16 @@ const addressParseMock = jest.fn() jest.mock('../../src/models/address-parser', () => ({ parse(address: string) { return addressParseMock(address) - } + }, })) const getOneByLockScriptAndTypeScriptMock = jest.fn() jest.mock('../../src/services/live-cell-service', () => ({ getInstance() { return { - getOneByLockScriptAndTypeScript: getOneByLockScriptAndTypeScriptMock + getOneByLockScriptAndTypeScript: getOneByLockScriptAndTypeScriptMock, } - } + }, })) const getNextChangeAddressMock = jest.fn() @@ -29,10 +29,10 @@ jest.mock('../../src/services/wallets', () => ({ getInstance() { return { get: () => ({ - getNextChangeAddress: getNextChangeAddressMock - }) + getNextChangeAddress: getNextChangeAddressMock, + }), } - } + }, })) const generateAnyoneCanPayToCKBTxMock = jest.fn() @@ -45,18 +45,18 @@ jest.mock('../../src/services/tx', () => ({ // @ts-ignore generateAnyoneCanPayToSudtTx: (...args) => generateAnyoneCanPayToSudtTxMock(...args), // @ts-ignore - generateSudtMigrateAcpTx: (...args) => generateSudtMigrateAcpTxMock(...args) - } + generateSudtMigrateAcpTx: (...args) => generateSudtMigrateAcpTxMock(...args), + }, })) const fromObjectMock = jest.fn() jest.mock('../../src/models/chain/output', () => ({ - fromObject: (obj: any) => fromObjectMock(obj) + fromObject: (obj: any) => fromObjectMock(obj), })) const getLiveCellMock = jest.fn() jest.mock('../../src/services/cells', () => ({ - getLiveCell: () => getLiveCellMock() + getLiveCell: () => getLiveCellMock(), })) function mockReset() { @@ -71,15 +71,39 @@ function mockReset() { } describe('anyone-can-pay-service', () => { - const assetAccount = AssetAccountEntity.fromModel(new AssetAccount('tokenId', 'symbol', 'accountName', 'tokenName', '8', '0', '0x62260b4dd406bee8a021185edaa60b7a77f7e99a')) - const ckbAssetAccount = AssetAccountEntity.fromModel(new AssetAccount('CKBytes', 'symbol', 'accountName', 'tokenName', '8', '0', '0xb2b8101595fe0ddeb9f4e1acead6107119497fe6')) + const assetAccount = AssetAccountEntity.fromModel( + new AssetAccount( + 'tokenId', + 'symbol', + 'accountName', + 'tokenName', + '8', + '0', + '0x62260b4dd406bee8a021185edaa60b7a77f7e99a' + ) + ) + const ckbAssetAccount = AssetAccountEntity.fromModel( + new AssetAccount( + 'CKBytes', + 'symbol', + 'accountName', + 'tokenName', + '8', + '0', + '0xb2b8101595fe0ddeb9f4e1acead6107119497fe6' + ) + ) let assetAccountEntity: AssetAccountEntity let ckbAssetAccountEntity: AssetAccountEntity // let sudtTokenInfoEntity beforeAll(async () => { await initConnection() - assetAccountEntity = (await getConnection().manager.save([assetAccount.sudtTokenInfo, assetAccount]))[1] as AssetAccountEntity - ckbAssetAccountEntity = (await getConnection().manager.save([ckbAssetAccount.sudtTokenInfo, ckbAssetAccount]))[1] as AssetAccountEntity + assetAccountEntity = ( + await getConnection().manager.save([assetAccount.sudtTokenInfo, assetAccount]) + )[1] as AssetAccountEntity + ckbAssetAccountEntity = ( + await getConnection().manager.save([ckbAssetAccount.sudtTokenInfo, ckbAssetAccount]) + )[1] as AssetAccountEntity }) afterAll(() => { @@ -92,23 +116,46 @@ describe('anyone-can-pay-service', () => { describe('generateAnyoneCanPayTx', () => { it('exception no asset account', async () => { - await expect(AnyoneCanPayServece.generateAnyoneCanPayTx('walletId', 'targetAddress', 'capacityOrAmount', 1000)).rejects.toThrow(new Error('Asset Account not found!')) + await expect( + AnyoneCanPayServece.generateAnyoneCanPayTx('walletId', 'targetAddress', 'capacityOrAmount', 1000) + ).rejects.toThrow(new Error('Asset Account not found!')) }) it('exception AcpSendSameAccountError', async () => { addressParseMock.mockReturnValueOnce({ args: assetAccount.blake160 }) - await expect(AnyoneCanPayServece.generateAnyoneCanPayTx('walletId', 'targetAddress', 'capacityOrAmount', assetAccountEntity.id)).rejects.toThrow(new AcpSendSameAccountError()) + await expect( + AnyoneCanPayServece.generateAnyoneCanPayTx( + 'walletId', + 'targetAddress', + 'capacityOrAmount', + assetAccountEntity.id + ) + ).rejects.toThrow(new AcpSendSameAccountError()) }) it('exception with TargetOutputNotFoundError', async () => { getOneByLockScriptAndTypeScriptMock.mockResolvedValueOnce(undefined) const anyonePayScript = new AssetAccountInfo().generateAnyoneCanPayScript(assetAccount.blake160) addressParseMock.mockReturnValueOnce(anyonePayScript) - await expect(AnyoneCanPayServece.generateAnyoneCanPayTx('walletId', 'anyoneCanPayAddress', 'capacityOrAmount', ckbAssetAccountEntity.id)).rejects.toThrow(new TargetOutputNotFoundError()) + await expect( + AnyoneCanPayServece.generateAnyoneCanPayTx( + 'walletId', + 'anyoneCanPayAddress', + 'capacityOrAmount', + ckbAssetAccountEntity.id + ) + ).rejects.toThrow(new TargetOutputNotFoundError()) }) it('exception with TargetLockError', async () => { getOneByLockScriptAndTypeScriptMock.mockResolvedValueOnce(undefined) const anyonePayScript = new AssetAccountInfo().generateChequeScript(assetAccount.blake160, assetAccount.blake160) addressParseMock.mockReturnValueOnce(anyonePayScript) - await expect(AnyoneCanPayServece.generateAnyoneCanPayTx('walletId', 'anyoneCanPayAddress', 'capacityOrAmount', ckbAssetAccountEntity.id)).rejects.toThrow(new TargetLockError()) + await expect( + AnyoneCanPayServece.generateAnyoneCanPayTx( + 'walletId', + 'anyoneCanPayAddress', + 'capacityOrAmount', + ckbAssetAccountEntity.id + ) + ).rejects.toThrow(new TargetLockError()) }) it('isSecpScript with ckb', async () => { const targetLockScript = SystemScriptInfo.generateSecpScript(assetAccount.blake160) @@ -119,11 +166,16 @@ describe('anyone-can-pay-service', () => { generateAnyoneCanPayToCKBTxMock.mockReturnValueOnce({}) const output = {} fromObjectMock.mockReturnValueOnce(output) - await AnyoneCanPayServece.generateAnyoneCanPayTx('walletId', 'targetAddress', 'capacityOrAmount', ckbAssetAccountEntity.id) + await AnyoneCanPayServece.generateAnyoneCanPayTx( + 'walletId', + 'targetAddress', + 'capacityOrAmount', + ckbAssetAccountEntity.id + ) expect(fromObjectMock).toHaveBeenCalledWith({ capacity: '0', lock: targetLockScript, - type: null + type: null, }) expect(generateAnyoneCanPayToCKBTxMock).toHaveBeenCalledWith( 'walletId', @@ -144,11 +196,16 @@ describe('anyone-can-pay-service', () => { generateAnyoneCanPayToSudtTxMock.mockReturnValueOnce({}) const output = {} fromObjectMock.mockReturnValueOnce(output) - await AnyoneCanPayServece.generateAnyoneCanPayTx('walletId', 'targetAddress', 'capacityOrAmount', assetAccountEntity.id) + await AnyoneCanPayServece.generateAnyoneCanPayTx( + 'walletId', + 'targetAddress', + 'capacityOrAmount', + assetAccountEntity.id + ) expect(fromObjectMock).toHaveBeenCalledWith({ capacity: BigInt(MIN_SUDT_CAPACITY).toString(), lock: targetLockScript, - type: new AssetAccountInfo().generateSudtScript(assetAccount.tokenID) + type: new AssetAccountInfo().generateSudtScript(assetAccount.tokenID), }) expect(generateAnyoneCanPayToSudtTxMock).toHaveBeenCalledWith( 'walletId', @@ -165,7 +222,9 @@ describe('anyone-can-pay-service', () => { describe('generateSudtMigrateAcpTx', () => { it('exception', async () => { getLiveCellMock.mockResolvedValueOnce(undefined) - await expect(AnyoneCanPayServece.generateSudtMigrateAcpTx({ txHash: '', index: '0' })).rejects.toThrow(new Error('sudt live cell not found')) + await expect(AnyoneCanPayServece.generateSudtMigrateAcpTx({ txHash: '', index: '0' })).rejects.toThrow( + new Error('sudt live cell not found') + ) }) it('normal', async () => { const cell = {} @@ -182,7 +241,7 @@ describe('anyone-can-pay-service', () => { expect(fromObjectMock).toHaveBeenCalledWith({ capacity: '0', lock: SystemScriptInfo.generateSecpScript(assetAccount.blake160), - type: null + type: null, }) }) it('send to anyone pay address not exist', async () => { @@ -195,26 +254,36 @@ describe('anyone-can-pay-service', () => { it('send to anyone pay address exist', async () => { const targetLiveCell = { capacity: '1000', - lock() { return {} }, - type() { return {} }, + lock() { + return {} + }, + type() { + return {} + }, data: '0x00', - outPoint() { return {}} + outPoint() { + return {} + }, } getOneByLockScriptAndTypeScriptMock.mockResolvedValue(targetLiveCell) //@ts-ignore - await AnyoneCanPayServece.getCKBTargetOutput(new AssetAccountInfo().generateAnyoneCanPayScript(assetAccount.blake160)) + await AnyoneCanPayServece.getCKBTargetOutput( + new AssetAccountInfo().generateAnyoneCanPayScript(assetAccount.blake160) + ) expect(fromObjectMock).toHaveBeenCalledWith({ capacity: targetLiveCell.capacity, lock: targetLiveCell.lock(), type: targetLiveCell.type(), data: targetLiveCell.data, - outPoint: targetLiveCell.outPoint() + outPoint: targetLiveCell.outPoint(), }) }) it('send to unknow address', async () => { await expect( //@ts-ignore private-method - AnyoneCanPayServece.getCKBTargetOutput(new AssetAccountInfo().generateChequeScript(assetAccount.blake160, assetAccount.blake160)) + AnyoneCanPayServece.getCKBTargetOutput( + new AssetAccountInfo().generateChequeScript(assetAccount.blake160, assetAccount.blake160) + ) ).rejects.toThrow(new TargetLockError()) }) }) @@ -222,40 +291,55 @@ describe('anyone-can-pay-service', () => { describe('getSUDTTargetOutput', () => { it('send to secp256', async () => { //@ts-ignore - await AnyoneCanPayServece.getSUDTTargetOutput(SystemScriptInfo.generateSecpScript(assetAccount.blake160), 'tokenID') + await AnyoneCanPayServece.getSUDTTargetOutput( + SystemScriptInfo.generateSecpScript(assetAccount.blake160), + 'tokenID' + ) expect(fromObjectMock).toHaveBeenCalledWith({ capacity: BigInt(MIN_SUDT_CAPACITY).toString(), lock: SystemScriptInfo.generateSecpScript(assetAccount.blake160), - type: new AssetAccountInfo().generateSudtScript('tokenID') + type: new AssetAccountInfo().generateSudtScript('tokenID'), }) }) it('send to anyone pay address not exist', async () => { getOneByLockScriptAndTypeScriptMock.mockResolvedValue(undefined) //@ts-ignore - await AnyoneCanPayServece.getSUDTTargetOutput(new AssetAccountInfo().generateAnyoneCanPayScript(assetAccount.blake160), 'tokenID') + await AnyoneCanPayServece.getSUDTTargetOutput( + new AssetAccountInfo().generateAnyoneCanPayScript(assetAccount.blake160), + 'tokenID' + ) expect(fromObjectMock).toHaveBeenCalledWith({ capacity: BigInt(MIN_SUDT_CAPACITY).toString(), lock: new AssetAccountInfo().generateAnyoneCanPayScript(assetAccount.blake160), - type: new AssetAccountInfo().generateSudtScript('tokenID') + type: new AssetAccountInfo().generateSudtScript('tokenID'), }) }) it('send to anyone pay address exist', async () => { const targetLiveCell = { capacity: '1000', - lock() { return {} }, - type() { return {} }, + lock() { + return {} + }, + type() { + return {} + }, data: '0x00', - outPoint() { return {}} + outPoint() { + return {} + }, } getOneByLockScriptAndTypeScriptMock.mockResolvedValue(targetLiveCell) //@ts-ignore - await AnyoneCanPayServece.getSUDTTargetOutput(new AssetAccountInfo().generateAnyoneCanPayScript(assetAccount.blake160), 'tokenID') + await AnyoneCanPayServece.getSUDTTargetOutput( + new AssetAccountInfo().generateAnyoneCanPayScript(assetAccount.blake160), + 'tokenID' + ) expect(fromObjectMock).toHaveBeenCalledWith({ capacity: targetLiveCell.capacity, lock: targetLiveCell.lock(), type: targetLiveCell.type(), data: targetLiveCell.data, - outPoint: targetLiveCell.outPoint() + outPoint: targetLiveCell.outPoint(), }) }) it('send to unknow address', async () => { @@ -266,34 +350,49 @@ describe('anyone-can-pay-service', () => { expect(fromObjectMock).toHaveBeenCalledWith({ capacity: BigInt(162 * 10 ** 8).toString(), lock: new AssetAccountInfo().generateChequeScript(args, args), - type: new AssetAccountInfo().generateSudtScript('tokenID') + type: new AssetAccountInfo().generateSudtScript('tokenID'), }) }) }) describe('getHoldSUDTCellCapacity', () => { it('is secp256 address', async () => { - const res = await AnyoneCanPayServece.getHoldSUDTCellCapacity(SystemScriptInfo.generateSecpScript(assetAccount.blake160), '0x00') + const res = await AnyoneCanPayServece.getHoldSUDTCellCapacity( + SystemScriptInfo.generateSecpScript(assetAccount.blake160), + '0x00' + ) expect(res).toBe(undefined) }) it('CKB acp', async () => { - const res = await AnyoneCanPayServece.getHoldSUDTCellCapacity(new AssetAccountInfo().generateAnyoneCanPayScript(assetAccount.blake160), 'CKBytes') + const res = await AnyoneCanPayServece.getHoldSUDTCellCapacity( + new AssetAccountInfo().generateAnyoneCanPayScript(assetAccount.blake160), + 'CKBytes' + ) expect(res).toBe(undefined) }) it('acp cell exist', async () => { getOneByLockScriptAndTypeScriptMock.mockResolvedValue({}) - const res = await AnyoneCanPayServece.getHoldSUDTCellCapacity(new AssetAccountInfo().generateAnyoneCanPayScript(assetAccount.blake160), '0x00') + const res = await AnyoneCanPayServece.getHoldSUDTCellCapacity( + new AssetAccountInfo().generateAnyoneCanPayScript(assetAccount.blake160), + '0x00' + ) expect(res).toBe(undefined) }) it('acp cell not exist', async () => { getOneByLockScriptAndTypeScriptMock.mockResolvedValue(undefined) - const res = await AnyoneCanPayServece.getHoldSUDTCellCapacity(new AssetAccountInfo().generateAnyoneCanPayScript(assetAccount.blake160), '0x00') + const res = await AnyoneCanPayServece.getHoldSUDTCellCapacity( + new AssetAccountInfo().generateAnyoneCanPayScript(assetAccount.blake160), + '0x00' + ) expect(res).toBe(BigInt(MIN_SUDT_CAPACITY).toString()) }) it('unknow lock not exist', async () => { getOneByLockScriptAndTypeScriptMock.mockResolvedValue(undefined) - const res = await AnyoneCanPayServece.getHoldSUDTCellCapacity(new AssetAccountInfo().generateChequeScript(assetAccount.blake160, assetAccount.blake160), '0x00') + const res = await AnyoneCanPayServece.getHoldSUDTCellCapacity( + new AssetAccountInfo().generateChequeScript(assetAccount.blake160, assetAccount.blake160), + '0x00' + ) expect(res).toBe(BigInt(162 * 10 ** 8).toString()) }) }) -}) \ No newline at end of file +}) diff --git a/packages/neuron-wallet/tests/services/asset-account-service.test.ts b/packages/neuron-wallet/tests/services/asset-account-service.test.ts index 56f77e4128..e2b29cb083 100644 --- a/packages/neuron-wallet/tests/services/asset-account-service.test.ts +++ b/packages/neuron-wallet/tests/services/asset-account-service.test.ts @@ -103,8 +103,8 @@ const walletId = 'w1' jest.mock('services/wallets', () => { return { getInstance: () => ({ - get: stubbedWalletServiceGet - }) + get: stubbedWalletServiceGet, + }), } }) jest.mock('services/tx', () => { @@ -118,14 +118,14 @@ jest.mock('services/tx', () => { // @ts-ignore generateWithdrawChequeTx: (...args) => stubbedGenerateWithdrawChequeTx(...args), // @ts-ignore - generateDestoryAssetAccountTx: (...args) => stubbedGenerateDestoryAssetAccountTx(...args) - } + generateDestoryAssetAccountTx: (...args) => stubbedGenerateDestoryAssetAccountTx(...args), + }, } }) jest.mock('services/transaction-sender', () => { - return function() { + return function () { return { - sendTx: stubbedTransactionSendersendTx + sendTx: stubbedTransactionSendersendTx, } } }) @@ -150,7 +150,7 @@ describe('AssetAccountService', () => { walletId, addressType: AddressType.Receiving, addressIndex: 0, - publicKeyInBlake160: blake160 + publicKeyInBlake160: blake160, }) await connection.manager.save(keyInfo) @@ -160,10 +160,7 @@ describe('AssetAccountService', () => { const entity = AssetAccountEntity.fromModel(assetAccount) const saved = await getConnection().manager.save([entity.sudtTokenInfo, entity]) - const sudtTokenInfoCount = await getConnection() - .getRepository(SudtTokenInfo) - .createQueryBuilder('s') - .getCount() + const sudtTokenInfoCount = await getConnection().getRepository(SudtTokenInfo).createQueryBuilder('s').getCount() const assetAccountCount = await getConnection() .getRepository(AssetAccountEntity) @@ -268,7 +265,7 @@ describe('AssetAccountService', () => { decimal: '0', balance: '0', accountName: 'sUDT', - blake160 + blake160, }), AssetAccount.fromObject({ tokenID: 'CKBytes', @@ -277,14 +274,14 @@ describe('AssetAccountService', () => { decimal: '0', balance: '0', accountName: 'ckb', - blake160 - }) + blake160, + }), ] const outputs = [ generateOutput(undefined, undefined, undefined, toShannon(1000)), generateOutput(undefined, undefined, undefined, toShannon(1000)), generateOutput(tokenID), - generateOutput(tokenID) + generateOutput(tokenID), ] await createAccounts(assetAccounts, outputs) }) @@ -306,7 +303,7 @@ describe('AssetAccountService', () => { decimal: '0', balance: '0', accountName: 'sUDT', - blake160 + blake160, }), AssetAccount.fromObject({ tokenID: 'CKBytes', @@ -315,14 +312,14 @@ describe('AssetAccountService', () => { decimal: '0', balance: '0', accountName: 'ckb', - blake160 - }) + blake160, + }), ] const outputs = [ generateOutput(undefined, undefined, undefined, toShannon(1000)), generateOutput(undefined, undefined, undefined, toShannon(1000), undefined, undefined, OutputStatus.Sent), generateOutput(tokenID), - generateOutput(tokenID, undefined, undefined, undefined, undefined, undefined, OutputStatus.Sent) + generateOutput(tokenID, undefined, undefined, undefined, undefined, undefined, OutputStatus.Sent), ] await createAccounts(assetAccounts, outputs) }) @@ -347,8 +344,8 @@ describe('AssetAccountService', () => { decimal: '0', balance: '0', accountName: 'ckb', - blake160 - }) + blake160, + }), ] const outputs = [generateOutput(undefined, undefined, undefined, minCapacity)] await createAccounts(assetAccounts, outputs) @@ -370,8 +367,8 @@ describe('AssetAccountService', () => { decimal: '0', balance: '0', accountName: 'ckb', - blake160 - }) + blake160, + }), ] const outputs: OutputEntity[] = [] await createAccounts(assetAccounts, outputs) @@ -392,13 +389,13 @@ describe('AssetAccountService', () => { decimal: '0', balance: '0', accountName: 'ckb', - blake160 - }) + blake160, + }), ] const customData = '0x00' const outputs = [ generateOutput(undefined, undefined, undefined, toShannon(1000)), - generateOutput(undefined, undefined, undefined, toShannon(2000), undefined, customData) + generateOutput(undefined, undefined, undefined, toShannon(2000), undefined, customData), ] await createAccounts(assetAccounts, outputs) }) @@ -421,12 +418,12 @@ describe('AssetAccountService', () => { decimal: '0', balance: '0', accountName: 'ckb', - blake160 - }) + blake160, + }), ] const outputs = [ generateOutput(undefined, undefined, undefined, minCapacity), - generateOutput(undefined, undefined, undefined, toShannon(100)) + generateOutput(undefined, undefined, undefined, toShannon(100)), ] await createAccounts(assetAccounts, outputs) }) @@ -450,8 +447,8 @@ describe('AssetAccountService', () => { decimal: '0', balance: '0', accountName: 'sUDT', - blake160 - }) + blake160, + }), ] const outputs = [generateOutput(tokenID, undefined, undefined, minCapacity, '0')] await createAccounts(assetAccounts, outputs) @@ -476,7 +473,7 @@ describe('AssetAccountService', () => { decimal: '0', balance: '0', accountName: 'sUDT', - blake160 + blake160, }), AssetAccount.fromObject({ tokenID: 'CKBytes', @@ -485,8 +482,8 @@ describe('AssetAccountService', () => { decimal: '0', balance: '0', accountName: 'ckb', - blake160 - }) + blake160, + }), ] const outputs: any[] = [] await createAccounts(assetAccounts, outputs) @@ -511,7 +508,7 @@ describe('AssetAccountService', () => { decimal: '0', balance: '0', accountName: 'sUDT', - blake160 + blake160, }), AssetAccount.fromObject({ tokenID: 'CKBytes', @@ -520,14 +517,14 @@ describe('AssetAccountService', () => { decimal: '0', balance: '0', accountName: 'ckb', - blake160 - }) + blake160, + }), ] const outputs = [ generateOutput(undefined, undefined, undefined, toShannon(1000)), generateOutput(undefined, undefined, undefined, toShannon(1000)), generateOutput(tokenID), - generateOutput(tokenID) + generateOutput(tokenID), ] accountIds = await createAccounts(assetAccounts, outputs) }) @@ -561,8 +558,8 @@ describe('AssetAccountService', () => { decimal: '0', balance: '0', accountName: 'ckb', - blake160 - }) + blake160, + }), ] const outputs = [generateOutput(undefined, undefined, undefined, minCapacity)] accountIds = await createAccounts(assetAccounts, outputs) @@ -589,8 +586,8 @@ describe('AssetAccountService', () => { decimal: '0', balance: '0', accountName: 'ckb', - blake160 - }) + blake160, + }), ] const outputs = [generateOutput(undefined, undefined, undefined, minCapacity)] accountIds = await createAccounts(assetAccounts, outputs) @@ -618,12 +615,12 @@ describe('AssetAccountService', () => { decimal: '0', balance: '0', accountName: 'ckb', - blake160 - }) + blake160, + }), ] const outputs = [ generateOutput(undefined, undefined, undefined, minCapacity), - generateOutput(undefined, undefined, undefined, toShannon(100)) + generateOutput(undefined, undefined, undefined, toShannon(100)), ] accountIds = await createAccounts(assetAccounts, outputs) }) @@ -649,13 +646,13 @@ describe('AssetAccountService', () => { decimal: '0', balance: '0', accountName: 'ckb', - blake160 - }) + blake160, + }), ] const customData = '0x00' const outputs = [ generateOutput(undefined, undefined, undefined, toShannon(1000)), - generateOutput(undefined, undefined, undefined, toShannon(2000), undefined, customData) + generateOutput(undefined, undefined, undefined, toShannon(2000), undefined, customData), ] accountIds = await createAccounts(assetAccounts, outputs) }) @@ -721,7 +718,7 @@ describe('AssetAccountService', () => { .getRepository(SudtTokenInfoEntity) .createQueryBuilder('info') .where({ - tokenID: assetAccount.tokenID + tokenID: assetAccount.tokenID, }) .getOne() expect(tokenInfo).not.toBeNull() @@ -749,7 +746,7 @@ describe('AssetAccountService', () => { .createQueryBuilder('aa') .leftJoinAndSelect('aa.sudtTokenInfo', 'info') .where({ - tokenID: assetAccount.tokenID + tokenID: assetAccount.tokenID, }) .getOne() expect(aae).not.toBeNull() @@ -784,7 +781,7 @@ describe('AssetAccountService', () => { decimal: '0', balance: '0', accountName: 'ckb', - blake160 + blake160, }), AssetAccount.fromObject({ tokenID: tokenID, @@ -793,8 +790,8 @@ describe('AssetAccountService', () => { decimal: '0', balance: '0', accountName: 'udt', - blake160 - }) + blake160, + }), ] for (const aa of assetAccounts) { @@ -808,7 +805,7 @@ describe('AssetAccountService', () => { generateOutput('CKBytes', TransactionStatus.Success, '1'), generateOutput('CKBytes', TransactionStatus.Success, '2'), generateOutput(tokenID, TransactionStatus.Success, '1'), - generateOutput(tokenID, TransactionStatus.Success, '2') + generateOutput(tokenID, TransactionStatus.Success, '2'), ] for (const e of outputEntities) { await getConnection().manager.save([e.transaction, e]) @@ -816,10 +813,7 @@ describe('AssetAccountService', () => { await AssetAccountService.checkAndDeleteWhenFork('1', anyoneCanPayLockHashes) - const result = await getConnection() - .getRepository(AssetAccountEntity) - .createQueryBuilder('aa') - .getMany() + const result = await getConnection().getRepository(AssetAccountEntity).createQueryBuilder('aa').getMany() expect(result.length).toEqual(0) }) @@ -829,7 +823,7 @@ describe('AssetAccountService', () => { generateOutput('CKBytes', TransactionStatus.Success, '1'), generateOutput('CKBytes', TransactionStatus.Success, '2'), generateOutput(tokenID, TransactionStatus.Success, '2'), - generateOutput(tokenID, TransactionStatus.Success, '3') + generateOutput(tokenID, TransactionStatus.Success, '3'), ] for (const e of outputEntities) { await getConnection().manager.save([e.transaction, e]) @@ -837,10 +831,7 @@ describe('AssetAccountService', () => { await AssetAccountService.checkAndDeleteWhenFork('2', anyoneCanPayLockHashes) - const result = await getConnection() - .getRepository(AssetAccountEntity) - .createQueryBuilder('aa') - .getMany() + const result = await getConnection().getRepository(AssetAccountEntity).createQueryBuilder('aa').getMany() expect(result.length).toEqual(1) expect(result[0].tokenID).toEqual('CKBytes') @@ -851,7 +842,7 @@ describe('AssetAccountService', () => { generateOutput('CKBytes', TransactionStatus.Success, '1'), generateOutput('CKBytes', TransactionStatus.Pending, '2'), generateOutput(tokenID, TransactionStatus.Success, '1'), - generateOutput(tokenID, TransactionStatus.Success, '2') + generateOutput(tokenID, TransactionStatus.Success, '2'), ] for (const e of outputEntities) { await getConnection().manager.save([e.transaction, e]) @@ -859,10 +850,7 @@ describe('AssetAccountService', () => { await AssetAccountService.checkAndDeleteWhenFork('1', anyoneCanPayLockHashes) - const result = await getConnection() - .getRepository(AssetAccountEntity) - .createQueryBuilder('aa') - .getMany() + const result = await getConnection().getRepository(AssetAccountEntity).createQueryBuilder('aa').getMany() expect(result.length).toEqual(1) expect(result[0].tokenID).toEqual('CKBytes') @@ -873,7 +861,7 @@ describe('AssetAccountService', () => { generateOutput('CKBytes', TransactionStatus.Success, '2'), generateOutput('CKBytes', TransactionStatus.Success, '3'), generateOutput(tokenID, TransactionStatus.Success, '1'), - generateOutput(tokenID, TransactionStatus.Success, '2') + generateOutput(tokenID, TransactionStatus.Success, '2'), ] for (const e of outputEntities) { await getConnection().manager.save([e.transaction, e]) @@ -881,10 +869,7 @@ describe('AssetAccountService', () => { await AssetAccountService.checkAndDeleteWhenFork('2', anyoneCanPayLockHashes) - const result = await getConnection() - .getRepository(AssetAccountEntity) - .createQueryBuilder('aa') - .getMany() + const result = await getConnection().getRepository(AssetAccountEntity).createQueryBuilder('aa').getMany() expect(result.length).toEqual(1) expect(result[0].tokenID).toEqual(tokenID) @@ -895,7 +880,7 @@ describe('AssetAccountService', () => { generateOutput('CKBytes', TransactionStatus.Success, '1'), generateOutput('CKBytes', TransactionStatus.Success, '2'), generateOutput(tokenID, TransactionStatus.Success, '1'), - generateOutput(tokenID, TransactionStatus.Success, '2') + generateOutput(tokenID, TransactionStatus.Success, '2'), ] for (const e of outputEntities) { await getConnection().manager.save([e.transaction, e]) @@ -903,10 +888,7 @@ describe('AssetAccountService', () => { await AssetAccountService.checkAndDeleteWhenFork('3', anyoneCanPayLockHashes) - const result = await getConnection() - .getRepository(AssetAccountEntity) - .createQueryBuilder('aa') - .getMany() + const result = await getConnection().getRepository(AssetAccountEntity).createQueryBuilder('aa').getMany() expect(result.length).toEqual(2) }) @@ -919,20 +901,20 @@ describe('AssetAccountService', () => { tokenID: 'CKBytes', symbol: 'ckb', tokenName: 'ckb', - decimal: '0' + decimal: '0', }, { tokenID: tokenID, symbol: 'udt', tokenName: 'udt', - decimal: '0' + decimal: '0', }, { tokenID: 'invalid token info', symbol: '', tokenName: '', - decimal: '' - } + decimal: '', + }, ] const repo = getConnection().getRepository(SudtTokenInfoEntity) await repo.save(tokens) @@ -964,7 +946,7 @@ describe('AssetAccountService', () => { const description = 'desc' const fakeWallet = { - getNextChangeAddress: () => changeAddressObj + getNextChangeAddress: () => changeAddressObj, } beforeEach(async () => { @@ -975,7 +957,7 @@ describe('AssetAccountService', () => { decimal: '0', balance: '0', accountName: 'udt', - blake160 + blake160, }) const e = AssetAccountEntity.fromModel(assetAccount) @@ -1015,7 +997,7 @@ describe('AssetAccountService', () => { const address = 'address' const fakeWallet = { getNextChangeAddress: () => ({ address }), - getAllAddresses: stubbedGetAllAddresses + getAllAddresses: stubbedGetAllAddresses, } const expectedAssetAccount = new AssetAccount( '0x0000000000000000000000000000000000000000000000000000000000000000', @@ -1053,7 +1035,7 @@ describe('AssetAccountService', () => { .mockResolvedValue(tx) fakeChequeCellOutPoint = OutPoint.fromObject({ txHash: output.transaction.hash, - index: '0x0' + index: '0x0', }) }) describe('without existing acp', () => { @@ -1073,7 +1055,7 @@ describe('AssetAccountService', () => { decimal: '0', balance: '0', accountName: 'udt', - blake160 + blake160, }) const e = AssetAccountEntity.fromModel(assetAccount) @@ -1094,7 +1076,7 @@ describe('AssetAccountService', () => { await getConnection().manager.save([output.transaction, output]) fakeChequeCellOutPoint = OutPoint.fromObject({ txHash: output.transaction.hash, - index: '0x0' + index: '0x0', }) await AssetAccountService.generateWithdrawChequeTx(fakeChequeCellOutPoint) }) @@ -1103,8 +1085,8 @@ describe('AssetAccountService', () => { expect.objectContaining({ outPoint: { index: '0', - txHash: fakeChequeCellOutPoint.txHash - } + txHash: fakeChequeCellOutPoint.txHash, + }, }), undefined, '1000' @@ -1121,7 +1103,7 @@ describe('AssetAccountService', () => { decimal: '0', balance: '0', accountName: 'ckb', - blake160 + blake160, }) const outputs = [generateOutput('CKBytes', undefined, undefined, toShannon(1000))] await createAccounts([assetAccount], outputs) @@ -1139,8 +1121,8 @@ describe('AssetAccountService', () => { lockHash: outputs[0].lockHash, typeHash: outputs[0].typeHash, data: outputs[0].data, - since: '0' - }) + since: '0', + }), ], 'blake160', true @@ -1154,7 +1136,7 @@ describe('AssetAccountService', () => { decimal: '0', balance: '0', accountName: 'sudt', - blake160 + blake160, }) const outputs = [generateOutput(assetAccount.tokenID, undefined, undefined, toShannon(1000))] await createAccounts([assetAccount], outputs) @@ -1172,8 +1154,8 @@ describe('AssetAccountService', () => { lockHash: outputs[0].lockHash, typeHash: outputs[0].typeHash, data: outputs[0].data, - since: '0' - }) + since: '0', + }), ], 'blake160', false @@ -1194,14 +1176,14 @@ describe('AssetAccountService', () => { undefined, OutputStatus.Live, assetAccountInfo.generateAnyoneCanPayScript(alice.publicKeyInBlake160) - ) + ), ] await createAccounts(accounts, outputs) }) describe('hd wallet', () => { it('exception with Asset account already exists!', async () => { stubbedWalletServiceGet.mockReturnValueOnce({ - isHardware: () => false + isHardware: () => false, }) await expect(AssetAccountService.sendTx('walletID', assetAccount)).rejects.toThrow( new Error('Asset account already exists!') @@ -1212,7 +1194,7 @@ describe('AssetAccountService', () => { it('no next address', async () => { stubbedWalletServiceGet.mockReturnValueOnce({ isHardware: () => true, - getNextAddress: () => undefined + getNextAddress: () => undefined, }) await AssetAccountService.sendTx( 'walletID', @@ -1223,7 +1205,7 @@ describe('AssetAccountService', () => { decimal: '0', balance: '0', accountName: 'sUDT', - blake160: alice.publicKeyInBlake160 + blake160: alice.publicKeyInBlake160, }), {}, 'password' @@ -1234,7 +1216,7 @@ describe('AssetAccountService', () => { .createQueryBuilder() .where({ tokenID, - blake160: alice.publicKeyInBlake160 + blake160: alice.publicKeyInBlake160, }) .getCount() expect(count).toBe(1) @@ -1242,7 +1224,7 @@ describe('AssetAccountService', () => { it('exception with Asset account already exists!', async () => { stubbedWalletServiceGet.mockReturnValueOnce({ isHardware: () => true, - getNextAddress: () => ({ blake160: alice.publicKeyInBlake160, tokenID: assetAccount.tokenID }) + getNextAddress: () => ({ blake160: alice.publicKeyInBlake160, tokenID: assetAccount.tokenID }), }) await expect(AssetAccountService.sendTx('walletID', assetAccount)).rejects.toThrow( new Error('Asset account already exists!') @@ -1251,7 +1233,7 @@ describe('AssetAccountService', () => { it('no acp cell and delete outdate account', async () => { stubbedWalletServiceGet.mockReturnValueOnce({ isHardware: () => true, - getNextAddress: () => ({ blake160: bob.publicKeyInBlake160, tokenID: assetAccount.tokenID }) + getNextAddress: () => ({ blake160: bob.publicKeyInBlake160, tokenID: assetAccount.tokenID }), }) await AssetAccountService.sendTx('walletID', assetAccount, {}, 'password') expect(stubbedTransactionSendersendTx).toHaveBeenCalledWith('walletID', {}, 'password', false, false) @@ -1260,7 +1242,7 @@ describe('AssetAccountService', () => { .createQueryBuilder() .where({ tokenID: assetAccount.tokenID, - blake160: assetAccount.blake160 + blake160: assetAccount.blake160, }) .getCount() expect(count).toBe(1) @@ -1276,7 +1258,7 @@ describe('AssetAccountService', () => { decimal: '0', balance: '0', accountName: 'sUDT', - blake160: alice.publicKeyInBlake160 + blake160: alice.publicKeyInBlake160, }), {}, 'password' @@ -1287,7 +1269,7 @@ describe('AssetAccountService', () => { .createQueryBuilder() .where({ tokenID, - blake160: alice.publicKeyInBlake160 + blake160: alice.publicKeyInBlake160, }) .getCount() expect(count).toBe(1) diff --git a/packages/neuron-wallet/tests/services/cells.test.ts b/packages/neuron-wallet/tests/services/cells.test.ts index 96cf6bfb88..09ba116676 100644 --- a/packages/neuron-wallet/tests/services/cells.test.ts +++ b/packages/neuron-wallet/tests/services/cells.test.ts @@ -36,9 +36,9 @@ const getManyByLockScriptsAndTypeScriptMock = jest.fn() jest.mock('../../src/services/live-cell-service', () => ({ getInstance() { return { - getManyByLockScriptsAndTypeScript: getManyByLockScriptsAndTypeScriptMock + getManyByLockScriptsAndTypeScript: getManyByLockScriptsAndTypeScriptMock, } - } + }, })) function resetMock() { @@ -55,7 +55,7 @@ describe('CellsService', () => { lockHash: aliceLockScript.computeHash(), address: scriptToAddress(aliceLockScript, false), blake160: alicePublicKeyHash, - walletId: walletId1 + walletId: walletId1, } const bobPublicKeyHash = '0x36c329ed630d6ce750712a477543672adab57f4c' @@ -65,7 +65,7 @@ describe('CellsService', () => { lockHash: bobLockScript.computeHash(), address: scriptToAddress(bobLockScript, false), blake160: bobPublicKeyHash, - walletId: walletId1 + walletId: walletId1, } const multisigPublicKeyHash = '0x447ff8941a6f0162d2194e9b592bb2534a3e6b74' @@ -75,7 +75,7 @@ describe('CellsService', () => { lockHash: multisigLockScript.computeHash(), address: scriptToAddress(multisigLockScript, false), blake160: multisigPublicKeyHash, - walletId: walletId1 + walletId: walletId1, } const charliePublicKeyHash = '0xe2193df51d78411601796b35b17b4f8f2cd80000' @@ -85,7 +85,7 @@ describe('CellsService', () => { lockHash: charlieLockScript.computeHash(), address: scriptToAddress(charlieLockScript, false), blake160: charliePublicKeyHash, - walletId: walletId2 + walletId: walletId2, } beforeAll(async () => { @@ -106,7 +106,7 @@ describe('CellsService', () => { walletId: d.walletId, publicKeyInBlake160: d.lockScript.args, addressType: 0, - addressIndex: 0 + addressIndex: 0, }) ) @@ -216,7 +216,7 @@ describe('CellsService', () => { generateCell('10000', OutputStatus.Live, false, typeScript), generateCell('20000', OutputStatus.Sent, false, typeScript), generateCell('30000', OutputStatus.Pending, false, typeScript), - generateCell('40000', OutputStatus.Dead, false, typeScript) + generateCell('40000', OutputStatus.Dead, false, typeScript), ] await getConnection().manager.save(cells) } @@ -265,11 +265,11 @@ describe('CellsService', () => { const cells: OutputEntity[] = [ generateCell(toShannon('1000'), OutputStatus.Live, false, null), generateCell(toShannon('1'), OutputStatus.Live, false, null, { - lockScript: new Script(bob.lockScript.codeHash, bob.lockScript.args, ScriptHashType.Data) + lockScript: new Script(bob.lockScript.codeHash, bob.lockScript.args, ScriptHashType.Data), }), generateCell(toShannon('200'), OutputStatus.Sent, false, null), generateCell(toShannon('2000'), OutputStatus.Live, true, null), - generateCell(toShannon('3000'), OutputStatus.Live, false, typeScript) + generateCell(toShannon('3000'), OutputStatus.Live, false, typeScript), ] await getConnection().manager.save(cells) } @@ -395,7 +395,7 @@ describe('CellsService', () => { beforeEach(async () => { const cells: OutputEntity[] = [ generateCell(toShannon('1000'), OutputStatus.Live, false, null), - generateCell(toShannon('2000'), OutputStatus.Live, false, null) + generateCell(toShannon('2000'), OutputStatus.Live, false, null), ] await getConnection().manager.save(cells) }) @@ -484,7 +484,7 @@ describe('CellsService', () => { CellsService.gatherInputs(toShannon('1001'), '', '0', '1000', 0, 0, 0, undefined, { lockArgs: ['bob.blake160'], hashType: SystemScriptInfo.MULTI_SIGN_HASH_TYPE, - codeHash: SystemScriptInfo.MULTI_SIGN_CODE_HASH + codeHash: SystemScriptInfo.MULTI_SIGN_CODE_HASH, }) ).rejects.toThrow(new CapacityNotEnough()) }) @@ -494,7 +494,7 @@ describe('CellsService', () => { CellsService.gatherInputs(toShannon('1001'), '', '0', '1000', 0, 0, 0, undefined, { lockArgs: [multisigInfo.lockScript.args], hashType: SystemScriptInfo.MULTI_SIGN_HASH_TYPE, - codeHash: SystemScriptInfo.MULTI_SIGN_CODE_HASH + codeHash: SystemScriptInfo.MULTI_SIGN_CODE_HASH, }) ).rejects.toThrow(new MultisigConfigNeedError()) }) @@ -513,7 +513,7 @@ describe('CellsService', () => { { lockArgs: [multisigInfo.lockScript.args], hashType: SystemScriptInfo.MULTI_SIGN_HASH_TYPE, - codeHash: SystemScriptInfo.MULTI_SIGN_CODE_HASH + codeHash: SystemScriptInfo.MULTI_SIGN_CODE_HASH, }, [ { @@ -522,8 +522,8 @@ describe('CellsService', () => { n: 1, getLockHash() { return multisigInfo.lockHash - } - } as any + }, + } as any, ] ) ).rejects.toThrow(new CapacityNotEnough()) @@ -543,7 +543,7 @@ describe('CellsService', () => { { lockArgs: [multisigInfo.lockScript.args], hashType: SystemScriptInfo.MULTI_SIGN_HASH_TYPE, - codeHash: SystemScriptInfo.MULTI_SIGN_CODE_HASH + codeHash: SystemScriptInfo.MULTI_SIGN_CODE_HASH, }, [ { @@ -552,8 +552,8 @@ describe('CellsService', () => { n: 1, getLockHash() { return multisigInfo.lockHash - } - } as any + }, + } as any, ] ) ).rejects.toThrow(new LiveCapacityNotEnough()) @@ -573,7 +573,7 @@ describe('CellsService', () => { { lockArgs: [multisigInfo.lockScript.args], hashType: SystemScriptInfo.MULTI_SIGN_HASH_TYPE, - codeHash: SystemScriptInfo.MULTI_SIGN_CODE_HASH + codeHash: SystemScriptInfo.MULTI_SIGN_CODE_HASH, }, [ { @@ -582,8 +582,8 @@ describe('CellsService', () => { n: 1, getLockHash() { return multisigInfo.lockHash - } - } as any + }, + } as any, ] ) ).rejects.toThrow(new LiveCapacityNotEnough()) @@ -602,7 +602,7 @@ describe('CellsService', () => { { lockArgs: [multisigInfo.lockScript.args], hashType: SystemScriptInfo.MULTI_SIGN_HASH_TYPE, - codeHash: SystemScriptInfo.MULTI_SIGN_CODE_HASH + codeHash: SystemScriptInfo.MULTI_SIGN_CODE_HASH, }, [ { @@ -611,8 +611,8 @@ describe('CellsService', () => { n: 1, getLockHash() { return multisigInfo.lockHash - } - } as any + }, + } as any, ] ) ).rejects.toThrow(new CapacityNotEnoughForChange()) @@ -632,21 +632,18 @@ describe('CellsService', () => { { lockArgs: [multisigInfo.lockScript.args], hashType: SystemScriptInfo.MULTI_SIGN_HASH_TYPE, - codeHash: SystemScriptInfo.MULTI_SIGN_CODE_HASH + codeHash: SystemScriptInfo.MULTI_SIGN_CODE_HASH, }, [ { ...multisigConfig, getLockHash() { return multisigInfo.lockHash - } - } as any + }, + } as any, ] ) - const input = await getConnection() - .getRepository(MultisigOutput) - .createQueryBuilder('multisig_output') - .getOne() + const input = await getConnection().getRepository(MultisigOutput).createQueryBuilder('multisig_output').getOne() expect(res).toEqual({ inputs: [new Input(input!.outPoint(), '0', input!.capacity, input!.lockScript(), input!.lockHash)], capacities: toShannon('1000'), @@ -655,7 +652,7 @@ describe('CellsService', () => { TransactionSize.multiSignWitness(multisigConfig.r, multisigConfig.m, multisigConfig.n), BigInt('1000') ).toString(), - hasChangeOutput: true + hasChangeOutput: true, }) }) }) @@ -666,11 +663,11 @@ describe('CellsService', () => { const cells: OutputEntity[] = [ generateCell(toShannon('1000'), OutputStatus.Live, false, null), generateCell(toShannon('1'), OutputStatus.Live, false, null, { - lockScript: new Script(bob.lockScript.codeHash, bob.lockScript.args, ScriptHashType.Data) + lockScript: new Script(bob.lockScript.codeHash, bob.lockScript.args, ScriptHashType.Data), }), generateCell(toShannon('200'), OutputStatus.Sent, false, null), generateCell(toShannon('2000'), OutputStatus.Live, true, null), - generateCell(toShannon('3000'), OutputStatus.Live, false, typeScript) + generateCell(toShannon('3000'), OutputStatus.Live, false, typeScript), ] await getConnection().manager.save(cells) }) @@ -689,7 +686,7 @@ describe('CellsService', () => { beforeEach(async () => { allInputs = await CellsService.gatherAllInputs(walletId1, { codeHash: 'non exist lock code hash', - hashType: ScriptHashType.Type + hashType: ScriptHashType.Type, }) }) it('returns empty array', async () => { @@ -704,7 +701,7 @@ describe('CellsService', () => { const inputs = await CellsService.gatherAllInputs(walletId1, { codeHash: SystemScriptInfo.MULTI_SIGN_CODE_HASH, hashType: SystemScriptInfo.MULTI_SIGN_HASH_TYPE, - args: multisigInfo.lockScript.args + args: multisigInfo.lockScript.args, }) expect(inputs).toHaveLength(1) expect(inputs[0].capacity).toEqual(toShannon('1000')) @@ -713,7 +710,7 @@ describe('CellsService', () => { const inputs = await CellsService.gatherAllInputs(walletId1, { codeHash: SystemScriptInfo.MULTI_SIGN_CODE_HASH, hashType: SystemScriptInfo.MULTI_SIGN_HASH_TYPE, - args: 'non-exist-args' + args: 'non-exist-args', }) expect(inputs).toHaveLength(0) }) @@ -742,7 +739,7 @@ describe('CellsService', () => { generateCell(toShannon('1000'), OutputStatus.Live, false, null, bob, depositData, tx1), generateCell(toShannon('2000'), OutputStatus.Live, false, null, bob, withdrawData, tx1), generateCell(toShannon('3000'), OutputStatus.Live, false, null, bob, depositData, tx2), - generateCell(toShannon('4000'), OutputStatus.Live, false, null, bob, withdrawData, tx2) + generateCell(toShannon('4000'), OutputStatus.Live, false, null, bob, withdrawData, tx2), ] await getConnection().manager.save([tx1, tx2, ...cells]) } @@ -762,9 +759,9 @@ describe('CellsService', () => { capacity: '1000', daoData: depositData, lock: bob.lockScript, - type: SystemScriptInfo.generateDaoScript() - }) - ] + type: SystemScriptInfo.generateDaoScript(), + }), + ], }) const withdrawTxHash = '0x' + '2'.repeat(64) @@ -779,8 +776,8 @@ describe('CellsService', () => { inputs: [ Input.fromObject({ previousOutput: new OutPoint(depositTxHash, '0'), - since: '0' - }) + since: '0', + }), ], outputs: [ Output.fromObject({ @@ -789,9 +786,9 @@ describe('CellsService', () => { lock: bob.lockScript, type: SystemScriptInfo.generateDaoScript(), depositOutPoint: new OutPoint(depositTxHash, '0'), - depositTimestamp: depositTx.timestamp - }) - ] + depositTimestamp: depositTx.timestamp, + }), + ], }) const unlockTxHash = '0x' + '4'.repeat(64) @@ -806,15 +803,15 @@ describe('CellsService', () => { inputs: [ Input.fromObject({ previousOutput: new OutPoint(withdrawTxHash, '0'), - since: '0' - }) + since: '0', + }), ], outputs: [ Output.fromObject({ capacity: '1000', - lock: bob.lockScript - }) - ] + lock: bob.lockScript, + }), + ], }) it('deposit', async () => { @@ -981,32 +978,28 @@ describe('CellsService', () => { inputs: [ Input.fromObject({ previousOutput: new OutPoint(withdrawTxHash, '0'), - since: '0' - }) + since: '0', + }), ], outputs: [ Output.fromObject({ capacity: '1000', - lock: bob.lockScript - }) - ] + lock: bob.lockScript, + }), + ], }) - + const tx1 = generateTx('0x1234', '1572862777481') it('output cells is not cost', async () => { - const cells = [ - generateCell(toShannon('1000'), OutputStatus.Live, false, null, bob, depositData, tx1).toModel() - ] + const cells = [generateCell(toShannon('1000'), OutputStatus.Live, false, null, bob, depositData, tx1).toModel()] //@ts-ignore private property await CellsService.addUnlockInfo(cells) expect(cells[0].unlockInfo).toBeUndefined() }) it('output cells no transaction', async () => { - const cells = [ - generateCell(toShannon('1000'), OutputStatus.Dead, false, null, bob, depositData, tx1).toModel() - ] + const cells = [generateCell(toShannon('1000'), OutputStatus.Dead, false, null, bob, depositData, tx1).toModel()] //@ts-ignore private property await CellsService.addUnlockInfo(cells) expect(cells[0].unlockInfo).toBeUndefined() @@ -1020,7 +1013,7 @@ describe('CellsService', () => { lock: bob.lockScript, type: SystemScriptInfo.generateDaoScript(), outPoint: new OutPoint(withdrawTxHash, '0'), - status: OutputStatus.Dead + status: OutputStatus.Dead, }) //@ts-ignore private property await CellsService.addUnlockInfo([outputs]) @@ -1058,26 +1051,22 @@ describe('CellsService', () => { capacity: '1000', daoData: depositData, lock: bob.lockScript, - type: SystemScriptInfo.generateDaoScript() - }) - ] + type: SystemScriptInfo.generateDaoScript(), + }), + ], }) - + const tx1 = generateTx('0x1234', '1572862777481') it('output cells is not deposit', async () => { - const cells = [ - generateCell(toShannon('1000'), OutputStatus.Live, false, null, bob, depositData, tx1).toModel() - ] + const cells = [generateCell(toShannon('1000'), OutputStatus.Live, false, null, bob, depositData, tx1).toModel()] //@ts-ignore private property await CellsService.addDepositInfo(cells) expect(cells[0].depositInfo).toBeUndefined() }) it('output cells no transaction', async () => { - const cells = [ - generateCell(toShannon('1000'), OutputStatus.Dead, false, null, bob, depositData, tx1).toModel() - ] + const cells = [generateCell(toShannon('1000'), OutputStatus.Dead, false, null, bob, depositData, tx1).toModel()] cells[0].depositOutPoint = new OutPoint('0x' + '0'.repeat(64), '0x0') //@ts-ignore private property await CellsService.addDepositInfo(cells) @@ -1092,7 +1081,7 @@ describe('CellsService', () => { lock: bob.lockScript, type: SystemScriptInfo.generateDaoScript(), depositOutPoint: new OutPoint(depositTx.hash!, '0'), - status: OutputStatus.Dead + status: OutputStatus.Dead, }) //@ts-ignore await CellsService.addDepositInfo([outputs]) @@ -1100,7 +1089,6 @@ describe('CellsService', () => { }) }) - describe('#usedByAnyoneCanPayBlake160s', () => { const fakeArgs1 = '0x1' const fakeArgs2 = '0x2' @@ -1153,7 +1141,7 @@ describe('CellsService', () => { describe('with indexed customized asset outputs', () => { const user = { - lockScript: multiSignLockScript + lockScript: multiSignLockScript, } const receiverChequeLock = assetAccountInfo.generateChequeScript(bobDefaultLock.computeHash(), '0'.repeat(40)) @@ -1180,7 +1168,7 @@ describe('CellsService', () => { // unknown asset generateCell('666', OutputStatus.Live, true, typeScript, { lockScript: bobDefaultLock }), // sudt asset - generateCell('777', OutputStatus.Live, true, sudtType, { lockScript: bobDefaultLock }) + generateCell('777', OutputStatus.Live, true, sudtType, { lockScript: bobDefaultLock }), ] await getConnection().manager.save(cells) }) @@ -1225,7 +1213,7 @@ describe('CellsService', () => { expect(cells[0].customizedAssetInfo).toEqual({ lock: CustomizedLock.SUDT, type: CustomizedType.SUDT, - data: '' + data: '', }) }) }) @@ -1303,7 +1291,7 @@ describe('CellsService', () => { index: string } = { txHash: '0x364ded6d4f2206041d0a635d63d3cfadc5b38b3a17e0cabc0d272d142d3542b8', - index: '0x0' + index: '0x0', }, data?: number ) => { @@ -1319,153 +1307,224 @@ describe('CellsService', () => { const gliaTypeScript = Script.fromObject({ codeHash: '0xc5e5dcf215925f7ef4dfaf5f4b4f105bc321c02776d6e7d52a1db3fcd9d011a4', hashType: ScriptHashType.Type, - args: '0x6fe3733cd9df22d05b8a70f7b505d0fb67fb58fb88693217135ff5079713e902' + args: '0x6fe3733cd9df22d05b8a70f7b505d0fb67fb58fb88693217135ff5079713e902', }) it('exception no live cell CapacityNotEnough', async () => { getManyByLockScriptsAndTypeScriptMock.mockResolvedValue([]) - await expect(CellsService.gatherSudtInputs('0', walletId1, [], gliaTypeScript, '')).rejects.toThrow(new CapacityNotEnough()) + await expect(CellsService.gatherSudtInputs('0', walletId1, [], gliaTypeScript, '')).rejects.toThrow( + new CapacityNotEnough() + ) }) it('exception amount oveflow CapacityNotEnough', async () => { getManyByLockScriptsAndTypeScriptMock.mockResolvedValue([ - generateSUDTLiveCell('142', bobLockScript, gliaTypeScript, undefined, 1000) + generateSUDTLiveCell('142', bobLockScript, gliaTypeScript, undefined, 1000), ]) - await expect(CellsService.gatherSudtInputs('2000', walletId1, [], gliaTypeScript, '')).rejects.toThrow(new CapacityNotEnough()) + await expect(CellsService.gatherSudtInputs('2000', walletId1, [], gliaTypeScript, '')).rejects.toThrow( + new CapacityNotEnough() + ) }) it('no fee success with exist cell', async () => { const liveCell = generateSUDTLiveCell('142', bobLockScript, gliaTypeScript, undefined, 3000) getManyByLockScriptsAndTypeScriptMock.mockResolvedValue([liveCell]) const res = await CellsService.gatherSudtInputs('2000', walletId1, [], gliaTypeScript, '') expect(res).toEqual({ - anyoneCanPayInputs: [Input.fromObject({ - previousOutput: liveCell.outPoint(), - since: '0', - capacity: liveCell.capacity, - lock: liveCell.lock(), - lockHash: liveCell.lockHash, - type: liveCell.type(), - typeHash: liveCell.typeHash, - data: liveCell.data - })], + anyoneCanPayInputs: [ + Input.fromObject({ + previousOutput: liveCell.outPoint(), + since: '0', + capacity: liveCell.capacity, + lock: liveCell.lock(), + lockHash: liveCell.lockHash, + type: liveCell.type(), + typeHash: liveCell.typeHash, + data: liveCell.data, + }), + ], changeInputs: [], - anyoneCanPayOutputs: [Output.fromObject({ - capacity: liveCell.capacity, - lock: liveCell.lock(), - type: liveCell.type(), - data: BufferUtils.writeBigUInt128LE(BigInt(1000)) - })], + anyoneCanPayOutputs: [ + Output.fromObject({ + capacity: liveCell.capacity, + lock: liveCell.lock(), + type: liveCell.type(), + data: BufferUtils.writeBigUInt128LE(BigInt(1000)), + }), + ], changeOutput: undefined, finalFee: '0', - amount: '2000' + amount: '2000', }) }), - it('fee not enough', async () => { - const liveCell = generateSUDTLiveCell('142', bobLockScript, gliaTypeScript, undefined, 3000) - getManyByLockScriptsAndTypeScriptMock.mockResolvedValue([liveCell]) - await expect(CellsService.gatherSudtInputs('2000', 'w3', [], gliaTypeScript, alice.blake160, '1000')) - .rejects.toThrow(new CapacityNotEnough()) - }) + it('fee not enough', async () => { + const liveCell = generateSUDTLiveCell('142', bobLockScript, gliaTypeScript, undefined, 3000) + getManyByLockScriptsAndTypeScriptMock.mockResolvedValue([liveCell]) + await expect( + CellsService.gatherSudtInputs('2000', 'w3', [], gliaTypeScript, alice.blake160, '1000') + ).rejects.toThrow(new CapacityNotEnough()) + }) it('fee enough', async () => { const liveCell = generateSUDTLiveCell('142', bobLockScript, gliaTypeScript, undefined, 3000) const output = await createCell(toShannon('62'), OutputStatus.Live, false, null, { lockScript: bobLockScript }) getManyByLockScriptsAndTypeScriptMock.mockResolvedValue([liveCell]) const res = await CellsService.gatherSudtInputs('2000', walletId1, [], gliaTypeScript, alice.blake160, '1000') expect(res).toEqual({ - anyoneCanPayInputs: [Input.fromObject({ - previousOutput: liveCell.outPoint(), - since: '0', - capacity: liveCell.capacity, - lock: liveCell.lock(), - lockHash: liveCell.lockHash, - type: liveCell.type(), - typeHash: liveCell.typeHash, - data: liveCell.data - })], + anyoneCanPayInputs: [ + Input.fromObject({ + previousOutput: liveCell.outPoint(), + since: '0', + capacity: liveCell.capacity, + lock: liveCell.lock(), + lockHash: liveCell.lockHash, + type: liveCell.type(), + typeHash: liveCell.typeHash, + data: liveCell.data, + }), + ], changeInputs: [new Input(output.outPoint(), '0', output.capacity, output.lockScript(), output.lockHash)], - anyoneCanPayOutputs: [Output.fromObject({ - capacity: liveCell.capacity, - lock: liveCell.lock(), - type: liveCell.type(), - data: BufferUtils.writeBigUInt128LE(BigInt(1000)) - })], + anyoneCanPayOutputs: [ + Output.fromObject({ + capacity: liveCell.capacity, + lock: liveCell.lock(), + type: liveCell.type(), + data: BufferUtils.writeBigUInt128LE(BigInt(1000)), + }), + ], changeOutput: Output.fromObject({ capacity: (BigInt(toShannon('62')) - BigInt('1000')).toString(), - lock: SystemScriptInfo.generateSecpScript(alice.blake160) + lock: SystemScriptInfo.generateSecpScript(alice.blake160), }), finalFee: '1000', - amount: '2000' + amount: '2000', }) }) it('add capacity and capacity not enough', async () => { const liveCell = generateSUDTLiveCell('142', bobLockScript, gliaTypeScript, undefined, 3000) await createCell(toShannon('61'), OutputStatus.Live, false, null, { lockScript: bobLockScript }) getManyByLockScriptsAndTypeScriptMock.mockResolvedValue([liveCell]) - await expect(CellsService.gatherSudtInputs('2000', walletId1, [], gliaTypeScript, alice.blake160, '1000', '0', 0, 0, 0, toShannon('61'))) - .rejects.toThrow(new CapacityNotEnough()) + await expect( + CellsService.gatherSudtInputs( + '2000', + walletId1, + [], + gliaTypeScript, + alice.blake160, + '1000', + '0', + 0, + 0, + 0, + toShannon('61') + ) + ).rejects.toThrow(new CapacityNotEnough()) }) it('add capacity,no fee capacity enough', async () => { const liveCell = generateSUDTLiveCell('142', bobLockScript, gliaTypeScript, undefined, 3000) const output = await createCell(toShannon('61'), OutputStatus.Live, false, null, { lockScript: bobLockScript }) getManyByLockScriptsAndTypeScriptMock.mockResolvedValue([liveCell]) - const res = await CellsService.gatherSudtInputs('2000', walletId1, [], gliaTypeScript, alice.blake160, '0', '0', 0, 0, 0, toShannon('61')) + const res = await CellsService.gatherSudtInputs( + '2000', + walletId1, + [], + gliaTypeScript, + alice.blake160, + '0', + '0', + 0, + 0, + 0, + toShannon('61') + ) expect(res).toEqual({ - anyoneCanPayInputs: [Input.fromObject({ - previousOutput: liveCell.outPoint(), - since: '0', - capacity: liveCell.capacity, - lock: liveCell.lock(), - lockHash: liveCell.lockHash, - type: liveCell.type(), - typeHash: liveCell.typeHash, - data: liveCell.data - })], + anyoneCanPayInputs: [ + Input.fromObject({ + previousOutput: liveCell.outPoint(), + since: '0', + capacity: liveCell.capacity, + lock: liveCell.lock(), + lockHash: liveCell.lockHash, + type: liveCell.type(), + typeHash: liveCell.typeHash, + data: liveCell.data, + }), + ], changeInputs: [new Input(output.outPoint(), '0', output.capacity, output.lockScript(), output.lockHash)], - anyoneCanPayOutputs: [Output.fromObject({ - capacity: liveCell.capacity, - lock: liveCell.lock(), - type: liveCell.type(), - data: BufferUtils.writeBigUInt128LE(BigInt(1000)) - })], + anyoneCanPayOutputs: [ + Output.fromObject({ + capacity: liveCell.capacity, + lock: liveCell.lock(), + type: liveCell.type(), + data: BufferUtils.writeBigUInt128LE(BigInt(1000)), + }), + ], changeOutput: undefined, finalFee: '0', - amount: '2000' + amount: '2000', }) }) it('add capacity,with fee capacity not enough', async () => { const liveCell = generateSUDTLiveCell('142', bobLockScript, gliaTypeScript, undefined, 3000) await createCell(toShannon('61'), OutputStatus.Live, false, null, { lockScript: bobLockScript }) getManyByLockScriptsAndTypeScriptMock.mockResolvedValue([liveCell]) - await expect(CellsService.gatherSudtInputs('2000', walletId1, [], gliaTypeScript, alice.blake160, '1000', '0', 0, 0, 0, toShannon('61'))) - .rejects.toThrow(new CapacityNotEnough()) + await expect( + CellsService.gatherSudtInputs( + '2000', + walletId1, + [], + gliaTypeScript, + alice.blake160, + '1000', + '0', + 0, + 0, + 0, + toShannon('61') + ) + ).rejects.toThrow(new CapacityNotEnough()) }) it('add capacity,with fee capacity enough', async () => { const liveCell = generateSUDTLiveCell('142', bobLockScript, gliaTypeScript, undefined, 3000) const output = await createCell(toShannon('123'), OutputStatus.Live, false, null, { lockScript: bobLockScript }) getManyByLockScriptsAndTypeScriptMock.mockResolvedValue([liveCell]) - const res = await CellsService.gatherSudtInputs('2000', walletId1, [], gliaTypeScript, alice.blake160, '1000', '0', 0, 0, 0, toShannon('61')) + const res = await CellsService.gatherSudtInputs( + '2000', + walletId1, + [], + gliaTypeScript, + alice.blake160, + '1000', + '0', + 0, + 0, + 0, + toShannon('61') + ) expect(res).toEqual({ - anyoneCanPayInputs: [Input.fromObject({ - previousOutput: liveCell.outPoint(), - since: '0', - capacity: liveCell.capacity, - lock: liveCell.lock(), - lockHash: liveCell.lockHash, - type: liveCell.type(), - typeHash: liveCell.typeHash, - data: liveCell.data - })], + anyoneCanPayInputs: [ + Input.fromObject({ + previousOutput: liveCell.outPoint(), + since: '0', + capacity: liveCell.capacity, + lock: liveCell.lock(), + lockHash: liveCell.lockHash, + type: liveCell.type(), + typeHash: liveCell.typeHash, + data: liveCell.data, + }), + ], changeInputs: [new Input(output.outPoint(), '0', output.capacity, output.lockScript(), output.lockHash)], - anyoneCanPayOutputs: [Output.fromObject({ - capacity: liveCell.capacity, - lock: liveCell.lock(), - type: liveCell.type(), - data: BufferUtils.writeBigUInt128LE(BigInt(1000)) - })], + anyoneCanPayOutputs: [ + Output.fromObject({ + capacity: liveCell.capacity, + lock: liveCell.lock(), + type: liveCell.type(), + data: BufferUtils.writeBigUInt128LE(BigInt(1000)), + }), + ], changeOutput: Output.fromObject({ capacity: (BigInt(toShannon('123')) - BigInt(toShannon('61')) - BigInt('1000')).toString(), - lock: SystemScriptInfo.generateSecpScript(alice.blake160) + lock: SystemScriptInfo.generateSecpScript(alice.blake160), }), finalFee: '1000', - amount: '2000' + amount: '2000', }) }) }) diff --git a/packages/neuron-wallet/tests/services/ckb-runner.test.ts b/packages/neuron-wallet/tests/services/ckb-runner.test.ts index 35d2b20e5a..e4fe206a45 100644 --- a/packages/neuron-wallet/tests/services/ckb-runner.test.ts +++ b/packages/neuron-wallet/tests/services/ckb-runner.test.ts @@ -23,33 +23,33 @@ const resetMocks = () => { jest.doMock('child_process', () => { return { ChildProcess: stubbedChildProcess, - spawn: stubbedSpawn + spawn: stubbedSpawn, } }) jest.doMock('fs', () => { return { __esModule: true, default: { - existsSync: stubbedExistsSync - } + existsSync: stubbedExistsSync, + }, } }) const app = { getAppPath: () => '/', getPath: () => '/', - isPackaged: false + isPackaged: false, } jest.doMock('env', () => { return { - app + app, } }) jest.doMock('utils/logger', () => { return { info: stubbedLoggerInfo, error: stubbedLoggerError, - log: stubbedLoggerLog + log: stubbedLoggerLog, } }) jest.doMock('process', () => { @@ -60,19 +60,24 @@ const ckbDataPath = '/chains/mainnet' jest.mock('../../src/services/settings', () => ({ getInstance() { return { - ckbDataPath + ckbDataPath, } - } + }, })) jest.mock('../../src/block-sync-renderer', () => ({ resetSyncTaskQueue: { - push: jest.fn() - } + push: jest.fn(), + }, })) jest.mock('../../src/services/indexer', () => ({ - cleanOldIndexerData: jest.fn() + cleanOldIndexerData: jest.fn(), })) -const { startCkbNode, stopCkbNode, getLookingValidTargetStatus, migrateCkbData } = require('../../src/services/ckb-runner') +const { + startCkbNode, + stopCkbNode, + getLookingValidTargetStatus, + migrateCkbData, +} = require('../../src/services/ckb-runner') describe('ckb runner', () => { let stubbedCkb: any = new EventEmitter() @@ -88,7 +93,7 @@ describe('ckb runner', () => { { platform: 'win32', platformPath: 'win' }, { platform: 'linux', platformPath: 'linux' }, { platform: 'darwin', platformPath: 'mac' }, - { platform: '_', platformPath: '' } + { platform: '_', platformPath: '' }, ].forEach(({ platform, platformPath }) => { describe(`#startCkbNode on ${platform}`, () => { beforeEach(() => { @@ -110,7 +115,7 @@ describe('ckb runner', () => { '--chain', 'mainnet', '-C', - ckbDataPath + ckbDataPath, ]) }) it('runs ckb binary', () => { @@ -144,7 +149,7 @@ describe('ckb runner', () => { '--chain', 'mainnet', '-C', - ckbDataPath + ckbDataPath, ]) }) it('runs ckb binary', () => { @@ -231,7 +236,7 @@ describe('ckb runner', () => { const migrateNextMock = jest.fn() jest.mock('../../src/models/subjects/migrate-subject', () => ({ - next: (v: string) => migrateNextMock(v) + next: (v: string) => migrateNextMock(v), })) describe('ckb migrate', () => { diff --git a/packages/neuron-wallet/tests/services/hardware.test.ts b/packages/neuron-wallet/tests/services/hardware.test.ts index 2decc5b1a6..dcfac1b03d 100644 --- a/packages/neuron-wallet/tests/services/hardware.test.ts +++ b/packages/neuron-wallet/tests/services/hardware.test.ts @@ -13,7 +13,7 @@ describe('HardwareWalletService', () => { it('find specific model device', async () => { const devices = await HardwareService.findDevices({ manufacturer: Manufacturer.Ledger, - product: 'Nano S' + product: 'Nano S', }) expect(devices).toEqual([ledgerNanoS]) }) diff --git a/packages/neuron-wallet/tests/services/indexer.test.ts b/packages/neuron-wallet/tests/services/indexer.test.ts index 5673648fab..ad6aeefe68 100644 --- a/packages/neuron-wallet/tests/services/indexer.test.ts +++ b/packages/neuron-wallet/tests/services/indexer.test.ts @@ -10,7 +10,7 @@ jest.mock('fs', () => { existsSync: () => existsSyncMock(), readFileSync: () => jest.fn(), writeFileSync: () => jest.fn(), - rmSync: () => rmSyncMock() + rmSync: () => rmSyncMock(), } }) @@ -25,23 +25,19 @@ jest.mock('../../src/services/settings', () => { }, set indexerDataPath(value: string) { setIndexerDataPathMock(value) - } + }, } } } }) jest.mock('../../src/utils/logger', () => ({ - debug: () => jest.fn() + debug: () => jest.fn(), })) -jest.mock('../../src/models/synced-block-number', () => ({ - -})) +jest.mock('../../src/models/synced-block-number', () => ({})) -jest.mock('../../src/database/chain', () => ({ - -})) +jest.mock('../../src/database/chain', () => ({})) jest.mock('../../src/services/monitor', () => { function mockMonitor() {} @@ -54,9 +50,9 @@ jest.mock('../../src/services/node', () => ({ return { get isCkbNodeExternal() { return isCkbNodeExternalMock() - } + }, } - } + }, })) describe('test IndexerService', () => { diff --git a/packages/neuron-wallet/tests/services/monitor.test.ts b/packages/neuron-wallet/tests/services/monitor.test.ts index 1aa834682b..99ab94cbaa 100644 --- a/packages/neuron-wallet/tests/services/monitor.test.ts +++ b/packages/neuron-wallet/tests/services/monitor.test.ts @@ -9,14 +9,14 @@ jest.mock('../../src/services/node', () => ({ getInstance() { return { isDefaultCKBNeedRestart: isDefaultCKBNeedRestartMock, - startNode: startNodeMock + startNode: startNodeMock, } - } + }, })) const stopCkbNodeMock = jest.fn() jest.mock('../../src/services/ckb-runner', () => ({ - stopCkbNode: () => stopCkbNodeMock() + stopCkbNode: () => stopCkbNodeMock(), })) describe('ckb monitor', () => { @@ -53,8 +53,10 @@ class MonitorTest extends Monitor { } function wait(times: number) { - return new Promise((resolve) => { - setTimeout(() => { resolve(times) }, times) + return new Promise(resolve => { + setTimeout(() => { + resolve(times) + }, times) }) } describe('base monitor', () => { diff --git a/packages/neuron-wallet/tests/services/multisig.test.ts b/packages/neuron-wallet/tests/services/multisig.test.ts index 1314cd70c6..5c1f9909bd 100644 --- a/packages/neuron-wallet/tests/services/multisig.test.ts +++ b/packages/neuron-wallet/tests/services/multisig.test.ts @@ -14,15 +14,15 @@ const [alice, bob, charlie] = keyInfos const rpcBatchRequestMock = jest.fn() jest.mock('../../src/utils/rpc-request', () => ({ - rpcBatchRequest: () => rpcBatchRequestMock() + rpcBatchRequest: () => rpcBatchRequestMock(), })) const multisigOutputChangedSubjectNextMock = jest.fn() jest.mock('../../src/models/subjects/multisig-output-db-changed-subject', () => ({ getSubject() { return { - next: multisigOutputChangedSubjectNextMock + next: multisigOutputChangedSubjectNextMock, } - } + }, })) describe('multisig service', () => { @@ -34,18 +34,23 @@ describe('multisig service', () => { 3, [alice.publicKeyInBlake160, bob.publicKeyInBlake160, charlie.publicKeyInBlake160], 'alias' - ); + ) const defaultMultisigConfig = MultisigConfig.fromModel(multisigConfigModel) defaultMultisigConfig.lastestBlockNumber = '0x0' const lock = { - args: Multisig.hash(multisigConfigModel.blake160s, multisigConfigModel.r, multisigConfigModel.m, multisigConfigModel.n), + args: Multisig.hash( + multisigConfigModel.blake160s, + multisigConfigModel.r, + multisigConfigModel.m, + multisigConfigModel.n + ), code_hash: SystemScriptInfo.MULTI_SIGN_CODE_HASH, - hash_type: SystemScriptInfo.MULTI_SIGN_HASH_TYPE + hash_type: SystemScriptInfo.MULTI_SIGN_HASH_TYPE, } const defaultTxOutpoint = { tx_hash: 'tx_hash', index: '0x0' } const defaultOutput = { out_point: defaultTxOutpoint, - output: { lock, capacity: '6100000000' } + output: { lock, capacity: '6100000000' }, } const multisigOutput = MultisigOutput.fromIndexer(defaultOutput) @@ -81,7 +86,7 @@ describe('multisig service', () => { .getRepository(MultisigConfig) .createQueryBuilder() .where({ - id: res.id + id: res.id, }) .getCount() expect(count).toBe(1) @@ -91,27 +96,29 @@ describe('multisig service', () => { describe('update config', () => { it('update config is not exist', async () => { - expect(multisigService.updateMultisigConfig({ - id: 10000, - alias: 'error' - })).rejects.toThrow() + expect( + multisigService.updateMultisigConfig({ + id: 10000, + alias: 'error', + }) + ).rejects.toThrow() }) it('update config success', async () => { await multisigService.updateMultisigConfig({ id: multisigConfigModel.id!, - alias: 'newalisa' + alias: 'newalisa', }) const config = await getConnection() .getRepository(MultisigConfig) .createQueryBuilder() .where({ - id: multisigConfigModel.id + id: multisigConfigModel.id, }) .getOne() expect(config?.alias).toBe('newalisa') }) }) - + describe('test get config', () => { it('no config', async () => { const configs = await multisigService.getMultisigConfig('noconfigwallet') @@ -130,7 +137,7 @@ describe('multisig service', () => { .getRepository(MultisigConfig) .createQueryBuilder() .where({ - walletId: multisigConfigModel.walletId + walletId: multisigConfigModel.walletId, }) .getCount() expect(count).toBe(0) @@ -151,8 +158,8 @@ describe('multisig service', () => { it('a live cell', async () => { rpcBatchRequestMock.mockResolvedValueOnce([ { - result: { objects: [defaultOutput] } - } + result: { objects: [defaultOutput] }, + }, ]) const res = await MultisigService.getLiveCells([defaultMultisigConfig]) expect(res).toHaveLength(1) @@ -167,11 +174,11 @@ describe('multisig service', () => { defaultOutput, { out_point: { tx_hash: 'tx_hash_1', index: '0x0' }, - output: { lock, type: { args: '', code_hash: '', hash_type: ''}, capacity: '6100000000' } - } - ] - } - } + output: { lock, type: { args: '', code_hash: '', hash_type: '' }, capacity: '6100000000' }, + }, + ], + }, + }, ]) const res = await MultisigService.getLiveCells([defaultMultisigConfig]) expect(res).toHaveLength(1) @@ -187,8 +194,8 @@ describe('multisig service', () => { it('with live cell save', async () => { rpcBatchRequestMock.mockResolvedValueOnce([ { - result: { objects: [defaultOutput] } - } + result: { objects: [defaultOutput] }, + }, ]) await MultisigService.saveLiveMultisigOutput() expect(multisigOutputChangedSubjectNextMock).toHaveBeenCalledWith('create') @@ -208,8 +215,8 @@ describe('multisig service', () => { it('a Transaction', async () => { rpcBatchRequestMock.mockResolvedValueOnce([ { - result: { objects: [{ tx_hash: defaultTxOutpoint.tx_hash }] } - } + result: { objects: [{ tx_hash: defaultTxOutpoint.tx_hash }] }, + }, ]) const res = await MultisigService.getMultisigTransactionHashList([defaultMultisigConfig]) expect(res).toEqual(new Set([defaultTxOutpoint.tx_hash])) @@ -225,35 +232,31 @@ describe('multisig service', () => { it('no delete transaction', async () => { rpcBatchRequestMock.mockResolvedValueOnce([ { - result: { objects: [{ tx_hash: defaultTxOutpoint.tx_hash }] } - } + result: { objects: [{ tx_hash: defaultTxOutpoint.tx_hash }] }, + }, ]) // @ts-ignore Private method await MultisigService.deleteDeadMultisigOutput([defaultMultisigConfig]) - const multisigOutputs = await getConnection() - .getRepository(MultisigOutput) - .createQueryBuilder() - .getMany() + const multisigOutputs = await getConnection().getRepository(MultisigOutput).createQueryBuilder().getMany() expect(multisigOutputs).toHaveLength(1) expect(multisigOutputChangedSubjectNextMock).toHaveBeenCalledTimes(0) }) it('delete a transaction', async () => { - rpcBatchRequestMock.mockResolvedValueOnce([ - { - result: { objects: [{ tx_hash: defaultTxOutpoint.tx_hash }] } - } - ]).mockResolvedValueOnce([]) - .mockResolvedValueOnce([ - { - result: { transaction: { inputs: [{ previous_output: defaultTxOutpoint }] }} - } - ]) + rpcBatchRequestMock + .mockResolvedValueOnce([ + { + result: { objects: [{ tx_hash: defaultTxOutpoint.tx_hash }] }, + }, + ]) + .mockResolvedValueOnce([]) + .mockResolvedValueOnce([ + { + result: { transaction: { inputs: [{ previous_output: defaultTxOutpoint }] } }, + }, + ]) // @ts-ignore Private method await MultisigService.deleteDeadMultisigOutput([defaultMultisigConfig]) - const multisigOutputs = await getConnection() - .getRepository(MultisigOutput) - .createQueryBuilder() - .getMany() + const multisigOutputs = await getConnection().getRepository(MultisigOutput).createQueryBuilder().getMany() expect(multisigOutputs).toHaveLength(0) expect(multisigOutputChangedSubjectNextMock).toHaveBeenCalledWith('delete') }) @@ -261,15 +264,12 @@ describe('multisig service', () => { describe('deleteRemovedMultisigOutput', () => { it('delete cell thats config not in db', async () => { - const output = MultisigOutput.fromIndexer(defaultOutput) + const output = MultisigOutput.fromIndexer(defaultOutput) output.lockHash = scriptToHash(alice.lockScript) output.outPointTxHash = '0x9821d3184b5743726e4686541a74213eaa63e2d8f4fb9ee9ff50878aa9177c87' await getConnection().manager.save(output) await MultisigService.deleteRemovedMultisigOutput() - const multisigOutputs = await getConnection() - .getRepository(MultisigOutput) - .createQueryBuilder() - .getMany() + const multisigOutputs = await getConnection().getRepository(MultisigOutput).createQueryBuilder().getMany() expect(multisigOutputs).toEqual([multisigOutput]) expect(multisigOutputChangedSubjectNextMock).toHaveBeenCalledWith('delete') }) @@ -278,32 +278,31 @@ describe('multisig service', () => { describe('syncMultisigOutput', () => { it('success', async () => { await MultisigService.syncMultisigOutput('0xdddddd') - const multisigConfig = await getConnection() - .getRepository(MultisigConfig) - .createQueryBuilder() - .getOne() + const multisigConfig = await getConnection().getRepository(MultisigConfig).createQueryBuilder().getOne() expect(multisigConfig!.lastestBlockNumber).toEqual('0xdddddd') }) }) describe('saveSentMultisigOutput', () => { - it('success', async() => { + it('success', async () => { const tx = { hash: '0x2fefadab413ae1f919f4e21d53c719b583e124ca817f2497ce7a7688dedfbebb', - inputs: [{ - previousOutput: { txHash: defaultTxOutpoint.tx_hash, index: '0x0' } - }], + inputs: [ + { + previousOutput: { txHash: defaultTxOutpoint.tx_hash, index: '0x0' }, + }, + ], outputs: [ { capacity: '770000000', lock: { codeHash: lock.code_hash, hashType: lock.hash_type, - args: lock.args + args: lock.args, }, - lockHash: 'lockHash' - } - ] + lockHash: 'lockHash', + }, + ], } await MultisigService.saveSentMultisigOutput(tx as any) const sendMultisigConfig = await getConnection() @@ -323,4 +322,4 @@ describe('multisig service', () => { expect(multisigOutputChangedSubjectNextMock).toHaveBeenCalledWith('update') }) }) -}) \ No newline at end of file +}) diff --git a/packages/neuron-wallet/tests/services/networks.test.ts b/packages/neuron-wallet/tests/services/networks.test.ts index fb6e3ae19c..d9921dd8bd 100644 --- a/packages/neuron-wallet/tests/services/networks.test.ts +++ b/packages/neuron-wallet/tests/services/networks.test.ts @@ -26,7 +26,7 @@ describe(`Unit tests of networks service`, () => { let service: NetworksService = new NetworksService() - beforeEach(() => service = new NetworksService()) + beforeEach(() => (service = new NetworksService())) afterEach(() => service.clear()) describe(`success cases`, () => { @@ -105,14 +105,17 @@ describe(`Unit tests of networks service`, () => { }) it(`delete an inactive network`, async () => { - const inactiveNetwork = await service.create(newNetworkWithDefaultTypeOf1.name, newNetworkWithDefaultTypeOf1.remote) + const inactiveNetwork = await service.create( + newNetworkWithDefaultTypeOf1.name, + newNetworkWithDefaultTypeOf1.remote + ) const prevCurrentID = service.getCurrentID() || '' const prevNetworks = service.getAll() await service.delete(inactiveNetwork.id) const currentID = service.getCurrentID() const currentNetworks = service.getAll() expect(currentNetworks.map(n => n.id)).toEqual( - prevNetworks.filter(n => n.id !== inactiveNetwork.id).map(n => n.id), + prevNetworks.filter(n => n.id !== inactiveNetwork.id).map(n => n.id) ) expect(currentID).toBe(prevCurrentID) }) @@ -135,16 +138,12 @@ describe(`Unit tests of networks service`, () => { describe(`validation on parameters`, () => { describe(`validation on parameters`, () => { it(`service.create requires name, and remote`, async () => { - expect(service.create(undefined as any, undefined as any)).rejects.toThrowError( - t(ERROR_MESSAGE.MISSING_ARG), - ) + expect(service.create(undefined as any, undefined as any)).rejects.toThrowError(t(ERROR_MESSAGE.MISSING_ARG)) expect(service.create('network name', undefined as any)).rejects.toThrowError(t(ERROR_MESSAGE.MISSING_ARG)) }) it(`service.update requires id, options`, () => { - expect(service.update(undefined as any, undefined as any)).rejects.toThrowError( - t(ERROR_MESSAGE.MISSING_ARG), - ) + expect(service.update(undefined as any, undefined as any)).rejects.toThrowError(t(ERROR_MESSAGE.MISSING_ARG)) expect(service.update('', undefined as any)).rejects.toThrowError(t(ERROR_MESSAGE.MISSING_ARG)) }) @@ -161,7 +160,7 @@ describe(`Unit tests of networks service`, () => { describe(`validation on network existence`, () => { beforeEach(async () => { await service.create('Default', 'http://127.0.0.1:8114') - }); + }) it(`create network with existing name of Default`, () => { expect(service.create('Default', 'http://127.0.0.1:8114')).rejects.toThrowError(t(ERROR_MESSAGE.NAME_USED)) diff --git a/packages/neuron-wallet/tests/services/node.test.ts b/packages/neuron-wallet/tests/services/node.test.ts index 54edad3da4..160c21afbc 100644 --- a/packages/neuron-wallet/tests/services/node.test.ts +++ b/packages/neuron-wallet/tests/services/node.test.ts @@ -55,29 +55,29 @@ describe('NodeService', () => { jest.doMock('../../src/services/ckb-runner', () => { return { - startCkbNode: stubbedStartCKBNode + startCkbNode: stubbedStartCKBNode, } }) jest.doMock('../../src/services/networks', () => { return { getInstance: () => ({ get: stubbedNetworsServiceGet, - getCurrent: stubbedNetworsServiceGet + getCurrent: stubbedNetworsServiceGet, }), } }) jest.doMock('../../src/models/subjects/node', () => { return { ConnectionStatusSubject: { - next: stubbedConnectionStatusSubjectNext - } + next: stubbedConnectionStatusSubjectNext, + }, } }) jest.doMock('../../src/models/subjects/networks', () => { return { CurrentNetworkIDSubject: { - subscribe: stubbedCurrentNetworkIDSubjectSubscribe - } + subscribe: stubbedCurrentNetworkIDSubjectSubscribe, + }, } }) jest.doMock('@nervosnetwork/ckb-sdk-core', () => { @@ -102,17 +102,19 @@ describe('NodeService', () => { jest.doMock('fs', () => ({ existsSync: existsSyncMock, - readFileSync: readFileSyncMock + readFileSync: readFileSyncMock, })) jest.doMock('electron', () => { return { app: { - get isPackaged() { return isPackagedMock() }, - getAppPath: getAppPathMock + get isPackaged() { + return isPackagedMock() + }, + getAppPath: getAppPathMock, }, dialog: { - showMessageBox: showMessageBoxMock + showMessageBox: showMessageBoxMock, }, shell: shellMock, } @@ -120,32 +122,32 @@ describe('NodeService', () => { jest.doMock('../../src/env.ts', () => ({ app: { - quit: () => {} + quit: () => {}, }, })) jest.doMock('../../src/services/monitor', () => startMonitorMock) jest.doMock('../../src/utils/rpc-request', () => ({ - rpcRequest: rpcRequestMock + rpcRequest: rpcRequestMock, })) jest.doMock('../../src/services/rpc-service', () => { - return function() { + return function () { return { getChain: getChainMock, - getLocalNodeInfo: getLocalNodeInfoMock + getLocalNodeInfo: getLocalNodeInfoMock, } } }) stubbedRxjsDebounceTime.mockReturnValue((x: any) => x) getChainMock.mockRejectedValue('no chain') - }); + }) afterEach(() => { jest.clearAllTimers() - }); + }) describe('when targets external node', () => { beforeEach(async () => { @@ -155,15 +157,15 @@ describe('NodeService', () => { getTipBlockNumber: stubbedGetTipBlockNumber, }, node: { - url: fakeHTTPUrl - } + url: fakeHTTPUrl, + }, })) const NodeService = require('../../src/services/node').default nodeService = new NodeService() jest.advanceTimersByTime(1000) - }); + }) it('emits disconnected event in ConnectionStatusSubject', () => { expect(stubbedConnectionStatusSubjectNext).toHaveBeenCalledWith({ url: fakeHTTPUrl, @@ -177,7 +179,7 @@ describe('NodeService', () => { stubbedConnectionStatusSubjectNext.mockReset() stubbedGetTipBlockNumber.mockResolvedValueOnce('0x1') jest.advanceTimersByTime(1000) - }); + }) it('emits connected event in ConnectionStatusSubject', () => { expect(stubbedConnectionStatusSubjectNext).toHaveBeenCalledWith({ url: fakeHTTPUrl, @@ -192,7 +194,7 @@ describe('NodeService', () => { stubbedConnectionStatusSubjectNext.mockReset() stubbedGetTipBlockNumber.mockRejectedValueOnce(new Error()) jest.advanceTimersByTime(1000) - }); + }) it('emits disconnected event in ConnectionStatusSubject', () => { expect(stubbedConnectionStatusSubjectNext).toHaveBeenCalledWith({ url: fakeHTTPUrl, @@ -201,9 +203,9 @@ describe('NodeService', () => { startedBundledNode: false, }) }) - }); - }); - }); + }) + }) + }) describe('when targets bundled node', () => { beforeEach(async () => { stubbedCKB.mockImplementation(() => ({ @@ -212,8 +214,8 @@ describe('NodeService', () => { getTipBlockNumber: stubbedGetTipBlockNumber, }, node: { - url: BUNDLED_CKB_URL - } + url: BUNDLED_CKB_URL, + }, })) const NodeService = require('../../src/services/node').default @@ -221,15 +223,15 @@ describe('NodeService', () => { nodeService.verifyNodeVersion = () => {} nodeService.verifyStartWithIndexer = () => {} - stubbedNetworsServiceGet.mockReturnValueOnce({remote: BUNDLED_CKB_URL}) - }); + stubbedNetworsServiceGet.mockReturnValueOnce({ remote: BUNDLED_CKB_URL }) + }) describe('when node starts', () => { beforeEach(async () => { stubbedStartCKBNode.mockResolvedValue(true) await nodeService.tryStartNodeOnDefaultURI() jest.advanceTimersByTime(1000) - }); + }) it('emits disconnected event in ConnectionStatusSubject', () => { expect(stubbedConnectionStatusSubjectNext).toHaveBeenCalledWith({ url: BUNDLED_CKB_URL, @@ -243,7 +245,7 @@ describe('NodeService', () => { stubbedConnectionStatusSubjectNext.mockReset() stubbedGetTipBlockNumber.mockResolvedValueOnce('0x1') jest.advanceTimersByTime(1000) - }); + }) it('emits connected event in ConnectionStatusSubject', () => { expect(stubbedConnectionStatusSubjectNext).toHaveBeenCalledWith({ url: BUNDLED_CKB_URL, @@ -258,7 +260,7 @@ describe('NodeService', () => { stubbedConnectionStatusSubjectNext.mockReset() stubbedGetTipBlockNumber.mockRejectedValueOnce(new Error()) jest.advanceTimersByTime(1000) - }); + }) it('emits disconnected event in ConnectionStatusSubject', () => { expect(stubbedConnectionStatusSubjectNext).toHaveBeenCalledWith({ url: BUNDLED_CKB_URL, @@ -267,18 +269,18 @@ describe('NodeService', () => { startedBundledNode: true, }) }) - }); - }); - }); + }) + }) + }) describe('when node failed to start', () => { beforeEach(async () => { stubbedStartCKBNode.mockRejectedValue(new Error()) await nodeService.tryStartNodeOnDefaultURI() - }); + }) it('logs error', () => { expect(stubbedLoggerInfo).toHaveBeenCalledWith('CKB: fail to start bundled CKB with error:') expect(stubbedLoggerError).toHaveBeenCalledWith(new Error()) - }); + }) it('emits disconnected event in ConnectionStatusSubject', () => { expect(stubbedConnectionStatusSubjectNext).toHaveBeenCalledWith({ url: BUNDLED_CKB_URL, @@ -287,8 +289,8 @@ describe('NodeService', () => { startedBundledNode: false, }) }) - }); - }); + }) + }) describe('CurrentNetworkIDSubject#subscribe', () => { let eventCallback: any const stubbedTipNumberSubjectCallback = jest.fn() @@ -299,8 +301,8 @@ describe('NodeService', () => { getTipBlockNumber: stubbedGetTipBlockNumber, }, node: { - url: fakeHTTPUrl - } + url: fakeHTTPUrl, + }, })) const NodeService = require('../../src/services/node').default @@ -309,7 +311,7 @@ describe('NodeService', () => { nodeService.verifyNodeVersion = () => {} nodeService.verifyStartWithIndexer = () => {} eventCallback = stubbedCurrentNetworkIDSubjectSubscribe.mock.calls[0][0] - }); + }) it('emits disconnected event in ConnectionStatusSubject', () => { expect(stubbedConnectionStatusSubjectNext).toHaveBeenCalledWith({ url: fakeHTTPUrl, @@ -328,12 +330,12 @@ describe('NodeService', () => { nodeService.ckb.node.url = bundledNodeUrl }) stubbedStartCKBNode.mockResolvedValue(true) - stubbedNetworsServiceGet.mockReturnValue({remote: bundledNodeUrl}) + stubbedNetworsServiceGet.mockReturnValue({ remote: bundledNodeUrl }) await nodeService.tryStartNodeOnDefaultURI() - await eventCallback({currentNetworkID: 'network1'}) + await eventCallback({ currentNetworkID: 'network1' }) jest.advanceTimersByTime(10000) - }); + }) it('sets startedBundledNode to true in ConnectionStatusSubject', () => { expect(stubbedConnectionStatusSubjectNext).toHaveBeenCalledWith({ url: bundledNodeUrl, @@ -349,9 +351,9 @@ describe('NodeService', () => { nodeService.ckb.node.url = fakeHTTPUrl }) - await eventCallback({currentNetworkID: 'network2'}) + await eventCallback({ currentNetworkID: 'network2' }) jest.advanceTimersByTime(10000) - }); + }) it('sets startedBundledNode to true in ConnectionStatusSubject', () => { expect(stubbedConnectionStatusSubjectNext).toHaveBeenCalledWith({ url: fakeHTTPUrl, @@ -360,65 +362,65 @@ describe('NodeService', () => { startedBundledNode: false, }) }) - }); - }); + }) + }) describe('with http url', () => { beforeEach(async () => { - stubbedNetworsServiceGet.mockReturnValueOnce({remote: fakeHTTPUrl}) - await eventCallback({currentNetworkID: 'test'}) - }); + stubbedNetworsServiceGet.mockReturnValueOnce({ remote: fakeHTTPUrl }) + await eventCallback({ currentNetworkID: 'test' }) + }) it('sets http agent', () => { expect(stubbedCKBSetNode).toHaveBeenCalledWith( expect.objectContaining({ url: fakeHTTPUrl, - httpAgent: expect.anything() + httpAgent: expect.anything(), }) ) - }); - }); + }) + }) describe('with https url', () => { beforeEach(async () => { - stubbedNetworsServiceGet.mockReturnValueOnce({remote: fakeHTTPSUrl}) - await eventCallback({currentNetworkID: 'test'}) - }); + stubbedNetworsServiceGet.mockReturnValueOnce({ remote: fakeHTTPSUrl }) + await eventCallback({ currentNetworkID: 'test' }) + }) it('sets https agent', () => { expect(stubbedCKBSetNode).toHaveBeenCalledWith( expect.objectContaining({ url: fakeHTTPSUrl, - httpsAgent: expect.anything() + httpsAgent: expect.anything(), }) ) - }); - }); + }) + }) describe('with invalid url', () => { beforeEach(() => { - stubbedNetworsServiceGet.mockReturnValueOnce({remote: 'invalidurl'}) - }); + stubbedNetworsServiceGet.mockReturnValueOnce({ remote: 'invalidurl' }) + }) it('throws error', async () => { let err try { - await eventCallback({currentNetworkID: 'test'}) + await eventCallback({ currentNetworkID: 'test' }) } catch (error) { err = error } expect(err).toEqual(new Error('Protocol of url should be specified')) - }); - }); + }) + }) describe('when url is not a string', () => { beforeEach(() => { - stubbedNetworsServiceGet.mockReturnValueOnce({remote: {}}) - }); + stubbedNetworsServiceGet.mockReturnValueOnce({ remote: {} }) + }) it('throws error', async () => { let err try { - await eventCallback({currentNetworkID: 'test'}) + await eventCallback({ currentNetworkID: 'test' }) } catch (error) { err = error } expect(err).toEqual(new Error('should-be-type-of')) - }); - }); - }); + }) + }) + }) describe('test get node version', () => { beforeEach(() => { const NodeService = require('../../src/services/node').default @@ -436,12 +438,12 @@ describe('NodeService', () => { }) it('exist version file with new line', () => { existsSyncMock.mockReturnValue(true) - readFileSyncMock.mockReturnValue("v0.107.0\n") + readFileSyncMock.mockReturnValue('v0.107.0\n') expect(nodeService.getInternalNodeVersion()).toBe('0.107.0') }) it('exist version file without new line', () => { existsSyncMock.mockReturnValue(true) - readFileSyncMock.mockReturnValue("v0.107.0") + readFileSyncMock.mockReturnValue('v0.107.0') expect(nodeService.getInternalNodeVersion()).toBe('0.107.0') }) }) @@ -449,7 +451,7 @@ describe('NodeService', () => { beforeEach(() => { const NodeService = require('../../src/services/node').default nodeService = new NodeService() - stubbedNetworsServiceGet.mockReturnValueOnce({remote: BUNDLED_CKB_URL}) + stubbedNetworsServiceGet.mockReturnValueOnce({ remote: BUNDLED_CKB_URL }) }) it('get internal version failed', async () => { existsSyncMock.mockReturnValue(false) @@ -459,35 +461,35 @@ describe('NodeService', () => { }) it('get internal version success and same', async () => { existsSyncMock.mockReturnValue(true) - readFileSyncMock.mockReturnValue("v0.107.0") + readFileSyncMock.mockReturnValue('v0.107.0') getLocalNodeInfoMock.mockResolvedValue({ version: '0.107.0 (30e1255 2023-01-30)' }) await nodeService.verifyNodeVersion() expect(showMessageBoxMock).toBeCalledTimes(0) }) it('get internal version success and patch not same', async () => { existsSyncMock.mockReturnValue(true) - readFileSyncMock.mockReturnValue("v0.107.1") + readFileSyncMock.mockReturnValue('v0.107.1') getLocalNodeInfoMock.mockResolvedValue({ version: '0.107.0 (30e1255 2023-01-30)' }) await nodeService.verifyNodeVersion() expect(showMessageBoxMock).toBeCalledTimes(0) }) it('major is same and minor is not same with major 0', async () => { existsSyncMock.mockReturnValue(true) - readFileSyncMock.mockReturnValue("v0.107.0") + readFileSyncMock.mockReturnValue('v0.107.0') getLocalNodeInfoMock.mockResolvedValue({ version: '0.108.0 (30e1255 2023-01-30)' }) await nodeService.verifyNodeVersion() expect(showMessageBoxMock).toBeCalledTimes(1) }) it('major is same and minor is not same with major 1', async () => { existsSyncMock.mockReturnValue(true) - readFileSyncMock.mockReturnValue("v1.107.0") + readFileSyncMock.mockReturnValue('v1.107.0') getLocalNodeInfoMock.mockResolvedValue({ version: '1.108.0 (30e1255 2023-01-30)' }) await nodeService.verifyNodeVersion() expect(showMessageBoxMock).toBeCalledTimes(0) }) it('major is not same', async () => { existsSyncMock.mockReturnValue(true) - readFileSyncMock.mockReturnValue("v1.107.0") + readFileSyncMock.mockReturnValue('v1.107.0') getLocalNodeInfoMock.mockResolvedValue({ version: '0.108.0 (30e1255 2023-01-30)' }) await nodeService.verifyNodeVersion() expect(showMessageBoxMock).toBeCalledTimes(1) @@ -497,7 +499,7 @@ describe('NodeService', () => { beforeEach(() => { const NodeService = require('../../src/services/node').default nodeService = new NodeService() - stubbedNetworsServiceGet.mockReturnValueOnce({remote: BUNDLED_CKB_URL}) + stubbedNetworsServiceGet.mockReturnValueOnce({ remote: BUNDLED_CKB_URL }) }) it('start with indexer', async () => { rpcRequestMock.mockResolvedValue({}) @@ -505,7 +507,7 @@ describe('NodeService', () => { expect(showMessageBoxMock).toBeCalledTimes(0) }) it('start without indexer', async () => { - rpcRequestMock.mockResolvedValue({ error: { code: START_WITHOUT_INDEXER }}) + rpcRequestMock.mockResolvedValue({ error: { code: START_WITHOUT_INDEXER } }) await nodeService.verifyStartWithIndexer() expect(showMessageBoxMock).toBeCalledTimes(1) }) @@ -515,4 +517,4 @@ describe('NodeService', () => { expect(showMessageBoxMock).toBeCalledTimes(1) }) }) -}); +}) diff --git a/packages/neuron-wallet/tests/services/offline-sign.test.ts b/packages/neuron-wallet/tests/services/offline-sign.test.ts index 89d4ca035a..5fbd7e53a2 100644 --- a/packages/neuron-wallet/tests/services/offline-sign.test.ts +++ b/packages/neuron-wallet/tests/services/offline-sign.test.ts @@ -2,7 +2,7 @@ const stubbedElectronShowOpenDialog = jest.fn() const stubbedElectronShowErrorBox = jest.fn() const stubbedReadfileSync = jest.fn() -function resetMocks () { +function resetMocks() { stubbedElectronShowErrorBox.mockReset() stubbedElectronShowOpenDialog.mockReset() stubbedReadfileSync.mockReset() @@ -18,14 +18,14 @@ describe('OfflineSignService', () => { return { dialog: { showOpenDialog: stubbedElectronShowOpenDialog, - showErrorBox: stubbedElectronShowErrorBox - } + showErrorBox: stubbedElectronShowErrorBox, + }, } }) jest.doMock('fs', () => { return { - readFileSync: stubbedReadfileSync + readFileSync: stubbedReadfileSync, } }) @@ -33,7 +33,6 @@ describe('OfflineSignService', () => { }) describe('loadTransactionJSON', () => { - describe('early return', () => { beforeEach(() => { resetMocks() @@ -41,7 +40,7 @@ describe('OfflineSignService', () => { it('early return if user cancel', async () => { stubbedElectronShowOpenDialog.mockReturnValueOnce({ - canceled: true + canceled: true, }) const result = await OfflineSignService.loadTransactionJSON() expect(stubbedElectronShowOpenDialog).toHaveBeenCalled() @@ -51,7 +50,7 @@ describe('OfflineSignService', () => { it('early return if filePath is void', async () => { stubbedElectronShowOpenDialog.mockReturnValueOnce({ - canceled: false + canceled: false, }) const result = await OfflineSignService.loadTransactionJSON() expect(stubbedElectronShowOpenDialog).toHaveBeenCalled() @@ -69,7 +68,7 @@ describe('OfflineSignService', () => { stubbedElectronShowOpenDialog.mockReturnValue({ canceled: false, - filePaths: [filePath] + filePaths: [filePath], }) }) @@ -99,7 +98,7 @@ describe('OfflineSignService', () => { stubbedElectronShowOpenDialog.mockReturnValueOnce({ canceled: false, - filePaths: [filePath] + filePaths: [filePath], }) stubbedReadfileSync.mockReturnValueOnce(`{ "transaction": {} }`) }) diff --git a/packages/neuron-wallet/tests/services/setting.test.ts b/packages/neuron-wallet/tests/services/setting.test.ts index 3412584af5..6b30cee24a 100644 --- a/packages/neuron-wallet/tests/services/setting.test.ts +++ b/packages/neuron-wallet/tests/services/setting.test.ts @@ -24,24 +24,24 @@ jest.mock('../../src/models/store', () => { }) jest.mock('../../src/controllers/app/menu', () => ({ - updateApplicationMenu: () => updateApplicationMenuMock() + updateApplicationMenu: () => updateApplicationMenuMock(), })) jest.mock('electron', () => ({ BrowserWindow: { - getAllWindows: jest.fn().mockReturnValue([]) - } + getAllWindows: jest.fn().mockReturnValue([]), + }, })) jest.mock('path', () => ({ - resolve: () => resolveMock() + resolve: () => resolveMock(), })) jest.mock('env', () => ({ app: { getLocale: () => getLocaleMock(), - getPath: () => getPathMock() - } + getPath: () => getPathMock(), + }, })) describe('SettingsService', () => { @@ -66,7 +66,9 @@ describe('SettingsService', () => { expect(updateApplicationMenuMock).toHaveBeenCalled() }) it('set exception', () => { - expect(() => SettingsService.getInstance().locale = 'zh11' as any).toThrow(new Error(`Locale zh11 not supported`)) + expect(() => (SettingsService.getInstance().locale = 'zh11' as any)).toThrow( + new Error(`Locale zh11 not supported`) + ) }) }) diff --git a/packages/neuron-wallet/tests/services/sign-message.test.ts b/packages/neuron-wallet/tests/services/sign-message.test.ts index 602eac8f8b..90c58e2150 100644 --- a/packages/neuron-wallet/tests/services/sign-message.test.ts +++ b/packages/neuron-wallet/tests/services/sign-message.test.ts @@ -3,25 +3,29 @@ import { AddressNotFound } from '../../src/exceptions' const getAddressesByWalletIdMock = jest.fn() jest.mock('../../src/services/addresses', () => ({ - getAddressesByWalletId: () => getAddressesByWalletIdMock() + getAddressesByWalletId: () => getAddressesByWalletIdMock(), })) const walletMock = jest.fn().mockReturnValue({ - isHardware: () => false + isHardware: () => false, }) jest.mock('../../src/services/wallets', () => ({ getInstance: () => ({ - get() { return walletMock() } - }) + get() { + return walletMock() + }, + }), })) const hardWalletMock = jest.fn() jest.mock('../../src/services/hardware', () => ({ getInstance: () => ({ - getCurrent() { return hardWalletMock() } - }) + getCurrent() { + return hardWalletMock() + }, + }), })) // @ts-ignore: Private method @@ -31,7 +35,7 @@ jest // @ts-ignore: Private method .spyOn(SignMessage, 'getPrivateKey') // @ts-ignore - .mockImplementation((...args) => getPrivateKeyMock(...args)); + .mockImplementation((...args) => getPrivateKeyMock(...args)) describe(`SignMessage`, () => { const info = { @@ -39,7 +43,8 @@ describe(`SignMessage`, () => { message: 'HelloWorld', digest: '0xdfb48ccf7126479c052f68cb4202cd094632d30198a322e3c3638679bc73858d', address: 'ckb1qyqrdsefa43s6m882pcj53m4gdnj4k440axqdt9rtd', - signture: '0x97ed8c48879eed50743532bf7cc53e641c501509d2be19d06e6496dd944a21b4509136f18c8e139cc4002822b2deb5cbaff8e44b8782769af3113ff7fb8bd92700' + signture: + '0x97ed8c48879eed50743532bf7cc53e641c501509d2be19d06e6496dd944a21b4509136f18c8e139cc4002822b2deb5cbaff8e44b8782769af3113ff7fb8bd92700', } const extendedKeyInfo = { @@ -53,7 +58,8 @@ describe(`SignMessage`, () => { privateKey: '0x848422863825f69e66dc7f48a3302459ec845395370c23578817456ad6b04b14', message: 'HelloWorld', address: 'ckb1qyqgnjay335t89u0rpwlr8e3vd9msu8fgcuszgdmkp', - signture: '0x0050e46c60cee0b85387a3d16300d74f4761b157857f13ee0ab9cc8df419dd265bbd4babc9ef4c1fb39803d2afd0901104271da026087200a154f037fd88cef201', + signture: + '0x0050e46c60cee0b85387a3d16300d74f4761b157857f13ee0ab9cc8df419dd265bbd4babc9ef4c1fb39803d2afd0901104271da026087200a154f037fd88cef201', } const signInfo2 = { @@ -66,13 +72,14 @@ describe(`SignMessage`, () => { } describe('with extended key', () => { - SignMessage.GENERATE_COUNT = 3 describe('sign', () => { it('not match wallet address', async () => { getAddressesByWalletIdMock.mockReturnValueOnce([]) - await expect(SignMessage.sign('walletId', signInfo.address, extendedKeyInfo.password, signInfo.message)).rejects.toThrow(new AddressNotFound()) + await expect( + SignMessage.sign('walletId', signInfo.address, extendedKeyInfo.password, signInfo.message) + ).rejects.toThrow(new AddressNotFound()) }) it('with generate', async () => { @@ -93,7 +100,7 @@ describe(`SignMessage`, () => { }) }) - it("signByPrivateKey", () => { + it('signByPrivateKey', () => { // @ts-ignore: Private method const sig = SignMessage.signByPrivateKey(info.privateKey, info.message) expect(sig).toEqual(info.signture) diff --git a/packages/neuron-wallet/tests/services/transactions.test.ts b/packages/neuron-wallet/tests/services/transactions.test.ts index d3654b557c..7500dbfca9 100644 --- a/packages/neuron-wallet/tests/services/transactions.test.ts +++ b/packages/neuron-wallet/tests/services/transactions.test.ts @@ -76,40 +76,36 @@ describe('transactions service', () => { const connection = getConnection() await connection.synchronize(true) - txs = [ - generateTx('0x1', '1'), - generateTx('0x2', '2'), - generateTx('0x3', '3'), - ] + txs = [generateTx('0x1', '1'), generateTx('0x2', '2'), generateTx('0x3', '3')] await getConnection().manager.save(txs) }) describe('when none of the transaction hashes exists', () => { beforeEach(() => { hashes = ['0x4'] - }); + }) it('returns all hashes', async () => { const nonExistHashes = await TransactionsService.checkNonExistTransactionsByHashes(hashes) expect(nonExistHashes).toEqual(hashes) - }); - }); + }) + }) describe('when all of the transaction hashes exists', () => { beforeEach(() => { hashes = txs.map(tx => tx.hash) - }); + }) it('returns empty array', async () => { const nonExistHashes = await TransactionsService.checkNonExistTransactionsByHashes(hashes) expect(nonExistHashes).toEqual([]) }) - }); + }) describe('when some of the transaction hashes exists', () => { beforeEach(() => { hashes = ['0x4', txs[1].hash, '0x5'] - }); + }) it('returns the ones not exsit', async () => { const nonExistHashes = await TransactionsService.checkNonExistTransactionsByHashes(hashes) expect(nonExistHashes).toEqual(['0x4', '0x5']) }) - }); - }); + }) + }) }) diff --git a/packages/neuron-wallet/tests/services/tx-wallet.test.ts b/packages/neuron-wallet/tests/services/tx-wallet.test.ts index ba4eeee63f..d9730351e1 100644 --- a/packages/neuron-wallet/tests/services/tx-wallet.test.ts +++ b/packages/neuron-wallet/tests/services/tx-wallet.test.ts @@ -14,13 +14,15 @@ describe('sign witness', () => { } const privateKey: string = '0xe79f3207ea4980b7fed79956d5934249ceac4751a4fae01a0f7c4a96884bc4e3' const txHash = '0x00f5f31941964004d665a8762df8eb4fab53b5ef8437b7d34a38e018b1409054' - const expectedData = ['0x5500000010000000550000005500000041000000aa6de884b0dd0378383cedddc39790b5cad66e42d5dc7655de728ee7eb3a53be071605d76641ad26766c6ed4864e67dbc2cd1526e006c9be7ccfa9b8cbf9e7c701'] + const expectedData = [ + '0x5500000010000000550000005500000041000000aa6de884b0dd0378383cedddc39790b5cad66e42d5dc7655de728ee7eb3a53be071605d76641ad26766c6ed4864e67dbc2cd1526e006c9be7ccfa9b8cbf9e7c701', + ] it('success', () => { const ckb = new CKB('') const newWitness = ckb.signWitnesses(privateKey)({ witnesses: [witness], - transactionHash: txHash + transactionHash: txHash, }) expect(newWitness).toEqual(expectedData) }) @@ -66,7 +68,7 @@ describe('get keys with paths', () => { const masterPrivateKey = wallet.loadKeystore().extendedPrivateKey(password) expect(masterKeychain.privateKey.toString('hex')).toEqual(masterPrivateKey.privateKey) - const pathsAndKeys = (new TransactionSender()).getPrivateKeys(wallet, [receivingPath, changePath], password) + const pathsAndKeys = new TransactionSender().getPrivateKeys(wallet, [receivingPath, changePath], password) expect(pathsAndKeys[0]).toEqual({ path: receivingPath, privateKey: receivingPrivateKey, @@ -88,7 +90,7 @@ describe('epoch', () => { it('parse epoch', () => { // @ts-ignore: Private method - const result = (new TransactionSender()).parseEpoch(epochInfo.epoch) + const result = new TransactionSender().parseEpoch(epochInfo.epoch) expect(result.length).toEqual(epochInfo.length) expect(result.index).toEqual(epochInfo.index) @@ -97,7 +99,7 @@ describe('epoch', () => { it('epoch since', () => { // @ts-ignore: Private method - const epoch = (new TransactionSender()).epochSince(epochInfo.length, epochInfo.index, epochInfo.number) + const epoch = new TransactionSender().epochSince(epochInfo.length, epochInfo.index, epochInfo.number) expect(epoch).toEqual(epochInfo.epoch + (BigInt(0x20) << BigInt(56))) }) diff --git a/packages/neuron-wallet/tests/services/tx/transaction-generator.test.ts b/packages/neuron-wallet/tests/services/tx/transaction-generator.test.ts index 7e5c712260..84daf602bc 100644 --- a/packages/neuron-wallet/tests/services/tx/transaction-generator.test.ts +++ b/packages/neuron-wallet/tests/services/tx/transaction-generator.test.ts @@ -24,7 +24,7 @@ import { LiveCapacityNotEnough, MigrateSudtCellNoTypeError, SudtAcpHaveDataError, - TargetOutputNotFoundError + TargetOutputNotFoundError, } from '../../../src/exceptions' import LiveCell from '../../../src/models/chain/live-cell' import { keyInfos } from '../../setupAndTeardown/public-key-info.fixture' @@ -50,7 +50,7 @@ const fullAddressLockScript: Script = new Script( const fullAddressInfo = { lockScript: fullAddressLockScript, lockHash: fullAddressLockScript.computeHash(), - address: scriptToAddress(fullAddressLockScript, false) + address: scriptToAddress(fullAddressLockScript, false), } // diff = 1000min @@ -68,13 +68,13 @@ const getCurrentMock = jest.fn() jest.doMock('../../../src/services/wallets', () => ({ getInstance() { return { - getCurrent: getCurrentMock + getCurrent: getCurrentMock, } - } + }, })) jest.mock('../../../src/models/asset-account-info', () => { const originalModule = jest.requireActual('../../../src/models/asset-account-info').default - return function() { + return function () { return new originalModule('0x92b197aa1fba0f63633922c61c92375c9c074a93e85963554f5499fe1450d0e6') } }) @@ -93,24 +93,24 @@ describe('TransactionGenerator', () => { SystemScriptInfo.getInstance().secpOutPointInfo = new Map([ [ '0x92b197aa1fba0f63633922c61c92375c9c074a93e85963554f5499fe1450d0e5', - new OutPoint('0x71a7ba8fc96349fea0ed3a5c47992e3b4084b031a42264a018e0072e8172e46c', '0') - ] + new OutPoint('0x71a7ba8fc96349fea0ed3a5c47992e3b4084b031a42264a018e0072e8172e46c', '0'), + ], ]) // @ts-ignore: Private method SystemScriptInfo.getInstance().daoOutPointInfo = new Map([ [ '0x92b197aa1fba0f63633922c61c92375c9c074a93e85963554f5499fe1450d0e5', - new OutPoint('0xe2fb199810d49a4d8beec56718ba2593b665db9d52299a0f9e6e75416d73ff5c', '2') - ] + new OutPoint('0xe2fb199810d49a4d8beec56718ba2593b665db9d52299a0f9e6e75416d73ff5c', '2'), + ], ]) // @ts-ignore: Private method SystemScriptInfo.getInstance().multiSignOutPointInfo = new Map([ [ '0x92b197aa1fba0f63633922c61c92375c9c074a93e85963554f5499fe1450d0e5', - new OutPoint('0x71a7ba8fc96349fea0ed3a5c47992e3b4084b031a42264a018e0072e8172e46c', '1') - ] + new OutPoint('0x71a7ba8fc96349fea0ed3a5c47992e3b4084b031a42264a018e0072e8172e46c', '1'), + ], ]) const mockTipHeader = jest.fn() @@ -226,7 +226,7 @@ describe('TransactionGenerator', () => { beforeEach(async () => { const cells: OutputEntity[] = [ generateCell(toShannon('1000'), OutputStatus.Live, false, null), - generateCell(toShannon('2000'), OutputStatus.Live, false, null) + generateCell(toShannon('2000'), OutputStatus.Live, false, null), ] await getConnection().manager.save(cells) }) @@ -240,8 +240,8 @@ describe('TransactionGenerator', () => { [ { address: bob.address, - capacity: toShannon('500') - } + capacity: toShannon('500'), + }, ], bob.address, '0', @@ -270,8 +270,8 @@ describe('TransactionGenerator', () => { [ { address: bob.address, - capacity: toShannon('1000') - } + capacity: toShannon('1000'), + }, ], bob.address, '0', @@ -299,8 +299,8 @@ describe('TransactionGenerator', () => { [ { address: bob.address, - capacity: BigInt(1000 * 10 ** 8 - 355).toString() - } + capacity: BigInt(1000 * 10 ** 8 - 355).toString(), + }, ], bob.address, '0', @@ -328,8 +328,8 @@ describe('TransactionGenerator', () => { [ { address: bob.address, - capacity: (BigInt(1000 * 10 ** 8) - BigInt(464) + BigInt(1)).toString() - } + capacity: (BigInt(1000 * 10 ** 8) - BigInt(464) + BigInt(1)).toString(), + }, ], bob.address, '0', @@ -359,12 +359,12 @@ describe('TransactionGenerator', () => { [ { address: bob.address, - capacity: BigInt(1000 * 10 ** 8).toString() + capacity: BigInt(1000 * 10 ** 8).toString(), }, { address: alice.address, - capacity: BigInt(2500 * 10 ** 8).toString() - } + capacity: BigInt(2500 * 10 ** 8).toString(), + }, ], bob.address, '0', @@ -385,8 +385,8 @@ describe('TransactionGenerator', () => { [ { address: fullAddressInfo.address, - capacity: BigInt(43 * 10 ** 8).toString() - } + capacity: BigInt(43 * 10 ** 8).toString(), + }, ], bob.address, '0', @@ -406,8 +406,8 @@ describe('TransactionGenerator', () => { [ { address: fullAddressInfo.address, - capacity: BigInt(42 * 10 ** 8).toString() - } + capacity: BigInt(42 * 10 ** 8).toString(), + }, ], bob.address, '0', @@ -422,12 +422,12 @@ describe('TransactionGenerator', () => { [ { address: fullAddressInfo.address, - capacity: BigInt(1000 * 10 ** 8).toString() + capacity: BigInt(1000 * 10 ** 8).toString(), }, { address: bob.address, - capacity: BigInt(1000 * 10 ** 8).toString() - } + capacity: BigInt(1000 * 10 ** 8).toString(), + }, ], bob.address, '0', @@ -450,8 +450,8 @@ describe('TransactionGenerator', () => { { address: bob.address, capacity: toShannon('500'), - date - } + date, + }, ], bob.address, '0', @@ -486,8 +486,8 @@ describe('TransactionGenerator', () => { [ { address: bob.address, - capacity: toShannon('500') - } + capacity: toShannon('500'), + }, ], bob.address, fee @@ -509,8 +509,8 @@ describe('TransactionGenerator', () => { [ { address: bob.address, - capacity: toShannon('1000') - } + capacity: toShannon('1000'), + }, ], bob.address, fee @@ -532,8 +532,8 @@ describe('TransactionGenerator', () => { [ { address: bob.address, - capacity: (BigInt(1000 * 10 ** 8) - BigInt(fee)).toString() - } + capacity: (BigInt(1000 * 10 ** 8) - BigInt(fee)).toString(), + }, ], bob.address, fee @@ -555,8 +555,8 @@ describe('TransactionGenerator', () => { [ { address: bob.address, - capacity: (BigInt(1000 * 10 ** 8) - BigInt(fee) + BigInt(1)).toString() - } + capacity: (BigInt(1000 * 10 ** 8) - BigInt(fee) + BigInt(1)).toString(), + }, ], bob.address, fee @@ -579,7 +579,7 @@ describe('TransactionGenerator', () => { const cells: OutputEntity[] = [ generateCell(toShannon('1000'), OutputStatus.Live, false, null), generateCell(toShannon('2000'), OutputStatus.Live, false, null), - generateCell(toShannon('3000'), OutputStatus.Live, false, null, alice) + generateCell(toShannon('3000'), OutputStatus.Live, false, null, alice), ] await getConnection().manager.save(cells) }) @@ -589,16 +589,16 @@ describe('TransactionGenerator', () => { const targetOutputs: TargetOutput[] = [ { address: bob.address, - capacity: toShannon('500') + capacity: toShannon('500'), }, { address: alice.address, - capacity: toShannon('1000') + capacity: toShannon('1000'), }, { address: bob.address, - capacity: toShannon('0') - } + capacity: toShannon('0'), + }, ] it('with fee 800', async () => { @@ -657,12 +657,12 @@ describe('TransactionGenerator', () => { [ { address: fullAddressInfo.address, - capacity: toShannon('43') + capacity: toShannon('43'), }, { address: fullAddressInfo.address, - capacity: toShannon('0') - } + capacity: toShannon('0'), + }, ], '0', feeRate @@ -690,12 +690,12 @@ describe('TransactionGenerator', () => { [ { address: fullAddressInfo.address, - capacity: toShannon('42') + capacity: toShannon('42'), }, { address: fullAddressInfo.address, - capacity: toShannon('0') - } + capacity: toShannon('0'), + }, ], '0', feeRate @@ -712,8 +712,8 @@ describe('TransactionGenerator', () => { { address: bob.address, capacity: toShannon('500'), - date - } + date, + }, ], '0', feeRate @@ -736,8 +736,8 @@ describe('TransactionGenerator', () => { lockScript: Script.fromObject({ codeHash: '0x5c5069eb0857efc65e1bca0c07df34c31663b3622fd3876c876320fc9634e2a8', hashType: ScriptHashType.Type, - args: '0x87b9ae2c1c7108178e709bf4a89b736bc0f0ae60' - }) + args: '0x87b9ae2c1c7108178e709bf4a89b736bc0f0ae60', + }), }) const feeRate = '1000' const tx: Transaction = await TransactionGenerator.generateSendingAllTx( @@ -750,9 +750,11 @@ describe('TransactionGenerator', () => { r: 1, m: 2, n: 3, - blake160s: ( - ['ckt1qyqdpymnu202x3p4cnrrgek5czcdsg95xznswjr98y', 'ckt1qyqdpymnu202x3p4cnrrgek5czcdsg95xznswjr98y', 'ckt1qyqwqcknusdreymrhhme00hg9af3pr5hcmwqzfxvda'] - ).map(v => addressToScript(v).args), + blake160s: [ + 'ckt1qyqdpymnu202x3p4cnrrgek5czcdsg95xznswjr98y', + 'ckt1qyqdpymnu202x3p4cnrrgek5czcdsg95xznswjr98y', + 'ckt1qyqwqcknusdreymrhhme00hg9af3pr5hcmwqzfxvda', + ].map(v => addressToScript(v).args), }) ) @@ -782,7 +784,7 @@ describe('TransactionGenerator', () => { beforeEach(async () => { const cells: OutputEntity[] = [ generateCell(toShannon('1000'), OutputStatus.Live, false, null), - generateCell(toShannon('2000'), OutputStatus.Live, false, null) + generateCell(toShannon('2000'), OutputStatus.Live, false, null), ] await getConnection().manager.save(cells) }) @@ -863,7 +865,7 @@ describe('TransactionGenerator', () => { beforeEach(async () => { const cells: OutputEntity[] = [ generateCell(toShannon('1000'), OutputStatus.Live, false, null), - generateCell(toShannon('2000'), OutputStatus.Live, false, null) + generateCell(toShannon('2000'), OutputStatus.Live, false, null), ] await getConnection().manager.save(cells) }) @@ -1000,7 +1002,7 @@ describe('TransactionGenerator', () => { generateCell(toShannon('1000'), OutputStatus.Sent, false, null), generateCell(toShannon('1000'), OutputStatus.Dead, false, null), generateCell(toShannon('1000'), OutputStatus.Pending, false, null), - generateCell(toShannon('1000'), OutputStatus.Failed, false, null) + generateCell(toShannon('1000'), OutputStatus.Failed, false, null), ] await getConnection().manager.save(cells) @@ -1031,11 +1033,11 @@ describe('TransactionGenerator', () => { describe('generateWithdrawMultiSignTx', () => { const prevOutput = Output.fromObject({ capacity: toShannon('1000'), - lock: SystemScriptInfo.generateMultiSignScript(new Multisig().args(bob.lockScript.args, 100, '0x7080018000001')) + lock: SystemScriptInfo.generateMultiSignScript(new Multisig().args(bob.lockScript.args, 100, '0x7080018000001')), }) const outPoint = OutPoint.fromObject({ txHash: '0x' + '0'.repeat(64), - index: '1' + index: '1', }) describe('with feeRate 1000', () => { @@ -1091,17 +1093,17 @@ describe('TransactionGenerator', () => { block_hash: randomHex(), out_point: { tx_hash: randomHex(), - index: '0x0' + index: '0x0', }, cell_output: { capacity: capacity, lock: { code_hash: lockScript.codeHash, args: lockScript.args, - hash_type: lockScript.hashType.toString() - } + hash_type: lockScript.hashType.toString(), + }, }, - data: '0x' + data: '0x', } if (tokenID) { const typeScript = assetAccountInfo.generateSudtScript(tokenID) @@ -1109,7 +1111,7 @@ describe('TransactionGenerator', () => { liveCell.cell_output.type = { code_hash: typeScript.codeHash, args: typeScript.args, - hash_type: typeScript.hashType.toString() + hash_type: typeScript.hashType.toString(), } } liveCell.data = amount ? BufferUtils.writeBigUInt128LE(BigInt(amount)) : '0x' @@ -1123,7 +1125,7 @@ describe('TransactionGenerator', () => { beforeEach(async () => { const cells: OutputEntity[] = [ generateCell(toShannon('1000'), OutputStatus.Live, false, null, alice), - generateCell(toShannon('2000'), OutputStatus.Live, false, null, bob) + generateCell(toShannon('2000'), OutputStatus.Live, false, null, bob), ] await getConnection().manager.save(cells) }) @@ -1143,7 +1145,7 @@ describe('TransactionGenerator', () => { capacity: toShannon('61'), lock: aliceAnyoneCanPayLockScript, type: null, - data: '0x' + data: '0x', }) tx = await TransactionGenerator.generateAnyoneCanPayToCKBTx( @@ -1193,7 +1195,7 @@ describe('TransactionGenerator', () => { capacity: toShannon('61'), lock: aliceAnyoneCanPayLockScript, type: assetAccountInfo.generateSudtScript('0xuuid'), - data: '0x' + data: '0x', }) tx = await TransactionGenerator.generateAnyoneCanPayToCKBTx( @@ -1250,7 +1252,7 @@ describe('TransactionGenerator', () => { capacity: toShannon('61'), lock: pwAnyoneCanPayLockScript, type: null, - data: '0x' + data: '0x', }) tx = await TransactionGenerator.generateAnyoneCanPayToCKBTx( @@ -1293,7 +1295,7 @@ describe('TransactionGenerator', () => { capacity: toShannon('61'), lock: aliceAnyoneCanPayLockScript, type: null, - data: '0x' + data: '0x', }) beforeEach(() => { when(stubbedQueryIndexer) @@ -1324,7 +1326,7 @@ describe('TransactionGenerator', () => { capacity: toShannon('61'), lock: aliceAnyoneCanPayLockScript, type: null, - data: '0x' + data: '0x', }) let expectedTxSize: number let expectedTxFee: string @@ -1334,7 +1336,7 @@ describe('TransactionGenerator', () => { .calledWith({ lock: bobAnyoneCanPayLockScript, type: null, data: null }) .mockResolvedValue([ generateLiveCell(toShannon('62'), undefined, undefined, bobAnyoneCanPayLockScript), - generateLiveCell(toShannon('62'), undefined, undefined, bobAnyoneCanPayLockScript) + generateLiveCell(toShannon('62'), undefined, undefined, bobAnyoneCanPayLockScript), ]) tx = await TransactionGenerator.generateAnyoneCanPayToCKBTx( @@ -1377,7 +1379,7 @@ describe('TransactionGenerator', () => { capacity: toShannon('61'), lock: aliceAnyoneCanPayLockScript, type: null, - data: '0x' + data: '0x', }) let tx: Transaction let expectedTxSize: number @@ -1427,14 +1429,14 @@ describe('TransactionGenerator', () => { capacity: toShannon('61'), lock: bobAnyoneCanPayLockScript, type: null, - data: '0x' + data: '0x', }) let tx: Transaction const customData = '0x000000' const cellsByAlice = [ generateLiveCell(toShannon('62'), undefined, undefined, aliceAnyoneCanPayLockScript, customData), - generateLiveCell(toShannon('62'), undefined, undefined, aliceAnyoneCanPayLockScript) + generateLiveCell(toShannon('62'), undefined, undefined, aliceAnyoneCanPayLockScript), ] beforeEach(async () => { when(stubbedQueryIndexer) @@ -1467,7 +1469,7 @@ describe('TransactionGenerator', () => { capacity: toShannon('61'), lock: aliceAnyoneCanPayLockScript, type: null, - data: '0x' + data: '0x', }) beforeEach(() => { when(stubbedQueryIndexer) @@ -1498,7 +1500,7 @@ describe('TransactionGenerator', () => { capacity: toShannon('61'), lock: aliceAnyoneCanPayLockScript, type: null, - data: '0x' + data: '0x', }) let tx: Transaction describe('with all ACP cells without data', () => { @@ -1507,7 +1509,7 @@ describe('TransactionGenerator', () => { .calledWith({ lock: bobAnyoneCanPayLockScript, type: null, data: null }) .mockResolvedValue([ generateLiveCell(toShannon('70'), undefined, undefined, bobAnyoneCanPayLockScript), - generateLiveCell(toShannon('70'), undefined, undefined, bobAnyoneCanPayLockScript) + generateLiveCell(toShannon('70'), undefined, undefined, bobAnyoneCanPayLockScript), ]) tx = await TransactionGenerator.generateAnyoneCanPayToCKBTx( walletId1, @@ -1548,7 +1550,7 @@ describe('TransactionGenerator', () => { .calledWith({ lock: bobAnyoneCanPayLockScript, type: null, data: null }) .mockResolvedValue([ generateLiveCell(toShannon('70'), undefined, undefined, bobAnyoneCanPayLockScript), - generateLiveCell(toShannon('70'), undefined, undefined, bobAnyoneCanPayLockScript, '0x00') + generateLiveCell(toShannon('70'), undefined, undefined, bobAnyoneCanPayLockScript, '0x00'), ]) .calledWith({ lock: aliceAnyoneCanPayLockScript, type: null, data: null }) .mockResolvedValue([generateLiveCell(toShannon('61'), undefined, undefined, aliceAnyoneCanPayLockScript)]) @@ -1590,7 +1592,7 @@ describe('TransactionGenerator', () => { .calledWith({ lock: bobAnyoneCanPayLockScript, type: assetAccountInfo.generateSudtScript(tokenID), - data: null + data: null, }) .mockResolvedValue([generateLiveCell(toShannon('150'), '1000', tokenID)]) @@ -1601,7 +1603,7 @@ describe('TransactionGenerator', () => { lock: targetLiveCell.lock(), type: targetLiveCell.type(), data: targetLiveCell.data, - outPoint: new OutPoint('0x1558c9aed78d657eba858302b56800a8270aa7b43426d82c58cf96ae4afd6774', '0x0') + outPoint: new OutPoint('0x1558c9aed78d657eba858302b56800a8270aa7b43426d82c58cf96ae4afd6774', '0x0'), }) tx = await TransactionGenerator.generateAnyoneCanPayToSudtTx( @@ -1626,7 +1628,7 @@ describe('TransactionGenerator', () => { expect(tx.outputs.length).toEqual(2) expect(tx.outputs.map(o => o.lockHash)).toEqual([ bobAnyoneCanPayLockScript.computeHash(), - aliceAnyoneCanPayLockScript.computeHash() + aliceAnyoneCanPayLockScript.computeHash(), ]) }) it('calculates fees', () => { @@ -1634,7 +1636,7 @@ describe('TransactionGenerator', () => { const expectedOutputCapacities: bigint[] = [ BigInt(toShannon('150')) - BigInt(tx.fee ?? 0), - BigInt(toShannon('142')) + BigInt(toShannon('142')), ] expect(tx.outputs.map(o => BigInt(o.capacity))).toEqual(expectedOutputCapacities) @@ -1650,7 +1652,7 @@ describe('TransactionGenerator', () => { it('updates output data', () => { expect(tx.outputsData).toEqual([ BufferUtils.writeBigUInt128LE(BigInt(900)), - BufferUtils.writeBigUInt128LE(BigInt(200)) + BufferUtils.writeBigUInt128LE(BigInt(200)), ]) }) }) @@ -1675,7 +1677,7 @@ describe('TransactionGenerator', () => { lock: targetLiveCell.lock(), type: targetLiveCell.type(), data: targetLiveCell.data, - outPoint: new OutPoint('0x1558c9aed78d657eba858302b56800a8270aa7b43426d82c58cf96ae4afd6774', '0x0') + outPoint: new OutPoint('0x1558c9aed78d657eba858302b56800a8270aa7b43426d82c58cf96ae4afd6774', '0x0'), }) tx = await TransactionGenerator.generateAnyoneCanPayToSudtTx( @@ -1706,7 +1708,7 @@ describe('TransactionGenerator', () => { .calledWith({ lock: bobAnyoneCanPayLockScript, type: assetAccountInfo.generateSudtScript(tokenID), - data: null + data: null, }) .mockResolvedValue([generateLiveCell(toShannon('150'), '100', tokenID)]) @@ -1716,7 +1718,7 @@ describe('TransactionGenerator', () => { lock: targetLiveCell.lock(), type: targetLiveCell.type(), data: targetLiveCell.data, - outPoint: new OutPoint('0x1558c9aed78d657eba858302b56800a8270aa7b43426d82c58cf96ae4afd6774', '0x0') + outPoint: new OutPoint('0x1558c9aed78d657eba858302b56800a8270aa7b43426d82c58cf96ae4afd6774', '0x0'), }) }) it('throws error CapacityNotEnough', async () => { @@ -1746,7 +1748,7 @@ describe('TransactionGenerator', () => { .calledWith({ lock: bobAnyoneCanPayLockScript, type: assetAccountInfo.generateSudtScript(tokenID), - data: null + data: null, }) .mockResolvedValue([generateLiveCell(toShannon('142'), '1000', tokenID)]) @@ -1757,7 +1759,7 @@ describe('TransactionGenerator', () => { lock: targetLiveCell.lock(), type: targetLiveCell.type(), data: targetLiveCell.data, - outPoint: new OutPoint('0x1558c9aed78d657eba858302b56800a8270aa7b43426d82c58cf96ae4afd6774', '0x0') + outPoint: new OutPoint('0x1558c9aed78d657eba858302b56800a8270aa7b43426d82c58cf96ae4afd6774', '0x0'), }) tx = await TransactionGenerator.generateAnyoneCanPayToSudtTx( @@ -1783,7 +1785,7 @@ describe('TransactionGenerator', () => { expect(tx.outputs.map(o => o.lockHash)).toEqual([ bobAnyoneCanPayLockScript.computeHash(), aliceAnyoneCanPayLockScript.computeHash(), - bob.lockScript.computeHash() + bob.lockScript.computeHash(), ]) }) it('calculates fees', () => { @@ -1791,7 +1793,7 @@ describe('TransactionGenerator', () => { const expectedOutputCapacities: bigint[] = [ BigInt(toShannon('142')), BigInt(toShannon('142')), - BigInt(toShannon('1000')) - BigInt(tx.fee ?? 0) + BigInt(toShannon('1000')) - BigInt(tx.fee ?? 0), ] expect(tx.outputs.map(o => BigInt(o.capacity))).toEqual(expectedOutputCapacities) @@ -1808,7 +1810,7 @@ describe('TransactionGenerator', () => { expect(tx.outputsData).toEqual([ BufferUtils.writeBigUInt128LE(BigInt(900)), BufferUtils.writeBigUInt128LE(BigInt(200)), - '0x' + '0x', ]) }) }) @@ -1821,11 +1823,11 @@ describe('TransactionGenerator', () => { .calledWith({ lock: bobAnyoneCanPayLockScript, type: assetAccountInfo.generateSudtScript(tokenID), - data: null + data: null, }) .mockResolvedValue([ generateLiveCell(toShannon('143'), '50', tokenID), - generateLiveCell(toShannon('142'), '1000', tokenID) + generateLiveCell(toShannon('142'), '1000', tokenID), ]) const targetLiveCell: LiveCell = LiveCell.fromLumos(targetLiveCellEntity) @@ -1835,7 +1837,7 @@ describe('TransactionGenerator', () => { lock: targetLiveCell.lock(), type: targetLiveCell.type(), data: targetLiveCell.data, - outPoint: new OutPoint('0x1558c9aed78d657eba858302b56800a8270aa7b43426d82c58cf96ae4afd6774', '0x0') + outPoint: new OutPoint('0x1558c9aed78d657eba858302b56800a8270aa7b43426d82c58cf96ae4afd6774', '0x0'), }) tx = await TransactionGenerator.generateAnyoneCanPayToSudtTx( @@ -1860,7 +1862,7 @@ describe('TransactionGenerator', () => { expect(tx.outputs.map(o => o.lockHash)).toEqual([ bobAnyoneCanPayLockScript.computeHash(), - aliceAnyoneCanPayLockScript.computeHash() + aliceAnyoneCanPayLockScript.computeHash(), ]) }) it('calculates fees', () => { @@ -1877,14 +1879,14 @@ describe('TransactionGenerator', () => { const expectedOutputCapacities: bigint[] = [ BigInt(toShannon('143')) + BigInt(toShannon('142')) - BigInt(tx.fee ?? 0), - BigInt(toShannon('142')) + BigInt(toShannon('142')), ] expect(tx.outputs.map(o => BigInt(o.capacity))).toEqual(expectedOutputCapacities) }) it('updates output data', () => { expect(tx.outputsData).toEqual([ BufferUtils.writeBigUInt128LE(BigInt(950)), - BufferUtils.writeBigUInt128LE(BigInt(200)) + BufferUtils.writeBigUInt128LE(BigInt(200)), ]) }) }) @@ -1898,7 +1900,7 @@ describe('TransactionGenerator', () => { .calledWith({ lock: bobAnyoneCanPayLockScript, type: assetAccountInfo.generateSudtScript(tokenID), - data: null + data: null, }) .mockResolvedValue([generateLiveCell(toShannon('142'), '50', tokenID)]) @@ -1909,7 +1911,7 @@ describe('TransactionGenerator', () => { lock: targetLiveCell.lock(), type: targetLiveCell.type(), data: targetLiveCell.data, - outPoint: new OutPoint('0x1558c9aed78d657eba858302b56800a8270aa7b43426d82c58cf96ae4afd6774', '0x0') + outPoint: new OutPoint('0x1558c9aed78d657eba858302b56800a8270aa7b43426d82c58cf96ae4afd6774', '0x0'), }) }) it('throws error CapacityNotEnough', async () => { @@ -1939,7 +1941,7 @@ describe('TransactionGenerator', () => { .calledWith({ lock: bobAnyoneCanPayLockScript, type: assetAccountInfo.generateSudtScript(tokenID), - data: null + data: null, }) .mockResolvedValue([generateLiveCell(toShannon('1000'), '1000', tokenID)]) @@ -1950,7 +1952,7 @@ describe('TransactionGenerator', () => { lock: targetLiveCell.lock(), type: targetLiveCell.type(), data: targetLiveCell.data, - outPoint: new OutPoint('0x1558c9aed78d657eba858302b56800a8270aa7b43426d82c58cf96ae4afd6774', '0x0') + outPoint: new OutPoint('0x1558c9aed78d657eba858302b56800a8270aa7b43426d82c58cf96ae4afd6774', '0x0'), }) tx = await TransactionGenerator.generateAnyoneCanPayToSudtTx( @@ -1973,7 +1975,7 @@ describe('TransactionGenerator', () => { const expectedOutputCapacities: bigint[] = [ BigInt(toShannon('1000')) - BigInt(tx.fee ?? 0), - BigInt(toShannon('142')) + BigInt(toShannon('142')), ] expect(tx.outputs.map(o => BigInt(o.capacity))).toEqual(expectedOutputCapacities) @@ -1992,13 +1994,13 @@ describe('TransactionGenerator', () => { expect(tx.outputs.map(o => o.lockHash)).toEqual([ bobAnyoneCanPayLockScript.computeHash(), - aliceAnyoneCanPayLockScript.computeHash() + aliceAnyoneCanPayLockScript.computeHash(), ]) }) it('updates output data', () => { expect(tx.outputsData).toEqual([ BufferUtils.writeBigUInt128LE(BigInt(0)), - BufferUtils.writeBigUInt128LE(BigInt(1100)) + BufferUtils.writeBigUInt128LE(BigInt(1100)), ]) expect(tx.sudtInfo!.amount).toEqual('1000') }) @@ -2012,7 +2014,7 @@ describe('TransactionGenerator', () => { .calledWith({ lock: bobAnyoneCanPayLockScript, type: assetAccountInfo.generateSudtScript(tokenID), - data: null + data: null, }) .mockResolvedValue([generateLiveCell(toShannon('150'), '1000', tokenID)]) @@ -2022,7 +2024,7 @@ describe('TransactionGenerator', () => { capacity: targetLiveCell.capacity, lock: targetLiveCell.lock(), type: targetLiveCell.type(), - data: targetLiveCell.data + data: targetLiveCell.data, }) tx = await TransactionGenerator.generateAnyoneCanPayToSudtTx( @@ -2045,7 +2047,7 @@ describe('TransactionGenerator', () => { expect(tx.outputs.length).toEqual(3) expect(tx.inputs.map(o => o.lockHash)).toEqual([ bobAnyoneCanPayLockScript.computeHash(), - alice.lockScript.computeHash() + alice.lockScript.computeHash(), ]) expect(tx.outputs.map(o => o.lockHash)).toEqual([ bobAnyoneCanPayLockScript.computeHash(), @@ -2076,7 +2078,7 @@ describe('TransactionGenerator', () => { expect(tx.outputsData).toEqual([ BufferUtils.writeBigUInt128LE(BigInt(900)), BufferUtils.writeBigUInt128LE(BigInt(100)), - '0x' + '0x', ]) }) }) @@ -2168,11 +2170,11 @@ describe('TransactionGenerator', () => { .calledWith({ lock: aliceAnyoneCanPayLockScript, type: assetAccountInfo.generateSudtScript(tokenID), - data: null + data: null, }) .mockResolvedValue([ generateLiveCell(toShannon('142'), '100', tokenID, aliceAnyoneCanPayLockScript), - generateLiveCell(toShannon('142'), '100', tokenID, aliceAnyoneCanPayLockScript) + generateLiveCell(toShannon('142'), '100', tokenID, aliceAnyoneCanPayLockScript), ]) expectedChequeOutput = Output.fromObject({ @@ -2182,7 +2184,7 @@ describe('TransactionGenerator', () => { senderDefaultLock.computeHash() ), type: senderAcpLiveCell.type(), - data: BufferUtils.writeBigUInt128LE(BigInt(110)) + data: BufferUtils.writeBigUInt128LE(BigInt(110)), }) assetAccount = new AssetAccount(tokenID, '', '', '', '', '', alice.lockScript.args) }) @@ -2262,7 +2264,7 @@ describe('TransactionGenerator', () => { capacity: toShannon('161'), lock: assetAccountInfo.generateChequeScript(receiverDefaultLockHash, senderDefaultLockHash), type: typeScript, - data: BufferUtils.writeBigUInt128LE(BigInt(chequeAmount)) + data: BufferUtils.writeBigUInt128LE(BigInt(chequeAmount)), }) }) describe('with existing acp cell', () => { @@ -2387,7 +2389,7 @@ describe('TransactionGenerator', () => { transaction, senderAcpOutputEntity, senderDefaultLockInputEntity, - chequeOutputEntity + chequeOutputEntity, ]) const chequeOutput = chequeOutputEntity.toModel() @@ -2437,7 +2439,7 @@ describe('TransactionGenerator', () => { senderAcpOutputEntity, senderLiveAcpOutputEntity, senderDefaultLockInputEntity, - chequeOutputEntity + chequeOutputEntity, ]) const chequeOutput = chequeOutputEntity.toModel() @@ -2462,7 +2464,7 @@ describe('TransactionGenerator', () => { capacity: toShannon('142'), lock: alice.lockScript, type: assetAccountInfo.generateSudtScript('0x2619a9dc0428f87c0921ed22d0f10707c5c4ec9e8185764d8236d7ea996a9b03'), - data: BufferUtils.writeBigUInt128LE(BigInt(100)) + data: BufferUtils.writeBigUInt128LE(BigInt(100)), } it('no wallet', async () => { getCurrentMock.mockReturnValueOnce(undefined) @@ -2492,7 +2494,7 @@ describe('TransactionGenerator', () => { when(stubbedQueryIndexer) .calledWith({ lock: bobAnyoneCanPayLockScript, type: Output.fromObject(sudtCellObject).type, data: null }) .mockResolvedValue([ - generateLiveCell(toShannon('70'), '100', receiverAcpCell.typeArgs!, bobAnyoneCanPayLockScript) + generateLiveCell(toShannon('70'), '100', receiverAcpCell.typeArgs!, bobAnyoneCanPayLockScript), ]) }) it('sudt cell no type', async () => { @@ -2510,7 +2512,7 @@ describe('TransactionGenerator', () => { .calledWith({ lock: addressToScript('ckt1qyq0tejcz8rl6yyjw3m3vnu7r955d9ecj9gq46suu6'), type: sudtCell.type, - data: null + data: null, }) .mockResolvedValue([]) expect( @@ -2530,7 +2532,7 @@ describe('TransactionGenerator', () => { const sudtCell = Output.fromObject(sudtCellObject) getCurrentMock.mockReturnValueOnce({ id: alice.walletId, - getNextChangeAddress: () => ({ address: alice.address }) + getNextChangeAddress: () => ({ address: alice.address }), }) const bobLockHash = scriptToAddress(bobAnyoneCanPayLockScript) const res = (await TransactionGenerator.generateSudtMigrateAcpTx(sudtCell, bobLockHash)) as Transaction @@ -2566,7 +2568,7 @@ describe('TransactionGenerator', () => { id: alice.walletId, getNextChangeAddress: () => ({ address: alice.address }), isHDWallet: () => true, - getNextReceivingAddresses: () => [{ blake160: alice.publicKeyInBlake160 }] + getNextReceivingAddresses: () => [{ blake160: alice.publicKeyInBlake160 }], }) const res = (await TransactionGenerator.generateSudtMigrateAcpTx(sudtCell)) as Transaction expect(res.outputs).toHaveLength(1) @@ -2578,20 +2580,20 @@ describe('TransactionGenerator', () => { const sudtCell = Output.fromObject(sudtCellObject) getCurrentMock.mockReturnValueOnce({ id: alice.walletId, - getNextChangeAddress: () => ({ address: alice.address }) + getNextChangeAddress: () => ({ address: alice.address }), }) expect(TransactionGenerator.generateSudtMigrateAcpTx(sudtCell)).rejects.toThrow() }) it('account capacity not enough for change', async () => { const secpCell = generateCell(toShannon('61'), OutputStatus.Live, false, null, { - lockScript: alice.lockScript + lockScript: alice.lockScript, }) await getConnection().manager.save([receiverAcpCell, secpCell]) const sudtCell = Output.fromObject(sudtCellObject) getCurrentMock.mockReturnValueOnce({ id: alice.walletId, - getNextChangeAddress: () => ({ address: alice.address }) + getNextChangeAddress: () => ({ address: alice.address }), }) expect(TransactionGenerator.generateSudtMigrateAcpTx(sudtCell)).rejects.toThrow() }) @@ -2706,17 +2708,19 @@ describe('TransactionGenerator', () => { { lockScript: legacyACPLock }, undefined, BufferUtils.writeBigUInt128LE(BigInt(100)) - ) + ), ] await getConnection().manager.save(cells) }) it('generates acp migration transaction', async () => { const tx = (await TransactionGenerator.generateMigrateLegacyACPTx(alice.walletId))! - const totalLegacyACPCellsCount = tx.inputs.filter(input => input.lockHash === legacyACPLock.computeHash()) - .length + const totalLegacyACPCellsCount = tx.inputs.filter( + input => input.lockHash === legacyACPLock.computeHash() + ).length const totalMigratedACPCellsCount = tx.outputs.filter(output => output.lockHash === acpLock.computeHash()).length - const totalMigratedSUDTCellCount = tx.outputs.filter(output => output.typeHash === sudtScript.computeHash()) - .length + const totalMigratedSUDTCellCount = tx.outputs.filter( + output => output.typeHash === sudtScript.computeHash() + ).length const normalInputCellCapacity = tx.inputs .filter(input => input.lockHash === defaultLock.computeHash()) .reduce((sum, input) => { @@ -2772,7 +2776,7 @@ describe('TransactionGenerator', () => { { lockScript: acpLock }, undefined, BufferUtils.writeBigUInt128LE(BigInt(100)) - ) + ), ] await getConnection().manager.save(cells) }) @@ -2785,7 +2789,7 @@ describe('TransactionGenerator', () => { beforeEach(async () => { const cells = [ generateCell(toShannon('1000'), OutputStatus.Live, false, null, { lockScript: legacyACPLock }), - generateCell(toShannon('61'), OutputStatus.Live, false, null, { lockScript: defaultLock }) + generateCell(toShannon('61'), OutputStatus.Live, false, null, { lockScript: defaultLock }), ] await getConnection().manager.save(cells) }) diff --git a/packages/neuron-wallet/tests/services/tx/transaction-persistor.test.ts b/packages/neuron-wallet/tests/services/tx/transaction-persistor.test.ts index 391b0b8db1..391af9d05c 100644 --- a/packages/neuron-wallet/tests/services/tx/transaction-persistor.test.ts +++ b/packages/neuron-wallet/tests/services/tx/transaction-persistor.test.ts @@ -1,8 +1,8 @@ -import Transaction from "../../../src/models/chain/transaction" -import { TransactionPersistor, TxSaveType } from "../../../src/services/tx" -import initConnection from "../../../src/database/chain/ormconfig" -import TransactionEntity from "../../../src/database/chain/entities/transaction" -import { getConnection } from "typeorm" +import Transaction from '../../../src/models/chain/transaction' +import { TransactionPersistor, TxSaveType } from '../../../src/services/tx' +import initConnection from '../../../src/database/chain/ormconfig' +import TransactionEntity from '../../../src/database/chain/entities/transaction' +import { getConnection } from 'typeorm' import transactions from '../../setupAndTeardown/transactions.fixture' const [tx, tx2] = transactions @@ -26,13 +26,13 @@ describe('TransactionPersistor', () => { const multiSignBlake160 = '0x' + '6'.repeat(40) beforeEach(async () => { await TransactionPersistor.convertTransactionAndSave(tx, TxSaveType.Fetch) - }); + }) describe('when saved another transaction consuming an input from the previous transaction', () => { beforeEach(async () => { expect(tx.outputs[1].outPoint).toEqual(tx2.inputs[0].previousOutput) await TransactionPersistor.convertTransactionAndSave(tx2, TxSaveType.Fetch) - }); + }) describe('when updated an output of the previous transaction', () => { const txDup = Transaction.fromObject({ ...tx }) @@ -62,8 +62,8 @@ describe('TransactionPersistor', () => { expect(loadedTx2!.inputs[0].multiSignBlake160).toEqual(multiSignBlake160) expect(loadedTx2!.outputs[0].multiSignBlake160).toBe(null) }) - }); - }); - }); + }) + }) + }) }) }) diff --git a/packages/neuron-wallet/tests/services/tx/transaction-sender.test.ts b/packages/neuron-wallet/tests/services/tx/transaction-sender.test.ts index 63d6bf675e..44f18dcbf2 100644 --- a/packages/neuron-wallet/tests/services/tx/transaction-sender.test.ts +++ b/packages/neuron-wallet/tests/services/tx/transaction-sender.test.ts @@ -48,17 +48,17 @@ stubbedRPCServiceConstructor.mockImplementation(() => ({ getTransaction: stubbedGetTransaction, getBlockByNumber: stubbedGetBlockByNumber, getHeaderByNumber: stubbedGetHeaderByNumber, - getHeader: stubbedGetHeader + getHeader: stubbedGetHeader, })) stubbedWalletsServiceConstructor.mockImplementation(() => ({ get: stubbedGetWallet, - isHardware: () => false + isHardware: () => false, })) //@ts-ignore stubbedWalletsServiceConstructor.getInstance = () => ({ get: stubbedGetWallet, - getCurrent: stubbedGetCurrentWallet + getCurrent: stubbedGetCurrentWallet, }) jest.doMock('services/rpc-service', () => { @@ -75,21 +75,21 @@ jest.doMock('services/tx/transaction-generator', () => { generateSendingAllTx: stubbedGenerateSendingAllTx, generateTx: stubbedGenerateTx, generateDepositAllTx: stubbedGenerateDepositAllTx, - generateWithdrawMultiSignTx: stubbedGenerateWithdrawMultiSignTx - } + generateWithdrawMultiSignTx: stubbedGenerateWithdrawMultiSignTx, + }, } }) jest.doMock('services/tx/transaction-persistor', () => { return { TransactionPersistor: { - saveSentTx: stubbedSaveWithSentTx - } + saveSentTx: stubbedSaveWithSentTx, + }, } }) jest.doMock('services/multisig', () => { return { - saveSentMultisigOutput: jest.fn() + saveSentMultisigOutput: jest.fn(), } }) @@ -117,17 +117,17 @@ jest.mock('../../../src/models/system-script-info', () => { new OutPoint('0x3e6790b2f47c7de911c2def3c0a3b5bf613e457e38f185e2e566f9010e495874', '0'), DepType.DepGroup ) - ) - }) + ), + }), } }) jest.doMock('services/hardware', () => ({ getInstance: () => ({ getCurrent: stubbedHardWalletGetCurrent, initHardware: () => ({ - connect: jest.fn() - }) - }) + connect: jest.fn(), + }), + }), })) import Transaction from '../../../src/models/chain/transaction' @@ -148,7 +148,7 @@ import { CapacityNotEnoughForChange, CapacityNotEnoughForChangeByTransfer, MultisigConfigNeedError, - NoMatchAddressForSign + NoMatchAddressForSign, } from '../../../src/exceptions' import TransactionSender from '../../../src/services/transaction-sender' import MultisigConfigModel from '../../../src/models/multisig-config' @@ -171,15 +171,15 @@ const generateTxWithStatus = ( Input.fromObject({ previousOutput: new OutPoint('0x' + (parseInt(id) - 1).toString().repeat(64), '0'), since: '', - lock: fakeScript - }) + lock: fakeScript, + }), ] const outputs = [ Output.fromObject({ capacity: '1', lock, - type - }) + type, + }), ] return { @@ -190,9 +190,9 @@ const generateTxWithStatus = ( timestamp: block.timestamp.toString(), inputs, outputs, - outputsData + outputsData, }), - txStatus: TxStatus.fromSDK({ status: 'committed', blockHash: block.hash }) + txStatus: TxStatus.fromSDK({ status: 'committed', blockHash: block.hash }), } } @@ -200,7 +200,7 @@ describe('TransactionSender Test', () => { const transactionSender = new TransactionSender() const fakeBlock1 = { number: '1', hash: '0x' + '0'.repeat(64), timestamp: '1' } const fakeTx1 = generateTxWithStatus('1', fakeBlock1, undefined, SystemScriptInfo.generateDaoScript(), [ - '0x0000000000000000' + '0x0000000000000000', ]) const fakeWallet = { @@ -218,16 +218,16 @@ describe('TransactionSender Test', () => { n: 1, r: 1, p: 1, - salt: '1' + salt: '1', }, - mac: '1' + mac: '1', }, '0' ), isHardware: () => false, getNextAddress: stubbedGetNextAddress, getNextChangeAddress: stubbedGetNextChangeAddress, - checkAndGenerateAddresses: stubbedCheckAndGenerateAddresses + checkAndGenerateAddresses: stubbedCheckAndGenerateAddresses, } const fakeCellWithStatus = CellWithStatus.fromSDK({ @@ -237,20 +237,20 @@ describe('TransactionSender Test', () => { lock: { args: '0x61c928dedf2afc8cb434c1af311a29cbb16f7076', codeHash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8', - hashType: 'type' + hashType: 'type', }, type: { args: '0x', codeHash: '0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e', - hashType: 'type' - } + hashType: 'type', + }, }, data: { content: '0x6400000000000000', - hash: '0xa731cac6893c41dba273a301c57e5bd2cf88dbcf8e1ddd39961b97dd0b710822' - } + hash: '0xa731cac6893c41dba273a301c57e5bd2cf88dbcf8e1ddd39961b97dd0b710822', + }, }, - status: 'live' as CKBComponents.CellStatus + status: 'live' as CKBComponents.CellStatus, }) const fakeAddress1 = 'ckt1qyqrdsefa43s6m882pcj53m4gdnj4k440axqswmu83' @@ -263,7 +263,7 @@ describe('TransactionSender Test', () => { //@ts-ignore NodeService.getInstance().ckb.rpc = { - sendTransaction: stubbedSendTransaction + sendTransaction: stubbedSendTransaction, } NodeService.getInstance().ckb.calculateDaoMaximumWithdraw = stubbedCalculateDaoMaximumWithdraw }) @@ -271,7 +271,7 @@ describe('TransactionSender Test', () => { describe('sign', () => { const pathAndPrivateKey = { path: `m/44'/309'/0'/0/0`, - privateKey: '0xe79f3207ea4980b7fed79956d5934249ceac4751a4fae01a0f7c4a96884bc4e3' + privateKey: '0xe79f3207ea4980b7fed79956d5934249ceac4751a4fae01a0f7c4a96884bc4e3', } const mockGetPk = jest.fn() @@ -290,7 +290,7 @@ describe('TransactionSender Test', () => { pendingBalance: '0', balance: '0', blake160: '0x36c329ed630d6ce750712a477543672adab57f4c', - version: 'testnet' + version: 'testnet', } const mockGAI = jest.fn() @@ -305,25 +305,25 @@ describe('TransactionSender Test', () => { CellDep.fromObject({ outPoint: OutPoint.fromObject({ txHash: '0x0d9c4af3dd158d6359c9d25d0a600f1dd20b86072b85a095e7bc70c34509b73d', - index: '0x0' + index: '0x0', }), - depType: 'depGroup' as DepType - }) + depType: 'depGroup' as DepType, + }), ], headerDeps: [], inputs: [ Input.fromObject({ previousOutput: OutPoint.fromObject({ txHash: '0x1879851943fa686af29bed5c95acd566d0244e7b3ca89cf7c435622a5a5b4cb3', - index: '0x0' + index: '0x0', }), since: '0x0', lock: Script.fromObject({ args: '0x36c329ed630d6ce750712a477543672adab57f4c', codeHash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8', - hashType: 'type' as ScriptHashType - }) - }) + hashType: 'type' as ScriptHashType, + }), + }), ], outputs: [ Output.fromObject({ @@ -331,25 +331,25 @@ describe('TransactionSender Test', () => { lock: Script.fromObject({ codeHash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8', args: '0xe2193df51d78411601796b35b17b4f8f2cd85bd0', - hashType: 'type' as ScriptHashType + hashType: 'type' as ScriptHashType, }), - type: null + type: null, }), Output.fromObject({ capacity: '0x12319d9962f4', lock: Script.fromObject({ codeHash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8', args: '0x36c329ed630d6ce750712a477543672adab57f4c', - hashType: 'type' as ScriptHashType + hashType: 'type' as ScriptHashType, }), - type: null - }) + type: null, + }), ], outputsData: ['0x', '0x'], witnesses: [ - '0x55000000100000005500000055000000410000003965f54cc684d35d886358ad57214e5f4a5fd13ecc7aba67950495b9be7740267a1d6bb14f1c215e3bc926f9655648b75e173ce6f5fd1e60218383b45503c30301' + '0x55000000100000005500000055000000410000003965f54cc684d35d886358ad57214e5f4a5fd13ecc7aba67950495b9be7740267a1d6bb14f1c215e3bc926f9655648b75e173ce6f5fd1e60218383b45503c30301', ], - hash: '0x230ab250ee0ae681e88e462102e5c01a9994ac82bf0effbfb58d6c11a86579f1' + hash: '0x230ab250ee0ae681e88e462102e5c01a9994ac82bf0effbfb58d6c11a86579f1', }) it('success', async () => { @@ -366,26 +366,26 @@ describe('TransactionSender Test', () => { CellDep.fromObject({ outPoint: OutPoint.fromObject({ txHash: '0x0d9c4af3dd158d6359c9d25d0a600f1dd20b86072b85a095e7bc70c34509b73d', - index: '0x1' + index: '0x1', }), - depType: 'depGroup' as DepType - }) + depType: 'depGroup' as DepType, + }), ], headerDeps: [], inputs: [ Input.fromObject({ previousOutput: OutPoint.fromSDK({ txHash: '0xf1181e7d0ef95fa2e6c334f6aa647520a898d9f8259a2bb021a622434bc73a63', - index: '0x0' + index: '0x0', }), since: '0x2000f00078000002', lock: Script.fromObject({ // "args": "0x36c329ed630d6ce750712a477543672adab57f4c", args: '0x56f281b3d4bb5fc73c751714af0bf78eb8aba0d80200007800f00020', codeHash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8', - hashType: 'type' as ScriptHashType - }) - }) + hashType: 'type' as ScriptHashType, + }), + }), ], outputs: [ Output.fromObject({ @@ -393,18 +393,18 @@ describe('TransactionSender Test', () => { lock: Script.fromObject({ codeHash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8', args: '0x36c329ed630d6ce750712a477543672adab57f4c', - hashType: 'type' as ScriptHashType + hashType: 'type' as ScriptHashType, }), - type: null - }) + type: null, + }), ], outputsData: ['0x'], witnesses: [new WitnessArgs()], - hash: '0x7e69c5b95b25aa70e6e72f0e29ec7b92d6415f4bdacfb9562f9d40c3fddb8dca' + hash: '0x7e69c5b95b25aa70e6e72f0e29ec7b92d6415f4bdacfb9562f9d40c3fddb8dca', }) const expectedWitness = [ - '0x6d000000100000006d0000006d000000590000000000010136c329ed630d6ce750712a477543672adab57f4c1c12c81448189a3455996c31022b8a5407a3d54ff1710eaf4220375f906cb53423040ca9f81e56f41f2df0d6cfd124dbda30b8213a0b15173b745e20449afd5401' + '0x6d000000100000006d0000006d000000590000000000010136c329ed630d6ce750712a477543672adab57f4c1c12c81448189a3455996c31022b8a5407a3d54ff1710eaf4220375f906cb53423040ca9f81e56f41f2df0d6cfd124dbda30b8213a0b15173b745e20449afd5401', ] it('success', async () => { @@ -426,16 +426,16 @@ describe('TransactionSender Test', () => { Input.fromObject({ previousOutput: OutPoint.fromObject({ txHash: '0x1879851943fa686af29bed5c95acd566d0244e7b3ca89cf7c435622a5a5b4cb3', - index: '0x0' + index: '0x0', }), - since: '0x0' - }) + since: '0x0', + }), ], outputs: [], outputsData: [], witnesses: [ - '0x5500000010000000550000005500000041000000b6d1e054606d7229b594820357397ececac31685646d3dbf07d6afe421c96ff72d32ed139f20c7b97b47ec8361c00c1924976ed90031380c488c1bae8ce3bd9d00' - ] + '0x5500000010000000550000005500000041000000b6d1e054606d7229b594820357397ececac31685646d3dbf07d6afe421c96ff72d32ed139f20c7b97b47ec8361c00c1924976ed90031380c488c1bae8ce3bd9d00', + ], }) describe('when matched receiver lock hash', () => { beforeEach(() => { @@ -476,16 +476,16 @@ describe('TransactionSender Test', () => { Input.fromObject({ previousOutput: OutPoint.fromObject({ txHash: '0x1879851943fa686af29bed5c95acd566d0244e7b3ca89cf7c435622a5a5b4cb3', - index: '0x0' + index: '0x0', }), - since: '0x0' - }) + since: '0x0', + }), ], outputs: [], outputsData: [], witnesses: [ - '0x5500000010000000550000005500000041000000b6d1e054606d7229b594820357397ececac31685646d3dbf07d6afe421c96ff72d32ed139f20c7b97b47ec8361c00c1924976ed90031380c488c1bae8ce3bd9d00' - ] + '0x5500000010000000550000005500000041000000b6d1e054606d7229b594820357397ececac31685646d3dbf07d6afe421c96ff72d32ed139f20c7b97b47ec8361c00c1924976ed90031380c488c1bae8ce3bd9d00', + ], }) describe('when matched sender lock hash', () => { beforeEach(() => { @@ -538,12 +538,12 @@ describe('TransactionSender Test', () => { const feeRate = '10' const targetOutputs = [ { address: '1', capacity: '1' }, - { address: '1', capacity: '1' } + { address: '1', capacity: '1' }, ] beforeEach(() => { stubbedGetCurrentWallet.mockReturnValue(fakeWallet) stubbedGetNextChangeAddress.mockReturnValue({ - address: fakeAddress1 + address: fakeAddress1, }) }) describe('success', () => { @@ -555,7 +555,7 @@ describe('TransactionSender Test', () => { fakeWallet.id, [ { address: '1', capacity: '1' }, - { address: '1', capacity: '1' } + { address: '1', capacity: '1' }, ], fakeAddress1, fee, @@ -581,7 +581,7 @@ describe('TransactionSender Test', () => { beforeEach(async () => { const targetOutputs = [ { address: '1', capacity: '1' }, - { address: '1', capacity: '1' } + { address: '1', capacity: '1' }, ] await transactionSender.generateSendingAllTx(fakeWallet.id, targetOutputs, fee, feeRate) }) @@ -590,7 +590,7 @@ describe('TransactionSender Test', () => { fakeWallet.id, [ { address: '1', capacity: '1' }, - { address: '1', capacity: '1' } + { address: '1', capacity: '1' }, ], fee, feeRate @@ -602,14 +602,14 @@ describe('TransactionSender Test', () => { it('generates transaction', async () => { const targetOutputs = [ { address: '1', capacity: '1' }, - { address: '1', capacity: '1' } + { address: '1', capacity: '1' }, ] const multisigConfig = MultisigConfigModel.fromObject({ walletId: 'walletId', m: 1, n: 1, r: 1, - blake160s: ['blake160s'] + blake160s: ['blake160s'], }) await transactionSender.generateMultisigSendAllTx(targetOutputs, multisigConfig) expect(stubbedGenerateSendingAllTx).toHaveBeenCalledWith('', targetOutputs, '0', '1000', multisigConfig) @@ -623,10 +623,10 @@ describe('TransactionSender Test', () => { beforeEach(async () => { stubbedGetCurrentWallet.mockReturnValue(fakeWallet) stubbedGetNextChangeAddress.mockReturnValue({ - address: fakeAddress1 + address: fakeAddress1, }) stubbedGetNextAddress.mockReturnValue({ - address: fakeAddress2 + address: fakeAddress2, }) await transactionSender.generateDepositTx(fakeWallet.id, capacity, fee, feeRate) }) @@ -648,10 +648,10 @@ describe('TransactionSender Test', () => { beforeEach(async () => { stubbedGetWallet.mockReturnValue(fakeWallet) stubbedGetNextAddress.mockReturnValue({ - address: fakeAddress1 + address: fakeAddress1, }) stubbedGetNextChangeAddress.mockReturnValue({ - address: fakeAddress2 + address: fakeAddress2, }) await transactionSender.generateDepositAllTx(fakeWallet.id, false, fee, feeRate) }) @@ -696,7 +696,7 @@ describe('TransactionSender Test', () => { number: '100', epoch: '2199023255602', hash: '0x97b3620c97bf47b4b85f4de678165ea78768be98f080854b54a9e03b78ba21b3', - parentHash: '0x9ddda4dd7edd9e413cbd25f6258ad182ea4a0f8af6835a431e72553f28a61086' + parentHash: '0x9ddda4dd7edd9e413cbd25f6258ad182ea4a0f8af6835a431e72553f28a61086', } const fee = '1' const feeRate = '10' @@ -705,7 +705,7 @@ describe('TransactionSender Test', () => { stubbedGetTransaction.mockResolvedValue(fakeTx1) stubbedGetHeader.mockResolvedValue(fakeDepositBlockHeader) stubbedGetNextChangeAddress.mockReturnValue({ - address: fakeAddress1 + address: fakeAddress1, }) await transactionSender.startWithdrawFromDao(fakeWallet.id, fakeDepositOutPoint, '1', '10') }) @@ -731,7 +731,7 @@ describe('TransactionSender Test', () => { stubbedGetTransaction.mockResolvedValue(fakeTx1) stubbedGetBlockByNumber.mockResolvedValue({ header: { hash: '0x92b197aa1fba0f63633922c61c92375c9c074a93e85963554f5499fe1450d0e5' }, - transactions: [{ hash: '0x' + '0'.repeat(64) }, { hash: '0x' + '1'.repeat(64) }] + transactions: [{ hash: '0x' + '0'.repeat(64) }, { hash: '0x' + '1'.repeat(64) }], }) const depositBlockHeader = { version: '0', @@ -739,7 +739,7 @@ describe('TransactionSender Test', () => { number: '100', epoch: '2199023255602', hash: '0x97b3620c97bf47b4b85f4de678165ea78768be98f080854b54a9e03b78ba21b3', - parentHash: '0x9ddda4dd7edd9e413cbd25f6258ad182ea4a0f8af6835a431e72553f28a61086' + parentHash: '0x9ddda4dd7edd9e413cbd25f6258ad182ea4a0f8af6835a431e72553f28a61086', } stubbedGetHeaderByNumber.mockResolvedValue(depositBlockHeader) @@ -749,22 +749,22 @@ describe('TransactionSender Test', () => { number: '100', epoch: '2199023255602', hash: '0x97b3620c97bf47b4b85f4de678165ea78768be98f080854b54a9e03b78ba21b3', - parentHash: '0x9ddda4dd7edd9e413cbd25f6258ad182ea4a0f8af6835a431e72553f28a61086' + parentHash: '0x9ddda4dd7edd9e413cbd25f6258ad182ea4a0f8af6835a431e72553f28a61086', } stubbedGetHeader.mockResolvedValue(withdrawBlockHeader) stubbedCalculateDaoMaximumWithdraw.mockResolvedValue(10300000000) stubbedGetNextAddress.mockReturnValue({ - address: fakeAddress1 + address: fakeAddress1, }) const depositOutPoint = OutPoint.fromObject({ txHash: '0x' + '0'.repeat(64), - index: '0x0' + index: '0x0', }) const withdrawingOutPoint = OutPoint.fromObject({ txHash: '0x' + '1'.repeat(64), - index: '0x0' + index: '0x0', }) tx = await transactionSender.withdrawFromDao( fakeWallet.id, @@ -788,25 +788,25 @@ describe('TransactionSender Test', () => { CellDep.fromObject({ outPoint: OutPoint.fromObject({ txHash: '0x0d9c4af3dd158d6359c9d25d0a600f1dd20b86072b85a095e7bc70c34509b73d', - index: '0x0' + index: '0x0', }), - depType: 'depGroup' as DepType - }) + depType: 'depGroup' as DepType, + }), ], headerDeps: [], inputs: [ Input.fromObject({ previousOutput: OutPoint.fromObject({ txHash: '0x1879851943fa686af29bed5c95acd566d0244e7b3ca89cf7c435622a5a5b4cb3', - index: '0x0' + index: '0x0', }), since: '0x0', lock: Script.fromObject({ args: '', codeHash: SystemScriptInfo.MULTI_SIGN_CODE_HASH, - hashType: SystemScriptInfo.MULTI_SIGN_HASH_TYPE - }) - }) + hashType: SystemScriptInfo.MULTI_SIGN_HASH_TYPE, + }), + }), ], outputs: [ Output.fromObject({ @@ -814,23 +814,23 @@ describe('TransactionSender Test', () => { lock: Script.fromObject({ codeHash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8', args: '0xe2193df51d78411601796b35b17b4f8f2cd85bd0', - hashType: 'type' as ScriptHashType + hashType: 'type' as ScriptHashType, }), - type: null + type: null, }), Output.fromObject({ capacity: '0x12319d9962f4', lock: Script.fromObject({ codeHash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8', args: '0x36c329ed630d6ce750712a477543672adab57f4c', - hashType: 'type' as ScriptHashType + hashType: 'type' as ScriptHashType, }), - type: null - }) + type: null, + }), ], outputsData: ['0x', '0x'], witnesses: [], - hash: '0x230ab250ee0ae681e88e462102e5c01a9994ac82bf0effbfb58d6c11a86579f1' + hash: '0x230ab250ee0ae681e88e462102e5c01a9994ac82bf0effbfb58d6c11a86579f1', } const createMultisigConfig = (r: number, m: number, addresses: string[]): [string, MultisigConfigModel] => { @@ -843,22 +843,22 @@ describe('TransactionSender Test', () => { r, m, n: addresses.length, - blake160s: addresses.map(v => addressToScript(v).args) - }) + blake160s: addresses.map(v => addressToScript(v).args), + }), ] } it('m is 1', async () => { const addresses = [ 'ckt1qyq89x5ggpt0a5epm2k2gyxeffwkgfdxeg0s543mh4', - 'ckt1qyqql0vgjyxjxjxknkj6nq8jxa485xsyl66sy7c5f6' + 'ckt1qyqql0vgjyxjxjxknkj6nq8jxa485xsyl66sy7c5f6', ] const [multiArgs, multisigConfig] = createMultisigConfig(1, 1, addresses) const addr = { walletId: fakeWallet.id, path: `m/44'/309'/0'/0/0`, blake160: addressToScript(addresses[0]).args, - version: 'testnet' + version: 'testnet', } const mockGAI = jest.fn() @@ -873,13 +873,17 @@ describe('TransactionSender Test', () => { }) describe('m is 2', () => { - const addresses = ['ckt1qyq89x5ggpt0a5epm2k2gyxeffwkgfdxeg0s543mh4', 'ckt1qyqql0vgjyxjxjxknkj6nq8jxa485xsyl66sy7c5f6', 'ckt1qyqt9wqszk2lurw7h86wrt826cg8zx2f0lnq6e4vpl'] + const addresses = [ + 'ckt1qyq89x5ggpt0a5epm2k2gyxeffwkgfdxeg0s543mh4', + 'ckt1qyqql0vgjyxjxjxknkj6nq8jxa485xsyl66sy7c5f6', + 'ckt1qyqt9wqszk2lurw7h86wrt826cg8zx2f0lnq6e4vpl', + ] const [multiArgs, multisigConfig] = createMultisigConfig(1, 2, addresses) const addr = { walletId: fakeWallet.id, path: `m/44'/309'/0'/0/0`, blake160: '', - version: 'testnet' + version: 'testnet', } const mockGAI = jest.fn() @@ -893,7 +897,12 @@ describe('TransactionSender Test', () => { tx.inputs[0]!.setLock(SystemScriptInfo.generateMultiSignScript(multiArgs)) tx = await transactionSender.signMultisig(fakeWallet.id, tx, '1234', [multisigConfig]) const lock = (tx.witnesses[0] as WitnessArgs).lock! - const serializedMultiSign: string = Multisig.serialize(addresses.map(v => addressToScript(v).args), 1, 2, 3) + const serializedMultiSign: string = Multisig.serialize( + addresses.map(v => addressToScript(v).args), + 1, + 2, + 3 + ) expect(lock.startsWith(serializedMultiSign)).toBeTruthy() transactionSender.getAddressInfos = getAddressInfos }) @@ -920,7 +929,7 @@ describe('TransactionSender Test', () => { it('throw exception no matched multisig config addresses', async () => { const addresses = [ 'ckt1qyq89x5ggpt0a5epm2k2gyxeffwkgfdxeg0s543mh4', - 'ckt1qyqql0vgjyxjxjxknkj6nq8jxa485xsyl66sy7c5f6' + 'ckt1qyqql0vgjyxjxjxknkj6nq8jxa485xsyl66sy7c5f6', ] const noMatchAddress = 'ckt1qyqf5v66n4vrxu75kks2ku06g7trnkdwt52s8000ee' const [multiArgs, multisigConfig] = createMultisigConfig(1, 1, addresses) @@ -928,7 +937,7 @@ describe('TransactionSender Test', () => { walletId: fakeWallet.id, address: noMatchAddress, blake160: addressToScript(noMatchAddress).args, - version: 'testnet' + version: 'testnet', } const mockGAI = jest.fn() @@ -948,25 +957,25 @@ describe('TransactionSender Test', () => { ...fakeWallet, isHardware() { return true - } + }, }) }) it('m is 1', async () => { const witnessLock = '0'.repeat(130) stubbedHardWalletGetCurrent.mockReturnValueOnce({ - signTransaction: jest.fn().mockResolvedValueOnce(witnessLock) + signTransaction: jest.fn().mockResolvedValueOnce(witnessLock), }) const addresses = [ 'ckt1qyq89x5ggpt0a5epm2k2gyxeffwkgfdxeg0s543mh4', - 'ckt1qyqql0vgjyxjxjxknkj6nq8jxa485xsyl66sy7c5f6' + 'ckt1qyqql0vgjyxjxjxknkj6nq8jxa485xsyl66sy7c5f6', ] const [multiArgs, multisigConfig] = createMultisigConfig(1, 1, addresses) const addr = { walletId: fakeWallet.id, path: `m/44'/309'/0'/0/0`, blake160: addressToScript(addresses[0]).args, - version: 'testnet' + version: 'testnet', } const mockGAI = jest.fn() @@ -978,23 +987,29 @@ describe('TransactionSender Test', () => { const expectedValue = serializeWitnessArgs({ inputType: undefined, outputType: undefined, - lock: Multisig.serialize(addresses.map(v => addressToScript(v).args), 1, 1, 2) + witnessLock + lock: + Multisig.serialize( + addresses.map(v => addressToScript(v).args), + 1, + 1, + 2 + ) + witnessLock, }) expect(res.witnesses[0]).toBe(expectedValue) }) }) - it(`input cell's length is 2`, async() => { + it(`input cell's length is 2`, async () => { const addresses = [ 'ckt1qyq89x5ggpt0a5epm2k2gyxeffwkgfdxeg0s543mh4', - 'ckt1qyqql0vgjyxjxjxknkj6nq8jxa485xsyl66sy7c5f6' + 'ckt1qyqql0vgjyxjxjxknkj6nq8jxa485xsyl66sy7c5f6', ] const [multiArgs, multisigConfig] = createMultisigConfig(1, 1, addresses) const addr = { walletId: fakeWallet.id, path: `m/44'/309'/0'/0/0`, blake160: addressToScript(addresses[0]).args, - version: 'testnet' + version: 'testnet', } const mockGAI = jest.fn() @@ -1006,14 +1021,14 @@ describe('TransactionSender Test', () => { Input.fromObject({ previousOutput: OutPoint.fromObject({ txHash: '0x1879851943fa686af29bed5c95acd566d0244e7b3ca89cf7c435622a5a5b4cb3', - index: '0x0' + index: '0x0', }), since: '0x0', lock: Script.fromObject({ args: multiArgs, codeHash: SystemScriptInfo.MULTI_SIGN_CODE_HASH, - hashType: SystemScriptInfo.MULTI_SIGN_HASH_TYPE - }) + hashType: SystemScriptInfo.MULTI_SIGN_HASH_TYPE, + }), }) ) tx.witnesses = ['0x', '0x'] diff --git a/packages/neuron-wallet/tests/services/tx/transaction-service.test.ts b/packages/neuron-wallet/tests/services/tx/transaction-service.test.ts index 6ed5734137..47164809b5 100644 --- a/packages/neuron-wallet/tests/services/tx/transaction-service.test.ts +++ b/packages/neuron-wallet/tests/services/tx/transaction-service.test.ts @@ -12,7 +12,7 @@ import HdPublicKeyInfo from '../../../src/database/chain/entities/hd-public-key- jest.mock('../../../src/models/asset-account-info', () => { const originalModule = jest.requireActual('../../../src/models/asset-account-info').default - return function() { + return function () { return new originalModule('0x92b197aa1fba0f63633922c61c92375c9c074a93e85963554f5499fe1450d0e5') } }) @@ -36,7 +36,7 @@ describe('Test TransactionService', () => { describe('#filterSearchType(searchValue)', () => { const stubProvider = { - searchValue: '' + searchValue: '', } afterEach(() => { @@ -60,7 +60,7 @@ describe('Test TransactionService', () => { const TESTNET_ADDRESS = 'ckt1qyqv9w4p6k695wkkg54eex9d3ckv2tj3y0rs6ctv00' const fixtures = [ ['Mainnet', MAINNET_ADDRESS], - ['Testnet', TESTNET_ADDRESS] + ['Testnet', TESTNET_ADDRESS], ] test.each(fixtures)('Should return SearchType.Address When search value is a %s address', (_type, addr) => { @@ -109,7 +109,7 @@ describe('Test TransactionService', () => { describe('#blake160sOfTx(transaction)', () => { const stubProvider: { tx: Transaction | undefined } = { - tx: undefined + tx: undefined, } afterEach(() => { @@ -126,7 +126,7 @@ describe('Test TransactionService', () => { const res = TransactionService.blake160sOfTx(stubProvider.tx!) expect(res).toEqual([ '0x36c329ed630d6ce750712a477543672adab57f4c', - '0xe2193df51d78411601796b35b17b4f8f2cd85bd0' + '0xe2193df51d78411601796b35b17b4f8f2cd85bd0', ]) }) }) @@ -135,7 +135,7 @@ describe('Test TransactionService', () => { describe('#getCountByLockHashesAndStatus(lockHashList, status)', () => { const stubProvider = { lockHashList: new Set(), - status: new Set() + status: new Set(), } afterEach(() => { @@ -182,7 +182,7 @@ describe('Test TransactionService', () => { describe('#updateDescription(hash, description)', () => { const stubProvider = { hash: '', - description: '' + description: '', } afterEach(() => { @@ -224,7 +224,7 @@ describe('Test TransactionService', () => { describe('#get(hash)', () => { const stubProvider = { - hash: '' + hash: '', } afterEach(() => { @@ -259,7 +259,7 @@ describe('Test TransactionService', () => { describe('#exportTransactions({ walletID, filePath })', () => { const stubProvider = { filePath: path.resolve(os.tmpdir(), 'export-transaction.csv'), - walletID: '' + walletID: '', } afterEach(() => { @@ -276,7 +276,7 @@ describe('Test TransactionService', () => { it('Should return the total count', async () => { const actual = await TransactionService.exportTransactions({ walletID: stubProvider.walletID, - filePath: stubProvider.filePath + filePath: stubProvider.filePath, }) expect(actual).toBe(0) }) @@ -288,7 +288,7 @@ describe('Test TransactionService', () => { // TODO: validate complex sudt transaction, nervos dao transaction const ADDRESSES: string[] = [ 'ckt1qyqwyxfa75whssgkq9ukkdd30d8c7txct0gqfvmy2v', - 'ckt1qyqwyxfa75whssgkq9ukkdd30d8c7txcqqqqtrnpa5' + 'ckt1qyqwyxfa75whssgkq9ukkdd30d8c7txcqqqqtrnpa5', ] const stubProvider: { walletID: string @@ -301,7 +301,7 @@ describe('Test TransactionService', () => { pageNo: 1, pageSize: 15, addresses: ADDRESSES, - searchValue: '' + searchValue: '', } beforeEach(async () => { @@ -361,7 +361,7 @@ describe('Test TransactionService', () => { type: 'receive', status: 'success', sudtInfo: undefined, - nervosDao: false + nervosDao: false, }) ) ) diff --git a/packages/neuron-wallet/tests/services/tx/transaction.description.intg.test.ts b/packages/neuron-wallet/tests/services/tx/transaction.description.intg.test.ts index 1c735cebca..6e3e3bc849 100644 --- a/packages/neuron-wallet/tests/services/tx/transaction.description.intg.test.ts +++ b/packages/neuron-wallet/tests/services/tx/transaction.description.intg.test.ts @@ -1,13 +1,13 @@ -import initConnection from "../../../src/database/chain/ormconfig"; -import { getConnection } from "typeorm"; -import TxDescription from "../../../src/database/chain/entities/tx-description"; -import { get, set } from "../../../src/services/tx/transaction-description"; +import initConnection from '../../../src/database/chain/ormconfig' +import { getConnection } from 'typeorm' +import TxDescription from '../../../src/database/chain/entities/tx-description' +import { get, set } from '../../../src/services/tx/transaction-description' describe('transaction description service', () => { const txs = [ - {walletId: 'w1', txHash: 'hash1', description: 'desc1'}, - {walletId: 'w2', txHash: 'hash2', description: 'desc2'}, - {walletId: 'w3', txHash: 'hash3', description: 'desc3'}, + { walletId: 'w1', txHash: 'hash1', description: 'desc1' }, + { walletId: 'w2', txHash: 'hash2', description: 'desc2' }, + { walletId: 'w3', txHash: 'hash3', description: 'desc3' }, ] beforeAll(async () => { await initConnection('') @@ -29,27 +29,26 @@ describe('transaction description service', () => { }) await getConnection().manager.save(entities) - }) describe('#get', () => { let result: any describe('when matched txs', () => { beforeEach(async () => { result = await get(txs[0].walletId, txs[0].txHash) - }); + }) it('returns description', () => { expect(result).toEqual(txs[0].description) - }); - }); + }) + }) describe('when no matched txs', () => { beforeEach(async () => { result = await get(txs[0].walletId, 'hash4') - }); + }) it('return empty string', () => { expect(result).toEqual('') }) - }); - }); + }) + }) describe('#set', () => { describe('when no matched records', () => { const walletId = 'w4' @@ -57,23 +56,23 @@ describe('transaction description service', () => { const description = 'desc4' beforeEach(async () => { await set(walletId, txHash, description) - }); + }) it('saves new description', async () => { const desc = await get(walletId, txHash) expect(desc).toEqual(description) - }); - }); + }) + }) describe('when matched a tx', () => { const walletId = 'w3' const txHash = 'hash3' const description = 'desc4' beforeEach(async () => { await set(walletId, txHash, description) - }); + }) it('updates description', async () => { const desc = await get(walletId, txHash) expect(desc).toEqual(description) - }); - }); - }); -}); + }) + }) + }) +}) diff --git a/packages/neuron-wallet/tests/services/wallets.test.ts b/packages/neuron-wallet/tests/services/wallets.test.ts index 4994d4ebb1..f23029ae7e 100644 --- a/packages/neuron-wallet/tests/services/wallets.test.ts +++ b/packages/neuron-wallet/tests/services/wallets.test.ts @@ -22,7 +22,7 @@ jest.doMock('../../src/services/addresses', () => { deleteByWalletId: stubbedDeleteByWalletId, generateAndSaveForExtendedKey: stubbedGenerateAndSaveForExtendedKeyFn, generateAndSaveForPublicKeyQueue: { - asyncPush: stubbedGenerateAndSaveForPublicKeyQueueAsyncPush + asyncPush: stubbedGenerateAndSaveForPublicKeyQueueAsyncPush, }, getNextUnusedAddressByWalletId: stubbedGetNextUnusedAddressByWalletIdFn, getNextUnusedChangeAddressByWalletId: stubbedGetNextUnusedChangeAddressByWalletIdFn, @@ -30,7 +30,7 @@ jest.doMock('../../src/services/addresses', () => { getFirstAddressByWalletId: stubbedGetFirstAddressByWalletIdFn, getAddressesByWalletId: stubbedGetAddressesByWalletId, } -}); +}) import WalletService, { WalletProperties, Wallet } from '../../src/services/wallets' import { AccountExtendedPublicKey } from '../../src/models/keys/key' import HdPublicKeyInfo from '../../src/database/chain/entities/hd-public-key-info' @@ -55,7 +55,6 @@ describe('wallet service', () => { const fakePublicKey = 'keykeykeykeykeykeykeykeykeykeykeykeykeykeykeykeykeykeykeykeykeykey' const fakeChainCode = 'codecodecodecodecodecodecodecodecodecodecodecodecodecodecodecode' - beforeAll(async () => { await initConnection('') }) @@ -153,7 +152,7 @@ describe('wallet service', () => { vendorId: '10086', addressIndex: 0, addressType: AddressType.Receiving, - } + }, } }) @@ -169,7 +168,7 @@ describe('wallet service', () => { let createdWallet: Wallet beforeEach(() => { createdWallet = walletService.create(wallet1) - }); + }) it('saves name', () => { const wallet = walletService.get(createdWallet.id) expect(wallet.name).toEqual(wallet1.name) @@ -180,7 +179,7 @@ describe('wallet service', () => { const keystore = wallet.loadKeystore() expect(keystore.crypto).toEqual(wallet1.keystore!.crypto) }) - }); + }) describe('#accountExtendedPublicKey', () => { it('returns xpubkey', () => { const wallet = walletService.get(createdWallet.id) @@ -188,15 +187,13 @@ describe('wallet service', () => { expect(extendedPublicKey.publicKey).toEqual(fakePublicKey) expect(extendedPublicKey.chainCode).toEqual(fakeChainCode) }) - }); + }) describe('#getDeviceInfo', () => { it('throws error', () => { const wallet = walletService.get(createdWallet.id) - expect(() => wallet.getDeviceInfo()).toThrowError( - new WalletFunctionNotSupported(wallet.getDeviceInfo.name) - ) + expect(() => wallet.getDeviceInfo()).toThrowError(new WalletFunctionNotSupported(wallet.getDeviceInfo.name)) }) - }); + }) describe('#checkAndGenerateAddresses', () => { beforeEach(async () => { @@ -215,7 +212,7 @@ describe('wallet service', () => { 10 ) }) - }); + }) describe('#getNextAddressByWalletId', () => { beforeEach(async () => { const wallet = await WalletService.getInstance().get(createdWallet.id) @@ -224,7 +221,7 @@ describe('wallet service', () => { it('calls AddressService.getNextUnusedAddressByWalletId', () => { expect(stubbedGetNextUnusedAddressByWalletIdFn).toHaveBeenCalledWith(createdWallet.id) }) - }); + }) describe('#getNextChangeAddressByWalletId', () => { beforeEach(async () => { const wallet = await WalletService.getInstance().get(createdWallet.id) @@ -233,7 +230,7 @@ describe('wallet service', () => { it('calls AddressService.getNextUnusedChangeAddressByWalletId', () => { expect(stubbedGetNextUnusedChangeAddressByWalletIdFn).toHaveBeenCalledWith(createdWallet.id) }) - }); + }) describe('#getNextReceivingAddressesByWalletId', () => { beforeEach(async () => { const wallet = await WalletService.getInstance().get(createdWallet.id) @@ -242,13 +239,13 @@ describe('wallet service', () => { it('calls AddressService.getUnusedReceivingAddressesByWalletId', () => { expect(stubbedGetUnusedReceivingAddressesByWalletIdFn).toHaveBeenCalledWith(createdWallet.id) }) - }); - }); + }) + }) describe('with a hardware wallet', () => { let createdWallet: Wallet beforeEach(() => { createdWallet = walletService.create(wallet4) - }); + }) it('saves name', () => { const wallet = walletService.get(createdWallet.id) expect(wallet.name).toEqual(wallet4.name) @@ -259,15 +256,13 @@ describe('wallet service', () => { const device = wallet.getDeviceInfo() expect(device).toEqual(wallet4.device) }) - }); + }) describe('#loadKeystore', () => { it('throws error', () => { const wallet = walletService.get(createdWallet.id) - expect(() => wallet.loadKeystore()).toThrowError( - new WalletFunctionNotSupported(wallet.loadKeystore.name) - ) + expect(() => wallet.loadKeystore()).toThrowError(new WalletFunctionNotSupported(wallet.loadKeystore.name)) }) - }); + }) describe('#checkAndGenerateAddresses', () => { beforeEach(async () => { @@ -283,7 +278,7 @@ describe('wallet service', () => { addressIndex: 0, }) }) - }); + }) describe('#getNextAddressByWalletId', () => { beforeEach(async () => { const wallet = await WalletService.getInstance().get(createdWallet.id) @@ -292,7 +287,7 @@ describe('wallet service', () => { it('calls AddressService.getGetFirstAddressByWalletId', () => { expect(stubbedGetFirstAddressByWalletIdFn).toHaveBeenCalledWith(createdWallet.id) }) - }); + }) describe('#getNextChangeAddressByWalletId', () => { beforeEach(async () => { const wallet = await WalletService.getInstance().get(createdWallet.id) @@ -301,7 +296,7 @@ describe('wallet service', () => { it('calls AddressService.getGetFirstAddressByWalletId', () => { expect(stubbedGetFirstAddressByWalletIdFn).toHaveBeenCalledWith(createdWallet.id) }) - }); + }) describe('#getNextReceivingAddressesByWalletId', () => { beforeEach(async () => { const wallet = await WalletService.getInstance().get(createdWallet.id) @@ -310,21 +305,21 @@ describe('wallet service', () => { it('calls AddressService.getGetFirstAddressByWalletId', () => { expect(stubbedGetFirstAddressByWalletIdFn).toHaveBeenCalledWith(createdWallet.id) }) - }); - }); + }) + }) describe('#update', () => { let createdWallet: Wallet beforeEach(() => { createdWallet = walletService.create(wallet1) - }); + }) it('renames wallet', () => { wallet1.name = 'renamed' walletService.update(createdWallet.id, wallet1) const updatedWallet = walletService.get(createdWallet.id) expect(updatedWallet.name).toEqual('renamed') }) - }); + }) describe('#getCurrent', () => { let createdWallet1: Wallet @@ -332,7 +327,7 @@ describe('wallet service', () => { beforeEach(() => { createdWallet1 = walletService.create(wallet2) createdWallet2 = walletService.create(wallet3) - }); + }) it('get all wallets', () => { expect(walletService.getAll().length).toBe(2) }) @@ -353,13 +348,13 @@ describe('wallet service', () => { const activeWallet = walletService.getCurrent() expect(activeWallet && activeWallet.id).toEqual(createdWallet2.id) }) - }); + }) describe('#delete', () => { let w1: any beforeEach(() => { w1 = walletService.create(wallet1) - }); + }) it('delete wallet', async () => { walletService.create(wallet2) expect(walletService.getAll().length).toBe(2) @@ -373,28 +368,28 @@ describe('wallet service', () => { let w2: any beforeEach(() => { w2 = walletService.create(wallet2) - }); + }) describe('when deleted current wallet', () => { beforeEach(async () => { await walletService.delete(w1.id) - }); + }) it('switches active wallet', () => { const activeWallet = walletService.getCurrent() expect(activeWallet && activeWallet.id).toEqual(w2.id) expect(walletService.getAll().length).toEqual(1) }) - }); + }) describe('when deleted wallets other than current wallet', () => { beforeEach(async () => { await walletService.delete(w2.id) - }); + }) it('should not switch active wallet', () => { const activeWallet = walletService.getCurrent() expect(activeWallet && activeWallet.id).toEqual(w1.id) }) - }); - }); - }); + }) + }) + }) describe('#maintainAddressesIfNecessary', () => { let createdWallet1: any @@ -406,31 +401,34 @@ describe('wallet service', () => { createdWallet3 = walletService.create(wallet3) when(stubbedGetAddressesByWalletId) - .calledWith(createdWallet1.id).mockResolvedValue({length: 1}) - .calledWith(createdWallet2.id).mockResolvedValue({length: 0}) - .calledWith(createdWallet3.id).mockResolvedValue({length: 0}) + .calledWith(createdWallet1.id) + .mockResolvedValue({ length: 1 }) + .calledWith(createdWallet2.id) + .mockResolvedValue({ length: 0 }) + .calledWith(createdWallet3.id) + .mockResolvedValue({ length: 0 }) await walletService.maintainAddressesIfNecessary() - }); + }) it('should not generate addresses for wallets already having addresses', () => { expect(stubbedGenerateAndSaveForExtendedKeyFn).not.toHaveBeenCalledWith(createdWallet1.id) }) it('generates addresses for wallets not having addresses', () => { expect(stubbedGenerateAndSaveForExtendedKeyFn).toHaveBeenCalledWith( createdWallet2.id, - expect.objectContaining({publicKey: 'a'}), + expect.objectContaining({ publicKey: 'a' }), false, 20, - 10, + 10 ) expect(stubbedGenerateAndSaveForExtendedKeyFn).toHaveBeenCalledWith( createdWallet3.id, - expect.objectContaining({publicKey: 'a'}), + expect.objectContaining({ publicKey: 'a' }), false, 20, - 10, + 10 ) - }); + }) describe('when having invalid wallet ids in key info', () => { const deletedWalletId = 'wallet4' const generateKeyInfo = (walletId: string, pk: string) => { @@ -455,15 +453,15 @@ describe('wallet service', () => { expect(keyInfosByDeletedWallet.length).toEqual(2) await walletService.maintainAddressesIfNecessary() - }); + }) it('deletes related key infos in hd_public_key_info table', async () => { const savedKeyInfos = await getConnection().getRepository(HdPublicKeyInfo).find() expect(savedKeyInfos.length).toEqual(1) const keyInfosByDeletedWallet = savedKeyInfos.filter(key => key.walletId === deletedWalletId) expect(keyInfosByDeletedWallet.length).toEqual(0) }) - }); - }); + }) + }) describe('checkAndGenerateAddress', () => { const walletServiceMock = new WalletService() diff --git a/packages/neuron-wallet/tests/setup.ts b/packages/neuron-wallet/tests/setup.ts index c485f54988..340ae061cf 100644 --- a/packages/neuron-wallet/tests/setup.ts +++ b/packages/neuron-wallet/tests/setup.ts @@ -8,7 +8,7 @@ jest.mock('levelup', () => { return new Promise(resolve => { resolve('description') }) - } + }, }) }) @@ -81,7 +81,7 @@ jest.mock('dotenv', () => ({ process.env.SECP256K1_CODE_HASH = systemScripts.SECP256K1_BLAKE160.codeHash process.env.DAO_CODE_HASH = systemScripts.NERVOS_DAO.codeHash process.env.MULTISIG_CODE_HASH = systemScripts.SECP256K1_MULTISIG.codeHash - } + }, })) process.on('unhandledRejection', console.error) diff --git a/packages/neuron-wallet/tests/setupAndTeardown/accounts.fixture.ts b/packages/neuron-wallet/tests/setupAndTeardown/accounts.fixture.ts index fea5ad4875..21d4c06b97 100644 --- a/packages/neuron-wallet/tests/setupAndTeardown/accounts.fixture.ts +++ b/packages/neuron-wallet/tests/setupAndTeardown/accounts.fixture.ts @@ -8,7 +8,7 @@ const ASSET_ACCOUNT = { decimal: '0', balance: '0', accountName: 'SUDT Account', - blake160: DEPLOY_KEY.blake160 + blake160: DEPLOY_KEY.blake160, } const CKB_ASSET_ACCOUNT = { @@ -18,7 +18,7 @@ const CKB_ASSET_ACCOUNT = { decimal: '8', balance: '0', accountName: 'CKB Account', - blake160: DEPLOY_KEY.blake160 + blake160: DEPLOY_KEY.blake160, } export default [ASSET_ACCOUNT, CKB_ASSET_ACCOUNT].map(acc => AssetAccount.fromObject(acc)) diff --git a/packages/neuron-wallet/tests/setupAndTeardown/index.ts b/packages/neuron-wallet/tests/setupAndTeardown/index.ts index 98d640a276..d524b0d544 100644 --- a/packages/neuron-wallet/tests/setupAndTeardown/index.ts +++ b/packages/neuron-wallet/tests/setupAndTeardown/index.ts @@ -1,9 +1,9 @@ -import initDB from "../../src/database/chain/ormconfig" +import initDB from '../../src/database/chain/ormconfig' import { getConnection } from 'typeorm' import { TransactionPersistor } from '../../src/services/tx' -import AssetAccount from "../../src/models/asset-account" -import OutputEntity from "../../src/database/chain/entities/output" -import AssetAccountEntity from "../../src/database/chain/entities/asset-account" +import AssetAccount from '../../src/models/asset-account' +import OutputEntity from '../../src/database/chain/entities/output' +import AssetAccountEntity from '../../src/database/chain/entities/asset-account' export const initConnection = () => { return initDB(':memory:') diff --git a/packages/neuron-wallet/tests/setupAndTeardown/keys.ts b/packages/neuron-wallet/tests/setupAndTeardown/keys.ts index ddeaf02ffe..5c4c214c54 100644 --- a/packages/neuron-wallet/tests/setupAndTeardown/keys.ts +++ b/packages/neuron-wallet/tests/setupAndTeardown/keys.ts @@ -1,3 +1,3 @@ export const DEPLOY_KEY = { - blake160: '0xe2193df51d78411601796b35b17b4f8f2cd80000' + blake160: '0xe2193df51d78411601796b35b17b4f8f2cd80000', } diff --git a/packages/neuron-wallet/tests/setupAndTeardown/public-key-info.fixture.ts b/packages/neuron-wallet/tests/setupAndTeardown/public-key-info.fixture.ts index 36c8f60d7f..585fb8dde0 100644 --- a/packages/neuron-wallet/tests/setupAndTeardown/public-key-info.fixture.ts +++ b/packages/neuron-wallet/tests/setupAndTeardown/public-key-info.fixture.ts @@ -1,6 +1,6 @@ -import { scriptToAddress } from "@nervosnetwork/ckb-sdk-utils" -import { AddressType } from "../../src/models/keys/address" -import SystemScriptInfo from "../../src/models/system-script-info" +import { scriptToAddress } from '@nervosnetwork/ckb-sdk-utils' +import { AddressType } from '../../src/models/keys/address' +import SystemScriptInfo from '../../src/models/system-script-info' const walletId1 = 'w1' const walletId2 = 'w2' @@ -13,7 +13,7 @@ const alice = { lockHash: aliceLockScript.computeHash(), address: scriptToAddress(aliceLockScript, false), blake160: aliceLockScript.args, - walletId: walletId1 + walletId: walletId1, } const bobPublicKeyHash = '0x36c329ed630d6ce750712a477543672adab57f4c' @@ -23,7 +23,7 @@ const bob = { lockHash: bobLockScript.computeHash(), address: scriptToAddress(bobLockScript, false), blake160: bobPublicKeyHash, - walletId: walletId1 + walletId: walletId1, } const charliePublicKeyHash = '0xe2193df51d78411601796b35b17b4f8f2cd80000' @@ -33,7 +33,7 @@ const charlie = { lockHash: charlieLockScript.computeHash(), address: scriptToAddress(charlieLockScript, false), blake160: charliePublicKeyHash, - walletId: walletId2 + walletId: walletId2, } const aliceKeyInfo = { @@ -43,7 +43,7 @@ const aliceKeyInfo = { addressType: AddressType.Receiving, addressIndex: 0, publicKeyInBlake160: aliceLockScript.args, - lockScript: aliceLockScript + lockScript: aliceLockScript, } const bobKeyInfo = { walletId: walletId1, @@ -52,7 +52,7 @@ const bobKeyInfo = { addressType: AddressType.Receiving, addressIndex: 1, publicKeyInBlake160: bobLockScript.args, - lockScript: bobLockScript + lockScript: bobLockScript, } const charlieKeyInfo = { walletId: walletId2, @@ -61,7 +61,7 @@ const charlieKeyInfo = { addressType: AddressType.Receiving, addressIndex: 2, publicKeyInBlake160: charlieLockScript.args, - lockScript: charlieLockScript + lockScript: charlieLockScript, } const duplicatedAliceKeyInfo = { @@ -71,7 +71,7 @@ const duplicatedAliceKeyInfo = { addressType: AddressType.Receiving, addressIndex: 0, publicKeyInBlake160: aliceLockScript.args, - lockScript: aliceLockScript + lockScript: aliceLockScript, } const duplicatedCharlieKeyInfo = { walletId: walletId3, @@ -80,7 +80,7 @@ const duplicatedCharlieKeyInfo = { addressType: AddressType.Receiving, addressIndex: 2, publicKeyInBlake160: charlieLockScript.args, - lockScript: charlieLockScript + lockScript: charlieLockScript, } export default [aliceKeyInfo, bobKeyInfo, charlieKeyInfo] diff --git a/packages/neuron-wallet/tests/setupAndTeardown/transactions.fixture.ts b/packages/neuron-wallet/tests/setupAndTeardown/transactions.fixture.ts index 54140236a6..378fb42e48 100644 --- a/packages/neuron-wallet/tests/setupAndTeardown/transactions.fixture.ts +++ b/packages/neuron-wallet/tests/setupAndTeardown/transactions.fixture.ts @@ -30,9 +30,9 @@ const fromTxObject = (tx: any) => capacity, lock, type, - outPoint + outPoint, }) - }) + }), }) /** @@ -48,8 +48,8 @@ const basicTx0 = { cellDeps: [ { outPoint: { txHash: '0x0d9c4af3dd158d6359c9d25d0a600f1dd20b86072b85a095e7bc70c34509b73d', index: '0x0' }, - depType: 'depGroup' - } + depType: 'depGroup', + }, ], headerDeps: [], inputs: [ @@ -60,9 +60,9 @@ const basicTx0 = { lock: { args: '0x36c329ed630d6ce750712a477543672adab57f4c', codeHash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8', - hashType: 'type' - } - } + hashType: 'type', + }, + }, ], outputs: [ { @@ -71,10 +71,10 @@ const basicTx0 = { lock: { codeHash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8', args: '0xe2193df51d78411601796b35b17b4f8f2cd85bd0', - hashType: 'type' + hashType: 'type', }, type: null, - outPoint: { txHash: '0x230ab250ee0ae681e88e462102e5c01a9994ac82bf0effbfb58d6c11a86579f1', index: '0' } + outPoint: { txHash: '0x230ab250ee0ae681e88e462102e5c01a9994ac82bf0effbfb58d6c11a86579f1', index: '0' }, }, { // address: ckt1qyqrdsefa43s6m882pcj53m4gdnj4k440axqswmu83 @@ -82,17 +82,17 @@ const basicTx0 = { lock: { codeHash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8', args: '0x36c329ed630d6ce750712a477543672adab57f4c', - hashType: 'type' + hashType: 'type', }, type: null, - outPoint: { txHash: '0x230ab250ee0ae681e88e462102e5c01a9994ac82bf0effbfb58d6c11a86579f1', index: '1' } - } + outPoint: { txHash: '0x230ab250ee0ae681e88e462102e5c01a9994ac82bf0effbfb58d6c11a86579f1', index: '1' }, + }, ], outputsData: ['0x', '0x'], witnesses: [ - '0x55000000100000005500000055000000410000003965f54cc684d35d886358ad57214e5f4a5fd13ecc7aba67950495b9be7740267a1d6bb14f1c215e3bc926f9655648b75e173ce6f5fd1e60218383b45503c30301' + '0x55000000100000005500000055000000410000003965f54cc684d35d886358ad57214e5f4a5fd13ecc7aba67950495b9be7740267a1d6bb14f1c215e3bc926f9655648b75e173ce6f5fd1e60218383b45503c30301', ], - hash: '0x230ab250ee0ae681e88e462102e5c01a9994ac82bf0effbfb58d6c11a86579f1' + hash: '0x230ab250ee0ae681e88e462102e5c01a9994ac82bf0effbfb58d6c11a86579f1', } /** @@ -108,10 +108,10 @@ const basicTx1 = { { outPoint: { txHash: '0x0d9c4af3dd158d6359c9d25d0a600f1dd20b86072b85a095e7bc70c34509b73d', - index: '0x0' + index: '0x0', }, - depType: 'depGroup' - } + depType: 'depGroup', + }, ], headerDeps: [], inputs: [ @@ -119,15 +119,15 @@ const basicTx1 = { // address: ckt1qyqrdsefa43s6m882pcj53m4gdnj4k440axqswmu83 previousOutput: { txHash: '0x230ab250ee0ae681e88e462102e5c01a9994ac82bf0effbfb58d6c11a86579f1', - index: '0x1' + index: '0x1', }, since: '0x0', lock: { codeHash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8', args: '0x36c329ed630d6ce750712a477543672adab57f4c', - hashType: 'type' - } - } + hashType: 'type', + }, + }, ], outputs: [ { @@ -136,15 +136,15 @@ const basicTx1 = { lock: { codeHash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8', args: DEPLOY_KEY.blake160, - hashType: 'type' + hashType: 'type', }, type: null, - outPoint: { txHash: '0x230ab250ee0ae681e88e462102e5c01a9994ac82bf0effbfb58d6c11a8657900', index: '0' } - } + outPoint: { txHash: '0x230ab250ee0ae681e88e462102e5c01a9994ac82bf0effbfb58d6c11a8657900', index: '0' }, + }, ], outputsData: ['0x'], witnesses: [], - hash: '0x230ab250ee0ae681e88e462102e5c01a9994ac82bf0effbfb58d6c11a8657900' + hash: '0x230ab250ee0ae681e88e462102e5c01a9994ac82bf0effbfb58d6c11a8657900', } /** @@ -161,16 +161,16 @@ const ACPTx0 = { { previousOutput: { txHash: '0x230ab250ee0ae681e88e462102e5c01a9994ac82bf0effbfb58d6c11a8657900', - index: '0x1' + index: '0x1', }, since: '0x0', // address: ckt1qyqwyxfa75whssgkq9ukkdd30d8c7txcqqqqtrnpa5 lock: { codeHash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8', args: DEPLOY_KEY.blake160, - hashType: 'type' - } - } + hashType: 'type', + }, + }, ], outputs: [ { @@ -178,21 +178,21 @@ const ACPTx0 = { lock: { args: '0xe2193df51d78411601796b35b17b4f8f2cd85bd0', codeHash: systemScripts.ANYONE_CAN_PAY_MAINNET.codeHash, - hashType: systemScripts.ANYONE_CAN_PAY_MAINNET.hashType + hashType: systemScripts.ANYONE_CAN_PAY_MAINNET.hashType, }, type: { args: '0xe2193df51d78411601796b35b17b4f8f2cd85bd0', codeHash: '0x0000000000000000000000000000000000000000000000000000000000000000', - hashType: 'data' + hashType: 'data', }, capacity: '0x34e62ce00', - outPoint: { txHash: '0x230ab250ee0ae681e88e462102e5c01a9994ac82bf0effbfb58d6c11a8657900', index: '0' } - } + outPoint: { txHash: '0x230ab250ee0ae681e88e462102e5c01a9994ac82bf0effbfb58d6c11a8657900', index: '0' }, + }, ], outputsData: ['0x00000000000000000000000000000000'], headerDeps: [], hash: '0x025ef744cbc86e92c5c766233cac9a203a3c470dfa23cd5005c3a086e0b0b3f4', - witnesses: [] + witnesses: [], } /** @@ -209,15 +209,15 @@ const ACPTx1 = { { previousOutput: { txHash: '0x025ef744cbc86e92c5c766233cac9a203a3c470dfa23cd5005c3a086e0b0b3f4', - index: '0x1' + index: '0x1', }, since: '0x0', lock: { codeHash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8', args: DEPLOY_KEY.blake160, - hashType: 'type' - } - } + hashType: 'type', + }, + }, ], outputs: [ { @@ -225,16 +225,16 @@ const ACPTx1 = { lock: { args: '0xe2193df51d78411601796b35b17b4f8f2cd85bd0', codeHash: systemScripts.ANYONE_CAN_PAY_MAINNET.codeHash, - hashType: systemScripts.ANYONE_CAN_PAY_MAINNET.hashType + hashType: systemScripts.ANYONE_CAN_PAY_MAINNET.hashType, }, capacity: '0x34e62ce00', - outPoint: { txHash: '0x230ab250ee0ae681e88e462102e5c01a9994ac82bf0effbfb58d6c11a8657900', index: '0' } - } + outPoint: { txHash: '0x230ab250ee0ae681e88e462102e5c01a9994ac82bf0effbfb58d6c11a8657900', index: '0' }, + }, ], outputsData: ['0x00000000000000000000000000000000'], headerDeps: [], hash: '0x025ef744cbc86e92c5c766233cac9a203a3c470dfa23cd5005c3a086e0b0b3f3', - witnesses: [] + witnesses: [], } const basicTx2 = { @@ -243,10 +243,10 @@ const basicTx2 = { { outPoint: { txHash: '0x0d9c4af3dd158d6359c9d25d0a600f1dd20b86072b85a095e7bc70c34509b73d', - index: '0x0' + index: '0x0', }, - depType: 'depGroup' - } + depType: 'depGroup', + }, ], headerDeps: [], inputs: [ @@ -254,15 +254,15 @@ const basicTx2 = { // address: ckb1qyqt8xaupvm8837nv3gtc9x0ekkj64vud3jqfwyw5v previousOutput: { txHash: '0x230ab250ee0ae681e88e462102e5c01a9994ac82bf0effbfb58d6c11a86579f1', - index: '0x1' + index: '0x1', }, since: '0x0', lock: { codeHash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8', hashType: 'type', - args: '0xb39bbc0b3673c7d36450bc14cfcdad2d559c6c64' - } - } + args: '0xb39bbc0b3673c7d36450bc14cfcdad2d559c6c64', + }, + }, ], outputs: [ { @@ -271,15 +271,15 @@ const basicTx2 = { lock: { codeHash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8', hashType: 'type', - args: '0xb39bbc0b3673c7d36450bc14cfcdad2d559c6c64' + args: '0xb39bbc0b3673c7d36450bc14cfcdad2d559c6c64', }, type: null, - outPoint: { txHash: '0x230ab250ee0ae681e88e462102e5c01a9994ac82bf0effbfb58d6c11a8657900', index: '0' } - } + outPoint: { txHash: '0x230ab250ee0ae681e88e462102e5c01a9994ac82bf0effbfb58d6c11a8657900', index: '0' }, + }, ], outputsData: ['0x'], witnesses: [], - hash: '0x230ab250ee0ae681e88e462102e5c01a9994ac82bf0effbfb58d6c11a8657901' + hash: '0x230ab250ee0ae681e88e462102e5c01a9994ac82bf0effbfb58d6c11a8657901', } // TODO: complex sUDT transaction diff --git a/packages/neuron-wallet/tests/utils/array.test.ts b/packages/neuron-wallet/tests/utils/array.test.ts index ad43353a98..8c54d8851a 100644 --- a/packages/neuron-wallet/tests/utils/array.test.ts +++ b/packages/neuron-wallet/tests/utils/array.test.ts @@ -25,7 +25,10 @@ describe('Key tests', () => { it('eachSlice', () => { const arr: number[] = [1, 2, 3, 4, 5, 6] const result = ArrayUtils.eachSlice(arr, 4) - expect(result).toEqual([[1, 2, 3, 4], [5, 6]]) + expect(result).toEqual([ + [1, 2, 3, 4], + [5, 6], + ]) }) it('range', () => { diff --git a/packages/neuron-wallet/tests/utils/buffer.test.ts b/packages/neuron-wallet/tests/utils/buffer.test.ts index 327fdb606a..fcefe09038 100644 --- a/packages/neuron-wallet/tests/utils/buffer.test.ts +++ b/packages/neuron-wallet/tests/utils/buffer.test.ts @@ -2,7 +2,7 @@ import BufferUtils from '../../src/utils/buffer' describe('BufferUtils', () => { const num = BigInt('1208925819614629174706177') - const leHex = "0x01000000000000000000010000000000" + const leHex = '0x01000000000000000000010000000000' describe('#writeBigUInt128LE', () => { describe('when success', () => { @@ -10,7 +10,7 @@ describe('BufferUtils', () => { const result = BufferUtils.writeBigUInt128LE(num) expect(result).toEqual(leHex) }) - }); + }) describe('when fails', () => { it('throws an error if the value < 0', () => { expect(() => { @@ -23,8 +23,8 @@ describe('BufferUtils', () => { BufferUtils.writeBigUInt128LE(BigInt(2) ** BigInt(128)) }).toThrowError() }) - }); - }); + }) + }) describe('#readBigUInt128LE', () => { describe('when success', () => { @@ -32,7 +32,7 @@ describe('BufferUtils', () => { const result = BufferUtils.readBigUInt128LE(leHex) expect(result).toEqual(num) }) - }); + }) describe('when fails', () => { it('throws an error if hex string does not start with 0x', () => { const hexWithout0x = '0100000000000000000001000000000000' @@ -52,8 +52,8 @@ describe('BufferUtils', () => { BufferUtils.readBigUInt128LE(hexWithInvalidLength) }).toThrowError() }) - }); - }); + }) + }) describe('#parseAmountFromSUDTData', () => { describe('when the format of hex string aligns with the protocol', () => { @@ -66,7 +66,7 @@ describe('BufferUtils', () => { const result = BufferUtils.parseAmountFromSUDTData(overflowHex) expect(result).toEqual(num) }) - }); + }) describe('when the format of hex string does not align with the protocol', () => { it('throws an error if hex string does not start with 0x', () => { const hexWithout0x = '0100000000000000000001000000000000' @@ -83,6 +83,6 @@ describe('BufferUtils', () => { const result = BufferUtils.parseAmountFromSUDTData(shortedHex) expect(result).toEqual(BigInt(0)) }) - }); - }); + }) + }) }) diff --git a/packages/neuron-wallet/tests/utils/export-history/index.test.ts b/packages/neuron-wallet/tests/utils/export-history/index.test.ts index 2765a41b65..e6e2e2734b 100644 --- a/packages/neuron-wallet/tests/utils/export-history/index.test.ts +++ b/packages/neuron-wallet/tests/utils/export-history/index.test.ts @@ -17,7 +17,7 @@ describe('Test exporting history', () => { const stubProvider = { walletID: WALLET_ID, chainType: MAINNET_CHAIN_TYPE, - filePath: FILE_PATH + filePath: FILE_PATH, } beforeAll(async () => { diff --git a/packages/neuron-wallet/tests/utils/multisig.test.ts b/packages/neuron-wallet/tests/utils/multisig.test.ts index 0131c54ee1..a8efc90acb 100644 --- a/packages/neuron-wallet/tests/utils/multisig.test.ts +++ b/packages/neuron-wallet/tests/utils/multisig.test.ts @@ -3,11 +3,10 @@ import MultisigConfigModel from '../../src/models/multisig-config' import { SignStatus } from '../../src/models/offline-sign' describe('getMultisigStatus test', () => { - const addressesToArgs: Record = { - 'ckt1qyq89x5ggpt0a5epm2k2gyxeffwkgfdxeg0s543mh4': '0x729a884056fed321daaca410d94a5d6425a6ca1f', - 'ckt1qyqql0vgjyxjxjxknkj6nq8jxa485xsyl66sy7c5f6': '0x0fbd88910d2348d69da5a980f2376a7a1a04feb5', - 'ckt1qyqt9wqszk2lurw7h86wrt826cg8zx2f0lnq6e4vpl': '0xb2b8101595fe0ddeb9f4e1acead6107119497fe6' + ckt1qyq89x5ggpt0a5epm2k2gyxeffwkgfdxeg0s543mh4: '0x729a884056fed321daaca410d94a5d6425a6ca1f', + ckt1qyqql0vgjyxjxjxknkj6nq8jxa485xsyl66sy7c5f6: '0x0fbd88910d2348d69da5a980f2376a7a1a04feb5', + ckt1qyqt9wqszk2lurw7h86wrt826cg8zx2f0lnq6e4vpl: '0xb2b8101595fe0ddeb9f4e1acead6107119497fe6', } describe('m is 2', () => { const multisigConfig = MultisigConfigModel.fromObject({ @@ -21,19 +20,33 @@ describe('getMultisigStatus test', () => { expect(getMultisigStatus(multisigConfig, {})).toBe(SignStatus.Unsigned) }) it('PartiallySigned lose m', () => { - expect(getMultisigStatus(multisigConfig, { - '0x76079ccbdb113a1e1392cf91aa7f409e4278d87181390dc3f8dd80ad3ef6b8f7': ['ckt1qyq89x5ggpt0a5epm2k2gyxeffwkgfdxeg0s543mh4'].map(v => addressesToArgs[v]) - })).toBe(SignStatus.PartiallySigned) + expect( + getMultisigStatus(multisigConfig, { + '0x76079ccbdb113a1e1392cf91aa7f409e4278d87181390dc3f8dd80ad3ef6b8f7': [ + 'ckt1qyq89x5ggpt0a5epm2k2gyxeffwkgfdxeg0s543mh4', + ].map(v => addressesToArgs[v]), + }) + ).toBe(SignStatus.PartiallySigned) }) it('PartiallySigned lose r', () => { - expect(getMultisigStatus(multisigConfig, { - '0x76079ccbdb113a1e1392cf91aa7f409e4278d87181390dc3f8dd80ad3ef6b8f7': ['ckt1qyqql0vgjyxjxjxknkj6nq8jxa485xsyl66sy7c5f6', 'ckt1qyqt9wqszk2lurw7h86wrt826cg8zx2f0lnq6e4vpl'].map(v => addressesToArgs[v]) - })).toBe(SignStatus.PartiallySigned) + expect( + getMultisigStatus(multisigConfig, { + '0x76079ccbdb113a1e1392cf91aa7f409e4278d87181390dc3f8dd80ad3ef6b8f7': [ + 'ckt1qyqql0vgjyxjxjxknkj6nq8jxa485xsyl66sy7c5f6', + 'ckt1qyqt9wqszk2lurw7h86wrt826cg8zx2f0lnq6e4vpl', + ].map(v => addressesToArgs[v]), + }) + ).toBe(SignStatus.PartiallySigned) }) it('Signed', () => { - expect(getMultisigStatus(multisigConfig, { - '0x76079ccbdb113a1e1392cf91aa7f409e4278d87181390dc3f8dd80ad3ef6b8f7': ['ckt1qyq89x5ggpt0a5epm2k2gyxeffwkgfdxeg0s543mh4', 'ckt1qyqt9wqszk2lurw7h86wrt826cg8zx2f0lnq6e4vpl'].map(v => addressesToArgs[v]) - })).toBe(SignStatus.Signed) + expect( + getMultisigStatus(multisigConfig, { + '0x76079ccbdb113a1e1392cf91aa7f409e4278d87181390dc3f8dd80ad3ef6b8f7': [ + 'ckt1qyq89x5ggpt0a5epm2k2gyxeffwkgfdxeg0s543mh4', + 'ckt1qyqt9wqszk2lurw7h86wrt826cg8zx2f0lnq6e4vpl', + ].map(v => addressesToArgs[v]), + }) + ).toBe(SignStatus.Signed) }) }) -}) \ No newline at end of file +}) diff --git a/packages/neuron-wallet/tests/utils/parse_sudt_token_info/index.test.ts b/packages/neuron-wallet/tests/utils/parse_sudt_token_info/index.test.ts index de3ec3158e..5d7fa624d8 100644 --- a/packages/neuron-wallet/tests/utils/parse_sudt_token_info/index.test.ts +++ b/packages/neuron-wallet/tests/utils/parse_sudt_token_info/index.test.ts @@ -1,4 +1,4 @@ -import parseSUDTTokenInfo from "../../../src/utils/parse_sudt_token_info"; +import parseSUDTTokenInfo from '../../../src/utils/parse_sudt_token_info' describe('parseSUDTTokenInfo', () => { it('parse sudt token info should success', function () { @@ -7,7 +7,7 @@ describe('parseSUDTTokenInfo', () => { expect(decimal).toEqual('8') expect(name).toEqual('Eirc-2') expect(symbol).toEqual('ET2') - }); + }) it('parse sudt token info with invalid hex data', function () { const hexData = '0x080a456972632d321a455432' @@ -15,7 +15,7 @@ describe('parseSUDTTokenInfo', () => { expect(decimal).toEqual('8') expect(name).not.toEqual('Eirc-2') expect(symbol).toEqual('') - }); + }) it('parse sudt token info with field not enough', function () { const hexData = '0x080a456972632d32' @@ -23,5 +23,5 @@ describe('parseSUDTTokenInfo', () => { expect(decimal).toEqual('8') expect(name).toEqual('Eirc-2') expect(symbol).toEqual('') - }); + }) }) diff --git a/packages/neuron-wallet/tests/utils/queue.test.ts b/packages/neuron-wallet/tests/utils/queue.test.ts index 9b4bd34c05..5cef8d8148 100644 --- a/packages/neuron-wallet/tests/utils/queue.test.ts +++ b/packages/neuron-wallet/tests/utils/queue.test.ts @@ -33,7 +33,8 @@ describe('queueWrapper', () => { it('asyncPush excute by order', async () => { const q = queueWrapper(fnMock) - fnMock.mockReturnValueOnce(createPromise(400)) + fnMock + .mockReturnValueOnce(createPromise(400)) .mockReturnValueOnce(createPromise(200)) .mockReturnValueOnce(createPromise(100)) q.asyncPush(1) @@ -47,7 +48,8 @@ describe('queueWrapper', () => { it('asyncPush excute by order and ignore same item', async () => { const q = queueWrapper(fnMock, 1, true) - fnMock.mockReturnValueOnce(createPromise(400)) + fnMock + .mockReturnValueOnce(createPromise(400)) .mockReturnValueOnce(createPromise(300)) .mockReturnValueOnce(createPromise(300)) q.asyncPush(1) diff --git a/packages/neuron-wallet/tests/utils/redist-check/index.test.ts b/packages/neuron-wallet/tests/utils/redist-check/index.test.ts index 807a475831..950555c026 100644 --- a/packages/neuron-wallet/tests/utils/redist-check/index.test.ts +++ b/packages/neuron-wallet/tests/utils/redist-check/index.test.ts @@ -9,16 +9,16 @@ jest.mock('util', () => ({ .fn(() => () => Promise.resolve({ stdout: 'success' })) .mockImplementationOnce(() => () => Promise.resolve({ stdout: 'success' })) .mockImplementationOnce(() => () => Promise.resolve({ stdout: null, stderr: 'err' })) - .mockImplementationOnce(() => () => Promise.reject({ stdout: null, stderr: 'err' })) + .mockImplementationOnce(() => () => Promise.reject({ stdout: null, stderr: 'err' })), })) jest.mock('utils/logger', () => console) describe('redist check', () => { describe('win32', () => { - beforeAll(function() { + beforeAll(function () { originalPlatform = process.platform Object.defineProperty(process, 'platform', { - value: 'win32' + value: 'win32', }) }) it('true', async () => { @@ -33,26 +33,26 @@ describe('redist check', () => { const redistStatus = await redistCheck() expect(redistStatus).toBe(false) }) - afterAll(function() { + afterAll(function () { Object.defineProperty(process, 'platform', { - value: originalPlatform + value: originalPlatform, }) }) }) describe('not win32', () => { - beforeAll(function() { + beforeAll(function () { originalPlatform = process.platform Object.defineProperty(process, 'platform', { - value: 'darwin' + value: 'darwin', }) }) it('true', async () => { const redistStatus = await redistCheck() expect(redistStatus).toBe(true) }) - afterAll(function() { + afterAll(function () { Object.defineProperty(process, 'platform', { - value: originalPlatform + value: originalPlatform, }) }) }) diff --git a/packages/neuron-wallet/tests/utils/rpc-request.test.ts b/packages/neuron-wallet/tests/utils/rpc-request.test.ts index 857105b5a5..82e7745a19 100644 --- a/packages/neuron-wallet/tests/utils/rpc-request.test.ts +++ b/packages/neuron-wallet/tests/utils/rpc-request.test.ts @@ -1,25 +1,26 @@ - import { rpcBatchRequest, rpcRequest } from '../../src/utils/rpc-request' const requestMock = jest.fn() jest.mock('undici', () => ({ - request: () => requestMock() + request: () => requestMock(), })) describe('rpc-batch-request', () => { const options = [ { method: 'get_block', - params: 1 + params: 1, }, { method: 'get_block', - params: 2 - } + params: 2, + }, ] it('fetch error', async () => { requestMock.mockResolvedValueOnce({ statusCode: 500 }) - await expect(rpcBatchRequest('url', options)).rejects.toThrow(new Error(`indexer request failed with HTTP code 500`)) + await expect(rpcBatchRequest('url', options)).rejects.toThrow( + new Error(`indexer request failed with HTTP code 500`) + ) }) it('result is order by id', async () => { requestMock.mockResolvedValueOnce({ @@ -29,26 +30,26 @@ describe('rpc-batch-request', () => { return Promise.resolve([ { id: 2, - result: 2 + result: 2, }, { id: 1, - result: 1 - } + result: 1, + }, ]) - } - } + }, + }, }) const res = await rpcBatchRequest('url', options) expect(res).toEqual([ { id: 1, - result: 1 + result: 1, }, { id: 2, - result: 2 - } + result: 2, + }, ]) }) }) @@ -56,7 +57,7 @@ describe('rpc-batch-request', () => { describe('rpc-request', () => { const option = { method: 'get_block', - params: 1 + params: 1, } it('fetch error', async () => { requestMock.mockResolvedValueOnce({ statusCode: 500 }) @@ -69,15 +70,15 @@ describe('rpc-request', () => { json() { return Promise.resolve({ id: 2, - result: 2 + result: 2, }) - } - } + }, + }, }) const res = await rpcRequest('url', option) expect(res).toEqual({ id: 2, - result: 2 + result: 2, }) }) }) diff --git a/packages/neuron-wallet/tests/utils/shannonToCKB.test.ts b/packages/neuron-wallet/tests/utils/shannonToCKB.test.ts index 916695e27a..0f7eb6d8ad 100644 --- a/packages/neuron-wallet/tests/utils/shannonToCKB.test.ts +++ b/packages/neuron-wallet/tests/utils/shannonToCKB.test.ts @@ -1,17 +1,17 @@ import shannonToCKB from '../../src/utils/shannonToCKB' -const fixtures: { shannon: bigint, expected: string }[] = [ +const fixtures: { shannon: bigint; expected: string }[] = [ { shannon: BigInt(0), - expected: '+0.00000000' + expected: '+0.00000000', }, { shannon: BigInt(1234567), - expected: '+0.01234567' + expected: '+0.01234567', }, { shannon: BigInt(-1234567), - expected: '-0.01234567' + expected: '-0.01234567', }, { shannon: BigInt(12345678), @@ -31,13 +31,12 @@ const fixtures: { shannon: bigint, expected: string }[] = [ }, { shannon: BigInt(12345678900000000), - expected: '+123456789.00000000' + expected: '+123456789.00000000', }, { shannon: BigInt(-12345678900000000), - expected: '-123456789.00000000' - } - + expected: '-123456789.00000000', + }, ] describe('Test Shannon To CKB', () => { diff --git a/yarn.lock b/yarn.lock index 49f6214e05..08dc31cee6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10855,13 +10855,6 @@ eslint-plugin-jsx-a11y@6.7.1, eslint-plugin-jsx-a11y@^6.5.1: object.fromentries "^2.0.6" semver "^6.3.0" -eslint-plugin-prettier@4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz#651cbb88b1dab98bfd42f017a12fa6b2d993f94b" - integrity sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ== - dependencies: - prettier-linter-helpers "^1.0.0" - eslint-plugin-react-hooks@^4.3.0: version "4.6.0" resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3" @@ -11364,11 +11357,6 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-diff@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" - integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== - fast-glob@3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1" @@ -18553,13 +18541,6 @@ prepend-http@^2.0.0: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" integrity sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA== -prettier-linter-helpers@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" - integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== - dependencies: - fast-diff "^1.1.2" - prettier@2.8.7: version "2.8.7" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.7.tgz#bb79fc8729308549d28fe3a98fce73d2c0656450" From 6bdd7e40946baece532df7f49025f372bb27a440 Mon Sep 17 00:00:00 2001 From: WhiteMind Date: Tue, 16 May 2023 17:02:59 +0800 Subject: [PATCH 46/52] refactor: resolve some eslint warnings --- packages/neuron-ui/src/components/HardwareSign/index.tsx | 4 +--- .../src/components/VerifyHardwareAddress/index.tsx | 1 - .../src/states/stateProvider/actionCreators/sudt.ts | 9 ++++++++- .../block-sync-renderer/sync/indexer-cache-service.ts | 1 - .../src/block-sync-renderer/task-wrapper.ts | 3 +-- packages/neuron-wallet/src/types/module.d.ts | 8 ++++++++ packages/neuron-wallet/tests/setupAndTeardown/index.ts | 3 ++- 7 files changed, 20 insertions(+), 9 deletions(-) create mode 100644 packages/neuron-wallet/src/types/module.d.ts diff --git a/packages/neuron-ui/src/components/HardwareSign/index.tsx b/packages/neuron-ui/src/components/HardwareSign/index.tsx index 69a797f37d..7b53021f2d 100644 --- a/packages/neuron-ui/src/components/HardwareSign/index.tsx +++ b/packages/neuron-ui/src/components/HardwareSign/index.tsx @@ -322,8 +322,7 @@ const HardwareSign = ({ if (isSuccessResponse(res)) { history!.push(RoutePath.History) } else { - // @ts-ignore - setError(res.message.content) + setError(typeof res.message === 'string' ? res.message : res.message.content ?? 'migrate-acp error') } }) break @@ -425,7 +424,6 @@ const HardwareSign = ({ }, [offlineSignType, generatedTx, onCancel, description, experimental]) useDidMount(() => { - // @ts-ignore dialogRef.current?.showModal() ensureDeviceAvailable(deviceInfo) }) diff --git a/packages/neuron-ui/src/components/VerifyHardwareAddress/index.tsx b/packages/neuron-ui/src/components/VerifyHardwareAddress/index.tsx index b6955a052f..8937d543cb 100644 --- a/packages/neuron-ui/src/components/VerifyHardwareAddress/index.tsx +++ b/packages/neuron-ui/src/components/VerifyHardwareAddress/index.tsx @@ -172,7 +172,6 @@ const VerifyHardwareAddress = ({ address, wallet, onDismiss }: VerifyHardwareAdd }, [deviceInfo, address, userInputStatus, verifiedStatus, invalidStatus, ensureDeviceAvailable, t]) useDidMount(() => { - // @ts-ignore dialogRef.current?.showModal() ensureDeviceAvailable(deviceInfo) }) diff --git a/packages/neuron-ui/src/states/stateProvider/actionCreators/sudt.ts b/packages/neuron-ui/src/states/stateProvider/actionCreators/sudt.ts index 235b910e32..49ad1e6ffa 100644 --- a/packages/neuron-ui/src/states/stateProvider/actionCreators/sudt.ts +++ b/packages/neuron-ui/src/states/stateProvider/actionCreators/sudt.ts @@ -4,6 +4,7 @@ import { sendSUDTTransaction as sendSUDTTx, migrateAcp as migrateAcpIpc, } from 'services/remote' +import { FailureFromController } from 'services/remote/remoteApiWrapper' import { AppActions, StateDispatch } from '../reducer' import { addNotification } from './app' @@ -42,7 +43,13 @@ export const migrateAcp = (params: Controller.MigrateAcp.Params) => async (dispa return res } catch (err) { console.warn(err) - return { status: ResponseCode.FAILURE, message: err } + const res: FailureFromController = { + status: ResponseCode.FAILURE, + message: { + content: String(err), + }, + } + return res } finally { dispatch({ type: AppActions.UpdateLoadings, diff --git a/packages/neuron-wallet/src/block-sync-renderer/sync/indexer-cache-service.ts b/packages/neuron-wallet/src/block-sync-renderer/sync/indexer-cache-service.ts index 72bcf1f5e5..40aa9f77b7 100644 --- a/packages/neuron-wallet/src/block-sync-renderer/sync/indexer-cache-service.ts +++ b/packages/neuron-wallet/src/block-sync-renderer/sync/indexer-cache-service.ts @@ -104,7 +104,6 @@ export default class IndexerCacheService { ) const fetchedTxHashes = await transactionCollector.getTransactionHashes() - //@ts-ignore if (!fetchedTxHashes.length) { continue } diff --git a/packages/neuron-wallet/src/block-sync-renderer/task-wrapper.ts b/packages/neuron-wallet/src/block-sync-renderer/task-wrapper.ts index 427f9b714a..5f541defe5 100644 --- a/packages/neuron-wallet/src/block-sync-renderer/task-wrapper.ts +++ b/packages/neuron-wallet/src/block-sync-renderer/task-wrapper.ts @@ -1,9 +1,8 @@ -//@ts-nocheck import Module from 'module' const originalLoad = Module._load -Module._load = function (...args: unknown[]) { +Module._load = function (...args) { if (args[0] === 'electron') { return {} } diff --git a/packages/neuron-wallet/src/types/module.d.ts b/packages/neuron-wallet/src/types/module.d.ts new file mode 100644 index 0000000000..ff5b10ce32 --- /dev/null +++ b/packages/neuron-wallet/src/types/module.d.ts @@ -0,0 +1,8 @@ +import 'module' + +declare module 'module' { + namespace Module { + function _load(...args: unknown[]): unknown + } + export = Module +} diff --git a/packages/neuron-wallet/tests/setupAndTeardown/index.ts b/packages/neuron-wallet/tests/setupAndTeardown/index.ts index d524b0d544..24d2cec210 100644 --- a/packages/neuron-wallet/tests/setupAndTeardown/index.ts +++ b/packages/neuron-wallet/tests/setupAndTeardown/index.ts @@ -16,6 +16,7 @@ export const closeConnection = () => { export const saveTransactions = async (txs: any) => { for (const tx of txs) { // TODO: do not use private methods + // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore: Private method await TransactionPersistor.saveWithFetch(tx) } @@ -23,7 +24,7 @@ export const saveTransactions = async (txs: any) => { export const createAccounts = async (assetAccounts: AssetAccount[], outputEntities: OutputEntity[]) => { const entities = assetAccounts.map(aa => AssetAccountEntity.fromModel(aa)) - const accountIds = [] + const accountIds: number[] = [] for (const entity of entities) { await getConnection().manager.save([entity.sudtTokenInfo]) const [assetAccount] = await getConnection().manager.save([entity]) From 0789169cc3e02ace7969698b2c1cc2bb8c01c689 Mon Sep 17 00:00:00 2001 From: WhiteMind Date: Tue, 23 May 2023 16:23:32 +0800 Subject: [PATCH 47/52] chore: upgrade typeorm to 0.2.45 (#2680) --- packages/neuron-wallet/package.json | 2 +- .../tests/controllers/sync-api.test.ts | 10 +- yarn.lock | 101 +++++++++++------- 3 files changed, 67 insertions(+), 46 deletions(-) diff --git a/packages/neuron-wallet/package.json b/packages/neuron-wallet/package.json index 015e29346b..bed50a94f3 100644 --- a/packages/neuron-wallet/package.json +++ b/packages/neuron-wallet/package.json @@ -61,7 +61,7 @@ "sha3": "2.1.4", "sqlite3": "5.1.4", "subleveldown": "4.1.4", - "typeorm": "0.2.25", + "typeorm": "0.2.45", "undici": "5.21.2", "uuid": "8.3.2" }, diff --git a/packages/neuron-wallet/tests/controllers/sync-api.test.ts b/packages/neuron-wallet/tests/controllers/sync-api.test.ts index 69ec939811..4d34ced8d9 100644 --- a/packages/neuron-wallet/tests/controllers/sync-api.test.ts +++ b/packages/neuron-wallet/tests/controllers/sync-api.test.ts @@ -1,7 +1,10 @@ import Emitter from 'events' import { flushPromises } from '../test-utils' -const stubbedEmitter = jest.fn() +const stubbedEmitter = jest.fn(() => { + const SyncAPIController = jest.requireActual('../../src/controllers/sync-api').default + return SyncAPIController.emiter +}) const stubbedSyncedBlockNumber = jest.fn() const stubbedSyncStateSubjectNext = jest.fn() const stubbedGetSyncState = jest.fn() @@ -66,9 +69,6 @@ describe('SyncApiController', () => { jest.doMock('services/indexer', () => ({ LISTEN_URI: 'stub_listen_uri' })) - jest.doMock('events', () => { - return stubbedEmitter - }) jest.doMock('models/synced-block-number', () => { return stubbedSyncedBlockNumber }) @@ -114,6 +114,8 @@ describe('SyncApiController', () => { emitter.removeAllListeners() const SyncAPIController = require('../../src/controllers/sync-api').default + // TODO: starting from jest@29.4.0 or above, you can use `jest.replaceProperty` as an alternative implementation. + Object.defineProperty(SyncAPIController, 'emiter', { get: stubbedEmitter }) controller = new SyncAPIController() controller.mount() }) diff --git a/yarn.lock b/yarn.lock index 08dc31cee6..a21335f56a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3559,6 +3559,11 @@ dependencies: "@sinonjs/commons" "^1.7.0" +"@sqltools/formatter@^1.2.2": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@sqltools/formatter/-/formatter-1.2.5.tgz#3abc203c79b8c3e90fd6c156a0c62d5403520e12" + integrity sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw== + "@storybook/addon-actions@5.3.18": version "5.3.18" resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-5.3.18.tgz#e3e3b1475cebc9bdd2d563822fba9ac662b2601a" @@ -5455,6 +5460,11 @@ dependencies: "@types/node" "*" +"@types/zen-observable@0.8.3": + version "0.8.3" + resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.3.tgz#781d360c282436494b32fe7d9f7f8e64b3118aa3" + integrity sha512-fbF6oTd4sGGy0xjHPKAt+eS2CrxJ3+6gQ3FGcBoIJR2TLAyCkCyI8JqZNy+FeON0AhVgNJoUumVoZQjBFUqHkw== + "@typescript-eslint/eslint-plugin@5.58.0": version "5.58.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.58.0.tgz#b1d4b0ad20243269d020ef9bbb036a40b0849829" @@ -8308,7 +8318,7 @@ chalk@5.2.0: resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.2.0.tgz#249623b7d66869c673699fb66d65723e54dfcfb3" integrity sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA== -chalk@^1.1.1, chalk@^1.1.3: +chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A== @@ -8525,7 +8535,7 @@ cli-cursor@^2.1.0: dependencies: restore-cursor "^2.0.0" -cli-highlight@^2.0.0: +cli-highlight@^2.1.11: version "2.1.11" resolved "https://registry.yarnpkg.com/cli-highlight/-/cli-highlight-2.1.11.tgz#49736fa452f0aaf4fae580e30acb26828d2dc1bf" integrity sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg== @@ -10172,7 +10182,7 @@ dotenv-webpack@^1.7.0: dependencies: dotenv-defaults "^1.0.2" -dotenv@8.6.0, dotenv@^8.0.0: +dotenv@8.6.0, dotenv@^8.0.0, dotenv@^8.2.0: version "8.6.0" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b" integrity sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g== @@ -11441,11 +11451,6 @@ figgy-pudding@^3.4.1, figgy-pudding@^3.5.1: resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw== -figlet@^1.1.1: - version "1.5.2" - resolved "https://registry.yarnpkg.com/figlet/-/figlet-1.5.2.tgz#dda34ff233c9a48e36fcff6741aeb5bafe49b634" - integrity sha512-WOn21V8AhyE1QqVfPIVxe3tupJacq1xGkPTB4iagT6o+P2cAgEOOwIxMftr4+ZCTI6d551ij9j61DFr0nsP2uQ== - figures@3.2.0, figures@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" @@ -14728,7 +14733,7 @@ js-xxhash@^1.0.4: resolved "https://registry.yarnpkg.com/js-xxhash/-/js-xxhash-1.0.4.tgz#ce465d8a5c038167a07aa35a855c0bd792fe8e06" integrity sha512-S/6Oo7ruxx5k8m4qlMnbpwQdJjRsvvfcIhIk1dA9c5y5GNhYHKYKu9krEK3QgBax6CxJuf4gRL2opgLkdzWIKg== -js-yaml@4.1.0, js-yaml@^4.1.0: +js-yaml@4.1.0, js-yaml@^4.0.0, js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== @@ -17552,11 +17557,6 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parent-require@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/parent-require/-/parent-require-1.0.0.tgz#746a167638083a860b0eef6732cb27ed46c32977" - integrity sha512-2MXDNZC4aXdkkap+rBBMv0lUsfJqvX5/2FiYYnfCnorZt3Pk06/IOR5KeaoghgS2w07MLWgjbsnyaq6PdHn2LQ== - parse-asn1@^5.0.0, parse-asn1@^5.1.5: version "5.1.6" resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" @@ -22184,26 +22184,28 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== -typeorm@0.2.25: - version "0.2.25" - resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.2.25.tgz#1a33513b375b78cc7740d2405202208b918d7dde" - integrity sha512-yzQ995fyDy5wolSLK9cmjUNcmQdixaeEm2TnXB5HN++uKbs9TiR6Y7eYAHpDlAE8s9J1uniDBgytecCZVFergQ== +typeorm@0.2.45: + version "0.2.45" + resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.2.45.tgz#e5bbb3af822dc4646bad96cfa48cd22fa4687cea" + integrity sha512-c0rCO8VMJ3ER7JQ73xfk0zDnVv0WDjpsP6Q1m6CVKul7DB9iVdWLRjPzc8v2eaeBuomsbZ2+gTaYr8k1gm3bYA== dependencies: + "@sqltools/formatter" "^1.2.2" app-root-path "^3.0.0" - buffer "^5.1.0" - chalk "^2.4.2" - cli-highlight "^2.0.0" - debug "^4.1.1" - dotenv "^6.2.0" - glob "^7.1.2" - js-yaml "^3.13.1" - mkdirp "^1.0.3" + buffer "^6.0.3" + chalk "^4.1.0" + cli-highlight "^2.1.11" + debug "^4.3.1" + dotenv "^8.2.0" + glob "^7.1.6" + js-yaml "^4.0.0" + mkdirp "^1.0.4" reflect-metadata "^0.1.13" sha.js "^2.4.11" - tslib "^1.9.0" - xml2js "^0.4.17" - yargonaut "^1.1.2" - yargs "^13.2.1" + tslib "^2.1.0" + uuid "^8.3.2" + xml2js "^0.4.23" + yargs "^17.0.1" + zen-observable-ts "^1.0.0" typescript@5.0.4: version "5.0.4" @@ -23462,7 +23464,7 @@ xml-name-validator@^3.0.0: resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== -xml2js@^0.4.17: +xml2js@^0.4.23: version "0.4.23" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66" integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug== @@ -23530,15 +23532,6 @@ yaml@^2.2.1: resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.2.1.tgz#3014bf0482dcd15147aa8e56109ce8632cd60ce4" integrity sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw== -yargonaut@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/yargonaut/-/yargonaut-1.1.4.tgz#c64f56432c7465271221f53f5cc517890c3d6e0c" - integrity sha512-rHgFmbgXAAzl+1nngqOcwEljqHGG9uUZoPjsdZEs1w5JW9RXYzrSvH/u70C1JE5qFi0qjsdhnUX/dJRpWqitSA== - dependencies: - chalk "^1.1.1" - figlet "^1.1.1" - parent-require "^1.0.0" - yargs-parser@20.2.4: version "20.2.4" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" @@ -23562,7 +23555,7 @@ yargs-parser@^13.1.2: camelcase "^5.0.0" decamelize "^1.2.0" -yargs@^13.2.1, yargs@^13.2.2: +yargs@^13.2.2: version "13.3.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== @@ -23591,6 +23584,19 @@ yargs@^16.0.0, yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" +yargs@^17.0.1: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + yargs@^17.5.1, yargs@^17.6.2, yargs@^17.7.1: version "17.7.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.1.tgz#34a77645201d1a8fc5213ace787c220eabbd0967" @@ -23617,6 +23623,19 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== +zen-observable-ts@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-1.1.0.tgz#2d1aa9d79b87058e9b75698b92791c1838551f83" + integrity sha512-1h4zlLSqI2cRLPJUHJFL8bCWHhkpuXkF+dbGkRaWjgDIG26DmzyshUMrdV/rL3UnR+mhaX4fRq8LPouq0MYYIA== + dependencies: + "@types/zen-observable" "0.8.3" + zen-observable "0.8.15" + +zen-observable@0.8.15: + version "0.8.15" + resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15" + integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ== + zip-stream@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-4.1.0.tgz#51dd326571544e36aa3f756430b313576dc8fc79" From 99dbd9665cc71dc0521cf564db52769f7adbbc47 Mon Sep 17 00:00:00 2001 From: WhiteMind Date: Tue, 23 May 2023 20:07:11 +0800 Subject: [PATCH 48/52] feat: improve the interaction design of the DatetimePicker component (#2674) * feat: improve the interaction design of the DatetimePicker component * fix: the Calendar component does not navigate to the correct panel when a value is provided --- .../neuron-ui/src/components/Send/index.tsx | 1 + packages/neuron-ui/src/styles/mixin.scss | 2 +- .../src/widgets/Calendar/focusControl.tsx | 5 ++++ .../neuron-ui/src/widgets/Calendar/index.tsx | 17 ++++-------- .../src/widgets/DatetimePicker/index.tsx | 26 +++++++++---------- 5 files changed, 25 insertions(+), 26 deletions(-) diff --git a/packages/neuron-ui/src/components/Send/index.tsx b/packages/neuron-ui/src/components/Send/index.tsx index 8127d2ae24..0a026f1b34 100644 --- a/packages/neuron-ui/src/components/Send/index.tsx +++ b/packages/neuron-ui/src/components/Send/index.tsx @@ -208,6 +208,7 @@ const Send = () => {
`${t('send.release-on')}${time == null ? '' : ` ${display}`}`} onConfirm={(time: number) => { updateTransactionOutput('date')(locktimeIndex)(`${time}`) setLocktimeIndex(-1) diff --git a/packages/neuron-ui/src/styles/mixin.scss b/packages/neuron-ui/src/styles/mixin.scss index b04b62dcc2..2e0454198f 100644 --- a/packages/neuron-ui/src/styles/mixin.scss +++ b/packages/neuron-ui/src/styles/mixin.scss @@ -43,7 +43,7 @@ @mixin dialog-confirm-button { border: none; - width: 5.125rem; + min-width: 5.125rem; height: 1.875rem; background-color: var(--nervos-green); color: #fff; diff --git a/packages/neuron-ui/src/widgets/Calendar/focusControl.tsx b/packages/neuron-ui/src/widgets/Calendar/focusControl.tsx index 7b2eaae4cd..043294341a 100644 --- a/packages/neuron-ui/src/widgets/Calendar/focusControl.tsx +++ b/packages/neuron-ui/src/widgets/Calendar/focusControl.tsx @@ -121,6 +121,11 @@ export const useTableFocusControl = ( moveDate(calendarYear, calendarMonth, focusDate.getDate()) }, [calendarYear, calendarMonth, minDate?.toDateString(), maxDate?.toDateString()]) + useEffect(() => { + setYear(value?.getFullYear() ?? new Date().getFullYear()) + setMonth((value?.getMonth() ?? new Date().getMonth()) + 1) + }, [value?.toDateString()]) + const onKeyDown = (e: KeyboardEvent) => { const keyEventMap = { Enter: () => onChange(focusDate), diff --git a/packages/neuron-ui/src/widgets/Calendar/index.tsx b/packages/neuron-ui/src/widgets/Calendar/index.tsx index e7c6b71b2d..73d267bf69 100644 --- a/packages/neuron-ui/src/widgets/Calendar/index.tsx +++ b/packages/neuron-ui/src/widgets/Calendar/index.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useMemo, useCallback } from 'react' +import React, { useState, useMemo, useCallback } from 'react' import { useTranslation } from 'react-i18next' import { getMonthCalendar, @@ -71,11 +71,6 @@ const Calendar: React.FC = ({ const [month, setMonth] = useState(new Date().getMonth() + 1) const [status, setStatus] = useState<'year' | 'month' | 'date'>('date') - useEffect(() => { - setYear(value?.getFullYear() ?? new Date().getFullYear()) - setMonth((value?.getMonth() ?? new Date().getMonth()) + 1) - }, [value?.toDateString()]) - const [uId] = useState(() => (+new Date()).toString(16).slice(-4)) const [t, { language }] = useTranslation() @@ -87,12 +82,10 @@ const Calendar: React.FC = ({ const monthName = monthNames[month - 1] const monthShortName = monthShortNames[month - 1] - const calendar = useMemo(() => getMonthCalendar(year, month, firstDayOfWeek, language), [ - year, - month, - firstDayOfWeek, - language, - ]) + const calendar = useMemo( + () => getMonthCalendar(year, month, firstDayOfWeek, language), + [year, month, firstDayOfWeek, language] + ) function isDisabledTime(date: Date): boolean { return !isDayInRange(date, { minDate, maxDate }) } diff --git a/packages/neuron-ui/src/widgets/DatetimePicker/index.tsx b/packages/neuron-ui/src/widgets/DatetimePicker/index.tsx index 1e0bd99252..e698282aaf 100644 --- a/packages/neuron-ui/src/widgets/DatetimePicker/index.tsx +++ b/packages/neuron-ui/src/widgets/DatetimePicker/index.tsx @@ -4,7 +4,6 @@ import Button from 'widgets/Button' import { useTranslation } from 'react-i18next' import styles from './datetimePicker.module.scss' -const SECONDS_PER_DAY = 24 * 3600 * 1000 let UTC: string | number = -new Date().getTimezoneOffset() / 60 if (UTC > 0) { UTC = `UTC+${UTC}` @@ -14,10 +13,7 @@ if (UTC > 0) { export const formatDate = (datetime: Date) => { const month = (datetime.getMonth() + 1).toString().padStart(2, '0') - const date = datetime - .getDate() - .toString() - .padStart(2, '0') + const date = datetime.getDate().toString().padStart(2, '0') const year = datetime.getFullYear() return `${month}/${date}/${year}` } @@ -28,14 +24,9 @@ export interface DatetimePickerProps { notice?: string onConfirm: (time: number) => void onCancel: (e: React.MouseEvent) => void + confirmText?: string | ((time?: number, display?: string) => string) } -const DatetimePicker = ({ - preset = new Date(Date.now() + SECONDS_PER_DAY), - onConfirm, - onCancel, - title, - notice, -}: DatetimePickerProps) => { +const DatetimePicker = ({ preset, onConfirm, onCancel, confirmText, title, notice }: DatetimePickerProps) => { const [t] = useTranslation() const [status, setStatus] = useState<'done' | 'edit'>('done') const [display, setDisplay] = useState(preset ? formatDate(new Date(+preset)) : '') @@ -138,7 +129,16 @@ const DatetimePicker = ({ ) : null}
From 600dbc54d56073e776528073f68cf2489fe99ef2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=A5=E5=9B=BD=E5=AE=87?= <841185308@qq.com> Date: Fri, 26 May 2023 22:03:46 +0800 Subject: [PATCH 49/52] fix: download x64 portable and fix running neuron locally (#2686) --- packages/neuron-wallet/src/services/ckb-runner.ts | 9 ++++++++- scripts/download-ckb.sh | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/neuron-wallet/src/services/ckb-runner.ts b/packages/neuron-wallet/src/services/ckb-runner.ts index 6bd6496a4a..f413129df3 100644 --- a/packages/neuron-wallet/src/services/ckb-runner.ts +++ b/packages/neuron-wallet/src/services/ckb-runner.ts @@ -30,7 +30,14 @@ const ckbPath = (): string => { const ckbBinary = (): string => { const binary = app.isPackaged ? path.resolve(ckbPath(), './ckb') : path.resolve(ckbPath(), `./${platform()}`, './ckb') - return platform() === 'win' ? binary + '.exe' : binary + switch (platform()) { + case 'win': + return binary + '.exe' + case 'mac': + return `${binary}-${process.arch === 'arm64' ? 'arm64' : 'x64'}` + default: + return binary + } } const initCkb = async () => { diff --git a/scripts/download-ckb.sh b/scripts/download-ckb.sh index 20474ec7c2..179c541c82 100755 --- a/scripts/download-ckb.sh +++ b/scripts/download-ckb.sh @@ -11,7 +11,7 @@ function download_macos() { function download_macos_x86_64() { # for macOS x64 - CKB_FILENAME="ckb_${CKB_VERSION}_x86_64-apple-darwin" + CKB_FILENAME="ckb_${CKB_VERSION}_x86_64-apple-darwin-portable" cd $ROOT_DIR/packages/neuron-wallet/bin/mac curl -O -L "${GITHUB_RELEASE_URL}/${CKB_VERSION}/${CKB_FILENAME}.zip" @@ -23,7 +23,7 @@ function download_macos_x86_64() { function download_macos_aarch64() { # for macOS arm64 - CKB_FILENAME="ckb_${CKB_VERSION}_aarch64-apple-darwin" + CKB_FILENAME="ckb_${CKB_VERSION}_aarch64-apple-darwin-portable" cd $ROOT_DIR/packages/neuron-wallet/bin/mac curl -O -L "${GITHUB_RELEASE_URL}/${CKB_VERSION}/${CKB_FILENAME}.zip" From 6ee3e00f4307a867c5c545b21216c0c6c6b3cf13 Mon Sep 17 00:00:00 2001 From: Chen Yu Date: Mon, 29 May 2023 10:24:56 +0800 Subject: [PATCH 50/52] feat: update ckb node version and assume valid target (#2689) --- .ckb-version | 2 +- packages/neuron-wallet/.env | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.ckb-version b/.ckb-version index 78519a718c..135af485bb 100644 --- a/.ckb-version +++ b/.ckb-version @@ -1 +1 @@ -v0.108.1 +v0.110.0 diff --git a/packages/neuron-wallet/.env b/packages/neuron-wallet/.env index 2c07257b9e..add16f6a2d 100644 --- a/packages/neuron-wallet/.env +++ b/packages/neuron-wallet/.env @@ -117,4 +117,4 @@ DAO_CODE_HASH=0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e MULTISIG_CODE_HASH=0x5c5069eb0857efc65e1bca0c07df34c31663b3622fd3876c876320fc9634e2a8 # CKB NODE OPTIONS -CKB_NODE_ASSUME_VALID_TARGET='0x076ffa81f8c6f2e1f22a778a1aa5d48531cc33bfd9b302e0d73fb2ce6fa4de3b' +CKB_NODE_ASSUME_VALID_TARGET='0xc0c532e10c708852d9586be46a5ed8317b2aa0835c721aa691abffb9bf4a26cd' From 1dfd25543ec381a0831d297039f84a56dc22ebc5 Mon Sep 17 00:00:00 2001 From: Chen Yu Date: Mon, 29 May 2023 15:06:37 +0800 Subject: [PATCH 51/52] feat: Adapt ckb light node (#2590) (#2615) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 严国宇 <841185308@qq.com> --- .ckb-light-version | 1 + .gitignore | 1 + .../src/components/ClearCache/index.tsx | 10 +- .../src/components/DataSetting/index.tsx | 17 +- .../src/components/MultisigAddress/hooks.ts | 41 +- .../src/components/MultisigAddress/index.tsx | 19 +- .../multisigAddress.module.scss | 4 + .../src/components/NervosDAO/hooks.ts | 90 ++-- .../src/components/NervosDAO/index.tsx | 21 +- .../src/components/NervosDAORecord/hooks.ts | 12 +- .../src/components/NervosDAORecord/index.tsx | 4 +- .../src/components/NetworkSetting/index.tsx | 12 +- .../src/components/NetworkStatus/index.tsx | 2 +- .../NetworkStatus/networkStatus.module.scss | 18 +- .../src/components/NetworkTypeLabel/index.tsx | 4 + .../SUDTMigrateToExistAccountDialog/index.tsx | 3 + .../src/components/SUDTSend/index.tsx | 17 +- .../components/SUDTSend/sUDTSend.module.scss | 14 + .../neuron-ui/src/components/Send/index.tsx | 1 + .../src/components/SendFieldset/index.tsx | 4 +- .../SendFromMultisigDialog/index.tsx | 1 + .../src/components/SpecialAssetList/index.tsx | 6 + .../src/components/WithdrawDialog/index.tsx | 34 +- .../neuron-ui/src/containers/Main/hooks.ts | 12 +- packages/neuron-ui/src/locales/en.json | 6 +- packages/neuron-ui/src/locales/zh-tw.json | 5 +- packages/neuron-ui/src/locales/zh.json | 6 +- packages/neuron-ui/src/services/chain.ts | 8 +- .../neuron-ui/src/services/remote/multisig.ts | 3 + .../src/services/remote/remoteApiWrapper.ts | 1 + packages/neuron-ui/src/states/init/app.ts | 3 - .../src/stories/NervosDAO.stories.tsx | 2 + .../src/stories/NetworkSetting.stories.tsx | 3 + .../src/stories/NetworkStatus.stories.tsx | 2 + .../src/stories/Overview.stories.tsx | 2 + .../src/stories/SendFieldset.stories.tsx | 1 + .../src/stories/WithdrawDialog.stories.tsx | 1 - packages/neuron-ui/src/styles/index.scss | 2 +- .../src/tests/is/isMainnet/fixtures.ts | 31 +- packages/neuron-ui/src/types/App/index.d.ts | 7 +- packages/neuron-ui/src/utils/const.ts | 4 + .../hooks/useGetCountDownAndFeeRateStats.ts | 50 +- .../src/widgets/InputSelect/index.tsx | 5 +- packages/neuron-wallet/electron-builder.yml | 14 +- packages/neuron-wallet/light/.gitkeep | 0 packages/neuron-wallet/package.json | 1 + .../src/block-sync-renderer/index.ts | 21 +- .../src/block-sync-renderer/sync/connector.ts | 55 +++ .../sync/indexer-connector.ts | 90 +--- .../sync/light-connector.ts | 320 ++++++++++++ .../src/block-sync-renderer/sync/queue.ts | 80 ++- .../src/block-sync-renderer/task.ts | 23 +- .../block-sync-renderer/tx-status-listener.ts | 4 +- packages/neuron-wallet/src/controllers/api.ts | 11 +- .../src/controllers/app/index.ts | 12 +- .../neuron-wallet/src/controllers/app/menu.ts | 52 +- .../src/controllers/export-debug.ts | 24 +- .../src/controllers/networks/index.ts | 2 +- .../src/controllers/offline-sign.ts | 9 +- .../neuron-wallet/src/controllers/sync-api.ts | 17 +- .../neuron-wallet/src/controllers/wallets.ts | 15 +- .../chain/entities/multisig-config.ts | 2 +- .../database/chain/entities/sync-progress.ts | 62 +++ .../neuron-wallet/src/database/chain/index.ts | 17 +- .../1676441837373-AddSyncProgress.ts | 28 ++ .../1681360188494-AddTypeSyncProgress.ts | 31 ++ .../src/database/chain/ormconfig.ts | 6 + .../src/exceptions/anyone-can-pay.ts | 6 + .../neuron-wallet/src/exceptions/index.ts | 1 + .../neuron-wallet/src/listeners/main/index.ts | 2 +- packages/neuron-wallet/src/locales/en.ts | 2 + packages/neuron-wallet/src/locales/zh-tw.ts | 2 + packages/neuron-wallet/src/locales/zh.ts | 2 + .../src/models/chain/live-cell.ts | 2 +- packages/neuron-wallet/src/models/network.ts | 2 + .../multisig-config-db-changed-subject.ts | 2 +- .../src/models/system-script-info.ts | 2 +- .../src/services/anyone-can-pay.ts | 13 +- .../neuron-wallet/src/services/ckb-runner.ts | 55 +-- .../src/services/hardware/ledger.ts | 17 +- .../neuron-wallet/src/services/indexer.ts | 13 +- .../src/services/light-runner.ts | 173 +++++++ .../src/services/live-cell-service.ts | 2 +- .../src/services/monitor/ckb-monitor.ts | 6 +- .../neuron-wallet/src/services/multisig.ts | 75 ++- .../neuron-wallet/src/services/networks.ts | 30 +- packages/neuron-wallet/src/services/node.ts | 62 +-- .../neuron-wallet/src/services/rpc-service.ts | 95 +--- .../neuron-wallet/src/services/settings.ts | 21 +- .../src/services/sync-progress.ts | 139 ++++++ .../src/services/transaction-sender.ts | 87 ++-- .../src/services/tx/transaction-generator.ts | 2 +- .../neuron-wallet/src/services/wallets.ts | 28 +- .../neuron-wallet/src/types/controller.d.ts | 2 +- packages/neuron-wallet/src/types/rpc.d.ts | 3 + packages/neuron-wallet/src/utils/ckb-rpc.ts | 334 +++++++++++++ packages/neuron-wallet/src/utils/common.ts | 6 +- packages/neuron-wallet/src/utils/const.ts | 2 + .../neuron-wallet/src/utils/rpc-request.ts | 5 +- .../indexer-connector.test.ts | 12 +- .../light-connector.test.ts | 462 ++++++++++++++++++ .../tests/block-sync-renderer/queue.test.ts | 57 ++- .../tests/controllers/export-debug.test.ts | 22 +- .../tests/controllers/multisig.test.ts | 9 + .../tests/controllers/offline-sign.test.ts | 22 +- .../tests/controllers/sync-api.test.ts | 27 +- .../tests/models/chain/live-cell.test.ts | 4 +- .../tests/services/ckb-runner.test.ts | 34 +- .../tests/services/indexer.test.ts | 49 +- .../tests/services/light-runner.test.ts | 297 +++++++++++ .../tests/services/networks.test.ts | 6 +- .../neuron-wallet/tests/services/node.test.ts | 143 +++--- .../services/tx/transaction-sender.test.ts | 36 +- .../neuron-wallet/tests/utils/ckb-rpc.test.ts | 19 + .../tests/utils/rpc-request.test.ts | 5 +- scripts/download-ckb.sh | 46 +- yarn.lock | 14 + 117 files changed, 3136 insertions(+), 707 deletions(-) create mode 100644 .ckb-light-version create mode 100644 packages/neuron-wallet/light/.gitkeep create mode 100644 packages/neuron-wallet/src/block-sync-renderer/sync/connector.ts create mode 100644 packages/neuron-wallet/src/block-sync-renderer/sync/light-connector.ts create mode 100644 packages/neuron-wallet/src/database/chain/entities/sync-progress.ts create mode 100644 packages/neuron-wallet/src/database/chain/migrations/1676441837373-AddSyncProgress.ts create mode 100644 packages/neuron-wallet/src/database/chain/migrations/1681360188494-AddTypeSyncProgress.ts create mode 100644 packages/neuron-wallet/src/services/light-runner.ts create mode 100644 packages/neuron-wallet/src/services/sync-progress.ts create mode 100644 packages/neuron-wallet/src/types/rpc.d.ts create mode 100644 packages/neuron-wallet/src/utils/ckb-rpc.ts create mode 100644 packages/neuron-wallet/tests/block-sync-renderer/light-connector.test.ts create mode 100644 packages/neuron-wallet/tests/services/light-runner.test.ts create mode 100644 packages/neuron-wallet/tests/utils/ckb-rpc.test.ts diff --git a/.ckb-light-version b/.ckb-light-version new file mode 100644 index 0000000000..f82e0685d9 --- /dev/null +++ b/.ckb-light-version @@ -0,0 +1 @@ +v0.2.4 diff --git a/.gitignore b/.gitignore index f49fd9ba91..e752ec8fce 100755 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ release /packages/neuron-wallet/bin/mac /packages/neuron-wallet/bin/linux /packages/neuron-wallet/bin/win +/packages/neuron-wallet/light # misc .DS_Store diff --git a/packages/neuron-ui/src/components/ClearCache/index.tsx b/packages/neuron-ui/src/components/ClearCache/index.tsx index e70e9b1726..e140af5948 100644 --- a/packages/neuron-ui/src/components/ClearCache/index.tsx +++ b/packages/neuron-ui/src/components/ClearCache/index.tsx @@ -18,7 +18,7 @@ const IDs = { rebuildCacheOption: 'rebuild-cache-option', } -const ClearCache = ({ dispatch }: { dispatch: StateDispatch }) => { +const ClearCache = ({ dispatch, hideRebuild }: { dispatch: StateDispatch; hideRebuild?: boolean }) => { const [t] = useTranslation() const [clearedDate, setClearedDate] = useState(cacheClearDate.load()) const [isClearing, setIsClearing] = useState(false) @@ -96,8 +96,12 @@ const ClearCache = ({ dispatch }: { dispatch: StateDispatch }) => {
- - + {hideRebuild ? null : ( + <> + + + + )}
- {isDefault ? null : ( + {network.chain === LIGHT_CLIENT_TESTNET ? null : ( + + )} + {isDefault || network.chain === LIGHT_CLIENT_TESTNET ? null : (
} {network ? ( -
+
{network.name}
diff --git a/packages/neuron-ui/src/components/NetworkStatus/networkStatus.module.scss b/packages/neuron-ui/src/components/NetworkStatus/networkStatus.module.scss index 562b4ec785..95fd700a2b 100644 --- a/packages/neuron-ui/src/components/NetworkStatus/networkStatus.module.scss +++ b/packages/neuron-ui/src/components/NetworkStatus/networkStatus.module.scss @@ -9,13 +9,17 @@ $hover-bg-color: #3cc68a4d; font-size: 0.8rem; font-weight: bold; - .name { - position: relative; - display: flex; - align-items: center; - line-height: 1em; - word-break: break-all; - margin-top: 3px; + .networkDisplay { + max-width: 100%; + + .name { + position: relative; + display: block; + line-height: 16px; + word-break: break-all; + overflow-wrap: break-word; + margin-top: 3px; + } } /* keep the tooltip popped to make it more obvious */ diff --git a/packages/neuron-ui/src/components/NetworkTypeLabel/index.tsx b/packages/neuron-ui/src/components/NetworkTypeLabel/index.tsx index e8ebf2434c..02653211b3 100644 --- a/packages/neuron-ui/src/components/NetworkTypeLabel/index.tsx +++ b/packages/neuron-ui/src/components/NetworkTypeLabel/index.tsx @@ -1,5 +1,6 @@ import React from 'react' import { useTranslation } from 'react-i18next' +import { LIGHT_CLIENT_TESTNET } from 'utils/const' const NetworkTypeLabel = ({ type }: { type: 'ckb' | 'ckb_testnet' | 'ckb_dev' | string }) => { const [t] = useTranslation() @@ -10,6 +11,9 @@ const NetworkTypeLabel = ({ type }: { type: 'ckb' | 'ckb_testnet' | 'ckb_dev' | case 'ckb_testnet': { return {t('settings.network.testnet')} } + case LIGHT_CLIENT_TESTNET: { + return {t('settings.network.lightTestnet')} + } default: { return {t('settings.network.devnet')} } diff --git a/packages/neuron-ui/src/components/SUDTMigrateToExistAccountDialog/index.tsx b/packages/neuron-ui/src/components/SUDTMigrateToExistAccountDialog/index.tsx index 06082136ca..2b27e7a47d 100644 --- a/packages/neuron-ui/src/components/SUDTMigrateToExistAccountDialog/index.tsx +++ b/packages/neuron-ui/src/components/SUDTMigrateToExistAccountDialog/index.tsx @@ -17,6 +17,7 @@ const SUDTMigrateToExistAccountDialog = ({ sUDTAccounts, isMainnet, walletID, + isLightClient, }: { cell: SpecialAssetCell closeDialog: () => void @@ -24,6 +25,7 @@ const SUDTMigrateToExistAccountDialog = ({ sUDTAccounts: State.SUDTAccount[] isMainnet: boolean walletID: string + isLightClient: boolean }) => { const [t] = useTranslation() const [address, setAddress] = useState('') @@ -92,6 +94,7 @@ const SUDTMigrateToExistAccountDialog = ({ onChange={onAddressChange} value={address} className={styles.addressInputSelect} + inputDisabeld={isLightClient} /> {addressError &&
{addressError}
}
diff --git a/packages/neuron-ui/src/components/SUDTSend/index.tsx b/packages/neuron-ui/src/components/SUDTSend/index.tsx index 34afa7c3ec..02a2b378b0 100644 --- a/packages/neuron-ui/src/components/SUDTSend/index.tsx +++ b/packages/neuron-ui/src/components/SUDTSend/index.tsx @@ -11,6 +11,7 @@ import Button from 'widgets/Button' import Spinner from 'widgets/Spinner' import { ReactComponent as TooltipIcon } from 'widgets/Icons/Tooltip.svg' import { ReactComponent as Attention } from 'widgets/Icons/Attention.svg' +import { ReactComponent as WarningAttention } from 'widgets/Icons/ExperimentalAttention.svg' import { getSUDTAccount, destoryAssetAccount } from 'services/remote' import { useState as useGlobalState, useDispatch, AppActions } from 'states' import { @@ -29,7 +30,15 @@ import { } from 'utils' import { AmountNotEnoughException, isErrorWithI18n } from 'exceptions' import { UANTokenName, UANTonkenSymbol } from 'components/UANDisplay' -import { AddressLockType, getGenerator, useAddressLockType, useOnSumbit, useOptions, useSendType } from './hooks' +import { + AddressLockType, + SendType, + getGenerator, + useAddressLockType, + useOnSumbit, + useOptions, + useSendType, +} from './hooks' import styles from './sUDTSend.module.scss' const { INIT_SEND_PRICE, DEFAULT_SUDT_FIELDS } = CONSTANTS @@ -405,6 +414,12 @@ const SUDTSend = () => {
) : null} + {(v.key === SendType.secp256Cheque && !isMainnet) ? ( +
+ + {t('messages.light-client-cheque-warning')} +
+ ) : null}
))} {!isOptionCorrect &&
{t('s-udt.send.select-option')}
} diff --git a/packages/neuron-ui/src/components/SUDTSend/sUDTSend.module.scss b/packages/neuron-ui/src/components/SUDTSend/sUDTSend.module.scss index 75db9cfa1d..4a09dd1132 100644 --- a/packages/neuron-ui/src/components/SUDTSend/sUDTSend.module.scss +++ b/packages/neuron-ui/src/components/SUDTSend/sUDTSend.module.scss @@ -178,6 +178,20 @@ } } } + + .chequeWarning { + padding: 0 8px; + margin-left: 8px; + background-color: rgb(255, 244, 206); + color: rgb(50, 49, 48); + + & > svg { + width: 14px; + height: 14px; + margin-right: 4px; + transform: translateY(20%); + } + } } .cheque { grid-area: option-0; diff --git a/packages/neuron-ui/src/components/Send/index.tsx b/packages/neuron-ui/src/components/Send/index.tsx index 0a026f1b34..fc06222a16 100644 --- a/packages/neuron-ui/src/components/Send/index.tsx +++ b/packages/neuron-ui/src/components/Send/index.tsx @@ -177,6 +177,7 @@ const Send = () => { onSendMaxClick={handleSendMaxClick} onLocktimeClick={handleLocktimeClick} isTimeLockable={!device} + isMainnet={isMainnet} /> ) }} diff --git a/packages/neuron-ui/src/components/SendFieldset/index.tsx b/packages/neuron-ui/src/components/SendFieldset/index.tsx index a7e85df255..6f937ee9af 100644 --- a/packages/neuron-ui/src/components/SendFieldset/index.tsx +++ b/packages/neuron-ui/src/components/SendFieldset/index.tsx @@ -36,6 +36,7 @@ interface SendSubformProps { onLocktimeClick?: React.EventHandler> onSendMaxClick?: React.EventHandler> onItemChange: React.EventHandler> + isMainnet: boolean } const SendFieldset = ({ @@ -54,6 +55,7 @@ const SendFieldset = ({ onSendMaxClick, onItemChange, isTimeLockable = true, + isMainnet, }: SendSubformProps) => { const [t] = useTranslation() @@ -162,7 +164,7 @@ const SendFieldset = ({ {item.date && (
- {t('send.locktime-warning')} + {t('send.locktime-warning', { extraNote: isMainnet ? null : t('messages.light-client-locktime-warning') })}
)}
diff --git a/packages/neuron-ui/src/components/SendFromMultisigDialog/index.tsx b/packages/neuron-ui/src/components/SendFromMultisigDialog/index.tsx index c682178a75..8722c071d9 100644 --- a/packages/neuron-ui/src/components/SendFromMultisigDialog/index.tsx +++ b/packages/neuron-ui/src/components/SendFromMultisigDialog/index.tsx @@ -102,6 +102,7 @@ const SendFromMultisigDialog = ({ onOutputRemove={deleteSendInfo} onItemChange={onSendInfoChange} onSendMaxClick={onSendMaxClick} + isMainnet={isMainnet} /> ))}
diff --git a/packages/neuron-ui/src/components/SpecialAssetList/index.tsx b/packages/neuron-ui/src/components/SpecialAssetList/index.tsx index 43e170ac89..0d23056d66 100644 --- a/packages/neuron-ui/src/components/SpecialAssetList/index.tsx +++ b/packages/neuron-ui/src/components/SpecialAssetList/index.tsx @@ -36,6 +36,7 @@ import { useGetAssetAccounts, } from './hooks' import styles from './specialAssetList.module.scss' +import { LIGHT_NETWORK_TYPE } from 'utils/const' const { PAGE_SIZE } = CONSTANTS @@ -113,6 +114,10 @@ const SpecialAssetList = () => { } = useGlobalState() const { suggestFeeRate } = useGetCountDownAndFeeRateStats() const isMainnet = isMainnetUtil(networks, networkID) + const isLightClient = useMemo(() => networks.find(n => n.id === networkID)?.type === LIGHT_NETWORK_TYPE, [ + networkID, + networks, + ]) const foundTokenInfo = tokenInfoList.find(token => token.tokenID === accountToClaim?.account.tokenID) const accountNames = useMemo(() => sUDTAccounts.filter(v => !!v.accountName).map(v => v.accountName!), [sUDTAccounts]) const updateAccountDialogProps: SUDTUpdateDialogProps | undefined = accountToClaim?.account @@ -384,6 +389,7 @@ const SpecialAssetList = () => { sUDTAccounts={sUDTAccounts} isMainnet={isMainnet} walletID={id} + isLightClient={isLightClient} /> )} diff --git a/packages/neuron-ui/src/components/WithdrawDialog/index.tsx b/packages/neuron-ui/src/components/WithdrawDialog/index.tsx index 9b8f180691..f887a19f54 100644 --- a/packages/neuron-ui/src/components/WithdrawDialog/index.tsx +++ b/packages/neuron-ui/src/components/WithdrawDialog/index.tsx @@ -3,8 +3,9 @@ import { useTranslation } from 'react-i18next' import Button from 'widgets/Button' import { CONSTANTS, shannonToCKBFormatter, localNumberFormatter, useCalculateEpochs, useDialog } from 'utils' -import { calculateDaoMaximumWithdraw, getHeader } from 'services/chain' +import { getTransaction, getHeader } from 'services/chain' +import { calculateMaximumWithdraw } from '@nervosnetwork/ckb-sdk-utils' import styles from './withdrawDialog.module.scss' const { WITHDRAW_EPOCHS } = CONSTANTS @@ -13,13 +14,13 @@ const WithdrawDialog = ({ onDismiss, onSubmit, record, - tipBlockHash, + tipDao, currentEpoch, }: { onDismiss: () => void onSubmit: () => void record: State.NervosDAORecord - tipBlockHash: string + tipDao?: string currentEpoch: string }) => { const [t] = useTranslation() @@ -42,24 +43,29 @@ const WithdrawDialog = ({ }, [record]) useEffect(() => { - if (!record || !tipBlockHash) { + if (!record || !tipDao) { return } - calculateDaoMaximumWithdraw( - { - txHash: record.outPoint.txHash, - index: `0x${BigInt(record.outPoint.index).toString(16)}`, - }, - tipBlockHash - ) - .then((res: string) => { - setWithdrawValue(res) + getTransaction(record.outPoint.txHash) + .then(tx => { + if (tx.txStatus.blockHash) { + getHeader(tx.txStatus.blockHash).then(header => { + setWithdrawValue( + calculateMaximumWithdraw( + tx.transaction.outputs[+record.outPoint.index], + tx.transaction.outputsData[+record.outPoint.index], + header.dao, + tipDao + ) + ) + }) + } }) .catch((err: Error) => { console.error(err) }) - }, [record, tipBlockHash]) + }, [record, tipDao]) const { currentEpochInfo, targetEpochValue } = useCalculateEpochs({ depositEpoch, currentEpoch }) diff --git a/packages/neuron-ui/src/containers/Main/hooks.ts b/packages/neuron-ui/src/containers/Main/hooks.ts index 25d96d94ee..a0714bb07f 100644 --- a/packages/neuron-ui/src/containers/Main/hooks.ts +++ b/packages/neuron-ui/src/containers/Main/hooks.ts @@ -18,7 +18,7 @@ import { SyncState as SyncStateSubject, Command as CommandSubject, } from 'services/subjects' -import { ckbCore, getBlockchainInfo, getTipHeader } from 'services/chain' +import { ckbCore, getTipHeader } from 'services/chain' import { networks as networksCache, currentNetworkID as currentNetworkIDCache } from 'services/localCache' import { WalletWizardPath } from 'components/WalletWizard' import { ErrorCode, RoutePath, getConnectionStatus } from 'utils' @@ -38,18 +38,16 @@ export const useSyncChainData = ({ chainURL, dispatch }: { chainURL: string; dis useEffect(() => { let timer: NodeJS.Timeout const syncBlockchainInfo = () => { - Promise.all([getTipHeader(), getBlockchainInfo()]) - .then(([header, chainInfo]) => { + getTipHeader() + .then(header => { if (isCurrentUrl(chainURL)) { dispatch({ type: AppActions.UpdateChainInfo, payload: { tipBlockNumber: `${BigInt(header.number)}`, - tipBlockHash: header.hash, + tipDao: header.dao, tipBlockTimestamp: +header.timestamp, - chain: chainInfo.chain, - difficulty: BigInt(chainInfo.difficulty), - epoch: chainInfo.epoch, + epoch: header.epoch, }, }) diff --git a/packages/neuron-ui/src/locales/en.json b/packages/neuron-ui/src/locales/en.json index 367d127345..eee3b132aa 100644 --- a/packages/neuron-ui/src/locales/en.json +++ b/packages/neuron-ui/src/locales/en.json @@ -217,7 +217,7 @@ "set-locktime": "Set Locktime", "locktime-notice-content": "According to the actual running block height, there may be some time variances in locktime.", "release-on": "Release on", - "locktime-warning": "Please ensure that receiver's wallet can support expiration unlocking. In general, exchanges do not support expiration unlocking, please use with caution!" + "locktime-warning": "Please ensure that receiver's wallet can support expiration unlocking. (Note: 1.Exchanges generally do not support expiration unlocking {{extraNote}})" }, "receive": { "title": "Receive", @@ -352,6 +352,7 @@ }, "mainnet": "Mainnet", "testnet": "Testnet", + "lightTestnet": "Light Testnet", "devnet": "Devnet" }, "locale": { @@ -510,6 +511,8 @@ "migrate-warning": "Warning: The migration process may fail for unknown reasons resulting in resynchronization, please back up manually and start the migration!", "migrate": "Migrate", "secp256k1/blake160-address-required": "Secp256k1/blake160 address is required", + "light-client-locktime-warning": "2.Light client mode doesn't support showing lock-time CKBytes.", + "light-client-cheque-warning": "Warning: Light client mode doesn't support showing Cheque assets.", "fields": { "wallet": "Wallet", "name": "Name", @@ -927,6 +930,7 @@ "type": "type", "balance": "balance", "copy-address": "Copy Address", + "sync-block": "Synced Block", "actions": { "info": "Info", "send": "Send", diff --git a/packages/neuron-ui/src/locales/zh-tw.json b/packages/neuron-ui/src/locales/zh-tw.json index 5980e80336..202dac1504 100644 --- a/packages/neuron-ui/src/locales/zh-tw.json +++ b/packages/neuron-ui/src/locales/zh-tw.json @@ -210,7 +210,7 @@ "set-locktime": "設置鎖定時間", "locktime-notice-content": "鎖定時間根據區塊鏈實際運行情況會有一定的誤差。", "release-on": "鎖定至", - "locktime-warning": "請確保對方錢包能夠支持到期解鎖功能。一般情況下,交易所不支持到期解鎖功能,請謹慎使用!" + "locktime-warning": "請確保對方錢包支持到期解鎖功能。(註:1.交易所壹般不支持到期解鎖功能 {{extraNote}})" }, "receive": { "title": "收款", @@ -503,6 +503,8 @@ "migrate-warning": "註意:遷移過程中可能由於未知原因失敗導致需要重新同步,請備份完成後開始遷移!", "migrate": "遷移", "secp256k1/blake160-address-required": "請輸入 secp256k1/blake160 地址", + "light-client-locktime-warning": "2.輕節點模式不支持展示到期解鎖的 CKBytes。", + "light-client-cheque-warning": "註意: 輕節點模式不支持展示 Cheque 資產。", "fields": { "wallet": "錢包", "name": "名稱", @@ -919,6 +921,7 @@ "type": "類型", "balance": "余额", "copy-address": "復製地址", + "sync-block": "同步高度", "actions": { "info": "詳情", "send": "轉賬", diff --git a/packages/neuron-ui/src/locales/zh.json b/packages/neuron-ui/src/locales/zh.json index 5225018c60..54c226e073 100644 --- a/packages/neuron-ui/src/locales/zh.json +++ b/packages/neuron-ui/src/locales/zh.json @@ -210,7 +210,7 @@ "set-locktime": "设置锁定时间", "locktime-notice-content": "锁定时间根据区块链实际运行情况会有一定的误差。", "release-on": "锁定至", - "locktime-warning": "请确保对方钱包能够支持到期解锁功能。一般情况下,交易所不支持到期解锁功能,请谨慎使用!" + "locktime-warning": "请确保对方钱包支持到期解锁功能。(注:1.交易所一般不支持到期解锁功能 {{extraNote}})" }, "receive": { "title": "收款", @@ -345,6 +345,7 @@ }, "mainnet": "主网", "testnet": "测试网", + "lightTestnet": "轻节点测试网", "devnet": "开发网" }, "locale": { @@ -503,6 +504,8 @@ "migrate-warning": "注意:迁移过程中可能由于未知原因失败导致需要重新同步,请备份完成后开始迁移!", "migrate": "迁移", "secp256k1/blake160-address-required": "请输入 secp256k1/blake160 地址", + "light-client-locktime-warning": "2.轻节点模式不支持展示到期解锁的 CKBytes。", + "light-client-cheque-warning": "注意: 轻节点模式不支持展示 Cheque 资产。", "fields": { "wallet": "钱包", "name": "名称", @@ -919,6 +922,7 @@ "type": "类型", "balance": "余额", "copy-address": "复制地址", + "sync-block": "同步高度", "actions": { "info": "详情", "send": "转账", diff --git a/packages/neuron-ui/src/services/chain.ts b/packages/neuron-ui/src/services/chain.ts index e83b569cbf..463b53868e 100644 --- a/packages/neuron-ui/src/services/chain.ts +++ b/packages/neuron-ui/src/services/chain.ts @@ -1,19 +1,17 @@ import CKBCore from '@nervosnetwork/ckb-sdk-core' export const ckbCore = new CKBCore('') -export const { getHeader, getBlock, getBlockchainInfo, getTipHeader, getHeaderByNumber, getFeeRateStats } = ckbCore.rpc +export const { getHeader, getBlockchainInfo, getTipHeader, getHeaderByNumber, getFeeRateStats, getTransaction } = ckbCore.rpc export const { calculateDaoMaximumWithdraw } = ckbCore export const { toUint64Le, parseEpoch } = ckbCore.utils + export default { ckbCore, - getBlock, - getBlockchainInfo, getHeader, getTipHeader, - getHeaderByNumber, - calculateDaoMaximumWithdraw, + getTransaction, toUint64Le, getFeeRateStats, } diff --git a/packages/neuron-ui/src/services/remote/multisig.ts b/packages/neuron-ui/src/services/remote/multisig.ts index 7c853a2994..4ac2b4aa2b 100644 --- a/packages/neuron-ui/src/services/remote/multisig.ts +++ b/packages/neuron-ui/src/services/remote/multisig.ts @@ -49,3 +49,6 @@ export const generateMultisigSendAllTx = remoteApi<{ multisigConfig: MultisigConfig }>('generate-multisig-send-all-tx') export const loadMultisigTxJson = remoteApi('load-multisig-tx-json') +export const getMultisigSyncProgress = remoteApi( + 'get-sync-progress-by-addresses' +) diff --git a/packages/neuron-ui/src/services/remote/remoteApiWrapper.ts b/packages/neuron-ui/src/services/remote/remoteApiWrapper.ts index 54729f60a2..3d1f28e184 100644 --- a/packages/neuron-ui/src/services/remote/remoteApiWrapper.ts +++ b/packages/neuron-ui/src/services/remote/remoteApiWrapper.ts @@ -147,6 +147,7 @@ type Action = | 'load-multisig-tx-json' | 'get-hold-sudt-cell-capacity' | 'start-migrate' + | 'get-sync-progress-by-addresses' export const remoteApi =

(action: Action) => diff --git a/packages/neuron-ui/src/states/init/app.ts b/packages/neuron-ui/src/states/init/app.ts index 35a433466a..4183fd81cd 100644 --- a/packages/neuron-ui/src/states/init/app.ts +++ b/packages/neuron-ui/src/states/init/app.ts @@ -12,10 +12,7 @@ const initNotifications: Array = [ export const appState: State.App = { tipBlockNumber: '', - tipBlockHash: '', tipBlockTimestamp: 0, - chain: '', - difficulty: BigInt(0), epoch: '', send: { txID: '', diff --git a/packages/neuron-ui/src/stories/NervosDAO.stories.tsx b/packages/neuron-ui/src/stories/NervosDAO.stories.tsx index f3b25c014b..8ab78818bc 100644 --- a/packages/neuron-ui/src/stories/NervosDAO.stories.tsx +++ b/packages/neuron-ui/src/stories/NervosDAO.stories.tsx @@ -40,6 +40,7 @@ const stateTemplate = { remote: 'http://testnet.nervos.com', chain: 'ckb_testnet', type: 1 as 0 | 1, + genesisHash: '0x10639e0895502b5688a6be8cf69460d76541bfa4821629d86d62ba0aae3f9606', }, ], }, @@ -158,6 +159,7 @@ stories.addDecorator(withKnobs).add('With knobs', () => { remote: text('Network Address', 'http://testnet.nervos.com'), chain: text('Chain', 'ckb_testnet'), type: 1 as 0 | 1, + genesisHash: '0x10639e0895502b5688a6be8cf69460d76541bfa4821629d86d62ba0aae3f9606', }, ], }, diff --git a/packages/neuron-ui/src/stories/NetworkSetting.stories.tsx b/packages/neuron-ui/src/stories/NetworkSetting.stories.tsx index 1fa4e8a932..9dcafdbf23 100644 --- a/packages/neuron-ui/src/stories/NetworkSetting.stories.tsx +++ b/packages/neuron-ui/src/stories/NetworkSetting.stories.tsx @@ -13,6 +13,7 @@ const states: { [title: string]: State.Network[] } = { remote: 'http://127.0.0.1:8114', chain: 'ckb', type: 0, + genesisHash: '0x92b197aa1fba0f63633922c61c92375c9c074a93e85963554f5499fe1450d0e5', }, { id: 'Testnet', @@ -20,6 +21,7 @@ const states: { [title: string]: State.Network[] } = { remote: 'http://127.0.0.1:8114', chain: 'ckb_testnet', type: 1, + genesisHash: '0x10639e0895502b5688a6be8cf69460d76541bfa4821629d86d62ba0aae3f9606', }, { id: 'Local', @@ -27,6 +29,7 @@ const states: { [title: string]: State.Network[] } = { remote: 'http://127.0.0.1:8114', chain: 'ckb_devnet', type: 1, + genesisHash: '0x10639e0895502b5688a6be8cf69460d76541bfa4821629d86d62ba0aae3f9606', }, ], } diff --git a/packages/neuron-ui/src/stories/NetworkStatus.stories.tsx b/packages/neuron-ui/src/stories/NetworkStatus.stories.tsx index 4f9572404e..40c32cf5bb 100644 --- a/packages/neuron-ui/src/stories/NetworkStatus.stories.tsx +++ b/packages/neuron-ui/src/stories/NetworkStatus.stories.tsx @@ -10,6 +10,7 @@ const defaultProps: Omit {}, isLookingValidTarget: false, @@ -71,6 +72,7 @@ stories.add('With knobs', () => { type: select('Type', [0, 1], 0) as any, id: text('id', 'd'), chain: select('Chain', ['ckb', 'ckb_testnet', 'ckb_dev'], 'ckb'), + genesisHash: '0x10639e0895502b5688a6be8cf69460d76541bfa4821629d86d62ba0aae3f9606', }, syncPercents: number('Sync Percents', 1), syncBlockNumbers: text('Sync Block Number', '1/100'), diff --git a/packages/neuron-ui/src/stories/Overview.stories.tsx b/packages/neuron-ui/src/stories/Overview.stories.tsx index c73c96b726..e35e89fbdd 100644 --- a/packages/neuron-ui/src/stories/Overview.stories.tsx +++ b/packages/neuron-ui/src/stories/Overview.stories.tsx @@ -41,6 +41,7 @@ const stateTemplate = { remote: 'http://testnet.nervos.com', chain: 'ckb_testnet', type: 1 as 0 | 1, + genesisHash: '0x10639e0895502b5688a6be8cf69460d76541bfa4821629d86d62ba0aae3f9606', }, ], }, @@ -116,6 +117,7 @@ stories.addDecorator(withKnobs).add('With knobs', () => { remote: text('Network Address', 'http://testnet.nervos.com'), chain: text('Chain', 'ckb_testnet'), type: 1 as 0 | 1, + genesisHash: '0x10639e0895502b5688a6be8cf69460d76541bfa4821629d86d62ba0aae3f9606', }, ], }, diff --git a/packages/neuron-ui/src/stories/SendFieldset.stories.tsx b/packages/neuron-ui/src/stories/SendFieldset.stories.tsx index 290d745393..8f19d4e767 100644 --- a/packages/neuron-ui/src/stories/SendFieldset.stories.tsx +++ b/packages/neuron-ui/src/stories/SendFieldset.stories.tsx @@ -30,6 +30,7 @@ stories.add('Common', () => { onItemChange: (e: any) => action('Item Change')(JSON.stringify(e.target.dataset), e.target.value), onScan: () => action('Scan'), onSendMaxClick: (e: any) => action('Click Send Max button')(JSON.stringify(e.target.dataset)), + isMainnet: false } return }) diff --git a/packages/neuron-ui/src/stories/WithdrawDialog.stories.tsx b/packages/neuron-ui/src/stories/WithdrawDialog.stories.tsx index c4e992bd2e..c6925ae0c6 100644 --- a/packages/neuron-ui/src/stories/WithdrawDialog.stories.tsx +++ b/packages/neuron-ui/src/stories/WithdrawDialog.stories.tsx @@ -36,7 +36,6 @@ const props = { timestamp: Date.now().toString(), depositTimestamp: Date.now().toString(), }, - tipBlockHash: '0x70abeeaa2ed08b7d7659341a122b9a2f2ede99bb6bd0df7398d7ffe488beab61', currentEpoch: '0x00000000', } diff --git a/packages/neuron-ui/src/styles/index.scss b/packages/neuron-ui/src/styles/index.scss index 8376832ef6..172c4489d3 100755 --- a/packages/neuron-ui/src/styles/index.scss +++ b/packages/neuron-ui/src/styles/index.scss @@ -39,7 +39,7 @@ body { justify-content: center; align-items: center; height: 18px; - width: 58px; + min-width: 58px; padding: 0 4px; font-size: 9px; font-weight: 600; diff --git a/packages/neuron-ui/src/tests/is/isMainnet/fixtures.ts b/packages/neuron-ui/src/tests/is/isMainnet/fixtures.ts index 9749009a15..56dc338194 100644 --- a/packages/neuron-ui/src/tests/is/isMainnet/fixtures.ts +++ b/packages/neuron-ui/src/tests/is/isMainnet/fixtures.ts @@ -16,7 +16,16 @@ const fixtures = { 'Should return false when network id cannot be found in network list': { params: { networkID: 'testnet', - networks: [{ id: 'mainnet', chain: 'ckb', type: 0 as 0 | 1, name: 'Mainnet', remote: 'http://127.0.0.1:8114' }], + networks: [ + { + id: 'mainnet', + chain: 'ckb', + type: 0 as 0 | 1, + name: 'Mainnet', + remote: 'http://127.0.0.1:8114', + genesisHash: '0x10639e0895502b5688a6be8cf69460d76541bfa4821629d86d62ba0aae3f9606', + }, + ], }, expected: false, }, @@ -24,7 +33,14 @@ const fixtures = { params: { networkID: 'testnet', networks: [ - { id: 'testnet', chain: 'ckb_testnet', type: 0 as 0 | 1, name: 'Mainnet', remote: 'http://127.0.0.1:8114' }, + { + id: 'testnet', + chain: 'ckb_testnet', + type: 0 as 0 | 1, + name: 'Mainnet', + remote: 'http://127.0.0.1:8114', + genesisHash: '0x10639e0895502b5688a6be8cf69460d76541bfa4821629d86d62ba0aae3f9606', + }, ], }, expected: false, @@ -32,7 +48,16 @@ const fixtures = { "Should return true when network id can be found in network list and it's Mainnet": { params: { networkID: 'mainnet', - networks: [{ id: 'mainnet', chain: 'ckb', type: 0 as 0 | 1, name: 'Mainnet', remote: 'http://127.0.0.1:8114' }], + networks: [ + { + id: 'mainnet', + chain: 'ckb', + type: 0 as 0 | 1, + name: 'Mainnet', + remote: 'http://127.0.0.1:8114', + genesisHash: '0x10639e0895502b5688a6be8cf69460d76541bfa4821629d86d62ba0aae3f9606', + }, + ], }, expected: true, }, diff --git a/packages/neuron-ui/src/types/App/index.d.ts b/packages/neuron-ui/src/types/App/index.d.ts index 458c724171..0b51453eef 100644 --- a/packages/neuron-ui/src/types/App/index.d.ts +++ b/packages/neuron-ui/src/types/App/index.d.ts @@ -125,10 +125,8 @@ declare namespace State { interface App { tipBlockNumber: string - tipBlockHash: string + tipDao?: string tipBlockTimestamp: number - chain: string - difficulty: bigint epoch: string send: Send passwordRequest: PasswordRequest @@ -149,7 +147,8 @@ declare namespace State { name: string remote: string chain: 'ckb' | 'ckb_testnet' | 'ckb_dev' | string - type: 0 | 1 + type: 0 | 1 | 2 + genesisHash: string } interface Network extends NetworkProperty { diff --git a/packages/neuron-ui/src/utils/const.ts b/packages/neuron-ui/src/utils/const.ts index 69d33c9b2f..1112f265f9 100644 --- a/packages/neuron-ui/src/utils/const.ts +++ b/packages/neuron-ui/src/utils/const.ts @@ -63,3 +63,7 @@ export const DEPRECATED_CODE_HASH: Record = { AcpOnLina: '0x0fb343953ee78c9986b091defb6252154e0bb51044fd2879fde5b27314506111', AcpOnAggron: '0x86a1c6987a4acbe1a887cca4c9dd2ac9fcb07405bbeda51b861b18bbf7492c4b', } + +export const LIGHT_CLIENT_TESTNET = 'light_client_testnet' +export const LIGHT_NETWORK_TYPE = 2 +export const METHOD_NOT_FOUND = -32601 diff --git a/packages/neuron-ui/src/utils/hooks/useGetCountDownAndFeeRateStats.ts b/packages/neuron-ui/src/utils/hooks/useGetCountDownAndFeeRateStats.ts index a1a97221fa..9caf6cf076 100644 --- a/packages/neuron-ui/src/utils/hooks/useGetCountDownAndFeeRateStats.ts +++ b/packages/neuron-ui/src/utils/hooks/useGetCountDownAndFeeRateStats.ts @@ -1,7 +1,6 @@ import { useState, useEffect, useCallback } from 'react' import { getFeeRateStats } from 'services/chain' -import { AppActions, StateDispatch, useDispatch } from 'states' -import { MEDIUM_FEE_RATE } from 'utils/const' +import { MEDIUM_FEE_RATE, METHOD_NOT_FOUND } from 'utils/const' type CountdownOptions = { seconds?: number @@ -15,34 +14,29 @@ const useGetCountDownAndFeeRateStats = ({ seconds = 30, interval = 1000 }: Count median?: string suggestFeeRate: number }>({ suggestFeeRate: MEDIUM_FEE_RATE }) - const dispatch = useDispatch() - const handleGetFeeRateStatis = useCallback( - (stateDispatch: StateDispatch) => { - getFeeRateStats() - .then(res => { - const { mean, median } = res ?? {} - const suggested = mean && median ? Math.max(1000, Number(mean), Number(median)) : MEDIUM_FEE_RATE + const handleGetFeeRateStatis = useCallback(() => { + getFeeRateStats() + .then(res => { + const { mean, median } = res ?? {} + const suggested = mean && median ? Math.max(1000, Number(mean), Number(median)) : MEDIUM_FEE_RATE - setFeeFatestatsData(states => ({ ...states, ...res, suggestFeeRate: suggested })) - }) - .catch((err: Error & { response?: { status: number } }) => { + setFeeFatestatsData(states => ({ ...states, ...res, suggestFeeRate: suggested })) + }) + .catch((err: Error & { response?: { status: number } }) => { + try { if (err?.response?.status === 404) { - setFeeFatestatsData(states => ({ ...states, suggestFeeRate: MEDIUM_FEE_RATE })) - } else { - stateDispatch({ - type: AppActions.AddNotification, - payload: { - type: 'alert', - timestamp: +new Date(), - content: err.message, - }, - }) + throw new Error('method not found') } - }) - }, - [getFeeRateStats, setFeeFatestatsData] - ) + const errMsg = JSON.parse(err.message) + if (errMsg?.code === METHOD_NOT_FOUND) { + throw new Error('method not found') + } + } catch (error) { + setFeeFatestatsData(states => ({ ...states, suggestFeeRate: MEDIUM_FEE_RATE })) + } + }) + }, []) useEffect(() => { const countInterval = setInterval(() => { @@ -56,9 +50,9 @@ const useGetCountDownAndFeeRateStats = ({ seconds = 30, interval = 1000 }: Count useEffect(() => { if (countDown === seconds) { - handleGetFeeRateStatis(dispatch) + handleGetFeeRateStatis() } - }, [countDown, seconds, dispatch]) + }, [countDown, seconds]) return { countDown, ...feeFatestatsData } } diff --git a/packages/neuron-ui/src/widgets/InputSelect/index.tsx b/packages/neuron-ui/src/widgets/InputSelect/index.tsx index bc7728a98e..6341b30953 100644 --- a/packages/neuron-ui/src/widgets/InputSelect/index.tsx +++ b/packages/neuron-ui/src/widgets/InputSelect/index.tsx @@ -16,6 +16,7 @@ export interface InputSelectProps { onChange?: (value: string, arg?: SelectOptions) => void value?: string placeholder?: string + inputDisabeld?: boolean } function parseValue(value: string, options: SelectOptions[]) { @@ -23,7 +24,7 @@ function parseValue(value: string, options: SelectOptions[]) { return option?.value || value } -const Select = ({ value, options, placeholder, disabled, onChange, className }: InputSelectProps) => { +const Select = ({ value, options, placeholder, disabled, onChange, className, inputDisabeld }: InputSelectProps) => { const mounted = useRef(true) const root = useRef(null) const openRef = useRef(false) @@ -121,7 +122,7 @@ const Select = ({ value, options, placeholder, disabled, onChange, className }: tabIndex={0} data-open={openRef.current} > - +

{openRef.current ? ( diff --git a/packages/neuron-wallet/electron-builder.yml b/packages/neuron-wallet/electron-builder.yml index 8125c6b0da..6cc88df861 100644 --- a/packages/neuron-wallet/electron-builder.yml +++ b/packages/neuron-wallet/electron-builder.yml @@ -13,7 +13,7 @@ afterSign: scripts/notarize.js files: - from: "../.." to: "." - filter: ["!**/*", ".ckb-version", "ormconfig.json"] + filter: ["!**/*", ".ckb-version", ".ckb-light-version", "ormconfig.json"] - package.json - dist - ".env" @@ -41,6 +41,10 @@ win: extraFiles: - from: "bin/win/ckb.exe" to: "bin/ckb.exe" + - from: "bin/win/ckb-light-client.exe" + to: "bin/ckb-light-client.exe" + - from: "light/ckb_light.toml" + to: "light/ckb_light.toml" target: - target: nsis arch: @@ -53,6 +57,10 @@ mac: extraFiles: - from: "bin/mac/ckb-${arch}" to: "bin/ckb" + - from: "bin/mac/ckb-light-client" + to: "bin/ckb-light-client" + - from: "light/ckb_light.toml" + to: "light/ckb_light.toml" hardenedRuntime: true gatekeeperAssess: false entitlements: assets/entitlements.plist @@ -71,5 +79,9 @@ linux: extraFiles: - from: "bin/linux/ckb" to: "bin/ckb" + - from: "bin/linux/ckb-light-client" + to: "bin/ckb-light-client" + - from: "light/ckb_light.toml" + to: "light/ckb_light.toml" target: - AppImage diff --git a/packages/neuron-wallet/light/.gitkeep b/packages/neuron-wallet/light/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/neuron-wallet/package.json b/packages/neuron-wallet/package.json index bed50a94f3..61f1259cf8 100644 --- a/packages/neuron-wallet/package.json +++ b/packages/neuron-wallet/package.json @@ -37,6 +37,7 @@ }, "dependencies": { "@ckb-lumos/base": "0.18.0-rc2", + "@ckb-lumos/codec": "0.19.0", "@ckb-lumos/rpc": "0.18.0-rc2", "@iarna/toml": "2.2.5", "@ledgerhq/hw-transport-node-hid": "6.27.13", diff --git a/packages/neuron-wallet/src/block-sync-renderer/index.ts b/packages/neuron-wallet/src/block-sync-renderer/index.ts index 3edddca360..6c8b3cb7cc 100644 --- a/packages/neuron-wallet/src/block-sync-renderer/index.ts +++ b/packages/neuron-wallet/src/block-sync-renderer/index.ts @@ -9,12 +9,16 @@ import DataUpdateSubject from '../models/subjects/data-update' import AddressCreatedSubject from '../models/subjects/address-created-subject' import WalletDeletedSubject from '../models/subjects/wallet-deleted-subject' import TxDbChangedSubject from '../models/subjects/tx-db-changed-subject' -import { LumosCellQuery, LumosCell } from './sync/indexer-connector' +import { LumosCellQuery, LumosCell } from './sync/connector' import { WorkerMessage, StartParams, QueryIndexerParams } from './task' import logger from '../utils/logger' import CommonUtils from '../utils/common' import queueWrapper from '../utils/queue' import env from '../env' +import MultisigConfigDbChangedSubject from '../models/subjects/multisig-config-db-changed-subject' +import Multisig from '../services/multisig' +import { SyncAddressType } from '../database/chain/entities/sync-progress' +import { debounceTime } from 'rxjs/operators' let network: Network | null let child: ChildProcess | null = null @@ -106,6 +110,7 @@ export const createBlockSyncTask = async () => { child = fork(path.join(__dirname, 'task-wrapper.js'), [], { env: { fileBasePath: env.fileBasePath }, stdio: ['ipc', process.stdout, 'pipe'], + execArgv: env.app.isPackaged ? [] : ['--inspect'] }) child.on('message', ({ id, message, channel }: WorkerMessage) => { @@ -192,3 +197,17 @@ export const registerRequest = (c: ChildProcess, msg: Required) = AddressCreatedSubject.getSubject().subscribe(() => resetSyncTaskQueue.asyncPush(true)) WalletDeletedSubject.getSubject().subscribe(() => resetSyncTaskQueue.asyncPush(true)) +MultisigConfigDbChangedSubject.getSubject() + .pipe(debounceTime(1000)) + .subscribe(async () => { + if (!child) { + return + } + const appendScripts = await Multisig.getMultisigConfigForLight() + const msg: Required> = { type: 'call', channel: 'append_scripts', id: requestId++, message: appendScripts } + return registerRequest(child, msg).catch(err => { + logger.error(`Sync:\ffailed to append script to light client`, err) + }) + }) diff --git a/packages/neuron-wallet/src/block-sync-renderer/sync/connector.ts b/packages/neuron-wallet/src/block-sync-renderer/sync/connector.ts new file mode 100644 index 0000000000..95b6339c7c --- /dev/null +++ b/packages/neuron-wallet/src/block-sync-renderer/sync/connector.ts @@ -0,0 +1,55 @@ +import { SyncAddressType } from '../../database/chain/entities/sync-progress' +import { Subject } from 'rxjs' + +export interface BlockTips { + cacheTipNumber: number + indexerTipNumber: number | undefined +} + +export interface LumosCellQuery { + lock: CKBComponents.Script | null + type: CKBComponents.Script | null + data: string | null +} + +export interface LumosCell { + block_hash: string + out_point: { + tx_hash: string + index: string + } + cell_output: { + capacity: string + lock: { + code_hash: string + args: string + hash_type: string + } + type?: { + code_hash: string + args: string + hash_type: string + } + } + data?: string +} + +export interface AppendScript { + walletId: string + script: CKBComponents.Script + addressType: SyncAddressType + scriptType: CKBRPC.ScriptType +} + +export abstract class Connector { + abstract blockTipsSubject: Subject + abstract transactionsSubject: Subject<{ txHashes: CKBComponents.Hash[]; params: TransactionsSubjectParam }> + + abstract connect(): Promise + abstract notifyCurrentBlockNumberProcessed(param: TransactionsSubjectParam): void + abstract stop(): void + abstract getLiveCellsByScript(query: LumosCellQuery): Promise + async appendScript(_scripts: AppendScript[]) { + // do nothing + } +} diff --git a/packages/neuron-wallet/src/block-sync-renderer/sync/indexer-connector.ts b/packages/neuron-wallet/src/block-sync-renderer/sync/indexer-connector.ts index de363b600e..8c67e3f5e8 100644 --- a/packages/neuron-wallet/src/block-sync-renderer/sync/indexer-connector.ts +++ b/packages/neuron-wallet/src/block-sync-renderer/sync/indexer-connector.ts @@ -1,65 +1,30 @@ -import type { ScriptHashType } from '../../models/chain/script' import { Subject } from 'rxjs' -import { queue, AsyncQueue } from 'async' +import { queue, QueueObject } from 'async' import { Tip, QueryOptions } from '@ckb-lumos/base' import { CkbIndexer, CellCollector } from '@nervina-labs/ckb-indexer' import logger from '../../utils/logger' import CommonUtils from '../../utils/common' import RpcService from '../../services/rpc-service' -import TransactionWithStatus from '../../models/chain/transaction-with-status' import { Address } from '../../models/address' import AddressMeta from '../../database/address/meta' import IndexerTxHashCache from '../../database/chain/entities/indexer-tx-hash-cache' import IndexerCacheService from './indexer-cache-service' +import { BlockTips, LumosCellQuery, Connector } from './connector' -export interface LumosCellQuery { - lock: { codeHash: string; hashType: ScriptHashType; args: string } | null - type: { codeHash: string; hashType: ScriptHashType; args: string } | null - data: string | null -} - -export interface LumosCell { - block_hash: string - out_point: { - tx_hash: string - index: string - } - cell_output: { - capacity: string - lock: { - code_hash: string - args: string - hash_type: string - } - type?: { - code_hash: string - args: string - hash_type: string - } - } - data?: string -} - -export interface BlockTips { - cacheTipNumber: number - indexerTipNumber: number | undefined -} - -export default class IndexerConnector { +export default class IndexerConnector extends Connector { private indexer: CkbIndexer private rpcService: RpcService private addressesByWalletId: Map - private processNextBlockNumberQueue: AsyncQueue | undefined - private indexerQueryQueue: AsyncQueue | undefined + private processNextBlockNumberQueue: QueueObject | undefined + private indexerQueryQueue: QueueObject | undefined private processingBlockNumber: string | undefined - public pollingIndexer: boolean = false + private pollingIndexer: boolean = false public readonly blockTipsSubject: Subject = new Subject() - public readonly transactionsSubject: Subject> = new Subject< - Array - >() + public readonly transactionsSubject = new Subject<{ txHashes: CKBComponents.Hash[]; params: string | undefined }>() constructor(addresses: Address[], nodeUrl: string, indexerUrl: string) { + super() this.indexer = new CkbIndexer(nodeUrl, indexerUrl) this.rpcService = new RpcService(nodeUrl) @@ -182,7 +147,7 @@ export default class IndexerConnector { return result } - private async getTxsInNextUnprocessedBlockNumber() { + private async getTxHashesWithNextUnprocessedBlockNumber(): Promise<[string | undefined, string[]]> { const txHashCachesByNextBlockNumberAndAddress = await Promise.all( [...this.addressesByWalletId.entries()].map(async ([walletId, addressMetas]) => { const indexerCacheService = new IndexerCacheService(walletId, addressMetas, this.rpcService, this.indexer) @@ -206,15 +171,12 @@ export default class IndexerConnector { const nextUnprocessedBlockNumber = [...groupedTxHashCaches.keys()].sort((a, b) => parseInt(a) - parseInt(b)).shift() if (!nextUnprocessedBlockNumber) { - return [] + return [undefined, []] } const txHashCachesInNextUnprocessedBlockNumber = groupedTxHashCaches.get(nextUnprocessedBlockNumber) - const txsInNextUnprocessedBlockNumber = await this.fetchTxsWithStatus( - txHashCachesInNextUnprocessedBlockNumber!.map(({ txHash }) => txHash) - ) - return txsInNextUnprocessedBlockNumber + return [nextUnprocessedBlockNumber, txHashCachesInNextUnprocessedBlockNumber!.map(({ txHash }) => txHash)] } private async upsertTxHashes(): Promise { @@ -233,31 +195,13 @@ export default class IndexerConnector { } private async processTxsInNextBlockNumber() { - const txsInNextUnprocessedBlockNumber = await this.getTxsInNextUnprocessedBlockNumber() - if (txsInNextUnprocessedBlockNumber.length) { - this.processingBlockNumber = txsInNextUnprocessedBlockNumber[0].transaction.blockNumber - this.transactionsSubject.next(txsInNextUnprocessedBlockNumber) + const [nextBlockNumber, txHashesInNextBlock] = await this.getTxHashesWithNextUnprocessedBlockNumber() + if (nextBlockNumber !== undefined && txHashesInNextBlock.length) { + this.processingBlockNumber = nextBlockNumber + this.transactionsSubject.next({ txHashes: txHashesInNextBlock, params: this.processingBlockNumber }) } } - private async fetchTxsWithStatus(txHashes: string[]) { - const txsWithStatus: TransactionWithStatus[] = [] - - for (const hash of txHashes) { - const txWithStatus = await this.rpcService.getTransaction(hash) - if (!txWithStatus) { - throw new Error(`failed to fetch transaction for hash ${hash}`) - } - const blockHeader = await this.rpcService.getHeader(txWithStatus!.txStatus.blockHash!) - txWithStatus!.transaction.blockNumber = blockHeader!.number - txWithStatus!.transaction.blockHash = txWithStatus!.txStatus.blockHash! - txWithStatus!.transaction.timestamp = blockHeader!.timestamp - txsWithStatus.push(txWithStatus) - } - - return txsWithStatus - } - public notifyCurrentBlockNumberProcessed(blockNumber: string) { if (blockNumber === this.processingBlockNumber) { delete this.processingBlockNumber @@ -266,4 +210,8 @@ export default class IndexerConnector { } this.processNextBlockNumber() } + + public stop(): void { + this.pollingIndexer = false + } } diff --git a/packages/neuron-wallet/src/block-sync-renderer/sync/light-connector.ts b/packages/neuron-wallet/src/block-sync-renderer/sync/light-connector.ts new file mode 100644 index 0000000000..e50f5a99fb --- /dev/null +++ b/packages/neuron-wallet/src/block-sync-renderer/sync/light-connector.ts @@ -0,0 +1,320 @@ +import { Subject } from 'rxjs' +import { queue, QueueObject } from 'async' +import { HexString, QueryOptions } from '@ckb-lumos/base' +import { CkbIndexer, CellCollector } from '@nervina-labs/ckb-indexer' +import logger from '../../utils/logger' +import { Address } from '../../models/address' +import AddressMeta from '../../database/address/meta' +import { scheduler } from 'timers/promises' +import SyncProgressService from '../../services/sync-progress' +import { BlockTips, LumosCellQuery, Connector, AppendScript } from './connector' +import { scriptToHash } from '@nervosnetwork/ckb-sdk-utils' +import { FetchTransactionReturnType, LightRPC, LightScriptFilter } from '../../utils/ckb-rpc' +import HexUtils from '../../utils/hex' +import Multisig from '../../services/multisig' +import { SyncAddressType } from '../../database/chain/entities/sync-progress' +import WalletService from '../../services/wallets' +import AssetAccountInfo from '../../models/asset-account-info' +import { DepType } from '../../models/chain/cell-dep' +import { molecule, number } from '@ckb-lumos/codec' + +interface SyncQueueParam { + script: CKBComponents.Script + scriptType: CKBRPC.ScriptType + blockRange: [HexString, HexString] + cursor?: HexString +} + +const unpackGroup = molecule.vector( + molecule.struct( + { + tx_hash: number.Uint256BE, + index: number.Uint32LE + }, + ['tx_hash', 'index'] + ) +) + +export default class LightConnector extends Connector { + private lightRpc: LightRPC + private indexer: CkbIndexer + private addressMetas: AddressMeta[] + private syncQueue: QueueObject = queue(this.syncNextWithScript.bind(this), 1) + private indexerQueryQueue: QueueObject | undefined + private pollingIndexer: boolean = false + private syncInQueue: Map< + CKBComponents.Hash, + { blockStartNumber: number; blockEndNumber: number; cursor?: string } + > = new Map() + + public readonly blockTipsSubject: Subject = new Subject() + public readonly transactionsSubject = new Subject<{ txHashes: CKBComponents.Hash[]; params: CKBComponents.Hash }>() + + constructor(addresses: Address[], nodeUrl: string) { + super() + this.indexer = new CkbIndexer(nodeUrl, nodeUrl) + this.lightRpc = new LightRPC(nodeUrl) + this.addressMetas = addresses.map(address => AddressMeta.fromObject(address)) + this.indexerQueryQueue = queue(this.collectLiveCellsByScript.bind(this)) + + // fetch some dep cell + this.fetchDepCell() + } + + private async getDepTxs(): Promise { + const assetAccountInfo = new AssetAccountInfo() + const fetchCellDeps = [ + assetAccountInfo.anyoneCanPayCellDep, + assetAccountInfo.sudtCellDep, + assetAccountInfo.getNftClassInfo().cellDep, + assetAccountInfo.getNftInfo().cellDep, + assetAccountInfo.getNftIssuerInfo().cellDep, + assetAccountInfo.getLegacyAnyoneCanPayInfo().cellDep, + assetAccountInfo.getChequeInfo().cellDep + ] + const fetchTxHashes = fetchCellDeps + .map(v => v.outPoint.txHash) + .map<[string, string]>(v => ['fetchTransaction', v]) + const txs = await this.lightRpc + .createBatchRequest(fetchTxHashes) + .exec() + if (txs.some(v => !v.txWithStatus)) { + // wait for light client sync the dep cell + await scheduler.wait(10000) + return await this.getDepTxs() + } + return fetchCellDeps + .map((v, idx) => { + if (v.depType === DepType.DepGroup) { + const tx = txs[idx] + return tx.txWithStatus ? tx?.txWithStatus?.transaction?.outputsData?.[+v.outPoint.index] : undefined + } + }) + .filter((v): v is string => !!v) + } + + private async fetchDepCell() { + const depGroupOutputsData: string[] = await this.getDepTxs() + const depGroupTxHashes = [ + ...new Set(depGroupOutputsData.map(v => unpackGroup.unpack(v).map(v => v.tx_hash.toHexString())).flat()) + ] + if (depGroupTxHashes.length) { + await this.lightRpc + .createBatchRequest( + depGroupTxHashes.map(v => ['fetchTransaction', v]) + ) + .exec() + } + } + + private async synchronize() { + if (!this.syncQueue.idle()) { + return + } + await this.subscribeSync() + const syncScripts = await this.lightRpc.getScripts() + const syncStatusMap = await SyncProgressService.getAllSyncStatusToMap() + syncStatusMap.forEach(v => { + if (v.cursor && !this.syncInQueue.has(v.hash)) { + this.syncQueue.push({ + script: { + codeHash: v.codeHash, + hashType: v.hashType, + args: v.args + }, + blockRange: [HexUtils.toHex(v.blockStartNumber), HexUtils.toHex(v.blockEndNumber)], + scriptType: v.scriptType, + cursor: v.cursor + }) + } + }) + syncScripts.forEach(syncScript => { + const scriptHash = scriptToHash(syncScript.script) + const syncStatus = syncStatusMap.get(scriptHash) + if ( + syncStatus && + !this.syncInQueue.has(scriptHash) && + !syncStatus.cursor && + syncStatus.blockEndNumber < parseInt(syncScript.blockNumber) + ) { + this.syncQueue.push({ + script: syncScript.script, + blockRange: [HexUtils.toHex(syncStatus.blockEndNumber), syncScript.blockNumber], + scriptType: syncScript.scriptType, + cursor: undefined + }) + } + }) + } + + private async subscribeSync() { + const minSyncBlockNumber = await SyncProgressService.getCurrentWalletMinBlockNumber() + const header = await this.lightRpc.getTipHeader() + this.blockTipsSubject.next({ + cacheTipNumber: minSyncBlockNumber, + indexerTipNumber: +header.number + }) + } + + private async initSyncProgress(appendScripts: AppendScript[] = []) { + if (!this.addressMetas.length && !appendScripts.length) { + return + } + const syncScripts = await this.lightRpc.getScripts() + const existSyncscripts: Record = {} + syncScripts.forEach(v => { + existSyncscripts[scriptToHash(v.script)] = v + }) + const currentWalletId = WalletService.getInstance().getCurrent()?.id + const allScripts = this.addressMetas + .filter(v => (currentWalletId ? v.walletId === currentWalletId : true)) + .map(addressMeta => { + const lockScripts = [ + addressMeta.generateDefaultLockScript(), + addressMeta.generateACPLockScript(), + addressMeta.generateLegacyACPLockScript() + ] + return lockScripts.map(v => ({ + script: v.toSDK(), + scriptType: 'lock' as CKBRPC.ScriptType, + walletId: addressMeta.walletId + })) + }) + .flat() + const walletMinBlockNumber = await SyncProgressService.getWalletMinBlockNumber() + const wallets = await WalletService.getInstance().getAll() + const walletStartBlockMap = wallets.reduce>( + (pre, cur) => ({ ...pre, [cur.id]: cur.startBlockNumberInLight }), + {} + ) + const otherTypeSyncProgress = await SyncProgressService.getOtherTypeSyncProgress() + const setScriptsParams = [ + ...allScripts.map(v => ({ + ...v, + blockNumber: + existSyncscripts[scriptToHash(v.script)]?.blockNumber ?? + walletStartBlockMap[v.walletId] ?? + `0x${(walletMinBlockNumber?.[v.walletId] ?? 0).toString(16)}` + })), + ...appendScripts.map(v => ({ + ...v, + blockNumber: + existSyncscripts[scriptToHash(v.script)]?.blockNumber ?? + `0x${(otherTypeSyncProgress[scriptToHash(v.script)] ?? 0).toString(16)}` + })) + ] + await this.lightRpc.setScripts(setScriptsParams) + const walletIds = [...new Set(this.addressMetas.map(v => v.walletId))] + await SyncProgressService.resetSyncProgress([allScripts, appendScripts].flat()) + await SyncProgressService.updateSyncProgressFlag(walletIds) + await SyncProgressService.removeByHashesAndAddressType( + SyncAddressType.Multisig, + appendScripts.map(v => scriptToHash(v.script)) + ) + } + + private async initSync() { + const appendScripts = await Multisig.getMultisigConfigForLight() + await this.initSyncProgress(appendScripts) + while (this.pollingIndexer) { + await this.synchronize() + await scheduler.wait(5000) + } + } + + private async syncNextWithScript({ script, scriptType, blockRange, cursor }: SyncQueueParam) { + const syncProgress = await SyncProgressService.getSyncStatus(script) + if (!syncProgress) { + return + } + const result = await this.lightRpc.getTransactions({ script, blockRange, scriptType }, 'asc', '0x64', cursor!) + if (!result.txs.length) { + await SyncProgressService.updateSyncStatus(syncProgress.hash, { + blockStartNumber: parseInt(blockRange[1]), + blockEndNumber: parseInt(blockRange[1]), + cursor: undefined + }) + return + } + this.transactionsSubject.next({ txHashes: result.txs.map(v => v.txHash), params: syncProgress.hash }) + this.syncInQueue.set(syncProgress.hash, { + blockStartNumber: result.lastCursor === '0x' ? parseInt(blockRange[1]) : parseInt(blockRange[0]), + blockEndNumber: parseInt(blockRange[1]), + cursor: result.lastCursor === '0x' ? undefined : result.lastCursor + }) + } + + private async collectLiveCellsByScript(query: LumosCellQuery) { + const { lock, type, data } = query + if (!lock && !type) { + throw new Error('at least one script is required') + } + + const queries: QueryOptions = {} + if (lock) { + queries.lock = { + code_hash: lock.codeHash, + hash_type: lock.hashType, + args: lock.args + } + } + if (type) { + queries.type = { + code_hash: type.codeHash, + hash_type: type.hashType, + args: type.args + } + } + queries.data = data || 'any' + + const collector = new CellCollector(this.indexer, queries) + + const result = [] + for await (const cell of collector.collect()) { + result.push(cell) + } + return result + } + + public async connect() { + try { + logger.info('LightConnector:\tconnect ...:') + this.pollingIndexer = true + this.initSync() + } catch (error) { + logger.error(`Error connecting to Light: ${error.message}`) + throw error + } + } + + public stop(): void { + this.pollingIndexer = false + } + + public async getLiveCellsByScript(query: LumosCellQuery) { + return new Promise((resolve, reject) => { + this.indexerQueryQueue!.push(query, (err: any, result: unknown) => { + if (err) { + return reject(err) + } + resolve(result) + }) + }) + } + + public async notifyCurrentBlockNumberProcessed(hash: CKBComponents.Hash) { + const nextSyncParams = this.syncInQueue.get(hash) + if (nextSyncParams) { + try { + await SyncProgressService.updateSyncStatus(hash, nextSyncParams) + } finally { + this.syncInQueue.delete(hash) + } + } + await this.subscribeSync() + } + + async appendScript(scripts: AppendScript[]) { + this.initSyncProgress(scripts) + } +} diff --git a/packages/neuron-wallet/src/block-sync-renderer/sync/queue.ts b/packages/neuron-wallet/src/block-sync-renderer/sync/queue.ts index 4b3903e29c..aa8b7102c9 100644 --- a/packages/neuron-wallet/src/block-sync-renderer/sync/queue.ts +++ b/packages/neuron-wallet/src/block-sync-renderer/sync/queue.ts @@ -1,4 +1,4 @@ -import { queue, AsyncQueue } from 'async' +import { queue, QueueObject } from 'async' import { TransactionPersistor } from '../../services/tx' import RpcService from '../../services/rpc-service' import AssetAccountService from '../../services/asset-account-service' @@ -10,12 +10,17 @@ import AssetAccountInfo from '../../models/asset-account-info' import { Address as AddressInterface } from '../../models/address' import AddressParser from '../../models/address-parser' import Multisig from '../../models/multisig' +import BlockHeader from '../../models/chain/block-header' import TxAddressFinder from './tx-address-finder' -import IndexerConnector, { BlockTips } from './indexer-connector' +import IndexerConnector from './indexer-connector' import IndexerCacheService from './indexer-cache-service' import logger from '../../utils/logger' import CommonUtils from '../../utils/common' import { ShouldInChildProcess } from '../../exceptions' +import { AppendScript, BlockTips, Connector } from './connector' +import LightConnector from './light-connector' +import { generateRPC } from '../../utils/ckb-rpc' +import { BUNDLED_LIGHT_CKB_URL } from '../../utils/const' export default class Queue { #lockHashes: string[] @@ -23,8 +28,8 @@ export default class Queue { #indexerUrl: string #addresses: AddressInterface[] #rpcService: RpcService - #indexerConnector: IndexerConnector | undefined - #checkAndSaveQueue: AsyncQueue<{ transactions: Transaction[] }> | undefined + #indexerConnector: Connector | undefined + #checkAndSaveQueue: QueueObject<{ txHashes: CKBComponents.Hash[], params: unknown }> | undefined #multiSignBlake160s: string[] #anyoneCanPayLockHashes: string[] @@ -48,9 +53,12 @@ export default class Queue { start = async () => { logger.info('Queue:\tstart') try { - this.#indexerConnector = new IndexerConnector(this.#addresses, this.#url, this.#indexerUrl) - - await this.#indexerConnector.connect() + if (this.#url === BUNDLED_LIGHT_CKB_URL) { + this.#indexerConnector = new LightConnector(this.#addresses, this.#url) + } else { + this.#indexerConnector = new IndexerConnector(this.#addresses, this.#url, this.#indexerUrl) + } + await this.#indexerConnector!.connect() } catch (error) { logger.error('Restarting child process due to error', error.message) if (process.send) { @@ -63,12 +71,12 @@ export default class Queue { this.#indexerConnector.blockTipsSubject.subscribe(tip => this.#updateBlockNumberTips(tip)) this.#checkAndSaveQueue = queue(async (task: any) => { - const { transactions } = task + const { txHashes, params } = task //need to retry after a certain period of time if throws errors // eslint-disable-next-line no-constant-condition while (true) { try { - await this.#checkAndSave(transactions) + await this.#checkAndSave(txHashes) break } catch (error) { logger.error('retry saving transactions in 2 seconds due to error:', error) @@ -76,22 +84,22 @@ export default class Queue { } } - this.#indexerConnector!.notifyCurrentBlockNumberProcessed(transactions[0].blockNumber) + this.#indexerConnector!.notifyCurrentBlockNumberProcessed(params) }) this.#checkAndSaveQueue.error((err: any, task: any) => { logger.error(err, JSON.stringify(task, undefined, 2)) }) - this.#indexerConnector.transactionsSubject.subscribe(transactions => { - const task = { transactions: transactions.map(t => t.transaction) } - this.#checkAndSaveQueue!.push(task) - }) + this.#indexerConnector.transactionsSubject + .subscribe(task => { + this.#checkAndSaveQueue!.push(task) + }) } - getIndexerConnector = (): IndexerConnector => this.#indexerConnector! + getIndexerConnector = (): Connector => this.#indexerConnector! - stop = () => (this.#indexerConnector!.pollingIndexer = false) + stop = () => this.#indexerConnector!.stop() stopAndWait = async () => { this.stop() @@ -100,7 +108,45 @@ export default class Queue { } } - #checkAndSave = async (transactions: Transaction[]): Promise => { + async appendLightScript(scripts: AppendScript[]) { + await this.#indexerConnector?.appendScript(scripts) + } + + private async fetchTxsWithStatus(txHashes: string[]) { + const rpc = generateRPC(this.#url) + const txsWithStatus = await rpc.createBatchRequest<'getTransaction', string[], CKBComponents.TransactionWithStatus[]>( + txHashes.map(v => ['getTransaction', v]) + ).exec() + const txs: Transaction[] = [] + const blockHashes = [] + for (let index = 0; index < txsWithStatus.length; index++) { + if (txsWithStatus[index]?.transaction) { + const tx = Transaction.fromSDK(txsWithStatus[index].transaction) + tx.blockHash = txsWithStatus[index].txStatus.blockHash! + blockHashes.push(tx.blockHash) + txs.push(tx) + } else { + if ((txsWithStatus[index].txStatus as any) === 'rejected') { + logger.warn(`Transaction[${txHashes[index]}] was rejected`) + } + throw new Error(`failed to fetch transaction for hash ${txHashes[index]}`) + } + } + const headers = await rpc.createBatchRequest<'getHeader', string[], CKBComponents.BlockHeader[]>( + blockHashes.map(v => ['getHeader', v]) + ).exec() + headers.forEach((blockHeader, idx) => { + if (blockHeader) { + const header = BlockHeader.fromSDK(blockHeader) + txs[idx].timestamp = header.timestamp + txs[idx].blockNumber = header.number + } + }) + return txs + } + + #checkAndSave = async (txHashes: CKBComponents.Hash[]): Promise => { + const transactions = await this.fetchTxsWithStatus(txHashes) const cachedPreviousTxs = new Map() const fetchTxQueue = queue(async (task: any) => { diff --git a/packages/neuron-wallet/src/block-sync-renderer/task.ts b/packages/neuron-wallet/src/block-sync-renderer/task.ts index ff33424118..eeb58d67c3 100644 --- a/packages/neuron-wallet/src/block-sync-renderer/task.ts +++ b/packages/neuron-wallet/src/block-sync-renderer/task.ts @@ -1,4 +1,4 @@ -import type { LumosCellQuery } from './sync/indexer-connector' +import type { LumosCellQuery } from './sync/connector' import initConnection from '../database/chain/ormconfig' import { register as registerTxStatusListener } from './tx-status-listener' import SyncQueue from './sync/queue' @@ -9,18 +9,9 @@ import env from '../env' let syncQueue: SyncQueue | null export interface WorkerMessage { - type: 'call' | 'response' | 'kill' - id?: number - channel: - | 'start' - | 'queryIndexer' - | 'unmount' - | 'cache-tip-block-updated' - | 'tx-db-changed' - | 'wallet-deleted' - | 'address-created' - | 'indexer-error' - | 'check-and-save-wallet-address' + type: 'call' | 'response' | 'kill', + id?: number, + channel: 'start' | 'queryIndexer' | 'unmount' | 'cache-tip-block-updated' | 'tx-db-changed' | 'wallet-deleted' | 'address-created' | 'indexer-error' | 'check-and-save-wallet-address' | 'append_scripts' message: T } @@ -87,6 +78,12 @@ export const listener = async ({ type, id, channel, message }: WorkerMessage) => res = message ? await syncQueue?.getIndexerConnector()?.getLiveCellsByScript(message) : [] break } + case 'append_scripts': { + if (Array.isArray(message)) { + await syncQueue?.appendLightScript(message) + } + break + } default: { // ignore } diff --git a/packages/neuron-wallet/src/block-sync-renderer/tx-status-listener.ts b/packages/neuron-wallet/src/block-sync-renderer/tx-status-listener.ts index 7bb9d8dbc9..ae10bb37f5 100644 --- a/packages/neuron-wallet/src/block-sync-renderer/tx-status-listener.ts +++ b/packages/neuron-wallet/src/block-sync-renderer/tx-status-listener.ts @@ -1,5 +1,4 @@ import { getConnection } from 'typeorm' -import CKB from '@nervosnetwork/ckb-sdk-core' import { CONNECTION_NOT_FOUND_NAME } from '../database/chain/ormconfig' import { FailedTransaction, TransactionPersistor } from '../services/tx' import RpcService from '../services/rpc-service' @@ -62,8 +61,7 @@ const trackingStatus = async () => { if (successTxs.length > 0) { const url: string = NetworksService.getInstance().getCurrent().remote - const ckb = new CKB(url) - const rpcService = new RpcService(ckb.rpc.node.url) + const rpcService = new RpcService(url) for (const successTx of successTxs) { const transaction = successTx.tx! const { blockHash } = successTx diff --git a/packages/neuron-wallet/src/controllers/api.ts b/packages/neuron-wallet/src/controllers/api.ts index 82acd734a2..a70dd91e62 100644 --- a/packages/neuron-wallet/src/controllers/api.ts +++ b/packages/neuron-wallet/src/controllers/api.ts @@ -51,13 +51,14 @@ import { GenerateAnyoneCanPayTxParams, SendAnyoneCanPayTxParams } from './anyone import { DeviceInfo, ExtendedPublicKey } from '../services/hardware/common' import HardwareController from './hardware' import OfflineSignController from './offline-sign' -import SUDTController from './sudt' +import SUDTController from '../controllers/sudt' import SyncedBlockNumber from '../models/synced-block-number' import IndexerService from '../services/indexer' import MultisigConfigModel from '../models/multisig-config' import startMonitor, { stopMonitor } from '../services/monitor' import { migrateCkbData } from '../services/ckb-runner' import NodeService from '../services/node' +import SyncProgressService from '../services/sync-progress' export type Command = 'export-xpubkey' | 'import-xpubkey' | 'delete-wallet' | 'backup-wallet' | 'migrate-acp' // Handle channel messages from renderer process and user actions. @@ -778,6 +779,14 @@ export default class ApiController { status: ResponseCode.Success, } }) + + //light client + handle('get-sync-progress-by-addresses', async (_, hashes: string[]) => { + return { + result: (await SyncProgressService.getSyncProgressByHashes(hashes)), + status: ResponseCode.Success, + } + }) } // Register handler, warp and serialize API response diff --git a/packages/neuron-wallet/src/controllers/app/index.ts b/packages/neuron-wallet/src/controllers/app/index.ts index ac95e2847d..80b6fa4c8c 100644 --- a/packages/neuron-wallet/src/controllers/app/index.ts +++ b/packages/neuron-wallet/src/controllers/app/index.ts @@ -9,11 +9,12 @@ import logger from '../../utils/logger' import { subscribe } from './subscribe' import { register as registerListeners } from '../../listeners/main' import WalletsService from '../../services/wallets' -import ApiController, { Command } from '../api' -import { migrate as mecuryMigrate } from '../mercury' -import SyncApiController from '../sync-api' +import ApiController, { Command } from '../../controllers/api' +import { migrate as mecuryMigrate } from '../../controllers/mercury' +import SyncApiController from '../../controllers/sync-api' import { SETTINGS_WINDOW_TITLE } from '../../utils/const' import { stopCkbNode } from '../../services/ckb-runner' +import { CKBLightRunner } from '../../services/light-runner' const app = electronApp @@ -58,7 +59,10 @@ export default class AppController { if (env.isTestMode) { return } - await stopCkbNode() + await Promise.all([ + stopCkbNode(), + CKBLightRunner.getInstance().stop(), + ]) } public registerChannels(win: BrowserWindow, channels: string[]) { diff --git a/packages/neuron-wallet/src/controllers/app/menu.ts b/packages/neuron-wallet/src/controllers/app/menu.ts index 426c01e940..19c5028898 100644 --- a/packages/neuron-wallet/src/controllers/app/menu.ts +++ b/packages/neuron-wallet/src/controllers/app/menu.ts @@ -5,9 +5,9 @@ import { t } from 'i18next' import { Subject } from 'rxjs' import { throttleTime } from 'rxjs/operators' import env from '../../env' -import UpdateController from '../update' -import ExportDebugController from '../export-debug' -import { showWindow } from '../app/show-window' +import UpdateController from '../../controllers/update' +import ExportDebugController from '../../controllers/export-debug' +import { showWindow } from '../../controllers/app/show-window' import WalletsService from '../../services/wallets' import OfflineSignService from '../../services/offline-sign' import CommandSubject from '../../models/subjects/command' @@ -16,6 +16,8 @@ import { SETTINGS_WINDOW_TITLE, SETTINGS_WINDOW_WIDTH } from '../../utils/const' import { OfflineSignJSON } from '../../models/offline-sign' import NetworksService from '../../services/networks' import { clearCkbNodeCache } from '../../services/ckb-runner' +import { CKBLightRunner } from '../../services/light-runner' +import { NetworkType } from '../../models/network' enum URL { Settings = '/settings/general', @@ -38,19 +40,28 @@ const separator: MenuItemConstructorOptions = { type: 'separator', } -const showAbout = () => { - let applicationVersion = t('about.app-version', { name: app.name, version: app.getVersion() }) - - const appPath = app.isPackaged ? app.getAppPath() : path.join(__dirname, '../../../../..') - const ckbVersionPath = path.join(appPath, '.ckb-version') - if (fs.existsSync(ckbVersionPath)) { +const getVerionFromFile = (filePath: string) => { + if (fs.existsSync(filePath)) { try { - const ckbVersion = fs.readFileSync(ckbVersionPath, 'utf8') - applicationVersion += `\n${t('about.ckb-client-version', { version: ckbVersion })}` + return fs.readFileSync(filePath, 'utf8') } catch (err) { logger.error(`[Menu]: `, err) } } +} + +const showAbout = () => { + let applicationVersion = t('about.app-version', { name: app.name, version: app.getVersion() }) + + const appPath = app.isPackaged ? app.getAppPath() : path.join(__dirname, '../../../../..') + const ckbVersion = getVerionFromFile(path.join(appPath, '.ckb-version')) + if (ckbVersion) { + applicationVersion += `\n${t('about.ckb-client-version', { version: ckbVersion })}` + } + const ckbLightClientVersion = getVerionFromFile(path.join(appPath, '.ckb-light-version')) + if (ckbLightClientVersion) { + applicationVersion += `${t('about.ckb-light-client-version', { version: ckbLightClientVersion })}` + } const isWin = process.platform === 'win32' @@ -116,7 +127,7 @@ const updateApplicationMenu = (mainWindow: BrowserWindow | null) => { let isMainWindow = mainWindow === currentWindow const walletsService = WalletsService.getInstance() - const isMainnet = new NetworksService().getCurrent().chain === 'ckb' + const network = new NetworksService().getCurrent() const wallets = walletsService.getAll().map(({ id, name }) => ({ id, name })) const currentWallet = walletsService.getCurrent() const hasCurrentWallet = currentWallet !== undefined @@ -316,10 +327,10 @@ const updateApplicationMenu = (mainWindow: BrowserWindow | null) => { `#/multisig-address/${currentWallet!.id}`, t(`messageBox.multisig-address.title`), { - width: 900, - maxWidth: 900, - minWidth: 900, - resizable: true, + width: 1000, + maxWidth: 1000, + minWidth: 1000, + resizable: true }, ['multisig-output-update'] ) @@ -327,7 +338,7 @@ const updateApplicationMenu = (mainWindow: BrowserWindow | null) => { }, { label: t('application-menu.tools.clear-sync-data'), - enabled: hasCurrentWallet && isMainnet, + enabled: hasCurrentWallet && (network.chain === 'ckb' || NetworkType.Light === network.type), click: async () => { const res = await dialog.showMessageBox({ type: 'warning', @@ -338,7 +349,12 @@ const updateApplicationMenu = (mainWindow: BrowserWindow | null) => { cancelId: 1, }) if (res.response === 0) { - await clearCkbNodeCache() + const network = new NetworksService().getCurrent() + if (network.type === NetworkType.Light) { + await CKBLightRunner.getInstance().clearNodeCache() + } else { + await clearCkbNodeCache() + } } }, }, diff --git a/packages/neuron-wallet/src/controllers/export-debug.ts b/packages/neuron-wallet/src/controllers/export-debug.ts index 0d3d36a267..9847fae5f2 100644 --- a/packages/neuron-wallet/src/controllers/export-debug.ts +++ b/packages/neuron-wallet/src/controllers/export-debug.ts @@ -2,7 +2,6 @@ import os from 'os' import fs from 'fs' import path from 'path' import archiver from 'archiver' -import CKB from '@nervosnetwork/ckb-sdk-core' import { app, dialog } from 'electron' import logger from '../utils/logger' import { t } from 'i18next' @@ -11,6 +10,8 @@ import SyncedBlockNumber from '../models/synced-block-number' import AddressService from '../services/addresses' import redistCheck from '../utils/redist-check' import SettingsService from '../services/settings' +import { generateRPC } from '../utils/ckb-rpc' +import { CKBLightRunner } from '../services/light-runner' export default class ExportDebugController { #I18N_PATH = 'export-debug-info' @@ -41,6 +42,7 @@ export default class ExportDebugController { this.addBundledCKBLog(), this.addLogFiles(), this.addHdPublicKeyInfoCsv(), + this.addBundledCKBLightClientLog() ]) await this.archive.finalize() dialog.showMessageBox({ @@ -55,23 +57,25 @@ export default class ExportDebugController { private addStatusFile = async () => { const neuronVersion = app.getVersion() const url = NetworksService.getInstance().getCurrent().remote - const ckb = new CKB(url) + const rpcService = generateRPC(url) const [syncedBlockNumber, ckbVersion, tipBlockNumber, peers, vcredist] = await Promise.all([ new SyncedBlockNumber() .getNextBlock() .then(n => n.toString()) .catch(() => ''), - ckb.rpc + rpcService .localNodeInfo() - .then(res => res.version) + .then(v => v.version) .catch(() => ''), - ckb.rpc + rpcService .getTipBlockNumber() .then(n => BigInt(n).toString()) .catch(() => ''), - ckb.rpc.getPeers().catch(() => []), - redistCheck(), + rpcService + .getPeers() + .catch(() => []), + redistCheck() ]) const { platform, arch } = process const release = os.release() @@ -154,4 +158,10 @@ export default class ExportDebugController { this.archive.file(path.join(logFile.path, '..', file), { name: file }) }) } + + private addBundledCKBLightClientLog() { + const logPath = CKBLightRunner.getInstance().logPath + if (!fs.existsSync(logPath)) {return} + this.archive.file(logPath, { name: 'bundled-ckb-lignt-client.log' }) + } } diff --git a/packages/neuron-wallet/src/controllers/networks/index.ts b/packages/neuron-wallet/src/controllers/networks/index.ts index b25d31e06c..2ff247281f 100644 --- a/packages/neuron-wallet/src/controllers/networks/index.ts +++ b/packages/neuron-wallet/src/controllers/networks/index.ts @@ -26,7 +26,7 @@ export default class NetworksController { await this.connectToNetwork(true) } else { logger.debug('Network:\tconnection dropped') - resetSyncTaskQueue.push(false) + resetSyncTaskQueue.asyncPush(false) } }) diff --git a/packages/neuron-wallet/src/controllers/offline-sign.ts b/packages/neuron-wallet/src/controllers/offline-sign.ts index 5899beb4c8..9b308c1427 100644 --- a/packages/neuron-wallet/src/controllers/offline-sign.ts +++ b/packages/neuron-wallet/src/controllers/offline-sign.ts @@ -13,6 +13,7 @@ import NodeService from '../services/node' import { MultisigNotSignedNeedError, OfflineSignFailed } from '../exceptions' import MultisigConfigModel from '../models/multisig-config' import { getMultisigStatus } from '../utils/multisig' +import { generateRPC } from '../utils/ckb-rpc' export default class OfflineSignController { public async exportTransactionAsJSON({ @@ -35,12 +36,12 @@ export default class OfflineSignController { } const tx = Transaction.fromObject(transaction) - const { ckb } = NodeService.getInstance() + const rpc = generateRPC(NodeService.getInstance().nodeUrl) if (context === undefined) { - const rawTx = ckb.rpc.paramsFormatter.toRawTransaction(tx.toSDKRawTransaction()) - const txs = await Promise.all(rawTx.inputs.map(i => ckb.rpc.getTransaction(i.previous_output!.tx_hash))) - context = txs.map(i => ckb.rpc.paramsFormatter.toRawTransaction(i.transaction)) + const rawTx = rpc.paramsFormatter.toRawTransaction(tx.toSDKRawTransaction()) + const txs = await Promise.all(rawTx.inputs.map(i => rpc.getTransaction(i.previous_output!.tx_hash))) + context = txs.map(i => rpc.paramsFormatter.toRawTransaction(i.transaction)) } const signer = OfflineSign.fromJSON({ diff --git a/packages/neuron-wallet/src/controllers/sync-api.ts b/packages/neuron-wallet/src/controllers/sync-api.ts index b21b199386..7c74fc4e45 100644 --- a/packages/neuron-wallet/src/controllers/sync-api.ts +++ b/packages/neuron-wallet/src/controllers/sync-api.ts @@ -58,7 +58,7 @@ export default class SyncApiController { } #getEstimatesByCurrentNode = () => { - const nodeUrl = this.#getCurrentNodeUrl() + const nodeUrl = NodeService.getInstance().nodeUrl return this.#estimates.filter( state => state.nodeUrl === nodeUrl && Date.now() - state.timestamp <= this.#sampleTime ) @@ -103,8 +103,8 @@ export default class SyncApiController { return newSyncState } - #fetchBestKnownBlockInfo = async (): Promise<{ bestKnownBlockNumber: number; bestKnownBlockTimestamp: number }> => { - const nodeUrl = this.#getCurrentNodeUrl() + #fetchBestKnownBlockInfo = async (): Promise<{ bestKnownBlockNumber: number, bestKnownBlockTimestamp: number }> => { + const nodeUrl = NodeService.getInstance().nodeUrl const rpcService = new RpcService(nodeUrl) try { const syncState = await rpcService.getSyncState() @@ -122,17 +122,12 @@ export default class SyncApiController { } } - #getCurrentNodeUrl = () => { - const ckb = NodeService.getInstance().ckb - return ckb.node.url - } - #estimate = async (states: any): Promise => { const indexerTipNumber = parseInt(states.indexerTipNumber) const cacheTipNumber = parseInt(states.cacheTipNumber) const currentTimestamp = Date.now() - const nodeUrl = this.#getCurrentNodeUrl() + const nodeUrl = NodeService.getInstance().nodeUrl const tipHeader = await new RpcService(nodeUrl).getTipHeader() const { bestKnownBlockNumber, bestKnownBlockTimestamp } = await this.#fetchBestKnownBlockInfo() @@ -205,7 +200,7 @@ export default class SyncApiController { return this.#cachedEstimation } - const nodeUrl = this.#getCurrentNodeUrl() + const nodeUrl = NodeService.getInstance().nodeUrl if ( this.#cachedEstimation.nodeUrl !== nodeUrl || @@ -228,7 +223,7 @@ export default class SyncApiController { }) CurrentNetworkIDSubject.pipe(debounceTime(500)).subscribe(() => { - const nodeUrl = this.#getCurrentNodeUrl() + const nodeUrl = NodeService.getInstance().nodeUrl const newSyncState: SyncState = { nodeUrl, timestamp: 0, diff --git a/packages/neuron-wallet/src/controllers/wallets.ts b/packages/neuron-wallet/src/controllers/wallets.ts index 37afcf66d2..913607ca63 100644 --- a/packages/neuron-wallet/src/controllers/wallets.ts +++ b/packages/neuron-wallet/src/controllers/wallets.ts @@ -20,9 +20,10 @@ import { InvalidJSON, InvalidAddress, UsedName, + MainnetAddressRequired, + TestnetAddressRequired } from '../exceptions' import AddressService from '../services/addresses' -import { MainnetAddressRequired, TestnetAddressRequired } from '../exceptions/address' import TransactionSender from '../services/transaction-sender' import Transaction from '../models/chain/transaction' import logger from '../utils/logger' @@ -31,6 +32,8 @@ import HardwareWalletService from '../services/hardware' import { DeviceInfo, ExtendedPublicKey } from '../services/hardware/common' import AddressParser from '../models/address-parser' import MultisigConfigModel from '../models/multisig-config' +import NodeService from '../services/node' +import { generateRPC } from '../utils/ckb-rpc' export default class WalletsController { public async getAll(): Promise[]>> { @@ -116,11 +119,21 @@ export default class WalletsController { ) const walletsService = WalletsService.getInstance() + const rpc = generateRPC(NodeService.getInstance().nodeUrl) + let startBlockNumberInLight: string | undefined = undefined + if (!isImporting) { + try { + startBlockNumberInLight = await rpc.getTipBlockNumber() + } catch (error) { + startBlockNumberInLight = undefined + } + } const wallet = walletsService.create({ id: '', name, extendedKey: accountExtendedPublicKey.serialize(), keystore, + startBlockNumberInLight }) wallet.checkAndGenerateAddresses(isImporting) diff --git a/packages/neuron-wallet/src/database/chain/entities/multisig-config.ts b/packages/neuron-wallet/src/database/chain/entities/multisig-config.ts index d32b193a25..30128092ae 100644 --- a/packages/neuron-wallet/src/database/chain/entities/multisig-config.ts +++ b/packages/neuron-wallet/src/database/chain/entities/multisig-config.ts @@ -53,7 +53,7 @@ export default class MultisigConfig { this.changed('AfterRemove') } - private changed = (event: string) => { + private changed = (event: 'AfterInsert' | 'AfterRemove') => { MultisigConfigDbChangedSubject.getSubject().next(event) } } diff --git a/packages/neuron-wallet/src/database/chain/entities/sync-progress.ts b/packages/neuron-wallet/src/database/chain/entities/sync-progress.ts new file mode 100644 index 0000000000..1d6d2d27dc --- /dev/null +++ b/packages/neuron-wallet/src/database/chain/entities/sync-progress.ts @@ -0,0 +1,62 @@ +import { HexString } from '@ckb-lumos/base' +import { scriptToHash } from '@nervosnetwork/ckb-sdk-utils' +import { Entity, PrimaryColumn, Column } from 'typeorm' + +export enum SyncAddressType { + Default, + Multisig +} + +@Entity({ name: 'sync_progress' }) +export default class SyncProgress { + @PrimaryColumn({ type: 'varchar' }) + hash!: string + + @Column({ type: 'varchar' }) + args!: string + + @Column({ type: 'varchar' }) + codeHash!: string + + @Column({ type: 'varchar' }) + hashType!: CKBComponents.ScriptHashType + + @Column() + scriptType!: CKBRPC.ScriptType + + @Column({ type: 'varchar' }) + walletId!: string + + @Column() + blockStartNumber: number = 0 + + @Column() + blockEndNumber: number = 0 + + @Column({ type: 'varchar' }) + cursor?: HexString + + @Column({ type: 'boolean' }) + delete: boolean = false + + @Column() + addressType: SyncAddressType = SyncAddressType.Default + + static fromObject(obj: { + script: CKBComponents.Script + scriptType: CKBRPC.ScriptType + walletId: string + addressType?: SyncAddressType + }) { + const res = new SyncProgress() + res.hash = scriptToHash(obj.script) + res.args = obj.script.args + res.codeHash = obj.script.codeHash + res.hashType = obj.script.hashType + res.walletId = obj.walletId + res.scriptType = obj.scriptType + res.delete = false + res.addressType = obj.addressType ?? SyncAddressType.Default + return res + } +} diff --git a/packages/neuron-wallet/src/database/chain/index.ts b/packages/neuron-wallet/src/database/chain/index.ts index 3ad38d7498..94a266ed6a 100644 --- a/packages/neuron-wallet/src/database/chain/index.ts +++ b/packages/neuron-wallet/src/database/chain/index.ts @@ -1,21 +1,26 @@ import { getConnection } from 'typeorm' import MultisigOutputChangedSubject from '../../models/subjects/multisig-output-db-changed-subject' +import SyncProgressService from '../../services/sync-progress' import InputEntity from './entities/input' import OutputEntity from './entities/output' import TransactionEntity from './entities/transaction' import SyncInfoEntity from './entities/sync-info' import IndexerTxHashCache from './entities/indexer-tx-hash-cache' import MultisigOutput from './entities/multisig-output' +import SyncProgress from './entities/sync-progress' /* * Clean local sqlite storage */ -export const clean = async () => { - await Promise.all( - [InputEntity, OutputEntity, TransactionEntity, IndexerTxHashCache, MultisigOutput].map(entity => { - return getConnection().getRepository(entity).clear() - }) - ) +export const clean = async (clearAllLightClientData?: boolean) => { + await Promise.all([ + ...[InputEntity, OutputEntity, TransactionEntity, IndexerTxHashCache, MultisigOutput].map(entity => { + return getConnection() + .getRepository(entity) + .clear() + }), + clearAllLightClientData ? getConnection().getRepository(SyncProgress).clear() : SyncProgressService.clearCurrentWalletProgress() + ]) MultisigOutputChangedSubject.getSubject().next('reset') await getConnection().createQueryBuilder().delete().from(SyncInfoEntity).execute() diff --git a/packages/neuron-wallet/src/database/chain/migrations/1676441837373-AddSyncProgress.ts b/packages/neuron-wallet/src/database/chain/migrations/1676441837373-AddSyncProgress.ts new file mode 100644 index 0000000000..c3ba09b3d4 --- /dev/null +++ b/packages/neuron-wallet/src/database/chain/migrations/1676441837373-AddSyncProgress.ts @@ -0,0 +1,28 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class AddSyncProgress1676441837373 implements MigrationInterface { + name = 'AddSyncProgress1676441837373' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + CREATE TABLE "sync_progress" + ( + "hash" varchar PRIMARY KEY NOT NULL, + "args" varchar NOT NULL, + "codeHash" varchar NOT NULL, + "hashType" varchar NOT NULL, + "scriptType" varchar NOT NULL, + "walletId" varchar NOT NULL, + "blockStartNumber" integer NOT NULL, + "blockEndNumber" integer, + "cursor" varchar, + "delete" boolean + ) + `); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP TABLE "sync_progress"`); + } + +} diff --git a/packages/neuron-wallet/src/database/chain/migrations/1681360188494-AddTypeSyncProgress.ts b/packages/neuron-wallet/src/database/chain/migrations/1681360188494-AddTypeSyncProgress.ts new file mode 100644 index 0000000000..70a0bd3ecc --- /dev/null +++ b/packages/neuron-wallet/src/database/chain/migrations/1681360188494-AddTypeSyncProgress.ts @@ -0,0 +1,31 @@ +import { MigrationInterface, QueryRunner, TableColumn, TableIndex } from "typeorm" +import Multisig from "../../../models/multisig" +import { scriptToHash } from "@nervosnetwork/ckb-sdk-utils" +import { SyncAddressType } from "../entities/sync-progress" +import MultisigConfig from "../entities/multisig-config" + +export class AddTypeSyncProgress1681360188494 implements MigrationInterface { + name = 'AddTypeSyncProgress1681360188494' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.addColumn('sync_progress', new TableColumn({ + name: 'addressType', + type: 'INTEGER', + isNullable: false, + default: SyncAddressType.Default, + })) + await queryRunner.createIndex("sync_progress", new TableIndex({ columnNames: ["addressType"] })) + const multisigConfigs = await queryRunner.connection + .getRepository(MultisigConfig) + .createQueryBuilder() + .getMany() + const scriptHashes = multisigConfigs.map(v => scriptToHash(Multisig.getMultisigScript(v.blake160s, v.r, v.m, v.n))) + await queryRunner.query(`UPDATE sync_progress set addressType=1 where hash in (${scriptHashes.map(v => `'${v}'`).join(',')})`) + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.dropColumn('sync_progress', 'addressType') + await queryRunner.dropIndex("sync_progress", new TableIndex({ columnNames: ["addressType"] })) + } + +} diff --git a/packages/neuron-wallet/src/database/chain/ormconfig.ts b/packages/neuron-wallet/src/database/chain/ormconfig.ts index e3910ceff3..b059bd03c1 100644 --- a/packages/neuron-wallet/src/database/chain/ormconfig.ts +++ b/packages/neuron-wallet/src/database/chain/ormconfig.ts @@ -17,6 +17,7 @@ import TxDescription from './entities/tx-description' import AddressDescription from './entities/address-description' import MultisigConfig from './entities/multisig-config' import MultisigOuput from './entities/multisig-output' +import SyncProgress from './entities/sync-progress' import { InitMigration1566959757554 } from './migrations/1566959757554-InitMigration' import { AddTypeAndHasData1567144517514 } from './migrations/1567144517514-AddTypeAndHasData' @@ -48,6 +49,8 @@ import { UpdateAddressDescription1650984779265 } from './migrations/165098477926 import { RemoveDuplicateBlake160s1656930265386 } from './migrations/1656930265386-RemoveDuplicateBlake160s' import { UpdateOutputChequeLockHash1652945662504 } from './migrations/1652945662504-UpdateOutputChequeLockHash' import { RemoveAddressesMultisigConfig1651820157100 } from './migrations/1651820157100-RemoveAddressesMultisigConfig' +import { AddSyncProgress1676441837373 } from './migrations/1676441837373-AddSyncProgress' +import { AddTypeSyncProgress1681360188494 } from './migrations/1681360188494-AddTypeSyncProgress' export const CONNECTION_NOT_FOUND_NAME = 'ConnectionNotFoundError' @@ -80,6 +83,7 @@ const connectOptions = async (genesisBlockHash: string): Promise { MultisigConfigDbChangedSubject.getSubject() .pipe(debounceTime(500)) - .subscribe(async (event: string) => { + .subscribe(async event => { try { if (event === 'AfterInsert') { await MultisigService.saveLiveMultisigOutput() diff --git a/packages/neuron-wallet/src/locales/en.ts b/packages/neuron-wallet/src/locales/en.ts index 9adfe49c03..6392f51a72 100644 --- a/packages/neuron-wallet/src/locales/en.ts +++ b/packages/neuron-wallet/src/locales/en.ts @@ -135,6 +135,7 @@ export default { 'no-match-address-for-sign': 'Not found matched address', 'target-lock-error': 'CKB asset account can only transfer to sepe256k1 or acp address', 'no-exist-ckb-node-data': '{{path}} has no CKB Node config and storage, press ok to synchronize from scratch', + 'light-client-sudt-acp-error': "Light client mode doesn't support sending assets to other's asset account" }, messageBox: { button: { @@ -247,6 +248,7 @@ export default { about: { 'app-version': '{{name}} Version: {{version}}', 'ckb-client-version': 'CKB Client Version: {{version}}', + 'ckb-light-client-version': 'CKB Light Client Version: {{version}}' }, settings: { title: { diff --git a/packages/neuron-wallet/src/locales/zh-tw.ts b/packages/neuron-wallet/src/locales/zh-tw.ts index d03db44bef..f14bf13462 100644 --- a/packages/neuron-wallet/src/locales/zh-tw.ts +++ b/packages/neuron-wallet/src/locales/zh-tw.ts @@ -125,6 +125,7 @@ export default { 'no-match-address-for-sign': '没有找到匹配的地址', 'target-lock-error': 'CKB 資產只能轉賬到 secp256k1 或者 acp 地址', 'no-exist-ckb-node-data': '{{path}} 目錄下沒有找到 CKB Node 配置和數據, 點擊繼續重新同步', + 'light-client-sudt-acp-error': '輕節點模式不支持發送資產給其他用戶的資產賬戶' }, messageBox: { button: { @@ -235,6 +236,7 @@ export default { about: { 'app-version': '{{name}} 版本: {{version}}', 'ckb-client-version': 'CKB 節點版本: {{version}}', + 'ckb-light-client-version': 'CKB 輕節點版本: {{version}}' }, settings: { title: { diff --git a/packages/neuron-wallet/src/locales/zh.ts b/packages/neuron-wallet/src/locales/zh.ts index a9b432473b..3712f7a416 100644 --- a/packages/neuron-wallet/src/locales/zh.ts +++ b/packages/neuron-wallet/src/locales/zh.ts @@ -126,6 +126,7 @@ export default { 'no-match-address-for-sign': '没有找到匹配的地址', 'target-lock-error': 'CKB 资产只能转账到 secp256k1 或者 acp 地址', 'no-exist-ckb-node-data': '{{path}} 目录下没有找到 CKB Node 配置和数据, 点击继续重新同步', + 'light-client-sudt-acp-error': '轻节点模式不支持发送资产给其他用户的资产账户' }, messageBox: { button: { @@ -236,6 +237,7 @@ export default { about: { 'app-version': '{{name}} 版本: {{version}}', 'ckb-client-version': 'CKB 节点版本: {{version}}', + 'ckb-light-client-version': 'CKB 轻节点版本: {{version}}' }, settings: { title: { diff --git a/packages/neuron-wallet/src/models/chain/live-cell.ts b/packages/neuron-wallet/src/models/chain/live-cell.ts index e72fa4b57b..8d8cd75a80 100644 --- a/packages/neuron-wallet/src/models/chain/live-cell.ts +++ b/packages/neuron-wallet/src/models/chain/live-cell.ts @@ -1,6 +1,6 @@ import Script, { ScriptHashType } from './script' import OutPoint from './out-point' -import { LumosCell } from '../../block-sync-renderer/sync/indexer-connector' +import { LumosCell } from '../../block-sync-renderer/sync/connector' const LUMOS_HASH_TYPE_MAP: Record = { type: ScriptHashType.Type, diff --git a/packages/neuron-wallet/src/models/network.ts b/packages/neuron-wallet/src/models/network.ts index 739be27e9a..dc37a4cf8d 100644 --- a/packages/neuron-wallet/src/models/network.ts +++ b/packages/neuron-wallet/src/models/network.ts @@ -1,9 +1,11 @@ export enum NetworkType { Default, // Preset mainnet node Normal, + Light } export const MAINNET_GENESIS_HASH = '0x92b197aa1fba0f63633922c61c92375c9c074a93e85963554f5499fe1450d0e5' +export const TESTNET_GENESIS_HASH = '0x10639e0895502b5688a6be8cf69460d76541bfa4821629d86d62ba0aae3f9606' export const EMPTY_GENESIS_HASH = '0x' export type ChainType = 'ckb' | 'ckb_testnet' | 'ckb_dev' diff --git a/packages/neuron-wallet/src/models/subjects/multisig-config-db-changed-subject.ts b/packages/neuron-wallet/src/models/subjects/multisig-config-db-changed-subject.ts index 70dee07b78..fc8358a5e8 100644 --- a/packages/neuron-wallet/src/models/subjects/multisig-config-db-changed-subject.ts +++ b/packages/neuron-wallet/src/models/subjects/multisig-config-db-changed-subject.ts @@ -2,7 +2,7 @@ import { ReplaySubject } from 'rxjs' // subscribe this Subject to monitor any transaction table changes export class MultisigConfigDbChangedSubject { - private static subject = new ReplaySubject(100) + private static subject = new ReplaySubject<'AfterInsert' | 'AfterRemove'>(100) public static getSubject() { return MultisigConfigDbChangedSubject.subject diff --git a/packages/neuron-wallet/src/models/system-script-info.ts b/packages/neuron-wallet/src/models/system-script-info.ts index d7241abb8f..b1a282f02a 100644 --- a/packages/neuron-wallet/src/models/system-script-info.ts +++ b/packages/neuron-wallet/src/models/system-script-info.ts @@ -101,7 +101,7 @@ export default class SystemScriptInfo { private async loadInfos(url: string): Promise { const rpcService = new RpcService(url) - const genesisBlock = (await rpcService.getBlockByNumber('0'))! + const genesisBlock = (await rpcService.getGenesisBlock())! const genesisBlockHash = genesisBlock.header.hash // set secp info diff --git a/packages/neuron-wallet/src/services/anyone-can-pay.ts b/packages/neuron-wallet/src/services/anyone-can-pay.ts index 5d68a50097..4046c3f92e 100644 --- a/packages/neuron-wallet/src/services/anyone-can-pay.ts +++ b/packages/neuron-wallet/src/services/anyone-can-pay.ts @@ -6,8 +6,12 @@ import Output from '../models/chain/output' import LiveCell from '../models/chain/live-cell' import Transaction from '../models/chain/transaction' import AssetAccountEntity from '../database/chain/entities/asset-account' -import { TargetLockError, TargetOutputNotFoundError } from '../exceptions' -import { AcpSendSameAccountError } from '../exceptions' +import { + LightClientNotSupportSendToACPError, + TargetLockError, + TargetOutputNotFoundError, + AcpSendSameAccountError +} from '../exceptions' import Script from '../models/chain/script' import OutPoint from '../models/chain/out-point' import LiveCellService from './live-cell-service' @@ -15,6 +19,8 @@ import WalletService from './wallets' import SystemScriptInfo from '../models/system-script-info' import CellsService from './cells' import { MIN_SUDT_CAPACITY } from '../utils/const' +import NetworksService from './networks' +import { NetworkType } from '../models/network' export default class AnyoneCanPayService { public static async generateAnyoneCanPayTx( @@ -90,6 +96,9 @@ export default class AnyoneCanPayService { ) if (new AssetAccountInfo().isAnyoneCanPayScript(lockScript)) { if (!targetOutputLiveCell) { + if (NetworksService.getInstance().getCurrent().type === NetworkType.Light) { + throw new LightClientNotSupportSendToACPError() + } throw new TargetOutputNotFoundError() } return Output.fromObject({ diff --git a/packages/neuron-wallet/src/services/ckb-runner.ts b/packages/neuron-wallet/src/services/ckb-runner.ts index f413129df3..cb1c40581c 100644 --- a/packages/neuron-wallet/src/services/ckb-runner.ts +++ b/packages/neuron-wallet/src/services/ckb-runner.ts @@ -1,12 +1,13 @@ import env from '../env' import path from 'path' import fs from 'fs' -import { ChildProcess, spawn } from 'child_process' +import { ChildProcess, StdioNull, StdioPipe, spawn } from 'child_process' import process from 'process' import logger from '../utils/logger' import SettingsService from './settings' import MigrateSubject from '../models/subjects/migrate-subject' import IndexerService from './indexer' +import { resetSyncTaskQueue } from '../block-sync-renderer' const platform = (): string => { switch (process.platform) { @@ -90,36 +91,33 @@ export const startCkbNode = async () => { logger.info('CKB:\tstarting node...') const options = ['run', '-C', SettingsService.getInstance().ckbDataPath, '--indexer'] + const stdio: (StdioNull | StdioPipe)[] = ['ignore', 'ignore', 'pipe'] if (app.isPackaged && process.env.CKB_NODE_ASSUME_VALID_TARGET) { options.push('--assume-valid-target', process.env.CKB_NODE_ASSUME_VALID_TARGET) + stdio[1] = 'pipe' } - ckb = spawn(ckbBinary(), options, { stdio: ['ignore', 'pipe', 'pipe'] }) + ckb = spawn(ckbBinary(), options, { stdio }) - ckb.stderr && - ckb.stderr.on('data', data => { - const dataString: string = data.toString() - logger.error('CKB:\trun fail:', dataString) - ckb = null - if (dataString.includes('CKB wants to migrate the data into new format')) { - MigrateSubject.next({ type: 'need-migrate' }) - } - }) - if (app.isPackaged && process.env.CKB_NODE_ASSUME_VALID_TARGET) { - ckb.stdout && - ckb.stdout.on('data', data => { - const dataString: string = data.toString() - if ( - dataString.includes( - `can't find assume valid target temporarily, hash: Byte32(${process.env.CKB_NODE_ASSUME_VALID_TARGET})` - ) - ) { - isLookingValidTarget = true - lastLogTime = Date.now() - } else if (lastLogTime && Date.now() - lastLogTime > 10000) { - isLookingValidTarget = false - } - }) - } + ckb.stderr?.on('data', data => { + const dataString: string = data.toString() + logger.error('CKB:\trun fail:', dataString) + if (dataString.includes('CKB wants to migrate the data into new format')) { + MigrateSubject.next({ type: 'need-migrate' }) + } + }) + ckb.stdout?.on('data', data => { + const dataString: string = data.toString() + if ( + dataString.includes( + `can't find assume valid target temporarily, hash: Byte32(${process.env.CKB_NODE_ASSUME_VALID_TARGET})` + ) + ) { + isLookingValidTarget = true + lastLogTime = Date.now() + } else if (lastLogTime && Date.now() - lastLogTime > 10000) { + isLookingValidTarget = false + } + }) ckb.on('error', error => { logger.error('CKB:\trun fail:', error) @@ -141,7 +139,7 @@ export const stopCkbNode = () => { if (ckb) { logger.info('CKB:\tkilling node') ckb.once('close', () => resolve()) - ckb.kill('SIGKILL') + ckb.kill() ckb = null } else { resolve() @@ -156,6 +154,7 @@ export const clearCkbNodeCache = async () => { await stopCkbNode() fs.rmSync(SettingsService.getInstance().ckbDataPath, { recursive: true, force: true }) await startCkbNode() + resetSyncTaskQueue.asyncPush(true) } export function migrateCkbData() { diff --git a/packages/neuron-wallet/src/services/hardware/ledger.ts b/packages/neuron-wallet/src/services/hardware/ledger.ts index b12b554a6d..a1b8de2793 100644 --- a/packages/neuron-wallet/src/services/hardware/ledger.ts +++ b/packages/neuron-wallet/src/services/hardware/ledger.ts @@ -12,6 +12,7 @@ import Address, { AddressType } from '../../models/keys/address' import HexUtils from '../../utils/hex' import logger from '../../utils/logger' import NetworksService from '../../services/networks' +import { generateRPC } from '../../utils/ckb-rpc' export default class Ledger extends Hardware { private ledgerCKB: LedgerCKB | null = null @@ -48,19 +49,13 @@ export default class Ledger extends Hardware { } } - public async signTransaction( - _: string, - tx: Transaction, - witnesses: string[], - path: string, - context?: RPC.RawTransaction[] - ) { - const { ckb } = NodeService.getInstance() - const rawTx = ckb.rpc.paramsFormatter.toRawTransaction(tx.toSDKRawTransaction()) + public async signTransaction (_: string, tx: Transaction, witnesses: string[], path: string, context?: RPC.RawTransaction[]) { + const rpc = generateRPC(NodeService.getInstance().nodeUrl) + const rawTx = rpc.paramsFormatter.toRawTransaction(tx.toSDKRawTransaction()) if (!context) { - const txs = await Promise.all(rawTx.inputs.map(i => ckb.rpc.getTransaction(i.previous_output!.tx_hash))) - context = txs.map(i => ckb.rpc.paramsFormatter.toRawTransaction(i.transaction)) + const txs = await Promise.all(rawTx.inputs.map(i => rpc.getTransaction(i.previous_output!.tx_hash))) + context = txs.map(i => rpc.paramsFormatter.toRawTransaction(i.transaction)) } const signature = await this.ledgerCKB!.signTransaction( diff --git a/packages/neuron-wallet/src/services/indexer.ts b/packages/neuron-wallet/src/services/indexer.ts index 0c50710634..f6e536bcc0 100644 --- a/packages/neuron-wallet/src/services/indexer.ts +++ b/packages/neuron-wallet/src/services/indexer.ts @@ -6,6 +6,7 @@ import { clean as cleanChain } from '../database/chain' import SettingsService from './settings' import startMonitor, { stopMonitor } from './monitor' import NodeService from './node' +import { resetSyncTaskQueue } from '../block-sync-renderer' export default class IndexerService { private constructor() {} @@ -19,19 +20,15 @@ export default class IndexerService { } static clearCache = async (clearIndexerFolder = false) => { - if (!NodeService.getInstance().isCkbNodeExternal) { - await stopMonitor('ckb') - } await cleanChain() - if (clearIndexerFolder) { + if (!NodeService.getInstance().isCkbNodeExternal && clearIndexerFolder) { + await stopMonitor('ckb') IndexerService.getInstance().clearData() await new SyncedBlockNumber().setNextBlock(BigInt(0)) + await startMonitor('ckb', true) } - - if (!NodeService.getInstance().isCkbNodeExternal) { - await startMonitor('ckb') - } + resetSyncTaskQueue.asyncPush(true) } static cleanOldIndexerData() { diff --git a/packages/neuron-wallet/src/services/light-runner.ts b/packages/neuron-wallet/src/services/light-runner.ts new file mode 100644 index 0000000000..2db887e093 --- /dev/null +++ b/packages/neuron-wallet/src/services/light-runner.ts @@ -0,0 +1,173 @@ +import path from 'path' +import fs from 'fs' +import { ChildProcess, spawn } from 'child_process' +import env from '../env' +import logger from '../utils/logger' +import SettingsService from '../services/settings' +import { clean } from '../database/chain' +import { resetSyncTaskQueue } from '../block-sync-renderer' + +const { app } = env + +export enum NetworkType { + Light, + Full +} + +abstract class NodeRunner { + protected constructor() {} + protected abstract networkType: NetworkType + protected runnerProcess: ChildProcess | undefined + protected static instance: NodeRunner | undefined + protected abstract binaryName: string + static getInstance(): NodeRunner { + throw new Error('should be called by concrete class') + } + + abstract start(): Promise + + protected get binary() { + const appPath = app.isPackaged + ? path.join(path.dirname(app.getAppPath()), '..', './bin') + : path.join(__dirname, '../../bin') + const binary = app.isPackaged + ? path.resolve(appPath, `./${this.binaryName}`) + : path.resolve(appPath, `./${this.platform()}`, `./${this.binaryName}`) + return this.platform() === 'win' ? binary + '.exe' : binary + } + + platform(): string { + switch (process.platform) { + case 'win32': + return 'win' + case 'linux': + return 'linux' + case 'darwin': + return 'mac' + default: + return '' + } + } + + async stop() { + return new Promise(resolve => { + if (this.runnerProcess) { + logger.info('Runner:\tkilling node') + this.runnerProcess.once('close', () => resolve()) + this.runnerProcess.kill() + this.runnerProcess = undefined + } else { + resolve() + } + }) + } +} + +export class CKBLightRunner extends NodeRunner { + protected networkType: NetworkType = NetworkType.Light + protected binaryName: string = 'ckb-light-client' + protected logStream?: fs.WriteStream + + static getInstance(): CKBLightRunner { + if (!CKBLightRunner.instance) { + CKBLightRunner.instance = new CKBLightRunner() + } + return CKBLightRunner.instance as CKBLightRunner + } + + private get templateConfigFile() { + const appPath = app.isPackaged + ? path.join(path.dirname(app.getAppPath()), '..', './light') + : path.join(__dirname, '../../light') + return path.resolve(appPath, './ckb_light.toml') + } + + private get configFile() { + return path.resolve(SettingsService.getInstance().testnetLightDataPath, './ckb_light.toml') + } + + initConfig() { + if (fs.existsSync(this.configFile)) { + logger.info(`CKB Light Runner:\tconfig has init, skip init...`) + return + } + const values = fs + .readFileSync(this.templateConfigFile) + .toString() + .split('\n') + let isStorePath = false + let isNetworkPath = false + const newValues = values.map(v => { + if (isStorePath) { + isStorePath = false + return `path = "${path.join(SettingsService.getInstance().testnetLightDataPath, './store')}"` + } + if (isNetworkPath) { + isNetworkPath = false + return `path = "${path.join(SettingsService.getInstance().testnetLightDataPath, './network')}"` + } + if (v === '[store]') { + isStorePath = true + } else if (v === '[network]') { + isNetworkPath = true + } + return v + }) + if (!fs.existsSync(SettingsService.getInstance().testnetLightDataPath)) { + fs.mkdirSync(SettingsService.getInstance().testnetLightDataPath, { recursive: true }) + } + fs.writeFileSync(this.configFile, newValues.join('\n')) + } + + async start() { + if (this.runnerProcess) { + logger.info(`CKB Light Runner:\tckb light is not closed, close it before start...`) + await this.stop() + } + this.initConfig() + + const options = ['run', '--config-file', this.configFile] + const runnerProcess = spawn(this.binary, options, { + stdio: ['ignore', 'pipe', 'pipe'], + env: { RUST_LOG: 'info', ckb_light_client: 'info' } + }) + this.runnerProcess = runnerProcess + + if (!this.logStream) { + this.logStream = fs.createWriteStream(this.logPath) + } + + runnerProcess.stderr && + runnerProcess.stderr.on('data', data => { + const dataString: string = data.toString() + logger.error('CKB Light Runner:\trun fail:', dataString) + this.logStream?.write(data) + }) + + runnerProcess.stdout && + runnerProcess.stdout.on('data', data => { + this.logStream?.write(data) + }) + runnerProcess.on('error', error => { + logger.error('CKB Light Runner:\trun fail:', error) + this.runnerProcess = undefined + }) + + runnerProcess.on('close', () => { + logger.info('CKB Light Runner:\tprocess closed') + this.runnerProcess = undefined + }) + } + + get logPath() { + return path.join(logger.transports.file.getFile().path, '..', 'light_client_run.log') + } + + async clearNodeCache(): Promise { + await this.stop() + fs.rmSync(SettingsService.getInstance().testnetLightDataPath, { recursive: true, force: true }) + await clean(true) + await this.start() + resetSyncTaskQueue.asyncPush(true) + } +} diff --git a/packages/neuron-wallet/src/services/live-cell-service.ts b/packages/neuron-wallet/src/services/live-cell-service.ts index 146eb256c0..8c6694e935 100644 --- a/packages/neuron-wallet/src/services/live-cell-service.ts +++ b/packages/neuron-wallet/src/services/live-cell-service.ts @@ -1,7 +1,7 @@ import Script from '../models/chain/script' import LiveCell from '../models/chain/live-cell' import { queryIndexer } from '../block-sync-renderer/index' -import { LumosCellQuery, LumosCell } from '../block-sync-renderer/sync/indexer-connector' +import { LumosCell, LumosCellQuery } from '../block-sync-renderer/sync/connector' export default class LiveCellService { private static instance: LiveCellService diff --git a/packages/neuron-wallet/src/services/monitor/ckb-monitor.ts b/packages/neuron-wallet/src/services/monitor/ckb-monitor.ts index 395f0e246d..eba85c88e9 100644 --- a/packages/neuron-wallet/src/services/monitor/ckb-monitor.ts +++ b/packages/neuron-wallet/src/services/monitor/ckb-monitor.ts @@ -1,4 +1,5 @@ import { stopCkbNode } from '../../services/ckb-runner' +import { CKBLightRunner } from '../../services/light-runner' import NodeService from '../node' import BaseMonitor from './base' @@ -12,7 +13,10 @@ export default class CkbMonitor extends BaseMonitor { } async stop(): Promise { - await stopCkbNode() + await Promise.all([ + stopCkbNode(), + CKBLightRunner.getInstance().stop() + ]) } name: string = 'ckb' diff --git a/packages/neuron-wallet/src/services/multisig.ts b/packages/neuron-wallet/src/services/multisig.ts index 5aa129fadb..e218ac172d 100644 --- a/packages/neuron-wallet/src/services/multisig.ts +++ b/packages/neuron-wallet/src/services/multisig.ts @@ -9,6 +9,9 @@ import Transaction from '../models/chain/transaction' import { OutputStatus } from '../models/chain/output' import NetworksService from './networks' import Multisig from '../models/multisig' +import SyncProgress, { SyncAddressType } from '../database/chain/entities/sync-progress' +import { NetworkType } from '../models/network' +import WalletService from './wallets' const max64Int = '0x' + 'f'.repeat(16) export default class MultisigService { @@ -96,7 +99,7 @@ export default class MultisigService { while (currentMultisigConfigs.length) { const res = await rpcBatchRequest( network.remote, - currentMultisigConfigs.map(v => { + currentMultisigConfigs.map((v) => { const script = Multisig.getMultisigScript(v.blake160s, v.r, v.m, v.n) return { method: 'get_cells', @@ -155,7 +158,7 @@ export default class MultisigService { while (currentMultisigConfigs.length) { const res = await rpcBatchRequest( network.remote, - currentMultisigConfigs.map(v => { + currentMultisigConfigs.map((v) => { const script = Multisig.getMultisigScript(v.blake160s, v.r, v.m, v.n) return { method: 'get_transactions', @@ -201,13 +204,13 @@ export default class MultisigService { const network = await NetworksService.getInstance().getCurrent() const txList = await rpcBatchRequest( network.remote, - [...multisigOutputTxHashList].map(v => ({ + [...multisigOutputTxHashList].map((v) => ({ method: 'get_transaction', params: [v], })) ) const removeOutputTxHashList: string[] = [] - txList.forEach(v => { + txList.forEach((v) => { if (!v.error && v?.result?.transaction?.inputs?.length) { v?.result?.transaction?.inputs?.forEach((input: any) => { removeOutputTxHashList.push(input.previous_output.tx_hash + input.previous_output.index) @@ -228,7 +231,7 @@ export default class MultisigService { static async deleteRemovedMultisigOutput() { const multisigConfigs = await getConnection().getRepository(MultisigConfig).createQueryBuilder().getMany() - const multisigLockHashList = multisigConfigs.map(v => + const multisigLockHashList = multisigConfigs.map((v) => scriptToHash(Multisig.getMultisigScript(v.blake160s, v.r, v.m, v.n)) ) await getConnection() @@ -242,19 +245,50 @@ export default class MultisigService { MultisigOutputChangedSubject.getSubject().next('delete') } - static async syncMultisigOutput(lastestBlockNumber: string) { - try { - const multisigConfigs = await getConnection().getRepository(MultisigConfig).createQueryBuilder().getMany() - await MultisigService.saveLiveMultisigOutput() - await MultisigService.deleteDeadMultisigOutput(multisigConfigs) + static async saveMultisigSyncBlockNumber(multisigConfigs: MultisigConfig[], lastestBlockNumber: string) { + const network = await NetworksService.getInstance().getCurrent() + if (network.type === NetworkType.Light) { + const multisigScriptHashList = multisigConfigs.map((v) => + scriptToHash(Multisig.getMultisigScript(v.blake160s, v.r, v.m, v.n)) + ) + const syncBlockNumbers = await getConnection() + .getRepository(SyncProgress) + .createQueryBuilder() + .where({ hash: In(multisigScriptHashList) }) + .getMany() + const syncBlockNumbersMap: Record = syncBlockNumbers.reduce( + (pre, cur) => ({ ...pre, [cur.hash]: cur.blockStartNumber }), + {} + ) await getConnection() .getRepository(MultisigConfig) .save( - multisigConfigs.map(v => ({ + multisigConfigs.map((v) => { + const blockNumber = + syncBlockNumbersMap[scriptToHash(Multisig.getMultisigScript(v.blake160s, v.r, v.m, v.n))] + v.lastestBlockNumber = `0x${BigInt(blockNumber).toString(16)}` + return v + }) + ) + } else { + await getConnection() + .getRepository(MultisigConfig) + .save( + multisigConfigs.map((v) => ({ ...v, lastestBlockNumber, })) ) + } + } + + static async syncMultisigOutput(lastestBlockNumber: string) { + try { + const multisigConfigs = await getConnection().getRepository(MultisigConfig).createQueryBuilder().getMany() + await MultisigService.saveLiveMultisigOutput() + await MultisigService.deleteDeadMultisigOutput(multisigConfigs) + await MultisigService.saveMultisigSyncBlockNumber(multisigConfigs, lastestBlockNumber) + MultisigOutputChangedSubject.getSubject().next('update') } catch (error) { // ignore error, if lastestBlockNumber not update, it will try next time } @@ -262,7 +296,7 @@ export default class MultisigService { static async saveSentMultisigOutput(transaction: Transaction) { const inputsOutpointList = transaction.inputs.map( - input => `${input.previousOutput?.txHash}0x${(+input.previousOutput!.index)?.toString(16)}` + (input) => `${input.previousOutput?.txHash}0x${(+input.previousOutput!.index)?.toString(16)}` ) const multisigOutputs = transaction.outputs.map((output, idx) => { const entity = new MultisigOutput() @@ -290,4 +324,21 @@ export default class MultisigService { .execute() MultisigOutputChangedSubject.getSubject().next('update') } + + static async getMultisigConfigForLight() { + const currentWallet = WalletService.getInstance().getCurrent() + const multisigConfigs = await getConnection() + .getRepository(MultisigConfig) + .createQueryBuilder() + .where({ + walletId: currentWallet?.id + }) + .getMany() + return multisigConfigs.map((v) => ({ + walletId: v.walletId, + script: Multisig.getMultisigScript(v.blake160s, v.r, v.m, v.n), + addressType: SyncAddressType.Multisig, + scriptType: 'lock' as CKBRPC.ScriptType + })) + } } diff --git a/packages/neuron-wallet/src/services/networks.ts b/packages/neuron-wallet/src/services/networks.ts index 888b6d67cf..32717d7fe4 100644 --- a/packages/neuron-wallet/src/services/networks.ts +++ b/packages/neuron-wallet/src/services/networks.ts @@ -1,4 +1,3 @@ -import CKB from '@nervosnetwork/ckb-sdk-core' import { v4 as uuid } from 'uuid' import { DefaultNetworkUnremovable } from '../exceptions/network' @@ -6,9 +5,10 @@ import Store from '../models/store' import { Validate, Required } from '../utils/validators' import { UsedName, NetworkNotFound, InvalidFormat } from '../exceptions' -import { MAINNET_GENESIS_HASH, EMPTY_GENESIS_HASH, NetworkType, Network } from '../models/network' +import { MAINNET_GENESIS_HASH, EMPTY_GENESIS_HASH, NetworkType, Network, TESTNET_GENESIS_HASH } from '../models/network' import CommonUtils from '../utils/common' -import { BUNDLED_CKB_URL } from '../utils/const' +import { BUNDLED_CKB_URL, BUNDLED_LIGHT_CKB_URL, LIGHT_CLIENT_TESTNET } from '../utils/const' +import { generateRPC } from '../utils/ckb-rpc' const presetNetworks: { selected: string; networks: Network[] } = { selected: 'mainnet', @@ -24,9 +24,21 @@ const presetNetworks: { selected: string; networks: Network[] } = { ], } +const lightClientNetwork: Network[] = [ + { + id: 'light_client_testnet', + name: 'Light Client Testnet', + remote: BUNDLED_LIGHT_CKB_URL, + genesisHash: TESTNET_GENESIS_HASH, + type: NetworkType.Light, + chain: LIGHT_CLIENT_TESTNET + } +] + enum NetworksKey { List = 'networks', Current = 'selected', + AddedLightNetwork = 'AddedLightNetwork' } export default class NetworksService extends Store { @@ -44,6 +56,12 @@ export default class NetworksService extends Store { const currentNetwork = this.getCurrent() this.update(currentNetwork.id, {}) // Update to trigger chain/genesis hash refresh + const addLight = this.readSync(NetworksKey.AddedLightNetwork) + if (!addLight) { + const networks = this.readSync(NetworksKey.List) || presetNetworks.networks + this.updateAll([...networks, ...lightClientNetwork]) + this.writeSync(NetworksKey.AddedLightNetwork, true) + } } public getAll = () => { @@ -167,10 +185,10 @@ export default class NetworksService extends Store { // Refresh a network's genesis and chain info private async refreshChainInfo(network: Network): Promise { - const ckb = new CKB(network.remote) + const rpc = generateRPC(network.remote) - const genesisHash = await ckb.rpc.getBlockHash('0x0').catch(() => EMPTY_GENESIS_HASH) - const chain = await ckb.rpc + const genesisHash = await rpc.getGenesisBlockHash().catch(() => EMPTY_GENESIS_HASH) + const chain = await rpc .getBlockchainInfo() .then(info => info.chain) .catch(() => '') diff --git a/packages/neuron-wallet/src/services/node.ts b/packages/neuron-wallet/src/services/node.ts index 4c6dc3b3b3..b8e38df6d3 100644 --- a/packages/neuron-wallet/src/services/node.ts +++ b/packages/neuron-wallet/src/services/node.ts @@ -1,25 +1,25 @@ import fs from 'fs' import path from 'path' -import https from 'https' -import http from 'http' import { app as electronApp, dialog, shell } from 'electron' import { t } from 'i18next' -import CKB from '@nervosnetwork/ckb-sdk-core' import { interval, BehaviorSubject, merge } from 'rxjs' import { distinctUntilChanged, sampleTime, flatMap, delay, retry, debounceTime } from 'rxjs/operators' import env from '../env' import { ShouldBeTypeOf } from '../exceptions' import { ConnectionStatusSubject } from '../models/subjects/node' import { CurrentNetworkIDSubject } from '../models/subjects/networks' +import { NetworkType } from '../models/network' import NetworksService from '../services/networks' import RpcService from '../services/rpc-service' -import { startCkbNode } from '../services/ckb-runner' -import HexUtils from '../utils/hex' -import { BUNDLED_CKB_URL, START_WITHOUT_INDEXER } from '../utils/const' +import { startCkbNode, stopCkbNode } from '../services/ckb-runner' +import { BUNDLED_CKB_URL, START_WITHOUT_INDEXER, BUNDLED_LIGHT_CKB_URL } from '../utils/const' import logger from '../utils/logger' import redistCheck from '../utils/redist-check' import { rpcRequest } from '../utils/rpc-request' +import { generateRPC } from '../utils/ckb-rpc' +import HexUtils from '..//utils/hex' import startMonitor from './monitor' +import { CKBLightRunner } from './light-runner' class NodeService { private static instance: NodeService @@ -39,10 +39,9 @@ class NodeService { private _tipBlockNumber: string = '0' private startedBundledNode: boolean = false private _isCkbNodeExternal: boolean = false + #nodeUrl: string = '' - public ckb: CKB = new CKB('') - - constructor() { + private constructor() { this.start() this.syncConnectionStatus() CurrentNetworkIDSubject.subscribe(async ({ currentNetworkID }) => { @@ -53,6 +52,10 @@ class NodeService { }) } + get nodeUrl() { + return this.#nodeUrl + } + public get tipBlockNumber(): string { return this._tipBlockNumber } @@ -63,9 +66,9 @@ class NodeService { merge(periodSync, realtimeSync) .pipe(debounceTime(500)) .subscribe(connected => { - const isBundledNode = this.ckb.node.url === BUNDLED_CKB_URL + const isBundledNode = this.#nodeUrl === BUNDLED_CKB_URL ConnectionStatusSubject.next({ - url: this.ckb.node.url, + url: this.#nodeUrl, connected, isBundledNode, startedBundledNode: isBundledNode ? this.startedBundledNode : false, @@ -73,23 +76,16 @@ class NodeService { }) } - public setNetwork = (url: string) => { + private setNetwork = (url: string) => { if (typeof url !== 'string') { throw new ShouldBeTypeOf('URL', 'string') } if (!url.startsWith('http')) { throw new Error('Protocol of url should be specified') } - if (url.startsWith('https')) { - const httpsAgent = new https.Agent({ keepAlive: true }) - this.ckb.setNode({ url, httpsAgent }) - } else { - const httpAgent = new http.Agent({ keepAlive: true }) - this.ckb.setNode({ url, httpAgent }) - } + this.#nodeUrl = url this.tipNumberSubject.next('0') this.connectionStatusSubject.next(false) - return this.ckb } public start = () => { @@ -104,7 +100,7 @@ class NodeService { .pipe( delay(this.delayTime), flatMap(() => { - return this.ckb.rpc + return generateRPC(this.#nodeUrl) .getTipBlockNumber() .then(tipNumber => { this.connectionStatusSubject.next(true) @@ -147,18 +143,21 @@ class NodeService { } else { logger.info('CKB:\texternal RPC on default uri detected, skip starting bundled CKB node.') this._isCkbNodeExternal = true - await this.verifyNodeVersion() - await this.verifyStartWithIndexer() + const network = NetworksService.getInstance().getCurrent() + if (network.type !== NetworkType.Light) { + await this.verifyNodeVersion() + await this.verifyStartWithIndexer() + } } } public async isDefaultCKBNeedRestart() { - let network = NetworksService.getInstance().getCurrent() - if (network.remote !== BUNDLED_CKB_URL) { + const network = NetworksService.getInstance().getCurrent() + if (network.remote !== BUNDLED_CKB_URL && network.remote !== BUNDLED_LIGHT_CKB_URL) { return false } try { - await new RpcService(network.remote).getChain() + await new RpcService(network.remote).localNodeInfo() return false } catch (err) { return true @@ -167,7 +166,14 @@ class NodeService { public async startNode() { try { - await startCkbNode() + const network = NetworksService.getInstance().getCurrent() + if (network.type === NetworkType.Light) { + await stopCkbNode() + await CKBLightRunner.getInstance().start() + } else { + await CKBLightRunner.getInstance().stop() + await startCkbNode() + } this.startedBundledNode = true } catch (error) { this.startedBundledNode = false @@ -215,7 +221,7 @@ class NodeService { private async verifyNodeVersion() { const network = NetworksService.getInstance().getCurrent() - const localNodeInfo = await new RpcService(network.remote).getLocalNodeInfo() + const localNodeInfo = await new RpcService(network.remote).localNodeInfo() const internalNodeVersion = this.getInternalNodeVersion() const [internalMajor, internalMinor] = internalNodeVersion?.split('.') ?? [] const [externalMajor, externalMinor] = localNodeInfo.version?.split('.') ?? [] diff --git a/packages/neuron-wallet/src/services/rpc-service.ts b/packages/neuron-wallet/src/services/rpc-service.ts index 09d2e2b39d..b4769e59c6 100644 --- a/packages/neuron-wallet/src/services/rpc-service.ts +++ b/packages/neuron-wallet/src/services/rpc-service.ts @@ -1,67 +1,29 @@ -import CKB from '@nervosnetwork/ckb-sdk-core' -import { generateCKB } from '../services/sdk-core' - -import HexUtils from '../utils/hex' import CommonUtils from '../utils/common' import Block from '../models/chain/block' import BlockHeader from '../models/chain/block-header' import TransactionWithStatus from '../models/chain/transaction-with-status' -import OutPoint from '../models/chain/out-point' -import CellWithStatus from '../models/chain/cell-with-status' import logger from '../utils/logger' - +import { generateRPC } from '../utils/ckb-rpc' export default class RpcService { private retryTime: number private retryInterval: number - private ckb: CKB + private rpc: ReturnType constructor(url: string, retryTime: number = 3, retryInterval: number = 100) { this.retryTime = retryTime this.retryInterval = retryInterval - this.ckb = generateCKB(url) - } - - public async getRangeBlocks(blockNumbers: string[]): Promise { - const blocks: Block[] = await Promise.all( - blockNumbers.map(async num => { - return (await this.retryGetBlock(num))! - }) - ) - - return blocks - } - - public async getRangeBlockHeaders(blockNumbers: string[]): Promise { - const headers: BlockHeader[] = await Promise.all( - blockNumbers.map(async num => { - return (await this.retryGetBlockHeader(num))! - }) - ) - - return headers + this.rpc = generateRPC(url) } public async getTipBlockNumber(): Promise { - return this.ckb.rpc.getTipBlockNumber() + return this.rpc.getTipBlockNumber() } public async getTipHeader(): Promise { - const result = await this.ckb.rpc.getTipHeader() + const result = await this.rpc.getTipHeader() return BlockHeader.fromSDK(result) } - public async retryGetBlock(num: string): Promise { - return this.retry(async () => { - return await this.getBlockByNumber(num) - }) - } - - public async retryGetBlockHeader(num: string): Promise { - return this.retry(async () => { - return this.getBlockHeaderByNumber(num) - }) - } - /** * TODO: rejected tx should be handled * { @@ -70,7 +32,7 @@ export default class RpcService { * } */ public async getTransaction(hash: string): Promise { - const result = await this.ckb.rpc.getTransaction(hash) + const result = await this.rpc.getTransaction(hash) if (result?.transaction) { return TransactionWithStatus.fromSDK(result) } @@ -80,66 +42,39 @@ export default class RpcService { return undefined } - public async getLiveCell(outPoint: OutPoint, withData: boolean = false): Promise { - const result = await this.ckb.rpc.getLiveCell(outPoint.toSDK(), withData) - return CellWithStatus.fromSDK(result) - } - public async getHeader(hash: string): Promise { - const result = await this.ckb.rpc.getHeader(hash) - if (result) { - return BlockHeader.fromSDK(result) - } - return undefined - } - - public async getHeaderByNumber(num: string): Promise { - const result = await this.ckb.rpc.getHeaderByNumber(HexUtils.toHex(num)) + const result = await this.rpc.getHeader(hash) if (result) { return BlockHeader.fromSDK(result) } return undefined } - public async getBlockByNumber(num: string): Promise { - const block = await this.ckb.rpc.getBlockByNumber(HexUtils.toHex(num)) + public async getGenesisBlock(): Promise { + const block = await this.rpc.getGenesisBlock() if (block) { return Block.fromSDK(block) } return undefined } - public async getBlockHeaderByNumber(num: string): Promise { - const header = await this.ckb.rpc.getHeaderByNumber(HexUtils.toHex(num)) - if (header) { - return BlockHeader.fromSDK(header) - } - return undefined - } - public async genesisBlockHash(): Promise { return this.retry(async () => { - return this.ckb.rpc.getBlockHash('0x0') - }) - } - - public async getChain(): Promise { - const chain: string = await this.retry(async () => { - const i = await this.ckb.rpc.getBlockchainInfo() - return i.chain + return this.rpc.getGenesisBlockHash() }) - return chain } public async getSyncState(): Promise { const syncState = await this.retry(async () => { - return await this.ckb.rpc.syncState() + return await this.rpc.syncState() }) return syncState } - public async getLocalNodeInfo() { - return this.ckb.rpc.localNodeInfo() + public async localNodeInfo() { + return this.retry(async () => { + return this.rpc.localNodeInfo() + }) } private async retry(func: () => T): Promise { diff --git a/packages/neuron-wallet/src/services/settings.ts b/packages/neuron-wallet/src/services/settings.ts index 52c068db7b..b8f2d0fdc0 100644 --- a/packages/neuron-wallet/src/services/settings.ts +++ b/packages/neuron-wallet/src/services/settings.ts @@ -8,7 +8,11 @@ import path from 'path' const { app } = env export const locales = ['zh', 'zh-TW', 'en', 'en-US'] as const -export type Locale = (typeof locales)[number] +export type Locale = typeof locales[number] +const settingKeys = { + testnetLightDataPath: 'testnetLightDataPath', + ckbDataPath: 'ckbDataPath' +} export default class SettingsService extends Store { private static instance: SettingsService | null = null @@ -43,11 +47,19 @@ export default class SettingsService extends Store { } get ckbDataPath() { - return this.readSync('ckbDataPath') + return this.readSync(settingKeys.ckbDataPath) } set ckbDataPath(dataPath: string) { - this.writeSync('ckbDataPath', dataPath) + this.writeSync(settingKeys.ckbDataPath, dataPath) + } + + get testnetLightDataPath() { + return this.readSync(settingKeys.testnetLightDataPath) + } + + set testnetLightDataPath(dataPath: string) { + this.writeSync(settingKeys.testnetLightDataPath, dataPath) } constructor() { @@ -62,6 +74,9 @@ export default class SettingsService extends Store { if (!this.ckbDataPath) { this.ckbDataPath = path.resolve(app.getPath('userData'), 'chains/mainnet') } + if (!this.testnetLightDataPath) { + this.testnetLightDataPath = path.resolve(app.getPath('userData'), 'chains/light/testnet') + } } private onLocaleChanged = (lng: Locale) => { diff --git a/packages/neuron-wallet/src/services/sync-progress.ts b/packages/neuron-wallet/src/services/sync-progress.ts new file mode 100644 index 0000000000..0a856973a4 --- /dev/null +++ b/packages/neuron-wallet/src/services/sync-progress.ts @@ -0,0 +1,139 @@ +import { Equal, getConnection, In, Not } from 'typeorm' +import { scriptToHash } from '@nervosnetwork/ckb-sdk-utils' +import { HexString } from '@ckb-lumos/base' +import SyncProgress, { SyncAddressType } from '../database/chain/entities/sync-progress' +import WalletService from './wallets' + +export default class SyncProgressService { + static async resetSyncProgress( + params: { + script: CKBComponents.Script + scriptType: CKBRPC.ScriptType + walletId: string + addressType?: SyncAddressType + }[] + ) { + await getConnection() + .getRepository(SyncProgress) + .createQueryBuilder() + .insert() + .orIgnore() + .values(params.map(v => SyncProgress.fromObject(v))) + .execute() + } + + static async updateSyncProgressFlag(existWalletIds: string[]) { + await getConnection() + .createQueryBuilder() + .update(SyncProgress) + .set({ delete: true }) + .where({ walletId: Not(In(existWalletIds)) }) + .execute() + await getConnection() + .createQueryBuilder() + .update(SyncProgress) + .set({ delete: false }) + .where({ walletId: In(existWalletIds) }) + .execute() + } + + static async removeByHashesAndAddressType(addressType: SyncAddressType, existHashes?: string[]) { + await getConnection() + .createQueryBuilder() + .update(SyncProgress) + .set({ delete: true }) + .where({ ...(existHashes?.length ? { hash: Not(In(existHashes)) } : {}), addressType }) + .execute() + } + + static async updateBlockNumber(blake160s: string[], blockNumber: number) { + await getConnection() + .createQueryBuilder() + .update(SyncProgress) + .set({ blockStartNumber: blockNumber }) + .where({ blake160s: In(blake160s) }) + .execute() + } + + static async getSyncStatus(script: CKBComponents.Script) { + const scriptHash = scriptToHash(script) + const res = await getConnection() + .getRepository(SyncProgress) + .createQueryBuilder() + .where({ delete: false, hash: scriptHash }) + .getOne() + return res + } + + static async getAllSyncStatusToMap() { + const result: Map = new Map() + const syncProgresses = await getConnection() + .getRepository(SyncProgress) + .createQueryBuilder() + .where({ delete: false }) + .getMany() + syncProgresses.forEach(v => { + result.set(v.hash, v) + }) + return result + } + + static async updateSyncStatus( + hash: HexString, + { blockStartNumber, blockEndNumber, cursor }: { blockStartNumber: number; blockEndNumber: number; cursor?: string } + ) { + await getConnection().manager.update(SyncProgress, { hash }, { blockStartNumber, blockEndNumber, cursor }) + } + + static async getCurrentWalletMinBlockNumber() { + const currentWallet = WalletService.getInstance().getCurrent() + const item = await getConnection() + .getRepository(SyncProgress) + .createQueryBuilder() + .where({ delete: false, addressType: SyncAddressType.Default, ...(currentWallet ? { walletId: currentWallet.id } : {}) }) + .orderBy('blockEndNumber', 'ASC') + .getOne() + return item?.blockEndNumber || 0 + } + + static async getWalletMinBlockNumber() { + const items = await getConnection() + .getRepository(SyncProgress) + .createQueryBuilder() + .select('MIN(blockStartNumber) as blockStartNumber, walletId') + .where({ addressType: SyncAddressType.Default }) + .groupBy('walletId') + .getRawMany<{ blockStartNumber: number; walletId: string }>() + return items.reduce>((pre, cur) => ({ ...pre, [cur.walletId]: cur.blockStartNumber }), {}) + } + + static async getOtherTypeSyncProgress() { + const items = await getConnection() + .getRepository(SyncProgress) + .find({ + addressType: SyncAddressType.Multisig, + }) + return items.reduce>((pre, cur) => ({ ...pre, [cur.hash]: cur.blockStartNumber }), {}) + } + + static async getSyncProgressByHashes(hashes: string[]) { + return await getConnection() + .getRepository(SyncProgress) + .createQueryBuilder() + .where({ hash: In(hashes) }) + .getMany() + } + + static async clearCurrentWalletProgress() { + const currentWallet = WalletService.getInstance().getCurrent() + await getConnection() + .getRepository(SyncProgress) + .delete({ walletId: currentWallet?.id }) + await getConnection() + .createQueryBuilder() + .update(SyncProgress) + .set({ blockEndNumber: 0, cursor: undefined }) + .where({ walletId: Not(Equal(currentWallet?.id)) }) + .execute() + } +} diff --git a/packages/neuron-wallet/src/services/transaction-sender.ts b/packages/neuron-wallet/src/services/transaction-sender.ts index c328efe724..916d24fd07 100644 --- a/packages/neuron-wallet/src/services/transaction-sender.ts +++ b/packages/neuron-wallet/src/services/transaction-sender.ts @@ -1,28 +1,27 @@ -import WalletService, { Wallet } from '../services/wallets' +import ECPair from '@nervosnetwork/ckb-sdk-utils/lib/ecpair' +import signWitnesses from '@nervosnetwork/ckb-sdk-core/lib/signWitnesses' import NodeService from './node' import { scriptToAddress, serializeWitnessArgs, toUint64Le } from '@nervosnetwork/ckb-sdk-utils' import { TransactionPersistor, TransactionGenerator, TargetOutput } from './tx' import AddressService from './addresses' -import { Address } from '../models/address' +import WalletService, { Wallet } from '../services/wallets' +import RpcService from '../services/rpc-service' import { PathAndPrivateKey } from '../models/keys/key' -import { CellIsNotYetLive, TransactionIsNotCommittedYet } from '../exceptions/dao' +import { Address } from '../models/address' import FeeMode from '../models/fee-mode' import TransactionSize from '../models/transaction-size' import TransactionFee from '../models/transaction-fee' -import logger from '../utils/logger' import Keychain from '../models/keys/keychain' import Input from '../models/chain/input' import OutPoint from '../models/chain/out-point' import Output from '../models/chain/output' -import RpcService from '../services/rpc-service' import WitnessArgs from '../models/chain/witness-args' import Transaction from '../models/chain/transaction' -import BlockHeader from '../models/chain/block-header' import Script from '../models/chain/script' import Multisig from '../models/multisig' import Blake2b from '../models/blake2b' +import logger from '../utils/logger' import HexUtils from '../utils/hex' -import ECPair from '@nervosnetwork/ckb-sdk-utils/lib/ecpair' import SystemScriptInfo from '../models/system-script-info' import AddressParser from '../models/address-parser' import HardwareWalletService from './hardware' @@ -32,6 +31,8 @@ import { MultisigConfigNeedError, NoMatchAddressForSign, SignTransactionFailed, + CellIsNotYetLive, + TransactionIsNotCommittedYet } from '../exceptions' import AssetAccountInfo from '../models/asset-account-info' import MultisigConfigModel from '../models/multisig-config' @@ -40,6 +41,9 @@ import MultisigService from './multisig' import { getMultisigStatus } from '../utils/multisig' import { SignStatus } from '../models/offline-sign' import NetworksService from './networks' +import { generateRPC } from '../utils/ckb-rpc' +import CKB from '@nervosnetwork/ckb-sdk-core' +import CellsService from './cells' interface SignInfo { witnessArgs: WitnessArgs @@ -86,8 +90,8 @@ export default class TransactionSender { } public async broadcastTx(walletID: string = '', tx: Transaction) { - const { ckb } = NodeService.getInstance() - await ckb.rpc.sendTransaction(tx.toSDKRawTransaction(), 'passthrough') + const rpc = generateRPC(NodeService.getInstance().nodeUrl) + await rpc.sendTransaction(tx.toSDKRawTransaction(), 'passthrough') const txHash = tx.hash! await TransactionPersistor.saveSentTx(tx, txHash) @@ -107,7 +111,6 @@ export default class TransactionSender { ) { const wallet = this.walletService.get(walletID) const tx = Transaction.fromObject(transaction) - const { ckb } = NodeService.getInstance() const txHash: string = tx.computeHash() if (wallet.isHardware()) { let device = HardwareWalletService.getInstance().getCurrent() @@ -212,7 +215,7 @@ export default class TransactionSender { wit.lock = serializedMultisig + wit.lock!.slice(2) signed[0] = serializeWitnessArgs(wit.toSDK()) } else { - signed = ckb.signWitnesses(privateKey)({ + signed = signWitnesses(privateKey)({ transactionHash: txHash, witnesses: serializedWitnesses.map(wit => { if (typeof wit === 'string') { @@ -534,19 +537,15 @@ export default class TransactionSender { feeRate: string = '0' ): Promise => { const changeAddress: string = await this.getChangeAddress() - const url: string = NodeService.getInstance().ckb.node.url - const rpcService = new RpcService(url) - // for some reason with data won't work - const cellWithStatus = await rpcService.getLiveCell(new OutPoint(outPoint.txHash, outPoint.index), true) - const prevOutput = cellWithStatus.cell!.output - if (!cellWithStatus.isLive()) { + const nftCellOutput = await CellsService.getLiveCell(new OutPoint(outPoint.txHash, outPoint.index)) + if (!nftCellOutput) { throw new CellIsNotYetLive() } const tx = await TransactionGenerator.generateTransferNftTx( walletId, outPoint, - prevOutput, + nftCellOutput, receiveAddress, changeAddress, fee, @@ -589,10 +588,10 @@ export default class TransactionSender { // only for check wallet exists this.walletService.get(walletID) - const url: string = NodeService.getInstance().ckb.node.url + const url: string = NodeService.getInstance().nodeUrl const rpcService = new RpcService(url) - const cellWithStatus = await rpcService.getLiveCell(outPoint, false) - if (!cellWithStatus.isLive()) { + const depositeOutput = await CellsService.getLiveCell(outPoint) + if (!depositeOutput) { throw new CellIsNotYetLive() } const prevTx = await rpcService.getTransaction(outPoint.txHash) @@ -604,11 +603,10 @@ export default class TransactionSender { const wallet = WalletService.getInstance().get(walletID) const changeAddress = await wallet.getNextChangeAddress() - const prevOutput = cellWithStatus.cell!.output const tx: Transaction = await TransactionGenerator.startWithdrawFromDao( walletID, outPoint, - prevOutput, + depositeOutput, depositBlockHeader!.number, depositBlockHeader!.hash, changeAddress!.address, @@ -632,11 +630,11 @@ export default class TransactionSender { const feeRateInt = BigInt(feeRate) const mode = new FeeMode(feeRateInt) - const url: string = NodeService.getInstance().ckb.node.url + const url: string = NodeService.getInstance().nodeUrl const rpcService = new RpcService(url) - const cellStatus = await rpcService.getLiveCell(withdrawingOutPoint, true) - if (!cellStatus.isLive()) { + const withdrawOutput = await CellsService.getLiveCell(withdrawingOutPoint) + if (!withdrawOutput) { throw new CellIsNotYetLive() } const prevTx = (await rpcService.getTransaction(withdrawingOutPoint.txHash))! @@ -647,12 +645,23 @@ export default class TransactionSender { const secpCellDep = await SystemScriptInfo.getInstance().getSecpCellDep() const daoCellDep = await SystemScriptInfo.getInstance().getDaoCellDep() - const content = cellStatus.cell!.data!.content - const buf = Buffer.from(content.slice(2), 'hex') - const depositBlockNumber: bigint = buf.readBigUInt64LE() - const depositBlockHeader: BlockHeader = (await rpcService.getHeaderByNumber(depositBlockNumber.toString()))! + const content = withdrawOutput.daoData + if (!content) { + throw new Error(`Withdraw output cell is not a dao cell, ${withdrawOutput.outPoint?.txHash}`) + } + if (!withdrawOutput.depositOutPoint) { + throw new Error('DAO has not finish step first withdraw') + } + const depositeTx = await rpcService.getTransaction(withdrawOutput.depositOutPoint.txHash) + if (!depositeTx?.txStatus.blockHash) { + throw new Error(`Get deposite block hash failed with tx hash ${withdrawOutput.depositOutPoint.txHash}`) + } + const depositBlockHeader = await rpcService.getHeader(depositeTx.txStatus.blockHash) + if (!depositBlockHeader) { + throw new Error(`Get Header failed with blockHash ${depositeTx.txStatus.blockHash}`) + } const depositEpoch = this.parseEpoch(BigInt(depositBlockHeader.epoch)) - const depositCapacity: bigint = BigInt(cellStatus.cell!.output.capacity) + const depositCapacity: bigint = BigInt(withdrawOutput.capacity) const withdrawBlockHeader = (await rpcService.getHeader(prevTx.txStatus.blockHash!))! const withdrawEpoch = this.parseEpoch(BigInt(withdrawBlockHeader.epoch)) @@ -686,12 +695,11 @@ export default class TransactionSender { const outputs: Output[] = [output] - const previousOutput = cellStatus.cell!.output const input: Input = new Input( withdrawingOutPoint, minimalSince.toString(), - previousOutput.capacity, - previousOutput.lock + withdrawOutput.capacity, + withdrawOutput.lock ) const withdrawWitnessArgs: WitnessArgs = new WitnessArgs(WitnessArgs.EMPTY_LOCK, '0x0000000000000000') @@ -751,10 +759,10 @@ export default class TransactionSender { // only for check wallet exists this.walletService.get(walletID) - const url: string = NodeService.getInstance().ckb.node.url + const url: string = NodeService.getInstance().nodeUrl const rpcService = new RpcService(url) - const cellWithStatus = await rpcService.getLiveCell(outPoint, false) - if (!cellWithStatus.isLive()) { + const locktimeOutput = await CellsService.getLiveCell(outPoint) + if (!locktimeOutput) { throw new CellIsNotYetLive() } const prevTx = await rpcService.getTransaction(outPoint.txHash) @@ -766,10 +774,9 @@ export default class TransactionSender { const receivingAddressInfo = await wallet.getNextAddress() const receivingAddress = receivingAddressInfo!.address - const prevOutput = cellWithStatus.cell!.output const tx: Transaction = await TransactionGenerator.generateWithdrawMultiSignTx( outPoint, - prevOutput, + locktimeOutput, receivingAddress, fee, feeRate @@ -782,7 +789,7 @@ export default class TransactionSender { depositOutPoint: OutPoint, withdrawBlockHash: string ): Promise => { - const { ckb } = NodeService.getInstance() + const ckb = new CKB(NodeService.getInstance().nodeUrl) const result = await ckb.calculateDaoMaximumWithdraw(depositOutPoint.toSDK(), withdrawBlockHash) return BigInt(result) diff --git a/packages/neuron-wallet/src/services/tx/transaction-generator.ts b/packages/neuron-wallet/src/services/tx/transaction-generator.ts index 9d0f9cdabb..94fc6c4cc8 100644 --- a/packages/neuron-wallet/src/services/tx/transaction-generator.ts +++ b/packages/neuron-wallet/src/services/tx/transaction-generator.ts @@ -340,7 +340,7 @@ export class TransactionGenerator { } private static async getTipHeader(): Promise { - const rpcService = new RpcService(NodeService.getInstance().ckb.node.url) + const rpcService = new RpcService(NodeService.getInstance().nodeUrl) const tipHeader = await rpcService.getTipHeader() return tipHeader } diff --git a/packages/neuron-wallet/src/services/wallets.ts b/packages/neuron-wallet/src/services/wallets.ts index 09bb0fc47a..f822b61847 100644 --- a/packages/neuron-wallet/src/services/wallets.ts +++ b/packages/neuron-wallet/src/services/wallets.ts @@ -12,6 +12,9 @@ import AddressService from './addresses' import { DeviceInfo } from './hardware/common' import HdPublicKeyInfo from '../database/chain/entities/hd-public-key-info' import { getConnection, In, Not } from 'typeorm' +import NetworksService from './networks' +import { NetworkType } from '../models/network' +import { resetSyncTaskQueue } from '../block-sync-renderer' const fileService = FileService.getInstance() @@ -24,6 +27,7 @@ export interface WalletProperties { isHDWallet?: boolean device?: DeviceInfo keystore?: Keystore + startBlockNumberInLight?: string } export abstract class Wallet { @@ -32,9 +36,10 @@ export abstract class Wallet { public device?: DeviceInfo protected extendedKey: string = '' protected isHD: boolean + protected startBlockNumberInLight?: string constructor(props: WalletProperties) { - const { id, name, extendedKey, device, isHDWallet } = props + const { id, name, extendedKey, device, isHDWallet, startBlockNumberInLight } = props if (id === undefined) { throw new IsRequired('ID') @@ -52,6 +57,7 @@ export abstract class Wallet { this.extendedKey = extendedKey this.device = device this.isHD = isHDWallet ?? true + this.startBlockNumberInLight = startBlockNumberInLight } public toJSON = () => ({ @@ -139,6 +145,7 @@ export class FileKeystoreWallet extends Wallet { extendedKey: this.extendedKey, device: this.device, isHD: this.isHD, + startBlockNumberInLight: this.startBlockNumberInLight } } @@ -309,7 +316,7 @@ export default class WalletService { await getConnection() .getRepository(HdPublicKeyInfo) .delete({ - walletId: Not(In(allWallets.map(w => w.id))), + walletId: Not(In(allWallets.map((w) => w.id))) }) } @@ -322,7 +329,7 @@ export default class WalletService { throw new IsRequired('ID') } - const wallet = this.getAll().find(w => w.id === id) + const wallet = this.getAll().find((w) => w.id === id) if (!wallet) { throw new WalletNotFound(id) } @@ -353,7 +360,7 @@ export default class WalletService { throw new IsRequired('wallet property') } - const index = this.getAll().findIndex(wallet => wallet.name === props.name) + const index = this.getAll().findIndex((wallet) => wallet.name === props.name) if (index !== -1) { throw new UsedName('Wallet') @@ -380,7 +387,7 @@ export default class WalletService { const wallet = this.fromJSON(wallets[index]) - if (wallet.name !== props.name && wallets.findIndex(storeWallet => storeWallet.name === props.name) !== -1) { + if (wallet.name !== props.name && wallets.findIndex((storeWallet) => storeWallet.name === props.name) !== -1) { throw new UsedName('Wallet') } @@ -395,14 +402,14 @@ export default class WalletService { public delete = async (id: string) => { const wallets = this.getAll() - const walletJSON = wallets.find(w => w.id === id) + const walletJSON = wallets.find((w) => w.id === id) if (!walletJSON) { throw new WalletNotFound(id) } const wallet = this.fromJSON(walletJSON) - const newWallets = wallets.filter(w => w.id !== id) + const newWallets = wallets.filter((w) => w.id !== id) const current = this.getCurrent() const currentID = current ? current.id : '' @@ -442,6 +449,11 @@ export default class WalletService { } } + const network = NetworksService.getInstance().getCurrent() + if (network.type === NetworkType.Light) { + resetSyncTaskQueue.asyncPush(true) + } + this.listStore.writeSync(this.currentWalletKey, id) } @@ -463,7 +475,7 @@ export default class WalletService { } public clearAll = () => { - this.getAll().forEach(w => { + this.getAll().forEach((w) => { const wallet = this.fromJSON(w) if (!wallet.isHardware()) { wallet.deleteKeystore() diff --git a/packages/neuron-wallet/src/types/controller.d.ts b/packages/neuron-wallet/src/types/controller.d.ts index 20cdba3b2e..ea54bc7f0f 100644 --- a/packages/neuron-wallet/src/types/controller.d.ts +++ b/packages/neuron-wallet/src/types/controller.d.ts @@ -91,7 +91,7 @@ declare namespace Controller { name: string remote: string - type: 0 | 1 // 0 for the default type, 1 for the normal type + type: 0 | 1 | 2 // 0 for the default type, 1 for the normal type, 2 for the light client } interface Address { diff --git a/packages/neuron-wallet/src/types/rpc.d.ts b/packages/neuron-wallet/src/types/rpc.d.ts new file mode 100644 index 0000000000..0fe9dcad1e --- /dev/null +++ b/packages/neuron-wallet/src/types/rpc.d.ts @@ -0,0 +1,3 @@ +declare namespace CKBRPC { + type ScriptType = 'lock' | 'type' +} diff --git a/packages/neuron-wallet/src/utils/ckb-rpc.ts b/packages/neuron-wallet/src/utils/ckb-rpc.ts new file mode 100644 index 0000000000..57481b27ce --- /dev/null +++ b/packages/neuron-wallet/src/utils/ckb-rpc.ts @@ -0,0 +1,334 @@ +import { HexString, Script } from '@ckb-lumos/base' +import CKBRPC from '@nervosnetwork/ckb-sdk-rpc' +import Method from '@nervosnetwork/ckb-sdk-rpc/lib/method' +import resultFormatter from '@nervosnetwork/ckb-sdk-rpc/lib/resultFormatter' +import paramsFormatter from '@nervosnetwork/ckb-sdk-rpc/lib/paramsFormatter' +import Base from '@nervosnetwork/ckb-sdk-rpc/lib/Base' +import { MethodInBatchNotFoundException, PayloadInBatchException, IdNotMatchedInBatchException } from '@nervosnetwork/ckb-sdk-rpc/lib/exceptions' +import https from 'https' +import http from 'http' +import { request } from 'undici' +import { BUNDLED_LIGHT_CKB_URL, LIGHT_CLIENT_TESTNET } from './const' +import CommonUtils from './common' + +export interface LightScriptFilter { + script: CKBComponents.Script + blockNumber: CKBComponents.BlockNumber + scriptType: CKBRPC.ScriptType +} + +export type LightScriptSyncStatus = LightScriptFilter + +const lightRPCProperties: Record[0], 'name'>> = { + setScripts: { + method: 'set_scripts', + paramsFormatters: [ + (params: LightScriptFilter[]) => params.map(v => ({ + script: { + args: v.script.args, + code_hash: v.script.codeHash, + hash_type: v.script.hashType + }, + block_number: v.blockNumber, + script_type: v.scriptType + })) + ] + }, + getScripts: { + method: 'get_scripts', + paramsFormatters: [], + resultFormatters: (result: { script: Script, block_number: CKBComponents.BlockNumber, script_type: CKBRPC.ScriptType }[]) => result.map(v => ({ + script: { + args: v.script.args, + codeHash: v.script.code_hash, + hashType: v.script.hash_type + }, + blockNumber: v.block_number, + scriptType: v.script_type + })) + }, + getTransactions: { + method: 'get_transactions', + paramsFormatters: [ + (searchKey: { script: CKBComponents.Script, scriptType: CKBRPC.ScriptType, blockRange: [HexString, HexString] }) => ({ + script: { + args: searchKey.script.args, + code_hash: searchKey.script.codeHash, + hash_type: searchKey.script.hashType + }, + script_type: searchKey.scriptType, + filter: { block_range: searchKey.blockRange }, + group_by_transaction: true + }) + ], + resultFormatters: (result: { + last_cursor: HexString, + objects: { + block_number: HexString, + tx_index: HexString, + transaction: { hash: HexString } + }[] }) => ({ + lastCursor: result.last_cursor, + txs: result.objects.map(v => ({ + txHash: v.transaction.hash, + txIndex: v.tx_index, + blockNumber: v.block_number, + })) + }) + }, + getGenesisBlock: { + method: 'get_genesis_block', + paramsFormatters: [], + resultFormatters: resultFormatter.toBlock + }, + sendTransaction: { + method: 'send_transaction', + paramsFormatters: [paramsFormatter.toRawTransaction], + resultFormatters: resultFormatter.toHash, + }, + fetchTransaction: { + method: 'fetch_transaction', + paramsFormatters: [paramsFormatter.toHash], + resultFormatters: (result: { status: 'fetched' | 'fetching' | 'added' | 'not_found', data?: RPC.TransactionWithStatus }) => { + return { + status: result.status, + txWithStatus: result.status === 'fetched' && result.data ? resultFormatter.toTransactionWithStatus(result.data) : undefined + } + } + } +} + +export class FullCKBRPC extends CKBRPC { + getGenesisBlockHash = async () => { + return this.getBlockHash('0x0') + } + + getGenesisBlock = async () => { + return this.getBlockByNumber('0x0') + } +} + +export type FetchTransactionReturnType = { status: 'fetched' | 'fetching' | 'added' | 'not_found', txWithStatus?: CKBComponents.TransactionWithStatus } + +export class LightRPC extends Base { + setScripts: (params: LightScriptFilter[]) => Promise + getScripts: () => Promise + getTransactions: ( + searchKey: { script: CKBComponents.Script, scriptType: CKBRPC.ScriptType, blockRange: [HexString, HexString] }, + order: 'asc' | 'desc', + limit: HexString, + afterCursor: HexString + ) => Promise<{ lastCursor: HexString, txs: { txHash: HexString, txIndex: HexString, blockNumber: CKBComponents.BlockNumber }[]}> + + getTransactionInLight: Base['getTransaction'] + fetchTransaction: (hash: string) => Promise + + getGenesisBlock: () => Promise + exceptionMethods = ['getCurrentEpoch', 'getEpochByNumber', 'getBlockHash', 'getLiveCell'] + coverMethods = ['getTipBlockNumber', 'syncState', 'getBlockchainInfo', 'sendTransaction', 'getTransaction'] + + constructor(url: string) { + super() + this.setNode({ url }) + + Object.defineProperties(this, { + addMethod: { value: this.addMethod, enumerable: false, writable: false, configurable: false }, + setNode: { value: this.setNode, enumerable: false, writable: false, configurable: false }, + }) + + Object.keys(this.rpcProperties).forEach(name => { + this.addMethod({ name, ...this.rpcProperties[name] }) + }) + + this.setScripts = new Method(this.node, { name: 'setScripts', ...lightRPCProperties['setScripts'] }).call + this.getScripts = new Method(this.node, { name: 'getScripts', ...lightRPCProperties['getScripts'] }).call + this.getTransactions = new Method(this.node, { name: 'getTransactions', ...lightRPCProperties['getTransactions'] }).call + this.getGenesisBlock = new Method(this.node, { name: 'getGenesisBlock', ...lightRPCProperties['getGenesisBlock'] }).call + const sendTransactionMethod = new Method(this.node, { name: 'sendTransaction', ...lightRPCProperties['sendTransaction'] }) + this.sendTransaction = (tx: CKBComponents.RawTransaction) => sendTransactionMethod.call(tx) + this.getTransactionInLight = new Method(this.node, { name: 'getTransaction', ...this.rpcProperties['getTransaction'] }).call + this.fetchTransaction = new Method(this.node, { name: 'fetchTransaction', ...lightRPCProperties['fetchTransaction'] }).call + } + + getTransaction = async (hash: string): Promise => { + let tx = await this.getTransactionInLight(hash) + if (!tx?.transaction) { + tx = await CommonUtils.retry(3, 100, async () => { + const tmp = await this.fetchTransaction(hash) + if (!tmp.txWithStatus) { + throw new Error(`transaction ${hash} status: ${tmp.status}`) + } + return tmp.txWithStatus + }) + if (!tx) {throw new Error(`Fetch transaction tx failed, please try it later: ${hash}`)} + } + return tx + } + + getTipBlockNumber = async () => { + const headerTip = await this.getTipHeader() + return headerTip.number + } + + getGenesisBlockHash = async () => { + const genesisBlock = await this.getGenesisBlock() + return genesisBlock.header.hash + } + + syncState = async () => { + const headerTip = await this.getTipHeader() + return { + bestKnownBlockNumber: headerTip.number, + bestKnownBlockTimestamp: headerTip.timestamp, + } as CKBComponents.SyncState + } + + getBlockchainInfo = async () => { + await this.localNodeInfo() + return { + chain: LIGHT_CLIENT_TESTNET + } as CKBComponents.BlockchainInfo + } + + #node: CKBComponents.Node = { + url: '', + } + + get node() { + return this.#node + } + + #paramsFormatter = paramsFormatter + + get paramsFormatter() { + return this.#paramsFormatter + } + + #resultFormatter = resultFormatter + + get resultFormatter() { + return this.#resultFormatter + } + + public setNode(node: CKBComponents.Node): CKBComponents.Node { + Object.assign(this.node, node) + return this.node + } + + public addMethod = (options: CKBComponents.Method) => { + if (this.exceptionMethods.includes(options.name)) { + Object.defineProperty(this, options.name, { + value: () => { + throw new Error(`Unrealized ${options.name} in light node`) + }, + enumerable: true, + }) + } else if (!this.coverMethods.includes(options.name)) { + const method = new Method(this.node, options) + + Object.defineProperty(this, options.name, { + value: method.call, + enumerable: true, + }) + } + } + + public createBatchRequest = ( + params: [method: N, ...rest: P][] = [], + ) => { + const methods = Object.keys(this) + const { node, rpcProperties } = this + + const proxied: [method: N, ...rest: P][] = new Proxy([], { + set(...p) { + if (p[1] !== 'length') { + const name = p?.[2]?.[0] + if (methods.indexOf(name) === -1) { + throw new MethodInBatchNotFoundException(name) + } + } + return Reflect.set(...p) + }, + }) + + Object.defineProperties(proxied, { + add: { + value(...args: P) { + this.push(args) + return this + }, + }, + remove: { + value(i: number) { + this.splice(i, 1) + return this + }, + }, + exec: { + async value() { + const payload = proxied.map(([f, ...p], i) => { + try { + const method = new Method(node, { ...({ ...rpcProperties, ...lightRPCProperties }[f]), name: f }) + return method.getPayload(...p) + } catch (err) { + throw new PayloadInBatchException(i, err.message) + } + }) + + const res = await request(node.url, { + method: 'POST', + body: JSON.stringify(payload), + headers: { 'content-type': 'application/json' }, + }) + const batchRes = await res.body.json() + + return batchRes.map((res: any, i: number) => { + if (res.id !== payload[i].id) { + return new IdNotMatchedInBatchException(i, payload[i].id, res.id) + } + return ({ ...rpcProperties, ...lightRPCProperties })[proxied[i][0]].resultFormatters?.(res.result) ?? res.result + }) + }, + }, + }) + params.forEach(p => proxied.push(p)) + + return proxied as typeof proxied & { + add: (n: N, ...p: P) => typeof proxied + remove: (index: number) => typeof proxied + exec: () => Promise + } + } +} + +let httpsAgent: https.Agent +let httpAgent: http.Agent + +const getHttpsAgent = () => { + if (!httpsAgent) { + httpsAgent = new https.Agent({ keepAlive: true }) + } + return httpsAgent +} + +const getHttpAgent = () => { + if (!httpAgent) { + httpAgent = new http.Agent({ keepAlive: true }) + } + return httpAgent +} + +export const generateRPC = (url: string) => { + let rpc: LightRPC | FullCKBRPC + if (url === BUNDLED_LIGHT_CKB_URL) { + rpc = new LightRPC(url) + } else { + rpc = new FullCKBRPC(url) + } + if (url?.startsWith('https')) { + rpc.setNode({ url, httpsAgent: getHttpsAgent() }) + } else { + rpc.setNode({ url, httpAgent: getHttpAgent() }) + } + return rpc +} diff --git a/packages/neuron-wallet/src/utils/common.ts b/packages/neuron-wallet/src/utils/common.ts index cdf789e01f..e67be1b0a4 100644 --- a/packages/neuron-wallet/src/utils/common.ts +++ b/packages/neuron-wallet/src/utils/common.ts @@ -5,18 +5,18 @@ export default class CommonUtils { return new Promise(resolve => setTimeout(resolve, ms)) } - public static async retry(times: number, interval: number, callback: () => T): Promise { + public static async retry(times: number, interval: number, callback: () => T): Promise> { let retryTime = 0 while (++retryTime < times) { try { - return await callback() + return await (callback() as Awaited) } catch (err) { logger.warn(`function call error: ${err}, retry ${retryTime + 1} ...`) await CommonUtils.sleep(interval) } } - return await callback() + return await (callback() as Awaited) } public static timeout(time: number, promise: Promise, value: T): Promise { diff --git a/packages/neuron-wallet/src/utils/const.ts b/packages/neuron-wallet/src/utils/const.ts index 1b84c7ef41..562394e4b1 100644 --- a/packages/neuron-wallet/src/utils/const.ts +++ b/packages/neuron-wallet/src/utils/const.ts @@ -1,6 +1,8 @@ export const MIN_PASSWORD_LENGTH = 8 export const MAX_PASSWORD_LENGTH = 50 export const BUNDLED_CKB_URL = 'http://127.0.0.1:8114' +export const BUNDLED_LIGHT_CKB_URL = 'http://127.0.0.1:9000' +export const LIGHT_CLIENT_TESTNET = 'light_client_testnet' export const SETTINGS_WINDOW_TITLE = process.platform === 'darwin' ? 'settings.title.mac' : 'settings.title.normal' export const SETTINGS_WINDOW_WIDTH = 900 export const DEFAULT_UDT_SYMBOL = 'Unknown' diff --git a/packages/neuron-wallet/src/utils/rpc-request.ts b/packages/neuron-wallet/src/utils/rpc-request.ts index 2793c7377e..2ed650a0e5 100644 --- a/packages/neuron-wallet/src/utils/rpc-request.ts +++ b/packages/neuron-wallet/src/utils/rpc-request.ts @@ -1,6 +1,6 @@ import { request } from 'undici' -export const rpcRequest = async ( +export const rpcRequest = async ( url: string, options: { method: string @@ -22,7 +22,8 @@ export const rpcRequest = async ( if (res.statusCode !== 200) { throw new Error(`indexer request failed with HTTP code ${res.statusCode}`) } - return res.body.json() + const body = await res.body.json() + return body?.result as T } export const rpcBatchRequest = async ( diff --git a/packages/neuron-wallet/tests/block-sync-renderer/indexer-connector.test.ts b/packages/neuron-wallet/tests/block-sync-renderer/indexer-connector.test.ts index a73f7c392f..c868b8ae34 100644 --- a/packages/neuron-wallet/tests/block-sync-renderer/indexer-connector.test.ts +++ b/packages/neuron-wallet/tests/block-sync-renderer/indexer-connector.test.ts @@ -3,7 +3,8 @@ import { when } from 'jest-when' import { AddressType } from '../../src/models/keys/address' import { Address, AddressVersion } from '../../src/models/address' import SystemScriptInfo from '../../src/models/system-script-info' -import IndexerConnector, { LumosCellQuery } from '../../src/block-sync-renderer/sync/indexer-connector' +import IndexerConnector from '../../src/block-sync-renderer/sync/indexer-connector' +import type { LumosCellQuery } from '../../src/block-sync-renderer/sync/connector' import { flushPromises } from '../test-utils' import { ScriptHashType } from '../../src/models/chain/script' @@ -236,7 +237,7 @@ describe('unit tests for IndexerConnector', () => { }) it('emits new transactions in batch by the next unprocessed block number', () => { expect(txObserver).toHaveBeenCalledTimes(1) - expect(txObserver).toHaveBeenCalledWith([fakeTx1]) + expect(txObserver).toHaveBeenCalledWith({ txHashes: [fakeTx1.transaction.hash], params: fakeTx1.transaction.blockNumber }) }) }) describe('when loaded block number is not in order', () => { @@ -252,7 +253,7 @@ describe('unit tests for IndexerConnector', () => { }) it('emits new transactions in batch by the next unprocessed block number', () => { expect(txObserver).toHaveBeenCalledTimes(1) - expect(txObserver).toHaveBeenCalledWith([fakeTx1]) + expect(txObserver).toHaveBeenCalledWith({ txHashes: [fakeTx1.transaction.hash], params: fakeTx1.transaction.blockNumber }) }) }) describe('#notifyCurrentBlockNumberProcessed', () => { @@ -326,8 +327,7 @@ describe('unit tests for IndexerConnector', () => { let txObserver: any beforeEach(async () => { stubbedUpsertTxHashesFn.mockReturnValueOnce([fakeTx3.transaction.hash]) - stubbedNextUnprocessedTxsGroupedByBlockNumberFn.mockResolvedValue([fakeTxHashCache3]) - when(stubbedGetTransactionFn).calledWith(fakeTxHashCache3.txHash).mockResolvedValueOnce(undefined) + stubbedNextUnprocessedTxsGroupedByBlockNumberFn.mockRejectedValue('exception') txObserver = jest.fn() transactionsSubject.subscribe((transactions: any) => txObserver(transactions)) @@ -336,7 +336,7 @@ describe('unit tests for IndexerConnector', () => { }) it('throws error', async () => { expect(stubbedLoggerErrorFn).toHaveBeenCalledWith( - 'Error in processing next block number queue: Error: failed to fetch transaction for hash hash3' + 'Error in processing next block number queue: Error: exception' ) }) }) diff --git a/packages/neuron-wallet/tests/block-sync-renderer/light-connector.test.ts b/packages/neuron-wallet/tests/block-sync-renderer/light-connector.test.ts new file mode 100644 index 0000000000..779a7f366e --- /dev/null +++ b/packages/neuron-wallet/tests/block-sync-renderer/light-connector.test.ts @@ -0,0 +1,462 @@ +import { scriptToHash } from '@nervosnetwork/ckb-sdk-utils' +import LightConnector from '../../src/block-sync-renderer/sync/light-connector' +import SyncProgress from '../../src/database/chain/entities/sync-progress' +import HexUtils from '../../src/utils/hex' +import AddressMeta from '../../src/database/address/meta' + +const getSyncStatusMock = jest.fn() +const getCurrentWalletMinBlockNumberMock = jest.fn() +const getAllSyncStatusToMapMock = jest.fn() +const resetSyncProgressMock = jest.fn() +const updateSyncStatusMock = jest.fn() +const updateSyncProgressFlagMock = jest.fn() +const getWalletMinBlockNumberMock = jest.fn() +const removeByHashesAndAddressType = jest.fn() +const getOtherTypeSyncProgressMock = jest.fn() + +const setScriptsMock = jest.fn() +const getScriptsMock = jest.fn() +const getTipHeaderMock = jest.fn() +const getTransactionsMock = jest.fn() +const createBatchRequestMock = jest.fn() + +const schedulerWaitMock = jest.fn() +const getMultisigConfigForLightMock = jest.fn() +const walletGetCurrentMock = jest.fn() +const walletGetAllMock = jest.fn() + +function mockReset() { + getSyncStatusMock.mockReset() + getCurrentWalletMinBlockNumberMock.mockReset() + getAllSyncStatusToMapMock.mockReset() + resetSyncProgressMock.mockReset() + updateSyncStatusMock.mockReset() + getWalletMinBlockNumberMock.mockReset() + getOtherTypeSyncProgressMock.mockReset() + + setScriptsMock.mockReset() + getScriptsMock.mockReset() + getTipHeaderMock.mockReset() + getTransactionsMock.mockReset() + createBatchRequestMock.mockReset() + + schedulerWaitMock.mockReset() + getMultisigConfigForLightMock.mockReset() + removeByHashesAndAddressType.mockReset() + walletGetCurrentMock.mockReset() + walletGetAllMock.mockReset() +} + +jest.mock('../../src/services/sync-progress', () => { + return class { + static getSyncStatus: any = () => getSyncStatusMock() + static getCurrentWalletMinBlockNumber: any = () => getCurrentWalletMinBlockNumberMock() + static getAllSyncStatusToMap: any = () => getAllSyncStatusToMapMock() + static resetSyncProgress: any = (arg: any) => resetSyncProgressMock(arg) + static updateSyncStatus: any = (hash: string, update: any) => updateSyncStatusMock(hash, update) + static updateSyncProgressFlag: any = (walletIds: string[]) => updateSyncProgressFlagMock(walletIds) + static getWalletMinBlockNumber: any = () => getWalletMinBlockNumberMock() + static removeByHashesAndAddressType: any = (type: number, scripts: CKBComponents.Script[]) => removeByHashesAndAddressType(type, scripts) + static getOtherTypeSyncProgress: any = () => getOtherTypeSyncProgressMock() + } +}) + +jest.mock('../../src/utils/ckb-rpc', () => ({ + LightRPC: function() { + return { + setScripts: setScriptsMock, + getScripts: getScriptsMock, + getTipHeader: getTipHeaderMock, + getTransactions: getTransactionsMock, + createBatchRequest: () => ({ exec: createBatchRequestMock }), + } + } +})) + +jest.mock('../../src/services/multisig', () => ({ + getMultisigConfigForLight: () => getMultisigConfigForLightMock() +})) + +jest.mock('../../src/services/wallets', () => ({ + getInstance() { + return { + getCurrent: walletGetCurrentMock, + getAll: walletGetAllMock, + } + } +})) + +jest.mock('timers/promises', () => ({ + scheduler: { + wait: (delay: number) => schedulerWaitMock(delay), + } +})) + +const script: CKBComponents.Script = { + args: '0x403f0d4e833b2a8d372772a63facaa310dfeef92', + codeHash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8', + hashType: 'type' +} +const scriptHash = scriptToHash(script) +const address = 'ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsq2q8ux5aqem92xnwfmj5cl6e233phlwlysqhjx5w' + +describe('test light connector', () => { + beforeEach(() => { + walletGetAllMock.mockReturnValue([]) + createBatchRequestMock.mockResolvedValue([]) + getMultisigConfigForLightMock.mockResolvedValue([]) + getOtherTypeSyncProgressMock.mockResolvedValue({}) + }) + afterEach(() => { + mockReset() + }) + describe('test synchronize', () => { + it('syncQueue is not idle', async () => { + const connector = new LightConnector([], '') + // @ts-ignore: private-method + connector.syncQueue.push({}) + // @ts-ignore: private-method + await connector.synchronize() + expect(getScriptsMock).not.toBeCalled() + }) + it('syncQueue is idle', async () => { + getScriptsMock.mockResolvedValue([]) + getAllSyncStatusToMapMock.mockResolvedValue(new Map()) + const connector = new LightConnector([], '') + // @ts-ignore: private-method + connector.subscribeSync = jest.fn() + // @ts-ignore: private-method + await connector.synchronize() + expect(getScriptsMock).toBeCalled() + expect(getAllSyncStatusToMapMock).toBeCalled() + }) + it('some script sync cursor is not empty', async () => { + getScriptsMock.mockResolvedValue([]) + const syncProgress = SyncProgress.fromObject({ + script, + scriptType: 'lock', + walletId: 'walletId1' + }) + syncProgress.blockStartNumber = 0 + syncProgress.blockEndNumber = 1 + syncProgress.cursor = '0x1' + getAllSyncStatusToMapMock.mockResolvedValue(new Map([[scriptHash, syncProgress]])) + const connector = new LightConnector([], '') + // @ts-ignore: private-method + connector.subscribeSync = jest.fn() + // @ts-ignore: private-method + await connector.synchronize() + // @ts-ignore: private-method + const queue = connector.syncQueue.workersList() + expect(queue[0].data).toStrictEqual({ + script: { + codeHash: syncProgress.codeHash, + hashType: syncProgress.hashType, + args: syncProgress.args + }, + blockRange: [HexUtils.toHex(syncProgress.blockStartNumber), HexUtils.toHex(syncProgress.blockEndNumber)], + scriptType: syncProgress.scriptType, + cursor: syncProgress.cursor + }) + }) + it('some script sync cursor is not empty but is in sync queue', async () => { + getScriptsMock.mockResolvedValue([]) + const syncProgress = SyncProgress.fromObject({ + script, + scriptType: 'lock', + walletId: 'walletId1' + }) + syncProgress.blockStartNumber = 0 + syncProgress.blockEndNumber = 1 + syncProgress.cursor = '0x1' + getAllSyncStatusToMapMock.mockResolvedValue(new Map([[scriptHash, syncProgress]])) + const connector = new LightConnector([], '') + // @ts-ignore: private-method + connector.syncInQueue.set(scriptHash, {}) + // @ts-ignore: private-method + connector.subscribeSync = jest.fn() + // @ts-ignore: private-method + connector.syncQueue.pause() + // @ts-ignore: private-method + await connector.synchronize() + // @ts-ignore: private-method + expect(connector.syncQueue.length()).toBe(0) + }) + it('some script sync to new block', async () => { + getScriptsMock.mockResolvedValue([{ + script, + scriptType: 'lock', + blockNumber: '0xaa' + }]) + const syncProgress = SyncProgress.fromObject({ + script, + scriptType: 'lock', + walletId: 'walletId1' + }) + syncProgress.blockStartNumber = 0 + syncProgress.blockEndNumber = 1 + getAllSyncStatusToMapMock.mockResolvedValue(new Map([[scriptHash, syncProgress]])) + const connector = new LightConnector([], '') + // @ts-ignore: private-method + connector.subscribeSync = jest.fn() + // @ts-ignore: private-method + await connector.synchronize() + // @ts-ignore: private-method + const queue = connector.syncQueue.workersList() + expect(queue[0].data).toStrictEqual({ + script: { + codeHash: syncProgress.codeHash, + hashType: syncProgress.hashType, + args: syncProgress.args + }, + blockRange: [HexUtils.toHex(syncProgress.blockEndNumber), HexUtils.toHex('0xaa')], + scriptType: syncProgress.scriptType, + cursor: syncProgress.cursor + }) + }), + it('some script sync to new block but is in sync queue', async () => { + getScriptsMock.mockResolvedValue([{ + script, + scriptType: 'lock', + blockNumber: '0xaa' + }]) + const syncProgress = SyncProgress.fromObject({ + script, + scriptType: 'lock', + walletId: 'walletId1' + }) + syncProgress.blockStartNumber = 0 + syncProgress.blockEndNumber = 1 + getAllSyncStatusToMapMock.mockResolvedValue(new Map([[scriptHash, syncProgress]])) + const connector = new LightConnector([], '') + // @ts-ignore: private-method + connector.syncInQueue.set(scriptHash, {}) + // @ts-ignore: private-method + connector.subscribeSync = jest.fn() + // @ts-ignore: private-method + connector.syncQueue.pause() + // @ts-ignore: private-method + await connector.synchronize() + // @ts-ignore: private-method + expect(connector.syncQueue.length()).toBe(0) + }) + }) + + describe('test subscribeSync', () => { + it('run success', async () => { + getCurrentWalletMinBlockNumberMock.mockResolvedValue(100) + getTipHeaderMock.mockResolvedValue({ number: '0xaa' }) + const connector = new LightConnector([], '') + // @ts-ignore: private-method + connector.blockTipsSubject = { next: jest.fn() } + // @ts-ignore: private-method + await connector.subscribeSync() + // @ts-ignore: private-method + expect(connector.blockTipsSubject.next).toBeCalledWith({ + cacheTipNumber: 100, + indexerTipNumber: 170 + }) + }) + }) + + describe('test initSyncProgress', () => { + it('there is not exist addressmata', async () => { + const connect = new LightConnector([], '') + //@ts-ignore + await connect.initSyncProgress() + expect(getScriptsMock).toBeCalledTimes(0) + }) + it('append multisig script', async () => { + getScriptsMock.mockResolvedValue([]) + const connect = new LightConnector([], '') + //@ts-ignore + await connect.initSyncProgress([{ walletId: 'walletId', script, addressType: 1, scriptType: 'lock' }]) + expect(getScriptsMock).toBeCalledTimes(1) + expect(setScriptsMock).toBeCalledWith([ + { script, scriptType: 'lock', walletId: 'walletId', blockNumber: '0x0', addressType: 1, }, + ]) + }) + it('there is not exist sync scripts with light client', async () => { + getScriptsMock.mockResolvedValue([{ script, blockNumber: '0xaa' }]) + const addressMeta = AddressMeta.fromObject({ walletId: 'walletId', address, path: '', addressIndex: 10, addressType: 0, blake160: script.args }) + const connect = new LightConnector([addressMeta], '') + //@ts-ignore + await connect.initSyncProgress() + expect(setScriptsMock).toBeCalledWith([ + { script: addressMeta.generateDefaultLockScript().toSDK(), scriptType: 'lock', walletId: 'walletId', blockNumber: '0xaa' }, + { script: addressMeta.generateACPLockScript().toSDK(), scriptType: 'lock', walletId: 'walletId', blockNumber: '0x0' }, + { script: addressMeta.generateLegacyACPLockScript().toSDK(), scriptType: 'lock', walletId: 'walletId', blockNumber: '0x0' }, + ]) + expect(resetSyncProgressMock).toBeCalledWith([ + { script: addressMeta.generateDefaultLockScript().toSDK(), scriptType: 'lock', walletId: 'walletId' }, + { script: addressMeta.generateACPLockScript().toSDK(), scriptType: 'lock', walletId: 'walletId' }, + { script: addressMeta.generateLegacyACPLockScript().toSDK(), scriptType: 'lock', walletId: 'walletId' }, + ]) + expect(updateSyncProgressFlagMock).toBeCalledWith(['walletId']) + }) + it('set new script with the synced min block number', async () => { + getScriptsMock.mockResolvedValue([]) + const addressMeta = AddressMeta.fromObject({ walletId: 'walletId', address, path: '', addressIndex: 10, addressType: 0, blake160: script.args }) + getWalletMinBlockNumberMock.mockResolvedValue({ 'walletId': 170}) + const connect = new LightConnector([addressMeta], '') + //@ts-ignore + await connect.initSyncProgress() + expect(setScriptsMock).toBeCalledWith([ + { script: addressMeta.generateDefaultLockScript().toSDK(), scriptType: 'lock', walletId: 'walletId', blockNumber: '0xaa' }, + { script: addressMeta.generateACPLockScript().toSDK(), scriptType: 'lock', walletId: 'walletId', blockNumber: '0xaa' }, + { script: addressMeta.generateLegacyACPLockScript().toSDK(), scriptType: 'lock', walletId: 'walletId', blockNumber: '0xaa' }, + ]) + }) + it('set new script with start block number in wallet', async () => { + getScriptsMock.mockResolvedValue([]) + const addressMeta = AddressMeta.fromObject({ walletId: 'walletId', address, path: '', addressIndex: 10, addressType: 0, blake160: script.args }) + getWalletMinBlockNumberMock.mockResolvedValue({}) + walletGetAllMock.mockReturnValue([{ id: 'walletId', startBlockNumberInLight: '0xaa' }]) + const connect = new LightConnector([addressMeta], '') + //@ts-ignore + await connect.initSyncProgress() + expect(setScriptsMock).toBeCalledWith([ + { script: addressMeta.generateDefaultLockScript().toSDK(), scriptType: 'lock', walletId: 'walletId', blockNumber: '0xaa' }, + { script: addressMeta.generateACPLockScript().toSDK(), scriptType: 'lock', walletId: 'walletId', blockNumber: '0xaa' }, + { script: addressMeta.generateLegacyACPLockScript().toSDK(), scriptType: 'lock', walletId: 'walletId', blockNumber: '0xaa' }, + ]) + }) + }) + + describe('test initSync', () => { + it('pollingIndexer is false', async () => { + const connect = new LightConnector([], '') + //@ts-ignore + connect.synchronize = jest.fn() + //@ts-ignore + await connect.initSync() + expect(schedulerWaitMock).toBeCalledTimes(0) + }) + it('pollingIndexer is true', async () => { + const connect = new LightConnector([], '') + schedulerWaitMock.mockImplementation(() => { + connect.stop() + }) + //@ts-ignore + connect.pollingIndexer = true + //@ts-ignore + connect.synchronize = jest.fn() + //@ts-ignore + await connect.initSync() + expect(schedulerWaitMock).toBeCalledWith(5000) + }) + }) + + describe('test syncNextWithScript', () => { + it('no syncprogress in db', async () => { + getSyncStatusMock.mockResolvedValue(undefined) + const connect = new LightConnector([], '') + //@ts-ignore + await connect.syncNextWithScript({ script, scriptType: 'lock' }) + expect(getTransactionsMock).toBeCalledTimes(0) + }) + it('there is no tx in blockRange ', async () => { + const syncProgress = SyncProgress.fromObject({ script, scriptType: 'lock', walletId: 'walletId' }) + getSyncStatusMock.mockResolvedValue(syncProgress) + getTransactionsMock.mockResolvedValue({ txs: [], lastCursor: '0x' }) + const connect = new LightConnector([], '') + //@ts-ignore + await connect.syncNextWithScript({ script, scriptType: 'lock', blockRange: ['0xaa', '0xbb'] }) + expect(getTransactionsMock).toBeCalledWith({ script, blockRange: ['0xaa', '0xbb'], scriptType: 'lock' }, 'asc', '0x64', undefined) + expect(updateSyncStatusMock).toBeCalledWith(scriptHash, { blockStartNumber: 187, blockEndNumber: 187, cursor: undefined }) + }) + it('there are some txs in blockRange but no more', async () => { + const syncProgress = SyncProgress.fromObject({ script, scriptType: 'lock', walletId: 'walletId' }) + getSyncStatusMock.mockResolvedValue(syncProgress) + getTransactionsMock.mockResolvedValue({ txs: [{ txHash: '0xhash1' }], lastCursor: '0x' }) + const connect = new LightConnector([], '') + //@ts-ignore + connect.transactionsSubject = { next: jest.fn() } + //@ts-ignore + await connect.syncNextWithScript({ script, scriptType: 'lock', blockRange: ['0xaa', '0xbb'] }) + expect(connect.transactionsSubject.next).toBeCalledWith({ txHashes: ['0xhash1'], params: scriptHash }) + //@ts-ignore + expect(connect.syncInQueue.has(scriptHash)).toBeTruthy() + //@ts-ignore + expect(connect.syncInQueue.get(scriptHash)).toStrictEqual({ + blockStartNumber: 187, + blockEndNumber: 187, + cursor: undefined, + }) + }) + it('there are some txs in blockRange and more', async () => { + const syncProgress = SyncProgress.fromObject({ script, scriptType: 'lock', walletId: 'walletId' }) + getSyncStatusMock.mockResolvedValue(syncProgress) + getTransactionsMock.mockResolvedValue({ txs: [{ txHash: '0xhash1' }], lastCursor: '0xaa' }) + const connect = new LightConnector([], '') + //@ts-ignore + connect.transactionsSubject = { next: jest.fn() } + //@ts-ignore + await connect.syncNextWithScript({ script, scriptType: 'lock', blockRange: ['0xaa', '0xbb'] }) + expect(connect.transactionsSubject.next).toBeCalledWith({ txHashes: ['0xhash1'], params: scriptHash }) + //@ts-ignore + expect(connect.syncInQueue.has(scriptHash)).toBeTruthy() + //@ts-ignore + expect(connect.syncInQueue.get(scriptHash)).toStrictEqual({ + blockStartNumber: 170, + blockEndNumber: 187, + cursor: '0xaa', + }) + }) + }) + + describe('test connect', () => { + const mockFn = jest.fn() + beforeEach(() => { + mockFn.mockReset() + }) + it('connect success', async () => { + const connect = new LightConnector([], '') + //@ts-ignore + connect.initSync = mockFn + await connect.connect() + expect(mockFn).toBeCalledTimes(1) + }) + it('connect failed', async () => { + const connect = new LightConnector([], '') + //@ts-ignore + connect.initSync = mockFn + mockFn.mockImplementation(() => { throw new Error('error') }) + expect(connect.connect()).rejects.toThrowError(new Error('error')) + }) + }) + + describe('test stop', () => { + it('test stop', () => { + const connect = new LightConnector([], '') + //@ts-ignore + connect.pollingIndexer = true + connect.stop() + //@ts-ignore + expect(connect.pollingIndexer).toBeFalsy() + }) + }) + + describe('test notifyCurrentBlockNumberProcessed', () => { + it ('hash is not in syncInQueue', async () => { + const connect = new LightConnector([], '') + const mockFn = jest.fn() + //@ts-ignore + connect.subscribeSync = mockFn + await connect.notifyCurrentBlockNumberProcessed('0xhash1') + expect(updateSyncStatusMock).toBeCalledTimes(0) + expect(mockFn).toBeCalledTimes(1) + }) + it ('hash is in syncInQueue', async () => { + const connect = new LightConnector([], '') + //@ts-ignore + connect.subscribeSync = jest.fn() + //@ts-ignore + connect.syncInQueue.set('0xhash1', { blockStartNumber: 1, blockEndNumber: 1 }) + await connect.notifyCurrentBlockNumberProcessed('0xhash1') + //@ts-ignore + expect(connect.syncInQueue.has('0xhash1')).toBeFalsy() + expect(updateSyncStatusMock).toBeCalledWith('0xhash1', { blockStartNumber: 1, blockEndNumber: 1 }) + }) + }) +}) diff --git a/packages/neuron-wallet/tests/block-sync-renderer/queue.test.ts b/packages/neuron-wallet/tests/block-sync-renderer/queue.test.ts index f441c0cf27..a0d08a6c3a 100644 --- a/packages/neuron-wallet/tests/block-sync-renderer/queue.test.ts +++ b/packages/neuron-wallet/tests/block-sync-renderer/queue.test.ts @@ -3,7 +3,6 @@ import { Tip } from '@ckb-lumos/base' import { scriptToAddress } from '@nervosnetwork/ckb-sdk-utils' import { AddressType } from '../../src/models/keys/address' import SystemScriptInfo from '../../src/models/system-script-info' -import TransactionWithStatus from '../../src/models/chain/transaction-with-status' import { Address, AddressVersion } from '../../src/models/address' import Queue from '../../src/block-sync-renderer/sync/queue' import Transaction from '../../src/models/chain/transaction' @@ -30,6 +29,7 @@ const stubbedCheckAndGenerateAddressesFn = jest.fn() const stubbedNotifyCurrentBlockNumberProcessedFn = jest.fn() const stubbedUpdateCacheProcessedFn = jest.fn() const stubbedLoggerErrorFn = jest.fn() +const stubbedRPCCreateBatchRequestExecFn = jest.fn() const stubbedTxAddressFinder = jest.fn().mockImplementation((...args) => { stubbedTxAddressFinderConstructor(...args) @@ -60,19 +60,21 @@ const resetMocks = () => { stubbedUpdateCacheProcessedFn.mockReset() stubbedLoggerErrorFn.mockReset() stubbedProcessSend.mockReset() + stubbedRPCCreateBatchRequestExecFn.mockReset() } const generateFakeTx = (id: string, publicKeyHash: string = '0x') => { const fakeTx = new Transaction('') - fakeTx.hash = 'hash1' - fakeTx.inputs = [new Input(new OutPoint('0x' + id.repeat(64), '0'))] + fakeTx.hash = '0xhash1' + '0'.repeat(59) + fakeTx.inputs = [new Input(new OutPoint('0x' + id.repeat(64), '0'), '0x0')] fakeTx.outputs = [ Output.fromObject({ capacity: '1', lock: Script.fromObject({ hashType: ScriptHashType.Type, codeHash: '0x' + id.repeat(64), args: publicKeyHash }), }), ] - fakeTx.blockNumber = '1' + fakeTx.blockNumber = '0x1' + fakeTx.timestamp = '0x1880a3fa5bc' const fakeTxWithStatus = { transaction: fakeTx, txStatus: new TxStatus('0x' + id.repeat(64), TxStatusType.Committed), @@ -80,6 +82,14 @@ const generateFakeTx = (id: string, publicKeyHash: string = '0x') => { return fakeTxWithStatus } +const fakeBlockHeader = { + version: '0x0', + epoch: '0x0', + hash: `0x${'0'.repeat(64)}`, + parentHash: `0x${'0'.repeat(64)}`, + timestamp: '0x0', + number: '0x0', +} describe('queue', () => { let queue: Queue const fakeNodeUrl = 'http://fakenode:8114' @@ -113,7 +123,7 @@ describe('queue', () => { jest.useFakeTimers('legacy') stubbedBlockTipsSubject = new Subject() - stubbedTransactionsSubject = new Subject>() + stubbedTransactionsSubject = new Subject<{ txHashes: CKBComponents.Hash[], params: unknown }>() const stubbedIndexerConnector = jest.fn().mockImplementation((...args) => { stubbedIndexerConnectorConstructor(...args) return { @@ -159,6 +169,19 @@ describe('queue', () => { jest.doMock('../../src/block-sync-renderer/sync/indexer-cache-service', () => { return { updateCacheProcessed: stubbedUpdateCacheProcessedFn } }) + jest.doMock('../../src/utils/ckb-rpc', () => { + return { + generateRPC() { + return { + createBatchRequest() { + return { + exec: stubbedRPCCreateBatchRequestExecFn + } + } + } + } + } + }) const Queue = require('../../src/block-sync-renderer/sync/queue').default queue = new Queue(fakeNodeUrl, addresses) }) @@ -193,30 +216,41 @@ describe('queue', () => { }) describe('subscribes to IndexerConnector#transactionsSubject', () => { const fakeTxWithStatus1 = generateFakeTx('1', addresses[0].blake160) - const fakeTxWithStatus2 = generateFakeTx('2', addresses[0].blake160) + const fakeTxWithStatus2 = generateFakeTx('0', addresses[0].blake160) const fakeTxs = [fakeTxWithStatus2] describe('processes transactions from an event', () => { beforeEach(() => { stubbedAddressesFn.mockResolvedValue([true, addresses.map(addressMeta => addressMeta.address), []]) stubbedGetTransactionFn.mockResolvedValue(fakeTxWithStatus1) - stubbedTransactionsSubject.next(fakeTxs) + stubbedRPCCreateBatchRequestExecFn + .mockResolvedValueOnce(fakeTxs) + .mockResolvedValueOnce(fakeTxs.map(v => ({ ...fakeBlockHeader, timestamp: v.transaction.timestamp, number: v.transaction.blockNumber }))) + stubbedTransactionsSubject.next({ txHashes: fakeTxs.map(v => v.transaction.hash), params: fakeTxs[0].transaction.blockNumber }) }) describe('when saving transactions is succeeded', () => { beforeEach(flushPromises) it('check infos by hashes derived from addresses', () => { const lockHashes = ['0x1f2615a8dde4e28ca736ff763c2078aff990043f4cbf09eb4b3a58a140a0862d'] + const tx = Transaction.fromSDK(fakeTxWithStatus2.transaction.toSDK()) + tx.blockHash = fakeTxWithStatus2.txStatus.blockHash! + tx.blockNumber = BigInt(fakeTxWithStatus2.transaction.blockNumber!).toString() + tx.timestamp = BigInt(fakeTxWithStatus2.transaction.timestamp!).toString() expect(stubbedTxAddressFinderConstructor).toHaveBeenCalledWith( lockHashes, [new AssetAccountInfo().generateAnyoneCanPayScript(addressInfo.blake160).computeHash()], - fakeTxs[0].transaction, + tx, [Multisig.hash([addressInfo.blake160])] ) }) it('saves transactions', () => { for (const { transaction } of fakeTxs) { - expect(stubbedSaveFetchFn).toHaveBeenCalledWith(transaction) + const tx = Transaction.fromSDK(transaction.toSDK()) + tx.blockHash = fakeTxWithStatus2.txStatus.blockHash! + tx.blockNumber = BigInt(fakeTxWithStatus2.transaction.blockNumber!).toString() + tx.timestamp = BigInt(fakeTxWithStatus2.transaction.timestamp!).toString() + expect(stubbedSaveFetchFn).toHaveBeenCalledWith(tx) } }) it('checks and generate new addresses', () => { @@ -238,7 +272,10 @@ describe('queue', () => { const err = new Error() beforeEach(async () => { stubbedSaveFetchFn.mockRejectedValueOnce(err) - stubbedTransactionsSubject.next(fakeTxs) + stubbedRPCCreateBatchRequestExecFn + .mockResolvedValueOnce(fakeTxs) + .mockResolvedValueOnce(fakeTxs.map(v => ({ ...fakeBlockHeader, timestamp: v.transaction.timestamp, number: v.transaction.blockNumber }))) + stubbedTransactionsSubject.next({ txHashes: fakeTxs.map(v => v.transaction.hash), params: fakeTxs[0].transaction.blockNumber }) await flushPromises() }) it('handles the exception', async () => { diff --git a/packages/neuron-wallet/tests/controllers/export-debug.test.ts b/packages/neuron-wallet/tests/controllers/export-debug.test.ts index a6839c03f8..5fdb6503e6 100644 --- a/packages/neuron-wallet/tests/controllers/export-debug.test.ts +++ b/packages/neuron-wallet/tests/controllers/export-debug.test.ts @@ -73,6 +73,18 @@ jest.mock('../../src/services/settings', () => { } }) +jest.mock('../../src/services/light-runner', () => { + return { + CKBLightRunner: { + getInstance() { + return { + logPath: '' + } + } + } + } +}) + import { dialog } from 'electron' import logger from '../../src/utils/logger' import ExportDebugController from '../../src/controllers/export-debug' @@ -86,6 +98,7 @@ describe('Test ExportDebugController', () => { let showErrorBoxMock: any // controller methods let addBundledCKBLogMock: any + let addBundledCKBLightClientLogMock: any let addLogFilesMock: any let addStatusFileMock: any let archiveAppendMock: any @@ -95,10 +108,11 @@ describe('Test ExportDebugController', () => { showMessageBoxMock = jest.spyOn(dialog, 'showMessageBox') showErrorBoxMock = jest.spyOn(dialog, 'showErrorBox') addBundledCKBLogMock = jest.spyOn(exportDebugController, 'addBundledCKBLog') + addBundledCKBLightClientLogMock = jest.spyOn(exportDebugController, 'addBundledCKBLightClientLog') addLogFilesMock = jest.spyOn(exportDebugController, 'addLogFiles') addStatusFileMock = jest.spyOn(exportDebugController, 'addStatusFile') archiveAppendMock = jest.spyOn(exportDebugController.archive, 'append') - jest.spyOn(exportDebugController.archive, 'file') + jest.spyOn(exportDebugController.archive, 'file').mockReturnValue(undefined) jest.spyOn(exportDebugController.archive, 'pipe').mockImplementation(() => {}) jest.spyOn(logger, 'error') }) @@ -118,10 +132,11 @@ describe('Test ExportDebugController', () => { }) it('should call required methods', () => { - expect.assertions(8) + expect.assertions(9) expect(showSaveDialogMock).toHaveBeenCalled() expect(addBundledCKBLogMock).toHaveBeenCalled() + expect(addBundledCKBLightClientLogMock).toHaveBeenCalled() expect(addLogFilesMock).toHaveBeenCalled() expect(addStatusFileMock).toHaveBeenCalled() @@ -141,11 +156,12 @@ describe('Test ExportDebugController', () => { }) it('should not call required methods', () => { - expect.assertions(8) + expect.assertions(9) expect(showSaveDialogMock).toHaveBeenCalled() expect(addBundledCKBLogMock).not.toHaveBeenCalled() + expect(addBundledCKBLightClientLogMock).not.toHaveBeenCalled() expect(addLogFilesMock).not.toHaveBeenCalled() expect(addStatusFileMock).not.toHaveBeenCalled() expect(archiveAppendMock).not.toHaveBeenCalled() diff --git a/packages/neuron-wallet/tests/controllers/multisig.test.ts b/packages/neuron-wallet/tests/controllers/multisig.test.ts index fbc830c0dc..6b793af56e 100644 --- a/packages/neuron-wallet/tests/controllers/multisig.test.ts +++ b/packages/neuron-wallet/tests/controllers/multisig.test.ts @@ -18,6 +18,15 @@ jest.mock('electron', () => ({ getFocusedWindow: jest.fn(), }, })) +jest.mock('services/wallets', () => ({ + getInstance() { + return { + getCurrent() { + return jest.fn() + } + } + } +})) jest.mock('../../src/services/multisig') const MultiSigServiceMock = MultisigService as jest.MockedClass diff --git a/packages/neuron-wallet/tests/controllers/offline-sign.test.ts b/packages/neuron-wallet/tests/controllers/offline-sign.test.ts index 6cee3aabdc..b3cdd1d622 100644 --- a/packages/neuron-wallet/tests/controllers/offline-sign.test.ts +++ b/packages/neuron-wallet/tests/controllers/offline-sign.test.ts @@ -151,15 +151,7 @@ describe('OfflineSignController', () => { jest.doMock('services/node', () => { return class { static getInstance() { - return { - ckb: { - rpc: { - paramsFormatter: { - toRawTransaction: (tx: any) => tx, - }, - }, - }, - } + return {} } } }) @@ -193,6 +185,18 @@ describe('OfflineSignController', () => { getMultisigStatus: getMultisigStatusMock, })) + jest.doMock('../../src/utils/ckb-rpc', () => { + return { + generateRPC() { + return { + paramsFormatter: { + toRawTransaction: (tx: any) => tx + } + } + } + } + }) + const OfflineSignController = require('../../src/controllers/offline-sign').default offlineSignController = new OfflineSignController() }) diff --git a/packages/neuron-wallet/tests/controllers/sync-api.test.ts b/packages/neuron-wallet/tests/controllers/sync-api.test.ts index 4d34ced8d9..ec06ed61d0 100644 --- a/packages/neuron-wallet/tests/controllers/sync-api.test.ts +++ b/packages/neuron-wallet/tests/controllers/sync-api.test.ts @@ -50,6 +50,9 @@ jest.doMock('services/ckb-runner', () => ({ jest.mock('undici', () => ({ request: () => jest.fn()(), })) +jest.mock('services/multisig', () => ({ + syncMultisigOutput: () => jest.fn() +})) describe('SyncApiController', () => { const emitter = new Emitter() @@ -134,11 +137,9 @@ describe('SyncApiController', () => { bestKnownBlockTimestamp: `0x${bestKnownBlockTimestamp.toString(16)}`, }) stubbedNodeGetInstance.mockReturnValue({ - ckb: { - node: { - url: fakeNodeUrl, - }, - }, + get nodeUrl() { + return fakeNodeUrl + } }) stubbedGetTipHeader.mockResolvedValue({ timestamp: '180000' }) }) @@ -360,11 +361,9 @@ describe('SyncApiController', () => { describe('with another node url', () => { beforeEach(async () => { stubbedNodeGetInstance.mockReturnValue({ - ckb: { - node: { - url: 'anotherfakeurl', - }, - }, + get nodeUrl() { + return 'anotherfakeurl' + } }) await sendFakeCacheBlockTipEvent(newFakeState) @@ -472,11 +471,9 @@ describe('SyncApiController', () => { describe('when node url changed', () => { beforeEach(async () => { stubbedNodeGetInstance.mockImplementation(() => ({ - ckb: { - node: { - url: 'http://diffurl', - }, - }, + get nodeUrl() { + return 'http://diffurl' + } })) await sendFakeCacheBlockTipEvent(fakeState3) }) diff --git a/packages/neuron-wallet/tests/models/chain/live-cell.test.ts b/packages/neuron-wallet/tests/models/chain/live-cell.test.ts index f60398acc5..7e8c199ada 100644 --- a/packages/neuron-wallet/tests/models/chain/live-cell.test.ts +++ b/packages/neuron-wallet/tests/models/chain/live-cell.test.ts @@ -1,6 +1,6 @@ import Script, { ScriptHashType } from '../../../src/models/chain/script' -import { LumosCell } from '../../../src/block-sync-renderer/sync/indexer-connector' -import LiveCell from '../../../src/models/chain/live-cell' +import { LumosCell } from '../../../src/block-sync-renderer/sync/connector' +import LiveCell from "../../../src/models/chain/live-cell" describe('LiveCell Test', () => { const INITIAL_DATA = { diff --git a/packages/neuron-wallet/tests/services/ckb-runner.test.ts b/packages/neuron-wallet/tests/services/ckb-runner.test.ts index e4fe206a45..fd2a07f6f8 100644 --- a/packages/neuron-wallet/tests/services/ckb-runner.test.ts +++ b/packages/neuron-wallet/tests/services/ckb-runner.test.ts @@ -1,5 +1,6 @@ import { EventEmitter } from 'typeorm/platform/PlatformTools' import path from 'path' +import { scheduler } from 'timers/promises' const stubbedChildProcess = jest.fn() const stubbedSpawn = jest.fn() @@ -8,6 +9,7 @@ const stubbedExistsSync = jest.fn() const stubbedLoggerInfo = jest.fn() const stubbedLoggerError = jest.fn() const stubbedLoggerLog = jest.fn() +const resetSyncTaskQueueAsyncPushMock = jest.fn() const stubbedProcess: any = {} @@ -18,6 +20,7 @@ const resetMocks = () => { stubbedLoggerInfo.mockReset() stubbedLoggerError.mockReset() stubbedLoggerLog.mockReset() + resetSyncTaskQueueAsyncPushMock.mockReset() } jest.doMock('child_process', () => { @@ -72,6 +75,11 @@ jest.mock('../../src/block-sync-renderer', () => ({ jest.mock('../../src/services/indexer', () => ({ cleanOldIndexerData: jest.fn(), })) +jest.doMock('../../src/block-sync-renderer', () => ({ + resetSyncTaskQueue: { + asyncPush: resetSyncTaskQueueAsyncPushMock + } +})) const { startCkbNode, stopCkbNode, @@ -88,6 +96,7 @@ describe('ckb runner', () => { stubbedCkb.stderr = new EventEmitter() stubbedCkb.stdout = new EventEmitter() stubbedSpawn.mockReturnValue(stubbedCkb) + resetSyncTaskQueueAsyncPushMock.mockReturnValue('') }) ;[ { platform: 'win32', platformPath: 'win' }, @@ -122,7 +131,7 @@ describe('ckb runner', () => { expect(stubbedSpawn).toHaveBeenCalledWith( expect.stringContaining(path.join(platformPath, 'ckb')), ['run', '-C', ckbDataPath, '--indexer'], - { stdio: ['ignore', 'pipe', 'pipe'] } + { stdio: ['ignore', 'ignore', 'pipe'] } ) }) }) @@ -156,7 +165,7 @@ describe('ckb runner', () => { expect(stubbedSpawn).toHaveBeenCalledWith( expect.stringContaining(path.join(platformPath, 'ckb')), ['run', '-C', ckbDataPath, '--indexer'], - { stdio: ['ignore', 'pipe', 'pipe'] } + { stdio: ['ignore', 'ignore', 'pipe'] } ) }) }) @@ -178,14 +187,25 @@ describe('ckb runner', () => { describe('with assume valid target', () => { beforeEach(async () => { + stubbedProcess.platform = platform app.isPackaged = true stubbedProcess.env = { CKB_NODE_ASSUME_VALID_TARGET: '0x' + '0'.repeat(64) } stubbedExistsSync.mockReturnValue(true) await startCkbNode() }) - afterEach(() => { + afterEach(async () => { app.isPackaged = false stubbedProcess.env = {} + const promise = stopCkbNode() + stubbedCkb.emit('close') + await promise + }) + it('runs ckb binary', () => { + expect(stubbedSpawn).toHaveBeenCalledWith( + expect.stringContaining(path.join('bin', 'ckb')), + ['run', '-C', ckbDataPath, '--indexer', "--assume-valid-target", '0x' + '0'.repeat(64)], + { stdio: ['ignore', 'pipe', 'pipe'] } + ) }) it('is Looking valid target', () => { stubbedCkb.stdout.emit( @@ -193,21 +213,15 @@ describe('ckb runner', () => { `can't find assume valid target temporarily, hash: Byte32(0x${'0'.repeat(64)})` ) expect(getLookingValidTargetStatus()).toBeTruthy() - stubbedCkb.emit('close') }) it('is Looking valid target', async () => { stubbedCkb.stdout.emit( 'data', `can't find assume valid target temporarily, hash: Byte32(0x${'0'.repeat(64)})` ) - await new Promise(resolve => - setTimeout(() => { - resolve(undefined) - }, 11000) - ) + await scheduler.wait(11000) stubbedCkb.stdout.emit('data', `had find valid target`) expect(getLookingValidTargetStatus()).toBeFalsy() - stubbedCkb.emit('close') }, 15000) it('ckb has closed', async () => { stubbedCkb.stdout.emit( diff --git a/packages/neuron-wallet/tests/services/indexer.test.ts b/packages/neuron-wallet/tests/services/indexer.test.ts index ad6aeefe68..0d8872c9fb 100644 --- a/packages/neuron-wallet/tests/services/indexer.test.ts +++ b/packages/neuron-wallet/tests/services/indexer.test.ts @@ -4,6 +4,7 @@ const existsSyncMock = jest.fn() const rmSyncMock = jest.fn() const isCkbNodeExternalMock = jest.fn() const stopMonitorMock = jest.fn() +const checkNodeMock = jest.fn() jest.mock('fs', () => { return { @@ -26,6 +27,9 @@ jest.mock('../../src/services/settings', () => { set indexerDataPath(value: string) { setIndexerDataPathMock(value) }, + get ckbDataPath() { + return jest.fn().mockReturnValue('')() + } } } } @@ -35,9 +39,17 @@ jest.mock('../../src/utils/logger', () => ({ debug: () => jest.fn(), })) -jest.mock('../../src/models/synced-block-number', () => ({})) +jest.mock('../../src/models/synced-block-number', () => { + return function() { + return { + setNextBlock: jest.fn() + } + } +}) -jest.mock('../../src/database/chain', () => ({})) +jest.mock('../../src/database/chain', () => ({ + clean: () => jest.fn() +})) jest.mock('../../src/services/monitor', () => { function mockMonitor() {} @@ -51,10 +63,18 @@ jest.mock('../../src/services/node', () => ({ get isCkbNodeExternal() { return isCkbNodeExternalMock() }, + checkNode: checkNodeMock, } }, })) +const resetSyncTaskQueueAsyncPushMock = jest.fn() +jest.mock('../../src/block-sync-renderer', () => ({ + resetSyncTaskQueue: { + asyncPush: () => resetSyncTaskQueueAsyncPushMock() + } +})) + describe('test IndexerService', () => { beforeEach(() => { existsSyncMock.mockReset() @@ -86,15 +106,32 @@ describe('test IndexerService', () => { }) describe('test clear cache', () => { - it('is external ckb node', () => { + beforeEach(() => { + resetSyncTaskQueueAsyncPushMock.mockReset() + }) + it('is external ckb node', async () => { isCkbNodeExternalMock.mockReturnValue(true) - IndexerService.clearCache() + await IndexerService.clearCache() + expect(stopMonitorMock).toBeCalledTimes(0) + expect(resetSyncTaskQueueAsyncPushMock).toBeCalledTimes(1) + }) + it('is internal ckb node', async () => { + isCkbNodeExternalMock.mockReturnValue(false) + await IndexerService.clearCache() expect(stopMonitorMock).toBeCalledTimes(0) + expect(resetSyncTaskQueueAsyncPushMock).toBeCalledTimes(1) }) - it('is internal ckb node', () => { + it('clear indexer data with internal ckb node', async () => { isCkbNodeExternalMock.mockReturnValue(false) - IndexerService.clearCache() + await IndexerService.clearCache(true) expect(stopMonitorMock).toBeCalledTimes(1) + expect(resetSyncTaskQueueAsyncPushMock).toBeCalledTimes(1) + }) + it('clear indexer data with external ckb node', async () => { + isCkbNodeExternalMock.mockReturnValue(true) + await IndexerService.clearCache(true) + expect(stopMonitorMock).toBeCalledTimes(0) + expect(resetSyncTaskQueueAsyncPushMock).toBeCalledTimes(1) }) }) }) diff --git a/packages/neuron-wallet/tests/services/light-runner.test.ts b/packages/neuron-wallet/tests/services/light-runner.test.ts new file mode 100644 index 0000000000..f2b1fdf74c --- /dev/null +++ b/packages/neuron-wallet/tests/services/light-runner.test.ts @@ -0,0 +1,297 @@ +import EventEmitter from 'events' +import path from 'path' + +const lightRunnerDirpath = path.join(__dirname, '../../src/services') +const mockFn = jest.fn() +const getAppPathMock = jest.fn() +const isPackagedMock = jest.fn() +const platformMock = jest.fn() +const joinMock = jest.fn() +const dirnameMock = jest.fn() +const resolveMock = jest.fn() +const lightDataPathMock = jest.fn() +const existsSyncMock = jest.fn() +const readFileSyncMock = jest.fn() +const mkdirSyncMock = jest.fn() +const writeFileSyncMock = jest.fn() +const createWriteStreamMock = jest.fn() +const spawnMock = jest.fn() +const loggerErrorMock = jest.fn() +const loggerInfoMock = jest.fn() +const transportsGetFileMock = jest.fn() +const cleanMock = jest.fn() +const resetSyncTaskQueueAsyncPushMock = jest.fn() + +function resetMock() { + mockFn.mockReset() + getAppPathMock.mockReset() + isPackagedMock.mockReset() + platformMock.mockReset() + joinMock.mockReset() + dirnameMock.mockReset() + resolveMock.mockReset() + lightDataPathMock.mockReset() + existsSyncMock.mockReset() + readFileSyncMock.mockReset() + mkdirSyncMock.mockReset() + writeFileSyncMock.mockReset() + createWriteStreamMock.mockReset() + spawnMock.mockReset() + loggerErrorMock.mockReset() + loggerInfoMock.mockReset() + transportsGetFileMock.mockReset() + cleanMock.mockReset() + resetSyncTaskQueueAsyncPushMock.mockReset() +} + +jest.doMock('../../src/env', () => ({ + app: { + getAppPath: getAppPathMock, + get isPackaged() { + return isPackagedMock() + }, + } +})) + +jest.doMock('../../src/utils/logger', () => ({ + info: loggerInfoMock, + error: loggerErrorMock, + transports: { + file: { + getFile: transportsGetFileMock + } + } +})) + +jest.doMock('../../src/services/settings', () => ({ + getInstance() { + return { + get testnetLightDataPath() { return lightDataPathMock() } + } + } +})) + +jest.doMock('../../src/database/chain', () => ({ + clean: cleanMock +})) + +jest.doMock('../../src/block-sync-renderer', () => ({ + resetSyncTaskQueue: { + asyncPush: resetSyncTaskQueueAsyncPushMock + } +})) + +jest.doMock('process', () => ({ + get platform() { + return platformMock() + }, +})) + +jest.doMock('path', () => ({ + join: joinMock, + dirname: dirnameMock, + resolve: resolveMock, +})) + +jest.doMock('fs', () => ({ + existsSync: existsSyncMock, + readFileSync: readFileSyncMock, + mkdirSync: mkdirSyncMock, + writeFileSync: writeFileSyncMock, + createWriteStream: createWriteStreamMock +})) + +jest.doMock('child_process', () => ({ + spawn: spawnMock, +})) + +const { CKBLightRunner } = require('../../src/services/light-runner') + +describe('test light runner', () => { + beforeEach(() => { + transportsGetFileMock.mockReturnValue({ path: ''}) + createWriteStreamMock.mockReturnValue({ write() {} }) + }) + afterEach(() => { + resetMock() + }) + + describe('test getInstance', () => { + it('get from getInstance is same', () => { + expect(CKBLightRunner.getInstance()).toBe(CKBLightRunner.getInstance()) + }) + }) + + describe('test binary', () => { + it('is packaged and is win', () => { + const tmp = CKBLightRunner.getInstance().platform + CKBLightRunner.getInstance().platform = mockFn + isPackagedMock.mockReturnValue(true) + getAppPathMock.mockReturnValue('apppath') + resolveMock.mockReturnValue('prefixpath') + joinMock.mockReturnValue('joinpath') + mockFn.mockReturnValue('win') + dirnameMock.mockReturnValue('dir') + expect(CKBLightRunner.getInstance().binary).toBe('prefixpath.exe') + expect(dirnameMock).toBeCalledWith('apppath') + expect(joinMock).toBeCalledWith('dir', '..', './bin') + expect(resolveMock).toBeCalledWith('joinpath', './ckb-light-client') + CKBLightRunner.getInstance().platform = tmp + }) + it('is packaged and is mac', () => { + const tmp = CKBLightRunner.getInstance().platform + CKBLightRunner.getInstance().platform = mockFn + isPackagedMock.mockReturnValue(true) + resolveMock.mockReturnValue('prefixpath') + mockFn.mockReturnValue('mac') + expect(CKBLightRunner.getInstance().binary).toBe('prefixpath') + CKBLightRunner.getInstance().platform = tmp + }) + it('is packaged and is linux', () => { + const tmp = CKBLightRunner.getInstance().platform + CKBLightRunner.getInstance().platform = mockFn + isPackagedMock.mockReturnValue(true) + resolveMock.mockReturnValue('prefixpath') + mockFn.mockReturnValue('linux') + expect(CKBLightRunner.getInstance().binary).toBe('prefixpath') + CKBLightRunner.getInstance().platform = tmp + }) + it('is not packaged', () => { + const tmp = CKBLightRunner.getInstance().platform + CKBLightRunner.getInstance().platform = mockFn + isPackagedMock.mockReturnValue(false) + resolveMock.mockReturnValue('prefixpath') + joinMock.mockReturnValue('joinpath') + mockFn.mockReturnValue('mac') + expect(CKBLightRunner.getInstance().binary).toBe('prefixpath') + expect(dirnameMock).toBeCalledTimes(0) + expect(getAppPathMock).toBeCalledTimes(0) + expect(joinMock).toBeCalledWith(lightRunnerDirpath, '../../bin') + expect(resolveMock).toBeCalledWith('joinpath', `./${CKBLightRunner.getInstance().platform()}`, './ckb-light-client') + CKBLightRunner.getInstance().platform = tmp + }) + }) + + describe('test templateConfigFile', () => { + it('app is packaged', () => { + isPackagedMock.mockReturnValue(true) + dirnameMock.mockReturnValue('dir') + joinMock.mockReturnValue('join') + resolveMock.mockReturnValue('resolve') + expect(CKBLightRunner.getInstance().templateConfigFile).toBe('resolve') + expect(joinMock).toBeCalledWith('dir', '..', './light') + expect(resolveMock).toBeCalledWith('join', './ckb_light.toml') + }) + it('app is not packaged', () => { + isPackagedMock.mockReturnValue(false) + dirnameMock.mockReturnValue('dir') + joinMock.mockReturnValue('join') + resolveMock.mockReturnValue('resolve') + expect(CKBLightRunner.getInstance().templateConfigFile).toBe('resolve') + expect(joinMock).toBeCalledWith(lightRunnerDirpath, '../../light') + expect(resolveMock).toBeCalledWith('join', './ckb_light.toml') + }) + }) + + describe('test configFile', () => { + lightDataPathMock.mockReturnValue('lightDataPath') + CKBLightRunner.getInstance().configFile + expect(resolveMock).toBeCalledWith('lightDataPath', './ckb_light.toml') + }) + + describe('test initConfig', () => { + it('configFile is exist', () => { + existsSyncMock.mockReturnValue(true) + CKBLightRunner.getInstance().initConfig() + expect(readFileSyncMock).toBeCalledTimes(0) + }) + it('configFile is not exist replace store path and network path', () => { + existsSyncMock.mockReturnValue(false) + readFileSyncMock.mockReturnValue('[store]\npath=aaa\n[network]\npath=bbb') + lightDataPathMock.mockReturnValue('light-data-path') + joinMock.mockReturnValue('new-path') + resolveMock.mockReturnValue('config') + CKBLightRunner.getInstance().initConfig() + expect(mkdirSyncMock).toBeCalledWith('light-data-path', { recursive: true }) + expect(writeFileSyncMock).toBeCalledWith('config', '[store]\npath = "new-path"\n[network]\npath = "new-path"') + }) + }) + + describe('test start', () => { + it('when runnerProcess is not undefined', async () => { + const tmp = CKBLightRunner.getInstance().stop + CKBLightRunner.getInstance().stop = mockFn + CKBLightRunner.getInstance().runnerProcess = {} + const eventEmitter = new EventEmitter() + spawnMock.mockReturnValue(eventEmitter) + existsSyncMock.mockReturnValue(true) + await CKBLightRunner.getInstance().start() + expect(mockFn).toBeCalledTimes(1) + CKBLightRunner.getInstance().stop = tmp + }) + it('when runnerProcess is undefined', async () => { + const tmp = CKBLightRunner.getInstance().stop + CKBLightRunner.getInstance().stop = mockFn + CKBLightRunner.getInstance().runnerProcess = undefined + const eventEmitter = new EventEmitter() + spawnMock.mockReturnValue(eventEmitter) + existsSyncMock.mockReturnValue(true) + await CKBLightRunner.getInstance().start() + expect(mockFn).toBeCalledTimes(0) + CKBLightRunner.getInstance().stop = tmp + }) + it('when runnerProcess is undefined and on error', async () => { + CKBLightRunner.getInstance().runnerProcess = undefined + const eventEmitter = new EventEmitter() + spawnMock.mockReturnValue(eventEmitter) + existsSyncMock.mockReturnValue(true) + await CKBLightRunner.getInstance().start() + expect(CKBLightRunner.getInstance().runnerProcess).toBeDefined() + expect(mockFn).toBeCalledTimes(0) + eventEmitter.emit('error', 'errorInfo') + expect(loggerErrorMock).toBeCalledWith('CKB Light Runner:\trun fail:', 'errorInfo') + expect(CKBLightRunner.getInstance().runnerProcess).toBeUndefined() + }) + it('when runnerProcess is undefined and on close', async () => { + CKBLightRunner.getInstance().runnerProcess = undefined + const eventEmitter = new EventEmitter() + spawnMock.mockReturnValue(eventEmitter) + existsSyncMock.mockReturnValue(true) + await CKBLightRunner.getInstance().start() + expect(CKBLightRunner.getInstance().runnerProcess).toBeDefined() + expect(mockFn).toBeCalledTimes(0) + eventEmitter.emit('close', 'closeInfo') + expect(loggerInfoMock).toBeCalledWith('CKB Light Runner:\tprocess closed') + expect(CKBLightRunner.getInstance().runnerProcess).toBeUndefined() + }) + it('when runnerProcess is undefined and on stderr', async () => { + CKBLightRunner.getInstance().runnerProcess = undefined + const eventEmitter: EventEmitter & { stderr?: EventEmitter } = new EventEmitter() + eventEmitter.stderr = new EventEmitter() + spawnMock.mockReturnValue(eventEmitter) + existsSyncMock.mockReturnValue(true) + await CKBLightRunner.getInstance().start() + expect(CKBLightRunner.getInstance().runnerProcess).toBeDefined() + expect(mockFn).toBeCalledTimes(0) + eventEmitter.stderr.emit('data', 'error-data') + expect(loggerErrorMock).toBeCalledWith('CKB Light Runner:\trun fail:', 'error-data') + expect(CKBLightRunner.getInstance().runnerProcess).toBeDefined() + }) + }) + + describe('test stop', () => { + it('runnerProcess is undefined', async () => { + CKBLightRunner.getInstance().runnerProcess = undefined + await CKBLightRunner.getInstance().stop() + }) + it('runnerProcess is defined', async () => { + const emitter: EventEmitter & { kill?: Function } = new EventEmitter() + emitter.kill = mockFn + CKBLightRunner.getInstance().runnerProcess = emitter + mockFn.mockImplementation(() => { emitter.emit('close') }) + await CKBLightRunner.getInstance().stop() + expect(mockFn).toBeCalledWith() + expect(CKBLightRunner.getInstance().runnerProcess).toBeUndefined() + }) + }) +}) \ No newline at end of file diff --git a/packages/neuron-wallet/tests/services/networks.test.ts b/packages/neuron-wallet/tests/services/networks.test.ts index d9921dd8bd..f35bcdae93 100644 --- a/packages/neuron-wallet/tests/services/networks.test.ts +++ b/packages/neuron-wallet/tests/services/networks.test.ts @@ -37,7 +37,7 @@ describe(`Unit tests of networks service`, () => { it(`has preset networks`, () => { const networks = service.getAll() - expect(networks.length).toBe(1) + expect(networks.length).toBe(2) expect(networks[0].id).toEqual('mainnet') }) @@ -126,10 +126,10 @@ describe(`Unit tests of networks service`, () => { const prevCurrentID = service.getCurrentID() const prevNetworks = service.getAll() expect(prevCurrentID).toBe(network.id) - expect(prevNetworks.map(n => n.id)).toEqual(['mainnet', network.id]) + expect(prevNetworks.map(n => n.id)).toEqual(['mainnet', 'light_client_testnet', network.id]) await service.delete(prevCurrentID || '') const currentNetworks = service.getAll() - expect(currentNetworks.map(n => n.id)).toEqual(['mainnet']) + expect(currentNetworks.map(n => n.id)).toEqual(['mainnet', 'light_client_testnet']) const currentID = service.getCurrentID() expect(currentID).toBe('mainnet') }) diff --git a/packages/neuron-wallet/tests/services/node.test.ts b/packages/neuron-wallet/tests/services/node.test.ts index 160c21afbc..5cf5b39d24 100644 --- a/packages/neuron-wallet/tests/services/node.test.ts +++ b/packages/neuron-wallet/tests/services/node.test.ts @@ -1,14 +1,17 @@ import { distinctUntilChanged, sampleTime, flatMap, delay, retry } from 'rxjs/operators' import { BUNDLED_CKB_URL, START_WITHOUT_INDEXER } from '../../src/utils/const' +import { NetworkType } from '../../src/models/network' describe('NodeService', () => { let nodeService: any const stubbedStartCKBNode = jest.fn() + const stubbedStopCkbNode = jest.fn() + const stubbedStartLightNode = jest.fn() + const stubbedStopLightNode = jest.fn() const stubbedConnectionStatusSubjectNext = jest.fn() const stubbedCKBSetNode = jest.fn() const stubbedGetTipBlockNumber = jest.fn() const stubbedRxjsDebounceTime = jest.fn() - const stubbedCKB = jest.fn() const stubbedCurrentNetworkIDSubjectSubscribe = jest.fn() const stubbedNetworsServiceGet = jest.fn() const stubbedLoggerInfo = jest.fn() @@ -25,14 +28,13 @@ describe('NodeService', () => { const getLocalNodeInfoMock = jest.fn() const fakeHTTPUrl = 'http://fakeurl' - const fakeHTTPSUrl = 'https://fakeurl' const resetMocks = () => { stubbedStartCKBNode.mockReset() + stubbedStopCkbNode.mockReset() stubbedConnectionStatusSubjectNext.mockReset() stubbedCKBSetNode.mockReset() stubbedGetTipBlockNumber.mockReset() - stubbedCKB.mockReset() stubbedCurrentNetworkIDSubjectSubscribe.mockReset() stubbedNetworsServiceGet.mockReset() stubbedLoggerInfo.mockReset() @@ -47,6 +49,8 @@ describe('NodeService', () => { rpcRequestMock.mockReset() getChainMock.mockReset() getLocalNodeInfoMock.mockReset() + stubbedStartLightNode.mockReset() + stubbedStopLightNode.mockReset() } beforeEach(() => { @@ -56,6 +60,7 @@ describe('NodeService', () => { jest.doMock('../../src/services/ckb-runner', () => { return { startCkbNode: stubbedStartCKBNode, + stopCkbNode: stubbedStopCkbNode, } }) jest.doMock('../../src/services/networks', () => { @@ -80,8 +85,14 @@ describe('NodeService', () => { }, } }) - jest.doMock('@nervosnetwork/ckb-sdk-core', () => { - return stubbedCKB + jest.doMock('../../src/utils/ckb-rpc', () => { + return { + generateRPC() { + return { + getTipBlockNumber: stubbedGetTipBlockNumber, + } + } + } }) jest.doMock('rxjs/operators', () => { return { @@ -136,7 +147,20 @@ describe('NodeService', () => { return function () { return { getChain: getChainMock, - getLocalNodeInfo: getLocalNodeInfoMock, + localNodeInfo: getLocalNodeInfoMock + } + } + }) + + jest.doMock('../../src/services/light-runner', () => { + return { + CKBLightRunner: { + getInstance() { + return { + start: stubbedStartLightNode, + stop: stubbedStopLightNode, + } + } } } }) @@ -151,16 +175,6 @@ describe('NodeService', () => { describe('when targets external node', () => { beforeEach(async () => { - stubbedCKB.mockImplementation(() => ({ - setNode: stubbedCKBSetNode, - rpc: { - getTipBlockNumber: stubbedGetTipBlockNumber, - }, - node: { - url: fakeHTTPUrl, - }, - })) - const NodeService = require('../../src/services/node').default nodeService = new NodeService() @@ -168,7 +182,7 @@ describe('NodeService', () => { }) it('emits disconnected event in ConnectionStatusSubject', () => { expect(stubbedConnectionStatusSubjectNext).toHaveBeenCalledWith({ - url: fakeHTTPUrl, + url: nodeService.nodeUrl, connected: false, isBundledNode: false, startedBundledNode: false, @@ -176,6 +190,7 @@ describe('NodeService', () => { }) describe('advance to next event', () => { beforeEach(async () => { + nodeService.setNetwork(fakeHTTPUrl) stubbedConnectionStatusSubjectNext.mockReset() stubbedGetTipBlockNumber.mockResolvedValueOnce('0x1') jest.advanceTimersByTime(1000) @@ -208,16 +223,6 @@ describe('NodeService', () => { }) describe('when targets bundled node', () => { beforeEach(async () => { - stubbedCKB.mockImplementation(() => ({ - setNode: stubbedCKBSetNode, - rpc: { - getTipBlockNumber: stubbedGetTipBlockNumber, - }, - node: { - url: BUNDLED_CKB_URL, - }, - })) - const NodeService = require('../../src/services/node').default nodeService = new NodeService() nodeService.verifyNodeVersion = () => {} @@ -228,20 +233,21 @@ describe('NodeService', () => { describe('when node starts', () => { beforeEach(async () => { stubbedStartCKBNode.mockResolvedValue(true) - await nodeService.tryStartNodeOnDefaultURI() + await nodeService.startNode() jest.advanceTimersByTime(1000) }) it('emits disconnected event in ConnectionStatusSubject', () => { - expect(stubbedConnectionStatusSubjectNext).toHaveBeenCalledWith({ - url: BUNDLED_CKB_URL, + expect(stubbedConnectionStatusSubjectNext).toHaveBeenLastCalledWith({ + url: nodeService.nodeUrl, connected: false, - isBundledNode: true, + isBundledNode: false, startedBundledNode: false, }) }) describe('advance to next event', () => { beforeEach(async () => { + nodeService.setNetwork(BUNDLED_CKB_URL) stubbedConnectionStatusSubjectNext.mockReset() stubbedGetTipBlockNumber.mockResolvedValueOnce('0x1') jest.advanceTimersByTime(1000) @@ -275,36 +281,37 @@ describe('NodeService', () => { describe('when node failed to start', () => { beforeEach(async () => { stubbedStartCKBNode.mockRejectedValue(new Error()) - await nodeService.tryStartNodeOnDefaultURI() - }) + await nodeService.startNode() + }); it('logs error', () => { expect(stubbedLoggerInfo).toHaveBeenCalledWith('CKB: fail to start bundled CKB with error:') expect(stubbedLoggerError).toHaveBeenCalledWith(new Error()) }) it('emits disconnected event in ConnectionStatusSubject', () => { expect(stubbedConnectionStatusSubjectNext).toHaveBeenCalledWith({ - url: BUNDLED_CKB_URL, + url: nodeService.nodeUrl, connected: false, - isBundledNode: true, + isBundledNode: false, startedBundledNode: false, }) }) + }); + describe('start light node', () => { + beforeEach(() => { + stubbedNetworsServiceGet.mockReset() + }) + it('start light node', async () => { + stubbedNetworsServiceGet.mockReturnValueOnce({type: NetworkType.Light}) + await nodeService.startNode() + expect(stubbedStartLightNode).toBeCalled() + expect(stubbedStopCkbNode).toBeCalled() + }) }) - }) + }); describe('CurrentNetworkIDSubject#subscribe', () => { let eventCallback: any const stubbedTipNumberSubjectCallback = jest.fn() beforeEach(async () => { - stubbedCKB.mockImplementation(() => ({ - setNode: stubbedCKBSetNode, - rpc: { - getTipBlockNumber: stubbedGetTipBlockNumber, - }, - node: { - url: fakeHTTPUrl, - }, - })) - const NodeService = require('../../src/services/node').default nodeService = new NodeService() nodeService.tipNumberSubject.subscribe(stubbedTipNumberSubjectCallback) @@ -314,7 +321,7 @@ describe('NodeService', () => { }) it('emits disconnected event in ConnectionStatusSubject', () => { expect(stubbedConnectionStatusSubjectNext).toHaveBeenCalledWith({ - url: fakeHTTPUrl, + url: nodeService.nodeUrl, connected: false, isBundledNode: false, startedBundledNode: false, @@ -330,7 +337,8 @@ describe('NodeService', () => { nodeService.ckb.node.url = bundledNodeUrl }) stubbedStartCKBNode.mockResolvedValue(true) - stubbedNetworsServiceGet.mockReturnValue({ remote: bundledNodeUrl }) + stubbedNetworsServiceGet.mockReturnValue({remote: bundledNodeUrl}) + getLocalNodeInfoMock.mockRejectedValue('not start') await nodeService.tryStartNodeOnDefaultURI() await eventCallback({ currentNetworkID: 'network1' }) @@ -347,11 +355,8 @@ describe('NodeService', () => { describe('switches to other network', () => { beforeEach(async () => { stubbedConnectionStatusSubjectNext.mockReset() - stubbedCKBSetNode.mockImplementation(() => { - nodeService.ckb.node.url = fakeHTTPUrl - }) - - await eventCallback({ currentNetworkID: 'network2' }) + stubbedNetworsServiceGet.mockReturnValue({remote: fakeHTTPUrl}) + await eventCallback({currentNetworkID: 'network2'}) jest.advanceTimersByTime(10000) }) it('sets startedBundledNode to true in ConnectionStatusSubject', () => { @@ -362,36 +367,8 @@ describe('NodeService', () => { startedBundledNode: false, }) }) - }) - }) - describe('with http url', () => { - beforeEach(async () => { - stubbedNetworsServiceGet.mockReturnValueOnce({ remote: fakeHTTPUrl }) - await eventCallback({ currentNetworkID: 'test' }) - }) - it('sets http agent', () => { - expect(stubbedCKBSetNode).toHaveBeenCalledWith( - expect.objectContaining({ - url: fakeHTTPUrl, - httpAgent: expect.anything(), - }) - ) - }) - }) - describe('with https url', () => { - beforeEach(async () => { - stubbedNetworsServiceGet.mockReturnValueOnce({ remote: fakeHTTPSUrl }) - await eventCallback({ currentNetworkID: 'test' }) - }) - it('sets https agent', () => { - expect(stubbedCKBSetNode).toHaveBeenCalledWith( - expect.objectContaining({ - url: fakeHTTPSUrl, - httpsAgent: expect.anything(), - }) - ) - }) - }) + }); + }); describe('with invalid url', () => { beforeEach(() => { stubbedNetworsServiceGet.mockReturnValueOnce({ remote: 'invalidurl' }) diff --git a/packages/neuron-wallet/tests/services/tx/transaction-sender.test.ts b/packages/neuron-wallet/tests/services/tx/transaction-sender.test.ts index 44f18dcbf2..853d4e6aa9 100644 --- a/packages/neuron-wallet/tests/services/tx/transaction-sender.test.ts +++ b/packages/neuron-wallet/tests/services/tx/transaction-sender.test.ts @@ -130,6 +130,26 @@ jest.doMock('services/hardware', () => ({ }), })) +jest.doMock('@nervosnetwork/ckb-sdk-core', () => { + return function() { + return { + calculateDaoMaximumWithdraw: stubbedCalculateDaoMaximumWithdraw, + } + } +}) + +jest.doMock('utils/ckb-rpc.ts', () => ({ + generateRPC() { + return { + sendTransaction: stubbedSendTransaction + } + } +})) + +jest.doMock('services/cells', () => ({ + getLiveCell: stubbedGetLiveCell +})) + import Transaction from '../../../src/models/chain/transaction' import TxStatus from '../../../src/models/chain/tx-status' import CellDep, { DepType } from '../../../src/models/chain/cell-dep' @@ -142,7 +162,6 @@ import { AddressType } from '../../../src/models/keys/address' import WitnessArgs from '../../../src/models/chain/witness-args' import CellWithStatus from '../../../src/models/chain/cell-with-status' import SystemScriptInfo from '../../../src/models/system-script-info' -import NodeService from '../../../src/services/node' import AssetAccountInfo from '../../../src/models/asset-account-info' import { CapacityNotEnoughForChange, @@ -260,12 +279,6 @@ describe('TransactionSender Test', () => { resetMocks() stubbedGetWallet.mockReturnValue(fakeWallet) - - //@ts-ignore - NodeService.getInstance().ckb.rpc = { - sendTransaction: stubbedSendTransaction, - } - NodeService.getInstance().ckb.calculateDaoMaximumWithdraw = stubbedCalculateDaoMaximumWithdraw }) describe('sign', () => { @@ -672,7 +685,7 @@ describe('TransactionSender Test', () => { const feeRate = '10' const fakeDepositOutPoint = OutPoint.fromObject({ txHash: '0x' + '0'.repeat(64), index: '0x0' }) beforeEach(async () => { - stubbedGetLiveCell.mockResolvedValue(fakeCellWithStatus) + stubbedGetLiveCell.mockResolvedValue(fakeCellWithStatus.cell!.output) stubbedGetTransaction.mockResolvedValue(fakeTx1) stubbedGetNextAddress.mockResolvedValue({ address: fakeAddress1 }) await transactionSender.generateWithdrawMultiSignTx(fakeWallet.id, fakeDepositOutPoint, fee, feeRate) @@ -701,7 +714,7 @@ describe('TransactionSender Test', () => { const fee = '1' const feeRate = '10' beforeEach(async () => { - stubbedGetLiveCell.mockResolvedValue(fakeCellWithStatus) + stubbedGetLiveCell.mockResolvedValue(fakeCellWithStatus.cell!.output) stubbedGetTransaction.mockResolvedValue(fakeTx1) stubbedGetHeader.mockResolvedValue(fakeDepositBlockHeader) stubbedGetNextChangeAddress.mockReturnValue({ @@ -727,7 +740,10 @@ describe('TransactionSender Test', () => { let tx: any beforeEach(async () => { - stubbedGetLiveCell.mockResolvedValue(fakeCellWithStatus) + const output = fakeCellWithStatus.cell!.output + output.daoData = '0x6400000000000000' + output.setDepositOutPoint(new OutPoint(`0x${'0'.repeat(64)}`, '0x0')) + stubbedGetLiveCell.mockResolvedValue(output) stubbedGetTransaction.mockResolvedValue(fakeTx1) stubbedGetBlockByNumber.mockResolvedValue({ header: { hash: '0x92b197aa1fba0f63633922c61c92375c9c074a93e85963554f5499fe1450d0e5' }, diff --git a/packages/neuron-wallet/tests/utils/ckb-rpc.test.ts b/packages/neuron-wallet/tests/utils/ckb-rpc.test.ts new file mode 100644 index 0000000000..a1eca58a5f --- /dev/null +++ b/packages/neuron-wallet/tests/utils/ckb-rpc.test.ts @@ -0,0 +1,19 @@ +import { FullCKBRPC, generateRPC, LightRPC } from '../../src/utils/ckb-rpc' +import { BUNDLED_LIGHT_CKB_URL, BUNDLED_CKB_URL } from '../../src/utils/const' + +describe('test ckb rpc file', () => { + describe('test generateRPC', () => { + it('url is light node', () => { + const result = generateRPC(BUNDLED_LIGHT_CKB_URL) + expect(result instanceof LightRPC).toBeTruthy() + }) + it('url is not light node', () => { + const result = generateRPC(BUNDLED_CKB_URL) + expect(result instanceof FullCKBRPC).toBeTruthy() + }) + it('url is https', () => { + const result = generateRPC('https://localhost:8114') + expect(result.node.httpsAgent).toBeDefined() + }) + }) +}) \ No newline at end of file diff --git a/packages/neuron-wallet/tests/utils/rpc-request.test.ts b/packages/neuron-wallet/tests/utils/rpc-request.test.ts index 82e7745a19..f93ad617b9 100644 --- a/packages/neuron-wallet/tests/utils/rpc-request.test.ts +++ b/packages/neuron-wallet/tests/utils/rpc-request.test.ts @@ -76,9 +76,6 @@ describe('rpc-request', () => { }, }) const res = await rpcRequest('url', option) - expect(res).toEqual({ - id: 2, - result: 2, - }) + expect(res).toEqual(2) }) }) diff --git a/scripts/download-ckb.sh b/scripts/download-ckb.sh index 179c541c82..335b0f36d2 100755 --- a/scripts/download-ckb.sh +++ b/scripts/download-ckb.sh @@ -1,6 +1,7 @@ #!/bin/bash CKB_VERSION=$(cat .ckb-version) +CKB_LIGHT_VERSION=$(cat .ckb-light-version) ROOT_DIR=$(pwd) # Be sure to run this from root directory! GITHUB_RELEASE_URL="https://github.com/nervosnetwork/ckb/releases/download" @@ -33,6 +34,18 @@ function download_macos_aarch64() { rm ${CKB_FILENAME}.zip } +function download_macos_light() { + # macOS + CKB_FILENAME="ckb-light-client_${CKB_LIGHT_VERSION}-x86_64-darwin-portable" + cd $ROOT_DIR/packages/neuron-wallet/bin/mac + + curl -O -L "https://github.com/nervosnetwork/ckb-light-client/releases/download/${CKB_LIGHT_VERSION}/${CKB_FILENAME}.tar.gz" + tar -xzvf ${CKB_FILENAME}.tar.gz + cp ./config/testnet.toml ../../light/ckb_light.toml + rm -rf ./config + rm ${CKB_FILENAME}.tar.gz +} + function download_linux() { # Linux CKB_FILENAME="ckb_${CKB_VERSION}_x86_64-unknown-linux-gnu-portable" @@ -45,6 +58,18 @@ function download_linux() { rm ${CKB_FILENAME}.tar.gz } +function download_linux_light() { + # macOS + CKB_FILENAME="ckb-light-client_${CKB_LIGHT_VERSION}-x86_64-linux-portable" + cd $ROOT_DIR/packages/neuron-wallet/bin/linux + + curl -O -L "https://github.com/nervosnetwork/ckb-light-client/releases/download/${CKB_LIGHT_VERSION}/${CKB_FILENAME}.tar.gz" + tar -xzvf ${CKB_FILENAME}.tar.gz + cp ./config/testnet.toml ../../light/ckb_light.toml + rm -rf ./config + rm ${CKB_FILENAME}.tar.gz +} + function download_windows() { # Windows CKB_FILENAME="ckb_${CKB_VERSION}_x86_64-pc-windows-msvc" @@ -57,17 +82,32 @@ function download_windows() { rm ${CKB_FILENAME}.zip } +function download_windows_light() { + # macOS + CKB_FILENAME="ckb-light-client_${CKB_LIGHT_VERSION}-x86_64-windows" + cd $ROOT_DIR/packages/neuron-wallet/bin/win + + curl -O -L "https://github.com/nervosnetwork/ckb-light-client/releases/download/${CKB_LIGHT_VERSION}/${CKB_FILENAME}.tar.gz" + tar -xzvf ${CKB_FILENAME}.tar.gz + cp ./config/testnet.toml ../../light/ckb_light.toml + rm -rf ./config + rm ${CKB_FILENAME}.tar.gz +} + case $1 in - mac) download_macos ;; - linux) download_linux ;; - win) download_windows ;; + mac) download_macos; download_macos_light;; + linux) download_linux; download_linux_light;; + win) download_windows; download_windows_light;; *) if [[ "$OSTYPE" == "darwin"* ]]; then download_macos + download_macos_light elif [[ "$OSTYPE" == "linux-gnu" ]]; then download_linux + download_linux_light else download_windows + download_windows_light fi ;; esac diff --git a/yarn.lock b/yarn.lock index a21335f56a..6cad60b959 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1286,6 +1286,20 @@ dependencies: jsbi "^4.1.0" +"@ckb-lumos/bi@0.19.0": + version "0.19.0" + resolved "https://registry.yarnpkg.com/@ckb-lumos/bi/-/bi-0.19.0.tgz#ccd7e9e32e58eec7effc78cd171eb79f0f858d4a" + integrity sha512-+EFkUOqCtIwilAfrd680wEeMTXME9Wjjyl436+0x32jlbfo4sa+iNqwPaTjUQ2/SDwsuqK3eB+DntYxxFxoEtw== + dependencies: + jsbi "^4.1.0" + +"@ckb-lumos/codec@0.19.0": + version "0.19.0" + resolved "https://registry.yarnpkg.com/@ckb-lumos/codec/-/codec-0.19.0.tgz#c9cda5e37fd5591abeaac9d5ed9577cfad206c09" + integrity sha512-MAts5rm5xLcvPslW6HwU/TlRoJ3jTtgsdtyakIa7qQo+0DlHdV6BOxTNDPtP3yqp8p5YFef7uCi/rcpi/KOGwA== + dependencies: + "@ckb-lumos/bi" "^0.19.0" + "@ckb-lumos/rpc@0.18.0": version "0.18.0" resolved "https://registry.yarnpkg.com/@ckb-lumos/rpc/-/rpc-0.18.0.tgz#3858b5eaa4b06a90d4a0931cc3168fab835f4a0c" From 7272fe718d33bd19081aee8e875dba4f7fa977c6 Mon Sep 17 00:00:00 2001 From: Keith Date: Mon, 29 May 2023 16:27:51 +0800 Subject: [PATCH 52/52] chore: update update neuron version and changelog --- CHANGELOG.md | 83 +++++++++++++++++++++++++++++ lerna.json | 2 +- package.json | 2 +- packages/neuron-ui/package.json | 2 +- packages/neuron-wallet/package.json | 4 +- 5 files changed, 88 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e6fb86231..02d0fe5f7f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,86 @@ +# 0.110.0 (2023-05-31) + +### CKB Node & Light Client + +- [CKB@v0.110.0](https://github.com/nervosnetwork/ckb/releases/tag/v0.110.0) was released on May. 17th, 2023. This version of CKB node is now bundled and preconfigured in Neuron. +- [CKB Light Client@v0.2.4](https://github.com/nervosnetwork/ckb-light-client/releases/tag/v0.2.4) was released on May. 28th, 2023. This version of CKB Light Client is now bundled and preconfigured in Neuron + +#### Caveat +◆ **CKB Light Client** is only activated on testnet, thus only `light testnet` is enabled in Neuron. **CKB Light Client on Mainnet** requires a hardfork on the mainnet in the future. +◆ **CKB@v0.110** requires data migration, which is irreversible. Be cautious to start the migration without a backup. [How to back up data of ckb node](https://github.com/nervosnetwork/neuron/issues/2557#issue-1512510978) + +> On the other hand, we strongly recommend you to back up the old data before migrating, the **ckb node data path** can be found by clicking **preference -> Data -> CKB Node Config & Storage**. Because once the migration starts, the data will be no longer compatible with all older versions of CKB. + +### Assumed valid target + +Block before `0xc0c532e10c708852d9586be46a5ed8317b2aa0835c721aa691abffb9bf4a26cd`(at height `10,004,892`) will be skipped in validation.(#2689) + +--- + +### Light Client Mode +[![Light client guide](https://github.com/Magickbase/neuron-public-issues/assets/7271329/eeed68ac-5f1b-457f-8203-c5d7b341b6b0)](https://youtu.be/tQm9YvgG7iE) + +YouTube: https://youtu.be/tQm9YvgG7iE + +--- + +We are thrilled to introduce our new feature: **Light Client Mode**. This feature makes Neuron more practical and convenient, allowing you to manage your digital assets more easily. Please note that it is currently only available on the testnet, as activation on the mainnet will require a hardfork. + +#### What is the light client model? + +**Light Client Mode** is a connection mode of Neuron that connects to a built-in **CKB Light Client**. Compared to a full node, it downloads a portion of the blockchain data to obtain necessary information. This allows Neuron to access the CKB blockchain faster. + +#### Light Client Mode Advantages + +1. **Higher synchronization speed**: Light Client Mode enables faster synchronization of blockchain data, saving users' time and network bandwidth. +2. **Less disk usage**: Light Client Mode requires only a fraction of the blockchain data to be stored, resulting in less storage space requirement compared to a full node. + +Using a **MacBook Pro (13-inch, M1, 2020)** device as an example, we conducted a realistic test of synchronization from **block 0 to the latest block 9,380,828** (2023/05/22 Pudge network data): + +- Light Client Mode: The synchronization process consumed about **5.5 hours** and approximately **45MB** of disk space during running. (The disk usage is related to the transaction count, and this test included 782 transactions.) +- Full Node Mode: It took about **36 hours** to synchronize **107.8GB** of data. (Excluding the time to find an assumed valid target block.) + +In the above test scenario, using a light node compared to a full node **reduced synchronization time by 84.7% and disk usage by 99.9%**. (Please note that these numbers are for reference only and may vary depending on different equipment, network conditions, and account data.) + +#### Light Client Mode Usage Scenarios + +Compared to full nodes, light nodes require less disk space and network bandwidth, making them suitable for users who want to quickly access blockchain information without needing the full blockchain data. However, please note that for transactions containing time locks, Cheque contracts, or other operations that require full node data verification, you will need to switch to full nodes. + +--- + +## New features + +- #2615: Adapt ckb light node.(@yanguoyu) +- #2599: Implement dynamic fee rate based on fee rate statistics.(@jeffreyma597) +- #2689: Upgrade ckb node to v0.110.0.(@Keith-CY) +- #2627: Download ckb_aarch64 for neuron-arm64.(@Keith-CY) +- #2651: Add dialog warn for migrate date to 0.108.(@yanguoyu) +- #2567,#2568: Set allowToChangeInstallationDirectory for windows.(@yanguoyu) +- #2674: Improve the interaction design of the DatetimePicker component.(@WhiteMinds) + +## Bug fixes + +- #2530: Batch request to improve performance of nervos dao records.(@yanguoyu) +- #2574: Improve heart beating check of built-in ckb node.(@yanguoyu) +- #2565: Remove obsolete indexer data.(@yanguoyu) +- #2581: Skip password requirement when interact with a hardware wallet.(@yanguoyu) +- #2609: Upgrade leveldown to fix SQLITE_MISUSE.(@devchenyan) +- #2595: Fix latency of switching networks.(@yanguoyu) +- #2629: Fix crash when enter over 8 decimal.(@yanguoyu) + +## New Contributors + +- @Kuzirashi made their first contribution in https://github.com/nervosnetwork/neuron/pull/2559 +- @mortoys made their first contribution in https://github.com/nervosnetwork/neuron/pull/2592 +- @devchenyan made their first contribution in https://github.com/nervosnetwork/neuron/pull/2609 +- @WhiteMinds made their first contribution in https://github.com/nervosnetwork/neuron/pull/2652 +- @homura made their first contribution in https://github.com/nervosnetwork/neuron/pull/2657 + + +**Full Changelog**: https://github.com/nervosnetwork/neuron/compare/v0.106.0...v0.110.0 + + + # 0.106.0 (2022-12-28) ### CKB diff --git a/lerna.json b/lerna.json index c0b80cf1d0..f41b488c71 100644 --- a/lerna.json +++ b/lerna.json @@ -2,7 +2,7 @@ "packages": [ "packages/*" ], - "version": "0.106.0", + "version": "0.110.0", "npmClient": "yarn", "useWorkspaces": true } diff --git a/package.json b/package.json index 06a7830d4a..6860d15d69 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "neuron", "productName": "Neuron", "description": "CKB Neuron Wallet", - "version": "0.101.3", + "version": "0.110.0", "private": true, "author": { "name": "Nervos Core Dev", diff --git a/packages/neuron-ui/package.json b/packages/neuron-ui/package.json index 5cca4a9e76..4e43c39815 100644 --- a/packages/neuron-ui/package.json +++ b/packages/neuron-ui/package.json @@ -1,6 +1,6 @@ { "name": "neuron-ui", - "version": "0.106.0", + "version": "0.110.0", "private": true, "author": { "name": "Nervos Core Dev", diff --git a/packages/neuron-wallet/package.json b/packages/neuron-wallet/package.json index 61f1259cf8..1b59cbfd2a 100644 --- a/packages/neuron-wallet/package.json +++ b/packages/neuron-wallet/package.json @@ -3,7 +3,7 @@ "productName": "Neuron", "description": "CKB Neuron Wallet", "homepage": "https://www.nervos.org/", - "version": "0.106.0", + "version": "0.110.0", "private": true, "author": { "name": "Nervos Core Dev", @@ -87,7 +87,7 @@ "electron-builder": "23.6.0", "electron-devtools-installer": "3.2.0", "jest-when": "2.8.1", - "neuron-ui": "0.106.0", + "neuron-ui": "0.110.0", "typescript": "5.0.4" } }