Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/dev' into mixmix/faucet-tidy
Browse files Browse the repository at this point in the history
  • Loading branch information
mixmix committed Oct 21, 2024
2 parents 24b4a81 + ee2709b commit 63604b6
Show file tree
Hide file tree
Showing 12 changed files with 123 additions and 202 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ Arguments:
address Account address whose balance you want to query
Options:
-p, --password <password> Password for the account
-e, --endpoint <endpoint> Runs entropy with the given endpoint and ignores network endpoints in
config. Can also be given a stored endpoint name from config eg: `entropy
--endpoint test-net`. (default: "ws://testnet.entropy.xyz:9944/", env:
Expand Down
6 changes: 1 addition & 5 deletions src/account/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { EntropyAccount } from "./main";
import { selectAndPersistNewAccount, addVerifyingKeyToAccountAndSelect } from "./utils";
import { ACCOUNTS_CONTENT } from './constants'
import * as config from '../config'
import { cliWrite, accountOption, endpointOption, loadEntropy, passwordOption } from "../common/utils-cli";
import { cliWrite, accountOption, endpointOption, loadEntropy } from "../common/utils-cli";

export function entropyAccountCommand () {
return new Command('account')
Expand All @@ -19,7 +19,6 @@ function entropyAccountCreate () {
return new Command('create')
.alias('new')
.description('Create a new entropy account from scratch. Output is JSON of form {name, address}')
.addOption(passwordOption())
.argument('<name>', 'A user friendly name for your new account.')
.addOption(
new Option(
Expand All @@ -44,7 +43,6 @@ function entropyAccountCreate () {
function entropyAccountImport () {
return new Command('import')
.description('Import an existing entropy account from seed. Output is JSON of form {name, address}')
.addOption(passwordOption())
.argument('<name>', 'A user friendly name for your new account.')
.argument('<seed>', 'The seed for the account you are importing')
.addOption(
Expand Down Expand Up @@ -72,7 +70,6 @@ function entropyAccountList () {
.alias('ls')
.description('List all accounts. Output is JSON of form [{ name, address, verifyingKeys }]')
.action(async () => {
// TODO: test if it's an encrypted account, if no password provided, throw because later on there's no protection from a prompt coming up
const storedConfig = await config.get()
const accounts = EntropyAccount.list(storedConfig)
cliWrite(accounts)
Expand All @@ -84,7 +81,6 @@ function entropyAccountList () {
function entropyAccountRegister () {
return new Command('register')
.description('Register an entropy account with a program')
.addOption(passwordOption())
.addOption(endpointOption())
.addOption(accountOption())
// Removing these options for now until we update the design to accept program configs
Expand Down
2 changes: 0 additions & 2 deletions src/account/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,11 @@ export class EntropyAccount extends EntropyBase {

const data = fullAccount
delete admin.pair
// const encryptedData = password ? passwordFlow.encrypt(data, password) : data

return {
name,
address: admin.address,
data
// data: encryptedData // TODO: replace once password input is added back
}
}

Expand Down
3 changes: 1 addition & 2 deletions src/balance/command.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { Command } from "commander";
import Entropy from "@entropyxyz/sdk";
import { cliWrite, endpointOption, loadEntropy, passwordOption } from "src/common/utils-cli";
import { cliWrite, endpointOption, loadEntropy } from "src/common/utils-cli";
import { EntropyBalance } from "./main";

export function entropyBalanceCommand () {
const balanceCommand = new Command('balance')
balanceCommand
.description('Command to retrieive the balance of an account on the Entropy Network')
.argument('address', 'Account address whose balance you want to query')
.addOption(passwordOption())
.addOption(endpointOption())
.action(async (address, opts) => {
const entropy: Entropy = await loadEntropy(address, opts.endpoint)
Expand Down
71 changes: 7 additions & 64 deletions src/common/initializeEntropy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import Entropy, { wasmGlobalsReady } from "@entropyxyz/sdk"
// TODO: fix importing of types from @entropy/sdk/keys
// @ts-ignore
import Keyring from "@entropyxyz/sdk/keys"
import inquirer from "inquirer"
import { decrypt, encrypt } from "../flows/password"
import * as config from "../config"
import { EntropyAccountData } from "../config/types"
import { EntropyLogger } from "./logger"
Expand All @@ -27,20 +25,19 @@ export function getKeyring (address?: string) {

interface InitializeEntropyOpts {
keyMaterial: MaybeKeyMaterial,
password?: string,
endpoint: string,
configPath?: string // for testing
}
type MaybeKeyMaterial = EntropyAccountData | string

// WARNING: in programatic cli mode this function should NEVER prompt users, but it will if no password was provided
// This is currently caught earlier in the code
export const initializeEntropy = async ({ keyMaterial, password, endpoint, configPath }: InitializeEntropyOpts): Promise<Entropy> => {
// WARNING: in programatic cli mode this function should NEVER prompt users

export const initializeEntropy = async ({ keyMaterial, endpoint, configPath }: InitializeEntropyOpts): Promise<Entropy> => {
const logger = new EntropyLogger('initializeEntropy', endpoint)
try {
await wasmGlobalsReady()

const { accountData, password: successfulPassword } = await getAccountDataAndPassword(keyMaterial, password)
const { accountData } = await getAccountData(keyMaterial)
// check if there is no admin account and no seed so that we can throw an error
if (!accountData.seed && !accountData.admin) {
throw new Error("Data format is not recognized as either encrypted or unencrypted")
Expand All @@ -52,12 +49,9 @@ export const initializeEntropy = async ({ keyMaterial, password, endpoint, confi
const store = await config.get(configPath)
store.accounts = store.accounts.map((account) => {
if (account.address === accountData.admin.address) {
let data = accountData
// @ts-ignore
if (typeof account.data === 'string' ) data = encrypt(accountData, successfulPassword)
account = {
...account,
data,
data: accountData,
}
}
return account
Expand All @@ -75,11 +69,9 @@ export const initializeEntropy = async ({ keyMaterial, password, endpoint, confi
const store = await config.get(configPath)
store.accounts = store.accounts.map((account) => {
if (account.address === store.selectedAccount) {
let data = newAccountData
if (typeof account.data === 'string') data = encrypt(newAccountData, successfulPassword)
const newAccount = {
...account,
data,
data: newAccountData,
}
return newAccount
}
Expand Down Expand Up @@ -122,65 +114,16 @@ export const initializeEntropy = async ({ keyMaterial, password, endpoint, confi


// NOTE: frankie this was prettier before I had to refactor it for merge conflicts, promise
async function getAccountDataAndPassword (keyMaterial: MaybeKeyMaterial, password?: string): Promise<{ password: string | null, accountData: EntropyAccountData }> {
async function getAccountData (keyMaterial: MaybeKeyMaterial): Promise<{ accountData: EntropyAccountData }> {
if (isEntropyAccountData(keyMaterial)) {
return {
password: null,
accountData: keyMaterial as EntropyAccountData
}
}

if (typeof keyMaterial !== 'string') {
throw new Error("Data format is not recognized as either encrypted or unencrypted")
}

/* Programmatic Mode */
if (password) {
const decryptedData = decrypt(keyMaterial, password)
if (!isEntropyAccountData(decryptedData)) {
throw new Error("Failed to decrypt keyMaterial or decrypted keyMaterial is invalid")
}
// @ts-ignore TODO: some type work here
return { password, accountData: decryptedData }
}

/* Interactive Mode */
let sucessfulPassword: string
let decryptedData
let attempts = 0

while (attempts < 3) {
const answers = await inquirer.prompt([
{
type: 'password',
name: 'password',
message: 'Enter password to decrypt keyMaterial:',
mask: '*',
}
])

try {
decryptedData = decrypt(keyMaterial, answers.password)
//@ts-ignore
if (!isEntropyAccountData(decryptedData)) {
throw new Error("Failed to decrypt keyMaterial or decrypted keyMaterial is invalid")
}

sucessfulPassword = answers.password
break
} catch (error) {
console.error("Incorrect password. Try again")
attempts++
if (attempts >= 3) {
throw new Error("Failed to decrypt keyMaterial after 3 attempts.")
}
}
}

return {
password: sucessfulPassword,
accountData: decryptedData as EntropyAccountData
}
}

function isEntropyAccountData (maybeAccountData: any) {
Expand Down
16 changes: 2 additions & 14 deletions src/common/utils-cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,6 @@ export function endpointOption () {
// NOTE: argParser is only run IF an option is provided, so this cannot be 'test-net'
}

export function passwordOption (description?: string) {
return new Option(
'-p, --password <password>',
description || 'Password for the account'
)
}

export function accountOption () {
const storedConfig = getConfigOrNull()

Expand Down Expand Up @@ -76,17 +69,12 @@ export function accountOption () {
// TODO: standardise whether selectedAccount is name or address.
}

export async function loadEntropy (addressOrName: string, endpoint: string, password?: string): Promise<Entropy> {
export async function loadEntropy (addressOrName: string, endpoint: string): Promise<Entropy> {
const accounts = getConfigOrNull()?.accounts || []
const selectedAccount = findAccountByAddressOrName(accounts, addressOrName)
if (!selectedAccount) throw new Error(`No account with name or address: "${addressOrName}"`)

// check if data is encrypted + we have a password
if (typeof selectedAccount.data === 'string' && !password) {
throw new Error('AuthError: This account requires a password, add --password <password>')
}

const entropy = await initializeEntropy({ keyMaterial: selectedAccount.data, endpoint, password })
const entropy = await initializeEntropy({ keyMaterial: selectedAccount.data, endpoint })
if (!entropy?.keyring?.accounts?.registration?.pair) {
throw new Error("Signer keypair is undefined or not properly initialized.")
}
Expand Down
5 changes: 4 additions & 1 deletion src/faucet/interaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import { EntropyFaucet } from "./main"
import { print } from "src/common/utils"

let chosenVerifyingKeys = []
const amount = "10000000000"
// Sending only 1e10 BITS does not allow user's to register after receiving funds
// there are limits in place to ensure user's are leftover with a certain balance in their accounts
// increasing amount send here, will allow user's to register right away
const amount = "20000000000"
// context for logging file
const FLOW_CONTEXT = 'ENTROPY_FAUCET_INTERACTION'
export async function entropyFaucet (entropy: Entropy, options, logger: EntropyLogger) {
Expand Down
2 changes: 2 additions & 0 deletions src/faucet/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ export const FAUCET_PROGRAM_MOD_KEY = '5GWamxgW4XWcwGsrUynqnFq2oNZPqNXQhMDfgNH9x
// this is differnt from tests because the fauce that is live now was lazily deployed without schemas
// TO-DO: update this when faucet is deployed properly
export const TESTNET_PROGRAM_HASH = '0x12af0bd1f2d91f12e34aeb07ea622c315dbc3c2bdc1e25ff98c23f1e61106c77'
// Hash with max send of 1e10
export const LOCAL_PROGRAM_HASH = '0x5fa0536818acaa380b0c349c8e887bf269d593a47e30c8e31de53a75d327f7b1'
61 changes: 0 additions & 61 deletions src/flows/password/index.ts

This file was deleted.

3 changes: 1 addition & 2 deletions src/sign/command.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { Command, /* Option */ } from 'commander'
import { cliWrite, accountOption, endpointOption, loadEntropy, passwordOption } from '../common/utils-cli'
import { cliWrite, accountOption, endpointOption, loadEntropy } from '../common/utils-cli'
import { EntropySign } from './main'

export function entropySignCommand () {
const signCommand = new Command('sign')
.description('Sign a message using the Entropy network. Output is a JSON { verifyingKey, signature }')
.argument('msg', 'Message you would like to sign (string)')
.addOption(passwordOption('Password for the source account (if required)'))
.addOption(endpointOption())
.addOption(accountOption())
// .addOption(
Expand Down
3 changes: 1 addition & 2 deletions src/transfer/command.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Command } from "commander"
import { accountOption, endpointOption, loadEntropy, passwordOption } from "src/common/utils-cli"
import { accountOption, endpointOption, loadEntropy } from "src/common/utils-cli"
import { EntropyTransfer } from "./main"

export function entropyTransferCommand () {
Expand All @@ -8,7 +8,6 @@ export function entropyTransferCommand () {
.description('Transfer funds between two Entropy accounts.') // TODO: name the output
.argument('destination', 'Account address funds will be sent to')
.argument('amount', 'Amount of funds to be moved')
.addOption(passwordOption('Password for the source account (if required)'))
.addOption(endpointOption())
.addOption(accountOption())
.action(async (destination, amount, opts) => {
Expand Down
Loading

0 comments on commit 63604b6

Please sign in to comment.