Skip to content

Commit

Permalink
Fixes after deps upgrade screw up (#47)
Browse files Browse the repository at this point in the history
Motivation is to fix the CLI that was broken after upgrading the NNS depdendencies which included breaking changes.
  • Loading branch information
lmuntaner authored Aug 30, 2024
1 parent 61e51e4 commit 9ce71a6
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 29 deletions.
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

A CLI to interact with the Internet Computer App on Ledger Nano S/X devices.

## Important Note

> [!WARNING]
> The CLI does NOT support tokens with different than eight decimals at the moment.
**Do NOT USE the cli to transfer ckETH or ckERC20 tokens.**

## Quick Start

- Install `node >= 18.13.0`.
Expand All @@ -28,4 +35,4 @@ To execute a command, you can use `npm run execute -- <args>`.
For example

- The command `ic-hardware-wallet --network https://nnsdapp.dfinity.network icp balance`.
- Would be `npm run execute -- --network https://nnsdapp.dfinity.network icp balance` for development.
- Would be `npm run execute -- --network http://127.0.0.1:4943 icp balance` for development.
42 changes: 21 additions & 21 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,10 @@
*/
import { Command, Option } from "commander";
import {
AccountIdentifier,
LedgerCanister,
GenesisTokenCanister,
GovernanceCanister,
GovernanceError,
ICP,
InsufficientAmountError,
InsufficientFundsError,
TokenAmount,
Vote,
Topic,
} from "@dfinity/nns";
Expand All @@ -30,7 +25,6 @@ import {
tryParseSnsNeuronId,
} from "./parsers";
import { Principal } from "@dfinity/principal";
import type { Secp256k1PublicKey } from "./ledger/secp256k1";
import {
assertLedgerVersion,
hasValidStake,
Expand All @@ -41,26 +35,28 @@ import {
nowInBigIntNanoSeconds,
isCurrentVersionSmallerThanFullCandidParser,
} from "./utils";
import {
CANDID_PARSER_VERSION,
FULL_CANDID_PARSER_VERSION,
HOTKEY_PERMISSIONS,
} from "./constants";
import { CANDID_PARSER_VERSION, HOTKEY_PERMISSIONS } from "./constants";
import { AnonymousIdentity, Identity } from "@dfinity/agent";
import { SnsGovernanceCanister, SnsNeuronId } from "@dfinity/sns";
import { fromNullable, toNullable } from "@dfinity/utils";
import { TokenAmountV2, fromNullable, toNullable } from "@dfinity/utils";
import {
encodeIcrcAccount,
IcrcAccount,
IcrcLedgerCanister,
} from "@dfinity/ledger-icrc";
import chalk from "chalk";
import {
AccountIdentifier,
LedgerCanister,
InsufficientFundsError,
} from "@dfinity/ledger-icp";

// Add polyfill for `window` for `TransportWebHID` checks to work.
import "node-window-polyfill/register";

// @ts-ignore (no types are available)
import fetch from "node-fetch";
import { Secp256k1PublicKey } from "./ledger/secp256k1";

(global as any).fetch = fetch;
// Add polyfill for `window.fetch` for agent-js to work.
Expand Down Expand Up @@ -112,7 +108,9 @@ async function snsListNeurons(canisterId: Principal) {
neurons.forEach((n) => {
const neuronId = fromNullable(n.id);
if (neuronId !== undefined) {
log(`Neuron ID: ${subaccountToHexString(neuronId.id)}`);
log(
`Neuron ID: ${subaccountToHexString(Uint8Array.from(neuronId.id))}`
);
} else {
log("Neuron ID: N/A");
}
Expand Down Expand Up @@ -199,7 +197,7 @@ async function snsDisburse({
to,
}: {
neuronId: SnsNeuronId;
amount?: TokenAmount;
amount?: TokenAmountV2;
to?: IcrcAccount;
} & SnsCallParams) {
const identity = await getIdentity();
Expand Down Expand Up @@ -301,7 +299,7 @@ async function icrcSendTokens({
amount,
to,
}: {
amount: TokenAmount;
amount: TokenAmountV2;
to: IcrcAccount;
canisterId: Principal;
}) {
Expand Down Expand Up @@ -344,7 +342,6 @@ async function getBalance() {

const ledger = LedgerCanister.create({
agent: await getCurrentAgent(new AnonymousIdentity()),
hardwareWallet: await isCurrentVersionSmallerThanFullCandidParser(identity),
});

const balance = await ledger.accountBalance({
Expand All @@ -360,11 +357,10 @@ async function getBalance() {
* @param to The account identifier in hex.
* @param amount Amount to send in e8s.
*/
async function sendICP(to: AccountIdentifier, amount: ICP) {
async function sendICP(to: AccountIdentifier, amount: TokenAmountV2) {
const identity = await getIdentity();
const ledger = LedgerCanister.create({
agent: await getCurrentAgent(identity),
hardwareWallet: await isCurrentVersionSmallerThanFullCandidParser(identity),
});

const blockHeight = await ledger.transfer({
Expand Down Expand Up @@ -403,7 +399,7 @@ async function showInfo(showOnDevice?: boolean) {
*
* @param amount Amount to stake in e8s.
*/
async function stakeNeuron(stake: ICP) {
async function stakeNeuron(stake: TokenAmountV2) {
const identity = await getIdentity();
const ledger = LedgerCanister.create({
agent: await getCurrentAgent(identity),
Expand All @@ -425,11 +421,15 @@ async function stakeNeuron(stake: ICP) {
});

ok(`Staked neuron with ID: ${stakedNeuronId}`);
} catch (error) {
} catch (error: unknown) {
if (error instanceof InsufficientAmountError) {
err(`Cannot stake less than ${error.minimumAmount} e8s`);
} else if (error instanceof InsufficientFundsError) {
err(`Your account has insufficient funds (${error.balance} e8s)`);
err(
`Your account has insufficient funds (${
(error as InsufficientFundsError).balance
} e8s)`
);
} else {
console.log(error);
}
Expand Down
10 changes: 6 additions & 4 deletions src/ledger/secp256k1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ export class Secp256k1PublicKey implements PublicKey {
return rawKey;
}

private readonly rawKey: ArrayBuffer;
private readonly derKey: DerEncodedPublicKey;
readonly rawKey: ArrayBuffer;
readonly derKey: DerEncodedPublicKey;

// `fromRaw` and `fromDer` should be used for instantiation, not this constructor.
private constructor(key: ArrayBuffer) {
Expand All @@ -107,9 +107,11 @@ export class Secp256k1PublicKey implements PublicKey {
if (!isHex) {
throw new Error(`${hexPubKey} is not a hex string.`);
}

if (hexPubKey.length < 130 || hexPubKey.length > 150) {
throw new Error(`The key must be >= 130 characters and <= 150 characters.`);
throw new Error(
`The key must be >= 130 characters and <= 150 characters.`
);
}

return hexPubKey;
Expand Down
7 changes: 4 additions & 3 deletions src/parsers.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { InvalidArgumentError } from "commander";
import { AccountIdentifier, ICPToken, Token, TokenAmount } from "@dfinity/nns";
import { AccountIdentifier } from "@dfinity/ledger-icp";
import { Principal } from "@dfinity/principal";
import { hexToSnsNeuronId } from "./utils";
import { SnsNeuronId } from "@dfinity/sns";
import { decodeIcrcAccount, IcrcAccount } from "@dfinity/ledger-icrc";
import { TokenAmountV2, ICPToken } from "@dfinity/utils";

export function tryParseInt(value: string): number {
const parsedValue = parseInt(value, 10);
Expand Down Expand Up @@ -64,9 +65,9 @@ export function tryParseSnsNeuronId(value: string): SnsNeuronId {
}
}

export function tryParseE8s(e8s: string): TokenAmount {
export function tryParseE8s(e8s: string): TokenAmountV2 {
try {
return TokenAmount.fromE8s({
return TokenAmountV2.fromUlps({
amount: tryParseBigInt(e8s),
token: ICPToken,
});
Expand Down

0 comments on commit 9ce71a6

Please sign in to comment.