Skip to content

Commit fc8d80e

Browse files
authored
Merge pull request iron-fish#5198 from iron-fish/staging
Staging to master v2.5.0
2 parents d255420 + 66f7afe commit fc8d80e

File tree

241 files changed

+10569
-6357
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

241 files changed

+10569
-6357
lines changed

Cargo.lock

Lines changed: 21 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ homepage = "https://ironfish.network/"
1515
repository = "https://github.com/iron-fish/ironfish"
1616

1717
[profile.release]
18-
debug = true
18+
debug = true

config/eslint-config-ironfish/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ module.exports = {
6868
rules: {
6969
'ironfish/no-vague-imports': 'error',
7070
'ironfish/no-buffer-cmp': 'error',
71+
'ironfish/no-promise-race': 'error',
7172

7273
// Catches expressions that aren't assigned
7374
'@typescript-eslint/no-unused-expressions': [

config/eslint-plugin-ironfish/index.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,19 @@ module.exports.rules = {
4242
};
4343
},
4444
},
45+
"no-promise-race": {
46+
create(context) {
47+
return {
48+
MemberExpression: function (node) {
49+
if (node.object.name === 'Promise' && node.property.name === 'race') {
50+
context.report({
51+
node,
52+
message:
53+
"Promise.race leaks memory. You can work around it by using PromiseUtils.split to pass resolve/reject to other Promises. See https://github.com/nodejs/node/issues/17469#issuecomment-685216777 for more details.",
54+
});
55+
}
56+
},
57+
};
58+
},
59+
},
4560
};

ironfish-cli/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM node:20-bookworm as build
1+
FROM node:20-bookworm AS build
22
ENV PATH="/root/.cargo/bin:${PATH}"
33

44
RUN \

ironfish-cli/STYLE_GUIDE.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,20 @@ However, if prompting is required to complete a command, this means the user wil
6969

7070
## Output
7171

72+
When designing the output for a command, commands should output human readable output and not machine readable output. This means you should use components under the `ui` module such as `card`, `table`, or normal logs. It's fine if you only display a simplified version of the output. If the user needs the full data in machine readable format they can use the `--json` flag.
73+
74+
You can categorize commands in a few ways, and you will design their output differently depending on the purpose of the command. You have output commands (status, chain:blocks:info, wallet:transactions), operation commands (stop, wallet:rename).
75+
76+
### JSON Output
77+
78+
We want to support JSON output in all data commands. This will allow developers to use our CLI for basic automating purposes avoiding the need to set up an HTTP client.
79+
80+
If a command returns data it should have `static enableJsonFlag = true` and return an object with the JSON data in the command. The output JSON will automatically be colorized. See more here, https://oclif.io/docs/json/
81+
82+
It's OK to both return an object and use `log` even if JSON is not enabled. If you need custom logic and don't want to rely on returning the JSON, you can use `jsonEnabled()` and the `ui.json()` component to manually log colorized JSON.
83+
84+
This is not necessary for operation commands that perform actions and quit such as `wallet:rename`.
85+
7286
### Progress
7387

7488
Many commands need to run long running operations. The CLI should not look like it's unresponsive. For example, `ironfish wallet:post` posts a transaction and optionally sends it to the network:

ironfish-cli/bin/run

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,4 @@ if (Number(process.versions.node.split('.')[0]) < MIN_NODE_VERSION) {
2424
process.exit(1)
2525
}
2626

27-
require('@oclif/core')
28-
.run()
29-
.then(require('@oclif/core/flush'))
30-
.catch(require('@oclif/core/handle'))
27+
require('@oclif/core').execute({ dir: __dirname })

ironfish-cli/package.json

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ironfish",
3-
"version": "2.4.1",
3+
"version": "2.5.0",
44
"description": "CLI for running and interacting with an Iron Fish node",
55
"author": "Iron Fish <[email protected]> (https://ironfish.network)",
66
"main": "build/src/index.js",
@@ -23,8 +23,9 @@
2323
"node": ">=18"
2424
},
2525
"devDependencies": {
26-
"@oclif/test": "2.1.0",
26+
"@oclif/test": "4.0.4",
2727
"@types/blessed": "0.1.17",
28+
"@types/cli-progress": "3.11.6",
2829
"@types/inquirer": "8.2.5",
2930
"@types/node": "18.11.16",
3031
"@types/tar": "6.1.1",
@@ -34,7 +35,7 @@
3435
"eslint-plugin-deprecation": "2.0.0",
3536
"jest": "29.7.0",
3637
"jest-jasmine2": "29.7.0",
37-
"oclif": "3.7.2",
38+
"oclif": "4.14.0",
3839
"rimraf": "^3.0.2",
3940
"ts-jest": "29.1.1",
4041
"tsc-watch": "4.2.9",
@@ -58,15 +59,17 @@
5859
"oclif:version": "oclif readme && git add README.md"
5960
},
6061
"dependencies": {
61-
"@ironfish/rust-nodejs": "2.4.0",
62-
"@ironfish/sdk": "2.4.1",
63-
"@oclif/core": "3.27.0",
64-
"@oclif/plugin-autocomplete": "1.3.10",
65-
"@oclif/plugin-help": "5.1.12",
66-
"@oclif/plugin-not-found": "2.3.1",
67-
"@oclif/plugin-warn-if-update-available": "2.0.40",
62+
"@ironfish/rust-nodejs": "2.5.0",
63+
"@ironfish/sdk": "2.5.0",
64+
"@ledgerhq/hw-transport-node-hid": "6.29.1",
65+
"@oclif/core": "4.0.11",
66+
"@oclif/plugin-autocomplete": "3.1.6",
67+
"@oclif/plugin-help": "6.2.5",
68+
"@oclif/plugin-not-found": "3.2.10",
69+
"@oclif/plugin-warn-if-update-available": "3.1.8",
6870
"@types/keccak": "3.0.4",
6971
"@types/tar": "6.1.1",
72+
"@zondax/ledger-ironfish": "0.1.2",
7073
"axios": "1.7.2",
7174
"bech32": "2.0.0",
7275
"blessed": "0.1.81",
@@ -77,6 +80,8 @@
7780
"inquirer": "8.2.5",
7881
"json-colorizer": "2.2.2",
7982
"keccak": "3.0.4",
83+
"natural-orderby": "3.0.2",
84+
"string-width": "4.2.3",
8085
"supports-hyperlinks": "2.2.0",
8186
"tar": "6.1.11",
8287
"uuid": "8.3.2"
@@ -99,6 +104,12 @@
99104
"topics": {
100105
"wallet:scanning": {
101106
"description": "Turn on or off scanning for accounts"
107+
},
108+
"chain:blocks": {
109+
"description": "commands to look at blocks"
110+
},
111+
"chain:assets": {
112+
"description": "commands to look at assets"
102113
}
103114
}
104115
},

ironfish-cli/scripts/build-docker.sh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,14 @@ set -euo pipefail
33
cd "$(dirname "$0")/../.."
44

55
cat .gitignore - > .dockerignore <<EOF
6-
# do not send the .git directory to the Docker daemon to make builds faster
6+
# Do not send all the files from the .git directory to the Docker daemon to
7+
# make builds faster. Send only the strictly necessary files/directories to
8+
# make git know the hash of the HEAD.
79
.git
10+
!.git/HEAD
11+
!.git/refs
12+
!.git/objects
13+
.git/objects/*
814
EOF
915

1016
echo "Building Docker Image"

ironfish-cli/src/command.ts

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,15 @@ import {
99
InternalOptions,
1010
IronfishSdk,
1111
Logger,
12+
RpcClient,
1213
RpcConnectionError,
1314
} from '@ironfish/sdk'
14-
import { Command, Config } from '@oclif/core'
15-
import { CLIError, ExitError } from '@oclif/core/lib/errors'
15+
import { Command, Config, ux } from '@oclif/core'
16+
import { CLIError, ExitError } from '@oclif/core/errors'
1617
import {
18+
ConfigFlag,
1719
ConfigFlagKey,
20+
DataDirFlag,
1821
DataDirFlagKey,
1922
RpcAuthFlagKey,
2023
RpcHttpHostFlagKey,
@@ -33,6 +36,7 @@ import {
3336
VerboseFlagKey,
3437
} from './flags'
3538
import { IronfishCliPKG } from './package'
39+
import * as ui from './ui'
3640
import { hasUserResponseError } from './utils'
3741

3842
export type SIGNALS = 'SIGTERM' | 'SIGINT' | 'SIGUSR2'
@@ -68,16 +72,24 @@ export abstract class IronfishCommand extends Command {
6872
*/
6973
closing = false
7074

75+
client: RpcClient | null = null
76+
77+
public static baseFlags = {
78+
[VerboseFlagKey]: VerboseFlag,
79+
[ConfigFlagKey]: ConfigFlag,
80+
[DataDirFlagKey]: DataDirFlag,
81+
}
82+
7183
constructor(argv: string[], config: Config) {
7284
super(argv, config)
7385
this.logger = createRootLogger().withTag(this.ctor.id)
7486
}
7587

76-
abstract start(): Promise<void> | void
88+
abstract start(): Promise<unknown> | void
7789

78-
async run(): Promise<void> {
90+
async run(): Promise<unknown> {
7991
try {
80-
await this.start()
92+
return await this.start()
8193
} catch (error: unknown) {
8294
if (hasUserResponseError(error)) {
8395
this.log(error.codeMessage)
@@ -103,16 +115,15 @@ export abstract class IronfishCommand extends Command {
103115
} else {
104116
throw error
105117
}
118+
} finally {
119+
this.client?.close()
106120
}
107121

108122
this.exit(0)
109123
}
110124

111125
async init(): Promise<void> {
112-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any
113-
const commandClass = this.constructor as any
114-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
115-
const { flags } = await this.parse(commandClass)
126+
const { flags } = await this.parse(this.ctor)
116127

117128
// Get the flags from the flag object which is unknown
118129
const dataDirFlag = getFlag(flags, DataDirFlagKey)
@@ -220,6 +231,19 @@ export abstract class IronfishCommand extends Command {
220231
closeFromSignal(signal: NodeJS.Signals): Promise<unknown> {
221232
throw new Error(`Not implemented closeFromSignal: ${signal}`)
222233
}
234+
235+
// Override the built-in logJson method to implement our own colorizer that
236+
// works with default terminal colors instead of requiring a theme to be
237+
// configured.
238+
logJson(json: unknown): void {
239+
ux.stdout(ui.json(json))
240+
}
241+
242+
async connectRpc(forceLocal = false, forceRemote = false): Promise<RpcClient> {
243+
const client = await this.sdk.connectRpc(forceLocal, forceRemote)
244+
this.client = client
245+
return client
246+
}
223247
}
224248

225249
function getFlag(flags: unknown, flag: FLAGS): unknown {

0 commit comments

Comments
 (0)