Skip to main content

Wallet

The wallet module is exposed as:

import Neon, { wallet, CONST } from "@cityofzion/neon-js";
const account = Neon.create.account(privateKey);
const alternative = new wallet.Account(privateKey);

Neon.is.address(string, CONST.DEFAULT_ADDRESS_VERSION);
wallet.isAddress(string, CONST.DEFAULT_ADDRESS_VERSION);

The wallet module contains methods for manipulating keys, creating signatures and verifying keys.


Classes

Account

class Account {
constructor(str: string);

WIF: string;
privateKey: string;
publicKey: string;
scriptHash: string;
address: string;

getPublicKey(encoded: boolean): string;
encrypt(keyphrase: string, scryptParams?: ScryptParams): Promise<this>;
decrypt(keyphrase: string, scryptParams?: ScryptParams): Promise<this>;
export(): WalletAccount;
}

The Account class is used to store and transform keys to its various formats. It can be instantiated with any key format and is smart enough to recognise the format and store it appropriately.

const a = Neon.create.Account("NNtxeX9UhKfHySqPQ29hQnZe22k8LwcFk1");
console.log(a.address); // NNtxeX9UhKfHySqPQ29hQnZe22k8LwcFk1

const b = new wallet.Account(
"9ab7e154840daca3a2efadaf0df93cd3a5b51768c632f5433f86909d9b994a69"
);
console.log(b.privateKey); // 9ab7e154840daca3a2efadaf0df93cd3a5b51768c632f5433f86909d9b994a69

The class enables us to easily retrieve keys in any derivable format without needing to remember any methods. However, we can only retrieve formats that can be derived from our input. For example, we cannot retrieve any formats other than address and scripthash from a because we instantiated it with an address. However, we can get any format from b because it was instantiated with a private key, which is the lowest level key available.

console.log(a.publicKey); // throws an error
console.log(b.publicKey); // prints the public key
console.log(b.address); // prints the address

The order of the keys are:

  1. encrypted (NEP2)
  2. privateKey / WIF
  3. publicKey
  4. scriptHash
  5. address

When you instantiate an Account with a key, you can retrieve any format that is below it in the list. For example, if we instantiate with a public key, we can get the publc key, scriptHash and address but not the private key.

The Account class can be instantiated from encrypted key, private key, public key, address or ScriptHash.

The encryptedKey is special as it is the lowest level key but requires the user to unlock it first before we can derive anything from it. This can be done through the decrypt method.

const c = new wallet.Account(
"6PYLHmDf6AjF4AsVtosmxHuPYeuyJL3SLuw7J1U8i7HxKAnYNsp61HYRfF"
);
console.log(c.encrypted); // encrypted key
console.log(c.address); // throws error
c.decrypt("city of zion").then(() => console.log(c.address)); // ALq7AWrhAueN6mJNqk6FHJjnsEoPRytLdW

You can encrypt the key by using the encrypt method. This is necessary if you want to export this key to a JSON file.

c.encrypt("new password").then(() => c.export());

This action will encrypt the private key with the provided password and replace any old NEP2 key.

Wallet

The Wallet class implements the NEP-6 convention which is a standard way set by NEO council on how to export keys in a JSON file. By doing this, we can move keys across different software providers without worry.

The Wallet class is essentially a collection of encrypted keys as well as the parameters used to encrypt them.

import Neon, { wallet } from "cityofzion/neon-js";

const a = new wallet.Account(
"6PYLHmDf6AjF4AsVtosmxHuPYeuyJL3SLuw7J1U8i7HxKAnYNsp61HYRfF"
);
const b = new wallet.Account(
"9ab7e154840daca3a2efadaf0df93cd3a5b51768c632f5433f86909d9b994a69"
);

// We create a wallet with name 'myWallet'. This is optional. The constructor is fine with no arguments.
const w1 = Neon.create.wallet({ name: "myWallet" });

// We generate a new Account and add it to the wallet
w1.addAccount();
// We add Account a to the wallet.
w1.addAccount(a);
// We add Account b to the wallet.
// Note that Account b is unencrypted and we can add this Account.
// The wallet will only error when trying to export an unencrypted key but does not prevent you from adding it.
w1.addAccount(b);

If your Account is not encrypted, it is still possible to add it to the Wallet. However, you will be unable to export the wallet until you encrypt it. The Wallet class provides some helper methods to quickly encrypt or decrypt all accounts.

// encrypting Account a will fail as it has not been unlocked.
w1.encryptAll("lousypassword").then((results) => console.log(results)); // returns [false, true]

// we will decrypt a (account at array position 0)
w1.decrypt(0, "city of zion").then((result) => console.log(result)); // returns true
// so we can encrypt everything with the same password
w1.encrypt(0, "lousypassword").then((result) => console.log(result)); // returns true

Similar methods for decryption (wallet.decrypt, wallet.decryptAll) is available. Encryption and decryption methods will return booleans which corresponds to the success or failure of the action.

Do note that decrypting does not mean that you cannot export the wallet. Decryption does not erase the old encryption but merely exposes your keys.

Once encrypted, you can proceed to export your wallet through export.

// exports as JSON string
const walletString = w1.export();

// Decryption failed for account[0]
w2.decryptAll("lousypassword").then((results) => console.log(results)); // returns [true, true]

Methods

Core

The core methods available are methods to convert key formats and generate new private keys.

Do note that the methods available is not the full set but only the minimum required. Generally, there is a method to retrieve the lower key from the higher key. For example, getPublicKeyFromPrivateKey exists but not getAddressFromPrivatKey or getPrivateKeyFromPublicKey. For conversions across all formats, you are encouraged to use the Account class.

const privateKey = Neon.create.privateKey();
const publicKey = Neon.get.publicKeyFromPrivateKey(publicKey);
const scriptHash = Neon.get.scriptHashFromPublicKey(publicKey);
const address = Neon.get.addressFromScriptHash(scriptHash);

const privateKey = wallet.generatePrivateKey();
const publicKey = wallet.getPublicKeyFromPrivateKey(privateKey);
const scriptHash = wallet.getScriptHashFromPublicKey(publicKey);
const address = wallet.getAddressFromScriptHash(scriptHash);

There are no checks in place for this set of methods to ensure the inputs are proper. Errors may be thrown when conversion fails for certain methods.

Components

These are methods used to convert JS objects into their respective neon-js implementation.

These methods are exposed for completeness but you are encouraged to use the constructors of the main objects Balance and Claims instead of manually recreating your own objects.

NEP2

The NEP2 standard describes the procedure to encrypt or decrypt a private key. The encryption method accepts either a WIF or HEX private key. However, the decryption method will always return a WIF for consistency.

Do note that the encryption/decryption takes a long time and might not work very nicely in browsers.

const privateKey = Neon.create.privateKey();
const WIF = Neon.get.WIFFromPrivateKey(privateKey);
const nep2Key = await Neon.encrypt(privateKey, "myPassword");
const decryptedKey = await Neon.decrypt(nep2Key, "myPassword");
WIF === decryptedKey; // true

const privateKey = wallet.generatePrivateKey();
const WIF = new wallet.Account(privateKey).WIF;
const nep2Key = await wallet.encrypt(WIF, "myPassword");
const decryptedKey = await wallet.decrypt(nep2Key, "myPassword");
WIF === decryptedKey; // true

Verify

Verification methods for the various key formats are available::

Neon.is.address(addrStr);
Neon.is.privateKey(keyStr);
Neon.is.encryptedKey(encryptedStr);
Neon.is.publicKey(publicKeyStr);
Neon.is.wif(wifStr);
Neon.is.scriptHash(scriptHashStr);

wallet.isAddress(addrStr);
wallet.isPrivateKey(keyStr);
wallet.isNEP2(keyStr);
wallet.isPublicKey(publicKeyStr);
wallet.isWIF(wifStr);
wallet.isScriptHash(scriptHashStr);

These methods will return a boolean regarding the key format. No errors will be thrown.