Skip to content

Commit

Permalink
v4 fix: several fee issues OK-26141 OK-25859 OK-26144 (#4243)
Browse files Browse the repository at this point in the history
* fix: use fee in dapp tx

* feat: add priority fee to sol dapp tx by default

* chore: update comments

* chore: update comments
  • Loading branch information
weatherstar authored Mar 14, 2024
1 parent f1c81d1 commit c486744
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 68 deletions.
33 changes: 0 additions & 33 deletions packages/engine/src/vaults/impl/evm/Vault.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1294,31 +1294,6 @@ export default class Vault extends VaultBase {
prices?.length && prices?.every((price) => typeof price === 'object'),
);

const gasLimitInTx = new BigNumber(
encodedTx.gas ?? encodedTx.gasLimit ?? 0,
).toFixed();
// NOTE: gasPrice deleted in removeFeeInfoInTx() if encodedTx build by DAPP
let gasPriceInTx: string | EIP1559Fee | undefined = encodedTx.gasPrice
? this._toNormalAmount(encodedTx.gasPrice, network.feeDecimals)
: undefined;
if (eip1559) {
gasPriceInTx = merge(
{
...(prices[0] as EIP1559Fee),
},
{
maxPriorityFeePerGas: encodedTx.maxPriorityFeePerGas
? this._toNormalAmount(
encodedTx.maxPriorityFeePerGas,
network.feeDecimals,
)
: undefined,
maxFeePerGas: encodedTx.maxFeePerGas
? this._toNormalAmount(encodedTx.maxFeePerGas, network.feeDecimals)
: undefined,
},
) as EIP1559Fee;
}
// [{baseFee: '928.361757873', maxPriorityFeePerGas: '11.36366', maxFeePerGas: '939.725417873'}]
// [10]
const limit = BigNumber.max(
Expand All @@ -1343,14 +1318,6 @@ export default class Vault extends VaultBase {
prices,
defaultPresetIndex: '1',

// feeInfo in original tx
tx: {
eip1559,
limit: gasLimitInTx,
...(eip1559
? { price1559: gasPriceInTx as EIP1559Fee }
: { price: gasPriceInTx as string }),
},
baseFeeValue,
extraInfo: {
networkCongestion,
Expand Down
78 changes: 71 additions & 7 deletions packages/engine/src/vaults/impl/sol/Vault.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,15 @@ import {
getAssociatedTokenAddressSync,
} from '@solana/spl-token';
import {
ComputeBudgetInstruction,
ComputeBudgetProgram,
MessageAccountKeys,
PublicKey,
SYSVAR_INSTRUCTIONS_PUBKEY,
SystemInstruction,
SystemProgram,
Transaction,
TransactionMessage,
VersionedTransaction,
} from '@solana/web3.js';
import axios from 'axios';
Expand Down Expand Up @@ -1037,14 +1040,73 @@ export default class Vault extends VaultBase {
return Promise.resolve(encodedTx);
}

const nativeTx = (await this.helper.parseToNativeTx(
encodedTx,
)) as Transaction;
const [instruction] = nativeTx.instructions;
const nativeTx = await this.helper.parseToNativeTx(encodedTx);

// add priority fees to DApp tx by default
try {
if (options.type === IEncodedTxUpdateType.priorityFees) {
const isVersionedTransaction = nativeTx instanceof VersionedTransaction;
let instructions: TransactionInstruction[] = [];
let unitPrice;
let transactionMessage;
if (isVersionedTransaction) {
transactionMessage = TransactionMessage.decompile(nativeTx.message);
instructions = transactionMessage.instructions;
} else {
instructions = nativeTx.instructions;
}

// try to find if the transaction has already set the compute unit price(priority fee)
try {
for (const instruction of instructions) {
unitPrice =
ComputeBudgetInstruction.decodeSetComputeUnitPrice(instruction);
}
} catch {
// pass
}

// if not set, add the compute unit price(priority fee) to the transaction
if (isNil(unitPrice)) {
const client = await this.getClient();
const accountAddress = await this.getAccountAddress();
const prioritizationFee = await client.getRecentMaxPrioritizationFees(
[accountAddress],
);

const addPriorityFee = ComputeBudgetProgram.setComputeUnitPrice({
microLamports: Math.max(MIN_PRIORITY_FEE, prioritizationFee),
});

if (isVersionedTransaction) {
transactionMessage?.instructions.push(addPriorityFee);
} else {
(nativeTx as Transaction).add(addPriorityFee);
}
}

if (isVersionedTransaction) {
return bs58.encode(
new VersionedTransaction(
(transactionMessage as TransactionMessage).compileToV0Message(),
).serialize(),
);
}

return bs58.encode(
(nativeTx as Transaction).serialize({ requireAllSignatures: false }),
);
}
} catch (e) {
return encodedTx;
}

const nativeTxForUpdateTransfer = nativeTx as Transaction;
const [instruction] = nativeTxForUpdateTransfer.instructions;
// max native token transfer update
if (
options.type === 'transfer' &&
nativeTx.instructions.length === 1 &&
nativeTxForUpdateTransfer.instructions.length === 1 &&
instruction.programId.toString() === SystemProgram.programId.toString()
) {
const instructionType =
Expand All @@ -1056,7 +1118,7 @@ export default class Vault extends VaultBase {
this.networkId,
);
const { amount } = payload as IEncodedTxUpdatePayloadTransfer;
nativeTx.instructions = [
nativeTxForUpdateTransfer.instructions = [
SystemProgram.transfer({
fromPubkey,
toPubkey,
Expand All @@ -1065,7 +1127,9 @@ export default class Vault extends VaultBase {
),
}),
];
return bs58.encode(nativeTx.serialize({ requireAllSignatures: false }));
return bs58.encode(
nativeTxForUpdateTransfer.serialize({ requireAllSignatures: false }),
);
}
}
return Promise.resolve(encodedTx);
Expand Down
1 change: 1 addition & 0 deletions packages/engine/src/vaults/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ export enum IEncodedTxUpdateType {
cancel = 'cancel',
advancedSettings = 'advancedSettings',
customData = 'customData',
priorityFees = 'priorityFees',
}

export type IEncodedTxUpdateOptions = {
Expand Down
72 changes: 52 additions & 20 deletions packages/kit/src/views/Send/modals/SendConfirmFromDapp.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { useEffect, useRef } from 'react';
import { useCallback, useEffect, useRef } from 'react';

import { StackActions, useNavigation } from '@react-navigation/native';
import { AppState } from 'react-native';

import type { IEncodedTxBtc } from '@onekeyhq/engine/src/vaults/impl/btc/types';
import { IEncodedTxUpdateType } from '@onekeyhq/engine/src/vaults/types';
import { IMPL_SOL } from '@onekeyhq/shared/src/engine/engineConsts';

import backgroundApiProxy from '../../../background/instance/backgroundApiProxy';
import { getActiveWalletAccount } from '../../../hooks';
import useDappParams from '../../../hooks/useDappParams';
import { useReduxReady } from '../../../hooks/useReduxReady';
Expand Down Expand Up @@ -35,37 +38,37 @@ export function SendConfirmFromDapp() {
_$t = undefined,
networkId: dappNetworkId,
} = useDappParams();
useEffect(() => {
if (!isReady) {
return;
}
// OK-16560: navigate when app in background would cause modal render in wrong size
const appStateListener = AppState.addEventListener('change', (state) => {
if (state === 'active') {
setTimeout(() => {
if (pendingAction.current) {
navigation.dispatch(pendingAction.current);
pendingAction.current = undefined;
}
});
}
});

const navigateToSendConfirm = useCallback(async () => {
let action: any;
// TODO get network and account from dapp connections
const { networkId, accountId } = getActiveWalletAccount();
const { networkId, accountId, networkImpl } = getActiveWalletAccount();

// alert(JSON.stringify({ networkId, accountId, isReady }));
// TODO providerName
if (encodedTx) {
const isPsbt = (encodedTx as IEncodedTxBtc).psbtHex;
let newEncodedTx = encodedTx;
const isPsbt = (newEncodedTx as IEncodedTxBtc).psbtHex;

if (networkImpl === IMPL_SOL) {
newEncodedTx = await backgroundApiProxy.engine.updateEncodedTx({
accountId,
networkId,
encodedTx,
payload: {},
options: {
type: IEncodedTxUpdateType.priorityFees,
},
});
}

const params: SendConfirmParams = {
networkId: dappNetworkId ?? networkId,
accountId,
sourceInfo,
encodedTx,
encodedTx: newEncodedTx,
feeInfoEditable: !isPsbt,
feeInfoUseFeeInTx: !!isPsbt,
feeInfoUseFeeInTx: true,
ignoreFetchFeeCalling: !!isPsbt,
signOnly,
// @ts-ignore
Expand Down Expand Up @@ -95,6 +98,34 @@ export function SendConfirmFromDapp() {
pendingAction.current = action;
}
}
}, [
_$t,
dappNetworkId,
encodedTx,
navigation,
signOnly,
sourceInfo,
unsignedMessage,
]);

useEffect(() => {
if (!isReady) {
return;
}
// OK-16560: navigate when app in background would cause modal render in wrong size
const appStateListener = AppState.addEventListener('change', (state) => {
if (state === 'active') {
setTimeout(() => {
if (pendingAction.current) {
navigation.dispatch(pendingAction.current);
pendingAction.current = undefined;
}
});
}
});

navigateToSendConfirm();

return () => {
appStateListener.remove();
};
Expand All @@ -107,6 +138,7 @@ export function SendConfirmFromDapp() {
unsignedMessage,
signOnly,
dappNetworkId,
navigateToSendConfirm,
]);

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,11 @@ export async function prepareSendConfirmEncodedTx({
// routeParams is not editable, so should create new one
let tx = { ...encodedTxEvm };
tx.from = tx.from || address;
// remove gas price if encodedTx build by DAPP
if (sendConfirmParams.sourceInfo) {
tx = removeFeeInfoInTx(tx);
}
// keep gas price if encodedTx build by DAPP

// if (sendConfirmParams.sourceInfo) {
// tx = removeFeeInfoInTx(tx);
// }

// Ensure IEncodedTxEvm's value is hex string.
if (tx.value && tx.value.startsWith && !tx.value.startsWith('0x')) {
Expand Down
24 changes: 20 additions & 4 deletions packages/kit/src/views/Send/utils/useFeeInfoPayload.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import BigNumber from 'bignumber.js';

import { ToastManager } from '@onekeyhq/components';
import { FailedToEstimatedGasError } from '@onekeyhq/engine/src/errors';
import type { EIP1559Fee } from '@onekeyhq/engine/src/types/network';
import type { IEncodedTxEvm } from '@onekeyhq/engine/src/vaults/impl/evm/Vault';
import type {
IEncodedTx,
Expand Down Expand Up @@ -163,7 +164,6 @@ export function useFeeInfoPayload({
gasPrice,
} = encodedTx as IEncodedTxEvm;
const limit = gasLimit || gas;

if (maxFeePerGas && maxPriorityFeePerGas) {
const price1559 = {
baseFee: new BigNumber(gasPrice ?? 0)
Expand All @@ -177,23 +177,39 @@ export function useFeeInfoPayload({
.toFixed(),
};
info.eip1559 = true;
info.limit = limit;
info.limit = limit || info.limit;
info.prices = [price1559];
info.tx = {
eip1559: true,
limit,
price1559,
};
} else {
} else if (gasPrice) {
const price = new BigNumber(gasPrice ?? 0)
.shiftedBy(-(feeDecimals ?? 0))
.toFixed();
info.limit = limit;
info.limit = limit || info.limit;
info.prices = [price];
info.tx = {
limit,
price,
};
} else if (limit) {
info.tx = {
limit,
eip1559: info.eip1559,
...(info.eip1559
? {
price1559: info.prices[
Number(info.defaultPresetIndex)
] as EIP1559Fee,
}
: {
price: info.prices[
Number(info.defaultPresetIndex)
] as string,
}),
};
}
}
}
Expand Down

0 comments on commit c486744

Please sign in to comment.