@augustdigital/sdk 4.27.4-alpha.0 → 5.1.0

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.
Files changed (171) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +58 -0
  3. package/lib/core/analytics/sanitize.d.ts +3 -0
  4. package/lib/core/analytics/sanitize.js +74 -0
  5. package/lib/core/analytics/sentry.d.ts +1 -1
  6. package/lib/core/analytics/sentry.js +4 -1
  7. package/lib/core/auth/verify.js +9 -4
  8. package/lib/core/base.class.d.ts +5 -1
  9. package/lib/core/base.class.js +19 -2
  10. package/lib/core/errors/index.d.ts +40 -0
  11. package/lib/core/errors/index.js +103 -0
  12. package/lib/core/fetcher.d.ts +2 -0
  13. package/lib/core/fetcher.js +149 -41
  14. package/lib/core/helpers/web3.d.ts +3 -3
  15. package/lib/core/helpers/web3.js +43 -11
  16. package/lib/core/index.d.ts +2 -0
  17. package/lib/core/index.js +2 -0
  18. package/lib/core/logger/index.d.ts +10 -0
  19. package/lib/core/logger/index.js +37 -4
  20. package/lib/core/logger/slack.js +6 -2
  21. package/lib/core/version-check.d.ts +6 -0
  22. package/lib/core/version-check.js +101 -0
  23. package/lib/index.d.ts +1 -0
  24. package/lib/index.js +1 -7
  25. package/lib/main.d.ts +7 -2
  26. package/lib/main.js +5 -2
  27. package/lib/modules/vaults/getters.d.ts +5 -1
  28. package/lib/modules/vaults/getters.js +28 -20
  29. package/lib/modules/vaults/main.d.ts +7 -1
  30. package/lib/modules/vaults/main.js +30 -1
  31. package/lib/polyfills.d.ts +1 -0
  32. package/lib/polyfills.js +10 -0
  33. package/package.json +27 -18
  34. package/lib/abis/AddressResolver.js.map +0 -1
  35. package/lib/abis/ChainlinkV3.js.map +0 -1
  36. package/lib/abis/ERC20.js.map +0 -1
  37. package/lib/abis/ERC20_Bytes32.js.map +0 -1
  38. package/lib/abis/ERC4626.js.map +0 -1
  39. package/lib/abis/ERC721.js.map +0 -1
  40. package/lib/abis/FeeOracle.js.map +0 -1
  41. package/lib/abis/LendingPool.js.map +0 -1
  42. package/lib/abis/LendingPoolV2.js.map +0 -1
  43. package/lib/abis/LendingPoolV3.js.map +0 -1
  44. package/lib/abis/Loan.js.map +0 -1
  45. package/lib/abis/MultiAssetNativeDepositWrapper.js.map +0 -1
  46. package/lib/abis/Multicall3.js.map +0 -1
  47. package/lib/abis/OFT.js.map +0 -1
  48. package/lib/abis/PoolAdapter.js.map +0 -1
  49. package/lib/abis/RewardDistributor.js.map +0 -1
  50. package/lib/abis/RwaRedeemSubaccount.js.map +0 -1
  51. package/lib/abis/SmartAccount.js.map +0 -1
  52. package/lib/abis/TextResolver.js.map +0 -1
  53. package/lib/abis/TokenizedVaultV2.js.map +0 -1
  54. package/lib/abis/TokenizedVaultV2DepositWithPermit.js.map +0 -1
  55. package/lib/abis/TokenizedVaultV2Receipt.js.map +0 -1
  56. package/lib/abis/TokenizedVaultV2SenderAllocationWhitelist.js.map +0 -1
  57. package/lib/abis/TokenizedVaultV2WhitelistedAllocation.js.map +0 -1
  58. package/lib/abis/TokenizedVaultV2WhitelistedAssets.js.map +0 -1
  59. package/lib/abis/UniversalResolverResolve.js.map +0 -1
  60. package/lib/abis/UniversalSignatureValidator.js.map +0 -1
  61. package/lib/abis/WrapperAdapter.js.map +0 -1
  62. package/lib/abis/index.js.map +0 -1
  63. package/lib/adapters/evm/getters.js.map +0 -1
  64. package/lib/adapters/evm/index.js.map +0 -1
  65. package/lib/adapters/evm/utils.js.map +0 -1
  66. package/lib/adapters/solana/constants.js.map +0 -1
  67. package/lib/adapters/solana/getters.js.map +0 -1
  68. package/lib/adapters/solana/idl/vault-idl.js.map +0 -1
  69. package/lib/adapters/solana/index.js.map +0 -1
  70. package/lib/adapters/solana/types.js.map +0 -1
  71. package/lib/adapters/solana/utils.js.map +0 -1
  72. package/lib/adapters/solana/vault.actions.js.map +0 -1
  73. package/lib/adapters/stellar/actions.js.map +0 -1
  74. package/lib/adapters/stellar/constants.js.map +0 -1
  75. package/lib/adapters/stellar/getters.js.map +0 -1
  76. package/lib/adapters/stellar/index.js.map +0 -1
  77. package/lib/adapters/stellar/soroban.js.map +0 -1
  78. package/lib/adapters/stellar/submit.js.map +0 -1
  79. package/lib/adapters/stellar/types.js.map +0 -1
  80. package/lib/adapters/stellar/utils.js.map +0 -1
  81. package/lib/adapters/sui/constants.js.map +0 -1
  82. package/lib/adapters/sui/getters.js.map +0 -1
  83. package/lib/adapters/sui/index.js.map +0 -1
  84. package/lib/adapters/sui/transformer.js.map +0 -1
  85. package/lib/adapters/sui/types.js.map +0 -1
  86. package/lib/adapters/sui/utils.js.map +0 -1
  87. package/lib/core/analytics/constants.js.map +0 -1
  88. package/lib/core/analytics/index.js.map +0 -1
  89. package/lib/core/analytics/instrumentation.js.map +0 -1
  90. package/lib/core/analytics/metrics.js.map +0 -1
  91. package/lib/core/analytics/sanitize.js.map +0 -1
  92. package/lib/core/analytics/sentry.js.map +0 -1
  93. package/lib/core/analytics/types.js.map +0 -1
  94. package/lib/core/analytics/user-identity.js.map +0 -1
  95. package/lib/core/auth/index.js.map +0 -1
  96. package/lib/core/auth/verify.js.map +0 -1
  97. package/lib/core/base.class.js.map +0 -1
  98. package/lib/core/cache.d.ts +0 -25
  99. package/lib/core/cache.js +0 -53
  100. package/lib/core/cache.js.map +0 -1
  101. package/lib/core/constants/adapters.js.map +0 -1
  102. package/lib/core/constants/core.js.map +0 -1
  103. package/lib/core/constants/vaults.js.map +0 -1
  104. package/lib/core/constants/web3.js.map +0 -1
  105. package/lib/core/fetcher.js.map +0 -1
  106. package/lib/core/helpers/adapters.js.map +0 -1
  107. package/lib/core/helpers/core.js.map +0 -1
  108. package/lib/core/helpers/signer.js.map +0 -1
  109. package/lib/core/helpers/vaults.js.map +0 -1
  110. package/lib/core/helpers/web3.js.map +0 -1
  111. package/lib/core/index.js.map +0 -1
  112. package/lib/core/logger/index.js.map +0 -1
  113. package/lib/core/logger/slack.js.map +0 -1
  114. package/lib/evm/index.js.map +0 -1
  115. package/lib/evm/methods/crossChainVault.js.map +0 -1
  116. package/lib/evm/methods/index.js.map +0 -1
  117. package/lib/evm/types/crossChain.js.map +0 -1
  118. package/lib/evm/types/index.js.map +0 -1
  119. package/lib/index.js.map +0 -1
  120. package/lib/main.js.map +0 -1
  121. package/lib/modules/sub-accounts/fetcher.js.map +0 -1
  122. package/lib/modules/sub-accounts/index.js.map +0 -1
  123. package/lib/modules/sub-accounts/main.js.map +0 -1
  124. package/lib/modules/sub-accounts/utils.js.map +0 -1
  125. package/lib/modules/vaults/adapter.helpers.js.map +0 -1
  126. package/lib/modules/vaults/fetcher.js.map +0 -1
  127. package/lib/modules/vaults/getters.js.map +0 -1
  128. package/lib/modules/vaults/index.js.map +0 -1
  129. package/lib/modules/vaults/main.js.map +0 -1
  130. package/lib/modules/vaults/read.actions.js.map +0 -1
  131. package/lib/modules/vaults/types.js.map +0 -1
  132. package/lib/modules/vaults/utils/call-data-decoder.js.map +0 -1
  133. package/lib/modules/vaults/utils/callDataDecoder.d.ts +0 -14
  134. package/lib/modules/vaults/utils/callDataDecoder.js +0 -138
  135. package/lib/modules/vaults/utils/callDataDecoder.js.map +0 -1
  136. package/lib/modules/vaults/utils/date-utils.js.map +0 -1
  137. package/lib/modules/vaults/utils/dateUtils.d.ts +0 -11
  138. package/lib/modules/vaults/utils/dateUtils.js +0 -39
  139. package/lib/modules/vaults/utils/dateUtils.js.map +0 -1
  140. package/lib/modules/vaults/utils/index.d.ts +0 -2
  141. package/lib/modules/vaults/utils/index.js +0 -19
  142. package/lib/modules/vaults/utils/index.js.map +0 -1
  143. package/lib/modules/vaults/utils.js.map +0 -1
  144. package/lib/modules/vaults/write.actions.js.map +0 -1
  145. package/lib/services/coingecko/fetcher.js.map +0 -1
  146. package/lib/services/coingecko/index.js.map +0 -1
  147. package/lib/services/coingecko/utils.js.map +0 -1
  148. package/lib/services/debank/fetcher.js.map +0 -1
  149. package/lib/services/debank/index.js.map +0 -1
  150. package/lib/services/debank/utils.js.map +0 -1
  151. package/lib/services/layerzero/deposits.js.map +0 -1
  152. package/lib/services/layerzero/redeems.js.map +0 -1
  153. package/lib/services/layerzero/utils.js.map +0 -1
  154. package/lib/services/octavfi/fetcher.js.map +0 -1
  155. package/lib/services/octavfi/index.js.map +0 -1
  156. package/lib/services/octavfi/types.js.map +0 -1
  157. package/lib/services/octavfi/utils.js.map +0 -1
  158. package/lib/services/subgraph/fetcher.js.map +0 -1
  159. package/lib/services/subgraph/index.js.map +0 -1
  160. package/lib/services/subgraph/vaults.js.map +0 -1
  161. package/lib/types/index.js.map +0 -1
  162. package/lib/types/points.js.map +0 -1
  163. package/lib/types/pools.js.map +0 -1
  164. package/lib/types/staking.js.map +0 -1
  165. package/lib/types/sub-accounts.js.map +0 -1
  166. package/lib/types/subgraph.js.map +0 -1
  167. package/lib/types/typed-contract.js.map +0 -1
  168. package/lib/types/user.js.map +0 -1
  169. package/lib/types/vaults.js.map +0 -1
  170. package/lib/types/web3.js.map +0 -1
  171. package/lib/types/webserver.js.map +0 -1
@@ -26,6 +26,71 @@ const web3_1 = require("./helpers/web3");
26
26
  const core_2 = require("./constants/core");
27
27
  const vaults_1 = require("./helpers/vaults");
28
28
  const analytics_1 = require("./analytics");
29
+ const sanitize_1 = require("./analytics/sanitize");
30
+ const errors_1 = require("./errors");
31
+ function errorFromResponseStatus(status, message, options) {
32
+ if (status === 401) {
33
+ return new errors_1.AugustAuthError('AUTH_UNAUTHORIZED', message, options);
34
+ }
35
+ if (status === 403) {
36
+ return new errors_1.AugustAuthError('AUTH_FORBIDDEN', message, options);
37
+ }
38
+ if (status === 429) {
39
+ return new errors_1.AugustRateLimitError(message, options);
40
+ }
41
+ return new errors_1.AugustServerError(status, message, options);
42
+ }
43
+ function buildRequestAbortSignal(options) {
44
+ const timeoutMs = options?.timeoutMs ?? core_2.REQUEST_TIMEOUT_MS;
45
+ const timeoutController = new AbortController();
46
+ let didTimeout = false;
47
+ const timeoutId = setTimeout(() => {
48
+ didTimeout = true;
49
+ timeoutController.abort();
50
+ }, timeoutMs);
51
+ let signal = timeoutController.signal;
52
+ let relayCleanup = () => { };
53
+ if (options?.signal) {
54
+ if (typeof AbortSignal.any === 'function') {
55
+ signal = AbortSignal.any([timeoutController.signal, options.signal]);
56
+ }
57
+ else if (options.signal.aborted) {
58
+ timeoutController.abort();
59
+ }
60
+ else {
61
+ const relay = () => timeoutController.abort();
62
+ options.signal.addEventListener('abort', relay, { once: true });
63
+ relayCleanup = () => options.signal.removeEventListener('abort', relay);
64
+ }
65
+ }
66
+ return {
67
+ signal,
68
+ timeoutId,
69
+ timeoutMs,
70
+ timedOut: () => didTimeout,
71
+ cleanup: () => {
72
+ clearTimeout(timeoutId);
73
+ relayCleanup();
74
+ },
75
+ };
76
+ }
77
+ let _overrideDeprecationWarned = false;
78
+ function warnOverrideDeprecation(callerTag) {
79
+ if (_overrideDeprecationWarned)
80
+ return;
81
+ _overrideDeprecationWarned = true;
82
+ console.warn(`[@augustdigital/sdk] ${callerTag}: option "override" is deprecated and will be removed in a future major version. Pass a valid apiKey instead.`);
83
+ }
84
+ function readResponseHeader(headers, name) {
85
+ if (!headers)
86
+ return undefined;
87
+ const h = headers;
88
+ if (typeof h.get === 'function') {
89
+ return h.get(name) ?? undefined;
90
+ }
91
+ const v = headers[name];
92
+ return typeof v === 'string' ? v : undefined;
93
+ }
29
94
  exports.CACHE = new lru_cache_1.LRUCache({
30
95
  max: 1000,
31
96
  ttl: 1000 * 60 * 60 * 24,
@@ -57,52 +122,85 @@ const PRICE_ERROR_CACHE = new lru_cache_1.LRUCache({
57
122
  allowStale: false,
58
123
  });
59
124
  const PRICE_REQUESTS = new Map();
125
+ function buildAugustUrl(server, relativeUrl) {
126
+ const serverKey = server;
127
+ const base = core_2.WEBSERVER_URL[serverKey];
128
+ if (!base) {
129
+ throw new errors_1.AugustValidationError('INVALID_URL', `Unknown August server "${String(server)}". Expected one of: ${Object.keys(core_2.WEBSERVER_URL).join(', ')}`);
130
+ }
131
+ if (typeof relativeUrl !== 'string' || relativeUrl.length === 0) {
132
+ throw new errors_1.AugustValidationError('INVALID_URL', 'relativeUrl must be a non-empty string');
133
+ }
134
+ if (/^\s*[a-z][a-z0-9+.-]*:|^\s*\/\//i.test(relativeUrl)) {
135
+ throw new errors_1.AugustValidationError('INVALID_URL', `relativeUrl must be a path, not an absolute or protocol-relative URL`);
136
+ }
137
+ const candidate = `${base}${relativeUrl}`;
138
+ let url;
139
+ try {
140
+ url = new URL(candidate);
141
+ }
142
+ catch {
143
+ throw new errors_1.AugustValidationError('INVALID_URL', `Invalid URL path: ${(0, sanitize_1.sanitizeString)(relativeUrl)}`);
144
+ }
145
+ const baseOrigin = new URL(base).origin;
146
+ if (url.origin !== baseOrigin) {
147
+ throw new errors_1.AugustValidationError('INVALID_URL', `URL origin mismatch: refusing to fetch ${url.origin} from a "${serverKey}" request scoped to ${baseOrigin}`);
148
+ }
149
+ return url.toString();
150
+ }
60
151
  async function fetchAugustWithKey(apiKey, relativeUrl, options) {
152
+ if (options?.override) {
153
+ warnOverrideDeprecation('fetchAugustWithKey');
154
+ }
61
155
  if (!apiKey && !options?.override) {
62
- return { status: 500, statusText: 'x-api-key is undefined' };
156
+ throw new errors_1.AugustAuthError('AUTH_MISSING_KEY', 'fetchAugustWithKey: apiKey is required (set keys.august on the SDK constructor, or pass an explicit apiKey).');
63
157
  }
64
158
  const defaultHeaders = {
65
159
  'x-api-key': apiKey,
66
160
  'content-type': 'application/json',
67
161
  accept: 'application/json',
68
162
  };
69
- const controller = new AbortController();
70
- const timeoutId = setTimeout(() => controller.abort(), core_2.REQUEST_TIMEOUT_MS);
163
+ const { signal: requestSignal, timeoutMs: effectiveTimeoutMs, timedOut, cleanup, } = buildRequestAbortSignal(options);
71
164
  const startTime = performance.now();
72
165
  const server = options?.server || 'production';
73
166
  try {
74
- const res = await fetch(`${core_2.WEBSERVER_URL[server]}${relativeUrl}`, {
167
+ const safeUrl = buildAugustUrl(server, relativeUrl);
168
+ const res = await fetch(safeUrl, {
75
169
  headers: {
76
170
  ...defaultHeaders,
77
171
  ...options?.headers,
78
172
  },
79
173
  method: options?.method ?? 'GET',
80
174
  body: JSON.stringify(options?.data),
81
- signal: controller.signal,
175
+ signal: requestSignal,
82
176
  });
83
- clearTimeout(timeoutId);
177
+ cleanup();
84
178
  (0, analytics_1.trackApiCall)(relativeUrl, options?.method ?? 'GET', startTime, res.status, server);
85
- const correlationId = res.headers['x-correlation-id'];
179
+ const correlationId = readResponseHeader(res.headers, 'x-correlation-id');
86
180
  const logger = logger_1.Logger.getLogger();
87
181
  if (!res.ok || res.status !== 200) {
88
182
  if (correlationId && logger) {
89
183
  logger.setTag('correlation_id', correlationId);
90
184
  }
91
- const error = new Error(`Request failed: ${res.status}`);
185
+ const error = errorFromResponseStatus(res.status, `Request failed: ${res.status}`, { correlationId });
92
186
  logger?.captureException(error, { correlationId, status: res.status });
93
187
  throw error;
94
188
  }
95
189
  return res;
96
190
  }
97
191
  catch (error) {
98
- clearTimeout(timeoutId);
192
+ cleanup();
99
193
  (0, analytics_1.trackApiCall)(relativeUrl, options?.method ?? 'GET', startTime, 0, server);
100
- if (error.name === 'AbortError') {
101
- const timeoutError = new Error(`Request timeout after ${core_2.REQUEST_TIMEOUT_MS / 1000}s: ${relativeUrl}`);
194
+ const err = error instanceof Error ? error : new Error(String(error));
195
+ if (err.name === 'AbortError') {
196
+ if (!timedOut()) {
197
+ throw err;
198
+ }
199
+ const timeoutError = new errors_1.AugustTimeoutError((0, sanitize_1.sanitizeString)(`Request timeout after ${effectiveTimeoutMs / 1000}s: ${relativeUrl}`), effectiveTimeoutMs);
102
200
  logger_1.Logger.log.error('fetchAugustWithKey', timeoutError, { relativeUrl });
103
201
  throw timeoutError;
104
202
  }
105
- throw error;
203
+ throw err;
106
204
  }
107
205
  }
108
206
  async function fetchAugustPublic(relativeUrl, options) {
@@ -110,42 +208,46 @@ async function fetchAugustPublic(relativeUrl, options) {
110
208
  'content-type': 'application/json',
111
209
  accept: 'application/json',
112
210
  };
113
- const controller = new AbortController();
114
- const timeoutId = setTimeout(() => controller.abort(), core_2.REQUEST_TIMEOUT_MS);
211
+ const { signal: requestSignal, timeoutMs: effectiveTimeoutMs, timedOut, cleanup, } = buildRequestAbortSignal(options);
115
212
  const startTime = performance.now();
116
213
  try {
117
- const res = await fetch(`${core_2.WEBSERVER_URL['public']}${relativeUrl}`, {
214
+ const safeUrl = buildAugustUrl('public', relativeUrl);
215
+ const res = await fetch(safeUrl, {
118
216
  headers: {
119
217
  ...defaultHeaders,
120
218
  ...options?.headers,
121
219
  },
122
220
  method: options?.method ?? 'GET',
123
221
  body: JSON.stringify(options?.data),
124
- signal: controller.signal,
222
+ signal: requestSignal,
125
223
  });
126
- clearTimeout(timeoutId);
224
+ cleanup();
127
225
  (0, analytics_1.trackApiCall)(relativeUrl, options?.method ?? 'GET', startTime, res.status, 'public');
128
- const correlationId = res.headers['x-correlation-id'];
226
+ const correlationId = readResponseHeader(res.headers, 'x-correlation-id');
129
227
  const logger = logger_1.Logger.getLogger();
130
228
  if (!res.ok || res.status !== 200) {
131
229
  if (correlationId && logger) {
132
230
  logger.setTag('correlation_id', correlationId);
133
231
  }
134
- const error = new Error(`Request failed: ${res.status}`);
232
+ const error = errorFromResponseStatus(res.status, `Request failed: ${res.status}`, { correlationId });
135
233
  logger?.captureException(error, { correlationId, status: res.status });
136
234
  throw error;
137
235
  }
138
236
  return res;
139
237
  }
140
238
  catch (error) {
141
- clearTimeout(timeoutId);
239
+ cleanup();
142
240
  (0, analytics_1.trackApiCall)(relativeUrl, options?.method ?? 'GET', startTime, 0, 'public');
143
- if (error.name === 'AbortError') {
144
- const timeoutError = new Error(`Request timeout after ${core_2.REQUEST_TIMEOUT_MS / 1000}s: ${relativeUrl}`);
241
+ const err = error instanceof Error ? error : new Error(String(error));
242
+ if (err.name === 'AbortError') {
243
+ if (!timedOut()) {
244
+ throw err;
245
+ }
246
+ const timeoutError = new errors_1.AugustTimeoutError((0, sanitize_1.sanitizeString)(`Request timeout after ${effectiveTimeoutMs / 1000}s: ${relativeUrl}`), effectiveTimeoutMs);
145
247
  logger_1.Logger.log.error('fetchAugustPublic', timeoutError, { relativeUrl });
146
248
  throw timeoutError;
147
249
  }
148
- throw error;
250
+ throw err;
149
251
  }
150
252
  }
151
253
  async function fetchAugustWithBearer(bearerToken, relativeUrl, options) {
@@ -154,43 +256,47 @@ async function fetchAugustWithBearer(bearerToken, relativeUrl, options) {
154
256
  'content-type': 'application/json',
155
257
  accept: 'application/json',
156
258
  };
157
- const controller = new AbortController();
158
- const timeoutId = setTimeout(() => controller.abort(), core_2.REQUEST_TIMEOUT_MS);
259
+ const { signal: requestSignal, timeoutMs: effectiveTimeoutMs, timedOut, cleanup, } = buildRequestAbortSignal(options);
159
260
  const startTime = performance.now();
160
261
  const server = options?.server ?? 'production';
161
262
  try {
162
- const res = await fetch(`${core_2.WEBSERVER_URL[server]}${relativeUrl}`, {
263
+ const safeUrl = buildAugustUrl(server, relativeUrl);
264
+ const res = await fetch(safeUrl, {
163
265
  headers: {
164
266
  ...defaultHeaders,
165
- ...options.headers,
267
+ ...options?.headers,
166
268
  },
167
- method: options.method,
168
- body: JSON.stringify(options.data),
169
- signal: controller.signal,
269
+ method: options?.method ?? 'GET',
270
+ body: JSON.stringify(options?.data),
271
+ signal: requestSignal,
170
272
  });
171
- clearTimeout(timeoutId);
273
+ cleanup();
172
274
  (0, analytics_1.trackApiCall)(relativeUrl, options?.method ?? 'GET', startTime, res.status, server);
173
- const correlationId = res.headers['x-correlation-id'];
275
+ const correlationId = readResponseHeader(res.headers, 'x-correlation-id');
174
276
  const logger = logger_1.Logger.getLogger();
175
277
  if (!res.ok || res.status !== 200) {
176
278
  if (correlationId && logger) {
177
279
  logger.setTag('correlation_id', correlationId);
178
280
  }
179
- const error = new Error(`Request failed: ${res.status}`);
281
+ const error = errorFromResponseStatus(res.status, `Request failed: ${res.status}`, { correlationId });
180
282
  logger?.captureException(error, { correlationId, status: res.status });
181
283
  throw error;
182
284
  }
183
285
  return res;
184
286
  }
185
287
  catch (error) {
186
- clearTimeout(timeoutId);
288
+ cleanup();
187
289
  (0, analytics_1.trackApiCall)(relativeUrl, options?.method ?? 'GET', startTime, 0, server);
188
- if (error.name === 'AbortError') {
189
- const timeoutError = new Error(`Request timeout after ${core_2.REQUEST_TIMEOUT_MS / 1000}s: ${relativeUrl}`);
290
+ const err = error instanceof Error ? error : new Error(String(error));
291
+ if (err.name === 'AbortError') {
292
+ if (!timedOut()) {
293
+ throw err;
294
+ }
295
+ const timeoutError = new errors_1.AugustTimeoutError((0, sanitize_1.sanitizeString)(`Request timeout after ${effectiveTimeoutMs / 1000}s: ${relativeUrl}`), effectiveTimeoutMs);
190
296
  logger_1.Logger.log.error('fetchAugustWithBearer', timeoutError, { relativeUrl });
191
297
  throw timeoutError;
192
298
  }
193
- throw error;
299
+ throw err;
194
300
  }
195
301
  }
196
302
  function isRetryableError(error) {
@@ -273,10 +379,11 @@ async function fetchTokenizedVaults(pool, headers, loadSubaccounts, loadSnapshot
273
379
  keyParts.push('no-snapshots');
274
380
  const key = keyParts.join('-');
275
381
  let tokenizedVaults;
276
- if (exports.CACHE.get(key)) {
277
- tokenizedVaults = exports.CACHE.get(key);
382
+ const cachedResponse = await (0, exports.getSafeCache)(key);
383
+ if (cachedResponse) {
384
+ tokenizedVaults = cachedResponse;
278
385
  }
279
- else {
386
+ if (!tokenizedVaults) {
280
387
  let endpoint = core_2.WEBSERVER_ENDPOINTS.public.tokenizedVault.list;
281
388
  const params = new URLSearchParams();
282
389
  if (loadSubaccounts === false) {
@@ -294,7 +401,8 @@ async function fetchTokenizedVaults(pool, headers, loadSubaccounts, loadSnapshot
294
401
  });
295
402
  tokenizedVaults =
296
403
  (await tokenizedVaultsResponse.json());
297
- exports.CACHE.set(key, tokenizedVaults);
404
+ const ttl = 1000 * 60 * 15;
405
+ exports.CACHE.set(key, tokenizedVaults, { ttl });
298
406
  }
299
407
  if (pool &&
300
408
  ((0, ethers_1.isAddress)(pool) ||
@@ -1,4 +1,4 @@
1
- import { ethers, Interface, InterfaceAbi } from 'ethers';
1
+ import { ethers, Interface, InterfaceAbi, JsonRpcProvider } from 'ethers';
2
2
  import type { Abi } from 'abitype';
3
3
  import type { TypedContract } from '../../types/typed-contract';
4
4
  import { IAddress, IChainId, IContractRunner, IExplorerType, IInfuraOptions } from '../../types';
@@ -11,8 +11,8 @@ export declare function createContract<const TAbi extends Abi>({ provider, addre
11
11
  provider: IContractRunner;
12
12
  abi: TAbi;
13
13
  }): TypedContract<TAbi> | undefined;
14
- export declare const createProvider: (rpcUrl: string) => any;
15
- export declare const getInfuraProvider: (infura: IInfuraOptions) => ethers.JsonRpcProvider;
14
+ export declare const createProvider: (rpcUrl: string, chainId?: number) => JsonRpcProvider;
15
+ export declare const getInfuraProvider: (infura: IInfuraOptions) => JsonRpcProvider;
16
16
  export declare const explorerLink: (hex: IAddress, chain: IChainId, type: IExplorerType) => string;
17
17
  export declare const getDecimals: (provider: IContractRunner, address: IAddress, isVault?: boolean) => Promise<any>;
18
18
  export declare const getReceiptTokenAddress: (provider: IContractRunner, address: IAddress) => Promise<any>;
@@ -80,13 +80,26 @@ function createContract({ provider, address, abi, }) {
80
80
  }
81
81
  return contract;
82
82
  }
83
- const createProvider = (rpcUrl) => {
84
- if (__1.CACHE.has(rpcUrl))
85
- return __1.CACHE.get(rpcUrl);
86
- const provider = new ethers_1.JsonRpcProvider(rpcUrl, undefined, {
87
- batchMaxCount: 10,
88
- });
89
- __1.CACHE.set(rpcUrl, provider);
83
+ const createProvider = (rpcUrl, chainId) => {
84
+ if (typeof rpcUrl !== 'string' || rpcUrl.trim().length === 0) {
85
+ const forChain = chainId ? ` for chain ${chainId}` : '';
86
+ throw new Error(`createProvider: no RPC URL provided${forChain}. ` +
87
+ 'Pass an RPC URL when constructing AugustSDK ' +
88
+ '(`new AugustSDK({ providers: { [chainId]: url } })`), ' +
89
+ `or set the AUGUST_RPC_${chainId ?? '<chainId>'} environment variable.`);
90
+ }
91
+ const cacheKey = chainId ? `${rpcUrl}|${chainId}` : rpcUrl;
92
+ if (__1.CACHE.has(cacheKey))
93
+ return __1.CACHE.get(cacheKey);
94
+ const provider = chainId
95
+ ? new ethers_1.JsonRpcProvider(rpcUrl, ethers_1.Network.from(chainId), {
96
+ staticNetwork: ethers_1.Network.from(chainId),
97
+ batchMaxCount: 10,
98
+ })
99
+ : new ethers_1.JsonRpcProvider(rpcUrl, undefined, {
100
+ batchMaxCount: 10,
101
+ });
102
+ __1.CACHE.set(cacheKey, provider);
90
103
  return provider;
91
104
  };
92
105
  exports.createProvider = createProvider;
@@ -114,7 +127,8 @@ const getInfuraProvider = (infura) => {
114
127
  break;
115
128
  }
116
129
  }
117
- return new ethers_1.JsonRpcProvider(`${baseUrl}.infura.io/v3/${infura.apiKey}`);
130
+ const url = `${baseUrl}.infura.io/v3/${infura.apiKey}`;
131
+ return (0, exports.createProvider)(url, infura.chainId);
118
132
  };
119
133
  exports.getInfuraProvider = getInfuraProvider;
120
134
  const explorerLink = (hex, chain, type) => {
@@ -123,6 +137,24 @@ const explorerLink = (hex, chain, type) => {
123
137
  return `${__1.NETWORKS[chain].explorer}/${type}/${hex}`;
124
138
  };
125
139
  exports.explorerLink = explorerLink;
140
+ function providerScope(provider) {
141
+ let chainId;
142
+ try {
143
+ const net = provider
144
+ ._network;
145
+ chainId = net?.chainId;
146
+ }
147
+ catch {
148
+ chainId = undefined;
149
+ }
150
+ if (chainId !== undefined && chainId !== null) {
151
+ return `chain:${String(chainId)}`;
152
+ }
153
+ const conn = provider._getConnection?.();
154
+ if (conn?.url)
155
+ return `url:${conn.url}`;
156
+ return 'unknown';
157
+ }
126
158
  const getDecimals = async (provider, address, isVault = true) => {
127
159
  if (address === ethers_1.ZeroAddress) {
128
160
  __1.Logger.log.info('getDecimals', 'address is zero address');
@@ -132,7 +164,7 @@ const getDecimals = async (provider, address, isVault = true) => {
132
164
  return constants_1.fallbackDecimals;
133
165
  if (!(address && provider))
134
166
  return;
135
- const key = `decimals-${address}`;
167
+ const key = `decimals-${providerScope(provider)}-${address}`;
136
168
  try {
137
169
  if (__1.CACHE.get(key))
138
170
  return __1.CACHE.get(key);
@@ -163,7 +195,7 @@ exports.getDecimals = getDecimals;
163
195
  const getReceiptTokenAddress = async (provider, address) => {
164
196
  if (!(address && provider))
165
197
  return;
166
- const key = `receipt-token-${address}`;
198
+ const key = `receipt-token-${providerScope(provider)}-${address}`;
167
199
  try {
168
200
  if (__1.CACHE.get(key))
169
201
  return __1.CACHE.get(key);
@@ -184,7 +216,7 @@ const getSymbol = async (provider, address, isVault = true) => {
184
216
  }
185
217
  if (!(address && provider))
186
218
  return;
187
- const key = `symbol-${address}`;
219
+ const key = `symbol-${providerScope(provider)}-${address}`;
188
220
  try {
189
221
  if (__1.CACHE.get(key))
190
222
  return __1.CACHE.get(key);
@@ -3,6 +3,8 @@ export * from './base.class';
3
3
  export * from './auth';
4
4
  export * from './logger';
5
5
  export * from './analytics';
6
+ export * from './version-check';
7
+ export * from './errors';
6
8
  export * from './constants/adapters';
7
9
  export * from './constants/core';
8
10
  export * from './constants/web3';
package/lib/core/index.js CHANGED
@@ -19,6 +19,8 @@ __exportStar(require("./base.class"), exports);
19
19
  __exportStar(require("./auth"), exports);
20
20
  __exportStar(require("./logger"), exports);
21
21
  __exportStar(require("./analytics"), exports);
22
+ __exportStar(require("./version-check"), exports);
23
+ __exportStar(require("./errors"), exports);
22
24
  __exportStar(require("./constants/adapters"), exports);
23
25
  __exportStar(require("./constants/core"), exports);
24
26
  __exportStar(require("./constants/web3"), exports);
@@ -2,13 +2,23 @@ export type SDKLogger = {
2
2
  setTag: (key: string, value: string) => void;
3
3
  captureException: (err: unknown, context?: Record<string, any>) => void;
4
4
  };
5
+ export interface ILogger {
6
+ debug?: (tag: string, context?: Record<string, unknown>) => void;
7
+ info?: (tag: string, context?: Record<string, unknown>) => void;
8
+ warn?: (tag: string, context?: Record<string, unknown>) => void;
9
+ error: (tag: string, error: unknown, context?: Record<string, unknown>) => void;
10
+ }
5
11
  declare function setLogger(customLogger: SDKLogger): void;
12
+ declare function setStructuredLogger(custom: ILogger | null): void;
6
13
  declare function getLogger(): SDKLogger | null;
14
+ declare function getStructuredLogger(): ILogger | null;
7
15
  declare function setDevMode(devMode: boolean): void;
8
16
  declare function isDevMode(): boolean;
9
17
  declare const Logger: {
10
18
  setLogger: typeof setLogger;
19
+ setStructuredLogger: typeof setStructuredLogger;
11
20
  getLogger: typeof getLogger;
21
+ getStructuredLogger: typeof getStructuredLogger;
12
22
  setDevMode: typeof setDevMode;
13
23
  isDevMode: typeof isDevMode;
14
24
  log: {
@@ -34,14 +34,22 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.Logger = exports.Slack = void 0;
37
+ const sanitize_1 = require("../analytics/sanitize");
37
38
  let logger = null;
39
+ let structuredLogger = null;
38
40
  let isDev = false;
39
41
  function setLogger(customLogger) {
40
42
  logger = customLogger;
41
43
  }
44
+ function setStructuredLogger(custom) {
45
+ structuredLogger = custom;
46
+ }
42
47
  function getLogger() {
43
48
  return logger;
44
49
  }
50
+ function getStructuredLogger() {
51
+ return structuredLogger;
52
+ }
45
53
  function setDevMode(devMode) {
46
54
  isDev = devMode;
47
55
  }
@@ -50,26 +58,51 @@ function isDevMode() {
50
58
  }
51
59
  const log = {
52
60
  info: (tag, ...args) => {
61
+ const safeArgs = args.map((a) => (0, sanitize_1.sanitizeForLogging)(a));
53
62
  if (isDev) {
54
- console.log(`[${tag}]`, ...args);
63
+ console.log(`[${tag}]`, ...safeArgs);
55
64
  }
65
+ structuredLogger?.info?.(tag, structuredContext(safeArgs));
56
66
  },
57
67
  warn: (tag, ...args) => {
68
+ const safeArgs = args.map((a) => (0, sanitize_1.sanitizeForLogging)(a));
58
69
  if (isDev) {
59
- console.warn(`[${tag}]`, ...args);
70
+ console.warn(`[${tag}]`, ...safeArgs);
60
71
  }
61
72
  logger?.setTag('warning', tag);
73
+ structuredLogger?.warn?.(tag, structuredContext(safeArgs));
62
74
  },
63
75
  error: (tag, error, context) => {
76
+ const safeError = (0, sanitize_1.sanitizeError)(error);
77
+ const safeContext = context
78
+ ? (0, sanitize_1.sanitizeForLogging)(context)
79
+ : undefined;
64
80
  if (isDev) {
65
- console.error(`[${tag}]`, error);
81
+ console.error(`[${tag}]`, safeError);
66
82
  }
67
- logger?.captureException(error, { tag, ...context });
83
+ logger?.captureException(safeError, { tag, ...(safeContext ?? {}) });
84
+ structuredLogger?.error(tag, safeError, safeContext);
68
85
  },
69
86
  };
87
+ function structuredContext(args) {
88
+ if (args.length === 0)
89
+ return undefined;
90
+ const [first, ...rest] = args;
91
+ if (first &&
92
+ typeof first === 'object' &&
93
+ !Array.isArray(first) &&
94
+ !(first instanceof Error)) {
95
+ return rest.length === 0
96
+ ? first
97
+ : { ...first, extras: rest };
98
+ }
99
+ return { args };
100
+ }
70
101
  const Logger = {
71
102
  setLogger,
103
+ setStructuredLogger,
72
104
  getLogger,
105
+ getStructuredLogger,
73
106
  setDevMode,
74
107
  isDevMode,
75
108
  log,
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SLACK = exports.DEFAULT_SLACK_WEBHOOK_URL = void 0;
4
4
  const core_1 = require("../helpers/core");
5
5
  const web3_1 = require("../helpers/web3");
6
+ const sanitize_1 = require("../analytics/sanitize");
6
7
  exports.DEFAULT_SLACK_WEBHOOK_URL = 'T04CM84GAV6/B0A2DS3ST8C/FLtOA3Jna3FN7UO4DoGxHfhG';
7
8
  function error(options) {
8
9
  const { title, error, poolAddress, chainId, slackWebookUrl, address } = options;
@@ -31,18 +32,21 @@ function error(options) {
31
32
  }
32
33
  (async () => {
33
34
  const webhookUrl = `https://hooks.slack.com/services/${slackWebookUrl}`;
35
+ const safeError = (0, sanitize_1.sanitizeString)(String(error));
36
+ const safeTitle = (0, sanitize_1.sanitizeString)(String(title));
34
37
  const data = {
35
- text: `*Error: ${title}*\n${new Date().toUTCString()}\n\nPool: [${(0, core_1.truncate)(poolAddress)}](${(0, web3_1.explorerLink)(poolAddress, chainId, 'address')})\n\n\nError: ${error}`,
38
+ text: `*Error: ${safeTitle}*\n${new Date().toUTCString()}\n\nPool: [${(0, core_1.truncate)(poolAddress)}](${(0, web3_1.explorerLink)(poolAddress, chainId, 'address')})\n\n\nError: ${safeError}`,
36
39
  };
37
40
  const res = await fetch(webhookUrl, {
38
41
  method: 'POST',
39
42
  body: JSON.stringify(data),
43
+ signal: AbortSignal.timeout(5000),
40
44
  });
41
45
  if (res?.status === 200)
42
46
  console.log('#Slack.error: successfully sent');
43
47
  else
44
48
  console.error('#Slack.error:', res.status, res.statusText);
45
- })().catch((e) => console.error('#Slack.error:', e));
49
+ })().catch((e) => console.error('#Slack.error:', (0, sanitize_1.sanitizeString)(String(e?.message ?? e))));
46
50
  }
47
51
  exports.SLACK = {
48
52
  error,
@@ -0,0 +1,6 @@
1
+ export declare function compareSemver(a: string, b: string): number;
2
+ export interface IVersionCheckConfig {
3
+ enabled?: boolean;
4
+ }
5
+ export declare function runVersionCheck(config?: IVersionCheckConfig): void;
6
+ export declare function _resetVersionCheckForTests(): void;