Skip to content

Commit

Permalink
Merge pull request #106 from Juneo-io/dev
Browse files Browse the repository at this point in the history
v0.0.91
  • Loading branch information
alekswaslet authored Apr 30, 2024
2 parents a9bd35b + d65f03e commit 8b36df6
Show file tree
Hide file tree
Showing 12 changed files with 335 additions and 62 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
18 changes: 6 additions & 12 deletions src/chain/jevm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -22,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 (
Expand All @@ -47,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 (
Expand All @@ -60,9 +59,8 @@ 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)) {
return this.erc20Handler.getTransferData(assetId, to, amount)
if (Transferables.includes(asset.type)) {
return this.contractManager.getTransferData(this.ethProvider, assetId, to, amount)
}
return '0x'
}
Expand All @@ -82,7 +80,7 @@ export class JEVMBlockchain extends AbstractBlockchain {
return ethers.isAddress(address)
}

async queryEVMBalance (api: JEVMAPI, address: string, assetId: string): Promise<bigint> {
async queryBalance (api: JEVMAPI, address: string, assetId: string): Promise<bigint> {
// native asset
if (assetId === this.assetId) {
return await api.eth_getBalance(address, 'pending')
Expand All @@ -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(this.ethProvider, assetId, address)
}
}
4 changes: 4 additions & 0 deletions src/chain/solidity/abi.ts
Original file line number Diff line number Diff line change
@@ -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)',
Expand Down
24 changes: 10 additions & 14 deletions src/chain/solidity/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,22 @@ export class ContractManager {
// Should do a better getHandler function in the future
this.handlers.unshift(handler)
}

async balanceOf (provider: ethers.JsonRpcProvider, contractAddress: string, address: string): Promise<bigint> {
const contract: ethers.Contract = new ethers.Contract(contractAddress, abi.BalanceOfABI, provider)
return BigInt.asUintN(256, BigInt(await contract.balanceOf(address)))
}

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])
}
}

export interface SolidityTokenHandler {
instanceOf: (contractAddress: string) => Promise<boolean>

queryBalance: (contractAddress: string, address: string) => Promise<bigint>

queryTokenData: (contractAddress: string) => Promise<TokenAsset>

getTransferData: (contractAddress: string, to: string, amount: bigint) => string
}

export class ERC20TokenHandler implements SolidityTokenHandler {
Expand All @@ -52,11 +58,6 @@ export class ERC20TokenHandler implements SolidityTokenHandler {
return true
}

async queryBalance (contractAddress: string, address: string): Promise<bigint> {
const contract: ethers.Contract = this.getContract(contractAddress)
return BigInt.asUintN(256, BigInt(await contract.balanceOf(address)))
}

async queryTokenData (contractAddress: string): Promise<TokenAsset> {
const contract: ethers.Contract = this.getContract(contractAddress)
const name: string = await contract.name()
Expand All @@ -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)
}
Expand Down
2 changes: 1 addition & 1 deletion src/wallet/account/evm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
}
30 changes: 28 additions & 2 deletions src/wallet/account/platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import {
estimatePlatformValidatePrimaryOperation,
estimatePlatformDelegatePrimaryOperation,
estimateSendOperation,
estimateSendUtxoOperation
estimateSendUtxoOperation,
estimatePlatformCreateSupernetOperation,
estimatePlatformAddSupernetValidatorOperation,
estimatePlatformRemoveSupernetValidatorOperation
} from '../transaction'
import { AccountError } from '../../utils'
import {
Expand All @@ -17,7 +20,10 @@ import {
type ValidatePrimaryOperation,
type ChainNetworkOperation,
type SendOperation,
type SendUtxoOperation
type SendUtxoOperation,
type CreateSupernetOperation,
type AddSupernetValidatorOperation,
type RemoveSupernetValidatorOperation
} from '../operation'
import { type MCNWallet } from '../wallet'
import { UtxoAccount } from './account'
Expand All @@ -41,6 +47,20 @@ 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)
} else if (operation.type === NetworkOperationType.ValidateSupernet) {
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}`)
}
Expand All @@ -56,6 +76,12 @@ 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)
} 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()
Expand Down
64 changes: 56 additions & 8 deletions src/wallet/operation/operation.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { type JRC20Asset, type WrappedAsset } from '../../asset'
import { type JEVMBlockchain, type Blockchain } from '../../chain'
import { type MCN } from '../../network'
import { type JEVMBlockchain, type Blockchain, type PlatformBlockchain } from '../../chain'
import { BLSPublicKey, BLSSignature, type Utxo } from '../../transaction'

export enum NetworkOperationType {
Expand All @@ -17,6 +16,9 @@ export enum NetworkOperationType {
RedeemAuction = 'Redeem auction',
WithdrawStream = 'Withdraw stream',
CancelStream = 'Cancel stream',
CreateSupernet = 'Create supernet',
ValidateSupernet = 'Validate supernet',
RemoveSupernetValidator = 'Remove supernet validator',
}

export enum NetworkOperationRange {
Expand Down Expand Up @@ -164,7 +166,7 @@ export abstract class Staking extends ChainNetworkOperation {

constructor (
type: NetworkOperationType,
mcn: MCN,
chain: PlatformBlockchain,
nodeId: string,
amount: bigint,
startTime: bigint,
Expand All @@ -174,7 +176,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
Expand All @@ -191,7 +193,7 @@ export class ValidatePrimaryOperation extends Staking {
signature: BLSSignature

constructor (
mcn: MCN,
chain: PlatformBlockchain,
nodeId: string,
publicKey: string,
signature: string,
Expand All @@ -205,7 +207,7 @@ export class ValidatePrimaryOperation extends Staking {
) {
super(
NetworkOperationType.ValidatePrimary,
mcn,
chain,
nodeId,
amount,
startTime,
Expand All @@ -222,7 +224,7 @@ export class ValidatePrimaryOperation extends Staking {

export class DelegatePrimaryOperation extends Staking {
constructor (
mcn: MCN,
chain: PlatformBlockchain,
nodeId: string,
amount: bigint,
startTime: bigint,
Expand All @@ -234,7 +236,7 @@ export class DelegatePrimaryOperation extends Staking {
) {
super(
NetworkOperationType.DelegatePrimary,
mcn,
chain,
nodeId,
amount,
startTime,
Expand All @@ -247,6 +249,52 @@ 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 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 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
Expand Down
10 changes: 3 additions & 7 deletions src/wallet/transaction/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -24,23 +23,22 @@ export async function estimateBaseTransaction (
amount: bigint,
addresses: string[],
threshold: number,
utxoSet: Utxo[],
locktime: bigint = BigInt(0)
): Promise<UtxoFeeData> {
const fee: BaseFeeData = await getBaseTxFee(provider, FeeType.BaseFee, chain)
const transaction: UnsignedTransaction =
chain.id === provider.platformChain.id
? buildPlatformBaseTransaction(
[new UserInput(assetId, chain, amount, addresses, threshold, chain, locktime)],
utxoSet,
account.utxoSet,
account.getSignersAddresses(),
fee.amount,
account.address,
provider.mcn.id
)
: buildJVMBaseTransaction(
[new UserInput(assetId, chain, amount, addresses, threshold, chain, locktime)],
utxoSet,
account.utxoSet,
account.getSignersAddresses(),
fee.amount,
account.address,
Expand All @@ -64,7 +62,6 @@ export async function estimateSendOperation (
send.amount,
[send.address],
1,
account.utxoSet,
BigInt(0)
).then(
(fee) => {
Expand Down Expand Up @@ -100,7 +97,6 @@ export async function estimateSendUtxoOperation (
send.amount,
send.addresses,
send.threshold,
account.utxoSet,
send.locktime
).then(
(fee) => {
Expand Down
Loading

0 comments on commit 8b36df6

Please sign in to comment.