Skip to content

Commit

Permalink
Merge pull request #18
Browse files Browse the repository at this point in the history
Made xnetwork to work with v1.7.0 and arm64
  • Loading branch information
gfusee authored Mar 11, 2024
2 parents ac3f2d3 + 4b37089 commit 71ec329
Show file tree
Hide file tree
Showing 43 changed files with 688 additions and 259 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# xNetwork

This project offers an effortless way to run a local testnet of MultiversX and its corresponding API without any configuration needed.
While you can run a local testnet of MultiversX using the [MultiversX CLI](https://multiversx.com/), this project provides a more comprehensive environment, including a proxy and a complete API.
This project offers an effortless way to run a localnet of MultiversX and its corresponding API without any configuration needed.
While you can run a localnet of MultiversX using the [MultiversX CLI](https://multiversx.com/), this project provides a more comprehensive environment, including a proxy and a complete API.

## Features
- Run your own local testnet of MultiversX
- Run your own localnet of MultiversX
- Choose the number of shards you prefer
- Create an initial address with 1,000,000 $EGLD
- Run the corresponding API, identical to https://api.multiversx.com
Expand Down
8 changes: 4 additions & 4 deletions cli/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions cli/src/config/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ export class Constants {
return path.join(Constants.CLI_USER_STORAGE_PATH, 'latest_config.json')
}

static get TESTNET_CONTAINER(): ContainerInfos {
static get LOCALNET_CONTAINER(): ContainerInfos {
return {
name: "testnet",
name: "localnet",
pauseBehavior: PauseBehavior.PAUSE
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ import {Answers} from "inquirer";
import {CLIConfig} from "../../config/config.js";
import {CustomAddressToGiveEGLDQuestion} from "./customAddressToGiveEGLDQuestion.js";

export class FreshTestnetFeaturesQuestion extends FeaturesQuestion {
export class FreshLocalnetFeaturesQuestion extends FeaturesQuestion {

static readonly giveToCustomAddressChoice = 'Give 1,000,000 EGLD to a custom address (otherwise a new one will be generated for you)'
cliChoices = [FreshTestnetFeaturesQuestion.giveToCustomAddressChoice]
cliChoices = [FreshLocalnetFeaturesQuestion.giveToCustomAddressChoice]

override async handleAnswer(answers: Answers, config: CLIConfig): Promise<CLIQuestion[]> {
const questions = await super.handleAnswer(answers, config)

if (answers.choice.includes(FreshTestnetFeaturesQuestion.giveToCustomAddressChoice)) {
if (answers.choice.includes(FreshLocalnetFeaturesQuestion.giveToCustomAddressChoice)) {
questions.push(new CustomAddressToGiveEGLDQuestion())
}

Expand Down
4 changes: 2 additions & 2 deletions cli/src/questions/fresh/numberShardsQuestion.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {CLIQuestion} from "../question.js";
import {FreshTestnetFeaturesQuestion} from "../features/freshTestnetFeaturesQuestion.js";
import {FreshLocalnetFeaturesQuestion} from "../features/freshLocalnetFeaturesQuestion.js";
import {Answers, Question} from "inquirer";
import {CLIConfig} from "../../config/config.js";

Expand Down Expand Up @@ -31,6 +31,6 @@ export class NumberShardsQuestion extends CLIQuestion {

config.numberOfShards = answers.numberShards

return [new FreshTestnetFeaturesQuestion()]
return [new FreshLocalnetFeaturesQuestion()]
}
}
10 changes: 5 additions & 5 deletions cli/src/questions/startQuestion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,19 @@ export class StartQuestion extends CLIQuestion {

const state = await getNetworkState()

if (state.testnetContainerState !== ContainerState.NonExistent) {
if (state.localnetContainerState !== ContainerState.NonExistent) {

if (state.testnetContainerState === ContainerState.Running) {
if (state.localnetContainerState === ContainerState.Running) {
cliChoices.push(StartQuestion.pauseNetworkChoice)
} else if (state.testnetContainerState === ContainerState.Stopped) {
} else if (state.localnetContainerState === ContainerState.Stopped) {
cliChoices.push(StartQuestion.resumeNetworkChoice)
}

cliChoices.push(StartQuestion.removeNetworkChoice)

cliChoices.push(new inquirer.Separator())

const stateChalk = state.testnetContainerState === ContainerState.Running ? chalk.bold.green('running') : chalk.bold.yellow('paused')
const stateChalk = state.localnetContainerState === ContainerState.Running ? chalk.bold.green('running') : chalk.bold.yellow('paused')
cliChoiceMessage = `A network is ${stateChalk}, what do you want to do ?`
}

Expand Down Expand Up @@ -69,7 +69,7 @@ export class StartQuestion extends CLIQuestion {
}

override async process(config: CLIConfig) {
if ((await getNetworkState()).testnetContainerState !== ContainerState.NonExistent) {
if ((await getNetworkState()).localnetContainerState !== ContainerState.NonExistent) {
await super.process(config)
} else {
await (new NumberShardsQuestion()).process(config)
Expand Down
16 changes: 8 additions & 8 deletions cli/src/result/resultLogger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@ export class ResultLogger {
async printResults(config: CLIConfig) {

const state = await getNetworkState()
const containerResults = state.testnetResult
const containerResults = state.localnetResult

if (!containerResults) {
console.log(dontIndent(chalk.bold.red("Something went wrong while checking the status of the local testnet.")))
console.log(dontIndent(chalk.bold.red("Something went wrong while checking the status of the localnet.")))
return
}

let firstPartResultString = `${chalk.bold.green("Local testnet successfully started !")}`
let firstPartResultString = `${chalk.bold.green("Localnet successfully started !")}`

firstPartResultString += `
Proxy/Gateway URL: ${chalk.blue("http://localhost:7950")}
ChainID: ${chalk.blue("local-testnet")}
ChainID: ${chalk.blue("localnet")}
`

if (config.shouldHaveElasticSearch) {
Expand All @@ -36,15 +36,15 @@ export class ResultLogger {
}

if (containerResults.genesisEgldPemPath) {
const addressPrivateKey = (await execCustomInRepo(`docker-compose exec testnet cat ${containerResults.genesisEgldPemPath}`)).stdout.toString()
const addressPrivateKey = (await execCustomInRepo(`docker-compose exec localnet cat ${containerResults.genesisEgldPemPath}`)).stdout.toString()
firstPartResultString += `
An address with 1,000,000 EGLD was generated for you. Here are the details:
${chalk.bold.red("Here is the private key. Keep it safe and don't use it in another place than the local testnet!")}
${chalk.bold.red("Here is the private key. Keep it safe and don't use it in another place than the localnet!")}
${addressPrivateKey}
${chalk.bold.red("End of the private key. You can copy/paste the content into a .pem file and use it to do transactions on the local testnet.")}
${chalk.bold.red("End of the private key. You can copy/paste the content into a .pem file and use it to do transactions on the localnet.")}
`
} else {
firstPartResultString += `
Expand All @@ -55,7 +55,7 @@ export class ResultLogger {
let mxOpsDisplayString = ''

if (config.mxOpsScenesPath) {
const mxopsXNetworkValuesRaw = (await execCustomInRepo(`docker-compose exec testnet python3 -m mxops data get -n LOCAL -s xnetwork`)).stdout.toString()
const mxopsXNetworkValuesRaw = (await execCustomInRepo(`docker-compose exec localnet python3 -m mxops data get -n LOCAL -s xnetwork`)).stdout.toString()
const searchString = 'ABSOLUTELY NO WARRANTY\n'
const mxopsXNetworkValues = mxopsXNetworkValuesRaw.substring(mxopsXNetworkValuesRaw.lastIndexOf(searchString) + searchString.length).trim()
const mxopsXNetworkValuesObject = JSON.parse(mxopsXNetworkValues)
Expand Down
6 changes: 3 additions & 3 deletions cli/src/utils/docker/createNetwork.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export async function createNetwork(config: CLIConfig) {
}

const startingNetworkSpinner = ora('Starting network...').start()
await upContainer(Constants.TESTNET_CONTAINER.name, {
await upContainer(Constants.LOCALNET_CONTAINER.name, {
...process.env,
"MX_LT_NUM_SHARDS": config.numberOfShards.toString(),
"MX_LT_ELASTIC_ENABLED": config.shouldHaveElasticSearch.toString(),
Expand All @@ -62,11 +62,11 @@ export async function createNetwork(config: CLIConfig) {

if (config.mxOpsScenesPath) {
const copyingScenesSpinner = ora('Copying mxops scenes...').start()
await execCustomInRepo(`docker-compose cp ${config.mxOpsScenesPath} testnet:/home/ubuntu/mxops`)
await execCustomInRepo(`docker-compose cp ${config.mxOpsScenesPath} localnet:/home/ubuntu/mxops`)
copyingScenesSpinner.succeed('Copied mxops scenes')

const runningScenesSpinner = ora('Running mxops scenes...').start()
await execCustomInRepo(`docker-compose exec testnet python3 run_mxops.py`)
await execCustomInRepo(`docker-compose exec localnet python3 run_mxops.py`)
runningScenesSpinner.succeed('Ran mxops scenes')
}

Expand Down
24 changes: 12 additions & 12 deletions cli/src/utils/docker/getNetworkState.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,41 @@
import {execCustomInRepo} from "../exec.js";

type TestnetResult = {
type LocalnetResult = {
genesisEgldAddress: string,
genesisEgldPemPath?: string,
}

type NetworkState = {
testnetContainerState: ContainerState,
testnetResult?: TestnetResult
localnetContainerState: ContainerState,
localnetResult?: LocalnetResult
}

export enum ContainerState {
Running, Stopped, NonExistent
}

export async function getNetworkState(): Promise<NetworkState> {
const containerState = await getTestnetContainerState()
const containerState = await getLocalnetContainerState()

try {
const containerResultsRaw = (await execCustomInRepo("docker-compose exec testnet cat /home/ubuntu/results.json")).stdout.toString()
const containerResults: TestnetResult = JSON.parse(containerResultsRaw)
const containerResultsRaw = (await execCustomInRepo("docker-compose exec localnet cat /home/ubuntu/results.json")).stdout.toString()
const containerResults: LocalnetResult = JSON.parse(containerResultsRaw)

return {
testnetContainerState: containerState,
testnetResult: containerResults,
localnetContainerState: containerState,
localnetResult: containerResults,
}
} catch (e) {
return {
testnetContainerState: containerState,
testnetResult: undefined,
localnetContainerState: containerState,
localnetResult: undefined,
}
}
}

async function getTestnetContainerState(): Promise<ContainerState> {
async function getLocalnetContainerState(): Promise<ContainerState> {
try {
const stdout = (await execCustomInRepo('docker-compose ps -a -q testnet')).stdout.toString()
const stdout = (await execCustomInRepo('docker-compose ps -a -q localnet')).stdout.toString()

const containerId = stdout.trim()

Expand Down
6 changes: 3 additions & 3 deletions cli/src/utils/docker/pauseExistingNetwork.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ export async function pauseExistingNetwork() {
await pauseContainer(Constants.RABBITMQ_CONTAINER)
}

const pausingTestnetSpinner = ora(`Pausing testnet...`).start()
await pauseContainer(Constants.TESTNET_CONTAINER)
pausingTestnetSpinner.succeed(`Paused testnet successfully`)
const pausingLocalnetSpinner = ora(`Pausing localnet...`).start()
await pauseContainer(Constants.LOCALNET_CONTAINER)
pausingLocalnetSpinner.succeed(`Paused localnet successfully`)
}

async function pauseContainer(containerInfos: ContainerInfos) {
Expand Down
2 changes: 1 addition & 1 deletion cli/src/utils/docker/resumeExistingNetwork.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export async function resumeExistingNetwork() {
await resumeContainer(Constants.RABBITMQ_CONTAINER)
}

await resumeContainer(Constants.TESTNET_CONTAINER)
await resumeContainer(Constants.LOCALNET_CONTAINER)

await waitForVMQueryToBeReady()

Expand Down
4 changes: 2 additions & 2 deletions containers/api/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ RUN curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - && sudo ap
RUN sudo apt install git -y
RUN sudo apt install ffmpeg -y
RUN sudo npm install -g @nestjs/cli
RUN git clone https://github.com/multiversx/mx-api-service.git -b development
RUN cd mx-api-service && git checkout 8cc3910
RUN git clone https://github.com/multiversx/mx-api-service.git -b main
RUN cd mx-api-service && git checkout 93a9abd0033050e46242836c6cf12e7b396e294c
RUN cd mx-api-service && npm install
RUN rm -rf mx-api-service/config/config.devnet.json
COPY api-config.devnet.yaml mx-api-service/config/config.devnet.yaml
Expand Down
52 changes: 38 additions & 14 deletions containers/api/api-config.devnet.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ metaChainShardId: 4294967295
api:
public: true
private: false
auth: false
cron:
transactionProcessor: true
transactionProcessorMaxLookBehind: 100
Expand All @@ -15,21 +14,52 @@ cron:
fastWarm: true
queueWorker: true
elasticUpdater: false
statusChecker: false
flags:
useRequestCaching: true
useKeepAliveAgent: true
useTracing: true
useRequestLogging: true
useVmQueryTracing: true
useTracing: false
useRequestLogging: false
useVmQueryTracing: false
processNfts: false
indexer-v3: true
collectionPropertiesFromGateway: false
features:
eventsNotifier:
enabled: false
port: 5674
url: 'amqp://guest:[email protected]:5672'
url: 'amqp://guest:[email protected]:5673'
exchange: 'all_events'
queue: 'api-process-logs-and-events'
guestCaching:
enabled: false
hitsThreshold: 100
ttl: 12
transactionPool:
enabled: true
transactionPoolWarmer:
enabled: true
cronExpression: '*/5 * * * * *'
ttlInSeconds: 60
updateCollectionExtraDetails:
enabled: false
marketplace:
enabled: false
serviceUrl: 'https://devnet-nfts-graph.multiversx.com/graphql'
exchange:
enabled: false
serviceUrl: 'https://devnet-graph.xexchange.com/graphql'
dataApi:
enabled: false
serviceUrl: 'https://devnet-data-api.multiversx.com'
auth:
enabled: false
maxExpirySeconds: 86400
acceptedOrigins:
- ''
admins:
- ''
jwtSecret: ''
image:
width: 600
height: 600
Expand All @@ -40,12 +70,12 @@ aws:
s3Bucket: 'devnet-media.elrond.com'
s3Region: ''
urls:
api:
- 'http://localhost:3001'
self: 'http://localhost:3001'
elastic:
- 'http://elastic:9200'
gateway:
- 'http://testnet:7950'
- 'http://localnet:7950'
verifier: 'https://play-api.multiversx.com'
redis: 'redis'
rabbitmq: 'amqp://rabbitmq:5672'
providers: 'https://devnet-delegation-api.multiversx.com/providers'
Expand Down Expand Up @@ -90,12 +120,6 @@ inflation:
- 1130177
- 924690
- 719203
security:
admins:
jwtSecret:
nftProcess:
parallelism: 1
maxRetries: 3
transaction-action:
mex:
microServiceUrl: ''
4 changes: 2 additions & 2 deletions containers/api/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ sudo ./wait-for-it.sh rabbitmq:5672 --timeout=0
echo "Waiting for Elastic Search..."
sudo ./wait-for-it.sh elastic:9200 --timeout=0

echo "Waiting for testnet..."
sudo ./wait-for-it.sh testnet:7950 --timeout=0
echo "Waiting for localnet..."
sudo ./wait-for-it.sh localnet:7950 --timeout=0

echo "Running api service..."
cd mx-api-service
Expand Down
Loading

0 comments on commit 71ec329

Please sign in to comment.