@gearbox-protocol/sdk 10.4.5 → 10.6.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 (32) hide show
  1. package/dist/cjs/abi/310/generated.js +239 -25
  2. package/dist/cjs/dev/RevolverTransport.js +124 -83
  3. package/dist/cjs/sdk/market/MarketSuite.js +4 -0
  4. package/dist/cjs/sdk/market/credit/CreditFacadeV300Contract.js +4 -1
  5. package/dist/cjs/sdk/market/credit/CreditFacadeV310Contract.js +2 -2
  6. package/dist/cjs/sdk/market/loss-policy/AliasLossPolicyV310Contract.js +40 -0
  7. package/dist/cjs/sdk/market/loss-policy/LossPolicyContract.js +40 -0
  8. package/dist/cjs/sdk/market/loss-policy/createLossPolicy.js +48 -0
  9. package/dist/cjs/sdk/market/loss-policy/index.js +28 -0
  10. package/dist/cjs/sdk/market/loss-policy/types.js +16 -0
  11. package/dist/esm/abi/310/generated.js +238 -25
  12. package/dist/esm/dev/RevolverTransport.js +125 -83
  13. package/dist/esm/sdk/market/MarketSuite.js +6 -0
  14. package/dist/esm/sdk/market/credit/CreditFacadeV300Contract.js +4 -1
  15. package/dist/esm/sdk/market/credit/CreditFacadeV310Contract.js +2 -2
  16. package/dist/esm/sdk/market/loss-policy/AliasLossPolicyV310Contract.js +16 -0
  17. package/dist/esm/sdk/market/loss-policy/LossPolicyContract.js +16 -0
  18. package/dist/esm/sdk/market/loss-policy/createLossPolicy.js +24 -0
  19. package/dist/esm/sdk/market/loss-policy/index.js +4 -0
  20. package/dist/esm/sdk/market/loss-policy/types.js +0 -0
  21. package/dist/types/abi/310/generated.d.ts +292 -22
  22. package/dist/types/dev/RevolverTransport.d.ts +14 -6
  23. package/dist/types/sdk/market/MarketSuite.d.ts +2 -0
  24. package/dist/types/sdk/market/credit/CreditFacadeV300Contract.d.ts +2 -2
  25. package/dist/types/sdk/market/credit/CreditFacadeV310Contract.d.ts +2 -2
  26. package/dist/types/sdk/market/loss-policy/AliasLossPolicyV310Contract.d.ts +277 -0
  27. package/dist/types/sdk/market/loss-policy/LossPolicyContract.d.ts +133 -0
  28. package/dist/types/sdk/market/loss-policy/createLossPolicy.d.ts +16 -0
  29. package/dist/types/sdk/market/loss-policy/index.d.ts +4 -0
  30. package/dist/types/sdk/market/loss-policy/types.d.ts +5 -0
  31. package/dist/types/sdk/types/state-human.d.ts +1 -0
  32. package/package.json +1 -1
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  BaseError,
3
+ CallExecutionError,
3
4
  HttpRequestError,
4
5
  http,
5
6
  InvalidInputRpcError,
@@ -16,11 +17,11 @@ class NoAvailableTransportsError extends BaseError {
16
17
  }
17
18
  }
18
19
  class RevolverTransport {
19
- #transports;
20
- #index = 0;
21
20
  #config;
22
- #rotating = false;
23
21
  #requests = /* @__PURE__ */ new WeakMap();
22
+ #selector;
23
+ #rotating = false;
24
+ #isSingle;
24
25
  overrides;
25
26
  /**
26
27
  * Create a new RevolverTransport
@@ -44,9 +45,9 @@ class RevolverTransport {
44
45
  ...config,
45
46
  shouldRetry: config.shouldRetry ?? defaultShouldRetry
46
47
  };
47
- this.#transports = config.providers.map(
48
+ const transports = config.providers.map(
48
49
  ({ url, name, cooldown }) => ({
49
- provider: name,
50
+ name,
50
51
  transport: http(url, {
51
52
  retryCount: config.retryCount,
52
53
  retryDelay: config.retryDelay,
@@ -60,40 +61,45 @@ class RevolverTransport {
60
61
  cooldown: cooldown ?? 0
61
62
  })
62
63
  );
63
- if (this.#transports.length === 0) {
64
+ if (transports.length === 0) {
64
65
  throw new NoAvailableTransportsError();
65
66
  }
67
+ this.#isSingle = transports.length === 1;
68
+ const selectionStrategy = config.selectionStrategy ?? "simple";
69
+ this.#selector = selectionStrategy === "simple" ? new SimpleTransportSelector(transports, config.cooldown) : new OrderedTransportSelector(transports, config.cooldown);
66
70
  }
67
71
  get value() {
68
72
  return {
69
73
  rotate: (reason) => this.rotate(reason),
70
- currentTransportName: () => this.currentTransportName(),
71
- statuses: () => this.statuses()
74
+ currentTransportName: () => this.#selector.transportName(),
75
+ statuses: () => this.#selector.statuses()
72
76
  };
73
77
  }
74
78
  request = async (r) => {
75
- if (this.#transports.length === 1) {
76
- return this.#transport({ ...this.overrides }).request(r);
79
+ if (this.#isSingle) {
80
+ return this.#selector.select()({
81
+ ...this.overrides
82
+ }).request(r);
77
83
  }
78
84
  let error;
79
85
  do {
80
86
  try {
81
- this.#requests.set(r, this.currentTransportName());
82
- const resp = await withRetry(
83
- () => this.#transport({ ...this.overrides }).request(r),
84
- {
85
- delay: this.#config.retryDelay,
86
- retryCount: this.#config.retryCount,
87
- shouldRetry: this.#config.shouldRetry
88
- }
89
- );
87
+ this.#requests.set(r, this.#selector.transportName());
88
+ const transport = this.#selector.select()({
89
+ ...this.overrides
90
+ });
91
+ const resp = await withRetry(() => transport.request(r), {
92
+ delay: this.#config.retryDelay,
93
+ retryCount: this.#config.retryCount,
94
+ shouldRetry: this.#config.shouldRetry
95
+ });
90
96
  this.#requests.delete(r);
91
97
  return resp;
92
98
  } catch (e) {
93
99
  error = error ?? e;
94
100
  if (e instanceof RpcError || e instanceof HttpRequestError) {
95
101
  const reqTransport = this.#requests.get(r);
96
- if (reqTransport === this.currentTransportName()) {
102
+ if (reqTransport === this.#selector.transportName()) {
97
103
  await this.rotate(e);
98
104
  } else {
99
105
  this.#logger?.debug(
@@ -105,7 +111,7 @@ class RevolverTransport {
105
111
  throw e;
106
112
  }
107
113
  }
108
- } while (this.#hasAvailableTransports);
114
+ } while (this.#selector.canRotate());
109
115
  this.#requests.delete(r);
110
116
  throw new NoAvailableTransportsError(error);
111
117
  };
@@ -127,82 +133,34 @@ class RevolverTransport {
127
133
  * @returns true if rotation was successful
128
134
  */
129
135
  async rotate(reason) {
130
- if (this.#transports.length === 1) {
131
- return true;
132
- }
133
136
  if (this.#rotating) {
134
137
  this.#logger?.debug("already rotating, skipping");
135
- return false;
138
+ return;
136
139
  }
137
140
  this.#rotating = true;
138
- this.#logger?.debug(
139
- {
140
- reason,
141
- current: this.currentTransportName,
142
- total: this.#transports.length
143
- },
144
- "rotating transport"
145
- );
146
- const oldTransportName = this.currentTransportName();
147
- const now = Date.now();
148
- this.#transports[this.#index].cooldown = now + (this.#config.cooldown ?? 6e4);
149
- for (let i = 0; i < this.#transports.length - 1; i++) {
150
- this.#index = (this.#index + 1) % this.#transports.length;
151
- if (this.#transports[this.#index].cooldown < now) {
152
- this.#logger?.info(
153
- {
154
- current: this.currentTransportName,
155
- total: this.#transports.length
156
- },
157
- "switched to next transport"
158
- );
141
+ const from = this.#selector.transportName();
142
+ const success = this.#selector.rotate();
143
+ const to = this.#selector.transportName();
144
+ if (success) {
145
+ if (from !== to) {
146
+ this.#logger?.debug({ from, to, reason }, "transport rotated");
159
147
  try {
160
- await this.#config.onRotateSuccess?.(
161
- oldTransportName,
162
- this.currentTransportName(),
163
- reason
164
- );
148
+ await this.#config.onRotateSuccess?.(from, to, reason);
165
149
  } catch {
166
150
  }
167
- this.#rotating = false;
168
- return true;
169
- } else {
170
- this.#logger?.warn(
171
- {
172
- current: this.currentTransportName,
173
- total: this.#transports.length
174
- },
175
- "transport is still on cooldown"
176
- );
177
151
  }
178
- }
179
- try {
180
- await this.#config.onRotateFailed?.(oldTransportName, reason);
181
- } catch {
152
+ } else {
153
+ this.#logger?.warn({ from, reason }, "transport rotation failed");
154
+ try {
155
+ await this.#config.onRotateFailed?.(from, reason);
156
+ } catch {
157
+ }
182
158
  }
183
159
  this.#rotating = false;
184
- return false;
185
- }
186
- currentTransportName() {
187
- return this.#transport({}).config.name;
188
- }
189
- statuses() {
190
- const now = Date.now();
191
- return this.#transports.map((t, i) => ({
192
- id: t.transport({}).config.name,
193
- status: t.cooldown < now ? this.#index === i ? "active" : "standby" : "cooldown"
194
- }));
195
160
  }
196
161
  get #logger() {
197
162
  return this.#config.logger;
198
163
  }
199
- get #transport() {
200
- return this.#transports[this.#index].transport;
201
- }
202
- get #hasAvailableTransports() {
203
- const now = Date.now();
204
- return this.#transports.some((t) => t.cooldown < now);
205
- }
206
164
  }
207
165
  const retryCodes = /* @__PURE__ */ new Set([
208
166
  InvalidRequestRpcError.code,
@@ -214,11 +172,95 @@ const retryCodes = /* @__PURE__ */ new Set([
214
172
  const defaultShouldRetry = ({
215
173
  error
216
174
  }) => {
175
+ if (error instanceof CallExecutionError && error.details === "header not found") {
176
+ return true;
177
+ }
217
178
  if ("code" in error && typeof error.code === "number") {
218
179
  return retryCodes.has(error.code);
219
180
  }
220
181
  return false;
221
182
  };
183
+ class AbstractTransportSelector {
184
+ transports;
185
+ cooldown;
186
+ index = 0;
187
+ constructor(transports, cooldown = 6e4) {
188
+ this.transports = transports;
189
+ this.cooldown = cooldown;
190
+ }
191
+ transportName() {
192
+ return this.transports[this.index].name;
193
+ }
194
+ canRotate() {
195
+ const now = Date.now();
196
+ return this.transports.some((t) => t.cooldown < now);
197
+ }
198
+ statuses() {
199
+ const now = Date.now();
200
+ return this.transports.map((t, i) => ({
201
+ id: t.name,
202
+ status: t.cooldown < now ? this.index === i ? "active" : "standby" : "cooldown"
203
+ }));
204
+ }
205
+ }
206
+ class SimpleTransportSelector extends AbstractTransportSelector {
207
+ /**
208
+ * For simple selector, transport status is not re-evaluated on each request
209
+ * @returns
210
+ */
211
+ select() {
212
+ return this.transports[this.index].transport;
213
+ }
214
+ /**
215
+ * Simply selects next transport that is not in cooldown by checking all transports in cyclic order
216
+ * @returns true if rotation was successful
217
+ */
218
+ rotate() {
219
+ if (this.transports.length === 1) {
220
+ return true;
221
+ }
222
+ const now = Date.now();
223
+ this.transports[this.index].cooldown = now + this.cooldown;
224
+ for (let i = 0; i < this.transports.length - 1; i++) {
225
+ this.index = (this.index + 1) % this.transports.length;
226
+ if (this.transports[this.index].cooldown < now) {
227
+ return true;
228
+ }
229
+ }
230
+ return false;
231
+ }
232
+ }
233
+ class OrderedTransportSelector extends AbstractTransportSelector {
234
+ /**
235
+ * Will select first transport that is not in cooldown
236
+ * @returns
237
+ */
238
+ select() {
239
+ this.#updateIndex(Date.now());
240
+ return this.transports[this.index].transport;
241
+ }
242
+ /**
243
+ * Will put current transport into cooldown and select first available transport that is not in cooldown
244
+ * @returns true if rotation was successful
245
+ */
246
+ rotate() {
247
+ if (this.transports.length === 1) {
248
+ return true;
249
+ }
250
+ const now = Date.now();
251
+ this.transports[this.index].cooldown = now + this.cooldown;
252
+ return this.#updateIndex(now);
253
+ }
254
+ #updateIndex(now) {
255
+ for (let i = 0; i < this.transports.length; i++) {
256
+ if (this.transports[i].cooldown < now) {
257
+ this.index = i;
258
+ return true;
259
+ }
260
+ }
261
+ return false;
262
+ }
263
+ }
222
264
  export {
223
265
  NoAvailableTransportsError,
224
266
  RevolverTransport
@@ -1,5 +1,8 @@
1
1
  import { SDKConstruct } from "../base/index.js";
2
2
  import { CreditSuite } from "./credit/index.js";
3
+ import {
4
+ createLossPolicy
5
+ } from "./loss-policy/index.js";
3
6
  import { MarketConfiguratorContract } from "./MarketConfiguratorContract.js";
4
7
  import { getOrCreatePriceOracle } from "./oracle/index.js";
5
8
  import { PoolSuite } from "./pool/index.js";
@@ -9,6 +12,7 @@ class MarketSuite extends SDKConstruct {
9
12
  configurator;
10
13
  pool;
11
14
  priceOracle;
15
+ lossPolicy;
12
16
  creditManagers = [];
13
17
  /**
14
18
  * Original data received from compressor
@@ -35,6 +39,7 @@ class MarketSuite extends SDKConstruct {
35
39
  this.creditManagers.push(new CreditSuite(sdk, marketData, i));
36
40
  }
37
41
  this.priceOracle = getOrCreatePriceOracle(sdk, marketData.priceOracle);
42
+ this.lossPolicy = createLossPolicy(sdk, marketData.lossPolicy);
38
43
  }
39
44
  get dirty() {
40
45
  return this.configurator.dirty || this.pool.dirty || this.priceOracle.dirty || this.creditManagers.some((cm) => cm.dirty);
@@ -54,6 +59,7 @@ class MarketSuite extends SDKConstruct {
54
59
  pool: this.pool.stateHuman(raw),
55
60
  creditManagers: this.creditManagers.map((cm) => cm.stateHuman(raw)),
56
61
  priceOracle: this.priceOracle.stateHuman(raw),
62
+ lossPolicy: this.lossPolicy.stateHuman(raw),
57
63
  pausableAdmins: this.state.pausableAdmins.map((a) => this.labelAddress(a)),
58
64
  unpausableAdmins: this.state.unpausableAdmins.map(
59
65
  (a) => this.labelAddress(a)
@@ -61,7 +61,10 @@ class CreditFacadeV300Contract extends BaseContract {
61
61
  break;
62
62
  }
63
63
  }
64
- liquidateCreditAccount(ca, to, calls) {
64
+ liquidateCreditAccount(ca, to, calls, lossPolicyData) {
65
+ if (lossPolicyData) {
66
+ this.logger?.warn("loss policy data is not supported");
67
+ }
65
68
  return this.createRawTx({
66
69
  functionName: "liquidateCreditAccount",
67
70
  args: [ca, to, calls]
@@ -61,10 +61,10 @@ class CreditFacadeV310Contract extends BaseContract {
61
61
  break;
62
62
  }
63
63
  }
64
- liquidateCreditAccount(ca, to, calls) {
64
+ liquidateCreditAccount(ca, to, calls, lossPolicyData) {
65
65
  return this.createRawTx({
66
66
  functionName: "liquidateCreditAccount",
67
- args: [ca, to, calls]
67
+ args: lossPolicyData ? [ca, to, calls, lossPolicyData] : [ca, to, calls]
68
68
  });
69
69
  }
70
70
  closeCreditAccount(ca, calls) {
@@ -0,0 +1,16 @@
1
+ import { iAliasedLossPolicyV310Abi } from "../../../abi/310/generated.js";
2
+ import { BaseContract } from "../../base/index.js";
3
+ const abi = iAliasedLossPolicyV310Abi;
4
+ class AliasLossPolicyV310Contract extends BaseContract {
5
+ constructor(sdk, params) {
6
+ super(sdk, {
7
+ abi,
8
+ addr: params.addr,
9
+ contractType: params.contractType,
10
+ version: params.version
11
+ });
12
+ }
13
+ }
14
+ export {
15
+ AliasLossPolicyV310Contract
16
+ };
@@ -0,0 +1,16 @@
1
+ import { iLossPolicyV310Abi } from "../../../abi/310/generated.js";
2
+ import { BaseContract } from "../../base/index.js";
3
+ const abi = iLossPolicyV310Abi;
4
+ class LossPolicyContract extends BaseContract {
5
+ constructor(sdk, params) {
6
+ super(sdk, {
7
+ abi,
8
+ addr: params.addr,
9
+ contractType: params.contractType,
10
+ version: params.version
11
+ });
12
+ }
13
+ }
14
+ export {
15
+ LossPolicyContract
16
+ };
@@ -0,0 +1,24 @@
1
+ import { bytes32ToString } from "../../index.js";
2
+ import { AliasLossPolicyV310Contract } from "./AliasLossPolicyV310Contract.js";
3
+ import { LossPolicyContract } from "./LossPolicyContract.js";
4
+ function createLossPolicy(sdk, { baseParams }) {
5
+ const existing = sdk.contracts.get(baseParams.addr);
6
+ if (existing) {
7
+ return existing;
8
+ }
9
+ const contractType = bytes32ToString(baseParams.contractType);
10
+ switch (contractType) {
11
+ case "LOSS_POLICY::ALIASED":
12
+ return new AliasLossPolicyV310Contract(sdk, baseParams);
13
+ case "LOSS_POLICY::DEFAULT":
14
+ return new LossPolicyContract(sdk, baseParams);
15
+ default:
16
+ if (sdk.strictContractTypes) {
17
+ throw new Error(`unsupported loss policy type ${contractType}`);
18
+ }
19
+ return new LossPolicyContract(sdk, baseParams);
20
+ }
21
+ }
22
+ export {
23
+ createLossPolicy
24
+ };
@@ -0,0 +1,4 @@
1
+ export * from "./AliasLossPolicyV310Contract.js";
2
+ export * from "./createLossPolicy.js";
3
+ export * from "./LossPolicyContract.js";
4
+ export * from "./types.js";
File without changes