Skip to content

Commit

Permalink
fix: comments
Browse files Browse the repository at this point in the history
  • Loading branch information
devchenyan committed Jan 26, 2025
1 parent fd1c98f commit 76bf66c
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 192 deletions.
4 changes: 3 additions & 1 deletion packages/neuron-ui/src/components/DepositDialog/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
useClearGeneratedTx,
validateAmount,
} from 'utils'
import getMultisigSignStatus from 'utils/getMultisigSignStatus'
import { MAX_DECIMAL_DIGITS, MIN_DEPOSIT_AMOUNT, SHANNON_CKB_RATIO } from 'utils/const'

const PERCENT_100 = 100
Expand Down Expand Up @@ -278,11 +279,12 @@ export const useOnDepositDialogSubmit = ({
const dispatch = useDispatch()
return useCallback(() => {
if (multisigConfig) {
const { canBroadcastAfterSign } = getMultisigSignStatus({ multisigConfig, addresses: wallet.addresses })
dispatch({
type: AppActions.RequestPassword,
payload: {
walletID: wallet.id,
actionType: multisigConfig.m === 1 ? 'send-from-multisig-need-one' : 'send-from-multisig',
actionType: canBroadcastAfterSign ? 'send-from-multisig-need-one' : 'send-from-multisig',
multisigConfig,
onSuccess: onDepositSuccess,
title: 'password-request.verify-password',
Expand Down
12 changes: 10 additions & 2 deletions packages/neuron-wallet/src/controllers/dao.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import OutPoint from '../models/chain/out-point'
import Cell from '../models/chain/output'
import Transaction from '../models/chain/transaction'
import MultisigConfigModel from '../models/multisig-config'
import Multisig from '../models/multisig'

export default class DaoController {
public async getDaoCells(params: Controller.Params.GetDaoCellsParams): Promise<Controller.Response<Cell[]>> {
Expand All @@ -27,7 +28,13 @@ export default class DaoController {
multisigConfig: MultisigConfigModel
}): Promise<Controller.Response<Cell[]>> {
const { multisigConfig } = params
const cells = await CellsService.getMultisigDaoCells(multisigConfig)
const multiSignBlake160 = Multisig.hash(
multisigConfig.blake160s,
multisigConfig.r,
multisigConfig.m,
multisigConfig.n
)
const cells = await CellsService.getDaoCells({ walletId: '', lockArgs: multiSignBlake160 })

if (!cells) {
throw new ServiceHasNoResponse('DaoCells')
Expand Down Expand Up @@ -206,7 +213,8 @@ export default class DaoController {
throw new IsRequired('Parameters')
}

const tx = await new TransactionSender().withdrawFromMultisigDao(
const tx = await new TransactionSender().withdrawFromDao(
'',
OutPoint.fromSDK(params.depositOutPoint),
OutPoint.fromSDK(params.withdrawingOutPoint),
params.fee,
Expand Down
74 changes: 13 additions & 61 deletions packages/neuron-wallet/src/services/cells.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,14 +223,16 @@ export default class CellsService {
return cells
}

public static async getDaoCells(walletId: string): Promise<Cell[]> {
public static async getDaoCells({ walletId, lockArgs }: { walletId: string; lockArgs?: string }): Promise<Cell[]> {
const outputs: OutputEntity[] = await getConnection()
.getRepository(OutputEntity)
.createQueryBuilder('output')
.leftJoinAndSelect('output.transaction', 'tx')
.where(
`
lockArgs
? `
output.daoData IS NOT NULL AND
output.lockArgs = :lockArgs AND
(
output.status = :liveStatus OR
output.status = :sentStatus OR
Expand All @@ -242,65 +244,9 @@ export default class CellsService {
) AND
output.depositTxHash is not null
)
) AND
output.lockArgs in (
SELECT publicKeyInBlake160
FROM hd_public_key_info
WHERE walletId = :walletId
)`,
{
walletId,
liveStatus: OutputStatus.Live,
sentStatus: OutputStatus.Sent,
failedStatus: TransactionStatus.Failed,
deadStatus: OutputStatus.Dead,
pendingStatus: OutputStatus.Pending,
}
)
.orderBy(`CASE output.daoData WHEN '0x0000000000000000' THEN 1 ELSE 0 END`, 'ASC')
.addOrderBy('tx.timestamp', 'ASC')
.getMany()

const cells: Cell[] = outputs.map(output => {
const cell = output.toModel()
if (!output.depositTxHash) {
// if deposit cell, set depositInfo
cell.setDepositInfo({
txHash: output.transaction!.hash,
timestamp: output.transaction!.timestamp!,
})
} else {
// if not deposit cell, set withdrawInfo
const withdrawTx = output.transaction
cell.setWithdrawInfo({
txHash: withdrawTx!.hash,
timestamp: withdrawTx!.timestamp!,
})
}
return cell
})

await Promise.all([CellsService.addDepositInfo(cells), CellsService.addUnlockInfo(cells)])

return cells
}

public static async getMultisigDaoCells(multisigConfig: MultisigConfigModel): Promise<Cell[]> {
const multiSignBlake160 = Multisig.hash(
multisigConfig.blake160s,
multisigConfig.r,
multisigConfig.m,
multisigConfig.n
)

const outputs: OutputEntity[] = await getConnection()
.getRepository(OutputEntity)
.createQueryBuilder('output')
.leftJoinAndSelect('output.transaction', 'tx')
.where(
`
)`
: `
output.daoData IS NOT NULL AND
output.lockArgs = :multiSignBlake160 AND
(
output.status = :liveStatus OR
output.status = :sentStatus OR
Expand All @@ -312,9 +258,15 @@ export default class CellsService {
) AND
output.depositTxHash is not null
)
) AND
output.lockArgs in (
SELECT publicKeyInBlake160
FROM hd_public_key_info
WHERE walletId = :walletId
)`,
{
multiSignBlake160,
walletId,
lockArgs,
liveStatus: OutputStatus.Live,
sentStatus: OutputStatus.Sent,
failedStatus: TransactionStatus.Failed,
Expand Down
149 changes: 24 additions & 125 deletions packages/neuron-wallet/src/services/transaction-sender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -788,7 +788,8 @@ export default class TransactionSender {
depositOutPoint: OutPoint,
withdrawingOutPoint: OutPoint,
fee: string = '0',
feeRate: string = '0'
feeRate: string = '0',
multisigConfig?: MultisigConfigModel
): Promise<Transaction> => {
const DAO_LOCK_PERIOD_EPOCHS = BigInt(180)

Expand All @@ -808,7 +809,9 @@ export default class TransactionSender {
throw new TransactionIsNotCommittedYet()
}

const secpCellDep = await SystemScriptInfo.getInstance().getSecpCellDep()
const cellDep = multisigConfig
? await SystemScriptInfo.getInstance().getMultiSignCellDep()
: await SystemScriptInfo.getInstance().getSecpCellDep()
const daoCellDep = await SystemScriptInfo.getInstance().getDaoCellDep()

const content = withdrawOutput.daoData
Expand Down Expand Up @@ -848,131 +851,27 @@ export default class TransactionSender {

const outputCapacity: bigint = await this.calculateDaoMaximumWithdraw(depositOutPoint, withdrawBlockHeader.hash)

const wallet = WalletService.getInstance().get(walletID)
const address = await wallet.getNextAddress()
const blake160 = AddressParser.toBlake160(address!.address)

const output: Output = new Output(
outputCapacity.toString(),
new Script(SystemScriptInfo.SECP_CODE_HASH, blake160, SystemScriptInfo.SECP_HASH_TYPE),
undefined,
'0x'
)

const outputs: Output[] = [output]

const input: Input = new Input(
withdrawingOutPoint,
minimalSince.toString(),
withdrawOutput.capacity,
withdrawOutput.lock
)

const withdrawWitnessArgs: WitnessArgs = new WitnessArgs(WitnessArgs.EMPTY_LOCK, '0x0000000000000000')
const tx: Transaction = Transaction.fromObject({
version: '0',
cellDeps: [secpCellDep, daoCellDep],
headerDeps: [depositBlockHeader.hash, withdrawBlockHeader.hash],
inputs: [input],
outputs,
outputsData: outputs.map(o => o.data || '0x'),
witnesses: [withdrawWitnessArgs],
interest: (BigInt(outputCapacity) - depositCapacity).toString(),
})
if (mode.isFeeRateMode()) {
const txSize: number = TransactionSize.tx(tx)
const txFee: bigint = TransactionFee.fee(txSize, BigInt(feeRate))
tx.fee = txFee.toString()
tx.outputs[0].capacity = (outputCapacity - txFee).toString()
let output: Output
if (multisigConfig) {
const lockScript = Multisig.getMultisigScript(
multisigConfig.blake160s,
multisigConfig.r,
multisigConfig.m,
multisigConfig.n
)
const multisigAddresses = scriptToAddress(lockScript, NetworksService.getInstance().isMainnet())
output = new Output(outputCapacity.toString(), AddressParser.parse(multisigAddresses), undefined, '0x')
} else {
tx.fee = fee
tx.outputs[0].capacity = (outputCapacity - feeInt).toString()
}

logger.debug('withdrawFromDao fee:', tx.fee)

return tx
}

public withdrawFromMultisigDao = async (
depositOutPoint: OutPoint,
withdrawingOutPoint: OutPoint,
fee: string = '0',
feeRate: string = '0',
multisigConfig: MultisigConfigModel
): Promise<Transaction> => {
const DAO_LOCK_PERIOD_EPOCHS = BigInt(180)

const feeInt = BigInt(fee)
const feeRateInt = BigInt(feeRate)
const mode = new FeeMode(feeRateInt)

const currentNetwork = NetworksService.getInstance().getCurrent()
const rpcService = new RpcService(currentNetwork.remote, currentNetwork.type)

const withdrawOutput = await CellsService.getLiveCell(withdrawingOutPoint)
if (!withdrawOutput) {
throw new CellIsNotYetLive()
}
const prevTx = (await rpcService.getTransaction(withdrawingOutPoint.txHash))!
if (!prevTx.txStatus.isCommitted()) {
throw new TransactionIsNotCommittedYet()
}

const cellDep = await SystemScriptInfo.getInstance().getMultiSignCellDep()
const daoCellDep = await SystemScriptInfo.getInstance().getDaoCellDep()

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 depositTx = await rpcService.getTransaction(withdrawOutput.depositOutPoint.txHash)
if (!depositTx?.txStatus.blockHash) {
throw new Error(`Get deposit block hash failed with tx hash ${withdrawOutput.depositOutPoint.txHash}`)
}
const depositBlockHeader = await rpcService.getHeader(depositTx.txStatus.blockHash)
if (!depositBlockHeader) {
throw new Error(`Get Header failed with blockHash ${depositTx.txStatus.blockHash}`)
}
const depositEpoch = this.parseEpoch(BigInt(depositBlockHeader.epoch))
const depositCapacity: bigint = BigInt(withdrawOutput.capacity)

const withdrawBlockHeader = (await rpcService.getHeader(prevTx.txStatus.blockHash!))!
const withdrawEpoch = this.parseEpoch(BigInt(withdrawBlockHeader.epoch))

const withdrawFraction = withdrawEpoch.index * depositEpoch.length
const depositFraction = depositEpoch.index * withdrawEpoch.length
let depositedEpochs = withdrawEpoch.number - depositEpoch.number
if (withdrawFraction > depositFraction) {
depositedEpochs += BigInt(1)
const wallet = WalletService.getInstance().get(walletID)
const address = await wallet.getNextAddress()
const blake160 = AddressParser.toBlake160(address!.address)
output = new Output(
outputCapacity.toString(),
new Script(SystemScriptInfo.SECP_CODE_HASH, blake160, SystemScriptInfo.SECP_HASH_TYPE),
undefined,
'0x'
)
}
const lockEpochs =
((depositedEpochs + (DAO_LOCK_PERIOD_EPOCHS - BigInt(1))) / DAO_LOCK_PERIOD_EPOCHS) * DAO_LOCK_PERIOD_EPOCHS
const minimalSinceEpochNumber = depositEpoch.number + lockEpochs
const minimalSinceEpochIndex = depositEpoch.index
const minimalSinceEpochLength = depositEpoch.length

const minimalSince = this.epochSince(minimalSinceEpochLength, minimalSinceEpochIndex, minimalSinceEpochNumber)

const outputCapacity: bigint = await this.calculateDaoMaximumWithdraw(depositOutPoint, withdrawBlockHeader.hash)

const lockScript = Multisig.getMultisigScript(
multisigConfig.blake160s,
multisigConfig.r,
multisigConfig.m,
multisigConfig.n
)
const multisigAddresses = scriptToAddress(lockScript, NetworksService.getInstance().isMainnet())

const output: Output = new Output(
outputCapacity.toString(),
AddressParser.parse(multisigAddresses),
undefined,
'0x'
)

const outputs: Output[] = [output]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -505,9 +505,7 @@ export class TransactionGenerator {
const allInputs: Input[] = await CellsService.gatherAllInputs(
walletId,
multisigConfig
? Script.fromSDK(
Multisig.getMultisigScript(multisigConfig.blake160s, multisigConfig.r, multisigConfig.m, multisigConfig.n)
)
? Multisig.getMultisigScript(multisigConfig.blake160s, multisigConfig.r, multisigConfig.m, multisigConfig.n)
: undefined
)
if (allInputs.length === 0) {
Expand Down

0 comments on commit 76bf66c

Please sign in to comment.