From e6edfde65e0f3582a39ab5cd8266ee38a182fbf1 Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Thu, 30 May 2024 20:39:44 +0330 Subject: [PATCH 001/132] initial ergo chain --- package.json | 1 + src/chains/ergo/dex.service.ts | 45 +++++ src/chains/ergo/ergo.config.ts | 33 ++++ src/chains/ergo/ergo.controller.ts | 4 + src/chains/ergo/ergo.interface.ts | 6 + src/chains/ergo/ergo.ts | 267 +++++++++++++++++++++++++++++ src/chains/ergo/node.service.ts | 45 +++++ 7 files changed, 401 insertions(+) create mode 100644 src/chains/ergo/dex.service.ts create mode 100644 src/chains/ergo/ergo.config.ts create mode 100644 src/chains/ergo/ergo.controller.ts create mode 100644 src/chains/ergo/ergo.interface.ts create mode 100644 src/chains/ergo/ergo.ts create mode 100644 src/chains/ergo/node.service.ts diff --git a/package.json b/package.json index da576477f8..38e07972dc 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "@pancakeswap/tokens": "^0.1.6", "@pancakeswap/v3-core": "^1.0.2", "@pancakeswap/v3-periphery": "^1.0.2", + "ergo-lib-wasm-nodejs": "^0.22.0", "@pancakeswap/v3-sdk": "^3.7.0", "@pangolindex/sdk": "^1.1.0", "@perp/sdk-curie": "^1.16.0", diff --git a/src/chains/ergo/dex.service.ts b/src/chains/ergo/dex.service.ts new file mode 100644 index 0000000000..b62b5c257e --- /dev/null +++ b/src/chains/ergo/dex.service.ts @@ -0,0 +1,45 @@ +import axios, { AxiosInstance } from 'axios' +import { BlockHeaders, ErgoStateContext, PreHeader } from 'ergo-lib-wasm-nodejs' + +export class DexService { + private backend: AxiosInstance + + constructor(dexURL: string, timeOut: number) { + this.backend = axios.create({ + baseURL: dexURL, + timeout: timeOut, + headers: { 'Content-Type': 'application/json' }, + }) + } + + async get(url: string, headers?: any, params?: any) { + return this.backend.get(url, { + timeout: 25000, + headers: { + 'Content-Type': 'application/json', + ...headers + }, + params + }).then((res: any) => res.data) + } + + async head(url: string) { + return this.backend.head(url, { + timeout: 1000 + }).then((res: any) => res.status).catch((e: any) => e.response.status) + } + + async post(url: string, headers?: any, params?: any) { + this.backend.defaults.headers = { + 'Content-Type': 'application/json', + ...headers + } + this.backend.defaults.timeout = 25000 + return this.backend.post(url, params).then((res: any) => res) + } + + async getTokens() { + return this.get('/ergo-token-list.json') + } + +} diff --git a/src/chains/ergo/ergo.config.ts b/src/chains/ergo/ergo.config.ts new file mode 100644 index 0000000000..b1a026cac2 --- /dev/null +++ b/src/chains/ergo/ergo.config.ts @@ -0,0 +1,33 @@ +import {ConfigManagerV2} from "../../services/config-manager-v2"; +import {NetworkPrefix} from "ergo-lib-wasm-nodejs"; + + +export interface NetworkConfig { + name: string; + nodeURL: string; + timeOut: number; + networkPrefix: NetworkPrefix; + minTxFee: number; + maxLRUCacheInstances: number; +} +export interface Config { + network: NetworkConfig; +} +export function getErgoConfig(network: string): Config { + return { + network: { + name: network, + nodeURL: ConfigManagerV2.getInstance().get( + 'algorand.networks.' + network + '.nodeURL' + ), + timeOut: ConfigManagerV2.getInstance().get( + 'ergo.networks.' + network + '.timeOut' + ), + networkPrefix: network === "Mainnet" ? NetworkPrefix.Mainnet : NetworkPrefix.Testnet, + minTxFee: ConfigManagerV2.getInstance().get( + 'algorand.networks.' + network + '.minTxFee' + ), + maxLRUCacheInstances: 10 + }, + }; +} \ No newline at end of file diff --git a/src/chains/ergo/ergo.controller.ts b/src/chains/ergo/ergo.controller.ts new file mode 100644 index 0000000000..8ee53f549d --- /dev/null +++ b/src/chains/ergo/ergo.controller.ts @@ -0,0 +1,4 @@ + +export class ErgoController{ + +} \ No newline at end of file diff --git a/src/chains/ergo/ergo.interface.ts b/src/chains/ergo/ergo.interface.ts new file mode 100644 index 0000000000..80d24d39eb --- /dev/null +++ b/src/chains/ergo/ergo.interface.ts @@ -0,0 +1,6 @@ +export interface ErgoAsset { + tokenId: number; + decimals: number; + name: string; + symbol: string +} \ No newline at end of file diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts new file mode 100644 index 0000000000..4f0a01af31 --- /dev/null +++ b/src/chains/ergo/ergo.ts @@ -0,0 +1,267 @@ +import {NetworkPrefix} from "ergo-lib-wasm-nodejs" +import LRUCache from 'lru-cache'; +import {ErgoController} from "./ergo.controller"; +import {NodeService} from "./node.service"; +import { TokenListType } from '../../services/base'; +import {getErgoConfig} from "./ergo.config"; +import {DexService} from "./dex.service"; +import {ErgoAsset} from "./ergo.interface"; + +type AssetListType = TokenListType; +export class Ergo { + private _assetMap: Record = {}; + private static _instances: LRUCache; + private _chain: string = 'ergo'; + private _network: string; + private _networkPrefix: NetworkPrefix; + private _node: NodeService; + private _dex: DexService; + private _assetListType: AssetListType; + private _assetListSource: string; + private _ready: boolean = false; + public txFee: number; + public controller: typeof ErgoController; + + constructor ( + network: string, + nodeUrl: string + ) { + this._network = network + const config = getErgoConfig(network); + if (network === "Mainnet") + this._networkPrefix = NetworkPrefix.Mainnet + else + this._networkPrefix = NetworkPrefix.Testnet + this._node = new NodeService(nodeUrl, config.network.timeOut) + this._dex = new DexService(nodeUrl, config.network.timeOut) + this.controller = ErgoController; + this.txFee = config.network.minTxFee; + this._assetListType = "URL" + } + public get node(): NodeService { + return this._node; + } + + public get network(): string { + return this._network; + } + + public get storedAssetList(): ErgoAsset[] { + return Object.values(this._assetMap); + } + + public ready(): boolean { + return this._ready; + } + + public async init(): Promise { + await this.loadAssets(); + this._ready = true; + return; + } + + async close() { + return; + } + + public static getInstance(network: string): Ergo { + const config = getErgoConfig(network); + if (Ergo._instances === undefined) { + Ergo._instances = new LRUCache({ + max: config.network.maxLRUCacheInstances, + }); + } + + if (!Ergo._instances.has(config.network.name)) { + if (network !== null) { + const nodeUrl = config.network.nodeURL; + Ergo._instances.set( + config.network.name, + new Ergo( + network, + nodeUrl + ) + ); + } else { + throw new Error( + `Ergo.getInstance received an unexpected network: ${network}.` + ); + } + } + + return Ergo._instances.get(config.network.name) as Ergo; + } + + public static getConnectedInstances(): { [name: string]: Ergo } { + const connectedInstances: { [name: string]: Ergo } = {}; + if (this._instances !== undefined) { + const keys = Array.from(this._instances.keys()); + for (const instance of keys) { + if (instance !== undefined) { + connectedInstances[instance] = this._instances.get( + instance + ) as Ergo; + } + } + } + return connectedInstances; + } + + async getCurrentBlockNumber(): Promise { + const status = await this._node.getNetworkHeight() + return status + 1; + } + + // public async getTransaction(txHash: string): Promise { + // const transactionId = txHash.startsWith('0x') ? txHash.slice(2) : txHash; + // let currentBlock; + // let transactionData; + // let transactionBlock; + // let fee; + // try { + // transactionData = await this._algod + // .pendingTransactionInformation(transactionId) + // .do(); + // transactionBlock = transactionData['confirmed-round']; // will be undefined if not confirmed + // transactionBlock = transactionBlock ? transactionBlock : null; + // fee = transactionData.txn.fee; + // currentBlock = await this.getCurrentBlockNumber(); + // } catch (error: any) { + // if (error.status != 404) { + // throw error; + // } + // transactionData = await this._indexer + // .lookupTransactionByID(transactionId) + // .do(); + // currentBlock = transactionData['current-round']; + // transactionBlock = transactionData.transaction['confirmed-round']; + // fee = transactionData.transaction.fee; + // } + // return { + // currentBlock, + // txBlock: transactionBlock, + // txHash: '0x' + transactionId, + // fee, + // }; + // } + // + // public getAccountFromPrivateKey(mnemonic: string): Account { + // return mnemonicToSecretKey(mnemonic); + // } + // async getAccountFromAddress(address: string): Promise { + // const path = `${walletPath}/${this._chain}`; + // const encryptedMnemonic: string = await fse.readFile( + // `${path}/${address}.json`, + // 'utf8' + // ); + // const passphrase = ConfigManagerCertPassphrase.readPassphrase(); + // if (!passphrase) { + // throw new Error('missing passphrase'); + // } + // const mnemonic = this.decrypt(encryptedMnemonic, passphrase); + // + // return mnemonicToSecretKey(mnemonic); + // } + // + // public encrypt(mnemonic: string, password: string): string { + // const iv = randomBytes(16); + // const key = Buffer.alloc(32); + // key.write(password); + // + // const cipher = createCipheriv('aes-256-cbc', key, iv); + // + // const encrypted = Buffer.concat([cipher.update(mnemonic), cipher.final()]); + // + // return `${iv.toString('hex')}:${encrypted.toString('hex')}`; + // } + // + // public decrypt(encryptedMnemonic: string, password: string): string { + // const [iv, encryptedKey] = encryptedMnemonic.split(':'); + // const key = Buffer.alloc(32); + // key.write(password); + // + // const decipher = createDecipheriv( + // 'aes-256-cbc', + // key, + // Buffer.from(iv, 'hex') + // ); + // + // const decrpyted = Buffer.concat([ + // decipher.update(Buffer.from(encryptedKey, 'hex')), + // decipher.final(), + // ]); + // + // return decrpyted.toString(); + // } + // + // public async getAssetBalance( + // account: Account, + // assetName: string + // ): Promise { + // const algorandAsset = this._assetMap[assetName]; + // let balance; + // + // try { + // const response = await this._algod + // .accountAssetInformation(account.addr, algorandAsset.assetId) + // .do(); + // balance = response['asset-holding'].amount; + // } catch (error: any) { + // if (!error.message.includes('account asset info not found')) { + // throw error; + // } + // balance = 0; + // } + // + // const amount = balance * parseFloat(`1e-${algorandAsset.decimals}`); + // return amount.toString(); + // } + // + // public async getNativeBalance(account: Account): Promise { + // const accountInfo = await this._algod.accountInformation(account.addr).do(); + // const algoAsset = this._assetMap[this.nativeTokenSymbol]; + // return ( + // accountInfo.amount * parseFloat(`1e-${algoAsset.decimals}`) + // ).toString(); + // } + // + // public getAssetForSymbol(symbol: string): AlgorandAsset | null { + // return this._assetMap[symbol] ? this._assetMap[symbol] : null; + // } + // + // public async optIn(address: string, symbol: string) { + // const account = await this.getAccountFromAddress(address); + // const assetIndex = this._assetMap[symbol].assetId; + // const suggestedParams = await this._algod.getTransactionParams().do(); + // const optInTxn = makeAssetTransferTxnWithSuggestedParamsFromObject({ + // from: account.addr, + // to: address, + // suggestedParams, + // assetIndex, + // amount: 0, + // }); + // const signedOptInTxn = optInTxn.signTxn(account.sk); + // const resp = await this._algod.sendRawTransaction(signedOptInTxn).do(); + // return resp; + // } + // + private async loadAssets(): Promise { + const assetData = await this.getAssetData(); + for (const result of assetData.tokens) { + this._assetMap[result.name.toUpperCase()] = { + tokenId: result.address, + decimals: result.decimals, + name: result.name, + symbol: result.ticker + }; + } + } + + private async getAssetData(): Promise { + return await this._dex.getTokens(); + } + + public get storedTokenList() { + return this._assetMap; + } +} \ No newline at end of file diff --git a/src/chains/ergo/node.service.ts b/src/chains/ergo/node.service.ts new file mode 100644 index 0000000000..454deb0745 --- /dev/null +++ b/src/chains/ergo/node.service.ts @@ -0,0 +1,45 @@ +import axios, { AxiosInstance } from 'axios' + +export class NodeService { + private backend: AxiosInstance + + constructor(nodeURL: string, timeOut: number) { + this.backend = axios.create({ + baseURL: nodeURL, + timeout: timeOut, + headers: { 'Content-Type': 'application/json' }, + }) + } + + async get(url: string, headers?: any, params?: any) { + return this.backend.get(url, { + timeout: 25000, + headers: { + 'Content-Type': 'application/json', + ...headers + }, + params + }).then((res: any) => res.data) + } + + async head(url: string) { + return this.backend.head(url, { + timeout: 1000 + }).then((res: any) => res.status).catch((e: any) => e.response.status) + } + + async post(url: string, headers?: any, params?: any) { + this.backend.defaults.headers = { + 'Content-Type': 'application/json', + ...headers + } + this.backend.defaults.timeout = 25000 + return this.backend.post(url, params).then((res: any) => res) + } + + async getNetworkHeight(): Promise { + const info = await this.get(`/info`); + return info.fullHeight + } + +} From 50f583c827bc829e32ec2b90beb005ae4569f4bf Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Sun, 2 Jun 2024 02:50:47 +0330 Subject: [PATCH 002/132] other ergo class functions implemented --- package.json | 5 +- src/chains/ergo/ergo.config.ts | 4 +- src/chains/ergo/ergo.interface.ts | 21 ++- src/chains/ergo/ergo.ts | 219 +++++++++++------------------- src/chains/ergo/node.service.ts | 4 + 5 files changed, 108 insertions(+), 145 deletions(-) diff --git a/package.json b/package.json index 38e07972dc..f1024672e0 100644 --- a/package.json +++ b/package.json @@ -23,8 +23,8 @@ "test:scripts": "jest -i --verbose ./test-scripts/*.test.ts" }, "dependencies": { - "@cosmjs/amino": "^0.32.2", "@bancor/carbon-sdk": "^0.0.93-DEV", + "@cosmjs/amino": "^0.32.2", "@cosmjs/proto-signing": "^0.31.1", "@cosmjs/stargate": "^0.31.1", "@cosmjs/tendermint-rpc": "^0.32.2", @@ -35,6 +35,7 @@ "@ethersproject/networks": "5.7.0", "@ethersproject/providers": "5.7.0", "@ethersproject/solidity": "5.7.0", + "@fleet-sdk/common": "^0.3.4", "@harmony-js/core": "^0.1.57", "@harmony-js/utils": "^0.1.56", "@improbable-eng/grpc-web": "^0.13.0", @@ -46,7 +47,6 @@ "@pancakeswap/tokens": "^0.1.6", "@pancakeswap/v3-core": "^1.0.2", "@pancakeswap/v3-periphery": "^1.0.2", - "ergo-lib-wasm-nodejs": "^0.22.0", "@pancakeswap/v3-sdk": "^3.7.0", "@pangolindex/sdk": "^1.1.0", "@perp/sdk-curie": "^1.16.0", @@ -79,6 +79,7 @@ "coinalpha-ref-sdk": "1.1.0", "dayjs": "^1.10.6", "decimal.js-light": "^2.5.1", + "ergo-lib-wasm-nodejs": "^0.22.0", "ethers": "^5.6.2", "ethers-xdc": "file:./vendor/ethers-xdc", "express": "^4.17.1", diff --git a/src/chains/ergo/ergo.config.ts b/src/chains/ergo/ergo.config.ts index b1a026cac2..46553a11a7 100644 --- a/src/chains/ergo/ergo.config.ts +++ b/src/chains/ergo/ergo.config.ts @@ -9,6 +9,7 @@ export interface NetworkConfig { networkPrefix: NetworkPrefix; minTxFee: number; maxLRUCacheInstances: number; + utxosLimit: number } export interface Config { network: NetworkConfig; @@ -27,7 +28,8 @@ export function getErgoConfig(network: string): Config { minTxFee: ConfigManagerV2.getInstance().get( 'algorand.networks.' + network + '.minTxFee' ), - maxLRUCacheInstances: 10 + maxLRUCacheInstances: 10, + utxosLimit: 100 }, }; } \ No newline at end of file diff --git a/src/chains/ergo/ergo.interface.ts b/src/chains/ergo/ergo.interface.ts index 80d24d39eb..3a9ac681ee 100644 --- a/src/chains/ergo/ergo.interface.ts +++ b/src/chains/ergo/ergo.interface.ts @@ -1,6 +1,25 @@ +import {Wallet} from "ergo-lib-wasm-nodejs"; +import {ErgoTreeHex, NonMandatoryRegisters} from "@fleet-sdk/common"; export interface ErgoAsset { tokenId: number; decimals: number; name: string; symbol: string -} \ No newline at end of file +} + +export interface Account { + wallet: Wallet; + address: string; +} + + + +export type BoxType = { + boxId: string; + ergoTree: ErgoTreeHex; + creationHeight: number; + value: number; + assets: any[]; + additionalRegisters: NonMandatoryRegisters; + index?: number +}; \ No newline at end of file diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 4f0a01af31..b6e360a6eb 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -1,13 +1,13 @@ -import {NetworkPrefix} from "ergo-lib-wasm-nodejs" +import {NetworkPrefix, SecretKey, SecretKeys, Wallet} from "ergo-lib-wasm-nodejs" import LRUCache from 'lru-cache'; import {ErgoController} from "./ergo.controller"; import {NodeService} from "./node.service"; -import { TokenListType } from '../../services/base'; import {getErgoConfig} from "./ergo.config"; import {DexService} from "./dex.service"; -import {ErgoAsset} from "./ergo.interface"; +import {Account, BoxType, ErgoAsset} from "./ergo.interface"; +import {createCipheriv, createDecipheriv, randomBytes} from 'crypto'; + -type AssetListType = TokenListType; export class Ergo { private _assetMap: Record = {}; private static _instances: LRUCache; @@ -16,13 +16,12 @@ export class Ergo { private _networkPrefix: NetworkPrefix; private _node: NodeService; private _dex: DexService; - private _assetListType: AssetListType; - private _assetListSource: string; private _ready: boolean = false; public txFee: number; public controller: typeof ErgoController; + private utxosLimit: number; - constructor ( + constructor( network: string, nodeUrl: string ) { @@ -36,8 +35,9 @@ export class Ergo { this._dex = new DexService(nodeUrl, config.network.timeOut) this.controller = ErgoController; this.txFee = config.network.minTxFee; - this._assetListType = "URL" + this.utxosLimit = config.network.utxosLimit } + public get node(): NodeService { return this._node; } @@ -112,139 +112,76 @@ export class Ergo { return status + 1; } - // public async getTransaction(txHash: string): Promise { - // const transactionId = txHash.startsWith('0x') ? txHash.slice(2) : txHash; - // let currentBlock; - // let transactionData; - // let transactionBlock; - // let fee; - // try { - // transactionData = await this._algod - // .pendingTransactionInformation(transactionId) - // .do(); - // transactionBlock = transactionData['confirmed-round']; // will be undefined if not confirmed - // transactionBlock = transactionBlock ? transactionBlock : null; - // fee = transactionData.txn.fee; - // currentBlock = await this.getCurrentBlockNumber(); - // } catch (error: any) { - // if (error.status != 404) { - // throw error; - // } - // transactionData = await this._indexer - // .lookupTransactionByID(transactionId) - // .do(); - // currentBlock = transactionData['current-round']; - // transactionBlock = transactionData.transaction['confirmed-round']; - // fee = transactionData.transaction.fee; - // } - // return { - // currentBlock, - // txBlock: transactionBlock, - // txHash: '0x' + transactionId, - // fee, - // }; - // } - // - // public getAccountFromPrivateKey(mnemonic: string): Account { - // return mnemonicToSecretKey(mnemonic); - // } - // async getAccountFromAddress(address: string): Promise { - // const path = `${walletPath}/${this._chain}`; - // const encryptedMnemonic: string = await fse.readFile( - // `${path}/${address}.json`, - // 'utf8' - // ); - // const passphrase = ConfigManagerCertPassphrase.readPassphrase(); - // if (!passphrase) { - // throw new Error('missing passphrase'); - // } - // const mnemonic = this.decrypt(encryptedMnemonic, passphrase); - // - // return mnemonicToSecretKey(mnemonic); - // } - // - // public encrypt(mnemonic: string, password: string): string { - // const iv = randomBytes(16); - // const key = Buffer.alloc(32); - // key.write(password); - // - // const cipher = createCipheriv('aes-256-cbc', key, iv); - // - // const encrypted = Buffer.concat([cipher.update(mnemonic), cipher.final()]); - // - // return `${iv.toString('hex')}:${encrypted.toString('hex')}`; - // } - // - // public decrypt(encryptedMnemonic: string, password: string): string { - // const [iv, encryptedKey] = encryptedMnemonic.split(':'); - // const key = Buffer.alloc(32); - // key.write(password); - // - // const decipher = createDecipheriv( - // 'aes-256-cbc', - // key, - // Buffer.from(iv, 'hex') - // ); - // - // const decrpyted = Buffer.concat([ - // decipher.update(Buffer.from(encryptedKey, 'hex')), - // decipher.final(), - // ]); - // - // return decrpyted.toString(); - // } - // - // public async getAssetBalance( - // account: Account, - // assetName: string - // ): Promise { - // const algorandAsset = this._assetMap[assetName]; - // let balance; - // - // try { - // const response = await this._algod - // .accountAssetInformation(account.addr, algorandAsset.assetId) - // .do(); - // balance = response['asset-holding'].amount; - // } catch (error: any) { - // if (!error.message.includes('account asset info not found')) { - // throw error; - // } - // balance = 0; - // } - // - // const amount = balance * parseFloat(`1e-${algorandAsset.decimals}`); - // return amount.toString(); - // } - // - // public async getNativeBalance(account: Account): Promise { - // const accountInfo = await this._algod.accountInformation(account.addr).do(); - // const algoAsset = this._assetMap[this.nativeTokenSymbol]; - // return ( - // accountInfo.amount * parseFloat(`1e-${algoAsset.decimals}`) - // ).toString(); - // } - // - // public getAssetForSymbol(symbol: string): AlgorandAsset | null { - // return this._assetMap[symbol] ? this._assetMap[symbol] : null; - // } - // - // public async optIn(address: string, symbol: string) { - // const account = await this.getAccountFromAddress(address); - // const assetIndex = this._assetMap[symbol].assetId; - // const suggestedParams = await this._algod.getTransactionParams().do(); - // const optInTxn = makeAssetTransferTxnWithSuggestedParamsFromObject({ - // from: account.addr, - // to: address, - // suggestedParams, - // assetIndex, - // amount: 0, - // }); - // const signedOptInTxn = optInTxn.signTxn(account.sk); - // const resp = await this._algod.sendRawTransaction(signedOptInTxn).do(); - // return resp; - // } - // + async getAddressUnSpentBoxes(address: string) { + let utxos: BoxType[] = [] + let offset = 0; + let nodeBoxes: BoxType[] = await this._node.getUnSpentBoxesByAddress(address, offset, this.utxosLimit) + while (nodeBoxes.length > 0) { + utxos = [...utxos, ...nodeBoxes] + offset += this.utxosLimit + nodeBoxes = await this._node.getUnSpentBoxesByAddress(address, offset, this.utxosLimit) + } + return utxos + } + public getAccountFromSecretKey(secret: string): Account { + const secretKey = SecretKey.dlog_from_bytes(Buffer.from(secret, 'hex')) + const address = secretKey.get_address().to_base58(this._networkPrefix) + const sks = new SecretKeys(); + sks.add(secretKey); + const wallet = Wallet.from_secrets(sks); + return { + address, + wallet + } + } + + public encrypt(secret: string, password: string): string { + const iv = randomBytes(16); + const key = Buffer.alloc(32); + key.write(password); + + const cipher = createCipheriv('aes-256-cbc', key, iv); + + const encrypted = Buffer.concat([cipher.update(secret), cipher.final()]); + + return `${iv.toString('hex')}:${encrypted.toString('hex')}`; + } + + public decrypt(encryptedSecret: string, password: string): string { + const [iv, encryptedKey] = encryptedSecret.split(':'); + const key = Buffer.alloc(32); + key.write(password); + + const decipher = createDecipheriv( + 'aes-256-cbc', + key, + Buffer.from(iv, 'hex') + ); + + const decrpyted = Buffer.concat([ + decipher.update(Buffer.from(encryptedKey, 'hex')), + decipher.final(), + ]); + + return decrpyted.toString(); + } + + public async getAssetBalance( + account: Account, + assetName: string + ): Promise { + const ergoAsset = this._assetMap[assetName]; + let balance = 0 + try { + const utxos = await this.getAddressUnSpentBoxes(account.address) + balance = utxos.reduce((total: number, box) => total + box.assets.filter((asset) => asset.tokenId === ergoAsset.tokenId).reduce((total_asset, asset) => total_asset + Number(asset.amount), 0), 0) + } catch (error: any) { + throw new Error(`problem during finding account assets ${this._chain} Node!`); + } + const amount = balance; + return amount.toString(); + } + private async loadAssets(): Promise { const assetData = await this.getAssetData(); for (const result of assetData.tokens) { diff --git a/src/chains/ergo/node.service.ts b/src/chains/ergo/node.service.ts index 454deb0745..974dd2be58 100644 --- a/src/chains/ergo/node.service.ts +++ b/src/chains/ergo/node.service.ts @@ -42,4 +42,8 @@ export class NodeService { return info.fullHeight } + async getUnSpentBoxesByAddress(address: string, offset: number, limit: number, sortDirection = 'desc'): Promise { + return this.post(`/blockchain/box/unspent/byAddress?offset=${offset}&limit=${limit}&sortDirection=${sortDirection}`, {'Content-Type': 'text/plain'}, `${address}`).then(res => res.data) + } + } From e68d8139e683d16e18bbf9f4978a2e56bfdf2b81 Mon Sep 17 00:00:00 2001 From: ahmadyazdanii Date: Tue, 4 Jun 2024 18:11:24 +0330 Subject: [PATCH 003/132] update [ergo]: format the codes --- src/chains/ergo/dex.service.ts | 45 ++++++------ src/chains/ergo/ergo.config.ts | 20 +++--- src/chains/ergo/ergo.controller.ts | 5 +- src/chains/ergo/ergo.interface.ts | 13 ++-- src/chains/ergo/ergo.ts | 111 ++++++++++++++++------------- src/chains/ergo/node.service.ts | 57 +++++++++------ 6 files changed, 137 insertions(+), 114 deletions(-) diff --git a/src/chains/ergo/dex.service.ts b/src/chains/ergo/dex.service.ts index b62b5c257e..05258cae67 100644 --- a/src/chains/ergo/dex.service.ts +++ b/src/chains/ergo/dex.service.ts @@ -1,45 +1,48 @@ -import axios, { AxiosInstance } from 'axios' -import { BlockHeaders, ErgoStateContext, PreHeader } from 'ergo-lib-wasm-nodejs' +import axios, { AxiosInstance } from 'axios'; export class DexService { - private backend: AxiosInstance + private backend: AxiosInstance; constructor(dexURL: string, timeOut: number) { this.backend = axios.create({ baseURL: dexURL, timeout: timeOut, headers: { 'Content-Type': 'application/json' }, - }) + }); } async get(url: string, headers?: any, params?: any) { - return this.backend.get(url, { - timeout: 25000, - headers: { - 'Content-Type': 'application/json', - ...headers - }, - params - }).then((res: any) => res.data) + return this.backend + .get(url, { + timeout: 25000, + headers: { + 'Content-Type': 'application/json', + ...headers, + }, + params, + }) + .then((res: any) => res.data); } async head(url: string) { - return this.backend.head(url, { - timeout: 1000 - }).then((res: any) => res.status).catch((e: any) => e.response.status) + return this.backend + .head(url, { + timeout: 1000, + }) + .then((res: any) => res.status) + .catch((e: any) => e.response.status); } async post(url: string, headers?: any, params?: any) { this.backend.defaults.headers = { 'Content-Type': 'application/json', - ...headers - } - this.backend.defaults.timeout = 25000 - return this.backend.post(url, params).then((res: any) => res) + ...headers, + }; + this.backend.defaults.timeout = 25000; + return this.backend.post(url, params).then((res: any) => res); } async getTokens() { - return this.get('/ergo-token-list.json') + return this.get('/ergo-token-list.json'); } - } diff --git a/src/chains/ergo/ergo.config.ts b/src/chains/ergo/ergo.config.ts index 46553a11a7..5ab78c2f72 100644 --- a/src/chains/ergo/ergo.config.ts +++ b/src/chains/ergo/ergo.config.ts @@ -1,6 +1,5 @@ -import {ConfigManagerV2} from "../../services/config-manager-v2"; -import {NetworkPrefix} from "ergo-lib-wasm-nodejs"; - +import { ConfigManagerV2 } from '../../services/config-manager-v2'; +import { NetworkPrefix } from 'ergo-lib-wasm-nodejs'; export interface NetworkConfig { name: string; @@ -9,7 +8,7 @@ export interface NetworkConfig { networkPrefix: NetworkPrefix; minTxFee: number; maxLRUCacheInstances: number; - utxosLimit: number + utxosLimit: number; } export interface Config { network: NetworkConfig; @@ -19,17 +18,18 @@ export function getErgoConfig(network: string): Config { network: { name: network, nodeURL: ConfigManagerV2.getInstance().get( - 'algorand.networks.' + network + '.nodeURL' + 'algorand.networks.' + network + '.nodeURL', ), timeOut: ConfigManagerV2.getInstance().get( - 'ergo.networks.' + network + '.timeOut' + 'ergo.networks.' + network + '.timeOut', ), - networkPrefix: network === "Mainnet" ? NetworkPrefix.Mainnet : NetworkPrefix.Testnet, + networkPrefix: + network === 'Mainnet' ? NetworkPrefix.Mainnet : NetworkPrefix.Testnet, minTxFee: ConfigManagerV2.getInstance().get( - 'algorand.networks.' + network + '.minTxFee' + 'algorand.networks.' + network + '.minTxFee', ), maxLRUCacheInstances: 10, - utxosLimit: 100 + utxosLimit: 100, }, }; -} \ No newline at end of file +} diff --git a/src/chains/ergo/ergo.controller.ts b/src/chains/ergo/ergo.controller.ts index 8ee53f549d..5f538edefb 100644 --- a/src/chains/ergo/ergo.controller.ts +++ b/src/chains/ergo/ergo.controller.ts @@ -1,4 +1 @@ - -export class ErgoController{ - -} \ No newline at end of file +export class ErgoController {} diff --git a/src/chains/ergo/ergo.interface.ts b/src/chains/ergo/ergo.interface.ts index 3a9ac681ee..7eac90c203 100644 --- a/src/chains/ergo/ergo.interface.ts +++ b/src/chains/ergo/ergo.interface.ts @@ -1,10 +1,11 @@ -import {Wallet} from "ergo-lib-wasm-nodejs"; -import {ErgoTreeHex, NonMandatoryRegisters} from "@fleet-sdk/common"; +import { Wallet } from 'ergo-lib-wasm-nodejs'; +import { ErgoTreeHex, NonMandatoryRegisters } from '@fleet-sdk/common'; + export interface ErgoAsset { tokenId: number; decimals: number; name: string; - symbol: string + symbol: string; } export interface Account { @@ -12,8 +13,6 @@ export interface Account { address: string; } - - export type BoxType = { boxId: string; ergoTree: ErgoTreeHex; @@ -21,5 +20,5 @@ export type BoxType = { value: number; assets: any[]; additionalRegisters: NonMandatoryRegisters; - index?: number -}; \ No newline at end of file + index?: number; +}; diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index b6e360a6eb..dc272ccfd4 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -1,12 +1,16 @@ -import {NetworkPrefix, SecretKey, SecretKeys, Wallet} from "ergo-lib-wasm-nodejs" +import { + NetworkPrefix, + SecretKey, + SecretKeys, + Wallet, +} from 'ergo-lib-wasm-nodejs'; import LRUCache from 'lru-cache'; -import {ErgoController} from "./ergo.controller"; -import {NodeService} from "./node.service"; -import {getErgoConfig} from "./ergo.config"; -import {DexService} from "./dex.service"; -import {Account, BoxType, ErgoAsset} from "./ergo.interface"; -import {createCipheriv, createDecipheriv, randomBytes} from 'crypto'; - +import { ErgoController } from './ergo.controller'; +import { NodeService } from './node.service'; +import { getErgoConfig } from './ergo.config'; +import { DexService } from './dex.service'; +import { Account, BoxType, ErgoAsset } from './ergo.interface'; +import { createCipheriv, createDecipheriv, randomBytes } from 'crypto'; export class Ergo { private _assetMap: Record = {}; @@ -21,21 +25,16 @@ export class Ergo { public controller: typeof ErgoController; private utxosLimit: number; - constructor( - network: string, - nodeUrl: string - ) { - this._network = network + constructor(network: string, nodeUrl: string) { + this._network = network; const config = getErgoConfig(network); - if (network === "Mainnet") - this._networkPrefix = NetworkPrefix.Mainnet - else - this._networkPrefix = NetworkPrefix.Testnet - this._node = new NodeService(nodeUrl, config.network.timeOut) - this._dex = new DexService(nodeUrl, config.network.timeOut) + if (network === 'Mainnet') this._networkPrefix = NetworkPrefix.Mainnet; + else this._networkPrefix = NetworkPrefix.Testnet; + this._node = new NodeService(nodeUrl, config.network.timeOut); + this._dex = new DexService(nodeUrl, config.network.timeOut); this.controller = ErgoController; this.txFee = config.network.minTxFee; - this.utxosLimit = config.network.utxosLimit + this.utxosLimit = config.network.utxosLimit; } public get node(): NodeService { @@ -75,16 +74,10 @@ export class Ergo { if (!Ergo._instances.has(config.network.name)) { if (network !== null) { const nodeUrl = config.network.nodeURL; - Ergo._instances.set( - config.network.name, - new Ergo( - network, - nodeUrl - ) - ); + Ergo._instances.set(config.network.name, new Ergo(network, nodeUrl)); } else { throw new Error( - `Ergo.getInstance received an unexpected network: ${network}.` + `Ergo.getInstance received an unexpected network: ${network}.`, ); } } @@ -98,9 +91,7 @@ export class Ergo { const keys = Array.from(this._instances.keys()); for (const instance of keys) { if (instance !== undefined) { - connectedInstances[instance] = this._instances.get( - instance - ) as Ergo; + connectedInstances[instance] = this._instances.get(instance) as Ergo; } } } @@ -108,31 +99,39 @@ export class Ergo { } async getCurrentBlockNumber(): Promise { - const status = await this._node.getNetworkHeight() + const status = await this._node.getNetworkHeight(); return status + 1; } async getAddressUnSpentBoxes(address: string) { - let utxos: BoxType[] = [] + let utxos: BoxType[] = []; let offset = 0; - let nodeBoxes: BoxType[] = await this._node.getUnSpentBoxesByAddress(address, offset, this.utxosLimit) + let nodeBoxes: BoxType[] = await this._node.getUnSpentBoxesByAddress( + address, + offset, + this.utxosLimit, + ); while (nodeBoxes.length > 0) { - utxos = [...utxos, ...nodeBoxes] - offset += this.utxosLimit - nodeBoxes = await this._node.getUnSpentBoxesByAddress(address, offset, this.utxosLimit) + utxos = [...utxos, ...nodeBoxes]; + offset += this.utxosLimit; + nodeBoxes = await this._node.getUnSpentBoxesByAddress( + address, + offset, + this.utxosLimit, + ); } - return utxos + return utxos; } public getAccountFromSecretKey(secret: string): Account { - const secretKey = SecretKey.dlog_from_bytes(Buffer.from(secret, 'hex')) - const address = secretKey.get_address().to_base58(this._networkPrefix) + const secretKey = SecretKey.dlog_from_bytes(Buffer.from(secret, 'hex')); + const address = secretKey.get_address().to_base58(this._networkPrefix); const sks = new SecretKeys(); sks.add(secretKey); const wallet = Wallet.from_secrets(sks); return { address, - wallet - } + wallet, + }; } public encrypt(secret: string, password: string): string { @@ -155,7 +154,7 @@ export class Ergo { const decipher = createDecipheriv( 'aes-256-cbc', key, - Buffer.from(iv, 'hex') + Buffer.from(iv, 'hex'), ); const decrpyted = Buffer.concat([ @@ -168,15 +167,27 @@ export class Ergo { public async getAssetBalance( account: Account, - assetName: string + assetName: string, ): Promise { const ergoAsset = this._assetMap[assetName]; - let balance = 0 + let balance = 0; try { - const utxos = await this.getAddressUnSpentBoxes(account.address) - balance = utxos.reduce((total: number, box) => total + box.assets.filter((asset) => asset.tokenId === ergoAsset.tokenId).reduce((total_asset, asset) => total_asset + Number(asset.amount), 0), 0) + const utxos = await this.getAddressUnSpentBoxes(account.address); + balance = utxos.reduce( + (total: number, box) => + total + + box.assets + .filter((asset) => asset.tokenId === ergoAsset.tokenId) + .reduce( + (total_asset, asset) => total_asset + Number(asset.amount), + 0, + ), + 0, + ); } catch (error: any) { - throw new Error(`problem during finding account assets ${this._chain} Node!`); + throw new Error( + `problem during finding account assets ${this._chain} Node!`, + ); } const amount = balance; return amount.toString(); @@ -189,7 +200,7 @@ export class Ergo { tokenId: result.address, decimals: result.decimals, name: result.name, - symbol: result.ticker + symbol: result.ticker, }; } } @@ -201,4 +212,4 @@ export class Ergo { public get storedTokenList() { return this._assetMap; } -} \ No newline at end of file +} diff --git a/src/chains/ergo/node.service.ts b/src/chains/ergo/node.service.ts index 974dd2be58..8a51e78c33 100644 --- a/src/chains/ergo/node.service.ts +++ b/src/chains/ergo/node.service.ts @@ -1,49 +1,62 @@ -import axios, { AxiosInstance } from 'axios' +import axios, { AxiosInstance } from 'axios'; export class NodeService { - private backend: AxiosInstance + private backend: AxiosInstance; constructor(nodeURL: string, timeOut: number) { this.backend = axios.create({ baseURL: nodeURL, timeout: timeOut, headers: { 'Content-Type': 'application/json' }, - }) + }); } async get(url: string, headers?: any, params?: any) { - return this.backend.get(url, { - timeout: 25000, - headers: { - 'Content-Type': 'application/json', - ...headers - }, - params - }).then((res: any) => res.data) + return this.backend + .get(url, { + timeout: 25000, + headers: { + 'Content-Type': 'application/json', + ...headers, + }, + params, + }) + .then((res: any) => res.data); } async head(url: string) { - return this.backend.head(url, { - timeout: 1000 - }).then((res: any) => res.status).catch((e: any) => e.response.status) + return this.backend + .head(url, { + timeout: 1000, + }) + .then((res: any) => res.status) + .catch((e: any) => e.response.status); } async post(url: string, headers?: any, params?: any) { this.backend.defaults.headers = { 'Content-Type': 'application/json', - ...headers - } - this.backend.defaults.timeout = 25000 - return this.backend.post(url, params).then((res: any) => res) + ...headers, + }; + this.backend.defaults.timeout = 25000; + return this.backend.post(url, params).then((res: any) => res); } async getNetworkHeight(): Promise { const info = await this.get(`/info`); - return info.fullHeight + return info.fullHeight; } - async getUnSpentBoxesByAddress(address: string, offset: number, limit: number, sortDirection = 'desc'): Promise { - return this.post(`/blockchain/box/unspent/byAddress?offset=${offset}&limit=${limit}&sortDirection=${sortDirection}`, {'Content-Type': 'text/plain'}, `${address}`).then(res => res.data) + async getUnSpentBoxesByAddress( + address: string, + offset: number, + limit: number, + sortDirection = 'desc', + ): Promise { + return this.post( + `/blockchain/box/unspent/byAddress?offset=${offset}&limit=${limit}&sortDirection=${sortDirection}`, + { 'Content-Type': 'text/plain' }, + `${address}`, + ).then((res) => res.data); } - } From 3eee1caed975c98fa1c8f489afc112596fe26d4e Mon Sep 17 00:00:00 2001 From: ahmadyazdanii Date: Tue, 4 Jun 2024 19:32:08 +0330 Subject: [PATCH 004/132] update [ergo]: refactor dex service --- src/chains/ergo/dex.service.ts | 58 ++++++++++++---------------------- 1 file changed, 20 insertions(+), 38 deletions(-) diff --git a/src/chains/ergo/dex.service.ts b/src/chains/ergo/dex.service.ts index 05258cae67..96b3189f28 100644 --- a/src/chains/ergo/dex.service.ts +++ b/src/chains/ergo/dex.service.ts @@ -1,48 +1,30 @@ -import axios, { AxiosInstance } from 'axios'; +import axios, { AxiosHeaders } from 'axios'; export class DexService { - private backend: AxiosInstance; + constructor( + private dexURL: string, + private timeout: number = 5000, + ) {} - constructor(dexURL: string, timeOut: number) { - this.backend = axios.create({ - baseURL: dexURL, - timeout: timeOut, - headers: { 'Content-Type': 'application/json' }, + private async request( + method: 'POST' | 'GET' | 'HEAD' = 'GET', + url: string, + headers?: AxiosHeaders, + body?: Record, + ) { + const response = await axios({ + baseURL: this.dexURL, + url, + method, + headers: headers, + timeout: this.timeout, + ...(method === 'POST' ? { body: body } : null), }); - } - - async get(url: string, headers?: any, params?: any) { - return this.backend - .get(url, { - timeout: 25000, - headers: { - 'Content-Type': 'application/json', - ...headers, - }, - params, - }) - .then((res: any) => res.data); - } - - async head(url: string) { - return this.backend - .head(url, { - timeout: 1000, - }) - .then((res: any) => res.status) - .catch((e: any) => e.response.status); - } - async post(url: string, headers?: any, params?: any) { - this.backend.defaults.headers = { - 'Content-Type': 'application/json', - ...headers, - }; - this.backend.defaults.timeout = 25000; - return this.backend.post(url, params).then((res: any) => res); + return response.data; } async getTokens() { - return this.get('/ergo-token-list.json'); + return this.request('GET', '/ergo-token-list.json'); } } From 3a4ec61d9ae47a9152cb1e0a0d6ae0c33dfab1a5 Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Tue, 4 Jun 2024 19:40:53 +0330 Subject: [PATCH 005/132] getting ammpool for ergo chain --- package.json | 1 + src/chains/ergo/dex.service.ts | 1 - src/chains/ergo/ergo.config.ts | 16 +++++++++-- src/chains/ergo/ergo.interface.ts | 33 +++++++++++++++++++++ src/chains/ergo/ergo.ts | 48 ++++++++++++++++++++++--------- 5 files changed, 82 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index f1024672e0..4043de3be6 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "@cosmjs/stargate": "^0.31.1", "@cosmjs/tendermint-rpc": "^0.32.2", "@crocswap/sdk": "^2.4.5", + "@ergolabs/ergo-dex-sdk": "^1.9.67-beta.4", "@ethersproject/abstract-provider": "5.7.0", "@ethersproject/address": "5.7.0", "@ethersproject/contracts": "5.7.0", diff --git a/src/chains/ergo/dex.service.ts b/src/chains/ergo/dex.service.ts index b62b5c257e..233fae0f0c 100644 --- a/src/chains/ergo/dex.service.ts +++ b/src/chains/ergo/dex.service.ts @@ -1,5 +1,4 @@ import axios, { AxiosInstance } from 'axios' -import { BlockHeaders, ErgoStateContext, PreHeader } from 'ergo-lib-wasm-nodejs' export class DexService { private backend: AxiosInstance diff --git a/src/chains/ergo/ergo.config.ts b/src/chains/ergo/ergo.config.ts index 46553a11a7..0b7ca187e6 100644 --- a/src/chains/ergo/ergo.config.ts +++ b/src/chains/ergo/ergo.config.ts @@ -5,6 +5,9 @@ import {NetworkPrefix} from "ergo-lib-wasm-nodejs"; export interface NetworkConfig { name: string; nodeURL: string; + explorerURL: string; + explorerDEXURL: string; + poolLimit: number; timeOut: number; networkPrefix: NetworkPrefix; minTxFee: number; @@ -19,17 +22,24 @@ export function getErgoConfig(network: string): Config { network: { name: network, nodeURL: ConfigManagerV2.getInstance().get( - 'algorand.networks.' + network + '.nodeURL' + 'ergo.networks.' + network + '.nodeURL' + ), + explorerURL: ConfigManagerV2.getInstance().get( + 'ergo.networks.' + network + '.explorerURL' + ), + explorerDEXURL: ConfigManagerV2.getInstance().get( + 'ergo.networks.' + network + '.explorerDEXURL' ), timeOut: ConfigManagerV2.getInstance().get( 'ergo.networks.' + network + '.timeOut' ), networkPrefix: network === "Mainnet" ? NetworkPrefix.Mainnet : NetworkPrefix.Testnet, minTxFee: ConfigManagerV2.getInstance().get( - 'algorand.networks.' + network + '.minTxFee' + 'ergo.networks.' + network + '.minTxFee' ), maxLRUCacheInstances: 10, - utxosLimit: 100 + utxosLimit: 100, + poolLimit: 100 }, }; } \ No newline at end of file diff --git a/src/chains/ergo/ergo.interface.ts b/src/chains/ergo/ergo.interface.ts index 3a9ac681ee..d81ada64b2 100644 --- a/src/chains/ergo/ergo.interface.ts +++ b/src/chains/ergo/ergo.interface.ts @@ -1,11 +1,44 @@ import {Wallet} from "ergo-lib-wasm-nodejs"; import {ErgoTreeHex, NonMandatoryRegisters} from "@fleet-sdk/common"; +import {AmmPool} from "@ergolabs/ergo-dex-sdk"; export interface ErgoAsset { tokenId: number; decimals: number; name: string; symbol: string } +export class Pool extends AmmPool{ + private name:string + constructor(public pool: AmmPool) { + super(pool.id,pool.lp, pool.x, pool.y, pool.poolFeeNum); + this.name = `${this.x.asset.name}/${this.y.asset.name}` + } + + // @ts-ignore + private getName() { + return this.name + } + + + // calculatePriceImpact(input: any): number { + // const ratio = + // input.asset.id === this.x.asset.id + // ? math.evaluate!( + // `${renderFractions(this.y.amount.valueOf(), this.y.asset.decimals)} / ${renderFractions(this.x.amount.valueOf(), this.x.asset.decimals)}`, + // ).toString() + // : math.evaluate!( + // `${renderFractions(this.x.amount.valueOf(), this.x.asset.decimals)} / ${renderFractions(this.y.amount.valueOf(), this.y.asset.decimals)}`, + // ).toString(); + // const outputAmount = calculatePureOutputAmount(input, this); + // const outputRatio = math.evaluate!( + // `${outputAmount} / ${renderFractions(input.amount, input.asset.decimals)}`, + // ).toString(); + // + // return Math.abs( + // math.evaluate!(`(${outputRatio} * 100 / ${ratio}) - 100`).toFixed(2), + // ); + // } +} export interface Account { wallet: Wallet; diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index b6e360a6eb..035f9b8441 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -4,9 +4,14 @@ import {ErgoController} from "./ergo.controller"; import {NodeService} from "./node.service"; import {getErgoConfig} from "./ergo.config"; import {DexService} from "./dex.service"; -import {Account, BoxType, ErgoAsset} from "./ergo.interface"; +import {Account, BoxType, ErgoAsset, Pool} from "./ergo.interface"; import {createCipheriv, createDecipheriv, randomBytes} from 'crypto'; - +import { + makeNativePools +} from '@ergolabs/ergo-dex-sdk'; +import { + Explorer, +} from '@ergolabs/ergo-sdk'; export class Ergo { private _assetMap: Record = {}; @@ -15,27 +20,31 @@ export class Ergo { private _network: string; private _networkPrefix: NetworkPrefix; private _node: NodeService; + private _explorer: Explorer; private _dex: DexService; private _ready: boolean = false; public txFee: number; public controller: typeof ErgoController; private utxosLimit: number; + private poolLimit: number; + private ammPools: Array = []; constructor( network: string, - nodeUrl: string ) { this._network = network const config = getErgoConfig(network); if (network === "Mainnet") - this._networkPrefix = NetworkPrefix.Mainnet + this._networkPrefix = NetworkPrefix.Mainnet; else - this._networkPrefix = NetworkPrefix.Testnet - this._node = new NodeService(nodeUrl, config.network.timeOut) - this._dex = new DexService(nodeUrl, config.network.timeOut) + this._networkPrefix = NetworkPrefix.Testnet; + this._node = new NodeService(config.network.nodeURL, config.network.timeOut); + this._explorer = new Explorer(config.network.explorerURL); + this._dex = new DexService(config.network.explorerDEXURL, config.network.timeOut); this.controller = ErgoController; this.txFee = config.network.minTxFee; - this.utxosLimit = config.network.utxosLimit + this.utxosLimit = config.network.utxosLimit; + this.poolLimit = config.network.poolLimit; } public get node(): NodeService { @@ -56,6 +65,7 @@ export class Ergo { public async init(): Promise { await this.loadAssets(); + await this.loadPools(); this._ready = true; return; } @@ -74,13 +84,9 @@ export class Ergo { if (!Ergo._instances.has(config.network.name)) { if (network !== null) { - const nodeUrl = config.network.nodeURL; Ergo._instances.set( config.network.name, - new Ergo( - network, - nodeUrl - ) + new Ergo(network) ); } else { throw new Error( @@ -198,6 +204,22 @@ export class Ergo { return await this._dex.getTokens(); } + private async loadPools(): Promise { + let offset = 0; + let pools: Pool[] = await this.getPoolData(this.poolLimit, offset) + while (pools.length > 0) { + for(const pool of pools){ + if (!this.ammPools.filter((ammPool)=>ammPool.id===pool.id).length) + this.ammPools.push(pool) + } + offset += this.utxosLimit + pools = await this.getPoolData(this.poolLimit, offset) + } + } + private async getPoolData(limit: number, offset: number): Promise { + return await makeNativePools(this._explorer).getAll({limit, offset}) + } + public get storedTokenList() { return this._assetMap; } From 9ff33c136d361cc05f1ff3dc29c6fab476272ef2 Mon Sep 17 00:00:00 2001 From: ahmadyazdanii Date: Tue, 4 Jun 2024 21:12:54 +0330 Subject: [PATCH 006/132] refactor [ergo]: refactor all functions & types & interfaces --- src/chains/ergo/dex.service.ts | 9 +- src/chains/ergo/ergo.config.ts | 15 +--- src/chains/ergo/ergo.ts | 85 ++++++++++++------- src/chains/ergo/interfaces/dex.interface.ts | 13 +++ src/chains/ergo/interfaces/ergo.interface.ts | 55 ++++++++++++ src/chains/ergo/interfaces/node.interface.ts | 3 + src/chains/ergo/node.service.ts | 72 +++++++--------- .../{ergo.interface.ts => types/ergo.type.ts} | 15 +--- src/chains/ergo/types/node.type.ts | 3 + 9 files changed, 166 insertions(+), 104 deletions(-) create mode 100644 src/chains/ergo/interfaces/dex.interface.ts create mode 100644 src/chains/ergo/interfaces/ergo.interface.ts create mode 100644 src/chains/ergo/interfaces/node.interface.ts rename src/chains/ergo/{ergo.interface.ts => types/ergo.type.ts} (51%) create mode 100644 src/chains/ergo/types/node.type.ts diff --git a/src/chains/ergo/dex.service.ts b/src/chains/ergo/dex.service.ts index 96b3189f28..d21a7b3fa6 100644 --- a/src/chains/ergo/dex.service.ts +++ b/src/chains/ergo/dex.service.ts @@ -1,4 +1,5 @@ -import axios, { AxiosHeaders } from 'axios'; +import axios from 'axios'; +import { DEXTokensResponse } from './interfaces/dex.interface'; export class DexService { constructor( @@ -6,10 +7,10 @@ export class DexService { private timeout: number = 5000, ) {} - private async request( + private async request( method: 'POST' | 'GET' | 'HEAD' = 'GET', url: string, - headers?: AxiosHeaders, + headers?: Record, body?: Record, ) { const response = await axios({ @@ -25,6 +26,6 @@ export class DexService { } async getTokens() { - return this.request('GET', '/ergo-token-list.json'); + return this.request('GET', '/ergo-token-list.json'); } } diff --git a/src/chains/ergo/ergo.config.ts b/src/chains/ergo/ergo.config.ts index 5ab78c2f72..0ba09b8c5b 100644 --- a/src/chains/ergo/ergo.config.ts +++ b/src/chains/ergo/ergo.config.ts @@ -1,19 +1,8 @@ import { ConfigManagerV2 } from '../../services/config-manager-v2'; import { NetworkPrefix } from 'ergo-lib-wasm-nodejs'; +import { ErgoConfig } from './interfaces/ergo.interface'; -export interface NetworkConfig { - name: string; - nodeURL: string; - timeOut: number; - networkPrefix: NetworkPrefix; - minTxFee: number; - maxLRUCacheInstances: number; - utxosLimit: number; -} -export interface Config { - network: NetworkConfig; -} -export function getErgoConfig(network: string): Config { +export function getErgoConfig(network: string): ErgoConfig { return { network: { name: network, diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index dc272ccfd4..4b8de2cfa9 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -9,8 +9,14 @@ import { ErgoController } from './ergo.controller'; import { NodeService } from './node.service'; import { getErgoConfig } from './ergo.config'; import { DexService } from './dex.service'; -import { Account, BoxType, ErgoAsset } from './ergo.interface'; import { createCipheriv, createDecipheriv, randomBytes } from 'crypto'; +import { + ErgoAccount, + ErgoAsset, + ErgoBox, + ErgoConnectedInstance, +} from './interfaces/ergo.interface'; +import { toNumber } from 'lodash'; export class Ergo { private _assetMap: Record = {}; @@ -22,14 +28,19 @@ export class Ergo { private _dex: DexService; private _ready: boolean = false; public txFee: number; - public controller: typeof ErgoController; + public controller: ErgoController; private utxosLimit: number; constructor(network: string, nodeUrl: string) { - this._network = network; const config = getErgoConfig(network); - if (network === 'Mainnet') this._networkPrefix = NetworkPrefix.Mainnet; - else this._networkPrefix = NetworkPrefix.Testnet; + + if (network === 'Mainnet') { + this._networkPrefix = NetworkPrefix.Mainnet; + } else { + this._networkPrefix = NetworkPrefix.Testnet; + } + + this._network = network; this._node = new NodeService(nodeUrl, config.network.timeOut); this._dex = new DexService(nodeUrl, config.network.timeOut); this.controller = ErgoController; @@ -45,7 +56,7 @@ export class Ergo { return this._network; } - public get storedAssetList(): ErgoAsset[] { + public get storedAssetList(): Array { return Object.values(this._assetMap); } @@ -65,15 +76,17 @@ export class Ergo { public static getInstance(network: string): Ergo { const config = getErgoConfig(network); - if (Ergo._instances === undefined) { + + if (!Ergo._instances) { Ergo._instances = new LRUCache({ max: config.network.maxLRUCacheInstances, }); } if (!Ergo._instances.has(config.network.name)) { - if (network !== null) { + if (network) { const nodeUrl = config.network.nodeURL; + Ergo._instances.set(config.network.name, new Ergo(network, nodeUrl)); } else { throw new Error( @@ -85,16 +98,19 @@ export class Ergo { return Ergo._instances.get(config.network.name) as Ergo; } - public static getConnectedInstances(): { [name: string]: Ergo } { - const connectedInstances: { [name: string]: Ergo } = {}; - if (this._instances !== undefined) { + public static getConnectedInstances(): ErgoConnectedInstance { + const connectedInstances: ErgoConnectedInstance = {}; + + if (this._instances) { const keys = Array.from(this._instances.keys()); + for (const instance of keys) { - if (instance !== undefined) { + if (instance) { connectedInstances[instance] = this._instances.get(instance) as Ergo; } } } + return connectedInstances; } @@ -103,31 +119,37 @@ export class Ergo { return status + 1; } - async getAddressUnSpentBoxes(address: string) { - let utxos: BoxType[] = []; + async getAddressUnspentBoxes(address: string) { + let utxos: Array = []; let offset = 0; - let nodeBoxes: BoxType[] = await this._node.getUnSpentBoxesByAddress( + let nodeBoxes = await this._node.getUnspentBoxesByAddress( address, offset, this.utxosLimit, ); + while (nodeBoxes.length > 0) { utxos = [...utxos, ...nodeBoxes]; offset += this.utxosLimit; - nodeBoxes = await this._node.getUnSpentBoxesByAddress( + nodeBoxes = await this._node.getUnspentBoxesByAddress( address, offset, this.utxosLimit, ); } + return utxos; } - public getAccountFromSecretKey(secret: string): Account { + + public getAccountFromSecretKey(secret: string): ErgoAccount { + const sks = new SecretKeys(); const secretKey = SecretKey.dlog_from_bytes(Buffer.from(secret, 'hex')); const address = secretKey.get_address().to_base58(this._networkPrefix); - const sks = new SecretKeys(); + sks.add(secretKey); + const wallet = Wallet.from_secrets(sks); + return { address, wallet, @@ -137,10 +159,10 @@ export class Ergo { public encrypt(secret: string, password: string): string { const iv = randomBytes(16); const key = Buffer.alloc(32); + key.write(password); const cipher = createCipheriv('aes-256-cbc', key, iv); - const encrypted = Buffer.concat([cipher.update(secret), cipher.final()]); return `${iv.toString('hex')}:${encrypted.toString('hex')}`; @@ -149,6 +171,7 @@ export class Ergo { public decrypt(encryptedSecret: string, password: string): string { const [iv, encryptedKey] = encryptedSecret.split(':'); const key = Buffer.alloc(32); + key.write(password); const decipher = createDecipheriv( @@ -156,28 +179,29 @@ export class Ergo { key, Buffer.from(iv, 'hex'), ); - - const decrpyted = Buffer.concat([ + const decrypted = Buffer.concat([ decipher.update(Buffer.from(encryptedKey, 'hex')), decipher.final(), ]); - return decrpyted.toString(); + return decrypted.toString(); } public async getAssetBalance( - account: Account, + account: ErgoAccount, assetName: string, ): Promise { const ergoAsset = this._assetMap[assetName]; let balance = 0; + try { - const utxos = await this.getAddressUnSpentBoxes(account.address); + const utxos = await this.getAddressUnspentBoxes(account.address); + balance = utxos.reduce( (total: number, box) => total + box.assets - .filter((asset) => asset.tokenId === ergoAsset.tokenId) + .filter((asset) => asset.tokenId === ergoAsset.tokenId.toString()) .reduce( (total_asset, asset) => total_asset + Number(asset.amount), 0, @@ -189,15 +213,16 @@ export class Ergo { `problem during finding account assets ${this._chain} Node!`, ); } - const amount = balance; - return amount.toString(); + + return balance.toString(); } - private async loadAssets(): Promise { + private async loadAssets() { const assetData = await this.getAssetData(); + for (const result of assetData.tokens) { this._assetMap[result.name.toUpperCase()] = { - tokenId: result.address, + tokenId: toNumber(result.address), decimals: result.decimals, name: result.name, symbol: result.ticker, @@ -205,7 +230,7 @@ export class Ergo { } } - private async getAssetData(): Promise { + private async getAssetData() { return await this._dex.getTokens(); } diff --git a/src/chains/ergo/interfaces/dex.interface.ts b/src/chains/ergo/interfaces/dex.interface.ts new file mode 100644 index 0000000000..bcb98c0fc8 --- /dev/null +++ b/src/chains/ergo/interfaces/dex.interface.ts @@ -0,0 +1,13 @@ +export interface DEXToken { + address: string; + decimals: number; + name: string; + ticker: string; + logoURI: string; + project: string; + description: string; +} + +export interface DEXTokensResponse { + tokens: Array; +} diff --git a/src/chains/ergo/interfaces/ergo.interface.ts b/src/chains/ergo/interfaces/ergo.interface.ts new file mode 100644 index 0000000000..c701be022a --- /dev/null +++ b/src/chains/ergo/interfaces/ergo.interface.ts @@ -0,0 +1,55 @@ +import { NetworkPrefix } from 'ergo-lib-wasm-nodejs'; +import { Wallet } from 'ergo-lib-wasm-nodejs'; +import { Ergo } from '../ergo'; + +export interface ErgoNetworkConfig { + name: string; + nodeURL: string; + timeOut: number; + networkPrefix: NetworkPrefix; + minTxFee: number; + maxLRUCacheInstances: number; + utxosLimit: number; +} +export interface ErgoConfig { + network: ErgoNetworkConfig; +} + +export interface ErgoAsset { + tokenId: number; + decimals: number; + name: string; + symbol: string; +} + +export interface ErgoAccount { + wallet: Wallet; + address: string; +} + +export interface ErgoConnectedInstance { + [name: string]: Ergo; +} + +export interface ErgoBoxAsset { + tokenId: string; + amount: number; +} + +export interface ErgoBox { + boxId: string; + value: number; + ergoTree: string; + creationHeight: number; + assets: Array; + additionalRegisters: { + R4: string; + }; + transactionId: string; + index: number; + address: string; + spentTransactionId: string; + spendingHeight: number; + inclusionHeight: number; + globalIndex: number; +} diff --git a/src/chains/ergo/interfaces/node.interface.ts b/src/chains/ergo/interfaces/node.interface.ts new file mode 100644 index 0000000000..d121a27be1 --- /dev/null +++ b/src/chains/ergo/interfaces/node.interface.ts @@ -0,0 +1,3 @@ +export interface NodeInfoResponse { + fullHeight: number; +} diff --git a/src/chains/ergo/node.service.ts b/src/chains/ergo/node.service.ts index 8a51e78c33..f65f1020a8 100644 --- a/src/chains/ergo/node.service.ts +++ b/src/chains/ergo/node.service.ts @@ -1,62 +1,48 @@ -import axios, { AxiosInstance } from 'axios'; +import axios from 'axios'; +import { NodeInfoResponse } from './interfaces/node.interface'; +import { NodeErgoBoxResponse } from './types/node.type'; export class NodeService { - private backend: AxiosInstance; + constructor( + private nodeURL: string, + private timeout: number, + ) {} - constructor(nodeURL: string, timeOut: number) { - this.backend = axios.create({ - baseURL: nodeURL, - timeout: timeOut, - headers: { 'Content-Type': 'application/json' }, + private async request( + method: 'POST' | 'GET' | 'HEAD' = 'GET', + url: string, + headers?: Record, + body?: Record | string, + ) { + const response = await axios({ + baseURL: this.nodeURL, + url, + method, + headers: headers, + timeout: this.timeout, + ...(method === 'POST' ? { body: body } : null), }); - } - - async get(url: string, headers?: any, params?: any) { - return this.backend - .get(url, { - timeout: 25000, - headers: { - 'Content-Type': 'application/json', - ...headers, - }, - params, - }) - .then((res: any) => res.data); - } - async head(url: string) { - return this.backend - .head(url, { - timeout: 1000, - }) - .then((res: any) => res.status) - .catch((e: any) => e.response.status); - } - - async post(url: string, headers?: any, params?: any) { - this.backend.defaults.headers = { - 'Content-Type': 'application/json', - ...headers, - }; - this.backend.defaults.timeout = 25000; - return this.backend.post(url, params).then((res: any) => res); + return response.data; } async getNetworkHeight(): Promise { - const info = await this.get(`/info`); + const info = await this.request('GET', '/info'); + return info.fullHeight; } - async getUnSpentBoxesByAddress( + async getUnspentBoxesByAddress( address: string, offset: number, limit: number, sortDirection = 'desc', - ): Promise { - return this.post( + ) { + return this.request( + 'POST', `/blockchain/box/unspent/byAddress?offset=${offset}&limit=${limit}&sortDirection=${sortDirection}`, { 'Content-Type': 'text/plain' }, - `${address}`, - ).then((res) => res.data); + address, + ); } } diff --git a/src/chains/ergo/ergo.interface.ts b/src/chains/ergo/types/ergo.type.ts similarity index 51% rename from src/chains/ergo/ergo.interface.ts rename to src/chains/ergo/types/ergo.type.ts index 7eac90c203..fa808a6d7e 100644 --- a/src/chains/ergo/ergo.interface.ts +++ b/src/chains/ergo/types/ergo.type.ts @@ -1,24 +1,11 @@ -import { Wallet } from 'ergo-lib-wasm-nodejs'; import { ErgoTreeHex, NonMandatoryRegisters } from '@fleet-sdk/common'; -export interface ErgoAsset { - tokenId: number; - decimals: number; - name: string; - symbol: string; -} - -export interface Account { - wallet: Wallet; - address: string; -} - export type BoxType = { boxId: string; ergoTree: ErgoTreeHex; creationHeight: number; value: number; - assets: any[]; + assets: Array; additionalRegisters: NonMandatoryRegisters; index?: number; }; diff --git a/src/chains/ergo/types/node.type.ts b/src/chains/ergo/types/node.type.ts new file mode 100644 index 0000000000..83ae9320b3 --- /dev/null +++ b/src/chains/ergo/types/node.type.ts @@ -0,0 +1,3 @@ +import { ErgoBox } from '../interfaces/ergo.interface'; + +export type NodeErgoBoxResponse = Array; From 08bebf898b761e5ad345951617da36a42adca00c Mon Sep 17 00:00:00 2001 From: ahmadyazdanii Date: Tue, 4 Jun 2024 21:26:09 +0330 Subject: [PATCH 007/132] update [ergo]: refactor pool class --- src/chains/ergo/ergo.ts | 34 +++- yarn.lock | 434 +++++++++++++++++++++++----------------- 2 files changed, 284 insertions(+), 184 deletions(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index aa64f589f7..89344129ff 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -17,9 +17,41 @@ import { ErgoConnectedInstance, } from './interfaces/ergo.interface'; import { toNumber } from 'lodash'; -import { makeNativePools } from '@ergolabs/ergo-dex-sdk'; +import { AmmPool, makeNativePools } from '@ergolabs/ergo-dex-sdk'; import { Explorer } from '@ergolabs/ergo-sdk'; +class Pool extends AmmPool { + private name: string; + constructor(public pool: AmmPool) { + super(pool.id, pool.lp, pool.x, pool.y, pool.poolFeeNum); + + this.name = `${this.x.asset.name}/${this.y.asset.name}`; + } + + private getName() { + return this.name; + } + + // calculatePriceImpact(input: any): number { + // const ratio = + // input.asset.id === this.x.asset.id + // ? math.evaluate!( + // `${renderFractions(this.y.amount.valueOf(), this.y.asset.decimals)} / ${renderFractions(this.x.amount.valueOf(), this.x.asset.decimals)}`, + // ).toString() + // : math.evaluate!( + // `${renderFractions(this.x.amount.valueOf(), this.x.asset.decimals)} / ${renderFractions(this.y.amount.valueOf(), this.y.asset.decimals)}`, + // ).toString(); + // const outputAmount = calculatePureOutputAmount(input, this); + // const outputRatio = math.evaluate!( + // `${outputAmount} / ${renderFractions(input.amount, input.asset.decimals)}`, + // ).toString(); + // + // return Math.abs( + // math.evaluate!(`(${outputRatio} * 100 / ${ratio}) - 100`).toFixed(2), + // ); + // } +} + export class Ergo { private _assetMap: Record = {}; private static _instances: LRUCache; diff --git a/yarn.lock b/yarn.lock index be94faef31..4b3c645902 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1362,6 +1362,39 @@ enabled "2.0.x" kuler "^2.0.0" +"@ergolabs/ergo-dex-sdk@^1.9.67-beta.4": + version "1.9.67-beta.4" + resolved "https://registry.yarnpkg.com/@ergolabs/ergo-dex-sdk/-/ergo-dex-sdk-1.9.67-beta.4.tgz#e8721d17a9cdcbcd0fdbed7b777519184afcdfd9" + integrity sha512-uy77cWzMFtQSJg8ad1GAsIXcVG91bLD8wbDYLyyi+HxP8Oh5SIptsMhhg9ist+SQOFkSab7dr9PLl2zK/r3PUQ== + dependencies: + "@ergolabs/ergo-sdk" "^0.5.7" + axios "^0.21.1" + blakejs "^1.1.0" + bs58 "^4.0.1" + crypto-js "^4.0.0" + ergo-lib-wasm-browser "0.20.1" + ergo-lib-wasm-nodejs "0.20.1" + esm-wallaby "^3.2.25" + json-bigint "^1.0.0" + mathjs "^9.4.4" + ramda "0.27.1" + +"@ergolabs/ergo-sdk@^0.5.7": + version "0.5.7" + resolved "https://registry.yarnpkg.com/@ergolabs/ergo-sdk/-/ergo-sdk-0.5.7.tgz#cb65f3f5d7fb72058ebf1e1188205e01630f7997" + integrity sha512-4hK5nKXdmqQOaBdNufdfOYLO41jnPOwAy8dOv1gveQRYYzlm2QXXIGMriyRGAhBD4rUa5afHSL+nTW7VMuGC3Q== + dependencies: + axios "^0.21.1" + blakejs "^1.1.0" + bs58 "^4.0.1" + crypto-js "^4.0.0" + ergo-lib-wasm-browser "^0.20.1" + ergo-lib-wasm-nodejs "^0.20.1" + esm-wallaby "^3.2.25" + json-bigint "^1.0.0" + mathjs "^9.4.4" + ramda "0.27.1" + "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" @@ -1434,137 +1467,137 @@ "@ethersproject-xdc/abi@file:vendor/@ethersproject-xdc/abi": version "5.7.0" dependencies: - "@ethersproject-xdc/address" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abi-5.7.0-dc6cad0a-b42e-41c0-add1-31aa9f73da8c-1711378365614/node_modules/@ethersproject-xdc/address" - "@ethersproject-xdc/bignumber" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abi-5.7.0-dc6cad0a-b42e-41c0-add1-31aa9f73da8c-1711378365614/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abi-5.7.0-dc6cad0a-b42e-41c0-add1-31aa9f73da8c-1711378365614/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/constants" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abi-5.7.0-dc6cad0a-b42e-41c0-add1-31aa9f73da8c-1711378365614/node_modules/@ethersproject-xdc/constants" - "@ethersproject-xdc/hash" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abi-5.7.0-dc6cad0a-b42e-41c0-add1-31aa9f73da8c-1711378365614/node_modules/@ethersproject-xdc/hash" - "@ethersproject-xdc/keccak256" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abi-5.7.0-dc6cad0a-b42e-41c0-add1-31aa9f73da8c-1711378365614/node_modules/@ethersproject-xdc/keccak256" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abi-5.7.0-dc6cad0a-b42e-41c0-add1-31aa9f73da8c-1711378365614/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/properties" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abi-5.7.0-dc6cad0a-b42e-41c0-add1-31aa9f73da8c-1711378365614/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/strings" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abi-5.7.0-dc6cad0a-b42e-41c0-add1-31aa9f73da8c-1711378365614/node_modules/@ethersproject-xdc/strings" + "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-b97335c9-ef20-4dbd-8f38-3439a5f2f5c3-1717523642486/node_modules/@ethersproject-xdc/address" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-b97335c9-ef20-4dbd-8f38-3439a5f2f5c3-1717523642486/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-b97335c9-ef20-4dbd-8f38-3439a5f2f5c3-1717523642486/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/constants" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-b97335c9-ef20-4dbd-8f38-3439a5f2f5c3-1717523642486/node_modules/@ethersproject-xdc/constants" + "@ethersproject-xdc/hash" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-b97335c9-ef20-4dbd-8f38-3439a5f2f5c3-1717523642486/node_modules/@ethersproject-xdc/hash" + "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-b97335c9-ef20-4dbd-8f38-3439a5f2f5c3-1717523642486/node_modules/@ethersproject-xdc/keccak256" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-b97335c9-ef20-4dbd-8f38-3439a5f2f5c3-1717523642486/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-b97335c9-ef20-4dbd-8f38-3439a5f2f5c3-1717523642486/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-b97335c9-ef20-4dbd-8f38-3439a5f2f5c3-1717523642486/node_modules/@ethersproject-xdc/strings" "@ethersproject-xdc/abstract-provider@file:vendor/@ethersproject-xdc/abstract-provider": version "5.7.0" dependencies: - "@ethersproject-xdc/bignumber" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-7563efea-d843-42b7-b285-fbeff4443c61-1711378365615/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-7563efea-d843-42b7-b285-fbeff4443c61-1711378365615/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-7563efea-d843-42b7-b285-fbeff4443c61-1711378365615/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/networks" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-7563efea-d843-42b7-b285-fbeff4443c61-1711378365615/node_modules/@ethersproject-xdc/networks" - "@ethersproject-xdc/properties" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-7563efea-d843-42b7-b285-fbeff4443c61-1711378365615/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/transactions" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-7563efea-d843-42b7-b285-fbeff4443c61-1711378365615/node_modules/@ethersproject-xdc/transactions" - "@ethersproject-xdc/web" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-7563efea-d843-42b7-b285-fbeff4443c61-1711378365615/node_modules/@ethersproject-xdc/web" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-907e104a-3c1f-447f-8ae0-1361a7acc3bc-1717523642483/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-907e104a-3c1f-447f-8ae0-1361a7acc3bc-1717523642483/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-907e104a-3c1f-447f-8ae0-1361a7acc3bc-1717523642483/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/networks" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-907e104a-3c1f-447f-8ae0-1361a7acc3bc-1717523642483/node_modules/@ethersproject-xdc/networks" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-907e104a-3c1f-447f-8ae0-1361a7acc3bc-1717523642483/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/transactions" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-907e104a-3c1f-447f-8ae0-1361a7acc3bc-1717523642483/node_modules/@ethersproject-xdc/transactions" + "@ethersproject-xdc/web" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-907e104a-3c1f-447f-8ae0-1361a7acc3bc-1717523642483/node_modules/@ethersproject-xdc/web" "@ethersproject-xdc/abstract-signer@file:vendor/@ethersproject-xdc/abstract-signer": version "5.7.0" dependencies: - "@ethersproject-xdc/abstract-provider" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abstract-signer-5.7.0-e30fa525-50b0-4a94-a2fc-4b012803d33e-1711378365615/node_modules/@ethersproject-xdc/abstract-provider" - "@ethersproject-xdc/bignumber" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abstract-signer-5.7.0-e30fa525-50b0-4a94-a2fc-4b012803d33e-1711378365615/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abstract-signer-5.7.0-e30fa525-50b0-4a94-a2fc-4b012803d33e-1711378365615/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abstract-signer-5.7.0-e30fa525-50b0-4a94-a2fc-4b012803d33e-1711378365615/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/properties" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abstract-signer-5.7.0-e30fa525-50b0-4a94-a2fc-4b012803d33e-1711378365615/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/abstract-provider" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-signer-5.7.0-5ddef21c-0a71-4642-8188-cd10d89e437c-1717523642484/node_modules/@ethersproject-xdc/abstract-provider" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-signer-5.7.0-5ddef21c-0a71-4642-8188-cd10d89e437c-1717523642484/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-signer-5.7.0-5ddef21c-0a71-4642-8188-cd10d89e437c-1717523642484/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-signer-5.7.0-5ddef21c-0a71-4642-8188-cd10d89e437c-1717523642484/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-signer-5.7.0-5ddef21c-0a71-4642-8188-cd10d89e437c-1717523642484/node_modules/@ethersproject-xdc/properties" "@ethersproject-xdc/address@file:vendor/@ethersproject-xdc/address": version "5.7.0" dependencies: - "@ethersproject-xdc/bignumber" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-address-5.7.0-ebb15099-34b3-4975-9cf8-7f3cae8cb2cf-1711378365616/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-address-5.7.0-ebb15099-34b3-4975-9cf8-7f3cae8cb2cf-1711378365616/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/keccak256" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-address-5.7.0-ebb15099-34b3-4975-9cf8-7f3cae8cb2cf-1711378365616/node_modules/@ethersproject-xdc/keccak256" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-address-5.7.0-ebb15099-34b3-4975-9cf8-7f3cae8cb2cf-1711378365616/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/rlp" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-address-5.7.0-ebb15099-34b3-4975-9cf8-7f3cae8cb2cf-1711378365616/node_modules/@ethersproject-xdc/rlp" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-address-5.7.0-46878ade-a717-4dec-8f34-64ced0f221a5-1717523642481/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-address-5.7.0-46878ade-a717-4dec-8f34-64ced0f221a5-1717523642481/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-address-5.7.0-46878ade-a717-4dec-8f34-64ced0f221a5-1717523642481/node_modules/@ethersproject-xdc/keccak256" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-address-5.7.0-46878ade-a717-4dec-8f34-64ced0f221a5-1717523642481/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/rlp" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-address-5.7.0-46878ade-a717-4dec-8f34-64ced0f221a5-1717523642481/node_modules/@ethersproject-xdc/rlp" "@ethersproject-xdc/base64@file:vendor/@ethersproject-xdc/base64": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-base64-5.7.0-ac940ee8-f7d7-44f8-a8e6-a8a2aa43673b-1711378365615/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-base64-5.7.0-88d810c8-1ad7-4b5f-8810-267aedd392db-1717523642482/node_modules/@ethersproject-xdc/bytes" "@ethersproject-xdc/basex@file:vendor/@ethersproject-xdc/basex": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-basex-5.7.0-a3964cd6-3388-4e1e-8827-ccb5f8cddbea-1711378365615/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/properties" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-basex-5.7.0-a3964cd6-3388-4e1e-8827-ccb5f8cddbea-1711378365615/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-basex-5.7.0-03472f6a-4ef6-435f-92bd-a160ef12584d-1717523642482/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-basex-5.7.0-03472f6a-4ef6-435f-92bd-a160ef12584d-1717523642482/node_modules/@ethersproject-xdc/properties" "@ethersproject-xdc/bignumber@file:vendor/@ethersproject-xdc/bignumber": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-bignumber-5.7.0-bc93acda-27ae-4704-88d0-8826555c062b-1711378365615/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-bignumber-5.7.0-bc93acda-27ae-4704-88d0-8826555c062b-1711378365615/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-bignumber-5.7.0-c16e35ca-70ef-4fa4-a4aa-fe1cdc7f4cb9-1717523642487/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-bignumber-5.7.0-c16e35ca-70ef-4fa4-a4aa-fe1cdc7f4cb9-1717523642487/node_modules/@ethersproject-xdc/logger" bn.js "^5.2.1" "@ethersproject-xdc/bytes@file:vendor/@ethersproject-xdc/bytes": version "5.7.0" dependencies: - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-bytes-5.7.0-99ecb1f1-f3c4-4352-b857-7f806ce05f5d-1711378365616/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-bytes-5.7.0-4840f7f4-33e6-43d3-acd8-2213a8333593-1717523642486/node_modules/@ethersproject-xdc/logger" "@ethersproject-xdc/constants@file:vendor/@ethersproject-xdc/constants": version "5.7.0" dependencies: - "@ethersproject-xdc/bignumber" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-constants-5.7.0-91a31af6-9be3-4e31-94b5-304ef35e3207-1711378365616/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-constants-5.7.0-183b26c2-261b-4d34-b271-3dc7ac599af4-1717523642484/node_modules/@ethersproject-xdc/bignumber" "@ethersproject-xdc/contracts@file:vendor/@ethersproject-xdc/contracts": version "5.6.0" dependencies: - "@ethersproject-xdc/abi" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-contracts-5.6.0-3a1d2199-b3e9-4cf8-a8e5-111bb620bb2f-1711378365616/node_modules/@ethersproject-xdc/abi" - "@ethersproject-xdc/abstract-provider" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-contracts-5.6.0-3a1d2199-b3e9-4cf8-a8e5-111bb620bb2f-1711378365616/node_modules/@ethersproject-xdc/abstract-provider" - "@ethersproject-xdc/abstract-signer" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-contracts-5.6.0-3a1d2199-b3e9-4cf8-a8e5-111bb620bb2f-1711378365616/node_modules/@ethersproject-xdc/abstract-signer" - "@ethersproject-xdc/address" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-contracts-5.6.0-3a1d2199-b3e9-4cf8-a8e5-111bb620bb2f-1711378365616/node_modules/@ethersproject-xdc/address" - "@ethersproject-xdc/bignumber" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-contracts-5.6.0-3a1d2199-b3e9-4cf8-a8e5-111bb620bb2f-1711378365616/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-contracts-5.6.0-3a1d2199-b3e9-4cf8-a8e5-111bb620bb2f-1711378365616/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/constants" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-contracts-5.6.0-3a1d2199-b3e9-4cf8-a8e5-111bb620bb2f-1711378365616/node_modules/@ethersproject-xdc/constants" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-contracts-5.6.0-3a1d2199-b3e9-4cf8-a8e5-111bb620bb2f-1711378365616/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/properties" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-contracts-5.6.0-3a1d2199-b3e9-4cf8-a8e5-111bb620bb2f-1711378365616/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/transactions" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-contracts-5.6.0-3a1d2199-b3e9-4cf8-a8e5-111bb620bb2f-1711378365616/node_modules/@ethersproject-xdc/transactions" + "@ethersproject-xdc/abi" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-3b740cca-f783-4775-b482-df49b3c6367f-1717523642484/node_modules/@ethersproject-xdc/abi" + "@ethersproject-xdc/abstract-provider" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-3b740cca-f783-4775-b482-df49b3c6367f-1717523642484/node_modules/@ethersproject-xdc/abstract-provider" + "@ethersproject-xdc/abstract-signer" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-3b740cca-f783-4775-b482-df49b3c6367f-1717523642484/node_modules/@ethersproject-xdc/abstract-signer" + "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-3b740cca-f783-4775-b482-df49b3c6367f-1717523642484/node_modules/@ethersproject-xdc/address" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-3b740cca-f783-4775-b482-df49b3c6367f-1717523642484/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-3b740cca-f783-4775-b482-df49b3c6367f-1717523642484/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/constants" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-3b740cca-f783-4775-b482-df49b3c6367f-1717523642484/node_modules/@ethersproject-xdc/constants" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-3b740cca-f783-4775-b482-df49b3c6367f-1717523642484/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-3b740cca-f783-4775-b482-df49b3c6367f-1717523642484/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/transactions" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-3b740cca-f783-4775-b482-df49b3c6367f-1717523642484/node_modules/@ethersproject-xdc/transactions" "@ethersproject-xdc/hash@file:vendor/@ethersproject-xdc/hash": version "5.7.0" dependencies: - "@ethersproject-xdc/abstract-signer" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hash-5.7.0-e59c6ed5-6f74-42e7-b132-f4bea3ddfad0-1711378365617/node_modules/@ethersproject-xdc/abstract-signer" - "@ethersproject-xdc/address" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hash-5.7.0-e59c6ed5-6f74-42e7-b132-f4bea3ddfad0-1711378365617/node_modules/@ethersproject-xdc/address" - "@ethersproject-xdc/base64" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hash-5.7.0-e59c6ed5-6f74-42e7-b132-f4bea3ddfad0-1711378365617/node_modules/@ethersproject-xdc/base64" - "@ethersproject-xdc/bignumber" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hash-5.7.0-e59c6ed5-6f74-42e7-b132-f4bea3ddfad0-1711378365617/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hash-5.7.0-e59c6ed5-6f74-42e7-b132-f4bea3ddfad0-1711378365617/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/keccak256" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hash-5.7.0-e59c6ed5-6f74-42e7-b132-f4bea3ddfad0-1711378365617/node_modules/@ethersproject-xdc/keccak256" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hash-5.7.0-e59c6ed5-6f74-42e7-b132-f4bea3ddfad0-1711378365617/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/properties" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hash-5.7.0-e59c6ed5-6f74-42e7-b132-f4bea3ddfad0-1711378365617/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/strings" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hash-5.7.0-e59c6ed5-6f74-42e7-b132-f4bea3ddfad0-1711378365617/node_modules/@ethersproject-xdc/strings" + "@ethersproject-xdc/abstract-signer" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-7653a163-9d90-42d8-a7f8-89d1d0d96d29-1717523642485/node_modules/@ethersproject-xdc/abstract-signer" + "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-7653a163-9d90-42d8-a7f8-89d1d0d96d29-1717523642485/node_modules/@ethersproject-xdc/address" + "@ethersproject-xdc/base64" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-7653a163-9d90-42d8-a7f8-89d1d0d96d29-1717523642485/node_modules/@ethersproject-xdc/base64" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-7653a163-9d90-42d8-a7f8-89d1d0d96d29-1717523642485/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-7653a163-9d90-42d8-a7f8-89d1d0d96d29-1717523642485/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-7653a163-9d90-42d8-a7f8-89d1d0d96d29-1717523642485/node_modules/@ethersproject-xdc/keccak256" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-7653a163-9d90-42d8-a7f8-89d1d0d96d29-1717523642485/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-7653a163-9d90-42d8-a7f8-89d1d0d96d29-1717523642485/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-7653a163-9d90-42d8-a7f8-89d1d0d96d29-1717523642485/node_modules/@ethersproject-xdc/strings" "@ethersproject-xdc/hdnode@file:vendor/@ethersproject-xdc/hdnode": version "5.7.0" dependencies: - "@ethersproject-xdc/abstract-signer" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hdnode-5.7.0-7df6d3a0-85a2-4dd8-84f0-7defb4301c82-1711378365618/node_modules/@ethersproject-xdc/abstract-signer" - "@ethersproject-xdc/basex" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hdnode-5.7.0-7df6d3a0-85a2-4dd8-84f0-7defb4301c82-1711378365618/node_modules/@ethersproject-xdc/basex" - "@ethersproject-xdc/bignumber" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hdnode-5.7.0-7df6d3a0-85a2-4dd8-84f0-7defb4301c82-1711378365618/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hdnode-5.7.0-7df6d3a0-85a2-4dd8-84f0-7defb4301c82-1711378365618/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hdnode-5.7.0-7df6d3a0-85a2-4dd8-84f0-7defb4301c82-1711378365618/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/pbkdf2" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hdnode-5.7.0-7df6d3a0-85a2-4dd8-84f0-7defb4301c82-1711378365618/node_modules/@ethersproject-xdc/pbkdf2" - "@ethersproject-xdc/properties" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hdnode-5.7.0-7df6d3a0-85a2-4dd8-84f0-7defb4301c82-1711378365618/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/sha2" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hdnode-5.7.0-7df6d3a0-85a2-4dd8-84f0-7defb4301c82-1711378365618/node_modules/@ethersproject-xdc/sha2" - "@ethersproject-xdc/signing-key" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hdnode-5.7.0-7df6d3a0-85a2-4dd8-84f0-7defb4301c82-1711378365618/node_modules/@ethersproject-xdc/signing-key" - "@ethersproject-xdc/strings" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hdnode-5.7.0-7df6d3a0-85a2-4dd8-84f0-7defb4301c82-1711378365618/node_modules/@ethersproject-xdc/strings" - "@ethersproject-xdc/transactions" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hdnode-5.7.0-7df6d3a0-85a2-4dd8-84f0-7defb4301c82-1711378365618/node_modules/@ethersproject-xdc/transactions" - "@ethersproject-xdc/wordlists" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hdnode-5.7.0-7df6d3a0-85a2-4dd8-84f0-7defb4301c82-1711378365618/node_modules/@ethersproject-xdc/wordlists" + "@ethersproject-xdc/abstract-signer" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-e6f42e00-ec83-4761-9362-9d1e3b6a1c1e-1717523642489/node_modules/@ethersproject-xdc/abstract-signer" + "@ethersproject-xdc/basex" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-e6f42e00-ec83-4761-9362-9d1e3b6a1c1e-1717523642489/node_modules/@ethersproject-xdc/basex" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-e6f42e00-ec83-4761-9362-9d1e3b6a1c1e-1717523642489/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-e6f42e00-ec83-4761-9362-9d1e3b6a1c1e-1717523642489/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-e6f42e00-ec83-4761-9362-9d1e3b6a1c1e-1717523642489/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/pbkdf2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-e6f42e00-ec83-4761-9362-9d1e3b6a1c1e-1717523642489/node_modules/@ethersproject-xdc/pbkdf2" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-e6f42e00-ec83-4761-9362-9d1e3b6a1c1e-1717523642489/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/sha2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-e6f42e00-ec83-4761-9362-9d1e3b6a1c1e-1717523642489/node_modules/@ethersproject-xdc/sha2" + "@ethersproject-xdc/signing-key" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-e6f42e00-ec83-4761-9362-9d1e3b6a1c1e-1717523642489/node_modules/@ethersproject-xdc/signing-key" + "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-e6f42e00-ec83-4761-9362-9d1e3b6a1c1e-1717523642489/node_modules/@ethersproject-xdc/strings" + "@ethersproject-xdc/transactions" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-e6f42e00-ec83-4761-9362-9d1e3b6a1c1e-1717523642489/node_modules/@ethersproject-xdc/transactions" + "@ethersproject-xdc/wordlists" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-e6f42e00-ec83-4761-9362-9d1e3b6a1c1e-1717523642489/node_modules/@ethersproject-xdc/wordlists" "@ethersproject-xdc/json-wallets@file:vendor/@ethersproject-xdc/json-wallets": version "5.6.0" dependencies: - "@ethersproject-xdc/abstract-signer" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-b09d5477-70d2-455d-95b9-95327c90a434-1711378365617/node_modules/@ethersproject-xdc/abstract-signer" - "@ethersproject-xdc/address" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-b09d5477-70d2-455d-95b9-95327c90a434-1711378365617/node_modules/@ethersproject-xdc/address" - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-b09d5477-70d2-455d-95b9-95327c90a434-1711378365617/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/hdnode" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-b09d5477-70d2-455d-95b9-95327c90a434-1711378365617/node_modules/@ethersproject-xdc/hdnode" - "@ethersproject-xdc/keccak256" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-b09d5477-70d2-455d-95b9-95327c90a434-1711378365617/node_modules/@ethersproject-xdc/keccak256" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-b09d5477-70d2-455d-95b9-95327c90a434-1711378365617/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/pbkdf2" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-b09d5477-70d2-455d-95b9-95327c90a434-1711378365617/node_modules/@ethersproject-xdc/pbkdf2" - "@ethersproject-xdc/properties" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-b09d5477-70d2-455d-95b9-95327c90a434-1711378365617/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/random" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-b09d5477-70d2-455d-95b9-95327c90a434-1711378365617/node_modules/@ethersproject-xdc/random" - "@ethersproject-xdc/strings" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-b09d5477-70d2-455d-95b9-95327c90a434-1711378365617/node_modules/@ethersproject-xdc/strings" - "@ethersproject-xdc/transactions" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-b09d5477-70d2-455d-95b9-95327c90a434-1711378365617/node_modules/@ethersproject-xdc/transactions" + "@ethersproject-xdc/abstract-signer" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-fade40f6-e5cc-45f1-9ec9-ca5fcc2a53f2-1717523642486/node_modules/@ethersproject-xdc/abstract-signer" + "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-fade40f6-e5cc-45f1-9ec9-ca5fcc2a53f2-1717523642486/node_modules/@ethersproject-xdc/address" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-fade40f6-e5cc-45f1-9ec9-ca5fcc2a53f2-1717523642486/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/hdnode" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-fade40f6-e5cc-45f1-9ec9-ca5fcc2a53f2-1717523642486/node_modules/@ethersproject-xdc/hdnode" + "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-fade40f6-e5cc-45f1-9ec9-ca5fcc2a53f2-1717523642486/node_modules/@ethersproject-xdc/keccak256" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-fade40f6-e5cc-45f1-9ec9-ca5fcc2a53f2-1717523642486/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/pbkdf2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-fade40f6-e5cc-45f1-9ec9-ca5fcc2a53f2-1717523642486/node_modules/@ethersproject-xdc/pbkdf2" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-fade40f6-e5cc-45f1-9ec9-ca5fcc2a53f2-1717523642486/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/random" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-fade40f6-e5cc-45f1-9ec9-ca5fcc2a53f2-1717523642486/node_modules/@ethersproject-xdc/random" + "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-fade40f6-e5cc-45f1-9ec9-ca5fcc2a53f2-1717523642486/node_modules/@ethersproject-xdc/strings" + "@ethersproject-xdc/transactions" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-fade40f6-e5cc-45f1-9ec9-ca5fcc2a53f2-1717523642486/node_modules/@ethersproject-xdc/transactions" aes-js "3.0.0" scrypt-js "3.0.1" "@ethersproject-xdc/keccak256@file:vendor/@ethersproject-xdc/keccak256": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-keccak256-5.7.0-9cb7534e-f2d4-4bb8-8726-aa8d2ae70a68-1711378365617/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-keccak256-5.7.0-bef06719-6d1a-4726-857c-d7d191877d3a-1717523642488/node_modules/@ethersproject-xdc/bytes" js-sha3 "0.8.0" "@ethersproject-xdc/logger@file:vendor/@ethersproject-xdc/logger": @@ -1573,67 +1606,67 @@ "@ethersproject-xdc/networks@file:vendor/@ethersproject-xdc/networks": version "5.7.1" dependencies: - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-networks-5.7.1-3318040d-6ee2-4fe1-8d35-2e90df014a04-1711378365619/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-networks-5.7.1-80a24561-208a-4e8d-855d-510bf0442b64-1717523642487/node_modules/@ethersproject-xdc/logger" "@ethersproject-xdc/pbkdf2@file:vendor/@ethersproject-xdc/pbkdf2": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-pbkdf2-5.7.0-1db75448-b10f-4529-b48f-66f22c09a20a-1711378365617/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/sha2" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-pbkdf2-5.7.0-1db75448-b10f-4529-b48f-66f22c09a20a-1711378365617/node_modules/@ethersproject-xdc/sha2" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-pbkdf2-5.7.0-0d41cf61-17cb-4636-85ab-7aaad0567290-1717523642490/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/sha2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-pbkdf2-5.7.0-0d41cf61-17cb-4636-85ab-7aaad0567290-1717523642490/node_modules/@ethersproject-xdc/sha2" "@ethersproject-xdc/properties@file:vendor/@ethersproject-xdc/properties": version "5.7.0" dependencies: - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-properties-5.7.0-d600654f-dc20-45bd-8730-5aea66cd419c-1711378365618/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-properties-5.7.0-d37a8b04-46a8-4bd3-84e6-764fc80da77d-1717523642496/node_modules/@ethersproject-xdc/logger" "@ethersproject-xdc/providers@file:vendor/@ethersproject-xdc/providers": version "5.6.2" dependencies: - "@ethersproject-xdc/abstract-provider" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/abstract-provider" - "@ethersproject-xdc/abstract-signer" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/abstract-signer" - "@ethersproject-xdc/address" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/address" - "@ethersproject-xdc/basex" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/basex" - "@ethersproject-xdc/bignumber" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/constants" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/constants" - "@ethersproject-xdc/hash" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/hash" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/networks" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/networks" - "@ethersproject-xdc/properties" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/random" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/random" - "@ethersproject-xdc/rlp" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/rlp" - "@ethersproject-xdc/sha2" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/sha2" - "@ethersproject-xdc/strings" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/strings" - "@ethersproject-xdc/transactions" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/transactions" - "@ethersproject-xdc/web" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/web" + "@ethersproject-xdc/abstract-provider" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-28309408-007c-442a-a440-08cf19687651-1717523642488/node_modules/@ethersproject-xdc/abstract-provider" + "@ethersproject-xdc/abstract-signer" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-28309408-007c-442a-a440-08cf19687651-1717523642488/node_modules/@ethersproject-xdc/abstract-signer" + "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-28309408-007c-442a-a440-08cf19687651-1717523642488/node_modules/@ethersproject-xdc/address" + "@ethersproject-xdc/basex" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-28309408-007c-442a-a440-08cf19687651-1717523642488/node_modules/@ethersproject-xdc/basex" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-28309408-007c-442a-a440-08cf19687651-1717523642488/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-28309408-007c-442a-a440-08cf19687651-1717523642488/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/constants" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-28309408-007c-442a-a440-08cf19687651-1717523642488/node_modules/@ethersproject-xdc/constants" + "@ethersproject-xdc/hash" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-28309408-007c-442a-a440-08cf19687651-1717523642488/node_modules/@ethersproject-xdc/hash" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-28309408-007c-442a-a440-08cf19687651-1717523642488/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/networks" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-28309408-007c-442a-a440-08cf19687651-1717523642488/node_modules/@ethersproject-xdc/networks" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-28309408-007c-442a-a440-08cf19687651-1717523642488/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/random" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-28309408-007c-442a-a440-08cf19687651-1717523642488/node_modules/@ethersproject-xdc/random" + "@ethersproject-xdc/rlp" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-28309408-007c-442a-a440-08cf19687651-1717523642488/node_modules/@ethersproject-xdc/rlp" + "@ethersproject-xdc/sha2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-28309408-007c-442a-a440-08cf19687651-1717523642488/node_modules/@ethersproject-xdc/sha2" + "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-28309408-007c-442a-a440-08cf19687651-1717523642488/node_modules/@ethersproject-xdc/strings" + "@ethersproject-xdc/transactions" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-28309408-007c-442a-a440-08cf19687651-1717523642488/node_modules/@ethersproject-xdc/transactions" + "@ethersproject-xdc/web" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-28309408-007c-442a-a440-08cf19687651-1717523642488/node_modules/@ethersproject-xdc/web" bech32 "1.1.4" ws "7.4.6" "@ethersproject-xdc/random@file:vendor/@ethersproject-xdc/random": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-random-5.7.0-98a7dd46-79c6-4335-9d15-21617d7f16a5-1711378365619/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-random-5.7.0-98a7dd46-79c6-4335-9d15-21617d7f16a5-1711378365619/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-random-5.7.0-20f18cb8-ebf5-4010-9bcb-c114c7eb2264-1717523642490/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-random-5.7.0-20f18cb8-ebf5-4010-9bcb-c114c7eb2264-1717523642490/node_modules/@ethersproject-xdc/logger" "@ethersproject-xdc/rlp@file:vendor/@ethersproject-xdc/rlp": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-rlp-5.7.0-7790503f-a04f-459f-8b5c-cf61ffd4ff12-1711378365619/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-rlp-5.7.0-7790503f-a04f-459f-8b5c-cf61ffd4ff12-1711378365619/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-rlp-5.7.0-e2b0e158-ead7-4679-ade8-f400b62f6a77-1717523642489/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-rlp-5.7.0-e2b0e158-ead7-4679-ade8-f400b62f6a77-1717523642489/node_modules/@ethersproject-xdc/logger" "@ethersproject-xdc/sha2@file:vendor/@ethersproject-xdc/sha2": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-sha2-5.7.0-c765449d-476b-4741-9e2e-dbccb8aa1809-1711378365619/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-sha2-5.7.0-c765449d-476b-4741-9e2e-dbccb8aa1809-1711378365619/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-sha2-5.7.0-b196a980-a384-4185-b9a7-9f470f910379-1717523642490/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-sha2-5.7.0-b196a980-a384-4185-b9a7-9f470f910379-1717523642490/node_modules/@ethersproject-xdc/logger" hash.js "1.1.7" "@ethersproject-xdc/signing-key@file:vendor/@ethersproject-xdc/signing-key": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-signing-key-5.7.0-21971b50-7b39-465c-bb5a-2f8689e48cc2-1711378365620/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-signing-key-5.7.0-21971b50-7b39-465c-bb5a-2f8689e48cc2-1711378365620/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/properties" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-signing-key-5.7.0-21971b50-7b39-465c-bb5a-2f8689e48cc2-1711378365620/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-signing-key-5.7.0-f018c560-1f37-4b2c-b9a1-91dcecfaac4c-1717523642491/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-signing-key-5.7.0-f018c560-1f37-4b2c-b9a1-91dcecfaac4c-1717523642491/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-signing-key-5.7.0-f018c560-1f37-4b2c-b9a1-91dcecfaac4c-1717523642491/node_modules/@ethersproject-xdc/properties" bn.js "^5.2.1" elliptic "6.5.4" hash.js "1.1.7" @@ -1641,76 +1674,76 @@ "@ethersproject-xdc/solidity@file:vendor/@ethersproject-xdc/solidity": version "5.6.0" dependencies: - "@ethersproject-xdc/bignumber" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-solidity-5.6.0-e3924149-bd04-4548-98cf-44195b92192d-1711378365619/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-solidity-5.6.0-e3924149-bd04-4548-98cf-44195b92192d-1711378365619/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/keccak256" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-solidity-5.6.0-e3924149-bd04-4548-98cf-44195b92192d-1711378365619/node_modules/@ethersproject-xdc/keccak256" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-solidity-5.6.0-e3924149-bd04-4548-98cf-44195b92192d-1711378365619/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/sha2" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-solidity-5.6.0-e3924149-bd04-4548-98cf-44195b92192d-1711378365619/node_modules/@ethersproject-xdc/sha2" - "@ethersproject-xdc/strings" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-solidity-5.6.0-e3924149-bd04-4548-98cf-44195b92192d-1711378365619/node_modules/@ethersproject-xdc/strings" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-solidity-5.6.0-c0ce073f-a06d-4980-bd15-a92460dfb45a-1717523642491/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-solidity-5.6.0-c0ce073f-a06d-4980-bd15-a92460dfb45a-1717523642491/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-solidity-5.6.0-c0ce073f-a06d-4980-bd15-a92460dfb45a-1717523642491/node_modules/@ethersproject-xdc/keccak256" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-solidity-5.6.0-c0ce073f-a06d-4980-bd15-a92460dfb45a-1717523642491/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/sha2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-solidity-5.6.0-c0ce073f-a06d-4980-bd15-a92460dfb45a-1717523642491/node_modules/@ethersproject-xdc/sha2" + "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-solidity-5.6.0-c0ce073f-a06d-4980-bd15-a92460dfb45a-1717523642491/node_modules/@ethersproject-xdc/strings" "@ethersproject-xdc/strings@file:vendor/@ethersproject-xdc/strings": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-strings-5.7.0-42e9cb08-71fd-4932-bd36-6f05e0f1b34b-1711378365620/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/constants" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-strings-5.7.0-42e9cb08-71fd-4932-bd36-6f05e0f1b34b-1711378365620/node_modules/@ethersproject-xdc/constants" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-strings-5.7.0-42e9cb08-71fd-4932-bd36-6f05e0f1b34b-1711378365620/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-strings-5.7.0-d5745e55-6021-4383-bc5b-7ec6686d1c6d-1717523642490/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/constants" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-strings-5.7.0-d5745e55-6021-4383-bc5b-7ec6686d1c6d-1717523642490/node_modules/@ethersproject-xdc/constants" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-strings-5.7.0-d5745e55-6021-4383-bc5b-7ec6686d1c6d-1717523642490/node_modules/@ethersproject-xdc/logger" "@ethersproject-xdc/transactions@file:vendor/@ethersproject-xdc/transactions": version "5.7.0" dependencies: - "@ethersproject-xdc/address" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-transactions-5.7.0-bb480f26-2b90-41a5-bfff-057ac9b6e8e9-1711378365622/node_modules/@ethersproject-xdc/address" - "@ethersproject-xdc/bignumber" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-transactions-5.7.0-bb480f26-2b90-41a5-bfff-057ac9b6e8e9-1711378365622/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-transactions-5.7.0-bb480f26-2b90-41a5-bfff-057ac9b6e8e9-1711378365622/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/constants" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-transactions-5.7.0-bb480f26-2b90-41a5-bfff-057ac9b6e8e9-1711378365622/node_modules/@ethersproject-xdc/constants" - "@ethersproject-xdc/keccak256" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-transactions-5.7.0-bb480f26-2b90-41a5-bfff-057ac9b6e8e9-1711378365622/node_modules/@ethersproject-xdc/keccak256" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-transactions-5.7.0-bb480f26-2b90-41a5-bfff-057ac9b6e8e9-1711378365622/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/properties" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-transactions-5.7.0-bb480f26-2b90-41a5-bfff-057ac9b6e8e9-1711378365622/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/rlp" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-transactions-5.7.0-bb480f26-2b90-41a5-bfff-057ac9b6e8e9-1711378365622/node_modules/@ethersproject-xdc/rlp" - "@ethersproject-xdc/signing-key" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-transactions-5.7.0-bb480f26-2b90-41a5-bfff-057ac9b6e8e9-1711378365622/node_modules/@ethersproject-xdc/signing-key" + "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-5337c33c-595e-40c3-8b3b-2ccd2049c220-1717523642492/node_modules/@ethersproject-xdc/address" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-5337c33c-595e-40c3-8b3b-2ccd2049c220-1717523642492/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-5337c33c-595e-40c3-8b3b-2ccd2049c220-1717523642492/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/constants" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-5337c33c-595e-40c3-8b3b-2ccd2049c220-1717523642492/node_modules/@ethersproject-xdc/constants" + "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-5337c33c-595e-40c3-8b3b-2ccd2049c220-1717523642492/node_modules/@ethersproject-xdc/keccak256" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-5337c33c-595e-40c3-8b3b-2ccd2049c220-1717523642492/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-5337c33c-595e-40c3-8b3b-2ccd2049c220-1717523642492/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/rlp" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-5337c33c-595e-40c3-8b3b-2ccd2049c220-1717523642492/node_modules/@ethersproject-xdc/rlp" + "@ethersproject-xdc/signing-key" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-5337c33c-595e-40c3-8b3b-2ccd2049c220-1717523642492/node_modules/@ethersproject-xdc/signing-key" "@ethersproject-xdc/units@file:vendor/@ethersproject-xdc/units": version "5.6.0" dependencies: - "@ethersproject-xdc/bignumber" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-units-5.6.0-5f41db51-35b1-4973-a795-080ed99a99b4-1711378365619/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/constants" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-units-5.6.0-5f41db51-35b1-4973-a795-080ed99a99b4-1711378365619/node_modules/@ethersproject-xdc/constants" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-units-5.6.0-5f41db51-35b1-4973-a795-080ed99a99b4-1711378365619/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-units-5.6.0-235877f7-4d67-48ee-b1c6-16542d75e02d-1717523642491/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/constants" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-units-5.6.0-235877f7-4d67-48ee-b1c6-16542d75e02d-1717523642491/node_modules/@ethersproject-xdc/constants" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-units-5.6.0-235877f7-4d67-48ee-b1c6-16542d75e02d-1717523642491/node_modules/@ethersproject-xdc/logger" "@ethersproject-xdc/wallet@file:vendor/@ethersproject-xdc/wallet": version "5.6.0" dependencies: - "@ethersproject-xdc/abstract-provider" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wallet-5.6.0-bc949dc4-090d-4ab9-b6c6-709a17fc75ad-1711378365622/node_modules/@ethersproject-xdc/abstract-provider" - "@ethersproject-xdc/abstract-signer" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wallet-5.6.0-bc949dc4-090d-4ab9-b6c6-709a17fc75ad-1711378365622/node_modules/@ethersproject-xdc/abstract-signer" - "@ethersproject-xdc/address" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wallet-5.6.0-bc949dc4-090d-4ab9-b6c6-709a17fc75ad-1711378365622/node_modules/@ethersproject-xdc/address" - "@ethersproject-xdc/bignumber" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wallet-5.6.0-bc949dc4-090d-4ab9-b6c6-709a17fc75ad-1711378365622/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wallet-5.6.0-bc949dc4-090d-4ab9-b6c6-709a17fc75ad-1711378365622/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/hash" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wallet-5.6.0-bc949dc4-090d-4ab9-b6c6-709a17fc75ad-1711378365622/node_modules/@ethersproject-xdc/hash" - "@ethersproject-xdc/hdnode" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wallet-5.6.0-bc949dc4-090d-4ab9-b6c6-709a17fc75ad-1711378365622/node_modules/@ethersproject-xdc/hdnode" - "@ethersproject-xdc/json-wallets" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wallet-5.6.0-bc949dc4-090d-4ab9-b6c6-709a17fc75ad-1711378365622/node_modules/@ethersproject-xdc/json-wallets" - "@ethersproject-xdc/keccak256" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wallet-5.6.0-bc949dc4-090d-4ab9-b6c6-709a17fc75ad-1711378365622/node_modules/@ethersproject-xdc/keccak256" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wallet-5.6.0-bc949dc4-090d-4ab9-b6c6-709a17fc75ad-1711378365622/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/properties" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wallet-5.6.0-bc949dc4-090d-4ab9-b6c6-709a17fc75ad-1711378365622/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/random" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wallet-5.6.0-bc949dc4-090d-4ab9-b6c6-709a17fc75ad-1711378365622/node_modules/@ethersproject-xdc/random" - "@ethersproject-xdc/signing-key" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wallet-5.6.0-bc949dc4-090d-4ab9-b6c6-709a17fc75ad-1711378365622/node_modules/@ethersproject-xdc/signing-key" - "@ethersproject-xdc/transactions" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wallet-5.6.0-bc949dc4-090d-4ab9-b6c6-709a17fc75ad-1711378365622/node_modules/@ethersproject-xdc/transactions" - "@ethersproject-xdc/wordlists" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wallet-5.6.0-bc949dc4-090d-4ab9-b6c6-709a17fc75ad-1711378365622/node_modules/@ethersproject-xdc/wordlists" + "@ethersproject-xdc/abstract-provider" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-5b765faf-81ff-4fda-996d-4f70577f5541-1717523642491/node_modules/@ethersproject-xdc/abstract-provider" + "@ethersproject-xdc/abstract-signer" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-5b765faf-81ff-4fda-996d-4f70577f5541-1717523642491/node_modules/@ethersproject-xdc/abstract-signer" + "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-5b765faf-81ff-4fda-996d-4f70577f5541-1717523642491/node_modules/@ethersproject-xdc/address" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-5b765faf-81ff-4fda-996d-4f70577f5541-1717523642491/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-5b765faf-81ff-4fda-996d-4f70577f5541-1717523642491/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/hash" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-5b765faf-81ff-4fda-996d-4f70577f5541-1717523642491/node_modules/@ethersproject-xdc/hash" + "@ethersproject-xdc/hdnode" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-5b765faf-81ff-4fda-996d-4f70577f5541-1717523642491/node_modules/@ethersproject-xdc/hdnode" + "@ethersproject-xdc/json-wallets" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-5b765faf-81ff-4fda-996d-4f70577f5541-1717523642491/node_modules/@ethersproject-xdc/json-wallets" + "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-5b765faf-81ff-4fda-996d-4f70577f5541-1717523642491/node_modules/@ethersproject-xdc/keccak256" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-5b765faf-81ff-4fda-996d-4f70577f5541-1717523642491/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-5b765faf-81ff-4fda-996d-4f70577f5541-1717523642491/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/random" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-5b765faf-81ff-4fda-996d-4f70577f5541-1717523642491/node_modules/@ethersproject-xdc/random" + "@ethersproject-xdc/signing-key" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-5b765faf-81ff-4fda-996d-4f70577f5541-1717523642491/node_modules/@ethersproject-xdc/signing-key" + "@ethersproject-xdc/transactions" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-5b765faf-81ff-4fda-996d-4f70577f5541-1717523642491/node_modules/@ethersproject-xdc/transactions" + "@ethersproject-xdc/wordlists" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-5b765faf-81ff-4fda-996d-4f70577f5541-1717523642491/node_modules/@ethersproject-xdc/wordlists" "@ethersproject-xdc/web@file:vendor/@ethersproject-xdc/web": version "5.7.1" dependencies: - "@ethersproject-xdc/base64" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-web-5.7.1-9ac39370-4d32-4c38-96c7-4498ea524885-1711378365623/node_modules/@ethersproject-xdc/base64" - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-web-5.7.1-9ac39370-4d32-4c38-96c7-4498ea524885-1711378365623/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-web-5.7.1-9ac39370-4d32-4c38-96c7-4498ea524885-1711378365623/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/properties" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-web-5.7.1-9ac39370-4d32-4c38-96c7-4498ea524885-1711378365623/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/strings" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-web-5.7.1-9ac39370-4d32-4c38-96c7-4498ea524885-1711378365623/node_modules/@ethersproject-xdc/strings" + "@ethersproject-xdc/base64" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-web-5.7.1-58fcf120-d395-41fd-95c1-9a6ca72a8f18-1717523642494/node_modules/@ethersproject-xdc/base64" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-web-5.7.1-58fcf120-d395-41fd-95c1-9a6ca72a8f18-1717523642494/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-web-5.7.1-58fcf120-d395-41fd-95c1-9a6ca72a8f18-1717523642494/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-web-5.7.1-58fcf120-d395-41fd-95c1-9a6ca72a8f18-1717523642494/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-web-5.7.1-58fcf120-d395-41fd-95c1-9a6ca72a8f18-1717523642494/node_modules/@ethersproject-xdc/strings" "@ethersproject-xdc/wordlists@file:vendor/@ethersproject-xdc/wordlists": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wordlists-5.7.0-eafc2a13-cd67-4bf6-9256-aec79a731277-1711378365623/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/hash" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wordlists-5.7.0-eafc2a13-cd67-4bf6-9256-aec79a731277-1711378365623/node_modules/@ethersproject-xdc/hash" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wordlists-5.7.0-eafc2a13-cd67-4bf6-9256-aec79a731277-1711378365623/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/properties" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wordlists-5.7.0-eafc2a13-cd67-4bf6-9256-aec79a731277-1711378365623/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/strings" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wordlists-5.7.0-eafc2a13-cd67-4bf6-9256-aec79a731277-1711378365623/node_modules/@ethersproject-xdc/strings" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wordlists-5.7.0-007f87de-a764-481c-a766-8c2bd6c91860-1717523642499/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/hash" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wordlists-5.7.0-007f87de-a764-481c-a766-8c2bd6c91860-1717523642499/node_modules/@ethersproject-xdc/hash" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wordlists-5.7.0-007f87de-a764-481c-a766-8c2bd6c91860-1717523642499/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wordlists-5.7.0-007f87de-a764-481c-a766-8c2bd6c91860-1717523642499/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wordlists-5.7.0-007f87de-a764-481c-a766-8c2bd6c91860-1717523642499/node_modules/@ethersproject-xdc/strings" "@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.0.12", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.4.0", "@ethersproject/abi@^5.5.0", "@ethersproject/abi@^5.6.3", "@ethersproject/abi@^5.7.0": version "5.7.0" @@ -2103,6 +2136,11 @@ dependencies: keccak "^3.0.0" +"@fleet-sdk/common@^0.3.4": + version "0.3.4" + resolved "https://registry.yarnpkg.com/@fleet-sdk/common/-/common-0.3.4.tgz#bd343ae03171b681444c51cc81e6a9021d660d1f" + integrity sha512-FzrjElAy2hmxuXkFnTITGQKS7tsO9DIqyN7a1ki5T/REdTAHgZX3LseZUf0zuzjH21arez81kAnNYU+yBOJtRg== + "@graphql-tools/batch-execute@8.5.1": version "8.5.1" resolved "https://registry.yarnpkg.com/@graphql-tools/batch-execute/-/batch-execute-8.5.1.tgz#fa3321d58c64041650be44250b1ebc3aab0ba7a9" @@ -7133,6 +7171,11 @@ crypto-browserify@3.12.0: randombytes "^2.0.0" randomfill "^1.0.3" +crypto-js@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.2.0.tgz#4d931639ecdfd12ff80e8186dba6af2c2e856631" + integrity sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q== + cssfilter@0.0.10: version "0.0.10" resolved "https://registry.yarnpkg.com/cssfilter/-/cssfilter-0.0.10.tgz#c6d2672632a2e5c83e013e6864a42ce8defd20ae" @@ -7660,6 +7703,21 @@ env-paths@^2.2.0, env-paths@^2.2.1: resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== +ergo-lib-wasm-browser@0.20.1, ergo-lib-wasm-browser@^0.20.1: + version "0.20.1" + resolved "https://registry.yarnpkg.com/ergo-lib-wasm-browser/-/ergo-lib-wasm-browser-0.20.1.tgz#68097ba6ddf464447866066c9c3f3d960651af7e" + integrity sha512-g324oXm9kdNphqVuiIzb1lWpawASp7zihcqc8wmr+/xwB8RBSEV+IBwAu4RYMRHNwlwffsPOtKvk+lRpxUFVxQ== + +ergo-lib-wasm-nodejs@0.20.1, ergo-lib-wasm-nodejs@^0.20.1: + version "0.20.1" + resolved "https://registry.yarnpkg.com/ergo-lib-wasm-nodejs/-/ergo-lib-wasm-nodejs-0.20.1.tgz#390802910290c37e83c5316028751ea5e4b41e79" + integrity sha512-2jGQ21HWQdsA9hOXr2DJS7iq32uIQHL45hxfNJ1VnYRUbVkQRpBWB7PRFKZvlIlZT6dIifcg8IacF6hqBOfB2g== + +ergo-lib-wasm-nodejs@^0.22.0: + version "0.22.0" + resolved "https://registry.yarnpkg.com/ergo-lib-wasm-nodejs/-/ergo-lib-wasm-nodejs-0.22.0.tgz#e482e645f72cf97d1b467624968c811e41b8b3c8" + integrity sha512-eyVIUcEakeBVzFfLkS7CLxRxHO7VyP/V4NghIXHiY8WxFkd0qNFBUs+4IfpQWmv0SOnArm58PpottK2Ka9aYpg== + err-code@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" @@ -8019,6 +8077,11 @@ eslint@^8.57.0: strip-ansi "^6.0.1" text-table "^0.2.0" +esm-wallaby@^3.2.25: + version "3.2.30" + resolved "https://registry.yarnpkg.com/esm-wallaby/-/esm-wallaby-3.2.30.tgz#b249c5da1000d29b2ddbd05a9e5974c0c34d1432" + integrity sha512-Zq4K2y5co9tASH6GE87r01ZF1u3qV4iqbgoPt8B+OWWLaNaExv15T8SioufCPGNfugpEhFZiux3Wr7GNNzXWLQ== + espree@^9.6.0, espree@^9.6.1: version "9.6.1" resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" @@ -8186,36 +8249,36 @@ ethereumjs-util@^6.0.0, ethereumjs-util@^6.2.1: "ethers-xdc@file:./vendor/ethers-xdc": version "5.7.2" dependencies: - "@ethersproject-xdc/abi" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/abi" - "@ethersproject-xdc/abstract-provider" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/abstract-provider" - "@ethersproject-xdc/abstract-signer" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/abstract-signer" - "@ethersproject-xdc/address" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/address" - "@ethersproject-xdc/base64" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/base64" - "@ethersproject-xdc/basex" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/basex" - "@ethersproject-xdc/bignumber" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/constants" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/constants" - "@ethersproject-xdc/contracts" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/contracts" - "@ethersproject-xdc/hash" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/hash" - "@ethersproject-xdc/hdnode" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/hdnode" - "@ethersproject-xdc/json-wallets" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/json-wallets" - "@ethersproject-xdc/keccak256" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/keccak256" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/networks" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/networks" - "@ethersproject-xdc/pbkdf2" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/pbkdf2" - "@ethersproject-xdc/properties" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/providers" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/providers" - "@ethersproject-xdc/random" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/random" - "@ethersproject-xdc/rlp" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/rlp" - "@ethersproject-xdc/sha2" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/sha2" - "@ethersproject-xdc/signing-key" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/signing-key" - "@ethersproject-xdc/solidity" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/solidity" - "@ethersproject-xdc/strings" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/strings" - "@ethersproject-xdc/transactions" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/transactions" - "@ethersproject-xdc/units" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/units" - "@ethersproject-xdc/wallet" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/wallet" - "@ethersproject-xdc/web" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/web" - "@ethersproject-xdc/wordlists" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/wordlists" + "@ethersproject-xdc/abi" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-3e64181d-aa16-48f8-9296-de58541b8b12-1717523642473/node_modules/@ethersproject-xdc/abi" + "@ethersproject-xdc/abstract-provider" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-3e64181d-aa16-48f8-9296-de58541b8b12-1717523642473/node_modules/@ethersproject-xdc/abstract-provider" + "@ethersproject-xdc/abstract-signer" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-3e64181d-aa16-48f8-9296-de58541b8b12-1717523642473/node_modules/@ethersproject-xdc/abstract-signer" + "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-3e64181d-aa16-48f8-9296-de58541b8b12-1717523642473/node_modules/@ethersproject-xdc/address" + "@ethersproject-xdc/base64" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-3e64181d-aa16-48f8-9296-de58541b8b12-1717523642473/node_modules/@ethersproject-xdc/base64" + "@ethersproject-xdc/basex" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-3e64181d-aa16-48f8-9296-de58541b8b12-1717523642473/node_modules/@ethersproject-xdc/basex" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-3e64181d-aa16-48f8-9296-de58541b8b12-1717523642473/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-3e64181d-aa16-48f8-9296-de58541b8b12-1717523642473/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/constants" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-3e64181d-aa16-48f8-9296-de58541b8b12-1717523642473/node_modules/@ethersproject-xdc/constants" + "@ethersproject-xdc/contracts" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-3e64181d-aa16-48f8-9296-de58541b8b12-1717523642473/node_modules/@ethersproject-xdc/contracts" + "@ethersproject-xdc/hash" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-3e64181d-aa16-48f8-9296-de58541b8b12-1717523642473/node_modules/@ethersproject-xdc/hash" + "@ethersproject-xdc/hdnode" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-3e64181d-aa16-48f8-9296-de58541b8b12-1717523642473/node_modules/@ethersproject-xdc/hdnode" + "@ethersproject-xdc/json-wallets" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-3e64181d-aa16-48f8-9296-de58541b8b12-1717523642473/node_modules/@ethersproject-xdc/json-wallets" + "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-3e64181d-aa16-48f8-9296-de58541b8b12-1717523642473/node_modules/@ethersproject-xdc/keccak256" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-3e64181d-aa16-48f8-9296-de58541b8b12-1717523642473/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/networks" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-3e64181d-aa16-48f8-9296-de58541b8b12-1717523642473/node_modules/@ethersproject-xdc/networks" + "@ethersproject-xdc/pbkdf2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-3e64181d-aa16-48f8-9296-de58541b8b12-1717523642473/node_modules/@ethersproject-xdc/pbkdf2" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-3e64181d-aa16-48f8-9296-de58541b8b12-1717523642473/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/providers" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-3e64181d-aa16-48f8-9296-de58541b8b12-1717523642473/node_modules/@ethersproject-xdc/providers" + "@ethersproject-xdc/random" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-3e64181d-aa16-48f8-9296-de58541b8b12-1717523642473/node_modules/@ethersproject-xdc/random" + "@ethersproject-xdc/rlp" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-3e64181d-aa16-48f8-9296-de58541b8b12-1717523642473/node_modules/@ethersproject-xdc/rlp" + "@ethersproject-xdc/sha2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-3e64181d-aa16-48f8-9296-de58541b8b12-1717523642473/node_modules/@ethersproject-xdc/sha2" + "@ethersproject-xdc/signing-key" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-3e64181d-aa16-48f8-9296-de58541b8b12-1717523642473/node_modules/@ethersproject-xdc/signing-key" + "@ethersproject-xdc/solidity" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-3e64181d-aa16-48f8-9296-de58541b8b12-1717523642473/node_modules/@ethersproject-xdc/solidity" + "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-3e64181d-aa16-48f8-9296-de58541b8b12-1717523642473/node_modules/@ethersproject-xdc/strings" + "@ethersproject-xdc/transactions" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-3e64181d-aa16-48f8-9296-de58541b8b12-1717523642473/node_modules/@ethersproject-xdc/transactions" + "@ethersproject-xdc/units" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-3e64181d-aa16-48f8-9296-de58541b8b12-1717523642473/node_modules/@ethersproject-xdc/units" + "@ethersproject-xdc/wallet" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-3e64181d-aa16-48f8-9296-de58541b8b12-1717523642473/node_modules/@ethersproject-xdc/wallet" + "@ethersproject-xdc/web" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-3e64181d-aa16-48f8-9296-de58541b8b12-1717523642473/node_modules/@ethersproject-xdc/web" + "@ethersproject-xdc/wordlists" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-3e64181d-aa16-48f8-9296-de58541b8b12-1717523642473/node_modules/@ethersproject-xdc/wordlists" ethers@4.0.0-beta.3: version "4.0.0-beta.3" @@ -11431,7 +11494,7 @@ mathjs@^10.5.0: tiny-emitter "^2.1.0" typed-function "^2.1.0" -mathjs@^9.3.0: +mathjs@^9.3.0, mathjs@^9.4.4: version "9.5.2" resolved "https://registry.yarnpkg.com/mathjs/-/mathjs-9.5.2.tgz#e0f3279320dc6f49e45d99c4fcdd8b52231f0462" integrity sha512-c0erTq0GP503/Ch2OtDOAn50GIOsuxTMjmE00NI/vKJFSWrDaQHRjx6ai+16xYv70yBSnnpUgHZGNf9FR9IwmA== @@ -13158,6 +13221,11 @@ quipuswap-v3-sdk@^0.0.7: typescript "^4.4.3" yargs "^17.2.1" +ramda@0.27.1: + version "0.27.1" + resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.27.1.tgz#66fc2df3ef873874ffc2da6aa8984658abacf5c9" + integrity sha512-PgIdVpn5y5Yns8vqb8FzBUEYn98V3xcPgawAkkgj0YJ0qDsnHCiNmZYfOGMgOvoB0eWFLpYbhxUR3mxfDIMvpw== + randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" From d77bc69f9802fcd17ffcd1eacef2aba4e11608b0 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Wed, 5 Jun 2024 13:30:55 +0330 Subject: [PATCH 008/132] add[test]: add unit tests for ergo.config file --- test/chains/ergo/ergo.config.test.ts | 65 ++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 test/chains/ergo/ergo.config.test.ts diff --git a/test/chains/ergo/ergo.config.test.ts b/test/chains/ergo/ergo.config.test.ts new file mode 100644 index 0000000000..77baad056d --- /dev/null +++ b/test/chains/ergo/ergo.config.test.ts @@ -0,0 +1,65 @@ +import { getErgoConfig } from "../../../src/chains/ergo/ergo.config"; +import { ConfigManagerV2 } from "../../../src/services/config-manager-v2"; +import { NetworkPrefix } from "ergo-lib-wasm-nodejs"; + +describe('getErgoConfig', () => { + afterEach(() => { + // Clear all mocks after each test + jest.clearAllMocks() + }) + + it('Should return correct config for Mainnet', () => { + jest.spyOn(ConfigManagerV2.getInstance(), "get").mockReturnValueOnce('algorand.networks.Mainnet.nodeURL'); + jest.spyOn(ConfigManagerV2.getInstance(), "get").mockReturnValueOnce(1000); + jest.spyOn(ConfigManagerV2.getInstance(), "get").mockReturnValueOnce(2000); + + // Act + const res = getErgoConfig('Mainnet'); + + // Assert + expect(res).toEqual({ + network: { + name: 'Mainnet', + nodeURL: 'algorand.networks.Mainnet.nodeURL' + , + timeOut: 1000, + networkPrefix: NetworkPrefix.Mainnet, + minTxFee: 2000, + maxLRUCacheInstances: 10, + utxosLimit: 100 + } + }); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledTimes(3); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith('algorand.networks.Mainnet.nodeURL'); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith('ergo.networks.Mainnet.timeOut'); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith('algorand.networks.Mainnet.minTxFee'); + }); + + it('Should return correct config for Testnet', () => { + // Mocking the get method of ConfigManagerV2 + jest.spyOn(ConfigManagerV2.getInstance(), "get").mockReturnValueOnce('algorand.networks.Testnet.nodeURL'); + jest.spyOn(ConfigManagerV2.getInstance(), "get").mockReturnValueOnce(1000); + jest.spyOn(ConfigManagerV2.getInstance(), "get").mockReturnValueOnce(2000); + + // Act + const res = getErgoConfig('Testnet'); + + // Assert + expect(res).toEqual({ + network: { + name: 'Testnet', + nodeURL: 'algorand.networks.Testnet.nodeURL' + , + timeOut: 1000, + networkPrefix: NetworkPrefix.Testnet, + minTxFee: 2000, + maxLRUCacheInstances: 10, + utxosLimit: 100 + } + }) + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledTimes(3); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith('algorand.networks.Testnet.nodeURL'); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith('ergo.networks.Testnet.timeOut'); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith('algorand.networks.Testnet.minTxFee'); + }); +}); From 72628616e783994c1833dbdeed2f22724aef2571 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Sat, 8 Jun 2024 15:46:14 +0330 Subject: [PATCH 009/132] add[unit-test]: Implement unit tests for "request" and "getTokens" methods of DexService --- test/chains/ergo/dex.service.test.ts | 98 ++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 test/chains/ergo/dex.service.test.ts diff --git a/test/chains/ergo/dex.service.test.ts b/test/chains/ergo/dex.service.test.ts new file mode 100644 index 0000000000..df8a68d1b9 --- /dev/null +++ b/test/chains/ergo/dex.service.test.ts @@ -0,0 +1,98 @@ +import axios from 'axios'; +import { DexService } from '../../../src/chains/ergo/dex.service'; +import { DEXTokensResponse } from '../../../src/chains/ergo/interfaces/dex.interface'; + +// Mocking axios to intercept HTTP requests and return controlled responses +jest.mock('axios'); + +describe('DexService', () => { + // Define constants for baseURL and timeout + const baseURL = 'https://example.com'; + const timeout = 5000; + // Initialize DexService instance + let dexService: DexService = new DexService(baseURL, timeout); + + test('should initialize with given baseURL and timeout', () => { + // Assert that the dexURL and timeout properties are correctly set + expect(dexService['dexURL']).toBe(baseURL); + expect(dexService['timeout']).toBe(timeout); + }); + + describe('request', () => { + // Define default parameters for the request method + const method = 'GET'; + const url = '/test-endpoint'; + const headers = { 'Content-Type': 'application/json' }; + const body = { key: 'value' }; + + test('should make a GET request with correct parameters', async () => { + + // Arrange: Mock the axios response + const mockResponse = { data: { name: 'test' } }; + (axios as any).mockResolvedValue(mockResponse); + + // Act: Call the private request method with GET parameters + const response = await dexService['request'](method, url, headers); + + // Assert: Check if axios was called with the correct configuration + expect(axios).toHaveBeenCalledWith({ + baseURL, + url, + method, + headers, + timeout, + }); + // Assert: Check if the response is as expected + expect(response).toEqual({ name: 'test' }); + }); + + test('should make a POST request with correct parameters', async () => { + + // Arrange: Change method to POST and mock the axios response + const method = 'POST'; + const mockResponse = { data: { name: 'test' } }; + (axios as any).mockResolvedValue(mockResponse); + + // Act: Call the private request method with POST parameters + const response = await dexService['request'](method, url, headers, body); + + // Assert: Check if axios was called with the correct configuration + expect(axios).toHaveBeenCalledWith({ + baseURL, + url, + method, + headers, + timeout, + body, + }); + // Assert: Check if the response is as expected + expect(response).toEqual({ name: 'test' }); + }); + }); + + describe('getTokens', () => { + test('should call request method with correct parameters', async () => { + + // Arrange: Mock the response of the request method + const mockResponse: DEXTokensResponse = { + tokens: [{ + address: '1', name: 'Token1', + decimals: 0, + ticker: '', + logoURI: '', + project: '', + description: '' + }] + }; + jest.spyOn(dexService as any, 'request').mockResolvedValue(mockResponse); + + // Act: Call the getTokens method + const response = await dexService.getTokens(); + + // Assert: Check if the request method was called with the correct parameters + expect(dexService['request']).toHaveBeenCalledWith('GET', '/ergo-token-list.json'); + // Assert: Check if the response from getTokens is as expected + expect(response).toEqual(mockResponse); + }); + }); +}); From 27d41263fbda20d072b8168a958f24c877c8aa5b Mon Sep 17 00:00:00 2001 From: satiparpar Date: Sun, 9 Jun 2024 09:21:34 +0330 Subject: [PATCH 010/132] update [unit-test]: update unit tests for "getErgoConfig" function, based on new configurations --- test/chains/ergo/dex.service.test.ts | 8 ++-- test/chains/ergo/ergo.config.test.ts | 61 ++++++++++++++++++---------- 2 files changed, 44 insertions(+), 25 deletions(-) diff --git a/test/chains/ergo/dex.service.test.ts b/test/chains/ergo/dex.service.test.ts index df8a68d1b9..8eb9380771 100644 --- a/test/chains/ergo/dex.service.test.ts +++ b/test/chains/ergo/dex.service.test.ts @@ -12,7 +12,7 @@ describe('DexService', () => { // Initialize DexService instance let dexService: DexService = new DexService(baseURL, timeout); - test('should initialize with given baseURL and timeout', () => { + it('Should initialize with given baseURL and timeout', () => { // Assert that the dexURL and timeout properties are correctly set expect(dexService['dexURL']).toBe(baseURL); expect(dexService['timeout']).toBe(timeout); @@ -25,7 +25,7 @@ describe('DexService', () => { const headers = { 'Content-Type': 'application/json' }; const body = { key: 'value' }; - test('should make a GET request with correct parameters', async () => { + it('Should make a GET request with correct parameters', async () => { // Arrange: Mock the axios response const mockResponse = { data: { name: 'test' } }; @@ -46,7 +46,7 @@ describe('DexService', () => { expect(response).toEqual({ name: 'test' }); }); - test('should make a POST request with correct parameters', async () => { + it('Should make a POST request with correct parameters', async () => { // Arrange: Change method to POST and mock the axios response const method = 'POST'; @@ -71,7 +71,7 @@ describe('DexService', () => { }); describe('getTokens', () => { - test('should call request method with correct parameters', async () => { + it('Should call request method with correct parameters', async () => { // Arrange: Mock the response of the request method const mockResponse: DEXTokensResponse = { diff --git a/test/chains/ergo/ergo.config.test.ts b/test/chains/ergo/ergo.config.test.ts index 77baad056d..d5e9fb98f2 100644 --- a/test/chains/ergo/ergo.config.test.ts +++ b/test/chains/ergo/ergo.config.test.ts @@ -2,64 +2,83 @@ import { getErgoConfig } from "../../../src/chains/ergo/ergo.config"; import { ConfigManagerV2 } from "../../../src/services/config-manager-v2"; import { NetworkPrefix } from "ergo-lib-wasm-nodejs"; +// Define the test suite for the getErgoConfig function describe('getErgoConfig', () => { + + // After each test, clear all mocks to ensure no interference between tests afterEach(() => { - // Clear all mocks after each test jest.clearAllMocks() }) + // Test case for verifying the configuration returned for the Mainnet it('Should return correct config for Mainnet', () => { - jest.spyOn(ConfigManagerV2.getInstance(), "get").mockReturnValueOnce('algorand.networks.Mainnet.nodeURL'); + + // Mock the get method of ConfigManagerV2 to return specific values for Mainnet + jest.spyOn(ConfigManagerV2.getInstance(), "get").mockReturnValueOnce('ergo.networks.Mainnet.nodeURL'); + jest.spyOn(ConfigManagerV2.getInstance(), "get").mockReturnValueOnce('ergo.networks.Mainnet.explorerURL'); + jest.spyOn(ConfigManagerV2.getInstance(), "get").mockReturnValueOnce('ergo.networks.Mainnet.explorerDEXURL'); jest.spyOn(ConfigManagerV2.getInstance(), "get").mockReturnValueOnce(1000); jest.spyOn(ConfigManagerV2.getInstance(), "get").mockReturnValueOnce(2000); - // Act + // Call the function to be tested with 'Mainnet' as the argument const res = getErgoConfig('Mainnet'); - // Assert + // Assert that the returned configuration matches the expected values for Mainnet expect(res).toEqual({ network: { name: 'Mainnet', - nodeURL: 'algorand.networks.Mainnet.nodeURL' - , + nodeURL: 'ergo.networks.Mainnet.nodeURL', + explorerURL: 'ergo.networks.Mainnet.explorerURL', + explorerDEXURL: 'ergo.networks.Mainnet.explorerDEXURL', timeOut: 1000, networkPrefix: NetworkPrefix.Mainnet, minTxFee: 2000, maxLRUCacheInstances: 10, - utxosLimit: 100 + utxosLimit: 100, + poolLimit: 100 } }); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledTimes(3); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith('algorand.networks.Mainnet.nodeURL'); + // Verify that the get method was called exactly five times with the expected arguments + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledTimes(5); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith('ergo.networks.Mainnet.nodeURL'); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith('ergo.networks.Mainnet.explorerURL'); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith('ergo.networks.Mainnet.explorerDEXURL'); expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith('ergo.networks.Mainnet.timeOut'); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith('algorand.networks.Mainnet.minTxFee'); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith('ergo.networks.Mainnet.minTxFee'); }); + // Test case for verifying the configuration returned for the Testnet it('Should return correct config for Testnet', () => { - // Mocking the get method of ConfigManagerV2 - jest.spyOn(ConfigManagerV2.getInstance(), "get").mockReturnValueOnce('algorand.networks.Testnet.nodeURL'); + jest.spyOn(ConfigManagerV2.getInstance(), "get").mockReturnValueOnce('ergo.networks.Testnet.nodeURL'); + jest.spyOn(ConfigManagerV2.getInstance(), "get").mockReturnValueOnce('ergo.networks.Testnet.explorerURL'); + jest.spyOn(ConfigManagerV2.getInstance(), "get").mockReturnValueOnce('ergo.networks.Testnet.explorerDEXURL'); jest.spyOn(ConfigManagerV2.getInstance(), "get").mockReturnValueOnce(1000); jest.spyOn(ConfigManagerV2.getInstance(), "get").mockReturnValueOnce(2000); - // Act + // Call the function to be tested with 'Testnet' as the argument const res = getErgoConfig('Testnet'); - // Assert + // Assert that the returned configuration matches the expected values for Testnet expect(res).toEqual({ network: { name: 'Testnet', - nodeURL: 'algorand.networks.Testnet.nodeURL' - , + nodeURL: 'ergo.networks.Testnet.nodeURL', + explorerURL: 'ergo.networks.Testnet.explorerURL', + explorerDEXURL: 'ergo.networks.Testnet.explorerDEXURL', timeOut: 1000, networkPrefix: NetworkPrefix.Testnet, minTxFee: 2000, maxLRUCacheInstances: 10, - utxosLimit: 100 + utxosLimit: 100, + poolLimit: 100 } - }) - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledTimes(3); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith('algorand.networks.Testnet.nodeURL'); + }); + // Verify that the get method was called exactly five times with the expected arguments + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledTimes(5); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith('ergo.networks.Testnet.nodeURL'); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith('ergo.networks.Testnet.explorerURL'); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith('ergo.networks.Testnet.explorerDEXURL'); expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith('ergo.networks.Testnet.timeOut'); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith('algorand.networks.Testnet.minTxFee'); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith('ergo.networks.Testnet.minTxFee'); }); }); From 5463f9d0675407f18eb3671d8b38db4c930478e7 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Sun, 9 Jun 2024 10:08:59 +0330 Subject: [PATCH 011/132] add [unit-test]: Implement unit tests for "NodeService" => "request" method --- test/chains/ergo/dex.service.test.ts | 40 ++++-- test/chains/ergo/ergo.config.test.ts | 177 +++++++++++++++----------- test/chains/ergo/node.service.test.ts | 76 +++++++++++ 3 files changed, 206 insertions(+), 87 deletions(-) create mode 100644 test/chains/ergo/node.service.test.ts diff --git a/test/chains/ergo/dex.service.test.ts b/test/chains/ergo/dex.service.test.ts index 8eb9380771..bfcff20b1b 100644 --- a/test/chains/ergo/dex.service.test.ts +++ b/test/chains/ergo/dex.service.test.ts @@ -5,19 +5,24 @@ import { DEXTokensResponse } from '../../../src/chains/ergo/interfaces/dex.inter // Mocking axios to intercept HTTP requests and return controlled responses jest.mock('axios'); +// Describe the test suite for the NodeService class describe('DexService', () => { // Define constants for baseURL and timeout const baseURL = 'https://example.com'; const timeout = 5000; + // Initialize DexService instance - let dexService: DexService = new DexService(baseURL, timeout); + const dexService: DexService = new DexService(baseURL, timeout); + // Test case to check if DexService is defined and its properties are set correctly it('Should initialize with given baseURL and timeout', () => { - // Assert that the dexURL and timeout properties are correctly set + // Assert: Check if the dexURL and timeout properties are correctly set and instance is defined + expect(dexService).toBeDefined(); expect(dexService['dexURL']).toBe(baseURL); expect(dexService['timeout']).toBe(timeout); }); + // Describe the test suite for the private request method of NodeService describe('request', () => { // Define default parameters for the request method const method = 'GET'; @@ -25,8 +30,8 @@ describe('DexService', () => { const headers = { 'Content-Type': 'application/json' }; const body = { key: 'value' }; + // Test case for making a GET request with correct parameters it('Should make a GET request with correct parameters', async () => { - // Arrange: Mock the axios response const mockResponse = { data: { name: 'test' } }; (axios as any).mockResolvedValue(mockResponse); @@ -46,8 +51,8 @@ describe('DexService', () => { expect(response).toEqual({ name: 'test' }); }); + // Test case for making a POST request with correct parameters it('Should make a POST request with correct parameters', async () => { - // Arrange: Change method to POST and mock the axios response const method = 'POST'; const mockResponse = { data: { name: 'test' } }; @@ -70,19 +75,23 @@ describe('DexService', () => { }); }); + // Describe the test suite for the getTokens method of NodeService describe('getTokens', () => { + // Test case to call getTokens method and check return value and function input arguments it('Should call request method with correct parameters', async () => { - // Arrange: Mock the response of the request method const mockResponse: DEXTokensResponse = { - tokens: [{ - address: '1', name: 'Token1', - decimals: 0, - ticker: '', - logoURI: '', - project: '', - description: '' - }] + tokens: [ + { + address: '1', + name: 'Token1', + decimals: 0, + ticker: '', + logoURI: '', + project: '', + description: '', + }, + ], }; jest.spyOn(dexService as any, 'request').mockResolvedValue(mockResponse); @@ -90,7 +99,10 @@ describe('DexService', () => { const response = await dexService.getTokens(); // Assert: Check if the request method was called with the correct parameters - expect(dexService['request']).toHaveBeenCalledWith('GET', '/ergo-token-list.json'); + expect(dexService['request']).toHaveBeenCalledWith( + 'GET', + '/ergo-token-list.json', + ); // Assert: Check if the response from getTokens is as expected expect(response).toEqual(mockResponse); }); diff --git a/test/chains/ergo/ergo.config.test.ts b/test/chains/ergo/ergo.config.test.ts index d5e9fb98f2..72b979b97b 100644 --- a/test/chains/ergo/ergo.config.test.ts +++ b/test/chains/ergo/ergo.config.test.ts @@ -1,84 +1,115 @@ -import { getErgoConfig } from "../../../src/chains/ergo/ergo.config"; -import { ConfigManagerV2 } from "../../../src/services/config-manager-v2"; -import { NetworkPrefix } from "ergo-lib-wasm-nodejs"; +import { getErgoConfig } from '../../../src/chains/ergo/ergo.config'; +import { ConfigManagerV2 } from '../../../src/services/config-manager-v2'; +import { NetworkPrefix } from 'ergo-lib-wasm-nodejs'; // Define the test suite for the getErgoConfig function describe('getErgoConfig', () => { + // After each test, clear all mocks to ensure no interference between tests + afterEach(() => { + jest.clearAllMocks(); + }); - // After each test, clear all mocks to ensure no interference between tests - afterEach(() => { - jest.clearAllMocks() - }) + // Test case for verifying the configuration returned for the Mainnet + it('Should return correct config for Mainnet', () => { + // Arrange: Mock the get method of ConfigManagerV2 to return specific values for Mainnet + jest + .spyOn(ConfigManagerV2.getInstance(), 'get') + .mockReturnValueOnce('ergo.networks.Mainnet.nodeURL'); + jest + .spyOn(ConfigManagerV2.getInstance(), 'get') + .mockReturnValueOnce('ergo.networks.Mainnet.explorerURL'); + jest + .spyOn(ConfigManagerV2.getInstance(), 'get') + .mockReturnValueOnce('ergo.networks.Mainnet.explorerDEXURL'); + jest.spyOn(ConfigManagerV2.getInstance(), 'get').mockReturnValueOnce(1000); + jest.spyOn(ConfigManagerV2.getInstance(), 'get').mockReturnValueOnce(2000); - // Test case for verifying the configuration returned for the Mainnet - it('Should return correct config for Mainnet', () => { + // Act: Call the function to be tested with 'Mainnet' as the argument + const res = getErgoConfig('Mainnet'); - // Mock the get method of ConfigManagerV2 to return specific values for Mainnet - jest.spyOn(ConfigManagerV2.getInstance(), "get").mockReturnValueOnce('ergo.networks.Mainnet.nodeURL'); - jest.spyOn(ConfigManagerV2.getInstance(), "get").mockReturnValueOnce('ergo.networks.Mainnet.explorerURL'); - jest.spyOn(ConfigManagerV2.getInstance(), "get").mockReturnValueOnce('ergo.networks.Mainnet.explorerDEXURL'); - jest.spyOn(ConfigManagerV2.getInstance(), "get").mockReturnValueOnce(1000); - jest.spyOn(ConfigManagerV2.getInstance(), "get").mockReturnValueOnce(2000); - - // Call the function to be tested with 'Mainnet' as the argument - const res = getErgoConfig('Mainnet'); - - // Assert that the returned configuration matches the expected values for Mainnet - expect(res).toEqual({ - network: { - name: 'Mainnet', - nodeURL: 'ergo.networks.Mainnet.nodeURL', - explorerURL: 'ergo.networks.Mainnet.explorerURL', - explorerDEXURL: 'ergo.networks.Mainnet.explorerDEXURL', - timeOut: 1000, - networkPrefix: NetworkPrefix.Mainnet, - minTxFee: 2000, - maxLRUCacheInstances: 10, - utxosLimit: 100, - poolLimit: 100 - } - }); - // Verify that the get method was called exactly five times with the expected arguments - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledTimes(5); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith('ergo.networks.Mainnet.nodeURL'); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith('ergo.networks.Mainnet.explorerURL'); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith('ergo.networks.Mainnet.explorerDEXURL'); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith('ergo.networks.Mainnet.timeOut'); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith('ergo.networks.Mainnet.minTxFee'); + // Assert: Check that the returned configuration matches the expected values for Mainnet + expect(res).toEqual({ + network: { + name: 'Mainnet', + nodeURL: 'ergo.networks.Mainnet.nodeURL', + explorerURL: 'ergo.networks.Mainnet.explorerURL', + explorerDEXURL: 'ergo.networks.Mainnet.explorerDEXURL', + timeOut: 1000, + networkPrefix: NetworkPrefix.Mainnet, + minTxFee: 2000, + maxLRUCacheInstances: 10, + utxosLimit: 100, + poolLimit: 100, + }, }); + // Assert: Verify that the get method was called exactly five times with the expected arguments + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledTimes(5); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( + 'ergo.networks.Mainnet.nodeURL', + ); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( + 'ergo.networks.Mainnet.explorerURL', + ); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( + 'ergo.networks.Mainnet.explorerDEXURL', + ); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( + 'ergo.networks.Mainnet.timeOut', + ); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( + 'ergo.networks.Mainnet.minTxFee', + ); + }); + + // Test case for verifying the configuration returned for the Testnet + it('Should return correct config for Testnet', () => { + // Arrange: Mock the get method of ConfigManagerV2 to return specific values for Testnet + jest + .spyOn(ConfigManagerV2.getInstance(), 'get') + .mockReturnValueOnce('ergo.networks.Testnet.nodeURL'); + jest + .spyOn(ConfigManagerV2.getInstance(), 'get') + .mockReturnValueOnce('ergo.networks.Testnet.explorerURL'); + jest + .spyOn(ConfigManagerV2.getInstance(), 'get') + .mockReturnValueOnce('ergo.networks.Testnet.explorerDEXURL'); + jest.spyOn(ConfigManagerV2.getInstance(), 'get').mockReturnValueOnce(1000); + jest.spyOn(ConfigManagerV2.getInstance(), 'get').mockReturnValueOnce(2000); - // Test case for verifying the configuration returned for the Testnet - it('Should return correct config for Testnet', () => { - jest.spyOn(ConfigManagerV2.getInstance(), "get").mockReturnValueOnce('ergo.networks.Testnet.nodeURL'); - jest.spyOn(ConfigManagerV2.getInstance(), "get").mockReturnValueOnce('ergo.networks.Testnet.explorerURL'); - jest.spyOn(ConfigManagerV2.getInstance(), "get").mockReturnValueOnce('ergo.networks.Testnet.explorerDEXURL'); - jest.spyOn(ConfigManagerV2.getInstance(), "get").mockReturnValueOnce(1000); - jest.spyOn(ConfigManagerV2.getInstance(), "get").mockReturnValueOnce(2000); - - // Call the function to be tested with 'Testnet' as the argument - const res = getErgoConfig('Testnet'); + // Act: Call the function to be tested with 'Testnet' as the argument + const res = getErgoConfig('Testnet'); - // Assert that the returned configuration matches the expected values for Testnet - expect(res).toEqual({ - network: { - name: 'Testnet', - nodeURL: 'ergo.networks.Testnet.nodeURL', - explorerURL: 'ergo.networks.Testnet.explorerURL', - explorerDEXURL: 'ergo.networks.Testnet.explorerDEXURL', - timeOut: 1000, - networkPrefix: NetworkPrefix.Testnet, - minTxFee: 2000, - maxLRUCacheInstances: 10, - utxosLimit: 100, - poolLimit: 100 - } - }); - // Verify that the get method was called exactly five times with the expected arguments - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledTimes(5); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith('ergo.networks.Testnet.nodeURL'); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith('ergo.networks.Testnet.explorerURL'); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith('ergo.networks.Testnet.explorerDEXURL'); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith('ergo.networks.Testnet.timeOut'); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith('ergo.networks.Testnet.minTxFee'); + // Assert: Check that the returned configuration matches the expected values for Testnet + expect(res).toEqual({ + network: { + name: 'Testnet', + nodeURL: 'ergo.networks.Testnet.nodeURL', + explorerURL: 'ergo.networks.Testnet.explorerURL', + explorerDEXURL: 'ergo.networks.Testnet.explorerDEXURL', + timeOut: 1000, + networkPrefix: NetworkPrefix.Testnet, + minTxFee: 2000, + maxLRUCacheInstances: 10, + utxosLimit: 100, + poolLimit: 100, + }, }); + // Assert: Verify that the get method was called exactly five times with the expected arguments + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledTimes(5); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( + 'ergo.networks.Testnet.nodeURL', + ); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( + 'ergo.networks.Testnet.explorerURL', + ); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( + 'ergo.networks.Testnet.explorerDEXURL', + ); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( + 'ergo.networks.Testnet.timeOut', + ); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( + 'ergo.networks.Testnet.minTxFee', + ); + }); }); diff --git a/test/chains/ergo/node.service.test.ts b/test/chains/ergo/node.service.test.ts new file mode 100644 index 0000000000..4376c5eab5 --- /dev/null +++ b/test/chains/ergo/node.service.test.ts @@ -0,0 +1,76 @@ +import axios from 'axios'; + +import { NodeService } from '../../../src/chains/ergo/node.service'; + +// Mock axios to avoid making real HTTP requests during tests +jest.mock('axios'); + +// Describe the test suite for the NodeService class +describe('NodeService', () => { + // Define constants for baseURL and timeout + const baseURL = 'https://example.com'; + const timeout = 5000; + + // Initialize NodeService instance + const nodeService: NodeService = new NodeService(baseURL, timeout); + + // Test case to check if NodeService is defined and its properties are set correctly + it('Should be defined and and set nodeURL & timeout correctly', () => { + // Assert: Check if the nodeURL and timeout properties are correctly set and instance is defined + expect(nodeService).toBeDefined(); + expect(nodeService['nodeURL']).toEqual('https://example.com'); + expect(nodeService['timeout']).toEqual(5000); + }); + + describe('request', () => { + // Define default parameters for the request method + const method = 'GET'; + const url = '/test-endpoint'; + const headers = { 'Content-Type': 'application/json' }; + const body = { key: 'value' }; + + // Test case for making a GET request with correct parameters + it('Should make a GET request with correct parameters', async () => { + // Arrange: Mock the axios response + const mockResponse = { data: { name: 'test' } }; + (axios as any).mockResolvedValue(mockResponse); + + // Act: Call the private request method with GET parameters + const response = await nodeService['request'](method, url, headers); + + // Assert: Check if axios was called with the correct configuration + expect(axios).toHaveBeenCalledWith({ + baseURL, + url, + method, + headers, + timeout, + }); + // Assert: Check if the response is as expected + expect(response).toEqual({ name: 'test' }); + }); + + // Test case for making a POST request with correct parameters + it('Should make a POST request with correct parameters', async () => { + // Arrange: Change method to POST and mock the axios response + const method = 'POST'; + const mockResponse = { data: { name: 'test' } }; + (axios as any).mockResolvedValue(mockResponse); + + // Act: Call the private request method with POST parameters + const response = await nodeService['request'](method, url, headers, body); + + // Assert: Check if axios was called with the correct configuration + expect(axios).toHaveBeenCalledWith({ + baseURL, + url, + method, + headers, + timeout, + body, + }); + // Assert: Check if the response is as expected + expect(response).toEqual({ name: 'test' }); + }); + }); +}); From 369fed6673d688eb4d1aed7ab42186013dff0bf4 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Sun, 9 Jun 2024 11:14:09 +0330 Subject: [PATCH 012/132] add [unit-test]: Implement unit tests for "NodeService" => "getNetworkHeight" & "getUnspentBoxesByAddress" methods --- test/chains/ergo/node.service.test.ts | 60 ++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/test/chains/ergo/node.service.test.ts b/test/chains/ergo/node.service.test.ts index 4376c5eab5..2451444df9 100644 --- a/test/chains/ergo/node.service.test.ts +++ b/test/chains/ergo/node.service.test.ts @@ -1,6 +1,6 @@ import axios from 'axios'; - import { NodeService } from '../../../src/chains/ergo/node.service'; +import { NodeInfoResponse } from '../../../src/chains/ergo/interfaces/node.interface'; // Mock axios to avoid making real HTTP requests during tests jest.mock('axios'); @@ -14,6 +14,11 @@ describe('NodeService', () => { // Initialize NodeService instance const nodeService: NodeService = new NodeService(baseURL, timeout); + // After each test, clear all mocks to ensure no interference between tests + afterEach(() => { + jest.clearAllMocks(); + }); + // Test case to check if NodeService is defined and its properties are set correctly it('Should be defined and and set nodeURL & timeout correctly', () => { // Assert: Check if the nodeURL and timeout properties are correctly set and instance is defined @@ -73,4 +78,57 @@ describe('NodeService', () => { expect(response).toEqual({ name: 'test' }); }); }); + + // Describe the test suite for the getNetworkHeight method + describe('getNetworkHeight', () => { + // Define a test case to check if getNetworkHeight is called with the correct parameters and returns the correct value + it('should call getNetworkHeight with correct parameters and returns the correct value', async () => { + // Define a mock response with fullHeight property + const res: NodeInfoResponse = { fullHeight: 100 }; + // Mock the private request method of nodeService to resolve with the mock response + jest.spyOn(nodeService as any, 'request').mockResolvedValue(res); + + // Call the getNetworkHeight method and store the result + const networkHeight = await nodeService.getNetworkHeight(); + + // Assert: Check if the returned network height is correct + expect(networkHeight).toEqual(100); + // Assert: Check if the private request method was called exactly once + expect(nodeService['request']).toHaveBeenCalledTimes(1); + // Assert: Check if the private request method was called with the correct HTTP method and URL + expect(nodeService['request']).toHaveBeenCalledWith('GET', '/info'); + }); + }); + + // Describe the test suite for the getUnspentBoxesByAddress method + describe('getUnspentBoxesByAddress', () => { + // Define constants for address, offset, and limit + const address = 'box-number-1.com'; + const offset = 10; + const limit = 20; + + // Define a test case to check if getUnspentBoxesByAddress is called with the correct parameters and returns the correct value + it('Should call getUnspentBoxesByAddress method with correct parameters and returns the correct value', async () => { + // Mock the private request method of nodeService to resolve with an empty data object + jest.spyOn(nodeService as any, 'request').mockResolvedValue({ data: {} }); + // Call the getUnspentBoxesByAddress method with the defined address, offset, and limit, and store the result + const unspentBoxesByAddress = await nodeService.getUnspentBoxesByAddress( + address, + offset, + limit, + ); + + // Assert: Check if the returned value matches the mock response + expect(unspentBoxesByAddress).toEqual({ data: {} }); + // Assert: Check if the private request method was called exactly once + expect(nodeService['request']).toHaveBeenCalledTimes(1); + // Assert: Check if the private request method was called with the correct HTTP method, URL, headers, and body + expect(nodeService['request']).toHaveBeenCalledWith( + 'POST', + `/blockchain/box/unspent/byAddress?offset=10&limit=20&sortDirection=desc`, + { 'Content-Type': 'text/plain' }, + 'box-number-1.com', + ); + }); + }); }); From 3c107c5cfa92ec8f0b2461ef27e2cd48cd1a92b4 Mon Sep 17 00:00:00 2001 From: ahmadyazdanii Date: Sun, 9 Jun 2024 14:28:17 +0330 Subject: [PATCH 013/132] update [ergo]: add dex service components doc --- src/chains/ergo/dex.service.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/chains/ergo/dex.service.ts b/src/chains/ergo/dex.service.ts index d21a7b3fa6..5dbf1e9842 100644 --- a/src/chains/ergo/dex.service.ts +++ b/src/chains/ergo/dex.service.ts @@ -1,6 +1,12 @@ import axios from 'axios'; import { DEXTokensResponse } from './interfaces/dex.interface'; +/** + * This class allows you to access elements of a DEX + * @class + * @param {string} dexURL - The DEX's base URL + * @param {number} [timeout=5000] - Timeout + */ export class DexService { constructor( private dexURL: string, @@ -25,6 +31,11 @@ export class DexService { return response.data; } + /** + * This function allow you to get Ergo's token list from DEX + * @function + * @async + */ async getTokens() { return this.request('GET', '/ergo-token-list.json'); } From ce08b2758588bc30f6510c9bf96ad5f781399da0 Mon Sep 17 00:00:00 2001 From: ahmadyazdanii Date: Sun, 9 Jun 2024 16:09:56 +0330 Subject: [PATCH 014/132] update [ergo]: add ergo config docs --- src/chains/ergo/ergo.config.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/chains/ergo/ergo.config.ts b/src/chains/ergo/ergo.config.ts index 469336ff3a..2da63f956d 100644 --- a/src/chains/ergo/ergo.config.ts +++ b/src/chains/ergo/ergo.config.ts @@ -2,6 +2,12 @@ import { ConfigManagerV2 } from '../../services/config-manager-v2'; import { NetworkPrefix } from 'ergo-lib-wasm-nodejs'; import { ErgoConfig } from './interfaces/ergo.interface'; +/** + * This function return configuration for Ergo + * @param {string} network - mainnet or testnet + * @returns ErgoConfig + * @function + */ export function getErgoConfig(network: string): ErgoConfig { return { network: { From 8e73760a403e960d29576e3a15ab7b1912a96cea Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Mon, 10 Jun 2024 10:47:00 +0330 Subject: [PATCH 015/132] add prover interface --- src/chains/ergo/ergo.interface.ts | 34 ++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/chains/ergo/ergo.interface.ts b/src/chains/ergo/ergo.interface.ts index d81ada64b2..95540b500e 100644 --- a/src/chains/ergo/ergo.interface.ts +++ b/src/chains/ergo/ergo.interface.ts @@ -1,12 +1,44 @@ -import {Wallet} from "ergo-lib-wasm-nodejs"; +import {ErgoBoxes, ErgoStateContext, UnsignedTransaction, Wallet} from "ergo-lib-wasm-nodejs"; import {ErgoTreeHex, NonMandatoryRegisters} from "@fleet-sdk/common"; import {AmmPool} from "@ergolabs/ergo-dex-sdk"; +import { + ErgoTx, + Input as TxInput, + Prover, + UnsignedErgoTx, + unsignedErgoTxToProxy, + publicKeyFromAddress, + AssetAmount, + Explorer, + DefaultTxAssembler, + RustModule, TransactionContext +} from '@ergolabs/ergo-sdk'; +import {NodeService} from "./node.service"; export interface ErgoAsset { tokenId: number; decimals: number; name: string; symbol: string } + +class WalletProver implements Prover { + /** Sign the given transaction. + */ + async sign(tx: UnsignedErgoTx, wallet: Wallet, nodeService: NodeService): Promise { + const ctx = await nodeService.getCtx() + const proxy = unsignedErgoTxToProxy(tx); + const wasmtx = UnsignedTransaction.from_json(JSON.stringify(proxy)) + try { + return wallet.sign_transaction(ctx, wasmtx, ErgoBoxes.from_boxes_json(proxy.inputs), ErgoBoxes.empty()).to_js_eip12() + } catch { + throw new Error("not be able to sign!") + } + } + + async submit(tx: ErgoTx, nodeService: NodeService): Promise { + return await nodeService.postTransaction(tx) + } +} export class Pool extends AmmPool{ private name:string constructor(public pool: AmmPool) { From d72bd93af1fabf864c41650a42f270c5e16ff413 Mon Sep 17 00:00:00 2001 From: ahmadyazdanii Date: Mon, 10 Jun 2024 17:29:31 +0330 Subject: [PATCH 016/132] update [ergo]: update document of ergo file --- src/chains/ergo/ergo.ts | 71 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 89344129ff..7fb9ca55d8 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -22,6 +22,7 @@ import { Explorer } from '@ergolabs/ergo-sdk'; class Pool extends AmmPool { private name: string; + constructor(public pool: AmmPool) { super(pool.id, pool.lp, pool.x, pool.y, pool.poolFeeNum); @@ -52,6 +53,11 @@ class Pool extends AmmPool { // } } +/** + * Ergo chain class + * @param {string} network - mainnet or testnet + * @class + */ export class Ergo { private _assetMap: Record = {}; private static _instances: LRUCache; @@ -105,10 +111,16 @@ export class Ergo { return Object.values(this._assetMap); } - public ready(): boolean { + public get ready(): boolean { return this._ready; } + /** + * This function initializes the Ergo class' instance + * @returns + * @function + * @async + */ public async init(): Promise { await this.loadAssets(); await this.loadPools(); @@ -120,6 +132,13 @@ export class Ergo { return; } + /** + * This static function returns the exists or create new Ergo class' instance based on the network + * @param {string} network - mainnet or testnet + * @returns Ergo + * @function + * @static + */ public static getInstance(network: string): Ergo { const config = getErgoConfig(network); @@ -142,6 +161,12 @@ export class Ergo { return Ergo._instances.get(config.network.name) as Ergo; } + /** + * This static function returns the connected instances + * @returns ErgoConnectedInstance + * @function + * @static + */ public static getConnectedInstances(): ErgoConnectedInstance { const connectedInstances: ErgoConnectedInstance = {}; @@ -158,11 +183,23 @@ export class Ergo { return connectedInstances; } + /** + * This function returns the current network height(Block number) + * @returns number + * @function + * @async + */ async getCurrentBlockNumber(): Promise { const status = await this._node.getNetworkHeight(); return status + 1; } + /** + * This function returns the unspent boxes based on the address from node + * @returns ErgoBox[] + * @function + * @async + */ async getAddressUnspentBoxes(address: string) { let utxos: Array = []; let offset = 0; @@ -185,6 +222,12 @@ export class Ergo { return utxos; } + /** + * Retrieves Ergo Account from secret key + * @param {string} secret - Secret key + * @returns ErgoAccount + * @function + */ public getAccountFromSecretKey(secret: string): ErgoAccount { const sks = new SecretKeys(); const secretKey = SecretKey.dlog_from_bytes(Buffer.from(secret, 'hex')); @@ -200,6 +243,13 @@ export class Ergo { }; } + /** + * Encrypt secret via password + * @param {string} secret - Secret key + * @param {string} password - password + * @returns string + * @function + */ public encrypt(secret: string, password: string): string { const iv = randomBytes(16); const key = Buffer.alloc(32); @@ -212,6 +262,13 @@ export class Ergo { return `${iv.toString('hex')}:${encrypted.toString('hex')}`; } + /** + * Decrypt encrypted secret key via password + * @param {string} encryptedSecret - Secret key + * @param {string} password - password + * @returns string + * @function + */ public decrypt(encryptedSecret: string, password: string): string { const [iv, encryptedKey] = encryptedSecret.split(':'); const key = Buffer.alloc(32); @@ -231,6 +288,14 @@ export class Ergo { return decrypted.toString(); } + /** + * Gets asset balance from unspent boxes + * @param {ErgoAccount} account + * @param {string} assetName + * @returns string + * @function + * @async + */ public async getAssetBalance( account: ErgoAccount, assetName: string, @@ -298,6 +363,10 @@ export class Ergo { return await makeNativePools(this._explorer).getAll({ limit, offset }); } + /** + * Returns a map of asset name and Ergo Asset + * @returns assetMap + */ public get storedTokenList() { return this._assetMap; } From 1546a0ebd3edeb556253eedce316a84404790234 Mon Sep 17 00:00:00 2001 From: ahmadyazdanii Date: Mon, 10 Jun 2024 17:33:29 +0330 Subject: [PATCH 017/132] update [ergo]: add node documentation --- src/chains/ergo/node.service.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/chains/ergo/node.service.ts b/src/chains/ergo/node.service.ts index f65f1020a8..439d67831d 100644 --- a/src/chains/ergo/node.service.ts +++ b/src/chains/ergo/node.service.ts @@ -2,6 +2,12 @@ import axios from 'axios'; import { NodeInfoResponse } from './interfaces/node.interface'; import { NodeErgoBoxResponse } from './types/node.type'; +/** + * This class allows you to access elements of a node + * @class + * @param {string} nodeURL - The node's base URL + * @param {number} timeout - Timeout + */ export class NodeService { constructor( private nodeURL: string, @@ -26,12 +32,28 @@ export class NodeService { return response.data; } + /** + * Gets network full height + * @returns number + * @function + * @async + */ async getNetworkHeight(): Promise { const info = await this.request('GET', '/info'); return info.fullHeight; } + /** + * Get unspent boxes via wallet address + * @param {string} address + * @param {string} offset + * @param {string} limit + * @param {string} sortDirection + * @returns NodeErgoBoxResponse + * @function + * @async + */ async getUnspentBoxesByAddress( address: string, offset: number, From 568a8292a838fef766ba3e1f7b3d574b6db38788 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Mon, 10 Jun 2024 19:16:56 +0330 Subject: [PATCH 018/132] update [unit-test]: update ergo.config.test based on new implementations --- test/chains/ergo/ergo.config.test.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/chains/ergo/ergo.config.test.ts b/test/chains/ergo/ergo.config.test.ts index 72b979b97b..8c43d6c2af 100644 --- a/test/chains/ergo/ergo.config.test.ts +++ b/test/chains/ergo/ergo.config.test.ts @@ -40,6 +40,10 @@ describe('getErgoConfig', () => { maxLRUCacheInstances: 10, utxosLimit: 100, poolLimit: 100, + defaultSlippage: 3, + defaultMinerFee: BigInt(2_000_000), + minNitro: 1.2, + minBoxValue: BigInt(400_000), }, }); // Assert: Verify that the get method was called exactly five times with the expected arguments @@ -92,6 +96,10 @@ describe('getErgoConfig', () => { maxLRUCacheInstances: 10, utxosLimit: 100, poolLimit: 100, + defaultSlippage: 3, + defaultMinerFee: BigInt(2_000_000), + minNitro: 1.2, + minBoxValue: BigInt(400_000), }, }); // Assert: Verify that the get method was called exactly five times with the expected arguments From 5401468e647a07c6e6c480cace6ac756bc83b4a4 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Tue, 11 Jun 2024 15:49:43 +0330 Subject: [PATCH 019/132] add [unit-test]: add unit tests for ergo.config file --- test/chains/ergo/ergo.config.test.ts | 114 +++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 test/chains/ergo/ergo.config.test.ts diff --git a/test/chains/ergo/ergo.config.test.ts b/test/chains/ergo/ergo.config.test.ts new file mode 100644 index 0000000000..fb668d5799 --- /dev/null +++ b/test/chains/ergo/ergo.config.test.ts @@ -0,0 +1,114 @@ +import { getErgoConfig } from '../../../src/chains/ergo/ergo.config'; +import { ConfigManagerV2 } from '../../../src/services/config-manager-v2'; +import { NetworkPrefix } from 'ergo-lib-wasm-nodejs'; + +// Define the test suite for the getErgoConfig function +describe('getErgoConfig', () => { + // After each test, clear all mocks to ensure no interference between tests + afterEach(() => { + jest.clearAllMocks(); + }); + + // Test case for verifying the configuration returned for the Mainnet + it('Should return correct config for Mainnet', () => { + // Arrange: Mock the get method of ConfigManagerV2 to return specific values for Mainnet + jest + .spyOn(ConfigManagerV2.getInstance(), 'get') + .mockReturnValueOnce('ergo.networks.Mainnet.nodeURL'); + jest + .spyOn(ConfigManagerV2.getInstance(), 'get') + .mockReturnValueOnce('ergo.networks.Mainnet.explorerURL'); + jest + .spyOn(ConfigManagerV2.getInstance(), 'get') + .mockReturnValueOnce('ergo.networks.Mainnet.explorerDEXURL'); + jest.spyOn(ConfigManagerV2.getInstance(), 'get').mockReturnValueOnce(1000); + jest.spyOn(ConfigManagerV2.getInstance(), 'get').mockReturnValueOnce(2000); + + // Act: Call the function to be tested with 'Mainnet' as the argument + const res = getErgoConfig('Mainnet'); + + // Assert: Check that the returned configuration matches the expected values for Mainnet + expect(res).toEqual({ + network: { + name: 'Mainnet', + nodeURL: 'ergo.networks.Mainnet.nodeURL', + explorerURL: 'ergo.networks.Mainnet.explorerURL', + explorerDEXURL: 'ergo.networks.Mainnet.explorerDEXURL', + timeOut: 1000, + networkPrefix: NetworkPrefix.Mainnet, + minTxFee: 2000, + maxLRUCacheInstances: 10, + utxosLimit: 100, + poolLimit: 100, + }, + }); + // Assert: Verify that the get method was called exactly five times with the expected arguments + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledTimes(5); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( + 'ergo.networks.Mainnet.nodeURL', + ); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( + 'ergo.networks.Mainnet.explorerURL', + ); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( + 'ergo.networks.Mainnet.explorerDEXURL', + ); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( + 'ergo.networks.Mainnet.timeOut', + ); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( + 'ergo.networks.Mainnet.minTxFee', + ); + }); + // Test case for verifying the configuration returned for the Testnet + it('Should return correct config for Testnet', () => { + // Arrange: Mock the get method of ConfigManagerV2 to return specific values for Testnet + jest + .spyOn(ConfigManagerV2.getInstance(), 'get') + .mockReturnValueOnce('ergo.networks.Testnet.nodeURL'); + jest + .spyOn(ConfigManagerV2.getInstance(), 'get') + .mockReturnValueOnce('ergo.networks.Testnet.explorerURL'); + jest + .spyOn(ConfigManagerV2.getInstance(), 'get') + .mockReturnValueOnce('ergo.networks.Testnet.explorerDEXURL'); + jest.spyOn(ConfigManagerV2.getInstance(), 'get').mockReturnValueOnce(1000); + jest.spyOn(ConfigManagerV2.getInstance(), 'get').mockReturnValueOnce(2000); + + // Act: Call the function to be tested with 'Testnet' as the argument + const res = getErgoConfig('Testnet'); + + // Assert: Check that the returned configuration matches the expected values for Testnet + expect(res).toEqual({ + network: { + name: 'Testnet', + nodeURL: 'ergo.networks.Testnet.nodeURL', + explorerURL: 'ergo.networks.Testnet.explorerURL', + explorerDEXURL: 'ergo.networks.Testnet.explorerDEXURL', + timeOut: 1000, + networkPrefix: NetworkPrefix.Testnet, + minTxFee: 2000, + maxLRUCacheInstances: 10, + utxosLimit: 100, + poolLimit: 100, + }, + }); + // Assert: Verify that the get method was called exactly five times with the expected arguments + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledTimes(5); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( + 'ergo.networks.Testnet.nodeURL', + ); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( + 'ergo.networks.Testnet.explorerURL', + ); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( + 'ergo.networks.Testnet.explorerDEXURL', + ); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( + 'ergo.networks.Testnet.timeOut', + ); + expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( + 'ergo.networks.Testnet.minTxFee', + ); + }); +}); From 0da881d3315a6ae02de1583be3aa9ca10f0f4030 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Tue, 11 Jun 2024 17:06:20 +0330 Subject: [PATCH 020/132] add [unit-test]: Implement unit tests for "DexService" => "request" method --- test/chains/ergo/dex.service.test.ts | 77 ++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 test/chains/ergo/dex.service.test.ts diff --git a/test/chains/ergo/dex.service.test.ts b/test/chains/ergo/dex.service.test.ts new file mode 100644 index 0000000000..e3e16355c1 --- /dev/null +++ b/test/chains/ergo/dex.service.test.ts @@ -0,0 +1,77 @@ +import axios from 'axios'; +import { DexService } from '../../../src/chains/ergo/dex.service'; +// import { DEXTokensResponse } from '../../../src/chains/ergo/interfaces/dex.interface'; + +// Mocking axios to intercept HTTP requests and return controlled responses +jest.mock('axios'); + +// Describe the test suite for the NodeService class +describe('DexService', () => { + // Define constants for baseURL and timeout + const baseURL = 'https://example.com'; + const timeout = 5000; + + // Initialize DexService instance + const dexService: DexService = new DexService(baseURL, timeout); + + // Test case to check if DexService is defined and its properties are set correctly + it('Should initialize with given baseURL and timeout', () => { + // Assert: Check if the dexURL and timeout properties are correctly set and instance is defined + expect(dexService).toBeDefined(); + expect(dexService['dexURL']).toBe(baseURL); + expect(dexService['timeout']).toBe(timeout); + }); + + // Describe the test suite for the private request method of NodeService + describe('request', () => { + // Define default parameters for the request method + const method = 'GET'; + const url = '/test-endpoint'; + const headers = { 'Content-Type': 'application/json' }; + const body = { key: 'value' }; + + // Test case for making a GET request with correct parameters + it('Should make a GET request with correct parameters', async () => { + // Arrange: Mock the axios response + const mockResponse = { data: { name: 'test' } }; + (axios as any).mockResolvedValue(mockResponse); + + // Act: Call the private request method with GET parameters + const response = await dexService['request'](method, url, headers); + + // Assert: Check if axios was called with the correct configuration + expect(axios).toHaveBeenCalledWith({ + baseURL, + url, + method, + headers, + timeout, + }); + // Assert: Check if the response is as expected + expect(response).toEqual({ name: 'test' }); + }); + + // Test case for making a POST request with correct parameters + it('Should make a POST request with correct parameters', async () => { + // Arrange: Change method to POST and mock the axios response + const method = 'POST'; + const mockResponse = { data: { name: 'test' } }; + (axios as any).mockResolvedValue(mockResponse); + + // Act: Call the private request method with POST parameters + const response = await dexService['request'](method, url, headers, body); + + // Assert: Check if axios was called with the correct configuration + expect(axios).toHaveBeenCalledWith({ + baseURL, + url, + method, + headers, + timeout, + body, + }); + // Assert: Check if the response is as expected + expect(response).toEqual({ name: 'test' }); + }); + }); +}); From 1a98f94d361901e6e85d8de13e4c05d2498211fd Mon Sep 17 00:00:00 2001 From: satiparpar Date: Tue, 11 Jun 2024 19:21:23 +0330 Subject: [PATCH 021/132] add [unit-test]: Implement unit tests for "DexService" => "getTokens" method --- test/chains/ergo/dex.service.test.ts | 35 +++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/test/chains/ergo/dex.service.test.ts b/test/chains/ergo/dex.service.test.ts index e3e16355c1..bfcff20b1b 100644 --- a/test/chains/ergo/dex.service.test.ts +++ b/test/chains/ergo/dex.service.test.ts @@ -1,6 +1,6 @@ import axios from 'axios'; import { DexService } from '../../../src/chains/ergo/dex.service'; -// import { DEXTokensResponse } from '../../../src/chains/ergo/interfaces/dex.interface'; +import { DEXTokensResponse } from '../../../src/chains/ergo/interfaces/dex.interface'; // Mocking axios to intercept HTTP requests and return controlled responses jest.mock('axios'); @@ -74,4 +74,37 @@ describe('DexService', () => { expect(response).toEqual({ name: 'test' }); }); }); + + // Describe the test suite for the getTokens method of NodeService + describe('getTokens', () => { + // Test case to call getTokens method and check return value and function input arguments + it('Should call request method with correct parameters', async () => { + // Arrange: Mock the response of the request method + const mockResponse: DEXTokensResponse = { + tokens: [ + { + address: '1', + name: 'Token1', + decimals: 0, + ticker: '', + logoURI: '', + project: '', + description: '', + }, + ], + }; + jest.spyOn(dexService as any, 'request').mockResolvedValue(mockResponse); + + // Act: Call the getTokens method + const response = await dexService.getTokens(); + + // Assert: Check if the request method was called with the correct parameters + expect(dexService['request']).toHaveBeenCalledWith( + 'GET', + '/ergo-token-list.json', + ); + // Assert: Check if the response from getTokens is as expected + expect(response).toEqual(mockResponse); + }); + }); }); From 5769f82f2d3d7ea6f50d39d55f842cb666dcf50c Mon Sep 17 00:00:00 2001 From: satiparpar Date: Wed, 12 Jun 2024 11:12:11 +0330 Subject: [PATCH 022/132] add [unit-test]: Implement unit tests for "NodeService" => "request" method --- test/chains/ergo/node.service.test.ts | 81 +++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 test/chains/ergo/node.service.test.ts diff --git a/test/chains/ergo/node.service.test.ts b/test/chains/ergo/node.service.test.ts new file mode 100644 index 0000000000..021f12f204 --- /dev/null +++ b/test/chains/ergo/node.service.test.ts @@ -0,0 +1,81 @@ +import axios from 'axios'; +import { NodeService } from '../../../src/chains/ergo/node.service'; +// import { NodeInfoResponse } from '../../../src/chains/ergo/interfaces/node.interface'; + +// Mock axios to avoid making real HTTP requests during tests +jest.mock('axios'); + +// Describe the test suite for the NodeService class +describe('NodeService', () => { + // Define constants for baseURL and timeout + const baseURL = 'https://example.com'; + const timeout = 5000; + + // Initialize NodeService instance + const nodeService: NodeService = new NodeService(baseURL, timeout); + + // After each test, clear all mocks to ensure no interference between tests + afterEach(() => { + jest.clearAllMocks(); + }); + + // Test case to check if NodeService is defined and its properties are set correctly + it('Should be defined and and set nodeURL & timeout correctly', () => { + // Assert: Check if the nodeURL and timeout properties are correctly set and instance is defined + expect(nodeService).toBeDefined(); + expect(nodeService['nodeURL']).toEqual('https://example.com'); + expect(nodeService['timeout']).toEqual(5000); + }); + + describe('request', () => { + // Define default parameters for the request method + const method = 'GET'; + const url = '/test-endpoint'; + const headers = { 'Content-Type': 'application/json' }; + const body = { key: 'value' }; + + // Test case for making a GET request with correct parameters + it('Should make a GET request with correct parameters', async () => { + // Arrange: Mock the axios response + const mockResponse = { data: { name: 'test' } }; + (axios as any).mockResolvedValue(mockResponse); + + // Act: Call the private request method with GET parameters + const response = await nodeService['request'](method, url, headers); + + // Assert: Check if axios was called with the correct configuration + expect(axios).toHaveBeenCalledWith({ + baseURL, + url, + method, + headers, + timeout, + }); + // Assert: Check if the response is as expected + expect(response).toEqual({ name: 'test' }); + }); + + // Test case for making a POST request with correct parameters + it('Should make a POST request with correct parameters', async () => { + // Arrange: Change method to POST and mock the axios response + const method = 'POST'; + const mockResponse = { data: { name: 'test' } }; + (axios as any).mockResolvedValue(mockResponse); + + // Act: Call the private request method with POST parameters + const response = await nodeService['request'](method, url, headers, body); + + // Assert: Check if axios was called with the correct configuration + expect(axios).toHaveBeenCalledWith({ + baseURL, + url, + method, + headers, + timeout, + body, + }); + // Assert: Check if the response is as expected + expect(response).toEqual({ name: 'test' }); + }); + }); +}); From 847e1c86b57b997d7911e1c4cb73dd63fa7ccb9b Mon Sep 17 00:00:00 2001 From: satiparpar Date: Wed, 12 Jun 2024 15:34:06 +0330 Subject: [PATCH 023/132] add [unit-test]: Implement unit tests for "NodeService" => "getNetworkHeight" & "getUnspentBoxesByAddress" methods --- test/chains/ergo/node.service.test.ts | 55 ++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/test/chains/ergo/node.service.test.ts b/test/chains/ergo/node.service.test.ts index 021f12f204..2451444df9 100644 --- a/test/chains/ergo/node.service.test.ts +++ b/test/chains/ergo/node.service.test.ts @@ -1,6 +1,6 @@ import axios from 'axios'; import { NodeService } from '../../../src/chains/ergo/node.service'; -// import { NodeInfoResponse } from '../../../src/chains/ergo/interfaces/node.interface'; +import { NodeInfoResponse } from '../../../src/chains/ergo/interfaces/node.interface'; // Mock axios to avoid making real HTTP requests during tests jest.mock('axios'); @@ -78,4 +78,57 @@ describe('NodeService', () => { expect(response).toEqual({ name: 'test' }); }); }); + + // Describe the test suite for the getNetworkHeight method + describe('getNetworkHeight', () => { + // Define a test case to check if getNetworkHeight is called with the correct parameters and returns the correct value + it('should call getNetworkHeight with correct parameters and returns the correct value', async () => { + // Define a mock response with fullHeight property + const res: NodeInfoResponse = { fullHeight: 100 }; + // Mock the private request method of nodeService to resolve with the mock response + jest.spyOn(nodeService as any, 'request').mockResolvedValue(res); + + // Call the getNetworkHeight method and store the result + const networkHeight = await nodeService.getNetworkHeight(); + + // Assert: Check if the returned network height is correct + expect(networkHeight).toEqual(100); + // Assert: Check if the private request method was called exactly once + expect(nodeService['request']).toHaveBeenCalledTimes(1); + // Assert: Check if the private request method was called with the correct HTTP method and URL + expect(nodeService['request']).toHaveBeenCalledWith('GET', '/info'); + }); + }); + + // Describe the test suite for the getUnspentBoxesByAddress method + describe('getUnspentBoxesByAddress', () => { + // Define constants for address, offset, and limit + const address = 'box-number-1.com'; + const offset = 10; + const limit = 20; + + // Define a test case to check if getUnspentBoxesByAddress is called with the correct parameters and returns the correct value + it('Should call getUnspentBoxesByAddress method with correct parameters and returns the correct value', async () => { + // Mock the private request method of nodeService to resolve with an empty data object + jest.spyOn(nodeService as any, 'request').mockResolvedValue({ data: {} }); + // Call the getUnspentBoxesByAddress method with the defined address, offset, and limit, and store the result + const unspentBoxesByAddress = await nodeService.getUnspentBoxesByAddress( + address, + offset, + limit, + ); + + // Assert: Check if the returned value matches the mock response + expect(unspentBoxesByAddress).toEqual({ data: {} }); + // Assert: Check if the private request method was called exactly once + expect(nodeService['request']).toHaveBeenCalledTimes(1); + // Assert: Check if the private request method was called with the correct HTTP method, URL, headers, and body + expect(nodeService['request']).toHaveBeenCalledWith( + 'POST', + `/blockchain/box/unspent/byAddress?offset=10&limit=20&sortDirection=desc`, + { 'Content-Type': 'text/plain' }, + 'box-number-1.com', + ); + }); + }); }); From e4d58dc85b5cb7fe00dff4889f6ca3bef6748fd6 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Thu, 13 Jun 2024 18:13:46 +0330 Subject: [PATCH 024/132] add [unit-test]: Implement unit tests for "Ergo" => verify initialization with Mainnet configuration --- test/chains/ergo/ergo.test.ts | 68 +++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 test/chains/ergo/ergo.test.ts diff --git a/test/chains/ergo/ergo.test.ts b/test/chains/ergo/ergo.test.ts new file mode 100644 index 0000000000..7c24ae545c --- /dev/null +++ b/test/chains/ergo/ergo.test.ts @@ -0,0 +1,68 @@ +import { NetworkPrefix } from 'ergo-lib-wasm-nodejs'; +import { Ergo } from '../../../src/chains/ergo/ergo'; +import { patch, unpatch } from '../../../test/services/patch'; +import * as ergo_cofing from '../../../src/chains/ergo/ergo.config'; +import { NodeService } from '../../../src/chains/ergo/node.service'; +import { Explorer } from '@ergolabs/ergo-sdk'; +import { DexService } from '../../../src/chains/ergo/dex.service'; +import { ErgoController } from '../../../src/chains/ergo/ergo.controller'; + +// Mocking dependencies for testing purposes using jest +jest.mock('@ergolabs/ergo-dex-sdk', () => ({ + AmmPool: jest.fn(), + makeNativePools: jest.fn(), +})); +jest.mock('@ergolabs/ergo-sdk', () => ({ + Explorer: jest.fn(), +})); + +// Clean up mocks after each test +afterEach(() => { + unpatch(); +}); + +// Helper function to patch getErgoConfig for Mainnet configuration +const pathGetErgoConfi = () => { + patch(ergo_cofing, 'getErgoConfig', () => { + return { + network: { + name: 'Mainnet', + nodeURL: 'ergo.networks.Mainnet.nodeURL', + explorerURL: 'ergo.networks.Mainnet.explorerURL', + explorerDEXURL: 'ergo.networks.Mainnet.explorerDEXURL', + timeOut: 1000, + networkPrefix: NetworkPrefix.Mainnet, + minTxFee: 2000, + maxLRUCacheInstances: 10, + utxosLimit: 100, + poolLimit: 100, + }, + }; + }); +}; + +// Describe the test suite for the Ergo class +describe('Ergo', () => { + // Test case to verify initialization with Mainnet configuration + it('Should initialize with Mainnet configuration', () => { + // Arrange: Mock the return value of getErgoConfig to simulate Mainnet configuration + pathGetErgoConfi(); + + // Act: Create a new instance of Ergo with 'Mainnet' configuration + const ergo = new Ergo('Mainnet'); + + // Assert: Validate the initialization state of Ergo instance + expect(ergo).toBeDefined(); + expect(ergo['_assetMap']).toEqual({}); + expect(ergo['_network']).toEqual('Mainnet'); + expect(ergo['_networkPrefix']).toEqual(NetworkPrefix.Mainnet); + expect(ergo['_node']).toBeInstanceOf(NodeService); + expect(ergo['_explorer']).toBeInstanceOf(Explorer); + expect(ergo['_dex']).toBeInstanceOf(DexService); + expect(ergo['txFee']).toEqual(2000); + expect(ergo['controller']).toEqual(ErgoController); + expect(ergo['utxosLimit']).toEqual(100); + expect(ergo['poolLimit']).toEqual(100); + expect(ergo['ammPools']).toEqual([]); + }); +}); From 9de3c3e85028425515b84b41a1bda2b34ffc6209 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Fri, 14 Jun 2024 15:06:47 +0330 Subject: [PATCH 025/132] add [unit-test]: Implement unit tests for "Ergo" => verify initialization with Testnet configuration --- test/chains/ergo/ergo.test.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/chains/ergo/ergo.test.ts b/test/chains/ergo/ergo.test.ts index 7c24ae545c..3d942889d5 100644 --- a/test/chains/ergo/ergo.test.ts +++ b/test/chains/ergo/ergo.test.ts @@ -65,4 +65,27 @@ describe('Ergo', () => { expect(ergo['poolLimit']).toEqual(100); expect(ergo['ammPools']).toEqual([]); }); + + // Test case to verify initialization with Testnet configuration + it('Should initialize with Mainnet configuration', () => { + // Arrange: Mock the return value of getErgoConfig to simulate Testnet configuration + pathGetErgoConfi(); + + // Act: Create a new instance of Ergo with 'Testnet' configuration + const ergo = new Ergo('Testnet'); + + // Assert: Validate the initialization state of Ergo instance + expect(ergo).toBeDefined(); + expect(ergo['_assetMap']).toEqual({}); + expect(ergo['_network']).toEqual('Testnet'); + expect(ergo['_networkPrefix']).toEqual(NetworkPrefix.Testnet); + expect(ergo['_node']).toBeInstanceOf(NodeService); + expect(ergo['_explorer']).toBeInstanceOf(Explorer); + expect(ergo['_dex']).toBeInstanceOf(DexService); + expect(ergo['txFee']).toEqual(2000); + expect(ergo['controller']).toEqual(ErgoController); + expect(ergo['utxosLimit']).toEqual(100); + expect(ergo['poolLimit']).toEqual(100); + expect(ergo['ammPools']).toEqual([]); + }); }); From 8f2c466429833b7e1eb8f99ec0085e7e81004290 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Fri, 14 Jun 2024 16:32:48 +0330 Subject: [PATCH 026/132] add [unit-test]: Implement unit tests for "Ergo" => "node", "network", "storedAssetList", "ready" and "close" methods --- test/chains/ergo/ergo.test.ts | 118 ++++++++++++++++++++++++++++++---- 1 file changed, 105 insertions(+), 13 deletions(-) diff --git a/test/chains/ergo/ergo.test.ts b/test/chains/ergo/ergo.test.ts index 3d942889d5..b65d74e2f8 100644 --- a/test/chains/ergo/ergo.test.ts +++ b/test/chains/ergo/ergo.test.ts @@ -6,6 +6,7 @@ import { NodeService } from '../../../src/chains/ergo/node.service'; import { Explorer } from '@ergolabs/ergo-sdk'; import { DexService } from '../../../src/chains/ergo/dex.service'; import { ErgoController } from '../../../src/chains/ergo/ergo.controller'; +import { ErgoAsset } from '../../../src/chains/ergo/interfaces/ergo.interface'; // Mocking dependencies for testing purposes using jest jest.mock('@ergolabs/ergo-dex-sdk', () => ({ @@ -22,16 +23,19 @@ afterEach(() => { }); // Helper function to patch getErgoConfig for Mainnet configuration -const pathGetErgoConfi = () => { +const pathGetErgoConfig = (imputNetwork: string) => { patch(ergo_cofing, 'getErgoConfig', () => { return { network: { - name: 'Mainnet', - nodeURL: 'ergo.networks.Mainnet.nodeURL', - explorerURL: 'ergo.networks.Mainnet.explorerURL', - explorerDEXURL: 'ergo.networks.Mainnet.explorerDEXURL', + name: imputNetwork, + nodeURL: 'ergo.networks.' + imputNetwork + '.nodeURL', + explorerURL: 'ergo.networks.' + imputNetwork + '.explorerURL', + explorerDEXURL: 'ergo.networks.' + imputNetwork + '.explorerDEXURL', timeOut: 1000, - networkPrefix: NetworkPrefix.Mainnet, + networkPrefix: + imputNetwork === 'Mainnet' + ? NetworkPrefix.Mainnet + : NetworkPrefix.Testnet, minTxFee: 2000, maxLRUCacheInstances: 10, utxosLimit: 100, @@ -43,14 +47,16 @@ const pathGetErgoConfi = () => { // Describe the test suite for the Ergo class describe('Ergo', () => { + let ergo: Ergo; + beforeEach(() => { + // Arrange: Mock the return value of getErgoConfig to simulate Mainnet configuration before each test + pathGetErgoConfig('Mainnet'); + + // Arrange: Create a new instance of Ergo with 'Mainnet' configuration before each test + ergo = new Ergo('Mainnet'); + }); // Test case to verify initialization with Mainnet configuration it('Should initialize with Mainnet configuration', () => { - // Arrange: Mock the return value of getErgoConfig to simulate Mainnet configuration - pathGetErgoConfi(); - - // Act: Create a new instance of Ergo with 'Mainnet' configuration - const ergo = new Ergo('Mainnet'); - // Assert: Validate the initialization state of Ergo instance expect(ergo).toBeDefined(); expect(ergo['_assetMap']).toEqual({}); @@ -69,7 +75,7 @@ describe('Ergo', () => { // Test case to verify initialization with Testnet configuration it('Should initialize with Mainnet configuration', () => { // Arrange: Mock the return value of getErgoConfig to simulate Testnet configuration - pathGetErgoConfi(); + pathGetErgoConfig('Testnet'); // Act: Create a new instance of Ergo with 'Testnet' configuration const ergo = new Ergo('Testnet'); @@ -88,4 +94,90 @@ describe('Ergo', () => { expect(ergo['poolLimit']).toEqual(100); expect(ergo['ammPools']).toEqual([]); }); + + // Describe the test suite for the get node method + describe('get node', () => { + // Test case to verify initialization of node service + it('Should initialize node correctly and return the correct node', () => { + // Assert: Validate the initialization state of node instance and check the returned value + expect(ergo.node).toBeInstanceOf(NodeService); + expect(ergo.node).toEqual({ + nodeURL: 'ergo.networks.Mainnet.nodeURL', + timeout: 1000, + }); + }); + }); + + // Describe the test suite for the get network method + describe('get network', () => { + // Test case to verify network value when initialized with Mainnet + it('should return the correct network when network is Mainnet', () => { + // Assert: Validate the return value + expect(ergo.network).toBe('Mainnet'); + }); + + // Test case to verify network value when initialized with Testnet + it('should return the correct network when network is Testnet', () => { + // Arrange: Mock the return value of getErgoConfig to simulate Testnet configuration + pathGetErgoConfig('Testnet'); + + // Act: Create a new instance of Ergo with 'Testnet' configuration + ergo = new Ergo('Testnet'); + + // Assert: Validate the return value + expect(ergo.network).toBe('Testnet'); + }); + }); + + // Describe the test suite for the get network method + describe('get storedAssetList', () => { + // Test case to verify the stored asset list + it('should return the stored asset list', () => { + // Arrange: Create mock assets and populate _assetMap + const asset1: ErgoAsset = 1 as any; + const asset2: ErgoAsset = 2 as any; + const assetMap = { + key1: asset1, + key2: asset2, + }; + + // Act: Set _assetMap directly + ergo['_assetMap'] = assetMap; + + // Assert: Validate the stored asset list returned by storedAssetList + expect(ergo.storedAssetList).toEqual(Object.values(assetMap)); + }); + }); + + // Describe the test suite for the ready method + describe('ready', () => { + // Test case to verify the return value of the ready method + it('should return the ready state', () => { + // Assert: Initially, the ready state should be false + expect(ergo.ready()).toBe(false); + + // Act: Manually set the _ready state to true + ergo['_ready'] = true; + + // Assert: Now, the ready state should be true + expect(ergo.ready()).toBe(true); + }); + }); + + // describe('', () => { + // it('should initialize assets and pools in init method', async () => { + // const loadAssetsSpy = jest.spyOn(ergo as any, 'loadAssets').mockResolvedValue(); + // const loadPoolsSpy = jest.spyOn(ergo as any, 'loadPools').mockResolvedValue(); + // await ergo.init(); + // expect(loadAssetsSpy).toHaveBeenCalled(); + // expect(loadPoolsSpy).toHaveBeenCalled(); + // expect(ergo.ready()).toBe(true); + // }); + // }); + + describe('close', () => { + it('should close correctly', async () => { + await expect(ergo.close()).resolves.toBeUndefined(); + }); + }); }); From 7e63a86121d891f4dcc6cf3b40a2d6110bce54a6 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Sat, 15 Jun 2024 12:28:24 +0330 Subject: [PATCH 027/132] add [unit-test]: Implement unit tests for "Ergo" => "getInstance" and "getConnectedInstances" methods --- test/chains/ergo/ergo.test.ts | 119 ++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/test/chains/ergo/ergo.test.ts b/test/chains/ergo/ergo.test.ts index b65d74e2f8..dee606a9c6 100644 --- a/test/chains/ergo/ergo.test.ts +++ b/test/chains/ergo/ergo.test.ts @@ -7,6 +7,7 @@ import { Explorer } from '@ergolabs/ergo-sdk'; import { DexService } from '../../../src/chains/ergo/dex.service'; import { ErgoController } from '../../../src/chains/ergo/ergo.controller'; import { ErgoAsset } from '../../../src/chains/ergo/interfaces/ergo.interface'; +import LRUCache from 'lru-cache'; // Mocking dependencies for testing purposes using jest jest.mock('@ergolabs/ergo-dex-sdk', () => ({ @@ -175,9 +176,127 @@ describe('Ergo', () => { // }); // }); + // Describe the test suite for the close method describe('close', () => { + // Test case to verify the close method it('should close correctly', async () => { + // Act and Assert: Call the close method and expect that the close method resolves without any errors or values await expect(ergo.close()).resolves.toBeUndefined(); }); }); + + // Describe the test suite for the getInstance method + describe('getInstance', () => { + const mockNetwork = 'Testnet'; + + // This block runs before each test in this suite + beforeEach(() => { + // Arrange: Mock the function to get the configuration for the 'Testnet' network + pathGetErgoConfig('Testnet'); + // Arrange: Clear the singleton and mock instances + Ergo['_instances'] = undefined as any; + }); + + // Test that the LRUCache is initialized if it hasn't been already + it('should initialize the LRUCache if not already initialized', () => { + // Act: Call the getInstance method with the mock network + Ergo.getInstance(mockNetwork); + + // Assert: Expect that the _instances property is defined and _instances is an instance of LRUCache + expect(Ergo['_instances']).toBeDefined(); + expect(Ergo['_instances']).toBeInstanceOf(LRUCache); + }); + + // Test that a new Ergo instance is created and returned if it's not in the cache + it('should set and return a new Ergo instance if not in the cache', () => { + // Act: Call the getInstance method with the mock network + const instance = Ergo.getInstance(mockNetwork); + + // Assert: Expect that the returned instance is an instance of Ergo, the cache contains the mock network key and the instance in the cache matches the returned instance + expect(instance).toBeInstanceOf(Ergo); + expect(Ergo['_instances'].has(mockNetwork)).toBe(true); + expect(Ergo['_instances'].get(mockNetwork)).toBe(instance); + }); + + // Test that an existing Ergo instance is returned from the cache + it('should return an existing Ergo instance from the cache', () => { + // Act: Call the getInstance method twice with the mock network + const instance1 = Ergo.getInstance(mockNetwork); + const instance2 = Ergo.getInstance(mockNetwork); + + // Assert: Expect that both calls return the same instance and the cache contains the mock network key + expect(instance1).toBe(instance2); + expect(Ergo['_instances'].get(mockNetwork)).toBe(instance1); + }); + + // Test that an error is thrown if an unexpected network is provided + it('should throw an error if an unexpected network is provided', () => { + // Act and Assert: Expect that calling getInstance with an empty string throws an error + expect(() => Ergo.getInstance('')).toThrow( + 'Ergo.getInstance received an unexpected network: .', + ); + }); + }); + + // Describe the test suite for the getConnectedInstances method + describe('getConnectedInstances', () => { + let mockErgoInstance1: Ergo; + let mockErgoInstance2: Ergo; + + // This block runs before each test in this suite + beforeEach(() => { + // Arrange: Create mock Ergo instances + mockErgoInstance1 = new Ergo('Testnet1') as any; + mockErgoInstance2 = new Ergo('Testnet2') as any; + + // Arrange: Initialize the _instances LRUCache with mock instances + Ergo['_instances'] = new LRUCache({ + max: 10, + }); + Ergo['_instances'].set('Testnet1', mockErgoInstance1); + Ergo['_instances'].set('Testnet2', mockErgoInstance2); + }); + // Test case to verify that all connected instances are returned + it('should return all connected instances', () => { + // Act: Call the getConnectedInstances method + const connectedInstances = Ergo.getConnectedInstances(); + + // Assert: Expect the connected instances to match the mock instances + expect(Object.keys(connectedInstances).sort()).toEqual([ + 'Testnet1', + 'Testnet2', + ]); + expect(connectedInstances['Testnet1']).toBe(mockErgoInstance1); + expect(connectedInstances['Testnet2']).toBe(mockErgoInstance2); + }); + + // Test case to verify that an empty object is returned if no instances exist + it('should return an empty object if there are no instances', () => { + // Arrange: Clear the _instances LRUCache + Ergo['_instances'] = undefined as any; + + // Act: Call the getConnectedInstances method + const connectedInstances = Ergo.getConnectedInstances(); + + // Assert: Expect the connected instances to be an empty object + expect(connectedInstances).toEqual({}); + }); + + // Test case to verify that only valid instances are returned + it('should return only valid instances', () => { + // Arrange: Set an invalid (null) instance in the _instances LRUCache + Ergo['_instances'].set('', null as any); + + // Act: Call the getConnectedInstances method + const connectedInstances = Ergo.getConnectedInstances(); + // Assert: Expect the valid instances to be returned and invalid instances to be excluded + expect(Object.keys(connectedInstances).sort()).toEqual([ + 'Testnet1', + 'Testnet2', + ]); + expect(connectedInstances['Testnet1']).toBe(mockErgoInstance1); + expect(connectedInstances['Testnet2']).toBe(mockErgoInstance2); + expect(connectedInstances['']).toBeUndefined(); + }); + }); }); From 9cd9920ca99ed917d4921cbc183b9833294af192 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Sat, 15 Jun 2024 16:52:16 +0330 Subject: [PATCH 028/132] add [unit-test]: Implement unit tests for "Ergo" => "getCurrentBlockNumber" and "getAddressUnspentBoxes" methods --- test/chains/ergo/ergo.test.ts | 85 ++++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 2 deletions(-) diff --git a/test/chains/ergo/ergo.test.ts b/test/chains/ergo/ergo.test.ts index dee606a9c6..32ca486696 100644 --- a/test/chains/ergo/ergo.test.ts +++ b/test/chains/ergo/ergo.test.ts @@ -1,4 +1,9 @@ -import { NetworkPrefix } from 'ergo-lib-wasm-nodejs'; +import { + NetworkPrefix, + // SecretKey, + // SecretKeys, + // Wallet, +} from 'ergo-lib-wasm-nodejs'; import { Ergo } from '../../../src/chains/ergo/ergo'; import { patch, unpatch } from '../../../test/services/patch'; import * as ergo_cofing from '../../../src/chains/ergo/ergo.config'; @@ -6,7 +11,10 @@ import { NodeService } from '../../../src/chains/ergo/node.service'; import { Explorer } from '@ergolabs/ergo-sdk'; import { DexService } from '../../../src/chains/ergo/dex.service'; import { ErgoController } from '../../../src/chains/ergo/ergo.controller'; -import { ErgoAsset } from '../../../src/chains/ergo/interfaces/ergo.interface'; +import { + ErgoAsset, + ErgoBox, +} from '../../../src/chains/ergo/interfaces/ergo.interface'; import LRUCache from 'lru-cache'; // Mocking dependencies for testing purposes using jest @@ -299,4 +307,77 @@ describe('Ergo', () => { expect(connectedInstances['']).toBeUndefined(); }); }); + + // Describe the test suite for the getCurrentBlockNumber method + describe('getCurrentBlockNumber', () => { + // Test case to verify return block number corectly + it('Should return the current block number incremented by one', async () => { + // Arrange: Mock the getNetworkHeight method to return a fixed value + jest.spyOn(ergo['_node'], 'getNetworkHeight').mockResolvedValue(17); + + // Act: Call the getCurrentBlockNumber method + const blockNumber = await ergo.getCurrentBlockNumber(); + + // Assert: Validate the returned block number + expect(blockNumber).toEqual(18); + expect(ergo['_node'].getNetworkHeight).toHaveBeenCalled; + }); + }); + + describe('getAddressUnspentBoxes', () => { + const mockAddress = '9j2s7d8f4s8s8o8s0q8f5s8d7f8s0d4r5'; + it('Should return an empty arry when length of nodeBoxes is 0', async () => { + jest + .spyOn(ergo['_node'], 'getUnspentBoxesByAddress') + .mockResolvedValue([]); + const utxos = await ergo.getAddressUnspentBoxes(mockAddress); + expect(utxos).toEqual([]); + expect(ergo['_node'].getUnspentBoxesByAddress).toHaveBeenCalledWith( + mockAddress, + 0, + 100, + ); + }); + + it('Should retrieve all unspent boxes for the given address', async () => { + // Arrange + const mockUnspentBoxesPage1 = [ + { boxId: 'box1' }, + { boxId: 'box2' }, + ] as Array; + const mockUnspentBoxesPage2 = [{ boxId: 'box3' }] as Array; + const mockUnspentBoxesPage3 = [] as Array; // Last page, empty + jest + .spyOn(ergo['_node'], 'getUnspentBoxesByAddress') + .mockResolvedValueOnce(mockUnspentBoxesPage1) + .mockResolvedValueOnce(mockUnspentBoxesPage2) + .mockResolvedValueOnce(mockUnspentBoxesPage3); + + // Act + const result = await ergo.getAddressUnspentBoxes(mockAddress); + + // Assert + expect(result).toEqual([ + { boxId: 'box1' }, + { boxId: 'box2' }, + { boxId: 'box3' }, + ]); + expect(ergo['_node'].getUnspentBoxesByAddress).toHaveBeenCalledTimes(3); + expect(ergo['_node'].getUnspentBoxesByAddress).toHaveBeenCalledWith( + mockAddress, + 0, + 100, + ); + expect(ergo['_node'].getUnspentBoxesByAddress).toHaveBeenCalledWith( + mockAddress, + 100, + 100, + ); + expect(ergo['_node'].getUnspentBoxesByAddress).toHaveBeenCalledWith( + mockAddress, + 200, + 100, + ); + }); + }); }); From 9c8f807646ad032de98b617128549857b1409491 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Sun, 16 Jun 2024 11:09:04 +0330 Subject: [PATCH 029/132] add [unit-test]: Implement unit tests for "Ergo" => "getAccountFromSecretKey" method --- test/chains/ergo/ergo.test.ts | 105 ++++++++++++++++++++++++++-------- 1 file changed, 80 insertions(+), 25 deletions(-) diff --git a/test/chains/ergo/ergo.test.ts b/test/chains/ergo/ergo.test.ts index 32ca486696..143c79e04a 100644 --- a/test/chains/ergo/ergo.test.ts +++ b/test/chains/ergo/ergo.test.ts @@ -1,8 +1,9 @@ import { NetworkPrefix, - // SecretKey, - // SecretKeys, - // Wallet, + SecretKey, + SecretKeys, + Wallet, + Address, } from 'ergo-lib-wasm-nodejs'; import { Ergo } from '../../../src/chains/ergo/ergo'; import { patch, unpatch } from '../../../test/services/patch'; @@ -26,11 +27,32 @@ jest.mock('@ergolabs/ergo-sdk', () => ({ Explorer: jest.fn(), })); -// Clean up mocks after each test -afterEach(() => { - unpatch(); +// Initializing Ergo instance for testing +let ergo: Ergo; + +// Before each test, configure and initialize Ergo with 'Mainnet' settings +beforeEach(() => { + // Arrange: Mock the return value of getErgoConfig to simulate Mainnet configuration before each test + pathGetErgoConfig('Mainnet'); + + // Arrange: Create a new instance of Ergo with 'Mainnet' configuration before each test + ergo = new Ergo('Mainnet'); }); +// Helper function to patch Wallet.from_secrets method for testing +const patchFrom_secrets = () => { + patch(Wallet, 'from_secrets', () => { + return 'testWallet' as any; + }); +}; + +// Helper function to patch Address.prototype.to_base58 method for testing +const patchTo_base58 = () => { + patch(Address.prototype, 'to_base58', () => { + return 'testAddress' as any; + }); +}; + // Helper function to patch getErgoConfig for Mainnet configuration const pathGetErgoConfig = (imputNetwork: string) => { patch(ergo_cofing, 'getErgoConfig', () => { @@ -54,16 +76,17 @@ const pathGetErgoConfig = (imputNetwork: string) => { }); }; +const patchErgo_node = async () => { + patch(ergo['_node'], 'getUnspentBoxesByAddress', () => { + return []; + }); +}; +// Clean up mocks after each test +afterEach(() => { + unpatch(); +}); // Describe the test suite for the Ergo class describe('Ergo', () => { - let ergo: Ergo; - beforeEach(() => { - // Arrange: Mock the return value of getErgoConfig to simulate Mainnet configuration before each test - pathGetErgoConfig('Mainnet'); - - // Arrange: Create a new instance of Ergo with 'Mainnet' configuration before each test - ergo = new Ergo('Mainnet'); - }); // Test case to verify initialization with Mainnet configuration it('Should initialize with Mainnet configuration', () => { // Assert: Validate the initialization state of Ergo instance @@ -324,23 +347,22 @@ describe('Ergo', () => { }); }); + // Describe the test suite for the getAddressUnspentBoxes method describe('getAddressUnspentBoxes', () => { + // Mock address for testing const mockAddress = '9j2s7d8f4s8s8o8s0q8f5s8d7f8s0d4r5'; + + // Test case to verify the return of an empty array when there are no unspent boxes it('Should return an empty arry when length of nodeBoxes is 0', async () => { - jest - .spyOn(ergo['_node'], 'getUnspentBoxesByAddress') - .mockResolvedValue([]); + // Arrange: Mock the getUnspentBoxesByAddress method to return an empty array + await patchErgo_node(); const utxos = await ergo.getAddressUnspentBoxes(mockAddress); expect(utxos).toEqual([]); - expect(ergo['_node'].getUnspentBoxesByAddress).toHaveBeenCalledWith( - mockAddress, - 0, - 100, - ); }); + // Test case to verify the retrieval of all unspent boxes for the given address it('Should retrieve all unspent boxes for the given address', async () => { - // Arrange + // Arrange: Mock the getUnspentBoxesByAddress method to return 3 boxes const mockUnspentBoxesPage1 = [ { boxId: 'box1' }, { boxId: 'box2' }, @@ -353,10 +375,10 @@ describe('Ergo', () => { .mockResolvedValueOnce(mockUnspentBoxesPage2) .mockResolvedValueOnce(mockUnspentBoxesPage3); - // Act + // Act: Call the getAddressUnspentBoxes method const result = await ergo.getAddressUnspentBoxes(mockAddress); - // Assert + // Assert: Validate that an empty array is returned expect(result).toEqual([ { boxId: 'box1' }, { boxId: 'box2' }, @@ -380,4 +402,37 @@ describe('Ergo', () => { ); }); }); + + // Describe the test suite for the getAccountFromSecretKey method + describe('getAccountFromSecretKey', () => { + // Test case to verify the return of an account with address and wallet + it('Should return an account with address and wallet', () => { + // Mock secret key + const secret = + '591811a0d6361f18e42549b32e65b98c9a63d6aad369d1056a97ca81f2a980d5'; + + // Patch methods for mock implementation + patchFrom_secrets(); + patchTo_base58(); + + // Arrange: Mock get_address method + const mockGetAddress = jest.fn().mockReturnValue(new Address()); + const mockSecretKeyInstance = { + get_address: mockGetAddress, + } as unknown as SecretKey; + jest + .spyOn(SecretKey, 'dlog_from_bytes') + .mockReturnValue(mockSecretKeyInstance); + // Arrange: Mock add method for SecretKeys + const mockAdd = jest.fn(); + jest.spyOn(SecretKeys.prototype, 'add').mockImplementation(mockAdd); + + // Act: Call the getAccountFromSecretKey method + const result = ergo.getAccountFromSecretKey(secret); + + // Assert: Validate the returned address and wallet + expect(result.address).toBe('testAddress'); + expect(result.wallet).toBe('testWallet'); + }); + }); }); From 1f612487c1ed43bf76b1f43b50ca975f4aa27082 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Sun, 16 Jun 2024 14:54:03 +0330 Subject: [PATCH 030/132] add [unit-test]: Implement unit tests for "Ergo" => "encrypt" and "decrypt" methods --- test/chains/ergo/ergo.test.ts | 156 +++++++++++++++++++++++++++++++--- 1 file changed, 144 insertions(+), 12 deletions(-) diff --git a/test/chains/ergo/ergo.test.ts b/test/chains/ergo/ergo.test.ts index 143c79e04a..c4540c9aff 100644 --- a/test/chains/ergo/ergo.test.ts +++ b/test/chains/ergo/ergo.test.ts @@ -143,13 +143,13 @@ describe('Ergo', () => { // Describe the test suite for the get network method describe('get network', () => { // Test case to verify network value when initialized with Mainnet - it('should return the correct network when network is Mainnet', () => { + it('Should return the correct network when network is Mainnet', () => { // Assert: Validate the return value expect(ergo.network).toBe('Mainnet'); }); // Test case to verify network value when initialized with Testnet - it('should return the correct network when network is Testnet', () => { + it('Should return the correct network when network is Testnet', () => { // Arrange: Mock the return value of getErgoConfig to simulate Testnet configuration pathGetErgoConfig('Testnet'); @@ -164,7 +164,7 @@ describe('Ergo', () => { // Describe the test suite for the get network method describe('get storedAssetList', () => { // Test case to verify the stored asset list - it('should return the stored asset list', () => { + it('Should return the stored asset list', () => { // Arrange: Create mock assets and populate _assetMap const asset1: ErgoAsset = 1 as any; const asset2: ErgoAsset = 2 as any; @@ -184,7 +184,7 @@ describe('Ergo', () => { // Describe the test suite for the ready method describe('ready', () => { // Test case to verify the return value of the ready method - it('should return the ready state', () => { + it('Should return the ready state', () => { // Assert: Initially, the ready state should be false expect(ergo.ready()).toBe(false); @@ -210,7 +210,7 @@ describe('Ergo', () => { // Describe the test suite for the close method describe('close', () => { // Test case to verify the close method - it('should close correctly', async () => { + it('Should close correctly', async () => { // Act and Assert: Call the close method and expect that the close method resolves without any errors or values await expect(ergo.close()).resolves.toBeUndefined(); }); @@ -229,7 +229,7 @@ describe('Ergo', () => { }); // Test that the LRUCache is initialized if it hasn't been already - it('should initialize the LRUCache if not already initialized', () => { + it('Should initialize the LRUCache if not already initialized', () => { // Act: Call the getInstance method with the mock network Ergo.getInstance(mockNetwork); @@ -239,7 +239,7 @@ describe('Ergo', () => { }); // Test that a new Ergo instance is created and returned if it's not in the cache - it('should set and return a new Ergo instance if not in the cache', () => { + it('Should set and return a new Ergo instance if not in the cache', () => { // Act: Call the getInstance method with the mock network const instance = Ergo.getInstance(mockNetwork); @@ -250,7 +250,7 @@ describe('Ergo', () => { }); // Test that an existing Ergo instance is returned from the cache - it('should return an existing Ergo instance from the cache', () => { + it('Should return an existing Ergo instance from the cache', () => { // Act: Call the getInstance method twice with the mock network const instance1 = Ergo.getInstance(mockNetwork); const instance2 = Ergo.getInstance(mockNetwork); @@ -261,7 +261,7 @@ describe('Ergo', () => { }); // Test that an error is thrown if an unexpected network is provided - it('should throw an error if an unexpected network is provided', () => { + it('Should throw an error if an unexpected network is provided', () => { // Act and Assert: Expect that calling getInstance with an empty string throws an error expect(() => Ergo.getInstance('')).toThrow( 'Ergo.getInstance received an unexpected network: .', @@ -288,7 +288,7 @@ describe('Ergo', () => { Ergo['_instances'].set('Testnet2', mockErgoInstance2); }); // Test case to verify that all connected instances are returned - it('should return all connected instances', () => { + it('Should return all connected instances', () => { // Act: Call the getConnectedInstances method const connectedInstances = Ergo.getConnectedInstances(); @@ -302,7 +302,7 @@ describe('Ergo', () => { }); // Test case to verify that an empty object is returned if no instances exist - it('should return an empty object if there are no instances', () => { + it('Should return an empty object if there are no instances', () => { // Arrange: Clear the _instances LRUCache Ergo['_instances'] = undefined as any; @@ -314,7 +314,7 @@ describe('Ergo', () => { }); // Test case to verify that only valid instances are returned - it('should return only valid instances', () => { + it('Should return only valid instances', () => { // Arrange: Set an invalid (null) instance in the _instances LRUCache Ergo['_instances'].set('', null as any); @@ -435,4 +435,136 @@ describe('Ergo', () => { expect(result.wallet).toBe('testWallet'); }); }); + + // Describe the test suite for the encrypt method + describe('encrypt', () => { + // Test case to verify encryption of a secret with a given password + it('Should encrypt a secret with a given password', () => { + // Arrange: Set up the secret and password + const secret = 'mySecret'; + const password = 'myPassword'; + + // Act: Call the encrypt method + const encryptedText = ergo.encrypt(secret, password); + + // Assert: Verify the encrypted text format + expect(encryptedText).toMatch(/^[0-9a-fA-F]{32}:[0-9a-fA-F]+$/); + }); + + // Test case to ensure different encryption outputs for different secrets + it('Should produce different encryption outputs for different secrets', () => { + // Arrange: Set up the password + const password = 'myPassword'; + + // Act: Call the encrypt method with two different secrets + const encryptedText1 = ergo.encrypt('secret1', password); + const encryptedText2 = ergo.encrypt('secret2', password); + + // Assert: Verify that the encrypted texts are different + expect(encryptedText1).not.toBe(encryptedText2); + }); + + // Test case to ensure different encryption outputs for different passwords + it('Should produce different encryption outputs for different passwords', () => { + // Arrange: Set up the secret + const secret = 'mySecret'; + + // Act: Call the encrypt method with two different passwords + const encryptedText1 = ergo.encrypt(secret, 'password1'); + const encryptedText2 = ergo.encrypt(secret, 'password2'); + + // Assert: Verify that the encrypted texts are different + expect(encryptedText1).not.toBe(encryptedText2); + }); + + // Test case to ensure different IVs for different encryptions + it('Should produce different IVs for different encryptions', () => { + // Arrange: Set up the secret and password + const secret = 'mySecret'; + const password = 'myPassword'; + + // Act: Call the encrypt method twice with the same secret and password + const encryptedText1 = ergo.encrypt(secret, password); + const encryptedText2 = ergo.encrypt(secret, password); + + // Extract IVs from the encrypted texts + const [iv1] = encryptedText1.split(':'); + const [iv2] = encryptedText2.split(':'); + + // Assert: Verify that the IVs are different + expect(iv1).not.toBe(iv2); + }); + + // Test case to handle passwords longer than 32 bytes + it('Should handle edge case where password is longer than 32 bytes', () => { + // Arrange: Set up the secret and a long password + const secret = 'mySecret'; + const longPassword = 'a'.repeat(50); // 50 bytes password + + // Act: Call the encrypt method + const encryptedText = ergo.encrypt(secret, longPassword); + + // Assert: Verify the encrypted text format + expect(encryptedText).toMatch(/^[0-9a-fA-F]{32}:[0-9a-fA-F]+$/); + }); + }); + + // Describe the test suite for the decrypt method + describe('decrypt', () => { + // Test case to verify correct decryption of an encrypted secret + it('Should decrypt an encrypted secret correctly', () => { + // Arrange: Set up the secret and password, and encrypt the secret + const secret = 'mySecret'; + const password = 'myPassword'; + const encryptedText = ergo.encrypt(secret, password); + + // Act: Call the decrypt method + const decryptedText = ergo.decrypt(encryptedText, password); + + // Assert: Verify that the decrypted text matches the original secret + expect(decryptedText).toBe(secret); + }); + + // Test case to ensure decryption fails with wrong password + it('Should fail to decrypt with wrong password', () => { + // Arrange: Set up the secret, correct password, wrong password, and encrypt the secret + const secret = 'mySecret'; + const correctPassword = 'correctPassword'; + const wrongPassword = 'wrongPassword'; + const encryptedText = ergo.encrypt(secret, correctPassword); + + // Act & Assert: Call the decrypt method with the wrong password and expect an error + expect(() => { + ergo.decrypt(encryptedText, wrongPassword); + }).toThrow(); + }); + + // Test case to handle passwords longer than 32 bytes + it('Should handle edge case where password is longer than 32 bytes', () => { + // Arrange: Set up the secret and a long password, and encrypt the secret + const secret = 'mySecret'; + const longPassword = 'a'.repeat(50); // 50 bytes password + const encryptedText = ergo.encrypt(secret, longPassword); + + // Act: Call the decrypt method + const decryptedText = ergo.decrypt(encryptedText, longPassword); + + // Assert: Verify that the decrypted text matches the original secret + expect(decryptedText).toBe(secret); + }); + + // Test case to handle passwords exactly 32 bytes long + it('Should handle case where password is exactly 32 bytes', () => { + // Arrange: Set up the secret and a 32 bytes password, and encrypt the secret + const secret = 'mySecret'; + const exact32BytesPassword = 'a'.repeat(32); // 32 bytes password + const encryptedText = ergo.encrypt(secret, exact32BytesPassword); + + // Act: Call the decrypt method + const decryptedText = ergo.decrypt(encryptedText, exact32BytesPassword); + + // Assert: Verify that the decrypted text matches the original secret + expect(decryptedText).toBe(secret); + }); + }); }); From f6db7b70c49f20fa285df48e8ddc999cdeca9862 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Mon, 17 Jun 2024 12:32:42 +0330 Subject: [PATCH 031/132] add [unit-test]: Implement unit tests for "Ergo" => "getAssetBalance" and "loadAssets" methods --- test/chains/ergo/ergo.test.ts | 172 +++++++++++++++++++++++++++++----- 1 file changed, 149 insertions(+), 23 deletions(-) diff --git a/test/chains/ergo/ergo.test.ts b/test/chains/ergo/ergo.test.ts index c4540c9aff..4b9a46cb10 100644 --- a/test/chains/ergo/ergo.test.ts +++ b/test/chains/ergo/ergo.test.ts @@ -13,6 +13,7 @@ import { Explorer } from '@ergolabs/ergo-sdk'; import { DexService } from '../../../src/chains/ergo/dex.service'; import { ErgoController } from '../../../src/chains/ergo/ergo.controller'; import { + ErgoAccount, ErgoAsset, ErgoBox, } from '../../../src/chains/ergo/interfaces/ergo.interface'; @@ -30,29 +31,6 @@ jest.mock('@ergolabs/ergo-sdk', () => ({ // Initializing Ergo instance for testing let ergo: Ergo; -// Before each test, configure and initialize Ergo with 'Mainnet' settings -beforeEach(() => { - // Arrange: Mock the return value of getErgoConfig to simulate Mainnet configuration before each test - pathGetErgoConfig('Mainnet'); - - // Arrange: Create a new instance of Ergo with 'Mainnet' configuration before each test - ergo = new Ergo('Mainnet'); -}); - -// Helper function to patch Wallet.from_secrets method for testing -const patchFrom_secrets = () => { - patch(Wallet, 'from_secrets', () => { - return 'testWallet' as any; - }); -}; - -// Helper function to patch Address.prototype.to_base58 method for testing -const patchTo_base58 = () => { - patch(Address.prototype, 'to_base58', () => { - return 'testAddress' as any; - }); -}; - // Helper function to patch getErgoConfig for Mainnet configuration const pathGetErgoConfig = (imputNetwork: string) => { patch(ergo_cofing, 'getErgoConfig', () => { @@ -76,11 +54,62 @@ const pathGetErgoConfig = (imputNetwork: string) => { }); }; +// Helper function to patch Wallet.from_secrets method for testing +const patchFrom_secrets = () => { + patch(Wallet, 'from_secrets', () => { + return 'testWallet' as any; + }); +}; + +// Helper function to patch Address.prototype.to_base58 method for testing +const patchTo_base58 = () => { + patch(Address.prototype, 'to_base58', () => { + return 'testAddress' as any; + }); +}; + const patchErgo_node = async () => { patch(ergo['_node'], 'getUnspentBoxesByAddress', () => { return []; }); }; + +// Helper function to patch ergo.getAddressUnspentBoxes method for testing +const patchGetAddressUnspentBoxes = () => { + patch(ergo, 'getAddressUnspentBoxes', () => { + return []; + }); +}; + +// Helper function to patch ergo.getAssetData method for testing +const patchGetAssetData = () => { + patch(ergo, 'getAssetData', () => { + return { + tokens: [ + { + address: + 'ba553573f83c61be880d79db0f4068177fa75ab7c250ce3543f7e7aeb471a9d2', + decimals: 7, + name: '$Bass Token', + ticker: '$bass', + logoURI: + 'https://cloudflare-ipfs.com/ipfs/bafybeifjq7aaleq2eg4o4vhqsg2zjow6pkbb3upb7vpz6g24r777ikh5ua', + project: '$Bass', + description: 'Memecoin of the Ergo ecosystem', + }, + ], + }; + }); +}; + +// Before each test, configure and initialize Ergo with 'Mainnet' settings +beforeEach(() => { + // Arrange: Mock the return value of getErgoConfig to simulate Mainnet configuration before each test + pathGetErgoConfig('Mainnet'); + + // Arrange: Create a new instance of Ergo with 'Mainnet' configuration before each test + ergo = new Ergo('Mainnet'); +}); // Clean up mocks after each test afterEach(() => { unpatch(); @@ -567,4 +596,101 @@ describe('Ergo', () => { expect(decryptedText).toBe(secret); }); }); + + // Describe the test suite for the getAssetBalance method + describe('getAssetBalance', () => { + // Test case to ensure balance is 0 when there are no unspent boxes + it('Should return balance as 0 when there are no unspent boxes', async () => { + // Arrange: Set up the account and asset map, and mock the getAddressUnspentBoxes method to return an empty array + const account: ErgoAccount = { address: 'mockAddress' } as any; + ergo['_assetMap'] = { + assetName: { tokenId: 1 }, + } as any; + patchGetAddressUnspentBoxes(); + + // Act: Call the getAssetBalance method + const balance = await ergo.getAssetBalance(account, 'assetName'); + + // Assert: Verify that the balance is 0 + expect(balance).toBe('0'); + }); + + // Test case to ensure balance is 0 when there are no matching assets + it('should return balance as 0 when there are no matching assets', async () => { + // Arrange: Set up the account, asset map, and mock the getAddressUnspentBoxes method to return utxos without matching assets + const account: ErgoAccount = { address: 'mockAddress' } as any; + ergo['_assetMap'] = { + assetName: { tokenId: 1 }, + } as any; + const utxos = [{ assets: [{ tokenId: 2, amount: '100' }] }]; + jest + .spyOn(ergo, 'getAddressUnspentBoxes') + .mockResolvedValue(utxos as any); + + // Act: Call the getAssetBalance method + const balance = await ergo.getAssetBalance(account, 'assetName'); + + // Assert: Verify that the balance is 0 + expect(balance).toBe('0'); + }); + + // Test case to ensure correct balance is returned when there are matching assets + it('Should return correct balance when there are matching assets', async () => { + // Arrange: Set up the account, asset map, and mock the getAddressUnspentBoxes method to return utxos with matching assets + const account: ErgoAccount = { address: 'mockAddress' } as any; + ergo['_assetMap'] = { + assetName: { tokenId: 1 }, + } as any; + const utxos = [ + { assets: [{ tokenId: '1', amount: 100 }] }, + { assets: [{ tokenId: '1', amount: 200 }] }, + ]; + jest + .spyOn(ergo, 'getAddressUnspentBoxes') + .mockResolvedValue(utxos as any); + + // Act: Call the getAssetBalance method + const balance = await ergo.getAssetBalance(account, 'assetName'); + + // Assert: Verify that the balance is correct + expect(balance).toBe('300'); + }); + + // Test case to ensure error is thrown when getAddressUnspentBoxes fails + it('Should throw an error when getAddressUnspentBoxes fails', async () => { + // Arrange: Set up the account and mock the getAddressUnspentBoxes method to reject with an error + const account: ErgoAccount = { address: 'mockAddress' } as any; + jest + .spyOn(ergo, 'getAddressUnspentBoxes') + .mockRejectedValue(new Error('some error')); + + // Act & Assert: Call the getAssetBalance method and expect it to throw an error + await expect(ergo.getAssetBalance(account, 'assetName')).rejects.toThrow( + 'problem during finding account assets ergo Node!', + ); + }); + }); + + // Describe the test suite for the loadAssets method + describe('loadAssets', () => { + // Test case to ensure assets are loaded and assetMap object is updated + it('Should load Assets and update assetMap object', async () => { + // Arrange: Set up the assetMap and mock the getAssetData method + ergo['_assetMap'] = {}; + patchGetAssetData(); + + // Act: Call the loadAssets method + await ergo['loadAssets'](); + + // Assert: Verify that the assetMap is updated correctly + expect(ergo['_assetMap']).toEqual({ + '$BASS TOKEN': { + tokenId: NaN, // This is wrong + decimals: 7, + name: '$Bass Token', + symbol: '$bass', + }, + }); + }); + }); }); From 02ea6d1bbe4dfb6286ad6252615ed8cfaffcc4f2 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Tue, 18 Jun 2024 09:16:26 +0330 Subject: [PATCH 032/132] fix [ergo]: fix tokenId to get string and update the related interface --- src/chains/ergo/ergo.ts | 3 +-- src/chains/ergo/interfaces/ergo.interface.ts | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 89344129ff..ce1204713b 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -16,7 +16,6 @@ import { ErgoBox, ErgoConnectedInstance, } from './interfaces/ergo.interface'; -import { toNumber } from 'lodash'; import { AmmPool, makeNativePools } from '@ergolabs/ergo-dex-sdk'; import { Explorer } from '@ergolabs/ergo-sdk'; @@ -266,7 +265,7 @@ export class Ergo { for (const result of assetData.tokens) { this._assetMap[result.name.toUpperCase()] = { - tokenId: toNumber(result.address), + tokenId: result.address, decimals: result.decimals, name: result.name, symbol: result.ticker, diff --git a/src/chains/ergo/interfaces/ergo.interface.ts b/src/chains/ergo/interfaces/ergo.interface.ts index 0b5a1a43fc..535bd24108 100644 --- a/src/chains/ergo/interfaces/ergo.interface.ts +++ b/src/chains/ergo/interfaces/ergo.interface.ts @@ -19,7 +19,7 @@ export interface ErgoConfig { } export interface ErgoAsset { - tokenId: number; + tokenId: string; decimals: number; name: string; symbol: string; From 6b45589b3f651395daeae40916480405347664ce Mon Sep 17 00:00:00 2001 From: satiparpar Date: Wed, 19 Jun 2024 14:43:16 +0330 Subject: [PATCH 033/132] add [unit-test]: Implement unit tests for "Ergo" => "getAssetData", "loadPools", "getPoolData" and "storedTokenList" methods --- test/chains/ergo/ergo.test.ts | 243 +++++++++++++++++++++++++++++++--- 1 file changed, 226 insertions(+), 17 deletions(-) diff --git a/test/chains/ergo/ergo.test.ts b/test/chains/ergo/ergo.test.ts index 4b9a46cb10..260d70c85a 100644 --- a/test/chains/ergo/ergo.test.ts +++ b/test/chains/ergo/ergo.test.ts @@ -18,6 +18,7 @@ import { ErgoBox, } from '../../../src/chains/ergo/interfaces/ergo.interface'; import LRUCache from 'lru-cache'; +import { makeNativePools } from '@ergolabs/ergo-dex-sdk'; // Mocking dependencies for testing purposes using jest jest.mock('@ergolabs/ergo-dex-sdk', () => ({ @@ -32,7 +33,7 @@ jest.mock('@ergolabs/ergo-sdk', () => ({ let ergo: Ergo; // Helper function to patch getErgoConfig for Mainnet configuration -const pathGetErgoConfig = (imputNetwork: string) => { +const patchGetErgoConfig = (imputNetwork: string) => { patch(ergo_cofing, 'getErgoConfig', () => { return { network: { @@ -102,10 +103,40 @@ const patchGetAssetData = () => { }); }; +// Helper function to patch getTokens method for testing +const patchGetTokens = () => { + patch(ergo['_dex'], 'getTokens', () => { + return { + name: 'Spectrum Finance Ergo Token List', + timestamp: '2024-04-02T08:05:42.697Z', + version: { + major: 2, + minor: 0, + patch: 0, + }, + tags: {}, + keywords: ['spectrum finance', 'tokens', 'ergo tokens'], + tokens: [ + { + address: + 'ba553573f83c61be880d79db0f4068177fa75ab7c250ce3543f7e7aeb471a9d2', + decimals: 7, + name: '$Bass Token', + ticker: '$bass', + logoURI: + 'https://cloudflare-ipfs.com/ipfs/bafybeifjq7aaleq2eg4o4vhqsg2zjow6pkbb3upb7vpz6g24r777ikh5ua', + project: '$Bass', + description: 'Memecoin of the Ergo ecosystem', + }, + ], + }; + }); +}; + // Before each test, configure and initialize Ergo with 'Mainnet' settings beforeEach(() => { // Arrange: Mock the return value of getErgoConfig to simulate Mainnet configuration before each test - pathGetErgoConfig('Mainnet'); + patchGetErgoConfig('Mainnet'); // Arrange: Create a new instance of Ergo with 'Mainnet' configuration before each test ergo = new Ergo('Mainnet'); @@ -113,6 +144,7 @@ beforeEach(() => { // Clean up mocks after each test afterEach(() => { unpatch(); + jest.clearAllMocks(); }); // Describe the test suite for the Ergo class describe('Ergo', () => { @@ -136,7 +168,7 @@ describe('Ergo', () => { // Test case to verify initialization with Testnet configuration it('Should initialize with Mainnet configuration', () => { // Arrange: Mock the return value of getErgoConfig to simulate Testnet configuration - pathGetErgoConfig('Testnet'); + patchGetErgoConfig('Testnet'); // Act: Create a new instance of Ergo with 'Testnet' configuration const ergo = new Ergo('Testnet'); @@ -180,7 +212,7 @@ describe('Ergo', () => { // Test case to verify network value when initialized with Testnet it('Should return the correct network when network is Testnet', () => { // Arrange: Mock the return value of getErgoConfig to simulate Testnet configuration - pathGetErgoConfig('Testnet'); + patchGetErgoConfig('Testnet'); // Act: Create a new instance of Ergo with 'Testnet' configuration ergo = new Ergo('Testnet'); @@ -214,7 +246,7 @@ describe('Ergo', () => { describe('ready', () => { // Test case to verify the return value of the ready method it('Should return the ready state', () => { - // Assert: Initially, the ready state should be false + // Arrange: Initially, the ready state should be false expect(ergo.ready()).toBe(false); // Act: Manually set the _ready state to true @@ -225,16 +257,23 @@ describe('Ergo', () => { }); }); - // describe('', () => { - // it('should initialize assets and pools in init method', async () => { - // const loadAssetsSpy = jest.spyOn(ergo as any, 'loadAssets').mockResolvedValue(); - // const loadPoolsSpy = jest.spyOn(ergo as any, 'loadPools').mockResolvedValue(); - // await ergo.init(); - // expect(loadAssetsSpy).toHaveBeenCalled(); - // expect(loadPoolsSpy).toHaveBeenCalled(); - // expect(ergo.ready()).toBe(true); - // }); - // }); + // Describe the test suite for the init method + describe('init', () => { + // Test case to verify the initialization process in the init method + it('Should initialize assets and pools in init method', async () => { + // Arrange: Mock the loadAssets & loadPools methods to return a fixed value + jest.spyOn(ergo as any, 'loadAssets').mockResolvedValue({}); + jest.spyOn(ergo as any, 'loadPools').mockResolvedValue({}); + + // Act: Call the init method to initialize assets and pools + await ergo.init(); + + // Assert: Ensure the loadAssets & loadPools methods were called during initialization + expect(ergo['loadAssets']).toHaveBeenCalled(); + expect(ergo['loadPools']).toHaveBeenCalled(); + expect(ergo.ready()).toBe(true); + }); + }); // Describe the test suite for the close method describe('close', () => { @@ -252,7 +291,7 @@ describe('Ergo', () => { // This block runs before each test in this suite beforeEach(() => { // Arrange: Mock the function to get the configuration for the 'Testnet' network - pathGetErgoConfig('Testnet'); + patchGetErgoConfig('Testnet'); // Arrange: Clear the singleton and mock instances Ergo['_instances'] = undefined as any; }); @@ -685,7 +724,8 @@ describe('Ergo', () => { // Assert: Verify that the assetMap is updated correctly expect(ergo['_assetMap']).toEqual({ '$BASS TOKEN': { - tokenId: NaN, // This is wrong + tokenId: + 'ba553573f83c61be880d79db0f4068177fa75ab7c250ce3543f7e7aeb471a9d2', decimals: 7, name: '$Bass Token', symbol: '$bass', @@ -693,4 +733,173 @@ describe('Ergo', () => { }); }); }); + + // Describe the test suite for the getAssetData method + describe('getAssetData', () => { + // Test case to ensure getAssetData returns all tokens with details + it('Should return all token with the details', async () => { + // Mock getTokens method to return predefined data + patchGetTokens(); + + // Act & Assert: Validate the returned data structure + expect(await ergo['getAssetData']()).toEqual({ + name: 'Spectrum Finance Ergo Token List', + timestamp: '2024-04-02T08:05:42.697Z', + version: { + major: 2, + minor: 0, + patch: 0, + }, + tags: {}, + keywords: ['spectrum finance', 'tokens', 'ergo tokens'], + tokens: [ + { + address: + 'ba553573f83c61be880d79db0f4068177fa75ab7c250ce3543f7e7aeb471a9d2', + decimals: 7, + name: '$Bass Token', + ticker: '$bass', + logoURI: + 'https://cloudflare-ipfs.com/ipfs/bafybeifjq7aaleq2eg4o4vhqsg2zjow6pkbb3upb7vpz6g24r777ikh5ua', + project: '$Bass', + description: 'Memecoin of the Ergo ecosystem', + }, + ], + }); + }); + }); + + // Describe the test suite for the loadPools method + describe('loadPools', () => { + // Test case to ensure ammPools remains empty when no PoolData is provided + it('Should push nothing to ammPools when no PoolData is provided', async () => { + // Arrange: Mock getPoolData to return an empty array + jest.spyOn(ergo as any, 'getPoolData').mockResolvedValue([] as any); + ergo['ammPools'] = []; + + // Act: Call the method under test + await ergo['loadPools'](); + + // Assert: Ensure ammPools remains empty + expect(ergo['ammPools']).toEqual([]); + }); + + // Test case to ensure ammPools contains provided PoolData when available + it('Should push nothing to ammPools when no PoolData is provided', async () => { + // Arrange: Mock getPoolData to return specific pool data + jest + .spyOn(ergo as any, 'getPoolData') + .mockResolvedValueOnce([{ id: '1' }, { id: 2 }] as any); + jest.spyOn(ergo as any, 'getPoolData').mockResolvedValueOnce([] as any); + + // Act: Call the method under test + ergo['ammPools'] = []; + await ergo['loadPools'](); + + // Assert: Verify ammPools contains expected pool data + expect(ergo['ammPools']).toEqual([{ id: '1' }, { id: 2 }]); + }); + + // Test case to ensure ammPools merges new pools without duplicates + it('Should not add duplicate pools to ammPools', async () => { + // Arrange: Mock getPoolData to simulate incremental pool data loading + const initialPools: any = [ + { id: 1, name: 'Pool 1' }, + { id: 2, name: 'Pool 2' }, + ]; + const newPools: any = [ + { id: 2, name: 'Pool 2' }, + { id: 3, name: 'Pool 3' }, + ]; + + jest + .spyOn(ergo as any, 'getPoolData') + .mockResolvedValueOnce(initialPools) + .mockResolvedValueOnce(newPools) + .mockResolvedValueOnce([]); + + ergo['ammPools'] = []; + + // Act: Call the method under test + await ergo['loadPools'](); + + // Assert: Verify ammPools contains merged pool data without duplicates + expect(ergo['ammPools']).toEqual([ + { id: 1, name: 'Pool 1' }, + { id: 2, name: 'Pool 2' }, + { id: 3, name: 'Pool 3' }, + ]); + }); + }); + + // Describe the test suite for the getPoolData method + describe('getPoolData', () => { + // Test case to ensure makeNativePools and getAll are called with correct parameters + it('Should call makeNativePools and getAll with correct parameters', async () => { + // Arrange: Mock makeNativePools and getAll methods + const mockGetAll = jest.fn().mockResolvedValue([]); + (makeNativePools as any).mockReturnValue({ getAll: mockGetAll }); + + const limit = 10; + const offset = 0; + + // Act: Call the method under test + await ergo['getPoolData'](limit, offset); + + // Assert: Ensure makeNativePools and getAll were called with correct parameters + expect(makeNativePools).toHaveBeenCalledWith(ergo['_explorer']); + expect(mockGetAll).toHaveBeenCalledWith({ limit, offset }); + }); + + // Test case to ensure getPoolData returns expected data from getAll method + it('Should return the data from getAll method', async () => { + // Arrange: Mock getAll method to return specific data + const expectedData = [{ id: 1, name: 'Pool 1' }]; + const mockGetAll = jest.fn().mockResolvedValue(expectedData); + (makeNativePools as any).mockReturnValue({ getAll: mockGetAll }); + + const limit = 10; + const offset = 0; + + // Act: Call the method under test + const result = await ergo['getPoolData'](limit, offset); + + // Assert: Verify the method returns expected data + expect(result).toEqual(expectedData); + }); + + // Test case to ensure getPoolData handles errors from getAll method + it('Should handle errors from getAll method', async () => { + // Arrange: Mock getAll method to simulate error + const mockGetAll = jest.fn().mockRejectedValue(new Error('Test error')); + (makeNativePools as any).mockReturnValue({ getAll: mockGetAll }); + + const limit = 10; + const offset = 0; + + // Act & Assert: Ensure the method throws the expected error + await expect(ergo['getPoolData'](limit, offset)).rejects.toThrow( + 'Test error', + ); + }); + }); + + // Describe the test suite for the getPoolData method + describe('storedTokenList', () => { + it('Should return the stored asset list', () => { + // Arrange: Create mock assets and populate _assetMap + const asset1: ErgoAsset = 1 as any; + const asset2: ErgoAsset = 2 as any; + const assetMap = { + key1: asset1, + key2: asset2, + }; + + // Act: Set _assetMap directly + ergo['_assetMap'] = assetMap; + + // Assert: Validate the stored asset list returned by storedAssetList + expect(ergo.storedTokenList).toEqual(assetMap); + }); + }); }); From 6eaa8cb070e8f0116bb6564c861935f173c18e67 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Wed, 19 Jun 2024 19:28:45 +0330 Subject: [PATCH 034/132] update [unit-test]: delete wrong unit test files --- test/chains/ergo/dex.service.test.ts | 110 --------------------- test/chains/ergo/ergo.config.test.ts | 123 ----------------------- test/chains/ergo/node.service.test.ts | 134 -------------------------- 3 files changed, 367 deletions(-) delete mode 100644 test/chains/ergo/dex.service.test.ts delete mode 100644 test/chains/ergo/ergo.config.test.ts delete mode 100644 test/chains/ergo/node.service.test.ts diff --git a/test/chains/ergo/dex.service.test.ts b/test/chains/ergo/dex.service.test.ts deleted file mode 100644 index bfcff20b1b..0000000000 --- a/test/chains/ergo/dex.service.test.ts +++ /dev/null @@ -1,110 +0,0 @@ -import axios from 'axios'; -import { DexService } from '../../../src/chains/ergo/dex.service'; -import { DEXTokensResponse } from '../../../src/chains/ergo/interfaces/dex.interface'; - -// Mocking axios to intercept HTTP requests and return controlled responses -jest.mock('axios'); - -// Describe the test suite for the NodeService class -describe('DexService', () => { - // Define constants for baseURL and timeout - const baseURL = 'https://example.com'; - const timeout = 5000; - - // Initialize DexService instance - const dexService: DexService = new DexService(baseURL, timeout); - - // Test case to check if DexService is defined and its properties are set correctly - it('Should initialize with given baseURL and timeout', () => { - // Assert: Check if the dexURL and timeout properties are correctly set and instance is defined - expect(dexService).toBeDefined(); - expect(dexService['dexURL']).toBe(baseURL); - expect(dexService['timeout']).toBe(timeout); - }); - - // Describe the test suite for the private request method of NodeService - describe('request', () => { - // Define default parameters for the request method - const method = 'GET'; - const url = '/test-endpoint'; - const headers = { 'Content-Type': 'application/json' }; - const body = { key: 'value' }; - - // Test case for making a GET request with correct parameters - it('Should make a GET request with correct parameters', async () => { - // Arrange: Mock the axios response - const mockResponse = { data: { name: 'test' } }; - (axios as any).mockResolvedValue(mockResponse); - - // Act: Call the private request method with GET parameters - const response = await dexService['request'](method, url, headers); - - // Assert: Check if axios was called with the correct configuration - expect(axios).toHaveBeenCalledWith({ - baseURL, - url, - method, - headers, - timeout, - }); - // Assert: Check if the response is as expected - expect(response).toEqual({ name: 'test' }); - }); - - // Test case for making a POST request with correct parameters - it('Should make a POST request with correct parameters', async () => { - // Arrange: Change method to POST and mock the axios response - const method = 'POST'; - const mockResponse = { data: { name: 'test' } }; - (axios as any).mockResolvedValue(mockResponse); - - // Act: Call the private request method with POST parameters - const response = await dexService['request'](method, url, headers, body); - - // Assert: Check if axios was called with the correct configuration - expect(axios).toHaveBeenCalledWith({ - baseURL, - url, - method, - headers, - timeout, - body, - }); - // Assert: Check if the response is as expected - expect(response).toEqual({ name: 'test' }); - }); - }); - - // Describe the test suite for the getTokens method of NodeService - describe('getTokens', () => { - // Test case to call getTokens method and check return value and function input arguments - it('Should call request method with correct parameters', async () => { - // Arrange: Mock the response of the request method - const mockResponse: DEXTokensResponse = { - tokens: [ - { - address: '1', - name: 'Token1', - decimals: 0, - ticker: '', - logoURI: '', - project: '', - description: '', - }, - ], - }; - jest.spyOn(dexService as any, 'request').mockResolvedValue(mockResponse); - - // Act: Call the getTokens method - const response = await dexService.getTokens(); - - // Assert: Check if the request method was called with the correct parameters - expect(dexService['request']).toHaveBeenCalledWith( - 'GET', - '/ergo-token-list.json', - ); - // Assert: Check if the response from getTokens is as expected - expect(response).toEqual(mockResponse); - }); - }); -}); diff --git a/test/chains/ergo/ergo.config.test.ts b/test/chains/ergo/ergo.config.test.ts deleted file mode 100644 index 8c43d6c2af..0000000000 --- a/test/chains/ergo/ergo.config.test.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { getErgoConfig } from '../../../src/chains/ergo/ergo.config'; -import { ConfigManagerV2 } from '../../../src/services/config-manager-v2'; -import { NetworkPrefix } from 'ergo-lib-wasm-nodejs'; - -// Define the test suite for the getErgoConfig function -describe('getErgoConfig', () => { - // After each test, clear all mocks to ensure no interference between tests - afterEach(() => { - jest.clearAllMocks(); - }); - - // Test case for verifying the configuration returned for the Mainnet - it('Should return correct config for Mainnet', () => { - // Arrange: Mock the get method of ConfigManagerV2 to return specific values for Mainnet - jest - .spyOn(ConfigManagerV2.getInstance(), 'get') - .mockReturnValueOnce('ergo.networks.Mainnet.nodeURL'); - jest - .spyOn(ConfigManagerV2.getInstance(), 'get') - .mockReturnValueOnce('ergo.networks.Mainnet.explorerURL'); - jest - .spyOn(ConfigManagerV2.getInstance(), 'get') - .mockReturnValueOnce('ergo.networks.Mainnet.explorerDEXURL'); - jest.spyOn(ConfigManagerV2.getInstance(), 'get').mockReturnValueOnce(1000); - jest.spyOn(ConfigManagerV2.getInstance(), 'get').mockReturnValueOnce(2000); - - // Act: Call the function to be tested with 'Mainnet' as the argument - const res = getErgoConfig('Mainnet'); - - // Assert: Check that the returned configuration matches the expected values for Mainnet - expect(res).toEqual({ - network: { - name: 'Mainnet', - nodeURL: 'ergo.networks.Mainnet.nodeURL', - explorerURL: 'ergo.networks.Mainnet.explorerURL', - explorerDEXURL: 'ergo.networks.Mainnet.explorerDEXURL', - timeOut: 1000, - networkPrefix: NetworkPrefix.Mainnet, - minTxFee: 2000, - maxLRUCacheInstances: 10, - utxosLimit: 100, - poolLimit: 100, - defaultSlippage: 3, - defaultMinerFee: BigInt(2_000_000), - minNitro: 1.2, - minBoxValue: BigInt(400_000), - }, - }); - // Assert: Verify that the get method was called exactly five times with the expected arguments - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledTimes(5); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( - 'ergo.networks.Mainnet.nodeURL', - ); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( - 'ergo.networks.Mainnet.explorerURL', - ); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( - 'ergo.networks.Mainnet.explorerDEXURL', - ); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( - 'ergo.networks.Mainnet.timeOut', - ); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( - 'ergo.networks.Mainnet.minTxFee', - ); - }); - - // Test case for verifying the configuration returned for the Testnet - it('Should return correct config for Testnet', () => { - // Arrange: Mock the get method of ConfigManagerV2 to return specific values for Testnet - jest - .spyOn(ConfigManagerV2.getInstance(), 'get') - .mockReturnValueOnce('ergo.networks.Testnet.nodeURL'); - jest - .spyOn(ConfigManagerV2.getInstance(), 'get') - .mockReturnValueOnce('ergo.networks.Testnet.explorerURL'); - jest - .spyOn(ConfigManagerV2.getInstance(), 'get') - .mockReturnValueOnce('ergo.networks.Testnet.explorerDEXURL'); - jest.spyOn(ConfigManagerV2.getInstance(), 'get').mockReturnValueOnce(1000); - jest.spyOn(ConfigManagerV2.getInstance(), 'get').mockReturnValueOnce(2000); - - // Act: Call the function to be tested with 'Testnet' as the argument - const res = getErgoConfig('Testnet'); - - // Assert: Check that the returned configuration matches the expected values for Testnet - expect(res).toEqual({ - network: { - name: 'Testnet', - nodeURL: 'ergo.networks.Testnet.nodeURL', - explorerURL: 'ergo.networks.Testnet.explorerURL', - explorerDEXURL: 'ergo.networks.Testnet.explorerDEXURL', - timeOut: 1000, - networkPrefix: NetworkPrefix.Testnet, - minTxFee: 2000, - maxLRUCacheInstances: 10, - utxosLimit: 100, - poolLimit: 100, - defaultSlippage: 3, - defaultMinerFee: BigInt(2_000_000), - minNitro: 1.2, - minBoxValue: BigInt(400_000), - }, - }); - // Assert: Verify that the get method was called exactly five times with the expected arguments - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledTimes(5); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( - 'ergo.networks.Testnet.nodeURL', - ); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( - 'ergo.networks.Testnet.explorerURL', - ); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( - 'ergo.networks.Testnet.explorerDEXURL', - ); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( - 'ergo.networks.Testnet.timeOut', - ); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( - 'ergo.networks.Testnet.minTxFee', - ); - }); -}); diff --git a/test/chains/ergo/node.service.test.ts b/test/chains/ergo/node.service.test.ts deleted file mode 100644 index 2451444df9..0000000000 --- a/test/chains/ergo/node.service.test.ts +++ /dev/null @@ -1,134 +0,0 @@ -import axios from 'axios'; -import { NodeService } from '../../../src/chains/ergo/node.service'; -import { NodeInfoResponse } from '../../../src/chains/ergo/interfaces/node.interface'; - -// Mock axios to avoid making real HTTP requests during tests -jest.mock('axios'); - -// Describe the test suite for the NodeService class -describe('NodeService', () => { - // Define constants for baseURL and timeout - const baseURL = 'https://example.com'; - const timeout = 5000; - - // Initialize NodeService instance - const nodeService: NodeService = new NodeService(baseURL, timeout); - - // After each test, clear all mocks to ensure no interference between tests - afterEach(() => { - jest.clearAllMocks(); - }); - - // Test case to check if NodeService is defined and its properties are set correctly - it('Should be defined and and set nodeURL & timeout correctly', () => { - // Assert: Check if the nodeURL and timeout properties are correctly set and instance is defined - expect(nodeService).toBeDefined(); - expect(nodeService['nodeURL']).toEqual('https://example.com'); - expect(nodeService['timeout']).toEqual(5000); - }); - - describe('request', () => { - // Define default parameters for the request method - const method = 'GET'; - const url = '/test-endpoint'; - const headers = { 'Content-Type': 'application/json' }; - const body = { key: 'value' }; - - // Test case for making a GET request with correct parameters - it('Should make a GET request with correct parameters', async () => { - // Arrange: Mock the axios response - const mockResponse = { data: { name: 'test' } }; - (axios as any).mockResolvedValue(mockResponse); - - // Act: Call the private request method with GET parameters - const response = await nodeService['request'](method, url, headers); - - // Assert: Check if axios was called with the correct configuration - expect(axios).toHaveBeenCalledWith({ - baseURL, - url, - method, - headers, - timeout, - }); - // Assert: Check if the response is as expected - expect(response).toEqual({ name: 'test' }); - }); - - // Test case for making a POST request with correct parameters - it('Should make a POST request with correct parameters', async () => { - // Arrange: Change method to POST and mock the axios response - const method = 'POST'; - const mockResponse = { data: { name: 'test' } }; - (axios as any).mockResolvedValue(mockResponse); - - // Act: Call the private request method with POST parameters - const response = await nodeService['request'](method, url, headers, body); - - // Assert: Check if axios was called with the correct configuration - expect(axios).toHaveBeenCalledWith({ - baseURL, - url, - method, - headers, - timeout, - body, - }); - // Assert: Check if the response is as expected - expect(response).toEqual({ name: 'test' }); - }); - }); - - // Describe the test suite for the getNetworkHeight method - describe('getNetworkHeight', () => { - // Define a test case to check if getNetworkHeight is called with the correct parameters and returns the correct value - it('should call getNetworkHeight with correct parameters and returns the correct value', async () => { - // Define a mock response with fullHeight property - const res: NodeInfoResponse = { fullHeight: 100 }; - // Mock the private request method of nodeService to resolve with the mock response - jest.spyOn(nodeService as any, 'request').mockResolvedValue(res); - - // Call the getNetworkHeight method and store the result - const networkHeight = await nodeService.getNetworkHeight(); - - // Assert: Check if the returned network height is correct - expect(networkHeight).toEqual(100); - // Assert: Check if the private request method was called exactly once - expect(nodeService['request']).toHaveBeenCalledTimes(1); - // Assert: Check if the private request method was called with the correct HTTP method and URL - expect(nodeService['request']).toHaveBeenCalledWith('GET', '/info'); - }); - }); - - // Describe the test suite for the getUnspentBoxesByAddress method - describe('getUnspentBoxesByAddress', () => { - // Define constants for address, offset, and limit - const address = 'box-number-1.com'; - const offset = 10; - const limit = 20; - - // Define a test case to check if getUnspentBoxesByAddress is called with the correct parameters and returns the correct value - it('Should call getUnspentBoxesByAddress method with correct parameters and returns the correct value', async () => { - // Mock the private request method of nodeService to resolve with an empty data object - jest.spyOn(nodeService as any, 'request').mockResolvedValue({ data: {} }); - // Call the getUnspentBoxesByAddress method with the defined address, offset, and limit, and store the result - const unspentBoxesByAddress = await nodeService.getUnspentBoxesByAddress( - address, - offset, - limit, - ); - - // Assert: Check if the returned value matches the mock response - expect(unspentBoxesByAddress).toEqual({ data: {} }); - // Assert: Check if the private request method was called exactly once - expect(nodeService['request']).toHaveBeenCalledTimes(1); - // Assert: Check if the private request method was called with the correct HTTP method, URL, headers, and body - expect(nodeService['request']).toHaveBeenCalledWith( - 'POST', - `/blockchain/box/unspent/byAddress?offset=10&limit=20&sortDirection=desc`, - { 'Content-Type': 'text/plain' }, - 'box-number-1.com', - ); - }); - }); -}); From d1ca93d27671e6559f38053e5c1ef140cfb530b2 Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Wed, 19 Jun 2024 21:02:48 +0330 Subject: [PATCH 035/132] Resolved #9 --- src/chains/ergo/ergo.ts | 225 +++++++++++++++++++++++------ src/chains/ergo/node.service.ts | 39 ++++- src/chains/ergo/types/node.type.ts | 1 + 3 files changed, 215 insertions(+), 50 deletions(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 5702619f5d..7b46c5e336 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -3,26 +3,30 @@ import { SecretKey, SecretKeys, Wallet, - ErgoBoxes, UnsignedTransaction, + ErgoBoxes, + UnsignedTransaction, } from 'ergo-lib-wasm-nodejs'; import LRUCache from 'lru-cache'; -import {ErgoController} from './ergo.controller'; -import {NodeService} from './node.service'; -import {getErgoConfig} from './ergo.config'; -import {DexService} from './dex.service'; -import {createCipheriv, createDecipheriv, randomBytes} from 'crypto'; +import { ErgoController } from './ergo.controller'; +import { NodeService } from './node.service'; +import { getErgoConfig } from './ergo.config'; +import { DexService } from './dex.service'; +import { createCipheriv, createDecipheriv, randomBytes } from 'crypto'; import { ErgoAccount, ErgoAsset, ErgoBox, ErgoConnectedInstance, } from './interfaces/ergo.interface'; -import {toNumber} from 'lodash'; +import { toNumber } from 'lodash'; import { AmmPool, makeNativePools, - makeWrappedNativePoolActionsSelector, minValueForOrder, minValueForSetup, - SwapExtremums, SwapParams, + makeWrappedNativePoolActionsSelector, + minValueForOrder, + minValueForSetup, + SwapExtremums, + SwapParams, swapVars, } from '@ergolabs/ergo-dex-sdk'; import { @@ -39,11 +43,12 @@ import { publicKeyFromAddress, TransactionContext, Address, - BoxSelection, Input as TxInput, + BoxSelection, + Input as TxInput, } from '@ergolabs/ergo-sdk'; -import {makeTarget} from "@ergolabs/ergo-dex-sdk/build/main/utils/makeTarget"; -import {NativeExFeeType} from "@ergolabs/ergo-dex-sdk/build/main/types"; -import {NetworkContext} from "@ergolabs/ergo-sdk/build/main/entities/networkContext"; +import { makeTarget } from '@ergolabs/ergo-dex-sdk/build/main/utils/makeTarget'; +import { NativeExFeeType } from '@ergolabs/ergo-dex-sdk/build/main/types'; +import { NetworkContext } from '@ergolabs/ergo-sdk/build/main/entities/networkContext'; class Pool extends AmmPool { private name: string; @@ -54,6 +59,8 @@ class Pool extends AmmPool { this.name = `${this.x.asset.name}/${this.y.asset.name}`; } + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error private getName() { return this.name; } @@ -85,7 +92,7 @@ export type BaseInputParameters = { }; export const getBaseInputParameters = ( pool: AmmPool, - {inputAmount, slippage}: { inputAmount: any; slippage: number }, + { inputAmount, slippage }: { inputAmount: any; slippage: number }, ): BaseInputParameters => { const baseInputAmount = inputAmount.asset.id === pool.x.asset.id @@ -117,6 +124,8 @@ export const getInputs = ( const target = makeTarget(assets, minFeeForOrder); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error const inputs = DefaultBoxSelector.select(utxos, target, minBoxValue); if (inputs instanceof InsufficientInputs) { @@ -152,23 +161,38 @@ export class WalletProver implements Prover { /** Sign the given transaction. */ async sign(tx: UnsignedErgoTx): Promise { - const ctx = await this.nodeService.getCtx() + const ctx = await this.nodeService.getCtx(); const proxy = unsignedErgoTxToProxy(tx); - const wasmtx = UnsignedTransaction.from_json(JSON.stringify(proxy)) + const wasmtx = UnsignedTransaction.from_json(JSON.stringify(proxy)); try { - return this.wallet.sign_transaction(ctx, wasmtx, ErgoBoxes.from_boxes_json(proxy.inputs), ErgoBoxes.empty()).to_js_eip12() + return this.wallet + .sign_transaction( + ctx, + wasmtx, + ErgoBoxes.from_boxes_json(proxy.inputs), + ErgoBoxes.empty(), + ) + .to_js_eip12(); } catch { - throw new Error("not be able to sign!") + throw new Error('not be able to sign!'); } } async submit(tx: ErgoTx): Promise { - return await this.nodeService.postTransaction(tx) + const txId = await this.nodeService.postTransaction(tx); + return { + ...tx, + id: txId, + }; } + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + // eslint-disable-next-line @typescript-eslint/no-unused-vars signInput(tx: UnsignedErgoTx, input: number): Promise { - // @ts-ignore - return + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + return; } } @@ -317,7 +341,7 @@ export class Ergo { return { address, wallet, - prover: new WalletProver(wallet, this._node) + prover: new WalletProver(wallet, this._node), }; } @@ -416,51 +440,73 @@ export class Ergo { } private async getPoolData(limit: number, offset: number): Promise { - return await makeNativePools(this._explorer).getAll({limit, offset}); + return await makeNativePools(this._explorer).getAll({ limit, offset }); } public get storedTokenList() { return this._assetMap; } - - private async swap(account: ErgoAccount, pool: Pool, x_amount: bigint, y_amount: bigint, output_address: string, return_address: string): Promise { + private async swap( + account: ErgoAccount, + pool: Pool, + x_amount: bigint, + y_amount: bigint, + output_address: string, + return_address: string, + slippage: number, + ): Promise { const config = getErgoConfig(this.network); - const networkContext = await this._explorer.getNetworkContext() - const mainnetTxAssembler = new DefaultTxAssembler(this.network === 'Mainnet'); - const poolActions = makeWrappedNativePoolActionsSelector(output_address, account.prover, mainnetTxAssembler) - let utxos = await this.getAddressUnspentBoxes(account.address) + const networkContext = await this._explorer.getNetworkContext(); + const mainnetTxAssembler = new DefaultTxAssembler( + this.network === 'Mainnet', + ); + const poolActions = makeWrappedNativePoolActionsSelector( + output_address, + account.prover, + mainnetTxAssembler, + ); + const utxos = await this.getAddressUnspentBoxes(account.address); const to = { asset: { id: pool.x.asset.id, - decimals: pool.x.asset.decimals + decimals: pool.x.asset.decimals, }, - amount: x_amount - } + amount: x_amount, + }; const max_to = { asset: { - id: pool.x.asset.id + id: pool.x.asset.id, }, - amount: x_amount + x_amount / 10n - } + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + amount: x_amount + x_amount / 10n, + }; const from = { asset: { id: pool.y.asset.id, - decimals: pool.y.asset.decimals + decimals: pool.y.asset.decimals, }, - amount: pool.outputAmount(max_to as any, config.network.defaultSlippage).amount - } - const {baseInput, baseInputAmount, minOutput} = getBaseInputParameters( + amount: pool.outputAmount( + max_to as any, + slippage || config.network.defaultSlippage, + ).amount, + }; + const { baseInput, baseInputAmount, minOutput } = getBaseInputParameters( pool, { inputAmount: from, - slippage: config.network.defaultSlippage, + slippage: slippage || config.network.defaultSlippage, }, ); const swapVariables: [number, SwapExtremums] | undefined = swapVars( + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error config.network.defaultMinerFee * 3n, config.network.minNitro, minOutput, ); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error const [exFeePerToken, extremum] = swapVariables; const inputs = getInputs( utxos, @@ -470,10 +516,12 @@ export class Ergo { uiFee: BigInt(y_amount), exFee: extremum.maxExFee, }, - config.network.minBoxValue + config.network.minBoxValue, ); const swapParams: SwapParams = { poolId: pool.id, + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error pk: publicKeyFromAddress(output_address), baseInput, minQuoteOutput: extremum.minOutput.amount, @@ -491,7 +539,98 @@ export class Ergo { ); const actions = poolActions(pool); - return await actions - .swap(swapParams, txContext) + return await actions.swap(swapParams, txContext); + } + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + private async buy( + account: ErgoAccount, + pool: Pool, + x_amount: bigint, + y_amount: bigint, + output_address: string, + return_address: string, + slippage: number, + ): Promise { + return await this.swap( + account, + pool, + y_amount, + x_amount, + output_address, + return_address, + slippage, + ); + } + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + private async sell( + account: ErgoAccount, + pool: Pool, + x_amount: bigint, + y_amount: bigint, + output_address: string, + return_address: string, + slippage: number, + ): Promise { + return await this.swap( + account, + pool, + x_amount, + y_amount, + output_address, + return_address, + slippage, + ); + } + private async estimate( + pool: Pool, + x_amount: bigint, + slippage: number, + ): Promise { + const config = getErgoConfig(this.network); + const max_to = { + asset: { + id: pool.x.asset.id, + }, + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + amount: x_amount + x_amount / 10n, + }; + const from = { + asset: { + id: pool.y.asset.id, + decimals: pool.y.asset.decimals, + }, + amount: pool.outputAmount( + max_to as any, + slippage || config.network.defaultSlippage, + ).amount, + }; + const { minOutput } = getBaseInputParameters(pool, { + inputAmount: from, + slippage: slippage || config.network.defaultSlippage, + }); + return minOutput; + } + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + private async estimateBuy( + pool: Pool, + x_amount: bigint, + y_amount: bigint, + slippage: number, + ): Promise { + return await this.estimate(pool, y_amount, x_amount, slippage); + } + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + private async estimateSell( + pool: Pool, + x_amount: bigint, + y_amount: bigint, + slippage: number, + ): Promise { + return await this.estimate(pool, x_amount, y_amount, slippage); } } diff --git a/src/chains/ergo/node.service.ts b/src/chains/ergo/node.service.ts index 14da8c3079..17f68f322f 100644 --- a/src/chains/ergo/node.service.ts +++ b/src/chains/ergo/node.service.ts @@ -1,7 +1,14 @@ import axios from 'axios'; -import {NodeChainSliceResponse, NodeInfoResponse} from './interfaces/node.interface'; -import { NodeErgoBoxResponse } from './types/node.type'; -import {BlockHeaders, ErgoStateContext, PreHeader} from "ergo-lib-wasm-nodejs"; +import { + NodeChainSliceResponse, + NodeInfoResponse, +} from './interfaces/node.interface'; +import { NodeErgoBoxResponse, NodeErgoPostTxResponse } from "./types/node.type"; +import { + BlockHeaders, + ErgoStateContext, + PreHeader, +} from 'ergo-lib-wasm-nodejs'; export class NodeService { constructor( @@ -46,13 +53,31 @@ export class NodeService { address, ); } + async chainSliceInfo(height: number): Promise { - return this.request('GET', `/blocks/chainSlice?fromHeight=${height - 10}&toHeight=${height}`) + return this.request( + 'GET', + `/blocks/chainSlice?fromHeight=${height - 10}&toHeight=${height}`, + ); } + async getCtx() { - const height = await this.getNetworkHeight() - const blockHeaders = BlockHeaders.from_json(await this.chainSliceInfo(height)) - const pre_header = PreHeader.from_block_header(blockHeaders.get(blockHeaders.len() - 1)) + const height = await this.getNetworkHeight(); + const blockHeaders = BlockHeaders.from_json( + await this.chainSliceInfo(height), + ); + const pre_header = PreHeader.from_block_header( + blockHeaders.get(blockHeaders.len() - 1), + ); return new ErgoStateContext(pre_header, blockHeaders); } + + async postTransaction(tx: any): Promise { + return this.request( + 'POST', + `/transactions`, + { 'Content-Type': 'text/plain' }, + tx, + ); + } } diff --git a/src/chains/ergo/types/node.type.ts b/src/chains/ergo/types/node.type.ts index 83ae9320b3..506fa6d396 100644 --- a/src/chains/ergo/types/node.type.ts +++ b/src/chains/ergo/types/node.type.ts @@ -1,3 +1,4 @@ import { ErgoBox } from '../interfaces/ergo.interface'; export type NodeErgoBoxResponse = Array; +export type NodeErgoPostTxResponse = string; From c6ad32f934f44d637260c82abdcb8f5c4b4f6dcc Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Fri, 21 Jun 2024 03:24:59 +0330 Subject: [PATCH 036/132] fix load pool bugs --- src/chains/ergo/ergo.ts | 22 ++++++++---- src/chains/ergo/interfaces/ergo.interface.ts | 2 +- src/services/schema/ergo-schema.json | 37 ++++++++++++++++++++ src/templates/ergo.yml | 8 +++++ src/templates/root.yml | 8 +++-- 5 files changed, 67 insertions(+), 10 deletions(-) create mode 100644 src/services/schema/ergo-schema.json create mode 100644 src/templates/ergo.yml diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 89344129ff..bc4963a794 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -16,19 +16,24 @@ import { ErgoBox, ErgoConnectedInstance, } from './interfaces/ergo.interface'; -import { toNumber } from 'lodash'; import { AmmPool, makeNativePools } from '@ergolabs/ergo-dex-sdk'; -import { Explorer } from '@ergolabs/ergo-sdk'; +import { Explorer, RustModule } from '@ergolabs/ergo-sdk'; + +async function x() { + await RustModule.load(true); +} +x(); class Pool extends AmmPool { private name: string; + constructor(public pool: AmmPool) { super(pool.id, pool.lp, pool.x, pool.y, pool.poolFeeNum); this.name = `${this.x.asset.name}/${this.y.asset.name}`; } - private getName() { + public getName() { return this.name; } @@ -266,7 +271,7 @@ export class Ergo { for (const result of assetData.tokens) { this._assetMap[result.name.toUpperCase()] = { - tokenId: toNumber(result.address), + tokenId: result.address, decimals: result.decimals, name: result.name, symbol: result.ticker, @@ -281,7 +286,6 @@ export class Ergo { private async loadPools(): Promise { let offset = 0; let pools: Array = await this.getPoolData(this.poolLimit, offset); - while (pools.length > 0) { for (const pool of pools) { if (!this.ammPools.filter((ammPool) => ammPool.id === pool.id).length) { @@ -289,13 +293,17 @@ export class Ergo { } } - offset += this.utxosLimit; + offset += this.poolLimit; pools = await this.getPoolData(this.poolLimit, offset); } } private async getPoolData(limit: number, offset: number): Promise { - return await makeNativePools(this._explorer).getAll({ limit, offset }); + const [AmmPool] = await makeNativePools(this._explorer).getAll({ + limit, + offset, + }); + return AmmPool; } public get storedTokenList() { diff --git a/src/chains/ergo/interfaces/ergo.interface.ts b/src/chains/ergo/interfaces/ergo.interface.ts index 0b5a1a43fc..535bd24108 100644 --- a/src/chains/ergo/interfaces/ergo.interface.ts +++ b/src/chains/ergo/interfaces/ergo.interface.ts @@ -19,7 +19,7 @@ export interface ErgoConfig { } export interface ErgoAsset { - tokenId: number; + tokenId: string; decimals: number; name: string; symbol: string; diff --git a/src/services/schema/ergo-schema.json b/src/services/schema/ergo-schema.json new file mode 100644 index 0000000000..f89f02a4d8 --- /dev/null +++ b/src/services/schema/ergo-schema.json @@ -0,0 +1,37 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "networks": { + "type": "object", + "patternProperties": { + "^\\w+$": { + "type": "object", + "properties": { + "nodeURL": { + "type": "string" + }, + "explorerURL": { + "type": "string" + }, + "explorerDEXURL": { + "type": "string" + }, + "timeOut": { + "type": "number" + } + }, + "required": [ + "nodeURL", + "explorerURL", + "explorerDEXURL", + "timeOut" + ], + "additionalProperties": false + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false +} diff --git a/src/templates/ergo.yml b/src/templates/ergo.yml new file mode 100644 index 0000000000..e3d047e0ef --- /dev/null +++ b/src/templates/ergo.yml @@ -0,0 +1,8 @@ +networks: + networks: + Mainnet: + nodeURL: "http://213.239.193.208:9053/" + explorerURL: "https://api.ergoplatform.com/api/v1/" + explorerDEXURL: "https://spectrum.fi/" + timeOut: 30000 + minTxFee: 1000000 \ No newline at end of file diff --git a/src/templates/root.yml b/src/templates/root.yml index 748ec134b2..3e5133d854 100644 --- a/src/templates/root.yml +++ b/src/templates/root.yml @@ -4,6 +4,10 @@ configurations: configurationPath: server.yml schemaPath: server-schema.json + $namespace ergo: + configurationPath: ergo.yml + schemaPath: ergo-schema.json + $namespace algorand: configurationPath: algorand.yml schemaPath: algorand-schema.json @@ -71,11 +75,11 @@ configurations: $namespace cosmos: configurationPath: cosmos.yml schemaPath: cosmos-schema.json - + $namespace osmosis: configurationPath: osmosis.yml schemaPath: osmosis-schema.json - + $namespace cronos: configurationPath: cronos.yml schemaPath: ethereum-schema.json From aec0fdd4c43cec92cea7c5fe0ab869ebecac8c57 Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Fri, 21 Jun 2024 15:34:47 +0330 Subject: [PATCH 037/132] some related bugs fixed --- src/chains/ergo/ergo.ts | 56 ++++++++++++-------- src/chains/ergo/interfaces/ergo.interface.ts | 2 +- src/chains/ergo/node.service.ts | 4 +- 3 files changed, 38 insertions(+), 24 deletions(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 2e86d86858..2ea12907b4 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -44,7 +44,7 @@ import { Address, BoxSelection, Input as TxInput, - RustModule + RustModule, } from '@ergolabs/ergo-sdk'; import { makeTarget } from '@ergolabs/ergo-dex-sdk/build/main/utils/makeTarget'; import { NativeExFeeType } from '@ergolabs/ergo-dex-sdk/build/main/types'; @@ -521,6 +521,7 @@ export class Ergo { output_address: string, return_address: string, slippage: number, + sell: boolean, ): Promise { const config = getErgoConfig(this.network); const networkContext = await this._explorer.getNetworkContext(); @@ -535,23 +536,23 @@ export class Ergo { const utxos = await this.getAddressUnspentBoxes(account.address); const to = { asset: { - id: pool.x.asset.id, - decimals: pool.x.asset.decimals, + id: sell ? pool.x.asset.id : pool.y.asset.id, + decimals: sell ? pool.x.asset.decimals : pool.y.asset.decimals, }, - amount: x_amount, + amount: sell ? x_amount : y_amount, }; const max_to = { asset: { - id: pool.x.asset.id, + id: sell ? pool.x.asset.id : pool.y.asset.id, }, // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error - amount: x_amount + x_amount / 10n, + amount: sell ? x_amount + x_amount / 10n : y_amount + y_amount / 10n, }; const from = { asset: { - id: pool.y.asset.id, - decimals: pool.y.asset.decimals, + id: sell ? pool.y.asset.id : pool.x.asset.id, + decimals: sell ? pool.y.asset.decimals : pool.x.asset.decimals, }, amount: pool.outputAmount( max_to as any, @@ -576,11 +577,20 @@ export class Ergo { // @ts-expect-error const [exFeePerToken, extremum] = swapVariables; const inputs = getInputs( - utxos, + utxos.map((utxo) => { + const temp = Object(utxo); + temp.value = BigInt(temp.value); + temp.assets = temp.assets.map((asset: any) => { + const temp2 = Object(asset); + temp2.amount = BigInt(temp2.amount); + return temp2; + }); + return temp; + }), [new AssetAmount(from.asset, baseInputAmount)], { minerFee: config.network.defaultMinerFee, - uiFee: BigInt(y_amount), + uiFee: BigInt(sell ? y_amount : x_amount), exFee: extremum.maxExFee, }, config.network.minBoxValue, @@ -593,7 +603,7 @@ export class Ergo { baseInput, minQuoteOutput: extremum.minOutput.amount, exFeePerToken, - uiFee: BigInt(y_amount), + uiFee: BigInt(sell ? y_amount : x_amount), quoteAsset: to.asset.id, poolFeeNum: pool.poolFeeNum, maxExFee: extremum.maxExFee, @@ -622,11 +632,12 @@ export class Ergo { return await this.swap( account, pool, - y_amount, x_amount, + y_amount, output_address, return_address, slippage, + false, ); } // eslint-disable-next-line @typescript-eslint/ban-ts-comment @@ -648,26 +659,28 @@ export class Ergo { output_address, return_address, slippage, + true, ); } private async estimate( pool: Pool, - x_amount: bigint, + amount: bigint, slippage: number, + sell: boolean, ): Promise { const config = getErgoConfig(this.network); const max_to = { asset: { - id: pool.x.asset.id, + id: sell ? pool.x.asset.id : pool.y.asset.id, }, // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - amount: x_amount + x_amount / 10n, + amount: amount + amount / 10n, }; const from = { asset: { - id: pool.y.asset.id, - decimals: pool.y.asset.decimals, + id: sell ? pool.y.asset.id : pool.x.asset.id, + decimals: sell ? pool.y.asset.decimals : pool.x.asset.decimals, }, amount: pool.outputAmount( max_to as any, @@ -684,20 +697,21 @@ export class Ergo { // @ts-expect-error private async estimateBuy( pool: Pool, - x_amount: bigint, y_amount: bigint, slippage: number, ): Promise { - return await this.estimate(pool, y_amount, x_amount, slippage); + return await this.estimate(pool, y_amount, slippage, false); } // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error private async estimateSell( pool: Pool, x_amount: bigint, - y_amount: bigint, slippage: number, ): Promise { - return await this.estimate(pool, x_amount, y_amount, slippage); + return await this.estimate(pool, x_amount, slippage, true); + } + public getPool(id: string): Pool { + return this.ammPools.find((ammPool) => ammPool.id === id); } } diff --git a/src/chains/ergo/interfaces/ergo.interface.ts b/src/chains/ergo/interfaces/ergo.interface.ts index 3b134268a2..0944bbf378 100644 --- a/src/chains/ergo/interfaces/ergo.interface.ts +++ b/src/chains/ergo/interfaces/ergo.interface.ts @@ -32,7 +32,7 @@ export interface ErgoAsset { export interface ErgoAccount { wallet: Wallet; address: string; - prover: WalletProver + prover: WalletProver; } export interface ErgoConnectedInstance { diff --git a/src/chains/ergo/node.service.ts b/src/chains/ergo/node.service.ts index ffc9f7fda0..18494f34d1 100644 --- a/src/chains/ergo/node.service.ts +++ b/src/chains/ergo/node.service.ts @@ -34,7 +34,7 @@ export class NodeService { method, headers: headers, timeout: this.timeout, - ...(method === 'POST' ? { body: body } : null), + ...(method === 'POST' ? { data: body } : null), }); return response.data; @@ -72,7 +72,7 @@ export class NodeService { 'POST', `/blockchain/box/unspent/byAddress?offset=${offset}&limit=${limit}&sortDirection=${sortDirection}`, { 'Content-Type': 'text/plain' }, - address, + `${address}`, ); } From 9095dae1ad8385b3e560e84016aa7865884b8536 Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Fri, 21 Jun 2024 15:36:47 +0330 Subject: [PATCH 038/132] some related bugs fixed --- src/chains/ergo/ergo.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 2ea12907b4..010b132acc 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -545,9 +545,7 @@ export class Ergo { asset: { id: sell ? pool.x.asset.id : pool.y.asset.id, }, - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - amount: sell ? x_amount + x_amount / 10n : y_amount + y_amount / 10n, + amount: sell ? x_amount : y_amount, }; const from = { asset: { @@ -675,7 +673,7 @@ export class Ergo { }, // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - amount: amount + amount / 10n, + amount, }; const from = { asset: { From 844347214efbb7a420761794d9db0973185a7e83 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Fri, 21 Jun 2024 16:08:21 +0330 Subject: [PATCH 039/132] update [commet]: update comments of unit tests --- test/chains/ergo/dex.service.test.ts | 11 ---- test/chains/ergo/ergo.config.test.ts | 5 +- test/chains/ergo/ergo.test.ts | 80 +-------------------------- test/chains/ergo/node.service.test.ts | 28 +--------- 4 files changed, 7 insertions(+), 117 deletions(-) diff --git a/test/chains/ergo/dex.service.test.ts b/test/chains/ergo/dex.service.test.ts index bfcff20b1b..71f1e05c3a 100644 --- a/test/chains/ergo/dex.service.test.ts +++ b/test/chains/ergo/dex.service.test.ts @@ -2,19 +2,14 @@ import axios from 'axios'; import { DexService } from '../../../src/chains/ergo/dex.service'; import { DEXTokensResponse } from '../../../src/chains/ergo/interfaces/dex.interface'; -// Mocking axios to intercept HTTP requests and return controlled responses jest.mock('axios'); -// Describe the test suite for the NodeService class describe('DexService', () => { - // Define constants for baseURL and timeout const baseURL = 'https://example.com'; const timeout = 5000; - // Initialize DexService instance const dexService: DexService = new DexService(baseURL, timeout); - // Test case to check if DexService is defined and its properties are set correctly it('Should initialize with given baseURL and timeout', () => { // Assert: Check if the dexURL and timeout properties are correctly set and instance is defined expect(dexService).toBeDefined(); @@ -22,15 +17,12 @@ describe('DexService', () => { expect(dexService['timeout']).toBe(timeout); }); - // Describe the test suite for the private request method of NodeService describe('request', () => { - // Define default parameters for the request method const method = 'GET'; const url = '/test-endpoint'; const headers = { 'Content-Type': 'application/json' }; const body = { key: 'value' }; - // Test case for making a GET request with correct parameters it('Should make a GET request with correct parameters', async () => { // Arrange: Mock the axios response const mockResponse = { data: { name: 'test' } }; @@ -51,7 +43,6 @@ describe('DexService', () => { expect(response).toEqual({ name: 'test' }); }); - // Test case for making a POST request with correct parameters it('Should make a POST request with correct parameters', async () => { // Arrange: Change method to POST and mock the axios response const method = 'POST'; @@ -75,9 +66,7 @@ describe('DexService', () => { }); }); - // Describe the test suite for the getTokens method of NodeService describe('getTokens', () => { - // Test case to call getTokens method and check return value and function input arguments it('Should call request method with correct parameters', async () => { // Arrange: Mock the response of the request method const mockResponse: DEXTokensResponse = { diff --git a/test/chains/ergo/ergo.config.test.ts b/test/chains/ergo/ergo.config.test.ts index fb668d5799..c58b1018f1 100644 --- a/test/chains/ergo/ergo.config.test.ts +++ b/test/chains/ergo/ergo.config.test.ts @@ -2,14 +2,11 @@ import { getErgoConfig } from '../../../src/chains/ergo/ergo.config'; import { ConfigManagerV2 } from '../../../src/services/config-manager-v2'; import { NetworkPrefix } from 'ergo-lib-wasm-nodejs'; -// Define the test suite for the getErgoConfig function describe('getErgoConfig', () => { - // After each test, clear all mocks to ensure no interference between tests afterEach(() => { jest.clearAllMocks(); }); - // Test case for verifying the configuration returned for the Mainnet it('Should return correct config for Mainnet', () => { // Arrange: Mock the get method of ConfigManagerV2 to return specific values for Mainnet jest @@ -60,7 +57,7 @@ describe('getErgoConfig', () => { 'ergo.networks.Mainnet.minTxFee', ); }); - // Test case for verifying the configuration returned for the Testnet + it('Should return correct config for Testnet', () => { // Arrange: Mock the get method of ConfigManagerV2 to return specific values for Testnet jest diff --git a/test/chains/ergo/ergo.test.ts b/test/chains/ergo/ergo.test.ts index 260d70c85a..08585af7e8 100644 --- a/test/chains/ergo/ergo.test.ts +++ b/test/chains/ergo/ergo.test.ts @@ -20,7 +20,6 @@ import { import LRUCache from 'lru-cache'; import { makeNativePools } from '@ergolabs/ergo-dex-sdk'; -// Mocking dependencies for testing purposes using jest jest.mock('@ergolabs/ergo-dex-sdk', () => ({ AmmPool: jest.fn(), makeNativePools: jest.fn(), @@ -29,10 +28,8 @@ jest.mock('@ergolabs/ergo-sdk', () => ({ Explorer: jest.fn(), })); -// Initializing Ergo instance for testing let ergo: Ergo; -// Helper function to patch getErgoConfig for Mainnet configuration const patchGetErgoConfig = (imputNetwork: string) => { patch(ergo_cofing, 'getErgoConfig', () => { return { @@ -55,14 +52,12 @@ const patchGetErgoConfig = (imputNetwork: string) => { }); }; -// Helper function to patch Wallet.from_secrets method for testing const patchFrom_secrets = () => { patch(Wallet, 'from_secrets', () => { return 'testWallet' as any; }); }; -// Helper function to patch Address.prototype.to_base58 method for testing const patchTo_base58 = () => { patch(Address.prototype, 'to_base58', () => { return 'testAddress' as any; @@ -75,14 +70,12 @@ const patchErgo_node = async () => { }); }; -// Helper function to patch ergo.getAddressUnspentBoxes method for testing const patchGetAddressUnspentBoxes = () => { patch(ergo, 'getAddressUnspentBoxes', () => { return []; }); }; -// Helper function to patch ergo.getAssetData method for testing const patchGetAssetData = () => { patch(ergo, 'getAssetData', () => { return { @@ -103,7 +96,6 @@ const patchGetAssetData = () => { }); }; -// Helper function to patch getTokens method for testing const patchGetTokens = () => { patch(ergo['_dex'], 'getTokens', () => { return { @@ -133,7 +125,6 @@ const patchGetTokens = () => { }); }; -// Before each test, configure and initialize Ergo with 'Mainnet' settings beforeEach(() => { // Arrange: Mock the return value of getErgoConfig to simulate Mainnet configuration before each test patchGetErgoConfig('Mainnet'); @@ -146,9 +137,8 @@ afterEach(() => { unpatch(); jest.clearAllMocks(); }); -// Describe the test suite for the Ergo class + describe('Ergo', () => { - // Test case to verify initialization with Mainnet configuration it('Should initialize with Mainnet configuration', () => { // Assert: Validate the initialization state of Ergo instance expect(ergo).toBeDefined(); @@ -165,7 +155,6 @@ describe('Ergo', () => { expect(ergo['ammPools']).toEqual([]); }); - // Test case to verify initialization with Testnet configuration it('Should initialize with Mainnet configuration', () => { // Arrange: Mock the return value of getErgoConfig to simulate Testnet configuration patchGetErgoConfig('Testnet'); @@ -188,9 +177,7 @@ describe('Ergo', () => { expect(ergo['ammPools']).toEqual([]); }); - // Describe the test suite for the get node method describe('get node', () => { - // Test case to verify initialization of node service it('Should initialize node correctly and return the correct node', () => { // Assert: Validate the initialization state of node instance and check the returned value expect(ergo.node).toBeInstanceOf(NodeService); @@ -201,15 +188,12 @@ describe('Ergo', () => { }); }); - // Describe the test suite for the get network method describe('get network', () => { - // Test case to verify network value when initialized with Mainnet it('Should return the correct network when network is Mainnet', () => { // Assert: Validate the return value expect(ergo.network).toBe('Mainnet'); }); - // Test case to verify network value when initialized with Testnet it('Should return the correct network when network is Testnet', () => { // Arrange: Mock the return value of getErgoConfig to simulate Testnet configuration patchGetErgoConfig('Testnet'); @@ -222,9 +206,7 @@ describe('Ergo', () => { }); }); - // Describe the test suite for the get network method describe('get storedAssetList', () => { - // Test case to verify the stored asset list it('Should return the stored asset list', () => { // Arrange: Create mock assets and populate _assetMap const asset1: ErgoAsset = 1 as any; @@ -242,9 +224,7 @@ describe('Ergo', () => { }); }); - // Describe the test suite for the ready method describe('ready', () => { - // Test case to verify the return value of the ready method it('Should return the ready state', () => { // Arrange: Initially, the ready state should be false expect(ergo.ready()).toBe(false); @@ -257,9 +237,7 @@ describe('Ergo', () => { }); }); - // Describe the test suite for the init method describe('init', () => { - // Test case to verify the initialization process in the init method it('Should initialize assets and pools in init method', async () => { // Arrange: Mock the loadAssets & loadPools methods to return a fixed value jest.spyOn(ergo as any, 'loadAssets').mockResolvedValue({}); @@ -275,20 +253,16 @@ describe('Ergo', () => { }); }); - // Describe the test suite for the close method describe('close', () => { - // Test case to verify the close method it('Should close correctly', async () => { // Act and Assert: Call the close method and expect that the close method resolves without any errors or values await expect(ergo.close()).resolves.toBeUndefined(); }); }); - // Describe the test suite for the getInstance method describe('getInstance', () => { const mockNetwork = 'Testnet'; - // This block runs before each test in this suite beforeEach(() => { // Arrange: Mock the function to get the configuration for the 'Testnet' network patchGetErgoConfig('Testnet'); @@ -296,7 +270,6 @@ describe('Ergo', () => { Ergo['_instances'] = undefined as any; }); - // Test that the LRUCache is initialized if it hasn't been already it('Should initialize the LRUCache if not already initialized', () => { // Act: Call the getInstance method with the mock network Ergo.getInstance(mockNetwork); @@ -306,7 +279,6 @@ describe('Ergo', () => { expect(Ergo['_instances']).toBeInstanceOf(LRUCache); }); - // Test that a new Ergo instance is created and returned if it's not in the cache it('Should set and return a new Ergo instance if not in the cache', () => { // Act: Call the getInstance method with the mock network const instance = Ergo.getInstance(mockNetwork); @@ -317,7 +289,6 @@ describe('Ergo', () => { expect(Ergo['_instances'].get(mockNetwork)).toBe(instance); }); - // Test that an existing Ergo instance is returned from the cache it('Should return an existing Ergo instance from the cache', () => { // Act: Call the getInstance method twice with the mock network const instance1 = Ergo.getInstance(mockNetwork); @@ -328,7 +299,6 @@ describe('Ergo', () => { expect(Ergo['_instances'].get(mockNetwork)).toBe(instance1); }); - // Test that an error is thrown if an unexpected network is provided it('Should throw an error if an unexpected network is provided', () => { // Act and Assert: Expect that calling getInstance with an empty string throws an error expect(() => Ergo.getInstance('')).toThrow( @@ -337,12 +307,10 @@ describe('Ergo', () => { }); }); - // Describe the test suite for the getConnectedInstances method describe('getConnectedInstances', () => { let mockErgoInstance1: Ergo; let mockErgoInstance2: Ergo; - // This block runs before each test in this suite beforeEach(() => { // Arrange: Create mock Ergo instances mockErgoInstance1 = new Ergo('Testnet1') as any; @@ -355,7 +323,7 @@ describe('Ergo', () => { Ergo['_instances'].set('Testnet1', mockErgoInstance1); Ergo['_instances'].set('Testnet2', mockErgoInstance2); }); - // Test case to verify that all connected instances are returned + it('Should return all connected instances', () => { // Act: Call the getConnectedInstances method const connectedInstances = Ergo.getConnectedInstances(); @@ -369,7 +337,6 @@ describe('Ergo', () => { expect(connectedInstances['Testnet2']).toBe(mockErgoInstance2); }); - // Test case to verify that an empty object is returned if no instances exist it('Should return an empty object if there are no instances', () => { // Arrange: Clear the _instances LRUCache Ergo['_instances'] = undefined as any; @@ -381,7 +348,6 @@ describe('Ergo', () => { expect(connectedInstances).toEqual({}); }); - // Test case to verify that only valid instances are returned it('Should return only valid instances', () => { // Arrange: Set an invalid (null) instance in the _instances LRUCache Ergo['_instances'].set('', null as any); @@ -399,9 +365,7 @@ describe('Ergo', () => { }); }); - // Describe the test suite for the getCurrentBlockNumber method describe('getCurrentBlockNumber', () => { - // Test case to verify return block number corectly it('Should return the current block number incremented by one', async () => { // Arrange: Mock the getNetworkHeight method to return a fixed value jest.spyOn(ergo['_node'], 'getNetworkHeight').mockResolvedValue(17); @@ -415,12 +379,9 @@ describe('Ergo', () => { }); }); - // Describe the test suite for the getAddressUnspentBoxes method describe('getAddressUnspentBoxes', () => { - // Mock address for testing const mockAddress = '9j2s7d8f4s8s8o8s0q8f5s8d7f8s0d4r5'; - // Test case to verify the return of an empty array when there are no unspent boxes it('Should return an empty arry when length of nodeBoxes is 0', async () => { // Arrange: Mock the getUnspentBoxesByAddress method to return an empty array await patchErgo_node(); @@ -428,7 +389,6 @@ describe('Ergo', () => { expect(utxos).toEqual([]); }); - // Test case to verify the retrieval of all unspent boxes for the given address it('Should retrieve all unspent boxes for the given address', async () => { // Arrange: Mock the getUnspentBoxesByAddress method to return 3 boxes const mockUnspentBoxesPage1 = [ @@ -471,15 +431,10 @@ describe('Ergo', () => { }); }); - // Describe the test suite for the getAccountFromSecretKey method describe('getAccountFromSecretKey', () => { - // Test case to verify the return of an account with address and wallet it('Should return an account with address and wallet', () => { - // Mock secret key const secret = '591811a0d6361f18e42549b32e65b98c9a63d6aad369d1056a97ca81f2a980d5'; - - // Patch methods for mock implementation patchFrom_secrets(); patchTo_base58(); @@ -504,9 +459,7 @@ describe('Ergo', () => { }); }); - // Describe the test suite for the encrypt method describe('encrypt', () => { - // Test case to verify encryption of a secret with a given password it('Should encrypt a secret with a given password', () => { // Arrange: Set up the secret and password const secret = 'mySecret'; @@ -519,7 +472,6 @@ describe('Ergo', () => { expect(encryptedText).toMatch(/^[0-9a-fA-F]{32}:[0-9a-fA-F]+$/); }); - // Test case to ensure different encryption outputs for different secrets it('Should produce different encryption outputs for different secrets', () => { // Arrange: Set up the password const password = 'myPassword'; @@ -532,7 +484,6 @@ describe('Ergo', () => { expect(encryptedText1).not.toBe(encryptedText2); }); - // Test case to ensure different encryption outputs for different passwords it('Should produce different encryption outputs for different passwords', () => { // Arrange: Set up the secret const secret = 'mySecret'; @@ -545,7 +496,6 @@ describe('Ergo', () => { expect(encryptedText1).not.toBe(encryptedText2); }); - // Test case to ensure different IVs for different encryptions it('Should produce different IVs for different encryptions', () => { // Arrange: Set up the secret and password const secret = 'mySecret'; @@ -563,7 +513,6 @@ describe('Ergo', () => { expect(iv1).not.toBe(iv2); }); - // Test case to handle passwords longer than 32 bytes it('Should handle edge case where password is longer than 32 bytes', () => { // Arrange: Set up the secret and a long password const secret = 'mySecret'; @@ -577,9 +526,7 @@ describe('Ergo', () => { }); }); - // Describe the test suite for the decrypt method describe('decrypt', () => { - // Test case to verify correct decryption of an encrypted secret it('Should decrypt an encrypted secret correctly', () => { // Arrange: Set up the secret and password, and encrypt the secret const secret = 'mySecret'; @@ -593,7 +540,6 @@ describe('Ergo', () => { expect(decryptedText).toBe(secret); }); - // Test case to ensure decryption fails with wrong password it('Should fail to decrypt with wrong password', () => { // Arrange: Set up the secret, correct password, wrong password, and encrypt the secret const secret = 'mySecret'; @@ -607,7 +553,6 @@ describe('Ergo', () => { }).toThrow(); }); - // Test case to handle passwords longer than 32 bytes it('Should handle edge case where password is longer than 32 bytes', () => { // Arrange: Set up the secret and a long password, and encrypt the secret const secret = 'mySecret'; @@ -621,7 +566,6 @@ describe('Ergo', () => { expect(decryptedText).toBe(secret); }); - // Test case to handle passwords exactly 32 bytes long it('Should handle case where password is exactly 32 bytes', () => { // Arrange: Set up the secret and a 32 bytes password, and encrypt the secret const secret = 'mySecret'; @@ -636,9 +580,7 @@ describe('Ergo', () => { }); }); - // Describe the test suite for the getAssetBalance method describe('getAssetBalance', () => { - // Test case to ensure balance is 0 when there are no unspent boxes it('Should return balance as 0 when there are no unspent boxes', async () => { // Arrange: Set up the account and asset map, and mock the getAddressUnspentBoxes method to return an empty array const account: ErgoAccount = { address: 'mockAddress' } as any; @@ -654,8 +596,7 @@ describe('Ergo', () => { expect(balance).toBe('0'); }); - // Test case to ensure balance is 0 when there are no matching assets - it('should return balance as 0 when there are no matching assets', async () => { + it('Should return balance as 0 when there are no matching assets', async () => { // Arrange: Set up the account, asset map, and mock the getAddressUnspentBoxes method to return utxos without matching assets const account: ErgoAccount = { address: 'mockAddress' } as any; ergo['_assetMap'] = { @@ -673,7 +614,6 @@ describe('Ergo', () => { expect(balance).toBe('0'); }); - // Test case to ensure correct balance is returned when there are matching assets it('Should return correct balance when there are matching assets', async () => { // Arrange: Set up the account, asset map, and mock the getAddressUnspentBoxes method to return utxos with matching assets const account: ErgoAccount = { address: 'mockAddress' } as any; @@ -695,7 +635,6 @@ describe('Ergo', () => { expect(balance).toBe('300'); }); - // Test case to ensure error is thrown when getAddressUnspentBoxes fails it('Should throw an error when getAddressUnspentBoxes fails', async () => { // Arrange: Set up the account and mock the getAddressUnspentBoxes method to reject with an error const account: ErgoAccount = { address: 'mockAddress' } as any; @@ -710,9 +649,7 @@ describe('Ergo', () => { }); }); - // Describe the test suite for the loadAssets method describe('loadAssets', () => { - // Test case to ensure assets are loaded and assetMap object is updated it('Should load Assets and update assetMap object', async () => { // Arrange: Set up the assetMap and mock the getAssetData method ergo['_assetMap'] = {}; @@ -734,9 +671,7 @@ describe('Ergo', () => { }); }); - // Describe the test suite for the getAssetData method describe('getAssetData', () => { - // Test case to ensure getAssetData returns all tokens with details it('Should return all token with the details', async () => { // Mock getTokens method to return predefined data patchGetTokens(); @@ -769,9 +704,7 @@ describe('Ergo', () => { }); }); - // Describe the test suite for the loadPools method describe('loadPools', () => { - // Test case to ensure ammPools remains empty when no PoolData is provided it('Should push nothing to ammPools when no PoolData is provided', async () => { // Arrange: Mock getPoolData to return an empty array jest.spyOn(ergo as any, 'getPoolData').mockResolvedValue([] as any); @@ -784,7 +717,6 @@ describe('Ergo', () => { expect(ergo['ammPools']).toEqual([]); }); - // Test case to ensure ammPools contains provided PoolData when available it('Should push nothing to ammPools when no PoolData is provided', async () => { // Arrange: Mock getPoolData to return specific pool data jest @@ -800,7 +732,6 @@ describe('Ergo', () => { expect(ergo['ammPools']).toEqual([{ id: '1' }, { id: 2 }]); }); - // Test case to ensure ammPools merges new pools without duplicates it('Should not add duplicate pools to ammPools', async () => { // Arrange: Mock getPoolData to simulate incremental pool data loading const initialPools: any = [ @@ -832,9 +763,7 @@ describe('Ergo', () => { }); }); - // Describe the test suite for the getPoolData method describe('getPoolData', () => { - // Test case to ensure makeNativePools and getAll are called with correct parameters it('Should call makeNativePools and getAll with correct parameters', async () => { // Arrange: Mock makeNativePools and getAll methods const mockGetAll = jest.fn().mockResolvedValue([]); @@ -851,7 +780,6 @@ describe('Ergo', () => { expect(mockGetAll).toHaveBeenCalledWith({ limit, offset }); }); - // Test case to ensure getPoolData returns expected data from getAll method it('Should return the data from getAll method', async () => { // Arrange: Mock getAll method to return specific data const expectedData = [{ id: 1, name: 'Pool 1' }]; @@ -868,7 +796,6 @@ describe('Ergo', () => { expect(result).toEqual(expectedData); }); - // Test case to ensure getPoolData handles errors from getAll method it('Should handle errors from getAll method', async () => { // Arrange: Mock getAll method to simulate error const mockGetAll = jest.fn().mockRejectedValue(new Error('Test error')); @@ -884,7 +811,6 @@ describe('Ergo', () => { }); }); - // Describe the test suite for the getPoolData method describe('storedTokenList', () => { it('Should return the stored asset list', () => { // Arrange: Create mock assets and populate _assetMap diff --git a/test/chains/ergo/node.service.test.ts b/test/chains/ergo/node.service.test.ts index 2451444df9..ec4e961592 100644 --- a/test/chains/ergo/node.service.test.ts +++ b/test/chains/ergo/node.service.test.ts @@ -2,24 +2,18 @@ import axios from 'axios'; import { NodeService } from '../../../src/chains/ergo/node.service'; import { NodeInfoResponse } from '../../../src/chains/ergo/interfaces/node.interface'; -// Mock axios to avoid making real HTTP requests during tests jest.mock('axios'); -// Describe the test suite for the NodeService class describe('NodeService', () => { - // Define constants for baseURL and timeout const baseURL = 'https://example.com'; const timeout = 5000; - // Initialize NodeService instance const nodeService: NodeService = new NodeService(baseURL, timeout); - // After each test, clear all mocks to ensure no interference between tests afterEach(() => { jest.clearAllMocks(); }); - // Test case to check if NodeService is defined and its properties are set correctly it('Should be defined and and set nodeURL & timeout correctly', () => { // Assert: Check if the nodeURL and timeout properties are correctly set and instance is defined expect(nodeService).toBeDefined(); @@ -28,13 +22,11 @@ describe('NodeService', () => { }); describe('request', () => { - // Define default parameters for the request method const method = 'GET'; const url = '/test-endpoint'; const headers = { 'Content-Type': 'application/json' }; const body = { key: 'value' }; - // Test case for making a GET request with correct parameters it('Should make a GET request with correct parameters', async () => { // Arrange: Mock the axios response const mockResponse = { data: { name: 'test' } }; @@ -55,7 +47,6 @@ describe('NodeService', () => { expect(response).toEqual({ name: 'test' }); }); - // Test case for making a POST request with correct parameters it('Should make a POST request with correct parameters', async () => { // Arrange: Change method to POST and mock the axios response const method = 'POST'; @@ -79,50 +70,37 @@ describe('NodeService', () => { }); }); - // Describe the test suite for the getNetworkHeight method describe('getNetworkHeight', () => { - // Define a test case to check if getNetworkHeight is called with the correct parameters and returns the correct value - it('should call getNetworkHeight with correct parameters and returns the correct value', async () => { - // Define a mock response with fullHeight property + it('Should call getNetworkHeight with correct parameters and returns the correct value', async () => { const res: NodeInfoResponse = { fullHeight: 100 }; - // Mock the private request method of nodeService to resolve with the mock response jest.spyOn(nodeService as any, 'request').mockResolvedValue(res); // Call the getNetworkHeight method and store the result const networkHeight = await nodeService.getNetworkHeight(); - // Assert: Check if the returned network height is correct + // Assert expect(networkHeight).toEqual(100); - // Assert: Check if the private request method was called exactly once expect(nodeService['request']).toHaveBeenCalledTimes(1); - // Assert: Check if the private request method was called with the correct HTTP method and URL expect(nodeService['request']).toHaveBeenCalledWith('GET', '/info'); }); }); - // Describe the test suite for the getUnspentBoxesByAddress method describe('getUnspentBoxesByAddress', () => { - // Define constants for address, offset, and limit const address = 'box-number-1.com'; const offset = 10; const limit = 20; - // Define a test case to check if getUnspentBoxesByAddress is called with the correct parameters and returns the correct value it('Should call getUnspentBoxesByAddress method with correct parameters and returns the correct value', async () => { - // Mock the private request method of nodeService to resolve with an empty data object jest.spyOn(nodeService as any, 'request').mockResolvedValue({ data: {} }); - // Call the getUnspentBoxesByAddress method with the defined address, offset, and limit, and store the result const unspentBoxesByAddress = await nodeService.getUnspentBoxesByAddress( address, offset, limit, ); - // Assert: Check if the returned value matches the mock response + // Assert expect(unspentBoxesByAddress).toEqual({ data: {} }); - // Assert: Check if the private request method was called exactly once expect(nodeService['request']).toHaveBeenCalledTimes(1); - // Assert: Check if the private request method was called with the correct HTTP method, URL, headers, and body expect(nodeService['request']).toHaveBeenCalledWith( 'POST', `/blockchain/box/unspent/byAddress?offset=10&limit=20&sortDirection=desc`, From 8b18452d6223dbc8e2e3cfeec055f1a55c47635a Mon Sep 17 00:00:00 2001 From: ahmadyazdanii Date: Sun, 23 Jun 2024 19:13:01 +0330 Subject: [PATCH 040/132] update [packages]: change ergo-sdk and ergo-dex-sdk packages --- package.json | 3 +- src/chains/ergo/ergo.ts | 10 +- yarn.lock | 434 +++++++++++++++++++++++----------------- 3 files changed, 258 insertions(+), 189 deletions(-) diff --git a/package.json b/package.json index 4043de3be6..77378c1cf2 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,6 @@ "@cosmjs/stargate": "^0.31.1", "@cosmjs/tendermint-rpc": "^0.32.2", "@crocswap/sdk": "^2.4.5", - "@ergolabs/ergo-dex-sdk": "^1.9.67-beta.4", "@ethersproject/abstract-provider": "5.7.0", "@ethersproject/address": "5.7.0", "@ethersproject/contracts": "5.7.0", @@ -50,6 +49,8 @@ "@pancakeswap/v3-periphery": "^1.0.2", "@pancakeswap/v3-sdk": "^3.7.0", "@pangolindex/sdk": "^1.1.0", + "@patternglobal/ergo-dex-sdk": "^1.0.1", + "@patternglobal/ergo-sdk": "^1.0.0", "@perp/sdk-curie": "^1.16.0", "@sushiswap/sdk": "^5.0.0-canary.116", "@taquito/rpc": "^17.0.0", diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 010b132acc..94c68de941 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -27,7 +27,7 @@ import { SwapExtremums, SwapParams, swapVars, -} from '@ergolabs/ergo-dex-sdk'; +} from '@patternglobal/ergo-dex-sdk'; import { Explorer, Prover, @@ -45,10 +45,10 @@ import { BoxSelection, Input as TxInput, RustModule, -} from '@ergolabs/ergo-sdk'; -import { makeTarget } from '@ergolabs/ergo-dex-sdk/build/main/utils/makeTarget'; -import { NativeExFeeType } from '@ergolabs/ergo-dex-sdk/build/main/types'; -import { NetworkContext } from '@ergolabs/ergo-sdk/build/main/entities/networkContext'; +} from '@patternglobal/ergo-sdk'; +import { makeTarget } from '@patternglobal/ergo-dex-sdk/build/main/utils/makeTarget'; +import { NativeExFeeType } from '@patternglobal/ergo-dex-sdk/build/main/types'; +import { NetworkContext } from '@patternglobal/ergo-sdk/build/main/entities/networkContext'; async function x() { await RustModule.load(true); } diff --git a/yarn.lock b/yarn.lock index be94faef31..190cb61aa1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1434,137 +1434,137 @@ "@ethersproject-xdc/abi@file:vendor/@ethersproject-xdc/abi": version "5.7.0" dependencies: - "@ethersproject-xdc/address" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abi-5.7.0-dc6cad0a-b42e-41c0-add1-31aa9f73da8c-1711378365614/node_modules/@ethersproject-xdc/address" - "@ethersproject-xdc/bignumber" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abi-5.7.0-dc6cad0a-b42e-41c0-add1-31aa9f73da8c-1711378365614/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abi-5.7.0-dc6cad0a-b42e-41c0-add1-31aa9f73da8c-1711378365614/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/constants" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abi-5.7.0-dc6cad0a-b42e-41c0-add1-31aa9f73da8c-1711378365614/node_modules/@ethersproject-xdc/constants" - "@ethersproject-xdc/hash" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abi-5.7.0-dc6cad0a-b42e-41c0-add1-31aa9f73da8c-1711378365614/node_modules/@ethersproject-xdc/hash" - "@ethersproject-xdc/keccak256" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abi-5.7.0-dc6cad0a-b42e-41c0-add1-31aa9f73da8c-1711378365614/node_modules/@ethersproject-xdc/keccak256" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abi-5.7.0-dc6cad0a-b42e-41c0-add1-31aa9f73da8c-1711378365614/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/properties" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abi-5.7.0-dc6cad0a-b42e-41c0-add1-31aa9f73da8c-1711378365614/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/strings" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abi-5.7.0-dc6cad0a-b42e-41c0-add1-31aa9f73da8c-1711378365614/node_modules/@ethersproject-xdc/strings" + "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-c67b1b0a-7ad0-496e-9730-c3c08bf73ba7-1719153755507/node_modules/@ethersproject-xdc/address" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-c67b1b0a-7ad0-496e-9730-c3c08bf73ba7-1719153755507/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-c67b1b0a-7ad0-496e-9730-c3c08bf73ba7-1719153755507/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/constants" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-c67b1b0a-7ad0-496e-9730-c3c08bf73ba7-1719153755507/node_modules/@ethersproject-xdc/constants" + "@ethersproject-xdc/hash" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-c67b1b0a-7ad0-496e-9730-c3c08bf73ba7-1719153755507/node_modules/@ethersproject-xdc/hash" + "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-c67b1b0a-7ad0-496e-9730-c3c08bf73ba7-1719153755507/node_modules/@ethersproject-xdc/keccak256" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-c67b1b0a-7ad0-496e-9730-c3c08bf73ba7-1719153755507/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-c67b1b0a-7ad0-496e-9730-c3c08bf73ba7-1719153755507/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-c67b1b0a-7ad0-496e-9730-c3c08bf73ba7-1719153755507/node_modules/@ethersproject-xdc/strings" "@ethersproject-xdc/abstract-provider@file:vendor/@ethersproject-xdc/abstract-provider": version "5.7.0" dependencies: - "@ethersproject-xdc/bignumber" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-7563efea-d843-42b7-b285-fbeff4443c61-1711378365615/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-7563efea-d843-42b7-b285-fbeff4443c61-1711378365615/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-7563efea-d843-42b7-b285-fbeff4443c61-1711378365615/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/networks" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-7563efea-d843-42b7-b285-fbeff4443c61-1711378365615/node_modules/@ethersproject-xdc/networks" - "@ethersproject-xdc/properties" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-7563efea-d843-42b7-b285-fbeff4443c61-1711378365615/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/transactions" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-7563efea-d843-42b7-b285-fbeff4443c61-1711378365615/node_modules/@ethersproject-xdc/transactions" - "@ethersproject-xdc/web" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-7563efea-d843-42b7-b285-fbeff4443c61-1711378365615/node_modules/@ethersproject-xdc/web" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-b4386266-161c-49e8-ae5f-612280a914b1-1719153755505/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-b4386266-161c-49e8-ae5f-612280a914b1-1719153755505/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-b4386266-161c-49e8-ae5f-612280a914b1-1719153755505/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/networks" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-b4386266-161c-49e8-ae5f-612280a914b1-1719153755505/node_modules/@ethersproject-xdc/networks" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-b4386266-161c-49e8-ae5f-612280a914b1-1719153755505/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/transactions" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-b4386266-161c-49e8-ae5f-612280a914b1-1719153755505/node_modules/@ethersproject-xdc/transactions" + "@ethersproject-xdc/web" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-b4386266-161c-49e8-ae5f-612280a914b1-1719153755505/node_modules/@ethersproject-xdc/web" "@ethersproject-xdc/abstract-signer@file:vendor/@ethersproject-xdc/abstract-signer": version "5.7.0" dependencies: - "@ethersproject-xdc/abstract-provider" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abstract-signer-5.7.0-e30fa525-50b0-4a94-a2fc-4b012803d33e-1711378365615/node_modules/@ethersproject-xdc/abstract-provider" - "@ethersproject-xdc/bignumber" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abstract-signer-5.7.0-e30fa525-50b0-4a94-a2fc-4b012803d33e-1711378365615/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abstract-signer-5.7.0-e30fa525-50b0-4a94-a2fc-4b012803d33e-1711378365615/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abstract-signer-5.7.0-e30fa525-50b0-4a94-a2fc-4b012803d33e-1711378365615/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/properties" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-abstract-signer-5.7.0-e30fa525-50b0-4a94-a2fc-4b012803d33e-1711378365615/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/abstract-provider" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-signer-5.7.0-e4ff2f21-fb22-4045-b15d-6e30d3c8e42e-1719153755506/node_modules/@ethersproject-xdc/abstract-provider" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-signer-5.7.0-e4ff2f21-fb22-4045-b15d-6e30d3c8e42e-1719153755506/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-signer-5.7.0-e4ff2f21-fb22-4045-b15d-6e30d3c8e42e-1719153755506/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-signer-5.7.0-e4ff2f21-fb22-4045-b15d-6e30d3c8e42e-1719153755506/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-signer-5.7.0-e4ff2f21-fb22-4045-b15d-6e30d3c8e42e-1719153755506/node_modules/@ethersproject-xdc/properties" "@ethersproject-xdc/address@file:vendor/@ethersproject-xdc/address": version "5.7.0" dependencies: - "@ethersproject-xdc/bignumber" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-address-5.7.0-ebb15099-34b3-4975-9cf8-7f3cae8cb2cf-1711378365616/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-address-5.7.0-ebb15099-34b3-4975-9cf8-7f3cae8cb2cf-1711378365616/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/keccak256" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-address-5.7.0-ebb15099-34b3-4975-9cf8-7f3cae8cb2cf-1711378365616/node_modules/@ethersproject-xdc/keccak256" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-address-5.7.0-ebb15099-34b3-4975-9cf8-7f3cae8cb2cf-1711378365616/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/rlp" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-address-5.7.0-ebb15099-34b3-4975-9cf8-7f3cae8cb2cf-1711378365616/node_modules/@ethersproject-xdc/rlp" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-address-5.7.0-2239aeab-37ee-49b1-9e78-2683b4b41226-1719153755508/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-address-5.7.0-2239aeab-37ee-49b1-9e78-2683b4b41226-1719153755508/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-address-5.7.0-2239aeab-37ee-49b1-9e78-2683b4b41226-1719153755508/node_modules/@ethersproject-xdc/keccak256" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-address-5.7.0-2239aeab-37ee-49b1-9e78-2683b4b41226-1719153755508/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/rlp" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-address-5.7.0-2239aeab-37ee-49b1-9e78-2683b4b41226-1719153755508/node_modules/@ethersproject-xdc/rlp" "@ethersproject-xdc/base64@file:vendor/@ethersproject-xdc/base64": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-base64-5.7.0-ac940ee8-f7d7-44f8-a8e6-a8a2aa43673b-1711378365615/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-base64-5.7.0-5d7118ad-448e-472d-890b-6643c76f8da1-1719153755506/node_modules/@ethersproject-xdc/bytes" "@ethersproject-xdc/basex@file:vendor/@ethersproject-xdc/basex": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-basex-5.7.0-a3964cd6-3388-4e1e-8827-ccb5f8cddbea-1711378365615/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/properties" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-basex-5.7.0-a3964cd6-3388-4e1e-8827-ccb5f8cddbea-1711378365615/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-basex-5.7.0-d2d232e8-ad6f-4994-b12c-2dbd09ae9393-1719153755507/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-basex-5.7.0-d2d232e8-ad6f-4994-b12c-2dbd09ae9393-1719153755507/node_modules/@ethersproject-xdc/properties" "@ethersproject-xdc/bignumber@file:vendor/@ethersproject-xdc/bignumber": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-bignumber-5.7.0-bc93acda-27ae-4704-88d0-8826555c062b-1711378365615/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-bignumber-5.7.0-bc93acda-27ae-4704-88d0-8826555c062b-1711378365615/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-bignumber-5.7.0-5aa4ecb3-dc23-41d8-b6af-bf4d052cc72a-1719153755509/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-bignumber-5.7.0-5aa4ecb3-dc23-41d8-b6af-bf4d052cc72a-1719153755509/node_modules/@ethersproject-xdc/logger" bn.js "^5.2.1" "@ethersproject-xdc/bytes@file:vendor/@ethersproject-xdc/bytes": version "5.7.0" dependencies: - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-bytes-5.7.0-99ecb1f1-f3c4-4352-b857-7f806ce05f5d-1711378365616/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-bytes-5.7.0-76b2fa68-887e-4f3a-99a4-ead820f7e492-1719153755506/node_modules/@ethersproject-xdc/logger" "@ethersproject-xdc/constants@file:vendor/@ethersproject-xdc/constants": version "5.7.0" dependencies: - "@ethersproject-xdc/bignumber" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-constants-5.7.0-91a31af6-9be3-4e31-94b5-304ef35e3207-1711378365616/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-constants-5.7.0-17c84972-a6c0-4bd8-8335-a3d4d127ee4b-1719153755507/node_modules/@ethersproject-xdc/bignumber" "@ethersproject-xdc/contracts@file:vendor/@ethersproject-xdc/contracts": version "5.6.0" dependencies: - "@ethersproject-xdc/abi" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-contracts-5.6.0-3a1d2199-b3e9-4cf8-a8e5-111bb620bb2f-1711378365616/node_modules/@ethersproject-xdc/abi" - "@ethersproject-xdc/abstract-provider" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-contracts-5.6.0-3a1d2199-b3e9-4cf8-a8e5-111bb620bb2f-1711378365616/node_modules/@ethersproject-xdc/abstract-provider" - "@ethersproject-xdc/abstract-signer" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-contracts-5.6.0-3a1d2199-b3e9-4cf8-a8e5-111bb620bb2f-1711378365616/node_modules/@ethersproject-xdc/abstract-signer" - "@ethersproject-xdc/address" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-contracts-5.6.0-3a1d2199-b3e9-4cf8-a8e5-111bb620bb2f-1711378365616/node_modules/@ethersproject-xdc/address" - "@ethersproject-xdc/bignumber" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-contracts-5.6.0-3a1d2199-b3e9-4cf8-a8e5-111bb620bb2f-1711378365616/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-contracts-5.6.0-3a1d2199-b3e9-4cf8-a8e5-111bb620bb2f-1711378365616/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/constants" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-contracts-5.6.0-3a1d2199-b3e9-4cf8-a8e5-111bb620bb2f-1711378365616/node_modules/@ethersproject-xdc/constants" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-contracts-5.6.0-3a1d2199-b3e9-4cf8-a8e5-111bb620bb2f-1711378365616/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/properties" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-contracts-5.6.0-3a1d2199-b3e9-4cf8-a8e5-111bb620bb2f-1711378365616/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/transactions" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-contracts-5.6.0-3a1d2199-b3e9-4cf8-a8e5-111bb620bb2f-1711378365616/node_modules/@ethersproject-xdc/transactions" + "@ethersproject-xdc/abi" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-78487f10-66d0-4607-8f7f-fd11ddd5c748-1719153755508/node_modules/@ethersproject-xdc/abi" + "@ethersproject-xdc/abstract-provider" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-78487f10-66d0-4607-8f7f-fd11ddd5c748-1719153755508/node_modules/@ethersproject-xdc/abstract-provider" + "@ethersproject-xdc/abstract-signer" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-78487f10-66d0-4607-8f7f-fd11ddd5c748-1719153755508/node_modules/@ethersproject-xdc/abstract-signer" + "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-78487f10-66d0-4607-8f7f-fd11ddd5c748-1719153755508/node_modules/@ethersproject-xdc/address" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-78487f10-66d0-4607-8f7f-fd11ddd5c748-1719153755508/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-78487f10-66d0-4607-8f7f-fd11ddd5c748-1719153755508/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/constants" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-78487f10-66d0-4607-8f7f-fd11ddd5c748-1719153755508/node_modules/@ethersproject-xdc/constants" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-78487f10-66d0-4607-8f7f-fd11ddd5c748-1719153755508/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-78487f10-66d0-4607-8f7f-fd11ddd5c748-1719153755508/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/transactions" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-78487f10-66d0-4607-8f7f-fd11ddd5c748-1719153755508/node_modules/@ethersproject-xdc/transactions" "@ethersproject-xdc/hash@file:vendor/@ethersproject-xdc/hash": version "5.7.0" dependencies: - "@ethersproject-xdc/abstract-signer" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hash-5.7.0-e59c6ed5-6f74-42e7-b132-f4bea3ddfad0-1711378365617/node_modules/@ethersproject-xdc/abstract-signer" - "@ethersproject-xdc/address" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hash-5.7.0-e59c6ed5-6f74-42e7-b132-f4bea3ddfad0-1711378365617/node_modules/@ethersproject-xdc/address" - "@ethersproject-xdc/base64" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hash-5.7.0-e59c6ed5-6f74-42e7-b132-f4bea3ddfad0-1711378365617/node_modules/@ethersproject-xdc/base64" - "@ethersproject-xdc/bignumber" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hash-5.7.0-e59c6ed5-6f74-42e7-b132-f4bea3ddfad0-1711378365617/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hash-5.7.0-e59c6ed5-6f74-42e7-b132-f4bea3ddfad0-1711378365617/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/keccak256" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hash-5.7.0-e59c6ed5-6f74-42e7-b132-f4bea3ddfad0-1711378365617/node_modules/@ethersproject-xdc/keccak256" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hash-5.7.0-e59c6ed5-6f74-42e7-b132-f4bea3ddfad0-1711378365617/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/properties" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hash-5.7.0-e59c6ed5-6f74-42e7-b132-f4bea3ddfad0-1711378365617/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/strings" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hash-5.7.0-e59c6ed5-6f74-42e7-b132-f4bea3ddfad0-1711378365617/node_modules/@ethersproject-xdc/strings" + "@ethersproject-xdc/abstract-signer" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-9ccfe7f3-be05-4975-b2a7-61d9ef6f6fd2-1719153755509/node_modules/@ethersproject-xdc/abstract-signer" + "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-9ccfe7f3-be05-4975-b2a7-61d9ef6f6fd2-1719153755509/node_modules/@ethersproject-xdc/address" + "@ethersproject-xdc/base64" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-9ccfe7f3-be05-4975-b2a7-61d9ef6f6fd2-1719153755509/node_modules/@ethersproject-xdc/base64" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-9ccfe7f3-be05-4975-b2a7-61d9ef6f6fd2-1719153755509/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-9ccfe7f3-be05-4975-b2a7-61d9ef6f6fd2-1719153755509/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-9ccfe7f3-be05-4975-b2a7-61d9ef6f6fd2-1719153755509/node_modules/@ethersproject-xdc/keccak256" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-9ccfe7f3-be05-4975-b2a7-61d9ef6f6fd2-1719153755509/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-9ccfe7f3-be05-4975-b2a7-61d9ef6f6fd2-1719153755509/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-9ccfe7f3-be05-4975-b2a7-61d9ef6f6fd2-1719153755509/node_modules/@ethersproject-xdc/strings" "@ethersproject-xdc/hdnode@file:vendor/@ethersproject-xdc/hdnode": version "5.7.0" dependencies: - "@ethersproject-xdc/abstract-signer" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hdnode-5.7.0-7df6d3a0-85a2-4dd8-84f0-7defb4301c82-1711378365618/node_modules/@ethersproject-xdc/abstract-signer" - "@ethersproject-xdc/basex" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hdnode-5.7.0-7df6d3a0-85a2-4dd8-84f0-7defb4301c82-1711378365618/node_modules/@ethersproject-xdc/basex" - "@ethersproject-xdc/bignumber" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hdnode-5.7.0-7df6d3a0-85a2-4dd8-84f0-7defb4301c82-1711378365618/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hdnode-5.7.0-7df6d3a0-85a2-4dd8-84f0-7defb4301c82-1711378365618/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hdnode-5.7.0-7df6d3a0-85a2-4dd8-84f0-7defb4301c82-1711378365618/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/pbkdf2" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hdnode-5.7.0-7df6d3a0-85a2-4dd8-84f0-7defb4301c82-1711378365618/node_modules/@ethersproject-xdc/pbkdf2" - "@ethersproject-xdc/properties" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hdnode-5.7.0-7df6d3a0-85a2-4dd8-84f0-7defb4301c82-1711378365618/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/sha2" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hdnode-5.7.0-7df6d3a0-85a2-4dd8-84f0-7defb4301c82-1711378365618/node_modules/@ethersproject-xdc/sha2" - "@ethersproject-xdc/signing-key" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hdnode-5.7.0-7df6d3a0-85a2-4dd8-84f0-7defb4301c82-1711378365618/node_modules/@ethersproject-xdc/signing-key" - "@ethersproject-xdc/strings" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hdnode-5.7.0-7df6d3a0-85a2-4dd8-84f0-7defb4301c82-1711378365618/node_modules/@ethersproject-xdc/strings" - "@ethersproject-xdc/transactions" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hdnode-5.7.0-7df6d3a0-85a2-4dd8-84f0-7defb4301c82-1711378365618/node_modules/@ethersproject-xdc/transactions" - "@ethersproject-xdc/wordlists" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-hdnode-5.7.0-7df6d3a0-85a2-4dd8-84f0-7defb4301c82-1711378365618/node_modules/@ethersproject-xdc/wordlists" + "@ethersproject-xdc/abstract-signer" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-3981ae87-a013-403b-a71b-c6ffdccc368b-1719153755510/node_modules/@ethersproject-xdc/abstract-signer" + "@ethersproject-xdc/basex" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-3981ae87-a013-403b-a71b-c6ffdccc368b-1719153755510/node_modules/@ethersproject-xdc/basex" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-3981ae87-a013-403b-a71b-c6ffdccc368b-1719153755510/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-3981ae87-a013-403b-a71b-c6ffdccc368b-1719153755510/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-3981ae87-a013-403b-a71b-c6ffdccc368b-1719153755510/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/pbkdf2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-3981ae87-a013-403b-a71b-c6ffdccc368b-1719153755510/node_modules/@ethersproject-xdc/pbkdf2" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-3981ae87-a013-403b-a71b-c6ffdccc368b-1719153755510/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/sha2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-3981ae87-a013-403b-a71b-c6ffdccc368b-1719153755510/node_modules/@ethersproject-xdc/sha2" + "@ethersproject-xdc/signing-key" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-3981ae87-a013-403b-a71b-c6ffdccc368b-1719153755510/node_modules/@ethersproject-xdc/signing-key" + "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-3981ae87-a013-403b-a71b-c6ffdccc368b-1719153755510/node_modules/@ethersproject-xdc/strings" + "@ethersproject-xdc/transactions" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-3981ae87-a013-403b-a71b-c6ffdccc368b-1719153755510/node_modules/@ethersproject-xdc/transactions" + "@ethersproject-xdc/wordlists" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-3981ae87-a013-403b-a71b-c6ffdccc368b-1719153755510/node_modules/@ethersproject-xdc/wordlists" "@ethersproject-xdc/json-wallets@file:vendor/@ethersproject-xdc/json-wallets": version "5.6.0" dependencies: - "@ethersproject-xdc/abstract-signer" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-b09d5477-70d2-455d-95b9-95327c90a434-1711378365617/node_modules/@ethersproject-xdc/abstract-signer" - "@ethersproject-xdc/address" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-b09d5477-70d2-455d-95b9-95327c90a434-1711378365617/node_modules/@ethersproject-xdc/address" - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-b09d5477-70d2-455d-95b9-95327c90a434-1711378365617/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/hdnode" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-b09d5477-70d2-455d-95b9-95327c90a434-1711378365617/node_modules/@ethersproject-xdc/hdnode" - "@ethersproject-xdc/keccak256" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-b09d5477-70d2-455d-95b9-95327c90a434-1711378365617/node_modules/@ethersproject-xdc/keccak256" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-b09d5477-70d2-455d-95b9-95327c90a434-1711378365617/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/pbkdf2" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-b09d5477-70d2-455d-95b9-95327c90a434-1711378365617/node_modules/@ethersproject-xdc/pbkdf2" - "@ethersproject-xdc/properties" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-b09d5477-70d2-455d-95b9-95327c90a434-1711378365617/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/random" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-b09d5477-70d2-455d-95b9-95327c90a434-1711378365617/node_modules/@ethersproject-xdc/random" - "@ethersproject-xdc/strings" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-b09d5477-70d2-455d-95b9-95327c90a434-1711378365617/node_modules/@ethersproject-xdc/strings" - "@ethersproject-xdc/transactions" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-b09d5477-70d2-455d-95b9-95327c90a434-1711378365617/node_modules/@ethersproject-xdc/transactions" + "@ethersproject-xdc/abstract-signer" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-4576d561-d46f-4350-bac0-c1f350e7140f-1719153755511/node_modules/@ethersproject-xdc/abstract-signer" + "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-4576d561-d46f-4350-bac0-c1f350e7140f-1719153755511/node_modules/@ethersproject-xdc/address" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-4576d561-d46f-4350-bac0-c1f350e7140f-1719153755511/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/hdnode" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-4576d561-d46f-4350-bac0-c1f350e7140f-1719153755511/node_modules/@ethersproject-xdc/hdnode" + "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-4576d561-d46f-4350-bac0-c1f350e7140f-1719153755511/node_modules/@ethersproject-xdc/keccak256" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-4576d561-d46f-4350-bac0-c1f350e7140f-1719153755511/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/pbkdf2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-4576d561-d46f-4350-bac0-c1f350e7140f-1719153755511/node_modules/@ethersproject-xdc/pbkdf2" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-4576d561-d46f-4350-bac0-c1f350e7140f-1719153755511/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/random" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-4576d561-d46f-4350-bac0-c1f350e7140f-1719153755511/node_modules/@ethersproject-xdc/random" + "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-4576d561-d46f-4350-bac0-c1f350e7140f-1719153755511/node_modules/@ethersproject-xdc/strings" + "@ethersproject-xdc/transactions" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-4576d561-d46f-4350-bac0-c1f350e7140f-1719153755511/node_modules/@ethersproject-xdc/transactions" aes-js "3.0.0" scrypt-js "3.0.1" "@ethersproject-xdc/keccak256@file:vendor/@ethersproject-xdc/keccak256": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-keccak256-5.7.0-9cb7534e-f2d4-4bb8-8726-aa8d2ae70a68-1711378365617/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-keccak256-5.7.0-cb051885-95c1-4a94-bbf8-f8d04f04eee0-1719153755510/node_modules/@ethersproject-xdc/bytes" js-sha3 "0.8.0" "@ethersproject-xdc/logger@file:vendor/@ethersproject-xdc/logger": @@ -1573,67 +1573,67 @@ "@ethersproject-xdc/networks@file:vendor/@ethersproject-xdc/networks": version "5.7.1" dependencies: - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-networks-5.7.1-3318040d-6ee2-4fe1-8d35-2e90df014a04-1711378365619/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-networks-5.7.1-171acc93-ca9f-4a12-8843-d9288ca886de-1719153755511/node_modules/@ethersproject-xdc/logger" "@ethersproject-xdc/pbkdf2@file:vendor/@ethersproject-xdc/pbkdf2": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-pbkdf2-5.7.0-1db75448-b10f-4529-b48f-66f22c09a20a-1711378365617/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/sha2" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-pbkdf2-5.7.0-1db75448-b10f-4529-b48f-66f22c09a20a-1711378365617/node_modules/@ethersproject-xdc/sha2" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-pbkdf2-5.7.0-bf8578fb-58ad-4269-8b7b-6a257581a040-1719153755508/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/sha2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-pbkdf2-5.7.0-bf8578fb-58ad-4269-8b7b-6a257581a040-1719153755508/node_modules/@ethersproject-xdc/sha2" "@ethersproject-xdc/properties@file:vendor/@ethersproject-xdc/properties": version "5.7.0" dependencies: - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-properties-5.7.0-d600654f-dc20-45bd-8730-5aea66cd419c-1711378365618/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-properties-5.7.0-fa8f5a3d-d88b-46a2-b3f9-e089d9818508-1719153755510/node_modules/@ethersproject-xdc/logger" "@ethersproject-xdc/providers@file:vendor/@ethersproject-xdc/providers": version "5.6.2" dependencies: - "@ethersproject-xdc/abstract-provider" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/abstract-provider" - "@ethersproject-xdc/abstract-signer" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/abstract-signer" - "@ethersproject-xdc/address" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/address" - "@ethersproject-xdc/basex" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/basex" - "@ethersproject-xdc/bignumber" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/constants" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/constants" - "@ethersproject-xdc/hash" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/hash" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/networks" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/networks" - "@ethersproject-xdc/properties" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/random" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/random" - "@ethersproject-xdc/rlp" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/rlp" - "@ethersproject-xdc/sha2" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/sha2" - "@ethersproject-xdc/strings" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/strings" - "@ethersproject-xdc/transactions" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/transactions" - "@ethersproject-xdc/web" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-providers-5.6.2-0e620e87-104e-4693-b0d6-cc54eba98645-1711378365618/node_modules/@ethersproject-xdc/web" + "@ethersproject-xdc/abstract-provider" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/abstract-provider" + "@ethersproject-xdc/abstract-signer" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/abstract-signer" + "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/address" + "@ethersproject-xdc/basex" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/basex" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/constants" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/constants" + "@ethersproject-xdc/hash" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/hash" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/networks" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/networks" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/random" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/random" + "@ethersproject-xdc/rlp" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/rlp" + "@ethersproject-xdc/sha2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/sha2" + "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/strings" + "@ethersproject-xdc/transactions" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/transactions" + "@ethersproject-xdc/web" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/web" bech32 "1.1.4" ws "7.4.6" "@ethersproject-xdc/random@file:vendor/@ethersproject-xdc/random": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-random-5.7.0-98a7dd46-79c6-4335-9d15-21617d7f16a5-1711378365619/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-random-5.7.0-98a7dd46-79c6-4335-9d15-21617d7f16a5-1711378365619/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-random-5.7.0-70f5f413-6e0e-4de6-ab10-ab66c16998cc-1719153755509/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-random-5.7.0-70f5f413-6e0e-4de6-ab10-ab66c16998cc-1719153755509/node_modules/@ethersproject-xdc/logger" "@ethersproject-xdc/rlp@file:vendor/@ethersproject-xdc/rlp": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-rlp-5.7.0-7790503f-a04f-459f-8b5c-cf61ffd4ff12-1711378365619/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-rlp-5.7.0-7790503f-a04f-459f-8b5c-cf61ffd4ff12-1711378365619/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-rlp-5.7.0-e704c0fb-ff6e-480e-b9ca-3687e620559f-1719153755510/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-rlp-5.7.0-e704c0fb-ff6e-480e-b9ca-3687e620559f-1719153755510/node_modules/@ethersproject-xdc/logger" "@ethersproject-xdc/sha2@file:vendor/@ethersproject-xdc/sha2": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-sha2-5.7.0-c765449d-476b-4741-9e2e-dbccb8aa1809-1711378365619/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-sha2-5.7.0-c765449d-476b-4741-9e2e-dbccb8aa1809-1711378365619/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-sha2-5.7.0-f65c2a79-9ae7-4c25-8f9f-d63c95cff9fd-1719153755515/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-sha2-5.7.0-f65c2a79-9ae7-4c25-8f9f-d63c95cff9fd-1719153755515/node_modules/@ethersproject-xdc/logger" hash.js "1.1.7" "@ethersproject-xdc/signing-key@file:vendor/@ethersproject-xdc/signing-key": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-signing-key-5.7.0-21971b50-7b39-465c-bb5a-2f8689e48cc2-1711378365620/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-signing-key-5.7.0-21971b50-7b39-465c-bb5a-2f8689e48cc2-1711378365620/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/properties" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-signing-key-5.7.0-21971b50-7b39-465c-bb5a-2f8689e48cc2-1711378365620/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-signing-key-5.7.0-44a763f8-7883-4c21-833a-8e22e8631ff7-1719153755515/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-signing-key-5.7.0-44a763f8-7883-4c21-833a-8e22e8631ff7-1719153755515/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-signing-key-5.7.0-44a763f8-7883-4c21-833a-8e22e8631ff7-1719153755515/node_modules/@ethersproject-xdc/properties" bn.js "^5.2.1" elliptic "6.5.4" hash.js "1.1.7" @@ -1641,76 +1641,76 @@ "@ethersproject-xdc/solidity@file:vendor/@ethersproject-xdc/solidity": version "5.6.0" dependencies: - "@ethersproject-xdc/bignumber" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-solidity-5.6.0-e3924149-bd04-4548-98cf-44195b92192d-1711378365619/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-solidity-5.6.0-e3924149-bd04-4548-98cf-44195b92192d-1711378365619/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/keccak256" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-solidity-5.6.0-e3924149-bd04-4548-98cf-44195b92192d-1711378365619/node_modules/@ethersproject-xdc/keccak256" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-solidity-5.6.0-e3924149-bd04-4548-98cf-44195b92192d-1711378365619/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/sha2" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-solidity-5.6.0-e3924149-bd04-4548-98cf-44195b92192d-1711378365619/node_modules/@ethersproject-xdc/sha2" - "@ethersproject-xdc/strings" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-solidity-5.6.0-e3924149-bd04-4548-98cf-44195b92192d-1711378365619/node_modules/@ethersproject-xdc/strings" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-solidity-5.6.0-9e516e38-2ffe-4712-9308-583e3643ccf8-1719153755511/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-solidity-5.6.0-9e516e38-2ffe-4712-9308-583e3643ccf8-1719153755511/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-solidity-5.6.0-9e516e38-2ffe-4712-9308-583e3643ccf8-1719153755511/node_modules/@ethersproject-xdc/keccak256" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-solidity-5.6.0-9e516e38-2ffe-4712-9308-583e3643ccf8-1719153755511/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/sha2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-solidity-5.6.0-9e516e38-2ffe-4712-9308-583e3643ccf8-1719153755511/node_modules/@ethersproject-xdc/sha2" + "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-solidity-5.6.0-9e516e38-2ffe-4712-9308-583e3643ccf8-1719153755511/node_modules/@ethersproject-xdc/strings" "@ethersproject-xdc/strings@file:vendor/@ethersproject-xdc/strings": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-strings-5.7.0-42e9cb08-71fd-4932-bd36-6f05e0f1b34b-1711378365620/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/constants" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-strings-5.7.0-42e9cb08-71fd-4932-bd36-6f05e0f1b34b-1711378365620/node_modules/@ethersproject-xdc/constants" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-strings-5.7.0-42e9cb08-71fd-4932-bd36-6f05e0f1b34b-1711378365620/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-strings-5.7.0-6eaaabc3-473b-4a57-aa46-a8f421dcf49d-1719153755513/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/constants" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-strings-5.7.0-6eaaabc3-473b-4a57-aa46-a8f421dcf49d-1719153755513/node_modules/@ethersproject-xdc/constants" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-strings-5.7.0-6eaaabc3-473b-4a57-aa46-a8f421dcf49d-1719153755513/node_modules/@ethersproject-xdc/logger" "@ethersproject-xdc/transactions@file:vendor/@ethersproject-xdc/transactions": version "5.7.0" dependencies: - "@ethersproject-xdc/address" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-transactions-5.7.0-bb480f26-2b90-41a5-bfff-057ac9b6e8e9-1711378365622/node_modules/@ethersproject-xdc/address" - "@ethersproject-xdc/bignumber" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-transactions-5.7.0-bb480f26-2b90-41a5-bfff-057ac9b6e8e9-1711378365622/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-transactions-5.7.0-bb480f26-2b90-41a5-bfff-057ac9b6e8e9-1711378365622/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/constants" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-transactions-5.7.0-bb480f26-2b90-41a5-bfff-057ac9b6e8e9-1711378365622/node_modules/@ethersproject-xdc/constants" - "@ethersproject-xdc/keccak256" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-transactions-5.7.0-bb480f26-2b90-41a5-bfff-057ac9b6e8e9-1711378365622/node_modules/@ethersproject-xdc/keccak256" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-transactions-5.7.0-bb480f26-2b90-41a5-bfff-057ac9b6e8e9-1711378365622/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/properties" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-transactions-5.7.0-bb480f26-2b90-41a5-bfff-057ac9b6e8e9-1711378365622/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/rlp" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-transactions-5.7.0-bb480f26-2b90-41a5-bfff-057ac9b6e8e9-1711378365622/node_modules/@ethersproject-xdc/rlp" - "@ethersproject-xdc/signing-key" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-transactions-5.7.0-bb480f26-2b90-41a5-bfff-057ac9b6e8e9-1711378365622/node_modules/@ethersproject-xdc/signing-key" + "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-8aafcfdf-6ea6-444e-ac98-a592f462b294-1719153755512/node_modules/@ethersproject-xdc/address" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-8aafcfdf-6ea6-444e-ac98-a592f462b294-1719153755512/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-8aafcfdf-6ea6-444e-ac98-a592f462b294-1719153755512/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/constants" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-8aafcfdf-6ea6-444e-ac98-a592f462b294-1719153755512/node_modules/@ethersproject-xdc/constants" + "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-8aafcfdf-6ea6-444e-ac98-a592f462b294-1719153755512/node_modules/@ethersproject-xdc/keccak256" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-8aafcfdf-6ea6-444e-ac98-a592f462b294-1719153755512/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-8aafcfdf-6ea6-444e-ac98-a592f462b294-1719153755512/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/rlp" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-8aafcfdf-6ea6-444e-ac98-a592f462b294-1719153755512/node_modules/@ethersproject-xdc/rlp" + "@ethersproject-xdc/signing-key" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-8aafcfdf-6ea6-444e-ac98-a592f462b294-1719153755512/node_modules/@ethersproject-xdc/signing-key" "@ethersproject-xdc/units@file:vendor/@ethersproject-xdc/units": version "5.6.0" dependencies: - "@ethersproject-xdc/bignumber" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-units-5.6.0-5f41db51-35b1-4973-a795-080ed99a99b4-1711378365619/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/constants" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-units-5.6.0-5f41db51-35b1-4973-a795-080ed99a99b4-1711378365619/node_modules/@ethersproject-xdc/constants" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-units-5.6.0-5f41db51-35b1-4973-a795-080ed99a99b4-1711378365619/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-units-5.6.0-2b8286d8-0442-4926-9f41-259da9273a3b-1719153755512/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/constants" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-units-5.6.0-2b8286d8-0442-4926-9f41-259da9273a3b-1719153755512/node_modules/@ethersproject-xdc/constants" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-units-5.6.0-2b8286d8-0442-4926-9f41-259da9273a3b-1719153755512/node_modules/@ethersproject-xdc/logger" "@ethersproject-xdc/wallet@file:vendor/@ethersproject-xdc/wallet": version "5.6.0" dependencies: - "@ethersproject-xdc/abstract-provider" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wallet-5.6.0-bc949dc4-090d-4ab9-b6c6-709a17fc75ad-1711378365622/node_modules/@ethersproject-xdc/abstract-provider" - "@ethersproject-xdc/abstract-signer" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wallet-5.6.0-bc949dc4-090d-4ab9-b6c6-709a17fc75ad-1711378365622/node_modules/@ethersproject-xdc/abstract-signer" - "@ethersproject-xdc/address" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wallet-5.6.0-bc949dc4-090d-4ab9-b6c6-709a17fc75ad-1711378365622/node_modules/@ethersproject-xdc/address" - "@ethersproject-xdc/bignumber" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wallet-5.6.0-bc949dc4-090d-4ab9-b6c6-709a17fc75ad-1711378365622/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wallet-5.6.0-bc949dc4-090d-4ab9-b6c6-709a17fc75ad-1711378365622/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/hash" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wallet-5.6.0-bc949dc4-090d-4ab9-b6c6-709a17fc75ad-1711378365622/node_modules/@ethersproject-xdc/hash" - "@ethersproject-xdc/hdnode" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wallet-5.6.0-bc949dc4-090d-4ab9-b6c6-709a17fc75ad-1711378365622/node_modules/@ethersproject-xdc/hdnode" - "@ethersproject-xdc/json-wallets" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wallet-5.6.0-bc949dc4-090d-4ab9-b6c6-709a17fc75ad-1711378365622/node_modules/@ethersproject-xdc/json-wallets" - "@ethersproject-xdc/keccak256" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wallet-5.6.0-bc949dc4-090d-4ab9-b6c6-709a17fc75ad-1711378365622/node_modules/@ethersproject-xdc/keccak256" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wallet-5.6.0-bc949dc4-090d-4ab9-b6c6-709a17fc75ad-1711378365622/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/properties" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wallet-5.6.0-bc949dc4-090d-4ab9-b6c6-709a17fc75ad-1711378365622/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/random" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wallet-5.6.0-bc949dc4-090d-4ab9-b6c6-709a17fc75ad-1711378365622/node_modules/@ethersproject-xdc/random" - "@ethersproject-xdc/signing-key" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wallet-5.6.0-bc949dc4-090d-4ab9-b6c6-709a17fc75ad-1711378365622/node_modules/@ethersproject-xdc/signing-key" - "@ethersproject-xdc/transactions" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wallet-5.6.0-bc949dc4-090d-4ab9-b6c6-709a17fc75ad-1711378365622/node_modules/@ethersproject-xdc/transactions" - "@ethersproject-xdc/wordlists" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wallet-5.6.0-bc949dc4-090d-4ab9-b6c6-709a17fc75ad-1711378365622/node_modules/@ethersproject-xdc/wordlists" + "@ethersproject-xdc/abstract-provider" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-086066b3-a620-4717-aa8f-ab6eb39a2d09-1719153755513/node_modules/@ethersproject-xdc/abstract-provider" + "@ethersproject-xdc/abstract-signer" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-086066b3-a620-4717-aa8f-ab6eb39a2d09-1719153755513/node_modules/@ethersproject-xdc/abstract-signer" + "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-086066b3-a620-4717-aa8f-ab6eb39a2d09-1719153755513/node_modules/@ethersproject-xdc/address" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-086066b3-a620-4717-aa8f-ab6eb39a2d09-1719153755513/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-086066b3-a620-4717-aa8f-ab6eb39a2d09-1719153755513/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/hash" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-086066b3-a620-4717-aa8f-ab6eb39a2d09-1719153755513/node_modules/@ethersproject-xdc/hash" + "@ethersproject-xdc/hdnode" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-086066b3-a620-4717-aa8f-ab6eb39a2d09-1719153755513/node_modules/@ethersproject-xdc/hdnode" + "@ethersproject-xdc/json-wallets" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-086066b3-a620-4717-aa8f-ab6eb39a2d09-1719153755513/node_modules/@ethersproject-xdc/json-wallets" + "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-086066b3-a620-4717-aa8f-ab6eb39a2d09-1719153755513/node_modules/@ethersproject-xdc/keccak256" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-086066b3-a620-4717-aa8f-ab6eb39a2d09-1719153755513/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-086066b3-a620-4717-aa8f-ab6eb39a2d09-1719153755513/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/random" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-086066b3-a620-4717-aa8f-ab6eb39a2d09-1719153755513/node_modules/@ethersproject-xdc/random" + "@ethersproject-xdc/signing-key" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-086066b3-a620-4717-aa8f-ab6eb39a2d09-1719153755513/node_modules/@ethersproject-xdc/signing-key" + "@ethersproject-xdc/transactions" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-086066b3-a620-4717-aa8f-ab6eb39a2d09-1719153755513/node_modules/@ethersproject-xdc/transactions" + "@ethersproject-xdc/wordlists" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-086066b3-a620-4717-aa8f-ab6eb39a2d09-1719153755513/node_modules/@ethersproject-xdc/wordlists" "@ethersproject-xdc/web@file:vendor/@ethersproject-xdc/web": version "5.7.1" dependencies: - "@ethersproject-xdc/base64" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-web-5.7.1-9ac39370-4d32-4c38-96c7-4498ea524885-1711378365623/node_modules/@ethersproject-xdc/base64" - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-web-5.7.1-9ac39370-4d32-4c38-96c7-4498ea524885-1711378365623/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-web-5.7.1-9ac39370-4d32-4c38-96c7-4498ea524885-1711378365623/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/properties" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-web-5.7.1-9ac39370-4d32-4c38-96c7-4498ea524885-1711378365623/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/strings" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-web-5.7.1-9ac39370-4d32-4c38-96c7-4498ea524885-1711378365623/node_modules/@ethersproject-xdc/strings" + "@ethersproject-xdc/base64" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-web-5.7.1-e313826a-9d51-48ff-a1d5-8f4abfb2b3ac-1719153755514/node_modules/@ethersproject-xdc/base64" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-web-5.7.1-e313826a-9d51-48ff-a1d5-8f4abfb2b3ac-1719153755514/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-web-5.7.1-e313826a-9d51-48ff-a1d5-8f4abfb2b3ac-1719153755514/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-web-5.7.1-e313826a-9d51-48ff-a1d5-8f4abfb2b3ac-1719153755514/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-web-5.7.1-e313826a-9d51-48ff-a1d5-8f4abfb2b3ac-1719153755514/node_modules/@ethersproject-xdc/strings" "@ethersproject-xdc/wordlists@file:vendor/@ethersproject-xdc/wordlists": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wordlists-5.7.0-eafc2a13-cd67-4bf6-9256-aec79a731277-1711378365623/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/hash" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wordlists-5.7.0-eafc2a13-cd67-4bf6-9256-aec79a731277-1711378365623/node_modules/@ethersproject-xdc/hash" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wordlists-5.7.0-eafc2a13-cd67-4bf6-9256-aec79a731277-1711378365623/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/properties" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wordlists-5.7.0-eafc2a13-cd67-4bf6-9256-aec79a731277-1711378365623/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/strings" "file:../Library/Caches/Yarn/v6/npm-@ethersproject-xdc-wordlists-5.7.0-eafc2a13-cd67-4bf6-9256-aec79a731277-1711378365623/node_modules/@ethersproject-xdc/strings" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wordlists-5.7.0-9d6615b4-40a6-4a9b-a974-87598d611be3-1719153755514/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/hash" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wordlists-5.7.0-9d6615b4-40a6-4a9b-a974-87598d611be3-1719153755514/node_modules/@ethersproject-xdc/hash" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wordlists-5.7.0-9d6615b4-40a6-4a9b-a974-87598d611be3-1719153755514/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wordlists-5.7.0-9d6615b4-40a6-4a9b-a974-87598d611be3-1719153755514/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wordlists-5.7.0-9d6615b4-40a6-4a9b-a974-87598d611be3-1719153755514/node_modules/@ethersproject-xdc/strings" "@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.0.12", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.4.0", "@ethersproject/abi@^5.5.0", "@ethersproject/abi@^5.6.3", "@ethersproject/abi@^5.7.0": version "5.7.0" @@ -2103,6 +2103,11 @@ dependencies: keccak "^3.0.0" +"@fleet-sdk/common@^0.3.4": + version "0.3.4" + resolved "https://registry.yarnpkg.com/@fleet-sdk/common/-/common-0.3.4.tgz#bd343ae03171b681444c51cc81e6a9021d660d1f" + integrity sha512-FzrjElAy2hmxuXkFnTITGQKS7tsO9DIqyN7a1ki5T/REdTAHgZX3LseZUf0zuzjH21arez81kAnNYU+yBOJtRg== + "@graphql-tools/batch-execute@8.5.1": version "8.5.1" resolved "https://registry.yarnpkg.com/@graphql-tools/batch-execute/-/batch-execute-8.5.1.tgz#fa3321d58c64041650be44250b1ebc3aab0ba7a9" @@ -3374,6 +3379,39 @@ tiny-warning "^1.0.3" toformat "^2.0.0" +"@patternglobal/ergo-dex-sdk@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@patternglobal/ergo-dex-sdk/-/ergo-dex-sdk-1.0.1.tgz#645638675b33fa22bbfb28eb6f6131ef82acacbe" + integrity sha512-N+ozRr7TRHcIlPKwLlLjhcCxC0gyy2TZxdnj3op57NXTe3ykFM1kq4+wWwn/o2rrIA+EMv69HflwULzlhkA8QA== + dependencies: + "@patternglobal/ergo-sdk" "^1.0.0" + axios "^0.21.1" + blakejs "^1.1.0" + bs58 "^4.0.1" + crypto-js "^4.0.0" + ergo-lib-wasm-browser "0.20.1" + ergo-lib-wasm-nodejs "0.20.1" + esm-wallaby "^3.2.25" + json-bigint "^1.0.0" + mathjs "^9.4.4" + ramda "0.27.1" + +"@patternglobal/ergo-sdk@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@patternglobal/ergo-sdk/-/ergo-sdk-1.0.0.tgz#661051216b719051ea9629fcee8c20a1c1743122" + integrity sha512-5ZOfpwavBmBT2CftoXyNOJlFQkult5pmAL2XcO5vvcxDDuD0BnlkTmOsaqOS3ShTFPW6z7U8wHovB2fSfdt5iA== + dependencies: + axios "^0.21.1" + blakejs "^1.1.0" + bs58 "^4.0.1" + crypto-js "^4.0.0" + ergo-lib-wasm-browser "^0.20.1" + ergo-lib-wasm-nodejs "^0.20.1" + esm-wallaby "^3.2.25" + json-bigint "^1.0.0" + mathjs "^9.4.4" + ramda "0.27.1" + "@perp/curie-deployments@2022.12.20-1671509278203": version "2022.12.20-1671509278203" resolved "https://registry.yarnpkg.com/@perp/curie-deployments/-/curie-deployments-2022.12.20-1671509278203.tgz#16c716936741df41cd91171d3d75575eb49971d8" @@ -7133,6 +7171,11 @@ crypto-browserify@3.12.0: randombytes "^2.0.0" randomfill "^1.0.3" +crypto-js@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.2.0.tgz#4d931639ecdfd12ff80e8186dba6af2c2e856631" + integrity sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q== + cssfilter@0.0.10: version "0.0.10" resolved "https://registry.yarnpkg.com/cssfilter/-/cssfilter-0.0.10.tgz#c6d2672632a2e5c83e013e6864a42ce8defd20ae" @@ -7660,6 +7703,21 @@ env-paths@^2.2.0, env-paths@^2.2.1: resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== +ergo-lib-wasm-browser@0.20.1, ergo-lib-wasm-browser@^0.20.1: + version "0.20.1" + resolved "https://registry.yarnpkg.com/ergo-lib-wasm-browser/-/ergo-lib-wasm-browser-0.20.1.tgz#68097ba6ddf464447866066c9c3f3d960651af7e" + integrity sha512-g324oXm9kdNphqVuiIzb1lWpawASp7zihcqc8wmr+/xwB8RBSEV+IBwAu4RYMRHNwlwffsPOtKvk+lRpxUFVxQ== + +ergo-lib-wasm-nodejs@0.20.1, ergo-lib-wasm-nodejs@^0.20.1: + version "0.20.1" + resolved "https://registry.yarnpkg.com/ergo-lib-wasm-nodejs/-/ergo-lib-wasm-nodejs-0.20.1.tgz#390802910290c37e83c5316028751ea5e4b41e79" + integrity sha512-2jGQ21HWQdsA9hOXr2DJS7iq32uIQHL45hxfNJ1VnYRUbVkQRpBWB7PRFKZvlIlZT6dIifcg8IacF6hqBOfB2g== + +ergo-lib-wasm-nodejs@^0.22.0: + version "0.22.0" + resolved "https://registry.yarnpkg.com/ergo-lib-wasm-nodejs/-/ergo-lib-wasm-nodejs-0.22.0.tgz#e482e645f72cf97d1b467624968c811e41b8b3c8" + integrity sha512-eyVIUcEakeBVzFfLkS7CLxRxHO7VyP/V4NghIXHiY8WxFkd0qNFBUs+4IfpQWmv0SOnArm58PpottK2Ka9aYpg== + err-code@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" @@ -8019,6 +8077,11 @@ eslint@^8.57.0: strip-ansi "^6.0.1" text-table "^0.2.0" +esm-wallaby@^3.2.25: + version "3.2.30" + resolved "https://registry.yarnpkg.com/esm-wallaby/-/esm-wallaby-3.2.30.tgz#b249c5da1000d29b2ddbd05a9e5974c0c34d1432" + integrity sha512-Zq4K2y5co9tASH6GE87r01ZF1u3qV4iqbgoPt8B+OWWLaNaExv15T8SioufCPGNfugpEhFZiux3Wr7GNNzXWLQ== + espree@^9.6.0, espree@^9.6.1: version "9.6.1" resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" @@ -8186,36 +8249,36 @@ ethereumjs-util@^6.0.0, ethereumjs-util@^6.2.1: "ethers-xdc@file:./vendor/ethers-xdc": version "5.7.2" dependencies: - "@ethersproject-xdc/abi" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/abi" - "@ethersproject-xdc/abstract-provider" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/abstract-provider" - "@ethersproject-xdc/abstract-signer" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/abstract-signer" - "@ethersproject-xdc/address" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/address" - "@ethersproject-xdc/base64" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/base64" - "@ethersproject-xdc/basex" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/basex" - "@ethersproject-xdc/bignumber" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/constants" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/constants" - "@ethersproject-xdc/contracts" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/contracts" - "@ethersproject-xdc/hash" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/hash" - "@ethersproject-xdc/hdnode" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/hdnode" - "@ethersproject-xdc/json-wallets" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/json-wallets" - "@ethersproject-xdc/keccak256" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/keccak256" - "@ethersproject-xdc/logger" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/networks" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/networks" - "@ethersproject-xdc/pbkdf2" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/pbkdf2" - "@ethersproject-xdc/properties" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/providers" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/providers" - "@ethersproject-xdc/random" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/random" - "@ethersproject-xdc/rlp" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/rlp" - "@ethersproject-xdc/sha2" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/sha2" - "@ethersproject-xdc/signing-key" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/signing-key" - "@ethersproject-xdc/solidity" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/solidity" - "@ethersproject-xdc/strings" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/strings" - "@ethersproject-xdc/transactions" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/transactions" - "@ethersproject-xdc/units" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/units" - "@ethersproject-xdc/wallet" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/wallet" - "@ethersproject-xdc/web" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/web" - "@ethersproject-xdc/wordlists" "file:../Library/Caches/Yarn/v6/npm-ethers-xdc-5.7.2-ba402b8c-f1be-43c1-a0b9-2b2aeab75ab2-1711378365608/node_modules/@ethersproject-xdc/wordlists" + "@ethersproject-xdc/abi" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/abi" + "@ethersproject-xdc/abstract-provider" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/abstract-provider" + "@ethersproject-xdc/abstract-signer" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/abstract-signer" + "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/address" + "@ethersproject-xdc/base64" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/base64" + "@ethersproject-xdc/basex" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/basex" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/constants" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/constants" + "@ethersproject-xdc/contracts" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/contracts" + "@ethersproject-xdc/hash" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/hash" + "@ethersproject-xdc/hdnode" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/hdnode" + "@ethersproject-xdc/json-wallets" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/json-wallets" + "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/keccak256" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/networks" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/networks" + "@ethersproject-xdc/pbkdf2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/pbkdf2" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/providers" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/providers" + "@ethersproject-xdc/random" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/random" + "@ethersproject-xdc/rlp" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/rlp" + "@ethersproject-xdc/sha2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/sha2" + "@ethersproject-xdc/signing-key" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/signing-key" + "@ethersproject-xdc/solidity" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/solidity" + "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/strings" + "@ethersproject-xdc/transactions" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/transactions" + "@ethersproject-xdc/units" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/units" + "@ethersproject-xdc/wallet" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/wallet" + "@ethersproject-xdc/web" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/web" + "@ethersproject-xdc/wordlists" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/wordlists" ethers@4.0.0-beta.3: version "4.0.0-beta.3" @@ -11431,7 +11494,7 @@ mathjs@^10.5.0: tiny-emitter "^2.1.0" typed-function "^2.1.0" -mathjs@^9.3.0: +mathjs@^9.3.0, mathjs@^9.4.4: version "9.5.2" resolved "https://registry.yarnpkg.com/mathjs/-/mathjs-9.5.2.tgz#e0f3279320dc6f49e45d99c4fcdd8b52231f0462" integrity sha512-c0erTq0GP503/Ch2OtDOAn50GIOsuxTMjmE00NI/vKJFSWrDaQHRjx6ai+16xYv70yBSnnpUgHZGNf9FR9IwmA== @@ -13158,6 +13221,11 @@ quipuswap-v3-sdk@^0.0.7: typescript "^4.4.3" yargs "^17.2.1" +ramda@0.27.1: + version "0.27.1" + resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.27.1.tgz#66fc2df3ef873874ffc2da6aa8984658abacf5c9" + integrity sha512-PgIdVpn5y5Yns8vqb8FzBUEYn98V3xcPgawAkkgj0YJ0qDsnHCiNmZYfOGMgOvoB0eWFLpYbhxUR3mxfDIMvpw== + randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" From 5245acf192c58fa8099ee9bfcbd601e6497426f0 Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Mon, 24 Jun 2024 14:43:10 +0330 Subject: [PATCH 041/132] Solved #21 --- src/chains/ergo/ergo.ts | 67 +++++++++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 16 deletions(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 94c68de941..a12d70ac6d 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -5,6 +5,9 @@ import { Wallet, ErgoBoxes, UnsignedTransaction, + Mnemonic, + ExtSecretKey, + DerivationPath, } from 'ergo-lib-wasm-nodejs'; import LRUCache from 'lru-cache'; import { ErgoController } from './ergo.controller'; @@ -49,10 +52,7 @@ import { import { makeTarget } from '@patternglobal/ergo-dex-sdk/build/main/utils/makeTarget'; import { NativeExFeeType } from '@patternglobal/ergo-dex-sdk/build/main/types'; import { NetworkContext } from '@patternglobal/ergo-sdk/build/main/entities/networkContext'; -async function x() { - await RustModule.load(true); -} -x(); + class Pool extends AmmPool { private name: string; @@ -261,6 +261,7 @@ export class Ergo { * @async */ public async init(): Promise { + await RustModule.load(true); await this.loadAssets(); await this.loadPools(); this._ready = true; @@ -383,6 +384,32 @@ export class Ergo { }; } + /** + * Retrieves Ergo Account from mnemonic + * @param {string} mnemonic - Mnemonic + * @returns ErgoAccount + * @function + */ + public getAccountFromMnemonic(mnemonic: string): ErgoAccount { + const sks = new SecretKeys(); + const seed = Mnemonic.to_seed(mnemonic, ''); + const rootSecret = ExtSecretKey.derive_master(seed); + const changePath = DerivationPath.new(0, new Uint32Array([0])); + const secretKeyBytes = rootSecret.derive(changePath).secret_key_bytes(); + const secretKey = SecretKey.dlog_from_bytes(secretKeyBytes); + const address = secretKey.get_address().to_base58(this._networkPrefix); + + sks.add(secretKey); + + const wallet = Wallet.from_secrets(sks); + + return { + address, + wallet, + prover: new WalletProver(wallet, this._node), + }; + } + /** * Encrypt secret via password * @param {string} secret - Secret key @@ -498,6 +525,15 @@ export class Ergo { } } + public async loadPool(poolId: string): Promise { + await RustModule.load(true); + this.ammPools.push( + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + new Pool(await makeNativePools(this._explorer).get(poolId)), + ); + } + private async getPoolData(limit: number, offset: number): Promise { const [AmmPool] = await makeNativePools(this._explorer).getAll({ limit, @@ -513,6 +549,7 @@ export class Ergo { public get storedTokenList() { return this._assetMap; } + private async swap( account: ErgoAccount, pool: Pool, @@ -616,9 +653,8 @@ export class Ergo { const actions = poolActions(pool); return await actions.swap(swapParams, txContext); } - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - private async buy( + + public async buy( account: ErgoAccount, pool: Pool, x_amount: bigint, @@ -638,9 +674,8 @@ export class Ergo { false, ); } - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - private async sell( + + public async sell( account: ErgoAccount, pool: Pool, x_amount: bigint, @@ -660,6 +695,7 @@ export class Ergo { true, ); } + private async estimate( pool: Pool, amount: bigint, @@ -691,24 +727,23 @@ export class Ergo { }); return minOutput; } - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - private async estimateBuy( + + public async estimateBuy( pool: Pool, y_amount: bigint, slippage: number, ): Promise { return await this.estimate(pool, y_amount, slippage, false); } - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - private async estimateSell( + + public async estimateSell( pool: Pool, x_amount: bigint, slippage: number, ): Promise { return await this.estimate(pool, x_amount, slippage, true); } + public getPool(id: string): Pool { return this.ammPools.find((ammPool) => ammPool.id === id); } From ce3f91481f56228bbb2d449cdf0df45a733e8302 Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Mon, 24 Jun 2024 14:46:49 +0330 Subject: [PATCH 042/132] Solved #21 --- src/chains/ergo/ergo.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index a12d70ac6d..d42a35d054 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -527,11 +527,13 @@ export class Ergo { public async loadPool(poolId: string): Promise { await RustModule.load(true); - this.ammPools.push( - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - new Pool(await makeNativePools(this._explorer).get(poolId)), - ); + const pool = await this.getPool(poolId); + if (!pool) + this.ammPools.push( + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + new Pool(await makeNativePools(this._explorer).get(poolId)), + ); } private async getPoolData(limit: number, offset: number): Promise { From 84b12e57d440102452e44fcd411983eba34cad59 Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Mon, 24 Jun 2024 15:06:16 +0330 Subject: [PATCH 043/132] Solved #17 --- src/chains/ergo/ergo.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 94c68de941..7cb06fad62 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -440,12 +440,11 @@ export class Ergo { account: ErgoAccount, assetName: string, ): Promise { - const ergoAsset = this._assetMap[assetName]; + const ergoAsset = this._assetMap[assetName.toUpperCase()]; let balance = 0; - + if (!ergoAsset) throw new Error(`assetName not found ${this._chain} Node!`); try { const utxos = await this.getAddressUnspentBoxes(account.address); - balance = utxos.reduce( (total: number, box) => total + From 6694dd59923ac10a2a96d2ca84b2c79554ad03b5 Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Mon, 24 Jun 2024 15:27:55 +0330 Subject: [PATCH 044/132] Solved #16 --- src/chains/ergo/ergo.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 94c68de941..cf9b923803 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -214,6 +214,8 @@ export class Ergo { private ammPools: Array = []; constructor(network: string) { + if (network !== 'Mainnet' && network !== 'Testnet') + throw new Error('network should be `Mainnet` or `Testnet`'); const config = getErgoConfig(network); if (network === 'Mainnet') { @@ -279,6 +281,8 @@ export class Ergo { * @static */ public static getInstance(network: string): Ergo { + if (network !== 'Mainnet' && network !== 'Testnet') + throw new Error('network should be `Mainnet` or `Testnet`'); const config = getErgoConfig(network); if (!Ergo._instances) { From fde4f63e2e86c88bb56de4b3bfacf50c6abb734c Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Mon, 24 Jun 2024 16:07:15 +0330 Subject: [PATCH 045/132] pool, balances, getTokens added to the controller --- src/chains/ergo/ergo.controller.ts | 39 +++++++++++++++++++++++++++++- src/chains/ergo/ergo.requests.ts | 25 +++++++++++++++++++ src/chains/ergo/ergo.ts | 36 ++++++++++++++++++++++++++- 3 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 src/chains/ergo/ergo.requests.ts diff --git a/src/chains/ergo/ergo.controller.ts b/src/chains/ergo/ergo.controller.ts index 5f538edefb..c4b05a6aa4 100644 --- a/src/chains/ergo/ergo.controller.ts +++ b/src/chains/ergo/ergo.controller.ts @@ -1 +1,38 @@ -export class ErgoController {} +import { Ergo } from './ergo'; +import { + AssetsResponse, + BalanceRequest, + PoolRequest, + PoolResponse, +} from './ergo.requests'; + +export class ErgoController { + static async pool(ergo: Ergo, req: PoolRequest): Promise { + if (!ergo.ready) { + await ergo.init(); + } + return ergo.getPool(req.poolId).getPoolInfo; + } + + static async balances(chain: Ergo, request: BalanceRequest) { + if (!chain.ready) { + await chain.init(); + } + const utxos = await chain.getAddressUnspentBoxes(request.address); + const { balance, assets } = chain.getBalance(utxos); + + return { + balance, + assets, + }; + } + + static async getTokens(ergo: Ergo): Promise { + if (!ergo.ready) { + await ergo.init(); + } + return { + assets: ergo.storedAssetList, + }; + } +} diff --git a/src/chains/ergo/ergo.requests.ts b/src/chains/ergo/ergo.requests.ts new file mode 100644 index 0000000000..d27f1e8954 --- /dev/null +++ b/src/chains/ergo/ergo.requests.ts @@ -0,0 +1,25 @@ +import { AssetAmount } from '@patternglobal/ergo-sdk'; +import { NetworkSelectionRequest } from '../../services/common-interfaces'; +import { ErgoAsset } from './interfaces/ergo.interface'; + +export interface PoolRequest { + network: string; + poolId: string; +} + +export type PoolResponse = { + id: string; + lp: AssetAmount; + x: AssetAmount; + y: AssetAmount; + feeNum: bigint; + feeDenom: bigint; +}; + +export interface BalanceRequest extends NetworkSelectionRequest { + address: string; // the users public key +} + +export type AssetsResponse = { + assets: ErgoAsset[]; +}; diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 94c68de941..41ea367c21 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -62,10 +62,21 @@ class Pool extends AmmPool { this.name = `${this.x.asset.name}/${this.y.asset.name}`; } - public getName() { + public get getName() { return this.name; } + public get getPoolInfo() { + return { + id: this.id, + lp: this.lp, + x: this.x, + y: this.y, + feeNum: this.feeNum, + feeDenom: this.feeDenom, + }; + } + // calculatePriceImpact(input: any): number { // const ratio = // input.asset.id === this.x.asset.id @@ -466,6 +477,22 @@ export class Ergo { return balance.toString(); } + public getBalance(utxos: ErgoBox[]) { + const balance = utxos.reduce( + (total, box) => total + BigInt(box.value), + BigInt(0), + ); + const assets: Record = {}; + utxos.forEach((box) => { + box.assets.forEach((asset) => { + if (Object.keys(assets).includes(asset.tokenId)) + assets[asset.tokenId] += BigInt(asset.amount); + else assets[asset.tokenId] = BigInt(asset.amount); + }); + }); + return { balance, assets }; + } + private async loadAssets() { const assetData = await this.getAssetData(); @@ -513,6 +540,7 @@ export class Ergo { public get storedTokenList() { return this._assetMap; } + private async swap( account: ErgoAccount, pool: Pool, @@ -616,6 +644,7 @@ export class Ergo { const actions = poolActions(pool); return await actions.swap(swapParams, txContext); } + // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error private async buy( @@ -638,6 +667,7 @@ export class Ergo { false, ); } + // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error private async sell( @@ -660,6 +690,7 @@ export class Ergo { true, ); } + private async estimate( pool: Pool, amount: bigint, @@ -691,6 +722,7 @@ export class Ergo { }); return minOutput; } + // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error private async estimateBuy( @@ -700,6 +732,7 @@ export class Ergo { ): Promise { return await this.estimate(pool, y_amount, slippage, false); } + // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error private async estimateSell( @@ -709,6 +742,7 @@ export class Ergo { ): Promise { return await this.estimate(pool, x_amount, slippage, true); } + public getPool(id: string): Pool { return this.ammPools.find((ammPool) => ammPool.id === id); } From fbf9099da0ad88863284d33912d41a964df8b224 Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Mon, 24 Jun 2024 16:31:40 +0330 Subject: [PATCH 046/132] added transfer to controller --- package.json | 1 + src/chains/ergo/ergo.controller.ts | 20 ++++++++++++++++++++ src/chains/ergo/ergo.requests.ts | 9 ++++++++- src/chains/ergo/ergo.ts | 14 +++++++++----- src/chains/ergo/interfaces/ergo.interface.ts | 6 +++--- 5 files changed, 41 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 77378c1cf2..a6469a6f8f 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "@ethersproject/providers": "5.7.0", "@ethersproject/solidity": "5.7.0", "@fleet-sdk/common": "^0.3.4", + "@fleet-sdk/core": "^0.5.0", "@harmony-js/core": "^0.1.57", "@harmony-js/utils": "^0.1.56", "@improbable-eng/grpc-web": "^0.13.0", diff --git a/src/chains/ergo/ergo.controller.ts b/src/chains/ergo/ergo.controller.ts index c4b05a6aa4..d7d4af4583 100644 --- a/src/chains/ergo/ergo.controller.ts +++ b/src/chains/ergo/ergo.controller.ts @@ -4,7 +4,13 @@ import { BalanceRequest, PoolRequest, PoolResponse, + transferRequest, } from './ergo.requests'; +import { + ErgoUnsignedTransaction, + OutputBuilder, + TransactionBuilder, +} from '@fleet-sdk/core'; export class ErgoController { static async pool(ergo: Ergo, req: PoolRequest): Promise { @@ -35,4 +41,18 @@ export class ErgoController { assets: ergo.storedAssetList, }; } + + static async transfer( + ergo: Ergo, + req: transferRequest, + ): Promise { + const networkHeight = await ergo.getNetworkHeight(); + const utxos = await ergo.getAddressUnspentBoxes(req.fromAddress); + return new TransactionBuilder(networkHeight) + .from(utxos) + .to(new OutputBuilder(req.toValue, req.toAddress).addTokens(req.assets)) + .sendChangeTo(req.fromAddress) + .payMinFee() + .build(); + } } diff --git a/src/chains/ergo/ergo.requests.ts b/src/chains/ergo/ergo.requests.ts index d27f1e8954..39be942449 100644 --- a/src/chains/ergo/ergo.requests.ts +++ b/src/chains/ergo/ergo.requests.ts @@ -1,6 +1,6 @@ import { AssetAmount } from '@patternglobal/ergo-sdk'; import { NetworkSelectionRequest } from '../../services/common-interfaces'; -import { ErgoAsset } from './interfaces/ergo.interface'; +import { ErgoAsset, ErgoBoxAsset } from './interfaces/ergo.interface'; export interface PoolRequest { network: string; @@ -23,3 +23,10 @@ export interface BalanceRequest extends NetworkSelectionRequest { export type AssetsResponse = { assets: ErgoAsset[]; }; + +export type transferRequest = { + fromAddress: string; + toAddress: string; + assets: ErgoBoxAsset[]; + toValue: string; +}; diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 41ea367c21..6fe60366e6 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -265,6 +265,10 @@ export class Ergo { return this._ready; } + public async getNetworkHeight() { + return await this._node.getNetworkHeight(); + } + /** * This function initializes the Ergo class' instance * @returns @@ -452,21 +456,21 @@ export class Ergo { assetName: string, ): Promise { const ergoAsset = this._assetMap[assetName]; - let balance = 0; + let balance = BigInt(0); try { const utxos = await this.getAddressUnspentBoxes(account.address); balance = utxos.reduce( - (total: number, box) => + (total: bigint, box) => total + box.assets .filter((asset) => asset.tokenId === ergoAsset.tokenId.toString()) .reduce( - (total_asset, asset) => total_asset + Number(asset.amount), - 0, + (total_asset, asset) => total_asset + BigInt(asset.amount), + BigInt(0), ), - 0, + BigInt(0), ); } catch (error: any) { throw new Error( diff --git a/src/chains/ergo/interfaces/ergo.interface.ts b/src/chains/ergo/interfaces/ergo.interface.ts index 0944bbf378..1b46acec40 100644 --- a/src/chains/ergo/interfaces/ergo.interface.ts +++ b/src/chains/ergo/interfaces/ergo.interface.ts @@ -16,7 +16,7 @@ export interface ErgoNetworkConfig { defaultSlippage: number; defaultMinerFee: bigint; minNitro: number; - minBoxValue: bigint + minBoxValue: bigint; } export interface ErgoConfig { network: ErgoNetworkConfig; @@ -41,12 +41,12 @@ export interface ErgoConnectedInstance { export interface ErgoBoxAsset { tokenId: string; - amount: number; + amount: bigint; } export interface ErgoBox { boxId: string; - value: number; + value: bigint; ergoTree: string; creationHeight: number; assets: Array; From 873fc64d9f934a570e3891418d78591f9e234f63 Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Tue, 25 Jun 2024 18:48:52 +0330 Subject: [PATCH 047/132] solved #31 --- src/chains/ergo/ergo.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 865cb0990b..dd6eb60b20 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -487,7 +487,7 @@ export class Ergo { assetName: string, ): Promise { const ergoAsset = this._assetMap[assetName.toUpperCase()]; - let balance = 0; + let balance = BigInt(0); if (!ergoAsset) throw new Error(`assetName not found ${this._chain} Node!`); try { const utxos = await this.getAddressUnspentBoxes(account.address); From c2139ddfee880828458ca6b2e32f39e609505da0 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Wed, 26 Jun 2024 14:06:49 +0330 Subject: [PATCH 048/132] update [unit-test]: Update unit tests based on new changes --- test/chains/ergo/ergo.config.test.ts | 8 ++++ test/chains/ergo/ergo.test.ts | 57 ++++++++++++++------------- test/chains/ergo/node.service.test.ts | 6 +-- 3 files changed, 41 insertions(+), 30 deletions(-) diff --git a/test/chains/ergo/ergo.config.test.ts b/test/chains/ergo/ergo.config.test.ts index c58b1018f1..ab954d3330 100644 --- a/test/chains/ergo/ergo.config.test.ts +++ b/test/chains/ergo/ergo.config.test.ts @@ -37,6 +37,10 @@ describe('getErgoConfig', () => { maxLRUCacheInstances: 10, utxosLimit: 100, poolLimit: 100, + defaultSlippage: 3, + defaultMinerFee: BigInt(2_000_000), + minNitro: 1.2, + minBoxValue: BigInt(400_000), }, }); // Assert: Verify that the get method was called exactly five times with the expected arguments @@ -88,6 +92,10 @@ describe('getErgoConfig', () => { maxLRUCacheInstances: 10, utxosLimit: 100, poolLimit: 100, + defaultSlippage: 3, + defaultMinerFee: BigInt(2_000_000), + minNitro: 1.2, + minBoxValue: BigInt(400_000), }, }); // Assert: Verify that the get method was called exactly five times with the expected arguments diff --git a/test/chains/ergo/ergo.test.ts b/test/chains/ergo/ergo.test.ts index 08585af7e8..ac6219cb21 100644 --- a/test/chains/ergo/ergo.test.ts +++ b/test/chains/ergo/ergo.test.ts @@ -9,7 +9,7 @@ import { Ergo } from '../../../src/chains/ergo/ergo'; import { patch, unpatch } from '../../../test/services/patch'; import * as ergo_cofing from '../../../src/chains/ergo/ergo.config'; import { NodeService } from '../../../src/chains/ergo/node.service'; -import { Explorer } from '@ergolabs/ergo-sdk'; +import { Explorer } from '@patternglobal/ergo-sdk'; import { DexService } from '../../../src/chains/ergo/dex.service'; import { ErgoController } from '../../../src/chains/ergo/ergo.controller'; import { @@ -18,14 +18,17 @@ import { ErgoBox, } from '../../../src/chains/ergo/interfaces/ergo.interface'; import LRUCache from 'lru-cache'; -import { makeNativePools } from '@ergolabs/ergo-dex-sdk'; +import { makeNativePools } from '@patternglobal/ergo-dex-sdk'; -jest.mock('@ergolabs/ergo-dex-sdk', () => ({ +jest.mock('@patternglobal/ergo-dex-sdk', () => ({ AmmPool: jest.fn(), makeNativePools: jest.fn(), })); -jest.mock('@ergolabs/ergo-sdk', () => ({ +jest.mock('@patternglobal/ergo-sdk', () => ({ Explorer: jest.fn(), + RustModule: { + load: jest.fn().mockResolvedValue, + }, })); let ergo: Ergo; @@ -227,13 +230,13 @@ describe('Ergo', () => { describe('ready', () => { it('Should return the ready state', () => { // Arrange: Initially, the ready state should be false - expect(ergo.ready()).toBe(false); + expect(ergo.ready).toBe(false); // Act: Manually set the _ready state to true ergo['_ready'] = true; // Assert: Now, the ready state should be true - expect(ergo.ready()).toBe(true); + expect(ergo.ready).toBe(true); }); }); @@ -249,7 +252,7 @@ describe('Ergo', () => { // Assert: Ensure the loadAssets & loadPools methods were called during initialization expect(ergo['loadAssets']).toHaveBeenCalled(); expect(ergo['loadPools']).toHaveBeenCalled(); - expect(ergo.ready()).toBe(true); + expect(ergo.ready).toBe(true); }); }); @@ -300,9 +303,9 @@ describe('Ergo', () => { }); it('Should throw an error if an unexpected network is provided', () => { - // Act and Assert: Expect that calling getInstance with an empty string throws an error - expect(() => Ergo.getInstance('')).toThrow( - 'Ergo.getInstance received an unexpected network: .', + // Act and Assert: Expect that calling getInstance with an invalid network throws an error + expect(() => Ergo.getInstance('invalidNetwork')).toThrow( + 'network should be `Mainnet` or `Testnet`', ); }); }); @@ -313,15 +316,15 @@ describe('Ergo', () => { beforeEach(() => { // Arrange: Create mock Ergo instances - mockErgoInstance1 = new Ergo('Testnet1') as any; - mockErgoInstance2 = new Ergo('Testnet2') as any; + mockErgoInstance1 = new Ergo('Testnet') as any; + mockErgoInstance2 = new Ergo('Mainnet') as any; // Arrange: Initialize the _instances LRUCache with mock instances Ergo['_instances'] = new LRUCache({ max: 10, }); - Ergo['_instances'].set('Testnet1', mockErgoInstance1); - Ergo['_instances'].set('Testnet2', mockErgoInstance2); + Ergo['_instances'].set('Testnet', mockErgoInstance1); + Ergo['_instances'].set('Mainnet', mockErgoInstance2); }); it('Should return all connected instances', () => { @@ -330,11 +333,11 @@ describe('Ergo', () => { // Assert: Expect the connected instances to match the mock instances expect(Object.keys(connectedInstances).sort()).toEqual([ - 'Testnet1', - 'Testnet2', + 'Mainnet', + 'Testnet', ]); - expect(connectedInstances['Testnet1']).toBe(mockErgoInstance1); - expect(connectedInstances['Testnet2']).toBe(mockErgoInstance2); + expect(connectedInstances['Testnet']).toBe(mockErgoInstance1); + expect(connectedInstances['Mainnet']).toBe(mockErgoInstance2); }); it('Should return an empty object if there are no instances', () => { @@ -356,11 +359,11 @@ describe('Ergo', () => { const connectedInstances = Ergo.getConnectedInstances(); // Assert: Expect the valid instances to be returned and invalid instances to be excluded expect(Object.keys(connectedInstances).sort()).toEqual([ - 'Testnet1', - 'Testnet2', + 'Mainnet', + 'Testnet', ]); - expect(connectedInstances['Testnet1']).toBe(mockErgoInstance1); - expect(connectedInstances['Testnet2']).toBe(mockErgoInstance2); + expect(connectedInstances['Testnet']).toBe(mockErgoInstance1); + expect(connectedInstances['Mainnet']).toBe(mockErgoInstance2); expect(connectedInstances['']).toBeUndefined(); }); }); @@ -585,7 +588,7 @@ describe('Ergo', () => { // Arrange: Set up the account and asset map, and mock the getAddressUnspentBoxes method to return an empty array const account: ErgoAccount = { address: 'mockAddress' } as any; ergo['_assetMap'] = { - assetName: { tokenId: 1 }, + ASSETNAME: { tokenId: 1 }, } as any; patchGetAddressUnspentBoxes(); @@ -600,7 +603,7 @@ describe('Ergo', () => { // Arrange: Set up the account, asset map, and mock the getAddressUnspentBoxes method to return utxos without matching assets const account: ErgoAccount = { address: 'mockAddress' } as any; ergo['_assetMap'] = { - assetName: { tokenId: 1 }, + ASSETNAME: { tokenId: 1 }, } as any; const utxos = [{ assets: [{ tokenId: 2, amount: '100' }] }]; jest @@ -618,7 +621,7 @@ describe('Ergo', () => { // Arrange: Set up the account, asset map, and mock the getAddressUnspentBoxes method to return utxos with matching assets const account: ErgoAccount = { address: 'mockAddress' } as any; ergo['_assetMap'] = { - assetName: { tokenId: 1 }, + ASSETNAME: { tokenId: 1 }, } as any; const utxos = [ { assets: [{ tokenId: '1', amount: 100 }] }, @@ -644,7 +647,7 @@ describe('Ergo', () => { // Act & Assert: Call the getAssetBalance method and expect it to throw an error await expect(ergo.getAssetBalance(account, 'assetName')).rejects.toThrow( - 'problem during finding account assets ergo Node!', + `assetName not found ${ergo['_chain']} Node!`, ); }); }); @@ -793,7 +796,7 @@ describe('Ergo', () => { const result = await ergo['getPoolData'](limit, offset); // Assert: Verify the method returns expected data - expect(result).toEqual(expectedData); + expect(result).toEqual(expectedData[0]); }); it('Should handle errors from getAll method', async () => { diff --git a/test/chains/ergo/node.service.test.ts b/test/chains/ergo/node.service.test.ts index ec4e961592..60186a6813 100644 --- a/test/chains/ergo/node.service.test.ts +++ b/test/chains/ergo/node.service.test.ts @@ -25,7 +25,7 @@ describe('NodeService', () => { const method = 'GET'; const url = '/test-endpoint'; const headers = { 'Content-Type': 'application/json' }; - const body = { key: 'value' }; + const data = { key: 'value' }; it('Should make a GET request with correct parameters', async () => { // Arrange: Mock the axios response @@ -54,7 +54,7 @@ describe('NodeService', () => { (axios as any).mockResolvedValue(mockResponse); // Act: Call the private request method with POST parameters - const response = await nodeService['request'](method, url, headers, body); + const response = await nodeService['request'](method, url, headers, data); // Assert: Check if axios was called with the correct configuration expect(axios).toHaveBeenCalledWith({ @@ -63,7 +63,7 @@ describe('NodeService', () => { method, headers, timeout, - body, + data, }); // Assert: Check if the response is as expected expect(response).toEqual({ name: 'test' }); From 88503e102bb2fea8df3eea30b055a72370f21b45 Mon Sep 17 00:00:00 2001 From: ahmadyazdanii Date: Wed, 26 Jun 2024 15:40:45 +0330 Subject: [PATCH 049/132] update [ergo]: update config files --- src/chains/ergo/ergo.config.ts | 27 ++++++++++--------------- src/chains/ergo/ergo.ts | 30 ++++++++++++++-------------- src/chains/ergo/types/ergo.type.ts | 2 ++ src/services/schema/ergo-schema.json | 6 +++++- src/templates/ergo.yml | 13 ++++++------ 5 files changed, 39 insertions(+), 39 deletions(-) diff --git a/src/chains/ergo/ergo.config.ts b/src/chains/ergo/ergo.config.ts index e01c09e397..972e3ffc07 100644 --- a/src/chains/ergo/ergo.config.ts +++ b/src/chains/ergo/ergo.config.ts @@ -1,6 +1,7 @@ import { ConfigManagerV2 } from '../../services/config-manager-v2'; import { NetworkPrefix } from 'ergo-lib-wasm-nodejs'; import { ErgoConfig } from './interfaces/ergo.interface'; +import { ErgoNetwork } from './types/ergo.type'; /** * This function return configuration for Ergo @@ -8,27 +9,21 @@ import { ErgoConfig } from './interfaces/ergo.interface'; * @returns ErgoConfig * @function */ -export function getErgoConfig(network: string): ErgoConfig { +export function getErgoConfig(network: ErgoNetwork): ErgoConfig { + const configManager = ConfigManagerV2.getInstance(); + return { network: { name: network, - nodeURL: ConfigManagerV2.getInstance().get( - 'ergo.networks.' + network + '.nodeURL', - ), - explorerURL: ConfigManagerV2.getInstance().get( - 'ergo.networks.' + network + '.explorerURL', - ), - explorerDEXURL: ConfigManagerV2.getInstance().get( - 'ergo.networks.' + network + '.explorerDEXURL', - ), - timeOut: ConfigManagerV2.getInstance().get( - 'ergo.networks.' + network + '.timeOut', + nodeURL: configManager.get(`ergo.networks.${network}.nodeURL`), + explorerURL: configManager.get(`ergo.networks.${network}.explorerURL`), + explorerDEXURL: configManager.get( + `ergo.networks.${network}.explorerDEXURL`, ), + timeOut: configManager.get(`ergo.networks.${network}.timeOut`), networkPrefix: - network === 'Mainnet' ? NetworkPrefix.Mainnet : NetworkPrefix.Testnet, - minTxFee: ConfigManagerV2.getInstance().get( - 'ergo.networks.' + network + '.minTxFee', - ), + network === 'mainnet' ? NetworkPrefix.Mainnet : NetworkPrefix.Testnet, + minTxFee: configManager.get(`ergo.networks.${network}.minTxFee`), maxLRUCacheInstances: 10, utxosLimit: 100, poolLimit: 100, diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index dd6eb60b20..4c8d2e3d13 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -52,6 +52,7 @@ import { import { makeTarget } from '@patternglobal/ergo-dex-sdk/build/main/utils/makeTarget'; import { NativeExFeeType } from '@patternglobal/ergo-dex-sdk/build/main/types'; import { NetworkContext } from '@patternglobal/ergo-sdk/build/main/entities/networkContext'; +import { ErgoNetwork } from './types/ergo.type'; class Pool extends AmmPool { private name: string; @@ -212,7 +213,7 @@ export class Ergo { private _assetMap: Record = {}; private static _instances: LRUCache; private _chain: string = 'ergo'; - private _network: string; + private _network: ErgoNetwork; private _networkPrefix: NetworkPrefix; private _node: NodeService; private _explorer: Explorer; @@ -224,17 +225,14 @@ export class Ergo { private poolLimit: number; private ammPools: Array = []; - constructor(network: string) { - if (network !== 'Mainnet' && network !== 'Testnet') - throw new Error('network should be `Mainnet` or `Testnet`'); - const config = getErgoConfig(network); - - if (network === 'Mainnet') { - this._networkPrefix = NetworkPrefix.Mainnet; - } else { - this._networkPrefix = NetworkPrefix.Testnet; + constructor(network: ErgoNetwork) { + if (network !== 'mainnet' && network !== 'testnet') { + throw new Error('network should be `mainnet` or `testnet`'); } + const config = getErgoConfig(network); + + this._networkPrefix = config.network.networkPrefix; this._network = network; this._node = new NodeService( config.network.nodeURL, @@ -255,7 +253,7 @@ export class Ergo { return this._node; } - public get network(): string { + public get network(): ErgoNetwork { return this._network; } @@ -296,9 +294,11 @@ export class Ergo { * @function * @static */ - public static getInstance(network: string): Ergo { - if (network !== 'Mainnet' && network !== 'Testnet') - throw new Error('network should be `Mainnet` or `Testnet`'); + public static getInstance(network: ErgoNetwork): Ergo { + if (network !== 'mainnet' && network !== 'testnet') { + throw new Error('network should be `mainnet` or `testnet`'); + } + const config = getErgoConfig(network); if (!Ergo._instances) { @@ -599,7 +599,7 @@ export class Ergo { const config = getErgoConfig(this.network); const networkContext = await this._explorer.getNetworkContext(); const mainnetTxAssembler = new DefaultTxAssembler( - this.network === 'Mainnet', + this.network === 'mainnet', ); const poolActions = makeWrappedNativePoolActionsSelector( output_address, diff --git a/src/chains/ergo/types/ergo.type.ts b/src/chains/ergo/types/ergo.type.ts index fa808a6d7e..c3bf13c852 100644 --- a/src/chains/ergo/types/ergo.type.ts +++ b/src/chains/ergo/types/ergo.type.ts @@ -1,5 +1,7 @@ import { ErgoTreeHex, NonMandatoryRegisters } from '@fleet-sdk/common'; +export type ErgoNetwork = 'mainnet' | 'testnet'; + export type BoxType = { boxId: string; ergoTree: ErgoTreeHex; diff --git a/src/services/schema/ergo-schema.json b/src/services/schema/ergo-schema.json index f89f02a4d8..81807e0e5a 100644 --- a/src/services/schema/ergo-schema.json +++ b/src/services/schema/ergo-schema.json @@ -19,13 +19,17 @@ }, "timeOut": { "type": "number" + }, + "minTxFee": { + "type": "number" } }, "required": [ "nodeURL", "explorerURL", "explorerDEXURL", - "timeOut" + "timeOut", + "minTxFee" ], "additionalProperties": false } diff --git a/src/templates/ergo.yml b/src/templates/ergo.yml index e3d047e0ef..185c4a6382 100644 --- a/src/templates/ergo.yml +++ b/src/templates/ergo.yml @@ -1,8 +1,7 @@ networks: - networks: - Mainnet: - nodeURL: "http://213.239.193.208:9053/" - explorerURL: "https://api.ergoplatform.com/api/v1/" - explorerDEXURL: "https://spectrum.fi/" - timeOut: 30000 - minTxFee: 1000000 \ No newline at end of file + mainnet: + nodeURL: "http://213.239.193.208:9053/" + explorerURL: "https://api.ergoplatform.com/api/v1/" + explorerDEXURL: "https://spectrum.fi/" + timeOut: 30000 + minTxFee: 1000000 \ No newline at end of file From ebdbc43428d12ce50b03637ea4e8473c0b2c6499 Mon Sep 17 00:00:00 2001 From: ahmadyazdanii Date: Wed, 26 Jun 2024 15:58:04 +0330 Subject: [PATCH 050/132] update [ergo]: cleanup ergo requests interfaces --- src/chains/ergo/ergo.controller.ts | 17 +- .../requests.interface.ts} | 16 +- yarn.lock | 405 ++++++++++-------- 3 files changed, 240 insertions(+), 198 deletions(-) rename src/chains/ergo/{ergo.requests.ts => interfaces/requests.interface.ts} (64%) diff --git a/src/chains/ergo/ergo.controller.ts b/src/chains/ergo/ergo.controller.ts index d7d4af4583..6a0359c8b7 100644 --- a/src/chains/ergo/ergo.controller.ts +++ b/src/chains/ergo/ergo.controller.ts @@ -1,16 +1,17 @@ import { Ergo } from './ergo'; -import { - AssetsResponse, - BalanceRequest, - PoolRequest, - PoolResponse, - transferRequest, -} from './ergo.requests'; + import { ErgoUnsignedTransaction, OutputBuilder, TransactionBuilder, } from '@fleet-sdk/core'; +import { + AssetsResponse, + BalanceRequest, + PoolRequest, + PoolResponse, + TransferRequest, +} from './interfaces/requests.interface'; export class ErgoController { static async pool(ergo: Ergo, req: PoolRequest): Promise { @@ -44,7 +45,7 @@ export class ErgoController { static async transfer( ergo: Ergo, - req: transferRequest, + req: TransferRequest, ): Promise { const networkHeight = await ergo.getNetworkHeight(); const utxos = await ergo.getAddressUnspentBoxes(req.fromAddress); diff --git a/src/chains/ergo/ergo.requests.ts b/src/chains/ergo/interfaces/requests.interface.ts similarity index 64% rename from src/chains/ergo/ergo.requests.ts rename to src/chains/ergo/interfaces/requests.interface.ts index 39be942449..9c3974802e 100644 --- a/src/chains/ergo/ergo.requests.ts +++ b/src/chains/ergo/interfaces/requests.interface.ts @@ -1,32 +1,32 @@ import { AssetAmount } from '@patternglobal/ergo-sdk'; -import { NetworkSelectionRequest } from '../../services/common-interfaces'; -import { ErgoAsset, ErgoBoxAsset } from './interfaces/ergo.interface'; +import { NetworkSelectionRequest } from '../../../services/common-interfaces'; +import { ErgoAsset, ErgoBoxAsset } from './ergo.interface'; export interface PoolRequest { network: string; poolId: string; } -export type PoolResponse = { +export interface PoolResponse { id: string; lp: AssetAmount; x: AssetAmount; y: AssetAmount; feeNum: bigint; feeDenom: bigint; -}; +} export interface BalanceRequest extends NetworkSelectionRequest { address: string; // the users public key } -export type AssetsResponse = { +export interface AssetsResponse { assets: ErgoAsset[]; -}; +} -export type transferRequest = { +export interface TransferRequest { fromAddress: string; toAddress: string; assets: ErgoBoxAsset[]; toValue: string; -}; +} diff --git a/yarn.lock b/yarn.lock index 190cb61aa1..84c225de1f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1434,137 +1434,137 @@ "@ethersproject-xdc/abi@file:vendor/@ethersproject-xdc/abi": version "5.7.0" dependencies: - "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-c67b1b0a-7ad0-496e-9730-c3c08bf73ba7-1719153755507/node_modules/@ethersproject-xdc/address" - "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-c67b1b0a-7ad0-496e-9730-c3c08bf73ba7-1719153755507/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-c67b1b0a-7ad0-496e-9730-c3c08bf73ba7-1719153755507/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/constants" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-c67b1b0a-7ad0-496e-9730-c3c08bf73ba7-1719153755507/node_modules/@ethersproject-xdc/constants" - "@ethersproject-xdc/hash" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-c67b1b0a-7ad0-496e-9730-c3c08bf73ba7-1719153755507/node_modules/@ethersproject-xdc/hash" - "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-c67b1b0a-7ad0-496e-9730-c3c08bf73ba7-1719153755507/node_modules/@ethersproject-xdc/keccak256" - "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-c67b1b0a-7ad0-496e-9730-c3c08bf73ba7-1719153755507/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-c67b1b0a-7ad0-496e-9730-c3c08bf73ba7-1719153755507/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-c67b1b0a-7ad0-496e-9730-c3c08bf73ba7-1719153755507/node_modules/@ethersproject-xdc/strings" + "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-02f2dcec-bdd5-45e8-994b-418998d4e418-1719404148751/node_modules/@ethersproject-xdc/address" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-02f2dcec-bdd5-45e8-994b-418998d4e418-1719404148751/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-02f2dcec-bdd5-45e8-994b-418998d4e418-1719404148751/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/constants" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-02f2dcec-bdd5-45e8-994b-418998d4e418-1719404148751/node_modules/@ethersproject-xdc/constants" + "@ethersproject-xdc/hash" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-02f2dcec-bdd5-45e8-994b-418998d4e418-1719404148751/node_modules/@ethersproject-xdc/hash" + "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-02f2dcec-bdd5-45e8-994b-418998d4e418-1719404148751/node_modules/@ethersproject-xdc/keccak256" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-02f2dcec-bdd5-45e8-994b-418998d4e418-1719404148751/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-02f2dcec-bdd5-45e8-994b-418998d4e418-1719404148751/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abi-5.7.0-02f2dcec-bdd5-45e8-994b-418998d4e418-1719404148751/node_modules/@ethersproject-xdc/strings" "@ethersproject-xdc/abstract-provider@file:vendor/@ethersproject-xdc/abstract-provider": version "5.7.0" dependencies: - "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-b4386266-161c-49e8-ae5f-612280a914b1-1719153755505/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-b4386266-161c-49e8-ae5f-612280a914b1-1719153755505/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-b4386266-161c-49e8-ae5f-612280a914b1-1719153755505/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/networks" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-b4386266-161c-49e8-ae5f-612280a914b1-1719153755505/node_modules/@ethersproject-xdc/networks" - "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-b4386266-161c-49e8-ae5f-612280a914b1-1719153755505/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/transactions" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-b4386266-161c-49e8-ae5f-612280a914b1-1719153755505/node_modules/@ethersproject-xdc/transactions" - "@ethersproject-xdc/web" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-b4386266-161c-49e8-ae5f-612280a914b1-1719153755505/node_modules/@ethersproject-xdc/web" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-fa6e4c5e-9487-4a17-b9eb-b5c2f75aa597-1719404148753/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-fa6e4c5e-9487-4a17-b9eb-b5c2f75aa597-1719404148753/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-fa6e4c5e-9487-4a17-b9eb-b5c2f75aa597-1719404148753/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/networks" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-fa6e4c5e-9487-4a17-b9eb-b5c2f75aa597-1719404148753/node_modules/@ethersproject-xdc/networks" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-fa6e4c5e-9487-4a17-b9eb-b5c2f75aa597-1719404148753/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/transactions" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-fa6e4c5e-9487-4a17-b9eb-b5c2f75aa597-1719404148753/node_modules/@ethersproject-xdc/transactions" + "@ethersproject-xdc/web" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-provider-5.7.0-fa6e4c5e-9487-4a17-b9eb-b5c2f75aa597-1719404148753/node_modules/@ethersproject-xdc/web" "@ethersproject-xdc/abstract-signer@file:vendor/@ethersproject-xdc/abstract-signer": version "5.7.0" dependencies: - "@ethersproject-xdc/abstract-provider" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-signer-5.7.0-e4ff2f21-fb22-4045-b15d-6e30d3c8e42e-1719153755506/node_modules/@ethersproject-xdc/abstract-provider" - "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-signer-5.7.0-e4ff2f21-fb22-4045-b15d-6e30d3c8e42e-1719153755506/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-signer-5.7.0-e4ff2f21-fb22-4045-b15d-6e30d3c8e42e-1719153755506/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-signer-5.7.0-e4ff2f21-fb22-4045-b15d-6e30d3c8e42e-1719153755506/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-signer-5.7.0-e4ff2f21-fb22-4045-b15d-6e30d3c8e42e-1719153755506/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/abstract-provider" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-signer-5.7.0-6ed9bc73-0f31-4a0f-aeeb-d83e036ecb0c-1719404148754/node_modules/@ethersproject-xdc/abstract-provider" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-signer-5.7.0-6ed9bc73-0f31-4a0f-aeeb-d83e036ecb0c-1719404148754/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-signer-5.7.0-6ed9bc73-0f31-4a0f-aeeb-d83e036ecb0c-1719404148754/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-signer-5.7.0-6ed9bc73-0f31-4a0f-aeeb-d83e036ecb0c-1719404148754/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-abstract-signer-5.7.0-6ed9bc73-0f31-4a0f-aeeb-d83e036ecb0c-1719404148754/node_modules/@ethersproject-xdc/properties" "@ethersproject-xdc/address@file:vendor/@ethersproject-xdc/address": version "5.7.0" dependencies: - "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-address-5.7.0-2239aeab-37ee-49b1-9e78-2683b4b41226-1719153755508/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-address-5.7.0-2239aeab-37ee-49b1-9e78-2683b4b41226-1719153755508/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-address-5.7.0-2239aeab-37ee-49b1-9e78-2683b4b41226-1719153755508/node_modules/@ethersproject-xdc/keccak256" - "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-address-5.7.0-2239aeab-37ee-49b1-9e78-2683b4b41226-1719153755508/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/rlp" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-address-5.7.0-2239aeab-37ee-49b1-9e78-2683b4b41226-1719153755508/node_modules/@ethersproject-xdc/rlp" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-address-5.7.0-97329d1c-3a5c-4bdf-bfa0-b7085f53301e-1719404148753/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-address-5.7.0-97329d1c-3a5c-4bdf-bfa0-b7085f53301e-1719404148753/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-address-5.7.0-97329d1c-3a5c-4bdf-bfa0-b7085f53301e-1719404148753/node_modules/@ethersproject-xdc/keccak256" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-address-5.7.0-97329d1c-3a5c-4bdf-bfa0-b7085f53301e-1719404148753/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/rlp" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-address-5.7.0-97329d1c-3a5c-4bdf-bfa0-b7085f53301e-1719404148753/node_modules/@ethersproject-xdc/rlp" "@ethersproject-xdc/base64@file:vendor/@ethersproject-xdc/base64": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-base64-5.7.0-5d7118ad-448e-472d-890b-6643c76f8da1-1719153755506/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-base64-5.7.0-e4e6cc79-7ea7-4d31-bd73-99a7cc1cfa8d-1719404148751/node_modules/@ethersproject-xdc/bytes" "@ethersproject-xdc/basex@file:vendor/@ethersproject-xdc/basex": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-basex-5.7.0-d2d232e8-ad6f-4994-b12c-2dbd09ae9393-1719153755507/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-basex-5.7.0-d2d232e8-ad6f-4994-b12c-2dbd09ae9393-1719153755507/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-basex-5.7.0-9ea5dcab-26ef-43e8-b626-abd1902adf8f-1719404148752/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-basex-5.7.0-9ea5dcab-26ef-43e8-b626-abd1902adf8f-1719404148752/node_modules/@ethersproject-xdc/properties" "@ethersproject-xdc/bignumber@file:vendor/@ethersproject-xdc/bignumber": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-bignumber-5.7.0-5aa4ecb3-dc23-41d8-b6af-bf4d052cc72a-1719153755509/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-bignumber-5.7.0-5aa4ecb3-dc23-41d8-b6af-bf4d052cc72a-1719153755509/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-bignumber-5.7.0-a551d07e-9bfd-48ec-b8bf-c46ad2f1e4d6-1719404148752/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-bignumber-5.7.0-a551d07e-9bfd-48ec-b8bf-c46ad2f1e4d6-1719404148752/node_modules/@ethersproject-xdc/logger" bn.js "^5.2.1" "@ethersproject-xdc/bytes@file:vendor/@ethersproject-xdc/bytes": version "5.7.0" dependencies: - "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-bytes-5.7.0-76b2fa68-887e-4f3a-99a4-ead820f7e492-1719153755506/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-bytes-5.7.0-4030618c-8082-428e-86c1-f49c98a60e90-1719404148755/node_modules/@ethersproject-xdc/logger" "@ethersproject-xdc/constants@file:vendor/@ethersproject-xdc/constants": version "5.7.0" dependencies: - "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-constants-5.7.0-17c84972-a6c0-4bd8-8335-a3d4d127ee4b-1719153755507/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-constants-5.7.0-6a2cb365-44e3-4747-b128-2f0170174636-1719404148752/node_modules/@ethersproject-xdc/bignumber" "@ethersproject-xdc/contracts@file:vendor/@ethersproject-xdc/contracts": version "5.6.0" dependencies: - "@ethersproject-xdc/abi" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-78487f10-66d0-4607-8f7f-fd11ddd5c748-1719153755508/node_modules/@ethersproject-xdc/abi" - "@ethersproject-xdc/abstract-provider" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-78487f10-66d0-4607-8f7f-fd11ddd5c748-1719153755508/node_modules/@ethersproject-xdc/abstract-provider" - "@ethersproject-xdc/abstract-signer" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-78487f10-66d0-4607-8f7f-fd11ddd5c748-1719153755508/node_modules/@ethersproject-xdc/abstract-signer" - "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-78487f10-66d0-4607-8f7f-fd11ddd5c748-1719153755508/node_modules/@ethersproject-xdc/address" - "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-78487f10-66d0-4607-8f7f-fd11ddd5c748-1719153755508/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-78487f10-66d0-4607-8f7f-fd11ddd5c748-1719153755508/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/constants" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-78487f10-66d0-4607-8f7f-fd11ddd5c748-1719153755508/node_modules/@ethersproject-xdc/constants" - "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-78487f10-66d0-4607-8f7f-fd11ddd5c748-1719153755508/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-78487f10-66d0-4607-8f7f-fd11ddd5c748-1719153755508/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/transactions" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-78487f10-66d0-4607-8f7f-fd11ddd5c748-1719153755508/node_modules/@ethersproject-xdc/transactions" + "@ethersproject-xdc/abi" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-cd212524-6e29-455d-92e3-56ea56ef3d2e-1719404148757/node_modules/@ethersproject-xdc/abi" + "@ethersproject-xdc/abstract-provider" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-cd212524-6e29-455d-92e3-56ea56ef3d2e-1719404148757/node_modules/@ethersproject-xdc/abstract-provider" + "@ethersproject-xdc/abstract-signer" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-cd212524-6e29-455d-92e3-56ea56ef3d2e-1719404148757/node_modules/@ethersproject-xdc/abstract-signer" + "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-cd212524-6e29-455d-92e3-56ea56ef3d2e-1719404148757/node_modules/@ethersproject-xdc/address" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-cd212524-6e29-455d-92e3-56ea56ef3d2e-1719404148757/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-cd212524-6e29-455d-92e3-56ea56ef3d2e-1719404148757/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/constants" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-cd212524-6e29-455d-92e3-56ea56ef3d2e-1719404148757/node_modules/@ethersproject-xdc/constants" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-cd212524-6e29-455d-92e3-56ea56ef3d2e-1719404148757/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-cd212524-6e29-455d-92e3-56ea56ef3d2e-1719404148757/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/transactions" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-contracts-5.6.0-cd212524-6e29-455d-92e3-56ea56ef3d2e-1719404148757/node_modules/@ethersproject-xdc/transactions" "@ethersproject-xdc/hash@file:vendor/@ethersproject-xdc/hash": version "5.7.0" dependencies: - "@ethersproject-xdc/abstract-signer" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-9ccfe7f3-be05-4975-b2a7-61d9ef6f6fd2-1719153755509/node_modules/@ethersproject-xdc/abstract-signer" - "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-9ccfe7f3-be05-4975-b2a7-61d9ef6f6fd2-1719153755509/node_modules/@ethersproject-xdc/address" - "@ethersproject-xdc/base64" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-9ccfe7f3-be05-4975-b2a7-61d9ef6f6fd2-1719153755509/node_modules/@ethersproject-xdc/base64" - "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-9ccfe7f3-be05-4975-b2a7-61d9ef6f6fd2-1719153755509/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-9ccfe7f3-be05-4975-b2a7-61d9ef6f6fd2-1719153755509/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-9ccfe7f3-be05-4975-b2a7-61d9ef6f6fd2-1719153755509/node_modules/@ethersproject-xdc/keccak256" - "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-9ccfe7f3-be05-4975-b2a7-61d9ef6f6fd2-1719153755509/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-9ccfe7f3-be05-4975-b2a7-61d9ef6f6fd2-1719153755509/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-9ccfe7f3-be05-4975-b2a7-61d9ef6f6fd2-1719153755509/node_modules/@ethersproject-xdc/strings" + "@ethersproject-xdc/abstract-signer" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-ad38d659-d7df-4c0d-a80f-27c44f9cf872-1719404148757/node_modules/@ethersproject-xdc/abstract-signer" + "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-ad38d659-d7df-4c0d-a80f-27c44f9cf872-1719404148757/node_modules/@ethersproject-xdc/address" + "@ethersproject-xdc/base64" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-ad38d659-d7df-4c0d-a80f-27c44f9cf872-1719404148757/node_modules/@ethersproject-xdc/base64" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-ad38d659-d7df-4c0d-a80f-27c44f9cf872-1719404148757/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-ad38d659-d7df-4c0d-a80f-27c44f9cf872-1719404148757/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-ad38d659-d7df-4c0d-a80f-27c44f9cf872-1719404148757/node_modules/@ethersproject-xdc/keccak256" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-ad38d659-d7df-4c0d-a80f-27c44f9cf872-1719404148757/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-ad38d659-d7df-4c0d-a80f-27c44f9cf872-1719404148757/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hash-5.7.0-ad38d659-d7df-4c0d-a80f-27c44f9cf872-1719404148757/node_modules/@ethersproject-xdc/strings" "@ethersproject-xdc/hdnode@file:vendor/@ethersproject-xdc/hdnode": version "5.7.0" dependencies: - "@ethersproject-xdc/abstract-signer" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-3981ae87-a013-403b-a71b-c6ffdccc368b-1719153755510/node_modules/@ethersproject-xdc/abstract-signer" - "@ethersproject-xdc/basex" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-3981ae87-a013-403b-a71b-c6ffdccc368b-1719153755510/node_modules/@ethersproject-xdc/basex" - "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-3981ae87-a013-403b-a71b-c6ffdccc368b-1719153755510/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-3981ae87-a013-403b-a71b-c6ffdccc368b-1719153755510/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-3981ae87-a013-403b-a71b-c6ffdccc368b-1719153755510/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/pbkdf2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-3981ae87-a013-403b-a71b-c6ffdccc368b-1719153755510/node_modules/@ethersproject-xdc/pbkdf2" - "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-3981ae87-a013-403b-a71b-c6ffdccc368b-1719153755510/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/sha2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-3981ae87-a013-403b-a71b-c6ffdccc368b-1719153755510/node_modules/@ethersproject-xdc/sha2" - "@ethersproject-xdc/signing-key" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-3981ae87-a013-403b-a71b-c6ffdccc368b-1719153755510/node_modules/@ethersproject-xdc/signing-key" - "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-3981ae87-a013-403b-a71b-c6ffdccc368b-1719153755510/node_modules/@ethersproject-xdc/strings" - "@ethersproject-xdc/transactions" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-3981ae87-a013-403b-a71b-c6ffdccc368b-1719153755510/node_modules/@ethersproject-xdc/transactions" - "@ethersproject-xdc/wordlists" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-3981ae87-a013-403b-a71b-c6ffdccc368b-1719153755510/node_modules/@ethersproject-xdc/wordlists" + "@ethersproject-xdc/abstract-signer" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-8b669336-8f12-49b0-a904-2c6c55eede12-1719404148755/node_modules/@ethersproject-xdc/abstract-signer" + "@ethersproject-xdc/basex" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-8b669336-8f12-49b0-a904-2c6c55eede12-1719404148755/node_modules/@ethersproject-xdc/basex" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-8b669336-8f12-49b0-a904-2c6c55eede12-1719404148755/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-8b669336-8f12-49b0-a904-2c6c55eede12-1719404148755/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-8b669336-8f12-49b0-a904-2c6c55eede12-1719404148755/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/pbkdf2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-8b669336-8f12-49b0-a904-2c6c55eede12-1719404148755/node_modules/@ethersproject-xdc/pbkdf2" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-8b669336-8f12-49b0-a904-2c6c55eede12-1719404148755/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/sha2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-8b669336-8f12-49b0-a904-2c6c55eede12-1719404148755/node_modules/@ethersproject-xdc/sha2" + "@ethersproject-xdc/signing-key" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-8b669336-8f12-49b0-a904-2c6c55eede12-1719404148755/node_modules/@ethersproject-xdc/signing-key" + "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-8b669336-8f12-49b0-a904-2c6c55eede12-1719404148755/node_modules/@ethersproject-xdc/strings" + "@ethersproject-xdc/transactions" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-8b669336-8f12-49b0-a904-2c6c55eede12-1719404148755/node_modules/@ethersproject-xdc/transactions" + "@ethersproject-xdc/wordlists" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-hdnode-5.7.0-8b669336-8f12-49b0-a904-2c6c55eede12-1719404148755/node_modules/@ethersproject-xdc/wordlists" "@ethersproject-xdc/json-wallets@file:vendor/@ethersproject-xdc/json-wallets": version "5.6.0" dependencies: - "@ethersproject-xdc/abstract-signer" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-4576d561-d46f-4350-bac0-c1f350e7140f-1719153755511/node_modules/@ethersproject-xdc/abstract-signer" - "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-4576d561-d46f-4350-bac0-c1f350e7140f-1719153755511/node_modules/@ethersproject-xdc/address" - "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-4576d561-d46f-4350-bac0-c1f350e7140f-1719153755511/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/hdnode" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-4576d561-d46f-4350-bac0-c1f350e7140f-1719153755511/node_modules/@ethersproject-xdc/hdnode" - "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-4576d561-d46f-4350-bac0-c1f350e7140f-1719153755511/node_modules/@ethersproject-xdc/keccak256" - "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-4576d561-d46f-4350-bac0-c1f350e7140f-1719153755511/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/pbkdf2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-4576d561-d46f-4350-bac0-c1f350e7140f-1719153755511/node_modules/@ethersproject-xdc/pbkdf2" - "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-4576d561-d46f-4350-bac0-c1f350e7140f-1719153755511/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/random" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-4576d561-d46f-4350-bac0-c1f350e7140f-1719153755511/node_modules/@ethersproject-xdc/random" - "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-4576d561-d46f-4350-bac0-c1f350e7140f-1719153755511/node_modules/@ethersproject-xdc/strings" - "@ethersproject-xdc/transactions" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-4576d561-d46f-4350-bac0-c1f350e7140f-1719153755511/node_modules/@ethersproject-xdc/transactions" + "@ethersproject-xdc/abstract-signer" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-ed48e616-559e-40a9-a41c-e520a0d5ff74-1719404148760/node_modules/@ethersproject-xdc/abstract-signer" + "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-ed48e616-559e-40a9-a41c-e520a0d5ff74-1719404148760/node_modules/@ethersproject-xdc/address" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-ed48e616-559e-40a9-a41c-e520a0d5ff74-1719404148760/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/hdnode" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-ed48e616-559e-40a9-a41c-e520a0d5ff74-1719404148760/node_modules/@ethersproject-xdc/hdnode" + "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-ed48e616-559e-40a9-a41c-e520a0d5ff74-1719404148760/node_modules/@ethersproject-xdc/keccak256" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-ed48e616-559e-40a9-a41c-e520a0d5ff74-1719404148760/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/pbkdf2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-ed48e616-559e-40a9-a41c-e520a0d5ff74-1719404148760/node_modules/@ethersproject-xdc/pbkdf2" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-ed48e616-559e-40a9-a41c-e520a0d5ff74-1719404148760/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/random" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-ed48e616-559e-40a9-a41c-e520a0d5ff74-1719404148760/node_modules/@ethersproject-xdc/random" + "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-ed48e616-559e-40a9-a41c-e520a0d5ff74-1719404148760/node_modules/@ethersproject-xdc/strings" + "@ethersproject-xdc/transactions" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-json-wallets-5.6.0-ed48e616-559e-40a9-a41c-e520a0d5ff74-1719404148760/node_modules/@ethersproject-xdc/transactions" aes-js "3.0.0" scrypt-js "3.0.1" "@ethersproject-xdc/keccak256@file:vendor/@ethersproject-xdc/keccak256": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-keccak256-5.7.0-cb051885-95c1-4a94-bbf8-f8d04f04eee0-1719153755510/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-keccak256-5.7.0-e016d199-207c-40de-bd24-1039805b3619-1719404148752/node_modules/@ethersproject-xdc/bytes" js-sha3 "0.8.0" "@ethersproject-xdc/logger@file:vendor/@ethersproject-xdc/logger": @@ -1573,67 +1573,67 @@ "@ethersproject-xdc/networks@file:vendor/@ethersproject-xdc/networks": version "5.7.1" dependencies: - "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-networks-5.7.1-171acc93-ca9f-4a12-8843-d9288ca886de-1719153755511/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-networks-5.7.1-bbe951f7-2c84-4cf4-ac30-df7647be3712-1719404148754/node_modules/@ethersproject-xdc/logger" "@ethersproject-xdc/pbkdf2@file:vendor/@ethersproject-xdc/pbkdf2": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-pbkdf2-5.7.0-bf8578fb-58ad-4269-8b7b-6a257581a040-1719153755508/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/sha2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-pbkdf2-5.7.0-bf8578fb-58ad-4269-8b7b-6a257581a040-1719153755508/node_modules/@ethersproject-xdc/sha2" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-pbkdf2-5.7.0-a94f6fbe-3af4-47fe-b447-418128c5cd61-1719404148754/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/sha2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-pbkdf2-5.7.0-a94f6fbe-3af4-47fe-b447-418128c5cd61-1719404148754/node_modules/@ethersproject-xdc/sha2" "@ethersproject-xdc/properties@file:vendor/@ethersproject-xdc/properties": version "5.7.0" dependencies: - "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-properties-5.7.0-fa8f5a3d-d88b-46a2-b3f9-e089d9818508-1719153755510/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-properties-5.7.0-586f202f-68c2-4054-a9e9-370006d7f52c-1719404148759/node_modules/@ethersproject-xdc/logger" "@ethersproject-xdc/providers@file:vendor/@ethersproject-xdc/providers": version "5.6.2" dependencies: - "@ethersproject-xdc/abstract-provider" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/abstract-provider" - "@ethersproject-xdc/abstract-signer" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/abstract-signer" - "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/address" - "@ethersproject-xdc/basex" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/basex" - "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/constants" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/constants" - "@ethersproject-xdc/hash" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/hash" - "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/networks" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/networks" - "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/random" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/random" - "@ethersproject-xdc/rlp" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/rlp" - "@ethersproject-xdc/sha2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/sha2" - "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/strings" - "@ethersproject-xdc/transactions" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/transactions" - "@ethersproject-xdc/web" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-a756a105-6c5f-4a5c-94ce-2c800b95d094-1719153755513/node_modules/@ethersproject-xdc/web" + "@ethersproject-xdc/abstract-provider" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-4b0e35de-984a-4c9e-b8af-706844b102b0-1719404148758/node_modules/@ethersproject-xdc/abstract-provider" + "@ethersproject-xdc/abstract-signer" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-4b0e35de-984a-4c9e-b8af-706844b102b0-1719404148758/node_modules/@ethersproject-xdc/abstract-signer" + "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-4b0e35de-984a-4c9e-b8af-706844b102b0-1719404148758/node_modules/@ethersproject-xdc/address" + "@ethersproject-xdc/basex" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-4b0e35de-984a-4c9e-b8af-706844b102b0-1719404148758/node_modules/@ethersproject-xdc/basex" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-4b0e35de-984a-4c9e-b8af-706844b102b0-1719404148758/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-4b0e35de-984a-4c9e-b8af-706844b102b0-1719404148758/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/constants" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-4b0e35de-984a-4c9e-b8af-706844b102b0-1719404148758/node_modules/@ethersproject-xdc/constants" + "@ethersproject-xdc/hash" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-4b0e35de-984a-4c9e-b8af-706844b102b0-1719404148758/node_modules/@ethersproject-xdc/hash" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-4b0e35de-984a-4c9e-b8af-706844b102b0-1719404148758/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/networks" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-4b0e35de-984a-4c9e-b8af-706844b102b0-1719404148758/node_modules/@ethersproject-xdc/networks" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-4b0e35de-984a-4c9e-b8af-706844b102b0-1719404148758/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/random" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-4b0e35de-984a-4c9e-b8af-706844b102b0-1719404148758/node_modules/@ethersproject-xdc/random" + "@ethersproject-xdc/rlp" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-4b0e35de-984a-4c9e-b8af-706844b102b0-1719404148758/node_modules/@ethersproject-xdc/rlp" + "@ethersproject-xdc/sha2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-4b0e35de-984a-4c9e-b8af-706844b102b0-1719404148758/node_modules/@ethersproject-xdc/sha2" + "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-4b0e35de-984a-4c9e-b8af-706844b102b0-1719404148758/node_modules/@ethersproject-xdc/strings" + "@ethersproject-xdc/transactions" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-4b0e35de-984a-4c9e-b8af-706844b102b0-1719404148758/node_modules/@ethersproject-xdc/transactions" + "@ethersproject-xdc/web" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-providers-5.6.2-4b0e35de-984a-4c9e-b8af-706844b102b0-1719404148758/node_modules/@ethersproject-xdc/web" bech32 "1.1.4" ws "7.4.6" "@ethersproject-xdc/random@file:vendor/@ethersproject-xdc/random": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-random-5.7.0-70f5f413-6e0e-4de6-ab10-ab66c16998cc-1719153755509/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-random-5.7.0-70f5f413-6e0e-4de6-ab10-ab66c16998cc-1719153755509/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-random-5.7.0-6aa2f08d-1c74-4b87-8fac-6eef1bee584b-1719404148758/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-random-5.7.0-6aa2f08d-1c74-4b87-8fac-6eef1bee584b-1719404148758/node_modules/@ethersproject-xdc/logger" "@ethersproject-xdc/rlp@file:vendor/@ethersproject-xdc/rlp": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-rlp-5.7.0-e704c0fb-ff6e-480e-b9ca-3687e620559f-1719153755510/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-rlp-5.7.0-e704c0fb-ff6e-480e-b9ca-3687e620559f-1719153755510/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-rlp-5.7.0-0a6b7462-929c-4bda-bd4d-4626929d923e-1719404148756/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-rlp-5.7.0-0a6b7462-929c-4bda-bd4d-4626929d923e-1719404148756/node_modules/@ethersproject-xdc/logger" "@ethersproject-xdc/sha2@file:vendor/@ethersproject-xdc/sha2": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-sha2-5.7.0-f65c2a79-9ae7-4c25-8f9f-d63c95cff9fd-1719153755515/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-sha2-5.7.0-f65c2a79-9ae7-4c25-8f9f-d63c95cff9fd-1719153755515/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-sha2-5.7.0-886252a7-09a5-4b6f-b240-f50bc9292497-1719404148756/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-sha2-5.7.0-886252a7-09a5-4b6f-b240-f50bc9292497-1719404148756/node_modules/@ethersproject-xdc/logger" hash.js "1.1.7" "@ethersproject-xdc/signing-key@file:vendor/@ethersproject-xdc/signing-key": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-signing-key-5.7.0-44a763f8-7883-4c21-833a-8e22e8631ff7-1719153755515/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-signing-key-5.7.0-44a763f8-7883-4c21-833a-8e22e8631ff7-1719153755515/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-signing-key-5.7.0-44a763f8-7883-4c21-833a-8e22e8631ff7-1719153755515/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-signing-key-5.7.0-357c05d0-1544-4bec-a989-0233fe3a01f4-1719404148763/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-signing-key-5.7.0-357c05d0-1544-4bec-a989-0233fe3a01f4-1719404148763/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-signing-key-5.7.0-357c05d0-1544-4bec-a989-0233fe3a01f4-1719404148763/node_modules/@ethersproject-xdc/properties" bn.js "^5.2.1" elliptic "6.5.4" hash.js "1.1.7" @@ -1641,76 +1641,76 @@ "@ethersproject-xdc/solidity@file:vendor/@ethersproject-xdc/solidity": version "5.6.0" dependencies: - "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-solidity-5.6.0-9e516e38-2ffe-4712-9308-583e3643ccf8-1719153755511/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-solidity-5.6.0-9e516e38-2ffe-4712-9308-583e3643ccf8-1719153755511/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-solidity-5.6.0-9e516e38-2ffe-4712-9308-583e3643ccf8-1719153755511/node_modules/@ethersproject-xdc/keccak256" - "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-solidity-5.6.0-9e516e38-2ffe-4712-9308-583e3643ccf8-1719153755511/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/sha2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-solidity-5.6.0-9e516e38-2ffe-4712-9308-583e3643ccf8-1719153755511/node_modules/@ethersproject-xdc/sha2" - "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-solidity-5.6.0-9e516e38-2ffe-4712-9308-583e3643ccf8-1719153755511/node_modules/@ethersproject-xdc/strings" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-solidity-5.6.0-53041401-265c-4aaf-9308-8e4884df4a80-1719404148755/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-solidity-5.6.0-53041401-265c-4aaf-9308-8e4884df4a80-1719404148755/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-solidity-5.6.0-53041401-265c-4aaf-9308-8e4884df4a80-1719404148755/node_modules/@ethersproject-xdc/keccak256" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-solidity-5.6.0-53041401-265c-4aaf-9308-8e4884df4a80-1719404148755/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/sha2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-solidity-5.6.0-53041401-265c-4aaf-9308-8e4884df4a80-1719404148755/node_modules/@ethersproject-xdc/sha2" + "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-solidity-5.6.0-53041401-265c-4aaf-9308-8e4884df4a80-1719404148755/node_modules/@ethersproject-xdc/strings" "@ethersproject-xdc/strings@file:vendor/@ethersproject-xdc/strings": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-strings-5.7.0-6eaaabc3-473b-4a57-aa46-a8f421dcf49d-1719153755513/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/constants" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-strings-5.7.0-6eaaabc3-473b-4a57-aa46-a8f421dcf49d-1719153755513/node_modules/@ethersproject-xdc/constants" - "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-strings-5.7.0-6eaaabc3-473b-4a57-aa46-a8f421dcf49d-1719153755513/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-strings-5.7.0-6f578214-d7da-4e19-8170-a9f16d1fbd8c-1719404148760/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/constants" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-strings-5.7.0-6f578214-d7da-4e19-8170-a9f16d1fbd8c-1719404148760/node_modules/@ethersproject-xdc/constants" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-strings-5.7.0-6f578214-d7da-4e19-8170-a9f16d1fbd8c-1719404148760/node_modules/@ethersproject-xdc/logger" "@ethersproject-xdc/transactions@file:vendor/@ethersproject-xdc/transactions": version "5.7.0" dependencies: - "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-8aafcfdf-6ea6-444e-ac98-a592f462b294-1719153755512/node_modules/@ethersproject-xdc/address" - "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-8aafcfdf-6ea6-444e-ac98-a592f462b294-1719153755512/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-8aafcfdf-6ea6-444e-ac98-a592f462b294-1719153755512/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/constants" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-8aafcfdf-6ea6-444e-ac98-a592f462b294-1719153755512/node_modules/@ethersproject-xdc/constants" - "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-8aafcfdf-6ea6-444e-ac98-a592f462b294-1719153755512/node_modules/@ethersproject-xdc/keccak256" - "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-8aafcfdf-6ea6-444e-ac98-a592f462b294-1719153755512/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-8aafcfdf-6ea6-444e-ac98-a592f462b294-1719153755512/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/rlp" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-8aafcfdf-6ea6-444e-ac98-a592f462b294-1719153755512/node_modules/@ethersproject-xdc/rlp" - "@ethersproject-xdc/signing-key" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-8aafcfdf-6ea6-444e-ac98-a592f462b294-1719153755512/node_modules/@ethersproject-xdc/signing-key" + "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-c342b24a-8215-4772-b50b-a93444b48bf0-1719404148766/node_modules/@ethersproject-xdc/address" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-c342b24a-8215-4772-b50b-a93444b48bf0-1719404148766/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-c342b24a-8215-4772-b50b-a93444b48bf0-1719404148766/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/constants" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-c342b24a-8215-4772-b50b-a93444b48bf0-1719404148766/node_modules/@ethersproject-xdc/constants" + "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-c342b24a-8215-4772-b50b-a93444b48bf0-1719404148766/node_modules/@ethersproject-xdc/keccak256" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-c342b24a-8215-4772-b50b-a93444b48bf0-1719404148766/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-c342b24a-8215-4772-b50b-a93444b48bf0-1719404148766/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/rlp" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-c342b24a-8215-4772-b50b-a93444b48bf0-1719404148766/node_modules/@ethersproject-xdc/rlp" + "@ethersproject-xdc/signing-key" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-transactions-5.7.0-c342b24a-8215-4772-b50b-a93444b48bf0-1719404148766/node_modules/@ethersproject-xdc/signing-key" "@ethersproject-xdc/units@file:vendor/@ethersproject-xdc/units": version "5.6.0" dependencies: - "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-units-5.6.0-2b8286d8-0442-4926-9f41-259da9273a3b-1719153755512/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/constants" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-units-5.6.0-2b8286d8-0442-4926-9f41-259da9273a3b-1719153755512/node_modules/@ethersproject-xdc/constants" - "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-units-5.6.0-2b8286d8-0442-4926-9f41-259da9273a3b-1719153755512/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-units-5.6.0-ae86f3e6-4890-4981-971f-2f306ce37656-1719404148764/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/constants" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-units-5.6.0-ae86f3e6-4890-4981-971f-2f306ce37656-1719404148764/node_modules/@ethersproject-xdc/constants" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-units-5.6.0-ae86f3e6-4890-4981-971f-2f306ce37656-1719404148764/node_modules/@ethersproject-xdc/logger" "@ethersproject-xdc/wallet@file:vendor/@ethersproject-xdc/wallet": version "5.6.0" dependencies: - "@ethersproject-xdc/abstract-provider" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-086066b3-a620-4717-aa8f-ab6eb39a2d09-1719153755513/node_modules/@ethersproject-xdc/abstract-provider" - "@ethersproject-xdc/abstract-signer" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-086066b3-a620-4717-aa8f-ab6eb39a2d09-1719153755513/node_modules/@ethersproject-xdc/abstract-signer" - "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-086066b3-a620-4717-aa8f-ab6eb39a2d09-1719153755513/node_modules/@ethersproject-xdc/address" - "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-086066b3-a620-4717-aa8f-ab6eb39a2d09-1719153755513/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-086066b3-a620-4717-aa8f-ab6eb39a2d09-1719153755513/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/hash" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-086066b3-a620-4717-aa8f-ab6eb39a2d09-1719153755513/node_modules/@ethersproject-xdc/hash" - "@ethersproject-xdc/hdnode" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-086066b3-a620-4717-aa8f-ab6eb39a2d09-1719153755513/node_modules/@ethersproject-xdc/hdnode" - "@ethersproject-xdc/json-wallets" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-086066b3-a620-4717-aa8f-ab6eb39a2d09-1719153755513/node_modules/@ethersproject-xdc/json-wallets" - "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-086066b3-a620-4717-aa8f-ab6eb39a2d09-1719153755513/node_modules/@ethersproject-xdc/keccak256" - "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-086066b3-a620-4717-aa8f-ab6eb39a2d09-1719153755513/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-086066b3-a620-4717-aa8f-ab6eb39a2d09-1719153755513/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/random" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-086066b3-a620-4717-aa8f-ab6eb39a2d09-1719153755513/node_modules/@ethersproject-xdc/random" - "@ethersproject-xdc/signing-key" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-086066b3-a620-4717-aa8f-ab6eb39a2d09-1719153755513/node_modules/@ethersproject-xdc/signing-key" - "@ethersproject-xdc/transactions" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-086066b3-a620-4717-aa8f-ab6eb39a2d09-1719153755513/node_modules/@ethersproject-xdc/transactions" - "@ethersproject-xdc/wordlists" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-086066b3-a620-4717-aa8f-ab6eb39a2d09-1719153755513/node_modules/@ethersproject-xdc/wordlists" + "@ethersproject-xdc/abstract-provider" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-f9526617-6012-41ec-bcc4-248a8c4b346a-1719404148764/node_modules/@ethersproject-xdc/abstract-provider" + "@ethersproject-xdc/abstract-signer" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-f9526617-6012-41ec-bcc4-248a8c4b346a-1719404148764/node_modules/@ethersproject-xdc/abstract-signer" + "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-f9526617-6012-41ec-bcc4-248a8c4b346a-1719404148764/node_modules/@ethersproject-xdc/address" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-f9526617-6012-41ec-bcc4-248a8c4b346a-1719404148764/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-f9526617-6012-41ec-bcc4-248a8c4b346a-1719404148764/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/hash" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-f9526617-6012-41ec-bcc4-248a8c4b346a-1719404148764/node_modules/@ethersproject-xdc/hash" + "@ethersproject-xdc/hdnode" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-f9526617-6012-41ec-bcc4-248a8c4b346a-1719404148764/node_modules/@ethersproject-xdc/hdnode" + "@ethersproject-xdc/json-wallets" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-f9526617-6012-41ec-bcc4-248a8c4b346a-1719404148764/node_modules/@ethersproject-xdc/json-wallets" + "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-f9526617-6012-41ec-bcc4-248a8c4b346a-1719404148764/node_modules/@ethersproject-xdc/keccak256" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-f9526617-6012-41ec-bcc4-248a8c4b346a-1719404148764/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-f9526617-6012-41ec-bcc4-248a8c4b346a-1719404148764/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/random" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-f9526617-6012-41ec-bcc4-248a8c4b346a-1719404148764/node_modules/@ethersproject-xdc/random" + "@ethersproject-xdc/signing-key" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-f9526617-6012-41ec-bcc4-248a8c4b346a-1719404148764/node_modules/@ethersproject-xdc/signing-key" + "@ethersproject-xdc/transactions" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-f9526617-6012-41ec-bcc4-248a8c4b346a-1719404148764/node_modules/@ethersproject-xdc/transactions" + "@ethersproject-xdc/wordlists" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wallet-5.6.0-f9526617-6012-41ec-bcc4-248a8c4b346a-1719404148764/node_modules/@ethersproject-xdc/wordlists" "@ethersproject-xdc/web@file:vendor/@ethersproject-xdc/web": version "5.7.1" dependencies: - "@ethersproject-xdc/base64" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-web-5.7.1-e313826a-9d51-48ff-a1d5-8f4abfb2b3ac-1719153755514/node_modules/@ethersproject-xdc/base64" - "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-web-5.7.1-e313826a-9d51-48ff-a1d5-8f4abfb2b3ac-1719153755514/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-web-5.7.1-e313826a-9d51-48ff-a1d5-8f4abfb2b3ac-1719153755514/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-web-5.7.1-e313826a-9d51-48ff-a1d5-8f4abfb2b3ac-1719153755514/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-web-5.7.1-e313826a-9d51-48ff-a1d5-8f4abfb2b3ac-1719153755514/node_modules/@ethersproject-xdc/strings" + "@ethersproject-xdc/base64" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-web-5.7.1-c34fda47-e446-4799-a6b9-c4278e2d1f3e-1719404148759/node_modules/@ethersproject-xdc/base64" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-web-5.7.1-c34fda47-e446-4799-a6b9-c4278e2d1f3e-1719404148759/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-web-5.7.1-c34fda47-e446-4799-a6b9-c4278e2d1f3e-1719404148759/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-web-5.7.1-c34fda47-e446-4799-a6b9-c4278e2d1f3e-1719404148759/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-web-5.7.1-c34fda47-e446-4799-a6b9-c4278e2d1f3e-1719404148759/node_modules/@ethersproject-xdc/strings" "@ethersproject-xdc/wordlists@file:vendor/@ethersproject-xdc/wordlists": version "5.7.0" dependencies: - "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wordlists-5.7.0-9d6615b4-40a6-4a9b-a974-87598d611be3-1719153755514/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/hash" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wordlists-5.7.0-9d6615b4-40a6-4a9b-a974-87598d611be3-1719153755514/node_modules/@ethersproject-xdc/hash" - "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wordlists-5.7.0-9d6615b4-40a6-4a9b-a974-87598d611be3-1719153755514/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wordlists-5.7.0-9d6615b4-40a6-4a9b-a974-87598d611be3-1719153755514/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wordlists-5.7.0-9d6615b4-40a6-4a9b-a974-87598d611be3-1719153755514/node_modules/@ethersproject-xdc/strings" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wordlists-5.7.0-6d86c90a-d744-4914-bedf-adfb058e06c9-1719404148766/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/hash" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wordlists-5.7.0-6d86c90a-d744-4914-bedf-adfb058e06c9-1719404148766/node_modules/@ethersproject-xdc/hash" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wordlists-5.7.0-6d86c90a-d744-4914-bedf-adfb058e06c9-1719404148766/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wordlists-5.7.0-6d86c90a-d744-4914-bedf-adfb058e06c9-1719404148766/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-@ethersproject-xdc-wordlists-5.7.0-6d86c90a-d744-4914-bedf-adfb058e06c9-1719404148766/node_modules/@ethersproject-xdc/strings" "@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.0.12", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.4.0", "@ethersproject/abi@^5.5.0", "@ethersproject/abi@^5.6.3", "@ethersproject/abi@^5.7.0": version "5.7.0" @@ -2108,6 +2108,37 @@ resolved "https://registry.yarnpkg.com/@fleet-sdk/common/-/common-0.3.4.tgz#bd343ae03171b681444c51cc81e6a9021d660d1f" integrity sha512-FzrjElAy2hmxuXkFnTITGQKS7tsO9DIqyN7a1ki5T/REdTAHgZX3LseZUf0zuzjH21arez81kAnNYU+yBOJtRg== +"@fleet-sdk/common@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@fleet-sdk/common/-/common-0.4.1.tgz#491834de3ecdec24bced22d6a9a6e39702a3b465" + integrity sha512-jivyBz7kAye1FrS2gDlZkVpu7rrWAw1aySX+OkIWJA703P9BrrAEmBGU0jz4tKL+3LY2CsJhulOlpSAuc3/ivQ== + +"@fleet-sdk/core@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@fleet-sdk/core/-/core-0.5.0.tgz#bce8f4866937d76815520e49f4f0228a2f0010b8" + integrity sha512-uPWd3p4E+Feh1qXYe56WwSd98uB/bDzjziKOJWZBD1NJ2gd0F5TN+w9p31tp65xALAjZNRrztuslULCGbZOAZA== + dependencies: + "@fleet-sdk/common" "^0.4.1" + "@fleet-sdk/crypto" "^0.5.0" + "@fleet-sdk/serializer" "^0.5.0" + +"@fleet-sdk/crypto@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@fleet-sdk/crypto/-/crypto-0.5.0.tgz#28f799cea728ddf85449206b70eda22d947cc05a" + integrity sha512-ktfhO8r/SFYQfz3QcPWvRkvm5qZHLMT/zXXs4jVIbt7jQUSXvEX5f90YzO1n6eqs3G3xeb/fg0wMI5dYb4QXMA== + dependencies: + "@fleet-sdk/common" "^0.4.1" + "@noble/hashes" "^1.4.0" + "@scure/base" "^1.1.7" + +"@fleet-sdk/serializer@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@fleet-sdk/serializer/-/serializer-0.5.0.tgz#a935137f7c48e01c3c16c1b6b90eef7df1f62acc" + integrity sha512-pQsebhoJKhdmj9jZSh5pqwiVn/S+FkYdltdYDoWLTTR8x4zAxNyB4OORybnMojJTpjoUyEO+kK+LiA+7OrbpCg== + dependencies: + "@fleet-sdk/common" "^0.4.1" + "@fleet-sdk/crypto" "^0.5.0" + "@graphql-tools/batch-execute@8.5.1": version "8.5.1" resolved "https://registry.yarnpkg.com/@graphql-tools/batch-execute/-/batch-execute-8.5.1.tgz#fa3321d58c64041650be44250b1ebc3aab0ba7a9" @@ -2895,6 +2926,11 @@ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== +"@noble/hashes@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" + integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== + "@noble/secp256k1@1.7.1", "@noble/secp256k1@^1.6.3", "@noble/secp256k1@~1.7.0": version "1.7.1" resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c" @@ -3562,6 +3598,11 @@ debug "^3.1.0" hosted-git-info "^2.6.0" +"@scure/base@^1.1.7": + version "1.1.7" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.7.tgz#fe973311a5c6267846aa131bc72e96c5d40d2b30" + integrity sha512-PPNYBslrLNNUQ/Yad37MHYsNQtK67EhWb6WtSvNLLPo7SdVZgkUjD6Dg+5On7zNwmskf8OX7I7Nx5oN+MIWE0g== + "@scure/base@~1.1.0": version "1.1.1" resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938" @@ -8249,36 +8290,36 @@ ethereumjs-util@^6.0.0, ethereumjs-util@^6.2.1: "ethers-xdc@file:./vendor/ethers-xdc": version "5.7.2" dependencies: - "@ethersproject-xdc/abi" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/abi" - "@ethersproject-xdc/abstract-provider" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/abstract-provider" - "@ethersproject-xdc/abstract-signer" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/abstract-signer" - "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/address" - "@ethersproject-xdc/base64" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/base64" - "@ethersproject-xdc/basex" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/basex" - "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/bignumber" - "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/bytes" - "@ethersproject-xdc/constants" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/constants" - "@ethersproject-xdc/contracts" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/contracts" - "@ethersproject-xdc/hash" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/hash" - "@ethersproject-xdc/hdnode" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/hdnode" - "@ethersproject-xdc/json-wallets" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/json-wallets" - "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/keccak256" - "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/logger" - "@ethersproject-xdc/networks" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/networks" - "@ethersproject-xdc/pbkdf2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/pbkdf2" - "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/properties" - "@ethersproject-xdc/providers" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/providers" - "@ethersproject-xdc/random" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/random" - "@ethersproject-xdc/rlp" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/rlp" - "@ethersproject-xdc/sha2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/sha2" - "@ethersproject-xdc/signing-key" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/signing-key" - "@ethersproject-xdc/solidity" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/solidity" - "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/strings" - "@ethersproject-xdc/transactions" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/transactions" - "@ethersproject-xdc/units" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/units" - "@ethersproject-xdc/wallet" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/wallet" - "@ethersproject-xdc/web" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/web" - "@ethersproject-xdc/wordlists" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-c36500ad-1a46-48c4-ac41-56261fa4f9f5-1719153755498/node_modules/@ethersproject-xdc/wordlists" + "@ethersproject-xdc/abi" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-1e7f6d95-4e63-4e80-a532-e9c65f7f2017-1719404148740/node_modules/@ethersproject-xdc/abi" + "@ethersproject-xdc/abstract-provider" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-1e7f6d95-4e63-4e80-a532-e9c65f7f2017-1719404148740/node_modules/@ethersproject-xdc/abstract-provider" + "@ethersproject-xdc/abstract-signer" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-1e7f6d95-4e63-4e80-a532-e9c65f7f2017-1719404148740/node_modules/@ethersproject-xdc/abstract-signer" + "@ethersproject-xdc/address" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-1e7f6d95-4e63-4e80-a532-e9c65f7f2017-1719404148740/node_modules/@ethersproject-xdc/address" + "@ethersproject-xdc/base64" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-1e7f6d95-4e63-4e80-a532-e9c65f7f2017-1719404148740/node_modules/@ethersproject-xdc/base64" + "@ethersproject-xdc/basex" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-1e7f6d95-4e63-4e80-a532-e9c65f7f2017-1719404148740/node_modules/@ethersproject-xdc/basex" + "@ethersproject-xdc/bignumber" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-1e7f6d95-4e63-4e80-a532-e9c65f7f2017-1719404148740/node_modules/@ethersproject-xdc/bignumber" + "@ethersproject-xdc/bytes" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-1e7f6d95-4e63-4e80-a532-e9c65f7f2017-1719404148740/node_modules/@ethersproject-xdc/bytes" + "@ethersproject-xdc/constants" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-1e7f6d95-4e63-4e80-a532-e9c65f7f2017-1719404148740/node_modules/@ethersproject-xdc/constants" + "@ethersproject-xdc/contracts" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-1e7f6d95-4e63-4e80-a532-e9c65f7f2017-1719404148740/node_modules/@ethersproject-xdc/contracts" + "@ethersproject-xdc/hash" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-1e7f6d95-4e63-4e80-a532-e9c65f7f2017-1719404148740/node_modules/@ethersproject-xdc/hash" + "@ethersproject-xdc/hdnode" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-1e7f6d95-4e63-4e80-a532-e9c65f7f2017-1719404148740/node_modules/@ethersproject-xdc/hdnode" + "@ethersproject-xdc/json-wallets" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-1e7f6d95-4e63-4e80-a532-e9c65f7f2017-1719404148740/node_modules/@ethersproject-xdc/json-wallets" + "@ethersproject-xdc/keccak256" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-1e7f6d95-4e63-4e80-a532-e9c65f7f2017-1719404148740/node_modules/@ethersproject-xdc/keccak256" + "@ethersproject-xdc/logger" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-1e7f6d95-4e63-4e80-a532-e9c65f7f2017-1719404148740/node_modules/@ethersproject-xdc/logger" + "@ethersproject-xdc/networks" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-1e7f6d95-4e63-4e80-a532-e9c65f7f2017-1719404148740/node_modules/@ethersproject-xdc/networks" + "@ethersproject-xdc/pbkdf2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-1e7f6d95-4e63-4e80-a532-e9c65f7f2017-1719404148740/node_modules/@ethersproject-xdc/pbkdf2" + "@ethersproject-xdc/properties" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-1e7f6d95-4e63-4e80-a532-e9c65f7f2017-1719404148740/node_modules/@ethersproject-xdc/properties" + "@ethersproject-xdc/providers" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-1e7f6d95-4e63-4e80-a532-e9c65f7f2017-1719404148740/node_modules/@ethersproject-xdc/providers" + "@ethersproject-xdc/random" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-1e7f6d95-4e63-4e80-a532-e9c65f7f2017-1719404148740/node_modules/@ethersproject-xdc/random" + "@ethersproject-xdc/rlp" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-1e7f6d95-4e63-4e80-a532-e9c65f7f2017-1719404148740/node_modules/@ethersproject-xdc/rlp" + "@ethersproject-xdc/sha2" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-1e7f6d95-4e63-4e80-a532-e9c65f7f2017-1719404148740/node_modules/@ethersproject-xdc/sha2" + "@ethersproject-xdc/signing-key" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-1e7f6d95-4e63-4e80-a532-e9c65f7f2017-1719404148740/node_modules/@ethersproject-xdc/signing-key" + "@ethersproject-xdc/solidity" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-1e7f6d95-4e63-4e80-a532-e9c65f7f2017-1719404148740/node_modules/@ethersproject-xdc/solidity" + "@ethersproject-xdc/strings" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-1e7f6d95-4e63-4e80-a532-e9c65f7f2017-1719404148740/node_modules/@ethersproject-xdc/strings" + "@ethersproject-xdc/transactions" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-1e7f6d95-4e63-4e80-a532-e9c65f7f2017-1719404148740/node_modules/@ethersproject-xdc/transactions" + "@ethersproject-xdc/units" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-1e7f6d95-4e63-4e80-a532-e9c65f7f2017-1719404148740/node_modules/@ethersproject-xdc/units" + "@ethersproject-xdc/wallet" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-1e7f6d95-4e63-4e80-a532-e9c65f7f2017-1719404148740/node_modules/@ethersproject-xdc/wallet" + "@ethersproject-xdc/web" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-1e7f6d95-4e63-4e80-a532-e9c65f7f2017-1719404148740/node_modules/@ethersproject-xdc/web" + "@ethersproject-xdc/wordlists" "file:C:/Users/AhmadYazdani/AppData/Local/Yarn/Cache/v6/npm-ethers-xdc-5.7.2-1e7f6d95-4e63-4e80-a532-e9c65f7f2017-1719404148740/node_modules/@ethersproject-xdc/wordlists" ethers@4.0.0-beta.3: version "4.0.0-beta.3" From 7de6cf32955dcd8a29b1f2204b0af606388d1be4 Mon Sep 17 00:00:00 2001 From: ahmadyazdanii Date: Wed, 26 Jun 2024 16:25:01 +0330 Subject: [PATCH 051/132] update [ergo]: general cleanup --- src/chains/ergo/ergo.controller.ts | 6 +- src/chains/ergo/ergo.ts | 167 ++----------------- src/chains/ergo/ergo.util.ts | 81 +++++++++ src/chains/ergo/interfaces/ergo.interface.ts | 10 +- src/chains/ergo/wallet-prover.service.ts | 58 +++++++ 5 files changed, 169 insertions(+), 153 deletions(-) create mode 100644 src/chains/ergo/ergo.util.ts create mode 100644 src/chains/ergo/wallet-prover.service.ts diff --git a/src/chains/ergo/ergo.controller.ts b/src/chains/ergo/ergo.controller.ts index 6a0359c8b7..c87e3149c3 100644 --- a/src/chains/ergo/ergo.controller.ts +++ b/src/chains/ergo/ergo.controller.ts @@ -18,13 +18,15 @@ export class ErgoController { if (!ergo.ready) { await ergo.init(); } - return ergo.getPool(req.poolId).getPoolInfo; + + return ergo.getPool(req.poolId).info; } static async balances(chain: Ergo, request: BalanceRequest) { if (!chain.ready) { await chain.init(); } + const utxos = await chain.getAddressUnspentBoxes(request.address); const { balance, assets } = chain.getBalance(utxos); @@ -38,6 +40,7 @@ export class ErgoController { if (!ergo.ready) { await ergo.init(); } + return { assets: ergo.storedAssetList, }; @@ -49,6 +52,7 @@ export class ErgoController { ): Promise { const networkHeight = await ergo.getNetworkHeight(); const utxos = await ergo.getAddressUnspentBoxes(req.fromAddress); + return new TransactionBuilder(networkHeight) .from(utxos) .to(new OutputBuilder(req.toValue, req.toAddress).addTokens(req.assets)) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 4c8d2e3d13..7072ca9682 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -3,8 +3,6 @@ import { SecretKey, SecretKeys, Wallet, - ErgoBoxes, - UnsignedTransaction, Mnemonic, ExtSecretKey, DerivationPath, @@ -25,49 +23,39 @@ import { AmmPool, makeNativePools, makeWrappedNativePoolActionsSelector, - minValueForOrder, - minValueForSetup, SwapExtremums, SwapParams, swapVars, } from '@patternglobal/ergo-dex-sdk'; import { Explorer, - Prover, ErgoTx, - UnsignedErgoTx, - unsignedErgoTxToProxy, DefaultTxAssembler, AssetAmount, - MinBoxValue, - DefaultBoxSelector, - InsufficientInputs, publicKeyFromAddress, TransactionContext, - Address, - BoxSelection, - Input as TxInput, RustModule, } from '@patternglobal/ergo-sdk'; -import { makeTarget } from '@patternglobal/ergo-dex-sdk/build/main/utils/makeTarget'; import { NativeExFeeType } from '@patternglobal/ergo-dex-sdk/build/main/types'; import { NetworkContext } from '@patternglobal/ergo-sdk/build/main/entities/networkContext'; import { ErgoNetwork } from './types/ergo.type'; +import { getBaseInputParameters, getInputs, getTxContext } from './ergo.util'; +import { WalletProver } from './wallet-prover.service'; class Pool extends AmmPool { - private name: string; + private _name: string; constructor(public pool: AmmPool) { super(pool.id, pool.lp, pool.x, pool.y, pool.poolFeeNum); - this.name = `${this.x.asset.name}/${this.y.asset.name}`; + this._name = `${this.x.asset.name}/${this.y.asset.name}`; } - public get getName() { - return this.name; + public get name() { + return this._name; } - public get getPoolInfo() { + public get info() { return { id: this.id, lp: this.lp, @@ -77,136 +65,6 @@ class Pool extends AmmPool { feeDenom: this.feeDenom, }; } - - // calculatePriceImpact(input: any): number { - // const ratio = - // input.asset.id === this.x.asset.id - // ? math.evaluate!( - // `${renderFractions(this.y.amount.valueOf(), this.y.asset.decimals)} / ${renderFractions(this.x.amount.valueOf(), this.x.asset.decimals)}`, - // ).toString() - // : math.evaluate!( - // `${renderFractions(this.x.amount.valueOf(), this.x.asset.decimals)} / ${renderFractions(this.y.amount.valueOf(), this.y.asset.decimals)}`, - // ).toString(); - // const outputAmount = calculatePureOutputAmount(input, this); - // const outputRatio = math.evaluate!( - // `${outputAmount} / ${renderFractions(input.amount, input.asset.decimals)}`, - // ).toString(); - // - // return Math.abs( - // math.evaluate!(`(${outputRatio} * 100 / ${ratio}) - 100`).toFixed(2), - // ); - // } -} - -export type BaseInputParameters = { - baseInput: AssetAmount; - baseInputAmount: bigint; - minOutput: AssetAmount; -}; -export const getBaseInputParameters = ( - pool: AmmPool, - { inputAmount, slippage }: { inputAmount: any; slippage: number }, -): BaseInputParameters => { - const baseInputAmount = - inputAmount.asset.id === pool.x.asset.id - ? pool.x.withAmount(inputAmount.amount) - : pool.y.withAmount(inputAmount.amount); - const minOutput = pool.outputAmount(baseInputAmount as any, slippage); - - return { - baseInput: baseInputAmount as any, - baseInputAmount: inputAmount.amount, - minOutput: minOutput as any, - }; -}; -export const getInputs = ( - utxos: ErgoBox[], - assets: AssetAmount[], - fees: { minerFee: bigint; uiFee: bigint; exFee: bigint }, - minBoxValue: bigint, - ignoreMinBoxValue?: boolean, - setup?: boolean, -): BoxSelection => { - let minFeeForOrder = minValueForOrder(fees.minerFee, fees.uiFee, fees.exFee); - if (setup) { - minFeeForOrder = minValueForSetup(fees.minerFee, fees.uiFee); - } - if (ignoreMinBoxValue) { - minFeeForOrder -= MinBoxValue; - } - - const target = makeTarget(assets, minFeeForOrder); - - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - const inputs = DefaultBoxSelector.select(utxos, target, minBoxValue); - - if (inputs instanceof InsufficientInputs) { - throw new Error( - `Error in getInputs function: InsufficientInputs -> ${inputs}`, - ); - } - - return inputs; -}; -export const getTxContext = ( - inputs: BoxSelection, - network: NetworkContext, - address: Address, - minerFee: bigint, -): TransactionContext => ({ - inputs, - selfAddress: address, - changeAddress: address, - feeNErgs: minerFee, - network, -}); - -export class WalletProver implements Prover { - readonly wallet: Wallet; - readonly nodeService: NodeService; - - constructor(wallet: Wallet, nodeService: NodeService) { - this.wallet = wallet; - this.nodeService = nodeService; - } - - /** Sign the given transaction. - */ - async sign(tx: UnsignedErgoTx): Promise { - const ctx = await this.nodeService.getCtx(); - const proxy = unsignedErgoTxToProxy(tx); - const wasmtx = UnsignedTransaction.from_json(JSON.stringify(proxy)); - try { - return this.wallet - .sign_transaction( - ctx, - wasmtx, - ErgoBoxes.from_boxes_json(proxy.inputs), - ErgoBoxes.empty(), - ) - .to_js_eip12(); - } catch { - throw new Error('not be able to sign!'); - } - } - - async submit(tx: ErgoTx): Promise { - const txId = await this.nodeService.postTransaction(tx); - return { - ...tx, - id: txId, - }; - } - - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - // eslint-disable-next-line @typescript-eslint/no-unused-vars - signInput(tx: UnsignedErgoTx, input: number): Promise { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - return; - } } export class Ergo { @@ -517,6 +375,7 @@ export class Ergo { BigInt(0), ); const assets: Record = {}; + utxos.forEach((box) => { box.assets.forEach((asset) => { if (Object.keys(assets).includes(asset.tokenId)) @@ -524,6 +383,7 @@ export class Ergo { else assets[asset.tokenId] = BigInt(asset.amount); }); }); + return { balance, assets }; } @@ -547,6 +407,7 @@ export class Ergo { private async loadPools(): Promise { let offset = 0; let pools: Array = await this.getPoolData(this.poolLimit, offset); + while (pools.length > 0) { for (const pool of pools) { if (!this.ammPools.filter((ammPool) => ammPool.id === pool.id).length) { @@ -562,12 +423,14 @@ export class Ergo { public async loadPool(poolId: string): Promise { await RustModule.load(true); const pool = await this.getPool(poolId); - if (!pool) + + if (!pool) { this.ammPools.push( // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error new Pool(await makeNativePools(this._explorer).get(poolId)), ); + } } private async getPoolData(limit: number, offset: number): Promise { @@ -575,6 +438,7 @@ export class Ergo { limit, offset, }); + return AmmPool; } @@ -685,8 +549,8 @@ export class Ergo { return_address, config.network.defaultMinerFee, ); - const actions = poolActions(pool); + return await actions.swap(swapParams, txContext); } @@ -761,6 +625,7 @@ export class Ergo { inputAmount: from, slippage: slippage || config.network.defaultSlippage, }); + return minOutput; } diff --git a/src/chains/ergo/ergo.util.ts b/src/chains/ergo/ergo.util.ts new file mode 100644 index 0000000000..cdaf68d762 --- /dev/null +++ b/src/chains/ergo/ergo.util.ts @@ -0,0 +1,81 @@ +import { BaseInputParameters, ErgoBox } from './interfaces/ergo.interface'; +import { + AmmPool, + minValueForOrder, + minValueForSetup, +} from '@patternglobal/ergo-dex-sdk'; +import { + AssetAmount, + MinBoxValue, + DefaultBoxSelector, + InsufficientInputs, + TransactionContext, + Address, + BoxSelection, +} from '@patternglobal/ergo-sdk'; +import { makeTarget } from '@patternglobal/ergo-dex-sdk/build/main/utils/makeTarget'; +import { NetworkContext } from '@patternglobal/ergo-sdk/build/main/entities/networkContext'; + +export function getBaseInputParameters( + pool: AmmPool, + { inputAmount, slippage }: { inputAmount: any; slippage: number }, +): BaseInputParameters { + const baseInputAmount = + inputAmount.asset.id === pool.x.asset.id + ? pool.x.withAmount(inputAmount.amount) + : pool.y.withAmount(inputAmount.amount); + const minOutput = pool.outputAmount(baseInputAmount as any, slippage); + + return { + baseInput: baseInputAmount as any, + baseInputAmount: inputAmount.amount, + minOutput: minOutput as any, + }; +} + +export function getInputs( + utxos: ErgoBox[], + assets: AssetAmount[], + fees: { minerFee: bigint; uiFee: bigint; exFee: bigint }, + minBoxValue: bigint, + ignoreMinBoxValue?: boolean, + setup?: boolean, +): BoxSelection { + let minFeeForOrder = minValueForOrder(fees.minerFee, fees.uiFee, fees.exFee); + + if (setup) { + minFeeForOrder = minValueForSetup(fees.minerFee, fees.uiFee); + } + + if (ignoreMinBoxValue) { + minFeeForOrder -= MinBoxValue; + } + + const target = makeTarget(assets, minFeeForOrder); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + const inputs = DefaultBoxSelector.select(utxos, target, minBoxValue); + + if (inputs instanceof InsufficientInputs) { + throw new Error( + `Error in getInputs function: InsufficientInputs -> ${inputs}`, + ); + } + + return inputs; +} + +export function getTxContext( + inputs: BoxSelection, + network: NetworkContext, + address: Address, + minerFee: bigint, +): TransactionContext { + return { + inputs, + selfAddress: address, + changeAddress: address, + feeNErgs: minerFee, + network, + }; +} diff --git a/src/chains/ergo/interfaces/ergo.interface.ts b/src/chains/ergo/interfaces/ergo.interface.ts index 1b46acec40..d01cb9e36d 100644 --- a/src/chains/ergo/interfaces/ergo.interface.ts +++ b/src/chains/ergo/interfaces/ergo.interface.ts @@ -1,6 +1,8 @@ import { NetworkPrefix } from 'ergo-lib-wasm-nodejs'; import { Wallet } from 'ergo-lib-wasm-nodejs'; -import { Ergo, WalletProver } from '../ergo'; +import { Ergo } from '../ergo'; +import { AssetAmount } from '@patternglobal/ergo-sdk'; +import { WalletProver } from '../wallet-prover.service'; export interface ErgoNetworkConfig { name: string; @@ -61,3 +63,9 @@ export interface ErgoBox { inclusionHeight: number; globalIndex: number; } + +export interface BaseInputParameters { + baseInput: AssetAmount; + baseInputAmount: bigint; + minOutput: AssetAmount; +} diff --git a/src/chains/ergo/wallet-prover.service.ts b/src/chains/ergo/wallet-prover.service.ts new file mode 100644 index 0000000000..3ccf23d602 --- /dev/null +++ b/src/chains/ergo/wallet-prover.service.ts @@ -0,0 +1,58 @@ +import { Wallet, ErgoBoxes, UnsignedTransaction } from 'ergo-lib-wasm-nodejs'; +import { NodeService } from './node.service'; +import { + Prover, + ErgoTx, + UnsignedErgoTx, + unsignedErgoTxToProxy, + Input as TxInput, +} from '@patternglobal/ergo-sdk'; + +export class WalletProver implements Prover { + readonly wallet: Wallet; + readonly nodeService: NodeService; + + constructor(wallet: Wallet, nodeService: NodeService) { + this.wallet = wallet; + this.nodeService = nodeService; + } + + /** Sign the given transaction. + */ + async sign(tx: UnsignedErgoTx): Promise { + const ctx = await this.nodeService.getCtx(); + const proxy = unsignedErgoTxToProxy(tx); + const wasmtx = UnsignedTransaction.from_json(JSON.stringify(proxy)); + + try { + return this.wallet + .sign_transaction( + ctx, + wasmtx, + ErgoBoxes.from_boxes_json(proxy.inputs), + ErgoBoxes.empty(), + ) + .to_js_eip12(); + } catch { + throw new Error('not be able to sign!'); + } + } + + async submit(tx: ErgoTx): Promise { + const txId = await this.nodeService.postTransaction(tx); + + return { + ...tx, + id: txId, + }; + } + + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + // eslint-disable-next-line @typescript-eslint/no-unused-vars + signInput(tx: UnsignedErgoTx, input: number): Promise { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + return; + } +} From 9d3b1f618a005d324ce6a89e716f42f1bb072ab1 Mon Sep 17 00:00:00 2001 From: ahmadyazdanii Date: Wed, 26 Jun 2024 18:42:03 +0330 Subject: [PATCH 052/132] update [ergo]: connect ergo to the chain router --- src/chains/ergo/ergo.controller.ts | 6 ++++- src/chains/ergo/ergo.ts | 4 +++- src/chains/ergo/node.service.ts | 2 +- src/chains/ergo/types/ergo.type.ts | 2 +- src/network/network.controllers.ts | 38 +++++++++++++++++------------- src/services/connection-manager.ts | 10 ++++++-- src/templates/ergo.yml | 2 +- 7 files changed, 41 insertions(+), 23 deletions(-) diff --git a/src/chains/ergo/ergo.controller.ts b/src/chains/ergo/ergo.controller.ts index c87e3149c3..999690a04d 100644 --- a/src/chains/ergo/ergo.controller.ts +++ b/src/chains/ergo/ergo.controller.ts @@ -12,6 +12,7 @@ import { PoolResponse, TransferRequest, } from './interfaces/requests.interface'; +import { TokensRequest } from '../../network/network.requests'; export class ErgoController { static async pool(ergo: Ergo, req: PoolRequest): Promise { @@ -36,7 +37,10 @@ export class ErgoController { }; } - static async getTokens(ergo: Ergo): Promise { + static async getTokens( + ergo: Ergo, + _req: TokensRequest, + ): Promise { if (!ergo.ready) { await ergo.init(); } diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 7072ca9682..0eb9650c9a 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -116,10 +116,12 @@ export class Ergo { } public get storedAssetList(): Array { + console.log(this._assetMap); + return Object.values(this._assetMap); } - public get ready(): boolean { + public ready(): boolean { return this._ready; } diff --git a/src/chains/ergo/node.service.ts b/src/chains/ergo/node.service.ts index 18494f34d1..163f89b0b8 100644 --- a/src/chains/ergo/node.service.ts +++ b/src/chains/ergo/node.service.ts @@ -3,7 +3,7 @@ import { NodeChainSliceResponse, NodeInfoResponse, } from './interfaces/node.interface'; -import { NodeErgoBoxResponse, NodeErgoPostTxResponse } from "./types/node.type"; +import { NodeErgoBoxResponse, NodeErgoPostTxResponse } from './types/node.type'; import { BlockHeaders, ErgoStateContext, diff --git a/src/chains/ergo/types/ergo.type.ts b/src/chains/ergo/types/ergo.type.ts index c3bf13c852..f9e421fead 100644 --- a/src/chains/ergo/types/ergo.type.ts +++ b/src/chains/ergo/types/ergo.type.ts @@ -1,6 +1,6 @@ import { ErgoTreeHex, NonMandatoryRegisters } from '@fleet-sdk/common'; -export type ErgoNetwork = 'mainnet' | 'testnet'; +export type ErgoNetwork = string | 'mainnet' | 'testnet'; export type BoxType = { boxId: string; diff --git a/src/network/network.controllers.ts b/src/network/network.controllers.ts index bb4b165158..866f3c46fc 100644 --- a/src/network/network.controllers.ts +++ b/src/network/network.controllers.ts @@ -21,9 +21,10 @@ import { } from '../services/connection-manager'; import { Osmosis } from '../chains/osmosis/osmosis'; import { XRPL } from '../chains/xrpl/xrpl'; +import { Ergo } from '../chains/ergo/ergo'; export async function getStatus( - req: StatusRequest + req: StatusRequest, ): Promise { const statuses: StatusResponse[] = []; let connections: any[] = []; @@ -37,14 +38,14 @@ export async function getStatus( if (req.chain) { try { connections.push( - await getInitializedChain(req.chain, req.network as string) + await getInitializedChain(req.chain, req.network as string), ); } catch (e) { if (e instanceof UnsupportedChainException) { throw new HttpException( 500, UNKNOWN_KNOWN_CHAIN_ERROR_MESSAGE(req.chain), - UNKNOWN_CHAIN_ERROR_CODE + UNKNOWN_CHAIN_ERROR_CODE, ); } throw e; @@ -52,67 +53,72 @@ export async function getStatus( } else { const algorandConnections = Algorand.getConnectedInstances(); connections = connections.concat( - algorandConnections ? Object.values(algorandConnections) : [] + algorandConnections ? Object.values(algorandConnections) : [], ); const avalancheConnections = Avalanche.getConnectedInstances(); connections = connections.concat( - avalancheConnections ? Object.values(avalancheConnections) : [] + avalancheConnections ? Object.values(avalancheConnections) : [], ); const harmonyConnections = Harmony.getConnectedInstances(); connections = connections.concat( - harmonyConnections ? Object.values(harmonyConnections) : [] + harmonyConnections ? Object.values(harmonyConnections) : [], ); const ethereumConnections = Ethereum.getConnectedInstances(); connections = connections.concat( - ethereumConnections ? Object.values(ethereumConnections) : [] + ethereumConnections ? Object.values(ethereumConnections) : [], ); const polygonConnections = Polygon.getConnectedInstances(); connections = connections.concat( - polygonConnections ? Object.values(polygonConnections) : [] + polygonConnections ? Object.values(polygonConnections) : [], ); const xdcConnections = Xdc.getConnectedInstances(); connections = connections.concat( - xdcConnections ? Object.values(xdcConnections) : [] + xdcConnections ? Object.values(xdcConnections) : [], ); const cronosConnections = Cronos.getConnectedInstances(); connections = connections.concat( - cronosConnections ? Object.values(cronosConnections) : [] + cronosConnections ? Object.values(cronosConnections) : [], ); const nearConnections = Near.getConnectedInstances(); connections = connections.concat( - nearConnections ? Object.values(nearConnections) : [] + nearConnections ? Object.values(nearConnections) : [], ); const bscConnections = BinanceSmartChain.getConnectedInstances(); connections = connections.concat( - bscConnections ? Object.values(bscConnections) : [] + bscConnections ? Object.values(bscConnections) : [], ); const tezosConnections = Tezos.getConnectedInstances(); connections = connections.concat( - tezosConnections ? Object.values(tezosConnections) : [] + tezosConnections ? Object.values(tezosConnections) : [], ); const xrplConnections = XRPL.getConnectedInstances(); connections = connections.concat( - xrplConnections ? Object.values(xrplConnections) : [] + xrplConnections ? Object.values(xrplConnections) : [], ); const kujiraConnections = Kujira.getConnectedInstances(); connections = connections.concat( - kujiraConnections ? Object.values(kujiraConnections) : [] + kujiraConnections ? Object.values(kujiraConnections) : [], ); const osmosisConnections = Osmosis.getConnectedInstances(); connections = connections.concat( - osmosisConnections ? Object.values(osmosisConnections) : [] + osmosisConnections ? Object.values(osmosisConnections) : [], + ); + + const ergoConnections = Ergo.getConnectedInstances(); + connections = connections.concat( + ergoConnections ? Object.values(ergoConnections) : [], ); } diff --git a/src/services/connection-manager.ts b/src/services/connection-manager.ts index e2bd6d4866..eda66c699b 100644 --- a/src/services/connection-manager.ts +++ b/src/services/connection-manager.ts @@ -8,6 +8,7 @@ import { Xdc } from '../chains/xdc/xdc'; import { Tezos } from '../chains/tezos/tezos'; import { Osmosis } from '../chains/osmosis/osmosis'; import { XRPL, XRPLish } from '../chains/xrpl/xrpl'; +import { Ergo } from '../chains/ergo/ergo'; import { MadMeerkat } from '../connectors/mad_meerkat/mad_meerkat'; import { Openocean } from '../connectors/openocean/openocean'; import { Pangolin } from '../connectors/pangolin/pangolin'; @@ -55,7 +56,8 @@ export type ChainUnion = | Tezosish | XRPLish | Kujira - | Osmosis; + | Osmosis + | Ergo; export type Chain = T extends Algorand ? Algorand @@ -75,7 +77,9 @@ export type Chain = T extends Algorand ? KujiraCLOB : T extends Osmosis ? Osmosis - : never; + : T extends Ergo + ? Ergo + : never; export class UnsupportedChainException extends Error { constructor(message?: string) { @@ -140,6 +144,8 @@ export async function getChainInstance( connection = XRPL.getInstance(network); } else if (chain === 'kujira') { connection = Kujira.getInstance(network); + } else if (chain === 'ergo') { + connection = Ergo.getInstance(network); } else { connection = undefined; } diff --git a/src/templates/ergo.yml b/src/templates/ergo.yml index 185c4a6382..16a8fe0841 100644 --- a/src/templates/ergo.yml +++ b/src/templates/ergo.yml @@ -1,7 +1,7 @@ networks: mainnet: nodeURL: "http://213.239.193.208:9053/" - explorerURL: "https://api.ergoplatform.com/api/v1/" + explorerURL: "https://api.ergoplatform.com" explorerDEXURL: "https://spectrum.fi/" timeOut: 30000 minTxFee: 1000000 \ No newline at end of file From 5f510624d98e417755e6f7db9810c968e245df6a Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Wed, 26 Jun 2024 20:54:08 +0330 Subject: [PATCH 053/132] config file fixed --- src/chains/ergo/ergo.config.ts | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/chains/ergo/ergo.config.ts b/src/chains/ergo/ergo.config.ts index 972e3ffc07..15ecefec5b 100644 --- a/src/chains/ergo/ergo.config.ts +++ b/src/chains/ergo/ergo.config.ts @@ -24,13 +24,21 @@ export function getErgoConfig(network: ErgoNetwork): ErgoConfig { networkPrefix: network === 'mainnet' ? NetworkPrefix.Mainnet : NetworkPrefix.Testnet, minTxFee: configManager.get(`ergo.networks.${network}.minTxFee`), - maxLRUCacheInstances: 10, - utxosLimit: 100, - poolLimit: 100, - defaultSlippage: 3, - defaultMinerFee: BigInt(2_000_000), - minNitro: 1.2, - minBoxValue: BigInt(400_000), + maxLRUCacheInstances: configManager.get( + `ergo.networks.${network}.maxLRUCacheInstances`, + ), + utxosLimit: configManager.get(`ergo.networks.${network}.utxosLimit`), + poolLimit: configManager.get(`ergo.networks.${network}.poolLimit`), + defaultSlippage: configManager.get( + `ergo.networks.${network}.defaultSlippage`, + ), + defaultMinerFee: BigInt( + configManager.get(`ergo.networks.${network}.defaultMinerFee`), + ), + minNitro: configManager.get(`ergo.networks.${network}.minNitro`), + minBoxValue: BigInt( + configManager.get(`ergo.networks.${network}.minBoxValue`), + ), }, }; } From aed07713b51639e768297ce8806b0d3994ecca27 Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Wed, 26 Jun 2024 21:10:05 +0330 Subject: [PATCH 054/132] poll added to controller --- src/chains/ergo/ergo.controller.ts | 8 ++++++++ src/chains/ergo/ergo.ts | 4 ++++ src/chains/ergo/interfaces/requests.interface.ts | 7 ++++++- src/chains/ergo/node.service.ts | 4 ++++ 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/chains/ergo/ergo.controller.ts b/src/chains/ergo/ergo.controller.ts index 999690a04d..77ee4f7c82 100644 --- a/src/chains/ergo/ergo.controller.ts +++ b/src/chains/ergo/ergo.controller.ts @@ -8,6 +8,8 @@ import { import { AssetsResponse, BalanceRequest, + PollRequest, + PollResponse, PoolRequest, PoolResponse, TransferRequest, @@ -22,7 +24,13 @@ export class ErgoController { return ergo.getPool(req.poolId).info; } + static async poll(ergo: Ergo, req: PollRequest): Promise { + if (!ergo.ready) { + await ergo.init(); + } + return await ergo.getTx(req.txId); + } static async balances(chain: Ergo, request: BalanceRequest) { if (!chain.ready) { await chain.init(); diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 0eb9650c9a..30d8d50faf 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -650,4 +650,8 @@ export class Ergo { public getPool(id: string): Pool { return this.ammPools.find((ammPool) => ammPool.id === id); } + + public async getTx(id: string): Promise { + return await this._node.getTxsById(id); + } } diff --git a/src/chains/ergo/interfaces/requests.interface.ts b/src/chains/ergo/interfaces/requests.interface.ts index 9c3974802e..77c0625e78 100644 --- a/src/chains/ergo/interfaces/requests.interface.ts +++ b/src/chains/ergo/interfaces/requests.interface.ts @@ -1,4 +1,4 @@ -import { AssetAmount } from '@patternglobal/ergo-sdk'; +import { AssetAmount, ErgoTx } from '@patternglobal/ergo-sdk'; import { NetworkSelectionRequest } from '../../../services/common-interfaces'; import { ErgoAsset, ErgoBoxAsset } from './ergo.interface'; @@ -16,6 +16,11 @@ export interface PoolResponse { feeDenom: bigint; } +export interface PollResponse extends ErgoTx {} +export interface PollRequest { + txId: string; +} + export interface BalanceRequest extends NetworkSelectionRequest { address: string; // the users public key } diff --git a/src/chains/ergo/node.service.ts b/src/chains/ergo/node.service.ts index 163f89b0b8..a02af4522e 100644 --- a/src/chains/ergo/node.service.ts +++ b/src/chains/ergo/node.service.ts @@ -9,6 +9,7 @@ import { ErgoStateContext, PreHeader, } from 'ergo-lib-wasm-nodejs'; +import { ErgoTx } from '@patternglobal/ergo-sdk'; /** * This class allows you to access elements of a node @@ -102,4 +103,7 @@ export class NodeService { tx, ); } + async getTxsById(id: string): Promise { + return this.request('GET', `/blockchain/transaction/byId/${id}`); + } } From 60c8f4e903d6ce4191d2dc92b46d9beb55ee5f85 Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Thu, 27 Jun 2024 16:36:31 +0330 Subject: [PATCH 055/132] config file fixed --- src/services/schema/ergo-schema.json | 30 +++++++++++++++++++++++++++- src/templates/ergo.yml | 9 ++++++++- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/services/schema/ergo-schema.json b/src/services/schema/ergo-schema.json index 81807e0e5a..7893f8ceb6 100644 --- a/src/services/schema/ergo-schema.json +++ b/src/services/schema/ergo-schema.json @@ -22,6 +22,27 @@ }, "minTxFee": { "type": "number" + }, + "maxLRUCacheInstances": { + "type": "number" + }, + "utxosLimit": { + "type": "number" + }, + "poolLimit": { + "type": "number" + }, + "defaultSlippage": { + "type": "number" + }, + "defaultMinerFee": { + "type": "number" + }, + "minNitro": { + "type": "number" + }, + "minBoxValue": { + "type": "number" } }, "required": [ @@ -29,7 +50,14 @@ "explorerURL", "explorerDEXURL", "timeOut", - "minTxFee" + "minTxFee", + "maxLRUCacheInstances", + "utxosLimit", + "poolLimit", + "defaultSlippage", + "defaultMinerFee", + "minNitro", + "minBoxValue" ], "additionalProperties": false } diff --git a/src/templates/ergo.yml b/src/templates/ergo.yml index 16a8fe0841..c4a83dc0f6 100644 --- a/src/templates/ergo.yml +++ b/src/templates/ergo.yml @@ -4,4 +4,11 @@ networks: explorerURL: "https://api.ergoplatform.com" explorerDEXURL: "https://spectrum.fi/" timeOut: 30000 - minTxFee: 1000000 \ No newline at end of file + minTxFee: 1000000 + maxLRUCacheInstances: 10 + utxosLimit: 100 + poolLimit: 100 + defaultSlippage: 3 + defaultMinerFee: 2000000 + minNitro: 1.2 + minBoxValue: 400000 From 14acaeaab4ac47047de3dd0939bda7bc436a0afc Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Thu, 27 Jun 2024 17:27:55 +0330 Subject: [PATCH 056/132] swap gets 1 amount instead of 2 --- src/chains/ergo/ergo.ts | 24 +++++++++--------------- src/chains/ergo/ergo.util.ts | 6 +----- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 30d8d50faf..4f8690e810 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -455,8 +455,7 @@ export class Ergo { private async swap( account: ErgoAccount, pool: Pool, - x_amount: bigint, - y_amount: bigint, + amount: bigint, output_address: string, return_address: string, slippage: number, @@ -478,13 +477,13 @@ export class Ergo { id: sell ? pool.x.asset.id : pool.y.asset.id, decimals: sell ? pool.x.asset.decimals : pool.y.asset.decimals, }, - amount: sell ? x_amount : y_amount, + amount: amount, }; const max_to = { asset: { id: sell ? pool.x.asset.id : pool.y.asset.id, }, - amount: sell ? x_amount : y_amount, + amount: amount, }; const from = { asset: { @@ -527,10 +526,9 @@ export class Ergo { [new AssetAmount(from.asset, baseInputAmount)], { minerFee: config.network.defaultMinerFee, - uiFee: BigInt(sell ? y_amount : x_amount), + uiFee: BigInt(0), exFee: extremum.maxExFee, }, - config.network.minBoxValue, ); const swapParams: SwapParams = { poolId: pool.id, @@ -540,7 +538,7 @@ export class Ergo { baseInput, minQuoteOutput: extremum.minOutput.amount, exFeePerToken, - uiFee: BigInt(sell ? y_amount : x_amount), + uiFee: BigInt(0), quoteAsset: to.asset.id, poolFeeNum: pool.poolFeeNum, maxExFee: extremum.maxExFee, @@ -559,8 +557,7 @@ export class Ergo { public async buy( account: ErgoAccount, pool: Pool, - x_amount: bigint, - y_amount: bigint, + amount: bigint, output_address: string, return_address: string, slippage: number, @@ -568,8 +565,7 @@ export class Ergo { return await this.swap( account, pool, - x_amount, - y_amount, + amount, output_address, return_address, slippage, @@ -580,8 +576,7 @@ export class Ergo { public async sell( account: ErgoAccount, pool: Pool, - x_amount: bigint, - y_amount: bigint, + amount: bigint, output_address: string, return_address: string, slippage: number, @@ -589,8 +584,7 @@ export class Ergo { return await this.swap( account, pool, - x_amount, - y_amount, + amount, output_address, return_address, slippage, diff --git a/src/chains/ergo/ergo.util.ts b/src/chains/ergo/ergo.util.ts index cdaf68d762..334cc3001d 100644 --- a/src/chains/ergo/ergo.util.ts +++ b/src/chains/ergo/ergo.util.ts @@ -37,7 +37,6 @@ export function getInputs( utxos: ErgoBox[], assets: AssetAmount[], fees: { minerFee: bigint; uiFee: bigint; exFee: bigint }, - minBoxValue: bigint, ignoreMinBoxValue?: boolean, setup?: boolean, ): BoxSelection { @@ -52,10 +51,7 @@ export function getInputs( } const target = makeTarget(assets, minFeeForOrder); - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - const inputs = DefaultBoxSelector.select(utxos, target, minBoxValue); - + const inputs = DefaultBoxSelector.select(utxos, target); if (inputs instanceof InsufficientInputs) { throw new Error( `Error in getInputs function: InsufficientInputs -> ${inputs}`, From e31473dbfc4416dde835ea79b5f434791816d4c7 Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Thu, 27 Jun 2024 18:40:09 +0330 Subject: [PATCH 057/132] swap gets 1 amount instead of 2 --- src/chains/ergo/ergo.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 4f8690e810..aa875badee 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -526,7 +526,7 @@ export class Ergo { [new AssetAmount(from.asset, baseInputAmount)], { minerFee: config.network.defaultMinerFee, - uiFee: BigInt(0), + uiFee: config.network.defaultMinerFee, exFee: extremum.maxExFee, }, ); @@ -538,7 +538,7 @@ export class Ergo { baseInput, minQuoteOutput: extremum.minOutput.amount, exFeePerToken, - uiFee: BigInt(0), + uiFee: config.network.defaultMinerFee, quoteAsset: to.asset.id, poolFeeNum: pool.poolFeeNum, maxExFee: extremum.maxExFee, From bff0e332e578a1e6f75a815c4e390b7e9c57fe72 Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Thu, 27 Jun 2024 22:19:26 +0330 Subject: [PATCH 058/132] tslint errors fixed --- src/chains/ergo/ergo.ts | 26 +++++++++----------------- src/chains/ergo/ergo.util.ts | 1 - 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index aa875badee..3d5e693baf 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -116,8 +116,6 @@ export class Ergo { } public get storedAssetList(): Array { - console.log(this._assetMap); - return Object.values(this._assetMap); } @@ -427,11 +425,10 @@ export class Ergo { const pool = await this.getPool(poolId); if (!pool) { - this.ammPools.push( - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - new Pool(await makeNativePools(this._explorer).get(poolId)), - ); + const new_pool = await makeNativePools(this._explorer).get(poolId); + if (!new_pool) + throw new Error(`can not get pool with this id: ${poolId}`); + this.ammPools.push(new Pool(pool)); } } @@ -503,14 +500,11 @@ export class Ergo { }, ); const swapVariables: [number, SwapExtremums] | undefined = swapVars( - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - config.network.defaultMinerFee * 3n, + config.network.defaultMinerFee * BigInt(3), config.network.minNitro, minOutput, ); - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error + if (!swapVariables) throw new Error('error in swap vars!'); const [exFeePerToken, extremum] = swapVariables; const inputs = getInputs( utxos.map((utxo) => { @@ -530,11 +524,11 @@ export class Ergo { exFee: extremum.maxExFee, }, ); + const pk = publicKeyFromAddress(output_address); + if (!pk) throw new Error(`output_address is not defined.`); const swapParams: SwapParams = { poolId: pool.id, - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - pk: publicKeyFromAddress(output_address), + pk, baseInput, minQuoteOutput: extremum.minOutput.amount, exFeePerToken, @@ -603,8 +597,6 @@ export class Ergo { asset: { id: sell ? pool.x.asset.id : pool.y.asset.id, }, - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore amount, }; const from = { diff --git a/src/chains/ergo/ergo.util.ts b/src/chains/ergo/ergo.util.ts index 334cc3001d..81b6d24805 100644 --- a/src/chains/ergo/ergo.util.ts +++ b/src/chains/ergo/ergo.util.ts @@ -25,7 +25,6 @@ export function getBaseInputParameters( ? pool.x.withAmount(inputAmount.amount) : pool.y.withAmount(inputAmount.amount); const minOutput = pool.outputAmount(baseInputAmount as any, slippage); - return { baseInput: baseInputAmount as any, baseInputAmount: inputAmount.amount, From 0679c7ae722b9900047bef192a01af1db6827b36 Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Thu, 27 Jun 2024 22:26:00 +0330 Subject: [PATCH 059/132] tslint errors fixed --- src/chains/ergo/ergo.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 3d5e693baf..5d1b0e5151 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -492,6 +492,8 @@ export class Ergo { slippage || config.network.defaultSlippage, ).amount, }; + if (from.amount === BigInt(0)) + throw new Error(`${amount} asset from ${max_to.asset.id} is not enough!`); const { baseInput, baseInputAmount, minOutput } = getBaseInputParameters( pool, { From 4546351e27555d0df17be6d1ebd12d40bdb03c80 Mon Sep 17 00:00:00 2001 From: ahmadyazdanii Date: Fri, 28 Jun 2024 17:51:32 +0330 Subject: [PATCH 060/132] new [spectrum]: add spectrum connector's config --- .../spectrum/interfaces/spectrum.interface.ts | 9 +++++++++ src/connectors/spectrum/spectrum.config.ts | 12 ++++++++++++ src/services/schema/spectrum-schema.json | 14 ++++++++++++++ src/templates/spectrum.yml | 6 ++++++ 4 files changed, 41 insertions(+) create mode 100644 src/connectors/spectrum/interfaces/spectrum.interface.ts create mode 100644 src/connectors/spectrum/spectrum.config.ts create mode 100644 src/services/schema/spectrum-schema.json create mode 100644 src/templates/spectrum.yml diff --git a/src/connectors/spectrum/interfaces/spectrum.interface.ts b/src/connectors/spectrum/interfaces/spectrum.interface.ts new file mode 100644 index 0000000000..66cdd8a9be --- /dev/null +++ b/src/connectors/spectrum/interfaces/spectrum.interface.ts @@ -0,0 +1,9 @@ +import { AvailableNetworks } from '../../../services/config-manager-types'; + +export interface NetworkConfig { + allowedSlippage: string; + gasLimitEstimate: number; + tradingTypes: Array; + availableNetworks: Array; + chainType: string; +} diff --git a/src/connectors/spectrum/spectrum.config.ts b/src/connectors/spectrum/spectrum.config.ts new file mode 100644 index 0000000000..45b65d05d6 --- /dev/null +++ b/src/connectors/spectrum/spectrum.config.ts @@ -0,0 +1,12 @@ +import { ConfigManagerV2 } from '../../services/config-manager-v2'; +import { NetworkConfig } from './interfaces/spectrum.interface'; + +const configManager = ConfigManagerV2.getInstance(); + +export const spectrumConfig: NetworkConfig = { + allowedSlippage: configManager.get('ergo.allowedSlippage'), + gasLimitEstimate: configManager.get('ergo.gasLimitEstimate'), + tradingTypes: ['AMM'], + chainType: 'ERGO', + availableNetworks: [{ chain: 'ergo', networks: ['mainnet'] }], +}; diff --git a/src/services/schema/spectrum-schema.json b/src/services/schema/spectrum-schema.json new file mode 100644 index 0000000000..b8ebcb03dd --- /dev/null +++ b/src/services/schema/spectrum-schema.json @@ -0,0 +1,14 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "allowedSlippage": { + "type": "string" + }, + "gasLimitEstimate": { + "type": "integer" + } + }, + "additionalProperties": false, + "required": ["allowedSlippage", "gasLimitEstimate"] +} diff --git a/src/templates/spectrum.yml b/src/templates/spectrum.yml new file mode 100644 index 0000000000..d516d348b8 --- /dev/null +++ b/src/templates/spectrum.yml @@ -0,0 +1,6 @@ +# how much the execution price is allowed to move unfavorably from the trade +# execution price. It uses a rational number for precision. +allowedSlippage: '1/100' + +# the maximum gas used to estimate gasCost for a pangolin trade. +gasLimitEstimate: 150688 \ No newline at end of file From 1b3512dbc26cc86181a34bec47d036ec5d689986 Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Sun, 30 Jun 2024 19:55:24 +0330 Subject: [PATCH 061/132] change inputs for estimate and swap --- src/chains/ergo/ergo.ts | 54 ++++++++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 5d1b0e5151..ec0bf9dd37 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -428,7 +428,7 @@ export class Ergo { const new_pool = await makeNativePools(this._explorer).get(poolId); if (!new_pool) throw new Error(`can not get pool with this id: ${poolId}`); - this.ammPools.push(new Pool(pool)); + this.ammPools.push(new Pool(new_pool)); } } @@ -451,13 +451,17 @@ export class Ergo { private async swap( account: ErgoAccount, - pool: Pool, + baseToken: string, + quoteToken: string, amount: bigint, output_address: string, return_address: string, slippage: number, sell: boolean, ): Promise { + const pool = this.getPoolByToken(baseToken, quoteToken); + if (!pool) + throw new Error(`pool not found base on ${baseToken}, ${quoteToken}`); const config = getErgoConfig(this.network); const networkContext = await this._explorer.getNetworkContext(); const mainnetTxAssembler = new DefaultTxAssembler( @@ -552,7 +556,8 @@ export class Ergo { public async buy( account: ErgoAccount, - pool: Pool, + baseToken: string, + quoteToken: string, amount: bigint, output_address: string, return_address: string, @@ -560,7 +565,8 @@ export class Ergo { ): Promise { return await this.swap( account, - pool, + baseToken, + quoteToken, amount, output_address, return_address, @@ -571,7 +577,8 @@ export class Ergo { public async sell( account: ErgoAccount, - pool: Pool, + baseToken: string, + quoteToken: string, amount: bigint, output_address: string, return_address: string, @@ -579,7 +586,8 @@ export class Ergo { ): Promise { return await this.swap( account, - pool, + baseToken, + quoteToken, amount, output_address, return_address, @@ -589,11 +597,15 @@ export class Ergo { } private async estimate( - pool: Pool, + baseToken: string, + quoteToken: string, amount: bigint, slippage: number, sell: boolean, ): Promise { + const pool = this.getPoolByToken(baseToken, quoteToken); + if (!pool) + throw new Error(`pool not found base on ${baseToken}, ${quoteToken}`); const config = getErgoConfig(this.network); const max_to = { asset: { @@ -620,25 +632,45 @@ export class Ergo { } public async estimateBuy( - pool: Pool, + baseToken: string, + quoteToken: string, y_amount: bigint, slippage: number, ): Promise { - return await this.estimate(pool, y_amount, slippage, false); + return await this.estimate( + baseToken, + quoteToken, + y_amount, + slippage, + false, + ); } public async estimateSell( - pool: Pool, + baseToken: string, + quoteToken: string, x_amount: bigint, slippage: number, ): Promise { - return await this.estimate(pool, x_amount, slippage, true); + return await this.estimate(baseToken, quoteToken, x_amount, slippage, true); } public getPool(id: string): Pool { return this.ammPools.find((ammPool) => ammPool.id === id); } + public getPoolByToken(baseToken: string, quoteToken: string): Pool { + return ( + this.ammPools.find( + (ammPool) => + (ammPool.x.asset.id === baseToken && + ammPool.y.asset.id === quoteToken) || + (ammPool.x.asset.id === quoteToken && + ammPool.y.asset.id === baseToken), + ) + ); + } + public async getTx(id: string): Promise { return await this._node.getTxsById(id); } From fbe845e0ad96891317c73c1c7940edcf2ef3ebd2 Mon Sep 17 00:00:00 2001 From: ahmadyazdanii Date: Mon, 1 Jul 2024 10:30:45 +0330 Subject: [PATCH 062/132] new [spectrum]: add basics and connection of spectrum --- src/connectors/connectors.routes.ts | 11 +- src/connectors/spectrum/spectrum.config.ts | 16 +-- src/connectors/spectrum/spectrum.ts | 122 +++++++++++++++++++++ 3 files changed, 140 insertions(+), 9 deletions(-) create mode 100644 src/connectors/spectrum/spectrum.ts diff --git a/src/connectors/connectors.routes.ts b/src/connectors/connectors.routes.ts index d9ac0b63f9..24938233fc 100644 --- a/src/connectors/connectors.routes.ts +++ b/src/connectors/connectors.routes.ts @@ -24,6 +24,7 @@ import { KujiraConfig } from './kujira/kujira.config'; import { QuipuswapConfig } from './quipuswap/quipuswap.config'; import { OsmosisConfig } from '../chains/osmosis/osmosis.config'; import { CarbonConfig } from './carbon/carbon.config'; +import { SpectrumConfig } from './spectrum/spectrum.config'; export namespace ConnectorsRoutes { export const router = Router(); @@ -44,7 +45,7 @@ export namespace ConnectorsRoutes { trading_type: UniswapConfig.config.tradingTypes('LP'), chain_type: UniswapConfig.config.chainType, available_networks: JSON.parse( - JSON.stringify(UniswapConfig.config.availableNetworks) + JSON.stringify(UniswapConfig.config.availableNetworks), ), additional_spenders: ['uniswap'], }, @@ -183,8 +184,14 @@ export namespace ConnectorsRoutes { chain_type: CarbonConfig.config.chainType, available_networks: CarbonConfig.config.availableNetworks, }, + { + name: 'spectrum', + trading_type: SpectrumConfig.config.tradingTypes, + chain_type: SpectrumConfig.config.chainType, + available_networks: SpectrumConfig.config.availableNetworks, + }, ], }); - }) + }), ); } diff --git a/src/connectors/spectrum/spectrum.config.ts b/src/connectors/spectrum/spectrum.config.ts index 45b65d05d6..391b52cee4 100644 --- a/src/connectors/spectrum/spectrum.config.ts +++ b/src/connectors/spectrum/spectrum.config.ts @@ -3,10 +3,12 @@ import { NetworkConfig } from './interfaces/spectrum.interface'; const configManager = ConfigManagerV2.getInstance(); -export const spectrumConfig: NetworkConfig = { - allowedSlippage: configManager.get('ergo.allowedSlippage'), - gasLimitEstimate: configManager.get('ergo.gasLimitEstimate'), - tradingTypes: ['AMM'], - chainType: 'ERGO', - availableNetworks: [{ chain: 'ergo', networks: ['mainnet'] }], -}; +export namespace SpectrumConfig { + export const config: NetworkConfig = { + allowedSlippage: configManager.get('ergo.allowedSlippage'), + gasLimitEstimate: configManager.get('ergo.gasLimitEstimate'), + tradingTypes: ['AMM'], + chainType: 'ERGO', + availableNetworks: [{ chain: 'ergo', networks: ['mainnet'] }], + }; +} diff --git a/src/connectors/spectrum/spectrum.ts b/src/connectors/spectrum/spectrum.ts new file mode 100644 index 0000000000..460c0b765c --- /dev/null +++ b/src/connectors/spectrum/spectrum.ts @@ -0,0 +1,122 @@ +import { SpectrumConfig } from './spectrum.config'; +import { Ergo } from '../../chains/ergo/ergo'; +import { ErgoAsset } from '../../chains/ergo/interfaces/ergo.interface'; + +export class Spectrum { + private static _instances: { [name: string]: Spectrum }; + private ergo: Ergo; + private _gasLimitEstimate: number; + private tokenList: Record = {}; + private _ready: boolean = false; + + private constructor(network: string) { + const config = SpectrumConfig.config; + + this.ergo = Ergo.getInstance(network); + this._gasLimitEstimate = config.gasLimitEstimate; + } + + public static getInstance(chain: string, network: string): Spectrum { + if (Spectrum._instances === undefined) { + Spectrum._instances = {}; + } + if (!(chain + network in Spectrum._instances)) { + Spectrum._instances[chain + network] = new Spectrum(network); + } + + return Spectrum._instances[chain + network]; + } + + /** + * Given a token's address, return the connector's native representation of + * the token. + * + * @param address Token address + */ + public getTokenByAddress(address: string): ErgoAsset { + return this.tokenList[address]; + } + + public async init() { + if (!this.ergo.ready()) { + await this.ergo.init(); + } + + this.tokenList = this.ergo.storedTokenList; + + this._ready = true; + } + + public ready(): boolean { + return this._ready; + } + + /** + * Default gas limit for swap transactions. + */ + public get gasLimitEstimate(): number { + return this._gasLimitEstimate; + } + + /** + * Given the amount of `baseToken` to put into a transaction, calculate the + * amount of `quoteToken` that can be expected from the transaction. + * + * This is typically used for calculating token sell prices. + * + * @param baseToken Token input for the transaction + * @param quoteToken Output from the transaction + * @param amount Amount of `baseToken` to put into the transaction + */ + // async estimateSellTrade( + // baseToken: Token, + // quoteToken: Token, + // amount: BigNumber, + // allowedSlippage?: string, + // ): Promise {} + + /** + * Given the amount of `baseToken` desired to acquire from a transaction, + * calculate the amount of `quoteToken` needed for the transaction. + * + * This is typically used for calculating token buy prices. + * + * @param quoteToken Token input for the transaction + * @param baseToken Token output from the transaction + * @param amount Amount of `baseToken` desired from the transaction + */ + // async estimateBuyTrade( + // quoteToken: Token, + // baseToken: Token, + // amount: BigNumber, + // allowedSlippage?: string, + // ): Promise {} + + /** + * Given a wallet and a Uniswap-ish trade, try to execute it on blockchain. + * + * @param wallet Wallet + * @param trade Expected trade + * @param gasPrice Base gas price, for pre-EIP1559 transactions + * @param pangolinRouter smart contract address + * @param ttl How long the swap is valid before expiry, in seconds + * @param abi Router contract ABI + * @param gasLimit Gas limit + * @param nonce (Optional) EVM transaction nonce + * @param maxFeePerGas (Optional) Maximum total fee per gas you want to pay + * @param maxPriorityFeePerGas (Optional) Maximum tip per gas you want to pay + */ + // async executeTrade( + // wallet: Wallet, + // trade: Trade, + // gasPrice: number, + // pangolinRouter: string, + // ttl: number, + // abi: ContractInterface, + // gasLimit: number, + // nonce?: number, + // maxFeePerGas?: BigNumber, + // maxPriorityFeePerGas?: BigNumber, + // allowedSlippage?: string, + // ): Promise {} +} From 7b31b01f4eb791135cee234a581b5ba25d7766d3 Mon Sep 17 00:00:00 2001 From: ahmadyazdanii Date: Mon, 1 Jul 2024 18:25:52 +0330 Subject: [PATCH 063/132] update [ergo]: convert slippage to optional prop --- src/chains/ergo/ergo.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index ec0bf9dd37..addf0037a8 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -456,8 +456,8 @@ export class Ergo { amount: bigint, output_address: string, return_address: string, - slippage: number, sell: boolean, + slippage?: number, ): Promise { const pool = this.getPoolByToken(baseToken, quoteToken); if (!pool) @@ -561,7 +561,7 @@ export class Ergo { amount: bigint, output_address: string, return_address: string, - slippage: number, + slippage?: number, ): Promise { return await this.swap( account, @@ -570,8 +570,8 @@ export class Ergo { amount, output_address, return_address, - slippage, false, + slippage, ); } @@ -582,7 +582,7 @@ export class Ergo { amount: bigint, output_address: string, return_address: string, - slippage: number, + slippage?: number, ): Promise { return await this.swap( account, @@ -591,8 +591,8 @@ export class Ergo { amount, output_address, return_address, - slippage, true, + slippage, ); } @@ -600,8 +600,8 @@ export class Ergo { baseToken: string, quoteToken: string, amount: bigint, - slippage: number, sell: boolean, + slippage?: number, ): Promise { const pool = this.getPoolByToken(baseToken, quoteToken); if (!pool) @@ -635,14 +635,14 @@ export class Ergo { baseToken: string, quoteToken: string, y_amount: bigint, - slippage: number, + slippage?: number, ): Promise { return await this.estimate( baseToken, quoteToken, y_amount, - slippage, false, + slippage, ); } @@ -650,9 +650,9 @@ export class Ergo { baseToken: string, quoteToken: string, x_amount: bigint, - slippage: number, + slippage?: number, ): Promise { - return await this.estimate(baseToken, quoteToken, x_amount, slippage, true); + return await this.estimate(baseToken, quoteToken, x_amount, true, slippage); } public getPool(id: string): Pool { From 3d7accdff03d2f7b8e8c90017debe0d402b67e65 Mon Sep 17 00:00:00 2001 From: ahmadyazdanii Date: Mon, 1 Jul 2024 18:35:20 +0330 Subject: [PATCH 064/132] update [spectrum]: add 3 main functions --- src/connectors/spectrum/spectrum.ts | 82 +++++++++++++++++------------ 1 file changed, 47 insertions(+), 35 deletions(-) diff --git a/src/connectors/spectrum/spectrum.ts b/src/connectors/spectrum/spectrum.ts index 460c0b765c..7b67b38aa8 100644 --- a/src/connectors/spectrum/spectrum.ts +++ b/src/connectors/spectrum/spectrum.ts @@ -1,6 +1,10 @@ import { SpectrumConfig } from './spectrum.config'; import { Ergo } from '../../chains/ergo/ergo'; -import { ErgoAsset } from '../../chains/ergo/interfaces/ergo.interface'; +import { + ErgoAccount, + ErgoAsset, +} from '../../chains/ergo/interfaces/ergo.interface'; +import { Trade } from 'swap-router-sdk'; export class Spectrum { private static _instances: { [name: string]: Spectrum }; @@ -68,12 +72,19 @@ export class Spectrum { * @param quoteToken Output from the transaction * @param amount Amount of `baseToken` to put into the transaction */ - // async estimateSellTrade( - // baseToken: Token, - // quoteToken: Token, - // amount: BigNumber, - // allowedSlippage?: string, - // ): Promise {} + async estimateSellTrade( + baseToken: string, + quoteToken: string, + amount: bigint, + allowedSlippage?: string, + ) { + return this.ergo.estimateSell( + baseToken, + quoteToken, + amount, + Number(allowedSlippage), + ); + } /** * Given the amount of `baseToken` desired to acquire from a transaction, @@ -85,38 +96,39 @@ export class Spectrum { * @param baseToken Token output from the transaction * @param amount Amount of `baseToken` desired from the transaction */ - // async estimateBuyTrade( - // quoteToken: Token, - // baseToken: Token, - // amount: BigNumber, - // allowedSlippage?: string, - // ): Promise {} + async estimateBuyTrade( + baseToken: string, + quoteToken: string, + amount: bigint, + allowedSlippage?: string, + ) { + return this.ergo.estimateBuy( + baseToken, + quoteToken, + amount, + Number(allowedSlippage), + ); + } /** - * Given a wallet and a Uniswap-ish trade, try to execute it on blockchain. + * Given a wallet and a Ergo trade, try to execute it on blockchain. * * @param wallet Wallet * @param trade Expected trade - * @param gasPrice Base gas price, for pre-EIP1559 transactions - * @param pangolinRouter smart contract address - * @param ttl How long the swap is valid before expiry, in seconds - * @param abi Router contract ABI - * @param gasLimit Gas limit - * @param nonce (Optional) EVM transaction nonce - * @param maxFeePerGas (Optional) Maximum total fee per gas you want to pay - * @param maxPriorityFeePerGas (Optional) Maximum tip per gas you want to pay */ - // async executeTrade( - // wallet: Wallet, - // trade: Trade, - // gasPrice: number, - // pangolinRouter: string, - // ttl: number, - // abi: ContractInterface, - // gasLimit: number, - // nonce?: number, - // maxFeePerGas?: BigNumber, - // maxPriorityFeePerGas?: BigNumber, - // allowedSlippage?: string, - // ): Promise {} + async executeTrade( + wallet: ErgoAccount, + trade: Trade, + allowedSlippage?: string, + ) { + return this.ergo.buy( + wallet, + trade[0].aTokenSlug, + trade[0].bTokenSlug, + BigInt(trade[0].aTokenAmount.toString()), + wallet.address, + wallet.address, + Number(allowedSlippage), + ); + } } From 239e21ec6f1b05b39c8ede16794c969ef316782e Mon Sep 17 00:00:00 2001 From: satiparpar Date: Tue, 2 Jul 2024 15:56:06 +0330 Subject: [PATCH 065/132] fix[ chain ]: Update configs to connect HummingBot to ergo --- src/chains/chain.routes.ts | 1 + src/chains/ergo/ergo.controller.ts | 4 ++-- src/chains/ergo/interfaces/requests.interface.ts | 1 + src/services/wallet/wallet.controllers.ts | 10 ++++++++++ src/services/wallet/wallet.routes.ts | 1 + src/services/wallet/wallet.validators.ts | 10 ++++++++-- 6 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/chains/chain.routes.ts b/src/chains/chain.routes.ts index cbc13bf922..3b0794a64e 100644 --- a/src/chains/chain.routes.ts +++ b/src/chains/chain.routes.ts @@ -95,6 +95,7 @@ export namespace ChainRoutes { req.body.chain, req.body.network ); + console.log('im here') res.status(200).json(await balances(chain, req.body)); } diff --git a/src/chains/ergo/ergo.controller.ts b/src/chains/ergo/ergo.controller.ts index 77ee4f7c82..5e34978236 100644 --- a/src/chains/ergo/ergo.controller.ts +++ b/src/chains/ergo/ergo.controller.ts @@ -35,8 +35,8 @@ export class ErgoController { if (!chain.ready) { await chain.init(); } - - const utxos = await chain.getAddressUnspentBoxes(request.address); + const address = chain.getAccountFromMnemonic(request.privateKey); + const utxos = await chain.getAddressUnspentBoxes(address.address); const { balance, assets } = chain.getBalance(utxos); return { diff --git a/src/chains/ergo/interfaces/requests.interface.ts b/src/chains/ergo/interfaces/requests.interface.ts index 77c0625e78..c2104e8710 100644 --- a/src/chains/ergo/interfaces/requests.interface.ts +++ b/src/chains/ergo/interfaces/requests.interface.ts @@ -23,6 +23,7 @@ export interface PollRequest { export interface BalanceRequest extends NetworkSelectionRequest { address: string; // the users public key + privateKey: string; } export interface AssetsResponse { diff --git a/src/services/wallet/wallet.controllers.ts b/src/services/wallet/wallet.controllers.ts index e6c23dbfe0..109631bdb8 100644 --- a/src/services/wallet/wallet.controllers.ts +++ b/src/services/wallet/wallet.controllers.ts @@ -35,6 +35,7 @@ import { import { Ethereumish, Tezosish } from '../common-interfaces'; import { Algorand } from '../../chains/algorand/algorand'; import { Osmosis } from '../../chains/osmosis/osmosis'; +import { Ergo } from '../../chains/ergo/ergo'; export function convertXdcAddressToEthAddress(publicKey: string): string { return publicKey.length === 43 && publicKey.slice(0, 3) === 'xdc' @@ -157,6 +158,15 @@ export async function addWallet( req.privateKey, passphrase ); + } else if (connection instanceof Ergo) { + const account = connection.getAccountFromMnemonic(req.privateKey); + console.log(account) + address = account.address; + encryptedPrivateKey = await connection.encrypt( + req.privateKey, + passphrase, + ); + console.log(encryptedPrivateKey); } if (address === undefined || encryptedPrivateKey === undefined) { diff --git a/src/services/wallet/wallet.routes.ts b/src/services/wallet/wallet.routes.ts index e1b5742ed5..491b434648 100644 --- a/src/services/wallet/wallet.routes.ts +++ b/src/services/wallet/wallet.routes.ts @@ -44,6 +44,7 @@ export namespace WalletRoutes { res: Response ) => { validateAddWalletRequest(req.body); + console.log('love you'); res.status(200).json(await addWallet(req.body)); } ) diff --git a/src/services/wallet/wallet.validators.ts b/src/services/wallet/wallet.validators.ts index d58a0db605..28cd82e219 100644 --- a/src/services/wallet/wallet.validators.ts +++ b/src/services/wallet/wallet.validators.ts @@ -143,7 +143,12 @@ export const validatePrivateKey: Validator = mkSelectingValidator( invalidKujiraPrivateKeyError, (val) => typeof val === 'string' && isKujiraPrivateKey(val) ), - } + ergo: mkValidator( + 'privateKey', + invalidKujiraPrivateKeyError, + (val) => typeof val === 'string', + ), + }, ); export const invalidChainError: string = @@ -177,7 +182,8 @@ export const validateChain: Validator = mkValidator( val === 'binance-smart-chain' || val === 'tezos' || val === 'xrpl' || - val === 'kujira') + val === 'kujira' || + val === 'ergo'), ); export const validateNetwork: Validator = mkValidator( From c3fd41e738c49d1e22ff015828d479b48e0ad473 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Tue, 2 Jul 2024 15:58:56 +0330 Subject: [PATCH 066/132] update[wallet.routs]: delete useless logs --- src/services/wallet/wallet.routes.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/services/wallet/wallet.routes.ts b/src/services/wallet/wallet.routes.ts index 491b434648..e1b5742ed5 100644 --- a/src/services/wallet/wallet.routes.ts +++ b/src/services/wallet/wallet.routes.ts @@ -44,7 +44,6 @@ export namespace WalletRoutes { res: Response ) => { validateAddWalletRequest(req.body); - console.log('love you'); res.status(200).json(await addWallet(req.body)); } ) From 15609c23b93a9260c0c0f7389faf6d2e2fa5d027 Mon Sep 17 00:00:00 2001 From: ahmadyazdanii Date: Wed, 3 Jul 2024 13:33:01 +0330 Subject: [PATCH 067/132] fix [spectrum]: add some configurations --- src/services/connection-manager.ts | 12 +++++++++--- src/templates/root.yml | 4 ++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/services/connection-manager.ts b/src/services/connection-manager.ts index eda66c699b..2f81c40ab4 100644 --- a/src/services/connection-manager.ts +++ b/src/services/connection-manager.ts @@ -46,6 +46,7 @@ import { PancakeswapLP } from '../connectors/pancakeswap/pancakeswap.lp'; import { XRPLCLOB } from '../connectors/xrpl/xrpl'; import { QuipuSwap } from '../connectors/quipuswap/quipuswap'; import { Carbonamm } from '../connectors/carbon/carbonAMM'; +import { Spectrum } from '../connectors/spectrum/spectrum'; export type ChainUnion = | Algorand @@ -164,7 +165,8 @@ export type ConnectorUnion = | XRPLCLOB | Curve | KujiraCLOB - | QuipuSwap; + | QuipuSwap + | Spectrum; export type Connector = T extends Uniswapish ? Uniswapish @@ -186,7 +188,9 @@ export type Connector = T extends Uniswapish ? KujiraCLOB : T extends QuipuSwap ? QuipuSwap - : never; + : T extends Spectrum + ? Spectrum + : never; export async function getConnector( chain: string, @@ -255,7 +259,9 @@ export async function getConnector( connectorInstance = QuipuSwap.getInstance(network); } else if (chain === 'ethereum' && connector === 'carbonamm') { connectorInstance = Carbonamm.getInstance(chain, network); - } else { + } else if(chain === 'ergo' && connector === 'spectrum') { + connectorInstance = Spectrum.getInstance(chain, network); + }else { throw new Error('unsupported chain or connector'); } diff --git a/src/templates/root.yml b/src/templates/root.yml index 3e5133d854..938d1618a1 100644 --- a/src/templates/root.yml +++ b/src/templates/root.yml @@ -135,3 +135,7 @@ configurations: $namespace carbon: configurationPath: carbon.yml schemaPath: carbon-schema.json + + $namespace spectrum: + configurationPath: spectrum.yml + schemaPath: spectrum-schema.json From a2cc0bc7e8922d8c1d11c9155e241675cfa4ffe6 Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Fri, 5 Jul 2024 04:06:54 +0330 Subject: [PATCH 068/132] change all bigint to bignumber as possible --- src/chains/ergo/ergo.config.ts | 5 +- src/chains/ergo/ergo.controller.ts | 26 +++++++- src/chains/ergo/ergo.ts | 63 ++++++++++---------- src/chains/ergo/ergo.util.ts | 20 ++++++- src/chains/ergo/interfaces/ergo.interface.ts | 11 ++-- src/connectors/spectrum/spectrum.ts | 7 ++- 6 files changed, 88 insertions(+), 44 deletions(-) diff --git a/src/chains/ergo/ergo.config.ts b/src/chains/ergo/ergo.config.ts index 15ecefec5b..11a022739e 100644 --- a/src/chains/ergo/ergo.config.ts +++ b/src/chains/ergo/ergo.config.ts @@ -2,6 +2,7 @@ import { ConfigManagerV2 } from '../../services/config-manager-v2'; import { NetworkPrefix } from 'ergo-lib-wasm-nodejs'; import { ErgoConfig } from './interfaces/ergo.interface'; import { ErgoNetwork } from './types/ergo.type'; +import { BigNumber } from 'bignumber.js'; /** * This function return configuration for Ergo @@ -32,11 +33,11 @@ export function getErgoConfig(network: ErgoNetwork): ErgoConfig { defaultSlippage: configManager.get( `ergo.networks.${network}.defaultSlippage`, ), - defaultMinerFee: BigInt( + defaultMinerFee: BigNumber( configManager.get(`ergo.networks.${network}.defaultMinerFee`), ), minNitro: configManager.get(`ergo.networks.${network}.minNitro`), - minBoxValue: BigInt( + minBoxValue: BigNumber( configManager.get(`ergo.networks.${network}.minBoxValue`), ), }, diff --git a/src/chains/ergo/ergo.controller.ts b/src/chains/ergo/ergo.controller.ts index 5e34978236..bc82aa73df 100644 --- a/src/chains/ergo/ergo.controller.ts +++ b/src/chains/ergo/ergo.controller.ts @@ -15,6 +15,7 @@ import { TransferRequest, } from './interfaces/requests.interface'; import { TokensRequest } from '../../network/network.requests'; +import { ErgoBoxAsset } from './interfaces/ergo.interface'; export class ErgoController { static async pool(ergo: Ergo, req: PoolRequest): Promise { @@ -24,6 +25,7 @@ export class ErgoController { return ergo.getPool(req.poolId).info; } + static async poll(ergo: Ergo, req: PollRequest): Promise { if (!ergo.ready) { await ergo.init(); @@ -31,6 +33,7 @@ export class ErgoController { return await ergo.getTx(req.txId); } + static async balances(chain: Ergo, request: BalanceRequest) { if (!chain.ready) { await chain.init(); @@ -66,8 +69,27 @@ export class ErgoController { const utxos = await ergo.getAddressUnspentBoxes(req.fromAddress); return new TransactionBuilder(networkHeight) - .from(utxos) - .to(new OutputBuilder(req.toValue, req.toAddress).addTokens(req.assets)) + .from( + utxos.map((utxo) => { + const temp = Object(utxo); + temp.value = temp.value.toString(); + temp.assets = temp.assets.map((asset: ErgoBoxAsset) => { + const temp2 = Object(asset); + temp2.amount = temp2.amount.toString(); + return temp2; + }); + return temp; + }), + ) + .to( + new OutputBuilder(req.toValue, req.toAddress).addTokens( + req.assets.map((asset) => { + const temp = Object(asset); + temp.amount = temp.amount.toString(); + return temp; + }), + ), + ) .sendChangeTo(req.fromAddress) .payMinFee() .build(); diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index addf0037a8..2ee7a8c5b3 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -41,6 +41,7 @@ import { NetworkContext } from '@patternglobal/ergo-sdk/build/main/entities/netw import { ErgoNetwork } from './types/ergo.type'; import { getBaseInputParameters, getInputs, getTxContext } from './ergo.util'; import { WalletProver } from './wallet-prover.service'; +import { BigNumber } from 'bignumber.js'; class Pool extends AmmPool { private _name: string; @@ -345,20 +346,22 @@ export class Ergo { assetName: string, ): Promise { const ergoAsset = this._assetMap[assetName.toUpperCase()]; - let balance = BigInt(0); + let balance = BigNumber(0); if (!ergoAsset) throw new Error(`assetName not found ${this._chain} Node!`); try { const utxos = await this.getAddressUnspentBoxes(account.address); balance = utxos.reduce( - (total: bigint, box) => - total + - box.assets - .filter((asset) => asset.tokenId === ergoAsset.tokenId.toString()) - .reduce( - (total_asset, asset) => total_asset + BigInt(asset.amount), - BigInt(0), - ), - BigInt(0), + (total: BigNumber, box) => + total.plus( + box.assets + .filter((asset) => asset.tokenId === ergoAsset.tokenId.toString()) + .reduce( + (total_asset, asset) => + total_asset.plus(BigNumber(asset.amount)), + BigNumber(0), + ), + ), + BigNumber(0), ); } catch (error: any) { throw new Error( @@ -371,16 +374,16 @@ export class Ergo { public getBalance(utxos: ErgoBox[]) { const balance = utxos.reduce( - (total, box) => total + BigInt(box.value), - BigInt(0), + (total, box) => total.plus(BigNumber(box.value)), + BigNumber(0), ); - const assets: Record = {}; + const assets: Record = {}; utxos.forEach((box) => { box.assets.forEach((asset) => { if (Object.keys(assets).includes(asset.tokenId)) - assets[asset.tokenId] += BigInt(asset.amount); - else assets[asset.tokenId] = BigInt(asset.amount); + assets[asset.tokenId].plus(BigNumber(asset.amount)); + else assets[asset.tokenId] = BigNumber(asset.amount); }); }); @@ -453,7 +456,7 @@ export class Ergo { account: ErgoAccount, baseToken: string, quoteToken: string, - amount: bigint, + amount: BigNumber, output_address: string, return_address: string, sell: boolean, @@ -506,7 +509,7 @@ export class Ergo { }, ); const swapVariables: [number, SwapExtremums] | undefined = swapVars( - config.network.defaultMinerFee * BigInt(3), + BigInt(config.network.defaultMinerFee.multipliedBy(3).toString()), config.network.minNitro, minOutput, ); @@ -515,19 +518,19 @@ export class Ergo { const inputs = getInputs( utxos.map((utxo) => { const temp = Object(utxo); - temp.value = BigInt(temp.value); + temp.value = BigNumber(temp.value); temp.assets = temp.assets.map((asset: any) => { const temp2 = Object(asset); - temp2.amount = BigInt(temp2.amount); + temp2.amount = BigNumber(temp2.amount); return temp2; }); return temp; }), - [new AssetAmount(from.asset, baseInputAmount)], + [new AssetAmount(from.asset, BigInt(baseInputAmount.toString()))], { - minerFee: config.network.defaultMinerFee, - uiFee: config.network.defaultMinerFee, - exFee: extremum.maxExFee, + minerFee: BigInt(config.network.defaultMinerFee.toString()), + uiFee: BigInt(config.network.defaultMinerFee.toString()), + exFee: BigInt(extremum.maxExFee.toString()), }, ); const pk = publicKeyFromAddress(output_address); @@ -538,7 +541,7 @@ export class Ergo { baseInput, minQuoteOutput: extremum.minOutput.amount, exFeePerToken, - uiFee: config.network.defaultMinerFee, + uiFee: BigInt(config.network.defaultMinerFee.toString()), quoteAsset: to.asset.id, poolFeeNum: pool.poolFeeNum, maxExFee: extremum.maxExFee, @@ -547,7 +550,7 @@ export class Ergo { inputs, networkContext as NetworkContext, return_address, - config.network.defaultMinerFee, + BigInt(config.network.defaultMinerFee.toString()), ); const actions = poolActions(pool); @@ -558,7 +561,7 @@ export class Ergo { account: ErgoAccount, baseToken: string, quoteToken: string, - amount: bigint, + amount: BigNumber, output_address: string, return_address: string, slippage?: number, @@ -579,7 +582,7 @@ export class Ergo { account: ErgoAccount, baseToken: string, quoteToken: string, - amount: bigint, + amount: BigNumber, output_address: string, return_address: string, slippage?: number, @@ -599,7 +602,7 @@ export class Ergo { private async estimate( baseToken: string, quoteToken: string, - amount: bigint, + amount: BigNumber, sell: boolean, slippage?: number, ): Promise { @@ -634,7 +637,7 @@ export class Ergo { public async estimateBuy( baseToken: string, quoteToken: string, - y_amount: bigint, + y_amount: BigNumber, slippage?: number, ): Promise { return await this.estimate( @@ -649,7 +652,7 @@ export class Ergo { public async estimateSell( baseToken: string, quoteToken: string, - x_amount: bigint, + x_amount: BigNumber, slippage?: number, ): Promise { return await this.estimate(baseToken, quoteToken, x_amount, true, slippage); diff --git a/src/chains/ergo/ergo.util.ts b/src/chains/ergo/ergo.util.ts index 81b6d24805..7489c4ab1f 100644 --- a/src/chains/ergo/ergo.util.ts +++ b/src/chains/ergo/ergo.util.ts @@ -1,4 +1,8 @@ -import { BaseInputParameters, ErgoBox } from './interfaces/ergo.interface'; +import { + BaseInputParameters, + ErgoBox, + ErgoBoxAsset, +} from './interfaces/ergo.interface'; import { AmmPool, minValueForOrder, @@ -50,7 +54,19 @@ export function getInputs( } const target = makeTarget(assets, minFeeForOrder); - const inputs = DefaultBoxSelector.select(utxos, target); + const inputs = DefaultBoxSelector.select( + utxos.map((utxo) => { + const temp = Object(utxo); + temp.value = temp.value.toString(); + temp.assets = temp.assets.map((asset: ErgoBoxAsset) => { + const temp2 = Object(asset); + temp2.amount = temp2.amount.toString(); + return temp2; + }); + return temp; + }), + target, + ); if (inputs instanceof InsufficientInputs) { throw new Error( `Error in getInputs function: InsufficientInputs -> ${inputs}`, diff --git a/src/chains/ergo/interfaces/ergo.interface.ts b/src/chains/ergo/interfaces/ergo.interface.ts index d01cb9e36d..a0bcd729a5 100644 --- a/src/chains/ergo/interfaces/ergo.interface.ts +++ b/src/chains/ergo/interfaces/ergo.interface.ts @@ -3,6 +3,7 @@ import { Wallet } from 'ergo-lib-wasm-nodejs'; import { Ergo } from '../ergo'; import { AssetAmount } from '@patternglobal/ergo-sdk'; import { WalletProver } from '../wallet-prover.service'; +import { BigNumber } from 'bignumber.js'; export interface ErgoNetworkConfig { name: string; @@ -16,9 +17,9 @@ export interface ErgoNetworkConfig { utxosLimit: number; poolLimit: number; defaultSlippage: number; - defaultMinerFee: bigint; + defaultMinerFee: BigNumber; minNitro: number; - minBoxValue: bigint; + minBoxValue: BigNumber; } export interface ErgoConfig { network: ErgoNetworkConfig; @@ -43,12 +44,12 @@ export interface ErgoConnectedInstance { export interface ErgoBoxAsset { tokenId: string; - amount: bigint; + amount: BigNumber; } export interface ErgoBox { boxId: string; - value: bigint; + value: BigNumber; ergoTree: string; creationHeight: number; assets: Array; @@ -66,6 +67,6 @@ export interface ErgoBox { export interface BaseInputParameters { baseInput: AssetAmount; - baseInputAmount: bigint; + baseInputAmount: BigNumber; minOutput: AssetAmount; } diff --git a/src/connectors/spectrum/spectrum.ts b/src/connectors/spectrum/spectrum.ts index 7b67b38aa8..4f316276e4 100644 --- a/src/connectors/spectrum/spectrum.ts +++ b/src/connectors/spectrum/spectrum.ts @@ -5,6 +5,7 @@ import { ErgoAsset, } from '../../chains/ergo/interfaces/ergo.interface'; import { Trade } from 'swap-router-sdk'; +import { BigNumber } from 'bignumber.js'; export class Spectrum { private static _instances: { [name: string]: Spectrum }; @@ -75,7 +76,7 @@ export class Spectrum { async estimateSellTrade( baseToken: string, quoteToken: string, - amount: bigint, + amount: BigNumber, allowedSlippage?: string, ) { return this.ergo.estimateSell( @@ -99,7 +100,7 @@ export class Spectrum { async estimateBuyTrade( baseToken: string, quoteToken: string, - amount: bigint, + amount: BigNumber, allowedSlippage?: string, ) { return this.ergo.estimateBuy( @@ -125,7 +126,7 @@ export class Spectrum { wallet, trade[0].aTokenSlug, trade[0].bTokenSlug, - BigInt(trade[0].aTokenAmount.toString()), + trade[0].aTokenAmount, wallet.address, wallet.address, Number(allowedSlippage), From 3629a2943b9ac687417b57a0ccd7b92d107058e8 Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Fri, 5 Jul 2024 05:05:29 +0330 Subject: [PATCH 069/132] amm connector added --- src/amm/amm.controllers.ts | 133 +++++++++++++--------- src/amm/amm.requests.ts | 17 ++- src/chains/ergo/ergo.ts | 126 ++++++++------------ src/chains/ergo/node.service.ts | 5 + src/connectors/spectrum/spectrum.ts | 75 ++++-------- src/services/connection-manager.ts | 4 +- src/services/wallet/wallet.controllers.ts | 43 ++++--- 7 files changed, 189 insertions(+), 214 deletions(-) diff --git a/src/amm/amm.controllers.ts b/src/amm/amm.controllers.ts index 54ba964bb7..6e123bd51c 100644 --- a/src/amm/amm.controllers.ts +++ b/src/amm/amm.controllers.ts @@ -88,21 +88,26 @@ import { Plenty } from '../connectors/plenty/plenty'; import { QuipuSwap } from '../connectors/quipuswap/quipuswap'; import { Osmosis } from '../chains/osmosis/osmosis'; import { Carbonamm } from '../connectors/carbon/carbonAMM'; +import { Spectrum } from '../connectors/spectrum/spectrum'; +import { Ergo } from '../chains/ergo/ergo'; export async function price(req: PriceRequest): Promise { const chain = await getInitializedChain< - Algorand | Ethereumish | Nearish | Tezosish | Osmosis + Algorand | Ethereumish | Nearish | Tezosish | Osmosis | Ergo >(req.chain, req.network); - if (chain instanceof Osmosis){ + if (chain instanceof Osmosis) { return chain.controller.price(chain as unknown as Osmosis, req); } - const connector: Uniswapish | RefAMMish | Tinyman | Plenty | QuipuSwap = - await getConnector( - req.chain, - req.network, - req.connector - ); + const connector: + | Uniswapish + | RefAMMish + | Tinyman + | Plenty + | QuipuSwap + | Spectrum = await getConnector< + Uniswapish | RefAMMish | Tinyman | Plenty | QuipuSwap | Spectrum + >(req.chain, req.network, req.connector); if (connector instanceof Plenty) { return plentyPrice(chain, connector, req); @@ -115,6 +120,8 @@ export async function price(req: PriceRequest): Promise { return uniswapPrice(chain, connector, req); } else if (connector instanceof Tinyman) { return tinymanPrice(chain as unknown as Algorand, connector, req); + } else if (connector instanceof Spectrum) { + return connector.estimateTrade(req); } else { return refPrice(chain, connector as RefAMMish, req); } @@ -122,18 +129,21 @@ export async function price(req: PriceRequest): Promise { export async function trade(req: TradeRequest): Promise { const chain = await getInitializedChain< - Algorand | Ethereumish | Nearish | Tezosish | Osmosis + Algorand | Ethereumish | Nearish | Tezosish | Osmosis | Ergo >(req.chain, req.network); - if (chain instanceof Osmosis){ + if (chain instanceof Osmosis) { return chain.controller.trade(chain as unknown as Osmosis, req); } - const connector: Uniswapish | RefAMMish | Tinyman | Plenty | QuipuSwap = - await getConnector( - req.chain, - req.network, - req.connector - ); + const connector: + | Uniswapish + | RefAMMish + | Tinyman + | Plenty + | QuipuSwap + | Spectrum = await getConnector< + Uniswapish | RefAMMish | Tinyman | Plenty | QuipuSwap | Spectrum + >(req.chain, req.network, req.connector); if (connector instanceof Plenty) { return plentyTrade(chain, connector, req); @@ -146,103 +156,120 @@ export async function trade(req: TradeRequest): Promise { return uniswapTrade(chain, connector, req); } else if (connector instanceof Tinyman) { return tinymanTrade(chain as unknown as Algorand, connector, req); + } else if (connector instanceof Spectrum) { + return connector.executeTrade(req); } else { return refTrade(chain, connector as RefAMMish, req); } } export async function addLiquidity( - req: AddLiquidityRequest + req: AddLiquidityRequest, ): Promise { - const chain = await getInitializedChain(req.chain, req.network); - if (chain instanceof Osmosis){ + const chain = await getInitializedChain( + req.chain, + req.network, + ); + if (chain instanceof Osmosis) { return chain.controller.addLiquidity(chain as unknown as Osmosis, req); } const connector: UniswapLPish = await getConnector( req.chain, req.network, - req.connector + req.connector, ); return uniswapV3AddLiquidity(chain, connector, req); } export async function reduceLiquidity( - req: RemoveLiquidityRequest + req: RemoveLiquidityRequest, ): Promise { - const chain = await getInitializedChain(req.chain, req.network); - if (chain instanceof Osmosis){ + const chain = await getInitializedChain( + req.chain, + req.network, + ); + if (chain instanceof Osmosis) { return chain.controller.removeLiquidity(chain as unknown as Osmosis, req); } const connector: UniswapLPish = await getConnector( req.chain, req.network, - req.connector + req.connector, ); return uniswapV3RemoveLiquidity(chain, connector, req); } export async function collectFees( - req: CollectEarnedFeesRequest + req: CollectEarnedFeesRequest, ): Promise { - const chain = await getInitializedChain(req.chain, req.network); - if (chain instanceof Osmosis){ + const chain = await getInitializedChain( + req.chain, + req.network, + ); + if (chain instanceof Osmosis) { return chain.controller.collectFees(chain as unknown as Osmosis, req); } const connector: UniswapLPish = await getConnector( req.chain, req.network, - req.connector + req.connector, ); return uniswapV3CollectEarnedFees(chain, connector, req); } export async function positionInfo( - req: PositionRequest + req: PositionRequest, ): Promise { - const chain = await getInitializedChain(req.chain, req.network); - if (chain instanceof Osmosis){ + const chain = await getInitializedChain( + req.chain, + req.network, + ); + if (chain instanceof Osmosis) { return chain.controller.poolPositions(chain as unknown as Osmosis, req); } const connector: UniswapLPish = await getConnector( req.chain, req.network, - req.connector + req.connector, ); return uniswapV3PositionInfo(chain, connector, req); } export async function poolPrice( - req: PoolPriceRequest + req: PoolPriceRequest, ): Promise { - const chain = await getInitializedChain(req.chain, req.network); - if (chain instanceof Osmosis){ + const chain = await getInitializedChain( + req.chain, + req.network, + ); + if (chain instanceof Osmosis) { return chain.controller.poolPrice(chain as unknown as Osmosis, req); } const connector: UniswapLPish = await getConnector( req.chain, req.network, - req.connector + req.connector, ); return uniswapV3PoolPrice(chain, connector, req); } export async function estimateGas( - req: NetworkSelectionRequest + req: NetworkSelectionRequest, ): Promise { const chain = await getInitializedChain< Algorand | Ethereumish | Nearish | Tezosish | Osmosis >(req.chain, req.network); - if (chain instanceof Osmosis){ + if (chain instanceof Osmosis) { return chain.controller.estimateGas(chain as unknown as Osmosis); } - + const connector: Uniswapish | RefAMMish | Tinyman | Plenty | QuipuSwap = await getConnector( req.chain, req.network, - req.connector + req.connector, ); if (connector instanceof Plenty) { @@ -263,46 +290,46 @@ export async function estimateGas( // perp export async function perpMarketPrices( - req: PriceRequest + req: PriceRequest, ): Promise { const chain = await getInitializedChain(req.chain, req.network); const connector: Perpish = await getConnector( req.chain, req.network, - req.connector + req.connector, ); return perpPriceData(chain, connector, req); } export async function perpOrder( req: PerpCreateTakerRequest, - isOpen: boolean + isOpen: boolean, ): Promise { const chain = await getInitializedChain(req.chain, req.network); const connector: Perpish = await getConnector( req.chain, req.network, req.connector, - req.address + req.address, ); return createTakerOrder(chain, connector, req, isOpen); } export async function perpPosition( - req: PerpPositionRequest + req: PerpPositionRequest, ): Promise { const chain = await getInitializedChain(req.chain, req.network); const connector: Perpish = await getConnector( req.chain, req.network, req.connector, - req.address + req.address, ); return getPosition(chain, connector, req); } export async function perpBalance( - req: PerpBalanceRequest + req: PerpBalanceRequest, ): Promise { const chain = await getInitializedChain(req.chain, req.network); const connector: Perpish = ( @@ -312,37 +339,37 @@ export async function perpBalance( } export async function perpPairs( - req: NetworkSelectionRequest + req: NetworkSelectionRequest, ): Promise { const chain = await getInitializedChain(req.chain, req.network); const connector: Perpish = await getConnector( req.chain, req.network, - req.connector + req.connector, ); return getAvailablePairs(chain, connector); } export async function getMarketStatus( - req: PerpMarketRequest + req: PerpMarketRequest, ): Promise { const chain = await getInitializedChain(req.chain, req.network); const connector: Perpish = await getConnector( req.chain, req.network, - req.connector + req.connector, ); return checkMarketStatus(chain, connector, req); } export async function estimatePerpGas( - req: NetworkSelectionRequest + req: NetworkSelectionRequest, ): Promise { const chain = await getInitializedChain(req.chain, req.network); const connector: Perpish = await getConnector( req.chain, req.network, - req.connector + req.connector, ); return perpEstimateGas(chain, connector); } diff --git a/src/amm/amm.requests.ts b/src/amm/amm.requests.ts index a02f0470c9..a9dfc5c663 100644 --- a/src/amm/amm.requests.ts +++ b/src/amm/amm.requests.ts @@ -1,4 +1,7 @@ -import { CoinAndSymbol, SerializableExtendedPool as CosmosSerializableExtendedPool } from '../chains/osmosis/osmosis.types'; +import { + CoinAndSymbol, + SerializableExtendedPool as CosmosSerializableExtendedPool, +} from '../chains/osmosis/osmosis.types'; import { PerpPosition } from '../connectors/perp/perp'; import { NetworkSelectionRequest, @@ -38,7 +41,7 @@ export interface PriceResponse { export interface PoolPriceRequest extends NetworkSelectionRequest { token0: string; token1: string; - address?: string + address?: string; fee?: string; period?: number; interval?: number; @@ -70,6 +73,7 @@ export interface TradeRequest extends NetworkSelectionRequest { maxPriorityFeePerGas?: string; allowedSlippage?: string; poolId?: string; + mnemonic?: string; } export interface TradeResponse { @@ -83,8 +87,8 @@ export interface TradeResponse { rawAmount: string; finalAmountReceived_basetoken?: string; // Cosmos expectedIn?: string; - expectedOut?: string; // Cosmos: expectedAmountReceived - expectedPrice?: string; // Cosmos + expectedOut?: string; // Cosmos: expectedAmountReceived + expectedPrice?: string; // Cosmos price: string; // Cosmos: finalPrice gasPrice: number; gasPriceToken: string; @@ -95,14 +99,15 @@ export interface TradeResponse { txHash: string | any | undefined; } -export interface AddLiquidityRequest extends NetworkSelectionRequest { // now also cosmos add swap position OR cosmos add LP position +export interface AddLiquidityRequest extends NetworkSelectionRequest { + // now also cosmos add swap position OR cosmos add LP position address: string; token0: string; token1: string; amount0: string; amount1: string; fee?: string; - lowerPrice?: string; // integer as string // COSMOS - using this != undefined then call addpositionLP(), else: addposition() + lowerPrice?: string; // integer as string // COSMOS - using this != undefined then call addpositionLP(), else: addposition() upperPrice?: string; // integer as string tokenId?: number; // COSMOS: poolId - will select one for you if not provided nonce?: number; diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 2ee7a8c5b3..869ddb29bc 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -42,6 +42,7 @@ import { ErgoNetwork } from './types/ergo.type'; import { getBaseInputParameters, getInputs, getTxContext } from './ergo.util'; import { WalletProver } from './wallet-prover.service'; import { BigNumber } from 'bignumber.js'; +import { PriceResponse, TradeResponse } from '../../amm/amm.requests'; class Pool extends AmmPool { private _name: string; @@ -452,19 +453,21 @@ export class Ergo { return this._assetMap; } - private async swap( + public async swap( account: ErgoAccount, baseToken: string, quoteToken: string, amount: BigNumber, output_address: string, return_address: string, - sell: boolean, slippage?: number, - ): Promise { + ): Promise { + let sell: boolean; const pool = this.getPoolByToken(baseToken, quoteToken); if (!pool) throw new Error(`pool not found base on ${baseToken}, ${quoteToken}`); + if (pool.x.asset.id === baseToken) sell = false; + else sell = true; const config = getErgoConfig(this.network); const networkContext = await this._explorer.getNetworkContext(); const mainnetTxAssembler = new DefaultTxAssembler( @@ -553,62 +556,42 @@ export class Ergo { BigInt(config.network.defaultMinerFee.toString()), ); const actions = poolActions(pool); - - return await actions.swap(swapParams, txContext); - } - - public async buy( - account: ErgoAccount, - baseToken: string, - quoteToken: string, - amount: BigNumber, - output_address: string, - return_address: string, - slippage?: number, - ): Promise { - return await this.swap( - account, - baseToken, - quoteToken, - amount, - output_address, - return_address, - false, - slippage, - ); - } - - public async sell( - account: ErgoAccount, - baseToken: string, - quoteToken: string, - amount: BigNumber, - output_address: string, - return_address: string, - slippage?: number, - ): Promise { - return await this.swap( - account, - baseToken, - quoteToken, - amount, - output_address, - return_address, - true, - slippage, - ); + const timestamp = ( + await this._node.getBlockInfo(networkContext.height.toString()) + ).header.timestamp; + const tx = await actions.swap(swapParams, txContext); + return { + network: this.network, + timestamp, + latency: 0, + base: baseToken, + quote: quoteToken, + amount: amount.toString(), + rawAmount: amount.toString(), + expectedOut: minOutput.amount.toString(), + price: sell + ? pool.priceX.numerator.toString() + : pool.priceY.numerator.toString(), // Cosmos: finalPrice + gasPrice: 0, + gasPriceToken: '0', + gasLimit: 0, + gasCost: '0', + txHash: tx.id, + }; } - private async estimate( + public async estimate( baseToken: string, quoteToken: string, amount: BigNumber, - sell: boolean, slippage?: number, - ): Promise { + ): Promise { + let sell: boolean; const pool = this.getPoolByToken(baseToken, quoteToken); if (!pool) throw new Error(`pool not found base on ${baseToken}, ${quoteToken}`); + if (pool.x.asset.id === baseToken) sell = false; + else sell = true; const config = getErgoConfig(this.network); const max_to = { asset: { @@ -630,32 +613,23 @@ export class Ergo { inputAmount: from, slippage: slippage || config.network.defaultSlippage, }); - - return minOutput; - } - - public async estimateBuy( - baseToken: string, - quoteToken: string, - y_amount: BigNumber, - slippage?: number, - ): Promise { - return await this.estimate( - baseToken, - quoteToken, - y_amount, - false, - slippage, - ); - } - - public async estimateSell( - baseToken: string, - quoteToken: string, - x_amount: BigNumber, - slippage?: number, - ): Promise { - return await this.estimate(baseToken, quoteToken, x_amount, true, slippage); + return { + base: baseToken, + quote: quoteToken, + amount: amount.toString(), + rawAmount: amount.toString(), + expectedAmount: minOutput.amount.toString(), + price: sell + ? pool.priceX.numerator.toString() + : pool.priceY.numerator.toString(), + network: this.network, + timestamp: Date.now(), + latency: 0, + gasPrice: 0, + gasPriceToken: '0', + gasLimit: 0, + gasCost: '0', + }; } public getPool(id: string): Pool { diff --git a/src/chains/ergo/node.service.ts b/src/chains/ergo/node.service.ts index a02af4522e..221ed4b6d1 100644 --- a/src/chains/ergo/node.service.ts +++ b/src/chains/ergo/node.service.ts @@ -106,4 +106,9 @@ export class NodeService { async getTxsById(id: string): Promise { return this.request('GET', `/blockchain/transaction/byId/${id}`); } + + async getBlockInfo(blockHeight: string): Promise { + const blockId = (await this.request('GET', `/blocks/at/${blockHeight}`))[0]; + return await this.request('GET', `/blocks/${blockId}`); + } } diff --git a/src/connectors/spectrum/spectrum.ts b/src/connectors/spectrum/spectrum.ts index 4f316276e4..42830d2478 100644 --- a/src/connectors/spectrum/spectrum.ts +++ b/src/connectors/spectrum/spectrum.ts @@ -1,11 +1,8 @@ import { SpectrumConfig } from './spectrum.config'; import { Ergo } from '../../chains/ergo/ergo'; -import { - ErgoAccount, - ErgoAsset, -} from '../../chains/ergo/interfaces/ergo.interface'; -import { Trade } from 'swap-router-sdk'; +import { ErgoAsset } from '../../chains/ergo/interfaces/ergo.interface'; import { BigNumber } from 'bignumber.js'; +import { PriceRequest, TradeRequest } from '../../amm/amm.requests'; export class Spectrum { private static _instances: { [name: string]: Spectrum }; @@ -63,51 +60,22 @@ export class Spectrum { return this._gasLimitEstimate; } - /** - * Given the amount of `baseToken` to put into a transaction, calculate the - * amount of `quoteToken` that can be expected from the transaction. - * - * This is typically used for calculating token sell prices. - * - * @param baseToken Token input for the transaction - * @param quoteToken Output from the transaction - * @param amount Amount of `baseToken` to put into the transaction - */ - async estimateSellTrade( - baseToken: string, - quoteToken: string, - amount: BigNumber, - allowedSlippage?: string, - ) { - return this.ergo.estimateSell( - baseToken, - quoteToken, - amount, - Number(allowedSlippage), - ); - } - /** * Given the amount of `baseToken` desired to acquire from a transaction, * calculate the amount of `quoteToken` needed for the transaction. * - * This is typically used for calculating token buy prices. + * This is typically used for calculating token prices. * * @param quoteToken Token input for the transaction * @param baseToken Token output from the transaction * @param amount Amount of `baseToken` desired from the transaction */ - async estimateBuyTrade( - baseToken: string, - quoteToken: string, - amount: BigNumber, - allowedSlippage?: string, - ) { - return this.ergo.estimateBuy( - baseToken, - quoteToken, - amount, - Number(allowedSlippage), + async estimateTrade(req: PriceRequest) { + return this.ergo.estimate( + req.base, + req.quote, + BigNumber(req.amount), + Number(req.allowedSlippage), ); } @@ -117,19 +85,18 @@ export class Spectrum { * @param wallet Wallet * @param trade Expected trade */ - async executeTrade( - wallet: ErgoAccount, - trade: Trade, - allowedSlippage?: string, - ) { - return this.ergo.buy( - wallet, - trade[0].aTokenSlug, - trade[0].bTokenSlug, - trade[0].aTokenAmount, - wallet.address, - wallet.address, - Number(allowedSlippage), + async executeTrade(req: TradeRequest) { + const account = this.ergo.getAccountFromMnemonic( + req.mnemonic as unknown as string, + ); + return this.ergo.swap( + account, + req.base, + req.quote, + BigNumber(req.amount), + req.address, + req.address, + Number(req.allowedSlippage), ); } } diff --git a/src/services/connection-manager.ts b/src/services/connection-manager.ts index 2f81c40ab4..09d7c8898d 100644 --- a/src/services/connection-manager.ts +++ b/src/services/connection-manager.ts @@ -259,9 +259,9 @@ export async function getConnector( connectorInstance = QuipuSwap.getInstance(network); } else if (chain === 'ethereum' && connector === 'carbonamm') { connectorInstance = Carbonamm.getInstance(chain, network); - } else if(chain === 'ergo' && connector === 'spectrum') { + } else if (chain === 'ergo' && connector === 'spectrum') { connectorInstance = Spectrum.getInstance(chain, network); - }else { + } else { throw new Error('unsupported chain or connector'); } diff --git a/src/services/wallet/wallet.controllers.ts b/src/services/wallet/wallet.controllers.ts index 109631bdb8..93011ec386 100644 --- a/src/services/wallet/wallet.controllers.ts +++ b/src/services/wallet/wallet.controllers.ts @@ -53,7 +53,7 @@ export async function mkdirIfDoesNotExist(path: string): Promise { } export async function addWallet( - req: AddWalletRequest + req: AddWalletRequest, ): Promise { const passphrase = ConfigManagerCertPassphrase.readPassphrase(); if (!passphrase) { @@ -68,7 +68,7 @@ export async function addWallet( throw new HttpException( 500, ACCOUNT_NOT_SPECIFIED_ERROR_MESSAGE(), - ACCOUNT_NOT_SPECIFIED_CODE + ACCOUNT_NOT_SPECIFIED_CODE, ); } } @@ -80,7 +80,7 @@ export async function addWallet( throw new HttpException( 500, UNKNOWN_KNOWN_CHAIN_ERROR_MESSAGE(req.chain), - UNKNOWN_CHAIN_ERROR_CODE + UNKNOWN_CHAIN_ERROR_CODE, ); } throw e; @@ -94,47 +94,47 @@ export async function addWallet( address = connection.getWalletFromPrivateKey(req.privateKey).address; encryptedPrivateKey = await connection.encrypt( req.privateKey, - passphrase + passphrase, ); } else if (connection instanceof Xdc) { address = convertXdcAddressToEthAddress( - connection.getWalletFromPrivateKey(req.privateKey).address + connection.getWalletFromPrivateKey(req.privateKey).address, ); encryptedPrivateKey = await connection.encrypt( req.privateKey, - passphrase + passphrase, ); } else if (connection instanceof Cosmos) { const wallet = await (connection as Cosmos).getAccountsfromPrivateKey( req.privateKey, - 'cosmos' + 'cosmos', ); address = wallet.address; encryptedPrivateKey = await (connection as Cosmos).encrypt( req.privateKey, - passphrase + passphrase, ); } else if (connection instanceof Osmosis) { const wallet = await (connection as Osmosis).getAccountsfromPrivateKey( req.privateKey, - 'osmo' + 'osmo', ); address = wallet.address; encryptedPrivateKey = await (connection as Osmosis).encrypt( req.privateKey, - passphrase + passphrase, ); } else if (connection instanceof Near) { address = ( await connection.getWalletFromPrivateKey( req.privateKey, - req.address + req.address, ) ).accountId; encryptedPrivateKey = connection.encrypt(req.privateKey, passphrase); } else if (connection instanceof Tezos) { const tezosWallet = await connection.getWalletFromPrivateKey( - req.privateKey + req.privateKey, ); address = await tezosWallet.signer.publicKeyHash(); encryptedPrivateKey = connection.encrypt(req.privateKey, passphrase); @@ -147,7 +147,7 @@ export async function addWallet( encryptedPrivateKey = await connection.encrypt( mnemonic, accountNumber, - address + address, ); } else { throw new Error('Kujira wallet requires an account number.'); @@ -156,16 +156,13 @@ export async function addWallet( address = connection.getWalletFromSeed(req.privateKey).classicAddress; encryptedPrivateKey = await connection.encrypt( req.privateKey, - passphrase + passphrase, ); } else if (connection instanceof Ergo) { const account = connection.getAccountFromMnemonic(req.privateKey); - console.log(account) + console.log(account); address = account.address; - encryptedPrivateKey = await connection.encrypt( - req.privateKey, - passphrase, - ); + encryptedPrivateKey = connection.encrypt(req.privateKey, passphrase); console.log(encryptedPrivateKey); } @@ -176,7 +173,7 @@ export async function addWallet( throw new HttpException( 500, ERROR_RETRIEVING_WALLET_ADDRESS_ERROR_MESSAGE(req.privateKey), - ERROR_RETRIEVING_WALLET_ADDRESS_ERROR_CODE + ERROR_RETRIEVING_WALLET_ADDRESS_ERROR_CODE, ); } const path = `${walletPath}/${req.chain}`; @@ -191,20 +188,20 @@ export async function removeWallet(req: RemoveWalletRequest): Promise { } export async function signMessage( - req: WalletSignRequest + req: WalletSignRequest, ): Promise { if (req.chain === 'tezos') { const chain: Tezosish = await getInitializedChain(req.chain, req.network); const wallet = await chain.getWallet(req.address); return { signature: (await wallet.signer.sign('0x03' + req.message)).sbytes.slice( - 4 + 4, ), }; } else { const chain: Ethereumish = await getInitializedChain( req.chain, - req.network + req.network, ); const wallet = await chain.getWallet(req.address); return { signature: await wallet.signMessage(req.message) }; From 768e52cbae925aa1331f7ce311a1e6ee6924535b Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Fri, 5 Jul 2024 05:23:35 +0330 Subject: [PATCH 070/132] balance fixed --- src/chains/ergo/ergo.controller.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/chains/ergo/ergo.controller.ts b/src/chains/ergo/ergo.controller.ts index bc82aa73df..c51ece9761 100644 --- a/src/chains/ergo/ergo.controller.ts +++ b/src/chains/ergo/ergo.controller.ts @@ -14,7 +14,7 @@ import { PoolResponse, TransferRequest, } from './interfaces/requests.interface'; -import { TokensRequest } from '../../network/network.requests'; +import { BalanceResponse, TokensRequest } from '../../network/network.requests'; import { ErgoBoxAsset } from './interfaces/ergo.interface'; export class ErgoController { @@ -34,17 +34,21 @@ export class ErgoController { return await ergo.getTx(req.txId); } - static async balances(chain: Ergo, request: BalanceRequest) { + static async balances( + chain: Ergo, + request: BalanceRequest, + ): Promise { if (!chain.ready) { await chain.init(); } const address = chain.getAccountFromMnemonic(request.privateKey); const utxos = await chain.getAddressUnspentBoxes(address.address); const { balance, assets } = chain.getBalance(utxos); - return { - balance, - assets, + network: chain.network, + timestamp: Date.now(), + latency: 0, + balances: { ERG: balance.toString(), ...assets }, }; } From 5ef67809a3f19f1c8eadb2b94181f4ac152a4f40 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Sat, 6 Jul 2024 18:07:44 +0330 Subject: [PATCH 071/132] [fix]: fix sum of assets for each tokenId --- src/chains/ergo/ergo.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 869ddb29bc..1ac849a8af 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -383,7 +383,9 @@ export class Ergo { utxos.forEach((box) => { box.assets.forEach((asset) => { if (Object.keys(assets).includes(asset.tokenId)) - assets[asset.tokenId].plus(BigNumber(asset.amount)); + assets[asset.tokenId] = assets[asset.tokenId].plus( + BigNumber(asset.amount), + ); else assets[asset.tokenId] = BigNumber(asset.amount); }); }); From ff288fca026cbffa86cfce7b08971e9d535772c5 Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Sat, 6 Jul 2024 19:54:22 +0330 Subject: [PATCH 072/132] balance fixed --- src/chains/ergo/ergo.controller.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/chains/ergo/ergo.controller.ts b/src/chains/ergo/ergo.controller.ts index c51ece9761..94b772df23 100644 --- a/src/chains/ergo/ergo.controller.ts +++ b/src/chains/ergo/ergo.controller.ts @@ -41,8 +41,7 @@ export class ErgoController { if (!chain.ready) { await chain.init(); } - const address = chain.getAccountFromMnemonic(request.privateKey); - const utxos = await chain.getAddressUnspentBoxes(address.address); + const utxos = await chain.getAddressUnspentBoxes(request.address); const { balance, assets } = chain.getBalance(utxos); return { network: chain.network, From 3576b8b1a478fc8afdf5c2a78c0ecce4f4369192 Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Sat, 6 Jul 2024 20:20:53 +0330 Subject: [PATCH 073/132] tokens decimal applied to balance values --- src/chains/ergo/ergo.controller.ts | 46 +++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/src/chains/ergo/ergo.controller.ts b/src/chains/ergo/ergo.controller.ts index 94b772df23..0045f112be 100644 --- a/src/chains/ergo/ergo.controller.ts +++ b/src/chains/ergo/ergo.controller.ts @@ -16,6 +16,7 @@ import { } from './interfaces/requests.interface'; import { BalanceResponse, TokensRequest } from '../../network/network.requests'; import { ErgoBoxAsset } from './interfaces/ergo.interface'; +import { AllowancesRequest, AllowancesResponse } from '../chain.requests'; export class ErgoController { static async pool(ergo: Ergo, req: PoolRequest): Promise { @@ -43,11 +44,22 @@ export class ErgoController { } const utxos = await chain.getAddressUnspentBoxes(request.address); const { balance, assets } = chain.getBalance(utxos); + const new_assets: Record = {}; + Object.keys(assets).forEach((value) => { + const temp = chain.storedAssetList.find( + (asset) => asset.tokenId === value, + ); + if (temp) { + new_assets[temp.symbol] = assets[value] + .div(Math.pow(10, temp.decimals)) + .toString(); + } + }); return { network: chain.network, timestamp: Date.now(), latency: 0, - balances: { ERG: balance.toString(), ...assets }, + balances: { ERG: balance.div(Math.pow(10, 9)).toString(), ...new_assets }, }; } @@ -97,4 +109,36 @@ export class ErgoController { .payMinFee() .build(); } + + static async allowances( + chain: Ergo, + request: AllowancesRequest, + ): Promise { + if (!chain.ready) { + await chain.init(); + } + const utxos = await chain.getAddressUnspentBoxes(request.address); + const { balance, assets } = chain.getBalance(utxos); + const new_assets: Record = {}; + Object.keys(assets).forEach((value) => { + const temp = chain.storedAssetList.find( + (asset) => asset.tokenId === value, + ); + if (temp) { + new_assets[temp.symbol] = assets[value] + .div(Math.pow(10, temp.decimals)) + .toString(); + } + }); + return { + network: chain.network, + timestamp: Date.now(), + latency: 0, + spender: request.spender, + approvals: { + ERG: balance.div(Math.pow(10, 9)).toString(), + ...new_assets, + }, + }; + } } From 9a93b29bee72dafbbd36297b2e3f6c1fe60e3115 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Sun, 7 Jul 2024 09:40:18 +0330 Subject: [PATCH 074/132] [fix]: fix route to get each asset name --- src/chains/ergo/ergo.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 1ac849a8af..e6e74ab912 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -50,7 +50,7 @@ class Pool extends AmmPool { constructor(public pool: AmmPool) { super(pool.id, pool.lp, pool.x, pool.y, pool.poolFeeNum); - this._name = `${this.x.asset.name}/${this.y.asset.name}`; + this._name = `${this.pool.x.asset.name}/${this.pool.y.asset.name}`; } public get name() { From 90e9b8192929196ed5b123e5183f55962f3788a2 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Wed, 10 Jul 2024 15:41:30 +0330 Subject: [PATCH 075/132] update [unit-test]: update unit tests for "Ergo" based on new network names --- test/chains/ergo/ergo.test.ts | 87 ++++++++++++++++------------------- 1 file changed, 39 insertions(+), 48 deletions(-) diff --git a/test/chains/ergo/ergo.test.ts b/test/chains/ergo/ergo.test.ts index ac6219cb21..a6901a3a65 100644 --- a/test/chains/ergo/ergo.test.ts +++ b/test/chains/ergo/ergo.test.ts @@ -43,7 +43,7 @@ const patchGetErgoConfig = (imputNetwork: string) => { explorerDEXURL: 'ergo.networks.' + imputNetwork + '.explorerDEXURL', timeOut: 1000, networkPrefix: - imputNetwork === 'Mainnet' + imputNetwork === 'mainnet' ? NetworkPrefix.Mainnet : NetworkPrefix.Testnet, minTxFee: 2000, @@ -129,11 +129,11 @@ const patchGetTokens = () => { }; beforeEach(() => { - // Arrange: Mock the return value of getErgoConfig to simulate Mainnet configuration before each test - patchGetErgoConfig('Mainnet'); + // Arrange: Mock the return value of getErgoConfig to simulate mainnet configuration before each test + patchGetErgoConfig('mainnet'); - // Arrange: Create a new instance of Ergo with 'Mainnet' configuration before each test - ergo = new Ergo('Mainnet'); + // Arrange: Create a new instance of Ergo with 'mainnet' configuration before each test + ergo = new Ergo('mainnet'); }); // Clean up mocks after each test afterEach(() => { @@ -142,11 +142,11 @@ afterEach(() => { }); describe('Ergo', () => { - it('Should initialize with Mainnet configuration', () => { + it('Should initialize with mainnet configuration', () => { // Assert: Validate the initialization state of Ergo instance expect(ergo).toBeDefined(); expect(ergo['_assetMap']).toEqual({}); - expect(ergo['_network']).toEqual('Mainnet'); + expect(ergo['_network']).toEqual('mainnet'); expect(ergo['_networkPrefix']).toEqual(NetworkPrefix.Mainnet); expect(ergo['_node']).toBeInstanceOf(NodeService); expect(ergo['_explorer']).toBeInstanceOf(Explorer); @@ -158,17 +158,17 @@ describe('Ergo', () => { expect(ergo['ammPools']).toEqual([]); }); - it('Should initialize with Mainnet configuration', () => { - // Arrange: Mock the return value of getErgoConfig to simulate Testnet configuration - patchGetErgoConfig('Testnet'); + it('Should initialize with testnet configuration', () => { + // Arrange: Mock the return value of getErgoConfig to simulate testnet configuration + patchGetErgoConfig('testnet'); - // Act: Create a new instance of Ergo with 'Testnet' configuration - const ergo = new Ergo('Testnet'); + // Act: Create a new instance of Ergo with 'testnet' configuration + const ergo = new Ergo('testnet'); // Assert: Validate the initialization state of Ergo instance expect(ergo).toBeDefined(); expect(ergo['_assetMap']).toEqual({}); - expect(ergo['_network']).toEqual('Testnet'); + expect(ergo['_network']).toEqual('testnet'); expect(ergo['_networkPrefix']).toEqual(NetworkPrefix.Testnet); expect(ergo['_node']).toBeInstanceOf(NodeService); expect(ergo['_explorer']).toBeInstanceOf(Explorer); @@ -185,27 +185,23 @@ describe('Ergo', () => { // Assert: Validate the initialization state of node instance and check the returned value expect(ergo.node).toBeInstanceOf(NodeService); expect(ergo.node).toEqual({ - nodeURL: 'ergo.networks.Mainnet.nodeURL', + nodeURL: 'ergo.networks.mainnet.nodeURL', timeout: 1000, }); }); }); describe('get network', () => { - it('Should return the correct network when network is Mainnet', () => { - // Assert: Validate the return value - expect(ergo.network).toBe('Mainnet'); + it('Should return the correct network when network is mainnet', () => { + expect(ergo.network).toBe('mainnet'); }); - it('Should return the correct network when network is Testnet', () => { - // Arrange: Mock the return value of getErgoConfig to simulate Testnet configuration - patchGetErgoConfig('Testnet'); + it('Should return the correct network when network is testnet', () => { + patchGetErgoConfig('testnet'); - // Act: Create a new instance of Ergo with 'Testnet' configuration - ergo = new Ergo('Testnet'); + ergo = new Ergo('testnet'); - // Assert: Validate the return value - expect(ergo.network).toBe('Testnet'); + expect(ergo.network).toBe('testnet'); }); }); @@ -229,14 +225,9 @@ describe('Ergo', () => { describe('ready', () => { it('Should return the ready state', () => { - // Arrange: Initially, the ready state should be false - expect(ergo.ready).toBe(false); - - // Act: Manually set the _ready state to true + expect(ergo.ready()).toBe(false); ergo['_ready'] = true; - - // Assert: Now, the ready state should be true - expect(ergo.ready).toBe(true); + expect(ergo.ready()).toBe(true); }); }); @@ -252,7 +243,7 @@ describe('Ergo', () => { // Assert: Ensure the loadAssets & loadPools methods were called during initialization expect(ergo['loadAssets']).toHaveBeenCalled(); expect(ergo['loadPools']).toHaveBeenCalled(); - expect(ergo.ready).toBe(true); + expect(ergo.ready()).toBe(true); }); }); @@ -264,11 +255,11 @@ describe('Ergo', () => { }); describe('getInstance', () => { - const mockNetwork = 'Testnet'; + const mockNetwork = 'testnet'; beforeEach(() => { - // Arrange: Mock the function to get the configuration for the 'Testnet' network - patchGetErgoConfig('Testnet'); + // Arrange: Mock the function to get the configuration for the 'testnet' network + patchGetErgoConfig('testnet'); // Arrange: Clear the singleton and mock instances Ergo['_instances'] = undefined as any; }); @@ -305,7 +296,7 @@ describe('Ergo', () => { it('Should throw an error if an unexpected network is provided', () => { // Act and Assert: Expect that calling getInstance with an invalid network throws an error expect(() => Ergo.getInstance('invalidNetwork')).toThrow( - 'network should be `Mainnet` or `Testnet`', + 'network should be `mainnet` or `testnet`', ); }); }); @@ -316,15 +307,15 @@ describe('Ergo', () => { beforeEach(() => { // Arrange: Create mock Ergo instances - mockErgoInstance1 = new Ergo('Testnet') as any; - mockErgoInstance2 = new Ergo('Mainnet') as any; + mockErgoInstance1 = new Ergo('testnet') as any; + mockErgoInstance2 = new Ergo('mainnet') as any; // Arrange: Initialize the _instances LRUCache with mock instances Ergo['_instances'] = new LRUCache({ max: 10, }); - Ergo['_instances'].set('Testnet', mockErgoInstance1); - Ergo['_instances'].set('Mainnet', mockErgoInstance2); + Ergo['_instances'].set('testnet', mockErgoInstance1); + Ergo['_instances'].set('mainnet', mockErgoInstance2); }); it('Should return all connected instances', () => { @@ -333,11 +324,11 @@ describe('Ergo', () => { // Assert: Expect the connected instances to match the mock instances expect(Object.keys(connectedInstances).sort()).toEqual([ - 'Mainnet', - 'Testnet', + 'mainnet', + 'testnet', ]); - expect(connectedInstances['Testnet']).toBe(mockErgoInstance1); - expect(connectedInstances['Mainnet']).toBe(mockErgoInstance2); + expect(connectedInstances['testnet']).toBe(mockErgoInstance1); + expect(connectedInstances['mainnet']).toBe(mockErgoInstance2); }); it('Should return an empty object if there are no instances', () => { @@ -359,11 +350,11 @@ describe('Ergo', () => { const connectedInstances = Ergo.getConnectedInstances(); // Assert: Expect the valid instances to be returned and invalid instances to be excluded expect(Object.keys(connectedInstances).sort()).toEqual([ - 'Mainnet', - 'Testnet', + 'mainnet', + 'testnet', ]); - expect(connectedInstances['Testnet']).toBe(mockErgoInstance1); - expect(connectedInstances['Mainnet']).toBe(mockErgoInstance2); + expect(connectedInstances['testnet']).toBe(mockErgoInstance1); + expect(connectedInstances['mainnet']).toBe(mockErgoInstance2); expect(connectedInstances['']).toBeUndefined(); }); }); From a6ae230a63603f4d463a0557e662645cbfdd86ac Mon Sep 17 00:00:00 2001 From: satiparpar Date: Wed, 10 Jul 2024 16:42:25 +0330 Subject: [PATCH 076/132] add [unit-test]: Implement unit tests for "ergo.utils" => "getBaseInputParameters" method --- test/chains/ergo/ergo.utils.test.ts | 103 ++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 test/chains/ergo/ergo.utils.test.ts diff --git a/test/chains/ergo/ergo.utils.test.ts b/test/chains/ergo/ergo.utils.test.ts new file mode 100644 index 0000000000..f605524728 --- /dev/null +++ b/test/chains/ergo/ergo.utils.test.ts @@ -0,0 +1,103 @@ +import * as ergo_utils from '../../../src/chains/ergo/ergo.util'; + +describe('getBaseInputParameters', () => { + const pool = { + id: '1b694b15467c62f0cd4525e368dbdea2329c713aa200b73df4a622e950551b40', + lp: { + withAmount: (_sth: any) => { + return { + asset: { + id: 'lpId', + name: 'lpNmae', + decimals: 0, + }, + amount: BigInt(922336941265222), + }; + }, + }, + x: { + withAmount: (_sth: any) => { + return { + asset: { + id: 'xId', + name: 'xNmae', + decimals: 9, + }, + amount: BigInt(752313805260857), + }; + }, + asset: { + id: 'xId', + name: 'xNmae', + decimals: 9, + }, + }, + y: { + withAmount: (_sth: any) => { + return { + asset: { + id: 'yId', + name: 'yNmae', + decimals: 3, + }, + amount: BigInt(9322283969), + }; + }, + asset: { + id: 'yId', + name: 'yNmae', + decimals: 3, + }, + }, + outputAmount: (_sth: any, _slippage: any) => { + return 1; + }, + }; + + it('Should be defined', () => { + console.log(pool.lp.withAmount('')); + expect(ergo_utils.getBaseInputParameters).toBeDefined(); + }); + + it('Should calculate base input parameters when inputAmount.asset.id matches pool.x.asset.id', () => { + const inputAmount = { asset: { id: 'xId' }, amount: 100 }; + const slippage = 0.02; + + const result: any = ergo_utils.getBaseInputParameters(pool as any, { + inputAmount, + slippage, + }); + + expect(result.baseInput).toEqual({ + asset: { + id: 'xId', + name: 'xNmae', + decimals: 9, + }, + amount: BigInt(752313805260857), + }); + expect(result.baseInputAmount).toEqual(100); + expect(result.minOutput).toEqual(1); + }); + + it('should calculate base input parameters when inputAmount.asset.id does not match pool.x.asset.id', () => { + const inputAmount = { asset: { id: 'yId' }, amount: 100 }; + const slippage = 0.02; + + const result: any = ergo_utils.getBaseInputParameters(pool as any, { + inputAmount, + slippage, + }); + + expect(result.baseInput).toEqual({ + asset: { + id: 'yId', + name: 'yNmae', + decimals: 3, + }, + amount: BigInt(9322283969), + }); + expect(result.baseInputAmount).toEqual(100); + expect(result.minOutput).toEqual(1); + }); +}); From aa38f6d02886cd29275c8caaab2a17a44d4f04fd Mon Sep 17 00:00:00 2001 From: satiparpar Date: Thu, 11 Jul 2024 10:44:51 +0330 Subject: [PATCH 077/132] add [unit-test]: Implement unit tests for "ergo.utils" => "getInputs" method --- test/chains/ergo/ergo.utils.test.ts | 85 ++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/test/chains/ergo/ergo.utils.test.ts b/test/chains/ergo/ergo.utils.test.ts index f605524728..c31d4ab27f 100644 --- a/test/chains/ergo/ergo.utils.test.ts +++ b/test/chains/ergo/ergo.utils.test.ts @@ -1,4 +1,22 @@ +import { + BoxSelection, + DefaultBoxSelector, + InsufficientInputs, +} from '@patternglobal/ergo-sdk'; import * as ergo_utils from '../../../src/chains/ergo/ergo.util'; +import { + minValueForOrder, + minValueForSetup, +} from '@patternglobal/ergo-dex-sdk'; + +jest.mock('@patternglobal/ergo-dex-sdk', () => ({ + minValueForOrder: jest.fn().mockReturnValue(BigInt(1)), + minValueForSetup: jest.fn(), +})); + +jest.mock('@patternglobal/ergo-dex-sdk/build/main/utils/makeTarget', () => ({ + makeTarget: jest.fn().mockReturnValue({} as any), +})); describe('getBaseInputParameters', () => { const pool = { @@ -55,7 +73,6 @@ describe('getBaseInputParameters', () => { }; it('Should be defined', () => { - console.log(pool.lp.withAmount('')); expect(ergo_utils.getBaseInputParameters).toBeDefined(); }); @@ -101,3 +118,69 @@ describe('getBaseInputParameters', () => { expect(result.minOutput).toEqual(1); }); }); + +describe('getInputs', () => { + const utxos: any = []; + const assets: any = []; + const fees: any = { + minerFee: BigInt(1), + uiFee: BigInt(1), + exFee: BigInt(1), + }; + const ignoreMinBoxValue = false; + const setup = false; + beforeEach(() => { + jest.clearAllMocks(); + }); + it('Should be defined', () => { + expect(ergo_utils.getInputs).toBeDefined(); + }); + it('Should not call minValueForSetup method when setup is false', () => { + jest + .spyOn(DefaultBoxSelector, 'select') + .mockReturnValue({} as unknown as BoxSelection); + ergo_utils.getInputs(utxos, assets, fees, ignoreMinBoxValue, setup); + expect(minValueForOrder).toHaveBeenCalledWith( + fees.minerFee, + fees.uiFee, + fees.exFee, + ); + expect(minValueForSetup).not.toHaveBeenCalledWith( + fees.minerFee, + fees.uiFee, + ); + }); + it('Should call minValueForSetup method with correct parameters when setup is true', () => { + jest + .spyOn(DefaultBoxSelector, 'select') + .mockReturnValue({} as unknown as BoxSelection); + const setup = true; + ergo_utils.getInputs(utxos, assets, fees, ignoreMinBoxValue, setup); + expect(minValueForOrder).toHaveBeenCalledWith( + fees.minerFee, + fees.uiFee, + fees.exFee, + ); + expect(minValueForSetup).toHaveBeenCalledWith(fees.minerFee, fees.uiFee); + }); + it('Should map on utxos and cast the related types to string and return the data correctly', () => { + jest + .spyOn(DefaultBoxSelector, 'select') + .mockReturnValue({} as unknown as BoxSelection); + const utxos: any = [{ value: 1, assets: [{ amount: 2 }] }]; + const result = ergo_utils.getInputs(utxos, assets, fees); + expect(DefaultBoxSelector.select).toHaveBeenCalledWith( + [{ value: '1', assets: [{ amount: '2' }] }], + {}, + ); + expect(result).toEqual({}); + }); + it('Should throw new Error when inputs are instanceof InsufficientInputs', () => { + const err: InsufficientInputs = new InsufficientInputs(''); + jest.spyOn(DefaultBoxSelector, 'select').mockReturnValue(err); + + expect(() => ergo_utils.getInputs(utxos, assets, fees)).toThrow( + `Error in getInputs function: InsufficientInputs -> ${err}`, + ); + }); +}); From 684ee194829593b52dfa81f57c077e7ab5398fa2 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Thu, 11 Jul 2024 11:02:14 +0330 Subject: [PATCH 078/132] add [unit-test]: Implement unit tests for "ergo.utils" => "getTxContext" method --- test/chains/ergo/ergo.utils.test.ts | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/test/chains/ergo/ergo.utils.test.ts b/test/chains/ergo/ergo.utils.test.ts index c31d4ab27f..b2fb0ee04d 100644 --- a/test/chains/ergo/ergo.utils.test.ts +++ b/test/chains/ergo/ergo.utils.test.ts @@ -8,9 +8,10 @@ import { minValueForOrder, minValueForSetup, } from '@patternglobal/ergo-dex-sdk'; +import { makeTarget } from '@patternglobal/ergo-dex-sdk/build/main/utils/makeTarget'; jest.mock('@patternglobal/ergo-dex-sdk', () => ({ - minValueForOrder: jest.fn().mockReturnValue(BigInt(1)), + minValueForOrder: jest.fn().mockReturnValue(BigInt(100000)), minValueForSetup: jest.fn(), })); @@ -163,6 +164,11 @@ describe('getInputs', () => { ); expect(minValueForSetup).toHaveBeenCalledWith(fees.minerFee, fees.uiFee); }); + it('Should subtract minFeeForOrder with MinBoxValue when ignoreMinBoxValue is true', () => { + const ignoreMinBoxValue = true; + ergo_utils.getInputs(utxos, assets, fees, ignoreMinBoxValue, setup); + expect(makeTarget).toHaveBeenCalledWith(assets, BigInt(40000)); + }); it('Should map on utxos and cast the related types to string and return the data correctly', () => { jest .spyOn(DefaultBoxSelector, 'select') @@ -184,3 +190,24 @@ describe('getInputs', () => { ); }); }); + +describe('getTxContext', () => { + const inputs: any = {}; + const network: any = {}; + const address: string = 'address'; + const minerFee: bigint = BigInt(1); + it('Should be defined', () => { + expect(ergo_utils.getTxContext).toBeDefined(); + }); + + it('Should return correct data', () => { + const result = ergo_utils.getTxContext(inputs, network, address, minerFee); + expect(result).toEqual({ + inputs, + selfAddress: address, + changeAddress: address, + feeNErgs: minerFee, + network, + }); + }); +}); From 5ddea9cb5885ee2ba55f1f1c0ff6d8f895903ee6 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Thu, 11 Jul 2024 12:03:50 +0330 Subject: [PATCH 079/132] add [unit-test]: Implement unit tests for "Ergo" => "getAccountFromMnemonic" method --- test/chains/ergo/ergo.test.ts | 59 ++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/test/chains/ergo/ergo.test.ts b/test/chains/ergo/ergo.test.ts index a6901a3a65..50020f9c84 100644 --- a/test/chains/ergo/ergo.test.ts +++ b/test/chains/ergo/ergo.test.ts @@ -4,6 +4,9 @@ import { SecretKeys, Wallet, Address, + Mnemonic, + ExtSecretKey, + DerivationPath, } from 'ergo-lib-wasm-nodejs'; import { Ergo } from '../../../src/chains/ergo/ergo'; import { patch, unpatch } from '../../../test/services/patch'; @@ -129,10 +132,7 @@ const patchGetTokens = () => { }; beforeEach(() => { - // Arrange: Mock the return value of getErgoConfig to simulate mainnet configuration before each test patchGetErgoConfig('mainnet'); - - // Arrange: Create a new instance of Ergo with 'mainnet' configuration before each test ergo = new Ergo('mainnet'); }); // Clean up mocks after each test @@ -142,6 +142,14 @@ afterEach(() => { }); describe('Ergo', () => { + it('Should be defined', () => { + expect(ergo).toBeDefined(); + }); + it('Should throw new Error if network is not mainnet or testnet', () => { + expect(() => new Ergo('invalidNetwork')).toThrow( + 'network should be `mainnet` or `testnet`', + ); + }); it('Should initialize with mainnet configuration', () => { // Assert: Validate the initialization state of Ergo instance expect(ergo).toBeDefined(); @@ -231,6 +239,14 @@ describe('Ergo', () => { }); }); + describe('getNetworkHeight', () => { + it('Should call getNetworkHeight method from node', async () => { + jest.spyOn(ergo['_node'], 'getNetworkHeight').mockResolvedValue(1); + await ergo.getNetworkHeight(); + expect(ergo['_node'].getNetworkHeight).toHaveBeenCalled(); + }); + }); + describe('init', () => { it('Should initialize assets and pools in init method', async () => { // Arrange: Mock the loadAssets & loadPools methods to return a fixed value @@ -426,7 +442,7 @@ describe('Ergo', () => { }); describe('getAccountFromSecretKey', () => { - it('Should return an account with address and wallet', () => { + it('Should return an account with address and wallet from secret key', () => { const secret = '591811a0d6361f18e42549b32e65b98c9a63d6aad369d1056a97ca81f2a980d5'; patchFrom_secrets(); @@ -453,6 +469,41 @@ describe('Ergo', () => { }); }); + describe('getAccountFromMnemonic', () => { + it('Should return an account with address and wallet from mnemonic', () => { + patchFrom_secrets(); + patchTo_base58(); + const mockGetAddress = jest.fn().mockReturnValue(new Address()); + const mockSecretKeyInstance = { + get_address: mockGetAddress, + } as unknown as SecretKey; + jest + .spyOn(SecretKey, 'dlog_from_bytes') + .mockReturnValue(mockSecretKeyInstance); + + jest.spyOn(DerivationPath, 'new').mockReturnValue({} as any); + jest.spyOn(Mnemonic, 'to_seed').mockReturnValue(1 as any); + jest.spyOn(ExtSecretKey, 'derive_master').mockReturnValue({ + derive: jest.fn().mockReturnValue({ + secret_key_bytes: jest.fn().mockReturnValue('uint*Array' as any), + }), + } as any); + const result = ergo.getAccountFromMnemonic('mnemonic'); + expect(result.address).toBe('testAddress'); + expect(result.wallet).toBe('testWallet'); + expect(result.prover).toEqual({ + wallet: 'testWallet', + nodeService: { + nodeURL: 'ergo.networks.mainnet.nodeURL', + timeout: 1000, + }, + }); + expect(DerivationPath.new).toHaveBeenCalledWith(0, new Uint32Array([0])); + // 1 as return value from Mnemonic.to_seed function + expect(ExtSecretKey.derive_master).toHaveBeenCalledWith(1); + }); + }); + describe('encrypt', () => { it('Should encrypt a secret with a given password', () => { // Arrange: Set up the secret and password From a5ea3b71879785d2340f7a6725435e6baaeb1077 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Thu, 11 Jul 2024 13:57:36 +0330 Subject: [PATCH 080/132] add & update [unit-test]: Implement unit tests for "Ergo" => "getBalance" & "getAssetBalance" methods --- test/chains/ergo/ergo.test.ts | 107 ++++++++++++++++++---------------- 1 file changed, 58 insertions(+), 49 deletions(-) diff --git a/test/chains/ergo/ergo.test.ts b/test/chains/ergo/ergo.test.ts index 50020f9c84..ba79df89dc 100644 --- a/test/chains/ergo/ergo.test.ts +++ b/test/chains/ergo/ergo.test.ts @@ -22,6 +22,7 @@ import { } from '../../../src/chains/ergo/interfaces/ergo.interface'; import LRUCache from 'lru-cache'; import { makeNativePools } from '@patternglobal/ergo-dex-sdk'; +import { BigNumber } from 'bignumber.js'; jest.mock('@patternglobal/ergo-dex-sdk', () => ({ AmmPool: jest.fn(), @@ -380,7 +381,6 @@ describe('Ergo', () => { // Arrange: Mock the getNetworkHeight method to return a fixed value jest.spyOn(ergo['_node'], 'getNetworkHeight').mockResolvedValue(17); - // Act: Call the getCurrentBlockNumber method const blockNumber = await ergo.getCurrentBlockNumber(); // Assert: Validate the returned block number @@ -412,10 +412,8 @@ describe('Ergo', () => { .mockResolvedValueOnce(mockUnspentBoxesPage1) .mockResolvedValueOnce(mockUnspentBoxesPage2) .mockResolvedValueOnce(mockUnspentBoxesPage3); - // Act: Call the getAddressUnspentBoxes method const result = await ergo.getAddressUnspentBoxes(mockAddress); - // Assert: Validate that an empty array is returned expect(result).toEqual([ { boxId: 'box1' }, @@ -447,7 +445,6 @@ describe('Ergo', () => { '591811a0d6361f18e42549b32e65b98c9a63d6aad369d1056a97ca81f2a980d5'; patchFrom_secrets(); patchTo_base58(); - // Arrange: Mock get_address method const mockGetAddress = jest.fn().mockReturnValue(new Address()); const mockSecretKeyInstance = { @@ -460,9 +457,7 @@ describe('Ergo', () => { const mockAdd = jest.fn(); jest.spyOn(SecretKeys.prototype, 'add').mockImplementation(mockAdd); - // Act: Call the getAccountFromSecretKey method const result = ergo.getAccountFromSecretKey(secret); - // Assert: Validate the returned address and wallet expect(result.address).toBe('testAddress'); expect(result.wallet).toBe('testWallet'); @@ -510,9 +505,7 @@ describe('Ergo', () => { const secret = 'mySecret'; const password = 'myPassword'; - // Act: Call the encrypt method const encryptedText = ergo.encrypt(secret, password); - // Assert: Verify the encrypted text format expect(encryptedText).toMatch(/^[0-9a-fA-F]{32}:[0-9a-fA-F]+$/); }); @@ -577,10 +570,8 @@ describe('Ergo', () => { const secret = 'mySecret'; const password = 'myPassword'; const encryptedText = ergo.encrypt(secret, password); - // Act: Call the decrypt method const decryptedText = ergo.decrypt(encryptedText, password); - // Assert: Verify that the decrypted text matches the original secret expect(decryptedText).toBe(secret); }); @@ -591,7 +582,6 @@ describe('Ergo', () => { const correctPassword = 'correctPassword'; const wrongPassword = 'wrongPassword'; const encryptedText = ergo.encrypt(secret, correctPassword); - // Act & Assert: Call the decrypt method with the wrong password and expect an error expect(() => { ergo.decrypt(encryptedText, wrongPassword); @@ -603,47 +593,34 @@ describe('Ergo', () => { const secret = 'mySecret'; const longPassword = 'a'.repeat(50); // 50 bytes password const encryptedText = ergo.encrypt(secret, longPassword); - // Act: Call the decrypt method const decryptedText = ergo.decrypt(encryptedText, longPassword); - // Assert: Verify that the decrypted text matches the original secret expect(decryptedText).toBe(secret); }); it('Should handle case where password is exactly 32 bytes', () => { - // Arrange: Set up the secret and a 32 bytes password, and encrypt the secret const secret = 'mySecret'; const exact32BytesPassword = 'a'.repeat(32); // 32 bytes password const encryptedText = ergo.encrypt(secret, exact32BytesPassword); - - // Act: Call the decrypt method const decryptedText = ergo.decrypt(encryptedText, exact32BytesPassword); - // Assert: Verify that the decrypted text matches the original secret expect(decryptedText).toBe(secret); }); }); describe('getAssetBalance', () => { + const account: ErgoAccount = { address: 'mockAddress' } as any; it('Should return balance as 0 when there are no unspent boxes', async () => { - // Arrange: Set up the account and asset map, and mock the getAddressUnspentBoxes method to return an empty array - const account: ErgoAccount = { address: 'mockAddress' } as any; ergo['_assetMap'] = { ASSETNAME: { tokenId: 1 }, } as any; patchGetAddressUnspentBoxes(); - - // Act: Call the getAssetBalance method const balance = await ergo.getAssetBalance(account, 'assetName'); - - // Assert: Verify that the balance is 0 expect(balance).toBe('0'); }); it('Should return balance as 0 when there are no matching assets', async () => { - // Arrange: Set up the account, asset map, and mock the getAddressUnspentBoxes method to return utxos without matching assets - const account: ErgoAccount = { address: 'mockAddress' } as any; ergo['_assetMap'] = { ASSETNAME: { tokenId: 1 }, } as any; @@ -651,17 +628,11 @@ describe('Ergo', () => { jest .spyOn(ergo, 'getAddressUnspentBoxes') .mockResolvedValue(utxos as any); - - // Act: Call the getAssetBalance method const balance = await ergo.getAssetBalance(account, 'assetName'); - - // Assert: Verify that the balance is 0 expect(balance).toBe('0'); }); it('Should return correct balance when there are matching assets', async () => { - // Arrange: Set up the account, asset map, and mock the getAddressUnspentBoxes method to return utxos with matching assets - const account: ErgoAccount = { address: 'mockAddress' } as any; ergo['_assetMap'] = { ASSETNAME: { tokenId: 1 }, } as any; @@ -672,24 +643,71 @@ describe('Ergo', () => { jest .spyOn(ergo, 'getAddressUnspentBoxes') .mockResolvedValue(utxos as any); - - // Act: Call the getAssetBalance method const balance = await ergo.getAssetBalance(account, 'assetName'); - - // Assert: Verify that the balance is correct expect(balance).toBe('300'); }); + it('Should throw an error when no ergo asset is found', async () => { + ergo['_assetMap'] = {}; + await expect(ergo.getAssetBalance(account, 'assetName')).rejects.toThrow( + `assetName not found ${ergo['_chain']} Node!`, + ); + }); it('Should throw an error when getAddressUnspentBoxes fails', async () => { - // Arrange: Set up the account and mock the getAddressUnspentBoxes method to reject with an error - const account: ErgoAccount = { address: 'mockAddress' } as any; jest .spyOn(ergo, 'getAddressUnspentBoxes') .mockRejectedValue(new Error('some error')); - - // Act & Assert: Call the getAssetBalance method and expect it to throw an error + ergo['_assetMap'] = { ASSETNAME: {} } as any; await expect(ergo.getAssetBalance(account, 'assetName')).rejects.toThrow( - `assetName not found ${ergo['_chain']} Node!`, + `problem during finding account assets ${ergo['_chain']} Node!`, + ); + }); + }); + + describe('getBalance', () => { + let utxos: any = []; + it('Should be defined', () => { + expect(ergo.getBalance).toBeDefined(); + }); + + it('Should return balance and assets when utxos is empty', () => { + const result = ergo.getBalance(utxos); + expect(result).toEqual({ assets: {}, balance: BigNumber(0) }); + }); + + it('Should calculate balance and assets correctly', () => { + utxos = [ + { + value: '1000', + assets: [ + { tokenId: 'token1', amount: '10' }, + { tokenId: 'token2', amount: '20' }, + ], + }, + { + value: '2000', + assets: [ + { tokenId: 'token1', amount: '30' }, + { tokenId: 'token3', amount: '40' }, + ], + }, + ]; + const expectedBalance = BigNumber(3000); + const expectedAssets = { + token1: BigNumber(40), + token2: BigNumber(20), + token3: BigNumber(40), + }; + const result = ergo.getBalance(utxos); + expect(result.balance.toString()).toBe(expectedBalance.toString()); + expect(result.assets.token1.toString()).toBe( + expectedAssets.token1.toString(), + ); + expect(result.assets.token2.toString()).toBe( + expectedAssets.token2.toString(), + ); + expect(result.assets.token3.toString()).toBe( + expectedAssets.token3.toString(), ); }); }); @@ -718,9 +736,7 @@ describe('Ergo', () => { describe('getAssetData', () => { it('Should return all token with the details', async () => { - // Mock getTokens method to return predefined data patchGetTokens(); - // Act & Assert: Validate the returned data structure expect(await ergo['getAssetData']()).toEqual({ name: 'Spectrum Finance Ergo Token List', @@ -755,10 +771,7 @@ describe('Ergo', () => { jest.spyOn(ergo as any, 'getPoolData').mockResolvedValue([] as any); ergo['ammPools'] = []; - // Act: Call the method under test await ergo['loadPools'](); - - // Assert: Ensure ammPools remains empty expect(ergo['ammPools']).toEqual([]); }); @@ -769,11 +782,9 @@ describe('Ergo', () => { .mockResolvedValueOnce([{ id: '1' }, { id: 2 }] as any); jest.spyOn(ergo as any, 'getPoolData').mockResolvedValueOnce([] as any); - // Act: Call the method under test ergo['ammPools'] = []; await ergo['loadPools'](); - // Assert: Verify ammPools contains expected pool data expect(ergo['ammPools']).toEqual([{ id: '1' }, { id: 2 }]); }); @@ -796,10 +807,8 @@ describe('Ergo', () => { ergo['ammPools'] = []; - // Act: Call the method under test await ergo['loadPools'](); - // Assert: Verify ammPools contains merged pool data without duplicates expect(ergo['ammPools']).toEqual([ { id: 1, name: 'Pool 1' }, { id: 2, name: 'Pool 2' }, From 6746705ea87a4cc0493fbae258f637787211a6cf Mon Sep 17 00:00:00 2001 From: satiparpar Date: Thu, 11 Jul 2024 15:25:23 +0330 Subject: [PATCH 081/132] add [unit-test]: Implement unit tests for "Ergo" => "loadPool" method --- test/chains/ergo/ergo.test.ts | 102 +++++++++++++++++++++++++++++++--- 1 file changed, 93 insertions(+), 9 deletions(-) diff --git a/test/chains/ergo/ergo.test.ts b/test/chains/ergo/ergo.test.ts index ba79df89dc..d65dcf6d8b 100644 --- a/test/chains/ergo/ergo.test.ts +++ b/test/chains/ergo/ergo.test.ts @@ -12,7 +12,7 @@ import { Ergo } from '../../../src/chains/ergo/ergo'; import { patch, unpatch } from '../../../test/services/patch'; import * as ergo_cofing from '../../../src/chains/ergo/ergo.config'; import { NodeService } from '../../../src/chains/ergo/node.service'; -import { Explorer } from '@patternglobal/ergo-sdk'; +import { Explorer, RustModule } from '@patternglobal/ergo-sdk'; import { DexService } from '../../../src/chains/ergo/dex.service'; import { ErgoController } from '../../../src/chains/ergo/ergo.controller'; import { @@ -817,15 +817,105 @@ describe('Ergo', () => { }); }); + describe('loadPool', () => { + beforeEach(() => { + jest.spyOn(RustModule, 'load').mockResolvedValue; + jest.spyOn(ergo, 'getPool').mockReturnValue({} as any); + }); + it('Should be defined', () => { + expect(ergo.loadPool).toBeDefined(); + }); + it('Should not update ammPools if pool with related id is found', async () => { + const before = ergo['ammPools'].length; + await ergo.loadPool('invalidPoolId'); + const after = ergo['ammPools'].length; + + expect(before).toEqual(after); + expect(ergo.getPool).toHaveBeenCalledWith('invalidPoolId'); + expect(makeNativePools).not.toHaveBeenCalled(); + }); + it('Should add pool to ammPools if pool is not added before', async () => { + const pool: any = { + id: '1b694b15467c62f0cd4525e368dbdea2329c713aa200b73df4a622e950551b40', + lp: { + withAmount: (_sth: any) => { + return { + asset: { + id: 'lpId', + name: 'lpNmae', + decimals: 0, + }, + amount: BigInt(922336941265222), + }; + }, + }, + x: { + withAmount: (_sth: any) => { + return { + asset: { + id: 'xId', + name: 'xNmae', + decimals: 9, + }, + amount: BigInt(752313805260857), + }; + }, + asset: { + id: 'xId', + name: 'xNmae', + decimals: 9, + }, + }, + y: { + withAmount: (_sth: any) => { + return { + asset: { + id: 'yId', + name: 'yNmae', + decimals: 3, + }, + amount: BigInt(9322283969), + }; + }, + asset: { + id: 'yId', + name: 'yNmae', + decimals: 3, + }, + }, + outputAmount: (_sth: any, _slippage: any) => { + return 1; + }, + }; + + jest.spyOn(ergo, 'getPool').mockReturnValue(null as any); + const mockGet = jest.fn().mockResolvedValue(pool); + (makeNativePools as any).mockReturnValue({ get: mockGet }); + + expect(ergo['ammPools'].length).toEqual(0); + await ergo.loadPool('validPoolId'); + expect(ergo['ammPools'].length).toEqual(1); + expect(makeNativePools).toHaveBeenCalledWith(ergo['_explorer']); + }); + + it('Should throw new Error if no pool is found with the related poolId from makeNativePools', async () => { + const mockGet = jest.fn().mockReturnValue(null); + (makeNativePools as any).mockReturnValue({ get: mockGet }); + jest.spyOn(ergo, 'getPool').mockReturnValue(null as any); + + await expect(ergo.loadPool('invalidPoolId')).rejects.toThrow( + `can not get pool with this id: invalidPoolId`, + ); + }); + }); + describe('getPoolData', () => { it('Should call makeNativePools and getAll with correct parameters', async () => { - // Arrange: Mock makeNativePools and getAll methods const mockGetAll = jest.fn().mockResolvedValue([]); (makeNativePools as any).mockReturnValue({ getAll: mockGetAll }); const limit = 10; const offset = 0; - // Act: Call the method under test await ergo['getPoolData'](limit, offset); @@ -835,17 +925,13 @@ describe('Ergo', () => { }); it('Should return the data from getAll method', async () => { - // Arrange: Mock getAll method to return specific data const expectedData = [{ id: 1, name: 'Pool 1' }]; const mockGetAll = jest.fn().mockResolvedValue(expectedData); (makeNativePools as any).mockReturnValue({ getAll: mockGetAll }); - const limit = 10; const offset = 0; - // Act: Call the method under test const result = await ergo['getPoolData'](limit, offset); - // Assert: Verify the method returns expected data expect(result).toEqual(expectedData[0]); }); @@ -858,7 +944,6 @@ describe('Ergo', () => { const limit = 10; const offset = 0; - // Act & Assert: Ensure the method throws the expected error await expect(ergo['getPoolData'](limit, offset)).rejects.toThrow( 'Test error', ); @@ -877,7 +962,6 @@ describe('Ergo', () => { // Act: Set _assetMap directly ergo['_assetMap'] = assetMap; - // Assert: Validate the stored asset list returned by storedAssetList expect(ergo.storedTokenList).toEqual(assetMap); }); From 6a2bd89095147f2fe26ec94fd2cb74c02dfbe9a4 Mon Sep 17 00:00:00 2001 From: ahmadyazdanii Date: Fri, 12 Jul 2024 20:27:50 +0330 Subject: [PATCH 082/132] fix [ergo]: convert token symbol to id before asking from pool --- src/chains/ergo/ergo.ts | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 1ac849a8af..01c9391e4b 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -404,6 +404,14 @@ export class Ergo { symbol: result.ticker, }; } + + this._assetMap['ERGO'] = { + tokenId: + '0000000000000000000000000000000000000000000000000000000000000000', + decimals: 9, + name: 'ERGO', + symbol: 'ERG', + }; } private async getAssetData() { @@ -589,6 +597,9 @@ export class Ergo { slippage?: number, ): Promise { let sell: boolean; + + console.log(baseToken, quoteToken); + const pool = this.getPoolByToken(baseToken, quoteToken); if (!pool) throw new Error(`pool not found base on ${baseToken}, ${quoteToken}`); @@ -639,13 +650,21 @@ export class Ergo { } public getPoolByToken(baseToken: string, quoteToken: string): Pool { + const realBaseToken = this.storedAssetList.find( + (asset) => asset.symbol === baseToken, + ); + const realQuoteToken = this.storedAssetList.find( + (asset) => asset.symbol === quoteToken, + ); + if (!realBaseToken || !realQuoteToken) + throw new Error(`${realBaseToken} or ${realQuoteToken} not found!`); return ( this.ammPools.find( (ammPool) => - (ammPool.x.asset.id === baseToken && - ammPool.y.asset.id === quoteToken) || - (ammPool.x.asset.id === quoteToken && - ammPool.y.asset.id === baseToken), + (ammPool.x.asset.id === realBaseToken.tokenId && + ammPool.y.asset.id === realQuoteToken.tokenId) || + (ammPool.x.asset.id === realQuoteToken.tokenId && + ammPool.y.asset.id === realBaseToken.tokenId), ) ); } From b7a307a3552b080b602ccec4aeab3ec0b58511c9 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Sat, 13 Jul 2024 10:30:00 +0330 Subject: [PATCH 083/132] add [unit-test]: Implement unit tests for "Ergo" => "swap" method : covered all error cases --- test/chains/ergo/ergo.test.ts | 241 +++++++++++++++++++++++++++++++++- 1 file changed, 237 insertions(+), 4 deletions(-) diff --git a/test/chains/ergo/ergo.test.ts b/test/chains/ergo/ergo.test.ts index d65dcf6d8b..1493aca1f2 100644 --- a/test/chains/ergo/ergo.test.ts +++ b/test/chains/ergo/ergo.test.ts @@ -12,7 +12,7 @@ import { Ergo } from '../../../src/chains/ergo/ergo'; import { patch, unpatch } from '../../../test/services/patch'; import * as ergo_cofing from '../../../src/chains/ergo/ergo.config'; import { NodeService } from '../../../src/chains/ergo/node.service'; -import { Explorer, RustModule } from '@patternglobal/ergo-sdk'; +import { RustModule } from '@patternglobal/ergo-sdk'; import { DexService } from '../../../src/chains/ergo/dex.service'; import { ErgoController } from '../../../src/chains/ergo/ergo.controller'; import { @@ -23,16 +23,33 @@ import { import LRUCache from 'lru-cache'; import { makeNativePools } from '@patternglobal/ergo-dex-sdk'; import { BigNumber } from 'bignumber.js'; +import * as ergo_utils from '../../../src/chains/ergo/ergo.util'; jest.mock('@patternglobal/ergo-dex-sdk', () => ({ AmmPool: jest.fn(), makeNativePools: jest.fn(), + makeWrappedNativePoolActionsSelector: jest.fn(), + swapVars: jest + .fn() + .mockReturnValueOnce(undefined) + .mockReturnValueOnce([ + 1, + { + minOutput: { amount: BigInt(1) }, + maxExFee: BigInt(1), + }, + ] as any), })); jest.mock('@patternglobal/ergo-sdk', () => ({ - Explorer: jest.fn(), + Explorer: jest.fn().mockReturnValue({ + getNetworkContext: jest.fn().mockReturnValue({} as any), + }), + AssetAmount: jest.fn(), + publicKeyFromAddress: jest.fn().mockReturnValueOnce(undefined), RustModule: { load: jest.fn().mockResolvedValue, }, + DefaultTxAssembler: jest.fn().mockReturnValue('mainnetTxAssembler' as any), })); let ergo: Ergo; @@ -54,6 +71,7 @@ const patchGetErgoConfig = (imputNetwork: string) => { maxLRUCacheInstances: 10, utxosLimit: 100, poolLimit: 100, + defaultMinerFee: BigNumber(2), }, }; }); @@ -158,7 +176,7 @@ describe('Ergo', () => { expect(ergo['_network']).toEqual('mainnet'); expect(ergo['_networkPrefix']).toEqual(NetworkPrefix.Mainnet); expect(ergo['_node']).toBeInstanceOf(NodeService); - expect(ergo['_explorer']).toBeInstanceOf(Explorer); + // expect(ergo['_explorer']).toBeInstanceOf(Explorer); expect(ergo['_dex']).toBeInstanceOf(DexService); expect(ergo['txFee']).toEqual(2000); expect(ergo['controller']).toEqual(ErgoController); @@ -180,7 +198,7 @@ describe('Ergo', () => { expect(ergo['_network']).toEqual('testnet'); expect(ergo['_networkPrefix']).toEqual(NetworkPrefix.Testnet); expect(ergo['_node']).toBeInstanceOf(NodeService); - expect(ergo['_explorer']).toBeInstanceOf(Explorer); + // expect(ergo['_explorer']).toBeInstanceOf(Explorer); expect(ergo['_dex']).toBeInstanceOf(DexService); expect(ergo['txFee']).toEqual(2000); expect(ergo['controller']).toEqual(ErgoController); @@ -966,4 +984,219 @@ describe('Ergo', () => { expect(ergo.storedTokenList).toEqual(assetMap); }); }); + + describe('swap', () => { + const account: any = {}; + const baseToken: string = 'baseToken'; + const quoteToken: string = 'quoteToken'; + const amount: BigNumber = BigNumber(10); + const output_address: string = 'output_address'; + const return_address: string = 'return_address'; + // const slippage: number = + beforeEach(() => { + jest.spyOn(ergo, 'getAddressUnspentBoxes').mockResolvedValue([]); + }); + const poolWithOutputAmount0: any = { + id: '1b694b15467c62f0cd4525e368dbdea2329c713aa200b73df4a622e950551b40', + lp: { + withAmount: (_sth: any) => { + return { + asset: { + id: 'lpId', + name: 'lpName', + decimals: 0, + }, + amount: BigInt(922336941265222), + }; + }, + }, + x: { + withAmount: (_sth: any) => { + return { + asset: { + id: 'xId', + name: 'xName', + decimals: 9, + }, + amount: BigInt(752313805260857), + }; + }, + asset: { + id: 'xId', + name: 'xName', + decimals: 9, + }, + }, + y: { + withAmount: (_sth: any) => { + return { + asset: { + id: 'yId', + name: 'yName', + decimals: 3, + }, + amount: BigInt(9322283969), + }; + }, + asset: { + id: 'yId', + name: 'yName', + decimals: 3, + }, + }, + outputAmount: (_sth: any, _slippage: any) => { + return { + amount: BigInt(0), + }; + }, + }; + const pool: any = { + id: '1b694b15467c62f0cd4525e368dbdea2329c713aa200b73df4a622e950551b40', + lp: { + withAmount: (_sth: any) => { + return { + asset: { + id: 'lpId', + name: 'lpName', + decimals: 0, + }, + amount: BigInt(922336941265222), + }; + }, + }, + x: { + withAmount: (_sth: any) => { + return { + asset: { + id: 'xId', + name: 'xName', + decimals: 9, + }, + amount: BigInt(752313805260857), + }; + }, + asset: { + id: 'xId', + name: 'xName', + decimals: 9, + }, + }, + y: { + withAmount: (_sth: any) => { + return { + asset: { + id: 'yId', + name: 'yName', + decimals: 3, + }, + amount: BigInt(9322283969), + }; + }, + asset: { + id: 'yId', + name: 'yName', + decimals: 3, + }, + }, + outputAmount: (_sth: any, _slippage: any) => { + return { + amount: BigInt(1), + }; + }, + }; + + it('Shoukd be defined', () => { + expect(ergo.swap).toBeDefined(); + }); + it('Should throw new Error if pool is not found base on baseToken and quoteToken', async () => { + jest.spyOn(ergo, 'getPoolByToken').mockReturnValue(null as any); + await expect( + ergo.swap( + account, + baseToken, + quoteToken, + amount, + output_address, + return_address, + ), + ).rejects.toThrow(`pool not found base on ${baseToken}, ${quoteToken}`); + }); + + it(`Should throw new Error if 'from.amount === 0' and sell is 'true'`, async () => { + jest.spyOn(ergo, 'getPoolByToken').mockReturnValue(poolWithOutputAmount0); + patchGetErgoConfig('mainnet'); + await expect( + ergo.swap( + account, + baseToken, + quoteToken, + amount, + output_address, + return_address, + ), + ).rejects.toThrow(`${amount} asset from xId is not enough!`); + }); + it(`Should throw new Error if 'from.amount === 0' and sell is 'false'`, async () => { + jest.spyOn(ergo, 'getPoolByToken').mockReturnValue(poolWithOutputAmount0); + patchGetErgoConfig('mainnet'); + // to set sell false + const baseToken = 'xId'; + await expect( + ergo.swap( + account, + baseToken, + quoteToken, + amount, + output_address, + return_address, + ), + ).rejects.toThrow(`${amount} asset from yId is not enough!`); + }); + + it('Should throw new Error if swapVariables are undefined', async () => { + jest.spyOn(ergo, 'getPoolByToken').mockReturnValue(pool); + jest + .spyOn(BigNumber.prototype, 'multipliedBy') + .mockReturnValue(BigNumber(2)); + // jest.spyOn(ergo, 'getAddressUnspentBoxes').mockResolvedValue([]); + patchGetErgoConfig('mainnet'); + jest + .spyOn(ergo_utils, 'getBaseInputParameters') + .mockReturnValue({} as any); + await expect( + ergo.swap( + account, + baseToken, + quoteToken, + amount, + output_address, + return_address, + ), + ).rejects.toThrow('error in swap vars!'); + }); + it('Should throw new Error if output_address is not defined', async () => { + jest.spyOn(ergo, 'getPoolByToken').mockReturnValue(pool); + jest + .spyOn(BigNumber.prototype, 'multipliedBy') + .mockReturnValue(BigNumber(2)); + // jest.spyOn(ergo, 'getAddressUnspentBoxes').mockResolvedValue([]); + patchGetErgoConfig('mainnet'); + jest.spyOn(ergo_utils, 'getBaseInputParameters').mockReturnValue({ + baseInput: BigNumber(1), + baseInputAmount: BigNumber(1), + minOutput: {}, + } as any); + jest.spyOn(ergo_utils, 'getInputs').mockReturnValue({} as any); + await expect( + ergo.swap( + account, + baseToken, + quoteToken, + amount, + output_address, + return_address, + ), + ).rejects.toThrow(`output_address is not defined.`); + }); + }); }); From 0a2ade2b5e538971c36684a1934588e68bbc0fea Mon Sep 17 00:00:00 2001 From: satiparpar Date: Sat, 13 Jul 2024 14:08:47 +0330 Subject: [PATCH 084/132] add [unit-test]: Implement unit tests for "Ergo" => "swap" method --- test/chains/ergo/ergo.test.ts | 178 ++++++++++++++++++++++++++++++++-- 1 file changed, 170 insertions(+), 8 deletions(-) diff --git a/test/chains/ergo/ergo.test.ts b/test/chains/ergo/ergo.test.ts index 1493aca1f2..4e14eb28c6 100644 --- a/test/chains/ergo/ergo.test.ts +++ b/test/chains/ergo/ergo.test.ts @@ -28,10 +28,26 @@ import * as ergo_utils from '../../../src/chains/ergo/ergo.util'; jest.mock('@patternglobal/ergo-dex-sdk', () => ({ AmmPool: jest.fn(), makeNativePools: jest.fn(), - makeWrappedNativePoolActionsSelector: jest.fn(), + makeWrappedNativePoolActionsSelector: jest.fn().mockReturnValue(() => ({ + swap: jest.fn().mockResolvedValue({ id: 'txId' }), + })), swapVars: jest .fn() .mockReturnValueOnce(undefined) + .mockReturnValueOnce([ + 1, + { + minOutput: { amount: BigInt(1) }, + maxExFee: BigInt(1), + }, + ] as any) + .mockReturnValueOnce([ + 1, + { + minOutput: { amount: BigInt(1) }, + maxExFee: BigInt(1), + }, + ] as any) .mockReturnValueOnce([ 1, { @@ -42,10 +58,14 @@ jest.mock('@patternglobal/ergo-dex-sdk', () => ({ })); jest.mock('@patternglobal/ergo-sdk', () => ({ Explorer: jest.fn().mockReturnValue({ - getNetworkContext: jest.fn().mockReturnValue({} as any), + getNetworkContext: jest.fn().mockReturnValue({ height: 1 } as any), }), AssetAmount: jest.fn(), - publicKeyFromAddress: jest.fn().mockReturnValueOnce(undefined), + publicKeyFromAddress: jest + .fn() + .mockReturnValueOnce(undefined) + .mockReturnValueOnce('publicKey') + .mockReturnValueOnce('publicKey'), RustModule: { load: jest.fn().mockResolvedValue, }, @@ -72,6 +92,7 @@ const patchGetErgoConfig = (imputNetwork: string) => { utxosLimit: 100, poolLimit: 100, defaultMinerFee: BigNumber(2), + defaultSlippage: 10, }, }; }); @@ -748,6 +769,13 @@ describe('Ergo', () => { name: '$Bass Token', symbol: '$bass', }, + ERGO: { + tokenId: + '0000000000000000000000000000000000000000000000000000000000000000', + decimals: 9, + name: 'ERGO', + symbol: 'ERG', + }, }); }); }); @@ -986,13 +1014,13 @@ describe('Ergo', () => { }); describe('swap', () => { - const account: any = {}; + const account: any = { address: 'address' }; const baseToken: string = 'baseToken'; const quoteToken: string = 'quoteToken'; const amount: BigNumber = BigNumber(10); const output_address: string = 'output_address'; const return_address: string = 'return_address'; - // const slippage: number = + const slippage: number = 10; beforeEach(() => { jest.spyOn(ergo, 'getAddressUnspentBoxes').mockResolvedValue([]); }); @@ -1098,6 +1126,8 @@ describe('Ergo', () => { decimals: 3, }, }, + priceX: { numerator: BigInt(1) }, + priceY: { numerator: BigInt(2) }, outputAmount: (_sth: any, _slippage: any) => { return { amount: BigInt(1), @@ -1105,7 +1135,7 @@ describe('Ergo', () => { }, }; - it('Shoukd be defined', () => { + it('Should be defined', () => { expect(ergo.swap).toBeDefined(); }); it('Should throw new Error if pool is not found base on baseToken and quoteToken', async () => { @@ -1120,6 +1150,7 @@ describe('Ergo', () => { return_address, ), ).rejects.toThrow(`pool not found base on ${baseToken}, ${quoteToken}`); + expect(ergo.getPoolByToken).toHaveBeenCalledWith(baseToken, quoteToken); }); it(`Should throw new Error if 'from.amount === 0' and sell is 'true'`, async () => { @@ -1135,6 +1166,7 @@ describe('Ergo', () => { return_address, ), ).rejects.toThrow(`${amount} asset from xId is not enough!`); + expect(ergo.getAddressUnspentBoxes).toHaveBeenCalledWith('address'); }); it(`Should throw new Error if 'from.amount === 0' and sell is 'false'`, async () => { jest.spyOn(ergo, 'getPoolByToken').mockReturnValue(poolWithOutputAmount0); @@ -1151,6 +1183,7 @@ describe('Ergo', () => { return_address, ), ).rejects.toThrow(`${amount} asset from yId is not enough!`); + expect(ergo.getAddressUnspentBoxes).toHaveBeenCalledWith('address'); }); it('Should throw new Error if swapVariables are undefined', async () => { @@ -1158,7 +1191,6 @@ describe('Ergo', () => { jest .spyOn(BigNumber.prototype, 'multipliedBy') .mockReturnValue(BigNumber(2)); - // jest.spyOn(ergo, 'getAddressUnspentBoxes').mockResolvedValue([]); patchGetErgoConfig('mainnet'); jest .spyOn(ergo_utils, 'getBaseInputParameters') @@ -1173,13 +1205,31 @@ describe('Ergo', () => { return_address, ), ).rejects.toThrow('error in swap vars!'); + expect(ergo.getAddressUnspentBoxes).toHaveBeenCalledWith('address'); + expect(ergo_utils.getBaseInputParameters).toHaveBeenCalledWith(pool, { + inputAmount: { + asset: { + id: 'yId', + decimals: 3, + }, + amount: pool.outputAmount( + { + asset: { + id: 'xId', + }, + amount: amount, + }, + slippage, + ).amount, + }, + slippage: slippage || 10, + }); }); it('Should throw new Error if output_address is not defined', async () => { jest.spyOn(ergo, 'getPoolByToken').mockReturnValue(pool); jest .spyOn(BigNumber.prototype, 'multipliedBy') .mockReturnValue(BigNumber(2)); - // jest.spyOn(ergo, 'getAddressUnspentBoxes').mockResolvedValue([]); patchGetErgoConfig('mainnet'); jest.spyOn(ergo_utils, 'getBaseInputParameters').mockReturnValue({ baseInput: BigNumber(1), @@ -1197,6 +1247,118 @@ describe('Ergo', () => { return_address, ), ).rejects.toThrow(`output_address is not defined.`); + expect(ergo.getAddressUnspentBoxes).toHaveBeenCalledWith('address'); + }); + + it('Should successfully swap tokens when sell is true', async () => { + const mockUtxos = [ + { + value: '1000', + assets: [{ amount: '500' }, { amount: '300' }], + }, + { + value: '2000', + assets: [{ amount: '1500' }, { amount: '1300' }], + }, + ]; + jest.spyOn(ergo, 'getPoolByToken').mockReturnValue(pool); + jest + .spyOn(ergo, 'getAddressUnspentBoxes') + .mockResolvedValue(mockUtxos as any); + // const date = new Date(); + jest + .spyOn(ergo['_node'], 'getBlockInfo') + .mockResolvedValue({ header: { timestamp: new Date() } }); + jest.spyOn(ergo_utils, 'getBaseInputParameters').mockReturnValue({ + baseInput: BigNumber(1), + baseInputAmount: BigNumber(1), + minOutput: { amount: BigInt(1) }, + } as any); + + const result = await ergo.swap( + account, + baseToken, + quoteToken, + amount, + output_address, + return_address, + slippage, + ); + expect(result).toMatchObject({ + network: ergo.network, + // timestamp ignored because there was a really small difference between create Date.new() in test file and main file + // timestamp: expect.any(Number), + latency: 0, + base: baseToken, + quote: quoteToken, + amount: amount.toString(), + rawAmount: amount.toString(), + expectedOut: BigInt(1).toString(), + price: '1', + gasPrice: 0, + gasPriceToken: '0', + gasLimit: 0, + gasCost: '0', + txHash: 'txId', + }); + // check to see if timestamps are close to each other + expect(new Date(result.timestamp).getTime()).toBeCloseTo(Date.now(), -1); + }); + + it('Should successfully swap tokens when sell is false', async () => { + const mockUtxos = [ + { + value: '1000', + assets: [{ amount: '500' }, { amount: '300' }], + }, + { + value: '2000', + assets: [{ amount: '1500' }, { amount: '1300' }], + }, + ]; + jest.spyOn(ergo, 'getPoolByToken').mockReturnValue(pool); + jest + .spyOn(ergo, 'getAddressUnspentBoxes') + .mockResolvedValue(mockUtxos as any); + // const date = new Date(); + jest + .spyOn(ergo['_node'], 'getBlockInfo') + .mockResolvedValue({ header: { timestamp: new Date() } }); + jest.spyOn(ergo_utils, 'getBaseInputParameters').mockReturnValue({ + baseInput: BigNumber(1), + baseInputAmount: BigNumber(1), + minOutput: { amount: BigInt(1) }, + } as any); + // to set sell false + const baseToken = 'xId'; + const result = await ergo.swap( + account, + baseToken, + quoteToken, + amount, + output_address, + return_address, + slippage, + ); + expect(result).toMatchObject({ + network: ergo.network, + // timestamp ignored because there was a really small difference between create Date.new() in test file and main file + // timestamp: expect.any(Number), + latency: 0, + base: baseToken, + quote: quoteToken, + amount: amount.toString(), + rawAmount: amount.toString(), + expectedOut: BigInt(1).toString(), + price: '2', + gasPrice: 0, + gasPriceToken: '0', + gasLimit: 0, + gasCost: '0', + txHash: 'txId', + }); + // check to see if timestamps are close to each other + expect(new Date(result.timestamp).getTime()).toBeCloseTo(Date.now(), -1); }); }); }); From e1769d4487db387d296b9e292ab487cdfd8518a8 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Sat, 13 Jul 2024 14:50:11 +0330 Subject: [PATCH 085/132] add [unit-test]: Implement unit tests for "Ergo" => "estimate" method --- test/chains/ergo/ergo.test.ts | 133 +++++++++++++++++++++++++++++++++- 1 file changed, 131 insertions(+), 2 deletions(-) diff --git a/test/chains/ergo/ergo.test.ts b/test/chains/ergo/ergo.test.ts index 4e14eb28c6..7220226d33 100644 --- a/test/chains/ergo/ergo.test.ts +++ b/test/chains/ergo/ergo.test.ts @@ -1320,7 +1320,6 @@ describe('Ergo', () => { jest .spyOn(ergo, 'getAddressUnspentBoxes') .mockResolvedValue(mockUtxos as any); - // const date = new Date(); jest .spyOn(ergo['_node'], 'getBlockInfo') .mockResolvedValue({ header: { timestamp: new Date() } }); @@ -1343,7 +1342,7 @@ describe('Ergo', () => { expect(result).toMatchObject({ network: ergo.network, // timestamp ignored because there was a really small difference between create Date.new() in test file and main file - // timestamp: expect.any(Number), + // timestamp: Date.now(), latency: 0, base: baseToken, quote: quoteToken, @@ -1361,4 +1360,134 @@ describe('Ergo', () => { expect(new Date(result.timestamp).getTime()).toBeCloseTo(Date.now(), -1); }); }); + + describe('estimate', () => { + const baseToken: string = 'baseToken'; + const quoteToken: string = 'quoteToken'; + const amount: BigNumber = BigNumber(10); + + const pool: any = { + id: '1b694b15467c62f0cd4525e368dbdea2329c713aa200b73df4a622e950551b40', + lp: { + withAmount: (_sth: any) => { + return { + asset: { + id: 'lpId', + name: 'lpName', + decimals: 0, + }, + amount: BigInt(922336941265222), + }; + }, + }, + x: { + withAmount: (_sth: any) => { + return { + asset: { + id: 'xId', + name: 'xName', + decimals: 9, + }, + amount: BigInt(752313805260857), + }; + }, + asset: { + id: 'xId', + name: 'xName', + decimals: 9, + }, + }, + y: { + withAmount: (_sth: any) => { + return { + asset: { + id: 'yId', + name: 'yName', + decimals: 3, + }, + amount: BigInt(9322283969), + }; + }, + asset: { + id: 'yId', + name: 'yName', + decimals: 3, + }, + }, + priceX: { numerator: BigInt(1) }, + priceY: { numerator: BigInt(2) }, + outputAmount: (_sth: any, _slippage: any) => { + return { + amount: BigInt(1), + }; + }, + }; + + it('Should be defined', () => { + expect(ergo.estimate).toBeDefined(); + }); + it('Should throw new Error if pool is not found', async () => { + jest.spyOn(ergo, 'getPoolByToken').mockReturnValue(null as any); + await expect( + ergo.estimate(baseToken, quoteToken, amount), + ).rejects.toThrow(`pool not found base on ${baseToken}, ${quoteToken}`); + }); + + it('Should estimate successfully when sell is true', async () => { + patchGetErgoConfig('mainnet'); + jest.spyOn(ergo, 'getPoolByToken').mockReturnValue(null as any); + jest + .spyOn(ergo_utils, 'getBaseInputParameters') + .mockReturnValue({ minOutput: { amount: BigInt(1) } } as any); + jest.spyOn(ergo, 'getPoolByToken').mockReturnValue(pool); + const result = await ergo.estimate(baseToken, quoteToken, amount); + expect(result).toMatchObject({ + base: baseToken, + quote: quoteToken, + amount: amount.toString(), + rawAmount: amount.toString(), + expectedAmount: BigInt(1).toString(), + price: BigInt(1).toString(), + network: ergo.network, + // timestamp ignored because there was a really small difference between create Date.new() in test file and main file + // timestamp: Date.now(), + latency: 0, + gasPrice: 0, + gasPriceToken: '0', + gasLimit: 0, + gasCost: '0', + }); + // check to see if timestamps are close to each other + expect(new Date(result.timestamp).getTime()).toBeCloseTo(Date.now(), -1); + }); + it('Should estimate successfully when sell is false', async () => { + patchGetErgoConfig('mainnet'); + jest.spyOn(ergo, 'getPoolByToken').mockReturnValue(null as any); + jest + .spyOn(ergo_utils, 'getBaseInputParameters') + .mockReturnValue({ minOutput: { amount: BigInt(1) } } as any); + jest.spyOn(ergo, 'getPoolByToken').mockReturnValue(pool); + // to set sell false: + const baseToken = 'xId'; + const result = await ergo.estimate(baseToken, quoteToken, amount); + expect(result).toMatchObject({ + base: baseToken, + quote: quoteToken, + amount: amount.toString(), + rawAmount: amount.toString(), + expectedAmount: BigInt(1).toString(), + price: BigInt(2).toString(), + network: ergo.network, + // timestamp ignored because there was a really small difference between create Date.new() in test file and main file + // timestamp: Date.now(), + latency: 0, + gasPrice: 0, + gasPriceToken: '0', + gasLimit: 0, + gasCost: '0', + }); + // check to see if timestamps are close to each other + expect(new Date(result.timestamp).getTime()).toBeCloseTo(Date.now(), -1); + }); + }); }); From 5290ae3eac02ed5567e160208383599c646de901 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Sat, 13 Jul 2024 15:17:17 +0330 Subject: [PATCH 086/132] fix [getPoolByToken]: fix the error message to send correct token symbols --- src/chains/ergo/ergo.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 032f72ab4f..85dac82db7 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -657,7 +657,7 @@ export class Ergo { (asset) => asset.symbol === quoteToken, ); if (!realBaseToken || !realQuoteToken) - throw new Error(`${realBaseToken} or ${realQuoteToken} not found!`); + throw new Error(`${baseToken} or ${quoteToken} not found!`); return ( this.ammPools.find( (ammPool) => From 9599767d3d0e18248ee1736fb8aa6a4320840d2e Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Sat, 13 Jul 2024 18:57:12 +0330 Subject: [PATCH 087/132] decimals considered for swap and estimate --- src/chains/ergo/ergo.ts | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 85dac82db7..774ea7bfe3 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -467,17 +467,26 @@ export class Ergo { account: ErgoAccount, baseToken: string, quoteToken: string, - amount: BigNumber, + value: BigNumber, output_address: string, return_address: string, slippage?: number, ): Promise { let sell: boolean; + let amount: BigNumber; const pool = this.getPoolByToken(baseToken, quoteToken); if (!pool) throw new Error(`pool not found base on ${baseToken}, ${quoteToken}`); - if (pool.x.asset.id === baseToken) sell = false; - else sell = true; + if (pool.x.asset.id === baseToken){sell = false; + amount = value.multipliedBy( + BigNumber(10).pow(pool.y.asset.decimals as number), + ); + } else { + sell = true; + amount = value.multipliedBy( + BigNumber(10).pow(pool.x.asset.decimals as number), + ); + } const config = getErgoConfig(this.network); const networkContext = await this._explorer.getNetworkContext(); const mainnetTxAssembler = new DefaultTxAssembler( @@ -593,18 +602,26 @@ export class Ergo { public async estimate( baseToken: string, quoteToken: string, - amount: BigNumber, + value: BigNumber, slippage?: number, ): Promise { let sell: boolean; - + let amount: BigNumber; console.log(baseToken, quoteToken); const pool = this.getPoolByToken(baseToken, quoteToken); if (!pool) throw new Error(`pool not found base on ${baseToken}, ${quoteToken}`); - if (pool.x.asset.id === baseToken) sell = false; - else sell = true; + if (pool.x.asset.id === baseToken){sell = false; + amount = value.multipliedBy( + BigNumber(10).pow(pool.y.asset.decimals as number), + ); + } else { + sell = true; + amount = value.multipliedBy( + BigNumber(10).pow(pool.x.asset.decimals as number), + ); + } const config = getErgoConfig(this.network); const max_to = { asset: { From 8b7d808e773b5c2843542ad66fca8c2665117524 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Sun, 14 Jul 2024 10:42:29 +0330 Subject: [PATCH 088/132] add [unit-test]: Implement unit tests for "Ergo" => "getPool", "getPoolByToken" & "getTx" methods --- test/chains/ergo/ergo.test.ts | 99 +++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/test/chains/ergo/ergo.test.ts b/test/chains/ergo/ergo.test.ts index 7220226d33..a32ed31bc0 100644 --- a/test/chains/ergo/ergo.test.ts +++ b/test/chains/ergo/ergo.test.ts @@ -1490,4 +1490,103 @@ describe('Ergo', () => { expect(new Date(result.timestamp).getTime()).toBeCloseTo(Date.now(), -1); }); }); + + describe('getPool', () => { + it('Should find the pool with related id and return it', () => { + // set a mock pool to check the id + const poolToCheck: any = { + id: '1b694b15467c62f0cd4525e368dbdea2329c713aa200b73df4a622e950551b40', + lp: { + withAmount: (_sth: any) => { + return { + asset: { + id: 'lpId', + name: 'lpName', + decimals: 0, + }, + amount: BigInt(922336941265222), + }; + }, + }, + }; + expect( + ergo.getPool( + '1b694b15467c62f0cd4525e368dbdea2329c713aa200b73df4a622e950551b40', + ), + ).toEqual(undefined); + ergo['ammPools'].push(poolToCheck); + const result = ergo.getPool( + '1b694b15467c62f0cd4525e368dbdea2329c713aa200b73df4a622e950551b40', + ); + expect(result).toEqual(poolToCheck); + }); + }); + describe('getPoolByToken', () => { + beforeEach(() => { + ergo['_assetMap']['ERGO'] = { + tokenId: + '0000000000000000000000000000000000000000000000000000000000000000', + decimals: 9, + name: 'ERGO', + symbol: 'ERG', + }; + }); + const baseToken = 'ERG'; + const quoteToken = 'RSN'; + it('Should throw new Error if quote token is not found', () => { + expect(() => ergo.getPoolByToken(baseToken, quoteToken)).toThrow( + `${baseToken} or ${quoteToken} not found!`, + ); + }); + it('Should throw new Error if base token is not found', () => { + // swap baseToken with quoteToken + const baseToken = 'RSN'; + const quoteToken = 'ERG'; + expect(() => ergo.getPoolByToken(baseToken, quoteToken)).toThrow( + `${baseToken} or ${quoteToken} not found!`, + ); + }); + it('Should find poll when both base token and quote are valid in ammPools array', () => { + ergo['_assetMap']['ROSEN'] = { + tokenId: + '1111111111111111111111111111111111111111111111111111111111111111', + decimals: 9, + name: 'ROSEN', + symbol: 'RSN', + }; + const ergoRnsPool = { + id: '1b694b15467c62f0cd4525e368dbdea2329c713aa200b73df4a622e950551b40', + x: { + asset: { + id: '0000000000000000000000000000000000000000000000000000000000000000', + name: 'ERGO', + decimals: 9, + }, + }, + y: { + asset: { + id: '1111111111111111111111111111111111111111111111111111111111111111', + name: 'ROSEN', + decimals: 3, + }, + }, + } as any; + ergo['ammPools'].push(ergoRnsPool); + const result = ergo.getPoolByToken(baseToken, quoteToken); + expect(result).toEqual(ergoRnsPool); + }); + }); + + describe('getTx', () => { + it('Shoyuld be defined', () => { + expect(ergo.getTx).toBeDefined(); + }); + + it('Should find and return TX by Id', async () => { + jest.spyOn(ergo['_node'], 'getTxsById').mockResolvedValue('TX' as any); + const result = await ergo.getTx('id'); + expect(ergo['_node'].getTxsById).toHaveBeenCalledWith('id'); + expect(result).toEqual('TX'); + }); + }); }); From c1ed799d3de917636ecbb4bd6d80764f5aac6b4d Mon Sep 17 00:00:00 2001 From: satiparpar Date: Sun, 14 Jul 2024 11:05:34 +0330 Subject: [PATCH 089/132] update [unit-test]: update unit tests for ergo.config based on new updates --- test/chains/ergo/ergo.config.test.ts | 195 ++++++++++++++++++--------- 1 file changed, 134 insertions(+), 61 deletions(-) diff --git a/test/chains/ergo/ergo.config.test.ts b/test/chains/ergo/ergo.config.test.ts index ab954d3330..0347dc9024 100644 --- a/test/chains/ergo/ergo.config.test.ts +++ b/test/chains/ergo/ergo.config.test.ts @@ -1,36 +1,52 @@ import { getErgoConfig } from '../../../src/chains/ergo/ergo.config'; import { ConfigManagerV2 } from '../../../src/services/config-manager-v2'; import { NetworkPrefix } from 'ergo-lib-wasm-nodejs'; +import { BigNumber } from 'bignumber.js'; describe('getErgoConfig', () => { afterEach(() => { jest.clearAllMocks(); }); - - it('Should return correct config for Mainnet', () => { + const configManager = ConfigManagerV2.getInstance(); + it('Should return correct config for mainnet', () => { // Arrange: Mock the get method of ConfigManagerV2 to return specific values for Mainnet jest - .spyOn(ConfigManagerV2.getInstance(), 'get') - .mockReturnValueOnce('ergo.networks.Mainnet.nodeURL'); + .spyOn(configManager, 'get') + .mockReturnValueOnce('ergo.networks.mainnet.nodeURL'); jest - .spyOn(ConfigManagerV2.getInstance(), 'get') - .mockReturnValueOnce('ergo.networks.Mainnet.explorerURL'); + .spyOn(configManager, 'get') + .mockReturnValueOnce('ergo.networks.mainnet.explorerURL'); jest - .spyOn(ConfigManagerV2.getInstance(), 'get') - .mockReturnValueOnce('ergo.networks.Mainnet.explorerDEXURL'); - jest.spyOn(ConfigManagerV2.getInstance(), 'get').mockReturnValueOnce(1000); - jest.spyOn(ConfigManagerV2.getInstance(), 'get').mockReturnValueOnce(2000); + .spyOn(configManager, 'get') + .mockReturnValueOnce('ergo.networks.mainnet.explorerDEXURL'); + // timeout + jest.spyOn(configManager, 'get').mockReturnValueOnce(1000); + // minTxFee + jest.spyOn(configManager, 'get').mockReturnValueOnce(2000); + // maxLRUCacheInstances + jest.spyOn(configManager, 'get').mockReturnValueOnce(10); + // utxosLimit + jest.spyOn(configManager, 'get').mockReturnValueOnce(100); + // poolLimit + jest.spyOn(configManager, 'get').mockReturnValueOnce(100); + // defaultSlippage + jest.spyOn(configManager, 'get').mockReturnValueOnce(3); + // defaultMinerFee + jest.spyOn(configManager, 'get').mockReturnValueOnce(BigNumber(7000)); + // minNitro + jest.spyOn(configManager, 'get').mockReturnValueOnce(1.2); + // minBoxValue + jest.spyOn(configManager, 'get').mockReturnValueOnce(BigNumber(8000)); - // Act: Call the function to be tested with 'Mainnet' as the argument - const res = getErgoConfig('Mainnet'); + const res = getErgoConfig('mainnet'); // Assert: Check that the returned configuration matches the expected values for Mainnet expect(res).toEqual({ network: { - name: 'Mainnet', - nodeURL: 'ergo.networks.Mainnet.nodeURL', - explorerURL: 'ergo.networks.Mainnet.explorerURL', - explorerDEXURL: 'ergo.networks.Mainnet.explorerDEXURL', + name: 'mainnet', + nodeURL: 'ergo.networks.mainnet.nodeURL', + explorerURL: 'ergo.networks.mainnet.explorerURL', + explorerDEXURL: 'ergo.networks.mainnet.explorerDEXURL', timeOut: 1000, networkPrefix: NetworkPrefix.Mainnet, minTxFee: 2000, @@ -38,54 +54,90 @@ describe('getErgoConfig', () => { utxosLimit: 100, poolLimit: 100, defaultSlippage: 3, - defaultMinerFee: BigInt(2_000_000), + defaultMinerFee: BigNumber(7000), minNitro: 1.2, - minBoxValue: BigInt(400_000), + minBoxValue: BigNumber(8000), }, }); - // Assert: Verify that the get method was called exactly five times with the expected arguments - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledTimes(5); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( - 'ergo.networks.Mainnet.nodeURL', + // Assert: Verify that the get method was called exactly 12 times with the expected arguments + expect(configManager.get).toHaveBeenCalledTimes(12); + expect(configManager.get).toHaveBeenCalledWith( + 'ergo.networks.mainnet.nodeURL', + ); + expect(configManager.get).toHaveBeenCalledWith( + 'ergo.networks.mainnet.explorerURL', + ); + expect(configManager.get).toHaveBeenCalledWith( + 'ergo.networks.mainnet.explorerDEXURL', + ); + expect(configManager.get).toHaveBeenCalledWith( + 'ergo.networks.mainnet.timeOut', + ); + expect(configManager.get).toHaveBeenCalledWith( + 'ergo.networks.mainnet.minTxFee', + ); + expect(configManager.get).toHaveBeenCalledWith( + 'ergo.networks.mainnet.maxLRUCacheInstances', + ); + expect(configManager.get).toHaveBeenCalledWith( + 'ergo.networks.mainnet.utxosLimit', + ); + expect(configManager.get).toHaveBeenCalledWith( + 'ergo.networks.mainnet.poolLimit', ); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( - 'ergo.networks.Mainnet.explorerURL', + expect(configManager.get).toHaveBeenCalledWith( + 'ergo.networks.mainnet.defaultSlippage', ); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( - 'ergo.networks.Mainnet.explorerDEXURL', + expect(configManager.get).toHaveBeenCalledWith( + 'ergo.networks.mainnet.defaultMinerFee', ); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( - 'ergo.networks.Mainnet.timeOut', + expect(configManager.get).toHaveBeenCalledWith( + 'ergo.networks.mainnet.minNitro', ); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( - 'ergo.networks.Mainnet.minTxFee', + expect(configManager.get).toHaveBeenCalledWith( + 'ergo.networks.mainnet.minBoxValue', ); }); - it('Should return correct config for Testnet', () => { - // Arrange: Mock the get method of ConfigManagerV2 to return specific values for Testnet + it('Should return correct config for testnet', () => { + // Arrange: Mock the get method of ConfigManagerV2 to return specific values for testnet jest - .spyOn(ConfigManagerV2.getInstance(), 'get') - .mockReturnValueOnce('ergo.networks.Testnet.nodeURL'); + .spyOn(configManager, 'get') + .mockReturnValueOnce('ergo.networks.testnet.nodeURL'); jest - .spyOn(ConfigManagerV2.getInstance(), 'get') - .mockReturnValueOnce('ergo.networks.Testnet.explorerURL'); + .spyOn(configManager, 'get') + .mockReturnValueOnce('ergo.networks.testnet.explorerURL'); jest - .spyOn(ConfigManagerV2.getInstance(), 'get') - .mockReturnValueOnce('ergo.networks.Testnet.explorerDEXURL'); - jest.spyOn(ConfigManagerV2.getInstance(), 'get').mockReturnValueOnce(1000); - jest.spyOn(ConfigManagerV2.getInstance(), 'get').mockReturnValueOnce(2000); + .spyOn(configManager, 'get') + .mockReturnValueOnce('ergo.networks.testnet.explorerDEXURL'); + // timeout + jest.spyOn(configManager, 'get').mockReturnValueOnce(1000); + // minTxFee + jest.spyOn(configManager, 'get').mockReturnValueOnce(2000); + // maxLRUCacheInstances + jest.spyOn(configManager, 'get').mockReturnValueOnce(10); + // utxosLimit + jest.spyOn(configManager, 'get').mockReturnValueOnce(100); + // poolLimit + jest.spyOn(configManager, 'get').mockReturnValueOnce(100); + // defaultSlippage + jest.spyOn(configManager, 'get').mockReturnValueOnce(3); + // defaultMinerFee + jest.spyOn(configManager, 'get').mockReturnValueOnce(BigNumber(7000)); + // minNitro + jest.spyOn(configManager, 'get').mockReturnValueOnce(1.2); + // minBoxValue + jest.spyOn(configManager, 'get').mockReturnValueOnce(BigNumber(8000)); - // Act: Call the function to be tested with 'Testnet' as the argument - const res = getErgoConfig('Testnet'); + const res = getErgoConfig('testnet'); - // Assert: Check that the returned configuration matches the expected values for Testnet + // Assert: Check that the returned configuration matches the expected values for testnet expect(res).toEqual({ network: { - name: 'Testnet', - nodeURL: 'ergo.networks.Testnet.nodeURL', - explorerURL: 'ergo.networks.Testnet.explorerURL', - explorerDEXURL: 'ergo.networks.Testnet.explorerDEXURL', + name: 'testnet', + nodeURL: 'ergo.networks.testnet.nodeURL', + explorerURL: 'ergo.networks.testnet.explorerURL', + explorerDEXURL: 'ergo.networks.testnet.explorerDEXURL', timeOut: 1000, networkPrefix: NetworkPrefix.Testnet, minTxFee: 2000, @@ -93,27 +145,48 @@ describe('getErgoConfig', () => { utxosLimit: 100, poolLimit: 100, defaultSlippage: 3, - defaultMinerFee: BigInt(2_000_000), + defaultMinerFee: BigNumber(7000), minNitro: 1.2, - minBoxValue: BigInt(400_000), + minBoxValue: BigNumber(8000), }, }); - // Assert: Verify that the get method was called exactly five times with the expected arguments - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledTimes(5); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( - 'ergo.networks.Testnet.nodeURL', + // Assert: Verify that the get method was called exactly 12 times with the expected arguments + expect(configManager.get).toHaveBeenCalledTimes(12); + expect(configManager.get).toHaveBeenCalledWith( + 'ergo.networks.testnet.nodeURL', + ); + expect(configManager.get).toHaveBeenCalledWith( + 'ergo.networks.testnet.explorerURL', + ); + expect(configManager.get).toHaveBeenCalledWith( + 'ergo.networks.testnet.explorerDEXURL', + ); + expect(configManager.get).toHaveBeenCalledWith( + 'ergo.networks.testnet.timeOut', + ); + expect(configManager.get).toHaveBeenCalledWith( + 'ergo.networks.testnet.minTxFee', + ); + expect(configManager.get).toHaveBeenCalledWith( + 'ergo.networks.testnet.maxLRUCacheInstances', + ); + expect(configManager.get).toHaveBeenCalledWith( + 'ergo.networks.testnet.utxosLimit', + ); + expect(configManager.get).toHaveBeenCalledWith( + 'ergo.networks.testnet.poolLimit', ); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( - 'ergo.networks.Testnet.explorerURL', + expect(configManager.get).toHaveBeenCalledWith( + 'ergo.networks.testnet.defaultSlippage', ); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( - 'ergo.networks.Testnet.explorerDEXURL', + expect(configManager.get).toHaveBeenCalledWith( + 'ergo.networks.testnet.defaultMinerFee', ); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( - 'ergo.networks.Testnet.timeOut', + expect(configManager.get).toHaveBeenCalledWith( + 'ergo.networks.testnet.minNitro', ); - expect(ConfigManagerV2.getInstance().get).toHaveBeenCalledWith( - 'ergo.networks.Testnet.minTxFee', + expect(configManager.get).toHaveBeenCalledWith( + 'ergo.networks.testnet.minBoxValue', ); }); }); From 44f77c3048910bbfe3632dc9369d72bdadf61ef3 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Sun, 14 Jul 2024 14:08:55 +0330 Subject: [PATCH 090/132] add [unit-test]: Implement unit tests for "NodeService" => "chainSliceInfo" & "getCtx" methods --- test/chains/ergo/node.service.test.ts | 51 +++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/test/chains/ergo/node.service.test.ts b/test/chains/ergo/node.service.test.ts index 60186a6813..f14a7c487c 100644 --- a/test/chains/ergo/node.service.test.ts +++ b/test/chains/ergo/node.service.test.ts @@ -1,8 +1,27 @@ import axios from 'axios'; import { NodeService } from '../../../src/chains/ergo/node.service'; import { NodeInfoResponse } from '../../../src/chains/ergo/interfaces/node.interface'; +import { + BlockHeaders, + ErgoStateContext, + PreHeader, +} from 'ergo-lib-wasm-nodejs'; jest.mock('axios'); +jest.mock('ergo-lib-wasm-nodejs', () => ({ + BlockHeaders: { + from_json: jest.fn().mockReturnValue({ + get: jest.fn().mockReturnValue({ headerData: 'mockData' }), + len: jest.fn().mockReturnValue(2), + }), + }, + PreHeader: { + from_block_header: jest.fn().mockReturnValue({ preHeaderData: 'mockData' }), + }, + ErgoStateContext: jest + .fn() + .mockReturnValue({} as unknown as ErgoStateContext), +})); describe('NodeService', () => { const baseURL = 'https://example.com'; @@ -109,4 +128,36 @@ describe('NodeService', () => { ); }); }); + + describe('chainSliceInfo', () => { + it('Should be defined', () => { + expect(nodeService.chainSliceInfo).toBeDefined(); + }); + it('Should call request method with correct parameters', async () => { + jest.spyOn(nodeService as any, 'request').mockResolvedValue({ data: {} }); + await nodeService.chainSliceInfo(20); + expect(nodeService['request']).toHaveBeenCalledWith( + 'GET', + `/blocks/chainSlice?fromHeight=10&toHeight=20`, + ); + }); + }); + + describe('getCtx', () => { + it('Should be defined', () => { + expect(nodeService.getCtx).toBeDefined(); + }); + it('Should return Ergo state context correctly', async () => { + jest.spyOn(nodeService, 'getNetworkHeight').mockResolvedValue(100); + jest.spyOn(nodeService, 'chainSliceInfo').mockResolvedValue({} as any); + const result = await nodeService.getCtx(); + expect(result).toEqual({}); + expect(nodeService.chainSliceInfo).toHaveBeenCalledWith(100); + expect(nodeService.getNetworkHeight).toHaveBeenCalled(); + expect(BlockHeaders.from_json).toHaveBeenCalledWith({}); + expect(PreHeader.from_block_header).toHaveBeenCalledWith({ + headerData: 'mockData', + }); + }); + }); }); From 9182022690981d0dde32b88a608a79dcf2df39ce Mon Sep 17 00:00:00 2001 From: satiparpar Date: Sun, 14 Jul 2024 14:43:36 +0330 Subject: [PATCH 091/132] add [unit-test]: Implement unit tests for "NodeService" => "postTransaction", "getTxsById" & "getBlockInfo" methods --- test/chains/ergo/node.service.test.ts | 55 +++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/test/chains/ergo/node.service.test.ts b/test/chains/ergo/node.service.test.ts index f14a7c487c..c859ff7f04 100644 --- a/test/chains/ergo/node.service.test.ts +++ b/test/chains/ergo/node.service.test.ts @@ -160,4 +160,59 @@ describe('NodeService', () => { }); }); }); + + describe('postTransaction', () => { + it('Should be defined', () => { + expect(nodeService.postTransaction).toBeDefined(); + }); + + it('Should call request method with the correct parameters', async () => { + const tx = 'tx'; + jest.spyOn(nodeService as any, 'request').mockResolvedValue({ data: {} }); + await nodeService.postTransaction(tx); + expect(nodeService['request']).toHaveBeenCalledWith( + 'POST', + `/transactions`, + { 'Content-Type': 'text/plain' }, + tx, + ); + }); + }); + + describe('getTxsById', () => { + it('Should be defined', () => { + expect(nodeService.getTxsById).toBeDefined(); + }); + + it('Should call request method with the correct parameters', async () => { + const id = 'id'; + await nodeService.getTxsById(id); + expect(nodeService['request']).toHaveBeenCalledWith( + 'GET', + `/blockchain/transaction/byId/id`, + ); + }); + }); + + describe('getBlockInfo', () => { + it('Should be defined', () => { + expect(nodeService.getBlockInfo).toBeDefined(); + }); + + it('Should call request method with the correct parameters', async () => { + jest.spyOn(nodeService as any, 'request').mockResolvedValueOnce([17, 18]); + jest + .spyOn(nodeService as any, 'request') + .mockResolvedValueOnce({ data: 'mockData' }); + + const result = await nodeService.getBlockInfo('blockHeight'); + + expect(result).toEqual({ data: 'mockData' }); + expect(nodeService['request']).toHaveBeenCalledWith( + 'GET', + `/blocks/at/blockHeight`, + ); + expect(nodeService['request']).toHaveBeenCalledWith('GET', `/blocks/17`); + }); + }); }); From bc94d4d6e07f00c20af6c7ea10a5649b50213895 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Sun, 14 Jul 2024 14:49:04 +0330 Subject: [PATCH 092/132] update [log]: remove useless logs --- src/chains/chain.routes.ts | 1 - src/chains/ergo/ergo.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/src/chains/chain.routes.ts b/src/chains/chain.routes.ts index 3b0794a64e..cbc13bf922 100644 --- a/src/chains/chain.routes.ts +++ b/src/chains/chain.routes.ts @@ -95,7 +95,6 @@ export namespace ChainRoutes { req.body.chain, req.body.network ); - console.log('im here') res.status(200).json(await balances(chain, req.body)); } diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 774ea7bfe3..adc1b3aab5 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -607,7 +607,6 @@ export class Ergo { ): Promise { let sell: boolean; let amount: BigNumber; - console.log(baseToken, quoteToken); const pool = this.getPoolByToken(baseToken, quoteToken); if (!pool) From 397cecad8bac4f6cf143840482ac8cd1bfae3e76 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Mon, 15 Jul 2024 09:00:16 +0330 Subject: [PATCH 093/132] update [unit-test]: update unit tests for Ergo based on new updates --- test/chains/ergo/ergo.test.ts | 89 ++++++++++++++++++++++------------- 1 file changed, 55 insertions(+), 34 deletions(-) diff --git a/test/chains/ergo/ergo.test.ts b/test/chains/ergo/ergo.test.ts index a32ed31bc0..efee2d7f08 100644 --- a/test/chains/ergo/ergo.test.ts +++ b/test/chains/ergo/ergo.test.ts @@ -1017,13 +1017,16 @@ describe('Ergo', () => { const account: any = { address: 'address' }; const baseToken: string = 'baseToken'; const quoteToken: string = 'quoteToken'; - const amount: BigNumber = BigNumber(10); + const value: BigNumber = BigNumber(10); const output_address: string = 'output_address'; const return_address: string = 'return_address'; const slippage: number = 10; beforeEach(() => { jest.spyOn(ergo, 'getAddressUnspentBoxes').mockResolvedValue([]); }); + afterEach(() => { + jest.clearAllMocks(); + }); const poolWithOutputAmount0: any = { id: '1b694b15467c62f0cd4525e368dbdea2329c713aa200b73df4a622e950551b40', lp: { @@ -1145,7 +1148,7 @@ describe('Ergo', () => { account, baseToken, quoteToken, - amount, + value, output_address, return_address, ), @@ -1161,11 +1164,15 @@ describe('Ergo', () => { account, baseToken, quoteToken, - amount, + value, output_address, return_address, ), - ).rejects.toThrow(`${amount} asset from xId is not enough!`); + ).rejects.toThrow( + `${value.multipliedBy( + BigNumber(10).pow(pool.x.asset.decimals as number), + )} asset from xId is not enough!`, + ); expect(ergo.getAddressUnspentBoxes).toHaveBeenCalledWith('address'); }); it(`Should throw new Error if 'from.amount === 0' and sell is 'false'`, async () => { @@ -1178,11 +1185,15 @@ describe('Ergo', () => { account, baseToken, quoteToken, - amount, + value, output_address, return_address, ), - ).rejects.toThrow(`${amount} asset from yId is not enough!`); + ).rejects.toThrow( + `${value.multipliedBy( + BigNumber(10).pow(pool.y.asset.decimals as number), + )} asset from yId is not enough!`, + ); expect(ergo.getAddressUnspentBoxes).toHaveBeenCalledWith('address'); }); @@ -1200,7 +1211,7 @@ describe('Ergo', () => { account, baseToken, quoteToken, - amount, + value, output_address, return_address, ), @@ -1217,7 +1228,7 @@ describe('Ergo', () => { asset: { id: 'xId', }, - amount: amount, + amount: value, }, slippage, ).amount, @@ -1242,7 +1253,7 @@ describe('Ergo', () => { account, baseToken, quoteToken, - amount, + value, output_address, return_address, ), @@ -1279,7 +1290,7 @@ describe('Ergo', () => { account, baseToken, quoteToken, - amount, + value, output_address, return_address, slippage, @@ -1291,8 +1302,12 @@ describe('Ergo', () => { latency: 0, base: baseToken, quote: quoteToken, - amount: amount.toString(), - rawAmount: amount.toString(), + amount: value + .multipliedBy(BigNumber(10).pow(pool.x.asset.decimals as number)) + .toString(), + rawAmount: value + .multipliedBy(BigNumber(10).pow(pool.x.asset.decimals as number)) + .toString(), expectedOut: BigInt(1).toString(), price: '1', gasPrice: 0, @@ -1301,8 +1316,6 @@ describe('Ergo', () => { gasCost: '0', txHash: 'txId', }); - // check to see if timestamps are close to each other - expect(new Date(result.timestamp).getTime()).toBeCloseTo(Date.now(), -1); }); it('Should successfully swap tokens when sell is false', async () => { @@ -1334,7 +1347,7 @@ describe('Ergo', () => { account, baseToken, quoteToken, - amount, + value, output_address, return_address, slippage, @@ -1346,8 +1359,12 @@ describe('Ergo', () => { latency: 0, base: baseToken, quote: quoteToken, - amount: amount.toString(), - rawAmount: amount.toString(), + amount: value + .multipliedBy(BigNumber(10).pow(pool.y.asset.decimals as number)) + .toString(), + rawAmount: value + .multipliedBy(BigNumber(10).pow(pool.y.asset.decimals as number)) + .toString(), expectedOut: BigInt(1).toString(), price: '2', gasPrice: 0, @@ -1356,16 +1373,16 @@ describe('Ergo', () => { gasCost: '0', txHash: 'txId', }); - // check to see if timestamps are close to each other - expect(new Date(result.timestamp).getTime()).toBeCloseTo(Date.now(), -1); }); }); describe('estimate', () => { const baseToken: string = 'baseToken'; const quoteToken: string = 'quoteToken'; - const amount: BigNumber = BigNumber(10); - + const value: BigNumber = BigNumber(10); + afterEach(() => { + jest.clearAllMocks(); + }); const pool: any = { id: '1b694b15467c62f0cd4525e368dbdea2329c713aa200b73df4a622e950551b40', lp: { @@ -1428,9 +1445,9 @@ describe('Ergo', () => { }); it('Should throw new Error if pool is not found', async () => { jest.spyOn(ergo, 'getPoolByToken').mockReturnValue(null as any); - await expect( - ergo.estimate(baseToken, quoteToken, amount), - ).rejects.toThrow(`pool not found base on ${baseToken}, ${quoteToken}`); + await expect(ergo.estimate(baseToken, quoteToken, value)).rejects.toThrow( + `pool not found base on ${baseToken}, ${quoteToken}`, + ); }); it('Should estimate successfully when sell is true', async () => { @@ -1440,12 +1457,16 @@ describe('Ergo', () => { .spyOn(ergo_utils, 'getBaseInputParameters') .mockReturnValue({ minOutput: { amount: BigInt(1) } } as any); jest.spyOn(ergo, 'getPoolByToken').mockReturnValue(pool); - const result = await ergo.estimate(baseToken, quoteToken, amount); + const result = await ergo.estimate(baseToken, quoteToken, value); expect(result).toMatchObject({ base: baseToken, quote: quoteToken, - amount: amount.toString(), - rawAmount: amount.toString(), + amount: value + .multipliedBy(BigNumber(10).pow(pool.x.asset.decimals as number)) + .toString(), + rawAmount: value + .multipliedBy(BigNumber(10).pow(pool.x.asset.decimals as number)) + .toString(), expectedAmount: BigInt(1).toString(), price: BigInt(1).toString(), network: ergo.network, @@ -1457,8 +1478,6 @@ describe('Ergo', () => { gasLimit: 0, gasCost: '0', }); - // check to see if timestamps are close to each other - expect(new Date(result.timestamp).getTime()).toBeCloseTo(Date.now(), -1); }); it('Should estimate successfully when sell is false', async () => { patchGetErgoConfig('mainnet'); @@ -1469,12 +1488,16 @@ describe('Ergo', () => { jest.spyOn(ergo, 'getPoolByToken').mockReturnValue(pool); // to set sell false: const baseToken = 'xId'; - const result = await ergo.estimate(baseToken, quoteToken, amount); + const result = await ergo.estimate(baseToken, quoteToken, value); expect(result).toMatchObject({ base: baseToken, quote: quoteToken, - amount: amount.toString(), - rawAmount: amount.toString(), + amount: value + .multipliedBy(BigNumber(10).pow(pool.y.asset.decimals as number)) + .toString(), + rawAmount: value + .multipliedBy(BigNumber(10).pow(pool.y.asset.decimals as number)) + .toString(), expectedAmount: BigInt(1).toString(), price: BigInt(2).toString(), network: ergo.network, @@ -1486,8 +1509,6 @@ describe('Ergo', () => { gasLimit: 0, gasCost: '0', }); - // check to see if timestamps are close to each other - expect(new Date(result.timestamp).getTime()).toBeCloseTo(Date.now(), -1); }); }); From 4e0addebf185b74bc881c6c63176b0b1c27bbf4f Mon Sep 17 00:00:00 2001 From: satiparpar Date: Mon, 15 Jul 2024 09:26:34 +0330 Subject: [PATCH 094/132] update [unit-test]: move unit test files to test-bronze --- {test => test-bronze}/chains/ergo/dex.service.test.ts | 0 {test => test-bronze}/chains/ergo/ergo.config.test.ts | 0 {test => test-bronze}/chains/ergo/ergo.test.ts | 0 {test => test-bronze}/chains/ergo/ergo.utils.test.ts | 0 {test => test-bronze}/chains/ergo/node.service.test.ts | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename {test => test-bronze}/chains/ergo/dex.service.test.ts (100%) rename {test => test-bronze}/chains/ergo/ergo.config.test.ts (100%) rename {test => test-bronze}/chains/ergo/ergo.test.ts (100%) rename {test => test-bronze}/chains/ergo/ergo.utils.test.ts (100%) rename {test => test-bronze}/chains/ergo/node.service.test.ts (100%) diff --git a/test/chains/ergo/dex.service.test.ts b/test-bronze/chains/ergo/dex.service.test.ts similarity index 100% rename from test/chains/ergo/dex.service.test.ts rename to test-bronze/chains/ergo/dex.service.test.ts diff --git a/test/chains/ergo/ergo.config.test.ts b/test-bronze/chains/ergo/ergo.config.test.ts similarity index 100% rename from test/chains/ergo/ergo.config.test.ts rename to test-bronze/chains/ergo/ergo.config.test.ts diff --git a/test/chains/ergo/ergo.test.ts b/test-bronze/chains/ergo/ergo.test.ts similarity index 100% rename from test/chains/ergo/ergo.test.ts rename to test-bronze/chains/ergo/ergo.test.ts diff --git a/test/chains/ergo/ergo.utils.test.ts b/test-bronze/chains/ergo/ergo.utils.test.ts similarity index 100% rename from test/chains/ergo/ergo.utils.test.ts rename to test-bronze/chains/ergo/ergo.utils.test.ts diff --git a/test/chains/ergo/node.service.test.ts b/test-bronze/chains/ergo/node.service.test.ts similarity index 100% rename from test/chains/ergo/node.service.test.ts rename to test-bronze/chains/ergo/node.service.test.ts From 6c0f09c216ceae15f94d8ae98ac7d93dedf5cdcb Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Tue, 16 Jul 2024 03:51:42 +0330 Subject: [PATCH 095/132] some bugs fixed --- src/chains/ergo/ergo.ts | 457 ++++++++++++++++++---------- src/connectors/spectrum/spectrum.ts | 27 +- 2 files changed, 318 insertions(+), 166 deletions(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 774ea7bfe3..2fd530f199 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -397,12 +397,20 @@ export class Ergo { const assetData = await this.getAssetData(); for (const result of assetData.tokens) { - this._assetMap[result.name.toUpperCase()] = { - tokenId: result.address, - decimals: result.decimals, - name: result.name, - symbol: result.ticker, - }; + if (result.ticker === 'SigUSD') + this._assetMap['USDT'] = { + tokenId: result.address, + decimals: result.decimals, + name: 'USDT', + symbol: 'USDT', + }; + else + this._assetMap[result.name.toUpperCase()] = { + tokenId: result.address, + decimals: result.decimals, + name: result.name, + symbol: result.ticker, + }; } this._assetMap['ERGO'] = { @@ -474,128 +482,194 @@ export class Ergo { ): Promise { let sell: boolean; let amount: BigNumber; - const pool = this.getPoolByToken(baseToken, quoteToken); - if (!pool) - throw new Error(`pool not found base on ${baseToken}, ${quoteToken}`); - if (pool.x.asset.id === baseToken){sell = false; - amount = value.multipliedBy( - BigNumber(10).pow(pool.y.asset.decimals as number), - ); - } else { - sell = true; - amount = value.multipliedBy( - BigNumber(10).pow(pool.x.asset.decimals as number), - ); - } - const config = getErgoConfig(this.network); - const networkContext = await this._explorer.getNetworkContext(); - const mainnetTxAssembler = new DefaultTxAssembler( - this.network === 'mainnet', - ); - const poolActions = makeWrappedNativePoolActionsSelector( - output_address, - account.prover, - mainnetTxAssembler, - ); - const utxos = await this.getAddressUnspentBoxes(account.address); - const to = { - asset: { - id: sell ? pool.x.asset.id : pool.y.asset.id, - decimals: sell ? pool.x.asset.decimals : pool.y.asset.decimals, - }, - amount: amount, - }; - const max_to = { - asset: { - id: sell ? pool.x.asset.id : pool.y.asset.id, - }, - amount: amount, - }; - const from = { - asset: { - id: sell ? pool.y.asset.id : pool.x.asset.id, - decimals: sell ? pool.y.asset.decimals : pool.x.asset.decimals, - }, - amount: pool.outputAmount( - max_to as any, - slippage || config.network.defaultSlippage, - ).amount, - }; - if (from.amount === BigInt(0)) - throw new Error(`${amount} asset from ${max_to.asset.id} is not enough!`); - const { baseInput, baseInputAmount, minOutput } = getBaseInputParameters( - pool, - { - inputAmount: from, - slippage: slippage || config.network.defaultSlippage, - }, + const pools = this.getPoolByToken(baseToken, quoteToken); + const realBaseToken = this.storedAssetList.find( + (asset) => asset.symbol === baseToken, ); - const swapVariables: [number, SwapExtremums] | undefined = swapVars( - BigInt(config.network.defaultMinerFee.multipliedBy(3).toString()), - config.network.minNitro, - minOutput, + const realQuoteToken = this.storedAssetList.find( + (asset) => asset.symbol === quoteToken, ); - if (!swapVariables) throw new Error('error in swap vars!'); - const [exFeePerToken, extremum] = swapVariables; - const inputs = getInputs( - utxos.map((utxo) => { - const temp = Object(utxo); - temp.value = BigNumber(temp.value); - temp.assets = temp.assets.map((asset: any) => { - const temp2 = Object(asset); - temp2.amount = BigNumber(temp2.amount); - return temp2; - }); - return temp; - }), - [new AssetAmount(from.asset, BigInt(baseInputAmount.toString()))], - { - minerFee: BigInt(config.network.defaultMinerFee.toString()), + if (!realBaseToken || !realQuoteToken) + throw new Error(`${baseToken} or ${quoteToken} not found!`); + for (const pool of pools) { + if (!pool) + throw new Error(`pool not found base on ${baseToken}, ${quoteToken}`); + if (pool.x.asset.id === baseToken) { + sell = false; + amount = value.multipliedBy( + BigNumber(10).pow(pool.y.asset.decimals as number), + ); + } else { + sell = true; + amount = value.multipliedBy( + BigNumber(10).pow(pool.x.asset.decimals as number), + ); + } + const config = getErgoConfig(this.network); + const networkContext = await this._explorer.getNetworkContext(); + const mainnetTxAssembler = new DefaultTxAssembler( + this.network === 'mainnet', + ); + const poolActions = makeWrappedNativePoolActionsSelector( + output_address, + account.prover, + mainnetTxAssembler, + ); + const utxos = await this.getAddressUnspentBoxes(account.address); + const to = { + asset: { + id: sell ? pool.x.asset.id : pool.y.asset.id, + decimals: sell ? pool.x.asset.decimals : pool.y.asset.decimals, + }, + amount: BigInt(amount.toString()), + }; + const max_to = { + asset: { + id: sell ? pool.x.asset.id : pool.y.asset.id, + }, + amount: BigInt(amount.toString()), + }; + const from = { + asset: { + id: sell ? pool.y.asset.id : pool.x.asset.id, + decimals: sell ? pool.y.asset.decimals : pool.x.asset.decimals, + }, + amount: pool.outputAmount( + max_to as any, + slippage || config.network.defaultSlippage, + ).amount, + }; + if (from.amount === BigInt(0)) + throw new Error( + `${amount} asset from ${max_to.asset.id} is not enough!`, + ); + const { baseInput, baseInputAmount, minOutput } = getBaseInputParameters( + pool, + { + inputAmount: from, + slippage: slippage || config.network.defaultSlippage, + }, + ); + if (minOutput.amount === BigInt(0)) continue; + const swapVariables: [number, SwapExtremums] | undefined = swapVars( + BigInt(config.network.defaultMinerFee.multipliedBy(3).toString()), + config.network.minNitro, + minOutput, + ); + if (!swapVariables) throw new Error('error in swap vars!'); + const [exFeePerToken, extremum] = swapVariables; + const inputs = getInputs( + utxos.map((utxo) => { + const temp = Object(utxo); + temp.value = BigNumber(temp.value); + temp.assets = temp.assets.map((asset: any) => { + const temp2 = Object(asset); + temp2.amount = BigNumber(temp2.amount); + return temp2; + }); + return temp; + }), + [new AssetAmount(from.asset, BigInt(baseInputAmount.toString()))], + { + minerFee: BigInt(config.network.defaultMinerFee.toString()), + uiFee: BigInt(config.network.defaultMinerFee.toString()), + exFee: BigInt(extremum.maxExFee.toString()), + }, + ); + const pk = publicKeyFromAddress(output_address); + if (!pk) throw new Error(`output_address is not defined.`); + const swapParams: SwapParams = { + poolId: pool.id, + pk, + baseInput, + minQuoteOutput: extremum.minOutput.amount, + exFeePerToken, uiFee: BigInt(config.network.defaultMinerFee.toString()), - exFee: BigInt(extremum.maxExFee.toString()), - }, - ); - const pk = publicKeyFromAddress(output_address); - if (!pk) throw new Error(`output_address is not defined.`); - const swapParams: SwapParams = { - poolId: pool.id, - pk, - baseInput, - minQuoteOutput: extremum.minOutput.amount, - exFeePerToken, - uiFee: BigInt(config.network.defaultMinerFee.toString()), - quoteAsset: to.asset.id, - poolFeeNum: pool.poolFeeNum, - maxExFee: extremum.maxExFee, - }; - const txContext: TransactionContext = getTxContext( - inputs, - networkContext as NetworkContext, - return_address, - BigInt(config.network.defaultMinerFee.toString()), - ); - const actions = poolActions(pool); - const timestamp = ( - await this._node.getBlockInfo(networkContext.height.toString()) - ).header.timestamp; - const tx = await actions.swap(swapParams, txContext); + quoteAsset: to.asset.id, + poolFeeNum: pool.poolFeeNum, + maxExFee: extremum.maxExFee, + }; + const txContext: TransactionContext = getTxContext( + inputs, + networkContext as NetworkContext, + return_address, + BigInt(config.network.defaultMinerFee.toString()), + ); + const actions = poolActions(pool); + const timestamp = ( + await this._node.getBlockInfo(networkContext.height.toString()) + ).header.timestamp; + const tx = await actions.swap(swapParams, txContext); + return { + network: this.network, + timestamp, + latency: 0, + base: baseToken, + quote: quoteToken, + amount: + sell === false + ? amount + .div(BigNumber(10).pow(pool.y.asset.decimals as number)) + .toString() + : amount + .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + .toString(), + rawAmount: + sell === false + ? amount + .div(BigNumber(10).pow(pool.y.asset.decimals as number)) + .toString() + : amount + .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + .toString(), + expectedOut: + sell === false + ? BigNumber(minOutput.amount.toString()) + .div(BigNumber(10).pow(pool.y.asset.decimals as number)) + .toString() + : BigNumber(minOutput.amount.toString()) + .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + .toString(), + price: + sell === false + ? BigNumber(minOutput.amount.toString()) + .div(BigNumber(10).pow(pool.y.asset.decimals as number)) + .div( + BigNumber(from.amount.toString()).div( + BigNumber(10).pow(pool.x.asset.decimals as number), + ), + ) + .toString() + : BigNumber(minOutput.amount.toString()) + .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + .div( + BigNumber(from.amount.toString()).div( + BigNumber(10).pow(pool.y.asset.decimals as number), + ), + ) + .toString(), + gasPrice: 0, + gasPriceToken: '0', + gasLimit: 0, + gasCost: '0', + txHash: tx.id, + }; + } return { network: this.network, - timestamp, + timestamp: 0, latency: 0, base: baseToken, quote: quoteToken, - amount: amount.toString(), - rawAmount: amount.toString(), - expectedOut: minOutput.amount.toString(), - price: sell - ? pool.priceX.numerator.toString() - : pool.priceY.numerator.toString(), // Cosmos: finalPrice + amount: '0', + rawAmount: '0', + expectedOut: '0', + price: '0', gasPrice: 0, gasPriceToken: '0', gasLimit: 0, gasCost: '0', - txHash: tx.id, + txHash: '', }; } @@ -607,51 +681,114 @@ export class Ergo { ): Promise { let sell: boolean; let amount: BigNumber; - console.log(baseToken, quoteToken); - const pool = this.getPoolByToken(baseToken, quoteToken); - if (!pool) + const pools = this.getPoolByToken(baseToken, quoteToken); + if (!pools.length) throw new Error(`pool not found base on ${baseToken}, ${quoteToken}`); - if (pool.x.asset.id === baseToken){sell = false; - amount = value.multipliedBy( - BigNumber(10).pow(pool.y.asset.decimals as number), - ); - } else { - sell = true; - amount = value.multipliedBy( - BigNumber(10).pow(pool.x.asset.decimals as number), - ); + const realBaseToken = this.storedAssetList.find( + (asset) => asset.symbol === baseToken, + ); + const realQuoteToken = this.storedAssetList.find( + (asset) => asset.symbol === quoteToken, + ); + if (!realBaseToken || !realQuoteToken) + throw new Error(`${baseToken} or ${quoteToken} not found!`); + for (const pool of pools) { + if (pool.x.asset.id === realBaseToken.tokenId) { + sell = false; + amount = value.multipliedBy( + BigNumber(10).pow(pool.y.asset.decimals as number), + ); + } else { + sell = true; + amount = value.multipliedBy( + BigNumber(10).pow(pool.x.asset.decimals as number), + ); + } + const config = getErgoConfig(this.network); + const max_to = { + asset: { + id: sell ? pool.x.asset.id : pool.y.asset.id, + decimals: sell ? pool.x.asset.decimals : pool.y.asset.decimals, + }, + amount: BigInt(amount.toString()), + }; + const from = { + asset: { + id: sell ? pool.y.asset.id : pool.x.asset.id, + decimals: sell ? pool.y.asset.decimals : pool.x.asset.decimals, + }, + amount: pool.outputAmount( + max_to as any, + slippage || config.network.defaultSlippage, + ).amount, + }; + const { minOutput } = getBaseInputParameters(pool, { + inputAmount: from, + slippage: slippage || config.network.defaultSlippage, + }); + if (minOutput.amount === BigInt(0)) continue; + return { + base: realBaseToken.symbol, + quote: realQuoteToken.symbol, + amount: + sell === false + ? amount + .div(BigNumber(10).pow(pool.y.asset.decimals as number)) + .toString() + : amount + .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + .toString(), + rawAmount: + sell === false + ? amount + .div(BigNumber(10).pow(pool.y.asset.decimals as number)) + .toString() + : amount + .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + .toString(), + expectedAmount: + sell === false + ? BigNumber(minOutput.amount.toString()) + .div(BigNumber(10).pow(pool.y.asset.decimals as number)) + .toString() + : BigNumber(minOutput.amount.toString()) + .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + .toString(), + price: + sell === false + ? BigNumber(minOutput.amount.toString()) + .div(BigNumber(10).pow(pool.y.asset.decimals as number)) + .div( + BigNumber(from.amount.toString()).div( + BigNumber(10).pow(pool.x.asset.decimals as number), + ), + ) + .toString() + : BigNumber(minOutput.amount.toString()) + .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + .div( + BigNumber(from.amount.toString()).div( + BigNumber(10).pow(pool.y.asset.decimals as number), + ), + ) + .toString(), + network: this.network, + timestamp: Date.now(), + latency: 0, + gasPrice: 0, + gasPriceToken: '0', + gasLimit: 0, + gasCost: '0', + }; } - const config = getErgoConfig(this.network); - const max_to = { - asset: { - id: sell ? pool.x.asset.id : pool.y.asset.id, - }, - amount, - }; - const from = { - asset: { - id: sell ? pool.y.asset.id : pool.x.asset.id, - decimals: sell ? pool.y.asset.decimals : pool.x.asset.decimals, - }, - amount: pool.outputAmount( - max_to as any, - slippage || config.network.defaultSlippage, - ).amount, - }; - const { minOutput } = getBaseInputParameters(pool, { - inputAmount: from, - slippage: slippage || config.network.defaultSlippage, - }); return { - base: baseToken, - quote: quoteToken, - amount: amount.toString(), - rawAmount: amount.toString(), - expectedAmount: minOutput.amount.toString(), - price: sell - ? pool.priceX.numerator.toString() - : pool.priceY.numerator.toString(), + base: realBaseToken.symbol, + quote: realQuoteToken.symbol, + amount: '0', + rawAmount: '0', + expectedAmount: '0', + price: '0', network: this.network, timestamp: Date.now(), latency: 0, @@ -666,7 +803,7 @@ export class Ergo { return this.ammPools.find((ammPool) => ammPool.id === id); } - public getPoolByToken(baseToken: string, quoteToken: string): Pool { + public getPoolByToken(baseToken: string, quoteToken: string): Pool[] { const realBaseToken = this.storedAssetList.find( (asset) => asset.symbol === baseToken, ); @@ -675,8 +812,8 @@ export class Ergo { ); if (!realBaseToken || !realQuoteToken) throw new Error(`${baseToken} or ${quoteToken} not found!`); - return ( - this.ammPools.find( + return ( + this.ammPools.filter( (ammPool) => (ammPool.x.asset.id === realBaseToken.tokenId && ammPool.y.asset.id === realQuoteToken.tokenId) || diff --git a/src/connectors/spectrum/spectrum.ts b/src/connectors/spectrum/spectrum.ts index 42830d2478..a88c673fa2 100644 --- a/src/connectors/spectrum/spectrum.ts +++ b/src/connectors/spectrum/spectrum.ts @@ -71,12 +71,27 @@ export class Spectrum { * @param amount Amount of `baseToken` desired from the transaction */ async estimateTrade(req: PriceRequest) { - return this.ergo.estimate( - req.base, - req.quote, - BigNumber(req.amount), - Number(req.allowedSlippage), - ); + if (req.side === 'BUY') + return this.ergo.estimate( + req.base, + req.quote, + BigNumber(req.amount), + Number(req.allowedSlippage), + ); + else if (req.side === 'SELL') + return this.ergo.estimate( + req.quote, + req.base, + BigNumber(req.amount), + Number(req.allowedSlippage), + ); + else + return this.ergo.estimate( + req.base, + req.quote, + BigNumber(req.amount), + Number(req.allowedSlippage), + ); } /** From 7872156fb77128c66436a22682606f008bee4468 Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Wed, 17 Jul 2024 02:54:44 +0330 Subject: [PATCH 096/132] ergo interface fixed --- src/chains/ergo/ergo.controller.ts | 10 +++- src/chains/ergo/ergo.ts | 45 ++++++++++---- src/chains/ergo/ergo.util.ts | 4 +- src/chains/ergo/interfaces/ergo.interface.ts | 6 +- .../ergo/interfaces/requests.interface.ts | 7 ++- src/chains/ergo/node.service.ts | 9 ++- src/connectors/spectrum/spectrum.ts | 59 +++++++++++++------ 7 files changed, 99 insertions(+), 41 deletions(-) diff --git a/src/chains/ergo/ergo.controller.ts b/src/chains/ergo/ergo.controller.ts index 0045f112be..e6786fda9a 100644 --- a/src/chains/ergo/ergo.controller.ts +++ b/src/chains/ergo/ergo.controller.ts @@ -31,8 +31,14 @@ export class ErgoController { if (!ergo.ready) { await ergo.init(); } - - return await ergo.getTx(req.txId); + const tx = await ergo.getTx(req.txId); + return { + ...tx, + currentBlock: Number(tx?.inclusionHeight), + txBlock: Number(tx?.inclusionHeight), + txHash: tx.id, + fee: 0, + }; } static async balances( diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 2fd530f199..ffb0736e30 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -18,6 +18,7 @@ import { ErgoAsset, ErgoBox, ErgoConnectedInstance, + ErgoTxFull, } from './interfaces/ergo.interface'; import { AmmPool, @@ -29,7 +30,6 @@ import { } from '@patternglobal/ergo-dex-sdk'; import { Explorer, - ErgoTx, DefaultTxAssembler, AssetAmount, publicKeyFromAddress, @@ -43,6 +43,9 @@ import { getBaseInputParameters, getInputs, getTxContext } from './ergo.util'; import { WalletProver } from './wallet-prover.service'; import { BigNumber } from 'bignumber.js'; import { PriceResponse, TradeResponse } from '../../amm/amm.requests'; +import { walletPath } from '../../services/base'; +import fse from 'fs-extra'; +import { ConfigManagerCertPassphrase } from '../../services/config-manager-cert-passphrase'; class Pool extends AmmPool { private _name: string; @@ -308,6 +311,20 @@ export class Ergo { return `${iv.toString('hex')}:${encrypted.toString('hex')}`; } + public async getAccountFromAddress(address: string): Promise { + const path = `${walletPath}/${this._chain}`; + const encryptedMnemonic: string = await fse.readFile( + `${path}/${address}.json`, + 'utf8', + ); + const passphrase = ConfigManagerCertPassphrase.readPassphrase(); + if (!passphrase) { + throw new Error('missing passphrase'); + } + const mnemonic = this.decrypt(encryptedMnemonic, passphrase); + return this.getAccountFromMnemonic(mnemonic); + } + /** * Decrypt encrypted secret key via password * @param {string} encryptedSecret - Secret key @@ -494,7 +511,7 @@ export class Ergo { for (const pool of pools) { if (!pool) throw new Error(`pool not found base on ${baseToken}, ${quoteToken}`); - if (pool.x.asset.id === baseToken) { + if (pool.x.asset.id === realBaseToken.tokenId) { sell = false; amount = value.multipliedBy( BigNumber(10).pow(pool.y.asset.decimals as number), @@ -506,16 +523,6 @@ export class Ergo { ); } const config = getErgoConfig(this.network); - const networkContext = await this._explorer.getNetworkContext(); - const mainnetTxAssembler = new DefaultTxAssembler( - this.network === 'mainnet', - ); - const poolActions = makeWrappedNativePoolActionsSelector( - output_address, - account.prover, - mainnetTxAssembler, - ); - const utxos = await this.getAddressUnspentBoxes(account.address); const to = { asset: { id: sell ? pool.x.asset.id : pool.y.asset.id, @@ -551,6 +558,16 @@ export class Ergo { }, ); if (minOutput.amount === BigInt(0)) continue; + const networkContext = await this._explorer.getNetworkContext(); + const mainnetTxAssembler = new DefaultTxAssembler( + this.network === 'mainnet', + ); + const poolActions = makeWrappedNativePoolActionsSelector( + output_address, + account.prover, + mainnetTxAssembler, + ); + const utxos = await this.getAddressUnspentBoxes(account.address); const swapVariables: [number, SwapExtremums] | undefined = swapVars( BigInt(config.network.defaultMinerFee.multipliedBy(3).toString()), config.network.minNitro, @@ -558,6 +575,7 @@ export class Ergo { ); if (!swapVariables) throw new Error('error in swap vars!'); const [exFeePerToken, extremum] = swapVariables; + const inputs = getInputs( utxos.map((utxo) => { const temp = Object(utxo); @@ -600,6 +618,7 @@ export class Ergo { await this._node.getBlockInfo(networkContext.height.toString()) ).header.timestamp; const tx = await actions.swap(swapParams, txContext); + await account.prover.submit(tx); return { network: this.network, timestamp, @@ -823,7 +842,7 @@ export class Ergo { ); } - public async getTx(id: string): Promise { + public async getTx(id: string): Promise { return await this._node.getTxsById(id); } } diff --git a/src/chains/ergo/ergo.util.ts b/src/chains/ergo/ergo.util.ts index 7489c4ab1f..996b439283 100644 --- a/src/chains/ergo/ergo.util.ts +++ b/src/chains/ergo/ergo.util.ts @@ -57,10 +57,10 @@ export function getInputs( const inputs = DefaultBoxSelector.select( utxos.map((utxo) => { const temp = Object(utxo); - temp.value = temp.value.toString(); + temp.value = BigInt(temp.value.toString()); temp.assets = temp.assets.map((asset: ErgoBoxAsset) => { const temp2 = Object(asset); - temp2.amount = temp2.amount.toString(); + temp2.amount = BigInt(temp2.amount.toString()); return temp2; }); return temp; diff --git a/src/chains/ergo/interfaces/ergo.interface.ts b/src/chains/ergo/interfaces/ergo.interface.ts index a0bcd729a5..59ecd2a8b1 100644 --- a/src/chains/ergo/interfaces/ergo.interface.ts +++ b/src/chains/ergo/interfaces/ergo.interface.ts @@ -1,7 +1,7 @@ import { NetworkPrefix } from 'ergo-lib-wasm-nodejs'; import { Wallet } from 'ergo-lib-wasm-nodejs'; import { Ergo } from '../ergo'; -import { AssetAmount } from '@patternglobal/ergo-sdk'; +import { AssetAmount, ErgoTx } from "@patternglobal/ergo-sdk"; import { WalletProver } from '../wallet-prover.service'; import { BigNumber } from 'bignumber.js'; @@ -70,3 +70,7 @@ export interface BaseInputParameters { baseInputAmount: BigNumber; minOutput: AssetAmount; } + +export interface ErgoTxFull extends ErgoTx { + inclusionHeight: string; +} diff --git a/src/chains/ergo/interfaces/requests.interface.ts b/src/chains/ergo/interfaces/requests.interface.ts index c2104e8710..35a4bdc683 100644 --- a/src/chains/ergo/interfaces/requests.interface.ts +++ b/src/chains/ergo/interfaces/requests.interface.ts @@ -16,7 +16,12 @@ export interface PoolResponse { feeDenom: bigint; } -export interface PollResponse extends ErgoTx {} +export interface PollResponse extends ErgoTx { + currentBlock: number; + txBlock: number | null; + txHash: string; + fee: number; +} export interface PollRequest { txId: string; } diff --git a/src/chains/ergo/node.service.ts b/src/chains/ergo/node.service.ts index 221ed4b6d1..765fbf54ef 100644 --- a/src/chains/ergo/node.service.ts +++ b/src/chains/ergo/node.service.ts @@ -9,7 +9,7 @@ import { ErgoStateContext, PreHeader, } from 'ergo-lib-wasm-nodejs'; -import { ErgoTx } from '@patternglobal/ergo-sdk'; +import { ErgoTxFull } from './interfaces/ergo.interface'; /** * This class allows you to access elements of a node @@ -103,8 +103,11 @@ export class NodeService { tx, ); } - async getTxsById(id: string): Promise { - return this.request('GET', `/blockchain/transaction/byId/${id}`); + async getTxsById(id: string): Promise { + return this.request( + 'GET', + `/blockchain/transaction/byId/${id}`, + ); } async getBlockInfo(blockHeight: string): Promise { diff --git a/src/connectors/spectrum/spectrum.ts b/src/connectors/spectrum/spectrum.ts index a88c673fa2..939ce393b1 100644 --- a/src/connectors/spectrum/spectrum.ts +++ b/src/connectors/spectrum/spectrum.ts @@ -71,24 +71,24 @@ export class Spectrum { * @param amount Amount of `baseToken` desired from the transaction */ async estimateTrade(req: PriceRequest) { - if (req.side === 'BUY') + if (req.side === 'SELL') return this.ergo.estimate( - req.base, - req.quote, + req.base.replace("_", ""), + req.quote.replace("_", ""), BigNumber(req.amount), Number(req.allowedSlippage), ); - else if (req.side === 'SELL') + else if (req.side === 'BUY') return this.ergo.estimate( - req.quote, - req.base, + req.quote.replace("_", ""), + req.base.replace("_", ""), BigNumber(req.amount), Number(req.allowedSlippage), ); else return this.ergo.estimate( - req.base, - req.quote, + req.base.replace("_", ""), + req.quote.replace("_", ""), BigNumber(req.amount), Number(req.allowedSlippage), ); @@ -101,17 +101,38 @@ export class Spectrum { * @param trade Expected trade */ async executeTrade(req: TradeRequest) { - const account = this.ergo.getAccountFromMnemonic( - req.mnemonic as unknown as string, - ); - return this.ergo.swap( - account, - req.base, - req.quote, - BigNumber(req.amount), - req.address, - req.address, - Number(req.allowedSlippage), + const account = await this.ergo.getAccountFromAddress( + req.address as unknown as string, ); + if (req.side === 'SELL') + return this.ergo.swap( + account, + req.base.replace("_", ""), + req.quote.replace("_", ""), + BigNumber(req.amount), + req.address, + req.address, + Number(req.allowedSlippage), + ); + else if (req.side === 'BUY') + return this.ergo.swap( + account, + req.quote.replace("_", ""), + req.base.replace("_", ""), + BigNumber(req.amount), + req.address, + req.address, + Number(req.allowedSlippage), + ); + else + return this.ergo.swap( + account, + req.base.replace("_", ""), + req.quote.replace("_", ""), + BigNumber(req.amount), + req.address, + req.address, + Number(req.allowedSlippage), + ); } } From f41a1c5a453625c3a363bce8921b840203b963d1 Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Wed, 17 Jul 2024 03:19:29 +0330 Subject: [PATCH 097/132] ergo interface fixed --- src/chains/ergo/node.service.ts | 7 ++++--- src/chains/ergo/wallet-prover.service.ts | 3 +-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/chains/ergo/node.service.ts b/src/chains/ergo/node.service.ts index 765fbf54ef..e05db17b27 100644 --- a/src/chains/ergo/node.service.ts +++ b/src/chains/ergo/node.service.ts @@ -3,7 +3,7 @@ import { NodeChainSliceResponse, NodeInfoResponse, } from './interfaces/node.interface'; -import { NodeErgoBoxResponse, NodeErgoPostTxResponse } from './types/node.type'; +import { NodeErgoBoxResponse } from './types/node.type'; import { BlockHeaders, ErgoStateContext, @@ -96,13 +96,14 @@ export class NodeService { } async postTransaction(tx: any): Promise { - return this.request( + return this.request( 'POST', `/transactions`, - { 'Content-Type': 'text/plain' }, + { 'Content-Type': 'application/json' }, tx, ); } + async getTxsById(id: string): Promise { return this.request( 'GET', diff --git a/src/chains/ergo/wallet-prover.service.ts b/src/chains/ergo/wallet-prover.service.ts index 3ccf23d602..0cbcf487fd 100644 --- a/src/chains/ergo/wallet-prover.service.ts +++ b/src/chains/ergo/wallet-prover.service.ts @@ -39,8 +39,7 @@ export class WalletProver implements Prover { } async submit(tx: ErgoTx): Promise { - const txId = await this.nodeService.postTransaction(tx); - + const txId = await this.nodeService.postTransaction(JSON.stringify(tx)); return { ...tx, id: txId, From 08c17191915da3341d6137b9a2766fb9a32bc38c Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Wed, 17 Jul 2024 03:23:49 +0330 Subject: [PATCH 098/132] ergo interface fixed --- src/chains/ergo/ergo.ts | 3 ++- src/chains/ergo/node.service.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index ffb0736e30..4d931e84a4 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -618,7 +618,8 @@ export class Ergo { await this._node.getBlockInfo(networkContext.height.toString()) ).header.timestamp; const tx = await actions.swap(swapParams, txContext); - await account.prover.submit(tx); + const submit_tx = await account.prover.submit(tx); + if (!submit_tx.id) throw new Error(`error during submit tx!`); return { network: this.network, timestamp, diff --git a/src/chains/ergo/node.service.ts b/src/chains/ergo/node.service.ts index e05db17b27..57be2790c1 100644 --- a/src/chains/ergo/node.service.ts +++ b/src/chains/ergo/node.service.ts @@ -101,7 +101,7 @@ export class NodeService { `/transactions`, { 'Content-Type': 'application/json' }, tx, - ); + ).catch(() => ''); } async getTxsById(id: string): Promise { From 7c0d7aaeb6069f79a5dd1b43de0d89aa2387b90c Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Fri, 19 Jul 2024 01:30:35 +0330 Subject: [PATCH 099/132] bug fixed --- src/chains/ergo/ergo.controller.ts | 16 ++++++++++++++-- src/chains/ergo/ergo.ts | 2 +- src/chains/ergo/interfaces/requests.interface.ts | 2 +- src/chains/ergo/node.service.ts | 13 +++++++++---- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/chains/ergo/ergo.controller.ts b/src/chains/ergo/ergo.controller.ts index e6786fda9a..3874a88c20 100644 --- a/src/chains/ergo/ergo.controller.ts +++ b/src/chains/ergo/ergo.controller.ts @@ -31,12 +31,24 @@ export class ErgoController { if (!ergo.ready) { await ergo.init(); } - const tx = await ergo.getTx(req.txId); + const tx = await ergo.getTx(req.txHash); + if (!tx) + return { + id: '', + inputs: [], + dataInputs: [], + outputs: [], + size: 0, + currentBlock: 0, + txBlock: 0, + txHash: '', + fee: 0, + }; return { ...tx, currentBlock: Number(tx?.inclusionHeight), txBlock: Number(tx?.inclusionHeight), - txHash: tx.id, + txHash: tx?.id, fee: 0, }; } diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 4d931e84a4..f1a7844c15 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -843,7 +843,7 @@ export class Ergo { ); } - public async getTx(id: string): Promise { + public async getTx(id: string): Promise { return await this._node.getTxsById(id); } } diff --git a/src/chains/ergo/interfaces/requests.interface.ts b/src/chains/ergo/interfaces/requests.interface.ts index 35a4bdc683..07f161f952 100644 --- a/src/chains/ergo/interfaces/requests.interface.ts +++ b/src/chains/ergo/interfaces/requests.interface.ts @@ -23,7 +23,7 @@ export interface PollResponse extends ErgoTx { fee: number; } export interface PollRequest { - txId: string; + txHash: string; } export interface BalanceRequest extends NetworkSelectionRequest { diff --git a/src/chains/ergo/node.service.ts b/src/chains/ergo/node.service.ts index 57be2790c1..23bd5a2604 100644 --- a/src/chains/ergo/node.service.ts +++ b/src/chains/ergo/node.service.ts @@ -101,14 +101,19 @@ export class NodeService { `/transactions`, { 'Content-Type': 'application/json' }, tx, - ).catch(() => ''); + ).catch((error) => { + return ''; + }); } - async getTxsById(id: string): Promise { - return this.request( + async getTxsById(id: string): Promise { + const result = await this.request( 'GET', `/blockchain/transaction/byId/${id}`, - ); + ).catch((error) => { + return undefined; + }); + return result; } async getBlockInfo(blockHeight: string): Promise { From c7b7faad593777ccff60b604ca777fddc5997813 Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Fri, 19 Jul 2024 02:47:49 +0330 Subject: [PATCH 100/132] bug fixed --- src/chains/ergo/node.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chains/ergo/node.service.ts b/src/chains/ergo/node.service.ts index 23bd5a2604..17cd80d39e 100644 --- a/src/chains/ergo/node.service.ts +++ b/src/chains/ergo/node.service.ts @@ -101,7 +101,7 @@ export class NodeService { `/transactions`, { 'Content-Type': 'application/json' }, tx, - ).catch((error) => { + ).catch(() => { return ''; }); } From b3d7322c136108fac790b8c79efa5670095b2a5a Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Fri, 19 Jul 2024 02:49:12 +0330 Subject: [PATCH 101/132] bug fixed --- src/chains/ergo/node.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chains/ergo/node.service.ts b/src/chains/ergo/node.service.ts index 17cd80d39e..a64ace48bf 100644 --- a/src/chains/ergo/node.service.ts +++ b/src/chains/ergo/node.service.ts @@ -110,7 +110,7 @@ export class NodeService { const result = await this.request( 'GET', `/blockchain/transaction/byId/${id}`, - ).catch((error) => { + ).catch(() => { return undefined; }); return result; From 8231d4c7d161a8b168ffb8aea0e222b2951d2b9a Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Fri, 19 Jul 2024 02:54:23 +0330 Subject: [PATCH 102/132] BUY change to SELL --- src/connectors/spectrum/spectrum.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/connectors/spectrum/spectrum.ts b/src/connectors/spectrum/spectrum.ts index 939ce393b1..3d91d43005 100644 --- a/src/connectors/spectrum/spectrum.ts +++ b/src/connectors/spectrum/spectrum.ts @@ -71,14 +71,14 @@ export class Spectrum { * @param amount Amount of `baseToken` desired from the transaction */ async estimateTrade(req: PriceRequest) { - if (req.side === 'SELL') + if (req.side === 'BUY') return this.ergo.estimate( req.base.replace("_", ""), req.quote.replace("_", ""), BigNumber(req.amount), Number(req.allowedSlippage), ); - else if (req.side === 'BUY') + else if (req.side === 'SELL') return this.ergo.estimate( req.quote.replace("_", ""), req.base.replace("_", ""), @@ -104,7 +104,7 @@ export class Spectrum { const account = await this.ergo.getAccountFromAddress( req.address as unknown as string, ); - if (req.side === 'SELL') + if (req.side === 'BUY') return this.ergo.swap( account, req.base.replace("_", ""), @@ -114,7 +114,7 @@ export class Spectrum { req.address, Number(req.allowedSlippage), ); - else if (req.side === 'BUY') + else if (req.side === 'SELL') return this.ergo.swap( account, req.quote.replace("_", ""), From 02a08468e94c04c8b95de8557a6d8af6fb1c0e06 Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Fri, 19 Jul 2024 03:15:24 +0330 Subject: [PATCH 103/132] usdt changed to sigusd --- src/chains/ergo/ergo.ts | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index f1a7844c15..b11e71d20d 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -414,20 +414,12 @@ export class Ergo { const assetData = await this.getAssetData(); for (const result of assetData.tokens) { - if (result.ticker === 'SigUSD') - this._assetMap['USDT'] = { - tokenId: result.address, - decimals: result.decimals, - name: 'USDT', - symbol: 'USDT', - }; - else - this._assetMap[result.name.toUpperCase()] = { - tokenId: result.address, - decimals: result.decimals, - name: result.name, - symbol: result.ticker, - }; + this._assetMap[result.name.toUpperCase()] = { + tokenId: result.address, + decimals: result.decimals, + name: result.name, + symbol: result.ticker, + }; } this._assetMap['ERGO'] = { From e3cc09fbf2003c23a771c2d82e47b2a88987e15f Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Fri, 19 Jul 2024 15:27:14 +0330 Subject: [PATCH 104/132] max expected amount for multiple pool --- src/chains/ergo/ergo.ts | 419 +++++++++++++++++++++------------------- 1 file changed, 220 insertions(+), 199 deletions(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index b11e71d20d..9c07466cdf 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -500,6 +500,22 @@ export class Ergo { ); if (!realBaseToken || !realQuoteToken) throw new Error(`${baseToken} or ${quoteToken} not found!`); + let result = { + network: this.network, + timestamp: 0, + latency: 0, + base: baseToken, + quote: quoteToken, + amount: '0', + rawAmount: '0', + expectedOut: '0', + price: '0', + gasPrice: 0, + gasPriceToken: '0', + gasLimit: 0, + gasCost: '0', + txHash: '', + }; for (const pool of pools) { if (!pool) throw new Error(`pool not found base on ${baseToken}, ${quoteToken}`); @@ -550,139 +566,134 @@ export class Ergo { }, ); if (minOutput.amount === BigInt(0)) continue; - const networkContext = await this._explorer.getNetworkContext(); - const mainnetTxAssembler = new DefaultTxAssembler( - this.network === 'mainnet', - ); - const poolActions = makeWrappedNativePoolActionsSelector( - output_address, - account.prover, - mainnetTxAssembler, - ); - const utxos = await this.getAddressUnspentBoxes(account.address); - const swapVariables: [number, SwapExtremums] | undefined = swapVars( - BigInt(config.network.defaultMinerFee.multipliedBy(3).toString()), - config.network.minNitro, - minOutput, - ); - if (!swapVariables) throw new Error('error in swap vars!'); - const [exFeePerToken, extremum] = swapVariables; - - const inputs = getInputs( - utxos.map((utxo) => { - const temp = Object(utxo); - temp.value = BigNumber(temp.value); - temp.assets = temp.assets.map((asset: any) => { - const temp2 = Object(asset); - temp2.amount = BigNumber(temp2.amount); - return temp2; - }); - return temp; - }), - [new AssetAmount(from.asset, BigInt(baseInputAmount.toString()))], - { - minerFee: BigInt(config.network.defaultMinerFee.toString()), + const expectedOut = + sell === false + ? BigNumber(minOutput.amount.toString()).div( + BigNumber(10).pow(pool.y.asset.decimals as number), + ) + : BigNumber(minOutput.amount.toString()).div( + BigNumber(10).pow(pool.x.asset.decimals as number), + ); + if (expectedOut >= BigNumber(result.expectedOut)) { + const networkContext = await this._explorer.getNetworkContext(); + const mainnetTxAssembler = new DefaultTxAssembler( + this.network === 'mainnet', + ); + const poolActions = makeWrappedNativePoolActionsSelector( + output_address, + account.prover, + mainnetTxAssembler, + ); + const utxos = await this.getAddressUnspentBoxes(account.address); + const swapVariables: [number, SwapExtremums] | undefined = swapVars( + BigInt(config.network.defaultMinerFee.multipliedBy(3).toString()), + config.network.minNitro, + minOutput, + ); + if (!swapVariables) throw new Error('error in swap vars!'); + const [exFeePerToken, extremum] = swapVariables; + + const inputs = getInputs( + utxos.map((utxo) => { + const temp = Object(utxo); + temp.value = BigNumber(temp.value); + temp.assets = temp.assets.map((asset: any) => { + const temp2 = Object(asset); + temp2.amount = BigNumber(temp2.amount); + return temp2; + }); + return temp; + }), + [new AssetAmount(from.asset, BigInt(baseInputAmount.toString()))], + { + minerFee: BigInt(config.network.defaultMinerFee.toString()), + uiFee: BigInt(config.network.defaultMinerFee.toString()), + exFee: BigInt(extremum.maxExFee.toString()), + }, + ); + const pk = publicKeyFromAddress(output_address); + if (!pk) throw new Error(`output_address is not defined.`); + const swapParams: SwapParams = { + poolId: pool.id, + pk, + baseInput, + minQuoteOutput: extremum.minOutput.amount, + exFeePerToken, uiFee: BigInt(config.network.defaultMinerFee.toString()), - exFee: BigInt(extremum.maxExFee.toString()), - }, - ); - const pk = publicKeyFromAddress(output_address); - if (!pk) throw new Error(`output_address is not defined.`); - const swapParams: SwapParams = { - poolId: pool.id, - pk, - baseInput, - minQuoteOutput: extremum.minOutput.amount, - exFeePerToken, - uiFee: BigInt(config.network.defaultMinerFee.toString()), - quoteAsset: to.asset.id, - poolFeeNum: pool.poolFeeNum, - maxExFee: extremum.maxExFee, - }; - const txContext: TransactionContext = getTxContext( - inputs, - networkContext as NetworkContext, - return_address, - BigInt(config.network.defaultMinerFee.toString()), - ); - const actions = poolActions(pool); - const timestamp = ( - await this._node.getBlockInfo(networkContext.height.toString()) - ).header.timestamp; - const tx = await actions.swap(swapParams, txContext); - const submit_tx = await account.prover.submit(tx); - if (!submit_tx.id) throw new Error(`error during submit tx!`); - return { - network: this.network, - timestamp, - latency: 0, - base: baseToken, - quote: quoteToken, - amount: - sell === false - ? amount - .div(BigNumber(10).pow(pool.y.asset.decimals as number)) - .toString() - : amount - .div(BigNumber(10).pow(pool.x.asset.decimals as number)) - .toString(), - rawAmount: - sell === false - ? amount - .div(BigNumber(10).pow(pool.y.asset.decimals as number)) - .toString() - : amount - .div(BigNumber(10).pow(pool.x.asset.decimals as number)) - .toString(), - expectedOut: - sell === false - ? BigNumber(minOutput.amount.toString()) - .div(BigNumber(10).pow(pool.y.asset.decimals as number)) - .toString() - : BigNumber(minOutput.amount.toString()) - .div(BigNumber(10).pow(pool.x.asset.decimals as number)) - .toString(), - price: - sell === false - ? BigNumber(minOutput.amount.toString()) - .div(BigNumber(10).pow(pool.y.asset.decimals as number)) - .div( - BigNumber(from.amount.toString()).div( - BigNumber(10).pow(pool.x.asset.decimals as number), - ), - ) - .toString() - : BigNumber(minOutput.amount.toString()) - .div(BigNumber(10).pow(pool.x.asset.decimals as number)) - .div( - BigNumber(from.amount.toString()).div( - BigNumber(10).pow(pool.y.asset.decimals as number), - ), - ) - .toString(), - gasPrice: 0, - gasPriceToken: '0', - gasLimit: 0, - gasCost: '0', - txHash: tx.id, - }; + quoteAsset: to.asset.id, + poolFeeNum: pool.poolFeeNum, + maxExFee: extremum.maxExFee, + }; + const txContext: TransactionContext = getTxContext( + inputs, + networkContext as NetworkContext, + return_address, + BigInt(config.network.defaultMinerFee.toString()), + ); + const actions = poolActions(pool); + const timestamp = ( + await this._node.getBlockInfo(networkContext.height.toString()) + ).header.timestamp; + const tx = await actions.swap(swapParams, txContext); + const submit_tx = await account.prover.submit(tx); + if (!submit_tx.id) throw new Error(`error during submit tx!`); + result = { + network: this.network, + timestamp, + latency: 0, + base: baseToken, + quote: quoteToken, + amount: + sell === false + ? amount + .div(BigNumber(10).pow(pool.y.asset.decimals as number)) + .toString() + : amount + .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + .toString(), + rawAmount: + sell === false + ? amount + .div(BigNumber(10).pow(pool.y.asset.decimals as number)) + .toString() + : amount + .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + .toString(), + expectedOut: + sell === false + ? BigNumber(minOutput.amount.toString()) + .div(BigNumber(10).pow(pool.y.asset.decimals as number)) + .toString() + : BigNumber(minOutput.amount.toString()) + .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + .toString(), + price: + sell === false + ? BigNumber(minOutput.amount.toString()) + .div(BigNumber(10).pow(pool.y.asset.decimals as number)) + .div( + BigNumber(from.amount.toString()).div( + BigNumber(10).pow(pool.x.asset.decimals as number), + ), + ) + .toString() + : BigNumber(minOutput.amount.toString()) + .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + .div( + BigNumber(from.amount.toString()).div( + BigNumber(10).pow(pool.y.asset.decimals as number), + ), + ) + .toString(), + gasPrice: 0, + gasPriceToken: '0', + gasLimit: 0, + gasCost: '0', + txHash: tx.id, + }; + } } - return { - network: this.network, - timestamp: 0, - latency: 0, - base: baseToken, - quote: quoteToken, - amount: '0', - rawAmount: '0', - expectedOut: '0', - price: '0', - gasPrice: 0, - gasPriceToken: '0', - gasLimit: 0, - gasCost: '0', - txHash: '', - }; + return result; } public async estimate( @@ -705,6 +716,21 @@ export class Ergo { ); if (!realBaseToken || !realQuoteToken) throw new Error(`${baseToken} or ${quoteToken} not found!`); + let result = { + base: realBaseToken.symbol, + quote: realQuoteToken.symbol, + amount: '0', + rawAmount: '0', + expectedAmount: '0', + price: '0', + network: this.network, + timestamp: Date.now(), + latency: 0, + gasPrice: 0, + gasPriceToken: '0', + gasLimit: 0, + gasCost: '0', + }; for (const pool of pools) { if (pool.x.asset.id === realBaseToken.tokenId) { sell = false; @@ -740,75 +766,70 @@ export class Ergo { slippage: slippage || config.network.defaultSlippage, }); if (minOutput.amount === BigInt(0)) continue; - return { - base: realBaseToken.symbol, - quote: realQuoteToken.symbol, - amount: - sell === false - ? amount - .div(BigNumber(10).pow(pool.y.asset.decimals as number)) - .toString() - : amount - .div(BigNumber(10).pow(pool.x.asset.decimals as number)) - .toString(), - rawAmount: - sell === false - ? amount - .div(BigNumber(10).pow(pool.y.asset.decimals as number)) - .toString() - : amount - .div(BigNumber(10).pow(pool.x.asset.decimals as number)) - .toString(), - expectedAmount: - sell === false - ? BigNumber(minOutput.amount.toString()) - .div(BigNumber(10).pow(pool.y.asset.decimals as number)) - .toString() - : BigNumber(minOutput.amount.toString()) - .div(BigNumber(10).pow(pool.x.asset.decimals as number)) - .toString(), - price: - sell === false - ? BigNumber(minOutput.amount.toString()) - .div(BigNumber(10).pow(pool.y.asset.decimals as number)) - .div( - BigNumber(from.amount.toString()).div( - BigNumber(10).pow(pool.x.asset.decimals as number), - ), - ) - .toString() - : BigNumber(minOutput.amount.toString()) - .div(BigNumber(10).pow(pool.x.asset.decimals as number)) - .div( - BigNumber(from.amount.toString()).div( - BigNumber(10).pow(pool.y.asset.decimals as number), - ), - ) - .toString(), - network: this.network, - timestamp: Date.now(), - latency: 0, - gasPrice: 0, - gasPriceToken: '0', - gasLimit: 0, - gasCost: '0', - }; + const expectedAmount = + sell === false + ? BigNumber(minOutput.amount.toString()).div( + BigNumber(10).pow(pool.y.asset.decimals as number), + ) + : BigNumber(minOutput.amount.toString()).div( + BigNumber(10).pow(pool.x.asset.decimals as number), + ); + if (expectedAmount >= BigNumber(result.expectedAmount)) + result = { + base: realBaseToken.symbol, + quote: realQuoteToken.symbol, + amount: + sell === false + ? amount + .div(BigNumber(10).pow(pool.y.asset.decimals as number)) + .toString() + : amount + .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + .toString(), + rawAmount: + sell === false + ? amount + .div(BigNumber(10).pow(pool.y.asset.decimals as number)) + .toString() + : amount + .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + .toString(), + expectedAmount: + sell === false + ? BigNumber(minOutput.amount.toString()) + .div(BigNumber(10).pow(pool.y.asset.decimals as number)) + .toString() + : BigNumber(minOutput.amount.toString()) + .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + .toString(), + price: + sell === false + ? BigNumber(minOutput.amount.toString()) + .div(BigNumber(10).pow(pool.y.asset.decimals as number)) + .div( + BigNumber(from.amount.toString()).div( + BigNumber(10).pow(pool.x.asset.decimals as number), + ), + ) + .toString() + : BigNumber(minOutput.amount.toString()) + .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + .div( + BigNumber(from.amount.toString()).div( + BigNumber(10).pow(pool.y.asset.decimals as number), + ), + ) + .toString(), + network: this.network, + timestamp: Date.now(), + latency: 0, + gasPrice: 0, + gasPriceToken: '0', + gasLimit: 0, + gasCost: '0', + }; } - return { - base: realBaseToken.symbol, - quote: realQuoteToken.symbol, - amount: '0', - rawAmount: '0', - expectedAmount: '0', - price: '0', - network: this.network, - timestamp: Date.now(), - latency: 0, - gasPrice: 0, - gasPriceToken: '0', - gasLimit: 0, - gasCost: '0', - }; + return result; } public getPool(id: string): Pool { From c4c535d877da03a4c34118169a4992a00870b361 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Fri, 19 Jul 2024 17:00:12 +0330 Subject: [PATCH 105/132] add [unit-test]: Implement unit tests for ErgoController => "pool" method --- .../chains/ergo/ergo.controller.test.ts | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 test-bronze/chains/ergo/ergo.controller.test.ts diff --git a/test-bronze/chains/ergo/ergo.controller.test.ts b/test-bronze/chains/ergo/ergo.controller.test.ts new file mode 100644 index 0000000000..48f2433c04 --- /dev/null +++ b/test-bronze/chains/ergo/ergo.controller.test.ts @@ -0,0 +1,42 @@ +import { Ergo } from '../../../src/chains/ergo/ergo'; +import { ErgoController } from '../../../src/chains/ergo/ergo.controller'; + +describe('ErgoController', () => { + // const controller: ErgoController = new ErgoController(); + const ergo: Ergo = new Ergo('mainnet'); + describe('pool', () => { + it('Should be defined', () => { + expect(ErgoController.pool).toBeDefined(); + }); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('Should not call init from ergo if ergo is ready', async () => { + jest.spyOn(ergo, 'ready').mockReturnValue(true); + ergo['_ready'] = false; + jest.spyOn(ergo, 'getPool').mockReturnValue({ info: 'info' } as any); + const result = await ErgoController.pool(ergo, { + network: 'mainnet', + poolId: 'poolId', + }); + expect(ergo.getPool).toHaveBeenCalled(); + expect(result).toEqual('info'); + }); + + it('Should call init from ergo if ergo is not ready', async () => { + jest.spyOn(ergo, 'ready').mockReturnValue(false); + jest.spyOn(ergo, 'init').mockResolvedValue({} as any); + jest.spyOn(ergo, 'getPool').mockReturnValue({ info: 'info' } as any); + const result = await ErgoController.pool(ergo, { + network: 'mainnet', + poolId: 'poolId', + }); + + expect(ergo.getPool).toHaveBeenCalled(); + expect(ergo.init).toHaveBeenCalled(); + expect(result).toEqual('info'); + }); + }); +}); From d29fc34d3c97a8ae0b289b26960a298b40439e5c Mon Sep 17 00:00:00 2001 From: satiparpar Date: Fri, 19 Jul 2024 17:02:55 +0330 Subject: [PATCH 106/132] fix [ ErgoController ]: fix wrong call on ergo.ready method --- src/chains/ergo/ergo.controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chains/ergo/ergo.controller.ts b/src/chains/ergo/ergo.controller.ts index 3874a88c20..8bb937680b 100644 --- a/src/chains/ergo/ergo.controller.ts +++ b/src/chains/ergo/ergo.controller.ts @@ -20,7 +20,7 @@ import { AllowancesRequest, AllowancesResponse } from '../chain.requests'; export class ErgoController { static async pool(ergo: Ergo, req: PoolRequest): Promise { - if (!ergo.ready) { + if (!ergo.ready()) { await ergo.init(); } From f05636507777776fcb97337af90165f8770690be Mon Sep 17 00:00:00 2001 From: satiparpar Date: Fri, 19 Jul 2024 17:14:41 +0330 Subject: [PATCH 107/132] fix [ ErgoController ]: fix ergo.ready call --- src/chains/ergo/ergo.controller.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/chains/ergo/ergo.controller.ts b/src/chains/ergo/ergo.controller.ts index 8bb937680b..63786bb01d 100644 --- a/src/chains/ergo/ergo.controller.ts +++ b/src/chains/ergo/ergo.controller.ts @@ -28,7 +28,7 @@ export class ErgoController { } static async poll(ergo: Ergo, req: PollRequest): Promise { - if (!ergo.ready) { + if (!ergo.ready()) { await ergo.init(); } const tx = await ergo.getTx(req.txHash); @@ -57,7 +57,7 @@ export class ErgoController { chain: Ergo, request: BalanceRequest, ): Promise { - if (!chain.ready) { + if (!chain.ready()) { await chain.init(); } const utxos = await chain.getAddressUnspentBoxes(request.address); @@ -85,7 +85,7 @@ export class ErgoController { ergo: Ergo, _req: TokensRequest, ): Promise { - if (!ergo.ready) { + if (!ergo.ready()) { await ergo.init(); } @@ -132,7 +132,7 @@ export class ErgoController { chain: Ergo, request: AllowancesRequest, ): Promise { - if (!chain.ready) { + if (!chain.ready()) { await chain.init(); } const utxos = await chain.getAddressUnspentBoxes(request.address); From 6ac88b92d0a87f05e47055ddfac1fc36dacecadd Mon Sep 17 00:00:00 2001 From: satiparpar Date: Sat, 20 Jul 2024 12:17:37 +0330 Subject: [PATCH 108/132] add [unit-test]: Implement unit tests for ErgoController => "pool" & "balances" methods --- .../chains/ergo/ergo.controller.test.ts | 147 +++++++++++++++++- 1 file changed, 141 insertions(+), 6 deletions(-) diff --git a/test-bronze/chains/ergo/ergo.controller.test.ts b/test-bronze/chains/ergo/ergo.controller.test.ts index 48f2433c04..87da53b6cf 100644 --- a/test-bronze/chains/ergo/ergo.controller.test.ts +++ b/test-bronze/chains/ergo/ergo.controller.test.ts @@ -1,28 +1,34 @@ import { Ergo } from '../../../src/chains/ergo/ergo'; import { ErgoController } from '../../../src/chains/ergo/ergo.controller'; +import { ErgoTxFull } from '../../../src/chains/ergo/interfaces/ergo.interface'; +import { BigNumber } from 'bignumber.js'; describe('ErgoController', () => { - // const controller: ErgoController = new ErgoController(); const ergo: Ergo = new Ergo('mainnet'); + afterEach(() => { + jest.clearAllMocks(); + }); + + it('Should be defined', () => { + expect(ErgoController).toBeDefined(); + }); + describe('pool', () => { it('Should be defined', () => { expect(ErgoController.pool).toBeDefined(); }); - beforeEach(() => { - jest.clearAllMocks(); - }); - it('Should not call init from ergo if ergo is ready', async () => { jest.spyOn(ergo, 'ready').mockReturnValue(true); - ergo['_ready'] = false; jest.spyOn(ergo, 'getPool').mockReturnValue({ info: 'info' } as any); + jest.spyOn(ergo, 'init').mockResolvedValue({} as any); const result = await ErgoController.pool(ergo, { network: 'mainnet', poolId: 'poolId', }); expect(ergo.getPool).toHaveBeenCalled(); expect(result).toEqual('info'); + expect(ergo.init).not.toHaveBeenCalled(); }); it('Should call init from ergo if ergo is not ready', async () => { @@ -39,4 +45,133 @@ describe('ErgoController', () => { expect(result).toEqual('info'); }); }); + + describe('poll', () => { + it('Should be defined', () => { + expect(ErgoController.poll).toBeDefined(); + }); + it('Should not call init from ergo if ergo is ready and return the correct answer basen on tx status', async () => { + jest.spyOn(ergo, 'ready').mockReturnValue(true); + jest.spyOn(ergo, 'getTx').mockResolvedValue(undefined); + const result = await ErgoController.poll(ergo, { + txHash: 'txHash', + }); + + expect(ergo.init).not.toHaveBeenCalled(); + expect(ergo.getTx).toHaveBeenCalledWith('txHash'); + expect(result).toEqual({ + id: '', + inputs: [], + dataInputs: [], + outputs: [], + size: 0, + currentBlock: 0, + txBlock: 0, + txHash: '', + fee: 0, + }); + }); + + it('Should call init from ergo if ergo is not ready and return the correct answer basen on tx status', async () => { + const tx: ErgoTxFull = { + id: 'txId', + inputs: [], + dataInputs: [], + outputs: [], + size: 100, + inclusionHeight: '100', + }; + jest.spyOn(ergo, 'ready').mockReturnValue(false); + jest.spyOn(ergo, 'init').mockResolvedValue({} as any); + jest.spyOn(ergo, 'getTx').mockResolvedValue(tx); + const result = await ErgoController.poll(ergo, { + txHash: 'txHash', + }); + expect(result).toEqual({ + id: 'txId', + inputs: [], + dataInputs: [], + outputs: [], + size: 100, + inclusionHeight: '100', + currentBlock: Number('100'), + txBlock: Number('100'), + txHash: 'txId', + fee: 0, + }); + expect(ergo.getTx).toHaveBeenCalledWith('txHash'); + expect(ergo.init).toHaveBeenCalled(); + }); + }); + + describe('balances', () => { + const request = { + chain: 'ergo', + network: 'mainnet', + address: 'usersPublicKey', + privateKey: 'privateKey', + }; + beforeEach(() => { + jest.spyOn(ergo, 'ready').mockReturnValue(true); + jest.spyOn(ergo, 'init').mockResolvedValue({} as any); + jest.spyOn(ergo, 'getAddressUnspentBoxes').mockResolvedValue([]); + jest.spyOn(ergo, 'getBalance').mockReturnValue({ + balance: BigNumber(0), + assets: {}, + }); + }); + it('Should be defined', () => { + expect(ErgoController.balances).toBeDefined(); + }); + it('Should call init from ergo if ergo is not ready', async () => { + jest.spyOn(ergo, 'ready').mockReturnValue(false); + await ErgoController.balances(ergo, request); + expect(ergo.init).toHaveBeenCalled(); + expect(ergo.ready).toHaveBeenCalled(); + }); + it('Should not call init from ergo if ergo is ready', async () => { + await ErgoController.balances(ergo, request); + expect(ergo.init).not.toHaveBeenCalled(); + expect(ergo.ready).toHaveBeenCalled(); + }); + + it('Should call getAddressUnspentBoxes & getBalance from ergo and return the correct data', async () => { + const result = await ErgoController.balances(ergo, request); + expect(ergo.getAddressUnspentBoxes).toHaveBeenCalledWith( + 'usersPublicKey', + ); + expect(ergo.getBalance).toHaveBeenCalledWith([]); + expect(result).toMatchObject({ + network: 'mainnet', + // timestamp ignored because there was a really small difference between create Date.new() in test file and main file + // timestamp: Date.now(), + latency: 0, + balances: { ERG: '0' }, + }); + }); + + it('Should iterate on assets returned from getBalance and return the correct data', async () => { + jest.spyOn(ergo, 'storedAssetList', 'get').mockReturnValue([ + { tokenId: 'token1', decimals: 9, name: 'name', symbol: 'TKN1' }, + { tokenId: 'token2', decimals: 3, name: 'name', symbol: 'TKN2' }, + ]); + + jest.spyOn(ergo, 'getBalance').mockReturnValue({ + balance: BigNumber(30000000000), + assets: { + token1: BigNumber(10000000000), + token2: BigNumber(20000000000), + }, + }); + const result = await ErgoController.balances(ergo, request); + console.log(result); + expect(result).toMatchObject({ + network: 'mainnet', + // timestamp ignored because there was a really small difference between create Date.new() in test file and main file + // timestamp: Date.now(), + latency: 0, + balances: { ERG: '30', TKN1: '10', TKN2: '20000000' }, + }); + }); + }); }); From 02249952b2c139aad3a634cb6cf3c53c0de3bac2 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Sun, 21 Jul 2024 11:26:56 +0330 Subject: [PATCH 109/132] add [unit-test]: Implement unit tests for ErgoController => "getTokens" & "transfer" methods --- .../chains/ergo/ergo.controller.test.ts | 122 ++++++++++++++++++ 1 file changed, 122 insertions(+) diff --git a/test-bronze/chains/ergo/ergo.controller.test.ts b/test-bronze/chains/ergo/ergo.controller.test.ts index 87da53b6cf..812662f396 100644 --- a/test-bronze/chains/ergo/ergo.controller.test.ts +++ b/test-bronze/chains/ergo/ergo.controller.test.ts @@ -1,7 +1,9 @@ +import { OutputBuilder, TransactionBuilder } from '@fleet-sdk/core'; import { Ergo } from '../../../src/chains/ergo/ergo'; import { ErgoController } from '../../../src/chains/ergo/ergo.controller'; import { ErgoTxFull } from '../../../src/chains/ergo/interfaces/ergo.interface'; import { BigNumber } from 'bignumber.js'; +import { TransferRequest } from '../../../src/chains/ergo/interfaces/requests.interface'; describe('ErgoController', () => { const ergo: Ergo = new Ergo('mainnet'); @@ -174,4 +176,124 @@ describe('ErgoController', () => { }); }); }); + + describe('getTokens', () => { + const mockStoredAssetList = [ + { tokenId: 'token1', decimals: 9, name: 'name', symbol: 'TKN1' }, + { tokenId: 'token2', decimals: 3, name: 'name', symbol: 'TKN2' }, + ]; + beforeEach(() => { + jest.spyOn(ergo, 'ready').mockReturnValue(true); + jest + .spyOn(ergo, 'storedAssetList', 'get') + .mockReturnValue(mockStoredAssetList); + }); + it('Should be defined', () => { + expect(ErgoController.getTokens).toBeDefined(); + }); + it('Should not call init from ergo if ergo is ready', async () => { + jest.spyOn(ergo, 'init').mockResolvedValue({} as any); + await ErgoController.getTokens(ergo, {}); + expect(ergo.init).not.toHaveBeenCalled(); + }); + + it('Should call init from ergo if ergo is not ready', async () => { + jest.spyOn(ergo, 'ready').mockReturnValue(false); + jest.spyOn(ergo, 'init').mockResolvedValue({} as any); + await ErgoController.getTokens(ergo, {}); + + expect(ergo.init).toHaveBeenCalled(); + expect(ergo.ready).toHaveBeenCalled(); + }); + + it('Should return correct data', async () => { + const result = await ErgoController.getTokens(ergo, {}); + expect(result).toEqual({ assets: mockStoredAssetList }); + }); + }); + + describe('transfer', () => { + const request: TransferRequest = { + fromAddress: '9huCzcjG9bmpKccftEauEYD6YP6qVpnJQXAtwuSpXy3WcMpYgFX', + toAddress: '9hA3BgMVWfLHTqAFbBCtHdPW7QRQDsMSQp8aaYiB6PiqVLLLAF1', + assets: [ + { tokenId: 'token1', amount: BigNumber(100) }, + { tokenId: 'token2', amount: BigNumber(200) }, + ], + toValue: '100000000', + }; + const mockFrom = new TransactionBuilder(1); + const mockTo = new TransactionBuilder(2); + const mockSendChangeTo = new TransactionBuilder(3); + const mockPayMinFee = new TransactionBuilder(4); + + const utxos = [ + { + value: 1000000000, + assets: [ + { tokenId: 'token1', amount: 100 }, + { tokenId: 'token2', amount: 200 }, + ], + }, + { + value: 2000000000, + assets: [{ tokenId: 'token3', amount: 300 }], + }, + ]; + it('Should be defined', () => { + expect(ErgoController.transfer).toBeDefined(); + }); + + it('Should return correct data', async () => { + jest.spyOn(ergo, 'getNetworkHeight').mockResolvedValue(100); + jest + .spyOn(ergo, 'getAddressUnspentBoxes') + .mockResolvedValue(utxos as any); + jest + .spyOn(TransactionBuilder.prototype, 'from') + .mockReturnValue(mockFrom); + jest.spyOn(TransactionBuilder.prototype, 'to').mockReturnValue(mockTo); + jest + .spyOn(TransactionBuilder.prototype, 'sendChangeTo') + .mockReturnValue(mockSendChangeTo); + jest + .spyOn(TransactionBuilder.prototype, 'build') + .mockReturnValue({} as any); + jest + .spyOn(TransactionBuilder.prototype, 'payMinFee') + .mockReturnValue(mockPayMinFee); + jest + .spyOn(OutputBuilder.prototype, 'addTokens') + .mockReturnValue({} as any); + const result = await ErgoController.transfer(ergo, request); + + expect(ergo.getAddressUnspentBoxes).toHaveBeenCalledWith( + '9huCzcjG9bmpKccftEauEYD6YP6qVpnJQXAtwuSpXy3WcMpYgFX', + ); + expect(ergo.getNetworkHeight).toHaveBeenCalled(); + expect(TransactionBuilder.prototype.from).toHaveBeenCalledWith([ + { + value: '1000000000', + assets: [ + { tokenId: 'token1', amount: '100' }, + { tokenId: 'token2', amount: '200' }, + ], + }, + { + value: '2000000000', + assets: [{ tokenId: 'token3', amount: '300' }], + }, + ]); + expect(OutputBuilder.prototype.addTokens).toHaveBeenCalledWith([ + { tokenId: 'token1', amount: '100' }, + { tokenId: 'token2', amount: '200' }, + ]); + expect(TransactionBuilder.prototype.sendChangeTo).toHaveBeenNthCalledWith( + '9huCzcjG9bmpKccftEauEYD6YP6qVpnJQXAtwuSpXy3WcMpYgFX', + ); + expect(TransactionBuilder.prototype.payMinFee).toHaveBeenCalled(); + expect(TransactionBuilder.prototype.build).toHaveBeenCalled(); + expect(result).toEqual({}); + }); + }); }); From ce0044a941cd2370f40dd7e0122ba00ef3601062 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Sun, 21 Jul 2024 16:50:17 +0330 Subject: [PATCH 110/132] add [unit-test]: Implement unit tests for ErgoController => "allowances" method --- .../chains/ergo/ergo.controller.test.ts | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/test-bronze/chains/ergo/ergo.controller.test.ts b/test-bronze/chains/ergo/ergo.controller.test.ts index 812662f396..585755acd5 100644 --- a/test-bronze/chains/ergo/ergo.controller.test.ts +++ b/test-bronze/chains/ergo/ergo.controller.test.ts @@ -296,4 +296,77 @@ describe('ErgoController', () => { expect(result).toEqual({}); }); }); + describe('allowances', () => { + const request = { + chain: 'ergo', + network: 'mainnet', + address: 'usersPublicEthereumKey', + spender: 'spenderAddress', + tokenSymbols: [], + }; + beforeEach(() => { + jest.spyOn(ergo, 'ready').mockReturnValue(true); + jest.spyOn(ergo, 'init').mockResolvedValue({} as any); + jest.spyOn(ergo, 'getAddressUnspentBoxes').mockResolvedValue([]); + jest.spyOn(ergo, 'getBalance').mockReturnValue({ + balance: BigNumber(0), + assets: {}, + }); + }); + it('Should be defined', () => { + expect(ErgoController.allowances).toBeDefined(); + }); + it('Should call init from ergo if ergo is not ready', async () => { + jest.spyOn(ergo, 'ready').mockReturnValue(false); + await ErgoController.allowances(ergo, request); + expect(ergo.init).toHaveBeenCalled(); + expect(ergo.ready).toHaveBeenCalled(); + }); + it('Should not call init from ergo if ergo is ready', async () => { + await ErgoController.allowances(ergo, request); + expect(ergo.init).not.toHaveBeenCalled(); + expect(ergo.ready).toHaveBeenCalled(); + }); + + it('Should call getAddressUnspentBoxes & getBalance from ergo and return the correct data', async () => { + const result = await ErgoController.allowances(ergo, request); + expect(ergo.getAddressUnspentBoxes).toHaveBeenCalledWith( + 'usersPublicEthereumKey', + ); + expect(ergo.getBalance).toHaveBeenCalledWith([]); + expect(result).toMatchObject({ + network: 'mainnet', + // timestamp ignored because there was a really small difference between create Date.new() in test file and main file + // timestamp: Date.now(), + latency: 0, + spender: 'spenderAddress', + approvals: { ERG: '0' }, + }); + }); + + it('Should iterate on assets returned from getBalance and return the correct data', async () => { + jest.spyOn(ergo, 'storedAssetList', 'get').mockReturnValue([ + { tokenId: 'token1', decimals: 9, name: 'name', symbol: 'TKN1' }, + { tokenId: 'token2', decimals: 3, name: 'name', symbol: 'TKN2' }, + ]); + + jest.spyOn(ergo, 'getBalance').mockReturnValue({ + balance: BigNumber(30000000000), + assets: { + token1: BigNumber(10000000000), + token2: BigNumber(20000000000), + }, + }); + const result = await ErgoController.allowances(ergo, request); + console.log(result); + expect(result).toMatchObject({ + network: 'mainnet', + // timestamp ignored because there was a really small difference between create Date.new() in test file and main file + // timestamp: Date.now(), + latency: 0, + spender: 'spenderAddress', + approvals: { ERG: '30', TKN1: '10', TKN2: '20000000' }, + }); + }); + }); }); From f7cc479dcc7a729db32e13808a1ccd7489b1a039 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Mon, 22 Jul 2024 16:49:34 +0330 Subject: [PATCH 111/132] update [unit-test]: update unit tests based on new updates for Ergo => "swap" mehtod --- test-bronze/chains/ergo/ergo.test.ts | 306 +++++++++++++++++++++------ 1 file changed, 236 insertions(+), 70 deletions(-) diff --git a/test-bronze/chains/ergo/ergo.test.ts b/test-bronze/chains/ergo/ergo.test.ts index efee2d7f08..7073db463e 100644 --- a/test-bronze/chains/ergo/ergo.test.ts +++ b/test-bronze/chains/ergo/ergo.test.ts @@ -48,6 +48,13 @@ jest.mock('@patternglobal/ergo-dex-sdk', () => ({ maxExFee: BigInt(1), }, ] as any) + .mockReturnValueOnce([ + 1, + { + minOutput: { amount: BigInt(1) }, + maxExFee: BigInt(1), + }, + ] as any) .mockReturnValueOnce([ 1, { @@ -65,6 +72,7 @@ jest.mock('@patternglobal/ergo-sdk', () => ({ .fn() .mockReturnValueOnce(undefined) .mockReturnValueOnce('publicKey') + .mockReturnValueOnce('publicKey') .mockReturnValueOnce('publicKey'), RustModule: { load: jest.fn().mockResolvedValue, @@ -1015,14 +1023,29 @@ describe('Ergo', () => { describe('swap', () => { const account: any = { address: 'address' }; - const baseToken: string = 'baseToken'; - const quoteToken: string = 'quoteToken'; + const baseToken: string = 'ERG'; + const quoteToken: string = 'SigUSD'; const value: BigNumber = BigNumber(10); const output_address: string = 'output_address'; const return_address: string = 'return_address'; const slippage: number = 10; beforeEach(() => { jest.spyOn(ergo, 'getAddressUnspentBoxes').mockResolvedValue([]); + jest.spyOn(ergo, 'storedAssetList', 'get').mockReturnValue([ + { + tokenId: 'SigUSDId', + decimals: 3, + name: 'SigUSD', + symbol: 'SigUSD', + }, + + { + tokenId: 'ERGId', + decimals: 9, + name: 'ergo', + symbol: 'ERG', + }, + ]); }); afterEach(() => { jest.clearAllMocks(); @@ -1045,16 +1068,16 @@ describe('Ergo', () => { withAmount: (_sth: any) => { return { asset: { - id: 'xId', - name: 'xName', + id: 'ERGId', + name: 'ergo', decimals: 9, }, amount: BigInt(752313805260857), }; }, asset: { - id: 'xId', - name: 'xName', + id: 'ERGId', + name: 'ergo', decimals: 9, }, }, @@ -1062,16 +1085,16 @@ describe('Ergo', () => { withAmount: (_sth: any) => { return { asset: { - id: 'yId', - name: 'yName', + id: 'SigUSDId', + name: 'SigUSD', decimals: 3, }, amount: BigInt(9322283969), }; }, asset: { - id: 'yId', - name: 'yName', + id: 'SigUSDId', + name: 'SigUSD', decimals: 3, }, }, @@ -1099,16 +1122,16 @@ describe('Ergo', () => { withAmount: (_sth: any) => { return { asset: { - id: 'xId', - name: 'xName', + id: 'ERGId', + name: 'ergo', decimals: 9, }, amount: BigInt(752313805260857), }; }, asset: { - id: 'xId', - name: 'xName', + id: 'ERGId', + name: 'ergo', decimals: 9, }, }, @@ -1116,16 +1139,16 @@ describe('Ergo', () => { withAmount: (_sth: any) => { return { asset: { - id: 'yId', - name: 'yName', + id: 'SigUSDId', + name: 'SigUSD', decimals: 3, }, amount: BigInt(9322283969), }; }, asset: { - id: 'yId', - name: 'yName', + id: 'SigUSDId', + name: 'SigUSD', decimals: 3, }, }, @@ -1141,8 +1164,17 @@ describe('Ergo', () => { it('Should be defined', () => { expect(ergo.swap).toBeDefined(); }); - it('Should throw new Error if pool is not found base on baseToken and quoteToken', async () => { - jest.spyOn(ergo, 'getPoolByToken').mockReturnValue(null as any); + it('Should throw new Error if baseToken is available but quoteToken is not available on storedAssetList', async () => { + jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([]); + // ERG is available but SigUSD is not + jest.spyOn(ergo, 'storedAssetList', 'get').mockReturnValue([ + { + tokenId: 'ERGId', + decimals: 9, + name: 'ergo', + symbol: 'ERG', + }, + ]); await expect( ergo.swap( account, @@ -1152,12 +1184,38 @@ describe('Ergo', () => { output_address, return_address, ), - ).rejects.toThrow(`pool not found base on ${baseToken}, ${quoteToken}`); + ).rejects.toThrow(`${baseToken} or ${quoteToken} not found!`); expect(ergo.getPoolByToken).toHaveBeenCalledWith(baseToken, quoteToken); }); - it(`Should throw new Error if 'from.amount === 0' and sell is 'true'`, async () => { - jest.spyOn(ergo, 'getPoolByToken').mockReturnValue(poolWithOutputAmount0); + it('Should throw new Error if quoteToken is available but baseToken is not available on storedAssetList', async () => { + jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([]); + // SigUSD is available but ERG is not + jest.spyOn(ergo, 'storedAssetList', 'get').mockReturnValue([ + { + tokenId: 'SigUSDId', + decimals: 3, + name: 'SigUSD', + symbol: 'SigUSD', + }, + ]); + await expect( + ergo.swap( + account, + baseToken, + quoteToken, + value, + output_address, + return_address, + ), + ).rejects.toThrow(`${baseToken} or ${quoteToken} not found!`); + expect(ergo.getPoolByToken).toHaveBeenCalledWith(baseToken, quoteToken); + }); + + it(`Should throw new Error if 'from.amount === 0' and sell is 'false'`, async () => { + jest + .spyOn(ergo, 'getPoolByToken') + .mockReturnValue([poolWithOutputAmount0]); patchGetErgoConfig('mainnet'); await expect( ergo.swap( @@ -1170,16 +1228,18 @@ describe('Ergo', () => { ), ).rejects.toThrow( `${value.multipliedBy( - BigNumber(10).pow(pool.x.asset.decimals as number), - )} asset from xId is not enough!`, + BigNumber(10).pow(pool.y.asset.decimals as number), + )} asset from SigUSDId is not enough!`, ); - expect(ergo.getAddressUnspentBoxes).toHaveBeenCalledWith('address'); }); - it(`Should throw new Error if 'from.amount === 0' and sell is 'false'`, async () => { - jest.spyOn(ergo, 'getPoolByToken').mockReturnValue(poolWithOutputAmount0); + it(`Should throw new Error if 'from.amount === 0' and sell is 'true'`, async () => { + // to set sell 'true' + const baseToken: string = 'SigUSD'; + const quoteToken: string = 'ERG'; + jest + .spyOn(ergo, 'getPoolByToken') + .mockReturnValue([poolWithOutputAmount0]); patchGetErgoConfig('mainnet'); - // to set sell false - const baseToken = 'xId'; await expect( ergo.swap( account, @@ -1191,21 +1251,20 @@ describe('Ergo', () => { ), ).rejects.toThrow( `${value.multipliedBy( - BigNumber(10).pow(pool.y.asset.decimals as number), - )} asset from yId is not enough!`, + BigNumber(10).pow(pool.x.asset.decimals as number), + )} asset from ERGId is not enough!`, ); - expect(ergo.getAddressUnspentBoxes).toHaveBeenCalledWith('address'); }); it('Should throw new Error if swapVariables are undefined', async () => { - jest.spyOn(ergo, 'getPoolByToken').mockReturnValue(pool); + jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([pool]); jest .spyOn(BigNumber.prototype, 'multipliedBy') .mockReturnValue(BigNumber(2)); patchGetErgoConfig('mainnet'); - jest - .spyOn(ergo_utils, 'getBaseInputParameters') - .mockReturnValue({} as any); + jest.spyOn(ergo_utils, 'getBaseInputParameters').mockReturnValue({ + minOutput: { amount: BigInt(1) }, + } as any); await expect( ergo.swap( account, @@ -1220,15 +1279,19 @@ describe('Ergo', () => { expect(ergo_utils.getBaseInputParameters).toHaveBeenCalledWith(pool, { inputAmount: { asset: { - id: 'yId', - decimals: 3, + id: 'ERGId', + decimals: 9, }, amount: pool.outputAmount( { asset: { - id: 'xId', + id: 'SigUSDId', }, - amount: value, + amount: value + .multipliedBy( + BigNumber(10).pow(pool.y.asset.decimals as number), + ) + .toString(), }, slippage, ).amount, @@ -1236,8 +1299,44 @@ describe('Ergo', () => { slippage: slippage || 10, }); }); + + it('Should ignore the rest of loop scope and return the base result if minOutput === BigInt(0)', async () => { + jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([pool]); + jest + .spyOn(BigNumber.prototype, 'multipliedBy') + .mockReturnValue(BigNumber(2)); + patchGetErgoConfig('mainnet'); + jest.spyOn(ergo_utils, 'getBaseInputParameters').mockReturnValue({ + minOutput: { amount: BigInt(0) }, + } as any); + expect( + await ergo.swap( + account, + baseToken, + quoteToken, + value, + output_address, + return_address, + ), + ).toEqual({ + network: 'mainnet', + timestamp: 0, + latency: 0, + base: baseToken, + quote: quoteToken, + amount: '0', + rawAmount: '0', + expectedOut: '0', + price: '0', + gasPrice: 0, + gasPriceToken: '0', + gasLimit: 0, + gasCost: '0', + txHash: '', + }); + }); it('Should throw new Error if output_address is not defined', async () => { - jest.spyOn(ergo, 'getPoolByToken').mockReturnValue(pool); + jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([pool]); jest .spyOn(BigNumber.prototype, 'multipliedBy') .mockReturnValue(BigNumber(2)); @@ -1245,7 +1344,7 @@ describe('Ergo', () => { jest.spyOn(ergo_utils, 'getBaseInputParameters').mockReturnValue({ baseInput: BigNumber(1), baseInputAmount: BigNumber(1), - minOutput: {}, + minOutput: { amount: BigInt(1) }, } as any); jest.spyOn(ergo_utils, 'getInputs').mockReturnValue({} as any); await expect( @@ -1261,7 +1360,40 @@ describe('Ergo', () => { expect(ergo.getAddressUnspentBoxes).toHaveBeenCalledWith('address'); }); - it('Should successfully swap tokens when sell is true', async () => { + it('Should throw new Error if any error occurs during submitting the tx', async () => { + jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([pool]); + jest + .spyOn(BigNumber.prototype, 'multipliedBy') + .mockReturnValue(BigNumber(2)); + patchGetErgoConfig('mainnet'); + jest.spyOn(ergo_utils, 'getBaseInputParameters').mockReturnValue({ + baseInput: BigNumber(1), + baseInputAmount: BigNumber(1), + minOutput: { amount: BigInt(1) }, + } as any); + jest.spyOn(ergo_utils, 'getInputs').mockReturnValue({} as any); + jest + .spyOn(NodeService.prototype, 'getBlockInfo') + .mockResolvedValue({ header: { timestamp: 123456 } }); + const account: any = { + prover: { + submit: jest.fn().mockResolvedValue({}), + }, + }; + + await expect( + ergo.swap( + account, + baseToken, + quoteToken, + value, + output_address, + return_address, + ), + ).rejects.toThrow(`error during submit tx!`); + }); + + it('Should successfully swap tokens when sell is false', async () => { const mockUtxos = [ { value: '1000', @@ -1272,20 +1404,25 @@ describe('Ergo', () => { assets: [{ amount: '1500' }, { amount: '1300' }], }, ]; - jest.spyOn(ergo, 'getPoolByToken').mockReturnValue(pool); + jest + .spyOn(NodeService.prototype, 'getBlockInfo') + .mockResolvedValue({ header: { timestamp: 123456 } }); + jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([pool]); jest .spyOn(ergo, 'getAddressUnspentBoxes') .mockResolvedValue(mockUtxos as any); - // const date = new Date(); - jest - .spyOn(ergo['_node'], 'getBlockInfo') - .mockResolvedValue({ header: { timestamp: new Date() } }); jest.spyOn(ergo_utils, 'getBaseInputParameters').mockReturnValue({ baseInput: BigNumber(1), baseInputAmount: BigNumber(1), minOutput: { amount: BigInt(1) }, } as any); + const account: any = { + prover: { + submit: jest.fn().mockResolvedValue({ id: 'id' }), + }, + }; + const result = await ergo.swap( account, baseToken, @@ -1295,21 +1432,32 @@ describe('Ergo', () => { return_address, slippage, ); - expect(result).toMatchObject({ + expect(result).toEqual({ network: ergo.network, - // timestamp ignored because there was a really small difference between create Date.new() in test file and main file - // timestamp: expect.any(Number), + timestamp: 123456, latency: 0, base: baseToken, quote: quoteToken, amount: value - .multipliedBy(BigNumber(10).pow(pool.x.asset.decimals as number)) + .multipliedBy(BigNumber(10).pow(pool.y.asset.decimals as number)) + .div(BigNumber(10).pow(pool.y.asset.decimals as number)) .toString(), rawAmount: value - .multipliedBy(BigNumber(10).pow(pool.x.asset.decimals as number)) + .multipliedBy(BigNumber(10).pow(pool.y.asset.decimals as number)) + .div(BigNumber(10).pow(pool.y.asset.decimals as number)) + .toString(), + expectedOut: BigNumber(BigInt(1).toString()) + .div(BigNumber(10).pow(pool.y.asset.decimals as number)) + .toString(), + price: BigNumber(BigInt(1).toString()) + .div(BigNumber(10).pow(pool.y.asset.decimals as number)) + .div( + BigNumber(pool.outputAmount().amount.toString()).div( + BigNumber(10).pow(pool.x.asset.decimals as number), + ), + ) + .toString() .toString(), - expectedOut: BigInt(1).toString(), - price: '1', gasPrice: 0, gasPriceToken: '0', gasLimit: 0, @@ -1318,7 +1466,7 @@ describe('Ergo', () => { }); }); - it('Should successfully swap tokens when sell is false', async () => { + it('Should successfully swap tokens when sell is true', async () => { const mockUtxos = [ { value: '1000', @@ -1329,20 +1477,27 @@ describe('Ergo', () => { assets: [{ amount: '1500' }, { amount: '1300' }], }, ]; - jest.spyOn(ergo, 'getPoolByToken').mockReturnValue(pool); + jest + .spyOn(NodeService.prototype, 'getBlockInfo') + .mockResolvedValue({ header: { timestamp: 123456 } }); + jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([pool]); jest .spyOn(ergo, 'getAddressUnspentBoxes') .mockResolvedValue(mockUtxos as any); - jest - .spyOn(ergo['_node'], 'getBlockInfo') - .mockResolvedValue({ header: { timestamp: new Date() } }); jest.spyOn(ergo_utils, 'getBaseInputParameters').mockReturnValue({ baseInput: BigNumber(1), baseInputAmount: BigNumber(1), minOutput: { amount: BigInt(1) }, } as any); - // to set sell false - const baseToken = 'xId'; + + const account: any = { + prover: { + submit: jest.fn().mockResolvedValue({ id: 'id' }), + }, + }; + // to set sell 'true' + const baseToken: string = 'SigUSD'; + const quoteToken: string = 'ERG'; const result = await ergo.swap( account, baseToken, @@ -1352,21 +1507,32 @@ describe('Ergo', () => { return_address, slippage, ); - expect(result).toMatchObject({ + expect(result).toEqual({ network: ergo.network, - // timestamp ignored because there was a really small difference between create Date.new() in test file and main file - // timestamp: Date.now(), + timestamp: 123456, latency: 0, base: baseToken, quote: quoteToken, amount: value - .multipliedBy(BigNumber(10).pow(pool.y.asset.decimals as number)) + .multipliedBy(BigNumber(10).pow(pool.x.asset.decimals as number)) + .div(BigNumber(10).pow(pool.x.asset.decimals as number)) .toString(), rawAmount: value - .multipliedBy(BigNumber(10).pow(pool.y.asset.decimals as number)) + .multipliedBy(BigNumber(10).pow(pool.x.asset.decimals as number)) + .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + .toString(), + expectedOut: BigNumber(BigInt(1).toString()) + .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + .toString(), + price: BigNumber(BigInt(1).toString()) + .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + .div( + BigNumber(pool.outputAmount().amount.toString()).div( + BigNumber(10).pow(pool.y.asset.decimals as number), + ), + ) + .toString() .toString(), - expectedOut: BigInt(1).toString(), - price: '2', gasPrice: 0, gasPriceToken: '0', gasLimit: 0, From e9f7f232a5e5f4e753433109644e6430e4c35881 Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Mon, 22 Jul 2024 18:47:38 +0330 Subject: [PATCH 112/132] bug fixed --- src/chains/ergo/ergo.ts | 328 ++++++++++++++++++++++------------------ 1 file changed, 178 insertions(+), 150 deletions(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 9c07466cdf..339e86c9c1 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -501,20 +501,8 @@ export class Ergo { if (!realBaseToken || !realQuoteToken) throw new Error(`${baseToken} or ${quoteToken} not found!`); let result = { - network: this.network, - timestamp: 0, - latency: 0, - base: baseToken, - quote: quoteToken, - amount: '0', - rawAmount: '0', - expectedOut: '0', - price: '0', - gasPrice: 0, - gasPriceToken: '0', - gasLimit: 0, - gasCost: '0', - txHash: '', + pool: {}, + expectedOut: BigNumber(0), }; for (const pool of pools) { if (!pool) @@ -531,13 +519,6 @@ export class Ergo { ); } const config = getErgoConfig(this.network); - const to = { - asset: { - id: sell ? pool.x.asset.id : pool.y.asset.id, - decimals: sell ? pool.x.asset.decimals : pool.y.asset.decimals, - }, - amount: BigInt(amount.toString()), - }; const max_to = { asset: { id: sell ? pool.x.asset.id : pool.y.asset.id, @@ -558,13 +539,10 @@ export class Ergo { throw new Error( `${amount} asset from ${max_to.asset.id} is not enough!`, ); - const { baseInput, baseInputAmount, minOutput } = getBaseInputParameters( - pool, - { - inputAmount: from, - slippage: slippage || config.network.defaultSlippage, - }, - ); + const { minOutput } = getBaseInputParameters(pool, { + inputAmount: from, + slippage: slippage || config.network.defaultSlippage, + }); if (minOutput.amount === BigInt(0)) continue; const expectedOut = sell === false @@ -575,125 +553,175 @@ export class Ergo { BigNumber(10).pow(pool.x.asset.decimals as number), ); if (expectedOut >= BigNumber(result.expectedOut)) { - const networkContext = await this._explorer.getNetworkContext(); - const mainnetTxAssembler = new DefaultTxAssembler( - this.network === 'mainnet', - ); - const poolActions = makeWrappedNativePoolActionsSelector( - output_address, - account.prover, - mainnetTxAssembler, - ); - const utxos = await this.getAddressUnspentBoxes(account.address); - const swapVariables: [number, SwapExtremums] | undefined = swapVars( - BigInt(config.network.defaultMinerFee.multipliedBy(3).toString()), - config.network.minNitro, - minOutput, - ); - if (!swapVariables) throw new Error('error in swap vars!'); - const [exFeePerToken, extremum] = swapVariables; - - const inputs = getInputs( - utxos.map((utxo) => { - const temp = Object(utxo); - temp.value = BigNumber(temp.value); - temp.assets = temp.assets.map((asset: any) => { - const temp2 = Object(asset); - temp2.amount = BigNumber(temp2.amount); - return temp2; - }); - return temp; - }), - [new AssetAmount(from.asset, BigInt(baseInputAmount.toString()))], - { - minerFee: BigInt(config.network.defaultMinerFee.toString()), - uiFee: BigInt(config.network.defaultMinerFee.toString()), - exFee: BigInt(extremum.maxExFee.toString()), - }, - ); - const pk = publicKeyFromAddress(output_address); - if (!pk) throw new Error(`output_address is not defined.`); - const swapParams: SwapParams = { - poolId: pool.id, - pk, - baseInput, - minQuoteOutput: extremum.minOutput.amount, - exFeePerToken, - uiFee: BigInt(config.network.defaultMinerFee.toString()), - quoteAsset: to.asset.id, - poolFeeNum: pool.poolFeeNum, - maxExFee: extremum.maxExFee, - }; - const txContext: TransactionContext = getTxContext( - inputs, - networkContext as NetworkContext, - return_address, - BigInt(config.network.defaultMinerFee.toString()), - ); - const actions = poolActions(pool); - const timestamp = ( - await this._node.getBlockInfo(networkContext.height.toString()) - ).header.timestamp; - const tx = await actions.swap(swapParams, txContext); - const submit_tx = await account.prover.submit(tx); - if (!submit_tx.id) throw new Error(`error during submit tx!`); result = { - network: this.network, - timestamp, - latency: 0, - base: baseToken, - quote: quoteToken, - amount: - sell === false - ? amount - .div(BigNumber(10).pow(pool.y.asset.decimals as number)) - .toString() - : amount - .div(BigNumber(10).pow(pool.x.asset.decimals as number)) - .toString(), - rawAmount: - sell === false - ? amount - .div(BigNumber(10).pow(pool.y.asset.decimals as number)) - .toString() - : amount - .div(BigNumber(10).pow(pool.x.asset.decimals as number)) - .toString(), - expectedOut: - sell === false - ? BigNumber(minOutput.amount.toString()) - .div(BigNumber(10).pow(pool.y.asset.decimals as number)) - .toString() - : BigNumber(minOutput.amount.toString()) - .div(BigNumber(10).pow(pool.x.asset.decimals as number)) - .toString(), - price: - sell === false - ? BigNumber(minOutput.amount.toString()) - .div(BigNumber(10).pow(pool.y.asset.decimals as number)) - .div( - BigNumber(from.amount.toString()).div( - BigNumber(10).pow(pool.x.asset.decimals as number), - ), - ) - .toString() - : BigNumber(minOutput.amount.toString()) - .div(BigNumber(10).pow(pool.x.asset.decimals as number)) - .div( - BigNumber(from.amount.toString()).div( - BigNumber(10).pow(pool.y.asset.decimals as number), - ), - ) - .toString(), - gasPrice: 0, - gasPriceToken: '0', - gasLimit: 0, - gasCost: '0', - txHash: tx.id, + pool, + expectedOut, }; } } - return result; + const pool = pools.find((pool) => pool.id === result.pool.id); + if (!pool) + throw new Error(`pool not found base on ${baseToken}, ${quoteToken}`); + if (pool.x.asset.id === realBaseToken.tokenId) { + sell = false; + amount = value.multipliedBy( + BigNumber(10).pow(pool.y.asset.decimals as number), + ); + } else { + sell = true; + amount = value.multipliedBy( + BigNumber(10).pow(pool.x.asset.decimals as number), + ); + } + const config = getErgoConfig(this.network); + const to = { + asset: { + id: sell ? pool.x.asset.id : pool.y.asset.id, + decimals: sell ? pool.x.asset.decimals : pool.y.asset.decimals, + }, + amount: BigInt(amount.toString()), + }; + const max_to = { + asset: { + id: sell ? pool.x.asset.id : pool.y.asset.id, + }, + amount: BigInt(amount.toString()), + }; + const from = { + asset: { + id: sell ? pool.y.asset.id : pool.x.asset.id, + decimals: sell ? pool.y.asset.decimals : pool.x.asset.decimals, + }, + amount: pool.outputAmount( + max_to as any, + slippage || config.network.defaultSlippage, + ).amount, + }; + if (from.amount === BigInt(0)) + throw new Error(`${amount} asset from ${max_to.asset.id} is not enough!`); + const { baseInput, baseInputAmount, minOutput } = getBaseInputParameters( + pool, + { + inputAmount: from, + slippage: slippage || config.network.defaultSlippage, + }, + ); + const networkContext = await this._explorer.getNetworkContext(); + const mainnetTxAssembler = new DefaultTxAssembler( + this.network === 'mainnet', + ); + const poolActions = makeWrappedNativePoolActionsSelector( + output_address, + account.prover, + mainnetTxAssembler, + ); + const utxos = await this.getAddressUnspentBoxes(account.address); + const swapVariables: [number, SwapExtremums] | undefined = swapVars( + BigInt(config.network.defaultMinerFee.multipliedBy(3).toString()), + config.network.minNitro, + minOutput, + ); + if (!swapVariables) throw new Error('error in swap vars!'); + const [exFeePerToken, extremum] = swapVariables; + + const inputs = getInputs( + utxos.map((utxo) => { + const temp = Object(utxo); + temp.value = BigNumber(temp.value); + temp.assets = temp.assets.map((asset: any) => { + const temp2 = Object(asset); + temp2.amount = BigNumber(temp2.amount); + return temp2; + }); + return temp; + }), + [new AssetAmount(from.asset, BigInt(baseInputAmount.toString()))], + { + minerFee: BigInt(config.network.defaultMinerFee.toString()), + uiFee: BigInt(config.network.defaultMinerFee.toString()), + exFee: BigInt(extremum.maxExFee.toString()), + }, + ); + const pk = publicKeyFromAddress(output_address); + if (!pk) throw new Error(`output_address is not defined.`); + const swapParams: SwapParams = { + poolId: pool.id, + pk, + baseInput, + minQuoteOutput: extremum.minOutput.amount, + exFeePerToken, + uiFee: BigInt(config.network.defaultMinerFee.toString()), + quoteAsset: to.asset.id, + poolFeeNum: pool.poolFeeNum, + maxExFee: extremum.maxExFee, + }; + const txContext: TransactionContext = getTxContext( + inputs, + networkContext as NetworkContext, + return_address, + BigInt(config.network.defaultMinerFee.toString()), + ); + const actions = poolActions(pool); + const timestamp = ( + await this._node.getBlockInfo(networkContext.height.toString()) + ).header.timestamp; + const tx = await actions.swap(swapParams, txContext); + const submit_tx = await account.prover.submit(tx); + if (!submit_tx.id) throw new Error(`error during submit tx!`); + return { + network: this.network, + timestamp, + latency: 0, + base: baseToken, + quote: quoteToken, + amount: + sell === false + ? amount + .div(BigNumber(10).pow(pool.y.asset.decimals as number)) + .toString() + : amount + .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + .toString(), + rawAmount: + sell === false + ? amount + .div(BigNumber(10).pow(pool.y.asset.decimals as number)) + .toString() + : amount + .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + .toString(), + expectedOut: + sell === false + ? BigNumber(minOutput.amount.toString()) + .div(BigNumber(10).pow(pool.y.asset.decimals as number)) + .toString() + : BigNumber(minOutput.amount.toString()) + .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + .toString(), + price: + sell === false + ? BigNumber(minOutput.amount.toString()) + .div(BigNumber(10).pow(pool.y.asset.decimals as number)) + .div( + BigNumber(from.amount.toString()).div( + BigNumber(10).pow(pool.x.asset.decimals as number), + ), + ) + .toString() + : BigNumber(minOutput.amount.toString()) + .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + .div( + BigNumber(from.amount.toString()).div( + BigNumber(10).pow(pool.y.asset.decimals as number), + ), + ) + .toString(), + gasPrice: config.network.minTxFee, + gasPriceToken: '0', + gasLimit: config.network.minTxFee, + gasCost: config.network.minTxFee.toString(), + txHash: tx.id, + }; } public async estimate( @@ -704,7 +732,7 @@ export class Ergo { ): Promise { let sell: boolean; let amount: BigNumber; - + const config = getErgoConfig(this.network); const pools = this.getPoolByToken(baseToken, quoteToken); if (!pools.length) throw new Error(`pool not found base on ${baseToken}, ${quoteToken}`); @@ -726,10 +754,10 @@ export class Ergo { network: this.network, timestamp: Date.now(), latency: 0, - gasPrice: 0, + gasPrice: config.network.minTxFee, gasPriceToken: '0', - gasLimit: 0, - gasCost: '0', + gasLimit: config.network.minTxFee, + gasCost: config.network.minTxFee.toString(), }; for (const pool of pools) { if (pool.x.asset.id === realBaseToken.tokenId) { @@ -823,10 +851,10 @@ export class Ergo { network: this.network, timestamp: Date.now(), latency: 0, - gasPrice: 0, + gasPrice: config.network.minTxFee, gasPriceToken: '0', - gasLimit: 0, - gasCost: '0', + gasLimit: config.network.minTxFee, + gasCost: config.network.minTxFee.toString(), }; } return result; From f66b1a27128e3799bd2b71607624b33e596e8ecf Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Mon, 22 Jul 2024 20:01:59 +0330 Subject: [PATCH 113/132] expected amount is now greater that prev --- src/chains/ergo/ergo.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 339e86c9c1..f95e7a3b59 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -552,7 +552,7 @@ export class Ergo { : BigNumber(minOutput.amount.toString()).div( BigNumber(10).pow(pool.x.asset.decimals as number), ); - if (expectedOut >= BigNumber(result.expectedOut)) { + if (expectedOut > BigNumber(result.expectedOut)) { result = { pool, expectedOut, @@ -802,7 +802,7 @@ export class Ergo { : BigNumber(minOutput.amount.toString()).div( BigNumber(10).pow(pool.x.asset.decimals as number), ); - if (expectedAmount >= BigNumber(result.expectedAmount)) + if (expectedAmount > BigNumber(result.expectedAmount)) result = { base: realBaseToken.symbol, quote: realQuoteToken.symbol, From 41c2da8eec40ef3c24e65f469656d118a40fae61 Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Tue, 23 Jul 2024 18:16:10 +0330 Subject: [PATCH 114/132] bug fixed --- src/chains/ergo/ergo.ts | 61 ++++++++++++++++------------- src/connectors/spectrum/spectrum.ts | 8 ++-- 2 files changed, 38 insertions(+), 31 deletions(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index f95e7a3b59..1b772d0e94 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -672,8 +672,8 @@ export class Ergo { network: this.network, timestamp, latency: 0, - base: baseToken, - quote: quoteToken, + base: realBaseToken.symbol, + quote: realQuoteToken.symbol, amount: sell === false ? amount @@ -708,18 +708,21 @@ export class Ergo { ), ) .toString() - : BigNumber(minOutput.amount.toString()) - .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + : BigNumber(1) .div( - BigNumber(from.amount.toString()).div( - BigNumber(10).pow(pool.y.asset.decimals as number), - ), + BigNumber(minOutput.amount.toString()) + .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + .div( + BigNumber(from.amount.toString()).div( + BigNumber(10).pow(pool.y.asset.decimals as number), + ), + ), ) .toString(), - gasPrice: config.network.minTxFee, - gasPriceToken: '0', - gasLimit: config.network.minTxFee, - gasCost: config.network.minTxFee.toString(), + gasPrice: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toNumber(), + gasPriceToken: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toString(), + gasLimit: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toNumber(), + gasCost: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toString(), txHash: tx.id, }; } @@ -754,10 +757,10 @@ export class Ergo { network: this.network, timestamp: Date.now(), latency: 0, - gasPrice: config.network.minTxFee, - gasPriceToken: '0', - gasLimit: config.network.minTxFee, - gasCost: config.network.minTxFee.toString(), + gasPrice: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toNumber(), + gasPriceToken: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toString(), + gasLimit: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toNumber(), + gasCost: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toString(), }; for (const pool of pools) { if (pool.x.asset.id === realBaseToken.tokenId) { @@ -802,7 +805,7 @@ export class Ergo { : BigNumber(minOutput.amount.toString()).div( BigNumber(10).pow(pool.x.asset.decimals as number), ); - if (expectedAmount > BigNumber(result.expectedAmount)) + if (expectedAmount > BigNumber(result.expectedAmount)) { result = { base: realBaseToken.symbol, quote: realQuoteToken.symbol, @@ -832,30 +835,34 @@ export class Ergo { .toString(), price: sell === false - ? BigNumber(minOutput.amount.toString()) - .div(BigNumber(10).pow(pool.y.asset.decimals as number)) + ? (BigNumber(minOutput.amount.toString()) + .div(BigNumber(10).pow(pool.y.asset.decimals as number))) .div( BigNumber(from.amount.toString()).div( BigNumber(10).pow(pool.x.asset.decimals as number), ), ) .toString() - : BigNumber(minOutput.amount.toString()) - .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + : BigNumber(1) .div( - BigNumber(from.amount.toString()).div( - BigNumber(10).pow(pool.y.asset.decimals as number), - ), + (BigNumber(minOutput.amount.toString()) + .div(BigNumber(10).pow(pool.x.asset.decimals as number))) + .div( + BigNumber(from.amount.toString()).div( + BigNumber(10).pow(pool.y.asset.decimals as number), + ), + ), ) .toString(), network: this.network, timestamp: Date.now(), latency: 0, - gasPrice: config.network.minTxFee, - gasPriceToken: '0', - gasLimit: config.network.minTxFee, - gasCost: config.network.minTxFee.toString(), + gasPrice: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toNumber(), + gasPriceToken: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toString(), + gasLimit: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toNumber(), + gasCost: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toString(), }; + } } return result; } diff --git a/src/connectors/spectrum/spectrum.ts b/src/connectors/spectrum/spectrum.ts index 3d91d43005..939ce393b1 100644 --- a/src/connectors/spectrum/spectrum.ts +++ b/src/connectors/spectrum/spectrum.ts @@ -71,14 +71,14 @@ export class Spectrum { * @param amount Amount of `baseToken` desired from the transaction */ async estimateTrade(req: PriceRequest) { - if (req.side === 'BUY') + if (req.side === 'SELL') return this.ergo.estimate( req.base.replace("_", ""), req.quote.replace("_", ""), BigNumber(req.amount), Number(req.allowedSlippage), ); - else if (req.side === 'SELL') + else if (req.side === 'BUY') return this.ergo.estimate( req.quote.replace("_", ""), req.base.replace("_", ""), @@ -104,7 +104,7 @@ export class Spectrum { const account = await this.ergo.getAccountFromAddress( req.address as unknown as string, ); - if (req.side === 'BUY') + if (req.side === 'SELL') return this.ergo.swap( account, req.base.replace("_", ""), @@ -114,7 +114,7 @@ export class Spectrum { req.address, Number(req.allowedSlippage), ); - else if (req.side === 'SELL') + else if (req.side === 'BUY') return this.ergo.swap( account, req.quote.replace("_", ""), From 69641256b3f6306683584e0504d2c37a285f8aeb Mon Sep 17 00:00:00 2001 From: satiparpar Date: Wed, 24 Jul 2024 11:39:19 +0330 Subject: [PATCH 115/132] update [unit-test]: update unit tests based on new updates for Ergo => "swap" mehtod --- test-bronze/chains/ergo/ergo.test.ts | 101 ++++++++++++++------------- 1 file changed, 51 insertions(+), 50 deletions(-) diff --git a/test-bronze/chains/ergo/ergo.test.ts b/test-bronze/chains/ergo/ergo.test.ts index 7073db463e..dd01d1fb8b 100644 --- a/test-bronze/chains/ergo/ergo.test.ts +++ b/test-bronze/chains/ergo/ergo.test.ts @@ -1300,41 +1300,41 @@ describe('Ergo', () => { }); }); - it('Should ignore the rest of loop scope and return the base result if minOutput === BigInt(0)', async () => { - jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([pool]); - jest - .spyOn(BigNumber.prototype, 'multipliedBy') - .mockReturnValue(BigNumber(2)); - patchGetErgoConfig('mainnet'); - jest.spyOn(ergo_utils, 'getBaseInputParameters').mockReturnValue({ - minOutput: { amount: BigInt(0) }, - } as any); - expect( - await ergo.swap( - account, - baseToken, - quoteToken, - value, - output_address, - return_address, - ), - ).toEqual({ - network: 'mainnet', - timestamp: 0, - latency: 0, - base: baseToken, - quote: quoteToken, - amount: '0', - rawAmount: '0', - expectedOut: '0', - price: '0', - gasPrice: 0, - gasPriceToken: '0', - gasLimit: 0, - gasCost: '0', - txHash: '', - }); - }); + // it('Should ignore the rest of loop scope and return the base result if minOutput === BigInt(0)', async () => { + // jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([pool]); + // jest + // .spyOn(BigNumber.prototype, 'multipliedBy') + // .mockReturnValue(BigNumber(2)); + // patchGetErgoConfig('mainnet'); + // jest.spyOn(ergo_utils, 'getBaseInputParameters').mockReturnValue({ + // minOutput: { amount: BigInt(0) }, + // } as any); + // expect( + // await ergo.swap( + // account, + // baseToken, + // quoteToken, + // value, + // output_address, + // return_address, + // ), + // ).toEqual({ + // network: 'mainnet', + // timestamp: 0, + // latency: 0, + // base: baseToken, + // quote: quoteToken, + // amount: '0', + // rawAmount: '0', + // expectedOut: '0', + // price: '0', + // gasPrice: 0, + // gasPriceToken: '0', + // gasLimit: 0, + // gasCost: '0', + // txHash: '', + // }); + // }); it('Should throw new Error if output_address is not defined', async () => { jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([pool]); jest @@ -1456,12 +1456,11 @@ describe('Ergo', () => { BigNumber(10).pow(pool.x.asset.decimals as number), ), ) - .toString() .toString(), - gasPrice: 0, - gasPriceToken: '0', - gasLimit: 0, - gasCost: '0', + gasPrice: BigNumber('2000').div(BigNumber(10).pow(9)).toNumber(), + gasPriceToken: BigNumber('2000').div(BigNumber(10).pow(9)).toString(), + gasLimit: BigNumber('2000').div(BigNumber(10).pow(9)).toNumber(), + gasCost: BigNumber('2000').div(BigNumber(10).pow(9)).toString(), txHash: 'txId', }); }); @@ -1524,19 +1523,21 @@ describe('Ergo', () => { expectedOut: BigNumber(BigInt(1).toString()) .div(BigNumber(10).pow(pool.x.asset.decimals as number)) .toString(), - price: BigNumber(BigInt(1).toString()) - .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + price: BigNumber(1) .div( - BigNumber(pool.outputAmount().amount.toString()).div( - BigNumber(10).pow(pool.y.asset.decimals as number), - ), + BigNumber(BigInt(1).toString()) + .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + .div( + BigNumber(pool.outputAmount().amount.toString()).div( + BigNumber(10).pow(pool.y.asset.decimals as number), + ), + ), ) - .toString() .toString(), - gasPrice: 0, - gasPriceToken: '0', - gasLimit: 0, - gasCost: '0', + gasPrice: BigNumber('2000').div(BigNumber(10).pow(9)).toNumber(), + gasPriceToken: BigNumber('2000').div(BigNumber(10).pow(9)).toString(), + gasLimit: BigNumber('2000').div(BigNumber(10).pow(9)).toNumber(), + gasCost: BigNumber('2000').div(BigNumber(10).pow(9)).toString(), txHash: 'txId', }); }); From c7ecc01e967917d86ccc5887757844ce87b0486a Mon Sep 17 00:00:00 2001 From: satiparpar Date: Wed, 24 Jul 2024 12:32:20 +0330 Subject: [PATCH 116/132] update [unit-test]: update unit tests based on new updates for Ergo => "estimate" mehtod --- test-bronze/chains/ergo/ergo.test.ts | 206 ++++++++++++++++++--------- 1 file changed, 136 insertions(+), 70 deletions(-) diff --git a/test-bronze/chains/ergo/ergo.test.ts b/test-bronze/chains/ergo/ergo.test.ts index dd01d1fb8b..feb472e790 100644 --- a/test-bronze/chains/ergo/ergo.test.ts +++ b/test-bronze/chains/ergo/ergo.test.ts @@ -1300,41 +1300,6 @@ describe('Ergo', () => { }); }); - // it('Should ignore the rest of loop scope and return the base result if minOutput === BigInt(0)', async () => { - // jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([pool]); - // jest - // .spyOn(BigNumber.prototype, 'multipliedBy') - // .mockReturnValue(BigNumber(2)); - // patchGetErgoConfig('mainnet'); - // jest.spyOn(ergo_utils, 'getBaseInputParameters').mockReturnValue({ - // minOutput: { amount: BigInt(0) }, - // } as any); - // expect( - // await ergo.swap( - // account, - // baseToken, - // quoteToken, - // value, - // output_address, - // return_address, - // ), - // ).toEqual({ - // network: 'mainnet', - // timestamp: 0, - // latency: 0, - // base: baseToken, - // quote: quoteToken, - // amount: '0', - // rawAmount: '0', - // expectedOut: '0', - // price: '0', - // gasPrice: 0, - // gasPriceToken: '0', - // gasLimit: 0, - // gasCost: '0', - // txHash: '', - // }); - // }); it('Should throw new Error if output_address is not defined', async () => { jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([pool]); jest @@ -1544,9 +1509,26 @@ describe('Ergo', () => { }); describe('estimate', () => { - const baseToken: string = 'baseToken'; - const quoteToken: string = 'quoteToken'; + const baseToken: string = 'ERG'; + const quoteToken: string = 'SigUSD'; const value: BigNumber = BigNumber(10); + beforeEach(() => { + jest.spyOn(ergo, 'storedAssetList', 'get').mockReturnValue([ + { + tokenId: 'SigUSDId', + decimals: 3, + name: 'SigUSD', + symbol: 'SigUSD', + }, + + { + tokenId: 'ERGId', + decimals: 9, + name: 'ergo', + symbol: 'ERG', + }, + ]); + }); afterEach(() => { jest.clearAllMocks(); }); @@ -1568,16 +1550,16 @@ describe('Ergo', () => { withAmount: (_sth: any) => { return { asset: { - id: 'xId', - name: 'xName', + id: 'ERGId', + name: 'ergo', decimals: 9, }, amount: BigInt(752313805260857), }; }, asset: { - id: 'xId', - name: 'xName', + id: 'ERGId', + name: 'ergo', decimals: 9, }, }, @@ -1585,16 +1567,16 @@ describe('Ergo', () => { withAmount: (_sth: any) => { return { asset: { - id: 'yId', - name: 'yName', + id: 'SigUSDId', + name: 'SigUSD', decimals: 3, }, amount: BigInt(9322283969), }; }, asset: { - id: 'yId', - name: 'yName', + id: 'SigUSDId', + name: 'SigUSD', decimals: 3, }, }, @@ -1611,70 +1593,154 @@ describe('Ergo', () => { expect(ergo.estimate).toBeDefined(); }); it('Should throw new Error if pool is not found', async () => { - jest.spyOn(ergo, 'getPoolByToken').mockReturnValue(null as any); + jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([]); await expect(ergo.estimate(baseToken, quoteToken, value)).rejects.toThrow( `pool not found base on ${baseToken}, ${quoteToken}`, ); }); - it('Should estimate successfully when sell is true', async () => { + it('Should throw new Error if baseToken is available but quoteToken is not available on storedAssetList', async () => { + jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([pool]); + // ERG is available but SigUSD is not + jest.spyOn(ergo, 'storedAssetList', 'get').mockReturnValue([ + { + tokenId: 'ERGId', + decimals: 9, + name: 'ergo', + symbol: 'ERG', + }, + ]); + await expect(ergo.estimate(baseToken, quoteToken, value)).rejects.toThrow( + `${baseToken} or ${quoteToken} not found!`, + ); + expect(ergo.getPoolByToken).toHaveBeenCalledWith(baseToken, quoteToken); + }); + + it('Should throw new Error if quoteToken is available but baseToken is not available on storedAssetList', async () => { + jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([pool]); + // SigUSD is available but ERG is not + jest.spyOn(ergo, 'storedAssetList', 'get').mockReturnValue([ + { + tokenId: 'SigUSDId', + decimals: 3, + name: 'SigUSD', + symbol: 'SigUSD', + }, + ]); + await expect(ergo.estimate(baseToken, quoteToken, value)).rejects.toThrow( + `${baseToken} or ${quoteToken} not found!`, + ); + expect(ergo.getPoolByToken).toHaveBeenCalledWith(baseToken, quoteToken); + }); + + it('Should ignore the rest of loop scope and return the base result if minOutput === BigInt(0)', async () => { + jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([pool]); + jest + .spyOn(BigNumber.prototype, 'multipliedBy') + .mockReturnValue(BigNumber(2)); patchGetErgoConfig('mainnet'); - jest.spyOn(ergo, 'getPoolByToken').mockReturnValue(null as any); + jest.spyOn(ergo_utils, 'getBaseInputParameters').mockReturnValue({ + minOutput: { amount: BigInt(0) }, + } as any); + expect(await ergo.estimate(baseToken, quoteToken, value)).toMatchObject({ + base: baseToken, + quote: quoteToken, + amount: '0', + rawAmount: '0', + expectedAmount: '0', + price: '0', + network: 'mainnet', + // timestamp ignored because there was a really small difference between create Date.new() in test file and main file + // timestamp: Date.now(), + latency: 0, + gasPrice: BigNumber('2000').div(BigNumber(10).pow(9)).toNumber(), + gasPriceToken: BigNumber('2000').div(BigNumber(10).pow(9)).toString(), + gasLimit: BigNumber('2000').div(BigNumber(10).pow(9)).toNumber(), + gasCost: BigNumber('2000').div(BigNumber(10).pow(9)).toString(), + }); + }); + it('Should estimate successfully when sell is false', async () => { + patchGetErgoConfig('mainnet'); + jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([pool]); jest .spyOn(ergo_utils, 'getBaseInputParameters') .mockReturnValue({ minOutput: { amount: BigInt(1) } } as any); - jest.spyOn(ergo, 'getPoolByToken').mockReturnValue(pool); const result = await ergo.estimate(baseToken, quoteToken, value); expect(result).toMatchObject({ base: baseToken, quote: quoteToken, amount: value - .multipliedBy(BigNumber(10).pow(pool.x.asset.decimals as number)) + .multipliedBy(BigNumber(10).pow(pool.y.asset.decimals as number)) + .div(BigNumber(10).pow(pool.y.asset.decimals as number)) .toString(), rawAmount: value - .multipliedBy(BigNumber(10).pow(pool.x.asset.decimals as number)) + .multipliedBy(BigNumber(10).pow(pool.y.asset.decimals as number)) + .div(BigNumber(10).pow(pool.y.asset.decimals as number)) + .toString(), + expectedAmount: BigNumber(BigInt(1).toString()) + .div(BigNumber(10).pow(pool.y.asset.decimals as number)) + .toString(), + price: BigNumber(BigInt(1).toString()) + .div(BigNumber(10).pow(pool.y.asset.decimals as number)) + .div( + BigNumber(pool.outputAmount().amount.toString()).div( + BigNumber(10).pow(pool.x.asset.decimals as number), + ), + ) .toString(), - expectedAmount: BigInt(1).toString(), - price: BigInt(1).toString(), network: ergo.network, // timestamp ignored because there was a really small difference between create Date.new() in test file and main file // timestamp: Date.now(), latency: 0, - gasPrice: 0, - gasPriceToken: '0', - gasLimit: 0, - gasCost: '0', + gasPrice: BigNumber('2000').div(BigNumber(10).pow(9)).toNumber(), + gasPriceToken: BigNumber('2000').div(BigNumber(10).pow(9)).toString(), + gasLimit: BigNumber('2000').div(BigNumber(10).pow(9)).toNumber(), + gasCost: BigNumber('2000').div(BigNumber(10).pow(9)).toString(), }); }); - it('Should estimate successfully when sell is false', async () => { + it('Should estimate successfully when sell is true', async () => { patchGetErgoConfig('mainnet'); - jest.spyOn(ergo, 'getPoolByToken').mockReturnValue(null as any); jest .spyOn(ergo_utils, 'getBaseInputParameters') .mockReturnValue({ minOutput: { amount: BigInt(1) } } as any); - jest.spyOn(ergo, 'getPoolByToken').mockReturnValue(pool); - // to set sell false: - const baseToken = 'xId'; + jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([pool]); + // to set sell 'true' + const baseToken: string = 'SigUSD'; + const quoteToken: string = 'ERG'; const result = await ergo.estimate(baseToken, quoteToken, value); expect(result).toMatchObject({ base: baseToken, quote: quoteToken, amount: value - .multipliedBy(BigNumber(10).pow(pool.y.asset.decimals as number)) + .multipliedBy(BigNumber(10).pow(pool.x.asset.decimals as number)) + .div(BigNumber(10).pow(pool.x.asset.decimals as number)) .toString(), rawAmount: value - .multipliedBy(BigNumber(10).pow(pool.y.asset.decimals as number)) + .multipliedBy(BigNumber(10).pow(pool.x.asset.decimals as number)) + .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + .toString(), + expectedAmount: BigNumber(BigInt(1).toString()) + .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + .toString(), + price: BigNumber(1) + .div( + BigNumber(BigInt(1).toString()) + .div(BigNumber(10).pow(pool.x.asset.decimals as number)) + .div( + BigNumber(pool.outputAmount().amount.toString()).div( + BigNumber(10).pow(pool.y.asset.decimals as number), + ), + ), + ) .toString(), - expectedAmount: BigInt(1).toString(), - price: BigInt(2).toString(), network: ergo.network, // timestamp ignored because there was a really small difference between create Date.new() in test file and main file // timestamp: Date.now(), latency: 0, - gasPrice: 0, - gasPriceToken: '0', - gasLimit: 0, - gasCost: '0', + gasPrice: BigNumber('2000').div(BigNumber(10).pow(9)).toNumber(), + gasPriceToken: BigNumber('2000').div(BigNumber(10).pow(9)).toString(), + gasLimit: BigNumber('2000').div(BigNumber(10).pow(9)).toNumber(), + gasCost: BigNumber('2000').div(BigNumber(10).pow(9)).toString(), }); }); }); From a71755a7cd51c74dd6832aa3b45faad57a1755ca Mon Sep 17 00:00:00 2001 From: satiparpar Date: Wed, 24 Jul 2024 12:49:07 +0330 Subject: [PATCH 117/132] update [unit-test]: update unit tests based on new updates for Ergo => "getPoolByToken" mehtod --- test-bronze/chains/ergo/ergo.test.ts | 66 ++++++++++++++++++---------- 1 file changed, 42 insertions(+), 24 deletions(-) diff --git a/test-bronze/chains/ergo/ergo.test.ts b/test-bronze/chains/ergo/ergo.test.ts index feb472e790..1cd04edf3c 100644 --- a/test-bronze/chains/ergo/ergo.test.ts +++ b/test-bronze/chains/ergo/ergo.test.ts @@ -1777,57 +1777,75 @@ describe('Ergo', () => { }); describe('getPoolByToken', () => { beforeEach(() => { - ergo['_assetMap']['ERGO'] = { - tokenId: - '0000000000000000000000000000000000000000000000000000000000000000', - decimals: 9, - name: 'ERGO', - symbol: 'ERG', - }; + jest.spyOn(ergo, 'storedAssetList', 'get').mockReturnValue([ + { + tokenId: 'SigUSDId', + decimals: 3, + name: 'SigUSD', + symbol: 'SigUSD', + }, + { + tokenId: 'ERGId', + decimals: 9, + name: 'ergo', + symbol: 'ERG', + }, + ]); }); const baseToken = 'ERG'; - const quoteToken = 'RSN'; - it('Should throw new Error if quote token is not found', () => { + const quoteToken = 'SigUSD'; + it('Should throw new Error if baseToken is available but quoteToken is not available on storedAssetList', () => { + // ERG is available but SigUSD is not + jest.spyOn(ergo, 'storedAssetList', 'get').mockReturnValue([ + { + tokenId: 'ERGId', + decimals: 9, + name: 'ergo', + symbol: 'ERG', + }, + ]); expect(() => ergo.getPoolByToken(baseToken, quoteToken)).toThrow( `${baseToken} or ${quoteToken} not found!`, ); }); - it('Should throw new Error if base token is not found', () => { - // swap baseToken with quoteToken - const baseToken = 'RSN'; - const quoteToken = 'ERG'; + it('Should throw new Error if baseToken is available but quoteToken is not available on storedAssetList', () => { + // SigUSD is available but ERG is not + jest.spyOn(ergo, 'storedAssetList', 'get').mockReturnValue([ + { + tokenId: 'SigUSDId', + decimals: 9, + name: 'SigUSD', + symbol: 'SigUSD', + }, + ]); expect(() => ergo.getPoolByToken(baseToken, quoteToken)).toThrow( `${baseToken} or ${quoteToken} not found!`, ); }); it('Should find poll when both base token and quote are valid in ammPools array', () => { - ergo['_assetMap']['ROSEN'] = { - tokenId: - '1111111111111111111111111111111111111111111111111111111111111111', - decimals: 9, - name: 'ROSEN', - symbol: 'RSN', - }; const ergoRnsPool = { id: '1b694b15467c62f0cd4525e368dbdea2329c713aa200b73df4a622e950551b40', x: { asset: { - id: '0000000000000000000000000000000000000000000000000000000000000000', + id: 'ERGId', name: 'ERGO', decimals: 9, }, }, y: { asset: { - id: '1111111111111111111111111111111111111111111111111111111111111111', - name: 'ROSEN', + id: 'SigUSDId', + name: 'SigUSD', decimals: 3, }, }, } as any; ergo['ammPools'].push(ergoRnsPool); const result = ergo.getPoolByToken(baseToken, quoteToken); - expect(result).toEqual(ergoRnsPool); + expect(result).toEqual([ergoRnsPool]); + expect(result[0].id).toEqual( + '1b694b15467c62f0cd4525e368dbdea2329c713aa200b73df4a622e950551b40', + ); }); }); From 624d63b0b30ea330dd081525ff27b143aeaf033c Mon Sep 17 00:00:00 2001 From: satiparpar Date: Wed, 24 Jul 2024 14:47:42 +0330 Subject: [PATCH 118/132] add [unit-test]: Implement unit tests for "Ergo" => "getAccountFromAddress" method --- test-bronze/chains/ergo/ergo.test.ts | 41 +++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/test-bronze/chains/ergo/ergo.test.ts b/test-bronze/chains/ergo/ergo.test.ts index 1cd04edf3c..77197d9f5d 100644 --- a/test-bronze/chains/ergo/ergo.test.ts +++ b/test-bronze/chains/ergo/ergo.test.ts @@ -21,9 +21,11 @@ import { ErgoBox, } from '../../../src/chains/ergo/interfaces/ergo.interface'; import LRUCache from 'lru-cache'; +import fse from 'fs-extra'; import { makeNativePools } from '@patternglobal/ergo-dex-sdk'; import { BigNumber } from 'bignumber.js'; import * as ergo_utils from '../../../src/chains/ergo/ergo.util'; +import { ConfigManagerCertPassphrase } from '../../../src/services/config-manager-cert-passphrase'; jest.mock('@patternglobal/ergo-dex-sdk', () => ({ AmmPool: jest.fn(), @@ -610,7 +612,44 @@ describe('Ergo', () => { expect(encryptedText).toMatch(/^[0-9a-fA-F]{32}:[0-9a-fA-F]+$/); }); }); - + describe('getAccountFromAddress', () => { + beforeEach(() => { + jest.spyOn(fse, 'readFile').mockResolvedValue('file' as any); + }); + it('Should be defined', () => { + expect(ergo.getAccountFromAddress).toBeDefined(); + }); + it('Should throw new Error if passphrase is invalid', async () => { + jest + .spyOn(ConfigManagerCertPassphrase, 'readPassphrase') + .mockReturnValue(undefined); + await expect(ergo.getAccountFromAddress('address')).rejects.toThrow( + 'missing passphrase', + ); + expect(fse.readFile).toHaveBeenCalledWith( + './conf/wallets/ergo/address.json', + 'utf8', + ); + }); + it('Should return account from address given', async () => { + jest + .spyOn(ConfigManagerCertPassphrase, 'readPassphrase') + .mockReturnValue('passphrase'); + jest.spyOn(ergo, 'decrypt').mockReturnValue('mnemonic'); + jest + .spyOn(ergo, 'getAccountFromMnemonic') + .mockReturnValue('Ergo Accont' as any); + const result = await ergo.getAccountFromAddress('address'); + expect(ergo.decrypt).toHaveBeenCalledWith('file', 'passphrase'); + expect(ConfigManagerCertPassphrase.readPassphrase).toHaveBeenCalled(); + expect(fse.readFile).toHaveBeenCalledWith( + './conf/wallets/ergo/address.json', + 'utf8', + ); + expect(ergo.getAccountFromMnemonic).toHaveBeenCalledWith('mnemonic'); + expect(result).toEqual('Ergo Accont'); + }); + }); describe('decrypt', () => { it('Should decrypt an encrypted secret correctly', () => { // Arrange: Set up the secret and password, and encrypt the secret From e40e75e30f1c1e9e926127a2b76ca602b2c79de9 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Wed, 24 Jul 2024 16:18:43 +0330 Subject: [PATCH 119/132] update [unit-test]: update unit tests based on new updates for NodeService & ergo.utils --- test-bronze/chains/ergo/ergo.utils.test.ts | 2 +- test-bronze/chains/ergo/node.service.test.ts | 20 ++++++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/test-bronze/chains/ergo/ergo.utils.test.ts b/test-bronze/chains/ergo/ergo.utils.test.ts index b2fb0ee04d..7b14cb0166 100644 --- a/test-bronze/chains/ergo/ergo.utils.test.ts +++ b/test-bronze/chains/ergo/ergo.utils.test.ts @@ -176,7 +176,7 @@ describe('getInputs', () => { const utxos: any = [{ value: 1, assets: [{ amount: 2 }] }]; const result = ergo_utils.getInputs(utxos, assets, fees); expect(DefaultBoxSelector.select).toHaveBeenCalledWith( - [{ value: '1', assets: [{ amount: '2' }] }], + [{ value: BigInt('1'), assets: [{ amount: BigInt('2') }] }], {}, ); expect(result).toEqual({}); diff --git a/test-bronze/chains/ergo/node.service.test.ts b/test-bronze/chains/ergo/node.service.test.ts index c859ff7f04..a74dd06fd7 100644 --- a/test-bronze/chains/ergo/node.service.test.ts +++ b/test-bronze/chains/ergo/node.service.test.ts @@ -165,16 +165,21 @@ describe('NodeService', () => { it('Should be defined', () => { expect(nodeService.postTransaction).toBeDefined(); }); + it('Should return an empty string if request method fails', async () => { + jest + .spyOn(nodeService as any, 'request') + .mockRejectedValue('Bad request'); + expect(await nodeService.postTransaction('tx')).toEqual(''); + }); it('Should call request method with the correct parameters', async () => { - const tx = 'tx'; jest.spyOn(nodeService as any, 'request').mockResolvedValue({ data: {} }); - await nodeService.postTransaction(tx); + await nodeService.postTransaction('tx'); expect(nodeService['request']).toHaveBeenCalledWith( 'POST', `/transactions`, - { 'Content-Type': 'text/plain' }, - tx, + { 'Content-Type': 'application/json' }, + 'tx', ); }); }); @@ -184,6 +189,13 @@ describe('NodeService', () => { expect(nodeService.getTxsById).toBeDefined(); }); + it('Should return undefined if request method fails', async () => { + jest + .spyOn(nodeService as any, 'request') + .mockRejectedValue('Bad request'); + expect(await nodeService.getTxsById('blockHeight')).toEqual(undefined); + }); + it('Should call request method with the correct parameters', async () => { const id = 'id'; await nodeService.getTxsById(id); From 68995cff22b62bb825b7ca8eb57d0a6b2fcfa48b Mon Sep 17 00:00:00 2001 From: satiparpar Date: Thu, 25 Jul 2024 11:33:54 +0330 Subject: [PATCH 120/132] add [unit-test]: Implement unit tests for "Spectrum" => "getInstance" method --- .../connectors/spectrum/spectrum.test.ts | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 test-bronze/connectors/spectrum/spectrum.test.ts diff --git a/test-bronze/connectors/spectrum/spectrum.test.ts b/test-bronze/connectors/spectrum/spectrum.test.ts new file mode 100644 index 0000000000..817e6e22e0 --- /dev/null +++ b/test-bronze/connectors/spectrum/spectrum.test.ts @@ -0,0 +1,60 @@ +import { Ergo } from '../../../src/chains/ergo/ergo'; +import { Spectrum } from '../../../src/connectors/spectrum/spectrum'; +// import { SpectrumConfig } from '../../../src/connectors/spectrum/spectrum.config'; +jest.mock('../../../src/connectors/spectrum/spectrum.config', () => { + return { + SpectrumConfig: { + config: { + allowedSlippage: '100', + gasLimitEstimate: '100000', + tradingTypes: ['AMM'], + chainType: 'ERGO', + availableNetworks: ['mainnet', 'testnet'], + }, + }, + }; +}); + +describe('Spectrum', () => { + const network = 'mainnet'; + const chain = 'ergo'; + let spectrum: Spectrum; + beforeEach(() => { + jest.spyOn(Ergo, 'getInstance').mockReturnValue('ergo instance' as any); + spectrum = Spectrum.getInstance('ergo', 'mainnet'); + }); + afterEach(() => { + jest.clearAllMocks(); + Spectrum['_instances'] = {}; + }); + it('Should be defined', () => { + expect(spectrum).toBeDefined(); + }); + describe('getInstance', () => { + it('should create a new instance if it does not exist', () => { + expect(spectrum).toBeDefined(); + expect(Spectrum['_instances'][chain + network]).toBe(spectrum); + expect(Spectrum['_instances']['ergomainnet']).toBeInstanceOf(Spectrum); + }); + + it('should return the existing instance if it exists', () => { + const instance2 = Spectrum.getInstance(chain, network); + + expect(spectrum).toBe(instance2); + expect(Spectrum['_instances'][chain + network]).toBe(spectrum); + }); + it('should call Ergo.getInstance with the correct network and initialize values correctly', () => { + // set _instances = {} to call the constructor + Spectrum['_instances'] = {}; + Spectrum.getInstance(chain, network); + expect(Ergo.getInstance).toHaveBeenCalledWith(network); + expect(spectrum['tokenList']).toEqual({}); + expect(spectrum['_ready']).toEqual(false); + expect(spectrum['ergo']).toEqual('ergo instance'); + }); + + it('should initialize gasLimitEstimate from SpectrumConfig', () => { + expect(spectrum['_gasLimitEstimate']).toEqual('100000'); + }); + }); +}); From c905be521f3f6b3b587ab59adcfde2aa30976b62 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Thu, 25 Jul 2024 12:31:22 +0330 Subject: [PATCH 121/132] add [unit-test]: Implement unit tests for "Spectrum" => "getTokenByAddress" & "init" methods --- .../connectors/spectrum/spectrum.test.ts | 63 ++++++++++++++++++- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/test-bronze/connectors/spectrum/spectrum.test.ts b/test-bronze/connectors/spectrum/spectrum.test.ts index 817e6e22e0..2bf0230795 100644 --- a/test-bronze/connectors/spectrum/spectrum.test.ts +++ b/test-bronze/connectors/spectrum/spectrum.test.ts @@ -1,6 +1,6 @@ import { Ergo } from '../../../src/chains/ergo/ergo'; +import { ErgoAsset } from '../../../src/chains/ergo/interfaces/ergo.interface'; import { Spectrum } from '../../../src/connectors/spectrum/spectrum'; -// import { SpectrumConfig } from '../../../src/connectors/spectrum/spectrum.config'; jest.mock('../../../src/connectors/spectrum/spectrum.config', () => { return { SpectrumConfig: { @@ -16,11 +16,12 @@ jest.mock('../../../src/connectors/spectrum/spectrum.config', () => { }); describe('Spectrum', () => { + const ergo: Ergo = new Ergo('mainnet'); const network = 'mainnet'; const chain = 'ergo'; let spectrum: Spectrum; beforeEach(() => { - jest.spyOn(Ergo, 'getInstance').mockReturnValue('ergo instance' as any); + jest.spyOn(Ergo, 'getInstance').mockReturnValue(ergo); spectrum = Spectrum.getInstance('ergo', 'mainnet'); }); afterEach(() => { @@ -31,6 +32,9 @@ describe('Spectrum', () => { expect(spectrum).toBeDefined(); }); describe('getInstance', () => { + it('Should be defined', () => { + expect(Spectrum.getInstance).toBeDefined(); + }); it('should create a new instance if it does not exist', () => { expect(spectrum).toBeDefined(); expect(Spectrum['_instances'][chain + network]).toBe(spectrum); @@ -50,11 +54,64 @@ describe('Spectrum', () => { expect(Ergo.getInstance).toHaveBeenCalledWith(network); expect(spectrum['tokenList']).toEqual({}); expect(spectrum['_ready']).toEqual(false); - expect(spectrum['ergo']).toEqual('ergo instance'); + expect(spectrum['ergo']).toEqual(ergo); }); it('should initialize gasLimitEstimate from SpectrumConfig', () => { expect(spectrum['_gasLimitEstimate']).toEqual('100000'); }); }); + + describe('getTokenByAddress', () => { + it('Should be defined', () => { + expect(spectrum.getTokenByAddress).toBeDefined(); + }); + it('Should return the token correctly', () => { + spectrum['tokenList']['tokenAddress'] = + 'ErgoAsset' as unknown as ErgoAsset; + expect(spectrum.getTokenByAddress('tokenAddress')).toEqual('ErgoAsset'); + }); + }); + describe('init', () => { + jest.spyOn(ergo, 'init').mockReturnValue('' as any); + it('Should be defined', () => { + expect(spectrum.init).toBeDefined(); + }); + it('Should call init method from ergo if ergo is not ready', async () => { + jest.spyOn(ergo, 'ready').mockReturnValue(false); + await spectrum.init(); + expect(ergo.ready).toHaveBeenCalled(); + expect(ergo.init).toHaveBeenCalled(); + }); + it('Should not call init method from ergo if ergo is ready', async () => { + jest.spyOn(ergo, 'ready').mockReturnValue(true); + await spectrum.init(); + expect(ergo.ready).toHaveBeenCalled(); + expect(ergo.init).not.toHaveBeenCalled(); + }); + + it('Should updtate "tokenList" & "ready" status', async () => { + const assetMap: Record = { + ERGO: { + tokenId: 'ERGOId', + decimals: 9, + name: 'ERGO', + symbol: 'ERG', + }, + SigUSD: { + tokenId: 'SigUSDId', + decimals: 3, + name: 'SigUSD', + symbol: 'SigUSD', + }, + }; + jest.spyOn(ergo, 'storedTokenList', 'get').mockReturnValue(assetMap); + // to ensure tokenList is empty + expect(spectrum['tokenList']).toEqual({}); + await spectrum.init(); + expect; + expect(spectrum['_ready']).toEqual(true); + expect(spectrum['tokenList']).toEqual(assetMap); + }); + }); }); From 52c063f7e07e7be1d35599aa34bcb84b86ca2bdd Mon Sep 17 00:00:00 2001 From: satiparpar Date: Thu, 25 Jul 2024 15:11:00 +0330 Subject: [PATCH 122/132] add [unit-test]: Implement unit tests for "Spectrum" => "ready", "gasLimitEstimate", "estimateTrade" & "executeTrade" methods --- .../connectors/spectrum/spectrum.test.ts | 143 ++++++++++++++++++ 1 file changed, 143 insertions(+) diff --git a/test-bronze/connectors/spectrum/spectrum.test.ts b/test-bronze/connectors/spectrum/spectrum.test.ts index 2bf0230795..a5d9ba0716 100644 --- a/test-bronze/connectors/spectrum/spectrum.test.ts +++ b/test-bronze/connectors/spectrum/spectrum.test.ts @@ -1,3 +1,5 @@ +import { BigNumber } from 'bignumber.js'; +import { PriceRequest, TradeRequest } from '../../../src/amm/amm.requests'; import { Ergo } from '../../../src/chains/ergo/ergo'; import { ErgoAsset } from '../../../src/chains/ergo/interfaces/ergo.interface'; import { Spectrum } from '../../../src/connectors/spectrum/spectrum'; @@ -114,4 +116,145 @@ describe('Spectrum', () => { expect(spectrum['tokenList']).toEqual(assetMap); }); }); + + describe('ready', () => { + it('Should be defined', () => { + expect(spectrum.ready).toBeDefined(); + }); + it('Should return the value of ready', () => { + expect(spectrum.ready()).toEqual(false); + }); + }); + describe('gasLimitEstimate', () => { + it('Should be defined', () => { + expect(spectrum.gasLimitEstimate).toBeDefined(); + }); + it('Should retuern gasLimitEstimate correctly', () => { + expect(spectrum.gasLimitEstimate).toEqual('100000'); + }); + }); + + describe('estimateTrade', () => { + const req: PriceRequest = { + chain: 'ergo', + network: 'mainnet', + quote: '_ERGO', + base: '_SigUSD', + amount: '1000', + side: 'SELL', + allowedSlippage: '50', + }; + jest.spyOn(ergo, 'estimate').mockResolvedValue({} as any); + afterEach(() => { + jest.clearAllMocks(); + }); + it('Should be defined', () => { + expect(spectrum.estimateTrade).toBeDefined(); + }); + it('Should call estimate from ergo with the correct data if erq.side === "SELL"', async () => { + const result = await spectrum.estimateTrade(req); + expect(ergo.estimate).toHaveBeenCalledWith( + 'SigUSD', + 'ERGO', + BigNumber('1000'), + Number('50'), + ); + expect(result).toEqual({}); + }); + + it('Should call estimate from ergo with the correct data if erq.side === "BUY"', async () => { + req.side = 'BUY'; + const result = await spectrum.estimateTrade(req); + expect(ergo.estimate).toHaveBeenCalledWith( + 'ERGO', + 'SigUSD', + BigNumber('1000'), + Number('50'), + ); + expect(result).toEqual({}); + }); + it('Should call estimate from ergo with the correct data if erq.side is not "SELL" nor "BUY"', async () => { + req.side = 'someOtherSide' as any; + const result = await spectrum.estimateTrade(req); + expect(ergo.estimate).toHaveBeenCalledWith( + 'SigUSD', + 'ERGO', + BigNumber('1000'), + Number('50'), + ); + expect(result).toEqual({}); + }); + }); + + describe('executeTrade', () => { + const req: TradeRequest = { + chain: 'ergo', + network: 'mainnet', + quote: '_ERGO', + base: '_SigUSD', + amount: '1000', + address: 'ergAccountAddress', + side: 'SELL', + allowedSlippage: '50', + }; + jest + .spyOn(ergo, 'getAccountFromAddress') + .mockResolvedValue('ergoAccount' as any); + jest.spyOn(ergo, 'swap').mockResolvedValue({} as any); + it('Should be defined', () => { + expect(spectrum.executeTrade).toBeDefined(); + }); + + it('Should call swap from ergo with the correct data if erq.side === "SELL"', async () => { + const result = await spectrum.executeTrade(req); + expect(ergo.swap).toHaveBeenCalledWith( + 'ergoAccount', + 'SigUSD', + 'ERGO', + BigNumber('1000'), + 'ergAccountAddress', + 'ergAccountAddress', + Number('50'), + ); + expect(ergo.getAccountFromAddress).toHaveBeenCalledWith( + 'ergAccountAddress', + ); + expect(result).toEqual({}); + }); + + it('Should call swap from ergo with the correct data if erq.side === "BUY"', async () => { + req.side = 'BUY'; + const result = await spectrum.executeTrade(req); + expect(ergo.swap).toHaveBeenCalledWith( + 'ergoAccount', + 'ERGO', + 'SigUSD', + BigNumber('1000'), + 'ergAccountAddress', + 'ergAccountAddress', + Number('50'), + ); + expect(ergo.getAccountFromAddress).toHaveBeenCalledWith( + 'ergAccountAddress', + ); + expect(result).toEqual({}); + }); + it('Should call swap from ergo with the correct data if erq.side is not "SELL" nor "BUY"', async () => { + req.side = 'someOtherSide' as any; + const result = await spectrum.executeTrade(req); + expect(ergo.swap).toHaveBeenCalledWith( + 'ergoAccount', + 'SigUSD', + 'ERGO', + BigNumber('1000'), + 'ergAccountAddress', + 'ergAccountAddress', + Number('50'), + ); + expect(ergo.getAccountFromAddress).toHaveBeenCalledWith( + 'ergAccountAddress', + ); + expect(result).toEqual({}); + }); + }); }); From f4a6ab2412bdd62170153b8475b36dcdfd9c8cfd Mon Sep 17 00:00:00 2001 From: satiparpar Date: Thu, 25 Jul 2024 15:41:42 +0330 Subject: [PATCH 123/132] add [unit-test]: Implement unit tests for "SpectrumConfig" --- .../spectrum/spectrum.config.test.ts | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 test-bronze/connectors/spectrum/spectrum.config.test.ts diff --git a/test-bronze/connectors/spectrum/spectrum.config.test.ts b/test-bronze/connectors/spectrum/spectrum.config.test.ts new file mode 100644 index 0000000000..1b974d586c --- /dev/null +++ b/test-bronze/connectors/spectrum/spectrum.config.test.ts @@ -0,0 +1,29 @@ +import { ConfigManagerV2 } from '../../../src/services/config-manager-v2'; + +describe('SpectrumConfig', () => { + let configManager: ReturnType; + + beforeEach(() => { + configManager = ConfigManagerV2.getInstance(); + jest.clearAllMocks(); + }); + it('Should initialize config with correct data', () => { + jest.spyOn(configManager, 'get').mockReturnValueOnce(0.01); + jest.spyOn(configManager, 'get').mockReturnValueOnce(100000); + + const { + SpectrumConfig, + } = require('../../../src/connectors/spectrum/spectrum.config'); + + expect(SpectrumConfig.config.allowedSlippage).toEqual(0.01); + expect(configManager.get).toHaveBeenCalledWith('ergo.allowedSlippage'); + expect(SpectrumConfig.config.gasLimitEstimate).toEqual(100000); + expect(configManager.get).toHaveBeenCalledWith('ergo.gasLimitEstimate'); + + expect(SpectrumConfig.config.tradingTypes).toEqual(['AMM']); + expect(SpectrumConfig.config.chainType).toEqual('ERGO'); + expect(SpectrumConfig.config.availableNetworks).toEqual([ + { chain: 'ergo', networks: ['mainnet'] }, + ]); + }); +}); From 16bb49170d44f2baa3ca924c9c57ce5ab2b88b20 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Fri, 26 Jul 2024 10:43:22 +0330 Subject: [PATCH 124/132] add [unit-test]: Implement unit tests for "WalletProver" --- .../chains/ergo/wallet-prover.service.test.ts | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 test-bronze/chains/ergo/wallet-prover.service.test.ts diff --git a/test-bronze/chains/ergo/wallet-prover.service.test.ts b/test-bronze/chains/ergo/wallet-prover.service.test.ts new file mode 100644 index 0000000000..f08eeb897b --- /dev/null +++ b/test-bronze/chains/ergo/wallet-prover.service.test.ts @@ -0,0 +1,93 @@ +import { WalletProver } from '../../../src/chains/ergo/wallet-prover.service'; +import { + UnsignedTransaction, + Wallet, + Transaction, + ErgoBoxes, +} from 'ergo-lib-wasm-nodejs'; +import { NodeService } from '../../../src/chains/ergo/node.service'; +import * as ergSDK from '@patternglobal/ergo-sdk'; +import { ErgoTx } from '@patternglobal/ergo-sdk'; +describe('WalletProver', () => { + const wallet = new Wallet(); + const nodeService = new NodeService('fake-url', 5000); + const prover = new WalletProver(wallet, nodeService); + it('Should be defined', () => { + expect(WalletProver).toBeDefined(); + }); + it('Should initialize WalletProver with the coorect parameters', () => { + expect(prover.wallet).toEqual(wallet); + expect(prover.nodeService).toEqual(nodeService); + }); + + describe('sign', () => { + const tx = new Transaction(); + beforeEach(() => { + jest.spyOn(JSON, 'stringify').mockReturnValue({} as any); + jest.spyOn(nodeService, 'getCtx').mockResolvedValue({} as any); + jest.spyOn(UnsignedTransaction, 'from_json').mockReturnValue({} as any); + jest + .spyOn(ergSDK, 'unsignedErgoTxToProxy') + .mockReturnValue({ inputs: [{ boxId: '123' }] } as any); + jest.spyOn(wallet, 'sign_transaction').mockReturnValue(tx); + }); + it('Should be defined', () => { + expect(prover.sign).toBeDefined(); + }); + it('Should sign the transaction successfully', async () => { + jest.spyOn(tx, 'to_js_eip12').mockReturnValue({} as any); + jest.spyOn(ErgoBoxes, 'from_boxes_json').mockReturnValue({} as any); + jest.spyOn(ErgoBoxes, 'empty').mockReturnValue({} as any); + const result = await prover.sign('tx' as any); + expect(result).toEqual({}); + }); + it('Should handle the case if signing the transaction fails', async () => { + jest.spyOn(JSON, 'stringify').mockReturnValue({} as any); + jest + .spyOn(wallet, 'sign_transaction') + .mockReturnValue(new Error('some error') as any); + + await expect(prover.sign('tx' as any)).rejects.toThrow( + 'not be able to sign!', + ); + }); + }); + + describe('submit', () => { + const tx: ErgoTx = { + id: 'TxId', + inputs: [], + dataInputs: [], + outputs: [], + size: 1, + }; + it('Should be defined', () => { + expect(prover.submit).toBeDefined(); + }); + it('Should call postTransaction from nodeService and return the correct data', async () => { + jest + .spyOn(nodeService, 'postTransaction') + .mockResolvedValue('returnedTxId'); + jest.spyOn(JSON, 'stringify').mockReturnValue({} as any); + const result = await prover.submit(tx); + expect(nodeService.postTransaction).toHaveBeenCalledWith({}); + expect(JSON.stringify).toHaveBeenCalledWith(tx); + expect(result).toEqual({ + id: 'returnedTxId', + inputs: [], + dataInputs: [], + outputs: [], + size: 1, + }); + }); + }); + + describe('signInput', () => { + it('Should be defined', () => { + expect(prover.signInput).toBeDefined(); + }); + it('Should retrn nothing is called', () => { + expect(prover.signInput('tx' as any, 'inout' as any)).toEqual(undefined); + }); + }); +}); From c92ca004b91721213bd3b7eb1ed9fa72b9ab7d60 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Fri, 26 Jul 2024 18:16:13 +0330 Subject: [PATCH 125/132] cleanUp [ unit-test ]: Ergo unit tests cleaned up --- test-bronze/chains/ergo/ergo.test.ts | 320 ++++++++++----------------- 1 file changed, 114 insertions(+), 206 deletions(-) diff --git a/test-bronze/chains/ergo/ergo.test.ts b/test-bronze/chains/ergo/ergo.test.ts index 77197d9f5d..10abd86942 100644 --- a/test-bronze/chains/ergo/ergo.test.ts +++ b/test-bronze/chains/ergo/ergo.test.ts @@ -185,7 +185,6 @@ beforeEach(() => { patchGetErgoConfig('mainnet'); ergo = new Ergo('mainnet'); }); -// Clean up mocks after each test afterEach(() => { unpatch(); jest.clearAllMocks(); @@ -207,7 +206,6 @@ describe('Ergo', () => { expect(ergo['_network']).toEqual('mainnet'); expect(ergo['_networkPrefix']).toEqual(NetworkPrefix.Mainnet); expect(ergo['_node']).toBeInstanceOf(NodeService); - // expect(ergo['_explorer']).toBeInstanceOf(Explorer); expect(ergo['_dex']).toBeInstanceOf(DexService); expect(ergo['txFee']).toEqual(2000); expect(ergo['controller']).toEqual(ErgoController); @@ -217,19 +215,15 @@ describe('Ergo', () => { }); it('Should initialize with testnet configuration', () => { - // Arrange: Mock the return value of getErgoConfig to simulate testnet configuration patchGetErgoConfig('testnet'); - // Act: Create a new instance of Ergo with 'testnet' configuration const ergo = new Ergo('testnet'); - // Assert: Validate the initialization state of Ergo instance expect(ergo).toBeDefined(); expect(ergo['_assetMap']).toEqual({}); expect(ergo['_network']).toEqual('testnet'); expect(ergo['_networkPrefix']).toEqual(NetworkPrefix.Testnet); expect(ergo['_node']).toBeInstanceOf(NodeService); - // expect(ergo['_explorer']).toBeInstanceOf(Explorer); expect(ergo['_dex']).toBeInstanceOf(DexService); expect(ergo['txFee']).toEqual(2000); expect(ergo['controller']).toEqual(ErgoController); @@ -239,8 +233,10 @@ describe('Ergo', () => { }); describe('get node', () => { + it('Should be defined', () => { + expect(ergo.node).toBeDefined(); + }); it('Should initialize node correctly and return the correct node', () => { - // Assert: Validate the initialization state of node instance and check the returned value expect(ergo.node).toBeInstanceOf(NodeService); expect(ergo.node).toEqual({ nodeURL: 'ergo.networks.mainnet.nodeURL', @@ -250,6 +246,9 @@ describe('Ergo', () => { }); describe('get network', () => { + it('Should be defined', () => { + expect(ergo.network).toBeDefined(); + }); it('Should return the correct network when network is mainnet', () => { expect(ergo.network).toBe('mainnet'); }); @@ -264,24 +263,33 @@ describe('Ergo', () => { }); describe('get storedAssetList', () => { + it('Should be defined', () => { + expect(ergo.storedAssetList); + }); it('Should return the stored asset list', () => { - // Arrange: Create mock assets and populate _assetMap - const asset1: ErgoAsset = 1 as any; - const asset2: ErgoAsset = 2 as any; - const assetMap = { - key1: asset1, - key2: asset2, + const assetMap: Record = { + ERGO: { + tokenId: 'ERGOId', + decimals: 9, + name: 'ERGO', + symbol: 'ERG', + }, + SigUSD: { + tokenId: 'SigUSDId', + decimals: 3, + name: 'SigUSD', + symbol: 'SigUSD', + }, }; - - // Act: Set _assetMap directly ergo['_assetMap'] = assetMap; - - // Assert: Validate the stored asset list returned by storedAssetList expect(ergo.storedAssetList).toEqual(Object.values(assetMap)); }); }); describe('ready', () => { + it('Should be defined', () => { + expect(ergo.ready).toBeDefined(); + }); it('Should return the ready state', () => { expect(ergo.ready()).toBe(false); ergo['_ready'] = true; @@ -290,6 +298,9 @@ describe('Ergo', () => { }); describe('getNetworkHeight', () => { + it('Should be defined', () => { + expect(ergo.getNetworkHeight).toBeDefined(); + }); it('Should call getNetworkHeight method from node', async () => { jest.spyOn(ergo['_node'], 'getNetworkHeight').mockResolvedValue(1); await ergo.getNetworkHeight(); @@ -298,15 +309,15 @@ describe('Ergo', () => { }); describe('init', () => { + it('Should be defined', () => { + expect(ergo.init).toBeDefined(); + }); it('Should initialize assets and pools in init method', async () => { - // Arrange: Mock the loadAssets & loadPools methods to return a fixed value jest.spyOn(ergo as any, 'loadAssets').mockResolvedValue({}); jest.spyOn(ergo as any, 'loadPools').mockResolvedValue({}); - // Act: Call the init method to initialize assets and pools await ergo.init(); - // Assert: Ensure the loadAssets & loadPools methods were called during initialization expect(ergo['loadAssets']).toHaveBeenCalled(); expect(ergo['loadPools']).toHaveBeenCalled(); expect(ergo.ready()).toBe(true); @@ -314,53 +325,48 @@ describe('Ergo', () => { }); describe('close', () => { + it('Should be defined', () => { + expect(ergo.close).toBeDefined(); + }); it('Should close correctly', async () => { - // Act and Assert: Call the close method and expect that the close method resolves without any errors or values await expect(ergo.close()).resolves.toBeUndefined(); }); }); describe('getInstance', () => { + it('Should be getInstance', () => { + expect(ergo.close).toBeDefined(); + }); const mockNetwork = 'testnet'; beforeEach(() => { - // Arrange: Mock the function to get the configuration for the 'testnet' network patchGetErgoConfig('testnet'); - // Arrange: Clear the singleton and mock instances Ergo['_instances'] = undefined as any; }); it('Should initialize the LRUCache if not already initialized', () => { - // Act: Call the getInstance method with the mock network Ergo.getInstance(mockNetwork); - // Assert: Expect that the _instances property is defined and _instances is an instance of LRUCache expect(Ergo['_instances']).toBeDefined(); expect(Ergo['_instances']).toBeInstanceOf(LRUCache); }); it('Should set and return a new Ergo instance if not in the cache', () => { - // Act: Call the getInstance method with the mock network const instance = Ergo.getInstance(mockNetwork); - // Assert: Expect that the returned instance is an instance of Ergo, the cache contains the mock network key and the instance in the cache matches the returned instance expect(instance).toBeInstanceOf(Ergo); expect(Ergo['_instances'].has(mockNetwork)).toBe(true); expect(Ergo['_instances'].get(mockNetwork)).toBe(instance); }); it('Should return an existing Ergo instance from the cache', () => { - // Act: Call the getInstance method twice with the mock network const instance1 = Ergo.getInstance(mockNetwork); const instance2 = Ergo.getInstance(mockNetwork); - - // Assert: Expect that both calls return the same instance and the cache contains the mock network key expect(instance1).toBe(instance2); expect(Ergo['_instances'].get(mockNetwork)).toBe(instance1); }); it('Should throw an error if an unexpected network is provided', () => { - // Act and Assert: Expect that calling getInstance with an invalid network throws an error expect(() => Ergo.getInstance('invalidNetwork')).toThrow( 'network should be `mainnet` or `testnet`', ); @@ -372,23 +378,20 @@ describe('Ergo', () => { let mockErgoInstance2: Ergo; beforeEach(() => { - // Arrange: Create mock Ergo instances - mockErgoInstance1 = new Ergo('testnet') as any; - mockErgoInstance2 = new Ergo('mainnet') as any; + mockErgoInstance1 = new Ergo('testnet'); + mockErgoInstance2 = new Ergo('mainnet'); - // Arrange: Initialize the _instances LRUCache with mock instances Ergo['_instances'] = new LRUCache({ max: 10, }); Ergo['_instances'].set('testnet', mockErgoInstance1); Ergo['_instances'].set('mainnet', mockErgoInstance2); }); - + it('Should be defined', () => { + expect(Ergo.getConnectedInstances).toBeDefined(); + }); it('Should return all connected instances', () => { - // Act: Call the getConnectedInstances method const connectedInstances = Ergo.getConnectedInstances(); - - // Assert: Expect the connected instances to match the mock instances expect(Object.keys(connectedInstances).sort()).toEqual([ 'mainnet', 'testnet', @@ -398,23 +401,14 @@ describe('Ergo', () => { }); it('Should return an empty object if there are no instances', () => { - // Arrange: Clear the _instances LRUCache Ergo['_instances'] = undefined as any; - - // Act: Call the getConnectedInstances method const connectedInstances = Ergo.getConnectedInstances(); - - // Assert: Expect the connected instances to be an empty object expect(connectedInstances).toEqual({}); }); it('Should return only valid instances', () => { - // Arrange: Set an invalid (null) instance in the _instances LRUCache Ergo['_instances'].set('', null as any); - - // Act: Call the getConnectedInstances method const connectedInstances = Ergo.getConnectedInstances(); - // Assert: Expect the valid instances to be returned and invalid instances to be excluded expect(Object.keys(connectedInstances).sort()).toEqual([ 'mainnet', 'testnet', @@ -426,30 +420,31 @@ describe('Ergo', () => { }); describe('getCurrentBlockNumber', () => { + it('Should be defined', () => { + expect(ergo.getCurrentBlockNumber).toBeDefined(); + }); it('Should return the current block number incremented by one', async () => { - // Arrange: Mock the getNetworkHeight method to return a fixed value jest.spyOn(ergo['_node'], 'getNetworkHeight').mockResolvedValue(17); const blockNumber = await ergo.getCurrentBlockNumber(); - - // Assert: Validate the returned block number expect(blockNumber).toEqual(18); expect(ergo['_node'].getNetworkHeight).toHaveBeenCalled; }); }); describe('getAddressUnspentBoxes', () => { + it('Should be defined', () => { + expect(ergo.getAddressUnspentBoxes).toBeDefined(); + }); const mockAddress = '9j2s7d8f4s8s8o8s0q8f5s8d7f8s0d4r5'; it('Should return an empty arry when length of nodeBoxes is 0', async () => { - // Arrange: Mock the getUnspentBoxesByAddress method to return an empty array await patchErgo_node(); const utxos = await ergo.getAddressUnspentBoxes(mockAddress); expect(utxos).toEqual([]); }); it('Should retrieve all unspent boxes for the given address', async () => { - // Arrange: Mock the getUnspentBoxesByAddress method to return 3 boxes const mockUnspentBoxesPage1 = [ { boxId: 'box1' }, { boxId: 'box2' }, @@ -461,9 +456,7 @@ describe('Ergo', () => { .mockResolvedValueOnce(mockUnspentBoxesPage1) .mockResolvedValueOnce(mockUnspentBoxesPage2) .mockResolvedValueOnce(mockUnspentBoxesPage3); - // Act: Call the getAddressUnspentBoxes method const result = await ergo.getAddressUnspentBoxes(mockAddress); - // Assert: Validate that an empty array is returned expect(result).toEqual([ { boxId: 'box1' }, { boxId: 'box2' }, @@ -489,12 +482,14 @@ describe('Ergo', () => { }); describe('getAccountFromSecretKey', () => { + it('Should be defined', () => { + expect(ergo.getAccountFromSecretKey).toBeDefined(); + }); it('Should return an account with address and wallet from secret key', () => { const secret = '591811a0d6361f18e42549b32e65b98c9a63d6aad369d1056a97ca81f2a980d5'; patchFrom_secrets(); patchTo_base58(); - // Arrange: Mock get_address method const mockGetAddress = jest.fn().mockReturnValue(new Address()); const mockSecretKeyInstance = { get_address: mockGetAddress, @@ -502,18 +497,19 @@ describe('Ergo', () => { jest .spyOn(SecretKey, 'dlog_from_bytes') .mockReturnValue(mockSecretKeyInstance); - // Arrange: Mock add method for SecretKeys const mockAdd = jest.fn(); jest.spyOn(SecretKeys.prototype, 'add').mockImplementation(mockAdd); const result = ergo.getAccountFromSecretKey(secret); - // Assert: Validate the returned address and wallet expect(result.address).toBe('testAddress'); expect(result.wallet).toBe('testWallet'); }); }); describe('getAccountFromMnemonic', () => { + it('Should be defined', () => { + expect(ergo.getAccountFromMnemonic).toBeDefined(); + }); it('Should return an account with address and wallet from mnemonic', () => { patchFrom_secrets(); patchTo_base58(); @@ -549,66 +545,40 @@ describe('Ergo', () => { }); describe('encrypt', () => { + const secret = 'mySecret'; + const password = 'myPassword'; + it('Should be defined', () => { + expect(ergo.encrypt).toBeDefined(); + }); it('Should encrypt a secret with a given password', () => { - // Arrange: Set up the secret and password - const secret = 'mySecret'; - const password = 'myPassword'; - const encryptedText = ergo.encrypt(secret, password); - // Assert: Verify the encrypted text format expect(encryptedText).toMatch(/^[0-9a-fA-F]{32}:[0-9a-fA-F]+$/); }); it('Should produce different encryption outputs for different secrets', () => { - // Arrange: Set up the password - const password = 'myPassword'; - - // Act: Call the encrypt method with two different secrets const encryptedText1 = ergo.encrypt('secret1', password); const encryptedText2 = ergo.encrypt('secret2', password); - - // Assert: Verify that the encrypted texts are different expect(encryptedText1).not.toBe(encryptedText2); }); it('Should produce different encryption outputs for different passwords', () => { - // Arrange: Set up the secret - const secret = 'mySecret'; - - // Act: Call the encrypt method with two different passwords const encryptedText1 = ergo.encrypt(secret, 'password1'); const encryptedText2 = ergo.encrypt(secret, 'password2'); - - // Assert: Verify that the encrypted texts are different expect(encryptedText1).not.toBe(encryptedText2); }); it('Should produce different IVs for different encryptions', () => { - // Arrange: Set up the secret and password - const secret = 'mySecret'; - const password = 'myPassword'; - - // Act: Call the encrypt method twice with the same secret and password const encryptedText1 = ergo.encrypt(secret, password); const encryptedText2 = ergo.encrypt(secret, password); - // Extract IVs from the encrypted texts const [iv1] = encryptedText1.split(':'); const [iv2] = encryptedText2.split(':'); - - // Assert: Verify that the IVs are different expect(iv1).not.toBe(iv2); }); it('Should handle edge case where password is longer than 32 bytes', () => { - // Arrange: Set up the secret and a long password - const secret = 'mySecret'; const longPassword = 'a'.repeat(50); // 50 bytes password - - // Act: Call the encrypt method const encryptedText = ergo.encrypt(secret, longPassword); - - // Assert: Verify the encrypted text format expect(encryptedText).toMatch(/^[0-9a-fA-F]{32}:[0-9a-fA-F]+$/); }); }); @@ -650,10 +620,14 @@ describe('Ergo', () => { expect(result).toEqual('Ergo Accont'); }); }); + describe('decrypt', () => { + const secret = 'mySecret'; + it('Should be defined', () => { + expect(ergo.decrypt).toBeDefined(); + }); it('Should decrypt an encrypted secret correctly', () => { // Arrange: Set up the secret and password, and encrypt the secret - const secret = 'mySecret'; const password = 'myPassword'; const encryptedText = ergo.encrypt(secret, password); // Act: Call the decrypt method @@ -664,7 +638,6 @@ describe('Ergo', () => { it('Should fail to decrypt with wrong password', () => { // Arrange: Set up the secret, correct password, wrong password, and encrypt the secret - const secret = 'mySecret'; const correctPassword = 'correctPassword'; const wrongPassword = 'wrongPassword'; const encryptedText = ergo.encrypt(secret, correctPassword); @@ -676,26 +649,25 @@ describe('Ergo', () => { it('Should handle edge case where password is longer than 32 bytes', () => { // Arrange: Set up the secret and a long password, and encrypt the secret - const secret = 'mySecret'; const longPassword = 'a'.repeat(50); // 50 bytes password const encryptedText = ergo.encrypt(secret, longPassword); - // Act: Call the decrypt method const decryptedText = ergo.decrypt(encryptedText, longPassword); // Assert: Verify that the decrypted text matches the original secret expect(decryptedText).toBe(secret); }); it('Should handle case where password is exactly 32 bytes', () => { - const secret = 'mySecret'; const exact32BytesPassword = 'a'.repeat(32); // 32 bytes password const encryptedText = ergo.encrypt(secret, exact32BytesPassword); const decryptedText = ergo.decrypt(encryptedText, exact32BytesPassword); - // Assert: Verify that the decrypted text matches the original secret expect(decryptedText).toBe(secret); }); }); describe('getAssetBalance', () => { + it('Should be defined', () => { + expect(ergo.getAssetBalance).toBeDefined(); + }); const account: ErgoAccount = { address: 'mockAddress' } as any; it('Should return balance as 0 when there are no unspent boxes', async () => { ergo['_assetMap'] = { @@ -751,6 +723,9 @@ describe('Ergo', () => { }); describe('getBalance', () => { + it('Should be defined', () => { + expect(ergo.getBalance).toBeDefined(); + }); let utxos: any = []; it('Should be defined', () => { expect(ergo.getBalance).toBeDefined(); @@ -799,15 +774,13 @@ describe('Ergo', () => { }); describe('loadAssets', () => { + it('Should be defined', () => { + expect(ergo['loadAssets']).toBeDefined(); + }); it('Should load Assets and update assetMap object', async () => { - // Arrange: Set up the assetMap and mock the getAssetData method ergo['_assetMap'] = {}; patchGetAssetData(); - - // Act: Call the loadAssets method await ergo['loadAssets'](); - - // Assert: Verify that the assetMap is updated correctly expect(ergo['_assetMap']).toEqual({ '$BASS TOKEN': { tokenId: @@ -828,9 +801,11 @@ describe('Ergo', () => { }); describe('getAssetData', () => { + it('Should be defined', () => { + expect(ergo['getAssetData']).toBeDefined(); + }); it('Should return all token with the details', async () => { patchGetTokens(); - // Act & Assert: Validate the returned data structure expect(await ergo['getAssetData']()).toEqual({ name: 'Spectrum Finance Ergo Token List', timestamp: '2024-04-02T08:05:42.697Z', @@ -859,17 +834,17 @@ describe('Ergo', () => { }); describe('loadPools', () => { + it('Should be defined', () => { + expect(ergo['loadPools']).toBeDefined(); + }); it('Should push nothing to ammPools when no PoolData is provided', async () => { - // Arrange: Mock getPoolData to return an empty array jest.spyOn(ergo as any, 'getPoolData').mockResolvedValue([] as any); ergo['ammPools'] = []; - await ergo['loadPools'](); expect(ergo['ammPools']).toEqual([]); }); it('Should push nothing to ammPools when no PoolData is provided', async () => { - // Arrange: Mock getPoolData to return specific pool data jest .spyOn(ergo as any, 'getPoolData') .mockResolvedValueOnce([{ id: '1' }, { id: 2 }] as any); @@ -882,7 +857,6 @@ describe('Ergo', () => { }); it('Should not add duplicate pools to ammPools', async () => { - // Arrange: Mock getPoolData to simulate incremental pool data loading const initialPools: any = [ { id: 1, name: 'Pool 1' }, { id: 2, name: 'Pool 2' }, @@ -1003,16 +977,16 @@ describe('Ergo', () => { }); describe('getPoolData', () => { + it('Should be defined', () => { + expect(ergo['getPoolData']).toBeDefined(); + }); it('Should call makeNativePools and getAll with correct parameters', async () => { const mockGetAll = jest.fn().mockResolvedValue([]); (makeNativePools as any).mockReturnValue({ getAll: mockGetAll }); const limit = 10; const offset = 0; - // Act: Call the method under test await ergo['getPoolData'](limit, offset); - - // Assert: Ensure makeNativePools and getAll were called with correct parameters expect(makeNativePools).toHaveBeenCalledWith(ergo['_explorer']); expect(mockGetAll).toHaveBeenCalledWith({ limit, offset }); }); @@ -1023,39 +997,32 @@ describe('Ergo', () => { (makeNativePools as any).mockReturnValue({ getAll: mockGetAll }); const limit = 10; const offset = 0; - // Act: Call the method under test const result = await ergo['getPoolData'](limit, offset); - // Assert: Verify the method returns expected data expect(result).toEqual(expectedData[0]); }); it('Should handle errors from getAll method', async () => { - // Arrange: Mock getAll method to simulate error const mockGetAll = jest.fn().mockRejectedValue(new Error('Test error')); (makeNativePools as any).mockReturnValue({ getAll: mockGetAll }); - const limit = 10; const offset = 0; - await expect(ergo['getPoolData'](limit, offset)).rejects.toThrow( 'Test error', ); }); }); - describe('storedTokenList', () => { + it('Should be defined', () => { + expect(ergo.storedTokenList).toBeDefined(); + }); it('Should return the stored asset list', () => { - // Arrange: Create mock assets and populate _assetMap const asset1: ErgoAsset = 1 as any; const asset2: ErgoAsset = 2 as any; const assetMap = { key1: asset1, key2: asset2, }; - - // Act: Set _assetMap directly ergo['_assetMap'] = assetMap; - // Assert: Validate the stored asset list returned by storedAssetList expect(ergo.storedTokenList).toEqual(assetMap); }); }); @@ -1085,10 +1052,29 @@ describe('Ergo', () => { symbol: 'ERG', }, ]); + jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([pool]); + jest + .spyOn(NodeService.prototype, 'getBlockInfo') + .mockResolvedValue({ header: { timestamp: 123456 } }); + jest.spyOn(ergo_utils, 'getBaseInputParameters').mockReturnValue({ + baseInput: BigNumber(1), + baseInputAmount: BigNumber(1), + minOutput: { amount: BigInt(1) }, + } as any); }); afterEach(() => { jest.clearAllMocks(); }); + const mockUtxos = [ + { + value: '1000', + assets: [{ amount: '500' }, { amount: '300' }], + }, + { + value: '2000', + assets: [{ amount: '1500' }, { amount: '1300' }], + }, + ]; const poolWithOutputAmount0: any = { id: '1b694b15467c62f0cd4525e368dbdea2329c713aa200b73df4a622e950551b40', lp: { @@ -1255,7 +1241,6 @@ describe('Ergo', () => { jest .spyOn(ergo, 'getPoolByToken') .mockReturnValue([poolWithOutputAmount0]); - patchGetErgoConfig('mainnet'); await expect( ergo.swap( account, @@ -1278,7 +1263,6 @@ describe('Ergo', () => { jest .spyOn(ergo, 'getPoolByToken') .mockReturnValue([poolWithOutputAmount0]); - patchGetErgoConfig('mainnet'); await expect( ergo.swap( account, @@ -1296,14 +1280,6 @@ describe('Ergo', () => { }); it('Should throw new Error if swapVariables are undefined', async () => { - jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([pool]); - jest - .spyOn(BigNumber.prototype, 'multipliedBy') - .mockReturnValue(BigNumber(2)); - patchGetErgoConfig('mainnet'); - jest.spyOn(ergo_utils, 'getBaseInputParameters').mockReturnValue({ - minOutput: { amount: BigInt(1) }, - } as any); await expect( ergo.swap( account, @@ -1340,16 +1316,6 @@ describe('Ergo', () => { }); it('Should throw new Error if output_address is not defined', async () => { - jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([pool]); - jest - .spyOn(BigNumber.prototype, 'multipliedBy') - .mockReturnValue(BigNumber(2)); - patchGetErgoConfig('mainnet'); - jest.spyOn(ergo_utils, 'getBaseInputParameters').mockReturnValue({ - baseInput: BigNumber(1), - baseInputAmount: BigNumber(1), - minOutput: { amount: BigInt(1) }, - } as any); jest.spyOn(ergo_utils, 'getInputs').mockReturnValue({} as any); await expect( ergo.swap( @@ -1365,20 +1331,7 @@ describe('Ergo', () => { }); it('Should throw new Error if any error occurs during submitting the tx', async () => { - jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([pool]); - jest - .spyOn(BigNumber.prototype, 'multipliedBy') - .mockReturnValue(BigNumber(2)); - patchGetErgoConfig('mainnet'); - jest.spyOn(ergo_utils, 'getBaseInputParameters').mockReturnValue({ - baseInput: BigNumber(1), - baseInputAmount: BigNumber(1), - minOutput: { amount: BigInt(1) }, - } as any); jest.spyOn(ergo_utils, 'getInputs').mockReturnValue({} as any); - jest - .spyOn(NodeService.prototype, 'getBlockInfo') - .mockResolvedValue({ header: { timestamp: 123456 } }); const account: any = { prover: { submit: jest.fn().mockResolvedValue({}), @@ -1398,28 +1351,9 @@ describe('Ergo', () => { }); it('Should successfully swap tokens when sell is false', async () => { - const mockUtxos = [ - { - value: '1000', - assets: [{ amount: '500' }, { amount: '300' }], - }, - { - value: '2000', - assets: [{ amount: '1500' }, { amount: '1300' }], - }, - ]; - jest - .spyOn(NodeService.prototype, 'getBlockInfo') - .mockResolvedValue({ header: { timestamp: 123456 } }); - jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([pool]); jest .spyOn(ergo, 'getAddressUnspentBoxes') .mockResolvedValue(mockUtxos as any); - jest.spyOn(ergo_utils, 'getBaseInputParameters').mockReturnValue({ - baseInput: BigNumber(1), - baseInputAmount: BigNumber(1), - minOutput: { amount: BigInt(1) }, - } as any); const account: any = { prover: { @@ -1470,28 +1404,9 @@ describe('Ergo', () => { }); it('Should successfully swap tokens when sell is true', async () => { - const mockUtxos = [ - { - value: '1000', - assets: [{ amount: '500' }, { amount: '300' }], - }, - { - value: '2000', - assets: [{ amount: '1500' }, { amount: '1300' }], - }, - ]; - jest - .spyOn(NodeService.prototype, 'getBlockInfo') - .mockResolvedValue({ header: { timestamp: 123456 } }); - jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([pool]); jest .spyOn(ergo, 'getAddressUnspentBoxes') .mockResolvedValue(mockUtxos as any); - jest.spyOn(ergo_utils, 'getBaseInputParameters').mockReturnValue({ - baseInput: BigNumber(1), - baseInputAmount: BigNumber(1), - minOutput: { amount: BigInt(1) }, - } as any); const account: any = { prover: { @@ -1567,6 +1482,10 @@ describe('Ergo', () => { symbol: 'ERG', }, ]); + jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([pool]); + jest + .spyOn(ergo_utils, 'getBaseInputParameters') + .mockReturnValue({ minOutput: { amount: BigInt(1) } } as any); }); afterEach(() => { jest.clearAllMocks(); @@ -1639,7 +1558,6 @@ describe('Ergo', () => { }); it('Should throw new Error if baseToken is available but quoteToken is not available on storedAssetList', async () => { - jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([pool]); // ERG is available but SigUSD is not jest.spyOn(ergo, 'storedAssetList', 'get').mockReturnValue([ { @@ -1656,7 +1574,6 @@ describe('Ergo', () => { }); it('Should throw new Error if quoteToken is available but baseToken is not available on storedAssetList', async () => { - jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([pool]); // SigUSD is available but ERG is not jest.spyOn(ergo, 'storedAssetList', 'get').mockReturnValue([ { @@ -1673,11 +1590,6 @@ describe('Ergo', () => { }); it('Should ignore the rest of loop scope and return the base result if minOutput === BigInt(0)', async () => { - jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([pool]); - jest - .spyOn(BigNumber.prototype, 'multipliedBy') - .mockReturnValue(BigNumber(2)); - patchGetErgoConfig('mainnet'); jest.spyOn(ergo_utils, 'getBaseInputParameters').mockReturnValue({ minOutput: { amount: BigInt(0) }, } as any); @@ -1699,11 +1611,6 @@ describe('Ergo', () => { }); }); it('Should estimate successfully when sell is false', async () => { - patchGetErgoConfig('mainnet'); - jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([pool]); - jest - .spyOn(ergo_utils, 'getBaseInputParameters') - .mockReturnValue({ minOutput: { amount: BigInt(1) } } as any); const result = await ergo.estimate(baseToken, quoteToken, value); expect(result).toMatchObject({ base: baseToken, @@ -1738,11 +1645,6 @@ describe('Ergo', () => { }); }); it('Should estimate successfully when sell is true', async () => { - patchGetErgoConfig('mainnet'); - jest - .spyOn(ergo_utils, 'getBaseInputParameters') - .mockReturnValue({ minOutput: { amount: BigInt(1) } } as any); - jest.spyOn(ergo, 'getPoolByToken').mockReturnValue([pool]); // to set sell 'true' const baseToken: string = 'SigUSD'; const quoteToken: string = 'ERG'; @@ -1785,6 +1687,9 @@ describe('Ergo', () => { }); describe('getPool', () => { + it('Should be defined', () => { + expect(ergo.getPool).toBeDefined(); + }); it('Should find the pool with related id and return it', () => { // set a mock pool to check the id const poolToCheck: any = { @@ -1833,6 +1738,9 @@ describe('Ergo', () => { }); const baseToken = 'ERG'; const quoteToken = 'SigUSD'; + it('Should be defined', () => { + expect(ergo.getPoolByToken).toBeDefined(); + }); it('Should throw new Error if baseToken is available but quoteToken is not available on storedAssetList', () => { // ERG is available but SigUSD is not jest.spyOn(ergo, 'storedAssetList', 'get').mockReturnValue([ From c7a7ccdd41d1b13cd08a41e9228de166227a0d2a Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Sat, 27 Jul 2024 19:48:10 +0330 Subject: [PATCH 126/132] final bug fixed --- src/chains/ergo/ergo.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 1b772d0e94..760ce84809 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -418,7 +418,7 @@ export class Ergo { tokenId: result.address, decimals: result.decimals, name: result.name, - symbol: result.ticker, + symbol: result.ticker.toUpperCase(), }; } From cc9cfeeb712ae661a8e38a704c897eaca4e3eba9 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Mon, 29 Jul 2024 10:29:01 +0330 Subject: [PATCH 127/132] update [unit-test]: update unit tests for loadAssets method --- test-bronze/chains/ergo/ergo.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test-bronze/chains/ergo/ergo.test.ts b/test-bronze/chains/ergo/ergo.test.ts index 10abd86942..7c9ad1ea30 100644 --- a/test-bronze/chains/ergo/ergo.test.ts +++ b/test-bronze/chains/ergo/ergo.test.ts @@ -787,7 +787,7 @@ describe('Ergo', () => { 'ba553573f83c61be880d79db0f4068177fa75ab7c250ce3543f7e7aeb471a9d2', decimals: 7, name: '$Bass Token', - symbol: '$bass', + symbol: '$bass'.toUpperCase(), }, ERGO: { tokenId: @@ -1797,7 +1797,7 @@ describe('Ergo', () => { }); describe('getTx', () => { - it('Shoyuld be defined', () => { + it('Should be defined', () => { expect(ergo.getTx).toBeDefined(); }); From 57ea57ebc345319c9ee1ed09e0c462d45c571256 Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Tue, 30 Jul 2024 20:48:39 +0330 Subject: [PATCH 128/132] ergo class refactored --- src/chains/ergo/ergo.ts | 847 +++++++++++++++++++++++----------------- 1 file changed, 483 insertions(+), 364 deletions(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 760ce84809..e2aafa6b6a 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -34,8 +34,8 @@ import { AssetAmount, publicKeyFromAddress, TransactionContext, - RustModule, -} from '@patternglobal/ergo-sdk'; + RustModule, BoxSelection +} from "@patternglobal/ergo-sdk"; import { NativeExFeeType } from '@patternglobal/ergo-dex-sdk/build/main/types'; import { NetworkContext } from '@patternglobal/ergo-sdk/build/main/entities/networkContext'; import { ErgoNetwork } from './types/ergo.type'; @@ -47,12 +47,14 @@ import { walletPath } from '../../services/base'; import fse from 'fs-extra'; import { ConfigManagerCertPassphrase } from '../../services/config-manager-cert-passphrase'; +/** + * Extended AmmPool class with additional properties and methods + */ class Pool extends AmmPool { private _name: string; constructor(public pool: AmmPool) { super(pool.id, pool.lp, pool.x, pool.y, pool.poolFeeNum); - this._name = `${this.pool.x.asset.name}/${this.pool.y.asset.name}`; } @@ -72,9 +74,12 @@ class Pool extends AmmPool { } } +/** + * Main Ergo class for interacting with the Ergo blockchain + */ export class Ergo { - private _assetMap: Record = {}; private static _instances: LRUCache; + private _assetMap: Record = {}; private _chain: string = 'ergo'; private _network: ErgoNetwork; private _networkPrefix: NetworkPrefix; @@ -88,6 +93,10 @@ export class Ergo { private poolLimit: number; private ammPools: Array = []; + /** + * Creates an instance of Ergo. + * @param {ErgoNetwork} network - The Ergo network to connect to ('mainnet' or 'testnet') + */ constructor(network: ErgoNetwork) { if (network !== 'mainnet' && network !== 'testnet') { throw new Error('network should be `mainnet` or `testnet`'); @@ -112,31 +121,49 @@ export class Ergo { this.poolLimit = config.network.poolLimit; } + /** + * Gets the node service + * @returns {NodeService} + */ public get node(): NodeService { return this._node; } + /** + * Gets the current network + * @returns {ErgoNetwork} + */ public get network(): ErgoNetwork { return this._network; } + /** + * Gets the list of stored assets + * @returns {Array} + */ public get storedAssetList(): Array { return Object.values(this._assetMap); } + /** + * Checks if the Ergo instance is ready + * @returns {boolean} + */ public ready(): boolean { return this._ready; } + /** + * Gets the current network height + * @returns {Promise} + */ public async getNetworkHeight() { return await this._node.getNetworkHeight(); } /** - * This function initializes the Ergo class' instance - * @returns - * @function - * @async + * Initializes the Ergo instance + * @returns {Promise} */ public async init(): Promise { await RustModule.load(true); @@ -146,15 +173,18 @@ export class Ergo { return; } + /** + * Closes the Ergo instance (placeholder for future implementation) + * @returns {Promise} + */ async close() { return; } /** - * This static function returns the exists or create new Ergo class' instance based on the network - * @param {string} network - mainnet or testnet - * @returns Ergo - * @function + * Gets or creates an Ergo instance + * @param {ErgoNetwork} network - The network to connect to + * @returns {Ergo} * @static */ public static getInstance(network: ErgoNetwork): Ergo { @@ -184,9 +214,8 @@ export class Ergo { } /** - * This static function returns the connected instances - * @returns ErgoConnectedInstance - * @function + * Gets all connected Ergo instances + * @returns {ErgoConnectedInstance} * @static */ public static getConnectedInstances(): ErgoConnectedInstance { @@ -206,10 +235,8 @@ export class Ergo { } /** - * This function returns the current network height(Block number) - * @returns number - * @function - * @async + * Gets the current block number + * @returns {Promise} */ async getCurrentBlockNumber(): Promise { const status = await this._node.getNetworkHeight(); @@ -217,10 +244,9 @@ export class Ergo { } /** - * This function returns the unspent boxes based on the address from node - * @returns ErgoBox[] - * @function - * @async + * Gets unspent boxes for a given address + * @param {string} address - The address to get unspent boxes for + * @returns {Promise} */ async getAddressUnspentBoxes(address: string) { let utxos: Array = []; @@ -245,10 +271,9 @@ export class Ergo { } /** - * Retrieves Ergo Account from secret key - * @param {string} secret - Secret key - * @returns ErgoAccount - * @function + * Gets an Ergo account from a secret key + * @param {string} secret - The secret key + * @returns {ErgoAccount} */ public getAccountFromSecretKey(secret: string): ErgoAccount { const sks = new SecretKeys(); @@ -267,10 +292,9 @@ export class Ergo { } /** - * Retrieves Ergo Account from mnemonic - * @param {string} mnemonic - Mnemonic - * @returns ErgoAccount - * @function + * Gets an Ergo account from a mnemonic phrase + * @param {string} mnemonic - The mnemonic phrase + * @returns {ErgoAccount} */ public getAccountFromMnemonic(mnemonic: string): ErgoAccount { const sks = new SecretKeys(); @@ -293,11 +317,10 @@ export class Ergo { } /** - * Encrypt secret via password - * @param {string} secret - Secret key - * @param {string} password - password - * @returns string - * @function + * Encrypts a secret using a password + * @param {string} secret - The secret to encrypt + * @param {string} password - The password to use for encryption + * @returns {string} The encrypted secret */ public encrypt(secret: string, password: string): string { const iv = randomBytes(16); @@ -311,6 +334,11 @@ export class Ergo { return `${iv.toString('hex')}:${encrypted.toString('hex')}`; } + /** + * Gets an Ergo account from an address + * @param {string} address - The address to get the account for + * @returns {Promise} + */ public async getAccountFromAddress(address: string): Promise { const path = `${walletPath}/${this._chain}`; const encryptedMnemonic: string = await fse.readFile( @@ -326,11 +354,10 @@ export class Ergo { } /** - * Decrypt encrypted secret key via password - * @param {string} encryptedSecret - Secret key - * @param {string} password - password - * @returns string - * @function + * Decrypts an encrypted secret using a password + * @param {string} encryptedSecret - The encrypted secret + * @param {string} password - The password to use for decryption + * @returns {string} The decrypted secret */ public decrypt(encryptedSecret: string, password: string): string { const [iv, encryptedKey] = encryptedSecret.split(':'); @@ -352,12 +379,10 @@ export class Ergo { } /** - * Gets asset balance from unspent boxes - * @param {ErgoAccount} account - * @param {string} assetName - * @returns string - * @function - * @async + * Gets the balance of a specific asset for an account + * @param {ErgoAccount} account - The account to get the balance for + * @param {string} assetName - The name of the asset + * @returns {Promise} The balance of the asset */ public async getAssetBalance( account: ErgoAccount, @@ -390,6 +415,11 @@ export class Ergo { return balance.toString(); } + /** + * Gets the balance of ERG and assets from unspent boxes + * @param {ErgoBox[]} utxos - The unspent transaction outputs + * @returns {{ balance: BigNumber, assets: Record }} + */ public getBalance(utxos: ErgoBox[]) { const balance = utxos.reduce( (total, box) => total.plus(BigNumber(box.value)), @@ -410,6 +440,10 @@ export class Ergo { return { balance, assets }; } + /** + * Loads assets from the DEX + * @private + */ private async loadAssets() { const assetData = await this.getAssetData(); @@ -431,10 +465,19 @@ export class Ergo { }; } + /** + * Retrieves asset data from the DEX + * @private + * @returns {Promise} Asset data + */ private async getAssetData() { return await this._dex.getTokens(); } + /** + * Loads AMM pools + * @private + */ private async loadPools(): Promise { let offset = 0; let pools: Array = await this.getPoolData(this.poolLimit, offset); @@ -451,6 +494,10 @@ export class Ergo { } } + /** + * Loads a specific pool by ID + * @param {string} poolId - The ID of the pool to load + */ public async loadPool(poolId: string): Promise { await RustModule.load(true); const pool = await this.getPool(poolId); @@ -463,6 +510,13 @@ export class Ergo { } } + /** + * Retrieves pool data + * @private + * @param {number} limit - The number of pools to retrieve + * @param {number} offset - The offset for pagination + * @returns {Promise} Pool data + */ private async getPoolData(limit: number, offset: number): Promise { const [AmmPool] = await makeNativePools(this._explorer).getAll({ limit, @@ -473,13 +527,25 @@ export class Ergo { } /** - * Returns a map of asset name and Ergo Asset - * @returns assetMap + * Gets the stored token list + * @returns {Record} Stored token list */ public get storedTokenList() { return this._assetMap; } + + /** + * Performs a swap operation + * @param {ErgoAccount} account - The account performing the swap + * @param {string} baseToken - The base token symbol + * @param {string} quoteToken - The quote token symbol + * @param {BigNumber} value - The amount to swap + * @param {string} output_address - The address to receive the output + * @param {string} return_address - The address for change return + * @param {number} [slippage] - The slippage tolerance + * @returns {Promise} The trade response + */ public async swap( account: ErgoAccount, baseToken: string, @@ -489,152 +555,211 @@ export class Ergo { return_address: string, slippage?: number, ): Promise { - let sell: boolean; - let amount: BigNumber; + const { realBaseToken, realQuoteToken, pool } = await this.findBestPool(baseToken, quoteToken, value, slippage); + const { sell, amount, from, to, minOutput } = this.calculateSwapParameters(pool, realBaseToken, value, slippage); + + const config = getErgoConfig(this.network); + const { baseInput, baseInputAmount } = getBaseInputParameters(pool, { inputAmount: from, slippage: slippage || config.network.defaultSlippage }); + + const networkContext = await this._explorer.getNetworkContext(); + const txAssembler = new DefaultTxAssembler(this.network === 'mainnet'); + const poolActions = this.getPoolActions(output_address, account, txAssembler); + + const utxos = await this.getAddressUnspentBoxes(account.address); + const swapVariables = this.calculateSwapVariables(config, minOutput); + const inputs = this.prepareInputs(utxos, from, baseInputAmount, config, swapVariables[1]); + + const swapParams = this.createSwapParams(pool, output_address, baseInput, to, swapVariables, config); + const txContext = this.createTxContext(inputs, networkContext, return_address, config); + + const actions = poolActions(pool); + const timestamp = await this.getBlockTimestamp(networkContext); + const tx = await actions.swap(swapParams, txContext); + + await this.submitTransaction(account, tx); + + return this.createTradeResponse(realBaseToken, realQuoteToken, amount, from, minOutput, pool, sell, config, timestamp, tx); + } + + /** + * Estimates the price for a swap + * @param {string} baseToken - The base token symbol + * @param {string} quoteToken - The quote token symbol + * @param {BigNumber} value - The amount to swap + * @param {number} [slippage] - The slippage tolerance + * @returns {Promise} The price estimate + */ + public async estimate( + baseToken: string, + quoteToken: string, + value: BigNumber, + slippage?: number, + ): Promise { + const { realBaseToken, realQuoteToken, pool } = await this.findBestPool(baseToken, quoteToken, value, slippage); + const { sell, amount, from, minOutput } = this.calculateSwapParameters(pool, realBaseToken, value, slippage); + + const config = getErgoConfig(this.network); + const expectedAmount = this.calculateExpectedAmount(minOutput, pool, sell); + + return this.createPriceResponse(realBaseToken, realQuoteToken, amount, from, minOutput, pool, sell, config, expectedAmount); + } + + /** + * Finds the best pool for a given token pair and amount + * @param {string} baseToken - The base token symbol + * @param {string} quoteToken - The quote token symbol + * @param {BigNumber} value - The amount to swap + * @param {number} [slippage] - The slippage tolerance + * @returns {Promise<{ realBaseToken: ErgoAsset, realQuoteToken: ErgoAsset, pool: Pool }>} + */ + private async findBestPool(baseToken: string, quoteToken: string, value: BigNumber, slippage?: number): Promise<{ realBaseToken: ErgoAsset, realQuoteToken: ErgoAsset, pool: Pool }> { const pools = this.getPoolByToken(baseToken, quoteToken); - const realBaseToken = this.storedAssetList.find( - (asset) => asset.symbol === baseToken, - ); - const realQuoteToken = this.storedAssetList.find( - (asset) => asset.symbol === quoteToken, - ); - if (!realBaseToken || !realQuoteToken) - throw new Error(`${baseToken} or ${quoteToken} not found!`); - let result = { - pool: {}, - expectedOut: BigNumber(0), - }; + if (!pools.length) throw new Error(`Pool not found for ${baseToken} and ${quoteToken}`); + + const realBaseToken = this.findToken(baseToken); + const realQuoteToken = this.findToken(quoteToken); + + let bestPool: Pool | null = null; + let bestExpectedOut = BigNumber(0); + for (const pool of pools) { - if (!pool) - throw new Error(`pool not found base on ${baseToken}, ${quoteToken}`); - if (pool.x.asset.id === realBaseToken.tokenId) { - sell = false; - amount = value.multipliedBy( - BigNumber(10).pow(pool.y.asset.decimals as number), - ); - } else { - sell = true; - amount = value.multipliedBy( - BigNumber(10).pow(pool.x.asset.decimals as number), - ); - } - const config = getErgoConfig(this.network); - const max_to = { - asset: { - id: sell ? pool.x.asset.id : pool.y.asset.id, - }, - amount: BigInt(amount.toString()), - }; - const from = { - asset: { - id: sell ? pool.y.asset.id : pool.x.asset.id, - decimals: sell ? pool.y.asset.decimals : pool.x.asset.decimals, - }, - amount: pool.outputAmount( - max_to as any, - slippage || config.network.defaultSlippage, - ).amount, - }; - if (from.amount === BigInt(0)) - throw new Error( - `${amount} asset from ${max_to.asset.id} is not enough!`, - ); - const { minOutput } = getBaseInputParameters(pool, { - inputAmount: from, - slippage: slippage || config.network.defaultSlippage, - }); - if (minOutput.amount === BigInt(0)) continue; - const expectedOut = - sell === false - ? BigNumber(minOutput.amount.toString()).div( - BigNumber(10).pow(pool.y.asset.decimals as number), - ) - : BigNumber(minOutput.amount.toString()).div( - BigNumber(10).pow(pool.x.asset.decimals as number), - ); - if (expectedOut > BigNumber(result.expectedOut)) { - result = { - pool, - expectedOut, - }; + const { minOutput } = this.calculateSwapParameters(pool, realBaseToken, value, slippage); + const expectedOut = this.calculateExpectedAmount(minOutput, pool, pool.x.asset.id !== realBaseToken.tokenId); + + if (expectedOut.gt(bestExpectedOut)) { + bestPool = pool; + bestExpectedOut = expectedOut; } } - const pool = pools.find((pool) => pool.id === result.pool.id); - if (!pool) - throw new Error(`pool not found base on ${baseToken}, ${quoteToken}`); - if (pool.x.asset.id === realBaseToken.tokenId) { - sell = false; - amount = value.multipliedBy( - BigNumber(10).pow(pool.y.asset.decimals as number), - ); - } else { - sell = true; - amount = value.multipliedBy( - BigNumber(10).pow(pool.x.asset.decimals as number), - ); - } + + if (!bestPool) throw new Error(`No suitable pool found for ${baseToken} and ${quoteToken}`); + + return { realBaseToken, realQuoteToken, pool: bestPool }; + } + + /** + * Finds a token by its symbol + * @param {string} symbol - The token symbol + * @returns {ErgoAsset} + */ + private findToken(symbol: string): ErgoAsset { + const token = this.storedAssetList.find(asset => asset.symbol === symbol); + if (!token) throw new Error(`Token ${symbol} not found`); + return token; + } + + /** + * Calculates swap parameters for a given pool and amount + * @param {Pool} pool - The pool to use for the swap + * @param {ErgoAsset} baseToken - The base token + * @param {BigNumber} value - The amount to swap + * @param {number} [slippage] - The slippage tolerance + * @returns {{ sell: boolean, amount: BigNumber, from: any, to: any, minOutput: any }} + */ + private calculateSwapParameters(pool: Pool, baseToken: ErgoAsset, value: BigNumber, slippage?: number) { const config = getErgoConfig(this.network); - const to = { - asset: { - id: sell ? pool.x.asset.id : pool.y.asset.id, - decimals: sell ? pool.x.asset.decimals : pool.y.asset.decimals, - }, - amount: BigInt(amount.toString()), - }; + const sell = pool.x.asset.id !== baseToken.tokenId; + const amount = this.calculateAmount(pool, value, sell); + const max_to = { - asset: { - id: sell ? pool.x.asset.id : pool.y.asset.id, - }, + asset: { id: sell ? pool.x.asset.id : pool.y.asset.id }, amount: BigInt(amount.toString()), }; + const from = { asset: { id: sell ? pool.y.asset.id : pool.x.asset.id, decimals: sell ? pool.y.asset.decimals : pool.x.asset.decimals, }, - amount: pool.outputAmount( - max_to as any, - slippage || config.network.defaultSlippage, - ).amount, + amount: pool.outputAmount(max_to as any, slippage || config.network.defaultSlippage).amount, }; - if (from.amount === BigInt(0)) - throw new Error(`${amount} asset from ${max_to.asset.id} is not enough!`); - const { baseInput, baseInputAmount, minOutput } = getBaseInputParameters( - pool, - { - inputAmount: from, - slippage: slippage || config.network.defaultSlippage, + + const to = { + asset: { + id: sell ? pool.x.asset.id : pool.y.asset.id, + decimals: sell ? pool.x.asset.decimals : pool.y.asset.decimals, }, - ); - const networkContext = await this._explorer.getNetworkContext(); - const mainnetTxAssembler = new DefaultTxAssembler( - this.network === 'mainnet', - ); - const poolActions = makeWrappedNativePoolActionsSelector( - output_address, - account.prover, - mainnetTxAssembler, - ); - const utxos = await this.getAddressUnspentBoxes(account.address); - const swapVariables: [number, SwapExtremums] | undefined = swapVars( + amount: BigInt(amount.toString()), + }; + + const { minOutput } = getBaseInputParameters(pool, { + inputAmount: from, + slippage: slippage || config.network.defaultSlippage, + }); + + return { sell, amount, from, to, minOutput }; + } + + /** + * Calculates the amount with proper decimals + * @param {Pool} pool - The pool to use for the calculation + * @param {BigNumber} value - The input value + * @param {boolean} sell - Whether it's a sell operation + * @returns {BigNumber} + */ + private calculateAmount(pool: Pool, value: BigNumber, sell: boolean): BigNumber { + const decimals = sell ? pool.x.asset.decimals : pool.y.asset.decimals; + return value.multipliedBy(BigNumber(10).pow(decimals as number)); + } + + /** + * Calculates the expected amount from the minimum output + * @param {any} minOutput - The minimum output + * @param {Pool} pool - The pool used for the swap + * @param {boolean} sell - Whether it's a sell operation + * @returns {BigNumber} + */ + private calculateExpectedAmount(minOutput: any, pool: Pool, sell: boolean): BigNumber { + const decimals = sell ? pool.x.asset.decimals : pool.y.asset.decimals; + return BigNumber(minOutput.amount.toString()).div(BigNumber(10).pow(decimals as number)); + } + + /** + * Gets pool actions for the swap + * @param {string} output_address - The output address + * @param {ErgoAccount} account - The account performing the swap + * @param {DefaultTxAssembler} txAssembler - The transaction assembler + * @returns {Function} + */ + private getPoolActions(output_address: string, account: ErgoAccount, txAssembler: DefaultTxAssembler) { + return makeWrappedNativePoolActionsSelector(output_address, account.prover, txAssembler); + } + + /** + * Calculates swap variables + * @param {any} config - The Ergo configuration + * @param {any} minOutput - The minimum output + * @returns {[number, SwapExtremums]} + */ + private calculateSwapVariables(config: any, minOutput: any): [number, SwapExtremums] { + const swapVariables = swapVars( BigInt(config.network.defaultMinerFee.multipliedBy(3).toString()), config.network.minNitro, minOutput, ); - if (!swapVariables) throw new Error('error in swap vars!'); - const [exFeePerToken, extremum] = swapVariables; + if (!swapVariables) throw new Error('Error in swap vars!'); + return swapVariables; + } - const inputs = getInputs( - utxos.map((utxo) => { - const temp = Object(utxo); - temp.value = BigNumber(temp.value); - temp.assets = temp.assets.map((asset: any) => { - const temp2 = Object(asset); - temp2.amount = BigNumber(temp2.amount); - return temp2; - }); - return temp; - }), + /** + * Prepares inputs for the swap + * @param {any[]} utxos - The unspent transaction outputs + * @param {any} from - The from asset + * @param {BigInt} baseInputAmount - The base input amount + * @param {any} config - The Ergo configuration + * @param {SwapExtremums} extremum - The swap extremums + * @returns {any[]} + */ + private prepareInputs(utxos: any[], from: any, baseInputAmount: BigNumber, config: any, extremum: SwapExtremums): BoxSelection { + return getInputs( + utxos.map((utxo) => ({ + ...utxo, + value: BigNumber(utxo.value), + assets: utxo.assets.map((asset: any) => ({ + ...asset, + amount: BigNumber(asset.amount), + })), + })), [new AssetAmount(from.asset, BigInt(baseInputAmount.toString()))], { minerFee: BigInt(config.network.defaultMinerFee.toString()), @@ -642,9 +767,24 @@ export class Ergo { exFee: BigInt(extremum.maxExFee.toString()), }, ); + } + + /** + * Creates swap parameters + * @param {Pool} pool - The pool to use for the swap + * @param {string} output_address - The output address + * @param {any} baseInput - The base input + * @param {any} to - The to asset + * @param {[number, SwapExtremums]} swapVariables - The swap variables + * @param {any} config - The Ergo configuration + * @returns {SwapParams} + */ + private createSwapParams(pool: Pool, output_address: string, baseInput: any, to: any, swapVariables: [number, SwapExtremums], config: any): SwapParams { + const [exFeePerToken, extremum] = swapVariables; const pk = publicKeyFromAddress(output_address); if (!pk) throw new Error(`output_address is not defined.`); - const swapParams: SwapParams = { + + return { poolId: pool.id, pk, baseInput, @@ -655,222 +795,196 @@ export class Ergo { poolFeeNum: pool.poolFeeNum, maxExFee: extremum.maxExFee, }; - const txContext: TransactionContext = getTxContext( + } + + /** + * Creates transaction context + * @param {any[]} inputs - The transaction inputs + * @param {NetworkContext} networkContext - The network context + * @param {string} return_address - The return address + * @param {any} config - The Ergo configuration + * @returns {TransactionContext} + */ + private createTxContext(inputs: BoxSelection, networkContext: NetworkContext, return_address: string, config: any): TransactionContext { + return getTxContext( inputs, - networkContext as NetworkContext, + networkContext, return_address, BigInt(config.network.defaultMinerFee.toString()), ); - const actions = poolActions(pool); - const timestamp = ( - await this._node.getBlockInfo(networkContext.height.toString()) - ).header.timestamp; - const tx = await actions.swap(swapParams, txContext); + } + + /** + * Gets the block timestamp + * @param {NetworkContext} networkContext - The network context + * @returns {Promise} + */ + private async getBlockTimestamp(networkContext: NetworkContext): Promise { + const blockInfo = await this._node.getBlockInfo(networkContext.height.toString()); + return blockInfo.header.timestamp; + } + + /** + * Submits a transaction + * @param {ErgoAccount} account - The account submitting the transaction + * @param {any} tx - The transaction to submit + */ + private async submitTransaction(account: ErgoAccount, tx: any): Promise { const submit_tx = await account.prover.submit(tx); - if (!submit_tx.id) throw new Error(`error during submit tx!`); + if (!submit_tx.id) throw new Error(`Error during submit tx!`); + } + + /** + * Creates a trade response + * @param {ErgoAsset} realBaseToken - The base token + * @param {ErgoAsset} realQuoteToken - The quote token + * @param {BigNumber} amount - The amount + * @param {any} from - The from asset + * @param {any} minOutput - The minimum output + * @param {Pool} pool - The pool used for the swap + * @param {boolean} sell - Whether it's a sell operation + * @param {any} config - The Ergo configuration + * @param {number} timestamp - The transaction timestamp + * @param {any} tx - The transaction + * @returns {TradeResponse} + */ + private createTradeResponse( + realBaseToken: ErgoAsset, + realQuoteToken: ErgoAsset, + amount: BigNumber, + from: any, + minOutput: any, + pool: Pool, + sell: boolean, + config: any, + timestamp: number, + tx: any + ): TradeResponse { + const xDecimals = pool.x.asset.decimals as number; + const yDecimals = pool.y.asset.decimals as number; + return { network: this.network, timestamp, latency: 0, base: realBaseToken.symbol, quote: realQuoteToken.symbol, - amount: - sell === false - ? amount - .div(BigNumber(10).pow(pool.y.asset.decimals as number)) - .toString() - : amount - .div(BigNumber(10).pow(pool.x.asset.decimals as number)) - .toString(), - rawAmount: - sell === false - ? amount - .div(BigNumber(10).pow(pool.y.asset.decimals as number)) - .toString() - : amount - .div(BigNumber(10).pow(pool.x.asset.decimals as number)) - .toString(), - expectedOut: - sell === false - ? BigNumber(minOutput.amount.toString()) - .div(BigNumber(10).pow(pool.y.asset.decimals as number)) - .toString() - : BigNumber(minOutput.amount.toString()) - .div(BigNumber(10).pow(pool.x.asset.decimals as number)) - .toString(), - price: - sell === false - ? BigNumber(minOutput.amount.toString()) - .div(BigNumber(10).pow(pool.y.asset.decimals as number)) - .div( - BigNumber(from.amount.toString()).div( - BigNumber(10).pow(pool.x.asset.decimals as number), - ), - ) - .toString() - : BigNumber(1) - .div( - BigNumber(minOutput.amount.toString()) - .div(BigNumber(10).pow(pool.x.asset.decimals as number)) - .div( - BigNumber(from.amount.toString()).div( - BigNumber(10).pow(pool.y.asset.decimals as number), - ), - ), - ) - .toString(), - gasPrice: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toNumber(), - gasPriceToken: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toString(), - gasLimit: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toNumber(), - gasCost: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toString(), + amount: this.formatAmount(amount, sell ? xDecimals : yDecimals), + rawAmount: this.formatAmount(amount, sell ? xDecimals : yDecimals), + expectedOut: this.formatAmount(BigNumber(minOutput.amount.toString()), sell ? xDecimals : yDecimals), + price: this.calculatePrice(minOutput, from, sell, xDecimals, yDecimals), + gasPrice: this.calculateGas(config.network.minTxFee), + gasPriceToken: 'ERG', + gasLimit: this.calculateGas(config.network.minTxFee), + gasCost: this.calculateGas(config.network.minTxFee).toString(), txHash: tx.id, }; } - public async estimate( - baseToken: string, - quoteToken: string, - value: BigNumber, - slippage?: number, - ): Promise { - let sell: boolean; - let amount: BigNumber; - const config = getErgoConfig(this.network); - const pools = this.getPoolByToken(baseToken, quoteToken); - if (!pools.length) - throw new Error(`pool not found base on ${baseToken}, ${quoteToken}`); - const realBaseToken = this.storedAssetList.find( - (asset) => asset.symbol === baseToken, - ); - const realQuoteToken = this.storedAssetList.find( - (asset) => asset.symbol === quoteToken, - ); - if (!realBaseToken || !realQuoteToken) - throw new Error(`${baseToken} or ${quoteToken} not found!`); - let result = { + /** + * Creates a price response + * @param {ErgoAsset} realBaseToken - The base token + * @param {ErgoAsset} realQuoteToken - The quote token + * @param {BigNumber} amount - The amount + * @param {any} from - The from asset + * @param {any} minOutput - The minimum output + * @param {Pool} pool - The pool used for the swap + * @param {boolean} sell - Whether it's a sell operation + * @param {any} config - The Ergo configuration + * @param {BigNumber} expectedAmount - The expected amount + * @returns {PriceResponse} + */ + private createPriceResponse( + realBaseToken: ErgoAsset, + realQuoteToken: ErgoAsset, + amount: BigNumber, + from: any, + minOutput: any, + pool: Pool, + sell: boolean, + config: any, + expectedAmount: BigNumber + ): PriceResponse { + const xDecimals = pool.x.asset.decimals as number; + const yDecimals = pool.y.asset.decimals as number; + + return { base: realBaseToken.symbol, quote: realQuoteToken.symbol, - amount: '0', - rawAmount: '0', - expectedAmount: '0', - price: '0', + amount: this.formatAmount(amount, sell ? xDecimals : yDecimals), + rawAmount: this.formatAmount(amount, sell ? xDecimals : yDecimals), + expectedAmount: expectedAmount.toString(), + price: this.calculatePrice(minOutput, from, sell, xDecimals, yDecimals), network: this.network, timestamp: Date.now(), latency: 0, - gasPrice: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toNumber(), - gasPriceToken: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toString(), - gasLimit: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toNumber(), - gasCost: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toString(), + gasPrice: this.calculateGas(config.network.minTxFee), + gasPriceToken: 'ERG', + gasLimit: this.calculateGas(config.network.minTxFee), + gasCost: this.calculateGas(config.network.minTxFee).toString(), }; - for (const pool of pools) { - if (pool.x.asset.id === realBaseToken.tokenId) { - sell = false; - amount = value.multipliedBy( - BigNumber(10).pow(pool.y.asset.decimals as number), - ); - } else { - sell = true; - amount = value.multipliedBy( - BigNumber(10).pow(pool.x.asset.decimals as number), - ); - } - const config = getErgoConfig(this.network); - const max_to = { - asset: { - id: sell ? pool.x.asset.id : pool.y.asset.id, - decimals: sell ? pool.x.asset.decimals : pool.y.asset.decimals, - }, - amount: BigInt(amount.toString()), - }; - const from = { - asset: { - id: sell ? pool.y.asset.id : pool.x.asset.id, - decimals: sell ? pool.y.asset.decimals : pool.x.asset.decimals, - }, - amount: pool.outputAmount( - max_to as any, - slippage || config.network.defaultSlippage, - ).amount, - }; - const { minOutput } = getBaseInputParameters(pool, { - inputAmount: from, - slippage: slippage || config.network.defaultSlippage, - }); - if (minOutput.amount === BigInt(0)) continue; - const expectedAmount = - sell === false - ? BigNumber(minOutput.amount.toString()).div( - BigNumber(10).pow(pool.y.asset.decimals as number), - ) - : BigNumber(minOutput.amount.toString()).div( - BigNumber(10).pow(pool.x.asset.decimals as number), - ); - if (expectedAmount > BigNumber(result.expectedAmount)) { - result = { - base: realBaseToken.symbol, - quote: realQuoteToken.symbol, - amount: - sell === false - ? amount - .div(BigNumber(10).pow(pool.y.asset.decimals as number)) - .toString() - : amount - .div(BigNumber(10).pow(pool.x.asset.decimals as number)) - .toString(), - rawAmount: - sell === false - ? amount - .div(BigNumber(10).pow(pool.y.asset.decimals as number)) - .toString() - : amount - .div(BigNumber(10).pow(pool.x.asset.decimals as number)) - .toString(), - expectedAmount: - sell === false - ? BigNumber(minOutput.amount.toString()) - .div(BigNumber(10).pow(pool.y.asset.decimals as number)) - .toString() - : BigNumber(minOutput.amount.toString()) - .div(BigNumber(10).pow(pool.x.asset.decimals as number)) - .toString(), - price: - sell === false - ? (BigNumber(minOutput.amount.toString()) - .div(BigNumber(10).pow(pool.y.asset.decimals as number))) - .div( - BigNumber(from.amount.toString()).div( - BigNumber(10).pow(pool.x.asset.decimals as number), - ), - ) - .toString() - : BigNumber(1) - .div( - (BigNumber(minOutput.amount.toString()) - .div(BigNumber(10).pow(pool.x.asset.decimals as number))) - .div( - BigNumber(from.amount.toString()).div( - BigNumber(10).pow(pool.y.asset.decimals as number), - ), - ), - ) - .toString(), - network: this.network, - timestamp: Date.now(), - latency: 0, - gasPrice: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toNumber(), - gasPriceToken: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toString(), - gasLimit: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toNumber(), - gasCost: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toString(), - }; - } + } + + /** + * Formats an amount with proper decimals + * @param {BigNumber} amount - The amount to format + * @param {number} decimals - The number of decimals + * @returns {string} + */ + private formatAmount(amount: BigNumber, decimals: number): string { + return amount.div(BigNumber(10).pow(decimals)).toString(); + } + + /** + * Calculates the price + * @param {any} minOutput - The minimum output + * @param {any} from - The from asset + * @param {boolean} sell - Whether it's a sell operation + * @param {number} xDecimals - The decimals of the x asset + * @param {number} yDecimals - The decimals of the y asset + * @returns {string} + */ + private calculatePrice(minOutput: any, from: any, sell: boolean, xDecimals: number, yDecimals: number): string { + if (sell) { + return BigNumber(1) + .div( + BigNumber(minOutput.amount.toString()) + .div(BigNumber(10).pow(xDecimals)) + .div(BigNumber(from.amount.toString()).div(BigNumber(10).pow(yDecimals))) + ) + .toString(); + } else { + return BigNumber(minOutput.amount.toString()) + .div(BigNumber(10).pow(yDecimals)) + .div(BigNumber(from.amount.toString()).div(BigNumber(10).pow(xDecimals))) + .toString(); } - return result; } + /** + * Calculates gas-related values + * @param {number} minTxFee - The minimum transaction fee + * @returns {number} + */ + private calculateGas(minTxFee: number): number { + return BigNumber(minTxFee).div(BigNumber(10).pow(9)).toNumber(); + } + + /** + * Gets a pool by its ID + * @param {string} id - The pool ID + * @returns {Pool} The pool + */ public getPool(id: string): Pool { return this.ammPools.find((ammPool) => ammPool.id === id); } + /** + * Gets pools by token pair + * @param {string} baseToken - The base token symbol + * @param {string} quoteToken - The quote token symbol + * @returns {Pool[]} The pools matching the token pair + */ public getPoolByToken(baseToken: string, quoteToken: string): Pool[] { const realBaseToken = this.storedAssetList.find( (asset) => asset.symbol === baseToken, @@ -891,6 +1005,11 @@ export class Ergo { ); } + /** + * Gets a transaction by its ID + * @param {string} id - The transaction ID + * @returns {Promise} The transaction details + */ public async getTx(id: string): Promise { return await this._node.getTxsById(id); } From 665aa398ed9f02a4a39526cfe3910776d353826e Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Wed, 31 Jul 2024 18:11:41 +0330 Subject: [PATCH 129/132] priceToken problem fixed --- src/chains/ergo/ergo.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 760ce84809..7ffca2b4e6 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -720,7 +720,7 @@ export class Ergo { ) .toString(), gasPrice: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toNumber(), - gasPriceToken: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toString(), + gasPriceToken: 'ERG', gasLimit: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toNumber(), gasCost: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toString(), txHash: tx.id, @@ -758,7 +758,7 @@ export class Ergo { timestamp: Date.now(), latency: 0, gasPrice: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toNumber(), - gasPriceToken: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toString(), + gasPriceToken: 'ERG', gasLimit: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toNumber(), gasCost: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toString(), }; @@ -858,7 +858,7 @@ export class Ergo { timestamp: Date.now(), latency: 0, gasPrice: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toNumber(), - gasPriceToken: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toString(), + gasPriceToken: 'ERG', gasLimit: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toNumber(), gasCost: BigNumber(config.network.minTxFee).div(BigNumber(10).pow(9)).toString(), }; From ecdb6ede4acc89a45874a2dcdf49e1f6696cda73 Mon Sep 17 00:00:00 2001 From: satiparpar Date: Fri, 2 Aug 2024 14:26:50 +0330 Subject: [PATCH 130/132] fix [unit-test]: fix ergoController to have been called correctly --- test-bronze/chains/ergo/ergo.controller.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-bronze/chains/ergo/ergo.controller.test.ts b/test-bronze/chains/ergo/ergo.controller.test.ts index 585755acd5..d094bfb6c4 100644 --- a/test-bronze/chains/ergo/ergo.controller.test.ts +++ b/test-bronze/chains/ergo/ergo.controller.test.ts @@ -288,7 +288,7 @@ describe('ErgoController', () => { { tokenId: 'token1', amount: '100' }, { tokenId: 'token2', amount: '200' }, ]); - expect(TransactionBuilder.prototype.sendChangeTo).toHaveBeenNthCalledWith( + expect(TransactionBuilder.prototype.sendChangeTo).toHaveBeenCalledWith( '9huCzcjG9bmpKccftEauEYD6YP6qVpnJQXAtwuSpXy3WcMpYgFX', ); expect(TransactionBuilder.prototype.payMinFee).toHaveBeenCalled(); From 04fcd51f4ed152d725bfaaa2c2cab38bc84ad01f Mon Sep 17 00:00:00 2001 From: hirotadashi Date: Fri, 2 Aug 2024 16:42:06 +0330 Subject: [PATCH 131/132] Merge branch 'refactor' # Conflicts: # src/chains/ergo/ergo.ts --- test-bronze/chains/ergo/ergo.test.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test-bronze/chains/ergo/ergo.test.ts b/test-bronze/chains/ergo/ergo.test.ts index 7e036a9813..efc6b4042c 100644 --- a/test-bronze/chains/ergo/ergo.test.ts +++ b/test-bronze/chains/ergo/ergo.test.ts @@ -277,7 +277,7 @@ describe('Ergo', () => { SIGUSD: { tokenId: 'SIGUSDId', decimals: 3, - name: 'SIGUSD', + name: 'SigUSD', symbol: 'SIGUSD', }, }; @@ -1041,7 +1041,7 @@ describe('Ergo', () => { { tokenId: 'SIGUSDId', decimals: 3, - name: 'SIGUSD', + name: 'SigUSD', symbol: 'SIGUSD', }, @@ -1220,7 +1220,7 @@ describe('Ergo', () => { { tokenId: 'SIGUSDId', decimals: 3, - name: 'SIGUSD', + name: 'SigUSD', symbol: 'SIGUSD', }, ]); @@ -1471,7 +1471,7 @@ describe('Ergo', () => { { tokenId: 'SIGUSDId', decimals: 3, - name: 'SIGUSD', + name: 'SigUSD', symbol: 'SIGUSD', }, @@ -1579,7 +1579,7 @@ describe('Ergo', () => { { tokenId: 'SIGUSDId', decimals: 3, - name: 'SIGUSD', + name: 'SigUSD', symbol: 'SIGUSD', }, ]); @@ -1712,7 +1712,7 @@ describe('Ergo', () => { { tokenId: 'SIGUSDId', decimals: 3, - name: 'SIGUSD', + name: 'SigUSD', symbol: 'SIGUSD', }, { From 0f55fa5584bcff9815ce7571d8a28d2f3bc80e4a Mon Sep 17 00:00:00 2001 From: satiparpar Date: Fri, 2 Aug 2024 17:47:04 +0330 Subject: [PATCH 132/132] update [unit-test]: useless logs removed & useless if removed in Ergo --- src/chains/ergo/ergo.ts | 8 +------- test-bronze/chains/ergo/ergo.controller.test.ts | 2 -- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/chains/ergo/ergo.ts b/src/chains/ergo/ergo.ts index 6d21c080ed..9c9e40440f 100644 --- a/src/chains/ergo/ergo.ts +++ b/src/chains/ergo/ergo.ts @@ -201,13 +201,7 @@ export class Ergo { } if (!Ergo._instances.has(config.network.name)) { - if (network) { - Ergo._instances.set(config.network.name, new Ergo(network)); - } else { - throw new Error( - `Ergo.getInstance received an unexpected network: ${network}.`, - ); - } + Ergo._instances.set(config.network.name, new Ergo(network)); } return Ergo._instances.get(config.network.name) as Ergo; diff --git a/test-bronze/chains/ergo/ergo.controller.test.ts b/test-bronze/chains/ergo/ergo.controller.test.ts index d094bfb6c4..fb2623a03f 100644 --- a/test-bronze/chains/ergo/ergo.controller.test.ts +++ b/test-bronze/chains/ergo/ergo.controller.test.ts @@ -166,7 +166,6 @@ describe('ErgoController', () => { }, }); const result = await ErgoController.balances(ergo, request); - console.log(result); expect(result).toMatchObject({ network: 'mainnet', // timestamp ignored because there was a really small difference between create Date.new() in test file and main file @@ -358,7 +357,6 @@ describe('ErgoController', () => { }, }); const result = await ErgoController.allowances(ergo, request); - console.log(result); expect(result).toMatchObject({ network: 'mainnet', // timestamp ignored because there was a really small difference between create Date.new() in test file and main file