@yuants/app-virtual-exchange 0.8.0 → 0.8.1
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/dist/credential.js +49 -44
- package/dist/credential.js.map +1 -1
- package/lib/credential.d.ts +14 -11
- package/lib/credential.d.ts.map +1 -1
- package/lib/credential.js +49 -46
- package/lib/credential.js.map +1 -1
- package/package.json +2 -2
- package/temp/package-deps.json +5 -5
package/dist/credential.js
CHANGED
|
@@ -1,35 +1,43 @@
|
|
|
1
1
|
import { createCache } from '@yuants/cache';
|
|
2
2
|
import { getCredentialId } from '@yuants/exchange';
|
|
3
3
|
import { Terminal } from '@yuants/protocol';
|
|
4
|
-
import { readSecret, writeSecret } from '@yuants/secret';
|
|
4
|
+
import { listSecrets, readSecret, writeSecret } from '@yuants/secret';
|
|
5
5
|
import { escapeSQL, requestSQL } from '@yuants/sql';
|
|
6
6
|
import { newError } from '@yuants/utils';
|
|
7
7
|
import { defer, firstValueFrom, map, repeat, retry, shareReplay } from 'rxjs';
|
|
8
8
|
const terminal = Terminal.fromNodeEnv();
|
|
9
9
|
const credentialReader = process.env.NODE_UNIT_PUBLIC_KEY || terminal.keyPair.public_key;
|
|
10
|
+
/**
|
|
11
|
+
* 根据 secret sign 解析出对应的 exchange credential
|
|
12
|
+
* 此处可以做缓存,因为同一个 secret sign 对应的 credential 信息永远不会变化,可以节约解密和后续 SQL 查询的开销
|
|
13
|
+
* 得到 credential 后,此 credential 不一定是有效的,因为可能凭证信息已经过期或被撤销
|
|
14
|
+
*/
|
|
15
|
+
const secretSignToCredentialIdCache = createCache(async (sign) => {
|
|
16
|
+
const sql = `SELECT * FROM secret WHERE sign = ${escapeSQL(sign)} LIMIT 1;`;
|
|
17
|
+
const res = await requestSQL(terminal, sql);
|
|
18
|
+
if (res.length === 0)
|
|
19
|
+
throw newError('SECRET_NOT_FOUND', { sign });
|
|
20
|
+
const secret = res[0];
|
|
21
|
+
const decrypted = await readSecret(terminal, secret);
|
|
22
|
+
const credential = JSON.parse(new TextDecoder().decode(decrypted));
|
|
23
|
+
return credential;
|
|
24
|
+
});
|
|
25
|
+
/**
|
|
26
|
+
* 根据 credential 信息解析出对应的 credential ID
|
|
27
|
+
* 此处可以做缓存,因为同一个 credential 永远对应同一个 credential ID,可以节约后续 SQL 查询的开销
|
|
28
|
+
* 但是需要注意的是,credential ID 可能会因为凭证被撤销而失效,但是可以在下游调用其他服务时感知到,因此可以永久缓存
|
|
29
|
+
*/
|
|
10
30
|
const credentialIdCache = createCache(async (credentialKey) => {
|
|
11
31
|
const credential = JSON.parse(credentialKey);
|
|
12
32
|
const res = await getCredentialId(terminal, credential);
|
|
13
33
|
return res.data;
|
|
14
34
|
});
|
|
15
|
-
|
|
16
|
-
const secrets = await
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const credential = JSON.parse(new TextDecoder().decode(decrypted));
|
|
22
|
-
result.credential = credential;
|
|
23
|
-
const res = await credentialIdCache.query(JSON.stringify(credential));
|
|
24
|
-
if (res) {
|
|
25
|
-
result.credentialId = res;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
catch (e) {
|
|
29
|
-
result.reason = `${e}`;
|
|
30
|
-
}
|
|
31
|
-
}));
|
|
32
|
-
return results;
|
|
35
|
+
const listAllCredentials = async () => {
|
|
36
|
+
const secrets = await listSecrets(terminal, {
|
|
37
|
+
reader: credentialReader,
|
|
38
|
+
tags: { type: 'exchange_credential' },
|
|
39
|
+
});
|
|
40
|
+
return Promise.allSettled(secrets.map((secret) => getCredentialBySecretId(secret.sign)));
|
|
33
41
|
};
|
|
34
42
|
terminal.server.provideService('VEX/RegisterExchangeCredential', {
|
|
35
43
|
type: 'object',
|
|
@@ -44,6 +52,7 @@ terminal.server.provideService('VEX/RegisterExchangeCredential', {
|
|
|
44
52
|
const secret = await writeSecret(terminal, credentialReader, { type: 'exchange_credential' }, secretData);
|
|
45
53
|
return { res: { code: 0, message: 'OK', data: secret } };
|
|
46
54
|
});
|
|
55
|
+
// For Debugging Purpose
|
|
47
56
|
terminal.server.provideService('VEX/ListExchangeCredential', {}, async () => {
|
|
48
57
|
return { res: { code: 0, message: 'OK', data: await listAllCredentials() } };
|
|
49
58
|
});
|
|
@@ -51,14 +60,15 @@ terminal.server.provideService('VEX/ListCredentials', {}, async () => {
|
|
|
51
60
|
const credentials = await firstValueFrom(validCredentials$);
|
|
52
61
|
return { res: { code: 0, message: 'OK', data: [...credentials.keys()] } };
|
|
53
62
|
});
|
|
54
|
-
const
|
|
55
|
-
export const validCredentials$ = defer(() => credentialCache.query('')).pipe(map((x) => {
|
|
63
|
+
export const validCredentials$ = defer(() => listAllCredentials()).pipe(map((x) => {
|
|
56
64
|
const map = new Map();
|
|
57
65
|
if (!x)
|
|
58
66
|
return map;
|
|
59
67
|
for (const xx of x) {
|
|
60
|
-
if (xx.
|
|
61
|
-
|
|
68
|
+
if (xx.status !== 'fulfilled')
|
|
69
|
+
continue;
|
|
70
|
+
if (xx.value.credentialId && xx.value.credential) {
|
|
71
|
+
map.set(xx.value.credentialId, xx.value.credential);
|
|
62
72
|
}
|
|
63
73
|
}
|
|
64
74
|
return map;
|
|
@@ -70,26 +80,21 @@ export const validCredentialTypes$ = validCredentials$.pipe(map((credentials) =>
|
|
|
70
80
|
});
|
|
71
81
|
return Array.from(types);
|
|
72
82
|
}));
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
if (!
|
|
84
|
-
throw newError('CREDENTIAL_NOT_RESOLVED', {
|
|
85
|
-
|
|
86
|
-
if (!
|
|
87
|
-
throw newError('CREDENTIAL_ID_NOT_RESOLVED', {
|
|
88
|
-
}
|
|
89
|
-
return {
|
|
90
|
-
secret: theCredential.secret,
|
|
91
|
-
credential: theCredential.credential,
|
|
92
|
-
credentialId: theCredential.credentialId,
|
|
93
|
-
};
|
|
83
|
+
/**
|
|
84
|
+
* 根据 secret sign 解析出对应的 credential 以及 credential ID
|
|
85
|
+
* @param sign - secret sign
|
|
86
|
+
* @returns 解析得到的 credential 以及对应的 credential ID
|
|
87
|
+
* @throws 如果无法解析出对应的 credential 或 credential ID,则抛出异常
|
|
88
|
+
*
|
|
89
|
+
* 不依赖 List Credential 服务,可以及时感知凭证的新增和变更
|
|
90
|
+
*/
|
|
91
|
+
export const getCredentialBySecretId = async (sign) => {
|
|
92
|
+
const credential = await secretSignToCredentialIdCache.query(sign);
|
|
93
|
+
if (!credential)
|
|
94
|
+
throw newError('CREDENTIAL_NOT_RESOLVED', { sign });
|
|
95
|
+
const credentialId = await credentialIdCache.query(JSON.stringify(credential));
|
|
96
|
+
if (!credentialId)
|
|
97
|
+
throw newError('CREDENTIAL_ID_NOT_RESOLVED', { sign });
|
|
98
|
+
return { sign, credential, credentialId };
|
|
94
99
|
};
|
|
95
100
|
//# sourceMappingURL=credential.js.map
|
package/dist/credential.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credential.js","sourceRoot":"","sources":["../src/credential.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAW,UAAU,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"credential.js","sourceRoot":"","sources":["../src/credential.ts"],"names":[],"mappings":"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","sourcesContent":["import { createCache } from '@yuants/cache';\nimport { getCredentialId } from '@yuants/exchange';\nimport { Terminal } from '@yuants/protocol';\nimport { ISecret, listSecrets, readSecret, writeSecret } from '@yuants/secret';\nimport { escapeSQL, requestSQL } from '@yuants/sql';\nimport { newError } from '@yuants/utils';\nimport { defer, firstValueFrom, map, repeat, retry, shareReplay } from 'rxjs';\n\ninterface IExchangeCredential {\n type: string;\n payload: any;\n}\n\nconst terminal = Terminal.fromNodeEnv();\n\nconst credentialReader = process.env.NODE_UNIT_PUBLIC_KEY || terminal.keyPair.public_key;\n\n/**\n * 根据 secret sign 解析出对应的 exchange credential\n * 此处可以做缓存,因为同一个 secret sign 对应的 credential 信息永远不会变化,可以节约解密和后续 SQL 查询的开销\n * 得到 credential 后,此 credential 不一定是有效的,因为可能凭证信息已经过期或被撤销\n */\nconst secretSignToCredentialIdCache = createCache(async (sign: string) => {\n const sql = `SELECT * FROM secret WHERE sign = ${escapeSQL(sign)} LIMIT 1;`;\n const res = await requestSQL<ISecret[]>(terminal, sql);\n if (res.length === 0) throw newError('SECRET_NOT_FOUND', { sign });\n const secret = res[0];\n const decrypted = await readSecret(terminal, secret);\n const credential = JSON.parse(new TextDecoder().decode(decrypted)) as IExchangeCredential;\n return credential;\n});\n\n/**\n * 根据 credential 信息解析出对应的 credential ID\n * 此处可以做缓存,因为同一个 credential 永远对应同一个 credential ID,可以节约后续 SQL 查询的开销\n * 但是需要注意的是,credential ID 可能会因为凭证被撤销而失效,但是可以在下游调用其他服务时感知到,因此可以永久缓存\n */\nconst credentialIdCache = createCache(async (credentialKey: string) => {\n const credential = JSON.parse(credentialKey) as IExchangeCredential;\n const res = await getCredentialId(terminal, credential);\n return res.data;\n});\n\nconst listAllCredentials = async () => {\n const secrets = await listSecrets(terminal, {\n reader: credentialReader,\n tags: { type: 'exchange_credential' },\n });\n\n return Promise.allSettled(secrets.map((secret) => getCredentialBySecretId(secret.sign)));\n};\n\nterminal.server.provideService<IExchangeCredential, ISecret>(\n 'VEX/RegisterExchangeCredential',\n {\n type: 'object',\n required: ['type', 'payload'],\n properties: {\n type: { type: 'string' },\n payload: { type: 'object' },\n },\n },\n async (msg) => {\n const credential = msg.req;\n const secretData = new TextEncoder().encode(JSON.stringify(credential));\n const secret = await writeSecret(terminal, credentialReader, { type: 'exchange_credential' }, secretData);\n return { res: { code: 0, message: 'OK', data: secret } };\n },\n);\n\n// For Debugging Purpose\nterminal.server.provideService('VEX/ListExchangeCredential', {}, async () => {\n return { res: { code: 0, message: 'OK', data: await listAllCredentials() } };\n});\n\nterminal.server.provideService<void, string[]>('VEX/ListCredentials', {}, async () => {\n const credentials = await firstValueFrom(validCredentials$);\n return { res: { code: 0, message: 'OK', data: [...credentials.keys()] } };\n});\n\nexport const validCredentials$ = defer(() => listAllCredentials()).pipe(\n map((x) => {\n const map = new Map<string, IExchangeCredential>();\n if (!x) return map;\n for (const xx of x) {\n if (xx.status !== 'fulfilled') continue;\n if (xx.value.credentialId && xx.value.credential) {\n map.set(xx.value.credentialId, xx.value.credential);\n }\n }\n return map;\n }),\n repeat({ delay: 10000 }),\n retry({ delay: 5000 }),\n shareReplay(1),\n);\n\nexport const validCredentialTypes$ = validCredentials$.pipe(\n map((credentials) => {\n const types = new Set<string>();\n credentials.forEach((credential) => {\n types.add(credential.type);\n });\n return Array.from(types);\n }),\n);\n\n/**\n * 根据 secret sign 解析出对应的 credential 以及 credential ID\n * @param sign - secret sign\n * @returns 解析得到的 credential 以及对应的 credential ID\n * @throws 如果无法解析出对应的 credential 或 credential ID,则抛出异常\n *\n * 不依赖 List Credential 服务,可以及时感知凭证的新增和变更\n */\nexport const getCredentialBySecretId = async (sign: string) => {\n const credential = await secretSignToCredentialIdCache.query(sign);\n if (!credential) throw newError('CREDENTIAL_NOT_RESOLVED', { sign });\n const credentialId = await credentialIdCache.query(JSON.stringify(credential));\n if (!credentialId) throw newError('CREDENTIAL_ID_NOT_RESOLVED', { sign });\n return { sign, credential, credentialId };\n};\n"]}
|
package/lib/credential.d.ts
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
export interface IExchangeCredential {
|
|
1
|
+
interface IExchangeCredential {
|
|
3
2
|
type: string;
|
|
4
3
|
payload: any;
|
|
5
4
|
}
|
|
6
|
-
interface ICredentialResolvedStatus {
|
|
7
|
-
secret: ISecret;
|
|
8
|
-
credential?: IExchangeCredential;
|
|
9
|
-
credentialId?: string;
|
|
10
|
-
reason?: string;
|
|
11
|
-
}
|
|
12
|
-
export declare const listAllCredentials: () => Promise<ICredentialResolvedStatus[]>;
|
|
13
5
|
export declare const validCredentials$: import("rxjs").Observable<Map<string, IExchangeCredential>>;
|
|
14
6
|
export declare const validCredentialTypes$: import("rxjs").Observable<string[]>;
|
|
15
|
-
|
|
16
|
-
|
|
7
|
+
/**
|
|
8
|
+
* 根据 secret sign 解析出对应的 credential 以及 credential ID
|
|
9
|
+
* @param sign - secret sign
|
|
10
|
+
* @returns 解析得到的 credential 以及对应的 credential ID
|
|
11
|
+
* @throws 如果无法解析出对应的 credential 或 credential ID,则抛出异常
|
|
12
|
+
*
|
|
13
|
+
* 不依赖 List Credential 服务,可以及时感知凭证的新增和变更
|
|
14
|
+
*/
|
|
15
|
+
export declare const getCredentialBySecretId: (sign: string) => Promise<{
|
|
16
|
+
sign: string;
|
|
17
|
+
credential: IExchangeCredential;
|
|
18
|
+
credentialId: string;
|
|
19
|
+
}>;
|
|
17
20
|
export {};
|
|
18
21
|
//# sourceMappingURL=credential.d.ts.map
|
package/lib/credential.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credential.d.ts","sourceRoot":"","sources":["../src/credential.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"credential.d.ts","sourceRoot":"","sources":["../src/credential.ts"],"names":[],"mappings":"AAQA,UAAU,mBAAmB;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,GAAG,CAAC;CACd;AAqED,eAAO,MAAM,iBAAiB,6DAe7B,CAAC;AAEF,eAAO,MAAM,qBAAqB,qCAQjC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,SAAgB,MAAM;;;;EAMzD,CAAC"}
|
package/lib/credential.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getCredentialBySecretId = exports.
|
|
3
|
+
exports.getCredentialBySecretId = exports.validCredentialTypes$ = exports.validCredentials$ = void 0;
|
|
4
4
|
const cache_1 = require("@yuants/cache");
|
|
5
5
|
const exchange_1 = require("@yuants/exchange");
|
|
6
6
|
const protocol_1 = require("@yuants/protocol");
|
|
@@ -10,31 +10,38 @@ const utils_1 = require("@yuants/utils");
|
|
|
10
10
|
const rxjs_1 = require("rxjs");
|
|
11
11
|
const terminal = protocol_1.Terminal.fromNodeEnv();
|
|
12
12
|
const credentialReader = process.env.NODE_UNIT_PUBLIC_KEY || terminal.keyPair.public_key;
|
|
13
|
+
/**
|
|
14
|
+
* 根据 secret sign 解析出对应的 exchange credential
|
|
15
|
+
* 此处可以做缓存,因为同一个 secret sign 对应的 credential 信息永远不会变化,可以节约解密和后续 SQL 查询的开销
|
|
16
|
+
* 得到 credential 后,此 credential 不一定是有效的,因为可能凭证信息已经过期或被撤销
|
|
17
|
+
*/
|
|
18
|
+
const secretSignToCredentialIdCache = (0, cache_1.createCache)(async (sign) => {
|
|
19
|
+
const sql = `SELECT * FROM secret WHERE sign = ${(0, sql_1.escapeSQL)(sign)} LIMIT 1;`;
|
|
20
|
+
const res = await (0, sql_1.requestSQL)(terminal, sql);
|
|
21
|
+
if (res.length === 0)
|
|
22
|
+
throw (0, utils_1.newError)('SECRET_NOT_FOUND', { sign });
|
|
23
|
+
const secret = res[0];
|
|
24
|
+
const decrypted = await (0, secret_1.readSecret)(terminal, secret);
|
|
25
|
+
const credential = JSON.parse(new TextDecoder().decode(decrypted));
|
|
26
|
+
return credential;
|
|
27
|
+
});
|
|
28
|
+
/**
|
|
29
|
+
* 根据 credential 信息解析出对应的 credential ID
|
|
30
|
+
* 此处可以做缓存,因为同一个 credential 永远对应同一个 credential ID,可以节约后续 SQL 查询的开销
|
|
31
|
+
* 但是需要注意的是,credential ID 可能会因为凭证被撤销而失效,但是可以在下游调用其他服务时感知到,因此可以永久缓存
|
|
32
|
+
*/
|
|
13
33
|
const credentialIdCache = (0, cache_1.createCache)(async (credentialKey) => {
|
|
14
34
|
const credential = JSON.parse(credentialKey);
|
|
15
35
|
const res = await (0, exchange_1.getCredentialId)(terminal, credential);
|
|
16
36
|
return res.data;
|
|
17
37
|
});
|
|
18
38
|
const listAllCredentials = async () => {
|
|
19
|
-
const secrets = await (0,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const credential = JSON.parse(new TextDecoder().decode(decrypted));
|
|
25
|
-
result.credential = credential;
|
|
26
|
-
const res = await credentialIdCache.query(JSON.stringify(credential));
|
|
27
|
-
if (res) {
|
|
28
|
-
result.credentialId = res;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
catch (e) {
|
|
32
|
-
result.reason = `${e}`;
|
|
33
|
-
}
|
|
34
|
-
}));
|
|
35
|
-
return results;
|
|
39
|
+
const secrets = await (0, secret_1.listSecrets)(terminal, {
|
|
40
|
+
reader: credentialReader,
|
|
41
|
+
tags: { type: 'exchange_credential' },
|
|
42
|
+
});
|
|
43
|
+
return Promise.allSettled(secrets.map((secret) => (0, exports.getCredentialBySecretId)(secret.sign)));
|
|
36
44
|
};
|
|
37
|
-
exports.listAllCredentials = listAllCredentials;
|
|
38
45
|
terminal.server.provideService('VEX/RegisterExchangeCredential', {
|
|
39
46
|
type: 'object',
|
|
40
47
|
required: ['type', 'payload'],
|
|
@@ -48,21 +55,23 @@ terminal.server.provideService('VEX/RegisterExchangeCredential', {
|
|
|
48
55
|
const secret = await (0, secret_1.writeSecret)(terminal, credentialReader, { type: 'exchange_credential' }, secretData);
|
|
49
56
|
return { res: { code: 0, message: 'OK', data: secret } };
|
|
50
57
|
});
|
|
58
|
+
// For Debugging Purpose
|
|
51
59
|
terminal.server.provideService('VEX/ListExchangeCredential', {}, async () => {
|
|
52
|
-
return { res: { code: 0, message: 'OK', data: await
|
|
60
|
+
return { res: { code: 0, message: 'OK', data: await listAllCredentials() } };
|
|
53
61
|
});
|
|
54
62
|
terminal.server.provideService('VEX/ListCredentials', {}, async () => {
|
|
55
63
|
const credentials = await (0, rxjs_1.firstValueFrom)(exports.validCredentials$);
|
|
56
64
|
return { res: { code: 0, message: 'OK', data: [...credentials.keys()] } };
|
|
57
65
|
});
|
|
58
|
-
|
|
59
|
-
exports.validCredentials$ = (0, rxjs_1.defer)(() => credentialCache.query('')).pipe((0, rxjs_1.map)((x) => {
|
|
66
|
+
exports.validCredentials$ = (0, rxjs_1.defer)(() => listAllCredentials()).pipe((0, rxjs_1.map)((x) => {
|
|
60
67
|
const map = new Map();
|
|
61
68
|
if (!x)
|
|
62
69
|
return map;
|
|
63
70
|
for (const xx of x) {
|
|
64
|
-
if (xx.
|
|
65
|
-
|
|
71
|
+
if (xx.status !== 'fulfilled')
|
|
72
|
+
continue;
|
|
73
|
+
if (xx.value.credentialId && xx.value.credential) {
|
|
74
|
+
map.set(xx.value.credentialId, xx.value.credential);
|
|
66
75
|
}
|
|
67
76
|
}
|
|
68
77
|
return map;
|
|
@@ -74,28 +83,22 @@ exports.validCredentialTypes$ = exports.validCredentials$.pipe((0, rxjs_1.map)((
|
|
|
74
83
|
});
|
|
75
84
|
return Array.from(types);
|
|
76
85
|
}));
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
return {
|
|
95
|
-
secret: theCredential.secret,
|
|
96
|
-
credential: theCredential.credential,
|
|
97
|
-
credentialId: theCredential.credentialId,
|
|
98
|
-
};
|
|
86
|
+
/**
|
|
87
|
+
* 根据 secret sign 解析出对应的 credential 以及 credential ID
|
|
88
|
+
* @param sign - secret sign
|
|
89
|
+
* @returns 解析得到的 credential 以及对应的 credential ID
|
|
90
|
+
* @throws 如果无法解析出对应的 credential 或 credential ID,则抛出异常
|
|
91
|
+
*
|
|
92
|
+
* 不依赖 List Credential 服务,可以及时感知凭证的新增和变更
|
|
93
|
+
*/
|
|
94
|
+
const getCredentialBySecretId = async (sign) => {
|
|
95
|
+
const credential = await secretSignToCredentialIdCache.query(sign);
|
|
96
|
+
if (!credential)
|
|
97
|
+
throw (0, utils_1.newError)('CREDENTIAL_NOT_RESOLVED', { sign });
|
|
98
|
+
const credentialId = await credentialIdCache.query(JSON.stringify(credential));
|
|
99
|
+
if (!credentialId)
|
|
100
|
+
throw (0, utils_1.newError)('CREDENTIAL_ID_NOT_RESOLVED', { sign });
|
|
101
|
+
return { sign, credential, credentialId };
|
|
99
102
|
};
|
|
100
103
|
exports.getCredentialBySecretId = getCredentialBySecretId;
|
|
101
104
|
//# sourceMappingURL=credential.js.map
|
package/lib/credential.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credential.js","sourceRoot":"","sources":["../src/credential.ts"],"names":[],"mappings":";;;AAAA,yCAA4C;AAC5C,+CAAmD;AACnD,+CAA4C;AAC5C,
|
|
1
|
+
{"version":3,"file":"credential.js","sourceRoot":"","sources":["../src/credential.ts"],"names":[],"mappings":"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","sourcesContent":["import { createCache } from '@yuants/cache';\nimport { getCredentialId } from '@yuants/exchange';\nimport { Terminal } from '@yuants/protocol';\nimport { ISecret, listSecrets, readSecret, writeSecret } from '@yuants/secret';\nimport { escapeSQL, requestSQL } from '@yuants/sql';\nimport { newError } from '@yuants/utils';\nimport { defer, firstValueFrom, map, repeat, retry, shareReplay } from 'rxjs';\n\ninterface IExchangeCredential {\n type: string;\n payload: any;\n}\n\nconst terminal = Terminal.fromNodeEnv();\n\nconst credentialReader = process.env.NODE_UNIT_PUBLIC_KEY || terminal.keyPair.public_key;\n\n/**\n * 根据 secret sign 解析出对应的 exchange credential\n * 此处可以做缓存,因为同一个 secret sign 对应的 credential 信息永远不会变化,可以节约解密和后续 SQL 查询的开销\n * 得到 credential 后,此 credential 不一定是有效的,因为可能凭证信息已经过期或被撤销\n */\nconst secretSignToCredentialIdCache = createCache(async (sign: string) => {\n const sql = `SELECT * FROM secret WHERE sign = ${escapeSQL(sign)} LIMIT 1;`;\n const res = await requestSQL<ISecret[]>(terminal, sql);\n if (res.length === 0) throw newError('SECRET_NOT_FOUND', { sign });\n const secret = res[0];\n const decrypted = await readSecret(terminal, secret);\n const credential = JSON.parse(new TextDecoder().decode(decrypted)) as IExchangeCredential;\n return credential;\n});\n\n/**\n * 根据 credential 信息解析出对应的 credential ID\n * 此处可以做缓存,因为同一个 credential 永远对应同一个 credential ID,可以节约后续 SQL 查询的开销\n * 但是需要注意的是,credential ID 可能会因为凭证被撤销而失效,但是可以在下游调用其他服务时感知到,因此可以永久缓存\n */\nconst credentialIdCache = createCache(async (credentialKey: string) => {\n const credential = JSON.parse(credentialKey) as IExchangeCredential;\n const res = await getCredentialId(terminal, credential);\n return res.data;\n});\n\nconst listAllCredentials = async () => {\n const secrets = await listSecrets(terminal, {\n reader: credentialReader,\n tags: { type: 'exchange_credential' },\n });\n\n return Promise.allSettled(secrets.map((secret) => getCredentialBySecretId(secret.sign)));\n};\n\nterminal.server.provideService<IExchangeCredential, ISecret>(\n 'VEX/RegisterExchangeCredential',\n {\n type: 'object',\n required: ['type', 'payload'],\n properties: {\n type: { type: 'string' },\n payload: { type: 'object' },\n },\n },\n async (msg) => {\n const credential = msg.req;\n const secretData = new TextEncoder().encode(JSON.stringify(credential));\n const secret = await writeSecret(terminal, credentialReader, { type: 'exchange_credential' }, secretData);\n return { res: { code: 0, message: 'OK', data: secret } };\n },\n);\n\n// For Debugging Purpose\nterminal.server.provideService('VEX/ListExchangeCredential', {}, async () => {\n return { res: { code: 0, message: 'OK', data: await listAllCredentials() } };\n});\n\nterminal.server.provideService<void, string[]>('VEX/ListCredentials', {}, async () => {\n const credentials = await firstValueFrom(validCredentials$);\n return { res: { code: 0, message: 'OK', data: [...credentials.keys()] } };\n});\n\nexport const validCredentials$ = defer(() => listAllCredentials()).pipe(\n map((x) => {\n const map = new Map<string, IExchangeCredential>();\n if (!x) return map;\n for (const xx of x) {\n if (xx.status !== 'fulfilled') continue;\n if (xx.value.credentialId && xx.value.credential) {\n map.set(xx.value.credentialId, xx.value.credential);\n }\n }\n return map;\n }),\n repeat({ delay: 10000 }),\n retry({ delay: 5000 }),\n shareReplay(1),\n);\n\nexport const validCredentialTypes$ = validCredentials$.pipe(\n map((credentials) => {\n const types = new Set<string>();\n credentials.forEach((credential) => {\n types.add(credential.type);\n });\n return Array.from(types);\n }),\n);\n\n/**\n * 根据 secret sign 解析出对应的 credential 以及 credential ID\n * @param sign - secret sign\n * @returns 解析得到的 credential 以及对应的 credential ID\n * @throws 如果无法解析出对应的 credential 或 credential ID,则抛出异常\n *\n * 不依赖 List Credential 服务,可以及时感知凭证的新增和变更\n */\nexport const getCredentialBySecretId = async (sign: string) => {\n const credential = await secretSignToCredentialIdCache.query(sign);\n if (!credential) throw newError('CREDENTIAL_NOT_RESOLVED', { sign });\n const credentialId = await credentialIdCache.query(JSON.stringify(credential));\n if (!credentialId) throw newError('CREDENTIAL_ID_NOT_RESOLVED', { sign });\n return { sign, credential, credentialId };\n};\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yuants/app-virtual-exchange",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"@yuants/data-account": "0.10.1",
|
|
15
15
|
"@yuants/data-order": "0.7.0",
|
|
16
16
|
"@yuants/data-quote": "0.2.43",
|
|
17
|
-
"@yuants/secret": "0.
|
|
17
|
+
"@yuants/secret": "0.4.0",
|
|
18
18
|
"@yuants/sql": "0.9.30",
|
|
19
19
|
"@yuants/exchange": "0.5.1",
|
|
20
20
|
"@yuants/cache": "0.3.3",
|
package/temp/package-deps.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
|
-
"apps/virtual-exchange/CHANGELOG.json": "
|
|
3
|
-
"apps/virtual-exchange/CHANGELOG.md": "
|
|
2
|
+
"apps/virtual-exchange/CHANGELOG.json": "df0691c9a901de4e3c328d62f38272a0b3bdae3f",
|
|
3
|
+
"apps/virtual-exchange/CHANGELOG.md": "d6932a16d2c0fb598e42f4d57a79c28b700ccb4e",
|
|
4
4
|
"apps/virtual-exchange/api-extractor.json": "62f4fd324425b9a235f0c117975967aab09ced0c",
|
|
5
5
|
"apps/virtual-exchange/config/jest.config.json": "4bb17bde3ee911163a3edb36a6eb71491d80b1bd",
|
|
6
6
|
"apps/virtual-exchange/config/rig.json": "f6c7b5537dc77a3170ba9f008bae3b6c3ee11956",
|
|
7
7
|
"apps/virtual-exchange/config/typescript.json": "854907e8a821f2050f6533368db160c649c25348",
|
|
8
8
|
"apps/virtual-exchange/etc/app-virtual-exchange.api.md": "6cb40ec1fa2d40a31a7b0dd3f02b8b24a4d7c4de",
|
|
9
|
-
"apps/virtual-exchange/package.json": "
|
|
10
|
-
"apps/virtual-exchange/src/credential.ts": "
|
|
9
|
+
"apps/virtual-exchange/package.json": "3281548ed4ee4726782a671c76c58d16f115a6e7",
|
|
10
|
+
"apps/virtual-exchange/src/credential.ts": "edf0901b4e1038233bff07b8486d88c777fda3f5",
|
|
11
11
|
"apps/virtual-exchange/src/general.ts": "b3d0cd8c57975b9711008beaa05ad7f6812bd57e",
|
|
12
12
|
"apps/virtual-exchange/src/index.ts": "8d7f19a07e6be09c4d8fd4a49ddb3127d3fbf3de",
|
|
13
13
|
"apps/virtual-exchange/src/legacy-services.ts": "a9f6b6c61b7a0efc909a443e6fde88c2766562bf",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"libraries/data-account/temp/package-deps.json": "e6ba0067a1b68f17266564f15987936ab2672eb9",
|
|
22
22
|
"libraries/data-order/temp/package-deps.json": "ccdc9819f254f37a3591bb37876a86c703df33a6",
|
|
23
23
|
"libraries/data-quote/temp/package-deps.json": "34d079eab44d2bf65e07b112ac2099c6e92a015e",
|
|
24
|
-
"libraries/secret/temp/package-deps.json": "
|
|
24
|
+
"libraries/secret/temp/package-deps.json": "28f70cf8095162d1adb59070f30bf21f452537df",
|
|
25
25
|
"libraries/sql/temp/package-deps.json": "4a9a7ec55f04b20459e664e81e76fa74b6c77b39",
|
|
26
26
|
"libraries/exchange/temp/package-deps.json": "2679f6d65ffd785cbca43cfbe5b6b9a13c7c003d",
|
|
27
27
|
"libraries/cache/temp/package-deps.json": "a4afa15e6462983f9d3735d31dc1ed8a683fb4dc",
|