@riocrypto/common-server 1.0.2480 → 1.0.2483
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/build/clients/secret-manager-client.d.ts +19 -7
- package/build/clients/secret-manager-client.js +75 -60
- package/build/index.d.ts +1 -0
- package/build/index.js +1 -0
- package/build/models/rio-settings.d.ts +20 -0
- package/build/models/rio-settings.js +3 -0
- package/build/models/twap-session.d.ts +38 -0
- package/build/models/twap-session.js +76 -0
- package/package.json +2 -2
|
@@ -8,22 +8,34 @@ declare class SecretManagerClient {
|
|
|
8
8
|
private readonly POLL_INTERVAL_MS;
|
|
9
9
|
constructor(env: RioEnv);
|
|
10
10
|
/**
|
|
11
|
-
* Get a secret value from cache or fetch
|
|
12
|
-
* Once fetched,
|
|
11
|
+
* Get a secret value from cache or fetch the entire secret file
|
|
12
|
+
* Once fetched, all secrets are cached and automatically refreshed every hour
|
|
13
13
|
*/
|
|
14
14
|
getSecretValue(secretId: string): Promise<string | null>;
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
16
|
+
* Refresh the entire secret cache by fetching the complete secret file
|
|
17
17
|
*/
|
|
18
|
-
private
|
|
18
|
+
private refreshSecretCache;
|
|
19
19
|
/**
|
|
20
|
-
* Set up cache
|
|
20
|
+
* Set up cache with polling for the entire secret file
|
|
21
21
|
*/
|
|
22
22
|
private setupCacheWithPolling;
|
|
23
23
|
/**
|
|
24
|
-
* Clear the
|
|
24
|
+
* Clear the entire secret cache
|
|
25
25
|
*/
|
|
26
|
-
clearCache(
|
|
26
|
+
clearCache(): void;
|
|
27
|
+
/**
|
|
28
|
+
* Get all cached secrets (useful for debugging)
|
|
29
|
+
*/
|
|
30
|
+
getAllSecrets(): Record<string, string> | null;
|
|
31
|
+
/**
|
|
32
|
+
* Get cache status information
|
|
33
|
+
*/
|
|
34
|
+
getCacheStatus(): {
|
|
35
|
+
isLoaded: boolean;
|
|
36
|
+
secretCount: number;
|
|
37
|
+
lastFetched: Date | null;
|
|
38
|
+
};
|
|
27
39
|
}
|
|
28
40
|
export declare const secretManagerClient: SecretManagerClient;
|
|
29
41
|
export {};
|
|
@@ -39,7 +39,7 @@ const fs = __importStar(require("fs"));
|
|
|
39
39
|
class SecretManagerClient {
|
|
40
40
|
constructor(env) {
|
|
41
41
|
this.env = env;
|
|
42
|
-
this.secretCache =
|
|
42
|
+
this.secretCache = null;
|
|
43
43
|
this.POLL_INTERVAL_MS = 60 * 60 * 1000; // 1 hour
|
|
44
44
|
const secretFilePath = "/etc/secrets/secret-manager/secret-manager-service-account-key.json";
|
|
45
45
|
const secretFileContents = fs.readFileSync(secretFilePath, "utf8");
|
|
@@ -56,29 +56,34 @@ class SecretManagerClient {
|
|
|
56
56
|
});
|
|
57
57
|
}
|
|
58
58
|
/**
|
|
59
|
-
* Get a secret value from cache or fetch
|
|
60
|
-
* Once fetched,
|
|
59
|
+
* Get a secret value from cache or fetch the entire secret file
|
|
60
|
+
* Once fetched, all secrets are cached and automatically refreshed every hour
|
|
61
61
|
*/
|
|
62
62
|
getSecretValue(secretId) {
|
|
63
63
|
return __awaiter(this, void 0, void 0, function* () {
|
|
64
|
-
// Check if
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
return cachedSecret.value;
|
|
64
|
+
// Check if we have a cache and the secret exists
|
|
65
|
+
if (this.secretCache && this.secretCache.secrets[secretId]) {
|
|
66
|
+
return this.secretCache.secrets[secretId];
|
|
68
67
|
}
|
|
69
|
-
// If not in cache, fetch
|
|
70
|
-
const
|
|
71
|
-
if (
|
|
72
|
-
|
|
68
|
+
// If not in cache or cache doesn't exist, fetch entire secret file
|
|
69
|
+
const success = yield this.refreshSecretCache();
|
|
70
|
+
if (!success) {
|
|
71
|
+
return null;
|
|
73
72
|
}
|
|
74
|
-
|
|
73
|
+
// Check again after refresh
|
|
74
|
+
if (this.secretCache && this.secretCache.secrets[secretId]) {
|
|
75
|
+
return this.secretCache.secrets[secretId];
|
|
76
|
+
}
|
|
77
|
+
// Secret not found even after refresh
|
|
78
|
+
console.error(`Secret ${secretId} not found in secret file`);
|
|
79
|
+
return null;
|
|
75
80
|
});
|
|
76
81
|
}
|
|
77
82
|
/**
|
|
78
|
-
*
|
|
83
|
+
* Refresh the entire secret cache by fetching the complete secret file
|
|
79
84
|
*/
|
|
80
|
-
|
|
81
|
-
var _a, _b;
|
|
85
|
+
refreshSecretCache() {
|
|
86
|
+
var _a, _b, _c;
|
|
82
87
|
return __awaiter(this, void 0, void 0, function* () {
|
|
83
88
|
let file;
|
|
84
89
|
if (this.env === common_1.RioEnv.Development) {
|
|
@@ -105,7 +110,14 @@ class SecretManagerClient {
|
|
|
105
110
|
throw new Error("No payload data");
|
|
106
111
|
}
|
|
107
112
|
const secrets = JSON.parse(version.payload.data.toString());
|
|
108
|
-
|
|
113
|
+
// Clear existing polling if it exists
|
|
114
|
+
if ((_c = this.secretCache) === null || _c === void 0 ? void 0 : _c.pollingInterval) {
|
|
115
|
+
clearInterval(this.secretCache.pollingInterval);
|
|
116
|
+
}
|
|
117
|
+
// Set up new cache with polling
|
|
118
|
+
this.setupCacheWithPolling(secrets);
|
|
119
|
+
console.info(`Refreshed ${Object.keys(secrets).length} secrets from ${file}`);
|
|
120
|
+
return true;
|
|
109
121
|
}
|
|
110
122
|
catch (err) {
|
|
111
123
|
attempt++;
|
|
@@ -117,74 +129,77 @@ class SecretManagerClient {
|
|
|
117
129
|
continue;
|
|
118
130
|
}
|
|
119
131
|
else {
|
|
120
|
-
console.error(`Failed to access secret ${
|
|
121
|
-
return
|
|
132
|
+
console.error(`Failed to access secret file ${file}:`, err);
|
|
133
|
+
return false;
|
|
122
134
|
}
|
|
123
135
|
}
|
|
124
136
|
}
|
|
125
|
-
console.error(`Failed to access secret ${
|
|
126
|
-
return
|
|
137
|
+
console.error(`Failed to access secret file ${file} after ${maxRetries} attempts.`);
|
|
138
|
+
return false;
|
|
127
139
|
});
|
|
128
140
|
}
|
|
129
141
|
/**
|
|
130
|
-
* Set up cache
|
|
142
|
+
* Set up cache with polling for the entire secret file
|
|
131
143
|
*/
|
|
132
|
-
setupCacheWithPolling(
|
|
144
|
+
setupCacheWithPolling(secrets) {
|
|
133
145
|
// Only set up polling in non-test environments
|
|
134
146
|
if (process.env.NODE_ENV === "test") {
|
|
135
|
-
// For test environments, just cache the
|
|
136
|
-
this.secretCache
|
|
137
|
-
|
|
147
|
+
// For test environments, just cache the secrets without polling
|
|
148
|
+
this.secretCache = {
|
|
149
|
+
secrets,
|
|
138
150
|
pollingInterval: null,
|
|
139
|
-
|
|
151
|
+
lastFetched: new Date(),
|
|
152
|
+
};
|
|
140
153
|
return;
|
|
141
154
|
}
|
|
142
|
-
// Set up polling interval to refresh
|
|
155
|
+
// Set up polling interval to refresh all secrets
|
|
143
156
|
const pollingInterval = setInterval(() => __awaiter(this, void 0, void 0, function* () {
|
|
144
157
|
try {
|
|
145
|
-
const
|
|
146
|
-
if (
|
|
147
|
-
|
|
148
|
-
// Only update and log if the value has changed
|
|
149
|
-
if (currentCached && currentCached.value !== newValue) {
|
|
150
|
-
console.info(`Secret ${secretId} has been updated`);
|
|
151
|
-
this.secretCache.set(secretId, {
|
|
152
|
-
value: newValue,
|
|
153
|
-
pollingInterval: currentCached.pollingInterval,
|
|
154
|
-
});
|
|
155
|
-
}
|
|
158
|
+
const success = yield this.refreshSecretCache();
|
|
159
|
+
if (!success) {
|
|
160
|
+
console.error("Failed to refresh secret cache during polling");
|
|
156
161
|
}
|
|
157
162
|
}
|
|
158
163
|
catch (error) {
|
|
159
|
-
console.error(
|
|
164
|
+
console.error("Error polling secrets:", error);
|
|
160
165
|
}
|
|
161
166
|
}), this.POLL_INTERVAL_MS);
|
|
162
|
-
// Store the
|
|
163
|
-
this.secretCache
|
|
164
|
-
|
|
167
|
+
// Store the cache with polling interval
|
|
168
|
+
this.secretCache = {
|
|
169
|
+
secrets,
|
|
165
170
|
pollingInterval,
|
|
166
|
-
|
|
171
|
+
lastFetched: new Date(),
|
|
172
|
+
};
|
|
167
173
|
}
|
|
168
174
|
/**
|
|
169
|
-
* Clear the
|
|
175
|
+
* Clear the entire secret cache
|
|
170
176
|
*/
|
|
171
|
-
clearCache(
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
clearInterval(cached.pollingInterval);
|
|
176
|
-
}
|
|
177
|
-
this.secretCache.delete(secretId);
|
|
178
|
-
}
|
|
179
|
-
else {
|
|
180
|
-
// Clear all cached secrets
|
|
181
|
-
this.secretCache.forEach((cached) => {
|
|
182
|
-
if (cached.pollingInterval) {
|
|
183
|
-
clearInterval(cached.pollingInterval);
|
|
184
|
-
}
|
|
185
|
-
});
|
|
186
|
-
this.secretCache.clear();
|
|
177
|
+
clearCache() {
|
|
178
|
+
var _a;
|
|
179
|
+
if ((_a = this.secretCache) === null || _a === void 0 ? void 0 : _a.pollingInterval) {
|
|
180
|
+
clearInterval(this.secretCache.pollingInterval);
|
|
187
181
|
}
|
|
182
|
+
this.secretCache = null;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Get all cached secrets (useful for debugging)
|
|
186
|
+
*/
|
|
187
|
+
getAllSecrets() {
|
|
188
|
+
var _a;
|
|
189
|
+
return ((_a = this.secretCache) === null || _a === void 0 ? void 0 : _a.secrets) || null;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Get cache status information
|
|
193
|
+
*/
|
|
194
|
+
getCacheStatus() {
|
|
195
|
+
var _a;
|
|
196
|
+
return {
|
|
197
|
+
isLoaded: !!this.secretCache,
|
|
198
|
+
secretCount: this.secretCache
|
|
199
|
+
? Object.keys(this.secretCache.secrets).length
|
|
200
|
+
: 0,
|
|
201
|
+
lastFetched: ((_a = this.secretCache) === null || _a === void 0 ? void 0 : _a.lastFetched) || null,
|
|
202
|
+
};
|
|
188
203
|
}
|
|
189
204
|
}
|
|
190
205
|
exports.secretManagerClient = new SecretManagerClient(process.env.RIO_ENV || process.env.NEXT_PUBLIC_RIO_ENV);
|
package/build/index.d.ts
CHANGED
|
@@ -94,6 +94,7 @@ export * from "./models/liquidity-reservation";
|
|
|
94
94
|
export * from "./models/axe-slack-thread";
|
|
95
95
|
export * from "./models/axe-telegram-thread";
|
|
96
96
|
export * from "./models/auth-activity-slack-thread";
|
|
97
|
+
export * from "./models/twap-session";
|
|
97
98
|
export * from "./clients/axios-with-logging";
|
|
98
99
|
export * from "./clients/slack-client";
|
|
99
100
|
export * from "./clients/fireblocks-client";
|
package/build/index.js
CHANGED
|
@@ -110,6 +110,7 @@ __exportStar(require("./models/liquidity-reservation"), exports);
|
|
|
110
110
|
__exportStar(require("./models/axe-slack-thread"), exports);
|
|
111
111
|
__exportStar(require("./models/axe-telegram-thread"), exports);
|
|
112
112
|
__exportStar(require("./models/auth-activity-slack-thread"), exports);
|
|
113
|
+
__exportStar(require("./models/twap-session"), exports);
|
|
113
114
|
__exportStar(require("./clients/axios-with-logging"), exports);
|
|
114
115
|
__exportStar(require("./clients/slack-client"), exports);
|
|
115
116
|
__exportStar(require("./clients/fireblocks-client"), exports);
|
|
@@ -72,6 +72,16 @@ interface RioSettingsAttrs {
|
|
|
72
72
|
dates: string[];
|
|
73
73
|
};
|
|
74
74
|
};
|
|
75
|
+
defaultTWAPSettings: {
|
|
76
|
+
[key in Fiat]?: {
|
|
77
|
+
[key in Side]: {
|
|
78
|
+
isEnabled: boolean;
|
|
79
|
+
spread: number;
|
|
80
|
+
minClipSize: number;
|
|
81
|
+
interval: number;
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
};
|
|
75
85
|
}
|
|
76
86
|
interface RioSettingsDoc extends mongoose.Document {
|
|
77
87
|
platformFee: number;
|
|
@@ -144,6 +154,16 @@ interface RioSettingsDoc extends mongoose.Document {
|
|
|
144
154
|
dates: string[];
|
|
145
155
|
};
|
|
146
156
|
};
|
|
157
|
+
defaultTWAPSettings: {
|
|
158
|
+
[key in Fiat]?: {
|
|
159
|
+
[key in Side]: {
|
|
160
|
+
isEnabled: boolean;
|
|
161
|
+
spread: number;
|
|
162
|
+
minClipSize: number;
|
|
163
|
+
interval: number;
|
|
164
|
+
};
|
|
165
|
+
};
|
|
166
|
+
};
|
|
147
167
|
}
|
|
148
168
|
interface RioSettingsModel extends mongoose.Model<RioSettingsDoc> {
|
|
149
169
|
build(attrs: RioSettingsAttrs): RioSettingsDoc;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Fiat, Crypto, Side, TWAPSessionStatus } from "@riocrypto/common";
|
|
2
|
+
import { Mongoose, Model, Document } from "mongoose";
|
|
3
|
+
interface TWAPSessionAttrs {
|
|
4
|
+
createdAt: Date;
|
|
5
|
+
status: TWAPSessionStatus;
|
|
6
|
+
side: Side;
|
|
7
|
+
crypto: Crypto;
|
|
8
|
+
fiat: Fiat;
|
|
9
|
+
amountToTrade: number;
|
|
10
|
+
amountTraded: number;
|
|
11
|
+
amountRemaining: number;
|
|
12
|
+
tradeCurrency: Fiat | Crypto;
|
|
13
|
+
spread: number;
|
|
14
|
+
clipSize: number;
|
|
15
|
+
interval: number;
|
|
16
|
+
isRunning: boolean;
|
|
17
|
+
}
|
|
18
|
+
interface TWAPSessionModel extends Model<TWAPSessionDoc> {
|
|
19
|
+
build(attrs: TWAPSessionAttrs): TWAPSessionDoc;
|
|
20
|
+
}
|
|
21
|
+
interface TWAPSessionDoc extends Document {
|
|
22
|
+
id: string;
|
|
23
|
+
createdAt: Date;
|
|
24
|
+
status: TWAPSessionStatus;
|
|
25
|
+
side: Side;
|
|
26
|
+
crypto: Crypto;
|
|
27
|
+
fiat: Fiat;
|
|
28
|
+
amountToTrade: number;
|
|
29
|
+
amountTraded: number;
|
|
30
|
+
amountRemaining: number;
|
|
31
|
+
tradeCurrency: Fiat | Crypto;
|
|
32
|
+
spread: number;
|
|
33
|
+
clipSize: number;
|
|
34
|
+
interval: number;
|
|
35
|
+
isRunning: boolean;
|
|
36
|
+
}
|
|
37
|
+
declare const buildTWAPSession: (mongoose: Mongoose) => TWAPSessionModel;
|
|
38
|
+
export { buildTWAPSession, TWAPSessionDoc, TWAPSessionAttrs };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildTWAPSession = void 0;
|
|
4
|
+
const buildTWAPSession = (mongoose) => {
|
|
5
|
+
if (mongoose.models.TWAPSession) {
|
|
6
|
+
return mongoose.model("TWAPSession");
|
|
7
|
+
}
|
|
8
|
+
const TWAPSessionSchema = new mongoose.Schema({
|
|
9
|
+
createdAt: {
|
|
10
|
+
type: Date,
|
|
11
|
+
required: true,
|
|
12
|
+
},
|
|
13
|
+
status: {
|
|
14
|
+
type: String,
|
|
15
|
+
required: true,
|
|
16
|
+
},
|
|
17
|
+
side: {
|
|
18
|
+
type: String,
|
|
19
|
+
required: true,
|
|
20
|
+
},
|
|
21
|
+
crypto: {
|
|
22
|
+
type: String,
|
|
23
|
+
required: true,
|
|
24
|
+
},
|
|
25
|
+
fiat: {
|
|
26
|
+
type: String,
|
|
27
|
+
required: true,
|
|
28
|
+
},
|
|
29
|
+
amountToTrade: {
|
|
30
|
+
type: Number,
|
|
31
|
+
required: true,
|
|
32
|
+
},
|
|
33
|
+
amountTraded: {
|
|
34
|
+
type: Number,
|
|
35
|
+
required: true,
|
|
36
|
+
},
|
|
37
|
+
amountRemaining: {
|
|
38
|
+
type: Number,
|
|
39
|
+
required: true,
|
|
40
|
+
},
|
|
41
|
+
tradeCurrency: {
|
|
42
|
+
type: String,
|
|
43
|
+
required: true,
|
|
44
|
+
},
|
|
45
|
+
spread: {
|
|
46
|
+
type: Number,
|
|
47
|
+
required: true,
|
|
48
|
+
},
|
|
49
|
+
clipSize: {
|
|
50
|
+
type: Number,
|
|
51
|
+
required: true,
|
|
52
|
+
},
|
|
53
|
+
interval: {
|
|
54
|
+
type: Number,
|
|
55
|
+
required: true,
|
|
56
|
+
},
|
|
57
|
+
isRunning: {
|
|
58
|
+
type: Boolean,
|
|
59
|
+
required: true,
|
|
60
|
+
},
|
|
61
|
+
}, {
|
|
62
|
+
toJSON: {
|
|
63
|
+
transform(doc, ret) {
|
|
64
|
+
ret.id = ret._id.valueOf();
|
|
65
|
+
delete ret._id;
|
|
66
|
+
delete ret.__v;
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
TWAPSessionSchema.statics.build = (attrs) => {
|
|
71
|
+
return new TWAPSession(attrs);
|
|
72
|
+
};
|
|
73
|
+
const TWAPSession = mongoose.model("TWAPSession", TWAPSessionSchema);
|
|
74
|
+
return TWAPSession;
|
|
75
|
+
};
|
|
76
|
+
exports.buildTWAPSession = buildTWAPSession;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@riocrypto/common-server",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2483",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./build/index.js",
|
|
6
6
|
"types": "./build/index.d.ts",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"@google-cloud/secret-manager": "^5.3.0",
|
|
29
29
|
"@google-cloud/storage": "^6.9.5",
|
|
30
30
|
"@hyperdx/node-opentelemetry": "^0.7.0",
|
|
31
|
-
"@riocrypto/common": "^1.0.
|
|
31
|
+
"@riocrypto/common": "^1.0.2250",
|
|
32
32
|
"@types/express": "^4.17.13",
|
|
33
33
|
"axios": "^1.7.4",
|
|
34
34
|
"crypto-js": "^4.2.0",
|