@leofcoin/peernet 1.2.22 → 1.2.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/release.yml +34 -0
- package/exports/browser/{browser-DEjI2nFg.js → browser-BOiH47em.js} +1 -1
- package/exports/browser/{browser-tK3uOLQV.js → browser-BuaFyOQj.js} +1 -1
- package/exports/browser/{client-Ba1cHcxF.js → client-B2wkkpij.js} +4 -4
- package/exports/browser/{identity-CjBX8cWv.js → identity-DWchlbmt.js} +49 -3
- package/exports/browser/identity.js +1 -1
- package/exports/browser/{index-DIhxISkU.js → index-s61gSKAd.js} +1 -1
- package/exports/browser/{messages-BX59GgBQ.js → messages-CZ-3jxiD.js} +2 -2
- package/exports/browser/{peernet-D3z5pEBD.js → peernet-Coi40mR_.js} +3 -3
- package/exports/browser/peernet.js +2 -2
- package/exports/identity.js +49 -3
- package/exports/store.js +0 -3
- package/exports/types/identity.d.ts +9 -1
- package/package.json +7 -2
- package/src/identity.ts +60 -1
- package/test/peernet.test.js +29 -2
- package/test-output.log +0 -84
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: Release package
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
|
|
6
|
+
permissions:
|
|
7
|
+
contents: read
|
|
8
|
+
id-token: write
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: release-package
|
|
12
|
+
cancel-in-progress: false
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
publish:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v7
|
|
19
|
+
|
|
20
|
+
- uses: actions/setup-node@v7
|
|
21
|
+
with:
|
|
22
|
+
node-version: 24
|
|
23
|
+
registry-url: https://registry.npmjs.org
|
|
24
|
+
cache: npm
|
|
25
|
+
|
|
26
|
+
- name: Use supported npm CLI
|
|
27
|
+
run: npm install --global npm@11.17.0
|
|
28
|
+
|
|
29
|
+
- run: npm ci
|
|
30
|
+
- run: npm run build
|
|
31
|
+
- run: npm test
|
|
32
|
+
|
|
33
|
+
- name: Publish with provenance
|
|
34
|
+
run: npm publish --access public --provenance
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { L as LittlePubSub, d as deflate_1, i as inflate_1, c as createDebugger } from './peernet-
|
|
2
|
-
import './identity-
|
|
1
|
+
import { L as LittlePubSub, d as deflate_1, i as inflate_1, c as createDebugger } from './peernet-Coi40mR_.js';
|
|
2
|
+
import './identity-DWchlbmt.js';
|
|
3
3
|
import 'crypto';
|
|
4
4
|
import './value-C3vAp-wb.js';
|
|
5
5
|
|
|
@@ -232,7 +232,7 @@ class SocketRequestClient {
|
|
|
232
232
|
const init = async () => {
|
|
233
233
|
// @ts-ignore
|
|
234
234
|
if (!globalThis.WebSocket && !this.#experimentalWebsocket)
|
|
235
|
-
globalThis.WebSocket = (await import('./browser-
|
|
235
|
+
globalThis.WebSocket = (await import('./browser-BuaFyOQj.js').then(function (n) { return n.b; })).default.w3cwebsocket;
|
|
236
236
|
const client = new WebSocket(this.#url, this.#protocol);
|
|
237
237
|
if (this.#experimentalWebsocket) {
|
|
238
238
|
client.addEventListener('error', this.onerror);
|
|
@@ -1303,7 +1303,7 @@ class Client {
|
|
|
1303
1303
|
}
|
|
1304
1304
|
}
|
|
1305
1305
|
async #loadNodeWebrtcImplementation() {
|
|
1306
|
-
const koushWrtcModule = await import('./browser-
|
|
1306
|
+
const koushWrtcModule = await import('./browser-BOiH47em.js').then(function (n) { return n.b; });
|
|
1307
1307
|
const koushWrtc = koushWrtcModule.default;
|
|
1308
1308
|
if (!isWrtcImplementation(koushWrtc)) {
|
|
1309
1309
|
throw new Error('@koush/wrtc does not match required wrtc contract');
|
|
@@ -8259,8 +8259,41 @@ function requireBrowser () {
|
|
|
8259
8259
|
var browserExports = requireBrowser();
|
|
8260
8260
|
var qrcode = /*@__PURE__*/getDefaultExportFromCjs(browserExports);
|
|
8261
8261
|
|
|
8262
|
+
const accountDerivationSchemes = [
|
|
8263
|
+
{
|
|
8264
|
+
name: 'current',
|
|
8265
|
+
accountIndex: (index) => index + 1,
|
|
8266
|
+
addressIndex: 1
|
|
8267
|
+
},
|
|
8268
|
+
{
|
|
8269
|
+
name: 'legacy-v1',
|
|
8270
|
+
accountIndex: (index) => index,
|
|
8271
|
+
addressIndex: 0
|
|
8272
|
+
}
|
|
8273
|
+
];
|
|
8274
|
+
const resolveAccountWallets = async (wallet, accounts) => {
|
|
8275
|
+
for (const scheme of accountDerivationSchemes) {
|
|
8276
|
+
const wallets = new Map();
|
|
8277
|
+
let matches = true;
|
|
8278
|
+
for (const [index, [, externalAddress, internalAddress]] of accounts.entries()) {
|
|
8279
|
+
const account = wallet.account(scheme.accountIndex(index));
|
|
8280
|
+
const external = (await account.external(scheme.addressIndex));
|
|
8281
|
+
const internal = (await account.internal(scheme.addressIndex));
|
|
8282
|
+
if ((await external.address) !== externalAddress || (await internal.address) !== internalAddress) {
|
|
8283
|
+
matches = false;
|
|
8284
|
+
break;
|
|
8285
|
+
}
|
|
8286
|
+
wallets.set(externalAddress, external);
|
|
8287
|
+
wallets.set(internalAddress, internal);
|
|
8288
|
+
}
|
|
8289
|
+
if (matches)
|
|
8290
|
+
return wallets;
|
|
8291
|
+
}
|
|
8292
|
+
throw new Error('stored accounts do not match this identity under a supported derivation scheme');
|
|
8293
|
+
};
|
|
8262
8294
|
class Identity {
|
|
8263
8295
|
#wallet;
|
|
8296
|
+
#accountWallets = new Map();
|
|
8264
8297
|
network;
|
|
8265
8298
|
id;
|
|
8266
8299
|
selectedAccount;
|
|
@@ -8298,7 +8331,7 @@ class Identity {
|
|
|
8298
8331
|
this.selectedAccount = new TextDecoder().decode(selected);
|
|
8299
8332
|
}
|
|
8300
8333
|
else {
|
|
8301
|
-
const importee = await import(/* webpackChunkName: "generate-account" */ './index-
|
|
8334
|
+
const importee = await import(/* webpackChunkName: "generate-account" */ './index-s61gSKAd.js');
|
|
8302
8335
|
const { identity, accounts } = await importee.default(password, this.network);
|
|
8303
8336
|
await globalThis.accountStore.put('public', JSON.stringify({ walletId: identity.walletId }));
|
|
8304
8337
|
await globalThis.walletStore.put('version', String(1));
|
|
@@ -8312,13 +8345,26 @@ class Identity {
|
|
|
8312
8345
|
this.#wallet = new MultiWallet(this.network);
|
|
8313
8346
|
const multiWIF = await decrypt(password, base58$1.decode(identity.multiWIF));
|
|
8314
8347
|
await this.#wallet.fromMultiWif(multiWIF);
|
|
8348
|
+
await this.#loadAccountWallets();
|
|
8349
|
+
}
|
|
8350
|
+
async #loadAccountWallets() {
|
|
8351
|
+
const accounts = await this.getAccounts();
|
|
8352
|
+
this.#accountWallets = await resolveAccountWallets(this.#wallet, accounts);
|
|
8353
|
+
if (!this.#accountWallets.has(this.selectedAccount)) {
|
|
8354
|
+
throw new Error(`selected account ${this.selectedAccount} is not part of this identity`);
|
|
8355
|
+
}
|
|
8315
8356
|
}
|
|
8316
8357
|
selectAccount(account) {
|
|
8358
|
+
if (!this.#accountWallets.has(account))
|
|
8359
|
+
throw new Error(`unknown identity account ${account}`);
|
|
8317
8360
|
this.selectedAccount = account;
|
|
8318
8361
|
return walletStore.put('selected-account', account);
|
|
8319
8362
|
}
|
|
8320
8363
|
sign(hash) {
|
|
8321
|
-
|
|
8364
|
+
const wallet = this.#accountWallets.get(this.selectedAccount);
|
|
8365
|
+
if (!wallet)
|
|
8366
|
+
throw new Error(`no signer available for selected account ${this.selectedAccount}`);
|
|
8367
|
+
return wallet.sign(hash.subarray(0, 32));
|
|
8322
8368
|
}
|
|
8323
8369
|
lock(password) {
|
|
8324
8370
|
this.#wallet.lock(password);
|
|
@@ -8344,4 +8390,4 @@ class Identity {
|
|
|
8344
8390
|
}
|
|
8345
8391
|
}
|
|
8346
8392
|
|
|
8347
|
-
export { Identity as I, MultiWallet as M, base58$1 as a, base as b, index as c, index$2 as d, index$4 as e, createSHA512 as f, createSHA384 as g, createSHA256 as h, index$3 as i, createSHA224 as j, createSHA1 as k, encrypt as l, getDefaultExportFromCjs as m };
|
|
8393
|
+
export { Identity as I, MultiWallet as M, base58$1 as a, base as b, index as c, index$2 as d, index$4 as e, createSHA512 as f, createSHA384 as g, createSHA256 as h, index$3 as i, createSHA224 as j, createSHA1 as k, encrypt as l, getDefaultExportFromCjs as m, resolveAccountWallets as r };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { I as default } from './identity-
|
|
1
|
+
export { I as default, r as resolveAccountWallets } from './identity-DWchlbmt.js';
|
|
2
2
|
import 'crypto';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as index$2, b as base, a as base58$1, c as index$3, d as index$4, e as index$5, f as createSHA512, g as createSHA384, h as createSHA256, j as createSHA224, k as createSHA1, I as Identity } from './identity-
|
|
1
|
+
import { i as index$2, b as base, a as base58$1, c as index$3, d as index$4, e as index$5, f as createSHA512, g as createSHA384, h as createSHA256, j as createSHA224, k as createSHA1, I as Identity } from './identity-DWchlbmt.js';
|
|
2
2
|
import { K as KeyPath, a as KeyValue } from './value-C3vAp-wb.js';
|
|
3
3
|
|
|
4
4
|
const getTargets = () => Array.from([]);
|
|
@@ -8615,7 +8615,7 @@ class Peernet {
|
|
|
8615
8615
|
await getAddress();
|
|
8616
8616
|
this.storePrefix = options.storePrefix;
|
|
8617
8617
|
this.root = options.root;
|
|
8618
|
-
const { RequestMessage, ResponseMessage, PeerMessage, PeerMessageResponse, PeernetMessage, DHTMessage, DHTMessageResponse, DataMessage, DataMessageResponse, PsMessage, ChatMessage, PeernetFile } = await import(/* webpackChunkName: "messages" */ './messages-
|
|
8618
|
+
const { RequestMessage, ResponseMessage, PeerMessage, PeerMessageResponse, PeernetMessage, DHTMessage, DHTMessageResponse, DataMessage, DataMessageResponse, PsMessage, ChatMessage, PeernetFile } = await import(/* webpackChunkName: "messages" */ './messages-CZ-3jxiD.js');
|
|
8619
8619
|
/**
|
|
8620
8620
|
* proto Object containing protos
|
|
8621
8621
|
* @type {Object}
|
|
@@ -8662,7 +8662,7 @@ class Peernet {
|
|
|
8662
8662
|
if (this.#starting || this.#started)
|
|
8663
8663
|
return;
|
|
8664
8664
|
this.#starting = true;
|
|
8665
|
-
const importee = await import('./client-
|
|
8665
|
+
const importee = await import('./client-B2wkkpij.js');
|
|
8666
8666
|
/**
|
|
8667
8667
|
* @access public
|
|
8668
8668
|
* @type {PeernetClient}
|
package/exports/identity.js
CHANGED
|
@@ -4,8 +4,41 @@ import { decrypt } from '@leofcoin/identity-utils';
|
|
|
4
4
|
import QrScanner from 'qr-scanner';
|
|
5
5
|
import qrcode from 'qrcode';
|
|
6
6
|
|
|
7
|
+
const accountDerivationSchemes = [
|
|
8
|
+
{
|
|
9
|
+
name: 'current',
|
|
10
|
+
accountIndex: (index) => index + 1,
|
|
11
|
+
addressIndex: 1
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
name: 'legacy-v1',
|
|
15
|
+
accountIndex: (index) => index,
|
|
16
|
+
addressIndex: 0
|
|
17
|
+
}
|
|
18
|
+
];
|
|
19
|
+
const resolveAccountWallets = async (wallet, accounts) => {
|
|
20
|
+
for (const scheme of accountDerivationSchemes) {
|
|
21
|
+
const wallets = new Map();
|
|
22
|
+
let matches = true;
|
|
23
|
+
for (const [index, [, externalAddress, internalAddress]] of accounts.entries()) {
|
|
24
|
+
const account = wallet.account(scheme.accountIndex(index));
|
|
25
|
+
const external = (await account.external(scheme.addressIndex));
|
|
26
|
+
const internal = (await account.internal(scheme.addressIndex));
|
|
27
|
+
if ((await external.address) !== externalAddress || (await internal.address) !== internalAddress) {
|
|
28
|
+
matches = false;
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
wallets.set(externalAddress, external);
|
|
32
|
+
wallets.set(internalAddress, internal);
|
|
33
|
+
}
|
|
34
|
+
if (matches)
|
|
35
|
+
return wallets;
|
|
36
|
+
}
|
|
37
|
+
throw new Error('stored accounts do not match this identity under a supported derivation scheme');
|
|
38
|
+
};
|
|
7
39
|
class Identity {
|
|
8
40
|
#wallet;
|
|
41
|
+
#accountWallets = new Map();
|
|
9
42
|
network;
|
|
10
43
|
id;
|
|
11
44
|
selectedAccount;
|
|
@@ -32,7 +65,7 @@ class Identity {
|
|
|
32
65
|
}
|
|
33
66
|
if (!password) {
|
|
34
67
|
// @ts-ignore
|
|
35
|
-
const importee = await import('./prompts/password.js');
|
|
68
|
+
const importee = await import('./home/runner/work/peernet/peernet/src/prompts/password.js');
|
|
36
69
|
password = await importee.default();
|
|
37
70
|
}
|
|
38
71
|
const accountExists = await globalThis.accountStore.has('public');
|
|
@@ -57,13 +90,26 @@ class Identity {
|
|
|
57
90
|
this.#wallet = new MultiWallet(this.network);
|
|
58
91
|
const multiWIF = await decrypt(password, base58.decode(identity.multiWIF));
|
|
59
92
|
await this.#wallet.fromMultiWif(multiWIF);
|
|
93
|
+
await this.#loadAccountWallets();
|
|
94
|
+
}
|
|
95
|
+
async #loadAccountWallets() {
|
|
96
|
+
const accounts = await this.getAccounts();
|
|
97
|
+
this.#accountWallets = await resolveAccountWallets(this.#wallet, accounts);
|
|
98
|
+
if (!this.#accountWallets.has(this.selectedAccount)) {
|
|
99
|
+
throw new Error(`selected account ${this.selectedAccount} is not part of this identity`);
|
|
100
|
+
}
|
|
60
101
|
}
|
|
61
102
|
selectAccount(account) {
|
|
103
|
+
if (!this.#accountWallets.has(account))
|
|
104
|
+
throw new Error(`unknown identity account ${account}`);
|
|
62
105
|
this.selectedAccount = account;
|
|
63
106
|
return walletStore.put('selected-account', account);
|
|
64
107
|
}
|
|
65
108
|
sign(hash) {
|
|
66
|
-
|
|
109
|
+
const wallet = this.#accountWallets.get(this.selectedAccount);
|
|
110
|
+
if (!wallet)
|
|
111
|
+
throw new Error(`no signer available for selected account ${this.selectedAccount}`);
|
|
112
|
+
return wallet.sign(hash.subarray(0, 32));
|
|
67
113
|
}
|
|
68
114
|
lock(password) {
|
|
69
115
|
this.#wallet.lock(password);
|
|
@@ -89,4 +135,4 @@ class Identity {
|
|
|
89
135
|
}
|
|
90
136
|
}
|
|
91
137
|
|
|
92
|
-
export { Identity as default };
|
|
138
|
+
export { Identity as default, resolveAccountWallets };
|
package/exports/store.js
CHANGED
|
@@ -102,9 +102,6 @@ class Store {
|
|
|
102
102
|
this.root = await init(root, homedir);
|
|
103
103
|
this.version = version;
|
|
104
104
|
this.db = new ClassicLevel(join(this.root, this.name), { valueEncoding: 'view' });
|
|
105
|
-
if (typeof this.db.open === 'function') {
|
|
106
|
-
await this.db.open();
|
|
107
|
-
}
|
|
108
105
|
}
|
|
109
106
|
toKeyPath(key) {
|
|
110
107
|
if (!key.isKeyPath())
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
+
import MultiWallet from '@leofcoin/multi-wallet';
|
|
1
2
|
import type { base58String } from '@vandeurenglenn/base58';
|
|
3
|
+
type StoredAccount = [name: string, externalAddress: string, internalAddress: string];
|
|
4
|
+
type AccountWallet = {
|
|
5
|
+
address: Promise<string>;
|
|
6
|
+
sign: (hash: Uint8Array) => Promise<Uint8Array>;
|
|
7
|
+
};
|
|
8
|
+
export declare const resolveAccountWallets: (wallet: MultiWallet, accounts: StoredAccount[]) => Promise<Map<string, AccountWallet>>;
|
|
2
9
|
export default class Identity {
|
|
3
10
|
#private;
|
|
4
11
|
network: string;
|
|
@@ -9,7 +16,7 @@ export default class Identity {
|
|
|
9
16
|
getAccounts(): Promise<[[name: string, externalAddress: string, internalAddress: string]]>;
|
|
10
17
|
load(password?: string): Promise<void>;
|
|
11
18
|
selectAccount(account: string): Promise<unknown>;
|
|
12
|
-
sign(hash: Uint8Array):
|
|
19
|
+
sign(hash: Uint8Array): Promise<Uint8Array<ArrayBufferLike>>;
|
|
13
20
|
lock(password: string): void;
|
|
14
21
|
unlock(password: string): void;
|
|
15
22
|
export(password: string): Promise<any>;
|
|
@@ -17,3 +24,4 @@ export default class Identity {
|
|
|
17
24
|
exportQR(password: string): Promise<string>;
|
|
18
25
|
importQR(image: File | Blob, password: string): Promise<void>;
|
|
19
26
|
}
|
|
27
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leofcoin/peernet",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.24",
|
|
4
4
|
"description": "",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/leofcoin/peernet.git"
|
|
8
|
+
},
|
|
5
9
|
"browser": "./exports/browser/peernet.js",
|
|
6
10
|
"exports": {
|
|
7
11
|
".": {
|
|
@@ -99,6 +103,7 @@
|
|
|
99
103
|
"keywords": [],
|
|
100
104
|
"author": "",
|
|
101
105
|
"license": "MIT",
|
|
106
|
+
"packageManager": "npm@11.17.0",
|
|
102
107
|
"dependencies": {
|
|
103
108
|
"@leofcoin/codec-format-interface": "^1.8.2",
|
|
104
109
|
"@leofcoin/codecs": "^1.1.2",
|
|
@@ -107,7 +112,7 @@
|
|
|
107
112
|
"@leofcoin/multi-wallet": "^3.1.8",
|
|
108
113
|
"@leofcoin/storage": "^3.5.38",
|
|
109
114
|
"@mapbox/node-pre-gyp": "^2.0.3",
|
|
110
|
-
"@netpeer/swarm": "^0.9.
|
|
115
|
+
"@netpeer/swarm": "^0.9.9",
|
|
111
116
|
"@vandeurenglenn/base58": "^1.1.9",
|
|
112
117
|
"@vandeurenglenn/debug": "^1.4.0",
|
|
113
118
|
"@vandeurenglenn/little-pubsub": "^1.5.2",
|
package/src/identity.ts
CHANGED
|
@@ -5,8 +5,55 @@ import { encrypt, decrypt } from '@leofcoin/identity-utils'
|
|
|
5
5
|
import QrScanner from 'qr-scanner'
|
|
6
6
|
import qrcode from 'qrcode'
|
|
7
7
|
|
|
8
|
+
type StoredAccount = [name: string, externalAddress: string, internalAddress: string]
|
|
9
|
+
type AccountWallet = {
|
|
10
|
+
address: Promise<string>
|
|
11
|
+
sign: (hash: Uint8Array) => Promise<Uint8Array>
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const accountDerivationSchemes = [
|
|
15
|
+
{
|
|
16
|
+
name: 'current',
|
|
17
|
+
accountIndex: (index: number) => index + 1,
|
|
18
|
+
addressIndex: 1
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
name: 'legacy-v1',
|
|
22
|
+
accountIndex: (index: number) => index,
|
|
23
|
+
addressIndex: 0
|
|
24
|
+
}
|
|
25
|
+
] as const
|
|
26
|
+
|
|
27
|
+
export const resolveAccountWallets = async (
|
|
28
|
+
wallet: MultiWallet,
|
|
29
|
+
accounts: StoredAccount[]
|
|
30
|
+
): Promise<Map<string, AccountWallet>> => {
|
|
31
|
+
for (const scheme of accountDerivationSchemes) {
|
|
32
|
+
const wallets = new Map<string, AccountWallet>()
|
|
33
|
+
let matches = true
|
|
34
|
+
|
|
35
|
+
for (const [index, [, externalAddress, internalAddress]] of accounts.entries()) {
|
|
36
|
+
const account = wallet.account(scheme.accountIndex(index))
|
|
37
|
+
const external = (await account.external(scheme.addressIndex)) as unknown as AccountWallet
|
|
38
|
+
const internal = (await account.internal(scheme.addressIndex)) as unknown as AccountWallet
|
|
39
|
+
|
|
40
|
+
if ((await external.address) !== externalAddress || (await internal.address) !== internalAddress) {
|
|
41
|
+
matches = false
|
|
42
|
+
break
|
|
43
|
+
}
|
|
44
|
+
wallets.set(externalAddress, external)
|
|
45
|
+
wallets.set(internalAddress, internal)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (matches) return wallets
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
throw new Error('stored accounts do not match this identity under a supported derivation scheme')
|
|
52
|
+
}
|
|
53
|
+
|
|
8
54
|
export default class Identity {
|
|
9
55
|
#wallet: MultiWallet
|
|
56
|
+
#accountWallets = new Map<string, AccountWallet>()
|
|
10
57
|
network
|
|
11
58
|
id: string
|
|
12
59
|
selectedAccount: string
|
|
@@ -63,15 +110,27 @@ export default class Identity {
|
|
|
63
110
|
this.#wallet = new MultiWallet(this.network)
|
|
64
111
|
const multiWIF = await decrypt(password, base58.decode(identity.multiWIF))
|
|
65
112
|
await this.#wallet.fromMultiWif(multiWIF)
|
|
113
|
+
await this.#loadAccountWallets()
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async #loadAccountWallets() {
|
|
117
|
+
const accounts = await this.getAccounts()
|
|
118
|
+
this.#accountWallets = await resolveAccountWallets(this.#wallet, accounts)
|
|
119
|
+
if (!this.#accountWallets.has(this.selectedAccount)) {
|
|
120
|
+
throw new Error(`selected account ${this.selectedAccount} is not part of this identity`)
|
|
121
|
+
}
|
|
66
122
|
}
|
|
67
123
|
|
|
68
124
|
selectAccount(account: string) {
|
|
125
|
+
if (!this.#accountWallets.has(account)) throw new Error(`unknown identity account ${account}`)
|
|
69
126
|
this.selectedAccount = account
|
|
70
127
|
return walletStore.put('selected-account', account)
|
|
71
128
|
}
|
|
72
129
|
|
|
73
130
|
sign(hash: Uint8Array) {
|
|
74
|
-
|
|
131
|
+
const wallet = this.#accountWallets.get(this.selectedAccount)
|
|
132
|
+
if (!wallet) throw new Error(`no signer available for selected account ${this.selectedAccount}`)
|
|
133
|
+
return wallet.sign(hash.subarray(0, 32))
|
|
75
134
|
}
|
|
76
135
|
|
|
77
136
|
lock(password: string) {
|
package/test/peernet.test.js
CHANGED
|
@@ -2,12 +2,14 @@ import test from 'node:test'
|
|
|
2
2
|
import assert from 'node:assert/strict'
|
|
3
3
|
|
|
4
4
|
import Peernet from '../exports/peernet.js'
|
|
5
|
-
import Identity from '../exports/identity.js'
|
|
5
|
+
import Identity, { resolveAccountWallets } from '../exports/identity.js'
|
|
6
|
+
import MultiWallet from '@leofcoin/multi-wallet'
|
|
7
|
+
import { fromBase58, toBase58 } from '@vandeurenglenn/typed-array-utils'
|
|
6
8
|
|
|
7
9
|
const options = {
|
|
8
10
|
network: 'leofcoin:peach',
|
|
9
11
|
stars: [],
|
|
10
|
-
root:
|
|
12
|
+
root: `.testnet-${process.pid}`,
|
|
11
13
|
version: '1.0.0',
|
|
12
14
|
storePrefix: 'test',
|
|
13
15
|
autoStart: false
|
|
@@ -234,6 +236,31 @@ test('selected account is set', () => {
|
|
|
234
236
|
assert.ok(typeof peernet.identity.selectedAccount === 'string')
|
|
235
237
|
})
|
|
236
238
|
|
|
239
|
+
test('identity signatures authenticate the selected account', async () => {
|
|
240
|
+
const payload = new Uint8Array(32).fill(7)
|
|
241
|
+
const signature = toBase58(await peernet.identity.sign(payload))
|
|
242
|
+
const verifier = new MultiWallet(peernet.network)
|
|
243
|
+
await verifier.fromAddress(peernet.selectedAccount, null, peernet.network)
|
|
244
|
+
assert.equal(await verifier.verify(fromBase58(signature), payload), true)
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
test('legacy account(0)/address(0) identities keep their original signer', async () => {
|
|
248
|
+
const wallet = new MultiWallet(peernet.network)
|
|
249
|
+
await wallet.generate()
|
|
250
|
+
const legacyAccount = wallet.account(0)
|
|
251
|
+
const external = await legacyAccount.external(0)
|
|
252
|
+
const internal = await legacyAccount.internal(0)
|
|
253
|
+
const externalAddress = await external.address
|
|
254
|
+
const wallets = await resolveAccountWallets(wallet, [
|
|
255
|
+
['legacy account', externalAddress, await internal.address]
|
|
256
|
+
])
|
|
257
|
+
const payload = new Uint8Array(32).fill(9)
|
|
258
|
+
const signature = toBase58(await wallets.get(externalAddress).sign(payload))
|
|
259
|
+
const verifier = new MultiWallet(peernet.network)
|
|
260
|
+
await verifier.fromAddress(externalAddress, null, peernet.network)
|
|
261
|
+
assert.equal(await verifier.verify(fromBase58(signature), payload), true)
|
|
262
|
+
})
|
|
263
|
+
|
|
237
264
|
test('error handling methods exist', () => {
|
|
238
265
|
assert.equal(typeof peernet.handleDHT, 'function')
|
|
239
266
|
assert.equal(typeof peernet.handleData, 'function')
|
package/test-output.log
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
✔ initializes with provided options (0.407125ms)
|
|
2
|
-
✔ exposes identity instance (0.051667ms)
|
|
3
|
-
✔ has a DHT instance (0.04425ms)
|
|
4
|
-
✔ returns peers and connections safely (0.267542ms)
|
|
5
|
-
✔ provides callable helpers (0.048958ms)
|
|
6
|
-
✔ pubsub subscribe registers callback (10.395584ms)
|
|
7
|
-
✔ addProto registers protocol (0.160417ms)
|
|
8
|
-
✔ addProto does not overwrite existing protocol (0.057709ms)
|
|
9
|
-
✔ addCodec is callable (0.063084ms)
|
|
10
|
-
✔ selectAccount delegates to identity (0.068584ms)
|
|
11
|
-
✔ identity has loaded account data (0.241875ms)
|
|
12
|
-
✔ peerId matches identity id (0.031375ms)
|
|
13
|
-
✔ data store operations (0.030125ms)
|
|
14
|
-
✔ get attempts to retrieve from store (0.035667ms)
|
|
15
|
-
✔ message object provides get/put/has (0.053917ms)
|
|
16
|
-
✔ data object provides get/put/has (0.045833ms)
|
|
17
|
-
✔ block object provides get/put/has (0.067375ms)
|
|
18
|
-
✔ transaction object provides get/put/has (0.042333ms)
|
|
19
|
-
✔ folder object provides get/put/has (0.034167ms)
|
|
20
|
-
✔ Buffer property is available (0.024417ms)
|
|
21
|
-
✔ handleData is callable (0.017709ms)
|
|
22
|
-
✔ handleDHT is callable (0.016167ms)
|
|
23
|
-
✔ handleRequest is callable (0.016417ms)
|
|
24
|
-
✔ walk is callable (0.015459ms)
|
|
25
|
-
✔ providersFor is callable (0.015583ms)
|
|
26
|
-
✔ addRequestHandler is callable (0.015375ms)
|
|
27
|
-
✔ sendMessage is callable (0.01625ms)
|
|
28
|
-
✔ start method exists (0.02675ms)
|
|
29
|
-
✔ default stores are initialized (0.0275ms)
|
|
30
|
-
✔ identity has all expected methods (0.020084ms)
|
|
31
|
-
✔ identity wallet is loaded (0.019333ms)
|
|
32
|
-
✔ selected account is set (0.016208ms)
|
|
33
|
-
✔ error handling methods exist (0.017083ms)
|
|
34
|
-
DEBUG_HANDLE_DATA: entering in-memory branch { hash: 'BA43QACTNQLBH6SW7NO7ZQ63I3USRUBTD5DOWLEUFJGMY6JN2BSUAES54X' }
|
|
35
|
-
DEBUG_HANDLE_DATA: got from _inMemoryBroadcasts {
|
|
36
|
-
type: 'object',
|
|
37
|
-
isUint8Array: true,
|
|
38
|
-
length: 34,
|
|
39
|
-
slice: [
|
|
40
|
-
230, 224, 1, 5, 47,
|
|
41
|
-
116, 101, 115, 116, 21,
|
|
42
|
-
104, 101, 108, 108, 111,
|
|
43
|
-
32
|
|
44
|
-
]
|
|
45
|
-
}
|
|
46
|
-
✔ in-memory broadcast and handleData returns correct data (4.52275ms)
|
|
47
|
-
DEBUG_HANDLE_DATA: entering in-memory branch { hash: 'BA43QACYLVOY2HRRGV4NOUDQ3GWPQ7YZVBBM5DOKGZIY4UOYMS3K3JSCVV' }
|
|
48
|
-
DEBUG_HANDLE_DATA: got from _inMemoryBroadcasts {
|
|
49
|
-
type: 'object',
|
|
50
|
-
isUint8Array: true,
|
|
51
|
-
length: 1048599,
|
|
52
|
-
slice: [
|
|
53
|
-
230, 224, 1, 13, 47, 108,
|
|
54
|
-
97, 114, 103, 101, 45, 98,
|
|
55
|
-
105, 110, 97, 114
|
|
56
|
-
]
|
|
57
|
-
}
|
|
58
|
-
DEBUG_TEST receivedBuffer {
|
|
59
|
-
type: 'object',
|
|
60
|
-
isUint8Array: true,
|
|
61
|
-
length: 1048576,
|
|
62
|
-
slice: [
|
|
63
|
-
0, 1, 2, 3, 4, 5,
|
|
64
|
-
6, 7, 8, 9, 10, 11,
|
|
65
|
-
12, 13, 14, 15
|
|
66
|
-
]
|
|
67
|
-
}
|
|
68
|
-
DEBUG_TEST originalBuffer {
|
|
69
|
-
length: 1048576,
|
|
70
|
-
slice: [
|
|
71
|
-
0, 1, 2, 3, 4, 5,
|
|
72
|
-
6, 7, 8, 9, 10, 11,
|
|
73
|
-
12, 13, 14, 15
|
|
74
|
-
]
|
|
75
|
-
}
|
|
76
|
-
✔ in-memory broadcast and handleData supports large binary data (163.195292ms)
|
|
77
|
-
ℹ tests 35
|
|
78
|
-
ℹ suites 0
|
|
79
|
-
ℹ pass 35
|
|
80
|
-
ℹ fail 0
|
|
81
|
-
ℹ cancelled 0
|
|
82
|
-
ℹ skipped 0
|
|
83
|
-
ℹ todo 0
|
|
84
|
-
ℹ duration_ms 366.132458
|