Skip to content

Commit

Permalink
Merge pull request #107 from CudoVentures/cudos-dev
Browse files Browse the repository at this point in the history
Release v2.1.0 - 10.08.2022
  • Loading branch information
maptuhec authored Aug 10, 2022
2 parents 7342ef9 + 1010843 commit 8126048
Show file tree
Hide file tree
Showing 23 changed files with 257 additions and 71 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"ecmaVersion": "latest",
"sourceType": "module"
},
"ignorePatterns": ["*.test.js"],
"ignorePatterns": ["**/template/tests", "**/template/scripts"],
"rules": {
"space-before-function-paren": ["error", {
"anonymous": "never",
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ node_modules/
.vscode
**/.DS_Store
test-blast-init*/
packages/*/package-lock.json
2 changes: 1 addition & 1 deletion package-lock.json

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

117 changes: 93 additions & 24 deletions packages/blast-core/README.md

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions packages/blast-core/cmd/blast-cmd.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@ const { hideBin } = require('yargs/helpers')
const commands = require('./commands')
const BlastError = require('../utilities/blast-error')

const { customTasks } = require('../utilities/task')
const { getConfig } = require('../utilities/config-utils')

async function main() {
if (hideBin(process.argv)[0] !== 'init') {
getConfig()
}

await yargs(hideBin(process.argv))
.scriptName('blast')
.usage('Usage: $0 <command> [arguments] [command options]')
Expand All @@ -16,6 +23,7 @@ async function main() {
.command(commands.nodeInfo)
.command(commands.runInfo)
.command(commands.keysInfo)
.command(customTasks)
.demandCommand(1, 'No command specified!') // user must specify atleast one command
.recommendCommands()
.strict() // checks if the command or optional parameters are specified, if not - user friendly error
Expand Down
3 changes: 2 additions & 1 deletion packages/blast-core/cmd/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const { rustTestCmd } = require('./rusttest/rusttest.js')
const { runCmd } = require('./run/run.js')
const keys = require('./keys/keys.js')
const node = require('./node/node.js')
const { DEFAULT_DENOM } = require('../config/blast-constants')

const initInfo = {
command: 'init',
Expand Down Expand Up @@ -113,7 +114,7 @@ const keysInfo = {
alias: 't',
type: 'string',
required: true,
describe: 'The amount of tokens in acudos. Example: --tokens 100000'
describe: `The amount of tokens in ${DEFAULT_DENOM}. Example: --tokens 100000`
})
}, keys.keysFundCmd)
.demandCommand(1, 'No command specified!') // user must specify atleast one command
Expand Down
9 changes: 8 additions & 1 deletion packages/blast-core/cmd/init/init.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const fs = require('fs')
const fsExtra = require('fs-extra')
const path = require('path')
const { spawnSync } = require('child_process')

const { getPackageRootPath } = require('../../utilities/package-info')
const BlastError = require('../../utilities/blast-error')
Expand All @@ -15,8 +16,14 @@ async function initCmd(argv) {
} catch (error) {
throw new BlastError(`Error copying folder: ${error}`)
}
console.log(`Sample project initialized in ${argv.dir !== '.' ? argv.dir : process.cwd()}`)

console.log(`Success! Sample project initialized in ${argv.dir !== '.' ? argv.dir : process.cwd()}`)
console.log('Installing default dependencies...')
spawnSync(`npm install --prefix "${argv.dir}"`, {
stdio: 'inherit',
shell: true
})
console.log('Project is ready')
}

function handleCustomDirCreation(argv) {
Expand Down
11 changes: 6 additions & 5 deletions packages/blast-core/cmd/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ const {
const { checkNodeOnline } = require('../../utilities/get-node-status')

const JS_TESTS_FOLDER_NAME = 'tests'
const GLOBALS_PATH = path.join(getPackageRootPath(), 'lib/bre.js')

async function testCmd(argv) {
const TEST_DIR = path.join(getProjectRootPath(), JS_TESTS_FOLDER_NAME)
if (!fs.existsSync(TEST_DIR)) {
const testDir = path.join(getProjectRootPath(), JS_TESTS_FOLDER_NAME)
const globalsPath = path.join(getPackageRootPath(), 'lib/bre.js')

if (!fs.existsSync(testDir)) {
throw new BlastError('No tests folder found! Make sure to place your JavaScript tests in /' +
JS_TESTS_FOLDER_NAME)
}
Expand All @@ -23,8 +24,8 @@ async function testCmd(argv) {

process.env.BLAST_NETWORK = argv.network ?? ''
// here JEST uses only initial globals file setup. process.env (not globals) persist through the new spawned process
spawnSync(`npx --no jest ${TEST_DIR} ` +
`--setupFilesAfterEnv=${GLOBALS_PATH} --testTimeout=15000 ${silent} --detectOpenHandles`,
spawnSync(`npx --no --prefix "${getPackageRootPath()}" jest "${testDir}" ` +
`--setupFilesAfterEnv="${globalsPath}" --testTimeout=15000 ${silent} --detectOpenHandles`,
{
stdio: 'inherit',
shell: true
Expand Down
4 changes: 3 additions & 1 deletion packages/blast-core/config/blast-constants.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/* eslint-disable object-curly-newline */
module.exports = {
localNetwork: 'http://localhost:26657'
DEFAULT_DENOM: 'acudos',
GAS_AUTO: 'auto',
LOCAL_NETWORK: 'http://localhost:26657'
}
59 changes: 40 additions & 19 deletions packages/blast-core/lib/cudos-contract.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const {
GasPrice,
calculateFee
calculateFee,
parseCoins
} = require('cudosjs')
const path = require('path')
const fs = require('fs')
Expand All @@ -12,18 +13,27 @@ const {
getContractInfo,
getCodeDetails
} = require('../utilities/network-utils')
const {
DEFAULT_DENOM,
GAS_AUTO
} = require('../config/blast-constants')

function getGasFee(gasLimit, gasMultiplier) {
if (!gasLimit || gasLimit === GAS_AUTO) {
if (!gasMultiplier || gasMultiplier === GAS_AUTO) {
return GAS_AUTO
}
return gasMultiplier
}
return calculateFee(gasLimit, GasPrice.fromString(getGasPrice()))
}

module.exports.CudosContract = class CudosContract {
#label
#wasmPath
#codeId
#contractAddress
#creator
#gasPrice

constructor() {
this.#gasPrice = GasPrice.fromString(getGasPrice())
}

static constructLocal(label) {
const wasmPath = path.join(getProjectRootPath(), `artifacts/${label}.wasm`)
Expand Down Expand Up @@ -54,27 +64,33 @@ module.exports.CudosContract = class CudosContract {
}

// Uploads the contract's code to the network
async uploadCode(options = { signer: null }) {
async uploadCode(options = {
signer: null, gasLimit: null, gasMultiplier: null
}) {
if (this.#isUploaded()) {
throw new BlastError('Cannot upload contract that is already uploaded')
}
options.signer = options.signer ?? await getDefaultSigner()
const uploadTx = await this.#uploadContract(options.signer)
const uploadTx = await this.#uploadContract(options.signer, options.gasLimit, options.gasMultiplier)
this.#codeId = uploadTx.codeId
this.#creator = options.signer.address
return uploadTx
}

// Instantiates uploaded code without assigning the new contract to current contract object instance
async instantiate(msg, label, options = {
signer: null, funds: null
signer: null, funds: null, gasLimit: null, gasMultiplier: null
}) {
if (!this.#isUploaded()) {
throw new BlastError('Cannot instantiate contract that is not uploaded. ' +
'Contract\'s code must exist on the network before instantiating')
}
if (options.funds) {
options.funds = parseCoins(options.funds + DEFAULT_DENOM)
}
options.signer = options.signer ?? await getDefaultSigner()
const instantiateTx = await this.#instantiateContract(options.signer, this.#codeId, msg, label, options.funds)
const instantiateTx = await this.#instantiateContract(options.signer, this.#codeId, msg, label, options.funds,
options.gasLimit, options.gasMultiplier)
return instantiateTx
}

Expand All @@ -86,11 +102,15 @@ module.exports.CudosContract = class CudosContract {
throw new BlastError('Cannot deploy contract that is already uploaded. Only new contracts can be deployed. ' +
'Use "instantiate" for uploaded contracts')
}
if (options.funds) {
options.funds = parseCoins(options.funds + DEFAULT_DENOM)
}
options.signer = options.signer ?? await getDefaultSigner()
const uploadTx = await this.#uploadContract(options.signer)
const uploadTx = await this.#uploadContract(options.signer, GAS_AUTO, GAS_AUTO)
this.#codeId = uploadTx.codeId
this.#creator = options.signer.address
const instantiateTx = await this.#instantiateContract(options.signer, uploadTx.codeId, msg, label, options.funds)
const instantiateTx = await this.#instantiateContract(options.signer, uploadTx.codeId, msg, label, options.funds,
GAS_AUTO, GAS_AUTO)
this.#contractAddress = instantiateTx.contractAddress
this.#label = label
return {
Expand All @@ -99,12 +119,14 @@ module.exports.CudosContract = class CudosContract {
}
}

async execute(msg, signer = null) {
async execute(msg, signer = null, options = {
gasLimit: null, gasMultiplier: null
}) {
if (!this.#isDeployed()) {
throw new BlastError('Cannot use "execute()" on non-deployed contracts')
}
signer = signer ?? await getDefaultSigner()
const fee = calculateFee(1_500_000, this.#gasPrice)
const fee = getGasFee(options.gasLimit, options.gasMultiplier)
return signer.execute(signer.address, this.#contractAddress, msg, fee)
}

Expand Down Expand Up @@ -144,19 +166,18 @@ module.exports.CudosContract = class CudosContract {
return this.#creator
}

async #uploadContract(signer) {
// TODO: pass gasLimit as a param or read it from config
async #uploadContract(signer, gasLimit, gasMultiplier) {
const wasm = fs.readFileSync(this.#wasmPath)
const uploadFee = calculateFee(1_500_000, this.#gasPrice)
const uploadFee = getGasFee(gasLimit, gasMultiplier)
return signer.upload(
signer.address,
wasm,
uploadFee
)
}

async #instantiateContract(signer, codeId, msg, label, funds) {
const instantiateFee = calculateFee(500_000, this.#gasPrice)
async #instantiateContract(signer, codeId, msg, label, funds, gasLimit, gasMultiplier) {
const instantiateFee = getGasFee(gasLimit, gasMultiplier)
return signer.instantiate(
signer.address,
codeId,
Expand Down
4 changes: 2 additions & 2 deletions packages/blast-core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cudos-blast",
"version": "2.0.0",
"version": "2.1.0",
"license": "GNU GENERAL PUBLIC",
"repository": "github:CudoVentures/cudos-blast",
"description": "Cudos Blast is a Node.js CLI tool designed to work with the Cudos blockchain. It allows you to scaffold, compile and test your Rust smart contracts.",
Expand All @@ -22,7 +22,7 @@
"install-global": "npm install -g"
},
"engines": {
"node": ">=12.5.0"
"node": ">=14.15.0"
},
"dependencies": {
"axios": "^0.26.0",
Expand Down
4 changes: 3 additions & 1 deletion packages/blast-core/template/blast.config.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
/* eslint-disable object-curly-newline */
module.exports.config = {
addressPrefix: 'cudos',
gasPrice: '250acudos',
rustOptimizerVersion: '0.12.6',
gasPrice: '250acudos',

// optional parameners
gasLimit: 'auto',
gasMultiplier: 'auto',
additionalAccounts: 0,
customAccountBalances: 1000000000000000000,
networks: {
Expand Down
4 changes: 2 additions & 2 deletions packages/blast-core/template/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
},
"author": "",
"license": "ISC",
"dependencies": {
"@cosmjs/stargate": "^0.28.3"
"devDependencies": {
"cudos-blast": "2.0.0"
}
}
2 changes: 1 addition & 1 deletion packages/blast-core/template/tests/alpha.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const bre = require('cudos-blast')

describe('alpha contract', () => {
// Optional timeout. Default is 15000
jest.setTimeout(30 * 1000);
jest.setTimeout(30 * 1000)

const MSG_INIT = { count: 13 }
const MSG_INCREMENT = { increment: {} }
Expand Down
3 changes: 2 additions & 1 deletion packages/blast-core/utilities/account-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ const BlastError = require('./blast-error')

let localAccounts

// set localAccounts once and when needed
function getLocalAccounts() {
if (!localAccounts) {
if (typeof localAccounts === 'undefined') {
const configPath = path.join(getProjectRootPath(), 'local-accounts.json')
localAccounts = Object.values(require(configPath))
}
Expand Down
3 changes: 2 additions & 1 deletion packages/blast-core/utilities/blast-helper.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const { DEFAULT_DENOM } = require('../config/blast-constants')

async function delay(n) {
return new Promise(function(resolve) {
Expand All @@ -7,7 +8,7 @@ async function delay(n) {

function transferTokensByNameCommand(fromName, toName, amount) {
return `cudos-noded tx bank send ${fromName} $(cudos-noded keys show ${toName} --keyring-backend test -a) ` +
`${amount}acudos --keyring-backend test --chain-id cudos-network --yes`
`${amount}${DEFAULT_DENOM} --keyring-backend test --chain-id cudos-network --yes`
}

module.exports = {
Expand Down
5 changes: 3 additions & 2 deletions packages/blast-core/utilities/config-utils.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const fs = require('fs')
const path = require('path')
const BlastError = require('./blast-error')
const { localNetwork } = require('../config/blast-constants')
const { LOCAL_NETWORK } = require('../config/blast-constants')
const { getProjectRootPath } = require('./package-info')

// creating global Blast runtime environment to hold exposed core fuctions and possible plugins
Expand All @@ -28,7 +28,7 @@ function getNetwork(network) {
return config.networks[network]
}
// network is not passed - return the local network
return localNetwork
return LOCAL_NETWORK
}

function getGasPrice() {
Expand Down Expand Up @@ -73,6 +73,7 @@ function getRustOptimizerVersion() {
}

module.exports = {
getConfig: getConfig,
getGasPrice: getGasPrice,
getAddressPrefix: getAddressPrefix,
getAdditionalAccounts: getAdditionalAccounts,
Expand Down
14 changes: 9 additions & 5 deletions packages/blast-core/utilities/network-utils.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
const {
CosmWasmClient,
DirectSecp256k1HdWallet,
SigningCosmWasmClient
SigningCosmWasmClient,
GasPrice
} = require('cudosjs')
const { localNetwork } = require('../config/blast-constants')
const { LOCAL_NETWORK } = require('../config/blast-constants')
const {
getNetwork,
getAddressPrefix
getAddressPrefix,
getGasPrice
} = require('./config-utils')
const {
getLocalAccounts,
Expand All @@ -18,7 +20,9 @@ const nodeUrl = getNetwork(process.env.BLAST_NETWORK)

async function getSigner(mnemonic) {
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, { prefix: getAddressPrefix() })
const signer = await SigningCosmWasmClient.connectWithSigner(nodeUrl, wallet)
// gasPrice in signing client is considered only when auto gas is used
const signer = await SigningCosmWasmClient.connectWithSigner(
nodeUrl, wallet, { gasPrice: GasPrice.fromString(getGasPrice()) })
const address = (await wallet.getAccounts())[0].address
signer.address = address
return signer
Expand All @@ -33,7 +37,7 @@ async function getDefaultSigner() {
}

function getAccounts() {
return (nodeUrl === localNetwork ? getLocalAccounts() : getPrivateAccounts())
return (nodeUrl === LOCAL_NETWORK ? getLocalAccounts() : getPrivateAccounts())
}

async function getContractInfo(contractAddress) {
Expand Down
Loading

0 comments on commit 8126048

Please sign in to comment.