+
+ {tx.inputs.map((v, idx) =>
+ v.lock && v.capacity ? (
+
+ ) : null
+ )}
+
+
+ {tx.inputs.length > 1 ? (
+ <>
+
+ {Array.from({ length: (tx.inputs.length - 1) * 4 }).map((_, idx) => (
+
2 * tx.inputs.length - 4 && idx < 2 * tx.inputs.length - 1}
+ className={
+ tx.inputs.length % 2 !== 0 && idx === tx.inputs.length * 2 - 2 ? styles.centerLine : undefined
+ }
+ />
+ ))}
+
+
+ >
+ ) : (
+
+ )}
+
Transaction
+
+
+ {Array.from({ length: tx.outputs.length * 4 }).map((_, idx) => (
+
2 * tx.outputs.length - 2 && idx <= 2 * tx.outputs.length}
+ className={tx.outputs.length % 2 === 0 && idx === tx.outputs.length * 2 ? styles.centerLine : undefined}
+ >
+ {idx % 4 === 0 || idx === tx.outputs.length * 4 - 1 ?
: null}
+
+ ))}
+
+
+
+ {tx.outputs.map((v, idx) =>
+ v.lock && v.capacity ? (
+
+ ) : null
+ )}
+
+
+
+
+ )
+}
+
+TxTopology.displayName = 'TxTopology'
+
+export default TxTopology
diff --git a/packages/neuron-ui/src/components/SendTxDetail/hooks.ts b/packages/neuron-ui/src/components/SendTxDetail/hooks.ts
new file mode 100644
index 0000000000..801f4380b1
--- /dev/null
+++ b/packages/neuron-ui/src/components/SendTxDetail/hooks.ts
@@ -0,0 +1,13 @@
+import { useCallback, useState } from 'react'
+
+export const useShowBalance = () => {
+ const [isBalanceShow, setIsBalanceShow] = useState(true)
+ return {
+ isBalanceShow,
+ onChange: useCallback(() => {
+ setIsBalanceShow((v: boolean) => !v)
+ }, []),
+ }
+}
+
+export default useShowBalance
diff --git a/packages/neuron-ui/src/components/SendTxDetail/index.tsx b/packages/neuron-ui/src/components/SendTxDetail/index.tsx
new file mode 100644
index 0000000000..7a064564f1
--- /dev/null
+++ b/packages/neuron-ui/src/components/SendTxDetail/index.tsx
@@ -0,0 +1,118 @@
+import React, { FC, useCallback, useState } from 'react'
+import { showPageNotice, useDispatch, useState as useGlobalState } from 'states'
+import { Copy, EyesOpen, GoBack } from 'widgets/Icons/icon'
+import PageContainer from 'components/PageContainer'
+import { useTranslation } from 'react-i18next'
+import { RoutePath, clsx, shannonToCKBFormatter, useGoBack, isMainnet as isMainnetUtils } from 'utils'
+import Tabs from 'widgets/Tabs'
+import { HIDE_BALANCE } from 'utils/const'
+import PasswordRequestInPage from 'components/PasswordRequest/PasswordRequestInPage'
+import { useNavigate } from 'react-router-dom'
+import useShowBalance from './hooks'
+import styles from './sendTxDetail.module.scss'
+import TxTopology from './TxTopology'
+
+enum TabId {
+ Basic,
+ Topology,
+}
+
+const TxBasic: FC<{
+ tx: State.GeneratedTx
+}> = ({ tx }) => {
+ const [t] = useTranslation()
+ const capacities = tx.inputs.reduce((total, addr) => total + BigInt(addr.capacity || 0), BigInt(0)).toString()
+ const dispatch = useDispatch()
+ const onCopy = useCallback(() => {
+ window.navigator.clipboard.writeText(tx.hash)
+ showPageNotice('common.copied')(dispatch)
+ }, [tx.hash, dispatch])
+ const { isBalanceShow: showCapacity, onChange: onChangeCapacityVisible } = useShowBalance()
+ const { isBalanceShow: showFee, onChange: onChangeFeeVisible } = useShowBalance()
+ return (
+
+
{t('send-tx-detail.tx-basic.tx-hash')}
+
+ {tx.hash}
+
+
+
{t('send-tx-detail.tx-basic.capacity')}
+
+ {`${showCapacity ? shannonToCKBFormatter(capacities) : HIDE_BALANCE} CKB`}
+
+
+
{t('send-tx-detail.tx-basic.tx-fee')}
+
+ {`${showFee ? shannonToCKBFormatter(tx.fee) : HIDE_BALANCE} CKB`}
+
+
+
{t('send-tx-detail.tx-basic.size')}
+
{`${tx.size} Bytes`}
+
+ )
+}
+
+const SendTxDetail = () => {
+ const {
+ app: {
+ pageNotice,
+ send: { generatedTx },
+ },
+ wallet,
+ chain: { networkID },
+ settings: { networks },
+ } = useGlobalState()
+ const isMainnet = isMainnetUtils(networks, networkID)
+ const [t] = useTranslation()
+ const onGoBack = useGoBack()
+ const tabs = [
+ { id: TabId.Basic, label: t('send-tx-detail.basic-info') },
+ { id: TabId.Topology, label: t('send-tx-detail.topology') },
+ ]
+ const [currentTab, setCurrentTab] = useState(tabs[0])
+ const navigate = useNavigate()
+ const onGotoView = useCallback(() => {
+ navigate(RoutePath.Overview)
+ }, [navigate])
+ if (!generatedTx) {
+ return null
+ }
+ return (
+
{
+ e.stopPropagation()
+ e.preventDefault()
+ }}
+ head={
+
+
+ {`${t('send-tx-detail.page-title')}`}
+
+ }
+ notice={pageNotice}
+ >
+
+
+ {currentTab.id === TabId.Basic ? (
+
+ ) : (
+
+ )}
+
+
+
+ )
+}
+
+SendTxDetail.displayName = 'SendTxDetail'
+
+export default SendTxDetail
diff --git a/packages/neuron-ui/src/components/SendTxDetail/sendTxDetail.module.scss b/packages/neuron-ui/src/components/SendTxDetail/sendTxDetail.module.scss
new file mode 100644
index 0000000000..abb96e135a
--- /dev/null
+++ b/packages/neuron-ui/src/components/SendTxDetail/sendTxDetail.module.scss
@@ -0,0 +1,92 @@
+@import '../../styles//mixin.scss';
+
+.goBack {
+ margin-right: 8px;
+ cursor: pointer;
+
+ & path {
+ stroke: var(--main-text-color);
+ }
+}
+
+.tx {
+ @include card;
+}
+
+.password {
+ @include card;
+ padding: 4px 16px 24px 16px;
+ margin-top: 16px;
+}
+
+.tabsClassName {
+ .tabsWrapClassName {
+ position: relative;
+ display: flex;
+
+ .tabsColumnClassName {
+ position: relative;
+ padding: 10px 20px;
+ font-size: 14px;
+ font-weight: 500;
+ color: var(--tabs-default-color);
+ background-color: transparent;
+ border: none;
+ margin-right: 10px;
+ cursor: pointer;
+
+ &:hover {
+ font-weight: bold;
+ color: var(--tabs-active);
+ }
+
+ &.active {
+ color: var(--tabs-active);
+ border-bottom: 2px solid var(--tabs-active);
+ }
+ }
+ }
+}
+
+.txBasicRoot {
+ display: grid;
+ grid-template-columns: repeat(2, minmax(112px, auto) 1fr);
+ grid-auto-rows: minmax(56px, auto);
+ border-radius: 16px;
+ background: var(--secondary-background-color);
+
+ .fieldName {
+ display: flex;
+ align-items: center;
+ border-top: 1px solid var(--table-head-border-color);
+ padding: 0 16px;
+ color: #999999;
+ }
+
+ .fieldValue {
+ display: flex;
+ align-items: center;
+ border-top: 1px solid var(--table-head-border-color);
+ padding-right: 16px;
+ color: var(--main-text-color);
+
+ &.fullRow {
+ grid-column: 2 / -1;
+ }
+
+ &.bold {
+ font-weight: 500;
+ }
+
+ & > svg {
+ cursor: pointer;
+ margin-left: 8px;
+ }
+ }
+
+ .txHash {
+ display: flex;
+ align-items: center;
+ font-family: 'JetBrains Mono';
+ }
+}
diff --git a/packages/neuron-ui/src/components/SendTxDetail/txTopology.module.scss b/packages/neuron-ui/src/components/SendTxDetail/txTopology.module.scss
new file mode 100644
index 0000000000..da42cb3d66
--- /dev/null
+++ b/packages/neuron-ui/src/components/SendTxDetail/txTopology.module.scss
@@ -0,0 +1,274 @@
+@import '../../styles/mixin.scss';
+
+.cellItemRoot {
+ margin: 16px 0;
+ position: relative;
+ min-width: 160px;
+
+ .inputStatus {
+ color: var(--secondary-text-color);
+ font-size: 12px;
+ font-weight: 400;
+ margin-bottom: 4px;
+ position: absolute;
+ bottom: 100%;
+ }
+
+ .itemTable {
+ border: 1px solid var(--divide-line-color);
+ border-radius: 4px;
+ font-size: 12px;
+ background-color: var(--table-head-background-color);
+ color: --third-text-color;
+ display: grid;
+ grid-template-areas:
+ 'label amount amount'
+ 'address address address';
+
+ & > div {
+ padding: 6px;
+ line-height: 16px;
+ }
+ .label {
+ grid-area: label;
+ color: var(--main-text-color);
+ border-right: 1px solid var(--divide-line-color);
+ font-weight: 500;
+ }
+
+ .amount {
+ grid-area: amount;
+ color: var(--third-text-color);
+ }
+
+ .address {
+ border-top: 1px solid var(--divide-line-color);
+ grid-area: address;
+ width: calc(100% - 12px);
+ color: var(--third-text-color);
+ &:hover {
+ color: var(--primary-color);
+ }
+ }
+
+ .copyAddress {
+ width: 346px;
+ @include copyAddress;
+ }
+ }
+}
+
+.root {
+ padding: 28px 0;
+ border-top: 1px solid var(--divide-line-color);
+ display: flex;
+ justify-content: center;
+
+ & > div {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ }
+
+ .center {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-direction: row;
+ .txBox {
+ border-radius: 4px;
+ border: 1px solid var(--divide-line-color);
+ background-color: var(--table-head-background-color);
+ width: 74px;
+ height: 24px;
+ line-height: 24px;
+ font-size: 12px;
+ font-weight: 400;
+ text-align: center;
+ color: var(--third-text-color);
+ }
+
+ .onlyOneInput {
+ width: 100px;
+ height: 1px;
+ background-color: var(--divide-line-color);
+ position: relative;
+ svg {
+ position: absolute;
+ left: 50%;
+ top: 100%;
+ transform: rotate(-90deg) translateX(50%);
+ > path {
+ fill: var(--divide-line-color);
+ stroke: var(--divide-line-color);
+ }
+ }
+ }
+ .inputConnection {
+ width: 40px;
+ display: flex;
+ flex-direction: column;
+ position: relative;
+
+ & > div {
+ flex: 1 1 auto;
+ border-color: var(--divide-line-color) !important;
+ border-right: 1px solid;
+
+ &:nth-child(4n + 1) {
+ border-top: 1px solid;
+ }
+ &:first-child {
+ border-radius: 0 8px 0 0;
+ }
+ &:last-child {
+ border-radius: 0 0 8px 0;
+ border-bottom: 1px solid;
+ }
+ &[data-ignore-right='true'] {
+ border-right: none;
+ }
+ &.centerLine {
+ position: absolute;
+ top: calc(50% - 1px);
+ width: calc(200% + 16px);
+ left: -28px;
+ transform: scale(0.5);
+ border-top: 2px solid;
+ }
+ }
+ }
+ .inputConnectTx {
+ width: 60px;
+ height: 46px;
+ position: relative;
+
+ & > div {
+ height: 50%;
+ border-left: 1px solid;
+ border-color: var(--divide-line-color) !important;
+ margin-left: -1px;
+ &:first-child {
+ border-bottom: 1px solid;
+ border-radius: 0 0 0 8px;
+ }
+ &:last-child {
+ border-top: 1px solid;
+ width: 8px;
+ border-radius: 8px 0 0 0;
+ margin-top: -1px;
+ }
+ }
+
+ svg {
+ position: absolute;
+ transform: translateY(-50%) rotate(-90deg);
+ left: 50%;
+ top: 50%;
+ > path {
+ fill: var(--divide-line-color);
+ stroke: var(--divide-line-color);
+ }
+ }
+ }
+ .outputConnectTx {
+ width: 60px;
+ height: 52px;
+ display: flex;
+ flex-direction: column;
+ align-items: flex-end;
+ & > div {
+ height: 50%;
+ border-right: 1px solid;
+ border-color: var(--divide-line-color) !important;
+ margin-right: -1px;
+ &:first-child {
+ width: 100%;
+ border-bottom: 1px solid;
+ border-radius: 0 0 8px 0;
+ }
+ &:last-child {
+ border-top: 1px solid;
+ width: 8px;
+ border-radius: 0 8px 0 0;
+ margin-top: -1px;
+ }
+ }
+ }
+ .outputConnection {
+ width: 40px;
+ height: calc(100% - 59px - 32px);
+ display: flex;
+ flex-direction: column;
+ position: relative;
+
+ & > div {
+ flex: 1;
+ border-color: var(--divide-line-color) !important;
+ border-left: 1px solid;
+ position: relative;
+ &:nth-child(4n + 1) {
+ border-top: 1px solid;
+ svg {
+ bottom: 100%;
+ transform: rotate(-90deg) translateY(-50%) translateX(-50%);
+ }
+ }
+ &:first-child {
+ border-radius: 8px 0 0 0;
+
+ svg {
+ bottom: 100%;
+ transform: rotate(-90deg) translateY(-50%) translateX(-50%);
+ }
+ }
+ &:last-child {
+ border-radius: 0 0 0 8px;
+ border-bottom: 1px solid;
+ position: relative;
+ top: -14px;
+ svg {
+ top: 100%;
+ transform: rotate(-90deg) translateY(-50%) translateX(50%);
+ }
+ }
+ &[data-ignore-left='true'] {
+ border-left: none;
+ }
+ &.centerLine {
+ position: absolute;
+ top: calc(50% - 1px);
+ width: calc(200% + 16px);
+ left: -28px;
+ transform: scale(0.5);
+ border-top: 2px solid;
+
+ & > svg {
+ transform: rotate(-90deg) translateY(-50%) translateX(-50%) scale(2);
+ }
+ }
+ }
+
+ svg {
+ position: absolute;
+ left: 50%;
+ > path {
+ fill: var(--divide-line-color);
+ stroke: var(--divide-line-color);
+ }
+ }
+ }
+ }
+
+ .inputs {
+ position: relative;
+ }
+
+ .outputs {
+ position: relative;
+
+ .placeHolder {
+ height: 29px;
+ }
+ }
+}
diff --git a/packages/neuron-ui/src/locales/en.json b/packages/neuron-ui/src/locales/en.json
index 338f714db6..509ce2726a 100644
--- a/packages/neuron-ui/src/locales/en.json
+++ b/packages/neuron-ui/src/locales/en.json
@@ -1193,6 +1193,18 @@
"lock": "Lock",
"unlock": "Unlock",
"consume": "Consume"
+ },
+ "send-tx-detail": {
+ "page-title": "Transaction Detail",
+ "basic-info": "Basic Information",
+ "topology": "Topology",
+ "tx-basic": {
+ "tx-hash": "Transaction Hash",
+ "capacity": "Capacity",
+ "tx-fee": "Transaction Fee",
+ "size": "Size",
+ "lock-time": "Lock Time"
+ }
}
}
}
diff --git a/packages/neuron-ui/src/locales/es.json b/packages/neuron-ui/src/locales/es.json
index 9909598ea0..1440ab833e 100644
--- a/packages/neuron-ui/src/locales/es.json
+++ b/packages/neuron-ui/src/locales/es.json
@@ -1188,6 +1188,18 @@
"lock": "Bloquear",
"unlock": "Desbloquear",
"consume": "Consumir"
+ },
+ "send-tx-detail": {
+ "page-title": "Detalles de la transacción",
+ "basic-info": "Información Básica",
+ "topology": "Diagrama de topología",
+ "tx-basic": {
+ "tx-hash": "Hash de Transacción",
+ "capacity": "Cantidad",
+ "tx-fee": "Tarifa de transacción",
+ "size": "tamaño",
+ "lock-time": "Período de Bloqueo"
+ }
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/neuron-ui/src/locales/fr.json b/packages/neuron-ui/src/locales/fr.json
index a4fcb7e2c9..abf5f0883c 100644
--- a/packages/neuron-ui/src/locales/fr.json
+++ b/packages/neuron-ui/src/locales/fr.json
@@ -1193,6 +1193,18 @@
"lock": "Verrouiller",
"unlock": "Déverrouiller",
"consume": "Consommer"
+ },
+ "send-tx-detail": {
+ "page-title": "Détail de l'historique",
+ "basic-info": "Informations de base",
+ "topology": "Schéma topologique",
+ "tx-basic": {
+ "tx-hash": "Hash de transaction",
+ "capacity": "Montant",
+ "tx-fee": "Frais de transaction",
+ "size": "taille",
+ "lock-time": "Période de verrouillage"
+ }
}
}
}
diff --git a/packages/neuron-ui/src/locales/zh-tw.json b/packages/neuron-ui/src/locales/zh-tw.json
index 151d07d7dd..cea843f0cc 100644
--- a/packages/neuron-ui/src/locales/zh-tw.json
+++ b/packages/neuron-ui/src/locales/zh-tw.json
@@ -1164,6 +1164,18 @@
"lock": "鎖定",
"unlock": "解鎖",
"consume": "消耗"
+ },
+ "send-tx-detail": {
+ "page-title": "交易詳情",
+ "basic-info": "基本信息",
+ "topology": "拓撲圖",
+ "tx-basic": {
+ "tx-hash": "交易哈希",
+ "capacity": "金額",
+ "tx-fee": "交易費",
+ "size": "大小",
+ "lock-time": "鎖定時間"
+ }
}
}
}
diff --git a/packages/neuron-ui/src/locales/zh.json b/packages/neuron-ui/src/locales/zh.json
index 05fdaf61bd..0146f9920d 100644
--- a/packages/neuron-ui/src/locales/zh.json
+++ b/packages/neuron-ui/src/locales/zh.json
@@ -1185,6 +1185,18 @@
"lock": "锁定",
"unlock": "解锁",
"consume": "消耗"
+ },
+ "send-tx-detail": {
+ "page-title": "交易详情",
+ "basic-info": "基本信息",
+ "topology": "拓扑图",
+ "tx-basic": {
+ "tx-hash": "交易哈希",
+ "capacity": "金额",
+ "tx-fee": "交易费",
+ "size": "大小",
+ "lock-time": "锁定时间"
+ }
}
}
}
diff --git a/packages/neuron-ui/src/router.tsx b/packages/neuron-ui/src/router.tsx
index 76114bd4f2..79bee75bd7 100644
--- a/packages/neuron-ui/src/router.tsx
+++ b/packages/neuron-ui/src/router.tsx
@@ -22,6 +22,7 @@ import Settings from 'components/Settings'
import SignAndVerify from 'components/SignAndVerify'
import MultisigAddress from 'components/MultisigAddress'
import CellManagement from 'components/CellManagement'
+import SendTxDetail from 'components/SendTxDetail'
const toolsRouters = [
{
@@ -113,6 +114,16 @@ const mainRouterConfig: RouteObject[] = [
},
],
},
+ {
+ path: RoutePath.SendTxDetail,
+ element: (
+ <>
+
+
+ >
+ ),
+ children: [...toolsRouters],
+ },
{
path: RoutePath.History,
children: [
diff --git a/packages/neuron-ui/src/states/init/chain.ts b/packages/neuron-ui/src/states/init/chain.ts
index 2fc84a4314..e0da056662 100644
--- a/packages/neuron-ui/src/states/init/chain.ts
+++ b/packages/neuron-ui/src/states/init/chain.ts
@@ -19,7 +19,6 @@ export const transactionState: State.DetailedTransaction = {
blockHash: '',
witnesses: [],
nervosDao: false,
- size: 0,
}
export const chainState: Readonly
= {
diff --git a/packages/neuron-ui/src/types/App/index.d.ts b/packages/neuron-ui/src/types/App/index.d.ts
index dd3e99b739..2c01956c4b 100644
--- a/packages/neuron-ui/src/types/App/index.d.ts
+++ b/packages/neuron-ui/src/types/App/index.d.ts
@@ -31,6 +31,7 @@ declare namespace State {
lock: CKBComponents.Script | null
type?: CKBComponents.Script
data?: string
+ status?: string
}
interface DetailedOutput {
@@ -40,6 +41,7 @@ declare namespace State {
outPoint: CKBComponents.OutPoint
type?: CKBComponents.Script
data?: string
+ isChangeCell?: boolean
}
interface DetailedTransaction extends Transaction {
blockHash: string
@@ -50,7 +52,8 @@ declare namespace State {
outputs: DetailedOutput[]
outputsCount: string
witnesses: string[]
- size: number
+ size?: number
+ isLastChange?: boolean
}
interface Output {
address: string | undefined
@@ -122,6 +125,7 @@ declare namespace State {
blake160s: string[]
}
onSuccess?: () => void
+ showType?: 'Global' | ''
}
interface SUDTAccount {
diff --git a/packages/neuron-ui/src/utils/enums.ts b/packages/neuron-ui/src/utils/enums.ts
index ce71adb71e..901eafe4ab 100644
--- a/packages/neuron-ui/src/utils/enums.ts
+++ b/packages/neuron-ui/src/utils/enums.ts
@@ -25,6 +25,7 @@ export enum RoutePath {
SUDTAccountList = '/s-udt/accounts',
SUDTSend = '/s-udt/send',
ImportHardware = '/import-hardware',
+ SendTxDetail = '/send-tx-detail',
OfflineSign = 'offline-sign',
SignVerify = 'sign-verify',
MultisigAddress = 'multisig-address',
diff --git a/packages/neuron-ui/src/widgets/Tooltip/tooltip.module.scss b/packages/neuron-ui/src/widgets/Tooltip/tooltip.module.scss
index 4e77a25c16..6c4d88ffd1 100644
--- a/packages/neuron-ui/src/widgets/Tooltip/tooltip.module.scss
+++ b/packages/neuron-ui/src/widgets/Tooltip/tooltip.module.scss
@@ -291,5 +291,12 @@ $placements: left, right, top, bottom, left-top, right-top, left-bottom, right-b
}
}
}
+ &[data-placement='top'] {
+ &[data-trigger-next-to-child='true'] {
+ & .tip {
+ margin-bottom: 2px;
+ }
+ }
+ }
}
}
diff --git a/packages/neuron-wallet/src/models/chain/input.ts b/packages/neuron-wallet/src/models/chain/input.ts
index 9c00015ede..352989fab8 100644
--- a/packages/neuron-wallet/src/models/chain/input.ts
+++ b/packages/neuron-wallet/src/models/chain/input.ts
@@ -2,6 +2,7 @@ import OutPoint from './out-point'
import Script from './script'
import { BI } from '@ckb-lumos/bi'
import TypeChecker from '../../utils/type-checker'
+import { OutputStatus } from './output'
export default class Input {
public previousOutput: OutPoint | null
@@ -14,6 +15,7 @@ export default class Input {
public type?: Script | null
public typeHash?: string | null
public data?: string | null
+ public status?: OutputStatus
// don't using = directly, using setXxx instead
// check hex string
@@ -27,7 +29,8 @@ export default class Input {
multiSignBlake160?: string | null,
type?: Script | null,
typeHash?: string | null,
- data?: string | null
+ data?: string | null,
+ status?: OutputStatus
) {
this.previousOutput = previousOutput
this.since = since ? BigInt(since).toString() : since
@@ -42,6 +45,7 @@ export default class Input {
this.typeHash = typeHash || this.type?.computeHash()
this.data = data
+ this.status = status
TypeChecker.hashChecker(this.lockHash, this.typeHash)
TypeChecker.numberChecker(this.since, this.capacity, this.inputIndex)
@@ -58,6 +62,7 @@ export default class Input {
type,
typeHash,
data,
+ status,
}: {
previousOutput: OutPoint | null
since?: string
@@ -69,6 +74,7 @@ export default class Input {
type?: Script | null
typeHash?: string | null
data?: string | null
+ status?: OutputStatus
}): Input {
return new Input(
previousOutput ? OutPoint.fromObject(previousOutput) : previousOutput,
@@ -80,7 +86,8 @@ export default class Input {
multiSignBlake160,
type ? Script.fromObject(type) : type,
typeHash,
- data
+ data,
+ status
)
}
diff --git a/packages/neuron-wallet/src/models/chain/output.ts b/packages/neuron-wallet/src/models/chain/output.ts
index 5a8e2f568f..9a15c8d774 100644
--- a/packages/neuron-wallet/src/models/chain/output.ts
+++ b/packages/neuron-wallet/src/models/chain/output.ts
@@ -42,6 +42,7 @@ export default class Output {
public depositOutPoint?: OutPoint
public depositTimestamp?: string
public multiSignBlake160?: string | null
+ public isChangeCell?: boolean
public customizedAssetInfo?: CustomizedAssetInfo
diff --git a/packages/neuron-wallet/src/services/cells.ts b/packages/neuron-wallet/src/services/cells.ts
index 6e41ac3d11..8cdbf836a2 100644
--- a/packages/neuron-wallet/src/services/cells.ts
+++ b/packages/neuron-wallet/src/services/cells.ts
@@ -744,7 +744,13 @@ export default class CellsService {
{}
)
useCells.every(cell => {
- const input: Input = new Input(cell.outPoint(), '0', cell.capacity, cell.lockScript(), cell.lockHash)
+ const input: Input = Input.fromObject({
+ previousOutput: cell.outPoint(),
+ since: '0',
+ capacity: cell.capacity,
+ lock: cell.lockScript(),
+ status: cell.status as OutputStatus,
+ })
if (inputs.find(el => el.lockHash === cell.lockHash!)) {
totalSize += TransactionSize.emptyWitness()
} else {
diff --git a/packages/neuron-wallet/src/services/tx/transaction-generator.ts b/packages/neuron-wallet/src/services/tx/transaction-generator.ts
index d0a833f13b..53dccc2047 100644
--- a/packages/neuron-wallet/src/services/tx/transaction-generator.ts
+++ b/packages/neuron-wallet/src/services/tx/transaction-generator.ts
@@ -260,12 +260,14 @@ export class TransactionGenerator {
const changeCapacity = BigInt(capacities) - needCapacities - finalFeeInt
const output = new Output(changeCapacity.toString(), Script.fromSDK(addressToScript(changeAddress)))
+ output.isChangeCell = true
tx.addOutput(output)
}
tx.outputs = ArrayUtils.shuffle(tx.outputs)
tx.outputsData = tx.outputs.map(output => output.data || '0x')
+ tx.hash = tx.computeHash()
return tx
}
diff --git a/packages/neuron-wallet/tests/services/cells.test.ts b/packages/neuron-wallet/tests/services/cells.test.ts
index e8afb1bf48..0b4129bdeb 100644
--- a/packages/neuron-wallet/tests/services/cells.test.ts
+++ b/packages/neuron-wallet/tests/services/cells.test.ts
@@ -704,7 +704,15 @@ describe('CellsService', () => {
)
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)],
+ inputs: [
+ Input.fromObject({
+ previousOutput: input!.outPoint(),
+ capacity: input!.capacity,
+ lock: input!.lockScript(),
+ since: '0',
+ status: OutputStatus.Live,
+ }),
+ ],
capacities: toShannon('1000'),
finalFee: TransactionFee.fee(
TransactionSize.input() +
@@ -1492,7 +1500,15 @@ describe('CellsService', () => {
data: liveCell.data,
}),
],
- changeInputs: [new Input(output.outPoint(), '0', output.capacity, output.lockScript(), output.lockHash)],
+ changeInputs: [
+ Input.fromObject({
+ previousOutput: output.outPoint(),
+ since: '0',
+ capacity: output.capacity,
+ lock: output.lockScript(),
+ status: OutputStatus.Live,
+ }),
+ ],
anyoneCanPayOutputs: [
Output.fromObject({
capacity: liveCell.capacity,
@@ -1559,7 +1575,15 @@ describe('CellsService', () => {
data: liveCell.data,
}),
],
- changeInputs: [new Input(output.outPoint(), '0', output.capacity, output.lockScript(), output.lockHash)],
+ changeInputs: [
+ Input.fromObject({
+ previousOutput: output.outPoint(),
+ since: '0',
+ capacity: output.capacity,
+ lock: output.lockScript(),
+ status: OutputStatus.Live,
+ }),
+ ],
anyoneCanPayOutputs: [
Output.fromObject({
capacity: liveCell.capacity,
@@ -1623,7 +1647,15 @@ describe('CellsService', () => {
data: liveCell.data,
}),
],
- changeInputs: [new Input(output.outPoint(), '0', output.capacity, output.lockScript(), output.lockHash)],
+ changeInputs: [
+ Input.fromObject({
+ previousOutput: output.outPoint(),
+ since: '0',
+ capacity: output.capacity,
+ lock: output.lockScript(),
+ status: OutputStatus.Live,
+ }),
+ ],
anyoneCanPayOutputs: [
Output.fromObject({
capacity: liveCell.capacity,