├── .env.example ├── .eslintignore ├── .eslintrc.json ├── .github └── workflows │ └── PROD-dispatch.yml ├── .gitignore ├── .prettierignore ├── .prettierrc.json ├── LICENSE ├── README.md ├── package.json ├── src ├── docs │ ├── addValidator.ts │ ├── crossJUNEtoJVM.ts │ ├── crossJVMtoP.ts │ ├── getCurrentValidators.ts │ └── getTxStatus.ts ├── provider.ts ├── supernet │ ├── _checks.spec.ts │ ├── addSupernetValidator.ts │ ├── createChain.ts │ ├── createSupernet.ts │ └── removeSupernetValidator.ts └── wallet │ ├── account │ ├── account.ts │ ├── accountOperation.ts │ └── balanceListener.ts │ ├── generateWallet.ts │ ├── operations │ ├── crossOperation.ts │ ├── stakeOperation.ts │ └── wrapOperation.ts │ └── recoverWallet.ts └── tsconfig.json /.env.example: -------------------------------------------------------------------------------- 1 | MNEMONIC='paste your mnemonic here' 2 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /dist/* 2 | /node_modules/* 3 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "node": true, 4 | "es2021": true 5 | }, 6 | "overrides": [], 7 | "parser": "@typescript-eslint/parser", 8 | "parserOptions": { 9 | "project": "tsconfig.json", 10 | "ecmaVersion": "latest", 11 | "sourceType": "module" 12 | }, 13 | "rules": {} 14 | } 15 | -------------------------------------------------------------------------------- /.github/workflows/PROD-dispatch.yml: -------------------------------------------------------------------------------- 1 | name: PROD_dispatch 2 | on: [repository_dispatch] 3 | 4 | jobs: 5 | build: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - name: Checkout Code 9 | uses: actions/checkout@v3 10 | with: 11 | ref: dev 12 | 13 | - name: Install Dependencies 14 | run: npm install 15 | 16 | - name: Build 17 | run: npm run build 18 | 19 | - name: Set npm to save exact version numbers 20 | run: npm config set save-exact true 21 | 22 | - name: Update juneojs package to latest version 23 | run: npm install juneojs@latest 24 | 25 | - name: Build to check if juneojs update broke anything 26 | run: npm run build 27 | 28 | - name: Commit and push if changed 29 | run: | 30 | git config --global user.name 'GitHub Actions' 31 | git config --global user.email 'github-actions@github.com' 32 | git add -A 33 | git diff-index --quiet HEAD || git commit -m "Update juneojs to latest version" 34 | git push origin dev 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled files 2 | dist/ 3 | 4 | ### Node ### 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | lerna-debug.log* 12 | .pnpm-debug.log* 13 | package-lock.json 14 | 15 | # Diagnostic reports (https://nodejs.org/api/report.html) 16 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 17 | 18 | # Runtime data 19 | pids 20 | *.pid 21 | *.seed 22 | *.pid.lock 23 | 24 | # Directory for instrumented libs generated by jscoverage/JSCover 25 | lib-cov 26 | 27 | # Coverage directory used by tools like istanbul 28 | coverage 29 | *.lcov 30 | 31 | # nyc test coverage 32 | .nyc_output 33 | 34 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 35 | .grunt 36 | 37 | # Bower dependency directory (https://bower.io/) 38 | bower_components 39 | 40 | # node-waf configuration 41 | .lock-wscript 42 | 43 | # Compiled binary addons (https://nodejs.org/api/addons.html) 44 | build/Release 45 | 46 | # Dependency directories 47 | node_modules/ 48 | jspm_packages/ 49 | 50 | # Snowpack dependency directory (https://snowpack.dev/) 51 | web_modules/ 52 | 53 | # TypeScript cache 54 | *.tsbuildinfo 55 | 56 | # Optional npm cache directory 57 | .npm 58 | 59 | # Optional eslint cache 60 | .eslintcache 61 | 62 | # Optional stylelint cache 63 | .stylelintcache 64 | 65 | # Microbundle cache 66 | .rpt2_cache/ 67 | .rts2_cache_cjs/ 68 | .rts2_cache_es/ 69 | .rts2_cache_umd/ 70 | 71 | # Optional REPL history 72 | .node_repl_history 73 | 74 | # Output of 'npm pack' 75 | *.tgz 76 | 77 | # Yarn Integrity file 78 | .yarn-integrity 79 | 80 | # dotenv environment variable files 81 | .env 82 | .env.development.local 83 | .env.test.local 84 | .env.production.local 85 | .env.local 86 | 87 | # parcel-bundler cache (https://parceljs.org/) 88 | .cache 89 | .parcel-cache 90 | 91 | # Next.js build output 92 | .next 93 | out 94 | 95 | # Nuxt.js build / generate output 96 | .nuxt 97 | dist 98 | 99 | # Gatsby files 100 | .cache/ 101 | # Comment in the public line in if your project uses Gatsby and not Next.js 102 | # https://nextjs.org/blog/next-9-1#public-directory-support 103 | # public 104 | 105 | # vuepress build output 106 | .vuepress/dist 107 | 108 | # vuepress v2.x temp and cache directory 109 | .temp 110 | .cache 111 | 112 | # Docusaurus cache and generated files 113 | .docusaurus 114 | 115 | # Serverless directories 116 | .serverless/ 117 | 118 | # FuseBox cache 119 | .fusebox/ 120 | 121 | # DynamoDB Local files 122 | .dynamodb/ 123 | 124 | # TernJS port file 125 | .tern-port 126 | 127 | # Stores VSCode versions used for testing VSCode extensions 128 | .vscode-test 129 | 130 | # yarn v2 131 | .yarn/cache 132 | .yarn/unplugged 133 | .yarn/build-state.yml 134 | .yarn/install-state.gz 135 | .pnp.* 136 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | *.md 4 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "singleQuote": true, 4 | "semi": false 5 | } 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2023, Juneo 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its 16 | contributors may be used to endorse or promote products derived from 17 | this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **DISCLAIMER:** This repository uses a library currently in its early development stage. Features may be incomplete or subject to change. Breaking changes may occur without notice until the first stable release. 2 | 3 | # juneojs-examples 4 | 5 | ## Introduction 6 | 7 | This repository contains example projects demonstrating the use of the JuneoJS library for some functionalities. 8 | 9 | ## Prerequisites 10 | 11 | - Node.js v18 or higher 12 | - npm v9 or higher 13 | 14 | ## Installation 15 | 16 | 1. Clone the repository: 17 | `git clone https://github.com/Juneo-io/juneojs-examples.git` 18 | 2. Navigate to the project directory: 19 | `cd juneojs-examples` 20 | 21 | 3. Install dependencies: 22 | `npm install` 23 | 24 | 4. Create a `.env` file in the root directory and add your Mnemonic (see `.env.example` for details). 25 | 26 | ## Usage 27 | 28 | Run the different examples using the following command: 29 | 30 | ```bash 31 | npx ts-node src/ 32 | ``` 33 | 34 | ### Examples 35 | 36 | - `docs/addValidator.ts`: This example demonstrates how to add a validator to the Juneo network. 37 | - `docs/crossJunetoJVM.ts`: This example shows how to send a cross-chain transaction from JUNE Chain to the JVM Chain. 38 | 39 | More documentation will be provided in the future. Stay tuned! 40 | 41 | ## License 42 | 43 | This project is licensed under the BSD 3-Clause License. See the [LICENSE](LICENSE) file for more details. 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "juneojs-examples", 3 | "version": "1.1.1", 4 | "description": "Usage examples of JuneoJS", 5 | "main": "dist/index.js", 6 | "types": "dist/index.d.ts", 7 | "scripts": { 8 | "build": "tsc", 9 | "clean": "rm -rf dist", 10 | "fix": "npm run prettier && npm run lint", 11 | "lint": "eslint . --ext .ts --fix", 12 | "prettier": "npx prettier . --write" 13 | }, 14 | "keywords": [ 15 | "Juneo", 16 | "blockchain" 17 | ], 18 | "author": "Aleksander Waslet", 19 | "license": "BSD-3-Clause", 20 | "devDependencies": { 21 | "@types/node": "20.12.11", 22 | "@typescript-eslint/eslint-plugin": "7.7.1", 23 | "dotenv": "16.4.5", 24 | "eslint": "8.56.0", 25 | "eslint-config-prettier": "9.1.0", 26 | "eslint-plugin-import": "2.29.1", 27 | "eslint-plugin-n": "17.3.1", 28 | "eslint-plugin-prettier": "5.1.3", 29 | "prettier": "3.2.5", 30 | "ts-node": "10.9.2", 31 | "typescript": "5.4.5" 32 | }, 33 | "dependencies": { 34 | "juneojs": "0.0.134", 35 | "juneojs-examples": "file:" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/docs/addValidator.ts: -------------------------------------------------------------------------------- 1 | import * as dotenv from 'dotenv' 2 | import { 3 | MCNAccount, 4 | MCNProvider, 5 | OperationSummary, 6 | SocotraNetwork, 7 | TimeUtils, 8 | ValidatePrimaryOperation, 9 | } from 'juneojs' 10 | dotenv.config() 11 | 12 | async function main() { 13 | // provider to interact with the MCN 14 | const provider: MCNProvider = new MCNProvider(SocotraNetwork) 15 | // recovering account used to sign transactions 16 | const account: MCNAccount = provider.recoverAccount(process.env.MNEMONIC!) 17 | 18 | // the node id which will validate the funds 19 | const nodeId = 'NodeID-DXGCAZFrcwfBmgXMePrTm2EU8N3s46wEq' 20 | // the amount to validate 21 | const stakeAmount = BigInt(100 * 10 ** 9) // 100 JUNE 22 | // the duration of the validation 23 | const durationInDays = 20 24 | const stakeDuration = TimeUtils.day() * BigInt(durationInDays) 25 | // the addresses that will receive the stake once the validation ends 26 | const stakeAddresses: string[] = [ 27 | account.wallet.getAddress(provider.platformChain), 28 | ] 29 | // the addresses that will receive the rewards once the validation ends 30 | const rewardsAddresses: string[] = [ 31 | account.wallet.getAddress(provider.platformChain), 32 | ] 33 | const validateOperation = new ValidatePrimaryOperation( 34 | provider.platformChain, 35 | nodeId, 36 | '0x87c92be581de7f2abcba91ec6319d79d7bd6bb781fd4832880c272ab0a5b5caa17428bcccdf869d4bb2558c8f06a21c2', 37 | '0x8f528af8e09d4fd6b7103eb2cd443bbcc66b103a3681b0f625bef0b37c74d73bd6d12c324c3431c9eee54d65183c827909296f14193c54626464db91a35e0ce538ab5ac52d10126e3878434d4b77482c5bfd2f04bc6fdb697ec5de5db123c77c', 38 | stakeAmount, 39 | stakeDuration, 40 | stakeAddresses, 41 | stakeAddresses.length, 42 | rewardsAddresses, 43 | rewardsAddresses.length, 44 | ) 45 | // estimate the operation to get a summary 46 | const summary: OperationSummary = await account.estimate(validateOperation) 47 | // execute the operation 48 | await account.execute(summary) 49 | } 50 | 51 | main().catch((error) => { 52 | console.error(error) 53 | process.exitCode = 1 54 | }) 55 | -------------------------------------------------------------------------------- /src/docs/crossJUNEtoJVM.ts: -------------------------------------------------------------------------------- 1 | import * as dotenv from 'dotenv' 2 | import { 3 | CrossOperation, 4 | type ExecutableOperation, 5 | MCNAccount, 6 | MCNProvider, 7 | type OperationSummary, 8 | SocotraNetwork, 9 | } from 'juneojs' 10 | dotenv.config() 11 | 12 | async function main() { 13 | const provider: MCNProvider = new MCNProvider(SocotraNetwork) 14 | const account: MCNAccount = provider.recoverAccount(process.env.MNEMONIC!) 15 | // we instantiate a cross operation that we want to perform 16 | const cross = new CrossOperation( 17 | // source 18 | provider.juneChain, 19 | // destination 20 | provider.jvmChain, 21 | provider.juneAssetId, 22 | BigInt('1100000000000000000'), // 1.1 JUNE 23 | ) 24 | // estimate the operation 25 | const summary: OperationSummary = await account.estimate(cross) 26 | // execute the operation 27 | await account.execute(summary) 28 | const executable: ExecutableOperation = summary.getExecutable() 29 | // the receipts should contain multiple transaction ids 30 | // that were performed to complete the cross operation 31 | console.log(executable.receipts) 32 | } 33 | 34 | main().catch((error) => { 35 | console.error(error) 36 | process.exitCode = 1 37 | }) 38 | -------------------------------------------------------------------------------- /src/docs/crossJVMtoP.ts: -------------------------------------------------------------------------------- 1 | import * as dotenv from 'dotenv' 2 | import { 3 | CrossOperation, 4 | type ExecutableOperation, 5 | MCNAccount, 6 | MCNProvider, 7 | type OperationSummary, 8 | SocotraNetwork, 9 | } from 'juneojs' 10 | dotenv.config() 11 | 12 | async function main() { 13 | const provider: MCNProvider = new MCNProvider(SocotraNetwork) 14 | const account: MCNAccount = provider.recoverAccount(process.env.MNEMONIC!) 15 | // we instantiate a cross operation that we want to perform 16 | const cross = new CrossOperation( 17 | // source 18 | provider.jvmChain, 19 | // destination 20 | provider.platformChain, 21 | provider.juneAssetId, 22 | BigInt(1_000_000_000), // 1 JUNE 23 | ) 24 | // estimate the operation 25 | const summary: OperationSummary = await account.estimate(cross) 26 | // execute the operation 27 | await account.execute(summary) 28 | const executable: ExecutableOperation = summary.getExecutable() 29 | // the receipts should contain multiple transaction ids 30 | // that were performed to complete the cross operation 31 | console.log(executable.receipts) 32 | } 33 | 34 | main().catch((error) => { 35 | console.error(error) 36 | process.exitCode = 1 37 | }) 38 | -------------------------------------------------------------------------------- /src/docs/getCurrentValidators.ts: -------------------------------------------------------------------------------- 1 | import { MCNProvider, SocotraNetwork } from 'juneojs' 2 | 3 | async function main() { 4 | const provider: MCNProvider = new MCNProvider(SocotraNetwork) 5 | const nodeId = 'NodeID-DXGCAZFrcwfBmgXMePrTm2EU8N3s46wEq' 6 | const currentValidators = await provider.platformApi.getCurrentValidators( 7 | provider.mcn.primary.id, 8 | [nodeId], 9 | ) 10 | console.log(`Looking for node: ${nodeId}...`) 11 | console.log(JSON.stringify(currentValidators.validators[0])) 12 | console.log('Done') 13 | } 14 | 15 | main() 16 | -------------------------------------------------------------------------------- /src/docs/getTxStatus.ts: -------------------------------------------------------------------------------- 1 | import { MCNProvider, SocotraNetwork } from 'juneojs' 2 | 3 | async function main() { 4 | const provider: MCNProvider = new MCNProvider(SocotraNetwork) 5 | const txID: string = '9Km2dM9UgJAcXVMeLZrpBMXAbaRW1x2zNmErgpe4yXpdAtjoS' 6 | const tx: string | object = await provider.platformApi.getTxStatus(txID) 7 | console.log(tx) 8 | } 9 | 10 | main() 11 | -------------------------------------------------------------------------------- /src/provider.ts: -------------------------------------------------------------------------------- 1 | import { JuneoClient, MCNProvider, SocotraNetwork } from 'juneojs' 2 | 3 | async function main() { 4 | // the provider is used to interact with a mcn we can instantiate it this way 5 | // this will automatically connect it to the most relevant MCN (Juneo MCN Mainnet) 6 | const provider: MCNProvider = new MCNProvider() 7 | // if we want to instantiate it to interact with another specific MCN 8 | // we must either create a new MCN instance or we can use already existing values 9 | const otherProvider: MCNProvider = new MCNProvider(SocotraNetwork) 10 | // the provider can also use another client by default the address 11 | // provided in the MCN values is used but if we want to use for example 12 | // our own local node to interact with the network we can do it 13 | const localProvider: MCNProvider = new MCNProvider( 14 | SocotraNetwork, 15 | JuneoClient.parse('http://127.0.0.1:9650'), 16 | ) 17 | } 18 | 19 | main().catch((error) => { 20 | console.error(error) 21 | process.exitCode = 1 22 | }) 23 | -------------------------------------------------------------------------------- /src/supernet/_checks.spec.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks before executing a script. Please do not update this file 3 | * */ 4 | 5 | export function supernetIdCheck(supernetId: string) { 6 | if (supernetId === 'ZxTjijy4iNthRzuFFzMH5RS2BgJemYxwgZbzqzEhZJWqSnwhP') 7 | throw Error('Please update the supernetId variable') 8 | } 9 | 10 | export function chainNameCheck(chainName: string) { 11 | if (chainName === 'Chain A') 12 | throw Error('Please update the chainName variable.') 13 | } 14 | 15 | export function chainIdCheck(chainId: number) { 16 | if (chainId === 330333) throw Error('Please update the chainId variable.') 17 | } 18 | 19 | export function genesisMintAddressCheck(genesisMintAddress: string) { 20 | if (genesisMintAddress === '0x44542FD7C3F096aE54Cc07833b1C0Dcf68B7790C') 21 | throw Error( 22 | 'Please update the genesisMintAddress variable to an address you can access.', 23 | ) 24 | } 25 | 26 | export function nodeIdCheck(nodeId: string) { 27 | if (nodeId === 'NodeID-B2GHMQ8GF6FyrvmPUX6miaGeuVLH9UwHr') 28 | throw Error('Please update the nodeID variable to your node id.') 29 | } 30 | -------------------------------------------------------------------------------- /src/supernet/addSupernetValidator.ts: -------------------------------------------------------------------------------- 1 | import * as dotenv from 'dotenv' 2 | import { 3 | AddSupernetValidatorOperation, 4 | MCNAccount, 5 | MCNProvider, 6 | OperationSummary, 7 | SocotraNetwork, 8 | TimeUtils, 9 | } from 'juneojs' 10 | import { nodeIdCheck, supernetIdCheck } from './_checks.spec' 11 | 12 | dotenv.config() 13 | async function main() { 14 | const provider: MCNProvider = new MCNProvider(SocotraNetwork) 15 | const account: MCNAccount = provider.recoverAccount(process.env.MNEMONIC!) 16 | 17 | // Operation parameters 18 | const nodeId = 'NodeID-B2GHMQ8GF6FyrvmPUX6miaGeuVLH9UwHr' 19 | const durationInDays = 20 20 | const stakeDuration = TimeUtils.day() * BigInt(durationInDays) 21 | const weight = BigInt(100) 22 | const supernetId = 'ZxTjijy4iNthRzuFFzMH5RS2BgJemYxwgZbzqzEhZJWqSnwhP' 23 | 24 | // Checks before executing script 25 | supernetIdCheck(supernetId) 26 | nodeIdCheck(nodeId) 27 | 28 | // Operation instantiation and execution 29 | const addSupernetValidatorOperation = new AddSupernetValidatorOperation( 30 | provider.platformChain, 31 | supernetId, 32 | nodeId, 33 | weight, 34 | stakeDuration, 35 | ) 36 | const summary: OperationSummary = await account.estimate( 37 | addSupernetValidatorOperation, 38 | ) 39 | await account.execute(summary) 40 | } 41 | 42 | main().catch((error) => { 43 | console.error(error) 44 | process.exitCode = 1 45 | }) 46 | -------------------------------------------------------------------------------- /src/supernet/createChain.ts: -------------------------------------------------------------------------------- 1 | import * as dotenv from 'dotenv' 2 | import { 3 | CreateChainOperation, 4 | EVMAllocation, 5 | MCNAccount, 6 | MCNProvider, 7 | NetworkOperationStatus, 8 | OperationSummary, 9 | SocotraNetwork, 10 | SupernetEVMGenesis, 11 | } from 'juneojs' 12 | import { 13 | chainIdCheck, 14 | chainNameCheck, 15 | genesisMintAddressCheck, 16 | supernetIdCheck, 17 | } from './_checks.spec' 18 | 19 | dotenv.config() 20 | async function main() { 21 | const provider: MCNProvider = new MCNProvider(SocotraNetwork) 22 | const account: MCNAccount = provider.recoverAccount(process.env.MNEMONIC!) 23 | 24 | // Operation parameters 25 | const supernetId = 'ZxTjijy4iNthRzuFFzMH5RS2BgJemYxwgZbzqzEhZJWqSnwhP' 26 | const chainName = 'Chain A' 27 | const vmId = 'supernetevm' 28 | const chainId = 330333 29 | const genesisMintAddress = '0x44542FD7C3F096aE54Cc07833b1C0Dcf68B7790C' 30 | const genesisMintAmount = BigInt('1000000000000000000000000') 31 | const genesisData: string = new SupernetEVMGenesis(chainId, [ 32 | new EVMAllocation(genesisMintAddress, genesisMintAmount), 33 | ]).generate() 34 | 35 | // Checks before executing script 36 | supernetIdCheck(supernetId) 37 | chainNameCheck(chainName) 38 | chainIdCheck(chainId) 39 | genesisMintAddressCheck(genesisMintAddress) 40 | 41 | // Operation instantiation and execution 42 | const createChainOperation = new CreateChainOperation( 43 | provider.platformChain, 44 | supernetId, 45 | chainName, 46 | vmId, 47 | genesisData, 48 | ) 49 | const summary: OperationSummary = await account.estimate(createChainOperation) 50 | await account.execute(summary) 51 | 52 | console.log(summary.getExecutable().status) 53 | if (summary.getExecutable().status === NetworkOperationStatus.Done) { 54 | console.log( 55 | `Created chain with id: ${summary.getExecutable().receipts[0].transactionId}`, 56 | ) 57 | } 58 | } 59 | 60 | main().catch((error) => { 61 | console.error(error) 62 | process.exitCode = 1 63 | }) 64 | -------------------------------------------------------------------------------- /src/supernet/createSupernet.ts: -------------------------------------------------------------------------------- 1 | import * as dotenv from 'dotenv' 2 | import { 3 | CreateSupernetOperation, 4 | MCNAccount, 5 | MCNProvider, 6 | NetworkOperationStatus, 7 | OperationSummary, 8 | SocotraNetwork, 9 | } from 'juneojs' 10 | 11 | dotenv.config() 12 | async function main() { 13 | const provider: MCNProvider = new MCNProvider(SocotraNetwork) 14 | const account: MCNAccount = provider.recoverAccount(process.env.MNEMONIC!) 15 | 16 | // Operation parameters 17 | const supernetAuthAddresses: string[] = account 18 | .getAccount(provider.platformChain.id) 19 | .getSignersAddresses() 20 | const supernetAuthThreshold = supernetAuthAddresses.length 21 | 22 | // Operation instantiation and execution 23 | const createSupernetOperation = new CreateSupernetOperation( 24 | provider.platformChain, 25 | supernetAuthAddresses, 26 | supernetAuthThreshold, 27 | ) 28 | const summary: OperationSummary = await account.estimate( 29 | createSupernetOperation, 30 | ) 31 | await account.execute(summary) 32 | 33 | console.log(summary.getExecutable().status) 34 | if (summary.getExecutable().status === NetworkOperationStatus.Done) { 35 | console.log( 36 | `Created supernet with id: ${summary.getExecutable().receipts[0].transactionId}`, 37 | ) 38 | } 39 | } 40 | 41 | main().catch((error) => { 42 | console.error(error) 43 | process.exitCode = 1 44 | }) 45 | -------------------------------------------------------------------------------- /src/supernet/removeSupernetValidator.ts: -------------------------------------------------------------------------------- 1 | import * as dotenv from 'dotenv' 2 | import { 3 | MCNAccount, 4 | MCNProvider, 5 | OperationSummary, 6 | RemoveSupernetValidatorOperation, 7 | SocotraNetwork, 8 | } from 'juneojs' 9 | import { nodeIdCheck, supernetIdCheck } from './_checks.spec' 10 | 11 | dotenv.config() 12 | async function main() { 13 | const provider: MCNProvider = new MCNProvider(SocotraNetwork) 14 | const account: MCNAccount = provider.recoverAccount(process.env.MNEMONIC!) 15 | 16 | // Operation parameters 17 | const nodeId = 'NodeID-B2GHMQ8GF6FyrvmPUX6miaGeuVLH9UwHr' 18 | const supernetId = 'ZxTjijy4iNthRzuFFzMH5RS2BgJemYxwgZbzqzEhZJWqSnwhP' 19 | 20 | // Checks before executing script 21 | supernetIdCheck(supernetId) 22 | nodeIdCheck(nodeId) 23 | 24 | // Operation instantiation and execution 25 | const removeSupernetValidatorOperation = new RemoveSupernetValidatorOperation( 26 | provider.platformChain, 27 | supernetId, 28 | nodeId, 29 | ) 30 | const summary: OperationSummary = await account.estimate( 31 | removeSupernetValidatorOperation, 32 | ) 33 | await account.execute(summary) 34 | } 35 | 36 | main().catch((error) => { 37 | console.error(error) 38 | process.exitCode = 1 39 | }) 40 | -------------------------------------------------------------------------------- /src/wallet/account/account.ts: -------------------------------------------------------------------------------- 1 | import * as dotenv from 'dotenv' 2 | import { 3 | EVMAccount, 4 | JVMAccount, 5 | MCNAccount, 6 | MCNProvider, 7 | SocotraNetwork, 8 | SocotraWJUNEAsset, 9 | UtxoAccount, 10 | type AssetValue, 11 | type ChainAccount, 12 | } from 'juneojs' 13 | 14 | dotenv.config() 15 | async function main() { 16 | const provider: MCNProvider = new MCNProvider(SocotraNetwork) 17 | // create a MCNAccount from the provider with the chains of the default used MCN 18 | const account: MCNAccount = provider.recoverAccount(process.env.MNEMONIC!) 19 | // getting the account of one chain 20 | // note that if you are trying to retrieve the account of a chain that is not registered 21 | // in the creation of the MCNAccount you will get an error 22 | const chainAccount: ChainAccount = account.getAccount(provider.juneChain.id) 23 | // we can fetch the balances 24 | // it can be done individually 25 | await chainAccount.fetchBalance(provider.juneChain.assetId) 26 | // or with multiple values 27 | await chainAccount.fetchBalances([ 28 | SocotraWJUNEAsset.assetId, 29 | provider.juneAssetId, 30 | ]) 31 | // the balance can be retrieved with either a provider and an asset id 32 | // the provider will try to gather information about the asset id from the network 33 | let balance: AssetValue = await chainAccount.getValue( 34 | provider, 35 | provider.juneAssetId, 36 | ) 37 | // or with a TokenAsset that already holds information about the asset (type, name, symbol, decimals) 38 | balance = chainAccount.getAssetValue(provider.juneChain.asset) 39 | // the returned balance will be an AssetValue which contains useful methods 40 | // this is the value that must be used to create transactions 41 | console.log(balance.value) 42 | // this value is human friendly and shows all the decimals 43 | console.log(balance.getReadableValue()) 44 | // this value is rounded down up to 2 decimals 45 | console.log(balance.getReadableValueRounded()) 46 | // this value is rounded down up to 6 decimals 47 | console.log(balance.getReadableValueRounded(6)) 48 | 49 | // note that the JVM-Chain and Platform-Chain are both utxo accounts 50 | // and EVM chains are using nonce accounts 51 | const jvmAccount: UtxoAccount = new JVMAccount(provider, account.wallet) 52 | const juneAccount: EVMAccount = new EVMAccount( 53 | provider, 54 | provider.juneChain.id, 55 | account.wallet, 56 | ) 57 | // in utxo accounts all the balances that are on the account on the network 58 | // should already be fetched because of the nature of utxos. 59 | // however in nonce accounts not all the balances at a given block can be 60 | // fetched that easily from the network. So if you want to get the balance 61 | // of a specific asset on such account, you should make sure that it is fetched first. 62 | } 63 | 64 | main().catch((error) => { 65 | console.error(error) 66 | process.exitCode = 1 67 | }) 68 | -------------------------------------------------------------------------------- /src/wallet/account/accountOperation.ts: -------------------------------------------------------------------------------- 1 | import * as dotenv from 'dotenv' 2 | import { 3 | type ExecutableOperation, 4 | MCNAccount, 5 | MCNProvider, 6 | NetworkOperationStatus, 7 | type OperationSummary, 8 | SendOperation, 9 | SocotraNetwork, 10 | } from 'juneojs' 11 | 12 | dotenv.config() 13 | async function main() { 14 | const provider: MCNProvider = new MCNProvider(SocotraNetwork) 15 | const account: MCNAccount = provider.recoverAccount(process.env.MNEMONIC!) 16 | // we instantiate an operation that we want to perform on the chain 17 | const operation = new SendOperation( 18 | provider.juneChain, 19 | provider.juneChain.assetId, 20 | BigInt('1000000000000000000'), // 1 JUNE 21 | '0x8fc822F43B9d4C4E83E5198C56A4FfBc43dbd19a', 22 | ) 23 | // estimate returns a summary of the operation that contains data about it such as the fees to pay 24 | // note that if you try to estimate an operation which is not compatible with the chain 25 | // an error will be thrown. If you try to do an operation on a chain which is not 26 | // registered in the MCNAccount you will also encounter an error 27 | const summary: OperationSummary = await account.estimate(operation) 28 | console.log(summary.fees) 29 | // from the summary we can get the executable operation that will be used to perform it 30 | const executable: ExecutableOperation = summary.getExecutable() 31 | await account.execute(summary) 32 | // the executable has fields that can help keeping track of the current state of the operation 33 | console.log(executable.status === NetworkOperationStatus.Done) 34 | // a list of the current receipts created by the operation is also available 35 | console.log(executable.receipts) 36 | // once a finished status is set there should be no newer receipts into it 37 | // MCNOperationStatus.Done indicates that the executable successfully achieved all transactions 38 | // MCNOperationStatus.Error indicates that an error occured on one of the transactions and it stopped the operation 39 | // MCNOperationStatus.Timeout indicates that the executable stopped its execution because it was too long 40 | 41 | // because in this example we are doing a send operation which is pretty simple 42 | // there should be no more than one receipt into it but for more complex operations 43 | // there could be more transactions that are sent 44 | } 45 | 46 | main().catch((error) => { 47 | console.error(error) 48 | process.exitCode = 1 49 | }) 50 | -------------------------------------------------------------------------------- /src/wallet/account/balanceListener.ts: -------------------------------------------------------------------------------- 1 | import * as dotenv from 'dotenv' 2 | import { 3 | type BalanceListener, 4 | type BalanceUpdateEvent, 5 | type ChainAccount, 6 | MCNAccount, 7 | MCNProvider, 8 | SocotraNetwork, 9 | } from 'juneojs' 10 | 11 | dotenv.config() 12 | async function main() { 13 | const provider: MCNProvider = new MCNProvider(SocotraNetwork) 14 | const account: MCNAccount = provider.recoverAccount(process.env.MNEMONIC!) 15 | const juneAccount: ChainAccount = account.getAccount(provider.juneChain.id) 16 | // the asset id of the balance we will listen to 17 | const assetId: string = provider.juneChain.assetId 18 | // the listener we want to use 19 | const listener: BalanceListener = new ExampleComponent() 20 | // registering the listener for balance events 21 | juneAccount.getBalance(assetId).registerEvents(listener) 22 | } 23 | 24 | class ExampleComponent implements BalanceListener { 25 | onBalanceUpdateEvent(event: BalanceUpdateEvent) { 26 | console.log(event.previousValue + ' => ' + event.value) 27 | } 28 | } 29 | 30 | main().catch((error) => { 31 | console.error(error) 32 | process.exitCode = 1 33 | }) 34 | -------------------------------------------------------------------------------- /src/wallet/generateWallet.ts: -------------------------------------------------------------------------------- 1 | import { 2 | MCNProvider, 3 | MCNWallet, 4 | SocotraJUNEChain, 5 | SocotraJVMChain, 6 | SocotraNetwork, 7 | type VMWallet, 8 | } from 'juneojs' 9 | 10 | async function main() { 11 | const provider: MCNProvider = new MCNProvider(SocotraNetwork) 12 | // generating new master wallet 13 | const wallet: MCNWallet = provider.mcn.generateWallet() 14 | // can also be done this way with 12 being words count 15 | const wallet2 = new MCNWallet(provider.mcn.hrp, 12) 16 | // generated mnemonic 17 | console.log(wallet.mnemonic) 18 | const jvmChainAddress: string = wallet.getAddress(SocotraJVMChain) 19 | console.log(jvmChainAddress) 20 | const juneChainWallet: VMWallet = wallet.getWallet(SocotraJUNEChain) 21 | // june chain jeth address 22 | console.log(juneChainWallet.getJuneoAddress()) 23 | // june chain evm hex address 24 | console.log(juneChainWallet.getAddress()) 25 | } 26 | 27 | main().catch((error) => { 28 | console.error(error) 29 | process.exitCode = 1 30 | }) 31 | -------------------------------------------------------------------------------- /src/wallet/operations/crossOperation.ts: -------------------------------------------------------------------------------- 1 | import * as dotenv from 'dotenv' 2 | import { 3 | CrossOperation, 4 | type ExecutableOperation, 5 | type JEVMBlockchain, 6 | type JVMBlockchain, 7 | MCNAccount, 8 | MCNProvider, 9 | type OperationSummary, 10 | SocotraNetwork, 11 | } from 'juneojs' 12 | 13 | dotenv.config() 14 | async function main() { 15 | const provider: MCNProvider = new MCNProvider(SocotraNetwork) 16 | const account: MCNAccount = provider.recoverAccount(process.env.MNEMONIC!) 17 | // the chain which we will perform the cross from 18 | const sourceChain: JEVMBlockchain = provider.juneChain 19 | // the chain we will perform the cross to 20 | const destinationChain: JVMBlockchain = provider.jvmChain 21 | // asset id of JUNE Chain is JUNE asset id 22 | const assetId: string = sourceChain.assetId 23 | const amount = BigInt(1_000_000_000) // 1 JUNE 24 | // we instantiate a cross operation that we want to perform 25 | const cross = new CrossOperation( 26 | sourceChain, 27 | destinationChain, 28 | assetId, 29 | amount, 30 | ) 31 | // estimate the operation 32 | const summary: OperationSummary = await account.estimate(cross) 33 | console.log(summary.fees) 34 | // execute the operation 35 | await account.execute(summary) 36 | const executable: ExecutableOperation = summary.getExecutable() 37 | // the receipts should contain multiple transaction ids 38 | // that were performed to complete the cross operation 39 | console.log(executable.receipts) 40 | } 41 | 42 | main().catch((error) => { 43 | console.error(error) 44 | process.exitCode = 1 45 | }) 46 | -------------------------------------------------------------------------------- /src/wallet/operations/stakeOperation.ts: -------------------------------------------------------------------------------- 1 | import * as dotenv from 'dotenv' 2 | import { 3 | DelegatePrimaryOperation, 4 | MCNAccount, 5 | MCNProvider, 6 | NetworkOperationStatus, 7 | SocotraNetwork, 8 | TimeUtils, 9 | ValidatePrimaryOperation, 10 | type ExecutableOperation, 11 | type OperationSummary, 12 | type StakingOperationSummary, 13 | } from 'juneojs' 14 | 15 | dotenv.config() 16 | async function main() { 17 | const provider: MCNProvider = new MCNProvider(SocotraNetwork) 18 | const account: MCNAccount = provider.recoverAccount(process.env.MNEMONIC!) 19 | // the node id where to stake funds 20 | const nodeId: string = 'NodeID-DXGCAZFrcwfBmgXMePrTm2EU8N3s46wEq' 21 | // the amount to stake 22 | const stakeAmount = BigInt(1_000000000) // 1 JUNE 23 | // the time to end the stake with start time is staking period 24 | // staking period has a minimal and maximal value 25 | // the min duration is 14 days. But if you want to create delegation on the node 26 | // you should set a duration higher than 14 days 27 | // the duration of the validation 28 | const durationInDays = 20 29 | const stakeDuration = TimeUtils.day() * BigInt(durationInDays) 30 | // the addresses that will receive the stake once the validation ends 31 | const stakeAddresses: string[] = [ 32 | account.wallet.getAddress(provider.platformChain), 33 | ] 34 | // the addresses that will receive the rewards once the validation ends 35 | const rewardsAddresses: string[] = [ 36 | account.wallet.getAddress(provider.platformChain), 37 | ] 38 | // we instantiate a validate operation that we want to perform on the chain 39 | const validateOperation = new ValidatePrimaryOperation( 40 | provider.platformChain, 41 | nodeId, 42 | '0x87c92be581de7f2abcba91ec6319d79d7bd6bb781fd4832880c272ab0a5b5caa17428bcccdf869d4bb2558c8f06a21c2', 43 | '0x8f528af8e09d4fd6b7103eb2cd443bbcc66b103a3681b0f625bef0b37c74d73bd6d12c324c3431c9eee54d65183c827909296f14193c54626464db91a35e0ce538ab5ac52d10126e3878434d4b77482c5bfd2f04bc6fdb697ec5de5db123c77c', 44 | stakeAmount, 45 | stakeDuration, 46 | stakeAddresses, 47 | stakeAddresses.length, 48 | rewardsAddresses, 49 | rewardsAddresses.length, 50 | ) 51 | // estimate the operation to get a summary 52 | const summary: OperationSummary = await account.estimate(validateOperation) 53 | // from the summary we can get the executable operation that will be used to perform it 54 | const executable: ExecutableOperation = summary.getExecutable() 55 | // execute the operation 56 | await account.execute(summary) 57 | // check if the operation is successfull 58 | console.log(executable.status === NetworkOperationStatus.Done) 59 | // to retrieve the potential reward from the summary we must first convert it 60 | // when estimating a validate or delegate operation it will always return a staking operation summary 61 | const validateSummary: StakingOperationSummary = 62 | summary as StakingOperationSummary 63 | console.log(validateSummary.potentialReward) 64 | // we can instantiate a delegate operation if we want to perform it instead of a validation 65 | const delegateOperation = new DelegatePrimaryOperation( 66 | provider.platformChain, 67 | nodeId, 68 | stakeAmount, 69 | stakeDuration, 70 | stakeAddresses, 71 | stakeAddresses.length, 72 | stakeAddresses, 73 | stakeAddresses.length, 74 | ) 75 | const delegationSummary: OperationSummary = 76 | await account.estimate(delegateOperation) 77 | // execute the operation 78 | await account.execute(delegationSummary) 79 | } 80 | 81 | main().catch((error) => { 82 | console.error(error) 83 | process.exitCode = 1 84 | }) 85 | -------------------------------------------------------------------------------- /src/wallet/operations/wrapOperation.ts: -------------------------------------------------------------------------------- 1 | import * as dotenv from 'dotenv' 2 | import { 3 | type ExecutableOperation, 4 | MCNAccount, 5 | MCNProvider, 6 | NetworkOperationStatus, 7 | type OperationSummary, 8 | SocotraNetwork, 9 | WrapOperation, 10 | } from 'juneojs' 11 | 12 | dotenv.config() 13 | async function main() { 14 | const provider: MCNProvider = new MCNProvider(SocotraNetwork) 15 | const account: MCNAccount = provider.recoverAccount(process.env.MNEMONIC!) 16 | // we instantiate a wrap operation that we want to perform on the june chain 17 | // note that wrap operation can only be done on EVM chains 18 | const wrapOperation = new WrapOperation( 19 | provider.juneChain, 20 | provider.juneChain.wrappedAsset, 21 | BigInt('1000000000000000000'), 22 | ) 23 | // estimate the operation to get a summary 24 | const summary: OperationSummary = await account.estimate(wrapOperation) 25 | // from the summary we can get the executable operation that will be used to perform it 26 | const executable: ExecutableOperation = summary.getExecutable() 27 | // execute the operation 28 | await account.execute(summary) 29 | // check if the operation is successfull 30 | console.log(executable.status === NetworkOperationStatus.Done) 31 | } 32 | 33 | main().catch((error) => { 34 | console.error(error) 35 | process.exitCode = 1 36 | }) 37 | -------------------------------------------------------------------------------- /src/wallet/recoverWallet.ts: -------------------------------------------------------------------------------- 1 | import * as dotenv from 'dotenv' 2 | import { 3 | MCNProvider, 4 | MCNWallet, 5 | SocotraJUNEChain, 6 | SocotraJVMChain, 7 | SocotraNetwork, 8 | type VMWallet, 9 | } from 'juneojs' 10 | 11 | dotenv.config() 12 | async function main() { 13 | const provider: MCNProvider = new MCNProvider(SocotraNetwork) 14 | // recovering wallet from mnemonic 15 | const wallet: MCNWallet = provider.mcn.recoverWallet(process.env.MNEMONIC!) 16 | // can also be done this way with 12 being words count 17 | const wallet2 = new MCNWallet(provider.mcn.hrp, process.env.MNEMONIC!) 18 | const jvmChainAddress: string = wallet.getAddress(SocotraJVMChain) 19 | console.log(jvmChainAddress) 20 | const juneChainWallet: VMWallet = wallet.getWallet(SocotraJUNEChain) 21 | // june chain jeth address 22 | console.log(juneChainWallet.getJuneoAddress()) 23 | // june chain evm hex address 24 | console.log(juneChainWallet.getAddress()) 25 | } 26 | 27 | main().catch((error) => { 28 | console.error(error) 29 | process.exitCode = 1 30 | }) 31 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist/", 4 | "target": "ES2015", 5 | "module": "commonjs" 6 | }, 7 | "exclude": ["node_modules"], 8 | "include": ["src/"] 9 | } 10 | --------------------------------------------------------------------------------