@ocap/wallet 1.18.166 → 1.19.0

Sign up to get free protection for your applications and to get access to all the features.
package/.eslintrc.js ADDED
@@ -0,0 +1,12 @@
1
+ const path = require('path');
2
+
3
+ module.exports = {
4
+ root: true,
5
+ extends: ['@arcblock/eslint-config-ts/base'],
6
+ parserOptions: {
7
+ project: path.resolve(__dirname, 'tsconfig.eslint.json'),
8
+ },
9
+ rules: {
10
+ '@typescript-eslint/comma-dangle': 'off',
11
+ },
12
+ };
package/docs/README.md ADDED
@@ -0,0 +1,186 @@
1
+ ## Modules
2
+
3
+ <dl>
4
+ <dt><a href="#module_@ocap/wallet">@ocap/wallet</a></dt>
5
+ <dd><p>This module wraps common utility functions to help developers manipulate crypto wallets</p>
6
+ </dd>
7
+ </dl>
8
+
9
+ ## Typedefs
10
+
11
+ <dl>
12
+ <dt><a href="#WalletObject">WalletObject</a></dt>
13
+ <dd></dd>
14
+ </dl>
15
+
16
+ ## @ocap/wallet
17
+
18
+ This module wraps common utility functions to help developers manipulate crypto wallets
19
+
20
+ **Requires**: `module:@ocap/mcrypto`, `module:@arcblock/did`\
21
+ **Example**
22
+
23
+ ```js
24
+ yarn add @ocap/wallet
25
+ ```
26
+
27
+ * [Wallet(keyPair, \[type\])](#Wallet) ⇒ [`WalletObject`](#WalletObject)
28
+ * [fromSecretKey(sk, \[type\])](#fromSecretKey) ⇒ [`WalletObject`](#WalletObject)
29
+ * [fromPublicKey(pk, \[type\])](#fromPublicKey) ⇒ [`WalletObject`](#WalletObject)
30
+ * [fromAddress(address)](#fromAddress) ⇒ [`WalletObject`](#WalletObject)
31
+ * [fromRandom(\[type\])](#fromRandom) ⇒ [`WalletObject`](#WalletObject)
32
+ * [fromJSON(json)](#fromJSON) ⇒ [`WalletObject`](#WalletObject)
33
+ * [isValid(wallet, canSign)](#isValid)
34
+
35
+ ### Wallet(keyPair, \[type]) ⇒ [`WalletObject`](#WalletObject)
36
+
37
+ Generate an wallet instance that can be used to sign a message or verify a signature
38
+
39
+ **Kind**: static method\
40
+ **Returns**: [`WalletObject`](#WalletObject) - wallet object that can be used to sign/verify/getAddress\
41
+ **Access**: public
42
+
43
+ | Param | Type | Default | Description |
44
+ | --- | --- | --- | --- |
45
+ | keyPair | `object` | | the key pair |
46
+ | keyPair.sk | `string` | | the secretKey |
47
+ | keyPair.pk | `string` | | the wallet publicKey |
48
+ | \[type] | `DidType` | `&#x27;default&#x27;` | wallet type |
49
+
50
+ ### fromSecretKey(sk, \[type]) ⇒ [`WalletObject`](#WalletObject)
51
+
52
+ Generate a wallet from secretKey
53
+
54
+ **Kind**: static method\
55
+ **Returns**: [`WalletObject`](#WalletObject) - wallet object that can be used to sign/verify/getAddress\
56
+ **Access**: public
57
+
58
+ | Param | Type | Default | Description |
59
+ | --- | --- | --- | --- |
60
+ | sk | `string` | | the secret key, `hex encoded string` |
61
+ | \[type] | `DidType` | `&#x27;default&#x27;` | wallet type |
62
+
63
+ **Example**
64
+
65
+ ```js
66
+ const assert = require('assert');
67
+ const { fromSecretKey } = require('@ocap/wallet');
68
+
69
+ const sk =
70
+ '0xD67C071B6F51D2B61180B9B1AA9BE0DD0704619F0E30453AB4A592B036EDE644E4852B7091317E3622068E62A5127D1FB0D4AE2FC50213295E10652D2F0ABFC7';
71
+ const sig =
72
+ '0x08a102851c38c072e42756c1cc70938b5499c8e9358dfe5f383823f56cdb282ffda60fcd581a02c6c673069e5afc0bf09abbe3639b61b84d64fd58ef9f083003';
73
+
74
+ const wallet = fromSecretKey(sk, type);
75
+ const message = 'data to sign';
76
+ const signature = wallet.sign(message);
77
+ assert.equal(signature, sig, "signature should match");
78
+ assert.ok(wallet.verify(message, signature), "signature should be verified");
79
+ ```
80
+
81
+ ### fromPublicKey(pk, \[type]) ⇒ [`WalletObject`](#WalletObject)
82
+
83
+ Generate a wallet from publicKey
84
+
85
+ **Kind**: static method\
86
+ **Returns**: [`WalletObject`](#WalletObject) - wallet object that can be used to sign/verify/getAddress\
87
+ **Access**: public
88
+
89
+ | Param | Type | Default | Description |
90
+ | --- | --- | --- | --- |
91
+ | pk | `string` | | the public key, `hex encoded string` |
92
+ | \[type] | `DidType` | `&#x27;default&#x27;` | wallet type |
93
+
94
+ ### fromAddress(address) ⇒ [`WalletObject`](#WalletObject)
95
+
96
+ Generate a wallet from address (did)
97
+
98
+ Since we do not know the publicKey and secretKey, this kind of wallet cannot be used for signing and verifying
99
+
100
+ **Kind**: static method\
101
+ **Returns**: [`WalletObject`](#WalletObject) - wallet object that can be used to sign/verify/getAddress\
102
+ **Access**: public
103
+
104
+ | Param | Type | Description |
105
+ | --- | --- | --- |
106
+ | address | `string` | the wallet address |
107
+
108
+ **Example**
109
+
110
+ ```js
111
+ const assert = require('assert');
112
+ const { fromAddress } = require('@ocap/wallet');
113
+
114
+ const address = 'zNKtCNqYWLYWYW3gWRA1vnRykfCBZYHZvzKr';
115
+ const wallet = fromAddress(address);
116
+ console.log(wallet.toJSON());
117
+ ```
118
+
119
+ ### fromRandom(\[type]) ⇒ [`WalletObject`](#WalletObject)
120
+
121
+ Generate a wallet by generating a random secretKey
122
+
123
+ **Kind**: static method\
124
+ **Returns**: [`WalletObject`](#WalletObject) - wallet object that can be used to sign/verify/getAddress\
125
+ **Access**: public
126
+
127
+ | Param | Type | Default | Description |
128
+ | --- | --- | --- | --- |
129
+ | \[type] | `DidType` | `&#x27;default&#x27;` | wallet type |
130
+
131
+ **Example**
132
+
133
+ ```js
134
+ const { fromRandom } = require('@ocap/wallet');
135
+ const wallet = fromRandom();
136
+ // Do something with wallet
137
+ ```
138
+
139
+ ### fromJSON(json) ⇒ [`WalletObject`](#WalletObject)
140
+
141
+ Generating a wallet from a serialized json presentation of another wallet
142
+
143
+ **Kind**: static method\
144
+ **Returns**: [`WalletObject`](#WalletObject) - wallet object that can be used to sign/verify/getAddress\
145
+ **Access**: public
146
+
147
+ | Param | Type | Description |
148
+ | --- | --- | --- |
149
+ | json | `object` | json presentation of a wallet |
150
+
151
+ **Example**
152
+
153
+ ```js
154
+ const { fromJSON, fromRandom } = require('@ocap/wallet');
155
+ const wallet = fromRandom();
156
+ const wallet2 = fromJSON(wallet.toJSON());
157
+ // wallet2 is identical to wallet
158
+ ```
159
+
160
+ ### isValid(wallet, canSign)
161
+
162
+ Check if an object is valid wallet object
163
+
164
+ **Kind**: static method\
165
+ **Access**: public
166
+
167
+ | Param | Type | Default | Description |
168
+ | --- | --- | --- | --- |
169
+ | wallet | `object` | | |
170
+ | canSign | `boolean` | `true` | should the wallet support sign |
171
+
172
+ ## WalletObject
173
+
174
+ **Kind**: global typedef\
175
+ **Access**: public\
176
+ **Properties**
177
+
178
+ | Name | Type | Description |
179
+ | --- | --- | --- |
180
+ | type | `DidType` | Indicates the wallet type |
181
+ | secretKey | `secretKey` | Wallet secretKey |
182
+ | publicKey | `publicKey` | Wallet publicKey |
183
+ | sign | `function` | Sign `data`, data is hashed using the `HashType` defined in type before signing |
184
+ | verify | `function` | Verify `signature`, data is hashed using the `HashType` defined in type before verifying |
185
+ | toAddress | `function` | Get wallet address without `did:abt:` prefix |
186
+ | toJSON | `function` | Serialize wallet to json object, checkout [fromJSON](fromJSON) for deserialisation |
package/jest.config.js ADDED
@@ -0,0 +1,7 @@
1
+ const base = require('../../jest.config.base');
2
+
3
+ module.exports = {
4
+ ...base,
5
+ preset: 'ts-jest',
6
+ collectCoverageFrom: ['<rootDir>/core/wallet/src/*.ts', '<rootDir>/core/wallet/src/**/*.ts'],
7
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ocap/wallet",
3
- "version": "1.18.166",
3
+ "version": "1.19.0",
4
4
  "description": "Utility function to create and use an forge compatible crypto wallet",
5
5
  "keywords": [
6
6
  "crypto",
@@ -20,19 +20,24 @@
20
20
  ],
21
21
  "homepage": "https://github.com/ArcBlock/blockchain/tree/master/core/forge-wallet",
22
22
  "license": "Apache-2.0",
23
- "main": "lib/index.js",
24
- "typings": "lib/index.d.ts",
25
- "files": [
26
- "lib"
27
- ],
23
+ "main": "./lib/index.js",
24
+ "module": "./lib/index.js",
25
+ "types": "./esm/index.d.ts",
26
+ "exports": {
27
+ ".": {
28
+ "import": "./esm/index.js",
29
+ "require": "./lib/index.js",
30
+ "default": "./esm/index.js"
31
+ }
32
+ },
28
33
  "devDependencies": {
29
- "@arcblock/eslint-config-ts": "0.2.3",
30
- "@types/jest": "^29.5.12",
31
- "@types/node": "^17.0.45",
32
- "eslint": "^8.25.0",
34
+ "@arcblock/eslint-config-ts": "0.3.3",
35
+ "@types/jest": "^29.5.13",
36
+ "@types/node": "^22.7.5",
37
+ "eslint": "^8.57.0",
33
38
  "jest": "^29.7.0",
34
39
  "ts-jest": "^29.2.5",
35
- "typescript": "^4.8.4"
40
+ "typescript": "^5.6.2"
36
41
  },
37
42
  "repository": {
38
43
  "type": "git",
@@ -43,18 +48,20 @@
43
48
  "lint:fix": "eslint --fix tests src",
44
49
  "test": "jest --forceExit --detectOpenHandles",
45
50
  "coverage": "npm run test -- --coverage",
46
- "clean": "rm -fr lib",
51
+ "clean": "rm -fr lib esm",
47
52
  "prebuild": "npm run clean",
48
- "build": "tsc",
53
+ "build:cjs": "tsc -p tsconfig.cjs.json",
54
+ "build:esm": "tsc -p tsconfig.esm.json",
55
+ "build": "npm run build:cjs && npm run build:esm",
49
56
  "build:watch": "npm run build -- -w"
50
57
  },
51
58
  "bugs": {
52
59
  "url": "https://github.com/ArcBlock/blockchain/issues"
53
60
  },
54
61
  "dependencies": {
55
- "@arcblock/did": "1.18.166",
56
- "@ocap/mcrypto": "1.18.166",
57
- "@ocap/util": "1.18.166"
62
+ "@arcblock/did": "1.19.0",
63
+ "@ocap/mcrypto": "1.19.0",
64
+ "@ocap/util": "1.19.0"
58
65
  },
59
- "gitHead": "58c8356b3b8c238728560e4c3fef6ed1704d3ac4"
66
+ "gitHead": "1b6fac03988fb18507c8ef4c21de282762005f87"
60
67
  }
package/src/index.ts ADDED
@@ -0,0 +1,235 @@
1
+ import { toHex, EncodingType, BytesType } from '@ocap/util';
2
+ import { getSigner, getHasher } from '@ocap/mcrypto';
3
+ import {
4
+ toAddress,
5
+ fromPublicKey as DIDFromPublicKey,
6
+ toTypeInfo,
7
+ DidType,
8
+ DIDType,
9
+ DIDTypeStr,
10
+ DIDTypeArg,
11
+ } from '@arcblock/did';
12
+
13
+ type KeyPairType<T extends BytesType = string> = {
14
+ sk?: T;
15
+ pk?: T;
16
+ address?: string;
17
+ };
18
+
19
+ export type SerializedWallet = {
20
+ type: DIDTypeStr;
21
+ pk: string;
22
+ sk: string;
23
+ address: string;
24
+ };
25
+
26
+ export interface WalletObject<T extends BytesType = string> {
27
+ type: DIDType;
28
+ secretKey: T;
29
+ publicKey: T;
30
+ address: string;
31
+
32
+ hash(data: BytesType, round?: number, encoding?: 'hex'): string;
33
+ hash(data: BytesType, round?: number, encoding?: 'base16'): string;
34
+ hash(data: BytesType, round?: number, encoding?: 'base58'): string;
35
+ hash(data: BytesType, round?: number, encoding?: 'base64'): string;
36
+ hash(data: BytesType, round?: number, encoding?: 'buffer'): Buffer;
37
+ hash(data: BytesType, round?: number, encoding?: 'Uint8Array'): Uint8Array;
38
+ hash(data: BytesType, round?: number, encoding?: EncodingType): BytesType;
39
+
40
+ sign(data: BytesType, hashBeforeSign?: boolean, encoding?: 'hex'): string;
41
+ sign(data: BytesType, hashBeforeSign?: boolean, encoding?: 'base16'): string;
42
+ sign(data: BytesType, hashBeforeSign?: boolean, encoding?: 'base58'): string;
43
+ sign(data: BytesType, hashBeforeSign?: boolean, encoding?: 'base64'): string;
44
+ sign(data: BytesType, hashBeforeSign?: boolean, encoding?: 'buffer'): Buffer;
45
+ sign(data: BytesType, hashBeforeSign?: boolean, encoding?: 'Uint8Array'): Uint8Array;
46
+ sign(data: BytesType, hashBeforeSign?: boolean, encoding?: EncodingType): BytesType;
47
+
48
+ verify(data: BytesType, signature: BytesType, hashBeforeVerify?: boolean, extra?: any): Promise<boolean>;
49
+
50
+ ethHash(data: string): string;
51
+ ethSign(data: string, hashBeforeSign?: boolean): string;
52
+ ethVerify(data: string, signature: string, hashBeforeVerify?: boolean): boolean;
53
+
54
+ toJSON(): SerializedWallet;
55
+
56
+ /**
57
+ * @deprecated ES6: use `wallet.address` instead
58
+ */
59
+ toAddress(): string;
60
+ }
61
+
62
+ export const WalletType = DidType;
63
+
64
+ /**
65
+ * Generate an wallet instance that can be used to sign a message or verify a signature
66
+ */
67
+ export function Wallet<T extends BytesType = string>(
68
+ keyPair: KeyPairType<T>,
69
+ t: DIDTypeArg = 'default'
70
+ ): WalletObject<T> {
71
+ const type = DidType(t);
72
+ const signer = getSigner(type.pk);
73
+ const hasher = getHasher(type.hash);
74
+ return {
75
+ type,
76
+ secretKey: keyPair.sk,
77
+ publicKey: keyPair.pk,
78
+ address: keyPair.pk ? DIDFromPublicKey(keyPair.pk, type) : keyPair.address,
79
+
80
+ // @ts-ignore
81
+ hash(data: BytesType, round = 1, encoding: EncodingType = 'hex'): BytesType {
82
+ return hasher(data, round, encoding);
83
+ },
84
+
85
+ // @ts-ignore
86
+ sign(data: BytesType, hashBeforeSign = true, encoding: EncodingType = 'hex'): BytesType {
87
+ if (!keyPair.sk) {
88
+ throw new Error('Cannot sign data without a secretKey');
89
+ }
90
+ if (hashBeforeSign) {
91
+ const hash = hasher(data, 1);
92
+ return signer.sign(hash, keyPair.sk, encoding);
93
+ }
94
+ return signer.sign(data, keyPair.sk, encoding);
95
+ },
96
+
97
+ // eslint-disable-next-line require-await
98
+ async verify(data: BytesType, signature: BytesType, hashBeforeVerify = true, extra?: any): Promise<boolean> {
99
+ if (!keyPair.pk) {
100
+ throw new Error('Cannot verify data without a publicKey');
101
+ }
102
+ const hash = hashBeforeVerify ? hasher(data, 1) : data;
103
+ return signer.verify(hash, signature, keyPair.pk, extra);
104
+ },
105
+
106
+ ethHash(data: string): string {
107
+ if (typeof signer.ethHash !== 'function') {
108
+ throw new Error('ethHash is not supported by signer');
109
+ }
110
+ return signer.ethHash(data);
111
+ },
112
+ ethSign(data: string, hashBeforeSign = true): string {
113
+ if (!keyPair.sk) {
114
+ throw new Error('Cannot sign data without a secretKey');
115
+ }
116
+ if (typeof signer.ethHash !== 'function') {
117
+ throw new Error('ethSign is not supported by signer');
118
+ }
119
+ if (hashBeforeSign) {
120
+ return signer.ethSign(signer.ethHash(data), toHex(keyPair.sk));
121
+ }
122
+ return signer.ethSign(data, toHex(keyPair.sk));
123
+ },
124
+ ethVerify(data: string, signature: string, hashBeforeVerify = true): boolean {
125
+ if (typeof signer.ethHash !== 'function') {
126
+ throw new Error('ethVerify is not supported by signer');
127
+ }
128
+ const hash = hashBeforeVerify ? signer.ethHash(data) : data;
129
+ return signer.ethRecover(hash, signature) === this.address;
130
+ },
131
+
132
+ // deprecated
133
+ toAddress(): string {
134
+ return keyPair.pk ? DIDFromPublicKey(keyPair.pk, type) : keyPair.address;
135
+ },
136
+
137
+ toJSON(): SerializedWallet {
138
+ return {
139
+ type: DidType.toJSON(type),
140
+ sk: toHex(keyPair.sk),
141
+ pk: toHex(keyPair.pk),
142
+ address: this.address,
143
+ };
144
+ },
145
+ };
146
+ }
147
+
148
+ /**
149
+ * Generate a wallet from secretKey
150
+ *
151
+ * @example
152
+ * const assert = require('assert');
153
+ * const { fromSecretKey } = require('@ocap/wallet');
154
+ *
155
+ * const sk =
156
+ * '0xD67C071B6F51D2B61180B9B1AA9BE0DD0704619F0E30453AB4A592B036EDE644E4852B7091317E3622068E62A5127D1FB0D4AE2FC50213295E10652D2F0ABFC7';
157
+ * const sig =
158
+ * '0x08a102851c38c072e42756c1cc70938b5499c8e9358dfe5f383823f56cdb282ffda60fcd581a02c6c673069e5afc0bf09abbe3639b61b84d64fd58ef9f083003';
159
+ *
160
+ * const wallet = fromSecretKey(sk, type);
161
+ * const message = 'data to sign';
162
+ * const signature = wallet.sign(message);
163
+ * assert.equal(signature, sig, "signature should match");
164
+ * assert.ok(wallet.verify(message, signature), "signature should be verified");
165
+ */
166
+ export function fromSecretKey<T extends BytesType = string>(sk: T, _type: DIDTypeArg = 'default'): WalletObject<T> {
167
+ const type = DidType(_type);
168
+ const keyPair = { sk, pk: getSigner(type.pk).getPublicKey(sk) as T };
169
+ return Wallet<T>(keyPair, type);
170
+ }
171
+
172
+ /**
173
+ * Generate a wallet from publicKey
174
+ */
175
+ export function fromPublicKey<T extends BytesType = string>(pk: T, _type: DIDTypeArg = 'default'): WalletObject<T> {
176
+ return Wallet<T>({ pk }, DidType(_type));
177
+ }
178
+
179
+ /**
180
+ * Generate a wallet from address (did)
181
+ *
182
+ * Since we do not know the publicKey and secretKey, this kind of wallet cannot be used for signing and verifying
183
+ */
184
+ export function fromAddress<T extends BytesType = string>(address: string): WalletObject<T> {
185
+ return Wallet<T>({ address: toAddress(address) }, toTypeInfo(address));
186
+ }
187
+
188
+ /**
189
+ * Generate a wallet by generating a random secretKey
190
+ */
191
+ export function fromRandom<T extends BytesType = string>(_type: DIDTypeArg = 'default'): WalletObject<T> {
192
+ const type = DidType(_type);
193
+ const signer = getSigner(type.pk);
194
+ const keyPair = signer.genKeyPair();
195
+ return Wallet<T>({ sk: keyPair.secretKey as T, pk: keyPair.publicKey as T }, type);
196
+ }
197
+
198
+ /**
199
+ * Generating a wallet from a serialized json presentation of another wallet
200
+ */
201
+ export function fromJSON<T extends BytesType = string>(json: SerializedWallet): WalletObject<T> {
202
+ const type = DidType.fromJSON(json.type);
203
+ // @ts-ignore
204
+ return Wallet<T>(json, type);
205
+ }
206
+
207
+ /**
208
+ * Check if an object is valid wallet object
209
+ */
210
+ export function isValid(wallet: WalletObject, canSign = true): boolean {
211
+ if (!wallet || typeof wallet !== 'object') {
212
+ return false;
213
+ }
214
+ if (typeof wallet.verify !== 'function') {
215
+ return false;
216
+ }
217
+ if (typeof wallet.toAddress !== 'function') {
218
+ return false;
219
+ }
220
+ if (typeof wallet.toJSON !== 'function') {
221
+ return false;
222
+ }
223
+ if (!wallet.type || !wallet.publicKey) {
224
+ return false;
225
+ }
226
+ if (canSign) {
227
+ if (!wallet.secretKey) {
228
+ return false;
229
+ }
230
+ if (typeof wallet.sign !== 'function') {
231
+ return false;
232
+ }
233
+ }
234
+ return true;
235
+ }
@@ -0,0 +1,116 @@
1
+ import { types } from '@ocap/mcrypto';
2
+ import { fromBase64 } from '@ocap/util';
3
+ import { fromRandom, fromPublicKey, fromSecretKey, fromJSON, fromAddress, isValid } from '../src/index';
4
+
5
+ const sk =
6
+ '0xD67C071B6F51D2B61180B9B1AA9BE0DD0704619F0E30453AB4A592B036EDE644E4852B7091317E3622068E62A5127D1FB0D4AE2FC50213295E10652D2F0ABFC7';
7
+ const pk = '0xE4852B7091317E3622068E62A5127D1FB0D4AE2FC50213295E10652D2F0ABFC7';
8
+ const appId = 'zNKtCNqYWLYWYW3gWRA1vnRykfCBZYHZvzKr';
9
+ const sig =
10
+ '0x8122c608f61b04f6b574f005dc8e0463d393a7fb50e0426bca587b20778a8a9f6376bab87bc3983b0a5f1c9581f6d94162317c715a3c1c0f086be1e514399109';
11
+ const type = {
12
+ role: types.RoleType.ROLE_APPLICATION,
13
+ pk: types.KeyType.ED25519,
14
+ hash: types.HashType.SHA3,
15
+ address: types.EncodingType.BASE58,
16
+ };
17
+ describe('#Wallet', () => {
18
+ test('should have basic functions', () => {
19
+ expect(typeof fromPublicKey).toEqual('function');
20
+ expect(typeof fromSecretKey).toEqual('function');
21
+ expect(typeof fromJSON).toEqual('function');
22
+ });
23
+
24
+ test('should serialize to json as expected', () => {
25
+ const wallet = fromPublicKey(pk, type);
26
+ const json = wallet.toJSON();
27
+ expect(json.address).toEqual(appId);
28
+ const wallet2 = fromJSON(json);
29
+ expect(wallet2.address).toEqual(appId);
30
+ expect(wallet2.address).toEqual(appId);
31
+ });
32
+
33
+ test('should throw error when sign without sk', () => {
34
+ const wallet = fromPublicKey(pk, type);
35
+ const hash = wallet.hash('abc');
36
+ expect(hash).toEqual('0x3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532');
37
+ try {
38
+ wallet.sign('data to sign');
39
+ } catch (err) {
40
+ expect(err).toBeTruthy();
41
+ }
42
+ });
43
+
44
+ test('should sign when sk is provided', async () => {
45
+ const wallet = fromSecretKey(sk, type);
46
+ const hash = wallet.hash('abc');
47
+ expect(hash).toEqual('0x3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532');
48
+ const message = 'data to sign';
49
+ const signature = wallet.sign(message);
50
+ expect(signature).toEqual(sig);
51
+ expect(await wallet.verify(message, signature)).toEqual(true);
52
+ expect(() => fromSecretKey('abc')).toThrow();
53
+ });
54
+
55
+ test('should gen type from address', () => {
56
+ const wallet = fromAddress(appId);
57
+ expect(wallet.type.pk).toEqual(type.pk);
58
+ expect(wallet.type.hash).toEqual(type.hash);
59
+ expect(wallet.type.role).toEqual(type.role);
60
+ });
61
+
62
+ test('should detect invalid wallets', () => {
63
+ const wallet = fromRandom();
64
+ expect(isValid(wallet)).toEqual(true);
65
+ const wallet2 = fromPublicKey(pk, type);
66
+ expect(isValid(wallet2, false)).toEqual(true);
67
+ });
68
+
69
+ test('should generate base58 address', () => {
70
+ const wallet = fromRandom();
71
+ expect(wallet.toAddress().startsWith('z')).toBeTruthy();
72
+ expect(wallet.address.startsWith('z')).toBeTruthy();
73
+ expect(() => wallet.ethHash('abc')).toThrow();
74
+ expect(() => wallet.ethSign('abc')).toThrow();
75
+ });
76
+
77
+ test('should generate base16 address', () => {
78
+ const wallet = fromRandom('eth');
79
+ expect(wallet.address.startsWith('0x')).toBeTruthy();
80
+ });
81
+
82
+ test('should work with ethereum', async () => {
83
+ // eslint-disable-next-line
84
+ const sk = '0xfe51dc1dfe30e2f4b06f7941bdfe0341704c10e28d28e4ecd7871f8f0204fa33';
85
+ const address = '0x5547a73ed3c2Ad599114866fA1d5E8a02147D1C9';
86
+ const data = '0xef56b956483ebe2fa8ed6c35c8b884d940d57fdf535a70a2df245661c9cf42e4';
87
+ // eslint-disable-next-line
88
+ const sig = '0x242ad32e16c38307e2909600cb641da17734121d9d50df93b6240db40ad3fc2d562f3e41cc6409730cbb81c5bc90a914f24baf0d3537a7db8334dc67ed2000fe1c'; // prettier-ignore
89
+ const wallet = fromSecretKey(sk, 'eth');
90
+ expect(wallet.address).toEqual(address);
91
+ expect(wallet.ethSign(data)).toEqual(sig);
92
+ expect(wallet.ethHash(data)).toEqual('0x9f5dc66bef3e8053b02c4cb6a8504cb4d7e48862245a4d34fc69bc615080d276');
93
+ expect(await wallet.ethVerify(data, sig)).toEqual(true);
94
+ expect(() => fromSecretKey('abc', 'eth')).toThrow();
95
+ });
96
+
97
+ test('should work with passkey', async () => {
98
+ const publicKey = fromBase64(
99
+ 'pQECAyYgASFYIA3GyM4rSxM_HyV52QTRwGJOdkXurky3cwTLvb_gKSF-Ilggpd0fhMlPdxHBl45_eJxqywCRl-a4IDpeFa4pcfmrxuM'
100
+ );
101
+
102
+ const wallet = fromPublicKey(publicKey, 'passkey');
103
+ expect(wallet.address).toEqual('z3i165rPumFgyQZpZ1W3VLEYBPuV2xSCAjoqo');
104
+
105
+ const challenge = '0x7E093B990CB41A97990657D6AD688BD4E28267C9FCC0A36BC15D241D5D302CEF';
106
+ const response = {
107
+ authenticatorData: 'u_rJjitfFaLnT_p0uECHZ0CSuRQE7psYSUxv2p-nql0dAAAAAA',
108
+ clientDataJSON:
109
+ 'eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiZmdrN21ReTBHcGVaQmxmV3JXaUwxT0tDWjhuOHdLTnJ3VjBrSFYwd0xPOCIsIm9yaWdpbiI6Imh0dHBzOi8vYmJxYXhlN2lhZGZpbWRkY2c0cmZycHRmdXp4bW12NWI2dnBudXB1bmk0NC5kaWQuYWJ0bmV0LmlvIiwiY3Jvc3NPcmlnaW4iOmZhbHNlfQ',
110
+ signature: 'MEUCIQCo51Gg_3UrSotxrguG92iXcuSbW5fNZqcSsHS8zlZbdAIgEmaBD0cQeiML3Mr60HSPP176EyqNvqfTdEV1oGWhQ-o',
111
+ };
112
+
113
+ const verified = await wallet.verify(challenge, response.signature, false, JSON.stringify(response));
114
+ expect(verified).toEqual(true);
115
+ });
116
+ });
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "include": ["src"],
4
+ "exclude": ["node_modules", "tests"],
5
+ "compilerOptions": {
6
+ "module": "commonjs",
7
+ "outDir": "lib"
8
+ }
9
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "include": ["src", "tests", ".eslintrc.js", "jest.config.js"]
4
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "include": ["src"],
4
+ "exclude": ["node_modules", "tests"],
5
+ "compilerOptions": {
6
+ "module": "esnext",
7
+ "outDir": "esm"
8
+ }
9
+ }
package/lib/index.d.ts DELETED
@@ -1,90 +0,0 @@
1
- /// <reference types="node" />
2
- import { EncodingType, BytesType } from '@ocap/util';
3
- import { DidType, DIDType, DIDTypeStr, DIDTypeArg } from '@arcblock/did';
4
- declare type KeyPairType<T extends BytesType = string> = {
5
- sk?: T;
6
- pk?: T;
7
- address?: string;
8
- };
9
- export declare type SerializedWallet = {
10
- type: DIDTypeStr;
11
- pk: string;
12
- sk: string;
13
- address: string;
14
- };
15
- export interface WalletObject<T extends BytesType = string> {
16
- type: DIDType;
17
- secretKey: T;
18
- publicKey: T;
19
- address: string;
20
- hash(data: BytesType, round?: number, encoding?: 'hex'): string;
21
- hash(data: BytesType, round?: number, encoding?: 'base16'): string;
22
- hash(data: BytesType, round?: number, encoding?: 'base58'): string;
23
- hash(data: BytesType, round?: number, encoding?: 'base64'): string;
24
- hash(data: BytesType, round?: number, encoding?: 'buffer'): Buffer;
25
- hash(data: BytesType, round?: number, encoding?: 'Uint8Array'): Uint8Array;
26
- hash(data: BytesType, round?: number, encoding?: EncodingType): BytesType;
27
- sign(data: BytesType, hashBeforeSign?: boolean, encoding?: 'hex'): string;
28
- sign(data: BytesType, hashBeforeSign?: boolean, encoding?: 'base16'): string;
29
- sign(data: BytesType, hashBeforeSign?: boolean, encoding?: 'base58'): string;
30
- sign(data: BytesType, hashBeforeSign?: boolean, encoding?: 'base64'): string;
31
- sign(data: BytesType, hashBeforeSign?: boolean, encoding?: 'buffer'): Buffer;
32
- sign(data: BytesType, hashBeforeSign?: boolean, encoding?: 'Uint8Array'): Uint8Array;
33
- sign(data: BytesType, hashBeforeSign?: boolean, encoding?: EncodingType): BytesType;
34
- verify(data: BytesType, signature: BytesType, hashBeforeVerify?: boolean): boolean;
35
- ethHash(data: string): string;
36
- ethSign(data: string, hashBeforeSign?: boolean): string;
37
- ethVerify(data: string, signature: string, hashBeforeVerify?: boolean): boolean;
38
- toJSON(): SerializedWallet;
39
- /**
40
- * @deprecated ES6: use `wallet.address` instead
41
- */
42
- toAddress(): string;
43
- }
44
- export declare const WalletType: typeof DidType;
45
- /**
46
- * Generate an wallet instance that can be used to sign a message or verify a signature
47
- */
48
- export declare function Wallet<T extends BytesType = string>(keyPair: KeyPairType<T>, t?: DIDTypeArg): WalletObject<T>;
49
- /**
50
- * Generate a wallet from secretKey
51
- *
52
- * @example
53
- * const assert = require('assert');
54
- * const { fromSecretKey } = require('@ocap/wallet');
55
- *
56
- * const sk =
57
- * '0xD67C071B6F51D2B61180B9B1AA9BE0DD0704619F0E30453AB4A592B036EDE644E4852B7091317E3622068E62A5127D1FB0D4AE2FC50213295E10652D2F0ABFC7';
58
- * const sig =
59
- * '0x08a102851c38c072e42756c1cc70938b5499c8e9358dfe5f383823f56cdb282ffda60fcd581a02c6c673069e5afc0bf09abbe3639b61b84d64fd58ef9f083003';
60
- *
61
- * const wallet = fromSecretKey(sk, type);
62
- * const message = 'data to sign';
63
- * const signature = wallet.sign(message);
64
- * assert.equal(signature, sig, "signature should match");
65
- * assert.ok(wallet.verify(message, signature), "signature should be verified");
66
- */
67
- export declare function fromSecretKey<T extends BytesType = string>(sk: T, _type?: DIDTypeArg): WalletObject<T>;
68
- /**
69
- * Generate a wallet from publicKey
70
- */
71
- export declare function fromPublicKey<T extends BytesType = string>(pk: T, _type?: DIDTypeArg): WalletObject<T>;
72
- /**
73
- * Generate a wallet from address (did)
74
- *
75
- * Since we do not know the publicKey and secretKey, this kind of wallet cannot be used for signing and verifying
76
- */
77
- export declare function fromAddress<T extends BytesType = string>(address: string): WalletObject<T>;
78
- /**
79
- * Generate a wallet by generating a random secretKey
80
- */
81
- export declare function fromRandom<T extends BytesType = string>(_type?: DIDTypeArg): WalletObject<T>;
82
- /**
83
- * Generating a wallet from a serialized json presentation of another wallet
84
- */
85
- export declare function fromJSON<T extends BytesType = string>(json: SerializedWallet): WalletObject<T>;
86
- /**
87
- * Check if an object is valid wallet object
88
- */
89
- export declare function isValid(wallet: WalletObject, canSign?: boolean): boolean;
90
- export {};
package/lib/index.js DELETED
@@ -1,170 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isValid = exports.fromJSON = exports.fromRandom = exports.fromAddress = exports.fromPublicKey = exports.fromSecretKey = exports.Wallet = exports.WalletType = void 0;
4
- const util_1 = require("@ocap/util");
5
- const mcrypto_1 = require("@ocap/mcrypto");
6
- const did_1 = require("@arcblock/did");
7
- exports.WalletType = did_1.DidType;
8
- /**
9
- * Generate an wallet instance that can be used to sign a message or verify a signature
10
- */
11
- function Wallet(keyPair, t = 'default') {
12
- const type = (0, did_1.DidType)(t);
13
- const signer = (0, mcrypto_1.getSigner)(type.pk);
14
- const hasher = (0, mcrypto_1.getHasher)(type.hash);
15
- return {
16
- type,
17
- secretKey: keyPair.sk,
18
- publicKey: keyPair.pk,
19
- address: keyPair.pk ? (0, did_1.fromPublicKey)(keyPair.pk, type) : keyPair.address,
20
- // @ts-ignore
21
- hash(data, round = 1, encoding = 'hex') {
22
- return hasher(data, round, encoding);
23
- },
24
- // @ts-ignore
25
- sign(data, hashBeforeSign = true, encoding = 'hex') {
26
- if (!keyPair.sk) {
27
- throw new Error('Cannot sign data without a secretKey');
28
- }
29
- if (hashBeforeSign) {
30
- const hash = hasher(data, 1);
31
- return signer.sign(hash, keyPair.sk, encoding);
32
- }
33
- return signer.sign(data, keyPair.sk, encoding);
34
- },
35
- verify(data, signature, hashBeforeVerify = true) {
36
- if (!keyPair.pk) {
37
- throw new Error('Cannot verify data without a publicKey');
38
- }
39
- const hash = hashBeforeVerify ? hasher(data, 1) : data;
40
- return signer.verify(hash, signature, keyPair.pk);
41
- },
42
- ethHash(data) {
43
- if (typeof signer.ethHash !== 'function') {
44
- throw new Error('ethHash is not supported by signer');
45
- }
46
- return signer.ethHash(data);
47
- },
48
- ethSign(data, hashBeforeSign = true) {
49
- if (!keyPair.sk) {
50
- throw new Error('Cannot sign data without a secretKey');
51
- }
52
- if (typeof signer.ethHash !== 'function') {
53
- throw new Error('ethSign is not supported by signer');
54
- }
55
- if (hashBeforeSign) {
56
- return signer.ethSign(signer.ethHash(data), (0, util_1.toHex)(keyPair.sk));
57
- }
58
- return signer.ethSign(data, (0, util_1.toHex)(keyPair.sk));
59
- },
60
- ethVerify(data, signature, hashBeforeVerify = true) {
61
- if (typeof signer.ethHash !== 'function') {
62
- throw new Error('ethVerify is not supported by signer');
63
- }
64
- const hash = hashBeforeVerify ? signer.ethHash(data) : data;
65
- return signer.ethRecover(hash, signature) === this.address;
66
- },
67
- // deprecated
68
- toAddress() {
69
- return keyPair.pk ? (0, did_1.fromPublicKey)(keyPair.pk, type) : keyPair.address;
70
- },
71
- toJSON() {
72
- return {
73
- type: did_1.DidType.toJSON(type),
74
- sk: (0, util_1.toHex)(keyPair.sk),
75
- pk: (0, util_1.toHex)(keyPair.pk),
76
- address: this.address,
77
- };
78
- },
79
- };
80
- }
81
- exports.Wallet = Wallet;
82
- /**
83
- * Generate a wallet from secretKey
84
- *
85
- * @example
86
- * const assert = require('assert');
87
- * const { fromSecretKey } = require('@ocap/wallet');
88
- *
89
- * const sk =
90
- * '0xD67C071B6F51D2B61180B9B1AA9BE0DD0704619F0E30453AB4A592B036EDE644E4852B7091317E3622068E62A5127D1FB0D4AE2FC50213295E10652D2F0ABFC7';
91
- * const sig =
92
- * '0x08a102851c38c072e42756c1cc70938b5499c8e9358dfe5f383823f56cdb282ffda60fcd581a02c6c673069e5afc0bf09abbe3639b61b84d64fd58ef9f083003';
93
- *
94
- * const wallet = fromSecretKey(sk, type);
95
- * const message = 'data to sign';
96
- * const signature = wallet.sign(message);
97
- * assert.equal(signature, sig, "signature should match");
98
- * assert.ok(wallet.verify(message, signature), "signature should be verified");
99
- */
100
- function fromSecretKey(sk, _type = 'default') {
101
- const type = (0, did_1.DidType)(_type);
102
- const keyPair = { sk, pk: (0, mcrypto_1.getSigner)(type.pk).getPublicKey(sk) };
103
- return Wallet(keyPair, type);
104
- }
105
- exports.fromSecretKey = fromSecretKey;
106
- /**
107
- * Generate a wallet from publicKey
108
- */
109
- function fromPublicKey(pk, _type = 'default') {
110
- return Wallet({ pk }, (0, did_1.DidType)(_type));
111
- }
112
- exports.fromPublicKey = fromPublicKey;
113
- /**
114
- * Generate a wallet from address (did)
115
- *
116
- * Since we do not know the publicKey and secretKey, this kind of wallet cannot be used for signing and verifying
117
- */
118
- function fromAddress(address) {
119
- return Wallet({ address: (0, did_1.toAddress)(address) }, (0, did_1.toTypeInfo)(address));
120
- }
121
- exports.fromAddress = fromAddress;
122
- /**
123
- * Generate a wallet by generating a random secretKey
124
- */
125
- function fromRandom(_type = 'default') {
126
- const type = (0, did_1.DidType)(_type);
127
- const signer = (0, mcrypto_1.getSigner)(type.pk);
128
- const keyPair = signer.genKeyPair();
129
- return Wallet({ sk: keyPair.secretKey, pk: keyPair.publicKey }, type);
130
- }
131
- exports.fromRandom = fromRandom;
132
- /**
133
- * Generating a wallet from a serialized json presentation of another wallet
134
- */
135
- function fromJSON(json) {
136
- const type = did_1.DidType.fromJSON(json.type);
137
- // @ts-ignore
138
- return Wallet(json, type);
139
- }
140
- exports.fromJSON = fromJSON;
141
- /**
142
- * Check if an object is valid wallet object
143
- */
144
- function isValid(wallet, canSign = true) {
145
- if (!wallet || typeof wallet !== 'object') {
146
- return false;
147
- }
148
- if (typeof wallet.verify !== 'function') {
149
- return false;
150
- }
151
- if (typeof wallet.toAddress !== 'function') {
152
- return false;
153
- }
154
- if (typeof wallet.toJSON !== 'function') {
155
- return false;
156
- }
157
- if (!wallet.type || !wallet.publicKey) {
158
- return false;
159
- }
160
- if (canSign) {
161
- if (!wallet.secretKey) {
162
- return false;
163
- }
164
- if (typeof wallet.sign !== 'function') {
165
- return false;
166
- }
167
- }
168
- return true;
169
- }
170
- exports.isValid = isValid;