Skip to content

Commit

Permalink
Refactor and fix some error
Browse files Browse the repository at this point in the history
  • Loading branch information
S2kael committed Sep 7, 2024
1 parent 2356e0c commit 084a061
Show file tree
Hide file tree
Showing 11 changed files with 182 additions and 463 deletions.
5 changes: 5 additions & 0 deletions packages/extension-base/src/background/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ export interface AccountJson extends AbstractAddressJson {
/** Account abstraction */
}

export interface SmartAccountData {
owner: string;
provider?: AccountContract;
}

export interface AddressJson extends AbstractAddressJson {
isRecent?: boolean;
recentChainSlugs?: string[];
Expand Down
482 changes: 90 additions & 392 deletions packages/extension-base/src/koni/background/handlers/Extension.ts

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,28 +1,11 @@
// Copyright 2019-2022 @subwallet/extension-base authors & contributors
// SPDX-License-Identifier: Apache-2.0

import {
batchTx,
BiconomyV2AccountInitData,
BridgePlugin,
BridgePluginParams,
buildItx,
buildMultichainReadonlyClient,
buildRpcInfo,
buildTokenMapping,
deployment,
encodeApproveTx,
initKlaster,
klasterNodeHost,
KlasterSDK,
loadBicoV2Account,
MultichainClient,
MultichainTokenMapping, QuoteResponse,
rawTx
} from 'klaster-sdk';
import { _ChainAsset, _ChainInfo } from '@subwallet/chain-list/types';
import { _getContractAddressOfToken, _getEvmChainId } from '@subwallet/extension-base/services/chain-service/utils';
import { Abi } from 'abitype/src/abi';
import { batchTx, BiconomyV2AccountInitData, BridgePlugin, BridgePluginParams, buildItx, buildMultichainReadonlyClient, buildRpcInfo, buildTokenMapping, deployment, encodeApproveTx, initKlaster, klasterNodeHost, KlasterSDK, loadBicoV2Account, MultichainClient, MultichainTokenMapping, QuoteResponse, rawTx } from 'klaster-sdk';
import { encodeFunctionData, Hex, parseAbi } from 'viem';
import {_ChainAsset, _ChainInfo} from "@subwallet/chain-list/types";
import {_getContractAddressOfToken, _getEvmChainId} from "@subwallet/extension-base/services/chain-service/utils";

export interface AcrossSuggestedFeeResp {
totalRelayFee: {
Expand Down Expand Up @@ -54,7 +37,7 @@ function encodeAcrossCallData (data: BridgePluginParams, fees: AcrossSuggestedFe
// @ts-ignore
const abi = parseAbi([
'function depositV3(address depositor, address recipient, address inputToken, address outputToken, uint256 inputAmount, uint256 outputAmount, uint256 destinationChainId, address exclusiveRelayer, uint32 quoteTimestamp, uint32 fillDeadline, uint32 exclusivityDeadline, bytes calldata message) external'
]);
]) as Abi;
const outputAmount = data.amount - BigInt(fees.totalRelayFee.total);
const fillDeadline = Math.round(Date.now() / 1000) + 300;

Expand All @@ -67,7 +50,6 @@ function encodeAcrossCallData (data: BridgePluginParams, fees: AcrossSuggestedFe
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return encodeFunctionData({
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
abi: abi,
functionName: 'depositV3',
args: [
Expand Down Expand Up @@ -181,6 +163,6 @@ export class KlasterService {

console.log(quote);

return quote;
return quote;
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
// Copyright 2019-2022 @subwallet/extension-base authors & contributors
// SPDX-License-Identifier: Apache-2.0

import { SmartAccount, SmartAccountConfig, Transaction, UserOp, UserOpBundle } from '@particle-network/aa';
import { AccountContract, SmartAccount, SmartAccountConfig, Transaction, UserOp, UserOpBundle } from '@particle-network/aa';
import { SmartAccountData } from '@subwallet/extension-base/background/types';
import { anyNumberToBN } from '@subwallet/extension-base/utils';
import { createMockParticleProvider } from '@subwallet/extension-base/utils/mock/provider/particle';
import { TransactionConfig } from 'web3-core';

export const ParticleContract: AccountContract = {
name: 'BICONOMY',
version: '2.0.0'
};

const config: SmartAccountConfig = {
projectId: '80d48082-7a98-41e0-8eb5-571e2e00cc7f',
clientKey: 'cSuNrTTMf0d2Vp3l9aaAyvGm2UzRjywnNK0duRHN',
Expand Down Expand Up @@ -43,22 +49,22 @@ const config: SmartAccountConfig = {
};

export class ParticleAAHandler {
static getSmartAccount = async (ownerAddress: string): Promise<string> => {
const provider = createMockParticleProvider(1, ownerAddress);
static getSmartAccount = async (account: SmartAccountData): Promise<string> => {
const provider = createMockParticleProvider(1, account.owner);

const smartAccount = new SmartAccount(provider, config);

smartAccount.setSmartAccountContract({ name: 'BICONOMY', version: '2.0.0' });
smartAccount.setSmartAccountContract(account.provider || ParticleContract);

return smartAccount.getAddress();
};

static createUserOperation = async (ownerAddress: string, chainId: number, _tx: TransactionConfig): Promise<UserOpBundle> => {
const provider = createMockParticleProvider(chainId, ownerAddress);
static createUserOperation = async (chainId: number, account: SmartAccountData, _tx: TransactionConfig): Promise<UserOpBundle> => {
const provider = createMockParticleProvider(chainId, account.owner);

const smartAccount = new SmartAccount(provider, config);

smartAccount.setSmartAccountContract({ name: 'BICONOMY', version: '2.0.0' });
smartAccount.setSmartAccountContract(account.provider || ParticleContract);

const tx: Transaction = {
data: _tx.data,
Expand All @@ -67,15 +73,17 @@ export class ParticleAAHandler {
gasLimit: _tx.gas
};

console.debug('quote', await smartAccount.getFeeQuotes(tx));

return await smartAccount.buildUserOperation({ tx });
};

static sendSignedUserOperation = async (ownerAddress: string, chainId: number, userOp: UserOp): Promise<string> => {
const provider = createMockParticleProvider(chainId, ownerAddress);
static sendSignedUserOperation = async (chainId: number, account: SmartAccountData, userOp: UserOp): Promise<string> => {
const provider = createMockParticleProvider(chainId, account.owner);

const smartAccount = new SmartAccount(provider, config);

smartAccount.setSmartAccountContract({ name: 'BICONOMY', version: '2.0.0' });
smartAccount.setSmartAccountContract(account.provider || ParticleContract);

return await smartAccount.sendSignedUserOperation(userOp);
};
Expand Down
14 changes: 5 additions & 9 deletions packages/extension-base/src/services/keyring-service/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@

import { CurrentAccountInfo, KeyringState } from '@subwallet/extension-base/background/KoniTypes';
import { ALL_ACCOUNT_KEY } from '@subwallet/extension-base/constants';
import { KlasterService } from '@subwallet/extension-base/services/chain-abstraction-service/klaster';
import { ParticleAAHandler } from '@subwallet/extension-base/services/chain-abstraction-service/particle';
import { ParticleAAHandler, ParticleContract } from '@subwallet/extension-base/services/chain-abstraction-service/particle';
import { EventService } from '@subwallet/extension-base/services/event-service';
import { CurrentAccountStore } from '@subwallet/extension-base/stores';
import { InjectedAccountWithMeta } from '@subwallet/extension-inject/types';
Expand Down Expand Up @@ -123,8 +122,8 @@ export class KeyringService {
const isEthereum = isEthereumAddress(acc.address);

if (isEthereum) {
// const smartAddress = await ParticleAAHandler.getSmartAccount(acc.address);
const smartAddress = await KlasterService.getSmartAccount(acc.address);
const smartAddress = await ParticleAAHandler.getSmartAccount({ owner: acc.address, provider: ParticleContract });
// const smartAddress = await KlasterService.getSmartAccount(acc.address);

return {
...acc,
Expand All @@ -134,10 +133,7 @@ export class KeyringService {
isSmartAccount: true,
smartAccountOwner: acc.address,
aaSdk: 'particle',
aaProvider: {
name: 'BICONOMY',
version: '2.0.0'
}
aaProvider: ParticleContract
}
};
}
Expand Down Expand Up @@ -189,7 +185,7 @@ export class KeyringService {
const isEthereum = isEthereumAddress(address);

if (isEthereum) {
return await ParticleAAHandler.getSmartAccount(address);
return await ParticleAAHandler.getSmartAccount({ owner: address });
}

return address;
Expand Down
52 changes: 33 additions & 19 deletions packages/extension-base/src/services/transaction-service/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { UserOpBundle } from '@particle-network/aa';
import { EvmProviderError } from '@subwallet/extension-base/background/errors/EvmProviderError';
import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
import { AmountData, BasicTxErrorType, ChainType, EvmProviderErrorType, EvmSendTransactionRequest, EvmSignatureRequest, ExtrinsicStatus, ExtrinsicType, NotificationType, TransactionAdditionalInfo, TransactionDirection, TransactionHistoryItem } from '@subwallet/extension-base/background/KoniTypes';
import { AccountJson } from '@subwallet/extension-base/background/types';
import { AccountJson, SmartAccountData } from '@subwallet/extension-base/background/types';
import { ALL_ACCOUNT_KEY } from '@subwallet/extension-base/constants';
import { checkBalanceWithTransactionFee, checkSigningAccountForTransaction, checkSupportForTransaction, estimateFeeForTransaction } from '@subwallet/extension-base/core/logic-validation/transfer';
import KoniState from '@subwallet/extension-base/koni/background/handlers/State';
Expand All @@ -23,15 +23,17 @@ import { getExplorerLink, parseTransactionData } from '@subwallet/extension-base
import { isWalletConnectRequest } from '@subwallet/extension-base/services/wallet-connect-service/helpers';
import { Web3Transaction } from '@subwallet/extension-base/signers/types';
import { LeavePoolAdditionalData, RequestStakePoolingBonding, RequestYieldStepSubmit, SpecialYieldPoolInfo, YieldPoolType } from '@subwallet/extension-base/types';
import { _isRuntimeUpdated, anyNumberToBN, reformatAddress } from '@subwallet/extension-base/utils';
import { _isRuntimeUpdated, anyNumberToBN, getEthereumSmartAccountOwner, reformatAddress } from '@subwallet/extension-base/utils';
import { mergeTransactionAndSignature } from '@subwallet/extension-base/utils/eth/mergeTransactionAndSignature';
import { isContractAddress, parseContractInput } from '@subwallet/extension-base/utils/eth/parseTransaction';
import { BN_ZERO } from '@subwallet/extension-base/utils/number';
import { isParticleOP } from '@subwallet/extension-base/utils/request';
import keyring from '@subwallet/ui-keyring';
import { addHexPrefix } from 'ethereumjs-util';
import { ethers, TransactionLike } from 'ethers';
import EventEmitter from 'eventemitter3';
import { t } from 'i18next';
import { QuoteResponse } from 'klaster-sdk';
import { BehaviorSubject, interval as rxjsInterval, Subscription } from 'rxjs';
import { TransactionConfig, TransactionReceipt } from 'web3-core';

Expand All @@ -43,8 +45,6 @@ import { isHex } from '@polkadot/util';
import { HexString } from '@polkadot/util/types';

import NotificationService from '../notification-service/NotificationService';
import {QuoteResponse} from "klaster-sdk";
import { log } from 'console';

export default class TransactionService {
private readonly state: KoniState;
Expand Down Expand Up @@ -242,8 +242,8 @@ export default class TransactionService {

public async handleAATransaction (transaction: SWTransactionAAInput): Promise<SWTransactionResponse> {
const validatedTransaction: SWAATransaction = {
transaction: transaction.transaction as UserOpBundle,
provider: transaction?.transaction?.userOpHash ? 'particle': 'klaster',
transaction: transaction.transaction,
provider: isParticleOP(transaction.transaction) ? 'particle' : 'klaster',
chain: transaction.chain,
chainType: transaction.chainType,
address: transaction.address,
Expand All @@ -254,22 +254,24 @@ export default class TransactionService {
createdAt: new Date().getTime(),
updatedAt: new Date().getTime(),
extrinsicType: transaction.extrinsicType,
id: transaction.id || getTransactionId(transaction.chainType, transaction.chain, false, false)
id: transaction.id || getTransactionId(transaction.chainType, transaction.chain, false, false),
errors: transaction.errors || [],
warnings: transaction.warnings || []
};

const emitter = this.sendAATransaction(validatedTransaction);

await new Promise<void>((resolve, reject) => {
// TODO
emitter.on('success', (data: TransactionEventResponse) => {
emitter.on('send', (data: TransactionEventResponse) => {
validatedTransaction.id = data.id;
// validatedTransaction.extrinsicHash = data.extrinsicHash;
resolve();
});

emitter.on('error', (data: TransactionEventResponse) => {
if (data.errors.length > 0) {
// validatedTransaction.errors.push(...data.errors);
validatedTransaction.errors.push(...data.errors);
resolve();
}
});
Expand All @@ -290,7 +292,7 @@ export default class TransactionService {
});

emitter.on('send', (data: TransactionEventResponse) => {
this.onSend(data);
// this.onSend(data);
});

emitter.on('extrinsicHash', (data: TransactionEventResponse) => {
Expand Down Expand Up @@ -1244,19 +1246,19 @@ export default class TransactionService {
private signAndSendEvmAATransaction ({ address,
chain,
id,
transaction, provider }: SWAATransaction): TransactionEmitter {
provider, transaction }: SWAATransaction): TransactionEmitter {
const chainInfo = this.state.chainService.getChainInfoByKey(chain);
const chainId = _getEvmChainId(chainInfo) || 1;
const accountPair = keyring.getPair(address);
const account: AccountJson = { address, ...accountPair.meta };
const ownerAddress = account.smartAccountOwner || account.address;
const owner = getEthereumSmartAccountOwner(address) as SmartAccountData;

const emitter = new EventEmitter<TransactionEventMap>();

let _payload: EvmSignatureRequest;

if (provider === 'particle') {
const { userOp, userOpHash } = transaction as UserOpBundle;
const { userOpHash } = transaction as UserOpBundle;

_payload = {
account,
Expand All @@ -1277,7 +1279,7 @@ export default class TransactionService {
type: 'personal_sign',
canSign: true,
id
}
};
}

const eventData: TransactionEventResponse = {
Expand All @@ -1287,7 +1289,7 @@ export default class TransactionService {
extrinsicHash: id
};

this.state.requestService.addConfirmation(id, 'EXTENSION_REQUEST_URL', 'evmSignatureRequest', _payload, {})
this.state.requestService.addConfirmation(id, EXTENSION_REQUEST_URL, 'evmSignatureRequest', _payload)
.then(async ({ isApproved, payload: signature }) => {
if (isApproved) {
if (!signature) {
Expand All @@ -1302,12 +1304,24 @@ export default class TransactionService {
// Add start info
emitter.emit('send', eventData); // This event is needed after sending transaction with queue

// userOp.signature = signature;
const result = await this.state.klasterService.sdk.execute(transaction as QuoteResponse, signature);
if (provider === 'particle') {
const userOp = (transaction as UserOpBundle).userOp;

userOp.signature = signature;

console.log('submitted', result);
const result = await ParticleAAHandler.sendSignedUserOperation(chainId, owner, userOp);

console.log('submitted', result);

eventData.extrinsicHash = result;
} else {
const result = await this.state.klasterService.sdk.execute(transaction as QuoteResponse, signature);

console.log('submitted', result);

eventData.extrinsicHash = result.itxHash;
}

eventData.extrinsicHash = result.itxHash;
emitter.emit('extrinsicHash', eventData);
} else {
this.removeTransaction(id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
import { UserOpBundle } from '@particle-network/aa';
import { BaseRequestSign, ChainType, ExtrinsicDataTypeMap, ExtrinsicStatus, ExtrinsicType, FeeData, ValidateTransactionResponse } from '@subwallet/extension-base/background/KoniTypes';
import EventEmitter from 'eventemitter3';
import { QuoteResponse } from 'klaster-sdk';
import { TransactionConfig } from 'web3-core';

import { SubmittableExtrinsic } from '@polkadot/api/promise/types';
import { EventRecord } from '@polkadot/types/interfaces';
import {QuoteResponse} from "klaster-sdk";

export interface SWTransaction extends ValidateTransactionResponse, Partial<Pick<BaseRequestSign, 'ignoreWarnings'>> {
id: string;
Expand All @@ -29,7 +29,7 @@ export interface SWTransaction extends ValidateTransactionResponse, Partial<Pick
eventsHandler?: (eventEmitter: TransactionEmitter) => void;
}

export interface SWAATransaction extends Pick<SWTransaction, 'chain' | 'chainType' | 'address' | 'data' | 'status' | 'extrinsicHash' | 'extrinsicType' | 'createdAt' | 'updatedAt' | 'estimateFee' | 'id'> {
export interface SWAATransaction extends Pick<SWTransaction, 'chain' | 'chainType' | 'address' | 'data' | 'status' | 'extrinsicHash' | 'extrinsicType' | 'createdAt' | 'updatedAt' | 'estimateFee' | 'id' | 'errors' | 'warnings'> {
transaction: UserOpBundle | QuoteResponse;
provider: 'klaster' | 'particle';
}
Expand All @@ -51,7 +51,7 @@ export interface SWTransactionInput extends SwInputBase, Partial<Pick<SWTransact
}

export interface SWTransactionAAInput extends Omit<SWTransactionInput, 'estimateFee' | 'transaction'> {
transaction?: SWAATransaction['transaction'] | null;
transaction: SWAATransaction['transaction'];
}

export type SWTransactionResponse = SwInputBase & Pick<SWTransaction, 'warnings' | 'errors'> & Partial<Pick<SWTransaction, 'id' | 'extrinsicHash' | 'status' | 'estimateFee'>>;
Expand Down
Loading

0 comments on commit 084a061

Please sign in to comment.