@arcblock/did-connect-js 1.21.2

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.
@@ -0,0 +1,256 @@
1
+ const { Joi } = require('@arcblock/validator');
2
+ const { types } = require('@ocap/mcrypto');
3
+
4
+ const trustedIssuerSchema = Joi.alternatives().try(
5
+ Joi.object({
6
+ did: Joi.DID().required(),
7
+ endpoint: Joi.string()
8
+ .uri({ scheme: ['http', 'https'] })
9
+ .required(),
10
+ }),
11
+ Joi.DID().required()
12
+ );
13
+
14
+ const optionalUrlSchema = Joi.string()
15
+ .uri({ scheme: ['http', 'https'], allowRelative: true })
16
+ .optional()
17
+ .default('')
18
+ .allow('');
19
+
20
+ const requirementSchema = Joi.object({
21
+ tokens: Joi.array()
22
+ .items(
23
+ Joi.object({
24
+ address: Joi.DID().required(),
25
+ value: Joi.BN().positive().required(),
26
+ })
27
+ )
28
+ .required(),
29
+ assets: Joi.object({
30
+ address: Joi.array().items(Joi.DID()).optional(),
31
+ parent: Joi.array().items(Joi.DID()).optional(),
32
+ issuer: Joi.array().items(Joi.DID()).optional(),
33
+ amount: Joi.number().positive().min(1),
34
+ }).optional(),
35
+ });
36
+
37
+ const targetTypeSchema = Joi.object({
38
+ key: Joi.string()
39
+ .valid(...Object.keys(types.KeyType).map((x) => x.toLowerCase()))
40
+ .default('ed25519'),
41
+ hash: Joi.string()
42
+ .valid(...Object.keys(types.HashType).map((x) => x.toLowerCase()))
43
+ .default('sha3'),
44
+ role: Joi.string()
45
+ .valid(...Object.keys(types.RoleType).map((x) => x.toLowerCase().split('_').pop()))
46
+ .default('account'),
47
+ encoding: Joi.string()
48
+ .valid(...Object.keys(types.EncodingType).map((x) => x.toLowerCase()))
49
+ .default('base58'),
50
+ }).optional();
51
+ // .default({
52
+ // key: 'ed25519',
53
+ // hash: 'sha3',
54
+ // role: 'account',
55
+ // encoding: 'base58',
56
+ // });
57
+
58
+ module.exports = (chainInfo) => {
59
+ const options = { stripUnknown: true, noDefaults: false };
60
+ const createStandardFields = (type, description) => ({
61
+ type: Joi.string().valid(type).default(type),
62
+ description: Joi.string().min(1).default(description),
63
+ chainInfo,
64
+ mfaCode: Joi.array().items(Joi.number().min(10).max(99).optional()).default([]),
65
+ meta: Joi.any().optional().default({}),
66
+ });
67
+
68
+ // Ask wallet to select a did for later interaction
69
+ const authPrincipal = Joi.object({
70
+ ...createStandardFields('authPrincipal', 'Please continue with your account'),
71
+ target: Joi.DID().optional().allow('').default(''),
72
+ supervised: Joi.boolean().default(false),
73
+ targetType: targetTypeSchema,
74
+ }).options(options);
75
+
76
+ // Ask wallet to create new did and provide sk
77
+ const keyPair = Joi.object({
78
+ ...createStandardFields('keyPair', 'Please create account to continue.'),
79
+ moniker: Joi.string()
80
+ .regex(/^[a-zA-Z0-9][-a-zA-Z0-9_]{2,128}$/)
81
+ .required(),
82
+ declare: Joi.boolean().optional().default(true),
83
+ migrateFrom: Joi.DID().optional().allow('').default(''),
84
+ targetType: targetTypeSchema,
85
+ }).options(options);
86
+
87
+ // Ask wallet to derive encryption key = SHA3(Buffer.concat(keyPair.sk, salt), 3)
88
+ const encryptionKey = Joi.object({
89
+ ...createStandardFields('encryptionKey', 'Please provide encryptionKey to continue.'),
90
+ salt: Joi.string().required(),
91
+ delegation: Joi.string().optional().allow('').default(''),
92
+ }).options(options);
93
+
94
+ const profile = Joi.object({
95
+ ...createStandardFields('profile', 'Please provide your profile to continue.'),
96
+ items: Joi.array()
97
+ .items(Joi.string().valid('did', 'fullName', 'email', 'phone', 'signature', 'avatar', 'birthday', 'url'))
98
+ .min(1)
99
+ .default(['fullName']),
100
+ })
101
+ .rename('fields', 'items', { ignoreUndefined: true, override: true })
102
+ .options(options);
103
+
104
+ const signature = Joi.object({
105
+ ...createStandardFields('signature', 'Sign this transaction or message to continue.'),
106
+ typeUrl: Joi.string()
107
+ .valid(
108
+ 'fg:x:delegation',
109
+ 'fg:t:transaction',
110
+ 'mime:text/plain',
111
+ 'mime:text/html',
112
+ 'eth:transaction',
113
+ 'eth:standard-data',
114
+ 'eth:personal-data',
115
+ 'eth:typed-data',
116
+ 'eth:legacy-data'
117
+ )
118
+ .required(),
119
+ display: Joi.string().allow('').default(''),
120
+ method: Joi.string()
121
+ .allow('none', ...Object.keys(types.HashType).map((x) => x.toLowerCase()))
122
+ .optional()
123
+ .default('sha3'),
124
+ digest: Joi.string().allow('').default(''),
125
+ origin: Joi.string().allow('').default(''),
126
+ nonce: Joi.string().allow('').default(''),
127
+ requirement: requirementSchema.optional(),
128
+ }).options(options);
129
+
130
+ const prepareTx = Joi.object({
131
+ ...createStandardFields('prepareTx', 'Prepare and sign this transaction to continue.'),
132
+ display: Joi.string().allow('').default(''),
133
+ partialTx: Joi.string().required(),
134
+ nonce: Joi.string().allow('').default(''),
135
+ requirement: requirementSchema.required(),
136
+ }).options(options);
137
+
138
+ const agreement = Joi.object({
139
+ ...createStandardFields('agreement', 'Confirm your agreement to continue.'),
140
+ uri: Joi.string()
141
+ .uri({ scheme: ['http', 'https'] })
142
+ .required()
143
+ .allow(''),
144
+ method: Joi.string()
145
+ .allow(...Object.keys(types.HashType).map((x) => x.toLowerCase()))
146
+ .optional()
147
+ .default('sha2'),
148
+ digest: Joi.string().required(),
149
+ }).options(options);
150
+
151
+ const verifiableCredential = Joi.object({
152
+ ...createStandardFields('verifiableCredential', 'Please present a verifiable credential to continue.'),
153
+
154
+ optional: Joi.boolean().default(false),
155
+
156
+ claimUrl: optionalUrlSchema,
157
+ acquireUrl: optionalUrlSchema,
158
+
159
+ // v1
160
+ item: Joi.array().items(Joi.string().min(1).required()).min(1).optional(), // alias to type
161
+ target: Joi.DID().optional(),
162
+ trustedIssuers: Joi.array().items(trustedIssuerSchema).min(1).optional(),
163
+ tag: Joi.string().min(1).allow('').default(''),
164
+ ownerDid: Joi.array().items(Joi.DID()).optional().default([]),
165
+
166
+ // v2
167
+ // - multiple filter should be interpreted as OR
168
+ // - fields inside a filter should be interpreted as AND
169
+ // - values inside a filter field should be interpreted as OR
170
+ filters: Joi.array()
171
+ .items(
172
+ Joi.object({
173
+ type: Joi.array().items(Joi.string().min(1).required()).min(1).optional(),
174
+ target: Joi.DID().optional(),
175
+ trustedIssuers: Joi.array().items(trustedIssuerSchema).min(1).optional(),
176
+ tag: Joi.string().min(1).allow('').default(''),
177
+ ownerDid: Joi.array().items(Joi.DID()).optional().default([]),
178
+ claimUrl: optionalUrlSchema,
179
+ acquireUrl: optionalUrlSchema,
180
+ })
181
+ )
182
+ .optional(),
183
+ }).options(options);
184
+
185
+ const asset = Joi.object({
186
+ ...createStandardFields('asset', 'Please present an on chain asset to continue.'),
187
+
188
+ optional: Joi.boolean().default(false),
189
+
190
+ // v1
191
+ address: Joi.DID().optional(),
192
+ trustedIssuers: Joi.array().items(trustedIssuerSchema).min(1).optional(),
193
+ trustedParents: Joi.array().items(Joi.DID().required()).min(1).optional(),
194
+ tag: Joi.string().min(1).allow('').default(''),
195
+ ownerDid: Joi.array().items(Joi.DID()).optional().default([]),
196
+ consumed: Joi.boolean().optional(),
197
+ acquireUrl: optionalUrlSchema,
198
+
199
+ // v2
200
+ // - multiple filter should be interpreted as OR
201
+ // - fields inside a filter should be interpreted as AND
202
+ // - values inside a filter field should be interpreted as OR
203
+ filters: Joi.array()
204
+ .items(
205
+ Joi.object({
206
+ address: Joi.DID().optional(),
207
+ trustedIssuers: Joi.array().items(trustedIssuerSchema).min(1).optional(),
208
+ trustedParents: Joi.array().items(Joi.DID().required()).min(1).optional(),
209
+ tag: Joi.string().min(1).allow('').default(''),
210
+ ownerDid: Joi.array().items(Joi.DID()).optional().default([]),
211
+ consumed: Joi.boolean().optional(),
212
+ acquireUrl: optionalUrlSchema,
213
+ })
214
+ )
215
+ .optional(),
216
+ }).options(options);
217
+
218
+ const assetOrVC = Joi.object({
219
+ ...createStandardFields('assetOrVC', 'Please present NFT to continue.'),
220
+
221
+ // - multiple filter should be interpreted as OR
222
+ // - fields inside a filter should be interpreted as AND
223
+ // - values inside a filter field should be interpreted as OR
224
+ filters: Joi.array()
225
+ .items(
226
+ Joi.object({
227
+ type: Joi.array().items(Joi.string().min(1).required()).min(1).optional(), // by vc type
228
+ address: Joi.DID().optional(), // by nft or vc did
229
+ trustedIssuers: Joi.array().items(trustedIssuerSchema).min(1).optional(),
230
+ trustedParents: Joi.array().items(Joi.DID().required()).min(1).optional(),
231
+ tag: Joi.string().min(1).allow('').default(''), // by vc or nft tag
232
+ ownerDid: Joi.array().items(Joi.DID()).optional().default([]),
233
+ consumed: Joi.boolean().optional(), // only valid for nft
234
+ claimUrl: optionalUrlSchema, // only valid for vc
235
+ acquireUrl: optionalUrlSchema, // only valid for nft
236
+ })
237
+ )
238
+ .required()
239
+ .min(1),
240
+
241
+ optional: Joi.boolean().default(false),
242
+ }).options(options);
243
+
244
+ return {
245
+ authPrincipal,
246
+ profile,
247
+ signature,
248
+ prepareTx,
249
+ agreement,
250
+ verifiableCredential,
251
+ asset,
252
+ assetOrVC,
253
+ keyPair,
254
+ encryptionKey,
255
+ };
256
+ };
@@ -0,0 +1,56 @@
1
+ const { Joi } = require('@arcblock/validator');
2
+
3
+ const createClaimsSchema = require('./claims');
4
+
5
+ const chainInfo = Joi.object({
6
+ type: Joi.string().optional().valid('arcblock', 'ethereum', 'solona').default('arcblock'),
7
+ id: Joi.any()
8
+ .when('type', { is: 'arcblock', then: Joi.string().optional().default('none') })
9
+ .when('type', {
10
+ is: 'ethereum',
11
+ then: Joi.string()
12
+ .required()
13
+ .pattern(/^[0-9]+$/, 'numbers'),
14
+ })
15
+ .when('type', {
16
+ is: 'solona',
17
+ then: Joi.string()
18
+ .required()
19
+ .pattern(/^[0-9]+$/, 'numbers'),
20
+ }),
21
+ host: Joi.string()
22
+ .when('type', { is: 'ethereum', then: Joi.string().optional().allow('') })
23
+ .when('type', { is: 'solona', then: Joi.string().optional().allow('') })
24
+ .when('type', {
25
+ is: 'arcblock',
26
+ then: Joi.string()
27
+ .uri({ scheme: ['http', 'https'] })
28
+ .allow('none')
29
+ .default('none'),
30
+ }),
31
+ }).options({ stripUnknown: true, noDefaults: false });
32
+
33
+ const appInfo = Joi.object({
34
+ name: Joi.string().required(),
35
+ description: Joi.string().required(),
36
+ icon: Joi.string()
37
+ .uri({ scheme: ['http', 'https'] })
38
+ .required(),
39
+ link: Joi.string()
40
+ .uri({ scheme: ['http', 'https'] })
41
+ .optional(),
42
+ path: Joi.string()
43
+ .uri({ scheme: ['http', 'https'] })
44
+ .default('https://abtwallet.io/i/'),
45
+ publisher: Joi.DID().optional(),
46
+ updateSubEndpoint: Joi.boolean().optional(),
47
+ subscriptionEndpoint: Joi.string().optional(),
48
+ nodeDid: Joi.DID().optional(),
49
+ agentDid: Joi.DID().optional(),
50
+ }).options({ stripUnknown: false, noDefaults: false });
51
+
52
+ module.exports = Object.freeze({
53
+ chainInfo,
54
+ appInfo,
55
+ claims: createClaimsSchema(chainInfo),
56
+ });
package/package.json ADDED
@@ -0,0 +1,86 @@
1
+ {
2
+ "name": "@arcblock/did-connect-js",
3
+ "description": "Helper function to setup DID Connect support on a node.js web server",
4
+ "version": "1.21.2",
5
+ "author": {
6
+ "name": "wangshijun",
7
+ "email": "shijun@arcblock.io",
8
+ "url": "https://github.com/wangshijun"
9
+ },
10
+ "contributors": [
11
+ "wangshijun <shijun@arcblock.io> (https://github.com/wangshijun)"
12
+ ],
13
+ "bugs": {
14
+ "url": "https://github.com/ArcBlock/blockchain/issues",
15
+ "email": "shijun@arcblock.io"
16
+ },
17
+ "publishConfig": {
18
+ "access": "public"
19
+ },
20
+ "dependencies": {
21
+ "cors": "^2.8.5",
22
+ "debug": "^4.3.6",
23
+ "json-stable-stringify": "^1.0.1",
24
+ "lodash": "^4.17.21",
25
+ "semver": "^7.6.3",
26
+ "tweetnacl-sealedbox-js": "^1.2.0",
27
+ "@arcblock/did": "1.21.2",
28
+ "@arcblock/jwt": "1.21.2",
29
+ "@arcblock/validator": "1.21.2",
30
+ "@ocap/client": "1.21.2",
31
+ "@ocap/mcrypto": "1.21.2",
32
+ "@ocap/util": "1.21.2",
33
+ "@ocap/wallet": "1.21.2"
34
+ },
35
+ "devDependencies": {
36
+ "@arcblock/did-agent-storage-memory": "^1.8.0",
37
+ "@arcblock/did-connect-storage-memory": "^1.8.0",
38
+ "axios": "^1.7.5",
39
+ "jest": "^29.7.0",
40
+ "remark-cli": "^10.0.1",
41
+ "remark-preset-github": "^4.0.4",
42
+ "tweetnacl": "^1.0.3",
43
+ "@ocap/e2e-test": "1.21.2"
44
+ },
45
+ "remarkConfig": {
46
+ "plugins": [
47
+ "preset-github",
48
+ [
49
+ {
50
+ "repository": "ArcBlock/blockchain"
51
+ }
52
+ ]
53
+ ]
54
+ },
55
+ "homepage": "https://github.com/ArcBlock/blockchain/tree/master/did/did-connect",
56
+ "keywords": [
57
+ "blockchain",
58
+ "arcblock",
59
+ "sdk",
60
+ "nodejs"
61
+ ],
62
+ "license": "Apache-2.0",
63
+ "main": "./lib/index.js",
64
+ "files": [
65
+ "lib"
66
+ ],
67
+ "repository": {
68
+ "type": "git",
69
+ "url": "https://github.com/ArcBlock/blockchain/tree/master/did/did-connect"
70
+ },
71
+ "resolutions": {
72
+ "tweetnacl": "1.0.3"
73
+ },
74
+ "gitHead": "87990c8b5e215107fc587c1ced0d6b3e2cd2483e",
75
+ "scripts": {
76
+ "lint": "eslint lib tests",
77
+ "lint:fix": "eslint --fix lib tests",
78
+ "docs": "pnpm run gen-dts && pnpm run gen-docs && pnpm run cleanup-docs && pnpm run format-docs",
79
+ "cleanup-docs": "node ../../scripts/cleanup-docs.js docs/README.md $npm_package_name",
80
+ "gen-docs": "jsdoc2md lib/**/*.js lib/**/**/*.js > docs/README.md",
81
+ "gen-dts": "j2d lib/index.js",
82
+ "format-docs": "remark . -o",
83
+ "test": "jest --forceExit --detectOpenHandles",
84
+ "coverage": "npm run test -- --coverage"
85
+ }
86
+ }