* be fetched from the network.\r
*/\r
export class Account {\r
+ static #isInternal: boolean = false\r
#a: string\r
#pub: string\r
#prv: string | null\r
if (v?.constructor === Account) {\r
this.#rep = v\r
} else if (typeof v === 'string') {\r
- this.#rep = new Account(v)\r
+ this.#rep = Account.fromAddress(v)\r
} else {\r
throw new TypeError(`Invalid argument for account representative: ${v}`)\r
}\r
}\r
set weight (v) { this.#w = v ? BigInt(v) : undefined }\r
\r
- constructor (address: string, index?: number) {\r
- Account.validate(address)\r
+ constructor (address: string, publicKey: string, privateKey?: string, index?: number) {\r
+ if (!Account.#isInternal) {\r
+ throw new Error(`Account cannot be instantiated directly. Use factory methods instead.`)\r
+ }\r
if (index !== undefined && typeof index !== 'number') {\r
throw new TypeError(`Invalid index ${index} when creating Account ${address}`)\r
}\r
this.#a = address\r
- .replace(PREFIX, '')\r
- .replace(PREFIX_LEGACY, '')\r
- this.#pub = Account.#addressToKey(this.#a)\r
- this.#prv = null\r
+ this.#pub = publicKey\r
+ this.#prv = privateKey ?? null\r
this.#i = index\r
this.#s = new Safe()\r
+ Account.#isInternal = false\r
+ }\r
+\r
+ /**\r
+ * Instantiates an Account object from its Nano address.\r
+ *\r
+ * @param {string} address - Address of the account\r
+ * @param {number} [index] - Account number used when deriving the address\r
+ * @returns {Promise<Account>} The instantiated Account object\r
+ */\r
+ static fromAddress (address: string, index?: number): Account {\r
+ Account.#isInternal = true\r
+ Account.validate(address)\r
+ address = address\r
+ .replace(PREFIX, '')\r
+ .replace(PREFIX_LEGACY, '')\r
+ const publicKey = Account.#addressToKey(address)\r
+ const account = new this(address, publicKey, undefined, index)\r
+ return account\r
}\r
\r
/**\r
- * Asynchronously instantiates an Account object from its public key.\r
+ * Instantiates an Account object from its public key.\r
*\r
- * @param {string} key - Public key of the account\r
+ * @param {string} publicKey - Public key of the account\r
* @param {number} [index] - Account number used when deriving the key\r
* @returns {Promise<Account>} The instantiated Account object\r
*/\r
- static async fromPublicKey (key: string, index?: number): Promise<Account> {\r
- Account.#validateKey(key)\r
- const address = await Account.#keyToAddress(key)\r
- const account = new this(address, index)\r
+ static fromPublicKey (publicKey: string, index?: number): Account {\r
+ Account.#isInternal = true\r
+ Account.#validateKey(publicKey)\r
+ const address = Account.#keyToAddress(publicKey)\r
+ const account = new this(address, publicKey, undefined, index)\r
return account\r
}\r
\r
/**\r
- * Asynchronously instantiates an Account object from its private key.\r
+ * Instantiates an Account object from its private key. The\r
+ * corresponding public key will automatically be derived and saved.\r
*\r
- * @param {string} key - Private key of the account\r
+ * @param {string} privateKey - Private key of the account\r
* @param {number} [index] - Account number used when deriving the key\r
* @returns {Promise<Account>} A new Account object\r
*/\r
- static async fromPrivateKey (key: string, index?: number): Promise<Account> {\r
- Account.#validateKey(key)\r
- const { publicKey } = nacl.keyPair.fromSeed(hex.toBytes(key))\r
- const account = await Account.fromPublicKey(bytes.toHex(publicKey), index)\r
- account.#prv = key.toUpperCase()\r
+ static fromPrivateKey (privateKey: string, index?: number): Account {\r
+ Account.#isInternal = true\r
+ Account.#validateKey(privateKey)\r
+ const { publicKey } = nacl.keyPair.fromSeed(hex.toBytes(privateKey))\r
+ const account = Account.fromPublicKey(bytes.toHex(publicKey), index)\r
+ account.#prv = privateKey.toUpperCase()\r
+ return account\r
+ }\r
+\r
+ /**\r
+ * Asynchronously instantiates an Account object from its public and private\r
+ * keys.\r
+ *\r
+ * WARNING: The validity of the keys is checked, but they are assumed to have\r
+ * been precalculated. Whether they are an actual matching pair is NOT checked!\r
+ * If unsure, use `Account.fromPrivateKey(key)` instead.\r
+ *\r
+ * @param {string} publicKey - Public key of the account\r
+ * @param {string} privateKey - Private key of the account\r
+ * @param {number} [index] - Account number used when deriving the key\r
+ * @returns {Promise<Account>} The instantiated Account object\r
+ */\r
+ static fromKnownKeys (publicKey: string, privateKey: string, index?: number): Account {\r
+ Account.#isInternal = true\r
+ Account.#validateKey(publicKey)\r
+ Account.#validateKey(privateKey)\r
+ const account = Account.fromPublicKey(publicKey)\r
+ account.#prv = privateKey.toUpperCase()\r
return account\r
}\r
\r
this.#b = BigInt(balance)\r
this.#f = frontier\r
this.#r = BigInt(receivable)\r
- this.#rep = new Account(representative)\r
+ this.#rep = Account.fromAddress(representative)\r
this.#w = BigInt(weight)\r
}\r
\r
return bytes.toHex(keyBytes)\r
}\r
\r
- static async #keyToAddress (key: string): Promise<string> {\r
+ static #keyToAddress (key: string): string {\r
const publicKeyBytes = hex.toBytes(key)\r
const checksum = new Blake2b(5).update(publicKeyBytes).digest() as Uint8Array\r
checksum.reverse()\r
if (account.constructor === Account) {
this.account = account
} else if (typeof account === 'string') {
- this.account = new Account(account)
+ this.account = Account.fromAddress(account)
} else {
throw new TypeError('Invalid account')
}
constructor (sender: Account | string, balance: string, recipient: string, amount: string, representative: string, frontier: string, work?: string) {
super(sender)
this.previous = frontier
- this.representative = new Account(representative)
- this.link = new Account(recipient).publicKey
+ this.representative = Account.fromAddress(representative)
+ this.link = Account.fromAddress(recipient).publicKey
this.work = work ?? ''
const bigBalance = BigInt(balance)
constructor (recipient: string, balance: string, origin: string, amount: string, representative: string, frontier?: string, work?: string) {
super(recipient)
- this.previous = frontier ?? new Account(recipient).publicKey
- this.representative = new Account(representative)
+ this.previous = frontier ?? Account.fromAddress(recipient).publicKey
+ this.representative = Account.fromAddress(representative)
this.link = origin
this.work = work ?? ''
previous: string
representative: Account
balance: bigint
- link: string = new Account(BURN_ADDRESS).publicKey
+ link: string = Account.fromAddress(BURN_ADDRESS).publicKey
signature?: string
work?: string
constructor (account: string, balance: string, representative: string, frontier: string, work?: string) {
super(account)
this.previous = frontier
- this.representative = new Account(representative)
+ this.representative = Account.fromAddress(representative)
this.balance = BigInt(balance)
this.work = work ?? ''