@gearbox-protocol/sdk 13.4.0 → 13.5.0-next.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.
Files changed (90) hide show
  1. package/dist/cjs/abi/310/iSecuritizeDegenNFT.js +263 -0
  2. package/dist/cjs/abi/310/iSecuritizeKYCFactory.js +278 -0
  3. package/dist/cjs/{sdk/pools/PoolServiceV310.js → abi/iStateSerializer.js} +14 -8
  4. package/dist/cjs/dev/AccountOpener.js +45 -5
  5. package/dist/cjs/sdk/accounts/AbstractCreditAccountsService.js +375 -13
  6. package/dist/cjs/sdk/accounts/CreditAccountsServiceV310.js +16 -5
  7. package/dist/cjs/sdk/base/ChainContractsRegister.js +1 -1
  8. package/dist/cjs/sdk/base/TokensMeta.js +255 -32
  9. package/dist/cjs/sdk/base/index.js +2 -0
  10. package/dist/cjs/sdk/{constants/phantom-tokens.js → base/token-types.js} +9 -3
  11. package/dist/cjs/sdk/chain/chains.js +2 -1
  12. package/dist/cjs/sdk/constants/index.js +0 -2
  13. package/dist/cjs/sdk/market/MarketRegister.js +5 -2
  14. package/dist/cjs/sdk/market/MarketSuite.js +6 -0
  15. package/dist/cjs/{plugins/zappers/extraZappers.js → sdk/market/ZapperRegister.js} +110 -6
  16. package/dist/cjs/sdk/market/index.js +3 -1
  17. package/dist/cjs/sdk/market/pool/PoolSuite.js +3 -0
  18. package/dist/cjs/sdk/market/pool/PoolV310Contract.js +17 -2
  19. package/dist/cjs/sdk/market/pool/SecuritizeKYCFactory.js +97 -0
  20. package/dist/cjs/sdk/market/pool/index.js +4 -0
  21. package/dist/cjs/sdk/pools/PoolService.js +391 -0
  22. package/dist/cjs/sdk/pools/index.js +2 -4
  23. package/dist/esm/abi/310/iSecuritizeDegenNFT.js +239 -0
  24. package/dist/esm/abi/310/iSecuritizeKYCFactory.js +254 -0
  25. package/dist/esm/abi/iStateSerializer.js +12 -0
  26. package/dist/esm/dev/AccountOpener.js +47 -6
  27. package/dist/esm/sdk/accounts/AbstractCreditAccountsService.js +375 -13
  28. package/dist/esm/sdk/accounts/CreditAccountsServiceV310.js +16 -5
  29. package/dist/esm/sdk/base/ChainContractsRegister.js +1 -1
  30. package/dist/esm/sdk/base/TokensMeta.js +261 -32
  31. package/dist/esm/sdk/base/index.js +1 -0
  32. package/dist/esm/sdk/{constants/phantom-tokens.js → base/token-types.js} +4 -0
  33. package/dist/esm/sdk/chain/chains.js +2 -1
  34. package/dist/esm/sdk/constants/index.js +0 -1
  35. package/dist/esm/sdk/market/MarketRegister.js +5 -2
  36. package/dist/esm/sdk/market/MarketSuite.js +6 -0
  37. package/dist/esm/{plugins/zappers/extraZappers.js → sdk/market/ZapperRegister.js} +109 -2
  38. package/dist/esm/sdk/market/index.js +1 -0
  39. package/dist/esm/sdk/market/pool/PoolSuite.js +3 -0
  40. package/dist/esm/sdk/market/pool/PoolV310Contract.js +17 -2
  41. package/dist/esm/sdk/market/pool/SecuritizeKYCFactory.js +73 -0
  42. package/dist/esm/sdk/market/pool/index.js +2 -0
  43. package/dist/esm/sdk/pools/PoolService.js +371 -0
  44. package/dist/esm/sdk/pools/index.js +1 -2
  45. package/dist/types/abi/310/iSecuritizeDegenNFT.d.ts +324 -0
  46. package/dist/types/abi/310/iSecuritizeKYCFactory.d.ts +322 -0
  47. package/dist/types/abi/iStateSerializer.d.ts +11 -0
  48. package/dist/types/sdk/accounts/AbstractCreditAccountsService.d.ts +114 -3
  49. package/dist/types/sdk/accounts/CreditAccountsServiceV310.d.ts +1 -1
  50. package/dist/types/sdk/accounts/types.d.ts +96 -6
  51. package/dist/types/sdk/base/TokensMeta.d.ts +34 -21
  52. package/dist/types/sdk/base/index.d.ts +1 -0
  53. package/dist/types/sdk/base/token-types.d.ts +33 -0
  54. package/dist/types/sdk/base/types.d.ts +0 -7
  55. package/dist/types/sdk/chain/chains.d.ts +1 -1
  56. package/dist/types/sdk/constants/index.d.ts +0 -1
  57. package/dist/types/sdk/market/MarketRegister.d.ts +2 -2
  58. package/dist/types/sdk/market/MarketSuite.d.ts +3 -0
  59. package/dist/types/sdk/market/ZapperRegister.d.ts +17 -0
  60. package/dist/types/sdk/market/index.d.ts +1 -0
  61. package/dist/types/sdk/market/pool/PoolSuite.d.ts +2 -0
  62. package/dist/types/sdk/market/pool/PoolV310Contract.d.ts +6 -2
  63. package/dist/types/sdk/market/pool/SecuritizeKYCFactory.d.ts +345 -0
  64. package/dist/types/sdk/market/pool/index.d.ts +2 -0
  65. package/dist/types/sdk/market/types.d.ts +10 -0
  66. package/dist/types/sdk/pools/PoolService.d.ts +14 -0
  67. package/dist/types/sdk/pools/index.d.ts +1 -2
  68. package/dist/types/sdk/pools/types.d.ts +85 -111
  69. package/package.json +1 -1
  70. package/dist/cjs/plugins/zappers/ZappersPlugin.js +0 -144
  71. package/dist/cjs/plugins/zappers/index.js +0 -26
  72. package/dist/cjs/plugins/zappers/package.json +0 -1
  73. package/dist/cjs/sdk/pools/AbstractPoolService.js +0 -143
  74. package/dist/cjs/sdk/pools/createPoolService.js +0 -35
  75. package/dist/esm/plugins/zappers/ZappersPlugin.js +0 -126
  76. package/dist/esm/plugins/zappers/index.js +0 -3
  77. package/dist/esm/plugins/zappers/package.json +0 -1
  78. package/dist/esm/sdk/pools/AbstractPoolService.js +0 -119
  79. package/dist/esm/sdk/pools/PoolServiceV310.js +0 -6
  80. package/dist/esm/sdk/pools/createPoolService.js +0 -11
  81. package/dist/types/plugins/zappers/ZappersPlugin.d.ts +0 -18
  82. package/dist/types/plugins/zappers/extraZappers.d.ts +0 -6
  83. package/dist/types/plugins/zappers/index.d.ts +0 -3
  84. package/dist/types/plugins/zappers/types.d.ts +0 -12
  85. package/dist/types/sdk/constants/phantom-tokens.d.ts +0 -2
  86. package/dist/types/sdk/pools/AbstractPoolService.d.ts +0 -21
  87. package/dist/types/sdk/pools/PoolServiceV310.d.ts +0 -4
  88. package/dist/types/sdk/pools/createPoolService.d.ts +0 -3
  89. /package/dist/cjs/{plugins/zappers → sdk/market}/types.js +0 -0
  90. /package/dist/esm/{plugins/zappers → sdk/market}/types.js +0 -0
@@ -1,3 +1,10 @@
1
+ import {
2
+ decodeAbiParameters,
3
+ erc20Abi
4
+ } from "viem";
5
+ import { iSecuritizeDegenNFTAbi } from "../../abi/310/iSecuritizeDegenNFT.js";
6
+ import { iSecuritizeKYCFactoryAbi } from "../../abi/310/iSecuritizeKYCFactory.js";
7
+ import { iStateSerializerAbi } from "../../abi/iStateSerializer.js";
1
8
  import { iVersionAbi } from "../../abi/iVersion.js";
2
9
  import {
3
10
  AddressMap,
@@ -5,19 +12,36 @@ import {
5
12
  bytes32ToString,
6
13
  formatBN
7
14
  } from "../utils/index.js";
15
+ import {
16
+ KYC_UNDERLYING_DEFAULT,
17
+ KYC_UNDERLYING_ON_DEMAND
18
+ } from "./token-types.js";
8
19
  class TokensMeta extends AddressMap {
9
20
  #client;
10
- #phantomTokensLoaded;
11
- constructor(client) {
21
+ #tokenDataLoaded = new AddressSet();
22
+ #logger;
23
+ constructor(client, logger) {
12
24
  super(void 0, "tokensMeta");
13
25
  this.#client = client;
26
+ this.#logger = logger?.child?.({ name: "TokensMeta" }) ?? logger;
14
27
  }
15
28
  /**
16
29
  * Clears all token metadata
17
30
  **/
18
31
  reset() {
19
32
  this.clear();
20
- this.#phantomTokensLoaded = void 0;
33
+ this.#tokenDataLoaded.clear();
34
+ }
35
+ upsert(address, value) {
36
+ let v = value;
37
+ const existing = this.get(address);
38
+ if (existing && v) {
39
+ v = {
40
+ ...existing,
41
+ ...v
42
+ };
43
+ }
44
+ super.upsert(address, v);
21
45
  }
22
46
  /**
23
47
  * Returns the symbol string for a token.
@@ -36,27 +60,78 @@ class TokensMeta extends AddressMap {
36
60
  return this.mustGet(token).decimals;
37
61
  }
38
62
  /**
39
- * Returns the phantom token type for a given token, or undefined for normal tokens
40
- * Throws if the phantom token data is not loaded
63
+ * Returns true if the token is a phantom token, throws if the token data is not loaded
64
+ * @param t
65
+ * @returns
66
+ */
67
+ isPhantomToken(t) {
68
+ if (!this.#tokenDataLoaded.has(t.addr)) {
69
+ throw new Error(
70
+ `extended token data not loaded for ${t.symbol} (${t.addr})`
71
+ );
72
+ }
73
+ return !!t.contractType?.startsWith("PHANTOM_TOKEN::");
74
+ }
75
+ /**
76
+ * Returns true if the token is a KYC underlying token, throws if the token data is not loaded
77
+ * @param t
78
+ * @returns
79
+ */
80
+ isKYCUnderlying(t) {
81
+ if (!this.#tokenDataLoaded.has(t.addr)) {
82
+ throw new Error(
83
+ `extended token data not loaded for ${t.symbol} (${t.addr})`
84
+ );
85
+ }
86
+ return !!t.contractType?.startsWith("KYC_UNDERLYING::");
87
+ }
88
+ /**
89
+ * Returns true if the token is a DSToken, throws if the token data is not loaded
90
+ * @param t
91
+ * @returns
41
92
  */
42
- phantomTokenType(token) {
43
- if (!this.#phantomTokensLoaded?.has(token)) {
44
- throw new Error("phantom token data not loaded");
93
+ isDSToken(t) {
94
+ if (!this.#tokenDataLoaded.has(t.addr)) {
95
+ throw new Error(
96
+ `extended token data not loaded for ${t.symbol} (${t.addr})`
97
+ );
45
98
  }
46
- return this.mustGet(token).phantomTokenType;
99
+ return !!t.isDSToken;
47
100
  }
48
101
  /**
49
102
  * Returns a map of all phantom tokens
50
- * Throws if the phantom token data is not loaded
103
+ * Throws if token data is not loaded
51
104
  */
52
105
  get phantomTokens() {
53
- if (!this.#phantomTokensLoaded) {
54
- throw new Error("phantom tokens not loaded");
106
+ const result = new AddressMap();
107
+ for (const [token, meta] of this.entries()) {
108
+ if (this.isPhantomToken(meta)) {
109
+ result.upsert(token, meta);
110
+ }
55
111
  }
56
- return new AddressMap(
57
- this.entries().filter(([_, v]) => !!v.phantomTokenType),
58
- "phantomTokens"
59
- );
112
+ return result;
113
+ }
114
+ /**
115
+ * Returns a map of all KYC underlying tokens
116
+ * Throws if token data is not loaded
117
+ */
118
+ get kycUnderlyings() {
119
+ const result = new AddressMap();
120
+ for (const [token, meta] of this.entries()) {
121
+ if (this.isKYCUnderlying(meta)) {
122
+ result.upsert(token, meta);
123
+ }
124
+ }
125
+ return result;
126
+ }
127
+ get dsTokens() {
128
+ const result = new AddressMap();
129
+ for (const [token, meta] of this.entries()) {
130
+ if (this.isDSToken(meta)) {
131
+ result.upsert(token, meta);
132
+ }
133
+ }
134
+ return result;
60
135
  }
61
136
  formatBN(arg0, arg1, arg2) {
62
137
  const token = typeof arg0 === "object" ? arg0.token : arg0;
@@ -87,30 +162,184 @@ class TokensMeta extends AddressMap {
87
162
  return meta;
88
163
  }
89
164
  /**
90
- * Loads phantom token data for all known tokens from chain
165
+ * Loads token information about phantom tokens, KYC underlying tokens and DSTokens
166
+ *
167
+ * @param tokens - tokens to load data for, defaults to all tokens
91
168
  */
92
- async loadPhantomTokens() {
93
- this.#phantomTokensLoaded = new AddressSet();
94
- const tokens = this.keys();
169
+ async loadTokenData(...tokens) {
170
+ const tokenz = new AddressSet(tokens.length > 0 ? tokens : this.keys());
171
+ const tokensToLoad = Array.from(tokenz.difference(this.#tokenDataLoaded));
172
+ if (tokensToLoad.length === 0) {
173
+ return;
174
+ }
95
175
  const resp = await this.#client.multicall({
96
- contracts: tokens.map(
97
- (t) => ({
98
- address: t,
99
- abi: iVersionAbi,
100
- functionName: "contractType"
101
- })
176
+ contracts: tokensToLoad.flatMap(
177
+ (t) => [
178
+ {
179
+ address: t,
180
+ abi: iVersionAbi,
181
+ functionName: "contractType"
182
+ },
183
+ {
184
+ address: t,
185
+ abi: iStateSerializerAbi,
186
+ functionName: "serialize"
187
+ }
188
+ ]
102
189
  ),
103
190
  allowFailure: true,
104
191
  batchSize: 0
105
192
  });
106
- for (let i = 0; i < resp.length; i++) {
107
- if (resp[i].status === "success") {
108
- const contractType = bytes32ToString(resp[i].result);
109
- if (contractType.startsWith("PHANTOM_TOKEN::")) {
110
- this.mustGet(tokens[i]).phantomTokenType = contractType;
193
+ this.#logger?.debug(`loaded ${resp.length} contract types`);
194
+ const kycFactories = new AddressSet();
195
+ for (let i = 0; i < tokensToLoad.length; i++) {
196
+ const meta = this.#overrideTokenMeta(
197
+ tokensToLoad[i],
198
+ resp[2 * i],
199
+ resp[2 * i + 1]
200
+ );
201
+ this.#tokenDataLoaded.add(tokensToLoad[i]);
202
+ if (this.isKYCUnderlying(meta)) {
203
+ kycFactories.add(meta.kycFactory);
204
+ }
205
+ }
206
+ this.#logger?.debug(`found ${kycFactories.size} KYC factories`);
207
+ await this.#loadDSTokens(kycFactories);
208
+ }
209
+ #overrideTokenMeta(token, contractTypeResp, serializeResp) {
210
+ const meta = this.mustGet(token);
211
+ if (contractTypeResp.status === "success") {
212
+ const contractType = bytes32ToString(contractTypeResp.result);
213
+ if (contractType.startsWith("KYC_UNDERLYING::")) {
214
+ if (serializeResp.status === "success") {
215
+ this.#overrideKYCUnderlying(meta, contractType, serializeResp.result);
216
+ } else {
217
+ throw new Error(
218
+ `token ${meta.symbol} (${token}) is ${contractType} but serialize failed: ${serializeResp.error}`
219
+ );
111
220
  }
221
+ } else {
222
+ this.upsert(token, {
223
+ ...meta,
224
+ contractType
225
+ });
112
226
  }
113
- this.#phantomTokensLoaded.add(tokens[i]);
227
+ this.#logger?.debug(`token ${meta.symbol} is ${contractType}`);
228
+ }
229
+ return this.mustGet(token);
230
+ }
231
+ #overrideKYCUnderlying(meta, contractType, serialized) {
232
+ if (contractType === KYC_UNDERLYING_DEFAULT) {
233
+ const decoded = decodeAbiParameters(
234
+ [
235
+ { type: "address", name: "kycFactory" },
236
+ { type: "address", name: "asset" }
237
+ ],
238
+ serialized
239
+ );
240
+ this.upsert(meta.addr, {
241
+ ...meta,
242
+ contractType,
243
+ kycFactory: decoded[0],
244
+ asset: decoded[1]
245
+ });
246
+ } else if (contractType === KYC_UNDERLYING_ON_DEMAND) {
247
+ const decoded = decodeAbiParameters(
248
+ [
249
+ { type: "address", name: "kycFactory" },
250
+ { type: "address", name: "asset" },
251
+ { type: "address", name: "pool" },
252
+ { type: "address", name: "liquidityProvider" }
253
+ ],
254
+ serialized
255
+ );
256
+ this.upsert(meta.addr, {
257
+ ...meta,
258
+ contractType,
259
+ kycFactory: decoded[0],
260
+ asset: decoded[1],
261
+ pool: decoded[2],
262
+ liquidityProvider: decoded[3]
263
+ });
264
+ }
265
+ }
266
+ async #loadDSTokens(kycFactories) {
267
+ const degenNFTs = await this.#client.multicall({
268
+ contracts: kycFactories.map((address) => {
269
+ return {
270
+ address,
271
+ abi: iSecuritizeKYCFactoryAbi,
272
+ functionName: "getDegenNFT"
273
+ };
274
+ }),
275
+ allowFailure: false,
276
+ batchSize: 0
277
+ });
278
+ const resp = await this.#client.multicall({
279
+ contracts: degenNFTs.map((address) => {
280
+ return {
281
+ address,
282
+ abi: iSecuritizeDegenNFTAbi,
283
+ functionName: "getDSTokens"
284
+ };
285
+ }),
286
+ allowFailure: false,
287
+ batchSize: 0
288
+ });
289
+ const dsToken = new AddressSet(resp.flat());
290
+ const tokensToLoad = dsToken.difference(new Set(this.keys()));
291
+ this.#logger?.debug(
292
+ `found ${dsToken.size} DSTokens in KYC factories, need to load ${tokensToLoad.size} basic metadata`
293
+ );
294
+ await this.#loadWithoutCompressor(tokensToLoad);
295
+ for (const token of dsToken) {
296
+ const meta = this.mustGet(token);
297
+ this.upsert(token, {
298
+ ...meta,
299
+ isDSToken: true
300
+ });
301
+ this.#tokenDataLoaded.add(token);
302
+ this.#logger?.debug(`token ${meta.symbol} (${token}) is a DSToken`);
303
+ }
304
+ }
305
+ async #loadWithoutCompressor(tokens_) {
306
+ if (tokens_.size === 0) {
307
+ return;
308
+ }
309
+ const tokens = Array.from(tokens_);
310
+ const resp = await this.#client.multicall({
311
+ contracts: tokens.flatMap(
312
+ (t) => [
313
+ {
314
+ address: t,
315
+ abi: erc20Abi,
316
+ functionName: "symbol"
317
+ },
318
+ {
319
+ address: t,
320
+ abi: erc20Abi,
321
+ functionName: "name"
322
+ },
323
+ {
324
+ address: t,
325
+ abi: erc20Abi,
326
+ functionName: "decimals"
327
+ }
328
+ ]
329
+ ),
330
+ allowFailure: false,
331
+ batchSize: 0
332
+ });
333
+ this.#logger?.debug(
334
+ `loaded ${resp.length} basic metadata without compressor`
335
+ );
336
+ for (let i = 0; i < tokens.length; i++) {
337
+ this.upsert(tokens[i], {
338
+ addr: tokens[i],
339
+ symbol: resp[3 * i],
340
+ name: resp[3 * i + 1],
341
+ decimals: resp[3 * i + 2]
342
+ });
114
343
  }
115
344
  }
116
345
  }
@@ -5,4 +5,5 @@ export * from "./errors.js";
5
5
  export * from "./PlaceholderContract.js";
6
6
  export * from "./SDKConstruct.js";
7
7
  export * from "./TokensMeta.js";
8
+ export * from "./token-types.js";
8
9
  export * from "./types.js";
@@ -7,6 +7,10 @@ const PHANTOM_TOKEN_CONTRACT_TYPES = [
7
7
  "PHANTOM_TOKEN::STAKING_REWARDS",
8
8
  "PHANTOM_TOKEN::UPSHIFT_WITHDRAW"
9
9
  ];
10
+ const KYC_UNDERLYING_DEFAULT = "KYC_UNDERLYING::DEFAULT";
11
+ const KYC_UNDERLYING_ON_DEMAND = "KYC_UNDERLYING::ON_DEMAND";
10
12
  export {
13
+ KYC_UNDERLYING_DEFAULT,
14
+ KYC_UNDERLYING_ON_DEMAND,
11
15
  PHANTOM_TOKEN_CONTRACT_TYPES
12
16
  };
@@ -65,7 +65,8 @@ const chains = {
65
65
  "0x601067eba24bb5b558a184fc082525637e96a42d": "Gami Labs"
66
66
  },
67
67
  testMarketConfigurators: {
68
- "0x99df7330bf42d596af2e9d9836d4fc2077c574aa": "M11 Credit"
68
+ "0x99df7330bf42d596af2e9d9836d4fc2077c574aa": "M11 Credit",
69
+ "0xE0527dE5908B3fc2e054B7eEE0DeF6c9965AbF24": "Securitize"
69
70
  },
70
71
  isPublic: true,
71
72
  wellKnownToken: {
@@ -4,5 +4,4 @@ export * from "./bot-permissions.js";
4
4
  export * from "./math.js";
5
5
  export * from "./networks.js";
6
6
  export * from "./periphery.js";
7
- export * from "./phantom-tokens.js";
8
7
  export * from "./versions.js";
@@ -1,5 +1,4 @@
1
1
  import { marketCompressorAbi } from "../../abi/compressors/marketCompressor.js";
2
- import { SDKConstruct } from "../base/index.js";
3
2
  import {
4
3
  ADDRESS_0X0,
5
4
  AP_MARKET_COMPRESSOR,
@@ -9,7 +8,11 @@ import { AddressMap } from "../utils/index.js";
9
8
  import { simulateWithPriceUpdates } from "../utils/viem/index.js";
10
9
  import { MarketConfiguratorContract } from "./MarketConfiguratorContract.js";
11
10
  import { MarketSuite } from "./MarketSuite.js";
12
- class MarketRegister extends SDKConstruct {
11
+ import { ZapperRegister } from "./ZapperRegister.js";
12
+ class MarketRegister extends ZapperRegister {
13
+ /**
14
+ * Mapping pool.address -> MarketSuite
15
+ */
13
16
  #markets = new AddressMap(void 0, "markets");
14
17
  #marketFilter;
15
18
  #marketConfigurators = new AddressMap(
@@ -41,6 +41,12 @@ class MarketSuite extends SDKConstruct {
41
41
  this.priceOracle = createPriceOracle(sdk, marketData.priceOracle);
42
42
  this.lossPolicy = createLossPolicy(sdk, marketData.lossPolicy);
43
43
  }
44
+ get underlying() {
45
+ return this.pool.underlying;
46
+ }
47
+ async getKYCFactory() {
48
+ return this.pool.getKYCFactory();
49
+ }
44
50
  get dirty() {
45
51
  return this.configurator.dirty || this.pool.dirty || this.priceOracle.dirty || this.creditManagers.some((cm) => cm.dirty);
46
52
  }
@@ -1,4 +1,110 @@
1
- const extraZappers = {
1
+ import { peripheryCompressorAbi } from "../../abi/compressors/peripheryCompressor.js";
2
+ import { SDKConstruct } from "../base/index.js";
3
+ import {
4
+ AP_PERIPHERY_COMPRESSOR,
5
+ VERSION_RANGE_310
6
+ } from "../constants/index.js";
7
+ import { AddressMap, hexEq } from "../utils/index.js";
8
+ class ZapperRegister extends SDKConstruct {
9
+ /**
10
+ * Mapping pool.address -> ZapperData[]
11
+ * Needs to be loaded explicitly using loadZappers method
12
+ */
13
+ #zappers;
14
+ /**
15
+ * Load zappers for all pools using periphery compressor, adds hardcoded zappers
16
+ */
17
+ async loadZappers(force) {
18
+ if (!force && this.#zappers) {
19
+ return;
20
+ }
21
+ const [pcAddr] = this.sdk.addressProvider.mustGetLatest(
22
+ AP_PERIPHERY_COMPRESSOR,
23
+ VERSION_RANGE_310
24
+ );
25
+ this.logger?.debug(`loading zappers with periphery compressor ${pcAddr}`);
26
+ const markets = this.sdk.marketRegister.markets;
27
+ const resp = await this.client.multicall({
28
+ contracts: markets.map(
29
+ (m) => ({
30
+ abi: peripheryCompressorAbi,
31
+ address: pcAddr,
32
+ functionName: "getZappers",
33
+ args: [m.configurator.address, m.pool.pool.address]
34
+ })
35
+ ),
36
+ allowFailure: true,
37
+ batchSize: 0
38
+ });
39
+ this.#zappers = new AddressMap(void 0, "zappers");
40
+ for (let i = 0; i < resp.length; i++) {
41
+ const { status, result, error } = resp[i];
42
+ const marketConfigurator = markets[i].configurator.address;
43
+ const pool = markets[i].pool.pool.address;
44
+ if (status === "success") {
45
+ for (const z of result) {
46
+ this.#addZapper({ ...z, pool, type: "base" });
47
+ }
48
+ } else {
49
+ this.logger?.error(
50
+ `failed to load zapper for market configurator ${this.labelAddress(
51
+ marketConfigurator
52
+ )} and pool ${this.labelAddress(pool)}: ${error}`
53
+ );
54
+ }
55
+ }
56
+ for (const z of KYC_ZAPPERS[this.networkType] ?? []) {
57
+ this.#addZapper({ ...z, type: "kyc" });
58
+ }
59
+ for (const z of MIGRATION_ZAPPERS[this.networkType] ?? []) {
60
+ this.#addZapper({ ...z, type: "migration" });
61
+ }
62
+ }
63
+ #addZapper(z) {
64
+ if (BROKEN_ZAPPERS.has(z.baseParams.addr)) {
65
+ return;
66
+ }
67
+ const existing = this.zappers.get(z.pool);
68
+ if (existing) {
69
+ const hasZapper = existing.some(
70
+ (zz) => hexEq(zz.baseParams.addr, z.baseParams.addr)
71
+ );
72
+ if (!hasZapper) {
73
+ existing.push(z);
74
+ }
75
+ } else {
76
+ this.zappers.upsert(z.pool, [z]);
77
+ }
78
+ const zappersTokens = [z.tokenIn, z.tokenOut];
79
+ for (const t of zappersTokens) {
80
+ this.sdk.tokensMeta.upsert(t.addr, t);
81
+ this.sdk.setAddressLabel(t.addr, t.symbol);
82
+ }
83
+ }
84
+ get zappers() {
85
+ if (!this.#zappers) {
86
+ throw new Error("zappers not loaded, call loadZappers first");
87
+ }
88
+ return this.#zappers;
89
+ }
90
+ poolZappers(pool) {
91
+ return this.zappers.get(pool) ?? [];
92
+ }
93
+ /**
94
+ * Can return multiple zappers if there are multiple zappers for the same tokenIn and tokenOut
95
+ */
96
+ getZapper(pool, tokenIn, tokenOut) {
97
+ const zappers = this.zappers.get(pool)?.filter(
98
+ (z) => hexEq(z.tokenIn.addr, tokenIn) && hexEq(z.tokenOut.addr, tokenOut)
99
+ );
100
+ return zappers;
101
+ }
102
+ }
103
+ const BROKEN_ZAPPERS = new AddressMap(
104
+ [["0x90D66b03EC4D462e42e3c7741049FB46a4a03B69", true]],
105
+ "brokenZappers"
106
+ );
107
+ const MIGRATION_ZAPPERS = {
2
108
  Mainnet: [
3
109
  {
4
110
  baseParams: {
@@ -107,6 +213,7 @@ const extraZappers = {
107
213
  }
108
214
  ]
109
215
  };
216
+ const KYC_ZAPPERS = {};
110
217
  export {
111
- extraZappers
218
+ ZapperRegister
112
219
  };
@@ -5,3 +5,4 @@ export * from "./MarketSuite.js";
5
5
  export * from "./oracle/index.js";
6
6
  export * from "./pool/index.js";
7
7
  export * from "./pricefeeds/index.js";
8
+ export * from "./types.js";
@@ -55,6 +55,9 @@ class PoolSuite extends SDKConstruct {
55
55
  get underlying() {
56
56
  return this.pool.underlying;
57
57
  }
58
+ async getKYCFactory() {
59
+ return this.pool.getKYCFactory();
60
+ }
58
61
  get dirty() {
59
62
  return this.pool.dirty || this.rateKeeper.dirty || this.pqk.dirty || this.interestRateModel.dirty;
60
63
  }
@@ -7,16 +7,20 @@ import {
7
7
  formatBNvalue,
8
8
  percentFmt
9
9
  } from "../../utils/index.js";
10
+ import { SecuritizeKYCFactory } from "./SecuritizeKYCFactory.js";
10
11
  const abi = [...iPoolV310Abi, ...iPausableAbi];
11
12
  class PoolV310Contract extends BaseContract {
12
13
  creditManagerDebtParams;
13
- constructor(options, data) {
14
+ #sdk;
15
+ #kycFactory;
16
+ constructor(sdk, data) {
14
17
  const { baseParams, creditManagerDebtParams, ...rest } = data;
15
- super(options, {
18
+ super(sdk, {
16
19
  ...data.baseParams,
17
20
  name: `PoolV3(${data.name})`,
18
21
  abi
19
22
  });
23
+ this.#sdk = sdk;
20
24
  Object.assign(this, rest);
21
25
  this.creditManagerDebtParams = new AddressMap(
22
26
  creditManagerDebtParams.map((p) => [p.creditManager, p])
@@ -28,6 +32,17 @@ class PoolV310Contract extends BaseContract {
28
32
  symbol: data.symbol
29
33
  });
30
34
  }
35
+ async getKYCFactory() {
36
+ if (this.#kycFactory) {
37
+ return this.#kycFactory;
38
+ }
39
+ await this.#sdk.tokensMeta.loadTokenData(this.underlying);
40
+ const u = this.#sdk.tokensMeta.mustGet(this.underlying);
41
+ if (this.#sdk.tokensMeta.isKYCUnderlying(u)) {
42
+ this.#kycFactory = new SecuritizeKYCFactory(this.#sdk, u.kycFactory);
43
+ }
44
+ return this.#kycFactory;
45
+ }
31
46
  stateHuman(raw = true) {
32
47
  return {
33
48
  ...super.stateHuman(raw),
@@ -0,0 +1,73 @@
1
+ import { iSecuritizeDegenNFTAbi } from "../../../abi/310/iSecuritizeDegenNFT.js";
2
+ import { iSecuritizeKYCFactoryAbi } from "../../../abi/310/iSecuritizeKYCFactory.js";
3
+ import { BaseContract } from "../../base/index.js";
4
+ import { AddressMap } from "../../index.js";
5
+ const abi = iSecuritizeKYCFactoryAbi;
6
+ class SecuritizeKYCFactory extends BaseContract {
7
+ investorCache;
8
+ #degenNFT;
9
+ constructor(options, address) {
10
+ super(options, {
11
+ addr: address,
12
+ name: "SecuritizeKYCFactory",
13
+ abi
14
+ });
15
+ }
16
+ async precomputeWalletAddress(creditManager, investor) {
17
+ return this.contract.read.precomputeWalletAddress([
18
+ creditManager,
19
+ investor
20
+ ]);
21
+ }
22
+ async getWallet(creditAccount) {
23
+ return this.contract.read.getWallet([creditAccount]);
24
+ }
25
+ /**
26
+ * Returns the investor address for a credit account.
27
+ * @param creditAccount - Credit account address
28
+ * @param fromCache - If true, use and update an in-memory cache (creditAccount -> investor). On cache miss, loads from contract and stores the result for future calls.
29
+ */
30
+ async getInvestor(creditAccount, fromCache) {
31
+ if (fromCache && this.investorCache?.has(creditAccount)) {
32
+ return this.investorCache.get(creditAccount);
33
+ }
34
+ const investor = await this.contract.read.getInvestor([creditAccount]);
35
+ if (fromCache) {
36
+ if (!this.investorCache) {
37
+ this.investorCache = new AddressMap();
38
+ }
39
+ this.investorCache.upsert(creditAccount, investor);
40
+ }
41
+ return investor;
42
+ }
43
+ async getDSTokens() {
44
+ const degenNFT = await this.getDegenNFT();
45
+ const tokens = await this.client.readContract({
46
+ address: degenNFT,
47
+ abi: iSecuritizeDegenNFTAbi,
48
+ functionName: "getDSTokens"
49
+ });
50
+ return [...tokens];
51
+ }
52
+ multicall(creditAccount, calls, tokensToRegister) {
53
+ return this.createRawTx({
54
+ functionName: "multicall",
55
+ args: [creditAccount, calls, tokensToRegister]
56
+ });
57
+ }
58
+ openCreditAccount(creditManager, calls, tokensToRegister) {
59
+ return this.createRawTx({
60
+ functionName: "openCreditAccount",
61
+ args: [creditManager, calls, tokensToRegister]
62
+ });
63
+ }
64
+ async getDegenNFT() {
65
+ if (!this.#degenNFT) {
66
+ this.#degenNFT = await this.contract.read.getDegenNFT();
67
+ }
68
+ return this.#degenNFT;
69
+ }
70
+ }
71
+ export {
72
+ SecuritizeKYCFactory
73
+ };
@@ -1,4 +1,6 @@
1
1
  export * from "./GaugeContract.js";
2
2
  export * from "./LinearInterestRateModelContract.js";
3
3
  export * from "./PoolSuite.js";
4
+ export * from "./PoolV310Contract.js";
5
+ export * from "./SecuritizeKYCFactory.js";
4
6
  export * from "./types.js";