Skip to content

Commit

Permalink
feat: parse tx (#6456)
Browse files Browse the repository at this point in the history
* chore: init SignatureConfirm entry

* chore: init SignatureConfirm router

* chore: all enable new signaure confirm entry

* feat: parse tx send token/nft types

* feat: use signature confirm entry

* refactor: replace send confirm route with signature confirm

* refactor: replace send confirm route with signature confirm

* fix: signature confirm router

* fix: lint

* feat: service signatureConfirm

* feat: enable serviceSignatureConfirm

* chore: update several signature confirm comments

* feat: signature confirm account info

* feat: render tx account info

* feat: render tx details

* feat: tx advanced settings

* feat: tx actions

* feat: tx fee info

* fix: lint

* fix: lint

* fix: data viewer

* fix: tx abi string

* fix: token approval

* fix: aprove token amount

* fix: tx alerts

* fix: native token balance alert

* fix: lint

* fix: swap extra info

* fix: parse tx through api fallback

* fix: handle default tx display

* fix: sol extra fee info

* fix: confirm title

* feat: confirm loading state

* fix: lint
  • Loading branch information
weatherstar authored Jan 9, 2025
1 parent 2f85fde commit 834ae5b
Show file tree
Hide file tree
Showing 82 changed files with 7,494 additions and 217 deletions.
7 changes: 7 additions & 0 deletions packages/core/src/chains/sol/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,10 @@ import type { Transaction, VersionedTransaction } from '@solana/web3.js';

export type IEncodedTxSol = string; // bs58 encoded string
export type INativeTxSol = Transaction | VersionedTransaction;
export type IDecodedTxExtraSol = {
createTokenAccountFee?: {
amount: string;
amountValue: string;
symbol: string;
};
};
10 changes: 10 additions & 0 deletions packages/kit-bg/src/apis/BackgroundApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -563,5 +563,15 @@ class BackgroundApi extends BackgroundApiBase implements IBackgroundApi {
Object.defineProperty(this, 'serviceCustomRpc', { value });
return value;
}

get serviceSignatureConfirm() {
const ServiceSignatureConfirm =
require('../services/ServiceSignatureConfirm') as typeof import('../services/ServiceSignatureConfirm');
const value = new ServiceSignatureConfirm.default({
backgroundApi: this,
});
Object.defineProperty(this, 'serviceSignatureConfirm', { value });
return value;
}
}
export default BackgroundApi;
5 changes: 5 additions & 0 deletions packages/kit-bg/src/apis/BackgroundApiProxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import type ServiceScanQRCode from '../services/ServiceScanQRCode';
import type ServiceSend from '../services/ServiceSend';
import type ServiceSetting from '../services/ServiceSetting';
import type ServiceSignature from '../services/ServiceSignature';
import type ServiceSignatureConfirm from '../services/ServiceSignatureConfirm';
import type ServiceSpotlight from '../services/ServiceSpotlight';
import type ServiceStaking from '../services/ServiceStaking';
import type ServiceSwap from '../services/ServiceSwap';
Expand Down Expand Up @@ -246,6 +247,10 @@ class BackgroundApiProxy
serviceCustomRpc = this._createProxyService(
'serviceCustomRpc',
) as ServiceCustomRpc;

serviceSignatureConfirm = this._createProxyService(
'serviceSignatureConfirm',
) as ServiceSignatureConfirm;
}

export default BackgroundApiProxy;
2 changes: 2 additions & 0 deletions packages/kit-bg/src/apis/IBackgroundApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import type ServiceScanQRCode from '../services/ServiceScanQRCode';
import type ServiceSend from '../services/ServiceSend';
import type ServiceSetting from '../services/ServiceSetting';
import type ServiceSignature from '../services/ServiceSignature';
import type ServiceSignatureConfirm from '../services/ServiceSignatureConfirm';
import type ServiceSpotlight from '../services/ServiceSpotlight';
import type ServiceStaking from '../services/ServiceStaking';
import type ServiceSwap from '../services/ServiceSwap';
Expand Down Expand Up @@ -177,4 +178,5 @@ export interface IBackgroundApi extends IBackgroundApiBridge {
serviceNostr: ServiceNostr;
serviceUniversalSearch: ServiceUniversalSearch;
serviceStaking: ServiceStaking;
serviceSignatureConfirm: ServiceSignatureConfirm;
}
7 changes: 5 additions & 2 deletions packages/kit-bg/src/services/ServiceDApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { parseRPCResponse } from '@onekeyhq/shared/src/request/utils';
import {
EDAppConnectionModal,
EModalRoutes,
EModalSendRoutes,
EModalSignatureConfirmRoutes,
ERootRoutes,
} from '@onekeyhq/shared/src/routes';
import accountUtils from '@onekeyhq/shared/src/utils/accountUtils';
Expand Down Expand Up @@ -302,7 +302,10 @@ class ServiceDApp extends ServiceBase {
}): Promise<ISignedTxPro> {
return this.openModal({
request,
screens: [EModalRoutes.SendModal, EModalSendRoutes.SendConfirmFromDApp],
screens: [
EModalRoutes.SignatureConfirmModal,
EModalSignatureConfirmRoutes.TxConfirmFromDApp,
],
params: {
encodedTx,
transfersInfo,
Expand Down
6 changes: 2 additions & 4 deletions packages/kit-bg/src/services/ServiceSend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,9 @@ import type {
IFeeInfoUnit,
ISendSelectedFeeInfo,
} from '@onekeyhq/shared/types/fee';
import type {
ESendPreCheckTimingEnum,
IParseTransactionResp,
} from '@onekeyhq/shared/types/send';
import type { ESendPreCheckTimingEnum } from '@onekeyhq/shared/types/send';
import { EReasonForNeedPassword } from '@onekeyhq/shared/types/setting';
import type { IParseTransactionResp } from '@onekeyhq/shared/types/signatureConfirm';
import type { IFetchTokenDetailItem } from '@onekeyhq/shared/types/token';
import type {
EReplaceTxType,
Expand Down
217 changes: 217 additions & 0 deletions packages/kit-bg/src/services/ServiceSignatureConfirm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
import type { IUnsignedTxPro } from '@onekeyhq/core/src/types';
import {
backgroundClass,
backgroundMethod,
} from '@onekeyhq/shared/src/background/backgroundDecorators';
import {
convertAddressToSignatureConfirmAddress,
convertDecodedTxActionsToSignatureConfirmTxDisplayComponents,
convertDecodedTxActionsToSignatureConfirmTxDisplayTitle,
convertNetworkToSignatureConfirmNetwork,
} from '@onekeyhq/shared/src/utils/txActionUtils';
import { EServiceEndpointEnum } from '@onekeyhq/shared/types/endpoint';
import {
EParseTxType,
type IParseTransactionResp,
} from '@onekeyhq/shared/types/signatureConfirm';
import type {
IDecodedTx,
IParseTransactionParams,
ISendTxBaseParams,
} from '@onekeyhq/shared/types/tx';

import { vaultFactory } from '../vaults/factory';

import ServiceBase from './ServiceBase';

import type { IBuildDecodedTxParams } from '../vaults/types';

@backgroundClass()
class ServiceSignatureConfirm extends ServiceBase {
constructor({ backgroundApi }: { backgroundApi: any }) {
super({ backgroundApi });
}

@backgroundMethod()
async buildDecodedTxs(
params: ISendTxBaseParams &
Omit<IBuildDecodedTxParams, 'unsignedTx'> & {
unsignedTxs: IUnsignedTxPro[];
},
) {
const { unsignedTxs, accountId, networkId, ...rest } = params;

let accountAddress = params.accountAddress;
if (!accountAddress) {
accountAddress =
await this.backgroundApi.serviceAccount.getAccountAddressForApi({
accountId,
networkId,
});
}
const isMultiTxs = unsignedTxs.length > 1;
const r = await Promise.all(
params.unsignedTxs.map((unsignedTx) =>
this.buildDecodedTx({
...rest,
accountId,
networkId,
accountAddress,
unsignedTx,
isMultiTxs,
}),
),
);

if (r[0] && r[0].txDisplay && r[0].isLocalParsed) {
// add network and account info as leading components

r[0].txDisplay.components.unshift(
convertAddressToSignatureConfirmAddress({
address: accountAddress,
}),
);

r[0].txDisplay.components.unshift(
convertNetworkToSignatureConfirmNetwork({
networkId,
}),
);

r[0].txDisplay.title =
convertDecodedTxActionsToSignatureConfirmTxDisplayTitle({
decodedTxs: r,
unsignedTxs: params.unsignedTxs,
});
}

console.log('r', r);

return r;
}

@backgroundMethod()
async buildDecodedTx(
params: ISendTxBaseParams &
IBuildDecodedTxParams & {
isMultiTxs?: boolean;
},
): Promise<IDecodedTx> {
const {
networkId,
accountId,
accountAddress,
unsignedTx,
feeInfo,
transferPayload,
saveToLocalHistory,
isMultiTxs,
} = params;

let parsedTx: IParseTransactionResp | null = null;

// try to parse tx through background api
// multi txs not supported by api for now, will support in future versions
if (!isMultiTxs) {
try {
parsedTx = await this.parseTransaction({
networkId,
accountId,
accountAddress,
encodedTx: unsignedTx.encodedTx,
});
} catch (e) {
console.log('parse tx through api failed', e);
}
}

if (
parsedTx &&
(unsignedTx.stakingInfo || unsignedTx.swapInfo) &&
parsedTx?.type === EParseTxType.Unknown
) {
parsedTx = null;
}

const vault = await vaultFactory.getVault({ networkId, accountId });
const decodedTx = await vault.buildDecodedTx({
unsignedTx,
transferPayload,
saveToLocalHistory,
isToContract: parsedTx?.parsedTx?.to?.isContract,
});

if (feeInfo) {
decodedTx.totalFeeInNative =
feeInfo.totalNativeForDisplay ?? feeInfo.totalNative;
decodedTx.totalFeeFiatValue =
feeInfo.totalFiatForDisplay ?? feeInfo.totalFiat;
decodedTx.feeInfo = feeInfo.feeInfo;
}

if (parsedTx && parsedTx.display) {
decodedTx.txDisplay = parsedTx.display;
decodedTx.txABI = parsedTx.parsedTx?.data;
} else {
// convert decodedTx actions to signatureConfirm txDisplay as fallback
const txDisplayComponents =
convertDecodedTxActionsToSignatureConfirmTxDisplayComponents({
decodedTx,
isMultiTxs,
unsignedTx,
});

decodedTx.txDisplay = {
title: '',
components: txDisplayComponents,
alerts: [],
};
decodedTx.isLocalParsed = true;
}

return decodedTx;
}

@backgroundMethod()
async parseTransaction(params: IParseTransactionParams) {
const { accountId, networkId, encodedTx } = params;
const vault = await vaultFactory.getVault({
networkId,
accountId,
});
let accountAddress = params.accountAddress;
if (!accountAddress) {
accountAddress =
await this.backgroundApi.serviceAccount.getAccountAddressForApi({
accountId,
networkId,
});
}

const { encodedTx: encodedTxToParse } =
await vault.buildParseTransactionParams({
encodedTx,
});

const client = await this.backgroundApi.serviceGas.getClient(
EServiceEndpointEnum.Wallet,
);
const resp = await client.post<{ data: IParseTransactionResp }>(
'/wallet/v1/account/parse-transaction',
{
networkId,
accountAddress,
encodedTx: encodedTxToParse,
},
{
headers:
await this.backgroundApi.serviceAccountProfile._getWalletTypeHeader({
accountId,
}),
},
);
return resp.data.data;
}
}

export default ServiceSignatureConfirm;
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export enum EJotaiContextStoreNames {
universalSearch = 'universalSearch',
earn = 'earn',
sendConfirm = 'sendConfirm',
signatureConfirm = 'signatureConfirm',
}
export type IJotaiContextStoreData = {
storeName: EJotaiContextStoreNames;
Expand Down
15 changes: 1 addition & 14 deletions packages/kit-bg/src/vaults/impls/evm/Vault.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ export default class Vault extends VaultBase {
icon: network.logoURI ?? '',
},
};
let isToContract: boolean | undefined;
let isToContract: boolean | undefined = params.isToContract;
let extraNativeTransferAction: IDecodedTxAction | undefined;

if (swapInfo) {
Expand Down Expand Up @@ -272,19 +272,6 @@ export default class Vault extends VaultBase {
}
}

try {
const parseResult =
await this.backgroundApi.serviceSend.parseTransaction({
accountId: this.accountId,
networkId: this.networkId,
encodedTx,
accountAddress,
});
isToContract = parseResult.parsedTx.to.isContract;
} catch (e) {
// ignore
}

if (
isToContract === false ||
checkIsEvmNativeTransfer({ tx: nativeTx })
Expand Down
Loading

0 comments on commit 834ae5b

Please sign in to comment.