Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NayNay] File Restructure: Base Class + Balance Restructure #207

Merged
merged 16 commits into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,15 @@ Version header format: `[version] Name - year-month-day (entropy-core compatibil
- new: 'src/flows/user-program-management/view.ts' - service file for pure functions of viewing user programs
- new: 'src/flows/user-program-management/helpers/utils.ts' - utility helper file for user program management specific methods
- new: './src/flows/user-program-management/remove.ts' - service file for removing user program pure function
- new: './src/common/base.ts' - base abstract class for new command classes
rh0delta marked this conversation as resolved.
Show resolved Hide resolved
- new: './src/balance' - new file structure for our CLI/TUI flows
- new: './src/balance/command.ts' - main entry file for balance command for tui/cli
- new: './src/balance/utils.ts' - utilities and helper methods for all things balance

### Changed
- folder name for user programs to match the kebab-case style for folder namespace
- updated SDK version to v0.2.3
- logger to handle nested contexts for better organization of logs

## [0.0.3] Blade - 2024-07-17 (entropy-core compatibility: 0.2.0)

Expand Down
18 changes: 18 additions & 0 deletions src/balance/command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import Entropy from "@entropyxyz/sdk"
import { BaseCommand } from "../common/base-command"
import * as BalanceUtils from "./utils"
import { FLOW_CONTEXT } from "./constants"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Questions:

  1. why did you split out utils?
    • is it because you don't want logger things in that level?
  2. why is FLOW_CONTEXT extracted?
    • it seems like that's not gonna be used by anything else, so ... premature optimization
    • can you just put it as a const at the top of this file / in the constructor?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Questions:

  1. why did you split out utils?

    • is it because you don't want logger things in that level?
  2. why is FLOW_CONTEXT extracted?

    • it seems like that's not gonna be used by anything else, so ... premature optimization
    • can you just put it as a const at the top of this file / in the constructor?
  1. splitting out utils was a decision made to have one unified file that contains the pure functions for the individual command, and remove any idea about having to do anything but make the request to retrieve balance (in this case) and return that data. the removal of logging here was a decision made to allow the command class take care of the "business logic" as my corporate colleagues would call it, which includes error handling/logging and logging of generic information.
  2. yeah it was kinda premature, i was under the impression there would be more shareable variables, and originally there was a use since we had the need for flow context in both the utils and command classes, but that has since changed so i will update and remove this file


export class BalanceCommand extends BaseCommand {
constructor (entropy: Entropy, endpoint: string) {
super(entropy, endpoint, FLOW_CONTEXT)
}

public async getBalance (address: string) {
const balance = await BalanceUtils.getBalance(this.entropy, address)

this.logger.log(`Current balance of ${address}: ${balance}`, `${BalanceCommand.name}`)

return `${balance.toLocaleString('en-US')} BITS`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really don't think this should have BITS, I don't even know about the tolocaleString.
We want this to be CLI first, so just raw JSON friendly formats like numbers, objects, not sentences (number + unit).

I could be wrong!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the utils method is the pure function that returns a number, my vision was that the controller/command file will handle how we want the data to be presented

}
}
1 change: 1 addition & 0 deletions src/balance/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const FLOW_CONTEXT = 'ENTROPY-BALANCE'
File renamed without changes.
24 changes: 24 additions & 0 deletions src/balance/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Entropy from "@entropyxyz/sdk";
import { BalanceInfo } from "./types";

const hexToBigInt = (hexString: string) => BigInt(hexString)

export async function getBalance (entropy: Entropy, address: string): Promise<number> {
const accountInfo = (await entropy.substrate.query.system.account(address)) as any
return parseInt(hexToBigInt(accountInfo.data.free).toString())
}

export async function getBalances (entropy: Entropy, addresses: string[]): Promise<BalanceInfo> {
const balanceInfo: BalanceInfo = {}
await Promise.all(addresses.map(async address => {
try {
const balance = await getBalance(entropy, address)

balanceInfo[address] = { balance }
} catch (error) {
balanceInfo[address] = { error: error.message }
}
}))

return balanceInfo
}
12 changes: 12 additions & 0 deletions src/common/base-command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import Entropy from "@entropyxyz/sdk";
import { EntropyLogger } from "./logger";

export abstract class BaseCommand {
protected logger: EntropyLogger
protected entropy: Entropy

constructor (entropy: Entropy, endpoint: string, flowContext: string) {
this.logger = new EntropyLogger(flowContext, endpoint)
this.entropy = entropy
}
}
2 changes: 1 addition & 1 deletion src/common/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ export class EntropyLogger {
this.winstonLogger.log({
level,
message: maskPayload(message),
context: context || this.context,
context: context ? `${this.context}:${context}` : this.context,
endpoint: this.endpoint,
description,
stack,
Expand Down
36 changes: 0 additions & 36 deletions src/flows/balance/balance.ts

This file was deleted.

9 changes: 6 additions & 3 deletions src/flows/balance/cli.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { BalanceCommand } from 'src/balance/command'
rh0delta marked this conversation as resolved.
Show resolved Hide resolved
import { initializeEntropy } from '../../common/initializeEntropy'
import * as config from '../../config'
import { getBalance } from './balance'
import { EntropyLogger } from 'src/common/logger'

// TO-DO: move entropy initialization and account retrieval to a shared container
// should remove the need to initialize entropy every time
export async function cliGetBalance ({ address, password, endpoint }) {
const logger = new EntropyLogger('CLI::CHECK_BALANCE', endpoint)
const storedConfig = await config.get()
Expand All @@ -17,8 +19,9 @@ export async function cliGetBalance ({ address, password, endpoint }) {
}

const entropy = await initializeEntropy({ keyMaterial: account.data, password, endpoint })
const balance = await getBalance(entropy, address)
const balanceCommand = new BalanceCommand(entropy, endpoint)
const balance = await balanceCommand.getBalance(address)

return `${balance.toLocaleString('en-US')} BITS`
return balance
}

11 changes: 7 additions & 4 deletions src/flows/balance/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { EntropyLogger } from "src/common/logger";
import { initializeEntropy } from "../../common/initializeEntropy"
import { print, getSelectedAccount } from "../../common/utils"
import { getBalance } from "./balance";
import { BalanceCommand } from "src/balance/command";

// TO-DO setup flow method to provide options to allow users to select account,
// TO-DO: setup flow method to provide options to allow users to select account,
// use external address, or get balances for all accounts in config
// TO-DO: move entropy initialization and account retrieval to a shared container
// should remove the need to initialize entropy every time
export async function checkBalance ({ accounts, selectedAccount: selectedAccountAddress }, options, logger: EntropyLogger) {
const FLOW_CONTEXT = 'CHECK_BALANCE'
const { endpoint } = options
Expand All @@ -13,7 +15,8 @@ export async function checkBalance ({ accounts, selectedAccount: selectedAccount
const selectedAccount = getSelectedAccount(accounts, selectedAccountAddress)
logger.log(selectedAccount, FLOW_CONTEXT)
const entropy = await initializeEntropy({ keyMaterial: selectedAccount.data, endpoint });
const balanceCommand = new BalanceCommand(entropy, endpoint)
const accountAddress = selectedAccountAddress
const freeBalance = await getBalance(entropy, accountAddress)
print(`Address ${accountAddress} has a balance of: ${freeBalance.toLocaleString('en-US')} BITS`)
const freeBalanceString = await balanceCommand.getBalance(accountAddress)
print(`Address ${accountAddress} has a balance of: ${freeBalanceString}`)
}
13 changes: 6 additions & 7 deletions tests/balance.test.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,31 @@
import test from 'tape'

import { getBalance, getBalances } from '../src/flows/balance/balance'
import { setupTest, charlieStashAddress as richAddress } from './testing-utils'
import * as BalanceUtils from 'src/balance/utils'

const networkType = 'two-nodes'

test('getBalance + getBalances', async (t) => {
const { run, entropy } = await setupTest(t, { networkType })

const { run, entropy, endpoint } = await setupTest(t, { networkType })
const newAddress = entropy.keyring.accounts.registration.address

/* getBalance */
const newAddressBalance = await run(
'getBalance (newSeed)',
getBalance(entropy, newAddress)
BalanceUtils.getBalance(entropy, newAddress)
)
t.equal(newAddressBalance, 0, 'newSeed balance = 0')

const richAddressBalance = await run(
'getBalance (richAddress)',
getBalance(entropy, richAddress)
BalanceUtils.getBalance(entropy, richAddress)
)
t.true(richAddressBalance > BigInt(10e10), 'richAddress balance >>> 0')

/* getBalances */
const balances = await run(
'getBalances',
getBalances(entropy, [newAddress, richAddress])
BalanceUtils.getBalances(entropy, [newAddress, richAddress])
)
t.deepEqual(
balances,
Expand All @@ -40,7 +39,7 @@ test('getBalance + getBalances', async (t) => {
const badAddresses = ['5Cz6BfUaxxXCA3jninzxdan4JdmC1NVpgkiRPYhXbhr', '5Cz6BfUaxxXCA3jninzxdan4JdmC1NVpgkiRPYhXbhrfnD']
const balancesWithNoGoodAddress = await run(
'getBalances::one good address',
getBalances(entropy, badAddresses)
BalanceUtils.getBalances(entropy, badAddresses)
)

badAddresses.forEach(addr => {
Expand Down
12 changes: 7 additions & 5 deletions tests/testing-utils/setup-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,18 @@ import { makeSeed, promiseRunner, sleep } from './'
interface SetupTestOpts {
configPath?: string
networkType?: string
seed?: string,
seed?: string
endpoint?: string
}
const NETWORK_TYPE_DEFAULT = 'two-nodes'
let counter = 0

export async function setupTest (t: Test, opts?: SetupTestOpts): Promise<{ entropy: Entropy; run: any }> {
export async function setupTest (t: Test, opts?: SetupTestOpts): Promise<{ entropy: Entropy; run: any; endpoint: string }> {
const {
configPath = `/tmp/entropy-cli-${Date.now()}_${counter++}.json`,
networkType = NETWORK_TYPE_DEFAULT,
seed = makeSeed()
seed = makeSeed(),
endpoint = 'ws://127.0.0.1:9944',
} = opts || {}

const run = promiseRunner(t)
Expand All @@ -45,11 +47,11 @@ export async function setupTest (t: Test, opts?: SetupTestOpts): Promise<{ entro
const keyring = new Keyring({ seed, debug: true })
const entropy = await initializeEntropy({
keyMaterial: keyring.getAccount(),
endpoint: 'ws://127.0.0.1:9944',
endpoint,
configPath
})

await run('entropy ready', entropy.ready)

return { entropy, run }
return { entropy, run, endpoint }
}
13 changes: 7 additions & 6 deletions tests/transfer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ import {
spinNetworkDown
} from './testing-utils'

import { getBalance } from '../src/flows/balance/balance'
import { initializeEntropy } from 'src/common/initializeEntropy'
import { charlieStashAddress, charlieStashSeed } from './testing-utils/constants'
import { transfer } from 'src/flows/entropyTransfer/transfer'
import * as BalanceUtils from 'src/balance/utils'

const networkType = 'two-nodes'
const endpoint = 'ws://127.0.0.1:9944'

test('Transfer', async (t) => {
/* Setup */
Expand All @@ -37,8 +38,8 @@ test('Transfer', async (t) => {
const naynayKeyring = new Keyring({ seed: naynaySeed, debug: true })
const charlieKeyring = new Keyring({ seed: charlieStashSeed, debug: true })

const entropy = await initializeEntropy({ keyMaterial: naynayKeyring.getAccount(), endpoint: 'ws://127.0.0.1:9944', })
const charlieEntropy = await initializeEntropy({ keyMaterial: charlieKeyring.getAccount(), endpoint: 'ws://127.0.0.1:9944', })
const entropy = await initializeEntropy({ keyMaterial: naynayKeyring.getAccount(), endpoint, })
const charlieEntropy = await initializeEntropy({ keyMaterial: charlieKeyring.getAccount(), endpoint, })
await run('entropy ready', entropy.ready)
await run('charlie ready', charlieEntropy.ready)

Expand All @@ -47,14 +48,14 @@ test('Transfer', async (t) => {
// Check Balance of new account
let naynayBalance = await run(
'getBalance (naynay)',
getBalance(entropy, recipientAddress)
BalanceUtils.getBalance(entropy, recipientAddress)
)

t.equal(naynayBalance, 0, 'naynay is broke')

let charlieBalance = await run(
'getBalance (charlieStash)',
getBalance(entropy, charlieStashAddress)
BalanceUtils.getBalance(entropy, charlieStashAddress)
)

t.equal(charlieBalance, 1e17, 'charlie got bank')
Expand All @@ -73,7 +74,7 @@ test('Transfer', async (t) => {
// Re-Check Balance of new account
naynayBalance = await run(
'getBalance (naynay)',
getBalance(entropy, recipientAddress)
BalanceUtils.getBalance(entropy, recipientAddress)
)

t.equal(naynayBalance, 1000 * 10e10, 'naynay is rolling in it!')
Expand Down
Loading