},
legalComments: 'inline',
outdir: 'dist',
- target: 'es2024'
+ target: 'es2024',
+ dropLabels: ['NODE'],
+ inject: ['./esbuild/inject/buffer.mjs']
+}
+
+/**
+* @type {import('esbuild').BuildOptions}
+*/
+export const libraryOptions = {
+ ...sharedOptions,
+ bundle: false,
+ format: 'esm',
+ entryPoints: ['./src/**/*.ts']
}
/**
...sharedOptions,
format: 'esm',
entryPoints: [
- { in: './src/main.ts', out: 'browser.min' },
- { in: './src/types.d.ts', out: 'types.d' }
- ],
- dropLabels: ['NODE'],
- inject: ['./esbuild/inject/buffer.mjs']
+ { in: './src/main.ts', out: 'browser.min' }
+ ]
}
/**
format: 'iife',
globalName: 'libnemo',
entryPoints: [
- { in: './src/main.ts', out: 'global.min' },
- { in: './src/types.d.ts', out: 'types.d' }
- ],
- dropLabels: ['NODE'],
- inject: ['./esbuild/inject/buffer.mjs']
+ { in: './src/main.ts', out: 'global.min' }
+ ]
}
/**
entryPoints: [
{ in: './src/main.ts', out: 'nodejs.min' }
],
- dropLabels: ['BROWSER'],
external: ['node:worker_threads'],
+ dropLabels: ['BROWSER'],
inject: ['./esbuild/inject/fake-indexeddb.mjs']
}
//! SPDX-License-Identifier: GPL-3.0-or-later
import { build } from 'esbuild'
-import { browserOptions, iifeOptions, nodeOptions } from './config.mjs'
+import { browserOptions, iifeOptions, libraryOptions, nodeOptions } from './config.mjs'
await build(browserOptions)
await build(iifeOptions)
+await build(libraryOptions)
await build(nodeOptions)
//! SPDX-License-Identifier: GPL-3.0-or-later
import { build } from 'esbuild'
-import { browserOptions, iifeOptions, nodeOptions } from './config.mjs'
+import { browserOptions, iifeOptions, libraryOptions, nodeOptions } from './config.mjs'
/**
* @type {import('esbuild').BuildOptions}
await build({ ...browserOptions, ...prodOptions })
await build({ ...iifeOptions, ...prodOptions })
+await build({ ...libraryOptions, ...prodOptions })
await build({ ...nodeOptions, ...prodOptions })
"version": "0.9.0",
"license": "(GPL-3.0-or-later AND MIT AND ISC)",
"dependencies": {
+ "@ledgerhq/hw-transport-web-ble": "^6.29.10",
+ "@ledgerhq/hw-transport-webhid": "^6.30.6",
+ "@ledgerhq/hw-transport-webusb": "^6.29.10",
"nano-pow": "^5.1.6"
},
"devDependencies": {
"funding": {
"type": "nano",
"url": "nano:nano_1zosoqs47yt47bnfg7sdf46kj7asn58b7uzm9ek95jw7ccatq37898u1zoso"
- },
- "peerDependencies": {
- "@ledgerhq/hw-transport-web-ble": "^6.29.10",
- "@ledgerhq/hw-transport-webhid": "^6.30.6",
- "@ledgerhq/hw-transport-webusb": "^6.29.10",
- "buffer": "^6.0.3"
- },
- "peerDependenciesMeta": {
- "@ledgerhq/hw-transport-web-ble": {
- "optional": true
- },
- "@ledgerhq/hw-transport-webhid": {
- "optional": true
- },
- "@ledgerhq/hw-transport-webusb": {
- "optional": true
- },
- "buffer": {
- "optional": true
- }
}
},
"node_modules/@babel/code-frame": {
}
},
"node_modules/@esbuild/aix-ppc64": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz",
- "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==",
+ "version": "0.25.10",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.10.tgz",
+ "integrity": "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==",
"cpu": [
"ppc64"
],
}
},
"node_modules/@esbuild/android-arm": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz",
- "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==",
+ "version": "0.25.10",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.10.tgz",
+ "integrity": "sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==",
"cpu": [
"arm"
],
}
},
"node_modules/@esbuild/android-arm64": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz",
- "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==",
+ "version": "0.25.10",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.10.tgz",
+ "integrity": "sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==",
"cpu": [
"arm64"
],
}
},
"node_modules/@esbuild/android-x64": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz",
- "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==",
+ "version": "0.25.10",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.10.tgz",
+ "integrity": "sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==",
"cpu": [
"x64"
],
}
},
"node_modules/@esbuild/darwin-arm64": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz",
- "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==",
+ "version": "0.25.10",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.10.tgz",
+ "integrity": "sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==",
"cpu": [
"arm64"
],
}
},
"node_modules/@esbuild/darwin-x64": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz",
- "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==",
+ "version": "0.25.10",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.10.tgz",
+ "integrity": "sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==",
"cpu": [
"x64"
],
}
},
"node_modules/@esbuild/freebsd-arm64": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz",
- "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==",
+ "version": "0.25.10",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.10.tgz",
+ "integrity": "sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==",
"cpu": [
"arm64"
],
}
},
"node_modules/@esbuild/freebsd-x64": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz",
- "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==",
+ "version": "0.25.10",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.10.tgz",
+ "integrity": "sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==",
"cpu": [
"x64"
],
}
},
"node_modules/@esbuild/linux-arm": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz",
- "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==",
+ "version": "0.25.10",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.10.tgz",
+ "integrity": "sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==",
"cpu": [
"arm"
],
}
},
"node_modules/@esbuild/linux-arm64": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz",
- "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==",
+ "version": "0.25.10",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.10.tgz",
+ "integrity": "sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==",
"cpu": [
"arm64"
],
}
},
"node_modules/@esbuild/linux-ia32": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz",
- "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==",
+ "version": "0.25.10",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.10.tgz",
+ "integrity": "sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==",
"cpu": [
"ia32"
],
}
},
"node_modules/@esbuild/linux-loong64": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz",
- "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==",
+ "version": "0.25.10",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.10.tgz",
+ "integrity": "sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==",
"cpu": [
"loong64"
],
}
},
"node_modules/@esbuild/linux-mips64el": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz",
- "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==",
+ "version": "0.25.10",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.10.tgz",
+ "integrity": "sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==",
"cpu": [
"mips64el"
],
}
},
"node_modules/@esbuild/linux-ppc64": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz",
- "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==",
+ "version": "0.25.10",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.10.tgz",
+ "integrity": "sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==",
"cpu": [
"ppc64"
],
}
},
"node_modules/@esbuild/linux-riscv64": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz",
- "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==",
+ "version": "0.25.10",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.10.tgz",
+ "integrity": "sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==",
"cpu": [
"riscv64"
],
}
},
"node_modules/@esbuild/linux-s390x": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz",
- "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==",
+ "version": "0.25.10",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.10.tgz",
+ "integrity": "sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==",
"cpu": [
"s390x"
],
}
},
"node_modules/@esbuild/linux-x64": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz",
- "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==",
+ "version": "0.25.10",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.10.tgz",
+ "integrity": "sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==",
"cpu": [
"x64"
],
}
},
"node_modules/@esbuild/netbsd-arm64": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz",
- "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==",
+ "version": "0.25.10",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.10.tgz",
+ "integrity": "sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==",
"cpu": [
"arm64"
],
}
},
"node_modules/@esbuild/netbsd-x64": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz",
- "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==",
+ "version": "0.25.10",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.10.tgz",
+ "integrity": "sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==",
"cpu": [
"x64"
],
}
},
"node_modules/@esbuild/openbsd-arm64": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz",
- "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==",
+ "version": "0.25.10",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.10.tgz",
+ "integrity": "sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==",
"cpu": [
"arm64"
],
}
},
"node_modules/@esbuild/openbsd-x64": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz",
- "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==",
+ "version": "0.25.10",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.10.tgz",
+ "integrity": "sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==",
"cpu": [
"x64"
],
}
},
"node_modules/@esbuild/openharmony-arm64": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz",
- "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==",
+ "version": "0.25.10",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.10.tgz",
+ "integrity": "sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==",
"cpu": [
"arm64"
],
}
},
"node_modules/@esbuild/sunos-x64": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz",
- "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==",
+ "version": "0.25.10",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.10.tgz",
+ "integrity": "sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==",
"cpu": [
"x64"
],
}
},
"node_modules/@esbuild/win32-arm64": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz",
- "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==",
+ "version": "0.25.10",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.10.tgz",
+ "integrity": "sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==",
"cpu": [
"arm64"
],
}
},
"node_modules/@esbuild/win32-ia32": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz",
- "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==",
+ "version": "0.25.10",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.10.tgz",
+ "integrity": "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==",
"cpu": [
"ia32"
],
}
},
"node_modules/@esbuild/win32-x64": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz",
- "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==",
+ "version": "0.25.10",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.10.tgz",
+ "integrity": "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==",
"cpu": [
"x64"
],
"node": ">=18"
}
},
+ "node_modules/@ledgerhq/devices": {
+ "version": "8.5.1",
+ "resolved": "https://registry.npmjs.org/@ledgerhq/devices/-/devices-8.5.1.tgz",
+ "integrity": "sha512-oW75YQQiP2muHveXTuwSAze6CBxJ7jOYILhFiJbsVzmgLPVqtdw4s0bJJlOBft4Aup67yNAjboFCIU7kTYQBFg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@ledgerhq/errors": "^6.25.0",
+ "@ledgerhq/logs": "^6.13.0",
+ "rxjs": "^7.8.1",
+ "semver": "^7.3.5"
+ }
+ },
+ "node_modules/@ledgerhq/errors": {
+ "version": "6.25.0",
+ "resolved": "https://registry.npmjs.org/@ledgerhq/errors/-/errors-6.25.0.tgz",
+ "integrity": "sha512-9cU0dgUyq3Adb1bHAjJnbwl+r+4WBjuPq0k+/DbBNpuYHwcz2xKtRIjLimUJyACjHti3iWwRt1sFcbQDDdI08w==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@ledgerhq/hw-transport": {
+ "version": "6.31.10",
+ "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport/-/hw-transport-6.31.10.tgz",
+ "integrity": "sha512-ruNtkTPMO3rFCaSM+oPTOXXerzxWFZF43pAHVAHhsjiQGhLWzLSkMc7qBEpWIpZPubKRAbWSXR2zXBIJPNy8oQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@ledgerhq/devices": "8.5.1",
+ "@ledgerhq/errors": "^6.25.0",
+ "@ledgerhq/logs": "^6.13.0",
+ "events": "^3.3.0"
+ }
+ },
+ "node_modules/@ledgerhq/hw-transport-web-ble": {
+ "version": "6.29.10",
+ "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-web-ble/-/hw-transport-web-ble-6.29.10.tgz",
+ "integrity": "sha512-c4MrXSS4UfPsq0Qk7C1bLGXp7OnQtifDswaEQpvjoOQ57fArObh5rpYzUuBxNPHhwh/3zNcqIWNkR0oe4ugP5Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@ledgerhq/devices": "8.5.1",
+ "@ledgerhq/errors": "^6.25.0",
+ "@ledgerhq/hw-transport": "^6.31.10",
+ "@ledgerhq/logs": "^6.13.0",
+ "rxjs": "^7.8.1"
+ }
+ },
+ "node_modules/@ledgerhq/hw-transport-webhid": {
+ "version": "6.30.6",
+ "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-webhid/-/hw-transport-webhid-6.30.6.tgz",
+ "integrity": "sha512-AOzjFv5n1OTMfvEInAZRfLO11G5zfG8pB5zhmjK5d/mVQfFNcKsLZNAC2h4OZZMBtUy8UTT3n03z93e6k6n4pQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@ledgerhq/devices": "8.5.1",
+ "@ledgerhq/errors": "^6.25.0",
+ "@ledgerhq/hw-transport": "^6.31.10",
+ "@ledgerhq/logs": "^6.13.0"
+ }
+ },
+ "node_modules/@ledgerhq/hw-transport-webusb": {
+ "version": "6.29.10",
+ "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-webusb/-/hw-transport-webusb-6.29.10.tgz",
+ "integrity": "sha512-3op7ipyZrM/Gg2qUBUM6tGKgYVh7k3hvXPE7z4i5ElAFHBdM5XMI4OD2cfl38XE0fij1dk/NCpKntOekIL7lmA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@ledgerhq/devices": "8.5.1",
+ "@ledgerhq/errors": "^6.25.0",
+ "@ledgerhq/hw-transport": "^6.31.10",
+ "@ledgerhq/logs": "^6.13.0"
+ }
+ },
+ "node_modules/@ledgerhq/logs": {
+ "version": "6.13.0",
+ "resolved": "https://registry.npmjs.org/@ledgerhq/logs/-/logs-6.13.0.tgz",
+ "integrity": "sha512-4+qRW2Pc8V+btL0QEmdB2X+uyx0kOWMWE1/LWsq5sZy3Q5tpi4eItJS6mB0XL3wGW59RQ+8bchNQQ1OW/va8Og==",
+ "license": "Apache-2.0"
+ },
"node_modules/@puppeteer/browsers": {
"version": "2.10.10",
"resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.10.10.tgz",
}
},
"node_modules/esbuild": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz",
- "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==",
+ "version": "0.25.10",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.10.tgz",
+ "integrity": "sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"node": ">=18"
},
"optionalDependencies": {
- "@esbuild/aix-ppc64": "0.25.9",
- "@esbuild/android-arm": "0.25.9",
- "@esbuild/android-arm64": "0.25.9",
- "@esbuild/android-x64": "0.25.9",
- "@esbuild/darwin-arm64": "0.25.9",
- "@esbuild/darwin-x64": "0.25.9",
- "@esbuild/freebsd-arm64": "0.25.9",
- "@esbuild/freebsd-x64": "0.25.9",
- "@esbuild/linux-arm": "0.25.9",
- "@esbuild/linux-arm64": "0.25.9",
- "@esbuild/linux-ia32": "0.25.9",
- "@esbuild/linux-loong64": "0.25.9",
- "@esbuild/linux-mips64el": "0.25.9",
- "@esbuild/linux-ppc64": "0.25.9",
- "@esbuild/linux-riscv64": "0.25.9",
- "@esbuild/linux-s390x": "0.25.9",
- "@esbuild/linux-x64": "0.25.9",
- "@esbuild/netbsd-arm64": "0.25.9",
- "@esbuild/netbsd-x64": "0.25.9",
- "@esbuild/openbsd-arm64": "0.25.9",
- "@esbuild/openbsd-x64": "0.25.9",
- "@esbuild/openharmony-arm64": "0.25.9",
- "@esbuild/sunos-x64": "0.25.9",
- "@esbuild/win32-arm64": "0.25.9",
- "@esbuild/win32-ia32": "0.25.9",
- "@esbuild/win32-x64": "0.25.9"
+ "@esbuild/aix-ppc64": "0.25.10",
+ "@esbuild/android-arm": "0.25.10",
+ "@esbuild/android-arm64": "0.25.10",
+ "@esbuild/android-x64": "0.25.10",
+ "@esbuild/darwin-arm64": "0.25.10",
+ "@esbuild/darwin-x64": "0.25.10",
+ "@esbuild/freebsd-arm64": "0.25.10",
+ "@esbuild/freebsd-x64": "0.25.10",
+ "@esbuild/linux-arm": "0.25.10",
+ "@esbuild/linux-arm64": "0.25.10",
+ "@esbuild/linux-ia32": "0.25.10",
+ "@esbuild/linux-loong64": "0.25.10",
+ "@esbuild/linux-mips64el": "0.25.10",
+ "@esbuild/linux-ppc64": "0.25.10",
+ "@esbuild/linux-riscv64": "0.25.10",
+ "@esbuild/linux-s390x": "0.25.10",
+ "@esbuild/linux-x64": "0.25.10",
+ "@esbuild/netbsd-arm64": "0.25.10",
+ "@esbuild/netbsd-x64": "0.25.10",
+ "@esbuild/openbsd-arm64": "0.25.10",
+ "@esbuild/openbsd-x64": "0.25.10",
+ "@esbuild/openharmony-arm64": "0.25.10",
+ "@esbuild/sunos-x64": "0.25.10",
+ "@esbuild/win32-arm64": "0.25.10",
+ "@esbuild/win32-ia32": "0.25.10",
+ "@esbuild/win32-x64": "0.25.10"
}
},
"node_modules/escalade": {
"node": ">=0.10.0"
}
},
+ "node_modules/events": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.x"
+ }
+ },
"node_modules/extract-zip": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
"node": ">=4"
}
},
+ "node_modules/rxjs": {
+ "version": "7.8.2",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
+ "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.1.0"
+ }
+ },
"node_modules/semver": {
"version": "7.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
"license": "ISC",
- "optional": true,
"bin": {
"semver": "bin/semver.js"
},
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
- "license": "0BSD",
- "optional": true
+ "license": "0BSD"
},
"node_modules/typed-query-selector": {
"version": "2.12.0",
"package.json.license"
],
"types": "dist/types.d.ts",
- "main": "dist/node.min.js",
+ "main": "dist/nodejs.min.js",
"browser": {
"./dist/browser.min.js": "./dist/browser.min.js",
"node:worker_threads": false
},
"scripts": {
"clean": "rm -rf dist types && tsc",
- "build": "npm run clean && node esbuild/dev.mjs",
+ "build": "npm run clean && node esbuild/dev.mjs && cp -r types dist",
"build:prod": "npm run clean && node esbuild/prod.mjs",
"prepublishOnly": "npm run test:prod",
"reinstall": "rm -rf node_modules package-lock.json && npm cache clean --force && npm i",
"#types": "./src/types.d.ts"
},
"dependencies": {
- "nano-pow": "^5.1.6"
+ "nano-pow": "^5.1.6",
+ "@ledgerhq/hw-transport-web-ble": "^6.29.10",
+ "@ledgerhq/hw-transport-webhid": "^6.30.6",
+ "@ledgerhq/hw-transport-webusb": "^6.29.10"
},
"devDependencies": {
"@types/node": "^24.5.0",
"fake-indexeddb": "^6.2.2",
"typescript": "^5.9.2"
},
- "peerDependencies": {
- "@ledgerhq/hw-transport-web-ble": "^6.29.10",
- "@ledgerhq/hw-transport-webhid": "^6.30.6",
- "@ledgerhq/hw-transport-webusb": "^6.29.10",
- "buffer": "^6.0.3"
- },
- "peerDependenciesMeta": {
- "@ledgerhq/hw-transport-web-ble": {
- "optional": true
- },
- "@ledgerhq/hw-transport-webhid": {
- "optional": true
- },
- "@ledgerhq/hw-transport-webusb": {
- "optional": true
- },
- "buffer": {
- "optional": true
- }
- },
"type": "module",
"exports": {
".": {
- "types": "./dist/types.d.ts",
+ "types": "./dist/types/main.d.ts",
+ "import": "./dist/main.js",
"browser": "./dist/browser.min.js",
"node": "./dist/nodejs.min.js",
- "default": "./dist/browser.min.js"
+ "default": "./dist/global.min.js"
}
},
"unpkg": "dist/browser.min.js"
//! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@zoso.dev>\r
//! SPDX-License-Identifier: GPL-3.0-or-later\r
\r
-import { KeyPair } from '#types'\r
import { Block } from '../block'\r
import { ACCOUNT_KEY_BYTE_LENGTH, ACCOUNT_KEY_HEX_LENGTH } from '../constants'\r
import { bytes, hex } from '../convert'\r
import { _refresh } from './refresh'\r
import { _validate } from './validate'\r
\r
+type KeyPair = {\r
+ index?: number\r
+ privateKey?: string | Uint8Array<ArrayBuffer>\r
+ publicKey?: string | Uint8Array<ArrayBuffer>\r
+}\r
+\r
/**\r
* Represents a single Nano address and the associated public key. To include the\r
* matching private key, it must be known at the time of object instantiation.\r
import { bytes, dec, hex } from './convert'
import { Blake2b, NanoNaCl } from './crypto'
import { Rpc } from './rpc'
-import { convert } from './tools'
+import { Tools } from './tools'
import { Wallet } from './wallet'
/**
throw new TypeError('Account frontier is unknown')
}
this.account = account
- this.balance = convert(balance, 'raw', 'raw', 'bigint')
+ this.balance = Tools.convert(balance, 'raw', 'raw', 'bigint')
this.previous = hex.toBytes(previous, 32)
if (representative instanceof Account) {
this.representative = representative
if (typeof amount !== 'bigint' && typeof amount !== 'number' && typeof amount !== 'string') {
throw new TypeError('Invalid amount')
}
- this.balance += convert(amount, unit, 'raw', 'bigint')
+ this.balance += Tools.convert(amount, unit, 'raw', 'bigint')
if (typeof sendBlock !== 'string' && !(sendBlock instanceof Block)) {
throw new TypeError('Invalid send block')
if (typeof amount !== 'bigint' && typeof amount !== 'number' && typeof amount !== 'string') {
throw new TypeError(`Invalid amount ${amount}`, { cause: typeof amount })
}
- this.balance -= convert(amount, unit, 'raw', 'bigint')
+ this.balance -= Tools.convert(amount, unit, 'raw', 'bigint')
if (this.balance < 0) {
throw new RangeError('Insufficient funds', { cause: this.balance })
//! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@zoso.dev>
//! SPDX-License-Identifier: GPL-3.0-or-later
-import { NamedData } from "#types"
-
export class WalletAesGcm {
static encoder: TextEncoder = new TextEncoder()
- static decrypt (type: string, key: CryptoKey, iv: ArrayBuffer, encrypted: ArrayBuffer): Promise<NamedData<ArrayBuffer>> {
+ static decrypt (type: string, key: CryptoKey, iv: ArrayBuffer, encrypted: ArrayBuffer): Promise<{ [key: string]: ArrayBuffer }> {
const seedLength = type === 'BIP-44' ? 64 : 32
const additionalData = this.encoder.encode(type)
return crypto.subtle
})
}
- static encrypt (type: string, key: CryptoKey, seed: ArrayBuffer, mnemonic?: ArrayBuffer): Promise<NamedData<ArrayBuffer>> {
+ static encrypt (type: string, key: CryptoKey, seed: ArrayBuffer, mnemonic?: ArrayBuffer): Promise<{ [key: string]: ArrayBuffer }> {
if (type == null) {
throw new Error('Wallet type missing')
}
//! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@zoso.dev>
//! SPDX-License-Identifier: GPL-3.0-or-later
-//@ts-expect-error
import { default as TransportBLE } from '@ledgerhq/hw-transport-web-ble'
-//@ts-expect-error
import { default as TransportHID } from '@ledgerhq/hw-transport-webhid'
-//@ts-expect-error
import { default as TransportUSB } from '@ledgerhq/hw-transport-webusb'
-import { LedgerStatus, LedgerAccountResponse, LedgerResponse, LedgerSignResponse, LedgerVersionResponse } from '#types'
import { Account } from './account'
import { Block } from './block'
import { BIP44_COIN_NANO, BIP44_PURPOSE, HARDENED_OFFSET } from './constants'
import { Rpc } from './rpc'
import { Wallet } from './wallet'
+type LedgerStatus = 'UNSUPPORTED' | 'DISCONNECTED' | 'BUSY' | 'LOCKED' | 'CONNECTED'
+
+interface LedgerResponse {
+ status: string
+}
+
+interface LedgerVersionResponse extends LedgerResponse {
+ name: string | null,
+ version: string | null
+}
+
+interface LedgerAccountResponse extends LedgerResponse {
+ publicKey: string | null,
+ address: string | null
+}
+
+interface LedgerSignResponse extends LedgerResponse {
+ signature: string | null,
+ hash?: string
+}
+
/**
* Ledger hardware wallet created by communicating with a Ledger device via ADPU
* calls. This wallet does not feature any seed nor mnemonic phrase as all
}
try {
const version = await this.#version()
+ globalThis.navigator?.hid?.addEventListener('connect', console.log)
+ globalThis.navigator?.usb?.addEventListener('connect', console.log)
+ globalThis.navigator?.hid?.addEventListener('disconnect', console.log)
+ globalThis.navigator?.usb?.addEventListener('disconnect', console.log)
+ globalThis.navigator?.hid?.addEventListener('connect', this.#onConnectHid)
+ globalThis.navigator?.usb?.addEventListener('connect', this.#onConnectUsb)
+ globalThis.navigator?.hid?.addEventListener('disconnect', this.#onDisconnectHid)
+ globalThis.navigator?.usb?.addEventListener('disconnect', this.#onDisconnectUsb)
if (version.status !== 'OK') {
this.#status = 'DISCONNECTED'
} else if (version.name === 'Nano') {
*/
static disconnect (): void {
setTimeout(async () => {
- const hidDevices = await globalThis.navigator.hid.getDevices()
+ const hidDevices = await globalThis.navigator?.hid?.getDevices?.() ?? []
for (const device of hidDevices) {
if (device.vendorId === this.UsbVendorId) {
device.forget()
}
}
- const bleDevices = await globalThis.navigator.bluetooth.getDevices()
+ const bleDevices = await globalThis.navigator?.bluetooth?.getDevices?.() ?? []
for (const device of bleDevices) {
TransportBLE.disconnect(device.id)
}
- const usbDevices = await globalThis.navigator.usb.getDevices()
+ const usbDevices = await globalThis.navigator?.usb?.getDevices?.() ?? []
for (const device of usbDevices) {
if (device.vendorId === this.UsbVendorId) {
device.forget()
}
static #onConnectHid = async (e: HIDConnectionEvent): Promise<void> => {
+ console.log('onConnectHid')
console.log(e)
if (e.device?.vendorId === this.UsbVendorId) {
console.log('Ledger connected via HID')
}
static #onDisconnectHid = async (e: HIDConnectionEvent): Promise<void> => {
+ console.log('onDisconnectHid')
console.log(e)
if (e.device?.vendorId === this.UsbVendorId) {
console.log('Ledger disconnected via HID')
}
static #onConnectUsb = async (e: USBConnectionEvent): Promise<void> => {
+ console.log('onConnectUsb')
console.log(e)
if (e.device?.vendorId === this.UsbVendorId) {
console.log('Ledger connected via USB')
}
static #onDisconnectUsb = async (e: USBConnectionEvent): Promise<void> => {
+ console.log('onDisconnectUsb')
console.log(e)
if (e.device?.vendorId === this.UsbVendorId) {
console.log('Ledger disconnected via USB')
import { NamedData } from '#types'
import { Account } from './account'
import { Database } from './database'
-import { verify } from './tools'
+import { Tools } from './tools'
/**
* Represents a basic address book of Nano accounts. Multiple addresses can be
const addresses = await this.getAddresses(name)
for (const address of addresses) {
const { publicKey } = Account.load(address)
- const verified = await verify(publicKey, signature, ...data)
+ const verified = await Tools.verify(publicKey, signature, ...data)
if (verified) {
return true
}
//! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@zoso.dev>
//! SPDX-License-Identifier: GPL-3.0-or-later
-import { SweepResult } from '#types'
import { Account } from './account'
import { Block } from './block'
import { MAX_SUPPLY, UNITS } from './constants'
import { Rpc } from './rpc'
import { Wallet } from './wallet'
-/**
-* Converts a decimal amount of nano from one unit divider to another.
-*
-* @param {(bigint|number|string)} amount - Decimal amount to convert
-* @param {string} inputUnit - Current denomination
-* @param {string} outputUnit - Desired denomination
-* @param {string} [format] - Data type of output
-*/
-export function convert (amount: bigint | number | string, inputUnit: string, outputUnit: string): string
-export function convert (amount: bigint | number | string, inputUnit: string, outputUnit: string, format: 'bigint'): bigint
-export function convert (amount: bigint | number | string, inputUnit: string, outputUnit: string, format: 'number'): number
-export function convert (amount: bigint | number | string, inputUnit: string, outputUnit: string, format: 'string'): string
-export function convert (amount: unknown, inputUnit: unknown, outputUnit: unknown, format?: unknown): bigint | number | string {
- if (typeof amount !== 'bigint' && typeof amount !== 'number' && typeof amount !== 'string') {
- throw new Error('Invalid amount', { cause: typeof amount })
- }
- if (typeof amount === 'string' && !/^[0-9]+\.?[0-9]*$/.test(amount)) {
- throw new Error('Invalid amount', { cause: amount })
- }
- if (typeof inputUnit !== 'string') {
- throw new TypeError('Invalid input unit', { cause: typeof inputUnit })
- }
- (inputUnit as string) = inputUnit.toUpperCase()
- if (typeof outputUnit !== 'string') {
- throw new TypeError('Invalid output unit', { cause: typeof outputUnit })
- }
- (outputUnit as string) = outputUnit.toUpperCase()
- if (UNITS[inputUnit] == null) {
- throw new Error(`Unknown denomination ${inputUnit}, expected one of the following: ${Object.keys(UNITS)}`)
- }
- if (UNITS[outputUnit] == null) {
- throw new Error(`Unknown denomination ${outputUnit}, expected one of the following: ${Object.keys(UNITS)}`)
- }
- if (format !== undefined && format !== 'bigint' && format !== 'number' && format !== 'string') {
- throw new Error('Invalid output format', { cause: format })
- }
+type SweepResult = {
+ status: "success" | "error"
+ address: string
+ message: string
+}
- let [i, f] = typeof amount === 'string'
- ? amount.split('.')
- : amount.toString().split('.')
- i = i.replace(/^0*/g, '')
- f = f?.replace(/0*$/g, '')
+export class Tools {
+ static #ledger: typeof import('./ledger').Ledger
- const inUnit = UNITS[inputUnit]
- const intShift = i.length + inUnit
- if (f?.length > inUnit) {
- throw new RangeError('Amount contains fractional raw')
+ static {
+ (async () => {
+ this.#ledger = (await import('./ledger')).Ledger
+ })()
}
- // convert to raw
- let int = BigInt(i.padEnd(intShift, '0') || '0')
- if (f != null) {
- const fracShift = f?.length + inUnit
- let frac = BigInt(f?.padEnd(fracShift, '0') || '0')
- frac /= 10n ** BigInt(f.length)
- int += frac
- }
- if (int > MAX_SUPPLY) {
- throw new Error('Amount exceeds available supply')
- }
- if (int < 0n) {
- throw new Error('Amount must be non-negative')
- }
+ /**
+ * Converts a decimal amount of nano from one unit divider to another.
+ *
+ * @param {(bigint|number|string)} amount - Decimal amount to convert
+ * @param {string} inputUnit - Current denomination
+ * @param {string} outputUnit - Desired denomination
+ * @param {string} [format] - Data type of output
+ */
+ static convert (amount: bigint | number | string, inputUnit: string, outputUnit: string): string
+ static convert (amount: bigint | number | string, inputUnit: string, outputUnit: string, format: 'bigint'): bigint
+ static convert (amount: bigint | number | string, inputUnit: string, outputUnit: string, format: 'number'): number
+ static convert (amount: bigint | number | string, inputUnit: string, outputUnit: string, format: 'string'): string
+ static convert (amount: unknown, inputUnit: unknown, outputUnit: unknown, format?: unknown): bigint | number | string {
+ if (typeof amount !== 'bigint' && typeof amount !== 'number' && typeof amount !== 'string') {
+ throw new Error('Invalid amount', { cause: typeof amount })
+ }
+ if (typeof amount === 'string' && !/^[0-9]+\.?[0-9]*$/.test(amount)) {
+ throw new Error('Invalid amount', { cause: amount })
+ }
+ if (typeof inputUnit !== 'string') {
+ throw new TypeError('Invalid input unit', { cause: typeof inputUnit })
+ }
+ (inputUnit as string) = inputUnit.toUpperCase()
+ if (typeof outputUnit !== 'string') {
+ throw new TypeError('Invalid output unit', { cause: typeof outputUnit })
+ }
+ (outputUnit as string) = outputUnit.toUpperCase()
+ if (UNITS[inputUnit] == null) {
+ throw new Error(`Unknown denomination ${inputUnit}, expected one of the following: ${Object.keys(UNITS)}`)
+ }
+ if (UNITS[outputUnit] == null) {
+ throw new Error(`Unknown denomination ${outputUnit}, expected one of the following: ${Object.keys(UNITS)}`)
+ }
+ if (format !== undefined && format !== 'bigint' && format !== 'number' && format !== 'string') {
+ throw new Error('Invalid output format', { cause: format })
+ }
- // convert to desired denomination
- const outUnit = UNITS[outputUnit]
- i = int.toString().padStart(40, '0')
- f = i.slice(40 - outUnit).replace(/0*$/g, '')
- i = i.slice(0, 40 - outUnit).replace(/^0*/g, '')
- const output = `${i === '' ? '0' : i}${f === '' ? '' : '.'}${f}`
+ let [i, f] = typeof amount === 'string'
+ ? amount.split('.')
+ : amount.toString().split('.')
+ i = i.replace(/^0*/g, '')
+ f = f?.replace(/0*$/g, '')
- switch (format) {
- case 'bigint': {
- if (!f) return BigInt(output)
- throw new RangeError('Output fractional amount truncated')
+ const inUnit = UNITS[inputUnit]
+ const intShift = i.length + inUnit
+ if (f?.length > inUnit) {
+ throw new RangeError('Amount contains fractional raw')
}
- case 'number': {
- if (Number(i) <= Number.MAX_SAFE_INTEGER) return Number(output)
- throw new RangeError('Output larger than Number.MAX_SAFE_INTEGER')
- }
- case 'string':
- default: return output
- }
-}
-function hash (data: string | string[], encoding?: 'hex'): Uint8Array<ArrayBuffer>
-function hash (data: string | string[], encoding?: 'hex', format?: 'hex'): string | Uint8Array<ArrayBuffer> {
- if (!Array.isArray(data)) data = [data]
- const hash = new Blake2b(32)
- if (encoding === 'hex') {
- data.forEach(str => hash.update(hex.toBytes(str)))
- } else {
- const enc = new TextEncoder()
- data.forEach(str => hash.update(enc.encode(str)))
- }
- return format === 'hex'
- ? bytes.toHex(hash.digest())
- : hash.digest()
-}
+ // convert to raw
+ let int = BigInt(i.padEnd(intShift, '0') || '0')
+ if (f != null) {
+ const fracShift = f?.length + inUnit
+ let frac = BigInt(f?.padEnd(fracShift, '0') || '0')
+ frac /= 10n ** BigInt(f.length)
+ int += frac
+ }
+ if (int > MAX_SUPPLY) {
+ throw new Error('Amount exceeds available supply')
+ }
+ if (int < 0n) {
+ throw new Error('Amount must be non-negative')
+ }
-async function ledger (): Promise<typeof import('./ledger').Ledger> {
- const { Ledger } = await import('./ledger')
- return Ledger
-}
+ // convert to desired denomination
+ const outUnit = UNITS[outputUnit]
+ i = int.toString().padStart(40, '0')
+ f = i.slice(40 - outUnit).replace(/0*$/g, '')
+ i = i.slice(0, 40 - outUnit).replace(/^0*/g, '')
+ const output = `${i === '' ? '0' : i}${f === '' ? '' : '.'}${f}`
-/**
-* Signs arbitrary strings with a private key using the Ed25519 signature scheme.
-* The strings are first hashed to a 32-byte value using BLAKE2b.
-*
-* @param {string | Uint8Array<ArrayBuffer>} key - Hexadecimal-formatted private key to use for signing
-* @param {...string} input - Data to be signed
-* @returns {Promise<string>} Hexadecimal-formatted signature
-*/
-export async function sign (key: string | Uint8Array<ArrayBuffer>, ...input: string[]): Promise<string> {
- if (typeof key === 'string') key = hex.toBytes(key)
- try {
- const signature = await NanoNaCl.detached(hash(input), key)
- return bytes.toHex(signature)
- } catch (err) {
- throw new Error(`Failed to sign message with private key`, { cause: err })
- } finally {
- bytes.erase(key)
+ switch (format) {
+ case 'bigint': {
+ if (!f) return BigInt(output)
+ throw new RangeError('Output fractional amount truncated')
+ }
+ case 'number': {
+ if (Number(i) <= Number.MAX_SAFE_INTEGER) return Number(output)
+ throw new RangeError('Output larger than Number.MAX_SAFE_INTEGER')
+ }
+ case 'string':
+ default: return output
+ }
}
-}
-/**
-* Collects the funds from a specified range of accounts in a wallet and sends
-* them all to a single recipient address. Hardware wallets are unsupported.
-*
-* @param {Rpc|string|URL} rpc - RPC node information required to refresh accounts, calculate PoW, and process blocks
-* @param {(Wallet)} wallet - Wallet from which to sweep funds
-* @param {string} recipient - Destination address for all swept funds
-* @param {number} [from=0] - Starting account index to sweep
-* @param {number} [to=from] - Ending account index to sweep
-* @returns An array of results including both successes and failures
- */
-export async function sweep (
- rpc: Rpc | string | URL,
- wallet: Wallet,
- recipient: string,
- from: number = 0,
- to: number = from
-): Promise<SweepResult[]> {
- if (rpc == null || wallet == null || recipient == null) {
- throw new ReferenceError('Missing required sweep arguments')
+ /**
+ * Hashes one or more arbitrary strings to a 32-byte value using BLAKE2b.
+ *
+ * @param {(string|string[])} data String(s) to hash
+ * @param {string} [encoding] Interprets input strings as hexadecimal values if 'hex' is passed, else UTF-8
+ */
+ static hash (data: string | string[], encoding?: 'hex'): Uint8Array<ArrayBuffer>
+ /**
+ * Hashes one or more arbitrary strings to a 32-byte value using BLAKE2b.
+ *
+ * @param {(string|string[])} data String(s) to hash
+ * @param {string} [encoding] Interprets input strings as hexadecimal values if 'hex' is passed, else UTF-8
+ * @param {string} [format] Formats output as a hexadecimal value if 'hex' is passed, else Uint8Array<ArrayBuffer>
+ */
+ static hash (data: string | string[], encoding?: 'hex', format?: 'hex'): string | Uint8Array<ArrayBuffer> {
+ if (!Array.isArray(data)) data = [data]
+ const hash = new Blake2b(32)
+ if (encoding === 'hex') {
+ data.forEach(str => hash.update(hex.toBytes(str)))
+ } else {
+ const enc = new TextEncoder()
+ data.forEach(str => hash.update(enc.encode(str)))
+ }
+ return format === 'hex'
+ ? bytes.toHex(hash.digest())
+ : hash.digest()
}
- if (typeof rpc === 'string' || rpc instanceof URL) {
- rpc = new Rpc(rpc)
+
+ /**
+ * Provides low-level access to Ledger hardware wallets.
+ *
+ * @returns `Ledger` class with collection of static methods for managing the device
+ */
+ static get Ledger (): typeof import('./ledger').Ledger {
+ return this.#ledger
}
- if (!(rpc instanceof Rpc)) {
- throw new TypeError('RPC must be a valid node')
+
+ /**
+ * Signs arbitrary strings with a private key using the Ed25519 signature scheme.
+ * The strings are first hashed to a 32-byte value using BLAKE2b.
+ *
+ * @param {string | Uint8Array<ArrayBuffer>} key - Hexadecimal-formatted private key to use for signing
+ * @param {...string} input - Data to be signed
+ * @returns {Promise<string>} Hexadecimal-formatted signature
+ */
+ static async sign (key: string | Uint8Array<ArrayBuffer>, ...input: string[]): Promise<string> {
+ if (typeof key === 'string') key = hex.toBytes(key)
+ try {
+ const signature = await NanoNaCl.detached(this.hash(input), key)
+ return bytes.toHex(signature)
+ } catch (err) {
+ throw new Error(`Failed to sign message with private key`, { cause: err })
+ } finally {
+ bytes.erase(key)
+ }
}
- const blockQueue: Promise<void>[] = []
- const results: SweepResult[] = []
- const recipientAccount = Account.load(recipient)
- const accounts = await wallet.refresh(rpc, from, to)
-
- for (const [index, account] of accounts) {
- const blockRequest: Promise<void> = new Promise(async (resolve) => {
- let block
- try {
- if (index == null && account.index == null) {
- throw new TypeError('Account index is required', { cause: account })
+ /**
+ * Collects the funds from a specified range of accounts in a wallet and sends
+ * them all to a single recipient address. Hardware wallets are unsupported.
+ *
+ * @param {Rpc|string|URL} rpc - RPC node information required to refresh accounts, calculate PoW, and process blocks
+ * @param {(Wallet)} wallet - Wallet from which to sweep funds
+ * @param {string} recipient - Destination address for all swept funds
+ * @param {number} [from=0] - Starting account index to sweep
+ * @param {number} [to=from] - Ending account index to sweep
+ * @returns An array of results including both successes and failures
+ */
+ static async sweep (
+ rpc: Rpc | string | URL,
+ wallet: Wallet,
+ recipient: string,
+ from: number = 0,
+ to: number = from
+ ): Promise<SweepResult[]> {
+ if (rpc == null || wallet == null || recipient == null) {
+ throw new ReferenceError('Missing required sweep arguments')
+ }
+ if (typeof rpc === 'string' || rpc instanceof URL) {
+ rpc = new Rpc(rpc)
+ }
+ if (!(rpc instanceof Rpc)) {
+ throw new TypeError('RPC must be a valid node')
+ }
+
+ const blockQueue: Promise<void>[] = []
+ const results: SweepResult[] = []
+ const recipientAccount = Account.load(recipient)
+ const accounts = await wallet.refresh(rpc, from, to)
+
+ for (const [index, account] of accounts) {
+ const blockRequest: Promise<void> = new Promise(async (resolve) => {
+ let block
+ try {
+ if (index == null && account.index == null) {
+ throw new TypeError('Account index is required', { cause: account })
+ }
+ block = await new Block(account)
+ .send(recipientAccount, account.balance ?? 0n)
+ .sign(wallet, account.index ?? index)
+ await block.pow()
+ const hash = await block.process(rpc)
+ results.push({ status: 'success', address: block.account.address, message: hash })
+ } catch (err: any) {
+ results.push({ status: 'error', address: account.address, message: err.message })
+ } finally {
+ resolve()
}
- block = await new Block(account)
- .send(recipientAccount, account.balance ?? 0n)
- .sign(wallet, account.index ?? index)
- await block.pow()
- const hash = await block.process(rpc)
- results.push({ status: 'success', address: block.account.address, message: hash })
- } catch (err: any) {
- results.push({ status: 'error', address: account.address, message: err.message })
- } finally {
- resolve()
- }
- })
- blockQueue.push(blockRequest)
+ })
+ blockQueue.push(blockRequest)
+ }
+ await Promise.allSettled(blockQueue)
+ return results
}
- await Promise.allSettled(blockQueue)
- return results
-}
-/**
-* Verifies the signature of arbitrary strings using a public key.
-*
-* @param {string | Uint8Array<ArrayBuffer>} key - Hexadecimal-formatted public key to use for verification
-* @param {string} signature - Hexadcimal-formatted signature
-* @param {...string} input - Data to be verified
-* @returns {Promise<boolean>} True if the data was signed by the public key's matching private key
-*/
-export async function verify (key: string | Uint8Array<ArrayBuffer>, signature: string, ...input: string[]): Promise<boolean> {
- if (typeof key === 'string') key = hex.toBytes(key)
- try {
- return await NanoNaCl.verify(hash(input), hex.toBytes(signature), key)
- } catch (err) {
- throw new Error('Failed to verify signature', { cause: err })
- } finally {
- bytes.erase(key)
+ /**
+ * Verifies the signature of arbitrary strings using a public key.
+ *
+ * @param {string | Uint8Array<ArrayBuffer>} key - Hexadecimal-formatted public key to use for verification
+ * @param {string} signature - Hexadcimal-formatted signature
+ * @param {...string} input - Data to be verified
+ * @returns {Promise<boolean>} True if the data was signed by the public key's matching private key
+ */
+ static async verify (key: string | Uint8Array<ArrayBuffer>, signature: string, ...input: string[]): Promise<boolean> {
+ if (typeof key === 'string') key = hex.toBytes(key)
+ try {
+ return await NanoNaCl.verify(this.hash(input), hex.toBytes(signature), key)
+ } catch (err) {
+ throw new Error('Failed to verify signature', { cause: err })
+ } finally {
+ bytes.erase(key)
+ }
}
}
-
-export const Tools = { convert, hash, ledger, sign, sweep, verify }
//! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@zoso.dev>
//! SPDX-License-Identifier: GPL-3.0-or-later
-import { NamedData, WalletType } from '#types'
+import { NamedData } from '#types'
import { BIP44_COIN_NANO } from '../constants'
import { Bip39, Bip44, Blake2b, NanoNaCl, WalletAesGcm } from '../crypto'
+import { WalletType } from '../wallet'
import { Passkey } from './passkey'
import { VaultTimer } from './vault-timer'
//! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@zoso.dev>
//! SPDX-License-Identifier: GPL-3.0-or-later
-import { KeyPair, WalletType } from '#types'
import { Account } from '../account'
+import { Ledger } from '../ledger'
import { Vault } from '../vault'
+import { WalletType } from '.'
export async function _accounts (type: WalletType, accounts: Map<number, Account>, vault: Vault, index: number): Promise<Account>
export async function _accounts (type: WalletType, accounts: Map<number, Account>, vault: Vault, from: number, to: number): Promise<Map<number, Account>>
if (indexes.length > 0) {
const publicAccounts = []
if (type === 'Ledger') {
- const { Ledger } = await import('../ledger')
for (const index of indexes) {
const { status, publicKey } = await Ledger.account(index)
if (status !== 'OK' || publicKey == null) {
index
}))
}
- const publicKeys: KeyPair[] = await Promise.all(promises)
+ const publicKeys = await Promise.all(promises)
if (publicKeys.length > 0) {
publicAccounts.push(...Account.load(publicKeys))
}
//! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@zoso.dev>
//! SPDX-License-Identifier: GPL-3.0-or-later
-import { WalletType } from '#types'
+import { Ledger } from '../ledger'
import { Vault } from '../vault'
+import { WalletType } from '.'
export async function _config (type: WalletType, vault: Vault, settings: { connection: 'hid' | 'ble' | 'usb' } | { timeout: number }): Promise<void>
export async function _config (type: WalletType, vault: Vault, settings: unknown): Promise<void> {
}
const { connection, timeout } = settings as { [key: string]: unknown }
if (type === 'Ledger') {
- const { Ledger } = await import('../ledger')
if (connection !== undefined && connection !== 'hid' && connection !== 'ble' && connection !== 'usb') {
throw new Error('Ledger connection must be hid, ble, or usb', { cause: connection })
}
import { NamedData } from '#types'
import { utf8 } from '../convert'
import { Database } from '../database'
+import { Ledger } from '../ledger'
import { Vault } from '../vault'
import { Wallet } from '../wallet'
import { _load } from './load'
type: wallet.type
}
if (wallet.type === 'Ledger') {
- const { Ledger } = await import('../ledger')
try {
if (Ledger.isUnsupported) {
throw new Error('Browser is unsupported')
//! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@zoso.dev>\r
//! SPDX-License-Identifier: GPL-3.0-or-later\r
\r
-import { NamedData, WalletType } from '#types'\r
+import { NamedData } from '#types'\r
import { Account } from '../account'\r
import { Block } from '../block'\r
import { ADDRESS_GAP } from '../constants'\r
import { bytes } from '../convert'\r
+import { Ledger } from '../ledger'\r
import { Rpc } from '../rpc'\r
import { Vault } from '../vault'\r
import { _accounts } from './accounts'\r
import { _update } from './update'\r
import { _verify } from './verify'\r
\r
+export type WalletType = 'BIP-44' | 'BLAKE2b' | 'Ledger'\r
+\r
/**\r
* Represents a wallet containing numerous Nano accounts derived from a single\r
* source, the form of which can vary based on the type of wallet. Currently,\r
*/\r
export class Wallet {\r
static get DB_NAME (): 'Wallet' { return 'Wallet' }\r
- static #ledger: typeof import('../ledger').Ledger\r
\r
/**\r
* Retrieves all wallets with encrypted secrets and unencrypted metadata from\r
*/\r
static async create (type: 'BIP-44' | 'BLAKE2b', password: string, mnemonicSalt?: string): Promise<Wallet>\r
static async create (type: WalletType, password?: string, mnemonicSalt?: string): Promise<Wallet> {\r
- Wallet.#ledger ??= (await import('../ledger')).Ledger\r
Wallet.#isInternal = true\r
const self = new this(type)\r
{ ({ mnemonic: self.#mnemonic, seed: self.#seed } = await _create(self, self.#vault, password, mnemonicSalt)) }\r
*/\r
static async load (type: 'BIP-44' | 'BLAKE2b', password: string, mnemonicPhrase: string, mnemonicSalt?: string): Promise<Wallet>\r
static async load (type: WalletType, password: string, secret: string, mnemonicSalt?: string): Promise<Wallet> {\r
- Wallet.#ledger ??= (await import('../ledger')).Ledger\r
Wallet.#isInternal = true\r
const self = new this(type)\r
await _load(self, self.#vault, password, secret, mnemonicSalt)\r
- if (type === 'Ledger' && Wallet.#ledger === undefined) {\r
- Wallet.#ledger = (await import('../ledger')).Ledger\r
- }\r
return self\r
}\r
\r
*/\r
static async restore (): Promise<Wallet[]>\r
static async restore (id?: string): Promise<Wallet | Wallet[]> {\r
- Wallet.#ledger ??= (await import('../ledger')).Ledger\r
const backups = await _restore(id)\r
const wallets = backups.map(backup => {\r
Wallet.#isInternal = true\r
*/\r
get isLocked (): boolean {\r
return this.type === 'Ledger'\r
- ? Wallet.#ledger.status !== 'CONNECTED'\r
+ ? Ledger.status !== 'CONNECTED'\r
: this.#vault.isLocked\r
}\r
\r
import { hex, utf8 } from '../convert'
import { Bip39 } from '../crypto'
import { Database } from '../database'
+import { Ledger } from '../ledger'
import { Vault } from '../vault'
import { Wallet } from '../wallet'
}
if (wallet.type === 'Ledger') {
- const { Ledger } = await import('../ledger')
if (Ledger.isUnsupported) {
throw new Error('Failed to initialize Ledger wallet', { cause: 'Browser is unsupported' })
}
//! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@zoso.dev>
//! SPDX-License-Identifier: GPL-3.0-or-later
+import { Ledger } from '../ledger'
import { Vault } from '../vault'
import { Wallet } from '../wallet'
export async function _lock (wallet: Wallet, vault: Vault): Promise<void> {
try {
if (wallet.type === 'Ledger') {
- const { Ledger } = await import('../ledger')
Ledger.disconnect()
} else {
await vault.request({
//! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@zoso.dev>
//! SPDX-License-Identifier: GPL-3.0-or-later
-import { BlockInfo } from '#types'
import { Account } from '../account'
import { Block } from '../block'
import { Rpc } from '../rpc'
import { Wallet } from '../wallet'
+export type BlockInfo = {
+ blocks: {
+ [hash: string]: {
+ [p: string]: string
+ } & {
+ contents: {
+ [p: string]: string
+ }
+ }
+ }
+}
+
export async function _refresh (wallet: Wallet, rpc: Rpc | string | URL, from: number, to: number): Promise<Map<number, Account>>
export async function _refresh (wallet: Wallet, rpc: unknown, from: unknown, to: unknown): Promise<Map<number, Account>> {
try {
import { Block } from '../block'
import { bytes, hex, utf8 } from '../convert'
import { Blake2b } from '../crypto'
+import { Ledger } from '../ledger'
import { Vault } from '../vault'
import { Wallet } from '../wallet'
throw new TypeError('Invalid Block', { cause: block })
}
if (wallet.type === 'Ledger') {
- const { Ledger } = await import('../ledger')
const account = await wallet.account(index)
if (frontier instanceof Block) {
try {
import { NamedData } from '#types'
import { utf8 } from '../convert'
+import { Ledger } from '../ledger'
import { Vault } from '../vault'
import { Wallet } from '../wallet'
import { _get } from './get'
type: wallet.type
}
if (wallet.type === 'Ledger') {
- const { Ledger } = await import('../ledger')
const status = await Ledger.connect()
if (await status !== 'CONNECTED') {
throw new Error('Failed to unlock wallet', { cause: status })
//! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@zoso.dev>
//! SPDX-License-Identifier: GPL-3.0-or-later
-import { NamedData, WalletType } from '#types'
import { hex } from '../convert'
+import { Ledger } from '../ledger'
import { Vault } from '../vault'
+import { WalletType } from '.'
export async function _verify (type: WalletType, vault: Vault, secret: string): Promise<boolean>
export async function _verify (type: WalletType, vault: Vault, secret: unknown): Promise<boolean> {
throw new TypeError('Wallet secret must be a string', { cause: typeof secret })
}
if (type === 'Ledger') {
- const { Ledger } = await import('../ledger')
return await Ledger.verify(secret)
} else {
- const data: NamedData = {
+ const data: { [key: string]: string | ArrayBuffer } = {
action: 'verify'
}
if (/^(?:[A-F0-9]{64}){1,2}$/i.test(secret)) {
import { Account } from './lib/account'
import { Block } from './lib/block'
import { Blake2b } from './lib/crypto'
+import { Ledger } from './lib/ledger'
import { Rolodex } from './lib/rolodex'
import { Rpc } from './lib/rpc'
import { Tools } from './lib/tools'
Account,
Blake2b,
Block,
+ Ledger,
Rolodex,
Rpc,
Tools,
//! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@zoso.dev>
//! SPDX-License-Identifier: GPL-3.0-or-later
-/**
-* Represents a single Nano address and the associated public key. To include the
-* matching private key, it must be known at the time of object instantiation.
-* The frontier, balance, and representative for the account can also be set or
-* be fetched from the network.
-*/
-export declare class Account {
- #private
- [key: string]: any
- static get DB_NAME (): 'Account'
- get address (): string
- get index (): number | undefined
- get publicKey (): string
- get confirmed_balance (): bigint | undefined
- get confirmed_height (): number | undefined
- get confirmed_frontier (): string | undefined
- get confirmed_frontier_block (): Block | undefined
- get confirmed_receivable (): bigint | undefined
- get confirmed_representative (): Account | undefined
- get balance (): bigint | undefined
- get block_count (): number | undefined
- get frontier (): string | undefined
- get frontier_block (): Block | undefined
- get open_block (): string | undefined
- get receivable (): bigint | undefined
- get representative (): Account | undefined
- get representative_block (): string | undefined
- get weight (): bigint | undefined
- set confirmed_balance (v: bigint | number | string)
- set confirmed_height (v: number | undefined)
- set confirmed_frontier (v: string | undefined)
- set confirmed_frontier_block (v: Block | undefined)
- set confirmed_receivable (v: bigint | number | string)
- set confirmed_representative (v: unknown)
- set balance (v: bigint | number | string)
- set block_count (v: number | undefined)
- set frontier (v: string | undefined)
- set frontier_block (v: Block | undefined)
- set open_block (v: string | undefined)
- set receivable (v: bigint | number | string)
- set representative (v: unknown)
- set representative_block (v: string | undefined)
- set weight (v: bigint | number | string)
- private constructor ()
- /**
- * Releases variable references to allow garbage collection.
- */
- destroy (): Promise<void>
- /**
- * Stringifies public properties into a JSON object so it can be further
- * stringified by JSON.stringify()
- */
- toJSON (): {
- address: string
- index: number | undefined
- publicKey: string
- confirmed_balance: string | undefined
- confirmed_height: string | undefined
- confirmed_frontier: string | undefined
- confirmed_receivable: string | undefined
- confirmed_representative: string | undefined
- balance: string | undefined
- block_count: number | undefined
- frontier: string | undefined
- open_block: string | undefined
- receivable: string | undefined
- representative: string | undefined
- representative_block: string | undefined
- weight: string | undefined
- }
- /**
- * Instantiates an Account object from its Nano address.
- *
- * @param {string} address - Address of the account
- * @returns {Account} A new Account object
- */
- static load (address: string): Account
- /**
- * Instantiates Account objects from their Nano addresses.
- *
- * @param {string[]} addresses - Addresses of the accounts
- * @returns {Account[]} Array of new Account objects
- */
- static load (addresses: string[]): Account[]
- /**
- * Instantiates an Account object from its public key. It is unable to sign
- * blocks or messages since it has no private key.
- *
- * @param {string | Uint8Array<ArrayBuffer>} publicKey - Public key of the account
- * @returns {Account} A new Account object
- */
- static load (publicKey: string | Uint8Array<ArrayBuffer>): Account
- /**
- * Instantiates Account objects from their public keys. They are unable to sign
- * blocks or messages since they have no private key.
- *
- * @param {string | Uint8Array<ArrayBuffer>[]} publicKeys - Public keys of the accounts
- * @returns {Account[]} Array of new Account objects
- */
- static load (publicKeys: string | Uint8Array<ArrayBuffer>[]): Account[]
- /**
- * Instantiates an Account object from its public key. It is unable to sign
- * blocks or messages since it has no private key.
- *
- * @param {KeyPair} keypair - Index and keys of the account
- * @returns {Account} A new Account object
- */
- static load (keypair: KeyPair): Account
- /**
- * Instantiates Account objects from their public keys. They are unable to sign
- * blocks or messages since they have no private key.
- *
- * @param {KeyPair[]} keypairs - Indexes and keys of the accounts
- * @returns {Account[]} Array of new Account objects
- */
- static load (keypairs: KeyPair[]): Account[]
- /**
- * Instantiates an Account object from its private key which is used to derive
- * a public key and then discarded.
- *
- * @param {KeyPair} keypair - Index and key of the account
- * @param {string} type - Indicates a private key
- * @returns {Promise<Account>} Promise for a new Account object
- */
- static load (keypair: KeyPair, type: 'private'): Promise<Account>
- /**
- * Instantiates Account objects from their private keys which are used to
- * derive public keys and then discarded.
- *
- * @param {KeyPair[]} keypairs - Indexes and keys of the accounts
- * @param {string} type - Indicates private keys
- * @returns {Promise<Account[]>} Promise for array of new Account objects
- */
- static load (keypairs: KeyPair[], type: 'private'): Promise<Account[]>
- /**
- * Refreshes the account from its current state on the network.
- *
- * A successful response sets the balance, frontier, and representative
- * properties.
- *
- * @param {Rpc|string|URL} rpc - RPC node information required to call `account_info`
- */
- refresh (rpc: Rpc | string | URL): Promise<void>
- /**
- * Validates a Nano address with 'nano' and 'xrb' prefixes.
- * Derived from https://github.com/alecrios/nano-address-validator
- *
- * @param {string} address - Nano address to validate
- * @throws Error if address is undefined, not a string, or an invalid format
- */
- static validate (address: string): asserts address is string
-}
-
-/**
-* Represents a mnemonic phrase that identifies a wallet as defined by BIP-39.
-*/
-export declare class Bip39 {
- #private
- encoder: TextEncoder
- /**
- * SHA-256 hash of entropy that is appended to the entropy and subsequently
- * used to generate the mnemonic phrase.
- *
- * @param {Uint8Array<ArrayBuffer>} entropy - Cryptographically strong pseudorandom data of length N bits
- * @returns {Promise<bigint>} First N/32 bits of the hash as a bigint
- */
- static checksum (entropy: Uint8Array<ArrayBuffer>): Promise<bigint>
- /**
- * Derives a mnemonic phrase from source of entropy or seed.
- *
- * The entropy must be between 16-32 bytes (32-64 characters) to stay within
- * the limit of 128-256 bits defined in BIP-39. Typically, wallets use the
- * maximum entropy allowed.
- *
- * @param {(ArrayBuffer|Uint8Array<ArrayBuffer>)} entropy - Cryptographically secure random value
- * @returns {Promise<Bip39>} Mnemonic phrase created using the BIP-39 wordlist
- */
- static fromEntropy (entropy: ArrayBuffer | Uint8Array<ArrayBuffer>): Promise<Bip39>
- /**
- * Imports and validates an existing mnemonic phrase.
- *
- * The phrase must be valid according to the BIP-39 specification. Typically,
- * wallets use the maximum of 24 words.
- *
- * @param {string} phrase - String of 12, 15, 18, 21, or 24 words
- * @returns {Promise<Bip39>} Mnemonic phrase validated using the BIP-39 wordlist
- */
- static fromPhrase (phrase: string): Promise<Bip39>
- /**
- * Validates a mnemonic phrase meets the BIP-39 specification.
- *
- * @param {string} mnemonic - Mnemonic phrase to validate
- * @returns {Promise<boolean>} True if the mnemonic phrase is valid
- */
- static validate (mnemonic: string): Promise<boolean>
- private constructor ()
- /**
- * BIP-39 mnemonic phrase, normlized using Normalization Form Compatibility
- * Decomposition (NFKD).
- */
- get phrase (): string | undefined
- /**
- * Erases seed bytes and releases variable references.
- */
- destroy (): void
- /**
- * Converts the mnemonic phrase to a BIP-39 seed.
- *
- * A passphrase string can be specified. If the passphrase is undefined, null,
- * or not a string, the empty string ("") is used instead.
- *
- * @param {string} [passphrase=''] - Used as the PBKDF2 salt. Default: ""
- * @returns {Promise<Uint8Array<ArrayBuffer>>} Promise for seed as bytes
- */
- toBip39Seed (passphrase: string): Promise<Uint8Array<ArrayBuffer>>
- /**
- * Converts the mnemonic phrase to a BIP-39 seed.
- *
- * A passphrase string can be specified. If the passphrase is undefined, null,
- * or not a string, the empty string ("") is used instead.
- *
- * @param {string} [passphrase=''] - Used as the PBKDF2 salt. Default: ""
- * @returns {Promise<string>} Promise for seed as hexadecimal string
- */
- toBip39Seed (passphrase: string, format: 'hex'): Promise<string>
- /**
- * Converts the mnemonic phrase to a BLAKE2b seed.
- *
- * @returns {Uint8Array<ArrayBuffer>} Seed as bytes
- */
- toBlake2bSeed (): Uint8Array<ArrayBuffer>
- /**
- * Converts the mnemonic phrase to a BLAKE2b seed.
- *
- * @param {string} format
- * @returns {string} Seed as hexadecimal string
- */
- toBlake2bSeed (format: 'hex'): string
- /**
- * https://github.com/bitcoin/bips/blob/master/bip-0039/english.txt
- */
- static wordlist: readonly string[]
-}
-
-/**
-* Implementation derived from blake2b@2.1.4. Copyright 2017 Emil Bay
-* <github@tixz.dk> (https://github.com/emilbayes/blake2b). See LICENSES/ISC.txt
-*
-* Modified to use BigUint64 values, eliminate dependencies, port to TypeScript,
-* and embed in web workers.
-*
-* Original source commit: https://github.com/emilbayes/blake2b/blob/1f63e02e3f226642959506cdaa67c8819ff145cd/index.js
-*/
-export declare class Blake2b {
- #private
- /**
- * Derives account private keys from a wallet seed using the BLAKE2b hashing
- * algorithm.
- *
- * Separately, account public keys are derived from the private key using the
- * Ed25519 key algorithm, and account addresses are derived from the public key
- * as described in the Nano documentation.
- * https://docs.nano.org/integration-guides/the-basics/
- *
- * @param {ArrayBuffer} seed - 32-byte secret seed of the wallet
- * @param {number} index - 4-byte index of account to derive
- * @returns {ArrayBuffer} Private key for the account
- */
- static ckd (seed: ArrayBuffer, index: number): Promise<ArrayBuffer>
- static get OUTBYTES_MIN (): 1
- static get OUTBYTES_MAX (): 64
- static get KEYBYTES_MIN (): 1
- static get KEYBYTES_MAX (): 64
- static get SALTBYTES (): 16
- static get PERSONALBYTES (): 16
- static get IV (): bigint[]
- static get SIGMA (): number[][]
- /**
- * Creates a BLAKE2b hashing context.
- *
- * @param {number} length - Output length between 1-64 bytes
- * @param {Uint8Array} [key] - (_optional_) Used for keyed hashing (MAC and PRF)
- * @param {Uint8Array} [salt] - (_optional_) Used to simplify randomized hashing for digital signatures
- * @param {Uint8Array} [personal] - (_optional_) Arbitrary user-specified value
- */
- constructor (length: number, key?: Uint8Array<ArrayBuffer>, salt?: Uint8Array<ArrayBuffer>, personal?: Uint8Array<ArrayBuffer>)
- update (input: ArrayBuffer | Uint8Array): Blake2b
- digest (): Uint8Array<ArrayBuffer>
-}
-
-/**
-* Represents a block as defined by the Nano cryptocurrency protocol.
-*/
-export declare class Block {
- #private
- [key: string]: bigint | string | Account | Function | Uint8Array<ArrayBuffer> | 'send' | 'receive' | 'change' | undefined
- subtype?: 'send' | 'receive' | 'change'
- account: Account
- balance: bigint
- previous: Uint8Array<ArrayBuffer>
- representative?: Account
- link?: Uint8Array<ArrayBuffer>
- signature?: string
- work?: string
- /**
- * Initialize a block with the current state of an account so that it can
- * subsequently be configured as a change, receive, or send transaction.
- *
- * All parameters are eventually required in order to initialize the block, but
- * but if `account` is an Account class object, its properties can be used for
- * the other parameters instead of passing them into the constructor.
- *
- * @param {(string|Account)} account - Target of the transaction; can include `balance`, `frontier`, `representative`
- * @param {(bigint|number|string)} [balance] - Current balance of the target account in raw
- * @param {string} [previous] - Current frontier block hash of the target account
- * @param {(string|Account)} [representative] - Current representative of the target account
- */
- constructor (account: string | Account, balance?: bigint | number | string, previous?: string, representative?: string | Account)
- /**
- * Calculates the block hash using Blake2b.
- *
- * @returns {string} Hexadecimal representation of 32-byte hash of block data
- */
- get hash (): string
- /**
- * Converts the block to JSON format as expected by the `process` RPC.
- *
- * @returns {string} JSON representation of the block
- */
- toJSON (): {
- [key: string]: string
- }
- /**
- * Set the subtype, link, and target account to configure this as a change
- * representative block.
- *
- * @param {(string|Account)} account - Account to choose as representative, or its address or public key
- * @returns {Block} This block with link, representative, and subtype configured
- */
- change (representative: string | Account): Block
- /**
- * Calculates proof-of-work using a pool of Web Workers.
- *
- * A successful response sets the `work` property.
- */
- pow (work?: string): Promise<Block>
- /**
- * Sends the block to a node for processing on the network.
- *
- * The block must already be signed (see `sign()` for more information).
- * The block must also have a `work` value.
- *
- * @param {Rpc|string|URL} rpc - RPC node information required to call `process`
- * @returns {Promise<string>} Hash of the processed block
- */
- process (rpc: Rpc): Promise<string>
- /**
- * Set the amount of nano that this block will receive from a corresponding
- * send block.
- *
- * @param {(string|Block)} sendBlock - Corresponding send block or its hash
- * @param {(bigint|number|string)} amount - Amount to be received from sender
- * @param {string} [unit] - Unit of measure for amount (e.g. 'NANO' = 10³⁰ RAW). Default: "RAW"
- * @returns {Block} This block with balance, link, and subtype configured
- */
- receive (sendBlock: string | Block, amount: bigint | number | string, unit?: string): Block
- /**
- * Set the amount of nano that this block will send to a recipient account.
- *
- * @param {(string|Account)} account - Account to target or its address or public key
- * @param {(bigint|number|string)} amount - Amount to send to recipient
- * @param {string} [unit] - Unit of measure for amount (e.g. 'NANO' = 10³⁰ RAW). Default: "RAW"
- * @returns {Block} This block with balance, link, and subtype configured
- */
- send (account: string | Account, amount: bigint | number | string, unit?: string): Block
- /**
- * Sets the `signature` property of the block to a precalculated value.
- *
- * @param {string} signature - 64-byte hexadecimal signature
- * @returns Block with `signature` value set
- */
- sign (signature: string): Block
- /**
- * Signs the block using a private key. If successful, the result is stored in
- * the `signature` property of the block.
- *
- * @param {string} [key] - 32-byte hexadecimal private key to use for signing
- * @returns Block with `signature` value set
- */
- sign (key: string): Promise<Block>
- /**
- * Signs the block using a Wallet. If successful, the result is stored in
- * the `signature` property of the block. The wallet must be unlocked prior to
- * signing.
- *
- * @param {Wallet} wallet - Wallet to use for signing
- * @param {number} index - Account in wallet to use for signing
- * @returns Block with `signature` value set
- */
- sign (wallet: Wallet, index: number): Promise<Block>
- /**
- * Signs the block using a Ledger hardware wallet. If that fails, an error is
- * thrown with the status code from the device. If successful, the result is
- * stored in the `signature` property of the block. The wallet must be unlocked
- * prior to signing.
- *
- * @param {number} index - Account index between 0x0 and 0x7fffffff
- * @param {object} [frontier] - JSON of frontier block for offline signing
- * @returns Block with `signature` value set
- */
- sign (wallet: Wallet, index: number, frontier?: Block): Promise<Block>
- /**
- * Verifies the signature of the block. If a key is not provided, the public
- * key of the block's account will be used if it exists.
- *
- * @param {string} [key] - Hexadecimal-formatted public key to use for verification
- * @returns {boolean} True if block was signed by the matching private key
- */
- verify (key?: string): Promise<boolean>
-}
-
-export type BlockInfo = {
- blocks: {
- [hash: string]: {
- [p: string]: string
- } & {
- contents: {
- [p: string]: string
- }
- }
- }
-}
-
-export type Data = boolean | number | number[] | string | string[] | Account | ArrayBuffer | CryptoKey | { [key: string]: Data }
+export type Data = boolean | number | number[] | string | string[] | ArrayBuffer | CryptoKey | { [key: string]: Data }
export type NamedData<T extends Data = Data> = {
[key: string]: T
}
-
-export type KeyPair = {
- index?: number
- privateKey?: string | Uint8Array<ArrayBuffer>
- publicKey?: string | Uint8Array<ArrayBuffer>
-}
-
-export type LedgerStatus = 'UNSUPPORTED' | 'DISCONNECTED' | 'BUSY' | 'LOCKED' | 'CONNECTED'
-
-interface LedgerResponse {
- status: string
-}
-
-interface LedgerVersionResponse extends LedgerResponse {
- name: string | null,
- version: string | null
-}
-
-interface LedgerAccountResponse extends LedgerResponse {
- publicKey: string | null,
- address: string | null
-}
-
-interface LedgerSignResponse extends LedgerResponse {
- signature: string | null,
- hash?: string
-}
-
-/**
-* Ledger hardware wallet created by communicating with a Ledger device via ADPU
-* calls. This wallet does not feature any seed nor mnemonic phrase as all
-* private keys are held in the secure chip of the device. As such, the user
-* is responsible for using Ledger technology to back up these pieces of data.
-*
-* https://github.com/roosmaa/ledger-app-nano/blob/master/doc/nano.md
-*/
-export declare class Ledger {
- #private
- static get UsbVendorId (): 0x2c97
- /**
- * Check which transport protocols are supported by the browser and return the
- * transport type according to the following priorities: HID, Bluetooth, USB.
- */
- static get isUnsupported (): boolean
- /**
- * Status of the Ledger device connection.
- *
- * DISCONNECTED | BUSY | LOCKED | CONNECTED
- */
- static get status (): LedgerStatus
- /**
- * Request an account at a specific BIP-44 index.
- *
- * @returns Response object containing command status, public key, and address
- */
- static account (index?: number, show?: boolean): Promise<LedgerAccountResponse>
- /**
- * Check if the Nano app is currently open and set device status accordingly.
- *
- * @param {string} [api] Transport interface to use
- * @returns Device status as follows:
- * - DISCONNECTED: Failed to communicate properly with the app
- * - BUSY: Nano app is not currently open
- * - LOCKED: Nano app is open but the device locked after a timeout
- * - CONNECTED: Nano app is open and listening
- */
- static connect (api?: 'hid' | 'ble' | 'usb'): Promise<LedgerStatus>
- /**
- * Clears Ledger connections from all device interfaces.
- */
- static disconnect (): void
- /**
- * Sign a block with the Ledger device.
- *
- * @param {number} index - Account number
- * @param {Block} block - Block data to sign
- * @param {Block} [frontier] - Previous block data to cache in the device
- */
- static sign (index: number, block: Block, frontier?: Block): Promise<string>
- /**
- * Update cache from raw block data. Suitable for offline use.
- *
- * @param {number} index - Account number
- * @param {object} block - JSON-formatted block data
- */
- static updateCache (index: number, block: Block): Promise<LedgerResponse>
- /**
- * Update cache from a block hash by calling out to a node. Suitable for online
- * use only.
- *
- * @param {number} index - Account number
- * @param {string} hash - Hexadecimal block hash
- * @param {Rpc} rpc - Rpc class object with a node URL
- */
- static updateCache (index: number, hash: string, rpc: Rpc): Promise<LedgerResponse>
- /**
- * Checks whether a given seed matches the wallet seed. The wallet must be
- * unlocked prior to verification.
- *
- * @param {string} seed - Hexadecimal seed to be matched against the wallet data
- * @returns True if input matches wallet seed
- */
- static verify (seed: string): Promise<boolean>
- /**
- * Checks whether a given mnemonic phrase matches the wallet mnemonic. If a
- * personal salt was used when generating the mnemonic, it cannot be verified.
- * The wallet must be unlocked prior to verification.
- *
- * @param {string} mnemonic - Phrase to be matched against the wallet data
- * @returns True if input matches wallet mnemonic
- */
- static verify (mnemonic: string): Promise<boolean>
-}
-
-/**
-* Represents a basic address book of Nano accounts. Multiple addresses can be
-* saved under one nickname.
-*/
-export declare class Rolodex {
- static get DB_NAME (): 'Rolodex'
- /**
- * Adds an address to the rolodex under a specific nickname.
- *
- * If the name exists, add the address as a new association to that name. If
- * the account exists under a different name, update the name. If no matches
- * are found at all, add a new entry.
- *
- * @param {string} name - Contact alias for the address
- * @param {string} address - Nano account address
- * @returns {Promise<boolean>} Promise for true if name and address are added to the rolodex, else false
- */
- static add (name: string, address: string): Promise<boolean>
- /**
- * Removes a Nano address from its related contact in the rolodex.
- *
- * @param {string} address - Nano account address
- * @returns {Promise<boolean>} Promise for true if address successfully removed, else false
- */
- static deleteAddress (address: string): Promise<boolean>
- /**
- * Removes a contact and its related Nano addresses from the rolodex.
- *
- * @param {string} name - Contact name to delete
- * @returns {Promise<boolean>} Promise for true if name and related addresses successfully removed, else false
- */
- static deleteName (name: string): Promise<boolean>
- /**
- * Gets all Nano account addresses associated with a name from the rolodex.
- *
- * @param {string} name - Alias to look up
- * @returns {Promise<string[]>} Promise for a list of Nano addresses associated with the name
- */
- static getAddresses (name: string): Promise<string[]>
- /**
- * Gets all names stored in the rolodex.
- *
- * @returns {Promise<string[]>} Promise for a list of all names stored in the rolodex
- */
- static getAllNames (): Promise<string[]>
- /**
- * Gets the name associated with a specific Nano address from the rolodex.
- *
- * @param {string} address - Nano account address
- * @returns {Promise<string|null>} Promise for the name associated with the address, or null if not found
- */
- static getName (address: string): Promise<string | null>
- /**
- * Verifies whether the public key of any Nano address saved under a specific
- * name in the rolodex was used to sign a specific set of data.
- *
- * @param {string} name - Alias to look up
- * @param {string} signature - Signature to use for verification
- * @param {...string} data - Signed data to verify
- * @returns {Promise<boolean>} True if the signature was used to sign the data, else false
- */
- static verify (name: string, signature: string, ...data: string[]): Promise<boolean>
-}
-
-/**
-* Represents a Nano network node. It primarily consists of a URL which will
-* accept RPC calls, and an optional API key header construction can be passed if
-* required by the node. Once instantiated, the Rpc object can be used to call
-* any action supported by the Nano protocol. The URL protocol must be HTTPS; any
-* other value will be changed automatically.
-*/
-export declare class Rpc {
- #private
- constructor (url: string | URL, apiKeyName?: string)
- /**
- * Sends a nano RPC call to a node endpoint.
- *
- * @param {string} action - Nano protocol RPC call to execute
- * @param {object} [data] - JSON to send to the node as defined by the action
- * @returns {Promise<any>} JSON-formatted RPC results from the node
- */
- call (action: string, data?: {
- [key: string]: unknown
- }): Promise<any>
-}
-
-type SweepResult = {
- status: "success" | "error"
- address: string
- message: string
-}
-
-/**
-* Converts a decimal amount of nano from one unit divider to another.
-*
-* @param {(bigint|number|string)} amount - Decimal amount to convert
-* @param {string} inputUnit - Current denomination
-* @param {string} outputUnit - Desired denomination
-* @param {string} [format] - Data type of output
-*/
-export declare function convert (amount: bigint | number | string, inputUnit: string, outputUnit: string): string
-export declare function convert (amount: bigint | number | string, inputUnit: string, outputUnit: string, format: 'bigint'): bigint
-export declare function convert (amount: bigint | number | string, inputUnit: string, outputUnit: string, format: 'number'): number
-export declare function convert (amount: bigint | number | string, inputUnit: string, outputUnit: string, format: 'string'): string
-declare function hash (data: string | string[], encoding?: 'hex'): Uint8Array<ArrayBuffer>
-/**
-* Signs arbitrary strings with a private key using the Ed25519 signature scheme.
-* The strings are first hashed to a 32-byte value using BLAKE2b.
-*
-* @param {string | Uint8Array<ArrayBuffer>} key - Hexadecimal-formatted private key to use for signing
-* @param {...string} input - Data to be signed
-* @returns {Promise<string>} Hexadecimal-formatted signature
-*/
-export declare function sign (key: string | Uint8Array<ArrayBuffer>, ...input: string[]): Promise<string>
-/**
-* Collects the funds from a specified range of accounts in a wallet and sends
-* them all to a single recipient address. Hardware wallets are unsupported.
-*
-* @param {Rpc|string|URL} rpc - RPC node information required to refresh accounts, calculate PoW, and process blocks
-* @param {(Wallet)} wallet - Wallet from which to sweep funds
-* @param {string} recipient - Destination address for all swept funds
-* @param {number} [from=0] - Starting account index to sweep
-* @param {number} [to=from] - Ending account index to sweep
-* @returns An array of results including both successes and failures
- */
-export declare function sweep (rpc: Rpc | string | URL, wallet: Wallet, recipient: string, from?: number, to?: number): Promise<SweepResult[]>
-/**
-* Verifies the signature of arbitrary strings using a public key.
-*
-* @param {string | Uint8Array<ArrayBuffer>} key - Hexadecimal-formatted public key to use for verification
-* @param {string} signature - Hexadcimal-formatted signature
-* @param {...string} input - Data to be verified
-* @returns {Promise<boolean>} True if the data was signed by the public key's matching private key
-*/
-export declare function verify (key: string | Uint8Array<ArrayBuffer>, signature: string, ...input: string[]): Promise<boolean>
-export declare const Tools: {
- convert: typeof convert
- hash: typeof hash
- sign: typeof sign
- sweep: typeof sweep
- verify: typeof verify
-}
-
-export type WalletType = 'BIP-44' | 'BLAKE2b' | 'Ledger'
-
-/**
-* Represents a wallet containing numerous Nano accounts derived from a single
-* source, the form of which can vary based on the type of wallet. Currently,
-* three types of wallets are supported: BIP-44, BLAKE2b, and Ledger.
-*/
-export declare class Wallet {
- #private
- static get DB_NAME (): 'Wallet'
- /**
- * Retrieves all wallets with encrypted secrets and unencrypted metadata from
- * the database.
- *
- * @returns id, type, iv, salt, encrypted
- */
- static backup (): Promise<NamedData[]>
- /**
- * Creates a new hardware wallet manager.
- *
- * @param {string} type - Wallet manufacturer
- * @returns {Wallet} A newly instantiated Wallet
- */
- static create (type: 'Ledger'): Promise<Wallet>
- /**
- * Creates a new HD wallet by using an entropy value generated using a
- * cryptographically strong pseudorandom number generator.
- *
- * @param {string} type - Algorithm used to generate wallet and child accounts
- * @param {string} password - Encrypts the wallet to lock and unlock it
- * @param {string} [salt=''] - Used when generating the final seed
- * @returns {Wallet} A newly instantiated Wallet
- */
- static create (type: 'BIP-44' | 'BLAKE2b', password: string, mnemonicSalt?: string): Promise<Wallet>
- /**
- * Imports an existing HD wallet by using an entropy value generated using a
- * cryptographically strong pseudorandom number generator.NamedD
- *
- * @param {string} type - Algorithm used to generate wallet and child accounts
- * @param {string} password - Encrypts the wallet to lock and unlock it. Discard as soon as possible after loading the wallet.
- * @param {string} seed - Used to derive child accounts
- * @returns Wallet in a locked state
- */
- static load (type: 'BIP-44' | 'BLAKE2b', password: string, seed: string): Promise<Wallet>
- /**
- * Imports an existing HD wallet by using an entropy value generated using a
- * cryptographically strong pseudorandom number generator.
- *
- * @param {string} type - Algorithm used to generate wallet and child accounts
- * @param {string} password - Encrypts the wallet to lock and unlock it. Discard as soon as possible after loading the wallet.
- * @param {string} mnemonicPhrase - Used to derive the wallet seed
- * @param {string} [mnemonicSalt] - Used to alter the seed derived from the mnemonic phrase
- * @returns Wallet in a locked state
- */
- static load (type: 'BIP-44' | 'BLAKE2b', password: string, mnemonicPhrase: string, mnemonicSalt?: string): Promise<Wallet>
- /**
- * Instantiates a Wallet from an existing record in the database using its UUID.
- *
- * @param {string} id - Generated when the wallet was created or imported
- * @returns {Promise<Wallet>} Restored locked Wallet
- */
- static restore (id: string): Promise<Wallet>
- /**
- * Instantiates Wallet objects from records in the database.
- *
- * @param {string} id - Generated when the wallet was created or imported
- * @returns {Promise<Wallet[]>} Restored locked Wallets
- */
- static restore (): Promise<Wallet[]>
- constructor (type: WalletType, id?: string)
- /**
- * @returns UUID of the wallet.
- */
- get id (): string
- /**
- * @returns True if the wallet is locked, else false
- */
- get isLocked (): boolean
- /**
- * Algorithm or device used to create wallet and derive accounts.
- */
- get type (): WalletType
- /**
- * Set when calling `create()`. Self-destructs after the first read.
- * @returns Mnemonic phrase used to derive the wallet seed.
- */
- get mnemonic (): string | undefined
- /**
- * Set when calling `create()`. Self-destructs after the first read.
- * @returns Seed used to derive accounts.
- */
- get seed (): string | undefined
- /**
- * Retrieves an account from a wallet using its child key derivation function.
- * Defaults to the first account at index 0.
- *
- * The returned object will have keys corresponding with the requested range
- * of account indexes. The value of each key will be the Account derived for
- * that index in the wallet.
- *
- * ```
- * const account = await wallet.account(1)
- * // outputs the second account of the wallet
- * console.log(account)
- * // { address: <...>, publicKey: <...>, index: 1, <etc...> }
- * ```
- *
- * @param {number} index - Wallet index of account. Default: 0
- * @returns Promise for the Account at the specified index
- */
- account (index?: number): Promise<Account>
- /**
- * Retrieves accounts from a wallet using its child key derivation function.
- * Defaults to the first account at index 0.
- *
- * The returned object will have keys corresponding with the requested range
- * of account indexes. The value of each key will be the Account derived for
- * that index in the wallet.
- *
- * ```
- * const accounts = await wallet.accounts(0, 1))
- * // outputs the first and second account of the wallet
- * console.log(accounts)
- * // {
- * // 0: {
- * // address: <...>,
- * // publicKey: <...>,
- * // index: 0,
- * // <etc...>
- * // },
- * // 1: {
- * // address: <...>,
- * // publicKey: <...>,
- * // index: 1,
- * // <etc...>
- * // }
- * // }
- * // individual accounts can be referenced using array index notation
- * console.log(accounts[1])
- * // { address: <...>, publicKey: <...>, index: 1, <etc...> }
- * ```
- *
- * If `from` is greater than `to`, their values will be swapped.
- * @param {number} [from=0] - Start index of accounts. Default: 0
- * @param {number} [to=from] - End index of accounts. Default: `from`
- * @returns {Promise<Map<number, Account>>} Promise for a list of Accounts at the specified indexes
- */
- accounts (from?: number, to?: number): Promise<Map<number, Account>>
- /**
- * Configures Ledger connection settings.
- * @param {string} connection - Transport interface to use
- */
- config (settings: {
- connection: 'hid' | 'ble' | 'usb'
- }): Promise<void>
- /**
- * Configures vault worker settings.
- * @param {number} timeout - Measured in seconds of inactivity before wallet automatically locks
- */
- config (settings: {
- timeout: number
- }): Promise<void>
- /**
- * Removes encrypted secrets in storage, releases variable references to
- * allow garbage collection, and terminates vault worker.
- */
- destroy (): Promise<void>
- /**
- * For BIP-44 and BLAKE2b wallets, clears the seed and mnemonic from the vault.
- *
- * For Ledger hardware wallets, revokes permission granted by the user to
- * access the Ledger device. The 'quit app' ADPU command is uncooperative, so
- * this is currently the only way to ensure the connection is severed.
- * `setTimeout` is used to expire any lingering transient user activation.
- */
- lock (): void
- /**
- * Refreshes wallet account balances, frontiers, and representatives from the
- * current state on the network.
- *
- * A successful response will set these properties on each account.
- *
- * @param {(Rpc|string|URL)} rpc - RPC node information required to refresh accounts, calculate PoW, and process blocks
- * @returns {Promise<Map<number, Account>>} Promise for accounts with updated balances, frontiers, and representatives
- */
- refresh (rpc: Rpc | string | URL, from?: number, to?: number): Promise<Map<number, Account>>
- /**
- * Signs arbitrary strings using the private key of the account at the wallet
- * index specified and returns a detached signature as a hexadecimal string.
- * For compatibility with other Nano tools, the data is first hashed to a
- * 32-byte value using BLAKE2b. The wallet must be unlocked prior to signing.
- *
- * @param {number} index - Account to use for signing
- * @param {(string|string[])} data - Arbitrary data to be hashed and signed
- */
- sign (index: number, data: string | string[]): Promise<string>
- /**
- * Signs a block using the private key of the account at the wallet index
- * specified. The signature is appended to the signature field of the block
- * before being returned. The wallet must be unlocked prior to signing.
- *
- * @param {number} index - Account to use for signing
- * @param {Block} block - Block data to be hashed and signed
- */
- sign (index: number, block: Block): Promise<void>
- /**
- * Signs a block using a Ledger hardware wallet at the wallet index specified.
- * The signature is appended to the signature field of the block before being
- * returned. The wallet must be unlocked prior to signing.
- *
- * @param {number} index - Account to use for signing
- * @param {Block} block - Block data to be hashed and signed
- * @param {Block} [frontier] - Previous block data to be cached by Ledger wallet
- */
- sign (index: number, block: Block, frontier?: Block): Promise<void>
- /**
- * Attempts to connect to the Ledger device.
- */
- unlock (): Promise<void>
- /**
- * Unlocks the wallet using the same password as used prior to lock it.
- *
- * @param {string} password Used previously to lock the wallet
- */
- unlock (password: string): Promise<void>
- /**
- * Fetches the lowest-indexed unopened account from a wallet in sequential
- * order. An account is unopened if it has no frontier block.
- *
- * @param {Rpc|string|URL} rpc - RPC node information required to refresh accounts, calculate PoW, and process blocks
- * @param {number} batchSize - Number of accounts to fetch and check per RPC callout
- * @param {number} from - Account index from which to start the search
- * @returns {Promise<Account>} The lowest-indexed unopened account belonging to the wallet
- */
- unopened (rpc: Rpc, batchSize?: number, from?: number): Promise<Account>
- /**
- * Updates the password used to encrypt the wallet. The wallet must be unlocked
- * prior to update.
- *
- * @param {string} password Used to re-encrypt the wallet
- */
- update (password: string): Promise<void>
- /**
- * Checks whether a given seed matches the wallet seed. The wallet must be
- * unlocked prior to verification.
- *
- * @param {string} seed - Hexadecimal seed to be matched against the wallet data
- * @returns True if input matches wallet seed
- */
- verify (seed: string): Promise<boolean>
- /**
- * Checks whether a given mnemonic phrase matches the wallet mnemonic. If a
- * personal salt was used when generating the mnemonic, it cannot be verified.
- * The wallet must be unlocked prior to verification.
- *
- * @param {string} mnemonic - Phrase to be matched against the wallet data
- * @returns True if input matches wallet mnemonic
- */
- verify (mnemonic: string): Promise<boolean>
-}
import { failures, passes } from './GLOBALS.mjs'
import './test.runner-check.mjs'
-import './test.blake2b.mjs'
-import './test.blocks.mjs'
-import './test.calculate-pow.mjs'
-import './test.create-wallet.mjs'
-import './test.derive-accounts.mjs'
-import './test.import-wallet.mjs'
+// import './test.blake2b.mjs'
+// import './test.blocks.mjs'
+// import './test.calculate-pow.mjs'
+// import './test.create-wallet.mjs'
+// import './test.derive-accounts.mjs'
+// import './test.import-wallet.mjs'
import './test.ledger.mjs'
-import './test.lock-unlock.mjs'
-import './test.manage-rolodex.mjs'
-import './test.refresh-accounts.mjs'
-import './test.tools.mjs'
-import './test.wallet-sign.mjs'
+// import './test.lock-unlock.mjs'
+// import './test.manage-rolodex.mjs'
+// import './test.refresh-accounts.mjs'
+// import './test.tools.mjs'
+// import './test.wallet-sign.mjs'
console.log('%cTESTING COMPLETE', 'color:orange;font-weight:bold')
console.log('%cPASS: ', 'color:green;font-weight:bold', passes.length)
import { NANO_TEST_VECTORS } from './VECTORS.mjs'
/**
-* @type {typeof import('../dist/types.d.ts').Wallet}
+* @type {typeof import('../dist/types/main.d.ts').Wallet}
*/
let Wallet
if (isNode) {
import { NANO_TEST_VECTORS } from './VECTORS.mjs'
/**
-* @type {typeof import('../dist/types.d.ts').Block}
+* @type {typeof import('../dist/types/main.d.ts').Block}
*/
let Block
if (isNode) {
import { NANO_TEST_VECTORS } from './VECTORS.mjs'
/**
-* @type {typeof import('../dist/types.d.ts').Wallet}
+* @type {typeof import('../dist/types/main.d.ts').Wallet}
*/
let Wallet
if (isNode) {
import { BLAKE2B_TEST_VECTORS } from './VECTORS.mjs'\r
\r
/**\r
-* @type {typeof import('../dist/types.d.ts').Blake2b}\r
+* @type {typeof import('../dist/types/main.d.ts').Blake2b}\r
*/\r
let Blake2b\r
if (isNode) {\r
import { CUSTOM_TEST_VECTORS, NANO_TEST_VECTORS } from './VECTORS.mjs'\r
\r
/**\r
-* @type {typeof import('../dist/types.d.ts').Account}\r
+* @type {typeof import('../dist/types/main.d.ts').Account}\r
*/\r
let Account\r
/**\r
-* @type {typeof import('../dist/types.d.ts').Block}\r
+* @type {typeof import('../dist/types/main.d.ts').Block}\r
*/\r
let Block\r
/**\r
-* @type {typeof import('../dist/types.d.ts').Wallet}\r
+* @type {typeof import('../dist/types/main.d.ts').Wallet}\r
*/\r
let Wallet\r
if (isNode) {\r
import { NANO_TEST_VECTORS } from './VECTORS.mjs'\r
\r
/**\r
-* @type {typeof import('../dist/types.d.ts').Blake2b}\r
+* @type {typeof import('../dist/types/main.d.ts').Blake2b}\r
*/\r
let Blake2b\r
/**\r
-* @type {typeof import('../dist/types.d.ts').Block}\r
+* @type {typeof import('../dist/types/main.d.ts').Block}\r
*/\r
let Block\r
if (isNode) {\r
import { NANO_TEST_VECTORS } from './VECTORS.mjs'\r
\r
/**\r
-* @type {typeof import('../dist/types.d.ts').Wallet}\r
+* @type {typeof import('../dist/types/main.d.ts').Wallet}\r
*/\r
let Wallet\r
if (isNode) {\r
import { NANO_TEST_VECTORS } from './VECTORS.mjs'\r
\r
/**\r
-* @type {typeof import('../dist/types.d.ts').Wallet}\r
+* @type {typeof import('../dist/types/main.d.ts').Wallet}\r
*/\r
let Wallet\r
if (isNode) {\r
import { BIP32_TEST_VECTORS, CUSTOM_TEST_VECTORS, NANO_TEST_VECTORS, TREZOR_TEST_VECTORS } from './VECTORS.mjs'\r
\r
/**\r
-* @type {typeof import('../dist/types.d.ts').Account}\r
+* @type {typeof import('../dist/types/main.d.ts').Account}\r
*/\r
let Account\r
/**\r
-* @type {typeof import('../dist/types.d.ts').Wallet}\r
+* @type {typeof import('../dist/types/main.d.ts').Wallet}\r
*/\r
let Wallet\r
if (isNode) {\r
import { CUSTOM_TEST_VECTORS, NANO_TEST_VECTORS } from './VECTORS.mjs'
/**
-* @type {typeof import('../dist/types.d.ts').Account}
+* @type {typeof import('../dist/types/main.d.ts').Account}
*/
let Account
/**
-* @type {typeof import('../dist/types.d.ts').Block}
+* @type {typeof import('../dist/types/main.d.ts').Block}
*/
let Block
/**
-* @type {typeof import('../dist/types.d.ts').Ledger}
+* @type {typeof import('../dist/types/main.d.ts').Ledger}
*/
let Ledger
/**
-* @type {typeof import('../dist/types.d.ts').Rpc}
+* @type {typeof import('../dist/types/main.d.ts').Rpc}
*/
let Rpc
/**
-* @type {typeof import('../dist/types.d.ts').Wallet}
+* @type {typeof import('../dist/types/main.d.ts').Wallet}
*/
let Wallet
import { NANO_TEST_VECTORS, TREZOR_TEST_VECTORS } from './VECTORS.mjs'\r
\r
/**\r
-* @type {typeof import('../dist/types.d.ts').Account}\r
+* @type {typeof import('../dist/types/main.d.ts').Account}\r
*/\r
let Account\r
/**\r
-* @type {typeof import('../dist/types.d.ts').Wallet}\r
+* @type {typeof import('../dist/types/main.d.ts').Wallet}\r
*/\r
let Wallet\r
if (isNode) {\r
import { NANO_TEST_VECTORS } from './VECTORS.mjs'
/**
-* @type {typeof import('../dist/types.d.ts').Rolodex}
+* @type {typeof import('../dist/types/main.d.ts').Rolodex}
*/
let Rolodex
/**
import { NANO_TEST_VECTORS } from './VECTORS.mjs'
/**
-* @type {typeof import('../dist/types.d.ts').Account}
+* @type {typeof import('../dist/types/main.d.ts').Account}
*/
let Account
/**
-* @type {typeof import('../dist/types.d.ts').Rpc}
+* @type {typeof import('../dist/types/main.d.ts').Rpc}
*/
let Rpc
/**
-* @type {typeof import('../dist/types.d.ts').Wallet}
+* @type {typeof import('../dist/types/main.d.ts').Wallet}
*/
let Wallet
if (isNode) {
import { MAX_RAW, MAX_SUPPLY, NANO_TEST_VECTORS } from './VECTORS.mjs'\r
\r
/**\r
-* @type {typeof import('../dist/types.d.ts').Account}\r
+* @type {typeof import('../dist/types/main.d.ts').Account}\r
*/\r
let Account\r
/**\r
-* @type {typeof import('../dist/types.d.ts').Block}\r
+* @type {typeof import('../dist/types/main.d.ts').Block}\r
*/\r
let Block\r
/**\r
-* @type {typeof import('../dist/types.d.ts').Rpc}\r
+* @type {typeof import('../dist/types/main.d.ts').Rpc}\r
*/\r
let Rpc\r
/**\r
-* @type {typeof import('../dist/types.d.ts').Tools}\r
+* @type {typeof import('../dist/types/main.d.ts').Tools}\r
*/\r
let Tools\r
/**\r
-* @type {typeof import('../dist/types.d.ts').Wallet}\r
+* @type {typeof import('../dist/types/main.d.ts').Wallet}\r
*/\r
let Wallet\r
if (isNode) {\r