@didcid/keymaster 0.1.3
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/LICENSE +21 -0
- package/README.md +109 -0
- package/dist/cjs/db/abstract-base.cjs +25 -0
- package/dist/cjs/db/cache.cjs +27 -0
- package/dist/cjs/db/chrome.cjs +32 -0
- package/dist/cjs/db/json-memory.cjs +24 -0
- package/dist/cjs/db/json.cjs +35 -0
- package/dist/cjs/db/mongo.cjs +57 -0
- package/dist/cjs/db/redis.cjs +55 -0
- package/dist/cjs/db/sqlite.cjs +69 -0
- package/dist/cjs/db/typeGuards.cjs +11 -0
- package/dist/cjs/db/web.cjs +29 -0
- package/dist/cjs/encryption.cjs +59 -0
- package/dist/cjs/index.cjs +32 -0
- package/dist/cjs/keymaster-client.cjs +1139 -0
- package/dist/cjs/keymaster.cjs +3787 -0
- package/dist/cjs/node.cjs +45 -0
- package/dist/cjs/search-client.cjs +87 -0
- package/dist/esm/db/abstract-base.js +22 -0
- package/dist/esm/db/abstract-base.js.map +1 -0
- package/dist/esm/db/cache.js +21 -0
- package/dist/esm/db/cache.js.map +1 -0
- package/dist/esm/db/chrome.js +26 -0
- package/dist/esm/db/chrome.js.map +1 -0
- package/dist/esm/db/json-memory.js +18 -0
- package/dist/esm/db/json-memory.js.map +1 -0
- package/dist/esm/db/json.js +29 -0
- package/dist/esm/db/json.js.map +1 -0
- package/dist/esm/db/mongo.js +51 -0
- package/dist/esm/db/mongo.js.map +1 -0
- package/dist/esm/db/redis.js +49 -0
- package/dist/esm/db/redis.js.map +1 -0
- package/dist/esm/db/sqlite.js +63 -0
- package/dist/esm/db/sqlite.js.map +1 -0
- package/dist/esm/db/typeGuards.js +7 -0
- package/dist/esm/db/typeGuards.js.map +1 -0
- package/dist/esm/db/web.js +23 -0
- package/dist/esm/db/web.js.map +1 -0
- package/dist/esm/encryption.js +55 -0
- package/dist/esm/encryption.js.map +1 -0
- package/dist/esm/index.js +11 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/keymaster-client.js +1133 -0
- package/dist/esm/keymaster-client.js.map +1 -0
- package/dist/esm/keymaster.js +2733 -0
- package/dist/esm/keymaster.js.map +1 -0
- package/dist/esm/node.js +7 -0
- package/dist/esm/node.js.map +1 -0
- package/dist/esm/search-client.js +81 -0
- package/dist/esm/search-client.js.map +1 -0
- package/dist/esm/types.js +2 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/types/db/abstract-base.d.ts +7 -0
- package/dist/types/db/cache.d.ts +9 -0
- package/dist/types/db/chrome.d.ts +8 -0
- package/dist/types/db/json-memory.d.ts +7 -0
- package/dist/types/db/json.d.ts +9 -0
- package/dist/types/db/mongo.d.ts +15 -0
- package/dist/types/db/redis.d.ts +13 -0
- package/dist/types/db/sqlite.d.ts +12 -0
- package/dist/types/db/typeGuards.d.ts +3 -0
- package/dist/types/db/web.d.ts +8 -0
- package/dist/types/encryption.d.ts +10 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types/keymaster-client.d.ts +134 -0
- package/dist/types/keymaster.d.ts +211 -0
- package/dist/types/node.d.ts +6 -0
- package/dist/types/search-client.d.ts +9 -0
- package/dist/types/types.d.ts +373 -0
- package/package.json +171 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Archetech
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Archon Keymaster
|
|
2
|
+
|
|
3
|
+
Keymaster is a client library for Archon.
|
|
4
|
+
It manages a wallet with any number of identities.
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npm install @didcid/keymaster
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
### Library
|
|
15
|
+
|
|
16
|
+
The library must be configured by calling the start function with 3 dependencies:
|
|
17
|
+
- a configured gatekeeper instance
|
|
18
|
+
- a wallet database
|
|
19
|
+
- a cipher library (@didcid/cipher/node for servers or @didcid/cipher/web for web browsers)
|
|
20
|
+
|
|
21
|
+
#### Node application
|
|
22
|
+
|
|
23
|
+
```js
|
|
24
|
+
// Import using subpaths
|
|
25
|
+
import GatekeeperClient from '@didcid/gatekeeper/client';
|
|
26
|
+
import WalletJson from '@didcid/keymaster/wallet/json';
|
|
27
|
+
import CipherNode from '@didcid/cipher/node';
|
|
28
|
+
import Keymaster from '@didcid/keymaster';
|
|
29
|
+
|
|
30
|
+
// Non-subpath imports
|
|
31
|
+
import { GatekeeperClient } from '@didcid/gatekeeper';
|
|
32
|
+
import Keymaster, { WalletJson } from '@didcid/keymaster';
|
|
33
|
+
import CipherNode from '@didcid/cipher';
|
|
34
|
+
|
|
35
|
+
const gatekeeper = new GatekeeperClient();
|
|
36
|
+
await gatekeeper.connect({
|
|
37
|
+
url: 'http://gatekeeper-host:4224',
|
|
38
|
+
waitUntilReady: true,
|
|
39
|
+
intervalSeconds: 5,
|
|
40
|
+
chatty: true,
|
|
41
|
+
});
|
|
42
|
+
const wallet = new WalletJson();
|
|
43
|
+
const cipher = new CipherNode();
|
|
44
|
+
const passphrase = 'SuperSecurePassphrase';
|
|
45
|
+
const keymaster = new Keymaster({
|
|
46
|
+
gatekeeper,
|
|
47
|
+
wallet,
|
|
48
|
+
cipher,
|
|
49
|
+
passphrase
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const newId = await keymaster.createId('Bob');
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
#### Browser wallet
|
|
56
|
+
|
|
57
|
+
```js
|
|
58
|
+
// Import using subpaths
|
|
59
|
+
import GatekeeperClient from '@didcid/gatekeeper/client';
|
|
60
|
+
import WalletWeb from '@didcid/keymaster/wallet/web';
|
|
61
|
+
import CipherWeb from '@didcid/cipher/web';
|
|
62
|
+
import Keymaster from '@didcid/keymaster';
|
|
63
|
+
|
|
64
|
+
// Non-subpath imports
|
|
65
|
+
import { GatekeeperClient } from '@didcid/gatekeeper';
|
|
66
|
+
import Keymaster, { WalletWeb } from '@didcid/keymaster';
|
|
67
|
+
import CipherWeb from '@didcid/cipher';
|
|
68
|
+
|
|
69
|
+
const gatekeeper = new GatekeeperClient();
|
|
70
|
+
await gatekeeper.connect({
|
|
71
|
+
url: 'http://gatekeeper-host:4224',
|
|
72
|
+
waitUntilReady: true,
|
|
73
|
+
intervalSeconds: 5,
|
|
74
|
+
chatty: true
|
|
75
|
+
});
|
|
76
|
+
const wallet = new WalletWeb();
|
|
77
|
+
const cipher = new CipherWeb();
|
|
78
|
+
const passphrase = 'SuperSecurePassphrase';
|
|
79
|
+
const keymaster = new Keymaster({
|
|
80
|
+
gatekeeper,
|
|
81
|
+
wallet,
|
|
82
|
+
cipher,
|
|
83
|
+
passphrase
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const newId = await keymaster.createId('Bob');
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Client
|
|
90
|
+
|
|
91
|
+
The KeymasterClient is used to communicate with a keymaster REST API service.
|
|
92
|
+
|
|
93
|
+
```js
|
|
94
|
+
// Import using subpaths
|
|
95
|
+
import KeymasterClient from '@didcid/keymaster/client';
|
|
96
|
+
|
|
97
|
+
// Non-subpath imports
|
|
98
|
+
import { KeymasterClient } from '@didcid/keymaster';
|
|
99
|
+
|
|
100
|
+
const keymaster = new KeymasterClient();
|
|
101
|
+
await keymaster.connect({
|
|
102
|
+
url: 'http://keymaster-host:4226',
|
|
103
|
+
waitUntilReady: true,
|
|
104
|
+
intervalSeconds: 5,
|
|
105
|
+
chatty: true
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const newId = await keymaster.createId('Bob');
|
|
109
|
+
```
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
class AbstractBase {
|
|
4
|
+
_lock = Promise.resolve();
|
|
5
|
+
async updateWallet(mutator) {
|
|
6
|
+
const run = async () => {
|
|
7
|
+
const wallet = await this.loadWallet();
|
|
8
|
+
if (!wallet) {
|
|
9
|
+
throw new Error('updateWallet: no wallet found to update');
|
|
10
|
+
}
|
|
11
|
+
const before = JSON.stringify(wallet);
|
|
12
|
+
await mutator(wallet);
|
|
13
|
+
const after = JSON.stringify(wallet);
|
|
14
|
+
if (before === after) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
await this.saveWallet(wallet, true);
|
|
18
|
+
};
|
|
19
|
+
const chained = this._lock.then(run, run);
|
|
20
|
+
this._lock = chained.catch(() => { });
|
|
21
|
+
return chained;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
exports.AbstractBase = AbstractBase;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var db_abstractBase = require('./abstract-base.cjs');
|
|
6
|
+
|
|
7
|
+
class WalletCache extends db_abstractBase.AbstractBase {
|
|
8
|
+
baseWallet;
|
|
9
|
+
cachedWallet;
|
|
10
|
+
constructor(baseWallet) {
|
|
11
|
+
super();
|
|
12
|
+
this.baseWallet = baseWallet;
|
|
13
|
+
this.cachedWallet = null;
|
|
14
|
+
}
|
|
15
|
+
async saveWallet(wallet, overwrite = false) {
|
|
16
|
+
this.cachedWallet = wallet;
|
|
17
|
+
return this.baseWallet.saveWallet(wallet, overwrite);
|
|
18
|
+
}
|
|
19
|
+
async loadWallet() {
|
|
20
|
+
if (!this.cachedWallet) {
|
|
21
|
+
this.cachedWallet = await this.baseWallet.loadWallet();
|
|
22
|
+
}
|
|
23
|
+
return this.cachedWallet;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
exports.default = WalletCache;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var db_abstractBase = require('./abstract-base.cjs');
|
|
6
|
+
|
|
7
|
+
class WalletChrome extends db_abstractBase.AbstractBase {
|
|
8
|
+
walletName;
|
|
9
|
+
constructor(walletName = 'archon-keymaster') {
|
|
10
|
+
super();
|
|
11
|
+
this.walletName = walletName;
|
|
12
|
+
}
|
|
13
|
+
async saveWallet(wallet, overwrite = false) {
|
|
14
|
+
if (!overwrite) {
|
|
15
|
+
const res = await chrome.storage.local.get([this.walletName]);
|
|
16
|
+
if (res[this.walletName]) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
await chrome.storage.local.set({ [this.walletName]: JSON.stringify(wallet) });
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
async loadWallet() {
|
|
24
|
+
const res = await chrome.storage.local.get([this.walletName]);
|
|
25
|
+
if (res[this.walletName]) {
|
|
26
|
+
return JSON.parse(res[this.walletName]);
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
exports.default = WalletChrome;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var db_abstractBase = require('./abstract-base.cjs');
|
|
6
|
+
|
|
7
|
+
class WalletJsonMemory extends db_abstractBase.AbstractBase {
|
|
8
|
+
walletCache = null;
|
|
9
|
+
async saveWallet(wallet, overwrite = false) {
|
|
10
|
+
if (this.walletCache && !overwrite) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
this.walletCache = JSON.stringify(wallet);
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
async loadWallet() {
|
|
17
|
+
if (!this.walletCache) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
return JSON.parse(this.walletCache);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
exports.default = WalletJsonMemory;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var fs = require('fs');
|
|
6
|
+
var db_abstractBase = require('./abstract-base.cjs');
|
|
7
|
+
|
|
8
|
+
class WalletJson extends db_abstractBase.AbstractBase {
|
|
9
|
+
dataFolder;
|
|
10
|
+
walletName;
|
|
11
|
+
constructor(walletFileName = 'wallet.json', dataFolder = 'data') {
|
|
12
|
+
super();
|
|
13
|
+
this.dataFolder = dataFolder;
|
|
14
|
+
this.walletName = `${dataFolder}/${walletFileName}`;
|
|
15
|
+
}
|
|
16
|
+
async saveWallet(wallet, overwrite = false) {
|
|
17
|
+
if (fs.existsSync(this.walletName) && !overwrite) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
if (!fs.existsSync(this.dataFolder)) {
|
|
21
|
+
fs.mkdirSync(this.dataFolder, { recursive: true });
|
|
22
|
+
}
|
|
23
|
+
fs.writeFileSync(this.walletName, JSON.stringify(wallet, null, 4));
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
async loadWallet() {
|
|
27
|
+
if (!fs.existsSync(this.walletName)) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
const walletJson = fs.readFileSync(this.walletName, 'utf-8');
|
|
31
|
+
return JSON.parse(walletJson);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
exports.default = WalletJson;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var db_abstractBase = require('./abstract-base.cjs');
|
|
6
|
+
var mongodb = require('mongodb');
|
|
7
|
+
|
|
8
|
+
class WalletMongo extends db_abstractBase.AbstractBase {
|
|
9
|
+
client;
|
|
10
|
+
db;
|
|
11
|
+
collection;
|
|
12
|
+
dbName = 'keymaster';
|
|
13
|
+
collectionName;
|
|
14
|
+
static async create() {
|
|
15
|
+
const wallet = new WalletMongo();
|
|
16
|
+
await wallet.connect();
|
|
17
|
+
return wallet;
|
|
18
|
+
}
|
|
19
|
+
constructor(walletKey = 'wallet') {
|
|
20
|
+
super();
|
|
21
|
+
const url = process.env.ARCHON_MONGODB_URL || 'mongodb://localhost:27017';
|
|
22
|
+
this.client = new mongodb.MongoClient(url);
|
|
23
|
+
this.collectionName = walletKey;
|
|
24
|
+
}
|
|
25
|
+
async connect() {
|
|
26
|
+
await this.client.connect();
|
|
27
|
+
this.db = this.client.db(this.dbName);
|
|
28
|
+
this.collection = this.db.collection(this.collectionName);
|
|
29
|
+
}
|
|
30
|
+
async disconnect() {
|
|
31
|
+
await this.client.close();
|
|
32
|
+
}
|
|
33
|
+
async saveWallet(wallet, overwrite = false) {
|
|
34
|
+
if (!this.collection) {
|
|
35
|
+
throw new Error('Not connected to MongoDB. Call connect() first or use WalletMongo.create().');
|
|
36
|
+
}
|
|
37
|
+
const exists = await this.collection.findOne({});
|
|
38
|
+
if (exists && !overwrite) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
await this.collection.replaceOne({}, wallet, { upsert: true });
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
async loadWallet() {
|
|
45
|
+
if (!this.collection) {
|
|
46
|
+
throw new Error('Not connected to MongoDB. Call connect() first or use WalletMongo.create().');
|
|
47
|
+
}
|
|
48
|
+
const wallet = await this.collection.findOne({});
|
|
49
|
+
if (!wallet) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
const { _id, ...rest } = wallet;
|
|
53
|
+
return rest;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
exports.default = WalletMongo;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var db_abstractBase = require('./abstract-base.cjs');
|
|
6
|
+
var ioredis = require('ioredis');
|
|
7
|
+
|
|
8
|
+
class WalletRedis extends db_abstractBase.AbstractBase {
|
|
9
|
+
walletKey;
|
|
10
|
+
url;
|
|
11
|
+
redis;
|
|
12
|
+
static async create(walletKey = 'wallet') {
|
|
13
|
+
const wallet = new WalletRedis(walletKey);
|
|
14
|
+
await wallet.connect();
|
|
15
|
+
return wallet;
|
|
16
|
+
}
|
|
17
|
+
constructor(walletKey = 'wallet') {
|
|
18
|
+
super();
|
|
19
|
+
this.url = process.env.ARCHON_REDIS_URL || 'redis://localhost:6379';
|
|
20
|
+
this.walletKey = walletKey;
|
|
21
|
+
this.redis = null;
|
|
22
|
+
}
|
|
23
|
+
async connect() {
|
|
24
|
+
this.redis = new ioredis.Redis(this.url);
|
|
25
|
+
}
|
|
26
|
+
async disconnect() {
|
|
27
|
+
if (this.redis) {
|
|
28
|
+
await this.redis.quit();
|
|
29
|
+
this.redis = null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async saveWallet(wallet, overwrite = false) {
|
|
33
|
+
if (!this.redis) {
|
|
34
|
+
throw new Error('Redis is not connected. Call connect() first or use WalletRedis.create().');
|
|
35
|
+
}
|
|
36
|
+
const exists = await this.redis.exists(this.walletKey);
|
|
37
|
+
if (exists && !overwrite) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
await this.redis.set(this.walletKey, JSON.stringify(wallet));
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
async loadWallet() {
|
|
44
|
+
if (!this.redis) {
|
|
45
|
+
throw new Error('Redis is not connected. Call connect() first or use WalletRedis.create().');
|
|
46
|
+
}
|
|
47
|
+
const walletJson = await this.redis.get(this.walletKey);
|
|
48
|
+
if (!walletJson) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
return JSON.parse(walletJson);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
exports.default = WalletRedis;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var db_abstractBase = require('./abstract-base.cjs');
|
|
6
|
+
var sqlite3 = require('sqlite3');
|
|
7
|
+
var sqlite = require('sqlite');
|
|
8
|
+
|
|
9
|
+
class WalletSQLite extends db_abstractBase.AbstractBase {
|
|
10
|
+
walletName;
|
|
11
|
+
db;
|
|
12
|
+
static async create(walletFileName = 'wallet.db', dataFolder = 'data') {
|
|
13
|
+
const wallet = new WalletSQLite(walletFileName, dataFolder);
|
|
14
|
+
await wallet.connect();
|
|
15
|
+
return wallet;
|
|
16
|
+
}
|
|
17
|
+
constructor(walletFileName = 'wallet.db', dataFolder = 'data') {
|
|
18
|
+
super();
|
|
19
|
+
this.walletName = `${dataFolder}/${walletFileName}`;
|
|
20
|
+
this.db = null;
|
|
21
|
+
}
|
|
22
|
+
async connect() {
|
|
23
|
+
if (this.db) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
this.db = await sqlite.open({
|
|
27
|
+
filename: this.walletName,
|
|
28
|
+
driver: sqlite3.Database
|
|
29
|
+
});
|
|
30
|
+
await this.db.exec(`
|
|
31
|
+
CREATE TABLE IF NOT EXISTS wallet (
|
|
32
|
+
id INTEGER PRIMARY KEY,
|
|
33
|
+
data TEXT NOT NULL
|
|
34
|
+
)
|
|
35
|
+
`);
|
|
36
|
+
}
|
|
37
|
+
async disconnect() {
|
|
38
|
+
if (this.db) {
|
|
39
|
+
await this.db.close();
|
|
40
|
+
this.db = null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
async saveWallet(wallet, overwrite = false) {
|
|
44
|
+
await this.connect();
|
|
45
|
+
if (!this.db) {
|
|
46
|
+
throw new Error('DB failed to connect.');
|
|
47
|
+
}
|
|
48
|
+
const exists = await this.db.get('SELECT 1 FROM wallet LIMIT 1');
|
|
49
|
+
if (exists && !overwrite) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
await this.db.run('DELETE FROM wallet');
|
|
53
|
+
await this.db.run('INSERT INTO wallet (data) VALUES (?)', JSON.stringify(wallet));
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
async loadWallet() {
|
|
57
|
+
await this.connect();
|
|
58
|
+
if (!this.db) {
|
|
59
|
+
throw new Error('DB failed to connect.');
|
|
60
|
+
}
|
|
61
|
+
const row = await this.db.get('SELECT data FROM wallet LIMIT 1');
|
|
62
|
+
if (!row) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
return JSON.parse(row.data);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
exports.default = WalletSQLite;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function isWalletEncFile(obj) {
|
|
4
|
+
return !!obj && obj.version === 1 && typeof obj.enc === 'string' && obj.seed?.mnemonicEnc;
|
|
5
|
+
}
|
|
6
|
+
function isWalletFile(obj) {
|
|
7
|
+
return !!obj && obj.version === 1 && obj.seed?.mnemonicEnc && !('enc' in obj);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
exports.isWalletEncFile = isWalletEncFile;
|
|
11
|
+
exports.isWalletFile = isWalletFile;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var db_abstractBase = require('./abstract-base.cjs');
|
|
6
|
+
|
|
7
|
+
class WalletWeb extends db_abstractBase.AbstractBase {
|
|
8
|
+
walletName;
|
|
9
|
+
constructor(walletName = 'archon-keymaster') {
|
|
10
|
+
super();
|
|
11
|
+
this.walletName = walletName;
|
|
12
|
+
}
|
|
13
|
+
async saveWallet(wallet, overwrite = false) {
|
|
14
|
+
if (!overwrite && window.localStorage.getItem(this.walletName)) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
window.localStorage.setItem(this.walletName, JSON.stringify(wallet));
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
async loadWallet() {
|
|
21
|
+
const walletJson = window.localStorage.getItem(this.walletName);
|
|
22
|
+
if (walletJson) {
|
|
23
|
+
return JSON.parse(walletJson);
|
|
24
|
+
}
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
exports.default = WalletWeb;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const ENC_ALG = 'AES-GCM';
|
|
4
|
+
const ENC_KDF = 'PBKDF2';
|
|
5
|
+
const ENC_HASH = 'SHA-512';
|
|
6
|
+
const ENC_ITER_DEFAULT = 100_000;
|
|
7
|
+
const IV_LEN = 12;
|
|
8
|
+
const SALT_LEN = 16;
|
|
9
|
+
function getIterations() {
|
|
10
|
+
if (typeof process !== 'undefined' && process.env?.PBKDF2_ITERATIONS) {
|
|
11
|
+
const parsed = parseInt(process.env.PBKDF2_ITERATIONS, 10);
|
|
12
|
+
if (!isNaN(parsed) && parsed > 0) {
|
|
13
|
+
return parsed;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return ENC_ITER_DEFAULT;
|
|
17
|
+
}
|
|
18
|
+
async function encMnemonic(mnemonic, pass) {
|
|
19
|
+
if (!hasSubtle()) {
|
|
20
|
+
throw new Error('Web Cryptography API not available');
|
|
21
|
+
}
|
|
22
|
+
const salt = await randBytes(SALT_LEN);
|
|
23
|
+
const iv = await randBytes(IV_LEN);
|
|
24
|
+
const key = await deriveKey(pass, salt);
|
|
25
|
+
const ct = await crypto.subtle.encrypt({ name: ENC_ALG, iv: iv }, key, new TextEncoder().encode(mnemonic));
|
|
26
|
+
return { salt: b64(salt), iv: b64(iv), data: b64(new Uint8Array(ct)) };
|
|
27
|
+
}
|
|
28
|
+
async function decMnemonic(blob, pass) {
|
|
29
|
+
if (!hasSubtle()) {
|
|
30
|
+
throw new Error('Web Cryptography API not available');
|
|
31
|
+
}
|
|
32
|
+
const salt = ub64(blob.salt);
|
|
33
|
+
const iv = ub64(blob.iv);
|
|
34
|
+
const data = ub64(blob.data);
|
|
35
|
+
const key = await deriveKey(pass, salt);
|
|
36
|
+
const pt = await crypto.subtle.decrypt({ name: ENC_ALG, iv }, key, data);
|
|
37
|
+
return new TextDecoder().decode(pt);
|
|
38
|
+
}
|
|
39
|
+
const b64 = (buf) => {
|
|
40
|
+
return Buffer.from(buf).toString('base64');
|
|
41
|
+
};
|
|
42
|
+
const ub64 = (b64) => {
|
|
43
|
+
return new Uint8Array(Buffer.from(b64, 'base64'));
|
|
44
|
+
};
|
|
45
|
+
const hasSubtle = () => typeof globalThis !== 'undefined' &&
|
|
46
|
+
!!(globalThis.crypto && globalThis.crypto.subtle);
|
|
47
|
+
async function randBytes(len) {
|
|
48
|
+
const u8 = new Uint8Array(len);
|
|
49
|
+
crypto.getRandomValues(u8);
|
|
50
|
+
return u8;
|
|
51
|
+
}
|
|
52
|
+
async function deriveKey(pass, salt) {
|
|
53
|
+
const enc = new TextEncoder();
|
|
54
|
+
const passKey = await crypto.subtle.importKey('raw', enc.encode(pass), { name: ENC_KDF }, false, ['deriveKey']);
|
|
55
|
+
return crypto.subtle.deriveKey({ name: ENC_KDF, salt: salt, iterations: getIterations(), hash: ENC_HASH }, passKey, { name: ENC_ALG, length: 256 }, false, ['encrypt', 'decrypt']);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
exports.decMnemonic = decMnemonic;
|
|
59
|
+
exports.encMnemonic = encMnemonic;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var keymaster = require('./keymaster.cjs');
|
|
6
|
+
var keymasterClient = require('./keymaster-client.cjs');
|
|
7
|
+
var searchClient = require('./search-client.cjs');
|
|
8
|
+
var db_jsonMemory = require('./db/json-memory.cjs');
|
|
9
|
+
var db_web = require('./db/web.cjs');
|
|
10
|
+
var db_cache = require('./db/cache.cjs');
|
|
11
|
+
var db_chrome = require('./db/chrome.cjs');
|
|
12
|
+
var db_abstractBase = require('./db/abstract-base.cjs');
|
|
13
|
+
var db_typeGuards = require('./db/typeGuards.cjs');
|
|
14
|
+
require('image-size');
|
|
15
|
+
require('file-type');
|
|
16
|
+
require('crypto');
|
|
17
|
+
require('./encryption.cjs');
|
|
18
|
+
require('buffer');
|
|
19
|
+
require('axios');
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
exports.default = keymaster.default;
|
|
24
|
+
exports.KeymasterClient = keymasterClient.default;
|
|
25
|
+
exports.SearchClient = searchClient.default;
|
|
26
|
+
exports.WalletJsonMemory = db_jsonMemory.default;
|
|
27
|
+
exports.WalletWeb = db_web.default;
|
|
28
|
+
exports.WalletCache = db_cache.default;
|
|
29
|
+
exports.WalletChrome = db_chrome.default;
|
|
30
|
+
exports.AbstractBase = db_abstractBase.AbstractBase;
|
|
31
|
+
exports.isWalletEncFile = db_typeGuards.isWalletEncFile;
|
|
32
|
+
exports.isWalletFile = db_typeGuards.isWalletFile;
|