@gearbox-protocol/sdk 12.7.2 → 13.0.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 (58) hide show
  1. package/dist/cjs/{sdk/pools/PoolServiceV310.js → abi/iStateSerializer.js} +14 -8
  2. package/dist/cjs/sdk/base/TokensMeta.js +100 -31
  3. package/dist/cjs/sdk/base/index.js +2 -0
  4. package/dist/cjs/sdk/{constants/phantom-tokens.js → base/token-types.js} +9 -3
  5. package/dist/cjs/sdk/chain/chains.js +2 -1
  6. package/dist/cjs/sdk/constants/index.js +0 -2
  7. package/dist/cjs/sdk/market/MarketSuite.js +3 -0
  8. package/dist/cjs/sdk/pools/PoolService.js +310 -0
  9. package/dist/cjs/sdk/pools/index.js +2 -4
  10. package/dist/esm/abi/iStateSerializer.js +12 -0
  11. package/dist/esm/sdk/base/TokensMeta.js +108 -33
  12. package/dist/esm/sdk/base/index.js +1 -0
  13. package/dist/esm/sdk/{constants/phantom-tokens.js → base/token-types.js} +4 -0
  14. package/dist/esm/sdk/chain/chains.js +2 -1
  15. package/dist/esm/sdk/constants/index.js +0 -1
  16. package/dist/esm/sdk/market/MarketSuite.js +3 -0
  17. package/dist/esm/sdk/pools/PoolService.js +296 -0
  18. package/dist/esm/sdk/pools/index.js +1 -2
  19. package/dist/types/abi/iStateSerializer.d.ts +11 -0
  20. package/dist/types/sdk/base/TokensMeta.d.ts +9 -18
  21. package/dist/types/sdk/base/index.d.ts +1 -0
  22. package/dist/types/sdk/base/token-types.d.ts +25 -0
  23. package/dist/types/sdk/base/types.d.ts +0 -1
  24. package/dist/types/sdk/chain/chains.d.ts +1 -1
  25. package/dist/types/sdk/constants/index.d.ts +0 -1
  26. package/dist/types/sdk/market/MarketSuite.d.ts +1 -0
  27. package/dist/types/sdk/pools/PoolService.d.ts +19 -0
  28. package/dist/types/sdk/pools/extraZappers.d.ts +9 -0
  29. package/dist/types/sdk/pools/index.d.ts +1 -2
  30. package/dist/types/sdk/pools/types.d.ts +73 -57
  31. package/dist/types/sdk/sdk-legacy/payload/pool.d.ts +3 -2
  32. package/package.json +3 -3
  33. package/dist/cjs/plugins/zappers/ZappersPlugin.js +0 -143
  34. package/dist/cjs/plugins/zappers/index.js +0 -26
  35. package/dist/cjs/plugins/zappers/package.json +0 -1
  36. package/dist/cjs/plugins/zappers/types.js +0 -16
  37. package/dist/cjs/sdk/pools/AbstractPoolService.js +0 -137
  38. package/dist/cjs/sdk/pools/PoolServiceV300.js +0 -30
  39. package/dist/cjs/sdk/pools/createPoolService.js +0 -39
  40. package/dist/esm/plugins/zappers/ZappersPlugin.js +0 -125
  41. package/dist/esm/plugins/zappers/index.js +0 -3
  42. package/dist/esm/plugins/zappers/package.json +0 -1
  43. package/dist/esm/plugins/zappers/types.js +0 -0
  44. package/dist/esm/sdk/pools/AbstractPoolService.js +0 -113
  45. package/dist/esm/sdk/pools/PoolServiceV300.js +0 -6
  46. package/dist/esm/sdk/pools/PoolServiceV310.js +0 -6
  47. package/dist/esm/sdk/pools/createPoolService.js +0 -15
  48. package/dist/types/plugins/zappers/ZappersPlugin.d.ts +0 -18
  49. package/dist/types/plugins/zappers/extraZappers.d.ts +0 -6
  50. package/dist/types/plugins/zappers/index.d.ts +0 -3
  51. package/dist/types/plugins/zappers/types.d.ts +0 -12
  52. package/dist/types/sdk/constants/phantom-tokens.d.ts +0 -2
  53. package/dist/types/sdk/pools/AbstractPoolService.d.ts +0 -9
  54. package/dist/types/sdk/pools/PoolServiceV300.d.ts +0 -4
  55. package/dist/types/sdk/pools/PoolServiceV310.d.ts +0 -4
  56. package/dist/types/sdk/pools/createPoolService.d.ts +0 -8
  57. /package/dist/cjs/{plugins/zappers → sdk/pools}/extraZappers.js +0 -0
  58. /package/dist/esm/{plugins/zappers → sdk/pools}/extraZappers.js +0 -0
@@ -1,16 +1,24 @@
1
+ import {
2
+ decodeAbiParameters
3
+ } from "viem";
4
+ import { iStateSerializerAbi } from "../../abi/iStateSerializer.js";
1
5
  import { iVersionAbi } from "../../abi/iVersion.js";
2
- import { bytes32ToString } from "../index.js";
3
- import { AddressMap, AddressSet, formatBN } from "../utils/index.js";
6
+ import {
7
+ bytes32ToString,
8
+ KYC_UNDERLYING_DEFAULT,
9
+ KYC_UNDERLYING_ON_DEMAND
10
+ } from "../index.js";
11
+ import { AddressMap, formatBN } from "../utils/index.js";
4
12
  class TokensMeta extends AddressMap {
5
13
  #client;
6
- #phantomTokensLoaded;
14
+ #tokenDataLoaded = false;
7
15
  constructor(client) {
8
16
  super(void 0, "tokensMeta");
9
17
  this.#client = client;
10
18
  }
11
19
  reset() {
12
20
  this.clear();
13
- this.#phantomTokensLoaded = void 0;
21
+ this.#tokenDataLoaded = false;
14
22
  }
15
23
  symbol(token) {
16
24
  return this.mustGet(token).symbol;
@@ -18,28 +26,39 @@ class TokensMeta extends AddressMap {
18
26
  decimals(token) {
19
27
  return this.mustGet(token).decimals;
20
28
  }
21
- /**
22
- * Returns the phantom token type for a given token, or undefined for normal tokens
23
- * Throws if the phantom token data is not loaded
24
- */
25
- phantomTokenType(token) {
26
- if (!this.#phantomTokensLoaded?.has(token)) {
27
- throw new Error("phantom token data not loaded");
29
+ isPhantomToken(t) {
30
+ if (!this.#tokenDataLoaded) {
31
+ throw new Error("extended token data not loaded");
28
32
  }
29
- return this.mustGet(token).phantomTokenType;
33
+ return "contractType" in t && t.contractType.startsWith("PHANTOM_TOKEN::");
34
+ }
35
+ isKYCUnderlying(t) {
36
+ if (!this.#tokenDataLoaded) {
37
+ throw new Error("extended token data not loaded");
38
+ }
39
+ return "contractType" in t && t.contractType.startsWith("KYC_UNDERLYING::");
30
40
  }
31
41
  /**
32
42
  * Returns a map of all phantom tokens
33
43
  * Throws if the phantom token data is not loaded
34
44
  */
35
45
  get phantomTokens() {
36
- if (!this.#phantomTokensLoaded) {
37
- throw new Error("phantom tokens not loaded");
46
+ const result = new AddressMap();
47
+ for (const [token, meta] of this.entries()) {
48
+ if (this.isPhantomToken(meta)) {
49
+ result.upsert(token, meta);
50
+ }
38
51
  }
39
- return new AddressMap(
40
- this.entries().filter(([_, v]) => !!v.phantomTokenType),
41
- "phantomTokens"
42
- );
52
+ return result;
53
+ }
54
+ get kycUnderlyings() {
55
+ const result = new AddressMap();
56
+ for (const [token, meta] of this.entries()) {
57
+ if (this.isKYCUnderlying(meta)) {
58
+ result.upsert(token, meta);
59
+ }
60
+ }
61
+ return result;
43
62
  }
44
63
  formatBN(arg0, arg1, arg2) {
45
64
  const token = typeof arg0 === "object" ? arg0.token : arg0;
@@ -60,30 +79,86 @@ class TokensMeta extends AddressMap {
60
79
  return meta;
61
80
  }
62
81
  /**
63
- * Loads phantom token data for all known tokens from chain
82
+ * Loads token information about phantom token and KYC underlying tokens
64
83
  */
65
- async loadPhantomTokens() {
66
- this.#phantomTokensLoaded = new AddressSet();
84
+ async loadTokenData() {
67
85
  const tokens = this.keys();
68
86
  const resp = await this.#client.multicall({
69
- contracts: tokens.map(
70
- (t) => ({
71
- address: t,
72
- abi: iVersionAbi,
73
- functionName: "contractType"
74
- })
87
+ contracts: tokens.flatMap(
88
+ (t) => [
89
+ {
90
+ address: t,
91
+ abi: iVersionAbi,
92
+ functionName: "contractType"
93
+ },
94
+ {
95
+ address: t,
96
+ abi: iStateSerializerAbi,
97
+ functionName: "serialize"
98
+ }
99
+ ]
75
100
  ),
76
101
  allowFailure: true,
77
102
  batchSize: 0
78
103
  });
79
- for (let i = 0; i < resp.length; i++) {
80
- if (resp[i].status === "success") {
81
- const contractType = bytes32ToString(resp[i].result);
82
- if (contractType.startsWith("PHANTOM_TOKEN::")) {
83
- this.mustGet(tokens[i]).phantomTokenType = contractType;
104
+ for (let i = 0; i < tokens.length; i++) {
105
+ this.#overrideTokenMeta(tokens[i], resp[i], resp[i + 1]);
106
+ }
107
+ this.#tokenDataLoaded = true;
108
+ }
109
+ #overrideTokenMeta(token, contractTypeResp, serializeResp) {
110
+ const meta = this.mustGet(token);
111
+ if (contractTypeResp.status === "success") {
112
+ const contractType = bytes32ToString(contractTypeResp.result);
113
+ if (contractType.startsWith("KYC_UNDERLYING::")) {
114
+ if (serializeResp.status === "success") {
115
+ this.#overrideKYCUnderlying(meta, contractType, serializeResp.result);
116
+ } else {
117
+ throw new Error(
118
+ `token ${meta.symbol} (${token}) is ${contractType} but serialize failed: ${serializeResp.error}`
119
+ );
84
120
  }
121
+ } else if (contractType.startsWith("PHANTOM_TOKEN::")) {
122
+ this.upsert(token, {
123
+ ...meta,
124
+ contractType
125
+ });
85
126
  }
86
- this.#phantomTokensLoaded.add(tokens[i]);
127
+ }
128
+ }
129
+ #overrideKYCUnderlying(meta, contractType, serialized) {
130
+ if (contractType === KYC_UNDERLYING_DEFAULT) {
131
+ const decoded = decodeAbiParameters(
132
+ [
133
+ { type: "address", name: "kycFactory" },
134
+ { type: "address", name: "asset" }
135
+ ],
136
+ serialized
137
+ );
138
+ this.upsert(meta.addr, {
139
+ ...meta,
140
+ contractType,
141
+ kycFactory: decoded[0],
142
+ asset: decoded[1]
143
+ });
144
+ } else if (contractType === KYC_UNDERLYING_ON_DEMAND) {
145
+ const decoded = decodeAbiParameters(
146
+ [
147
+ { type: "address", name: "kycFactory" },
148
+ { type: "address", name: "asset" },
149
+ { type: "address", name: "pool" },
150
+ { type: "address", name: "liquidityProvider" }
151
+ ],
152
+ serialized
153
+ );
154
+ this.upsert(meta.addr, {
155
+ ...meta,
156
+ contractType,
157
+ kycFactory: decoded[0],
158
+ asset: decoded[1],
159
+ pool: decoded[2],
160
+ liquidityProvider: decoded[3]
161
+ });
87
162
  }
88
163
  }
89
164
  }
@@ -4,4 +4,5 @@ export * from "./Construct.js";
4
4
  export * from "./PlaceholderContract.js";
5
5
  export * from "./SDKConstruct.js";
6
6
  export * from "./TokensMeta.js";
7
+ export * from "./token-types.js";
7
8
  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
  };
@@ -62,7 +62,8 @@ const chains = {
62
62
  "0x7a133fbd01736fd076158307c9476cc3877f1af5": "Invariant Group",
63
63
  "0x09d8305F49374AEA6A78aF6C996df2913e8f3b19": "Tulipa",
64
64
  "0x1b265b97eb169fb6668e3258007c3b0242c7bdbe": "kpk",
65
- "0x9dddd1b9ce0ac8aa0c80e4ec141600b9bf0101c3": "Edge UltraYield"
65
+ "0x9dddd1b9ce0ac8aa0c80e4ec141600b9bf0101c3": "Edge UltraYield",
66
+ "0x601067eba24bb5b558a184fc082525637e96a42d": "Gami Labs"
66
67
  },
67
68
  testMarketConfigurators: {
68
69
  "0x99df7330bf42d596af2e9d9836d4fc2077c574aa": "M11 Credit"
@@ -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";
@@ -41,6 +41,9 @@ class MarketSuite extends SDKConstruct {
41
41
  this.priceOracle = getOrCreatePriceOracle(sdk, marketData.priceOracle);
42
42
  this.lossPolicy = createLossPolicy(sdk, marketData.lossPolicy);
43
43
  }
44
+ get underlying() {
45
+ return this.pool.underlying;
46
+ }
44
47
  get dirty() {
45
48
  return this.configurator.dirty || this.pool.dirty || this.priceOracle.dirty || this.creditManagers.some((cm) => cm.dirty);
46
49
  }
@@ -0,0 +1,296 @@
1
+ import { peripheryCompressorAbi } from "../../abi/compressors/peripheryCompressor.js";
2
+ import { ierc20Abi } from "../../abi/iERC20.js";
3
+ import { ierc20ZapperDepositsAbi } from "../../abi/iERC20ZapperDeposits.js";
4
+ import { iethZapperDepositsAbi } from "../../abi/iETHZapperDeposits.js";
5
+ import { iZapperAbi } from "../../abi/iZapper.js";
6
+ import { iPoolV300Abi } from "../../abi/v300.js";
7
+ import {
8
+ KYC_UNDERLYING_DEFAULT,
9
+ KYC_UNDERLYING_ON_DEMAND,
10
+ SDKConstruct
11
+ } from "../base/index.js";
12
+ import {
13
+ AddressMap,
14
+ AddressSet,
15
+ AP_PERIPHERY_COMPRESSOR,
16
+ hexEq,
17
+ VERSION_RANGE_310
18
+ } from "../index.js";
19
+ import { extraZappers } from "./extraZappers.js";
20
+ const NATIVE_ADDRESS = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
21
+ class PoolService extends SDKConstruct {
22
+ #zappers;
23
+ get zappers() {
24
+ if (!this.#zappers) {
25
+ throw new Error("zappers not loaded, call loadZappers first");
26
+ }
27
+ return this.#zappers;
28
+ }
29
+ async loadZappers(force) {
30
+ if (!force && this.#zappers) {
31
+ return;
32
+ }
33
+ const [pcAddr] = this.sdk.addressProvider.mustGetLatest(
34
+ AP_PERIPHERY_COMPRESSOR,
35
+ VERSION_RANGE_310
36
+ );
37
+ this.logger?.debug(`loading zappers with periphery compressor ${pcAddr}`);
38
+ const markets = this.sdk.marketRegister.markets;
39
+ const resp = await this.client.multicall({
40
+ contracts: markets.map(
41
+ (m) => ({
42
+ abi: peripheryCompressorAbi,
43
+ address: pcAddr,
44
+ functionName: "getZappers",
45
+ args: [m.configurator.address, m.pool.pool.address]
46
+ })
47
+ ),
48
+ allowFailure: true,
49
+ batchSize: 0
50
+ });
51
+ this.#zappers = new AddressMap(void 0, "zappers");
52
+ for (let i = 0; i < resp.length; i++) {
53
+ const { status, result, error } = resp[i];
54
+ const marketConfigurator = markets[i].configurator.address;
55
+ const pool = markets[i].pool.pool.address;
56
+ if (status === "success") {
57
+ for (const z of result) {
58
+ this.#addZapper({ ...z, pool });
59
+ }
60
+ } else {
61
+ this.sdk.logger?.error(
62
+ `failed to load zapper for market configurator ${this.labelAddress(
63
+ marketConfigurator
64
+ )} and pool ${this.labelAddress(pool)}: ${error}`
65
+ );
66
+ }
67
+ }
68
+ for (const z of extraZappers[this.networkType] ?? []) {
69
+ this.#addZapper(z);
70
+ }
71
+ }
72
+ getDepositTokensIn(pool) {
73
+ const underlying = this.#describeUnderlying(pool);
74
+ if (this.sdk.tokensMeta.isKYCUnderlying(underlying)) {
75
+ switch (underlying.contractType) {
76
+ case KYC_UNDERLYING_DEFAULT:
77
+ return this.depositTokensIn(pool, false);
78
+ case KYC_UNDERLYING_ON_DEMAND:
79
+ return [underlying.asset];
80
+ }
81
+ }
82
+ return this.depositTokensIn(pool, true);
83
+ }
84
+ getDepositTokensOut(pool, tokenIn) {
85
+ const underlying = this.#describeUnderlying(pool);
86
+ if (this.sdk.tokensMeta.isKYCUnderlying(underlying)) {
87
+ switch (underlying.contractType) {
88
+ case KYC_UNDERLYING_DEFAULT:
89
+ return this.depositTokensOut(pool, tokenIn, false);
90
+ case KYC_UNDERLYING_ON_DEMAND:
91
+ return [];
92
+ }
93
+ }
94
+ return this.depositTokensOut(pool, tokenIn, true);
95
+ }
96
+ getDepositMetadata(pool, tokenIn, tokenOut) {
97
+ const underlying = this.#describeUnderlying(pool);
98
+ if (this.sdk.tokensMeta.isKYCUnderlying(underlying)) {
99
+ switch (underlying.contractType) {
100
+ case KYC_UNDERLYING_DEFAULT: {
101
+ return this.depositMetadata(pool, tokenIn, tokenOut, false);
102
+ }
103
+ case KYC_UNDERLYING_ON_DEMAND:
104
+ return {
105
+ zapper: void 0,
106
+ approveTarget: underlying.liquidityProvider,
107
+ permissible: false
108
+ };
109
+ }
110
+ }
111
+ return this.depositMetadata(pool, tokenIn, tokenOut, true);
112
+ }
113
+ addLiquidity(props) {
114
+ const { collateral, meta, permit, referralCode, pool, wallet } = props;
115
+ const underlying = this.#describeUnderlying(pool);
116
+ if (this.sdk.tokensMeta.isKYCUnderlying(underlying)) {
117
+ if (underlying.contractType === KYC_UNDERLYING_ON_DEMAND) {
118
+ return void 0;
119
+ }
120
+ }
121
+ const { zapper } = meta;
122
+ if (zapper?.tokenIn.addr === NATIVE_ADDRESS) {
123
+ return {
124
+ target: zapper.baseParams.addr,
125
+ abi: iethZapperDepositsAbi,
126
+ functionName: "depositWithReferral",
127
+ args: [wallet, referralCode],
128
+ value: collateral.balance
129
+ };
130
+ } else if (zapper) {
131
+ return permit ? {
132
+ target: zapper.baseParams.addr,
133
+ abi: ierc20ZapperDepositsAbi,
134
+ functionName: "depositWithReferralAndPermit",
135
+ args: [
136
+ collateral.balance,
137
+ wallet,
138
+ referralCode,
139
+ permit.deadline,
140
+ permit.v,
141
+ permit.r,
142
+ permit.s
143
+ ]
144
+ } : {
145
+ target: zapper.baseParams.addr,
146
+ abi: ierc20ZapperDepositsAbi,
147
+ functionName: "depositWithReferral",
148
+ args: [collateral.balance, wallet, referralCode]
149
+ };
150
+ } else {
151
+ return {
152
+ target: pool,
153
+ abi: iPoolV300Abi,
154
+ functionName: "depositWithReferral",
155
+ args: [collateral.balance, wallet, referralCode]
156
+ };
157
+ }
158
+ }
159
+ removeLiquidity(props) {
160
+ const { pool, amount, account, zapper, permit } = props;
161
+ const underlying = this.#describeUnderlying(pool);
162
+ if (this.sdk.tokensMeta.isKYCUnderlying(underlying)) {
163
+ if (underlying.contractType === KYC_UNDERLYING_ON_DEMAND) {
164
+ return {
165
+ abi: ierc20Abi,
166
+ functionName: "approve",
167
+ args: [underlying.liquidityProvider, 0n],
168
+ target: underlying.asset
169
+ };
170
+ }
171
+ }
172
+ if (zapper) {
173
+ return permit ? {
174
+ target: zapper.zapper,
175
+ abi: iZapperAbi,
176
+ functionName: "redeemWithPermit",
177
+ args: [
178
+ amount,
179
+ account,
180
+ permit.deadline,
181
+ permit.v,
182
+ permit.r,
183
+ permit.s
184
+ ]
185
+ } : {
186
+ target: zapper.zapper,
187
+ abi: iZapperAbi,
188
+ functionName: "redeem",
189
+ args: [amount, account]
190
+ };
191
+ }
192
+ return {
193
+ target: pool,
194
+ abi: iPoolV300Abi,
195
+ functionName: "redeem",
196
+ args: [amount, account, account]
197
+ };
198
+ }
199
+ depositTokensIn(poolAddr, allowDirectDeposit) {
200
+ const { pool } = this.sdk.marketRegister.findByPool(poolAddr);
201
+ const result = new AddressSet();
202
+ if (allowDirectDeposit) {
203
+ result.add(pool.underlying);
204
+ }
205
+ const zappers = this.zappers.get(poolAddr) ?? [];
206
+ for (const z of zappers) {
207
+ if (hexEq(z.tokenOut.addr, poolAddr)) {
208
+ result.add(z.tokenIn.addr);
209
+ }
210
+ }
211
+ if (result.size === 0) {
212
+ throw new Error(
213
+ `No tokensIn found for pool ${this.labelAddress(poolAddr)}`
214
+ );
215
+ }
216
+ return result.asArray();
217
+ }
218
+ depositTokensOut(poolAddr, tokenIn, allowDirectDeposit) {
219
+ const result = new AddressSet();
220
+ const { pool } = this.sdk.marketRegister.findByPool(poolAddr);
221
+ const zappers = this.zappers.get(poolAddr) ?? [];
222
+ for (const z of zappers) {
223
+ if (hexEq(z.tokenIn.addr, tokenIn)) {
224
+ result.add(z.tokenOut.addr);
225
+ }
226
+ }
227
+ if (allowDirectDeposit && hexEq(tokenIn, pool.underlying)) {
228
+ result.add(poolAddr);
229
+ }
230
+ if (result.size === 0) {
231
+ throw new Error(
232
+ `No tokensOut found for tokenIn ${this.labelAddress(tokenIn)} on pool ${this.labelAddress(poolAddr)}`
233
+ );
234
+ }
235
+ return result.asArray();
236
+ }
237
+ depositMetadata(poolAddr, tokenIn, tokenOut, allowDirectDeposit) {
238
+ if (!tokenOut) {
239
+ throw new Error("tokenOut is required for classic pool deposit");
240
+ }
241
+ const { pool } = this.sdk.marketRegister.findByPool(poolAddr);
242
+ const zapper = this.getZapper(poolAddr, tokenIn, tokenOut);
243
+ if (!zapper && !allowDirectDeposit) {
244
+ throw new Error(
245
+ `No zapper found for tokenIn ${this.labelAddress(tokenIn)} and tokenOut ${this.labelAddress(tokenOut)} on pool ${this.labelAddress(poolAddr)}`
246
+ );
247
+ }
248
+ return {
249
+ zapper,
250
+ // zapper or pool itself
251
+ approveTarget: zapper?.baseParams.addr ?? pool.pool.address,
252
+ // TODO: instead of permissible, return permitType зависимости от tokenIn
253
+ // "none" | "eip2612" | "dai_like";
254
+ permissible: !!zapper && tokenIn !== NATIVE_ADDRESS
255
+ };
256
+ }
257
+ getZapper(pool, tokenIn, tokenOut) {
258
+ return this.zappers.get(pool)?.find(
259
+ (z) => hexEq(z.tokenIn.addr, tokenIn) && hexEq(z.tokenOut.addr, tokenOut)
260
+ );
261
+ }
262
+ mustGetZapper(poolAddr, tokenIn, tokenOut) {
263
+ const result = this.getZapper(poolAddr, tokenIn, tokenOut);
264
+ if (!result) {
265
+ throw new Error(
266
+ `No zapper found for tokenIn ${this.labelAddress(tokenIn)} and tokenOut ${this.labelAddress(tokenOut)} on pool ${this.labelAddress(poolAddr)}`
267
+ );
268
+ }
269
+ return result;
270
+ }
271
+ #addZapper(z) {
272
+ const existing = this.zappers.get(z.pool);
273
+ if (existing) {
274
+ const hasZapper = existing.some(
275
+ (zz) => hexEq(zz.baseParams.addr, z.baseParams.addr)
276
+ );
277
+ if (!hasZapper) {
278
+ existing.push(z);
279
+ }
280
+ } else {
281
+ this.zappers.upsert(z.pool, [z]);
282
+ }
283
+ const zappersTokens = [z.tokenIn, z.tokenOut];
284
+ for (const t of zappersTokens) {
285
+ this.sdk.tokensMeta.upsert(t.addr, t);
286
+ this.sdk.setAddressLabel(t.addr, t.symbol);
287
+ }
288
+ }
289
+ #describeUnderlying(pool) {
290
+ const market = this.sdk.marketRegister.findByPool(pool);
291
+ return this.sdk.tokensMeta.mustGet(market.underlying);
292
+ }
293
+ }
294
+ export {
295
+ PoolService
296
+ };
@@ -1,3 +1,2 @@
1
- export * from "./AbstractPoolService.js";
2
- export * from "./createPoolService.js";
1
+ export * from "./PoolService.js";
3
2
  export * from "./types.js";
@@ -0,0 +1,11 @@
1
+ export declare const iStateSerializerAbi: readonly [{
2
+ readonly type: "function";
3
+ readonly inputs: readonly [];
4
+ readonly name: "serialize";
5
+ readonly outputs: readonly [{
6
+ readonly name: "serializedData";
7
+ readonly internalType: "bytes";
8
+ readonly type: "bytes";
9
+ }];
10
+ readonly stateMutability: "view";
11
+ }];
@@ -1,40 +1,31 @@
1
- import type { Address, Chain, PublicClient, Transport } from "viem";
2
- import { type PhantomTokenContractType } from "../index.js";
1
+ import { type Address, type Chain, type PublicClient, type Transport } from "viem";
3
2
  import type { Asset } from "../router/index.js";
4
3
  import { AddressMap } from "../utils/index.js";
5
- import type { TokenMetaData } from "./types.js";
4
+ import type { KYCTokenMeta, PhantomTokenMeta, TokenMetaData } from "./token-types.js";
6
5
  export interface FormatBNOptions {
7
6
  precision?: number;
8
7
  symbol?: boolean;
9
8
  }
10
- export interface TokenMetaDataExtended extends TokenMetaData {
11
- /**
12
- * Undefined if token is not a phantom token
13
- */
14
- phantomTokenType?: PhantomTokenContractType;
15
- }
16
- export declare class TokensMeta extends AddressMap<TokenMetaDataExtended> {
9
+ export declare class TokensMeta extends AddressMap<TokenMetaData> {
17
10
  #private;
18
11
  constructor(client: PublicClient<Transport, Chain>);
19
12
  reset(): void;
20
13
  symbol(token: Address): string;
21
14
  decimals(token: Address): number;
22
- /**
23
- * Returns the phantom token type for a given token, or undefined for normal tokens
24
- * Throws if the phantom token data is not loaded
25
- */
26
- phantomTokenType(token: Address): PhantomTokenContractType | undefined;
15
+ isPhantomToken(t: TokenMetaData): t is PhantomTokenMeta;
16
+ isKYCUnderlying(t: TokenMetaData): t is KYCTokenMeta;
27
17
  /**
28
18
  * Returns a map of all phantom tokens
29
19
  * Throws if the phantom token data is not loaded
30
20
  */
31
- get phantomTokens(): AddressMap<TokenMetaDataExtended>;
21
+ get phantomTokens(): AddressMap<PhantomTokenMeta>;
22
+ get kycUnderlyings(): AddressMap<KYCTokenMeta>;
32
23
  formatBN(asset: Asset, options?: FormatBNOptions): string;
33
24
  formatBN(token: Address, amount: number | bigint | string | undefined, options?: FormatBNOptions): string;
34
25
  findBySymbol(symbol: string): TokenMetaData | undefined;
35
26
  mustFindBySymbol(symbol: string): TokenMetaData;
36
27
  /**
37
- * Loads phantom token data for all known tokens from chain
28
+ * Loads token information about phantom token and KYC underlying tokens
38
29
  */
39
- loadPhantomTokens(): Promise<void>;
30
+ loadTokenData(): Promise<void>;
40
31
  }
@@ -4,4 +4,5 @@ export * from "./Construct.js";
4
4
  export * from "./PlaceholderContract.js";
5
5
  export * from "./SDKConstruct.js";
6
6
  export * from "./TokensMeta.js";
7
+ export * from "./token-types.js";
7
8
  export * from "./types.js";
@@ -0,0 +1,25 @@
1
+ import type { Address } from "viem";
2
+ import type { MarketData, Unarray } from "./types.js";
3
+ export type SimpleTokenMeta = Unarray<MarketData["tokens"]>;
4
+ export declare const PHANTOM_TOKEN_CONTRACT_TYPES: readonly ["PHANTOM_TOKEN::CONVEX", "PHANTOM_TOKEN::INFINIFI_UNWIND", "PHANTOM_TOKEN::INFRARED", "PHANTOM_TOKEN::MELLOW_WITHDRAWAL", "PHANTOM_TOKEN::MIDAS_REDEMPTION", "PHANTOM_TOKEN::STAKING_REWARDS", "PHANTOM_TOKEN::UPSHIFT_WITHDRAW"];
5
+ export declare const KYC_UNDERLYING_DEFAULT = "KYC_UNDERLYING::DEFAULT";
6
+ export declare const KYC_UNDERLYING_ON_DEMAND = "KYC_UNDERLYING::ON_DEMAND";
7
+ export type KYCUnderlyingContractType = typeof KYC_UNDERLYING_DEFAULT | typeof KYC_UNDERLYING_ON_DEMAND;
8
+ export type PhantomTokenContractType = (typeof PHANTOM_TOKEN_CONTRACT_TYPES)[number];
9
+ export type PhantomTokenMeta = SimpleTokenMeta & {
10
+ contractType: PhantomTokenContractType;
11
+ };
12
+ export type KYCDefaultTokenMeta = SimpleTokenMeta & {
13
+ contractType: typeof KYC_UNDERLYING_DEFAULT;
14
+ kycFactory: Address;
15
+ asset: Address;
16
+ };
17
+ export type KYCOnDemandTokenMeta = SimpleTokenMeta & {
18
+ contractType: typeof KYC_UNDERLYING_ON_DEMAND;
19
+ kycFactory: Address;
20
+ asset: Address;
21
+ pool: Address;
22
+ liquidityProvider: Address;
23
+ };
24
+ export type KYCTokenMeta = KYCDefaultTokenMeta | KYCOnDemandTokenMeta;
25
+ export type TokenMetaData = SimpleTokenMeta | PhantomTokenMeta | KYCTokenMeta;
@@ -26,7 +26,6 @@ export type CreditManagerState = CreditSuiteState["creditManager"];
26
26
  export type CreditFacadeState = CreditSuiteState["creditFacade"];
27
27
  export type CreditConfiguratorState = CreditSuiteState["creditConfigurator"];
28
28
  export type AdapterData = Unarray<CreditSuiteState["adapters"]>;
29
- export type TokenMetaData = Unarray<MarketData["tokens"]>;
30
29
  export type PoolState = MarketData["pool"];
31
30
  export type QuotaKeeperState = MarketData["quotaKeeper"];
32
31
  export type QuotaState = Unarray<QuotaKeeperState["quotas"]>;
@@ -1,6 +1,6 @@
1
1
  import type { Address, Chain } from "viem";
2
2
  import { z } from "zod/v4";
3
- export type Curator = "Chaos Labs" | "K3" | "cp0x" | "Re7" | "Invariant Group" | "Tulipa" | "M11 Credit" | "kpk" | "Hyperithm" | "Edge UltraYield" | "TelosC";
3
+ export type Curator = "Chaos Labs" | "K3" | "cp0x" | "Re7" | "Invariant Group" | "Tulipa" | "M11 Credit" | "kpk" | "Hyperithm" | "Edge UltraYield" | "TelosC" | "Gami Labs";
4
4
  export interface GearboxChain extends Chain {
5
5
  network: NetworkType;
6
6
  defaultMarketConfigurators: Record<Address, Curator>;
@@ -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";
@@ -21,6 +21,7 @@ export declare class MarketSuite extends SDKConstruct {
21
21
  */
22
22
  readonly state: MarketData;
23
23
  constructor(sdk: GearboxSDK, marketData: MarketData);
24
+ get underlying(): Address;
24
25
  get dirty(): boolean;
25
26
  get watchAddresses(): Set<Address>;
26
27
  stateHuman(raw?: boolean): MarketStateHuman;