diff --git a/package-lock.json b/package-lock.json index 470f704..0c885d6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,18 @@ { "name": "banani", - "version": "1.0.0", + "version": "1.0.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "banani", - "version": "1.0.0", + "version": "1.0.4", "license": "MIT", "dependencies": { "blake2b": "^2.1.4" }, "devDependencies": { + "@types/blake2b": "^2.1.3", "esbuild": "^0.21.4", "prettier": "3.3.2", "typedoc": "^0.25.13", @@ -386,6 +387,13 @@ "node": ">=12" } }, + "node_modules/@types/blake2b": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@types/blake2b/-/blake2b-2.1.3.tgz", + "integrity": "sha512-MFCdX0MNxFBP/xEILO5Td0kv6nI7+Q2iRWZbTL/yzH2/eDVZS5Wd1LHdsmXClvsCyzqaZfHFzZaN6BUeUCfSDA==", + "dev": true, + "license": "MIT" + }, "node_modules/ansi-sequence-parser": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz", diff --git a/package.json b/package.json index 80aac99..41c5154 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "banani", - "version": "1.0.4", + "version": "1.0.5", "description": "JS/TS library for the Banano cryptocurrency in the style of bananopie", "main": "main.js", "scripts": { @@ -27,6 +27,7 @@ }, "homepage": "https://github.com/stjet/banani#readme", "devDependencies": { + "@types/blake2b": "^2.1.3", "esbuild": "^0.21.4", "prettier": "3.3.2", "typedoc": "^0.25.13", diff --git a/rpc.ts b/rpc.ts index 3abb2e6..7f3ecc7 100644 --- a/rpc.ts +++ b/rpc.ts @@ -212,7 +212,8 @@ export class RPCWithBackup extends RPC { return resp_json; } catch (e) { //increment (so try next RPC in provided list), if all RPCs exhausted (all failed), throw error - if (!this.rpc_urls[++i]) throw Error(e); + //typescript says e might not inherit from Error which is technically true, but in this case it always will be + if (!this.rpc_urls[++i]) throw Error(e instanceof Error ? e.toString() : "RPC call error"); } } } diff --git a/tsconfig.json b/tsconfig.json index 2c0ab3c..b0ab561 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,7 +6,9 @@ "typeRoots": ["./node_modules/@types"], "esModuleInterop": true, "skipLibCheck": true, - "forceConsistentCasingInFileNames": true + "forceConsistentCasingInFileNames": true, + "strict": true, + "noUnusedLocals": true }, "lib": ["ES2020"], "exclude": ["node_modules", ".build", "browser-main.ts"] diff --git a/util.ts b/util.ts index d4b2250..32eea56 100644 --- a/util.ts +++ b/util.ts @@ -1,3 +1,4 @@ +// @ts-ignore import * as nacl from "./tweetnacl_mod"; import blake2b from "blake2b"; import type { AddressPrefix, Address, BlockNoSignature, BlockHash } from "./rpc_types"; @@ -122,7 +123,7 @@ export function utf8_to_uint8array(utf8: string): Uint8Array { const BANANO_DECIMALS: number = 29; /** Do `rpc.DECIMALS = banani.NANO_DECIMALS` if using Nano. Putting the wrong amount of decimals in may result in LOSS OF FUNDS. */ -const NANO_DECIMALS: number = 30; +export const NANO_DECIMALS: number = 30; /** Does NOT mean whole number, can be decimal like "4.2001". Use instead of regular number since those lose precision when decimal */ export type Whole = `${number}`; //number can include non-base-10 formats... but whatever, we can assume users will pass in only base-10 because they are normal for the most part @@ -175,7 +176,7 @@ export function get_address_from_public_key(public_key: string, prefix: AddressP //the previously mentioned padding the front with 4 bits const encoded = uint8array_to_base32(hex_to_uint8array(`0${public_key}`)); //skip byte length assertions - const hashed = uint8array_to_base32(blake2b(5, null, null, null, true).update(hex_to_uint8array(public_key)).digest().reverse()); + const hashed = uint8array_to_base32(blake2b(5, undefined, undefined, undefined, true).update(hex_to_uint8array(public_key)).digest().reverse()); return `ban_${encoded}${hashed}` as Address; //fix for old versions of typescript or something } diff --git a/wallet.ts b/wallet.ts index 2902833..69f8b16 100644 --- a/wallet.ts +++ b/wallet.ts @@ -1,6 +1,6 @@ import * as util from "./util"; import type { AccountInfoRPC, AccountReceivableRPC, AccountReceivableThresholdRPC, AccountReceivableSourceRPC, Address, Block, BlockNoSignature, BlockSubtype, BlockHash } from "./rpc_types"; -import type { RPCInterface, RPC } from "./rpc"; +import type { RPCInterface } from "./rpc"; export type WorkFunction = (block_hash: BlockHash) => Promise; @@ -68,7 +68,10 @@ export class Wallet { const raw_send = util.whole_to_raw(amount, this.rpc.DECIMALS); const info = cached_account_info ?? (await this.get_account_info(undefined, true)); //this should be lazy. the true makes sure representative is included const pub_receive = util.get_public_key_from_address(to); - if (!representative) representative = info.representative; + if (representative === undefined) { + if (info.representative === undefined) throw Error("Missing field 'representative' in `cached_account_info`"); + representative = info.representative; + } const before_balance = BigInt(info.balance); const new_balance = before_balance - raw_send; if (new_balance < 0n) { @@ -86,7 +89,7 @@ export class Wallet { }; const s_block_hash = util.hash_block(block_ns); //block hash of the send block let work = undefined; - if (gen_work) work = await this.work_function(s_block_hash); + if (gen_work && this.work_function) work = await this.work_function(s_block_hash); const signature = util.sign_block_hash(this.private_key, s_block_hash); const block = { ...block_ns, signature, work }; return await this.send_process(block, "send"); @@ -106,12 +109,11 @@ export class Wallet { //doesn't matter if open or not, I think? const block_info = await this.rpc.get_block_info(block_hash); let before_balance = 0n; - if (!representative) representative = this.address; let previous; try { const info = await this.get_account_info(undefined, true); previous = info.frontier; - representative = info.representative; + if (!representative) representative = info.representative; before_balance = BigInt(info.balance); } catch (e) { //todo, check if error message is "Account not found" @@ -119,18 +121,19 @@ export class Wallet { //unopened account probably previous = "0".repeat(64); } + if (representative === undefined) representative = this.address; const block_ns: BlockNoSignature = { type: "state", account: this.address, previous, representative, - balance: (before_balance + BigInt(block_info.amount)).toString() as `${number}`, + balance: ((before_balance + BigInt(block_info.amount)).toString() as `${number}`), //link is hash of send block link: block_hash, }; const r_block_hash = util.hash_block(block_ns); //block hash of the receive block let work = undefined; - if (gen_work) work = await this.work_function(r_block_hash); + if (gen_work && this.work_function) work = await this.work_function(r_block_hash); const signature = util.sign_block_hash(this.private_key, r_block_hash); const block = { ...block_ns, signature, work }; return await this.send_process(block, "receive"); @@ -156,9 +159,9 @@ export class Wallet { //console.log(e) //unopened account probably previous = "0".repeat(64); - representative = this.address; before_balance = BigInt(0); } + if (representative === undefined) representative = this.address; let receive_block_hashes: BlockHash[] = []; for (const receive_hash of Object.keys(to_receive)) { const new_balance = (before_balance + BigInt(to_receive[receive_hash].amount)).toString() as `${number}`; @@ -173,7 +176,7 @@ export class Wallet { }; const r_block_hash = util.hash_block(block_ns); //block hash of the receive block let work = undefined; - if (gen_work) work = await this.work_function(r_block_hash); + if (gen_work && this.work_function) work = await this.work_function(r_block_hash); const signature = util.sign_block_hash(this.private_key, r_block_hash); const block = { ...block_ns, signature, work }; await this.send_process(block, "receive"); @@ -200,7 +203,7 @@ export class Wallet { }; const c_block_hash = util.hash_block(block_ns); //block hash of the change block let work = undefined; - if (gen_work) work = await this.work_function(c_block_hash); + if (gen_work && this.work_function) work = await this.work_function(c_block_hash); const signature = util.sign_block_hash(this.private_key, c_block_hash); const block = { ...block_ns, signature, work }; return await this.send_process(block, "change");