@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.
@@ -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 it from Secret Manager
12
- * Once fetched, the secret will be cached and automatically refreshed every 15 seconds
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
- * Fetch a secret value directly from Secret Manager without using the cache
16
+ * Refresh the entire secret cache by fetching the complete secret file
17
17
  */
18
- private fetchSecretValue;
18
+ private refreshSecretCache;
19
19
  /**
20
- * Set up cache entry with polling for a secret
20
+ * Set up cache with polling for the entire secret file
21
21
  */
22
22
  private setupCacheWithPolling;
23
23
  /**
24
- * Clear the cache for a specific secret or all secrets
24
+ * Clear the entire secret cache
25
25
  */
26
- clearCache(secretId?: string): void;
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 = new Map();
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 it from Secret Manager
60
- * Once fetched, the secret will be cached and automatically refreshed every 15 seconds
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 the secret is already in the cache
65
- const cachedSecret = this.secretCache.get(secretId);
66
- if (cachedSecret) {
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 it and set up polling
70
- const value = yield this.fetchSecretValue(secretId);
71
- if (value) {
72
- this.setupCacheWithPolling(secretId, value);
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
- return value;
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
- * Fetch a secret value directly from Secret Manager without using the cache
83
+ * Refresh the entire secret cache by fetching the complete secret file
79
84
  */
80
- fetchSecretValue(secretId) {
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
- return secrets[secretId];
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 ${secretId}:`, err);
121
- return null;
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 ${secretId} after ${maxRetries} attempts.`);
126
- return null;
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 entry with polling for a secret
142
+ * Set up cache with polling for the entire secret file
131
143
  */
132
- setupCacheWithPolling(secretId, initialValue) {
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 value without polling
136
- this.secretCache.set(secretId, {
137
- value: initialValue,
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 the secret
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 newValue = yield this.fetchSecretValue(secretId);
146
- if (newValue) {
147
- const currentCached = this.secretCache.get(secretId);
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(`Error polling secret ${secretId}:`, error);
164
+ console.error("Error polling secrets:", error);
160
165
  }
161
166
  }), this.POLL_INTERVAL_MS);
162
- // Store the initial value and polling interval
163
- this.secretCache.set(secretId, {
164
- value: initialValue,
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 cache for a specific secret or all secrets
175
+ * Clear the entire secret cache
170
176
  */
171
- clearCache(secretId) {
172
- if (secretId) {
173
- const cached = this.secretCache.get(secretId);
174
- if (cached && cached.pollingInterval) {
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;
@@ -66,6 +66,9 @@ const buildRioSettings = (mongoose) => {
66
66
  holidays: {
67
67
  type: Object,
68
68
  },
69
+ defaultTWAPSettings: {
70
+ type: Object,
71
+ },
69
72
  }, {
70
73
  toJSON: {
71
74
  transform(doc, ret) {
@@ -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.2480",
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.2249",
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",