Skip to content

Commit

Permalink
[Issue 228] [fix] Recheck ui
Browse files Browse the repository at this point in the history
  • Loading branch information
Thiendekaco committed Jul 5, 2024
1 parent 616b50b commit 89cda57
Show file tree
Hide file tree
Showing 10 changed files with 218 additions and 50 deletions.
7 changes: 5 additions & 2 deletions packages/extension-base/src/background/KoniTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { _BitcoinApi, _ChainState, _EvmApi, _NetworkUpsertParams, _SubstrateApi,
import { CrowdloanContributionsResponse } from '@subwallet/extension-base/services/subscan-service/types';
import { BitcoinTransactionData, SWTransactionResponse, SWTransactionResult } from '@subwallet/extension-base/services/transaction-service/types';
import { WalletConnectNotSupportRequest, WalletConnectSessionRequest } from '@subwallet/extension-base/services/wallet-connect-service/types';
import { BalanceJson, BuyServiceInfo, BuyTokenInfo, EarningRewardHistoryItem, EarningRewardJson, EarningStatus, HandleYieldStepParams, LeavePoolAdditionalData, NominationPoolInfo, OptimalYieldPath, OptimalYieldPathParams, RequestEarlyValidateYield, RequestGetYieldPoolTargets, RequestStakeCancelWithdrawal, RequestStakeClaimReward, RequestSubmitTransfer, RequestSubmitTransferWithId, RequestSubscribeTransfer, RequestUnlockDotCheckCanMint, RequestUnlockDotSubscribeMintedData, RequestYieldLeave, RequestYieldStepSubmit, RequestYieldWithdrawal, ResponseEarlyValidateYield, ResponseGetYieldPoolTargets, ResponseSubscribeTransfer, ResponseSubscribeTransferConfirmation, SubmitYieldStepData, TokenApproveData, UnlockDotTransactionNft, UnstakingStatus, ValidateYieldProcessParams, YieldPoolInfo, YieldPositionInfo, YieldValidationStatus } from '@subwallet/extension-base/types';
import { BalanceJson, BuyServiceInfo, BuyTokenInfo, EarningRewardHistoryItem, EarningRewardJson, EarningStatus, HandleYieldStepParams, LeavePoolAdditionalData, NominationPoolInfo, OptimalYieldPath, OptimalYieldPathParams, RequestEarlyValidateYield, RequestGetYieldPoolTargets, RequestStakeCancelWithdrawal, RequestStakeClaimReward, RequestSubmitSignPsbtTransfer, RequestSubmitTransfer, RequestSubmitTransferWithId, RequestSubscribeTransfer, RequestUnlockDotCheckCanMint, RequestUnlockDotSubscribeMintedData, RequestYieldLeave, RequestYieldStepSubmit, RequestYieldWithdrawal, ResponseEarlyValidateYield, ResponseGetYieldPoolTargets, ResponseSubscribeTransfer, ResponseSubscribeTransferConfirmation, SubmitYieldStepData, TokenApproveData, UnlockDotTransactionNft, UnstakingStatus, ValidateYieldProcessParams, YieldPoolInfo, YieldPositionInfo, YieldValidationStatus } from '@subwallet/extension-base/types';
import { InjectedAccount, InjectedAccountWithMeta, MetadataDefBase } from '@subwallet/extension-inject/types';
import { KeypairType, KeyringPair$Json, KeyringPair$Meta } from '@subwallet/keyring/types';
import { KeyringOptions } from '@subwallet/ui-keyring/options/types';
Expand Down Expand Up @@ -1352,6 +1352,8 @@ export interface PsbtTransactionArg {
export interface BitcoinSignPsbtPayload extends Omit<BitcoinSignPsbtRawRequest, 'psbt'>{
txInput: PsbtTransactionArg[];
txOutput: PsbtTransactionArg[];
to: string;
value: string;
psbt: Psbt;
tokenSlug: string;
}
Expand All @@ -1369,7 +1371,7 @@ export interface BitcoinSignPsbtRawRequest {
allowedSighash?: SignatureHash[];
signAtIndex?: number | number[];
broadcast?: boolean;
network: 'mainnet' | 'testnet';
network: string;
account: string;
}

Expand Down Expand Up @@ -2574,6 +2576,7 @@ export interface KoniRequestSignatures {
'pri(accounts.checkTransfer)': [RequestCheckTransfer, ValidateTransactionResponse];
'pri(accounts.transfer)': [RequestSubmitTransfer, SWTransactionResponse];
'pri(accounts.transfer.after.confirmation)': [RequestSubmitTransferWithId, SWTransactionResponse];
'pri(accounts.psbt.transfer.after.confirmation)': [RequestSubmitSignPsbtTransfer, SWTransactionResponse];
'pri(accounts.getBitcoinTransactionData)': [RequestSubmitTransfer, BitcoinTransactionData];

'pri(accounts.checkCrossChainTransfer)': [RequestCheckCrossChainTransfer, ValidateTransactionResponse];
Expand Down
81 changes: 78 additions & 3 deletions packages/extension-base/src/koni/background/handlers/Extension.ts

Large diffs are not rendered by default.

45 changes: 33 additions & 12 deletions packages/extension-base/src/koni/background/handlers/State.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import WalletConnectService from '@subwallet/extension-base/services/wallet-conn
import { SWStorage } from '@subwallet/extension-base/storage';
import AccountRefStore from '@subwallet/extension-base/stores/AccountRef';
import { BalanceItem, BalanceMap, EvmFeeInfo } from '@subwallet/extension-base/types';
import { isAccountAll, keyringGetAccounts, stripUrl, targetIsWeb } from '@subwallet/extension-base/utils';
import { isAccountAll, isSameAddress, keyringGetAccounts, stripUrl, targetIsWeb } from '@subwallet/extension-base/utils';
import { isContractAddress, parseContractInput } from '@subwallet/extension-base/utils/eth/parseTransaction';
import { createPromiseHandler } from '@subwallet/extension-base/utils/promise';
import { MetadataDef, ProviderMeta } from '@subwallet/extension-inject/types';
Expand All @@ -50,6 +50,7 @@ import { KeypairType } from '@subwallet/keyring/types';
import { keyring } from '@subwallet/ui-keyring';
import BigN from 'bignumber.js';
import * as bitcoin from 'bitcoinjs-lib';
import { Psbt } from 'bitcoinjs-lib';
import BN from 'bn.js';
import SimpleKeyring from 'eth-simple-keyring';
import { t } from 'i18next';
Expand Down Expand Up @@ -1236,7 +1237,7 @@ export default class KoniState {
}

public async bitcoinSignPspt (id: string, url: string, networkKey: string, method: string, params: BitcoinSignPsbtRawRequest, allowedAccounts: string[]): Promise<string | undefined | SignMessageBitcoinResult | SignPsbtBitcoinResult> {
const { account: address, allowedSighash, broadcast, network, psbt, signAtIndex } = params;
const { account: address, allowedSighash, broadcast, psbt, signAtIndex } = params;

if (!psbt || !address) {
throw new BitcoinProviderError(BitcoinProviderErrorType.INVALID_PARAMS, t('Not found payload to sign'));
Expand Down Expand Up @@ -1275,28 +1276,46 @@ export default class KoniState {

const network_ = networkKey === 'bitcoinTestnet' ? bitcoin.networks.testnet : bitcoin.networks.bitcoin;

const psbtGenerate = bitcoin.Psbt.fromHex(psbt, {
const psbtGenerate = Psbt.fromHex(psbt, {
network: network_
});

const tokenInfo = this.getNativeTokenInfo(networkKey);
const isExistedInput = (inputs: PsbtTransactionArg[], address: string) => inputs.findIndex(({ address: address_ }) => isSameAddress(address, address_ || ''));

const psbtInputData = psbtGenerate.data.inputs.map(({ witnessUtxo }) => {
const tokenInfo = this.getNativeTokenInfo(networkKey);
let to = '';
let value = new BigN(0);
const psbtInputData = psbtGenerate.data.inputs.reduce((inputs, { witnessUtxo }) => {
if (!witnessUtxo) {
return {};
return inputs;
}

const address = bitcoin.address.fromOutputScript(witnessUtxo?.script, network_);
const existedInput = isExistedInput(inputs, address);

return {
address,
amount: witnessUtxo.value.toString()
} as PsbtTransactionArg;
});
if (existedInput === -1) {
inputs.push({
address,
amount: witnessUtxo.value.toString()
});
} else {
inputs[existedInput] = {
...inputs[existedInput],
amount: new BigN(inputs[existedInput].amount || 0).plus(new BigN(witnessUtxo.value.toString())).toString()
};
}

return inputs;
}, [] as PsbtTransactionArg[]);

const psbtOutputData = psbtGenerate.txOutputs.map((output) => {
const address = output.address || bitcoin.address.fromOutputScript(output.script, network_);

if (isExistedInput(psbtInputData, address) === -1) {
to = address;
value = value.plus(new BigN(output.value));
}

return {
address,
amount: output.value.toString()
Expand All @@ -1306,7 +1325,9 @@ export default class KoniState {
const payload: BitcoinSignPsbtPayload = {
psbt: psbtGenerate,
broadcast: !!broadcast,
network,
value: value.toString(),
to,
network: networkKey,
signAtIndex: isArray(signAtIndex) && signAtIndex.length === 0 ? undefined : signAtIndex,
account: account.address,
allowedSighash,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ export default class BitcoinRequestHandler {
private async signPsbt (request: ConfirmationDefinitionsBitcoin['bitcoinSignPsbtRequest'][0]): Promise<SignPsbtBitcoinResult> {
// Extract necessary information from the BitcoinSendTransactionRequest
const { account, payload } = request.payload;
const { allowedSighash, broadcast, network, psbt, signAtIndex } = payload;
const { allowedSighash, broadcast, psbt, signAtIndex } = payload;

// todo: validate type of the account

Expand All @@ -299,8 +299,6 @@ export default class BitcoinRequestHandler {
}

const signAtIndexGenerate = signAtIndex ? (isArray(signAtIndex) ? signAtIndex : [signAtIndex]) : [...(Array(psbt.inputCount) as number[])].map((_, i) => i);

console.log(signAtIndexGenerate);
// Sign the Psbt using the pair's bitcoin object
const psptSignedTransaction = pair.bitcoin.signTransaction(psbt, signAtIndexGenerate, allowedSighash);

Expand All @@ -314,18 +312,45 @@ export default class BitcoinRequestHandler {
};
}

const transaction = this.#transactionService.getTransaction(request.id);

console.log(transaction);
const { chain, emitterTransaction, id } = transaction;
const chainInfo = this.#chainService.getChainInfoByKey(chain);
const eventData: TransactionEventResponse = {
id,
errors: [],
warnings: [],
extrinsicHash: id
};

if (!emitterTransaction) {
throw new BitcoinProviderError(BitcoinProviderErrorType.INTERNAL_ERROR);
}

psptSignedTransaction.finalizeAllInputs();

const chain = network === 'mainnet' ? 'bitcoin' : 'bitcoinTestnet';
const hexTransaction = psptSignedTransaction.extractTransaction().toHex();

const txid = await this.#chainService.getBitcoinApi(chain).api.simpleSendRawTransaction(psptSignedTransaction.extractTransaction().toHex());
this.#transactionService.emitterEventTransaction(emitterTransaction, eventData, chainInfo.slug, hexTransaction);
const { promise, reject, resolve } = createPromiseHandler<SignPsbtBitcoinResult>();

console.log('TXID', txid);
emitterTransaction.on('extrinsicHash', (data) => {
if (!data.extrinsicHash) {
reject(BitcoinProviderErrorType.INTERNAL_ERROR);
} else {
resolve({
psbt: psptSignedTransaction.toHex(),
txid: data.extrinsicHash
});
}
});

return {
psbt: psptSignedTransaction.toHex(),
txid
};
emitterTransaction.on('error', (error) => {
reject(error);
});

return promise;
}

private async decorateResultBitcoin<T extends ConfirmationTypeBitcoin> (t: T, request: ConfirmationDefinitionsBitcoin[T][0], result: ConfirmationDefinitionsBitcoin[T][1]) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ export default class TransactionService {
address,
chain,
edAsWarning,
estimateFee: estimateFee_,
extrinsicType,
feeCustom,
feeOption,
Expand All @@ -130,7 +131,7 @@ export default class TransactionService {
const chainInfo = this.state.chainService.getChainInfoByKey(chain);

// Estimate fee
const estimateFee: FeeData = {
const estimateFee: FeeData = estimateFee_ || {
symbol: '',
decimals: 0,
value: '',
Expand All @@ -147,7 +148,7 @@ export default class TransactionService {

const id = getId();

if (transaction) {
if (transaction && !estimateFee_) {
try {
if (isSubstrateTransaction(transaction)) {
estimateFee.value = (await transaction.paymentInfo(address)).partialFee.toString();
Expand Down Expand Up @@ -388,7 +389,7 @@ export default class TransactionService {
const emitter = new EventEmitter<TransactionEventMap>();

// Fill transaction default info
const transactionUpdated = this.fillTransactionDefaultInfo(transaction);
const transactionUpdated = this.fillTransactionDefaultInfo(validatedTransaction);

// Add Transaction
transactionsSubject[transactionUpdated.id] = { ...transactionUpdated, emitterTransaction: emitter };
Expand Down
15 changes: 14 additions & 1 deletion packages/extension-base/src/types/balance/transfer.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// Copyright 2019-2022 @subwallet/extension-base authors & contributors
// SPDX-License-Identifier: Apache-2.0

import { BaseRequestSign } from '@subwallet/extension-base/background/KoniTypes';
import { BaseRequestSign, PsbtTransactionArg } from '@subwallet/extension-base/background/KoniTypes';
import { Psbt } from 'bitcoinjs-lib';

import { FeeChainType, FeeDetail, TransactionFee } from '../fee';

Expand Down Expand Up @@ -39,3 +40,15 @@ export interface RequestSubmitTransfer extends BaseRequestSign, TransactionFee {
export interface RequestSubmitTransferWithId extends RequestSubmitTransfer{
id?: string;
}

export interface RequestSubmitSignPsbtTransfer extends BaseRequestSign {
id: string;
chain: string;
from: string;
to: string;
value: string;
txInput: PsbtTransactionArg[];
txOutput: PsbtTransactionArg[];
tokenSlug: string;
psbt: Psbt;
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ const BaseDetailModal = styled(Component)<Props>(({ theme: { token } }: Props) =

'.__label': {
textTransform: 'capitalize'
},

'.ant-web3-block-right-item': {
marginRight: 0
}
};
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// Copyright 2019-2022 @subwallet/extension-koni-ui authors & contributors
// SPDX-License-Identifier: Apache-2.0

import { BitcoinSignatureRequest, ConfirmationDefinitionsBitcoin, ConfirmationResult, EvmSendTransactionRequest, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
import { BitcoinSignatureRequest, BitcoinSignPsbtRequest, ConfirmationDefinitionsBitcoin, ConfirmationResult, EvmSendTransactionRequest, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
import { RequestSubmitTransferWithId } from '@subwallet/extension-base/types';
import { wait } from '@subwallet/extension-base/utils';
import { CONFIRMATION_QR_MODAL } from '@subwallet/extension-koni-ui/constants';
import { useGetChainInfoByChainId, useLedger, useNotification, useUnlockChecker } from '@subwallet/extension-koni-ui/hooks';
import { completeConfirmationBitcoin, makeTransferAfterConfirmation } from '@subwallet/extension-koni-ui/messaging';
import { completeConfirmationBitcoin, makePSBTTransferAfterConfirmation, makeTransferAfterConfirmation } from '@subwallet/extension-koni-ui/messaging';
import { AccountSignMode, BitcoinSignatureSupportType, PhosphorIcon, SigData, ThemeProps } from '@subwallet/extension-koni-ui/types';
import { getSignMode, isBitcoinMessage, removeTransactionPersist } from '@subwallet/extension-koni-ui/utils';
import { Button, Icon, ModalContext } from '@subwallet/react-ui';
Expand Down Expand Up @@ -55,7 +55,7 @@ const handleSignature = async (type: BitcoinSignatureSupportType, id: string, si
const Component: React.FC<Props> = (props: Props) => {
const { canSign, className, editedPayload, extrinsicType, id, payload, type } = props;
const { payload: { hashPayload } } = payload;
const account = (payload.payload as BitcoinSignatureRequest).account;
const { account } = (payload.payload as BitcoinSignatureRequest);
const chainId = (payload.payload as EvmSendTransactionRequest)?.chainId || 1;

const { t } = useTranslation();
Expand Down Expand Up @@ -110,15 +110,31 @@ const Component: React.FC<Props> = (props: Props) => {

const onApprovePassword = useCallback(() => {
setLoading(true);
(type === 'bitcoinSendTransactionRequestAfterConfirmation' && editedPayload ? makeTransferAfterConfirmation(editedPayload) : wait(1000))
.then(() => {
console.log('complete', type, id);
handleConfirm(type, id, '').finally(() => {
setLoading(false);
});
})

const promise = async () => {
if (type === 'bitcoinSendTransactionRequestAfterConfirmation' && editedPayload) {
await makeTransferAfterConfirmation(editedPayload);
} else if (type === 'bitcoinSignPsbtRequest') {
const { payload: { account, broadcast, network, psbt, to, tokenSlug, txInput, txOutput, value } } = payload.payload as BitcoinSignPsbtRequest;

if (broadcast) {
await makePSBTTransferAfterConfirmation({ id, chain: network, txOutput, txInput, tokenSlug, psbt, from: account, to, value });
} else {
await wait(1000);
}
} else {
await wait(1000);
}
};

promise().then(() => {
console.log('complete', type, id);
handleConfirm(type, id, '').finally(() => {
setLoading(false);
});
})
.catch(console.error);
}, [editedPayload, id, type]);
}, [editedPayload, id, payload.payload, type]);

const onApproveSignature = useCallback((signature: SigData) => {
setLoading(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { useOpenDetailModal } from '@subwallet/extension-koni-ui/hooks';
import { BitcoinSignArea } from '@subwallet/extension-koni-ui/Popup/Confirmations/parts';
import { RootState } from '@subwallet/extension-koni-ui/stores';
import { BitcoinSignatureSupportType, ThemeProps } from '@subwallet/extension-koni-ui/types';
import { findAccountByAddress } from '@subwallet/extension-koni-ui/utils';
import { Button, Number } from '@subwallet/react-ui';
import CN from 'classnames';
import React, { useCallback, useMemo } from 'react';
Expand All @@ -27,18 +28,22 @@ function Component ({ className, request, type }: Props) {
const { t } = useTranslation();
const { account } = payload;
const { tokenSlug, txInput, txOutput } = request.payload.payload;
const accounts = useSelector((state: RootState) => state.accountState.accounts);
const assetRegistry = useSelector((root: RootState) => root.assetRegistry.assetRegistry);
const onClickDetail = useOpenDetailModal();

const assetInfo: _ChainAsset | undefined = useMemo(() => {
return assetRegistry[tokenSlug];
}, [assetRegistry, tokenSlug]);
const renderAccount = useCallback((accounts: PsbtTransactionArg[]) => {
const renderAccount = useCallback((accountsPsbt: PsbtTransactionArg[]) => {
return (
<>
<div style={{ display: 'flex', flexDirection: 'column', gap: '4px' }}>
{
accounts.map(({ address, amount }) =>
<AccountItemWithName
accountsPsbt.map(({ address, amount }) => {
const account = findAccountByAddress(accounts, address);

return (<AccountItemWithName
accountName={account?.name}
address={address || ''}
key={address}
rightItem={amount
Expand All @@ -48,13 +53,14 @@ function Component ({ className, request, type }: Props) {
value={amount}
/>
: <></>}
/>
/>);
}
)
}

</>
</div>
);
}, [assetInfo.decimals, assetInfo.symbol]);
}, [accounts, assetInfo.decimals, assetInfo.symbol]);

return (
<>
Expand Down
Loading

0 comments on commit 89cda57

Please sign in to comment.