Skip to content

Commit

Permalink
Merge pull request #5531 from iron-fish/staging
Browse files Browse the repository at this point in the history
STAGING -> MASTER
  • Loading branch information
NullSoldier authored Oct 9, 2024
2 parents 311abaf + bb17b38 commit 700c521
Show file tree
Hide file tree
Showing 69 changed files with 3,633 additions and 1,141 deletions.
21 changes: 11 additions & 10 deletions ironfish-cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ironfish",
"version": "2.7.0",
"version": "2.8.0",
"description": "CLI for running and interacting with an Iron Fish node",
"author": "Iron Fish <[email protected]> (https://ironfish.network)",
"main": "build/src/index.js",
Expand Down Expand Up @@ -43,34 +43,35 @@
"yarn": "^1.22.10"
},
"scripts": {
"build": "tsc -b",
"lint": "tsc -b && eslint --ext .ts,.tsx,.js,.jsx src/",
"build": "tsc -b tsconfig.build.json",
"build:tests": "tsc -b",
"lint": "yarn build && eslint --ext .ts,.tsx,.js,.jsx src/",
"lint:deprecated": "yarn lint --rule \"deprecation/deprecation: warn\"",
"lint:fix": "tsc -b && eslint --ext .ts,.tsx,.js,.jsx src/ --fix",
"lint:fix": "yarn build && eslint --ext .ts,.tsx,.js,.jsx src/ --fix",
"start:dev": "node start",
"start": "yarn build && yarn start:js",
"start:js": "cross-env OCLIF_TS_NODE=0 IRONFISH_DEBUG=1 node --expose-gc --inspect=:0 --inspect-publish-uid=http --enable-source-maps bin/run",
"test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest",
"test:coverage:html": "tsc -b tsconfig.test.json && cross-env NODE_OPTIONS=--experimental-vm-modules jest --testPathIgnorePatterns --coverage --coverage-reporters html",
"test:watch": "yarn clean && tsc -b && tsc -b tsconfig.test.json && cross-env NODE_OPTIONS=--experimental-vm-modules jest --watch --coverage false",
"test:coverage:html": "yarn build:tests && cross-env NODE_OPTIONS=--experimental-vm-modules jest --testPathIgnorePatterns --coverage --coverage-reporters html",
"test:watch": "yarn clean && yarn build && yarn build:tests && cross-env NODE_OPTIONS=--experimental-vm-modules jest --watch --coverage false",
"postpack": "rimraf oclif.manifest.json",
"clean": "rimraf build",
"prepack": "rimraf build && yarn build && oclif manifest && oclif readme",
"oclif:version": "oclif readme && git add README.md"
},
"dependencies": {
"@ironfish/rust-nodejs": "2.7.0",
"@ironfish/sdk": "2.7.0",
"@ironfish/sdk": "2.8.0",
"@ledgerhq/errors": "6.17.0",
"@ledgerhq/hw-transport-node-hid": "6.29.1",
"@oclif/core": "4.0.11",
"@oclif/plugin-help": "6.2.5",
"@oclif/plugin-not-found": "3.2.10",
"@oclif/plugin-warn-if-update-available": "3.1.8",
"@types/keccak": "3.0.4",
"@types/tar": "6.1.1",
"@zondax/ledger-ironfish": "0.1.2",
"@zondax/ledger-ironfish-dkg": "npm:@zondax/[email protected]",
"@zondax/ledger-js": "^1.0.1",
"@zondax/ledger-ironfish": "1.0.0",
"@zondax/ledger-js": "1.0.1",
"axios": "1.7.2",
"bech32": "2.0.0",
"blessed": "0.1.81",
Expand Down
119 changes: 75 additions & 44 deletions ironfish-cli/src/commands/wallet/chainport/send.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,20 @@ import * as ui from '../../../ui'
import {
ChainportBridgeTransaction,
ChainportNetwork,
ChainportVerifiedToken,
ChainportToken,
fetchChainportBridgeTransaction,
fetchChainportNetworkMap,
fetchChainportVerifiedTokens,
fetchChainportTokenPaths,
fetchChainportTokens,
} from '../../../utils/chainport'
import { isEthereumAddress } from '../../../utils/chainport/address'
import { promptCurrency } from '../../../utils/currency'
import { promptExpiration } from '../../../utils/expiration'
import { getExplorer } from '../../../utils/explorer'
import { selectFee } from '../../../utils/fees'
import { watchTransaction } from '../../../utils/transaction'

export class BridgeCommand extends IronfishCommand {
static description = `Use the Chainport bridge to bridge assets to EVM networks.`
static hidden = true

static flags = {
...RemoteFlags,
Expand Down Expand Up @@ -74,6 +74,15 @@ export class BridgeCommand extends IronfishCommand {
default: false,
description: 'Allow offline transaction creation',
}),
unsignedTransaction: Flags.boolean({
default: false,
description:
'Return a serialized UnsignedTransaction. Use it to create a transaction and build proofs but not post to the network',
}),
ledger: Flags.boolean({
default: false,
description: 'Send a transaction using a Ledger device',
}),
}

async start(): Promise<void> {
Expand All @@ -98,7 +107,7 @@ export class BridgeCommand extends IronfishCommand {
}
}

const { targetNetwork, from, to, amount, asset, assetData } =
const { targetNetwork, from, to, amount, asset, assetData, expiration } =
await this.getAndValidateInputs(client, networkId)

const rawTransaction = await this.constructBridgeTransaction(
Expand All @@ -110,8 +119,31 @@ export class BridgeCommand extends IronfishCommand {
amount,
asset,
assetData,
expiration,
)

if (flags.unsignedTransaction) {
const response = await client.wallet.buildTransaction({
account: from,
rawTransaction: RawTransactionSerde.serialize(rawTransaction).toString('hex'),
})
this.log('Unsigned Bridge Transaction')
this.log(response.content.unsignedTransaction)
this.exit(0)
}

if (flags.ledger) {
await ui.sendTransactionWithLedger(
client,
rawTransaction,
from,
flags.watch,
true,
this.logger,
)
this.exit(0)
}

await ui.confirmOrQuit()

const postTransaction = await client.wallet.postTransaction({
Expand Down Expand Up @@ -178,11 +210,19 @@ export class BridgeCommand extends IronfishCommand {
this.error('Invalid to ethereum address')
}

if (flags.expiration !== undefined && flags.expiration < 0) {
let expiration = flags.expiration

if (flags.unsignedTransaction && expiration === undefined) {
expiration = await promptExpiration({ logger: this.logger, client: client })
}

if (expiration !== undefined && expiration < 0) {
this.error('Expiration sequence must be non-negative')
}

const tokens = await fetchChainportVerifiedTokens(networkId)
ux.action.start('Fetching bridgeable assets')
const tokens = await fetchChainportTokens(networkId)
ux.action.stop()

const tokenNames = tokens.map(
(t, index) => `${index + 1}. ${t.name} (${t.symbol}) - ${t.web3_address}`,
Expand Down Expand Up @@ -211,9 +251,7 @@ export class BridgeCommand extends IronfishCommand {
assetId = asset.id
}

const asset: ChainportVerifiedToken | undefined = tokens.find(
(t) => t.web3_address === assetId,
)
const asset: ChainportToken | undefined = tokens.find((t) => t.web3_address === assetId)

if (!asset) {
this.logger.error(
Expand All @@ -224,8 +262,6 @@ export class BridgeCommand extends IronfishCommand {
this.exit(1)
}

const targetNetworks = asset.target_networks

const assetData = (
await client.wallet.getAsset({
account: from,
Expand All @@ -239,7 +275,7 @@ export class BridgeCommand extends IronfishCommand {
assetData.verification.status = 'verified'
}

const targetNetwork = await this.selectNetwork(networkId, targetNetworks, asset)
const targetNetwork = await this.selectNetwork(networkId, asset)

let amount
if (flags.amount) {
Expand Down Expand Up @@ -270,7 +306,7 @@ export class BridgeCommand extends IronfishCommand {
},
})
}
return { targetNetwork, from, to, amount, asset, assetData }
return { targetNetwork, from, to, amount, asset, assetData, expiration }
}

private async constructBridgeTransaction(
Expand All @@ -280,12 +316,21 @@ export class BridgeCommand extends IronfishCommand {
from: string,
to: string,
amount: bigint,
asset: ChainportVerifiedToken,
asset: ChainportToken,
assetData: RpcAsset,
expiration: number | undefined,
) {
const { flags } = await this.parse(BridgeCommand)

const txn = await fetchChainportBridgeTransaction(networkId, amount, to, network, asset)
ux.action.start('Fetching bridge transaction details')
const txn = await fetchChainportBridgeTransaction(
networkId,
amount,
asset.web3_address,
network.chainport_network_id,
to,
)
ux.action.stop()

const params: CreateTransactionRequest = {
account: from,
Expand All @@ -304,13 +349,14 @@ export class BridgeCommand extends IronfishCommand {
],
fee: flags.fee ? CurrencyUtils.encode(flags.fee) : null,
feeRate: flags.feeRate ? CurrencyUtils.encode(flags.feeRate) : null,
expiration: flags.expiration,
expiration,
}

let rawTransaction: RawTransaction
if (params.fee === null && params.feeRate === null) {
rawTransaction = await selectFee({
client,
account: from,
transaction: params,
logger: this.logger,
})
Expand All @@ -320,7 +366,7 @@ export class BridgeCommand extends IronfishCommand {
rawTransaction = RawTransactionSerde.deserialize(bytes)
}

this.displayTransactionSummary(txn, rawTransaction, from, to, asset, assetData, network)
this.displayTransactionSummary(txn, rawTransaction, from, to, assetData, network)

return rawTransaction
}
Expand All @@ -330,24 +376,18 @@ export class BridgeCommand extends IronfishCommand {
raw: RawTransaction,
from: string,
to: string,
asset: ChainportVerifiedToken,
assetData: RpcAsset,
network: ChainportNetwork,
) {
const bridgeAmount = CurrencyUtils.render(
BigInt(txn.bridge_output.amount) - BigInt(txn.bridge_fee.source_token_fee_amount ?? 0),
true,
asset.web3_address,
assetData.id,
assetData.verification,
)
const ironfishNetworkFee = CurrencyUtils.render(raw.fee, true)

const targetNetworkFee = CurrencyUtils.render(
BigInt(txn.gas_fee_output.amount),
true,
asset.web3_address,
assetData.verification,
)
const targetNetworkFee = CurrencyUtils.render(BigInt(txn.gas_fee_output.amount), true)

let chainportFee: string

Expand All @@ -367,7 +407,7 @@ export class BridgeCommand extends IronfishCommand {
chainportFee = CurrencyUtils.render(
BigInt(txn.bridge_fee.source_token_fee_amount ?? 0),
true,
asset.web3_address,
assetData.id,
assetData.verification,
)
}
Expand All @@ -377,7 +417,7 @@ export class BridgeCommand extends IronfishCommand {
From ${from}
To ${to}
Target Network ${network.name}
Target Network ${network.label}
Estimated Amount Received ${bridgeAmount}
Fees:
Expand All @@ -394,25 +434,13 @@ export class BridgeCommand extends IronfishCommand {

private async selectNetwork(
networkId: number,
targetNetworks: number[],
asset: ChainportVerifiedToken,
asset: ChainportToken,
): Promise<ChainportNetwork> {
ux.action.start('Fetching available networks')
const networks = await fetchChainportNetworkMap(networkId)
const networks = await fetchChainportTokenPaths(networkId, asset.id)
ux.action.stop()

const choices = Object.keys(networks).map((key) => {
return {
name: networks[key].label,
value: networks[key],
}
})

const filteredChoices = choices.filter((choice) =>
targetNetworks.includes(choice.value.chainport_network_id),
)

if (filteredChoices.length === 0) {
if (networks.length === 0) {
this.error(`No networks available for token ${asset.symbol} on Chainport`)
}

Expand All @@ -423,7 +451,10 @@ export class BridgeCommand extends IronfishCommand {
name: 'selection',
message: `Select the network you would like to bridge ${asset.symbol} to`,
type: 'list',
choices: filteredChoices,
choices: networks.map((network) => ({
name: network.label,
value: network,
})),
},
])

Expand Down
15 changes: 11 additions & 4 deletions ironfish-cli/src/commands/wallet/import.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import { AccountFormat, encodeAccountImport } from '@ironfish/sdk'
import { Args, Flags, ux } from '@oclif/core'
import { IronfishCommand } from '../../command'
import { RemoteFlags } from '../../flags'
import { LedgerError, LedgerSingleSigner } from '../../ledger'
import { checkWalletUnlocked, inputPrompt } from '../../ui'
import * as ui from '../../ui'
import { importFile, importPipe, longPrompt } from '../../ui/longPrompt'
import { importAccount } from '../../utils'
import { Ledger, LedgerError } from '../../utils/ledger'

export class ImportCommand extends IronfishCommand {
static description = `import an account`
Expand Down Expand Up @@ -118,9 +119,15 @@ export class ImportCommand extends IronfishCommand {

async importLedger(): Promise<string> {
try {
const ledger = new Ledger(this.logger)
await ledger.connect()
const account = await ledger.importAccount()
const ledger = new LedgerSingleSigner()

const account = await ui.ledger({
ledger,
message: 'Import Wallet',
approval: true,
action: () => ledger.importAccount(),
})

return encodeAccountImport(account, AccountFormat.Base64Json)
} catch (e) {
if (e instanceof LedgerError) {
Expand Down
3 changes: 1 addition & 2 deletions ironfish-cli/src/commands/wallet/mint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import { promptCurrency } from '../../utils/currency'
import { promptExpiration } from '../../utils/expiration'
import { getExplorer } from '../../utils/explorer'
import { selectFee } from '../../utils/fees'
import { sendTransactionWithLedger } from '../../utils/ledger'
import { watchTransaction } from '../../utils/transaction'

export class Mint extends IronfishCommand {
Expand Down Expand Up @@ -314,7 +313,7 @@ This will create tokens and increase supply for a given asset.`
)

if (flags.ledger) {
await sendTransactionWithLedger(
await ui.sendTransactionWithLedger(
client,
raw,
account,
Expand Down
Loading

0 comments on commit 700c521

Please sign in to comment.