Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Evm transaction operation refactoring #118

Merged
merged 5 commits into from
Jun 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions src/chain/solidity/abi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,3 @@ export const WrappedABI: string[] = ERC20ABI.concat([
'event Deposit(address indexed dst, uint wad)',
'event Withdrawal(address indexed src, uint wad)'
])

export const AuctionABI: string[] = ['function redeemAuction(uint256 auctionId)']

export const StreamABI: string[] = [
'function withdrawFromStream(uint256 streamId, uint256 amount) returns (bool)',
'function cancelStream(uint256 streamId) returns (bool)'
]
28 changes: 2 additions & 26 deletions src/chain/solidity/contract.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ethers } from 'ethers'
import * as abi from './abi'
import { AssetId } from '../../transaction'
import { ERC20Asset, type TokenAsset } from '../../asset'
import { AssetId } from '../../transaction'
import * as abi from './abi'

export class ContractManager {
private readonly handlers: SolidityTokenHandler[] = []
Expand Down Expand Up @@ -120,27 +120,3 @@ export class WrappedContractAdapter extends EVMCallAdapter {
return this.getFunctionData('deposit')
}
}

export class AuctionContractAdapter extends EVMCallAdapter {
constructor (contractAddress: string) {
super(contractAddress, abi.AuctionABI)
}

getRedeemAuctionData (auctionId: bigint): string {
return this.getFunctionData('redeemAuction', [auctionId])
}
}

export class StreamContractAdapter extends EVMCallAdapter {
constructor (contractAddress: string) {
super(contractAddress, abi.StreamABI)
}

getWithdrawFromStreamData (streamId: bigint, amount: bigint): string {
return this.getFunctionData('withdrawFromStream', [streamId, amount])
}

getCancelStreamData (streamId: bigint): string {
return this.getFunctionData('cancelStream', [streamId])
}
}
100 changes: 59 additions & 41 deletions src/wallet/account/evm.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,23 @@
import { ethers } from 'ethers'
import { type JEVMBlockchain } from '../../chain'
import { type MCNProvider } from '../../juneo'
import { AccountError } from '../../utils'
import { AccountError, isContractAddress } from '../../utils'
import {
type CancelStreamOperation,
type ChainNetworkOperation,
ChainOperationSummary,
type ChainOperationSummary,
type EthCallOperation,
type ExecutableOperation,
NetworkOperationType,
type RedeemAuctionOperation,
type SendOperation,
type UnwrapOperation,
type WithdrawStreamOperation,
type WrapOperation
} from '../operation'
import {
BaseSpending,
type EVMFeeData,
FeeType,
TransactionType,
estimateEVMCancelStreamOperation,
estimateEVMRedeemAuctionOperation,
estimateEVMTransfer,
estimateEVMUnwrapOperation,
estimateEVMWithdrawStreamOperation,
estimateEVMWrapOperation,
estimateEthCallOperation,
estimateEVMOperation,
executeEVMTransaction
} from '../transaction'
import { type JEVMWallet, type MCNWallet } from '../wallet'
Expand All @@ -47,41 +40,72 @@ export class EVMAccount extends AbstractChainAccount {
const provider: MCNProvider = await this.provider.getStaticProvider()
if (operation.type === NetworkOperationType.Send) {
const send: SendOperation = operation as SendOperation
const fee: EVMFeeData = await estimateEVMTransfer(
const isContract: boolean = isContractAddress(send.assetId)
const address: string = isContract ? send.assetId : send.address
const amount: bigint = isContract ? BigInt(0) : send.amount
const data: string = isContract
? await this.chain.getContractTransactionData(provider, send.assetId, address, amount)
: '0x'
return await estimateEVMOperation(
provider,
this.chainWallet,
this.chain.id,
send.assetId,
send.amount,
send.address
this.chain,
this.chainWallet.getAddress(),
send,
[new BaseSpending(this.chain, send.amount, send.assetId)],
new Map<string, bigint>([[send.assetId, send.amount]]),
address,
amount,
data,
FeeType.BaseFee
)
const spending: BaseSpending = new BaseSpending(this.chain, send.amount, send.assetId)
const values = new Map<string, bigint>([[send.assetId, send.amount]])
return new ChainOperationSummary(provider, operation, this.chain, fee, [spending, fee.spending], values)
} else if (operation.type === NetworkOperationType.Wrap) {
return await estimateEVMWrapOperation(provider, this.chainWallet.getAddress(), operation as WrapOperation)
} else if (operation.type === NetworkOperationType.Unwrap) {
return await estimateEVMUnwrapOperation(provider, this.chainWallet.getAddress(), operation as UnwrapOperation)
} else if (operation.type === NetworkOperationType.RedeemAuction) {
return await estimateEVMRedeemAuctionOperation(
const wrap = operation as WrapOperation
return await estimateEVMOperation(
provider,
this.chain,
this.chainWallet.getAddress(),
operation as RedeemAuctionOperation
wrap,
[new BaseSpending(this.chain, wrap.amount, this.chain.assetId)],
new Map<string, bigint>([[this.chain.assetId, wrap.amount]]),
wrap.asset.address,
wrap.amount,
wrap.asset.adapter.getDepositData(),
FeeType.Wrap
)
} else if (operation.type === NetworkOperationType.WithdrawStream) {
return await estimateEVMWithdrawStreamOperation(
} else if (operation.type === NetworkOperationType.Unwrap) {
const unwrap = operation as UnwrapOperation
return await estimateEVMOperation(
provider,
this.chain,
this.chainWallet.getAddress(),
operation as WithdrawStreamOperation
unwrap,
[new BaseSpending(this.chain, unwrap.amount, unwrap.asset.assetId)],
new Map<string, bigint>([[unwrap.asset.assetId, unwrap.amount]]),
unwrap.asset.address,
BigInt(0),
unwrap.asset.adapter.getWithdrawData(unwrap.amount),
FeeType.Unwrap
)
} else if (operation.type === NetworkOperationType.CancelStream) {
return await estimateEVMCancelStreamOperation(
} else if (operation.type === NetworkOperationType.EthCall) {
const ethCall = operation as EthCallOperation
const contract = new ethers.Contract(ethCall.contract, ethCall.abi, this.chain.ethProvider)
const data = contract.interface.encodeFunctionData(ethCall.functionName, ethCall.values)
const values = new Map<string, bigint>()
if (ethCall.amount > 0) {
values.set(this.chain.assetId, ethCall.amount)
}
return await estimateEVMOperation(
provider,
this.chain,
this.chainWallet.getAddress(),
operation as CancelStreamOperation
ethCall,
[],
values,
ethCall.contract,
ethCall.amount,
data,
FeeType.EthCall
)
} else if (operation.type === NetworkOperationType.EthCall) {
return await estimateEthCallOperation(provider, this.chainWallet.getAddress(), operation as EthCallOperation)
}
throw new AccountError(`unsupported operation: ${operation.type} for the chain with id: ${this.chain.id}`)
}
Expand All @@ -95,12 +119,6 @@ export class EVMAccount extends AbstractChainAccount {
await this.executeAndTrackTransaction(summary, TransactionType.Wrap)
} else if (operation === NetworkOperationType.Unwrap) {
await this.executeAndTrackTransaction(summary, TransactionType.Unwrap)
} else if (operation === NetworkOperationType.RedeemAuction) {
await this.executeAndTrackTransaction(summary, TransactionType.RedeemAuction)
} else if (operation === NetworkOperationType.WithdrawStream) {
await this.executeAndTrackTransaction(summary, TransactionType.WithdrawStream)
} else if (operation === NetworkOperationType.CancelStream) {
await this.executeAndTrackTransaction(summary, TransactionType.CancelStream)
} else if (operation === NetworkOperationType.EthCall) {
await this.executeAndTrackTransaction(summary, TransactionType.EthCall)
}
Expand Down
40 changes: 0 additions & 40 deletions src/wallet/operation/operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ export enum NetworkOperationType {
DelegatePrimary = 'Delegate primary',
Wrap = 'Wrap',
Unwrap = 'Unwrap',
RedeemAuction = 'Redeem auction',
WithdrawStream = 'Withdraw stream',
CancelStream = 'Cancel stream',
CreateSupernet = 'Create supernet',
ValidateSupernet = 'Validate supernet',
RemoveSupernetValidator = 'Remove supernet validator',
Expand Down Expand Up @@ -122,43 +119,6 @@ export class UnwrapOperation extends Wrapping {
}
}

export class RedeemAuctionOperation extends JEVMChainOperation {
auctionAddress: string
auctionId: bigint

constructor (chain: JEVMBlockchain, auctionAddress: string, auctionId: bigint) {
super(NetworkOperationType.RedeemAuction, chain)
this.auctionAddress = auctionAddress
this.auctionId = auctionId
}
}

abstract class StreamOperation extends JEVMChainOperation {
streamAddress: string
streamId: bigint

constructor (type: NetworkOperationType, chain: JEVMBlockchain, streamAddress: string, streamId: bigint) {
super(type, chain)
this.streamAddress = streamAddress
this.streamId = streamId
}
}

export class WithdrawStreamOperation extends StreamOperation {
amount: bigint

constructor (chain: JEVMBlockchain, streamAddress: string, streamId: bigint, amount: bigint) {
super(NetworkOperationType.WithdrawStream, chain, streamAddress, streamId)
this.amount = amount
}
}

export class CancelStreamOperation extends StreamOperation {
constructor (chain: JEVMBlockchain, streamAddress: string, streamId: bigint) {
super(NetworkOperationType.CancelStream, chain, streamAddress, streamId)
}
}

export class EthCallOperation extends JEVMChainOperation {
contract: string
abi: string
Expand Down
48 changes: 31 additions & 17 deletions src/wallet/operation/summary.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { type PlatformBlockchain, type Blockchain } from '../../chain'
import { type Blockchain, type PlatformBlockchain } from '../../chain'
import { type MCNProvider } from '../../juneo'
import { type Utxo } from '../../transaction'
import { type UtxoFeeData, type FeeData, type Spending, type EVMFeeData } from '../transaction'
import { type EVMFeeData, type FeeData, type Spending, type UtxoFeeData } from '../transaction'
import { ExecutableOperation } from './executable'
import {
type Staking,
type NetworkOperation,
type CrossResumeOperation,
type ChainNetworkOperation,
type CrossOperation,
type DepositResumeOperation
type CrossResumeOperation,
type DepositResumeOperation,
type NetworkOperation,
type Staking
} from './operation'

export interface OperationSummary {
Expand All @@ -23,27 +23,32 @@ export interface OperationSummary {
getAssets: () => Set<string>

getChains: () => Blockchain[]

getErrors: () => Error[]
}

abstract class AbstractOperationSummary implements OperationSummary {
operation: NetworkOperation
fees: FeeData[]
spendings: Spending[]
values: Map<string, bigint>
errors: Error[]
private readonly executable: ExecutableOperation

constructor (
provider: MCNProvider,
operation: NetworkOperation,
fees: FeeData[],
spendings: Spending[],
values: Map<string, bigint>
values: Map<string, bigint>,
errors: Error[]
) {
this.operation = operation
this.fees = fees
this.spendings = spendings
this.values = values
this.executable = new ExecutableOperation(provider)
this.errors = errors
}

getExecutable (): ExecutableOperation {
Expand All @@ -69,6 +74,10 @@ abstract class AbstractOperationSummary implements OperationSummary {
}

abstract getChains (): Blockchain[]

getErrors (): Error[] {
return this.errors
}
}

export class ChainOperationSummary extends AbstractOperationSummary {
Expand All @@ -82,9 +91,10 @@ export class ChainOperationSummary extends AbstractOperationSummary {
chain: Blockchain,
fee: FeeData,
spendings: Spending[],
values: Map<string, bigint>
values: Map<string, bigint>,
errors: Error[] = []
) {
super(provider, operation, [fee], spendings, values)
super(provider, operation, [fee], spendings, values, errors)
this.operation = operation
this.chain = chain
this.fee = fee
Expand All @@ -105,9 +115,10 @@ export class CrossOperationSummary extends AbstractOperationSummary {
chains: Blockchain[],
fees: FeeData[],
spendings: Spending[],
values: Map<string, bigint>
values: Map<string, bigint>,
errors: Error[] = []
) {
super(provider, operation, fees, spendings, values)
super(provider, operation, fees, spendings, values, errors)
this.operation = operation
this.chains = chains
}
Expand All @@ -127,9 +138,10 @@ export class StakingOperationSummary extends ChainOperationSummary {
fee: UtxoFeeData,
spendings: Spending[],
values: Map<string, bigint>,
potentialReward: bigint
potentialReward: bigint,
errors: Error[] = []
) {
super(provider, operation, chain, fee, spendings, values)
super(provider, operation, chain, fee, spendings, values, errors)
this.potentialReward = potentialReward
}
}
Expand All @@ -147,9 +159,10 @@ export class CrossResumeOperationSummary extends ChainOperationSummary {
spendings: Spending[],
values: Map<string, bigint>,
payImportFee: boolean,
utxoSet: Utxo[]
utxoSet: Utxo[],
errors: Error[] = []
) {
super(provider, operation, operation.destination, importFee, spendings, values)
super(provider, operation, operation.destination, importFee, spendings, values, errors)
this.operation = operation
this.importFee = importFee
this.payImportFee = payImportFee
Expand All @@ -166,9 +179,10 @@ export class DepositResumeOperationSummary extends ChainOperationSummary {
operation: DepositResumeOperation,
fee: EVMFeeData,
spendings: Spending[],
values: Map<string, bigint>
values: Map<string, bigint>,
errors: Error[] = []
) {
super(provider, operation, operation.chain, fee, spendings, values)
super(provider, operation, operation.chain, fee, spendings, values, errors)
this.operation = operation
this.fee = fee
}
Expand Down
7 changes: 0 additions & 7 deletions src/wallet/transaction/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,5 @@ export const WalletStatusFetcherDelay: number = 100
export const MaxInvalidNonceAttempts: number = 5
export const InvalidNonceRetryDelay: number = 1000

export const DefaultWrapEstimate: bigint = BigInt(55_000)
export const DefaultUnwrapEstimate: bigint = BigInt(45_000)
export const DefaultTransferEstimate: bigint = BigInt(200_000)
export const DefaultWithdrawEstimate: bigint = BigInt(100_000)
export const DefaultDepositEstimate: bigint = BigInt(100_000)
export const DefaultRedeemAuctionEstimate: bigint = BigInt(100_000)
export const DefaultWithdrawStreamEstimate: bigint = BigInt(100_000)
export const DefaultCancelStreamEstimate: bigint = BigInt(125_000)
export const DefaultEthCallEstimate: bigint = BigInt(1_000_000)
Loading
Loading