From 261407028ad4c8ccbf21f838624c744688abcf2a Mon Sep 17 00:00:00 2001 From: alekswaslet <1346150+alekswaslet@users.noreply.github.com> Date: Tue, 30 Apr 2024 11:12:17 +0200 Subject: [PATCH 1/8] Fix wrong fee type --- src/wallet/transaction/evm.ts | 50 +++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/src/wallet/transaction/evm.ts b/src/wallet/transaction/evm.ts index 04f14b1c..36e914b1 100644 --- a/src/wallet/transaction/evm.ts +++ b/src/wallet/transaction/evm.ts @@ -194,7 +194,15 @@ export async function estimateEVMWrapOperation ( }, async () => { const gasPrice: bigint = await estimateEVMGasPrice(api) - const fee: BaseFeeData = new BaseFeeData(chain, DefaultWrapEstimate * gasPrice, type) + const transactionData: EVMTransactionData = new EVMTransactionData(from, wrap.asset.address, BigInt(0), data) + const fee: EVMFeeData = new EVMFeeData( + chain, + gasPrice * DefaultWrapEstimate, + type, + gasPrice, + DefaultWrapEstimate, + transactionData + ) const spending: BaseSpending = new BaseSpending(chain, wrap.amount, chain.assetId) return new ChainOperationSummary(provider, wrap, chain, fee, [spending, fee.spending], values) } @@ -218,7 +226,15 @@ export async function estimateEVMUnwrapOperation ( }, async () => { const gasPrice: bigint = await estimateEVMGasPrice(api) - const fee: BaseFeeData = new BaseFeeData(chain, DefaultUnwrapEstimate * gasPrice, type) + const transactionData: EVMTransactionData = new EVMTransactionData(from, unwrap.asset.address, BigInt(0), data) + const fee: EVMFeeData = new EVMFeeData( + chain, + gasPrice * DefaultUnwrapEstimate, + type, + gasPrice, + DefaultUnwrapEstimate, + transactionData + ) const spending: BaseSpending = new BaseSpending(chain, unwrap.amount, unwrap.asset.assetId) return new ChainOperationSummary(provider, unwrap, chain, fee, [spending, fee.spending], values) } @@ -241,7 +257,15 @@ export async function estimateEVMRedeemAuctionOperation ( }, async () => { const gasPrice: bigint = await estimateEVMGasPrice(api) - const fee: BaseFeeData = new BaseFeeData(chain, DefaultRedeemAuctionEstimate * gasPrice, type) + const transactionData: EVMTransactionData = new EVMTransactionData(from, redeem.auctionAddress, BigInt(0), data) + const fee: EVMFeeData = new EVMFeeData( + chain, + gasPrice * DefaultRedeemAuctionEstimate, + type, + gasPrice, + DefaultRedeemAuctionEstimate, + transactionData + ) return new ChainOperationSummary(provider, redeem, chain, fee, [fee.spending], new Map()) } ) @@ -263,7 +287,15 @@ export async function estimateEVMWithdrawStreamOperation ( }, async () => { const gasPrice: bigint = await estimateEVMGasPrice(api) - const fee: BaseFeeData = new BaseFeeData(chain, DefaultWithdrawStreamEstimate * gasPrice, type) + const transactionData: EVMTransactionData = new EVMTransactionData(from, withdraw.streamAddress, BigInt(0), data) + const fee: EVMFeeData = new EVMFeeData( + chain, + gasPrice * DefaultWithdrawStreamEstimate, + type, + gasPrice, + DefaultWithdrawStreamEstimate, + transactionData + ) return new ChainOperationSummary(provider, withdraw, chain, fee, [fee.spending], new Map()) } ) @@ -285,7 +317,15 @@ export async function estimateEVMCancelStreamOperation ( }, async () => { const gasPrice: bigint = await estimateEVMGasPrice(api) - const fee: BaseFeeData = new BaseFeeData(chain, DefaultCancelStreamEstimate * gasPrice, type) + const transactionData: EVMTransactionData = new EVMTransactionData(from, cancel.streamAddress, BigInt(0), data) + const fee: EVMFeeData = new EVMFeeData( + chain, + gasPrice * DefaultCancelStreamEstimate, + type, + gasPrice, + DefaultCancelStreamEstimate, + transactionData + ) return new ChainOperationSummary(provider, cancel, chain, fee, [fee.spending], new Map()) } ) From 1079098a38df5e0db41d62b76266dedfaeffd331 Mon Sep 17 00:00:00 2001 From: alekswaslet <1346150+alekswaslet@users.noreply.github.com> Date: Tue, 30 Apr 2024 11:23:00 +0200 Subject: [PATCH 2/8] Rename query and remove magic value --- src/chain/jevm.ts | 6 +++--- src/wallet/account/evm.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/chain/jevm.ts b/src/chain/jevm.ts index d472586b..09770727 100644 --- a/src/chain/jevm.ts +++ b/src/chain/jevm.ts @@ -14,6 +14,7 @@ export const NativeAssetBalanceContract: string = '0x010000000000000000000000000 export const NativeAssetCallContract: string = '0x0100000000000000000000000000000000000002' export const SendEtherGasLimit: bigint = BigInt(21_000) +const Transferables: string[] = [TokenType.ERC20, TokenType.JRC20, TokenType.Wrapped] export class JEVMBlockchain extends AbstractBlockchain { override asset: JEVMGasToken @@ -60,8 +61,7 @@ export class JEVMBlockchain extends AbstractBlockchain { // could rather use contract manager but it would require one extra network call // we avoid it if the asset is already registered const asset: TokenAsset = await this.getAsset(provider, assetId) - const erc20Types: string[] = [TokenType.ERC20, TokenType.JRC20, TokenType.Wrapped] - if (erc20Types.includes(asset.type)) { + if (Transferables.includes(asset.type)) { return this.erc20Handler.getTransferData(assetId, to, amount) } return '0x' @@ -82,7 +82,7 @@ export class JEVMBlockchain extends AbstractBlockchain { return ethers.isAddress(address) } - async queryEVMBalance (api: JEVMAPI, address: string, assetId: string): Promise { + async queryBalance (api: JEVMAPI, address: string, assetId: string): Promise { // native asset if (assetId === this.assetId) { return await api.eth_getBalance(address, 'pending') diff --git a/src/wallet/account/evm.ts b/src/wallet/account/evm.ts index 5807287f..ba567a67 100644 --- a/src/wallet/account/evm.ts +++ b/src/wallet/account/evm.ts @@ -119,6 +119,6 @@ export class EVMAccount extends AbstractChainAccount { } const balance: Balance = this.balances.get(assetId)! const address: string = this.chainWallet.getAddress() - await balance.updateAsync(this.chain.queryEVMBalance(this.provider.jevmApi[this.chain.id], address, assetId)) + await balance.updateAsync(this.chain.queryBalance(this.provider.jevmApi[this.chain.id], address, assetId)) } } From 0caede44813920db63ea2898f616d80a2f554a03 Mon Sep 17 00:00:00 2001 From: alekswaslet <1346150+alekswaslet@users.noreply.github.com> Date: Tue, 30 Apr 2024 12:24:56 +0200 Subject: [PATCH 3/8] Use ContractManager instead of ERC20Handler --- src/chain/jevm.ts | 12 +++--------- src/chain/solidity/abi.ts | 4 ++++ src/chain/solidity/contract.ts | 24 ++++++++++-------------- 3 files changed, 17 insertions(+), 23 deletions(-) diff --git a/src/chain/jevm.ts b/src/chain/jevm.ts index 09770727..6cb45d5d 100644 --- a/src/chain/jevm.ts +++ b/src/chain/jevm.ts @@ -23,7 +23,6 @@ export class JEVMBlockchain extends AbstractBlockchain { ethProvider: ethers.JsonRpcProvider jrc20Assets: JRC20Asset[] wrappedAsset: WrappedAsset | undefined - private readonly erc20Handler: ERC20TokenHandler private readonly contractManager: ContractManager = new ContractManager() constructor ( @@ -48,8 +47,7 @@ export class JEVMBlockchain extends AbstractBlockchain { if (typeof wrappedAsset !== 'undefined') { this.addRegisteredAsset(wrappedAsset) } - this.erc20Handler = new ERC20TokenHandler(this.ethProvider) - this.contractManager.registerHandler(this.erc20Handler) + this.contractManager.registerHandler(new ERC20TokenHandler(this.ethProvider)) } async getContractTransactionData ( @@ -62,7 +60,7 @@ export class JEVMBlockchain extends AbstractBlockchain { // we avoid it if the asset is already registered const asset: TokenAsset = await this.getAsset(provider, assetId) if (Transferables.includes(asset.type)) { - return this.erc20Handler.getTransferData(assetId, to, amount) + return this.contractManager.getTransferData(assetId, to, amount) } return '0x' } @@ -95,10 +93,6 @@ export class JEVMBlockchain extends AbstractBlockchain { if (!isContractAddress(assetId)) { throw new ChainError(`cannot query balance of invalid asset id ${assetId}`) } - const handler: SolidityTokenHandler | null = await this.contractManager.getHandler(assetId) - if (handler !== null) { - return await handler.queryBalance(assetId, address) - } - return BigInt(0) + return await this.contractManager.balanceOf(assetId, address) } } diff --git a/src/chain/solidity/abi.ts b/src/chain/solidity/abi.ts index ea6d2d9b..7353407a 100644 --- a/src/chain/solidity/abi.ts +++ b/src/chain/solidity/abi.ts @@ -1,3 +1,7 @@ +export const TransferABI: string[] = ['function transfer(address to, uint amount) returns (bool)'] + +export const BalanceOfABI: string[] = ['function balanceOf(address owner) view returns (uint256)'] + export const ERC20ABI: string[] = [ 'function name() view returns (string)', 'function decimals() view returns (uint8)', diff --git a/src/chain/solidity/contract.ts b/src/chain/solidity/contract.ts index d1059410..624dcf34 100644 --- a/src/chain/solidity/contract.ts +++ b/src/chain/solidity/contract.ts @@ -22,16 +22,22 @@ export class ContractManager { // Should do a better getHandler function in the future this.handlers.unshift(handler) } + + async balanceOf (contractAddress: string, address: string): Promise { + const contract: ethers.Contract = new ethers.Contract(contractAddress, abi.BalanceOfABI) + return BigInt.asUintN(256, BigInt(await contract.balanceOf(address))) + } + + getTransferData (contractAddress: string, to: string, amount: bigint): string { + const contract: ethers.Contract = new ethers.Contract(contractAddress, abi.TransferABI) + return contract.interface.encodeFunctionData('transfer', [to, amount]) + } } export interface SolidityTokenHandler { instanceOf: (contractAddress: string) => Promise - queryBalance: (contractAddress: string, address: string) => Promise - queryTokenData: (contractAddress: string) => Promise - - getTransferData: (contractAddress: string, to: string, amount: bigint) => string } export class ERC20TokenHandler implements SolidityTokenHandler { @@ -52,11 +58,6 @@ export class ERC20TokenHandler implements SolidityTokenHandler { return true } - async queryBalance (contractAddress: string, address: string): Promise { - const contract: ethers.Contract = this.getContract(contractAddress) - return BigInt.asUintN(256, BigInt(await contract.balanceOf(address))) - } - async queryTokenData (contractAddress: string): Promise { const contract: ethers.Contract = this.getContract(contractAddress) const name: string = await contract.name() @@ -65,11 +66,6 @@ export class ERC20TokenHandler implements SolidityTokenHandler { return new ERC20Asset(contractAddress, name, symbol, decimals) } - getTransferData (contractAddress: string, to: string, amount: bigint): string { - const contract: ethers.Contract = new ethers.Contract(contractAddress, abi.ERC20ABI) - return contract.interface.encodeFunctionData('transfer', [to, amount]) - } - protected getContract (contractAddress: string): ethers.Contract { return new ethers.Contract(contractAddress, abi.ERC20ABI, this.provider) } From cd8317330e615663606e9afaac1139408be29d71 Mon Sep 17 00:00:00 2001 From: alekswaslet <1346150+alekswaslet@users.noreply.github.com> Date: Tue, 30 Apr 2024 13:56:20 +0200 Subject: [PATCH 4/8] Added CreateSupernetOperation --- src/wallet/account/platform.ts | 10 +++- src/wallet/operation/operation.ts | 14 +++++- src/wallet/transaction/base.ts | 10 ++-- src/wallet/transaction/fee.ts | 1 + src/wallet/transaction/platform.ts | 69 ++++++++++++++++++++++----- src/wallet/transaction/transaction.ts | 1 + 6 files changed, 83 insertions(+), 22 deletions(-) diff --git a/src/wallet/account/platform.ts b/src/wallet/account/platform.ts index 894b6d54..0d4e93ff 100644 --- a/src/wallet/account/platform.ts +++ b/src/wallet/account/platform.ts @@ -6,7 +6,8 @@ import { estimatePlatformValidatePrimaryOperation, estimatePlatformDelegatePrimaryOperation, estimateSendOperation, - estimateSendUtxoOperation + estimateSendUtxoOperation, + estimatePlatformCreateSupernetOperation } from '../transaction' import { AccountError } from '../../utils' import { @@ -17,7 +18,8 @@ import { type ValidatePrimaryOperation, type ChainNetworkOperation, type SendOperation, - type SendUtxoOperation + type SendUtxoOperation, + type CreateSupernetOperation } from '../operation' import { type MCNWallet } from '../wallet' import { UtxoAccount } from './account' @@ -41,6 +43,8 @@ export class PlatformAccount extends UtxoAccount { return await estimateSendOperation(provider, this.chain, this, operation as SendOperation) } else if (operation.type === NetworkOperationType.SendUtxo) { return await estimateSendUtxoOperation(provider, this.chain, this, operation as SendUtxoOperation) + } else if (operation.type === NetworkOperationType.CreateSupernet) { + return await estimatePlatformCreateSupernetOperation(provider, operation as CreateSupernetOperation, this) } throw new AccountError(`unsupported operation: ${operation.type} for the chain with id: ${this.chain.id}`) } @@ -56,6 +60,8 @@ export class PlatformAccount extends UtxoAccount { await this.executeAndTrackTransaction(summary, TransactionType.Send) } else if (operation === NetworkOperationType.SendUtxo) { await this.executeAndTrackTransaction(summary, TransactionType.Send) + } else if (operation === NetworkOperationType.CreateSupernet) { + await this.executeAndTrackTransaction(summary, TransactionType.CreateSupernet) } // balances fetching is needed to get new utxos creating from this operation await super.refreshBalances() diff --git a/src/wallet/operation/operation.ts b/src/wallet/operation/operation.ts index ece74c59..1cda6272 100644 --- a/src/wallet/operation/operation.ts +++ b/src/wallet/operation/operation.ts @@ -1,5 +1,5 @@ import { type JRC20Asset, type WrappedAsset } from '../../asset' -import { type JEVMBlockchain, type Blockchain } from '../../chain' +import { type JEVMBlockchain, type Blockchain, type PlatformBlockchain } from '../../chain' import { type MCN } from '../../network' import { BLSPublicKey, BLSSignature, type Utxo } from '../../transaction' @@ -17,6 +17,7 @@ export enum NetworkOperationType { RedeemAuction = 'Redeem auction', WithdrawStream = 'Withdraw stream', CancelStream = 'Cancel stream', + CreateSupernet = 'Create supernet', } export enum NetworkOperationRange { @@ -247,6 +248,17 @@ export class DelegatePrimaryOperation extends Staking { } } +export class CreateSupernetOperation extends ChainNetworkOperation { + supernetAuthAddresses: string[] + supernetAuthThreshold: number + + constructor (chain: PlatformBlockchain, supernetAuthAddresses: string[], supernetAuthThreshold: number) { + super(NetworkOperationType.CreateSupernet, chain) + this.supernetAuthAddresses = supernetAuthAddresses + this.supernetAuthThreshold = supernetAuthThreshold + } +} + export class CrossOperation implements NetworkOperation { type: NetworkOperationType = NetworkOperationType.Cross range: NetworkOperationRange = NetworkOperationRange.Supernet diff --git a/src/wallet/transaction/base.ts b/src/wallet/transaction/base.ts index f9dd9816..d4c34dab 100644 --- a/src/wallet/transaction/base.ts +++ b/src/wallet/transaction/base.ts @@ -4,8 +4,7 @@ import { buildJVMBaseTransaction, buildPlatformBaseTransaction, type UnsignedTransaction, - UserInput, - type Utxo + UserInput } from '../../transaction' import { type UtxoAccount } from '../account' import { ChainOperationSummary, type SendOperation, type SendUtxoOperation } from '../operation' @@ -24,7 +23,6 @@ export async function estimateBaseTransaction ( amount: bigint, addresses: string[], threshold: number, - utxoSet: Utxo[], locktime: bigint = BigInt(0) ): Promise { const fee: BaseFeeData = await getBaseTxFee(provider, FeeType.BaseFee, chain) @@ -32,7 +30,7 @@ export async function estimateBaseTransaction ( chain.id === provider.platformChain.id ? buildPlatformBaseTransaction( [new UserInput(assetId, chain, amount, addresses, threshold, chain, locktime)], - utxoSet, + account.utxoSet, account.getSignersAddresses(), fee.amount, account.address, @@ -40,7 +38,7 @@ export async function estimateBaseTransaction ( ) : buildJVMBaseTransaction( [new UserInput(assetId, chain, amount, addresses, threshold, chain, locktime)], - utxoSet, + account.utxoSet, account.getSignersAddresses(), fee.amount, account.address, @@ -64,7 +62,6 @@ export async function estimateSendOperation ( send.amount, [send.address], 1, - account.utxoSet, BigInt(0) ).then( (fee) => { @@ -100,7 +97,6 @@ export async function estimateSendUtxoOperation ( send.amount, send.addresses, send.threshold, - account.utxoSet, send.locktime ).then( (fee) => { diff --git a/src/wallet/transaction/fee.ts b/src/wallet/transaction/fee.ts index fca47549..fef39145 100644 --- a/src/wallet/transaction/fee.ts +++ b/src/wallet/transaction/fee.ts @@ -18,6 +18,7 @@ export enum FeeType { RedeemAuction = 'Redeem fee', WithdrawStream = 'Withdraw stream fee', CancelStream = 'Cancel stream fee', + CreateSupernet = 'Create supernet fee', } export interface FeeData { diff --git a/src/wallet/transaction/platform.ts b/src/wallet/transaction/platform.ts index f1362a2e..db8ab8f9 100644 --- a/src/wallet/transaction/platform.ts +++ b/src/wallet/transaction/platform.ts @@ -2,17 +2,18 @@ import { type PlatformBlockchain } from '../../chain' import { type MCNProvider } from '../../juneo' import { Validator, - type Utxo, type UnsignedTransaction, NodeId, buildAddPermissionlessValidatorTransaction, ProofOfPossession, PrimarySigner, - buildAddPermissionlessDelegatorTransaction + buildAddPermissionlessDelegatorTransaction, + buildCreateSupernetTransaction } from '../../transaction' import { type PlatformAccount } from '../account' import { ChainOperationSummary, + type CreateSupernetOperation, type DelegatePrimaryOperation, StakingOperationSummary, type ValidatePrimaryOperation @@ -30,6 +31,11 @@ async function getPlatformAddPrimaryDelegatorFee (provider: MCNProvider): Promis return new BaseFeeData(provider.platformChain, fee, FeeType.DelegateFee) } +async function getPlatformCreateSupernetFee (provider: MCNProvider): Promise { + const fee: bigint = BigInt((await provider.info.getTxFee()).createSupernetTxFee) + return new BaseFeeData(provider.platformChain, fee, FeeType.CreateSupernet) +} + export async function estimatePlatformAddPrimaryValidatorTransaction ( provider: MCNProvider, account: PlatformAccount, @@ -39,12 +45,11 @@ export async function estimatePlatformAddPrimaryValidatorTransaction ( stakeAddresses: string[], stakeThreshold: number, rewardAddresses: string[], - rewardThreshold: number, - utxoSet: Utxo[] + rewardThreshold: number ): Promise { const fee: BaseFeeData = await getPlatformAddPrimaryValidatorFee(provider) const transaction: UnsignedTransaction = buildAddPermissionlessValidatorTransaction( - utxoSet, + account.utxoSet, account.getSignersAddresses(), fee.amount, provider.platformChain, @@ -94,8 +99,7 @@ export async function estimatePlatformValidatePrimaryOperation ( validate.stakeAddresses, validate.stakeThreshold, validate.rewardAddresses, - validate.rewardThreshold, - account.utxoSet + validate.rewardThreshold ).then( (fee) => { const spending: UtxoSpending = new UtxoSpending(chain, validate.amount, chain.assetId, fee.transaction.getUtxos()) @@ -130,12 +134,11 @@ export async function estimatePlatformAddPrimaryDelegatorTransaction ( stakeAddresses: string[], stakeThreshold: number, rewardAddresses: string[], - rewardThreshold: number, - utxoSet: Utxo[] + rewardThreshold: number ): Promise { const fee: BaseFeeData = await getPlatformAddPrimaryDelegatorFee(provider) const transaction: UnsignedTransaction = buildAddPermissionlessDelegatorTransaction( - utxoSet, + account.utxoSet, account.getSignersAddresses(), fee.amount, provider.platformChain, @@ -181,8 +184,7 @@ export async function estimatePlatformDelegatePrimaryOperation ( delegate.stakeAddresses, delegate.stakeThreshold, delegate.rewardAddresses, - delegate.rewardThreshold, - account.utxoSet + delegate.rewardThreshold ).then( (fee) => { const spending: UtxoSpending = new UtxoSpending(chain, delegate.amount, chain.assetId, fee.transaction.getUtxos()) @@ -209,3 +211,46 @@ export async function estimatePlatformDelegatePrimaryOperation ( } ) } + +export async function estimatePlatformCreateSupernetTransaction ( + provider: MCNProvider, + account: PlatformAccount, + supernetAuthAddresses: string[], + supernetAuthThreshold: number +): Promise { + const fee: BaseFeeData = await getPlatformCreateSupernetFee(provider) + const transaction: UnsignedTransaction = buildCreateSupernetTransaction( + account.utxoSet, + account.getSignersAddresses(), + fee.amount, + provider.platformChain, + supernetAuthAddresses, + supernetAuthThreshold, + account.address, + provider.mcn.id + ) + return new UtxoFeeData(fee.chain, fee.amount, fee.type, transaction) +} + +export async function estimatePlatformCreateSupernetOperation ( + provider: MCNProvider, + createSupernet: CreateSupernetOperation, + account: PlatformAccount +): Promise { + const chain: PlatformBlockchain = provider.platformChain + const values = new Map() + return await estimatePlatformCreateSupernetTransaction( + provider, + account, + createSupernet.supernetAuthAddresses, + createSupernet.supernetAuthThreshold + ).then( + (fee) => { + return new ChainOperationSummary(provider, createSupernet, chain, fee, [fee.spending], values) + }, + async () => { + const fee: BaseFeeData = await getPlatformCreateSupernetFee(provider) + return new ChainOperationSummary(provider, createSupernet, chain, fee, [fee.spending], values) + } + ) +} diff --git a/src/wallet/transaction/transaction.ts b/src/wallet/transaction/transaction.ts index 382c1515..8c389f4f 100644 --- a/src/wallet/transaction/transaction.ts +++ b/src/wallet/transaction/transaction.ts @@ -15,6 +15,7 @@ export enum TransactionType { RedeemAuction = 'Redeem auction transaction', WithdrawStream = 'Withdraw stream transaction', CancelStream = 'Cancel stream transaction', + CreateSupernet = 'Create supernet transaction', } export class TransactionReceipt { From c1a246d4bbe6726f00ef121ea6dc9ace52bd568c Mon Sep 17 00:00:00 2001 From: alekswaslet <1346150+alekswaslet@users.noreply.github.com> Date: Tue, 30 Apr 2024 14:07:08 +0200 Subject: [PATCH 5/8] Add missing provider --- src/chain/jevm.ts | 4 ++-- src/chain/solidity/contract.ts | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/chain/jevm.ts b/src/chain/jevm.ts index 6cb45d5d..81af6c80 100644 --- a/src/chain/jevm.ts +++ b/src/chain/jevm.ts @@ -60,7 +60,7 @@ export class JEVMBlockchain extends AbstractBlockchain { // we avoid it if the asset is already registered const asset: TokenAsset = await this.getAsset(provider, assetId) if (Transferables.includes(asset.type)) { - return this.contractManager.getTransferData(assetId, to, amount) + return this.contractManager.getTransferData(this.ethProvider, assetId, to, amount) } return '0x' } @@ -93,6 +93,6 @@ export class JEVMBlockchain extends AbstractBlockchain { if (!isContractAddress(assetId)) { throw new ChainError(`cannot query balance of invalid asset id ${assetId}`) } - return await this.contractManager.balanceOf(assetId, address) + return await this.contractManager.balanceOf(this.ethProvider, assetId, address) } } diff --git a/src/chain/solidity/contract.ts b/src/chain/solidity/contract.ts index 624dcf34..b3ce3a64 100644 --- a/src/chain/solidity/contract.ts +++ b/src/chain/solidity/contract.ts @@ -23,13 +23,13 @@ export class ContractManager { this.handlers.unshift(handler) } - async balanceOf (contractAddress: string, address: string): Promise { - const contract: ethers.Contract = new ethers.Contract(contractAddress, abi.BalanceOfABI) + async balanceOf (provider: ethers.JsonRpcProvider, contractAddress: string, address: string): Promise { + const contract: ethers.Contract = new ethers.Contract(contractAddress, abi.BalanceOfABI, provider) return BigInt.asUintN(256, BigInt(await contract.balanceOf(address))) } - getTransferData (contractAddress: string, to: string, amount: bigint): string { - const contract: ethers.Contract = new ethers.Contract(contractAddress, abi.TransferABI) + getTransferData (provider: ethers.JsonRpcProvider, contractAddress: string, to: string, amount: bigint): string { + const contract: ethers.Contract = new ethers.Contract(contractAddress, abi.TransferABI, provider) return contract.interface.encodeFunctionData('transfer', [to, amount]) } } From d7d5576368bf3e065fa162c383aaeed70191d038 Mon Sep 17 00:00:00 2001 From: alekswaslet <1346150+alekswaslet@users.noreply.github.com> Date: Tue, 30 Apr 2024 14:45:08 +0200 Subject: [PATCH 6/8] Added AddSupernetValidatorOperation --- src/wallet/account/platform.ts | 10 +++- src/wallet/operation/operation.ts | 38 ++++++++++++--- src/wallet/transaction/platform.ts | 67 ++++++++++++++++++++++++++- src/wallet/transaction/transaction.ts | 1 + 4 files changed, 106 insertions(+), 10 deletions(-) diff --git a/src/wallet/account/platform.ts b/src/wallet/account/platform.ts index 0d4e93ff..30a3ba2e 100644 --- a/src/wallet/account/platform.ts +++ b/src/wallet/account/platform.ts @@ -7,7 +7,8 @@ import { estimatePlatformDelegatePrimaryOperation, estimateSendOperation, estimateSendUtxoOperation, - estimatePlatformCreateSupernetOperation + estimatePlatformCreateSupernetOperation, + estimatePlatformAddSupernetValidatorOperation } from '../transaction' import { AccountError } from '../../utils' import { @@ -19,7 +20,8 @@ import { type ChainNetworkOperation, type SendOperation, type SendUtxoOperation, - type CreateSupernetOperation + type CreateSupernetOperation, + AddSupernetValidatorOperation } from '../operation' import { type MCNWallet } from '../wallet' import { UtxoAccount } from './account' @@ -45,6 +47,8 @@ export class PlatformAccount extends UtxoAccount { return await estimateSendUtxoOperation(provider, this.chain, this, operation as SendUtxoOperation) } else if (operation.type === NetworkOperationType.CreateSupernet) { return await estimatePlatformCreateSupernetOperation(provider, operation as CreateSupernetOperation, this) + } else if (operation.type === NetworkOperationType.ValidateSupernet) { + return await estimatePlatformAddSupernetValidatorOperation(provider, operation as AddSupernetValidatorOperation, this) } throw new AccountError(`unsupported operation: ${operation.type} for the chain with id: ${this.chain.id}`) } @@ -62,6 +66,8 @@ export class PlatformAccount extends UtxoAccount { await this.executeAndTrackTransaction(summary, TransactionType.Send) } else if (operation === NetworkOperationType.CreateSupernet) { await this.executeAndTrackTransaction(summary, TransactionType.CreateSupernet) + } else if (operation === NetworkOperationType.ValidateSupernet) { + await this.executeAndTrackTransaction(summary, TransactionType.ValidateSupernet) } // balances fetching is needed to get new utxos creating from this operation await super.refreshBalances() diff --git a/src/wallet/operation/operation.ts b/src/wallet/operation/operation.ts index 1cda6272..d3604db6 100644 --- a/src/wallet/operation/operation.ts +++ b/src/wallet/operation/operation.ts @@ -1,6 +1,5 @@ import { type JRC20Asset, type WrappedAsset } from '../../asset' import { type JEVMBlockchain, type Blockchain, type PlatformBlockchain } from '../../chain' -import { type MCN } from '../../network' import { BLSPublicKey, BLSSignature, type Utxo } from '../../transaction' export enum NetworkOperationType { @@ -18,6 +17,7 @@ export enum NetworkOperationType { WithdrawStream = 'Withdraw stream', CancelStream = 'Cancel stream', CreateSupernet = 'Create supernet', + ValidateSupernet = 'Validate supernet', } export enum NetworkOperationRange { @@ -165,7 +165,7 @@ export abstract class Staking extends ChainNetworkOperation { constructor ( type: NetworkOperationType, - mcn: MCN, + chain: PlatformBlockchain, nodeId: string, amount: bigint, startTime: bigint, @@ -175,7 +175,7 @@ export abstract class Staking extends ChainNetworkOperation { rewardAddresses: string[], rewardThreshold: number ) { - super(type, mcn.primary.platform) + super(type, chain) this.nodeId = nodeId this.amount = amount this.startTime = startTime @@ -192,7 +192,7 @@ export class ValidatePrimaryOperation extends Staking { signature: BLSSignature constructor ( - mcn: MCN, + chain: PlatformBlockchain, nodeId: string, publicKey: string, signature: string, @@ -206,7 +206,7 @@ export class ValidatePrimaryOperation extends Staking { ) { super( NetworkOperationType.ValidatePrimary, - mcn, + chain, nodeId, amount, startTime, @@ -223,7 +223,7 @@ export class ValidatePrimaryOperation extends Staking { export class DelegatePrimaryOperation extends Staking { constructor ( - mcn: MCN, + chain: PlatformBlockchain, nodeId: string, amount: bigint, startTime: bigint, @@ -235,7 +235,7 @@ export class DelegatePrimaryOperation extends Staking { ) { super( NetworkOperationType.DelegatePrimary, - mcn, + chain, nodeId, amount, startTime, @@ -259,6 +259,30 @@ export class CreateSupernetOperation extends ChainNetworkOperation { } } +export class AddSupernetValidatorOperation extends ChainNetworkOperation { + supernetId: string + nodeId: string + amount: bigint + startTime: bigint + endTime: bigint + + constructor ( + chain: PlatformBlockchain, + supernetId: string, + nodeId: string, + amount: bigint, + startTime: bigint, + endTime: bigint + ) { + super(NetworkOperationType.ValidateSupernet, chain) + this.supernetId = supernetId + this.nodeId = nodeId + this.amount = amount + this.startTime = startTime + this.endTime = endTime + } +} + export class CrossOperation implements NetworkOperation { type: NetworkOperationType = NetworkOperationType.Cross range: NetworkOperationRange = NetworkOperationRange.Supernet diff --git a/src/wallet/transaction/platform.ts b/src/wallet/transaction/platform.ts index db8ab8f9..c83b7989 100644 --- a/src/wallet/transaction/platform.ts +++ b/src/wallet/transaction/platform.ts @@ -8,10 +8,14 @@ import { ProofOfPossession, PrimarySigner, buildAddPermissionlessDelegatorTransaction, - buildCreateSupernetTransaction + buildCreateSupernetTransaction, + buildAddSupernetValidatorTransaction, + CreateSupernetTransaction, + Address } from '../../transaction' import { type PlatformAccount } from '../account' import { + type AddSupernetValidatorOperation, ChainOperationSummary, type CreateSupernetOperation, type DelegatePrimaryOperation, @@ -36,6 +40,11 @@ async function getPlatformCreateSupernetFee (provider: MCNProvider): Promise { + const fee: bigint = BigInt((await provider.info.getTxFee()).addSupernetValidatorFee) + return new BaseFeeData(provider.platformChain, fee, FeeType.ValidateFee) +} + export async function estimatePlatformAddPrimaryValidatorTransaction ( provider: MCNProvider, account: PlatformAccount, @@ -254,3 +263,59 @@ export async function estimatePlatformCreateSupernetOperation ( } ) } + +export async function estimatePlatformAddSupernetValidatorTransaction ( + provider: MCNProvider, + account: PlatformAccount, + supernetId: string, + validator: Validator +): Promise { + const fee: BaseFeeData = await getPlatformAddSupernetValidatorFee(provider) + const createSupernetTx: CreateSupernetTransaction = CreateSupernetTransaction.parse( + (await provider.platformApi.getTx(supernetId)).tx + ) + const transaction: UnsignedTransaction = buildAddSupernetValidatorTransaction( + account.utxoSet, + account.getSignersAddresses(), + fee.amount, + provider.platformChain, + validator.nodeId, + validator.startTime, + validator.endTime, + validator.weight, + supernetId, + createSupernetTx.getSupernetAuth(Address.toAddresses(account.getSignersAddresses())), + account.address, + provider.mcn.id + ) + return new UtxoFeeData(fee.chain, fee.amount, fee.type, transaction) +} + +export async function estimatePlatformAddSupernetValidatorOperation ( + provider: MCNProvider, + addValidator: AddSupernetValidatorOperation, + account: PlatformAccount +): Promise { + const chain: PlatformBlockchain = provider.platformChain + const validator: Validator = new Validator( + new NodeId(addValidator.nodeId), + addValidator.startTime, + addValidator.endTime, + addValidator.amount + ) + const values = new Map() + return await estimatePlatformAddSupernetValidatorTransaction( + provider, + account, + addValidator.supernetId, + validator + ).then( + (fee) => { + return new ChainOperationSummary(provider, addValidator, chain, fee, [fee.spending], values) + }, + async () => { + const fee: BaseFeeData = await getPlatformAddSupernetValidatorFee(provider) + return new ChainOperationSummary(provider, addValidator, chain, fee, [fee.spending], values) + } + ) +} diff --git a/src/wallet/transaction/transaction.ts b/src/wallet/transaction/transaction.ts index 8c389f4f..f809f751 100644 --- a/src/wallet/transaction/transaction.ts +++ b/src/wallet/transaction/transaction.ts @@ -16,6 +16,7 @@ export enum TransactionType { WithdrawStream = 'Withdraw stream transaction', CancelStream = 'Cancel stream transaction', CreateSupernet = 'Create supernet transaction', + ValidateSupernet = 'Supernet validation transaction', } export class TransactionReceipt { From a87e6fb37c9659dba1a2c7064d752ee745313a37 Mon Sep 17 00:00:00 2001 From: alekswaslet <1346150+alekswaslet@users.noreply.github.com> Date: Tue, 30 Apr 2024 14:59:52 +0200 Subject: [PATCH 7/8] RemoveSupernetValidator Operation --- src/wallet/account/platform.ts | 20 ++++++++-- src/wallet/operation/operation.ts | 12 ++++++ src/wallet/transaction/fee.ts | 1 + src/wallet/transaction/platform.ts | 56 ++++++++++++++++++++++++++- src/wallet/transaction/transaction.ts | 1 + 5 files changed, 86 insertions(+), 4 deletions(-) diff --git a/src/wallet/account/platform.ts b/src/wallet/account/platform.ts index 30a3ba2e..e8f7730f 100644 --- a/src/wallet/account/platform.ts +++ b/src/wallet/account/platform.ts @@ -8,7 +8,8 @@ import { estimateSendOperation, estimateSendUtxoOperation, estimatePlatformCreateSupernetOperation, - estimatePlatformAddSupernetValidatorOperation + estimatePlatformAddSupernetValidatorOperation, + estimatePlatformRemoveSupernetValidatorOperation } from '../transaction' import { AccountError } from '../../utils' import { @@ -21,7 +22,8 @@ import { type SendOperation, type SendUtxoOperation, type CreateSupernetOperation, - AddSupernetValidatorOperation + type AddSupernetValidatorOperation, + type RemoveSupernetValidatorOperation } from '../operation' import { type MCNWallet } from '../wallet' import { UtxoAccount } from './account' @@ -48,7 +50,17 @@ export class PlatformAccount extends UtxoAccount { } else if (operation.type === NetworkOperationType.CreateSupernet) { return await estimatePlatformCreateSupernetOperation(provider, operation as CreateSupernetOperation, this) } else if (operation.type === NetworkOperationType.ValidateSupernet) { - return await estimatePlatformAddSupernetValidatorOperation(provider, operation as AddSupernetValidatorOperation, this) + return await estimatePlatformAddSupernetValidatorOperation( + provider, + operation as AddSupernetValidatorOperation, + this + ) + } else if (operation.type === NetworkOperationType.RemoveSupernetValidator) { + return await estimatePlatformRemoveSupernetValidatorOperation( + provider, + operation as RemoveSupernetValidatorOperation, + this + ) } throw new AccountError(`unsupported operation: ${operation.type} for the chain with id: ${this.chain.id}`) } @@ -68,6 +80,8 @@ export class PlatformAccount extends UtxoAccount { await this.executeAndTrackTransaction(summary, TransactionType.CreateSupernet) } else if (operation === NetworkOperationType.ValidateSupernet) { await this.executeAndTrackTransaction(summary, TransactionType.ValidateSupernet) + } else if (operation === NetworkOperationType.RemoveSupernetValidator) { + await this.executeAndTrackTransaction(summary, TransactionType.RemoveSupernetValidator) } // balances fetching is needed to get new utxos creating from this operation await super.refreshBalances() diff --git a/src/wallet/operation/operation.ts b/src/wallet/operation/operation.ts index d3604db6..efe6c596 100644 --- a/src/wallet/operation/operation.ts +++ b/src/wallet/operation/operation.ts @@ -18,6 +18,7 @@ export enum NetworkOperationType { CancelStream = 'Cancel stream', CreateSupernet = 'Create supernet', ValidateSupernet = 'Validate supernet', + RemoveSupernetValidator = 'Remove supernet validator', } export enum NetworkOperationRange { @@ -283,6 +284,17 @@ export class AddSupernetValidatorOperation extends ChainNetworkOperation { } } +export class RemoveSupernetValidatorOperation extends ChainNetworkOperation { + supernetId: string + nodeId: string + + constructor (chain: PlatformBlockchain, supernetId: string, nodeId: string) { + super(NetworkOperationType.RemoveSupernetValidator, chain) + this.supernetId = supernetId + this.nodeId = nodeId + } +} + export class CrossOperation implements NetworkOperation { type: NetworkOperationType = NetworkOperationType.Cross range: NetworkOperationRange = NetworkOperationRange.Supernet diff --git a/src/wallet/transaction/fee.ts b/src/wallet/transaction/fee.ts index fef39145..46269258 100644 --- a/src/wallet/transaction/fee.ts +++ b/src/wallet/transaction/fee.ts @@ -19,6 +19,7 @@ export enum FeeType { WithdrawStream = 'Withdraw stream fee', CancelStream = 'Cancel stream fee', CreateSupernet = 'Create supernet fee', + RemoveSupernetValidator = 'Remove supernet validator fee', } export interface FeeData { diff --git a/src/wallet/transaction/platform.ts b/src/wallet/transaction/platform.ts index c83b7989..8ff8fa25 100644 --- a/src/wallet/transaction/platform.ts +++ b/src/wallet/transaction/platform.ts @@ -11,7 +11,8 @@ import { buildCreateSupernetTransaction, buildAddSupernetValidatorTransaction, CreateSupernetTransaction, - Address + Address, + buildRemoveSupernetValidatorTransaction } from '../../transaction' import { type PlatformAccount } from '../account' import { @@ -19,6 +20,7 @@ import { ChainOperationSummary, type CreateSupernetOperation, type DelegatePrimaryOperation, + type RemoveSupernetValidatorOperation, StakingOperationSummary, type ValidatePrimaryOperation } from '../operation' @@ -45,6 +47,11 @@ async function getPlatformAddSupernetValidatorFee (provider: MCNProvider): Promi return new BaseFeeData(provider.platformChain, fee, FeeType.ValidateFee) } +async function getPlatformRemoveSupernetValidatorFee (provider: MCNProvider): Promise { + const fee: bigint = BigInt((await provider.info.getTxFee()).txFee) + return new BaseFeeData(provider.platformChain, fee, FeeType.RemoveSupernetValidator) +} + export async function estimatePlatformAddPrimaryValidatorTransaction ( provider: MCNProvider, account: PlatformAccount, @@ -319,3 +326,50 @@ export async function estimatePlatformAddSupernetValidatorOperation ( } ) } + +export async function estimatePlatformRemoveSupernetValidatorTransaction ( + provider: MCNProvider, + account: PlatformAccount, + supernetId: string, + nodeId: string +): Promise { + const fee: BaseFeeData = await getPlatformRemoveSupernetValidatorFee(provider) + const createSupernetTx: CreateSupernetTransaction = CreateSupernetTransaction.parse( + (await provider.platformApi.getTx(supernetId)).tx + ) + const transaction: UnsignedTransaction = buildRemoveSupernetValidatorTransaction( + account.utxoSet, + account.getSignersAddresses(), + fee.amount, + provider.platformChain, + nodeId, + supernetId, + createSupernetTx.getSupernetAuth(Address.toAddresses(account.getSignersAddresses())), + account.address, + provider.mcn.id + ) + return new UtxoFeeData(fee.chain, fee.amount, fee.type, transaction) +} + +export async function estimatePlatformRemoveSupernetValidatorOperation ( + provider: MCNProvider, + removeValidator: RemoveSupernetValidatorOperation, + account: PlatformAccount +): Promise { + const chain: PlatformBlockchain = provider.platformChain + const values = new Map() + return await estimatePlatformRemoveSupernetValidatorTransaction( + provider, + account, + removeValidator.supernetId, + removeValidator.nodeId + ).then( + (fee) => { + return new ChainOperationSummary(provider, removeValidator, chain, fee, [fee.spending], values) + }, + async () => { + const fee: BaseFeeData = await getPlatformRemoveSupernetValidatorFee(provider) + return new ChainOperationSummary(provider, removeValidator, chain, fee, [fee.spending], values) + } + ) +} diff --git a/src/wallet/transaction/transaction.ts b/src/wallet/transaction/transaction.ts index f809f751..e2b06f24 100644 --- a/src/wallet/transaction/transaction.ts +++ b/src/wallet/transaction/transaction.ts @@ -17,6 +17,7 @@ export enum TransactionType { CancelStream = 'Cancel stream transaction', CreateSupernet = 'Create supernet transaction', ValidateSupernet = 'Supernet validation transaction', + RemoveSupernetValidator = 'Remove supernet validator transaction', } export class TransactionReceipt { From d65f03e7dd700b3a0515ea949275b66ff6df9468 Mon Sep 17 00:00:00 2001 From: alekswaslet <1346150+alekswaslet@users.noreply.github.com> Date: Tue, 30 Apr 2024 15:00:04 +0200 Subject: [PATCH 8/8] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f12645ce..14c414c5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "juneojs", - "version": "0.0.90", + "version": "0.0.91", "description": "Juneo JS Library", "main": "dist/index.js", "types": "dist/index.d.ts",