├── .gitignore ├── account_tmp.js ├── src ├── utils │ ├── enum │ │ ├── channel.js │ │ ├── bridge.js │ │ ├── pair.js │ │ └── coin.js │ ├── constant.js │ └── helper.js ├── module │ ├── init_ai │ │ ├── operation │ │ │ └── signer.js │ │ ├── exception │ │ │ └── exception.js │ │ └── init_ai.js │ ├── tucana │ │ ├── operation │ │ │ └── signer.js │ │ ├── exception │ │ │ └── exception.js │ │ └── tucana.js │ ├── civitia │ │ ├── operation │ │ │ └── signer.js │ │ ├── civitia.js │ │ └── exception │ │ │ └── exception.js │ └── initia │ │ ├── operation │ │ └── signer.js │ │ ├── exception │ │ └── exception.js │ │ └── initia.js └── repository │ ├── tucana_repo.js │ └── initia_repo.js ├── package.json ├── .github └── workflows │ └── npm-publish.yml ├── schedule.js ├── test └── test.js ├── user_config_tmp.js ├── index.js ├── Readme.md └── config.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | account.js 3 | user_config.js -------------------------------------------------------------------------------- /account_tmp.js: -------------------------------------------------------------------------------- 1 | const account = [["WALLET ADDRESS", "PRIVATE KEY"]]; 2 | 3 | export { account }; 4 | -------------------------------------------------------------------------------- /src/utils/enum/channel.js: -------------------------------------------------------------------------------- 1 | export const CHANNEL = { 2 | USDC: "channel-13", 3 | TIA: "channel-31", 4 | TUCANA: "channel-25", 5 | ETH: "channel-0", 6 | }; 7 | -------------------------------------------------------------------------------- /src/utils/enum/bridge.js: -------------------------------------------------------------------------------- 1 | export const BridgeID = { 2 | MINIMOVE: 1, 3 | MINIWASM: 2, 4 | INITAI: 6, 5 | BLACKWING: 8, 6 | TUCANA: 14, 7 | NOON: 17, 8 | CIVITA: 24, 9 | 10 | getBridgeByValue: function (value) { 11 | for (const key in this) { 12 | if (this.hasOwnProperty(key) && this[key] === value) { 13 | return key; 14 | } 15 | } 16 | throw new Error("No such Bridge Id with value: " + value); 17 | }, 18 | }; 19 | -------------------------------------------------------------------------------- /src/utils/enum/pair.js: -------------------------------------------------------------------------------- 1 | export const Pair = { 2 | INITIAUSDC: "INITIA/USDC", 3 | INITIATIA: "INITIA/TIA", 4 | INITIAETH: "INITIA/ETH", 5 | INITIATUC: "INITIA/TUCANA", 6 | INIT: "INIT", 7 | 8 | getKey: function (value) { 9 | for (const key in this) { 10 | if (this.hasOwnProperty(key) && this[key] === value) { 11 | return key; 12 | } 13 | } 14 | throw new Error("No such pair with value: " + value); 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "initia-daily-bot", 3 | "version": "v1.0.4-beta", 4 | "description": "Initia Daily Routine Bot", 5 | "type": "module", 6 | "repository": { 7 | "url": "https://github.com/Widiskel/initia-daily-bot.git" 8 | }, 9 | "main": "index.js", 10 | "scripts": { 11 | "start": "node index.js", 12 | "schedule" : "node schedule.js", 13 | "test" : "node ./test/test.js" 14 | }, 15 | "keywords": [ 16 | "Initia", "Bot", "Node Js", "Initia Bot", "Airdrop" 17 | ], 18 | "author": "Widiskel", 19 | "license": "ISC", 20 | "dependencies": { 21 | "@initia/initia.js": "^0.2.5", 22 | "cron": "^3.1.6", 23 | "twisters": "^1.1.0" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/module/init_ai/operation/signer.js: -------------------------------------------------------------------------------- 1 | class InitAiSigner { 2 | constructor(wallet, lcd, chainId) { 3 | this.wallet = wallet; 4 | this.lcd = lcd; 5 | this.chainId = chainId; 6 | } 7 | 8 | async signAndBroadcast(msg) { 9 | try { 10 | const signedTx = await this.wallet.createAndSignTx({ 11 | msgs: [msg], 12 | }); 13 | console.log("TX Signature : ", signedTx.signatures[0]); 14 | const broadcastResult = await this.lcd.tx.broadcast(signedTx); 15 | console.log("TX Hash : ", broadcastResult.txhash); 16 | console.log( 17 | `Explorer : https://scan.testnet.initia.xyz/${this.chainId}/txs/${broadcastResult.txhash}` 18 | ); 19 | } catch (error) { 20 | throw error; 21 | } 22 | } 23 | } 24 | 25 | export { InitAiSigner }; 26 | -------------------------------------------------------------------------------- /src/module/tucana/operation/signer.js: -------------------------------------------------------------------------------- 1 | class TucanaSigner { 2 | constructor(wallet, lcd, chainId) { 3 | this.wallet = wallet; 4 | this.lcd = lcd; 5 | this.chainId = chainId; 6 | } 7 | 8 | async signAndBroadcast(msg) { 9 | try { 10 | const signedTx = await this.wallet.createAndSignTx({ 11 | msgs: [msg], 12 | }); 13 | console.log("TX Signature : ", signedTx.signatures[0]); 14 | const broadcastResult = await this.lcd.tx.broadcast(signedTx); 15 | console.log("TX Hash : ", broadcastResult.txhash); 16 | console.log( 17 | `Explorer : https://scan.testnet.initia.xyz/${this.chainId}/txs/${broadcastResult.txhash}` 18 | ); 19 | } catch (error) { 20 | throw error; 21 | } 22 | } 23 | } 24 | 25 | export { TucanaSigner }; 26 | -------------------------------------------------------------------------------- /src/module/civitia/operation/signer.js: -------------------------------------------------------------------------------- 1 | class CivitiaSigner { 2 | constructor(wallet, lcd, chainId) { 3 | this.wallet = wallet; 4 | this.lcd = lcd; 5 | this.chainId = chainId; 6 | } 7 | 8 | async signAndBroadcast(msg) { 9 | try { 10 | const signedTx = await this.wallet.createAndSignTx({ 11 | msgs: [msg], 12 | }); 13 | console.log("TX Signature : ", signedTx.signatures[0]); 14 | const broadcastResult = await this.lcd.tx.broadcast(signedTx); 15 | console.log("TX Hash : ", broadcastResult.txhash); 16 | console.log( 17 | `Explorer : https://scan.testnet.initia.xyz/${this.chainId}/txs/${broadcastResult.txhash}` 18 | ); 19 | } catch (error) { 20 | throw error; 21 | } 22 | } 23 | } 24 | 25 | export { CivitiaSigner }; 26 | -------------------------------------------------------------------------------- /src/module/initia/operation/signer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Initia Signer class. 3 | * 4 | * Author : Widiskel 5 | * 6 | */ 7 | class InitiaSigner { 8 | constructor(wallet, lcd, chainId) { 9 | this.wallet = wallet; 10 | this.lcd = lcd; 11 | this.chainId = chainId; 12 | } 13 | 14 | async signAndBroadcast(msg) { 15 | try { 16 | const signedTx = await this.wallet.createAndSignTx({ 17 | msgs: [msg], 18 | }); 19 | console.log("TX Signature : ", signedTx.signatures[0]); 20 | const broadcastResult = await this.lcd.tx.broadcast(signedTx); 21 | console.log("TX Hash : ", broadcastResult.txhash); 22 | console.log( 23 | `Explorer : https://scan.testnet.initia.xyz/${this.chainId}/txs/${broadcastResult.txhash}` 24 | ); 25 | } catch (error) { 26 | throw error; 27 | } 28 | } 29 | } 30 | 31 | export { InitiaSigner }; 32 | -------------------------------------------------------------------------------- /src/utils/enum/coin.js: -------------------------------------------------------------------------------- 1 | export const COIN = { 2 | GAS: "move/944f8dd8dc49f96c25fea9849f16436dcfa6d564eec802f3ef7f8b3ea85368ff", 3 | ETHINITLP: 4 | "move/a2b0d3c8e53e379ede31f3a361ff02716d50ec53c6b65b8c48a81d5b06548200", 5 | TIAINITLP: 6 | "move/b134ae6786f10ef74294e627d2519b63b7c742a6735f98682929fea9a84744d2", 7 | USDCINITLP: 8 | "move/dbf06c48af3984ec6d9ae8a9aa7dbb0bb1e784aa9b8c4a5681af660cf8558d7d", 9 | INIT: "uinit", 10 | USDC: "uusdc", 11 | ETH: "ueth", 12 | TIA: "utia", 13 | TUCANA: 14 | "ibc/276C63284D960E3E4D76AEFC9A8BA338BAD24E30530C7C95E7EFC4D250D4E23D", 15 | UNKNOWN: "UNKNOWN", 16 | 17 | getCoinByValue: function (value) { 18 | for (const key in this) { 19 | if (this.hasOwnProperty(key) && this[key] === value) { 20 | return key; 21 | } else { 22 | return this.UNKNOWN; 23 | } 24 | } 25 | return this.UNKNOWN; 26 | }, 27 | }; 28 | -------------------------------------------------------------------------------- /.github/workflows/npm-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created 2 | # For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages 3 | 4 | name: Node.js Package 5 | 6 | on: 7 | release: 8 | types: [created] 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | - uses: actions/setup-node@v3 16 | with: 17 | node-version: 22 18 | - run: cp account_tmp.js account.js 19 | - run: npm ci 20 | 21 | publish-npm: 22 | needs: build 23 | runs-on: ubuntu-latest 24 | steps: 25 | - uses: actions/checkout@v4 26 | - uses: actions/setup-node@v3 27 | with: 28 | node-version: 22 29 | registry-url: https://registry.npmjs.org/ 30 | - run: npm ci 31 | - run: npm publish 32 | env: 33 | NODE_AUTH_TOKEN: ${{secrets.NPMJS_TOKEN}} 34 | -------------------------------------------------------------------------------- /schedule.js: -------------------------------------------------------------------------------- 1 | import { Twisters } from "twisters"; 2 | import { CronJob } from "cron"; 3 | import { doQuest } from "./index.js"; 4 | 5 | (async () => { 6 | try { 7 | const twisters = new Twisters(); 8 | 9 | twisters.put("title", { 10 | active: false, 11 | text: ` 12 | Initia Task Runner ! 13 | `, 14 | }); 15 | 16 | const job = new CronJob( 17 | "38 * * * *", 18 | () => { 19 | twisters.put("title", { 20 | active: false, 21 | text: ` 22 | Retrying ... 23 | `, 24 | }); 25 | account.forEach(async (account) => { 26 | var walletAddress = account[0]; 27 | var privateKey = account[1]; 28 | await doQuest(walletAddress, privateKey).catch((error) => 29 | console.error(error) 30 | ); 31 | }); 32 | }, 33 | null, 34 | true 35 | ); 36 | job.start(); 37 | } catch (error) { 38 | console.error("Error During executing bot", error); 39 | } 40 | })(); 41 | -------------------------------------------------------------------------------- /src/repository/tucana_repo.js: -------------------------------------------------------------------------------- 1 | async function getTucanaFaucet(address) { 2 | try { 3 | const response = await fetch("https://birdee-faucet.testnet.mesoops.net/", { 4 | headers: { 5 | accept: "*/*", 6 | "accept-language": "en-US,en;q=0.9,id;q=0.8", 7 | "content-type": "application/json", 8 | Referer: "https://birdee.faucet.tucana.zone/", 9 | "Referrer-Policy": "strict-origin-when-cross-origin", 10 | }, 11 | body: JSON.stringify({ 12 | address: address, 13 | coins: ["10000000utuc"], 14 | }), 15 | method: "POST", 16 | }); 17 | 18 | const data = await response.json(); 19 | 20 | if (response.ok) { 21 | console.log("Successfully request Faucet on TUCANA"); 22 | console.log(); 23 | } else { 24 | console.error( 25 | `Error during request tucana faucet: ${response.statusText} - ${data.error}` 26 | ); 27 | } 28 | } catch (error) { 29 | console.error("Error during request tucana faucet: Internal server Error"); 30 | } 31 | } 32 | export { getTucanaFaucet }; 33 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | import * as initia from "@initia/initia.js"; 2 | import { account } from "../src/account.js"; 3 | import * as initiaRepo from "../src/repository/initia_repo.js"; 4 | import { AppConstant } from "../src/utils/constant.js"; 5 | import { signAndBroadcast } from "../src/module/initia/initia.js"; 6 | 7 | const privateKeyBytes = Buffer.from(account[0][1], "hex"); 8 | const key = new initia.RawKey(Uint8Array.from(privateKeyBytes)); 9 | 10 | //DESERIALIZE 11 | // console.log( 12 | // initia.bcs 13 | // .u256() // type 14 | // .parse( 15 | // Uint8Array.from( 16 | // Buffer.from("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", "base64") 17 | // ) 18 | // ) 19 | // ); 20 | 21 | console.log( 22 | initia.bcs 23 | .u32() // type 24 | .parse(Uint8Array.from(Buffer.from("6v///w==", "base64"))) 25 | ); 26 | console.log( 27 | initia.bcs 28 | .u32() // type 29 | .parse(Uint8Array.from(Buffer.from("sAAAAA==", "base64"))) 30 | ); 31 | console.log( 32 | initia.bcs 33 | .u64() // type 34 | .parse(Uint8Array.from(Buffer.from("oIYBAAAAAAA=", "base64"))) 35 | ); 36 | console.log( 37 | initia.bcs 38 | .u64() // type 39 | .parse(Uint8Array.from(Buffer.from("HYABAAAAAAA=", "base64"))) 40 | ); 41 | console.log( 42 | initia.bcs 43 | .bool() // type 44 | .parse(Uint8Array.from(Buffer.from("AQ==", "base64"))) 45 | ); 46 | -------------------------------------------------------------------------------- /user_config_tmp.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Initia daily bot user config. 3 | * 4 | * Bot Feature 5 | * 1. Send 1 Init to Other 6 | * 2. Send 1 Init to Other (BLACKWING) 7 | * 3. Send 1 Init to Other (NOON) 8 | * 4. Send 1 Init to Other (TUCANA) 9 | * 5. Send 1 Init to Other (INIT AI) 10 | * 6. Send 1 Init to Other (MINIMOVE) 11 | * 7. Send 1 Init to Other (MINIWASM) 12 | * 8. Send 1 Init to Other (CIVITA) 13 | * 9. Bridge 1 Init to (CIVITA) 14 | * 10. Bridge 1 Init to (TUCANA) 15 | * 11. Bridge 1 Init to (INIT AI) 16 | * 12. Send 0.1 TIA to Other (NOON) (EXPERIMENTAL) 17 | * 13. Send 1 USDC to Other (BLACKWING) (EXPERIMENTAL) 18 | * 14. Send 5 TUC to Other (TUCANA) (EXPERIMENTAL) 19 | * 15. Send 0.0001 ETH to Other (MINIMOVE) (EXPERIMENTAL) 20 | * 16. Swap 1 INIT to USDC 21 | * 17. Swap 1 INIT to TIA 22 | * 18. Swap 1 INIT to TUC 23 | * 19. Swap 1 INIT to ETH 24 | * 20. Stake 1 INIT to Omninode 25 | * 21. Stake 0.5 USDC / INITIA LP to Omninode 26 | * 22. Stake 0.01 TIA / INITIA LP to Omninode 27 | * 23. Stake 0.0001 ETH / INITIA LP to Omninode 28 | * 24. Request Faucet for Tucana 29 | * 25. Add 1 TUC to Tucana Liquidity PERP 30 | * 26. Swap 1 INIT to USDC on TUCANA 31 | * 27. Roll Civitia Dice 3x 32 | * 28. Claim Staking Reward on Omninode 33 | * 29. Vote a proposal on Initia 34 | * 30. Move 0.1 Initia Stakes from Omninode to Nodes.Guru 35 | * 31. Add Liquidity INIT/USDC on Tucana Liquidity Pool 36 | * 32. Generate Collection on Init AI 37 | * 33. Mint NFT on Collection Assasin Holding blade NFT 38 | * 39 | * Author : Widiskel 40 | * 41 | */ 42 | 43 | // MORE TX CONFIG 44 | // const userConfig = Array.from({ length: 33 }, (_, i) => i + 1); 45 | 46 | // FOCUS EXP CONFIG 47 | // const userConfig = [9, 10, 11, 16, 17, 18, 19, 20, 21, 22, 23, 28, 29, 30, 24, 25, 26, 31, 27 , 32, 33]; 48 | 49 | // USER CONFIG 50 | const userConfig = [9, 10, 24, 25, 26, 27, 31]; 51 | 52 | export { userConfig }; 53 | -------------------------------------------------------------------------------- /src/module/civitia/civitia.js: -------------------------------------------------------------------------------- 1 | import * as initia from "@initia/initia.js"; 2 | import { CivitiaSigner } from "./operation/signer.js"; 3 | import { CivitiaException } from "./exception/exception.js"; 4 | import { AppConstant } from "../../utils/constant.js"; 5 | class Civitia extends CivitiaSigner { 6 | constructor(address, pk) { 7 | const chainId = "landlord-1"; 8 | const privateKeyBytes = Buffer.from(pk, "hex"); 9 | const key = new initia.RawKey(Uint8Array.from(privateKeyBytes)); 10 | const lcd = new initia.LCDClient( 11 | "https://maze-rest-sequencer-beab9b6f-d96d-435e-9caf-5679296d8172.ue1-prod.newmetric.xyz", 12 | { 13 | chainId: chainId, 14 | gasPrices: 15 | "0.151l2/afaa3f4e1717c75712f8e8073e41f051a4e516cd25daa82d948c4729388edefd", 16 | gasAdjustment: "2.0", 17 | } 18 | ); 19 | const wallet = new initia.Wallet(lcd, key); 20 | 21 | super(wallet, lcd); 22 | 23 | this.address = address; 24 | this.pk = pk; 25 | this.chainId = chainId; 26 | this.privateKeyBytes = privateKeyBytes; 27 | this.key = key; 28 | this.lcd = lcd; 29 | this.wallet = wallet; 30 | this.exception = new CivitiaException(this); 31 | } 32 | 33 | async rollDice() { 34 | try { 35 | console.log("Rolling dice on Civitia"); 36 | const msg = new initia.MsgExecute( 37 | this.key.accAddress, 38 | AppConstant.CIVITIAMODULEADDRESS, 39 | "civitia", 40 | "roll_dice" 41 | ); 42 | 43 | // console.log(msg); 44 | 45 | await this.signAndBroadcast(msg) 46 | .then(() => { 47 | console.log(`Successfully Roll Dice For Address ${this.address}`); 48 | }) 49 | .catch((err) => { 50 | throw err; 51 | }); 52 | } catch (error) { 53 | // console.log(error); 54 | this.exception.handlingError(error, "rollDice"); 55 | } 56 | } 57 | } 58 | 59 | export { Civitia }; 60 | -------------------------------------------------------------------------------- /src/module/init_ai/exception/exception.js: -------------------------------------------------------------------------------- 1 | import { AppConstant } from "../../../utils/constant.js"; 2 | import { InitAi } from "../init_ai.js"; 3 | 4 | class InitAiException { 5 | constructor(initAi) { 6 | this.maxRetries = 3; 7 | this.retryableErrors = []; 8 | 9 | /** @type {InitAi} */ 10 | this.initAi = initAi; 11 | } 12 | 13 | resetRoutine() { 14 | this.retryableErrors = []; 15 | } 16 | 17 | async retryContext(context) { 18 | console.log(`Retrying... ${context} \n`); 19 | if (context === "requestCreateCollection") { 20 | await this.initAi.requestCreateCollection(); 21 | } else if (context === "requestMint") { 22 | await this.initAi.requestMint(); 23 | } 24 | } 25 | 26 | async retry(context) { 27 | if ( 28 | this.retryableErrors.filter((val) => val == context).length < 29 | this.maxRetries 30 | ) { 31 | this.retryableErrors.push(context); 32 | await this.retryContext(context); 33 | } else { 34 | console.error( 35 | `Error during ${context} : RPC error and Max retry limit reached` 36 | ); 37 | } 38 | } 39 | 40 | async handlingError(error, context) { 41 | if (error.response != undefined) { 42 | if (error.response.data.message.includes("rpc error")) { 43 | console.error(`Error during ${context} : RPC error`); 44 | await this.retry(context); 45 | } else if (error.response.data.message.includes("failed to execute")) { 46 | console.error( 47 | `Error during ${context} : InitAI has limited uses through the day. Available again in 1 hour` 48 | ); 49 | await this.retry(context); 50 | } else { 51 | console.error(`Error during ${context} `, error.response.data.message); 52 | } 53 | } else { 54 | console.error( 55 | `Error during ${context} ${ 56 | subcontext != undefined ? `(${AppConstant.getKey(subcontext)})` : "" 57 | }: `, 58 | error.message 59 | ); 60 | } 61 | } 62 | } 63 | 64 | export { InitAiException }; 65 | -------------------------------------------------------------------------------- /src/utils/constant.js: -------------------------------------------------------------------------------- 1 | class AppConstant { 2 | //receiver 3 | static RECEIVERWALLETADDRESS = "init1gadzrjcp3ef90yka3sz2r6tf4wrjdhe2qr0hyp"; 4 | 5 | //module 6 | static CLAIMPOINTMODULEADDRESS = "0x9065fda28f52bb14ade545411f02e8e07a9cb4ba"; 7 | static TUCANAMODULEADDRESS = "0x3933C6AB1A6F84E9CDA13AE78F389666C9B83E69"; 8 | static TUCANAPERPMODULEADDRESS = "0x298a9dc53eda7750a5683960b01775d3a34ddb5f"; 9 | static TUCANAPOOLMODULEADDRESS = 10 | "0x8609f642a8ab1c13d661c14d733cab227bba15635a730af2057051b3f2ada3f6"; 11 | static CIVITIAMODULEADDRESS = "0x99132d33b555cd1565c59cee1e0e4ff52fbc7fb7"; 12 | static BRIDGEMODULEADDRESS = 13 | "0x42cd8467b1c86e59bf319e5664a09b6b5840bb3fac64f5ce690b5041c530565a"; 14 | 15 | //liquidity 16 | static INITIAUSDCLIQUIDITYADDRESS = 17 | "0xdbf06c48af3984ec6d9ae8a9aa7dbb0bb1e784aa9b8c4a5681af660cf8558d7d"; 18 | static INITIATIALIQUIDITYADDRESS = 19 | "0xb134ae6786f10ef74294e627d2519b63b7c742a6735f98682929fea9a84744d2"; 20 | static INITIAETHLIQUIDITYADDRESS = 21 | "0xa2b0d3c8e53e379ede31f3a361ff02716d50ec53c6b65b8c48a81d5b06548200"; 22 | static INITIATUCANALIQUIDITYADDRESS = 23 | "0x6396ff1a2938e726acc101b9c5414b805d9a605c03c8e08324f5c0c8807f7cbc"; 24 | static TUCANAINITIAUSDCLIQUIDITYADDRESS = 25 | "0x16b6ee2513acbd7f6e2a5c80d4b31d4bd42c4b07dee4b38bbf1db13b303093e1"; 26 | 27 | //Pep Position 28 | static TUCANAINITIAUSDCPOSITIONADDRESS = 29 | "0x7a7258fd680c6b925713aebe3069c73a5b5dd6a371abf362cc20d145ef4b029b"; 30 | 31 | //metadata 32 | static INITIAMETADATAADDRESS = 33 | "0x8e4733bdabcf7d4afc3d14f0dd46c9bf52fb0fce9e4b996c939e195b8bc891d9"; 34 | static USDCMETADATAADDRESS = 35 | "0x29824d952e035490fae7567deea5f15b504a68fa73610063c160ab1fa87dd609"; 36 | static TIAMETADATAADRESS = 37 | "0xacceb3b245392afe08346b794cf5c4ff85e7e9a8c82fcaf5112ae9d64ba57ccb"; 38 | static ETHMETADATAADRESS = 39 | "0xbe0ef849e425ca89830c1ff0f984f5b0b512b70cab6a5ae294c6255c3ee4cd0c"; 40 | static TUCMETADATAADRESS = 41 | "0x2b14e88b06f7eb3001fc6b1eb60802358555a4dfb1a4ed36507309a2d766ce4d"; 42 | static TUCPERPMETADATAADDRESS = 43 | "0xeb85af3fac00260b3f802aa1b8443da571ab28a823ba4d3c982553b9727625df"; 44 | 45 | //validator 46 | static OMNINODEVALIDATORADDRESS = 47 | "initvaloper1m07fvq8flvc3ltjlgk30nznfdjf4hx9nwcpdy9"; 48 | static NODESGURUVALIDATORADDRESS = 49 | "initvaloper1x7j4d9ccds889yxecuylp803d0h6lrfnv30k9y"; 50 | } 51 | 52 | export { AppConstant }; 53 | -------------------------------------------------------------------------------- /src/module/civitia/exception/exception.js: -------------------------------------------------------------------------------- 1 | import { AppConstant } from "../../../utils/constant.js"; 2 | import { Civitia } from "../civitia.js"; 3 | 4 | class CivitiaException { 5 | constructor(civitia) { 6 | this.maxRetries = 3; 7 | this.retryableErrors = []; 8 | 9 | /** @type {Civitia} */ 10 | this.civitia = civitia; 11 | } 12 | 13 | resetRoutine() { 14 | this.retryableErrors = []; 15 | } 16 | 17 | async retryContext(context, subcontext) { 18 | console.log(`Retrying... ${context} ${subcontext}`); 19 | if (context === "rollDice") { 20 | await this.civitia.rollDice(); 21 | } 22 | } 23 | 24 | async handlingError(error, context, subcontext) { 25 | if (error.response != undefined) { 26 | if (error.response.data.message.includes("rpc error")) { 27 | if (error.response.data.message.includes("account")) { 28 | console.error( 29 | `Error during ${context} : RPC error account not found in civitia chain ${ 30 | this.address 31 | }. ${ 32 | subcontext != undefined 33 | ? `(${AppConstant.getKey(subcontext)})` 34 | : "" 35 | }` 36 | ); 37 | } else { 38 | if ( 39 | this.retryableErrors.filter((val) => val == context).length < 40 | this.maxRetries 41 | ) { 42 | this.retryableErrors.push(context); 43 | console.error( 44 | `Error during ${context} : RPC error ${ 45 | subcontext != undefined 46 | ? `(${AppConstant.getKey(subcontext)})` 47 | : "" 48 | }` 49 | ); 50 | await this.retryContext(context, subcontext); 51 | } else { 52 | console.error( 53 | `Error during ${context} : RPC error ${ 54 | subcontext != undefined 55 | ? `(${AppConstant.getKey(subcontext)})` 56 | : "" 57 | }Max retry limit reached` 58 | ); 59 | } 60 | } 61 | } else { 62 | console.error( 63 | `Error during ${context} ${ 64 | subcontext != undefined ? AppConstant.getKey(subcontext) : "" 65 | } : `, 66 | error.response.data.message 67 | ); 68 | } 69 | } else { 70 | console.error( 71 | `Error during ${context} ${ 72 | subcontext != undefined ? `(${AppConstant.getKey(subcontext)})` : "" 73 | }: `, 74 | error.message 75 | ); 76 | } 77 | } 78 | } 79 | 80 | export { CivitiaException }; 81 | -------------------------------------------------------------------------------- /src/module/tucana/exception/exception.js: -------------------------------------------------------------------------------- 1 | import { Tucana } from "../tucana.js"; 2 | 3 | class TucanaException { 4 | constructor(tucana) { 5 | this.maxRetries = 3; 6 | this.retryableErrors = []; 7 | 8 | /** @type {Tucana} */ 9 | this.tucana = tucana; 10 | } 11 | 12 | resetRoutine() { 13 | this.retryableErrors = []; 14 | } 15 | 16 | async retryContext(context, subcontext) { 17 | console.log(`Retrying... ${context} ${subcontext}`); 18 | if (context === "swapTucana") { 19 | await this.tucana.swap(); 20 | } else if (context === "tucanaPerpAddLiquidity") { 21 | await this.tucana.tucanaPerpAddLiquidity(); 22 | } else if (context === "tucanaPoolAddLiquidity") { 23 | await this.tucana.tucanaPoolAddLiquidity(); 24 | } else if (context === "requestFaucet") { 25 | await this.tucana.requestFaucet(); 26 | } 27 | } 28 | 29 | async handlingError(error, context, subcontext) { 30 | if (error.response != undefined) { 31 | if (error.response.data.message.includes("rpc error")) { 32 | if (error.response.data.message.includes("account")) { 33 | console.error( 34 | `Error during ${context} : RPC error account not found in tucana chain ${ 35 | this.address 36 | }. ${ 37 | subcontext != undefined 38 | ? `(${AppConstant.getKey(subcontext)})` 39 | : "" 40 | }` 41 | ); 42 | } else { 43 | if ( 44 | this.retryableErrors.filter((val) => val == context).length < 45 | this.maxRetries 46 | ) { 47 | this.retryableErrors.push(context); 48 | console.error( 49 | `Error during ${context} : RPC error ${ 50 | subcontext != undefined 51 | ? `(${AppConstant.getKey(subcontext)})` 52 | : "" 53 | }` 54 | ); 55 | await this.retryContext(context, subcontext); 56 | } else { 57 | console.error( 58 | `Error during ${context} : RPC error ${ 59 | subcontext != undefined 60 | ? `(${AppConstant.getKey(subcontext)})` 61 | : "" 62 | }Max retry limit reached` 63 | ); 64 | } 65 | } 66 | } else { 67 | console.error( 68 | `Error during ${context} ${ 69 | subcontext != undefined ? AppConstant.getKey(subcontext) : "" 70 | } : `, 71 | error.response.data.message 72 | ); 73 | } 74 | } else { 75 | console.error( 76 | `Error during ${context} ${ 77 | subcontext != undefined ? `(${AppConstant.getKey(subcontext)})` : "" 78 | }: `, 79 | error.message 80 | ); 81 | } 82 | } 83 | } 84 | 85 | export { TucanaException }; 86 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import { account } from "./account.js"; 2 | import { Tucana } from "./src/module/tucana/tucana.js"; 3 | import { Civitia } from "./src/module/civitia/civitia.js"; 4 | import { Initia } from "./src/module/initia/initia.js"; 5 | import { Config } from "./config.js"; 6 | import { COIN } from "./src/utils/enum/coin.js"; 7 | import { InitAi } from "./src/module/init_ai/init_ai.js"; 8 | import { userConfig } from "./user_config.js"; 9 | 10 | async function doQuest(walletAddress, privateKey) { 11 | return new Promise(async (resolve, reject) => { 12 | try { 13 | const initia = new Initia(walletAddress, privateKey); 14 | const tucana = new Tucana(walletAddress, privateKey, initia); 15 | const civitia = new Civitia(walletAddress, privateKey); 16 | const initAi = new InitAi(walletAddress, privateKey); 17 | 18 | await initia.checkGas().then(async (gasBalance) => { 19 | if (gasBalance / 1000000 < 5) { 20 | reject( 21 | `Account ${walletAddress} GAS Token is not enough, min balance is 5 GAS` 22 | ); 23 | } else { 24 | console.log(`Account ${walletAddress} Information`); 25 | 26 | await initia 27 | .queryBalance(COIN.INIT) 28 | .then(async (initBalance) => { 29 | console.log(); 30 | console.log("Doing daily routine for Account " + walletAddress); 31 | console.log(); 32 | 33 | if (initBalance / 1000000 < 10) { 34 | reject( 35 | `Balance < 20 Initia for account ${walletAddress}, Please request initia token from faucet ` 36 | ); 37 | } else { 38 | const config = new Config( 39 | initia, 40 | civitia, 41 | tucana, 42 | initAi, 43 | userConfig, 44 | walletAddress 45 | ); 46 | 47 | for (const number of config.config) { 48 | await config.executeConfigCode(number); 49 | } 50 | 51 | initia.exception.resetRoutine(); 52 | tucana.exception.resetRoutine(); 53 | civitia.exception.resetRoutine(); 54 | initAi.exception.resetRoutine(); 55 | resolve(true); 56 | } 57 | }) 58 | .then((error) => reject(error)); 59 | } 60 | }); 61 | } catch (error) { 62 | reject(error); 63 | } 64 | }); 65 | } 66 | 67 | (async () => { 68 | try { 69 | for (const acc of account) { 70 | var walletAddress = acc[0]; 71 | var privateKey = acc[1]; 72 | await doQuest(walletAddress, privateKey).catch((error) => 73 | console.error(error) 74 | ); 75 | } 76 | } catch (error) { 77 | console.error("Error During executing bot", error); 78 | } 79 | })(); 80 | 81 | export { doQuest }; 82 | -------------------------------------------------------------------------------- /src/module/initia/exception/exception.js: -------------------------------------------------------------------------------- 1 | import { Initia } from "../initia.js"; 2 | 3 | /** 4 | * Initia Exception class. 5 | * 6 | * Author : Widiskel 7 | * 8 | */ 9 | class InitiaException { 10 | constructor(initia) { 11 | this.maxRetries = 3; 12 | this.retryableErrors = []; 13 | 14 | /** @type {Initia} */ 15 | this.initia = initia; 16 | } 17 | 18 | resetRoutine() { 19 | this.retryableErrors = []; 20 | } 21 | 22 | async retryContext(context, subcontext) { 23 | console.log(`Retrying... ${context} ${subcontext}`); 24 | if (context === "sendOneInitToOther") { 25 | await this.initia.sendOneInitToOther(); 26 | } else if (context === "sendTokenToOtherLayer") { 27 | await this.initia.sendTokenToOtherLayer( 28 | subcontext[0], 29 | subcontext[1], 30 | subcontext[2] 31 | ); 32 | } else if (context === "swap") { 33 | await this.initia.swap(false, subcontext); 34 | } else if (context === "claimStakingReward") { 35 | await this.initia.claimStakingReward(); 36 | } else if (context === "vote") { 37 | await this.initia.vote(); 38 | } else if (context === "bridge") { 39 | await this.initia.bridge(subcontext[0], subcontext[1], subcontext[2]); 40 | } else if (context === "moveStake") { 41 | await this.initia.moveStake(); 42 | } else if (context === "stake") { 43 | await this.initia.stake(subcontext); 44 | } 45 | } 46 | 47 | async handlingError(error, context, subcontext) { 48 | if (error.response != undefined) { 49 | if (error.response.data.message.includes("rpc error")) { 50 | if (error.response.data.message.includes("redelegation")) { 51 | console.error( 52 | `Error during ${context} : redelegation to this validator already in progress, first redelegation to this validator must complete before next redelegation` 53 | ); 54 | } else { 55 | if ( 56 | this.retryableErrors.filter((val) => val == context).length < 57 | this.maxRetries 58 | ) { 59 | this.retryableErrors.push(context); 60 | console.error( 61 | `Error during ${context} : RPC error ${ 62 | subcontext != undefined ? `(${subcontext})` : "" 63 | } ${error.response.data.message}` 64 | ); 65 | await this.retryContext(context, subcontext); 66 | } else { 67 | console.error( 68 | `Error during ${context} : RPC error ${ 69 | subcontext != undefined ? `(${subcontext})` : "" 70 | } Max retry limit reached` 71 | ); 72 | } 73 | } 74 | } else { 75 | console.error( 76 | `Error during ${context} ${ 77 | subcontext != undefined ? `(${subcontext})` : "" 78 | } : `, 79 | error.response.data.message 80 | ); 81 | } 82 | } else { 83 | console.error( 84 | `Error during ${context} ${ 85 | subcontext != undefined ? `(${subcontext})` : "" 86 | }: `, 87 | error.message 88 | ); 89 | } 90 | } 91 | } 92 | 93 | export { InitiaException }; 94 | -------------------------------------------------------------------------------- /src/repository/initia_repo.js: -------------------------------------------------------------------------------- 1 | async function getInitiation() { 2 | try { 3 | const response = await fetch( 4 | "https://omni-api.initiation-1.initia.xyz/v1/registry/chains/initiation-1", 5 | { 6 | headers: { 7 | accept: "application/json, text/plain, */*", 8 | }, 9 | referrer: "https://app.testnet.initia.xyz/", 10 | referrerPolicy: "strict-origin-when-cross-origin", 11 | method: "GET", 12 | mode: "cors", 13 | credentials: "omit", 14 | } 15 | ); 16 | 17 | if (response.ok) { 18 | const data = await response.json(); 19 | return data; 20 | } else { 21 | console.error("Error during initiation:", response.statusText); 22 | throw new Error( 23 | "Failed to fetch initiation data. Status: " + response.statusText 24 | ); 25 | } 26 | } catch (error) { 27 | throw error; 28 | } 29 | } 30 | 31 | async function getStageInfo() { 32 | const response = await fetch( 33 | "https://b545809c-5562-4e60-b5a1-22e83df57748.initiation-1.mesa-rest.ue1-prod.newmetric.xyz/initia/move/v1/accounts/0x9065fda28f52bb14ade545411f02e8e07a9cb4ba/modules/jennie/view_functions/stage_info", 34 | { 35 | headers: { 36 | accept: "application/json", 37 | "content-type": "application/json", 38 | }, 39 | referrer: "https://app.testnet.initia.xyz/", 40 | referrerPolicy: "strict-origin-when-cross-origin", 41 | body: '{"type_args":[],"args":[]}', 42 | method: "POST", 43 | mode: "cors", 44 | credentials: "omit", 45 | } 46 | ); 47 | 48 | if (response.ok) { 49 | const data = await response.json(); 50 | return data; 51 | } else { 52 | throw new Error( 53 | "Failed to fetch stage info data. Status: " + response.statusText 54 | ); 55 | } 56 | } 57 | async function getReferalPoint() { 58 | const response = await fetch( 59 | "https://xp-api.initiation-1.initia.xyz/leaderboard/rankings/init1gadzrjcp3ef90yka3sz2r6tf4wrjdhe2qr0hyp", 60 | { 61 | headers: { 62 | accept: "application/json, text/plain, */*", 63 | }, 64 | referrer: "https://app.testnet.initia.xyz/", 65 | referrerPolicy: "strict-origin-when-cross-origin", 66 | body: null, 67 | method: "GET", 68 | mode: "cors", 69 | credentials: "omit", 70 | } 71 | ); 72 | 73 | if (response.ok) { 74 | const data = await response.json(); 75 | return data; 76 | } else { 77 | throw new Error( 78 | "Failed to fetch stage info data. Status: " + response.statusText 79 | ); 80 | } 81 | } 82 | 83 | async function getLatestProposal() { 84 | try { 85 | const response = await fetch( 86 | "https://api.initiation-1.initia.xyz/indexer/gov/v1/proposals?status=all", 87 | { 88 | headers: { 89 | accept: "application/json, text/plain, */*", 90 | }, 91 | referrer: "https://app.testnet.initia.xyz/", 92 | referrerPolicy: "strict-origin-when-cross-origin", 93 | body: null, 94 | method: "GET", 95 | mode: "cors", 96 | credentials: "omit", 97 | } 98 | ); 99 | 100 | if (response.ok) { 101 | const data = await response.json(); 102 | return data.proposals[0]; 103 | } else { 104 | throw new Error( 105 | "Failed to fetch proposals data. Status: " + response.statusText 106 | ); 107 | } 108 | } catch (error) { 109 | throw error; 110 | } 111 | } 112 | 113 | export { getInitiation, getStageInfo, getReferalPoint, getLatestProposal }; 114 | -------------------------------------------------------------------------------- /src/module/init_ai/init_ai.js: -------------------------------------------------------------------------------- 1 | import * as initia from "@initia/initia.js"; 2 | import { InitAiSigner } from "./operation/signer.js"; 3 | import { InitAiException } from "./exception/exception.js"; 4 | import { AppConstant } from "../../utils/constant.js"; 5 | 6 | class InitAi extends InitAiSigner { 7 | constructor(address, pk) { 8 | const chainId = "init-ai-1"; 9 | const privateKeyBytes = Buffer.from(pk, "hex"); 10 | const key = new initia.RawKey(Uint8Array.from(privateKeyBytes)); 11 | const lcd = new initia.LCDClient( 12 | "https://maze-rest-617bacff-7d34-4eb8-87f4-ee16fb4e0ac7.ue1-prod.newmetric.xyz", 13 | { 14 | chainId: chainId, 15 | gasPrices: 16 | "0.151l2/aadf1a9da6a38b7e7e11839364ee42002260eff1657f403b9ce608337bcb986b", 17 | gasAdjustment: "2.0", 18 | } 19 | ); 20 | const wallet = new initia.Wallet(lcd, key); 21 | 22 | super(wallet, lcd); 23 | 24 | this.address = address; 25 | this.pk = pk; 26 | this.chainId = chainId; 27 | this.privateKeyBytes = privateKeyBytes; 28 | this.key = key; 29 | this.lcd = lcd; 30 | this.wallet = wallet; 31 | this.exception = new InitAiException(this); 32 | } 33 | 34 | async requestCreateCollection() { 35 | try { 36 | var prompt = `Something with number number ${Math.floor( 37 | Date.now() / 1000 38 | )}`; 39 | console.log(`Creating collection with prompt ${prompt}`); 40 | const msg = new initia.MsgExecute( 41 | this.key.accAddress, 42 | AppConstant.BRIDGEMODULEADDRESS, 43 | "ai_generate_nft", 44 | "request_create_collection", 45 | undefined, 46 | [ 47 | initia.bcs.string().serialize(prompt).toBase64(), 48 | initia.bcs.string().serialize(prompt).toBase64(), 49 | initia.bcs.string().serialize(prompt).toBase64(), 50 | initia.bcs.u8().serialize(1).toBase64(), 51 | ] 52 | ); 53 | 54 | await this.signAndBroadcast(msg) 55 | .then(() => { 56 | console.log( 57 | `Successfully Request for generate NFT Collection ${this.address}` 58 | ); 59 | }) 60 | .catch((err) => { 61 | throw err; 62 | }); 63 | } catch (error) { 64 | // console.log(error); 65 | this.exception.handlingError(error, "requestCreateCollection"); 66 | } 67 | } 68 | async requestMint() { 69 | try { 70 | var prompt = `Create me an Assasin holding blade with number ${ 71 | Math.floor(Math.random() * 10000) + 1 72 | }`; 73 | console.log( 74 | `Mint Nft on collection Assasin Holding blade NFT with prompt ${prompt}` 75 | ); 76 | const msg = new initia.MsgExecute( 77 | this.key.accAddress, 78 | AppConstant.BRIDGEMODULEADDRESS, 79 | "ai_generate_nft", 80 | "request_mint", 81 | undefined, 82 | [ 83 | initia.bcs 84 | .address() 85 | .serialize( 86 | "0xa239f18a073482b2c000e9b6be85f3ba055d20fcbd8d1dd6b388d93d28a5ded6" 87 | ) 88 | .toBase64(), 89 | initia.bcs.string().serialize(prompt).toBase64(), 90 | initia.bcs.u8().serialize(1).toBase64(), 91 | ] 92 | ); 93 | 94 | await this.signAndBroadcast(msg) 95 | .then(() => { 96 | console.log( 97 | `Successfully Request for generate NFT Collection ${this.address}` 98 | ); 99 | }) 100 | .catch((err) => { 101 | throw err; 102 | }); 103 | } catch (error) { 104 | // console.log(error); 105 | this.exception.handlingError(error, "requestMint"); 106 | } 107 | } 108 | } 109 | 110 | export { InitAi }; 111 | -------------------------------------------------------------------------------- /src/utils/helper.js: -------------------------------------------------------------------------------- 1 | import { AppConstant } from "./../utils/constant.js"; 2 | import { CHANNEL } from "./enum/channel.js"; 3 | import { Pair } from "./enum/pair.js"; 4 | 5 | function formatDateNowToCustomFormat() { 6 | const currentDate = new Date(); 7 | const monthNames = [ 8 | "Jan", 9 | "Feb", 10 | "Mar", 11 | "Apr", 12 | "May", 13 | "Jun", 14 | "Jul", 15 | "Aug", 16 | "Sep", 17 | "Oct", 18 | "Nov", 19 | "Dec", 20 | ]; 21 | 22 | // Get the components of the date 23 | const year = currentDate.getFullYear(); 24 | const month = monthNames[currentDate.getMonth()]; 25 | const day = currentDate.getDate(); 26 | let hours = currentDate.getHours(); 27 | const minutes = currentDate.getMinutes(); 28 | const seconds = currentDate.getSeconds(); 29 | const ampm = hours >= 12 ? "PM" : "AM"; 30 | 31 | hours = hours % 12; 32 | hours = hours ? hours : 12; 33 | const formattedDate = `${month} ${day}, ${year}, ${hours}:${minutes}:${seconds} ${ampm} (UTC)`; 34 | return formattedDate; 35 | } 36 | 37 | function generateTokenInfo(pair, oneWaySwap, address) { 38 | let liq; 39 | let firstMetadata; 40 | let secMetadata; 41 | if (pair == Pair.INITIATIA) { 42 | console.log( 43 | `Swapping 1 INITIA to TIA ${ 44 | !oneWaySwap ? "& TIA to INITIA" : "" 45 | } for Account ${address}` 46 | ); 47 | firstMetadata = AppConstant.INITIAMETADATAADDRESS; 48 | secMetadata = AppConstant.TIAMETADATAADRESS; 49 | liq = AppConstant.INITIATIALIQUIDITYADDRESS; 50 | } else if (pair == Pair.INITIAUSDC) { 51 | console.log( 52 | `Swapping 1 INITIA to USDC ${ 53 | !oneWaySwap ? "& USDC to INITIA" : "" 54 | } for Account ${address}` 55 | ); 56 | firstMetadata = AppConstant.INITIAMETADATAADDRESS; 57 | secMetadata = AppConstant.USDCMETADATAADDRESS; 58 | liq = AppConstant.INITIAUSDCLIQUIDITYADDRESS; 59 | } else if (pair == Pair.INITIAETH) { 60 | console.log( 61 | `Swapping 1 INITIA to ETH ${ 62 | !oneWaySwap ? "& ETH to INITIA" : "" 63 | } for Account ${address}` 64 | ); 65 | firstMetadata = AppConstant.INITIAMETADATAADDRESS; 66 | secMetadata = AppConstant.ETHMETADATAADRESS; 67 | liq = AppConstant.INITIAETHLIQUIDITYADDRESS; 68 | } else if (pair == Pair.INITIATUC) { 69 | console.log( 70 | `Swapping 1 INITIA to TUCANA ${ 71 | !oneWaySwap ? "& TUCANA to INITIA" : "" 72 | } for Account ${address}` 73 | ); 74 | firstMetadata = AppConstant.INITIAMETADATAADDRESS; 75 | secMetadata = AppConstant.TUCMETADATAADRESS; 76 | liq = AppConstant.INITIATUCANALIQUIDITYADDRESS; 77 | } 78 | return [liq, firstMetadata, secMetadata]; 79 | } 80 | 81 | function getChannel(coin) { 82 | if (coin == AppConstant.COIN.USDC) { 83 | return CHANNEL.USDC; 84 | } else if (coin == AppConstant.COIN.TIA) { 85 | return CHANNEL.TIA; 86 | } else if (coin == AppConstant.COIN.TUCANA) { 87 | return CHANNEL.TUCANA; 88 | } else if (coin == AppConstant.COIN.ETH) { 89 | return CHANNEL.ETH; 90 | } 91 | } 92 | 93 | function getTimestamp(coin) { 94 | if (coin == AppConstant.COIN.USDC) { 95 | return "1717731635350000000"; 96 | } else if (coin == AppConstant.COIN.TUCANA) { 97 | return "1717730232981000000"; 98 | } else if (coin == AppConstant.COIN.ETH) { 99 | return "1717731004768000000"; 100 | } 101 | } 102 | 103 | function getMetadataAndPair(coin) { 104 | if (coin == AppConstant.COIN.USDC) { 105 | metadata = AppConstant.USDCMETADATAADDRESS; 106 | pair = Pair.INITIAUSDC; 107 | } else if (coin == AppConstant.COIN.ETH) { 108 | metadata = AppConstant.ETHMETADATAADRESS; 109 | pair = Pair.INITIAETH; 110 | } else { 111 | metadata = AppConstant.INITIAMETADATAADDRESS; 112 | } 113 | } 114 | 115 | export { 116 | formatDateNowToCustomFormat, 117 | generateTokenInfo, 118 | getChannel, 119 | getTimestamp, 120 | getMetadataAndPair, 121 | }; 122 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # INITIA DAILY ROUTINE BOT 2 | 3 | Initia testnet daily routine bot 4 | 5 | ## Prerequisite 6 | 7 | To run this bot you need to 8 | 9 | 1. Initia Testnet Account with > 30 INIT AND > 5 GAS Balance. 10 | 2. Node JS Installed. 11 | 12 | ## BOT Feature Overview 13 | 14 | This BOT automates various tasks for a given wallet address. Below is a detailed breakdown of the features and the sequence of operations it performs. 15 | 16 | Bot Feature 17 | 18 | 1. Send 1 Init to Other 19 | 2. Send 1 Init to Other (BLACKWING) 20 | 3. Send 1 Init to Other (NOON) 21 | 4. Send 1 Init to Other (TUCANA) 22 | 5. Send 1 Init to Other (INIT AI) 23 | 6. Send 1 Init to Other (MINIMOVE) 24 | 7. Send 1 Init to Other (MINIWASM) 25 | 8. Send 1 Init to Other (CIVITA) 26 | 9. Bridge 1 Init to (CIVITA) 27 | 10. Bridge 1 Init to (TUCANA) 28 | 11. Bridge 1 Init to (INIT AI) 29 | 12. Send 0.1 TIA to Other (NOON) (EXPERIMENTAL) 30 | 13. Send 1 USDC to Other (BLACKWING) (EXPERIMENTAL) 31 | 14. Send 5 TUC to Other (TUCANA) (EXPERIMENTAL) 32 | 15. Send 0.0001 ETH to Other (MINIMOVE) (EXPERIMENTAL) 33 | 16. Swap 1 INIT to USDC 34 | 17. Swap 1 INIT to TIA 35 | 18. Swap 1 INIT to TUC 36 | 19. Swap 1 INIT to ETH 37 | 20. Stake 1 INIT to Omninode Account 38 | 21. Stake 0.5 USDC / INITIA LP to Omninode Account 39 | 22. Stake 0.01 TIA / INITIA LP to Omninode Account 40 | 23. Stake 0.0001 ETH / INITIA LP to Omninode Account 41 | 24. Request Faucet for Tucana Account 42 | 25. Add 1 TUC to Tucana Liquidity PERP 43 | 26. Swap 1 INIT to USDC on TUCANA Account 44 | 27. Roll Civitia Dice 3x For Account 45 | 28. Claim Staking Reward on Omninode 46 | 29. Vote a proposal on Initia 47 | 30. Move 0.1 Initia Stakes from Omninode to Nodes.Guru 48 | 31. Add Liquidity INIT/USDC on Tucana Liquidity Pool 49 | 32. Generate Collection on Init AI 50 | 33. Mint NFT on Collection Assasin Holding blade NFT 51 | 52 | ## Set Up 53 | 54 | 1. Clone the repo or Download the latest release [Here](https://github.com/Widiskel/initia-daily-bot/releases) 55 | 2. cd to project directory 56 | 3. run `npm install` 57 | 4. run `cp account_tmp.js account.js` 58 | 5. modify your account address and private key on `account.js` 59 | 60 | ```js 61 | const account = [["WALLET ADDRESS", "PRIVATE KEY"]]; 62 | 63 | export { account }; 64 | ``` 65 | 66 | 6. run `cp user_config_tmp.js user_config.js` 67 | 68 | ## Configure Bot 69 | 70 | Bot now have so many feature, but your daily faucet is only 30 INITIA. Thats why now im provide the way to configure what feature you want to use. To choose what feature you want to use 71 | 72 | 1. Open `user_config.js`. 73 | 2. look at 74 | 75 | ```js 76 | // MORE TX CONFIG 77 | // const userConfig = Array.from({ length: 29 }, (_, i) => i + 1); 78 | 79 | // FOCUS EXP CONFIG 80 | // const userConfig = [9, 10, 11, 16, 17, 18, 19, 20, 21, 22, 23, 28, 29, 30, 24, 25, 26, 31, 27]; 81 | 82 | // USER CONFIG 83 | const userConfig = [ 84 | 9, 10, 11, 16, 17, 18, 19, 20, 21, 22, 23, 28, 29, 30, 24, 25, 26, 31, 27, 85 | ]; 86 | ``` 87 | 88 | 3. Modify the USER CONFIG, based on the bot feature number that you want to run. 89 | 90 | ## Running Bot 91 | 92 | - To do 1 time run execute `npm run start` 93 | - To do scheduler run execute `npm run schedule` (EXPERIMENTAL) 94 | 95 | ## Note 96 | 97 | This bot send token to my testnet address account, to change the address with yours, check the `src/utils/constant.js` and change the `RECEIVERWALLETADDRESS` with your address. 98 | 99 | ## UPDATE 100 | 101 | to update the bot, 102 | 103 | - if you clone the repo you can simply run `git pull` or `git pull --rebase`. 104 | - if you download from the release, just download new latest release. 105 | 106 | ## CONTRIBUTE 107 | 108 | Feel free to fork and contribute adding more feature thanks. 109 | 110 | ## SUPPORT 111 | 112 | want to support me for creating another bot ? 113 | buy me a coffee on 114 | 115 | EVM : `0x3fe6a02ab20de8bf34fefc106d72d7094c8c4404 116 | 117 | SOLANA : `3tE3Hs7P2wuRyVxyMD7JSf8JTAmEekdNsQWqAnayE1CN` 118 | -------------------------------------------------------------------------------- /src/module/tucana/tucana.js: -------------------------------------------------------------------------------- 1 | import * as initia from "@initia/initia.js"; 2 | import { AppConstant } from "../../utils/constant.js"; 3 | import { Initia } from "../initia/initia.js"; 4 | import { TucanaSigner } from "./operation/signer.js"; 5 | import { TucanaException } from "./exception/exception.js"; 6 | import { getTucanaFaucet } from "../../repository/tucana_repo.js"; 7 | 8 | class Tucana extends TucanaSigner { 9 | /** @param {Initia} initiaClass */ 10 | constructor(address, pk, initiaClass) { 11 | const chainId = "birdee-1"; 12 | const privateKeyBytes = Buffer.from(pk, "hex"); 13 | const key = new initia.RawKey(Uint8Array.from(privateKeyBytes)); 14 | const lcd = new initia.LCDClient( 15 | "https://maze-rest-c9796789-107d-49ab-b6de-059724d2a91d.ue1-prod.newmetric.xyz", 16 | { 17 | chainId: "birdee-1", 18 | gasPrices: "0.15utuc", 19 | gasAdjustment: "2.0", 20 | } 21 | ); 22 | const wallet = new initia.Wallet(lcd, key); 23 | 24 | super(wallet, lcd); 25 | this.address = address; 26 | this.pk = pk; 27 | this.chainId = chainId; 28 | this.privateKeyBytes = privateKeyBytes; 29 | this.key = key; 30 | this.lcd = lcd; 31 | this.wallet = wallet; 32 | 33 | /** @type {TucanaException} */ 34 | this.exception = new TucanaException(this); 35 | 36 | /** @type {Initia} */ 37 | this.initia = initiaClass; 38 | } 39 | 40 | async swap(oneWaySwap = false) { 41 | try { 42 | //Swap 1 Initia To USDC 43 | var args = [ 44 | "Ari0w69X9eSgBvo1sCsf52UCM8WEtsf7YupiNqom7hs8iFZu7rMJRPyo/OnsbG7e6VNi2s/uVfxfWUnnNZzNQX8=", 45 | initia.bcs.vector(initia.bcs.bool()).serialize([true, true]).toBase64(), 46 | initia.bcs.bool().serialize(true).toBase64(), 47 | initia.bcs.u64().serialize(100000).toBase64(), 48 | ]; 49 | 50 | const calculate = await this.initia.lcd.move.viewFunction( 51 | AppConstant.TUCANAMODULEADDRESS, 52 | "router", 53 | "calculate_multi_hops_swap_result", 54 | [], 55 | args 56 | ); 57 | // console.log(calculate); 58 | args.push(initia.bcs.u64().serialize(calculate.amount_out).toBase64()); 59 | 60 | const msg = new initia.MsgExecute(); 61 | msg.sender = this.address; 62 | msg.module_address = AppConstant.TUCANAMODULEADDRESS; 63 | msg.function_name = "multi_hops_swap"; 64 | msg.module_name = "router"; 65 | msg.type_args = []; 66 | msg.args = args; 67 | 68 | // console.log(msg); 69 | await this.initia 70 | .signAndBroadcast(msg) 71 | .then(() => { 72 | console.log( 73 | `Successfully Swap 1 Initia To ${ 74 | calculate.amount_out / 1000000 75 | } USDC for Address : ${this.address}` 76 | ); 77 | }) 78 | .catch((err) => { 79 | throw err; 80 | }); 81 | 82 | if (!oneWaySwap) { 83 | //SWAP Back USDC To Initia 84 | var backArgs = [ 85 | "Ari0w69X9eSgBvo1sCsf52UCM8WEtsf7YupiNqom7hs8iFZu7rMJRPyo/OnsbG7e6VNi2s/uVfxfWUnnNZzNQX8=", 86 | initia.bcs 87 | .vector(initia.bcs.bool()) 88 | .serialize([true, true]) 89 | .toBase64(), 90 | initia.bcs.bool().serialize(true).toBase64(), 91 | initia.bcs 92 | .u64() 93 | .serialize(Math.ceil((calculate.amount_out * 50) / 100)) 94 | .toBase64(), 95 | ]; 96 | 97 | const calculateBack = await this.initia.lcd.move.viewFunction( 98 | AppConstant.TUCANAMODULEADDRESS, 99 | "router", 100 | "calculate_multi_hops_swap_result", 101 | [], 102 | backArgs 103 | ); 104 | // console.log(calculate); 105 | backArgs.push( 106 | initia.bcs.u64().serialize(calculateBack.amount_out).toBase64() 107 | ); 108 | 109 | const backMsg = new initia.MsgExecute(); 110 | backMsg.sender = this.address; 111 | backMsg.module_address = AppConstant.TUCANAMODULEADDRESS; 112 | backMsg.function_name = "multi_hops_swap"; 113 | backMsg.module_name = "router"; 114 | backMsg.type_args = []; 115 | backMsg.args = backArgs; 116 | 117 | await this.initia 118 | .signAndBroadcast(backMsg) 119 | .then(() => { 120 | console.log( 121 | `Successfully Swap ${ 122 | Math.ceil((calculate.amount_out * 50) / 100) / 1000000 123 | } (50%) USDC To ${ 124 | calculateBack.amount_out / 1000000 125 | } INIT for Address : ${this.address}` 126 | ); 127 | }) 128 | .catch((err) => { 129 | throw err; 130 | }); 131 | } 132 | } catch (error) { 133 | console.log(error); 134 | this.exception.handlingError(error, "swapTucana"); 135 | } 136 | } 137 | 138 | async tucanaPerpAddLiquidity() { 139 | try { 140 | const msg = new initia.MsgExecute(); 141 | msg.module_address = AppConstant.TUCANAPERPMODULEADDRESS; 142 | msg.module_name = "router"; 143 | msg.function_name = "add_liquidity"; 144 | msg.sender = this.address; 145 | msg.args = [ 146 | initia.bcs 147 | .u64() 148 | .serialize(1 * 1000000) 149 | .toBase64(), 150 | initia.bcs 151 | .address() 152 | .serialize(AppConstant.TUCPERPMETADATAADDRESS) 153 | .toBase64(), 154 | initia.bcs.address().serialize(this.address).toBase64(), 155 | initia.bcs.u256().serialize(0).toBase64(), 156 | initia.bcs.u256().serialize(0).toBase64(), 157 | ]; 158 | 159 | // console.log(msg); 160 | 161 | await this.signAndBroadcast(msg) 162 | .then(() => { 163 | console.log( 164 | `Successfully Add 1 TUC to Tucana Liquidity PERP For Address ${this.address}` 165 | ); 166 | }) 167 | .catch((err) => { 168 | throw err; 169 | }); 170 | } catch (error) { 171 | this.exception.handlingError(error, "tucanaPerpAddLiquidity"); 172 | } 173 | } 174 | 175 | async requestFaucet() { 176 | try { 177 | await getTucanaFaucet(this.address); 178 | } catch (error) { 179 | this.exception.handlingError(error, "requestFaucet"); 180 | } 181 | } 182 | 183 | async tucanaPoolAddLiquidity() { 184 | try { 185 | const pool = await this.initia.lcd.move.viewFunction( 186 | AppConstant.TUCANAPOOLMODULEADDRESS, 187 | "position", 188 | "position_metadata", 189 | undefined, 190 | [ 191 | initia.bcs 192 | .address() 193 | .serialize(AppConstant.TUCANAINITIAUSDCPOSITIONADDRESS) 194 | .toBase64(), 195 | ] 196 | ); 197 | const position = await this.initia.lcd.move.viewFunction( 198 | AppConstant.TUCANAPOOLMODULEADDRESS, 199 | "pool", 200 | "get_position_amounts", 201 | undefined, 202 | [ 203 | initia.bcs 204 | .address() 205 | .serialize(AppConstant.TUCANAINITIAUSDCPOSITIONADDRESS) 206 | .toBase64(), 207 | ] 208 | ); 209 | 210 | // console.log(pool); 211 | // console.log(position); 212 | 213 | const msg = new initia.MsgExecute(); 214 | msg.module_address = AppConstant.TUCANAPOOLMODULEADDRESS; 215 | msg.module_name = "router"; 216 | msg.function_name = "open_position_with_liquidity_with_all"; 217 | msg.sender = this.address; 218 | msg.args = [ 219 | initia.bcs 220 | .address() 221 | .serialize(AppConstant.TUCANAINITIAUSDCLIQUIDITYADDRESS) 222 | .toBase64(), 223 | initia.bcs.u32().serialize(pool.tick_lower_index.bits).toBase64(), //tick lower 224 | initia.bcs.u32().serialize(pool.tick_upper_index.bits).toBase64(), //tick upper 225 | initia.bcs 226 | .u64() 227 | .serialize(0.01 * 1000000) 228 | .toBase64(), 229 | initia.bcs.u64().serialize(position[1]).toBase64(), 230 | initia.bcs.bool().serialize(true).toBase64(), 231 | ]; 232 | 233 | // console.log(msg); 234 | 235 | await this.initia 236 | .signAndBroadcast(msg) 237 | .then(() => { 238 | console.log( 239 | `Successfully Add 0.01 USDC LP to Tucana Liquidity POOL For Address ${this.address}` 240 | ); 241 | }) 242 | .catch((err) => { 243 | throw err; 244 | }); 245 | } catch (error) { 246 | console.log(error); 247 | this.exception.handlingError(error, "tucanaPoolAddLiquidity"); 248 | } 249 | } 250 | } 251 | export { Tucana }; 252 | -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | import { Civitia } from "./src/module/civitia/civitia.js"; 2 | import { InitAi } from "./src/module/init_ai/init_ai.js"; 3 | import { Initia } from "./src/module/initia/initia.js"; 4 | import { Tucana } from "./src/module/tucana/tucana.js"; 5 | import { BridgeID } from "./src/utils/enum/bridge.js"; 6 | import { COIN } from "./src/utils/enum/coin.js"; 7 | import { Pair } from "./src/utils/enum/pair.js"; 8 | 9 | /** 10 | * Initia daily bot configuration class. 11 | * 12 | * @class 13 | * Configuration class for configuring bot feature 14 | * 15 | * Author : Widiskel 16 | * 17 | */ 18 | class Config { 19 | constructor(initia, civitia, tucana, initAi, userConfig, address) { 20 | /** @type {Civitia} */ 21 | this.civitia = civitia; 22 | /** @type {Tucana} */ 23 | this.tucana = tucana; 24 | /** @type {Initia} */ 25 | this.initia = initia; 26 | /** @type {InitAi} */ 27 | this.initAi = initAi; 28 | /** @type {string} */ 29 | this.walletAddress = address; 30 | 31 | this.config = userConfig; 32 | } 33 | 34 | isInConfig = (number) => { 35 | return config.includes(number); 36 | }; 37 | 38 | async executeConfigCode(number) { 39 | return new Promise(async (resolve, reject) => { 40 | try { 41 | switch (number) { 42 | case 1: 43 | console.log( 44 | "1. Send 1 Init to Other for Account " + this.walletAddress 45 | ); 46 | await this.initia.sendOneInitToOther(); 47 | console.log(); 48 | break; 49 | case 2: 50 | console.log( 51 | "2. Send 1 Init to Other (BLACKWING) for Account " + 52 | this.walletAddress 53 | ); 54 | await this.initia.sendTokenToOtherLayer(BridgeID.BLACKWING); 55 | console.log(); 56 | break; 57 | case 3: 58 | console.log( 59 | "3. Send 1 Init to Other (NOON) for Account " + this.walletAddress 60 | ); 61 | await this.initia.sendTokenToOtherLayer(BridgeID.NOON); 62 | console.log(); 63 | break; 64 | case 4: 65 | console.log( 66 | "4. Send 1 Init to Other (TUCANA) for Account " + 67 | this.walletAddress 68 | ); 69 | await this.initia.sendTokenToOtherLayer(BridgeID.TUCANA); 70 | console.log(); 71 | break; 72 | case 5: 73 | console.log( 74 | "5. Send 1 Init to Other (INIT AI) for Account " + 75 | this.walletAddress 76 | ); 77 | await this.initia.sendTokenToOtherLayer(BridgeID.INITAI); 78 | console.log(); 79 | break; 80 | case 6: 81 | console.log( 82 | "6. Send 1 Init to Other (MINIMOVE) for Account " + 83 | this.walletAddress 84 | ); 85 | await this.initia.sendTokenToOtherLayer(BridgeID.MINIMOVE); 86 | console.log(); 87 | break; 88 | case 7: 89 | console.log( 90 | "7. Send 1 Init to Other (MINIWASM) for Account " + 91 | this.walletAddress 92 | ); 93 | await this.initia.sendTokenToOtherLayer(BridgeID.MINIWASM); 94 | console.log(); 95 | break; 96 | case 8: 97 | console.log( 98 | "8. Send 1 Init to Other (CIVITA) for Account " + 99 | this.walletAddress 100 | ); 101 | await this.initia.sendTokenToOtherLayer(BridgeID.CIVITA); 102 | console.log(); 103 | break; 104 | case 9: 105 | console.log( 106 | "9. Bridge 1 Init to (CIVITA) for Account " + this.walletAddress 107 | ); 108 | await this.initia.sendTokenToOtherLayer( 109 | BridgeID.CIVITA, 110 | COIN.INIT, 111 | 1, 112 | "bridge" 113 | ); 114 | console.log(); 115 | break; 116 | case 10: 117 | console.log( 118 | "10. Bridge 1 Init to (TUCANA) for Account " + this.walletAddress 119 | ); 120 | await this.initia.sendTokenToOtherLayer( 121 | BridgeID.TUCANA, 122 | COIN.INIT, 123 | 1, 124 | "bridge" 125 | ); 126 | console.log(); 127 | break; 128 | case 11: 129 | console.log( 130 | "11. Bridge 1 Init to (INIT AI) for Account " + this.walletAddress 131 | ); 132 | await this.initia.sendTokenToOtherLayer( 133 | BridgeID.INITAI, 134 | COIN.INIT, 135 | 1, 136 | "bridge" 137 | ); 138 | console.log(); 139 | break; 140 | case 12: 141 | console.log( 142 | "12. Send 0.1 TIA to Other (NOON) for Account " + 143 | this.walletAddress 144 | ); 145 | await this.initia.sendTokenToOtherLayer( 146 | BridgeID.NOON, 147 | COIN.TIA, 148 | 0.1, 149 | "transfer" 150 | ); 151 | console.log(); 152 | break; 153 | case 13: 154 | console.log( 155 | "13. Send 1 USDC to Other (BLACKWING) for Account " + 156 | this.walletAddress 157 | ); 158 | await this.initia.sendTokenToOtherLayer( 159 | BridgeID.BLACKWING, 160 | COIN.USDC, 161 | 1, 162 | "transfer" 163 | ); 164 | console.log(); 165 | break; 166 | case 14: 167 | console.log( 168 | "14. Send 5 TUC to Other (TUCANA) for Account " + 169 | this.walletAddress 170 | ); 171 | await this.initia.sendTokenToOtherLayer( 172 | BridgeID.TUCANA, 173 | COIN.TUCANA, 174 | 5, 175 | "transfer" 176 | ); 177 | console.log(); 178 | break; 179 | case 15: 180 | console.log( 181 | "15. Send 0.0001 ETH to Other (MINIMOVE) for Account " + 182 | this.walletAddress 183 | ); 184 | await this.initia.sendTokenToOtherLayer( 185 | BridgeID.MINIMOVE, 186 | COIN.ETH, 187 | 0.0001, 188 | "transfer" 189 | ); 190 | console.log(); 191 | break; 192 | case 16: 193 | console.log( 194 | "16. Swap 1 INIT to USDC for Account " + this.walletAddress 195 | ); 196 | await this.initia.swap(false, Pair.INITIAUSDC); 197 | console.log(); 198 | break; 199 | case 17: 200 | console.log( 201 | "17. Swap 1 INIT to TIA for Account " + this.walletAddress 202 | ); 203 | await this.initia.swap(false, Pair.INITIATIA); 204 | console.log(); 205 | break; 206 | case 18: 207 | console.log( 208 | "18. Swap 1 INIT to TUC for Account " + this.walletAddress 209 | ); 210 | await this.initia.swap(false, Pair.INITIATUC); 211 | console.log(); 212 | break; 213 | case 19: 214 | console.log( 215 | "19. Swap 1 INIT to ETH for Account " + this.walletAddress 216 | ); 217 | await this.initia.swap(false, Pair.INITIAETH); 218 | console.log(); 219 | break; 220 | case 20: 221 | console.log( 222 | "20. Stake 0.1 INIT to Omninode Account " + this.walletAddress 223 | ); 224 | await this.initia.stakeInit(); 225 | console.log(); 226 | break; 227 | case 21: 228 | console.log( 229 | "21. Stake 0.5 USDC / INITIA LP to Omninode Account " + 230 | this.walletAddress 231 | ); 232 | await this.initia.stakeInit(Pair.INITIAUSDC); 233 | console.log(); 234 | break; 235 | case 22: 236 | console.log( 237 | "22. Stake 0.01 TIA / INITIA LP to Omninode Account " + 238 | this.walletAddress 239 | ); 240 | await this.initia.stakeInit(Pair.INITIAUSDC); 241 | console.log(); 242 | break; 243 | case 23: 244 | console.log( 245 | "23. Stake 0.0001 ETH / INITIA LP to Omninode Account " + 246 | this.walletAddress 247 | ); 248 | await this.initia.stakeInit(Pair.INITIAETH); 249 | console.log(); 250 | break; 251 | case 24: 252 | console.log("24. Request Faucet for Tucana " + this.walletAddress); 253 | await this.tucana.requestFaucet(this.walletAddress); 254 | console.log(); 255 | break; 256 | case 25: 257 | console.log( 258 | "25. Add 1 TUC to Tucana Liquidity PERP " + this.walletAddress 259 | ); 260 | await this.tucana.tucanaPerpAddLiquidity(); 261 | console.log(); 262 | break; 263 | case 26: 264 | console.log( 265 | "26. Swap 1 INIT to USDC on TUCANA Account " + this.walletAddress 266 | ); 267 | await this.tucana.swap(); 268 | console.log(); 269 | break; 270 | case 27: 271 | console.log( 272 | "27. Roll Civitia Dice 3x For Account " + this.walletAddress 273 | ); 274 | for (let x = 0; x < 3; x++) { 275 | await this.civitia.rollDice(); 276 | console.log(); 277 | } 278 | break; 279 | case 28: 280 | console.log( 281 | "28. Claim Staking Reward on Omninode for Account " + 282 | this.walletAddress 283 | ); 284 | await this.initia.claimStakingReward(); 285 | console.log(); 286 | break; 287 | case 29: 288 | console.log( 289 | "29. Vote a proposal for Account " + this.walletAddress 290 | ); 291 | await this.initia.vote(); 292 | console.log(); 293 | break; 294 | case 30: 295 | console.log( 296 | "30. Move Initia Stakes from Omninode to Nodes.Guru for Account " + 297 | this.walletAddress 298 | ); 299 | await this.initia.moveStake(); 300 | console.log(); 301 | break; 302 | case 31: 303 | console.log( 304 | "31. Add Liquidity INIT/USDC on Tucana Liquidity Pool for Account " + 305 | this.walletAddress 306 | ); 307 | await this.tucana.tucanaPoolAddLiquidity(); 308 | console.log(); 309 | break; 310 | case 32: 311 | console.log( 312 | "32. Generate Collection on Init AI for Account " + 313 | this.walletAddress 314 | ); 315 | await this.initAi.requestCreateCollection(); 316 | console.log(); 317 | break; 318 | case 33: 319 | console.log( 320 | "33. Mint NFT on Collection Assasin Holding blade NFT Account " + 321 | this.walletAddress 322 | ); 323 | await this.initAi.requestMint(); 324 | console.log(); 325 | break; 326 | default: 327 | console.log("Number " + number + " is not configured."); 328 | break; 329 | } 330 | } catch (error) { 331 | reject(error); 332 | } 333 | 334 | resolve(); 335 | }); 336 | } 337 | } 338 | 339 | export { Config }; 340 | -------------------------------------------------------------------------------- /src/module/initia/initia.js: -------------------------------------------------------------------------------- 1 | import * as initia from "@initia/initia.js"; 2 | import { AppConstant } from "../../utils/constant.js"; 3 | import { Pair } from "../../utils/enum/pair.js"; 4 | import { 5 | generateTokenInfo, 6 | getChannel, 7 | getMetadataAndPair, 8 | getTimestamp, 9 | } from "../../utils/helper.js"; 10 | import { COIN } from "../../utils/enum/coin.js"; 11 | import { InitiaSigner } from "./operation/signer.js"; 12 | import { BridgeID } from "../../utils/enum/bridge.js"; 13 | import { InitiaException } from "./exception/exception.js"; 14 | import { getLatestProposal } from "../../repository/initia_repo.js"; 15 | 16 | /** 17 | * Initia class. 18 | * 19 | * Author : Widiskel 20 | * 21 | */ 22 | class Initia extends InitiaSigner { 23 | constructor(address, pk) { 24 | const chainId = "initiation-1"; 25 | const privateKeyBytes = Buffer.from(pk, "hex"); 26 | const key = new initia.RawKey(Uint8Array.from(privateKeyBytes)); 27 | const lcd = new initia.LCDClient(`https://lcd.${chainId}.initia.xyz`, { 28 | chainId: chainId, 29 | gasPrices: `0.15${COIN.GAS}`, 30 | gasAdjustment: "2.0", 31 | }); 32 | const wallet = new initia.Wallet(lcd, key); 33 | 34 | super(wallet, lcd, chainId); 35 | this.chainId = this.chainId; 36 | this.key = key; 37 | this.lcd = lcd; 38 | this.wallet = wallet; 39 | this.address = address; 40 | 41 | /** @type {InitiaException} */ 42 | this.exception = new InitiaException(this); 43 | } 44 | 45 | async queryBalance(coin) { 46 | try { 47 | const balances = await this.lcd.bank.balance(this.address); 48 | const coinList = Object.keys(balances[0]._coins); 49 | coinList.forEach((coin) => { 50 | console.log( 51 | `${balances[0]._coins[coin].amount / 1000000} ${COIN.getCoinByValue( 52 | balances[0]._coins[coin].denom 53 | )}` 54 | ); 55 | }); 56 | 57 | console.log(); 58 | if (balances[0]._coins[coin]) { 59 | return balances[0]._coins[coin].amount; 60 | } else { 61 | return 0; 62 | } 63 | } catch (error) { 64 | console.error("Error during checking balance:", error); 65 | throw error; 66 | } 67 | } 68 | 69 | async checkGas() { 70 | try { 71 | const balances = await this.lcd.bank.balance(this.address); 72 | console.log(); 73 | if (balances[0]._coins[COIN.GAS]) { 74 | return balances[0]._coins[COIN.GAS].amount; 75 | } else { 76 | return 0; 77 | } 78 | } catch (error) { 79 | console.error("Error during checking balance:", error); 80 | throw error; 81 | } 82 | } 83 | 84 | async swap(oneWaySwap, pair) { 85 | try { 86 | const [liq, firstMetadata, secMetadata] = generateTokenInfo( 87 | pair, 88 | oneWaySwap, 89 | this.address 90 | ); 91 | 92 | //First 93 | var args = [ 94 | initia.bcs.address().serialize(liq).toBase64(), 95 | initia.bcs.address().serialize(firstMetadata).toBase64(), 96 | initia.bcs.u64().serialize(1000000).toBase64(), // 1 INITIA 97 | ]; 98 | const firstSim = await this.lcd.move.viewFunction( 99 | "0x1", 100 | "dex", 101 | "get_swap_simulation", 102 | [], 103 | args 104 | ); 105 | 106 | args.push( 107 | initia.bcs.option(initia.bcs.u64()).serialize(firstSim).toBase64() 108 | ); 109 | 110 | const firstMsg = new initia.MsgExecute(); 111 | firstMsg.function_name = "swap_script"; 112 | firstMsg.module_address = "0x1"; 113 | firstMsg.module_name = "dex"; 114 | firstMsg.sender = this.address; 115 | firstMsg.args = args; 116 | 117 | await this.signAndBroadcast(firstMsg) 118 | .then(() => { 119 | console.log( 120 | `Successfully Swap 1 To ${ 121 | firstSim / 1000000 122 | } with Pair ${pair} for Address : ${this.address}` 123 | ); 124 | console.log(); 125 | }) 126 | .catch((err) => { 127 | throw err; 128 | }); 129 | 130 | if (oneWaySwap != true) { 131 | // SECOND 132 | args = [ 133 | initia.bcs.address().serialize(liq).toBase64(), 134 | initia.bcs.address().serialize(secMetadata).toBase64(), 135 | initia.bcs.u64().serialize(firstSim).toBase64(), // SWAPPED TOKEN 136 | ]; 137 | const secondSim = await this.lcd.move.viewFunction( 138 | "0x1", 139 | "dex", 140 | "get_swap_simulation", 141 | [], 142 | args 143 | ); 144 | args.push( 145 | initia.bcs.option(initia.bcs.u64()).serialize(secondSim).toBase64() 146 | ); 147 | 148 | const secondMsg = new initia.MsgExecute(); 149 | secondMsg.function_name = "swap_script"; 150 | secondMsg.module_address = "0x1"; 151 | secondMsg.module_name = "dex"; 152 | secondMsg.sender = this.address; 153 | secondMsg.type_args = []; 154 | secondMsg.args = args; 155 | // console.log(secondMsg); 156 | 157 | await this.signAndBroadcast(secondMsg) 158 | .then(() => { 159 | console.log( 160 | `Successfully Swap Back ${pair} for Address : ${this.address}` 161 | ); 162 | }) 163 | .catch((err) => { 164 | throw err; 165 | }); 166 | } 167 | } catch (error) { 168 | await this.exception.handlingError(error, "swap", pair); 169 | } 170 | } 171 | 172 | async sendOneInitToOther() { 173 | try { 174 | console.log(`Sending 1 init to ${AppConstant.RECEIVERWALLETADDRESS}`); 175 | const msg = new initia.MsgSend( 176 | this.address, // sender address 177 | AppConstant.RECEIVERWALLETADDRESS, // recipient address 178 | "1000000uinit" // 1 Init 179 | ); 180 | 181 | await this.signAndBroadcast(msg) 182 | .then(() => { 183 | console.log( 184 | `Successfully Send 1 Init To ${AppConstant.RECEIVERWALLETADDRESS}` 185 | ); 186 | }) 187 | .catch((err) => { 188 | throw err; 189 | }); 190 | } catch (error) { 191 | throw this.exception.handlingError(error, "sendOneInitToOther"); 192 | } 193 | } 194 | 195 | async transferToken(bridgeId, coin = COIN.INIT, amount = 1) { 196 | try { 197 | console.log("Checking Balance"); 198 | var balance = await this.queryBalance(coin); 199 | 200 | console.log( 201 | `${coin} Balance : ${balance / 1000000} ${COIN.getCoinByValue( 202 | coin 203 | )} | required ${amount} ${COIN.getCoinByValue(coin)}` 204 | ); 205 | 206 | while (balance < amount * 1000000) { 207 | console.log("Swap and check Balance"); 208 | if (coin == COIN.ETH) { 209 | await this.swap(true, Pair.INITIAETH); 210 | } else if (coin == COIN.USDC) { 211 | await this.swap(true, Pair.INITIAUSDC); 212 | } else if (coin == COIN.TUCANA) { 213 | await this.swap(true, Pair.INITIATUC); 214 | } else if (coin == COIN.TIA) { 215 | await this.swap(true, Pair.INITIATIA); 216 | } 217 | balance = await this.queryBalance(coin); 218 | console.log( 219 | `${coin} Balance : ${balance / 1000000} ${COIN.getCoinByValue( 220 | coin 221 | )} | required ${amount} ${COIN.getCoinByValue(coin)}` 222 | ); 223 | } 224 | 225 | console.log( 226 | `Sending ${amount} ${coin} to ${ 227 | AppConstant.RECEIVERWALLETADDRESS 228 | } on ${BridgeID.getBridgeByValue(bridgeId)}` 229 | ); 230 | 231 | const msg = new initia.MsgTransfer( 232 | "transfer", 233 | getChannel(coin), 234 | initia.Coin.fromString(`${amount * 1000000}${coin}`), 235 | this.address, 236 | AppConstant.RECEIVERWALLETADDRESS, 237 | new initia.Height(0, 0), 238 | getTimestamp(coin) 239 | ); 240 | 241 | // console.log(msg); 242 | await this.signAndBroadcast(msg) 243 | .then(() => { 244 | console.log( 245 | `Successfully Send ${amount} ${COIN.getCoinByValue(coin)} To ${ 246 | AppConstant.RECEIVERWALLETADDRESS 247 | } From ${BridgeID.getBridgeByValue(bridgeId)} Layer` 248 | ); 249 | }) 250 | .catch((err) => { 251 | throw err; 252 | }); 253 | } catch (error) { 254 | throw error; 255 | } 256 | } 257 | 258 | async sendTokenDifferentLayer(bridgeId, coin = COIN.INIT, amount = 1) { 259 | try { 260 | console.log( 261 | `Sending ${amount} ${coin} to ${ 262 | AppConstant.RECEIVERWALLETADDRESS 263 | } on ${BridgeID.getBridgeByValue(bridgeId)}` 264 | ); 265 | const msg = new initia.MsgInitiateTokenDeposit(); 266 | msg.bridge_id = bridgeId; 267 | msg.amount = initia.Coin.fromString(`${amount * 1000000}${coin}`); 268 | msg.sender = this.address; 269 | msg.to = AppConstant.RECEIVERWALLETADDRESS; 270 | await this.signAndBroadcast(msg) 271 | .then(() => { 272 | console.log( 273 | `Successfully Send ${amount} ${COIN.getCoinByValue(coin)} To ${ 274 | AppConstant.RECEIVERWALLETADDRESS 275 | } From ${BridgeID.getBridgeByValue(bridgeId)} Layer` 276 | ); 277 | }) 278 | .catch((err) => { 279 | throw err; 280 | }); 281 | } catch (error) { 282 | throw error; 283 | } 284 | } 285 | 286 | async mixedRouteSwapTransfer(bridgeId, coin = COIN.INIT, amount) { 287 | const [metadata, pair] = getMetadataAndPair(coin); 288 | 289 | console.log(); 290 | console.log("Checking Balance"); 291 | var balance = await this.queryBalance(coin); 292 | 293 | console.log( 294 | `${coin} Balance : ${balance / 1000000} ${COIN.getCoinByValue( 295 | coin 296 | )} | required ${amount} ${COIN.getCoinByValue(coin)}` 297 | ); 298 | 299 | while (balance < amount * 1000000) { 300 | console.log("Swap and check Balance"); 301 | await this.swap(true, pair); 302 | balance = await this.queryBalance(coin); 303 | console.log( 304 | `${coin} Balance : ${balance / 1000000} ${COIN.getCoinByValue( 305 | coin 306 | )} | required ${amount} ${COIN.getCoinByValue(coin)}` 307 | ); 308 | } 309 | try { 310 | console.log( 311 | `Sending ${amount} ${coin} to ${ 312 | AppConstant.RECEIVERWALLETADDRESS 313 | } ${BridgeID.getBridgeByValue(bridgeId)}` 314 | ); 315 | const brigeArgs = [ 316 | initia.bcs.address().serialize(metadata).toBase64(), 317 | "AA==", 318 | initia.bcs 319 | .u64() 320 | .serialize(amount * 1000000) 321 | .toBase64(), 322 | ]; 323 | console.log(brigeArgs); 324 | const initToInit = await lcd.move.viewFunction( 325 | AppConstant.BRIDGEMODULEADDRESS, 326 | "swap_transfer", 327 | "mixed_route_swap_simulation", 328 | [], 329 | brigeArgs 330 | ); 331 | console.log(initToInit); 332 | 333 | const msg = new initia.MsgExecute(); 334 | msg.function_name = "mixed_route_swap_transfer"; 335 | msg.module_address = AppConstant.BRIDGEMODULEADDRESS; 336 | msg.module_name = "swap_transfer"; 337 | msg.sender = this.address; 338 | msg.type_args = []; 339 | msg.args = [ 340 | initia.bcs.address().serialize(metadata).toBase64(), 341 | "AA==", 342 | initia.bcs.u64().serialize(initToInit).toBase64(), 343 | initia.bcs.option(initia.bcs.u64()).serialize(initToInit).toBase64(), 344 | // initia.bcs.u64().serialize(bridgeId).toBase64(), 345 | initia.bcs.string().serialize(this.address).toBase64(), 346 | initia.bcs.string().serialize("transfer").toBase64(), 347 | initia.bcs.string().serialize(getChannel(coin)).toBase64(), 348 | "AA==", 349 | ]; 350 | 351 | await this.signAndBroadcast(msg) 352 | .then(() => { 353 | console.log( 354 | `Successfully Send ${amount} ${COIN.getCoinByValue(coin)} To ${ 355 | AppConstant.RECEIVERWALLETADDRESS 356 | } on ${BridgeID.getBridgeByValue(bridgeId)}` 357 | ); 358 | }) 359 | .catch((err) => { 360 | throw err; 361 | }); 362 | } catch (error) { 363 | throw error; 364 | } 365 | } 366 | 367 | async sendTokenToOtherLayer( 368 | bridgeId, 369 | coin = COIN.INIT, 370 | amount = 1, 371 | method = "" 372 | ) { 373 | try { 374 | if (method == "") { 375 | await this.sendTokenDifferentLayer(bridgeId, coin, amount); 376 | } else if (method == "bridge") { 377 | await this.bridge(bridgeId, coin, amount); 378 | } else if (method == "transfer") { 379 | await this.transferToken(bridgeId, coin, amount); 380 | } 381 | } catch (error) { 382 | await this.exception.handlingError(error, "sendTokenToOtherLayer", [ 383 | bridgeId, 384 | coin, 385 | amount, 386 | method, 387 | ]); 388 | } 389 | } 390 | 391 | async stakeInit() { 392 | try { 393 | console.log("Stake 1 INITIA to OmniNode for Account " + this.address); 394 | // Args INITIA > USDC 395 | const msg = new initia.MsgDelegate(); 396 | msg.delegator_address = this.address; 397 | msg.validator_address = AppConstant.OMNINODEVALIDATORADDRESS; 398 | msg.amount = initia.Coins.fromString("1000000uinit"); 399 | 400 | await this.signAndBroadcast(msg) 401 | .then(() => { 402 | console.log( 403 | `Successfully Stake 1 Initia to OmniNode for Address : ${this.address}` 404 | ); 405 | }) 406 | .catch((err) => { 407 | throw err; 408 | }); 409 | } catch (error) { 410 | await this.exception.handlingError(error, "stake", Pair.INIT); 411 | } 412 | } 413 | 414 | async stakeInitUsdc() { 415 | try { 416 | console.log( 417 | `Stake 0.5 USDC / INITIA LP to OmniNode for Account ${this.address}` 418 | ); 419 | 420 | await this.swap(true, Pair.INITIAUSDC) 421 | .then(async (data) => { 422 | const simulate = await lcd.move.viewFunction( 423 | AppConstant.BRIDGEMODULEADDRESS, 424 | "dex_utils", 425 | "single_asset_provide_liquidity_cal", 426 | [], 427 | [ 428 | initia.bcs 429 | .address() 430 | .serialize(AppConstant.INITIAUSDCLIQUIDITYADDRESS) 431 | .toBase64(), 432 | initia.bcs 433 | .address() 434 | .serialize(AppConstant.USDCMETADATAADDRESS) 435 | .toBase64(), 436 | initia.bcs 437 | .u64() 438 | .serialize(0.1 * 1000000) 439 | .toBase64(), 440 | ] 441 | ); 442 | 443 | const msg = new initia.MsgExecute(); 444 | msg.function_name = "single_asset_provide_stake"; 445 | msg.module_address = AppConstant.BRIDGEMODULEADDRESS; 446 | msg.sender = this.address; 447 | msg.module_name = "dex_utils"; 448 | msg.args = [ 449 | initia.bcs 450 | .address() 451 | .serialize(AppConstant.INITIAUSDCLIQUIDITYADDRESS) 452 | .toBase64(), 453 | initia.bcs 454 | .address() 455 | .serialize(AppConstant.USDCMETADATAADDRESS) 456 | .toBase64(), 457 | initia.bcs 458 | .u64() 459 | .serialize(0.5 * 1000000) 460 | .toBase64(), 461 | initia.bcs 462 | .option(initia.bcs.u64()) 463 | .serialize(simulate[0]) 464 | .toBase64(), 465 | initia.bcs 466 | .string() 467 | .serialize(AppConstant.OMNINODEVALIDATORADDRESS) 468 | .toBase64(), 469 | ]; 470 | 471 | await this.signAndBroadcast(msg) 472 | .then(() => { 473 | console.log( 474 | `Successfully Stake 0.5 USDC / INITIA LP to OmniNode for Address : ${this.address}` 475 | ); 476 | }) 477 | .catch((err) => { 478 | // console.log(err.response.data.message); 479 | throw err; 480 | }); 481 | }) 482 | .catch((err) => { 483 | throw err; 484 | }); 485 | } catch (error) { 486 | throw error; 487 | } 488 | } 489 | 490 | async stakeTiaInitia() { 491 | try { 492 | console.log( 493 | `Stake 0.01 TIA / INITIA LP to OmniNode for Account ${this.address}` 494 | ); 495 | 496 | await this.swap(true, Pair.INITIATIA) 497 | .then(async (data) => { 498 | const simulate = await lcd.move.viewFunction( 499 | AppConstant.BRIDGEMODULEADDRESS, 500 | "dex_utils", 501 | "single_asset_provide_liquidity_cal", 502 | [], 503 | [ 504 | initia.bcs 505 | .address() 506 | .serialize(AppConstant.INITIATIALIQUIDITYADDRESS) 507 | .toBase64(), 508 | initia.bcs 509 | .address() 510 | .serialize(AppConstant.TIAMETADATAADRESS) 511 | .toBase64(), 512 | initia.bcs 513 | .u64() 514 | .serialize(0.01 * 1000000) 515 | .toBase64(), 516 | ] 517 | ); 518 | 519 | const msg = new initia.MsgExecute(); 520 | msg.function_name = "single_asset_provide_stake"; 521 | msg.module_address = AppConstant.BRIDGEMODULEADDRESS; 522 | msg.sender = this.address; 523 | msg.module_name = "dex_utils"; 524 | msg.args = [ 525 | initia.bcs 526 | .address() 527 | .serialize(AppConstant.INITIATIALIQUIDITYADDRESS) 528 | .toBase64(), 529 | initia.bcs 530 | .address() 531 | .serialize(AppConstant.TIAMETADATAADRESS) 532 | .toBase64(), 533 | initia.bcs 534 | .u64() 535 | .serialize(0.01 * 1000000) 536 | .toBase64(), 537 | initia.bcs 538 | .option(initia.bcs.u64()) 539 | .serialize(simulate[0]) 540 | .toBase64(), 541 | initia.bcs 542 | .string() 543 | .serialize(AppConstant.OMNINODEVALIDATORADDRESS) 544 | .toBase64(), 545 | ]; 546 | 547 | await this.signAndBroadcast(msg) 548 | .then(() => { 549 | console.log( 550 | `Successfully Stake 0.01 TIA / INITIA LP to OmniNode for Address : ${this.address}` 551 | ); 552 | }) 553 | .catch((err) => { 554 | // console.log(err.response.data.message); 555 | throw err; 556 | }); 557 | }) 558 | .catch((err) => { 559 | throw err; 560 | }); 561 | } catch (error) { 562 | throw error; 563 | } 564 | } 565 | 566 | async stakeEthInitia() { 567 | try { 568 | console.log( 569 | `Stake 0.0001 ETH / INITIA LP to OmniNode for Account ${this.address}` 570 | ); 571 | 572 | await this.swap(true, Pair.INITIAETH) 573 | .then(async (data) => { 574 | const simulate = await lcd.move.viewFunction( 575 | AppConstant.BRIDGEMODULEADDRESS, 576 | "dex_utils", 577 | "single_asset_provide_liquidity_cal", 578 | [], 579 | [ 580 | initia.bcs 581 | .address() 582 | .serialize(AppConstant.INITIAETHLIQUIDITYADDRESS) 583 | .toBase64(), 584 | initia.bcs 585 | .address() 586 | .serialize(AppConstant.ETHMETADATAADRESS) 587 | .toBase64(), 588 | initia.bcs 589 | .u64() 590 | .serialize(0.0001 * 1000000) 591 | .toBase64(), 592 | ] 593 | ); 594 | 595 | const msg = new initia.MsgExecute(); 596 | msg.function_name = "single_asset_provide_stake"; 597 | msg.module_address = AppConstant.BRIDGEMODULEADDRESS; 598 | msg.sender = this.address; 599 | msg.module_name = "dex_utils"; 600 | msg.args = [ 601 | initia.bcs 602 | .address() 603 | .serialize(AppConstant.INITIAETHLIQUIDITYADDRESS) 604 | .toBase64(), 605 | initia.bcs 606 | .address() 607 | .serialize(AppConstant.ETHMETADATAADRESS) 608 | .toBase64(), 609 | initia.bcs 610 | .u64() 611 | .serialize(0.0001 * 1000000) 612 | .toBase64(), 613 | initia.bcs 614 | .option(initia.bcs.u64()) 615 | .serialize(simulate[0]) 616 | .toBase64(), 617 | initia.bcs 618 | .string() 619 | .serialize(AppConstant.OMNINODEVALIDATORADDRESS) 620 | .toBase64(), 621 | ]; 622 | 623 | await this.signAndBroadcast(msg) 624 | .then(() => { 625 | console.log( 626 | `Successfully Stake 0.01 ETH / INITIA LP to OmniNode for Address : ${this.address}` 627 | ); 628 | }) 629 | .catch((err) => { 630 | // console.log(err.response.data.message); 631 | throw err; 632 | }); 633 | }) 634 | .catch((err) => { 635 | throw err; 636 | }); 637 | } catch (error) { 638 | throw error; 639 | } 640 | } 641 | 642 | async stake(pair = Pair.INIT) { 643 | try { 644 | if (pair == Pair.INITIAUSDC) { 645 | await this.stakeInitUsdc(); 646 | } else if (pair == Pair.INITIATIA) { 647 | await this.stakeTiaInitia(); 648 | } else if (pair == Pair.INITIAETH) { 649 | await this.stakeEthInitia(); 650 | } else { 651 | await this.stakeInit(); 652 | } 653 | } catch (error) { 654 | await this.exception.handlingError(error, "stake", pair); 655 | } 656 | } 657 | 658 | async bridge(bridgeId, coin, amount) { 659 | try { 660 | console.log(`Bridging 1 init to ${AppConstant.RECEIVERWALLETADDRESS}`); 661 | const msg = new initia.MsgInitiateTokenDeposit( 662 | this.address, // sender address 663 | bridgeId, 664 | AppConstant.RECEIVERWALLETADDRESS, // recipient address 665 | initia.Coin.fromString(`${amount}${coin}`) 666 | ); 667 | 668 | // console.log(msg); 669 | 670 | await this.signAndBroadcast(msg) 671 | .then(() => { 672 | console.log( 673 | `Successfully Bridge 1 Init To ${ 674 | AppConstant.RECEIVERWALLETADDRESS 675 | } on ${BridgeID.getBridgeByValue(bridgeId)}` 676 | ); 677 | }) 678 | .catch((err) => { 679 | throw err; 680 | }); 681 | } catch (error) { 682 | await this.exception.handlingError(error, "bridge", [ 683 | bridgeId, 684 | coin, 685 | amount, 686 | ]); 687 | } 688 | } 689 | 690 | async vote() { 691 | try { 692 | const proposals = await getLatestProposal(); 693 | console.log( 694 | `Vote Proposal with Proposal ID ${proposals.id} (${proposals.title}), with Option YES` 695 | ); 696 | const msg = new initia.MsgVote( 697 | proposals.id, //proposal id 698 | this.address, 699 | 1 // vote optioin 700 | ); 701 | 702 | // console.log(msg); 703 | 704 | await this.signAndBroadcast(msg) 705 | .then(() => { 706 | console.log( 707 | `Successfully Vote a Proposal ID ${proposals.id} (${proposals.title})` 708 | ); 709 | }) 710 | .catch((err) => { 711 | throw err; 712 | }); 713 | } catch (error) { 714 | this.exception.handlingError(error, "vote"); 715 | } 716 | } 717 | 718 | async claimStakingReward() { 719 | try { 720 | console.log(`Claiming Staking reward on Omninode`); 721 | const msg = new initia.MsgWithdrawDelegatorReward( 722 | this.address, 723 | AppConstant.OMNINODEVALIDATORADDRESS 724 | ); 725 | 726 | await this.signAndBroadcast(msg) 727 | .then(() => { 728 | console.log( 729 | `Successfully Claim Staking Reward on Omninode Validator` 730 | ); 731 | }) 732 | .catch((err) => { 733 | throw err; 734 | }); 735 | } catch (error) { 736 | await this.exception.handlingError(error, "claimStakingReward"); 737 | } 738 | } 739 | 740 | async moveStake() { 741 | try { 742 | console.log(`Move Stakes From Omninode to Nodes.Guru`); 743 | const msg = new initia.MsgBeginRedelegate( 744 | this.address, 745 | AppConstant.OMNINODEVALIDATORADDRESS, 746 | AppConstant.NODESGURUVALIDATORADDRESS, 747 | `100000uinit` 748 | ); 749 | 750 | await this.signAndBroadcast(msg) 751 | .then(() => { 752 | console.log( 753 | `Successfully Move 0.1 INIT Stakes from Omninode to Nodes.Guru for Account ${this.address}` 754 | ); 755 | }) 756 | .catch((err) => { 757 | throw err; 758 | }); 759 | } catch (error) { 760 | await this.exception.handlingError(error, "moveStake"); 761 | } 762 | } 763 | } 764 | 765 | export { Initia }; 766 | --------------------------------------------------------------------------------